Bug Summary

File:home/maarten/src/libreoffice/core/include/tools/ref.hxx
Warning:line 56, column 30
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name font.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/glm -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/libmount -isystem /usr/include/blkid -isystem /usr/include/cairo -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/pixman-1 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/libxml2 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/dbus-1.0 -isystem /usr/lib64/dbus-1.0/include -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D VCL_DLLIMPLEMENTATION -D DLLIMPLEMENTATION_UITEST -D CUI_DLL_NAME="libcuilo.so" -D DESKTOP_DETECTOR_DLL_NAME="libdesktop_detectorlo.so" -D TK_DLL_NAME="libtklo.so" -D SYSTEM_ZLIB -D GLM_FORCE_CTOR_INIT -D SK_USER_CONFIG_HEADER=</home/maarten/src/libreoffice/core/config_host/config_skia.h> -D SKIA_DLL -D ENABLE_CUPS -D HAVE_VALGRIND_HEADERS -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/core -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/effects -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/config -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/ports -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/third_party/vulkan -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/tools/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia -I /home/maarten/src/libreoffice/core/external/skia/inc/ -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/mdds/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/lcms2/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/harfbuzz/src -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/graphite/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libpng -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libjpeg-turbo -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/vcl/inc -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libxml2 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/vcl/source/outdev/font.cxx

/home/maarten/src/libreoffice/core/vcl/source/outdev/font.cxx

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

