nss: upgrade to release 3.73
[LibreOffice.git] / vcl / source / font / font.cxx
blobbb98445c9d2f272cff15b3777861517387f22955
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <unotools/fontcfg.hxx>
24 #include <unotools/fontdefs.hxx>
26 #include <vcl/font.hxx>
28 #include <impfont.hxx>
29 #include <fontattributes.hxx>
30 #include <sft.hxx>
32 #include <algorithm>
34 #include <rtl/instance.hxx>
35 #include <TypeSerializer.hxx>
36 #include <vcl/svapp.hxx>
38 #ifdef _WIN32
39 #include <vcl/metric.hxx>
40 #else
41 #include <vcl/virdev.hxx>
42 #endif
44 using namespace vcl;
46 namespace
48 struct theGlobalDefault :
49 public rtl::Static< Font::ImplType, theGlobalDefault > {};
52 Font::Font() : mpImplFont(theGlobalDefault::get())
56 Font::Font( const vcl::Font& rFont ) : mpImplFont( rFont.mpImplFont )
60 Font::Font( vcl::Font&& rFont ) noexcept : mpImplFont( std::move(rFont.mpImplFont) )
64 Font::Font( const OUString& rFamilyName, const Size& rSize ) : mpImplFont()
66 mpImplFont->SetFamilyName( rFamilyName );
67 mpImplFont->SetFontSize( rSize );
70 Font::Font( const OUString& rFamilyName, const OUString& rStyleName, const Size& rSize ) : mpImplFont()
72 mpImplFont->SetFamilyName( rFamilyName );
73 mpImplFont->SetStyleName( rStyleName );
74 mpImplFont->SetFontSize( rSize );
77 Font::Font( FontFamily eFamily, const Size& rSize ) : mpImplFont()
79 mpImplFont->SetFamilyType( eFamily );
80 mpImplFont->SetFontSize( rSize );
83 Font::~Font()
87 void Font::SetColor( const Color& rColor )
89 if (const_cast<const ImplType&>(mpImplFont)->maColor != rColor)
91 mpImplFont->maColor = rColor;
95 void Font::SetFillColor( const Color& rColor )
97 mpImplFont->maFillColor = rColor;
98 if ( rColor.GetTransparency() )
99 mpImplFont->mbTransparent = true;
102 void Font::SetTransparent( bool bTransparent )
104 if (const_cast<const ImplType&>(mpImplFont)->mbTransparent != bTransparent)
105 mpImplFont->mbTransparent = bTransparent;
108 void Font::SetAlignment( FontAlign eAlign )
110 if (const_cast<const ImplType&>(mpImplFont)->meAlign != eAlign)
111 mpImplFont->SetAlignment(eAlign);
114 void Font::SetFamilyName( const OUString& rFamilyName )
116 mpImplFont->SetFamilyName( rFamilyName );
119 void Font::SetStyleName( const OUString& rStyleName )
121 mpImplFont->maStyleName = rStyleName;
124 void Font::SetFontSize( const Size& rSize )
126 if (const_cast<const ImplType&>(mpImplFont)->GetFontSize() != rSize)
127 mpImplFont->SetFontSize( rSize );
130 void Font::SetFamily( FontFamily eFamily )
132 if (const_cast<const ImplType&>(mpImplFont)->GetFamilyTypeNoAsk() != eFamily)
133 mpImplFont->SetFamilyType( eFamily );
136 void Font::SetCharSet( rtl_TextEncoding eCharSet )
138 if (const_cast<const ImplType&>(mpImplFont)->GetCharSet() != eCharSet)
140 mpImplFont->SetCharSet( eCharSet );
142 if ( eCharSet == RTL_TEXTENCODING_SYMBOL )
143 mpImplFont->SetSymbolFlag( true );
144 else
145 mpImplFont->SetSymbolFlag( false );
149 bool Font::IsSymbolFont() const
151 return mpImplFont->IsSymbolFont();
154 void Font::SetSymbolFlag( bool bSymbol )
156 mpImplFont->SetSymbolFlag( bSymbol );
158 if ( IsSymbolFont() )
160 mpImplFont->SetCharSet( RTL_TEXTENCODING_SYMBOL );
162 else
164 if ( mpImplFont->GetCharSet() == RTL_TEXTENCODING_SYMBOL )
165 mpImplFont->SetCharSet( RTL_TEXTENCODING_DONTKNOW );
169 void Font::SetLanguageTag( const LanguageTag& rLanguageTag )
171 if (const_cast<const ImplType&>(mpImplFont)->maLanguageTag != rLanguageTag)
172 mpImplFont->maLanguageTag = rLanguageTag;
175 void Font::SetCJKContextLanguageTag( const LanguageTag& rLanguageTag )
177 if (const_cast<const ImplType&>(mpImplFont)->maCJKLanguageTag != rLanguageTag)
178 mpImplFont->maCJKLanguageTag = rLanguageTag;
181 void Font::SetLanguage( LanguageType eLanguage )
183 if (const_cast<const ImplType&>(mpImplFont)->maLanguageTag.getLanguageType(false) != eLanguage)
184 mpImplFont->maLanguageTag.reset( eLanguage);
187 void Font::SetCJKContextLanguage( LanguageType eLanguage )
189 if (const_cast<const ImplType&>(mpImplFont)->maCJKLanguageTag.getLanguageType(false) != eLanguage)
190 mpImplFont->maCJKLanguageTag.reset( eLanguage);
193 void Font::SetPitch( FontPitch ePitch )
195 if (const_cast<const ImplType&>(mpImplFont)->GetPitchNoAsk() != ePitch)
196 mpImplFont->SetPitch( ePitch );
199 void Font::SetOrientation( Degree10 nOrientation )
201 if (const_cast<const ImplType&>(mpImplFont)->mnOrientation != nOrientation)
202 mpImplFont->mnOrientation = nOrientation;
205 void Font::SetVertical( bool bVertical )
207 if (const_cast<const ImplType&>(mpImplFont)->mbVertical != bVertical)
208 mpImplFont->mbVertical = bVertical;
211 void Font::SetKerning( FontKerning eKerning )
213 if (const_cast<const ImplType&>(mpImplFont)->meKerning != eKerning)
214 mpImplFont->meKerning = eKerning;
217 bool Font::IsKerning() const
219 return mpImplFont->meKerning != FontKerning::NONE;
222 void Font::SetWeight( FontWeight eWeight )
224 if (const_cast<const ImplType&>(mpImplFont)->GetWeightNoAsk() != eWeight)
225 mpImplFont->SetWeight( eWeight );
228 void Font::SetWidthType( FontWidth eWidth )
230 if (const_cast<const ImplType&>(mpImplFont)->GetWidthTypeNoAsk() != eWidth)
231 mpImplFont->SetWidthType( eWidth );
234 void Font::SetItalic( FontItalic eItalic )
236 if (const_cast<const ImplType&>(mpImplFont)->GetItalicNoAsk() != eItalic)
237 mpImplFont->SetItalic( eItalic );
240 void Font::SetOutline( bool bOutline )
242 if (const_cast<const ImplType&>(mpImplFont)->mbOutline != bOutline)
243 mpImplFont->mbOutline = bOutline;
246 void Font::SetShadow( bool bShadow )
248 if (const_cast<const ImplType&>(mpImplFont)->mbShadow != bShadow)
249 mpImplFont->mbShadow = bShadow;
252 void Font::SetUnderline( FontLineStyle eUnderline )
254 if (const_cast<const ImplType&>(mpImplFont)->meUnderline != eUnderline)
255 mpImplFont->meUnderline = eUnderline;
258 void Font::SetOverline( FontLineStyle eOverline )
260 if (const_cast<const ImplType&>(mpImplFont)->meOverline != eOverline)
261 mpImplFont->meOverline = eOverline;
264 void Font::SetStrikeout( FontStrikeout eStrikeout )
266 if (const_cast<const ImplType&>(mpImplFont)->meStrikeout != eStrikeout)
267 mpImplFont->meStrikeout = eStrikeout;
270 void Font::SetRelief( FontRelief eRelief )
272 if (const_cast<const ImplType&>(mpImplFont)->meRelief != eRelief)
273 mpImplFont->meRelief = eRelief;
276 void Font::SetEmphasisMark( FontEmphasisMark eEmphasisMark )
278 if (const_cast<const ImplType&>(mpImplFont)->meEmphasisMark != eEmphasisMark )
279 mpImplFont->meEmphasisMark = eEmphasisMark;
282 void Font::SetWordLineMode( bool bWordLine )
284 if (const_cast<const ImplType&>(mpImplFont)->mbWordLine != bWordLine)
285 mpImplFont->mbWordLine = bWordLine;
288 Font& Font::operator=( const vcl::Font& rFont )
290 mpImplFont = rFont.mpImplFont;
291 return *this;
294 Font& Font::operator=( vcl::Font&& rFont ) noexcept
296 mpImplFont = std::move(rFont.mpImplFont);
297 return *this;
300 bool Font::operator==( const vcl::Font& rFont ) const
302 return mpImplFont == rFont.mpImplFont;
305 void Font::Merge( const vcl::Font& rFont )
307 if ( !rFont.GetFamilyName().isEmpty() )
309 SetFamilyName( rFont.GetFamilyName() );
310 SetStyleName( rFont.GetStyleName() );
311 SetCharSet( GetCharSet() );
312 SetLanguageTag( rFont.GetLanguageTag() );
313 SetCJKContextLanguageTag( rFont.GetCJKContextLanguageTag() );
314 // don't use access methods here, might lead to AskConfig(), if DONTKNOW
315 SetFamily( rFont.mpImplFont->GetFamilyTypeNoAsk() );
316 SetPitch( rFont.mpImplFont->GetPitchNoAsk() );
319 // don't use access methods here, might lead to AskConfig(), if DONTKNOW
320 if ( rFont.mpImplFont->GetWeightNoAsk() != WEIGHT_DONTKNOW )
321 SetWeight( rFont.GetWeight() );
322 if ( rFont.mpImplFont->GetItalicNoAsk() != ITALIC_DONTKNOW )
323 SetItalic( rFont.GetItalic() );
324 if ( rFont.mpImplFont->GetWidthTypeNoAsk() != WIDTH_DONTKNOW )
325 SetWidthType( rFont.GetWidthType() );
327 if ( rFont.GetFontSize().Height() )
328 SetFontSize( rFont.GetFontSize() );
329 if ( rFont.GetUnderline() != LINESTYLE_DONTKNOW )
331 SetUnderline( rFont.GetUnderline() );
332 SetWordLineMode( rFont.IsWordLineMode() );
334 if ( rFont.GetOverline() != LINESTYLE_DONTKNOW )
336 SetOverline( rFont.GetOverline() );
337 SetWordLineMode( rFont.IsWordLineMode() );
339 if ( rFont.GetStrikeout() != STRIKEOUT_DONTKNOW )
341 SetStrikeout( rFont.GetStrikeout() );
342 SetWordLineMode( rFont.IsWordLineMode() );
345 // Defaults?
346 SetOrientation( rFont.GetOrientation() );
347 SetVertical( rFont.IsVertical() );
348 SetEmphasisMark( rFont.GetEmphasisMark() );
349 SetKerning( rFont.IsKerning() ? FontKerning::FontSpecific : FontKerning::NONE );
350 SetOutline( rFont.IsOutline() );
351 SetShadow( rFont.IsShadow() );
352 SetRelief( rFont.GetRelief() );
355 void Font::GetFontAttributes( FontAttributes& rAttrs ) const
357 rAttrs.SetFamilyName( mpImplFont->GetFamilyName() );
358 rAttrs.SetStyleName( mpImplFont->maStyleName );
359 rAttrs.SetFamilyType( mpImplFont->GetFamilyTypeNoAsk() );
360 rAttrs.SetPitch( mpImplFont->GetPitchNoAsk() );
361 rAttrs.SetItalic( mpImplFont->GetItalicNoAsk() );
362 rAttrs.SetWeight( mpImplFont->GetWeightNoAsk() );
363 rAttrs.SetWidthType( WIDTH_DONTKNOW );
364 rAttrs.SetSymbolFlag( mpImplFont->GetCharSet() == RTL_TEXTENCODING_SYMBOL );
367 // tdf#127471 for corrections on EMF/WMF we need the AvgFontWidth in Windows-specific notation
368 tools::Long Font::GetOrCalculateAverageFontWidth() const
370 if(0 == mpImplFont->GetCalculatedAverageFontWidth())
372 // VirtualDevice is not thread safe
373 SolarMutexGuard aGuard;
375 // create unscaled copy of font (this), a VirtualDevice and set it there
376 vcl::Font aUnscaledFont(*this);
377 ScopedVclPtr<VirtualDevice> pTempVirtualDevice(VclPtr<VirtualDevice>::Create());
378 aUnscaledFont.SetAverageFontWidth(0);
379 pTempVirtualDevice->SetFont(aUnscaledFont);
381 #ifdef _WIN32
382 // on Windows systems use FontMetric to get/create AverageFontWidth from system
383 const FontMetric aMetric(pTempVirtualDevice->GetFontMetric());
384 const_cast<Font*>(this)->mpImplFont->SetCalculatedAverageFontWidth(aMetric.GetAverageFontWidth());
385 #else
386 // On non-Windows systems we need to calculate AvgFontWidth
387 // as close as possible (discussion see documentation in task),
388 // so calculate it. For discussion of method used, see task
389 // buffer measure string creation, will always use the same
390 static OUString aMeasureString;
392 if(!aMeasureString.getLength())
394 const std::size_t nSize(127 - 32);
395 std::array<sal_Unicode, nSize> aArray;
397 for(sal_Unicode a(0); a < nSize; a++)
399 aArray[a] = a + 32;
402 aMeasureString = OUString(aArray.data());
405 const double fAverageFontWidth(
406 pTempVirtualDevice->GetTextWidth(aMeasureString, 0, aMeasureString.getLength()) /
407 static_cast<double>(aMeasureString.getLength()));
408 const_cast<Font*>(this)->mpImplFont->SetCalculatedAverageFontWidth(basegfx::fround(fAverageFontWidth));
409 #endif
412 return mpImplFont->GetCalculatedAverageFontWidth();
415 SvStream& ReadImplFont( SvStream& rIStm, ImplFont& rImplFont, tools::Long& rnNormedFontScaling )
417 VersionCompat aCompat( rIStm, StreamMode::READ );
418 sal_uInt16 nTmp16(0);
419 sal_Int16 nTmps16(0);
420 bool bTmp(false);
421 sal_uInt8 nTmp8(0);
423 rImplFont.SetFamilyName( rIStm.ReadUniOrByteString(rIStm.GetStreamCharSet()) );
424 rImplFont.maStyleName = rIStm.ReadUniOrByteString(rIStm.GetStreamCharSet());
425 TypeSerializer aSerializer(rIStm);
426 aSerializer.readSize(rImplFont.maAverageFontSize);
428 rIStm.ReadUInt16( nTmp16 ); rImplFont.SetCharSet( static_cast<rtl_TextEncoding>(nTmp16) );
429 rIStm.ReadUInt16( nTmp16 ); rImplFont.SetFamilyType( static_cast<FontFamily>(nTmp16) );
430 rIStm.ReadUInt16( nTmp16 ); rImplFont.SetPitch( static_cast<FontPitch>(nTmp16) );
431 rIStm.ReadUInt16( nTmp16 ); rImplFont.SetWeight( static_cast<FontWeight>(nTmp16) );
432 rIStm.ReadUInt16( nTmp16 ); rImplFont.meUnderline = static_cast<FontLineStyle>(nTmp16);
433 rIStm.ReadUInt16( nTmp16 ); rImplFont.meStrikeout = static_cast<FontStrikeout>(nTmp16);
434 rIStm.ReadUInt16( nTmp16 ); rImplFont.SetItalic( static_cast<FontItalic>(nTmp16) );
435 rIStm.ReadUInt16( nTmp16 ); rImplFont.maLanguageTag.reset( LanguageType(nTmp16) );
436 rIStm.ReadUInt16( nTmp16 ); rImplFont.meWidthType = static_cast<FontWidth>(nTmp16);
438 rIStm.ReadInt16( nTmps16 ); rImplFont.mnOrientation = Degree10(nTmps16);
440 rIStm.ReadCharAsBool( bTmp ); rImplFont.mbWordLine = bTmp;
441 rIStm.ReadCharAsBool( bTmp ); rImplFont.mbOutline = bTmp;
442 rIStm.ReadCharAsBool( bTmp ); rImplFont.mbShadow = bTmp;
443 rIStm.ReadUChar( nTmp8 ); rImplFont.meKerning = static_cast<FontKerning>(nTmp8);
445 if( aCompat.GetVersion() >= 2 )
447 rIStm.ReadUChar( nTmp8 ); rImplFont.meRelief = static_cast<FontRelief>(nTmp8);
448 rIStm.ReadUInt16( nTmp16 ); rImplFont.maCJKLanguageTag.reset( LanguageType(nTmp16) );
449 rIStm.ReadCharAsBool( bTmp ); rImplFont.mbVertical = bTmp;
450 rIStm.ReadUInt16( nTmp16 ); rImplFont.meEmphasisMark = static_cast<FontEmphasisMark>(nTmp16);
453 if( aCompat.GetVersion() >= 3 )
455 rIStm.ReadUInt16( nTmp16 ); rImplFont.meOverline = static_cast<FontLineStyle>(nTmp16);
458 // tdf#127471 read NormedFontScaling
459 if( aCompat.GetVersion() >= 4 )
461 sal_Int32 nNormedFontScaling(0);
462 rIStm.ReadInt32(nNormedFontScaling);
463 rnNormedFontScaling = nNormedFontScaling;
466 // Relief
467 // CJKContextLanguage
469 return rIStm;
472 SvStream& WriteImplFont( SvStream& rOStm, const ImplFont& rImplFont, const tools::Long& rnNormedFontScaling )
474 // tdf#127471 increase to version 4
475 VersionCompat aCompat( rOStm, StreamMode::WRITE, 4 );
477 TypeSerializer aSerializer(rOStm);
478 rOStm.WriteUniOrByteString( rImplFont.GetFamilyName(), rOStm.GetStreamCharSet() );
479 rOStm.WriteUniOrByteString( rImplFont.GetStyleName(), rOStm.GetStreamCharSet() );
480 aSerializer.writeSize(rImplFont.maAverageFontSize);
482 rOStm.WriteUInt16( GetStoreCharSet( rImplFont.GetCharSet() ) );
483 rOStm.WriteUInt16( rImplFont.GetFamilyTypeNoAsk() );
484 rOStm.WriteUInt16( rImplFont.GetPitchNoAsk() );
485 rOStm.WriteUInt16( rImplFont.GetWeightNoAsk() );
486 rOStm.WriteUInt16( rImplFont.meUnderline );
487 rOStm.WriteUInt16( rImplFont.meStrikeout );
488 rOStm.WriteUInt16( rImplFont.GetItalicNoAsk() );
489 rOStm.WriteUInt16( static_cast<sal_uInt16>(rImplFont.maLanguageTag.getLanguageType( false)) );
490 rOStm.WriteUInt16( rImplFont.GetWidthTypeNoAsk() );
492 rOStm.WriteInt16( rImplFont.mnOrientation.get() );
494 rOStm.WriteBool( rImplFont.mbWordLine );
495 rOStm.WriteBool( rImplFont.mbOutline );
496 rOStm.WriteBool( rImplFont.mbShadow );
497 rOStm.WriteUChar( static_cast<sal_uInt8>(rImplFont.meKerning) );
499 // new in version 2
500 rOStm.WriteUChar( static_cast<unsigned char>(rImplFont.meRelief) );
501 rOStm.WriteUInt16( static_cast<sal_uInt16>(rImplFont.maCJKLanguageTag.getLanguageType( false)) );
502 rOStm.WriteBool( rImplFont.mbVertical );
503 rOStm.WriteUInt16( static_cast<sal_uInt16>(rImplFont.meEmphasisMark) );
505 // new in version 3
506 rOStm.WriteUInt16( rImplFont.meOverline );
508 // new in version 4, NormedFontScaling
509 rOStm.WriteInt32(rnNormedFontScaling);
511 return rOStm;
514 SvStream& ReadFont( SvStream& rIStm, vcl::Font& rFont )
516 // tdf#127471 try to read NormedFontScaling
517 tools::Long nNormedFontScaling(0);
518 SvStream& rRetval(ReadImplFont( rIStm, *rFont.mpImplFont, nNormedFontScaling ));
520 if (nNormedFontScaling > 0)
522 #ifdef _WIN32
523 // we run on windows and a NormedFontScaling was written
524 if(rFont.GetFontSize().getWidth() == nNormedFontScaling)
526 // the writing producer was running on a non-windows system, adapt to needed windows
527 // system-specific pre-multiply
528 const tools::Long nHeight(std::max<tools::Long>(rFont.GetFontSize().getHeight(), 0));
529 sal_uInt32 nScaledWidth(0);
531 if(nHeight > 0)
533 vcl::Font aUnscaledFont(rFont);
534 aUnscaledFont.SetAverageFontWidth(0);
535 const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont));
537 if (nHeight > 0)
539 const double fScaleFactor(static_cast<double>(nNormedFontScaling) / static_cast<double>(nHeight));
540 nScaledWidth = basegfx::fround(static_cast<double>(aUnscaledFontMetric.GetAverageFontWidth()) * fScaleFactor);
544 rFont.SetAverageFontWidth(nScaledWidth);
546 else
548 // the writing producer was on a windows system, correct pre-multiplied value
549 // is already set, nothing to do. Ignore 2nd value. Here a check
550 // could be done if adapting the 2nd, NormedFontScaling value would be similar to
551 // the set value for plausability reasons
553 #else
554 // we do not run on windows and a NormedFontScaling was written
555 if(rFont.GetFontSize().getWidth() == nNormedFontScaling)
557 // the writing producer was not on a windows system, correct value
558 // already set, nothing to do
560 else
562 // the writing producer was on a windows system, correct FontScvaling.
563 // The correct non-pre-multiplied value is the 2nd one, use it
564 rFont.SetAverageFontWidth(nNormedFontScaling);
566 #endif
569 return rRetval;
572 SvStream& WriteFont( SvStream& rOStm, const vcl::Font& rFont )
574 // tdf#127471 prepare NormedFontScaling for additional export
575 tools::Long nNormedFontScaling(rFont.GetFontSize().getWidth());
577 // FontScaling usage at vcl-Font is detected by checking that FontWidth != 0
578 if (nNormedFontScaling > 0)
580 const tools::Long nHeight(std::max<tools::Long>(rFont.GetFontSize().getHeight(), 0));
582 // check for negative height
583 if(0 == nHeight)
585 nNormedFontScaling = 0;
587 else
589 #ifdef _WIN32
590 // for WIN32 the value is pre-multiplied with AverageFontWidth
591 // which makes it system-dependent. Turn that back to have the
592 // normed non-windows form of it for export as 2nd value
593 vcl::Font aUnscaledFont(rFont);
594 aUnscaledFont.SetAverageFontWidth(0);
595 const FontMetric aUnscaledFontMetric(
596 Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont));
598 if (aUnscaledFontMetric.GetAverageFontWidth() > 0)
600 const double fScaleFactor(
601 static_cast<double>(nNormedFontScaling)
602 / static_cast<double>(aUnscaledFontMetric.GetAverageFontWidth()));
603 nNormedFontScaling = static_cast<tools::Long>(fScaleFactor * nHeight);
605 #endif
609 return WriteImplFont( rOStm, *rFont.mpImplFont, nNormedFontScaling );
612 namespace
614 bool identifyTrueTypeFont( const void* i_pBuffer, sal_uInt32 i_nSize, Font& o_rResult )
616 bool bResult = false;
617 TrueTypeFont* pTTF = nullptr;
618 if( OpenTTFontBuffer( i_pBuffer, i_nSize, 0, &pTTF ) == SFErrCodes::Ok )
620 TTGlobalFontInfo aInfo;
621 GetTTGlobalFontInfo( pTTF, &aInfo );
622 // most importantly: the family name
623 if( aInfo.ufamily )
624 o_rResult.SetFamilyName( OUString(aInfo.ufamily) );
625 else if( aInfo.family )
626 o_rResult.SetFamilyName( OStringToOUString( aInfo.family, RTL_TEXTENCODING_ASCII_US ) );
627 // set weight
628 if( aInfo.weight )
630 if( aInfo.weight < FW_EXTRALIGHT )
631 o_rResult.SetWeight( WEIGHT_THIN );
632 else if( aInfo.weight < FW_LIGHT )
633 o_rResult.SetWeight( WEIGHT_ULTRALIGHT );
634 else if( aInfo.weight < FW_NORMAL )
635 o_rResult.SetWeight( WEIGHT_LIGHT );
636 else if( aInfo.weight < FW_MEDIUM )
637 o_rResult.SetWeight( WEIGHT_NORMAL );
638 else if( aInfo.weight < FW_SEMIBOLD )
639 o_rResult.SetWeight( WEIGHT_MEDIUM );
640 else if( aInfo.weight < FW_BOLD )
641 o_rResult.SetWeight( WEIGHT_SEMIBOLD );
642 else if( aInfo.weight < FW_EXTRABOLD )
643 o_rResult.SetWeight( WEIGHT_BOLD );
644 else if( aInfo.weight < FW_BLACK )
645 o_rResult.SetWeight( WEIGHT_ULTRABOLD );
646 else
647 o_rResult.SetWeight( WEIGHT_BLACK );
649 else
650 o_rResult.SetWeight( (aInfo.macStyle & 1) ? WEIGHT_BOLD : WEIGHT_NORMAL );
651 // set width
652 if( aInfo.width )
654 if( aInfo.width == FWIDTH_ULTRA_CONDENSED )
655 o_rResult.SetAverageFontWidth( WIDTH_ULTRA_CONDENSED );
656 else if( aInfo.width == FWIDTH_EXTRA_CONDENSED )
657 o_rResult.SetAverageFontWidth( WIDTH_EXTRA_CONDENSED );
658 else if( aInfo.width == FWIDTH_CONDENSED )
659 o_rResult.SetAverageFontWidth( WIDTH_CONDENSED );
660 else if( aInfo.width == FWIDTH_SEMI_CONDENSED )
661 o_rResult.SetAverageFontWidth( WIDTH_SEMI_CONDENSED );
662 else if( aInfo.width == FWIDTH_NORMAL )
663 o_rResult.SetAverageFontWidth( WIDTH_NORMAL );
664 else if( aInfo.width == FWIDTH_SEMI_EXPANDED )
665 o_rResult.SetAverageFontWidth( WIDTH_SEMI_EXPANDED );
666 else if( aInfo.width == FWIDTH_EXPANDED )
667 o_rResult.SetAverageFontWidth( WIDTH_EXPANDED );
668 else if( aInfo.width == FWIDTH_EXTRA_EXPANDED )
669 o_rResult.SetAverageFontWidth( WIDTH_EXTRA_EXPANDED );
670 else if( aInfo.width >= FWIDTH_ULTRA_EXPANDED )
671 o_rResult.SetAverageFontWidth( WIDTH_ULTRA_EXPANDED );
673 // set italic
674 o_rResult.SetItalic( (aInfo.italicAngle != 0) ? ITALIC_NORMAL : ITALIC_NONE );
676 // set pitch
677 o_rResult.SetPitch( (aInfo.pitch == 0) ? PITCH_VARIABLE : PITCH_FIXED );
679 // set style name
680 if( aInfo.usubfamily )
681 o_rResult.SetStyleName( OUString( aInfo.usubfamily ) );
682 else if( aInfo.subfamily )
683 o_rResult.SetStyleName( OUString::createFromAscii( aInfo.subfamily ) );
685 // cleanup
686 CloseTTFont( pTTF );
687 // success
688 bResult = true;
690 return bResult;
693 struct WeightSearchEntry
695 const char* string;
696 int string_len;
697 FontWeight weight;
699 bool operator<( const WeightSearchEntry& rRight ) const
701 return rtl_str_compareIgnoreAsciiCase_WithLength( string, string_len, rRight.string, rRight.string_len ) < 0;
704 const weight_table[] =
706 { "black", 5, WEIGHT_BLACK },
707 { "bold", 4, WEIGHT_BOLD },
708 { "book", 4, WEIGHT_LIGHT },
709 { "demi", 4, WEIGHT_SEMIBOLD },
710 { "heavy", 5, WEIGHT_BLACK },
711 { "light", 5, WEIGHT_LIGHT },
712 { "medium", 6, WEIGHT_MEDIUM },
713 { "regular", 7, WEIGHT_NORMAL },
714 { "super", 5, WEIGHT_ULTRABOLD },
715 { "thin", 4, WEIGHT_THIN }
718 bool identifyType1Font( const char* i_pBuffer, sal_uInt32 i_nSize, Font& o_rResult )
720 // might be a type1, find eexec
721 const char* pStream = i_pBuffer;
722 const char* const pExec = "eexec";
723 const char* pExecPos = std::search( pStream, pStream+i_nSize, pExec, pExec+5 );
724 if( pExecPos != pStream+i_nSize)
726 // find /FamilyName entry
727 static const char* const pFam = "/FamilyName";
728 const char* pFamPos = std::search( pStream, pExecPos, pFam, pFam+11 );
729 if( pFamPos != pExecPos )
731 // extract the string value behind /FamilyName
732 const char* pOpen = pFamPos+11;
733 while( pOpen < pExecPos && *pOpen != '(' )
734 pOpen++;
735 const char* pClose = pOpen;
736 while( pClose < pExecPos && *pClose != ')' )
737 pClose++;
738 if( pClose - pOpen > 1 )
740 o_rResult.SetFamilyName( OStringToOUString( OString( pOpen+1, pClose-pOpen-1 ), RTL_TEXTENCODING_ASCII_US ) );
744 // parse /ItalicAngle
745 static const char* const pItalic = "/ItalicAngle";
746 const char* pItalicPos = std::search( pStream, pExecPos, pItalic, pItalic+12 );
747 if( pItalicPos != pExecPos )
749 const char* pItalicEnd = pItalicPos + 12;
750 auto nItalic = rtl_str_toInt64_WithLength(pItalicEnd, 10, pExecPos - pItalicEnd);
751 o_rResult.SetItalic( (nItalic != 0) ? ITALIC_NORMAL : ITALIC_NONE );
754 // parse /Weight
755 static const char* const pWeight = "/Weight";
756 const char* pWeightPos = std::search( pStream, pExecPos, pWeight, pWeight+7 );
757 if( pWeightPos != pExecPos )
759 // extract the string value behind /Weight
760 const char* pOpen = pWeightPos+7;
761 while( pOpen < pExecPos && *pOpen != '(' )
762 pOpen++;
763 const char* pClose = pOpen;
764 while( pClose < pExecPos && *pClose != ')' )
765 pClose++;
766 if( pClose - pOpen > 1 )
768 WeightSearchEntry aEnt;
769 aEnt.string = pOpen+1;
770 aEnt.string_len = (pClose-pOpen)-1;
771 aEnt.weight = WEIGHT_NORMAL;
772 WeightSearchEntry const * pFound = std::lower_bound( std::begin(weight_table), std::end(weight_table), aEnt );
773 if( pFound != std::end(weight_table) &&
774 rtl_str_compareIgnoreAsciiCase_WithLength( pFound->string, pFound->string_len, aEnt.string, aEnt.string_len) == 0 )
775 o_rResult.SetWeight( pFound->weight );
779 // parse isFixedPitch
780 static const char* const pFixed = "/isFixedPitch";
781 const char* pFixedPos = std::search( pStream, pExecPos, pFixed, pFixed+13 );
782 if( pFixedPos != pExecPos )
784 // skip whitespace
785 while( pFixedPos < pExecPos-4 &&
786 ( *pFixedPos == ' ' ||
787 *pFixedPos == '\t' ||
788 *pFixedPos == '\r' ||
789 *pFixedPos == '\n' ) )
791 pFixedPos++;
793 // find "true" value
794 if( rtl_str_compareIgnoreAsciiCase_WithLength( pFixedPos, 4, "true", 4 ) == 0 )
795 o_rResult.SetPitch( PITCH_FIXED );
796 else
797 o_rResult.SetPitch( PITCH_VARIABLE );
800 return false;
804 Font Font::identifyFont( const void* i_pBuffer, sal_uInt32 i_nSize )
806 Font aResult;
807 if( ! identifyTrueTypeFont( i_pBuffer, i_nSize, aResult ) )
809 const char* pStream = static_cast<const char*>(i_pBuffer);
810 if( pStream && i_nSize > 100 &&
811 *pStream == '%' && pStream[1] == '!' )
813 identifyType1Font( pStream, i_nSize, aResult );
817 return aResult;
820 // The inlines from the font.hxx header are now instantiated for pImpl-ification
821 const Color& Font::GetColor() const { return mpImplFont->maColor; }
822 const Color& Font::GetFillColor() const { return mpImplFont->maFillColor; }
823 bool Font::IsTransparent() const { return mpImplFont->mbTransparent; }
825 FontAlign Font::GetAlignment() const { return mpImplFont->GetAlignment(); }
827 const OUString& Font::GetFamilyName() const { return mpImplFont->GetFamilyName(); }
828 const OUString& Font::GetStyleName() const { return mpImplFont->maStyleName; }
830 const Size& Font::GetFontSize() const { return mpImplFont->GetFontSize(); }
831 void Font::SetFontHeight( tools::Long nHeight ) { SetFontSize( Size( mpImplFont->GetFontSize().Width(), nHeight ) ); }
832 tools::Long Font::GetFontHeight() const { return mpImplFont->GetFontSize().Height(); }
833 void Font::SetAverageFontWidth( tools::Long nWidth ) { SetFontSize( Size( nWidth, mpImplFont->GetFontSize().Height() ) ); }
834 tools::Long Font::GetAverageFontWidth() const { return mpImplFont->GetFontSize().Width(); }
836 rtl_TextEncoding Font::GetCharSet() const { return mpImplFont->GetCharSet(); }
838 const LanguageTag& Font::GetLanguageTag() const { return mpImplFont->maLanguageTag; }
839 const LanguageTag& Font::GetCJKContextLanguageTag() const { return mpImplFont->maCJKLanguageTag; }
840 LanguageType Font::GetLanguage() const { return mpImplFont->maLanguageTag.getLanguageType( false); }
841 LanguageType Font::GetCJKContextLanguage() const { return mpImplFont->maCJKLanguageTag.getLanguageType( false); }
843 Degree10 Font::GetOrientation() const { return mpImplFont->mnOrientation; }
844 bool Font::IsVertical() const { return mpImplFont->mbVertical; }
845 FontKerning Font::GetKerning() const { return mpImplFont->meKerning; }
847 FontPitch Font::GetPitch() { return mpImplFont->GetPitch(); }
848 FontWeight Font::GetWeight() { return mpImplFont->GetWeight(); }
849 FontWidth Font::GetWidthType() { return mpImplFont->GetWidthType(); }
850 FontItalic Font::GetItalic() { return mpImplFont->GetItalic(); }
851 FontFamily Font::GetFamilyType() { return mpImplFont->GetFamilyType(); }
853 FontPitch Font::GetPitch() const { return mpImplFont->GetPitchNoAsk(); }
854 FontWeight Font::GetWeight() const { return mpImplFont->GetWeightNoAsk(); }
855 FontWidth Font::GetWidthType() const { return mpImplFont->GetWidthTypeNoAsk(); }
856 FontItalic Font::GetItalic() const { return mpImplFont->GetItalicNoAsk(); }
857 FontFamily Font::GetFamilyType() const { return mpImplFont->GetFamilyTypeNoAsk(); }
859 int Font::GetQuality() const { return mpImplFont->GetQuality(); }
860 void Font::SetQuality( int nQuality ) { mpImplFont->SetQuality( nQuality ); }
861 void Font::IncreaseQualityBy( int nQualityAmount ) { mpImplFont->IncreaseQualityBy( nQualityAmount ); }
862 void Font::DecreaseQualityBy( int nQualityAmount ) { mpImplFont->DecreaseQualityBy( nQualityAmount ); }
864 bool Font::IsOutline() const { return mpImplFont->mbOutline; }
865 bool Font::IsShadow() const { return mpImplFont->mbShadow; }
866 FontRelief Font::GetRelief() const { return mpImplFont->meRelief; }
867 FontLineStyle Font::GetUnderline() const { return mpImplFont->meUnderline; }
868 FontLineStyle Font::GetOverline() const { return mpImplFont->meOverline; }
869 FontStrikeout Font::GetStrikeout() const { return mpImplFont->meStrikeout; }
870 FontEmphasisMark Font::GetEmphasisMark() const { return mpImplFont->meEmphasisMark; }
871 bool Font::IsWordLineMode() const { return mpImplFont->mbWordLine; }
872 bool Font::IsSameInstance( const vcl::Font& rFont ) const { return (mpImplFont == rFont.mpImplFont); }
875 ImplFont::ImplFont() :
876 meWeight( WEIGHT_DONTKNOW ),
877 meFamily( FAMILY_DONTKNOW ),
878 mePitch( PITCH_DONTKNOW ),
879 meWidthType( WIDTH_DONTKNOW ),
880 meItalic( ITALIC_NONE ),
881 meAlign( ALIGN_TOP ),
882 meUnderline( LINESTYLE_NONE ),
883 meOverline( LINESTYLE_NONE ),
884 meStrikeout( STRIKEOUT_NONE ),
885 meRelief( FontRelief::NONE ),
886 meEmphasisMark( FontEmphasisMark::NONE ),
887 meKerning( FontKerning::FontSpecific ),
888 meCharSet( RTL_TEXTENCODING_DONTKNOW ),
889 maLanguageTag( LANGUAGE_DONTKNOW ),
890 maCJKLanguageTag( LANGUAGE_DONTKNOW ),
891 mbSymbolFlag( false ),
892 mbOutline( false ),
893 mbConfigLookup( false ),
894 mbShadow( false ),
895 mbVertical( false ),
896 mbTransparent( true ),
897 maColor( COL_TRANSPARENT ),
898 maFillColor( COL_TRANSPARENT ),
899 mbWordLine( false ),
900 mnOrientation( 0 ),
901 mnQuality( 0 ),
902 mnCalculatedAverageFontWidth( 0 )
905 ImplFont::ImplFont( const ImplFont& rImplFont ) :
906 maFamilyName( rImplFont.maFamilyName ),
907 maStyleName( rImplFont.maStyleName ),
908 meWeight( rImplFont.meWeight ),
909 meFamily( rImplFont.meFamily ),
910 mePitch( rImplFont.mePitch ),
911 meWidthType( rImplFont.meWidthType ),
912 meItalic( rImplFont.meItalic ),
913 meAlign( rImplFont.meAlign ),
914 meUnderline( rImplFont.meUnderline ),
915 meOverline( rImplFont.meOverline ),
916 meStrikeout( rImplFont.meStrikeout ),
917 meRelief( rImplFont.meRelief ),
918 meEmphasisMark( rImplFont.meEmphasisMark ),
919 meKerning( rImplFont.meKerning ),
920 maAverageFontSize( rImplFont.maAverageFontSize ),
921 meCharSet( rImplFont.meCharSet ),
922 maLanguageTag( rImplFont.maLanguageTag ),
923 maCJKLanguageTag( rImplFont.maCJKLanguageTag ),
924 mbSymbolFlag( rImplFont.mbSymbolFlag ),
925 mbOutline( rImplFont.mbOutline ),
926 mbConfigLookup( rImplFont.mbConfigLookup ),
927 mbShadow( rImplFont.mbShadow ),
928 mbVertical( rImplFont.mbVertical ),
929 mbTransparent( rImplFont.mbTransparent ),
930 maColor( rImplFont.maColor ),
931 maFillColor( rImplFont.maFillColor ),
932 mbWordLine( rImplFont.mbWordLine ),
933 mnOrientation( rImplFont.mnOrientation ),
934 mnQuality( rImplFont.mnQuality ),
935 mnCalculatedAverageFontWidth( rImplFont.mnCalculatedAverageFontWidth )
938 bool ImplFont::operator==( const ImplFont& rOther ) const
940 // equality tests split up for easier debugging
941 if( (meWeight != rOther.meWeight)
942 || (meItalic != rOther.meItalic)
943 || (meFamily != rOther.meFamily)
944 || (mePitch != rOther.mePitch) )
945 return false;
947 if( (meCharSet != rOther.meCharSet)
948 || (maLanguageTag != rOther.maLanguageTag)
949 || (maCJKLanguageTag != rOther.maCJKLanguageTag)
950 || (meAlign != rOther.meAlign) )
951 return false;
953 if( (maAverageFontSize != rOther.maAverageFontSize)
954 || (mnOrientation != rOther.mnOrientation)
955 || (mbVertical != rOther.mbVertical) )
956 return false;
958 if( (maFamilyName != rOther.maFamilyName)
959 || (maStyleName != rOther.maStyleName) )
960 return false;
962 if( (maColor != rOther.maColor)
963 || (maFillColor != rOther.maFillColor) )
964 return false;
966 if( (meUnderline != rOther.meUnderline)
967 || (meOverline != rOther.meOverline)
968 || (meStrikeout != rOther.meStrikeout)
969 || (meRelief != rOther.meRelief)
970 || (meEmphasisMark != rOther.meEmphasisMark)
971 || (mbWordLine != rOther.mbWordLine)
972 || (mbOutline != rOther.mbOutline)
973 || (mbShadow != rOther.mbShadow)
974 || (meKerning != rOther.meKerning)
975 || (mbTransparent != rOther.mbTransparent) )
976 return false;
978 return true;
981 void ImplFont::AskConfig()
983 if( mbConfigLookup )
984 return;
986 mbConfigLookup = true;
988 // prepare the FontSubst configuration lookup
989 const utl::FontSubstConfiguration& rFontSubst = utl::FontSubstConfiguration::get();
991 OUString aShortName;
992 OUString aFamilyName;
993 ImplFontAttrs nType = ImplFontAttrs::None;
994 FontWeight eWeight = WEIGHT_DONTKNOW;
995 FontWidth eWidthType = WIDTH_DONTKNOW;
996 OUString aMapName = GetEnglishSearchFontName( maFamilyName );
998 utl::FontSubstConfiguration::getMapName( aMapName,
999 aShortName, aFamilyName, eWeight, eWidthType, nType );
1001 // lookup the font name in the configuration
1002 const utl::FontNameAttr* pFontAttr = rFontSubst.getSubstInfo( aMapName );
1004 // if the direct lookup failed try again with an alias name
1005 if ( !pFontAttr && (aShortName != aMapName) )
1006 pFontAttr = rFontSubst.getSubstInfo( aShortName );
1008 if( pFontAttr )
1010 // the font was found in the configuration
1011 if( meFamily == FAMILY_DONTKNOW )
1013 if ( pFontAttr->Type & ImplFontAttrs::Serif )
1014 meFamily = FAMILY_ROMAN;
1015 else if ( pFontAttr->Type & ImplFontAttrs::SansSerif )
1016 meFamily = FAMILY_SWISS;
1017 else if ( pFontAttr->Type & ImplFontAttrs::Typewriter )
1018 meFamily = FAMILY_MODERN;
1019 else if ( pFontAttr->Type & ImplFontAttrs::Italic )
1020 meFamily = FAMILY_SCRIPT;
1021 else if ( pFontAttr->Type & ImplFontAttrs::Decorative )
1022 meFamily = FAMILY_DECORATIVE;
1025 if( mePitch == PITCH_DONTKNOW )
1027 if ( pFontAttr->Type & ImplFontAttrs::Fixed )
1028 mePitch = PITCH_FIXED;
1032 // if some attributes are still unknown then use the FontSubst magic
1033 if( meFamily == FAMILY_DONTKNOW )
1035 if( nType & ImplFontAttrs::Serif )
1036 meFamily = FAMILY_ROMAN;
1037 else if( nType & ImplFontAttrs::SansSerif )
1038 meFamily = FAMILY_SWISS;
1039 else if( nType & ImplFontAttrs::Typewriter )
1040 meFamily = FAMILY_MODERN;
1041 else if( nType & ImplFontAttrs::Italic )
1042 meFamily = FAMILY_SCRIPT;
1043 else if( nType & ImplFontAttrs::Decorative )
1044 meFamily = FAMILY_DECORATIVE;
1047 if( GetWeight() == WEIGHT_DONTKNOW )
1048 SetWeight( eWeight );
1049 if( meWidthType == WIDTH_DONTKNOW )
1050 meWidthType = eWidthType;
1053 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */