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