1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/stream.hxx>
21 #include <tools/vcompat.hxx>
22 #include <tools/gen.hxx>
23 #include <comphelper/configuration.hxx>
24 #include <unotools/fontcfg.hxx>
25 #include <unotools/fontdefs.hxx>
26 #include <o3tl/hash_combine.hxx>
27 #include <i18nlangtag/mslangid.hxx>
29 #include <vcl/font.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/outdev.hxx>
32 #include <vcl/virdev.hxx>
34 #include <impfont.hxx>
35 #include <fontattributes.hxx>
36 #include <fontsubset.hxx>
40 #include <string_view>
42 #include <vcl/TypeSerializer.hxx>
45 #include <vcl/metric.hxx>
52 Font::ImplType
& GetGlobalDefault()
54 static Font::ImplType gDefault
;
59 Font::Font() : mpImplFont(GetGlobalDefault())
63 Font::Font( const vcl::Font
& rFont
) : mpImplFont( rFont
.mpImplFont
)
67 Font::Font( vcl::Font
&& rFont
) noexcept
: mpImplFont( std::move(rFont
.mpImplFont
) )
71 Font::Font( const OUString
& rFamilyName
, const Size
& rSize
)
73 if (GetFamilyName() != rFamilyName
74 || GetAverageFontSize() != rSize
)
76 auto impl
= mpImplFont
.get();
77 impl
->SetFamilyName( rFamilyName
);
78 impl
->SetFontSize( rSize
);
82 Font::Font( const OUString
& rFamilyName
, const OUString
& rStyleName
, const Size
& rSize
)
84 if (GetFamilyName() != rFamilyName
85 || GetStyleName() != rStyleName
86 || GetAverageFontSize() != rSize
)
88 auto impl
= mpImplFont
.get();
89 impl
->SetFamilyName( rFamilyName
);
90 impl
->SetStyleName( rStyleName
);
91 impl
->SetFontSize( rSize
);
95 Font::Font( FontFamily eFamily
, const Size
& rSize
)
97 if (GetFontFamily() != eFamily
98 || GetAverageFontSize() != rSize
)
100 auto impl
= mpImplFont
.get();
101 impl
->SetFamilyType( eFamily
);
102 impl
->SetFontSize( rSize
);
110 void Font::SetColor( const Color
& rColor
)
112 if (GetColor() != rColor
)
114 mpImplFont
->maColor
= rColor
;
118 void Font::SetFillColor( const Color
& rColor
)
120 if (GetFillColor() != rColor
)
122 auto impl
= mpImplFont
.get();
123 impl
->maFillColor
= rColor
;
124 if ( rColor
.IsTransparent() )
125 impl
->mbTransparent
= true;
129 void Font::SetTransparent( bool bTransparent
)
131 if (IsTransparent() != bTransparent
)
132 mpImplFont
->mbTransparent
= bTransparent
;
135 void Font::SetAlignment( TextAlign eAlign
)
137 if (GetAlignment() != eAlign
)
138 mpImplFont
->SetAlignment(eAlign
);
141 void Font::SetFamilyName( const OUString
& rFamilyName
)
143 if (GetFamilyName() != rFamilyName
)
144 mpImplFont
->SetFamilyName( rFamilyName
);
147 void Font::SetStyleName( const OUString
& rStyleName
)
149 if (GetStyleName() != rStyleName
)
150 mpImplFont
->maStyleName
= rStyleName
;
153 void Font::SetFontSize( const Size
& rSize
)
155 if (GetFontSize() != rSize
)
156 mpImplFont
->SetFontSize( rSize
);
159 void Font::SetFamily( FontFamily eFamily
)
161 if (std::as_const(mpImplFont
)->GetFamilyTypeNoAsk() != eFamily
)
162 mpImplFont
->SetFamilyType( eFamily
);
165 void Font::SetCharSet( rtl_TextEncoding eCharSet
)
167 if (GetCharSet() != eCharSet
)
168 mpImplFont
->SetCharSet( eCharSet
);
171 void Font::SetLanguageTag( const LanguageTag
& rLanguageTag
)
173 if (GetLanguageTag() != rLanguageTag
)
174 mpImplFont
->maLanguageTag
= rLanguageTag
;
177 void Font::SetCJKContextLanguageTag( const LanguageTag
& rLanguageTag
)
179 if (GetCJKContextLanguageTag() != rLanguageTag
)
180 mpImplFont
->maCJKLanguageTag
= rLanguageTag
;
183 void Font::SetLanguage( LanguageType eLanguage
)
185 if (GetLanguage() != eLanguage
)
186 mpImplFont
->maLanguageTag
.reset( eLanguage
);
189 void Font::SetCJKContextLanguage( LanguageType eLanguage
)
191 if (GetCJKContextLanguage() != eLanguage
)
192 mpImplFont
->maCJKLanguageTag
.reset( eLanguage
);
195 void Font::SetPitch( FontPitch ePitch
)
197 if (std::as_const(mpImplFont
)->GetPitchNoAsk() != ePitch
)
198 mpImplFont
->SetPitch( ePitch
);
201 void Font::SetOrientation( Degree10 nOrientation
)
203 if (GetOrientation() != nOrientation
)
204 mpImplFont
->mnOrientation
= nOrientation
;
207 void Font::SetVertical( bool bVertical
)
209 if (IsVertical() != bVertical
)
210 mpImplFont
->mbVertical
= bVertical
;
213 void Font::SetKerning( FontKerning eKerning
)
215 if (GetKerning() != eKerning
)
216 mpImplFont
->meKerning
= eKerning
;
219 bool Font::IsKerning() const
221 return mpImplFont
->meKerning
!= FontKerning::NONE
;
224 void Font::SetFixKerning( short nSpacing
)
226 if (GetFixKerning() != nSpacing
)
227 mpImplFont
->mnSpacing
= nSpacing
;
230 short Font::GetFixKerning() const
232 return mpImplFont
->mnSpacing
;
235 bool Font::IsFixKerning() const
237 return mpImplFont
->mnSpacing
!= 0;
240 void Font::SetWeight( FontWeight eWeight
)
242 if (std::as_const(mpImplFont
)->GetWeightNoAsk() != eWeight
)
243 mpImplFont
->SetWeight( eWeight
);
246 void Font::SetWidthType( FontWidth eWidth
)
248 if (std::as_const(mpImplFont
)->GetWidthTypeNoAsk() != eWidth
)
249 mpImplFont
->SetWidthType( eWidth
);
252 void Font::SetItalic( FontItalic eItalic
)
254 if (std::as_const(mpImplFont
)->GetItalicNoAsk() != eItalic
)
255 mpImplFont
->SetItalic( eItalic
);
258 void Font::SetOutline( bool bOutline
)
260 if (IsOutline() != bOutline
)
261 mpImplFont
->mbOutline
= bOutline
;
264 void Font::SetShadow( bool bShadow
)
266 if (IsShadow() != bShadow
)
267 mpImplFont
->mbShadow
= bShadow
;
270 void Font::SetUnderline( FontLineStyle eUnderline
)
272 if (GetUnderline() != eUnderline
)
273 mpImplFont
->meUnderline
= eUnderline
;
276 void Font::SetOverline( FontLineStyle eOverline
)
278 if (GetOverline() != eOverline
)
279 mpImplFont
->meOverline
= eOverline
;
282 void Font::SetStrikeout( FontStrikeout eStrikeout
)
284 if (GetStrikeout() != eStrikeout
)
285 mpImplFont
->meStrikeout
= eStrikeout
;
288 void Font::SetRelief( FontRelief eRelief
)
290 if (GetRelief() != eRelief
)
291 mpImplFont
->meRelief
= eRelief
;
294 void Font::SetEmphasisMark( FontEmphasisMark eEmphasisMark
)
296 if (GetEmphasisMark() != eEmphasisMark
)
297 mpImplFont
->meEmphasisMark
= eEmphasisMark
;
300 void Font::SetWordLineMode( bool bWordLine
)
302 if (IsWordLineMode() != bWordLine
)
303 mpImplFont
->mbWordLine
= bWordLine
;
306 Font
& Font::operator=( const vcl::Font
& rFont
)
308 mpImplFont
= rFont
.mpImplFont
;
312 Font
& Font::operator=( vcl::Font
&& rFont
) noexcept
314 mpImplFont
= std::move(rFont
.mpImplFont
);
318 FontEmphasisMark
Font::GetEmphasisMarkStyle() const
320 FontEmphasisMark nEmphasisMark
= GetEmphasisMark();
322 // If no Position is set, then calculate the default position, which
323 // depends on the language
324 if (!(nEmphasisMark
& (FontEmphasisMark::PosAbove
| FontEmphasisMark::PosBelow
)))
326 LanguageType eLang
= GetLanguage();
327 // In Chinese Simplified the EmphasisMarks are below/left
328 if (MsLangId::isSimplifiedChinese(eLang
))
330 nEmphasisMark
|= FontEmphasisMark::PosBelow
;
334 eLang
= GetCJKContextLanguage();
336 // In Chinese Simplified the EmphasisMarks are below/left
337 if (MsLangId::isSimplifiedChinese(eLang
))
338 nEmphasisMark
|= FontEmphasisMark::PosBelow
;
340 nEmphasisMark
|= FontEmphasisMark::PosAbove
;
344 return nEmphasisMark
;
347 bool Font::operator==( const vcl::Font
& rFont
) const
349 return mpImplFont
== rFont
.mpImplFont
;
352 bool Font::EqualIgnoreColor( const vcl::Font
& rFont
) const
354 return mpImplFont
->EqualIgnoreColor( *rFont
.mpImplFont
);
357 size_t Font::GetHashValueIgnoreColor() const
359 return mpImplFont
->GetHashValueIgnoreColor();
362 void Font::Merge( const vcl::Font
& rFont
)
364 if ( !rFont
.GetFamilyName().isEmpty() )
366 SetFamilyName( rFont
.GetFamilyName() );
367 SetStyleName( rFont
.GetStyleName() );
368 SetCharSet( rFont
.GetCharSet() );
369 SetLanguageTag( rFont
.GetLanguageTag() );
370 SetCJKContextLanguageTag( rFont
.GetCJKContextLanguageTag() );
371 // don't use access methods here, might lead to AskConfig(), if DONTKNOW
372 SetFamily( rFont
.GetFamilyType() );
373 SetPitch( rFont
.GetPitch() );
376 if ( rFont
.GetWeight() != WEIGHT_DONTKNOW
)
377 SetWeight( rFont
.GetWeight() );
378 if ( rFont
.GetItalic() != ITALIC_DONTKNOW
)
379 SetItalic( rFont
.GetItalic() );
380 if ( rFont
.GetWidthType() != WIDTH_DONTKNOW
)
381 SetWidthType( rFont
.GetWidthType() );
383 if ( rFont
.GetFontSize().Height() )
384 SetFontSize( rFont
.GetFontSize() );
385 if ( rFont
.GetUnderline() != LINESTYLE_DONTKNOW
)
387 SetUnderline( rFont
.GetUnderline() );
388 SetWordLineMode( rFont
.IsWordLineMode() );
390 if ( rFont
.GetOverline() != LINESTYLE_DONTKNOW
)
392 SetOverline( rFont
.GetOverline() );
393 SetWordLineMode( rFont
.IsWordLineMode() );
395 if ( rFont
.GetStrikeout() != STRIKEOUT_DONTKNOW
)
397 SetStrikeout( rFont
.GetStrikeout() );
398 SetWordLineMode( rFont
.IsWordLineMode() );
402 SetOrientation( rFont
.GetOrientation() );
403 SetVertical( rFont
.IsVertical() );
404 SetEmphasisMark( rFont
.GetEmphasisMark() );
405 SetKerning( rFont
.IsKerning() ? FontKerning::FontSpecific
: FontKerning::NONE
);
406 SetOutline( rFont
.IsOutline() );
407 SetShadow( rFont
.IsShadow() );
408 SetRelief( rFont
.GetRelief() );
411 void Font::GetFontAttributes( FontAttributes
& rAttrs
) const
413 rAttrs
.SetFamilyName( GetFamilyName() );
414 rAttrs
.SetStyleName( GetStyleName() );
415 rAttrs
.SetFamilyType( GetFamilyType() );
416 rAttrs
.SetPitch( GetPitch() );
417 rAttrs
.SetItalic( GetItalic() );
418 rAttrs
.SetWeight( GetWeight() );
419 rAttrs
.SetWidthType( WIDTH_DONTKNOW
);
420 rAttrs
.SetMicrosoftSymbolEncoded( GetCharSet() == RTL_TEXTENCODING_SYMBOL
);
423 // tdf#127471 for corrections on EMF/WMF we need the AvgFontWidth in Windows-specific notation
424 tools::Long
Font::GetOrCalculateAverageFontWidth() const
426 if(0 == mpImplFont
->GetCalculatedAverageFontWidth())
428 // VirtualDevice is not thread safe
429 SolarMutexGuard aGuard
;
431 // create unscaled copy of font (this), a VirtualDevice and set it there
432 vcl::Font
aUnscaledFont(*this);
433 ScopedVclPtr
<VirtualDevice
> pTempVirtualDevice(VclPtr
<VirtualDevice
>::Create());
434 aUnscaledFont
.SetAverageFontWidth(0);
435 pTempVirtualDevice
->SetFont(aUnscaledFont
);
438 // on Windows systems use FontMetric to get/create AverageFontWidth from system
439 const FontMetric
aMetric(pTempVirtualDevice
->GetFontMetric());
440 const_cast<Font
*>(this)->mpImplFont
->SetCalculatedAverageFontWidth(aMetric
.GetAverageFontWidth());
442 // On non-Windows systems we need to calculate AvgFontWidth
443 // as close as possible (discussion see documentation in task),
444 // so calculate it. For discussion of method used, see task
445 // buffer measure string creation, will always use the same
446 static constexpr OUString aMeasureString
447 = u
"\u0020\u0021\u0022\u0023\u0024\u0025\u0026\u0027"
448 "\u0028\u0029\u002A\u002B\u002C\u002D\u002E\u002F"
449 "\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037"
450 "\u0038\u0039\u003A\u003B\u003C\u003D\u003E\u003F"
451 "\u0040\u0041\u0042\u0043\u0044\u0045\u0046\u0047"
452 "\u0048\u0049\u004A\u004B\u004C\u004D\u004E\u004F"
453 "\u0050\u0051\u0052\u0053\u0054\u0055\u0056\u0057"
454 "\u0058\u0059\u005A\u005B\u005C\u005D\u005E\u005F"
455 "\u0060\u0061\u0062\u0063\u0064\u0065\u0066\u0067"
456 "\u0068\u0069\u006A\u006B\u006C\u006D\u006E\u006F"
457 "\u0070\u0071\u0072\u0073\u0074\u0075\u0076\u0077"
458 "\u0078\u0079\u007A\u007B\u007C\u007D\u007E"_ustr
;
460 const double fAverageFontWidth(
461 pTempVirtualDevice
->GetTextWidth(aMeasureString
) /
462 static_cast<double>(aMeasureString
.getLength()));
463 const_cast<Font
*>(this)->mpImplFont
->SetCalculatedAverageFontWidth(basegfx::fround(fAverageFontWidth
));
467 return mpImplFont
->GetCalculatedAverageFontWidth();
470 SvStream
& ReadImplFont( SvStream
& rIStm
, ImplFont
& rImplFont
, tools::Long
& rnNormedFontScaling
)
472 VersionCompatRead
aCompat( rIStm
);
473 sal_uInt16
nTmp16(0);
474 sal_Int16
nTmps16(0);
478 rImplFont
.SetFamilyName( rIStm
.ReadUniOrByteString(rIStm
.GetStreamCharSet()) );
479 rImplFont
.maStyleName
= rIStm
.ReadUniOrByteString(rIStm
.GetStreamCharSet());
480 TypeSerializer
aSerializer(rIStm
);
481 aSerializer
.readSize(rImplFont
.maAverageFontSize
);
483 static const bool bFuzzing
= comphelper::IsFuzzing();
486 if (rImplFont
.maAverageFontSize
.Width() > 8192)
488 SAL_WARN("vcl.gdi", "suspicious average width of: " << rImplFont
.maAverageFontSize
.Width());
489 rImplFont
.maAverageFontSize
.setWidth(8192);
491 if (rImplFont
.maAverageFontSize
.Height() > 8192)
493 SAL_WARN("vcl.gdi", "suspicious average height of: " << rImplFont
.maAverageFontSize
.Height());
494 rImplFont
.maAverageFontSize
.setHeight(8192);
498 rIStm
.ReadUInt16( nTmp16
); rImplFont
.SetCharSet( static_cast<rtl_TextEncoding
>(nTmp16
) );
499 rIStm
.ReadUInt16( nTmp16
); rImplFont
.SetFamilyType( static_cast<FontFamily
>(nTmp16
) );
500 rIStm
.ReadUInt16( nTmp16
); rImplFont
.SetPitch( static_cast<FontPitch
>(nTmp16
) );
501 rIStm
.ReadUInt16( nTmp16
); rImplFont
.SetWeight( static_cast<FontWeight
>(nTmp16
) );
502 rIStm
.ReadUInt16( nTmp16
); rImplFont
.meUnderline
= static_cast<FontLineStyle
>(nTmp16
);
503 rIStm
.ReadUInt16( nTmp16
); rImplFont
.meStrikeout
= static_cast<FontStrikeout
>(nTmp16
);
504 rIStm
.ReadUInt16( nTmp16
); rImplFont
.SetItalic( static_cast<FontItalic
>(nTmp16
) );
505 rIStm
.ReadUInt16( nTmp16
); rImplFont
.maLanguageTag
.reset( LanguageType(nTmp16
) );
506 rIStm
.ReadUInt16( nTmp16
); rImplFont
.meWidthType
= static_cast<FontWidth
>(nTmp16
);
508 rIStm
.ReadInt16( nTmps16
); rImplFont
.mnOrientation
= Degree10(nTmps16
);
510 rIStm
.ReadCharAsBool( bTmp
); rImplFont
.mbWordLine
= bTmp
;
511 rIStm
.ReadCharAsBool( bTmp
); rImplFont
.mbOutline
= bTmp
;
512 rIStm
.ReadCharAsBool( bTmp
); rImplFont
.mbShadow
= bTmp
;
513 rIStm
.ReadUChar( nTmp8
); rImplFont
.meKerning
= static_cast<FontKerning
>(nTmp8
);
515 if( aCompat
.GetVersion() >= 2 )
517 rIStm
.ReadUChar( nTmp8
); rImplFont
.meRelief
= static_cast<FontRelief
>(nTmp8
);
518 rIStm
.ReadUInt16( nTmp16
); rImplFont
.maCJKLanguageTag
.reset( LanguageType(nTmp16
) );
519 rIStm
.ReadCharAsBool( bTmp
); rImplFont
.mbVertical
= bTmp
;
520 rIStm
.ReadUInt16( nTmp16
);
521 rImplFont
.meEmphasisMark
= static_cast<FontEmphasisMark
>(nTmp16
& o3tl::typed_flags
<FontEmphasisMark
>::mask
);
524 if( aCompat
.GetVersion() >= 3 )
526 rIStm
.ReadUInt16( nTmp16
); rImplFont
.meOverline
= static_cast<FontLineStyle
>(nTmp16
);
529 // tdf#127471 read NormedFontScaling
530 if( aCompat
.GetVersion() >= 4 )
532 sal_Int32
nNormedFontScaling(0);
533 rIStm
.ReadInt32(nNormedFontScaling
);
534 rnNormedFontScaling
= nNormedFontScaling
;
537 if( aCompat
.GetVersion() >= 5 )
539 rIStm
.ReadInt16( nTmps16
);
540 rImplFont
.mnSpacing
= nTmps16
;
544 // CJKContextLanguage
549 SvStream
& WriteImplFont( SvStream
& rOStm
, const ImplFont
& rImplFont
, tools::Long nNormedFontScaling
)
551 // tdf#127471 increase to version 4
552 // tdf#66819 increase to version 5
553 VersionCompatWrite
aCompat( rOStm
, 5 );
555 TypeSerializer
aSerializer(rOStm
);
556 rOStm
.WriteUniOrByteString( rImplFont
.GetFamilyName(), rOStm
.GetStreamCharSet() );
557 rOStm
.WriteUniOrByteString( rImplFont
.GetStyleName(), rOStm
.GetStreamCharSet() );
558 aSerializer
.writeSize(rImplFont
.maAverageFontSize
);
560 rOStm
.WriteUInt16( GetStoreCharSet( rImplFont
.GetCharSet() ) );
561 rOStm
.WriteUInt16( rImplFont
.GetFamilyTypeNoAsk() );
562 rOStm
.WriteUInt16( rImplFont
.GetPitchNoAsk() );
563 rOStm
.WriteUInt16( rImplFont
.GetWeightNoAsk() );
564 rOStm
.WriteUInt16( rImplFont
.meUnderline
);
565 rOStm
.WriteUInt16( rImplFont
.meStrikeout
);
566 rOStm
.WriteUInt16( rImplFont
.GetItalicNoAsk() );
567 rOStm
.WriteUInt16( static_cast<sal_uInt16
>(rImplFont
.maLanguageTag
.getLanguageType( false)) );
568 rOStm
.WriteUInt16( rImplFont
.GetWidthTypeNoAsk() );
570 rOStm
.WriteInt16( rImplFont
.mnOrientation
.get() );
572 rOStm
.WriteBool( rImplFont
.mbWordLine
);
573 rOStm
.WriteBool( rImplFont
.mbOutline
);
574 rOStm
.WriteBool( rImplFont
.mbShadow
);
575 rOStm
.WriteUChar( static_cast<sal_uInt8
>(rImplFont
.meKerning
) );
578 rOStm
.WriteUChar( static_cast<unsigned char>(rImplFont
.meRelief
) );
579 rOStm
.WriteUInt16( static_cast<sal_uInt16
>(rImplFont
.maCJKLanguageTag
.getLanguageType( false)) );
580 rOStm
.WriteBool( rImplFont
.mbVertical
);
581 rOStm
.WriteUInt16( static_cast<sal_uInt16
>(rImplFont
.meEmphasisMark
) );
584 rOStm
.WriteUInt16( rImplFont
.meOverline
);
586 // new in version 4, NormedFontScaling
587 rOStm
.WriteInt32(nNormedFontScaling
);
590 rOStm
.WriteInt16( rImplFont
.mnSpacing
);
594 SvStream
& ReadFont( SvStream
& rIStm
, vcl::Font
& rFont
)
596 // tdf#127471 try to read NormedFontScaling
597 tools::Long
nNormedFontScaling(0);
598 SvStream
& rRetval(ReadImplFont( rIStm
, *rFont
.mpImplFont
, nNormedFontScaling
));
600 if (nNormedFontScaling
> 0)
603 // we run on windows and a NormedFontScaling was written
604 if(rFont
.GetFontSize().getWidth() == nNormedFontScaling
)
606 // the writing producer was running on a non-windows system, adapt to needed windows
607 // system-specific pre-multiply
608 const tools::Long
nHeight(std::max
<tools::Long
>(rFont
.GetFontSize().getHeight(), 0));
609 sal_uInt32
nScaledWidth(0);
613 vcl::Font
aUnscaledFont(rFont
);
614 aUnscaledFont
.SetAverageFontWidth(0);
615 const FontMetric
aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont
));
619 const double fScaleFactor(static_cast<double>(nNormedFontScaling
) / static_cast<double>(nHeight
));
620 nScaledWidth
= basegfx::fround(static_cast<double>(aUnscaledFontMetric
.GetAverageFontWidth()) * fScaleFactor
);
624 rFont
.SetAverageFontWidth(nScaledWidth
);
628 // the writing producer was on a windows system, correct pre-multiplied value
629 // is already set, nothing to do. Ignore 2nd value. Here a check
630 // could be done if adapting the 2nd, NormedFontScaling value would be similar to
631 // the set value for plausibility reasons
634 // we do not run on windows and a NormedFontScaling was written
635 if(rFont
.GetFontSize().getWidth() == nNormedFontScaling
)
637 // the writing producer was not on a windows system, correct value
638 // already set, nothing to do
642 // the writing producer was on a windows system, correct FontScaling.
643 // The correct non-pre-multiplied value is the 2nd one, use it
644 rFont
.SetAverageFontWidth(nNormedFontScaling
);
652 SvStream
& WriteFont( SvStream
& rOStm
, const vcl::Font
& rFont
)
654 // tdf#127471 prepare NormedFontScaling for additional export
655 tools::Long
nNormedFontScaling(rFont
.GetFontSize().getWidth());
657 // FontScaling usage at vcl-Font is detected by checking that FontWidth != 0
658 if (nNormedFontScaling
> 0)
660 const tools::Long
nHeight(std::max
<tools::Long
>(rFont
.GetFontSize().getHeight(), 0));
662 // check for negative height
665 nNormedFontScaling
= 0;
670 // for WIN32 the value is pre-multiplied with AverageFontWidth
671 // which makes it system-dependent. Turn that back to have the
672 // normed non-windows form of it for export as 2nd value
673 vcl::Font
aUnscaledFont(rFont
);
674 aUnscaledFont
.SetAverageFontWidth(0);
675 const FontMetric
aUnscaledFontMetric(
676 Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont
));
678 if (aUnscaledFontMetric
.GetAverageFontWidth() > 0)
680 const double fScaleFactor(
681 static_cast<double>(nNormedFontScaling
)
682 / static_cast<double>(aUnscaledFontMetric
.GetAverageFontWidth()));
683 nNormedFontScaling
= static_cast<tools::Long
>(fScaleFactor
* nHeight
);
689 return WriteImplFont( rOStm
, *rFont
.mpImplFont
, nNormedFontScaling
);
694 bool identifyTrueTypeFont( const void* i_pBuffer
, sal_uInt32 i_nSize
, Font
& o_rResult
)
696 bool bResult
= false;
697 TrueTypeFont
* pTTF
= nullptr;
698 if( OpenTTFontBuffer( i_pBuffer
, i_nSize
, 0, &pTTF
) == SFErrCodes::Ok
)
700 TTGlobalFontInfo aInfo
;
701 GetTTGlobalFontInfo( pTTF
, &aInfo
);
702 // most importantly: the family name
703 if( !aInfo
.ufamily
.isEmpty() )
704 o_rResult
.SetFamilyName( aInfo
.ufamily
);
705 else if( !aInfo
.family
.isEmpty() )
706 o_rResult
.SetFamilyName( OStringToOUString( aInfo
.family
, RTL_TEXTENCODING_ASCII_US
) );
710 if( aInfo
.weight
< FW_EXTRALIGHT
)
711 o_rResult
.SetWeight( WEIGHT_THIN
);
712 else if( aInfo
.weight
< FW_LIGHT
)
713 o_rResult
.SetWeight( WEIGHT_ULTRALIGHT
);
714 else if( aInfo
.weight
< FW_NORMAL
)
715 o_rResult
.SetWeight( WEIGHT_LIGHT
);
716 else if( aInfo
.weight
< FW_MEDIUM
)
717 o_rResult
.SetWeight( WEIGHT_NORMAL
);
718 else if( aInfo
.weight
< FW_SEMIBOLD
)
719 o_rResult
.SetWeight( WEIGHT_MEDIUM
);
720 else if( aInfo
.weight
< FW_BOLD
)
721 o_rResult
.SetWeight( WEIGHT_SEMIBOLD
);
722 else if( aInfo
.weight
< FW_EXTRABOLD
)
723 o_rResult
.SetWeight( WEIGHT_BOLD
);
724 else if( aInfo
.weight
< FW_BLACK
)
725 o_rResult
.SetWeight( WEIGHT_ULTRABOLD
);
727 o_rResult
.SetWeight( WEIGHT_BLACK
);
730 o_rResult
.SetWeight( (aInfo
.macStyle
& 1) ? WEIGHT_BOLD
: WEIGHT_NORMAL
);
734 if( aInfo
.width
== FWIDTH_ULTRA_CONDENSED
)
735 o_rResult
.SetAverageFontWidth( WIDTH_ULTRA_CONDENSED
);
736 else if( aInfo
.width
== FWIDTH_EXTRA_CONDENSED
)
737 o_rResult
.SetAverageFontWidth( WIDTH_EXTRA_CONDENSED
);
738 else if( aInfo
.width
== FWIDTH_CONDENSED
)
739 o_rResult
.SetAverageFontWidth( WIDTH_CONDENSED
);
740 else if( aInfo
.width
== FWIDTH_SEMI_CONDENSED
)
741 o_rResult
.SetAverageFontWidth( WIDTH_SEMI_CONDENSED
);
742 else if( aInfo
.width
== FWIDTH_NORMAL
)
743 o_rResult
.SetAverageFontWidth( WIDTH_NORMAL
);
744 else if( aInfo
.width
== FWIDTH_SEMI_EXPANDED
)
745 o_rResult
.SetAverageFontWidth( WIDTH_SEMI_EXPANDED
);
746 else if( aInfo
.width
== FWIDTH_EXPANDED
)
747 o_rResult
.SetAverageFontWidth( WIDTH_EXPANDED
);
748 else if( aInfo
.width
== FWIDTH_EXTRA_EXPANDED
)
749 o_rResult
.SetAverageFontWidth( WIDTH_EXTRA_EXPANDED
);
750 else if( aInfo
.width
>= FWIDTH_ULTRA_EXPANDED
)
751 o_rResult
.SetAverageFontWidth( WIDTH_ULTRA_EXPANDED
);
754 o_rResult
.SetItalic( (aInfo
.italicAngle
!= 0) ? ITALIC_NORMAL
: ITALIC_NONE
);
757 o_rResult
.SetPitch( (aInfo
.pitch
== 0) ? PITCH_VARIABLE
: PITCH_FIXED
);
760 if( !aInfo
.usubfamily
.isEmpty() )
761 o_rResult
.SetStyleName( aInfo
.usubfamily
);
762 else if( !aInfo
.subfamily
.isEmpty() )
763 o_rResult
.SetStyleName( OUString::createFromAscii( aInfo
.subfamily
) );
773 struct WeightSearchEntry
779 bool operator<( const WeightSearchEntry
& rRight
) const
781 return rtl_str_compareIgnoreAsciiCase_WithLength( string
, string_len
, rRight
.string
, rRight
.string_len
) < 0;
784 const weight_table
[] =
786 { "black", 5, WEIGHT_BLACK
},
787 { "bold", 4, WEIGHT_BOLD
},
788 { "book", 4, WEIGHT_LIGHT
},
789 { "demi", 4, WEIGHT_SEMIBOLD
},
790 { "heavy", 5, WEIGHT_BLACK
},
791 { "light", 5, WEIGHT_LIGHT
},
792 { "medium", 6, WEIGHT_MEDIUM
},
793 { "regular", 7, WEIGHT_NORMAL
},
794 { "super", 5, WEIGHT_ULTRABOLD
},
795 { "thin", 4, WEIGHT_THIN
}
798 bool identifyType1Font( const char* i_pBuffer
, sal_uInt32 i_nSize
, Font
& o_rResult
)
800 // might be a type1, find eexec
801 const char* pStream
= i_pBuffer
;
802 const char* const pExec
= "eexec";
803 const char* pExecPos
= std::search( pStream
, pStream
+i_nSize
, pExec
, pExec
+5 );
804 if( pExecPos
!= pStream
+i_nSize
)
806 // find /FamilyName entry
807 static const char* const pFam
= "/FamilyName";
808 const char* pFamPos
= std::search( pStream
, pExecPos
, pFam
, pFam
+11 );
809 if( pFamPos
!= pExecPos
)
811 // extract the string value behind /FamilyName
812 const char* pOpen
= pFamPos
+11;
813 while( pOpen
< pExecPos
&& *pOpen
!= '(' )
815 const char* pClose
= pOpen
;
816 while( pClose
< pExecPos
&& *pClose
!= ')' )
818 if( pClose
- pOpen
> 1 )
820 o_rResult
.SetFamilyName( OStringToOUString( std::string_view( pOpen
+1, pClose
-pOpen
-1 ), RTL_TEXTENCODING_ASCII_US
) );
824 // parse /ItalicAngle
825 static const char* const pItalic
= "/ItalicAngle";
826 const char* pItalicPos
= std::search( pStream
, pExecPos
, pItalic
, pItalic
+12 );
827 if( pItalicPos
!= pExecPos
)
829 const char* pItalicEnd
= pItalicPos
+ 12;
830 auto nItalic
= rtl_str_toInt64_WithLength(pItalicEnd
, 10, pExecPos
- pItalicEnd
);
831 o_rResult
.SetItalic( (nItalic
!= 0) ? ITALIC_NORMAL
: ITALIC_NONE
);
835 static const char* const pWeight
= "/Weight";
836 const char* pWeightPos
= std::search( pStream
, pExecPos
, pWeight
, pWeight
+7 );
837 if( pWeightPos
!= pExecPos
)
839 // extract the string value behind /Weight
840 const char* pOpen
= pWeightPos
+7;
841 while( pOpen
< pExecPos
&& *pOpen
!= '(' )
843 const char* pClose
= pOpen
;
844 while( pClose
< pExecPos
&& *pClose
!= ')' )
846 if( pClose
- pOpen
> 1 )
848 WeightSearchEntry aEnt
;
849 aEnt
.string
= pOpen
+1;
850 aEnt
.string_len
= (pClose
-pOpen
)-1;
851 aEnt
.weight
= WEIGHT_NORMAL
;
852 WeightSearchEntry
const * pFound
= std::lower_bound( std::begin(weight_table
), std::end(weight_table
), aEnt
);
853 if( pFound
!= std::end(weight_table
) &&
854 rtl_str_compareIgnoreAsciiCase_WithLength( pFound
->string
, pFound
->string_len
, aEnt
.string
, aEnt
.string_len
) == 0 )
855 o_rResult
.SetWeight( pFound
->weight
);
859 // parse isFixedPitch
860 static const char* const pFixed
= "/isFixedPitch";
861 const char* pFixedPos
= std::search( pStream
, pExecPos
, pFixed
, pFixed
+13 );
862 if( pFixedPos
!= pExecPos
)
865 while( pFixedPos
< pExecPos
-4 &&
866 ( *pFixedPos
== ' ' ||
867 *pFixedPos
== '\t' ||
868 *pFixedPos
== '\r' ||
869 *pFixedPos
== '\n' ) )
874 if( rtl_str_compareIgnoreAsciiCase_WithLength( pFixedPos
, 4, "true", 4 ) == 0 )
875 o_rResult
.SetPitch( PITCH_FIXED
);
877 o_rResult
.SetPitch( PITCH_VARIABLE
);
884 Font
Font::identifyFont( const void* i_pBuffer
, sal_uInt32 i_nSize
)
887 if( ! identifyTrueTypeFont( i_pBuffer
, i_nSize
, aResult
) )
889 const char* pStream
= static_cast<const char*>(i_pBuffer
);
890 if( pStream
&& i_nSize
> 100 &&
891 *pStream
== '%' && pStream
[1] == '!' )
893 identifyType1Font( pStream
, i_nSize
, aResult
);
900 // The inlines from the font.hxx header are now instantiated for pImpl-ification
901 const Color
& Font::GetColor() const { return mpImplFont
->maColor
; }
902 const Color
& Font::GetFillColor() const { return mpImplFont
->maFillColor
; }
903 bool Font::IsTransparent() const { return mpImplFont
->mbTransparent
; }
905 TextAlign
Font::GetAlignment() const { return mpImplFont
->GetAlignment(); }
907 const OUString
& Font::GetFamilyName() const { return mpImplFont
->GetFamilyName(); }
908 const OUString
& Font::GetStyleName() const { return mpImplFont
->maStyleName
; }
909 const FontFamily
& Font::GetFontFamily() const { return mpImplFont
->meFamily
; }
911 const Size
& Font::GetFontSize() const { return mpImplFont
->GetFontSize(); }
912 void Font::SetFontHeight( tools::Long nHeight
) { SetFontSize( Size( std::as_const(mpImplFont
)->GetFontSize().Width(), nHeight
) ); }
913 tools::Long
Font::GetFontHeight() const { return mpImplFont
->GetFontSize().Height(); }
914 void Font::SetAverageFontWidth( tools::Long nWidth
) { SetFontSize( Size( nWidth
, std::as_const(mpImplFont
)->GetFontSize().Height() ) ); }
915 tools::Long
Font::GetAverageFontWidth() const { return mpImplFont
->GetFontSize().Width(); }
916 const Size
& Font::GetAverageFontSize() const { return mpImplFont
->maAverageFontSize
; }
918 rtl_TextEncoding
Font::GetCharSet() const { return mpImplFont
->GetCharSet(); }
920 const LanguageTag
& Font::GetLanguageTag() const { return mpImplFont
->maLanguageTag
; }
921 const LanguageTag
& Font::GetCJKContextLanguageTag() const { return mpImplFont
->maCJKLanguageTag
; }
922 LanguageType
Font::GetLanguage() const { return mpImplFont
->maLanguageTag
.getLanguageType( false); }
923 LanguageType
Font::GetCJKContextLanguage() const { return mpImplFont
->maCJKLanguageTag
.getLanguageType( false); }
925 Degree10
Font::GetOrientation() const { return mpImplFont
->mnOrientation
; }
926 bool Font::IsVertical() const { return mpImplFont
->mbVertical
; }
927 FontKerning
Font::GetKerning() const { return mpImplFont
->meKerning
; }
929 FontPitch
Font::GetPitch() { return mpImplFont
->GetPitch(); }
930 FontWeight
Font::GetWeight() { return mpImplFont
->GetWeight(); }
931 FontWidth
Font::GetWidthType() { return mpImplFont
->GetWidthType(); }
932 FontItalic
Font::GetItalic() { return mpImplFont
->GetItalic(); }
933 FontFamily
Font::GetFamilyType() { return mpImplFont
->GetFamilyType(); }
935 FontPitch
Font::GetPitch() const { return mpImplFont
->GetPitchNoAsk(); }
936 FontWeight
Font::GetWeight() const { return mpImplFont
->GetWeightNoAsk(); }
937 FontWidth
Font::GetWidthType() const { return mpImplFont
->GetWidthTypeNoAsk(); }
938 FontItalic
Font::GetItalic() const { return mpImplFont
->GetItalicNoAsk(); }
939 FontFamily
Font::GetFamilyType() const { return mpImplFont
->GetFamilyTypeNoAsk(); }
941 int Font::GetQuality() const { return mpImplFont
->GetQuality(); }
942 void Font::SetQuality( int nQuality
) { mpImplFont
->SetQuality( nQuality
); }
943 void Font::IncreaseQualityBy( int nQualityAmount
) { mpImplFont
->IncreaseQualityBy( nQualityAmount
); }
944 void Font::DecreaseQualityBy( int nQualityAmount
) { mpImplFont
->DecreaseQualityBy( nQualityAmount
); }
946 bool Font::IsOutline() const { return mpImplFont
->mbOutline
; }
947 bool Font::IsShadow() const { return mpImplFont
->mbShadow
; }
948 FontRelief
Font::GetRelief() const { return mpImplFont
->meRelief
; }
949 FontLineStyle
Font::GetUnderline() const { return mpImplFont
->meUnderline
; }
950 FontLineStyle
Font::GetOverline() const { return mpImplFont
->meOverline
; }
951 FontStrikeout
Font::GetStrikeout() const { return mpImplFont
->meStrikeout
; }
952 FontEmphasisMark
Font::GetEmphasisMark() const { return mpImplFont
->meEmphasisMark
; }
953 bool Font::IsWordLineMode() const { return mpImplFont
->mbWordLine
; }
954 bool Font::IsSameInstance( const vcl::Font
& rFont
) const { return (mpImplFont
== rFont
.mpImplFont
); }
957 ImplFont::ImplFont() :
958 meWeight( WEIGHT_DONTKNOW
),
959 meFamily( FAMILY_DONTKNOW
),
960 mePitch( PITCH_DONTKNOW
),
961 meWidthType( WIDTH_DONTKNOW
),
962 meItalic( ITALIC_NONE
),
963 meAlign( ALIGN_TOP
),
964 meUnderline( LINESTYLE_NONE
),
965 meOverline( LINESTYLE_NONE
),
966 meStrikeout( STRIKEOUT_NONE
),
967 meRelief( FontRelief::NONE
),
968 meEmphasisMark( FontEmphasisMark::NONE
),
969 meKerning( FontKerning::FontSpecific
),
971 meCharSet( RTL_TEXTENCODING_DONTKNOW
),
972 maLanguageTag( LANGUAGE_DONTKNOW
),
973 maCJKLanguageTag( LANGUAGE_DONTKNOW
),
975 mbConfigLookup( false ),
978 mbTransparent( true ),
979 maColor( COL_TRANSPARENT
),
980 maFillColor( COL_TRANSPARENT
),
984 mnCalculatedAverageFontWidth( 0 )
987 ImplFont::ImplFont( const ImplFont
& rImplFont
) :
988 maFamilyName( rImplFont
.maFamilyName
),
989 maStyleName( rImplFont
.maStyleName
),
990 meWeight( rImplFont
.meWeight
),
991 meFamily( rImplFont
.meFamily
),
992 mePitch( rImplFont
.mePitch
),
993 meWidthType( rImplFont
.meWidthType
),
994 meItalic( rImplFont
.meItalic
),
995 meAlign( rImplFont
.meAlign
),
996 meUnderline( rImplFont
.meUnderline
),
997 meOverline( rImplFont
.meOverline
),
998 meStrikeout( rImplFont
.meStrikeout
),
999 meRelief( rImplFont
.meRelief
),
1000 meEmphasisMark( rImplFont
.meEmphasisMark
),
1001 meKerning( rImplFont
.meKerning
),
1002 mnSpacing( rImplFont
.mnSpacing
),
1003 maAverageFontSize( rImplFont
.maAverageFontSize
),
1004 meCharSet( rImplFont
.meCharSet
),
1005 maLanguageTag( rImplFont
.maLanguageTag
),
1006 maCJKLanguageTag( rImplFont
.maCJKLanguageTag
),
1007 mbOutline( rImplFont
.mbOutline
),
1008 mbConfigLookup( rImplFont
.mbConfigLookup
),
1009 mbShadow( rImplFont
.mbShadow
),
1010 mbVertical( rImplFont
.mbVertical
),
1011 mbTransparent( rImplFont
.mbTransparent
),
1012 maColor( rImplFont
.maColor
),
1013 maFillColor( rImplFont
.maFillColor
),
1014 mbWordLine( rImplFont
.mbWordLine
),
1015 mnOrientation( rImplFont
.mnOrientation
),
1016 mnQuality( rImplFont
.mnQuality
),
1017 mnCalculatedAverageFontWidth( rImplFont
.mnCalculatedAverageFontWidth
)
1020 bool ImplFont::operator==( const ImplFont
& rOther
) const
1022 if(!EqualIgnoreColor( rOther
))
1025 if( (maColor
!= rOther
.maColor
)
1026 || (maFillColor
!= rOther
.maFillColor
) )
1032 bool ImplFont::EqualIgnoreColor( const ImplFont
& rOther
) const
1034 // equality tests split up for easier debugging
1035 if( (meWeight
!= rOther
.meWeight
)
1036 || (meItalic
!= rOther
.meItalic
)
1037 || (meFamily
!= rOther
.meFamily
)
1038 || (mePitch
!= rOther
.mePitch
) )
1041 if( (meCharSet
!= rOther
.meCharSet
)
1042 || (maLanguageTag
!= rOther
.maLanguageTag
)
1043 || (maCJKLanguageTag
!= rOther
.maCJKLanguageTag
)
1044 || (meAlign
!= rOther
.meAlign
) )
1047 if( (maAverageFontSize
!= rOther
.maAverageFontSize
)
1048 || (mnOrientation
!= rOther
.mnOrientation
)
1049 || (mbVertical
!= rOther
.mbVertical
) )
1052 if( (maFamilyName
!= rOther
.maFamilyName
)
1053 || (maStyleName
!= rOther
.maStyleName
) )
1056 if( (meUnderline
!= rOther
.meUnderline
)
1057 || (meOverline
!= rOther
.meOverline
)
1058 || (meStrikeout
!= rOther
.meStrikeout
)
1059 || (meRelief
!= rOther
.meRelief
)
1060 || (meEmphasisMark
!= rOther
.meEmphasisMark
)
1061 || (mbWordLine
!= rOther
.mbWordLine
)
1062 || (mbOutline
!= rOther
.mbOutline
)
1063 || (mbShadow
!= rOther
.mbShadow
)
1064 || (meKerning
!= rOther
.meKerning
)
1065 || (mnSpacing
!= rOther
.mnSpacing
)
1066 || (mbTransparent
!= rOther
.mbTransparent
) )
1072 size_t ImplFont::GetHashValue() const
1074 size_t hash
= GetHashValueIgnoreColor();
1075 o3tl::hash_combine( hash
, static_cast<sal_uInt32
>( maColor
));
1076 o3tl::hash_combine( hash
, static_cast<sal_uInt32
>( maFillColor
));
1080 size_t ImplFont::GetHashValueIgnoreColor() const
1084 o3tl::hash_combine( hash
, meWeight
);
1085 o3tl::hash_combine( hash
, meItalic
);
1086 o3tl::hash_combine( hash
, meFamily
);
1087 o3tl::hash_combine( hash
, mePitch
);
1089 o3tl::hash_combine( hash
, meCharSet
);
1090 o3tl::hash_combine( hash
, maLanguageTag
.getLanguageType( false ).get());
1091 o3tl::hash_combine( hash
, maCJKLanguageTag
.getLanguageType( false ).get());
1092 o3tl::hash_combine( hash
, meAlign
);
1094 o3tl::hash_combine( hash
, maAverageFontSize
.GetHashValue());
1095 o3tl::hash_combine( hash
, mnOrientation
.get());
1096 o3tl::hash_combine( hash
, mbVertical
);
1098 o3tl::hash_combine( hash
, maFamilyName
);
1099 o3tl::hash_combine( hash
, maStyleName
);
1101 o3tl::hash_combine( hash
, meUnderline
);
1102 o3tl::hash_combine( hash
, meOverline
);
1103 o3tl::hash_combine( hash
, meStrikeout
);
1104 o3tl::hash_combine( hash
, meRelief
);
1105 o3tl::hash_combine( hash
, meEmphasisMark
);
1106 o3tl::hash_combine( hash
, mbWordLine
);
1107 o3tl::hash_combine( hash
, mbOutline
);
1108 o3tl::hash_combine( hash
, mbShadow
);
1109 o3tl::hash_combine( hash
, meKerning
);
1110 o3tl::hash_combine( hash
, mnSpacing
);
1111 o3tl::hash_combine( hash
, mbTransparent
);
1116 void ImplFont::AskConfig()
1118 if( mbConfigLookup
)
1121 mbConfigLookup
= true;
1123 // prepare the FontSubst configuration lookup
1124 const utl::FontSubstConfiguration
& rFontSubst
= utl::FontSubstConfiguration::get();
1126 OUString aShortName
;
1127 OUString aFamilyName
;
1128 ImplFontAttrs nType
= ImplFontAttrs::None
;
1129 FontWeight eWeight
= WEIGHT_DONTKNOW
;
1130 FontWidth eWidthType
= WIDTH_DONTKNOW
;
1131 OUString aMapName
= GetEnglishSearchFontName( maFamilyName
);
1133 utl::FontSubstConfiguration::getMapName( aMapName
,
1134 aShortName
, aFamilyName
, eWeight
, eWidthType
, nType
);
1136 // lookup the font name in the configuration
1137 const utl::FontNameAttr
* pFontAttr
= rFontSubst
.getSubstInfo( aMapName
);
1139 // if the direct lookup failed try again with an alias name
1140 if ( !pFontAttr
&& (aShortName
!= aMapName
) )
1141 pFontAttr
= rFontSubst
.getSubstInfo( aShortName
);
1145 // the font was found in the configuration
1146 if( meFamily
== FAMILY_DONTKNOW
)
1148 if ( pFontAttr
->Type
& ImplFontAttrs::Serif
)
1149 meFamily
= FAMILY_ROMAN
;
1150 else if ( pFontAttr
->Type
& ImplFontAttrs::SansSerif
)
1151 meFamily
= FAMILY_SWISS
;
1152 else if ( pFontAttr
->Type
& ImplFontAttrs::Typewriter
)
1153 meFamily
= FAMILY_MODERN
;
1154 else if ( pFontAttr
->Type
& ImplFontAttrs::Italic
)
1155 meFamily
= FAMILY_SCRIPT
;
1156 else if ( pFontAttr
->Type
& ImplFontAttrs::Decorative
)
1157 meFamily
= FAMILY_DECORATIVE
;
1160 if( mePitch
== PITCH_DONTKNOW
)
1162 if ( pFontAttr
->Type
& ImplFontAttrs::Fixed
)
1163 mePitch
= PITCH_FIXED
;
1167 // if some attributes are still unknown then use the FontSubst magic
1168 if( meFamily
== FAMILY_DONTKNOW
)
1170 if( nType
& ImplFontAttrs::Serif
)
1171 meFamily
= FAMILY_ROMAN
;
1172 else if( nType
& ImplFontAttrs::SansSerif
)
1173 meFamily
= FAMILY_SWISS
;
1174 else if( nType
& ImplFontAttrs::Typewriter
)
1175 meFamily
= FAMILY_MODERN
;
1176 else if( nType
& ImplFontAttrs::Italic
)
1177 meFamily
= FAMILY_SCRIPT
;
1178 else if( nType
& ImplFontAttrs::Decorative
)
1179 meFamily
= FAMILY_DECORATIVE
;
1182 if( GetWeight() == WEIGHT_DONTKNOW
)
1183 SetWeight( eWeight
);
1184 if( meWidthType
== WIDTH_DONTKNOW
)
1185 meWidthType
= eWidthType
;
1188 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */