summaryrefslogtreecommitdiff
path: root/psprint
diff options
context:
space:
mode:
authorOliver Bolte <obo@openoffice.org>2004-07-05 08:22:36 +0000
committerOliver Bolte <obo@openoffice.org>2004-07-05 08:22:36 +0000
commit801ef844ad761f5cd99440a7272dd7ef47f96e01 (patch)
tree2ac4f08e8770586d60c36b58ca9f553497a7a609 /psprint
parent2297069d473c6ff3ba6a613222c20ce01cfecd60 (diff)
INTEGRATION: CWS vcl22 (1.4.2); FILE MERGED
2004/06/25 20:47:45 pl 1.4.2.2: #i30611# handle truetype collections correctly 2004/06/25 18:13:55 pl 1.4.2.1: #i30611# add: fontmatching via fontconfig, removed some warnings
Diffstat (limited to 'psprint')
-rw-r--r--psprint/source/fontmanager/fontconfig.cxx358
1 files changed, 302 insertions, 56 deletions
diff --git a/psprint/source/fontmanager/fontconfig.cxx b/psprint/source/fontmanager/fontconfig.cxx
index c8a70a96e8d3..29a951b42431 100644
--- a/psprint/source/fontmanager/fontconfig.cxx
+++ b/psprint/source/fontmanager/fontconfig.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: fontconfig.cxx,v $
*
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
*
- * last change: $Author: obo $ $Date: 2004-06-01 09:35:26 $
+ * last change: $Author: obo $ $Date: 2004-07-05 09:22:36 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -61,6 +61,10 @@
#ifdef ENABLE_FONTCONFIG
#include <fontconfig/fontconfig.h>
+// be compatible with fontconfig 2.2.0 release
+#ifndef FC_WEIGHT_BOOK
+#define FC_WEIGHT_BOOK 75
+#endif
#else
typedef void FcConfig;
typedef void FcObjectSet;
@@ -69,7 +73,6 @@ typedef void FcFontSet;
typedef int FcResult;
typedef int FcBool;
typedef char FcChar8;
-
#endif
#include <cstdio>
@@ -98,6 +101,7 @@ using namespace rtl;
class FontCfgWrapper
{
void* m_pLib;
+ FcConfig* m_pDefConfig;
FcConfig* (*m_pFcInitLoadConfigAndFonts)();
FcObjectSet* (*m_pFcObjectSetVaBuild)(const char*,va_list);
@@ -105,20 +109,34 @@ class FontCfgWrapper
FcPattern* (*m_pFcPatternCreate)();
void (*m_pFcPatternDestroy)(FcPattern*);
FcFontSet* (*m_pFcFontList)(FcConfig*,FcPattern*,FcObjectSet*);
+ FcFontSet* (*m_pFcFontSetCreate)();
void (*m_pFcFontSetDestroy)(FcFontSet*);
+ FcBool (*m_pFcFontSetAdd)(FcFontSet*,FcPattern*);
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*);
+ FcBool (*m_pFcConfigSubstitute)(FcConfig*,FcPattern*,FcMatchKind);
+ FcBool (*m_pFcPatternAddInteger)(FcPattern*,const char*,int);
+ FcBool (*m_pFcPatternAddString)(FcPattern*,const char*,const FcChar8*);
void* loadSymbol( const char* );
-public:
+
FontCfgWrapper();
~FontCfgWrapper();
+public:
+ static FontCfgWrapper& get();
+ static void release();
+
bool isValid() const
{ return m_pLib != NULL;}
+ FcConfig* getDefConfig() { return m_pDefConfig; }
+
+
FcConfig* FcInitLoadConfigAndFonts()
{ return m_pFcInitLoadConfigAndFonts(); }
@@ -143,8 +161,12 @@ public:
FcFontSet* FcFontList( FcConfig* pConfig, FcPattern* pPattern, FcObjectSet* pSet )
{ return m_pFcFontList( pConfig, pPattern, pSet ); }
+ FcFontSet* FcFontSetCreate()
+ { return m_pFcFontSetCreate(); }
void FcFontSetDestroy( FcFontSet* pSet )
{ m_pFcFontSetDestroy( pSet );}
+ FcBool FcFontSetAdd( FcFontSet* pSet, FcPattern* pPattern )
+ { return m_pFcFontSetAdd( pSet, pPattern ); }
FcResult FcPatternGetString( const FcPattern* pPattern, const char* object, int n, FcChar8** s )
{ return m_pFcPatternGetString( pPattern, object, n, s ); }
@@ -157,6 +179,16 @@ public:
FcResult FcPatternGetBool( const FcPattern* pPattern, const char* object, int n, FcBool* s )
{ return m_pFcPatternGetBool( pPattern, object, n, s ); }
+ void FcDefaultSubstitute( FcPattern* pPattern )
+ { m_pFcDefaultSubstitute( pPattern ); }
+ FcPattern* FcFontMatch( FcConfig* pConfig, FcPattern* pPattern, FcResult* pResult )
+ { return m_pFcFontMatch( pConfig, pPattern, pResult ); }
+ FcBool FcConfigSubstitute( FcConfig* pConfig, FcPattern* pPattern, FcMatchKind eKind )
+ { return m_pFcConfigSubstitute( pConfig, pPattern, eKind ); }
+ FcBool FcPatternAddInteger( FcPattern* pPattern, const char* pObject, int nValue )
+ { return m_pFcPatternAddInteger( pPattern, pObject, nValue ); }
+ FcBool FcPatternAddString( FcPattern* pPattern, const char* pObject, const FcChar8* pString )
+ { return m_pFcPatternAddString( pPattern, pObject, pString ); }
};
void* FontCfgWrapper::loadSymbol( const char* pSymbol )
@@ -170,7 +202,8 @@ void* FontCfgWrapper::loadSymbol( const char* pSymbol )
}
FontCfgWrapper::FontCfgWrapper()
- : m_pLib( NULL )
+ : m_pLib( NULL ),
+ m_pDefConfig( NULL )
{
#ifdef ENABLE_FONTCONFIG
OUString aLib( RTL_CONSTASCII_USTRINGPARAM( "libfontconfig.so.1" ) );
@@ -202,8 +235,12 @@ FontCfgWrapper::FontCfgWrapper()
loadSymbol( "FcPatternDestroy" );
m_pFcFontList = (FcFontSet*(*)(FcConfig*,FcPattern*,FcObjectSet*))
loadSymbol( "FcFontList" );
+ m_pFcFontSetCreate = (FcFontSet*(*)())
+ loadSymbol( "FcFontSetCreate" );
m_pFcFontSetDestroy = (void(*)(FcFontSet*))
loadSymbol( "FcFontSetDestroy" );
+ m_pFcFontSetAdd = (FcBool(*)(FcFontSet*,FcPattern*))
+ loadSymbol( "FcFontSetAdd" );
m_pFcPatternGetString = (FcResult(*)(const FcPattern*,const char*,int,FcChar8**))
loadSymbol( "FcPatternGetString" );
m_pFcPatternGetInteger = (FcResult(*)(const FcPattern*,const char*,int,int*))
@@ -212,6 +249,16 @@ FontCfgWrapper::FontCfgWrapper()
loadSymbol( "FcPatternGetDouble" );
m_pFcPatternGetBool = (FcResult(*)(const FcPattern*,const char*,int,FcBool*))
loadSymbol( "FcPatternGetBool" );
+ m_pFcDefaultSubstitute = (void(*)(FcPattern *))
+ loadSymbol( "FcDefaultSubstitute" );
+ m_pFcFontMatch = (FcPattern*(*)(FcConfig*,FcPattern*,FcResult*))
+ loadSymbol( "FcFontMatch" );
+ m_pFcConfigSubstitute = (FcBool(*)(FcConfig*,FcPattern*,FcMatchKind))
+ loadSymbol( "FcConfigSubstitute" );
+ m_pFcPatternAddInteger = (FcBool(*)(FcPattern*,const char*,int))
+ loadSymbol( "FcPatternAddInteger" );
+ m_pFcPatternAddString = (FcBool(*)(FcPattern*,const char*,const FcChar8*))
+ loadSymbol( "FcPatternAddString" );
if( ! (
m_pFcInitLoadConfigAndFonts &&
@@ -220,11 +267,18 @@ FontCfgWrapper::FontCfgWrapper()
m_pFcPatternCreate &&
m_pFcPatternDestroy &&
m_pFcFontList &&
+ m_pFcFontSetCreate &&
m_pFcFontSetDestroy &&
+ m_pFcFontSetAdd &&
m_pFcPatternGetString &&
m_pFcPatternGetInteger &&
m_pFcPatternGetDouble &&
- m_pFcPatternGetBool
+ m_pFcPatternGetBool &&
+ m_pFcDefaultSubstitute &&
+ m_pFcFontMatch &&
+ m_pFcConfigSubstitute &&
+ m_pFcPatternAddInteger &&
+ m_pFcPatternAddString
) )
{
osl_unloadModule( m_pLib );
@@ -233,6 +287,13 @@ FontCfgWrapper::FontCfgWrapper()
fprintf( stderr, "not all needed symbols were found in libfontconfig\n" );
#endif
}
+
+ m_pDefConfig = FcInitLoadConfigAndFonts();
+ if( ! m_pDefConfig )
+ {
+ osl_unloadModule( m_pLib );
+ m_pLib = NULL;
+ }
}
FontCfgWrapper::~FontCfgWrapper()
@@ -241,6 +302,24 @@ FontCfgWrapper::~FontCfgWrapper()
osl_unloadModule( m_pLib );
}
+static FontCfgWrapper* pOneInstance = NULL;
+
+FontCfgWrapper& FontCfgWrapper::get()
+{
+ if( ! pOneInstance )
+ pOneInstance = new FontCfgWrapper();
+ return *pOneInstance;
+}
+
+void FontCfgWrapper::release()
+{
+ if( pOneInstance )
+ {
+ delete pOneInstance;
+ pOneInstance = NULL;
+ }
+}
+
/*
* PrintFontManager::initFontconfig
*/
@@ -249,24 +328,22 @@ bool PrintFontManager::initFontconfig()
int nFonts = 0;
#ifdef ENABLE_FONTCONFIG
- FontCfgWrapper aWrapper;
- if( ! aWrapper.isValid() )
- return false;
-
- FcConfig* pConfig = aWrapper.FcInitLoadConfigAndFonts();
- if( ! pConfig )
+ FontCfgWrapper& rWrapper = FontCfgWrapper::get();
+ if( ! rWrapper.isValid() )
return false;
- FcObjectSet* pOSet = aWrapper.FcObjectSetBuild( FC_FAMILY,
+ FcConfig* pConfig = rWrapper.getDefConfig();
+ FcObjectSet* pOSet = rWrapper.FcObjectSetBuild( FC_FAMILY,
FC_STYLE,
FC_SLANT,
FC_WEIGHT,
FC_SPACING,
FC_FILE,
FC_OUTLINE,
+ FC_INDEX,
NULL );
- FcPattern* pPattern = aWrapper.FcPatternCreate();
- FcFontSet* pFSet = aWrapper.FcFontList( pConfig, pPattern, pOSet );
+ FcPattern* pPattern = rWrapper.FcPatternCreate();
+ FcFontSet* pFSet = rWrapper.FcFontList( pConfig, pPattern, pOSet );
if( pFSet )
{
@@ -281,16 +358,17 @@ bool PrintFontManager::initFontconfig()
int slant = 0;
int weight = 0;
int spacing = 0;
+ int nCollectionEntry = -1;
FcBool outline = false;
- FcResult eFileRes = aWrapper.FcPatternGetString( pFSet->fonts[i], FC_FILE, 0, &file );
- FcResult eFamilyRes = aWrapper.FcPatternGetString( pFSet->fonts[i], FC_FAMILY, 0, &family );
- FcResult eStyleRes = aWrapper.FcPatternGetString( pFSet->fonts[i], FC_STYLE, 0, &style );
- FcResult eSlantRes = aWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_SLANT, 0, &slant );
- FcResult eWeightRes = aWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_WEIGHT, 0, &weight );
- FcResult eSpacRes = aWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_SPACING, 0, &spacing );
- FcResult eOutRes = aWrapper.FcPatternGetBool( pFSet->fonts[i], FC_OUTLINE, 0, &outline );
-
+ FcResult eFileRes = rWrapper.FcPatternGetString( pFSet->fonts[i], FC_FILE, 0, &file );
+ FcResult eFamilyRes = rWrapper.FcPatternGetString( pFSet->fonts[i], FC_FAMILY, 0, &family );
+ 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 );
+ FcResult eSpacRes = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_SPACING, 0, &spacing );
+ FcResult eOutRes = rWrapper.FcPatternGetBool( pFSet->fonts[i], FC_OUTLINE, 0, &outline );
+ FcResult eIndexRes = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_INDEX, 0, &nCollectionEntry );
if( eFileRes != FcResultMatch || eFamilyRes != FcResultMatch || eOutRes != FcResultMatch )
continue;
@@ -327,81 +405,132 @@ bool PrintFontManager::initFontconfig()
// not described by fontconfig (e.g. alias names, PSName)
std::list< OString > aDummy;
analyzeFontFile( nDirID, aBase, true, aDummy, aFonts );
- }
#if OSL_DEBUG_LEVEL > 1
- if( aFonts.size() > 1 )
- fprintf( stderr, "Warning: file contains more than one font, updating all to fontconfig data\n" );
- else if( aFonts.empty() )
- fprintf( stderr, "Warning: file is unusable to psprint\n" );
+ if( aFonts.empty() )
+ fprintf( stderr, "Warning: file is unusable to psprint\n" );
#endif
+ }
+ if( aFonts.empty() )
+ continue;
+
int nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, OStringToOUString( OString( (sal_Char*)family ), osl_getThreadTextEncoding() ), sal_True );
+ PrintFont* pUpdate = aFonts.front();
+ if( ++aFonts.begin() != aFonts.end() ) // more than one font
+ {
+ // a collection entry, get the correct index
+ if( eIndexRes == FcResultMatch && nCollectionEntry != -1 )
+ {
+ for( std::list< PrintFont* >::iterator it = aFonts.begin(); it != aFonts.end(); ++it )
+ {
+ if( (*it)->m_eType == fonttype::TrueType &&
+ static_cast<TrueTypeFontFile*>(*it)->m_nCollectionEntry == nCollectionEntry )
+ {
+ pUpdate = *it;
+ break;
+ }
+ }
+ // update collection entry
+ // additional entries will be created in the cache
+ // if this is a new index (that is if the loop above
+ // ran to the end of the list)
+ if( pUpdate->m_eType == fonttype::TrueType ) // sanity check, this should always be the case here
+ static_cast<TrueTypeFontFile*>(pUpdate)->m_nCollectionEntry = nCollectionEntry;
+ }
+ else
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "multiple fonts for file, but no index in fontconfig pattern ! (index res = %d collection entry = %d\nfile will not be used\n", eIndexRes, nCollectionEntry );
+#endif
+ // we have found more than one font in this file
+ // but fontconfig will not tell us which index is meant
+ // -> something is in disorder, do not use this font
+ pUpdate = NULL;
+ }
+ }
- for( std::list< PrintFont* >::iterator it = aFonts.begin();
- it != aFonts.end(); ++it )
+ if( pUpdate )
{
// set family name
- if( (*it)->m_nFamilyName != nFamilyName )
+ if( pUpdate->m_nFamilyName != nFamilyName )
{
- (*it)->m_aAliases.remove( (*it)->m_nFamilyName );
- (*it)->m_aAliases.push_back( (*it)->m_nFamilyName );
- (*it)->m_aAliases.remove( nFamilyName );
- (*it)->m_nFamilyName = nFamilyName;
+ pUpdate->m_aAliases.remove( pUpdate->m_nFamilyName );
+ pUpdate->m_aAliases.push_back( pUpdate->m_nFamilyName );
+ pUpdate->m_aAliases.remove( nFamilyName );
+ pUpdate->m_nFamilyName = nFamilyName;
}
if( eWeightRes == FcResultMatch )
{
// set weight
- if( weight == FC_WEIGHT_LIGHT )
- (*it)->m_eWeight = weight::Light;
- else if( weight == FC_WEIGHT_MEDIUM )
- (*it)->m_eWeight = weight::Medium;
- else if( weight == FC_WEIGHT_DEMIBOLD )
- (*it)->m_eWeight = weight::SemiBold;
- else if( weight == FC_WEIGHT_BOLD )
- (*it)->m_eWeight = weight::Bold;
- else if( weight == FC_WEIGHT_BLACK )
- (*it)->m_eWeight = weight::Black;
+ if( weight <= FC_WEIGHT_THIN )
+ pUpdate->m_eWeight = weight::Thin;
+ else if( weight <= FC_WEIGHT_ULTRALIGHT )
+ pUpdate->m_eWeight = weight::UltraLight;
+ else if( weight <= FC_WEIGHT_LIGHT )
+ pUpdate->m_eWeight = weight::Light;
+ else if( weight <= FC_WEIGHT_BOOK )
+ pUpdate->m_eWeight = weight::SemiLight;
+ else if( weight <= FC_WEIGHT_NORMAL )
+ pUpdate->m_eWeight = weight::Normal;
+ else if( weight <= FC_WEIGHT_MEDIUM )
+ pUpdate->m_eWeight = weight::Medium;
+ else if( weight <= FC_WEIGHT_SEMIBOLD )
+ pUpdate->m_eWeight = weight::SemiBold;
+ else if( weight <= FC_WEIGHT_BOLD )
+ pUpdate->m_eWeight = weight::Bold;
+ else if( weight <= FC_WEIGHT_ULTRABOLD )
+ pUpdate->m_eWeight = weight::UltraBold;
+ else
+ pUpdate->m_eWeight = weight::Black;
}
if( eSpacRes == FcResultMatch )
{
// set pitch
if( spacing == FC_PROPORTIONAL )
- (*it)->m_ePitch = pitch::Variable;
+ pUpdate->m_ePitch = pitch::Variable;
else if( spacing == FC_MONO || spacing == FC_CHARCELL )
- (*it)->m_ePitch = pitch::Fixed;
+ pUpdate->m_ePitch = pitch::Fixed;
}
if( eSlantRes == FcResultMatch )
{
// set italic
if( slant == FC_SLANT_ROMAN )
- (*it)->m_eItalic = italic::Upright;
+ pUpdate->m_eItalic = italic::Upright;
else if( slant == FC_SLANT_ITALIC )
- (*it)->m_eItalic = italic::Italic;
+ pUpdate->m_eItalic = italic::Italic;
else if( slant == FC_SLANT_OBLIQUE )
- (*it)->m_eItalic = italic::Oblique;
+ pUpdate->m_eItalic = italic::Oblique;
}
// update font cache
- m_pFontCache->updateFontCacheEntry( *it, false );
+ m_pFontCache->updateFontCacheEntry( pUpdate, false );
// sort into known fonts
fontID aFont = m_nNextFontID++;
- m_aFonts[ aFont ] = *it;
+ m_aFonts[ aFont ] = pUpdate;
m_aFontFileToFontID[ aBase ].insert( aFont );
nFonts++;
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "inserted font %s as fontID %d\n", family, aFont );
#endif
}
+ // clean up the fonts we did not put into the list
+ for( std::list< PrintFont* >::iterator it = aFonts.begin(); it != aFonts.end(); ++it )
+ {
+ if( *it != pUpdate )
+ {
+ m_pFontCache->updateFontCacheEntry( *it, false ); // prepare a cache entry for a collection item
+ delete *it;
+ }
+ }
}
}
-
// cleanup
if( pPattern )
- aWrapper.FcPatternDestroy( pPattern );
+ rWrapper.FcPatternDestroy( pPattern );
if( pFSet )
- aWrapper.FcFontSetDestroy( pFSet );
+ rWrapper.FcFontSetDestroy( pFSet );
if( pOSet )
- aWrapper.FcObjectSetDestroy( pOSet );
+ rWrapper.FcObjectSetDestroy( pOSet );
// how does one get rid of the config ?
#if OSL_DEBUG_LEVEL > 1
@@ -410,3 +539,120 @@ bool PrintFontManager::initFontconfig()
#endif // ENABLE_FONTCONFIG
return nFonts != 0;
}
+
+void PrintFontManager::deinitFontconfig()
+{
+ FontCfgWrapper::release();
+}
+
+bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo )
+{
+ FontCfgWrapper& rWrapper = FontCfgWrapper::get();
+ if( ! rWrapper.isValid() )
+ return false;
+
+ FcConfig* pConfig = rWrapper.getDefConfig();
+ FcPattern* pPattern = rWrapper.FcPatternCreate();
+
+ // populate pattern with font characteristics
+ 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 )
+ {
+ int nSlant = FC_SLANT_ROMAN;
+ switch( rInfo.m_eItalic )
+ {
+ case italic::Italic: nSlant = FC_SLANT_ITALIC;break;
+ case italic::Oblique: nSlant = FC_SLANT_OBLIQUE;break;
+ default:
+ break;
+ }
+ rWrapper.FcPatternAddInteger( pPattern, FC_SLANT, nSlant );
+ }
+ if( rInfo.m_eWeight != weight::Unknown )
+ {
+ int nWeight = FC_WEIGHT_NORMAL;
+ switch( rInfo.m_eWeight )
+ {
+ case weight::Thin: nWeight = FC_WEIGHT_THIN;break;
+ case weight::UltraLight: nWeight = FC_WEIGHT_ULTRALIGHT;break;
+ case weight::Light: nWeight = FC_WEIGHT_LIGHT;break;
+ case weight::SemiLight: nWeight = FC_WEIGHT_BOOK;break;
+ case weight::Normal: nWeight = FC_WEIGHT_NORMAL;break;
+ case weight::Medium: nWeight = FC_WEIGHT_MEDIUM;break;
+ case weight::SemiBold: nWeight = FC_WEIGHT_SEMIBOLD;break;
+ case weight::Bold: nWeight = FC_WEIGHT_BOLD;break;
+ case weight::UltraBold: nWeight = FC_WEIGHT_ULTRABOLD;break;
+ case weight::Black: nWeight = FC_WEIGHT_BLACK;break;
+ default:
+ break;
+ }
+ rWrapper.FcPatternAddInteger( pPattern, FC_WEIGHT, nWeight );
+ }
+ if( rInfo.m_eWidth != width::Unknown )
+ {
+ int nWidth = FC_WIDTH_NORMAL;
+ switch( rInfo.m_eWidth )
+ {
+ case width::UltraCondensed: nWidth = FC_WIDTH_ULTRACONDENSED;break;
+ case width::ExtraCondensed: nWidth = FC_WIDTH_EXTRACONDENSED;break;
+ case width::Condensed: nWidth = FC_WIDTH_CONDENSED;break;
+ case width::SemiCondensed: nWidth = FC_WIDTH_SEMICONDENSED;break;
+ case width::Normal: nWidth = FC_WIDTH_NORMAL;break;
+ case width::SemiExpanded: nWidth = FC_WIDTH_SEMIEXPANDED;break;
+ case width::Expanded: nWidth = FC_WIDTH_EXPANDED;break;
+ case width::ExtraExpanded: nWidth = FC_WIDTH_EXTRAEXPANDED;break;
+ case width::UltraExpanded: nWidth = FC_WIDTH_ULTRACONDENSED;break;
+ default:
+ break;
+ }
+ rWrapper.FcPatternAddInteger( pPattern, FC_WIDTH, nWidth );
+ }
+ if( rInfo.m_ePitch != pitch::Unknown )
+ {
+ int nSpacing = FC_PROPORTIONAL;
+ switch( rInfo.m_ePitch )
+ {
+ case pitch::Fixed: nSpacing = FC_MONO;break;
+ case pitch::Variable: nSpacing = FC_PROPORTIONAL;break;
+ default:
+ break;
+ }
+ rWrapper.FcPatternAddInteger( pPattern, FC_SPACING, nSpacing );
+ }
+
+ rWrapper.FcConfigSubstitute( pConfig, pPattern, FcMatchPattern );
+ rWrapper.FcDefaultSubstitute( pPattern );
+ FcResult eResult = FcResultNoMatch;
+ FcPattern* pResult = rWrapper.FcFontMatch( pConfig, pPattern, &eResult );
+ bool bSuccess = false;
+ if( pResult )
+ {
+ FcFontSet* pSet = rWrapper.FcFontSetCreate();
+ rWrapper.FcFontSetAdd( pSet, pResult );
+ if( pSet->nfont > 0 )
+ {
+ //extract the closest match
+ FcChar8* file = NULL;
+ FcResult eFileRes = rWrapper.FcPatternGetString( pSet->fonts[0], FC_FILE, 0, &file );
+ if( eFileRes == FcResultMatch )
+ {
+ OString aDir, aBase, aOrgPath( (sal_Char*)file );
+ splitPath( aOrgPath, aDir, aBase );
+ int nDirID = getDirectoryAtom( aDir, true );
+ fontID aFont = findFontFileID( nDirID, aBase );
+ if( aFont > 0 )
+ bSuccess = getFontFastInfo( aFont, rInfo );
+ }
+ }
+ // info: destroying the pSet destroys pResult implicitly
+ // since pResult was "added" to pSet
+ rWrapper.FcFontSetDestroy( pSet );
+ }
+
+ // cleanup
+ rWrapper.FcPatternDestroy( pPattern );
+
+ return bSuccess;
+}