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

Generated by: LCOV version 1.10