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 : #include <cstdlib>
21 : #include <cstring>
22 :
23 : #include "fontcache.hxx"
24 :
25 : #include "osl/thread.h"
26 :
27 : #include "unotools/atom.hxx"
28 :
29 : #include "tools/stream.hxx"
30 :
31 : #include <rtl/strbuf.hxx>
32 :
33 : #include <unistd.h>
34 : #include <sys/stat.h>
35 :
36 : #if OSL_DEBUG_LEVEL >1
37 : #include <cstdio>
38 : #endif
39 :
40 : #define CACHE_MAGIC "LibreOffice PspFontCacheFile format 6"
41 :
42 : using namespace std;
43 : using namespace psp;
44 : using namespace utl;
45 :
46 : /*
47 : * FontCache constructor
48 : */
49 :
50 205 : FontCache::FontCache()
51 : {
52 205 : m_bDoFlush = false;
53 205 : m_aCacheFile = getOfficePath( UserPath );
54 205 : if( !m_aCacheFile.isEmpty() )
55 : {
56 205 : m_aCacheFile += "/user/psprint/pspfontcache";
57 205 : read();
58 : }
59 205 : }
60 :
61 : /*
62 : * FontCache destructor
63 : */
64 :
65 410 : FontCache::~FontCache()
66 : {
67 205 : clearCache();
68 205 : }
69 :
70 : /*
71 : * FontCache::clearCache
72 : */
73 205 : void FontCache::clearCache()
74 : {
75 2665 : for( FontCacheData::iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++dir_it )
76 : {
77 50430 : for( FontDirMap::iterator entry_it = dir_it->second.m_aEntries.begin(); entry_it != dir_it->second.m_aEntries.end(); ++entry_it )
78 : {
79 96145 : for( FontCacheEntry::iterator font_it = entry_it->second.m_aEntry.begin(); font_it != entry_it->second.m_aEntry.end(); ++font_it )
80 48175 : delete *font_it;
81 : }
82 : }
83 205 : m_aCache.clear();
84 205 : }
85 :
86 : /*
87 : * FontCache::Commit
88 : */
89 :
90 205 : void FontCache::flush()
91 : {
92 205 : if( ! m_bDoFlush || m_aCacheFile.isEmpty() )
93 294 : return;
94 :
95 58 : SvFileStream aStream;
96 58 : aStream.Open( m_aCacheFile, StreamMode::WRITE | StreamMode::TRUNC );
97 58 : if( ! (aStream.IsOpen() && aStream.IsWritable()) )
98 : {
99 : #if OSL_DEBUG_LEVEL > 1
100 : fprintf( stderr, "FontCache::flush: opening cache file %s failed\n", OUStringToOString(m_aCacheFile, osl_getThreadTextEncoding()).getStr() );
101 : #endif
102 0 : return;
103 : }
104 :
105 58 : aStream.SetLineDelimiter( LINEEND_LF );
106 58 : aStream.WriteLine( CACHE_MAGIC );
107 :
108 58 : PrintFontManager& rManager( PrintFontManager::get() );
109 58 : MultiAtomProvider* pAtoms = rManager.m_pAtoms;
110 :
111 754 : for( FontCacheData::const_iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++ dir_it )
112 : {
113 696 : const FontDirMap& rDir( dir_it->second.m_aEntries );
114 :
115 696 : OString aDirectory(rManager.getDirectory(dir_it->first));
116 1392 : OStringBuffer aLine("FontCacheDirectory:");
117 696 : aLine.append(dir_it->second.m_nTimestamp);
118 696 : aLine.append(':');
119 696 : aLine.append(aDirectory);
120 696 : if( rDir.empty() && dir_it->second.m_bNoFiles )
121 0 : aLine.insert(0, "Empty");
122 696 : aStream.WriteLine(aLine.makeStringAndClear());
123 :
124 14268 : for( FontDirMap::const_iterator entry_it = rDir.begin(); entry_it != rDir.end(); ++entry_it )
125 : {
126 : // insert cache entries
127 13572 : const FontCacheEntry& rEntry( entry_it->second.m_aEntry );
128 13572 : if( rEntry.begin() == rEntry.end() )
129 0 : continue;
130 :
131 13572 : aLine.append("File:");
132 13572 : aLine.append(entry_it->first);
133 13572 : aStream.WriteLine(aLine.makeStringAndClear());
134 :
135 13572 : int nEntrySize = entry_it->second.m_aEntry.size();
136 : // write: type;nfonts
137 13572 : aLine.append(static_cast<sal_Int32>(rEntry.front()->m_eType));
138 13572 : aLine.append(';');
139 13572 : aLine.append(static_cast<sal_Int32>(nEntrySize));
140 13572 : aStream.WriteLine(aLine.makeStringAndClear());
141 :
142 13572 : sal_Int32 nSubEntry = 0;
143 27202 : for( FontCacheEntry::const_iterator it = rEntry.begin(); it != rEntry.end(); ++it, nSubEntry++ )
144 : {
145 : /*
146 : * for each font entry write:
147 : * name[;name[;name]]
148 : * fontnr;PSName;italic;weight;width;pitch;encoding;ascend;descend;leading;vsubst;gxw;gxh;gyw;gyh;useroverrride;embed;antialias[;{metricfile,typeflags}][;stylename]
149 : */
150 13630 : if( nEntrySize > 1 )
151 116 : nSubEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nCollectionEntry;
152 : else
153 13514 : nSubEntry = 0;
154 :
155 13630 : aLine.append(OUStringToOString(pAtoms->getString( ATOM_FAMILYNAME, (*it)->m_nFamilyName), RTL_TEXTENCODING_UTF8));
156 14036 : for( ::std::list< int >::const_iterator name_it = (*it)->m_aAliases.begin(); name_it != (*it)->m_aAliases.end(); ++name_it )
157 : {
158 406 : const OUString& rAdd( pAtoms->getString( ATOM_FAMILYNAME, *name_it ) );
159 406 : if( !rAdd.isEmpty() )
160 : {
161 406 : aLine.append(';');
162 406 : aLine.append(OUStringToOString(rAdd, RTL_TEXTENCODING_UTF8));
163 : }
164 : }
165 13630 : aStream.WriteLine(aLine.makeStringAndClear());
166 :
167 13630 : const OUString& rPSName( pAtoms->getString( ATOM_PSNAME, (*it)->m_nPSName ) );
168 13630 : aLine.append(nSubEntry);
169 13630 : aLine.append(';');
170 13630 : aLine.append(OUStringToOString(rPSName, RTL_TEXTENCODING_UTF8));
171 13630 : aLine.append(';');
172 13630 : aLine.append(static_cast<sal_Int32>((*it)->m_eItalic));
173 13630 : aLine.append(';');
174 13630 : aLine.append(static_cast<sal_Int32>((*it)->m_eWeight));
175 13630 : aLine.append(';');
176 13630 : aLine.append(static_cast<sal_Int32>((*it)->m_eWidth));
177 13630 : aLine.append(';');
178 13630 : aLine.append(static_cast<sal_Int32>((*it)->m_ePitch));
179 13630 : aLine.append(';');
180 13630 : aLine.append(static_cast<sal_Int32>((*it)->m_aEncoding));
181 13630 : aLine.append(';');
182 13630 : aLine.append(static_cast<sal_Int32>((*it)->m_nAscend));
183 13630 : aLine.append(';');
184 13630 : aLine.append(static_cast<sal_Int32>((*it)->m_nDescend));
185 13630 : aLine.append(';');
186 13630 : aLine.append(static_cast<sal_Int32>((*it)->m_nLeading));
187 13630 : aLine.append(';');
188 13630 : aLine.append((*it)->m_bHaveVerticalSubstitutedGlyphs ? '1' : '0');
189 13630 : aLine.append(';');
190 13630 : aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricX.width ));
191 13630 : aLine.append(';');
192 13630 : aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricX.height));
193 13630 : aLine.append(';');
194 13630 : aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricY.width ));
195 13630 : aLine.append(';');
196 13630 : aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricY.height));
197 13630 : aLine.append(';');
198 13630 : aLine.append((*it)->m_bUserOverride ? '1' : '0');
199 13630 : aLine.append(';');
200 13630 : aLine.append(static_cast<sal_Int32>(0));
201 13630 : aLine.append(';');
202 13630 : aLine.append(static_cast<sal_Int32>(0));
203 :
204 13630 : switch( (*it)->m_eType )
205 : {
206 : case fonttype::Type1:
207 3654 : aLine.append(';');
208 3654 : aLine.append(static_cast<const PrintFontManager::Type1FontFile*>(*it)->m_aMetricFile);
209 3654 : break;
210 : case fonttype::TrueType:
211 9976 : aLine.append(';');
212 9976 : aLine.append(static_cast<sal_Int32>(static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nTypeFlags));
213 9976 : break;
214 0 : default: break;
215 : }
216 13630 : if( !(*it)->m_aStyleName.isEmpty() )
217 : {
218 13630 : aLine.append(';');
219 13630 : aLine.append(OUStringToOString((*it)->m_aStyleName, RTL_TEXTENCODING_UTF8));
220 : }
221 13630 : aStream.WriteLine(aLine.makeStringAndClear());
222 : }
223 13572 : aStream.WriteLine(OString());
224 : }
225 696 : }
226 58 : m_bDoFlush = false;
227 : }
228 :
229 : /*
230 : * FontCache::read
231 : */
232 :
233 205 : void FontCache::read()
234 : {
235 205 : PrintFontManager& rManager( PrintFontManager::get() );
236 205 : MultiAtomProvider* pAtoms = rManager.m_pAtoms;
237 :
238 205 : SvFileStream aStream( m_aCacheFile, StreamMode::READ );
239 205 : if( ! aStream.IsOpen() )
240 : {
241 : #if OSL_DEBUG_LEVEL > 1
242 : fprintf( stderr, "FontCache::read: opening cache file %s failed\n", OUStringToOString(m_aCacheFile, osl_getThreadTextEncoding()).getStr() );
243 : #endif
244 58 : return;
245 : }
246 :
247 294 : OString aLine;
248 147 : aStream.ReadLine( aLine );
249 147 : if ( !(aLine == CACHE_MAGIC) )
250 : {
251 : #if OSL_DEBUG_LEVEL >1
252 : fprintf( stderr, "FontCache::read: cache file %s fails magic test\n", OUStringToOString(m_aCacheFile, osl_getThreadTextEncoding()).getStr() );
253 : #endif
254 0 : return;
255 : }
256 :
257 147 : int nDir = 0;
258 147 : FontDirMap* pDir = NULL;
259 147 : bool bKeepOnlyUserOverridden = false;
260 70707 : do
261 : {
262 70707 : aStream.ReadLine( aLine );
263 139650 : if( aLine.startsWith("FontCacheDirectory:") ||
264 68943 : aLine.startsWith("EmptyFontCacheDirectory:") )
265 : {
266 1764 : bool bEmpty = aLine.startsWith("Empty");
267 1764 : sal_Int32 nSearchIndex = bEmpty ? 24 : 19;
268 :
269 1764 : OString aDir;
270 1764 : sal_Int64 nTimestamp = 0;
271 1764 : sal_Int32 nTEnd = aLine.indexOf( ':', nSearchIndex );
272 1764 : if( nTEnd != -1 )
273 : {
274 1764 : OString aTimeStamp = aLine.copy( nSearchIndex, nTEnd - nSearchIndex );
275 1764 : nTimestamp = aTimeStamp.toInt64();
276 1764 : aDir = aLine.copy( nTEnd+1 );
277 : }
278 : else
279 : {
280 : // invalid format, remove
281 0 : pDir = NULL;
282 0 : nDir = 0;
283 0 : m_bDoFlush = true;
284 0 : continue;
285 : }
286 :
287 : // is the directory modified ?
288 : struct stat aStat;
289 3528 : if( stat( aDir.getStr(), &aStat ) ||
290 1764 : ! S_ISDIR(aStat.st_mode) )
291 : {
292 : // remove outdated cache data
293 0 : pDir = NULL;
294 0 : nDir = 0;
295 0 : m_bDoFlush = true;
296 0 : continue;
297 : }
298 : else
299 : {
300 1764 : nDir = rManager.getDirectoryAtom( aDir, true );
301 1764 : m_aCache[ nDir ].m_nTimestamp = (sal_Int64)aStat.st_mtime;
302 1764 : m_aCache[ nDir ].m_bNoFiles = bEmpty;
303 1764 : pDir = bEmpty ? NULL : &m_aCache[ nDir ].m_aEntries;
304 1764 : bKeepOnlyUserOverridden = ((sal_Int64)aStat.st_mtime != nTimestamp);
305 1764 : m_aCache[ nDir ].m_bUserOverrideOnly = bKeepOnlyUserOverridden;
306 1764 : }
307 : }
308 68943 : else if( pDir && aLine.startsWith("File:") )
309 : {
310 34398 : OString aFile( aLine.copy( 5 ) );
311 34398 : aStream.ReadLine( aLine );
312 :
313 34398 : const char* pLine = aLine.getStr();
314 :
315 34398 : fonttype::type eType = (fonttype::type)atoi( pLine );
316 34398 : if( eType != fonttype::TrueType &&
317 : eType != fonttype::Type1 )
318 0 : continue;
319 103194 : while( *pLine && *pLine != ';' )
320 34398 : pLine++;
321 34398 : if( *pLine != ';' )
322 0 : continue;
323 :
324 34398 : pLine++;
325 34398 : sal_Int32 nFonts = atoi( pLine );
326 68943 : for( int n = 0; n < nFonts; n++ )
327 : {
328 34545 : aStream.ReadLine( aLine );
329 34545 : pLine = aLine.getStr();
330 34545 : int nLen = aLine.getLength();
331 :
332 34545 : PrintFontManager::PrintFont* pFont = NULL;
333 34545 : switch( eType )
334 : {
335 : case fonttype::TrueType:
336 25284 : pFont = new PrintFontManager::TrueTypeFontFile();
337 25284 : break;
338 : case fonttype::Type1:
339 9261 : pFont = new PrintFontManager::Type1FontFile();
340 9261 : break;
341 0 : default: break;
342 : }
343 :
344 : sal_Int32 nIndex;
345 :
346 34545 : for( nIndex = 0; nIndex < nLen && pLine[nIndex] != ';'; nIndex++ )
347 : ;
348 :
349 : pFont->m_nFamilyName = pAtoms->getAtom( ATOM_FAMILYNAME,
350 : OUString( pLine, nIndex, RTL_TEXTENCODING_UTF8 ),
351 34545 : true );
352 70119 : while( nIndex < nLen )
353 : {
354 1029 : sal_Int32 nLastIndex = nIndex+1;
355 1029 : for( nIndex = nLastIndex ; nIndex < nLen && pLine[nIndex] != ';'; nIndex++ )
356 : ;
357 1029 : if( nIndex - nLastIndex )
358 : {
359 1029 : OUString aAlias( pLine+nLastIndex, nIndex-nLastIndex, RTL_TEXTENCODING_UTF8 );
360 1029 : pFont->m_aAliases.push_back( pAtoms->getAtom( ATOM_FAMILYNAME, aAlias, true ) );
361 : }
362 : }
363 34545 : aStream.ReadLine( aLine );
364 34545 : pLine = aLine.getStr();
365 34545 : nLen = aLine.getLength();
366 :
367 : // get up to 20 token positions
368 34545 : const int nMaxTokens = 20;
369 : int nTokenPos[nMaxTokens];
370 34545 : nTokenPos[0] = 0;
371 34545 : int nTokens = 1;
372 2683779 : for( int i = 0; i < nLen; i++ )
373 : {
374 2683779 : if( pLine[i] == ';' )
375 : {
376 656355 : nTokenPos[nTokens++] = i+1;
377 656355 : if( nTokens == nMaxTokens )
378 34545 : break;
379 : }
380 : }
381 34545 : if( nTokens < 18 )
382 : {
383 0 : delete pFont;
384 0 : continue;
385 : }
386 34545 : int nCollEntry = atoi( pLine );
387 34545 : pFont->m_nPSName = pAtoms->getAtom( ATOM_PSNAME, OUString( pLine + nTokenPos[1], nTokenPos[2]-nTokenPos[1]-1, RTL_TEXTENCODING_UTF8 ), true );
388 34545 : pFont->m_eItalic = (FontItalic)atoi( pLine+nTokenPos[2] );
389 34545 : pFont->m_eWeight = (FontWeight)atoi( pLine+nTokenPos[3] );
390 34545 : pFont->m_eWidth = (FontWidth)atoi( pLine+nTokenPos[4] );
391 34545 : pFont->m_ePitch = (FontPitch)atoi( pLine+nTokenPos[5] );
392 34545 : pFont->m_aEncoding = (rtl_TextEncoding)atoi( pLine+nTokenPos[6] );
393 34545 : pFont->m_nAscend = atoi( pLine + nTokenPos[7] );
394 34545 : pFont->m_nDescend = atoi( pLine + nTokenPos[8] );
395 34545 : pFont->m_nLeading = atoi( pLine + nTokenPos[9] );
396 : pFont->m_bHaveVerticalSubstitutedGlyphs
397 34545 : = (atoi( pLine + nTokenPos[10] ) != 0);
398 : pFont->m_aGlobalMetricX.width
399 34545 : = atoi( pLine + nTokenPos[11] );
400 : pFont->m_aGlobalMetricX.height
401 34545 : = atoi( pLine + nTokenPos[12] );
402 : pFont->m_aGlobalMetricY.width
403 34545 : = atoi( pLine + nTokenPos[13] );
404 : pFont->m_aGlobalMetricY.height
405 34545 : = atoi( pLine + nTokenPos[14] );
406 : pFont->m_bUserOverride
407 34545 : = (atoi( pLine + nTokenPos[15] ) != 0);
408 34545 : int nStyleTokenNr = 18;
409 34545 : switch( eType )
410 : {
411 : case fonttype::TrueType:
412 25284 : static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nTypeFlags = atoi( pLine + nTokenPos[18] );
413 25284 : static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry = nCollEntry;
414 25284 : static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory = nDir;
415 25284 : static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile = aFile;
416 25284 : nStyleTokenNr++;
417 25284 : break;
418 : case fonttype::Type1:
419 : {
420 9261 : int nTokLen = (nTokens > 19 ) ? nTokenPos[19]-nTokenPos[18]-1 : nLen - nTokenPos[18];
421 9261 : static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aMetricFile = OString( pLine + nTokenPos[18], nTokLen );
422 9261 : static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory = nDir;
423 9261 : static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile = aFile;
424 9261 : nStyleTokenNr++;
425 : }
426 9261 : break;
427 0 : default: break;
428 : }
429 34545 : if( nTokens > nStyleTokenNr )
430 69090 : pFont->m_aStyleName = OUString::intern( pLine + nTokenPos[nStyleTokenNr],
431 34545 : nLen - nTokenPos[nStyleTokenNr],
432 34545 : RTL_TEXTENCODING_UTF8 );
433 :
434 34545 : bool bObsolete = false;
435 34545 : if( bKeepOnlyUserOverridden )
436 : {
437 0 : if( pFont->m_bUserOverride )
438 : {
439 0 : OStringBuffer aFilePath(rManager.getDirectory(nDir));
440 0 : aFilePath.append('/').append(aFile);
441 : struct stat aStat;
442 0 : if( stat( aFilePath.getStr(), &aStat ) ||
443 0 : ! S_ISREG( aStat.st_mode ) ||
444 0 : aStat.st_size < 16 )
445 : {
446 0 : bObsolete = true;
447 0 : }
448 : #if OSL_DEBUG_LEVEL > 2
449 : else
450 : fprintf( stderr, "keeping file %s in outdated cache entry due to user override\n",
451 : aFilePath.getStr() );
452 : #endif
453 : }
454 : else
455 0 : bObsolete = true;
456 : }
457 34545 : if( bObsolete )
458 : {
459 0 : m_bDoFlush = true;
460 : #if OSL_DEBUG_LEVEL > 2
461 : fprintf( stderr, "removing obsolete font %s\n", aFile.getStr() );
462 : #endif
463 0 : delete pFont;
464 0 : continue;
465 : }
466 :
467 34545 : FontCacheEntry& rEntry = (*pDir)[aFile].m_aEntry;
468 34545 : rEntry.push_back( pFont );
469 34398 : }
470 : }
471 70854 : } while( ! aStream.IsEof() );
472 : }
473 :
474 : /*
475 : * FontCache::copyPrintFont
476 : */
477 48643 : void FontCache::copyPrintFont( const PrintFontManager::PrintFont* pFrom, PrintFontManager::PrintFont* pTo )
478 : {
479 48643 : if( pFrom->m_eType != pTo->m_eType )
480 48643 : return;
481 48643 : switch( pFrom->m_eType )
482 : {
483 : case fonttype::TrueType:
484 35728 : static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nDirectory;
485 35728 : static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_aFontFile;
486 35728 : static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nCollectionEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nCollectionEntry;
487 35728 : static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nTypeFlags = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nTypeFlags;
488 35728 : break;
489 : case fonttype::Type1:
490 12915 : static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_nDirectory;
491 12915 : static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aFontFile;
492 12915 : static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aMetricFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aMetricFile;
493 12915 : break;
494 0 : default: break;
495 : }
496 48643 : pTo->m_nFamilyName = pFrom->m_nFamilyName;
497 48643 : pTo->m_aStyleName = pFrom->m_aStyleName;
498 48643 : pTo->m_aAliases = pFrom->m_aAliases;
499 48643 : pTo->m_nPSName = pFrom->m_nPSName;
500 48643 : pTo->m_eItalic = pFrom->m_eItalic;
501 48643 : pTo->m_eWeight = pFrom->m_eWeight;
502 48643 : pTo->m_eWidth = pFrom->m_eWidth;
503 48643 : pTo->m_ePitch = pFrom->m_ePitch;
504 48643 : pTo->m_aEncoding = pFrom->m_aEncoding;
505 48643 : pTo->m_aGlobalMetricX = pFrom->m_aGlobalMetricX;
506 48643 : pTo->m_aGlobalMetricY = pFrom->m_aGlobalMetricY;
507 48643 : pTo->m_nAscend = pFrom->m_nAscend;
508 48643 : pTo->m_nDescend = pFrom->m_nDescend;
509 48643 : pTo->m_nLeading = pFrom->m_nLeading;
510 48643 : pTo->m_nXMin = pFrom->m_nXMin;
511 48643 : pTo->m_nYMin = pFrom->m_nYMin;
512 48643 : pTo->m_nXMax = pFrom->m_nXMax;
513 48643 : pTo->m_nYMax = pFrom->m_nYMax;
514 48643 : pTo->m_bHaveVerticalSubstitutedGlyphs = pFrom->m_bHaveVerticalSubstitutedGlyphs;
515 48643 : pTo->m_bUserOverride = pFrom->m_bUserOverride;
516 : }
517 :
518 : /*
519 : * FontCache::equalsPrintFont
520 : */
521 34955 : bool FontCache::equalsPrintFont( const PrintFontManager::PrintFont* pLeft, PrintFontManager::PrintFont* pRight )
522 : {
523 34955 : if( pLeft->m_eType != pRight->m_eType )
524 0 : return false;
525 34955 : switch( pLeft->m_eType )
526 : {
527 : case fonttype::TrueType:
528 : {
529 25694 : const PrintFontManager::TrueTypeFontFile* pLT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pLeft);
530 25694 : const PrintFontManager::TrueTypeFontFile* pRT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pRight);
531 77082 : if( pRT->m_nDirectory != pLT->m_nDirectory ||
532 51388 : pRT->m_aFontFile != pLT->m_aFontFile ||
533 77082 : pRT->m_nCollectionEntry != pLT->m_nCollectionEntry ||
534 25694 : pRT->m_nTypeFlags != pLT->m_nTypeFlags )
535 0 : return false;
536 : }
537 25694 : break;
538 : case fonttype::Type1:
539 : {
540 9261 : const PrintFontManager::Type1FontFile* pLT = static_cast<const PrintFontManager::Type1FontFile*>(pLeft);
541 9261 : const PrintFontManager::Type1FontFile* pRT = static_cast<const PrintFontManager::Type1FontFile*>(pRight);
542 27783 : if( pRT->m_nDirectory != pLT->m_nDirectory ||
543 18522 : pRT->m_aFontFile != pLT->m_aFontFile ||
544 9261 : pRT->m_aMetricFile != pLT->m_aMetricFile )
545 0 : return false;
546 : }
547 9261 : break;
548 0 : default: break;
549 : }
550 104865 : if( pRight->m_nFamilyName != pLeft->m_nFamilyName ||
551 69852 : pRight->m_aStyleName != pLeft->m_aStyleName ||
552 69794 : pRight->m_nPSName != pLeft->m_nPSName ||
553 69794 : pRight->m_eItalic != pLeft->m_eItalic ||
554 69794 : pRight->m_eWeight != pLeft->m_eWeight ||
555 69794 : pRight->m_eWidth != pLeft->m_eWidth ||
556 69794 : pRight->m_ePitch != pLeft->m_ePitch ||
557 69794 : pRight->m_aEncoding != pLeft->m_aEncoding ||
558 69794 : pRight->m_aGlobalMetricX != pLeft->m_aGlobalMetricX ||
559 69794 : pRight->m_aGlobalMetricY != pLeft->m_aGlobalMetricY ||
560 69794 : pRight->m_nAscend != pLeft->m_nAscend ||
561 69794 : pRight->m_nDescend != pLeft->m_nDescend ||
562 69794 : pRight->m_nLeading != pLeft->m_nLeading ||
563 69794 : pRight->m_nXMin != pLeft->m_nXMin ||
564 69794 : pRight->m_nYMin != pLeft->m_nYMin ||
565 69794 : pRight->m_nXMax != pLeft->m_nXMax ||
566 69794 : pRight->m_nYMax != pLeft->m_nYMax ||
567 104749 : pRight->m_bHaveVerticalSubstitutedGlyphs != pLeft->m_bHaveVerticalSubstitutedGlyphs ||
568 34897 : pRight->m_bUserOverride != pLeft->m_bUserOverride
569 : )
570 58 : return false;
571 34897 : std::list< int >::const_iterator lit, rit;
572 107453 : for( lit = pLeft->m_aAliases.begin(), rit = pRight->m_aAliases.begin();
573 108834 : lit != pLeft->m_aAliases.end() && rit != pRight->m_aAliases.end() && (*lit) == (*rit);
574 : ++lit, ++rit )
575 : ;
576 34897 : return lit == pLeft->m_aAliases.end() && rit == pRight->m_aAliases.end();
577 : }
578 :
579 : /*
580 : * FontCache::clonePrintFont
581 : */
582 48585 : PrintFontManager::PrintFont* FontCache::clonePrintFont( const PrintFontManager::PrintFont* pOldFont )
583 : {
584 48585 : PrintFontManager::PrintFont* pFont = NULL;
585 48585 : switch( pOldFont->m_eType )
586 : {
587 : case fonttype::TrueType:
588 35670 : pFont = new PrintFontManager::TrueTypeFontFile();
589 35670 : break;
590 : case fonttype::Type1:
591 12915 : pFont = new PrintFontManager::Type1FontFile();
592 12915 : break;
593 0 : default: break;
594 : }
595 48585 : if( pFont )
596 : {
597 48585 : copyPrintFont( pOldFont, pFont );
598 : }
599 48585 : return pFont;
600 : }
601 :
602 : /*
603 : * FontCache::getFontCacheFile
604 : */
605 48380 : bool FontCache::getFontCacheFile( int nDirID, const OString& rFile, list< PrintFontManager::PrintFont* >& rNewFonts ) const
606 : {
607 48380 : bool bSuccess = false;
608 :
609 48380 : FontCacheData::const_iterator dir = m_aCache.find( nDirID );
610 48380 : if( dir != m_aCache.end() )
611 : {
612 47684 : FontDirMap::const_iterator entry = dir->second.m_aEntries.find( rFile );
613 47684 : if( entry != dir->second.m_aEntries.end() )
614 : {
615 69558 : for( FontCacheEntry::const_iterator font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
616 : {
617 34955 : bSuccess = true;
618 34955 : PrintFontManager::PrintFont* pFont = clonePrintFont( *font );
619 34955 : rNewFonts.push_back( pFont );
620 : }
621 : }
622 : }
623 48380 : return bSuccess;
624 : }
625 :
626 : /*
627 : * FontCache::updateFontCacheEntry
628 : */
629 48585 : void FontCache::updateFontCacheEntry( const PrintFontManager::PrintFont* pFont, bool bFlush )
630 : {
631 48585 : OString aFile;
632 48585 : int nDirID = 0;
633 48585 : switch( pFont->m_eType )
634 : {
635 : case fonttype::TrueType:
636 35670 : nDirID = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory;
637 35670 : aFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile;
638 35670 : break;
639 : case fonttype::Type1:
640 12915 : nDirID = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory;
641 12915 : aFile = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile;
642 12915 : break;
643 : default:
644 48585 : return;
645 : }
646 48585 : FontCacheData::const_iterator dir = m_aCache.find( nDirID );
647 48585 : FontDirMap::const_iterator entry;
648 48585 : FontCacheEntry::const_iterator font;
649 48585 : PrintFontManager::PrintFont* pCacheFont = NULL;
650 :
651 48585 : if( dir != m_aCache.end() )
652 : {
653 47889 : entry = dir->second.m_aEntries.find( aFile );
654 47889 : if( entry != dir->second.m_aEntries.end() )
655 : {
656 35423 : for( font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
657 : {
658 105685 : if( (*font)->m_eType == pFont->m_eType &&
659 61469 : ( (*font)->m_eType != fonttype::TrueType ||
660 26104 : static_cast<const PrintFontManager::TrueTypeFontFile*>(*font)->m_nCollectionEntry == static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry
661 : ) )
662 34955 : break;
663 : }
664 35013 : if( font != entry->second.m_aEntry.end() )
665 34955 : pCacheFont = *font;
666 : }
667 : }
668 : else
669 696 : createCacheDir( nDirID );
670 :
671 48585 : if( pCacheFont )
672 : {
673 34955 : if( ! equalsPrintFont( pFont, pCacheFont ) )
674 : {
675 58 : copyPrintFont( pFont, pCacheFont );
676 58 : m_bDoFlush = true;
677 : }
678 : }
679 : else
680 : {
681 13630 : pCacheFont = clonePrintFont( pFont );
682 13630 : m_aCache[nDirID].m_aEntries[aFile].m_aEntry.push_back( pCacheFont );
683 13630 : m_bDoFlush = true;
684 : }
685 48585 : if( bFlush )
686 0 : flush();
687 : }
688 :
689 : /*
690 : * FontCache::listDirectory
691 : */
692 410 : bool FontCache::listDirectory( const OString& rDir, std::list< PrintFontManager::PrintFont* >& rNewFonts ) const
693 : {
694 410 : PrintFontManager& rManager( PrintFontManager::get() );
695 410 : int nDirID = rManager.getDirectoryAtom( rDir );
696 :
697 410 : FontCacheData::const_iterator dir = m_aCache.find( nDirID );
698 410 : bool bFound = (dir != m_aCache.end());
699 :
700 410 : if( bFound && !dir->second.m_bNoFiles )
701 : {
702 0 : for( FontDirMap::const_iterator file = dir->second.m_aEntries.begin(); file != dir->second.m_aEntries.end(); ++file )
703 : {
704 0 : for( FontCacheEntry::const_iterator font = file->second.m_aEntry.begin(); font != file->second.m_aEntry.end(); ++font )
705 : {
706 0 : PrintFontManager::PrintFont* pFont = clonePrintFont( *font );
707 0 : rNewFonts.push_back( pFont );
708 : }
709 : }
710 : }
711 410 : return bFound;
712 : }
713 :
714 : /*
715 : * FontCache::listDirectory
716 : */
717 0 : bool FontCache::scanAdditionalFiles( const OString& rDir )
718 : {
719 0 : PrintFontManager& rManager( PrintFontManager::get() );
720 0 : int nDirID = rManager.getDirectoryAtom( rDir );
721 0 : FontCacheData::const_iterator dir = m_aCache.find( nDirID );
722 0 : bool bFound = (dir != m_aCache.end());
723 :
724 0 : return (bFound && dir->second.m_bUserOverrideOnly);
725 : }
726 :
727 : /*
728 : * FontCache::createCacheDir
729 : */
730 696 : void FontCache::createCacheDir( int nDirID )
731 : {
732 696 : PrintFontManager& rManager( PrintFontManager::get() );
733 :
734 696 : const OString& rDir = rManager.getDirectory( nDirID );
735 : struct stat aStat;
736 696 : if( ! stat( rDir.getStr(), &aStat ) )
737 696 : m_aCache[nDirID].m_nTimestamp = (sal_Int64)aStat.st_mtime;
738 696 : }
739 :
740 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|