xref: /aoo42x/main/unotools/source/config/fontcfg.cxx (revision cdf0e10c)
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_unotools.hxx"
30*cdf0e10cSrcweir #include <unotools/fontcfg.hxx>
31*cdf0e10cSrcweir #include <unotools/fontdefs.hxx>
32*cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
33*cdf0e10cSrcweir #include <com/sun/star/uno/Any.hxx>
34*cdf0e10cSrcweir #include <com/sun/star/uno/Sequence.hxx>
35*cdf0e10cSrcweir #include <com/sun/star/beans/PropertyValue.hpp>
36*cdf0e10cSrcweir #include <unotools/configpathes.hxx>
37*cdf0e10cSrcweir #include <unotools/syslocale.hxx>
38*cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
39*cdf0e10cSrcweir #include <tools/debug.hxx>
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
42*cdf0e10cSrcweir #include <stdio.h>
43*cdf0e10cSrcweir #endif
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir #include <string.h>
46*cdf0e10cSrcweir #include <list>
47*cdf0e10cSrcweir #include <algorithm>
48*cdf0e10cSrcweir 
49*cdf0e10cSrcweir #define DEFAULTFONT_CONFIGNODE "VCL/DefaultFonts"
50*cdf0e10cSrcweir #define SUBSTFONT_CONFIGNODE "VCL/FontSubstitutions"
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir using namespace rtl;
53*cdf0e10cSrcweir using namespace utl;
54*cdf0e10cSrcweir using namespace com::sun::star::uno;
55*cdf0e10cSrcweir using namespace com::sun::star::lang;
56*cdf0e10cSrcweir using namespace com::sun::star::beans;
57*cdf0e10cSrcweir using namespace com::sun::star::container;
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir static DefaultFontConfiguration* mpDefaultFontConfiguration = 0;
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir static FontSubstConfiguration* mpFontSubstConfiguration = 0;
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir /*
64*cdf0e10cSrcweir  * DefaultFontConfiguration
65*cdf0e10cSrcweir  */
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir static const char* getKeyType( int nKeyType )
68*cdf0e10cSrcweir {
69*cdf0e10cSrcweir     switch( nKeyType )
70*cdf0e10cSrcweir     {
71*cdf0e10cSrcweir     case DEFAULTFONT_CJK_DISPLAY: return "CJK_DISPLAY";
72*cdf0e10cSrcweir     case DEFAULTFONT_CJK_HEADING: return "CJK_HEADING";
73*cdf0e10cSrcweir     case DEFAULTFONT_CJK_PRESENTATION: return "CJK_PRESENTATION";
74*cdf0e10cSrcweir     case DEFAULTFONT_CJK_SPREADSHEET: return "CJK_SPREADSHEET";
75*cdf0e10cSrcweir     case DEFAULTFONT_CJK_TEXT: return "CJK_TEXT";
76*cdf0e10cSrcweir     case DEFAULTFONT_CTL_DISPLAY: return "CTL_DISPLAY";
77*cdf0e10cSrcweir     case DEFAULTFONT_CTL_HEADING: return "CTL_HEADING";
78*cdf0e10cSrcweir     case DEFAULTFONT_CTL_PRESENTATION: return "CTL_PRESENTATION";
79*cdf0e10cSrcweir     case DEFAULTFONT_CTL_SPREADSHEET: return "CTL_SPREADSHEET";
80*cdf0e10cSrcweir     case DEFAULTFONT_CTL_TEXT: return "CTL_TEXT";
81*cdf0e10cSrcweir     case DEFAULTFONT_FIXED: return "FIXED";
82*cdf0e10cSrcweir     case DEFAULTFONT_LATIN_DISPLAY: return "LATIN_DISPLAY";
83*cdf0e10cSrcweir     case DEFAULTFONT_LATIN_FIXED: return "LATIN_FIXED";
84*cdf0e10cSrcweir     case DEFAULTFONT_LATIN_HEADING: return "LATIN_HEADING";
85*cdf0e10cSrcweir     case DEFAULTFONT_LATIN_PRESENTATION: return "LATIN_PRESENTATION";
86*cdf0e10cSrcweir     case DEFAULTFONT_LATIN_SPREADSHEET: return "LATIN_SPREADSHEET";
87*cdf0e10cSrcweir     case DEFAULTFONT_LATIN_TEXT: return "LATIN_TEXT";
88*cdf0e10cSrcweir     case DEFAULTFONT_SANS: return "SANS";
89*cdf0e10cSrcweir     case DEFAULTFONT_SANS_UNICODE: return "SANS_UNICODE";
90*cdf0e10cSrcweir     case DEFAULTFONT_SERIF: return "SERIF";
91*cdf0e10cSrcweir     case DEFAULTFONT_SYMBOL: return "SYMBOL";
92*cdf0e10cSrcweir     case DEFAULTFONT_UI_FIXED: return "UI_FIXED";
93*cdf0e10cSrcweir     case DEFAULTFONT_UI_SANS: return "UI_SANS";
94*cdf0e10cSrcweir     default:
95*cdf0e10cSrcweir         DBG_ERROR( "unmatched type" );
96*cdf0e10cSrcweir         return "";
97*cdf0e10cSrcweir     }
98*cdf0e10cSrcweir }
99*cdf0e10cSrcweir 
100*cdf0e10cSrcweir DefaultFontConfiguration* DefaultFontConfiguration::get()
101*cdf0e10cSrcweir {
102*cdf0e10cSrcweir     if( !mpDefaultFontConfiguration )
103*cdf0e10cSrcweir         mpDefaultFontConfiguration = new DefaultFontConfiguration();
104*cdf0e10cSrcweir     return mpDefaultFontConfiguration;
105*cdf0e10cSrcweir }
106*cdf0e10cSrcweir 
107*cdf0e10cSrcweir DefaultFontConfiguration::DefaultFontConfiguration()
108*cdf0e10cSrcweir {
109*cdf0e10cSrcweir     try
110*cdf0e10cSrcweir     {
111*cdf0e10cSrcweir         // get service provider
112*cdf0e10cSrcweir         Reference< XMultiServiceFactory > xSMgr( comphelper::getProcessServiceFactory() );
113*cdf0e10cSrcweir         // create configuration hierachical access name
114*cdf0e10cSrcweir         if( xSMgr.is() )
115*cdf0e10cSrcweir         {
116*cdf0e10cSrcweir             try
117*cdf0e10cSrcweir             {
118*cdf0e10cSrcweir                 m_xConfigProvider =
119*cdf0e10cSrcweir                     Reference< XMultiServiceFactory >(
120*cdf0e10cSrcweir                         xSMgr->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
121*cdf0e10cSrcweir                                         "com.sun.star.configuration.ConfigurationProvider" ))),
122*cdf0e10cSrcweir                         UNO_QUERY );
123*cdf0e10cSrcweir                 if( m_xConfigProvider.is() )
124*cdf0e10cSrcweir                 {
125*cdf0e10cSrcweir                     Sequence< Any > aArgs(1);
126*cdf0e10cSrcweir                     PropertyValue aVal;
127*cdf0e10cSrcweir                     aVal.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
128*cdf0e10cSrcweir                     aVal.Value <<= OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.VCL/DefaultFonts" ) );
129*cdf0e10cSrcweir                     aArgs.getArray()[0] <<= aVal;
130*cdf0e10cSrcweir                     m_xConfigAccess =
131*cdf0e10cSrcweir                         Reference< XNameAccess >(
132*cdf0e10cSrcweir                             m_xConfigProvider->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
133*cdf0e10cSrcweir                                                 "com.sun.star.configuration.ConfigurationAccess" )),
134*cdf0e10cSrcweir                                                                             aArgs ),
135*cdf0e10cSrcweir                             UNO_QUERY );
136*cdf0e10cSrcweir                     if( m_xConfigAccess.is() )
137*cdf0e10cSrcweir                     {
138*cdf0e10cSrcweir                         Sequence< OUString > aLocales = m_xConfigAccess->getElementNames();
139*cdf0e10cSrcweir                         // fill config hash with empty interfaces
140*cdf0e10cSrcweir                         int nLocales = aLocales.getLength();
141*cdf0e10cSrcweir                         const OUString* pLocaleStrings = aLocales.getConstArray();
142*cdf0e10cSrcweir                         Locale aLoc;
143*cdf0e10cSrcweir                         for( int i = 0; i < nLocales; i++ )
144*cdf0e10cSrcweir                         {
145*cdf0e10cSrcweir                             sal_Int32 nIndex = 0;
146*cdf0e10cSrcweir                             aLoc.Language = pLocaleStrings[i].getToken( 0, sal_Unicode('-'), nIndex ).toAsciiLowerCase();
147*cdf0e10cSrcweir                             if( nIndex != -1 )
148*cdf0e10cSrcweir                                 aLoc.Country = pLocaleStrings[i].getToken( 0, sal_Unicode('-'), nIndex ).toAsciiUpperCase();
149*cdf0e10cSrcweir                             else
150*cdf0e10cSrcweir                                 aLoc.Country = OUString();
151*cdf0e10cSrcweir                             if( nIndex != -1 )
152*cdf0e10cSrcweir                                 aLoc.Variant = pLocaleStrings[i].getToken( 0, sal_Unicode('-'), nIndex ).toAsciiUpperCase();
153*cdf0e10cSrcweir                             else
154*cdf0e10cSrcweir                                 aLoc.Variant = OUString();
155*cdf0e10cSrcweir                             m_aConfig[ aLoc ] = LocaleAccess();
156*cdf0e10cSrcweir                             m_aConfig[ aLoc ].aConfigLocaleString = pLocaleStrings[i];
157*cdf0e10cSrcweir                         }
158*cdf0e10cSrcweir                     }
159*cdf0e10cSrcweir                 }
160*cdf0e10cSrcweir             }
161*cdf0e10cSrcweir             catch( Exception& )
162*cdf0e10cSrcweir             {
163*cdf0e10cSrcweir                 // configuration is awry
164*cdf0e10cSrcweir                 m_xConfigProvider.clear();
165*cdf0e10cSrcweir                 m_xConfigAccess.clear();
166*cdf0e10cSrcweir             }
167*cdf0e10cSrcweir         }
168*cdf0e10cSrcweir     }
169*cdf0e10cSrcweir     catch( WrappedTargetException& )
170*cdf0e10cSrcweir     {
171*cdf0e10cSrcweir     }
172*cdf0e10cSrcweir     #if OSL_DEBUG_LEVEL > 1
173*cdf0e10cSrcweir     fprintf( stderr, "config provider: %s, config access: %s\n",
174*cdf0e10cSrcweir              m_xConfigProvider.is() ? "true" : "false",
175*cdf0e10cSrcweir              m_xConfigAccess.is() ? "true" : "false"
176*cdf0e10cSrcweir              );
177*cdf0e10cSrcweir     #endif
178*cdf0e10cSrcweir }
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir DefaultFontConfiguration::~DefaultFontConfiguration()
181*cdf0e10cSrcweir {
182*cdf0e10cSrcweir     // release all nodes
183*cdf0e10cSrcweir     m_aConfig.clear();
184*cdf0e10cSrcweir     // release top node
185*cdf0e10cSrcweir     m_xConfigAccess.clear();
186*cdf0e10cSrcweir     // release config provider
187*cdf0e10cSrcweir     m_xConfigProvider.clear();
188*cdf0e10cSrcweir }
189*cdf0e10cSrcweir 
190*cdf0e10cSrcweir OUString DefaultFontConfiguration::tryLocale( const Locale& rLocale, const OUString& rType ) const
191*cdf0e10cSrcweir {
192*cdf0e10cSrcweir     OUString aRet;
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir     std::hash_map< Locale, LocaleAccess, LocaleHash >::const_iterator it =
195*cdf0e10cSrcweir         m_aConfig.find( rLocale );
196*cdf0e10cSrcweir     if( it != m_aConfig.end() )
197*cdf0e10cSrcweir     {
198*cdf0e10cSrcweir         if( !it->second.xAccess.is() )
199*cdf0e10cSrcweir         {
200*cdf0e10cSrcweir             try
201*cdf0e10cSrcweir             {
202*cdf0e10cSrcweir                 Reference< XNameAccess > xNode;
203*cdf0e10cSrcweir                 if ( m_xConfigAccess->hasByName( it->second.aConfigLocaleString ) )
204*cdf0e10cSrcweir                 {
205*cdf0e10cSrcweir                     Any aAny = m_xConfigAccess->getByName( it->second.aConfigLocaleString );
206*cdf0e10cSrcweir                 	if( aAny >>= xNode )
207*cdf0e10cSrcweir                 	    it->second.xAccess = xNode;
208*cdf0e10cSrcweir 				}
209*cdf0e10cSrcweir             }
210*cdf0e10cSrcweir             catch( NoSuchElementException )
211*cdf0e10cSrcweir             {
212*cdf0e10cSrcweir             }
213*cdf0e10cSrcweir             catch( WrappedTargetException )
214*cdf0e10cSrcweir             {
215*cdf0e10cSrcweir             }
216*cdf0e10cSrcweir         }
217*cdf0e10cSrcweir         if( it->second.xAccess.is() )
218*cdf0e10cSrcweir         {
219*cdf0e10cSrcweir             try
220*cdf0e10cSrcweir             {
221*cdf0e10cSrcweir                 if ( it->second.xAccess->hasByName( rType ) )
222*cdf0e10cSrcweir                 {
223*cdf0e10cSrcweir                     Any aAny = it->second.xAccess->getByName( rType );
224*cdf0e10cSrcweir                     aAny >>= aRet;
225*cdf0e10cSrcweir                 }
226*cdf0e10cSrcweir             }
227*cdf0e10cSrcweir             catch( NoSuchElementException& )
228*cdf0e10cSrcweir             {
229*cdf0e10cSrcweir             }
230*cdf0e10cSrcweir             catch( WrappedTargetException& )
231*cdf0e10cSrcweir             {
232*cdf0e10cSrcweir             }
233*cdf0e10cSrcweir         }
234*cdf0e10cSrcweir     }
235*cdf0e10cSrcweir 
236*cdf0e10cSrcweir     return aRet;
237*cdf0e10cSrcweir }
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir OUString DefaultFontConfiguration::getDefaultFont( const Locale& rLocale, int nType ) const
240*cdf0e10cSrcweir {
241*cdf0e10cSrcweir     Locale aLocale;
242*cdf0e10cSrcweir     aLocale.Language = rLocale.Language.toAsciiLowerCase();
243*cdf0e10cSrcweir     aLocale.Country = rLocale.Country.toAsciiUpperCase();
244*cdf0e10cSrcweir     aLocale.Variant = rLocale.Variant.toAsciiUpperCase();
245*cdf0e10cSrcweir 
246*cdf0e10cSrcweir     OUString aType = OUString::createFromAscii( getKeyType( nType ) );
247*cdf0e10cSrcweir     OUString aRet = tryLocale( aLocale, aType );
248*cdf0e10cSrcweir     if( ! aRet.getLength() && aLocale.Variant.getLength() )
249*cdf0e10cSrcweir     {
250*cdf0e10cSrcweir         aLocale.Variant = OUString();
251*cdf0e10cSrcweir         aRet = tryLocale( aLocale, aType );
252*cdf0e10cSrcweir     }
253*cdf0e10cSrcweir     if( ! aRet.getLength() && aLocale.Country.getLength() )
254*cdf0e10cSrcweir     {
255*cdf0e10cSrcweir         aLocale.Country = OUString();
256*cdf0e10cSrcweir         aRet = tryLocale( aLocale, aType );
257*cdf0e10cSrcweir     }
258*cdf0e10cSrcweir     if( ! aRet.getLength() )
259*cdf0e10cSrcweir     {
260*cdf0e10cSrcweir         aLocale.Language = OUString( RTL_CONSTASCII_USTRINGPARAM( "en" ) );
261*cdf0e10cSrcweir         aRet = tryLocale( aLocale, aType );
262*cdf0e10cSrcweir     }
263*cdf0e10cSrcweir     return aRet;
264*cdf0e10cSrcweir }
265*cdf0e10cSrcweir 
266*cdf0e10cSrcweir OUString DefaultFontConfiguration::getUserInterfaceFont( const Locale& rLocale ) const
267*cdf0e10cSrcweir {
268*cdf0e10cSrcweir     Locale aLocale = rLocale;
269*cdf0e10cSrcweir     if( ! aLocale.Language.getLength() )
270*cdf0e10cSrcweir         aLocale = SvtSysLocale().GetUILocale();
271*cdf0e10cSrcweir 
272*cdf0e10cSrcweir     OUString aUIFont = getDefaultFont( aLocale, DEFAULTFONT_UI_SANS );
273*cdf0e10cSrcweir 
274*cdf0e10cSrcweir     if( aUIFont.getLength() )
275*cdf0e10cSrcweir         return aUIFont;
276*cdf0e10cSrcweir 
277*cdf0e10cSrcweir     // fallback mechanism (either no configuration or no entry in configuration
278*cdf0e10cSrcweir 
279*cdf0e10cSrcweir     #define FALLBACKFONT_UI_SANS "Andale Sans UI;Albany;Albany AMT;Tahoma;Arial Unicode MS;Arial;Nimbus Sans L;Bitstream Vera Sans;gnu-unifont;Interface User;Geneva;WarpSans;Dialog;Swiss;Lucida;Helvetica;Charcoal;Chicago;MS Sans Serif;Helv;Times;Times New Roman;Interface System"
280*cdf0e10cSrcweir     #define FALLBACKFONT_UI_SANS_LATIN2 "Andale Sans UI;Albany;Albany AMT;Tahoma;Arial Unicode MS;Arial;Nimbus Sans L;Luxi Sans;Bitstream Vera Sans;Interface User;Geneva;WarpSans;Dialog;Swiss;Lucida;Helvetica;Charcoal;Chicago;MS Sans Serif;Helv;Times;Times New Roman;Interface System"
281*cdf0e10cSrcweir     #define FALLBACKFONT_UI_SANS_ARABIC "Tahoma;Traditional Arabic;Simplified Arabic;Lucidasans;Lucida Sans;Supplement;Andale Sans UI;clearlyU;Interface User;Arial Unicode MS;Lucida Sans Unicode;WarpSans;Geneva;MS Sans Serif;Helv;Dialog;Albany;Lucida;Helvetica;Charcoal;Chicago;Arial;Helmet;Interface System;Sans Serif"
282*cdf0e10cSrcweir     #define FALLBACKFONT_UI_SANS_THAI "OONaksit;Tahoma;Lucidasans;Arial Unicode MS"
283*cdf0e10cSrcweir     #define FALLBACKFONT_UI_SANS_KOREAN "SunGulim;BaekmukGulim;Gulim;Roundgothic;Arial Unicode MS;Lucida Sans Unicode;gnu-unifont;Andale Sans UI"
284*cdf0e10cSrcweir     #define FALLBACKFONT_UI_SANS_JAPANESE1 "HG-GothicB-Sun;Andale Sans UI;HG MhinchoLightJ"
285*cdf0e10cSrcweir     #define FALLBACKFONT_UI_SANS_JAPANESE2 "Kochi Gothic;Gothic"
286*cdf0e10cSrcweir     #define FALLBACKFONT_UI_SANS_CHINSIM "Andale Sans UI;Arial Unicode MS;ZYSong18030;AR PL SungtiL GB;AR PL KaitiM GB;SimSun;Lucida Sans Unicode;Fangsong;Hei;Song;Kai;Ming;gnu-unifont;Interface User;"
287*cdf0e10cSrcweir     #define FALLBACKFONT_UI_SANS_CHINTRD "Andale Sans UI;Arial Unicode MS;AR PL Mingti2L Big5;AR PL KaitiM Big5;Kai;PMingLiU;MingLiU;Ming;Lucida Sans Unicode;gnu-unifont;Interface User;"
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir     // we need localized names for japanese fonts
290*cdf0e10cSrcweir     static sal_Unicode const aMSGothic[] = { 0xFF2D, 0xFF33, ' ', 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0, 0 };
291*cdf0e10cSrcweir     static sal_Unicode const aMSPGothic[] = { 0xFF2D, 0xFF33, ' ', 0xFF30, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0, 0 };
292*cdf0e10cSrcweir     static sal_Unicode const aTLPGothic[] = { 0x0054, 0x004C, 0x0050, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0, 0 };
293*cdf0e10cSrcweir     static sal_Unicode const aLXGothic[] = { 0x004C, 0x0058, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0, 0 };
294*cdf0e10cSrcweir     static sal_Unicode const aKochiGothic[] = { 0x6771, 0x98A8, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0, 0 };
295*cdf0e10cSrcweir 
296*cdf0e10cSrcweir     String aFallBackJapaneseLocalized( RTL_CONSTASCII_USTRINGPARAM( "MS UI Gothic;" ) );
297*cdf0e10cSrcweir     aFallBackJapaneseLocalized += String( RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_JAPANESE1 ) );
298*cdf0e10cSrcweir     aFallBackJapaneseLocalized += String( aMSPGothic );
299*cdf0e10cSrcweir     aFallBackJapaneseLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
300*cdf0e10cSrcweir     aFallBackJapaneseLocalized += String( aMSGothic );
301*cdf0e10cSrcweir     aFallBackJapaneseLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
302*cdf0e10cSrcweir     aFallBackJapaneseLocalized += String( aTLPGothic );
303*cdf0e10cSrcweir     aFallBackJapaneseLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
304*cdf0e10cSrcweir     aFallBackJapaneseLocalized += String( aLXGothic );
305*cdf0e10cSrcweir     aFallBackJapaneseLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
306*cdf0e10cSrcweir     aFallBackJapaneseLocalized += String( aKochiGothic );
307*cdf0e10cSrcweir     aFallBackJapaneseLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
308*cdf0e10cSrcweir     aFallBackJapaneseLocalized += String(RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_JAPANESE2 ) );
309*cdf0e10cSrcweir     static const OUString aFallBackJapanese( aFallBackJapaneseLocalized );
310*cdf0e10cSrcweir     static const OUString aFallback (RTL_CONSTASCII_USTRINGPARAM(FALLBACKFONT_UI_SANS));
311*cdf0e10cSrcweir     static const OUString aFallbackLatin2 (RTL_CONSTASCII_USTRINGPARAM(FALLBACKFONT_UI_SANS_LATIN2));
312*cdf0e10cSrcweir     static const OUString aFallBackArabic (RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_ARABIC ) );
313*cdf0e10cSrcweir     static const OUString aFallBackThai (RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_THAI ) );
314*cdf0e10cSrcweir     static const OUString aFallBackChineseSIM (RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_CHINSIM ) );
315*cdf0e10cSrcweir     static const OUString aFallBackChineseTRD (RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_CHINTRD ) );
316*cdf0e10cSrcweir 
317*cdf0e10cSrcweir     // we need localized names for korean fonts
318*cdf0e10cSrcweir     static sal_Unicode const aSunGulim[] = { 0xC36C, 0xAD74, 0xB9BC, 0 };
319*cdf0e10cSrcweir     static sal_Unicode const aBaekmukGulim[] = { 0xBC31, 0xBC35, 0xAD74, 0xB9BC, 0 };
320*cdf0e10cSrcweir     String aFallBackKoreanLocalized( aSunGulim );
321*cdf0e10cSrcweir     aFallBackKoreanLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
322*cdf0e10cSrcweir     aFallBackKoreanLocalized += String( aBaekmukGulim );
323*cdf0e10cSrcweir     aFallBackKoreanLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
324*cdf0e10cSrcweir     aFallBackKoreanLocalized += String(RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_KOREAN ) );
325*cdf0e10cSrcweir     static const OUString aFallBackKorean( aFallBackKoreanLocalized );
326*cdf0e10cSrcweir 
327*cdf0e10cSrcweir     // optimize font list for some locales, as long as Andale Sans UI does not support them
328*cdf0e10cSrcweir     if( aLocale.Language.equalsAscii( "ar" ) ||
329*cdf0e10cSrcweir         aLocale.Language.equalsAscii( "he" ) ||
330*cdf0e10cSrcweir         aLocale.Language.equalsAscii( "iw" ) )
331*cdf0e10cSrcweir     {
332*cdf0e10cSrcweir         return aFallBackArabic;
333*cdf0e10cSrcweir     }
334*cdf0e10cSrcweir     else if( aLocale.Language.equalsAscii( "th" ) )
335*cdf0e10cSrcweir     {
336*cdf0e10cSrcweir         return aFallBackThai;
337*cdf0e10cSrcweir     }
338*cdf0e10cSrcweir     else if( aLocale.Language.equalsAscii( "ko" ) )
339*cdf0e10cSrcweir     {
340*cdf0e10cSrcweir         return aFallBackKorean;
341*cdf0e10cSrcweir     }
342*cdf0e10cSrcweir     else if( aLocale.Language.equalsAscii( "cs" ) ||
343*cdf0e10cSrcweir              aLocale.Language.equalsAscii( "hu" ) ||
344*cdf0e10cSrcweir              aLocale.Language.equalsAscii( "pl" ) ||
345*cdf0e10cSrcweir              aLocale.Language.equalsAscii( "ro" ) ||
346*cdf0e10cSrcweir              aLocale.Language.equalsAscii( "rm" ) ||
347*cdf0e10cSrcweir              aLocale.Language.equalsAscii( "hr" ) ||
348*cdf0e10cSrcweir              aLocale.Language.equalsAscii( "sk" ) ||
349*cdf0e10cSrcweir              aLocale.Language.equalsAscii( "sl" ) ||
350*cdf0e10cSrcweir              aLocale.Language.equalsAscii( "sb" ) )
351*cdf0e10cSrcweir     {
352*cdf0e10cSrcweir         return aFallbackLatin2;
353*cdf0e10cSrcweir     }
354*cdf0e10cSrcweir     else if( aLocale.Language.equalsAscii( "zh" ) )
355*cdf0e10cSrcweir     {
356*cdf0e10cSrcweir         if( ! aLocale.Country.equalsAscii( "cn" ) )
357*cdf0e10cSrcweir             return aFallBackChineseTRD;
358*cdf0e10cSrcweir         else
359*cdf0e10cSrcweir             return aFallBackChineseSIM;
360*cdf0e10cSrcweir     }
361*cdf0e10cSrcweir     else if( aLocale.Language.equalsAscii( "ja" ) )
362*cdf0e10cSrcweir     {
363*cdf0e10cSrcweir         return aFallBackJapanese;
364*cdf0e10cSrcweir     }
365*cdf0e10cSrcweir 
366*cdf0e10cSrcweir    return aFallback;
367*cdf0e10cSrcweir }
368*cdf0e10cSrcweir 
369*cdf0e10cSrcweir // ------------------------------------------------------------------------------------
370*cdf0e10cSrcweir 
371*cdf0e10cSrcweir /*
372*cdf0e10cSrcweir  *  FontSubstConfigItem::get
373*cdf0e10cSrcweir  */
374*cdf0e10cSrcweir 
375*cdf0e10cSrcweir FontSubstConfiguration* FontSubstConfiguration::get()
376*cdf0e10cSrcweir {
377*cdf0e10cSrcweir     if( !mpFontSubstConfiguration )
378*cdf0e10cSrcweir         mpFontSubstConfiguration = new FontSubstConfiguration();
379*cdf0e10cSrcweir     return mpFontSubstConfiguration;
380*cdf0e10cSrcweir }
381*cdf0e10cSrcweir 
382*cdf0e10cSrcweir /*
383*cdf0e10cSrcweir  *  FontSubstConfigItem::FontSubstConfigItem
384*cdf0e10cSrcweir  */
385*cdf0e10cSrcweir 
386*cdf0e10cSrcweir FontSubstConfiguration::FontSubstConfiguration() :
387*cdf0e10cSrcweir 	maSubstHash( 300 )
388*cdf0e10cSrcweir {
389*cdf0e10cSrcweir     try
390*cdf0e10cSrcweir     {
391*cdf0e10cSrcweir         // get service provider
392*cdf0e10cSrcweir         Reference< XMultiServiceFactory > xSMgr( comphelper::getProcessServiceFactory() );
393*cdf0e10cSrcweir         // create configuration hierachical access name
394*cdf0e10cSrcweir         if( xSMgr.is() )
395*cdf0e10cSrcweir         {
396*cdf0e10cSrcweir             try
397*cdf0e10cSrcweir             {
398*cdf0e10cSrcweir                 m_xConfigProvider =
399*cdf0e10cSrcweir                     Reference< XMultiServiceFactory >(
400*cdf0e10cSrcweir                         xSMgr->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
401*cdf0e10cSrcweir                                         "com.sun.star.configuration.ConfigurationProvider" ))),
402*cdf0e10cSrcweir                         UNO_QUERY );
403*cdf0e10cSrcweir                 if( m_xConfigProvider.is() )
404*cdf0e10cSrcweir                 {
405*cdf0e10cSrcweir                     Sequence< Any > aArgs(1);
406*cdf0e10cSrcweir                     PropertyValue aVal;
407*cdf0e10cSrcweir                     aVal.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
408*cdf0e10cSrcweir                     aVal.Value <<= OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.VCL/FontSubstitutions" ) );
409*cdf0e10cSrcweir                     aArgs.getArray()[0] <<= aVal;
410*cdf0e10cSrcweir                     m_xConfigAccess =
411*cdf0e10cSrcweir                         Reference< XNameAccess >(
412*cdf0e10cSrcweir                             m_xConfigProvider->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
413*cdf0e10cSrcweir                                                 "com.sun.star.configuration.ConfigurationAccess" )),
414*cdf0e10cSrcweir                                                                             aArgs ),
415*cdf0e10cSrcweir                             UNO_QUERY );
416*cdf0e10cSrcweir                     if( m_xConfigAccess.is() )
417*cdf0e10cSrcweir                     {
418*cdf0e10cSrcweir                         Sequence< OUString > aLocales = m_xConfigAccess->getElementNames();
419*cdf0e10cSrcweir                         // fill config hash with empty interfaces
420*cdf0e10cSrcweir                         int nLocales = aLocales.getLength();
421*cdf0e10cSrcweir                         const OUString* pLocaleStrings = aLocales.getConstArray();
422*cdf0e10cSrcweir                         Locale aLoc;
423*cdf0e10cSrcweir                         for( int i = 0; i < nLocales; i++ )
424*cdf0e10cSrcweir                         {
425*cdf0e10cSrcweir                             sal_Int32 nIndex = 0;
426*cdf0e10cSrcweir                             aLoc.Language = pLocaleStrings[i].getToken( 0, sal_Unicode('-'), nIndex ).toAsciiLowerCase();
427*cdf0e10cSrcweir                             if( nIndex != -1 )
428*cdf0e10cSrcweir                                 aLoc.Country = pLocaleStrings[i].getToken( 0, sal_Unicode('-'), nIndex ).toAsciiUpperCase();
429*cdf0e10cSrcweir                             else
430*cdf0e10cSrcweir                                 aLoc.Country = OUString();
431*cdf0e10cSrcweir                             if( nIndex != -1 )
432*cdf0e10cSrcweir                                 aLoc.Variant = pLocaleStrings[i].getToken( 0, sal_Unicode('-'), nIndex ).toAsciiUpperCase();
433*cdf0e10cSrcweir                             else
434*cdf0e10cSrcweir                                 aLoc.Variant = OUString();
435*cdf0e10cSrcweir                             m_aSubst[ aLoc ] = LocaleSubst();
436*cdf0e10cSrcweir                             m_aSubst[ aLoc ].aConfigLocaleString = pLocaleStrings[i];
437*cdf0e10cSrcweir                         }
438*cdf0e10cSrcweir                     }
439*cdf0e10cSrcweir                 }
440*cdf0e10cSrcweir             }
441*cdf0e10cSrcweir             catch( Exception& )
442*cdf0e10cSrcweir             {
443*cdf0e10cSrcweir                 // configuration is awry
444*cdf0e10cSrcweir                 m_xConfigProvider.clear();
445*cdf0e10cSrcweir                 m_xConfigAccess.clear();
446*cdf0e10cSrcweir             }
447*cdf0e10cSrcweir         }
448*cdf0e10cSrcweir     }
449*cdf0e10cSrcweir     catch( WrappedTargetException& )
450*cdf0e10cSrcweir     {
451*cdf0e10cSrcweir     }
452*cdf0e10cSrcweir     #if OSL_DEBUG_LEVEL > 1
453*cdf0e10cSrcweir     fprintf( stderr, "config provider: %s, config access: %s\n",
454*cdf0e10cSrcweir              m_xConfigProvider.is() ? "true" : "false",
455*cdf0e10cSrcweir              m_xConfigAccess.is() ? "true" : "false"
456*cdf0e10cSrcweir              );
457*cdf0e10cSrcweir     #endif
458*cdf0e10cSrcweir }
459*cdf0e10cSrcweir 
460*cdf0e10cSrcweir /*
461*cdf0e10cSrcweir  *  FontSubstConfigItem::~FontSubstConfigItem
462*cdf0e10cSrcweir  */
463*cdf0e10cSrcweir 
464*cdf0e10cSrcweir FontSubstConfiguration::~FontSubstConfiguration()
465*cdf0e10cSrcweir {
466*cdf0e10cSrcweir     // release config access
467*cdf0e10cSrcweir     m_xConfigAccess.clear();
468*cdf0e10cSrcweir     // release config provider
469*cdf0e10cSrcweir     m_xConfigProvider.clear();
470*cdf0e10cSrcweir }
471*cdf0e10cSrcweir 
472*cdf0e10cSrcweir /*
473*cdf0e10cSrcweir  *  FontSubstConfigItem::getMapName
474*cdf0e10cSrcweir  */
475*cdf0e10cSrcweir // =======================================================================
476*cdf0e10cSrcweir 
477*cdf0e10cSrcweir static const char* const aImplKillLeadingList[] =
478*cdf0e10cSrcweir {
479*cdf0e10cSrcweir     "microsoft",
480*cdf0e10cSrcweir     "monotype",
481*cdf0e10cSrcweir     "linotype",
482*cdf0e10cSrcweir     "baekmuk",
483*cdf0e10cSrcweir     "adobe",
484*cdf0e10cSrcweir     "nimbus",
485*cdf0e10cSrcweir     "zycjk",
486*cdf0e10cSrcweir     "itc",
487*cdf0e10cSrcweir     "sun",
488*cdf0e10cSrcweir     "amt",
489*cdf0e10cSrcweir     "ms",
490*cdf0e10cSrcweir     "mt",
491*cdf0e10cSrcweir     "cg",
492*cdf0e10cSrcweir     "hg",
493*cdf0e10cSrcweir     "fz",
494*cdf0e10cSrcweir     "ipa",
495*cdf0e10cSrcweir     "sazanami",
496*cdf0e10cSrcweir     "kochi",
497*cdf0e10cSrcweir     NULL
498*cdf0e10cSrcweir };
499*cdf0e10cSrcweir 
500*cdf0e10cSrcweir // -----------------------------------------------------------------------
501*cdf0e10cSrcweir 
502*cdf0e10cSrcweir static const char* const aImplKillTrailingList[] =
503*cdf0e10cSrcweir {
504*cdf0e10cSrcweir     "microsoft",
505*cdf0e10cSrcweir     "monotype",
506*cdf0e10cSrcweir     "linotype",
507*cdf0e10cSrcweir     "adobe",
508*cdf0e10cSrcweir     "nimbus",
509*cdf0e10cSrcweir     "itc",
510*cdf0e10cSrcweir     "sun",
511*cdf0e10cSrcweir     "amt",
512*cdf0e10cSrcweir     "ms",
513*cdf0e10cSrcweir     "mt",
514*cdf0e10cSrcweir     "clm",
515*cdf0e10cSrcweir     // Scripts, for compatibility with older versions
516*cdf0e10cSrcweir     "we",
517*cdf0e10cSrcweir     "cyr",
518*cdf0e10cSrcweir     "tur",
519*cdf0e10cSrcweir     "wt",
520*cdf0e10cSrcweir     "greek",
521*cdf0e10cSrcweir     "wl",
522*cdf0e10cSrcweir     // CJK extensions
523*cdf0e10cSrcweir     "gb",
524*cdf0e10cSrcweir     "big5",
525*cdf0e10cSrcweir     "pro",
526*cdf0e10cSrcweir     "z01",
527*cdf0e10cSrcweir     "z02",
528*cdf0e10cSrcweir     "z03",
529*cdf0e10cSrcweir     "z13",
530*cdf0e10cSrcweir     "b01",
531*cdf0e10cSrcweir     "w3x12",
532*cdf0e10cSrcweir     // Old Printer Fontnames
533*cdf0e10cSrcweir     "5cpi",
534*cdf0e10cSrcweir     "6cpi",
535*cdf0e10cSrcweir     "7cpi",
536*cdf0e10cSrcweir     "8cpi",
537*cdf0e10cSrcweir     "9cpi",
538*cdf0e10cSrcweir     "10cpi",
539*cdf0e10cSrcweir     "11cpi",
540*cdf0e10cSrcweir     "12cpi",
541*cdf0e10cSrcweir     "13cpi",
542*cdf0e10cSrcweir     "14cpi",
543*cdf0e10cSrcweir     "15cpi",
544*cdf0e10cSrcweir     "16cpi",
545*cdf0e10cSrcweir     "18cpi",
546*cdf0e10cSrcweir     "24cpi",
547*cdf0e10cSrcweir     "scale",
548*cdf0e10cSrcweir     "pc",
549*cdf0e10cSrcweir     NULL
550*cdf0e10cSrcweir };
551*cdf0e10cSrcweir 
552*cdf0e10cSrcweir // -----------------------------------------------------------------------
553*cdf0e10cSrcweir 
554*cdf0e10cSrcweir static const char* const aImplKillTrailingWithExceptionsList[] =
555*cdf0e10cSrcweir {
556*cdf0e10cSrcweir     "ce", "monospace", "oldface", NULL,
557*cdf0e10cSrcweir     "ps", "caps", NULL,
558*cdf0e10cSrcweir     NULL
559*cdf0e10cSrcweir };
560*cdf0e10cSrcweir 
561*cdf0e10cSrcweir // -----------------------------------------------------------------------
562*cdf0e10cSrcweir 
563*cdf0e10cSrcweir struct ImplFontAttrWeightSearchData
564*cdf0e10cSrcweir {
565*cdf0e10cSrcweir     const char*             mpStr;
566*cdf0e10cSrcweir     FontWeight              meWeight;
567*cdf0e10cSrcweir };
568*cdf0e10cSrcweir 
569*cdf0e10cSrcweir static ImplFontAttrWeightSearchData const aImplWeightAttrSearchList[] =
570*cdf0e10cSrcweir {
571*cdf0e10cSrcweir // the attribute names are ordered by "first match wins"
572*cdf0e10cSrcweir // e.g. "semilight" should wins over "semi"
573*cdf0e10cSrcweir {   "extrablack",           WEIGHT_BLACK },
574*cdf0e10cSrcweir {   "ultrablack",           WEIGHT_BLACK },
575*cdf0e10cSrcweir {   "ultrabold",            WEIGHT_ULTRABOLD },
576*cdf0e10cSrcweir {   "semibold",             WEIGHT_SEMIBOLD },
577*cdf0e10cSrcweir {   "semilight",            WEIGHT_SEMILIGHT },
578*cdf0e10cSrcweir {   "semi",                 WEIGHT_SEMIBOLD },
579*cdf0e10cSrcweir {   "demi",                 WEIGHT_SEMIBOLD },
580*cdf0e10cSrcweir {   "black",                WEIGHT_BLACK },
581*cdf0e10cSrcweir {   "bold",                 WEIGHT_BOLD },
582*cdf0e10cSrcweir {   "heavy",                WEIGHT_BLACK },
583*cdf0e10cSrcweir {   "ultralight",           WEIGHT_ULTRALIGHT },
584*cdf0e10cSrcweir {   "light",                WEIGHT_LIGHT },
585*cdf0e10cSrcweir {   "medium",               WEIGHT_MEDIUM },
586*cdf0e10cSrcweir {   NULL,                   WEIGHT_DONTKNOW },
587*cdf0e10cSrcweir };
588*cdf0e10cSrcweir 
589*cdf0e10cSrcweir // -----------------------------------------------------------------------
590*cdf0e10cSrcweir 
591*cdf0e10cSrcweir struct ImplFontAttrWidthSearchData
592*cdf0e10cSrcweir {
593*cdf0e10cSrcweir     const char*             mpStr;
594*cdf0e10cSrcweir     FontWidth               meWidth;
595*cdf0e10cSrcweir };
596*cdf0e10cSrcweir 
597*cdf0e10cSrcweir static ImplFontAttrWidthSearchData const aImplWidthAttrSearchList[] =
598*cdf0e10cSrcweir {
599*cdf0e10cSrcweir {   "narrow",               WIDTH_CONDENSED },
600*cdf0e10cSrcweir {   "semicondensed",        WIDTH_SEMI_CONDENSED },
601*cdf0e10cSrcweir {   "ultracondensed",       WIDTH_ULTRA_CONDENSED },
602*cdf0e10cSrcweir {   "semiexpanded",         WIDTH_SEMI_EXPANDED },
603*cdf0e10cSrcweir {   "ultraexpanded",        WIDTH_ULTRA_EXPANDED },
604*cdf0e10cSrcweir {   "expanded",             WIDTH_EXPANDED },
605*cdf0e10cSrcweir {   "wide",                 WIDTH_ULTRA_EXPANDED },
606*cdf0e10cSrcweir {   "condensed",            WIDTH_CONDENSED },
607*cdf0e10cSrcweir {   "cond",                 WIDTH_CONDENSED },
608*cdf0e10cSrcweir {   "cn",                   WIDTH_CONDENSED },
609*cdf0e10cSrcweir {   NULL,                   WIDTH_DONTKNOW },
610*cdf0e10cSrcweir };
611*cdf0e10cSrcweir 
612*cdf0e10cSrcweir struct ImplFontAttrTypeSearchData
613*cdf0e10cSrcweir {
614*cdf0e10cSrcweir     const char*             mpStr;
615*cdf0e10cSrcweir     sal_uLong                   mnType;
616*cdf0e10cSrcweir };
617*cdf0e10cSrcweir 
618*cdf0e10cSrcweir static ImplFontAttrTypeSearchData const aImplTypeAttrSearchList[] =
619*cdf0e10cSrcweir {
620*cdf0e10cSrcweir {   "monotype",             0 },
621*cdf0e10cSrcweir {   "linotype",             0 },
622*cdf0e10cSrcweir {   "titling",              IMPL_FONT_ATTR_TITLING },
623*cdf0e10cSrcweir {   "captitals",            IMPL_FONT_ATTR_CAPITALS },
624*cdf0e10cSrcweir {   "captital",             IMPL_FONT_ATTR_CAPITALS },
625*cdf0e10cSrcweir {   "caps",                 IMPL_FONT_ATTR_CAPITALS },
626*cdf0e10cSrcweir {   "italic",               IMPL_FONT_ATTR_ITALIC },
627*cdf0e10cSrcweir {   "oblique",              IMPL_FONT_ATTR_ITALIC },
628*cdf0e10cSrcweir {   "rounded",              IMPL_FONT_ATTR_ROUNDED },
629*cdf0e10cSrcweir {   "outline",              IMPL_FONT_ATTR_OUTLINE },
630*cdf0e10cSrcweir {   "shadow",               IMPL_FONT_ATTR_SHADOW },
631*cdf0e10cSrcweir {   "handwriting",          IMPL_FONT_ATTR_HANDWRITING | IMPL_FONT_ATTR_SCRIPT },
632*cdf0e10cSrcweir {   "hand",                 IMPL_FONT_ATTR_HANDWRITING | IMPL_FONT_ATTR_SCRIPT },
633*cdf0e10cSrcweir {   "signet",               IMPL_FONT_ATTR_HANDWRITING | IMPL_FONT_ATTR_SCRIPT },
634*cdf0e10cSrcweir {   "script",               IMPL_FONT_ATTR_BRUSHSCRIPT | IMPL_FONT_ATTR_SCRIPT },
635*cdf0e10cSrcweir {   "calligraphy",          IMPL_FONT_ATTR_CHANCERY | IMPL_FONT_ATTR_SCRIPT },
636*cdf0e10cSrcweir {   "chancery",             IMPL_FONT_ATTR_CHANCERY | IMPL_FONT_ATTR_SCRIPT },
637*cdf0e10cSrcweir {   "corsiva",              IMPL_FONT_ATTR_CHANCERY | IMPL_FONT_ATTR_SCRIPT },
638*cdf0e10cSrcweir {   "gothic",               IMPL_FONT_ATTR_SANSSERIF | IMPL_FONT_ATTR_GOTHIC },
639*cdf0e10cSrcweir {   "schoolbook",           IMPL_FONT_ATTR_SERIF | IMPL_FONT_ATTR_SCHOOLBOOK },
640*cdf0e10cSrcweir {   "schlbk",               IMPL_FONT_ATTR_SERIF | IMPL_FONT_ATTR_SCHOOLBOOK },
641*cdf0e10cSrcweir {   "typewriter",           IMPL_FONT_ATTR_TYPEWRITER | IMPL_FONT_ATTR_FIXED },
642*cdf0e10cSrcweir {   "lineprinter",          IMPL_FONT_ATTR_TYPEWRITER | IMPL_FONT_ATTR_FIXED },
643*cdf0e10cSrcweir {   "monospaced",           IMPL_FONT_ATTR_FIXED },
644*cdf0e10cSrcweir {   "monospace",            IMPL_FONT_ATTR_FIXED },
645*cdf0e10cSrcweir {   "mono",                 IMPL_FONT_ATTR_FIXED },
646*cdf0e10cSrcweir {   "fixed",                IMPL_FONT_ATTR_FIXED },
647*cdf0e10cSrcweir {   "sansserif",            IMPL_FONT_ATTR_SANSSERIF },
648*cdf0e10cSrcweir {   "sans",                 IMPL_FONT_ATTR_SANSSERIF },
649*cdf0e10cSrcweir {   "swiss",                IMPL_FONT_ATTR_SANSSERIF },
650*cdf0e10cSrcweir {   "serif",                IMPL_FONT_ATTR_SERIF },
651*cdf0e10cSrcweir {   "bright",               IMPL_FONT_ATTR_SERIF },
652*cdf0e10cSrcweir {   "symbols",              IMPL_FONT_ATTR_SYMBOL },
653*cdf0e10cSrcweir {   "symbol",               IMPL_FONT_ATTR_SYMBOL },
654*cdf0e10cSrcweir {   "dingbats",             IMPL_FONT_ATTR_SYMBOL },
655*cdf0e10cSrcweir {   "dings",                IMPL_FONT_ATTR_SYMBOL },
656*cdf0e10cSrcweir {   "ding",                 IMPL_FONT_ATTR_SYMBOL },
657*cdf0e10cSrcweir {   "bats",                 IMPL_FONT_ATTR_SYMBOL },
658*cdf0e10cSrcweir {   "math",                 IMPL_FONT_ATTR_SYMBOL },
659*cdf0e10cSrcweir {   "oldstyle",             IMPL_FONT_ATTR_OTHERSTYLE },
660*cdf0e10cSrcweir {   "oldface",              IMPL_FONT_ATTR_OTHERSTYLE },
661*cdf0e10cSrcweir {   "old",                  IMPL_FONT_ATTR_OTHERSTYLE },
662*cdf0e10cSrcweir {   "new",                  0 },
663*cdf0e10cSrcweir {   "modern",               0 },
664*cdf0e10cSrcweir {   "lucida",               0 },
665*cdf0e10cSrcweir {   "regular",              0 },
666*cdf0e10cSrcweir {   "extended",             0 },
667*cdf0e10cSrcweir {   "extra",                IMPL_FONT_ATTR_OTHERSTYLE },
668*cdf0e10cSrcweir {   "ext",                  0 },
669*cdf0e10cSrcweir {   "scalable",             0 },
670*cdf0e10cSrcweir {   "scale",                0 },
671*cdf0e10cSrcweir {   "nimbus",               0 },
672*cdf0e10cSrcweir {   "adobe",                0 },
673*cdf0e10cSrcweir {   "itc",                  0 },
674*cdf0e10cSrcweir {   "amt",                  0 },
675*cdf0e10cSrcweir {   "mt",                   0 },
676*cdf0e10cSrcweir {   "ms",                   0 },
677*cdf0e10cSrcweir {   "cpi",                  0 },
678*cdf0e10cSrcweir {   "no",                   0 },
679*cdf0e10cSrcweir {   NULL,                   0 },
680*cdf0e10cSrcweir };
681*cdf0e10cSrcweir 
682*cdf0e10cSrcweir // -----------------------------------------------------------------------
683*cdf0e10cSrcweir 
684*cdf0e10cSrcweir static bool ImplKillLeading( String& rName, const char* const* ppStr )
685*cdf0e10cSrcweir {
686*cdf0e10cSrcweir     for(; *ppStr; ++ppStr )
687*cdf0e10cSrcweir     {
688*cdf0e10cSrcweir         const char*         pStr = *ppStr;
689*cdf0e10cSrcweir         const xub_Unicode*  pNameStr = rName.GetBuffer();
690*cdf0e10cSrcweir         while ( (*pNameStr == (xub_Unicode)(unsigned char)*pStr) && *pStr )
691*cdf0e10cSrcweir         {
692*cdf0e10cSrcweir             pNameStr++;
693*cdf0e10cSrcweir             pStr++;
694*cdf0e10cSrcweir         }
695*cdf0e10cSrcweir         if ( !*pStr )
696*cdf0e10cSrcweir         {
697*cdf0e10cSrcweir             xub_StrLen nLen = sal::static_int_cast<xub_StrLen>(pNameStr - rName.GetBuffer());
698*cdf0e10cSrcweir             rName.Erase( 0, nLen );
699*cdf0e10cSrcweir             return true;
700*cdf0e10cSrcweir         }
701*cdf0e10cSrcweir     }
702*cdf0e10cSrcweir 
703*cdf0e10cSrcweir     // special case for Baekmuk
704*cdf0e10cSrcweir     // TODO: allow non-ASCII KillLeading list
705*cdf0e10cSrcweir     const xub_Unicode* pNameStr = rName.GetBuffer();
706*cdf0e10cSrcweir     if( (pNameStr[0]==0xBC31) && (pNameStr[1]==0xBC35) )
707*cdf0e10cSrcweir     {
708*cdf0e10cSrcweir         xub_StrLen nLen = (pNameStr[2]==0x0020) ? 3 : 2;
709*cdf0e10cSrcweir         rName.Erase( 0, nLen );
710*cdf0e10cSrcweir         return true;
711*cdf0e10cSrcweir     }
712*cdf0e10cSrcweir 
713*cdf0e10cSrcweir     return false;
714*cdf0e10cSrcweir }
715*cdf0e10cSrcweir 
716*cdf0e10cSrcweir // -----------------------------------------------------------------------
717*cdf0e10cSrcweir 
718*cdf0e10cSrcweir static xub_StrLen ImplIsTrailing( const String& rName, const char* pStr )
719*cdf0e10cSrcweir {
720*cdf0e10cSrcweir     xub_StrLen nStrLen = static_cast<xub_StrLen>( strlen( pStr ) );
721*cdf0e10cSrcweir     if( nStrLen >= rName.Len() )
722*cdf0e10cSrcweir         return 0;
723*cdf0e10cSrcweir 
724*cdf0e10cSrcweir     const xub_Unicode* pEndName = rName.GetBuffer() + rName.Len();
725*cdf0e10cSrcweir     const sal_Unicode* pNameStr = pEndName - nStrLen;
726*cdf0e10cSrcweir     do if( *(pNameStr++) != *(pStr++) )
727*cdf0e10cSrcweir         return 0;
728*cdf0e10cSrcweir     while( *pStr );
729*cdf0e10cSrcweir 
730*cdf0e10cSrcweir     return nStrLen;
731*cdf0e10cSrcweir }
732*cdf0e10cSrcweir 
733*cdf0e10cSrcweir // -----------------------------------------------------------------------
734*cdf0e10cSrcweir 
735*cdf0e10cSrcweir static bool ImplKillTrailing( String& rName, const char* const* ppStr )
736*cdf0e10cSrcweir {
737*cdf0e10cSrcweir     for(; *ppStr; ++ppStr )
738*cdf0e10cSrcweir     {
739*cdf0e10cSrcweir         xub_StrLen nTrailLen = ImplIsTrailing( rName, *ppStr );
740*cdf0e10cSrcweir         if( nTrailLen )
741*cdf0e10cSrcweir         {
742*cdf0e10cSrcweir             rName.Erase( rName.Len()-nTrailLen );
743*cdf0e10cSrcweir             return true;
744*cdf0e10cSrcweir         }
745*cdf0e10cSrcweir     }
746*cdf0e10cSrcweir 
747*cdf0e10cSrcweir     return false;
748*cdf0e10cSrcweir }
749*cdf0e10cSrcweir 
750*cdf0e10cSrcweir // -----------------------------------------------------------------------
751*cdf0e10cSrcweir 
752*cdf0e10cSrcweir static bool ImplKillTrailingWithExceptions( String& rName, const char* const* ppStr )
753*cdf0e10cSrcweir {
754*cdf0e10cSrcweir     for(; *ppStr; ++ppStr )
755*cdf0e10cSrcweir     {
756*cdf0e10cSrcweir         xub_StrLen nTrailLen = ImplIsTrailing( rName, *ppStr );
757*cdf0e10cSrcweir         if( nTrailLen )
758*cdf0e10cSrcweir         {
759*cdf0e10cSrcweir             // check string match against string exceptions
760*cdf0e10cSrcweir             while( *++ppStr )
761*cdf0e10cSrcweir                 if( ImplIsTrailing( rName, *ppStr ) )
762*cdf0e10cSrcweir                     return false;
763*cdf0e10cSrcweir 
764*cdf0e10cSrcweir             rName.Erase( rName.Len()-nTrailLen );
765*cdf0e10cSrcweir             return true;
766*cdf0e10cSrcweir         }
767*cdf0e10cSrcweir         else
768*cdf0e10cSrcweir         {
769*cdf0e10cSrcweir             // skip exception strings
770*cdf0e10cSrcweir             while( *++ppStr ) ;
771*cdf0e10cSrcweir         }
772*cdf0e10cSrcweir     }
773*cdf0e10cSrcweir 
774*cdf0e10cSrcweir     return false;
775*cdf0e10cSrcweir }
776*cdf0e10cSrcweir 
777*cdf0e10cSrcweir // -----------------------------------------------------------------------
778*cdf0e10cSrcweir 
779*cdf0e10cSrcweir static sal_Bool ImplFindAndErase( String& rName, const char* pStr )
780*cdf0e10cSrcweir {
781*cdf0e10cSrcweir     xub_StrLen nPos = rName.SearchAscii( pStr );
782*cdf0e10cSrcweir     if ( nPos == STRING_NOTFOUND )
783*cdf0e10cSrcweir         return sal_False;
784*cdf0e10cSrcweir 
785*cdf0e10cSrcweir     const char* pTempStr = pStr;
786*cdf0e10cSrcweir     while ( *pTempStr )
787*cdf0e10cSrcweir         pTempStr++;
788*cdf0e10cSrcweir     rName.Erase( nPos, (xub_StrLen)(pTempStr-pStr) );
789*cdf0e10cSrcweir     return sal_True;
790*cdf0e10cSrcweir }
791*cdf0e10cSrcweir 
792*cdf0e10cSrcweir // =======================================================================
793*cdf0e10cSrcweir 
794*cdf0e10cSrcweir void FontSubstConfiguration::getMapName( const String& rOrgName, String& rShortName,
795*cdf0e10cSrcweir     String& rFamilyName, FontWeight& rWeight, FontWidth& rWidth, sal_uLong& rType )
796*cdf0e10cSrcweir {
797*cdf0e10cSrcweir     rShortName = rOrgName;
798*cdf0e10cSrcweir 
799*cdf0e10cSrcweir     // TODO: get rid of the crazy O(N*strlen) searches below
800*cdf0e10cSrcweir     // they should be possible in O(strlen)
801*cdf0e10cSrcweir 
802*cdf0e10cSrcweir     // Kill leading vendor names and other unimportant data
803*cdf0e10cSrcweir     ImplKillLeading( rShortName, aImplKillLeadingList );
804*cdf0e10cSrcweir 
805*cdf0e10cSrcweir     // Kill trailing vendor names and other unimportant data
806*cdf0e10cSrcweir     ImplKillTrailing( rShortName, aImplKillTrailingList );
807*cdf0e10cSrcweir     ImplKillTrailingWithExceptions( rShortName, aImplKillTrailingWithExceptionsList );
808*cdf0e10cSrcweir 
809*cdf0e10cSrcweir     rFamilyName = rShortName;
810*cdf0e10cSrcweir 
811*cdf0e10cSrcweir     // Kill attributes from the name and update the data
812*cdf0e10cSrcweir     // Weight
813*cdf0e10cSrcweir     const ImplFontAttrWeightSearchData* pWeightList = aImplWeightAttrSearchList;
814*cdf0e10cSrcweir     while ( pWeightList->mpStr )
815*cdf0e10cSrcweir     {
816*cdf0e10cSrcweir         if ( ImplFindAndErase( rFamilyName, pWeightList->mpStr ) )
817*cdf0e10cSrcweir         {
818*cdf0e10cSrcweir             if ( (rWeight == WEIGHT_DONTKNOW) || (rWeight == WEIGHT_NORMAL) )
819*cdf0e10cSrcweir                 rWeight = pWeightList->meWeight;
820*cdf0e10cSrcweir             break;
821*cdf0e10cSrcweir         }
822*cdf0e10cSrcweir         pWeightList++;
823*cdf0e10cSrcweir     }
824*cdf0e10cSrcweir 
825*cdf0e10cSrcweir     // Width
826*cdf0e10cSrcweir     const ImplFontAttrWidthSearchData* pWidthList = aImplWidthAttrSearchList;
827*cdf0e10cSrcweir     while ( pWidthList->mpStr )
828*cdf0e10cSrcweir     {
829*cdf0e10cSrcweir         if ( ImplFindAndErase( rFamilyName, pWidthList->mpStr ) )
830*cdf0e10cSrcweir         {
831*cdf0e10cSrcweir             if ( (rWidth == WIDTH_DONTKNOW) || (rWidth == WIDTH_NORMAL) )
832*cdf0e10cSrcweir                 rWidth = pWidthList->meWidth;
833*cdf0e10cSrcweir             break;
834*cdf0e10cSrcweir         }
835*cdf0e10cSrcweir         pWidthList++;
836*cdf0e10cSrcweir     }
837*cdf0e10cSrcweir 
838*cdf0e10cSrcweir     // Type
839*cdf0e10cSrcweir     rType = 0;
840*cdf0e10cSrcweir     const ImplFontAttrTypeSearchData* pTypeList = aImplTypeAttrSearchList;
841*cdf0e10cSrcweir     while ( pTypeList->mpStr )
842*cdf0e10cSrcweir     {
843*cdf0e10cSrcweir         if ( ImplFindAndErase( rFamilyName, pTypeList->mpStr ) )
844*cdf0e10cSrcweir             rType |= pTypeList->mnType;
845*cdf0e10cSrcweir         pTypeList++;
846*cdf0e10cSrcweir     }
847*cdf0e10cSrcweir 
848*cdf0e10cSrcweir     // Remove numbers
849*cdf0e10cSrcweir     // TODO: also remove localized and fullwidth digits
850*cdf0e10cSrcweir     xub_StrLen i = 0;
851*cdf0e10cSrcweir     while ( i < rFamilyName.Len() )
852*cdf0e10cSrcweir     {
853*cdf0e10cSrcweir         sal_Unicode c = rFamilyName.GetChar( i );
854*cdf0e10cSrcweir         if ( (c >= 0x0030) && (c <= 0x0039) )
855*cdf0e10cSrcweir             rFamilyName.Erase( i, 1 );
856*cdf0e10cSrcweir         else
857*cdf0e10cSrcweir             i++;
858*cdf0e10cSrcweir     }
859*cdf0e10cSrcweir }
860*cdf0e10cSrcweir 
861*cdf0e10cSrcweir 
862*cdf0e10cSrcweir struct StrictStringSort : public ::std::binary_function< const FontNameAttr&, const FontNameAttr&, bool >
863*cdf0e10cSrcweir {
864*cdf0e10cSrcweir     bool operator()( const FontNameAttr& rLeft, const FontNameAttr& rRight )
865*cdf0e10cSrcweir     { return rLeft.Name.CompareTo( rRight.Name ) == COMPARE_LESS ; }
866*cdf0e10cSrcweir };
867*cdf0e10cSrcweir 
868*cdf0e10cSrcweir static const char* const pAttribNames[] =
869*cdf0e10cSrcweir {
870*cdf0e10cSrcweir     "default",
871*cdf0e10cSrcweir     "standard",
872*cdf0e10cSrcweir     "normal",
873*cdf0e10cSrcweir     "symbol",
874*cdf0e10cSrcweir     "fixed",
875*cdf0e10cSrcweir     "sansserif",
876*cdf0e10cSrcweir     "serif",
877*cdf0e10cSrcweir     "decorative",
878*cdf0e10cSrcweir     "special",
879*cdf0e10cSrcweir     "italic",
880*cdf0e10cSrcweir     "title",
881*cdf0e10cSrcweir     "capitals",
882*cdf0e10cSrcweir     "cjk",
883*cdf0e10cSrcweir     "cjk_jp",
884*cdf0e10cSrcweir     "cjk_sc",
885*cdf0e10cSrcweir     "cjk_tc",
886*cdf0e10cSrcweir     "cjk_kr",
887*cdf0e10cSrcweir     "ctl",
888*cdf0e10cSrcweir     "nonelatin",
889*cdf0e10cSrcweir     "full",
890*cdf0e10cSrcweir     "outline",
891*cdf0e10cSrcweir     "shadow",
892*cdf0e10cSrcweir     "rounded",
893*cdf0e10cSrcweir     "typewriter",
894*cdf0e10cSrcweir     "script",
895*cdf0e10cSrcweir     "handwriting",
896*cdf0e10cSrcweir     "chancery",
897*cdf0e10cSrcweir     "comic",
898*cdf0e10cSrcweir     "brushscript",
899*cdf0e10cSrcweir     "gothic",
900*cdf0e10cSrcweir     "schoolbook",
901*cdf0e10cSrcweir     "other"
902*cdf0e10cSrcweir };
903*cdf0e10cSrcweir 
904*cdf0e10cSrcweir struct enum_convert
905*cdf0e10cSrcweir {
906*cdf0e10cSrcweir     const char* pName;
907*cdf0e10cSrcweir     int          nEnum;
908*cdf0e10cSrcweir };
909*cdf0e10cSrcweir 
910*cdf0e10cSrcweir 
911*cdf0e10cSrcweir static const enum_convert pWeightNames[] =
912*cdf0e10cSrcweir {
913*cdf0e10cSrcweir     { "normal", WEIGHT_NORMAL },
914*cdf0e10cSrcweir     { "medium", WEIGHT_MEDIUM },
915*cdf0e10cSrcweir     { "bold", WEIGHT_BOLD },
916*cdf0e10cSrcweir     { "black", WEIGHT_BLACK },
917*cdf0e10cSrcweir     { "semibold", WEIGHT_SEMIBOLD },
918*cdf0e10cSrcweir     { "light", WEIGHT_LIGHT },
919*cdf0e10cSrcweir     { "semilight", WEIGHT_SEMILIGHT },
920*cdf0e10cSrcweir     { "ultrabold", WEIGHT_ULTRABOLD },
921*cdf0e10cSrcweir     { "semi", WEIGHT_SEMIBOLD },
922*cdf0e10cSrcweir     { "demi", WEIGHT_SEMIBOLD },
923*cdf0e10cSrcweir     { "heavy", WEIGHT_BLACK },
924*cdf0e10cSrcweir     { "unknown", WEIGHT_DONTKNOW },
925*cdf0e10cSrcweir     { "thin", WEIGHT_THIN },
926*cdf0e10cSrcweir     { "ultralight", WEIGHT_ULTRALIGHT }
927*cdf0e10cSrcweir };
928*cdf0e10cSrcweir 
929*cdf0e10cSrcweir static const enum_convert pWidthNames[] =
930*cdf0e10cSrcweir {
931*cdf0e10cSrcweir     { "normal", WIDTH_NORMAL },
932*cdf0e10cSrcweir     { "condensed", WIDTH_CONDENSED },
933*cdf0e10cSrcweir     { "expanded", WIDTH_EXPANDED },
934*cdf0e10cSrcweir     { "unknown", WIDTH_DONTKNOW },
935*cdf0e10cSrcweir     { "ultracondensed", WIDTH_ULTRA_CONDENSED },
936*cdf0e10cSrcweir     { "extracondensed", WIDTH_EXTRA_CONDENSED },
937*cdf0e10cSrcweir     { "semicondensed", WIDTH_SEMI_CONDENSED },
938*cdf0e10cSrcweir     { "semiexpanded", WIDTH_SEMI_EXPANDED },
939*cdf0e10cSrcweir     { "extraexpanded", WIDTH_EXTRA_EXPANDED },
940*cdf0e10cSrcweir     { "ultraexpanded", WIDTH_ULTRA_EXPANDED }
941*cdf0e10cSrcweir };
942*cdf0e10cSrcweir 
943*cdf0e10cSrcweir void FontSubstConfiguration::fillSubstVector( const com::sun::star::uno::Reference< XNameAccess > xFont,
944*cdf0e10cSrcweir                                               const rtl::OUString& rType,
945*cdf0e10cSrcweir                                               std::vector< String >& rSubstVector ) const
946*cdf0e10cSrcweir {
947*cdf0e10cSrcweir     try
948*cdf0e10cSrcweir     {
949*cdf0e10cSrcweir         Any aAny = xFont->getByName( rType );
950*cdf0e10cSrcweir         if( aAny.getValueTypeClass() == TypeClass_STRING )
951*cdf0e10cSrcweir         {
952*cdf0e10cSrcweir             const OUString* pLine = (const OUString*)aAny.getValue();
953*cdf0e10cSrcweir             sal_Int32 nIndex = 0;
954*cdf0e10cSrcweir             sal_Int32 nLength = pLine->getLength();
955*cdf0e10cSrcweir             if( nLength )
956*cdf0e10cSrcweir             {
957*cdf0e10cSrcweir                 const sal_Unicode* pStr = pLine->getStr();
958*cdf0e10cSrcweir                 sal_Int32 nTokens = 0;
959*cdf0e10cSrcweir                 // count tokens
960*cdf0e10cSrcweir                 while( nLength-- )
961*cdf0e10cSrcweir                 {
962*cdf0e10cSrcweir                     if( *pStr++ == sal_Unicode(';') )
963*cdf0e10cSrcweir                         nTokens++;
964*cdf0e10cSrcweir                 }
965*cdf0e10cSrcweir                 rSubstVector.clear();
966*cdf0e10cSrcweir                 // optimize performance, heap fragmentation
967*cdf0e10cSrcweir                 rSubstVector.reserve( nTokens );
968*cdf0e10cSrcweir                 while( nIndex != -1 )
969*cdf0e10cSrcweir                 {
970*cdf0e10cSrcweir                     OUString aSubst( pLine->getToken( 0, ';', nIndex ) );
971*cdf0e10cSrcweir                     if( aSubst.getLength() )
972*cdf0e10cSrcweir 					{
973*cdf0e10cSrcweir 						UniqueSubstHash::iterator aEntry = maSubstHash.find( aSubst );
974*cdf0e10cSrcweir 						if (aEntry != maSubstHash.end())
975*cdf0e10cSrcweir 							aSubst = *aEntry;
976*cdf0e10cSrcweir 						else
977*cdf0e10cSrcweir 							maSubstHash.insert( aSubst );
978*cdf0e10cSrcweir                         rSubstVector.push_back( aSubst );
979*cdf0e10cSrcweir 					}
980*cdf0e10cSrcweir                 }
981*cdf0e10cSrcweir             }
982*cdf0e10cSrcweir         }
983*cdf0e10cSrcweir     }
984*cdf0e10cSrcweir     catch( NoSuchElementException )
985*cdf0e10cSrcweir     {
986*cdf0e10cSrcweir     }
987*cdf0e10cSrcweir     catch( WrappedTargetException )
988*cdf0e10cSrcweir     {
989*cdf0e10cSrcweir     }
990*cdf0e10cSrcweir }
991*cdf0e10cSrcweir 
992*cdf0e10cSrcweir FontWeight FontSubstConfiguration::getSubstWeight( const com::sun::star::uno::Reference< XNameAccess > xFont,
993*cdf0e10cSrcweir                                                    const rtl::OUString& rType ) const
994*cdf0e10cSrcweir {
995*cdf0e10cSrcweir     int weight = -1;
996*cdf0e10cSrcweir     try
997*cdf0e10cSrcweir     {
998*cdf0e10cSrcweir         Any aAny = xFont->getByName( rType );
999*cdf0e10cSrcweir         if( aAny.getValueTypeClass() == TypeClass_STRING )
1000*cdf0e10cSrcweir         {
1001*cdf0e10cSrcweir             const OUString* pLine = (const OUString*)aAny.getValue();
1002*cdf0e10cSrcweir             if( pLine->getLength() )
1003*cdf0e10cSrcweir             {
1004*cdf0e10cSrcweir                 for( weight=sizeof(pWeightNames)/sizeof(pWeightNames[0])-1; weight >= 0; weight-- )
1005*cdf0e10cSrcweir                     if( pLine->equalsIgnoreAsciiCaseAscii( pWeightNames[weight].pName ) )
1006*cdf0e10cSrcweir                         break;
1007*cdf0e10cSrcweir             }
1008*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1009*cdf0e10cSrcweir             if( weight < 0 )
1010*cdf0e10cSrcweir                 fprintf( stderr, "Error: invalid weight %s\n",
1011*cdf0e10cSrcweir                          OUStringToOString( *pLine, RTL_TEXTENCODING_ASCII_US ).getStr() );
1012*cdf0e10cSrcweir #endif
1013*cdf0e10cSrcweir         }
1014*cdf0e10cSrcweir     }
1015*cdf0e10cSrcweir     catch( NoSuchElementException )
1016*cdf0e10cSrcweir     {
1017*cdf0e10cSrcweir     }
1018*cdf0e10cSrcweir     catch( WrappedTargetException )
1019*cdf0e10cSrcweir     {
1020*cdf0e10cSrcweir     }
1021*cdf0e10cSrcweir     return (FontWeight)( weight >= 0 ? pWeightNames[weight].nEnum : WEIGHT_DONTKNOW );
1022*cdf0e10cSrcweir }
1023*cdf0e10cSrcweir 
1024*cdf0e10cSrcweir FontWidth FontSubstConfiguration::getSubstWidth( const com::sun::star::uno::Reference< XNameAccess > xFont,
1025*cdf0e10cSrcweir                                                  const rtl::OUString& rType ) const
1026*cdf0e10cSrcweir {
1027*cdf0e10cSrcweir     int width = -1;
1028*cdf0e10cSrcweir     try
1029*cdf0e10cSrcweir     {
1030*cdf0e10cSrcweir         Any aAny = xFont->getByName( rType );
1031*cdf0e10cSrcweir         if( aAny.getValueTypeClass() == TypeClass_STRING )
1032*cdf0e10cSrcweir         {
1033*cdf0e10cSrcweir             const OUString* pLine = (const OUString*)aAny.getValue();
1034*cdf0e10cSrcweir             if( pLine->getLength() )
1035*cdf0e10cSrcweir             {
1036*cdf0e10cSrcweir                 for( width=sizeof(pWidthNames)/sizeof(pWidthNames[0])-1; width >= 0; width-- )
1037*cdf0e10cSrcweir                     if( pLine->equalsIgnoreAsciiCaseAscii( pWidthNames[width].pName ) )
1038*cdf0e10cSrcweir                         break;
1039*cdf0e10cSrcweir             }
1040*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1041*cdf0e10cSrcweir             if( width < 0 )
1042*cdf0e10cSrcweir                 fprintf( stderr, "Error: invalid width %s\n",
1043*cdf0e10cSrcweir                          OUStringToOString( *pLine, RTL_TEXTENCODING_ASCII_US ).getStr() );
1044*cdf0e10cSrcweir #endif
1045*cdf0e10cSrcweir         }
1046*cdf0e10cSrcweir     }
1047*cdf0e10cSrcweir     catch( NoSuchElementException )
1048*cdf0e10cSrcweir     {
1049*cdf0e10cSrcweir     }
1050*cdf0e10cSrcweir     catch( WrappedTargetException )
1051*cdf0e10cSrcweir     {
1052*cdf0e10cSrcweir     }
1053*cdf0e10cSrcweir     return (FontWidth)( width >= 0 ? pWidthNames[width].nEnum : WIDTH_DONTKNOW );
1054*cdf0e10cSrcweir }
1055*cdf0e10cSrcweir 
1056*cdf0e10cSrcweir unsigned long FontSubstConfiguration::getSubstType( const com::sun::star::uno::Reference< XNameAccess > xFont,
1057*cdf0e10cSrcweir                                                     const rtl::OUString& rType ) const
1058*cdf0e10cSrcweir {
1059*cdf0e10cSrcweir     unsigned long type = 0;
1060*cdf0e10cSrcweir     try
1061*cdf0e10cSrcweir     {
1062*cdf0e10cSrcweir         Any aAny = xFont->getByName( rType );
1063*cdf0e10cSrcweir         if( aAny.getValueTypeClass() == TypeClass_STRING )
1064*cdf0e10cSrcweir         {
1065*cdf0e10cSrcweir             const OUString* pLine = (const OUString*)aAny.getValue();
1066*cdf0e10cSrcweir             if( pLine->getLength() )
1067*cdf0e10cSrcweir             {
1068*cdf0e10cSrcweir                 sal_Int32 nIndex = 0;
1069*cdf0e10cSrcweir                 while( nIndex != -1 )
1070*cdf0e10cSrcweir                 {
1071*cdf0e10cSrcweir                     String aToken( pLine->getToken( 0, ',', nIndex ) );
1072*cdf0e10cSrcweir                     for( int k = 0; k < 32; k++ )
1073*cdf0e10cSrcweir                         if( aToken.EqualsIgnoreCaseAscii( pAttribNames[k] ) )
1074*cdf0e10cSrcweir                         {
1075*cdf0e10cSrcweir                             type |= 1 << k;
1076*cdf0e10cSrcweir                             break;
1077*cdf0e10cSrcweir                         }
1078*cdf0e10cSrcweir                 }
1079*cdf0e10cSrcweir             }
1080*cdf0e10cSrcweir         }
1081*cdf0e10cSrcweir     }
1082*cdf0e10cSrcweir     catch( NoSuchElementException )
1083*cdf0e10cSrcweir     {
1084*cdf0e10cSrcweir     }
1085*cdf0e10cSrcweir     catch( WrappedTargetException )
1086*cdf0e10cSrcweir     {
1087*cdf0e10cSrcweir     }
1088*cdf0e10cSrcweir 
1089*cdf0e10cSrcweir     return type;
1090*cdf0e10cSrcweir }
1091*cdf0e10cSrcweir 
1092*cdf0e10cSrcweir void FontSubstConfiguration::readLocaleSubst( const com::sun::star::lang::Locale& rLocale ) const
1093*cdf0e10cSrcweir {
1094*cdf0e10cSrcweir     std::hash_map< Locale, LocaleSubst, LocaleHash >::const_iterator it =
1095*cdf0e10cSrcweir         m_aSubst.find( rLocale );
1096*cdf0e10cSrcweir     if( it != m_aSubst.end() )
1097*cdf0e10cSrcweir     {
1098*cdf0e10cSrcweir         if( ! it->second.bConfigRead )
1099*cdf0e10cSrcweir         {
1100*cdf0e10cSrcweir             it->second.bConfigRead = true;
1101*cdf0e10cSrcweir             Reference< XNameAccess > xNode;
1102*cdf0e10cSrcweir             try
1103*cdf0e10cSrcweir             {
1104*cdf0e10cSrcweir                 Any aAny = m_xConfigAccess->getByName( it->second.aConfigLocaleString );
1105*cdf0e10cSrcweir                 aAny >>= xNode;
1106*cdf0e10cSrcweir             }
1107*cdf0e10cSrcweir             catch( NoSuchElementException )
1108*cdf0e10cSrcweir             {
1109*cdf0e10cSrcweir             }
1110*cdf0e10cSrcweir             catch( WrappedTargetException )
1111*cdf0e10cSrcweir             {
1112*cdf0e10cSrcweir             }
1113*cdf0e10cSrcweir             if( xNode.is() )
1114*cdf0e10cSrcweir             {
1115*cdf0e10cSrcweir                 Sequence< OUString > aFonts = xNode->getElementNames();
1116*cdf0e10cSrcweir                 int nFonts = aFonts.getLength();
1117*cdf0e10cSrcweir                 const OUString* pFontNames = aFonts.getConstArray();
1118*cdf0e10cSrcweir                 // improve performance, heap fragmentation
1119*cdf0e10cSrcweir                 it->second.aSubstAttributes.reserve( nFonts );
1120*cdf0e10cSrcweir 
1121*cdf0e10cSrcweir                 // strings for subst retrieval, construct only once
1122*cdf0e10cSrcweir                 OUString aSubstFontsStr     ( RTL_CONSTASCII_USTRINGPARAM( "SubstFonts" ) );
1123*cdf0e10cSrcweir                 OUString aSubstFontsMSStr   ( RTL_CONSTASCII_USTRINGPARAM( "SubstFontsMS" ) );
1124*cdf0e10cSrcweir                 OUString aSubstFontsPSStr   ( RTL_CONSTASCII_USTRINGPARAM( "SubstFontsPS" ) );
1125*cdf0e10cSrcweir                 OUString aSubstFontsHTMLStr ( RTL_CONSTASCII_USTRINGPARAM( "SubstFontsHTML" ) );
1126*cdf0e10cSrcweir                 OUString aSubstWeightStr    ( RTL_CONSTASCII_USTRINGPARAM( "FontWeight" ) );
1127*cdf0e10cSrcweir                 OUString aSubstWidthStr     ( RTL_CONSTASCII_USTRINGPARAM( "FontWidth" ) );
1128*cdf0e10cSrcweir                 OUString aSubstTypeStr      ( RTL_CONSTASCII_USTRINGPARAM( "FontType" ) );
1129*cdf0e10cSrcweir                 for( int i = 0; i < nFonts; i++ )
1130*cdf0e10cSrcweir                 {
1131*cdf0e10cSrcweir                     Reference< XNameAccess > xFont;
1132*cdf0e10cSrcweir                     try
1133*cdf0e10cSrcweir                     {
1134*cdf0e10cSrcweir                         Any aAny = xNode->getByName( pFontNames[i] );
1135*cdf0e10cSrcweir                         aAny >>= xFont;
1136*cdf0e10cSrcweir                     }
1137*cdf0e10cSrcweir                     catch( NoSuchElementException )
1138*cdf0e10cSrcweir                     {
1139*cdf0e10cSrcweir                     }
1140*cdf0e10cSrcweir                     catch( WrappedTargetException )
1141*cdf0e10cSrcweir                     {
1142*cdf0e10cSrcweir                     }
1143*cdf0e10cSrcweir                     if( ! xFont.is() )
1144*cdf0e10cSrcweir                     {
1145*cdf0e10cSrcweir                         #if OSL_DEBUG_LEVEL > 1
1146*cdf0e10cSrcweir                         fprintf( stderr, "did not get font attributes for %s\n",
1147*cdf0e10cSrcweir                                  OUStringToOString( pFontNames[i], RTL_TEXTENCODING_UTF8 ).getStr() );
1148*cdf0e10cSrcweir                         #endif
1149*cdf0e10cSrcweir                         continue;
1150*cdf0e10cSrcweir                     }
1151*cdf0e10cSrcweir 
1152*cdf0e10cSrcweir                     FontNameAttr aAttr;
1153*cdf0e10cSrcweir                     // read subst attributes from config
1154*cdf0e10cSrcweir                     aAttr.Name = pFontNames[i];
1155*cdf0e10cSrcweir                     fillSubstVector( xFont, aSubstFontsStr, aAttr.Substitutions );
1156*cdf0e10cSrcweir                     fillSubstVector( xFont, aSubstFontsMSStr, aAttr.MSSubstitutions );
1157*cdf0e10cSrcweir                     fillSubstVector( xFont, aSubstFontsPSStr, aAttr.PSSubstitutions );
1158*cdf0e10cSrcweir                     fillSubstVector( xFont, aSubstFontsHTMLStr, aAttr.HTMLSubstitutions );
1159*cdf0e10cSrcweir                     aAttr.Weight = getSubstWeight( xFont, aSubstWeightStr );
1160*cdf0e10cSrcweir                     aAttr.Width = getSubstWidth( xFont, aSubstWidthStr );
1161*cdf0e10cSrcweir                     aAttr.Type = getSubstType( xFont, aSubstTypeStr );
1162*cdf0e10cSrcweir 
1163*cdf0e10cSrcweir                     // finally insert this entry
1164*cdf0e10cSrcweir                     it->second.aSubstAttributes.push_back( aAttr );
1165*cdf0e10cSrcweir                 }
1166*cdf0e10cSrcweir                 std::sort( it->second.aSubstAttributes.begin(), it->second.aSubstAttributes.end(), StrictStringSort() );
1167*cdf0e10cSrcweir             }
1168*cdf0e10cSrcweir         }
1169*cdf0e10cSrcweir     }
1170*cdf0e10cSrcweir }
1171*cdf0e10cSrcweir 
1172*cdf0e10cSrcweir const FontNameAttr* FontSubstConfiguration::getSubstInfo( const String& rFontName, const Locale& rLocale ) const
1173*cdf0e10cSrcweir {
1174*cdf0e10cSrcweir     if( !rFontName.Len() )
1175*cdf0e10cSrcweir         return NULL;
1176*cdf0e10cSrcweir 
1177*cdf0e10cSrcweir     // search if a  (language dep.) replacement table for the given font exists
1178*cdf0e10cSrcweir     // fallback is english
1179*cdf0e10cSrcweir     String aSearchFont( rFontName );
1180*cdf0e10cSrcweir     aSearchFont.ToLowerAscii();
1181*cdf0e10cSrcweir     FontNameAttr aSearchAttr;
1182*cdf0e10cSrcweir     aSearchAttr.Name = aSearchFont;
1183*cdf0e10cSrcweir 
1184*cdf0e10cSrcweir     Locale aLocale;
1185*cdf0e10cSrcweir     aLocale.Language = rLocale.Language.toAsciiLowerCase();
1186*cdf0e10cSrcweir     aLocale.Country = rLocale.Country.toAsciiUpperCase();
1187*cdf0e10cSrcweir     aLocale.Variant = rLocale.Variant.toAsciiUpperCase();
1188*cdf0e10cSrcweir 
1189*cdf0e10cSrcweir     if( ! aLocale.Language.getLength() )
1190*cdf0e10cSrcweir         aLocale = SvtSysLocale().GetUILocale();
1191*cdf0e10cSrcweir 
1192*cdf0e10cSrcweir     while( aLocale.Language.getLength() )
1193*cdf0e10cSrcweir     {
1194*cdf0e10cSrcweir         std::hash_map< Locale, LocaleSubst, LocaleHash >::const_iterator lang = m_aSubst.find( aLocale );
1195*cdf0e10cSrcweir         if( lang != m_aSubst.end() )
1196*cdf0e10cSrcweir         {
1197*cdf0e10cSrcweir             if( ! lang->second.bConfigRead )
1198*cdf0e10cSrcweir                 readLocaleSubst( aLocale );
1199*cdf0e10cSrcweir             // try to find an exact match
1200*cdf0e10cSrcweir             // because the list is sorted this will also find fontnames of the form searchfontname*
1201*cdf0e10cSrcweir             std::vector< FontNameAttr >::const_iterator it = ::std::lower_bound( lang->second.aSubstAttributes.begin(), lang->second.aSubstAttributes.end(), aSearchAttr, StrictStringSort() );
1202*cdf0e10cSrcweir             if( it != lang->second.aSubstAttributes.end())
1203*cdf0e10cSrcweir             {
1204*cdf0e10cSrcweir                 const FontNameAttr& rFoundAttr = *it;
1205*cdf0e10cSrcweir                 // a search for "abcblack" may match with an entry for "abc"
1206*cdf0e10cSrcweir                 // the reverse is not a good idea (e.g. #i112731# alba->albani)
1207*cdf0e10cSrcweir                 if( rFoundAttr.Name.Len() <= aSearchFont.Len() )
1208*cdf0e10cSrcweir                     if( aSearchFont.CompareTo( rFoundAttr.Name, rFoundAttr.Name.Len() ) == COMPARE_EQUAL )
1209*cdf0e10cSrcweir                         return &rFoundAttr;
1210*cdf0e10cSrcweir             }
1211*cdf0e10cSrcweir         }
1212*cdf0e10cSrcweir         // gradually become more unspecific
1213*cdf0e10cSrcweir         if( aLocale.Variant.getLength() )
1214*cdf0e10cSrcweir             aLocale.Variant = OUString();
1215*cdf0e10cSrcweir         else if( aLocale.Country.getLength() )
1216*cdf0e10cSrcweir             aLocale.Country = OUString();
1217*cdf0e10cSrcweir         else if( ! aLocale.Language.equalsAscii( "en" ) )
1218*cdf0e10cSrcweir             aLocale.Language = OUString( RTL_CONSTASCII_USTRINGPARAM( "en" ) );
1219*cdf0e10cSrcweir         else
1220*cdf0e10cSrcweir             aLocale.Language = OUString();
1221*cdf0e10cSrcweir     }
1222*cdf0e10cSrcweir     return NULL;
1223*cdf0e10cSrcweir }
1224*cdf0e10cSrcweir 
1225