1*43ad51ffSHerbert Dürr /************************************************************** 2*43ad51ffSHerbert Dürr * 3*43ad51ffSHerbert Dürr * Licensed to the Apache Software Foundation (ASF) under one 4*43ad51ffSHerbert Dürr * or more contributor license agreements. See the NOTICE file 5*43ad51ffSHerbert Dürr * distributed with this work for additional information 6*43ad51ffSHerbert Dürr * regarding copyright ownership. The ASF licenses this file 7*43ad51ffSHerbert Dürr * to you under the Apache License, Version 2.0 (the 8*43ad51ffSHerbert Dürr * "License"); you may not use this file except in compliance 9*43ad51ffSHerbert Dürr * with the License. You may obtain a copy of the License at 10*43ad51ffSHerbert Dürr * 11*43ad51ffSHerbert Dürr * http://www.apache.org/licenses/LICENSE-2.0 12*43ad51ffSHerbert Dürr * 13*43ad51ffSHerbert Dürr * Unless required by applicable law or agreed to in writing, 14*43ad51ffSHerbert Dürr * software distributed under the License is distributed on an 15*43ad51ffSHerbert Dürr * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*43ad51ffSHerbert Dürr * KIND, either express or implied. See the License for the 17*43ad51ffSHerbert Dürr * specific language governing permissions and limitations 18*43ad51ffSHerbert Dürr * under the License. 19*43ad51ffSHerbert Dürr * 20*43ad51ffSHerbert Dürr *************************************************************/ 21*43ad51ffSHerbert Dürr 22*43ad51ffSHerbert Dürr // MARKER(update_precomp.py): autogen include statement, do not remove 23*43ad51ffSHerbert Dürr #include "precompiled_vcl.hxx" 24*43ad51ffSHerbert Dürr 25*43ad51ffSHerbert Dürr #include <vcl/metric.hxx> 26*43ad51ffSHerbert Dürr #include <outfont.hxx> 27*43ad51ffSHerbert Dürr #include <impfont.hxx> 28*43ad51ffSHerbert Dürr 29*43ad51ffSHerbert Dürr #include <vector> 30*43ad51ffSHerbert Dürr #include <set> 31*43ad51ffSHerbert Dürr 32*43ad51ffSHerbert Dürr // ======================================================================= 33*43ad51ffSHerbert Dürr 34*43ad51ffSHerbert Dürr CmapResult::CmapResult( bool bSymbolic, 35*43ad51ffSHerbert Dürr const sal_UCS4* pRangeCodes, int nRangeCount, 36*43ad51ffSHerbert Dürr const int* pStartGlyphs, const sal_uInt16* pExtraGlyphIds ) 37*43ad51ffSHerbert Dürr : mpRangeCodes( pRangeCodes) 38*43ad51ffSHerbert Dürr , mpStartGlyphs( pStartGlyphs) 39*43ad51ffSHerbert Dürr , mpGlyphIds( pExtraGlyphIds) 40*43ad51ffSHerbert Dürr , mnRangeCount( nRangeCount) 41*43ad51ffSHerbert Dürr , mbSymbolic( bSymbolic) 42*43ad51ffSHerbert Dürr , mbRecoded( false) 43*43ad51ffSHerbert Dürr {} 44*43ad51ffSHerbert Dürr 45*43ad51ffSHerbert Dürr // ======================================================================= 46*43ad51ffSHerbert Dürr 47*43ad51ffSHerbert Dürr ImplFontCharMap::ImplFontCharMap( const CmapResult& rCR ) 48*43ad51ffSHerbert Dürr : mpRangeCodes( rCR.mpRangeCodes ) 49*43ad51ffSHerbert Dürr , mpStartGlyphs( rCR.mpStartGlyphs ) 50*43ad51ffSHerbert Dürr , mpGlyphIds( rCR.mpGlyphIds ) 51*43ad51ffSHerbert Dürr , mnRangeCount( rCR.mnRangeCount ) 52*43ad51ffSHerbert Dürr , mnCharCount( 0 ) 53*43ad51ffSHerbert Dürr , mnRefCount( 1 ) 54*43ad51ffSHerbert Dürr { 55*43ad51ffSHerbert Dürr const sal_UCS4* pRangePtr = mpRangeCodes; 56*43ad51ffSHerbert Dürr for( int i = mnRangeCount; --i >= 0; pRangePtr += 2 ) 57*43ad51ffSHerbert Dürr { 58*43ad51ffSHerbert Dürr sal_UCS4 cFirst = pRangePtr[0]; 59*43ad51ffSHerbert Dürr sal_UCS4 cLast = pRangePtr[1]; 60*43ad51ffSHerbert Dürr mnCharCount += cLast - cFirst; 61*43ad51ffSHerbert Dürr } 62*43ad51ffSHerbert Dürr } 63*43ad51ffSHerbert Dürr 64*43ad51ffSHerbert Dürr static ImplFontCharMap* pDefaultImplFontCharMap = NULL; 65*43ad51ffSHerbert Dürr static const sal_UCS4 aDefaultUnicodeRanges[] = {0x0020,0xD800, 0xE000,0xFFF0}; 66*43ad51ffSHerbert Dürr static const sal_UCS4 aDefaultSymbolRanges[] = {0x0020,0x0100, 0xF020,0xF100}; 67*43ad51ffSHerbert Dürr 68*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 69*43ad51ffSHerbert Dürr 70*43ad51ffSHerbert Dürr bool ImplFontCharMap::IsDefaultMap() const 71*43ad51ffSHerbert Dürr { 72*43ad51ffSHerbert Dürr const bool bIsDefault = (mpRangeCodes == aDefaultUnicodeRanges) || (mpRangeCodes == aDefaultSymbolRanges); 73*43ad51ffSHerbert Dürr return bIsDefault; 74*43ad51ffSHerbert Dürr } 75*43ad51ffSHerbert Dürr 76*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 77*43ad51ffSHerbert Dürr 78*43ad51ffSHerbert Dürr ImplFontCharMap::~ImplFontCharMap() 79*43ad51ffSHerbert Dürr { 80*43ad51ffSHerbert Dürr if( IsDefaultMap() ) 81*43ad51ffSHerbert Dürr return; 82*43ad51ffSHerbert Dürr delete[] mpRangeCodes; 83*43ad51ffSHerbert Dürr delete[] mpStartGlyphs; 84*43ad51ffSHerbert Dürr delete[] mpGlyphIds; 85*43ad51ffSHerbert Dürr } 86*43ad51ffSHerbert Dürr 87*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 88*43ad51ffSHerbert Dürr 89*43ad51ffSHerbert Dürr ImplFontCharMap* ImplFontCharMap::GetDefaultMap( bool bSymbols) 90*43ad51ffSHerbert Dürr { 91*43ad51ffSHerbert Dürr if( pDefaultImplFontCharMap ) 92*43ad51ffSHerbert Dürr pDefaultImplFontCharMap->AddReference(); 93*43ad51ffSHerbert Dürr else 94*43ad51ffSHerbert Dürr { 95*43ad51ffSHerbert Dürr const sal_UCS4* pRangeCodes = aDefaultUnicodeRanges; 96*43ad51ffSHerbert Dürr int nCodesCount = sizeof(aDefaultUnicodeRanges) / sizeof(*pRangeCodes); 97*43ad51ffSHerbert Dürr if( bSymbols ) 98*43ad51ffSHerbert Dürr { 99*43ad51ffSHerbert Dürr pRangeCodes = aDefaultSymbolRanges; 100*43ad51ffSHerbert Dürr nCodesCount = sizeof(aDefaultSymbolRanges) / sizeof(*pRangeCodes); 101*43ad51ffSHerbert Dürr } 102*43ad51ffSHerbert Dürr 103*43ad51ffSHerbert Dürr CmapResult aDefaultCR( bSymbols, pRangeCodes, nCodesCount/2 ); 104*43ad51ffSHerbert Dürr pDefaultImplFontCharMap = new ImplFontCharMap( aDefaultCR ); 105*43ad51ffSHerbert Dürr } 106*43ad51ffSHerbert Dürr 107*43ad51ffSHerbert Dürr return pDefaultImplFontCharMap; 108*43ad51ffSHerbert Dürr } 109*43ad51ffSHerbert Dürr 110*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 111*43ad51ffSHerbert Dürr 112*43ad51ffSHerbert Dürr void ImplFontCharMap::AddReference( void) const 113*43ad51ffSHerbert Dürr { 114*43ad51ffSHerbert Dürr ++mnRefCount; 115*43ad51ffSHerbert Dürr } 116*43ad51ffSHerbert Dürr 117*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 118*43ad51ffSHerbert Dürr 119*43ad51ffSHerbert Dürr void ImplFontCharMap::DeReference( void) const 120*43ad51ffSHerbert Dürr { 121*43ad51ffSHerbert Dürr if( --mnRefCount <= 0 ) 122*43ad51ffSHerbert Dürr if( this != pDefaultImplFontCharMap ) 123*43ad51ffSHerbert Dürr delete this; 124*43ad51ffSHerbert Dürr } 125*43ad51ffSHerbert Dürr 126*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 127*43ad51ffSHerbert Dürr 128*43ad51ffSHerbert Dürr int ImplFontCharMap::GetCharCount() const 129*43ad51ffSHerbert Dürr { 130*43ad51ffSHerbert Dürr return mnCharCount; 131*43ad51ffSHerbert Dürr } 132*43ad51ffSHerbert Dürr 133*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 134*43ad51ffSHerbert Dürr 135*43ad51ffSHerbert Dürr int ImplFontCharMap::ImplFindRangeIndex( sal_UCS4 cChar ) const 136*43ad51ffSHerbert Dürr { 137*43ad51ffSHerbert Dürr int nLower = 0; 138*43ad51ffSHerbert Dürr int nMid = mnRangeCount; 139*43ad51ffSHerbert Dürr int nUpper = 2 * mnRangeCount - 1; 140*43ad51ffSHerbert Dürr while( nLower < nUpper ) 141*43ad51ffSHerbert Dürr { 142*43ad51ffSHerbert Dürr if( cChar >= mpRangeCodes[ nMid ] ) 143*43ad51ffSHerbert Dürr nLower = nMid; 144*43ad51ffSHerbert Dürr else 145*43ad51ffSHerbert Dürr nUpper = nMid - 1; 146*43ad51ffSHerbert Dürr nMid = (nLower + nUpper + 1) / 2; 147*43ad51ffSHerbert Dürr } 148*43ad51ffSHerbert Dürr 149*43ad51ffSHerbert Dürr return nMid; 150*43ad51ffSHerbert Dürr } 151*43ad51ffSHerbert Dürr 152*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 153*43ad51ffSHerbert Dürr 154*43ad51ffSHerbert Dürr bool ImplFontCharMap::HasChar( sal_UCS4 cChar ) const 155*43ad51ffSHerbert Dürr { 156*43ad51ffSHerbert Dürr bool bHasChar = false; 157*43ad51ffSHerbert Dürr 158*43ad51ffSHerbert Dürr if( mpStartGlyphs == NULL ) { // only the char-ranges are known 159*43ad51ffSHerbert Dürr const int nRange = ImplFindRangeIndex( cChar ); 160*43ad51ffSHerbert Dürr if( nRange==0 && cChar<mpRangeCodes[0] ) 161*43ad51ffSHerbert Dürr return false; 162*43ad51ffSHerbert Dürr bHasChar = ((nRange & 1) == 0); // inside a range 163*43ad51ffSHerbert Dürr } else { // glyph mapping is available 164*43ad51ffSHerbert Dürr const int nGlyphIndex = GetGlyphIndex( cChar ); 165*43ad51ffSHerbert Dürr bHasChar = (nGlyphIndex != 0); // not the notdef-glyph 166*43ad51ffSHerbert Dürr } 167*43ad51ffSHerbert Dürr 168*43ad51ffSHerbert Dürr return bHasChar; 169*43ad51ffSHerbert Dürr } 170*43ad51ffSHerbert Dürr 171*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 172*43ad51ffSHerbert Dürr 173*43ad51ffSHerbert Dürr int ImplFontCharMap::GetGlyphIndex( sal_UCS4 cChar ) const 174*43ad51ffSHerbert Dürr { 175*43ad51ffSHerbert Dürr // return -1 if the object doesn't know the glyph ids 176*43ad51ffSHerbert Dürr if( !mpStartGlyphs ) 177*43ad51ffSHerbert Dürr return -1; 178*43ad51ffSHerbert Dürr 179*43ad51ffSHerbert Dürr // return 0 if the unicode doesn't have a matching glyph 180*43ad51ffSHerbert Dürr int nRange = ImplFindRangeIndex( cChar ); 181*43ad51ffSHerbert Dürr // check that we are inside any range 182*43ad51ffSHerbert Dürr if( (nRange == 0) && (cChar < mpRangeCodes[0]) ) { 183*43ad51ffSHerbert Dürr // symbol aliasing gives symbol fonts a second chance 184*43ad51ffSHerbert Dürr const bool bSymbolic = (mpRangeCodes[0]>=0xF000) & (mpRangeCodes[1]<=0xF0FF); 185*43ad51ffSHerbert Dürr if( !bSymbolic ) 186*43ad51ffSHerbert Dürr return 0; 187*43ad51ffSHerbert Dürr // check for symbol aliasing (U+F0xx -> U+00xx) 188*43ad51ffSHerbert Dürr nRange = ImplFindRangeIndex( cChar | 0xF000 ); 189*43ad51ffSHerbert Dürr } 190*43ad51ffSHerbert Dürr // check that we are inside a range 191*43ad51ffSHerbert Dürr if( (nRange & 1) != 0 ) 192*43ad51ffSHerbert Dürr return 0; 193*43ad51ffSHerbert Dürr 194*43ad51ffSHerbert Dürr // get glyph index directly or indirectly 195*43ad51ffSHerbert Dürr int nGlyphIndex = cChar - mpRangeCodes[ nRange ]; 196*43ad51ffSHerbert Dürr const int nStartIndex = mpStartGlyphs[ nRange/2 ]; 197*43ad51ffSHerbert Dürr if( nStartIndex >= 0 ) { 198*43ad51ffSHerbert Dürr // the glyph index can be calculated 199*43ad51ffSHerbert Dürr nGlyphIndex += nStartIndex; 200*43ad51ffSHerbert Dürr } else { 201*43ad51ffSHerbert Dürr // the glyphid array has the glyph index 202*43ad51ffSHerbert Dürr nGlyphIndex = mpGlyphIds[ nGlyphIndex - nStartIndex]; 203*43ad51ffSHerbert Dürr } 204*43ad51ffSHerbert Dürr 205*43ad51ffSHerbert Dürr return nGlyphIndex; 206*43ad51ffSHerbert Dürr } 207*43ad51ffSHerbert Dürr 208*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 209*43ad51ffSHerbert Dürr 210*43ad51ffSHerbert Dürr // returns the number of chars supported by the font, which 211*43ad51ffSHerbert Dürr // are inside the unicode range from cMin to cMax (inclusive) 212*43ad51ffSHerbert Dürr int ImplFontCharMap::CountCharsInRange( sal_UCS4 cMin, sal_UCS4 cMax ) const 213*43ad51ffSHerbert Dürr { 214*43ad51ffSHerbert Dürr int nCount = 0; 215*43ad51ffSHerbert Dürr 216*43ad51ffSHerbert Dürr // find and adjust range and char count for cMin 217*43ad51ffSHerbert Dürr int nRangeMin = ImplFindRangeIndex( cMin ); 218*43ad51ffSHerbert Dürr if( nRangeMin & 1 ) 219*43ad51ffSHerbert Dürr ++nRangeMin; 220*43ad51ffSHerbert Dürr else if( cMin > mpRangeCodes[ nRangeMin ] ) 221*43ad51ffSHerbert Dürr nCount -= cMin - mpRangeCodes[ nRangeMin ]; 222*43ad51ffSHerbert Dürr 223*43ad51ffSHerbert Dürr // find and adjust range and char count for cMax 224*43ad51ffSHerbert Dürr int nRangeMax = ImplFindRangeIndex( cMax ); 225*43ad51ffSHerbert Dürr if( nRangeMax & 1 ) 226*43ad51ffSHerbert Dürr --nRangeMax; 227*43ad51ffSHerbert Dürr else 228*43ad51ffSHerbert Dürr nCount -= mpRangeCodes[ nRangeMax+1 ] - cMax - 1; 229*43ad51ffSHerbert Dürr 230*43ad51ffSHerbert Dürr // count chars in complete ranges between cMin and cMax 231*43ad51ffSHerbert Dürr for( int i = nRangeMin; i <= nRangeMax; i+=2 ) 232*43ad51ffSHerbert Dürr nCount += mpRangeCodes[i+1] - mpRangeCodes[i]; 233*43ad51ffSHerbert Dürr 234*43ad51ffSHerbert Dürr return nCount; 235*43ad51ffSHerbert Dürr } 236*43ad51ffSHerbert Dürr 237*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 238*43ad51ffSHerbert Dürr 239*43ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetFirstChar() const 240*43ad51ffSHerbert Dürr { 241*43ad51ffSHerbert Dürr return mpRangeCodes[0]; 242*43ad51ffSHerbert Dürr } 243*43ad51ffSHerbert Dürr 244*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 245*43ad51ffSHerbert Dürr 246*43ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetLastChar() const 247*43ad51ffSHerbert Dürr { 248*43ad51ffSHerbert Dürr return (mpRangeCodes[ 2*mnRangeCount-1 ] - 1); 249*43ad51ffSHerbert Dürr } 250*43ad51ffSHerbert Dürr 251*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 252*43ad51ffSHerbert Dürr 253*43ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetNextChar( sal_UCS4 cChar ) const 254*43ad51ffSHerbert Dürr { 255*43ad51ffSHerbert Dürr if( cChar < GetFirstChar() ) 256*43ad51ffSHerbert Dürr return GetFirstChar(); 257*43ad51ffSHerbert Dürr if( cChar >= GetLastChar() ) 258*43ad51ffSHerbert Dürr return GetLastChar(); 259*43ad51ffSHerbert Dürr 260*43ad51ffSHerbert Dürr int nRange = ImplFindRangeIndex( cChar + 1 ); 261*43ad51ffSHerbert Dürr if( nRange & 1 ) // outside of range? 262*43ad51ffSHerbert Dürr return mpRangeCodes[ nRange + 1 ]; // => first in next range 263*43ad51ffSHerbert Dürr return (cChar + 1); 264*43ad51ffSHerbert Dürr } 265*43ad51ffSHerbert Dürr 266*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 267*43ad51ffSHerbert Dürr 268*43ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetPrevChar( sal_UCS4 cChar ) const 269*43ad51ffSHerbert Dürr { 270*43ad51ffSHerbert Dürr if( cChar <= GetFirstChar() ) 271*43ad51ffSHerbert Dürr return GetFirstChar(); 272*43ad51ffSHerbert Dürr if( cChar > GetLastChar() ) 273*43ad51ffSHerbert Dürr return GetLastChar(); 274*43ad51ffSHerbert Dürr 275*43ad51ffSHerbert Dürr int nRange = ImplFindRangeIndex( cChar - 1 ); 276*43ad51ffSHerbert Dürr if( nRange & 1 ) // outside a range? 277*43ad51ffSHerbert Dürr return (mpRangeCodes[ nRange ] - 1); // => last in prev range 278*43ad51ffSHerbert Dürr return (cChar - 1); 279*43ad51ffSHerbert Dürr } 280*43ad51ffSHerbert Dürr 281*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 282*43ad51ffSHerbert Dürr 283*43ad51ffSHerbert Dürr int ImplFontCharMap::GetIndexFromChar( sal_UCS4 cChar ) const 284*43ad51ffSHerbert Dürr { 285*43ad51ffSHerbert Dürr // TODO: improve linear walk? 286*43ad51ffSHerbert Dürr int nCharIndex = 0; 287*43ad51ffSHerbert Dürr const sal_UCS4* pRange = &mpRangeCodes[0]; 288*43ad51ffSHerbert Dürr for( int i = 0; i < mnRangeCount; ++i ) 289*43ad51ffSHerbert Dürr { 290*43ad51ffSHerbert Dürr sal_UCS4 cFirst = *(pRange++); 291*43ad51ffSHerbert Dürr sal_UCS4 cLast = *(pRange++); 292*43ad51ffSHerbert Dürr if( cChar >= cLast ) 293*43ad51ffSHerbert Dürr nCharIndex += cLast - cFirst; 294*43ad51ffSHerbert Dürr else if( cChar >= cFirst ) 295*43ad51ffSHerbert Dürr return nCharIndex + (cChar - cFirst); 296*43ad51ffSHerbert Dürr else 297*43ad51ffSHerbert Dürr break; 298*43ad51ffSHerbert Dürr } 299*43ad51ffSHerbert Dürr 300*43ad51ffSHerbert Dürr return -1; 301*43ad51ffSHerbert Dürr } 302*43ad51ffSHerbert Dürr 303*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 304*43ad51ffSHerbert Dürr 305*43ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetCharFromIndex( int nCharIndex ) const 306*43ad51ffSHerbert Dürr { 307*43ad51ffSHerbert Dürr // TODO: improve linear walk? 308*43ad51ffSHerbert Dürr const sal_UCS4* pRange = &mpRangeCodes[0]; 309*43ad51ffSHerbert Dürr for( int i = 0; i < mnRangeCount; ++i ) 310*43ad51ffSHerbert Dürr { 311*43ad51ffSHerbert Dürr sal_UCS4 cFirst = *(pRange++); 312*43ad51ffSHerbert Dürr sal_UCS4 cLast = *(pRange++); 313*43ad51ffSHerbert Dürr nCharIndex -= cLast - cFirst; 314*43ad51ffSHerbert Dürr if( nCharIndex < 0 ) 315*43ad51ffSHerbert Dürr return (cLast + nCharIndex); 316*43ad51ffSHerbert Dürr } 317*43ad51ffSHerbert Dürr 318*43ad51ffSHerbert Dürr // we can only get here with an out-of-bounds charindex 319*43ad51ffSHerbert Dürr return mpRangeCodes[0]; 320*43ad51ffSHerbert Dürr } 321*43ad51ffSHerbert Dürr 322*43ad51ffSHerbert Dürr // ======================================================================= 323*43ad51ffSHerbert Dürr 324*43ad51ffSHerbert Dürr static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);} 325*43ad51ffSHerbert Dürr static unsigned Getsal_uInt16( const unsigned char* p ){ return((p[0]<<8) | p[1]);} 326*43ad51ffSHerbert Dürr static int GetSShort( const unsigned char* p ){ return((static_cast<signed char>(p[0])<<8)|p[1]);} 327*43ad51ffSHerbert Dürr 328*43ad51ffSHerbert Dürr // TODO: move CMAP parsing directly into the ImplFontCharMap class 329*43ad51ffSHerbert Dürr bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult ) 330*43ad51ffSHerbert Dürr { 331*43ad51ffSHerbert Dürr rResult.mpRangeCodes = NULL; 332*43ad51ffSHerbert Dürr rResult.mpStartGlyphs= NULL; 333*43ad51ffSHerbert Dürr rResult.mpGlyphIds = NULL; 334*43ad51ffSHerbert Dürr rResult.mnRangeCount = 0; 335*43ad51ffSHerbert Dürr rResult.mbRecoded = false; 336*43ad51ffSHerbert Dürr rResult.mbSymbolic = false; 337*43ad51ffSHerbert Dürr 338*43ad51ffSHerbert Dürr // parse the table header and check for validity 339*43ad51ffSHerbert Dürr if( !pCmap || (nLength < 24) ) 340*43ad51ffSHerbert Dürr return false; 341*43ad51ffSHerbert Dürr 342*43ad51ffSHerbert Dürr if( Getsal_uInt16( pCmap ) != 0x0000 ) // simple check for CMAP corruption 343*43ad51ffSHerbert Dürr return false; 344*43ad51ffSHerbert Dürr 345*43ad51ffSHerbert Dürr int nSubTables = Getsal_uInt16( pCmap + 2 ); 346*43ad51ffSHerbert Dürr if( (nSubTables <= 0) || (nLength < (24 + 8*nSubTables)) ) 347*43ad51ffSHerbert Dürr return false; 348*43ad51ffSHerbert Dürr 349*43ad51ffSHerbert Dürr // find the most interesting subtable in the CMAP 350*43ad51ffSHerbert Dürr rtl_TextEncoding eRecodeFrom = RTL_TEXTENCODING_UNICODE; 351*43ad51ffSHerbert Dürr int nOffset = 0; 352*43ad51ffSHerbert Dürr int nFormat = -1; 353*43ad51ffSHerbert Dürr int nBestVal = 0; 354*43ad51ffSHerbert Dürr for( const unsigned char* p = pCmap + 4; --nSubTables >= 0; p += 8 ) 355*43ad51ffSHerbert Dürr { 356*43ad51ffSHerbert Dürr int nPlatform = Getsal_uInt16( p ); 357*43ad51ffSHerbert Dürr int nEncoding = Getsal_uInt16( p+2 ); 358*43ad51ffSHerbert Dürr int nPlatformEncoding = (nPlatform << 8) + nEncoding; 359*43ad51ffSHerbert Dürr 360*43ad51ffSHerbert Dürr int nValue; 361*43ad51ffSHerbert Dürr rtl_TextEncoding eTmpEncoding = RTL_TEXTENCODING_UNICODE; 362*43ad51ffSHerbert Dürr switch( nPlatformEncoding ) 363*43ad51ffSHerbert Dürr { 364*43ad51ffSHerbert Dürr case 0x000: nValue = 20; break; // Unicode 1.0 365*43ad51ffSHerbert Dürr case 0x001: nValue = 21; break; // Unicode 1.1 366*43ad51ffSHerbert Dürr case 0x002: nValue = 22; break; // iso10646_1993 367*43ad51ffSHerbert Dürr case 0x003: nValue = 23; break; // UCS-2 368*43ad51ffSHerbert Dürr case 0x004: nValue = 24; break; // UCS-4 369*43ad51ffSHerbert Dürr case 0x100: nValue = 22; break; // Mac Unicode<2.0 370*43ad51ffSHerbert Dürr case 0x103: nValue = 23; break; // Mac Unicode>2.0 371*43ad51ffSHerbert Dürr case 0x300: nValue = 5; rResult.mbSymbolic = true; break; // Win Symbol 372*43ad51ffSHerbert Dürr case 0x301: nValue = 28; break; // Win UCS-2 373*43ad51ffSHerbert Dürr case 0x30A: nValue = 29; break; // Win-UCS-4 374*43ad51ffSHerbert Dürr case 0x302: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_SHIFT_JIS; break; 375*43ad51ffSHerbert Dürr case 0x303: nValue = 12; eTmpEncoding = RTL_TEXTENCODING_GB_18030; break; 376*43ad51ffSHerbert Dürr case 0x304: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_BIG5; break; 377*43ad51ffSHerbert Dürr case 0x305: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_MS_949; break; 378*43ad51ffSHerbert Dürr case 0x306: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_MS_1361; break; 379*43ad51ffSHerbert Dürr default: nValue = 0; break; 380*43ad51ffSHerbert Dürr } 381*43ad51ffSHerbert Dürr 382*43ad51ffSHerbert Dürr if( nValue <= 0 ) // ignore unknown encodings 383*43ad51ffSHerbert Dürr continue; 384*43ad51ffSHerbert Dürr 385*43ad51ffSHerbert Dürr int nTmpOffset = GetUInt( p+4 ); 386*43ad51ffSHerbert Dürr int nTmpFormat = Getsal_uInt16( pCmap + nTmpOffset ); 387*43ad51ffSHerbert Dürr if( nTmpFormat == 12 ) // 32bit code -> glyph map format 388*43ad51ffSHerbert Dürr nValue += 3; 389*43ad51ffSHerbert Dürr else if( nTmpFormat != 4 ) // 16bit code -> glyph map format 390*43ad51ffSHerbert Dürr continue; // ignore other formats 391*43ad51ffSHerbert Dürr 392*43ad51ffSHerbert Dürr if( nBestVal < nValue ) 393*43ad51ffSHerbert Dürr { 394*43ad51ffSHerbert Dürr nBestVal = nValue; 395*43ad51ffSHerbert Dürr nOffset = nTmpOffset; 396*43ad51ffSHerbert Dürr nFormat = nTmpFormat; 397*43ad51ffSHerbert Dürr eRecodeFrom = eTmpEncoding; 398*43ad51ffSHerbert Dürr } 399*43ad51ffSHerbert Dürr } 400*43ad51ffSHerbert Dürr 401*43ad51ffSHerbert Dürr // parse the best CMAP subtable 402*43ad51ffSHerbert Dürr int nRangeCount = 0; 403*43ad51ffSHerbert Dürr sal_UCS4* pCodePairs = NULL; 404*43ad51ffSHerbert Dürr int* pStartGlyphs = NULL; 405*43ad51ffSHerbert Dürr 406*43ad51ffSHerbert Dürr typedef std::vector<sal_uInt16> U16Vector; 407*43ad51ffSHerbert Dürr U16Vector aGlyphIdArray; 408*43ad51ffSHerbert Dürr aGlyphIdArray.reserve( 0x1000 ); 409*43ad51ffSHerbert Dürr aGlyphIdArray.push_back( 0 ); 410*43ad51ffSHerbert Dürr 411*43ad51ffSHerbert Dürr // format 4, the most common 16bit char mapping table 412*43ad51ffSHerbert Dürr if( (nFormat == 4) && ((nOffset+16) < nLength) ) 413*43ad51ffSHerbert Dürr { 414*43ad51ffSHerbert Dürr int nSegCountX2 = Getsal_uInt16( pCmap + nOffset + 6 ); 415*43ad51ffSHerbert Dürr nRangeCount = nSegCountX2/2 - 1; 416*43ad51ffSHerbert Dürr pCodePairs = new sal_UCS4[ nRangeCount * 2 ]; 417*43ad51ffSHerbert Dürr pStartGlyphs = new int[ nRangeCount ]; 418*43ad51ffSHerbert Dürr const unsigned char* pLimitBase = pCmap + nOffset + 14; 419*43ad51ffSHerbert Dürr const unsigned char* pBeginBase = pLimitBase + nSegCountX2 + 2; 420*43ad51ffSHerbert Dürr const unsigned char* pDeltaBase = pBeginBase + nSegCountX2; 421*43ad51ffSHerbert Dürr const unsigned char* pOffsetBase = pDeltaBase + nSegCountX2; 422*43ad51ffSHerbert Dürr sal_UCS4* pCP = pCodePairs; 423*43ad51ffSHerbert Dürr for( int i = 0; i < nRangeCount; ++i ) 424*43ad51ffSHerbert Dürr { 425*43ad51ffSHerbert Dürr const sal_UCS4 cMinChar = Getsal_uInt16( pBeginBase + 2*i ); 426*43ad51ffSHerbert Dürr const sal_UCS4 cMaxChar = Getsal_uInt16( pLimitBase + 2*i ); 427*43ad51ffSHerbert Dürr const int nGlyphDelta = GetSShort( pDeltaBase + 2*i ); 428*43ad51ffSHerbert Dürr const int nRangeOffset = Getsal_uInt16( pOffsetBase + 2*i ); 429*43ad51ffSHerbert Dürr if( cMinChar > cMaxChar ) // no sane font should trigger this 430*43ad51ffSHerbert Dürr break; 431*43ad51ffSHerbert Dürr if( cMaxChar == 0xFFFF ) 432*43ad51ffSHerbert Dürr break; 433*43ad51ffSHerbert Dürr *(pCP++) = cMinChar; 434*43ad51ffSHerbert Dürr *(pCP++) = cMaxChar + 1; 435*43ad51ffSHerbert Dürr if( !nRangeOffset ) { 436*43ad51ffSHerbert Dürr // glyphid can be calculated directly 437*43ad51ffSHerbert Dürr pStartGlyphs[i] = (cMinChar + nGlyphDelta) & 0xFFFF; 438*43ad51ffSHerbert Dürr } else { 439*43ad51ffSHerbert Dürr // update the glyphid-array with the glyphs in this range 440*43ad51ffSHerbert Dürr pStartGlyphs[i] = -(int)aGlyphIdArray.size(); 441*43ad51ffSHerbert Dürr const unsigned char* pGlyphIdPtr = pOffsetBase + 2*i + nRangeOffset; 442*43ad51ffSHerbert Dürr for( sal_UCS4 c = cMinChar; c <= cMaxChar; ++c, pGlyphIdPtr+=2 ) { 443*43ad51ffSHerbert Dürr const int nGlyphIndex = Getsal_uInt16( pGlyphIdPtr ) + nGlyphDelta; 444*43ad51ffSHerbert Dürr aGlyphIdArray.push_back( static_cast<sal_uInt16>(nGlyphIndex) ); 445*43ad51ffSHerbert Dürr } 446*43ad51ffSHerbert Dürr } 447*43ad51ffSHerbert Dürr } 448*43ad51ffSHerbert Dürr nRangeCount = (pCP - pCodePairs) / 2; 449*43ad51ffSHerbert Dürr } 450*43ad51ffSHerbert Dürr // format 12, the most common 32bit char mapping table 451*43ad51ffSHerbert Dürr else if( (nFormat == 12) && ((nOffset+16) < nLength) ) 452*43ad51ffSHerbert Dürr { 453*43ad51ffSHerbert Dürr nRangeCount = GetUInt( pCmap + nOffset + 12 ); 454*43ad51ffSHerbert Dürr pCodePairs = new sal_UCS4[ nRangeCount * 2 ]; 455*43ad51ffSHerbert Dürr pStartGlyphs = new int[ nRangeCount ]; 456*43ad51ffSHerbert Dürr const unsigned char* pGroup = pCmap + nOffset + 16; 457*43ad51ffSHerbert Dürr sal_UCS4* pCP = pCodePairs; 458*43ad51ffSHerbert Dürr for( int i = 0; i < nRangeCount; ++i ) 459*43ad51ffSHerbert Dürr { 460*43ad51ffSHerbert Dürr sal_UCS4 cMinChar = GetUInt( pGroup + 0 ); 461*43ad51ffSHerbert Dürr sal_UCS4 cMaxChar = GetUInt( pGroup + 4 ); 462*43ad51ffSHerbert Dürr int nGlyphId = GetUInt( pGroup + 8 ); 463*43ad51ffSHerbert Dürr pGroup += 12; 464*43ad51ffSHerbert Dürr #if 0 // TODO: remove unicode baseplane clipping for UCS-4 support 465*43ad51ffSHerbert Dürr if( cMinChar > 0xFFFF ) 466*43ad51ffSHerbert Dürr continue; 467*43ad51ffSHerbert Dürr if( cMaxChar > 0xFFFF ) 468*43ad51ffSHerbert Dürr cMaxChar = 0xFFFF; 469*43ad51ffSHerbert Dürr #else 470*43ad51ffSHerbert Dürr if( cMinChar > cMaxChar ) // no sane font should trigger this 471*43ad51ffSHerbert Dürr break; 472*43ad51ffSHerbert Dürr #endif 473*43ad51ffSHerbert Dürr *(pCP++) = cMinChar; 474*43ad51ffSHerbert Dürr *(pCP++) = cMaxChar + 1; 475*43ad51ffSHerbert Dürr pStartGlyphs[i] = nGlyphId; 476*43ad51ffSHerbert Dürr } 477*43ad51ffSHerbert Dürr nRangeCount = (pCP - pCodePairs) / 2; 478*43ad51ffSHerbert Dürr } 479*43ad51ffSHerbert Dürr 480*43ad51ffSHerbert Dürr // check if any subtable resulted in something usable 481*43ad51ffSHerbert Dürr if( nRangeCount <= 0 ) 482*43ad51ffSHerbert Dürr { 483*43ad51ffSHerbert Dürr delete[] pCodePairs; 484*43ad51ffSHerbert Dürr delete[] pStartGlyphs; 485*43ad51ffSHerbert Dürr 486*43ad51ffSHerbert Dürr // even when no CMAP is available we know it for symbol fonts 487*43ad51ffSHerbert Dürr if( rResult.mbSymbolic ) 488*43ad51ffSHerbert Dürr { 489*43ad51ffSHerbert Dürr pCodePairs = new sal_UCS4[4]; 490*43ad51ffSHerbert Dürr pCodePairs[0] = 0x0020; // aliased symbols 491*43ad51ffSHerbert Dürr pCodePairs[1] = 0x0100; 492*43ad51ffSHerbert Dürr pCodePairs[2] = 0xF020; // original symbols 493*43ad51ffSHerbert Dürr pCodePairs[3] = 0xF100; 494*43ad51ffSHerbert Dürr rResult.mpRangeCodes = pCodePairs; 495*43ad51ffSHerbert Dürr rResult.mnRangeCount = 2; 496*43ad51ffSHerbert Dürr return true; 497*43ad51ffSHerbert Dürr } 498*43ad51ffSHerbert Dürr 499*43ad51ffSHerbert Dürr return false; 500*43ad51ffSHerbert Dürr } 501*43ad51ffSHerbert Dürr 502*43ad51ffSHerbert Dürr // recode the code ranges to their unicode encoded ranges if needed 503*43ad51ffSHerbert Dürr rtl_TextToUnicodeConverter aConverter = NULL; 504*43ad51ffSHerbert Dürr rtl_UnicodeToTextContext aCvtContext = NULL; 505*43ad51ffSHerbert Dürr 506*43ad51ffSHerbert Dürr rResult.mbRecoded = ( eRecodeFrom != RTL_TEXTENCODING_UNICODE ); 507*43ad51ffSHerbert Dürr if( rResult.mbRecoded ) 508*43ad51ffSHerbert Dürr { 509*43ad51ffSHerbert Dürr aConverter = rtl_createTextToUnicodeConverter( eRecodeFrom ); 510*43ad51ffSHerbert Dürr aCvtContext = rtl_createTextToUnicodeContext( aConverter ); 511*43ad51ffSHerbert Dürr } 512*43ad51ffSHerbert Dürr 513*43ad51ffSHerbert Dürr if( aConverter && aCvtContext ) 514*43ad51ffSHerbert Dürr { 515*43ad51ffSHerbert Dürr // determine the set of supported unicodes from encoded ranges 516*43ad51ffSHerbert Dürr typedef std::set<sal_UCS4> Ucs4Set; 517*43ad51ffSHerbert Dürr Ucs4Set aSupportedUnicodes; 518*43ad51ffSHerbert Dürr 519*43ad51ffSHerbert Dürr static const int NINSIZE = 64; 520*43ad51ffSHerbert Dürr static const int NOUTSIZE = 64; 521*43ad51ffSHerbert Dürr sal_Char cCharsInp[ NINSIZE ]; 522*43ad51ffSHerbert Dürr sal_Unicode cCharsOut[ NOUTSIZE ]; 523*43ad51ffSHerbert Dürr sal_UCS4* pCP = pCodePairs; 524*43ad51ffSHerbert Dürr for( int i = 0; i < nRangeCount; ++i ) 525*43ad51ffSHerbert Dürr { 526*43ad51ffSHerbert Dürr sal_UCS4 cMin = *(pCP++); 527*43ad51ffSHerbert Dürr sal_UCS4 cEnd = *(pCP++); 528*43ad51ffSHerbert Dürr while( cMin < cEnd ) 529*43ad51ffSHerbert Dürr { 530*43ad51ffSHerbert Dürr int j = 0; 531*43ad51ffSHerbert Dürr for(; (cMin < cEnd) && (j < NINSIZE); ++cMin ) 532*43ad51ffSHerbert Dürr { 533*43ad51ffSHerbert Dürr if( cMin >= 0x0100 ) 534*43ad51ffSHerbert Dürr cCharsInp[ j++ ] = static_cast<sal_Char>(cMin >> 8); 535*43ad51ffSHerbert Dürr if( (cMin >= 0x0100) || (cMin < 0x00A0) ) 536*43ad51ffSHerbert Dürr cCharsInp[ j++ ] = static_cast<sal_Char>(cMin); 537*43ad51ffSHerbert Dürr } 538*43ad51ffSHerbert Dürr 539*43ad51ffSHerbert Dürr sal_uInt32 nCvtInfo; 540*43ad51ffSHerbert Dürr sal_Size nSrcCvtBytes; 541*43ad51ffSHerbert Dürr int nOutLen = rtl_convertTextToUnicode( 542*43ad51ffSHerbert Dürr aConverter, aCvtContext, 543*43ad51ffSHerbert Dürr cCharsInp, j, cCharsOut, NOUTSIZE, 544*43ad51ffSHerbert Dürr RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE 545*43ad51ffSHerbert Dürr | RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE, 546*43ad51ffSHerbert Dürr &nCvtInfo, &nSrcCvtBytes ); 547*43ad51ffSHerbert Dürr 548*43ad51ffSHerbert Dürr for( j = 0; j < nOutLen; ++j ) 549*43ad51ffSHerbert Dürr aSupportedUnicodes.insert( cCharsOut[j] ); 550*43ad51ffSHerbert Dürr } 551*43ad51ffSHerbert Dürr } 552*43ad51ffSHerbert Dürr 553*43ad51ffSHerbert Dürr rtl_destroyTextToUnicodeConverter( aCvtContext ); 554*43ad51ffSHerbert Dürr rtl_destroyTextToUnicodeConverter( aConverter ); 555*43ad51ffSHerbert Dürr 556*43ad51ffSHerbert Dürr // convert the set of supported unicodes to ranges 557*43ad51ffSHerbert Dürr typedef std::vector<sal_UCS4> Ucs4Vector; 558*43ad51ffSHerbert Dürr Ucs4Vector aSupportedRanges; 559*43ad51ffSHerbert Dürr 560*43ad51ffSHerbert Dürr Ucs4Set::const_iterator itChar = aSupportedUnicodes.begin(); 561*43ad51ffSHerbert Dürr for(; itChar != aSupportedUnicodes.end(); ++itChar ) 562*43ad51ffSHerbert Dürr { 563*43ad51ffSHerbert Dürr if( aSupportedRanges.empty() 564*43ad51ffSHerbert Dürr || (aSupportedRanges.back() != *itChar) ) 565*43ad51ffSHerbert Dürr { 566*43ad51ffSHerbert Dürr // add new range beginning with current unicode 567*43ad51ffSHerbert Dürr aSupportedRanges.push_back( *itChar ); 568*43ad51ffSHerbert Dürr aSupportedRanges.push_back( 0 ); 569*43ad51ffSHerbert Dürr } 570*43ad51ffSHerbert Dürr 571*43ad51ffSHerbert Dürr // extend existing range to include current unicode 572*43ad51ffSHerbert Dürr aSupportedRanges.back() = *itChar + 1; 573*43ad51ffSHerbert Dürr } 574*43ad51ffSHerbert Dürr 575*43ad51ffSHerbert Dürr // glyph mapping for non-unicode fonts not implemented 576*43ad51ffSHerbert Dürr delete[] pStartGlyphs; 577*43ad51ffSHerbert Dürr pStartGlyphs = NULL; 578*43ad51ffSHerbert Dürr aGlyphIdArray.clear(); 579*43ad51ffSHerbert Dürr 580*43ad51ffSHerbert Dürr // make a pCodePairs array using the vector from above 581*43ad51ffSHerbert Dürr delete[] pCodePairs; 582*43ad51ffSHerbert Dürr nRangeCount = aSupportedRanges.size() / 2; 583*43ad51ffSHerbert Dürr if( nRangeCount <= 0 ) 584*43ad51ffSHerbert Dürr return false; 585*43ad51ffSHerbert Dürr pCodePairs = new sal_UCS4[ nRangeCount * 2 ]; 586*43ad51ffSHerbert Dürr Ucs4Vector::const_iterator itInt = aSupportedRanges.begin(); 587*43ad51ffSHerbert Dürr for( pCP = pCodePairs; itInt != aSupportedRanges.end(); ++itInt ) 588*43ad51ffSHerbert Dürr *(pCP++) = *itInt; 589*43ad51ffSHerbert Dürr } 590*43ad51ffSHerbert Dürr 591*43ad51ffSHerbert Dürr // prepare the glyphid-array if needed 592*43ad51ffSHerbert Dürr // TODO: merge ranges if they are close enough? 593*43ad51ffSHerbert Dürr sal_uInt16* pGlyphIds = NULL; 594*43ad51ffSHerbert Dürr if( !aGlyphIdArray.empty()) 595*43ad51ffSHerbert Dürr { 596*43ad51ffSHerbert Dürr pGlyphIds = new sal_uInt16[ aGlyphIdArray.size() ]; 597*43ad51ffSHerbert Dürr sal_uInt16* pOut = pGlyphIds; 598*43ad51ffSHerbert Dürr U16Vector::const_iterator it = aGlyphIdArray.begin(); 599*43ad51ffSHerbert Dürr while( it != aGlyphIdArray.end() ) 600*43ad51ffSHerbert Dürr *(pOut++) = *(it++); 601*43ad51ffSHerbert Dürr } 602*43ad51ffSHerbert Dürr 603*43ad51ffSHerbert Dürr // update the result struct 604*43ad51ffSHerbert Dürr rResult.mpRangeCodes = pCodePairs; 605*43ad51ffSHerbert Dürr rResult.mpStartGlyphs = pStartGlyphs; 606*43ad51ffSHerbert Dürr rResult.mnRangeCount = nRangeCount; 607*43ad51ffSHerbert Dürr rResult.mpGlyphIds = pGlyphIds; 608*43ad51ffSHerbert Dürr return true; 609*43ad51ffSHerbert Dürr } 610*43ad51ffSHerbert Dürr 611*43ad51ffSHerbert Dürr // ======================================================================= 612*43ad51ffSHerbert Dürr 613*43ad51ffSHerbert Dürr FontCharMap::FontCharMap() 614*43ad51ffSHerbert Dürr : mpImpl( ImplFontCharMap::GetDefaultMap() ) 615*43ad51ffSHerbert Dürr {} 616*43ad51ffSHerbert Dürr 617*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 618*43ad51ffSHerbert Dürr 619*43ad51ffSHerbert Dürr FontCharMap::~FontCharMap() 620*43ad51ffSHerbert Dürr { 621*43ad51ffSHerbert Dürr mpImpl->DeReference(); 622*43ad51ffSHerbert Dürr mpImpl = NULL; 623*43ad51ffSHerbert Dürr } 624*43ad51ffSHerbert Dürr 625*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 626*43ad51ffSHerbert Dürr 627*43ad51ffSHerbert Dürr int FontCharMap::GetCharCount() const 628*43ad51ffSHerbert Dürr { 629*43ad51ffSHerbert Dürr return mpImpl->GetCharCount(); 630*43ad51ffSHerbert Dürr } 631*43ad51ffSHerbert Dürr 632*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 633*43ad51ffSHerbert Dürr 634*43ad51ffSHerbert Dürr int FontCharMap::CountCharsInRange( sal_UCS4 cMin, sal_UCS4 cMax ) const 635*43ad51ffSHerbert Dürr { 636*43ad51ffSHerbert Dürr return mpImpl->CountCharsInRange( cMin, cMax ); 637*43ad51ffSHerbert Dürr } 638*43ad51ffSHerbert Dürr 639*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 640*43ad51ffSHerbert Dürr 641*43ad51ffSHerbert Dürr void FontCharMap::Reset( const ImplFontCharMap* pNewMap ) 642*43ad51ffSHerbert Dürr { 643*43ad51ffSHerbert Dürr if( pNewMap == NULL ) 644*43ad51ffSHerbert Dürr { 645*43ad51ffSHerbert Dürr mpImpl->DeReference(); 646*43ad51ffSHerbert Dürr mpImpl = ImplFontCharMap::GetDefaultMap(); 647*43ad51ffSHerbert Dürr } 648*43ad51ffSHerbert Dürr else if( pNewMap != mpImpl ) 649*43ad51ffSHerbert Dürr { 650*43ad51ffSHerbert Dürr mpImpl->DeReference(); 651*43ad51ffSHerbert Dürr mpImpl = pNewMap; 652*43ad51ffSHerbert Dürr mpImpl->AddReference(); 653*43ad51ffSHerbert Dürr } 654*43ad51ffSHerbert Dürr } 655*43ad51ffSHerbert Dürr 656*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 657*43ad51ffSHerbert Dürr 658*43ad51ffSHerbert Dürr bool FontCharMap::IsDefaultMap() const 659*43ad51ffSHerbert Dürr { 660*43ad51ffSHerbert Dürr return mpImpl->IsDefaultMap(); 661*43ad51ffSHerbert Dürr } 662*43ad51ffSHerbert Dürr 663*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 664*43ad51ffSHerbert Dürr 665*43ad51ffSHerbert Dürr bool FontCharMap::HasChar( sal_UCS4 cChar ) const 666*43ad51ffSHerbert Dürr { 667*43ad51ffSHerbert Dürr return mpImpl->HasChar( cChar ); 668*43ad51ffSHerbert Dürr } 669*43ad51ffSHerbert Dürr 670*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 671*43ad51ffSHerbert Dürr 672*43ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetFirstChar() const 673*43ad51ffSHerbert Dürr { 674*43ad51ffSHerbert Dürr return mpImpl->GetFirstChar(); 675*43ad51ffSHerbert Dürr } 676*43ad51ffSHerbert Dürr 677*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 678*43ad51ffSHerbert Dürr 679*43ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetLastChar() const 680*43ad51ffSHerbert Dürr { 681*43ad51ffSHerbert Dürr return mpImpl->GetLastChar(); 682*43ad51ffSHerbert Dürr } 683*43ad51ffSHerbert Dürr 684*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 685*43ad51ffSHerbert Dürr 686*43ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetNextChar( sal_UCS4 cChar ) const 687*43ad51ffSHerbert Dürr { 688*43ad51ffSHerbert Dürr return mpImpl->GetNextChar( cChar ); 689*43ad51ffSHerbert Dürr } 690*43ad51ffSHerbert Dürr 691*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 692*43ad51ffSHerbert Dürr 693*43ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetPrevChar( sal_UCS4 cChar ) const 694*43ad51ffSHerbert Dürr { 695*43ad51ffSHerbert Dürr return mpImpl->GetPrevChar( cChar ); 696*43ad51ffSHerbert Dürr } 697*43ad51ffSHerbert Dürr 698*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 699*43ad51ffSHerbert Dürr 700*43ad51ffSHerbert Dürr int FontCharMap::GetIndexFromChar( sal_UCS4 cChar ) const 701*43ad51ffSHerbert Dürr { 702*43ad51ffSHerbert Dürr return mpImpl->GetIndexFromChar( cChar ); 703*43ad51ffSHerbert Dürr } 704*43ad51ffSHerbert Dürr 705*43ad51ffSHerbert Dürr // ----------------------------------------------------------------------- 706*43ad51ffSHerbert Dürr 707*43ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetCharFromIndex( int nIndex ) const 708*43ad51ffSHerbert Dürr { 709*43ad51ffSHerbert Dürr return mpImpl->GetCharFromIndex( nIndex ); 710*43ad51ffSHerbert Dürr } 711*43ad51ffSHerbert Dürr 712*43ad51ffSHerbert Dürr // ======================================================================= 713*43ad51ffSHerbert Dürr 714*43ad51ffSHerbert Dürr // on some systems we have to get the font attributes from the name table 715*43ad51ffSHerbert Dürr // since neither head's macStyle nor OS/2's panose are easily available 716*43ad51ffSHerbert Dürr // during font enumeration. macStyle bits would be not sufficient anyway 717*43ad51ffSHerbert Dürr // and SFNT fonts on Mac usually do not contain an OS/2 table. 718*43ad51ffSHerbert Dürr void UpdateAttributesFromPSName( const String& rPSName, ImplDevFontAttributes& rDFA ) 719*43ad51ffSHerbert Dürr { 720*43ad51ffSHerbert Dürr ByteString aPSName( rPSName, RTL_TEXTENCODING_UTF8 ); 721*43ad51ffSHerbert Dürr aPSName.ToLowerAscii(); 722*43ad51ffSHerbert Dürr 723*43ad51ffSHerbert Dürr // TODO: use a multi-string ignore-case matcher once it becomes available 724*43ad51ffSHerbert Dürr if( (aPSName.Search("regular") != STRING_NOTFOUND) 725*43ad51ffSHerbert Dürr || (aPSName.Search("normal") != STRING_NOTFOUND) 726*43ad51ffSHerbert Dürr || (aPSName.Search("roman") != STRING_NOTFOUND) 727*43ad51ffSHerbert Dürr || (aPSName.Search("medium") != STRING_NOTFOUND) 728*43ad51ffSHerbert Dürr || (aPSName.Search("plain") != STRING_NOTFOUND) 729*43ad51ffSHerbert Dürr || (aPSName.Search("standard") != STRING_NOTFOUND) 730*43ad51ffSHerbert Dürr || (aPSName.Search("std") != STRING_NOTFOUND) ) 731*43ad51ffSHerbert Dürr { 732*43ad51ffSHerbert Dürr rDFA.meWidthType = WIDTH_NORMAL; 733*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_NORMAL; 734*43ad51ffSHerbert Dürr rDFA.meItalic = ITALIC_NONE; 735*43ad51ffSHerbert Dürr } 736*43ad51ffSHerbert Dürr 737*43ad51ffSHerbert Dürr // heuristics for font weight 738*43ad51ffSHerbert Dürr if (aPSName.Search("extrablack") != STRING_NOTFOUND) 739*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_BLACK; 740*43ad51ffSHerbert Dürr else if (aPSName.Search("black") != STRING_NOTFOUND) 741*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_BLACK; 742*43ad51ffSHerbert Dürr #if 1 743*43ad51ffSHerbert Dürr else if (aPSName.Search("book") != STRING_NOTFOUND) 744*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_NORMAL; 745*43ad51ffSHerbert Dürr #endif 746*43ad51ffSHerbert Dürr else if( (aPSName.Search("semibold") != STRING_NOTFOUND) 747*43ad51ffSHerbert Dürr || (aPSName.Search("smbd") != STRING_NOTFOUND)) 748*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_SEMIBOLD; 749*43ad51ffSHerbert Dürr else if( aPSName.Search("ultrabold") != STRING_NOTFOUND) 750*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_ULTRABOLD; 751*43ad51ffSHerbert Dürr else if( aPSName.Search("extrabold") != STRING_NOTFOUND) 752*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_BLACK; 753*43ad51ffSHerbert Dürr else if( (aPSName.Search("bold") != STRING_NOTFOUND) 754*43ad51ffSHerbert Dürr || (aPSName.Search("-bd") != STRING_NOTFOUND)) 755*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_BOLD; 756*43ad51ffSHerbert Dürr else if( aPSName.Search("extralight") != STRING_NOTFOUND) 757*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_ULTRALIGHT; 758*43ad51ffSHerbert Dürr else if( aPSName.Search("ultralight") != STRING_NOTFOUND) 759*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_ULTRALIGHT; 760*43ad51ffSHerbert Dürr else if( aPSName.Search("light") != STRING_NOTFOUND) 761*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_LIGHT; 762*43ad51ffSHerbert Dürr else if( aPSName.Search("thin") != STRING_NOTFOUND) 763*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_THIN; 764*43ad51ffSHerbert Dürr else if( aPSName.Search("-w3") != STRING_NOTFOUND) 765*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_LIGHT; 766*43ad51ffSHerbert Dürr else if( aPSName.Search("-w4") != STRING_NOTFOUND) 767*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_SEMILIGHT; 768*43ad51ffSHerbert Dürr else if( aPSName.Search("-w5") != STRING_NOTFOUND) 769*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_NORMAL; 770*43ad51ffSHerbert Dürr else if( aPSName.Search("-w6") != STRING_NOTFOUND) 771*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_SEMIBOLD; 772*43ad51ffSHerbert Dürr else if( aPSName.Search("-w7") != STRING_NOTFOUND) 773*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_BOLD; 774*43ad51ffSHerbert Dürr else if( aPSName.Search("-w8") != STRING_NOTFOUND) 775*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_ULTRABOLD; 776*43ad51ffSHerbert Dürr else if( aPSName.Search("-w9") != STRING_NOTFOUND) 777*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_BLACK; 778*43ad51ffSHerbert Dürr 779*43ad51ffSHerbert Dürr // heuristics for font slant 780*43ad51ffSHerbert Dürr if( (aPSName.Search("italic") != STRING_NOTFOUND) 781*43ad51ffSHerbert Dürr || (aPSName.Search(" ital") != STRING_NOTFOUND) 782*43ad51ffSHerbert Dürr || (aPSName.Search("cursive") != STRING_NOTFOUND) 783*43ad51ffSHerbert Dürr || (aPSName.Search("-it") != STRING_NOTFOUND) 784*43ad51ffSHerbert Dürr || (aPSName.Search("lightit") != STRING_NOTFOUND) 785*43ad51ffSHerbert Dürr || (aPSName.Search("mediumit") != STRING_NOTFOUND) 786*43ad51ffSHerbert Dürr || (aPSName.Search("boldit") != STRING_NOTFOUND) 787*43ad51ffSHerbert Dürr || (aPSName.Search("cnit") != STRING_NOTFOUND) 788*43ad51ffSHerbert Dürr || (aPSName.Search("bdcn") != STRING_NOTFOUND) 789*43ad51ffSHerbert Dürr || (aPSName.Search("bdit") != STRING_NOTFOUND) 790*43ad51ffSHerbert Dürr || (aPSName.Search("condit") != STRING_NOTFOUND) 791*43ad51ffSHerbert Dürr || (aPSName.Search("bookit") != STRING_NOTFOUND) 792*43ad51ffSHerbert Dürr || (aPSName.Search("blackit") != STRING_NOTFOUND) ) 793*43ad51ffSHerbert Dürr rDFA.meItalic = ITALIC_NORMAL; 794*43ad51ffSHerbert Dürr if( (aPSName.Search("oblique") != STRING_NOTFOUND) 795*43ad51ffSHerbert Dürr || (aPSName.Search("inclined") != STRING_NOTFOUND) 796*43ad51ffSHerbert Dürr || (aPSName.Search("slanted") != STRING_NOTFOUND) ) 797*43ad51ffSHerbert Dürr rDFA.meItalic = ITALIC_OBLIQUE; 798*43ad51ffSHerbert Dürr 799*43ad51ffSHerbert Dürr // heuristics for font width 800*43ad51ffSHerbert Dürr if( (aPSName.Search("condensed") != STRING_NOTFOUND) 801*43ad51ffSHerbert Dürr || (aPSName.Search("-cond") != STRING_NOTFOUND) 802*43ad51ffSHerbert Dürr || (aPSName.Search("boldcond") != STRING_NOTFOUND) 803*43ad51ffSHerbert Dürr || (aPSName.Search("boldcn") != STRING_NOTFOUND) 804*43ad51ffSHerbert Dürr || (aPSName.Search("cnit") != STRING_NOTFOUND) ) 805*43ad51ffSHerbert Dürr rDFA.meWidthType = WIDTH_CONDENSED; 806*43ad51ffSHerbert Dürr else if (aPSName.Search("narrow") != STRING_NOTFOUND) 807*43ad51ffSHerbert Dürr rDFA.meWidthType = WIDTH_SEMI_CONDENSED; 808*43ad51ffSHerbert Dürr else if (aPSName.Search("expanded") != STRING_NOTFOUND) 809*43ad51ffSHerbert Dürr rDFA.meWidthType = WIDTH_EXPANDED; 810*43ad51ffSHerbert Dürr else if (aPSName.Search("wide") != STRING_NOTFOUND) 811*43ad51ffSHerbert Dürr rDFA.meWidthType = WIDTH_EXPANDED; 812*43ad51ffSHerbert Dürr 813*43ad51ffSHerbert Dürr // heuristics for font pitch 814*43ad51ffSHerbert Dürr if( (aPSName.Search("mono") != STRING_NOTFOUND) 815*43ad51ffSHerbert Dürr || (aPSName.Search("courier") != STRING_NOTFOUND) 816*43ad51ffSHerbert Dürr || (aPSName.Search("monaco") != STRING_NOTFOUND) 817*43ad51ffSHerbert Dürr || (aPSName.Search("typewriter") != STRING_NOTFOUND) ) 818*43ad51ffSHerbert Dürr rDFA.mePitch = PITCH_FIXED; 819*43ad51ffSHerbert Dürr 820*43ad51ffSHerbert Dürr // heuristics for font family type 821*43ad51ffSHerbert Dürr if( (aPSName.Search("script") != STRING_NOTFOUND) 822*43ad51ffSHerbert Dürr || (aPSName.Search("chancery") != STRING_NOTFOUND) 823*43ad51ffSHerbert Dürr || (aPSName.Search("zapfino") != STRING_NOTFOUND)) 824*43ad51ffSHerbert Dürr rDFA.meFamily = FAMILY_SCRIPT; 825*43ad51ffSHerbert Dürr else if( (aPSName.Search("comic") != STRING_NOTFOUND) 826*43ad51ffSHerbert Dürr || (aPSName.Search("outline") != STRING_NOTFOUND) 827*43ad51ffSHerbert Dürr || (aPSName.Search("pinpoint") != STRING_NOTFOUND) ) 828*43ad51ffSHerbert Dürr rDFA.meFamily = FAMILY_DECORATIVE; 829*43ad51ffSHerbert Dürr else if( (aPSName.Search("sans") != STRING_NOTFOUND) 830*43ad51ffSHerbert Dürr || (aPSName.Search("arial") != STRING_NOTFOUND) ) 831*43ad51ffSHerbert Dürr rDFA.meFamily = FAMILY_SWISS; 832*43ad51ffSHerbert Dürr else if( (aPSName.Search("roman") != STRING_NOTFOUND) 833*43ad51ffSHerbert Dürr || (aPSName.Search("times") != STRING_NOTFOUND) ) 834*43ad51ffSHerbert Dürr rDFA.meFamily = FAMILY_ROMAN; 835*43ad51ffSHerbert Dürr 836*43ad51ffSHerbert Dürr // heuristics for codepoint semantic 837*43ad51ffSHerbert Dürr if( (aPSName.Search("symbol") != STRING_NOTFOUND) 838*43ad51ffSHerbert Dürr || (aPSName.Search("dings") != STRING_NOTFOUND) 839*43ad51ffSHerbert Dürr || (aPSName.Search("dingbats") != STRING_NOTFOUND) 840*43ad51ffSHerbert Dürr || (aPSName.Search("braille") != STRING_NOTFOUND) 841*43ad51ffSHerbert Dürr || (aPSName.Search("ornaments") != STRING_NOTFOUND) 842*43ad51ffSHerbert Dürr || (aPSName.Search("embellishments") != STRING_NOTFOUND) ) 843*43ad51ffSHerbert Dürr rDFA.mbSymbolFlag = true; 844*43ad51ffSHerbert Dürr 845*43ad51ffSHerbert Dürr // #i100020# special heuristic for names with single-char styles 846*43ad51ffSHerbert Dürr // NOTE: we are checking name that hasn't been lower-cased 847*43ad51ffSHerbert Dürr if( rPSName.Len() > 3 ) 848*43ad51ffSHerbert Dürr { 849*43ad51ffSHerbert Dürr int i = rPSName.Len(); 850*43ad51ffSHerbert Dürr sal_Unicode c = rPSName.GetChar( --i ); 851*43ad51ffSHerbert Dürr if( c == 'C' ) { // "capitals" 852*43ad51ffSHerbert Dürr rDFA.meFamily = FAMILY_DECORATIVE; 853*43ad51ffSHerbert Dürr c = rPSName.GetChar( --i ); 854*43ad51ffSHerbert Dürr } 855*43ad51ffSHerbert Dürr if( c == 'O' ) { // CFF-based OpenType 856*43ad51ffSHerbert Dürr c = rPSName.GetChar( --i ); 857*43ad51ffSHerbert Dürr } 858*43ad51ffSHerbert Dürr if( c == 'I' ) { // "italic" 859*43ad51ffSHerbert Dürr rDFA.meItalic = ITALIC_NORMAL; 860*43ad51ffSHerbert Dürr c = rPSName.GetChar( --i ); 861*43ad51ffSHerbert Dürr } 862*43ad51ffSHerbert Dürr if( c == 'B' ) // "bold" 863*43ad51ffSHerbert Dürr rDFA.meWeight = WEIGHT_BOLD; 864*43ad51ffSHerbert Dürr if( c == 'C' ) // "capitals" 865*43ad51ffSHerbert Dürr rDFA.meFamily = FAMILY_DECORATIVE; 866*43ad51ffSHerbert Dürr // TODO: check that all single-char styles have been resolved? 867*43ad51ffSHerbert Dürr } 868*43ad51ffSHerbert Dürr } 869*43ad51ffSHerbert Dürr 870*43ad51ffSHerbert Dürr // ======================================================================= 871*43ad51ffSHerbert Dürr 872