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 306 : FontCache::FontCache()
52 : {
53 306 : m_bDoFlush = false;
54 306 : m_aCacheFile = getOfficePath( UserPath );
55 306 : if( !m_aCacheFile.isEmpty() )
56 : {
57 306 : m_aCacheFile += FONTCACHEFILE;
58 306 : read();
59 : }
60 306 : }
61 :
62 : /*
63 : * FontCache destructor
64 : */
65 :
66 612 : FontCache::~FontCache()
67 : {
68 306 : clearCache();
69 306 : }
70 :
71 : /*
72 : * FontCache::clearCache
73 : */
74 306 : void FontCache::clearCache()
75 : {
76 1836 : for( FontCacheData::iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++dir_it )
77 : {
78 48042 : for( FontDirMap::iterator entry_it = dir_it->second.m_aEntries.begin(); entry_it != dir_it->second.m_aEntries.end(); ++entry_it )
79 : {
80 93024 : for( FontCacheEntry::iterator font_it = entry_it->second.m_aEntry.begin(); font_it != entry_it->second.m_aEntry.end(); ++font_it )
81 46512 : delete *font_it;
82 : }
83 : }
84 306 : m_aCache.clear();
85 306 : }
86 :
87 : /*
88 : * FontCache::Commit
89 : */
90 :
91 306 : void FontCache::flush()
92 : {
93 306 : if( ! m_bDoFlush || m_aCacheFile.isEmpty() )
94 468 : return;
95 :
96 72 : SvFileStream aStream;
97 72 : aStream.Open( m_aCacheFile, STREAM_WRITE | STREAM_TRUNC );
98 72 : 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 72 : aStream.SetLineDelimiter( LINEEND_LF );
107 72 : aStream.WriteLine( CACHE_MAGIC );
108 :
109 72 : PrintFontManager& rManager( PrintFontManager::get() );
110 72 : MultiAtomProvider* pAtoms = rManager.m_pAtoms;
111 :
112 432 : for( FontCacheData::const_iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++ dir_it )
113 : {
114 360 : const FontDirMap& rDir( dir_it->second.m_aEntries );
115 :
116 360 : OString aDirectory(rManager.getDirectory(dir_it->first));
117 720 : OStringBuffer aLine("FontCacheDirectory:");
118 360 : aLine.append(dir_it->second.m_nTimestamp);
119 360 : aLine.append(':');
120 360 : aLine.append(aDirectory);
121 360 : if( rDir.empty() && dir_it->second.m_bNoFiles )
122 0 : aLine.insert(0, "Empty");
123 360 : aStream.WriteLine(aLine.makeStringAndClear());
124 :
125 11304 : for( FontDirMap::const_iterator entry_it = rDir.begin(); entry_it != rDir.end(); ++entry_it )
126 : {
127 : // insert cache entries
128 10944 : const FontCacheEntry& rEntry( entry_it->second.m_aEntry );
129 10944 : if( rEntry.begin() == rEntry.end() )
130 0 : continue;
131 :
132 10944 : aLine.append("File:");
133 10944 : aLine.append(entry_it->first);
134 10944 : aStream.WriteLine(aLine.makeStringAndClear());
135 :
136 10944 : int nEntrySize = entry_it->second.m_aEntry.size();
137 : // write: type;nfonts
138 10944 : aLine.append(static_cast<sal_Int32>(rEntry.front()->m_eType));
139 10944 : aLine.append(';');
140 10944 : aLine.append(static_cast<sal_Int32>(nEntrySize));
141 10944 : aStream.WriteLine(aLine.makeStringAndClear());
142 :
143 10944 : sal_Int32 nSubEntry = 0;
144 21888 : 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 10944 : if( nEntrySize > 1 )
152 0 : nSubEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nCollectionEntry;
153 : else
154 10944 : nSubEntry = 0;
155 :
156 10944 : aLine.append(OUStringToOString(pAtoms->getString( ATOM_FAMILYNAME, (*it)->m_nFamilyName), RTL_TEXTENCODING_UTF8));
157 10944 : 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 10944 : aStream.WriteLine(aLine.makeStringAndClear());
167 :
168 10944 : const OUString& rPSName( pAtoms->getString( ATOM_PSNAME, (*it)->m_nPSName ) );
169 10944 : aLine.append(nSubEntry);
170 10944 : aLine.append(';');
171 10944 : aLine.append(OUStringToOString(rPSName, RTL_TEXTENCODING_UTF8));
172 10944 : aLine.append(';');
173 10944 : aLine.append(static_cast<sal_Int32>((*it)->m_eItalic));
174 10944 : aLine.append(';');
175 10944 : aLine.append(static_cast<sal_Int32>((*it)->m_eWeight));
176 10944 : aLine.append(';');
177 10944 : aLine.append(static_cast<sal_Int32>((*it)->m_eWidth));
178 10944 : aLine.append(';');
179 10944 : aLine.append(static_cast<sal_Int32>((*it)->m_ePitch));
180 10944 : aLine.append(';');
181 10944 : aLine.append(static_cast<sal_Int32>((*it)->m_aEncoding));
182 10944 : aLine.append(';');
183 10944 : aLine.append(static_cast<sal_Int32>((*it)->m_nAscend));
184 10944 : aLine.append(';');
185 10944 : aLine.append(static_cast<sal_Int32>((*it)->m_nDescend));
186 10944 : aLine.append(';');
187 10944 : aLine.append(static_cast<sal_Int32>((*it)->m_nLeading));
188 10944 : aLine.append(';');
189 10944 : aLine.append((*it)->m_bHaveVerticalSubstitutedGlyphs ? '1' : '0');
190 10944 : aLine.append(';');
191 10944 : aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricX.width ));
192 10944 : aLine.append(';');
193 10944 : aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricX.height));
194 10944 : aLine.append(';');
195 10944 : aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricY.width ));
196 10944 : aLine.append(';');
197 10944 : aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricY.height));
198 10944 : aLine.append(';');
199 10944 : aLine.append((*it)->m_bUserOverride ? '1' : '0');
200 10944 : aLine.append(';');
201 10944 : aLine.append(static_cast<sal_Int32>(0));
202 10944 : aLine.append(';');
203 10944 : aLine.append(static_cast<sal_Int32>(0));
204 :
205 10944 : switch( (*it)->m_eType )
206 : {
207 : case fonttype::Type1:
208 3384 : aLine.append(';');
209 3384 : aLine.append(static_cast<const PrintFontManager::Type1FontFile*>(*it)->m_aMetricFile);
210 3384 : break;
211 : case fonttype::TrueType:
212 7560 : aLine.append(';');
213 7560 : aLine.append(static_cast<sal_Int32>(static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nTypeFlags));
214 7560 : break;
215 0 : default: break;
216 : }
217 10944 : if( !(*it)->m_aStyleName.isEmpty() )
218 : {
219 10944 : aLine.append(';');
220 10944 : aLine.append(OUStringToOString((*it)->m_aStyleName, RTL_TEXTENCODING_UTF8));
221 : }
222 10944 : aStream.WriteLine(aLine.makeStringAndClear());
223 : }
224 10944 : aStream.WriteLine(OString());
225 : }
226 360 : }
227 72 : m_bDoFlush = false;
228 : }
229 :
230 : /*
231 : * FontCache::read
232 : */
233 :
234 306 : void FontCache::read()
235 : {
236 306 : PrintFontManager& rManager( PrintFontManager::get() );
237 306 : MultiAtomProvider* pAtoms = rManager.m_pAtoms;
238 :
239 306 : SvFileStream aStream( m_aCacheFile, STREAM_READ );
240 306 : 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 72 : return;
246 : }
247 :
248 468 : OString aLine;
249 234 : aStream.ReadLine( aLine );
250 234 : 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 234 : int nDir = 0;
259 234 : FontDirMap* pDir = NULL;
260 234 : bool bKeepOnlyUserOverridden = false;
261 72540 : do
262 : {
263 72540 : aStream.ReadLine( aLine );
264 143910 : if( aLine.startsWith("FontCacheDirectory:") ||
265 71370 : aLine.startsWith("EmptyFontCacheDirectory:") )
266 : {
267 1170 : bool bEmpty = aLine.startsWith("Empty");
268 1170 : sal_Int32 nSearchIndex = bEmpty ? 24 : 19;
269 :
270 1170 : OString aDir;
271 1170 : sal_Int64 nTimestamp = 0;
272 1170 : sal_Int32 nTEnd = aLine.indexOf( ':', nSearchIndex );
273 1170 : if( nTEnd != -1 )
274 : {
275 1170 : OString aTimeStamp = aLine.copy( nSearchIndex, nTEnd - nSearchIndex );
276 1170 : nTimestamp = aTimeStamp.toInt64();
277 1170 : 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 2340 : if( stat( aDir.getStr(), &aStat ) ||
291 1170 : ! 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 1170 : nDir = rManager.getDirectoryAtom( aDir, true );
302 1170 : m_aCache[ nDir ].m_nTimestamp = (sal_Int64)aStat.st_mtime;
303 1170 : m_aCache[ nDir ].m_bNoFiles = bEmpty;
304 1170 : pDir = bEmpty ? NULL : &m_aCache[ nDir ].m_aEntries;
305 1170 : bKeepOnlyUserOverridden = ((sal_Int64)aStat.st_mtime != nTimestamp);
306 1170 : m_aCache[ nDir ].m_bUserOverrideOnly = bKeepOnlyUserOverridden;
307 1170 : }
308 : }
309 71370 : else if( pDir && aLine.startsWith("File:") )
310 : {
311 35568 : OString aFile( aLine.copy( 5 ) );
312 35568 : aStream.ReadLine( aLine );
313 :
314 35568 : const char* pLine = aLine.getStr();
315 :
316 35568 : fonttype::type eType = (fonttype::type)atoi( pLine );
317 35568 : if( eType != fonttype::TrueType &&
318 : eType != fonttype::Type1 )
319 0 : continue;
320 106704 : while( *pLine && *pLine != ';' )
321 35568 : pLine++;
322 35568 : if( *pLine != ';' )
323 0 : continue;
324 :
325 35568 : pLine++;
326 35568 : sal_Int32 nFonts = atoi( pLine );
327 71136 : for( int n = 0; n < nFonts; n++ )
328 : {
329 35568 : aStream.ReadLine( aLine );
330 35568 : pLine = aLine.getStr();
331 35568 : int nLen = aLine.getLength();
332 :
333 35568 : PrintFontManager::PrintFont* pFont = NULL;
334 35568 : switch( eType )
335 : {
336 : case fonttype::TrueType:
337 24570 : pFont = new PrintFontManager::TrueTypeFontFile();
338 24570 : break;
339 : case fonttype::Type1:
340 10998 : pFont = new PrintFontManager::Type1FontFile();
341 10998 : break;
342 0 : default: break;
343 : }
344 :
345 : sal_Int32 nIndex;
346 :
347 35568 : 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 35568 : true );
353 71136 : 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 35568 : aStream.ReadLine( aLine );
365 35568 : pLine = aLine.getStr();
366 35568 : nLen = aLine.getLength();
367 :
368 : // get up to 20 token positions
369 35568 : const int nMaxTokens = 20;
370 : int nTokenPos[nMaxTokens];
371 35568 : nTokenPos[0] = 0;
372 35568 : int nTokens = 1;
373 2793024 : for( int i = 0; i < nLen; i++ )
374 : {
375 2793024 : if( pLine[i] == ';' )
376 : {
377 675792 : nTokenPos[nTokens++] = i+1;
378 675792 : if( nTokens == nMaxTokens )
379 35568 : break;
380 : }
381 : }
382 35568 : if( nTokens < 18 )
383 : {
384 0 : delete pFont;
385 0 : continue;
386 : }
387 35568 : int nCollEntry = atoi( pLine );
388 35568 : pFont->m_nPSName = pAtoms->getAtom( ATOM_PSNAME, OUString( pLine + nTokenPos[1], nTokenPos[2]-nTokenPos[1]-1, RTL_TEXTENCODING_UTF8 ), true );
389 35568 : pFont->m_eItalic = (FontItalic)atoi( pLine+nTokenPos[2] );
390 35568 : pFont->m_eWeight = (FontWeight)atoi( pLine+nTokenPos[3] );
391 35568 : pFont->m_eWidth = (FontWidth)atoi( pLine+nTokenPos[4] );
392 35568 : pFont->m_ePitch = (FontPitch)atoi( pLine+nTokenPos[5] );
393 35568 : pFont->m_aEncoding = (rtl_TextEncoding)atoi( pLine+nTokenPos[6] );
394 35568 : pFont->m_nAscend = atoi( pLine + nTokenPos[7] );
395 35568 : pFont->m_nDescend = atoi( pLine + nTokenPos[8] );
396 35568 : pFont->m_nLeading = atoi( pLine + nTokenPos[9] );
397 : pFont->m_bHaveVerticalSubstitutedGlyphs
398 35568 : = (atoi( pLine + nTokenPos[10] ) != 0);
399 : pFont->m_aGlobalMetricX.width
400 35568 : = atoi( pLine + nTokenPos[11] );
401 : pFont->m_aGlobalMetricX.height
402 35568 : = atoi( pLine + nTokenPos[12] );
403 : pFont->m_aGlobalMetricY.width
404 35568 : = atoi( pLine + nTokenPos[13] );
405 : pFont->m_aGlobalMetricY.height
406 35568 : = atoi( pLine + nTokenPos[14] );
407 : pFont->m_bUserOverride
408 35568 : = (atoi( pLine + nTokenPos[15] ) != 0);
409 35568 : int nStyleTokenNr = 18;
410 35568 : switch( eType )
411 : {
412 : case fonttype::TrueType:
413 24570 : static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nTypeFlags = atoi( pLine + nTokenPos[18] );
414 24570 : static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry = nCollEntry;
415 24570 : static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory = nDir;
416 24570 : static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile = aFile;
417 24570 : nStyleTokenNr++;
418 24570 : break;
419 : case fonttype::Type1:
420 : {
421 10998 : int nTokLen = (nTokens > 19 ) ? nTokenPos[19]-nTokenPos[18]-1 : nLen - nTokenPos[18];
422 10998 : static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aMetricFile = OString( pLine + nTokenPos[18], nTokLen );
423 10998 : static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory = nDir;
424 10998 : static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile = aFile;
425 10998 : nStyleTokenNr++;
426 : }
427 10998 : break;
428 0 : default: break;
429 : }
430 35568 : if( nTokens > nStyleTokenNr )
431 71136 : pFont->m_aStyleName = OUString::intern( pLine + nTokenPos[nStyleTokenNr],
432 35568 : nLen - nTokenPos[nStyleTokenNr],
433 35568 : RTL_TEXTENCODING_UTF8 );
434 :
435 35568 : bool bObsolete = false;
436 35568 : 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 35568 : 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 35568 : FontCacheEntry& rEntry = (*pDir)[aFile].m_aEntry;
469 35568 : rEntry.push_back( pFont );
470 35568 : }
471 : }
472 72774 : } while( ! aStream.IsEof() );
473 : }
474 :
475 : /*
476 : * FontCache::copyPrintFont
477 : */
478 46512 : void FontCache::copyPrintFont( const PrintFontManager::PrintFont* pFrom, PrintFontManager::PrintFont* pTo ) const
479 : {
480 46512 : if( pFrom->m_eType != pTo->m_eType )
481 46512 : return;
482 46512 : switch( pFrom->m_eType )
483 : {
484 : case fonttype::TrueType:
485 32130 : static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nDirectory;
486 32130 : static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_aFontFile;
487 32130 : static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nCollectionEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nCollectionEntry;
488 32130 : static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nTypeFlags = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nTypeFlags;
489 32130 : break;
490 : case fonttype::Type1:
491 14382 : static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_nDirectory;
492 14382 : static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aFontFile;
493 14382 : static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aMetricFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aMetricFile;
494 14382 : break;
495 0 : default: break;
496 : }
497 46512 : pTo->m_nFamilyName = pFrom->m_nFamilyName;
498 46512 : pTo->m_aStyleName = pFrom->m_aStyleName;
499 46512 : pTo->m_aAliases = pFrom->m_aAliases;
500 46512 : pTo->m_nPSName = pFrom->m_nPSName;
501 46512 : pTo->m_eItalic = pFrom->m_eItalic;
502 46512 : pTo->m_eWeight = pFrom->m_eWeight;
503 46512 : pTo->m_eWidth = pFrom->m_eWidth;
504 46512 : pTo->m_ePitch = pFrom->m_ePitch;
505 46512 : pTo->m_aEncoding = pFrom->m_aEncoding;
506 46512 : pTo->m_aGlobalMetricX = pFrom->m_aGlobalMetricX;
507 46512 : pTo->m_aGlobalMetricY = pFrom->m_aGlobalMetricY;
508 46512 : pTo->m_nAscend = pFrom->m_nAscend;
509 46512 : pTo->m_nDescend = pFrom->m_nDescend;
510 46512 : pTo->m_nLeading = pFrom->m_nLeading;
511 46512 : pTo->m_nXMin = pFrom->m_nXMin;
512 46512 : pTo->m_nYMin = pFrom->m_nYMin;
513 46512 : pTo->m_nXMax = pFrom->m_nXMax;
514 46512 : pTo->m_nYMax = pFrom->m_nYMax;
515 46512 : pTo->m_bHaveVerticalSubstitutedGlyphs = pFrom->m_bHaveVerticalSubstitutedGlyphs;
516 46512 : pTo->m_bUserOverride = pFrom->m_bUserOverride;
517 : }
518 :
519 : /*
520 : * FontCache::equalsPrintFont
521 : */
522 35568 : bool FontCache::equalsPrintFont( const PrintFontManager::PrintFont* pLeft, PrintFontManager::PrintFont* pRight ) const
523 : {
524 35568 : if( pLeft->m_eType != pRight->m_eType )
525 0 : return false;
526 35568 : switch( pLeft->m_eType )
527 : {
528 : case fonttype::TrueType:
529 : {
530 24570 : const PrintFontManager::TrueTypeFontFile* pLT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pLeft);
531 24570 : const PrintFontManager::TrueTypeFontFile* pRT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pRight);
532 73710 : if( pRT->m_nDirectory != pLT->m_nDirectory ||
533 49140 : pRT->m_aFontFile != pLT->m_aFontFile ||
534 73710 : pRT->m_nCollectionEntry != pLT->m_nCollectionEntry ||
535 24570 : pRT->m_nTypeFlags != pLT->m_nTypeFlags )
536 0 : return false;
537 : }
538 24570 : break;
539 : case fonttype::Type1:
540 : {
541 10998 : const PrintFontManager::Type1FontFile* pLT = static_cast<const PrintFontManager::Type1FontFile*>(pLeft);
542 10998 : const PrintFontManager::Type1FontFile* pRT = static_cast<const PrintFontManager::Type1FontFile*>(pRight);
543 32994 : if( pRT->m_nDirectory != pLT->m_nDirectory ||
544 21996 : pRT->m_aFontFile != pLT->m_aFontFile ||
545 10998 : pRT->m_aMetricFile != pLT->m_aMetricFile )
546 0 : return false;
547 : }
548 10998 : break;
549 0 : default: break;
550 : }
551 106704 : if( pRight->m_nFamilyName != pLeft->m_nFamilyName ||
552 71136 : pRight->m_aStyleName != pLeft->m_aStyleName ||
553 71136 : pRight->m_nPSName != pLeft->m_nPSName ||
554 71136 : pRight->m_eItalic != pLeft->m_eItalic ||
555 71136 : pRight->m_eWeight != pLeft->m_eWeight ||
556 71136 : pRight->m_eWidth != pLeft->m_eWidth ||
557 71136 : pRight->m_ePitch != pLeft->m_ePitch ||
558 71136 : pRight->m_aEncoding != pLeft->m_aEncoding ||
559 71136 : pRight->m_aGlobalMetricX != pLeft->m_aGlobalMetricX ||
560 71136 : pRight->m_aGlobalMetricY != pLeft->m_aGlobalMetricY ||
561 71136 : pRight->m_nAscend != pLeft->m_nAscend ||
562 71136 : pRight->m_nDescend != pLeft->m_nDescend ||
563 71136 : pRight->m_nLeading != pLeft->m_nLeading ||
564 71136 : pRight->m_nXMin != pLeft->m_nXMin ||
565 71136 : pRight->m_nYMin != pLeft->m_nYMin ||
566 71136 : pRight->m_nXMax != pLeft->m_nXMax ||
567 71136 : pRight->m_nYMax != pLeft->m_nYMax ||
568 106704 : pRight->m_bHaveVerticalSubstitutedGlyphs != pLeft->m_bHaveVerticalSubstitutedGlyphs ||
569 35568 : pRight->m_bUserOverride != pLeft->m_bUserOverride
570 : )
571 0 : return false;
572 35568 : std::list< int >::const_iterator lit, rit;
573 106704 : for( lit = pLeft->m_aAliases.begin(), rit = pRight->m_aAliases.begin();
574 106704 : lit != pLeft->m_aAliases.end() && rit != pRight->m_aAliases.end() && (*lit) == (*rit);
575 : ++lit, ++rit )
576 : ;
577 35568 : return lit == pLeft->m_aAliases.end() && rit == pRight->m_aAliases.end();
578 : }
579 :
580 : /*
581 : * FontCache::clonePrintFont
582 : */
583 46512 : PrintFontManager::PrintFont* FontCache::clonePrintFont( const PrintFontManager::PrintFont* pOldFont ) const
584 : {
585 46512 : PrintFontManager::PrintFont* pFont = NULL;
586 46512 : switch( pOldFont->m_eType )
587 : {
588 : case fonttype::TrueType:
589 32130 : pFont = new PrintFontManager::TrueTypeFontFile();
590 32130 : break;
591 : case fonttype::Type1:
592 14382 : pFont = new PrintFontManager::Type1FontFile();
593 14382 : break;
594 0 : default: break;
595 : }
596 46512 : if( pFont )
597 : {
598 46512 : copyPrintFont( pOldFont, pFont );
599 : }
600 46512 : return pFont;
601 : }
602 :
603 : /*
604 : * FontCache::getFontCacheFile
605 : */
606 47430 : bool FontCache::getFontCacheFile( int nDirID, const OString& rFile, list< PrintFontManager::PrintFont* >& rNewFonts ) const
607 : {
608 47430 : bool bSuccess = false;
609 :
610 47430 : FontCacheData::const_iterator dir = m_aCache.find( nDirID );
611 47430 : if( dir != m_aCache.end() )
612 : {
613 46458 : FontDirMap::const_iterator entry = dir->second.m_aEntries.find( rFile );
614 46458 : if( entry != dir->second.m_aEntries.end() )
615 : {
616 71136 : for( FontCacheEntry::const_iterator font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
617 : {
618 35568 : bSuccess = true;
619 35568 : PrintFontManager::PrintFont* pFont = clonePrintFont( *font );
620 35568 : rNewFonts.push_back( pFont );
621 : }
622 : }
623 : }
624 47430 : return bSuccess;
625 : }
626 :
627 : /*
628 : * FontCache::updateFontCacheEntry
629 : */
630 46512 : void FontCache::updateFontCacheEntry( const PrintFontManager::PrintFont* pFont, bool bFlush )
631 : {
632 46512 : OString aFile;
633 46512 : int nDirID = 0;
634 46512 : switch( pFont->m_eType )
635 : {
636 : case fonttype::TrueType:
637 32130 : nDirID = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory;
638 32130 : aFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile;
639 32130 : break;
640 : case fonttype::Type1:
641 14382 : nDirID = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory;
642 14382 : aFile = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile;
643 14382 : break;
644 : default:
645 46512 : return;
646 : }
647 46512 : FontCacheData::const_iterator dir = m_aCache.find( nDirID );
648 46512 : FontDirMap::const_iterator entry;
649 46512 : FontCacheEntry::const_iterator font;
650 46512 : PrintFontManager::PrintFont* pCacheFont = NULL;
651 :
652 46512 : if( dir != m_aCache.end() )
653 : {
654 46152 : entry = dir->second.m_aEntries.find( aFile );
655 46152 : if( entry != dir->second.m_aEntries.end() )
656 : {
657 35568 : for( font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
658 : {
659 106704 : if( (*font)->m_eType == pFont->m_eType &&
660 60138 : ( (*font)->m_eType != fonttype::TrueType ||
661 24570 : static_cast<const PrintFontManager::TrueTypeFontFile*>(*font)->m_nCollectionEntry == static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry
662 : ) )
663 35568 : break;
664 : }
665 35568 : if( font != entry->second.m_aEntry.end() )
666 35568 : pCacheFont = *font;
667 : }
668 : }
669 : else
670 360 : createCacheDir( nDirID );
671 :
672 46512 : if( pCacheFont )
673 : {
674 35568 : if( ! equalsPrintFont( pFont, pCacheFont ) )
675 : {
676 0 : copyPrintFont( pFont, pCacheFont );
677 0 : m_bDoFlush = true;
678 : }
679 : }
680 : else
681 : {
682 10944 : pCacheFont = clonePrintFont( pFont );
683 10944 : m_aCache[nDirID].m_aEntries[aFile].m_aEntry.push_back( pCacheFont );
684 10944 : m_bDoFlush = true;
685 : }
686 46512 : if( bFlush )
687 0 : flush();
688 : }
689 :
690 : /*
691 : * FontCache::listDirectory
692 : */
693 612 : bool FontCache::listDirectory( const OString& rDir, std::list< PrintFontManager::PrintFont* >& rNewFonts ) const
694 : {
695 612 : PrintFontManager& rManager( PrintFontManager::get() );
696 612 : int nDirID = rManager.getDirectoryAtom( rDir );
697 :
698 612 : FontCacheData::const_iterator dir = m_aCache.find( nDirID );
699 612 : bool bFound = (dir != m_aCache.end());
700 :
701 612 : 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 612 : 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 360 : void FontCache::createCacheDir( int nDirID )
732 : {
733 360 : PrintFontManager& rManager( PrintFontManager::get() );
734 :
735 360 : const OString& rDir = rManager.getDirectory( nDirID );
736 : struct stat aStat;
737 360 : if( ! stat( rDir.getStr(), &aStat ) )
738 360 : m_aCache[nDirID].m_nTimestamp = (sal_Int64)aStat.st_mtime;
739 360 : }
740 :
741 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|