xref: /aoo42x/main/vcl/source/gdi/font.cxx (revision cdf0e10c)
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