bump product version to 4.1.6.2
[LibreOffice.git] / vcl / generic / fontmanager / fontcache.cxx
blob0f6c6777c3cb824f9be06a0a58e15e9d039a527f
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;
50 * FontCache constructor
53 FontCache::FontCache()
55 m_bDoFlush = false;
56 m_aCacheFile = getOfficePath( UserPath );
57 if( m_aCacheFile.Len() )
59 m_aCacheFile.AppendAscii( FONTCACHEFILE );
60 read();
65 * FontCache destructor
68 FontCache::~FontCache()
70 clearCache();
74 * FontCache::clearCache
76 void FontCache::clearCache()
78 for( FontCacheData::iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++dir_it )
80 for( FontDirMap::iterator entry_it = dir_it->second.m_aEntries.begin(); entry_it != dir_it->second.m_aEntries.end(); ++entry_it )
82 for( FontCacheEntry::iterator font_it = entry_it->second.m_aEntry.begin(); font_it != entry_it->second.m_aEntry.end(); ++font_it )
83 delete *font_it;
86 m_aCache.clear();
90 * FontCache::Commit
93 void FontCache::flush()
95 if( ! m_bDoFlush || ! m_aCacheFile.Len() )
96 return;
98 SvFileStream aStream;
99 aStream.Open( m_aCacheFile, STREAM_WRITE | STREAM_TRUNC );
100 if( ! (aStream.IsOpen() && aStream.IsWritable()) )
102 #if OSL_DEBUG_LEVEL > 1
103 fprintf( stderr, "FontCache::flush: opening cache file %s failed\n", OUStringToOString(m_aCacheFile, osl_getThreadTextEncoding()).getStr() );
104 #endif
105 return;
108 aStream.SetLineDelimiter( LINEEND_LF );
109 aStream.WriteLine( CACHE_MAGIC );
111 PrintFontManager& rManager( PrintFontManager::get() );
112 MultiAtomProvider* pAtoms = rManager.m_pAtoms;
114 for( FontCacheData::const_iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++ dir_it )
116 const FontDirMap& rDir( dir_it->second.m_aEntries );
118 OString aDirectory(rManager.getDirectory(dir_it->first));
119 OStringBuffer aLine("FontCacheDirectory:");
120 aLine.append(dir_it->second.m_nTimestamp);
121 aLine.append(':');
122 aLine.append(aDirectory);
123 if( rDir.empty() && dir_it->second.m_bNoFiles )
124 aLine.insert(0, "Empty");
125 aStream.WriteLine(aLine.makeStringAndClear());
127 for( FontDirMap::const_iterator entry_it = rDir.begin(); entry_it != rDir.end(); ++entry_it )
129 // insert cache entries
130 const FontCacheEntry& rEntry( entry_it->second.m_aEntry );
131 if( rEntry.begin() == rEntry.end() )
132 continue;
134 aLine.append("File:");
135 aLine.append(entry_it->first);
136 aStream.WriteLine(aLine.makeStringAndClear());
138 int nEntrySize = entry_it->second.m_aEntry.size();
139 // write: type;nfonts
140 aLine.append(static_cast<sal_Int32>(rEntry.front()->m_eType));
141 aLine.append(';');
142 aLine.append(static_cast<sal_Int32>(nEntrySize));
143 aStream.WriteLine(aLine.makeStringAndClear());
145 sal_Int32 nSubEntry = 0;
146 for( FontCacheEntry::const_iterator it = rEntry.begin(); it != rEntry.end(); ++it, nSubEntry++ )
149 * for each font entry write:
150 * name[;name[;name]]
151 * fontnr;PSName;italic;weight;width;pitch;encoding;ascend;descend;leading;vsubst;gxw;gxh;gyw;gyh;useroverrride;embed;antialias[;{metricfile,typeflags}][;stylename]
153 if( nEntrySize > 1 )
154 nSubEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nCollectionEntry;
155 else
156 nSubEntry = 0;
158 aLine.append(OUStringToOString(pAtoms->getString( ATOM_FAMILYNAME, (*it)->m_nFamilyName), RTL_TEXTENCODING_UTF8));
159 for( ::std::list< int >::const_iterator name_it = (*it)->m_aAliases.begin(); name_it != (*it)->m_aAliases.end(); ++name_it )
161 const OUString& rAdd( pAtoms->getString( ATOM_FAMILYNAME, *name_it ) );
162 if( !rAdd.isEmpty() )
164 aLine.append(';');
165 aLine.append(OUStringToOString(rAdd, RTL_TEXTENCODING_UTF8));
168 aStream.WriteLine(aLine.makeStringAndClear());
170 const OUString& rPSName( pAtoms->getString( ATOM_PSNAME, (*it)->m_nPSName ) );
171 aLine.append(nSubEntry);
172 aLine.append(';');
173 aLine.append(OUStringToOString(rPSName, RTL_TEXTENCODING_UTF8));
174 aLine.append(';');
175 aLine.append(static_cast<sal_Int32>((*it)->m_eItalic));
176 aLine.append(';');
177 aLine.append(static_cast<sal_Int32>((*it)->m_eWeight));
178 aLine.append(';');
179 aLine.append(static_cast<sal_Int32>((*it)->m_eWidth));
180 aLine.append(';');
181 aLine.append(static_cast<sal_Int32>((*it)->m_ePitch));
182 aLine.append(';');
183 aLine.append(static_cast<sal_Int32>((*it)->m_aEncoding));
184 aLine.append(';');
185 aLine.append(static_cast<sal_Int32>((*it)->m_nAscend));
186 aLine.append(';');
187 aLine.append(static_cast<sal_Int32>((*it)->m_nDescend));
188 aLine.append(';');
189 aLine.append(static_cast<sal_Int32>((*it)->m_nLeading));
190 aLine.append(';');
191 aLine.append((*it)->m_bHaveVerticalSubstitutedGlyphs ? '1' : '0');
192 aLine.append(';');
193 aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricX.width ));
194 aLine.append(';');
195 aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricX.height));
196 aLine.append(';');
197 aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricY.width ));
198 aLine.append(';');
199 aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricY.height));
200 aLine.append(';');
201 aLine.append((*it)->m_bUserOverride ? '1' : '0');
202 aLine.append(';');
203 aLine.append(static_cast<sal_Int32>(0));
204 aLine.append(';');
205 aLine.append(static_cast<sal_Int32>(0));
207 switch( (*it)->m_eType )
209 case fonttype::Type1:
210 aLine.append(';');
211 aLine.append(static_cast<const PrintFontManager::Type1FontFile*>(*it)->m_aMetricFile);
212 break;
213 case fonttype::TrueType:
214 aLine.append(';');
215 aLine.append(static_cast<sal_Int32>(static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nTypeFlags));
216 break;
217 default: break;
219 if( !(*it)->m_aStyleName.isEmpty() )
221 aLine.append(';');
222 aLine.append(OUStringToOString((*it)->m_aStyleName, RTL_TEXTENCODING_UTF8));
224 aStream.WriteLine(aLine.makeStringAndClear());
226 aStream.WriteLine(OString());
229 m_bDoFlush = false;
233 * FontCache::read
236 void FontCache::read()
238 PrintFontManager& rManager( PrintFontManager::get() );
239 MultiAtomProvider* pAtoms = rManager.m_pAtoms;
241 SvFileStream aStream( m_aCacheFile, STREAM_READ );
242 if( ! aStream.IsOpen() )
244 #if OSL_DEBUG_LEVEL > 1
245 fprintf( stderr, "FontCache::read: opening cache file %s failed\n", OUStringToOString(m_aCacheFile, osl_getThreadTextEncoding()).getStr() );
246 #endif
247 return;
251 OString aLine;
252 aStream.ReadLine( aLine );
253 if ( !(aLine == CACHE_MAGIC) )
255 #if OSL_DEBUG_LEVEL >1
256 fprintf( stderr, "FontCache::read: cache file %s fails magic test\n", OUStringToOString(m_aCacheFile, osl_getThreadTextEncoding()).getStr() );
257 #endif
258 return;
261 int nDir = 0;
262 FontDirMap* pDir = NULL;
263 bool bKeepOnlyUserOverridden = false;
266 aStream.ReadLine( aLine );
267 if( aLine.startsWith("FontCacheDirectory:") ||
268 aLine.startsWith("EmptyFontCacheDirectory:") )
270 bool bEmpty = aLine.startsWith("Empty");
271 sal_Int32 nSearchIndex = bEmpty ? 24 : 19;
273 OString aDir;
274 sal_Int64 nTimestamp = 0;
275 sal_Int32 nTEnd = aLine.indexOf( ':', nSearchIndex );
276 if( nTEnd != -1 )
278 OString aTimeStamp = aLine.copy( nSearchIndex, nTEnd - nSearchIndex );
279 nTimestamp = aTimeStamp.toInt64();
280 aDir = aLine.copy( nTEnd+1 );
282 else
284 // invalid format, remove
285 pDir = NULL;
286 nDir = 0;
287 m_bDoFlush = true;
288 continue;
291 // is the directory modified ?
292 struct stat aStat;
293 if( stat( aDir.getStr(), &aStat ) ||
294 ! S_ISDIR(aStat.st_mode) )
296 // remove outdated cache data
297 pDir = NULL;
298 nDir = 0;
299 m_bDoFlush = true;
300 continue;
302 else
304 nDir = rManager.getDirectoryAtom( aDir, true );
305 m_aCache[ nDir ].m_nTimestamp = (sal_Int64)aStat.st_mtime;
306 m_aCache[ nDir ].m_bNoFiles = bEmpty;
307 pDir = bEmpty ? NULL : &m_aCache[ nDir ].m_aEntries;
308 bKeepOnlyUserOverridden = ((sal_Int64)aStat.st_mtime != nTimestamp);
309 m_aCache[ nDir ].m_bUserOverrideOnly = bKeepOnlyUserOverridden;
312 else if( pDir && aLine.startsWith("File:") )
314 OString aFile( aLine.copy( 5 ) );
315 aStream.ReadLine( aLine );
317 const char* pLine = aLine.getStr();
319 fonttype::type eType = (fonttype::type)atoi( pLine );
320 if( eType != fonttype::TrueType &&
321 eType != fonttype::Type1 &&
322 eType != fonttype::Builtin
324 continue;
325 while( *pLine && *pLine != ';' )
326 pLine++;
327 if( *pLine != ';' )
328 continue;
330 pLine++;
331 sal_Int32 nFonts = atoi( pLine );
332 for( int n = 0; n < nFonts; n++ )
334 aStream.ReadLine( aLine );
335 pLine = aLine.getStr();
336 int nLen = aLine.getLength();
338 PrintFontManager::PrintFont* pFont = NULL;
339 switch( eType )
341 case fonttype::TrueType:
342 pFont = new PrintFontManager::TrueTypeFontFile();
343 break;
344 case fonttype::Type1:
345 pFont = new PrintFontManager::Type1FontFile();
346 break;
347 case fonttype::Builtin:
348 pFont = new PrintFontManager::BuiltinFont();
349 break;
350 default: break;
353 sal_Int32 nIndex;
355 for( nIndex = 0; nIndex < nLen && pLine[nIndex] != ';'; nIndex++ )
358 pFont->m_nFamilyName = pAtoms->getAtom( ATOM_FAMILYNAME,
359 OUString( pLine, nIndex, RTL_TEXTENCODING_UTF8 ),
360 sal_True );
361 while( nIndex < nLen )
363 sal_Int32 nLastIndex = nIndex+1;
364 for( nIndex = nLastIndex ; nIndex < nLen && pLine[nIndex] != ';'; nIndex++ )
366 if( nIndex - nLastIndex )
368 OUString aAlias( pLine+nLastIndex, nIndex-nLastIndex, RTL_TEXTENCODING_UTF8 );
369 pFont->m_aAliases.push_back( pAtoms->getAtom( ATOM_FAMILYNAME, aAlias, sal_True ) );
372 aStream.ReadLine( aLine );
373 pLine = aLine.getStr();
374 nLen = aLine.getLength();
376 // get up to 20 token positions
377 const int nMaxTokens = 20;
378 int nTokenPos[nMaxTokens];
379 nTokenPos[0] = 0;
380 int nTokens = 1;
381 for( int i = 0; i < nLen; i++ )
383 if( pLine[i] == ';' )
385 nTokenPos[nTokens++] = i+1;
386 if( nTokens == nMaxTokens )
387 break;
390 if( nTokens < 18 )
392 delete pFont;
393 continue;
395 int nCollEntry = atoi( pLine );
396 pFont->m_nPSName = pAtoms->getAtom( ATOM_PSNAME, OUString( pLine + nTokenPos[1], nTokenPos[2]-nTokenPos[1]-1, RTL_TEXTENCODING_UTF8 ), sal_True );
397 pFont->m_eItalic = (FontItalic)atoi( pLine+nTokenPos[2] );
398 pFont->m_eWeight = (FontWeight)atoi( pLine+nTokenPos[3] );
399 pFont->m_eWidth = (FontWidth)atoi( pLine+nTokenPos[4] );
400 pFont->m_ePitch = (FontPitch)atoi( pLine+nTokenPos[5] );
401 pFont->m_aEncoding = (rtl_TextEncoding)atoi( pLine+nTokenPos[6] );
402 pFont->m_nAscend = atoi( pLine + nTokenPos[7] );
403 pFont->m_nDescend = atoi( pLine + nTokenPos[8] );
404 pFont->m_nLeading = atoi( pLine + nTokenPos[9] );
405 pFont->m_bHaveVerticalSubstitutedGlyphs
406 = (atoi( pLine + nTokenPos[10] ) != 0);
407 pFont->m_aGlobalMetricX.width
408 = atoi( pLine + nTokenPos[11] );
409 pFont->m_aGlobalMetricX.height
410 = atoi( pLine + nTokenPos[12] );
411 pFont->m_aGlobalMetricY.width
412 = atoi( pLine + nTokenPos[13] );
413 pFont->m_aGlobalMetricY.height
414 = atoi( pLine + nTokenPos[14] );
415 pFont->m_bUserOverride
416 = (atoi( pLine + nTokenPos[15] ) != 0);
417 int nStyleTokenNr = 18;
418 switch( eType )
420 case fonttype::TrueType:
421 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nTypeFlags = atoi( pLine + nTokenPos[18] );
422 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry = nCollEntry;
423 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory = nDir;
424 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile = aFile;
425 nStyleTokenNr++;
426 break;
427 case fonttype::Type1:
429 int nTokLen = (nTokens > 19 ) ? nTokenPos[19]-nTokenPos[18]-1 : nLen - nTokenPos[18];
430 static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aMetricFile = OString( pLine + nTokenPos[18], nTokLen );
431 static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory = nDir;
432 static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile = aFile;
433 nStyleTokenNr++;
435 break;
436 case fonttype::Builtin:
437 static_cast<PrintFontManager::BuiltinFont*>(pFont)->m_nDirectory = nDir;
438 static_cast<PrintFontManager::BuiltinFont*>(pFont)->m_aMetricFile = aFile;
439 break;
440 default: break;
442 if( nTokens > nStyleTokenNr )
443 pFont->m_aStyleName = OUString::intern( pLine + nTokenPos[nStyleTokenNr],
444 nLen - nTokenPos[nStyleTokenNr],
445 RTL_TEXTENCODING_UTF8 );
447 bool bObsolete = false;
448 if( bKeepOnlyUserOverridden )
450 if( pFont->m_bUserOverride )
452 OStringBuffer aFilePath(rManager.getDirectory(nDir));
453 aFilePath.append('/').append(aFile);
454 struct stat aStat;
455 if( stat( aFilePath.getStr(), &aStat ) ||
456 ! S_ISREG( aStat.st_mode ) ||
457 aStat.st_size < 16 )
459 bObsolete = true;
461 #if OSL_DEBUG_LEVEL > 2
462 else
463 fprintf( stderr, "keeping file %s in outdated cache entry due to user override\n",
464 aFilePath.getStr() );
465 #endif
467 else
468 bObsolete = true;
470 if( bObsolete )
472 m_bDoFlush = true;
473 #if OSL_DEBUG_LEVEL > 2
474 fprintf( stderr, "removing obsolete font %s\n", aFile.getStr() );
475 #endif
476 delete pFont;
477 continue;
480 FontCacheEntry& rEntry = (*pDir)[aFile].m_aEntry;
481 rEntry.push_back( pFont );
484 } while( ! aStream.IsEof() );
488 * FontCache::copyPrintFont
490 void FontCache::copyPrintFont( const PrintFontManager::PrintFont* pFrom, PrintFontManager::PrintFont* pTo ) const
492 if( pFrom->m_eType != pTo->m_eType )
493 return;
494 switch( pFrom->m_eType )
496 case fonttype::TrueType:
497 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nDirectory;
498 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_aFontFile;
499 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nCollectionEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nCollectionEntry;
500 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nTypeFlags = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nTypeFlags;
501 break;
502 case fonttype::Type1:
503 static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_nDirectory;
504 static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aFontFile;
505 static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aMetricFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aMetricFile;
506 break;
507 case fonttype::Builtin:
508 static_cast<PrintFontManager::BuiltinFont*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::BuiltinFont*>(pFrom)->m_nDirectory;
509 static_cast<PrintFontManager::BuiltinFont*>(pTo)->m_aMetricFile = static_cast<const PrintFontManager::BuiltinFont*>(pFrom)->m_aMetricFile;
510 break;
511 default: break;
513 pTo->m_nFamilyName = pFrom->m_nFamilyName;
514 pTo->m_aStyleName = pFrom->m_aStyleName;
515 pTo->m_aAliases = pFrom->m_aAliases;
516 pTo->m_nPSName = pFrom->m_nPSName;
517 pTo->m_eItalic = pFrom->m_eItalic;
518 pTo->m_eWeight = pFrom->m_eWeight;
519 pTo->m_eWidth = pFrom->m_eWidth;
520 pTo->m_ePitch = pFrom->m_ePitch;
521 pTo->m_aEncoding = pFrom->m_aEncoding;
522 pTo->m_aGlobalMetricX = pFrom->m_aGlobalMetricX;
523 pTo->m_aGlobalMetricY = pFrom->m_aGlobalMetricY;
524 pTo->m_nAscend = pFrom->m_nAscend;
525 pTo->m_nDescend = pFrom->m_nDescend;
526 pTo->m_nLeading = pFrom->m_nLeading;
527 pTo->m_nXMin = pFrom->m_nXMin;
528 pTo->m_nYMin = pFrom->m_nYMin;
529 pTo->m_nXMax = pFrom->m_nXMax;
530 pTo->m_nYMax = pFrom->m_nYMax;
531 pTo->m_bHaveVerticalSubstitutedGlyphs = pFrom->m_bHaveVerticalSubstitutedGlyphs;
532 pTo->m_bUserOverride = pFrom->m_bUserOverride;
536 * FontCache::equalsPrintFont
538 bool FontCache::equalsPrintFont( const PrintFontManager::PrintFont* pLeft, PrintFontManager::PrintFont* pRight ) const
540 if( pLeft->m_eType != pRight->m_eType )
541 return false;
542 switch( pLeft->m_eType )
544 case fonttype::TrueType:
546 const PrintFontManager::TrueTypeFontFile* pLT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pLeft);
547 const PrintFontManager::TrueTypeFontFile* pRT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pRight);
548 if( pRT->m_nDirectory != pLT->m_nDirectory ||
549 pRT->m_aFontFile != pLT->m_aFontFile ||
550 pRT->m_nCollectionEntry != pLT->m_nCollectionEntry ||
551 pRT->m_nTypeFlags != pLT->m_nTypeFlags )
552 return false;
554 break;
555 case fonttype::Type1:
557 const PrintFontManager::Type1FontFile* pLT = static_cast<const PrintFontManager::Type1FontFile*>(pLeft);
558 const PrintFontManager::Type1FontFile* pRT = static_cast<const PrintFontManager::Type1FontFile*>(pRight);
559 if( pRT->m_nDirectory != pLT->m_nDirectory ||
560 pRT->m_aFontFile != pLT->m_aFontFile ||
561 pRT->m_aMetricFile != pLT->m_aMetricFile )
562 return false;
564 break;
565 case fonttype::Builtin:
567 const PrintFontManager::BuiltinFont* pLT = static_cast<const PrintFontManager::BuiltinFont*>(pLeft);
568 const PrintFontManager::BuiltinFont* pRT = static_cast<const PrintFontManager::BuiltinFont*>(pRight);
569 if( pRT->m_nDirectory != pLT->m_nDirectory ||
570 pRT->m_aMetricFile != pLT->m_aMetricFile )
571 return false;
573 break;
574 default: break;
576 if( pRight->m_nFamilyName != pLeft->m_nFamilyName ||
577 pRight->m_aStyleName != pLeft->m_aStyleName ||
578 pRight->m_nPSName != pLeft->m_nPSName ||
579 pRight->m_eItalic != pLeft->m_eItalic ||
580 pRight->m_eWeight != pLeft->m_eWeight ||
581 pRight->m_eWidth != pLeft->m_eWidth ||
582 pRight->m_ePitch != pLeft->m_ePitch ||
583 pRight->m_aEncoding != pLeft->m_aEncoding ||
584 pRight->m_aGlobalMetricX != pLeft->m_aGlobalMetricX ||
585 pRight->m_aGlobalMetricY != pLeft->m_aGlobalMetricY ||
586 pRight->m_nAscend != pLeft->m_nAscend ||
587 pRight->m_nDescend != pLeft->m_nDescend ||
588 pRight->m_nLeading != pLeft->m_nLeading ||
589 pRight->m_nXMin != pLeft->m_nXMin ||
590 pRight->m_nYMin != pLeft->m_nYMin ||
591 pRight->m_nXMax != pLeft->m_nXMax ||
592 pRight->m_nYMax != pLeft->m_nYMax ||
593 pRight->m_bHaveVerticalSubstitutedGlyphs != pLeft->m_bHaveVerticalSubstitutedGlyphs ||
594 pRight->m_bUserOverride != pLeft->m_bUserOverride
596 return false;
597 std::list< int >::const_iterator lit, rit;
598 for( lit = pLeft->m_aAliases.begin(), rit = pRight->m_aAliases.begin();
599 lit != pLeft->m_aAliases.end() && rit != pRight->m_aAliases.end() && (*lit) == (*rit);
600 ++lit, ++rit )
602 return lit == pLeft->m_aAliases.end() && rit == pRight->m_aAliases.end();
606 * FontCache::clonePrintFont
608 PrintFontManager::PrintFont* FontCache::clonePrintFont( const PrintFontManager::PrintFont* pOldFont ) const
610 PrintFontManager::PrintFont* pFont = NULL;
611 switch( pOldFont->m_eType )
613 case fonttype::TrueType:
614 pFont = new PrintFontManager::TrueTypeFontFile();
615 break;
616 case fonttype::Type1:
617 pFont = new PrintFontManager::Type1FontFile();
618 break;
619 case fonttype::Builtin:
620 pFont = new PrintFontManager::BuiltinFont();
621 break;
622 default: break;
624 if( pFont )
626 copyPrintFont( pOldFont, pFont );
628 return pFont;
632 * FontCache::getFontCacheFile
634 bool FontCache::getFontCacheFile( int nDirID, const OString& rFile, list< PrintFontManager::PrintFont* >& rNewFonts ) const
636 bool bSuccess = false;
638 FontCacheData::const_iterator dir = m_aCache.find( nDirID );
639 if( dir != m_aCache.end() )
641 FontDirMap::const_iterator entry = dir->second.m_aEntries.find( rFile );
642 if( entry != dir->second.m_aEntries.end() )
644 for( FontCacheEntry::const_iterator font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
646 bSuccess = true;
647 PrintFontManager::PrintFont* pFont = clonePrintFont( *font );
648 rNewFonts.push_back( pFont );
652 return bSuccess;
656 * FontCache::updateFontCacheEntry
658 void FontCache::updateFontCacheEntry( const PrintFontManager::PrintFont* pFont, bool bFlush )
660 OString aFile;
661 int nDirID = 0;
662 switch( pFont->m_eType )
664 case fonttype::TrueType:
665 nDirID = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory;
666 aFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile;
667 break;
668 case fonttype::Type1:
669 nDirID = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory;
670 aFile = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile;
671 break;
672 case fonttype::Builtin:
673 nDirID = static_cast<const PrintFontManager::BuiltinFont*>(pFont)->m_nDirectory;
674 aFile = static_cast<const PrintFontManager::BuiltinFont*>(pFont)->m_aMetricFile;
675 break;
676 default:
677 return;
679 FontCacheData::const_iterator dir = m_aCache.find( nDirID );
680 FontDirMap::const_iterator entry;
681 FontCacheEntry::const_iterator font;
682 PrintFontManager::PrintFont* pCacheFont = NULL;
684 if( dir != m_aCache.end() )
686 entry = dir->second.m_aEntries.find( aFile );
687 if( entry != dir->second.m_aEntries.end() )
689 for( font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
691 if( (*font)->m_eType == pFont->m_eType &&
692 ( (*font)->m_eType != fonttype::TrueType ||
693 static_cast<const PrintFontManager::TrueTypeFontFile*>(*font)->m_nCollectionEntry == static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry
695 break;
697 if( font != entry->second.m_aEntry.end() )
698 pCacheFont = *font;
701 else
702 createCacheDir( nDirID );
704 if( pCacheFont )
706 if( ! equalsPrintFont( pFont, pCacheFont ) )
708 copyPrintFont( pFont, pCacheFont );
709 m_bDoFlush = true;
712 else
714 pCacheFont = clonePrintFont( pFont );
715 m_aCache[nDirID].m_aEntries[aFile].m_aEntry.push_back( pCacheFont );
716 m_bDoFlush = true;
718 if( bFlush )
719 flush();
723 * FontCache::listDirectory
725 bool FontCache::listDirectory( const OString& rDir, std::list< PrintFontManager::PrintFont* >& rNewFonts ) const
727 PrintFontManager& rManager( PrintFontManager::get() );
728 int nDirID = rManager.getDirectoryAtom( rDir );
730 FontCacheData::const_iterator dir = m_aCache.find( nDirID );
731 bool bFound = (dir != m_aCache.end());
733 if( bFound && !dir->second.m_bNoFiles )
735 for( FontDirMap::const_iterator file = dir->second.m_aEntries.begin(); file != dir->second.m_aEntries.end(); ++file )
737 for( FontCacheEntry::const_iterator font = file->second.m_aEntry.begin(); font != file->second.m_aEntry.end(); ++font )
739 PrintFontManager::PrintFont* pFont = clonePrintFont( *font );
740 rNewFonts.push_back( pFont );
744 return bFound;
748 * FontCache::listDirectory
750 bool FontCache::scanAdditionalFiles( const OString& rDir )
752 PrintFontManager& rManager( PrintFontManager::get() );
753 int nDirID = rManager.getDirectoryAtom( rDir );
754 FontCacheData::const_iterator dir = m_aCache.find( nDirID );
755 bool bFound = (dir != m_aCache.end());
757 return (bFound && dir->second.m_bUserOverrideOnly);
761 * FontCache::createCacheDir
763 void FontCache::createCacheDir( int nDirID )
765 PrintFontManager& rManager( PrintFontManager::get() );
767 const OString& rDir = rManager.getDirectory( nDirID );
768 struct stat aStat;
769 if( ! stat( rDir.getStr(), &aStat ) )
770 m_aCache[nDirID].m_nTimestamp = (sal_Int64)aStat.st_mtime;
774 * FontCache::markEmptyDir
776 void FontCache::markEmptyDir( int nDirID, bool bNoFiles )
778 createCacheDir( nDirID );
779 m_aCache[nDirID].m_bNoFiles = bNoFiles;
780 m_bDoFlush = true;
783 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */