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
FontCache()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
~FontCache()76 FontCache::~FontCache()
77 {
78 clearCache();
79 }
80
81 /*
82 * FontCache::clearCache
83 */
clearCache()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
flush()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
read()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 */
updateDirTimestamp(int nDirID)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 */
copyPrintFont(const PrintFontManager::PrintFont * pFrom,PrintFontManager::PrintFont * pTo) const511 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 */
equalsPrintFont(const PrintFontManager::PrintFont * pLeft,PrintFontManager::PrintFont * pRight) const559 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 */
clonePrintFont(const PrintFontManager::PrintFont * pOldFont) const629 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 */
getFontCacheFile(int nDirID,const OString & rFile,list<PrintFontManager::PrintFont * > & rNewFonts) const655 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 */
updateFontCacheEntry(const PrintFontManager::PrintFont * pFont,bool bFlush)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 */
listDirectory(const OString & rDir,std::list<PrintFontManager::PrintFont * > & rNewFonts) const752 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 */
scanAdditionalFiles(const OString & rDir)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 */
createCacheDir(int nDirID)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 */
markEmptyDir(int nDirID,bool bNoFiles)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