LCOV - code coverage report
Current view: top level - libreoffice/unotools/source/config - fontcfg.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 331 441 75.1 %
Date: 2012-12-27 Functions: 23 23 100.0 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.10