File: | home/maarten/src/libreoffice/core/vcl/source/outdev/font.cxx |
Warning: | line 1359, column 5 Dereference of null smart pointer 'pSalLayout' of type 'std::unique_ptr' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
47 | FontMetric 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 | ||||
72 | int 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 | ||||
92 | bool OutputDevice::IsFontAvailable( const OUString& rFontName ) const | |||
93 | { | |||
94 | ImplInitFontList(); | |||
95 | PhysicalFontFamily* pFound = mxFontCollection->FindFontFamily( rFontName ); | |||
96 | return (pFound != nullptr); | |||
97 | } | |||
98 | ||||
99 | int 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 | ||||
108 | Size OutputDevice::GetDevFontSize( const vcl::Font& rFont, int nSizeIndex ) const | |||
109 | { | |||
110 | // check range | |||
111 | int nCount = GetDevFontSizeCount( rFont ); | |||
112 | if ( nSizeIndex >= nCount ) | |||
113 | return Size(); | |||
114 | ||||
115 | // when mapping is enabled round to .5 points | |||
116 | Size aSize( 0, mpDeviceFontSizeList->Get( nSizeIndex ) ); | |||
117 | if ( mbMap ) | |||
118 | { | |||
119 | aSize.setHeight( aSize.Height() * 10 ); | |||
120 | MapMode aMap( MapUnit::Map10thInch, Point(), Fraction( 1, 72 ), Fraction( 1, 72 ) ); | |||
121 | aSize = PixelToLogic( aSize, aMap ); | |||
122 | aSize.AdjustHeight(5 ); | |||
123 | aSize.setHeight( aSize.Height() / 10 ); | |||
124 | long nRound = aSize.Height() % 5; | |||
125 | if ( nRound >= 3 ) | |||
126 | aSize.AdjustHeight(5-nRound); | |||
127 | else | |||
128 | aSize.AdjustHeight( -nRound ); | |||
129 | aSize.setHeight( aSize.Height() * 10 ); | |||
130 | aSize = LogicToPixel( aSize, aMap ); | |||
131 | aSize = PixelToLogic( aSize ); | |||
132 | aSize.AdjustHeight(5 ); | |||
133 | aSize.setHeight( aSize.Height() / 10 ); | |||
134 | } | |||
135 | return aSize; | |||
136 | } | |||
137 | ||||
138 | namespace | |||
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 | ||||
154 | bool 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 | ||||
173 | bool 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 | ||||
198 | FontMetric 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 | ||||
247 | FontMetric 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 | ||||
257 | bool OutputDevice::GetFontCharMap( FontCharMapRef& rxFontCharMap ) const | |||
258 | { | |||
259 | if (!InitFont()) | |||
260 | return false; | |||
261 | ||||
262 | FontCharMapRef xFontCharMap ( mpGraphics->GetFontCharMap() ); | |||
263 | if (!xFontCharMap.is()) | |||
264 | { | |||
265 | FontCharMapRef xDefaultMap( new FontCharMap() ); | |||
266 | rxFontCharMap = xDefaultMap; | |||
267 | } | |||
268 | else | |||
269 | rxFontCharMap = xFontCharMap; | |||
270 | ||||
271 | return !rxFontCharMap->IsDefaultMap(); | |||
272 | } | |||
273 | ||||
274 | bool OutputDevice::GetFontCapabilities( vcl::FontCapabilities& rFontCapabilities ) const | |||
275 | { | |||
276 | if (!InitFont()) | |||
277 | return false; | |||
278 | return mpGraphics->GetFontCapabilities(rFontCapabilities); | |||
279 | } | |||
280 | ||||
281 | void 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 | ||||
442 | FontEmphasisMark 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 | ||||
468 | long OutputDevice::GetFontExtLeading() const | |||
469 | { | |||
470 | return mpFontInstance->mxFontMetric->GetExternalLeading(); | |||
471 | } | |||
472 | ||||
473 | void 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 | ||||
503 | void OutputDevice::RefreshFontData( const bool bNewFontLists ) | |||
504 | { | |||
505 | ImplRefreshFontData( bNewFontLists ); | |||
506 | } | |||
507 | ||||
508 | void OutputDevice::ImplRefreshFontData( const bool bNewFontLists ) | |||
509 | { | |||
510 | if (bNewFontLists && AcquireGraphics()) | |||
511 | mpGraphics->GetDevFontList( mxFontCollection.get() ); | |||
512 | } | |||
513 | ||||
514 | void OutputDevice::ImplUpdateFontData() | |||
515 | { | |||
516 | ImplClearFontData( true/*bNewFontLists*/ ); | |||
517 | ImplRefreshFontData( true/*bNewFontLists*/ ); | |||
518 | } | |||
519 | ||||
520 | void 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 | ||||
544 | void 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 | ||||
558 | void OutputDevice::ImplUpdateAllFontData(bool bNewFontLists) | |||
559 | { | |||
560 | OutputDevice::ImplClearAllFontData(bNewFontLists); | |||
561 | OutputDevice::ImplRefreshAllFontData(bNewFontLists); | |||
562 | } | |||
563 | ||||
564 | void 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 | ||||
601 | void 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 | ||||
622 | void OutputDevice::BeginFontSubstitution() | |||
623 | { | |||
624 | ImplSVData* pSVData = ImplGetSVData(); | |||
625 | pSVData->maGDIData.mbFontSubChanged = false; | |||
626 | } | |||
627 | ||||
628 | void 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 | ||||
642 | void 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 | ||||
653 | void ImplDirectFontSubstitution::AddFontSubstitute( const OUString& rFontName, | |||
654 | const OUString& rSubstFontName, AddFontSubstituteFlags nFlags ) | |||
655 | { | |||
656 | maFontSubstList.emplace_back( rFontName, rSubstFontName, nFlags ); | |||
657 | } | |||
658 | ||||
659 | ImplFontSubstEntry::ImplFontSubstEntry( const OUString& rFontName, | |||
660 | const OUString& rSubstFontName, AddFontSubstituteFlags nSubstFlags ) | |||
661 | : mnFlags( nSubstFlags ) | |||
662 | { | |||
663 | maSearchName = GetEnglishSearchFontName( rFontName ); | |||
664 | maSearchReplaceName = GetEnglishSearchFontName( rSubstFontName ); | |||
665 | } | |||
666 | ||||
667 | void OutputDevice::RemoveFontsSubstitute() | |||
668 | { | |||
669 | ImplDirectFontSubstitution* pSubst = ImplGetSVData()->maGDIData.mpDirectFontSubst; | |||
670 | if( pSubst ) | |||
671 | pSubst->RemoveFontsSubstitute(); | |||
672 | } | |||
673 | ||||
674 | void ImplDirectFontSubstitution::RemoveFontsSubstitute() | |||
675 | { | |||
676 | maFontSubstList.clear(); | |||
677 | } | |||
678 | ||||
679 | bool 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 | ||||
695 | void 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 | |||
712 | vcl::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 | ||||
909 | void 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 | ||||
931 | bool 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 | ||||
952 | const LogicalFontInstance* OutputDevice::GetFontInstance() const | |||
953 | { | |||
954 | if (!InitFont()) | |||
955 | return nullptr; | |||
956 | return mpFontInstance.get(); | |||
957 | } | |||
958 | ||||
959 | bool 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 | ||||
1122 | void 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 | ||||
1135 | void 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 | ||||
1177 | void 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 | ||||
1260 | std::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 | ||||
1286 | std::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 | ||||
1365 | long OutputDevice::GetMinKashida() const | |||
1366 | { | |||
1367 | if (!ImplNewFont()) | |||
1368 | return 0; | |||
1369 | ||||
1370 | return ImplDevicePixelToLogicWidth( mpFontInstance->mxFontMetric->GetMinKashida() ); | |||
1371 | } | |||
1372 | ||||
1373 | sal_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 | ||||
1395 | bool 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 | ||||
1420 | sal_Int32 OutputDevice::HasGlyphs( const vcl::Font& rTempFont, const OUString& rStr, | |||
1421 | sal_Int32 nIndex, sal_Int32 nLen ) const | |||
1422 | { | |||
1423 | if( nIndex >= rStr.getLength() ) | |||
1424 | return nIndex; | |||
1425 | sal_Int32 nEnd; | |||
1426 | if( nLen == -1 ) | |||
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); | |||
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); | |||
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 ); | |||
1439 | const_cast<OutputDevice&>(*this).SetFont( aOrigFont ); | |||
1440 | ||||
1441 | // if fontmap is unknown assume it doesn't have the glyphs | |||
1442 | if( !bRet ) | |||
1443 | return nIndex; | |||
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 | ||||
1452 | void OutputDevice::ReleaseFontCache() { mxFontCache.reset(); } | |||
1453 | ||||
1454 | void OutputDevice::ReleaseFontCollection() { mxFontCollection.reset(); } | |||
1455 | ||||
1456 | void OutputDevice::SetFontCollectionFromSVData() | |||
1457 | { | |||
1458 | mxFontCollection = ImplGetSVData()->maGDIData.mxScreenFontList->Clone(); | |||
1459 | } | |||
1460 | ||||
1461 | void OutputDevice::ResetNewFontCache() | |||
1462 | { | |||
1463 | mxFontCache = std::make_shared<ImplFontCache>(); | |||
1464 | } | |||
1465 | ||||
1466 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |