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