Bump for 4.0-15
[LibreOffice.git] / vcl / generic / fontmanager / fontcache.cxx
blobc8a9df10d060c25a95d1e4fc58998acc7b57d0b8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <cstdlib>
22 #include <cstring>
24 #include "fontcache.hxx"
26 #include "osl/thread.h"
28 #include "unotools/atom.hxx"
30 #include "tools/stream.hxx"
32 #include <rtl/strbuf.hxx>
34 #include <unistd.h>
35 #include <sys/stat.h>
37 #if OSL_DEBUG_LEVEL >1
38 #include <cstdio>
39 #endif
41 #define FONTCACHEFILE "/user/psprint/pspfontcache"
42 #define CACHE_MAGIC "LibreOffice PspFontCacheFile format 5"
44 using namespace std;
45 using namespace psp;
46 using namespace utl;
48 using ::rtl::OUString;
49 using ::rtl::OString;
50 using ::rtl::OUStringToOString;
53 * FontCache constructor
56 FontCache::FontCache()
58 m_bDoFlush = false;
59 m_aCacheFile = getOfficePath( UserPath );
60 if( m_aCacheFile.Len() )
62 m_aCacheFile.AppendAscii( FONTCACHEFILE );
63 read();
68 * FontCache destructor
71 FontCache::~FontCache()
73 clearCache();
77 * FontCache::clearCache
79 void FontCache::clearCache()
81 for( FontCacheData::iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++dir_it )
83 for( FontDirMap::iterator entry_it = dir_it->second.m_aEntries.begin(); entry_it != dir_it->second.m_aEntries.end(); ++entry_it )
85 for( FontCacheEntry::iterator font_it = entry_it->second.m_aEntry.begin(); font_it != entry_it->second.m_aEntry.end(); ++font_it )
86 delete *font_it;
89 m_aCache.clear();
93 * FontCache::Commit
96 void FontCache::flush()
98 if( ! m_bDoFlush || ! m_aCacheFile.Len() )
99 return;
101 SvFileStream aStream;
102 aStream.Open( m_aCacheFile, STREAM_WRITE | STREAM_TRUNC );
103 if( ! (aStream.IsOpen() && aStream.IsWritable()) )
105 #if OSL_DEBUG_LEVEL > 1
106 fprintf( stderr, "FontCache::flush: opening cache file %s failed\n", rtl::OUStringToOString(m_aCacheFile, osl_getThreadTextEncoding()).getStr() );
107 #endif
108 return;
111 aStream.SetLineDelimiter( LINEEND_LF );
112 aStream.WriteLine(rtl::OString(RTL_CONSTASCII_STRINGPARAM(CACHE_MAGIC)));
114 PrintFontManager& rManager( PrintFontManager::get() );
115 MultiAtomProvider* pAtoms = rManager.m_pAtoms;
117 for( FontCacheData::const_iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++ dir_it )
119 const FontDirMap& rDir( dir_it->second.m_aEntries );
121 rtl::OString aDirectory(rManager.getDirectory(dir_it->first));
122 rtl::OStringBuffer aLine(
123 RTL_CONSTASCII_STRINGPARAM("FontCacheDirectory:"));
124 aLine.append(dir_it->second.m_nTimestamp);
125 aLine.append(':');
126 aLine.append(aDirectory);
127 if( rDir.empty() && dir_it->second.m_bNoFiles )
128 aLine.insert(0, RTL_CONSTASCII_STRINGPARAM("Empty"));
129 aStream.WriteLine(aLine.makeStringAndClear());
131 for( FontDirMap::const_iterator entry_it = rDir.begin(); entry_it != rDir.end(); ++entry_it )
133 // insert cache entries
134 const FontCacheEntry& rEntry( entry_it->second.m_aEntry );
135 if( rEntry.begin() == rEntry.end() )
136 continue;
138 aLine.append(RTL_CONSTASCII_STRINGPARAM("File:"));
139 aLine.append(entry_it->first);
140 aStream.WriteLine(aLine.makeStringAndClear());
142 int nEntrySize = entry_it->second.m_aEntry.size();
143 // write: type;nfonts
144 aLine.append(static_cast<sal_Int32>(rEntry.front()->m_eType));
145 aLine.append(';');
146 aLine.append(static_cast<sal_Int32>(nEntrySize));
147 aStream.WriteLine(aLine.makeStringAndClear());
149 sal_Int32 nSubEntry = 0;
150 for( FontCacheEntry::const_iterator it = rEntry.begin(); it != rEntry.end(); ++it, nSubEntry++ )
153 * for each font entry write:
154 * name[;name[;name]]
155 * fontnr;PSName;italic;weight;width;pitch;encoding;ascend;descend;leading;vsubst;gxw;gxh;gyw;gyh;useroverrride;embed;antialias[;{metricfile,typeflags}][;stylename]
157 if( nEntrySize > 1 )
158 nSubEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nCollectionEntry;
159 else
160 nSubEntry = 0;
162 aLine.append(OUStringToOString(pAtoms->getString( ATOM_FAMILYNAME, (*it)->m_nFamilyName), RTL_TEXTENCODING_UTF8));
163 for( ::std::list< int >::const_iterator name_it = (*it)->m_aAliases.begin(); name_it != (*it)->m_aAliases.end(); ++name_it )
165 const OUString& rAdd( pAtoms->getString( ATOM_FAMILYNAME, *name_it ) );
166 if( !rAdd.isEmpty() )
168 aLine.append(';');
169 aLine.append(OUStringToOString(rAdd, RTL_TEXTENCODING_UTF8));
172 aStream.WriteLine(aLine.makeStringAndClear());
174 const OUString& rPSName( pAtoms->getString( ATOM_PSNAME, (*it)->m_nPSName ) );
175 aLine.append(nSubEntry);
176 aLine.append(';');
177 aLine.append(OUStringToOString(rPSName, RTL_TEXTENCODING_UTF8));
178 aLine.append(';');
179 aLine.append(static_cast<sal_Int32>((*it)->m_eItalic));
180 aLine.append(';');
181 aLine.append(static_cast<sal_Int32>((*it)->m_eWeight));
182 aLine.append(';');
183 aLine.append(static_cast<sal_Int32>((*it)->m_eWidth));
184 aLine.append(';');
185 aLine.append(static_cast<sal_Int32>((*it)->m_ePitch));
186 aLine.append(';');
187 aLine.append(static_cast<sal_Int32>((*it)->m_aEncoding));
188 aLine.append(';');
189 aLine.append(static_cast<sal_Int32>((*it)->m_nAscend));
190 aLine.append(';');
191 aLine.append(static_cast<sal_Int32>((*it)->m_nDescend));
192 aLine.append(';');
193 aLine.append(static_cast<sal_Int32>((*it)->m_nLeading));
194 aLine.append(';');
195 aLine.append((*it)->m_bHaveVerticalSubstitutedGlyphs ? '1' : '0');
196 aLine.append(';');
197 aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricX.width ));
198 aLine.append(';');
199 aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricX.height));
200 aLine.append(';');
201 aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricY.width ));
202 aLine.append(';');
203 aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricY.height));
204 aLine.append(';');
205 aLine.append((*it)->m_bUserOverride ? '1' : '0');
206 aLine.append(';');
207 aLine.append(static_cast<sal_Int32>(0));
208 aLine.append(';');
209 aLine.append(static_cast<sal_Int32>(0));
211 switch( (*it)->m_eType )
213 case fonttype::Type1:
214 aLine.append(';');
215 aLine.append(static_cast<const PrintFontManager::Type1FontFile*>(*it)->m_aMetricFile);
216 break;
217 case fonttype::TrueType:
218 aLine.append(';');
219 aLine.append(static_cast<sal_Int32>(static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nTypeFlags));
220 break;
221 default: break;
223 if( !(*it)->m_aStyleName.isEmpty() )
225 aLine.append(';');
226 aLine.append(OUStringToOString((*it)->m_aStyleName, RTL_TEXTENCODING_UTF8));
228 aStream.WriteLine(aLine.makeStringAndClear());
230 aStream.WriteLine(rtl::OString());
233 m_bDoFlush = false;
237 * FontCache::read
240 void FontCache::read()
242 PrintFontManager& rManager( PrintFontManager::get() );
243 MultiAtomProvider* pAtoms = rManager.m_pAtoms;
245 SvFileStream aStream( m_aCacheFile, STREAM_READ );
246 if( ! aStream.IsOpen() )
248 #if OSL_DEBUG_LEVEL > 1
249 fprintf( stderr, "FontCache::read: opening cache file %s failed\n", rtl::OUStringToOString(m_aCacheFile, osl_getThreadTextEncoding()).getStr() );
250 #endif
251 return;
255 OString aLine;
256 aStream.ReadLine( aLine );
257 if (!aLine.equalsL(RTL_CONSTASCII_STRINGPARAM(CACHE_MAGIC)))
259 #if OSL_DEBUG_LEVEL >1
260 fprintf( stderr, "FontCache::read: cache file %s fails magic test\n", rtl::OUStringToOString(m_aCacheFile, osl_getThreadTextEncoding()).getStr() );
261 #endif
262 return;
265 int nDir = 0;
266 FontDirMap* pDir = NULL;
267 bool bKeepOnlyUserOverridden = false;
270 aStream.ReadLine( aLine );
271 if( aLine.compareTo( RTL_CONSTASCII_STRINGPARAM( "FontCacheDirectory:" ) ) == 0 ||
272 aLine.compareTo( RTL_CONSTASCII_STRINGPARAM( "EmptyFontCacheDirectory:" ) ) == 0 )
274 bool bEmpty = (aLine.compareTo( RTL_CONSTASCII_STRINGPARAM ("Empty" ) ) == 0);
275 sal_Int32 nSearchIndex = bEmpty ? 24 : 19;
277 OString aDir;
278 sal_Int64 nTimestamp = 0;
279 sal_Int32 nTEnd = aLine.indexOf( ':', nSearchIndex );
280 if( nTEnd != -1 )
282 rtl::OString aTimeStamp = aLine.copy( nSearchIndex, nTEnd - nSearchIndex );
283 nTimestamp = aTimeStamp.toInt64();
284 aDir = aLine.copy( nTEnd+1 );
286 else
288 // invalid format, remove
289 pDir = NULL;
290 nDir = 0;
291 m_bDoFlush = true;
292 continue;
295 // is the directory modified ?
296 struct stat aStat;
297 if( stat( aDir.getStr(), &aStat ) ||
298 ! S_ISDIR(aStat.st_mode) )
300 // remove outdated cache data
301 pDir = NULL;
302 nDir = 0;
303 m_bDoFlush = true;
304 continue;
306 else
308 nDir = rManager.getDirectoryAtom( aDir, true );
309 m_aCache[ nDir ].m_nTimestamp = (sal_Int64)aStat.st_mtime;
310 m_aCache[ nDir ].m_bNoFiles = bEmpty;
311 pDir = bEmpty ? NULL : &m_aCache[ nDir ].m_aEntries;
312 bKeepOnlyUserOverridden = ((sal_Int64)aStat.st_mtime != nTimestamp);
313 m_aCache[ nDir ].m_bUserOverrideOnly = bKeepOnlyUserOverridden;
316 else if( pDir && aLine.compareTo( RTL_CONSTASCII_STRINGPARAM( "File:" ) ) == 0 )
318 OString aFile( aLine.copy( 5 ) );
319 aStream.ReadLine( aLine );
321 const char* pLine = aLine.getStr();
323 fonttype::type eType = (fonttype::type)atoi( pLine );
324 if( eType != fonttype::TrueType &&
325 eType != fonttype::Type1 &&
326 eType != fonttype::Builtin
328 continue;
329 while( *pLine && *pLine != ';' )
330 pLine++;
331 if( *pLine != ';' )
332 continue;
334 pLine++;
335 sal_Int32 nFonts = atoi( pLine );
336 for( int n = 0; n < nFonts; n++ )
338 aStream.ReadLine( aLine );
339 pLine = aLine.getStr();
340 int nLen = aLine.getLength();
342 PrintFontManager::PrintFont* pFont = NULL;
343 switch( eType )
345 case fonttype::TrueType:
346 pFont = new PrintFontManager::TrueTypeFontFile();
347 break;
348 case fonttype::Type1:
349 pFont = new PrintFontManager::Type1FontFile();
350 break;
351 case fonttype::Builtin:
352 pFont = new PrintFontManager::BuiltinFont();
353 break;
354 default: break;
357 sal_Int32 nIndex;
359 for( nIndex = 0; nIndex < nLen && pLine[nIndex] != ';'; nIndex++ )
362 pFont->m_nFamilyName = pAtoms->getAtom( ATOM_FAMILYNAME,
363 OUString( pLine, nIndex, RTL_TEXTENCODING_UTF8 ),
364 sal_True );
365 while( nIndex < nLen )
367 sal_Int32 nLastIndex = nIndex+1;
368 for( nIndex = nLastIndex ; nIndex < nLen && pLine[nIndex] != ';'; nIndex++ )
370 if( nIndex - nLastIndex )
372 OUString aAlias( pLine+nLastIndex, nIndex-nLastIndex, RTL_TEXTENCODING_UTF8 );
373 pFont->m_aAliases.push_back( pAtoms->getAtom( ATOM_FAMILYNAME, aAlias, sal_True ) );
376 aStream.ReadLine( aLine );
377 pLine = aLine.getStr();
378 nLen = aLine.getLength();
380 // get up to 20 token positions
381 const int nMaxTokens = 20;
382 int nTokenPos[nMaxTokens];
383 nTokenPos[0] = 0;
384 int nTokens = 1;
385 for( int i = 0; i < nLen; i++ )
387 if( pLine[i] == ';' )
389 nTokenPos[nTokens++] = i+1;
390 if( nTokens == nMaxTokens )
391 break;
394 if( nTokens < 18 )
396 delete pFont;
397 continue;
399 int nCollEntry = atoi( pLine );
400 pFont->m_nPSName = pAtoms->getAtom( ATOM_PSNAME, OUString( pLine + nTokenPos[1], nTokenPos[2]-nTokenPos[1]-1, RTL_TEXTENCODING_UTF8 ), sal_True );
401 pFont->m_eItalic = (FontItalic)atoi( pLine+nTokenPos[2] );
402 pFont->m_eWeight = (FontWeight)atoi( pLine+nTokenPos[3] );
403 pFont->m_eWidth = (FontWidth)atoi( pLine+nTokenPos[4] );
404 pFont->m_ePitch = (FontPitch)atoi( pLine+nTokenPos[5] );
405 pFont->m_aEncoding = (rtl_TextEncoding)atoi( pLine+nTokenPos[6] );
406 pFont->m_nAscend = atoi( pLine + nTokenPos[7] );
407 pFont->m_nDescend = atoi( pLine + nTokenPos[8] );
408 pFont->m_nLeading = atoi( pLine + nTokenPos[9] );
409 pFont->m_bHaveVerticalSubstitutedGlyphs
410 = (atoi( pLine + nTokenPos[10] ) != 0);
411 pFont->m_aGlobalMetricX.width
412 = atoi( pLine + nTokenPos[11] );
413 pFont->m_aGlobalMetricX.height
414 = atoi( pLine + nTokenPos[12] );
415 pFont->m_aGlobalMetricY.width
416 = atoi( pLine + nTokenPos[13] );
417 pFont->m_aGlobalMetricY.height
418 = atoi( pLine + nTokenPos[14] );
419 pFont->m_bUserOverride
420 = (atoi( pLine + nTokenPos[15] ) != 0);
421 int nStyleTokenNr = 18;
422 switch( eType )
424 case fonttype::TrueType:
425 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nTypeFlags = atoi( pLine + nTokenPos[18] );
426 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry = nCollEntry;
427 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory = nDir;
428 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile = aFile;
429 nStyleTokenNr++;
430 break;
431 case fonttype::Type1:
433 int nTokLen = (nTokens > 19 ) ? nTokenPos[19]-nTokenPos[18]-1 : nLen - nTokenPos[18];
434 static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aMetricFile = OString( pLine + nTokenPos[18], nTokLen );
435 static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory = nDir;
436 static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile = aFile;
437 nStyleTokenNr++;
439 break;
440 case fonttype::Builtin:
441 static_cast<PrintFontManager::BuiltinFont*>(pFont)->m_nDirectory = nDir;
442 static_cast<PrintFontManager::BuiltinFont*>(pFont)->m_aMetricFile = aFile;
443 break;
444 default: break;
446 if( nTokens > nStyleTokenNr )
447 pFont->m_aStyleName = OUString::intern( pLine + nTokenPos[nStyleTokenNr],
448 nLen - nTokenPos[nStyleTokenNr],
449 RTL_TEXTENCODING_UTF8 );
451 bool bObsolete = false;
452 if( bKeepOnlyUserOverridden )
454 if( pFont->m_bUserOverride )
456 rtl::OStringBuffer aFilePath(rManager.getDirectory(nDir));
457 aFilePath.append('/').append(aFile);
458 struct stat aStat;
459 if( stat( aFilePath.getStr(), &aStat ) ||
460 ! S_ISREG( aStat.st_mode ) ||
461 aStat.st_size < 16 )
463 bObsolete = true;
465 #if OSL_DEBUG_LEVEL > 2
466 else
467 fprintf( stderr, "keeping file %s in outdated cache entry due to user override\n",
468 aFilePath.getStr() );
469 #endif
471 else
472 bObsolete = true;
474 if( bObsolete )
476 m_bDoFlush = true;
477 #if OSL_DEBUG_LEVEL > 2
478 fprintf( stderr, "removing obsolete font %s\n", aFile.getStr() );
479 #endif
480 delete pFont;
481 continue;
484 FontCacheEntry& rEntry = (*pDir)[aFile].m_aEntry;
485 rEntry.push_back( pFont );
488 } while( ! aStream.IsEof() );
492 * FontCache::copyPrintFont
494 void FontCache::copyPrintFont( const PrintFontManager::PrintFont* pFrom, PrintFontManager::PrintFont* pTo ) const
496 if( pFrom->m_eType != pTo->m_eType )
497 return;
498 switch( pFrom->m_eType )
500 case fonttype::TrueType:
501 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nDirectory;
502 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_aFontFile;
503 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nCollectionEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nCollectionEntry;
504 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nTypeFlags = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nTypeFlags;
505 break;
506 case fonttype::Type1:
507 static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_nDirectory;
508 static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aFontFile;
509 static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aMetricFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aMetricFile;
510 break;
511 case fonttype::Builtin:
512 static_cast<PrintFontManager::BuiltinFont*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::BuiltinFont*>(pFrom)->m_nDirectory;
513 static_cast<PrintFontManager::BuiltinFont*>(pTo)->m_aMetricFile = static_cast<const PrintFontManager::BuiltinFont*>(pFrom)->m_aMetricFile;
514 break;
515 default: break;
517 pTo->m_nFamilyName = pFrom->m_nFamilyName;
518 pTo->m_aStyleName = pFrom->m_aStyleName;
519 pTo->m_aAliases = pFrom->m_aAliases;
520 pTo->m_nPSName = pFrom->m_nPSName;
521 pTo->m_eItalic = pFrom->m_eItalic;
522 pTo->m_eWeight = pFrom->m_eWeight;
523 pTo->m_eWidth = pFrom->m_eWidth;
524 pTo->m_ePitch = pFrom->m_ePitch;
525 pTo->m_aEncoding = pFrom->m_aEncoding;
526 pTo->m_aGlobalMetricX = pFrom->m_aGlobalMetricX;
527 pTo->m_aGlobalMetricY = pFrom->m_aGlobalMetricY;
528 pTo->m_nAscend = pFrom->m_nAscend;
529 pTo->m_nDescend = pFrom->m_nDescend;
530 pTo->m_nLeading = pFrom->m_nLeading;
531 pTo->m_nXMin = pFrom->m_nXMin;
532 pTo->m_nYMin = pFrom->m_nYMin;
533 pTo->m_nXMax = pFrom->m_nXMax;
534 pTo->m_nYMax = pFrom->m_nYMax;
535 pTo->m_bHaveVerticalSubstitutedGlyphs = pFrom->m_bHaveVerticalSubstitutedGlyphs;
536 pTo->m_bUserOverride = pFrom->m_bUserOverride;
540 * FontCache::equalsPrintFont
542 bool FontCache::equalsPrintFont( const PrintFontManager::PrintFont* pLeft, PrintFontManager::PrintFont* pRight ) const
544 if( pLeft->m_eType != pRight->m_eType )
545 return false;
546 switch( pLeft->m_eType )
548 case fonttype::TrueType:
550 const PrintFontManager::TrueTypeFontFile* pLT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pLeft);
551 const PrintFontManager::TrueTypeFontFile* pRT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pRight);
552 if( pRT->m_nDirectory != pLT->m_nDirectory ||
553 pRT->m_aFontFile != pLT->m_aFontFile ||
554 pRT->m_nCollectionEntry != pLT->m_nCollectionEntry ||
555 pRT->m_nTypeFlags != pLT->m_nTypeFlags )
556 return false;
558 break;
559 case fonttype::Type1:
561 const PrintFontManager::Type1FontFile* pLT = static_cast<const PrintFontManager::Type1FontFile*>(pLeft);
562 const PrintFontManager::Type1FontFile* pRT = static_cast<const PrintFontManager::Type1FontFile*>(pRight);
563 if( pRT->m_nDirectory != pLT->m_nDirectory ||
564 pRT->m_aFontFile != pLT->m_aFontFile ||
565 pRT->m_aMetricFile != pLT->m_aMetricFile )
566 return false;
568 break;
569 case fonttype::Builtin:
571 const PrintFontManager::BuiltinFont* pLT = static_cast<const PrintFontManager::BuiltinFont*>(pLeft);
572 const PrintFontManager::BuiltinFont* pRT = static_cast<const PrintFontManager::BuiltinFont*>(pRight);
573 if( pRT->m_nDirectory != pLT->m_nDirectory ||
574 pRT->m_aMetricFile != pLT->m_aMetricFile )
575 return false;
577 break;
578 default: break;
580 if( pRight->m_nFamilyName != pLeft->m_nFamilyName ||
581 pRight->m_aStyleName != pLeft->m_aStyleName ||
582 pRight->m_nPSName != pLeft->m_nPSName ||
583 pRight->m_eItalic != pLeft->m_eItalic ||
584 pRight->m_eWeight != pLeft->m_eWeight ||
585 pRight->m_eWidth != pLeft->m_eWidth ||
586 pRight->m_ePitch != pLeft->m_ePitch ||
587 pRight->m_aEncoding != pLeft->m_aEncoding ||
588 pRight->m_aGlobalMetricX != pLeft->m_aGlobalMetricX ||
589 pRight->m_aGlobalMetricY != pLeft->m_aGlobalMetricY ||
590 pRight->m_nAscend != pLeft->m_nAscend ||
591 pRight->m_nDescend != pLeft->m_nDescend ||
592 pRight->m_nLeading != pLeft->m_nLeading ||
593 pRight->m_nXMin != pLeft->m_nXMin ||
594 pRight->m_nYMin != pLeft->m_nYMin ||
595 pRight->m_nXMax != pLeft->m_nXMax ||
596 pRight->m_nYMax != pLeft->m_nYMax ||
597 pRight->m_bHaveVerticalSubstitutedGlyphs != pLeft->m_bHaveVerticalSubstitutedGlyphs ||
598 pRight->m_bUserOverride != pLeft->m_bUserOverride
600 return false;
601 std::list< int >::const_iterator lit, rit;
602 for( lit = pLeft->m_aAliases.begin(), rit = pRight->m_aAliases.begin();
603 lit != pLeft->m_aAliases.end() && rit != pRight->m_aAliases.end() && (*lit) == (*rit);
604 ++lit, ++rit )
606 return lit == pLeft->m_aAliases.end() && rit == pRight->m_aAliases.end();
610 * FontCache::clonePrintFont
612 PrintFontManager::PrintFont* FontCache::clonePrintFont( const PrintFontManager::PrintFont* pOldFont ) const
614 PrintFontManager::PrintFont* pFont = NULL;
615 switch( pOldFont->m_eType )
617 case fonttype::TrueType:
618 pFont = new PrintFontManager::TrueTypeFontFile();
619 break;
620 case fonttype::Type1:
621 pFont = new PrintFontManager::Type1FontFile();
622 break;
623 case fonttype::Builtin:
624 pFont = new PrintFontManager::BuiltinFont();
625 break;
626 default: break;
628 if( pFont )
630 copyPrintFont( pOldFont, pFont );
632 return pFont;
636 * FontCache::getFontCacheFile
638 bool FontCache::getFontCacheFile( int nDirID, const OString& rFile, list< PrintFontManager::PrintFont* >& rNewFonts ) const
640 bool bSuccess = false;
642 FontCacheData::const_iterator dir = m_aCache.find( nDirID );
643 if( dir != m_aCache.end() )
645 FontDirMap::const_iterator entry = dir->second.m_aEntries.find( rFile );
646 if( entry != dir->second.m_aEntries.end() )
648 for( FontCacheEntry::const_iterator font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
650 bSuccess = true;
651 PrintFontManager::PrintFont* pFont = clonePrintFont( *font );
652 rNewFonts.push_back( pFont );
656 return bSuccess;
660 * FontCache::updateFontCacheEntry
662 void FontCache::updateFontCacheEntry( const PrintFontManager::PrintFont* pFont, bool bFlush )
664 OString aFile;
665 int nDirID = 0;
666 switch( pFont->m_eType )
668 case fonttype::TrueType:
669 nDirID = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory;
670 aFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile;
671 break;
672 case fonttype::Type1:
673 nDirID = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory;
674 aFile = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile;
675 break;
676 case fonttype::Builtin:
677 nDirID = static_cast<const PrintFontManager::BuiltinFont*>(pFont)->m_nDirectory;
678 aFile = static_cast<const PrintFontManager::BuiltinFont*>(pFont)->m_aMetricFile;
679 break;
680 default:
681 return;
683 FontCacheData::const_iterator dir = m_aCache.find( nDirID );
684 FontDirMap::const_iterator entry;
685 FontCacheEntry::const_iterator font;
686 PrintFontManager::PrintFont* pCacheFont = NULL;
688 if( dir != m_aCache.end() )
690 entry = dir->second.m_aEntries.find( aFile );
691 if( entry != dir->second.m_aEntries.end() )
693 for( font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
695 if( (*font)->m_eType == pFont->m_eType &&
696 ( (*font)->m_eType != fonttype::TrueType ||
697 static_cast<const PrintFontManager::TrueTypeFontFile*>(*font)->m_nCollectionEntry == static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry
699 break;
701 if( font != entry->second.m_aEntry.end() )
702 pCacheFont = *font;
705 else
706 createCacheDir( nDirID );
708 if( pCacheFont )
710 if( ! equalsPrintFont( pFont, pCacheFont ) )
712 copyPrintFont( pFont, pCacheFont );
713 m_bDoFlush = true;
716 else
718 pCacheFont = clonePrintFont( pFont );
719 m_aCache[nDirID].m_aEntries[aFile].m_aEntry.push_back( pCacheFont );
720 m_bDoFlush = true;
722 if( bFlush )
723 flush();
727 * FontCache::listDirectory
729 bool FontCache::listDirectory( const OString& rDir, std::list< PrintFontManager::PrintFont* >& rNewFonts ) const
731 PrintFontManager& rManager( PrintFontManager::get() );
732 int nDirID = rManager.getDirectoryAtom( rDir );
733 FontCacheData::const_iterator dir = m_aCache.find( nDirID );
734 bool bFound = (dir != m_aCache.end());
736 if( bFound && !dir->second.m_bNoFiles )
738 for( FontDirMap::const_iterator file = dir->second.m_aEntries.begin(); file != dir->second.m_aEntries.end(); ++file )
740 for( FontCacheEntry::const_iterator font = file->second.m_aEntry.begin(); font != file->second.m_aEntry.end(); ++font )
742 PrintFontManager::PrintFont* pFont = clonePrintFont( *font );
743 rNewFonts.push_back( pFont );
747 return bFound;
751 * FontCache::listDirectory
753 bool FontCache::scanAdditionalFiles( const OString& rDir )
755 PrintFontManager& rManager( PrintFontManager::get() );
756 int nDirID = rManager.getDirectoryAtom( rDir );
757 FontCacheData::const_iterator dir = m_aCache.find( nDirID );
758 bool bFound = (dir != m_aCache.end());
760 return (bFound && dir->second.m_bUserOverrideOnly);
764 * FontCache::createCacheDir
766 void FontCache::createCacheDir( int nDirID )
768 PrintFontManager& rManager( PrintFontManager::get() );
770 const OString& rDir = rManager.getDirectory( nDirID );
771 struct stat aStat;
772 if( ! stat( rDir.getStr(), &aStat ) )
773 m_aCache[nDirID].m_nTimestamp = (sal_Int64)aStat.st_mtime;
777 * FontCache::markEmptyDir
779 void FontCache::markEmptyDir( int nDirID, bool bNoFiles )
781 createCacheDir( nDirID );
782 m_aCache[nDirID].m_bNoFiles = bNoFiles;
783 m_bDoFlush = true;
786 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */