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