LCOV - code coverage report
Current view: top level - unotools/source/config - fontcfg.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 309 417 74.1 %
Date: 2014-04-11 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      114298 : static const char* getKeyType( int nKeyType )
      54             : {
      55      114298 :     switch( nKeyType )
      56             :     {
      57           0 :     case DEFAULTFONT_CJK_DISPLAY: return "CJK_DISPLAY";
      58        3592 :     case DEFAULTFONT_CJK_HEADING: return "CJK_HEADING";
      59         414 :     case DEFAULTFONT_CJK_PRESENTATION: return "CJK_PRESENTATION";
      60         445 :     case DEFAULTFONT_CJK_SPREADSHEET: return "CJK_SPREADSHEET";
      61       31740 :     case DEFAULTFONT_CJK_TEXT: return "CJK_TEXT";
      62           0 :     case DEFAULTFONT_CTL_DISPLAY: return "CTL_DISPLAY";
      63        3592 :     case DEFAULTFONT_CTL_HEADING: return "CTL_HEADING";
      64         414 :     case DEFAULTFONT_CTL_PRESENTATION: return "CTL_PRESENTATION";
      65         446 :     case DEFAULTFONT_CTL_SPREADSHEET: return "CTL_SPREADSHEET";
      66       31740 :     case DEFAULTFONT_CTL_TEXT: return "CTL_TEXT";
      67         433 :     case DEFAULTFONT_FIXED: return "FIXED";
      68           0 :     case DEFAULTFONT_LATIN_DISPLAY: return "LATIN_DISPLAY";
      69           0 :     case DEFAULTFONT_LATIN_FIXED: return "LATIN_FIXED";
      70        3592 :     case DEFAULTFONT_LATIN_HEADING: return "LATIN_HEADING";
      71         414 :     case DEFAULTFONT_LATIN_PRESENTATION: return "LATIN_PRESENTATION";
      72        1450 :     case DEFAULTFONT_LATIN_SPREADSHEET: return "LATIN_SPREADSHEET";
      73       31715 :     case DEFAULTFONT_LATIN_TEXT: return "LATIN_TEXT";
      74           9 :     case DEFAULTFONT_SANS: return "SANS";
      75           0 :     case DEFAULTFONT_SANS_UNICODE: return "SANS_UNICODE";
      76         116 :     case DEFAULTFONT_SERIF: return "SERIF";
      77           0 :     case DEFAULTFONT_SYMBOL: return "SYMBOL";
      78           0 :     case DEFAULTFONT_UI_FIXED: return "UI_FIXED";
      79        4186 :     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      110482 : DefaultFontConfiguration& DefaultFontConfiguration::get()
      96             : {
      97      110482 :     return theDefaultFontConfiguration::get();
      98             : }
      99             : 
     100         155 : DefaultFontConfiguration::DefaultFontConfiguration()
     101             : {
     102             :     try
     103             :     {
     104             :         // get service provider
     105         155 :         Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
     106             :         // create configuration hierachical access name
     107             :         try
     108             :         {
     109         155 :             m_xConfigProvider = theDefaultProvider::get( xContext );
     110         155 :             Sequence< Any > aArgs(1);
     111         310 :             PropertyValue aVal;
     112         155 :             aVal.Name = "nodepath";
     113         155 :             aVal.Value <<= OUString( "/org.openoffice.VCL/DefaultFonts" );
     114         155 :             aArgs.getArray()[0] <<= aVal;
     115         310 :             m_xConfigAccess =
     116             :                 Reference< XNameAccess >(
     117         155 :                     m_xConfigProvider->createInstanceWithArguments( OUString( "com.sun.star.configuration.ConfigurationAccess" ),
     118         155 :                                                                     aArgs ),
     119         155 :                     UNO_QUERY );
     120         155 :             if( m_xConfigAccess.is() )
     121             :             {
     122         155 :                 Sequence< OUString > aLocales = m_xConfigAccess->getElementNames();
     123             :                 // fill config hash with empty interfaces
     124         155 :                 int nLocales = aLocales.getLength();
     125         155 :                 const OUString* pLocaleStrings = aLocales.getConstArray();
     126        5270 :                 for( int i = 0; i < nLocales; i++ )
     127             :                 {
     128             :                     // Feed through LanguageTag for casing.
     129        5115 :                     OUString aLoc( LanguageTag( pLocaleStrings[i], true).getBcp47( false));
     130        5115 :                     m_aConfig[ aLoc ] = LocaleAccess();
     131        5115 :                     m_aConfig[ aLoc ].aConfigLocaleString = pLocaleStrings[i];
     132        5270 :                 }
     133         155 :             }
     134             :         }
     135           0 :         catch (const Exception&)
     136             :         {
     137             :             // configuration is awry
     138           0 :             m_xConfigProvider.clear();
     139           0 :             m_xConfigAccess.clear();
     140         155 :         }
     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         155 : }
     152             : 
     153         310 : DefaultFontConfiguration::~DefaultFontConfiguration()
     154             : {
     155             :     // release all nodes
     156         155 :     m_aConfig.clear();
     157             :     // release top node
     158         155 :     m_xConfigAccess.clear();
     159             :     // release config provider
     160         155 :     m_xConfigProvider.clear();
     161         155 : }
     162             : 
     163      199752 : OUString DefaultFontConfiguration::tryLocale( const OUString& rBcp47, const OUString& rType ) const
     164             : {
     165      199752 :     OUString aRet;
     166             : 
     167      199752 :     boost::unordered_map< OUString, LocaleAccess, OUStringHash >::const_iterator it = m_aConfig.find( rBcp47 );
     168      199752 :     if( it != m_aConfig.end() )
     169             :     {
     170      118123 :         if( !it->second.xAccess.is() )
     171             :         {
     172             :             try
     173             :             {
     174         375 :                 Reference< XNameAccess > xNode;
     175         375 :                 if ( m_xConfigAccess->hasByName( it->second.aConfigLocaleString ) )
     176             :                 {
     177         375 :                     Any aAny = m_xConfigAccess->getByName( it->second.aConfigLocaleString );
     178         375 :                     if( aAny >>= xNode )
     179         375 :                         it->second.xAccess = xNode;
     180         375 :                 }
     181             :             }
     182           0 :             catch (const NoSuchElementException&)
     183             :             {
     184             :             }
     185           0 :             catch (const WrappedTargetException&)
     186             :             {
     187             :             }
     188             :         }
     189      118123 :         if( it->second.xAccess.is() )
     190             :         {
     191             :             try
     192             :             {
     193      118123 :                 if ( it->second.xAccess->hasByName( rType ) )
     194             :                 {
     195      110482 :                     Any aAny = it->second.xAccess->getByName( rType );
     196      110482 :                     aAny >>= aRet;
     197             :                 }
     198             :             }
     199           0 :             catch (const NoSuchElementException&)
     200             :             {
     201             :             }
     202           0 :             catch (const WrappedTargetException&)
     203             :             {
     204             :             }
     205             :         }
     206             :     }
     207             : 
     208      199752 :     return aRet;
     209             : }
     210             : 
     211      114298 : OUString DefaultFontConfiguration::getDefaultFont( const LanguageTag& rLanguageTag, int nType ) const
     212             : {
     213      114298 :     OUString aType = OUString::createFromAscii( getKeyType( nType ) );
     214             :     // Try the simple cases first without constructing fallbacks.
     215      114298 :     OUString aRet = tryLocale( rLanguageTag.getBcp47(), aType );
     216      114298 :     if (aRet.isEmpty())
     217             :     {
     218       81556 :         if (rLanguageTag.isIsoLocale())
     219             :         {
     220       81556 :             if (!rLanguageTag.getCountry().isEmpty())
     221             :             {
     222       81548 :                 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      114298 :     if( aRet.isEmpty() )
     236             :     {
     237        3906 :         aRet = tryLocale( "en", aType );
     238             :     }
     239      114298 :     return aRet;
     240             : }
     241             : 
     242        4186 : OUString DefaultFontConfiguration::getUserInterfaceFont( const LanguageTag& rLanguageTag ) const
     243             : {
     244        4186 :     LanguageTag aLanguageTag( rLanguageTag);
     245        4186 :     if( aLanguageTag.isSystemLocale() )
     246           0 :         aLanguageTag = SvtSysLocale().GetUILanguageTag();
     247             : 
     248        8372 :     OUString aUIFont = getDefaultFont( aLanguageTag, DEFAULTFONT_UI_SANS );
     249             : 
     250        4186 :     if( !aUIFont.isEmpty() )
     251        4186 :         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        4186 :     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       23437 : FontSubstConfiguration& FontSubstConfiguration::get()
     354             : {
     355       23437 :     return theFontSubstConfiguration::get();
     356             : }
     357             : 
     358             : /*
     359             :  *  FontSubstConfigItem::FontSubstConfigItem
     360             :  */
     361             : 
     362          53 : FontSubstConfiguration::FontSubstConfiguration() :
     363          53 :     maSubstHash( 300 )
     364             : {
     365             :     try
     366             :     {
     367             :         // get service provider
     368          53 :         Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
     369             :         // create configuration hierachical access name
     370          53 :         m_xConfigProvider = theDefaultProvider::get( xContext );
     371         106 :         Sequence< Any > aArgs(1);
     372         106 :         PropertyValue aVal;
     373          53 :         aVal.Name = "nodepath";
     374          53 :         aVal.Value <<= OUString( "/org.openoffice.VCL/FontSubstitutions" );
     375          53 :         aArgs.getArray()[0] <<= aVal;
     376         106 :         m_xConfigAccess =
     377             :             Reference< XNameAccess >(
     378          53 :                 m_xConfigProvider->createInstanceWithArguments( OUString( "com.sun.star.configuration.ConfigurationAccess" ),
     379          53 :                                                                 aArgs ),
     380          53 :                 UNO_QUERY );
     381          53 :         if( m_xConfigAccess.is() )
     382             :         {
     383          53 :             Sequence< OUString > aLocales = m_xConfigAccess->getElementNames();
     384             :             // fill config hash with empty interfaces
     385          53 :             int nLocales = aLocales.getLength();
     386          53 :             const OUString* pLocaleStrings = aLocales.getConstArray();
     387         106 :             for( int i = 0; i < nLocales; i++ )
     388             :             {
     389             :                 // Feed through LanguageTag for casing.
     390          53 :                 OUString aLoc( LanguageTag( pLocaleStrings[i], true).getBcp47( false));
     391          53 :                 m_aSubst[ aLoc ] = LocaleSubst();
     392          53 :                 m_aSubst[ aLoc ].aConfigLocaleString = pLocaleStrings[i];
     393         106 :             }
     394          53 :         }
     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          53 : }
     409             : 
     410             : /*
     411             :  *  FontSubstConfigItem::~FontSubstConfigItem
     412             :  */
     413             : 
     414         106 : FontSubstConfiguration::~FontSubstConfiguration()
     415             : {
     416             :     // release config access
     417          53 :     m_xConfigAccess.clear();
     418             :     // release config provider
     419          53 :     m_xConfigProvider.clear();
     420          53 : }
     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       13007 : static bool ImplKillLeading( OUString& rName, const char* const* ppStr )
     624             : {
     625      247133 :     for(; *ppStr; ++ppStr )
     626             :     {
     627      234126 :         const char*         pStr = *ppStr;
     628      234126 :         const sal_Unicode*  pNameStr = rName.getStr();
     629      486880 :         while ( (*pNameStr == (sal_Unicode)(unsigned char)*pStr) && *pStr )
     630             :         {
     631       18628 :             pNameStr++;
     632       18628 :             pStr++;
     633             :         }
     634      234126 :         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       13007 :     const sal_Unicode* pNameStr = rName.getStr();
     645       13007 :     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       13007 :     return false;
     653             : }
     654             : 
     655      572308 : static sal_Int32 ImplIsTrailing( const OUString& rName, const char* pStr )
     656             : {
     657      572308 :     sal_Int32 nStrLen = (sal_Int32)strlen( pStr );
     658      572308 :     if( nStrLen >= rName.getLength() )
     659       17295 :         return 0;
     660             : 
     661      555013 :     const sal_Unicode* pEndName = rName.getStr() + rName.getLength();
     662      555013 :     const sal_Unicode* pNameStr = pEndName - nStrLen;
     663      603365 :     do if( *(pNameStr++) != *(pStr++) )
     664      555013 :         return 0;
     665             :     while( *pStr );
     666             : 
     667           0 :     return nStrLen;
     668             : }
     669             : 
     670       13007 : static bool ImplKillTrailing( OUString& rName, const char* const* ppStr )
     671             : {
     672      559301 :     for(; *ppStr; ++ppStr )
     673             :     {
     674      546294 :         sal_Int32 nTrailLen = ImplIsTrailing( rName, *ppStr );
     675      546294 :         if( nTrailLen )
     676             :         {
     677           0 :             rName = rName.copy(0, rName.getLength() - nTrailLen );
     678           0 :             return true;
     679             :         }
     680             :     }
     681             : 
     682       13007 :     return false;
     683             : }
     684             : 
     685       13007 : static bool ImplKillTrailingWithExceptions( OUString& rName, const char* const* ppStr )
     686             : {
     687       39021 :     for(; *ppStr; ++ppStr )
     688             :     {
     689       26014 :         sal_Int32 nTrailLen = ImplIsTrailing( rName, *ppStr );
     690       26014 :         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       26014 :             while( *++ppStr );
     704             :         }
     705             :     }
     706             : 
     707       13007 :     return false;
     708             : }
     709             : 
     710     1066573 : static bool ImplFindAndErase( OUString& rName, const char* pStr )
     711             : {
     712     1066573 :     sal_Int32 nLen = (sal_Int32)strlen(pStr);
     713     1066573 :     sal_Int32 nPos = rName.indexOfAsciiL(pStr, nLen );
     714     1066573 :     if ( nPos < 0 )
     715     1058351 :         return false;
     716             : 
     717        8222 :     OUStringBuffer sBuff(rName);
     718        8222 :     sBuff.remove(nPos, nLen);
     719        8222 :     rName = sBuff.makeStringAndClear();
     720        8222 :     return true;
     721             : }
     722             : 
     723       13007 : void FontSubstConfiguration::getMapName( const OUString& rOrgName, OUString& rShortName,
     724             :                                          OUString& rFamilyName, FontWeight& rWeight,
     725             :                                          FontWidth& rWidth, sal_uLong& rType )
     726             : {
     727       13007 :     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       13007 :     ImplKillLeading( rShortName, aImplKillLeadingList );
     734             : 
     735             :     // Kill trailing vendor names and other unimportant data
     736       13007 :     ImplKillTrailing( rShortName, aImplKillTrailingList );
     737       13007 :     ImplKillTrailingWithExceptions( rShortName, aImplKillTrailingWithExceptionsList );
     738             : 
     739       13007 :     rFamilyName = rShortName;
     740             : 
     741             :     // Kill attributes from the name and update the data
     742             :     // Weight
     743       13007 :     const ImplFontAttrWeightSearchData* pWeightList = aImplWeightAttrSearchList;
     744      195103 :     while ( pWeightList->mpStr )
     745             :     {
     746      169090 :         if ( ImplFindAndErase( rFamilyName, pWeightList->mpStr ) )
     747             :         {
     748           1 :             if ( (rWeight == WEIGHT_DONTKNOW) || (rWeight == WEIGHT_NORMAL) )
     749           1 :                 rWeight = pWeightList->meWeight;
     750           1 :             break;
     751             :         }
     752      169089 :         pWeightList++;
     753             :     }
     754             : 
     755             :     // Width
     756       13007 :     const ImplFontAttrWidthSearchData* pWidthList = aImplWidthAttrSearchList;
     757      156084 :     while ( pWidthList->mpStr )
     758             :     {
     759      130070 :         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      130070 :         pWidthList++;
     766             :     }
     767             : 
     768             :     // Type
     769       13007 :     rType = 0;
     770       13007 :     const ImplFontAttrTypeSearchData* pTypeList = aImplTypeAttrSearchList;
     771      793427 :     while ( pTypeList->mpStr )
     772             :     {
     773      767413 :         if ( ImplFindAndErase( rFamilyName, pTypeList->mpStr ) )
     774        8221 :             rType |= pTypeList->mnType;
     775      767413 :         pTypeList++;
     776             :     }
     777             : 
     778             :     // Remove numbers
     779             :     // TODO: also remove localized and fullwidth digits
     780       13007 :     sal_Int32 i = 0;
     781       13007 :     OUStringBuffer sBuff(rFamilyName);
     782      166818 :     while ( i < sBuff.getLength() )
     783             :     {
     784      140804 :         sal_Unicode c = sBuff[ i ];
     785      140804 :         if ( (c >= 0x0030) && (c <= 0x0039) )
     786           4 :             sBuff.remove(i, 1);
     787             :         else
     788      140800 :             i++;
     789       13007 :     }
     790       13007 : }
     791             : 
     792             : struct StrictStringSort : public ::std::binary_function< const FontNameAttr&, const FontNameAttr&, bool >
     793             : {
     794      371230 :     bool operator()( const FontNameAttr& rLeft, const FontNameAttr& rRight )
     795      371230 :     { 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       75048 : 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       75048 :         Any aAny = xFont->getByName( rType );
     879       75048 :         if( aAny.getValueTypeClass() == TypeClass_STRING )
     880             :         {
     881       66144 :             const OUString* pLine = (const OUString*)aAny.getValue();
     882       66144 :             sal_Int32 nLength = pLine->getLength();
     883       66144 :             if( nLength )
     884             :             {
     885       30157 :                 const sal_Unicode* pStr = pLine->getStr();
     886       30157 :                 sal_Int32 nTokens = 0;
     887             :                 // count tokens
     888     3251179 :                 while( nLength-- )
     889             :                 {
     890     3190865 :                     if( *pStr++ == ';' )
     891      269558 :                         nTokens++;
     892             :                 }
     893       30157 :                 rSubstVector.clear();
     894             :                 // optimize performance, heap fragmentation
     895       30157 :                 rSubstVector.reserve( nTokens );
     896       30157 :                 sal_Int32 nIndex = 0;
     897      360029 :                 while( nIndex != -1 )
     898             :                 {
     899      299715 :                     OUString aSubst( pLine->getToken( 0, ';', nIndex ) );
     900      299715 :                     if( !aSubst.isEmpty() )
     901             :                     {
     902      298655 :                         UniqueSubstHash::iterator aEntry = maSubstHash.find( aSubst );
     903      298655 :                         if (aEntry != maSubstHash.end())
     904      282172 :                             aSubst = *aEntry;
     905             :                         else
     906       16483 :                             maSubstHash.insert( aSubst );
     907      298655 :                         rSubstVector.push_back( aSubst );
     908             :                     }
     909      299715 :                 }
     910             :             }
     911       75048 :         }
     912             :     }
     913           0 :     catch (const NoSuchElementException&)
     914             :     {
     915             :     }
     916           0 :     catch (const WrappedTargetException&)
     917             :     {
     918             :     }
     919       75048 : }
     920             : 
     921       18762 : FontWeight FontSubstConfiguration::getSubstWeight( const com::sun::star::uno::Reference< XNameAccess > xFont,
     922             :                                                    const OUString& rType ) const
     923             : {
     924       18762 :     int weight = -1;
     925             :     try
     926             :     {
     927       18762 :         Any aAny = xFont->getByName( rType );
     928       18762 :         if( aAny.getValueTypeClass() == TypeClass_STRING )
     929             :         {
     930       17331 :             const OUString* pLine = (const OUString*)aAny.getValue();
     931       17331 :             if( !pLine->isEmpty() )
     932             :             {
     933      239189 :                 for( weight=SAL_N_ELEMENTS(pWeightNames)-1; weight >= 0; weight-- )
     934      239189 :                     if( pLine->equalsIgnoreAsciiCaseAscii( pWeightNames[weight].pName ) )
     935       17331 :                         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       18762 :         }
     943             :     }
     944           0 :     catch (const NoSuchElementException&)
     945             :     {
     946             :     }
     947           0 :     catch (const WrappedTargetException&)
     948             :     {
     949             :     }
     950       18762 :     return (FontWeight)( weight >= 0 ? pWeightNames[weight].nEnum : WEIGHT_DONTKNOW );
     951             : }
     952             : 
     953       18762 : FontWidth FontSubstConfiguration::getSubstWidth( const com::sun::star::uno::Reference< XNameAccess > xFont,
     954             :                                                  const OUString& rType ) const
     955             : {
     956       18762 :     int width = -1;
     957             :     try
     958             :     {
     959       18762 :         Any aAny = xFont->getByName( rType );
     960       18762 :         if( aAny.getValueTypeClass() == TypeClass_STRING )
     961             :         {
     962       17331 :             const OUString* pLine = (const OUString*)aAny.getValue();
     963       17331 :             if( !pLine->isEmpty() )
     964             :             {
     965      170130 :                 for( width=SAL_N_ELEMENTS(pWidthNames)-1; width >= 0; width-- )
     966      170130 :                     if( pLine->equalsIgnoreAsciiCaseAscii( pWidthNames[width].pName ) )
     967       17331 :                         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       18762 :         }
     975             :     }
     976           0 :     catch (const NoSuchElementException&)
     977             :     {
     978             :     }
     979           0 :     catch (const WrappedTargetException&)
     980             :     {
     981             :     }
     982       18762 :     return (FontWidth)( width >= 0 ? pWidthNames[width].nEnum : WIDTH_DONTKNOW );
     983             : }
     984             : 
     985       18762 : unsigned long FontSubstConfiguration::getSubstType( const com::sun::star::uno::Reference< XNameAccess > xFont,
     986             :                                                     const OUString& rType ) const
     987             : {
     988       18762 :     unsigned long type = 0;
     989             :     try
     990             :     {
     991       18762 :         Any aAny = xFont->getByName( rType );
     992       18762 :         if( aAny.getValueTypeClass() == TypeClass_STRING )
     993             :         {
     994       18232 :             const OUString* pLine = (const OUString*)aAny.getValue();
     995       18232 :             if( !pLine->isEmpty() )
     996             :             {
     997       18232 :                 sal_Int32 nIndex = 0;
     998       81037 :                 while( nIndex != -1 )
     999             :                 {
    1000       44573 :                     OUString aToken( pLine->getToken( 0, ',', nIndex ) );
    1001      471011 :                     for( int k = 0; k < 32; k++ )
    1002      470587 :                         if( aToken.equalsIgnoreAsciiCaseAscii( pAttribNames[k] ) )
    1003             :                         {
    1004       44149 :                             type |= 1 << k;
    1005       44149 :                             break;
    1006             :                         }
    1007       44573 :                 }
    1008             :             }
    1009       18762 :         }
    1010             :     }
    1011           0 :     catch (const NoSuchElementException&)
    1012             :     {
    1013             :     }
    1014           0 :     catch (const WrappedTargetException&)
    1015             :     {
    1016             :     }
    1017             : 
    1018       18762 :     return type;
    1019             : }
    1020             : 
    1021          53 : void FontSubstConfiguration::readLocaleSubst( const OUString& rBcp47 ) const
    1022             : {
    1023          53 :     boost::unordered_map< OUString, LocaleSubst, OUStringHash >::const_iterator it = m_aSubst.find( rBcp47 );
    1024          53 :     if( it != m_aSubst.end() )
    1025             :     {
    1026          53 :         if( ! it->second.bConfigRead )
    1027             :         {
    1028          53 :             it->second.bConfigRead = true;
    1029          53 :             Reference< XNameAccess > xNode;
    1030             :             try
    1031             :             {
    1032          53 :                 Any aAny = m_xConfigAccess->getByName( it->second.aConfigLocaleString );
    1033          53 :                 aAny >>= xNode;
    1034             :             }
    1035           0 :             catch (const NoSuchElementException&)
    1036             :             {
    1037             :             }
    1038           0 :             catch (const WrappedTargetException&)
    1039             :             {
    1040             :             }
    1041          53 :             if( xNode.is() )
    1042             :             {
    1043          53 :                 Sequence< OUString > aFonts = xNode->getElementNames();
    1044          53 :                 int nFonts = aFonts.getLength();
    1045          53 :                 const OUString* pFontNames = aFonts.getConstArray();
    1046             :                 // improve performance, heap fragmentation
    1047          53 :                 it->second.aSubstAttributes.reserve( nFonts );
    1048             : 
    1049             :                 // strings for subst retrieval, construct only once
    1050         106 :                 OUString aSubstFontsStr     ( "SubstFonts" );
    1051         106 :                 OUString aSubstFontsMSStr   ( "SubstFontsMS" );
    1052         106 :                 OUString aSubstFontsPSStr   ( "SubstFontsPS" );
    1053         106 :                 OUString aSubstFontsHTMLStr ( "SubstFontsHTML" );
    1054         106 :                 OUString aSubstWeightStr    ( "FontWeight" );
    1055         106 :                 OUString aSubstWidthStr     ( "FontWidth" );
    1056         106 :                 OUString aSubstTypeStr      ( "FontType" );
    1057       18815 :                 for( int i = 0; i < nFonts; i++ )
    1058             :                 {
    1059       18762 :                     Reference< XNameAccess > xFont;
    1060             :                     try
    1061             :                     {
    1062       18762 :                         Any aAny = xNode->getByName( pFontNames[i] );
    1063       18762 :                         aAny >>= xFont;
    1064             :                     }
    1065           0 :                     catch (const NoSuchElementException&)
    1066             :                     {
    1067             :                     }
    1068           0 :                     catch (const WrappedTargetException&)
    1069             :                     {
    1070             :                     }
    1071       18762 :                     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       37524 :                     FontNameAttr aAttr;
    1081             :                     // read subst attributes from config
    1082       18762 :                     aAttr.Name = pFontNames[i];
    1083       18762 :                     fillSubstVector( xFont, aSubstFontsStr, aAttr.Substitutions );
    1084       18762 :                     fillSubstVector( xFont, aSubstFontsMSStr, aAttr.MSSubstitutions );
    1085       18762 :                     fillSubstVector( xFont, aSubstFontsPSStr, aAttr.PSSubstitutions );
    1086       18762 :                     fillSubstVector( xFont, aSubstFontsHTMLStr, aAttr.HTMLSubstitutions );
    1087       18762 :                     aAttr.Weight = getSubstWeight( xFont, aSubstWeightStr );
    1088       18762 :                     aAttr.Width = getSubstWidth( xFont, aSubstWidthStr );
    1089       18762 :                     aAttr.Type = getSubstType( xFont, aSubstTypeStr );
    1090             : 
    1091             :                     // finally insert this entry
    1092       18762 :                     it->second.aSubstAttributes.push_back( aAttr );
    1093       18762 :                 }
    1094         106 :                 std::sort( it->second.aSubstAttributes.begin(), it->second.aSubstAttributes.end(), StrictStringSort() );
    1095          53 :             }
    1096             :         }
    1097             :     }
    1098          53 : }
    1099             : 
    1100       23437 : const FontNameAttr* FontSubstConfiguration::getSubstInfo( const OUString& rFontName,
    1101             :         const LanguageTag& rLanguageTag ) const
    1102             : {
    1103       23437 :     if( rFontName.isEmpty() )
    1104          71 :         return NULL;
    1105             : 
    1106             :     // search if a  (language dep.) replacement table for the given font exists
    1107             :     // fallback is english
    1108       23366 :     OUString aSearchFont( rFontName.toAsciiLowerCase() );
    1109       46732 :     FontNameAttr aSearchAttr;
    1110       23366 :     aSearchAttr.Name = aSearchFont;
    1111             : 
    1112       46732 :     LanguageTag aLanguageTag( rLanguageTag);
    1113             : 
    1114       23366 :     if( aLanguageTag.isSystemLocale() )
    1115           0 :         aLanguageTag = SvtSysLocale().GetUILanguageTag();
    1116             : 
    1117       46732 :     ::std::vector< OUString > aFallbacks( aLanguageTag.getFallbackStrings( true));
    1118       23366 :     if (aLanguageTag.getLanguage() != "en")
    1119           0 :         aFallbacks.push_back("en");
    1120             : 
    1121       30616 :     for (::std::vector< OUString >::const_iterator fb( aFallbacks.begin()); fb != aFallbacks.end(); ++fb)
    1122             :     {
    1123       23366 :         boost::unordered_map< OUString, LocaleSubst, OUStringHash >::const_iterator lang = m_aSubst.find( *fb );
    1124       23366 :         if( lang != m_aSubst.end() )
    1125             :         {
    1126       23366 :             if( ! lang->second.bConfigRead )
    1127          53 :                 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       23366 :             std::vector< FontNameAttr >::const_iterator it = ::std::lower_bound( lang->second.aSubstAttributes.begin(), lang->second.aSubstAttributes.end(), aSearchAttr, StrictStringSort() );
    1131       23366 :             if( it != lang->second.aSubstAttributes.end())
    1132             :             {
    1133       23366 :                 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       23366 :                 if( rFoundAttr.Name.getLength() <= aSearchFont.getLength() )
    1137       23221 :                     if( aSearchFont.startsWith( rFoundAttr.Name))
    1138       16116 :                         return &rFoundAttr;
    1139             :             }
    1140             :         }
    1141             :     }
    1142       30616 :     return NULL;
    1143             : }
    1144             : 
    1145             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10