1c82f2877SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3c82f2877SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4c82f2877SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5c82f2877SAndrew Rist  * distributed with this work for additional information
6c82f2877SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7c82f2877SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8c82f2877SAndrew Rist  * "License"); you may not use this file except in compliance
9c82f2877SAndrew Rist  * with the License.  You may obtain a copy of the License at
10c82f2877SAndrew Rist  *
11c82f2877SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12c82f2877SAndrew Rist  *
13c82f2877SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14c82f2877SAndrew Rist  * software distributed under the License is distributed on an
15c82f2877SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16c82f2877SAndrew Rist  * KIND, either express or implied.  See the License for the
17c82f2877SAndrew Rist  * specific language governing permissions and limitations
18c82f2877SAndrew Rist  * under the License.
19c82f2877SAndrew Rist  *
20c82f2877SAndrew Rist  *************************************************************/
21c82f2877SAndrew Rist 
22c82f2877SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "fontcache.hxx"
28cdf0e10cSrcweir #include "impfont.hxx"
29cdf0e10cSrcweir #include "vcl/fontmanager.hxx"
30cdf0e10cSrcweir 
31cdf0e10cSrcweir using namespace psp;
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #ifdef ENABLE_FONTCONFIG
34cdf0e10cSrcweir     #include <fontconfig/fontconfig.h>
35cdf0e10cSrcweir     #include <ft2build.h>
36cdf0e10cSrcweir     #include <fontconfig/fcfreetype.h>
37cdf0e10cSrcweir     // allow compile on baseline (currently with fontconfig 2.2.0)
38cdf0e10cSrcweir     #ifndef FC_WEIGHT_BOOK		// TODO: remove when baseline moves to fc>=2.2.1
39cdf0e10cSrcweir         #define FC_WEIGHT_BOOK 75
40cdf0e10cSrcweir     #endif
41cdf0e10cSrcweir     #ifndef FC_EMBEDDED_BITMAP	// TODO: remove when baseline moves to fc>=2.3.92
42cdf0e10cSrcweir         #define FC_EMBEDDED_BITMAP "embeddedbitmap"
43cdf0e10cSrcweir     #endif
44cdf0e10cSrcweir     #ifndef FC_FAMILYLANG		// TODO: remove when baseline moves to fc>=2.2.97
45cdf0e10cSrcweir         #define FC_FAMILYLANG "familylang"
46cdf0e10cSrcweir     #endif
47cdf0e10cSrcweir     #ifndef FC_HINT_STYLE		// TODO: remove when baseline moves to fc>=2.2.91
48cdf0e10cSrcweir     	#define FC_HINT_STYLE  "hintstyle"
49cdf0e10cSrcweir     	#define FC_HINT_NONE   0
50cdf0e10cSrcweir     	#define FC_HINT_SLIGHT 1
51cdf0e10cSrcweir     	#define FC_HINT_MEDIUM 2
52cdf0e10cSrcweir     	#define FC_HINT_FULL   3
53cdf0e10cSrcweir 	#endif
54cdf0e10cSrcweir #else
55cdf0e10cSrcweir     typedef void FcConfig;
56cdf0e10cSrcweir     typedef void FcObjectSet;
57cdf0e10cSrcweir     typedef void FcPattern;
58cdf0e10cSrcweir     typedef void FcFontSet;
59cdf0e10cSrcweir     typedef void FcCharSet;
60cdf0e10cSrcweir     typedef int FcResult;
61cdf0e10cSrcweir     typedef int FcBool;
62cdf0e10cSrcweir     typedef int FcMatchKind;
63cdf0e10cSrcweir     typedef char FcChar8;
64cdf0e10cSrcweir     typedef int FcChar32;
65cdf0e10cSrcweir     typedef unsigned int FT_UInt;
66cdf0e10cSrcweir     typedef void* FT_Face;
67cdf0e10cSrcweir     typedef int FcSetName;
68cdf0e10cSrcweir #endif
69cdf0e10cSrcweir 
70cdf0e10cSrcweir #include <cstdio>
71cdf0e10cSrcweir #include <cstdarg>
72cdf0e10cSrcweir 
73cdf0e10cSrcweir #include "unotools/atom.hxx"
74cdf0e10cSrcweir 
75cdf0e10cSrcweir #include "osl/module.h"
76cdf0e10cSrcweir #include "osl/thread.h"
77cdf0e10cSrcweir #include "osl/process.h"
78cdf0e10cSrcweir 
79cdf0e10cSrcweir #include "rtl/ustrbuf.hxx"
80cdf0e10cSrcweir #include "rtl/locale.hxx"
81cdf0e10cSrcweir 
82cdf0e10cSrcweir #include "sal/alloca.h"
83cdf0e10cSrcweir 
84cdf0e10cSrcweir #include <utility>
85cdf0e10cSrcweir #include <algorithm>
86cdf0e10cSrcweir 
87cdf0e10cSrcweir using namespace osl;
88cdf0e10cSrcweir using namespace rtl;
89cdf0e10cSrcweir 
90cdf0e10cSrcweir class FontCfgWrapper
91cdf0e10cSrcweir {
92cdf0e10cSrcweir     oslModule		m_pLib;
93cdf0e10cSrcweir     FcFontSet*      m_pOutlineSet;
94cdf0e10cSrcweir 
95cdf0e10cSrcweir     int             m_nFcVersion;
96cdf0e10cSrcweir     FcBool          (*m_pFcInit)();
97cdf0e10cSrcweir     int             (*m_pFcGetVersion)();
98cdf0e10cSrcweir     FcConfig*		(*m_pFcConfigGetCurrent)();
99cdf0e10cSrcweir     FcObjectSet*	(*m_pFcObjectSetVaBuild)(const char*,va_list);
100cdf0e10cSrcweir     void			(*m_pFcObjectSetDestroy)(FcObjectSet* pSet);
101cdf0e10cSrcweir     FcPattern*		(*m_pFcPatternCreate)();
102cdf0e10cSrcweir     void			(*m_pFcPatternDestroy)(FcPattern*);
103cdf0e10cSrcweir     FcFontSet*		(*m_pFcFontList)(FcConfig*,FcPattern*,FcObjectSet*);
104cdf0e10cSrcweir     FcFontSet*      (*m_pFcConfigGetFonts)(FcConfig*,FcSetName);
105cdf0e10cSrcweir     FcFontSet*		(*m_pFcFontSetCreate)();
106cdf0e10cSrcweir     FcCharSet*                (*m_pFcCharSetCreate)();
107cdf0e10cSrcweir     FcBool                    (*m_pFcCharSetAddChar)(FcCharSet *, FcChar32);
108cdf0e10cSrcweir     FcBool          (*m_pFcCharSetHasChar)(FcCharSet *, FcChar32);
109cdf0e10cSrcweir     void            (*m_pFcCharSetDestroy)(FcCharSet*);
110cdf0e10cSrcweir     void			(*m_pFcFontSetDestroy)(FcFontSet*);
111cdf0e10cSrcweir     FcBool			(*m_pFcFontSetAdd)(FcFontSet*,FcPattern*);
112cdf0e10cSrcweir     void            (*m_pFcPatternReference)(FcPattern*);
113cdf0e10cSrcweir     FcResult        (*m_pFcPatternGetCharSet)(const FcPattern*,const char*,int,FcCharSet**);
114cdf0e10cSrcweir     FcResult		(*m_pFcPatternGetString)(const FcPattern*,const char*,int,FcChar8**);
115cdf0e10cSrcweir     FcResult		(*m_pFcPatternGetInteger)(const FcPattern*,const char*,int,int*);
116cdf0e10cSrcweir     FcResult		(*m_pFcPatternGetDouble)(const FcPattern*,const char*,int,double*);
117cdf0e10cSrcweir     FcResult		(*m_pFcPatternGetBool)(const FcPattern*,const char*,int,FcBool*);
118cdf0e10cSrcweir     void			(*m_pFcDefaultSubstitute)(FcPattern *);
119cdf0e10cSrcweir     FcPattern*		(*m_pFcFontSetMatch)(FcConfig*,FcFontSet**, int, FcPattern*,FcResult*);
120cdf0e10cSrcweir     FcPattern*		(*m_pFcFontMatch)(FcConfig*,FcPattern*,FcResult*);
121cdf0e10cSrcweir     FcBool			(*m_pFcConfigAppFontAddFile)(FcConfig*, const FcChar8*);
122cdf0e10cSrcweir     FcBool			(*m_pFcConfigAppFontAddDir)(FcConfig*, const FcChar8*);
123cdf0e10cSrcweir     FcBool			(*m_pFcConfigParseAndLoad)(FcConfig*,const FcChar8*,FcBool);
124cdf0e10cSrcweir     FcBool			(*m_pFcConfigSubstitute)(FcConfig*,FcPattern*,FcMatchKind);
125cdf0e10cSrcweir 
126cdf0e10cSrcweir     FcPattern*		(*m_pFcPatternDuplicate)(const FcPattern*);
127cdf0e10cSrcweir     FcBool			(*m_pFcPatternAddInteger)(FcPattern*,const char*,int);
128cdf0e10cSrcweir     FcBool                    (*m_pFcPatternAddDouble)(FcPattern*,const char*,double);
129cdf0e10cSrcweir     FcBool                    (*m_pFcPatternAddBool)(FcPattern*,const char*,FcBool);
130cdf0e10cSrcweir     FcBool                    (*m_pFcPatternAddCharSet)(FcPattern*,const char*,const FcCharSet*);
131cdf0e10cSrcweir     FcBool			(*m_pFcPatternAddString)(FcPattern*,const char*,const FcChar8*);
132cdf0e10cSrcweir     FcBool                    (*m_pFcPatternDel)(FcPattern*,const char*);
133cdf0e10cSrcweir 
134cdf0e10cSrcweir 	FT_UInt         (*m_pFcFreeTypeCharIndex)(FT_Face,FcChar32);
135cdf0e10cSrcweir 
136cdf0e10cSrcweir     oslGenericFunction loadSymbol( const char* );
137cdf0e10cSrcweir     void addFontSet( FcSetName );
138cdf0e10cSrcweir 
139cdf0e10cSrcweir     FontCfgWrapper();
140cdf0e10cSrcweir     ~FontCfgWrapper();
141cdf0e10cSrcweir 
142cdf0e10cSrcweir public:
143cdf0e10cSrcweir     static FontCfgWrapper& get();
144cdf0e10cSrcweir     static void release();
145cdf0e10cSrcweir 
isValid() const146cdf0e10cSrcweir     bool isValid() const
147cdf0e10cSrcweir     { return m_pLib != NULL;}
148cdf0e10cSrcweir 
149cdf0e10cSrcweir     FcFontSet* getFontSet();
150cdf0e10cSrcweir 
FcInit()151cdf0e10cSrcweir     FcBool FcInit()
152cdf0e10cSrcweir     { return m_pFcInit(); }
153cdf0e10cSrcweir 
FcGetVersion()154cdf0e10cSrcweir     int FcGetVersion()
155cdf0e10cSrcweir     { return m_pFcGetVersion(); }
156cdf0e10cSrcweir 
FcConfigGetCurrent()157cdf0e10cSrcweir     FcConfig* FcConfigGetCurrent()
158cdf0e10cSrcweir     { return m_pFcConfigGetCurrent(); }
159cdf0e10cSrcweir 
FcObjectSetBuild(const char * first,...)160cdf0e10cSrcweir     FcObjectSet* FcObjectSetBuild( const char* first, ... )
161cdf0e10cSrcweir     {
162cdf0e10cSrcweir         va_list ap;
163cdf0e10cSrcweir         va_start( ap, first );
164cdf0e10cSrcweir         FcObjectSet* pSet = m_pFcObjectSetVaBuild( first, ap );
165cdf0e10cSrcweir         va_end( ap );
166cdf0e10cSrcweir         return pSet;
167cdf0e10cSrcweir     }
168cdf0e10cSrcweir 
FcObjectSetDestroy(FcObjectSet * pSet)169cdf0e10cSrcweir     void FcObjectSetDestroy( FcObjectSet* pSet )
170cdf0e10cSrcweir     { m_pFcObjectSetDestroy( pSet ); }
171cdf0e10cSrcweir 
FcPatternCreate()172cdf0e10cSrcweir     FcPattern* FcPatternCreate()
173cdf0e10cSrcweir     { return m_pFcPatternCreate(); }
174cdf0e10cSrcweir 
FcPatternDestroy(FcPattern * pPattern)175cdf0e10cSrcweir     void FcPatternDestroy( FcPattern* pPattern )
176cdf0e10cSrcweir     { m_pFcPatternDestroy( pPattern ); }
177cdf0e10cSrcweir 
FcFontList(FcConfig * pConfig,FcPattern * pPattern,FcObjectSet * pSet)178cdf0e10cSrcweir     FcFontSet* FcFontList( FcConfig* pConfig, FcPattern* pPattern, FcObjectSet* pSet )
179cdf0e10cSrcweir     { return m_pFcFontList( pConfig, pPattern, pSet ); }
180cdf0e10cSrcweir 
FcConfigGetFonts(FcConfig * pConfig,FcSetName eSet)181cdf0e10cSrcweir     FcFontSet* FcConfigGetFonts( FcConfig* pConfig, FcSetName eSet)
182cdf0e10cSrcweir     { return m_pFcConfigGetFonts( pConfig, eSet ); }
183cdf0e10cSrcweir 
FcFontSetCreate()184cdf0e10cSrcweir     FcFontSet* FcFontSetCreate()
185cdf0e10cSrcweir     { return m_pFcFontSetCreate(); }
186cdf0e10cSrcweir 
FcCharSetCreate()187cdf0e10cSrcweir     FcCharSet* FcCharSetCreate()
188cdf0e10cSrcweir     { return m_pFcCharSetCreate(); }
189cdf0e10cSrcweir 
FcCharSetAddChar(FcCharSet * fcs,FcChar32 ucs4)190cdf0e10cSrcweir     FcBool FcCharSetAddChar(FcCharSet *fcs, FcChar32 ucs4)
191cdf0e10cSrcweir     { return m_pFcCharSetAddChar(fcs, ucs4); }
192cdf0e10cSrcweir 
FcCharSetHasChar(FcCharSet * fcs,FcChar32 ucs4)193cdf0e10cSrcweir     FcBool FcCharSetHasChar(FcCharSet *fcs, FcChar32 ucs4)
194cdf0e10cSrcweir     { return m_pFcCharSetHasChar(fcs, ucs4); }
195cdf0e10cSrcweir 
FcCharSetDestroy(FcCharSet * pSet)196cdf0e10cSrcweir     void FcCharSetDestroy( FcCharSet* pSet )
197cdf0e10cSrcweir     { m_pFcCharSetDestroy( pSet );}
198cdf0e10cSrcweir 
FcFontSetDestroy(FcFontSet * pSet)199cdf0e10cSrcweir     void FcFontSetDestroy( FcFontSet* pSet )
200cdf0e10cSrcweir     { m_pFcFontSetDestroy( pSet );}
201cdf0e10cSrcweir 
FcFontSetAdd(FcFontSet * pSet,FcPattern * pPattern)202cdf0e10cSrcweir     FcBool FcFontSetAdd( FcFontSet* pSet, FcPattern* pPattern )
203cdf0e10cSrcweir     { return m_pFcFontSetAdd( pSet, pPattern ); }
204cdf0e10cSrcweir 
FcPatternReference(FcPattern * pPattern)205cdf0e10cSrcweir     void FcPatternReference( FcPattern* pPattern )
206cdf0e10cSrcweir     { m_pFcPatternReference( pPattern ); }
207cdf0e10cSrcweir 
FcPatternGetCharSet(const FcPattern * pPattern,const char * object,int n,FcCharSet ** s)208cdf0e10cSrcweir     FcResult FcPatternGetCharSet( const FcPattern* pPattern, const char* object, int n, FcCharSet** s )
209cdf0e10cSrcweir     { return m_pFcPatternGetCharSet( pPattern, object, n, s ); }
210cdf0e10cSrcweir 
FcPatternGetString(const FcPattern * pPattern,const char * object,int n,FcChar8 ** s)211cdf0e10cSrcweir     FcResult FcPatternGetString( const FcPattern* pPattern, const char* object, int n, FcChar8** s )
212cdf0e10cSrcweir     { return m_pFcPatternGetString( pPattern, object, n, s ); }
213cdf0e10cSrcweir 
FcPatternGetInteger(const FcPattern * pPattern,const char * object,int n,int * s)214cdf0e10cSrcweir     FcResult FcPatternGetInteger( const FcPattern* pPattern, const char* object, int n, int* s )
215cdf0e10cSrcweir     { return m_pFcPatternGetInteger( pPattern, object, n, s ); }
216cdf0e10cSrcweir 
FcPatternGetDouble(const FcPattern * pPattern,const char * object,int n,double * s)217cdf0e10cSrcweir     FcResult FcPatternGetDouble( const FcPattern* pPattern, const char* object, int n, double* s )
218cdf0e10cSrcweir     { return m_pFcPatternGetDouble( pPattern, object, n, s ); }
219cdf0e10cSrcweir 
FcPatternGetBool(const FcPattern * pPattern,const char * object,int n,FcBool * s)220cdf0e10cSrcweir     FcResult FcPatternGetBool( const FcPattern* pPattern, const char* object, int n, FcBool* s )
221cdf0e10cSrcweir     { return m_pFcPatternGetBool( pPattern, object, n, s ); }
FcConfigAppFontAddFile(FcConfig * pConfig,const FcChar8 * pFileName)222cdf0e10cSrcweir     FcBool FcConfigAppFontAddFile( FcConfig* pConfig, const FcChar8* pFileName )
223cdf0e10cSrcweir     { return m_pFcConfigAppFontAddFile( pConfig, pFileName ); }
FcConfigAppFontAddDir(FcConfig * pConfig,const FcChar8 * pDirName)224cdf0e10cSrcweir     FcBool FcConfigAppFontAddDir(FcConfig* pConfig, const FcChar8* pDirName )
225cdf0e10cSrcweir     { return m_pFcConfigAppFontAddDir( pConfig, pDirName ); }
FcConfigParseAndLoad(FcConfig * pConfig,const FcChar8 * pFileName,FcBool bComplain)226cdf0e10cSrcweir     FcBool FcConfigParseAndLoad( FcConfig* pConfig, const FcChar8* pFileName, FcBool bComplain )
227cdf0e10cSrcweir     { return m_pFcConfigParseAndLoad( pConfig, pFileName, bComplain ); }
228cdf0e10cSrcweir 
FcDefaultSubstitute(FcPattern * pPattern)229cdf0e10cSrcweir     void FcDefaultSubstitute( FcPattern* pPattern )
230cdf0e10cSrcweir     { m_pFcDefaultSubstitute( pPattern ); }
FcFontSetMatch(FcConfig * pConfig,FcFontSet ** ppFontSet,int nset,FcPattern * pPattern,FcResult * pResult)231cdf0e10cSrcweir     FcPattern* FcFontSetMatch( FcConfig* pConfig, FcFontSet **ppFontSet, int nset, FcPattern* pPattern, FcResult* pResult )
232cdf0e10cSrcweir     { return m_pFcFontSetMatch ? m_pFcFontSetMatch( pConfig, ppFontSet, nset, pPattern, pResult ) : 0; }
FcFontMatch(FcConfig * pConfig,FcPattern * pPattern,FcResult * pResult)233cdf0e10cSrcweir     FcPattern* FcFontMatch( FcConfig* pConfig, FcPattern* pPattern, FcResult* pResult )
234cdf0e10cSrcweir     { return m_pFcFontMatch( pConfig, pPattern, pResult ); }
FcConfigSubstitute(FcConfig * pConfig,FcPattern * pPattern,FcMatchKind eKind)235cdf0e10cSrcweir     FcBool FcConfigSubstitute( FcConfig* pConfig, FcPattern* pPattern, FcMatchKind eKind )
236cdf0e10cSrcweir     { return m_pFcConfigSubstitute( pConfig, pPattern, eKind ); }
237cdf0e10cSrcweir 
FcPatternDuplicate(const FcPattern * pPattern) const238cdf0e10cSrcweir     FcPattern* FcPatternDuplicate( const FcPattern* pPattern ) const
239cdf0e10cSrcweir     { return m_pFcPatternDuplicate( pPattern ); }
FcPatternAddInteger(FcPattern * pPattern,const char * pObject,int nValue)240cdf0e10cSrcweir     FcBool FcPatternAddInteger( FcPattern* pPattern, const char* pObject, int nValue )
241cdf0e10cSrcweir     { return m_pFcPatternAddInteger( pPattern, pObject, nValue ); }
FcPatternAddDouble(FcPattern * pPattern,const char * pObject,double nValue)242cdf0e10cSrcweir     FcBool FcPatternAddDouble( FcPattern* pPattern, const char* pObject, double nValue )
243cdf0e10cSrcweir     { return m_pFcPatternAddDouble( pPattern, pObject, nValue ); }
FcPatternAddString(FcPattern * pPattern,const char * pObject,const FcChar8 * pString)244cdf0e10cSrcweir     FcBool FcPatternAddString( FcPattern* pPattern, const char* pObject, const FcChar8* pString )
245cdf0e10cSrcweir     { return m_pFcPatternAddString( pPattern, pObject, pString ); }
FcPatternAddBool(FcPattern * pPattern,const char * pObject,bool nValue)246cdf0e10cSrcweir     FcBool FcPatternAddBool( FcPattern* pPattern, const char* pObject, bool nValue )
247cdf0e10cSrcweir     { return m_pFcPatternAddBool( pPattern, pObject, nValue ); }
FcPatternAddCharSet(FcPattern * pPattern,const char * pObject,const FcCharSet * pCharSet)248cdf0e10cSrcweir     FcBool FcPatternAddCharSet(FcPattern* pPattern,const char* pObject,const FcCharSet*pCharSet)
249cdf0e10cSrcweir     { return m_pFcPatternAddCharSet(pPattern,pObject,pCharSet); }
FcPatternDel(FcPattern * pPattern,const char * object)250cdf0e10cSrcweir 	FcBool FcPatternDel(FcPattern* pPattern, const char* object)
251cdf0e10cSrcweir 	{ return m_pFcPatternDel( pPattern, object); }
252cdf0e10cSrcweir 
FcFreeTypeCharIndex(FT_Face face,FcChar32 ucs4)253cdf0e10cSrcweir     FT_UInt FcFreeTypeCharIndex( FT_Face face, FcChar32 ucs4 )
254cdf0e10cSrcweir     { return m_pFcFreeTypeCharIndex ? m_pFcFreeTypeCharIndex( face, ucs4 ) : 0; }
255cdf0e10cSrcweir 
256cdf0e10cSrcweir public: // TODO: cleanup
257cdf0e10cSrcweir     FcResult FamilyFromPattern(FcPattern* pPattern, FcChar8 **family);
258cdf0e10cSrcweir     std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash > m_aFontNameToLocalized;
259cdf0e10cSrcweir     std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash > m_aLocalizedToCanonical;
260cdf0e10cSrcweir };
261cdf0e10cSrcweir 
loadSymbol(const char * pSymbol)262cdf0e10cSrcweir oslGenericFunction FontCfgWrapper::loadSymbol( const char* pSymbol )
263cdf0e10cSrcweir {
264cdf0e10cSrcweir     OUString aSym( OUString::createFromAscii( pSymbol ) );
265cdf0e10cSrcweir     oslGenericFunction pSym = osl_getFunctionSymbol( m_pLib, aSym.pData );
266cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
267cdf0e10cSrcweir     fprintf( stderr, "%s %s\n", pSymbol, pSym ? "found" : "not found" );
268cdf0e10cSrcweir #endif
269cdf0e10cSrcweir     return pSym;
270cdf0e10cSrcweir }
271cdf0e10cSrcweir 
FontCfgWrapper()272cdf0e10cSrcweir FontCfgWrapper::FontCfgWrapper()
273cdf0e10cSrcweir         : m_pLib( NULL ),
274cdf0e10cSrcweir           m_pOutlineSet( NULL ),
275cdf0e10cSrcweir           m_nFcVersion( 0 )
276cdf0e10cSrcweir {
277aa150a94SHerbert Dürr     m_pLib = osl_loadAsciiModule( "libfontconfig.so.1", SAL_LOADMODULE_LAZY );
278cdf0e10cSrcweir     if( !m_pLib )
279aa150a94SHerbert Dürr         m_pLib = osl_loadAsciiModule( "libfontconfig.so", SAL_LOADMODULE_LAZY );
280cdf0e10cSrcweir 
281cdf0e10cSrcweir     if( ! m_pLib )
282cdf0e10cSrcweir     {
283cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
284cdf0e10cSrcweir         fprintf( stderr, "no libfontconfig\n" );
285cdf0e10cSrcweir #endif
286cdf0e10cSrcweir         return;
287cdf0e10cSrcweir     }
288cdf0e10cSrcweir 
289cdf0e10cSrcweir     m_pFcInit = (FcBool(*)())
290cdf0e10cSrcweir         loadSymbol( "FcInit" );
291cdf0e10cSrcweir     m_pFcGetVersion = (int(*)())
292cdf0e10cSrcweir         loadSymbol( "FcGetVersion" );
293cdf0e10cSrcweir     m_pFcConfigGetCurrent = (FcConfig *(*)())
294cdf0e10cSrcweir         loadSymbol( "FcConfigGetCurrent" );
295cdf0e10cSrcweir     m_pFcObjectSetVaBuild = (FcObjectSet*(*)(const char*,va_list))
296cdf0e10cSrcweir         loadSymbol( "FcObjectSetVaBuild" );
297cdf0e10cSrcweir     m_pFcObjectSetDestroy = (void(*)(FcObjectSet*))
298cdf0e10cSrcweir         loadSymbol( "FcObjectSetDestroy" );
299cdf0e10cSrcweir     m_pFcPatternCreate = (FcPattern*(*)())
300cdf0e10cSrcweir         loadSymbol( "FcPatternCreate" );
301cdf0e10cSrcweir     m_pFcPatternDestroy = (void(*)(FcPattern*))
302cdf0e10cSrcweir         loadSymbol( "FcPatternDestroy" );
303cdf0e10cSrcweir     m_pFcFontList = (FcFontSet*(*)(FcConfig*,FcPattern*,FcObjectSet*))
304cdf0e10cSrcweir         loadSymbol( "FcFontList" );
305cdf0e10cSrcweir     m_pFcConfigGetFonts = (FcFontSet*(*)(FcConfig*,FcSetName))
306cdf0e10cSrcweir         loadSymbol( "FcConfigGetFonts" );
307cdf0e10cSrcweir     m_pFcFontSetCreate = (FcFontSet*(*)())
308cdf0e10cSrcweir         loadSymbol( "FcFontSetCreate" );
309cdf0e10cSrcweir     m_pFcCharSetCreate = (FcCharSet*(*)())
310cdf0e10cSrcweir         loadSymbol( "FcCharSetCreate" );
311cdf0e10cSrcweir     m_pFcCharSetAddChar = (FcBool(*)(FcCharSet*, FcChar32))
312cdf0e10cSrcweir         loadSymbol( "FcCharSetAddChar" );
313cdf0e10cSrcweir     m_pFcCharSetHasChar = (FcBool(*)(FcCharSet*, FcChar32))
314cdf0e10cSrcweir         loadSymbol( "FcCharSetHasChar" );
315cdf0e10cSrcweir     m_pFcCharSetDestroy = (void(*)(FcCharSet*))
316cdf0e10cSrcweir         loadSymbol( "FcCharSetDestroy" );
317cdf0e10cSrcweir     m_pFcFontSetDestroy = (void(*)(FcFontSet*))
318cdf0e10cSrcweir         loadSymbol( "FcFontSetDestroy" );
319cdf0e10cSrcweir     m_pFcFontSetAdd = (FcBool(*)(FcFontSet*,FcPattern*))
320cdf0e10cSrcweir         loadSymbol( "FcFontSetAdd" );
321cdf0e10cSrcweir     m_pFcPatternReference = (void(*)(FcPattern*))
322cdf0e10cSrcweir         loadSymbol( "FcPatternReference" );
323cdf0e10cSrcweir     m_pFcPatternGetCharSet = (FcResult(*)(const FcPattern*,const char*,int,FcCharSet**))
324cdf0e10cSrcweir         loadSymbol( "FcPatternGetCharSet" );
325cdf0e10cSrcweir     m_pFcPatternGetString = (FcResult(*)(const FcPattern*,const char*,int,FcChar8**))
326cdf0e10cSrcweir         loadSymbol( "FcPatternGetString" );
327cdf0e10cSrcweir     m_pFcPatternGetInteger = (FcResult(*)(const FcPattern*,const char*,int,int*))
328cdf0e10cSrcweir         loadSymbol( "FcPatternGetInteger" );
329cdf0e10cSrcweir     m_pFcPatternGetDouble = (FcResult(*)(const FcPattern*,const char*,int,double*))
330cdf0e10cSrcweir         loadSymbol( "FcPatternGetDouble" );
331cdf0e10cSrcweir     m_pFcPatternGetBool = (FcResult(*)(const FcPattern*,const char*,int,FcBool*))
332cdf0e10cSrcweir         loadSymbol( "FcPatternGetBool" );
333cdf0e10cSrcweir     m_pFcConfigAppFontAddFile = (FcBool(*)(FcConfig*, const FcChar8*))
334cdf0e10cSrcweir         loadSymbol( "FcConfigAppFontAddFile" );
335cdf0e10cSrcweir     m_pFcConfigAppFontAddDir = (FcBool(*)(FcConfig*, const FcChar8*))
336cdf0e10cSrcweir         loadSymbol( "FcConfigAppFontAddDir" );
337cdf0e10cSrcweir     m_pFcConfigParseAndLoad = (FcBool(*)(FcConfig*, const FcChar8*, FcBool))
338cdf0e10cSrcweir         loadSymbol( "FcConfigParseAndLoad" );
339cdf0e10cSrcweir     m_pFcDefaultSubstitute = (void(*)(FcPattern *))
340cdf0e10cSrcweir         loadSymbol( "FcDefaultSubstitute" );
341cdf0e10cSrcweir     m_pFcFontSetMatch = (FcPattern*(*)(FcConfig*,FcFontSet**,int,FcPattern*,FcResult*))
342cdf0e10cSrcweir         loadSymbol( "FcFontSetMatch" );
343cdf0e10cSrcweir     m_pFcFontMatch = (FcPattern*(*)(FcConfig*,FcPattern*,FcResult*))
344cdf0e10cSrcweir         loadSymbol( "FcFontMatch" );
345cdf0e10cSrcweir     m_pFcConfigSubstitute = (FcBool(*)(FcConfig*,FcPattern*,FcMatchKind))
346cdf0e10cSrcweir         loadSymbol( "FcConfigSubstitute" );
347cdf0e10cSrcweir 
348cdf0e10cSrcweir     m_pFcPatternDuplicate = (FcPattern*(*)(const FcPattern*))
349cdf0e10cSrcweir         loadSymbol( "FcPatternDuplicate" );
350cdf0e10cSrcweir     m_pFcPatternAddInteger = (FcBool(*)(FcPattern*,const char*,int))
351cdf0e10cSrcweir         loadSymbol( "FcPatternAddInteger" );
352cdf0e10cSrcweir     m_pFcPatternAddDouble = (FcBool(*)(FcPattern*,const char*,double))
353cdf0e10cSrcweir         loadSymbol( "FcPatternAddDouble" );
354cdf0e10cSrcweir     m_pFcPatternAddBool = (FcBool(*)(FcPattern*,const char*,FcBool))
355cdf0e10cSrcweir         loadSymbol( "FcPatternAddBool" );
356cdf0e10cSrcweir     m_pFcPatternAddCharSet = (FcBool(*)(FcPattern*,const char*,const FcCharSet *))
357cdf0e10cSrcweir         loadSymbol( "FcPatternAddCharSet" );
358cdf0e10cSrcweir     m_pFcPatternAddString = (FcBool(*)(FcPattern*,const char*,const FcChar8*))
359cdf0e10cSrcweir         loadSymbol( "FcPatternAddString" );
360cdf0e10cSrcweir     m_pFcPatternDel = (FcBool(*)(FcPattern*,const char*))
361cdf0e10cSrcweir 		loadSymbol( "FcPatternDel" );
362cdf0e10cSrcweir 
363cdf0e10cSrcweir     m_pFcFreeTypeCharIndex = (FT_UInt(*)(FT_Face,FcChar32))
364cdf0e10cSrcweir         loadSymbol( "FcFreeTypeCharIndex" );
365cdf0e10cSrcweir 
366cdf0e10cSrcweir     m_nFcVersion = FcGetVersion();
367cdf0e10cSrcweir #if (OSL_DEBUG_LEVEL > 1)
368cdf0e10cSrcweir     fprintf( stderr,"FC_VERSION = %05d\n", m_nFcVersion );
369cdf0e10cSrcweir #endif
370cdf0e10cSrcweir     // make minimum version configurable
371cdf0e10cSrcweir     const char* pMinFcVersion = getenv( "SAL_MIN_FC_VERSION");
372cdf0e10cSrcweir     if( pMinFcVersion )
373cdf0e10cSrcweir     {
374cdf0e10cSrcweir         const int nMinFcVersion = atoi( pMinFcVersion );
375cdf0e10cSrcweir         if( m_nFcVersion < nMinFcVersion )
376cdf0e10cSrcweir             m_pFcInit = NULL;
377cdf0e10cSrcweir     }
378cdf0e10cSrcweir 
379cdf0e10cSrcweir     if( ! (
380cdf0e10cSrcweir             m_pFcInit						&&
381cdf0e10cSrcweir             m_pFcGetVersion					&&
382cdf0e10cSrcweir             m_pFcConfigGetCurrent			&&
383cdf0e10cSrcweir             m_pFcObjectSetVaBuild			&&
384cdf0e10cSrcweir             m_pFcObjectSetDestroy			&&
385cdf0e10cSrcweir             m_pFcPatternCreate				&&
386cdf0e10cSrcweir             m_pFcPatternDestroy				&&
387cdf0e10cSrcweir             m_pFcFontList					&&
388cdf0e10cSrcweir             m_pFcConfigGetFonts             &&
389cdf0e10cSrcweir             m_pFcFontSetCreate				&&
390cdf0e10cSrcweir             m_pFcCharSetCreate				&&
391cdf0e10cSrcweir             m_pFcCharSetAddChar 			&&
392cdf0e10cSrcweir             m_pFcCharSetHasChar             &&
393cdf0e10cSrcweir             m_pFcCharSetDestroy             &&
394cdf0e10cSrcweir             m_pFcFontSetDestroy				&&
395cdf0e10cSrcweir             m_pFcFontSetAdd					&&
396cdf0e10cSrcweir             m_pFcPatternReference           &&
397cdf0e10cSrcweir             m_pFcPatternGetCharSet			&&
398cdf0e10cSrcweir             m_pFcPatternGetString			&&
399cdf0e10cSrcweir             m_pFcPatternGetInteger			&&
400cdf0e10cSrcweir             m_pFcPatternGetDouble			&&
401cdf0e10cSrcweir             m_pFcPatternGetBool				&&
402cdf0e10cSrcweir             m_pFcConfigAppFontAddFile				&&
403cdf0e10cSrcweir             m_pFcConfigAppFontAddDir				&&
404cdf0e10cSrcweir             m_pFcConfigParseAndLoad				&&
405cdf0e10cSrcweir             m_pFcFontMatch					&&
406cdf0e10cSrcweir             m_pFcDefaultSubstitute			&&
407cdf0e10cSrcweir             m_pFcConfigSubstitute			&&
408cdf0e10cSrcweir             m_pFcPatternDuplicate			&&
409cdf0e10cSrcweir             m_pFcPatternAddInteger			&&
410cdf0e10cSrcweir             m_pFcPatternAddDouble                     &&
411cdf0e10cSrcweir             m_pFcPatternAddCharSet			&&
412cdf0e10cSrcweir             m_pFcPatternAddBool 			&&
413cdf0e10cSrcweir             m_pFcPatternAddString 			&&
414cdf0e10cSrcweir             m_pFcPatternDel
415cdf0e10cSrcweir             ) )
416cdf0e10cSrcweir     {
417cdf0e10cSrcweir         osl_unloadModule( (oslModule)m_pLib );
418cdf0e10cSrcweir         m_pLib = NULL;
419cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
420cdf0e10cSrcweir         fprintf( stderr, "not all needed symbols were found in libfontconfig\n" );
421cdf0e10cSrcweir #endif
422cdf0e10cSrcweir         return;
423cdf0e10cSrcweir     }
424cdf0e10cSrcweir 
425cdf0e10cSrcweir 
426cdf0e10cSrcweir     FcInit();
427cdf0e10cSrcweir     if( ! FcConfigGetCurrent() )
428cdf0e10cSrcweir     {
429cdf0e10cSrcweir         osl_unloadModule( (oslModule)m_pLib );
430cdf0e10cSrcweir         m_pLib = NULL;
431cdf0e10cSrcweir     }
432cdf0e10cSrcweir }
433cdf0e10cSrcweir 
addFontSet(FcSetName eSetName)434cdf0e10cSrcweir void FontCfgWrapper::addFontSet( FcSetName eSetName )
435cdf0e10cSrcweir {
436cdf0e10cSrcweir     #ifdef ENABLE_FONTCONFIG
437cdf0e10cSrcweir     /*
438cdf0e10cSrcweir       add only acceptable outlined fonts to our config,
439cdf0e10cSrcweir       for future fontconfig use
440cdf0e10cSrcweir     */
441cdf0e10cSrcweir     FcFontSet* pOrig = FcConfigGetFonts( FcConfigGetCurrent(), eSetName );
442cdf0e10cSrcweir     if( !pOrig )
443cdf0e10cSrcweir         return;
444cdf0e10cSrcweir 
445cdf0e10cSrcweir 	// filter the font sets to remove obsolete or duplicate faces
446cdf0e10cSrcweir 	for( int i = 0; i < pOrig->nfont; ++i )
447cdf0e10cSrcweir 	{
448cdf0e10cSrcweir 		FcPattern* pOrigPattern = pOrig->fonts[i];
449cdf0e10cSrcweir 		// #i115131# ignore non-outline fonts
450cdf0e10cSrcweir 		FcBool bOutline = FcFalse;
451cdf0e10cSrcweir 		FcResult eOutRes = FcPatternGetBool( pOrigPattern, FC_OUTLINE, 0, &bOutline );
452cdf0e10cSrcweir 		if( (eOutRes != FcResultMatch) || (bOutline == FcFalse) )
453cdf0e10cSrcweir 			continue;
454cdf0e10cSrcweir 		// create a pattern to find eventually better alternatives
455cdf0e10cSrcweir 		FcPattern* pBetterPattern = pOrigPattern;
456cdf0e10cSrcweir 		if( m_nFcVersion > 20400 ) // #i115204# avoid trouble with old FC versions
457cdf0e10cSrcweir 		{
458cdf0e10cSrcweir 			FcPattern* pTestPattern = FcPatternDuplicate( pOrigPattern );
459*96cc864aSArrigo Marchiori             FcDefaultSubstitute( pTestPattern );
460cdf0e10cSrcweir 			FcPatternAddBool( pTestPattern, FC_OUTLINE, FcTrue );
461cdf0e10cSrcweir 			// TODO: ignore all attributes that are not interesting for finding dupes
462cdf0e10cSrcweir 			//       e.g. by using pattern->ImplFontAttr->pattern conversion
463cdf0e10cSrcweir 			FcPatternDel( pTestPattern, FC_FONTVERSION );
464cdf0e10cSrcweir 			FcPatternDel( pTestPattern, FC_CHARSET );
465cdf0e10cSrcweir 			FcPatternDel( pTestPattern, FC_FILE );
466cdf0e10cSrcweir 			// find the font face for the dupe-search pattern
467cdf0e10cSrcweir 			FcResult eFcResult = FcResultMatch;
468cdf0e10cSrcweir 			pBetterPattern = FcFontMatch( FcConfigGetCurrent(), pTestPattern, &eFcResult );
469cdf0e10cSrcweir 			FcPatternDestroy( pTestPattern );
470cdf0e10cSrcweir 			if( eFcResult != FcResultMatch )
471cdf0e10cSrcweir 				continue;
472cdf0e10cSrcweir 			// #i115131# double check results and eventually ignore them
473cdf0e10cSrcweir 			eOutRes = FcPatternGetBool( pBetterPattern, FC_OUTLINE, 0, &bOutline );
474cdf0e10cSrcweir 			if( (eOutRes != FcResultMatch) || (bOutline == FcFalse) )
475cdf0e10cSrcweir 				continue;
476cdf0e10cSrcweir 		}
477cdf0e10cSrcweir 		// insert best found pattern for the dupe-search pattern
478cdf0e10cSrcweir 		// TODO: skip inserting patterns that are already known in the target fontset
479cdf0e10cSrcweir 		FcPatternReference( pBetterPattern );
480cdf0e10cSrcweir 		FcFontSetAdd( m_pOutlineSet, pBetterPattern );
481cdf0e10cSrcweir 	}
482cdf0e10cSrcweir 
483cdf0e10cSrcweir     // TODO?: FcFontSetDestroy( pOrig );
484cdf0e10cSrcweir     #else
485cdf0e10cSrcweir     (void)eSetName; // prevent compiler warning about unused parameter
486cdf0e10cSrcweir     #endif
487cdf0e10cSrcweir }
488cdf0e10cSrcweir 
getFontSet()489cdf0e10cSrcweir FcFontSet* FontCfgWrapper::getFontSet()
490cdf0e10cSrcweir {
491cdf0e10cSrcweir     #ifdef ENABLE_FONTCONFIG
492cdf0e10cSrcweir     if( !m_pOutlineSet )
493cdf0e10cSrcweir     {
494cdf0e10cSrcweir         m_pOutlineSet = FcFontSetCreate();
495cdf0e10cSrcweir         addFontSet( FcSetSystem );
496cdf0e10cSrcweir 	if( m_nFcVersion > 20400 ) // #i85462# prevent crashes
497cdf0e10cSrcweir             addFontSet( FcSetApplication );
498cdf0e10cSrcweir     }
499cdf0e10cSrcweir     #endif
500cdf0e10cSrcweir 
501cdf0e10cSrcweir     return m_pOutlineSet;
502cdf0e10cSrcweir }
503cdf0e10cSrcweir 
~FontCfgWrapper()504cdf0e10cSrcweir FontCfgWrapper::~FontCfgWrapper()
505cdf0e10cSrcweir {
506cdf0e10cSrcweir 	if( m_pOutlineSet )
507cdf0e10cSrcweir 		FcFontSetDestroy( m_pOutlineSet );
508cdf0e10cSrcweir     if( m_pLib )
509cdf0e10cSrcweir         osl_unloadModule( (oslModule)m_pLib );
510cdf0e10cSrcweir }
511cdf0e10cSrcweir 
512cdf0e10cSrcweir static FontCfgWrapper* pOneInstance = NULL;
513cdf0e10cSrcweir 
get()514cdf0e10cSrcweir FontCfgWrapper& FontCfgWrapper::get()
515cdf0e10cSrcweir {
516cdf0e10cSrcweir     if( ! pOneInstance )
517cdf0e10cSrcweir         pOneInstance = new FontCfgWrapper();
518cdf0e10cSrcweir     return *pOneInstance;
519cdf0e10cSrcweir }
520cdf0e10cSrcweir 
release()521cdf0e10cSrcweir void FontCfgWrapper::release()
522cdf0e10cSrcweir {
523cdf0e10cSrcweir     if( pOneInstance )
524cdf0e10cSrcweir     {
525cdf0e10cSrcweir         delete pOneInstance;
526cdf0e10cSrcweir         pOneInstance = NULL;
527cdf0e10cSrcweir     }
528cdf0e10cSrcweir }
529cdf0e10cSrcweir 
530cdf0e10cSrcweir #ifdef ENABLE_FONTCONFIG
531cdf0e10cSrcweir namespace
532cdf0e10cSrcweir {
533cdf0e10cSrcweir     typedef std::pair<FcChar8*, FcChar8*> lang_and_family;
534cdf0e10cSrcweir 
535cdf0e10cSrcweir     class localizedsorter
536cdf0e10cSrcweir     {
537cdf0e10cSrcweir             rtl::OLocale maLoc;
538cdf0e10cSrcweir         public:
localizedsorter(rtl_Locale * pLoc)539cdf0e10cSrcweir             localizedsorter(rtl_Locale* pLoc) : maLoc(pLoc) {}
540cdf0e10cSrcweir             FcChar8* bestname(const std::vector<lang_and_family> &families);
541cdf0e10cSrcweir     };
542cdf0e10cSrcweir 
bestname(const std::vector<lang_and_family> & families)543cdf0e10cSrcweir     FcChar8* localizedsorter::bestname(const std::vector<lang_and_family> &families)
544cdf0e10cSrcweir     {
545cdf0e10cSrcweir         FcChar8* candidate = families.begin()->second;
546cdf0e10cSrcweir         rtl::OString sLangMatch(rtl::OUStringToOString(maLoc.getLanguage().toAsciiLowerCase(), RTL_TEXTENCODING_UTF8));
547cdf0e10cSrcweir 	rtl::OString sFullMatch = sLangMatch;
548cdf0e10cSrcweir         sFullMatch += OString('-');
549cdf0e10cSrcweir         sFullMatch += rtl::OUStringToOString(maLoc.getCountry().toAsciiLowerCase(), RTL_TEXTENCODING_UTF8);
550cdf0e10cSrcweir 
551cdf0e10cSrcweir         std::vector<lang_and_family>::const_iterator aEnd = families.end();
552cdf0e10cSrcweir         bool alreadyclosematch = false;
553cdf0e10cSrcweir         for( std::vector<lang_and_family>::const_iterator aIter = families.begin(); aIter != aEnd; ++aIter )
554cdf0e10cSrcweir         {
555cdf0e10cSrcweir             const char *pLang = (const char*)aIter->first;
556cdf0e10cSrcweir             if( rtl_str_compare( pLang, sFullMatch.getStr() ) == 0)
557cdf0e10cSrcweir             {
558cdf0e10cSrcweir                 // both language and country match
559cdf0e10cSrcweir                 candidate = aIter->second;
560cdf0e10cSrcweir                 break;
561cdf0e10cSrcweir             }
562cdf0e10cSrcweir             else if( alreadyclosematch )
563cdf0e10cSrcweir 	        continue;
564cdf0e10cSrcweir             else if( rtl_str_compare( pLang, sLangMatch.getStr()) == 0)
565cdf0e10cSrcweir             {
566cdf0e10cSrcweir                 // just the language matches
567cdf0e10cSrcweir                 candidate = aIter->second;
568cdf0e10cSrcweir                 alreadyclosematch = true;
569cdf0e10cSrcweir             }
570cdf0e10cSrcweir             else if( rtl_str_compare( pLang, "en") == 0)
571cdf0e10cSrcweir             {
572cdf0e10cSrcweir                 // fallback to the english family name
573cdf0e10cSrcweir                 candidate = aIter->second;
574cdf0e10cSrcweir             }
575cdf0e10cSrcweir         }
576cdf0e10cSrcweir         return candidate;
577cdf0e10cSrcweir     }
578cdf0e10cSrcweir }
579cdf0e10cSrcweir 
FamilyFromPattern(FcPattern * pPattern,FcChar8 ** family)580cdf0e10cSrcweir FcResult FontCfgWrapper::FamilyFromPattern(FcPattern* pPattern, FcChar8 **family)
581cdf0e10cSrcweir {
582cdf0e10cSrcweir     FcChar8 *origfamily;
583cdf0e10cSrcweir     FcResult eFamilyRes	= FcPatternGetString( pPattern, FC_FAMILY, 0, &origfamily );
584cdf0e10cSrcweir     *family = origfamily;
585cdf0e10cSrcweir 
586cdf0e10cSrcweir     if( eFamilyRes == FcResultMatch)
587cdf0e10cSrcweir     {
588cdf0e10cSrcweir         FcChar8* familylang = NULL;
589cdf0e10cSrcweir         if (FcPatternGetString( pPattern, FC_FAMILYLANG, 0, &familylang ) == FcResultMatch)
590cdf0e10cSrcweir         {
591cdf0e10cSrcweir             std::vector< lang_and_family > lang_and_families;
592cdf0e10cSrcweir             lang_and_families.push_back(lang_and_family(familylang, *family));
593cdf0e10cSrcweir             int k = 1;
594cdf0e10cSrcweir             while (1)
595cdf0e10cSrcweir             {
596cdf0e10cSrcweir                 if (FcPatternGetString( pPattern, FC_FAMILYLANG, k, &familylang ) != FcResultMatch)
597cdf0e10cSrcweir                     break;
598cdf0e10cSrcweir                 if (FcPatternGetString( pPattern, FC_FAMILY, k, family ) != FcResultMatch)
599cdf0e10cSrcweir                     break;
600cdf0e10cSrcweir                 lang_and_families.push_back(lang_and_family(familylang, *family));
601cdf0e10cSrcweir                 ++k;
602cdf0e10cSrcweir             }
603cdf0e10cSrcweir 
604cdf0e10cSrcweir             //possible to-do, sort by UILocale instead of process locale
605cdf0e10cSrcweir             rtl_Locale* pLoc;
606cdf0e10cSrcweir             osl_getProcessLocale(&pLoc);
607cdf0e10cSrcweir             localizedsorter aSorter(pLoc);
608cdf0e10cSrcweir             *family = aSorter.bestname(lang_and_families);
609cdf0e10cSrcweir 
610cdf0e10cSrcweir             std::vector<lang_and_family>::const_iterator aEnd = lang_and_families.end();
611cdf0e10cSrcweir             for (std::vector<lang_and_family>::const_iterator aIter = lang_and_families.begin(); aIter != aEnd; ++aIter)
612cdf0e10cSrcweir             {
613cdf0e10cSrcweir                 const char *candidate = (const char*)(aIter->second);
614cdf0e10cSrcweir                 if (rtl_str_compare(candidate, (const char*)(*family)) != 0)
615cdf0e10cSrcweir                     m_aFontNameToLocalized[OString(candidate)] = OString((const char*)(*family));
616cdf0e10cSrcweir             }
617cdf0e10cSrcweir             if (rtl_str_compare((const char*)origfamily, (const char*)(*family)) != 0)
618cdf0e10cSrcweir                 m_aLocalizedToCanonical[OString((const char*)(*family))] = OString((const char*)origfamily);
619cdf0e10cSrcweir         }
620cdf0e10cSrcweir     }
621cdf0e10cSrcweir 
622cdf0e10cSrcweir     return eFamilyRes;
623cdf0e10cSrcweir }
624cdf0e10cSrcweir 
625cdf0e10cSrcweir /*
626cdf0e10cSrcweir  * PrintFontManager::initFontconfig
627cdf0e10cSrcweir  */
initFontconfig()628cdf0e10cSrcweir bool PrintFontManager::initFontconfig()
629cdf0e10cSrcweir {
630cdf0e10cSrcweir     FontCfgWrapper& rWrapper = FontCfgWrapper::get();
631cdf0e10cSrcweir     if( ! rWrapper.isValid() )
632cdf0e10cSrcweir         return false;
633cdf0e10cSrcweir     return true;
634cdf0e10cSrcweir }
635cdf0e10cSrcweir 
636cdf0e10cSrcweir namespace
637cdf0e10cSrcweir {
convertWeight(int weight)638cdf0e10cSrcweir     weight::type convertWeight(int weight)
639cdf0e10cSrcweir     {
640cdf0e10cSrcweir         // set weight
641cdf0e10cSrcweir         if( weight <= FC_WEIGHT_THIN )
642cdf0e10cSrcweir             return weight::Thin;
643cdf0e10cSrcweir         else if( weight <= FC_WEIGHT_ULTRALIGHT )
644cdf0e10cSrcweir             return weight::UltraLight;
645cdf0e10cSrcweir         else if( weight <= FC_WEIGHT_LIGHT )
646cdf0e10cSrcweir             return weight::Light;
647cdf0e10cSrcweir         else if( weight <= FC_WEIGHT_BOOK )
648cdf0e10cSrcweir             return weight::SemiLight;
649cdf0e10cSrcweir         else if( weight <= FC_WEIGHT_NORMAL )
650cdf0e10cSrcweir             return weight::Normal;
651cdf0e10cSrcweir         else if( weight <= FC_WEIGHT_MEDIUM )
652cdf0e10cSrcweir             return weight::Medium;
653cdf0e10cSrcweir         else if( weight <= FC_WEIGHT_SEMIBOLD )
654cdf0e10cSrcweir             return weight::SemiBold;
655cdf0e10cSrcweir         else if( weight <= FC_WEIGHT_BOLD )
656cdf0e10cSrcweir             return weight::Bold;
657cdf0e10cSrcweir         else if( weight <= FC_WEIGHT_ULTRABOLD )
658cdf0e10cSrcweir             return weight::UltraBold;
659cdf0e10cSrcweir         return weight::Black;
660cdf0e10cSrcweir     }
661cdf0e10cSrcweir 
convertSlant(int slant)662cdf0e10cSrcweir     italic::type convertSlant(int slant)
663cdf0e10cSrcweir     {
664cdf0e10cSrcweir         // set italic
665cdf0e10cSrcweir         if( slant == FC_SLANT_ITALIC )
666cdf0e10cSrcweir             return italic::Italic;
667cdf0e10cSrcweir         else if( slant == FC_SLANT_OBLIQUE )
668cdf0e10cSrcweir             return italic::Oblique;
669cdf0e10cSrcweir         return italic::Upright;
670cdf0e10cSrcweir     }
671cdf0e10cSrcweir 
convertSpacing(int spacing)672cdf0e10cSrcweir     pitch::type convertSpacing(int spacing)
673cdf0e10cSrcweir     {
674cdf0e10cSrcweir         // set pitch
675cdf0e10cSrcweir         if( spacing == FC_MONO || spacing == FC_CHARCELL )
676cdf0e10cSrcweir             return pitch::Fixed;
677cdf0e10cSrcweir         return pitch::Variable;
678cdf0e10cSrcweir     }
679cdf0e10cSrcweir 
convertWidth(int width)680cdf0e10cSrcweir     width::type convertWidth(int width)
681cdf0e10cSrcweir     {
682cdf0e10cSrcweir         if (width == FC_WIDTH_ULTRACONDENSED)
683cdf0e10cSrcweir             return width::UltraCondensed;
684cdf0e10cSrcweir         else if (width == FC_WIDTH_EXTRACONDENSED)
685cdf0e10cSrcweir             return width::ExtraCondensed;
686cdf0e10cSrcweir         else if (width == FC_WIDTH_CONDENSED)
687cdf0e10cSrcweir             return width::Condensed;
688cdf0e10cSrcweir         else if (width == FC_WIDTH_SEMICONDENSED)
689cdf0e10cSrcweir             return width::SemiCondensed;
690cdf0e10cSrcweir         else if (width == FC_WIDTH_SEMIEXPANDED)
691cdf0e10cSrcweir             return width::SemiExpanded;
692cdf0e10cSrcweir         else if (width == FC_WIDTH_EXPANDED)
693cdf0e10cSrcweir             return width::Expanded;
694cdf0e10cSrcweir         else if (width == FC_WIDTH_EXTRAEXPANDED)
695cdf0e10cSrcweir             return width::ExtraExpanded;
696cdf0e10cSrcweir         else if (width == FC_WIDTH_ULTRAEXPANDED)
697cdf0e10cSrcweir             return width::UltraExpanded;
698cdf0e10cSrcweir         return width::Normal;
699cdf0e10cSrcweir     }
700cdf0e10cSrcweir }
701cdf0e10cSrcweir 
countFontconfigFonts(std::hash_map<rtl::OString,int,rtl::OStringHash> & o_rVisitedPaths)702cdf0e10cSrcweir int PrintFontManager::countFontconfigFonts( std::hash_map<rtl::OString, int, rtl::OStringHash>& o_rVisitedPaths )
703cdf0e10cSrcweir {
704cdf0e10cSrcweir     int nFonts = 0;
705cdf0e10cSrcweir 
706cdf0e10cSrcweir     FontCfgWrapper& rWrapper = FontCfgWrapper::get();
707cdf0e10cSrcweir     if( !rWrapper.isValid() )
708cdf0e10cSrcweir         return 0;
709cdf0e10cSrcweir 
710cdf0e10cSrcweir     FcFontSet* pFSet = rWrapper.getFontSet();
711cdf0e10cSrcweir     if( pFSet )
712cdf0e10cSrcweir     {
713cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
714cdf0e10cSrcweir         fprintf( stderr, "found %d entries in fontconfig fontset\n", pFSet->nfont );
715cdf0e10cSrcweir #endif
716cdf0e10cSrcweir         for( int i = 0; i < pFSet->nfont; i++ )
717cdf0e10cSrcweir         {
718cdf0e10cSrcweir             FcChar8* file = NULL;
719cdf0e10cSrcweir             FcChar8* family = NULL;
720cdf0e10cSrcweir             FcChar8* style = NULL;
721cdf0e10cSrcweir             int slant = 0;
722cdf0e10cSrcweir             int weight = 0;
723cdf0e10cSrcweir             int spacing = 0;
724cdf0e10cSrcweir             int nCollectionEntry = -1;
725cdf0e10cSrcweir             FcBool outline = false;
726cdf0e10cSrcweir 
727cdf0e10cSrcweir             FcResult eFileRes	      = rWrapper.FcPatternGetString( pFSet->fonts[i], FC_FILE, 0, &file );
728cdf0e10cSrcweir             FcResult eFamilyRes       = rWrapper.FamilyFromPattern( pFSet->fonts[i], &family );
729cdf0e10cSrcweir             FcResult eStyleRes	      = rWrapper.FcPatternGetString( pFSet->fonts[i], FC_STYLE, 0, &style );
730cdf0e10cSrcweir             FcResult eSlantRes	      = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_SLANT, 0, &slant );
731cdf0e10cSrcweir             FcResult eWeightRes	      = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_WEIGHT, 0, &weight );
732cdf0e10cSrcweir             FcResult eSpacRes	      = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_SPACING, 0, &spacing );
733cdf0e10cSrcweir             FcResult eOutRes	      = rWrapper.FcPatternGetBool( pFSet->fonts[i], FC_OUTLINE, 0, &outline );
734cdf0e10cSrcweir             FcResult eIndexRes        = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_INDEX, 0, &nCollectionEntry );
735cdf0e10cSrcweir 
736cdf0e10cSrcweir             if( eFileRes != FcResultMatch || eFamilyRes != FcResultMatch || eOutRes != FcResultMatch )
737cdf0e10cSrcweir                 continue;
738cdf0e10cSrcweir 
739cdf0e10cSrcweir #if (OSL_DEBUG_LEVEL > 2)
740cdf0e10cSrcweir             fprintf( stderr, "found font \"%s\" in file %s\n"
741cdf0e10cSrcweir                      "   weight = %d, slant = %d, style = \"%s\"\n"
742cdf0e10cSrcweir                      "   spacing = %d, outline = %d\n"
743cdf0e10cSrcweir                      , family, file
744cdf0e10cSrcweir                      , eWeightRes == FcResultMatch ? weight : -1
745cdf0e10cSrcweir                      , eSpacRes == FcResultMatch ? slant : -1
746cdf0e10cSrcweir                      , eStyleRes == FcResultMatch ? (const char*) style : "<nil>"
747cdf0e10cSrcweir                      , eSpacRes == FcResultMatch ? spacing : -1
748cdf0e10cSrcweir                      , eOutRes == FcResultMatch ? outline : -1
749cdf0e10cSrcweir                      );
750cdf0e10cSrcweir #endif
751cdf0e10cSrcweir 
752cdf0e10cSrcweir //            OSL_ASSERT(eOutRes != FcResultMatch || outline);
753cdf0e10cSrcweir 
754cdf0e10cSrcweir             // only outline fonts are usable to psprint anyway
755cdf0e10cSrcweir             if( eOutRes == FcResultMatch && ! outline )
756cdf0e10cSrcweir                 continue;
757cdf0e10cSrcweir 
758cdf0e10cSrcweir             // see if this font is already cached
759cdf0e10cSrcweir             // update attributes
760cdf0e10cSrcweir             std::list< PrintFont* > aFonts;
761cdf0e10cSrcweir             OString aDir, aBase, aOrgPath( (sal_Char*)file );
762cdf0e10cSrcweir             splitPath( aOrgPath, aDir, aBase );
763cdf0e10cSrcweir 
764cdf0e10cSrcweir             o_rVisitedPaths[aDir] = 1;
765cdf0e10cSrcweir 
766cdf0e10cSrcweir             int nDirID = getDirectoryAtom( aDir, true );
767cdf0e10cSrcweir             if( ! m_pFontCache->getFontCacheFile( nDirID, aBase, aFonts ) )
768cdf0e10cSrcweir             {
769cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 2
770cdf0e10cSrcweir                 fprintf( stderr, "file %s not cached\n", aBase.getStr() );
771cdf0e10cSrcweir #endif
772cdf0e10cSrcweir                 // not known, analyze font file to get attributes
773cdf0e10cSrcweir                 // not described by fontconfig (e.g. alias names, PSName)
774cdf0e10cSrcweir                 std::list< OString > aDummy;
775cdf0e10cSrcweir                 analyzeFontFile( nDirID, aBase, aDummy, aFonts );
776cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
777cdf0e10cSrcweir                 if( aFonts.empty() )
778cdf0e10cSrcweir                     fprintf( stderr, "Warning: file \"%s\" is unusable to psprint\n", aOrgPath.getStr() );
779cdf0e10cSrcweir #endif
780cdf0e10cSrcweir             }
781cdf0e10cSrcweir             if( aFonts.empty() )
782cdf0e10cSrcweir             {
783cdf0e10cSrcweir                 // TODO: remove fonts unusable to psprint from fontset
784cdf0e10cSrcweir                 continue;
785cdf0e10cSrcweir             }
786cdf0e10cSrcweir 
787cdf0e10cSrcweir             int nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, OStringToOUString( OString( (sal_Char*)family ), RTL_TEXTENCODING_UTF8 ), sal_True );
788cdf0e10cSrcweir             PrintFont* pUpdate = aFonts.front();
789cdf0e10cSrcweir             std::list<PrintFont*>::const_iterator second_font = aFonts.begin();
790cdf0e10cSrcweir             ++second_font;
791cdf0e10cSrcweir             if( second_font != aFonts.end() ) // more than one font
792cdf0e10cSrcweir             {
793cdf0e10cSrcweir                 // a collection entry, get the correct index
794cdf0e10cSrcweir                 if( eIndexRes == FcResultMatch && nCollectionEntry != -1 )
795cdf0e10cSrcweir                 {
796cdf0e10cSrcweir                     for( std::list< PrintFont* >::iterator it = aFonts.begin(); it != aFonts.end(); ++it )
797cdf0e10cSrcweir                     {
798cdf0e10cSrcweir                         if( (*it)->m_eType == fonttype::TrueType &&
799cdf0e10cSrcweir                             static_cast<TrueTypeFontFile*>(*it)->m_nCollectionEntry == nCollectionEntry )
800cdf0e10cSrcweir                         {
801cdf0e10cSrcweir                             pUpdate = *it;
802cdf0e10cSrcweir                             break;
803cdf0e10cSrcweir                         }
804cdf0e10cSrcweir                     }
805cdf0e10cSrcweir                     // update collection entry
806cdf0e10cSrcweir                     // additional entries will be created in the cache
807cdf0e10cSrcweir                     // if this is a new index (that is if the loop above
808cdf0e10cSrcweir                     // ran to the end of the list)
809cdf0e10cSrcweir                     if( pUpdate->m_eType == fonttype::TrueType ) // sanity check, this should always be the case here
810cdf0e10cSrcweir                         static_cast<TrueTypeFontFile*>(pUpdate)->m_nCollectionEntry = nCollectionEntry;
811cdf0e10cSrcweir                 }
812cdf0e10cSrcweir                 else
813cdf0e10cSrcweir                 {
814cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
815cdf0e10cSrcweir                     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 );
816cdf0e10cSrcweir #endif
817cdf0e10cSrcweir                     // we have found more than one font in this file
818cdf0e10cSrcweir                     // but fontconfig will not tell us which index is meant
819cdf0e10cSrcweir                     // -> something is in disorder, do not use this font
820cdf0e10cSrcweir                     pUpdate = NULL;
821cdf0e10cSrcweir                 }
822cdf0e10cSrcweir             }
823cdf0e10cSrcweir 
824cdf0e10cSrcweir             if( pUpdate )
825cdf0e10cSrcweir             {
826cdf0e10cSrcweir                 // set family name
827cdf0e10cSrcweir                 if( pUpdate->m_nFamilyName != nFamilyName )
828cdf0e10cSrcweir                 {
829cdf0e10cSrcweir #if 0 // fontconfig prefers nameid=16 for the family name which is all fine
830cdf0e10cSrcweir       // but Writer suffers from #i79878#
831cdf0e10cSrcweir       // the only reasonable workaround for now is to use the classic nameid=1
832cdf0e10cSrcweir                     pUpdate->m_aAliases.remove( pUpdate->m_nFamilyName );
833cdf0e10cSrcweir                     pUpdate->m_aAliases.push_back( pUpdate->m_nFamilyName );
834cdf0e10cSrcweir                     pUpdate->m_aAliases.remove( nFamilyName );
835cdf0e10cSrcweir                     pUpdate->m_nFamilyName = nFamilyName;
836cdf0e10cSrcweir #endif
837cdf0e10cSrcweir                 }
838cdf0e10cSrcweir                 if( eWeightRes == FcResultMatch )
839cdf0e10cSrcweir 					pUpdate->m_eWeight = convertWeight(weight);
840cdf0e10cSrcweir                 if( eSpacRes == FcResultMatch )
841cdf0e10cSrcweir                     pUpdate->m_ePitch = convertSpacing(spacing);
842cdf0e10cSrcweir                 if( eSlantRes == FcResultMatch )
843cdf0e10cSrcweir 					pUpdate->m_eItalic = convertSlant(slant);
844cdf0e10cSrcweir                 if( eStyleRes == FcResultMatch )
845cdf0e10cSrcweir                 {
846cdf0e10cSrcweir                     pUpdate->m_aStyleName = OStringToOUString( OString( (sal_Char*)style ), RTL_TEXTENCODING_UTF8 );
847cdf0e10cSrcweir                 }
848cdf0e10cSrcweir 
849cdf0e10cSrcweir                 // update font cache
850cdf0e10cSrcweir                 m_pFontCache->updateFontCacheEntry( pUpdate, false );
851cdf0e10cSrcweir                 // sort into known fonts
852cdf0e10cSrcweir                 fontID aFont = m_nNextFontID++;
853cdf0e10cSrcweir                 m_aFonts[ aFont ] = pUpdate;
854cdf0e10cSrcweir                 m_aFontFileToFontID[ aBase ].insert( aFont );
855cdf0e10cSrcweir                 nFonts++;
856cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 2
857cdf0e10cSrcweir                 fprintf( stderr, "inserted font %s as fontID %d\n", family, aFont );
858cdf0e10cSrcweir #endif
859cdf0e10cSrcweir             }
860cdf0e10cSrcweir             // clean up the fonts we did not put into the list
861cdf0e10cSrcweir             for( std::list< PrintFont* >::iterator it = aFonts.begin(); it != aFonts.end(); ++it )
862cdf0e10cSrcweir             {
863cdf0e10cSrcweir                 if( *it != pUpdate )
864cdf0e10cSrcweir                 {
865cdf0e10cSrcweir                     m_pFontCache->updateFontCacheEntry( *it, false ); // prepare a cache entry for a collection item
866cdf0e10cSrcweir                     delete *it;
867cdf0e10cSrcweir                 }
868cdf0e10cSrcweir             }
869cdf0e10cSrcweir         }
870cdf0e10cSrcweir     }
871cdf0e10cSrcweir 
872cdf0e10cSrcweir     // how does one get rid of the config ?
873cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
874cdf0e10cSrcweir     fprintf( stderr, "inserted %d fonts from fontconfig\n", nFonts );
875cdf0e10cSrcweir #endif
876cdf0e10cSrcweir     return nFonts;
877cdf0e10cSrcweir }
878cdf0e10cSrcweir 
deinitFontconfig()879cdf0e10cSrcweir void PrintFontManager::deinitFontconfig()
880cdf0e10cSrcweir {
881cdf0e10cSrcweir     FontCfgWrapper::release();
882cdf0e10cSrcweir }
883cdf0e10cSrcweir 
FreeTypeCharIndex(void * pFace,sal_uInt32 aChar)884cdf0e10cSrcweir int PrintFontManager::FreeTypeCharIndex( void *pFace, sal_uInt32 aChar )
885cdf0e10cSrcweir {
886cdf0e10cSrcweir     FontCfgWrapper& rWrapper = FontCfgWrapper::get();
887cdf0e10cSrcweir     return rWrapper.isValid() ? rWrapper.FcFreeTypeCharIndex( (FT_Face)pFace, aChar ) : 0;
888cdf0e10cSrcweir }
889cdf0e10cSrcweir 
addFontconfigDir(const rtl::OString & rDirName)890cdf0e10cSrcweir bool PrintFontManager::addFontconfigDir( const rtl::OString& rDirName )
891cdf0e10cSrcweir {
892cdf0e10cSrcweir     FontCfgWrapper& rWrapper = FontCfgWrapper::get();
893cdf0e10cSrcweir     if( ! rWrapper.isValid() )
894cdf0e10cSrcweir         return false;
895cdf0e10cSrcweir 
896cdf0e10cSrcweir     // workaround for a stability problems in older FC versions
897cdf0e10cSrcweir     // when handling application specifc fonts
898cdf0e10cSrcweir     const int nVersion = rWrapper.FcGetVersion();
899cdf0e10cSrcweir     if( nVersion <= 20400 )
900cdf0e10cSrcweir         return false;
901cdf0e10cSrcweir     const char* pDirName = (const char*)rDirName.getStr();
902cdf0e10cSrcweir     bool bDirOk = (rWrapper.FcConfigAppFontAddDir( rWrapper.FcConfigGetCurrent(), (FcChar8*)pDirName ) == FcTrue);
903cdf0e10cSrcweir 
904cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
905cdf0e10cSrcweir     fprintf( stderr, "FcConfigAppFontAddDir( \"%s\") => %d\n", pDirName, bDirOk );
906cdf0e10cSrcweir #endif
907cdf0e10cSrcweir 
908cdf0e10cSrcweir     if( !bDirOk )
909cdf0e10cSrcweir         return false;
910cdf0e10cSrcweir 
911cdf0e10cSrcweir     // load dir-specific fc-config file too if available
912cdf0e10cSrcweir     const rtl::OString aConfFileName = rDirName + "/fc_local.conf";
913cdf0e10cSrcweir     FILE* pCfgFile = fopen( aConfFileName.getStr(), "rb" );
914cdf0e10cSrcweir     if( pCfgFile )
915cdf0e10cSrcweir     {
916cdf0e10cSrcweir         fclose( pCfgFile);
917cdf0e10cSrcweir         bool bCfgOk = rWrapper.FcConfigParseAndLoad( rWrapper.FcConfigGetCurrent(),
918cdf0e10cSrcweir                         (FcChar8*)aConfFileName.getStr(), FcTrue );
919cdf0e10cSrcweir         if( !bCfgOk )
920cdf0e10cSrcweir             fprintf( stderr, "FcConfigParseAndLoad( \"%s\") => %d\n", aConfFileName.getStr(), bCfgOk );
921cdf0e10cSrcweir     }
922cdf0e10cSrcweir 
923cdf0e10cSrcweir     return true;
924cdf0e10cSrcweir }
925cdf0e10cSrcweir 
addtopattern(FontCfgWrapper & rWrapper,FcPattern * pPattern,italic::type eItalic,weight::type eWeight,width::type eWidth,pitch::type ePitch)926cdf0e10cSrcweir static void addtopattern(FontCfgWrapper& rWrapper, FcPattern *pPattern,
927cdf0e10cSrcweir 	italic::type eItalic, weight::type eWeight, width::type eWidth, pitch::type ePitch)
928cdf0e10cSrcweir {
929cdf0e10cSrcweir     if( eItalic != italic::Unknown )
930cdf0e10cSrcweir     {
931cdf0e10cSrcweir         int nSlant = FC_SLANT_ROMAN;
932cdf0e10cSrcweir         switch( eItalic )
933cdf0e10cSrcweir         {
934cdf0e10cSrcweir             case italic::Italic:	 	nSlant = FC_SLANT_ITALIC;break;
935cdf0e10cSrcweir             case italic::Oblique:	 	nSlant = FC_SLANT_OBLIQUE;break;
936cdf0e10cSrcweir             default:
937cdf0e10cSrcweir                 break;
938cdf0e10cSrcweir         }
939cdf0e10cSrcweir         rWrapper.FcPatternAddInteger( pPattern, FC_SLANT, nSlant );
940cdf0e10cSrcweir     }
941cdf0e10cSrcweir     if( eWeight != weight::Unknown )
942cdf0e10cSrcweir     {
943cdf0e10cSrcweir         int nWeight = FC_WEIGHT_NORMAL;
944cdf0e10cSrcweir         switch( eWeight )
945cdf0e10cSrcweir         {
946cdf0e10cSrcweir             case weight::Thin:			nWeight = FC_WEIGHT_THIN;break;
947cdf0e10cSrcweir             case weight::UltraLight:	nWeight = FC_WEIGHT_ULTRALIGHT;break;
948cdf0e10cSrcweir             case weight::Light:			nWeight = FC_WEIGHT_LIGHT;break;
949cdf0e10cSrcweir             case weight::SemiLight:		nWeight = FC_WEIGHT_BOOK;break;
950cdf0e10cSrcweir             case weight::Normal:		nWeight = FC_WEIGHT_NORMAL;break;
951cdf0e10cSrcweir             case weight::Medium:		nWeight = FC_WEIGHT_MEDIUM;break;
952cdf0e10cSrcweir             case weight::SemiBold:		nWeight = FC_WEIGHT_SEMIBOLD;break;
953cdf0e10cSrcweir             case weight::Bold:			nWeight = FC_WEIGHT_BOLD;break;
954cdf0e10cSrcweir             case weight::UltraBold:		nWeight	= FC_WEIGHT_ULTRABOLD;break;
955cdf0e10cSrcweir             case weight::Black:			nWeight	= FC_WEIGHT_BLACK;break;
956cdf0e10cSrcweir             default:
957cdf0e10cSrcweir                 break;
958cdf0e10cSrcweir         }
959cdf0e10cSrcweir         rWrapper.FcPatternAddInteger( pPattern, FC_WEIGHT, nWeight );
960cdf0e10cSrcweir     }
961cdf0e10cSrcweir     if( eWidth != width::Unknown )
962cdf0e10cSrcweir     {
963cdf0e10cSrcweir         int nWidth = FC_WIDTH_NORMAL;
964cdf0e10cSrcweir         switch( eWidth )
965cdf0e10cSrcweir         {
966cdf0e10cSrcweir             case width::UltraCondensed:	nWidth = FC_WIDTH_ULTRACONDENSED;break;
967cdf0e10cSrcweir             case width::ExtraCondensed: nWidth = FC_WIDTH_EXTRACONDENSED;break;
968cdf0e10cSrcweir             case width::Condensed:		nWidth = FC_WIDTH_CONDENSED;break;
969cdf0e10cSrcweir             case width::SemiCondensed:	nWidth = FC_WIDTH_SEMICONDENSED;break;
970cdf0e10cSrcweir             case width::Normal:			nWidth = FC_WIDTH_NORMAL;break;
971cdf0e10cSrcweir             case width::SemiExpanded:	nWidth = FC_WIDTH_SEMIEXPANDED;break;
972cdf0e10cSrcweir             case width::Expanded:		nWidth = FC_WIDTH_EXPANDED;break;
973cdf0e10cSrcweir             case width::ExtraExpanded:	nWidth = FC_WIDTH_EXTRAEXPANDED;break;
974cdf0e10cSrcweir             case width::UltraExpanded:	nWidth = FC_WIDTH_ULTRACONDENSED;break;
975cdf0e10cSrcweir             default:
976cdf0e10cSrcweir                 break;
977cdf0e10cSrcweir         }
978cdf0e10cSrcweir         rWrapper.FcPatternAddInteger( pPattern, FC_WIDTH, nWidth );
979cdf0e10cSrcweir     }
980cdf0e10cSrcweir     if( ePitch != pitch::Unknown )
981cdf0e10cSrcweir     {
982cdf0e10cSrcweir         int nSpacing = FC_PROPORTIONAL;
983cdf0e10cSrcweir         switch( ePitch )
984cdf0e10cSrcweir         {
985cdf0e10cSrcweir             case pitch::Fixed:			nSpacing = FC_MONO;break;
986cdf0e10cSrcweir             case pitch::Variable:		nSpacing = FC_PROPORTIONAL;break;
987cdf0e10cSrcweir             default:
988cdf0e10cSrcweir                 break;
989cdf0e10cSrcweir         }
990cdf0e10cSrcweir         rWrapper.FcPatternAddInteger( pPattern, FC_SPACING, nSpacing );
991cdf0e10cSrcweir         if (nSpacing == FC_MONO)
992cdf0e10cSrcweir             rWrapper.FcPatternAddString( pPattern, FC_FAMILY, (FcChar8*)"monospace");
993cdf0e10cSrcweir     }
994cdf0e10cSrcweir }
995cdf0e10cSrcweir 
Substitute(const rtl::OUString & rFontName,rtl::OUString & rMissingCodes,const rtl::OString & rLangAttrib,italic::type & rItalic,weight::type & rWeight,width::type & rWidth,pitch::type & rPitch) const996cdf0e10cSrcweir rtl::OUString PrintFontManager::Substitute(const rtl::OUString& rFontName,
997cdf0e10cSrcweir     rtl::OUString& rMissingCodes, const rtl::OString &rLangAttrib,
998cdf0e10cSrcweir     italic::type &rItalic, weight::type &rWeight,
999cdf0e10cSrcweir     width::type &rWidth, pitch::type &rPitch) const
1000cdf0e10cSrcweir {
1001cdf0e10cSrcweir     rtl::OUString aName;
1002cdf0e10cSrcweir     FontCfgWrapper& rWrapper = FontCfgWrapper::get();
1003cdf0e10cSrcweir     if( ! rWrapper.isValid() )
1004cdf0e10cSrcweir         return aName;
1005cdf0e10cSrcweir 
1006cdf0e10cSrcweir     // build pattern argument for fontconfig query
1007cdf0e10cSrcweir     FcPattern* pPattern = rWrapper.FcPatternCreate();
1008cdf0e10cSrcweir 
1009cdf0e10cSrcweir     // Prefer scalable fonts
1010cdf0e10cSrcweir     rWrapper.FcPatternAddBool( pPattern, FC_SCALABLE, FcTrue );
1011cdf0e10cSrcweir 
1012cdf0e10cSrcweir     const rtl::OString aTargetName = rtl::OUStringToOString( rFontName, RTL_TEXTENCODING_UTF8 );
1013cdf0e10cSrcweir     const FcChar8* pTargetNameUtf8 = (FcChar8*)aTargetName.getStr();
1014cdf0e10cSrcweir     rWrapper.FcPatternAddString( pPattern, FC_FAMILY, pTargetNameUtf8 );
1015cdf0e10cSrcweir 
1016cdf0e10cSrcweir     const FcChar8* pLangAttribUtf8 = (FcChar8*)rLangAttrib.getStr();
1017cdf0e10cSrcweir     if( rLangAttrib.getLength() )
1018cdf0e10cSrcweir         rWrapper.FcPatternAddString( pPattern, FC_LANG, pLangAttribUtf8 );
1019cdf0e10cSrcweir 
1020cdf0e10cSrcweir     // Add required Unicode characters, if any
1021cdf0e10cSrcweir     if ( rMissingCodes.getLength() )
1022cdf0e10cSrcweir     {
1023cdf0e10cSrcweir        FcCharSet *unicodes = rWrapper.FcCharSetCreate();
1024cdf0e10cSrcweir        for( sal_Int32 nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); )
1025cdf0e10cSrcweir        {
1026cdf0e10cSrcweir            // also handle unicode surrogates
1027cdf0e10cSrcweir            const sal_uInt32 nCode = rMissingCodes.iterateCodePoints( &nStrIndex );
1028cdf0e10cSrcweir            rWrapper.FcCharSetAddChar( unicodes, nCode );
1029cdf0e10cSrcweir        }
1030cdf0e10cSrcweir        rWrapper.FcPatternAddCharSet( pPattern, FC_CHARSET, unicodes);
1031cdf0e10cSrcweir        rWrapper.FcCharSetDestroy( unicodes );
1032cdf0e10cSrcweir     }
1033cdf0e10cSrcweir 
1034cdf0e10cSrcweir     addtopattern(rWrapper, pPattern, rItalic, rWeight, rWidth, rPitch);
1035cdf0e10cSrcweir 
1036cdf0e10cSrcweir     // query fontconfig for a substitute
1037cdf0e10cSrcweir     rWrapper.FcConfigSubstitute( rWrapper.FcConfigGetCurrent(), pPattern, FcMatchPattern );
1038cdf0e10cSrcweir     rWrapper.FcDefaultSubstitute( pPattern );
1039cdf0e10cSrcweir 
1040cdf0e10cSrcweir     // process the result of the fontconfig query
1041cdf0e10cSrcweir     FcResult eResult = FcResultNoMatch;
1042cdf0e10cSrcweir     FcFontSet* pFontSet = rWrapper.getFontSet();
1043cdf0e10cSrcweir     FcPattern* pResult = rWrapper.FcFontSetMatch( rWrapper.FcConfigGetCurrent(), &pFontSet, 1, pPattern, &eResult );
1044cdf0e10cSrcweir     rWrapper.FcPatternDestroy( pPattern );
1045cdf0e10cSrcweir 
1046cdf0e10cSrcweir     FcFontSet*  pSet = NULL;
1047cdf0e10cSrcweir     if( pResult )
1048cdf0e10cSrcweir     {
1049cdf0e10cSrcweir         pSet = rWrapper.FcFontSetCreate();
1050cdf0e10cSrcweir         // info: destroying the pSet destroys pResult implicitly
1051cdf0e10cSrcweir         // since pResult was "added" to pSet
1052cdf0e10cSrcweir         rWrapper.FcFontSetAdd( pSet, pResult );
1053cdf0e10cSrcweir     }
1054cdf0e10cSrcweir 
1055cdf0e10cSrcweir     if( pSet )
1056cdf0e10cSrcweir     {
1057cdf0e10cSrcweir         if( pSet->nfont > 0 )
1058cdf0e10cSrcweir         {
1059cdf0e10cSrcweir             //extract the closest match
1060cdf0e10cSrcweir             FcChar8* family = NULL;
1061cdf0e10cSrcweir             FcResult eFileRes = rWrapper.FcPatternGetString( pSet->fonts[0], FC_FAMILY, 0, &family );
1062cdf0e10cSrcweir 
1063cdf0e10cSrcweir 			// get the family name
1064cdf0e10cSrcweir             if( eFileRes == FcResultMatch )
1065cdf0e10cSrcweir             {
1066cdf0e10cSrcweir                 OString sFamily((sal_Char*)family);
1067cdf0e10cSrcweir                 std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash >::const_iterator aI = rWrapper.m_aFontNameToLocalized.find(sFamily);
1068cdf0e10cSrcweir                 if (aI != rWrapper.m_aFontNameToLocalized.end())
1069cdf0e10cSrcweir                     sFamily = aI->second;
1070cdf0e10cSrcweir                 aName = rtl::OStringToOUString( sFamily, RTL_TEXTENCODING_UTF8 );
1071cdf0e10cSrcweir 
1072cdf0e10cSrcweir 
1073cdf0e10cSrcweir                 int val = 0;
1074cdf0e10cSrcweir                 if ( FcResultMatch == rWrapper.FcPatternGetInteger( pSet->fonts[0], FC_WEIGHT, 0, &val))
1075cdf0e10cSrcweir                     rWeight = convertWeight(val);
1076cdf0e10cSrcweir                 if ( FcResultMatch == rWrapper.FcPatternGetInteger( pSet->fonts[0], FC_SLANT, 0, &val))
1077cdf0e10cSrcweir                     rItalic = convertSlant(val);
1078cdf0e10cSrcweir                 if ( FcResultMatch == rWrapper.FcPatternGetInteger( pSet->fonts[0], FC_SPACING, 0, &val))
1079cdf0e10cSrcweir                     rPitch = convertSpacing(val);
1080cdf0e10cSrcweir                 if ( FcResultMatch == rWrapper.FcPatternGetInteger( pSet->fonts[0], FC_WIDTH, 0, &val))
1081cdf0e10cSrcweir                     rWidth = convertWidth(val);
1082cdf0e10cSrcweir             }
1083cdf0e10cSrcweir 
1084cdf0e10cSrcweir 			// update rMissingCodes by removing resolved unicodes
1085cdf0e10cSrcweir 	    	if( rMissingCodes.getLength() > 0 )
1086cdf0e10cSrcweir             {
1087cdf0e10cSrcweir                 sal_uInt32* pRemainingCodes = (sal_uInt32*)alloca( rMissingCodes.getLength() * sizeof(sal_uInt32) );
1088cdf0e10cSrcweir                 int nRemainingLen = 0;
1089cdf0e10cSrcweir 		    	FcCharSet* unicodes;
1090cdf0e10cSrcweir 		    	if( !rWrapper.FcPatternGetCharSet( pSet->fonts[0], FC_CHARSET, 0, &unicodes ) )
1091cdf0e10cSrcweir 		    	{
1092cdf0e10cSrcweir        				for( sal_Int32 nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); )
1093cdf0e10cSrcweir 					{
1094cdf0e10cSrcweir 						// also handle unicode surrogates
1095cdf0e10cSrcweir 						const sal_uInt32 nCode = rMissingCodes.iterateCodePoints( &nStrIndex );
1096cdf0e10cSrcweir 		            	if( rWrapper.FcCharSetHasChar( unicodes, nCode ) != FcTrue )
1097cdf0e10cSrcweir 							pRemainingCodes[ nRemainingLen++ ] = nCode;
1098cdf0e10cSrcweir                     }
1099cdf0e10cSrcweir 		    	}
1100cdf0e10cSrcweir 		    	rMissingCodes = OUString( pRemainingCodes, nRemainingLen );
1101cdf0e10cSrcweir             }
1102cdf0e10cSrcweir         }
1103cdf0e10cSrcweir 
1104cdf0e10cSrcweir     	rWrapper.FcFontSetDestroy( pSet );
1105cdf0e10cSrcweir     }
1106cdf0e10cSrcweir 
1107cdf0e10cSrcweir     return aName;
1108cdf0e10cSrcweir }
1109cdf0e10cSrcweir 
getFontOptions(const FastPrintFontInfo & rInfo,int nSize,void (* subcallback)(void *),ImplFontOptions & rOptions) const1110cdf0e10cSrcweir bool PrintFontManager::getFontOptions(
1111cdf0e10cSrcweir     const FastPrintFontInfo& rInfo, int nSize, void (*subcallback)(void*),
1112cdf0e10cSrcweir     ImplFontOptions& rOptions) const
1113cdf0e10cSrcweir {
1114cdf0e10cSrcweir #ifndef ENABLE_FONTCONFIG
1115cdf0e10cSrcweir     (void)rInfo;(void)nSize;(void)subcallback;(void)rOptions;
1116cdf0e10cSrcweir     return false;
1117cdf0e10cSrcweir #else // ENABLE_FONTCONFIG
1118cdf0e10cSrcweir     FontCfgWrapper& rWrapper = FontCfgWrapper::get();
1119cdf0e10cSrcweir     if( ! rWrapper.isValid() )
1120cdf0e10cSrcweir         return false;
1121cdf0e10cSrcweir 
1122cdf0e10cSrcweir     FcConfig* pConfig = rWrapper.FcConfigGetCurrent();
1123cdf0e10cSrcweir     FcPattern* pPattern = rWrapper.FcPatternCreate();
1124cdf0e10cSrcweir 
1125cdf0e10cSrcweir     OString sFamily = OUStringToOString( rInfo.m_aFamilyName, RTL_TEXTENCODING_UTF8 );
1126cdf0e10cSrcweir 
1127cdf0e10cSrcweir     std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash >::const_iterator aI = rWrapper.m_aLocalizedToCanonical.find(sFamily);
1128cdf0e10cSrcweir     if (aI != rWrapper.m_aLocalizedToCanonical.end())
1129cdf0e10cSrcweir         sFamily = aI->second;
1130cdf0e10cSrcweir     if( sFamily.getLength() )
1131cdf0e10cSrcweir         rWrapper.FcPatternAddString( pPattern, FC_FAMILY, (FcChar8*)sFamily.getStr() );
1132cdf0e10cSrcweir 
1133cdf0e10cSrcweir     addtopattern(rWrapper, pPattern, rInfo.m_eItalic, rInfo.m_eWeight, rInfo.m_eWidth, rInfo.m_ePitch);
1134cdf0e10cSrcweir     rWrapper.FcPatternAddDouble( pPattern, FC_PIXEL_SIZE, nSize);
1135cdf0e10cSrcweir 
1136cdf0e10cSrcweir     FcBool embitmap = true, antialias = true, autohint = true, hinting = true;
1137cdf0e10cSrcweir     int hintstyle = FC_HINT_FULL;
1138cdf0e10cSrcweir 
1139cdf0e10cSrcweir     rWrapper.FcConfigSubstitute( pConfig, pPattern, FcMatchPattern );
1140cdf0e10cSrcweir     if (subcallback) subcallback(pPattern);
1141cdf0e10cSrcweir     rWrapper.FcDefaultSubstitute( pPattern );
1142cdf0e10cSrcweir 
1143cdf0e10cSrcweir     FcResult eResult = FcResultNoMatch;
1144cdf0e10cSrcweir     FcFontSet* pFontSet = rWrapper.getFontSet();
1145cdf0e10cSrcweir     FcPattern* pResult = rWrapper.FcFontSetMatch( pConfig, &pFontSet, 1, pPattern, &eResult );
1146cdf0e10cSrcweir     if( pResult )
1147cdf0e10cSrcweir     {
1148cdf0e10cSrcweir         FcFontSet* pSet = rWrapper.FcFontSetCreate();
1149cdf0e10cSrcweir         rWrapper.FcFontSetAdd( pSet, pResult );
1150cdf0e10cSrcweir         if( pSet->nfont > 0 )
1151cdf0e10cSrcweir         {
1152cdf0e10cSrcweir             FcResult eEmbeddedBitmap = rWrapper.FcPatternGetBool(pSet->fonts[0],
1153cdf0e10cSrcweir                 FC_EMBEDDED_BITMAP, 0, &embitmap);
1154cdf0e10cSrcweir             FcResult eAntialias = rWrapper.FcPatternGetBool(pSet->fonts[0],
1155cdf0e10cSrcweir                 FC_ANTIALIAS, 0, &antialias);
1156cdf0e10cSrcweir             FcResult eAutoHint = rWrapper.FcPatternGetBool(pSet->fonts[0],
1157cdf0e10cSrcweir                 FC_AUTOHINT, 0, &autohint);
1158cdf0e10cSrcweir             FcResult eHinting = rWrapper.FcPatternGetBool(pSet->fonts[0],
1159cdf0e10cSrcweir                 FC_HINTING, 0, &hinting);
1160cdf0e10cSrcweir             /*FcResult eHintStyle =*/ rWrapper.FcPatternGetInteger( pSet->fonts[0],
1161cdf0e10cSrcweir                 FC_HINT_STYLE, 0, &hintstyle);
1162cdf0e10cSrcweir 
1163cdf0e10cSrcweir             if( eEmbeddedBitmap == FcResultMatch )
1164cdf0e10cSrcweir                 rOptions.meEmbeddedBitmap = embitmap ? EMBEDDEDBITMAP_TRUE : EMBEDDEDBITMAP_FALSE;
1165cdf0e10cSrcweir             if( eAntialias == FcResultMatch )
1166cdf0e10cSrcweir                 rOptions.meAntiAlias = antialias ? ANTIALIAS_TRUE : ANTIALIAS_FALSE;
1167cdf0e10cSrcweir             if( eAutoHint == FcResultMatch )
1168cdf0e10cSrcweir                 rOptions.meAutoHint = autohint ? AUTOHINT_TRUE : AUTOHINT_FALSE;
1169cdf0e10cSrcweir             if( eHinting == FcResultMatch )
1170cdf0e10cSrcweir                 rOptions.meHinting = hinting ? HINTING_TRUE : HINTING_FALSE;
1171cdf0e10cSrcweir             switch (hintstyle)
1172cdf0e10cSrcweir             {
1173cdf0e10cSrcweir                 case FC_HINT_NONE:   rOptions.meHintStyle = HINT_NONE; break;
1174cdf0e10cSrcweir                 case FC_HINT_SLIGHT: rOptions.meHintStyle = HINT_SLIGHT; break;
1175cdf0e10cSrcweir                 case FC_HINT_MEDIUM: rOptions.meHintStyle = HINT_MEDIUM; break;
1176cdf0e10cSrcweir                 default: // fall through
1177cdf0e10cSrcweir                 case FC_HINT_FULL:   rOptions.meHintStyle = HINT_FULL; break;
1178cdf0e10cSrcweir             }
1179cdf0e10cSrcweir         }
1180cdf0e10cSrcweir         // info: destroying the pSet destroys pResult implicitly
1181cdf0e10cSrcweir         // since pResult was "added" to pSet
1182cdf0e10cSrcweir         rWrapper.FcFontSetDestroy( pSet );
1183cdf0e10cSrcweir     }
1184cdf0e10cSrcweir 
1185cdf0e10cSrcweir     // cleanup
1186cdf0e10cSrcweir     rWrapper.FcPatternDestroy( pPattern );
1187cdf0e10cSrcweir 
1188cdf0e10cSrcweir     // TODO: return true only if non-default font options are set
1189cdf0e10cSrcweir     const bool bOK = (pResult != NULL);
1190cdf0e10cSrcweir     return bOK;
1191cdf0e10cSrcweir #endif
1192cdf0e10cSrcweir }
1193cdf0e10cSrcweir 
matchFont(FastPrintFontInfo & rInfo,const com::sun::star::lang::Locale & rLocale)1194cdf0e10cSrcweir bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const com::sun::star::lang::Locale& rLocale )
1195cdf0e10cSrcweir {
1196cdf0e10cSrcweir     FontCfgWrapper& rWrapper = FontCfgWrapper::get();
1197cdf0e10cSrcweir     if( ! rWrapper.isValid() )
1198cdf0e10cSrcweir         return false;
1199cdf0e10cSrcweir 
1200cdf0e10cSrcweir     FcConfig* pConfig = rWrapper.FcConfigGetCurrent();
1201cdf0e10cSrcweir     FcPattern* pPattern = rWrapper.FcPatternCreate();
1202cdf0e10cSrcweir 
1203cdf0e10cSrcweir     OString aLangAttrib;
1204cdf0e10cSrcweir     // populate pattern with font characteristics
1205cdf0e10cSrcweir     if( rLocale.Language.getLength() )
1206cdf0e10cSrcweir     {
1207cdf0e10cSrcweir         OUStringBuffer aLang(6);
1208cdf0e10cSrcweir         aLang.append( rLocale.Language );
1209cdf0e10cSrcweir         if( rLocale.Country.getLength() )
1210cdf0e10cSrcweir         {
1211cdf0e10cSrcweir             aLang.append( sal_Unicode('-') );
1212cdf0e10cSrcweir             aLang.append( rLocale.Country );
1213cdf0e10cSrcweir         }
1214cdf0e10cSrcweir         aLangAttrib = OUStringToOString( aLang.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
1215cdf0e10cSrcweir     }
1216cdf0e10cSrcweir     if( aLangAttrib.getLength() )
1217cdf0e10cSrcweir         rWrapper.FcPatternAddString( pPattern, FC_LANG, (FcChar8*)aLangAttrib.getStr() );
1218cdf0e10cSrcweir 
1219cdf0e10cSrcweir     OString aFamily = OUStringToOString( rInfo.m_aFamilyName, RTL_TEXTENCODING_UTF8 );
1220cdf0e10cSrcweir     if( aFamily.getLength() )
1221cdf0e10cSrcweir         rWrapper.FcPatternAddString( pPattern, FC_FAMILY, (FcChar8*)aFamily.getStr() );
1222cdf0e10cSrcweir 
1223cdf0e10cSrcweir     addtopattern(rWrapper, pPattern, rInfo.m_eItalic, rInfo.m_eWeight, rInfo.m_eWidth, rInfo.m_ePitch);
1224cdf0e10cSrcweir 
1225cdf0e10cSrcweir     rWrapper.FcConfigSubstitute( pConfig, pPattern, FcMatchPattern );
1226cdf0e10cSrcweir     rWrapper.FcDefaultSubstitute( pPattern );
1227cdf0e10cSrcweir     FcResult eResult = FcResultNoMatch;
1228cdf0e10cSrcweir     FcFontSet *pFontSet = rWrapper.getFontSet();
1229cdf0e10cSrcweir     FcPattern* pResult = rWrapper.FcFontSetMatch( pConfig, &pFontSet, 1, pPattern, &eResult );
1230cdf0e10cSrcweir     bool bSuccess = false;
1231cdf0e10cSrcweir     if( pResult )
1232cdf0e10cSrcweir     {
1233cdf0e10cSrcweir         FcFontSet* pSet = rWrapper.FcFontSetCreate();
1234cdf0e10cSrcweir         rWrapper.FcFontSetAdd( pSet, pResult );
1235cdf0e10cSrcweir         if( pSet->nfont > 0 )
1236cdf0e10cSrcweir         {
1237cdf0e10cSrcweir             //extract the closest match
1238cdf0e10cSrcweir             FcChar8* file = NULL;
1239cdf0e10cSrcweir             FcResult eFileRes = rWrapper.FcPatternGetString( pSet->fonts[0], FC_FILE, 0, &file );
1240cdf0e10cSrcweir             if( eFileRes == FcResultMatch )
1241cdf0e10cSrcweir             {
1242cdf0e10cSrcweir                 OString aDir, aBase, aOrgPath( (sal_Char*)file );
1243cdf0e10cSrcweir                 splitPath( aOrgPath, aDir, aBase );
1244cdf0e10cSrcweir                 int nDirID = getDirectoryAtom( aDir, true );
1245cdf0e10cSrcweir                 fontID aFont = findFontFileID( nDirID, aBase );
1246cdf0e10cSrcweir                 if( aFont > 0 )
1247cdf0e10cSrcweir                     bSuccess = getFontFastInfo( aFont, rInfo );
1248cdf0e10cSrcweir             }
1249cdf0e10cSrcweir         }
1250cdf0e10cSrcweir         // info: destroying the pSet destroys pResult implicitly
1251cdf0e10cSrcweir         // since pResult was "added" to pSet
1252cdf0e10cSrcweir         rWrapper.FcFontSetDestroy( pSet );
1253cdf0e10cSrcweir     }
1254cdf0e10cSrcweir 
1255cdf0e10cSrcweir     // cleanup
1256cdf0e10cSrcweir     rWrapper.FcPatternDestroy( pPattern );
1257cdf0e10cSrcweir 
1258cdf0e10cSrcweir     return bSuccess;
1259cdf0e10cSrcweir }
1260cdf0e10cSrcweir 
1261cdf0e10cSrcweir #else // ENABLE_FONTCONFIG not defined
1262cdf0e10cSrcweir 
initFontconfig()1263cdf0e10cSrcweir bool PrintFontManager::initFontconfig()
1264cdf0e10cSrcweir {
1265cdf0e10cSrcweir     return false;
1266cdf0e10cSrcweir }
1267cdf0e10cSrcweir 
countFontconfigFonts(std::hash_map<rtl::OString,int,rtl::OStringHash> &)1268cdf0e10cSrcweir int PrintFontManager::countFontconfigFonts( std::hash_map<rtl::OString, int, rtl::OStringHash>& )
1269cdf0e10cSrcweir {
1270cdf0e10cSrcweir     return 0;
1271cdf0e10cSrcweir }
1272cdf0e10cSrcweir 
deinitFontconfig()1273cdf0e10cSrcweir void PrintFontManager::deinitFontconfig()
1274cdf0e10cSrcweir {}
1275cdf0e10cSrcweir 
addFontconfigDir(const rtl::OString &)1276cdf0e10cSrcweir bool PrintFontManager::addFontconfigDir( const rtl::OString& )
1277cdf0e10cSrcweir {
1278cdf0e10cSrcweir     return false;
1279cdf0e10cSrcweir }
1280cdf0e10cSrcweir 
matchFont(FastPrintFontInfo &,const com::sun::star::lang::Locale &)1281cdf0e10cSrcweir bool PrintFontManager::matchFont( FastPrintFontInfo&, const com::sun::star::lang::Locale& )
1282cdf0e10cSrcweir {
1283cdf0e10cSrcweir     return false;
1284cdf0e10cSrcweir }
1285cdf0e10cSrcweir 
FreeTypeCharIndex(void *,sal_uInt32)1286cdf0e10cSrcweir int PrintFontManager::FreeTypeCharIndex( void*, sal_uInt32 )
1287cdf0e10cSrcweir {
1288cdf0e10cSrcweir     return 0;
1289cdf0e10cSrcweir }
1290cdf0e10cSrcweir 
Substitute(const rtl::OUString &,rtl::OUString &,const rtl::OString &,italic::type,weight::type,width::type,pitch::type) const1291cdf0e10cSrcweir rtl::OUString PrintFontManager::Substitute( const rtl::OUString&,
1292cdf0e10cSrcweir     rtl::OUString&, const rtl::OString&, italic::type, weight::type, width::type, pitch::type) const
1293cdf0e10cSrcweir {
1294cdf0e10cSrcweir     rtl::OUString aName;
1295cdf0e10cSrcweir     return aName;
1296cdf0e10cSrcweir }
1297cdf0e10cSrcweir 
1298cdf0e10cSrcweir #endif // ENABLE_FONTCONFIG
1299cdf0e10cSrcweir 
1300