/home/maarten/src/libreoffice/core/include/tools/ref.hxx

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#ifndef INCLUDED_TOOLS_REF_HXX
20#define INCLUDED_TOOLS_REF_HXX
21
22#include <sal/config.h>
23#include <cassert>
24#include <tools/toolsdllapi.h>
25#include <utility>
26
27/**
28 This implements similar functionality to boost::intrusive_ptr
29*/
30
31namespace tools {
32
33/** T must be a class that extends SvRefBase */
34template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final {
35public:
36 SvRef(): pObj(nullptr) {}
37
38 SvRef(SvRef&& rObj) noexcept
39 {
40 pObj = rObj.pObj;
41 rObj.pObj = nullptr;
42 }
43
44 SvRef(SvRef const & rObj): pObj(rObj.pObj)
45 {
46 if (pObj != nullptr) pObj->AddNextRef();
47 }
48
49 SvRef(T * pObjP): pObj(pObjP)
50 {
51 if (pObj != nullptr) pObj->AddFirstRef();
52 }
53
54 ~SvRef()
55 {
56 if (pObj != nullptr) pObj->ReleaseRef();
14
Taking true branch
15
Calling 'SvRefBase::ReleaseRef'
21
Returning; memory was released
26
Taking true branch
27
Use of memory after it is freed
57 }
58
59 void clear()
60 {
61 if (pObj != nullptr) {
62 T * pRefObj = pObj;
63 pObj = nullptr;
64 pRefObj->ReleaseRef();
65 }
66 }
67
68 SvRef & operator =(SvRef const & rObj)
69 {
70 if (rObj.pObj != nullptr) {
71 rObj.pObj->AddNextRef();
72 }
73 T * pRefObj = pObj;
74 pObj = rObj.pObj;
75 if (pRefObj != nullptr) {
76 pRefObj->ReleaseRef();
77 }
78 return *this;
79 }
80
81 SvRef & operator =(SvRef && rObj)
82 {
83 if (pObj != nullptr) {
84 pObj->ReleaseRef();
85 }
86 pObj = rObj.pObj;
87 rObj.pObj = nullptr;
88 return *this;
89 }
90
91 bool is() const { return pObj != nullptr; }
92
93 explicit operator bool() const { return is(); }
94
95 T * get() const { return pObj; }
96
97 T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail
("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx"
, 97, __extension__ __PRETTY_FUNCTION__))
; return pObj; }
98
99 T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail
("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx"
, 99, __extension__ __PRETTY_FUNCTION__))
; return *pObj; }
100
101 bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; }
102 bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); }
103
104private:
105 T * pObj;
106};
107
108/**
109 * This implements similar functionality to std::make_shared.
110 */
111template<typename T, typename... Args>
112SvRef<T> make_ref(Args&& ... args)
113{
114 return SvRef<T>(new T(std::forward<Args>(args)...));
115}
116
117}
118
119/** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */
120class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase
121{
122 // work around a clang 3.5 optimization bug: if the bNoDelete is *first*
123 // it mis-compiles "if (--nRefCount == 0)" and never deletes any object
124 unsigned int nRefCount : 31;
125 // the only reason this is not bool is because MSVC cannot handle mixed type bitfields
126 unsigned int bNoDelete : 1;
127
128protected:
129 virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE;
130
131public:
132 SvRefBase() : nRefCount(0), bNoDelete(1) {}
133 SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {}
134
135 SvRefBase & operator=(const SvRefBase &) { return *this; }
136
137 void RestoreNoDelete()
138 { bNoDelete = 1; }
139
140 void AddNextRef()
141 {
142 assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) &&
"Do not add refs to dead objects") ? void (0) : __assert_fail
("nRefCount < (1 << 30) && \"Do not add refs to dead objects\""
, "/home/maarten/src/libreoffice/core/include/tools/ref.hxx",
142, __extension__ __PRETTY_FUNCTION__))
;
143 ++nRefCount;
144 }
145
146 void AddFirstRef()
147 {
148 assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) &&
"Do not add refs to dead objects") ? void (0) : __assert_fail
("nRefCount < (1 << 30) && \"Do not add refs to dead objects\""
, "/home/maarten/src/libreoffice/core/include/tools/ref.hxx",
148, __extension__ __PRETTY_FUNCTION__))
;
149 if( bNoDelete )
150 bNoDelete = 0;
151 ++nRefCount;
152 }
153
154 void ReleaseRef()
155 {
156 assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail
("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx"
, 156, __extension__ __PRETTY_FUNCTION__))
;
16
'?' condition is true
157 if( --nRefCount == 0 && !bNoDelete)
17
Assuming the condition is true
18
Assuming field 'bNoDelete' is 0
19
Taking true branch
158 {
159 // I'm not sure about the original purpose of this line, but right now
160 // it serves the purpose that anything that attempts to do an AddRef()
161 // after an object is deleted will trip an assert.
162 nRefCount = 1 << 30;
163 delete this;
20
Memory is released
164 }
165 }
166
167 unsigned int GetRefCount() const
168 { return nRefCount; }
169};
170
171template<typename T>
172class SvCompatWeakBase;
173
174/** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T.
175*/
176template<typename T>
177class SvCompatWeakHdl final : public SvRefBase
178{
179 friend class SvCompatWeakBase<T>;
180 T* _pObj;
181
182 SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {}
183
184public:
185 void ResetWeakBase( ) { _pObj = nullptr; }
186 T* GetObj() { return _pObj; }
187};
188
189/** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame.
190 Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted.
191*/
192template<typename T>
193class SvCompatWeakBase
194{
195 tools::SvRef< SvCompatWeakHdl<T> > _xHdl;
196
197public:
198 /** Does not use initializer due to compiler warnings,
199 because the lifetime of the _xHdl object can exceed the lifetime of this class.
200 */
201 SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); }
202
203 ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); }
204
205 SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); }
206};
207
208/** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak.
209*/
210template<typename T>
211class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef
212{
213 tools::SvRef< SvCompatWeakHdl<T> > _xHdl;
214public:
215 SvCompatWeakRef( ) {}
216 SvCompatWeakRef( T* pObj )
217 { if( pObj ) _xHdl = pObj->GetHdl(); }
218#if defined(__COVERITY__)
219 ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {}
220#endif
221 SvCompatWeakRef& operator = ( T * pObj )
222 { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; }
223 bool is() const
224 { return _xHdl.is() && _xHdl->GetObj(); }
225 explicit operator bool() const { return is(); }
226 T* operator -> () const
227 { return _xHdl.is() ? _xHdl->GetObj() : nullptr; }
228 operator T* () const
229 { return _xHdl.is() ? _xHdl->GetObj() : nullptr; }
230};
231
232#endif
233
234/* vim:set shiftwidth=4 softtabstop=4 expandtab: */