diff options
author | Kurt Zenker <kz@openoffice.org> | 2007-12-12 12:16:47 +0000 |
---|---|---|
committer | Kurt Zenker <kz@openoffice.org> | 2007-12-12 12:16:47 +0000 |
commit | 5c55c8244f607380a0f1ff45759abd66562191f0 (patch) | |
tree | a76600928ad2cf9de83dd3cc8e672bb7b1b24926 /psprint | |
parent | 34e2f289d24ed72b5f969892a6204ea561a02c79 (diff) |
INTEGRATION: CWS gfbfcfg (1.24.68); FILE MERGED
2007/12/11 13:15:59 rt 1.24.68.18: if - endif mismatch, caused by resync-merge.
2007/12/11 10:50:40 rt 1.24.68.17: if - endif mismatch, caused by resync-merge.
2007/12/03 13:24:34 hdu 1.24.68.16: #i83370# fix size of allocation for unresolved unicodes
2007/11/27 12:46:12 hdu 1.24.68.15: RESYNC: (1.24-1.26); FILE MERGED
2007/11/14 08:34:49 hdu 1.24.68.14: #i54603# include alloca header
2007/11/10 15:42:22 hdu 1.24.68.13: #i54603# fix calculation of remaining missing codes
2007/11/07 13:19:37 hdu 1.24.68.12: #i54603# forgot to commit fix for typo
2007/11/06 11:57:05 hdu 1.24.68.11: #i83284# result of FcConfigGetFonts() must not be destroyed
2007/10/22 14:45:47 hdu 1.24.68.10: #i54603# prevent older libfontconfig from crashing by preventing Application FontSet use
2007/09/26 13:33:42 hdu 1.24.68.9: #i54603# fix buildbot errors and warnings for non-fontconfig platforms
2007/09/17 13:57:14 hdu 1.24.68.8: #i54603# switch to rtl strings, support glyph fallbacks for surrogates, reintroduce update of missing codes container
2007/09/14 11:53:50 hdu 1.24.68.7: #i54603# delay fontconfig font enumeration until all appfonts are registered
2007/09/13 16:44:00 hdu 1.24.68.6: #i56403# some tweaks for better the glue code
2007/09/13 13:44:08 hdu 1.24.68.5: #i54603# fix typo
2007/09/13 09:10:28 hdu 1.24.68.4: #i54603# add PrintFontManager::addFontconfigDir() method
2007/09/12 17:11:20 hdu 1.24.68.3: #i54603# change interface for fontconfig assisted glyph fallback substitutions to allow non-baseplane unicodes
2007/09/06 12:13:43 hdu 1.24.68.2: #i54603# fix compile for older fontconfig header, minimal cleanup
2007/09/05 09:58:10 hdu 1.24.68.1: #i54603# apply Caolan's fontconfig based glyph fallback back
Diffstat (limited to 'psprint')
-rw-r--r-- | psprint/source/fontmanager/fontconfig.cxx | 542 |
1 files changed, 454 insertions, 88 deletions
diff --git a/psprint/source/fontmanager/fontconfig.cxx b/psprint/source/fontmanager/fontconfig.cxx index e1ab276ac336..14df055bc60a 100644 --- a/psprint/source/fontmanager/fontconfig.cxx +++ b/psprint/source/fontmanager/fontconfig.cxx @@ -4,9 +4,9 @@ * * $RCSfile: fontconfig.cxx,v $ * - * $Revision: 1.26 $ + * $Revision: 1.27 $ * - * last change: $Author: obo $ $Date: 2007-10-01 07:55:05 $ + * last change: $Author: kz $ $Date: 2007-12-12 13:16:47 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -36,13 +36,27 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_psprint.hxx" +#ifndef _PSPRINT_FONTMANAGER_HXX_ +#include <psprint/fontmanager.hxx> +#endif +#ifndef _PSPRINT_FONTCACHE_HXX_ +#include <psprint/fontcache.hxx> +#endif +using namespace psp; + #ifdef ENABLE_FONTCONFIG #include <fontconfig/fontconfig.h> #include <ft2build.h> #include <fontconfig/fcfreetype.h> // be compatible with fontconfig 2.2.0 release #ifndef FC_WEIGHT_BOOK -#define FC_WEIGHT_BOOK 75 + #define FC_WEIGHT_BOOK 75 +#endif +#ifndef FC_EMBEDDED_BITMAP + #define FC_EMBEDDED_BITMAP "embeddedbitmap" +#endif +#ifndef FC_FAMILYLANG + #define FC_FAMILYLANG "familylang" #endif #else typedef void FcConfig; @@ -60,13 +74,6 @@ typedef void* FT_Face; #include <cstdio> #include <cstdarg> - -#ifndef _PSPRINT_FONTMANAGER_HXX_ -#include <psprint/fontmanager.hxx> -#endif -#ifndef _PSPRINT_FONTCACHE_HXX_ -#include <psprint/fontcache.hxx> -#endif #ifndef _UTL_ATOM_HXX_ #include <unotools/atom.hxx> #endif @@ -79,8 +86,17 @@ typedef void* FT_Face; #ifndef _RTL_USTRBUF_HXX #include <rtl/ustrbuf.hxx> #endif +#ifndef _OSL_PROCESS_H_ +#include <osl/process.h> +#endif +#ifndef _RTL_LOCALE_HXX_ +#include <rtl/locale.hxx> +#endif +#include <sal/alloca.h> + +#include <utility> +#include <algorithm> -using namespace psp; using namespace osl; using namespace rtl; @@ -88,30 +104,43 @@ class FontCfgWrapper { oslModule m_pLib; FcConfig* m_pDefConfig; + FcFontSet* m_pOutlineSet; FcBool (*m_pFcInit)(); + int (*m_pFcVersion)(); FcConfig* (*m_pFcConfigGetCurrent)(); FcObjectSet* (*m_pFcObjectSetVaBuild)(const char*,va_list); void (*m_pFcObjectSetDestroy)(FcObjectSet* pSet); FcPattern* (*m_pFcPatternCreate)(); void (*m_pFcPatternDestroy)(FcPattern*); FcFontSet* (*m_pFcFontList)(FcConfig*,FcPattern*,FcObjectSet*); + FcFontSet* (*m_pFcConfigGetFonts)(FcConfig*,FcSetName); FcFontSet* (*m_pFcFontSetCreate)(); + FcCharSet* (*m_pFcCharSetCreate)(); + FcBool (*m_pFcCharSetAddChar)(FcCharSet *, FcChar32); + FcBool (*m_pFcCharSetHasChar)(FcCharSet *, FcChar32); + void (*m_pFcCharSetDestroy)(FcCharSet*); void (*m_pFcFontSetDestroy)(FcFontSet*); FcBool (*m_pFcFontSetAdd)(FcFontSet*,FcPattern*); + void (*m_pFcPatternReference)(FcPattern*); + FcResult (*m_pFcPatternGetCharSet)(const FcPattern*,const char*,int,FcCharSet**); FcResult (*m_pFcPatternGetString)(const FcPattern*,const char*,int,FcChar8**); FcResult (*m_pFcPatternGetInteger)(const FcPattern*,const char*,int,int*); FcResult (*m_pFcPatternGetDouble)(const FcPattern*,const char*,int,double*); FcResult (*m_pFcPatternGetBool)(const FcPattern*,const char*,int,FcBool*); void (*m_pFcDefaultSubstitute)(FcPattern *); - FcPattern* (*m_pFcFontMatch)(FcConfig*,FcPattern*,FcResult*); FcPattern* (*m_pFcFontSetMatch)(FcConfig*,FcFontSet**, int, FcPattern*,FcResult*); + FcBool (*m_pFcConfigAppFontAddFile)(FcConfig*, const FcChar8*); + FcBool (*m_pFcConfigAppFontAddDir)(FcConfig*, const FcChar8*); FcBool (*m_pFcConfigSubstitute)(FcConfig*,FcPattern*,FcMatchKind); FcBool (*m_pFcPatternAddInteger)(FcPattern*,const char*,int); + FcBool (*m_pFcPatternAddBool)(FcPattern*,const char*,FcBool); + FcBool (*m_pFcPatternAddCharSet)(FcPattern*,const char*,const FcCharSet*); FcBool (*m_pFcPatternAddString)(FcPattern*,const char*,const FcChar8*); FT_UInt (*m_pFcFreeTypeCharIndex)(FT_Face,FcChar32); oslGenericFunction loadSymbol( const char* ); + void addFontSet( FcSetName ); FontCfgWrapper(); ~FontCfgWrapper(); @@ -124,6 +153,7 @@ public: { return m_pLib != NULL;} FcConfig* getDefConfig() { return m_pDefConfig; } + FcFontSet* getFontSet(); FcBool FcInit() { return m_pFcInit(); } @@ -154,13 +184,36 @@ public: FcFontSet* FcFontList( FcConfig* pConfig, FcPattern* pPattern, FcObjectSet* pSet ) { return m_pFcFontList( pConfig, pPattern, pSet ); } + FcFontSet* FcConfigGetFonts( FcConfig* pConfig, FcSetName eSet) + { return m_pFcConfigGetFonts( pConfig, eSet ); } + FcFontSet* FcFontSetCreate() { return m_pFcFontSetCreate(); } + + FcCharSet* FcCharSetCreate() + { return m_pFcCharSetCreate(); } + + FcBool FcCharSetAddChar(FcCharSet *fcs, FcChar32 ucs4) + { return m_pFcCharSetAddChar(fcs, ucs4); } + + FcBool FcCharSetHasChar(FcCharSet *fcs, FcChar32 ucs4) + { return m_pFcCharSetHasChar(fcs, ucs4); } + + void FcCharSetDestroy( FcCharSet* pSet ) + { m_pFcCharSetDestroy( pSet );} + void FcFontSetDestroy( FcFontSet* pSet ) { m_pFcFontSetDestroy( pSet );} + FcBool FcFontSetAdd( FcFontSet* pSet, FcPattern* pPattern ) { return m_pFcFontSetAdd( pSet, pPattern ); } + void FcPatternReference( FcPattern* pPattern ) + { m_pFcPatternReference( pPattern ); } + + FcResult FcPatternGetCharSet( const FcPattern* pPattern, const char* object, int n, FcCharSet** s ) + { return m_pFcPatternGetCharSet( pPattern, object, n, s ); } + FcResult FcPatternGetString( const FcPattern* pPattern, const char* object, int n, FcChar8** s ) { return m_pFcPatternGetString( pPattern, object, n, s ); } @@ -172,10 +225,12 @@ public: FcResult FcPatternGetBool( const FcPattern* pPattern, const char* object, int n, FcBool* s ) { return m_pFcPatternGetBool( pPattern, object, n, s ); } + FcBool FcConfigAppFontAddFile( FcConfig* pConfig, const FcChar8* pFileName ) + { return m_pFcConfigAppFontAddFile( pConfig, pFileName ); } + FcBool FcConfigAppFontAddDir(FcConfig* pConfig, const FcChar8* pDirName ) + { return m_pFcConfigAppFontAddDir( pConfig, pDirName ); } void FcDefaultSubstitute( FcPattern* pPattern ) { m_pFcDefaultSubstitute( pPattern ); } - FcPattern* FcFontMatch( FcConfig* pConfig, FcPattern* pPattern, FcResult* pResult ) - { return m_pFcFontMatch( pConfig, pPattern, pResult ); } FcPattern* FcFontSetMatch( FcConfig* pConfig, FcFontSet **ppFontSet, int nset, FcPattern* pPattern, FcResult* pResult ) { return m_pFcFontSetMatch ? m_pFcFontSetMatch( pConfig, ppFontSet, nset, pPattern, pResult ) : 0; } FcBool FcConfigSubstitute( FcConfig* pConfig, FcPattern* pPattern, FcMatchKind eKind ) @@ -184,8 +239,16 @@ public: { return m_pFcPatternAddInteger( pPattern, pObject, nValue ); } FcBool FcPatternAddString( FcPattern* pPattern, const char* pObject, const FcChar8* pString ) { return m_pFcPatternAddString( pPattern, pObject, pString ); } + FcBool FcPatternAddBool( FcPattern* pPattern, const char* pObject, bool nValue ) + { return m_pFcPatternAddBool( pPattern, pObject, nValue ); } + FcBool FcPatternAddCharSet(FcPattern* pPattern,const char* pObject,const FcCharSet*pCharSet) + { return m_pFcPatternAddCharSet(pPattern,pObject,pCharSet); } + FT_UInt FcFreeTypeCharIndex( FT_Face face, FcChar32 ucs4 ) { return m_pFcFreeTypeCharIndex ? m_pFcFreeTypeCharIndex( face, ucs4 ) : 0; } + +public: // TODO: cleanup + std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash > m_aFontconfigNameToLocalized; }; oslGenericFunction FontCfgWrapper::loadSymbol( const char* pSymbol ) @@ -200,9 +263,9 @@ oslGenericFunction FontCfgWrapper::loadSymbol( const char* pSymbol ) FontCfgWrapper::FontCfgWrapper() : m_pLib( NULL ), - m_pDefConfig( NULL ) + m_pDefConfig( NULL ), + m_pOutlineSet( NULL ) { -#ifdef ENABLE_FONTCONFIG OUString aLib( RTL_CONSTASCII_USTRINGPARAM( "libfontconfig.so.1" ) ); m_pLib = osl_loadModule( aLib.pData, SAL_LOADMODULE_LAZY ); if( !m_pLib ) @@ -210,7 +273,6 @@ FontCfgWrapper::FontCfgWrapper() aLib = OUString( RTL_CONSTASCII_USTRINGPARAM( "libfontconfig.so" ) ); m_pLib = osl_loadModule( aLib.pData, SAL_LOADMODULE_LAZY ); } -#endif if( ! m_pLib ) { @@ -222,6 +284,8 @@ FontCfgWrapper::FontCfgWrapper() m_pFcInit = (FcBool(*)()) loadSymbol( "FcInit" ); + m_pFcVersion = (int(*)()) + loadSymbol( "FcGetVersion" ); m_pFcConfigGetCurrent = (FcConfig *(*)()) loadSymbol( "FcConfigGetCurrent" ); m_pFcObjectSetVaBuild = (FcObjectSet*(*)(const char*,va_list)) @@ -234,12 +298,26 @@ FontCfgWrapper::FontCfgWrapper() loadSymbol( "FcPatternDestroy" ); m_pFcFontList = (FcFontSet*(*)(FcConfig*,FcPattern*,FcObjectSet*)) loadSymbol( "FcFontList" ); + m_pFcConfigGetFonts = (FcFontSet*(*)(FcConfig*,FcSetName)) + loadSymbol( "FcConfigGetFonts" ); m_pFcFontSetCreate = (FcFontSet*(*)()) loadSymbol( "FcFontSetCreate" ); + m_pFcCharSetCreate = (FcCharSet*(*)()) + loadSymbol( "FcCharSetCreate" ); + m_pFcCharSetAddChar = (FcBool(*)(FcCharSet*, FcChar32)) + loadSymbol( "FcCharSetAddChar" ); + m_pFcCharSetHasChar = (FcBool(*)(FcCharSet*, FcChar32)) + loadSymbol( "FcCharSetHasChar" ); + m_pFcCharSetDestroy = (void(*)(FcCharSet*)) + loadSymbol( "FcCharSetDestroy" ); m_pFcFontSetDestroy = (void(*)(FcFontSet*)) loadSymbol( "FcFontSetDestroy" ); m_pFcFontSetAdd = (FcBool(*)(FcFontSet*,FcPattern*)) loadSymbol( "FcFontSetAdd" ); + m_pFcPatternReference = (void(*)(FcPattern*)) + loadSymbol( "FcPatternReference" ); + m_pFcPatternGetCharSet = (FcResult(*)(const FcPattern*,const char*,int,FcCharSet**)) + loadSymbol( "FcPatternGetCharSet" ); m_pFcPatternGetString = (FcResult(*)(const FcPattern*,const char*,int,FcChar8**)) loadSymbol( "FcPatternGetString" ); m_pFcPatternGetInteger = (FcResult(*)(const FcPattern*,const char*,int,int*)) @@ -248,16 +326,22 @@ FontCfgWrapper::FontCfgWrapper() loadSymbol( "FcPatternGetDouble" ); m_pFcPatternGetBool = (FcResult(*)(const FcPattern*,const char*,int,FcBool*)) loadSymbol( "FcPatternGetBool" ); + m_pFcConfigAppFontAddFile = (FcBool(*)(FcConfig*, const FcChar8*)) + loadSymbol( "FcConfigAppFontAddFile" ); + m_pFcConfigAppFontAddDir = (FcBool(*)(FcConfig*, const FcChar8*)) + loadSymbol( "FcConfigAppFontAddDir" ); m_pFcDefaultSubstitute = (void(*)(FcPattern *)) loadSymbol( "FcDefaultSubstitute" ); - m_pFcFontMatch = (FcPattern*(*)(FcConfig*,FcPattern*,FcResult*)) - loadSymbol( "FcFontMatch" ); m_pFcFontSetMatch = (FcPattern*(*)(FcConfig*,FcFontSet**,int,FcPattern*,FcResult*)) loadSymbol( "FcFontSetMatch" ); m_pFcConfigSubstitute = (FcBool(*)(FcConfig*,FcPattern*,FcMatchKind)) loadSymbol( "FcConfigSubstitute" ); m_pFcPatternAddInteger = (FcBool(*)(FcPattern*,const char*,int)) loadSymbol( "FcPatternAddInteger" ); + m_pFcPatternAddBool = (FcBool(*)(FcPattern*,const char*,FcBool)) + loadSymbol( "FcPatternAddBool" ); + m_pFcPatternAddCharSet = (FcBool(*)(FcPattern*,const char*,const FcCharSet *)) + loadSymbol( "FcPatternAddCharSet" ); m_pFcPatternAddString = (FcBool(*)(FcPattern*,const char*,const FcChar8*)) loadSymbol( "FcPatternAddString" ); m_pFcFreeTypeCharIndex = (FT_UInt(*)(FT_Face,FcChar32)) @@ -265,23 +349,34 @@ FontCfgWrapper::FontCfgWrapper() if( ! ( m_pFcInit && + m_pFcVersion && m_pFcConfigGetCurrent && m_pFcObjectSetVaBuild && m_pFcObjectSetDestroy && m_pFcPatternCreate && m_pFcPatternDestroy && m_pFcFontList && + m_pFcConfigGetFonts && m_pFcFontSetCreate && + m_pFcCharSetCreate && + m_pFcCharSetAddChar && + m_pFcCharSetHasChar && + m_pFcCharSetDestroy && m_pFcFontSetDestroy && m_pFcFontSetAdd && + m_pFcPatternReference && + m_pFcPatternGetCharSet && m_pFcPatternGetString && m_pFcPatternGetInteger && m_pFcPatternGetDouble && m_pFcPatternGetBool && + m_pFcConfigAppFontAddFile && + m_pFcConfigAppFontAddDir && m_pFcDefaultSubstitute && - m_pFcFontMatch && m_pFcConfigSubstitute && m_pFcPatternAddInteger && + m_pFcPatternAddCharSet && + m_pFcPatternAddBool && m_pFcPatternAddString ) ) { @@ -293,6 +388,7 @@ FontCfgWrapper::FontCfgWrapper() return; } + FcInit(); m_pDefConfig = FcConfigGetCurrent(); if( ! m_pDefConfig ) @@ -302,8 +398,47 @@ FontCfgWrapper::FontCfgWrapper() } } +void FontCfgWrapper::addFontSet( FcSetName eSetName ) +{ + /* + add only acceptable outlined fonts to our config, + for future fontconfig use + */ + FcFontSet* pOrig = FcConfigGetFonts( getDefConfig(), eSetName ); + if( !pOrig ) + return; + + for( int i = 0; i < pOrig->nfont; ++i ) + { + FcBool outline = false; + FcPattern *pOutlinePattern = pOrig->fonts[i]; + FcResult eOutRes = + FcPatternGetBool( pOutlinePattern, FC_OUTLINE, 0, &outline ); + if( (eOutRes != FcResultMatch) || (outline != FcTrue) ) + continue; + FcPatternReference(pOutlinePattern); + FcFontSetAdd(m_pOutlineSet, pOutlinePattern); + } +} + +FcFontSet* FontCfgWrapper::getFontSet() +{ + if( !m_pOutlineSet ) + { + m_pOutlineSet = FcFontSetCreate(); + addFontSet( FcSetSystem ); + const int nVersion = (*m_pFcVersion)(); + if( nVersion > 20400 ) + addFontSet( FcSetApplication ); + } + + return m_pOutlineSet; +} + FontCfgWrapper::~FontCfgWrapper() { + if( m_pOutlineSet ) + FcFontSetDestroy( m_pOutlineSet ); if( m_pLib ) osl_unloadModule( (oslModule)m_pLib ); } @@ -326,37 +461,115 @@ void FontCfgWrapper::release() } } -#ifndef FC_EMBEDDED_BITMAP -#define FC_EMBEDDED_BITMAP "embeddedbitmap" -#endif +namespace +{ + typedef std::pair<FcChar8*, FcChar8*> lang_and_family; + + class localizedsorter + { + rtl::OLocale maLoc; + public: + localizedsorter(rtl_Locale* pLoc) : maLoc(pLoc) {} + FcChar8* bestname(const std::vector<lang_and_family> &families); + }; + + FcChar8* localizedsorter::bestname(const std::vector<lang_and_family> &families) + { + FcChar8* candidate = families.begin()->second; + rtl::OString sLangMatch(rtl::OUStringToOString(maLoc.getLanguage().toAsciiLowerCase(), RTL_TEXTENCODING_UTF8)); + rtl::OString sFullMatch = sLangMatch; + sFullMatch += OString('-'); + sFullMatch += rtl::OUStringToOString(maLoc.getCountry().toAsciiLowerCase(), RTL_TEXTENCODING_UTF8); + + std::vector<lang_and_family>::const_iterator aEnd = families.end(); + bool alreadyclosematch = false; + for (std::vector<lang_and_family>::const_iterator aIter = families.begin(); aIter != aEnd; ++aIter) + { + const char *pLang = (const char*)aIter->first; + //perfect + if( rtl_str_compare(pLang,sFullMatch.getStr() ) == 0) + { + candidate = aIter->second; + break; + } + else if( (rtl_str_compare(pLang,sLangMatch.getStr()) == 0) && (!alreadyclosematch)) + { + candidate = aIter->second; + alreadyclosematch = true; + } + } + + return candidate; + } + + + FcResult lcl_FamilyFromPattern(FontCfgWrapper& rWrapper, FcPattern* pPattern, FcChar8 **family, + std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash > &aFontconfigNameToLocalized) + { + FcChar8 *origfamily; + FcResult eFamilyRes = rWrapper.FcPatternGetString( pPattern, FC_FAMILY, 0, &origfamily ); + *family = origfamily; + + if( eFamilyRes == FcResultMatch) + { + FcChar8* familylang = NULL; + if (rWrapper.FcPatternGetString( pPattern, FC_FAMILYLANG, 0, &familylang ) == FcResultMatch) + { + std::vector< lang_and_family > lang_and_families; + lang_and_families.push_back(lang_and_family(familylang, *family)); + int k = 1; + while (1) + { + if (rWrapper.FcPatternGetString( pPattern, FC_FAMILYLANG, k, &familylang ) != FcResultMatch) + break; + if (rWrapper.FcPatternGetString( pPattern, FC_FAMILY, k, family ) != FcResultMatch) + break; + lang_and_families.push_back(lang_and_family(familylang, *family)); + ++k; + } + + //possible to-do, sort by UILocale instead of process locale + rtl_Locale* pLoc; + osl_getProcessLocale(&pLoc); + localizedsorter aSorter(pLoc); + *family = aSorter.bestname(lang_and_families); + + std::vector<lang_and_family>::const_iterator aEnd = lang_and_families.end(); + for (std::vector<lang_and_family>::const_iterator aIter = lang_and_families.begin(); aIter != aEnd; ++aIter) + { + const char *candidate = (const char*)(aIter->second); + if (rtl_str_compare(candidate, (const char*)(*family)) != 0) + aFontconfigNameToLocalized[OString(candidate)] = OString((const char*)(*family)); + } + } + } + + return eFamilyRes; + } +} + /* * PrintFontManager::initFontconfig */ +#ifdef ENABLE_FONTCONFIG bool PrintFontManager::initFontconfig() { - int nFonts = 0; - -#ifdef ENABLE_FONTCONFIG FontCfgWrapper& rWrapper = FontCfgWrapper::get(); if( ! rWrapper.isValid() ) return false; + return true; +} - FcConfig* pConfig = rWrapper.getDefConfig(); - FcObjectSet* pOSet = rWrapper.FcObjectSetBuild( FC_FAMILY, - FC_STYLE, - FC_SLANT, - FC_WEIGHT, - FC_SPACING, - FC_FILE, - FC_OUTLINE, - FC_INDEX, - FC_EMBEDDED_BITMAP, - FC_ANTIALIAS, - (void *) NULL ); - FcPattern* pPattern = rWrapper.FcPatternCreate(); - FcFontSet* pFSet = rWrapper.FcFontList( pConfig, pPattern, pOSet ); +int PrintFontManager::countFontconfigFonts() +{ + int nFonts = 0; + FontCfgWrapper& rWrapper = FontCfgWrapper::get(); + if( !rWrapper.isValid() ) + return 0; + + FcFontSet* pFSet = rWrapper.getFontSet(); if( pFSet ) { #if OSL_DEBUG_LEVEL > 1 @@ -374,7 +587,7 @@ bool PrintFontManager::initFontconfig() FcBool outline = false, embitmap = true, antialias = true; FcResult eFileRes = rWrapper.FcPatternGetString( pFSet->fonts[i], FC_FILE, 0, &file ); - FcResult eFamilyRes = rWrapper.FcPatternGetString( pFSet->fonts[i], FC_FAMILY, 0, &family ); + FcResult eFamilyRes = lcl_FamilyFromPattern(rWrapper, pFSet->fonts[i], &family, rWrapper.m_aFontconfigNameToLocalized ); FcResult eStyleRes = rWrapper.FcPatternGetString( pFSet->fonts[i], FC_STYLE, 0, &style ); FcResult eSlantRes = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_SLANT, 0, &slant ); FcResult eWeightRes = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_WEIGHT, 0, &weight ); @@ -387,7 +600,7 @@ bool PrintFontManager::initFontconfig() if( eFileRes != FcResultMatch || eFamilyRes != FcResultMatch || eOutRes != FcResultMatch ) continue; -#if OSL_DEBUG_LEVEL > 2 +#if (OSL_DEBUG_LEVEL > 2) fprintf( stderr, "found font \"%s\" in file %s\n" " weight = %d, slant = %d, style = \"%s\"\n" " spacing = %d, outline = %d\n" @@ -400,6 +613,8 @@ bool PrintFontManager::initFontconfig() ); #endif + OSL_ASSERT(eOutRes != FcResultMatch || outline); + // only outline fonts are usable to psprint anyway if( eOutRes == FcResultMatch && ! outline ) continue; @@ -553,20 +768,11 @@ bool PrintFontManager::initFontconfig() } } - // cleanup - if( pPattern ) - rWrapper.FcPatternDestroy( pPattern ); - if( pFSet ) - rWrapper.FcFontSetDestroy( pFSet ); - if( pOSet ) - rWrapper.FcObjectSetDestroy( pOSet ); - // how does one get rid of the config ? #if OSL_DEBUG_LEVEL > 1 fprintf( stderr, "inserted %d fonts from fontconfig\n", nFonts ); #endif -#endif // ENABLE_FONTCONFIG - return nFonts != 0; + return nFonts; } void PrintFontManager::deinitFontconfig() @@ -580,39 +786,31 @@ int PrintFontManager::FreeTypeCharIndex( void *pFace, sal_uInt32 aChar ) return rWrapper.isValid() ? rWrapper.FcFreeTypeCharIndex( (FT_Face)pFace, aChar ) : 0; } -bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const com::sun::star::lang::Locale& rLocale ) +bool PrintFontManager::addFontconfigDir( const rtl::OString& rDirName ) { -#ifdef ENABLE_FONTCONFIG FontCfgWrapper& rWrapper = FontCfgWrapper::get(); if( ! rWrapper.isValid() ) return false; - FcConfig* pConfig = rWrapper.getDefConfig(); - FcPattern* pPattern = rWrapper.FcPatternCreate(); + // libfontcconfig's AppFontAddDir was broken in version 2.4.0 + // TODO: is there a workaround? + const char* pDirName = (const char*)rDirName.getStr(); + bool bRet = (rWrapper.FcConfigAppFontAddDir( rWrapper.getDefConfig(), (FcChar8*)pDirName ) == FcTrue); - OString aLangAttrib; - // populate pattern with font characteristics - if( rLocale.Language.getLength() ) - { - OUStringBuffer aLang(6); - aLang.append( rLocale.Language ); - if( rLocale.Country.getLength() ) - { - aLang.append( sal_Unicode('-') ); - aLang.append( rLocale.Country ); - } - aLangAttrib = OUStringToOString( aLang.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ); - } - if( aLangAttrib.getLength() ) - rWrapper.FcPatternAddString( pPattern, FC_LANG, (FcChar8*)aLangAttrib.getStr() ); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "FcConfigAppFontAddDir( \"%s\") => %d\n", pDirName, bRet ); +#endif - OString aFamily = OUStringToOString( rInfo.m_aFamilyName, RTL_TEXTENCODING_UTF8 ); - if( aFamily.getLength() ) - rWrapper.FcPatternAddString( pPattern, FC_FAMILY, (FcChar8*)aFamily.getStr() ); - if( rInfo.m_eItalic != italic::Unknown ) + return bRet; +} + +static void addtopattern(FontCfgWrapper& rWrapper, FcPattern *pPattern, + italic::type eItalic, weight::type eWeight, width::type eWidth, pitch::type ePitch) +{ + if( eItalic != italic::Unknown ) { int nSlant = FC_SLANT_ROMAN; - switch( rInfo.m_eItalic ) + switch( eItalic ) { case italic::Italic: nSlant = FC_SLANT_ITALIC;break; case italic::Oblique: nSlant = FC_SLANT_OBLIQUE;break; @@ -621,10 +819,10 @@ bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const com::sun::star } rWrapper.FcPatternAddInteger( pPattern, FC_SLANT, nSlant ); } - if( rInfo.m_eWeight != weight::Unknown ) + if( eWeight != weight::Unknown ) { int nWeight = FC_WEIGHT_NORMAL; - switch( rInfo.m_eWeight ) + switch( eWeight ) { case weight::Thin: nWeight = FC_WEIGHT_THIN;break; case weight::UltraLight: nWeight = FC_WEIGHT_ULTRALIGHT;break; @@ -641,10 +839,10 @@ bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const com::sun::star } rWrapper.FcPatternAddInteger( pPattern, FC_WEIGHT, nWeight ); } - if( rInfo.m_eWidth != width::Unknown ) + if( eWidth != width::Unknown ) { int nWidth = FC_WIDTH_NORMAL; - switch( rInfo.m_eWidth ) + switch( eWidth ) { case width::UltraCondensed: nWidth = FC_WIDTH_ULTRACONDENSED;break; case width::ExtraCondensed: nWidth = FC_WIDTH_EXTRACONDENSED;break; @@ -660,10 +858,10 @@ bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const com::sun::star } rWrapper.FcPatternAddInteger( pPattern, FC_WIDTH, nWidth ); } - if( rInfo.m_ePitch != pitch::Unknown ) + if( ePitch != pitch::Unknown ) { int nSpacing = FC_PROPORTIONAL; - switch( rInfo.m_ePitch ) + switch( ePitch ) { case pitch::Fixed: nSpacing = FC_MONO;break; case pitch::Variable: nSpacing = FC_PROPORTIONAL;break; @@ -671,12 +869,150 @@ bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const com::sun::star break; } rWrapper.FcPatternAddInteger( pPattern, FC_SPACING, nSpacing ); + if (nSpacing == FC_MONO) + rWrapper.FcPatternAddString( pPattern, FC_FAMILY, (FcChar8*)"monospace"); + } +} + +rtl::OUString PrintFontManager::Substitute(const rtl::OUString& rFontName, + rtl::OUString& rMissingCodes, const rtl::OString &rLangAttrib, + italic::type eItalic, weight::type eWeight, + width::type eWidth, pitch::type ePitch) const +{ + rtl::OUString aName; + FontCfgWrapper& rWrapper = FontCfgWrapper::get(); + if( ! rWrapper.isValid() ) + return aName; + + // build pattern argument for fontconfig query + FcPattern* pPattern = rWrapper.FcPatternCreate(); + + // Prefer scalable fonts + rWrapper.FcPatternAddBool( pPattern, FC_SCALABLE, FcTrue ); + + const rtl::OString aTargetName = rtl::OUStringToOString( rFontName, RTL_TEXTENCODING_UTF8 ); + const FcChar8* pTargetNameUtf8 = (FcChar8*)aTargetName.getStr(); + rWrapper.FcPatternAddString( pPattern, FC_FAMILY, pTargetNameUtf8 ); + + const FcChar8* pLangAttribUtf8 = (FcChar8*)rLangAttrib.getStr(); + if( rLangAttrib.getLength() ) + rWrapper.FcPatternAddString( pPattern, FC_LANG, pLangAttribUtf8 ); + + // Add required Unicode characters, if any + if ( rMissingCodes.getLength() ) + { + FcCharSet *unicodes = rWrapper.FcCharSetCreate(); + for( sal_Int32 nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); ) + { + // also handle unicode surrogates + const sal_uInt32 nCode = rMissingCodes.iterateCodePoints( &nStrIndex ); + rWrapper.FcCharSetAddChar( unicodes, nCode ); + } + rWrapper.FcPatternAddCharSet( pPattern, FC_CHARSET, unicodes); + rWrapper.FcCharSetDestroy( unicodes ); + } + + addtopattern(rWrapper, pPattern, eItalic, eWeight, eWidth, ePitch); + + // query fontconfig for a substitute + rWrapper.FcConfigSubstitute( rWrapper.getDefConfig(), pPattern, FcMatchPattern ); + rWrapper.FcDefaultSubstitute( pPattern ); + + // process the result of the fontconfig query + FcResult eResult = FcResultNoMatch; + FcFontSet* pFontSet = rWrapper.getFontSet(); + FcPattern* pResult = rWrapper.FcFontSetMatch( rWrapper.getDefConfig(), &pFontSet, 1, pPattern, &eResult ); + rWrapper.FcPatternDestroy( pPattern ); + + FcFontSet* pSet = NULL; + if( pResult ) + { + pSet = rWrapper.FcFontSetCreate(); + // info: destroying the pSet destroys pResult implicitly + // since pResult was "added" to pSet + rWrapper.FcFontSetAdd( pSet, pResult ); } + if( pSet ) + { + if( pSet->nfont > 0 ) + { + //extract the closest match + FcChar8* family = NULL; + FcResult eFileRes = rWrapper.FcPatternGetString( pSet->fonts[0], FC_FAMILY, 0, &family ); + + // get the family name + if( eFileRes == FcResultMatch ) + { + OString sFamily((sal_Char*)family); + std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash >::const_iterator aI = rWrapper.m_aFontconfigNameToLocalized.find(sFamily); + if (aI != rWrapper.m_aFontconfigNameToLocalized.end()) + sFamily = aI->second; + aName = rtl::OStringToOUString( sFamily, RTL_TEXTENCODING_UTF8 ); + } + + // update rMissingCodes by removing resolved unicodes + if( rMissingCodes.getLength() > 0 ) + { + sal_uInt32* pRemainingCodes = (sal_uInt32*)alloca( rMissingCodes.getLength() * sizeof(sal_uInt32) ); + int nRemainingLen = 0; + FcCharSet* unicodes; + if( !rWrapper.FcPatternGetCharSet( pSet->fonts[0], FC_CHARSET, 0, &unicodes ) ) + { + for( sal_Int32 nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); ) + { + // also handle unicode surrogates + const sal_uInt32 nCode = rMissingCodes.iterateCodePoints( &nStrIndex ); + if( rWrapper.FcCharSetHasChar( unicodes, nCode ) != FcTrue ) + pRemainingCodes[ nRemainingLen++ ] = nCode; + } + } + rMissingCodes = OUString( pRemainingCodes, nRemainingLen ); + } + } + + rWrapper.FcFontSetDestroy( pSet ); + } + + return aName; +} + +bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const com::sun::star::lang::Locale& rLocale ) +{ + FontCfgWrapper& rWrapper = FontCfgWrapper::get(); + if( ! rWrapper.isValid() ) + return false; + + FcConfig* pConfig = rWrapper.getDefConfig(); + FcPattern* pPattern = rWrapper.FcPatternCreate(); + + OString aLangAttrib; + // populate pattern with font characteristics + if( rLocale.Language.getLength() ) + { + OUStringBuffer aLang(6); + aLang.append( rLocale.Language ); + if( rLocale.Country.getLength() ) + { + aLang.append( sal_Unicode('-') ); + aLang.append( rLocale.Country ); + } + aLangAttrib = OUStringToOString( aLang.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ); + } + if( aLangAttrib.getLength() ) + rWrapper.FcPatternAddString( pPattern, FC_LANG, (FcChar8*)aLangAttrib.getStr() ); + + OString aFamily = OUStringToOString( rInfo.m_aFamilyName, RTL_TEXTENCODING_UTF8 ); + if( aFamily.getLength() ) + rWrapper.FcPatternAddString( pPattern, FC_FAMILY, (FcChar8*)aFamily.getStr() ); + + addtopattern(rWrapper, pPattern, rInfo.m_eItalic, rInfo.m_eWeight, rInfo.m_eWidth, rInfo.m_ePitch); + rWrapper.FcConfigSubstitute( pConfig, pPattern, FcMatchPattern ); rWrapper.FcDefaultSubstitute( pPattern ); FcResult eResult = FcResultNoMatch; - FcPattern* pResult = rWrapper.FcFontMatch( pConfig, pPattern, &eResult ); + FcFontSet *pFontSet = rWrapper.getFontSet(); + FcPattern* pResult = rWrapper.FcFontSetMatch( pConfig, &pFontSet, 1, pPattern, &eResult ); bool bSuccess = false; if( pResult ) { @@ -686,7 +1022,7 @@ bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const com::sun::star { //extract the closest match FcChar8* file = NULL; - FcResult eFileRes = rWrapper.FcPatternGetString( pSet->fonts[0], FC_FILE, 0, &file ); + FcResult eFileRes = rWrapper.FcPatternGetString( pSet->fonts[0], FC_FILE, 0, &file ); if( eFileRes == FcResultMatch ) { OString aDir, aBase, aOrgPath( (sal_Char*)file ); @@ -706,9 +1042,39 @@ bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const com::sun::star rWrapper.FcPatternDestroy( pPattern ); return bSuccess; -#else - (void)rInfo; - (void)rLocale; +} + +#else // ENABLE_FONTCONFIG not defined + +bool PrintFontManager::initFontconfig() +{ return false; -#endif } + +int PrintFontManager::countFontconfigFonts() +{ + return 0; +} + +void PrintFontManager::deinitFontconfig() +{} + +bool PrintFontManager::addFontconfigDir( const rtl::OString& ) +{ + return false; +} + +bool PrintFontManager::matchFont( FastPrintFontInfo&, const com::sun::star::lang::Locale& ) +{ + return false; +} + +rtl::OUString PrintFontManager::Substitute( const rtl::OUString&, + rtl::OUString&, const rtl::OString&, italic::type, weight::type, width::type, pitch::type) const +{ + rtl::OUString aName; + return aName; +} + +#endif // ENABLE_FONTCONFIG + |