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 <unistd.h> 32 #include <sys/stat.h> 33 #include <dirent.h> 34 #include <stdlib.h> 35 #include <osl/thread.h> 36 37 #include "unotools/atom.hxx" 38 39 #include "fontcache.hxx" 40 #include "fontsubset.hxx" 41 #include "impfont.hxx" 42 #include "svdata.hxx" 43 #include "salinst.hxx" 44 #include "vcl/fontmanager.hxx" 45 #include "vcl/strhelper.hxx" 46 #include "vcl/ppdparser.hxx" 47 48 #include "tools/urlobj.hxx" 49 #include "tools/stream.hxx" 50 #include "tools/debug.hxx" 51 #include "tools/config.hxx" 52 53 #include "osl/file.hxx" 54 #include "osl/process.h" 55 56 #include "rtl/tencinfo.h" 57 #include "rtl/ustrbuf.hxx" 58 #include "rtl/strbuf.hxx" 59 60 #include "i18npool/mslangid.hxx" 61 62 63 #include "parseAFM.hxx" 64 #include "sft.hxx" 65 66 #if OSL_DEBUG_LEVEL > 1 67 #include <sys/times.h> 68 #include <stdio.h> 69 #endif 70 71 #include "sal/alloca.h" 72 73 #include <set> 74 #include <hash_set> 75 #include <algorithm> 76 77 #include "adobeenc.tab" // get encoding table for AFM metrics 78 79 #ifdef CALLGRIND_COMPILE 80 #include <valgrind/callgrind.h> 81 #endif 82 83 #include "comphelper/processfactory.hxx" 84 #include "com/sun/star/beans/XMaterialHolder.hpp" 85 #include "com/sun/star/beans/NamedValue.hpp" 86 87 #define PRINTER_METRICDIR "fontmetric" 88 89 namespace { 90 91 namespace css = com::sun::star; 92 93 } 94 95 using namespace vcl; 96 using namespace utl; 97 using namespace psp; 98 using namespace osl; 99 using namespace rtl; 100 using namespace com::sun::star::uno; 101 using namespace com::sun::star::beans; 102 using namespace com::sun::star::lang; 103 104 /* 105 * static helpers 106 */ 107 108 inline sal_uInt16 getUInt16BE( const sal_uInt8*& pBuffer ) 109 { 110 sal_uInt16 nRet = (sal_uInt16)pBuffer[1] | 111 (((sal_uInt16)pBuffer[0]) << 8); 112 pBuffer+=2; 113 return nRet; 114 } 115 116 inline sal_uInt32 getUInt32BE( const sal_uInt8*& pBuffer ) 117 { 118 sal_uInt32 nRet = (((sal_uInt32)pBuffer[0]) << 24) | 119 (((sal_uInt32)pBuffer[1]) << 16) | 120 (((sal_uInt32)pBuffer[2]) << 8) | 121 (((sal_uInt32)pBuffer[3]) ); 122 pBuffer += 4; 123 return nRet; 124 } 125 126 static italic::type parseItalic( const ByteString& rItalic ) 127 { 128 italic::type eItalic = italic::Unknown; 129 if( rItalic.EqualsIgnoreCaseAscii( "i" ) ) 130 eItalic = italic::Italic; 131 else if( rItalic.EqualsIgnoreCaseAscii( "o" ) ) 132 eItalic = italic::Oblique; 133 else 134 eItalic = italic::Upright; 135 return eItalic; 136 } 137 138 // ------------------------------------------------------------------------- 139 140 static weight::type parseWeight( const ByteString& rWeight ) 141 { 142 weight::type eWeight = weight::Unknown; 143 if( rWeight.Search( "bold" ) != STRING_NOTFOUND ) 144 { 145 if( rWeight.Search( "emi" ) != STRING_NOTFOUND ) // semi, demi 146 eWeight = weight::SemiBold; 147 else if( rWeight.Search( "ultra" ) != STRING_NOTFOUND ) 148 eWeight = weight::UltraBold; 149 else 150 eWeight = weight::Bold; 151 } 152 else if( rWeight.Search( "heavy" ) != STRING_NOTFOUND ) 153 eWeight = weight::Bold; 154 else if( rWeight.Search( "light" ) != STRING_NOTFOUND ) 155 { 156 if( rWeight.Search( "emi" ) != STRING_NOTFOUND ) // semi, demi 157 eWeight = weight::SemiLight; 158 else if( rWeight.Search( "ultra" ) != STRING_NOTFOUND ) 159 eWeight = weight::UltraLight; 160 else 161 eWeight = weight::Light; 162 } 163 else if( rWeight.Search( "black" ) != STRING_NOTFOUND ) 164 eWeight = weight::Black; 165 else if( rWeight.Equals( "demi" ) ) 166 eWeight = weight::SemiBold; 167 else if( rWeight.Equals( "book" ) || 168 rWeight.Equals( "semicondensed" ) ) 169 eWeight = weight::Light; 170 else if( rWeight.Equals( "medium" ) || rWeight.Equals( "roman" ) ) 171 eWeight = weight::Medium; 172 else 173 eWeight = weight::Normal; 174 return eWeight; 175 } 176 177 // ------------------------------------------------------------------------- 178 179 static width::type parseWidth( const ByteString& rWidth ) 180 { 181 width::type eWidth = width::Unknown; 182 if( rWidth.Equals( "bold" ) || 183 rWidth.Equals( "semiexpanded" ) ) 184 eWidth = width::SemiExpanded; 185 else if( rWidth.Equals( "condensed" ) || 186 rWidth.Equals( "narrow" ) ) 187 eWidth = width::Condensed; 188 else if( rWidth.Equals( "double wide" ) || 189 rWidth.Equals( "extraexpanded" ) || 190 rWidth.Equals( "ultraexpanded" ) ) 191 eWidth = width::UltraExpanded; 192 else if( rWidth.Equals( "expanded" ) || 193 rWidth.Equals( "wide" ) ) 194 eWidth = width::Expanded; 195 else if( rWidth.Equals( "extracondensed" ) ) 196 eWidth = width::ExtraCondensed; 197 else if( rWidth.Equals( "semicondensed" ) ) 198 eWidth = width::SemiCondensed; 199 else if( rWidth.Equals( "ultracondensed" ) ) 200 eWidth = width::UltraCondensed; 201 else 202 eWidth = width::Normal; 203 204 return eWidth; 205 } 206 207 // ------------------------------------------------------------------------- 208 bool PrintFontManager::XLFDEntry::operator<(const PrintFontManager::XLFDEntry& rRight) const 209 { 210 sal_Int32 nCmp = 0; 211 if( (nMask & MaskFamily) && (rRight.nMask & MaskFamily) ) 212 { 213 nCmp = rtl_str_compareIgnoreAsciiCase_WithLength( aFamily.pData->buffer, 214 aFamily.pData->length, 215 rRight.aFamily.pData->buffer, 216 rRight.aFamily.pData->length ); 217 if( nCmp != 0 ) 218 return nCmp < 0; 219 } 220 221 if( (nMask & MaskFoundry) && (rRight.nMask & MaskFoundry) ) 222 { 223 nCmp = rtl_str_compareIgnoreAsciiCase_WithLength( aFoundry.pData->buffer, 224 aFoundry.pData->length, 225 rRight.aFoundry.pData->buffer, 226 rRight.aFoundry.pData->length ); 227 if( nCmp != 0 ) 228 return nCmp < 0; 229 } 230 231 if( (nMask & MaskItalic) && (rRight.nMask & MaskItalic) ) 232 { 233 if( eItalic != rRight.eItalic ) 234 return (int)eItalic < (int)rRight.eItalic; 235 } 236 237 if( (nMask & MaskWeight) && (rRight.nMask & MaskWeight) ) 238 { 239 if( eWeight != rRight.eWeight ) 240 return (int)eWeight < (int)rRight.eWeight; 241 } 242 243 if( (nMask & MaskWidth) && (rRight.nMask & MaskWidth) ) 244 { 245 if( eWidth != rRight.eWidth ) 246 return (int)eWidth < (int)rRight.eWidth; 247 } 248 249 if( (nMask & MaskPitch) && (rRight.nMask & MaskPitch) ) 250 { 251 if( ePitch != rRight.ePitch ) 252 return (int)ePitch < (int)rRight.ePitch; 253 } 254 255 if( (nMask & MaskAddStyle) && (rRight.nMask & MaskAddStyle) ) 256 { 257 nCmp = rtl_str_compareIgnoreAsciiCase_WithLength( aAddStyle.pData->buffer, 258 aAddStyle.pData->length, 259 rRight.aAddStyle.pData->buffer, 260 rRight.aAddStyle.pData->length ); 261 if( nCmp != 0 ) 262 return nCmp < 0; 263 } 264 265 if( (nMask & MaskEncoding) && (rRight.nMask & MaskEncoding) ) 266 { 267 if( aEncoding != rRight.aEncoding ) 268 return aEncoding < rRight.aEncoding; 269 } 270 271 return false; 272 } 273 274 bool PrintFontManager::XLFDEntry::operator==(const PrintFontManager::XLFDEntry& rRight) const 275 { 276 sal_Int32 nCmp = 0; 277 if( (nMask & MaskFamily) && (rRight.nMask & MaskFamily) ) 278 { 279 nCmp = rtl_str_compareIgnoreAsciiCase_WithLength( aFamily.pData->buffer, 280 aFamily.pData->length, 281 rRight.aFamily.pData->buffer, 282 rRight.aFamily.pData->length ); 283 if( nCmp != 0 ) 284 return false; 285 } 286 287 if( (nMask & MaskFoundry) && (rRight.nMask & MaskFoundry) ) 288 { 289 nCmp = rtl_str_compareIgnoreAsciiCase_WithLength( aFoundry.pData->buffer, 290 aFoundry.pData->length, 291 rRight.aFoundry.pData->buffer, 292 rRight.aFoundry.pData->length ); 293 if( nCmp != 0 ) 294 return false; 295 } 296 297 if( (nMask & MaskItalic) && (rRight.nMask & MaskItalic) ) 298 { 299 if( eItalic != rRight.eItalic ) 300 return false; 301 } 302 303 if( (nMask & MaskWeight) && (rRight.nMask & MaskWeight) ) 304 { 305 if( eWeight != rRight.eWeight ) 306 return false; 307 } 308 309 if( (nMask & MaskWidth) && (rRight.nMask & MaskWidth) ) 310 { 311 if( eWidth != rRight.eWidth ) 312 return false; 313 } 314 315 if( (nMask & MaskPitch) && (rRight.nMask & MaskPitch) ) 316 { 317 if( ePitch != rRight.ePitch ) 318 return false; 319 } 320 321 if( (nMask & MaskAddStyle) && (rRight.nMask & MaskAddStyle) ) 322 { 323 nCmp = rtl_str_compareIgnoreAsciiCase_WithLength( aAddStyle.pData->buffer, 324 aAddStyle.pData->length, 325 rRight.aAddStyle.pData->buffer, 326 rRight.aAddStyle.pData->length ); 327 if( nCmp != 0 ) 328 return false; 329 } 330 331 if( (nMask & MaskEncoding) && (rRight.nMask & MaskEncoding) ) 332 { 333 if( aEncoding != rRight.aEncoding ) 334 return false; 335 } 336 337 return true; 338 } 339 340 /* 341 * PrintFont implementations 342 */ 343 PrintFontManager::PrintFont::PrintFont( fonttype::type eType ) : 344 m_eType( eType ), 345 m_nFamilyName( 0 ), 346 m_nPSName( 0 ), 347 m_eItalic( italic::Unknown ), 348 m_eWidth( width::Unknown ), 349 m_eWeight( weight::Unknown ), 350 m_ePitch( pitch::Unknown ), 351 m_aEncoding( RTL_TEXTENCODING_DONTKNOW ), 352 m_bFontEncodingOnly( false ), 353 m_pMetrics( NULL ), 354 m_nAscend( 0 ), 355 m_nDescend( 0 ), 356 m_nLeading( 0 ), 357 m_nXMin( 0 ), 358 m_nYMin( 0 ), 359 m_nXMax( 0 ), 360 m_nYMax( 0 ), 361 m_bHaveVerticalSubstitutedGlyphs( false ), 362 m_bUserOverride( false ) 363 { 364 } 365 366 // ------------------------------------------------------------------------- 367 368 PrintFontManager::PrintFont::~PrintFont() 369 { 370 if( m_pMetrics ) 371 delete m_pMetrics; 372 } 373 374 // ------------------------------------------------------------------------- 375 376 PrintFontManager::Type1FontFile::~Type1FontFile() 377 { 378 } 379 380 // ------------------------------------------------------------------------- 381 382 PrintFontManager::TrueTypeFontFile::TrueTypeFontFile() 383 : PrintFont( fonttype::TrueType ) 384 , m_nDirectory( 0 ) 385 , m_nCollectionEntry(-1) 386 , m_nTypeFlags( TYPEFLAG_INVALID ) 387 {} 388 389 // ------------------------------------------------------------------------- 390 391 PrintFontManager::TrueTypeFontFile::~TrueTypeFontFile() 392 { 393 } 394 395 // ------------------------------------------------------------------------- 396 397 PrintFontManager::BuiltinFont::~BuiltinFont() 398 { 399 } 400 401 // ------------------------------------------------------------------------- 402 403 bool PrintFontManager::Type1FontFile::queryMetricPage( int /*nPage*/, MultiAtomProvider* pProvider ) 404 { 405 return readAfmMetrics( PrintFontManager::get().getAfmFile( this ), pProvider, false, false ); 406 } 407 408 // ------------------------------------------------------------------------- 409 410 bool PrintFontManager::BuiltinFont::queryMetricPage( int /*nPage*/, MultiAtomProvider* pProvider ) 411 { 412 return readAfmMetrics( PrintFontManager::get().getAfmFile( this ), pProvider, false, false ); 413 } 414 415 // ------------------------------------------------------------------------- 416 417 bool PrintFontManager::TrueTypeFontFile::queryMetricPage( int nPage, MultiAtomProvider* pProvider ) 418 { 419 bool bSuccess = false; 420 421 ByteString aFile( PrintFontManager::get().getFontFile( this ) ); 422 423 TrueTypeFont* pTTFont = NULL; 424 425 if( OpenTTFontFile( aFile.GetBuffer(), m_nCollectionEntry < 0 ? 0 : m_nCollectionEntry, &pTTFont ) == SF_OK ) 426 { 427 if( ! m_pMetrics ) 428 { 429 m_pMetrics = new PrintFontMetrics; 430 memset (m_pMetrics->m_aPages, 0, sizeof(m_pMetrics->m_aPages)); 431 } 432 m_pMetrics->m_aPages[ nPage/8 ] |= (1 << ( nPage & 7 )); 433 int i; 434 sal_uInt16 table[256], table_vert[256]; 435 436 for( i = 0; i < 256; i++ ) 437 table[ i ] = 256*nPage + i; 438 439 int nCharacters = nPage < 255 ? 256 : 254; 440 MapString( pTTFont, table, nCharacters, NULL, 0 ); 441 TTSimpleGlyphMetrics* pMetrics = GetTTSimpleCharMetrics( pTTFont, nPage*256, nCharacters, 0 ); 442 if( pMetrics ) 443 { 444 for( i = 0; i < nCharacters; i++ ) 445 { 446 if( table[i] ) 447 { 448 CharacterMetric& rChar = m_pMetrics->m_aMetrics[ nPage*256 + i ]; 449 rChar.width = pMetrics[ i ].adv; 450 rChar.height = m_aGlobalMetricX.height; 451 } 452 } 453 454 free( pMetrics ); 455 } 456 457 for( i = 0; i < 256; i++ ) 458 table_vert[ i ] = 256*nPage + i; 459 MapString( pTTFont, table_vert, nCharacters, NULL, 1 ); 460 pMetrics = GetTTSimpleCharMetrics( pTTFont, nPage*256, nCharacters, 1 ); 461 if( pMetrics ) 462 { 463 for( i = 0; i < nCharacters; i++ ) 464 { 465 if( table_vert[i] ) 466 { 467 CharacterMetric& rChar = m_pMetrics->m_aMetrics[ nPage*256 + i + ( 1 << 16 ) ]; 468 rChar.width = m_aGlobalMetricY.width; 469 rChar.height = pMetrics[ i ].adv; 470 if( table_vert[i] != table[i] ) 471 m_pMetrics->m_bVerticalSubstitutions[ nPage*256 + i ] = 1; 472 } 473 } 474 free( pMetrics ); 475 } 476 477 if( ! m_pMetrics->m_bKernPairsQueried ) 478 { 479 m_pMetrics->m_bKernPairsQueried = true; 480 // this is really a hack 481 // in future MapString/KernGlyphs should be used 482 // but vcl is not in a state where that could be used 483 // so currently we get kernpairs by accessing the raw data 484 struct _TrueTypeFont* pImplTTFont = (struct _TrueTypeFont*)pTTFont; 485 486 //----------------------------------------------------------------- 487 // Kerning: KT_MICROSOFT 488 //----------------------------------------------------------------- 489 if( pImplTTFont->nkern && pImplTTFont->kerntype == KT_MICROSOFT ) 490 { 491 // create a glyph -> character mapping 492 ::std::hash_map< sal_uInt16, sal_Unicode > aGlyphMap; 493 ::std::hash_map< sal_uInt16, sal_Unicode >::iterator left, right; 494 for( i = 21; i < 0xfffd; i++ ) 495 { 496 sal_uInt16 nGlyph = MapChar( pTTFont, (sal_Unicode)i, 0 ); // kerning for horz only 497 if( nGlyph != 0 ) 498 aGlyphMap[ nGlyph ] = (sal_Unicode)i; 499 } 500 501 502 KernPair aPair; 503 for( i = 0; i < (int)pImplTTFont->nkern; i++ ) 504 { 505 const sal_uInt8* pTable = pImplTTFont->kerntables[i]; 506 507 /*sal_uInt16 nVersion =*/ getUInt16BE( pTable ); 508 /*sal_uInt16 nLength =*/ getUInt16BE( pTable ); 509 sal_uInt16 nCoverage = getUInt16BE( pTable ); 510 511 aPair.kern_x = 0; 512 aPair.kern_y = 0; 513 switch( nCoverage >> 8 ) 514 { 515 case 0: 516 { 517 sal_uInt16 nPairs = getUInt16BE( pTable ); 518 pTable += 6; 519 for( int n = 0; n < nPairs; n++ ) 520 { 521 sal_uInt16 nLeftGlyph = getUInt16BE( pTable ); 522 sal_uInt16 nRightGlyph = getUInt16BE( pTable ); 523 sal_Int16 nKern = (sal_Int16)getUInt16BE( pTable ); 524 525 left = aGlyphMap.find( nLeftGlyph ); 526 right = aGlyphMap.find( nRightGlyph ); 527 if( left != aGlyphMap.end() && right != aGlyphMap.end() ) 528 { 529 aPair.first = left->second; 530 aPair.second = right->second; 531 switch( nCoverage & 1 ) 532 { 533 case 1: 534 aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm; 535 m_pMetrics->m_aXKernPairs.push_back( aPair ); 536 break; 537 case 0: 538 aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm; 539 m_pMetrics->m_aYKernPairs.push_back( aPair ); 540 break; 541 } 542 } 543 } 544 } 545 break; 546 547 case 2: 548 { 549 const sal_uInt8* pSubTable = pTable; 550 /*sal_uInt16 nRowWidth =*/ getUInt16BE( pTable ); 551 sal_uInt16 nOfLeft = getUInt16BE( pTable ); 552 sal_uInt16 nOfRight = getUInt16BE( pTable ); 553 /*sal_uInt16 nOfArray =*/ getUInt16BE( pTable ); 554 const sal_uInt8* pTmp = pSubTable + nOfLeft; 555 sal_uInt16 nFirstLeft = getUInt16BE( pTmp ); 556 sal_uInt16 nLastLeft = getUInt16BE( pTmp ) + nFirstLeft - 1; 557 pTmp = pSubTable + nOfRight; 558 sal_uInt16 nFirstRight = getUInt16BE( pTmp ); 559 sal_uInt16 nLastRight = getUInt16BE( pTmp ) + nFirstRight -1; 560 561 // int nPairs = (int)(nLastLeft-nFirstLeft+1)*(int)(nLastRight-nFirstRight+1); 562 for( aPair.first = nFirstLeft; aPair.first < nLastLeft; aPair.first++ ) 563 { 564 for( aPair.second = 0; aPair.second < nLastRight; aPair.second++ ) 565 { 566 sal_Int16 nKern = (sal_Int16)getUInt16BE( pTmp ); 567 switch( nCoverage & 1 ) 568 { 569 case 1: 570 aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm; 571 m_pMetrics->m_aXKernPairs.push_back( aPair ); 572 break; 573 case 0: 574 aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm; 575 m_pMetrics->m_aYKernPairs.push_back( aPair ); 576 break; 577 } 578 } 579 } 580 } 581 break; 582 } 583 } 584 } 585 586 //----------------------------------------------------------------- 587 // Kerning: KT_APPLE_NEW 588 //----------------------------------------------------------------- 589 if( pImplTTFont->nkern && pImplTTFont->kerntype == KT_APPLE_NEW ) 590 { 591 // create a glyph -> character mapping 592 ::std::hash_map< sal_uInt16, sal_Unicode > aGlyphMap; 593 ::std::hash_map< sal_uInt16, sal_Unicode >::iterator left, right; 594 for( i = 21; i < 0xfffd; i++ ) 595 { 596 sal_uInt16 nGlyph = MapChar( pTTFont, (sal_Unicode)i, 0 ); // kerning for horz only 597 if( nGlyph != 0 ) 598 aGlyphMap[ nGlyph ] = (sal_Unicode)i; 599 } 600 601 // Loop through each of the 'kern' subtables 602 KernPair aPair; 603 for( i = 0; (unsigned int)i < pImplTTFont->nkern; i++ ) 604 { 605 const sal_uInt8* pTable = pImplTTFont->kerntables[i]; 606 607 /*sal_uInt32 nLength =*/ getUInt32BE( pTable ); 608 sal_uInt16 nCoverage = getUInt16BE( pTable ); 609 /*sal_uInt16 nTupleIndex =*/ getUInt16BE( pTable ); 610 611 // Get kerning type 612 // sal_Bool bKernVertical = nCoverage & 0x8000; 613 // sal_Bool bKernCrossStream = nCoverage & 0x4000; 614 // sal_Bool bKernVariation = nCoverage & 0x2000; 615 616 // Kerning sub-table format, 0 through 3 617 sal_uInt8 nSubTableFormat = nCoverage & 0x00FF; 618 619 aPair.kern_x = 0; 620 aPair.kern_y = 0; 621 switch( nSubTableFormat ) 622 { 623 case 0: 624 { 625 // Grab the # of kern pairs but skip over the: 626 // searchRange 627 // entrySelector 628 // rangeShift 629 sal_uInt16 nPairs = getUInt16BE( pTable ); 630 pTable += 6; 631 632 for( int n = 0; n < nPairs; n++ ) 633 { 634 sal_uInt16 nLeftGlyph = getUInt16BE( pTable ); 635 sal_uInt16 nRightGlyph = getUInt16BE( pTable ); 636 sal_Int16 nKern = (sal_Int16)getUInt16BE( pTable ); 637 638 left = aGlyphMap.find( nLeftGlyph ); 639 right = aGlyphMap.find( nRightGlyph ); 640 if( left != aGlyphMap.end() && right != aGlyphMap.end() ) 641 { 642 aPair.first = left->second; 643 aPair.second = right->second; 644 645 // Only support horizontal kerning for now 646 aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm; 647 aPair.kern_y = 0; 648 m_pMetrics->m_aXKernPairs.push_back( aPair ); 649 650 /* switch( nCoverage & 1 ) 651 { 652 case 1: 653 aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm; 654 m_pMetrics->m_aXKernPairs.push_back( aPair ); 655 break; 656 case 0: 657 aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm; 658 m_pMetrics->m_aYKernPairs.push_back( aPair ); 659 break; 660 } 661 */ 662 } 663 } 664 } 665 break; 666 667 case 2: 668 { 669 const sal_uInt8* pSubTable = pTable; 670 /*sal_uInt16 nRowWidth =*/ getUInt16BE( pTable ); 671 sal_uInt16 nOfLeft = getUInt16BE( pTable ); 672 sal_uInt16 nOfRight = getUInt16BE( pTable ); 673 /*sal_uInt16 nOfArray =*/ getUInt16BE( pTable ); 674 const sal_uInt8* pTmp = pSubTable + nOfLeft; 675 sal_uInt16 nFirstLeft = getUInt16BE( pTmp ); 676 sal_uInt16 nLastLeft = getUInt16BE( pTmp ) + nFirstLeft - 1; 677 pTmp = pSubTable + nOfRight; 678 sal_uInt16 nFirstRight = getUInt16BE( pTmp ); 679 sal_uInt16 nLastRight = getUInt16BE( pTmp ) + nFirstRight -1; 680 681 for( aPair.first = nFirstLeft; aPair.first < nLastLeft; aPair.first++ ) 682 { 683 for( aPair.second = 0; aPair.second < nLastRight; aPair.second++ ) 684 { 685 sal_Int16 nKern = (sal_Int16)getUInt16BE( pTmp ); 686 switch( nCoverage & 1 ) 687 { 688 case 1: 689 aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm; 690 m_pMetrics->m_aXKernPairs.push_back( aPair ); 691 break; 692 case 0: 693 aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm; 694 m_pMetrics->m_aYKernPairs.push_back( aPair ); 695 break; 696 } 697 } 698 } 699 } 700 break; 701 702 default: 703 fprintf( stderr, "Found unsupported Apple-style kern subtable type %d.\n", nSubTableFormat ); 704 break; 705 } 706 } 707 } 708 709 #if OSL_DEBUG_LEVEL > 1 710 fprintf( stderr, "found %d/%d kern pairs for %s\n", 711 m_pMetrics->m_aXKernPairs.size(), 712 m_pMetrics->m_aYKernPairs.size(), 713 OUStringToOString( pProvider->getString( ATOM_FAMILYNAME, m_nFamilyName ), RTL_TEXTENCODING_MS_1252 ).getStr() ); 714 #else 715 (void) pProvider; /* avoid warnings */ 716 #endif 717 } 718 719 CloseTTFont( pTTFont ); 720 bSuccess = true; 721 } 722 return bSuccess; 723 } 724 725 // ------------------------------------------------------------------------- 726 727 /* #i73387# There seem to be fonts with a rather unwell chosen family name 728 * consider e.g. "Helvetica Narrow" which defines its family as "Helvetica" 729 * It can really only be distinguished by its PSName and FullName. Both of 730 * which are not user presentable in OOo. So replace it by something sensible. 731 * 732 * If other fonts feature this behaviour, insert them to the map. 733 */ 734 static bool familyNameOverride( const OUString& i_rPSname, OUString& o_rFamilyName ) 735 { 736 static std::hash_map< OUString, OUString, OUStringHash > aPSNameToFamily( 16 ); 737 if( aPSNameToFamily.empty() ) // initialization 738 { 739 aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow" ) ) ] = 740 OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) ); 741 aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-Bold" ) ) ] = 742 OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) ); 743 aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-BoldOblique" ) ) ] = 744 OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) ); 745 aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-Oblique" ) ) ] = 746 OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) ); 747 } 748 std::hash_map<OUString,OUString,OUStringHash>::const_iterator it = 749 aPSNameToFamily.find( i_rPSname ); 750 bool bReplaced = (it != aPSNameToFamily.end() ); 751 if( bReplaced ) 752 o_rFamilyName = it->second; 753 return bReplaced; 754 }; 755 756 bool PrintFontManager::PrintFont::readAfmMetrics( const OString& rFileName, MultiAtomProvider* pProvider, bool bFillEncodingvector, bool bOnlyGlobalAttributes ) 757 { 758 PrintFontManager& rManager( PrintFontManager::get() ); 759 760 int i; 761 FontInfo* pInfo = NULL; 762 parseFile( rFileName.getStr(), &pInfo, P_ALL ); 763 if( ! pInfo || ! pInfo->numOfChars ) 764 { 765 if( pInfo ) 766 freeFontInfo( pInfo ); 767 return false; 768 } 769 770 m_aEncodingVector.clear(); 771 // fill in global info 772 773 // PSName 774 OUString aPSName( OStringToOUString( pInfo->gfi->fontName, RTL_TEXTENCODING_ISO_8859_1 ) ); 775 m_nPSName = pProvider->getAtom( ATOM_PSNAME, aPSName, sal_True ); 776 777 // family name (if not already set) 778 OUString aFamily; 779 if( ! m_nFamilyName ) 780 { 781 aFamily = OStringToOUString( pInfo->gfi->familyName, RTL_TEXTENCODING_ISO_8859_1 ); 782 if( ! aFamily.getLength() ) 783 { 784 aFamily = OStringToOUString( pInfo->gfi->fontName, RTL_TEXTENCODING_ISO_8859_1 ); 785 sal_Int32 nIndex = 0; 786 aFamily = aFamily.getToken( 0, '-', nIndex ); 787 } 788 familyNameOverride( aPSName, aFamily ); 789 m_nFamilyName = pProvider->getAtom( ATOM_FAMILYNAME, aFamily, sal_True ); 790 } 791 else 792 aFamily = pProvider->getString( ATOM_FAMILYNAME, m_nFamilyName ); 793 794 // style name: if fullname begins with family name 795 // interpret the rest of fullname as style 796 if( ! m_aStyleName.getLength() && pInfo->gfi->fullName && *pInfo->gfi->fullName ) 797 { 798 OUString aFullName( OStringToOUString( pInfo->gfi->fullName, RTL_TEXTENCODING_ISO_8859_1 ) ); 799 if( aFullName.indexOf( aFamily ) == 0 ) 800 m_aStyleName = WhitespaceToSpace( aFullName.copy( aFamily.getLength() ) ); 801 } 802 803 // italic 804 if( pInfo->gfi->italicAngle > 0 ) 805 m_eItalic = italic::Oblique; 806 else if( pInfo->gfi->italicAngle < 0 ) 807 m_eItalic = italic::Italic; 808 else 809 m_eItalic = italic::Upright; 810 811 // weight 812 ByteString aLowerWeight( pInfo->gfi->weight ); 813 aLowerWeight.ToLowerAscii(); 814 m_eWeight = parseWeight( aLowerWeight ); 815 816 // pitch 817 m_ePitch = pInfo->gfi->isFixedPitch ? pitch::Fixed : pitch::Variable; 818 819 // encoding - only set if unknown 820 int nAdobeEncoding = 0; 821 if( pInfo->gfi->encodingScheme ) 822 { 823 if( !strcmp( pInfo->gfi->encodingScheme, "AdobeStandardEncoding" ) ) 824 nAdobeEncoding = 1; 825 else if( !strcmp( pInfo->gfi->encodingScheme, "ISO10646-1" ) ) 826 { 827 nAdobeEncoding = 1; 828 m_aEncoding = RTL_TEXTENCODING_UNICODE; 829 } 830 else if( !strcmp( pInfo->gfi->encodingScheme, "Symbol") ) 831 nAdobeEncoding = 2; 832 else if( !strcmp( pInfo->gfi->encodingScheme, "FontSpecific") ) 833 nAdobeEncoding = 3; 834 835 if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW ) 836 m_aEncoding = nAdobeEncoding == 1 ? 837 RTL_TEXTENCODING_ADOBE_STANDARD : RTL_TEXTENCODING_SYMBOL; 838 } 839 else if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW ) 840 m_aEncoding = RTL_TEXTENCODING_ADOBE_STANDARD; 841 842 // try to parse the font name and decide wether it might be a 843 // japanese font. Who invented this PITA ? 844 OUString aPSNameLastToken( aPSName.copy( aPSName.lastIndexOf( '-' )+1 ) ); 845 if( ! aPSNameLastToken.compareToAscii( "H" ) || 846 ! aPSNameLastToken.compareToAscii( "V" ) ) 847 { 848 static const char* pEncs[] = 849 { 850 "EUC", 851 "RKSJ", 852 "SJ" 853 }; 854 static const rtl_TextEncoding aEncs[] = 855 { 856 RTL_TEXTENCODING_EUC_JP, 857 RTL_TEXTENCODING_SHIFT_JIS, 858 RTL_TEXTENCODING_JIS_X_0208 859 }; 860 861 for( unsigned int enc = 0; enc < sizeof( aEncs )/sizeof(aEncs[0]) && m_aEncoding == RTL_TEXTENCODING_DONTKNOW; enc++ ) 862 { 863 sal_Int32 nIndex = 0, nOffset = 1; 864 do 865 { 866 OUString aToken( aPSName.getToken( nOffset, '-', nIndex ) ); 867 if( nIndex == -1 ) 868 break; 869 nOffset = 0; 870 if( ! aToken.compareToAscii( pEncs[enc] ) ) 871 { 872 m_aEncoding = aEncs[ enc ]; 873 m_bFontEncodingOnly = true; 874 } 875 } while( nIndex != -1 ); 876 } 877 878 // default is jis 879 if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW ) 880 m_aEncoding = RTL_TEXTENCODING_JIS_X_0208; 881 #if OSL_DEBUG_LEVEL > 1 882 fprintf( stderr, "Encoding %d for %s\n", m_aEncoding, pInfo->gfi->fontName ); 883 #endif 884 } 885 886 // hack for GB encoded builtin fonts posing as FontSpecific 887 if( m_eType == fonttype::Builtin && ( nAdobeEncoding == 3 || nAdobeEncoding == 0 ) ) 888 { 889 int nLen = aFamily.getLength(); 890 if( nLen > 2 && 891 aFamily.getStr()[ nLen-2 ] == 'G' && 892 aFamily.getStr()[ nLen-1 ] == 'B' && 893 pInfo->numOfChars > 255 ) 894 { 895 m_aEncoding = RTL_TEXTENCODING_GBK; 896 m_bFontEncodingOnly = true; 897 #if OSL_DEBUG_LEVEL > 1 898 fprintf( stderr, "found builtin font %s with GBK encoding\n", pInfo->gfi->fontName ); 899 #endif 900 } 901 } 902 903 // #i37313# check if Fontspecific is not rather some character encoding 904 if( nAdobeEncoding == 3 && m_aEncoding == RTL_TEXTENCODING_SYMBOL ) 905 { 906 bool bYFound = false; 907 bool bQFound = false; 908 CharMetricInfo* pChar = pInfo->cmi; 909 for( int j = 0; j < pInfo->numOfChars && ! (bYFound && bQFound); j++ ) 910 { 911 if( pChar[j].name ) 912 { 913 if( pChar[j].name[0] == 'Y' && pChar[j].name[1] == 0 ) 914 bYFound = true; 915 else if( pChar[j].name[0] == 'Q' && pChar[j].name[1] == 0 ) 916 bQFound = true; 917 } 918 } 919 if( bQFound && bYFound ) 920 { 921 #if OSL_DEBUG_LEVEL > 1 922 fprintf( stderr, "setting FontSpecific font %s (file %s) to unicode\n", 923 pInfo->gfi->fontName, 924 rFileName.getStr() 925 ); 926 #endif 927 nAdobeEncoding = 4; 928 m_aEncoding = RTL_TEXTENCODING_UNICODE; 929 bFillEncodingvector = false; // will be filled anyway, don't do the work twice 930 } 931 } 932 933 // ascend 934 m_nAscend = pInfo->gfi->fontBBox.ury; 935 936 // descend 937 // descends have opposite sign of our definition 938 m_nDescend = -pInfo->gfi->fontBBox.lly; 939 940 // fallback to ascender, descender 941 // interesting: the BBox seems to describe Ascender and Descender better 942 // as we understand it 943 if( m_nAscend == 0 ) 944 m_nAscend = pInfo->gfi->ascender; 945 if( m_nDescend == 0) 946 m_nDescend = -pInfo->gfi->descender; 947 948 m_nLeading = m_nAscend + m_nDescend - 1000; 949 950 if( m_pMetrics ) 951 delete m_pMetrics; 952 m_pMetrics = new PrintFontMetrics; 953 // mark all pages as queried (or clear if only global font info queiried) 954 memset( m_pMetrics->m_aPages, bOnlyGlobalAttributes ? 0 : 0xff, sizeof( m_pMetrics->m_aPages ) ); 955 956 m_aGlobalMetricX.width = m_aGlobalMetricY.width = 957 pInfo->gfi->charwidth ? pInfo->gfi->charwidth : pInfo->gfi->fontBBox.urx; 958 m_aGlobalMetricX.height = m_aGlobalMetricY.height = 959 pInfo->gfi->capHeight ? pInfo->gfi->capHeight : pInfo->gfi->fontBBox.ury; 960 961 m_nXMin = pInfo->gfi->fontBBox.llx; 962 m_nYMin = pInfo->gfi->fontBBox.lly; 963 m_nXMax = pInfo->gfi->fontBBox.urx; 964 m_nYMax = pInfo->gfi->fontBBox.ury; 965 966 if( bFillEncodingvector || !bOnlyGlobalAttributes ) 967 { 968 // fill in character metrics 969 970 // first transform the character codes to unicode 971 // note: this only works with single byte encodings 972 sal_Unicode* pUnicodes = (sal_Unicode*)alloca( pInfo->numOfChars * sizeof(sal_Unicode)); 973 CharMetricInfo* pChar = pInfo->cmi; 974 975 for( i = 0; i < pInfo->numOfChars; i++, pChar++ ) 976 { 977 if( nAdobeEncoding == 4 ) 978 { 979 if( pChar->name ) 980 { 981 pUnicodes[i] = 0; 982 std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name ); 983 for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it ) 984 { 985 if( *it != 0 ) 986 { 987 m_aEncodingVector[ *it ] = pChar->code; 988 if( pChar->code == -1 ) 989 m_aNonEncoded[ *it ] = pChar->name; 990 if( ! pUnicodes[i] ) // map the first 991 pUnicodes[i] = *it; 992 } 993 } 994 } 995 } 996 else if( pChar->code != -1 ) 997 { 998 if( nAdobeEncoding == 3 && m_aEncoding == RTL_TEXTENCODING_SYMBOL ) 999 { 1000 pUnicodes[i] = pChar->code + 0xf000; 1001 if( bFillEncodingvector ) 1002 m_aEncodingVector[ pUnicodes[i] ] = pChar->code; 1003 continue; 1004 } 1005 1006 if( m_aEncoding == RTL_TEXTENCODING_UNICODE ) 1007 { 1008 pUnicodes[i] = (sal_Unicode)pChar->code; 1009 continue; 1010 } 1011 1012 ByteString aTranslate; 1013 if( pChar->code & 0xff000000 ) 1014 aTranslate += (char)(pChar->code >> 24 ); 1015 if( pChar->code & 0xffff0000 ) 1016 aTranslate += (char)((pChar->code & 0x00ff0000) >> 16 ); 1017 if( pChar->code & 0xffffff00 ) 1018 aTranslate += (char)((pChar->code & 0x0000ff00) >> 8 ); 1019 aTranslate += (char)(pChar->code & 0xff); 1020 String aUni( aTranslate, m_aEncoding ); 1021 pUnicodes[i] = *aUni.GetBuffer(); 1022 } 1023 else 1024 pUnicodes[i] = 0; 1025 } 1026 1027 // now fill in the character metrics 1028 // parseAFM.cxx effectively only supports direction 0 (horizontal) 1029 pChar = pInfo->cmi; 1030 CharacterMetric aMetric; 1031 for( i = 0; i < pInfo->numOfChars; i++, pChar++ ) 1032 { 1033 if( pChar->code == -1 && ! pChar->name ) 1034 continue; 1035 1036 if( bFillEncodingvector && pChar->name ) 1037 { 1038 std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name ); 1039 for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it ) 1040 { 1041 if( *it != 0 ) 1042 { 1043 m_aEncodingVector[ *it ] = pChar->code; 1044 if( pChar->code == -1 ) 1045 m_aNonEncoded[ *it ] = pChar->name; 1046 } 1047 } 1048 } 1049 1050 aMetric.width = pChar->wx ? pChar->wx : pChar->charBBox.urx; 1051 aMetric.height = pChar->wy ? pChar->wy : pChar->charBBox.ury - pChar->charBBox.lly; 1052 if( aMetric.width == 0 && aMetric.height == 0 ) 1053 // guess something for e.g. space 1054 aMetric.width = m_aGlobalMetricX.width/4; 1055 1056 if( ( nAdobeEncoding == 0 ) || 1057 ( ( nAdobeEncoding == 3 ) && ( m_aEncoding != RTL_TEXTENCODING_SYMBOL ) ) ) 1058 { 1059 if( pChar->code != -1 ) 1060 { 1061 m_pMetrics->m_aMetrics[ pUnicodes[i] ] = aMetric; 1062 if( bFillEncodingvector ) 1063 m_aEncodingVector[ pUnicodes[i] ] = pChar->code; 1064 } 1065 else if( pChar->name ) 1066 { 1067 std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name ); 1068 for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it ) 1069 { 1070 if( *it != 0 ) 1071 m_pMetrics->m_aMetrics[ *it ] = aMetric; 1072 } 1073 } 1074 } 1075 else if( nAdobeEncoding == 1 || nAdobeEncoding == 2 || nAdobeEncoding == 4) 1076 { 1077 if( pChar->name ) 1078 { 1079 std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name ); 1080 for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it ) 1081 { 1082 if( *it != 0 ) 1083 m_pMetrics->m_aMetrics[ *it ] = aMetric; 1084 } 1085 } 1086 else if( pChar->code != -1 ) 1087 { 1088 ::std::pair< ::std::hash_multimap< sal_uInt8, sal_Unicode >::const_iterator, 1089 ::std::hash_multimap< sal_uInt8, sal_Unicode >::const_iterator > 1090 aCodes = rManager.getUnicodeFromAdobeCode( pChar->code ); 1091 while( aCodes.first != aCodes.second ) 1092 { 1093 if( (*aCodes.first).second != 0 ) 1094 { 1095 m_pMetrics->m_aMetrics[ (*aCodes.first).second ] = aMetric; 1096 if( bFillEncodingvector ) 1097 m_aEncodingVector[ (*aCodes.first).second ] = pChar->code; 1098 } 1099 ++aCodes.first; 1100 } 1101 } 1102 } 1103 else if( nAdobeEncoding == 3 ) 1104 { 1105 if( pChar->code != -1 ) 1106 { 1107 sal_Unicode code = 0xf000 + pChar->code; 1108 m_pMetrics->m_aMetrics[ code ] = aMetric; 1109 // maybe should try to find the name in the convtabs ? 1110 if( bFillEncodingvector ) 1111 m_aEncodingVector[ code ] = pChar->code; 1112 } 1113 } 1114 } 1115 1116 m_pMetrics->m_aXKernPairs.clear(); 1117 m_pMetrics->m_aYKernPairs.clear(); 1118 1119 // now fill in the kern pairs 1120 // parseAFM.cxx effectively only supports direction 0 (horizontal) 1121 PairKernData* pKern = pInfo->pkd; 1122 KernPair aPair; 1123 for( i = 0; i < pInfo->numOfPairs; i++, pKern++ ) 1124 { 1125 // #i37703# broken kern table 1126 if( ! pKern->name1 || ! pKern->name2 ) 1127 continue; 1128 1129 aPair.first = 0; 1130 aPair.second = 0; 1131 // currently we have to find the adobe character names 1132 // in the already parsed character metrics to find 1133 // the corresponding UCS2 code which is a bit dangerous 1134 // since the character names are not required 1135 // in the metric descriptions 1136 pChar = pInfo->cmi; 1137 for( int j = 0; 1138 j < pInfo->numOfChars && ( aPair.first == 0 || aPair.second == 0 ); 1139 j++, pChar++ ) 1140 { 1141 if( pChar->code != -1 ) 1142 { 1143 if( ! strcmp( pKern->name1, pChar->name ? pChar->name : "" ) ) 1144 aPair.first = pUnicodes[ j ]; 1145 if( ! strcmp( pKern->name2, pChar->name ? pChar->name : "" ) ) 1146 aPair.second = pUnicodes[ j ]; 1147 } 1148 } 1149 if( aPair.first && aPair.second ) 1150 { 1151 aPair.kern_x = pKern->xamt; 1152 aPair.kern_y = pKern->yamt; 1153 m_pMetrics->m_aXKernPairs.push_back( aPair ); 1154 } 1155 } 1156 m_pMetrics->m_bKernPairsQueried = true; 1157 } 1158 1159 freeFontInfo( pInfo ); 1160 return true; 1161 } 1162 1163 // ------------------------------------------------------------------------- 1164 1165 OString PrintFontManager::s_aEmptyOString; 1166 1167 /* 1168 * one instance only 1169 */ 1170 PrintFontManager& PrintFontManager::get() 1171 { 1172 static PrintFontManager* theManager = NULL; 1173 if( ! theManager ) 1174 { 1175 theManager = new PrintFontManager(); 1176 theManager->initialize(); 1177 } 1178 return *theManager; 1179 } 1180 1181 // ------------------------------------------------------------------------- 1182 1183 /* 1184 * the PrintFontManager 1185 */ 1186 1187 PrintFontManager::PrintFontManager() : 1188 m_nNextFontID( 1 ), 1189 m_pAtoms( new MultiAtomProvider() ), 1190 m_nNextDirAtom( 1 ), 1191 m_pFontCache( NULL ), 1192 m_bFontconfigSuccess( false ) 1193 { 1194 for( unsigned int i = 0; i < sizeof( aAdobeCodes )/sizeof( aAdobeCodes[0] ); i++ ) 1195 { 1196 m_aUnicodeToAdobename.insert( ::std::hash_multimap< sal_Unicode, ::rtl::OString >::value_type( aAdobeCodes[i].aUnicode, aAdobeCodes[i].pAdobename ) ); 1197 m_aAdobenameToUnicode.insert( ::std::hash_multimap< ::rtl::OString, sal_Unicode, ::rtl::OStringHash >::value_type( aAdobeCodes[i].pAdobename, aAdobeCodes[i].aUnicode ) ); 1198 if( aAdobeCodes[i].aAdobeStandardCode ) 1199 { 1200 m_aUnicodeToAdobecode.insert( ::std::hash_multimap< sal_Unicode, sal_uInt8 >::value_type( aAdobeCodes[i].aUnicode, aAdobeCodes[i].aAdobeStandardCode ) ); 1201 m_aAdobecodeToUnicode.insert( ::std::hash_multimap< sal_uInt8, sal_Unicode >::value_type( aAdobeCodes[i].aAdobeStandardCode, aAdobeCodes[i].aUnicode ) ); 1202 } 1203 #if 0 1204 m_aUnicodeToAdobename[ aAdobeCodes[i].aUnicode ] = aAdobeCodes[i].pAdobename; 1205 m_aAdobenameToUnicode[ aAdobeCodes[i].pAdobename ] = aAdobeCodes[i].aUnicode; 1206 if( aAdobeCodes[i].aAdobeStandardCode ) 1207 { 1208 m_aUnicodeToAdobecode[ aAdobeCodes[i].aUnicode ] = aAdobeCodes[i].aAdobeStandardCode; 1209 m_aAdobecodeToUnicode[ aAdobeCodes[i].aAdobeStandardCode ] = aAdobeCodes[i].aUnicode; 1210 } 1211 #endif 1212 } 1213 } 1214 1215 // ------------------------------------------------------------------------- 1216 1217 PrintFontManager::~PrintFontManager() 1218 { 1219 deinitFontconfig(); 1220 for( ::std::hash_map< fontID, PrintFont* >::const_iterator it = m_aFonts.begin(); it != m_aFonts.end(); ++it ) 1221 delete (*it).second; 1222 delete m_pAtoms; 1223 if( m_pFontCache ) 1224 delete m_pFontCache; 1225 } 1226 1227 // ------------------------------------------------------------------------- 1228 1229 const OString& PrintFontManager::getDirectory( int nAtom ) const 1230 { 1231 ::std::hash_map< int, OString >::const_iterator it( m_aAtomToDir.find( nAtom ) ); 1232 return it != m_aAtomToDir.end() ? it->second : s_aEmptyOString; 1233 } 1234 1235 // ------------------------------------------------------------------------- 1236 1237 int PrintFontManager::getDirectoryAtom( const OString& rDirectory, bool bCreate ) 1238 { 1239 int nAtom = 0; 1240 ::std::hash_map< OString, int, OStringHash >::const_iterator it 1241 ( m_aDirToAtom.find( rDirectory ) ); 1242 if( it != m_aDirToAtom.end() ) 1243 nAtom = it->second; 1244 else if( bCreate ) 1245 { 1246 nAtom = m_nNextDirAtom++; 1247 m_aDirToAtom[ rDirectory ] = nAtom; 1248 m_aAtomToDir[ nAtom ] = rDirectory; 1249 } 1250 return nAtom; 1251 } 1252 1253 // ------------------------------------------------------------------------- 1254 1255 int PrintFontManager::addFontFile( const ::rtl::OString& rFileName, int /*nFaceNum*/ ) 1256 { 1257 rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); 1258 INetURLObject aPath( OStringToOUString( rFileName, aEncoding ), INET_PROT_FILE, INetURLObject::ENCODE_ALL ); 1259 OString aName( OUStringToOString( aPath.GetName(), aEncoding ) ); 1260 OString aDir( OUStringToOString( aPath.GetPath(), aEncoding ) ); 1261 1262 int nDirID = getDirectoryAtom( aDir, true ); 1263 fontID nFontId = findFontFileID( nDirID, aName ); 1264 if( !nFontId ) 1265 { 1266 ::std::list< PrintFont* > aNewFonts; 1267 if( analyzeFontFile( nDirID, aName, ::std::list<OString>(), aNewFonts ) ) 1268 { 1269 for( ::std::list< PrintFont* >::iterator it = aNewFonts.begin(); 1270 it != aNewFonts.end(); ++it ) 1271 { 1272 m_aFonts[ nFontId = m_nNextFontID++ ] = *it; 1273 m_aFontFileToFontID[ aName ].insert( nFontId ); 1274 m_pFontCache->updateFontCacheEntry( *it, true ); 1275 } 1276 } 1277 } 1278 return nFontId; 1279 } 1280 1281 // ------------------------------------------------------------------------- 1282 1283 bool PrintFontManager::analyzeFontFile( int nDirID, const OString& rFontFile, const ::std::list<OString>& rXLFDs, ::std::list< PrintFontManager::PrintFont* >& rNewFonts ) const 1284 { 1285 rNewFonts.clear(); 1286 1287 OString aDir( getDirectory( nDirID ) ); 1288 1289 OString aFullPath( aDir ); 1290 aFullPath += "/"; 1291 aFullPath += rFontFile; 1292 1293 // #i1872# reject unreadable files 1294 if( access( aFullPath.getStr(), R_OK ) ) 1295 return false; 1296 1297 ByteString aExt( rFontFile.copy( rFontFile.lastIndexOf( '.' )+1 ) ); 1298 if( aExt.EqualsIgnoreCaseAscii( "pfb" ) || aExt.EqualsIgnoreCaseAscii( "pfa" ) ) 1299 { 1300 // check for corresponding afm metric 1301 // first look for an adjacent file 1302 static const char* pSuffix[] = { ".afm", ".AFM" }; 1303 1304 for( unsigned int i = 0; i < sizeof(pSuffix)/sizeof(pSuffix[0]); i++ ) 1305 { 1306 ByteString aName( rFontFile ); 1307 aName.Erase( aName.Len()-4 ); 1308 aName.Append( pSuffix[i] ); 1309 1310 ByteString aFilePath( aDir ); 1311 aFilePath.Append( '/' ); 1312 aFilePath.Append( aName ); 1313 1314 ByteString aAfmFile; 1315 if( access( aFilePath.GetBuffer(), R_OK ) ) 1316 { 1317 // try in subdirectory afm instead 1318 aFilePath = aDir; 1319 aFilePath.Append( "/afm/" ); 1320 aFilePath.Append( aName ); 1321 1322 if( ! access( aFilePath.GetBuffer(), R_OK ) ) 1323 { 1324 aAfmFile = "afm/"; 1325 aAfmFile += aName; 1326 } 1327 } 1328 else 1329 aAfmFile = aName; 1330 1331 if( aAfmFile.Len() ) 1332 { 1333 Type1FontFile* pFont = new Type1FontFile(); 1334 pFont->m_nDirectory = nDirID; 1335 1336 pFont->m_aFontFile = rFontFile; 1337 pFont->m_aMetricFile = aAfmFile; 1338 1339 if( ! pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true ) ) 1340 { 1341 delete pFont; 1342 pFont = NULL; 1343 } 1344 if( pFont && rXLFDs.size() ) 1345 getFontAttributesFromXLFD( pFont, rXLFDs ); 1346 if( pFont ) 1347 rNewFonts.push_back( pFont ); 1348 break; 1349 } 1350 } 1351 } 1352 else if( aExt.EqualsIgnoreCaseAscii( "afm" ) ) 1353 { 1354 ByteString aFilePath( aDir ); 1355 aFilePath.Append( '/' ); 1356 aFilePath.Append( ByteString( rFontFile ) ); 1357 BuiltinFont* pFont = new BuiltinFont(); 1358 pFont->m_nDirectory = nDirID; 1359 pFont->m_aMetricFile = rFontFile; 1360 if( pFont->readAfmMetrics( aFilePath, m_pAtoms, false, true ) ) 1361 rNewFonts.push_back( pFont ); 1362 else 1363 delete pFont; 1364 } 1365 else if( aExt.EqualsIgnoreCaseAscii( "ttf" ) 1366 || aExt.EqualsIgnoreCaseAscii( "tte" ) // #i33947# for Gaiji support 1367 || aExt.EqualsIgnoreCaseAscii( "otf" ) ) // check for TTF- and PS-OpenType too 1368 { 1369 TrueTypeFontFile* pFont = new TrueTypeFontFile(); 1370 pFont->m_nDirectory = nDirID; 1371 pFont->m_aFontFile = rFontFile; 1372 pFont->m_nCollectionEntry = -1; 1373 1374 if( rXLFDs.size() ) 1375 getFontAttributesFromXLFD( pFont, rXLFDs ); 1376 // need to read the font anyway to get aliases inside the font file 1377 if( ! analyzeTrueTypeFile( pFont ) ) 1378 { 1379 delete pFont; 1380 pFont = NULL; 1381 } 1382 else 1383 rNewFonts.push_back( pFont ); 1384 } 1385 else if( aExt.EqualsIgnoreCaseAscii( "ttc" ) ) 1386 { 1387 // get number of ttc entries 1388 int nLength = CountTTCFonts( aFullPath.getStr() ); 1389 if( nLength ) 1390 { 1391 #if OSL_DEBUG_LEVEL > 1 1392 fprintf( stderr, "%s contains %d fonts\n", aFullPath.getStr(), nLength ); 1393 #endif 1394 for( int i = 0; i < nLength; i++ ) 1395 { 1396 TrueTypeFontFile* pFont = new TrueTypeFontFile(); 1397 pFont->m_nDirectory = nDirID; 1398 pFont->m_aFontFile = rFontFile; 1399 pFont->m_nCollectionEntry = i; 1400 if( nLength == 1 ) 1401 getFontAttributesFromXLFD( pFont, rXLFDs ); 1402 if( ! analyzeTrueTypeFile( pFont ) ) 1403 { 1404 delete pFont; 1405 pFont = NULL; 1406 } 1407 else 1408 rNewFonts.push_back( pFont ); 1409 } 1410 } 1411 #if OSL_DEBUG_LEVEL > 1 1412 else 1413 fprintf( stderr, "CountTTCFonts( \"%s/%s\" ) failed\n", getDirectory(nDirID).getStr(), rFontFile.getStr() ); 1414 #endif 1415 } 1416 return ! rNewFonts.empty(); 1417 } 1418 1419 // ------------------------------------------------------------------------- 1420 1421 fontID PrintFontManager::findFontBuiltinID( int nPSNameAtom ) const 1422 { 1423 fontID nID = 0; 1424 ::std::hash_map< fontID, PrintFont* >::const_iterator it; 1425 for( it = m_aFonts.begin(); nID == 0 && it != m_aFonts.end(); ++it ) 1426 { 1427 if( it->second->m_eType == fonttype::Builtin && 1428 it->second->m_nPSName == nPSNameAtom ) 1429 nID = it->first; 1430 } 1431 return nID; 1432 } 1433 1434 // ------------------------------------------------------------------------- 1435 1436 fontID PrintFontManager::findFontFileID( int nDirID, const OString& rFontFile ) const 1437 { 1438 fontID nID = 0; 1439 1440 ::std::hash_map< OString, ::std::set< fontID >, OStringHash >::const_iterator set_it = m_aFontFileToFontID.find( rFontFile ); 1441 if( set_it != m_aFontFileToFontID.end() ) 1442 { 1443 for( ::std::set< fontID >::const_iterator font_it = set_it->second.begin(); font_it != set_it->second.end() && ! nID; ++font_it ) 1444 { 1445 ::std::hash_map< fontID, PrintFont* >::const_iterator it = m_aFonts.find( *font_it ); 1446 if( it != m_aFonts.end() ) 1447 { 1448 switch( it->second->m_eType ) 1449 { 1450 case fonttype::Type1: 1451 { 1452 Type1FontFile* const pFont = static_cast< Type1FontFile* const >((*it).second); 1453 if( pFont->m_nDirectory == nDirID && 1454 pFont->m_aFontFile == rFontFile ) 1455 nID = it->first; 1456 } 1457 break; 1458 case fonttype::TrueType: 1459 { 1460 TrueTypeFontFile* const pFont = static_cast< TrueTypeFontFile* const >((*it).second); 1461 if( pFont->m_nDirectory == nDirID && 1462 pFont->m_aFontFile == rFontFile ) 1463 nID = it->first; 1464 } 1465 break; 1466 case fonttype::Builtin: 1467 if( static_cast<const BuiltinFont*>((*it).second)->m_nDirectory == nDirID && 1468 static_cast<const BuiltinFont*>((*it).second)->m_aMetricFile == rFontFile ) 1469 nID = it->first; 1470 break; 1471 default: 1472 break; 1473 } 1474 } 1475 } 1476 } 1477 return nID; 1478 } 1479 1480 // ------------------------------------------------------------------------- 1481 1482 bool PrintFontManager::parseXLFD( const OString& rXLFD, XLFDEntry& rEntry ) 1483 { 1484 sal_Int32 nIndex = 0; 1485 OString aFoundry = WhitespaceToSpace( rXLFD.getToken( 1, '-', nIndex ) ); 1486 if( nIndex < 0 ) return false; 1487 OString aFamilyXLFD = WhitespaceToSpace( rXLFD.getToken( 0, '-', nIndex ) ); 1488 if( nIndex < 0 ) return false; 1489 OString aWeight = rXLFD.getToken( 0, '-', nIndex ).toAsciiLowerCase(); 1490 if( nIndex < 0 ) return false; 1491 OString aSlant = rXLFD.getToken( 0, '-', nIndex ).toAsciiLowerCase(); 1492 if( nIndex < 0 ) return false; 1493 OString aWidth = rXLFD.getToken( 0, '-', nIndex ).toAsciiLowerCase(); 1494 if( nIndex < 0 ) return false; 1495 OString aAddStyle = rXLFD.getToken( 0, '-', nIndex ).toAsciiLowerCase(); 1496 if( nIndex < 0 ) return false; 1497 OString aPitch = rXLFD.getToken( 4, '-', nIndex ).toAsciiLowerCase(); 1498 if( nIndex < 0 ) return false; 1499 OString aRegEnc = WhitespaceToSpace( rXLFD.getToken( 1, '-', nIndex ).toAsciiLowerCase() ); 1500 if( nIndex < 0 ) return false; 1501 OString aEnc = WhitespaceToSpace( rXLFD.getToken( 0, '-', nIndex ).toAsciiLowerCase() ); 1502 1503 // capitalize words 1504 sal_Int32 nFamIndex = 0; 1505 OStringBuffer aFamilyName; 1506 while( nFamIndex >= 0 ) 1507 { 1508 OString aToken = aFamilyXLFD.getToken( 0, ' ', nFamIndex ); 1509 sal_Char aFirst = aToken.toChar(); 1510 if( aFirst >= 'a' && aFirst <= 'z' ) 1511 aFirst = aFirst - 'a' + 'A'; 1512 OStringBuffer aNewToken( aToken.getLength() ); 1513 aNewToken.append( aToken ); 1514 aNewToken.setCharAt( 0, aFirst ); 1515 if( aFamilyName.getLength() > 0 ) 1516 aFamilyName.append( ' ' ); 1517 aFamilyName.append( aNewToken.makeStringAndClear() ); 1518 } 1519 1520 rEntry.aFoundry = aFoundry; 1521 rEntry.aFamily = aFamilyName.makeStringAndClear(); 1522 rEntry.aAddStyle = aAddStyle; 1523 // evaluate weight 1524 rEntry.eWeight = parseWeight( aWeight ); 1525 // evaluate slant 1526 rEntry.eItalic = parseItalic( aSlant ); 1527 // evaluate width 1528 rEntry.eWidth = parseWidth( aWidth ); 1529 1530 // evaluate pitch 1531 if( aPitch.toChar() == 'c' || aPitch.toChar() == 'm' ) 1532 rEntry.ePitch = pitch::Fixed; 1533 else 1534 rEntry.ePitch = pitch::Variable; 1535 1536 OString aToken = aEnc.toAsciiLowerCase(); 1537 // get encoding 1538 if( aAddStyle.indexOf( "symbol" ) != -1 ) 1539 rEntry.aEncoding = RTL_TEXTENCODING_SYMBOL; 1540 else 1541 { 1542 if( aToken.equals( "symbol" ) ) 1543 rEntry.aEncoding = RTL_TEXTENCODING_SYMBOL; 1544 else 1545 { 1546 OStringBuffer aCharset( aRegEnc.getLength() + aEnc.getLength() + 1 ); 1547 aCharset.append( aRegEnc ); 1548 aCharset.append( '-' ); 1549 aCharset.append( aEnc ); 1550 rEntry.aEncoding = rtl_getTextEncodingFromUnixCharset( aCharset.getStr() ); 1551 } 1552 } 1553 1554 // set correct mask flags 1555 rEntry.nMask = 0; 1556 if( rEntry.aFoundry != "*" ) rEntry.nMask |= XLFDEntry::MaskFoundry; 1557 if( rEntry.aFamily != "*" ) rEntry.nMask |= XLFDEntry::MaskFamily; 1558 if( rEntry.aAddStyle != "*" ) rEntry.nMask |= XLFDEntry::MaskAddStyle; 1559 if( aWeight != "*" ) rEntry.nMask |= XLFDEntry::MaskWeight; 1560 if( aSlant != "*" ) rEntry.nMask |= XLFDEntry::MaskItalic; 1561 if( aWidth != "*" ) rEntry.nMask |= XLFDEntry::MaskWidth; 1562 if( aPitch != "*" ) rEntry.nMask |= XLFDEntry::MaskPitch; 1563 if( aRegEnc != "*" && aEnc != "*" ) rEntry.nMask |= XLFDEntry::MaskEncoding; 1564 1565 return true; 1566 } 1567 1568 // ------------------------------------------------------------------------- 1569 1570 void PrintFontManager::parseXLFD_appendAliases( const std::list< OString >& rXLFDs, std::list< XLFDEntry >& rEntries ) const 1571 { 1572 for( std::list< OString >::const_iterator it = rXLFDs.begin(); it != rXLFDs.end(); ++it ) 1573 { 1574 XLFDEntry aEntry; 1575 if( ! parseXLFD(*it, aEntry) ) 1576 continue; 1577 rEntries.push_back( aEntry ); 1578 std::map< XLFDEntry, std::list< XLFDEntry > >::const_iterator alias_it = 1579 m_aXLFD_Aliases.find( aEntry ); 1580 if( alias_it != m_aXLFD_Aliases.end() ) 1581 { 1582 rEntries.insert( rEntries.end(), alias_it->second.begin(), alias_it->second.end() ); 1583 } 1584 } 1585 } 1586 1587 // ------------------------------------------------------------------------- 1588 1589 void PrintFontManager::getFontAttributesFromXLFD( PrintFont* pFont, const std::list< OString >& rXLFDs ) const 1590 { 1591 bool bFamilyName = false; 1592 1593 std::list< XLFDEntry > aXLFDs; 1594 1595 parseXLFD_appendAliases( rXLFDs, aXLFDs ); 1596 1597 for( std::list< XLFDEntry >::const_iterator it = aXLFDs.begin(); 1598 it != aXLFDs.end(); ++it ) 1599 { 1600 // set family name or alias 1601 int nFam = 1602 m_pAtoms->getAtom( ATOM_FAMILYNAME, 1603 OStringToOUString( it->aFamily, it->aAddStyle.indexOf( "utf8" ) != -1 ? RTL_TEXTENCODING_UTF8 : RTL_TEXTENCODING_ISO_8859_1 ), 1604 sal_True ); 1605 if( ! bFamilyName ) 1606 { 1607 bFamilyName = true; 1608 pFont->m_nFamilyName = nFam; 1609 switch( pFont->m_eType ) 1610 { 1611 case fonttype::Type1: 1612 static_cast<Type1FontFile*>(pFont)->m_aXLFD = rXLFDs.front(); 1613 break; 1614 case fonttype::TrueType: 1615 static_cast<TrueTypeFontFile*>(pFont)->m_aXLFD = rXLFDs.front(); 1616 break; 1617 default: 1618 break; 1619 } 1620 } 1621 else 1622 { 1623 // make sure that aliases are unique 1624 if( nFam != pFont->m_nFamilyName ) 1625 { 1626 std::list< int >::const_iterator al_it; 1627 for( al_it = pFont->m_aAliases.begin(); al_it != pFont->m_aAliases.end() && *al_it != nFam; ++al_it ) 1628 ; 1629 if( al_it == pFont->m_aAliases.end() ) 1630 pFont->m_aAliases.push_back( nFam ); 1631 1632 } 1633 // for the rest of the attributes there can only be one value; 1634 // we'll trust the first one 1635 continue; 1636 } 1637 1638 // fill in weight 1639 pFont->m_eWeight = it->eWeight; 1640 // fill in slant 1641 pFont->m_eItalic = it->eItalic; 1642 // fill in width 1643 pFont->m_eWidth = it->eWidth; 1644 // fill in pitch 1645 pFont->m_ePitch = it->ePitch; 1646 // fill in encoding 1647 pFont->m_aEncoding = it->aEncoding; 1648 } 1649 1650 // handle iso8859-1 as ms1252 to fill the "gap" starting at 0x80 1651 if( pFont->m_aEncoding == RTL_TEXTENCODING_ISO_8859_1 ) 1652 pFont->m_aEncoding = RTL_TEXTENCODING_MS_1252; 1653 if( rXLFDs.begin() != rXLFDs.end() ) 1654 { 1655 switch( pFont->m_eType ) 1656 { 1657 case fonttype::Type1: 1658 static_cast<Type1FontFile*>(pFont)->m_aXLFD = rXLFDs.front(); 1659 break; 1660 case fonttype::TrueType: 1661 static_cast<TrueTypeFontFile*>(pFont)->m_aXLFD = rXLFDs.front(); 1662 break; 1663 default: break; 1664 } 1665 } 1666 } 1667 1668 // ------------------------------------------------------------------------- 1669 1670 OString PrintFontManager::getXLFD( PrintFont* pFont ) const 1671 { 1672 if( pFont->m_eType == fonttype::Type1 ) 1673 { 1674 if( static_cast<Type1FontFile*>(pFont)->m_aXLFD.getLength() ) 1675 return static_cast<Type1FontFile*>(pFont)->m_aXLFD; 1676 } 1677 if( pFont->m_eType == fonttype::TrueType ) 1678 { 1679 if( static_cast<TrueTypeFontFile*>(pFont)->m_aXLFD.getLength() ) 1680 return static_cast<TrueTypeFontFile*>(pFont)->m_aXLFD; 1681 } 1682 1683 OStringBuffer aXLFD( 128 ); 1684 1685 aXLFD.append( "-misc-" ); 1686 ByteString aFamily( String( m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ) ), RTL_TEXTENCODING_UTF8 ); 1687 aFamily.SearchAndReplaceAll( '-',' ' ); 1688 aFamily.SearchAndReplaceAll( '?',' ' ); 1689 aFamily.SearchAndReplaceAll( '*',' ' ); 1690 aXLFD.append( OString( aFamily ) ); 1691 aXLFD.append( '-' ); 1692 switch( pFont->m_eWeight ) 1693 { 1694 case weight::Thin: aXLFD.append("thin");break; 1695 case weight::UltraLight: aXLFD.append("ultralight");break; 1696 case weight::Light: aXLFD.append("light");break; 1697 case weight::SemiLight: aXLFD.append("semilight");break; 1698 case weight::Normal: aXLFD.append("normal");break; 1699 case weight::Medium: aXLFD.append("medium");break; 1700 case weight::SemiBold: aXLFD.append("semibold");break; 1701 case weight::Bold: aXLFD.append("bold");break; 1702 case weight::UltraBold: aXLFD.append("ultrabold");break; 1703 case weight::Black: aXLFD.append("black");break; 1704 default: break; 1705 } 1706 aXLFD.append('-'); 1707 switch( pFont->m_eItalic ) 1708 { 1709 case italic::Upright: aXLFD.append('r');break; 1710 case italic::Oblique: aXLFD.append('o');break; 1711 case italic::Italic: aXLFD.append('i');break; 1712 default: break; 1713 } 1714 aXLFD.append('-'); 1715 switch( pFont->m_eWidth ) 1716 { 1717 case width::UltraCondensed: aXLFD.append("ultracondensed");break; 1718 case width::ExtraCondensed: aXLFD.append("extracondensed");break; 1719 case width::Condensed: aXLFD.append("condensed");break; 1720 case width::SemiCondensed: aXLFD.append("semicondensed");break; 1721 case width::Normal: aXLFD.append("normal");break; 1722 case width::SemiExpanded: aXLFD.append("semiexpanded");break; 1723 case width::Expanded: aXLFD.append("expanded");break; 1724 case width::ExtraExpanded: aXLFD.append("extraexpanded");break; 1725 case width::UltraExpanded: aXLFD.append("ultraexpanded");break; 1726 default: break; 1727 } 1728 aXLFD.append("-utf8-0-0-0-0-"); 1729 aXLFD.append( pFont->m_ePitch == pitch::Fixed ? "m" : "p" ); 1730 aXLFD.append("-0-"); 1731 const char* pEnc = rtl_getBestUnixCharsetFromTextEncoding( pFont->m_aEncoding ); 1732 if( ! pEnc ) 1733 { 1734 if( pFont->m_aEncoding == RTL_TEXTENCODING_ADOBE_STANDARD ) 1735 pEnc = "adobe-standard"; 1736 else 1737 pEnc = "iso8859-1"; 1738 } 1739 aXLFD .append( pEnc ); 1740 1741 return aXLFD.makeStringAndClear(); 1742 } 1743 1744 // ------------------------------------------------------------------------- 1745 1746 OUString PrintFontManager::convertTrueTypeName( void* pRecord ) const 1747 { 1748 NameRecord* pNameRecord = (NameRecord*)pRecord; 1749 OUString aValue; 1750 if( 1751 ( pNameRecord->platformID == 3 && ( pNameRecord->encodingID == 0 || pNameRecord->encodingID == 1 ) ) // MS, Unicode 1752 || 1753 ( pNameRecord->platformID == 0 ) // Apple, Unicode 1754 ) 1755 { 1756 OUStringBuffer aName( pNameRecord->slen/2 ); 1757 const sal_uInt8* pNameBuffer = pNameRecord->sptr; 1758 for(int n = 0; n < pNameRecord->slen/2; n++ ) 1759 aName.append( (sal_Unicode)getUInt16BE( pNameBuffer ) ); 1760 aValue = aName.makeStringAndClear(); 1761 } 1762 else if( pNameRecord->platformID == 3 ) 1763 { 1764 if( pNameRecord->encodingID >= 2 && pNameRecord->encodingID <= 6 ) 1765 { 1766 /* 1767 * and now for a special kind of madness: 1768 * some fonts encode their byte value string as BE uint16 1769 * (leading to stray zero bytes in the string) 1770 * while others code two bytes as a uint16 and swap to BE 1771 */ 1772 OStringBuffer aName; 1773 const sal_uInt8* pNameBuffer = pNameRecord->sptr; 1774 for(int n = 0; n < pNameRecord->slen/2; n++ ) 1775 { 1776 sal_Unicode aCode = (sal_Unicode)getUInt16BE( pNameBuffer ); 1777 sal_Char aChar = aCode >> 8; 1778 if( aChar ) 1779 aName.append( aChar ); 1780 aChar = aCode & 0x00ff; 1781 if( aChar ) 1782 aName.append( aChar ); 1783 } 1784 switch( pNameRecord->encodingID ) 1785 { 1786 case 2: 1787 aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_932 ); 1788 break; 1789 case 3: 1790 aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_936 ); 1791 break; 1792 case 4: 1793 aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_950 ); 1794 break; 1795 case 5: 1796 aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_949 ); 1797 break; 1798 case 6: 1799 aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_1361 ); 1800 break; 1801 } 1802 } 1803 } 1804 return aValue; 1805 } 1806 1807 // ------------------------------------------------------------------------- 1808 1809 void PrintFontManager::analyzeTrueTypeFamilyName( void* pTTFont, ::std::list< OUString >& rNames ) const 1810 { 1811 OUString aFamily; 1812 1813 rNames.clear(); 1814 ::std::set< OUString > aSet; 1815 1816 NameRecord* pNameRecords = NULL; 1817 int nNameRecords = GetTTNameRecords( (TrueTypeFont*)pTTFont, &pNameRecords ); 1818 if( nNameRecords && pNameRecords ) 1819 { 1820 LanguageType aLang = MsLangId::getSystemLanguage(); 1821 int nLastMatch = -1; 1822 for( int i = 0; i < nNameRecords; i++ ) 1823 { 1824 if( pNameRecords[i].nameID != 1 || pNameRecords[i].sptr == NULL ) 1825 continue; 1826 int nMatch = -1; 1827 if( pNameRecords[i].platformID == 0 ) // Unicode 1828 nMatch = 4000; 1829 else if( pNameRecords[i].platformID == 3 ) 1830 { 1831 // this bases on the LanguageType actually being a Win LCID 1832 if( pNameRecords[i].languageID == aLang ) 1833 nMatch = 8000; 1834 else if( pNameRecords[i].languageID == LANGUAGE_ENGLISH_US ) 1835 nMatch = 2000; 1836 else if( pNameRecords[i].languageID == LANGUAGE_ENGLISH || 1837 pNameRecords[i].languageID == LANGUAGE_ENGLISH_UK ) 1838 nMatch = 1500; 1839 else 1840 nMatch = 1000; 1841 } 1842 OUString aName = convertTrueTypeName( pNameRecords + i ); 1843 aSet.insert( aName ); 1844 if( nMatch > nLastMatch ) 1845 { 1846 nLastMatch = nMatch; 1847 aFamily = aName; 1848 } 1849 } 1850 DisposeNameRecords( pNameRecords, nNameRecords ); 1851 } 1852 if( aFamily.getLength() ) 1853 { 1854 rNames.push_front( aFamily ); 1855 for( ::std::set< OUString >::const_iterator it = aSet.begin(); it != aSet.end(); ++it ) 1856 if( *it != aFamily ) 1857 rNames.push_back( *it ); 1858 } 1859 return; 1860 } 1861 1862 // ------------------------------------------------------------------------- 1863 1864 bool PrintFontManager::analyzeTrueTypeFile( PrintFont* pFont ) const 1865 { 1866 bool bSuccess = false; 1867 rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); 1868 ByteString aFile = getFontFile( pFont ); 1869 TrueTypeFont* pTTFont = NULL; 1870 1871 TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont); 1872 if( OpenTTFontFile( aFile.GetBuffer(), pTTFontFile->m_nCollectionEntry < 0 ? 0 : pTTFontFile->m_nCollectionEntry, &pTTFont ) == SF_OK ) 1873 { 1874 TTGlobalFontInfo aInfo; 1875 GetTTGlobalFontInfo( pTTFont, & aInfo ); 1876 1877 ::std::list< OUString > aNames; 1878 analyzeTrueTypeFamilyName( pTTFont, aNames ); 1879 1880 // set family name from XLFD if possible 1881 if( ! pFont->m_nFamilyName ) 1882 { 1883 if( aNames.begin() != aNames.end() ) 1884 { 1885 pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, aNames.front(), sal_True ); 1886 aNames.pop_front(); 1887 } 1888 else 1889 { 1890 sal_Int32 dotIndex; 1891 1892 // poor font does not have a family name 1893 // name it to file name minus the extension 1894 dotIndex = pTTFontFile->m_aFontFile.lastIndexOf( '.' ); 1895 if ( dotIndex == -1 ) 1896 dotIndex = pTTFontFile->m_aFontFile.getLength(); 1897 1898 pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, OStringToOUString( pTTFontFile->m_aFontFile.copy( 0, dotIndex ), aEncoding ), sal_True ); 1899 } 1900 } 1901 for( ::std::list< OUString >::iterator it = aNames.begin(); it != aNames.end(); ++it ) 1902 { 1903 if( it->getLength() ) 1904 { 1905 int nAlias = m_pAtoms->getAtom( ATOM_FAMILYNAME, *it, sal_True ); 1906 if( nAlias != pFont->m_nFamilyName ) 1907 { 1908 std::list< int >::const_iterator al_it; 1909 for( al_it = pFont->m_aAliases.begin(); al_it != pFont->m_aAliases.end() && *al_it != nAlias; ++al_it ) 1910 ; 1911 if( al_it == pFont->m_aAliases.end() ) 1912 pFont->m_aAliases.push_back( nAlias ); 1913 } 1914 } 1915 } 1916 1917 if( aInfo.usubfamily ) 1918 pFont->m_aStyleName = OUString( aInfo.usubfamily ); 1919 1920 pFont->m_nPSName = m_pAtoms->getAtom( ATOM_PSNAME, String( ByteString( aInfo.psname ), aEncoding ), sal_True ); 1921 switch( aInfo.weight ) 1922 { 1923 case FW_THIN: pFont->m_eWeight = weight::Thin; break; 1924 case FW_EXTRALIGHT: pFont->m_eWeight = weight::UltraLight; break; 1925 case FW_LIGHT: pFont->m_eWeight = weight::Light; break; 1926 case FW_MEDIUM: pFont->m_eWeight = weight::Medium; break; 1927 case FW_SEMIBOLD: pFont->m_eWeight = weight::SemiBold; break; 1928 case FW_BOLD: pFont->m_eWeight = weight::Bold; break; 1929 case FW_EXTRABOLD: pFont->m_eWeight = weight::UltraBold; break; 1930 case FW_BLACK: pFont->m_eWeight = weight::Black; break; 1931 1932 case FW_NORMAL: 1933 default: pFont->m_eWeight = weight::Normal; break; 1934 } 1935 1936 switch( aInfo.width ) 1937 { 1938 case FWIDTH_ULTRA_CONDENSED: pFont->m_eWidth = width::UltraCondensed; break; 1939 case FWIDTH_EXTRA_CONDENSED: pFont->m_eWidth = width::ExtraCondensed; break; 1940 case FWIDTH_CONDENSED: pFont->m_eWidth = width::Condensed; break; 1941 case FWIDTH_SEMI_CONDENSED: pFont->m_eWidth = width::SemiCondensed; break; 1942 case FWIDTH_SEMI_EXPANDED: pFont->m_eWidth = width::SemiExpanded; break; 1943 case FWIDTH_EXPANDED: pFont->m_eWidth = width::Expanded; break; 1944 case FWIDTH_EXTRA_EXPANDED: pFont->m_eWidth = width::ExtraExpanded; break; 1945 case FWIDTH_ULTRA_EXPANDED: pFont->m_eWidth = width::UltraExpanded; break; 1946 1947 case FWIDTH_NORMAL: 1948 default: pFont->m_eWidth = width::Normal; break; 1949 } 1950 1951 pFont->m_ePitch = aInfo.pitch ? pitch::Fixed : pitch::Variable; 1952 pFont->m_eItalic = aInfo.italicAngle == 0 ? italic::Upright : ( aInfo.italicAngle < 0 ? italic::Italic : italic::Oblique ); 1953 // #104264# there are fonts that set italic angle 0 although they are 1954 // italic; use macstyle bit here 1955 if( aInfo.italicAngle == 0 && (aInfo.macStyle & 2) ) 1956 pFont->m_eItalic = italic::Italic; 1957 1958 pFont->m_aEncoding = aInfo.symbolEncoded ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UCS2; 1959 1960 pFont->m_aGlobalMetricY.width = pFont->m_aGlobalMetricX.width = aInfo.xMax - aInfo.xMin; 1961 pFont->m_aGlobalMetricY.height = pFont->m_aGlobalMetricX.height = aInfo.yMax - aInfo.yMin; 1962 1963 if( aInfo.winAscent && aInfo.winDescent ) 1964 { 1965 pFont->m_nAscend = aInfo.winAscent; 1966 pFont->m_nDescend = aInfo.winDescent; 1967 pFont->m_nLeading = pFont->m_nAscend + pFont->m_nDescend - 1000; 1968 } 1969 else if( aInfo.typoAscender && aInfo.typoDescender ) 1970 { 1971 pFont->m_nLeading = aInfo.typoLineGap; 1972 pFont->m_nAscend = aInfo.typoAscender; 1973 pFont->m_nDescend = -aInfo.typoDescender; 1974 } 1975 else 1976 { 1977 pFont->m_nLeading = aInfo.linegap; 1978 pFont->m_nAscend = aInfo.ascender; 1979 pFont->m_nDescend = -aInfo.descender; 1980 } 1981 1982 // last try: font bounding box 1983 if( pFont->m_nAscend == 0 ) 1984 pFont->m_nAscend = aInfo.yMax; 1985 if( pFont->m_nDescend == 0 ) 1986 pFont->m_nDescend = -aInfo.yMin; 1987 if( pFont->m_nLeading == 0 ) 1988 pFont->m_nLeading = 15 * (pFont->m_nAscend+pFont->m_nDescend) / 100; 1989 1990 if( pFont->m_nAscend ) 1991 pFont->m_aGlobalMetricX.height = pFont->m_aGlobalMetricY.height = pFont->m_nAscend + pFont->m_nDescend; 1992 1993 // get bounding box 1994 pFont->m_nXMin = aInfo.xMin; 1995 pFont->m_nYMin = aInfo.yMin; 1996 pFont->m_nXMax = aInfo.xMax; 1997 pFont->m_nYMax = aInfo.yMax; 1998 1999 // get type flags 2000 pTTFontFile->m_nTypeFlags = (unsigned int)aInfo.typeFlags; 2001 2002 // get vertical substitutions flag 2003 pFont->m_bHaveVerticalSubstitutedGlyphs = DoesVerticalSubstitution( pTTFont, 1 ); 2004 2005 CloseTTFont( pTTFont ); 2006 bSuccess = true; 2007 } 2008 #if OSL_DEBUG_LEVEL > 1 2009 else 2010 fprintf( stderr, "could not OpenTTFont \"%s\"\n", aFile.GetBuffer() ); 2011 #endif 2012 2013 return bSuccess; 2014 } 2015 2016 // ------------------------------------------------------------------------- 2017 2018 void PrintFontManager::initFontsAlias() 2019 { 2020 m_aXLFD_Aliases.clear(); 2021 rtl_TextEncoding aEnc = osl_getThreadTextEncoding(); 2022 for( std::list< OString >::const_iterator dir_it = m_aFontDirectories.begin(); 2023 dir_it != m_aFontDirectories.end(); ++dir_it ) 2024 { 2025 OStringBuffer aDirName(512); 2026 aDirName.append( *dir_it ); 2027 aDirName.append( "/fonts.alias" ); 2028 SvFileStream aStream( OStringToOUString( aDirName.makeStringAndClear(), aEnc ), STREAM_READ ); 2029 if( ! aStream.IsOpen() ) 2030 continue; 2031 2032 do 2033 { 2034 ByteString aLine; 2035 aStream.ReadLine( aLine ); 2036 2037 // get the alias and the pattern it gets translated to 2038 ByteString aAlias = GetCommandLineToken( 0, aLine ); 2039 ByteString aMap = GetCommandLineToken( 1, aLine ); 2040 2041 // remove eventual quotes 2042 aAlias.EraseLeadingChars( '"' ); 2043 aAlias.EraseTrailingChars( '"' ); 2044 aMap.EraseLeadingChars( '"' ); 2045 aMap.EraseTrailingChars( '"' ); 2046 2047 XLFDEntry aAliasEntry, aMapEntry; 2048 parseXLFD( aAlias, aAliasEntry ); 2049 parseXLFD( aMap, aMapEntry ); 2050 2051 if( aAliasEntry.nMask && aMapEntry.nMask ) 2052 m_aXLFD_Aliases[ aMapEntry ].push_back( aAliasEntry ); 2053 } while( ! aStream.IsEof() ); 2054 } 2055 } 2056 2057 // code stolen from vcl's RegisterFontSubstitutors() 2058 // TODO: use that method once psprint gets merged into vcl 2059 static bool AreFCSubstitutionsEnabled() 2060 { 2061 // init font substitution defaults 2062 int nDisableBits = 0; 2063 #ifdef SOLARIS 2064 // TODO: check the OS version and fc-data maintenance level 2065 nDisableBits = 1; // disable "font fallback" here on default 2066 #endif 2067 // apply the environment variable if any 2068 const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" ); 2069 if( pEnvStr ) 2070 { 2071 // 2072 if( (*pEnvStr >= '0') && (*pEnvStr <= '9') ) 2073 nDisableBits = (*pEnvStr - '0'); 2074 else 2075 nDisableBits = ~0U; // no specific bits set: disable all 2076 } 2077 2078 return ((nDisableBits & 3) == 0); 2079 } 2080 2081 void PrintFontManager::initialize() 2082 { 2083 #ifdef CALLGRIND_COMPILE 2084 CALLGRIND_TOGGLE_COLLECT(); 2085 CALLGRIND_ZERO_STATS(); 2086 #endif 2087 2088 long aDirEntBuffer[ (sizeof(struct dirent)+_PC_NAME_MAX)+1 ]; 2089 2090 if( ! m_pFontCache ) 2091 { 2092 #if OSL_DEBUG_LEVEL > 1 2093 fprintf( stderr, "creating font cache ... " ); 2094 clock_t aStart; 2095 struct tms tms; 2096 aStart = times( &tms ); 2097 #endif 2098 m_pFontCache = new FontCache(); 2099 #if OSL_DEBUG_LEVEL > 1 2100 clock_t aStop = times( &tms ); 2101 fprintf( stderr, "done in %lf s\n", (double)(aStop - aStart)/(double)sysconf( _SC_CLK_TCK ) ); 2102 #endif 2103 } 2104 2105 // initialize may be called twice in the future 2106 { 2107 for( ::std::hash_map< fontID, PrintFont* >::const_iterator it = m_aFonts.begin(); it != m_aFonts.end(); ++it ) 2108 delete (*it).second; 2109 m_nNextFontID = 1; 2110 m_aFonts.clear(); 2111 m_aFontDirectories.clear(); 2112 m_aPrivateFontDirectories.clear(); 2113 m_aOverrideFonts.clear(); 2114 } 2115 2116 #if OSL_DEBUG_LEVEL > 1 2117 clock_t aStart; 2118 clock_t aStep1; 2119 clock_t aStep2; 2120 clock_t aStep3; 2121 int nBuiltinFonts = 0; 2122 int nCached = 0; 2123 2124 struct tms tms; 2125 2126 aStart = times( &tms ); 2127 #endif 2128 2129 // first try fontconfig 2130 m_bFontconfigSuccess = initFontconfig(); 2131 2132 // part one - look for downloadable fonts 2133 rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); 2134 const ::rtl::OUString &rSalPrivatePath = psp::getFontPath(); 2135 2136 // search for the fonts in SAL_PRIVATE_FONTPATH first; those are 2137 // the fonts installed with the office 2138 if( rSalPrivatePath.getLength() ) 2139 { 2140 OString aPath = rtl::OUStringToOString( rSalPrivatePath, aEncoding ); 2141 const bool bAreFCSubstitutionsEnabled = AreFCSubstitutionsEnabled(); 2142 sal_Int32 nIndex = 0; 2143 do 2144 { 2145 OString aToken = aPath.getToken( 0, ';', nIndex ); 2146 normPath( aToken ); 2147 // if registering an app-specific fontdir with fontconfig fails 2148 // and fontconfig-based substitutions are enabled 2149 // then trying to use these app-specific fonts doesn't make sense 2150 if( m_bFontconfigSuccess && !addFontconfigDir( aToken ) ) 2151 if( bAreFCSubstitutionsEnabled ) 2152 continue; 2153 m_aFontDirectories.push_back( aToken ); 2154 m_aPrivateFontDirectories.push_back( getDirectoryAtom( aToken, true ) ); 2155 } while( nIndex >= 0 ); 2156 } 2157 2158 // protect against duplicate paths 2159 std::hash_map< OString, int, OStringHash > visited_dirs; 2160 2161 // now that all global and local font dirs are known to fontconfig 2162 // check that there are fonts actually managed by fontconfig 2163 // also don't search directories that fontconfig already did 2164 if( m_bFontconfigSuccess ) 2165 m_bFontconfigSuccess = (countFontconfigFonts( visited_dirs ) > 0); 2166 2167 // don't search through many directories fontconfig already told us about 2168 if( ! m_bFontconfigSuccess ) 2169 ImplGetSVData()->mpDefInst->FillFontPathList( m_aFontDirectories ); 2170 2171 // fill XLFD aliases from fonts.alias files 2172 initFontsAlias(); 2173 2174 // search for font files in each path 2175 std::list< OString >::iterator dir_it; 2176 for( dir_it = m_aFontDirectories.begin(); dir_it != m_aFontDirectories.end(); ++dir_it ) 2177 { 2178 OString aPath( *dir_it ); 2179 // see if we were here already 2180 if( visited_dirs.find( aPath ) != visited_dirs.end() ) 2181 continue; 2182 visited_dirs[ aPath ] = 1; 2183 2184 // there may be ":unscaled" directories (see XFree86) 2185 // it should be safe to ignore them since they should not 2186 // contain any of our recognizeable fonts 2187 2188 // ask the font cache whether it handles this directory 2189 std::list< PrintFont* > aCacheFonts; 2190 if( m_pFontCache->listDirectory( aPath, aCacheFonts ) ) 2191 { 2192 #if OSL_DEBUG_LEVEL > 1 2193 fprintf( stderr, "adding cache directory: %s\n", aPath.getStr() ); 2194 #endif 2195 for( ::std::list< PrintFont* >::iterator it = aCacheFonts.begin(); it != aCacheFonts.end(); ++it ) 2196 { 2197 fontID aFont = m_nNextFontID++; 2198 m_aFonts[ aFont ] = *it; 2199 if( (*it)->m_eType == fonttype::Type1 ) 2200 m_aFontFileToFontID[ static_cast<Type1FontFile*>(*it)->m_aFontFile ].insert( aFont ); 2201 else if( (*it)->m_eType == fonttype::TrueType ) 2202 m_aFontFileToFontID[ static_cast<TrueTypeFontFile*>(*it)->m_aFontFile ].insert( aFont ); 2203 else if( (*it)->m_eType == fonttype::Builtin ) 2204 m_aFontFileToFontID[ static_cast<BuiltinFont*>(*it)->m_aMetricFile ].insert( aFont ); 2205 #if OSL_DEBUG_LEVEL > 1 2206 if( (*it)->m_eType == fonttype::Builtin ) 2207 nBuiltinFonts++; 2208 nCached++; 2209 #if OSL_DEBUG_LEVEL > 2 2210 fprintf( stderr, "adding cached font %d: \"%s\" from %s\n", aFont, 2211 OUStringToOString( getFontFamily( aFont ), RTL_TEXTENCODING_MS_1252 ).getStr(), 2212 getFontFileSysPath( aFont ).getStr() ); 2213 #endif 2214 #endif 2215 } 2216 if( ! m_pFontCache->scanAdditionalFiles( aPath ) ) 2217 continue; 2218 } 2219 2220 DIR* pDIR = opendir( aPath.getStr() ); 2221 struct dirent* pEntry = (struct dirent*)aDirEntBuffer; 2222 if( pDIR ) 2223 { 2224 // read fonts.dir if possible 2225 ::std::hash_map< OString, ::std::list<OString>, OStringHash > aFontsDir; 2226 int nDirID = getDirectoryAtom( aPath, true ); 2227 // #i38367# no fonts.dir in our own directories anymore 2228 std::list< int >::const_iterator priv_dir; 2229 for( priv_dir = m_aPrivateFontDirectories.begin(); 2230 priv_dir != m_aPrivateFontDirectories.end() && *priv_dir != nDirID; 2231 ++priv_dir ) 2232 ; 2233 2234 if( priv_dir == m_aPrivateFontDirectories.end() ) 2235 { 2236 ByteString aGccDummy( aPath ); 2237 String aFontsDirPath( aGccDummy, aEncoding ); 2238 aFontsDirPath.AppendAscii( "/fonts.dir" ); 2239 SvFileStream aStream( aFontsDirPath, STREAM_READ ); 2240 if( aStream.IsOpen() ) 2241 { 2242 ByteString aLine; 2243 while( ! aStream.IsEof() ) 2244 { 2245 aStream.ReadLine( aLine ); 2246 ByteString aFileName( GetCommandLineToken( 0, aLine ) ); 2247 ByteString aXLFD( aLine.Copy( aFileName.Len() ) ); 2248 if( aFileName.Len() && aXLFD.Len() ) 2249 aFontsDir[ aFileName ].push_back(aXLFD); 2250 } 2251 } 2252 } 2253 2254 int nDirFonts = 0; 2255 while( ! readdir_r( pDIR, (struct dirent*)aDirEntBuffer, &pEntry ) && pEntry ) 2256 { 2257 OString aFileName( pEntry->d_name ); 2258 // ignore .afm files here 2259 if( aFileName.getLength() > 3 && 2260 aFileName.lastIndexOf( ".afm" ) == aFileName.getLength()-4 ) 2261 continue; 2262 2263 struct stat aStat; 2264 ByteString aFilePath( aPath ); 2265 aFilePath.Append( '/' ); 2266 aFilePath.Append( ByteString( aFileName ) ); 2267 if( ! stat( aFilePath.GetBuffer(), &aStat ) && 2268 S_ISREG( aStat.st_mode ) ) 2269 { 2270 if( findFontFileID( nDirID, aFileName ) == 0 ) 2271 { 2272 ::std::list<OString> aXLFDs; 2273 ::std::hash_map< OString, ::std::list<OString>, OStringHash >::const_iterator it = 2274 aFontsDir.find( aFileName ); 2275 if( it != aFontsDir.end() ) 2276 aXLFDs = (*it).second; 2277 2278 // fill in font attributes from XLFD rather 2279 // than reading every file 2280 ::std::list< PrintFont* > aNewFonts; 2281 if( analyzeFontFile( nDirID, aFileName, aXLFDs, aNewFonts ) ) 2282 { 2283 for( ::std::list< PrintFont* >::iterator font_it = aNewFonts.begin(); font_it != aNewFonts.end(); ++font_it ) 2284 { 2285 fontID aFont = m_nNextFontID++; 2286 m_aFonts[ aFont ] = *font_it; 2287 m_aFontFileToFontID[ aFileName ].insert( aFont ); 2288 m_pFontCache->updateFontCacheEntry( *font_it, false ); 2289 nDirFonts++; 2290 #if OSL_DEBUG_LEVEL > 2 2291 fprintf( stderr, "adding font %d: \"%s\" from %s\n", aFont, 2292 OUStringToOString( getFontFamily( aFont ), RTL_TEXTENCODING_MS_1252 ).getStr(), 2293 getFontFileSysPath( aFont ).getStr() ); 2294 #endif 2295 } 2296 } 2297 } 2298 } 2299 } 2300 closedir( pDIR ); 2301 m_pFontCache->updateDirTimestamp( nDirID ); 2302 if( ! nDirFonts ) 2303 m_pFontCache->markEmptyDir( nDirID ); 2304 } 2305 } 2306 2307 #if OSL_DEBUG_LEVEL > 1 2308 aStep1 = times( &tms ); 2309 #endif 2310 2311 // part two - look for metrics for builtin printer fonts 2312 std::list< OUString > aMetricDirs; 2313 psp::getPrinterPathList( aMetricDirs, PRINTER_METRICDIR ); 2314 2315 std::list< OString > aEmptyFontsDir; 2316 for( std::list< OUString >::const_iterator met_dir_it = aMetricDirs.begin(); met_dir_it != aMetricDirs.end(); ++met_dir_it ) 2317 { 2318 OString aDir = OUStringToOString( *met_dir_it, aEncoding ); 2319 2320 // ask the font cache whether it handles this directory 2321 std::list< PrintFont* > aCacheFonts; 2322 2323 if( m_pFontCache->listDirectory( aDir, aCacheFonts ) ) 2324 { 2325 #if OSL_DEBUG_LEVEL > 1 2326 fprintf( stderr, "adding cache directory: %s\n", aDir.getStr() ); 2327 #endif 2328 for( ::std::list< PrintFont* >::iterator it = aCacheFonts.begin(); it != aCacheFonts.end(); ++it ) 2329 { 2330 fontID aFont = m_nNextFontID++; 2331 m_aFonts[ aFont ] = *it; 2332 if( (*it)->m_eType == fonttype::Type1 ) 2333 m_aFontFileToFontID[ static_cast<Type1FontFile*>(*it)->m_aFontFile ].insert( aFont ); 2334 else if( (*it)->m_eType == fonttype::TrueType ) 2335 m_aFontFileToFontID[ static_cast<TrueTypeFontFile*>(*it)->m_aFontFile ].insert( aFont ); 2336 else if( (*it)->m_eType == fonttype::Builtin ) 2337 m_aFontFileToFontID[ static_cast<BuiltinFont*>(*it)->m_aMetricFile ].insert( aFont ); 2338 #if OSL_DEBUG_LEVEL > 1 2339 if( (*it)->m_eType == fonttype::Builtin ) 2340 nBuiltinFonts++; 2341 nCached++; 2342 #if OSL_DEBUG_LEVEL > 2 2343 fprintf( stderr, "adding cached font %d: \"%s\" from %s\n", aFont, 2344 OUStringToOString( getFontFamily( aFont ), RTL_TEXTENCODING_MS_1252 ).getStr(), 2345 getFontFileSysPath( aFont ).getStr() ); 2346 #endif 2347 #endif 2348 } 2349 continue; 2350 } 2351 2352 DIR* pDIR = opendir( aDir.getStr() ); 2353 if( pDIR ) 2354 { 2355 struct dirent* pDirEntry = (struct dirent*)aDirEntBuffer; 2356 int nDirID = getDirectoryAtom( aDir, true ); 2357 int nDirFonts = 0; 2358 2359 while( ! readdir_r( pDIR, (struct dirent*)aDirEntBuffer, &pDirEntry ) && pDirEntry ) 2360 { 2361 ByteString aFile( aDir ); 2362 aFile += '/'; 2363 aFile += pDirEntry->d_name; 2364 struct stat aStat; 2365 if( ! stat( aFile.GetBuffer(), &aStat ) 2366 && S_ISREG( aStat.st_mode ) 2367 ) 2368 { 2369 OString aFileName( pDirEntry->d_name, strlen( pDirEntry->d_name ) ); 2370 OString aExt( aFileName.copy( aFileName.lastIndexOf( '.' )+1 ) ); 2371 if( aExt.equalsIgnoreAsciiCase( "afm" ) ) 2372 { 2373 ::std::list< PrintFont* > aNewFonts; 2374 2375 analyzeFontFile( nDirID, aFileName, aEmptyFontsDir, aNewFonts ); 2376 for( ::std::list< PrintFont* >::iterator it = aNewFonts.begin(); it != aNewFonts.end(); ++it ) 2377 { 2378 if( findFontBuiltinID( (*it)->m_nPSName ) == 0 ) 2379 { 2380 m_aFontFileToFontID[ aFileName ].insert( m_nNextFontID ); 2381 m_aFonts[ m_nNextFontID++ ] = *it; 2382 m_pFontCache->updateFontCacheEntry( *it, false ); 2383 #if OSL_DEBUG_LEVEL > 2 2384 nBuiltinFonts++; 2385 #endif 2386 } 2387 else 2388 delete *it; 2389 } 2390 } 2391 } 2392 } 2393 closedir( pDIR ); 2394 if( ! nDirFonts ) 2395 m_pFontCache->markEmptyDir( nDirID ); 2396 } 2397 } 2398 2399 #if OSL_DEBUG_LEVEL > 1 2400 aStep2 = times( &tms ); 2401 #endif 2402 2403 // part three - fill in family styles 2404 ::std::hash_map< fontID, PrintFont* >::iterator font_it; 2405 for (font_it = m_aFonts.begin(); font_it != m_aFonts.end(); ++font_it) 2406 { 2407 ::std::hash_map< int, family::type >::const_iterator it = 2408 m_aFamilyTypes.find( font_it->second->m_nFamilyName ); 2409 if (it != m_aFamilyTypes.end()) 2410 continue; 2411 const ::rtl::OUString& rFamily = 2412 m_pAtoms->getString( ATOM_FAMILYNAME, font_it->second->m_nFamilyName); 2413 family::type eType = matchFamilyName( rFamily ); 2414 m_aFamilyTypes[ font_it->second->m_nFamilyName ] = eType; 2415 } 2416 2417 #if OSL_DEBUG_LEVEL > 1 2418 aStep3 = times( &tms ); 2419 fprintf( stderr, "PrintFontManager::initialize: collected %d fonts (%d builtin, %d cached)\n", m_aFonts.size(), nBuiltinFonts, nCached ); 2420 double fTick = (double)sysconf( _SC_CLK_TCK ); 2421 fprintf( stderr, "Step 1 took %lf seconds\n", (double)(aStep1 - aStart)/fTick ); 2422 fprintf( stderr, "Step 2 took %lf seconds\n", (double)(aStep2 - aStep1)/fTick ); 2423 fprintf( stderr, "Step 3 took %lf seconds\n", (double)(aStep3 - aStep2)/fTick ); 2424 #endif 2425 2426 m_pFontCache->flush(); 2427 2428 #ifdef CALLGRIND_COMPILE 2429 CALLGRIND_DUMP_STATS(); 2430 CALLGRIND_TOGGLE_COLLECT(); 2431 #endif 2432 } 2433 2434 // ------------------------------------------------------------------------- 2435 inline bool 2436 equalPitch (psp::pitch::type from, psp::pitch::type to) 2437 { 2438 return from == to; 2439 } 2440 2441 inline bool 2442 equalWeight (psp::weight::type from, psp::weight::type to) 2443 { 2444 return from > to ? (from - to) <= 3 : (to - from) <= 3; 2445 } 2446 2447 inline bool 2448 equalItalic (psp::italic::type from, psp::italic::type to) 2449 { 2450 if ( (from == psp::italic::Italic) || (from == psp::italic::Oblique) ) 2451 return (to == psp::italic::Italic) || (to == psp::italic::Oblique); 2452 return to == from; 2453 } 2454 inline bool 2455 equalEncoding (rtl_TextEncoding from, rtl_TextEncoding to) 2456 { 2457 if ((from == RTL_TEXTENCODING_ISO_8859_1) || (from == RTL_TEXTENCODING_MS_1252)) 2458 return (to == RTL_TEXTENCODING_ISO_8859_1) || (to == RTL_TEXTENCODING_MS_1252); 2459 return from == to; 2460 } 2461 2462 namespace { 2463 struct BuiltinFontIdentifier 2464 { 2465 OUString aFamily; 2466 italic::type eItalic; 2467 weight::type eWeight; 2468 pitch::type ePitch; 2469 rtl_TextEncoding aEncoding; 2470 2471 BuiltinFontIdentifier( const OUString& rFam, 2472 italic::type eIt, 2473 weight::type eWg, 2474 pitch::type ePt, 2475 rtl_TextEncoding enc ) : 2476 aFamily( rFam ), 2477 eItalic( eIt ), 2478 eWeight( eWg ), 2479 ePitch( ePt ), 2480 aEncoding( enc ) 2481 {} 2482 2483 bool operator==( const BuiltinFontIdentifier& rRight ) const 2484 { 2485 return equalItalic( eItalic, rRight.eItalic ) && 2486 equalWeight( eWeight, rRight.eWeight ) && 2487 equalPitch( ePitch, rRight.ePitch ) && 2488 equalEncoding( aEncoding, rRight.aEncoding ) && 2489 aFamily.equalsIgnoreAsciiCase( rRight.aFamily ); 2490 } 2491 }; 2492 2493 struct BuiltinFontIdentifierHash 2494 { 2495 size_t operator()( const BuiltinFontIdentifier& rFont ) const 2496 { 2497 return rFont.aFamily.hashCode() ^ rFont.eItalic ^ rFont.eWeight ^ rFont.ePitch ^ rFont.aEncoding; 2498 } 2499 }; 2500 } 2501 2502 void PrintFontManager::getFontList( ::std::list< fontID >& rFontIDs, const PPDParser* pParser, bool bUseOverrideMetrics ) 2503 { 2504 rFontIDs.clear(); 2505 std::hash_map< fontID, PrintFont* >::const_iterator it; 2506 2507 /* 2508 * Note: there are two easy steps making this faster: 2509 * first: insert the printer builtins first, then the not builtins, 2510 * if they do not match. 2511 * drawback: this would change the sequence of fonts; this could have 2512 * subtle, unknown consequences in vcl font matching 2513 * second: instead of comparing attributes to see whether a softfont 2514 * is duplicate to a builtin one could simply compare the PSName (which is 2515 * supposed to be unique), which at this point is just an int. 2516 * drawback: this could change which fonts are listed; especially TrueType 2517 * fonts often have a rather dubious PSName, so this could change the 2518 * font list not so subtle. 2519 * Until getFontList for a printer becomes a performance issue (which is 2520 * currently not the case), best stay with the current algorithm. 2521 */ 2522 2523 // fill sets of printer supported fonts 2524 if( pParser ) 2525 { 2526 std::set<int> aBuiltinPSNames; 2527 std::hash_set< BuiltinFontIdentifier, 2528 BuiltinFontIdentifierHash 2529 > aBuiltinFonts; 2530 2531 std::map<int, fontID > aOverridePSNames; 2532 if( bUseOverrideMetrics ) 2533 { 2534 readOverrideMetrics(); 2535 for( std::vector<fontID>::const_iterator over = m_aOverrideFonts.begin(); 2536 over != m_aOverrideFonts.end(); ++over ) 2537 { 2538 std::hash_map<fontID,PrintFont*>::const_iterator font_it = m_aFonts.find( *over ); 2539 DBG_ASSERT( font_it != m_aFonts.end(), "override to nonexistant font" ); 2540 if( font_it != m_aFonts.end() ) 2541 aOverridePSNames[ font_it->second->m_nPSName ] = *over; 2542 } 2543 } 2544 2545 int nFonts = pParser->getFonts(); 2546 for( int i = 0; i < nFonts; i++ ) 2547 aBuiltinPSNames.insert( m_pAtoms->getAtom( ATOM_PSNAME, pParser->getFont( i ) ) ); 2548 for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it ) 2549 { 2550 PrintFont* pFont = it->second; 2551 if( it->second->m_eType == fonttype::Builtin && 2552 aBuiltinPSNames.find( pFont->m_nPSName ) != aBuiltinPSNames.end() ) 2553 { 2554 bool bInsert = true; 2555 if( bUseOverrideMetrics ) 2556 { 2557 // in override case only use the override fonts, not their counterparts 2558 std::map<int,fontID>::const_iterator over = aOverridePSNames.find( pFont->m_nPSName ); 2559 if( over != aOverridePSNames.end() && over->second != it->first ) 2560 bInsert = false; 2561 } 2562 else 2563 { 2564 // do not insert override fonts in non override case 2565 if( std::find( m_aOverrideFonts.begin(), m_aOverrideFonts.end(), it->first ) != m_aOverrideFonts.end() ) 2566 bInsert = false; 2567 } 2568 if( bInsert ) 2569 { 2570 aBuiltinFonts.insert( BuiltinFontIdentifier( 2571 m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ), 2572 pFont->m_eItalic, 2573 pFont->m_eWeight, 2574 pFont->m_ePitch, 2575 pFont->m_aEncoding 2576 ) ); 2577 } 2578 } 2579 } 2580 for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it ) 2581 { 2582 PrintFont* pFont = it->second; 2583 if( it->second->m_eType == fonttype::Builtin ) 2584 { 2585 if( aBuiltinPSNames.find( pFont->m_nPSName ) != aBuiltinPSNames.end() ) 2586 { 2587 bool bInsert = true; 2588 if( bUseOverrideMetrics ) 2589 { 2590 // in override case only use the override fonts, not their counterparts 2591 std::map<int,fontID>::const_iterator over = aOverridePSNames.find( pFont->m_nPSName ); 2592 if( over != aOverridePSNames.end() && over->second != it->first ) 2593 bInsert = false; 2594 } 2595 else 2596 { 2597 // do not insert override fonts in non override case 2598 if( std::find( m_aOverrideFonts.begin(), m_aOverrideFonts.end(), it->first ) != m_aOverrideFonts.end() ) 2599 bInsert = false; 2600 } 2601 if( bInsert ) 2602 rFontIDs.push_back( it->first ); 2603 } 2604 } 2605 else if( aBuiltinFonts.find( BuiltinFontIdentifier( 2606 m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ), 2607 pFont->m_eItalic, 2608 pFont->m_eWeight, 2609 pFont->m_ePitch, 2610 pFont->m_aEncoding 2611 ) ) == aBuiltinFonts.end() ) 2612 { 2613 rFontIDs.push_back( it->first ); 2614 } 2615 } 2616 } 2617 else // no specific printer 2618 { 2619 for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it ) 2620 rFontIDs.push_back( it->first ); 2621 } 2622 } 2623 2624 // ------------------------------------------------------------------------- 2625 2626 void PrintFontManager::fillPrintFontInfo( PrintFont* pFont, FastPrintFontInfo& rInfo ) const 2627 { 2628 ::std::hash_map< int, family::type >::const_iterator style_it = 2629 m_aFamilyTypes.find( pFont->m_nFamilyName ); 2630 rInfo.m_eType = pFont->m_eType; 2631 rInfo.m_aFamilyName = m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ); 2632 rInfo.m_aStyleName = pFont->m_aStyleName; 2633 rInfo.m_eFamilyStyle = style_it != m_aFamilyTypes.end() ? style_it->second : family::Unknown; 2634 rInfo.m_eItalic = pFont->m_eItalic; 2635 rInfo.m_eWidth = pFont->m_eWidth; 2636 rInfo.m_eWeight = pFont->m_eWeight; 2637 rInfo.m_ePitch = pFont->m_ePitch; 2638 rInfo.m_aEncoding = pFont->m_aEncoding; 2639 2640 rInfo.m_bEmbeddable = (pFont->m_eType == fonttype::Type1); 2641 rInfo.m_bSubsettable = (pFont->m_eType == fonttype::TrueType); // TODO: rename to SfntType 2642 2643 rInfo.m_aAliases.clear(); 2644 for( ::std::list< int >::iterator it = pFont->m_aAliases.begin(); it != pFont->m_aAliases.end(); ++it ) 2645 rInfo.m_aAliases.push_back( m_pAtoms->getString( ATOM_FAMILYNAME, *it ) ); 2646 } 2647 2648 // ------------------------------------------------------------------------- 2649 2650 void PrintFontManager::fillPrintFontInfo( PrintFont* pFont, PrintFontInfo& rInfo ) const 2651 { 2652 if( ( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 ) || 2653 ! pFont->m_pMetrics || pFont->m_pMetrics->isEmpty() 2654 ) 2655 { 2656 // might be a truetype font not analyzed or type1 without metrics read 2657 if( pFont->m_eType == fonttype::Type1 ) 2658 pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, false ); 2659 else if( pFont->m_eType == fonttype::TrueType ) 2660 analyzeTrueTypeFile( pFont ); 2661 } 2662 2663 fillPrintFontInfo( pFont, static_cast< FastPrintFontInfo& >( rInfo ) ); 2664 2665 rInfo.m_nAscend = pFont->m_nAscend; 2666 rInfo.m_nDescend = pFont->m_nDescend; 2667 rInfo.m_nLeading = pFont->m_nLeading; 2668 rInfo.m_nWidth = pFont->m_aGlobalMetricX.width < pFont->m_aGlobalMetricY.width ? pFont->m_aGlobalMetricY.width : pFont->m_aGlobalMetricX.width; 2669 } 2670 2671 // ------------------------------------------------------------------------- 2672 2673 void PrintFontManager::getFontListWithInfo( ::std::list< PrintFontInfo >& rFonts, const PPDParser* pParser, bool bUseOverrideMetrics ) 2674 { 2675 rFonts.clear(); 2676 ::std::list< fontID > aFontList; 2677 getFontList( aFontList, pParser, bUseOverrideMetrics ); 2678 2679 ::std::list< fontID >::iterator it; 2680 for( it = aFontList.begin(); it != aFontList.end(); ++it ) 2681 { 2682 PrintFontInfo aInfo; 2683 aInfo.m_nID = *it; 2684 fillPrintFontInfo( getFont( *it ), aInfo ); 2685 rFonts.push_back( aInfo ); 2686 } 2687 } 2688 2689 // ------------------------------------------------------------------------- 2690 2691 void PrintFontManager::getFontListWithFastInfo( ::std::list< FastPrintFontInfo >& rFonts, const PPDParser* pParser, bool bUseOverrideMetrics ) 2692 { 2693 rFonts.clear(); 2694 ::std::list< fontID > aFontList; 2695 getFontList( aFontList, pParser, bUseOverrideMetrics ); 2696 2697 ::std::list< fontID >::iterator it; 2698 for( it = aFontList.begin(); it != aFontList.end(); ++it ) 2699 { 2700 FastPrintFontInfo aInfo; 2701 aInfo.m_nID = *it; 2702 fillPrintFontInfo( getFont( *it ), aInfo ); 2703 rFonts.push_back( aInfo ); 2704 } 2705 } 2706 2707 // ------------------------------------------------------------------------- 2708 2709 bool PrintFontManager::getFontInfo( fontID nFontID, PrintFontInfo& rInfo ) const 2710 { 2711 PrintFont* pFont = getFont( nFontID ); 2712 if( pFont ) 2713 { 2714 rInfo.m_nID = nFontID; 2715 fillPrintFontInfo( pFont, rInfo ); 2716 } 2717 return pFont ? true : false; 2718 } 2719 2720 // ------------------------------------------------------------------------- 2721 2722 bool PrintFontManager::getFontFastInfo( fontID nFontID, FastPrintFontInfo& rInfo ) const 2723 { 2724 PrintFont* pFont = getFont( nFontID ); 2725 if( pFont ) 2726 { 2727 rInfo.m_nID = nFontID; 2728 fillPrintFontInfo( pFont, rInfo ); 2729 } 2730 return pFont ? true : false; 2731 } 2732 2733 // ------------------------------------------------------------------------- 2734 2735 bool PrintFontManager::getFontBoundingBox( fontID nFontID, int& xMin, int& yMin, int& xMax, int& yMax ) 2736 { 2737 bool bSuccess = false; 2738 PrintFont* pFont = getFont( nFontID ); 2739 if( pFont ) 2740 { 2741 if( pFont->m_nXMin == 0 && pFont->m_nYMin == 0 && pFont->m_nXMax == 0 && pFont->m_nYMax == 0 ) 2742 { 2743 // might be a truetype font not analyzed or type1 without metrics read 2744 if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin ) 2745 pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true ); 2746 else if( pFont->m_eType == fonttype::TrueType ) 2747 analyzeTrueTypeFile( pFont ); 2748 } 2749 bSuccess = true; 2750 xMin = pFont->m_nXMin; 2751 yMin = pFont->m_nYMin; 2752 xMax = pFont->m_nXMax; 2753 yMax = pFont->m_nYMax; 2754 } 2755 return bSuccess; 2756 } 2757 2758 // ------------------------------------------------------------------------- 2759 2760 int PrintFontManager::getFontFaceNumber( fontID nFontID ) const 2761 { 2762 int nRet = -1; 2763 PrintFont* pFont = getFont( nFontID ); 2764 if( pFont && pFont->m_eType == fonttype::TrueType ) 2765 nRet = static_cast< TrueTypeFontFile* >(pFont)->m_nCollectionEntry; 2766 return nRet; 2767 } 2768 2769 // ------------------------------------------------------------------------- 2770 2771 2772 family::type PrintFontManager::matchFamilyName( const ::rtl::OUString& rFamily ) const 2773 { 2774 typedef struct { 2775 const char* mpName; 2776 sal_uInt16 mnLength; 2777 family::type meType; 2778 } family_t; 2779 2780 #define InitializeClass( p, a ) p, sizeof(p) - 1, a 2781 const family_t pFamilyMatch[] = { 2782 { InitializeClass( "arial", family::Swiss ) }, 2783 { InitializeClass( "arioso", family::Script ) }, 2784 { InitializeClass( "avant garde", family::Swiss ) }, 2785 { InitializeClass( "avantgarde", family::Swiss ) }, 2786 { InitializeClass( "bembo", family::Roman ) }, 2787 { InitializeClass( "bookman", family::Roman ) }, 2788 { InitializeClass( "conga", family::Roman ) }, 2789 { InitializeClass( "courier", family::Modern ) }, 2790 { InitializeClass( "curl", family::Script ) }, 2791 { InitializeClass( "fixed", family::Modern ) }, 2792 { InitializeClass( "gill", family::Swiss ) }, 2793 { InitializeClass( "helmet", family::Modern ) }, 2794 { InitializeClass( "helvetica", family::Swiss ) }, 2795 { InitializeClass( "international", family::Modern ) }, 2796 { InitializeClass( "lucida", family::Swiss ) }, 2797 { InitializeClass( "new century schoolbook", family::Roman ) }, 2798 { InitializeClass( "palatino", family::Roman ) }, 2799 { InitializeClass( "roman", family::Roman ) }, 2800 { InitializeClass( "sans serif", family::Swiss ) }, 2801 { InitializeClass( "sansserif", family::Swiss ) }, 2802 { InitializeClass( "serf", family::Roman ) }, 2803 { InitializeClass( "serif", family::Roman ) }, 2804 { InitializeClass( "times", family::Roman ) }, 2805 { InitializeClass( "utopia", family::Roman ) }, 2806 { InitializeClass( "zapf chancery", family::Script ) }, 2807 { InitializeClass( "zapfchancery", family::Script ) } 2808 }; 2809 2810 rtl::OString aFamily = rtl::OUStringToOString( rFamily, RTL_TEXTENCODING_ASCII_US ); 2811 sal_uInt32 nLower = 0; 2812 sal_uInt32 nUpper = sizeof(pFamilyMatch) / sizeof(pFamilyMatch[0]); 2813 2814 while( nLower < nUpper ) 2815 { 2816 sal_uInt32 nCurrent = (nLower + nUpper) / 2; 2817 const family_t* pHaystack = pFamilyMatch + nCurrent; 2818 sal_Int32 nComparison = 2819 rtl_str_compareIgnoreAsciiCase_WithLength 2820 ( 2821 aFamily.getStr(), aFamily.getLength(), 2822 pHaystack->mpName, pHaystack->mnLength 2823 ); 2824 2825 if( nComparison < 0 ) 2826 nUpper = nCurrent; 2827 else 2828 if( nComparison > 0 ) 2829 nLower = nCurrent + 1; 2830 else 2831 return pHaystack->meType; 2832 } 2833 2834 return family::Unknown; 2835 } 2836 2837 // ------------------------------------------------------------------------- 2838 2839 family::type PrintFontManager::getFontFamilyType( fontID nFontID ) const 2840 { 2841 PrintFont* pFont = getFont( nFontID ); 2842 if( !pFont ) 2843 return family::Unknown; 2844 2845 ::std::hash_map< int, family::type >::const_iterator it = 2846 m_aFamilyTypes.find( pFont->m_nFamilyName ); 2847 return (it != m_aFamilyTypes.end()) ? it->second : family::Unknown; 2848 } 2849 2850 2851 // ------------------------------------------------------------------------- 2852 2853 const ::rtl::OUString& PrintFontManager::getFontFamily( fontID nFontID ) const 2854 { 2855 PrintFont* pFont = getFont( nFontID ); 2856 return m_pAtoms->getString( ATOM_FAMILYNAME, pFont ? pFont->m_nFamilyName : INVALID_ATOM ); 2857 } 2858 2859 // ------------------------------------------------------------------------- 2860 2861 OString PrintFontManager::getAfmFile( PrintFont* pFont ) const 2862 { 2863 OString aMetricPath; 2864 if( pFont ) 2865 { 2866 switch( pFont->m_eType ) 2867 { 2868 case fonttype::Type1: 2869 { 2870 Type1FontFile* pPSFont = static_cast< Type1FontFile* >(pFont); 2871 aMetricPath = getDirectory( pPSFont->m_nDirectory ); 2872 aMetricPath += "/"; 2873 aMetricPath += pPSFont->m_aMetricFile; 2874 } 2875 break; 2876 case fonttype::Builtin: 2877 { 2878 BuiltinFont* pBuiltinFont = static_cast< BuiltinFont* >(pFont); 2879 aMetricPath = getDirectory( pBuiltinFont->m_nDirectory ); 2880 aMetricPath += "/"; 2881 aMetricPath += pBuiltinFont->m_aMetricFile; 2882 } 2883 break; 2884 default: break; 2885 } 2886 } 2887 return aMetricPath; 2888 } 2889 2890 // ------------------------------------------------------------------------- 2891 2892 OString PrintFontManager::getFontFile( PrintFont* pFont ) const 2893 { 2894 OString aPath; 2895 2896 if( pFont && pFont->m_eType == fonttype::Type1 ) 2897 { 2898 Type1FontFile* pPSFont = static_cast< Type1FontFile* >(pFont); 2899 ::std::hash_map< int, OString >::const_iterator it = m_aAtomToDir.find( pPSFont->m_nDirectory ); 2900 aPath = it->second; 2901 aPath += "/"; 2902 aPath += pPSFont->m_aFontFile; 2903 } 2904 else if( pFont && pFont->m_eType == fonttype::TrueType ) 2905 { 2906 TrueTypeFontFile* pTTFont = static_cast< TrueTypeFontFile* >(pFont); 2907 ::std::hash_map< int, OString >::const_iterator it = m_aAtomToDir.find( pTTFont->m_nDirectory ); 2908 aPath = it->second; 2909 aPath += "/"; 2910 aPath += pTTFont->m_aFontFile; 2911 } 2912 return aPath; 2913 } 2914 2915 // ------------------------------------------------------------------------- 2916 2917 const ::rtl::OUString& PrintFontManager::getPSName( fontID nFontID ) const 2918 { 2919 PrintFont* pFont = getFont( nFontID ); 2920 if( pFont && pFont->m_nPSName == 0 ) 2921 { 2922 if( pFont->m_eType == fonttype::TrueType ) 2923 analyzeTrueTypeFile( pFont ); 2924 } 2925 2926 return m_pAtoms->getString( ATOM_PSNAME, pFont ? pFont->m_nPSName : INVALID_ATOM ); 2927 } 2928 2929 // ------------------------------------------------------------------------- 2930 2931 const CharacterMetric& PrintFontManager::getGlobalFontMetric( fontID nFontID, bool bHorizontal ) const 2932 { 2933 static CharacterMetric aMetric; 2934 PrintFont* pFont = getFont( nFontID ); 2935 return pFont ? ( bHorizontal ? pFont->m_aGlobalMetricX : pFont->m_aGlobalMetricY ) : aMetric; 2936 } 2937 2938 // ------------------------------------------------------------------------- 2939 2940 int PrintFontManager::getFontAscend( fontID nFontID ) const 2941 { 2942 PrintFont* pFont = getFont( nFontID ); 2943 if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 ) 2944 { 2945 // might be a truetype font not yet analyzed 2946 if( pFont->m_eType == fonttype::TrueType ) 2947 analyzeTrueTypeFile( pFont ); 2948 else if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin ) 2949 pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true ); 2950 } 2951 return pFont->m_nAscend; 2952 } 2953 2954 // ------------------------------------------------------------------------- 2955 2956 int PrintFontManager::getFontDescend( fontID nFontID ) const 2957 { 2958 PrintFont* pFont = getFont( nFontID ); 2959 if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 ) 2960 { 2961 // might be a truetype font not yet analyzed 2962 if( pFont->m_eType == fonttype::TrueType ) 2963 analyzeTrueTypeFile( pFont ); 2964 else if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin ) 2965 pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true ); 2966 } 2967 return pFont->m_nDescend; 2968 } 2969 2970 // ------------------------------------------------------------------------- 2971 2972 int PrintFontManager::getFontLeading( fontID nFontID ) const 2973 { 2974 PrintFont* pFont = getFont( nFontID ); 2975 if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 ) 2976 { 2977 // might be a truetype font not yet analyzed 2978 if( pFont->m_eType == fonttype::TrueType ) 2979 analyzeTrueTypeFile( pFont ); 2980 } 2981 return pFont->m_nLeading; 2982 } 2983 2984 // ------------------------------------------------------------------------- 2985 2986 bool PrintFontManager::hasVerticalSubstitutions( fontID nFontID ) const 2987 { 2988 PrintFont* pFont = getFont( nFontID ); 2989 if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 ) 2990 { 2991 // might be a truetype font not yet analyzed 2992 if( pFont->m_eType == fonttype::TrueType ) 2993 analyzeTrueTypeFile( pFont ); 2994 } 2995 return pFont->m_bHaveVerticalSubstitutedGlyphs; 2996 } 2997 2998 // ------------------------------------------------------------------------- 2999 3000 void PrintFontManager::hasVerticalSubstitutions( fontID nFontID, 3001 const sal_Unicode* pCharacters, int nCharacters, bool* pHasSubst ) const 3002 { 3003 PrintFont* pFont = getFont( nFontID ); 3004 if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 ) 3005 { 3006 // might be a truetype font not yet analyzed 3007 if( pFont->m_eType == fonttype::TrueType ) 3008 analyzeTrueTypeFile( pFont ); 3009 } 3010 3011 if( ! pFont->m_bHaveVerticalSubstitutedGlyphs ) 3012 memset( pHasSubst, 0, sizeof(bool)*nCharacters ); 3013 else 3014 { 3015 for( int i = 0; i < nCharacters; i++ ) 3016 { 3017 sal_Unicode code = pCharacters[i]; 3018 if( ! pFont->m_pMetrics || 3019 ! ( pFont->m_pMetrics->m_aPages[ code >> 11 ] & ( 1 << ( ( code >> 8 ) & 7 ) ) ) ) 3020 pFont->queryMetricPage( code >> 8, m_pAtoms ); 3021 ::std::hash_map< sal_Unicode, bool >::const_iterator it = pFont->m_pMetrics->m_bVerticalSubstitutions.find( code ); 3022 pHasSubst[i] = it != pFont->m_pMetrics->m_bVerticalSubstitutions.end(); 3023 } 3024 } 3025 } 3026 3027 // ------------------------------------------------------------------------- 3028 3029 OUString PrintFontManager::getFontXLFD( fontID nFontID ) const 3030 { 3031 PrintFont* pFont = getFont( nFontID ); 3032 OUString aRet; 3033 if( pFont ) 3034 { 3035 ByteString aXLFD( getXLFD( pFont ) ); 3036 rtl_TextEncoding aEncoding = aXLFD.GetToken( 6, '-' ).Search( "utf8" ) != STRING_NOTFOUND ? RTL_TEXTENCODING_UTF8 : RTL_TEXTENCODING_ISO_8859_1; 3037 aRet = OStringToOUString( aXLFD, aEncoding ); 3038 } 3039 return aRet; 3040 } 3041 3042 // ------------------------------------------------------------------------- 3043 3044 const ::std::list< KernPair >& PrintFontManager::getKernPairs( fontID nFontID, bool bVertical ) const 3045 { 3046 static ::std::list< KernPair > aEmpty; 3047 3048 PrintFont* pFont = getFont( nFontID ); 3049 if( ! pFont ) 3050 return aEmpty; 3051 3052 if( ! pFont->m_pMetrics || ! pFont->m_pMetrics->m_bKernPairsQueried ) 3053 pFont->queryMetricPage( 0, m_pAtoms ); 3054 if( ! pFont->m_pMetrics || ! pFont->m_pMetrics->m_bKernPairsQueried ) 3055 return aEmpty; 3056 return bVertical ? pFont->m_pMetrics->m_aYKernPairs : pFont->m_pMetrics->m_aXKernPairs; 3057 } 3058 3059 // ------------------------------------------------------------------------- 3060 3061 bool PrintFontManager::isFontDownloadingAllowed( fontID nFont ) const 3062 { 3063 static const char* pEnable = getenv( "PSPRINT_ENABLE_TTF_COPYRIGHTAWARENESS" ); 3064 bool bRet = true; 3065 3066 if( pEnable && *pEnable ) 3067 { 3068 PrintFont* pFont = getFont( nFont ); 3069 if( pFont && pFont->m_eType == fonttype::TrueType ) 3070 { 3071 TrueTypeFontFile* pTTFontFile = static_cast<TrueTypeFontFile*>(pFont); 3072 if( pTTFontFile->m_nTypeFlags & TYPEFLAG_INVALID ) 3073 { 3074 TrueTypeFont* pTTFont = NULL; 3075 ByteString aFile = getFontFile( pFont ); 3076 if( OpenTTFontFile( aFile.GetBuffer(), pTTFontFile->m_nCollectionEntry < 0 ? 0 : pTTFontFile->m_nCollectionEntry, &pTTFont ) == SF_OK ) 3077 { 3078 // get type flags 3079 TTGlobalFontInfo aInfo; 3080 GetTTGlobalFontInfo( pTTFont, & aInfo ); 3081 pTTFontFile->m_nTypeFlags = (unsigned int)aInfo.typeFlags; 3082 CloseTTFont( pTTFont ); 3083 } 3084 } 3085 3086 unsigned int nCopyrightFlags = pTTFontFile->m_nTypeFlags & TYPEFLAG_COPYRIGHT_MASK; 3087 3088 // font embedding is allowed if either 3089 // no restriction at all (bit 1 clear) 3090 // printing allowed (bit 1 set, bit 2 set ) 3091 bRet = ! ( nCopyrightFlags & 0x02 ) || ( nCopyrightFlags & 0x04 ); 3092 } 3093 } 3094 return bRet; 3095 } 3096 3097 // ------------------------------------------------------------------------- 3098 3099 bool PrintFontManager::getMetrics( fontID nFontID, const sal_Unicode* pString, int nLen, CharacterMetric* pArray, bool bVertical ) const 3100 { 3101 PrintFont* pFont = getFont( nFontID ); 3102 if( ! pFont ) 3103 return false; 3104 3105 if( ( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 ) 3106 || ! pFont->m_pMetrics || pFont->m_pMetrics->isEmpty() 3107 ) 3108 { 3109 // might be a font not yet analyzed 3110 if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin ) 3111 pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, false ); 3112 else if( pFont->m_eType == fonttype::TrueType ) 3113 analyzeTrueTypeFile( pFont ); 3114 } 3115 3116 for( int i = 0; i < nLen; i++ ) 3117 { 3118 if( ! pFont->m_pMetrics || 3119 ! ( pFont->m_pMetrics->m_aPages[ pString[i] >> 11 ] & ( 1 << ( ( pString[i] >> 8 ) & 7 ) ) ) ) 3120 pFont->queryMetricPage( pString[i] >> 8, m_pAtoms ); 3121 pArray[i].width = pArray[i].height = -1; 3122 if( pFont->m_pMetrics ) 3123 { 3124 int effectiveCode = pString[i]; 3125 effectiveCode |= bVertical ? 1 << 16 : 0; 3126 ::std::hash_map< int, CharacterMetric >::const_iterator it = 3127 pFont->m_pMetrics->m_aMetrics.find( effectiveCode ); 3128 // if no vertical metrics are available assume rotated horizontal metrics 3129 if( bVertical && (it == pFont->m_pMetrics->m_aMetrics.end()) ) 3130 it = pFont->m_pMetrics->m_aMetrics.find( pString[i] ); 3131 // the character metrics are in it->second 3132 if( it != pFont->m_pMetrics->m_aMetrics.end() ) 3133 pArray[ i ] = it->second; 3134 } 3135 } 3136 3137 return true; 3138 } 3139 3140 // ------------------------------------------------------------------------- 3141 3142 bool PrintFontManager::getMetrics( fontID nFontID, sal_Unicode minCharacter, sal_Unicode maxCharacter, CharacterMetric* pArray, bool bVertical ) const 3143 { 3144 PrintFont* pFont = getFont( nFontID ); 3145 if( ! pFont ) 3146 return false; 3147 3148 if( ( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 ) 3149 || ! pFont->m_pMetrics || pFont->m_pMetrics->isEmpty() 3150 ) 3151 { 3152 // might be a font not yet analyzed 3153 if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin ) 3154 pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, false ); 3155 else if( pFont->m_eType == fonttype::TrueType ) 3156 analyzeTrueTypeFile( pFont ); 3157 } 3158 3159 sal_Unicode code = minCharacter; 3160 do 3161 { 3162 if( ! pFont->m_pMetrics || 3163 ! ( pFont->m_pMetrics->m_aPages[ code >> 11 ] & ( 1 << ( ( code >> 8 ) & 7 ) ) ) ) 3164 pFont->queryMetricPage( code >> 8, m_pAtoms ); 3165 pArray[ code - minCharacter ].width = -1; 3166 pArray[ code - minCharacter ].height = -1; 3167 if( pFont->m_pMetrics ) 3168 { 3169 int effectiveCode = code; 3170 effectiveCode |= bVertical ? 1 << 16 : 0; 3171 ::std::hash_map< int, CharacterMetric >::const_iterator it = 3172 pFont->m_pMetrics->m_aMetrics.find( effectiveCode ); 3173 // if no vertical metrics are available assume rotated horizontal metrics 3174 if( bVertical && (it == pFont->m_pMetrics->m_aMetrics.end()) ) 3175 it = pFont->m_pMetrics->m_aMetrics.find( code ); 3176 // the character metrics are in it->second 3177 if( it != pFont->m_pMetrics->m_aMetrics.end() ) 3178 pArray[ code - minCharacter ] = it->second; 3179 } 3180 } while( code++ != maxCharacter ); 3181 3182 return true; 3183 } 3184 3185 // ------------------------------------------------------------------------- 3186 3187 static bool createWriteablePath( const ByteString& rPath ) 3188 { 3189 bool bSuccess = false; 3190 3191 if( access( rPath.GetBuffer(), W_OK ) ) 3192 { 3193 int nPos = rPath.SearchBackward( '/' ); 3194 if( nPos != STRING_NOTFOUND ) 3195 while( nPos > 0 && rPath.GetChar( nPos ) == '/' ) 3196 nPos--; 3197 3198 if( nPos != STRING_NOTFOUND && nPos != 0 && createWriteablePath( rPath.Copy( 0, nPos+1 ) ) ) 3199 { 3200 bSuccess = mkdir( rPath.GetBuffer(), 0777 ) ? false : true; 3201 } 3202 } 3203 else 3204 bSuccess = true; 3205 3206 return bSuccess; 3207 } 3208 3209 3210 // ------------------------------------------------------------------------- 3211 3212 int PrintFontManager::importFonts( const ::std::list< OString >& rFiles, bool bLinkOnly, ImportFontCallback* pCallback ) 3213 { 3214 int nSuccess = 0; 3215 3216 // find a directory with write access 3217 rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); 3218 bool bCanWrite = false; 3219 int nDirID = 0; 3220 INetURLObject aDir; 3221 for( ::std::list< int >::const_iterator dir_it = m_aPrivateFontDirectories.begin(); 3222 ! bCanWrite && dir_it != m_aPrivateFontDirectories.end(); ++dir_it ) 3223 { 3224 // check if we can create files in that directory 3225 ByteString aDirPath = getDirectory( *dir_it ); 3226 if( createWriteablePath( aDirPath ) ) 3227 { 3228 aDir = INetURLObject( OStringToOUString( aDirPath, aEncoding ), INET_PROT_FILE, INetURLObject::ENCODE_ALL ); 3229 nDirID = *dir_it; 3230 bCanWrite = true; 3231 } 3232 } 3233 if( bCanWrite ) 3234 { 3235 for( ::std::list< OString >::const_iterator font_it = rFiles.begin(); 3236 font_it != rFiles.end(); ++font_it ) 3237 { 3238 INetURLObject aFrom( OStringToOUString( *font_it, aEncoding ), INET_PROT_FILE, INetURLObject::ENCODE_ALL ); 3239 INetURLObject aTo( aDir ); 3240 aTo.Append( aFrom.GetName() ); 3241 3242 if( pCallback ) 3243 pCallback->progress( aTo.PathToFileName() ); 3244 3245 if( pCallback && pCallback->isCanceled() ) 3246 break; 3247 3248 if( ! access( ByteString( String(aTo.PathToFileName()), aEncoding ).GetBuffer(), F_OK ) ) 3249 { 3250 if( ! ( pCallback ? pCallback->queryOverwriteFile( aTo.PathToFileName() ) : false ) ) 3251 continue; 3252 } 3253 // look for afm if necessary 3254 OUString aAfmCopied; 3255 FileBase::RC nError; 3256 if( aFrom.getExtension().equalsIgnoreAsciiCaseAscii( "pfa" ) || 3257 aFrom.getExtension().equalsIgnoreAsciiCaseAscii( "pfb" ) ) 3258 { 3259 INetURLObject aFromAfm( aFrom ); 3260 aFromAfm.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) ); 3261 if( access( ByteString( String(aFromAfm.PathToFileName()), aEncoding ).GetBuffer(), F_OK ) ) 3262 { 3263 aFromAfm.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AFM" ) ) ); 3264 if( access( ByteString( String(aFromAfm.PathToFileName()), aEncoding ).GetBuffer(), F_OK ) ) 3265 { 3266 aFromAfm.removeSegment(); 3267 aFromAfm.Append( String( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) ); 3268 aFromAfm.Append( aTo.GetName() ); 3269 aFromAfm.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) ); 3270 if( access( ByteString( String(aFromAfm.PathToFileName()), aEncoding ).GetBuffer(), F_OK ) ) 3271 { 3272 aFromAfm.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AFM" ) ) ); 3273 if( access( ByteString( String(aFromAfm.PathToFileName()), aEncoding ).GetBuffer(), F_OK ) ) 3274 { 3275 // give up 3276 if( pCallback ) 3277 pCallback->importFontFailed( aTo.PathToFileName(), ImportFontCallback::NoAfmMetric ); 3278 continue; 3279 } 3280 } 3281 } 3282 } 3283 INetURLObject aToAfm( aTo ); 3284 aToAfm.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) ); 3285 OUString aFromPath, aToPath; 3286 if( bLinkOnly ) 3287 { 3288 ByteString aLinkFromPath( String(aFromAfm.PathToFileName()), 3289 aEncoding ); 3290 ByteString aLinkToPath( String(aToAfm.PathToFileName()), 3291 aEncoding ); 3292 nError = (FileBase::RC)symlink( aLinkFromPath.GetBuffer(), aLinkToPath.GetBuffer() ); 3293 } 3294 else 3295 nError = File::copy( aFromAfm.GetMainURL(INetURLObject::DECODE_TO_IURI), aToAfm.GetMainURL(INetURLObject::DECODE_TO_IURI) ); 3296 if( nError ) 3297 { 3298 if( pCallback ) 3299 pCallback->importFontFailed( aTo.PathToFileName(), ImportFontCallback::AfmCopyFailed ); 3300 continue; 3301 } 3302 aAfmCopied = aToPath; 3303 } 3304 if( bLinkOnly ) 3305 { 3306 ByteString aFromPath( String(aFrom.PathToFileName()), 3307 aEncoding ); 3308 ByteString aToPath( String(aTo.PathToFileName()), aEncoding ); 3309 nError = (FileBase::RC)symlink( aFromPath.GetBuffer(), 3310 aToPath.GetBuffer() ); 3311 } 3312 else 3313 nError = File::copy( aFrom.GetMainURL(INetURLObject::DECODE_TO_IURI), aTo.GetMainURL(INetURLObject::DECODE_TO_IURI) ); 3314 // copy font file 3315 if( nError ) 3316 { 3317 if( aAfmCopied.getLength() ) 3318 File::remove( aAfmCopied ); 3319 if( pCallback ) 3320 pCallback->importFontFailed( aTo.PathToFileName(), ImportFontCallback::FontCopyFailed ); 3321 continue; 3322 } 3323 3324 ::std::list< PrintFont* > aNewFonts; 3325 ::std::list< PrintFont* >::iterator it; 3326 if( analyzeFontFile( nDirID, OUStringToOString( aTo.GetName(), aEncoding ), ::std::list<OString>(), aNewFonts ) ) 3327 { 3328 // remove all fonts for the same file 3329 // discarding their font ids 3330 ::std::hash_map< fontID, PrintFont* >::iterator current, next; 3331 current = m_aFonts.begin(); 3332 OString aFileName( OUStringToOString( aTo.GetName(), aEncoding ) ); 3333 while( current != m_aFonts.end() ) 3334 { 3335 bool bRemove = false; 3336 switch( current->second->m_eType ) 3337 { 3338 case fonttype::Type1: 3339 if( static_cast<Type1FontFile*>(current->second)->m_aFontFile == aFileName ) 3340 bRemove = true; 3341 break; 3342 case fonttype::TrueType: 3343 if( static_cast<TrueTypeFontFile*>(current->second)->m_aFontFile == aFileName ) 3344 bRemove = true; 3345 break; 3346 default: break; 3347 } 3348 if( bRemove ) 3349 { 3350 next = current; 3351 ++next; 3352 m_aFontFileToFontID[ aFileName ].erase( current->first ); 3353 delete current->second; 3354 m_aFonts.erase( current ); 3355 current = next; 3356 } 3357 else 3358 ++current; 3359 } 3360 3361 DBG_ASSERT( !findFontFileID( nDirID, aFileName ), "not all fonts removed for file" ); 3362 3363 nSuccess++; 3364 for( it = aNewFonts.begin(); it != aNewFonts.end(); ++it ) 3365 { 3366 m_aFontFileToFontID[ aFileName ].insert( m_nNextFontID ); 3367 m_aFonts[ m_nNextFontID++ ] = *it; 3368 m_pFontCache->updateFontCacheEntry( *it, false ); 3369 } 3370 } 3371 } 3372 3373 m_pFontCache->updateDirTimestamp( nDirID ); 3374 m_pFontCache->flush(); 3375 } 3376 else if( pCallback ) 3377 pCallback->importFontsFailed( ImportFontCallback::NoWritableDirectory ); 3378 3379 return nSuccess; 3380 } 3381 3382 // ------------------------------------------------------------------------- 3383 3384 bool PrintFontManager::checkImportPossible() const 3385 { 3386 bool bSuccess = false; 3387 3388 // find a directory with write access 3389 ByteString aDir; 3390 for( std::list< int >::const_iterator dir_it = m_aPrivateFontDirectories.begin(); 3391 dir_it != m_aPrivateFontDirectories.end(); ++dir_it ) 3392 { 3393 aDir = getDirectory( *dir_it ); 3394 if( createWriteablePath( aDir ) ) 3395 { 3396 bSuccess = true; 3397 break; 3398 } 3399 } 3400 3401 #if OSL_DEBUG_LEVEL > 1 3402 if( bSuccess ) 3403 fprintf( stderr, "found writable %s\n", aDir.GetBuffer() ); 3404 #endif 3405 3406 return bSuccess; 3407 } 3408 3409 // ------------------------------------------------------------------------- 3410 3411 bool PrintFontManager::checkChangeFontPropertiesPossible( fontID /*nFontID*/ ) const 3412 { 3413 // since font properties are changed in the font cache file only nowadays 3414 // they can always be changed 3415 return true; 3416 } 3417 3418 // ------------------------------------------------------------------------- 3419 3420 bool PrintFontManager::changeFontProperties( fontID nFontID, const ::rtl::OUString& rXLFD ) 3421 { 3422 ByteString aXLFD( OUStringToOString( rXLFD, RTL_TEXTENCODING_UTF8 ) ); 3423 ByteString aAddStyle = aXLFD.GetToken( '-', 6 ); 3424 if( aAddStyle.Search( "utf8" ) == STRING_NOTFOUND ) 3425 { 3426 aAddStyle.Append( aAddStyle.Len() ? ";utf8" : "utf8" ); 3427 aXLFD.SetToken( 6, ';', aAddStyle ); 3428 } 3429 PrintFont* pFont = getFont( nFontID ); 3430 std::list< OString > aDummyList; 3431 aDummyList.push_back( aXLFD ); 3432 getFontAttributesFromXLFD( pFont, aDummyList ); 3433 pFont->m_bUserOverride = true; 3434 m_pFontCache->updateFontCacheEntry( pFont, true ); 3435 3436 return true; 3437 } 3438 3439 // ------------------------------------------------------------------------- 3440 3441 bool PrintFontManager:: 3442 getImportableFontProperties( 3443 const OString& rFile, 3444 ::std::list< FastPrintFontInfo >& rFontProps 3445 ) 3446 { 3447 rFontProps.clear(); 3448 int nIndex = rFile.lastIndexOf( '/' ); 3449 OString aDir, aFile( rFile.copy( nIndex+1 ) ); 3450 if( nIndex != -1 ) 3451 aDir = rFile.copy( 0, nIndex ); 3452 int nDirID = getDirectoryAtom( aDir, true ); 3453 ::std::list< PrintFont* > aFonts; 3454 bool bRet = analyzeFontFile( nDirID, aFile, ::std::list<OString>(), aFonts ); 3455 while( aFonts.begin() != aFonts.end() ) 3456 { 3457 PrintFont* pFont = aFonts.front(); 3458 aFonts.pop_front(); 3459 FastPrintFontInfo aInfo; 3460 fillPrintFontInfo( pFont, aInfo ); 3461 rFontProps.push_back( aInfo ); 3462 delete pFont; 3463 } 3464 return bRet; 3465 } 3466 3467 // ------------------------------------------------------------------------- 3468 3469 bool PrintFontManager::getFileDuplicates( fontID nFont, ::std::list< fontID >& rFonts ) const 3470 { 3471 bool bRet = false; 3472 3473 rFonts.clear(); 3474 3475 PrintFont* pSearchFont = getFont( nFont ); 3476 if( ! pSearchFont || 3477 pSearchFont->m_eType != fonttype::TrueType || 3478 static_cast<TrueTypeFontFile*>(pSearchFont)->m_nCollectionEntry == -1 3479 ) 3480 return false; 3481 3482 OString aFile( getFontFileSysPath( nFont ) ); 3483 if( ! aFile.getLength() ) 3484 return false; 3485 3486 for( ::std::hash_map< fontID, PrintFont* >::const_iterator it = m_aFonts.begin(); it != m_aFonts.end(); ++it ) 3487 { 3488 if( nFont != it->first ) 3489 { 3490 OString aCompFile( getFontFile( it->second ) ); 3491 if( aCompFile == aFile ) 3492 { 3493 rFonts.push_back( it->first ); 3494 bRet = true; 3495 } 3496 } 3497 } 3498 return bRet; 3499 } 3500 3501 // ------------------------------------------------------------------------- 3502 3503 bool PrintFontManager::removeFonts( const ::std::list< fontID >& rFonts ) 3504 { 3505 bool bRet = true; 3506 ::std::list< fontID > aDuplicates; 3507 for( ::std::list< fontID >::const_iterator it = rFonts.begin(); it != rFonts.end(); ++it ) 3508 { 3509 ::std::hash_map< fontID, PrintFont* >::const_iterator haveFont = m_aFonts.find( *it ); 3510 if( haveFont == m_aFonts.end() ) 3511 continue; 3512 3513 PrintFont* pFont = haveFont->second; 3514 bool bRemoveDuplicates = getFileDuplicates( *it, aDuplicates ); 3515 ByteString aFile( getFontFile( pFont ) ); 3516 if( aFile.Len() ) 3517 { 3518 #if OSL_DEBUG_LEVEL > 1 3519 fprintf( stderr, "try unlink( \"%s\" ) ... ", aFile.GetBuffer() ); 3520 #endif 3521 if( unlink( aFile.GetBuffer() ) ) 3522 { 3523 bRet = false; 3524 #if OSL_DEBUG_LEVEL > 1 3525 fprintf( stderr, "failed\n" ); 3526 #endif 3527 continue; 3528 } 3529 #if OSL_DEBUG_LEVEL > 1 3530 fprintf( stderr, "succeeded\n" ); 3531 #endif 3532 OString aAfm( getAfmFile( pFont ) ); 3533 if( aAfm.getLength() ) 3534 { 3535 #if OSL_DEBUG_LEVEL > 1 3536 fprintf( stderr, "unlink( \"%s\" )\n", aAfm.getStr() ); 3537 #endif 3538 unlink( aAfm.getStr() ); 3539 } 3540 m_aFonts.erase( *it ); 3541 delete pFont; 3542 if( bRemoveDuplicates ) 3543 { 3544 for( ::std::list< fontID >::iterator dup = aDuplicates.begin(); dup != aDuplicates.end(); ++dup ) 3545 { 3546 m_aFontFileToFontID[ aFile ].erase( *dup ); 3547 PrintFont* pDup = m_aFonts[ *dup ]; 3548 m_aFonts.erase( *dup ); 3549 delete pDup; 3550 } 3551 } 3552 } 3553 } 3554 return bRet; 3555 } 3556 3557 // ------------------------------------------------------------------------- 3558 3559 bool PrintFontManager::isPrivateFontFile( fontID nFont ) const 3560 { 3561 bool bRet = false; 3562 int nDirID = -1; 3563 PrintFont* pFont = getFont( nFont ); 3564 if( pFont ) 3565 { 3566 switch( pFont->m_eType ) 3567 { 3568 case fonttype::Type1: nDirID = static_cast< Type1FontFile* >(pFont)->m_nDirectory;break; 3569 case fonttype::TrueType: nDirID = static_cast< TrueTypeFontFile* >(pFont)->m_nDirectory;break; 3570 default: break; 3571 } 3572 } 3573 if( nDirID != -1 ) 3574 { 3575 for( ::std::list< int >::const_iterator it = m_aPrivateFontDirectories.begin(); it != m_aPrivateFontDirectories.end(); ++it ) 3576 { 3577 if( nDirID == *it ) 3578 { 3579 bRet = true; 3580 break; 3581 } 3582 } 3583 } 3584 return bRet; 3585 } 3586 3587 // ------------------------------------------------------------------------- 3588 3589 bool PrintFontManager::getAlternativeFamilyNames( fontID nFont, ::std::list< OUString >& rNames ) const 3590 { 3591 rNames.clear(); 3592 3593 PrintFont* pFont = getFont( nFont ); 3594 if( pFont && pFont->m_eType == fonttype::TrueType ) 3595 { 3596 TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont); 3597 ByteString aFile( getFontFile( pFont ) ); 3598 TrueTypeFont* pTTFont; 3599 if( OpenTTFontFile( aFile.GetBuffer(), pTTFontFile->m_nCollectionEntry < 0 ? 0 : pTTFontFile->m_nCollectionEntry, &pTTFont ) == SF_OK ) 3600 { 3601 NameRecord* pNameRecords = NULL; 3602 int nNameRecords = GetTTNameRecords( pTTFont, &pNameRecords ); 3603 for( int i = 0; i < nNameRecords; i++ ) 3604 { 3605 if( pNameRecords[i].nameID != 1 ) // family name 3606 continue; 3607 3608 OUString aFamily( convertTrueTypeName( pNameRecords+i ) ); 3609 if( aFamily.getLength() 3610 && 3611 m_pAtoms->getAtom( ATOM_FAMILYNAME, aFamily, sal_True ) != pFont->m_nFamilyName 3612 ) 3613 { 3614 rNames.push_back( aFamily ); 3615 } 3616 } 3617 3618 if( nNameRecords ) 3619 DisposeNameRecords( pNameRecords, nNameRecords ); 3620 CloseTTFont( pTTFont ); 3621 } 3622 } 3623 return rNames.begin() != rNames.end(); 3624 } 3625 3626 // ------------------------------------------------------------------------- 3627 3628 // TODO: move most of this stuff into the central font-subsetting code 3629 bool PrintFontManager::createFontSubset( 3630 FontSubsetInfo& rInfo, 3631 fontID nFont, 3632 const OUString& rOutFile, 3633 sal_Int32* pGlyphIDs, 3634 sal_uInt8* pNewEncoding, 3635 sal_Int32* pWidths, 3636 int nGlyphs, 3637 bool bVertical 3638 ) 3639 { 3640 PrintFont* pFont = getFont( nFont ); 3641 if( !pFont ) 3642 return false; 3643 3644 switch( pFont->m_eType ) 3645 { 3646 case psp::fonttype::TrueType: rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; break; 3647 case psp::fonttype::Type1: rInfo.m_nFontType = FontSubsetInfo::ANY_TYPE1; break; 3648 default: 3649 return false; 3650 } 3651 // TODO: remove when Type1 subsetting gets implemented 3652 if( pFont->m_eType != fonttype::TrueType ) 3653 return false; 3654 3655 // reshuffle array of requested glyphs to make sure glyph0==notdef 3656 sal_uInt8 pEnc[256]; 3657 sal_uInt16 pGID[256]; 3658 sal_uInt8 pOldIndex[256]; 3659 memset( pEnc, 0, sizeof( pEnc ) ); 3660 memset( pGID, 0, sizeof( pGID ) ); 3661 memset( pOldIndex, 0, sizeof( pOldIndex ) ); 3662 if( nGlyphs > 256 ) 3663 return false; 3664 int nChar = 1; 3665 for( int i = 0; i < nGlyphs; i++ ) 3666 { 3667 if( pNewEncoding[i] == 0 ) 3668 { 3669 pOldIndex[ 0 ] = i; 3670 } 3671 else 3672 { 3673 DBG_ASSERT( !(pGlyphIDs[i] & 0x007f0000), "overlong glyph id" ); 3674 DBG_ASSERT( (int)pNewEncoding[i] < nGlyphs, "encoding wrong" ); 3675 DBG_ASSERT( pEnc[pNewEncoding[i]] == 0 && pGID[pNewEncoding[i]] == 0, "duplicate encoded glyph" ); 3676 pEnc[ pNewEncoding[i] ] = pNewEncoding[i]; 3677 pGID[ pNewEncoding[i] ] = (sal_uInt16)pGlyphIDs[ i ]; 3678 pOldIndex[ pNewEncoding[i] ] = i; 3679 nChar++; 3680 } 3681 } 3682 nGlyphs = nChar; // either input value or increased by one 3683 3684 // prepare system name for read access for subset source file 3685 // TODO: since this file is usually already mmapped there is no need to open it again 3686 const ByteString aFromFile = getFontFile( pFont ); 3687 3688 TrueTypeFont* pTTFont = NULL; // TODO: rename to SfntFont 3689 TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont); 3690 if( OpenTTFontFile( aFromFile.GetBuffer(), pTTFontFile->m_nCollectionEntry < 0 ? 0 : pTTFontFile->m_nCollectionEntry, &pTTFont ) != SF_OK ) 3691 return false; 3692 3693 // prepare system name for write access for subset file target 3694 OUString aSysPath; 3695 if( osl_File_E_None != osl_getSystemPathFromFileURL( rOutFile.pData, &aSysPath.pData ) ) 3696 return false; 3697 const rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); 3698 const ByteString aToFile( OUStringToOString( aSysPath, aEncoding ) ); 3699 3700 // do CFF subsetting if possible 3701 int nCffLength = 0; 3702 const sal_uInt8* pCffBytes = NULL; 3703 if( GetSfntTable( pTTFont, O_CFF, &pCffBytes, &nCffLength ) ) 3704 { 3705 rInfo.LoadFont( FontSubsetInfo::CFF_FONT, pCffBytes, nCffLength ); 3706 #if 1 // TODO: remove 16bit->long conversion when related methods handle non-16bit glyphids 3707 long aRequestedGlyphs[256]; 3708 for( int i = 0; i < nGlyphs; ++i ) 3709 aRequestedGlyphs[i] = pGID[i]; 3710 #endif 3711 // create subset file at requested path 3712 FILE* pOutFile = fopen( aToFile.GetBuffer(), "wb" ); 3713 // create font subset 3714 const char* pGlyphSetName = NULL; // TODO: better name? 3715 const bool bOK = rInfo.CreateFontSubset( 3716 FontSubsetInfo::TYPE1_PFB, 3717 pOutFile, pGlyphSetName, 3718 aRequestedGlyphs, pEnc, nGlyphs, pWidths ); 3719 fclose( pOutFile ); 3720 // cleanup before early return 3721 CloseTTFont( pTTFont ); 3722 return bOK; 3723 } 3724 3725 // do TTF->Type42 or Type3 subsetting 3726 // fill in font info 3727 psp::PrintFontInfo aFontInfo; 3728 if( ! getFontInfo( nFont, aFontInfo ) ) 3729 return false; 3730 3731 rInfo.m_nAscent = aFontInfo.m_nAscend; 3732 rInfo.m_nDescent = aFontInfo.m_nDescend; 3733 rInfo.m_aPSName = getPSName( nFont ); 3734 3735 int xMin, yMin, xMax, yMax; 3736 getFontBoundingBox( nFont, xMin, yMin, xMax, yMax ); 3737 rInfo.m_aFontBBox = Rectangle( Point( xMin, yMin ), Size( xMax-xMin, yMax-yMin ) ); 3738 rInfo.m_nCapHeight = yMax; // Well ... 3739 3740 // fill in glyph advance widths 3741 TTSimpleGlyphMetrics* pMetrics = GetTTSimpleGlyphMetrics( pTTFont, 3742 pGID, 3743 nGlyphs, 3744 bVertical ? 1 : 0 ); 3745 if( pMetrics ) 3746 { 3747 for( int i = 0; i < nGlyphs; i++ ) 3748 pWidths[pOldIndex[i]] = pMetrics[i].adv; 3749 free( pMetrics ); 3750 } 3751 else 3752 { 3753 CloseTTFont( pTTFont ); 3754 return false; 3755 } 3756 3757 bool bSuccess = ( SF_OK == CreateTTFromTTGlyphs( pTTFont, 3758 aToFile.GetBuffer(), 3759 pGID, 3760 pEnc, 3761 nGlyphs, 3762 0, 3763 NULL, 3764 0 ) ); 3765 CloseTTFont( pTTFont ); 3766 3767 return bSuccess; 3768 } 3769 3770 void PrintFontManager::getGlyphWidths( fontID nFont, 3771 bool bVertical, 3772 std::vector< sal_Int32 >& rWidths, 3773 std::map< sal_Unicode, sal_uInt32 >& rUnicodeEnc ) 3774 { 3775 PrintFont* pFont = getFont( nFont ); 3776 if( !pFont || 3777 (pFont->m_eType != fonttype::TrueType && pFont->m_eType != fonttype::Type1) ) 3778 return; 3779 if( pFont->m_eType == fonttype::TrueType ) 3780 { 3781 TrueTypeFont* pTTFont = NULL; 3782 TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont); 3783 ByteString aFromFile = getFontFile( pFont ); 3784 if( OpenTTFontFile( aFromFile.GetBuffer(), pTTFontFile->m_nCollectionEntry < 0 ? 0 : pTTFontFile->m_nCollectionEntry, &pTTFont ) != SF_OK ) 3785 return; 3786 int nGlyphs = GetTTGlyphCount( pTTFont ); 3787 if( nGlyphs > 0 ) 3788 { 3789 rWidths.resize(nGlyphs); 3790 std::vector<sal_uInt16> aGlyphIds(nGlyphs); 3791 for( int i = 0; i < nGlyphs; i++ ) 3792 aGlyphIds[i] = sal_uInt16(i); 3793 TTSimpleGlyphMetrics* pMetrics = GetTTSimpleGlyphMetrics( pTTFont, 3794 &aGlyphIds[0], 3795 nGlyphs, 3796 bVertical ? 1 : 0 ); 3797 if( pMetrics ) 3798 { 3799 for( int i = 0; i< nGlyphs; i++ ) 3800 rWidths[i] = pMetrics[i].adv; 3801 free( pMetrics ); 3802 rUnicodeEnc.clear(); 3803 } 3804 3805 // fill the unicode map 3806 // TODO: isn't this map already available elsewhere in the fontmanager? 3807 const sal_uInt8* pCmapData = NULL; 3808 int nCmapSize = 0; 3809 if( GetSfntTable( pTTFont, O_cmap, &pCmapData, &nCmapSize ) ) 3810 { 3811 CmapResult aCmapResult; 3812 if( ParseCMAP( pCmapData, nCmapSize, aCmapResult ) ) 3813 { 3814 const ImplFontCharMap aCharMap( aCmapResult ); 3815 for( sal_uInt32 cOld = 0;;) 3816 { 3817 // get next unicode covered by font 3818 const sal_uInt32 c = aCharMap.GetNextChar( cOld ); 3819 if( c == cOld ) 3820 break; 3821 cOld = c; 3822 #if 1 // TODO: remove when sal_Unicode covers all of unicode 3823 if( c > (sal_Unicode)~0 ) 3824 break; 3825 #endif 3826 // get the matching glyph index 3827 const sal_uInt32 nGlyphId = aCharMap.GetGlyphIndex( c ); 3828 // update the requested map 3829 rUnicodeEnc[ (sal_Unicode)c ] = nGlyphId; 3830 } 3831 } 3832 } 3833 } 3834 CloseTTFont( pTTFont ); 3835 } 3836 else if( pFont->m_eType == fonttype::Type1 ) 3837 { 3838 if( ! pFont->m_aEncodingVector.size() ) 3839 pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, true, true ); 3840 if( pFont->m_pMetrics ) 3841 { 3842 rUnicodeEnc.clear(); 3843 rWidths.clear(); 3844 rWidths.reserve( pFont->m_pMetrics->m_aMetrics.size() ); 3845 for( std::hash_map< int, CharacterMetric >::const_iterator it = 3846 pFont->m_pMetrics->m_aMetrics.begin(); 3847 it != pFont->m_pMetrics->m_aMetrics.end(); ++it ) 3848 { 3849 if( (it->first & 0x00010000) == 0 || bVertical ) 3850 { 3851 rUnicodeEnc[ sal_Unicode(it->first & 0x0000ffff) ] = sal_uInt32(rWidths.size()); 3852 rWidths.push_back( it->second.width ); 3853 } 3854 } 3855 } 3856 } 3857 } 3858 3859 // ------------------------------------------------------------------------- 3860 3861 const std::map< sal_Unicode, sal_Int32 >* PrintFontManager::getEncodingMap( fontID nFont, const std::map< sal_Unicode, rtl::OString >** pNonEncoded ) const 3862 { 3863 PrintFont* pFont = getFont( nFont ); 3864 if( !pFont || 3865 (pFont->m_eType != fonttype::Type1 && pFont->m_eType != fonttype::Builtin) 3866 ) 3867 return NULL; 3868 3869 if( ! pFont->m_aEncodingVector.size() ) 3870 pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, true, true ); 3871 3872 if( pNonEncoded ) 3873 *pNonEncoded = pFont->m_aNonEncoded.size() ? &pFont->m_aNonEncoded : NULL; 3874 3875 return pFont->m_aEncodingVector.size() ? &pFont->m_aEncodingVector : NULL; 3876 } 3877 3878 // ------------------------------------------------------------------------- 3879 3880 std::list< OString > PrintFontManager::getAdobeNameFromUnicode( sal_Unicode aChar ) const 3881 { 3882 std::pair< std::hash_multimap< sal_Unicode, rtl::OString >::const_iterator, 3883 std::hash_multimap< sal_Unicode, rtl::OString >::const_iterator > range 3884 = m_aUnicodeToAdobename.equal_range( aChar ); 3885 3886 std::list< OString > aRet; 3887 for( ; range.first != range.second; ++range.first ) 3888 aRet.push_back( range.first->second ); 3889 3890 if( aRet.begin() == aRet.end() && aChar != 0 ) 3891 { 3892 sal_Char aBuf[8]; 3893 sal_Int32 nChars = snprintf( (char*)aBuf, sizeof( aBuf ), "uni%.4hX", aChar ); 3894 aRet.push_back( OString( aBuf, nChars ) ); 3895 } 3896 3897 return aRet; 3898 } 3899 3900 // ------------------------------------------------------------------------- 3901 std::list< sal_Unicode > PrintFontManager::getUnicodeFromAdobeName( const rtl::OString& rName ) const 3902 { 3903 std::pair< std::hash_multimap< rtl::OString, sal_Unicode, rtl::OStringHash >::const_iterator, 3904 std::hash_multimap< rtl::OString, sal_Unicode, rtl::OStringHash >::const_iterator > range 3905 = m_aAdobenameToUnicode.equal_range( rName ); 3906 3907 std::list< sal_Unicode > aRet; 3908 for( ; range.first != range.second; ++range.first ) 3909 aRet.push_back( range.first->second ); 3910 3911 if( aRet.begin() == aRet.end() ) 3912 { 3913 if( rName.getLength() == 7 && rName.indexOf( "uni" ) == 0 ) 3914 { 3915 sal_Unicode aCode = (sal_Unicode)rName.copy( 3 ).toInt32( 16 ); 3916 aRet.push_back( aCode ); 3917 } 3918 } 3919 3920 return aRet; 3921 } 3922 3923 // ------------------------------------------------------------------------- 3924 namespace 3925 { 3926 OUString getString( const Any& rAny ) 3927 { 3928 OUString aStr; 3929 rAny >>= aStr; 3930 return aStr; 3931 } 3932 bool getBool( const Any& rAny ) 3933 { 3934 sal_Bool bBool = sal_False; 3935 rAny >>= bBool; 3936 return static_cast<bool>(bBool); 3937 } 3938 sal_Int32 getInt( const Any& rAny ) 3939 { 3940 sal_Int32 n = 0; 3941 rAny >>= n; 3942 return n; 3943 } 3944 } 3945 bool PrintFontManager::readOverrideMetrics() 3946 { 3947 if( ! m_aOverrideFonts.empty() ) 3948 return false; 3949 3950 css::uno::Reference< XMultiServiceFactory > xFact( comphelper::getProcessServiceFactory() ); 3951 if( !xFact.is() ) 3952 return false; 3953 css::uno::Reference< XMaterialHolder > xMat( 3954 xFact->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.psprint.CompatMetricOverride" ) ) ), 3955 UNO_QUERY ); 3956 if( !xMat.is() ) 3957 return false; 3958 3959 Any aAny( xMat->getMaterial() ); 3960 Sequence< Any > aOverrideFonts; 3961 if( ! (aAny >>= aOverrideFonts ) ) 3962 return false; 3963 sal_Int32 nFonts = aOverrideFonts.getLength(); 3964 for( sal_Int32 i = 0; i < nFonts; i++ ) 3965 { 3966 Sequence< NamedValue > aMetrics; 3967 if( ! (aOverrideFonts.getConstArray()[i] >>= aMetrics) ) 3968 continue; 3969 BuiltinFont* pFont = new BuiltinFont(); 3970 pFont->m_nDirectory = 0; 3971 pFont->m_bUserOverride = false; 3972 pFont->m_pMetrics = new PrintFontMetrics; 3973 memset( pFont->m_pMetrics->m_aPages, 0xff, sizeof( pFont->m_pMetrics->m_aPages ) ); 3974 pFont->m_pMetrics->m_bKernPairsQueried = true; 3975 sal_Int32 nProps = aMetrics.getLength(); 3976 const NamedValue* pProps = aMetrics.getConstArray(); 3977 for( sal_Int32 n = 0; n < nProps; n++ ) 3978 { 3979 if( pProps[n].Name.equalsAscii( "FamilyName" ) ) 3980 pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, 3981 getString(pProps[n].Value), 3982 sal_True ); 3983 else if( pProps[n].Name.equalsAscii( "PSName" ) ) 3984 pFont->m_nPSName = m_pAtoms->getAtom( ATOM_PSNAME, 3985 getString(pProps[n].Value), 3986 sal_True ); 3987 else if( pProps[n].Name.equalsAscii( "StyleName" ) ) 3988 pFont->m_aStyleName = getString(pProps[n].Value); 3989 else if( pProps[n].Name.equalsAscii( "Italic" ) ) 3990 pFont->m_eItalic = static_cast<italic::type>(getInt(pProps[n].Value)); 3991 else if( pProps[n].Name.equalsAscii( "Width" ) ) 3992 pFont->m_eWidth = static_cast<width::type>(getInt(pProps[n].Value)); 3993 else if( pProps[n].Name.equalsAscii( "Weight" ) ) 3994 pFont->m_eWeight = static_cast<weight::type>(getInt(pProps[n].Value)); 3995 else if( pProps[n].Name.equalsAscii( "Pitch" ) ) 3996 pFont->m_ePitch = static_cast<pitch::type>(getInt(pProps[n].Value)); 3997 else if( pProps[n].Name.equalsAscii( "Encoding" ) ) 3998 pFont->m_aEncoding = static_cast<rtl_TextEncoding>(getInt(pProps[n].Value)); 3999 else if( pProps[n].Name.equalsAscii( "FontEncodingOnly" ) ) 4000 pFont->m_bFontEncodingOnly = getBool(pProps[n].Value); 4001 else if( pProps[n].Name.equalsAscii( "GlobalMetricXWidth" ) ) 4002 pFont->m_aGlobalMetricX.width = getInt(pProps[n].Value); 4003 else if( pProps[n].Name.equalsAscii( "GlobalMetricXHeight" ) ) 4004 pFont->m_aGlobalMetricX.height = getInt(pProps[n].Value); 4005 else if( pProps[n].Name.equalsAscii( "GlobalMetricYWidth" ) ) 4006 pFont->m_aGlobalMetricY.width = getInt(pProps[n].Value); 4007 else if( pProps[n].Name.equalsAscii( "GlobalMetricYHeight" ) ) 4008 pFont->m_aGlobalMetricY.height = getInt(pProps[n].Value); 4009 else if( pProps[n].Name.equalsAscii( "Ascend" ) ) 4010 pFont->m_nAscend = getInt(pProps[n].Value); 4011 else if( pProps[n].Name.equalsAscii( "Descend" ) ) 4012 pFont->m_nDescend = getInt(pProps[n].Value); 4013 else if( pProps[n].Name.equalsAscii( "Leading" ) ) 4014 pFont->m_nLeading = getInt(pProps[n].Value); 4015 else if( pProps[n].Name.equalsAscii( "XMin" ) ) 4016 pFont->m_nXMin = getInt(pProps[n].Value); 4017 else if( pProps[n].Name.equalsAscii( "YMin" ) ) 4018 pFont->m_nYMin = getInt(pProps[n].Value); 4019 else if( pProps[n].Name.equalsAscii( "XMax" ) ) 4020 pFont->m_nXMax = getInt(pProps[n].Value); 4021 else if( pProps[n].Name.equalsAscii( "YMax" ) ) 4022 pFont->m_nYMax = getInt(pProps[n].Value); 4023 else if( pProps[n].Name.equalsAscii( "VerticalSubstitutes" ) ) 4024 pFont->m_bHaveVerticalSubstitutedGlyphs = getBool(pProps[n].Value); 4025 else if( pProps[n].Name.equalsAscii( "EncodingVector" ) ) 4026 { 4027 Sequence< NamedValue > aEncoding; 4028 pProps[n].Value >>= aEncoding; 4029 sal_Int32 nEnc = aEncoding.getLength(); 4030 const NamedValue* pEnc = aEncoding.getConstArray(); 4031 for( sal_Int32 m = 0; m < nEnc; m++ ) 4032 { 4033 sal_Unicode cCode = *pEnc[m].Name.getStr(); 4034 sal_Int32 nGlyph = getInt(pEnc[m].Value); 4035 pFont->m_aEncodingVector[ cCode ] = nGlyph; 4036 } 4037 } 4038 else if( pProps[n].Name.equalsAscii( "NonEncoded" ) ) 4039 { 4040 Sequence< NamedValue > aEncoding; 4041 pProps[n].Value >>= aEncoding; 4042 sal_Int32 nEnc = aEncoding.getLength(); 4043 const NamedValue* pEnc = aEncoding.getConstArray(); 4044 for( sal_Int32 m = 0; m < nEnc; m++ ) 4045 { 4046 sal_Unicode cCode = *pEnc[m].Name.getStr(); 4047 OUString aGlyphName( getString(pEnc[m].Value) ); 4048 pFont->m_aNonEncoded[ cCode ] = OUStringToOString(aGlyphName,RTL_TEXTENCODING_ASCII_US); 4049 } 4050 } 4051 else if( pProps[n].Name.equalsAscii( "CharacterMetrics" ) ) 4052 { 4053 // fill pFont->m_pMetrics->m_aMetrics 4054 // expect triples of int: int -> CharacterMetric.{ width, height } 4055 Sequence< sal_Int32 > aSeq; 4056 pProps[n].Value >>= aSeq; 4057 sal_Int32 nInts = aSeq.getLength(); 4058 const sal_Int32* pInts = aSeq.getConstArray(); 4059 for( sal_Int32 m = 0; m < nInts; m+=3 ) 4060 { 4061 pFont->m_pMetrics->m_aMetrics[ pInts[m] ].width = static_cast<short int>(pInts[m+1]); 4062 pFont->m_pMetrics->m_aMetrics[ pInts[m] ].height = static_cast<short int>(pInts[m+2]); 4063 } 4064 } 4065 else if( pProps[n].Name.equalsAscii( "XKernPairs" ) ) 4066 { 4067 // fill pFont->m_pMetrics->m_aXKernPairs 4068 // expection name: <unicode1><unicode2> value: ((height << 16)| width) 4069 Sequence< NamedValue > aKern; 4070 pProps[n].Value >>= aKern; 4071 KernPair aPair; 4072 const NamedValue* pVals = aKern.getConstArray(); 4073 int nPairs = aKern.getLength(); 4074 for( int m = 0; m < nPairs; m++ ) 4075 { 4076 if( pVals[m].Name.getLength() == 2 ) 4077 { 4078 aPair.first = pVals[m].Name.getStr()[0]; 4079 aPair.second = pVals[m].Name.getStr()[1]; 4080 sal_Int32 nKern = getInt( pVals[m].Value ); 4081 aPair.kern_x = static_cast<short int>(nKern & 0xffff); 4082 aPair.kern_y = static_cast<short int>((sal_uInt32(nKern) >> 16) & 0xffff); 4083 pFont->m_pMetrics->m_aXKernPairs.push_back( aPair ); 4084 } 4085 } 4086 } 4087 } 4088 // sanity check 4089 if( pFont->m_nPSName && 4090 pFont->m_nFamilyName && 4091 ! pFont->m_pMetrics->m_aMetrics.empty() ) 4092 { 4093 m_aOverrideFonts.push_back( m_nNextFontID ); 4094 m_aFonts[ m_nNextFontID++ ] = pFont; 4095 } 4096 else 4097 { 4098 DBG_ASSERT( 0, "override font failed" ); 4099 delete pFont; 4100 } 4101 } 4102 4103 return true; 4104 } 4105