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