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