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