LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/vcl/source/gdi - metric.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 240 426 56.3 %
Date: 2013-07-09 Functions: 36 56 64.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <impfont.hxx>
      22             : #include <vcl/metric.hxx>
      23             : 
      24             : #include <vector>
      25             : #include <set>
      26             : 
      27             : #include <cstdio>
      28             : 
      29             : // =======================================================================
      30             : 
      31      925203 : ImplFontMetric::ImplFontMetric()
      32             : :   mnAscent( 0 ),
      33             :     mnDescent( 0 ),
      34             :     mnIntLeading( 0 ),
      35             :     mnExtLeading( 0 ),
      36             :     mnLineHeight( 0 ),
      37             :     mnSlant( 0 ),
      38             :     mnMiscFlags( 0 ),
      39      925203 :     mnRefCount( 1 )
      40      925203 : {}
      41             : 
      42             : // -----------------------------------------------------------------------
      43             : 
      44      466073 : inline void ImplFontMetric::AddReference()
      45             : {
      46             :     // TODO: disable refcounting on the default maps?
      47      466073 :     ++mnRefCount;
      48      466073 : }
      49             : 
      50             : // -----------------------------------------------------------------------
      51             : 
      52     1388375 : inline void ImplFontMetric::DeReference()
      53             : {
      54             :     // TODO: disable refcounting on the default maps?
      55     1388375 :     if( --mnRefCount <= 0 )
      56      922302 :         delete this;
      57     1388375 : }
      58             : 
      59             : // -----------------------------------------------------------------------
      60             : 
      61           0 : bool ImplFontMetric::operator==( const ImplFontMetric& r ) const
      62             : {
      63           0 :     if( mnMiscFlags  != r.mnMiscFlags )
      64           0 :         return false;
      65           0 :     if( mnAscent     != r.mnAscent )
      66           0 :         return false;
      67           0 :     if( mnDescent    != r.mnDescent )
      68           0 :         return false;
      69           0 :     if( mnIntLeading != r.mnIntLeading )
      70           0 :         return false;
      71           0 :     if( mnExtLeading != r.mnExtLeading )
      72           0 :         return false;
      73           0 :     if( mnSlant      != r.mnSlant )
      74           0 :         return false;
      75             : 
      76           0 :     return true;
      77             : }
      78             : 
      79             : // =======================================================================
      80             : 
      81      925203 : FontInfo::FontInfo()
      82      925203 : :   mpImplMetric( new ImplFontMetric )
      83      925203 : {}
      84             : 
      85             : // -----------------------------------------------------------------------
      86             : 
      87      461722 : FontInfo::FontInfo( const FontInfo& rInfo )
      88      461722 : :  Font( rInfo )
      89             : {
      90      461722 :     mpImplMetric = rInfo.mpImplMetric;
      91      461722 :     mpImplMetric->AddReference();
      92      461722 : }
      93             : 
      94             : // -----------------------------------------------------------------------
      95             : 
      96     2768048 : FontInfo::~FontInfo()
      97             : {
      98     1384024 :     mpImplMetric->DeReference();
      99     1384024 : }
     100             : 
     101             : // -----------------------------------------------------------------------
     102             : 
     103        4351 : FontInfo& FontInfo::operator=( const FontInfo& rInfo )
     104             : {
     105        4351 :     Font::operator=( rInfo );
     106             : 
     107        4351 :     if( mpImplMetric != rInfo.mpImplMetric )
     108             :     {
     109        4351 :         mpImplMetric->DeReference();
     110        4351 :         mpImplMetric = rInfo.mpImplMetric;
     111        4351 :         mpImplMetric->AddReference();
     112             :     }
     113             : 
     114        4351 :     return *this;
     115             : }
     116             : 
     117             : // -----------------------------------------------------------------------
     118             : 
     119           0 : sal_Bool FontInfo::operator==( const FontInfo& rInfo ) const
     120             : {
     121           0 :     if( !Font::operator==( rInfo ) )
     122           0 :         return sal_False;
     123           0 :     if( mpImplMetric == rInfo.mpImplMetric )
     124           0 :         return sal_True;
     125           0 :     if( *mpImplMetric == *rInfo.mpImplMetric  )
     126           0 :         return sal_True;
     127           0 :     return sal_False;
     128             : }
     129             : 
     130             : // -----------------------------------------------------------------------
     131             : 
     132      110700 : FontType FontInfo::GetType() const
     133             : {
     134      110700 :     return (mpImplMetric->IsScalable() ? TYPE_SCALABLE : TYPE_RASTER);
     135             : }
     136             : 
     137           0 : FontMetric::FontMetric( const FontMetric& rMetric )
     138           0 : :    FontInfo( rMetric )
     139           0 : {}
     140             : 
     141             : // -----------------------------------------------------------------------
     142             : 
     143      543005 : long FontMetric::GetAscent() const
     144             : {
     145      543005 :     return mpImplMetric->GetAscent();
     146             : }
     147             : 
     148             : // -----------------------------------------------------------------------
     149             : 
     150      516448 : long FontMetric::GetDescent() const
     151             : {
     152      516448 :     return mpImplMetric->GetDescent();
     153             : }
     154             : 
     155             : // -----------------------------------------------------------------------
     156             : 
     157      378799 : long FontMetric::GetIntLeading() const
     158             : {
     159      378799 :     return mpImplMetric->GetIntLeading();
     160             : }
     161             : 
     162             : // -----------------------------------------------------------------------
     163             : 
     164        2709 : long FontMetric::GetExtLeading() const
     165             : {
     166        2709 :     return mpImplMetric->GetExtLeading();
     167             : }
     168             : 
     169             : // -----------------------------------------------------------------------
     170             : 
     171           0 : long FontMetric::GetLineHeight() const
     172             : {
     173           0 :     return mpImplMetric->GetLineHeight();
     174             : }
     175             : 
     176             : // -----------------------------------------------------------------------
     177             : 
     178           0 : long FontMetric::GetSlant() const
     179             : {
     180           0 :     return mpImplMetric->GetSlant();
     181             : }
     182             : 
     183             : // -----------------------------------------------------------------------
     184             : 
     185        2195 : FontMetric& FontMetric::operator =( const FontMetric& rMetric )
     186             : {
     187        2195 :     FontInfo::operator=( rMetric );
     188        2195 :     return *this;
     189             : }
     190             : 
     191             : // -----------------------------------------------------------------------
     192             : 
     193           0 : sal_Bool FontMetric::operator==( const FontMetric& rMetric ) const
     194             : {
     195           0 :     return FontInfo::operator==( rMetric );
     196             : }
     197             : 
     198             : // =======================================================================
     199             : 
     200         242 : CmapResult::CmapResult( bool bSymbolic,
     201             :     const sal_uInt32* pRangeCodes, int nRangeCount,
     202             :     const int* pStartGlyphs, const sal_uInt16* pExtraGlyphIds )
     203             : :   mpRangeCodes( pRangeCodes)
     204             : ,   mpStartGlyphs( pStartGlyphs)
     205             : ,   mpGlyphIds( pExtraGlyphIds)
     206             : ,   mnRangeCount( nRangeCount)
     207             : ,   mbSymbolic( bSymbolic)
     208         242 : ,   mbRecoded( false)
     209         242 : {}
     210             : 
     211             : // =======================================================================
     212             : 
     213         242 : ImplFontCharMap::ImplFontCharMap( const CmapResult& rCR )
     214             : :   mpRangeCodes( rCR.mpRangeCodes )
     215             : ,   mpStartGlyphs( rCR.mpStartGlyphs )
     216             : ,   mpGlyphIds( rCR.mpGlyphIds )
     217             : ,   mnRangeCount( rCR.mnRangeCount )
     218             : ,   mnCharCount( 0 )
     219         242 : ,   mnRefCount( 0 )
     220             : {
     221         242 :     const sal_uInt32* pRangePtr = mpRangeCodes;
     222       31697 :     for( int i = mnRangeCount; --i >= 0; pRangePtr += 2 )
     223             :     {
     224       31455 :         sal_uInt32 cFirst = pRangePtr[0];
     225       31455 :         sal_uInt32 cLast  = pRangePtr[1];
     226       31455 :         mnCharCount += cLast - cFirst;
     227             :     }
     228         242 : }
     229             : 
     230             : static ImplFontCharMap* pDefaultUnicodeImplFontCharMap = NULL;
     231             : static ImplFontCharMap* pDefaultSymbolImplFontCharMap = NULL;
     232             : static const sal_uInt32 aDefaultUnicodeRanges[] = {0x0020,0xD800, 0xE000,0xFFF0};
     233             : static const sal_uInt32 aDefaultSymbolRanges[] = {0x0020,0x0100, 0xF020,0xF100};
     234             : 
     235             : // -----------------------------------------------------------------------
     236             : 
     237        4413 : bool ImplFontCharMap::IsDefaultMap() const
     238             : {
     239        4413 :     const bool bIsDefault = (mpRangeCodes == aDefaultUnicodeRanges) || (mpRangeCodes == aDefaultSymbolRanges);
     240        4413 :     return bIsDefault;
     241             : }
     242             : 
     243             : // -----------------------------------------------------------------------
     244             : 
     245         280 : ImplFontCharMap::~ImplFontCharMap()
     246             : {
     247         140 :     if( IsDefaultMap() )
     248           0 :         return;
     249         140 :     delete[] mpRangeCodes;
     250         140 :     delete[] mpStartGlyphs;
     251         140 :     delete[] mpGlyphIds;
     252         280 :  }
     253             : 
     254             : // -----------------------------------------------------------------------
     255             : 
     256             : namespace
     257             : {
     258        8546 :     ImplFontCharMap *GetDefaultUnicodeMap()
     259             :     {
     260        8546 :         if( !pDefaultUnicodeImplFontCharMap )
     261             :         {
     262         102 :             const sal_uInt32* pRangeCodes = aDefaultUnicodeRanges;
     263         102 :             int nCodesCount = sizeof(aDefaultUnicodeRanges) / sizeof(*pRangeCodes);
     264         102 :             CmapResult aDefaultCR( false, pRangeCodes, nCodesCount/2 );
     265         102 :             pDefaultUnicodeImplFontCharMap = new ImplFontCharMap( aDefaultCR );
     266         102 :             pDefaultUnicodeImplFontCharMap->AddReference();
     267             :         }
     268             : 
     269        8546 :         return pDefaultUnicodeImplFontCharMap;
     270             :     }
     271             : 
     272           0 :     ImplFontCharMap *GetDefaultSymbolMap()
     273             :     {
     274           0 :         if( !pDefaultSymbolImplFontCharMap )
     275             :         {
     276           0 :             const sal_uInt32* pRangeCodes = aDefaultSymbolRanges;
     277           0 :             int nCodesCount = sizeof(aDefaultSymbolRanges) / sizeof(*pRangeCodes);
     278           0 :             CmapResult aDefaultCR( true, pRangeCodes, nCodesCount/2 );
     279           0 :             pDefaultSymbolImplFontCharMap = new ImplFontCharMap( aDefaultCR );
     280           0 :             pDefaultSymbolImplFontCharMap->AddReference();
     281             :         }
     282             : 
     283           0 :         return pDefaultSymbolImplFontCharMap;
     284             :     }
     285             : }
     286             : 
     287        8546 : ImplFontCharMap* ImplFontCharMap::GetDefaultMap( bool bSymbols)
     288             : {
     289        8546 :     return bSymbols ? GetDefaultSymbolMap() : GetDefaultUnicodeMap();
     290             : }
     291             : 
     292             : // -----------------------------------------------------------------------
     293             : 
     294       13061 : void ImplFontCharMap::AddReference( void ) const
     295             : {
     296             :     // TODO: disable refcounting on the default maps?
     297       13061 :     ++mnRefCount;
     298       13061 : }
     299             : 
     300             : // -----------------------------------------------------------------------
     301             : 
     302       12959 : void ImplFontCharMap::DeReference( void ) const
     303             : {
     304       12959 :     if( --mnRefCount <= 0 )
     305         140 :         if( (this != pDefaultUnicodeImplFontCharMap) && (this != pDefaultSymbolImplFontCharMap) )
     306         140 :             delete this;
     307       12959 : }
     308             : 
     309             : // -----------------------------------------------------------------------
     310             : 
     311           0 : int ImplFontCharMap::GetCharCount() const
     312             : {
     313           0 :     return mnCharCount;
     314             : }
     315             : 
     316             : // -----------------------------------------------------------------------
     317             : 
     318       29673 : int ImplFontCharMap::ImplFindRangeIndex( sal_uInt32 cChar ) const
     319             : {
     320       29673 :     int nLower = 0;
     321       29673 :     int nMid   = mnRangeCount;
     322       29673 :     int nUpper = 2 * mnRangeCount - 1;
     323      299458 :     while( nLower < nUpper )
     324             :     {
     325      240112 :         if( cChar >= mpRangeCodes[ nMid ] )
     326       98819 :             nLower = nMid;
     327             :         else
     328      141293 :             nUpper = nMid - 1;
     329      240112 :         nMid = (nLower + nUpper + 1) / 2;
     330             :     }
     331             : 
     332       29673 :     return nMid;
     333             : }
     334             : 
     335             : // -----------------------------------------------------------------------
     336             : 
     337       29673 : bool ImplFontCharMap::HasChar( sal_uInt32 cChar ) const
     338             : {
     339       29673 :     bool bHasChar = false;
     340             : 
     341       29673 :     if( mpStartGlyphs  == NULL ) { // only the char-ranges are known
     342           0 :         const int nRange = ImplFindRangeIndex( cChar );
     343           0 :         if( nRange==0 && cChar<mpRangeCodes[0] )
     344           0 :             return false;
     345           0 :         bHasChar = ((nRange & 1) == 0); // inside a range
     346             :     } else { // glyph mapping is available
     347       29673 :         const int nGlyphIndex = GetGlyphIndex( cChar );
     348       29673 :         bHasChar = (nGlyphIndex != 0); // not the notdef-glyph
     349             :     }
     350             : 
     351       29673 :     return bHasChar;
     352             : }
     353             : 
     354             : // -----------------------------------------------------------------------
     355             : 
     356       29673 : int ImplFontCharMap::GetGlyphIndex( sal_uInt32 cChar ) const
     357             : {
     358             :     // return -1 if the object doesn't know the glyph ids
     359       29673 :     if( !mpStartGlyphs )
     360           0 :         return -1;
     361             : 
     362             :     // return 0 if the unicode doesn't have a matching glyph
     363       29673 :     int nRange = ImplFindRangeIndex( cChar );
     364             :     // check that we are inside any range
     365       29673 :     if( (nRange == 0) && (cChar < mpRangeCodes[0]) ) {
     366             :         // symbol aliasing gives symbol fonts a second chance
     367           0 :         const bool bSymbolic = (mpRangeCodes[0]>=0xF000) & (mpRangeCodes[1]<=0xF0FF);
     368           0 :         if( !bSymbolic )
     369           0 :             return 0;
     370             :         // check for symbol aliasing (U+00xx <-> U+F0xx)
     371           0 :         cChar |= 0xF000;
     372           0 :         nRange = ImplFindRangeIndex( cChar );
     373             :     }
     374             :     // check that we are inside a range
     375       29673 :     if( (nRange & 1) != 0 )
     376       15702 :         return 0;
     377             : 
     378             :     // get glyph index directly or indirectly
     379       13971 :     int nGlyphIndex = cChar - mpRangeCodes[ nRange ];
     380       13971 :     const int nStartIndex = mpStartGlyphs[ nRange/2 ];
     381       13971 :     if( nStartIndex >= 0 ) {
     382             :         // the glyph index can be calculated
     383       13971 :         nGlyphIndex += nStartIndex;
     384             :     } else {
     385             :         // the glyphid array has the glyph index
     386           0 :         nGlyphIndex = mpGlyphIds[ nGlyphIndex - nStartIndex ];
     387             :     }
     388             : 
     389       13971 :     return nGlyphIndex;
     390             : }
     391             : 
     392             : // -----------------------------------------------------------------------
     393             : 
     394             : // returns the number of chars supported by the font, which
     395             : // are inside the unicode range from cMin to cMax (inclusive)
     396           0 : int ImplFontCharMap::CountCharsInRange( sal_uInt32 cMin, sal_uInt32 cMax ) const
     397             : {
     398           0 :     int nCount = 0;
     399             : 
     400             :     // find and adjust range and char count for cMin
     401           0 :     int nRangeMin = ImplFindRangeIndex( cMin );
     402           0 :     if( nRangeMin & 1 )
     403           0 :         ++nRangeMin;
     404           0 :     else if( cMin > mpRangeCodes[ nRangeMin ] )
     405           0 :         nCount -= cMin - mpRangeCodes[ nRangeMin ];
     406             : 
     407             :     // find and adjust range and char count for cMax
     408           0 :     int nRangeMax = ImplFindRangeIndex( cMax );
     409           0 :     if( nRangeMax & 1 )
     410           0 :         --nRangeMax;
     411             :     else
     412           0 :         nCount -= mpRangeCodes[ nRangeMax+1 ] - cMax - 1;
     413             : 
     414             :     // count chars in complete ranges between cMin and cMax
     415           0 :     for( int i = nRangeMin; i <= nRangeMax; i+=2 )
     416           0 :         nCount += mpRangeCodes[i+1] - mpRangeCodes[i];
     417             : 
     418           0 :     return nCount;
     419             : }
     420             : 
     421             : // -----------------------------------------------------------------------
     422             : 
     423         344 : sal_uInt32 ImplFontCharMap::GetFirstChar() const
     424             : {
     425         344 :     return mpRangeCodes[0];
     426             : }
     427             : 
     428             : // -----------------------------------------------------------------------
     429             : 
     430           0 : sal_uInt32 ImplFontCharMap::GetLastChar() const
     431             : {
     432           0 :     return (mpRangeCodes[ 2*mnRangeCount-1 ] - 1);
     433             : }
     434             : 
     435             : // -----------------------------------------------------------------------
     436             : 
     437           0 : sal_uInt32 ImplFontCharMap::GetNextChar( sal_uInt32 cChar ) const
     438             : {
     439           0 :     if( cChar < GetFirstChar() )
     440           0 :         return GetFirstChar();
     441           0 :     if( cChar >= GetLastChar() )
     442           0 :         return GetLastChar();
     443             : 
     444           0 :     int nRange = ImplFindRangeIndex( cChar + 1 );
     445           0 :     if( nRange & 1 )                       // outside of range?
     446           0 :         return mpRangeCodes[ nRange + 1 ]; // => first in next range
     447           0 :     return (cChar + 1);
     448             : }
     449             : 
     450             : // -----------------------------------------------------------------------
     451             : 
     452           0 : sal_uInt32 ImplFontCharMap::GetPrevChar( sal_uInt32 cChar ) const
     453             : {
     454           0 :     if( cChar <= GetFirstChar() )
     455           0 :         return GetFirstChar();
     456           0 :     if( cChar > GetLastChar() )
     457           0 :         return GetLastChar();
     458             : 
     459           0 :     int nRange = ImplFindRangeIndex( cChar - 1 );
     460           0 :     if( nRange & 1 )                            // outside a range?
     461           0 :         return (mpRangeCodes[ nRange ] - 1);    // => last in prev range
     462           0 :     return (cChar - 1);
     463             : }
     464             : 
     465             : // -----------------------------------------------------------------------
     466             : 
     467           0 : int ImplFontCharMap::GetIndexFromChar( sal_uInt32 cChar ) const
     468             : {
     469             :     // TODO: improve linear walk?
     470           0 :     int nCharIndex = 0;
     471           0 :     const sal_uInt32* pRange = &mpRangeCodes[0];
     472           0 :     for( int i = 0; i < mnRangeCount; ++i )
     473             :     {
     474           0 :         sal_uInt32 cFirst = *(pRange++);
     475           0 :         sal_uInt32 cLast  = *(pRange++);
     476           0 :         if( cChar >= cLast )
     477           0 :             nCharIndex += cLast - cFirst;
     478           0 :         else if( cChar >= cFirst )
     479           0 :             return nCharIndex + (cChar - cFirst);
     480             :         else
     481           0 :             break;
     482             :     }
     483             : 
     484           0 :     return -1;
     485             : }
     486             : 
     487             : // -----------------------------------------------------------------------
     488             : 
     489           0 : sal_uInt32 ImplFontCharMap::GetCharFromIndex( int nCharIndex ) const
     490             : {
     491             :     // TODO: improve linear walk?
     492           0 :     const sal_uInt32* pRange = &mpRangeCodes[0];
     493           0 :     for( int i = 0; i < mnRangeCount; ++i )
     494             :     {
     495           0 :         sal_uInt32 cFirst = *(pRange++);
     496           0 :         sal_uInt32 cLast  = *(pRange++);
     497           0 :         nCharIndex -= cLast - cFirst;
     498           0 :         if( nCharIndex < 0 )
     499           0 :             return (cLast + nCharIndex);
     500             :     }
     501             : 
     502             :     // we can only get here with an out-of-bounds charindex
     503           0 :     return mpRangeCodes[0];
     504             : }
     505             : 
     506             : // =======================================================================
     507             : 
     508       80880 : static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);}
     509       18283 : static unsigned GetUShort( const unsigned char* p ){ return((p[0]<<8) | p[1]);}
     510        4527 : static int GetSShort( const unsigned char* p ){ return((static_cast<signed char>(p[0])<<8)|p[1]);}
     511             : 
     512             : // TODO: move CMAP parsing directly into the ImplFontCharMap class
     513         140 : bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult )
     514             : {
     515         140 :     rResult.mpRangeCodes = NULL;
     516         140 :     rResult.mpStartGlyphs= NULL;
     517         140 :     rResult.mpGlyphIds   = NULL;
     518         140 :     rResult.mnRangeCount = 0;
     519         140 :     rResult.mbRecoded    = false;
     520         140 :     rResult.mbSymbolic   = false;
     521             : 
     522             :     // parse the table header and check for validity
     523         140 :     if( !pCmap || (nLength < 24) )
     524           0 :         return false;
     525             : 
     526         140 :     if( GetUShort( pCmap ) != 0x0000 ) // simple check for CMAP corruption
     527           0 :         return false;
     528             : 
     529         140 :     int nSubTables = GetUShort( pCmap + 2 );
     530         140 :     if( (nSubTables <= 0) || (nLength < (24 + 8*nSubTables)) )
     531           0 :         return false;
     532             : 
     533             :     // find the most interesting subtable in the CMAP
     534         140 :     rtl_TextEncoding eRecodeFrom = RTL_TEXTENCODING_UNICODE;
     535         140 :     int nOffset = 0;
     536         140 :     int nFormat = -1;
     537         140 :     int nBestVal = 0;
     538         764 :     for( const unsigned char* p = pCmap + 4; --nSubTables >= 0; p += 8 )
     539             :     {
     540         624 :         int nPlatform = GetUShort( p );
     541         624 :         int nEncoding = GetUShort( p+2 );
     542         624 :         int nPlatformEncoding = (nPlatform << 8) + nEncoding;
     543             : 
     544             :         int nValue;
     545         624 :         rtl_TextEncoding eTmpEncoding = RTL_TEXTENCODING_UNICODE;
     546         624 :         switch( nPlatformEncoding )
     547             :         {
     548           0 :             case 0x000: nValue = 20; break;                             // Unicode 1.0
     549           0 :             case 0x001: nValue = 21; break;                             // Unicode 1.1
     550           0 :             case 0x002: nValue = 22; break;                             // iso10646_1993
     551         140 :             case 0x003: nValue = 23; break;                             // UCS-2
     552          84 :             case 0x004: nValue = 24; break;                             // UCS-4
     553         140 :             case 0x100: nValue = 22; break;                             // Mac Unicode<2.0
     554           0 :             case 0x103: nValue = 23; break;                             // Mac Unicode>2.0
     555           0 :             case 0x300: nValue =  5; rResult.mbSymbolic = true; break;  // Win Symbol
     556         140 :             case 0x301: nValue = 28; break;                             // Win UCS-2
     557         102 :             case 0x30A: nValue = 29; break;                             // Win-UCS-4
     558           0 :             case 0x302: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_SHIFT_JIS; break;
     559           0 :             case 0x303: nValue = 12; eTmpEncoding = RTL_TEXTENCODING_GB_18030; break;
     560           0 :             case 0x304: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_BIG5; break;
     561           0 :             case 0x305: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_MS_949; break;
     562           0 :             case 0x306: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_MS_1361; break;
     563          18 :             default:    nValue = 0; break;
     564             :         }
     565             : 
     566         624 :         if( nValue <= 0 )   // ignore unknown encodings
     567          18 :             continue;
     568             : 
     569         606 :         int nTmpOffset = GetUInt( p+4 );
     570         606 :         int nTmpFormat = GetUShort( pCmap + nTmpOffset );
     571         606 :         if( nTmpFormat == 12 )                  // 32bit code -> glyph map format
     572         186 :             nValue += 3;
     573         420 :         else if( nTmpFormat != 4 )              // 16bit code -> glyph map format
     574         140 :             continue;                           // ignore other formats
     575             : 
     576         466 :         if( nBestVal < nValue )
     577             :         {
     578         466 :             nBestVal = nValue;
     579         466 :             nOffset = nTmpOffset;
     580         466 :             nFormat = nTmpFormat;
     581         466 :             eRecodeFrom = eTmpEncoding;
     582             :         }
     583             :     }
     584             : 
     585             :     // parse the best CMAP subtable
     586         140 :     int nRangeCount = 0;
     587         140 :     sal_uInt32* pCodePairs = NULL;
     588         140 :     int* pStartGlyphs = NULL;
     589             : 
     590             :     typedef std::vector<sal_uInt16> U16Vector;
     591         140 :     U16Vector aGlyphIdArray;
     592         140 :     aGlyphIdArray.reserve( 0x1000 );
     593         140 :     aGlyphIdArray.push_back( 0 );
     594             : 
     595             :     // format 4, the most common 16bit char mapping table
     596         140 :     if( (nFormat == 4) && ((nOffset+16) < nLength) )
     597             :     {
     598          38 :         int nSegCountX2 = GetUShort( pCmap + nOffset + 6 );
     599          38 :         nRangeCount = nSegCountX2/2 - 1;
     600          38 :         pCodePairs = new sal_uInt32[ nRangeCount * 2 ];
     601          38 :         pStartGlyphs = new int[ nRangeCount ];
     602          38 :         const unsigned char* pLimitBase = pCmap + nOffset + 14;
     603          38 :         const unsigned char* pBeginBase = pLimitBase + nSegCountX2 + 2;
     604          38 :         const unsigned char* pDeltaBase = pBeginBase + nSegCountX2;
     605          38 :         const unsigned char* pOffsetBase = pDeltaBase + nSegCountX2;
     606          38 :         sal_uInt32* pCP = pCodePairs;
     607        4565 :         for( int i = 0; i < nRangeCount; ++i )
     608             :         {
     609        4527 :             const sal_uInt32 cMinChar = GetUShort( pBeginBase + 2*i );
     610        4527 :             const sal_uInt32 cMaxChar = GetUShort( pLimitBase + 2*i );
     611        4527 :             const int nGlyphDelta  = GetSShort( pDeltaBase + 2*i );
     612        4527 :             const int nRangeOffset = GetUShort( pOffsetBase + 2*i );
     613        4527 :             if( cMinChar > cMaxChar )   // no sane font should trigger this
     614           0 :                 break;
     615        4527 :             if( cMaxChar == 0xFFFF )
     616           0 :                 break;
     617        4527 :             *(pCP++) = cMinChar;
     618        4527 :             *(pCP++) = cMaxChar + 1;
     619        4527 :             if( !nRangeOffset ) {
     620             :                 // glyphid can be calculated directly
     621        4495 :                 pStartGlyphs[i] = (cMinChar + nGlyphDelta) & 0xFFFF;
     622             :             } else {
     623             :                 // update the glyphid-array with the glyphs in this range
     624          32 :                 pStartGlyphs[i] = -(int)aGlyphIdArray.size();
     625          32 :                 const unsigned char* pGlyphIdPtr = pOffsetBase + 2*i + nRangeOffset;
     626        2562 :                 for( sal_uInt32 c = cMinChar; c <= cMaxChar; ++c, pGlyphIdPtr+=2 ) {
     627        2530 :                     const int nGlyphIndex = GetUShort( pGlyphIdPtr ) + nGlyphDelta;
     628        2530 :                     aGlyphIdArray.push_back( static_cast<sal_uInt16>(nGlyphIndex) );
     629             :                 }
     630             :             }
     631             :         }
     632          38 :         nRangeCount = (pCP - pCodePairs) / 2;
     633             :     }
     634             :     // format 12, the most common 32bit char mapping table
     635         102 :     else if( (nFormat == 12) && ((nOffset+16) < nLength) )
     636             :     {
     637         102 :         nRangeCount = GetUInt( pCmap + nOffset + 12 );
     638         102 :         pCodePairs = new sal_uInt32[ nRangeCount * 2 ];
     639         102 :         pStartGlyphs = new int[ nRangeCount ];
     640         102 :         const unsigned char* pGroup = pCmap + nOffset + 16;
     641         102 :         sal_uInt32* pCP = pCodePairs;
     642       26826 :         for( int i = 0; i < nRangeCount; ++i )
     643             :         {
     644       26724 :             sal_uInt32 cMinChar = GetUInt( pGroup + 0 );
     645       26724 :             sal_uInt32 cMaxChar = GetUInt( pGroup + 4 );
     646       26724 :             int nGlyphId = GetUInt( pGroup + 8 );
     647       26724 :             pGroup += 12;
     648       26724 :             if( cMinChar > cMaxChar )   // no sane font should trigger this
     649           0 :                 break;
     650       26724 :             *(pCP++) = cMinChar;
     651       26724 :             *(pCP++) = cMaxChar + 1;
     652       26724 :             pStartGlyphs[i] = nGlyphId;
     653             :         }
     654         102 :         nRangeCount = (pCP - pCodePairs) / 2;
     655             :     }
     656             : 
     657             :     // check if any subtable resulted in something usable
     658         140 :     if( nRangeCount <= 0 )
     659             :     {
     660           0 :         delete[] pCodePairs;
     661           0 :         delete[] pStartGlyphs;
     662             : 
     663             :         // even when no CMAP is available we know it for symbol fonts
     664           0 :         if( rResult.mbSymbolic )
     665             :         {
     666           0 :             pCodePairs = new sal_uInt32[4];
     667           0 :             pCodePairs[0] = 0x0020;    // aliased symbols
     668           0 :             pCodePairs[1] = 0x0100;
     669           0 :             pCodePairs[2] = 0xF020;    // original symbols
     670           0 :             pCodePairs[3] = 0xF100;
     671           0 :             rResult.mpRangeCodes = pCodePairs;
     672           0 :             rResult.mnRangeCount = 2;
     673           0 :             return true;
     674             :         }
     675             : 
     676           0 :         return false;
     677             :     }
     678             : 
     679             :     // recode the code ranges to their unicode encoded ranges if needed
     680         140 :     rtl_TextToUnicodeConverter aConverter = NULL;
     681         140 :     rtl_UnicodeToTextContext aCvtContext = NULL;
     682             : 
     683         140 :     rResult.mbRecoded = ( eRecodeFrom != RTL_TEXTENCODING_UNICODE );
     684         140 :     if( rResult.mbRecoded )
     685             :     {
     686           0 :         aConverter = rtl_createTextToUnicodeConverter( eRecodeFrom );
     687           0 :         aCvtContext = rtl_createTextToUnicodeContext( aConverter );
     688             :     }
     689             : 
     690         140 :     if( aConverter && aCvtContext )
     691             :     {
     692             :         // determine the set of supported unicodes from encoded ranges
     693             :         typedef std::set<sal_uInt32> IntSet;
     694           0 :         IntSet aSupportedUnicodes;
     695             : 
     696             :         static const int NINSIZE = 64;
     697             :         static const int NOUTSIZE = 64;
     698             :         sal_Char    cCharsInp[ NINSIZE ];
     699             :         sal_Unicode cCharsOut[ NOUTSIZE ];
     700           0 :         sal_uInt32* pCP = pCodePairs;
     701           0 :         for( int i = 0; i < nRangeCount; ++i )
     702             :         {
     703           0 :             sal_uInt32 cMin = *(pCP++);
     704           0 :             sal_uInt32 cEnd = *(pCP++);
     705           0 :             while( cMin < cEnd )
     706             :             {
     707           0 :                 int j = 0;
     708           0 :                 for (; (cMin < cEnd) && (j < (NINSIZE-1)); ++cMin)
     709             :                 {
     710           0 :                     if( cMin >= 0x0100 )
     711           0 :                         cCharsInp[ j++ ] = static_cast<sal_Char>(cMin >> 8);
     712           0 :                     if( (cMin >= 0x0100) || (cMin < 0x00A0)  )
     713           0 :                         cCharsInp[ j++ ] = static_cast<sal_Char>(cMin);
     714             :                 }
     715             : 
     716             :                 sal_uInt32 nCvtInfo;
     717             :                 sal_Size nSrcCvtBytes;
     718             :                 int nOutLen = rtl_convertTextToUnicode(
     719             :                     aConverter, aCvtContext,
     720             :                     cCharsInp, j, cCharsOut, NOUTSIZE,
     721             :                     RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE
     722             :                     | RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE,
     723           0 :                     &nCvtInfo, &nSrcCvtBytes );
     724             : 
     725           0 :                 for( j = 0; j < nOutLen; ++j )
     726           0 :                     aSupportedUnicodes.insert( cCharsOut[j] );
     727             :             }
     728             :         }
     729             : 
     730           0 :         rtl_destroyTextToUnicodeConverter( aCvtContext );
     731           0 :         rtl_destroyTextToUnicodeConverter( aConverter );
     732             : 
     733             :         // convert the set of supported unicodes to ranges
     734             :         typedef std::vector<sal_uInt32> IntVector;
     735           0 :         IntVector aSupportedRanges;
     736             : 
     737           0 :         IntSet::const_iterator itChar = aSupportedUnicodes.begin();
     738           0 :         for(; itChar != aSupportedUnicodes.end(); ++itChar )
     739             :         {
     740           0 :             if( aSupportedRanges.empty()
     741           0 :             || (aSupportedRanges.back() != *itChar) )
     742             :             {
     743             :                 // add new range beginning with current unicode
     744           0 :                 aSupportedRanges.push_back( *itChar );
     745           0 :                 aSupportedRanges.push_back( 0 );
     746             :             }
     747             : 
     748             :             // extend existing range to include current unicode
     749           0 :             aSupportedRanges.back() = *itChar + 1;
     750             :         }
     751             : 
     752             :         // glyph mapping for non-unicode fonts not implemented
     753           0 :         delete[] pStartGlyphs;
     754           0 :         pStartGlyphs = NULL;
     755           0 :         aGlyphIdArray.clear();
     756             : 
     757             :         // make a pCodePairs array using the vector from above
     758           0 :         delete[] pCodePairs;
     759           0 :         nRangeCount = aSupportedRanges.size() / 2;
     760           0 :         if( nRangeCount <= 0 )
     761           0 :             return false;
     762           0 :         pCodePairs = new sal_uInt32[ nRangeCount * 2 ];
     763           0 :         IntVector::const_iterator itInt = aSupportedRanges.begin();
     764           0 :         for( pCP = pCodePairs; itInt != aSupportedRanges.end(); ++itInt )
     765           0 :             *(pCP++) = *itInt;
     766             :     }
     767             : 
     768             :     // prepare the glyphid-array if needed
     769             :     // TODO: merge ranges if they are close enough?
     770         140 :     sal_uInt16* pGlyphIds = NULL;
     771         140 :     if( !aGlyphIdArray.empty())
     772             :     {
     773         140 :         pGlyphIds = new sal_uInt16[ aGlyphIdArray.size() ];
     774         140 :         sal_uInt16* pOut = pGlyphIds;
     775         140 :         U16Vector::const_iterator it = aGlyphIdArray.begin();
     776        2950 :         while( it != aGlyphIdArray.end() )
     777        2670 :             *(pOut++) = *(it++);
     778             :     }
     779             : 
     780             :     // update the result struct
     781         140 :     rResult.mpRangeCodes = pCodePairs;
     782         140 :     rResult.mpStartGlyphs = pStartGlyphs;
     783         140 :     rResult.mnRangeCount = nRangeCount;
     784         140 :     rResult.mpGlyphIds = pGlyphIds;
     785         140 :     return true;
     786             : }
     787             : 
     788             : // =======================================================================
     789             : 
     790        4273 : FontCharMap::FontCharMap()
     791        4273 : :   mpImpl( ImplFontCharMap::GetDefaultMap() )
     792             : {
     793        4273 :     mpImpl->AddReference();
     794        4273 : }
     795             : 
     796             : // -----------------------------------------------------------------------
     797             : 
     798        4273 : FontCharMap::~FontCharMap()
     799             : {
     800        4273 :     mpImpl->DeReference();
     801        4273 :     mpImpl = NULL;
     802        4273 : }
     803             : 
     804             : // -----------------------------------------------------------------------
     805             : 
     806           0 : int FontCharMap::GetCharCount() const
     807             : {
     808           0 :     return mpImpl->GetCharCount();
     809             : }
     810             : 
     811             : // -----------------------------------------------------------------------
     812             : 
     813           0 : int FontCharMap::CountCharsInRange( sal_uInt32 cMin, sal_uInt32 cMax ) const
     814             : {
     815           0 :     return mpImpl->CountCharsInRange( cMin, cMax );
     816             : }
     817             : 
     818             : // -----------------------------------------------------------------------
     819             : 
     820        8546 : void FontCharMap::Reset( const ImplFontCharMap* pNewMap )
     821             : {
     822        8546 :     mpImpl->DeReference();
     823        8546 :     if( pNewMap == NULL )
     824        4273 :         mpImpl = ImplFontCharMap::GetDefaultMap();
     825        4273 :     else if( pNewMap != mpImpl )
     826        4273 :         mpImpl = pNewMap;
     827        8546 :     mpImpl->AddReference();
     828        8546 : }
     829             : 
     830             : // -----------------------------------------------------------------------
     831             : 
     832        4273 : sal_Bool FontCharMap::IsDefaultMap() const
     833             : {
     834        4273 :     return mpImpl->IsDefaultMap();
     835             : }
     836             : 
     837             : // -----------------------------------------------------------------------
     838             : 
     839       29673 : sal_Bool FontCharMap::HasChar( sal_uInt32 cChar ) const
     840             : {
     841       29673 :     return mpImpl->HasChar( cChar );
     842             : }
     843             : 
     844             : // -----------------------------------------------------------------------
     845             : 
     846         344 : sal_uInt32 FontCharMap::GetFirstChar() const
     847             : {
     848         344 :     return mpImpl->GetFirstChar();
     849             : }
     850             : 
     851             : // -----------------------------------------------------------------------
     852             : 
     853           0 : sal_uInt32 FontCharMap::GetNextChar( sal_uInt32 cChar ) const
     854             : {
     855           0 :     return mpImpl->GetNextChar( cChar );
     856             : }
     857             : 
     858             : // -----------------------------------------------------------------------
     859             : 
     860           0 : sal_uInt32 FontCharMap::GetPrevChar( sal_uInt32 cChar ) const
     861             : {
     862           0 :     return mpImpl->GetPrevChar( cChar );
     863             : }
     864             : 
     865             : // -----------------------------------------------------------------------
     866             : 
     867           0 : int FontCharMap::GetIndexFromChar( sal_uInt32 cChar ) const
     868             : {
     869           0 :     return mpImpl->GetIndexFromChar( cChar );
     870             : }
     871             : 
     872             : // -----------------------------------------------------------------------
     873             : 
     874           0 : sal_uInt32 FontCharMap::GetCharFromIndex( int nIndex ) const
     875             : {
     876           0 :     return mpImpl->GetCharFromIndex( nIndex );
     877             : }
     878             : 
     879             : // =======================================================================
     880             : 
     881             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10