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