1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 31 #include <cstdlib> 32 #include <cstring> 33 34 #include "fontcache.hxx" 35 36 #include "osl/thread.h" 37 38 #include "unotools/atom.hxx" 39 40 #include "tools/stream.hxx" 41 42 #include <unistd.h> 43 #include <sys/stat.h> 44 45 #if OSL_DEBUG_LEVEL >1 46 #include <cstdio> 47 #endif 48 49 #define FONTCACHEFILE "/user/psprint/pspfontcache" 50 #define CACHE_MAGIC "PspFontCacheFile format 4" 51 52 using namespace std; 53 using namespace rtl; 54 using namespace psp; 55 using namespace utl; 56 57 /* 58 * static helpers 59 */ 60 61 /* 62 * FontCache constructor 63 */ 64 65 FontCache::FontCache() 66 { 67 m_bDoFlush = false; 68 m_aCacheFile = getOfficePath( UserPath ); 69 if( m_aCacheFile.Len() ) 70 { 71 m_aCacheFile.AppendAscii( FONTCACHEFILE ); 72 read(); 73 } 74 } 75 76 /* 77 * FontCache destructor 78 */ 79 80 FontCache::~FontCache() 81 { 82 clearCache(); 83 } 84 85 /* 86 * FontCache::clearCache 87 */ 88 void FontCache::clearCache() 89 { 90 for( FontCacheData::iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++dir_it ) 91 { 92 for( FontDirMap::iterator entry_it = dir_it->second.m_aEntries.begin(); entry_it != dir_it->second.m_aEntries.end(); ++entry_it ) 93 { 94 for( FontCacheEntry::iterator font_it = entry_it->second.m_aEntry.begin(); font_it != entry_it->second.m_aEntry.end(); ++font_it ) 95 delete *font_it; 96 } 97 } 98 m_aCache.clear(); 99 } 100 101 /* 102 * FontCache::Commit 103 */ 104 105 void FontCache::flush() 106 { 107 if( ! m_bDoFlush || ! m_aCacheFile.Len() ) 108 return; 109 110 SvFileStream aStream; 111 aStream.Open( m_aCacheFile, STREAM_WRITE | STREAM_TRUNC ); 112 if( ! (aStream.IsOpen() && aStream.IsWritable()) ) 113 { 114 #if OSL_DEBUG_LEVEL > 1 115 fprintf( stderr, "FontCache::flush: opening cache file %s failed\n", ByteString( m_aCacheFile, osl_getThreadTextEncoding() ).GetBuffer() ); 116 #endif 117 return; 118 } 119 120 aStream.SetLineDelimiter( LINEEND_LF ); 121 aStream.WriteLine( ByteString( CACHE_MAGIC ) ); 122 123 PrintFontManager& rManager( PrintFontManager::get() ); 124 MultiAtomProvider* pAtoms = rManager.m_pAtoms; 125 126 for( FontCacheData::const_iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++ dir_it ) 127 { 128 const FontDirMap& rDir( dir_it->second.m_aEntries ); 129 130 ByteString aDirectory( rManager.getDirectory( dir_it->first ) ); 131 ByteString aLine( "FontCacheDirectory:" ); 132 aLine.Append( ByteString::CreateFromInt64( dir_it->second.m_nTimestamp ) ); 133 aLine.Append( ':' ); 134 aLine.Append( aDirectory ); 135 if( rDir.empty() && dir_it->second.m_bNoFiles ) 136 aLine.Insert( "Empty", 0 ); 137 aStream.WriteLine( aLine ); 138 139 for( FontDirMap::const_iterator entry_it = rDir.begin(); entry_it != rDir.end(); ++entry_it ) 140 { 141 // insert cache entries 142 const FontCacheEntry& rEntry( entry_it->second.m_aEntry ); 143 if( rEntry.begin() == rEntry.end() ) 144 continue; 145 146 aLine = "File:"; 147 aLine.Append( ByteString( entry_it->first ) ); 148 aStream.WriteLine( aLine ); 149 150 int nEntrySize = entry_it->second.m_aEntry.size(); 151 // write: type;nfonts 152 aLine = ByteString::CreateFromInt32( rEntry.front()->m_eType ); 153 aLine.Append( ';' ); 154 aLine.Append( ByteString::CreateFromInt32( nEntrySize ) ); 155 aStream.WriteLine( aLine ); 156 157 sal_Int32 nSubEntry = 0; 158 for( FontCacheEntry::const_iterator it = rEntry.begin(); it != rEntry.end(); ++it, nSubEntry++ ) 159 { 160 /* 161 * for each font entry write: 162 * name[;name[;name]] 163 * fontnr;PSName;italic;weight;width;pitch;encoding;ascend;descend;leading;vsubst;gxw;gxh;gyw;gyh;useroverrride;embed;antialias[;{metricfile,typeflags}][;stylename] 164 */ 165 if( nEntrySize > 1 ) 166 nSubEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nCollectionEntry; 167 else 168 nSubEntry = -1; 169 170 aLine = OUStringToOString( pAtoms->getString( ATOM_FAMILYNAME, (*it)->m_nFamilyName ), RTL_TEXTENCODING_UTF8 ); 171 for( ::std::list< int >::const_iterator name_it = (*it)->m_aAliases.begin(); name_it != (*it)->m_aAliases.end(); ++name_it ) 172 { 173 const OUString& rAdd( pAtoms->getString( ATOM_FAMILYNAME, *name_it ) ); 174 if( rAdd.getLength() ) 175 { 176 aLine.Append( ';' ); 177 aLine.Append( ByteString( String( rAdd ), RTL_TEXTENCODING_UTF8 ) ); 178 } 179 } 180 aStream.WriteLine( aLine ); 181 182 const OUString& rPSName( pAtoms->getString( ATOM_PSNAME, (*it)->m_nPSName ) ); 183 aLine = ByteString::CreateFromInt32( nSubEntry ); 184 aLine.Append( ';' ); 185 aLine.Append( ByteString( String( rPSName ), RTL_TEXTENCODING_UTF8 ) ); 186 aLine.Append( ';' ); 187 aLine.Append( ByteString::CreateFromInt32( (*it)->m_eItalic ) ); 188 aLine.Append( ';' ); 189 aLine.Append( ByteString::CreateFromInt32( (*it)->m_eWeight ) ); 190 aLine.Append( ';' ); 191 aLine.Append( ByteString::CreateFromInt32( (*it)->m_eWidth ) ); 192 aLine.Append( ';' ); 193 aLine.Append( ByteString::CreateFromInt32( (*it)->m_ePitch ) ); 194 aLine.Append( ';' ); 195 aLine.Append( ByteString::CreateFromInt32( (*it)->m_aEncoding ) ); 196 aLine.Append( ';' ); 197 aLine.Append( ByteString::CreateFromInt32( (*it)->m_nAscend ) ); 198 aLine.Append( ';' ); 199 aLine.Append( ByteString::CreateFromInt32( (*it)->m_nDescend ) ); 200 aLine.Append( ';' ); 201 aLine.Append( ByteString::CreateFromInt32( (*it)->m_nLeading ) ); 202 aLine.Append( ';' ); 203 aLine.Append( (*it)->m_bHaveVerticalSubstitutedGlyphs ? "1" : "0" ); 204 aLine.Append( ';' ); 205 aLine.Append( ByteString::CreateFromInt32( (*it)->m_aGlobalMetricX.width ) ); 206 aLine.Append( ';' ); 207 aLine.Append( ByteString::CreateFromInt32( (*it)->m_aGlobalMetricX.height ) ); 208 aLine.Append( ';' ); 209 aLine.Append( ByteString::CreateFromInt32( (*it)->m_aGlobalMetricY.width ) ); 210 aLine.Append( ';' ); 211 aLine.Append( ByteString::CreateFromInt32( (*it)->m_aGlobalMetricY.height ) ); 212 aLine.Append( ';' ); 213 aLine.Append( (*it)->m_bUserOverride ? "1" : "0" ); 214 aLine.Append( ';' ); 215 aLine.Append( ByteString::CreateFromInt32( 0 ) ); 216 aLine.Append( ';' ); 217 aLine.Append( ByteString::CreateFromInt32( 0 ) ); 218 219 switch( (*it)->m_eType ) 220 { 221 case fonttype::Type1: 222 aLine.Append( ';' ); 223 aLine.Append( ByteString( static_cast<const PrintFontManager::Type1FontFile*>(*it)->m_aMetricFile ) ); 224 break; 225 case fonttype::TrueType: 226 aLine.Append( ';' ); 227 aLine.Append( ByteString::CreateFromInt32( static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nTypeFlags ) ); 228 break; 229 default: break; 230 } 231 if( (*it)->m_aStyleName.getLength() ) 232 { 233 aLine.Append( ';' ); 234 aLine.Append( ByteString( String( (*it)->m_aStyleName ), RTL_TEXTENCODING_UTF8 ) ); 235 } 236 aStream.WriteLine( aLine ); 237 } 238 aStream.WriteLine( ByteString() ); 239 } 240 } 241 m_bDoFlush = false; 242 } 243 244 /* 245 * FontCache::read 246 */ 247 248 void FontCache::read() 249 { 250 PrintFontManager& rManager( PrintFontManager::get() ); 251 MultiAtomProvider* pAtoms = rManager.m_pAtoms; 252 253 SvFileStream aStream( m_aCacheFile, STREAM_READ ); 254 if( ! aStream.IsOpen() ) 255 { 256 #if OSL_DEBUG_LEVEL > 1 257 fprintf( stderr, "FontCache::read: opening cache file %s failed\n", ByteString( m_aCacheFile, osl_getThreadTextEncoding() ).GetBuffer() ); 258 #endif 259 return; 260 } 261 262 263 ByteString aLine; 264 aStream.ReadLine( aLine ); 265 if( !aLine.Equals( CACHE_MAGIC ) ) 266 { 267 #if OSL_DEBUG_LEVEL >1 268 fprintf( stderr, "FontCache::read: cache file %s fails magic test\n", ByteString( m_aCacheFile, osl_getThreadTextEncoding() ).GetBuffer() ); 269 #endif 270 return; 271 } 272 273 int nDir = 0; 274 FontDirMap* pDir = NULL; 275 xub_StrLen nIndex; 276 bool bKeepOnlyUserOverridden = false; 277 do 278 { 279 aStream.ReadLine( aLine ); 280 if( aLine.CompareTo( "FontCacheDirectory:", 19 ) == COMPARE_EQUAL || 281 aLine.CompareTo( "EmptyFontCacheDirectory:", 24 ) == COMPARE_EQUAL ) 282 { 283 bool bEmpty = (aLine.CompareTo( "Empty", 5 ) == COMPARE_EQUAL); 284 xub_StrLen nSearchIndex = bEmpty ? 24 : 19; 285 286 OString aDir; 287 sal_Int64 nTimestamp = 0; 288 xub_StrLen nTEnd = aLine.Search( ':', nSearchIndex ); 289 if( nTEnd != STRING_NOTFOUND ) 290 { 291 nTimestamp = aLine.Copy( nSearchIndex, nTEnd - nSearchIndex ).ToInt64(); 292 aDir = aLine.Copy( nTEnd+1 ); 293 } 294 else 295 { 296 // invalid format, remove 297 pDir = NULL; 298 nDir = 0; 299 m_bDoFlush = true; 300 continue; 301 } 302 303 // is the directory modified ? 304 struct stat aStat; 305 if( stat( aDir.getStr(), &aStat ) || 306 ! S_ISDIR(aStat.st_mode) ) 307 { 308 // remove outdated cache data 309 pDir = NULL; 310 nDir = 0; 311 m_bDoFlush = true; 312 continue; 313 } 314 else 315 { 316 nDir = rManager.getDirectoryAtom( aDir, true ); 317 m_aCache[ nDir ].m_nTimestamp = (sal_Int64)aStat.st_mtime; 318 m_aCache[ nDir ].m_bNoFiles = bEmpty; 319 pDir = bEmpty ? NULL : &m_aCache[ nDir ].m_aEntries; 320 bKeepOnlyUserOverridden = ((sal_Int64)aStat.st_mtime != nTimestamp); 321 m_aCache[ nDir ].m_bUserOverrideOnly = bKeepOnlyUserOverridden; 322 } 323 } 324 else if( pDir && aLine.CompareTo( "File:", 5 ) == COMPARE_EQUAL ) 325 { 326 OString aFile( aLine.Copy( 5 ) ); 327 aStream.ReadLine( aLine ); 328 329 const char* pLine = aLine.GetBuffer(); 330 331 fonttype::type eType = (fonttype::type)atoi( pLine ); 332 if( eType != fonttype::TrueType && 333 eType != fonttype::Type1 && 334 eType != fonttype::Builtin 335 ) 336 continue; 337 while( *pLine && *pLine != ';' ) 338 pLine++; 339 if( *pLine != ';' ) 340 continue; 341 342 pLine++; 343 sal_Int32 nFonts = atoi( pLine ); 344 for( int n = 0; n < nFonts; n++ ) 345 { 346 aStream.ReadLine( aLine ); 347 pLine = aLine.GetBuffer(); 348 int nLen = aLine.Len(); 349 350 PrintFontManager::PrintFont* pFont = NULL; 351 switch( eType ) 352 { 353 case fonttype::TrueType: 354 pFont = new PrintFontManager::TrueTypeFontFile(); 355 break; 356 case fonttype::Type1: 357 pFont = new PrintFontManager::Type1FontFile(); 358 break; 359 case fonttype::Builtin: 360 pFont = new PrintFontManager::BuiltinFont(); 361 break; 362 default: break; 363 } 364 365 for( nIndex = 0; nIndex < nLen && pLine[nIndex] != ';'; nIndex++ ) 366 ; 367 368 pFont->m_nFamilyName = pAtoms->getAtom( ATOM_FAMILYNAME, 369 OUString( pLine, nIndex, RTL_TEXTENCODING_UTF8 ), 370 sal_True ); 371 while( nIndex < nLen ) 372 { 373 xub_StrLen nLastIndex = nIndex+1; 374 for( nIndex = nLastIndex ; nIndex < nLen && pLine[nIndex] != ';'; nIndex++ ) 375 ; 376 if( nIndex - nLastIndex ) 377 { 378 OUString aAlias( pLine+nLastIndex, nIndex-nLastIndex, RTL_TEXTENCODING_UTF8 ); 379 pFont->m_aAliases.push_back( pAtoms->getAtom( ATOM_FAMILYNAME, aAlias, sal_True ) ); 380 } 381 } 382 aStream.ReadLine( aLine ); 383 pLine = aLine.GetBuffer(); 384 nLen = aLine.Len(); 385 386 // get up to 20 token positions 387 const int nMaxTokens = 20; 388 int nTokenPos[nMaxTokens]; 389 nTokenPos[0] = 0; 390 int nTokens = 1; 391 for( int i = 0; i < nLen; i++ ) 392 { 393 if( pLine[i] == ';' ) 394 { 395 nTokenPos[nTokens++] = i+1; 396 if( nTokens == nMaxTokens ) 397 break; 398 } 399 } 400 if( nTokens < 18 ) 401 { 402 delete pFont; 403 continue; 404 } 405 int nCollEntry = atoi( pLine ); 406 pFont->m_nPSName = pAtoms->getAtom( ATOM_PSNAME, OUString( pLine + nTokenPos[1], nTokenPos[2]-nTokenPos[1]-1, RTL_TEXTENCODING_UTF8 ), sal_True ); 407 pFont->m_eItalic = (italic::type)atoi( pLine+nTokenPos[2] ); 408 pFont->m_eWeight = (weight::type)atoi( pLine+nTokenPos[3] ); 409 pFont->m_eWidth = (width::type)atoi( pLine+nTokenPos[4] ); 410 pFont->m_ePitch = (pitch::type)atoi( pLine+nTokenPos[5] ); 411 pFont->m_aEncoding = (rtl_TextEncoding)atoi( pLine+nTokenPos[6] ); 412 pFont->m_nAscend = atoi( pLine + nTokenPos[7] ); 413 pFont->m_nDescend = atoi( pLine + nTokenPos[8] ); 414 pFont->m_nLeading = atoi( pLine + nTokenPos[9] ); 415 pFont->m_bHaveVerticalSubstitutedGlyphs 416 = (atoi( pLine + nTokenPos[10] ) != 0); 417 pFont->m_aGlobalMetricX.width 418 = atoi( pLine + nTokenPos[11] ); 419 pFont->m_aGlobalMetricX.height 420 = atoi( pLine + nTokenPos[12] ); 421 pFont->m_aGlobalMetricY.width 422 = atoi( pLine + nTokenPos[13] ); 423 pFont->m_aGlobalMetricY.height 424 = atoi( pLine + nTokenPos[14] ); 425 pFont->m_bUserOverride 426 = (atoi( pLine + nTokenPos[15] ) != 0); 427 int nStyleTokenNr = 18; 428 switch( eType ) 429 { 430 case fonttype::TrueType: 431 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nTypeFlags = atoi( pLine + nTokenPos[18] ); 432 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry = nCollEntry; 433 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory = nDir; 434 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile = aFile; 435 nStyleTokenNr++; 436 break; 437 case fonttype::Type1: 438 { 439 int nTokLen = (nTokens > 19 ) ? nTokenPos[19]-nTokenPos[18]-1 : nLen - nTokenPos[18]; 440 static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aMetricFile = OString( pLine + nTokenPos[18], nTokLen ); 441 static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory = nDir; 442 static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile = aFile; 443 nStyleTokenNr++; 444 } 445 break; 446 case fonttype::Builtin: 447 static_cast<PrintFontManager::BuiltinFont*>(pFont)->m_nDirectory = nDir; 448 static_cast<PrintFontManager::BuiltinFont*>(pFont)->m_aMetricFile = aFile; 449 break; 450 default: break; 451 } 452 if( nTokens > nStyleTokenNr ) 453 pFont->m_aStyleName = OUString::intern( pLine + nTokenPos[nStyleTokenNr], 454 nLen - nTokenPos[nStyleTokenNr], 455 RTL_TEXTENCODING_UTF8 ); 456 457 bool bObsolete = false; 458 if( bKeepOnlyUserOverridden ) 459 { 460 if( pFont->m_bUserOverride ) 461 { 462 ByteString aFilePath = rManager.getDirectory( nDir ); 463 aFilePath.Append( '/' ); 464 aFilePath.Append( ByteString(aFile) ); 465 struct stat aStat; 466 if( stat( aFilePath.GetBuffer(), &aStat ) || 467 ! S_ISREG( aStat.st_mode ) || 468 aStat.st_size < 16 ) 469 { 470 bObsolete = true; 471 } 472 #if OSL_DEBUG_LEVEL > 2 473 else 474 fprintf( stderr, "keeping file %s in outdated cache entry due to user override\n", 475 aFilePath.GetBuffer() ); 476 #endif 477 } 478 else 479 bObsolete = true; 480 } 481 if( bObsolete ) 482 { 483 m_bDoFlush = true; 484 #if OSL_DEBUG_LEVEL > 2 485 fprintf( stderr, "removing obsolete font %s\n", aFile.getStr() ); 486 #endif 487 delete pFont; 488 continue; 489 } 490 491 FontCacheEntry& rEntry = (*pDir)[aFile].m_aEntry; 492 rEntry.push_back( pFont ); 493 } 494 } 495 } while( ! aStream.IsEof() ); 496 } 497 498 /* 499 * FontCache::updateDirTimestamp 500 */ 501 void FontCache::updateDirTimestamp( int nDirID ) 502 { 503 PrintFontManager& rManager( PrintFontManager::get() ); 504 const OString& rDir = rManager.getDirectory( nDirID ); 505 506 struct stat aStat; 507 if( ! stat( rDir.getStr(), &aStat ) ) 508 m_aCache[ nDirID ].m_nTimestamp = (sal_Int64)aStat.st_mtime; 509 } 510 511 512 /* 513 * FontCache::copyPrintFont 514 */ 515 void FontCache::copyPrintFont( const PrintFontManager::PrintFont* pFrom, PrintFontManager::PrintFont* pTo ) const 516 { 517 if( pFrom->m_eType != pTo->m_eType ) 518 return; 519 switch( pFrom->m_eType ) 520 { 521 case fonttype::TrueType: 522 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nDirectory; 523 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_aFontFile; 524 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nCollectionEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nCollectionEntry; 525 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nTypeFlags = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nTypeFlags; 526 break; 527 case fonttype::Type1: 528 static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_nDirectory; 529 static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aFontFile; 530 static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aMetricFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aMetricFile; 531 break; 532 case fonttype::Builtin: 533 static_cast<PrintFontManager::BuiltinFont*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::BuiltinFont*>(pFrom)->m_nDirectory; 534 static_cast<PrintFontManager::BuiltinFont*>(pTo)->m_aMetricFile = static_cast<const PrintFontManager::BuiltinFont*>(pFrom)->m_aMetricFile; 535 break; 536 default: break; 537 } 538 pTo->m_nFamilyName = pFrom->m_nFamilyName; 539 pTo->m_aStyleName = pFrom->m_aStyleName; 540 pTo->m_aAliases = pFrom->m_aAliases; 541 pTo->m_nPSName = pFrom->m_nPSName; 542 pTo->m_eItalic = pFrom->m_eItalic; 543 pTo->m_eWeight = pFrom->m_eWeight; 544 pTo->m_eWidth = pFrom->m_eWidth; 545 pTo->m_ePitch = pFrom->m_ePitch; 546 pTo->m_aEncoding = pFrom->m_aEncoding; 547 pTo->m_aGlobalMetricX = pFrom->m_aGlobalMetricX; 548 pTo->m_aGlobalMetricY = pFrom->m_aGlobalMetricY; 549 pTo->m_nAscend = pFrom->m_nAscend; 550 pTo->m_nDescend = pFrom->m_nDescend; 551 pTo->m_nLeading = pFrom->m_nLeading; 552 pTo->m_nXMin = pFrom->m_nXMin; 553 pTo->m_nYMin = pFrom->m_nYMin; 554 pTo->m_nXMax = pFrom->m_nXMax; 555 pTo->m_nYMax = pFrom->m_nYMax; 556 pTo->m_bHaveVerticalSubstitutedGlyphs = pFrom->m_bHaveVerticalSubstitutedGlyphs; 557 pTo->m_bUserOverride = pFrom->m_bUserOverride; 558 } 559 560 /* 561 * FontCache::equalsPrintFont 562 */ 563 bool FontCache::equalsPrintFont( const PrintFontManager::PrintFont* pLeft, PrintFontManager::PrintFont* pRight ) const 564 { 565 if( pLeft->m_eType != pRight->m_eType ) 566 return false; 567 switch( pLeft->m_eType ) 568 { 569 case fonttype::TrueType: 570 { 571 const PrintFontManager::TrueTypeFontFile* pLT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pLeft); 572 const PrintFontManager::TrueTypeFontFile* pRT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pRight); 573 if( pRT->m_nDirectory != pLT->m_nDirectory || 574 pRT->m_aFontFile != pLT->m_aFontFile || 575 pRT->m_nCollectionEntry != pLT->m_nCollectionEntry || 576 pRT->m_nTypeFlags != pLT->m_nTypeFlags ) 577 return false; 578 } 579 break; 580 case fonttype::Type1: 581 { 582 const PrintFontManager::Type1FontFile* pLT = static_cast<const PrintFontManager::Type1FontFile*>(pLeft); 583 const PrintFontManager::Type1FontFile* pRT = static_cast<const PrintFontManager::Type1FontFile*>(pRight); 584 if( pRT->m_nDirectory != pLT->m_nDirectory || 585 pRT->m_aFontFile != pLT->m_aFontFile || 586 pRT->m_aMetricFile != pLT->m_aMetricFile ) 587 return false; 588 } 589 break; 590 case fonttype::Builtin: 591 { 592 const PrintFontManager::BuiltinFont* pLT = static_cast<const PrintFontManager::BuiltinFont*>(pLeft); 593 const PrintFontManager::BuiltinFont* pRT = static_cast<const PrintFontManager::BuiltinFont*>(pRight); 594 if( pRT->m_nDirectory != pLT->m_nDirectory || 595 pRT->m_aMetricFile != pLT->m_aMetricFile ) 596 return false; 597 } 598 break; 599 default: break; 600 } 601 if( pRight->m_nFamilyName != pLeft->m_nFamilyName || 602 pRight->m_aStyleName != pLeft->m_aStyleName || 603 pRight->m_nPSName != pLeft->m_nPSName || 604 pRight->m_eItalic != pLeft->m_eItalic || 605 pRight->m_eWeight != pLeft->m_eWeight || 606 pRight->m_eWidth != pLeft->m_eWidth || 607 pRight->m_ePitch != pLeft->m_ePitch || 608 pRight->m_aEncoding != pLeft->m_aEncoding || 609 pRight->m_aGlobalMetricX != pLeft->m_aGlobalMetricX || 610 pRight->m_aGlobalMetricY != pLeft->m_aGlobalMetricY || 611 pRight->m_nAscend != pLeft->m_nAscend || 612 pRight->m_nDescend != pLeft->m_nDescend || 613 pRight->m_nLeading != pLeft->m_nLeading || 614 pRight->m_nXMin != pLeft->m_nXMin || 615 pRight->m_nYMin != pLeft->m_nYMin || 616 pRight->m_nXMax != pLeft->m_nXMax || 617 pRight->m_nYMax != pLeft->m_nYMax || 618 pRight->m_bHaveVerticalSubstitutedGlyphs != pLeft->m_bHaveVerticalSubstitutedGlyphs || 619 pRight->m_bUserOverride != pLeft->m_bUserOverride 620 ) 621 return false; 622 std::list< int >::const_iterator lit, rit; 623 for( lit = pLeft->m_aAliases.begin(), rit = pRight->m_aAliases.begin(); 624 lit != pLeft->m_aAliases.end() && rit != pRight->m_aAliases.end() && (*lit) == (*rit); 625 ++lit, ++rit ) 626 ; 627 return lit == pLeft->m_aAliases.end() && rit == pRight->m_aAliases.end(); 628 } 629 630 /* 631 * FontCache::clonePrintFont 632 */ 633 PrintFontManager::PrintFont* FontCache::clonePrintFont( const PrintFontManager::PrintFont* pOldFont ) const 634 { 635 PrintFontManager::PrintFont* pFont = NULL; 636 switch( pOldFont->m_eType ) 637 { 638 case fonttype::TrueType: 639 pFont = new PrintFontManager::TrueTypeFontFile(); 640 break; 641 case fonttype::Type1: 642 pFont = new PrintFontManager::Type1FontFile(); 643 break; 644 case fonttype::Builtin: 645 pFont = new PrintFontManager::BuiltinFont(); 646 break; 647 default: break; 648 } 649 if( pFont ) 650 { 651 copyPrintFont( pOldFont, pFont ); 652 } 653 return pFont; 654 } 655 656 /* 657 * FontCache::getFontCacheFile 658 */ 659 bool FontCache::getFontCacheFile( int nDirID, const OString& rFile, list< PrintFontManager::PrintFont* >& rNewFonts ) const 660 { 661 bool bSuccess = false; 662 663 FontCacheData::const_iterator dir = m_aCache.find( nDirID ); 664 if( dir != m_aCache.end() ) 665 { 666 FontDirMap::const_iterator entry = dir->second.m_aEntries.find( rFile ); 667 if( entry != dir->second.m_aEntries.end() ) 668 { 669 for( FontCacheEntry::const_iterator font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font ) 670 { 671 bSuccess = true; 672 PrintFontManager::PrintFont* pFont = clonePrintFont( *font ); 673 rNewFonts.push_back( pFont ); 674 } 675 } 676 } 677 return bSuccess; 678 } 679 680 /* 681 * FontCache::updateFontCacheEntry 682 */ 683 void FontCache::updateFontCacheEntry( const PrintFontManager::PrintFont* pFont, bool bFlush ) 684 { 685 PrintFontManager& rManager( PrintFontManager::get() ); 686 687 OString aFile; 688 int nDirID = 0; 689 switch( pFont->m_eType ) 690 { 691 case fonttype::TrueType: 692 nDirID = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory; 693 aFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile; 694 break; 695 case fonttype::Type1: 696 nDirID = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory; 697 aFile = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile; 698 break; 699 case fonttype::Builtin: 700 nDirID = static_cast<const PrintFontManager::BuiltinFont*>(pFont)->m_nDirectory; 701 aFile = static_cast<const PrintFontManager::BuiltinFont*>(pFont)->m_aMetricFile; 702 break; 703 default: 704 return; 705 } 706 FontCacheData::const_iterator dir = m_aCache.find( nDirID ); 707 FontDirMap::const_iterator entry; 708 FontCacheEntry::const_iterator font; 709 PrintFontManager::PrintFont* pCacheFont = NULL; 710 711 if( dir != m_aCache.end() ) 712 { 713 entry = dir->second.m_aEntries.find( aFile ); 714 if( entry != dir->second.m_aEntries.end() ) 715 { 716 for( font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font ) 717 { 718 if( (*font)->m_eType == pFont->m_eType && 719 ( (*font)->m_eType != fonttype::TrueType || 720 static_cast<const PrintFontManager::TrueTypeFontFile*>(*font)->m_nCollectionEntry == static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry 721 ) ) 722 break; 723 } 724 if( font != entry->second.m_aEntry.end() ) 725 pCacheFont = *font; 726 } 727 } 728 else 729 createCacheDir( nDirID ); 730 731 if( pCacheFont ) 732 { 733 if( ! equalsPrintFont( pFont, pCacheFont ) ) 734 { 735 copyPrintFont( pFont, pCacheFont ); 736 m_bDoFlush = true; 737 } 738 } 739 else 740 { 741 pCacheFont = clonePrintFont( pFont ); 742 m_aCache[nDirID].m_aEntries[aFile].m_aEntry.push_back( pCacheFont ); 743 744 ByteString aPath = rManager.getDirectory( nDirID ); 745 aPath.Append( '/' ); 746 aPath.Append( ByteString( aFile ) ); 747 m_bDoFlush = true; 748 } 749 if( bFlush ) 750 flush(); 751 } 752 753 /* 754 * FontCache::listDirectory 755 */ 756 bool FontCache::listDirectory( const OString& rDir, std::list< PrintFontManager::PrintFont* >& rNewFonts ) const 757 { 758 PrintFontManager& rManager( PrintFontManager::get() ); 759 int nDirID = rManager.getDirectoryAtom( rDir ); 760 FontCacheData::const_iterator dir = m_aCache.find( nDirID ); 761 bool bFound = (dir != m_aCache.end()); 762 763 if( bFound && !dir->second.m_bNoFiles ) 764 { 765 for( FontDirMap::const_iterator file = dir->second.m_aEntries.begin(); file != dir->second.m_aEntries.end(); ++file ) 766 { 767 for( FontCacheEntry::const_iterator font = file->second.m_aEntry.begin(); font != file->second.m_aEntry.end(); ++font ) 768 { 769 PrintFontManager::PrintFont* pFont = clonePrintFont( *font ); 770 rNewFonts.push_back( pFont ); 771 } 772 } 773 } 774 return bFound; 775 } 776 777 /* 778 * FontCache::listDirectory 779 */ 780 bool FontCache::scanAdditionalFiles( const OString& rDir ) 781 { 782 PrintFontManager& rManager( PrintFontManager::get() ); 783 int nDirID = rManager.getDirectoryAtom( rDir ); 784 FontCacheData::const_iterator dir = m_aCache.find( nDirID ); 785 bool bFound = (dir != m_aCache.end()); 786 787 return (bFound && dir->second.m_bUserOverrideOnly); 788 } 789 790 /* 791 * FontCache::createCacheDir 792 */ 793 void FontCache::createCacheDir( int nDirID ) 794 { 795 PrintFontManager& rManager( PrintFontManager::get() ); 796 797 const OString& rDir = rManager.getDirectory( nDirID ); 798 struct stat aStat; 799 if( ! stat( rDir.getStr(), &aStat ) ) 800 m_aCache[nDirID].m_nTimestamp = (sal_Int64)aStat.st_mtime; 801 } 802 803 /* 804 * FontCache::markEmptyDir 805 */ 806 void FontCache::markEmptyDir( int nDirID, bool bNoFiles ) 807 { 808 createCacheDir( nDirID ); 809 m_aCache[nDirID].m_bNoFiles = bNoFiles; 810 m_bDoFlush = true; 811 } 812