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