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