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