merge the formfield patch from ooo-build
[ooovba.git] / vcl / unx / source / fontmanager / fontcache.cxx
blob3a2eb60dd5a0fe4eff75f088051d9b5815373113
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fontcache.cxx,v $
11 * This file is part of OpenOffice.org.
13 * OpenOffice.org is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License version 3
15 * only, as published by the Free Software Foundation.
17 * OpenOffice.org is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License version 3 for more details
21 * (a copy is included in the LICENSE file that accompanied this code).
23 * You should have received a copy of the GNU Lesser General Public License
24 * version 3 along with OpenOffice.org. If not, see
25 * <http://www.openoffice.org/license.html>
26 * for a copy of the LGPLv3 License.
28 ************************************************************************/
30 // MARKER(update_precomp.py): autogen include statement, do not remove
31 #include "precompiled_vcl.hxx"
33 #include <cstdlib>
34 #include <cstring>
36 #include "vcl/fontcache.hxx"
38 #include "osl/thread.h"
40 #include "unotools/atom.hxx"
42 #include "tools/stream.hxx"
44 #include <unistd.h>
45 #include <sys/stat.h>
47 #if OSL_DEBUG_LEVEL >1
48 #include <cstdio>
49 #endif
51 #define FONTCACHEFILE "/user/psprint/pspfontcache"
52 #define CACHE_MAGIC "PspFontCacheFile format 4"
54 using namespace std;
55 using namespace rtl;
56 using namespace psp;
57 using namespace utl;
60 * static helpers
64 * FontCache constructor
67 FontCache::FontCache()
69 m_bDoFlush = false;
70 m_aCacheFile = getOfficePath( UserPath );
71 if( m_aCacheFile.Len() )
73 m_aCacheFile.AppendAscii( FONTCACHEFILE );
74 read();
79 * FontCache destructor
82 FontCache::~FontCache()
84 clearCache();
88 * FontCache::clearCache
90 void FontCache::clearCache()
92 for( FontCacheData::iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++dir_it )
94 for( FontDirMap::iterator entry_it = dir_it->second.m_aEntries.begin(); entry_it != dir_it->second.m_aEntries.end(); ++entry_it )
96 for( FontCacheEntry::iterator font_it = entry_it->second.m_aEntry.begin(); font_it != entry_it->second.m_aEntry.end(); ++font_it )
97 delete *font_it;
100 m_aCache.clear();
104 * FontCache::Commit
107 void FontCache::flush()
109 if( ! m_bDoFlush || ! m_aCacheFile.Len() )
110 return;
112 SvFileStream aStream;
113 aStream.Open( m_aCacheFile, STREAM_WRITE | STREAM_TRUNC );
114 if( ! (aStream.IsOpen() && aStream.IsWritable()) )
116 #if OSL_DEBUG_LEVEL > 1
117 fprintf( stderr, "FontCache::flush: opening cache file %s failed\n", ByteString( m_aCacheFile, osl_getThreadTextEncoding() ).GetBuffer() );
118 #endif
119 return;
122 aStream.SetLineDelimiter( LINEEND_LF );
123 aStream.WriteLine( ByteString( CACHE_MAGIC ) );
125 PrintFontManager& rManager( PrintFontManager::get() );
126 MultiAtomProvider* pAtoms = rManager.m_pAtoms;
128 for( FontCacheData::const_iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++ dir_it )
130 const FontDirMap& rDir( dir_it->second.m_aEntries );
132 ByteString aDirectory( rManager.getDirectory( dir_it->first ) );
133 ByteString aLine( "FontCacheDirectory:" );
134 aLine.Append( ByteString::CreateFromInt64( dir_it->second.m_nTimestamp ) );
135 aLine.Append( ':' );
136 aLine.Append( aDirectory );
137 if( rDir.empty() && dir_it->second.m_bNoFiles )
138 aLine.Insert( "Empty", 0 );
139 aStream.WriteLine( aLine );
141 for( FontDirMap::const_iterator entry_it = rDir.begin(); entry_it != rDir.end(); ++entry_it )
143 // insert cache entries
144 const FontCacheEntry& rEntry( entry_it->second.m_aEntry );
145 if( rEntry.begin() == rEntry.end() )
146 continue;
148 aLine = "File:";
149 aLine.Append( ByteString( entry_it->first ) );
150 aStream.WriteLine( aLine );
152 int nEntrySize = entry_it->second.m_aEntry.size();
153 // write: type;nfonts
154 aLine = ByteString::CreateFromInt32( rEntry.front()->m_eType );
155 aLine.Append( ';' );
156 aLine.Append( ByteString::CreateFromInt32( nEntrySize ) );
157 aStream.WriteLine( aLine );
159 sal_Int32 nSubEntry = 0;
160 for( FontCacheEntry::const_iterator it = rEntry.begin(); it != rEntry.end(); ++it, nSubEntry++ )
163 * for each font entry write:
164 * name[;name[;name]]
165 * fontnr;PSName;italic;weight;width;pitch;encoding;ascend;descend;leading;vsubst;gxw;gxh;gyw;gyh;useroverrride;embed;antialias[;{metricfile,typeflags}][;stylename]
167 if( nEntrySize > 1 )
168 nSubEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nCollectionEntry;
169 else
170 nSubEntry = -1;
172 aLine = OUStringToOString( pAtoms->getString( ATOM_FAMILYNAME, (*it)->m_nFamilyName ), RTL_TEXTENCODING_UTF8 );
173 for( ::std::list< int >::const_iterator name_it = (*it)->m_aAliases.begin(); name_it != (*it)->m_aAliases.end(); ++name_it )
175 const OUString& rAdd( pAtoms->getString( ATOM_FAMILYNAME, *name_it ) );
176 if( rAdd.getLength() )
178 aLine.Append( ';' );
179 aLine.Append( ByteString( String( rAdd ), RTL_TEXTENCODING_UTF8 ) );
182 aStream.WriteLine( aLine );
184 const OUString& rPSName( pAtoms->getString( ATOM_PSNAME, (*it)->m_nPSName ) );
185 aLine = ByteString::CreateFromInt32( nSubEntry );
186 aLine.Append( ';' );
187 aLine.Append( ByteString( String( rPSName ), RTL_TEXTENCODING_UTF8 ) );
188 aLine.Append( ';' );
189 aLine.Append( ByteString::CreateFromInt32( (*it)->m_eItalic ) );
190 aLine.Append( ';' );
191 aLine.Append( ByteString::CreateFromInt32( (*it)->m_eWeight ) );
192 aLine.Append( ';' );
193 aLine.Append( ByteString::CreateFromInt32( (*it)->m_eWidth ) );
194 aLine.Append( ';' );
195 aLine.Append( ByteString::CreateFromInt32( (*it)->m_ePitch ) );
196 aLine.Append( ';' );
197 aLine.Append( ByteString::CreateFromInt32( (*it)->m_aEncoding ) );
198 aLine.Append( ';' );
199 aLine.Append( ByteString::CreateFromInt32( (*it)->m_nAscend ) );
200 aLine.Append( ';' );
201 aLine.Append( ByteString::CreateFromInt32( (*it)->m_nDescend ) );
202 aLine.Append( ';' );
203 aLine.Append( ByteString::CreateFromInt32( (*it)->m_nLeading ) );
204 aLine.Append( ';' );
205 aLine.Append( (*it)->m_bHaveVerticalSubstitutedGlyphs ? "1" : "0" );
206 aLine.Append( ';' );
207 aLine.Append( ByteString::CreateFromInt32( (*it)->m_aGlobalMetricX.width ) );
208 aLine.Append( ';' );
209 aLine.Append( ByteString::CreateFromInt32( (*it)->m_aGlobalMetricX.height ) );
210 aLine.Append( ';' );
211 aLine.Append( ByteString::CreateFromInt32( (*it)->m_aGlobalMetricY.width ) );
212 aLine.Append( ';' );
213 aLine.Append( ByteString::CreateFromInt32( (*it)->m_aGlobalMetricY.height ) );
214 aLine.Append( ';' );
215 aLine.Append( (*it)->m_bUserOverride ? "1" : "0" );
216 aLine.Append( ';' );
217 aLine.Append( ByteString::CreateFromInt32( (*it)->m_eEmbeddedbitmap ) );
218 aLine.Append( ';' );
219 aLine.Append( ByteString::CreateFromInt32( (*it)->m_eAntialias ) );
221 switch( (*it)->m_eType )
223 case fonttype::Type1:
224 aLine.Append( ';' );
225 aLine.Append( ByteString( static_cast<const PrintFontManager::Type1FontFile*>(*it)->m_aMetricFile ) );
226 break;
227 case fonttype::TrueType:
228 aLine.Append( ';' );
229 aLine.Append( ByteString::CreateFromInt32( static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nTypeFlags ) );
230 break;
231 default: break;
233 if( (*it)->m_aStyleName.getLength() )
235 aLine.Append( ';' );
236 aLine.Append( ByteString( String( (*it)->m_aStyleName ), RTL_TEXTENCODING_UTF8 ) );
238 aStream.WriteLine( aLine );
240 aStream.WriteLine( ByteString() );
243 m_bDoFlush = false;
247 * FontCache::read
250 void FontCache::read()
252 PrintFontManager& rManager( PrintFontManager::get() );
253 MultiAtomProvider* pAtoms = rManager.m_pAtoms;
255 SvFileStream aStream( m_aCacheFile, STREAM_READ );
256 if( ! aStream.IsOpen() )
258 #if OSL_DEBUG_LEVEL > 1
259 fprintf( stderr, "FontCache::read: opening cache file %s failed\n", ByteString( m_aCacheFile, osl_getThreadTextEncoding() ).GetBuffer() );
260 #endif
261 return;
265 ByteString aLine;
266 aStream.ReadLine( aLine );
267 if( !aLine.Equals( CACHE_MAGIC ) )
269 #if OSL_DEBUG_LEVEL >1
270 fprintf( stderr, "FontCache::read: cache file %s fails magic test\n", ByteString( m_aCacheFile, osl_getThreadTextEncoding() ).GetBuffer() );
271 #endif
272 return;
275 int nDir = 0;
276 FontDirMap* pDir = NULL;
277 xub_StrLen nIndex;
278 bool bKeepOnlyUserOverridden = false;
281 aStream.ReadLine( aLine );
282 if( aLine.CompareTo( "FontCacheDirectory:", 19 ) == COMPARE_EQUAL ||
283 aLine.CompareTo( "EmptyFontCacheDirectory:", 24 ) == COMPARE_EQUAL )
285 bool bEmpty = (aLine.CompareTo( "Empty", 5 ) == COMPARE_EQUAL);
286 xub_StrLen nSearchIndex = bEmpty ? 24 : 19;
288 OString aDir;
289 sal_Int64 nTimestamp = 0;
290 xub_StrLen nTEnd = aLine.Search( ':', nSearchIndex );
291 if( nTEnd != STRING_NOTFOUND )
293 nTimestamp = aLine.Copy( nSearchIndex, nTEnd - nSearchIndex ).ToInt64();
294 aDir = aLine.Copy( nTEnd+1 );
296 else
298 // invalid format, remove
299 pDir = NULL;
300 nDir = 0;
301 m_bDoFlush = true;
302 continue;
305 // is the directory modified ?
306 struct stat aStat;
307 if( stat( aDir.getStr(), &aStat ) ||
308 ! S_ISDIR(aStat.st_mode) )
310 // remove outdated cache data
311 pDir = NULL;
312 nDir = 0;
313 m_bDoFlush = true;
314 continue;
316 else
318 nDir = rManager.getDirectoryAtom( aDir, true );
319 m_aCache[ nDir ].m_nTimestamp = (sal_Int64)aStat.st_mtime;
320 m_aCache[ nDir ].m_bNoFiles = bEmpty;
321 pDir = bEmpty ? NULL : &m_aCache[ nDir ].m_aEntries;
322 bKeepOnlyUserOverridden = ((sal_Int64)aStat.st_mtime != nTimestamp);
323 m_aCache[ nDir ].m_bUserOverrideOnly = bKeepOnlyUserOverridden;
326 else if( pDir && aLine.CompareTo( "File:", 5 ) == COMPARE_EQUAL )
328 OString aFile( aLine.Copy( 5 ) );
329 aStream.ReadLine( aLine );
331 const char* pLine = aLine.GetBuffer();
333 fonttype::type eType = (fonttype::type)atoi( pLine );
334 if( eType != fonttype::TrueType &&
335 eType != fonttype::Type1 &&
336 eType != fonttype::Builtin
338 continue;
339 while( *pLine && *pLine != ';' )
340 pLine++;
341 if( *pLine != ';' )
342 continue;
344 pLine++;
345 sal_Int32 nFonts = atoi( pLine );
346 for( int n = 0; n < nFonts; n++ )
348 aStream.ReadLine( aLine );
349 pLine = aLine.GetBuffer();
350 int nLen = aLine.Len();
352 PrintFontManager::PrintFont* pFont = NULL;
353 switch( eType )
355 case fonttype::TrueType:
356 pFont = new PrintFontManager::TrueTypeFontFile();
357 break;
358 case fonttype::Type1:
359 pFont = new PrintFontManager::Type1FontFile();
360 break;
361 case fonttype::Builtin:
362 pFont = new PrintFontManager::BuiltinFont();
363 break;
364 default: break;
367 for( nIndex = 0; nIndex < nLen && pLine[nIndex] != ';'; nIndex++ )
370 pFont->m_nFamilyName = pAtoms->getAtom( ATOM_FAMILYNAME,
371 OUString( pLine, nIndex, RTL_TEXTENCODING_UTF8 ),
372 sal_True );
373 while( nIndex < nLen )
375 xub_StrLen nLastIndex = nIndex+1;
376 for( nIndex = nLastIndex ; nIndex < nLen && pLine[nIndex] != ';'; nIndex++ )
378 if( nIndex - nLastIndex > 1 )
380 OUString aAlias( pLine+nLastIndex, nIndex-nLastIndex-1, RTL_TEXTENCODING_UTF8 );
381 pFont->m_aAliases.push_back( pAtoms->getAtom( ATOM_FAMILYNAME, aAlias, sal_True ) );
384 aStream.ReadLine( aLine );
385 pLine = aLine.GetBuffer();
386 nLen = aLine.Len();
388 // get up to 20 token positions
389 const int nMaxTokens = 20;
390 int nTokenPos[nMaxTokens];
391 nTokenPos[0] = 0;
392 int nTokens = 1;
393 for( int i = 0; i < nLen; i++ )
395 if( pLine[i] == ';' )
397 nTokenPos[nTokens++] = i+1;
398 if( nTokens == nMaxTokens )
399 break;
402 if( nTokens < 18 )
404 delete pFont;
405 continue;
407 int nCollEntry = atoi( pLine );
408 pFont->m_nPSName = pAtoms->getAtom( ATOM_PSNAME, OUString( pLine + nTokenPos[1], nTokenPos[2]-nTokenPos[1]-1, RTL_TEXTENCODING_UTF8 ), sal_True );
409 pFont->m_eItalic = (italic::type)atoi( pLine+nTokenPos[2] );
410 pFont->m_eWeight = (weight::type)atoi( pLine+nTokenPos[3] );
411 pFont->m_eWidth = (width::type)atoi( pLine+nTokenPos[4] );
412 pFont->m_ePitch = (pitch::type)atoi( pLine+nTokenPos[5] );
413 pFont->m_aEncoding = (rtl_TextEncoding)atoi( pLine+nTokenPos[6] );
414 pFont->m_nAscend = atoi( pLine + nTokenPos[7] );
415 pFont->m_nDescend = atoi( pLine + nTokenPos[8] );
416 pFont->m_nLeading = atoi( pLine + nTokenPos[9] );
417 pFont->m_bHaveVerticalSubstitutedGlyphs
418 = (atoi( pLine + nTokenPos[10] ) != 0);
419 pFont->m_aGlobalMetricX.width
420 = atoi( pLine + nTokenPos[11] );
421 pFont->m_aGlobalMetricX.height
422 = atoi( pLine + nTokenPos[12] );
423 pFont->m_aGlobalMetricY.width
424 = atoi( pLine + nTokenPos[13] );
425 pFont->m_aGlobalMetricY.height
426 = atoi( pLine + nTokenPos[14] );
427 pFont->m_bUserOverride
428 = (atoi( pLine + nTokenPos[15] ) != 0);
429 pFont->m_eEmbeddedbitmap
430 = (fcstatus::type)atoi(pLine+nTokenPos[16]);
431 pFont->m_eAntialias = (fcstatus::type)atoi(pLine+nTokenPos[17]);
432 int nStyleTokenNr = 18;
433 switch( eType )
435 case fonttype::TrueType:
436 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nTypeFlags = atoi( pLine + nTokenPos[18] );
437 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry = nCollEntry;
438 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory = nDir;
439 static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile = aFile;
440 nStyleTokenNr++;
441 break;
442 case fonttype::Type1:
444 int nTokLen = (nTokens > 19 ) ? nTokenPos[19]-nTokenPos[18]-1 : nLen - nTokenPos[18];
445 static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aMetricFile = OString( pLine + nTokenPos[18], nTokLen );
446 static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory = nDir;
447 static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile = aFile;
448 nStyleTokenNr++;
450 break;
451 case fonttype::Builtin:
452 static_cast<PrintFontManager::BuiltinFont*>(pFont)->m_nDirectory = nDir;
453 static_cast<PrintFontManager::BuiltinFont*>(pFont)->m_aMetricFile = aFile;
454 break;
455 default: break;
457 if( nTokens > nStyleTokenNr )
458 pFont->m_aStyleName = OUString::intern( pLine + nTokenPos[nStyleTokenNr],
459 nLen - nTokenPos[nStyleTokenNr],
460 RTL_TEXTENCODING_UTF8 );
462 bool bObsolete = false;
463 if( bKeepOnlyUserOverridden )
465 if( pFont->m_bUserOverride )
467 ByteString aFilePath = rManager.getDirectory( nDir );
468 aFilePath.Append( '/' );
469 aFilePath.Append( ByteString(aFile) );
470 struct stat aStat;
471 if( stat( aFilePath.GetBuffer(), &aStat ) ||
472 ! S_ISREG( aStat.st_mode ) ||
473 aStat.st_size < 16 )
475 bObsolete = true;
477 #if OSL_DEBUG_LEVEL > 2
478 else
479 fprintf( stderr, "keeping file %s in outdated cache entry due to user override\n",
480 aFilePath.GetBuffer() );
481 #endif
483 else
484 bObsolete = true;
486 if( bObsolete )
488 m_bDoFlush = true;
489 #if OSL_DEBUG_LEVEL > 2
490 fprintf( stderr, "removing obsolete font %s\n", aFile.getStr() );
491 #endif
492 delete pFont;
493 continue;
496 FontCacheEntry& rEntry = (*pDir)[aFile].m_aEntry;
497 rEntry.push_back( pFont );
500 } while( ! aStream.IsEof() );
504 * FontCache::updateDirTimestamp
506 void FontCache::updateDirTimestamp( int nDirID )
508 PrintFontManager& rManager( PrintFontManager::get() );
509 const OString& rDir = rManager.getDirectory( nDirID );
511 struct stat aStat;
512 if( ! stat( rDir.getStr(), &aStat ) )
513 m_aCache[ nDirID ].m_nTimestamp = (sal_Int64)aStat.st_mtime;
518 * FontCache::copyPrintFont
520 void FontCache::copyPrintFont( const PrintFontManager::PrintFont* pFrom, PrintFontManager::PrintFont* pTo ) const
522 if( pFrom->m_eType != pTo->m_eType )
523 return;
524 switch( pFrom->m_eType )
526 case fonttype::TrueType:
527 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nDirectory;
528 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_aFontFile;
529 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nCollectionEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nCollectionEntry;
530 static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nTypeFlags = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nTypeFlags;
531 break;
532 case fonttype::Type1:
533 static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_nDirectory;
534 static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aFontFile;
535 static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aMetricFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aMetricFile;
536 break;
537 case fonttype::Builtin:
538 static_cast<PrintFontManager::BuiltinFont*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::BuiltinFont*>(pFrom)->m_nDirectory;
539 static_cast<PrintFontManager::BuiltinFont*>(pTo)->m_aMetricFile = static_cast<const PrintFontManager::BuiltinFont*>(pFrom)->m_aMetricFile;
540 break;
541 default: break;
543 pTo->m_nFamilyName = pFrom->m_nFamilyName;
544 pTo->m_aStyleName = pFrom->m_aStyleName;
545 pTo->m_aAliases = pFrom->m_aAliases;
546 pTo->m_nPSName = pFrom->m_nPSName;
547 pTo->m_eItalic = pFrom->m_eItalic;
548 pTo->m_eWeight = pFrom->m_eWeight;
549 pTo->m_eWidth = pFrom->m_eWidth;
550 pTo->m_ePitch = pFrom->m_ePitch;
551 pTo->m_aEncoding = pFrom->m_aEncoding;
552 pTo->m_aGlobalMetricX = pFrom->m_aGlobalMetricX;
553 pTo->m_aGlobalMetricY = pFrom->m_aGlobalMetricY;
554 pTo->m_nAscend = pFrom->m_nAscend;
555 pTo->m_nDescend = pFrom->m_nDescend;
556 pTo->m_nLeading = pFrom->m_nLeading;
557 pTo->m_nXMin = pFrom->m_nXMin;
558 pTo->m_nYMin = pFrom->m_nYMin;
559 pTo->m_nXMax = pFrom->m_nXMax;
560 pTo->m_nYMax = pFrom->m_nYMax;
561 pTo->m_bHaveVerticalSubstitutedGlyphs = pFrom->m_bHaveVerticalSubstitutedGlyphs;
562 pTo->m_bUserOverride = pFrom->m_bUserOverride;
563 pTo->m_eEmbeddedbitmap = pFrom->m_eEmbeddedbitmap;
564 pTo->m_eAntialias = pFrom->m_eAntialias;
568 * FontCache::equalsPrintFont
570 bool FontCache::equalsPrintFont( const PrintFontManager::PrintFont* pLeft, PrintFontManager::PrintFont* pRight ) const
572 if( pLeft->m_eType != pRight->m_eType )
573 return false;
574 switch( pLeft->m_eType )
576 case fonttype::TrueType:
578 const PrintFontManager::TrueTypeFontFile* pLT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pLeft);
579 const PrintFontManager::TrueTypeFontFile* pRT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pRight);
580 if( pRT->m_nDirectory != pLT->m_nDirectory ||
581 pRT->m_aFontFile != pLT->m_aFontFile ||
582 pRT->m_nCollectionEntry != pLT->m_nCollectionEntry ||
583 pRT->m_nTypeFlags != pLT->m_nTypeFlags )
584 return false;
586 break;
587 case fonttype::Type1:
589 const PrintFontManager::Type1FontFile* pLT = static_cast<const PrintFontManager::Type1FontFile*>(pLeft);
590 const PrintFontManager::Type1FontFile* pRT = static_cast<const PrintFontManager::Type1FontFile*>(pRight);
591 if( pRT->m_nDirectory != pLT->m_nDirectory ||
592 pRT->m_aFontFile != pLT->m_aFontFile ||
593 pRT->m_aMetricFile != pLT->m_aMetricFile )
594 return false;
596 break;
597 case fonttype::Builtin:
599 const PrintFontManager::BuiltinFont* pLT = static_cast<const PrintFontManager::BuiltinFont*>(pLeft);
600 const PrintFontManager::BuiltinFont* pRT = static_cast<const PrintFontManager::BuiltinFont*>(pRight);
601 if( pRT->m_nDirectory != pLT->m_nDirectory ||
602 pRT->m_aMetricFile != pLT->m_aMetricFile )
603 return false;
605 break;
606 default: break;
608 if( pRight->m_nFamilyName != pLeft->m_nFamilyName ||
609 pRight->m_aStyleName != pLeft->m_aStyleName ||
610 pRight->m_nPSName != pLeft->m_nPSName ||
611 pRight->m_eItalic != pLeft->m_eItalic ||
612 pRight->m_eWeight != pLeft->m_eWeight ||
613 pRight->m_eWidth != pLeft->m_eWidth ||
614 pRight->m_ePitch != pLeft->m_ePitch ||
615 pRight->m_aEncoding != pLeft->m_aEncoding ||
616 pRight->m_aGlobalMetricX != pLeft->m_aGlobalMetricX ||
617 pRight->m_aGlobalMetricY != pLeft->m_aGlobalMetricY ||
618 pRight->m_nAscend != pLeft->m_nAscend ||
619 pRight->m_nDescend != pLeft->m_nDescend ||
620 pRight->m_nLeading != pLeft->m_nLeading ||
621 pRight->m_nXMin != pLeft->m_nXMin ||
622 pRight->m_nYMin != pLeft->m_nYMin ||
623 pRight->m_nXMax != pLeft->m_nXMax ||
624 pRight->m_nYMax != pLeft->m_nYMax ||
625 pRight->m_bHaveVerticalSubstitutedGlyphs != pLeft->m_bHaveVerticalSubstitutedGlyphs ||
626 pRight->m_bUserOverride != pLeft->m_bUserOverride ||
627 pRight->m_eEmbeddedbitmap != pLeft->m_eEmbeddedbitmap ||
628 pRight->m_eAntialias != pLeft->m_eAntialias
630 return false;
631 std::list< int >::const_iterator lit, rit;
632 for( lit = pLeft->m_aAliases.begin(), rit = pRight->m_aAliases.begin();
633 lit != pLeft->m_aAliases.end() && rit != pRight->m_aAliases.end() && (*lit) == (*rit);
634 ++lit, ++rit )
636 return lit == pLeft->m_aAliases.end() && rit == pRight->m_aAliases.end();
640 * FontCache::clonePrintFont
642 PrintFontManager::PrintFont* FontCache::clonePrintFont( const PrintFontManager::PrintFont* pOldFont ) const
644 PrintFontManager::PrintFont* pFont = NULL;
645 switch( pOldFont->m_eType )
647 case fonttype::TrueType:
648 pFont = new PrintFontManager::TrueTypeFontFile();
649 break;
650 case fonttype::Type1:
651 pFont = new PrintFontManager::Type1FontFile();
652 break;
653 case fonttype::Builtin:
654 pFont = new PrintFontManager::BuiltinFont();
655 break;
656 default: break;
658 if( pFont )
660 copyPrintFont( pOldFont, pFont );
662 return pFont;
666 * FontCache::getFontCacheFile
668 bool FontCache::getFontCacheFile( int nDirID, const OString& rFile, list< PrintFontManager::PrintFont* >& rNewFonts ) const
670 bool bSuccess = false;
672 FontCacheData::const_iterator dir = m_aCache.find( nDirID );
673 if( dir != m_aCache.end() )
675 FontDirMap::const_iterator entry = dir->second.m_aEntries.find( rFile );
676 if( entry != dir->second.m_aEntries.end() )
678 for( FontCacheEntry::const_iterator font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
680 bSuccess = true;
681 PrintFontManager::PrintFont* pFont = clonePrintFont( *font );
682 rNewFonts.push_back( pFont );
686 return bSuccess;
690 * FontCache::updateFontCacheEntry
692 void FontCache::updateFontCacheEntry( const PrintFontManager::PrintFont* pFont, bool bFlush )
694 PrintFontManager& rManager( PrintFontManager::get() );
696 OString aFile;
697 int nDirID = 0;
698 switch( pFont->m_eType )
700 case fonttype::TrueType:
701 nDirID = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory;
702 aFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile;
703 break;
704 case fonttype::Type1:
705 nDirID = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory;
706 aFile = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile;
707 break;
708 case fonttype::Builtin:
709 nDirID = static_cast<const PrintFontManager::BuiltinFont*>(pFont)->m_nDirectory;
710 aFile = static_cast<const PrintFontManager::BuiltinFont*>(pFont)->m_aMetricFile;
711 break;
712 default:
713 return;
715 FontCacheData::const_iterator dir = m_aCache.find( nDirID );
716 FontDirMap::const_iterator entry;
717 FontCacheEntry::const_iterator font;
718 PrintFontManager::PrintFont* pCacheFont = NULL;
720 if( dir != m_aCache.end() )
722 entry = dir->second.m_aEntries.find( aFile );
723 if( entry != dir->second.m_aEntries.end() )
725 for( font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
727 if( (*font)->m_eType == pFont->m_eType &&
728 ( (*font)->m_eType != fonttype::TrueType ||
729 static_cast<const PrintFontManager::TrueTypeFontFile*>(*font)->m_nCollectionEntry == static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry
731 break;
733 if( font != entry->second.m_aEntry.end() )
734 pCacheFont = *font;
737 else
738 createCacheDir( nDirID );
740 if( pCacheFont )
742 if( ! equalsPrintFont( pFont, pCacheFont ) )
744 copyPrintFont( pFont, pCacheFont );
745 m_bDoFlush = true;
748 else
750 pCacheFont = clonePrintFont( pFont );
751 m_aCache[nDirID].m_aEntries[aFile].m_aEntry.push_back( pCacheFont );
753 ByteString aPath = rManager.getDirectory( nDirID );
754 aPath.Append( '/' );
755 aPath.Append( ByteString( aFile ) );
756 m_bDoFlush = true;
758 if( bFlush )
759 flush();
763 * FontCache::listDirectory
765 bool FontCache::listDirectory( const OString& rDir, std::list< PrintFontManager::PrintFont* >& rNewFonts ) const
767 PrintFontManager& rManager( PrintFontManager::get() );
768 int nDirID = rManager.getDirectoryAtom( rDir );
769 FontCacheData::const_iterator dir = m_aCache.find( nDirID );
770 bool bFound = (dir != m_aCache.end());
772 if( bFound && !dir->second.m_bNoFiles )
774 for( FontDirMap::const_iterator file = dir->second.m_aEntries.begin(); file != dir->second.m_aEntries.end(); ++file )
776 for( FontCacheEntry::const_iterator font = file->second.m_aEntry.begin(); font != file->second.m_aEntry.end(); ++font )
778 PrintFontManager::PrintFont* pFont = clonePrintFont( *font );
779 rNewFonts.push_back( pFont );
783 return bFound;
787 * FontCache::listDirectory
789 bool FontCache::scanAdditionalFiles( const OString& rDir )
791 PrintFontManager& rManager( PrintFontManager::get() );
792 int nDirID = rManager.getDirectoryAtom( rDir );
793 FontCacheData::const_iterator dir = m_aCache.find( nDirID );
794 bool bFound = (dir != m_aCache.end());
796 return (bFound && dir->second.m_bUserOverrideOnly);
800 * FontCache::createCacheDir
802 void FontCache::createCacheDir( int nDirID )
804 PrintFontManager& rManager( PrintFontManager::get() );
806 const OString& rDir = rManager.getDirectory( nDirID );
807 struct stat aStat;
808 if( ! stat( rDir.getStr(), &aStat ) )
809 m_aCache[nDirID].m_nTimestamp = (sal_Int64)aStat.st_mtime;
813 * FontCache::markEmptyDir
815 void FontCache::markEmptyDir( int nDirID, bool bNoFiles )
817 createCacheDir( nDirID );
818 m_aCache[nDirID].m_bNoFiles = bNoFiles;
819 m_bDoFlush = true;