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