1188 lines
41 KiB
C++
1188 lines
41 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <tools/stream.hxx>
|
|
#include <tools/vcompat.hxx>
|
|
#include <tools/gen.hxx>
|
|
#include <comphelper/configuration.hxx>
|
|
#include <unotools/fontcfg.hxx>
|
|
#include <unotools/fontdefs.hxx>
|
|
#include <o3tl/hash_combine.hxx>
|
|
#include <i18nlangtag/mslangid.hxx>
|
|
|
|
#include <vcl/font.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/outdev.hxx>
|
|
#include <vcl/virdev.hxx>
|
|
|
|
#include <impfont.hxx>
|
|
#include <fontattributes.hxx>
|
|
#include <fontsubset.hxx>
|
|
#include <sft.hxx>
|
|
|
|
#include <algorithm>
|
|
#include <string_view>
|
|
|
|
#include <vcl/TypeSerializer.hxx>
|
|
|
|
#ifdef _WIN32
|
|
#include <vcl/metric.hxx>
|
|
#endif
|
|
|
|
using namespace vcl;
|
|
|
|
namespace
|
|
{
|
|
Font::ImplType& GetGlobalDefault()
|
|
{
|
|
static Font::ImplType gDefault;
|
|
return gDefault;
|
|
}
|
|
}
|
|
|
|
Font::Font() : mpImplFont(GetGlobalDefault())
|
|
{
|
|
}
|
|
|
|
Font::Font( const vcl::Font& rFont ) : mpImplFont( rFont.mpImplFont )
|
|
{
|
|
}
|
|
|
|
Font::Font( vcl::Font&& rFont ) noexcept : mpImplFont( std::move(rFont.mpImplFont) )
|
|
{
|
|
}
|
|
|
|
Font::Font( const OUString& rFamilyName, const Size& rSize )
|
|
{
|
|
if (GetFamilyName() != rFamilyName
|
|
|| GetAverageFontSize() != rSize)
|
|
{
|
|
auto impl = mpImplFont.get();
|
|
impl->SetFamilyName( rFamilyName );
|
|
impl->SetFontSize( rSize );
|
|
}
|
|
}
|
|
|
|
Font::Font( const OUString& rFamilyName, const OUString& rStyleName, const Size& rSize )
|
|
{
|
|
if (GetFamilyName() != rFamilyName
|
|
|| GetStyleName() != rStyleName
|
|
|| GetAverageFontSize() != rSize)
|
|
{
|
|
auto impl = mpImplFont.get();
|
|
impl->SetFamilyName( rFamilyName );
|
|
impl->SetStyleName( rStyleName );
|
|
impl->SetFontSize( rSize );
|
|
}
|
|
}
|
|
|
|
Font::Font( FontFamily eFamily, const Size& rSize )
|
|
{
|
|
if (GetFontFamily() != eFamily
|
|
|| GetAverageFontSize() != rSize)
|
|
{
|
|
auto impl = mpImplFont.get();
|
|
impl->SetFamilyType( eFamily );
|
|
impl->SetFontSize( rSize );
|
|
}
|
|
}
|
|
|
|
Font::~Font()
|
|
{
|
|
}
|
|
|
|
void Font::SetColor( const Color& rColor )
|
|
{
|
|
if (GetColor() != rColor)
|
|
{
|
|
mpImplFont->maColor = rColor;
|
|
}
|
|
}
|
|
|
|
void Font::SetFillColor( const Color& rColor )
|
|
{
|
|
if (GetFillColor() != rColor)
|
|
{
|
|
auto impl = mpImplFont.get();
|
|
impl->maFillColor = rColor;
|
|
if ( rColor.IsTransparent() )
|
|
impl->mbTransparent = true;
|
|
}
|
|
}
|
|
|
|
void Font::SetTransparent( bool bTransparent )
|
|
{
|
|
if (IsTransparent() != bTransparent)
|
|
mpImplFont->mbTransparent = bTransparent;
|
|
}
|
|
|
|
void Font::SetAlignment( TextAlign eAlign )
|
|
{
|
|
if (GetAlignment() != eAlign)
|
|
mpImplFont->SetAlignment(eAlign);
|
|
}
|
|
|
|
void Font::SetFamilyName( const OUString& rFamilyName )
|
|
{
|
|
if (GetFamilyName() != rFamilyName)
|
|
mpImplFont->SetFamilyName( rFamilyName );
|
|
}
|
|
|
|
void Font::SetStyleName( const OUString& rStyleName )
|
|
{
|
|
if (GetStyleName() != rStyleName)
|
|
mpImplFont->maStyleName = rStyleName;
|
|
}
|
|
|
|
void Font::SetFontSize( const Size& rSize )
|
|
{
|
|
if (GetFontSize() != rSize)
|
|
mpImplFont->SetFontSize( rSize );
|
|
}
|
|
|
|
void Font::SetFamily( FontFamily eFamily )
|
|
{
|
|
if (std::as_const(mpImplFont)->GetFamilyTypeNoAsk() != eFamily)
|
|
mpImplFont->SetFamilyType( eFamily );
|
|
}
|
|
|
|
void Font::SetCharSet( rtl_TextEncoding eCharSet )
|
|
{
|
|
if (GetCharSet() != eCharSet)
|
|
mpImplFont->SetCharSet( eCharSet );
|
|
}
|
|
|
|
void Font::SetLanguageTag( const LanguageTag& rLanguageTag )
|
|
{
|
|
if (GetLanguageTag() != rLanguageTag)
|
|
mpImplFont->maLanguageTag = rLanguageTag;
|
|
}
|
|
|
|
void Font::SetCJKContextLanguageTag( const LanguageTag& rLanguageTag )
|
|
{
|
|
if (GetCJKContextLanguageTag() != rLanguageTag)
|
|
mpImplFont->maCJKLanguageTag = rLanguageTag;
|
|
}
|
|
|
|
void Font::SetLanguage( LanguageType eLanguage )
|
|
{
|
|
if (GetLanguage() != eLanguage)
|
|
mpImplFont->maLanguageTag.reset( eLanguage);
|
|
}
|
|
|
|
void Font::SetCJKContextLanguage( LanguageType eLanguage )
|
|
{
|
|
if (GetCJKContextLanguage() != eLanguage)
|
|
mpImplFont->maCJKLanguageTag.reset( eLanguage);
|
|
}
|
|
|
|
void Font::SetPitch( FontPitch ePitch )
|
|
{
|
|
if (std::as_const(mpImplFont)->GetPitchNoAsk() != ePitch)
|
|
mpImplFont->SetPitch( ePitch );
|
|
}
|
|
|
|
void Font::SetOrientation( Degree10 nOrientation )
|
|
{
|
|
if (GetOrientation() != nOrientation)
|
|
mpImplFont->mnOrientation = nOrientation;
|
|
}
|
|
|
|
void Font::SetVertical( bool bVertical )
|
|
{
|
|
if (IsVertical() != bVertical)
|
|
mpImplFont->mbVertical = bVertical;
|
|
}
|
|
|
|
void Font::SetKerning( FontKerning eKerning )
|
|
{
|
|
if (GetKerning() != eKerning)
|
|
mpImplFont->meKerning = eKerning;
|
|
}
|
|
|
|
bool Font::IsKerning() const
|
|
{
|
|
return mpImplFont->meKerning != FontKerning::NONE;
|
|
}
|
|
|
|
void Font::SetFixKerning( short nSpacing )
|
|
{
|
|
if (GetFixKerning() != nSpacing)
|
|
mpImplFont->mnSpacing = nSpacing;
|
|
}
|
|
|
|
short Font::GetFixKerning() const
|
|
{
|
|
return mpImplFont->mnSpacing;
|
|
}
|
|
|
|
bool Font::IsFixKerning() const
|
|
{
|
|
return mpImplFont->mnSpacing != 0;
|
|
}
|
|
|
|
void Font::SetWeight( FontWeight eWeight )
|
|
{
|
|
if (std::as_const(mpImplFont)->GetWeightNoAsk() != eWeight)
|
|
mpImplFont->SetWeight( eWeight );
|
|
}
|
|
|
|
void Font::SetWidthType( FontWidth eWidth )
|
|
{
|
|
if (std::as_const(mpImplFont)->GetWidthTypeNoAsk() != eWidth)
|
|
mpImplFont->SetWidthType( eWidth );
|
|
}
|
|
|
|
void Font::SetItalic( FontItalic eItalic )
|
|
{
|
|
if (std::as_const(mpImplFont)->GetItalicNoAsk() != eItalic)
|
|
mpImplFont->SetItalic( eItalic );
|
|
}
|
|
|
|
void Font::SetOutline( bool bOutline )
|
|
{
|
|
if (IsOutline() != bOutline)
|
|
mpImplFont->mbOutline = bOutline;
|
|
}
|
|
|
|
void Font::SetShadow( bool bShadow )
|
|
{
|
|
if (IsShadow() != bShadow)
|
|
mpImplFont->mbShadow = bShadow;
|
|
}
|
|
|
|
void Font::SetUnderline( FontLineStyle eUnderline )
|
|
{
|
|
if (GetUnderline() != eUnderline)
|
|
mpImplFont->meUnderline = eUnderline;
|
|
}
|
|
|
|
void Font::SetOverline( FontLineStyle eOverline )
|
|
{
|
|
if (GetOverline() != eOverline)
|
|
mpImplFont->meOverline = eOverline;
|
|
}
|
|
|
|
void Font::SetStrikeout( FontStrikeout eStrikeout )
|
|
{
|
|
if (GetStrikeout() != eStrikeout)
|
|
mpImplFont->meStrikeout = eStrikeout;
|
|
}
|
|
|
|
void Font::SetRelief( FontRelief eRelief )
|
|
{
|
|
if (GetRelief() != eRelief)
|
|
mpImplFont->meRelief = eRelief;
|
|
}
|
|
|
|
void Font::SetEmphasisMark( FontEmphasisMark eEmphasisMark )
|
|
{
|
|
if (GetEmphasisMark() != eEmphasisMark)
|
|
mpImplFont->meEmphasisMark = eEmphasisMark;
|
|
}
|
|
|
|
void Font::SetWordLineMode( bool bWordLine )
|
|
{
|
|
if (IsWordLineMode() != bWordLine)
|
|
mpImplFont->mbWordLine = bWordLine;
|
|
}
|
|
|
|
Font& Font::operator=( const vcl::Font& rFont )
|
|
{
|
|
mpImplFont = rFont.mpImplFont;
|
|
return *this;
|
|
}
|
|
|
|
Font& Font::operator=( vcl::Font&& rFont ) noexcept
|
|
{
|
|
mpImplFont = std::move(rFont.mpImplFont);
|
|
return *this;
|
|
}
|
|
|
|
FontEmphasisMark Font::GetEmphasisMarkStyle() const
|
|
{
|
|
FontEmphasisMark nEmphasisMark = GetEmphasisMark();
|
|
|
|
// If no Position is set, then calculate the default position, which
|
|
// depends on the language
|
|
if (!(nEmphasisMark & (FontEmphasisMark::PosAbove | FontEmphasisMark::PosBelow)))
|
|
{
|
|
LanguageType eLang = GetLanguage();
|
|
// In Chinese Simplified the EmphasisMarks are below/left
|
|
if (MsLangId::isSimplifiedChinese(eLang))
|
|
{
|
|
nEmphasisMark |= FontEmphasisMark::PosBelow;
|
|
}
|
|
else
|
|
{
|
|
eLang = GetCJKContextLanguage();
|
|
|
|
// In Chinese Simplified the EmphasisMarks are below/left
|
|
if (MsLangId::isSimplifiedChinese(eLang))
|
|
nEmphasisMark |= FontEmphasisMark::PosBelow;
|
|
else
|
|
nEmphasisMark |= FontEmphasisMark::PosAbove;
|
|
}
|
|
}
|
|
|
|
return nEmphasisMark;
|
|
}
|
|
|
|
bool Font::operator==( const vcl::Font& rFont ) const
|
|
{
|
|
return mpImplFont == rFont.mpImplFont;
|
|
}
|
|
|
|
bool Font::EqualIgnoreColor( const vcl::Font& rFont ) const
|
|
{
|
|
return mpImplFont->EqualIgnoreColor( *rFont.mpImplFont );
|
|
}
|
|
|
|
size_t Font::GetHashValueIgnoreColor() const
|
|
{
|
|
return mpImplFont->GetHashValueIgnoreColor();
|
|
}
|
|
|
|
void Font::Merge( const vcl::Font& rFont )
|
|
{
|
|
if ( !rFont.GetFamilyName().isEmpty() )
|
|
{
|
|
SetFamilyName( rFont.GetFamilyName() );
|
|
SetStyleName( rFont.GetStyleName() );
|
|
SetCharSet( rFont.GetCharSet() );
|
|
SetLanguageTag( rFont.GetLanguageTag() );
|
|
SetCJKContextLanguageTag( rFont.GetCJKContextLanguageTag() );
|
|
// don't use access methods here, might lead to AskConfig(), if DONTKNOW
|
|
SetFamily( rFont.GetFamilyType() );
|
|
SetPitch( rFont.GetPitch() );
|
|
}
|
|
|
|
if ( rFont.GetWeight() != WEIGHT_DONTKNOW )
|
|
SetWeight( rFont.GetWeight() );
|
|
if ( rFont.GetItalic() != ITALIC_DONTKNOW )
|
|
SetItalic( rFont.GetItalic() );
|
|
if ( rFont.GetWidthType() != WIDTH_DONTKNOW )
|
|
SetWidthType( rFont.GetWidthType() );
|
|
|
|
if ( rFont.GetFontSize().Height() )
|
|
SetFontSize( rFont.GetFontSize() );
|
|
if ( rFont.GetUnderline() != LINESTYLE_DONTKNOW )
|
|
{
|
|
SetUnderline( rFont.GetUnderline() );
|
|
SetWordLineMode( rFont.IsWordLineMode() );
|
|
}
|
|
if ( rFont.GetOverline() != LINESTYLE_DONTKNOW )
|
|
{
|
|
SetOverline( rFont.GetOverline() );
|
|
SetWordLineMode( rFont.IsWordLineMode() );
|
|
}
|
|
if ( rFont.GetStrikeout() != STRIKEOUT_DONTKNOW )
|
|
{
|
|
SetStrikeout( rFont.GetStrikeout() );
|
|
SetWordLineMode( rFont.IsWordLineMode() );
|
|
}
|
|
|
|
// Defaults?
|
|
SetOrientation( rFont.GetOrientation() );
|
|
SetVertical( rFont.IsVertical() );
|
|
SetEmphasisMark( rFont.GetEmphasisMark() );
|
|
SetKerning( rFont.IsKerning() ? FontKerning::FontSpecific : FontKerning::NONE );
|
|
SetOutline( rFont.IsOutline() );
|
|
SetShadow( rFont.IsShadow() );
|
|
SetRelief( rFont.GetRelief() );
|
|
}
|
|
|
|
void Font::GetFontAttributes( FontAttributes& rAttrs ) const
|
|
{
|
|
rAttrs.SetFamilyName( GetFamilyName() );
|
|
rAttrs.SetStyleName( GetStyleName() );
|
|
rAttrs.SetFamilyType( GetFamilyType() );
|
|
rAttrs.SetPitch( GetPitch() );
|
|
rAttrs.SetItalic( GetItalic() );
|
|
rAttrs.SetWeight( GetWeight() );
|
|
rAttrs.SetWidthType( WIDTH_DONTKNOW );
|
|
rAttrs.SetMicrosoftSymbolEncoded( GetCharSet() == RTL_TEXTENCODING_SYMBOL );
|
|
}
|
|
|
|
// tdf#127471 for corrections on EMF/WMF we need the AvgFontWidth in Windows-specific notation
|
|
tools::Long Font::GetOrCalculateAverageFontWidth() const
|
|
{
|
|
if(0 == mpImplFont->GetCalculatedAverageFontWidth())
|
|
{
|
|
// VirtualDevice is not thread safe
|
|
SolarMutexGuard aGuard;
|
|
|
|
// create unscaled copy of font (this), a VirtualDevice and set it there
|
|
vcl::Font aUnscaledFont(*this);
|
|
ScopedVclPtr<VirtualDevice> pTempVirtualDevice(VclPtr<VirtualDevice>::Create());
|
|
aUnscaledFont.SetAverageFontWidth(0);
|
|
pTempVirtualDevice->SetFont(aUnscaledFont);
|
|
|
|
#ifdef _WIN32
|
|
// on Windows systems use FontMetric to get/create AverageFontWidth from system
|
|
const FontMetric aMetric(pTempVirtualDevice->GetFontMetric());
|
|
const_cast<Font*>(this)->mpImplFont->SetCalculatedAverageFontWidth(aMetric.GetAverageFontWidth());
|
|
#else
|
|
// On non-Windows systems we need to calculate AvgFontWidth
|
|
// as close as possible (discussion see documentation in task),
|
|
// so calculate it. For discussion of method used, see task
|
|
// buffer measure string creation, will always use the same
|
|
static constexpr OUString aMeasureString
|
|
= u"\u0020\u0021\u0022\u0023\u0024\u0025\u0026\u0027"
|
|
"\u0028\u0029\u002A\u002B\u002C\u002D\u002E\u002F"
|
|
"\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037"
|
|
"\u0038\u0039\u003A\u003B\u003C\u003D\u003E\u003F"
|
|
"\u0040\u0041\u0042\u0043\u0044\u0045\u0046\u0047"
|
|
"\u0048\u0049\u004A\u004B\u004C\u004D\u004E\u004F"
|
|
"\u0050\u0051\u0052\u0053\u0054\u0055\u0056\u0057"
|
|
"\u0058\u0059\u005A\u005B\u005C\u005D\u005E\u005F"
|
|
"\u0060\u0061\u0062\u0063\u0064\u0065\u0066\u0067"
|
|
"\u0068\u0069\u006A\u006B\u006C\u006D\u006E\u006F"
|
|
"\u0070\u0071\u0072\u0073\u0074\u0075\u0076\u0077"
|
|
"\u0078\u0079\u007A\u007B\u007C\u007D\u007E"_ustr;
|
|
|
|
const double fAverageFontWidth(
|
|
pTempVirtualDevice->GetTextWidth(aMeasureString) /
|
|
static_cast<double>(aMeasureString.getLength()));
|
|
const_cast<Font*>(this)->mpImplFont->SetCalculatedAverageFontWidth(basegfx::fround(fAverageFontWidth));
|
|
#endif
|
|
}
|
|
|
|
return mpImplFont->GetCalculatedAverageFontWidth();
|
|
}
|
|
|
|
SvStream& ReadImplFont( SvStream& rIStm, ImplFont& rImplFont, tools::Long& rnNormedFontScaling )
|
|
{
|
|
VersionCompatRead aCompat( rIStm );
|
|
sal_uInt16 nTmp16(0);
|
|
sal_Int16 nTmps16(0);
|
|
bool bTmp(false);
|
|
sal_uInt8 nTmp8(0);
|
|
|
|
rImplFont.SetFamilyName( rIStm.ReadUniOrByteString(rIStm.GetStreamCharSet()) );
|
|
rImplFont.maStyleName = rIStm.ReadUniOrByteString(rIStm.GetStreamCharSet());
|
|
TypeSerializer aSerializer(rIStm);
|
|
aSerializer.readSize(rImplFont.maAverageFontSize);
|
|
|
|
static const bool bFuzzing = comphelper::IsFuzzing();
|
|
if (bFuzzing)
|
|
{
|
|
if (rImplFont.maAverageFontSize.Width() > 8192)
|
|
{
|
|
SAL_WARN("vcl.gdi", "suspicious average width of: " << rImplFont.maAverageFontSize.Width());
|
|
rImplFont.maAverageFontSize.setWidth(8192);
|
|
}
|
|
if (rImplFont.maAverageFontSize.Height() > 8192)
|
|
{
|
|
SAL_WARN("vcl.gdi", "suspicious average height of: " << rImplFont.maAverageFontSize.Height());
|
|
rImplFont.maAverageFontSize.setHeight(8192);
|
|
}
|
|
}
|
|
|
|
rIStm.ReadUInt16( nTmp16 ); rImplFont.SetCharSet( static_cast<rtl_TextEncoding>(nTmp16) );
|
|
rIStm.ReadUInt16( nTmp16 ); rImplFont.SetFamilyType( static_cast<FontFamily>(nTmp16) );
|
|
rIStm.ReadUInt16( nTmp16 ); rImplFont.SetPitch( static_cast<FontPitch>(nTmp16) );
|
|
rIStm.ReadUInt16( nTmp16 ); rImplFont.SetWeight( static_cast<FontWeight>(nTmp16) );
|
|
rIStm.ReadUInt16( nTmp16 ); rImplFont.meUnderline = static_cast<FontLineStyle>(nTmp16);
|
|
rIStm.ReadUInt16( nTmp16 ); rImplFont.meStrikeout = static_cast<FontStrikeout>(nTmp16);
|
|
rIStm.ReadUInt16( nTmp16 ); rImplFont.SetItalic( static_cast<FontItalic>(nTmp16) );
|
|
rIStm.ReadUInt16( nTmp16 ); rImplFont.maLanguageTag.reset( LanguageType(nTmp16) );
|
|
rIStm.ReadUInt16( nTmp16 ); rImplFont.meWidthType = static_cast<FontWidth>(nTmp16);
|
|
|
|
rIStm.ReadInt16( nTmps16 ); rImplFont.mnOrientation = Degree10(nTmps16);
|
|
|
|
rIStm.ReadCharAsBool( bTmp ); rImplFont.mbWordLine = bTmp;
|
|
rIStm.ReadCharAsBool( bTmp ); rImplFont.mbOutline = bTmp;
|
|
rIStm.ReadCharAsBool( bTmp ); rImplFont.mbShadow = bTmp;
|
|
rIStm.ReadUChar( nTmp8 ); rImplFont.meKerning = static_cast<FontKerning>(nTmp8);
|
|
|
|
if( aCompat.GetVersion() >= 2 )
|
|
{
|
|
rIStm.ReadUChar( nTmp8 ); rImplFont.meRelief = static_cast<FontRelief>(nTmp8);
|
|
rIStm.ReadUInt16( nTmp16 ); rImplFont.maCJKLanguageTag.reset( LanguageType(nTmp16) );
|
|
rIStm.ReadCharAsBool( bTmp ); rImplFont.mbVertical = bTmp;
|
|
rIStm.ReadUInt16( nTmp16 );
|
|
rImplFont.meEmphasisMark = static_cast<FontEmphasisMark>(nTmp16 & o3tl::typed_flags<FontEmphasisMark>::mask);
|
|
}
|
|
|
|
if( aCompat.GetVersion() >= 3 )
|
|
{
|
|
rIStm.ReadUInt16( nTmp16 ); rImplFont.meOverline = static_cast<FontLineStyle>(nTmp16);
|
|
}
|
|
|
|
// tdf#127471 read NormedFontScaling
|
|
if( aCompat.GetVersion() >= 4 )
|
|
{
|
|
sal_Int32 nNormedFontScaling(0);
|
|
rIStm.ReadInt32(nNormedFontScaling);
|
|
rnNormedFontScaling = nNormedFontScaling;
|
|
}
|
|
|
|
if( aCompat.GetVersion() >= 5 )
|
|
{
|
|
rIStm.ReadInt16( nTmps16 );
|
|
rImplFont.mnSpacing = nTmps16;
|
|
}
|
|
|
|
// Relief
|
|
// CJKContextLanguage
|
|
|
|
return rIStm;
|
|
}
|
|
|
|
SvStream& WriteImplFont( SvStream& rOStm, const ImplFont& rImplFont, tools::Long nNormedFontScaling )
|
|
{
|
|
// tdf#127471 increase to version 4
|
|
// tdf#66819 increase to version 5
|
|
VersionCompatWrite aCompat( rOStm, 5 );
|
|
|
|
TypeSerializer aSerializer(rOStm);
|
|
rOStm.WriteUniOrByteString( rImplFont.GetFamilyName(), rOStm.GetStreamCharSet() );
|
|
rOStm.WriteUniOrByteString( rImplFont.GetStyleName(), rOStm.GetStreamCharSet() );
|
|
aSerializer.writeSize(rImplFont.maAverageFontSize);
|
|
|
|
rOStm.WriteUInt16( GetStoreCharSet( rImplFont.GetCharSet() ) );
|
|
rOStm.WriteUInt16( rImplFont.GetFamilyTypeNoAsk() );
|
|
rOStm.WriteUInt16( rImplFont.GetPitchNoAsk() );
|
|
rOStm.WriteUInt16( rImplFont.GetWeightNoAsk() );
|
|
rOStm.WriteUInt16( rImplFont.meUnderline );
|
|
rOStm.WriteUInt16( rImplFont.meStrikeout );
|
|
rOStm.WriteUInt16( rImplFont.GetItalicNoAsk() );
|
|
rOStm.WriteUInt16( static_cast<sal_uInt16>(rImplFont.maLanguageTag.getLanguageType( false)) );
|
|
rOStm.WriteUInt16( rImplFont.GetWidthTypeNoAsk() );
|
|
|
|
rOStm.WriteInt16( rImplFont.mnOrientation.get() );
|
|
|
|
rOStm.WriteBool( rImplFont.mbWordLine );
|
|
rOStm.WriteBool( rImplFont.mbOutline );
|
|
rOStm.WriteBool( rImplFont.mbShadow );
|
|
rOStm.WriteUChar( static_cast<sal_uInt8>(rImplFont.meKerning) );
|
|
|
|
// new in version 2
|
|
rOStm.WriteUChar( static_cast<unsigned char>(rImplFont.meRelief) );
|
|
rOStm.WriteUInt16( static_cast<sal_uInt16>(rImplFont.maCJKLanguageTag.getLanguageType( false)) );
|
|
rOStm.WriteBool( rImplFont.mbVertical );
|
|
rOStm.WriteUInt16( static_cast<sal_uInt16>(rImplFont.meEmphasisMark) );
|
|
|
|
// new in version 3
|
|
rOStm.WriteUInt16( rImplFont.meOverline );
|
|
|
|
// new in version 4, NormedFontScaling
|
|
rOStm.WriteInt32(nNormedFontScaling);
|
|
|
|
// new in version 5
|
|
rOStm.WriteInt16( rImplFont.mnSpacing );
|
|
return rOStm;
|
|
}
|
|
|
|
SvStream& ReadFont( SvStream& rIStm, vcl::Font& rFont )
|
|
{
|
|
// tdf#127471 try to read NormedFontScaling
|
|
tools::Long nNormedFontScaling(0);
|
|
SvStream& rRetval(ReadImplFont( rIStm, *rFont.mpImplFont, nNormedFontScaling ));
|
|
|
|
if (nNormedFontScaling > 0)
|
|
{
|
|
#ifdef _WIN32
|
|
// we run on windows and a NormedFontScaling was written
|
|
if(rFont.GetFontSize().getWidth() == nNormedFontScaling)
|
|
{
|
|
// the writing producer was running on a non-windows system, adapt to needed windows
|
|
// system-specific pre-multiply
|
|
const tools::Long nHeight(std::max<tools::Long>(rFont.GetFontSize().getHeight(), 0));
|
|
sal_uInt32 nScaledWidth(0);
|
|
|
|
if(nHeight > 0)
|
|
{
|
|
vcl::Font aUnscaledFont(rFont);
|
|
aUnscaledFont.SetAverageFontWidth(0);
|
|
const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont));
|
|
|
|
if (nHeight > 0)
|
|
{
|
|
const double fScaleFactor(static_cast<double>(nNormedFontScaling) / static_cast<double>(nHeight));
|
|
nScaledWidth = basegfx::fround(static_cast<double>(aUnscaledFontMetric.GetAverageFontWidth()) * fScaleFactor);
|
|
}
|
|
}
|
|
|
|
rFont.SetAverageFontWidth(nScaledWidth);
|
|
}
|
|
else
|
|
{
|
|
// the writing producer was on a windows system, correct pre-multiplied value
|
|
// is already set, nothing to do. Ignore 2nd value. Here a check
|
|
// could be done if adapting the 2nd, NormedFontScaling value would be similar to
|
|
// the set value for plausibility reasons
|
|
}
|
|
#else
|
|
// we do not run on windows and a NormedFontScaling was written
|
|
if(rFont.GetFontSize().getWidth() == nNormedFontScaling)
|
|
{
|
|
// the writing producer was not on a windows system, correct value
|
|
// already set, nothing to do
|
|
}
|
|
else
|
|
{
|
|
// the writing producer was on a windows system, correct FontScaling.
|
|
// The correct non-pre-multiplied value is the 2nd one, use it
|
|
rFont.SetAverageFontWidth(nNormedFontScaling);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return rRetval;
|
|
}
|
|
|
|
SvStream& WriteFont( SvStream& rOStm, const vcl::Font& rFont )
|
|
{
|
|
// tdf#127471 prepare NormedFontScaling for additional export
|
|
tools::Long nNormedFontScaling(rFont.GetFontSize().getWidth());
|
|
|
|
// FontScaling usage at vcl-Font is detected by checking that FontWidth != 0
|
|
if (nNormedFontScaling > 0)
|
|
{
|
|
const tools::Long nHeight(std::max<tools::Long>(rFont.GetFontSize().getHeight(), 0));
|
|
|
|
// check for negative height
|
|
if(0 == nHeight)
|
|
{
|
|
nNormedFontScaling = 0;
|
|
}
|
|
else
|
|
{
|
|
#ifdef _WIN32
|
|
// for WIN32 the value is pre-multiplied with AverageFontWidth
|
|
// which makes it system-dependent. Turn that back to have the
|
|
// normed non-windows form of it for export as 2nd value
|
|
vcl::Font aUnscaledFont(rFont);
|
|
aUnscaledFont.SetAverageFontWidth(0);
|
|
const FontMetric aUnscaledFontMetric(
|
|
Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont));
|
|
|
|
if (aUnscaledFontMetric.GetAverageFontWidth() > 0)
|
|
{
|
|
const double fScaleFactor(
|
|
static_cast<double>(nNormedFontScaling)
|
|
/ static_cast<double>(aUnscaledFontMetric.GetAverageFontWidth()));
|
|
nNormedFontScaling = static_cast<tools::Long>(fScaleFactor * nHeight);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return WriteImplFont( rOStm, *rFont.mpImplFont, nNormedFontScaling );
|
|
}
|
|
|
|
namespace
|
|
{
|
|
bool identifyTrueTypeFont( const void* i_pBuffer, sal_uInt32 i_nSize, Font& o_rResult )
|
|
{
|
|
bool bResult = false;
|
|
TrueTypeFont* pTTF = nullptr;
|
|
if( OpenTTFontBuffer( i_pBuffer, i_nSize, 0, &pTTF ) == SFErrCodes::Ok )
|
|
{
|
|
TTGlobalFontInfo aInfo;
|
|
GetTTGlobalFontInfo( pTTF, &aInfo );
|
|
// most importantly: the family name
|
|
if( !aInfo.ufamily.isEmpty() )
|
|
o_rResult.SetFamilyName( aInfo.ufamily );
|
|
else if( !aInfo.family.isEmpty() )
|
|
o_rResult.SetFamilyName( OStringToOUString( aInfo.family, RTL_TEXTENCODING_ASCII_US ) );
|
|
// set weight
|
|
if( aInfo.weight )
|
|
{
|
|
if( aInfo.weight < FW_EXTRALIGHT )
|
|
o_rResult.SetWeight( WEIGHT_THIN );
|
|
else if( aInfo.weight < FW_LIGHT )
|
|
o_rResult.SetWeight( WEIGHT_ULTRALIGHT );
|
|
else if( aInfo.weight < FW_NORMAL )
|
|
o_rResult.SetWeight( WEIGHT_LIGHT );
|
|
else if( aInfo.weight < FW_MEDIUM )
|
|
o_rResult.SetWeight( WEIGHT_NORMAL );
|
|
else if( aInfo.weight < FW_SEMIBOLD )
|
|
o_rResult.SetWeight( WEIGHT_MEDIUM );
|
|
else if( aInfo.weight < FW_BOLD )
|
|
o_rResult.SetWeight( WEIGHT_SEMIBOLD );
|
|
else if( aInfo.weight < FW_EXTRABOLD )
|
|
o_rResult.SetWeight( WEIGHT_BOLD );
|
|
else if( aInfo.weight < FW_BLACK )
|
|
o_rResult.SetWeight( WEIGHT_ULTRABOLD );
|
|
else
|
|
o_rResult.SetWeight( WEIGHT_BLACK );
|
|
}
|
|
else
|
|
o_rResult.SetWeight( (aInfo.macStyle & 1) ? WEIGHT_BOLD : WEIGHT_NORMAL );
|
|
// set width
|
|
if( aInfo.width )
|
|
{
|
|
if( aInfo.width == FWIDTH_ULTRA_CONDENSED )
|
|
o_rResult.SetAverageFontWidth( WIDTH_ULTRA_CONDENSED );
|
|
else if( aInfo.width == FWIDTH_EXTRA_CONDENSED )
|
|
o_rResult.SetAverageFontWidth( WIDTH_EXTRA_CONDENSED );
|
|
else if( aInfo.width == FWIDTH_CONDENSED )
|
|
o_rResult.SetAverageFontWidth( WIDTH_CONDENSED );
|
|
else if( aInfo.width == FWIDTH_SEMI_CONDENSED )
|
|
o_rResult.SetAverageFontWidth( WIDTH_SEMI_CONDENSED );
|
|
else if( aInfo.width == FWIDTH_NORMAL )
|
|
o_rResult.SetAverageFontWidth( WIDTH_NORMAL );
|
|
else if( aInfo.width == FWIDTH_SEMI_EXPANDED )
|
|
o_rResult.SetAverageFontWidth( WIDTH_SEMI_EXPANDED );
|
|
else if( aInfo.width == FWIDTH_EXPANDED )
|
|
o_rResult.SetAverageFontWidth( WIDTH_EXPANDED );
|
|
else if( aInfo.width == FWIDTH_EXTRA_EXPANDED )
|
|
o_rResult.SetAverageFontWidth( WIDTH_EXTRA_EXPANDED );
|
|
else if( aInfo.width >= FWIDTH_ULTRA_EXPANDED )
|
|
o_rResult.SetAverageFontWidth( WIDTH_ULTRA_EXPANDED );
|
|
}
|
|
// set italic
|
|
o_rResult.SetItalic( (aInfo.italicAngle != 0) ? ITALIC_NORMAL : ITALIC_NONE );
|
|
|
|
// set pitch
|
|
o_rResult.SetPitch( (aInfo.pitch == 0) ? PITCH_VARIABLE : PITCH_FIXED );
|
|
|
|
// set style name
|
|
if( !aInfo.usubfamily.isEmpty() )
|
|
o_rResult.SetStyleName( aInfo.usubfamily );
|
|
else if( !aInfo.subfamily.isEmpty() )
|
|
o_rResult.SetStyleName( OUString::createFromAscii( aInfo.subfamily ) );
|
|
|
|
// cleanup
|
|
CloseTTFont( pTTF );
|
|
// success
|
|
bResult = true;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
struct WeightSearchEntry
|
|
{
|
|
const char* string;
|
|
int string_len;
|
|
FontWeight weight;
|
|
|
|
bool operator<( const WeightSearchEntry& rRight ) const
|
|
{
|
|
return rtl_str_compareIgnoreAsciiCase_WithLength( string, string_len, rRight.string, rRight.string_len ) < 0;
|
|
}
|
|
}
|
|
const weight_table[] =
|
|
{
|
|
{ "black", 5, WEIGHT_BLACK },
|
|
{ "bold", 4, WEIGHT_BOLD },
|
|
{ "book", 4, WEIGHT_LIGHT },
|
|
{ "demi", 4, WEIGHT_SEMIBOLD },
|
|
{ "heavy", 5, WEIGHT_BLACK },
|
|
{ "light", 5, WEIGHT_LIGHT },
|
|
{ "medium", 6, WEIGHT_MEDIUM },
|
|
{ "regular", 7, WEIGHT_NORMAL },
|
|
{ "super", 5, WEIGHT_ULTRABOLD },
|
|
{ "thin", 4, WEIGHT_THIN }
|
|
};
|
|
|
|
bool identifyType1Font( const char* i_pBuffer, sal_uInt32 i_nSize, Font& o_rResult )
|
|
{
|
|
// might be a type1, find eexec
|
|
const char* pStream = i_pBuffer;
|
|
const char* const pExec = "eexec";
|
|
const char* pExecPos = std::search( pStream, pStream+i_nSize, pExec, pExec+5 );
|
|
if( pExecPos != pStream+i_nSize)
|
|
{
|
|
// find /FamilyName entry
|
|
static const char* const pFam = "/FamilyName";
|
|
const char* pFamPos = std::search( pStream, pExecPos, pFam, pFam+11 );
|
|
if( pFamPos != pExecPos )
|
|
{
|
|
// extract the string value behind /FamilyName
|
|
const char* pOpen = pFamPos+11;
|
|
while( pOpen < pExecPos && *pOpen != '(' )
|
|
pOpen++;
|
|
const char* pClose = pOpen;
|
|
while( pClose < pExecPos && *pClose != ')' )
|
|
pClose++;
|
|
if( pClose - pOpen > 1 )
|
|
{
|
|
o_rResult.SetFamilyName( OStringToOUString( std::string_view( pOpen+1, pClose-pOpen-1 ), RTL_TEXTENCODING_ASCII_US ) );
|
|
}
|
|
}
|
|
|
|
// parse /ItalicAngle
|
|
static const char* const pItalic = "/ItalicAngle";
|
|
const char* pItalicPos = std::search( pStream, pExecPos, pItalic, pItalic+12 );
|
|
if( pItalicPos != pExecPos )
|
|
{
|
|
const char* pItalicEnd = pItalicPos + 12;
|
|
auto nItalic = rtl_str_toInt64_WithLength(pItalicEnd, 10, pExecPos - pItalicEnd);
|
|
o_rResult.SetItalic( (nItalic != 0) ? ITALIC_NORMAL : ITALIC_NONE );
|
|
}
|
|
|
|
// parse /Weight
|
|
static const char* const pWeight = "/Weight";
|
|
const char* pWeightPos = std::search( pStream, pExecPos, pWeight, pWeight+7 );
|
|
if( pWeightPos != pExecPos )
|
|
{
|
|
// extract the string value behind /Weight
|
|
const char* pOpen = pWeightPos+7;
|
|
while( pOpen < pExecPos && *pOpen != '(' )
|
|
pOpen++;
|
|
const char* pClose = pOpen;
|
|
while( pClose < pExecPos && *pClose != ')' )
|
|
pClose++;
|
|
if( pClose - pOpen > 1 )
|
|
{
|
|
WeightSearchEntry aEnt;
|
|
aEnt.string = pOpen+1;
|
|
aEnt.string_len = (pClose-pOpen)-1;
|
|
aEnt.weight = WEIGHT_NORMAL;
|
|
WeightSearchEntry const * pFound = std::lower_bound( std::begin(weight_table), std::end(weight_table), aEnt );
|
|
if( pFound != std::end(weight_table) &&
|
|
rtl_str_compareIgnoreAsciiCase_WithLength( pFound->string, pFound->string_len, aEnt.string, aEnt.string_len) == 0 )
|
|
o_rResult.SetWeight( pFound->weight );
|
|
}
|
|
}
|
|
|
|
// parse isFixedPitch
|
|
static const char* const pFixed = "/isFixedPitch";
|
|
const char* pFixedPos = std::search( pStream, pExecPos, pFixed, pFixed+13 );
|
|
if( pFixedPos != pExecPos )
|
|
{
|
|
// skip whitespace
|
|
while( pFixedPos < pExecPos-4 &&
|
|
( *pFixedPos == ' ' ||
|
|
*pFixedPos == '\t' ||
|
|
*pFixedPos == '\r' ||
|
|
*pFixedPos == '\n' ) )
|
|
{
|
|
pFixedPos++;
|
|
}
|
|
// find "true" value
|
|
if( rtl_str_compareIgnoreAsciiCase_WithLength( pFixedPos, 4, "true", 4 ) == 0 )
|
|
o_rResult.SetPitch( PITCH_FIXED );
|
|
else
|
|
o_rResult.SetPitch( PITCH_VARIABLE );
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Font Font::identifyFont( const void* i_pBuffer, sal_uInt32 i_nSize )
|
|
{
|
|
Font aResult;
|
|
if( ! identifyTrueTypeFont( i_pBuffer, i_nSize, aResult ) )
|
|
{
|
|
const char* pStream = static_cast<const char*>(i_pBuffer);
|
|
if( pStream && i_nSize > 100 &&
|
|
*pStream == '%' && pStream[1] == '!' )
|
|
{
|
|
identifyType1Font( pStream, i_nSize, aResult );
|
|
}
|
|
}
|
|
|
|
return aResult;
|
|
}
|
|
|
|
// The inlines from the font.hxx header are now instantiated for pImpl-ification
|
|
const Color& Font::GetColor() const { return mpImplFont->maColor; }
|
|
const Color& Font::GetFillColor() const { return mpImplFont->maFillColor; }
|
|
bool Font::IsTransparent() const { return mpImplFont->mbTransparent; }
|
|
|
|
TextAlign Font::GetAlignment() const { return mpImplFont->GetAlignment(); }
|
|
|
|
const OUString& Font::GetFamilyName() const { return mpImplFont->GetFamilyName(); }
|
|
const OUString& Font::GetStyleName() const { return mpImplFont->maStyleName; }
|
|
const FontFamily& Font::GetFontFamily() const { return mpImplFont->meFamily; }
|
|
|
|
const Size& Font::GetFontSize() const { return mpImplFont->GetFontSize(); }
|
|
void Font::SetFontHeight( tools::Long nHeight ) { SetFontSize( Size( std::as_const(mpImplFont)->GetFontSize().Width(), nHeight ) ); }
|
|
tools::Long Font::GetFontHeight() const { return mpImplFont->GetFontSize().Height(); }
|
|
void Font::SetAverageFontWidth( tools::Long nWidth ) { SetFontSize( Size( nWidth, std::as_const(mpImplFont)->GetFontSize().Height() ) ); }
|
|
tools::Long Font::GetAverageFontWidth() const { return mpImplFont->GetFontSize().Width(); }
|
|
const Size& Font::GetAverageFontSize() const { return mpImplFont->maAverageFontSize; }
|
|
|
|
rtl_TextEncoding Font::GetCharSet() const { return mpImplFont->GetCharSet(); }
|
|
|
|
const LanguageTag& Font::GetLanguageTag() const { return mpImplFont->maLanguageTag; }
|
|
const LanguageTag& Font::GetCJKContextLanguageTag() const { return mpImplFont->maCJKLanguageTag; }
|
|
LanguageType Font::GetLanguage() const { return mpImplFont->maLanguageTag.getLanguageType( false); }
|
|
LanguageType Font::GetCJKContextLanguage() const { return mpImplFont->maCJKLanguageTag.getLanguageType( false); }
|
|
|
|
Degree10 Font::GetOrientation() const { return mpImplFont->mnOrientation; }
|
|
bool Font::IsVertical() const { return mpImplFont->mbVertical; }
|
|
FontKerning Font::GetKerning() const { return mpImplFont->meKerning; }
|
|
|
|
FontPitch Font::GetPitch() { return mpImplFont->GetPitch(); }
|
|
FontWeight Font::GetWeight() { return mpImplFont->GetWeight(); }
|
|
FontWidth Font::GetWidthType() { return mpImplFont->GetWidthType(); }
|
|
FontItalic Font::GetItalic() { return mpImplFont->GetItalic(); }
|
|
FontFamily Font::GetFamilyType() { return mpImplFont->GetFamilyType(); }
|
|
|
|
FontPitch Font::GetPitch() const { return mpImplFont->GetPitchNoAsk(); }
|
|
FontWeight Font::GetWeight() const { return mpImplFont->GetWeightNoAsk(); }
|
|
FontWidth Font::GetWidthType() const { return mpImplFont->GetWidthTypeNoAsk(); }
|
|
FontItalic Font::GetItalic() const { return mpImplFont->GetItalicNoAsk(); }
|
|
FontFamily Font::GetFamilyType() const { return mpImplFont->GetFamilyTypeNoAsk(); }
|
|
|
|
int Font::GetQuality() const { return mpImplFont->GetQuality(); }
|
|
void Font::SetQuality( int nQuality ) { mpImplFont->SetQuality( nQuality ); }
|
|
void Font::IncreaseQualityBy( int nQualityAmount ) { mpImplFont->IncreaseQualityBy( nQualityAmount ); }
|
|
void Font::DecreaseQualityBy( int nQualityAmount ) { mpImplFont->DecreaseQualityBy( nQualityAmount ); }
|
|
|
|
bool Font::IsOutline() const { return mpImplFont->mbOutline; }
|
|
bool Font::IsShadow() const { return mpImplFont->mbShadow; }
|
|
FontRelief Font::GetRelief() const { return mpImplFont->meRelief; }
|
|
FontLineStyle Font::GetUnderline() const { return mpImplFont->meUnderline; }
|
|
FontLineStyle Font::GetOverline() const { return mpImplFont->meOverline; }
|
|
FontStrikeout Font::GetStrikeout() const { return mpImplFont->meStrikeout; }
|
|
FontEmphasisMark Font::GetEmphasisMark() const { return mpImplFont->meEmphasisMark; }
|
|
bool Font::IsWordLineMode() const { return mpImplFont->mbWordLine; }
|
|
bool Font::IsSameInstance( const vcl::Font& rFont ) const { return (mpImplFont == rFont.mpImplFont); }
|
|
|
|
|
|
ImplFont::ImplFont() :
|
|
meWeight( WEIGHT_DONTKNOW ),
|
|
meFamily( FAMILY_DONTKNOW ),
|
|
mePitch( PITCH_DONTKNOW ),
|
|
meWidthType( WIDTH_DONTKNOW ),
|
|
meItalic( ITALIC_NONE ),
|
|
meAlign( ALIGN_TOP ),
|
|
meUnderline( LINESTYLE_NONE ),
|
|
meOverline( LINESTYLE_NONE ),
|
|
meStrikeout( STRIKEOUT_NONE ),
|
|
meRelief( FontRelief::NONE ),
|
|
meEmphasisMark( FontEmphasisMark::NONE ),
|
|
meKerning( FontKerning::FontSpecific ),
|
|
mnSpacing( 0 ),
|
|
meCharSet( RTL_TEXTENCODING_DONTKNOW ),
|
|
maLanguageTag( LANGUAGE_DONTKNOW ),
|
|
maCJKLanguageTag( LANGUAGE_DONTKNOW ),
|
|
mbOutline( false ),
|
|
mbConfigLookup( false ),
|
|
mbShadow( false ),
|
|
mbVertical( false ),
|
|
mbTransparent( true ),
|
|
maColor( COL_TRANSPARENT ),
|
|
maFillColor( COL_TRANSPARENT ),
|
|
mbWordLine( false ),
|
|
mnOrientation( 0 ),
|
|
mnQuality( 0 ),
|
|
mnCalculatedAverageFontWidth( 0 )
|
|
{}
|
|
|
|
ImplFont::ImplFont( const ImplFont& rImplFont ) :
|
|
maFamilyName( rImplFont.maFamilyName ),
|
|
maStyleName( rImplFont.maStyleName ),
|
|
meWeight( rImplFont.meWeight ),
|
|
meFamily( rImplFont.meFamily ),
|
|
mePitch( rImplFont.mePitch ),
|
|
meWidthType( rImplFont.meWidthType ),
|
|
meItalic( rImplFont.meItalic ),
|
|
meAlign( rImplFont.meAlign ),
|
|
meUnderline( rImplFont.meUnderline ),
|
|
meOverline( rImplFont.meOverline ),
|
|
meStrikeout( rImplFont.meStrikeout ),
|
|
meRelief( rImplFont.meRelief ),
|
|
meEmphasisMark( rImplFont.meEmphasisMark ),
|
|
meKerning( rImplFont.meKerning ),
|
|
mnSpacing( rImplFont.mnSpacing ),
|
|
maAverageFontSize( rImplFont.maAverageFontSize ),
|
|
meCharSet( rImplFont.meCharSet ),
|
|
maLanguageTag( rImplFont.maLanguageTag ),
|
|
maCJKLanguageTag( rImplFont.maCJKLanguageTag ),
|
|
mbOutline( rImplFont.mbOutline ),
|
|
mbConfigLookup( rImplFont.mbConfigLookup ),
|
|
mbShadow( rImplFont.mbShadow ),
|
|
mbVertical( rImplFont.mbVertical ),
|
|
mbTransparent( rImplFont.mbTransparent ),
|
|
maColor( rImplFont.maColor ),
|
|
maFillColor( rImplFont.maFillColor ),
|
|
mbWordLine( rImplFont.mbWordLine ),
|
|
mnOrientation( rImplFont.mnOrientation ),
|
|
mnQuality( rImplFont.mnQuality ),
|
|
mnCalculatedAverageFontWidth( rImplFont.mnCalculatedAverageFontWidth )
|
|
{}
|
|
|
|
bool ImplFont::operator==( const ImplFont& rOther ) const
|
|
{
|
|
if(!EqualIgnoreColor( rOther ))
|
|
return false;
|
|
|
|
if( (maColor != rOther.maColor)
|
|
|| (maFillColor != rOther.maFillColor) )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ImplFont::EqualIgnoreColor( const ImplFont& rOther ) const
|
|
{
|
|
// equality tests split up for easier debugging
|
|
if( (meWeight != rOther.meWeight)
|
|
|| (meItalic != rOther.meItalic)
|
|
|| (meFamily != rOther.meFamily)
|
|
|| (mePitch != rOther.mePitch) )
|
|
return false;
|
|
|
|
if( (meCharSet != rOther.meCharSet)
|
|
|| (maLanguageTag != rOther.maLanguageTag)
|
|
|| (maCJKLanguageTag != rOther.maCJKLanguageTag)
|
|
|| (meAlign != rOther.meAlign) )
|
|
return false;
|
|
|
|
if( (maAverageFontSize != rOther.maAverageFontSize)
|
|
|| (mnOrientation != rOther.mnOrientation)
|
|
|| (mbVertical != rOther.mbVertical) )
|
|
return false;
|
|
|
|
if( (maFamilyName != rOther.maFamilyName)
|
|
|| (maStyleName != rOther.maStyleName) )
|
|
return false;
|
|
|
|
if( (meUnderline != rOther.meUnderline)
|
|
|| (meOverline != rOther.meOverline)
|
|
|| (meStrikeout != rOther.meStrikeout)
|
|
|| (meRelief != rOther.meRelief)
|
|
|| (meEmphasisMark != rOther.meEmphasisMark)
|
|
|| (mbWordLine != rOther.mbWordLine)
|
|
|| (mbOutline != rOther.mbOutline)
|
|
|| (mbShadow != rOther.mbShadow)
|
|
|| (meKerning != rOther.meKerning)
|
|
|| (mnSpacing != rOther.mnSpacing)
|
|
|| (mbTransparent != rOther.mbTransparent) )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
size_t ImplFont::GetHashValue() const
|
|
{
|
|
size_t hash = GetHashValueIgnoreColor();
|
|
o3tl::hash_combine( hash, static_cast<sal_uInt32>( maColor ));
|
|
o3tl::hash_combine( hash, static_cast<sal_uInt32>( maFillColor ));
|
|
return hash;
|
|
}
|
|
|
|
size_t ImplFont::GetHashValueIgnoreColor() const
|
|
{
|
|
size_t hash = 0;
|
|
|
|
o3tl::hash_combine( hash, meWeight );
|
|
o3tl::hash_combine( hash, meItalic );
|
|
o3tl::hash_combine( hash, meFamily );
|
|
o3tl::hash_combine( hash, mePitch );
|
|
|
|
o3tl::hash_combine( hash, meCharSet );
|
|
o3tl::hash_combine( hash, maLanguageTag.getLanguageType( false ).get());
|
|
o3tl::hash_combine( hash, maCJKLanguageTag.getLanguageType( false ).get());
|
|
o3tl::hash_combine( hash, meAlign );
|
|
|
|
o3tl::hash_combine( hash, maAverageFontSize.GetHashValue());
|
|
o3tl::hash_combine( hash, mnOrientation.get());
|
|
o3tl::hash_combine( hash, mbVertical );
|
|
|
|
o3tl::hash_combine( hash, maFamilyName );
|
|
o3tl::hash_combine( hash, maStyleName );
|
|
|
|
o3tl::hash_combine( hash, meUnderline );
|
|
o3tl::hash_combine( hash, meOverline );
|
|
o3tl::hash_combine( hash, meStrikeout );
|
|
o3tl::hash_combine( hash, meRelief );
|
|
o3tl::hash_combine( hash, meEmphasisMark );
|
|
o3tl::hash_combine( hash, mbWordLine );
|
|
o3tl::hash_combine( hash, mbOutline );
|
|
o3tl::hash_combine( hash, mbShadow );
|
|
o3tl::hash_combine( hash, meKerning );
|
|
o3tl::hash_combine( hash, mnSpacing );
|
|
o3tl::hash_combine( hash, mbTransparent );
|
|
|
|
return hash;
|
|
}
|
|
|
|
void ImplFont::AskConfig()
|
|
{
|
|
if( mbConfigLookup )
|
|
return;
|
|
|
|
mbConfigLookup = true;
|
|
|
|
// prepare the FontSubst configuration lookup
|
|
const utl::FontSubstConfiguration& rFontSubst = utl::FontSubstConfiguration::get();
|
|
|
|
OUString aShortName;
|
|
OUString aFamilyName;
|
|
ImplFontAttrs nType = ImplFontAttrs::None;
|
|
FontWeight eWeight = WEIGHT_DONTKNOW;
|
|
FontWidth eWidthType = WIDTH_DONTKNOW;
|
|
OUString aMapName = GetEnglishSearchFontName( maFamilyName );
|
|
|
|
utl::FontSubstConfiguration::getMapName( aMapName,
|
|
aShortName, aFamilyName, eWeight, eWidthType, nType );
|
|
|
|
// lookup the font name in the configuration
|
|
const utl::FontNameAttr* pFontAttr = rFontSubst.getSubstInfo( aMapName );
|
|
|
|
// if the direct lookup failed try again with an alias name
|
|
if ( !pFontAttr && (aShortName != aMapName) )
|
|
pFontAttr = rFontSubst.getSubstInfo( aShortName );
|
|
|
|
if( pFontAttr )
|
|
{
|
|
// the font was found in the configuration
|
|
if( meFamily == FAMILY_DONTKNOW )
|
|
{
|
|
if ( pFontAttr->Type & ImplFontAttrs::Serif )
|
|
meFamily = FAMILY_ROMAN;
|
|
else if ( pFontAttr->Type & ImplFontAttrs::SansSerif )
|
|
meFamily = FAMILY_SWISS;
|
|
else if ( pFontAttr->Type & ImplFontAttrs::Typewriter )
|
|
meFamily = FAMILY_MODERN;
|
|
else if ( pFontAttr->Type & ImplFontAttrs::Italic )
|
|
meFamily = FAMILY_SCRIPT;
|
|
else if ( pFontAttr->Type & ImplFontAttrs::Decorative )
|
|
meFamily = FAMILY_DECORATIVE;
|
|
}
|
|
|
|
if( mePitch == PITCH_DONTKNOW )
|
|
{
|
|
if ( pFontAttr->Type & ImplFontAttrs::Fixed )
|
|
mePitch = PITCH_FIXED;
|
|
}
|
|
}
|
|
|
|
// if some attributes are still unknown then use the FontSubst magic
|
|
if( meFamily == FAMILY_DONTKNOW )
|
|
{
|
|
if( nType & ImplFontAttrs::Serif )
|
|
meFamily = FAMILY_ROMAN;
|
|
else if( nType & ImplFontAttrs::SansSerif )
|
|
meFamily = FAMILY_SWISS;
|
|
else if( nType & ImplFontAttrs::Typewriter )
|
|
meFamily = FAMILY_MODERN;
|
|
else if( nType & ImplFontAttrs::Italic )
|
|
meFamily = FAMILY_SCRIPT;
|
|
else if( nType & ImplFontAttrs::Decorative )
|
|
meFamily = FAMILY_DECORATIVE;
|
|
}
|
|
|
|
if( GetWeight() == WEIGHT_DONTKNOW )
|
|
SetWeight( eWeight );
|
|
if( meWidthType == WIDTH_DONTKNOW )
|
|
meWidthType = eWidthType;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|