LCOV - code coverage report
Current view: top level - vcl/generic/fontmanager - fontmanager.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 686 1505 45.6 %
Date: 2012-08-25 Functions: 44 71 62.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 791 2607 30.3 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #include <unistd.h>
      31                 :            : #include <sys/stat.h>
      32                 :            : #include <dirent.h>
      33                 :            : #include <stdlib.h>
      34                 :            : #include <osl/thread.h>
      35                 :            : 
      36                 :            : #include "unotools/atom.hxx"
      37                 :            : 
      38                 :            : #include "fontcache.hxx"
      39                 :            : #include "fontsubset.hxx"
      40                 :            : #include "impfont.hxx"
      41                 :            : #include "svdata.hxx"
      42                 :            : #include "generic/geninst.h"
      43                 :            : #include "vcl/fontmanager.hxx"
      44                 :            : #include "vcl/strhelper.hxx"
      45                 :            : #include "vcl/ppdparser.hxx"
      46                 :            : 
      47                 :            : #include "tools/urlobj.hxx"
      48                 :            : #include "tools/stream.hxx"
      49                 :            : #include "tools/debug.hxx"
      50                 :            : 
      51                 :            : #include "osl/file.hxx"
      52                 :            : #include "osl/process.h"
      53                 :            : 
      54                 :            : #include "rtl/tencinfo.h"
      55                 :            : #include "rtl/ustrbuf.hxx"
      56                 :            : #include "rtl/strbuf.hxx"
      57                 :            : 
      58                 :            : #include <sal/macros.h>
      59                 :            : 
      60                 :            : #include "i18npool/mslangid.hxx"
      61                 :            : 
      62                 :            : 
      63                 :            : #include "parseAFM.hxx"
      64                 :            : #include "sft.hxx"
      65                 :            : 
      66                 :            : #if OSL_DEBUG_LEVEL > 1
      67                 :            : #include <sys/times.h>
      68                 :            : #include <stdio.h>
      69                 :            : #endif
      70                 :            : 
      71                 :            : #include "sal/alloca.h"
      72                 :            : 
      73                 :            : #include <set>
      74                 :            : #include <boost/unordered_set.hpp>
      75                 :            : #include <algorithm>
      76                 :            : 
      77                 :            : #include "adobeenc.tab" // get encoding table for AFM metrics
      78                 :            : 
      79                 :            : #ifdef CALLGRIND_COMPILE
      80                 :            : #include <valgrind/callgrind.h>
      81                 :            : #endif
      82                 :            : 
      83                 :            : #include <comphelper/processfactory.hxx>
      84                 :            : #include <comphelper/string.hxx>
      85                 :            : #include "com/sun/star/beans/XMaterialHolder.hpp"
      86                 :            : #include "com/sun/star/beans/NamedValue.hpp"
      87                 :            : 
      88                 :            : #define PRINTER_METRICDIR "fontmetric"
      89                 :            : 
      90                 :            : namespace {
      91                 :            : 
      92                 :            : namespace css = com::sun::star;
      93                 :            : 
      94                 :            : }
      95                 :            : 
      96                 :            : using namespace vcl;
      97                 :            : using namespace utl;
      98                 :            : using namespace psp;
      99                 :            : using namespace osl;
     100                 :            : using namespace com::sun::star::uno;
     101                 :            : using namespace com::sun::star::beans;
     102                 :            : using namespace com::sun::star::lang;
     103                 :            : 
     104                 :            : using ::comphelper::string::getToken;
     105                 :            : using ::rtl::OUString;
     106                 :            : using ::rtl::OString;
     107                 :            : using ::rtl::OStringHash;
     108                 :            : using ::rtl::OStringBuffer;
     109                 :            : using ::rtl::OUStringBuffer;
     110                 :            : using ::rtl::OUStringHash;
     111                 :            : using ::rtl::OStringToOUString;
     112                 :            : using ::rtl::OUStringToOString;
     113                 :            : 
     114                 :            : /*
     115                 :            :  *  static helpers
     116                 :            :  */
     117                 :            : 
     118                 :     130145 : inline sal_uInt16 getUInt16BE( const sal_uInt8*& pBuffer )
     119                 :            : {
     120                 :     130145 :     sal_uInt16 nRet = (sal_uInt16)pBuffer[1] |
     121                 :     130145 :         (((sal_uInt16)pBuffer[0]) << 8);
     122                 :     130145 :     pBuffer+=2;
     123                 :     130145 :     return nRet;
     124                 :            : }
     125                 :            : 
     126                 :          0 : inline sal_uInt32 getUInt32BE( const sal_uInt8*& pBuffer )
     127                 :            : {
     128                 :          0 :     sal_uInt32 nRet = (((sal_uInt32)pBuffer[0]) << 24) |
     129                 :          0 :                       (((sal_uInt32)pBuffer[1]) << 16) |
     130                 :          0 :                       (((sal_uInt32)pBuffer[2]) << 8)  |
     131                 :          0 :                       (((sal_uInt32)pBuffer[3]) );
     132                 :          0 :     pBuffer += 4;
     133                 :          0 :     return nRet;
     134                 :            : }
     135                 :            : 
     136                 :            : // -------------------------------------------------------------------------
     137                 :            : 
     138                 :       4214 : static FontWeight parseWeight( const rtl::OString& rWeight )
     139                 :            : {
     140                 :       4214 :     FontWeight eWeight = WEIGHT_DONTKNOW;
     141         [ +  + ]:       4214 :     if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("bold") ) != -1)
     142                 :            :     {
     143         [ -  + ]:       1532 :         if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("emi")) != -1) // semi, demi
     144                 :          0 :             eWeight = WEIGHT_SEMIBOLD;
     145         [ -  + ]:       1532 :         else if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("ultra")) != -1)
     146                 :          0 :             eWeight = WEIGHT_ULTRABOLD;
     147                 :            :         else
     148                 :       1532 :             eWeight = WEIGHT_BOLD;
     149                 :            :     }
     150         [ -  + ]:       2682 :     else if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("heavy")) != -1)
     151                 :          0 :         eWeight = WEIGHT_BOLD;
     152         [ +  + ]:       2682 :     else if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("light")) != -1)
     153                 :            :     {
     154         [ -  + ]:        124 :         if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("emi")) != -1) // semi, demi
     155                 :          0 :             eWeight = WEIGHT_SEMILIGHT;
     156         [ -  + ]:        124 :         else if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("ultra")) != -1)
     157                 :          0 :             eWeight = WEIGHT_ULTRALIGHT;
     158                 :            :         else
     159                 :        124 :             eWeight = WEIGHT_LIGHT;
     160                 :            :     }
     161         [ -  + ]:       2558 :     else if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("black")) != -1)
     162                 :          0 :         eWeight = WEIGHT_BLACK;
     163         [ +  + ]:       2558 :     else if (rWeight.equalsL(RTL_CONSTASCII_STRINGPARAM("demi")))
     164                 :        378 :         eWeight = WEIGHT_SEMIBOLD;
     165   [ +  +  -  + ]:       4106 :     else if (rWeight.equalsL(RTL_CONSTASCII_STRINGPARAM("book")) ||
                 [ +  + ]
     166                 :       1926 :              rWeight.equalsL(RTL_CONSTASCII_STRINGPARAM("semicondensed")))
     167                 :        254 :         eWeight = WEIGHT_LIGHT;
     168 [ +  + ][ +  + ]:       1926 :     else if (rWeight.equalsL(RTL_CONSTASCII_STRINGPARAM("medium")) || rWeight.equalsL(RTL_CONSTASCII_STRINGPARAM("roman")))
                 [ +  + ]
     169                 :       1001 :         eWeight = WEIGHT_MEDIUM;
     170                 :            :     else
     171                 :        925 :         eWeight = WEIGHT_NORMAL;
     172                 :       4214 :     return eWeight;
     173                 :            : }
     174                 :            : 
     175                 :            : /*
     176                 :            :  *  PrintFont implementations
     177                 :            :  */
     178                 :      83968 : PrintFontManager::PrintFont::PrintFont( fonttype::type eType ) :
     179                 :            :         m_eType( eType ),
     180                 :            :         m_nFamilyName( 0 ),
     181                 :            :         m_nPSName( 0 ),
     182                 :            :         m_eItalic( ITALIC_DONTKNOW ),
     183                 :            :         m_eWidth( WIDTH_DONTKNOW ),
     184                 :            :         m_eWeight( WEIGHT_DONTKNOW ),
     185                 :            :         m_ePitch( PITCH_DONTKNOW ),
     186                 :            :         m_aEncoding( RTL_TEXTENCODING_DONTKNOW ),
     187                 :            :         m_bFontEncodingOnly( false ),
     188                 :            :         m_pMetrics( NULL ),
     189                 :            :         m_nAscend( 0 ),
     190                 :            :         m_nDescend( 0 ),
     191                 :            :         m_nLeading( 0 ),
     192                 :            :         m_nXMin( 0 ),
     193                 :            :         m_nYMin( 0 ),
     194                 :            :         m_nXMax( 0 ),
     195                 :            :         m_nYMax( 0 ),
     196                 :            :         m_bHaveVerticalSubstitutedGlyphs( false ),
     197 [ +  - ][ +  - ]:      83968 :         m_bUserOverride( false )
     198                 :            : {
     199                 :      83968 : }
     200                 :            : 
     201                 :            : // -------------------------------------------------------------------------
     202                 :            : 
     203                 :      83968 : PrintFontManager::PrintFont::~PrintFont()
     204                 :            : {
     205         [ +  + ]:      83968 :     if( m_pMetrics )
     206 [ +  - ][ +  - ]:       4214 :         delete m_pMetrics;
     207         [ -  + ]:      83968 : }
     208                 :            : 
     209                 :            : // -------------------------------------------------------------------------
     210                 :            : 
     211                 :      16520 : PrintFontManager::Type1FontFile::~Type1FontFile()
     212                 :            : {
     213         [ -  + ]:      33040 : }
     214                 :            : 
     215                 :            : // -------------------------------------------------------------------------
     216                 :            : 
     217                 :      57652 : PrintFontManager::TrueTypeFontFile::TrueTypeFontFile()
     218                 :            : :   PrintFont( fonttype::TrueType )
     219                 :            : ,   m_nDirectory( 0 )
     220                 :            : ,   m_nCollectionEntry( 0 )
     221                 :      57652 : ,   m_nTypeFlags( TYPEFLAG_INVALID )
     222                 :      57652 : {}
     223                 :            : 
     224                 :            : // -------------------------------------------------------------------------
     225                 :            : 
     226                 :      57652 : PrintFontManager::TrueTypeFontFile::~TrueTypeFontFile()
     227                 :            : {
     228         [ -  + ]:     115304 : }
     229                 :            : 
     230                 :            : // -------------------------------------------------------------------------
     231                 :            : 
     232                 :       9796 : PrintFontManager::BuiltinFont::~BuiltinFont()
     233                 :            : {
     234         [ -  + ]:      19592 : }
     235                 :            : 
     236                 :            : // -------------------------------------------------------------------------
     237                 :            : 
     238                 :         17 : bool PrintFontManager::Type1FontFile::queryMetricPage( int /*nPage*/, MultiAtomProvider* pProvider )
     239                 :            : {
     240         [ +  - ]:         17 :     return readAfmMetrics( PrintFontManager::get().getAfmFile( this ), pProvider, false, false );
     241                 :            : }
     242                 :            : 
     243                 :            : // -------------------------------------------------------------------------
     244                 :            : 
     245                 :          0 : bool PrintFontManager::BuiltinFont::queryMetricPage( int /*nPage*/, MultiAtomProvider* pProvider )
     246                 :            : {
     247         [ #  # ]:          0 :     return readAfmMetrics( PrintFontManager::get().getAfmFile( this ), pProvider, false, false );
     248                 :            : }
     249                 :            : 
     250                 :            : // -------------------------------------------------------------------------
     251                 :            : 
     252                 :          0 : bool PrintFontManager::TrueTypeFontFile::queryMetricPage( int nPage, MultiAtomProvider* pProvider )
     253                 :            : {
     254                 :          0 :     bool bSuccess = false;
     255                 :            : 
     256 [ #  # ][ #  # ]:          0 :     rtl::OString aFile( PrintFontManager::get().getFontFile( this ) );
     257                 :            : 
     258                 :          0 :     TrueTypeFont* pTTFont = NULL;
     259                 :            : 
     260 [ #  # ][ #  # ]:          0 :     if( OpenTTFontFile( aFile.getStr(), m_nCollectionEntry, &pTTFont ) == SF_OK )
     261                 :            :     {
     262         [ #  # ]:          0 :         if( ! m_pMetrics )
     263                 :            :         {
     264 [ #  # ][ #  # ]:          0 :             m_pMetrics = new PrintFontMetrics;
     265                 :          0 :             memset (m_pMetrics->m_aPages, 0, sizeof(m_pMetrics->m_aPages));
     266                 :            :         }
     267                 :          0 :         m_pMetrics->m_aPages[ nPage/8 ] |= (1 << ( nPage & 7 ));
     268                 :            :         int i;
     269                 :            :         sal_uInt16 table[256], table_vert[256];
     270                 :            : 
     271         [ #  # ]:          0 :         for( i = 0; i < 256; i++ )
     272                 :          0 :             table[ i ] = 256*nPage + i;
     273                 :            : 
     274         [ #  # ]:          0 :         int nCharacters = nPage < 255 ? 256 : 254;
     275         [ #  # ]:          0 :         MapString( pTTFont, table, nCharacters, NULL, 0 );
     276         [ #  # ]:          0 :         TTSimpleGlyphMetrics* pMetrics = GetTTSimpleCharMetrics( pTTFont, nPage*256, nCharacters, 0 );
     277         [ #  # ]:          0 :         if( pMetrics )
     278                 :            :         {
     279         [ #  # ]:          0 :             for( i = 0; i < nCharacters; i++ )
     280                 :            :             {
     281         [ #  # ]:          0 :                 if( table[i] )
     282                 :            :                 {
     283         [ #  # ]:          0 :                     CharacterMetric& rChar = m_pMetrics->m_aMetrics[ nPage*256 + i ];
     284                 :          0 :                     rChar.width = pMetrics[ i ].adv;
     285                 :          0 :                     rChar.height = m_aGlobalMetricX.height;
     286                 :            :                 }
     287                 :            :             }
     288                 :            : 
     289                 :          0 :             free( pMetrics );
     290                 :            :         }
     291                 :            : 
     292         [ #  # ]:          0 :         for( i = 0; i < 256; i++ )
     293                 :          0 :             table_vert[ i ] = 256*nPage + i;
     294         [ #  # ]:          0 :         MapString( pTTFont, table_vert, nCharacters, NULL, 1 );
     295         [ #  # ]:          0 :         pMetrics = GetTTSimpleCharMetrics( pTTFont, nPage*256, nCharacters, 1 );
     296         [ #  # ]:          0 :         if( pMetrics )
     297                 :            :         {
     298         [ #  # ]:          0 :             for( i = 0; i < nCharacters; i++ )
     299                 :            :             {
     300         [ #  # ]:          0 :                 if( table_vert[i] )
     301                 :            :                 {
     302         [ #  # ]:          0 :                     CharacterMetric& rChar = m_pMetrics->m_aMetrics[ nPage*256 + i + ( 1 << 16 ) ];
     303                 :          0 :                     rChar.width = m_aGlobalMetricY.width;
     304                 :          0 :                     rChar.height = pMetrics[ i ].adv;
     305         [ #  # ]:          0 :                     if( table_vert[i] != table[i] )
     306         [ #  # ]:          0 :                         m_pMetrics->m_bVerticalSubstitutions[ nPage*256 + i ] = 1;
     307                 :            :                 }
     308                 :            :             }
     309                 :          0 :             free( pMetrics );
     310                 :            :         }
     311                 :            : 
     312         [ #  # ]:          0 :         if( ! m_pMetrics->m_bKernPairsQueried )
     313                 :            :         {
     314                 :          0 :             m_pMetrics->m_bKernPairsQueried = true;
     315                 :            :             // this is really a hack
     316                 :            :             // in future MapString/KernGlyphs should be used
     317                 :            :             // but vcl is not in a state where that could be used
     318                 :            :             // so currently we get kernpairs by accessing the raw data
     319                 :          0 :             struct _TrueTypeFont* pImplTTFont = (struct _TrueTypeFont*)pTTFont;
     320                 :            : 
     321                 :            :             //-----------------------------------------------------------------
     322                 :            :             // Kerning:  KT_MICROSOFT
     323                 :            :             //-----------------------------------------------------------------
     324 [ #  # ][ #  # ]:          0 :             if( pImplTTFont->nkern && pImplTTFont->kerntype == KT_MICROSOFT )
     325                 :            :             {
     326                 :            :                 // create a glyph -> character mapping
     327         [ #  # ]:          0 :                 ::boost::unordered_map< sal_uInt16, sal_Unicode > aGlyphMap;
     328                 :          0 :                 ::boost::unordered_map< sal_uInt16, sal_Unicode >::iterator left, right;
     329         [ #  # ]:          0 :                 for( i = 21; i < 0xfffd; i++ )
     330                 :            :                 {
     331         [ #  # ]:          0 :                     sal_uInt16 nGlyph = MapChar( pTTFont, (sal_Unicode)i, 0 ); // kerning for horz only
     332         [ #  # ]:          0 :                     if( nGlyph != 0 )
     333         [ #  # ]:          0 :                         aGlyphMap[ nGlyph ] = (sal_Unicode)i;
     334                 :            :                 }
     335                 :            : 
     336                 :            : 
     337                 :          0 :                 KernPair aPair;
     338         [ #  # ]:          0 :                 for( i = 0; i < (int)pImplTTFont->nkern; i++ )
     339                 :            :                 {
     340                 :          0 :                     const sal_uInt8* pTable = pImplTTFont->kerntables[i];
     341                 :            : 
     342                 :          0 :                     /*sal_uInt16 nVersion     =*/ getUInt16BE( pTable );
     343                 :          0 :                     /*sal_uInt16 nLength      =*/ getUInt16BE( pTable );
     344                 :          0 :                     sal_uInt16 nCoverage    = getUInt16BE( pTable );
     345                 :            : 
     346                 :          0 :                     aPair.kern_x    = 0;
     347                 :          0 :                     aPair.kern_y    = 0;
     348      [ #  #  # ]:          0 :                     switch( nCoverage >> 8 )
     349                 :            :                     {
     350                 :            :                         case 0:
     351                 :            :                         {
     352                 :          0 :                             sal_uInt16 nPairs = getUInt16BE( pTable );
     353                 :          0 :                             pTable += 6;
     354         [ #  # ]:          0 :                             for( int n = 0; n < nPairs; n++ )
     355                 :            :                             {
     356                 :          0 :                                 sal_uInt16 nLeftGlyph   = getUInt16BE( pTable );
     357                 :          0 :                                 sal_uInt16 nRightGlyph  = getUInt16BE( pTable );
     358                 :          0 :                                 sal_Int16 nKern         = (sal_Int16)getUInt16BE( pTable );
     359                 :            : 
     360         [ #  # ]:          0 :                                 left = aGlyphMap.find( nLeftGlyph );
     361         [ #  # ]:          0 :                                 right = aGlyphMap.find( nRightGlyph );
     362 [ #  # ][ #  # ]:          0 :                                 if( left != aGlyphMap.end() && right != aGlyphMap.end() )
         [ #  # ][ #  # ]
                 [ #  # ]
     363                 :            :                                 {
     364         [ #  # ]:          0 :                                     aPair.first     = left->second;
     365         [ #  # ]:          0 :                                     aPair.second    = right->second;
     366      [ #  #  # ]:          0 :                                     switch( nCoverage & 1 )
     367                 :            :                                     {
     368                 :            :                                         case 1:
     369                 :          0 :                                             aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
     370         [ #  # ]:          0 :                                             m_pMetrics->m_aXKernPairs.push_back( aPair );
     371                 :          0 :                                             break;
     372                 :            :                                         case 0:
     373                 :          0 :                                             aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
     374         [ #  # ]:          0 :                                             m_pMetrics->m_aYKernPairs.push_back( aPair );
     375                 :          0 :                                             break;
     376                 :            :                                     }
     377                 :            :                                 }
     378                 :            :                             }
     379                 :            :                         }
     380                 :          0 :                         break;
     381                 :            : 
     382                 :            :                         case 2:
     383                 :            :                         {
     384                 :          0 :                             const sal_uInt8* pSubTable = pTable;
     385                 :          0 :                             /*sal_uInt16 nRowWidth    =*/ getUInt16BE( pTable );
     386                 :          0 :                             sal_uInt16 nOfLeft      = getUInt16BE( pTable );
     387                 :          0 :                             sal_uInt16 nOfRight     = getUInt16BE( pTable );
     388                 :          0 :                             /*sal_uInt16 nOfArray     =*/ getUInt16BE( pTable );
     389                 :          0 :                             const sal_uInt8* pTmp = pSubTable + nOfLeft;
     390                 :          0 :                             sal_uInt16 nFirstLeft   = getUInt16BE( pTmp );
     391                 :          0 :                             sal_uInt16 nLastLeft    = getUInt16BE( pTmp ) + nFirstLeft - 1;
     392                 :          0 :                             pTmp = pSubTable + nOfRight;
     393                 :          0 :                             sal_uInt16 nFirstRight  = getUInt16BE( pTmp );
     394                 :          0 :                             sal_uInt16 nLastRight   = getUInt16BE( pTmp ) + nFirstRight -1;
     395                 :            : 
     396                 :            :                             // int nPairs = (int)(nLastLeft-nFirstLeft+1)*(int)(nLastRight-nFirstRight+1);
     397         [ #  # ]:          0 :                             for( aPair.first = nFirstLeft; aPair.first < nLastLeft; aPair.first++ )
     398                 :            :                             {
     399         [ #  # ]:          0 :                                 for( aPair.second = 0; aPair.second < nLastRight; aPair.second++ )
     400                 :            :                                 {
     401                 :          0 :                                     sal_Int16 nKern = (sal_Int16)getUInt16BE( pTmp );
     402      [ #  #  # ]:          0 :                                     switch( nCoverage & 1 )
     403                 :            :                                     {
     404                 :            :                                         case 1:
     405                 :          0 :                                             aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
     406         [ #  # ]:          0 :                                             m_pMetrics->m_aXKernPairs.push_back( aPair );
     407                 :          0 :                                             break;
     408                 :            :                                         case 0:
     409                 :          0 :                                             aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
     410         [ #  # ]:          0 :                                             m_pMetrics->m_aYKernPairs.push_back( aPair );
     411                 :          0 :                                             break;
     412                 :            :                                     }
     413                 :            :                                 }
     414                 :            :                             }
     415                 :            :                         }
     416                 :          0 :                         break;
     417                 :            :                     }
     418         [ #  # ]:          0 :                 }
     419                 :            :             }
     420                 :            : 
     421                 :            :             //-----------------------------------------------------------------
     422                 :            :             // Kerning:  KT_APPLE_NEW
     423                 :            :             //-----------------------------------------------------------------
     424 [ #  # ][ #  # ]:          0 :             if( pImplTTFont->nkern && pImplTTFont->kerntype == KT_APPLE_NEW )
     425                 :            :             {
     426                 :            :                 // create a glyph -> character mapping
     427         [ #  # ]:          0 :                 ::boost::unordered_map< sal_uInt16, sal_Unicode > aGlyphMap;
     428                 :          0 :                 ::boost::unordered_map< sal_uInt16, sal_Unicode >::iterator left, right;
     429         [ #  # ]:          0 :                 for( i = 21; i < 0xfffd; i++ )
     430                 :            :                 {
     431         [ #  # ]:          0 :                     sal_uInt16 nGlyph = MapChar( pTTFont, (sal_Unicode)i, 0 ); // kerning for horz only
     432         [ #  # ]:          0 :                     if( nGlyph != 0 )
     433         [ #  # ]:          0 :                         aGlyphMap[ nGlyph ] = (sal_Unicode)i;
     434                 :            :                 }
     435                 :            : 
     436                 :            :                 // Loop through each of the 'kern' subtables
     437                 :          0 :                 KernPair aPair;
     438         [ #  # ]:          0 :                 for( i = 0; (unsigned int)i < pImplTTFont->nkern; i++ )
     439                 :            :                 {
     440                 :          0 :                     const sal_uInt8* pTable = pImplTTFont->kerntables[i];
     441                 :            : 
     442                 :          0 :                     /*sal_uInt32 nLength      =*/ getUInt32BE( pTable );
     443                 :          0 :                     sal_uInt16 nCoverage    = getUInt16BE( pTable );
     444                 :          0 :                     /*sal_uInt16 nTupleIndex  =*/ getUInt16BE( pTable );
     445                 :            : 
     446                 :            :                     // Get kerning type
     447                 :            :                     // sal_Bool bKernVertical     = nCoverage & 0x8000;
     448                 :            :                     // sal_Bool bKernCrossStream  = nCoverage & 0x4000;
     449                 :            :                     // sal_Bool bKernVariation    = nCoverage & 0x2000;
     450                 :            : 
     451                 :            :                     // Kerning sub-table format, 0 through 3
     452                 :          0 :                     sal_uInt8 nSubTableFormat  = nCoverage & 0x00FF;
     453                 :            : 
     454                 :          0 :                     aPair.kern_x    = 0;
     455                 :          0 :                     aPair.kern_y    = 0;
     456      [ #  #  # ]:          0 :                     switch( nSubTableFormat )
     457                 :            :                     {
     458                 :            :                         case 0:
     459                 :            :                         {
     460                 :            :                             // Grab the # of kern pairs but skip over the:
     461                 :            :                             //   searchRange
     462                 :            :                             //   entrySelector
     463                 :            :                             //   rangeShift
     464                 :          0 :                             sal_uInt16 nPairs = getUInt16BE( pTable );
     465                 :          0 :                             pTable += 6;
     466                 :            : 
     467         [ #  # ]:          0 :                             for( int n = 0; n < nPairs; n++ )
     468                 :            :                             {
     469                 :          0 :                                 sal_uInt16 nLeftGlyph   = getUInt16BE( pTable );
     470                 :          0 :                                 sal_uInt16 nRightGlyph  = getUInt16BE( pTable );
     471                 :          0 :                                 sal_Int16  nKern         = (sal_Int16)getUInt16BE( pTable );
     472                 :            : 
     473         [ #  # ]:          0 :                                 left = aGlyphMap.find( nLeftGlyph );
     474         [ #  # ]:          0 :                                 right = aGlyphMap.find( nRightGlyph );
     475 [ #  # ][ #  # ]:          0 :                                 if( left != aGlyphMap.end() && right != aGlyphMap.end() )
         [ #  # ][ #  # ]
                 [ #  # ]
     476                 :            :                                 {
     477         [ #  # ]:          0 :                                     aPair.first     = left->second;
     478         [ #  # ]:          0 :                                     aPair.second    = right->second;
     479                 :            : 
     480                 :            :                                     // Only support horizontal kerning for now
     481                 :          0 :                                     aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
     482                 :          0 :                                     aPair.kern_y = 0;
     483         [ #  # ]:          0 :                                     m_pMetrics->m_aXKernPairs.push_back( aPair );
     484                 :            :                                 }
     485                 :            :                             }
     486                 :            :                         }
     487                 :          0 :                         break;
     488                 :            : 
     489                 :            :                         case 2:
     490                 :            :                         {
     491                 :          0 :                             const sal_uInt8* pSubTable = pTable;
     492                 :          0 :                             /*sal_uInt16 nRowWidth    =*/ getUInt16BE( pTable );
     493                 :          0 :                             sal_uInt16 nOfLeft      = getUInt16BE( pTable );
     494                 :          0 :                             sal_uInt16 nOfRight     = getUInt16BE( pTable );
     495                 :          0 :                             /*sal_uInt16 nOfArray     =*/ getUInt16BE( pTable );
     496                 :          0 :                             const sal_uInt8* pTmp = pSubTable + nOfLeft;
     497                 :          0 :                             sal_uInt16 nFirstLeft   = getUInt16BE( pTmp );
     498                 :          0 :                             sal_uInt16 nLastLeft    = getUInt16BE( pTmp ) + nFirstLeft - 1;
     499                 :          0 :                             pTmp = pSubTable + nOfRight;
     500                 :          0 :                             sal_uInt16 nFirstRight  = getUInt16BE( pTmp );
     501                 :          0 :                             sal_uInt16 nLastRight   = getUInt16BE( pTmp ) + nFirstRight -1;
     502                 :            : 
     503         [ #  # ]:          0 :                             for( aPair.first = nFirstLeft; aPair.first < nLastLeft; aPair.first++ )
     504                 :            :                             {
     505         [ #  # ]:          0 :                                 for( aPair.second = 0; aPair.second < nLastRight; aPair.second++ )
     506                 :            :                                 {
     507                 :          0 :                                     sal_Int16 nKern = (sal_Int16)getUInt16BE( pTmp );
     508      [ #  #  # ]:          0 :                                     switch( nCoverage & 1 )
     509                 :            :                                     {
     510                 :            :                                         case 1:
     511                 :          0 :                                             aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
     512         [ #  # ]:          0 :                                             m_pMetrics->m_aXKernPairs.push_back( aPair );
     513                 :          0 :                                             break;
     514                 :            :                                         case 0:
     515                 :          0 :                                             aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
     516         [ #  # ]:          0 :                                             m_pMetrics->m_aYKernPairs.push_back( aPair );
     517                 :          0 :                                             break;
     518                 :            :                                     }
     519                 :            :                                 }
     520                 :            :                             }
     521                 :            :                         }
     522                 :          0 :                         break;
     523                 :            : 
     524                 :            :                         default:
     525         [ #  # ]:          0 :                             fprintf( stderr, "Found unsupported Apple-style kern subtable type %d.\n", nSubTableFormat );
     526                 :          0 :                             break;
     527                 :            :                     }
     528         [ #  # ]:          0 :                 }
     529                 :            :             }
     530                 :            : 
     531                 :            : #if OSL_DEBUG_LEVEL > 1
     532                 :            :             fprintf( stderr, "found %" SAL_PRI_SIZET "u/%" SAL_PRI_SIZET "u kern pairs for %s\n",
     533                 :            :                      m_pMetrics->m_aXKernPairs.size(),
     534                 :            :                      m_pMetrics->m_aYKernPairs.size(),
     535                 :            :                      OUStringToOString( pProvider->getString( ATOM_FAMILYNAME, m_nFamilyName ), RTL_TEXTENCODING_MS_1252 ).getStr() );
     536                 :            : #else
     537                 :            :             (void) pProvider; /* avoid warnings */
     538                 :            : #endif
     539                 :            :         }
     540                 :            : 
     541         [ #  # ]:          0 :         CloseTTFont( pTTFont );
     542                 :          0 :         bSuccess = true;
     543                 :            :     }
     544                 :          0 :     return bSuccess;
     545                 :            : }
     546                 :            : 
     547                 :            : // -------------------------------------------------------------------------
     548                 :            : 
     549                 :            : /* #i73387# There seem to be fonts with a rather unwell chosen family name
     550                 :            : *  consider e.g. "Helvetica Narrow" which defines its family as "Helvetica"
     551                 :            : *  It can really only be distinguished by its PSName and FullName. Both of
     552                 :            : *  which are not user presentable in OOo. So replace it by something sensible.
     553                 :            : *
     554                 :            : *  If other fonts feature this behaviour, insert them to the map.
     555                 :            : */
     556                 :       4197 : static bool familyNameOverride( const OUString& i_rPSname, OUString& o_rFamilyName )
     557                 :            : {
     558 [ +  + ][ +  - ]:       4197 :     static boost::unordered_map< OUString, OUString, OUStringHash > aPSNameToFamily( 16 );
         [ +  - ][ #  # ]
     559         [ +  + ]:       4197 :     if( aPSNameToFamily.empty() ) // initialization
     560                 :            :     {
     561 [ +  - ][ +  - ]:        130 :         aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow" ) ) ] =
     562         [ +  - ]:        195 :                          OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
     563 [ +  - ][ +  - ]:        130 :         aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-Bold" ) ) ] =
     564         [ +  - ]:        195 :                          OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
     565 [ +  - ][ +  - ]:        130 :         aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-BoldOblique" ) ) ] =
     566         [ +  - ]:        195 :                          OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
     567 [ +  - ][ +  - ]:        130 :         aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-Oblique" ) ) ] =
     568         [ +  - ]:        195 :                          OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
     569                 :            :     }
     570                 :            :     boost::unordered_map<OUString,OUString,OUStringHash>::const_iterator it =
     571         [ +  - ]:       4197 :        aPSNameToFamily.find( i_rPSname );
     572         [ +  - ]:       4197 :     bool bReplaced = (it != aPSNameToFamily.end() );
     573         [ -  + ]:       4197 :     if( bReplaced )
     574         [ #  # ]:          0 :         o_rFamilyName = it->second;
     575                 :       4197 :     return bReplaced;
     576                 :            : };
     577                 :            : 
     578                 :       4214 : bool PrintFontManager::PrintFont::readAfmMetrics( const OString& rFileName, MultiAtomProvider* pProvider, bool bFillEncodingvector, bool bOnlyGlobalAttributes )
     579                 :            : {
     580         [ +  - ]:       4214 :     PrintFontManager& rManager( PrintFontManager::get() );
     581                 :            : 
     582                 :       4214 :     FontInfo* pInfo = NULL;
     583         [ +  - ]:       4214 :     parseFile( rFileName.getStr(), &pInfo, P_ALL );
     584 [ +  - ][ -  + ]:       4214 :     if( ! pInfo || ! pInfo->numOfChars )
     585                 :            :     {
     586         [ #  # ]:          0 :         if( pInfo )
     587         [ #  # ]:          0 :             freeFontInfo( pInfo );
     588                 :          0 :         return false;
     589                 :            :     }
     590                 :            : 
     591                 :       4214 :     m_aEncodingVector.clear();
     592                 :            :     // fill in global info
     593                 :            : 
     594                 :            :     // PSName
     595         [ +  - ]:       4214 :     OUString aPSName( OStringToOUString( pInfo->gfi->fontName, RTL_TEXTENCODING_ISO_8859_1 ) );
     596         [ +  - ]:       4214 :     m_nPSName = pProvider->getAtom( ATOM_PSNAME, aPSName, sal_True );
     597                 :            : 
     598                 :            :     // family name (if not already set)
     599                 :       4214 :     OUString aFamily;
     600         [ +  + ]:       4214 :     if( ! m_nFamilyName )
     601                 :            :     {
     602         [ +  - ]:       4197 :         aFamily = OStringToOUString( pInfo->gfi->familyName, RTL_TEXTENCODING_ISO_8859_1 );
     603         [ -  + ]:       4197 :         if( aFamily.isEmpty() )
     604                 :            :         {
     605         [ #  # ]:          0 :             aFamily = OStringToOUString( pInfo->gfi->fontName, RTL_TEXTENCODING_ISO_8859_1 );
     606                 :          0 :             sal_Int32 nIndex  = 0;
     607                 :          0 :             aFamily = aFamily.getToken( 0, '-', nIndex );
     608                 :            :         }
     609         [ +  - ]:       4197 :         familyNameOverride( aPSName, aFamily );
     610         [ +  - ]:       4197 :         m_nFamilyName = pProvider->getAtom( ATOM_FAMILYNAME, aFamily, sal_True );
     611                 :            :     }
     612                 :            :     else
     613         [ +  - ]:         17 :         aFamily = pProvider->getString( ATOM_FAMILYNAME, m_nFamilyName );
     614                 :            : 
     615                 :            :     // style name: if fullname begins with family name
     616                 :            :     // interpret the rest of fullname as style
     617 [ +  + ][ +  - ]:       4214 :     if( m_aStyleName.isEmpty() && pInfo->gfi->fullName && *pInfo->gfi->fullName )
         [ +  - ][ +  + ]
     618                 :            :     {
     619         [ +  - ]:       4197 :         OUString aFullName( OStringToOUString( pInfo->gfi->fullName, RTL_TEXTENCODING_ISO_8859_1 ) );
     620         [ +  - ]:       4197 :         if( aFullName.indexOf( aFamily ) == 0 )
     621 [ +  - ][ +  - ]:       4197 :             m_aStyleName = WhitespaceToSpace( aFullName.copy( aFamily.getLength() ) );
         [ +  - ][ +  - ]
                 [ +  - ]
     622                 :            :     }
     623                 :            : 
     624                 :            :     // italic
     625         [ -  + ]:       4214 :     if( pInfo->gfi->italicAngle > 0 )
     626                 :          0 :         m_eItalic = ITALIC_OBLIQUE;
     627         [ +  + ]:       4214 :     else if( pInfo->gfi->italicAngle < 0 )
     628                 :       2037 :         m_eItalic = ITALIC_NORMAL;
     629                 :            :     else
     630                 :       2177 :         m_eItalic = ITALIC_NONE;
     631                 :            : 
     632                 :            :     // weight
     633                 :       4214 :     rtl::OString aWeight( pInfo->gfi->weight );
     634         [ +  - ]:       4214 :     m_eWeight = parseWeight( aWeight.toAsciiLowerCase() );
     635                 :            : 
     636                 :            :     // pitch
     637         [ +  + ]:       4214 :     m_ePitch = pInfo->gfi->isFixedPitch ? PITCH_FIXED : PITCH_VARIABLE;
     638                 :            : 
     639                 :            :     // encoding - only set if unknown
     640                 :       4214 :     int nAdobeEncoding = 0;
     641         [ +  - ]:       4214 :     if( pInfo->gfi->encodingScheme )
     642                 :            :     {
     643         [ +  + ]:       4214 :         if( !strcmp( pInfo->gfi->encodingScheme, "AdobeStandardEncoding" ) )
     644                 :       3951 :             nAdobeEncoding = 1;
     645         [ -  + ]:        263 :         else if( !strcmp( pInfo->gfi->encodingScheme, "ISO10646-1" ) )
     646                 :            :         {
     647                 :          0 :             nAdobeEncoding = 1;
     648                 :          0 :             m_aEncoding = RTL_TEXTENCODING_UNICODE;
     649                 :            :         }
     650         [ -  + ]:        263 :         else if( !strcmp( pInfo->gfi->encodingScheme, "Symbol") )
     651                 :          0 :             nAdobeEncoding = 2;
     652         [ +  - ]:        263 :         else if( !strcmp( pInfo->gfi->encodingScheme, "FontSpecific") )
     653                 :        263 :             nAdobeEncoding = 3;
     654                 :            : 
     655         [ +  + ]:       4214 :         if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW )
     656                 :            :             m_aEncoding = nAdobeEncoding == 1 ?
     657         [ +  + ]:       4197 :                 RTL_TEXTENCODING_ADOBE_STANDARD : RTL_TEXTENCODING_SYMBOL;
     658                 :            :     }
     659         [ #  # ]:          0 :     else if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW )
     660                 :          0 :         m_aEncoding = RTL_TEXTENCODING_ADOBE_STANDARD;
     661                 :            : 
     662                 :            :     // try to parse the font name and decide whether it might be a
     663                 :            :     // japanese font. Who invented this PITA ?
     664                 :       4214 :     OUString aPSNameLastToken( aPSName.copy( aPSName.lastIndexOf( '-' )+1 ) );
     665         [ -  + ]:       8428 :     if( ! aPSNameLastToken.compareToAscii( "H" )    ||
           [ +  -  -  + ]
     666                 :       4214 :         ! aPSNameLastToken.compareToAscii( "V" )  )
     667                 :            :     {
     668                 :            :         static const char* pEncs[] =
     669                 :            :             {
     670                 :            :                 "EUC",
     671                 :            :                 "RKSJ",
     672                 :            :                 "SJ"
     673                 :            :             };
     674                 :            :         static const rtl_TextEncoding aEncs[] =
     675                 :            :             {
     676                 :            :                 RTL_TEXTENCODING_EUC_JP,
     677                 :            :                 RTL_TEXTENCODING_SHIFT_JIS,
     678                 :            :                 RTL_TEXTENCODING_JIS_X_0208
     679                 :            :             };
     680                 :            : 
     681 [ #  # ][ #  # ]:          0 :         for( unsigned int enc = 0; enc < SAL_N_ELEMENTS( aEncs ) && m_aEncoding == RTL_TEXTENCODING_DONTKNOW; enc++ )
                 [ #  # ]
     682                 :            :         {
     683                 :          0 :             sal_Int32 nIndex = 0, nOffset = 1;
     684         [ #  # ]:          0 :             do
     685                 :            :             {
     686                 :          0 :                 OUString aToken( aPSName.getToken( nOffset, '-', nIndex ) );
     687         [ #  # ]:          0 :                 if( nIndex == -1 )
     688                 :            :                     break;
     689                 :          0 :                 nOffset = 0;
     690         [ #  # ]:          0 :                 if( ! aToken.compareToAscii( pEncs[enc] ) )
     691                 :            :                 {
     692                 :          0 :                     m_aEncoding = aEncs[ enc ];
     693                 :          0 :                     m_bFontEncodingOnly = true;
     694         [ #  # ]:          0 :                 }
     695                 :            :             } while( nIndex != -1 );
     696                 :            :         }
     697                 :            : 
     698                 :            :         // default is jis
     699         [ #  # ]:          0 :         if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW )
     700                 :          0 :             m_aEncoding = RTL_TEXTENCODING_JIS_X_0208;
     701                 :            : #if OSL_DEBUG_LEVEL > 1
     702                 :            :         fprintf( stderr, "Encoding %d for %s\n", m_aEncoding, pInfo->gfi->fontName );
     703                 :            : #endif
     704                 :            :     }
     705                 :            : 
     706                 :            :     // hack for GB encoded builtin fonts posing as FontSpecific
     707 [ +  + ][ +  + ]:       4214 :     if( m_eType == fonttype::Builtin && ( nAdobeEncoding == 3 || nAdobeEncoding == 0 ) )
                 [ -  + ]
     708                 :            :     {
     709                 :        124 :         int nLen = aFamily.getLength();
     710 [ #  # ][ -  + ]:        248 :         if( nLen > 2 &&
           [ +  -  -  +  
                   #  # ]
     711                 :        124 :             aFamily.getStr()[ nLen-2 ] == 'G' &&
     712                 :          0 :             aFamily.getStr()[ nLen-1 ] == 'B' &&
     713                 :            :             pInfo->numOfChars > 255 )
     714                 :            :         {
     715                 :          0 :             m_aEncoding = RTL_TEXTENCODING_GBK;
     716                 :          0 :             m_bFontEncodingOnly = true;
     717                 :            : #if OSL_DEBUG_LEVEL > 1
     718                 :            :             fprintf( stderr, "found builtin font %s with GBK encoding\n", pInfo->gfi->fontName );
     719                 :            : #endif
     720                 :            :         }
     721                 :            :     }
     722                 :            : 
     723                 :            :     // #i37313# check if Fontspecific is not rather some character encoding
     724 [ +  + ][ +  - ]:       4214 :     if( nAdobeEncoding == 3 && m_aEncoding == RTL_TEXTENCODING_SYMBOL )
     725                 :            :     {
     726                 :        263 :         bool bYFound = false;
     727                 :        263 :         bool bQFound = false;
     728                 :        263 :         CharMetricInfo* pChar = pInfo->cmi;
     729 [ +  + ][ -  + ]:      51861 :         for( int j = 0; j < pInfo->numOfChars && ! (bYFound && bQFound); j++ )
         [ #  # ][ +  + ]
     730                 :            :         {
     731         [ +  - ]:      51598 :             if( pChar[j].name )
     732                 :            :             {
     733 [ -  + ][ #  # ]:      51598 :                 if( pChar[j].name[0] == 'Y' && pChar[j].name[1] == 0 )
     734                 :          0 :                     bYFound = true;
     735 [ -  + ][ #  # ]:      51598 :                 else if( pChar[j].name[0] == 'Q' && pChar[j].name[1] == 0 )
     736                 :      51598 :                     bQFound = true;
     737                 :            :             }
     738                 :            :         }
     739 [ -  + ][ #  # ]:        263 :         if( bQFound && bYFound )
     740                 :            :         {
     741                 :            :             #if OSL_DEBUG_LEVEL > 1
     742                 :            :             fprintf( stderr, "setting FontSpecific font %s (file %s) to unicode\n",
     743                 :            :                      pInfo->gfi->fontName,
     744                 :            :                      rFileName.getStr()
     745                 :            :                      );
     746                 :            :             #endif
     747                 :          0 :             nAdobeEncoding = 4;
     748                 :          0 :             m_aEncoding = RTL_TEXTENCODING_UNICODE;
     749                 :          0 :             bFillEncodingvector = false; // will be filled anyway, don't do the work twice
     750                 :            :         }
     751                 :            :     }
     752                 :            : 
     753                 :            :     // ascend
     754                 :       4214 :     m_nAscend = pInfo->gfi->fontBBox.ury;
     755                 :            : 
     756                 :            :     // descend
     757                 :            :     // descends have opposite sign of our definition
     758                 :       4214 :     m_nDescend = -pInfo->gfi->fontBBox.lly;
     759                 :            : 
     760                 :            :     // fallback to ascender, descender
     761                 :            :     // interesting: the BBox seems to describe Ascender and Descender better
     762                 :            :     // as we understand it
     763         [ -  + ]:       4214 :     if( m_nAscend == 0 )
     764                 :          0 :         m_nAscend = pInfo->gfi->ascender;
     765         [ -  + ]:       4214 :     if( m_nDescend == 0)
     766                 :          0 :         m_nDescend = -pInfo->gfi->descender;
     767                 :            : 
     768                 :       4214 :     m_nLeading = m_nAscend + m_nDescend - 1000;
     769                 :            : 
     770         [ -  + ]:       4214 :     if( m_pMetrics )
     771 [ #  # ][ #  # ]:          0 :         delete m_pMetrics;
     772 [ +  - ][ +  - ]:       4214 :     m_pMetrics = new PrintFontMetrics;
     773                 :            :     // mark all pages as queried (or clear if only global font info queiried)
     774         [ +  + ]:       4214 :     memset( m_pMetrics->m_aPages, bOnlyGlobalAttributes ? 0 : 0xff, sizeof( m_pMetrics->m_aPages ) );
     775                 :            : 
     776                 :            :     m_aGlobalMetricX.width = m_aGlobalMetricY.width =
     777         [ -  + ]:       4214 :         pInfo->gfi->charwidth ? pInfo->gfi->charwidth : pInfo->gfi->fontBBox.urx;
     778                 :            :     m_aGlobalMetricX.height = m_aGlobalMetricY.height =
     779         [ +  + ]:       4214 :         pInfo->gfi->capHeight ? pInfo->gfi->capHeight : pInfo->gfi->fontBBox.ury;
     780                 :            : 
     781                 :       4214 :     m_nXMin = pInfo->gfi->fontBBox.llx;
     782                 :       4214 :     m_nYMin = pInfo->gfi->fontBBox.lly;
     783                 :       4214 :     m_nXMax = pInfo->gfi->fontBBox.urx;
     784                 :       4214 :     m_nYMax = pInfo->gfi->fontBBox.ury;
     785                 :            : 
     786 [ +  - ][ +  + ]:       4214 :     if( bFillEncodingvector || !bOnlyGlobalAttributes )
     787                 :            :     {
     788                 :            :         // fill in character metrics
     789                 :            : 
     790                 :            :         // first transform the character codes to unicode
     791                 :            :         // note: this only works with single byte encodings
     792                 :         17 :         sal_Unicode* pUnicodes = (sal_Unicode*)alloca( pInfo->numOfChars * sizeof(sal_Unicode));
     793                 :         17 :         CharMetricInfo* pChar = pInfo->cmi;
     794                 :            :         int i;
     795                 :            : 
     796         [ +  + ]:       6176 :         for( i = 0; i < pInfo->numOfChars; i++, pChar++ )
     797                 :            :         {
     798         [ -  + ]:       6159 :             if( nAdobeEncoding == 4 )
     799                 :            :             {
     800         [ #  # ]:          0 :                 if( pChar->name )
     801                 :            :                 {
     802                 :          0 :                     pUnicodes[i] = 0;
     803         [ #  # ]:          0 :                     std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name );
     804 [ #  # ][ #  # ]:          0 :                     for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it )
         [ #  # ][ #  # ]
                 [ #  # ]
     805                 :            :                     {
     806 [ #  # ][ #  # ]:          0 :                         if( *it != 0 )
     807                 :            :                         {
     808 [ #  # ][ #  # ]:          0 :                             m_aEncodingVector[ *it ] = pChar->code;
     809         [ #  # ]:          0 :                             if( pChar->code == -1 )
     810 [ #  # ][ #  # ]:          0 :                                 m_aNonEncoded[ *it ] = pChar->name;
     811         [ #  # ]:          0 :                             if( ! pUnicodes[i] ) // map the first
     812         [ #  # ]:          0 :                                 pUnicodes[i] = *it;
     813                 :            :                         }
     814                 :          0 :                     }
     815                 :            :                 }
     816                 :            :             }
     817         [ +  + ]:       6159 :             else if( pChar->code != -1 )
     818                 :            :             {
     819 [ +  + ][ +  - ]:       2890 :                 if( nAdobeEncoding == 3 && m_aEncoding == RTL_TEXTENCODING_SYMBOL )
     820                 :            :                 {
     821                 :       1698 :                     pUnicodes[i] = pChar->code + 0xf000;
     822         [ -  + ]:       1698 :                     if( bFillEncodingvector )
     823         [ #  # ]:          0 :                         m_aEncodingVector[ pUnicodes[i] ] = pChar->code;
     824                 :       1698 :                     continue;
     825                 :            :                 }
     826                 :            : 
     827         [ -  + ]:       1192 :                 if( m_aEncoding == RTL_TEXTENCODING_UNICODE )
     828                 :            :                 {
     829                 :          0 :                     pUnicodes[i] = (sal_Unicode)pChar->code;
     830                 :          0 :                     continue;
     831                 :            :                 }
     832                 :            : 
     833                 :       1192 :                 rtl::OStringBuffer aTranslate;
     834         [ -  + ]:       1192 :                 if( pChar->code & 0xff000000 )
     835         [ #  # ]:          0 :                     aTranslate.append((char)(pChar->code >> 24));
     836         [ -  + ]:       1192 :                 if( pChar->code & 0xffff0000 )
     837         [ #  # ]:          0 :                     aTranslate.append((char)((pChar->code & 0x00ff0000) >> 16));
     838         [ -  + ]:       1192 :                 if( pChar->code & 0xffffff00 )
     839         [ #  # ]:          0 :                     aTranslate.append((char)((pChar->code & 0x0000ff00) >> 8 ));
     840         [ +  - ]:       1192 :                 aTranslate.append((char)(pChar->code & 0xff));
     841         [ +  - ]:       1192 :                 rtl::OUString aUni(rtl::OStringToOUString(aTranslate.makeStringAndClear(), m_aEncoding));
     842                 :       2890 :                 pUnicodes[i] = aUni.toChar();
     843                 :            :             }
     844                 :            :             else
     845                 :       3269 :                 pUnicodes[i] = 0;
     846                 :            :         }
     847                 :            : 
     848                 :            :         // now fill in the character metrics
     849                 :            :         // parseAFM.cxx effectively only supports direction 0 (horizontal)
     850                 :         17 :         pChar = pInfo->cmi;
     851                 :         17 :         CharacterMetric aMetric;
     852         [ +  + ]:       6176 :         for( i = 0; i < pInfo->numOfChars; i++, pChar++ )
     853                 :            :         {
     854 [ +  + ][ -  + ]:       6159 :             if( pChar->code == -1 && ! pChar->name )
     855                 :          0 :                 continue;
     856                 :            : 
     857 [ -  + ][ #  # ]:       6159 :             if( bFillEncodingvector && pChar->name )
     858                 :            :             {
     859         [ #  # ]:          0 :                 std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name );
     860 [ #  # ][ #  # ]:          0 :                 for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it )
         [ #  # ][ #  # ]
                 [ #  # ]
     861                 :            :                 {
     862 [ #  # ][ #  # ]:          0 :                     if( *it != 0 )
     863                 :            :                     {
     864 [ #  # ][ #  # ]:          0 :                         m_aEncodingVector[ *it ] = pChar->code;
     865         [ #  # ]:          0 :                         if( pChar->code == -1 )
     866 [ #  # ][ #  # ]:          0 :                             m_aNonEncoded[ *it ] = pChar->name;
     867                 :            :                     }
     868                 :          0 :                 }
     869                 :            :             }
     870                 :            : 
     871         [ +  - ]:       6159 :             aMetric.width   = pChar->wx ? pChar->wx : pChar->charBBox.urx;
     872         [ -  + ]:       6159 :             aMetric.height  = pChar->wy ? pChar->wy : pChar->charBBox.ury - pChar->charBBox.lly;
     873 [ -  + ][ #  # ]:       6159 :             if( aMetric.width == 0 && aMetric.height == 0 )
     874                 :            :                 // guess something for e.g. space
     875                 :          0 :                 aMetric.width = m_aGlobalMetricX.width/4;
     876                 :            : 
     877 [ +  - ][ +  + ]:       6159 :             if( ( nAdobeEncoding == 0 ) ||
                 [ -  + ]
     878                 :            :                 ( ( nAdobeEncoding == 3 ) && ( m_aEncoding != RTL_TEXTENCODING_SYMBOL ) ) )
     879                 :            :             {
     880         [ #  # ]:          0 :                 if( pChar->code != -1 )
     881                 :            :                 {
     882         [ #  # ]:          0 :                     m_pMetrics->m_aMetrics[ pUnicodes[i] ] = aMetric;
     883         [ #  # ]:          0 :                     if( bFillEncodingvector )
     884         [ #  # ]:          0 :                         m_aEncodingVector[ pUnicodes[i] ] = pChar->code;
     885                 :            :                 }
     886         [ #  # ]:          0 :                 else if( pChar->name )
     887                 :            :                 {
     888         [ #  # ]:          0 :                     std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name );
     889 [ #  # ][ #  # ]:          0 :                     for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it )
         [ #  # ][ #  # ]
                 [ #  # ]
     890                 :            :                     {
     891 [ #  # ][ #  # ]:          0 :                         if( *it != 0 )
     892 [ #  # ][ #  # ]:          0 :                             m_pMetrics->m_aMetrics[ *it ] = aMetric;
     893                 :          0 :                     }
     894                 :          0 :                 }
     895                 :            :             }
     896 [ +  + ][ +  - ]:       6159 :             else if( nAdobeEncoding == 1 || nAdobeEncoding == 2 || nAdobeEncoding == 4)
                 [ -  + ]
     897                 :            :             {
     898         [ +  - ]:       4410 :                 if( pChar->name )
     899                 :            :                 {
     900         [ +  - ]:       4410 :                     std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name );
     901 [ +  - ][ +  - ]:       8908 :                     for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it )
         [ +  - ][ +  + ]
                 [ +  - ]
     902                 :            :                     {
     903 [ +  - ][ +  - ]:       4498 :                         if( *it != 0 )
     904 [ +  - ][ +  - ]:       4498 :                             m_pMetrics->m_aMetrics[ *it ] = aMetric;
     905                 :       4410 :                     }
     906                 :            :                 }
     907         [ #  # ]:          0 :                 else if( pChar->code != -1 )
     908                 :            :                 {
     909                 :            :                     ::std::pair< ::boost::unordered_multimap< sal_uInt8, sal_Unicode >::const_iterator,
     910                 :            :                           ::boost::unordered_multimap< sal_uInt8, sal_Unicode >::const_iterator >
     911         [ #  # ]:          0 :                           aCodes = rManager.getUnicodeFromAdobeCode( pChar->code );
     912         [ #  # ]:          0 :                     while( aCodes.first != aCodes.second )
     913                 :            :                     {
     914 [ #  # ][ #  # ]:          0 :                         if( (*aCodes.first).second != 0 )
     915                 :            :                         {
     916 [ #  # ][ #  # ]:          0 :                             m_pMetrics->m_aMetrics[ (*aCodes.first).second ] = aMetric;
     917         [ #  # ]:          0 :                             if( bFillEncodingvector )
     918 [ #  # ][ #  # ]:          0 :                                 m_aEncodingVector[ (*aCodes.first).second ] = pChar->code;
     919                 :            :                         }
     920                 :          0 :                         ++aCodes.first;
     921                 :            :                     }
     922                 :       4410 :                 }
     923                 :            :             }
     924         [ +  - ]:       1749 :             else if( nAdobeEncoding == 3 )
     925                 :            :             {
     926         [ +  + ]:       1749 :                 if( pChar->code != -1 )
     927                 :            :                 {
     928                 :       1698 :                     sal_Unicode code = 0xf000 + pChar->code;
     929         [ +  - ]:       1698 :                     m_pMetrics->m_aMetrics[ code ] = aMetric;
     930                 :            :                     // maybe should try to find the name in the convtabs ?
     931         [ -  + ]:       1698 :                     if( bFillEncodingvector )
     932         [ #  # ]:       1698 :                         m_aEncodingVector[ code ] = pChar->code;
     933                 :            :                 }
     934                 :            :             }
     935                 :            :         }
     936                 :            : 
     937                 :         17 :         m_pMetrics->m_aXKernPairs.clear();
     938                 :         17 :         m_pMetrics->m_aYKernPairs.clear();
     939                 :            : 
     940                 :            :         // now fill in the kern pairs
     941                 :            :         // parseAFM.cxx effectively only supports direction 0 (horizontal)
     942                 :         17 :         PairKernData* pKern = pInfo->pkd;
     943                 :         17 :         KernPair aPair;
     944         [ +  + ]:       7867 :         for( i = 0; i < pInfo->numOfPairs; i++, pKern++ )
     945                 :            :         {
     946                 :            :             // #i37703# broken kern table
     947 [ +  - ][ -  + ]:       7850 :             if( ! pKern->name1 || ! pKern->name2 )
     948                 :          0 :                 continue;
     949                 :            : 
     950                 :       7850 :             aPair.first = 0;
     951                 :       7850 :             aPair.second = 0;
     952                 :            :             // currently we have to find the adobe character names
     953                 :            :             // in the already parsed character metrics to find
     954                 :            :             // the corresponding UCS2 code which is a bit dangerous
     955                 :            :             // since the character names are not required
     956                 :            :             // in the metric descriptions
     957                 :       7850 :             pChar = pInfo->cmi;
     958 [ +  + ][ +  + ]:    2245187 :             for( int j = 0;
         [ +  + ][ +  + ]
     959                 :            :                  j < pInfo->numOfChars && ( aPair.first == 0 || aPair.second == 0 );
     960                 :            :                  j++, pChar++ )
     961                 :            :             {
     962         [ +  + ]:    2237337 :                 if( pChar->code != -1 )
     963                 :            :                 {
     964 [ +  - ][ +  + ]:     853838 :                     if( ! strcmp( pKern->name1, pChar->name ? pChar->name : "" ) )
     965                 :       6380 :                         aPair.first = pUnicodes[ j ];
     966 [ +  - ][ +  + ]:     853838 :                     if( ! strcmp( pKern->name2, pChar->name ? pChar->name : "" ) )
     967                 :       5881 :                         aPair.second = pUnicodes[ j ];
     968                 :            :                 }
     969                 :            :             }
     970 [ +  + ][ +  + ]:       7850 :             if( aPair.first && aPair.second )
     971                 :            :             {
     972                 :       4411 :                 aPair.kern_x = pKern->xamt;
     973                 :       4411 :                 aPair.kern_y = pKern->yamt;
     974         [ +  - ]:       4411 :                 m_pMetrics->m_aXKernPairs.push_back( aPair );
     975                 :            :             }
     976                 :            :         }
     977                 :         17 :         m_pMetrics->m_bKernPairsQueried = true;
     978                 :            :     }
     979                 :            : 
     980         [ +  - ]:       4214 :     freeFontInfo( pInfo );
     981                 :       4214 :     return true;
     982                 :            : }
     983                 :            : 
     984                 :            : /*
     985                 :            :  *  one instance only
     986                 :            :  */
     987                 :      41908 : PrintFontManager& PrintFontManager::get()
     988                 :            : {
     989                 :            :     static PrintFontManager* pManager = NULL;
     990         [ +  + ]:      41908 :     if( ! pManager )
     991                 :            :     {
     992 [ +  - ][ +  - ]:        236 :         static PrintFontManager theManager;
         [ +  - ][ #  # ]
     993                 :        236 :         pManager = &theManager;
     994                 :        236 :         pManager->initialize();
     995                 :            :     }
     996                 :      41908 :     return *pManager;
     997                 :            : }
     998                 :            : 
     999                 :            : // -------------------------------------------------------------------------
    1000                 :            : 
    1001                 :            : /*
    1002                 :            :  *  the PrintFontManager
    1003                 :            :  */
    1004                 :            : 
    1005                 :        236 : PrintFontManager::PrintFontManager()
    1006                 :            :     : m_nNextFontID( 1 )
    1007                 :          0 :     , m_pAtoms( new MultiAtomProvider() )
    1008                 :            :     , m_nNextDirAtom( 1 )
    1009 [ +  - ][ +  - ]:        236 :     , m_pFontCache( NULL )
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1010                 :            : {
    1011         [ +  + ]:     248272 :     for( unsigned int i = 0; i < SAL_N_ELEMENTS( aAdobeCodes ); i++ )
    1012                 :            :     {
    1013 [ +  - ][ +  - ]:     248036 :         m_aUnicodeToAdobename.insert( ::boost::unordered_multimap< sal_Unicode, ::rtl::OString >::value_type( aAdobeCodes[i].aUnicode, aAdobeCodes[i].pAdobename ) );
    1014 [ +  - ][ +  - ]:     248036 :         m_aAdobenameToUnicode.insert( ::boost::unordered_multimap< ::rtl::OString, sal_Unicode, ::rtl::OStringHash >::value_type( aAdobeCodes[i].pAdobename, aAdobeCodes[i].aUnicode ) );
    1015         [ +  + ]:     248036 :         if( aAdobeCodes[i].aAdobeStandardCode )
    1016                 :            :         {
    1017 [ +  - ][ +  - ]:      35636 :             m_aUnicodeToAdobecode.insert( ::boost::unordered_multimap< sal_Unicode, sal_uInt8 >::value_type( aAdobeCodes[i].aUnicode, aAdobeCodes[i].aAdobeStandardCode ) );
    1018 [ +  - ][ +  - ]:      35636 :             m_aAdobecodeToUnicode.insert( ::boost::unordered_multimap< sal_uInt8, sal_Unicode >::value_type( aAdobeCodes[i].aAdobeStandardCode, aAdobeCodes[i].aUnicode ) );
    1019                 :            :         }
    1020                 :            :     }
    1021                 :        236 : }
    1022                 :            : 
    1023                 :            : // -------------------------------------------------------------------------
    1024                 :            : 
    1025 [ +  - ][ +  - ]:        236 : PrintFontManager::~PrintFontManager()
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1026                 :            : {
    1027         [ +  - ]:        236 :     deinitFontconfig();
    1028 [ +  - ][ +  - ]:      40096 :     for( ::boost::unordered_map< fontID, PrintFont* >::const_iterator it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
                 [ +  + ]
    1029 [ +  - ][ +  - ]:      39860 :         delete (*it).second;
                 [ +  - ]
    1030 [ +  - ][ +  - ]:        236 :     delete m_pAtoms;
    1031         [ +  - ]:        236 :     if( m_pFontCache )
    1032 [ +  - ][ +  - ]:        236 :         delete m_pFontCache;
    1033                 :        236 : }
    1034                 :            : 
    1035                 :            : // -------------------------------------------------------------------------
    1036                 :            : 
    1037                 :      19271 : OString PrintFontManager::getDirectory( int nAtom ) const
    1038                 :            : {
    1039         [ +  - ]:      19271 :     ::boost::unordered_map< int, OString >::const_iterator it( m_aAtomToDir.find( nAtom ) );
    1040 [ +  - ][ +  - ]:      19271 :     return it != m_aAtomToDir.end() ? it->second : OString();
                 [ +  - ]
    1041                 :            : }
    1042                 :            : 
    1043                 :            : // -------------------------------------------------------------------------
    1044                 :            : 
    1045                 :      51096 : int PrintFontManager::getDirectoryAtom( const OString& rDirectory, bool bCreate )
    1046                 :            : {
    1047                 :      51096 :     int nAtom = 0;
    1048                 :            :     ::boost::unordered_map< OString, int, OStringHash >::const_iterator it
    1049         [ +  - ]:      51096 :           ( m_aDirToAtom.find( rDirectory ) );
    1050 [ +  + ][ +  - ]:      51096 :     if( it != m_aDirToAtom.end() )
    1051         [ +  - ]:      43418 :         nAtom = it->second;
    1052         [ +  + ]:       7678 :     else if( bCreate )
    1053                 :            :     {
    1054                 :       7551 :         nAtom = m_nNextDirAtom++;
    1055         [ +  - ]:       7551 :         m_aDirToAtom[ rDirectory ] = nAtom;
    1056         [ +  - ]:       7551 :         m_aAtomToDir[ nAtom ] = rDirectory;
    1057                 :            :     }
    1058                 :      51096 :     return nAtom;
    1059                 :            : }
    1060                 :            : 
    1061                 :            : // -------------------------------------------------------------------------
    1062                 :            : 
    1063                 :          0 : std::vector<fontID> PrintFontManager::addFontFile( const ::rtl::OString& rFileName )
    1064                 :            : {
    1065         [ #  # ]:          0 :     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
    1066 [ #  # ][ #  # ]:          0 :     INetURLObject aPath( OStringToOUString( rFileName, aEncoding ), INET_PROT_FILE, INetURLObject::ENCODE_ALL );
    1067 [ #  # ][ #  # ]:          0 :     OString aName( OUStringToOString( aPath.GetName(), aEncoding ) );
    1068 [ #  # ][ #  # ]:          0 :     OString aDir( OUStringToOString( aPath.GetPath(), aEncoding ) );
    1069                 :            : 
    1070         [ #  # ]:          0 :     int nDirID = getDirectoryAtom( aDir, true );
    1071         [ #  # ]:          0 :     std::vector<fontID> aFontIds = findFontFileIDs( nDirID, aName );
    1072         [ #  # ]:          0 :     if( aFontIds.empty() )
    1073                 :            :     {
    1074         [ #  # ]:          0 :         ::std::list< PrintFont* > aNewFonts;
    1075 [ #  # ][ #  # ]:          0 :         if( analyzeFontFile( nDirID, aName, aNewFonts ) )
    1076                 :            :         {
    1077   [ #  #  #  # ]:          0 :             for( ::std::list< PrintFont* >::iterator it = aNewFonts.begin();
                 [ #  # ]
    1078                 :          0 :                  it != aNewFonts.end(); ++it )
    1079                 :            :             {
    1080                 :          0 :                 fontID nFontId = m_nNextFontID++;
    1081 [ #  # ][ #  # ]:          0 :                 m_aFonts[nFontId] = *it;
    1082 [ #  # ][ #  # ]:          0 :                 m_aFontFileToFontID[ aName ].insert( nFontId );
    1083 [ #  # ][ #  # ]:          0 :                 m_pFontCache->updateFontCacheEntry( *it, true );
    1084         [ #  # ]:          0 :                 aFontIds.push_back(nFontId);
    1085                 :            :             }
    1086                 :          0 :         }
    1087                 :            :     }
    1088         [ #  # ]:          0 :     return aFontIds;
    1089                 :            : }
    1090                 :            : 
    1091                 :            : enum fontFormat
    1092                 :            : {
    1093                 :            :     UNKNOWN, TRUETYPE, CFF, TYPE1, AFM
    1094                 :            : };
    1095                 :            : 
    1096                 :      13113 : bool PrintFontManager::analyzeFontFile( int nDirID, const OString& rFontFile, ::std::list< PrintFontManager::PrintFont* >& rNewFonts, const char *pFormat ) const
    1097                 :            : {
    1098                 :      13113 :     rNewFonts.clear();
    1099                 :            : 
    1100         [ +  - ]:      13113 :     OString aDir( getDirectory( nDirID ) );
    1101                 :            : 
    1102                 :      13113 :     OString aFullPath( aDir );
    1103                 :      13113 :     aFullPath += "/";
    1104                 :      13113 :     aFullPath += rFontFile;
    1105                 :            : 
    1106                 :            :     // #i1872# reject unreadable files
    1107         [ -  + ]:      13113 :     if( access( aFullPath.getStr(), R_OK ) )
    1108                 :          0 :         return false;
    1109                 :            : 
    1110                 :      13113 :     fontFormat eFormat = UNKNOWN;
    1111         [ +  + ]:      13113 :     if (pFormat)
    1112                 :            :     {
    1113         [ +  + ]:      11191 :         if (!strcmp(pFormat, "TrueType"))
    1114                 :       7582 :             eFormat = TRUETYPE;
    1115         [ +  + ]:       3609 :         else if (!strcmp(pFormat, "CFF"))
    1116                 :        390 :             eFormat = CFF;
    1117         [ +  - ]:       3219 :         else if (!strcmp(pFormat, "Type 1"))
    1118                 :       3219 :             eFormat = TYPE1;
    1119                 :            :     }
    1120         [ +  + ]:      13113 :     if (eFormat == UNKNOWN)
    1121                 :            :     {
    1122                 :       1922 :         rtl::OString aExt( rFontFile.copy( rFontFile.lastIndexOf( '.' )+1 ) );
    1123 [ -  + ][ -  + ]:       1922 :         if( aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("pfb")) || aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("pfa")) )
                 [ +  - ]
    1124                 :          0 :             eFormat = TYPE1;
    1125         [ +  - ]:       1922 :         else if( aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("afm")))
    1126                 :       1922 :             eFormat = AFM;
    1127   [ #  #  #  #  :          0 :         else if( aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("ttf"))
           #  # ][ #  # ]
    1128                 :          0 :              ||  aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("ttc"))
    1129                 :          0 :              ||  aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("tte")) ) // #i33947# for Gaiji support
    1130                 :          0 :             eFormat = TRUETYPE;
    1131         [ #  # ]:          0 :         else if( aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("otf")) ) // check for TTF- and PS-OpenType too
    1132                 :       1922 :             eFormat = CFF;
    1133                 :            :     }
    1134                 :            : 
    1135         [ +  + ]:      13113 :     if (eFormat == TYPE1)
    1136                 :            :     {
    1137                 :            :         // check for corresponding afm metric
    1138                 :            :         // first look for an adjacent file
    1139                 :            :         static const char* pSuffix[] = { ".afm", ".AFM" };
    1140                 :            : 
    1141         [ +  + ]:       7382 :         for( unsigned int i = 0; i < SAL_N_ELEMENTS(pSuffix); i++ )
    1142                 :            :         {
    1143                 :            :             rtl::OString aName = rtl::OStringBuffer(
    1144                 :       4163 :                 rFontFile.copy(0, rFontFile.getLength() - 4)).
    1145 [ +  - ][ +  - ]:       4163 :                 append(pSuffix[i]).makeStringAndClear();
    1146                 :            : 
    1147         [ +  - ]:       4163 :             rtl::OStringBuffer aFilePath(aDir);
    1148 [ +  - ][ +  - ]:       4163 :             aFilePath.append('/').append(aName);
    1149                 :            : 
    1150                 :       4163 :             rtl::OString aAfmFile;
    1151         [ +  + ]:       4163 :             if( access( aFilePath.makeStringAndClear().getStr(), R_OK ) )
    1152                 :            :             {
    1153                 :            :                 // try in subdirectory afm instead
    1154 [ +  - ][ +  - ]:       1888 :                 aFilePath.append(aDir).append(RTL_CONSTASCII_STRINGPARAM("/afm/")).append(aName);
                 [ +  - ]
    1155                 :            : 
    1156         [ -  + ]:       1888 :                 if (!access(aFilePath.getStr(), R_OK))
    1157                 :          0 :                     aAfmFile = rtl::OString(RTL_CONSTASCII_STRINGPARAM("afm/")) + aName;
    1158                 :            :             }
    1159                 :            :             else
    1160                 :       2275 :                 aAfmFile = aName;
    1161                 :            : 
    1162         [ +  + ]:       4163 :             if( !aAfmFile.isEmpty() )
    1163                 :            :             {
    1164 [ +  - ][ +  - ]:       2275 :                 Type1FontFile* pFont = new Type1FontFile();
    1165                 :       2275 :                 pFont->m_nDirectory     = nDirID;
    1166                 :            : 
    1167                 :       2275 :                 pFont->m_aFontFile      = rFontFile;
    1168                 :       2275 :                 pFont->m_aMetricFile    = aAfmFile;
    1169                 :            : 
    1170 [ +  - ][ -  + ]:       2275 :                 if( ! pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true ) )
                 [ +  - ]
    1171                 :            :                 {
    1172 [ #  # ][ #  # ]:          0 :                     delete pFont;
    1173                 :          0 :                     pFont = NULL;
    1174                 :            :                 }
    1175         [ +  - ]:       2275 :                 if( pFont )
    1176         [ +  - ]:       4163 :                     rNewFonts.push_back( pFont );
    1177                 :            :                 break;
    1178                 :            :             }
    1179 [ +  + ][ +  + ]:       4163 :         }
                 [ +  + ]
    1180                 :            :     }
    1181         [ +  + ]:       9894 :     else if (eFormat == AFM)
    1182                 :            :     {
    1183         [ +  - ]:       1922 :         rtl::OStringBuffer aFilePath(aDir);
    1184 [ +  - ][ +  - ]:       1922 :         aFilePath.append('/').append(rFontFile);
    1185 [ +  - ][ +  - ]:       1922 :         BuiltinFont* pFont = new BuiltinFont();
    1186                 :       1922 :         pFont->m_nDirectory     = nDirID;
    1187                 :       1922 :         pFont->m_aMetricFile    = rFontFile;
    1188   [ +  -  +  - ]:       3844 :         if( pFont->readAfmMetrics( aFilePath.makeStringAndClear(), m_pAtoms,
    1189                 :       3844 :             false, true ) )
    1190                 :            :         {
    1191         [ +  - ]:       1922 :             rNewFonts.push_back( pFont );
    1192                 :            :         }
    1193                 :            :         else
    1194 [ #  # ][ #  # ]:       1922 :             delete pFont;
    1195                 :            :     }
    1196 [ +  + ][ +  - ]:       7972 :     else if (eFormat == TRUETYPE || eFormat == CFF)
    1197                 :            :     {
    1198                 :            :         // get number of ttc entries
    1199         [ +  - ]:       7972 :         int nLength = CountTTCFonts( aFullPath.getStr() );
    1200         [ +  + ]:       7972 :         if( nLength )
    1201                 :            :         {
    1202                 :            : #if OSL_DEBUG_LEVEL > 1
    1203                 :            :             fprintf( stderr, "ttc: %s contains %d fonts\n", aFullPath.getStr(), nLength );
    1204                 :            : #endif
    1205         [ +  + ]:        585 :             for( int i = 0; i < nLength; i++ )
    1206                 :            :             {
    1207 [ +  - ][ +  - ]:        455 :                 TrueTypeFontFile* pFont     = new TrueTypeFontFile();
    1208                 :        455 :                 pFont->m_nDirectory         = nDirID;
    1209                 :        455 :                 pFont->m_aFontFile          = rFontFile;
    1210                 :        455 :                 pFont->m_nCollectionEntry   = i;
    1211 [ -  + ][ +  - ]:        455 :                 if( ! analyzeTrueTypeFile( pFont ) )
    1212                 :            :                 {
    1213 [ #  # ][ #  # ]:          0 :                     delete pFont;
    1214                 :          0 :                     pFont = NULL;
    1215                 :            :                 }
    1216                 :            :                 else
    1217         [ +  - ]:        455 :                     rNewFonts.push_back( pFont );
    1218                 :            :             }
    1219                 :            :         }
    1220                 :            :         else
    1221                 :            :         {
    1222 [ +  - ][ +  - ]:       7842 :             TrueTypeFontFile* pFont     = new TrueTypeFontFile();
    1223                 :       7842 :             pFont->m_nDirectory         = nDirID;
    1224                 :       7842 :             pFont->m_aFontFile          = rFontFile;
    1225                 :       7842 :             pFont->m_nCollectionEntry   = 0;
    1226                 :            : 
    1227                 :            :             // need to read the font anyway to get aliases inside the font file
    1228 [ -  + ][ +  - ]:       7842 :             if( ! analyzeTrueTypeFile( pFont ) )
    1229                 :            :             {
    1230 [ #  # ][ #  # ]:          0 :                 delete pFont;
    1231                 :          0 :                 pFont = NULL;
    1232                 :            :             }
    1233                 :            :             else
    1234         [ +  - ]:       7842 :                 rNewFonts.push_back( pFont );
    1235                 :            :         }
    1236                 :            :     }
    1237                 :      13113 :     return ! rNewFonts.empty();
    1238                 :            : }
    1239                 :            : 
    1240                 :            : // -------------------------------------------------------------------------
    1241                 :            : 
    1242                 :       1922 : fontID PrintFontManager::findFontBuiltinID( int nPSNameAtom ) const
    1243                 :            : {
    1244                 :       1922 :     fontID nID = 0;
    1245                 :       1922 :     ::boost::unordered_map< fontID, PrintFont* >::const_iterator it;
    1246 [ +  - ][ +  + ]:     347882 :     for( it = m_aFonts.begin(); nID == 0 && it != m_aFonts.end(); ++it )
         [ +  - ][ +  + ]
                 [ +  - ]
    1247                 :            :     {
    1248 [ +  - ][ +  + ]:     374790 :         if( it->second->m_eType == fonttype::Builtin &&
         [ -  + ][ -  + ]
    1249         [ +  - ]:      28830 :             it->second->m_nPSName == nPSNameAtom )
    1250         [ #  # ]:          0 :             nID = it->first;
    1251                 :            :     }
    1252                 :       1922 :     return nID;
    1253                 :            : }
    1254                 :            : 
    1255                 :            : // -------------------------------------------------------------------------
    1256                 :            : 
    1257                 :       8749 : fontID PrintFontManager::findFontFileID( int nDirID, const OString& rFontFile, int nFaceIndex ) const
    1258                 :            : {
    1259                 :       8749 :     fontID nID = 0;
    1260                 :            : 
    1261         [ +  - ]:       8749 :     ::boost::unordered_map< OString, ::std::set< fontID >, OStringHash >::const_iterator set_it = m_aFontFileToFontID.find( rFontFile );
    1262 [ +  - ][ -  + ]:       8749 :     if( set_it == m_aFontFileToFontID.end() )
    1263                 :          0 :         return nID;
    1264                 :            : 
    1265 [ +  - ][ +  - ]:      18340 :     for( ::std::set< fontID >::const_iterator font_it = set_it->second.begin(); font_it != set_it->second.end() && ! nID; ++font_it )
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
                 [ +  - ]
           [ +  +  #  # ]
    1266                 :            :     {
    1267 [ +  - ][ +  - ]:       9591 :         ::boost::unordered_map< fontID, PrintFont* >::const_iterator it = m_aFonts.find( *font_it );
    1268         [ -  + ]:       9591 :         if( it == m_aFonts.end() )
    1269                 :          0 :             continue;
    1270         [ +  - ]:       9591 :         switch( it->second->m_eType )
           [ +  +  -  - ]
    1271                 :            :         {
    1272                 :            :             case fonttype::Type1:
    1273                 :            :             {
    1274         [ +  - ]:        176 :                 Type1FontFile* const pFont = static_cast< Type1FontFile* const >((*it).second);
    1275   [ +  -  +  - ]:        352 :                 if( pFont->m_nDirectory == nDirID &&
                 [ +  - ]
    1276                 :        176 :                     pFont->m_aFontFile == rFontFile )
    1277         [ +  - ]:        176 :                     nID = it->first;
    1278                 :            :             }
    1279                 :        176 :             break;
    1280                 :            :             case fonttype::TrueType:
    1281                 :            :             {
    1282         [ +  - ]:       9415 :                 TrueTypeFontFile* const pFont = static_cast< TrueTypeFontFile* const >((*it).second);
    1283   [ +  -  +  - ]:      18830 :                 if( pFont->m_nDirectory == nDirID &&
         [ +  + ][ +  + ]
    1284                 :       9415 :                     pFont->m_aFontFile == rFontFile && pFont->m_nCollectionEntry == nFaceIndex )
    1285         [ +  - ]:       8573 :                         nID = it->first;
    1286                 :            :             }
    1287                 :       9415 :             break;
    1288                 :            :             case fonttype::Builtin:
    1289         [ #  # ]:          0 :                 if( static_cast<const BuiltinFont*>((*it).second)->m_nDirectory == nDirID &&
           [ #  #  #  # ]
                 [ #  # ]
    1290         [ #  # ]:          0 :                     static_cast<const BuiltinFont*>((*it).second)->m_aMetricFile == rFontFile )
    1291         [ #  # ]:          0 :                     nID = it->first;
    1292                 :          0 :                 break;
    1293                 :            :             default:
    1294                 :       9591 :                 break;
    1295                 :            :         }
    1296                 :            :     }
    1297                 :            : 
    1298                 :       8749 :     return nID;
    1299                 :            : }
    1300                 :            : 
    1301                 :          0 : std::vector<fontID> PrintFontManager::findFontFileIDs( int nDirID, const OString& rFontFile ) const
    1302                 :            : {
    1303         [ #  # ]:          0 :     std::vector<fontID> aIds;
    1304                 :            : 
    1305         [ #  # ]:          0 :     ::boost::unordered_map< OString, ::std::set< fontID >, OStringHash >::const_iterator set_it = m_aFontFileToFontID.find( rFontFile );
    1306 [ #  # ][ #  # ]:          0 :     if( set_it == m_aFontFileToFontID.end() )
    1307                 :            :         return aIds;
    1308                 :            : 
    1309 [ #  # ][ #  # ]:          0 :     for( ::std::set< fontID >::const_iterator font_it = set_it->second.begin(); font_it != set_it->second.end(); ++font_it )
         [ #  # ][ #  # ]
                 [ #  # ]
    1310                 :            :     {
    1311 [ #  # ][ #  # ]:          0 :         ::boost::unordered_map< fontID, PrintFont* >::const_iterator it = m_aFonts.find( *font_it );
    1312         [ #  # ]:          0 :         if( it == m_aFonts.end() )
    1313                 :          0 :             continue;
    1314         [ #  # ]:          0 :         switch( it->second->m_eType )
           [ #  #  #  # ]
    1315                 :            :         {
    1316                 :            :             case fonttype::Type1:
    1317                 :            :             {
    1318         [ #  # ]:          0 :                 Type1FontFile* const pFont = static_cast< Type1FontFile* const >((*it).second);
    1319   [ #  #  #  # ]:          0 :                 if( pFont->m_nDirectory == nDirID &&
                 [ #  # ]
    1320                 :          0 :                     pFont->m_aFontFile == rFontFile )
    1321 [ #  # ][ #  # ]:          0 :                     aIds.push_back(it->first);
    1322                 :            :             }
    1323                 :          0 :             break;
    1324                 :            :             case fonttype::TrueType:
    1325                 :            :             {
    1326         [ #  # ]:          0 :                 TrueTypeFontFile* const pFont = static_cast< TrueTypeFontFile* const >((*it).second);
    1327   [ #  #  #  # ]:          0 :                 if( pFont->m_nDirectory == nDirID &&
                 [ #  # ]
    1328                 :          0 :                     pFont->m_aFontFile == rFontFile )
    1329 [ #  # ][ #  # ]:          0 :                     aIds.push_back(it->first);
    1330                 :            :             }
    1331                 :          0 :             break;
    1332                 :            :             case fonttype::Builtin:
    1333         [ #  # ]:          0 :                 if( static_cast<const BuiltinFont*>((*it).second)->m_nDirectory == nDirID &&
           [ #  #  #  # ]
                 [ #  # ]
    1334         [ #  # ]:          0 :                     static_cast<const BuiltinFont*>((*it).second)->m_aMetricFile == rFontFile )
    1335 [ #  # ][ #  # ]:          0 :                     aIds.push_back(it->first);
    1336                 :          0 :                 break;
    1337                 :            :             default:
    1338                 :          0 :                 break;
    1339                 :            :         }
    1340                 :            :     }
    1341                 :            : 
    1342                 :          0 :     return aIds;
    1343                 :            : }
    1344                 :            : 
    1345                 :            : // -------------------------------------------------------------------------
    1346                 :            : 
    1347                 :      18461 : OUString PrintFontManager::convertTrueTypeName( void* pRecord ) const
    1348                 :            : {
    1349                 :      18461 :     NameRecord* pNameRecord = (NameRecord*)pRecord;
    1350                 :      18461 :     OUString aValue;
    1351 [ +  - ][ -  + ]:      18461 :     if(
         [ -  + ][ +  + ]
    1352                 :            :        ( pNameRecord->platformID == 3 && ( pNameRecord->encodingID == 0 || pNameRecord->encodingID == 1 ) )  // MS, Unicode
    1353                 :            :        ||
    1354                 :            :        ( pNameRecord->platformID == 0 ) // Apple, Unicode
    1355                 :            :        )
    1356                 :            :     {
    1357                 :       9653 :         OUStringBuffer aName( pNameRecord->slen/2 );
    1358                 :       9653 :         const sal_uInt8* pNameBuffer = pNameRecord->sptr;
    1359         [ +  + ]:     139798 :         for(int n = 0; n < pNameRecord->slen/2; n++ )
    1360         [ +  - ]:     130145 :             aName.append( (sal_Unicode)getUInt16BE( pNameBuffer ) );
    1361         [ +  - ]:       9653 :         aValue = aName.makeStringAndClear();
    1362                 :            :     }
    1363         [ -  + ]:       8808 :     else if( pNameRecord->platformID == 3 )
    1364                 :            :     {
    1365 [ #  # ][ #  # ]:          0 :         if( pNameRecord->encodingID >= 2 && pNameRecord->encodingID <= 6 )
    1366                 :            :         {
    1367                 :            :             /*
    1368                 :            :              *  and now for a special kind of madness:
    1369                 :            :              *  some fonts encode their byte value string as BE uint16
    1370                 :            :              *  (leading to stray zero bytes in the string)
    1371                 :            :              *  while others code two bytes as a uint16 and swap to BE
    1372                 :            :              */
    1373                 :          0 :             OStringBuffer aName;
    1374                 :          0 :             const sal_uInt8* pNameBuffer = pNameRecord->sptr;
    1375         [ #  # ]:          0 :             for(int n = 0; n < pNameRecord->slen/2; n++ )
    1376                 :            :             {
    1377                 :          0 :                 sal_Unicode aCode = (sal_Unicode)getUInt16BE( pNameBuffer );
    1378                 :          0 :                 sal_Char aChar = aCode >> 8;
    1379         [ #  # ]:          0 :                 if( aChar )
    1380         [ #  # ]:          0 :                     aName.append( aChar );
    1381                 :          0 :                 aChar = aCode & 0x00ff;
    1382         [ #  # ]:          0 :                 if( aChar )
    1383         [ #  # ]:          0 :                     aName.append( aChar );
    1384                 :            :             }
    1385   [ #  #  #  #  :          0 :             switch( pNameRecord->encodingID )
                   #  # ]
    1386                 :            :             {
    1387                 :            :                 case 2:
    1388         [ #  # ]:          0 :                     aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_932 );
    1389                 :          0 :                     break;
    1390                 :            :                 case 3:
    1391         [ #  # ]:          0 :                     aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_936 );
    1392                 :          0 :                     break;
    1393                 :            :                 case 4:
    1394         [ #  # ]:          0 :                     aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_950 );
    1395                 :          0 :                     break;
    1396                 :            :                 case 5:
    1397         [ #  # ]:          0 :                     aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_949 );
    1398                 :          0 :                     break;
    1399                 :            :                 case 6:
    1400         [ #  # ]:          0 :                     aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_1361 );
    1401                 :          0 :                     break;
    1402                 :          0 :             }
    1403                 :            :         }
    1404                 :            :     }
    1405                 :      18461 :     return aValue;
    1406                 :            : }
    1407                 :            : 
    1408                 :            : //fdo#33349.There exists an archaic Berling Antiqua font which has a "Times New
    1409                 :            : //Roman" name field in it. We don't want the "Times New Roman" name to take
    1410                 :            : //precedence in this case. We take Berling Antiqua as a higher priority name,
    1411                 :            : //and erase the "Times New Roman" name
    1412                 :            : namespace
    1413                 :            : {
    1414                 :       9848 :     bool isBadTNR(const OUString &rName, ::std::set< OUString >& rSet)
    1415                 :            :     {
    1416                 :       9848 :         bool bRet = false;
    1417         [ -  + ]:       9848 :         if ( rName == "Berling Antiqua" )
    1418                 :            :         {
    1419                 :          0 :             ::std::set< OUString >::iterator aEnd = rSet.end();
    1420 [ #  # ][ #  # ]:          0 :             ::std::set< OUString >::iterator aI = rSet.find(OUString(RTL_CONSTASCII_USTRINGPARAM("Times New Roman")));
    1421         [ #  # ]:          0 :             if (aI != aEnd)
    1422                 :            :             {
    1423                 :          0 :                 bRet = true;
    1424         [ #  # ]:          0 :                 rSet.erase(aI);
    1425                 :            :             }
    1426                 :            :         }
    1427                 :       9848 :         return bRet;
    1428                 :            :     }
    1429                 :            : }
    1430                 :            : 
    1431                 :            : // -------------------------------------------------------------------------
    1432                 :            : 
    1433                 :       8418 : void PrintFontManager::analyzeTrueTypeFamilyName( void* pTTFont, ::std::list< OUString >& rNames ) const
    1434                 :            : {
    1435                 :       8418 :     OUString aFamily;
    1436                 :            : 
    1437                 :       8418 :     rNames.clear();
    1438         [ +  - ]:       8418 :     ::std::set< OUString > aSet;
    1439                 :            : 
    1440                 :       8418 :     NameRecord* pNameRecords = NULL;
    1441         [ +  - ]:       8418 :     int nNameRecords = GetTTNameRecords( (TrueTypeFont*)pTTFont, &pNameRecords );
    1442 [ +  - ][ +  - ]:       8418 :     if( nNameRecords && pNameRecords )
    1443                 :            :     {
    1444         [ +  - ]:       8418 :         LanguageType aLang = MsLangId::getSystemLanguage();
    1445                 :       8418 :         int nLastMatch = -1;
    1446         [ +  + ]:     483726 :         for( int i = 0; i < nNameRecords; i++ )
    1447                 :            :         {
    1448 [ +  + ][ -  + ]:     475308 :             if( pNameRecords[i].nameID != 1 || pNameRecords[i].sptr == NULL )
    1449                 :     456847 :                 continue;
    1450                 :      18461 :             int nMatch = -1;
    1451         [ -  + ]:      18461 :             if( pNameRecords[i].platformID == 0 ) // Unicode
    1452                 :          0 :                 nMatch = 4000;
    1453         [ +  + ]:      18461 :             else if( pNameRecords[i].platformID == 3 )
    1454                 :            :             {
    1455                 :            :                 // this bases on the LanguageType actually being a Win LCID
    1456         [ +  + ]:       9653 :                 if( pNameRecords[i].languageID == aLang )
    1457                 :       8418 :                     nMatch = 8000;
    1458         [ -  + ]:       1235 :                 else if( pNameRecords[i].languageID == LANGUAGE_ENGLISH_US )
    1459                 :          0 :                     nMatch = 2000;
    1460 [ +  - ][ -  + ]:       1235 :                 else if( pNameRecords[i].languageID == LANGUAGE_ENGLISH ||
    1461                 :       1235 :                          pNameRecords[i].languageID == LANGUAGE_ENGLISH_UK )
    1462                 :          0 :                     nMatch = 1500;
    1463                 :            :                 else
    1464                 :       9653 :                     nMatch = 1000;
    1465                 :            :             }
    1466         [ +  - ]:      18461 :             OUString aName = convertTrueTypeName( pNameRecords + i );
    1467         [ +  - ]:      18461 :             aSet.insert( aName );
    1468 [ +  + ][ +  - ]:      18461 :             if( nMatch > nLastMatch || isBadTNR(aName, aSet) )
         [ -  + ][ +  + ]
    1469                 :            :             {
    1470                 :       8613 :                 nLastMatch = nMatch;
    1471                 :       8613 :                 aFamily = aName;
    1472                 :            :             }
    1473                 :      18461 :         }
    1474         [ +  - ]:       8418 :         DisposeNameRecords( pNameRecords, nNameRecords );
    1475                 :            :     }
    1476         [ +  - ]:       8418 :     if( !aFamily.isEmpty() )
    1477                 :            :     {
    1478         [ +  - ]:       8418 :         rNames.push_front( aFamily );
    1479         [ +  + ]:      25904 :         for( ::std::set< OUString >::const_iterator it = aSet.begin(); it != aSet.end(); ++it )
    1480         [ +  + ]:      17486 :             if( *it != aFamily )
    1481         [ +  - ]:       9068 :                 rNames.push_back( *it );
    1482                 :            :     }
    1483                 :       8418 :     return;
    1484                 :            : }
    1485                 :            : 
    1486                 :            : // -------------------------------------------------------------------------
    1487                 :            : 
    1488                 :       8418 : bool PrintFontManager::analyzeTrueTypeFile( PrintFont* pFont ) const
    1489                 :            : {
    1490                 :       8418 :     bool bSuccess = false;
    1491         [ +  - ]:       8418 :     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
    1492         [ +  - ]:       8418 :     rtl::OString aFile = getFontFile( pFont );
    1493                 :       8418 :     TrueTypeFont* pTTFont = NULL;
    1494                 :            : 
    1495                 :       8418 :     TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont);
    1496 [ +  - ][ +  - ]:       8418 :     if( OpenTTFontFile( aFile.getStr(), pTTFontFile->m_nCollectionEntry, &pTTFont ) == SF_OK )
    1497                 :            :     {
    1498                 :            :         TTGlobalFontInfo aInfo;
    1499         [ +  - ]:       8418 :         GetTTGlobalFontInfo( pTTFont, & aInfo );
    1500                 :            : 
    1501         [ +  - ]:       8418 :         ::std::list< OUString > aNames;
    1502         [ +  - ]:       8418 :         analyzeTrueTypeFamilyName( pTTFont, aNames );
    1503                 :            : 
    1504                 :            :         // set family name from XLFD if possible
    1505         [ +  + ]:       8418 :         if( ! pFont->m_nFamilyName )
    1506                 :            :         {
    1507         [ +  - ]:       8297 :             if( aNames.begin() != aNames.end() )
    1508                 :            :             {
    1509 [ +  - ][ +  - ]:       8297 :                 pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, aNames.front(), sal_True );
    1510         [ +  - ]:       8297 :                 aNames.pop_front();
    1511                 :            :             }
    1512                 :            :             else
    1513                 :            :             {
    1514                 :            :                  sal_Int32   dotIndex;
    1515                 :            : 
    1516                 :            :                  // poor font does not have a family name
    1517                 :            :                  // name it to file name minus the extension
    1518                 :          0 :                  dotIndex = pTTFontFile->m_aFontFile.lastIndexOf( '.' );
    1519         [ #  # ]:          0 :                  if ( dotIndex == -1 )
    1520                 :          0 :                      dotIndex = pTTFontFile->m_aFontFile.getLength();
    1521                 :            : 
    1522 [ #  # ][ #  # ]:          0 :                  pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, OStringToOUString( pTTFontFile->m_aFontFile.copy( 0, dotIndex ), aEncoding ), sal_True );
    1523                 :            :             }
    1524                 :            :         }
    1525         [ +  + ]:      17607 :         for( ::std::list< OUString >::iterator it = aNames.begin(); it != aNames.end(); ++it )
    1526                 :            :         {
    1527         [ +  + ]:       9189 :             if( !it->isEmpty() )
    1528                 :            :             {
    1529         [ +  - ]:        771 :                 int nAlias = m_pAtoms->getAtom( ATOM_FAMILYNAME, *it, sal_True );
    1530         [ +  + ]:        771 :                 if( nAlias != pFont->m_nFamilyName )
    1531                 :            :                 {
    1532         [ +  - ]:        650 :                     std::list< int >::const_iterator al_it;
    1533 [ +  - ][ +  - ]:        845 :                     for( al_it = pFont->m_aAliases.begin(); al_it != pFont->m_aAliases.end() && *al_it != nAlias; ++al_it )
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  +  
             #  #  #  # ]
    1534                 :            :                         ;
    1535 [ +  - ][ +  - ]:        650 :                     if( al_it == pFont->m_aAliases.end() )
                 [ +  - ]
    1536         [ +  - ]:        771 :                         pFont->m_aAliases.push_back( nAlias );
    1537                 :            :                 }
    1538                 :            :             }
    1539                 :            :         }
    1540                 :            : 
    1541         [ -  + ]:       8418 :         if( aInfo.usubfamily )
    1542                 :          0 :             pFont->m_aStyleName = OUString( aInfo.usubfamily );
    1543                 :            : 
    1544                 :            :         SAL_WARN_IF( !aInfo.psname, "vcl", "No PostScript name in font:" << aFile.getStr() );
    1545                 :            : 
    1546                 :            :         rtl::OUString sPSName = aInfo.psname ?
    1547                 :            :             rtl::OUString(aInfo.psname, rtl_str_getLength(aInfo.psname), aEncoding) :
    1548 [ +  - ][ +  - ]:       8418 :             m_pAtoms->getString(ATOM_FAMILYNAME, pFont->m_nFamilyName); // poor font does not have a postscript name
                 [ #  # ]
    1549                 :            : 
    1550         [ +  - ]:       8418 :         pFont->m_nPSName = m_pAtoms->getAtom( ATOM_PSNAME, sPSName, sal_True );
    1551                 :            : 
    1552   [ -  +  +  +  :       8418 :         switch( aInfo.weight )
             +  +  -  -  
                      + ]
    1553                 :            :         {
    1554                 :          0 :             case FW_THIN:           pFont->m_eWeight = WEIGHT_THIN; break;
    1555                 :        127 :             case FW_EXTRALIGHT: pFont->m_eWeight = WEIGHT_ULTRALIGHT; break;
    1556                 :        260 :             case FW_LIGHT:          pFont->m_eWeight = WEIGHT_LIGHT; break;
    1557                 :        325 :             case FW_MEDIUM:     pFont->m_eWeight = WEIGHT_MEDIUM; break;
    1558                 :        189 :             case FW_SEMIBOLD:       pFont->m_eWeight = WEIGHT_SEMIBOLD; break;
    1559                 :       3122 :             case FW_BOLD:           pFont->m_eWeight = WEIGHT_BOLD; break;
    1560                 :          0 :             case FW_EXTRABOLD:      pFont->m_eWeight = WEIGHT_ULTRABOLD; break;
    1561                 :          0 :             case FW_BLACK:          pFont->m_eWeight = WEIGHT_BLACK; break;
    1562                 :            : 
    1563                 :            :             case FW_NORMAL:
    1564                 :       4395 :             default:        pFont->m_eWeight = WEIGHT_NORMAL; break;
    1565                 :            :         }
    1566                 :            : 
    1567   [ -  -  +  +  :       8418 :         switch( aInfo.width )
             -  -  -  -  
                      + ]
    1568                 :            :         {
    1569                 :          0 :             case FWIDTH_ULTRA_CONDENSED:    pFont->m_eWidth = WIDTH_ULTRA_CONDENSED; break;
    1570                 :          0 :             case FWIDTH_EXTRA_CONDENSED:    pFont->m_eWidth = WIDTH_EXTRA_CONDENSED; break;
    1571                 :        378 :             case FWIDTH_CONDENSED:          pFont->m_eWidth = WIDTH_CONDENSED; break;
    1572                 :        954 :             case FWIDTH_SEMI_CONDENSED: pFont->m_eWidth = WIDTH_SEMI_CONDENSED; break;
    1573                 :          0 :             case FWIDTH_SEMI_EXPANDED:      pFont->m_eWidth = WIDTH_SEMI_EXPANDED; break;
    1574                 :          0 :             case FWIDTH_EXPANDED:           pFont->m_eWidth = WIDTH_EXPANDED; break;
    1575                 :          0 :             case FWIDTH_EXTRA_EXPANDED: pFont->m_eWidth = WIDTH_EXTRA_EXPANDED; break;
    1576                 :          0 :             case FWIDTH_ULTRA_EXPANDED: pFont->m_eWidth = WIDTH_ULTRA_EXPANDED; break;
    1577                 :            : 
    1578                 :            :             case FWIDTH_NORMAL:
    1579                 :       7086 :             default:                        pFont->m_eWidth = WIDTH_NORMAL; break;
    1580                 :            :         }
    1581                 :            : 
    1582         [ +  + ]:       8418 :         pFont->m_ePitch = aInfo.pitch ? PITCH_FIXED : PITCH_VARIABLE;
    1583 [ +  + ][ +  - ]:       8418 :         pFont->m_eItalic = aInfo.italicAngle == 0 ? ITALIC_NONE : ( aInfo.italicAngle < 0 ? ITALIC_NORMAL : ITALIC_OBLIQUE );
    1584                 :            :         // #104264# there are fonts that set italic angle 0 although they are
    1585                 :            :         // italic; use macstyle bit here
    1586 [ +  + ][ -  + ]:       8418 :         if( aInfo.italicAngle == 0 && (aInfo.macStyle & 2) )
    1587                 :          0 :             pFont->m_eItalic = ITALIC_NORMAL;
    1588                 :            : 
    1589         [ -  + ]:       8418 :         pFont->m_aEncoding = aInfo.symbolEncoded ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UCS2;
    1590                 :            : 
    1591                 :       8418 :         pFont->m_aGlobalMetricY.width = pFont->m_aGlobalMetricX.width = aInfo.xMax - aInfo.xMin;
    1592                 :       8418 :         pFont->m_aGlobalMetricY.height = pFont->m_aGlobalMetricX.height = aInfo.yMax - aInfo.yMin;
    1593                 :            : 
    1594 [ +  - ][ +  - ]:       8418 :         if( aInfo.winAscent && aInfo.winDescent )
    1595                 :            :         {
    1596                 :       8418 :             pFont->m_nAscend    = aInfo.winAscent;
    1597                 :       8418 :             pFont->m_nDescend   = aInfo.winDescent;
    1598                 :       8418 :             pFont->m_nLeading   = pFont->m_nAscend + pFont->m_nDescend - 1000;
    1599                 :            :         }
    1600 [ #  # ][ #  # ]:          0 :         else if( aInfo.typoAscender && aInfo.typoDescender )
    1601                 :            :         {
    1602                 :          0 :             pFont->m_nLeading   = aInfo.typoLineGap;
    1603                 :          0 :             pFont->m_nAscend    = aInfo.typoAscender;
    1604                 :          0 :             pFont->m_nDescend   = -aInfo.typoDescender;
    1605                 :            :         }
    1606                 :            :         else
    1607                 :            :         {
    1608                 :          0 :             pFont->m_nLeading   = aInfo.linegap;
    1609                 :          0 :             pFont->m_nAscend    = aInfo.ascender;
    1610                 :          0 :             pFont->m_nDescend   = -aInfo.descender;
    1611                 :            :         }
    1612                 :            : 
    1613                 :            :         // last try: font bounding box
    1614         [ -  + ]:       8418 :         if( pFont->m_nAscend == 0 )
    1615                 :          0 :             pFont->m_nAscend = aInfo.yMax;
    1616         [ -  + ]:       8418 :         if( pFont->m_nDescend == 0 )
    1617                 :          0 :             pFont->m_nDescend = -aInfo.yMin;
    1618         [ -  + ]:       8418 :         if( pFont->m_nLeading == 0 )
    1619                 :          0 :             pFont->m_nLeading = 15 * (pFont->m_nAscend+pFont->m_nDescend) / 100;
    1620                 :            : 
    1621         [ +  - ]:       8418 :         if( pFont->m_nAscend )
    1622                 :       8418 :             pFont->m_aGlobalMetricX.height = pFont->m_aGlobalMetricY.height = pFont->m_nAscend + pFont->m_nDescend;
    1623                 :            : 
    1624                 :            :         // get bounding box
    1625                 :       8418 :         pFont->m_nXMin = aInfo.xMin;
    1626                 :       8418 :         pFont->m_nYMin = aInfo.yMin;
    1627                 :       8418 :         pFont->m_nXMax = aInfo.xMax;
    1628                 :       8418 :         pFont->m_nYMax = aInfo.yMax;
    1629                 :            : 
    1630                 :            :         // get type flags
    1631                 :       8418 :         pTTFontFile->m_nTypeFlags = (unsigned int)aInfo.typeFlags;
    1632                 :            : 
    1633                 :            :         // get vertical substitutions flag
    1634         [ +  - ]:       8418 :         pFont->m_bHaveVerticalSubstitutedGlyphs = DoesVerticalSubstitution( pTTFont, 1 );
    1635                 :            : 
    1636         [ +  - ]:       8418 :         CloseTTFont( pTTFont );
    1637                 :       8418 :         bSuccess = true;
    1638                 :            :     }
    1639                 :            : #if OSL_DEBUG_LEVEL > 1
    1640                 :            :     else
    1641                 :            :         fprintf( stderr, "could not OpenTTFont \"%s\"\n", aFile.getStr() );
    1642                 :            : #endif
    1643                 :            : 
    1644                 :       8418 :     return bSuccess;
    1645                 :            : }
    1646                 :            : 
    1647                 :        233 : static bool AreFCSubstitutionsEnabled()
    1648                 :            : {
    1649                 :        233 :     return (SalGenericInstance::FetchFontSubstitutionFlags() & 3) == 0;
    1650                 :            : }
    1651                 :            : 
    1652                 :        236 : void PrintFontManager::initialize()
    1653                 :            : {
    1654                 :            :     #ifdef CALLGRIND_COMPILE
    1655                 :            :     CALLGRIND_TOGGLE_COLLECT();
    1656                 :            :     CALLGRIND_ZERO_STATS();
    1657                 :            :     #endif
    1658                 :            : 
    1659                 :            :     long aDirEntBuffer[ (sizeof(struct dirent)+_PC_NAME_MAX)+1 ];
    1660                 :            : 
    1661         [ +  - ]:        236 :     if( ! m_pFontCache )
    1662                 :            :     {
    1663                 :            : #if OSL_DEBUG_LEVEL > 1
    1664                 :            :         fprintf( stderr, "creating font cache ... " );
    1665                 :            :         clock_t aStart;
    1666                 :            :         struct tms tms;
    1667                 :            :         aStart = times( &tms );
    1668                 :            : #endif
    1669 [ +  - ][ +  - ]:        236 :         m_pFontCache = new FontCache();
    1670                 :            : #if OSL_DEBUG_LEVEL > 1
    1671                 :            :         clock_t aStop = times( &tms );
    1672                 :            :         fprintf( stderr, "done in %lf s\n", (double)(aStop - aStart)/(double)sysconf( _SC_CLK_TCK ) );
    1673                 :            : #endif
    1674                 :            :     }
    1675                 :            : 
    1676                 :            :     // initialize may be called twice in the future
    1677                 :            :     {
    1678 [ +  - ][ +  - ]:        236 :         for( ::boost::unordered_map< fontID, PrintFont* >::const_iterator it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
                 [ -  + ]
    1679 [ #  # ][ #  # ]:          0 :             delete (*it).second;
                 [ #  # ]
    1680                 :        236 :         m_nNextFontID = 1;
    1681         [ +  - ]:        236 :         m_aFonts.clear();
    1682                 :        236 :         m_aFontDirectories.clear();
    1683                 :        236 :         m_aPrivateFontDirectories.clear();
    1684                 :        236 :         m_aOverrideFonts.clear();
    1685                 :            :     }
    1686                 :            : 
    1687                 :            : #if OSL_DEBUG_LEVEL > 1
    1688                 :            :     clock_t aStart;
    1689                 :            :     clock_t aStep1;
    1690                 :            :     clock_t aStep2;
    1691                 :            :     clock_t aStep3;
    1692                 :            :     int nBuiltinFonts = 0;
    1693                 :            :     int nCached = 0;
    1694                 :            : 
    1695                 :            :     struct tms tms;
    1696                 :            : 
    1697                 :            :     aStart = times( &tms );
    1698                 :            : #endif
    1699                 :            : 
    1700                 :            :     // first try fontconfig
    1701         [ +  - ]:        236 :     initFontconfig();
    1702                 :            : 
    1703                 :            :     // part one - look for downloadable fonts
    1704         [ +  - ]:        236 :     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
    1705         [ +  - ]:        236 :     const ::rtl::OUString &rSalPrivatePath = psp::getFontPath();
    1706                 :            : 
    1707                 :            :     // search for the fonts in SAL_PRIVATE_FONTPATH first; those are
    1708                 :            :     // the fonts installed with the office
    1709         [ +  + ]:        236 :     if( !rSalPrivatePath.isEmpty() )
    1710                 :            :     {
    1711         [ +  - ]:        233 :         OString aPath = rtl::OUStringToOString( rSalPrivatePath, aEncoding );
    1712         [ +  - ]:        233 :         const bool bAreFCSubstitutionsEnabled = AreFCSubstitutionsEnabled();
    1713                 :        233 :         sal_Int32 nIndex = 0;
    1714         [ +  + ]:        549 :         do
    1715                 :            :         {
    1716                 :        549 :             OString aToken = aPath.getToken( 0, ';', nIndex );
    1717         [ +  - ]:        549 :             normPath( aToken );
    1718         [ -  + ]:        549 :             if ( aToken.isEmpty() )
    1719                 :            :             {
    1720                 :          0 :                 continue;
    1721                 :            :             }
    1722                 :            :             // if registering an app-specific fontdir with fontconfig fails
    1723                 :            :             // and fontconfig-based substitutions are enabled
    1724                 :            :             // then trying to use these app-specific fonts doesn't make sense
    1725 [ +  - ][ -  + ]:        549 :             if( !addFontconfigDir( aToken ) )
    1726         [ #  # ]:          0 :                 if( bAreFCSubstitutionsEnabled )
    1727                 :          0 :                     continue;
    1728         [ +  - ]:        549 :             m_aFontDirectories.push_back( aToken );
    1729 [ +  - ][ +  - ]:        549 :             m_aPrivateFontDirectories.push_back( getDirectoryAtom( aToken, true ) );
                 [ +  - ]
    1730                 :        233 :         } while( nIndex >= 0 );
    1731                 :            :     }
    1732                 :            : 
    1733                 :            :     // protect against duplicate paths
    1734         [ +  - ]:        236 :     boost::unordered_map< OString, int, OStringHash > visited_dirs;
    1735                 :            : 
    1736                 :            :     // Don't search directories that fontconfig already did
    1737         [ +  - ]:        236 :     countFontconfigFonts( visited_dirs );
    1738                 :            : 
    1739                 :            :     // search for font files in each path
    1740                 :        236 :     std::list< OString >::iterator dir_it;
    1741         [ +  + ]:        785 :     for( dir_it = m_aFontDirectories.begin(); dir_it != m_aFontDirectories.end(); ++dir_it )
    1742                 :            :     {
    1743                 :        549 :         OString aPath( *dir_it );
    1744                 :            :         // see if we were here already
    1745 [ +  - ][ +  + ]:        549 :         if( visited_dirs.find( aPath ) != visited_dirs.end() )
                 [ +  - ]
    1746                 :        158 :             continue;
    1747         [ +  - ]:        391 :         visited_dirs[ aPath ] = 1;
    1748                 :            : 
    1749                 :            :         // there may be ":unscaled" directories (see XFree86)
    1750                 :            :         // it should be safe to ignore them since they should not
    1751                 :            :         // contain any of our recognizeable fonts
    1752                 :            : 
    1753                 :            :         // ask the font cache whether it handles this directory
    1754         [ +  - ]:        391 :         std::list< PrintFont* > aCacheFonts;
    1755 [ +  - ][ -  + ]:        391 :         if( m_pFontCache->listDirectory( aPath, aCacheFonts ) )
    1756                 :            :         {
    1757                 :            : #if OSL_DEBUG_LEVEL > 1
    1758                 :            :             fprintf( stderr, "adding cache directory: %s\n", aPath.getStr() );
    1759                 :            : #endif
    1760 [ #  # ][ #  # ]:          0 :             for( ::std::list< PrintFont* >::iterator it = aCacheFonts.begin(); it != aCacheFonts.end(); ++it )
                 [ #  # ]
    1761                 :            :             {
    1762                 :          0 :                 fontID aFont = m_nNextFontID++;
    1763 [ #  # ][ #  # ]:          0 :                 m_aFonts[ aFont ] = *it;
    1764 [ #  # ][ #  # ]:          0 :                 if( (*it)->m_eType == fonttype::Type1 )
    1765 [ #  # ][ #  # ]:          0 :                     m_aFontFileToFontID[ static_cast<Type1FontFile*>(*it)->m_aFontFile ].insert( aFont );
                 [ #  # ]
    1766 [ #  # ][ #  # ]:          0 :                 else if( (*it)->m_eType == fonttype::TrueType )
    1767 [ #  # ][ #  # ]:          0 :                     m_aFontFileToFontID[ static_cast<TrueTypeFontFile*>(*it)->m_aFontFile ].insert( aFont );
                 [ #  # ]
    1768 [ #  # ][ #  # ]:          0 :                 else if( (*it)->m_eType == fonttype::Builtin )
    1769 [ #  # ][ #  # ]:          0 :                     m_aFontFileToFontID[ static_cast<BuiltinFont*>(*it)->m_aMetricFile ].insert( aFont );
                 [ #  # ]
    1770                 :            : #if OSL_DEBUG_LEVEL > 1
    1771                 :            :                 if( (*it)->m_eType == fonttype::Builtin )
    1772                 :            :                     nBuiltinFonts++;
    1773                 :            :                 nCached++;
    1774                 :            : #if OSL_DEBUG_LEVEL > 2
    1775                 :            :                 fprintf( stderr, "adding cached font %d: %s\n", aFont, getFontFileSysPath( aFont ).getStr() );
    1776                 :            : #endif
    1777                 :            : #endif
    1778                 :            :             }
    1779 [ #  # ][ #  # ]:          0 :             if( ! m_pFontCache->scanAdditionalFiles( aPath ) )
    1780                 :        391 :                 continue;
    1781                 :            :         }
    1782                 :            : 
    1783 [ -  + ][ +  + ]:        549 :     }
    1784                 :            : 
    1785                 :            : #if OSL_DEBUG_LEVEL > 1
    1786                 :            :     aStep1 = times( &tms );
    1787                 :            : #endif
    1788                 :            : 
    1789                 :            :     // part two - look for metrics for builtin printer fonts
    1790         [ +  - ]:        236 :     std::list< OUString > aMetricDirs;
    1791         [ +  - ]:        236 :     psp::getPrinterPathList( aMetricDirs, PRINTER_METRICDIR );
    1792                 :            : 
    1793         [ +  + ]:        630 :     for( std::list< OUString >::const_iterator met_dir_it = aMetricDirs.begin(); met_dir_it != aMetricDirs.end(); ++met_dir_it )
    1794                 :            :     {
    1795         [ +  - ]:        394 :         OString aDir = OUStringToOString( *met_dir_it, aEncoding );
    1796                 :            : 
    1797                 :            :         // ask the font cache whether it handles this directory
    1798         [ +  - ]:        394 :         std::list< PrintFont* > aCacheFonts;
    1799                 :            : 
    1800 [ +  - ][ +  + ]:        394 :         if( m_pFontCache->listDirectory( aDir, aCacheFonts ) )
    1801                 :            :         {
    1802                 :            : #if OSL_DEBUG_LEVEL > 1
    1803                 :            :             fprintf( stderr, "adding cache directory: %s\n", aDir.getStr() );
    1804                 :            : #endif
    1805 [ +  - ][ +  - ]:       3243 :             for( ::std::list< PrintFont* >::iterator it = aCacheFonts.begin(); it != aCacheFonts.end(); ++it )
                 [ +  + ]
    1806                 :            :             {
    1807                 :       2976 :                 fontID aFont = m_nNextFontID++;
    1808 [ +  - ][ +  - ]:       2976 :                 m_aFonts[ aFont ] = *it;
    1809 [ +  - ][ -  + ]:       2976 :                 if( (*it)->m_eType == fonttype::Type1 )
    1810 [ #  # ][ #  # ]:          0 :                     m_aFontFileToFontID[ static_cast<Type1FontFile*>(*it)->m_aFontFile ].insert( aFont );
                 [ #  # ]
    1811 [ +  - ][ -  + ]:       2976 :                 else if( (*it)->m_eType == fonttype::TrueType )
    1812 [ #  # ][ #  # ]:          0 :                     m_aFontFileToFontID[ static_cast<TrueTypeFontFile*>(*it)->m_aFontFile ].insert( aFont );
                 [ #  # ]
    1813 [ +  - ][ +  - ]:       2976 :                 else if( (*it)->m_eType == fonttype::Builtin )
    1814 [ +  - ][ +  - ]:       2976 :                     m_aFontFileToFontID[ static_cast<BuiltinFont*>(*it)->m_aMetricFile ].insert( aFont );
                 [ +  - ]
    1815                 :            : #if OSL_DEBUG_LEVEL > 1
    1816                 :            :                 if( (*it)->m_eType == fonttype::Builtin )
    1817                 :            :                     nBuiltinFonts++;
    1818                 :            :                 nCached++;
    1819                 :            : #if OSL_DEBUG_LEVEL > 2
    1820                 :            :                 fprintf( stderr, "adding cached font %d: from %s\n", aFont,
    1821                 :            :                          getFontFileSysPath( aFont ).getStr() );
    1822                 :            : #endif
    1823                 :            : #endif
    1824                 :            :             }
    1825                 :        267 :             continue;
    1826                 :            :         }
    1827                 :            : 
    1828         [ +  - ]:        127 :         DIR* pDIR = opendir( aDir.getStr() );
    1829         [ +  - ]:        127 :         if( pDIR )
    1830                 :            :         {
    1831                 :        127 :             struct dirent* pDirEntry = (struct dirent*)aDirEntBuffer;
    1832         [ +  - ]:        127 :             int nDirID = getDirectoryAtom( aDir, true );
    1833                 :        127 :             int nDirFonts = 0;
    1834                 :            : 
    1835 [ +  - ][ +  - ]:       2306 :             while( ! readdir_r( pDIR, (struct dirent*)aDirEntBuffer, &pDirEntry ) && pDirEntry )
         [ +  + ][ +  + ]
    1836                 :            :             {
    1837         [ +  - ]:       2179 :                 rtl::OStringBuffer aFile(aDir);
    1838 [ +  - ][ +  - ]:       2179 :                 aFile.append('/').append(pDirEntry->d_name);
    1839                 :            :                 struct stat aStat;
    1840 [ +  - ][ +  + ]:       2179 :                 if( ! stat( aFile.getStr(), &aStat )
                 [ +  + ]
    1841                 :            :                     && S_ISREG( aStat.st_mode )
    1842                 :            :                     )
    1843                 :            :                 {
    1844                 :       1925 :                     OString aFileName( pDirEntry->d_name, strlen( pDirEntry->d_name ) );
    1845                 :       1925 :                     OString aExt( aFileName.copy( aFileName.lastIndexOf( '.' )+1 ) );
    1846         [ +  + ]:       1925 :                     if( aExt.equalsIgnoreAsciiCase( "afm" ) )
    1847                 :            :                     {
    1848         [ +  - ]:       1922 :                         ::std::list< PrintFont* > aNewFonts;
    1849                 :            : 
    1850         [ +  - ]:       1922 :                         analyzeFontFile( nDirID, aFileName, aNewFonts );
    1851 [ +  - ][ +  - ]:       3844 :                         for( ::std::list< PrintFont* >::iterator it = aNewFonts.begin(); it != aNewFonts.end(); ++it )
                 [ +  + ]
    1852                 :            :                         {
    1853 [ +  - ][ +  - ]:       1922 :                             if( findFontBuiltinID( (*it)->m_nPSName ) == 0 )
                 [ +  - ]
    1854                 :            :                             {
    1855 [ +  - ][ +  - ]:       1922 :                                 m_aFontFileToFontID[ aFileName ].insert( m_nNextFontID );
    1856 [ +  - ][ +  - ]:       1922 :                                 m_aFonts[ m_nNextFontID++ ] = *it;
    1857 [ +  - ][ +  - ]:       1922 :                                 m_pFontCache->updateFontCacheEntry( *it, false );
    1858                 :            : #if OSL_DEBUG_LEVEL > 2
    1859                 :            :                                 nBuiltinFonts++;
    1860                 :            : #endif
    1861                 :            :                             }
    1862                 :            :                             else
    1863 [ #  # ][ #  # ]:          0 :                                 delete *it;
                 [ #  # ]
    1864                 :       1922 :                         }
    1865                 :       1925 :                     }
    1866                 :            :                 }
    1867                 :       2179 :             }
    1868         [ +  - ]:        127 :             closedir( pDIR );
    1869         [ +  - ]:        127 :             if( ! nDirFonts )
    1870         [ +  - ]:        127 :                 m_pFontCache->markEmptyDir( nDirID );
    1871                 :            :         }
    1872 [ +  + ][ +  + ]:        394 :     }
    1873                 :            : 
    1874                 :            : #if OSL_DEBUG_LEVEL > 1
    1875                 :            :     aStep2 = times( &tms );
    1876                 :            : #endif
    1877                 :            : 
    1878                 :            :     // part three - fill in family styles
    1879                 :        236 :     ::boost::unordered_map< fontID, PrintFont* >::iterator font_it;
    1880 [ +  - ][ +  + ]:      40096 :     for (font_it = m_aFonts.begin(); font_it != m_aFonts.end(); ++font_it)
                 [ +  - ]
    1881                 :            :     {
    1882                 :            :         ::boost::unordered_map< int, FontFamily >::const_iterator it =
    1883 [ +  - ][ +  - ]:      39860 :               m_aFamilyTypes.find( font_it->second->m_nFamilyName );
    1884 [ +  + ][ +  - ]:      39860 :         if (it != m_aFamilyTypes.end())
    1885                 :      25060 :             continue;
    1886                 :            :         const ::rtl::OUString& rFamily =
    1887 [ +  - ][ +  - ]:      14800 :             m_pAtoms->getString( ATOM_FAMILYNAME, font_it->second->m_nFamilyName);
    1888         [ +  - ]:      14800 :         FontFamily eType = matchFamilyName( rFamily );
    1889 [ +  - ][ +  - ]:      14800 :         m_aFamilyTypes[ font_it->second->m_nFamilyName ] = eType;
    1890                 :            :     }
    1891                 :            : 
    1892                 :            : #if OSL_DEBUG_LEVEL > 1
    1893                 :            :     aStep3 = times( &tms );
    1894                 :            :     fprintf( stderr, "PrintFontManager::initialize: collected %" SAL_PRI_SIZET "u fonts (%d builtin, %d cached)\n", m_aFonts.size(), nBuiltinFonts, nCached );
    1895                 :            :     double fTick = (double)sysconf( _SC_CLK_TCK );
    1896                 :            :     fprintf( stderr, "Step 1 took %lf seconds\n", (double)(aStep1 - aStart)/fTick );
    1897                 :            :     fprintf( stderr, "Step 2 took %lf seconds\n", (double)(aStep2 - aStep1)/fTick );
    1898                 :            :     fprintf( stderr, "Step 3 took %lf seconds\n", (double)(aStep3 - aStep2)/fTick );
    1899                 :            : #endif
    1900                 :            : 
    1901 [ +  - ][ +  - ]:        236 :     m_pFontCache->flush();
    1902                 :            : 
    1903                 :            :     #ifdef CALLGRIND_COMPILE
    1904                 :            :     CALLGRIND_DUMP_STATS();
    1905                 :            :     CALLGRIND_TOGGLE_COLLECT();
    1906                 :            :     #endif
    1907                 :        236 : }
    1908                 :            : 
    1909                 :            : // -------------------------------------------------------------------------
    1910                 :            : inline bool
    1911                 :          0 : equalPitch (FontPitch from, FontPitch to)
    1912                 :            : {
    1913                 :          0 :     return from == to;
    1914                 :            : }
    1915                 :            : 
    1916                 :            : inline bool
    1917                 :          0 : equalWeight (FontWeight from, FontWeight to)
    1918                 :            : {
    1919         [ #  # ]:          0 :     return from > to ? (from - to) <= 3 : (to - from) <= 3;
    1920                 :            : }
    1921                 :            : 
    1922                 :            : inline bool
    1923                 :          0 : equalItalic (FontItalic from, FontItalic to)
    1924                 :            : {
    1925 [ #  # ][ #  # ]:          0 :     if ( (from == ITALIC_NORMAL) || (from == ITALIC_OBLIQUE) )
    1926 [ #  # ][ #  # ]:          0 :         return (to == ITALIC_NORMAL) || (to == ITALIC_OBLIQUE);
    1927                 :          0 :     return to == from;
    1928                 :            : }
    1929                 :            : inline bool
    1930                 :          0 : equalEncoding (rtl_TextEncoding from, rtl_TextEncoding to)
    1931                 :            : {
    1932 [ #  # ][ #  # ]:          0 :     if ((from == RTL_TEXTENCODING_ISO_8859_1) || (from == RTL_TEXTENCODING_MS_1252))
    1933 [ #  # ][ #  # ]:          0 :         return (to == RTL_TEXTENCODING_ISO_8859_1) || (to == RTL_TEXTENCODING_MS_1252);
    1934                 :          0 :     return from == to;
    1935                 :            : }
    1936                 :            : 
    1937                 :            : namespace {
    1938                 :      29412 :     struct BuiltinFontIdentifier
    1939                 :            :     {
    1940                 :            :         OUString            aFamily;
    1941                 :            :         FontItalic          eItalic;
    1942                 :            :         FontWeight          eWeight;
    1943                 :            :         FontPitch           ePitch;
    1944                 :            :         rtl_TextEncoding    aEncoding;
    1945                 :            : 
    1946                 :      22344 :         BuiltinFontIdentifier( const OUString& rFam,
    1947                 :            :                                FontItalic eIt,
    1948                 :            :                                FontWeight eWg,
    1949                 :            :                                FontPitch ePt,
    1950                 :            :                                rtl_TextEncoding enc ) :
    1951                 :            :             aFamily( rFam ),
    1952                 :            :             eItalic( eIt ),
    1953                 :            :             eWeight( eWg ),
    1954                 :            :             ePitch( ePt ),
    1955                 :      22344 :             aEncoding( enc )
    1956                 :      22344 :         {}
    1957                 :            : 
    1958                 :          0 :         bool operator==( const BuiltinFontIdentifier& rRight ) const
    1959                 :            :         {
    1960                 :          0 :             return equalItalic( eItalic, rRight.eItalic ) &&
    1961                 :          0 :                    equalWeight( eWeight, rRight.eWeight ) &&
    1962                 :          0 :                    equalPitch( ePitch, rRight.ePitch ) &&
    1963                 :          0 :                    equalEncoding( aEncoding, rRight.aEncoding ) &&
    1964 [ #  # ][ #  #  :          0 :                    aFamily.equalsIgnoreAsciiCase( rRight.aFamily );
          #  #  #  #  #  
                      # ]
    1965                 :            :         }
    1966                 :            :     };
    1967                 :            : 
    1968                 :            :     struct BuiltinFontIdentifierHash
    1969                 :            :     {
    1970                 :      22344 :         size_t operator()( const BuiltinFontIdentifier& rFont ) const
    1971                 :            :         {
    1972                 :      22344 :             return rFont.aFamily.hashCode() ^ rFont.eItalic ^ rFont.eWeight ^ rFont.ePitch ^ rFont.aEncoding;
    1973                 :            :         }
    1974                 :            :     };
    1975                 :            : }
    1976                 :            : 
    1977                 :        359 : void PrintFontManager::getFontList( ::std::list< fontID >& rFontIDs, const PPDParser* pParser, bool bUseOverrideMetrics )
    1978                 :            : {
    1979                 :        359 :     rFontIDs.clear();
    1980                 :        359 :     boost::unordered_map< fontID, PrintFont* >::const_iterator it;
    1981                 :            : 
    1982                 :            :     /*
    1983                 :            :     * Note: there are two easy steps making this faster:
    1984                 :            :     * first: insert the printer builtins first, then the not builtins,
    1985                 :            :     * if they do not match.
    1986                 :            :     * drawback: this would change the sequence of fonts; this could have
    1987                 :            :     * subtle, unknown consequences in vcl font matching
    1988                 :            :     * second: instead of comparing attributes to see whether a softfont
    1989                 :            :     * is duplicate to a builtin one could simply compare the PSName (which is
    1990                 :            :     * supposed to be unique), which at this point is just an int.
    1991                 :            :     * drawback: this could change which fonts are listed; especially TrueType
    1992                 :            :     * fonts often have a rather dubious PSName, so this could change the
    1993                 :            :     * font list not so subtle.
    1994                 :            :     * Until getFontList for a printer becomes a performance issue (which is
    1995                 :            :     * currently not the case), best stay with the current algorithm.
    1996                 :            :     */
    1997                 :            : 
    1998                 :            :     // fill sets of printer supported fonts
    1999         [ +  + ]:        359 :     if( pParser )
    2000                 :            :     {
    2001         [ +  - ]:        114 :         std::set<int> aBuiltinPSNames;
    2002                 :            :         boost::unordered_set< BuiltinFontIdentifier,
    2003                 :            :                        BuiltinFontIdentifierHash
    2004         [ +  - ]:        114 :                        > aBuiltinFonts;
    2005                 :            : 
    2006         [ +  - ]:        114 :         std::map<int, fontID > aOverridePSNames;
    2007         [ +  + ]:        114 :         if( bUseOverrideMetrics )
    2008                 :            :         {
    2009         [ +  - ]:          2 :             readOverrideMetrics();
    2010         [ +  - ]:          4 :             for( std::vector<fontID>::const_iterator over = m_aOverrideFonts.begin();
           [ #  #  +  - ]
                 [ -  + ]
    2011                 :          2 :                  over != m_aOverrideFonts.end(); ++over )
    2012                 :            :             {
    2013 [ #  # ][ #  # ]:          0 :                 boost::unordered_map<fontID,PrintFont*>::const_iterator font_it = m_aFonts.find( *over );
    2014                 :            :                 DBG_ASSERT( font_it != m_aFonts.end(), "override to nonexistant font" );
    2015 [ #  # ][ #  # ]:          0 :                 if( font_it != m_aFonts.end() )
    2016 [ #  # ][ #  # ]:          0 :                     aOverridePSNames[ font_it->second->m_nPSName ] = *over;
                 [ #  # ]
    2017                 :            :             }
    2018                 :            :         }
    2019                 :            : 
    2020         [ +  - ]:        114 :         int nFonts = pParser->getFonts();
    2021         [ +  + ]:       4104 :         for( int i = 0; i < nFonts; i++ )
    2022 [ +  - ][ +  - ]:       3990 :             aBuiltinPSNames.insert( m_pAtoms->getAtom( ATOM_PSNAME, pParser->getFont( i ) ) );
         [ +  - ][ +  - ]
                 [ +  - ]
    2023 [ +  - ][ +  - ]:      22458 :         for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
                 [ +  + ]
    2024                 :            :         {
    2025         [ +  - ]:      22344 :             PrintFont* pFont = it->second;
    2026 [ +  - ][ +  + ]:      48222 :             if( it->second->m_eType == fonttype::Builtin &&
         [ +  - ][ +  + ]
    2027 [ +  - ][ +  - ]:      25878 :                 aBuiltinPSNames.find( pFont->m_nPSName ) != aBuiltinPSNames.end() )
         [ +  + ][ +  + ]
           [ #  #  #  # ]
    2028                 :            :             {
    2029                 :       3534 :                 bool bInsert = true;
    2030         [ +  + ]:       3534 :                 if( bUseOverrideMetrics )
    2031                 :            :                 {
    2032                 :            :                     // in override case only use the override fonts, not their counterparts
    2033 [ +  - ][ +  - ]:         62 :                     std::map<int,fontID>::const_iterator over = aOverridePSNames.find( pFont->m_nPSName );
    2034 [ +  - ][ +  - ]:         62 :                     if( over != aOverridePSNames.end() && over->second != it->first )
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
           [ -  +  #  #  
                   #  # ]
    2035                 :         62 :                         bInsert = false;
    2036                 :            :                 }
    2037                 :            :                 else
    2038                 :            :                 {
    2039                 :            :                     // do not insert override fonts in non override case
    2040 [ +  - ][ +  - ]:       3472 :                     if( std::find( m_aOverrideFonts.begin(), m_aOverrideFonts.end(), it->first ) != m_aOverrideFonts.end() )
         [ +  - ][ -  + ]
    2041                 :          0 :                         bInsert = false;
    2042                 :            :                 }
    2043         [ +  - ]:       3534 :                 if( bInsert )
    2044                 :            :                 {
    2045                 :            :                     aBuiltinFonts.insert( BuiltinFontIdentifier(
    2046         [ +  - ]:       3534 :                         m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ),
    2047                 :            :                         pFont->m_eItalic,
    2048                 :            :                         pFont->m_eWeight,
    2049                 :            :                         pFont->m_ePitch,
    2050                 :            :                         pFont->m_aEncoding
    2051         [ +  - ]:       3534 :                         ) );
    2052                 :            :                 }
    2053                 :            :             }
    2054                 :            :         }
    2055 [ +  - ][ +  - ]:      22458 :         for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
                 [ +  + ]
    2056                 :            :         {
    2057         [ +  - ]:      22344 :             PrintFont* pFont = it->second;
    2058 [ +  - ][ +  + ]:      22344 :             if( it->second->m_eType == fonttype::Builtin )
    2059                 :            :             {
    2060 [ +  - ][ +  - ]:       3534 :                 if( aBuiltinPSNames.find( pFont->m_nPSName ) != aBuiltinPSNames.end() )
                 [ +  - ]
    2061                 :            :                 {
    2062                 :       3534 :                     bool bInsert = true;
    2063         [ +  + ]:       3534 :                     if( bUseOverrideMetrics )
    2064                 :            :                     {
    2065                 :            :                         // in override case only use the override fonts, not their counterparts
    2066 [ +  - ][ +  - ]:         62 :                         std::map<int,fontID>::const_iterator over = aOverridePSNames.find( pFont->m_nPSName );
    2067 [ +  - ][ +  - ]:         62 :                         if( over != aOverridePSNames.end() && over->second != it->first )
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
           [ -  +  #  #  
                   #  # ]
    2068                 :         62 :                             bInsert = false;
    2069                 :            :                     }
    2070                 :            :                     else
    2071                 :            :                     {
    2072                 :            :                         // do not insert override fonts in non override case
    2073 [ +  - ][ +  - ]:       3472 :                         if( std::find( m_aOverrideFonts.begin(), m_aOverrideFonts.end(), it->first ) != m_aOverrideFonts.end() )
         [ +  - ][ -  + ]
    2074                 :          0 :                             bInsert = false;
    2075                 :            :                     }
    2076         [ +  - ]:       3534 :                     if( bInsert )
    2077 [ +  - ][ +  - ]:       3534 :                         rFontIDs.push_back( it->first );
    2078                 :            :                 }
    2079                 :            :             }
    2080         [ +  - ]:      37620 :             else if( aBuiltinFonts.find( BuiltinFontIdentifier(
    2081         [ +  - ]:      18810 :                 m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ),
    2082                 :            :                 pFont->m_eItalic,
    2083                 :            :                 pFont->m_eWeight,
    2084                 :            :                 pFont->m_ePitch,
    2085                 :            :                 pFont->m_aEncoding
    2086 [ +  - ][ +  - ]:      56430 :                 ) ) == aBuiltinFonts.end() )
    2087                 :            :             {
    2088 [ +  - ][ +  - ]:      18810 :                 rFontIDs.push_back( it->first );
    2089                 :            :             }
    2090         [ +  - ]:        114 :         }
    2091                 :            :     }
    2092                 :            :     else // no specific printer
    2093                 :            :     {
    2094 [ +  - ][ +  - ]:      41131 :         for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
                 [ +  + ]
    2095 [ +  - ][ +  - ]:      40886 :             rFontIDs.push_back( it->first );
    2096                 :            :     }
    2097                 :        359 : }
    2098                 :            : 
    2099                 :            : // -------------------------------------------------------------------------
    2100                 :            : 
    2101                 :      72100 : void PrintFontManager::fillPrintFontInfo( PrintFont* pFont, FastPrintFontInfo& rInfo ) const
    2102                 :            : {
    2103                 :            :     ::boost::unordered_map< int, FontFamily >::const_iterator style_it =
    2104         [ +  - ]:      72100 :           m_aFamilyTypes.find( pFont->m_nFamilyName );
    2105                 :      72100 :     rInfo.m_eType           = pFont->m_eType;
    2106         [ +  - ]:      72100 :     rInfo.m_aFamilyName     = m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName );
    2107                 :      72100 :     rInfo.m_aStyleName      = pFont->m_aStyleName;
    2108 [ +  - ][ +  - ]:      72100 :     rInfo.m_eFamilyStyle    = style_it != m_aFamilyTypes.end() ? style_it->second : FAMILY_DONTKNOW;
                 [ +  - ]
    2109                 :      72100 :     rInfo.m_eItalic         = pFont->m_eItalic;
    2110                 :      72100 :     rInfo.m_eWidth          = pFont->m_eWidth;
    2111                 :      72100 :     rInfo.m_eWeight         = pFont->m_eWeight;
    2112                 :      72100 :     rInfo.m_ePitch          = pFont->m_ePitch;
    2113                 :      72100 :     rInfo.m_aEncoding       = pFont->m_aEncoding;
    2114                 :            : 
    2115                 :      72100 :     rInfo.m_bEmbeddable  = (pFont->m_eType == fonttype::Type1);
    2116                 :      72100 :     rInfo.m_bSubsettable = (pFont->m_eType == fonttype::TrueType); // TODO: rename to SfntType
    2117                 :            : 
    2118                 :      72100 :     rInfo.m_aAliases.clear();
    2119 [ +  - ][ +  - ]:      77006 :     for( ::std::list< int >::iterator it = pFont->m_aAliases.begin(); it != pFont->m_aAliases.end(); ++it )
                 [ +  + ]
    2120 [ +  - ][ +  - ]:       4906 :         rInfo.m_aAliases.push_back( m_pAtoms->getString( ATOM_FAMILYNAME, *it ) );
                 [ +  - ]
    2121                 :      72100 : }
    2122                 :            : 
    2123                 :            : // -------------------------------------------------------------------------
    2124                 :            : 
    2125                 :        121 : void PrintFontManager::fillPrintFontInfo( PrintFont* pFont, PrintFontInfo& rInfo ) const
    2126                 :            : {
    2127 [ -  + ][ #  # ]:        121 :     if( ( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 ) ||
           [ -  +  #  # ]
                 [ +  - ]
    2128                 :          0 :         ! pFont->m_pMetrics || pFont->m_pMetrics->isEmpty()
    2129                 :            :         )
    2130                 :            :     {
    2131                 :            :         // might be a truetype font not analyzed or type1 without metrics read
    2132         [ -  + ]:        121 :         if( pFont->m_eType == fonttype::Type1 )
    2133         [ #  # ]:          0 :             pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, false );
    2134         [ +  - ]:        121 :         else if( pFont->m_eType == fonttype::TrueType )
    2135                 :        121 :             analyzeTrueTypeFile( pFont );
    2136                 :            :     }
    2137                 :            : 
    2138                 :        121 :     fillPrintFontInfo( pFont, static_cast< FastPrintFontInfo& >( rInfo ) );
    2139                 :            : 
    2140                 :        121 :     rInfo.m_nAscend         = pFont->m_nAscend;
    2141                 :        121 :     rInfo.m_nDescend        = pFont->m_nDescend;
    2142                 :        121 :     rInfo.m_nLeading        = pFont->m_nLeading;
    2143                 :        121 :     rInfo.m_nWidth          = pFont->m_aGlobalMetricX.width < pFont->m_aGlobalMetricY.width ? pFont->m_aGlobalMetricY.width : pFont->m_aGlobalMetricX.width;
    2144                 :        121 : }
    2145                 :            : 
    2146                 :            : // -------------------------------------------------------------------------
    2147                 :            : 
    2148                 :          0 : void PrintFontManager::getFontListWithFastInfo( ::std::list< FastPrintFontInfo >& rFonts, const PPDParser* pParser, bool bUseOverrideMetrics )
    2149                 :            : {
    2150                 :          0 :     rFonts.clear();
    2151         [ #  # ]:          0 :     ::std::list< fontID > aFontList;
    2152         [ #  # ]:          0 :     getFontList( aFontList, pParser, bUseOverrideMetrics );
    2153                 :            : 
    2154         [ #  # ]:          0 :     ::std::list< fontID >::iterator it;
    2155 [ #  # ][ #  # ]:          0 :     for( it = aFontList.begin(); it != aFontList.end(); ++it )
                 [ #  # ]
    2156                 :            :     {
    2157         [ #  # ]:          0 :         FastPrintFontInfo aInfo;
    2158         [ #  # ]:          0 :         aInfo.m_nID = *it;
    2159 [ #  # ][ #  # ]:          0 :         fillPrintFontInfo( getFont( *it ), aInfo );
                 [ #  # ]
    2160         [ #  # ]:          0 :         rFonts.push_back( aInfo );
    2161                 :          0 :     }
    2162                 :          0 : }
    2163                 :            : 
    2164                 :            : // -------------------------------------------------------------------------
    2165                 :            : 
    2166                 :        121 : bool PrintFontManager::getFontInfo( fontID nFontID, PrintFontInfo& rInfo ) const
    2167                 :            : {
    2168                 :        121 :     PrintFont* pFont = getFont( nFontID );
    2169         [ +  - ]:        121 :     if( pFont )
    2170                 :            :     {
    2171                 :        121 :         rInfo.m_nID = nFontID;
    2172                 :        121 :         fillPrintFontInfo( pFont, rInfo );
    2173                 :            :     }
    2174                 :        121 :     return pFont ? true : false;
    2175                 :            : }
    2176                 :            : 
    2177                 :            : // -------------------------------------------------------------------------
    2178                 :            : 
    2179                 :      71979 : bool PrintFontManager::getFontFastInfo( fontID nFontID, FastPrintFontInfo& rInfo ) const
    2180                 :            : {
    2181                 :      71979 :     PrintFont* pFont = getFont( nFontID );
    2182         [ +  - ]:      71979 :     if( pFont )
    2183                 :            :     {
    2184                 :      71979 :         rInfo.m_nID = nFontID;
    2185                 :      71979 :         fillPrintFontInfo( pFont, rInfo );
    2186                 :            :     }
    2187                 :      71979 :     return pFont ? true : false;
    2188                 :            : }
    2189                 :            : 
    2190                 :            : // -------------------------------------------------------------------------
    2191                 :            : 
    2192                 :          0 : bool PrintFontManager::getFontBoundingBox( fontID nFontID, int& xMin, int& yMin, int& xMax, int& yMax )
    2193                 :            : {
    2194                 :          0 :     bool bSuccess = false;
    2195                 :          0 :     PrintFont* pFont = getFont( nFontID );
    2196         [ #  # ]:          0 :     if( pFont )
    2197                 :            :     {
    2198 [ #  # ][ #  # ]:          0 :         if( pFont->m_nXMin == 0 && pFont->m_nYMin == 0 && pFont->m_nXMax == 0 && pFont->m_nYMax == 0 )
         [ #  # ][ #  # ]
    2199                 :            :         {
    2200                 :            :             // might be a truetype font not analyzed or type1 without metrics read
    2201 [ #  # ][ #  # ]:          0 :             if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
    2202         [ #  # ]:          0 :                 pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true );
    2203         [ #  # ]:          0 :             else if( pFont->m_eType == fonttype::TrueType )
    2204                 :          0 :                 analyzeTrueTypeFile( pFont );
    2205                 :            :         }
    2206                 :          0 :         bSuccess = true;
    2207                 :          0 :         xMin = pFont->m_nXMin;
    2208                 :          0 :         yMin = pFont->m_nYMin;
    2209                 :          0 :         xMax = pFont->m_nXMax;
    2210                 :          0 :         yMax = pFont->m_nYMax;
    2211                 :            :     }
    2212                 :          0 :     return bSuccess;
    2213                 :            : }
    2214                 :            : 
    2215                 :            : // -------------------------------------------------------------------------
    2216                 :            : 
    2217                 :      35988 : int PrintFontManager::getFontFaceNumber( fontID nFontID ) const
    2218                 :            : {
    2219                 :      35988 :     int nRet = 0;
    2220                 :      35988 :     PrintFont* pFont = getFont( nFontID );
    2221 [ +  + ][ +  - ]:      35988 :     if( pFont && pFont->m_eType == fonttype::TrueType )
    2222                 :      27413 :         nRet = static_cast< TrueTypeFontFile* >(pFont)->m_nCollectionEntry;
    2223         [ -  + ]:      35988 :     if (nRet < 0)
    2224                 :          0 :         nRet = 0;
    2225                 :      35988 :     return nRet;
    2226                 :            : }
    2227                 :            : 
    2228                 :            : // -------------------------------------------------------------------------
    2229                 :            : 
    2230                 :            : 
    2231                 :      14800 : FontFamily PrintFontManager::matchFamilyName( const ::rtl::OUString& rFamily ) const
    2232                 :            : {
    2233                 :            :     typedef struct {
    2234                 :            :         const char*  mpName;
    2235                 :            :         sal_uInt16   mnLength;
    2236                 :            :         FontFamily   meType;
    2237                 :            :     } family_t;
    2238                 :            : 
    2239                 :            : #define InitializeClass( p, a ) p, sizeof(p) - 1, a
    2240                 :            :     const family_t pFamilyMatch[] =  {
    2241                 :            :         { InitializeClass( "arial",                  FAMILY_SWISS )  },
    2242                 :            :         { InitializeClass( "arioso",                 FAMILY_SCRIPT ) },
    2243                 :            :         { InitializeClass( "avant garde",            FAMILY_SWISS )  },
    2244                 :            :         { InitializeClass( "avantgarde",             FAMILY_SWISS )  },
    2245                 :            :         { InitializeClass( "bembo",                  FAMILY_ROMAN )  },
    2246                 :            :         { InitializeClass( "bookman",                FAMILY_ROMAN )  },
    2247                 :            :         { InitializeClass( "conga",                  FAMILY_ROMAN )  },
    2248                 :            :         { InitializeClass( "courier",                FAMILY_MODERN ) },
    2249                 :            :         { InitializeClass( "curl",                   FAMILY_SCRIPT ) },
    2250                 :            :         { InitializeClass( "fixed",                  FAMILY_MODERN ) },
    2251                 :            :         { InitializeClass( "gill",                   FAMILY_SWISS )  },
    2252                 :            :         { InitializeClass( "helmet",                 FAMILY_MODERN ) },
    2253                 :            :         { InitializeClass( "helvetica",              FAMILY_SWISS )  },
    2254                 :            :         { InitializeClass( "international",          FAMILY_MODERN ) },
    2255                 :            :         { InitializeClass( "lucida",                 FAMILY_SWISS )  },
    2256                 :            :         { InitializeClass( "new century schoolbook", FAMILY_ROMAN )  },
    2257                 :            :         { InitializeClass( "palatino",               FAMILY_ROMAN )  },
    2258                 :            :         { InitializeClass( "roman",                  FAMILY_ROMAN )  },
    2259                 :            :         { InitializeClass( "sans serif",             FAMILY_SWISS )  },
    2260                 :            :         { InitializeClass( "sansserif",              FAMILY_SWISS )  },
    2261                 :            :         { InitializeClass( "serf",                   FAMILY_ROMAN )  },
    2262                 :            :         { InitializeClass( "serif",                  FAMILY_ROMAN )  },
    2263                 :            :         { InitializeClass( "times",                  FAMILY_ROMAN )  },
    2264                 :            :         { InitializeClass( "utopia",                 FAMILY_ROMAN )  },
    2265                 :            :         { InitializeClass( "zapf chancery",          FAMILY_SCRIPT ) },
    2266                 :            :         { InitializeClass( "zapfchancery",           FAMILY_SCRIPT ) }
    2267                 :      14800 :     };
    2268                 :            : 
    2269         [ +  - ]:      14800 :     rtl::OString aFamily = rtl::OUStringToOString( rFamily, RTL_TEXTENCODING_ASCII_US );
    2270                 :      14800 :     sal_uInt32 nLower = 0;
    2271                 :      14800 :     sal_uInt32 nUpper = SAL_N_ELEMENTS(pFamilyMatch);
    2272                 :            : 
    2273         [ +  + ]:      86120 :     while( nLower < nUpper )
    2274                 :            :     {
    2275                 :      72110 :         sal_uInt32 nCurrent = (nLower + nUpper) / 2;
    2276                 :      72110 :         const family_t* pHaystack = pFamilyMatch + nCurrent;
    2277                 :            :         sal_Int32  nComparison =
    2278                 :            :             rtl_str_compareIgnoreAsciiCase_WithLength
    2279                 :            :             (
    2280                 :            :              aFamily.getStr(), aFamily.getLength(),
    2281                 :            :              pHaystack->mpName, pHaystack->mnLength
    2282                 :      72110 :              );
    2283                 :            : 
    2284         [ +  + ]:      72110 :         if( nComparison < 0 )
    2285                 :      45972 :             nUpper = nCurrent;
    2286                 :            :         else
    2287         [ +  + ]:      26138 :             if( nComparison > 0 )
    2288                 :      25348 :                 nLower = nCurrent + 1;
    2289                 :            :             else
    2290                 :        790 :                 return pHaystack->meType;
    2291                 :            :     }
    2292                 :            : 
    2293                 :      14800 :     return FAMILY_DONTKNOW;
    2294                 :            : }
    2295                 :            : 
    2296                 :            : // -------------------------------------------------------------------------
    2297                 :            : 
    2298                 :       2292 : OString PrintFontManager::getAfmFile( PrintFont* pFont ) const
    2299                 :            : {
    2300                 :       2292 :     OString aMetricPath;
    2301         [ +  - ]:       2292 :     if( pFont )
    2302                 :            :     {
    2303      [ +  -  - ]:       2292 :         switch( pFont->m_eType )
    2304                 :            :         {
    2305                 :            :             case fonttype::Type1:
    2306                 :            :             {
    2307                 :       2292 :                 Type1FontFile* pPSFont = static_cast< Type1FontFile* >(pFont);
    2308         [ +  - ]:       2292 :                 aMetricPath = getDirectory( pPSFont->m_nDirectory );
    2309                 :       2292 :                 aMetricPath += "/";
    2310                 :       2292 :                 aMetricPath += pPSFont->m_aMetricFile;
    2311                 :            :             }
    2312                 :       2292 :             break;
    2313                 :            :             case fonttype::Builtin:
    2314                 :            :             {
    2315                 :          0 :                 BuiltinFont* pBuiltinFont = static_cast< BuiltinFont* >(pFont);
    2316         [ #  # ]:          0 :                 aMetricPath = getDirectory( pBuiltinFont->m_nDirectory );
    2317                 :          0 :                 aMetricPath += "/";
    2318                 :          0 :                 aMetricPath += pBuiltinFont->m_aMetricFile;
    2319                 :            :             }
    2320                 :          0 :             break;
    2321                 :       2292 :             default: break;
    2322                 :            :         }
    2323                 :            :     }
    2324                 :       2292 :     return aMetricPath;
    2325                 :            : }
    2326                 :            : 
    2327                 :            : // -------------------------------------------------------------------------
    2328                 :            : 
    2329                 :      59226 : OString PrintFontManager::getFontFile( PrintFont* pFont ) const
    2330                 :            : {
    2331                 :      59226 :     OString aPath;
    2332                 :            : 
    2333 [ +  + ][ +  - ]:      59226 :     if( pFont && pFont->m_eType == fonttype::Type1 )
    2334                 :            :     {
    2335                 :       8575 :         Type1FontFile* pPSFont = static_cast< Type1FontFile* >(pFont);
    2336         [ +  - ]:       8575 :         ::boost::unordered_map< int, OString >::const_iterator it = m_aAtomToDir.find( pPSFont->m_nDirectory );
    2337         [ +  - ]:       8575 :         aPath = it->second;
    2338                 :       8575 :         aPath += "/";
    2339                 :       8575 :         aPath += pPSFont->m_aFontFile;
    2340                 :            :     }
    2341 [ +  - ][ +  - ]:      50651 :     else if( pFont && pFont->m_eType == fonttype::TrueType )
    2342                 :            :     {
    2343                 :      50651 :         TrueTypeFontFile* pTTFont = static_cast< TrueTypeFontFile* >(pFont);
    2344         [ +  - ]:      50651 :         ::boost::unordered_map< int, OString >::const_iterator it = m_aAtomToDir.find( pTTFont->m_nDirectory );
    2345         [ +  - ]:      50651 :         aPath = it->second;
    2346                 :      50651 :         aPath += "/";
    2347                 :      50651 :         aPath += pTTFont->m_aFontFile;
    2348                 :            :     }
    2349                 :      59226 :     return aPath;
    2350                 :            : }
    2351                 :            : 
    2352                 :            : // -------------------------------------------------------------------------
    2353                 :            : 
    2354                 :          0 : const ::rtl::OUString& PrintFontManager::getPSName( fontID nFontID ) const
    2355                 :            : {
    2356                 :          0 :     PrintFont* pFont = getFont( nFontID );
    2357 [ #  # ][ #  # ]:          0 :     if( pFont && pFont->m_nPSName == 0 )
    2358                 :            :     {
    2359         [ #  # ]:          0 :         if( pFont->m_eType == fonttype::TrueType )
    2360                 :          0 :             analyzeTrueTypeFile( pFont );
    2361                 :            :     }
    2362                 :            : 
    2363         [ #  # ]:          0 :     return m_pAtoms->getString( ATOM_PSNAME, pFont ? pFont->m_nPSName : INVALID_ATOM );
    2364                 :            : }
    2365                 :            : 
    2366                 :            : // -------------------------------------------------------------------------
    2367                 :            : 
    2368                 :          0 : int PrintFontManager::getFontAscend( fontID nFontID ) const
    2369                 :            : {
    2370                 :          0 :     PrintFont* pFont = getFont( nFontID );
    2371 [ #  # ][ #  # ]:          0 :     if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
    2372                 :            :     {
    2373                 :            :         // might be a truetype font not yet analyzed
    2374         [ #  # ]:          0 :         if( pFont->m_eType == fonttype::TrueType )
    2375                 :          0 :             analyzeTrueTypeFile( pFont );
    2376 [ #  # ][ #  # ]:          0 :         else if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
    2377         [ #  # ]:          0 :             pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true );
    2378                 :            :     }
    2379                 :          0 :     return pFont->m_nAscend;
    2380                 :            : }
    2381                 :            : 
    2382                 :            : // -------------------------------------------------------------------------
    2383                 :            : 
    2384                 :          0 : int PrintFontManager::getFontDescend( fontID nFontID ) const
    2385                 :            : {
    2386                 :          0 :     PrintFont* pFont = getFont( nFontID );
    2387 [ #  # ][ #  # ]:          0 :     if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
    2388                 :            :     {
    2389                 :            :         // might be a truetype font not yet analyzed
    2390         [ #  # ]:          0 :         if( pFont->m_eType == fonttype::TrueType )
    2391                 :          0 :             analyzeTrueTypeFile( pFont );
    2392 [ #  # ][ #  # ]:          0 :         else if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
    2393         [ #  # ]:          0 :             pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true );
    2394                 :            :     }
    2395                 :          0 :     return pFont->m_nDescend;
    2396                 :            : }
    2397                 :            : 
    2398                 :            : // -------------------------------------------------------------------------
    2399                 :            : 
    2400                 :          0 : void PrintFontManager::hasVerticalSubstitutions( fontID nFontID,
    2401                 :            :     const sal_Unicode* pCharacters, int nCharacters, bool* pHasSubst ) const
    2402                 :            : {
    2403                 :          0 :     PrintFont* pFont = getFont( nFontID );
    2404 [ #  # ][ #  # ]:          0 :     if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
    2405                 :            :     {
    2406                 :            :         // might be a truetype font not yet analyzed
    2407         [ #  # ]:          0 :         if( pFont->m_eType == fonttype::TrueType )
    2408                 :          0 :             analyzeTrueTypeFile( pFont );
    2409                 :            :     }
    2410                 :            : 
    2411         [ #  # ]:          0 :     if( ! pFont->m_bHaveVerticalSubstitutedGlyphs )
    2412                 :          0 :         memset( pHasSubst, 0, sizeof(bool)*nCharacters );
    2413                 :            :     else
    2414                 :            :     {
    2415         [ #  # ]:          0 :         for( int i = 0; i < nCharacters; i++ )
    2416                 :            :         {
    2417                 :          0 :             sal_Unicode code = pCharacters[i];
    2418 [ #  # ][ #  # ]:          0 :             if( ! pFont->m_pMetrics ||
    2419                 :          0 :                 ! ( pFont->m_pMetrics->m_aPages[ code >> 11 ] & ( 1 << ( ( code >> 8 ) & 7 ) ) ) )
    2420         [ #  # ]:          0 :                 pFont->queryMetricPage( code >> 8, m_pAtoms );
    2421         [ #  # ]:          0 :             ::boost::unordered_map< sal_Unicode, bool >::const_iterator it = pFont->m_pMetrics->m_bVerticalSubstitutions.find( code );
    2422         [ #  # ]:          0 :             pHasSubst[i] = it != pFont->m_pMetrics->m_bVerticalSubstitutions.end();
    2423                 :            :         }
    2424                 :            :     }
    2425                 :          0 : }
    2426                 :            : 
    2427                 :            : // -------------------------------------------------------------------------
    2428                 :            : 
    2429                 :         17 : const ::std::list< KernPair >& PrintFontManager::getKernPairs( fontID nFontID, bool bVertical ) const
    2430                 :            : {
    2431 [ +  + ][ +  - ]:         17 :     static ::std::list< KernPair > aEmpty;
         [ +  - ][ #  # ]
    2432                 :            : 
    2433                 :         17 :     PrintFont* pFont = getFont( nFontID );
    2434         [ -  + ]:         17 :     if( ! pFont )
    2435                 :          0 :         return aEmpty;
    2436                 :            : 
    2437 [ -  + ][ #  # ]:         17 :     if( ! pFont->m_pMetrics || ! pFont->m_pMetrics->m_bKernPairsQueried )
    2438                 :         17 :         pFont->queryMetricPage( 0, m_pAtoms );
    2439 [ +  - ][ -  + ]:         17 :     if( ! pFont->m_pMetrics || ! pFont->m_pMetrics->m_bKernPairsQueried )
    2440                 :          0 :         return aEmpty;
    2441         [ -  + ]:         17 :     return bVertical ? pFont->m_pMetrics->m_aYKernPairs : pFont->m_pMetrics->m_aXKernPairs;
    2442                 :            : }
    2443                 :            : 
    2444                 :            : // -------------------------------------------------------------------------
    2445                 :            : 
    2446                 :          0 : bool PrintFontManager::isFontDownloadingAllowed( fontID nFont ) const
    2447                 :            : {
    2448 [ #  # ][ #  # ]:          0 :     static const char* pEnable = getenv( "PSPRINT_ENABLE_TTF_COPYRIGHTAWARENESS" );
    2449                 :          0 :     bool bRet = true;
    2450                 :            : 
    2451 [ #  # ][ #  # ]:          0 :     if( pEnable && *pEnable )
    2452                 :            :     {
    2453                 :          0 :         PrintFont* pFont = getFont( nFont );
    2454 [ #  # ][ #  # ]:          0 :         if( pFont && pFont->m_eType == fonttype::TrueType )
    2455                 :            :         {
    2456                 :          0 :             TrueTypeFontFile* pTTFontFile = static_cast<TrueTypeFontFile*>(pFont);
    2457         [ #  # ]:          0 :             if( pTTFontFile->m_nTypeFlags & TYPEFLAG_INVALID )
    2458                 :            :             {
    2459                 :          0 :                 TrueTypeFont* pTTFont = NULL;
    2460         [ #  # ]:          0 :                 rtl::OString aFile = getFontFile( pFont );
    2461 [ #  # ][ #  # ]:          0 :                 if( OpenTTFontFile( aFile.getStr(), pTTFontFile->m_nCollectionEntry, &pTTFont ) == SF_OK )
    2462                 :            :                 {
    2463                 :            :                     // get type flags
    2464                 :            :                     TTGlobalFontInfo aInfo;
    2465         [ #  # ]:          0 :                     GetTTGlobalFontInfo( pTTFont, & aInfo );
    2466                 :          0 :                     pTTFontFile->m_nTypeFlags = (unsigned int)aInfo.typeFlags;
    2467         [ #  # ]:          0 :                     CloseTTFont( pTTFont );
    2468                 :          0 :                 }
    2469                 :            :             }
    2470                 :            : 
    2471                 :          0 :             unsigned int nCopyrightFlags = pTTFontFile->m_nTypeFlags & TYPEFLAG_COPYRIGHT_MASK;
    2472                 :            : 
    2473                 :            :             // font embedding is allowed if either
    2474                 :            :             //   no restriction at all (bit 1 clear)
    2475                 :            :             //   printing allowed (bit 1 set, bit 2 set )
    2476 [ #  # ][ #  # ]:          0 :             bRet = ! ( nCopyrightFlags & 0x02 ) || ( nCopyrightFlags & 0x04 );
    2477                 :            :         }
    2478                 :            :     }
    2479                 :          0 :     return bRet;
    2480                 :            : }
    2481                 :            : 
    2482                 :            : // -------------------------------------------------------------------------
    2483                 :            : 
    2484                 :          0 : bool PrintFontManager::getMetrics( fontID nFontID, const sal_Unicode* pString, int nLen, CharacterMetric* pArray, bool bVertical ) const
    2485                 :            : {
    2486                 :          0 :     PrintFont* pFont = getFont( nFontID );
    2487         [ #  # ]:          0 :     if( ! pFont )
    2488                 :          0 :         return false;
    2489                 :            : 
    2490 [ #  # ][ #  # ]:          0 :     if( ( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
           [ #  #  #  # ]
                 [ #  # ]
    2491                 :          0 :         || ! pFont->m_pMetrics || pFont->m_pMetrics->isEmpty()
    2492                 :            :         )
    2493                 :            :     {
    2494                 :            :         // might be a font not yet analyzed
    2495 [ #  # ][ #  # ]:          0 :         if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
    2496         [ #  # ]:          0 :             pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, false );
    2497         [ #  # ]:          0 :         else if( pFont->m_eType == fonttype::TrueType )
    2498                 :          0 :             analyzeTrueTypeFile( pFont );
    2499                 :            :     }
    2500                 :            : 
    2501         [ #  # ]:          0 :     for( int i = 0; i < nLen; i++ )
    2502                 :            :     {
    2503 [ #  # ][ #  # ]:          0 :         if( ! pFont->m_pMetrics ||
    2504                 :          0 :             ! ( pFont->m_pMetrics->m_aPages[ pString[i] >> 11 ] & ( 1 << ( ( pString[i] >> 8 ) & 7 ) ) ) )
    2505                 :          0 :             pFont->queryMetricPage( pString[i] >> 8, m_pAtoms );
    2506                 :          0 :         pArray[i].width = pArray[i].height = -1;
    2507         [ #  # ]:          0 :         if( pFont->m_pMetrics )
    2508                 :            :         {
    2509                 :          0 :             int effectiveCode = pString[i];
    2510         [ #  # ]:          0 :             effectiveCode |= bVertical ? 1 << 16 : 0;
    2511                 :            :             ::boost::unordered_map< int, CharacterMetric >::const_iterator it =
    2512         [ #  # ]:          0 :                   pFont->m_pMetrics->m_aMetrics.find( effectiveCode );
    2513                 :            :         // if no vertical metrics are available assume rotated horizontal metrics
    2514 [ #  # ][ #  # ]:          0 :         if( bVertical && (it == pFont->m_pMetrics->m_aMetrics.end()) )
         [ #  # ][ #  # ]
           [ #  #  #  #  
           #  # ][ #  # ]
    2515         [ #  # ]:          0 :                   it = pFont->m_pMetrics->m_aMetrics.find( pString[i] );
    2516                 :            :         // the character metrics are in it->second
    2517 [ #  # ][ #  # ]:          0 :             if( it != pFont->m_pMetrics->m_aMetrics.end() )
    2518         [ #  # ]:          0 :                 pArray[ i ] = it->second;
    2519                 :            :         }
    2520                 :            :     }
    2521                 :            : 
    2522                 :          0 :     return true;
    2523                 :            : }
    2524                 :            : 
    2525                 :            : // -------------------------------------------------------------------------
    2526                 :            : 
    2527                 :          0 : bool PrintFontManager::getMetrics( fontID nFontID, sal_Unicode minCharacter, sal_Unicode maxCharacter, CharacterMetric* pArray, bool bVertical ) const
    2528                 :            : {
    2529                 :            :     OSL_PRECOND(minCharacter <= maxCharacter, "invalid char. range");
    2530         [ #  # ]:          0 :     if (minCharacter > maxCharacter)
    2531                 :          0 :         return false;
    2532                 :            : 
    2533                 :          0 :     PrintFont* pFont = getFont( nFontID );
    2534         [ #  # ]:          0 :     if( ! pFont )
    2535                 :          0 :         return false;
    2536                 :            : 
    2537 [ #  # ][ #  # ]:          0 :     if( ( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
           [ #  #  #  # ]
                 [ #  # ]
    2538                 :          0 :         || ! pFont->m_pMetrics || pFont->m_pMetrics->isEmpty()
    2539                 :            :         )
    2540                 :            :     {
    2541                 :            :         // might be a font not yet analyzed
    2542 [ #  # ][ #  # ]:          0 :         if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
    2543         [ #  # ]:          0 :             pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, false );
    2544         [ #  # ]:          0 :         else if( pFont->m_eType == fonttype::TrueType )
    2545                 :          0 :             analyzeTrueTypeFile( pFont );
    2546                 :            :     }
    2547                 :            : 
    2548                 :          0 :     sal_Unicode code = minCharacter;
    2549         [ #  # ]:          0 :     do
    2550                 :            :     {
    2551 [ #  # ][ #  # ]:          0 :         if( ! pFont->m_pMetrics ||
    2552                 :          0 :             ! ( pFont->m_pMetrics->m_aPages[ code >> 11 ] & ( 1 << ( ( code >> 8 ) & 7 ) ) ) )
    2553                 :          0 :             pFont->queryMetricPage( code >> 8, m_pAtoms );
    2554                 :          0 :         pArray[ code - minCharacter ].width     = -1;
    2555                 :          0 :         pArray[ code - minCharacter ].height    = -1;
    2556         [ #  # ]:          0 :         if( pFont->m_pMetrics )
    2557                 :            :         {
    2558                 :          0 :             int effectiveCode = code;
    2559         [ #  # ]:          0 :             effectiveCode |= bVertical ? 1 << 16 : 0;
    2560                 :            :             ::boost::unordered_map< int, CharacterMetric >::const_iterator it =
    2561         [ #  # ]:          0 :                   pFont->m_pMetrics->m_aMetrics.find( effectiveCode );
    2562                 :            :             // if no vertical metrics are available assume rotated horizontal metrics
    2563 [ #  # ][ #  # ]:          0 :             if( bVertical && (it == pFont->m_pMetrics->m_aMetrics.end()) )
         [ #  # ][ #  # ]
           [ #  #  #  #  
           #  # ][ #  # ]
    2564         [ #  # ]:          0 :                 it = pFont->m_pMetrics->m_aMetrics.find( code );
    2565                 :            :             // the character metrics are in it->second
    2566 [ #  # ][ #  # ]:          0 :             if( it != pFont->m_pMetrics->m_aMetrics.end() )
    2567         [ #  # ]:          0 :                 pArray[ code - minCharacter ] = it->second;
    2568                 :            :         }
    2569                 :            :     } while( code++ != maxCharacter );
    2570                 :            : 
    2571                 :          0 :     return true;
    2572                 :            : }
    2573                 :            : 
    2574                 :            : // -------------------------------------------------------------------------
    2575                 :            : 
    2576                 :            : // TODO: move most of this stuff into the central font-subsetting code
    2577                 :          0 : bool PrintFontManager::createFontSubset(
    2578                 :            :                                         FontSubsetInfo& rInfo,
    2579                 :            :                                         fontID nFont,
    2580                 :            :                                         const OUString& rOutFile,
    2581                 :            :                                         sal_Int32* pGlyphIDs,
    2582                 :            :                                         sal_uInt8* pNewEncoding,
    2583                 :            :                                         sal_Int32* pWidths,
    2584                 :            :                                         int nGlyphs,
    2585                 :            :                                         bool bVertical
    2586                 :            :                                         )
    2587                 :            : {
    2588         [ #  # ]:          0 :     PrintFont* pFont = getFont( nFont );
    2589         [ #  # ]:          0 :     if( !pFont )
    2590                 :          0 :         return false;
    2591                 :            : 
    2592      [ #  #  # ]:          0 :     switch( pFont->m_eType )
    2593                 :            :     {
    2594                 :          0 :         case psp::fonttype::TrueType: rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; break;
    2595                 :          0 :         case psp::fonttype::Type1: rInfo.m_nFontType = FontSubsetInfo::ANY_TYPE1; break;
    2596                 :            :         default:
    2597                 :          0 :             return false;
    2598                 :            :     }
    2599                 :            :     // TODO: remove when Type1 subsetting gets implemented
    2600         [ #  # ]:          0 :     if( pFont->m_eType != fonttype::TrueType )
    2601                 :          0 :         return false;
    2602                 :            : 
    2603                 :            :     // reshuffle array of requested glyphs to make sure glyph0==notdef
    2604                 :            :     sal_uInt8  pEnc[256];
    2605                 :            :     sal_uInt16 pGID[256];
    2606                 :            :     sal_uInt8  pOldIndex[256];
    2607                 :          0 :     memset( pEnc, 0, sizeof( pEnc ) );
    2608                 :          0 :     memset( pGID, 0, sizeof( pGID ) );
    2609                 :          0 :     memset( pOldIndex, 0, sizeof( pOldIndex ) );
    2610         [ #  # ]:          0 :     if( nGlyphs > 256 )
    2611                 :          0 :         return false;
    2612                 :          0 :     int nChar = 1;
    2613         [ #  # ]:          0 :     for( int i = 0; i < nGlyphs; i++ )
    2614                 :            :     {
    2615         [ #  # ]:          0 :         if( pNewEncoding[i] == 0 )
    2616                 :            :         {
    2617                 :          0 :             pOldIndex[ 0 ] = i;
    2618                 :            :         }
    2619                 :            :         else
    2620                 :            :         {
    2621                 :            :             DBG_ASSERT( !(pGlyphIDs[i] & 0x007f0000), "overlong glyph id" );
    2622                 :            :             DBG_ASSERT( (int)pNewEncoding[i] < nGlyphs, "encoding wrong" );
    2623                 :            :             DBG_ASSERT( pEnc[pNewEncoding[i]] == 0 && pGID[pNewEncoding[i]] == 0, "duplicate encoded glyph" );
    2624                 :          0 :             pEnc[ pNewEncoding[i] ] = pNewEncoding[i];
    2625                 :          0 :             pGID[ pNewEncoding[i] ] = (sal_uInt16)pGlyphIDs[ i ];
    2626                 :          0 :             pOldIndex[ pNewEncoding[i] ] = i;
    2627                 :          0 :             nChar++;
    2628                 :            :         }
    2629                 :            :     }
    2630                 :          0 :     nGlyphs = nChar; // either input value or increased by one
    2631                 :            : 
    2632                 :            :     // prepare system name for read access for subset source file
    2633                 :            :     // TODO: since this file is usually already mmapped there is no need to open it again
    2634         [ #  # ]:          0 :     const rtl::OString aFromFile = getFontFile( pFont );
    2635                 :            : 
    2636                 :          0 :     TrueTypeFont* pTTFont = NULL; // TODO: rename to SfntFont
    2637                 :          0 :     TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont);
    2638 [ #  # ][ #  # ]:          0 :     if( OpenTTFontFile( aFromFile.getStr(), pTTFontFile->m_nCollectionEntry, &pTTFont ) != SF_OK )
    2639                 :          0 :         return false;
    2640                 :            : 
    2641                 :            :     // prepare system name for write access for subset file target
    2642                 :          0 :     OUString aSysPath;
    2643 [ #  # ][ #  # ]:          0 :     if( osl_File_E_None != osl_getSystemPathFromFileURL( rOutFile.pData, &aSysPath.pData ) )
    2644                 :          0 :         return false;
    2645         [ #  # ]:          0 :     const rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
    2646         [ #  # ]:          0 :     const rtl::OString aToFile( OUStringToOString( aSysPath, aEncoding ) );
    2647                 :            : 
    2648                 :            :     // do CFF subsetting if possible
    2649                 :          0 :     int nCffLength = 0;
    2650                 :          0 :     const sal_uInt8* pCffBytes = NULL;
    2651 [ #  # ][ #  # ]:          0 :     if( GetSfntTable( pTTFont, O_CFF, &pCffBytes, &nCffLength ) )
    2652                 :            :     {
    2653         [ #  # ]:          0 :         rInfo.LoadFont( FontSubsetInfo::CFF_FONT, pCffBytes, nCffLength );
    2654                 :            : #if 1 // TODO: remove 16bit->long conversion when related methods handle non-16bit glyphids
    2655                 :            :         long aRequestedGlyphs[256];
    2656         [ #  # ]:          0 :         for( int i = 0; i < nGlyphs; ++i )
    2657                 :          0 :             aRequestedGlyphs[i] = pGID[i];
    2658                 :            : #endif
    2659                 :            :         // create subset file at requested path
    2660         [ #  # ]:          0 :         FILE* pOutFile = fopen( aToFile.getStr(), "wb" );
    2661                 :            :         // create font subset
    2662                 :          0 :         const char* pGlyphSetName = NULL; // TODO: better name?
    2663                 :            :         const bool bOK = rInfo.CreateFontSubset(
    2664                 :            :             FontSubsetInfo::TYPE1_PFB,
    2665                 :            :             pOutFile, pGlyphSetName,
    2666         [ #  # ]:          0 :             aRequestedGlyphs, pEnc, nGlyphs, pWidths );
    2667         [ #  # ]:          0 :         fclose( pOutFile );
    2668                 :            :         // cleanup before early return
    2669         [ #  # ]:          0 :         CloseTTFont( pTTFont );
    2670                 :          0 :         return bOK;
    2671                 :            :     }
    2672                 :            : 
    2673                 :            :     // do TTF->Type42 or Type3 subsetting
    2674                 :            :     // fill in font info
    2675         [ #  # ]:          0 :     psp::PrintFontInfo aFontInfo;
    2676 [ #  # ][ #  # ]:          0 :     if( ! getFontInfo( nFont, aFontInfo ) )
    2677                 :          0 :         return false;
    2678                 :            : 
    2679                 :          0 :     rInfo.m_nAscent     = aFontInfo.m_nAscend;
    2680                 :          0 :     rInfo.m_nDescent    = aFontInfo.m_nDescend;
    2681 [ #  # ][ #  # ]:          0 :     rInfo.m_aPSName     = getPSName( nFont );
    2682                 :            : 
    2683                 :            :     int xMin, yMin, xMax, yMax;
    2684         [ #  # ]:          0 :     getFontBoundingBox( nFont, xMin, yMin, xMax, yMax );
    2685         [ #  # ]:          0 :     rInfo.m_aFontBBox   = Rectangle( Point( xMin, yMin ), Size( xMax-xMin, yMax-yMin ) );
    2686                 :          0 :     rInfo.m_nCapHeight  = yMax; // Well ...
    2687                 :            : 
    2688                 :            :     // fill in glyph advance widths
    2689                 :            :     TTSimpleGlyphMetrics* pMetrics = GetTTSimpleGlyphMetrics( pTTFont,
    2690                 :            :                                                               pGID,
    2691                 :            :                                                               nGlyphs,
    2692 [ #  # ][ #  # ]:          0 :                                                               bVertical ? 1 : 0 );
    2693         [ #  # ]:          0 :     if( pMetrics )
    2694                 :            :     {
    2695         [ #  # ]:          0 :         for( int i = 0; i < nGlyphs; i++ )
    2696                 :          0 :             pWidths[pOldIndex[i]] = pMetrics[i].adv;
    2697                 :          0 :         free( pMetrics );
    2698                 :            :     }
    2699                 :            :     else
    2700                 :            :     {
    2701         [ #  # ]:          0 :         CloseTTFont( pTTFont );
    2702                 :          0 :         return false;
    2703                 :            :     }
    2704                 :            : 
    2705                 :            :     bool bSuccess = ( SF_OK == CreateTTFromTTGlyphs( pTTFont,
    2706                 :            :                                                      aToFile.getStr(),
    2707                 :            :                                                      pGID,
    2708                 :            :                                                      pEnc,
    2709                 :            :                                                      nGlyphs,
    2710                 :            :                                                      0,
    2711                 :            :                                                      NULL,
    2712         [ #  # ]:          0 :                                                      0 ) );
    2713         [ #  # ]:          0 :     CloseTTFont( pTTFont );
    2714                 :            : 
    2715                 :          0 :     return bSuccess;
    2716                 :            : }
    2717                 :            : 
    2718                 :          0 : void PrintFontManager::getGlyphWidths( fontID nFont,
    2719                 :            :                                        bool bVertical,
    2720                 :            :                                        std::vector< sal_Int32 >& rWidths,
    2721                 :            :                                        std::map< sal_Unicode, sal_uInt32 >& rUnicodeEnc )
    2722                 :            : {
    2723                 :          0 :     PrintFont* pFont = getFont( nFont );
    2724 [ #  # ][ #  # ]:          0 :     if( !pFont ||
                 [ #  # ]
    2725                 :            :         (pFont->m_eType != fonttype::TrueType && pFont->m_eType != fonttype::Type1) )
    2726                 :          0 :         return;
    2727         [ #  # ]:          0 :     if( pFont->m_eType == fonttype::TrueType )
    2728                 :            :     {
    2729                 :          0 :         TrueTypeFont* pTTFont = NULL;
    2730                 :          0 :         TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont);
    2731         [ #  # ]:          0 :         rtl::OString aFromFile = getFontFile( pFont );
    2732 [ #  # ][ #  # ]:          0 :         if( OpenTTFontFile( aFromFile.getStr(), pTTFontFile->m_nCollectionEntry, &pTTFont ) != SF_OK )
    2733                 :            :             return;
    2734         [ #  # ]:          0 :         int nGlyphs = GetTTGlyphCount( pTTFont );
    2735         [ #  # ]:          0 :         if( nGlyphs > 0 )
    2736                 :            :         {
    2737         [ #  # ]:          0 :             rWidths.resize(nGlyphs);
    2738         [ #  # ]:          0 :             std::vector<sal_uInt16> aGlyphIds(nGlyphs);
    2739         [ #  # ]:          0 :             for( int i = 0; i < nGlyphs; i++ )
    2740         [ #  # ]:          0 :                 aGlyphIds[i] = sal_uInt16(i);
    2741                 :            :             TTSimpleGlyphMetrics* pMetrics = GetTTSimpleGlyphMetrics( pTTFont,
    2742         [ #  # ]:          0 :                                                                       &aGlyphIds[0],
    2743                 :            :                                                                       nGlyphs,
    2744 [ #  # ][ #  # ]:          0 :                                                                       bVertical ? 1 : 0 );
    2745         [ #  # ]:          0 :             if( pMetrics )
    2746                 :            :             {
    2747         [ #  # ]:          0 :                 for( int i = 0; i< nGlyphs; i++ )
    2748         [ #  # ]:          0 :                     rWidths[i] = pMetrics[i].adv;
    2749                 :          0 :                 free( pMetrics );
    2750                 :          0 :                 rUnicodeEnc.clear();
    2751                 :            :             }
    2752                 :            : 
    2753                 :            :             // fill the unicode map
    2754                 :            :             // TODO: isn't this map already available elsewhere in the fontmanager?
    2755                 :          0 :             const sal_uInt8* pCmapData = NULL;
    2756                 :          0 :             int nCmapSize = 0;
    2757 [ #  # ][ #  # ]:          0 :             if( GetSfntTable( pTTFont, O_cmap, &pCmapData, &nCmapSize ) )
    2758                 :            :             {
    2759         [ #  # ]:          0 :                 CmapResult aCmapResult;
    2760 [ #  # ][ #  # ]:          0 :                 if( ParseCMAP( pCmapData, nCmapSize, aCmapResult ) )
    2761                 :            :                 {
    2762         [ #  # ]:          0 :                     const ImplFontCharMap aCharMap( aCmapResult );
    2763                 :          0 :                     for( sal_uInt32 cOld = 0;;)
    2764                 :            :                     {
    2765                 :            :                         // get next unicode covered by font
    2766         [ #  # ]:          0 :                         const sal_uInt32 c = aCharMap.GetNextChar( cOld );
    2767         [ #  # ]:          0 :                         if( c == cOld )
    2768                 :          0 :                             break;
    2769                 :          0 :                         cOld = c;
    2770                 :            : #if 1 // TODO: remove when sal_Unicode covers all of unicode
    2771         [ #  # ]:          0 :                         if( c > (sal_Unicode)~0 )
    2772                 :          0 :                             break;
    2773                 :            : #endif
    2774                 :            :                         // get the matching glyph index
    2775         [ #  # ]:          0 :                         const sal_uInt32 nGlyphId = aCharMap.GetGlyphIndex( c );
    2776                 :            :                         // update the requested map
    2777         [ #  # ]:          0 :                         rUnicodeEnc[ (sal_Unicode)c ] = nGlyphId;
    2778         [ #  # ]:          0 :                     }
    2779                 :            :                 }
    2780                 :          0 :             }
    2781                 :            :         }
    2782 [ #  # ][ #  # ]:          0 :         CloseTTFont( pTTFont );
    2783                 :            :     }
    2784         [ #  # ]:          0 :     else if( pFont->m_eType == fonttype::Type1 )
    2785                 :            :     {
    2786         [ #  # ]:          0 :         if( ! pFont->m_aEncodingVector.size() )
    2787         [ #  # ]:          0 :             pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, true, true );
    2788         [ #  # ]:          0 :         if( pFont->m_pMetrics )
    2789                 :            :         {
    2790                 :          0 :             rUnicodeEnc.clear();
    2791                 :          0 :             rWidths.clear();
    2792                 :          0 :             rWidths.reserve( pFont->m_pMetrics->m_aMetrics.size() );
    2793         [ #  # ]:          0 :             for( boost::unordered_map< int, CharacterMetric >::const_iterator it =
    2794         [ #  # ]:          0 :                  pFont->m_pMetrics->m_aMetrics.begin();
    2795         [ #  # ]:          0 :                  it != pFont->m_pMetrics->m_aMetrics.end(); ++it )
    2796                 :            :             {
    2797 [ #  # ][ #  # ]:          0 :                 if( (it->first & 0x00010000) == 0 || bVertical )
         [ #  # ][ #  # ]
    2798                 :            :                 {
    2799 [ #  # ][ #  # ]:          0 :                     rUnicodeEnc[ sal_Unicode(it->first & 0x0000ffff) ] = sal_uInt32(rWidths.size());
    2800 [ #  # ][ #  # ]:          0 :                     rWidths.push_back( it->second.width );
    2801                 :            :                 }
    2802                 :            :             }
    2803                 :            :         }
    2804                 :            :     }
    2805                 :            : }
    2806                 :            : 
    2807                 :            : // -------------------------------------------------------------------------
    2808                 :            : 
    2809                 :          0 : const std::map< sal_Unicode, sal_Int32 >* PrintFontManager::getEncodingMap( fontID nFont, const std::map< sal_Unicode, rtl::OString >** pNonEncoded ) const
    2810                 :            : {
    2811                 :          0 :     PrintFont* pFont = getFont( nFont );
    2812 [ #  # ][ #  # ]:          0 :     if( !pFont ||
                 [ #  # ]
    2813                 :            :         (pFont->m_eType != fonttype::Type1 && pFont->m_eType != fonttype::Builtin)
    2814                 :            :         )
    2815                 :          0 :         return NULL;
    2816                 :            : 
    2817         [ #  # ]:          0 :     if( ! pFont->m_aEncodingVector.size() )
    2818         [ #  # ]:          0 :         pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, true, true );
    2819                 :            : 
    2820         [ #  # ]:          0 :     if( pNonEncoded )
    2821         [ #  # ]:          0 :         *pNonEncoded = pFont->m_aNonEncoded.size() ? &pFont->m_aNonEncoded : NULL;
    2822                 :            : 
    2823         [ #  # ]:          0 :     return pFont->m_aEncodingVector.size() ? &pFont->m_aEncodingVector : NULL;
    2824                 :            : }
    2825                 :            : 
    2826                 :            : // -------------------------------------------------------------------------
    2827                 :            : 
    2828                 :          0 : std::list< OString > PrintFontManager::getAdobeNameFromUnicode( sal_Unicode aChar ) const
    2829                 :            : {
    2830                 :            :     std::pair< boost::unordered_multimap< sal_Unicode, rtl::OString >::const_iterator,
    2831                 :            :         boost::unordered_multimap< sal_Unicode, rtl::OString >::const_iterator > range
    2832         [ #  # ]:          0 :         =  m_aUnicodeToAdobename.equal_range( aChar );
    2833                 :            : 
    2834         [ #  # ]:          0 :     std::list< OString > aRet;
    2835         [ #  # ]:          0 :     for( ; range.first != range.second; ++range.first )
    2836 [ #  # ][ #  # ]:          0 :         aRet.push_back( range.first->second );
    2837                 :            : 
    2838 [ #  # ][ #  # ]:          0 :     if( aRet.begin() == aRet.end() && aChar != 0 )
         [ #  # ][ #  # ]
                 [ #  # ]
    2839                 :            :     {
    2840                 :            :         sal_Char aBuf[8];
    2841                 :          0 :         sal_Int32 nChars = snprintf( (char*)aBuf, sizeof( aBuf ), "uni%.4hX", aChar );
    2842         [ #  # ]:          0 :         aRet.push_back( OString( aBuf, nChars ) );
    2843                 :            :     }
    2844                 :            : 
    2845                 :          0 :     return aRet;
    2846                 :            : }
    2847                 :            : 
    2848                 :            : // -------------------------------------------------------------------------
    2849                 :       4410 : std::list< sal_Unicode >  PrintFontManager::getUnicodeFromAdobeName( const rtl::OString& rName ) const
    2850                 :            : {
    2851                 :            :     std::pair< boost::unordered_multimap< rtl::OString, sal_Unicode, rtl::OStringHash >::const_iterator,
    2852                 :            :         boost::unordered_multimap< rtl::OString, sal_Unicode, rtl::OStringHash >::const_iterator > range
    2853         [ +  - ]:       4410 :         =  m_aAdobenameToUnicode.equal_range( rName );
    2854                 :            : 
    2855         [ +  - ]:       4410 :     std::list< sal_Unicode > aRet;
    2856         [ +  + ]:       8132 :     for( ; range.first != range.second; ++range.first )
    2857 [ +  - ][ +  - ]:       3722 :         aRet.push_back( range.first->second );
    2858                 :            : 
    2859 [ +  - ][ +  + ]:       4410 :     if( aRet.begin() == aRet.end() )
    2860                 :            :     {
    2861 [ +  - ][ +  - ]:        776 :         if( rName.getLength() == 7 && rName.indexOf( "uni" ) == 0 )
                 [ +  - ]
    2862                 :            :         {
    2863                 :        776 :             sal_Unicode aCode = (sal_Unicode)rName.copy( 3 ).toInt32( 16 );
    2864         [ +  - ]:       4410 :             aRet.push_back( aCode );
    2865                 :            :         }
    2866                 :            :     }
    2867                 :            : 
    2868                 :       4410 :     return aRet;
    2869                 :            : }
    2870                 :            : 
    2871                 :            : // -------------------------------------------------------------------------
    2872                 :            : namespace
    2873                 :            : {
    2874                 :          0 :     OUString getString( const Any& rAny )
    2875                 :            :     {
    2876                 :          0 :         OUString aStr;
    2877                 :          0 :         rAny >>= aStr;
    2878                 :          0 :         return aStr;
    2879                 :            :     }
    2880                 :          0 :     bool getBool( const Any& rAny )
    2881                 :            :     {
    2882                 :          0 :         sal_Bool bBool = sal_False;
    2883                 :          0 :         rAny >>= bBool;
    2884                 :          0 :         return static_cast<bool>(bBool);
    2885                 :            :     }
    2886                 :          0 :     sal_Int32 getInt( const Any& rAny )
    2887                 :            :     {
    2888                 :          0 :         sal_Int32 n = 0;
    2889                 :          0 :         rAny >>= n;
    2890                 :          0 :         return n;
    2891                 :            :     }
    2892                 :            : }
    2893                 :          2 : bool PrintFontManager::readOverrideMetrics()
    2894                 :            : {
    2895         [ -  + ]:          2 :     if( ! m_aOverrideFonts.empty() )
    2896                 :          0 :         return false;
    2897                 :            : 
    2898         [ +  - ]:          2 :     css::uno::Reference< XMultiServiceFactory > xFact( comphelper::getProcessServiceFactory() );
    2899         [ -  + ]:          2 :     if( !xFact.is() )
    2900                 :          0 :         return false;
    2901                 :            :     css::uno::Reference< XMaterialHolder > xMat(
    2902         [ +  - ]:          2 :                 xFact->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.psprint.CompatMetricOverride" ) ) ),
    2903 [ +  - ][ +  - ]:          2 :                 UNO_QUERY );
                 [ +  - ]
    2904         [ +  - ]:          2 :     if( !xMat.is() )
    2905                 :          2 :         return false;
    2906                 :            : 
    2907 [ #  # ][ #  # ]:          0 :     Any aAny( xMat->getMaterial() );
    2908         [ #  # ]:          0 :     Sequence< Any > aOverrideFonts;
    2909 [ #  # ][ #  # ]:          0 :     if( ! (aAny >>= aOverrideFonts ) )
    2910                 :          0 :         return false;
    2911                 :          0 :     sal_Int32 nFonts = aOverrideFonts.getLength();
    2912         [ #  # ]:          0 :     for( sal_Int32 i = 0; i < nFonts; i++ )
    2913                 :            :     {
    2914         [ #  # ]:          0 :         Sequence< NamedValue > aMetrics;
    2915 [ #  # ][ #  # ]:          0 :         if( ! (aOverrideFonts.getConstArray()[i] >>= aMetrics) )
    2916                 :          0 :             continue;
    2917 [ #  # ][ #  # ]:          0 :         BuiltinFont* pFont = new BuiltinFont();
    2918                 :          0 :         pFont->m_nDirectory = 0;
    2919                 :          0 :         pFont->m_bUserOverride = false;
    2920 [ #  # ][ #  # ]:          0 :         pFont->m_pMetrics = new PrintFontMetrics;
    2921                 :          0 :         memset( pFont->m_pMetrics->m_aPages, 0xff, sizeof( pFont->m_pMetrics->m_aPages ) );
    2922                 :          0 :         pFont->m_pMetrics->m_bKernPairsQueried = true;
    2923                 :          0 :         sal_Int32 nProps = aMetrics.getLength();
    2924                 :          0 :         const NamedValue* pProps = aMetrics.getConstArray();
    2925         [ #  # ]:          0 :         for( sal_Int32 n = 0; n < nProps; n++ )
    2926                 :            :         {
    2927         [ #  # ]:          0 :             if ( pProps[n].Name == "FamilyName" )
    2928                 :            :                 pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME,
    2929                 :          0 :                                                           getString(pProps[n].Value),
    2930         [ #  # ]:          0 :                                                           sal_True );
    2931         [ #  # ]:          0 :             else if ( pProps[n].Name == "PSName" )
    2932                 :            :                 pFont->m_nPSName = m_pAtoms->getAtom( ATOM_PSNAME,
    2933                 :          0 :                                                       getString(pProps[n].Value),
    2934         [ #  # ]:          0 :                                                       sal_True );
    2935         [ #  # ]:          0 :             else if ( pProps[n].Name == "StyleName" )
    2936                 :          0 :                 pFont->m_aStyleName = getString(pProps[n].Value);
    2937         [ #  # ]:          0 :             else if ( pProps[n].Name == "Italic" )
    2938                 :          0 :                 pFont->m_eItalic = static_cast<FontItalic>(getInt(pProps[n].Value));
    2939         [ #  # ]:          0 :             else if ( pProps[n].Name == "Width" )
    2940                 :          0 :                 pFont->m_eWidth = static_cast<FontWidth>(getInt(pProps[n].Value));
    2941         [ #  # ]:          0 :             else if ( pProps[n].Name == "Weight" )
    2942                 :          0 :                 pFont->m_eWeight = static_cast<FontWeight>(getInt(pProps[n].Value));
    2943         [ #  # ]:          0 :             else if ( pProps[n].Name == "Pitch" )
    2944                 :          0 :                 pFont->m_ePitch = static_cast<FontPitch>(getInt(pProps[n].Value));
    2945         [ #  # ]:          0 :             else if ( pProps[n].Name == "Encoding" )
    2946                 :          0 :                 pFont->m_aEncoding = static_cast<rtl_TextEncoding>(getInt(pProps[n].Value));
    2947         [ #  # ]:          0 :             else if ( pProps[n].Name == "FontEncodingOnly" )
    2948                 :          0 :                 pFont->m_bFontEncodingOnly = getBool(pProps[n].Value);
    2949         [ #  # ]:          0 :             else if ( pProps[n].Name == "GlobalMetricXWidth" )
    2950                 :          0 :                 pFont->m_aGlobalMetricX.width = getInt(pProps[n].Value);
    2951         [ #  # ]:          0 :             else if ( pProps[n].Name == "GlobalMetricXHeight" )
    2952                 :          0 :                 pFont->m_aGlobalMetricX.height = getInt(pProps[n].Value);
    2953         [ #  # ]:          0 :             else if ( pProps[n].Name == "GlobalMetricYWidth" )
    2954                 :          0 :                 pFont->m_aGlobalMetricY.width = getInt(pProps[n].Value);
    2955         [ #  # ]:          0 :             else if ( pProps[n].Name == "GlobalMetricYHeight" )
    2956                 :          0 :                 pFont->m_aGlobalMetricY.height = getInt(pProps[n].Value);
    2957         [ #  # ]:          0 :             else if ( pProps[n].Name == "Ascend" )
    2958                 :          0 :                 pFont->m_nAscend = getInt(pProps[n].Value);
    2959         [ #  # ]:          0 :             else if ( pProps[n].Name == "Descend" )
    2960                 :          0 :                 pFont->m_nDescend = getInt(pProps[n].Value);
    2961         [ #  # ]:          0 :             else if ( pProps[n].Name == "Leading" )
    2962                 :          0 :                 pFont->m_nLeading = getInt(pProps[n].Value);
    2963         [ #  # ]:          0 :             else if ( pProps[n].Name == "XMin" )
    2964                 :          0 :                 pFont->m_nXMin = getInt(pProps[n].Value);
    2965         [ #  # ]:          0 :             else if ( pProps[n].Name == "YMin" )
    2966                 :          0 :                 pFont->m_nYMin = getInt(pProps[n].Value);
    2967         [ #  # ]:          0 :             else if ( pProps[n].Name == "XMax" )
    2968                 :          0 :                 pFont->m_nXMax = getInt(pProps[n].Value);
    2969         [ #  # ]:          0 :             else if ( pProps[n].Name == "YMax" )
    2970                 :          0 :                 pFont->m_nYMax = getInt(pProps[n].Value);
    2971         [ #  # ]:          0 :             else if ( pProps[n].Name == "VerticalSubstitutes" )
    2972                 :          0 :                 pFont->m_bHaveVerticalSubstitutedGlyphs = getBool(pProps[n].Value);
    2973         [ #  # ]:          0 :             else if ( pProps[n].Name == "EncodingVector" )
    2974                 :            :             {
    2975         [ #  # ]:          0 :                 Sequence< NamedValue > aEncoding;
    2976         [ #  # ]:          0 :                 pProps[n].Value >>= aEncoding;
    2977                 :          0 :                 sal_Int32 nEnc = aEncoding.getLength();
    2978                 :          0 :                 const NamedValue* pEnc = aEncoding.getConstArray();
    2979         [ #  # ]:          0 :                 for( sal_Int32 m = 0; m < nEnc; m++ )
    2980                 :            :                 {
    2981                 :          0 :                     sal_Unicode cCode = *pEnc[m].Name.getStr();
    2982                 :          0 :                     sal_Int32 nGlyph = getInt(pEnc[m].Value);
    2983         [ #  # ]:          0 :                     pFont->m_aEncodingVector[ cCode ] = nGlyph;
    2984         [ #  # ]:          0 :                 }
    2985                 :            :             }
    2986         [ #  # ]:          0 :             else if ( pProps[n].Name == "NonEncoded" )
    2987                 :            :             {
    2988         [ #  # ]:          0 :                 Sequence< NamedValue > aEncoding;
    2989         [ #  # ]:          0 :                 pProps[n].Value >>= aEncoding;
    2990                 :          0 :                 sal_Int32 nEnc = aEncoding.getLength();
    2991                 :          0 :                 const NamedValue* pEnc = aEncoding.getConstArray();
    2992         [ #  # ]:          0 :                 for( sal_Int32 m = 0; m < nEnc; m++ )
    2993                 :            :                 {
    2994                 :          0 :                     sal_Unicode cCode = *pEnc[m].Name.getStr();
    2995                 :          0 :                     OUString aGlyphName( getString(pEnc[m].Value) );
    2996 [ #  # ][ #  # ]:          0 :                     pFont->m_aNonEncoded[ cCode ] = OUStringToOString(aGlyphName,RTL_TEXTENCODING_ASCII_US);
    2997         [ #  # ]:          0 :                 }
    2998                 :            :             }
    2999         [ #  # ]:          0 :             else if ( pProps[n].Name == "CharacterMetrics" )
    3000                 :            :             {
    3001                 :            :                 // fill pFont->m_pMetrics->m_aMetrics
    3002                 :            :                 // expect triples of int: int -> CharacterMetric.{ width, height }
    3003         [ #  # ]:          0 :                 Sequence< sal_Int32 > aSeq;
    3004         [ #  # ]:          0 :                 pProps[n].Value >>= aSeq;
    3005                 :          0 :                 sal_Int32 nInts = aSeq.getLength();
    3006                 :          0 :                 const sal_Int32* pInts = aSeq.getConstArray();
    3007         [ #  # ]:          0 :                 for( sal_Int32 m = 0; m < nInts; m+=3 )
    3008                 :            :                 {
    3009         [ #  # ]:          0 :                     pFont->m_pMetrics->m_aMetrics[ pInts[m] ].width = static_cast<short int>(pInts[m+1]);
    3010         [ #  # ]:          0 :                     pFont->m_pMetrics->m_aMetrics[ pInts[m] ].height = static_cast<short int>(pInts[m+2]);
    3011         [ #  # ]:          0 :                 }
    3012                 :            :             }
    3013         [ #  # ]:          0 :             else if ( pProps[n].Name == "XKernPairs" )
    3014                 :            :             {
    3015                 :            :                 // fill pFont->m_pMetrics->m_aXKernPairs
    3016                 :            :                 // expection name: <unicode1><unicode2> value: ((height << 16)| width)
    3017         [ #  # ]:          0 :                 Sequence< NamedValue > aKern;
    3018         [ #  # ]:          0 :                 pProps[n].Value >>= aKern;
    3019                 :          0 :                 KernPair aPair;
    3020                 :          0 :                 const NamedValue* pVals = aKern.getConstArray();
    3021                 :          0 :                 int nPairs = aKern.getLength();
    3022         [ #  # ]:          0 :                 for( int m = 0; m < nPairs; m++ )
    3023                 :            :                 {
    3024         [ #  # ]:          0 :                     if( pVals[m].Name.getLength() == 2 )
    3025                 :            :                     {
    3026                 :          0 :                         aPair.first = pVals[m].Name.getStr()[0];
    3027                 :          0 :                         aPair.second = pVals[m].Name.getStr()[1];
    3028                 :          0 :                         sal_Int32 nKern = getInt( pVals[m].Value );
    3029                 :          0 :                         aPair.kern_x = static_cast<short int>(nKern & 0xffff);
    3030                 :          0 :                         aPair.kern_y = static_cast<short int>((sal_uInt32(nKern) >> 16) & 0xffff);
    3031         [ #  # ]:          0 :                         pFont->m_pMetrics->m_aXKernPairs.push_back( aPair );
    3032                 :            :                     }
    3033         [ #  # ]:          0 :                 }
    3034                 :            :             }
    3035                 :            :         }
    3036                 :            :         // sanity check
    3037         [ #  # ]:          0 :         if( pFont->m_nPSName                        &&
           [ #  #  #  # ]
                 [ #  # ]
    3038                 :            :             pFont->m_nFamilyName                    &&
    3039                 :          0 :             ! pFont->m_pMetrics->m_aMetrics.empty() )
    3040                 :            :         {
    3041         [ #  # ]:          0 :             m_aOverrideFonts.push_back( m_nNextFontID );
    3042         [ #  # ]:          0 :             m_aFonts[ m_nNextFontID++ ] = pFont;
    3043                 :            :         }
    3044                 :            :         else
    3045                 :            :         {
    3046                 :            :             DBG_ASSERT( 0, "override font failed" );
    3047 [ #  # ][ #  # ]:          0 :             delete pFont;
    3048                 :            :         }
    3049 [ #  # ][ #  # ]:          0 :     }
    3050                 :            : 
    3051         [ #  # ]:          2 :     return true;
    3052                 :            : }
    3053                 :            : 
    3054                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10