Line data Source code
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 "unotools/fontcfg.hxx"
21 :
22 : #include "tools/stream.hxx"
23 : #include "tools/vcompat.hxx"
24 : #include "tools/debug.hxx"
25 : #include <tools/gen.hxx>
26 :
27 : #include "vcl/font.hxx"
28 :
29 : #include "impfont.hxx"
30 : #include "outfont.hxx"
31 : #include "sft.hxx"
32 :
33 : #include <sal/macros.h>
34 :
35 : #include <algorithm>
36 :
37 : using namespace vcl;
38 :
39 55277 : Impl_Font::Impl_Font() :
40 : maColor( COL_TRANSPARENT ),
41 : maFillColor( COL_TRANSPARENT ),
42 : maLanguageTag( LANGUAGE_DONTKNOW ),
43 55277 : maCJKLanguageTag( LANGUAGE_DONTKNOW )
44 : {
45 55277 : mnRefCount = 1;
46 55277 : meCharSet = RTL_TEXTENCODING_DONTKNOW;
47 55277 : meFamily = FAMILY_DONTKNOW;
48 55277 : mePitch = PITCH_DONTKNOW;
49 55277 : meAlign = ALIGN_TOP;
50 55277 : meWeight = WEIGHT_DONTKNOW;
51 55277 : meWidthType = WIDTH_DONTKNOW;
52 55277 : meItalic = ITALIC_NONE;
53 55277 : meUnderline = UNDERLINE_NONE;
54 55277 : meOverline = UNDERLINE_NONE;
55 55277 : meStrikeout = STRIKEOUT_NONE;
56 55277 : meRelief = RELIEF_NONE;
57 55277 : meEmphasisMark = EMPHASISMARK_NONE;
58 55277 : mnOrientation = 0;
59 55277 : mnKerning = FontKerning::NONE;
60 55277 : mbWordLine = false;
61 55277 : mbOutline = false;
62 55277 : mbShadow = false;
63 55277 : mbVertical = false;
64 55277 : mbTransparent = true;
65 55277 : mbConfigLookup = false;
66 55277 : }
67 :
68 7302689 : Impl_Font::Impl_Font( const Impl_Font& rImplFont )
69 : : maFamilyName( rImplFont.maFamilyName ),
70 : maStyleName( rImplFont.maStyleName ),
71 : maSize( rImplFont.maSize ),
72 : maColor( rImplFont.maColor ),
73 : maFillColor( rImplFont.maFillColor ),
74 : maLanguageTag( rImplFont.maLanguageTag ),
75 7302689 : maCJKLanguageTag( rImplFont.maCJKLanguageTag )
76 : {
77 7302689 : mnRefCount = 1;
78 7302689 : meCharSet = rImplFont.meCharSet;
79 7302689 : meFamily = rImplFont.meFamily;
80 7302689 : mePitch = rImplFont.mePitch;
81 7302689 : meAlign = rImplFont.meAlign;
82 7302689 : meWeight = rImplFont.meWeight;
83 7302689 : meWidthType = rImplFont.meWidthType;
84 7302689 : meItalic = rImplFont.meItalic;
85 7302689 : meUnderline = rImplFont.meUnderline;
86 7302689 : meOverline = rImplFont.meOverline;
87 7302689 : meStrikeout = rImplFont.meStrikeout;
88 7302689 : meRelief = rImplFont.meRelief;
89 7302689 : meEmphasisMark = rImplFont.meEmphasisMark;
90 7302689 : mnOrientation = rImplFont.mnOrientation;
91 7302689 : mnKerning = rImplFont.mnKerning;
92 7302689 : mbWordLine = rImplFont.mbWordLine;
93 7302689 : mbOutline = rImplFont.mbOutline;
94 7302689 : mbShadow = rImplFont.mbShadow;
95 7302689 : mbVertical = rImplFont.mbVertical;
96 7302689 : mbTransparent = rImplFont.mbTransparent;
97 7302689 : mbConfigLookup = rImplFont.mbConfigLookup;
98 7302689 : }
99 :
100 1203116 : bool Impl_Font::operator==( const Impl_Font& rOther ) const
101 : {
102 : // equality tests split up for easier debugging
103 1203116 : if( (meWeight != rOther.meWeight)
104 1087696 : || (meItalic != rOther.meItalic)
105 1076788 : || (meFamily != rOther.meFamily)
106 921002 : || (mePitch != rOther.mePitch) )
107 282470 : return false;
108 :
109 1841292 : if( (meCharSet != rOther.meCharSet)
110 915789 : || (maLanguageTag != rOther.maLanguageTag)
111 906745 : || (maCJKLanguageTag != rOther.maCJKLanguageTag)
112 1825206 : || (meAlign != rOther.meAlign) )
113 16100 : return false;
114 :
115 1809092 : if( (maSize != rOther.maSize)
116 801752 : || (mnOrientation != rOther.mnOrientation)
117 1706036 : || (mbVertical != rOther.mbVertical) )
118 103060 : return false;
119 :
120 1602972 : if( (maFamilyName != rOther.maFamilyName)
121 801486 : || (maStyleName != rOther.maStyleName) )
122 6394 : return false;
123 :
124 1590184 : if( (maColor != rOther.maColor)
125 795092 : || (maFillColor != rOther.maFillColor) )
126 10610 : return false;
127 :
128 784482 : if( (meUnderline != rOther.meUnderline)
129 779890 : || (meOverline != rOther.meOverline)
130 779759 : || (meStrikeout != rOther.meStrikeout)
131 779351 : || (meRelief != rOther.meRelief)
132 778700 : || (meEmphasisMark != rOther.meEmphasisMark)
133 778275 : || (mbWordLine != rOther.mbWordLine)
134 778172 : || (mbOutline != rOther.mbOutline)
135 778029 : || (mbShadow != rOther.mbShadow)
136 777971 : || (mnKerning != rOther.mnKerning)
137 774255 : || (mbTransparent != rOther.mbTransparent) )
138 10227 : return false;
139 :
140 774255 : return true;
141 : }
142 :
143 33984 : void Impl_Font::AskConfig()
144 : {
145 33984 : if( mbConfigLookup )
146 54633 : return;
147 :
148 13335 : mbConfigLookup = true;
149 :
150 : // prepare the FontSubst configuration lookup
151 13335 : const utl::FontSubstConfiguration& rFontSubst = utl::FontSubstConfiguration::get();
152 :
153 13335 : OUString aShortName;
154 26670 : OUString aFamilyName;
155 13335 : ImplFontAttrs nType = ImplFontAttrs::None;
156 13335 : FontWeight eWeight = WEIGHT_DONTKNOW;
157 13335 : FontWidth eWidthType = WIDTH_DONTKNOW;
158 26670 : OUString aMapName = GetEnglishSearchFontName( maFamilyName );
159 :
160 : utl::FontSubstConfiguration::getMapName( aMapName,
161 13335 : aShortName, aFamilyName, eWeight, eWidthType, nType );
162 :
163 : // lookup the font name in the configuration
164 13335 : const utl::FontNameAttr* pFontAttr = rFontSubst.getSubstInfo( aMapName );
165 :
166 : // if the direct lookup failed try again with an alias name
167 13335 : if ( !pFontAttr && (aShortName != aMapName) )
168 0 : pFontAttr = rFontSubst.getSubstInfo( aShortName );
169 :
170 13335 : if( pFontAttr )
171 : {
172 : // the font was found in the configuration
173 12759 : if( meFamily == FAMILY_DONTKNOW )
174 : {
175 11983 : if ( pFontAttr->Type & ImplFontAttrs::Serif )
176 118 : meFamily = FAMILY_ROMAN;
177 11865 : else if ( pFontAttr->Type & ImplFontAttrs::SansSerif )
178 9939 : meFamily = FAMILY_SWISS;
179 1926 : else if ( pFontAttr->Type & ImplFontAttrs::Typewriter )
180 64 : meFamily = FAMILY_MODERN;
181 1862 : else if ( pFontAttr->Type & ImplFontAttrs::Italic )
182 0 : meFamily = FAMILY_SCRIPT;
183 1862 : else if ( pFontAttr->Type & ImplFontAttrs::Decorative )
184 0 : meFamily = FAMILY_DECORATIVE;
185 : }
186 :
187 12759 : if( mePitch == PITCH_DONTKNOW )
188 : {
189 12662 : if ( pFontAttr->Type & ImplFontAttrs::Fixed )
190 78 : mePitch = PITCH_FIXED;
191 : }
192 : }
193 :
194 : // if some attributes are still unknown then use the FontSubst magic
195 13335 : if( meFamily == FAMILY_DONTKNOW )
196 : {
197 1927 : if( nType & ImplFontAttrs::Serif )
198 5 : meFamily = FAMILY_ROMAN;
199 1922 : else if( nType & ImplFontAttrs::SansSerif )
200 2 : meFamily = FAMILY_SWISS;
201 1920 : else if( nType & ImplFontAttrs::Typewriter )
202 0 : meFamily = FAMILY_MODERN;
203 1920 : else if( nType & ImplFontAttrs::Italic )
204 0 : meFamily = FAMILY_SCRIPT;
205 1920 : else if( nType & ImplFontAttrs::Decorative )
206 0 : meFamily = FAMILY_DECORATIVE;
207 : }
208 :
209 13335 : if( meWeight == WEIGHT_DONTKNOW )
210 9042 : meWeight = eWeight;
211 13335 : if( meWidthType == WIDTH_DONTKNOW )
212 26670 : meWidthType = eWidthType;
213 : }
214 :
215 25303725 : void Font::MakeUnique()
216 : {
217 : // create a copy if others still reference it
218 25303725 : if ( mpImplFont->mnRefCount != 1 )
219 : {
220 7302689 : if ( mpImplFont->mnRefCount )
221 2750809 : mpImplFont->mnRefCount--;
222 7302689 : mpImplFont = new Impl_Font( *mpImplFont );
223 : }
224 25303725 : }
225 :
226 5905960 : Font::Font()
227 : {
228 :
229 5905960 : static Impl_Font aStaticImplFont;
230 : // RefCount is zero for static objects
231 5905960 : aStaticImplFont.mnRefCount = 0;
232 5905960 : mpImplFont = &aStaticImplFont;
233 5905960 : }
234 :
235 7027390 : Font::Font( const vcl::Font& rFont )
236 : {
237 7027390 : bool bRefIncrementable = rFont.mpImplFont->mnRefCount < ::std::numeric_limits<sal_uInt32>::max();
238 : DBG_ASSERT( bRefIncrementable, "Font: RefCount overflow" );
239 :
240 7027390 : mpImplFont = rFont.mpImplFont;
241 : // do not count static objects (where RefCount is zero)
242 7027390 : if ( mpImplFont->mnRefCount && bRefIncrementable )
243 7012814 : mpImplFont->mnRefCount++;
244 7027390 : }
245 :
246 12444 : Font::Font( const OUString& rFamilyName, const Size& rSize )
247 : {
248 :
249 12444 : mpImplFont = new Impl_Font;
250 12444 : mpImplFont->maFamilyName = rFamilyName;
251 12444 : mpImplFont->maSize = rSize;
252 12444 : }
253 :
254 42068 : Font::Font( const OUString& rFamilyName, const OUString& rStyleName, const Size& rSize )
255 : {
256 :
257 42068 : mpImplFont = new Impl_Font;
258 42068 : mpImplFont->maFamilyName= rFamilyName;
259 42068 : mpImplFont->maStyleName = rStyleName;
260 42068 : mpImplFont->maSize = rSize;
261 42068 : }
262 :
263 538 : Font::Font( FontFamily eFamily, const Size& rSize )
264 : {
265 :
266 538 : mpImplFont = new Impl_Font;
267 538 : mpImplFont->meFamily = eFamily;
268 538 : mpImplFont->maSize = rSize;
269 538 : }
270 :
271 12923096 : Font::~Font()
272 : {
273 :
274 : // decrement reference counter and delete if last reference
275 : // if the object is not static (Refcounter==0)
276 12923096 : if ( mpImplFont->mnRefCount )
277 : {
278 12623303 : if ( mpImplFont->mnRefCount == 1 )
279 3649991 : delete mpImplFont;
280 : else
281 8973312 : mpImplFont->mnRefCount--;
282 : }
283 12923096 : }
284 :
285 1301350 : void Font::SetColor( const Color& rColor )
286 : {
287 :
288 1301350 : if( mpImplFont->maColor != rColor )
289 : {
290 342332 : MakeUnique();
291 342332 : mpImplFont->maColor = rColor;
292 : }
293 1301350 : }
294 :
295 917636 : void Font::SetFillColor( const Color& rColor )
296 : {
297 :
298 917636 : MakeUnique();
299 917636 : mpImplFont->maFillColor = rColor;
300 917636 : if ( rColor.GetTransparency() )
301 892669 : mpImplFont->mbTransparent = true;
302 917636 : if (GetUnderline() == UNDERLINE_SINGLE ) {
303 : SAL_INFO("vcl.gdi", "I'm setting a filling (from Font) of (" << rColor.GetRed() << "," << rColor.GetGreen() << "," << rColor.GetBlue() << ")");
304 : }
305 917636 : }
306 :
307 1356988 : void Font::SetTransparent( bool bTransparent )
308 : {
309 :
310 1356988 : if( mpImplFont->mbTransparent != bTransparent )
311 : {
312 22980 : MakeUnique();
313 22980 : mpImplFont->mbTransparent = bTransparent;
314 : }
315 1356988 : }
316 :
317 1396222 : void Font::SetAlign( FontAlign eAlign )
318 : {
319 :
320 1396222 : if( mpImplFont->meAlign != eAlign )
321 : {
322 301664 : MakeUnique();
323 301664 : mpImplFont->meAlign = eAlign;
324 : }
325 1396222 : }
326 :
327 3716836 : void Font::SetName( const OUString& rFamilyName )
328 : {
329 :
330 3716836 : MakeUnique();
331 3716836 : mpImplFont->maFamilyName = rFamilyName;
332 3716836 : }
333 :
334 2491650 : void Font::SetStyleName( const OUString& rStyleName )
335 : {
336 :
337 2491650 : MakeUnique();
338 2491650 : mpImplFont->maStyleName = rStyleName;
339 2491650 : }
340 :
341 2583165 : void Font::SetSize( const Size& rSize )
342 : {
343 :
344 2583165 : if( mpImplFont->maSize != rSize )
345 : {
346 1885081 : MakeUnique();
347 1885081 : mpImplFont->maSize = rSize;
348 : }
349 2583165 : }
350 :
351 3552103 : void Font::SetFamily( FontFamily eFamily )
352 : {
353 :
354 3552103 : if( mpImplFont->meFamily != eFamily )
355 : {
356 1145887 : MakeUnique();
357 1145887 : mpImplFont->meFamily = eFamily;
358 : }
359 3552103 : }
360 :
361 3609888 : void Font::SetCharSet( rtl_TextEncoding eCharSet )
362 : {
363 :
364 3609888 : if( mpImplFont->meCharSet != eCharSet )
365 : {
366 2659742 : MakeUnique();
367 2659742 : mpImplFont->meCharSet = eCharSet;
368 : }
369 3609888 : }
370 :
371 8842 : void Font::SetLanguageTag( const LanguageTag& rLanguageTag )
372 : {
373 :
374 8842 : if( mpImplFont->maLanguageTag != rLanguageTag )
375 : {
376 0 : MakeUnique();
377 0 : mpImplFont->maLanguageTag = rLanguageTag;
378 : }
379 8842 : }
380 :
381 8842 : void Font::SetCJKContextLanguageTag( const LanguageTag& rLanguageTag )
382 : {
383 :
384 8842 : if( mpImplFont->maCJKLanguageTag != rLanguageTag )
385 : {
386 0 : MakeUnique();
387 0 : mpImplFont->maCJKLanguageTag = rLanguageTag;
388 : }
389 8842 : }
390 :
391 5544017 : void Font::SetLanguage( LanguageType eLanguage )
392 : {
393 :
394 5544017 : if( mpImplFont->maLanguageTag.getLanguageType( false) != eLanguage )
395 : {
396 3180862 : MakeUnique();
397 3180862 : mpImplFont->maLanguageTag.reset( eLanguage);
398 : }
399 5544017 : }
400 :
401 913620 : void Font::SetCJKContextLanguage( LanguageType eLanguage )
402 : {
403 :
404 913620 : if( mpImplFont->maCJKLanguageTag.getLanguageType( false) != eLanguage )
405 : {
406 740064 : MakeUnique();
407 740064 : mpImplFont->maCJKLanguageTag.reset( eLanguage);
408 : }
409 913620 : }
410 :
411 3593510 : void Font::SetPitch( FontPitch ePitch )
412 : {
413 :
414 3593510 : if( mpImplFont->mePitch != ePitch )
415 : {
416 2224869 : MakeUnique();
417 2224869 : mpImplFont->mePitch = ePitch;
418 : }
419 3593510 : }
420 :
421 861758 : void Font::SetOrientation( short nOrientation )
422 : {
423 :
424 861758 : if( mpImplFont->mnOrientation != nOrientation )
425 : {
426 8891 : MakeUnique();
427 8891 : mpImplFont->mnOrientation = nOrientation;
428 : }
429 861758 : }
430 :
431 319155 : void Font::SetVertical( bool bVertical )
432 : {
433 :
434 319155 : if( mpImplFont->mbVertical != bVertical )
435 : {
436 28 : MakeUnique();
437 28 : mpImplFont->mbVertical = bVertical;
438 : }
439 319155 : }
440 :
441 1148539 : void Font::SetKerning( FontKerning nKerning )
442 : {
443 :
444 1148539 : if( mpImplFont->mnKerning != nKerning )
445 : {
446 254573 : MakeUnique();
447 254573 : mpImplFont->mnKerning = nKerning;
448 : }
449 1148539 : }
450 :
451 12946 : bool Font::IsKerning() const
452 : {
453 12946 : return bool(mpImplFont->mnKerning & FontKerning::FontSpecific);
454 : }
455 :
456 3656444 : void Font::SetWeight( FontWeight eWeight )
457 : {
458 :
459 3656444 : if( mpImplFont->meWeight != eWeight )
460 : {
461 2241970 : MakeUnique();
462 2241970 : mpImplFont->meWeight = eWeight;
463 : }
464 3656444 : }
465 :
466 2186615 : void Font::SetWidthType( FontWidth eWidth )
467 : {
468 :
469 2186615 : if( mpImplFont->meWidthType != eWidth )
470 : {
471 2185676 : MakeUnique();
472 2185676 : mpImplFont->meWidthType = eWidth;
473 : }
474 2186615 : }
475 :
476 3439300 : void Font::SetItalic( FontItalic eItalic )
477 : {
478 :
479 3439300 : if( mpImplFont->meItalic != eItalic )
480 : {
481 718070 : MakeUnique();
482 718070 : mpImplFont->meItalic = eItalic;
483 : }
484 3439300 : }
485 :
486 1169023 : void Font::SetOutline( bool bOutline )
487 : {
488 :
489 1169023 : if( mpImplFont->mbOutline != bOutline )
490 : {
491 18154 : MakeUnique();
492 18154 : mpImplFont->mbOutline = bOutline;
493 : }
494 1169023 : }
495 :
496 1128857 : void Font::SetShadow( bool bShadow )
497 : {
498 :
499 1128857 : if( mpImplFont->mbShadow != bShadow )
500 : {
501 16737 : MakeUnique();
502 16737 : mpImplFont->mbShadow = bShadow;
503 : }
504 1128857 : }
505 :
506 1204602 : void Font::SetUnderline( FontUnderline eUnderline )
507 : {
508 :
509 1204602 : if( mpImplFont->meUnderline != eUnderline )
510 : {
511 70307 : MakeUnique();
512 70307 : mpImplFont->meUnderline = eUnderline;
513 : }
514 1204602 : }
515 :
516 1145940 : void Font::SetOverline( FontUnderline eOverline )
517 : {
518 :
519 1145940 : if( mpImplFont->meOverline != eOverline )
520 : {
521 19969 : MakeUnique();
522 19969 : mpImplFont->meOverline = eOverline;
523 : }
524 1145940 : }
525 :
526 1146494 : void Font::SetStrikeout( FontStrikeout eStrikeout )
527 : {
528 :
529 1146494 : if( mpImplFont->meStrikeout != eStrikeout )
530 : {
531 27856 : MakeUnique();
532 27856 : mpImplFont->meStrikeout = eStrikeout;
533 : }
534 1146494 : }
535 :
536 957962 : void Font::SetRelief( FontRelief eRelief )
537 : {
538 :
539 957962 : if( mpImplFont->meRelief != eRelief )
540 : {
541 27606 : MakeUnique();
542 27606 : mpImplFont->meRelief = eRelief;
543 : }
544 957962 : }
545 :
546 1127930 : void Font::SetEmphasisMark( FontEmphasisMark eEmphasisMark )
547 : {
548 :
549 1127930 : if( mpImplFont->meEmphasisMark != eEmphasisMark )
550 : {
551 28661 : MakeUnique();
552 28661 : mpImplFont->meEmphasisMark = eEmphasisMark;
553 : }
554 1127930 : }
555 :
556 1115579 : void Font::SetWordLineMode( bool bWordLine )
557 : {
558 :
559 1115579 : if( mpImplFont->mbWordLine != bWordLine )
560 : {
561 17747 : MakeUnique();
562 17747 : mpImplFont->mbWordLine = bWordLine;
563 : }
564 1115579 : }
565 :
566 6258953 : Font& Font::operator=( const vcl::Font& rFont )
567 : {
568 6258953 : bool bRefIncrementable = rFont.mpImplFont->mnRefCount < ::std::numeric_limits<sal_uInt32>::max();
569 : DBG_ASSERT( bRefIncrementable, "Font: RefCount overflow" );
570 :
571 : // Increment RefCount first, so that we can reference ourselves
572 : // RefCount == 0 for static objects
573 6258953 : if ( rFont.mpImplFont->mnRefCount && bRefIncrementable )
574 6247085 : rFont.mpImplFont->mnRefCount++;
575 :
576 : // If it's not static ImplData and if it's the last reference, delete it
577 : // else decrement RefCount
578 6258953 : if ( mpImplFont->mnRefCount )
579 : {
580 5178674 : if ( mpImplFont->mnRefCount == 1 )
581 3687898 : delete mpImplFont;
582 : else
583 1490776 : mpImplFont->mnRefCount--;
584 : }
585 :
586 6258953 : mpImplFont = rFont.mpImplFont;
587 :
588 6258953 : return *this;
589 : }
590 :
591 2095407 : bool Font::operator==( const vcl::Font& rFont ) const
592 : {
593 2095407 : return mpImplFont == rFont.mpImplFont || *mpImplFont == *rFont.mpImplFont;
594 : }
595 :
596 9111 : void Font::Merge( const vcl::Font& rFont )
597 : {
598 9111 : if ( !rFont.GetName().isEmpty() )
599 : {
600 8842 : SetName( rFont.GetName() );
601 8842 : SetStyleName( rFont.GetStyleName() );
602 8842 : SetCharSet( GetCharSet() );
603 8842 : SetLanguageTag( rFont.GetLanguageTag() );
604 8842 : SetCJKContextLanguageTag( rFont.GetCJKContextLanguageTag() );
605 : // don't use access methods here, might lead to AskConfig(), if DONTKNOW
606 8842 : SetFamily( rFont.mpImplFont->meFamily );
607 8842 : SetPitch( rFont.mpImplFont->mePitch );
608 : }
609 :
610 : // don't use access methods here, might lead to AskConfig(), if DONTKNOW
611 9111 : if ( rFont.mpImplFont->meWeight != WEIGHT_DONTKNOW )
612 9086 : SetWeight( rFont.GetWeight() );
613 9111 : if ( rFont.mpImplFont->meItalic != ITALIC_DONTKNOW )
614 8275 : SetItalic( rFont.GetItalic() );
615 9111 : if ( rFont.mpImplFont->meWidthType != WIDTH_DONTKNOW )
616 2286 : SetWidthType( rFont.GetWidthType() );
617 :
618 9111 : if ( rFont.GetSize().Height() )
619 8846 : SetSize( rFont.GetSize() );
620 9111 : if ( rFont.GetUnderline() != UNDERLINE_DONTKNOW )
621 : {
622 9111 : SetUnderline( rFont.GetUnderline() );
623 9111 : SetWordLineMode( rFont.IsWordLineMode() );
624 : }
625 9111 : if ( rFont.GetOverline() != UNDERLINE_DONTKNOW )
626 : {
627 9111 : SetOverline( rFont.GetOverline() );
628 9111 : SetWordLineMode( rFont.IsWordLineMode() );
629 : }
630 9111 : if ( rFont.GetStrikeout() != STRIKEOUT_DONTKNOW )
631 : {
632 9111 : SetStrikeout( rFont.GetStrikeout() );
633 9111 : SetWordLineMode( rFont.IsWordLineMode() );
634 : }
635 :
636 : // Defaults?
637 9111 : SetOrientation( rFont.GetOrientation() );
638 9111 : SetVertical( rFont.IsVertical() );
639 9111 : SetEmphasisMark( rFont.GetEmphasisMark() );
640 9111 : SetKerning( rFont.IsKerning() ? FontKerning::FontSpecific : FontKerning::NONE );
641 9111 : SetOutline( rFont.IsOutline() );
642 9111 : SetShadow( rFont.IsShadow() );
643 9111 : SetRelief( rFont.GetRelief() );
644 9111 : }
645 :
646 951167 : void Font::GetFontAttributes( ImplFontAttributes& rAttrs ) const
647 : {
648 951167 : rAttrs.SetFamilyName( mpImplFont->maFamilyName );
649 951167 : rAttrs.SetStyleName( mpImplFont->maStyleName );
650 951167 : rAttrs.SetFamilyType( mpImplFont->meFamily );
651 951167 : rAttrs.SetPitch( mpImplFont->mePitch );
652 951167 : rAttrs.SetItalic( mpImplFont->meItalic );
653 951167 : rAttrs.SetWeight( mpImplFont->meWeight );
654 951167 : rAttrs.SetWidthType( WIDTH_DONTKNOW );
655 951167 : rAttrs.SetSymbolFlag( mpImplFont->meCharSet == RTL_TEXTENCODING_SYMBOL );
656 951167 : }
657 :
658 37877 : SvStream& ReadImpl_Font( SvStream& rIStm, Impl_Font& rImpl_Font )
659 : {
660 37877 : VersionCompat aCompat( rIStm, StreamMode::READ );
661 : sal_uInt16 nTmp16;
662 : bool bTmp;
663 : sal_uInt8 nTmp8;
664 :
665 37877 : rImpl_Font.maFamilyName = rIStm.ReadUniOrByteString(rIStm.GetStreamCharSet());
666 37877 : rImpl_Font.maStyleName = rIStm.ReadUniOrByteString(rIStm.GetStreamCharSet());
667 37877 : ReadPair( rIStm, rImpl_Font.maSize );
668 :
669 37877 : rIStm.ReadUInt16( nTmp16 ); rImpl_Font.meCharSet = (rtl_TextEncoding) nTmp16;
670 37877 : rIStm.ReadUInt16( nTmp16 ); rImpl_Font.meFamily = (FontFamily) nTmp16;
671 37877 : rIStm.ReadUInt16( nTmp16 ); rImpl_Font.mePitch = (FontPitch) nTmp16;
672 37877 : rIStm.ReadUInt16( nTmp16 ); rImpl_Font.meWeight = (FontWeight) nTmp16;
673 37877 : rIStm.ReadUInt16( nTmp16 ); rImpl_Font.meUnderline = (FontUnderline) nTmp16;
674 37877 : rIStm.ReadUInt16( nTmp16 ); rImpl_Font.meStrikeout = (FontStrikeout) nTmp16;
675 37877 : rIStm.ReadUInt16( nTmp16 ); rImpl_Font.meItalic = (FontItalic) nTmp16;
676 37877 : rIStm.ReadUInt16( nTmp16 ); rImpl_Font.maLanguageTag.reset( (LanguageType) nTmp16);
677 37877 : rIStm.ReadUInt16( nTmp16 ); rImpl_Font.meWidthType = (FontWidth) nTmp16;
678 :
679 37877 : rIStm.ReadInt16( rImpl_Font.mnOrientation );
680 :
681 37877 : rIStm.ReadCharAsBool( bTmp ); rImpl_Font.mbWordLine = bTmp;
682 37877 : rIStm.ReadCharAsBool( bTmp ); rImpl_Font.mbOutline = bTmp;
683 37877 : rIStm.ReadCharAsBool( bTmp ); rImpl_Font.mbShadow = bTmp;
684 37877 : rIStm.ReadUChar( nTmp8 ); rImpl_Font.mnKerning = static_cast<FontKerning>(nTmp8);
685 :
686 37877 : if( aCompat.GetVersion() >= 2 )
687 : {
688 37877 : rIStm.ReadUChar( nTmp8 ); rImpl_Font.meRelief = (FontRelief)nTmp8;
689 37877 : rIStm.ReadUInt16( nTmp16 ); rImpl_Font.maCJKLanguageTag.reset( (LanguageType)nTmp16);
690 37877 : rIStm.ReadCharAsBool( bTmp ); rImpl_Font.mbVertical = bTmp;
691 37877 : rIStm.ReadUInt16( nTmp16 ); rImpl_Font.meEmphasisMark = (FontEmphasisMark)nTmp16;
692 : }
693 37877 : if( aCompat.GetVersion() >= 3 )
694 : {
695 37877 : rIStm.ReadUInt16( nTmp16 ); rImpl_Font.meOverline = (FontUnderline) nTmp16;
696 : }
697 : // Relief
698 : // CJKContextLanguage
699 :
700 37877 : return rIStm;
701 : }
702 :
703 42730 : SvStream& WriteImpl_Font( SvStream& rOStm, const Impl_Font& rImpl_Font )
704 : {
705 42730 : VersionCompat aCompat( rOStm, StreamMode::WRITE, 3 );
706 42730 : rOStm.WriteUniOrByteString( rImpl_Font.maFamilyName, rOStm.GetStreamCharSet() );
707 42730 : rOStm.WriteUniOrByteString( rImpl_Font.maStyleName, rOStm.GetStreamCharSet() );
708 42730 : WritePair( rOStm, rImpl_Font.maSize );
709 :
710 42730 : rOStm.WriteUInt16( GetStoreCharSet( rImpl_Font.meCharSet ) );
711 42730 : rOStm.WriteUInt16( rImpl_Font.meFamily );
712 42730 : rOStm.WriteUInt16( rImpl_Font.mePitch );
713 42730 : rOStm.WriteUInt16( rImpl_Font.meWeight );
714 42730 : rOStm.WriteUInt16( rImpl_Font.meUnderline );
715 42730 : rOStm.WriteUInt16( rImpl_Font.meStrikeout );
716 42730 : rOStm.WriteUInt16( rImpl_Font.meItalic );
717 42730 : rOStm.WriteUInt16( rImpl_Font.maLanguageTag.getLanguageType( false) );
718 42730 : rOStm.WriteUInt16( rImpl_Font.meWidthType );
719 :
720 42730 : rOStm.WriteInt16( rImpl_Font.mnOrientation );
721 :
722 42730 : rOStm.WriteBool( rImpl_Font.mbWordLine );
723 42730 : rOStm.WriteBool( rImpl_Font.mbOutline );
724 42730 : rOStm.WriteBool( rImpl_Font.mbShadow );
725 42730 : rOStm.WriteUChar( static_cast<sal_uInt8>(rImpl_Font.mnKerning) );
726 :
727 : // new in version 2
728 42730 : rOStm.WriteUChar( rImpl_Font.meRelief );
729 42730 : rOStm.WriteUInt16( rImpl_Font.maCJKLanguageTag.getLanguageType( false) );
730 42730 : rOStm.WriteBool( rImpl_Font.mbVertical );
731 42730 : rOStm.WriteUInt16( rImpl_Font.meEmphasisMark );
732 :
733 : // new in version 3
734 42730 : rOStm.WriteUInt16( rImpl_Font.meOverline );
735 :
736 42730 : return rOStm;
737 : }
738 :
739 37877 : SvStream& ReadFont( SvStream& rIStm, vcl::Font& rFont )
740 : {
741 37877 : rFont.MakeUnique();
742 37877 : return ReadImpl_Font( rIStm, *rFont.mpImplFont );
743 : }
744 :
745 42730 : SvStream& WriteFont( SvStream& rOStm, const vcl::Font& rFont )
746 : {
747 42730 : return WriteImpl_Font( rOStm, *rFont.mpImplFont );
748 : }
749 :
750 : namespace
751 : {
752 0 : bool identifyTrueTypeFont( const void* i_pBuffer, sal_uInt32 i_nSize, Font& o_rResult )
753 : {
754 0 : bool bResult = false;
755 0 : TrueTypeFont* pTTF = NULL;
756 0 : if( OpenTTFontBuffer( i_pBuffer, i_nSize, 0, &pTTF ) == SF_OK )
757 : {
758 : TTGlobalFontInfo aInfo;
759 0 : GetTTGlobalFontInfo( pTTF, &aInfo );
760 : // most importantly: the family name
761 0 : if( aInfo.ufamily )
762 0 : o_rResult.SetName( aInfo.ufamily );
763 0 : else if( aInfo.family )
764 0 : o_rResult.SetName( OStringToOUString( aInfo.family, RTL_TEXTENCODING_ASCII_US ) );
765 : // set weight
766 0 : if( aInfo.weight )
767 : {
768 0 : if( aInfo.weight < FW_EXTRALIGHT )
769 0 : o_rResult.SetWeight( WEIGHT_THIN );
770 0 : else if( aInfo.weight < FW_LIGHT )
771 0 : o_rResult.SetWeight( WEIGHT_ULTRALIGHT );
772 0 : else if( aInfo.weight < FW_NORMAL )
773 0 : o_rResult.SetWeight( WEIGHT_LIGHT );
774 0 : else if( aInfo.weight < FW_MEDIUM )
775 0 : o_rResult.SetWeight( WEIGHT_NORMAL );
776 0 : else if( aInfo.weight < FW_SEMIBOLD )
777 0 : o_rResult.SetWeight( WEIGHT_MEDIUM );
778 0 : else if( aInfo.weight < FW_BOLD )
779 0 : o_rResult.SetWeight( WEIGHT_SEMIBOLD );
780 0 : else if( aInfo.weight < FW_EXTRABOLD )
781 0 : o_rResult.SetWeight( WEIGHT_BOLD );
782 0 : else if( aInfo.weight < FW_BLACK )
783 0 : o_rResult.SetWeight( WEIGHT_ULTRABOLD );
784 : else
785 0 : o_rResult.SetWeight( WEIGHT_BLACK );
786 : }
787 : else
788 0 : o_rResult.SetWeight( (aInfo.macStyle & 1) ? WEIGHT_BOLD : WEIGHT_NORMAL );
789 : // set width
790 0 : if( aInfo.width )
791 : {
792 0 : if( aInfo.width == FWIDTH_ULTRA_CONDENSED )
793 0 : o_rResult.SetWidth( WIDTH_ULTRA_CONDENSED );
794 0 : else if( aInfo.width == FWIDTH_EXTRA_CONDENSED )
795 0 : o_rResult.SetWidth( WIDTH_EXTRA_CONDENSED );
796 0 : else if( aInfo.width == FWIDTH_CONDENSED )
797 0 : o_rResult.SetWidth( WIDTH_CONDENSED );
798 0 : else if( aInfo.width == FWIDTH_SEMI_CONDENSED )
799 0 : o_rResult.SetWidth( WIDTH_SEMI_CONDENSED );
800 0 : else if( aInfo.width == FWIDTH_NORMAL )
801 0 : o_rResult.SetWidth( WIDTH_NORMAL );
802 0 : else if( aInfo.width == FWIDTH_SEMI_EXPANDED )
803 0 : o_rResult.SetWidth( WIDTH_SEMI_EXPANDED );
804 0 : else if( aInfo.width == FWIDTH_EXPANDED )
805 0 : o_rResult.SetWidth( WIDTH_EXPANDED );
806 0 : else if( aInfo.width == FWIDTH_EXTRA_EXPANDED )
807 0 : o_rResult.SetWidth( WIDTH_EXTRA_EXPANDED );
808 0 : else if( aInfo.width >= FWIDTH_ULTRA_EXPANDED )
809 0 : o_rResult.SetWidth( WIDTH_ULTRA_EXPANDED );
810 : }
811 : // set italic
812 0 : o_rResult.SetItalic( (aInfo.italicAngle != 0) ? ITALIC_NORMAL : ITALIC_NONE );
813 :
814 : // set pitch
815 0 : o_rResult.SetPitch( (aInfo.pitch == 0) ? PITCH_VARIABLE : PITCH_FIXED );
816 :
817 : // set style name
818 0 : if( aInfo.usubfamily )
819 0 : o_rResult.SetStyleName( OUString( aInfo.usubfamily ) );
820 0 : else if( aInfo.subfamily )
821 0 : o_rResult.SetStyleName( OUString::createFromAscii( aInfo.subfamily ) );
822 :
823 : // cleanup
824 0 : CloseTTFont( pTTF );
825 : // success
826 0 : bResult = true;
827 : }
828 0 : return bResult;
829 : }
830 :
831 : struct WeightSearchEntry
832 : {
833 : const char* string;
834 : int string_len;
835 : FontWeight weight;
836 :
837 0 : bool operator<( const WeightSearchEntry& rRight ) const
838 : {
839 0 : return rtl_str_compareIgnoreAsciiCase_WithLength( string, string_len, rRight.string, rRight.string_len ) < 0;
840 : }
841 : }
842 : weight_table[] =
843 : {
844 : { "black", 5, WEIGHT_BLACK },
845 : { "bold", 4, WEIGHT_BOLD },
846 : { "book", 4, WEIGHT_LIGHT },
847 : { "demi", 4, WEIGHT_SEMIBOLD },
848 : { "heavy", 5, WEIGHT_BLACK },
849 : { "light", 5, WEIGHT_LIGHT },
850 : { "medium", 6, WEIGHT_MEDIUM },
851 : { "regular", 7, WEIGHT_NORMAL },
852 : { "super", 5, WEIGHT_ULTRABOLD },
853 : { "thin", 4, WEIGHT_THIN }
854 : };
855 :
856 0 : bool identifyType1Font( const char* i_pBuffer, sal_uInt32 i_nSize, Font& o_rResult )
857 : {
858 0 : bool bResult = false;
859 : // might be a type1, find eexec
860 0 : const char* pStream = i_pBuffer;
861 0 : const char* pExec = "eexec";
862 0 : const char* pExecPos = std::search( pStream, pStream+i_nSize, pExec, pExec+5 );
863 0 : if( pExecPos != pStream+i_nSize)
864 : {
865 : // find /FamilyName entry
866 : static const char* pFam = "/FamilyName";
867 0 : const char* pFamPos = std::search( pStream, pExecPos, pFam, pFam+11 );
868 0 : if( pFamPos != pExecPos )
869 : {
870 : // extract the string value behind /FamilyName
871 0 : const char* pOpen = pFamPos+11;
872 0 : while( pOpen < pExecPos && *pOpen != '(' )
873 0 : pOpen++;
874 0 : const char* pClose = pOpen;
875 0 : while( pClose < pExecPos && *pClose != ')' )
876 0 : pClose++;
877 0 : if( pClose - pOpen > 1 )
878 : {
879 0 : o_rResult.SetName( OStringToOUString( OString( pOpen+1, pClose-pOpen-1 ), RTL_TEXTENCODING_ASCII_US ) );
880 : }
881 : }
882 :
883 : // parse /ItalicAngle
884 : static const char* pItalic = "/ItalicAngle";
885 0 : const char* pItalicPos = std::search( pStream, pExecPos, pItalic, pItalic+12 );
886 0 : if( pItalicPos != pExecPos )
887 : {
888 0 : sal_Int32 nItalic = rtl_str_toInt32( pItalicPos+12, 10 );
889 0 : o_rResult.SetItalic( (nItalic != 0) ? ITALIC_NORMAL : ITALIC_NONE );
890 : }
891 :
892 : // parse /Weight
893 : static const char* pWeight = "/Weight";
894 0 : const char* pWeightPos = std::search( pStream, pExecPos, pWeight, pWeight+7 );
895 0 : if( pWeightPos != pExecPos )
896 : {
897 : // extract the string value behind /Weight
898 0 : const char* pOpen = pWeightPos+7;
899 0 : while( pOpen < pExecPos && *pOpen != '(' )
900 0 : pOpen++;
901 0 : const char* pClose = pOpen;
902 0 : while( pClose < pExecPos && *pClose != ')' )
903 0 : pClose++;
904 0 : if( pClose - pOpen > 1 )
905 : {
906 : WeightSearchEntry aEnt;
907 0 : aEnt.string = pOpen+1;
908 0 : aEnt.string_len = (pClose-pOpen)-1;
909 0 : aEnt.weight = WEIGHT_NORMAL;
910 0 : const int nEnt = SAL_N_ELEMENTS( weight_table );
911 0 : WeightSearchEntry* pFound = std::lower_bound( weight_table, weight_table+nEnt, aEnt );
912 0 : if( pFound != (weight_table+nEnt) )
913 0 : o_rResult.SetWeight( pFound->weight );
914 : }
915 : }
916 :
917 : // parse isFixedPitch
918 : static const char* pFixed = "/isFixedPitch";
919 0 : const char* pFixedPos = std::search( pStream, pExecPos, pFixed, pFixed+13 );
920 0 : if( pFixedPos != pExecPos )
921 : {
922 : // skip whitespace
923 0 : while( pFixedPos < pExecPos-4 &&
924 0 : ( *pFixedPos == ' ' ||
925 0 : *pFixedPos == '\t' ||
926 0 : *pFixedPos == '\r' ||
927 0 : *pFixedPos == '\n' ) )
928 : {
929 0 : pFixedPos++;
930 : }
931 : // find "true" value
932 0 : if( rtl_str_compareIgnoreAsciiCase_WithLength( pFixedPos, 4, "true", 4 ) == 0 )
933 0 : o_rResult.SetPitch( PITCH_FIXED );
934 : else
935 0 : o_rResult.SetPitch( PITCH_VARIABLE );
936 : }
937 : }
938 0 : return bResult;
939 : }
940 : }
941 :
942 0 : Font Font::identifyFont( const void* i_pBuffer, sal_uInt32 i_nSize )
943 : {
944 0 : Font aResult;
945 0 : if( ! identifyTrueTypeFont( i_pBuffer, i_nSize, aResult ) )
946 : {
947 0 : const char* pStream = static_cast<const char*>(i_pBuffer);
948 0 : if( pStream && i_nSize > 100 &&
949 0 : *pStream == '%' && pStream[1] == '!' )
950 : {
951 0 : identifyType1Font( pStream, i_nSize, aResult );
952 : }
953 : }
954 :
955 0 : return aResult;
956 : }
957 :
958 : // The inlines from the font.hxx header are now instantiated for pImpl-ification
959 3147558 : const Color& Font::GetColor() const { return mpImplFont->maColor; }
960 :
961 111971 : const Color& Font::GetFillColor() const { return mpImplFont->maFillColor; }
962 :
963 785737 : bool Font::IsTransparent() const { return mpImplFont->mbTransparent; }
964 :
965 1640370 : FontAlign Font::GetAlign() const { return mpImplFont->meAlign; }
966 :
967 4107662 : const OUString& Font::GetName() const { return mpImplFont->maFamilyName; }
968 :
969 114779 : const OUString& Font::GetStyleName() const { return mpImplFont->maStyleName; }
970 :
971 3640338 : const Size& Font::GetSize() const { return mpImplFont->maSize; }
972 :
973 185344 : void Font::SetHeight( long nHeight ) { SetSize( Size( mpImplFont->maSize.Width(), nHeight ) ); }
974 :
975 938194 : long Font::GetHeight() const { return mpImplFont->maSize.Height(); }
976 :
977 0 : void Font::SetWidth( long nWidth ) { SetSize( Size( nWidth, mpImplFont->maSize.Height() ) ); }
978 :
979 0 : long Font::GetWidth() const { return mpImplFont->maSize.Width(); }
980 :
981 482786 : rtl_TextEncoding Font::GetCharSet() const { return mpImplFont->meCharSet; }
982 :
983 1593710 : const LanguageTag& Font::GetLanguageTag() const { return mpImplFont->maLanguageTag; }
984 :
985 8842 : const LanguageTag& Font::GetCJKContextLanguageTag() const { return mpImplFont->maCJKLanguageTag; }
986 :
987 3214085 : LanguageType Font::GetLanguage() const { return mpImplFont->maLanguageTag.getLanguageType( false); }
988 :
989 6497 : LanguageType Font::GetCJKContextLanguage() const { return mpImplFont->maCJKLanguageTag.getLanguageType( false); }
990 :
991 1565568 : short Font::GetOrientation() const { return mpImplFont->mnOrientation; }
992 :
993 2585130 : bool Font::IsVertical() const { return mpImplFont->mbVertical; }
994 :
995 4190202 : FontKerning Font::GetKerning() const { return mpImplFont->mnKerning; }
996 :
997 80205 : FontPitch Font::GetPitch() const { return mpImplFont->GetPitch(); }
998 :
999 1501876 : FontWeight Font::GetWeight() const { return mpImplFont->GetWeight(); }
1000 :
1001 2304 : FontWidth Font::GetWidthType() const { return mpImplFont->GetWidthType(); }
1002 :
1003 7321516 : FontItalic Font::GetItalic() const { return mpImplFont->GetItalic(); }
1004 :
1005 57284 : FontFamily Font::GetFamily() const { return mpImplFont->GetFamily(); }
1006 :
1007 908999 : bool Font::IsOutline() const { return mpImplFont->mbOutline; }
1008 :
1009 928799 : bool Font::IsShadow() const { return mpImplFont->mbShadow; }
1010 :
1011 960647 : FontRelief Font::GetRelief() const { return mpImplFont->meRelief; }
1012 :
1013 2783455 : FontUnderline Font::GetUnderline() const { return mpImplFont->meUnderline; }
1014 :
1015 1437596 : FontUnderline Font::GetOverline() const { return mpImplFont->meOverline; }
1016 :
1017 1432661 : FontStrikeout Font::GetStrikeout() const { return mpImplFont->meStrikeout; }
1018 :
1019 1230447 : FontEmphasisMark Font::GetEmphasisMark() const { return mpImplFont->meEmphasisMark; }
1020 :
1021 969053 : bool Font::IsWordLineMode() const { return mpImplFont->mbWordLine; }
1022 :
1023 2969719 : bool Font::IsSameInstance( const vcl::Font& rFont ) const { return (mpImplFont == rFont.mpImplFont); }
1024 :
1025 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|