LibreOffice Module vcl (master)  1
outdev/font.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <i18nlangtag/mslangid.hxx>
21 #include <i18nlangtag/lang.h>
22 
23 #include <unotools/configmgr.hxx>
24 #include <vcl/metric.hxx>
25 #include <vcl/virdev.hxx>
26 #include <vcl/print.hxx>
27 #include <vcl/sysdata.hxx>
28 #include <vcl/fontcharmap.hxx>
29 #include <vcl/event.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include <sal/log.hxx>
33 #include <tools/debug.hxx>
34 
35 #include <sallayout.hxx>
36 #include <salgdi.hxx>
37 #include <svdata.hxx>
38 #include <impglyphitem.hxx>
39 
40 #include <outdev.h>
41 #include <window.h>
42 
44 
45 #include <strings.hrc>
46 
47 FontMetric OutputDevice::GetDevFont( int nDevFontIndex ) const
48 {
49  FontMetric aFontMetric;
50 
52 
53  int nCount = GetDevFontCount();
54  if( nDevFontIndex < nCount )
55  {
56  const PhysicalFontFace& rData = *mpDeviceFontList->Get( nDevFontIndex );
57  aFontMetric.SetFamilyName( rData.GetFamilyName() );
58  aFontMetric.SetStyleName( rData.GetStyleName() );
59  aFontMetric.SetCharSet( rData.GetCharSet() );
60  aFontMetric.SetFamily( rData.GetFamilyType() );
61  aFontMetric.SetPitch( rData.GetPitch() );
62  aFontMetric.SetWeight( rData.GetWeight() );
63  aFontMetric.SetItalic( rData.GetItalic() );
64  aFontMetric.SetAlignment( TextAlign::ALIGN_TOP );
65  aFontMetric.SetWidthType( rData.GetWidthType() );
66  aFontMetric.SetQuality( rData.GetQuality() );
67  }
68 
69  return aFontMetric;
70 }
71 
73 {
74  if( !mpDeviceFontList )
75  {
76  if (!mxFontCollection)
77  {
78  return 0;
79  }
80 
81  mpDeviceFontList = mxFontCollection->GetDeviceFontList();
82 
83  if (!mpDeviceFontList->Count())
84  {
85  mpDeviceFontList.reset();
86  return 0;
87  }
88  }
89  return mpDeviceFontList->Count();
90 }
91 
92 bool OutputDevice::IsFontAvailable( const OUString& rFontName ) const
93 {
95  PhysicalFontFamily* pFound = mxFontCollection->FindFontFamily( rFontName );
96  return (pFound != nullptr);
97 }
98 
100 {
101  mpDeviceFontSizeList.reset();
102 
104  mpDeviceFontSizeList = mxFontCollection->GetDeviceFontSizeList( rFont.GetFamilyName() );
105  return mpDeviceFontSizeList->Count();
106 }
107 
108 Size OutputDevice::GetDevFontSize( const vcl::Font& rFont, int nSizeIndex ) const
109 {
110  // check range
111  int nCount = GetDevFontSizeCount( rFont );
112  if ( nSizeIndex >= nCount )
113  return Size();
114 
115  // when mapping is enabled round to .5 points
116  Size aSize( 0, mpDeviceFontSizeList->Get( nSizeIndex ) );
117  if ( mbMap )
118  {
119  aSize.setHeight( aSize.Height() * 10 );
120  MapMode aMap( MapUnit::Map10thInch, Point(), Fraction( 1, 72 ), Fraction( 1, 72 ) );
121  aSize = PixelToLogic( aSize, aMap );
122  aSize.AdjustHeight(5 );
123  aSize.setHeight( aSize.Height() / 10 );
124  tools::Long nRound = aSize.Height() % 5;
125  if ( nRound >= 3 )
126  aSize.AdjustHeight(5-nRound);
127  else
128  aSize.AdjustHeight( -nRound );
129  aSize.setHeight( aSize.Height() * 10 );
130  aSize = LogicToPixel( aSize, aMap );
131  aSize = PixelToLogic( aSize );
132  aSize.AdjustHeight(5 );
133  aSize.setHeight( aSize.Height() / 10 );
134  }
135  return aSize;
136 }
137 
138 bool OutputDevice::AddTempDevFont( const OUString& rFileURL, const OUString& rFontName )
139 {
141 
142  if( !mpGraphics && !AcquireGraphics() )
143  return false;
144 
145  bool bRC = mpGraphics->AddTempDevFont( mxFontCollection.get(), rFileURL, rFontName );
146  if( !bRC )
147  return false;
148 
149  if( mpAlphaVDev )
150  mpAlphaVDev->AddTempDevFont( rFileURL, rFontName );
151 
152  return true;
153 }
154 
155 bool OutputDevice::GetFontFeatures(std::vector<vcl::font::Feature>& rFontFeatures) const
156 {
157  if (!ImplNewFont())
158  return false;
159 
160  LogicalFontInstance* pFontInstance = mpFontInstance.get();
161  if (!pFontInstance)
162  return false;
163 
164  hb_font_t* pHbFont = pFontInstance->GetHbFont();
165  if (!pHbFont)
166  return false;
167 
168  hb_face_t* pHbFace = hb_font_get_face(pHbFont);
169  if (!pHbFace)
170  return false;
171 
173 
174  vcl::font::FeatureCollector aFeatureCollector(pHbFace, rFontFeatures, eOfficeLanguage);
175  aFeatureCollector.collect();
176 
177  return true;
178 }
179 
181 {
182  FontMetric aMetric;
183  if (!ImplNewFont())
184  return aMetric;
185 
186  LogicalFontInstance* pFontInstance = mpFontInstance.get();
187  ImplFontMetricDataRef xFontMetric = pFontInstance->mxFontMetric;
188 
189  // prepare metric
190  aMetric = maFont;
191 
192  // set aMetric with info from font
193  aMetric.SetFamilyName( maFont.GetFamilyName() );
194  aMetric.SetStyleName( xFontMetric->GetStyleName() );
195  aMetric.SetFontSize( PixelToLogic( Size( xFontMetric->GetWidth(), xFontMetric->GetAscent() + xFontMetric->GetDescent() - xFontMetric->GetInternalLeading() ) ) );
196  aMetric.SetCharSet( xFontMetric->IsSymbolFont() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
197  aMetric.SetFamily( xFontMetric->GetFamilyType() );
198  aMetric.SetPitch( xFontMetric->GetPitch() );
199  aMetric.SetWeight( xFontMetric->GetWeight() );
200  aMetric.SetItalic( xFontMetric->GetItalic() );
201  aMetric.SetAlignment( TextAlign::ALIGN_TOP );
202  aMetric.SetWidthType( xFontMetric->GetWidthType() );
203  if ( pFontInstance->mnOwnOrientation )
204  aMetric.SetOrientation( pFontInstance->mnOwnOrientation );
205  else
206  aMetric.SetOrientation( xFontMetric->GetOrientation() );
207 
208  // set remaining metric fields
209  aMetric.SetFullstopCenteredFlag( xFontMetric->IsFullstopCentered() );
210  aMetric.SetBulletOffset( xFontMetric->GetBulletOffset() );
211  aMetric.SetAscent( ImplDevicePixelToLogicHeight( xFontMetric->GetAscent() + mnEmphasisAscent ) );
214  // OutputDevice has its own external leading function due to #i60945#
216  aMetric.SetLineHeight( ImplDevicePixelToLogicHeight( xFontMetric->GetAscent() + xFontMetric->GetDescent() + mnEmphasisAscent + mnEmphasisDescent ) );
217  aMetric.SetSlant( ImplDevicePixelToLogicHeight( xFontMetric->GetSlant() ) );
218 
219  // get miscellaneous data
220  aMetric.SetQuality( xFontMetric->GetQuality() );
221 
222  SAL_INFO("vcl.gdi.fontmetric", "OutputDevice::GetFontMetric:" << aMetric);
223 
224  xFontMetric = nullptr;
225 
226  return aMetric;
227 }
228 
230 {
231  // select font, query metrics, select original font again
232  vcl::Font aOldFont = GetFont();
233  const_cast<OutputDevice*>(this)->SetFont( rFont );
234  FontMetric aMetric( GetFontMetric() );
235  const_cast<OutputDevice*>(this)->SetFont( aOldFont );
236  return aMetric;
237 }
238 
239 bool OutputDevice::GetFontCharMap( FontCharMapRef& rxFontCharMap ) const
240 {
241  if (!InitFont())
242  return false;
243 
244  FontCharMapRef xFontCharMap ( mpGraphics->GetFontCharMap() );
245  if (!xFontCharMap.is())
246  {
247  FontCharMapRef xDefaultMap( new FontCharMap() );
248  rxFontCharMap = xDefaultMap;
249  }
250  else
251  rxFontCharMap = xFontCharMap;
252 
253  return !rxFontCharMap->IsDefaultMap();
254 }
255 
257 {
258  if (!InitFont())
259  return false;
260  return mpGraphics->GetFontCapabilities(rFontCapabilities);
261 }
262 
263 void OutputDevice::ImplGetEmphasisMark( tools::PolyPolygon& rPolyPoly, bool& rPolyLine,
264  tools::Rectangle& rRect1, tools::Rectangle& rRect2,
265  tools::Long& rYOff, tools::Long& rWidth,
266  FontEmphasisMark eEmphasis,
267  tools::Long nHeight )
268 {
269  static const PolyFlags aAccentPolyFlags[24] =
270  {
271  PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control,
272  PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control,
273  PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control,
274  PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control,
275  PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control,
276  PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control,
277  PolyFlags::Normal, PolyFlags::Normal, PolyFlags::Control,
278  PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control
279  };
280 
281  static const Point aAccentPos[24] =
282  {
283  { 78, 0 },
284  { 348, 79 },
285  { 599, 235 },
286  { 843, 469 },
287  { 938, 574 },
288  { 990, 669 },
289  { 990, 773 },
290  { 990, 843 },
291  { 964, 895 },
292  { 921, 947 },
293  { 886, 982 },
294  { 860, 999 },
295  { 825, 999 },
296  { 764, 999 },
297  { 721, 964 },
298  { 686, 895 },
299  { 625, 791 },
300  { 556, 660 },
301  { 469, 504 },
302  { 400, 400 },
303  { 261, 252 },
304  { 61, 61 },
305  { 0, 27 },
306  { 9, 0 }
307  };
308 
309  rWidth = 0;
310  rYOff = 0;
311  rPolyLine = false;
312 
313  if ( !nHeight )
314  return;
315 
316  FontEmphasisMark nEmphasisStyle = eEmphasis & FontEmphasisMark::Style;
317  tools::Long nDotSize = 0;
318  switch ( nEmphasisStyle )
319  {
320  case FontEmphasisMark::Dot:
321  // Dot has 55% of the height
322  nDotSize = (nHeight*550)/1000;
323  if ( !nDotSize )
324  nDotSize = 1;
325  if ( nDotSize <= 2 )
326  rRect1 = tools::Rectangle( Point(), Size( nDotSize, nDotSize ) );
327  else
328  {
329  tools::Long nRad = nDotSize/2;
330  tools::Polygon aPoly( Point( nRad, nRad ), nRad, nRad );
331  rPolyPoly.Insert( aPoly );
332  }
333  rYOff = ((nHeight*250)/1000)/2; // Center to the another EmphasisMarks
334  rWidth = nDotSize;
335  break;
336 
337  case FontEmphasisMark::Circle:
338  // Dot has 80% of the height
339  nDotSize = (nHeight*800)/1000;
340  if ( !nDotSize )
341  nDotSize = 1;
342  if ( nDotSize <= 2 )
343  rRect1 = tools::Rectangle( Point(), Size( nDotSize, nDotSize ) );
344  else
345  {
346  tools::Long nRad = nDotSize/2;
347  tools::Polygon aPoly( Point( nRad, nRad ), nRad, nRad );
348  rPolyPoly.Insert( aPoly );
349  // BorderWidth is 15%
350  tools::Long nBorder = (nDotSize*150)/1000;
351  if ( nBorder <= 1 )
352  rPolyLine = true;
353  else
354  {
355  tools::Polygon aPoly2( Point( nRad, nRad ),
356  nRad-nBorder, nRad-nBorder );
357  rPolyPoly.Insert( aPoly2 );
358  }
359  }
360  rWidth = nDotSize;
361  break;
362 
363  case FontEmphasisMark::Disc:
364  // Dot has 80% of the height
365  nDotSize = (nHeight*800)/1000;
366  if ( !nDotSize )
367  nDotSize = 1;
368  if ( nDotSize <= 2 )
369  rRect1 = tools::Rectangle( Point(), Size( nDotSize, nDotSize ) );
370  else
371  {
372  tools::Long nRad = nDotSize/2;
373  tools::Polygon aPoly( Point( nRad, nRad ), nRad, nRad );
374  rPolyPoly.Insert( aPoly );
375  }
376  rWidth = nDotSize;
377  break;
378 
379  case FontEmphasisMark::Accent:
380  // Dot has 80% of the height
381  nDotSize = (nHeight*800)/1000;
382  if ( !nDotSize )
383  nDotSize = 1;
384  if ( nDotSize <= 2 )
385  {
386  if ( nDotSize == 1 )
387  {
388  rRect1 = tools::Rectangle( Point(), Size( nDotSize, nDotSize ) );
389  rWidth = nDotSize;
390  }
391  else
392  {
393  rRect1 = tools::Rectangle( Point(), Size( 1, 1 ) );
394  rRect2 = tools::Rectangle( Point( 1, 1 ), Size( 1, 1 ) );
395  }
396  }
397  else
398  {
399  tools::Polygon aPoly( SAL_N_ELEMENTS(aAccentPos), aAccentPos,
400  aAccentPolyFlags );
401  double dScale = static_cast<double>(nDotSize)/1000.0;
402  aPoly.Scale( dScale, dScale );
403  tools::Polygon aTemp;
404  aPoly.AdaptiveSubdivide( aTemp );
405  tools::Rectangle aBoundRect = aTemp.GetBoundRect();
406  rWidth = aBoundRect.GetWidth();
407  nDotSize = aBoundRect.GetHeight();
408  rPolyPoly.Insert( aTemp );
409  }
410  break;
411  default: break;
412  }
413 
414  // calculate position
415  tools::Long nOffY = 1+(mnDPIY/300); // one visible pixel space
416  tools::Long nSpaceY = nHeight-nDotSize;
417  if ( nSpaceY >= nOffY*2 )
418  rYOff += nOffY;
419  if ( !(eEmphasis & FontEmphasisMark::PosBelow) )
420  rYOff += nDotSize;
421 }
422 
424 {
425  FontEmphasisMark nEmphasisMark = rFont.GetEmphasisMark();
426 
427  // If no Position is set, then calculate the default position, which
428  // depends on the language
429  if ( !(nEmphasisMark & (FontEmphasisMark::PosAbove | FontEmphasisMark::PosBelow)) )
430  {
431  LanguageType eLang = rFont.GetLanguage();
432  // In Chinese Simplified the EmphasisMarks are below/left
434  nEmphasisMark |= FontEmphasisMark::PosBelow;
435  else
436  {
437  eLang = rFont.GetCJKContextLanguage();
438  // In Chinese Simplified the EmphasisMarks are below/left
440  nEmphasisMark |= FontEmphasisMark::PosBelow;
441  else
442  nEmphasisMark |= FontEmphasisMark::PosAbove;
443  }
444  }
445 
446  return nEmphasisMark;
447 }
448 
450 {
451  return mpFontInstance->mxFontMetric->GetExternalLeading();
452 }
453 
454 void OutputDevice::ImplClearFontData( const bool bNewFontLists )
455 {
456  // the currently selected logical font is no longer needed
457  mpFontInstance.clear();
458 
459  mbInitFont = true;
460  mbNewFont = true;
461 
462  if ( bNewFontLists )
463  {
464  mpDeviceFontList.reset();
465  mpDeviceFontSizeList.reset();
466 
467  // release all physically selected fonts on this device
468  if( AcquireGraphics() )
470  }
471 
472  ImplSVData* pSVData = ImplGetSVData();
473 
475  mxFontCache->Invalidate();
476 
477  if (bNewFontLists && AcquireGraphics())
478  {
480  mxFontCollection->Clear();
481  }
482 }
483 
484 void OutputDevice::RefreshFontData( const bool bNewFontLists )
485 {
486  ImplRefreshFontData( bNewFontLists );
487 }
488 
489 void OutputDevice::ImplRefreshFontData( const bool bNewFontLists )
490 {
491  if (bNewFontLists && AcquireGraphics())
493 }
494 
496 {
497  ImplClearFontData( true/*bNewFontLists*/ );
498  ImplRefreshFontData( true/*bNewFontLists*/ );
499 }
500 
501 void OutputDevice::ImplClearAllFontData(bool bNewFontLists)
502 {
503  ImplSVData* pSVData = ImplGetSVData();
504 
506 
507  // clear global font lists to have them updated
508  pSVData->maGDIData.mxScreenFontCache->Invalidate();
509  if ( !bNewFontLists )
510  return;
511 
512  pSVData->maGDIData.mxScreenFontList->Clear();
513  vcl::Window * pFrame = pSVData->maFrameData.mpFirstFrame;
514  if ( pFrame )
515  {
516  if ( pFrame->AcquireGraphics() )
517  {
518  OutputDevice *pDevice = pFrame;
519  pDevice->mpGraphics->ClearDevFontCache();
520  pDevice->mpGraphics->GetDevFontList(pFrame->mpWindowImpl->mpFrameData->mxFontCollection.get());
521  }
522  }
523 }
524 
525 void OutputDevice::ImplRefreshAllFontData(bool bNewFontLists)
526 {
528 }
529 
530 void OutputDevice::ImplUpdateAllFontData(bool bNewFontLists)
531 {
532  OutputDevice::ImplClearAllFontData(bNewFontLists);
534 }
535 
536 void OutputDevice::ImplUpdateFontDataForAllFrames( const FontUpdateHandler_t pHdl, const bool bNewFontLists )
537 {
538  ImplSVData* const pSVData = ImplGetSVData();
539 
540  // update all windows
541  vcl::Window* pFrame = pSVData->maFrameData.mpFirstFrame;
542  while ( pFrame )
543  {
544  ( pFrame->*pHdl )( bNewFontLists );
545 
546  vcl::Window* pSysWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap;
547  while ( pSysWin )
548  {
549  ( pSysWin->*pHdl )( bNewFontLists );
550  pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
551  }
552 
553  pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
554  }
555 
556  // update all virtual devices
557  VirtualDevice* pVirDev = pSVData->maGDIData.mpFirstVirDev;
558  while ( pVirDev )
559  {
560  ( pVirDev->*pHdl )( bNewFontLists );
561  pVirDev = pVirDev->mpNext;
562  }
563 
564  // update all printers
565  Printer* pPrinter = pSVData->maGDIData.mpFirstPrinter;
566  while ( pPrinter )
567  {
568  ( pPrinter->*pHdl )( bNewFontLists );
569  pPrinter = pPrinter->mpNext;
570  }
571 }
572 
574 {
575  ImplSVData* pSVData = ImplGetSVData();
576  pSVData->maGDIData.mbFontSubChanged = false;
577 }
578 
580 {
581  ImplSVData* pSVData = ImplGetSVData();
582  if ( pSVData->maGDIData.mbFontSubChanged )
583  {
584  ImplUpdateAllFontData( false );
585 
589  pSVData->maGDIData.mbFontSubChanged = false;
590  }
591 }
592 
593 void OutputDevice::AddFontSubstitute( const OUString& rFontName,
594  const OUString& rReplaceFontName,
595  AddFontSubstituteFlags nFlags )
596 {
598  if( !rpSubst )
599  rpSubst = new ImplDirectFontSubstitution;
600  rpSubst->AddFontSubstitute( rFontName, rReplaceFontName, nFlags );
602 }
603 
604 void ImplDirectFontSubstitution::AddFontSubstitute( const OUString& rFontName,
605  const OUString& rSubstFontName, AddFontSubstituteFlags nFlags )
606 {
607  maFontSubstList.emplace_back( rFontName, rSubstFontName, nFlags );
608 }
609 
610 ImplFontSubstEntry::ImplFontSubstEntry( const OUString& rFontName,
611  const OUString& rSubstFontName, AddFontSubstituteFlags nSubstFlags )
612 : mnFlags( nSubstFlags )
613 {
614  maSearchName = GetEnglishSearchFontName( rFontName );
615  maSearchReplaceName = GetEnglishSearchFontName( rSubstFontName );
616 }
617 
619 {
621  if( pSubst )
622  pSubst->RemoveFontsSubstitute();
623 }
624 
626 {
627  maFontSubstList.clear();
628 }
629 
631  const OUString& rSearchName ) const
632 {
633  // TODO: get rid of O(N) searches
634  std::vector<ImplFontSubstEntry>::const_iterator it = std::find_if (
635  maFontSubstList.begin(), maFontSubstList.end(),
636  [&] (const ImplFontSubstEntry& s) { return (s.mnFlags & AddFontSubstituteFlags::ALWAYS)
637  && (s.maSearchName == rSearchName); } );
638  if (it != maFontSubstList.end())
639  {
640  rSubstName = it->maSearchReplaceName;
641  return true;
642  }
643  return false;
644 }
645 
646 void ImplFontSubstitute( OUString& rFontName )
647 {
648  // must be canonicalised
649  assert( GetEnglishSearchFontName( rFontName ) == rFontName );
650 
651  OUString aSubstFontName;
652 
653  // apply user-configurable font replacement (eg, from the list in Tools->Options)
655  if( pSubst && pSubst->FindFontSubstitute( aSubstFontName, rFontName ) )
656  {
657  rFontName = aSubstFontName;
658  return;
659  }
660 }
661 
662 //hidpi TODO: This routine has hard-coded font-sizes that break places such as DialControl
664  GetDefaultFontFlags nFlags, const OutputDevice* pOutDev )
665 {
666  if (!pOutDev && !utl::ConfigManager::IsFuzzing()) // default is NULL
667  pOutDev = Application::GetDefaultDevice();
668 
669  OUString aSearch;
671  {
672  LanguageTag aLanguageTag(
673  ( eLang == LANGUAGE_NONE || eLang == LANGUAGE_SYSTEM || eLang == LANGUAGE_DONTKNOW ) ?
674  Application::GetSettings().GetUILanguageTag() :
675  LanguageTag( eLang ));
676 
678  OUString aDefault = rDefaults.getDefaultFont( aLanguageTag, nType );
679 
680  if( !aDefault.isEmpty() )
681  aSearch = aDefault;
682  else
683  aSearch = rDefaults.getUserInterfaceFont( aLanguageTag ); // use the UI font as a fallback
684  }
685  else
686  aSearch = "Liberation Serif";
687 
688  vcl::Font aFont;
689  aFont.SetPitch( PITCH_VARIABLE );
690 
691  switch ( nType )
692  {
693  case DefaultFontType::SANS_UNICODE:
694  case DefaultFontType::UI_SANS:
695  aFont.SetFamily( FAMILY_SWISS );
696  break;
697 
698  case DefaultFontType::SANS:
699  case DefaultFontType::LATIN_HEADING:
700  case DefaultFontType::LATIN_SPREADSHEET:
701  case DefaultFontType::LATIN_DISPLAY:
702  aFont.SetFamily( FAMILY_SWISS );
703  break;
704 
705  case DefaultFontType::SERIF:
706  case DefaultFontType::LATIN_TEXT:
707  case DefaultFontType::LATIN_PRESENTATION:
708  aFont.SetFamily( FAMILY_ROMAN );
709  break;
710 
711  case DefaultFontType::FIXED:
712  case DefaultFontType::LATIN_FIXED:
713  case DefaultFontType::UI_FIXED:
714  aFont.SetPitch( PITCH_FIXED );
715  aFont.SetFamily( FAMILY_MODERN );
716  break;
717 
718  case DefaultFontType::SYMBOL:
719  aFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
720  break;
721 
722  case DefaultFontType::CJK_TEXT:
723  case DefaultFontType::CJK_PRESENTATION:
724  case DefaultFontType::CJK_SPREADSHEET:
725  case DefaultFontType::CJK_HEADING:
726  case DefaultFontType::CJK_DISPLAY:
727  aFont.SetFamily( FAMILY_SYSTEM ); // don't care, but don't use font subst config later...
728  break;
729 
730  case DefaultFontType::CTL_TEXT:
731  case DefaultFontType::CTL_PRESENTATION:
732  case DefaultFontType::CTL_SPREADSHEET:
733  case DefaultFontType::CTL_HEADING:
734  case DefaultFontType::CTL_DISPLAY:
735  aFont.SetFamily( FAMILY_SYSTEM ); // don't care, but don't use font subst config later...
736  break;
737  }
738 
739  if ( !aSearch.isEmpty() )
740  {
741  aFont.SetFontHeight( 12 ); // corresponds to nDefaultHeight
742  aFont.SetWeight( WEIGHT_NORMAL );
743  aFont.SetLanguage( eLang );
744 
745  if ( aFont.GetCharSet() == RTL_TEXTENCODING_DONTKNOW )
746  aFont.SetCharSet( osl_getThreadTextEncoding() );
747 
748  // Should we only return available fonts on the given device
749  if ( pOutDev )
750  {
751  pOutDev->ImplInitFontList();
752 
753  // Search Font in the FontList
754  OUString aName;
755  sal_Int32 nIndex = 0;
756  do
757  {
758  PhysicalFontFamily* pFontFamily = pOutDev->mxFontCollection->FindFontFamily( GetNextFontToken( aSearch, nIndex ) );
759  if( pFontFamily )
760  {
761  AddTokenFontName( aName, pFontFamily->GetFamilyName() );
762  if( nFlags & GetDefaultFontFlags::OnlyOne )
763  break;
764  }
765  }
766  while ( nIndex != -1 );
767  aFont.SetFamilyName( aName );
768  }
769 
770  // No Name, then set all names
771  if ( aFont.GetFamilyName().isEmpty() )
772  {
773  if ( nFlags & GetDefaultFontFlags::OnlyOne )
774  {
775  if( !pOutDev )
776  {
777  SAL_WARN_IF(!utl::ConfigManager::IsFuzzing(), "vcl.gdi", "No default window has been set for the application - we really shouldn't be able to get here");
778  aFont.SetFamilyName( aSearch.getToken( 0, ';' ) );
779  }
780  else
781  {
782  pOutDev->ImplInitFontList();
783 
784  aFont.SetFamilyName( aSearch );
785 
786  // convert to pixel height
787  Size aSize = pOutDev->ImplLogicToDevicePixel( aFont.GetFontSize() );
788  if ( !aSize.Height() )
789  {
790  // use default pixel height only when logical height is zero
791  if ( aFont.GetFontHeight() )
792  aSize.setHeight( 1 );
793  else
794  aSize.setHeight( (12*pOutDev->mnDPIY)/72 );
795  }
796 
797  // use default width only when logical width is zero
798  if( (0 == aSize.Width()) && (0 != aFont.GetFontSize().Width()) )
799  aSize.setWidth( 1 );
800 
801  // get the name of the first available font
802  float fExactHeight = static_cast<float>(aSize.Height());
803  rtl::Reference<LogicalFontInstance> pFontInstance = pOutDev->mxFontCache->GetFontInstance( pOutDev->mxFontCollection.get(), aFont, aSize, fExactHeight );
804  if (pFontInstance)
805  {
806  assert(pFontInstance->GetFontFace());
807  aFont.SetFamilyName(pFontInstance->GetFontFace()->GetFamilyName());
808  }
809  }
810  }
811  else
812  aFont.SetFamilyName( aSearch );
813  }
814  }
815 
816 #if OSL_DEBUG_LEVEL > 2
817  const char* s = "SANS_UNKNOWN";
818  switch ( nType )
819  {
820  case DefaultFontType::SANS_UNICODE: s = "SANS_UNICODE"; break;
821  case DefaultFontType::UI_SANS: s = "UI_SANS"; break;
822 
823  case DefaultFontType::SANS: s = "SANS"; break;
824  case DefaultFontType::LATIN_HEADING: s = "LATIN_HEADING"; break;
825  case DefaultFontType::LATIN_SPREADSHEET: s = "LATIN_SPREADSHEET"; break;
826  case DefaultFontType::LATIN_DISPLAY: s = "LATIN_DISPLAY"; break;
827 
828  case DefaultFontType::SERIF: s = "SERIF"; break;
829  case DefaultFontType::LATIN_TEXT: s = "LATIN_TEXT"; break;
830  case DefaultFontType::LATIN_PRESENTATION: s = "LATIN_PRESENTATION"; break;
831 
832  case DefaultFontType::FIXED: s = "FIXED"; break;
833  case DefaultFontType::LATIN_FIXED: s = "LATIN_FIXED"; break;
834  case DefaultFontType::UI_FIXED: s = "UI_FIXED"; break;
835 
836  case DefaultFontType::SYMBOL: s = "SYMBOL"; break;
837 
838  case DefaultFontType::CJK_TEXT: s = "CJK_TEXT"; break;
839  case DefaultFontType::CJK_PRESENTATION: s = "CJK_PRESENTATION"; break;
840  case DefaultFontType::CJK_SPREADSHEET: s = "CJK_SPREADSHEET"; break;
841  case DefaultFontType::CJK_HEADING: s = "CJK_HEADING"; break;
842  case DefaultFontType::CJK_DISPLAY: s = "CJK_DISPLAY"; break;
843 
844  case DefaultFontType::CTL_TEXT: s = "CTL_TEXT"; break;
845  case DefaultFontType::CTL_PRESENTATION: s = "CTL_PRESENTATION"; break;
846  case DefaultFontType::CTL_SPREADSHEET: s = "CTL_SPREADSHEET"; break;
847  case DefaultFontType::CTL_HEADING: s = "CTL_HEADING"; break;
848  case DefaultFontType::CTL_DISPLAY: s = "CTL_DISPLAY"; break;
849  }
850  SAL_INFO("vcl.gdi",
851  "OutputDevice::GetDefaultFont() Type=" << s
852  << " lang=" << eLang
853  << " flags=" << static_cast<int>(nFlags)
854  << " family=\"" << aFont.GetFamilyName() << "\"");
855 #endif
856 
857  return aFont;
858 }
859 
861 {
862  if( mxFontCollection->Count() )
863  return;
864 
865  if( !(mpGraphics || AcquireGraphics()) )
866  return;
867 
868  SAL_INFO( "vcl.gdi", "OutputDevice::ImplInitFontList()" );
870 
871  // There is absolutely no way there should be no fonts available on the device
872  if( !mxFontCollection->Count() )
873  {
874  OUString aError( "Application error: no fonts and no vcl resource found on your system" );
875  OUString aResStr(VclResId(SV_ACCESSERROR_NO_FONTS));
876  if (!aResStr.isEmpty())
877  aError = aResStr;
878  Application::Abort(aError);
879  }
880 }
881 
883 {
885 
886  if (!ImplNewFont())
887  return false;
888  if (!mpFontInstance)
889  return false;
890  if (!mpGraphics)
891  {
892  if (!AcquireGraphics())
893  return false;
894  }
895  else if (!mbInitFont)
896  return true;
897 
898  mpGraphics->SetFont(mpFontInstance.get(), 0);
899  mbInitFont = false;
900  return true;
901 }
902 
904 {
905  if (!InitFont())
906  return nullptr;
907  return mpFontInstance.get();
908 }
909 
911 {
913 
914  // get correct font list on the PDF writer if necessary
915  if (GetOutDevType() == OUTDEV_PDF)
916  {
917  const ImplSVData* pSVData = ImplGetSVData();
919  || mxFontCache == pSVData->maGDIData.mxScreenFontCache )
920  const_cast<OutputDevice&>(*this).ImplUpdateFontData();
921  }
922 
923  if ( !mbNewFont )
924  return true;
925 
926  // we need a graphics
927  if ( !mpGraphics && !AcquireGraphics() )
928  {
929  SAL_WARN("vcl.gdi", "OutputDevice::ImplNewFont(): no Graphics, no Font");
930  return false;
931  }
932 
934 
935  // convert to pixel height
936  // TODO: replace integer based aSize completely with subpixel accurate type
937  float fExactHeight = ImplFloatLogicHeightToDevicePixel( static_cast<float>(maFont.GetFontHeight()) );
939  if ( !aSize.Height() )
940  {
941  // use default pixel height only when logical height is zero
942  if ( maFont.GetFontSize().Height() )
943  aSize.setHeight( 1 );
944  else
945  aSize.setHeight( (12*mnDPIY)/72 );
946  fExactHeight = static_cast<float>(aSize.Height());
947  }
948 
949  // select the default width only when logical width is zero
950  if( (0 == aSize.Width()) && (0 != maFont.GetFontSize().Width()) )
951  aSize.setWidth( 1 );
952 
953  // decide if antialiasing is appropriate
954  bool bNonAntialiased(GetAntialiasing() & AntialiasingFlags::DisableText);
956  {
957  const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
958  bNonAntialiased |= bool(rStyleSettings.GetDisplayOptions() & DisplayOptions::AADisable);
959  bNonAntialiased |= (int(rStyleSettings.GetAntialiasingMinPixelHeight()) > maFont.GetFontSize().Height());
960  }
961 
962  // get font entry
964  mpFontInstance = mxFontCache->GetFontInstance(mxFontCollection.get(), maFont, aSize, fExactHeight, bNonAntialiased);
965  const bool bNewFontInstance = pOldFontInstance.get() != mpFontInstance.get();
966  pOldFontInstance.clear();
967 
968  LogicalFontInstance* pFontInstance = mpFontInstance.get();
969 
970  if (!pFontInstance)
971  {
972  SAL_WARN("vcl.gdi", "OutputDevice::ImplNewFont(): no LogicalFontInstance, no Font");
973  return false;
974  }
975 
976  // mark when lower layers need to get involved
977  mbNewFont = false;
978  if( bNewFontInstance )
979  mbInitFont = true;
980 
981  // select font when it has not been initialized yet
982  if (!pFontInstance->mbInit && InitFont())
983  {
984  // get metric data from device layers
985  pFontInstance->mbInit = true;
986 
987  pFontInstance->mxFontMetric->SetOrientation( mpFontInstance->GetFontSelectPattern().mnOrientation );
988  mpGraphics->GetFontMetric( pFontInstance->mxFontMetric, 0 );
989 
990  pFontInstance->mxFontMetric->ImplInitTextLineSize( this );
991  pFontInstance->mxFontMetric->ImplInitAboveTextLineSize();
992  pFontInstance->mxFontMetric->ImplInitFlags( this );
993 
994  pFontInstance->mnLineHeight = pFontInstance->mxFontMetric->GetAscent() + pFontInstance->mxFontMetric->GetDescent();
995 
996  SetFontOrientation( pFontInstance );
997  }
998 
999  // calculate EmphasisArea
1000  mnEmphasisAscent = 0;
1001  mnEmphasisDescent = 0;
1002  if ( maFont.GetEmphasisMark() & FontEmphasisMark::Style )
1003  {
1005  tools::Long nEmphasisHeight = (pFontInstance->mnLineHeight*250)/1000;
1006  if ( nEmphasisHeight < 1 )
1007  nEmphasisHeight = 1;
1008  if ( nEmphasisMark & FontEmphasisMark::PosBelow )
1009  mnEmphasisDescent = nEmphasisHeight;
1010  else
1011  mnEmphasisAscent = nEmphasisHeight;
1012  }
1013 
1014  // calculate text offset depending on TextAlignment
1015  TextAlign eAlign = maFont.GetAlignment();
1016  if ( eAlign == ALIGN_BASELINE )
1017  {
1018  mnTextOffX = 0;
1019  mnTextOffY = 0;
1020  }
1021  else if ( eAlign == ALIGN_TOP )
1022  {
1023  mnTextOffX = 0;
1024  mnTextOffY = +pFontInstance->mxFontMetric->GetAscent() + mnEmphasisAscent;
1025  if ( pFontInstance->mnOrientation )
1026  {
1027  Point aOriginPt(0, 0);
1028  aOriginPt.RotateAround( mnTextOffX, mnTextOffY, pFontInstance->mnOrientation );
1029  }
1030  }
1031  else // eAlign == ALIGN_BOTTOM
1032  {
1033  mnTextOffX = 0;
1034  mnTextOffY = -pFontInstance->mxFontMetric->GetDescent() + mnEmphasisDescent;
1035  if ( pFontInstance->mnOrientation )
1036  {
1037  Point aOriginPt(0, 0);
1038  aOriginPt.RotateAround( mnTextOffX, mnTextOffY, pFontInstance->mnOrientation );
1039  }
1040  }
1041 
1047 
1048 
1049  bool bRet = true;
1050 
1051  // #95414# fix for OLE objects which use scale factors very creatively
1052  if( mbMap && !aSize.Width() )
1053  {
1054  int nOrigWidth = pFontInstance->mxFontMetric->GetWidth();
1055  float fStretch = static_cast<float>(maMapRes.mnMapScNumX) * maMapRes.mnMapScDenomY;
1056  fStretch /= static_cast<float>(maMapRes.mnMapScNumY) * maMapRes.mnMapScDenomX;
1057  int nNewWidth = static_cast<int>(nOrigWidth * fStretch + 0.5);
1058  if( (nNewWidth != nOrigWidth) && (nNewWidth != 0) )
1059  {
1060  Size aOrigSize = maFont.GetFontSize();
1061  const_cast<vcl::Font&>(maFont).SetFontSize( Size( nNewWidth, aSize.Height() ) );
1062  mbMap = false;
1063  mbNewFont = true;
1064  bRet = ImplNewFont(); // recurse once using stretched width
1065  mbMap = true;
1066  const_cast<vcl::Font&>(maFont).SetFontSize( aOrigSize );
1067  }
1068  }
1069 
1070  return bRet;
1071 }
1072 
1073 void OutputDevice::SetFontOrientation( LogicalFontInstance* const pFontInstance ) const
1074 {
1075  if( pFontInstance->GetFontSelectPattern().mnOrientation && !pFontInstance->mxFontMetric->GetOrientation() )
1076  {
1077  pFontInstance->mnOwnOrientation = pFontInstance->GetFontSelectPattern().mnOrientation;
1078  pFontInstance->mnOrientation = pFontInstance->mnOwnOrientation;
1079  }
1080  else
1081  {
1082  pFontInstance->mnOrientation = pFontInstance->mxFontMetric->GetOrientation();
1083  }
1084 }
1085 
1087  const tools::PolyPolygon& rPolyPoly, bool bPolyLine,
1088  const tools::Rectangle& rRect1, const tools::Rectangle& rRect2 )
1089 {
1090  if( IsRTLEnabled() )
1091  nX = nBaseX - (nX - nBaseX - 1);
1092 
1093  nX -= mnOutOffX;
1094  nY -= mnOutOffY;
1095 
1096  if ( rPolyPoly.Count() )
1097  {
1098  if ( bPolyLine )
1099  {
1100  tools::Polygon aPoly = rPolyPoly.GetObject( 0 );
1101  aPoly.Move( nX, nY );
1102  DrawPolyLine( aPoly );
1103  }
1104  else
1105  {
1106  tools::PolyPolygon aPolyPoly = rPolyPoly;
1107  aPolyPoly.Move( nX, nY );
1108  DrawPolyPolygon( aPolyPoly );
1109  }
1110  }
1111 
1112  if ( !rRect1.IsEmpty() )
1113  {
1114  tools::Rectangle aRect( Point( nX+rRect1.Left(),
1115  nY+rRect1.Top() ), rRect1.GetSize() );
1116  DrawRect( aRect );
1117  }
1118 
1119  if ( !rRect2.IsEmpty() )
1120  {
1121  tools::Rectangle aRect( Point( nX+rRect2.Left(),
1122  nY+rRect2.Top() ), rRect2.GetSize() );
1123 
1124  DrawRect( aRect );
1125  }
1126 }
1127 
1129 {
1130  Color aOldLineColor = GetLineColor();
1131  Color aOldFillColor = GetFillColor();
1132  bool bOldMap = mbMap;
1133  GDIMetaFile* pOldMetaFile = mpMetaFile;
1134  mpMetaFile = nullptr;
1135  EnableMapMode( false );
1136 
1138  tools::PolyPolygon aPolyPoly;
1139  tools::Rectangle aRect1;
1140  tools::Rectangle aRect2;
1141  tools::Long nEmphasisYOff;
1142  tools::Long nEmphasisWidth;
1143  tools::Long nEmphasisHeight;
1144  bool bPolyLine;
1145 
1146  if ( nEmphasisMark & FontEmphasisMark::PosBelow )
1147  nEmphasisHeight = mnEmphasisDescent;
1148  else
1149  nEmphasisHeight = mnEmphasisAscent;
1150 
1151  ImplGetEmphasisMark( aPolyPoly, bPolyLine,
1152  aRect1, aRect2,
1153  nEmphasisYOff, nEmphasisWidth,
1154  nEmphasisMark,
1155  nEmphasisHeight );
1156 
1157  if ( bPolyLine )
1158  {
1160  SetFillColor();
1161  }
1162  else
1163  {
1164  SetLineColor();
1166  }
1167 
1168  Point aOffset(0,0);
1169 
1170  if ( nEmphasisMark & FontEmphasisMark::PosBelow )
1171  aOffset.AdjustY(mpFontInstance->mxFontMetric->GetDescent() + nEmphasisYOff );
1172  else
1173  aOffset.AdjustY( -(mpFontInstance->mxFontMetric->GetAscent() + nEmphasisYOff) );
1174 
1175  tools::Long nEmphasisWidth2 = nEmphasisWidth / 2;
1176  tools::Long nEmphasisHeight2 = nEmphasisHeight / 2;
1177  aOffset += Point( nEmphasisWidth2, nEmphasisHeight2 );
1178 
1179  Point aOutPoint;
1180  tools::Rectangle aRectangle;
1181  const GlyphItem* pGlyph;
1182  int nStart = 0;
1183  while (rSalLayout.GetNextGlyph(&pGlyph, aOutPoint, nStart))
1184  {
1185  if (!pGlyph->GetGlyphBoundRect(aRectangle))
1186  continue;
1187 
1188  if (!pGlyph->IsSpacing())
1189  {
1190  Point aAdjPoint = aOffset;
1191  aAdjPoint.AdjustX(aRectangle.Left() + (aRectangle.GetWidth() - nEmphasisWidth) / 2 );
1192  if ( mpFontInstance->mnOrientation )
1193  {
1194  Point aOriginPt(0, 0);
1195  aOriginPt.RotateAround( aAdjPoint, mpFontInstance->mnOrientation );
1196  }
1197  aOutPoint += aAdjPoint;
1198  aOutPoint -= Point( nEmphasisWidth2, nEmphasisHeight2 );
1199  ImplDrawEmphasisMark( rSalLayout.DrawBase().X(),
1200  aOutPoint.X(), aOutPoint.Y(),
1201  aPolyPoly, bPolyLine, aRect1, aRect2 );
1202  }
1203  }
1204 
1205  SetLineColor( aOldLineColor );
1206  SetFillColor( aOldFillColor );
1207  EnableMapMode( bOldMap );
1208  mpMetaFile = pOldMetaFile;
1209 }
1210 
1211 std::unique_ptr<SalLayout> OutputDevice::getFallbackLayout(
1212  LogicalFontInstance* pLogicalFont, int nFallbackLevel,
1213  ImplLayoutArgs& rLayoutArgs) const
1214 {
1215  // we need a graphics
1216  if (!mpGraphics && !AcquireGraphics())
1217  return nullptr;
1218 
1219  assert(mpGraphics != nullptr);
1220  mpGraphics->SetFont( pLogicalFont, nFallbackLevel );
1221 
1222  rLayoutArgs.ResetPos();
1223  std::unique_ptr<GenericSalLayout> pFallback = mpGraphics->GetTextLayout(nFallbackLevel);
1224 
1225  if (!pFallback)
1226  return nullptr;
1227 
1228  if (!pFallback->LayoutText(rLayoutArgs, nullptr))
1229  {
1230  // there is no need for a font that couldn't resolve anything
1231  return nullptr;
1232  }
1233 
1234  return pFallback;
1235 }
1236 
1237 std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_ptr<SalLayout> pSalLayout, ImplLayoutArgs& rLayoutArgs ) const
1238 {
1239  // This function relies on a valid mpFontInstance, if it doesn't exist bail out
1240  // - we'd have crashed later on anyway. At least here we can catch the error in debug
1241  // mode.
1242  if ( !mpFontInstance )
1243  {
1244  SAL_WARN ("vcl.gdi", "No font entry set in OutputDevice");
1246  return nullptr;
1247  }
1248 
1249  // keep a pointer to the layout because we might move ownership of the unique_ptr
1250  const SalLayout* pSalLayoutTmp = pSalLayout.get();
1251 
1252  // prepare multi level glyph fallback
1253  std::unique_ptr<MultiSalLayout> pMultiSalLayout;
1254  ImplLayoutRuns aLayoutRuns = rLayoutArgs.maRuns;
1255  rLayoutArgs.PrepareFallback();
1256  rLayoutArgs.mnFlags |= SalLayoutFlags::ForFallback;
1257 
1258  // get list of code units that need glyph fallback
1259  int nCharPos = -1;
1260  bool bRTL = false;
1261  OUStringBuffer aMissingCodeBuf(512);
1262  while (rLayoutArgs.GetNextPos( &nCharPos, &bRTL))
1263  aMissingCodeBuf.append(rLayoutArgs.mrStr[nCharPos]);
1264  rLayoutArgs.ResetPos();
1265  OUString aMissingCodes = aMissingCodeBuf.makeStringAndClear();
1266 
1267  FontSelectPattern aFontSelData(mpFontInstance->GetFontSelectPattern());
1268 
1269  // try if fallback fonts support the missing code units
1270  for( int nFallbackLevel = 1; nFallbackLevel < MAX_FALLBACK; ++nFallbackLevel )
1271  {
1272  // find a font family suited for glyph fallback
1273  // GetGlyphFallbackFont() needs a valid FontInstance
1274  // if the system-specific glyph fallback is active
1275  rtl::Reference<LogicalFontInstance> pFallbackFont = mxFontCache->GetGlyphFallbackFont( mxFontCollection.get(),
1276  aFontSelData, mpFontInstance.get(), nFallbackLevel, aMissingCodes );
1277  if( !pFallbackFont )
1278  break;
1279 
1280  if( nFallbackLevel < MAX_FALLBACK-1)
1281  {
1282  // ignore fallback font if it is the same as the original font
1283  // unless we are looking for a substitution for 0x202F, in which
1284  // case we'll just use a normal space
1285  if( mpFontInstance->GetFontFace() == pFallbackFont->GetFontFace() &&
1286  aMissingCodes.indexOf(0x202F) == -1 )
1287  {
1288  continue;
1289  }
1290  }
1291 
1292  // create and add glyph fallback layout to multilayout
1293  std::unique_ptr<SalLayout> pFallback = getFallbackLayout(pFallbackFont.get(),
1294  nFallbackLevel, rLayoutArgs);
1295  if (pFallback)
1296  {
1297  if( !pMultiSalLayout )
1298  pMultiSalLayout.reset( new MultiSalLayout( std::move(pSalLayout) ) );
1299  pMultiSalLayout->AddFallback(std::move(pFallback), rLayoutArgs.maRuns);
1300  if (nFallbackLevel == MAX_FALLBACK-1)
1301  pMultiSalLayout->SetIncomplete(true);
1302  }
1303 
1304  // break when this fallback was sufficient
1305  if( !rLayoutArgs.PrepareFallback() )
1306  break;
1307  }
1308 
1309  if( pMultiSalLayout && pMultiSalLayout->LayoutText( rLayoutArgs, nullptr ) )
1310  pSalLayout = std::move(pMultiSalLayout);
1311 
1312  // restore orig font settings
1313  pSalLayoutTmp->InitFont();
1314  rLayoutArgs.maRuns = aLayoutRuns;
1315 
1316  return pSalLayout;
1317 }
1318 
1320 {
1321  if (!ImplNewFont())
1322  return 0;
1323 
1324  return ImplDevicePixelToLogicWidth( mpFontInstance->mxFontMetric->GetMinKashida() );
1325 }
1326 
1327 sal_Int32 OutputDevice::ValidateKashidas ( const OUString& rTxt,
1328  sal_Int32 nIdx, sal_Int32 nLen,
1329  sal_Int32 nKashCount,
1330  const sal_Int32* pKashidaPos,
1331  sal_Int32* pKashidaPosDropped ) const
1332 {
1333  // do layout
1334  std::unique_ptr<SalLayout> pSalLayout = ImplLayout( rTxt, nIdx, nLen );
1335  if( !pSalLayout )
1336  return 0;
1337  sal_Int32 nDropped = 0;
1338  for( int i = 0; i < nKashCount; ++i )
1339  {
1340  if( !pSalLayout->IsKashidaPosValid( pKashidaPos[ i ] ))
1341  {
1342  pKashidaPosDropped[ nDropped ] = pKashidaPos [ i ];
1343  ++nDropped;
1344  }
1345  }
1346  return nDropped;
1347 }
1348 
1349 bool OutputDevice::GetGlyphBoundRects( const Point& rOrigin, const OUString& rStr,
1350  int nIndex, int nLen, MetricVector& rVector )
1351 {
1352  rVector.clear();
1353 
1354  if( nIndex >= rStr.getLength() )
1355  return false;
1356 
1357  if( nLen < 0 || nIndex + nLen >= rStr.getLength() )
1358  {
1359  nLen = rStr.getLength() - nIndex;
1360  }
1361 
1362  tools::Rectangle aRect;
1363  for( int i = 0; i < nLen; i++ )
1364  {
1365  if( !GetTextBoundRect( aRect, rStr, nIndex, nIndex + i, 1 ) )
1366  break;
1367  aRect.Move( rOrigin.X(), rOrigin.Y() );
1368  rVector.push_back( aRect );
1369  }
1370 
1371  return (nLen == static_cast<int>(rVector.size()));
1372 }
1373 
1374 sal_Int32 OutputDevice::HasGlyphs( const vcl::Font& rTempFont, const OUString& rStr,
1375  sal_Int32 nIndex, sal_Int32 nLen ) const
1376 {
1377  if( nIndex >= rStr.getLength() )
1378  return nIndex;
1379  sal_Int32 nEnd;
1380  if( nLen == -1 )
1381  nEnd = rStr.getLength();
1382  else
1383  nEnd = std::min( rStr.getLength(), nIndex + nLen );
1384 
1385  SAL_WARN_IF( nIndex >= nEnd, "vcl.gdi", "StartPos >= EndPos?" );
1386  SAL_WARN_IF( nEnd > rStr.getLength(), "vcl.gdi", "String too short" );
1387 
1388  // to get the map temporarily set font
1389  const vcl::Font aOrigFont = GetFont();
1390  const_cast<OutputDevice&>(*this).SetFont( rTempFont );
1391  FontCharMapRef xFontCharMap;
1392  bool bRet = GetFontCharMap( xFontCharMap );
1393  const_cast<OutputDevice&>(*this).SetFont( aOrigFont );
1394 
1395  // if fontmap is unknown assume it doesn't have the glyphs
1396  if( !bRet )
1397  return nIndex;
1398 
1399  for( sal_Int32 i = nIndex; nIndex < nEnd; ++i, ++nIndex )
1400  if( ! xFontCharMap->HasChar( rStr[i] ) )
1401  return nIndex;
1402 
1403  return -1;
1404 }
1405 
1407 
1409 
1411 {
1413 }
1414 
1416 {
1417  mxFontCache = std::make_shared<ImplFontCache>();
1418 }
1419 
1420 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetFamily(FontFamily)
Definition: font/font.cxx:123
SAL_DLLPRIVATE std::unique_ptr< SalLayout > ImplGlyphFallbackLayout(std::unique_ptr< SalLayout >, ImplLayoutArgs &) const
sal_uInt16 Count() const
const Color & GetTextColor() const
Definition: outdev.hxx:1132
OutDevType GetOutDevType() const
Definition: outdev.hxx:523
bool HasChar(sal_UCS4) const
Does the font character map include the UCS4 character?
#define LANGUAGE_NONE
virtual void ClearDevFontCache()=0
static vcl::Font GetDefaultFont(DefaultFontType nType, LanguageType eLang, GetDefaultFontFlags nFlags, const OutputDevice *pOutDev=nullptr)
bool GetFontCharMap(FontCharMapRef &rxFontCharMap) const
sal_Int32 nIndex
const tools::Polygon & GetObject(sal_uInt16 nPos) const
void SetFontSize(const Size &)
Definition: font/font.cxx:117
const OUString & GetStyleName() const
static void AddFontSubstitute(const OUString &rFontName, const OUString &rReplaceFontName, AddFontSubstituteFlags nFlags)
tools::Long mnTextOffX
font specific text alignment offsets in pixel units
Definition: outdev.hxx:349
const OUString & GetFamilyName() const
Definition: font/font.cxx:671
std::vector< tools::Rectangle > MetricVector
Definition: outdev.hxx:137
bool mbFontSubChanged
Definition: svdata.hxx:228
tools::Long mnLineHeight
void setWidth(tools::Long nWidth)
static void NotifyAllWindows(DataChangedEvent &rDCEvt)
Notify all windows that the application has changed data.
Definition: svapp.cxx:734
FAMILY_MODERN
virtual void ImplRefreshFontData(bool bNewFontLists)
VclPtr< VirtualDevice > mpNext
Definition: virdev.hxx:50
bool IsDefaultMap() const
Determines if the font character map is the "default".
bool GetNextPos(int *nCharPos, bool *bRTL)
Definition: sallayout.hxx:109
bool IsOutline() const
Definition: font/font.cxx:708
LanguageType getLanguageType(bool bResolveSystem=true) const
sal_Int32 HasGlyphs(const vcl::Font &rFont, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1) const
bool mbTextSpecial
Definition: outdev.hxx:389
FontLineStyle GetOverline() const
Definition: font/font.cxx:712
static SAL_DLLPRIVATE void ImplUpdateFontDataForAllFrames(FontUpdateHandler_t pHdl, bool bNewFontLists)
LanguageType GetCJKContextLanguage() const
Definition: font/font.cxx:685
#define MAX_FALLBACK
Definition: sallayout.hxx:42
long Long
bool FindFontSubstitute(OUString &rSubstName, const OUString &rFontName) const
static void EndFontSubstitution()
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:707
virtual bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const =0
FontEmphasisMark
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
OUString maSearchReplaceName
Definition: outdev.h:88
SAL_DLLPRIVATE std::unique_ptr< SalLayout > getFallbackLayout(LogicalFontInstance *pLogicalFont, int nFallbackLevel, ImplLayoutArgs &rLayoutArgs) const
void SetInternalLeading(tools::Long nIntLeading)
Definition: metric.hxx:50
void SetWeight(FontWeight)
Definition: font/font.cxx:215
tools::Long mnOutOffY
Output offset for device output in pixel (pseudo window offset within window system's frames) ...
Definition: outdev.hxx:342
void DrawPolyLine(const tools::Polygon &rPoly)
Render the given polygon as a line stroke.
Definition: polyline.cxx:33
const ContentProperties & rData
std::shared_ptr< PhysicalFontCollection > mxFontCollection
Definition: outdev.hxx:320
sal_Int32 mnDPIY
Definition: outdev.hxx:346
hb_font_t * GetHbFont()
tools::Long GetWidth() const
void Move(tools::Long nHorzMove, tools::Long nVertMove)
std::unique_ptr< ImplDeviceFontSizeList > mpDeviceFontSizeList
Definition: outdev.hxx:322
void SetCharSet(rtl_TextEncoding)
Definition: font/font.cxx:129
void ReleaseFontCollection()
void ImplInitAboveTextLineSize()
Definition: fontmetric.cxx:216
FAMILY_ROMAN
void EnableMapMode(bool bEnable=true)
Definition: map.cxx:538
bool IsSpacing() const
bool mbMap
Definition: outdev.hxx:373
SAL_DLLPRIVATE const LogicalFontInstance * GetFontInstance() const
ImplFontMetricDataRef mxFontMetric
tools::Long mnMapScDenomX
Definition: outdevmap.hxx:29
AntialiasingFlags GetAntialiasing() const
Definition: outdev.hxx:603
tools::Long mnEmphasisDescent
Definition: outdev.hxx:352
ImplSVGDIData maGDIData
Definition: svdata.hxx:390
virtual std::unique_ptr< GenericSalLayout > GetTextLayout(int nFallbackLevel)=0
tools::Long GetFontHeight() const
Definition: font/font.cxx:676
tools::Long GetInternalLeading() const
void ImplInitTextLineSize(const OutputDevice *pDev)
Definition: fontmetric.cxx:126
void Scale(double fScaleX, double fScaleY)
FontAlign GetAlignment() const
Definition: font/font.cxx:669
void SetQuality(int)
Definition: font/font.cxx:704
virtual FontCharMapRef GetFontCharMap() const =0
OUString maSearchName
Definition: outdev.h:87
static OutputDevice * GetDefaultDevice()
Get the default "device" (in this case the default window).
Definition: svapp.cxx:1047
bool IsEmpty() const
HashMap_OWString_Interface aMap
SAL_DLLPRIVATE void ImplInitFontList() const
FuncFlags mnFlags
LanguageType GetLanguage() const
Definition: font/font.cxx:684
VclPtr< Printer > mpNext
Definition: print.hxx:152
static void ImplCallEventListenersApplicationDataChanged(void *pData)
Send event to all VCL application event listeners.
Definition: svapp.cxx:753
AddFontSubstituteFlags
Definition: outdev.hxx:242
tools::Long Left() const
LINESTYLE_NONE
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
OUString GetEnglishSearchFontName(const OUString &rInName)
const vcl::Font & GetFont() const
Definition: outdev.hxx:648
ImplLayoutRuns maRuns
Definition: sallayout.hxx:95
static bool IsFuzzing()
int nCount
void RefreshFontData(const bool bNewFontLists)
tools::Long mnMapScDenomY
Definition: outdevmap.hxx:30
tools::Long GetDescent() const
void Insert(const tools::Polygon &rPoly, sal_uInt16 nPos=POLYPOLY_APPEND)
FontMetric GetFontMetric() const
VclPtr< VirtualDevice > mpFirstVirDev
Definition: svdata.hxx:217
PITCH_VARIABLE
SAL_DLLPRIVATE bool ImplNewFont() const
void SetFontCollectionFromSVData()
FontItalic GetItalic() const
bool GetFontFeatures(std::vector< vcl::font::Feature > &rFontFeatures) const
rtl_TextEncoding GetCharSet() const
void ReleaseFontCache()
static void BeginFontSubstitution()
void AddTokenFontName(OUString &rName, const OUString &rNewToken)
GetDefaultFontFlags
Definition: outdev.hxx:254
FontEmphasisMark GetEmphasisMark() const
Definition: font/font.cxx:714
void SetLanguage(LanguageType)
Definition: font/font.cxx:174
bool AddTempDevFont(const OUString &rFileURL, const OUString &rFontName)
OUString getDefaultFont(const LanguageTag &rLanguageTag, DefaultFontType nType) const
void DrawRect(const tools::Rectangle &rRect)
Definition: rect.cxx:51
void SetPitch(FontPitch ePitch)
Definition: font/font.cxx:186
const LanguageTag & GetLanguageTag() const
#define SAL_N_ELEMENTS(arr)
SalGraphics * mpGraphics
Graphics context to draw on.
Definition: outdev.hxx:314
void SetExternalLeading(tools::Long nExtLeading)
Definition: metric.hxx:49
abstract base class for physical font faces
const OUString & mrStr
Definition: sallayout.hxx:82
FontFamily GetFamilyType() const
FontMetric GetDevFont(int nDevFontIndex) const
Definition: outdev/font.cxx:47
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:76
VclPtr< Printer > mpFirstPrinter
Definition: svdata.hxx:219
void SetAlignment(FontAlign)
Definition: font/font.cxx:101
ImplFontSubstEntry(const OUString &rFontName, const OUString &rSubstFontName, AddFontSubstituteFlags nSubstFlags)
static SAL_DLLPRIVATE void ImplRefreshAllFontData(bool bNewFontLists)
void SetLineColor()
ALIGN_BASELINE
tools::Long GetAscent() const
bool IsRTLEnabled() const
Definition: outdev.hxx:1360
void SetFamilyName(const OUString &rFamilyName)
Definition: font/font.cxx:107
virtual void InitFont() const
Definition: vcllayout.hxx:78
int i
SAL_DLLPRIVATE float ImplFloatLogicHeightToDevicePixel(float fLogicHeight) const
Convert logical height to device pixels, with exact sub-pixel value.
Definition: map.cxx:360
Degree10 mnOrientation
Definition: fontselect.hxx:63
bool PrepareFallback()
Definition: sallayout.cxx:489
FontWeight GetWeight() const
tools::Long GetBulletOffset() const
PITCH_FIXED
#define LANGUAGE_SYSTEM
void SetOrientation(Degree10 nLineOrientation)
Definition: font/font.cxx:192
void ImplInitFlags(const OutputDevice *pDev)
Definition: fontmetric.cxx:266
void SetBulletOffset(tools::Long nOffset)
Definition: metric.hxx:53
virtual bool AcquireGraphics() const =0
Acquire a graphics device that the output device uses to draw on.
DisplayOptions GetDisplayOptions() const
std::unique_ptr< ImplDeviceFontList > mpDeviceFontList
Definition: outdev.hxx:321
virtual void SetFontOrientation(LogicalFontInstance *const pFontInstance) const
void SetFillColor()
tools::Long Width() const
bool mbNewFont
Definition: outdev.hxx:387
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:302
WEIGHT_NORMAL
const Color & GetLineColor() const
Definition: outdev.hxx:629
bool mbTextLines
Definition: outdev.hxx:388
bool IsFontAvailable(const OUString &rFontName) const
Definition: outdev/font.cxx:92
void Move(tools::Long nHorzMove, tools::Long nVertMove)
std::unique_ptr< WindowImpl > mpWindowImpl
Definition: window.hxx:519
static SAL_DLLPRIVATE FontEmphasisMark ImplGetEmphasisMarkStyle(const vcl::Font &rFont)
bool IsShadow() const
Definition: font/font.cxx:709
#define LANGUAGE_DONTKNOW
const Size & GetFontSize() const
Definition: font/font.cxx:674
vcl::Font maFont
Definition: outdev.hxx:361
FontStrikeout GetStrikeout() const
Definition: font/font.cxx:713
int GetQuality() const
void SetWidthType(FontWidth)
Definition: font/font.cxx:221
const AllSettings & GetSettings() const
Definition: outdev.hxx:417
tools::Long Top() const
virtual tools::Long GetFontExtLeading() const
LINESTYLE_DONTKNOW
tools::Long mnEmphasisAscent
Definition: outdev.hxx:351
void ReleaseFonts()
Definition: salgdi.hxx:133
Size GetSize() const
static bool isSimplifiedChinese(LanguageType nLang)
std::unique_ptr< SalLayout > ImplLayout(const OUString &, sal_Int32 nIndex, sal_Int32 nLen, const Point &rLogicPos=Point(0, 0), tools::Long nLogicWidth=0, const tools::Long *pLogicDXArray=nullptr, SalLayoutFlags flags=SalLayoutFlags::NONE, vcl::TextLayoutCache const *=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
Definition: text.cxx:1253
Point & DrawBase()
Definition: vcllayout.hxx:70
TextAlign
bool GetGlyphBoundRects(const Point &rOrigin, const OUString &rStr, int nIndex, int nLen, MetricVector &rVector)
Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1049
Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:828
tools::Long const nBorder
FAMILY_SYSTEM
static DefaultFontConfiguration & get()
tools::Long GetMinKashida() const
FontRelief GetRelief() const
Definition: font/font.cxx:710
VclPtr< VirtualDevice > mpAlphaVDev
Definition: outdev.hxx:329
ALIGN_TOP
const FontSelectPattern & GetFontSelectPattern() const
void SetStyleName(const OUString &rStyleName)
Definition: font/font.cxx:112
static void Abort(const OUString &rErrorText)
Ends the program prematurely with an error message.
Definition: svapp.cxx:255
ImplMapRes maMapRes
Definition: outdev.hxx:355
tools::Long mnMapScNumY
Definition: outdevmap.hxx:28
bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
void SetLineHeight(tools::Long nHeight)
Definition: metric.hxx:51
#define SAL_WARN_IF(condition, area, stream)
void ResetNewFontCache()
bool IsFullstopCentered() const
void SetFont(const vcl::Font &rNewFont)
tools::Long mnMapScNumX
Definition: outdevmap.hxx:27
ImplSVFrameData maFrameData
Definition: svdata.hxx:391
#define SAL_INFO(area, stream)
SAL_DLLPRIVATE void ImplDrawEmphasisMarks(SalLayout &)
OUString aName
FAMILY_SWISS
void SetDescent(tools::Long nDescent)
Definition: metric.hxx:48
void ImplFontSubstitute(OUString &rFontName)
SAL_DLLPRIVATE void ImplUpdateFontData()
OUString getUserInterfaceFont(const LanguageTag &rLanguageTag) const
Degree10 GetOrientation() const
tools::Long GetWidth() const
std::shared_ptr< ImplFontCache > mxScreenFontCache
Definition: svdata.hxx:222
ImplDirectFontSubstitution * mpDirectFontSubst
Definition: svdata.hxx:224
void SetOrientation(Degree10 nOrientation)
tools::Long Height() const
void DrawPolyPolygon(const tools::PolyPolygon &rPolyPoly)
Render the given poly-polygon.
Definition: polygon.cxx:36
int GetDevFontSizeCount(const vcl::Font &) const
Definition: outdev/font.cxx:99
virtual void ImplClearFontData(bool bNewFontLists)
bool mbInitFont
Definition: outdev.hxx:383
static SAL_DLLPRIVATE void ImplUpdateAllFontData(bool bNewFontLists)
rtl::Reference< LogicalFontInstance > mpFontInstance
Definition: outdev.hxx:318
void SetAscent(tools::Long nAscent)
Definition: metric.hxx:47
SalLayoutFlags mnFlags
Definition: sallayout.hxx:81
Size GetDevFontSize(const vcl::Font &rFont, int nSizeIndex) const
DefaultFontType
sal_Int32 ValidateKashidas(const OUString &rTxt, sal_Int32 nIdx, sal_Int32 nLen, sal_Int32 nKashCount, const sal_Int32 *pKashidaPos, sal_Int32 *pKashidaPosDropped) const
std::vector< ImplFontSubstEntry > maFontSubstList
Definition: outdev.h:98
void SetFontHeight(tools::Long nHeight)
Definition: font/font.cxx:675
int GetDevFontCount() const
Definition: outdev/font.cxx:72
bool GetTextBoundRect(tools::Rectangle &rRect, const OUString &rStr, sal_Int32 nBase=0, sal_Int32 nIndex=0, sal_Int32 nLen=-1, sal_uLong nLayoutWidth=0, const tools::Long *pDXArray=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
Return the exact bounding rectangle of rStr.
Definition: text.cxx:2264
void SetItalic(FontItalic)
Definition: font/font.cxx:227
void AdaptiveSubdivide(tools::Polygon &rResult, const double d=1.0) const
SAL_DLLPRIVATE tools::Rectangle ImplLogicToDevicePixel(const tools::Rectangle &rLogicRect) const
Convert a logical rectangle to a rectangle in physical device pixel units.
Definition: map.cxx:406
STRIKEOUT_DONTKNOW
void setHeight(tools::Long nHeight)
tools::Long GetHeight() const
FontLineStyle GetUnderline() const
Definition: font/font.cxx:711
virtual bool GetNextGlyph(const GlyphItem **pGlyph, Point &rPos, int &nStart, const PhysicalFontFace **pFallbackFont=nullptr) const =0
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
OUString GetNextFontToken(const OUString &rTokenStr, sal_Int32 &rIndex)
virtual void GetFontMetric(ImplFontMetricDataRef &, int nFallbackLevel)=0
std::shared_ptr< ImplFontCache > mxFontCache
Definition: outdev.hxx:319
VclPtr< vcl::Window > mpFirstFrame
Definition: svdata.hxx:237
FontWidth GetWidthType() const
tools::Long mnOutOffX
Output offset for device output in pixel (pseudo window offset within window system's frames) ...
Definition: outdev.hxx:340
#define SAL_WARN(area, stream)
void SetSlant(tools::Long nSlant)
Definition: metric.hxx:52
bool IsSymbolFont() const
OUString VclResId(const char *pId)
Definition: svdata.cxx:267
virtual bool AddTempDevFont(PhysicalFontCollection *, const OUString &rFileURL, const OUString &rFontName)=0
static void RemoveFontsSubstitute()
SAL_DLLPRIVATE void ImplDrawEmphasisMark(tools::Long nBaseX, tools::Long nX, tools::Long nY, const tools::PolyPolygon &rPolyPoly, bool bPolyLine, const tools::Rectangle &rRect1, const tools::Rectangle &rRect2)
#define DBG_TESTSOLARMUTEX()
tools::Rectangle GetBoundRect() const
void SetFullstopCenteredFlag(bool bCentered)
Definition: metric.hxx:57
FontPitch GetPitch() const
virtual bool AcquireGraphics() const override
Acquire a graphics device that the output device uses to draw on.
Definition: window.cxx:820
virtual void SetFont(LogicalFontInstance *, int nFallbackLevel)=0
STRIKEOUT_NONE
SAL_DLLPRIVATE void ImplGetEmphasisMark(tools::PolyPolygon &rPolyPoly, bool &rPolyLine, tools::Rectangle &rRect1, tools::Rectangle &rRect2, tools::Long &rYOff, tools::Long &rWidth, FontEmphasisMark eEmphasis, tools::Long nHeight)
bool GetGlyphBoundRect(tools::Rectangle &) const
SAL_DLLPRIVATE tools::Long ImplDevicePixelToLogicWidth(tools::Long nWidth) const
Convert device pixels to a width in logical units.
Definition: map.cxx:368
static SAL_DLLPRIVATE void ImplClearAllFontData(bool bNewFontLists)
const OUString & GetFamilyName() const
std::shared_ptr< PhysicalFontCollection > mxScreenFontList
Definition: svdata.hxx:221
SAL_DLLPRIVATE tools::Long ImplDevicePixelToLogicHeight(tools::Long nHeight) const
Convert device pixels to a height in logical units.
Definition: map.cxx:376
void AddFontSubstitute(const OUString &rFontName, const OUString &rSubstName, AddFontSubstituteFlags nFlags)
tools::Long mnTextOffY
Definition: outdev.hxx:350
sal_uLong GetAntialiasingMinPixelHeight() const
rtl_TextEncoding GetCharSet() const
Definition: font/font.cxx:680
const Color & GetFillColor() const
Definition: outdev.hxx:634
GDIMetaFile * mpMetaFile
Definition: outdev.hxx:317
PolyFlags
virtual void GetDevFontList(PhysicalFontCollection *)=0
SAL_DLLPRIVATE bool InitFont() const
const OUString & GetFamilyName() const