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