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