xref: /AOO41X/main/vcl/source/gdi/font.cxx (revision 9f62ea84a806e17e6f2bbff75724a7257a0eb5d9)
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 <__anonbfef55cd0111::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