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