/************************************************************** * * 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 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_vcl.hxx" #include "unotools/fontcfg.hxx" #include "tools/stream.hxx" #include "tools/vcompat.hxx" #include "tools/debug.hxx" #include "vcl/font.hxx" #include "impfont.hxx" #include "outfont.hxx" #include "sft.hxx" #include using namespace vcl; // ======================================================================= DBG_NAME( Font ) // ----------------------------------------------------------------------- Impl_Font::Impl_Font() : maColor( COL_TRANSPARENT ), maFillColor( COL_TRANSPARENT ) { mnRefCount = 1; meCharSet = RTL_TEXTENCODING_DONTKNOW; meLanguage = LANGUAGE_DONTKNOW; meCJKLanguage = LANGUAGE_DONTKNOW; meFamily = FAMILY_DONTKNOW; mePitch = PITCH_DONTKNOW; meAlign = ALIGN_TOP; meWeight = WEIGHT_DONTKNOW; meWidthType = WIDTH_DONTKNOW; meItalic = ITALIC_NONE; meUnderline = UNDERLINE_NONE; meOverline = UNDERLINE_NONE; meStrikeout = STRIKEOUT_NONE; meRelief = RELIEF_NONE; meEmphasisMark = EMPHASISMARK_NONE; mnOrientation = 0; mnKerning = 0; mbWordLine = false; mbOutline = false; mbShadow = false; mbVertical = false; mbTransparent = true; mbConfigLookup = false; } // ----------------------------------------------------------------------- Impl_Font::Impl_Font( const Impl_Font& rImplFont ) : maFamilyName( rImplFont.maFamilyName ), maStyleName( rImplFont.maStyleName ), maSize( rImplFont.maSize ), maColor( rImplFont.maColor ), maFillColor( rImplFont.maFillColor ) { mnRefCount = 1; meCharSet = rImplFont.meCharSet; meLanguage = rImplFont.meLanguage; meCJKLanguage = rImplFont.meCJKLanguage; meFamily = rImplFont.meFamily; mePitch = rImplFont.mePitch; meAlign = rImplFont.meAlign; meWeight = rImplFont.meWeight; meWidthType = rImplFont.meWidthType; meItalic = rImplFont.meItalic; meUnderline = rImplFont.meUnderline; meOverline = rImplFont.meOverline; meStrikeout = rImplFont.meStrikeout; meRelief = rImplFont.meRelief; meEmphasisMark = rImplFont.meEmphasisMark; mnOrientation = rImplFont.mnOrientation; mnKerning = rImplFont.mnKerning; mbWordLine = rImplFont.mbWordLine; mbOutline = rImplFont.mbOutline; mbShadow = rImplFont.mbShadow; mbVertical = rImplFont.mbVertical; mbTransparent = rImplFont.mbTransparent; mbConfigLookup = rImplFont.mbConfigLookup; } // ----------------------------------------------------------------------- bool Impl_Font::operator==( const Impl_Font& 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) || (meLanguage != rOther.meLanguage) || (meCJKLanguage != rOther.meCJKLanguage) || (meAlign != rOther.meAlign) ) return false; if( (maSize != rOther.maSize) || (mnOrientation != rOther.mnOrientation) || (mbVertical != rOther.mbVertical) ) return false; if( (maFamilyName != rOther.maFamilyName) || (maStyleName != rOther.maStyleName) ) return false; if( (maColor != rOther.maColor) || (maFillColor != rOther.maFillColor) ) 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) || (mnKerning != rOther.mnKerning) || (mbTransparent != rOther.mbTransparent) ) return false; return true; } // ----------------------------------------------------------------------- void Impl_Font::AskConfig() { if( mbConfigLookup ) return; mbConfigLookup = true; // prepare the FontSubst configuration lookup const utl::FontSubstConfiguration* pFontSubst = utl::FontSubstConfiguration::get(); String aShortName; String aFamilyName; sal_uLong nType = 0; FontWeight eWeight = WEIGHT_DONTKNOW; FontWidth eWidthType = WIDTH_DONTKNOW; String aMapName = maFamilyName; GetEnglishSearchFontName( aMapName ); utl::FontSubstConfiguration::getMapName( aMapName, aShortName, aFamilyName, eWeight, eWidthType, nType ); // lookup the font name in the configuration const utl::FontNameAttr* pFontAttr = pFontSubst->getSubstInfo( aMapName ); // if the direct lookup failed try again with an alias name if ( !pFontAttr && (aShortName != aMapName) ) pFontAttr = pFontSubst->getSubstInfo( aShortName ); if( pFontAttr ) { // the font was found in the configuration if( meFamily == FAMILY_DONTKNOW ) { if ( pFontAttr->Type & IMPL_FONT_ATTR_SERIF ) meFamily = FAMILY_ROMAN; else if ( pFontAttr->Type & IMPL_FONT_ATTR_SANSSERIF ) meFamily = FAMILY_SWISS; else if ( pFontAttr->Type & IMPL_FONT_ATTR_TYPEWRITER ) meFamily = FAMILY_MODERN; else if ( pFontAttr->Type & IMPL_FONT_ATTR_ITALIC ) meFamily = FAMILY_SCRIPT; else if ( pFontAttr->Type & IMPL_FONT_ATTR_DECORATIVE ) meFamily = FAMILY_DECORATIVE; } if( mePitch == PITCH_DONTKNOW ) { if ( pFontAttr->Type & IMPL_FONT_ATTR_FIXED ) mePitch = PITCH_FIXED; } } // if some attributes are still unknown then use the FontSubst magic if( meFamily == FAMILY_DONTKNOW ) { if( nType & IMPL_FONT_ATTR_SERIF ) meFamily = FAMILY_ROMAN; else if( nType & IMPL_FONT_ATTR_SANSSERIF ) meFamily = FAMILY_SWISS; else if( nType & IMPL_FONT_ATTR_TYPEWRITER ) meFamily = FAMILY_MODERN; else if( nType & IMPL_FONT_ATTR_ITALIC ) meFamily = FAMILY_SCRIPT; else if( nType & IMPL_FONT_ATTR_DECORATIVE ) meFamily = FAMILY_DECORATIVE; } if( meWeight == WEIGHT_DONTKNOW ) meWeight = eWeight; if( meWidthType == WIDTH_DONTKNOW ) meWidthType = eWidthType; } // ======================================================================= void Font::MakeUnique() { // create a copy if others still reference it if ( mpImplFont->mnRefCount != 1 ) { if ( mpImplFont->mnRefCount ) mpImplFont->mnRefCount--; mpImplFont = new Impl_Font( *mpImplFont ); } } // ----------------------------------------------------------------------- Font::Font() { DBG_CTOR( Font, NULL ); static Impl_Font aStaticImplFont; // RefCount is zero for static objects aStaticImplFont.mnRefCount = 0; mpImplFont = &aStaticImplFont; } // ----------------------------------------------------------------------- Font::Font( const Font& rFont ) { DBG_CTOR( Font, NULL ); DBG_CHKOBJ( &rFont, Font, NULL ); DBG_ASSERT( rFont.mpImplFont->mnRefCount < 0xFFFE, "Font: RefCount overflow" ); mpImplFont = rFont.mpImplFont; // do not count static objects (where RefCount is zero) if ( mpImplFont->mnRefCount ) mpImplFont->mnRefCount++; } // ----------------------------------------------------------------------- Font::Font( const String& rFamilyName, const Size& rSize ) { DBG_CTOR( Font, NULL ); mpImplFont = new Impl_Font; mpImplFont->maFamilyName= rFamilyName; mpImplFont->maSize = rSize; } // ----------------------------------------------------------------------- Font::Font( const String& rFamilyName, const String& rStyleName, const Size& rSize ) { DBG_CTOR( Font, NULL ); mpImplFont = new Impl_Font; mpImplFont->maFamilyName= rFamilyName; mpImplFont->maStyleName = rStyleName; mpImplFont->maSize = rSize; } // ----------------------------------------------------------------------- Font::Font( FontFamily eFamily, const Size& rSize ) { DBG_CTOR( Font, NULL ); mpImplFont = new Impl_Font; mpImplFont->meFamily = eFamily; mpImplFont->maSize = rSize; } // ----------------------------------------------------------------------- Font::~Font() { DBG_DTOR( Font, NULL ); // decrement reference counter and delete if last reference // if the object is not static (Refcounter==0) if ( mpImplFont->mnRefCount ) { if ( mpImplFont->mnRefCount == 1 ) delete mpImplFont; else mpImplFont->mnRefCount--; } } // ----------------------------------------------------------------------- void Font::SetColor( const Color& rColor ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->maColor != rColor ) { MakeUnique(); mpImplFont->maColor = rColor; } } // ----------------------------------------------------------------------- void Font::SetFillColor( const Color& rColor ) { DBG_CHKTHIS( Font, NULL ); MakeUnique(); mpImplFont->maFillColor = rColor; if ( rColor.GetTransparency() ) mpImplFont->mbTransparent = true; } // ----------------------------------------------------------------------- void Font::SetTransparent( sal_Bool bTransparent ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->mbTransparent != bTransparent ) { MakeUnique(); mpImplFont->mbTransparent = bTransparent; } } // ----------------------------------------------------------------------- void Font::SetAlign( FontAlign eAlign ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meAlign != eAlign ) { MakeUnique(); mpImplFont->meAlign = eAlign; } } // ----------------------------------------------------------------------- void Font::SetName( const String& rFamilyName ) { DBG_CHKTHIS( Font, NULL ); MakeUnique(); mpImplFont->maFamilyName = rFamilyName; } // ----------------------------------------------------------------------- void Font::SetStyleName( const String& rStyleName ) { DBG_CHKTHIS( Font, NULL ); MakeUnique(); mpImplFont->maStyleName = rStyleName; } // ----------------------------------------------------------------------- void Font::SetSize( const Size& rSize ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->maSize != rSize ) { MakeUnique(); mpImplFont->maSize = rSize; } } // ----------------------------------------------------------------------- void Font::SetFamily( FontFamily eFamily ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meFamily != eFamily ) { MakeUnique(); mpImplFont->meFamily = eFamily; } } // ----------------------------------------------------------------------- void Font::SetCharSet( CharSet eCharSet ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meCharSet != eCharSet ) { MakeUnique(); mpImplFont->meCharSet = eCharSet; } } // ----------------------------------------------------------------------- void Font::SetLanguage( LanguageType eLanguage ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meLanguage != eLanguage ) { MakeUnique(); mpImplFont->meLanguage = eLanguage; } } // ----------------------------------------------------------------------- void Font::SetCJKContextLanguage( LanguageType eLanguage ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meCJKLanguage != eLanguage ) { MakeUnique(); mpImplFont->meCJKLanguage = eLanguage; } } // ----------------------------------------------------------------------- void Font::SetPitch( FontPitch ePitch ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->mePitch != ePitch ) { MakeUnique(); mpImplFont->mePitch = ePitch; } } // ----------------------------------------------------------------------- void Font::SetOrientation( short nOrientation ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->mnOrientation != nOrientation ) { MakeUnique(); mpImplFont->mnOrientation = nOrientation; } } // ----------------------------------------------------------------------- void Font::SetVertical( sal_Bool bVertical ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->mbVertical != bVertical ) { MakeUnique(); mpImplFont->mbVertical = bVertical; } } // ----------------------------------------------------------------------- void Font::SetKerning( FontKerning nKerning ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->mnKerning != nKerning ) { MakeUnique(); mpImplFont->mnKerning = nKerning; } } // ----------------------------------------------------------------------- sal_Bool Font::IsKerning() const { return (mpImplFont->mnKerning & KERNING_FONTSPECIFIC) != 0; } // ----------------------------------------------------------------------- void Font::SetWeight( FontWeight eWeight ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meWeight != eWeight ) { MakeUnique(); mpImplFont->meWeight = eWeight; } } // ----------------------------------------------------------------------- void Font::SetWidthType( FontWidth eWidth ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meWidthType != eWidth ) { MakeUnique(); mpImplFont->meWidthType = eWidth; } } // ----------------------------------------------------------------------- void Font::SetItalic( FontItalic eItalic ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meItalic != eItalic ) { MakeUnique(); mpImplFont->meItalic = eItalic; } } // ----------------------------------------------------------------------- void Font::SetOutline( sal_Bool bOutline ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->mbOutline != bOutline ) { MakeUnique(); mpImplFont->mbOutline = bOutline; } } // ----------------------------------------------------------------------- void Font::SetShadow( sal_Bool bShadow ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->mbShadow != bShadow ) { MakeUnique(); mpImplFont->mbShadow = bShadow; } } // ----------------------------------------------------------------------- void Font::SetUnderline( FontUnderline eUnderline ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meUnderline != eUnderline ) { MakeUnique(); mpImplFont->meUnderline = eUnderline; } } // ----------------------------------------------------------------------- void Font::SetOverline( FontUnderline eOverline ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meOverline != eOverline ) { MakeUnique(); mpImplFont->meOverline = eOverline; } } // ----------------------------------------------------------------------- void Font::SetStrikeout( FontStrikeout eStrikeout ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meStrikeout != eStrikeout ) { MakeUnique(); mpImplFont->meStrikeout = eStrikeout; } } // ----------------------------------------------------------------------- void Font::SetRelief( FontRelief eRelief ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meRelief != eRelief ) { MakeUnique(); mpImplFont->meRelief = eRelief; } } // ----------------------------------------------------------------------- void Font::SetEmphasisMark( FontEmphasisMark eEmphasisMark ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->meEmphasisMark != eEmphasisMark ) { MakeUnique(); mpImplFont->meEmphasisMark = eEmphasisMark; } } // ----------------------------------------------------------------------- void Font::SetWordLineMode( sal_Bool bWordLine ) { DBG_CHKTHIS( Font, NULL ); if( mpImplFont->mbWordLine != bWordLine ) { MakeUnique(); mpImplFont->mbWordLine = bWordLine; } } // ----------------------------------------------------------------------- Font& Font::operator=( const Font& rFont ) { DBG_CHKTHIS( Font, NULL ); DBG_CHKOBJ( &rFont, Font, NULL ); DBG_ASSERT( rFont.mpImplFont->mnRefCount < 0xFFFE, "Font: RefCount overflow" ); // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann // RefCount == 0 fuer statische Objekte if ( rFont.mpImplFont->mnRefCount ) rFont.mpImplFont->mnRefCount++; // Wenn es keine statischen ImplDaten sind, dann loeschen, wenn es // die letzte Referenz ist, sonst Referenzcounter decrementieren if ( mpImplFont->mnRefCount ) { if ( mpImplFont->mnRefCount == 1 ) delete mpImplFont; else mpImplFont->mnRefCount--; } mpImplFont = rFont.mpImplFont; return *this; } // ----------------------------------------------------------------------- sal_Bool Font::operator==( const Font& rFont ) const { DBG_CHKTHIS( Font, NULL ); DBG_CHKOBJ( &rFont, Font, NULL ); if( mpImplFont == rFont.mpImplFont ) return sal_True; if( *mpImplFont == *rFont.mpImplFont ) return sal_True; return sal_False; } // ----------------------------------------------------------------------- void Font::Merge( const Font& rFont ) { if ( rFont.GetName().Len() ) { SetName( rFont.GetName() ); SetStyleName( rFont.GetStyleName() ); SetCharSet( GetCharSet() ); SetLanguage( rFont.GetLanguage() ); SetCJKContextLanguage( rFont.GetCJKContextLanguage() ); // don't use access methods here, might lead to AskConfig(), if DONTKNOW SetFamily( rFont.mpImplFont->meFamily ); SetPitch( rFont.mpImplFont->mePitch ); } // don't use access methods here, might lead to AskConfig(), if DONTKNOW if ( rFont.mpImplFont->meWeight != WEIGHT_DONTKNOW ) SetWeight( rFont.GetWeight() ); if ( rFont.mpImplFont->meItalic != ITALIC_DONTKNOW ) SetItalic( rFont.GetItalic() ); if ( rFont.mpImplFont->meWidthType != WIDTH_DONTKNOW ) SetWidthType( rFont.GetWidthType() ); if ( rFont.GetSize().Height() ) SetSize( rFont.GetSize() ); if ( rFont.GetUnderline() != UNDERLINE_DONTKNOW ) { SetUnderline( rFont.GetUnderline() ); SetWordLineMode( rFont.IsWordLineMode() ); } if ( rFont.GetOverline() != UNDERLINE_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() ); SetOutline( rFont.IsOutline() ); SetShadow( rFont.IsShadow() ); SetRelief( rFont.GetRelief() ); } void Font::GetFontAttributes( ImplFontAttributes& rAttrs ) const { // #i56788# Use members directly, don't risc config access. rAttrs.maName = mpImplFont->maFamilyName; rAttrs.maStyleName = mpImplFont->maStyleName; rAttrs.meFamily = mpImplFont->meFamily; rAttrs.mePitch = mpImplFont->mePitch; rAttrs.meItalic = mpImplFont->meItalic; rAttrs.meWeight = mpImplFont->meWeight; rAttrs.meWidthType = WIDTH_DONTKNOW; rAttrs.mbSymbolFlag= (mpImplFont->meCharSet == RTL_TEXTENCODING_SYMBOL); } // ----------------------------------------------------------------------- SvStream& operator>>( SvStream& rIStm, Impl_Font& rImpl_Font ) { VersionCompat aCompat( rIStm, STREAM_READ ); sal_uInt16 nTmp16; sal_Bool bTmp; sal_uInt8 nTmp8; rIStm.ReadByteString( rImpl_Font.maFamilyName, rIStm.GetStreamCharSet() ); rIStm.ReadByteString( rImpl_Font.maStyleName, rIStm.GetStreamCharSet() ); rIStm >> rImpl_Font.maSize; rIStm >> nTmp16; rImpl_Font.meCharSet = (rtl_TextEncoding) nTmp16; rIStm >> nTmp16; rImpl_Font.meFamily = (FontFamily) nTmp16; rIStm >> nTmp16; rImpl_Font.mePitch = (FontPitch) nTmp16; rIStm >> nTmp16; rImpl_Font.meWeight = (FontWeight) nTmp16; rIStm >> nTmp16; rImpl_Font.meUnderline = (FontUnderline) nTmp16; rIStm >> nTmp16; rImpl_Font.meStrikeout = (FontStrikeout) nTmp16; rIStm >> nTmp16; rImpl_Font.meItalic = (FontItalic) nTmp16; rIStm >> nTmp16; rImpl_Font.meLanguage = (LanguageType) nTmp16; rIStm >> nTmp16; rImpl_Font.meWidthType = (FontWidth) nTmp16; rIStm >> rImpl_Font.mnOrientation; rIStm >> bTmp; rImpl_Font.mbWordLine = bTmp; rIStm >> bTmp; rImpl_Font.mbOutline = bTmp; rIStm >> bTmp; rImpl_Font.mbShadow = bTmp; rIStm >> nTmp8; rImpl_Font.mnKerning = nTmp8; if( aCompat.GetVersion() >= 2 ) { rIStm >> nTmp8; rImpl_Font.meRelief = (FontRelief)nTmp8; rIStm >> nTmp16; rImpl_Font.meCJKLanguage = (LanguageType)nTmp16; rIStm >> bTmp; rImpl_Font.mbVertical = bTmp; rIStm >> nTmp16; rImpl_Font.meEmphasisMark = (FontEmphasisMark)nTmp16; } if( aCompat.GetVersion() >= 3 ) { rIStm >> nTmp16; rImpl_Font.meOverline = (FontUnderline) nTmp16; } // Relief // CJKContextLanguage return rIStm; } // ----------------------------------------------------------------------- SvStream& operator<<( SvStream& rOStm, const Impl_Font& rImpl_Font ) { VersionCompat aCompat( rOStm, STREAM_WRITE, 3 ); rOStm.WriteByteString( rImpl_Font.maFamilyName, rOStm.GetStreamCharSet() ); rOStm.WriteByteString( rImpl_Font.maStyleName, rOStm.GetStreamCharSet() ); rOStm << rImpl_Font.maSize; rOStm << (sal_uInt16) GetStoreCharSet( rImpl_Font.meCharSet ); rOStm << (sal_uInt16) rImpl_Font.meFamily; rOStm << (sal_uInt16) rImpl_Font.mePitch; rOStm << (sal_uInt16) rImpl_Font.meWeight; rOStm << (sal_uInt16) rImpl_Font.meUnderline; rOStm << (sal_uInt16) rImpl_Font.meStrikeout; rOStm << (sal_uInt16) rImpl_Font.meItalic; rOStm << (sal_uInt16) rImpl_Font.meLanguage; rOStm << (sal_uInt16) rImpl_Font.meWidthType; rOStm << rImpl_Font.mnOrientation; rOStm << (sal_Bool) rImpl_Font.mbWordLine; rOStm << (sal_Bool) rImpl_Font.mbOutline; rOStm << (sal_Bool) rImpl_Font.mbShadow; rOStm << (sal_uInt8) rImpl_Font.mnKerning; // new in version 2 rOStm << (sal_uInt8) rImpl_Font.meRelief; rOStm << (sal_uInt16) rImpl_Font.meCJKLanguage; rOStm << (sal_Bool) rImpl_Font.mbVertical; rOStm << (sal_uInt16) rImpl_Font.meEmphasisMark; // new in version 3 rOStm << (sal_uInt16) rImpl_Font.meOverline; return rOStm; } // ----------------------------------------------------------------------- SvStream& operator>>( SvStream& rIStm, Font& rFont ) { rFont.MakeUnique(); return( rIStm >> *rFont.mpImplFont ); } // ----------------------------------------------------------------------- SvStream& operator<<( SvStream& rOStm, const Font& rFont ) { return( rOStm << *rFont.mpImplFont ); } // ----------------------------------------------------------------------- namespace { bool identifyTrueTypeFont( const void* i_pBuffer, sal_uInt32 i_nSize, Font& o_rResult ) { bool bResult = false; TrueTypeFont* pTTF = NULL; if( OpenTTFontBuffer( const_cast(i_pBuffer), i_nSize, 0, &pTTF ) == SF_OK ) { TTGlobalFontInfo aInfo; GetTTGlobalFontInfo( pTTF, &aInfo ); // most important: the family name if( aInfo.ufamily ) o_rResult.SetName( aInfo.ufamily ); else if( aInfo.family ) o_rResult.SetName( rtl::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.SetWidth( WIDTH_ULTRA_CONDENSED ); else if( aInfo.width == FWIDTH_EXTRA_CONDENSED ) o_rResult.SetWidth( WIDTH_EXTRA_CONDENSED ); else if( aInfo.width == FWIDTH_CONDENSED ) o_rResult.SetWidth( WIDTH_CONDENSED ); else if( aInfo.width == FWIDTH_SEMI_CONDENSED ) o_rResult.SetWidth( WIDTH_SEMI_CONDENSED ); else if( aInfo.width == FWIDTH_NORMAL ) o_rResult.SetWidth( WIDTH_NORMAL ); else if( aInfo.width == FWIDTH_SEMI_EXPANDED ) o_rResult.SetWidth( WIDTH_SEMI_EXPANDED ); else if( aInfo.width == FWIDTH_EXPANDED ) o_rResult.SetWidth( WIDTH_EXPANDED ); else if( aInfo.width == FWIDTH_EXTRA_EXPANDED ) o_rResult.SetWidth( WIDTH_EXTRA_EXPANDED ); else if( aInfo.width >= FWIDTH_ULTRA_EXPANDED ) o_rResult.SetWidth( 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 ) o_rResult.SetStyleName( rtl::OUString( aInfo.usubfamily ) ); else if( aInfo.subfamily ) o_rResult.SetStyleName( rtl::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; } } 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 ) { bool bResult = false; // might be a type1, find eexec const char* pStream = i_pBuffer; const char* 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* 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.SetName( rtl::OStringToOUString( rtl::OString( pOpen+1, pClose-pOpen-1 ), RTL_TEXTENCODING_ASCII_US ) ); } } // parse /ItalicAngle static const char* pItalic = "/ItalicAngle"; const char* pItalicPos = std::search( pStream, pExecPos, pItalic, pItalic+12 ); if( pItalicPos != pExecPos ) { sal_Int32 nItalic = rtl_str_toInt32( pItalicPos+12, 10 ); o_rResult.SetItalic( (nItalic != 0) ? ITALIC_NORMAL : ITALIC_NONE ); } // parse /Weight static const char* 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; const int nEnt = sizeof( weight_table ) / sizeof( weight_table[0] ); WeightSearchEntry* pFound = std::lower_bound( weight_table, weight_table+nEnt, aEnt ); if( pFound != (weight_table+nEnt) ) o_rResult.SetWeight( pFound->weight ); } } // parse isFixedPitch static const char* 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 bResult; } } Font Font::identifyFont( const void* i_pBuffer, sal_uInt32 i_nSize ) { Font aResult; if( ! identifyTrueTypeFont( i_pBuffer, i_nSize, aResult ) ) { const char* pStream = reinterpret_cast(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 // TODO: reformat const Color& Font::GetColor() const { return mpImplFont->maColor; } const Color& Font::GetFillColor() const { return mpImplFont->maFillColor; } sal_Bool Font::IsTransparent() const { return mpImplFont->mbTransparent; } FontAlign Font::GetAlign() const { return mpImplFont->meAlign; } const String& Font::GetName() const { return mpImplFont->maFamilyName; } const String& Font::GetStyleName() const { return mpImplFont->maStyleName; } const Size& Font::GetSize() const { return mpImplFont->maSize; } void Font::SetHeight( long nHeight ) { SetSize( Size( mpImplFont->maSize.Width(), nHeight ) ); } long Font::GetHeight() const { return mpImplFont->maSize.Height(); } void Font::SetWidth( long nWidth ) { SetSize( Size( nWidth, mpImplFont->maSize.Height() ) ); } long Font::GetWidth() const { return mpImplFont->maSize.Width(); } rtl_TextEncoding Font::GetCharSet() const { return mpImplFont->meCharSet; } LanguageType Font::GetLanguage() const { return mpImplFont->meLanguage; } LanguageType Font::GetCJKContextLanguage() const { return mpImplFont->meCJKLanguage; } short Font::GetOrientation() const { return mpImplFont->mnOrientation; } sal_Bool Font::IsVertical() const { return mpImplFont->mbVertical; } FontKerning Font::GetKerning() const { return mpImplFont->mnKerning; } FontPitch Font::GetPitch() const { return mpImplFont->GetPitch(); } FontWeight Font::GetWeight() const { return mpImplFont->GetWeight(); } FontWidth Font::GetWidthType() const { return mpImplFont->GetWidthType(); } FontItalic Font::GetItalic() const { return mpImplFont->GetItalic(); } FontFamily Font::GetFamily() const { return mpImplFont->GetFamily(); } sal_Bool Font::IsOutline() const { return mpImplFont->mbOutline; } sal_Bool Font::IsShadow() const { return mpImplFont->mbShadow; } FontRelief Font::GetRelief() const { return mpImplFont->meRelief; } FontUnderline Font::GetUnderline() const { return mpImplFont->meUnderline; } FontUnderline Font::GetOverline() const { return mpImplFont->meOverline; } FontStrikeout Font::GetStrikeout() const { return mpImplFont->meStrikeout; } FontEmphasisMark Font::GetEmphasisMark() const { return mpImplFont->meEmphasisMark; } sal_Bool Font::IsWordLineMode() const { return mpImplFont->mbWordLine; } sal_Bool Font::IsSameInstance( const Font& rFont ) const { return (mpImplFont == rFont.mpImplFont); }