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 20 : FontCache::FontCache()
57 : {
58 20 : m_bDoFlush = false;
59 20 : m_aCacheFile = getOfficePath( UserPath );
60 20 : if( m_aCacheFile.Len() )
61 : {
62 19 : m_aCacheFile.AppendAscii( FONTCACHEFILE );
63 19 : read();
64 : }
65 20 : }
66 :
67 : /*
68 : * FontCache destructor
69 : */
70 :
71 40 : FontCache::~FontCache()
72 : {
73 20 : clearCache();
74 20 : }
75 :
76 : /*
77 : * FontCache::clearCache
78 : */
79 20 : void FontCache::clearCache()
80 : {
81 579 : for( FontCacheData::iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++dir_it )
82 : {
83 2739 : for( FontDirMap::iterator entry_it = dir_it->second.m_aEntries.begin(); entry_it != dir_it->second.m_aEntries.end(); ++entry_it )
84 : {
85 4460 : for( FontCacheEntry::iterator font_it = entry_it->second.m_aEntry.begin(); font_it != entry_it->second.m_aEntry.end(); ++font_it )
86 2280 : delete *font_it;
87 : }
88 : }
89 20 : m_aCache.clear();
90 20 : }
91 :
92 : /*
93 : * FontCache::Commit
94 : */
95 :
96 20 : void FontCache::flush()
97 : {
98 20 : if( ! m_bDoFlush || ! m_aCacheFile.Len() )
99 : return;
100 :
101 1 : SvFileStream aStream;
102 1 : aStream.Open( m_aCacheFile, STREAM_WRITE | STREAM_TRUNC );
103 1 : 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 1 : aStream.SetLineDelimiter( LINEEND_LF );
112 1 : aStream.WriteLine(rtl::OString(RTL_CONSTASCII_STRINGPARAM(CACHE_MAGIC)));
113 :
114 1 : PrintFontManager& rManager( PrintFontManager::get() );
115 1 : MultiAtomProvider* pAtoms = rManager.m_pAtoms;
116 :
117 29 : for( FontCacheData::const_iterator dir_it = m_aCache.begin(); dir_it != m_aCache.end(); ++ dir_it )
118 : {
119 28 : const FontDirMap& rDir( dir_it->second.m_aEntries );
120 :
121 28 : rtl::OString aDirectory(rManager.getDirectory(dir_it->first));
122 : rtl::OStringBuffer aLine(
123 28 : RTL_CONSTASCII_STRINGPARAM("FontCacheDirectory:"));
124 28 : aLine.append(dir_it->second.m_nTimestamp);
125 28 : aLine.append(':');
126 28 : aLine.append(aDirectory);
127 28 : if( rDir.empty() && dir_it->second.m_bNoFiles )
128 1 : aLine.insert(0, RTL_CONSTASCII_STRINGPARAM("Empty"));
129 28 : aStream.WriteLine(aLine.makeStringAndClear());
130 :
131 137 : for( FontDirMap::const_iterator entry_it = rDir.begin(); entry_it != rDir.end(); ++entry_it )
132 : {
133 : // insert cache entries
134 109 : const FontCacheEntry& rEntry( entry_it->second.m_aEntry );
135 109 : if( rEntry.begin() == rEntry.end() )
136 0 : continue;
137 :
138 109 : aLine.append(RTL_CONSTASCII_STRINGPARAM("File:"));
139 109 : aLine.append(entry_it->first);
140 109 : aStream.WriteLine(aLine.makeStringAndClear());
141 :
142 109 : int nEntrySize = entry_it->second.m_aEntry.size();
143 : // write: type;nfonts
144 109 : aLine.append(static_cast<sal_Int32>(rEntry.front()->m_eType));
145 109 : aLine.append(';');
146 109 : aLine.append(static_cast<sal_Int32>(nEntrySize));
147 109 : aStream.WriteLine(aLine.makeStringAndClear());
148 :
149 109 : sal_Int32 nSubEntry = 0;
150 223 : 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 114 : if( nEntrySize > 1 )
158 7 : nSubEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nCollectionEntry;
159 : else
160 107 : nSubEntry = 0;
161 :
162 114 : aLine.append(OUStringToOString(pAtoms->getString( ATOM_FAMILYNAME, (*it)->m_nFamilyName), RTL_TEXTENCODING_UTF8));
163 124 : for( ::std::list< int >::const_iterator name_it = (*it)->m_aAliases.begin(); name_it != (*it)->m_aAliases.end(); ++name_it )
164 : {
165 10 : const OUString& rAdd( pAtoms->getString( ATOM_FAMILYNAME, *name_it ) );
166 10 : if( !rAdd.isEmpty() )
167 : {
168 10 : aLine.append(';');
169 10 : aLine.append(OUStringToOString(rAdd, RTL_TEXTENCODING_UTF8));
170 : }
171 : }
172 114 : aStream.WriteLine(aLine.makeStringAndClear());
173 :
174 114 : const OUString& rPSName( pAtoms->getString( ATOM_PSNAME, (*it)->m_nPSName ) );
175 114 : aLine.append(nSubEntry);
176 114 : aLine.append(';');
177 114 : aLine.append(OUStringToOString(rPSName, RTL_TEXTENCODING_UTF8));
178 114 : aLine.append(';');
179 114 : aLine.append(static_cast<sal_Int32>((*it)->m_eItalic));
180 114 : aLine.append(';');
181 114 : aLine.append(static_cast<sal_Int32>((*it)->m_eWeight));
182 114 : aLine.append(';');
183 114 : aLine.append(static_cast<sal_Int32>((*it)->m_eWidth));
184 114 : aLine.append(';');
185 114 : aLine.append(static_cast<sal_Int32>((*it)->m_ePitch));
186 114 : aLine.append(';');
187 114 : aLine.append(static_cast<sal_Int32>((*it)->m_aEncoding));
188 114 : aLine.append(';');
189 114 : aLine.append(static_cast<sal_Int32>((*it)->m_nAscend));
190 114 : aLine.append(';');
191 114 : aLine.append(static_cast<sal_Int32>((*it)->m_nDescend));
192 114 : aLine.append(';');
193 114 : aLine.append(static_cast<sal_Int32>((*it)->m_nLeading));
194 114 : aLine.append(';');
195 114 : aLine.append((*it)->m_bHaveVerticalSubstitutedGlyphs ? '1' : '0');
196 114 : aLine.append(';');
197 114 : aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricX.width ));
198 114 : aLine.append(';');
199 114 : aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricX.height));
200 114 : aLine.append(';');
201 114 : aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricY.width ));
202 114 : aLine.append(';');
203 114 : aLine.append(static_cast<sal_Int32>((*it)->m_aGlobalMetricY.height));
204 114 : aLine.append(';');
205 114 : aLine.append((*it)->m_bUserOverride ? '1' : '0');
206 114 : aLine.append(';');
207 114 : aLine.append(static_cast<sal_Int32>(0));
208 114 : aLine.append(';');
209 114 : aLine.append(static_cast<sal_Int32>(0));
210 :
211 114 : switch( (*it)->m_eType )
212 : {
213 : case fonttype::Type1:
214 35 : aLine.append(';');
215 35 : aLine.append(static_cast<const PrintFontManager::Type1FontFile*>(*it)->m_aMetricFile);
216 35 : break;
217 : case fonttype::TrueType:
218 79 : aLine.append(';');
219 79 : aLine.append(static_cast<sal_Int32>(static_cast<const PrintFontManager::TrueTypeFontFile*>(*it)->m_nTypeFlags));
220 79 : break;
221 0 : default: break;
222 : }
223 114 : if( !(*it)->m_aStyleName.isEmpty() )
224 : {
225 114 : aLine.append(';');
226 114 : aLine.append(OUStringToOString((*it)->m_aStyleName, RTL_TEXTENCODING_UTF8));
227 : }
228 114 : aStream.WriteLine(aLine.makeStringAndClear());
229 : }
230 109 : aStream.WriteLine(rtl::OString());
231 : }
232 28 : }
233 1 : m_bDoFlush = false;
234 : }
235 :
236 : /*
237 : * FontCache::read
238 : */
239 :
240 19 : void FontCache::read()
241 : {
242 19 : PrintFontManager& rManager( PrintFontManager::get() );
243 19 : MultiAtomProvider* pAtoms = rManager.m_pAtoms;
244 :
245 19 : SvFileStream aStream( m_aCacheFile, STREAM_READ );
246 19 : 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 18 : OString aLine;
256 18 : aStream.ReadLine( aLine );
257 18 : 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 18 : int nDir = 0;
266 18 : FontDirMap* pDir = NULL;
267 18 : bool bKeepOnlyUserOverridden = false;
268 4446 : do
269 : {
270 4446 : aStream.ReadLine( aLine );
271 16812 : if( aLine.compareTo( RTL_CONSTASCII_STRINGPARAM( "FontCacheDirectory:" ) ) == 0 ||
272 12366 : aLine.compareTo( RTL_CONSTASCII_STRINGPARAM( "EmptyFontCacheDirectory:" ) ) == 0 )
273 : {
274 504 : bool bEmpty = (aLine.compareTo( RTL_CONSTASCII_STRINGPARAM ("Empty" ) ) == 0);
275 504 : sal_Int32 nSearchIndex = bEmpty ? 24 : 19;
276 :
277 504 : OString aDir;
278 504 : sal_Int64 nTimestamp = 0;
279 504 : sal_Int32 nTEnd = aLine.indexOf( ':', nSearchIndex );
280 504 : if( nTEnd != -1 )
281 : {
282 504 : rtl::OString aTimeStamp = aLine.copy( nSearchIndex, nTEnd - nSearchIndex );
283 504 : nTimestamp = aTimeStamp.toInt64();
284 504 : 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 1008 : if( stat( aDir.getStr(), &aStat ) ||
298 504 : ! 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 504 : nDir = rManager.getDirectoryAtom( aDir, true );
309 504 : m_aCache[ nDir ].m_nTimestamp = (sal_Int64)aStat.st_mtime;
310 504 : m_aCache[ nDir ].m_bNoFiles = bEmpty;
311 504 : pDir = bEmpty ? NULL : &m_aCache[ nDir ].m_aEntries;
312 504 : bKeepOnlyUserOverridden = ((sal_Int64)aStat.st_mtime != nTimestamp);
313 504 : m_aCache[ nDir ].m_bUserOverrideOnly = bKeepOnlyUserOverridden;
314 504 : }
315 : }
316 3942 : else if( pDir && aLine.compareTo( RTL_CONSTASCII_STRINGPARAM( "File:" ) ) == 0 )
317 : {
318 1962 : OString aFile( aLine.copy( 5 ) );
319 1962 : aStream.ReadLine( aLine );
320 :
321 1962 : const char* pLine = aLine.getStr();
322 :
323 1962 : fonttype::type eType = (fonttype::type)atoi( pLine );
324 1962 : if( eType != fonttype::TrueType &&
325 : eType != fonttype::Type1 &&
326 : eType != fonttype::Builtin
327 : )
328 0 : continue;
329 5886 : while( *pLine && *pLine != ';' )
330 1962 : pLine++;
331 1962 : if( *pLine != ';' )
332 0 : continue;
333 :
334 1962 : pLine++;
335 1962 : sal_Int32 nFonts = atoi( pLine );
336 4014 : for( int n = 0; n < nFonts; n++ )
337 : {
338 2052 : aStream.ReadLine( aLine );
339 2052 : pLine = aLine.getStr();
340 2052 : int nLen = aLine.getLength();
341 :
342 2052 : PrintFontManager::PrintFont* pFont = NULL;
343 2052 : switch( eType )
344 : {
345 : case fonttype::TrueType:
346 1422 : pFont = new PrintFontManager::TrueTypeFontFile();
347 1422 : break;
348 : case fonttype::Type1:
349 630 : pFont = new PrintFontManager::Type1FontFile();
350 630 : break;
351 : case fonttype::Builtin:
352 0 : pFont = new PrintFontManager::BuiltinFont();
353 0 : break;
354 0 : default: break;
355 : }
356 :
357 : sal_Int32 nIndex;
358 :
359 2052 : 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 2052 : sal_True );
365 4284 : while( nIndex < nLen )
366 : {
367 180 : sal_Int32 nLastIndex = nIndex+1;
368 180 : for( nIndex = nLastIndex ; nIndex < nLen && pLine[nIndex] != ';'; nIndex++ )
369 : ;
370 180 : if( nIndex - nLastIndex )
371 : {
372 180 : OUString aAlias( pLine+nLastIndex, nIndex-nLastIndex, RTL_TEXTENCODING_UTF8 );
373 180 : pFont->m_aAliases.push_back( pAtoms->getAtom( ATOM_FAMILYNAME, aAlias, sal_True ) );
374 : }
375 : }
376 2052 : aStream.ReadLine( aLine );
377 2052 : pLine = aLine.getStr();
378 2052 : nLen = aLine.getLength();
379 :
380 : // get up to 20 token positions
381 2052 : const int nMaxTokens = 20;
382 : int nTokenPos[nMaxTokens];
383 2052 : nTokenPos[0] = 0;
384 2052 : int nTokens = 1;
385 159732 : for( int i = 0; i < nLen; i++ )
386 : {
387 159732 : if( pLine[i] == ';' )
388 : {
389 38988 : nTokenPos[nTokens++] = i+1;
390 38988 : if( nTokens == nMaxTokens )
391 2052 : break;
392 : }
393 : }
394 2052 : if( nTokens < 18 )
395 : {
396 0 : delete pFont;
397 0 : continue;
398 : }
399 2052 : int nCollEntry = atoi( pLine );
400 2052 : pFont->m_nPSName = pAtoms->getAtom( ATOM_PSNAME, OUString( pLine + nTokenPos[1], nTokenPos[2]-nTokenPos[1]-1, RTL_TEXTENCODING_UTF8 ), sal_True );
401 2052 : pFont->m_eItalic = (FontItalic)atoi( pLine+nTokenPos[2] );
402 2052 : pFont->m_eWeight = (FontWeight)atoi( pLine+nTokenPos[3] );
403 2052 : pFont->m_eWidth = (FontWidth)atoi( pLine+nTokenPos[4] );
404 2052 : pFont->m_ePitch = (FontPitch)atoi( pLine+nTokenPos[5] );
405 2052 : pFont->m_aEncoding = (rtl_TextEncoding)atoi( pLine+nTokenPos[6] );
406 2052 : pFont->m_nAscend = atoi( pLine + nTokenPos[7] );
407 2052 : pFont->m_nDescend = atoi( pLine + nTokenPos[8] );
408 2052 : pFont->m_nLeading = atoi( pLine + nTokenPos[9] );
409 : pFont->m_bHaveVerticalSubstitutedGlyphs
410 2052 : = (atoi( pLine + nTokenPos[10] ) != 0);
411 : pFont->m_aGlobalMetricX.width
412 2052 : = atoi( pLine + nTokenPos[11] );
413 : pFont->m_aGlobalMetricX.height
414 2052 : = atoi( pLine + nTokenPos[12] );
415 : pFont->m_aGlobalMetricY.width
416 2052 : = atoi( pLine + nTokenPos[13] );
417 : pFont->m_aGlobalMetricY.height
418 2052 : = atoi( pLine + nTokenPos[14] );
419 : pFont->m_bUserOverride
420 2052 : = (atoi( pLine + nTokenPos[15] ) != 0);
421 2052 : int nStyleTokenNr = 18;
422 2052 : switch( eType )
423 : {
424 : case fonttype::TrueType:
425 1422 : static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nTypeFlags = atoi( pLine + nTokenPos[18] );
426 1422 : static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry = nCollEntry;
427 1422 : static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory = nDir;
428 1422 : static_cast<PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile = aFile;
429 1422 : nStyleTokenNr++;
430 1422 : break;
431 : case fonttype::Type1:
432 : {
433 630 : int nTokLen = (nTokens > 19 ) ? nTokenPos[19]-nTokenPos[18]-1 : nLen - nTokenPos[18];
434 630 : static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aMetricFile = OString( pLine + nTokenPos[18], nTokLen );
435 630 : static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory = nDir;
436 630 : static_cast<PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile = aFile;
437 630 : nStyleTokenNr++;
438 : }
439 630 : break;
440 : case fonttype::Builtin:
441 0 : static_cast<PrintFontManager::BuiltinFont*>(pFont)->m_nDirectory = nDir;
442 0 : static_cast<PrintFontManager::BuiltinFont*>(pFont)->m_aMetricFile = aFile;
443 0 : break;
444 0 : default: break;
445 : }
446 2052 : if( nTokens > nStyleTokenNr )
447 2052 : pFont->m_aStyleName = OUString::intern( pLine + nTokenPos[nStyleTokenNr],
448 2052 : nLen - nTokenPos[nStyleTokenNr],
449 4104 : RTL_TEXTENCODING_UTF8 );
450 :
451 2052 : bool bObsolete = false;
452 2052 : 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 2052 : 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 2052 : FontCacheEntry& rEntry = (*pDir)[aFile].m_aEntry;
485 2052 : rEntry.push_back( pFont );
486 1962 : }
487 : }
488 4464 : } while( ! aStream.IsEof() );
489 : }
490 :
491 : /*
492 : * FontCache::copyPrintFont
493 : */
494 2650 : void FontCache::copyPrintFont( const PrintFontManager::PrintFont* pFrom, PrintFontManager::PrintFont* pTo ) const
495 : {
496 2650 : if( pFrom->m_eType != pTo->m_eType )
497 2650 : return;
498 2650 : switch( pFrom->m_eType )
499 : {
500 : case fonttype::TrueType:
501 1950 : static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nDirectory;
502 1950 : static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_aFontFile;
503 1950 : static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nCollectionEntry = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nCollectionEntry;
504 1950 : static_cast<PrintFontManager::TrueTypeFontFile*>(pTo)->m_nTypeFlags = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFrom)->m_nTypeFlags;
505 1950 : break;
506 : case fonttype::Type1:
507 700 : static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_nDirectory;
508 700 : static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aFontFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aFontFile;
509 700 : static_cast<PrintFontManager::Type1FontFile*>(pTo)->m_aMetricFile = static_cast<const PrintFontManager::Type1FontFile*>(pFrom)->m_aMetricFile;
510 700 : break;
511 : case fonttype::Builtin:
512 0 : static_cast<PrintFontManager::BuiltinFont*>(pTo)->m_nDirectory = static_cast<const PrintFontManager::BuiltinFont*>(pFrom)->m_nDirectory;
513 0 : static_cast<PrintFontManager::BuiltinFont*>(pTo)->m_aMetricFile = static_cast<const PrintFontManager::BuiltinFont*>(pFrom)->m_aMetricFile;
514 0 : break;
515 0 : default: break;
516 : }
517 2650 : pTo->m_nFamilyName = pFrom->m_nFamilyName;
518 2650 : pTo->m_aStyleName = pFrom->m_aStyleName;
519 2650 : pTo->m_aAliases = pFrom->m_aAliases;
520 2650 : pTo->m_nPSName = pFrom->m_nPSName;
521 2650 : pTo->m_eItalic = pFrom->m_eItalic;
522 2650 : pTo->m_eWeight = pFrom->m_eWeight;
523 2650 : pTo->m_eWidth = pFrom->m_eWidth;
524 2650 : pTo->m_ePitch = pFrom->m_ePitch;
525 2650 : pTo->m_aEncoding = pFrom->m_aEncoding;
526 2650 : pTo->m_aGlobalMetricX = pFrom->m_aGlobalMetricX;
527 2650 : pTo->m_aGlobalMetricY = pFrom->m_aGlobalMetricY;
528 2650 : pTo->m_nAscend = pFrom->m_nAscend;
529 2650 : pTo->m_nDescend = pFrom->m_nDescend;
530 2650 : pTo->m_nLeading = pFrom->m_nLeading;
531 2650 : pTo->m_nXMin = pFrom->m_nXMin;
532 2650 : pTo->m_nYMin = pFrom->m_nYMin;
533 2650 : pTo->m_nXMax = pFrom->m_nXMax;
534 2650 : pTo->m_nYMax = pFrom->m_nYMax;
535 2650 : pTo->m_bHaveVerticalSubstitutedGlyphs = pFrom->m_bHaveVerticalSubstitutedGlyphs;
536 2650 : pTo->m_bUserOverride = pFrom->m_bUserOverride;
537 : }
538 :
539 : /*
540 : * FontCache::equalsPrintFont
541 : */
542 2412 : bool FontCache::equalsPrintFont( const PrintFontManager::PrintFont* pLeft, PrintFontManager::PrintFont* pRight ) const
543 : {
544 2412 : if( pLeft->m_eType != pRight->m_eType )
545 0 : return false;
546 2412 : switch( pLeft->m_eType )
547 : {
548 : case fonttype::TrueType:
549 : {
550 1782 : const PrintFontManager::TrueTypeFontFile* pLT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pLeft);
551 1782 : const PrintFontManager::TrueTypeFontFile* pRT = static_cast<const PrintFontManager::TrueTypeFontFile*>(pRight);
552 3564 : if( pRT->m_nDirectory != pLT->m_nDirectory ||
553 1782 : 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 1782 : break;
559 : case fonttype::Type1:
560 : {
561 630 : const PrintFontManager::Type1FontFile* pLT = static_cast<const PrintFontManager::Type1FontFile*>(pLeft);
562 630 : const PrintFontManager::Type1FontFile* pRT = static_cast<const PrintFontManager::Type1FontFile*>(pRight);
563 1890 : if( pRT->m_nDirectory != pLT->m_nDirectory ||
564 630 : pRT->m_aFontFile != pLT->m_aFontFile ||
565 630 : pRT->m_aMetricFile != pLT->m_aMetricFile )
566 0 : return false;
567 : }
568 630 : 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 9628 : if( pRight->m_nFamilyName != pLeft->m_nFamilyName ||
581 2412 : 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 2402 : pRight->m_aGlobalMetricX != pLeft->m_aGlobalMetricX ||
589 2402 : 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 2402 : std::list< int >::const_iterator lit, rit;
602 12492 : for( lit = pLeft->m_aAliases.begin(), rit = pRight->m_aAliases.begin();
603 10090 : lit != pLeft->m_aAliases.end() && rit != pRight->m_aAliases.end() && (*lit) == (*rit);
604 : ++lit, ++rit )
605 : ;
606 2402 : return lit == pLeft->m_aAliases.end() && rit == pRight->m_aAliases.end();
607 : }
608 :
609 : /*
610 : * FontCache::clonePrintFont
611 : */
612 2640 : PrintFontManager::PrintFont* FontCache::clonePrintFont( const PrintFontManager::PrintFont* pOldFont ) const
613 : {
614 2640 : PrintFontManager::PrintFont* pFont = NULL;
615 2640 : switch( pOldFont->m_eType )
616 : {
617 : case fonttype::TrueType:
618 1940 : pFont = new PrintFontManager::TrueTypeFontFile();
619 1940 : break;
620 : case fonttype::Type1:
621 700 : pFont = new PrintFontManager::Type1FontFile();
622 700 : break;
623 : case fonttype::Builtin:
624 0 : pFont = new PrintFontManager::BuiltinFont();
625 0 : break;
626 0 : default: break;
627 : }
628 2640 : if( pFont )
629 : {
630 2640 : copyPrintFont( pOldFont, pFont );
631 : }
632 2640 : return pFont;
633 : }
634 :
635 : /*
636 : * FontCache::getFontCacheFile
637 : */
638 2360 : bool FontCache::getFontCacheFile( int nDirID, const OString& rFile, list< PrintFontManager::PrintFont* >& rNewFonts ) const
639 : {
640 2360 : bool bSuccess = false;
641 :
642 2360 : FontCacheData::const_iterator dir = m_aCache.find( nDirID );
643 2360 : if( dir != m_aCache.end() )
644 : {
645 2226 : FontDirMap::const_iterator entry = dir->second.m_aEntries.find( rFile );
646 2226 : if( entry != dir->second.m_aEntries.end() )
647 : {
648 4474 : for( FontCacheEntry::const_iterator font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
649 : {
650 2412 : bSuccess = true;
651 2412 : PrintFontManager::PrintFont* pFont = clonePrintFont( *font );
652 2412 : rNewFonts.push_back( pFont );
653 : }
654 : }
655 : }
656 2360 : return bSuccess;
657 : }
658 :
659 : /*
660 : * FontCache::updateFontCacheEntry
661 : */
662 2640 : void FontCache::updateFontCacheEntry( const PrintFontManager::PrintFont* pFont, bool bFlush )
663 : {
664 2640 : OString aFile;
665 2640 : int nDirID = 0;
666 2640 : switch( pFont->m_eType )
667 : {
668 : case fonttype::TrueType:
669 1940 : nDirID = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nDirectory;
670 1940 : aFile = static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_aFontFile;
671 1940 : break;
672 : case fonttype::Type1:
673 700 : nDirID = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_nDirectory;
674 700 : aFile = static_cast<const PrintFontManager::Type1FontFile*>(pFont)->m_aFontFile;
675 700 : 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 2640 : return;
682 : }
683 2640 : FontCacheData::const_iterator dir = m_aCache.find( nDirID );
684 2640 : FontDirMap::const_iterator entry;
685 2640 : FontCacheEntry::const_iterator font;
686 2640 : PrintFontManager::PrintFont* pCacheFont = NULL;
687 :
688 2640 : if( dir != m_aCache.end() )
689 : {
690 2586 : entry = dir->second.m_aEntries.find( aFile );
691 2586 : if( entry != dir->second.m_aEntries.end() )
692 : {
693 3082 : for( font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
694 : {
695 8586 : if( (*font)->m_eType == pFont->m_eType &&
696 3072 : ( (*font)->m_eType != fonttype::TrueType ||
697 2442 : static_cast<const PrintFontManager::TrueTypeFontFile*>(*font)->m_nCollectionEntry == static_cast<const PrintFontManager::TrueTypeFontFile*>(pFont)->m_nCollectionEntry
698 : ) )
699 2412 : break;
700 : }
701 2422 : if( font != entry->second.m_aEntry.end() )
702 2412 : pCacheFont = *font;
703 : }
704 : }
705 : else
706 54 : createCacheDir( nDirID );
707 :
708 2640 : if( pCacheFont )
709 : {
710 2412 : 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 2640 : if( bFlush )
723 0 : flush();
724 : }
725 :
726 : /*
727 : * FontCache::listDirectory
728 : */
729 98 : bool FontCache::listDirectory( const OString& rDir, std::list< PrintFontManager::PrintFont* >& rNewFonts ) const
730 : {
731 98 : PrintFontManager& rManager( PrintFontManager::get() );
732 98 : int nDirID = rManager.getDirectoryAtom( rDir );
733 98 : FontCacheData::const_iterator dir = m_aCache.find( nDirID );
734 98 : bool bFound = (dir != m_aCache.end());
735 :
736 98 : if( bFound && !dir->second.m_bNoFiles )
737 : {
738 0 : for( FontDirMap::const_iterator file = dir->second.m_aEntries.begin(); file != dir->second.m_aEntries.end(); ++file )
739 : {
740 0 : for( FontCacheEntry::const_iterator font = file->second.m_aEntry.begin(); font != file->second.m_aEntry.end(); ++font )
741 : {
742 0 : PrintFontManager::PrintFont* pFont = clonePrintFont( *font );
743 0 : rNewFonts.push_back( pFont );
744 : }
745 : }
746 : }
747 98 : 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 55 : void FontCache::createCacheDir( int nDirID )
767 : {
768 55 : PrintFontManager& rManager( PrintFontManager::get() );
769 :
770 55 : const OString& rDir = rManager.getDirectory( nDirID );
771 : struct stat aStat;
772 55 : if( ! stat( rDir.getStr(), &aStat ) )
773 55 : m_aCache[nDirID].m_nTimestamp = (sal_Int64)aStat.st_mtime;
774 55 : }
775 :
776 : /*
777 : * FontCache::markEmptyDir
778 : */
779 1 : void FontCache::markEmptyDir( int nDirID, bool bNoFiles )
780 : {
781 1 : createCacheDir( nDirID );
782 1 : m_aCache[nDirID].m_bNoFiles = bNoFiles;
783 1 : m_bDoFlush = true;
784 1 : }
785 :
786 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|