summaryrefslogtreecommitdiff
path: root/psprint
diff options
context:
space:
mode:
authorKurt Zenker <kz@openoffice.org>2007-12-12 12:16:47 +0000
committerKurt Zenker <kz@openoffice.org>2007-12-12 12:16:47 +0000
commit5c55c8244f607380a0f1ff45759abd66562191f0 (patch)
treea76600928ad2cf9de83dd3cc8e672bb7b1b24926 /psprint
parent34e2f289d24ed72b5f969892a6204ea561a02c79 (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.cxx542
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
+