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