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

Generated by: LCOV version 1.11