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