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

Generated by: LCOV version 1.10