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