Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <unistd.h>
31 : : #include <sys/stat.h>
32 : : #include <dirent.h>
33 : : #include <stdlib.h>
34 : : #include <osl/thread.h>
35 : :
36 : : #include "unotools/atom.hxx"
37 : :
38 : : #include "fontcache.hxx"
39 : : #include "fontsubset.hxx"
40 : : #include "impfont.hxx"
41 : : #include "svdata.hxx"
42 : : #include "generic/geninst.h"
43 : : #include "vcl/fontmanager.hxx"
44 : : #include "vcl/strhelper.hxx"
45 : : #include "vcl/ppdparser.hxx"
46 : :
47 : : #include "tools/urlobj.hxx"
48 : : #include "tools/stream.hxx"
49 : : #include "tools/debug.hxx"
50 : :
51 : : #include "osl/file.hxx"
52 : : #include "osl/process.h"
53 : :
54 : : #include "rtl/tencinfo.h"
55 : : #include "rtl/ustrbuf.hxx"
56 : : #include "rtl/strbuf.hxx"
57 : :
58 : : #include <sal/macros.h>
59 : :
60 : : #include "i18npool/mslangid.hxx"
61 : :
62 : :
63 : : #include "parseAFM.hxx"
64 : : #include "sft.hxx"
65 : :
66 : : #if OSL_DEBUG_LEVEL > 1
67 : : #include <sys/times.h>
68 : : #include <stdio.h>
69 : : #endif
70 : :
71 : : #include "sal/alloca.h"
72 : :
73 : : #include <set>
74 : : #include <boost/unordered_set.hpp>
75 : : #include <algorithm>
76 : :
77 : : #include "adobeenc.tab" // get encoding table for AFM metrics
78 : :
79 : : #ifdef CALLGRIND_COMPILE
80 : : #include <valgrind/callgrind.h>
81 : : #endif
82 : :
83 : : #include <comphelper/processfactory.hxx>
84 : : #include <comphelper/string.hxx>
85 : : #include "com/sun/star/beans/XMaterialHolder.hpp"
86 : : #include "com/sun/star/beans/NamedValue.hpp"
87 : :
88 : : #define PRINTER_METRICDIR "fontmetric"
89 : :
90 : : namespace {
91 : :
92 : : namespace css = com::sun::star;
93 : :
94 : : }
95 : :
96 : : using namespace vcl;
97 : : using namespace utl;
98 : : using namespace psp;
99 : : using namespace osl;
100 : : using namespace com::sun::star::uno;
101 : : using namespace com::sun::star::beans;
102 : : using namespace com::sun::star::lang;
103 : :
104 : : using ::comphelper::string::getToken;
105 : : using ::rtl::OUString;
106 : : using ::rtl::OString;
107 : : using ::rtl::OStringHash;
108 : : using ::rtl::OStringBuffer;
109 : : using ::rtl::OUStringBuffer;
110 : : using ::rtl::OUStringHash;
111 : : using ::rtl::OStringToOUString;
112 : : using ::rtl::OUStringToOString;
113 : :
114 : : /*
115 : : * static helpers
116 : : */
117 : :
118 : 130145 : inline sal_uInt16 getUInt16BE( const sal_uInt8*& pBuffer )
119 : : {
120 : 130145 : sal_uInt16 nRet = (sal_uInt16)pBuffer[1] |
121 : 130145 : (((sal_uInt16)pBuffer[0]) << 8);
122 : 130145 : pBuffer+=2;
123 : 130145 : return nRet;
124 : : }
125 : :
126 : 0 : inline sal_uInt32 getUInt32BE( const sal_uInt8*& pBuffer )
127 : : {
128 : 0 : sal_uInt32 nRet = (((sal_uInt32)pBuffer[0]) << 24) |
129 : 0 : (((sal_uInt32)pBuffer[1]) << 16) |
130 : 0 : (((sal_uInt32)pBuffer[2]) << 8) |
131 : 0 : (((sal_uInt32)pBuffer[3]) );
132 : 0 : pBuffer += 4;
133 : 0 : return nRet;
134 : : }
135 : :
136 : : // -------------------------------------------------------------------------
137 : :
138 : 4214 : static FontWeight parseWeight( const rtl::OString& rWeight )
139 : : {
140 : 4214 : FontWeight eWeight = WEIGHT_DONTKNOW;
141 [ + + ]: 4214 : if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("bold") ) != -1)
142 : : {
143 [ - + ]: 1532 : if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("emi")) != -1) // semi, demi
144 : 0 : eWeight = WEIGHT_SEMIBOLD;
145 [ - + ]: 1532 : else if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("ultra")) != -1)
146 : 0 : eWeight = WEIGHT_ULTRABOLD;
147 : : else
148 : 1532 : eWeight = WEIGHT_BOLD;
149 : : }
150 [ - + ]: 2682 : else if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("heavy")) != -1)
151 : 0 : eWeight = WEIGHT_BOLD;
152 [ + + ]: 2682 : else if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("light")) != -1)
153 : : {
154 [ - + ]: 124 : if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("emi")) != -1) // semi, demi
155 : 0 : eWeight = WEIGHT_SEMILIGHT;
156 [ - + ]: 124 : else if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("ultra")) != -1)
157 : 0 : eWeight = WEIGHT_ULTRALIGHT;
158 : : else
159 : 124 : eWeight = WEIGHT_LIGHT;
160 : : }
161 [ - + ]: 2558 : else if (rWeight.indexOfL(RTL_CONSTASCII_STRINGPARAM("black")) != -1)
162 : 0 : eWeight = WEIGHT_BLACK;
163 [ + + ]: 2558 : else if (rWeight.equalsL(RTL_CONSTASCII_STRINGPARAM("demi")))
164 : 378 : eWeight = WEIGHT_SEMIBOLD;
165 [ + + - + ]: 4106 : else if (rWeight.equalsL(RTL_CONSTASCII_STRINGPARAM("book")) ||
[ + + ]
166 : 1926 : rWeight.equalsL(RTL_CONSTASCII_STRINGPARAM("semicondensed")))
167 : 254 : eWeight = WEIGHT_LIGHT;
168 [ + + ][ + + ]: 1926 : else if (rWeight.equalsL(RTL_CONSTASCII_STRINGPARAM("medium")) || rWeight.equalsL(RTL_CONSTASCII_STRINGPARAM("roman")))
[ + + ]
169 : 1001 : eWeight = WEIGHT_MEDIUM;
170 : : else
171 : 925 : eWeight = WEIGHT_NORMAL;
172 : 4214 : return eWeight;
173 : : }
174 : :
175 : : /*
176 : : * PrintFont implementations
177 : : */
178 : 83968 : PrintFontManager::PrintFont::PrintFont( fonttype::type eType ) :
179 : : m_eType( eType ),
180 : : m_nFamilyName( 0 ),
181 : : m_nPSName( 0 ),
182 : : m_eItalic( ITALIC_DONTKNOW ),
183 : : m_eWidth( WIDTH_DONTKNOW ),
184 : : m_eWeight( WEIGHT_DONTKNOW ),
185 : : m_ePitch( PITCH_DONTKNOW ),
186 : : m_aEncoding( RTL_TEXTENCODING_DONTKNOW ),
187 : : m_bFontEncodingOnly( false ),
188 : : m_pMetrics( NULL ),
189 : : m_nAscend( 0 ),
190 : : m_nDescend( 0 ),
191 : : m_nLeading( 0 ),
192 : : m_nXMin( 0 ),
193 : : m_nYMin( 0 ),
194 : : m_nXMax( 0 ),
195 : : m_nYMax( 0 ),
196 : : m_bHaveVerticalSubstitutedGlyphs( false ),
197 [ + - ][ + - ]: 83968 : m_bUserOverride( false )
198 : : {
199 : 83968 : }
200 : :
201 : : // -------------------------------------------------------------------------
202 : :
203 : 83968 : PrintFontManager::PrintFont::~PrintFont()
204 : : {
205 [ + + ]: 83968 : if( m_pMetrics )
206 [ + - ][ + - ]: 4214 : delete m_pMetrics;
207 [ - + ]: 83968 : }
208 : :
209 : : // -------------------------------------------------------------------------
210 : :
211 : 16520 : PrintFontManager::Type1FontFile::~Type1FontFile()
212 : : {
213 [ - + ]: 33040 : }
214 : :
215 : : // -------------------------------------------------------------------------
216 : :
217 : 57652 : PrintFontManager::TrueTypeFontFile::TrueTypeFontFile()
218 : : : PrintFont( fonttype::TrueType )
219 : : , m_nDirectory( 0 )
220 : : , m_nCollectionEntry( 0 )
221 : 57652 : , m_nTypeFlags( TYPEFLAG_INVALID )
222 : 57652 : {}
223 : :
224 : : // -------------------------------------------------------------------------
225 : :
226 : 57652 : PrintFontManager::TrueTypeFontFile::~TrueTypeFontFile()
227 : : {
228 [ - + ]: 115304 : }
229 : :
230 : : // -------------------------------------------------------------------------
231 : :
232 : 9796 : PrintFontManager::BuiltinFont::~BuiltinFont()
233 : : {
234 [ - + ]: 19592 : }
235 : :
236 : : // -------------------------------------------------------------------------
237 : :
238 : 17 : bool PrintFontManager::Type1FontFile::queryMetricPage( int /*nPage*/, MultiAtomProvider* pProvider )
239 : : {
240 [ + - ]: 17 : return readAfmMetrics( PrintFontManager::get().getAfmFile( this ), pProvider, false, false );
241 : : }
242 : :
243 : : // -------------------------------------------------------------------------
244 : :
245 : 0 : bool PrintFontManager::BuiltinFont::queryMetricPage( int /*nPage*/, MultiAtomProvider* pProvider )
246 : : {
247 [ # # ]: 0 : return readAfmMetrics( PrintFontManager::get().getAfmFile( this ), pProvider, false, false );
248 : : }
249 : :
250 : : // -------------------------------------------------------------------------
251 : :
252 : 0 : bool PrintFontManager::TrueTypeFontFile::queryMetricPage( int nPage, MultiAtomProvider* pProvider )
253 : : {
254 : 0 : bool bSuccess = false;
255 : :
256 [ # # ][ # # ]: 0 : rtl::OString aFile( PrintFontManager::get().getFontFile( this ) );
257 : :
258 : 0 : TrueTypeFont* pTTFont = NULL;
259 : :
260 [ # # ][ # # ]: 0 : if( OpenTTFontFile( aFile.getStr(), m_nCollectionEntry, &pTTFont ) == SF_OK )
261 : : {
262 [ # # ]: 0 : if( ! m_pMetrics )
263 : : {
264 [ # # ][ # # ]: 0 : m_pMetrics = new PrintFontMetrics;
265 : 0 : memset (m_pMetrics->m_aPages, 0, sizeof(m_pMetrics->m_aPages));
266 : : }
267 : 0 : m_pMetrics->m_aPages[ nPage/8 ] |= (1 << ( nPage & 7 ));
268 : : int i;
269 : : sal_uInt16 table[256], table_vert[256];
270 : :
271 [ # # ]: 0 : for( i = 0; i < 256; i++ )
272 : 0 : table[ i ] = 256*nPage + i;
273 : :
274 [ # # ]: 0 : int nCharacters = nPage < 255 ? 256 : 254;
275 [ # # ]: 0 : MapString( pTTFont, table, nCharacters, NULL, 0 );
276 [ # # ]: 0 : TTSimpleGlyphMetrics* pMetrics = GetTTSimpleCharMetrics( pTTFont, nPage*256, nCharacters, 0 );
277 [ # # ]: 0 : if( pMetrics )
278 : : {
279 [ # # ]: 0 : for( i = 0; i < nCharacters; i++ )
280 : : {
281 [ # # ]: 0 : if( table[i] )
282 : : {
283 [ # # ]: 0 : CharacterMetric& rChar = m_pMetrics->m_aMetrics[ nPage*256 + i ];
284 : 0 : rChar.width = pMetrics[ i ].adv;
285 : 0 : rChar.height = m_aGlobalMetricX.height;
286 : : }
287 : : }
288 : :
289 : 0 : free( pMetrics );
290 : : }
291 : :
292 [ # # ]: 0 : for( i = 0; i < 256; i++ )
293 : 0 : table_vert[ i ] = 256*nPage + i;
294 [ # # ]: 0 : MapString( pTTFont, table_vert, nCharacters, NULL, 1 );
295 [ # # ]: 0 : pMetrics = GetTTSimpleCharMetrics( pTTFont, nPage*256, nCharacters, 1 );
296 [ # # ]: 0 : if( pMetrics )
297 : : {
298 [ # # ]: 0 : for( i = 0; i < nCharacters; i++ )
299 : : {
300 [ # # ]: 0 : if( table_vert[i] )
301 : : {
302 [ # # ]: 0 : CharacterMetric& rChar = m_pMetrics->m_aMetrics[ nPage*256 + i + ( 1 << 16 ) ];
303 : 0 : rChar.width = m_aGlobalMetricY.width;
304 : 0 : rChar.height = pMetrics[ i ].adv;
305 [ # # ]: 0 : if( table_vert[i] != table[i] )
306 [ # # ]: 0 : m_pMetrics->m_bVerticalSubstitutions[ nPage*256 + i ] = 1;
307 : : }
308 : : }
309 : 0 : free( pMetrics );
310 : : }
311 : :
312 [ # # ]: 0 : if( ! m_pMetrics->m_bKernPairsQueried )
313 : : {
314 : 0 : m_pMetrics->m_bKernPairsQueried = true;
315 : : // this is really a hack
316 : : // in future MapString/KernGlyphs should be used
317 : : // but vcl is not in a state where that could be used
318 : : // so currently we get kernpairs by accessing the raw data
319 : 0 : struct _TrueTypeFont* pImplTTFont = (struct _TrueTypeFont*)pTTFont;
320 : :
321 : : //-----------------------------------------------------------------
322 : : // Kerning: KT_MICROSOFT
323 : : //-----------------------------------------------------------------
324 [ # # ][ # # ]: 0 : if( pImplTTFont->nkern && pImplTTFont->kerntype == KT_MICROSOFT )
325 : : {
326 : : // create a glyph -> character mapping
327 [ # # ]: 0 : ::boost::unordered_map< sal_uInt16, sal_Unicode > aGlyphMap;
328 : 0 : ::boost::unordered_map< sal_uInt16, sal_Unicode >::iterator left, right;
329 [ # # ]: 0 : for( i = 21; i < 0xfffd; i++ )
330 : : {
331 [ # # ]: 0 : sal_uInt16 nGlyph = MapChar( pTTFont, (sal_Unicode)i, 0 ); // kerning for horz only
332 [ # # ]: 0 : if( nGlyph != 0 )
333 [ # # ]: 0 : aGlyphMap[ nGlyph ] = (sal_Unicode)i;
334 : : }
335 : :
336 : :
337 : 0 : KernPair aPair;
338 [ # # ]: 0 : for( i = 0; i < (int)pImplTTFont->nkern; i++ )
339 : : {
340 : 0 : const sal_uInt8* pTable = pImplTTFont->kerntables[i];
341 : :
342 : 0 : /*sal_uInt16 nVersion =*/ getUInt16BE( pTable );
343 : 0 : /*sal_uInt16 nLength =*/ getUInt16BE( pTable );
344 : 0 : sal_uInt16 nCoverage = getUInt16BE( pTable );
345 : :
346 : 0 : aPair.kern_x = 0;
347 : 0 : aPair.kern_y = 0;
348 [ # # # ]: 0 : switch( nCoverage >> 8 )
349 : : {
350 : : case 0:
351 : : {
352 : 0 : sal_uInt16 nPairs = getUInt16BE( pTable );
353 : 0 : pTable += 6;
354 [ # # ]: 0 : for( int n = 0; n < nPairs; n++ )
355 : : {
356 : 0 : sal_uInt16 nLeftGlyph = getUInt16BE( pTable );
357 : 0 : sal_uInt16 nRightGlyph = getUInt16BE( pTable );
358 : 0 : sal_Int16 nKern = (sal_Int16)getUInt16BE( pTable );
359 : :
360 [ # # ]: 0 : left = aGlyphMap.find( nLeftGlyph );
361 [ # # ]: 0 : right = aGlyphMap.find( nRightGlyph );
362 [ # # ][ # # ]: 0 : if( left != aGlyphMap.end() && right != aGlyphMap.end() )
[ # # ][ # # ]
[ # # ]
363 : : {
364 [ # # ]: 0 : aPair.first = left->second;
365 [ # # ]: 0 : aPair.second = right->second;
366 [ # # # ]: 0 : switch( nCoverage & 1 )
367 : : {
368 : : case 1:
369 : 0 : aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
370 [ # # ]: 0 : m_pMetrics->m_aXKernPairs.push_back( aPair );
371 : 0 : break;
372 : : case 0:
373 : 0 : aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
374 [ # # ]: 0 : m_pMetrics->m_aYKernPairs.push_back( aPair );
375 : 0 : break;
376 : : }
377 : : }
378 : : }
379 : : }
380 : 0 : break;
381 : :
382 : : case 2:
383 : : {
384 : 0 : const sal_uInt8* pSubTable = pTable;
385 : 0 : /*sal_uInt16 nRowWidth =*/ getUInt16BE( pTable );
386 : 0 : sal_uInt16 nOfLeft = getUInt16BE( pTable );
387 : 0 : sal_uInt16 nOfRight = getUInt16BE( pTable );
388 : 0 : /*sal_uInt16 nOfArray =*/ getUInt16BE( pTable );
389 : 0 : const sal_uInt8* pTmp = pSubTable + nOfLeft;
390 : 0 : sal_uInt16 nFirstLeft = getUInt16BE( pTmp );
391 : 0 : sal_uInt16 nLastLeft = getUInt16BE( pTmp ) + nFirstLeft - 1;
392 : 0 : pTmp = pSubTable + nOfRight;
393 : 0 : sal_uInt16 nFirstRight = getUInt16BE( pTmp );
394 : 0 : sal_uInt16 nLastRight = getUInt16BE( pTmp ) + nFirstRight -1;
395 : :
396 : : // int nPairs = (int)(nLastLeft-nFirstLeft+1)*(int)(nLastRight-nFirstRight+1);
397 [ # # ]: 0 : for( aPair.first = nFirstLeft; aPair.first < nLastLeft; aPair.first++ )
398 : : {
399 [ # # ]: 0 : for( aPair.second = 0; aPair.second < nLastRight; aPair.second++ )
400 : : {
401 : 0 : sal_Int16 nKern = (sal_Int16)getUInt16BE( pTmp );
402 [ # # # ]: 0 : switch( nCoverage & 1 )
403 : : {
404 : : case 1:
405 : 0 : aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
406 [ # # ]: 0 : m_pMetrics->m_aXKernPairs.push_back( aPair );
407 : 0 : break;
408 : : case 0:
409 : 0 : aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
410 [ # # ]: 0 : m_pMetrics->m_aYKernPairs.push_back( aPair );
411 : 0 : break;
412 : : }
413 : : }
414 : : }
415 : : }
416 : 0 : break;
417 : : }
418 [ # # ]: 0 : }
419 : : }
420 : :
421 : : //-----------------------------------------------------------------
422 : : // Kerning: KT_APPLE_NEW
423 : : //-----------------------------------------------------------------
424 [ # # ][ # # ]: 0 : if( pImplTTFont->nkern && pImplTTFont->kerntype == KT_APPLE_NEW )
425 : : {
426 : : // create a glyph -> character mapping
427 [ # # ]: 0 : ::boost::unordered_map< sal_uInt16, sal_Unicode > aGlyphMap;
428 : 0 : ::boost::unordered_map< sal_uInt16, sal_Unicode >::iterator left, right;
429 [ # # ]: 0 : for( i = 21; i < 0xfffd; i++ )
430 : : {
431 [ # # ]: 0 : sal_uInt16 nGlyph = MapChar( pTTFont, (sal_Unicode)i, 0 ); // kerning for horz only
432 [ # # ]: 0 : if( nGlyph != 0 )
433 [ # # ]: 0 : aGlyphMap[ nGlyph ] = (sal_Unicode)i;
434 : : }
435 : :
436 : : // Loop through each of the 'kern' subtables
437 : 0 : KernPair aPair;
438 [ # # ]: 0 : for( i = 0; (unsigned int)i < pImplTTFont->nkern; i++ )
439 : : {
440 : 0 : const sal_uInt8* pTable = pImplTTFont->kerntables[i];
441 : :
442 : 0 : /*sal_uInt32 nLength =*/ getUInt32BE( pTable );
443 : 0 : sal_uInt16 nCoverage = getUInt16BE( pTable );
444 : 0 : /*sal_uInt16 nTupleIndex =*/ getUInt16BE( pTable );
445 : :
446 : : // Get kerning type
447 : : // sal_Bool bKernVertical = nCoverage & 0x8000;
448 : : // sal_Bool bKernCrossStream = nCoverage & 0x4000;
449 : : // sal_Bool bKernVariation = nCoverage & 0x2000;
450 : :
451 : : // Kerning sub-table format, 0 through 3
452 : 0 : sal_uInt8 nSubTableFormat = nCoverage & 0x00FF;
453 : :
454 : 0 : aPair.kern_x = 0;
455 : 0 : aPair.kern_y = 0;
456 [ # # # ]: 0 : switch( nSubTableFormat )
457 : : {
458 : : case 0:
459 : : {
460 : : // Grab the # of kern pairs but skip over the:
461 : : // searchRange
462 : : // entrySelector
463 : : // rangeShift
464 : 0 : sal_uInt16 nPairs = getUInt16BE( pTable );
465 : 0 : pTable += 6;
466 : :
467 [ # # ]: 0 : for( int n = 0; n < nPairs; n++ )
468 : : {
469 : 0 : sal_uInt16 nLeftGlyph = getUInt16BE( pTable );
470 : 0 : sal_uInt16 nRightGlyph = getUInt16BE( pTable );
471 : 0 : sal_Int16 nKern = (sal_Int16)getUInt16BE( pTable );
472 : :
473 [ # # ]: 0 : left = aGlyphMap.find( nLeftGlyph );
474 [ # # ]: 0 : right = aGlyphMap.find( nRightGlyph );
475 [ # # ][ # # ]: 0 : if( left != aGlyphMap.end() && right != aGlyphMap.end() )
[ # # ][ # # ]
[ # # ]
476 : : {
477 [ # # ]: 0 : aPair.first = left->second;
478 [ # # ]: 0 : aPair.second = right->second;
479 : :
480 : : // Only support horizontal kerning for now
481 : 0 : aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
482 : 0 : aPair.kern_y = 0;
483 [ # # ]: 0 : m_pMetrics->m_aXKernPairs.push_back( aPair );
484 : : }
485 : : }
486 : : }
487 : 0 : break;
488 : :
489 : : case 2:
490 : : {
491 : 0 : const sal_uInt8* pSubTable = pTable;
492 : 0 : /*sal_uInt16 nRowWidth =*/ getUInt16BE( pTable );
493 : 0 : sal_uInt16 nOfLeft = getUInt16BE( pTable );
494 : 0 : sal_uInt16 nOfRight = getUInt16BE( pTable );
495 : 0 : /*sal_uInt16 nOfArray =*/ getUInt16BE( pTable );
496 : 0 : const sal_uInt8* pTmp = pSubTable + nOfLeft;
497 : 0 : sal_uInt16 nFirstLeft = getUInt16BE( pTmp );
498 : 0 : sal_uInt16 nLastLeft = getUInt16BE( pTmp ) + nFirstLeft - 1;
499 : 0 : pTmp = pSubTable + nOfRight;
500 : 0 : sal_uInt16 nFirstRight = getUInt16BE( pTmp );
501 : 0 : sal_uInt16 nLastRight = getUInt16BE( pTmp ) + nFirstRight -1;
502 : :
503 [ # # ]: 0 : for( aPair.first = nFirstLeft; aPair.first < nLastLeft; aPair.first++ )
504 : : {
505 [ # # ]: 0 : for( aPair.second = 0; aPair.second < nLastRight; aPair.second++ )
506 : : {
507 : 0 : sal_Int16 nKern = (sal_Int16)getUInt16BE( pTmp );
508 [ # # # ]: 0 : switch( nCoverage & 1 )
509 : : {
510 : : case 1:
511 : 0 : aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
512 [ # # ]: 0 : m_pMetrics->m_aXKernPairs.push_back( aPair );
513 : 0 : break;
514 : : case 0:
515 : 0 : aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
516 [ # # ]: 0 : m_pMetrics->m_aYKernPairs.push_back( aPair );
517 : 0 : break;
518 : : }
519 : : }
520 : : }
521 : : }
522 : 0 : break;
523 : :
524 : : default:
525 [ # # ]: 0 : fprintf( stderr, "Found unsupported Apple-style kern subtable type %d.\n", nSubTableFormat );
526 : 0 : break;
527 : : }
528 [ # # ]: 0 : }
529 : : }
530 : :
531 : : #if OSL_DEBUG_LEVEL > 1
532 : : fprintf( stderr, "found %" SAL_PRI_SIZET "u/%" SAL_PRI_SIZET "u kern pairs for %s\n",
533 : : m_pMetrics->m_aXKernPairs.size(),
534 : : m_pMetrics->m_aYKernPairs.size(),
535 : : OUStringToOString( pProvider->getString( ATOM_FAMILYNAME, m_nFamilyName ), RTL_TEXTENCODING_MS_1252 ).getStr() );
536 : : #else
537 : : (void) pProvider; /* avoid warnings */
538 : : #endif
539 : : }
540 : :
541 [ # # ]: 0 : CloseTTFont( pTTFont );
542 : 0 : bSuccess = true;
543 : : }
544 : 0 : return bSuccess;
545 : : }
546 : :
547 : : // -------------------------------------------------------------------------
548 : :
549 : : /* #i73387# There seem to be fonts with a rather unwell chosen family name
550 : : * consider e.g. "Helvetica Narrow" which defines its family as "Helvetica"
551 : : * It can really only be distinguished by its PSName and FullName. Both of
552 : : * which are not user presentable in OOo. So replace it by something sensible.
553 : : *
554 : : * If other fonts feature this behaviour, insert them to the map.
555 : : */
556 : 4197 : static bool familyNameOverride( const OUString& i_rPSname, OUString& o_rFamilyName )
557 : : {
558 [ + + ][ + - ]: 4197 : static boost::unordered_map< OUString, OUString, OUStringHash > aPSNameToFamily( 16 );
[ + - ][ # # ]
559 [ + + ]: 4197 : if( aPSNameToFamily.empty() ) // initialization
560 : : {
561 [ + - ][ + - ]: 130 : aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow" ) ) ] =
562 [ + - ]: 195 : OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
563 [ + - ][ + - ]: 130 : aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-Bold" ) ) ] =
564 [ + - ]: 195 : OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
565 [ + - ][ + - ]: 130 : aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-BoldOblique" ) ) ] =
566 [ + - ]: 195 : OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
567 [ + - ][ + - ]: 130 : aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-Oblique" ) ) ] =
568 [ + - ]: 195 : OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
569 : : }
570 : : boost::unordered_map<OUString,OUString,OUStringHash>::const_iterator it =
571 [ + - ]: 4197 : aPSNameToFamily.find( i_rPSname );
572 [ + - ]: 4197 : bool bReplaced = (it != aPSNameToFamily.end() );
573 [ - + ]: 4197 : if( bReplaced )
574 [ # # ]: 0 : o_rFamilyName = it->second;
575 : 4197 : return bReplaced;
576 : : };
577 : :
578 : 4214 : bool PrintFontManager::PrintFont::readAfmMetrics( const OString& rFileName, MultiAtomProvider* pProvider, bool bFillEncodingvector, bool bOnlyGlobalAttributes )
579 : : {
580 [ + - ]: 4214 : PrintFontManager& rManager( PrintFontManager::get() );
581 : :
582 : 4214 : FontInfo* pInfo = NULL;
583 [ + - ]: 4214 : parseFile( rFileName.getStr(), &pInfo, P_ALL );
584 [ + - ][ - + ]: 4214 : if( ! pInfo || ! pInfo->numOfChars )
585 : : {
586 [ # # ]: 0 : if( pInfo )
587 [ # # ]: 0 : freeFontInfo( pInfo );
588 : 0 : return false;
589 : : }
590 : :
591 : 4214 : m_aEncodingVector.clear();
592 : : // fill in global info
593 : :
594 : : // PSName
595 [ + - ]: 4214 : OUString aPSName( OStringToOUString( pInfo->gfi->fontName, RTL_TEXTENCODING_ISO_8859_1 ) );
596 [ + - ]: 4214 : m_nPSName = pProvider->getAtom( ATOM_PSNAME, aPSName, sal_True );
597 : :
598 : : // family name (if not already set)
599 : 4214 : OUString aFamily;
600 [ + + ]: 4214 : if( ! m_nFamilyName )
601 : : {
602 [ + - ]: 4197 : aFamily = OStringToOUString( pInfo->gfi->familyName, RTL_TEXTENCODING_ISO_8859_1 );
603 [ - + ]: 4197 : if( aFamily.isEmpty() )
604 : : {
605 [ # # ]: 0 : aFamily = OStringToOUString( pInfo->gfi->fontName, RTL_TEXTENCODING_ISO_8859_1 );
606 : 0 : sal_Int32 nIndex = 0;
607 : 0 : aFamily = aFamily.getToken( 0, '-', nIndex );
608 : : }
609 [ + - ]: 4197 : familyNameOverride( aPSName, aFamily );
610 [ + - ]: 4197 : m_nFamilyName = pProvider->getAtom( ATOM_FAMILYNAME, aFamily, sal_True );
611 : : }
612 : : else
613 [ + - ]: 17 : aFamily = pProvider->getString( ATOM_FAMILYNAME, m_nFamilyName );
614 : :
615 : : // style name: if fullname begins with family name
616 : : // interpret the rest of fullname as style
617 [ + + ][ + - ]: 4214 : if( m_aStyleName.isEmpty() && pInfo->gfi->fullName && *pInfo->gfi->fullName )
[ + - ][ + + ]
618 : : {
619 [ + - ]: 4197 : OUString aFullName( OStringToOUString( pInfo->gfi->fullName, RTL_TEXTENCODING_ISO_8859_1 ) );
620 [ + - ]: 4197 : if( aFullName.indexOf( aFamily ) == 0 )
621 [ + - ][ + - ]: 4197 : m_aStyleName = WhitespaceToSpace( aFullName.copy( aFamily.getLength() ) );
[ + - ][ + - ]
[ + - ]
622 : : }
623 : :
624 : : // italic
625 [ - + ]: 4214 : if( pInfo->gfi->italicAngle > 0 )
626 : 0 : m_eItalic = ITALIC_OBLIQUE;
627 [ + + ]: 4214 : else if( pInfo->gfi->italicAngle < 0 )
628 : 2037 : m_eItalic = ITALIC_NORMAL;
629 : : else
630 : 2177 : m_eItalic = ITALIC_NONE;
631 : :
632 : : // weight
633 : 4214 : rtl::OString aWeight( pInfo->gfi->weight );
634 [ + - ]: 4214 : m_eWeight = parseWeight( aWeight.toAsciiLowerCase() );
635 : :
636 : : // pitch
637 [ + + ]: 4214 : m_ePitch = pInfo->gfi->isFixedPitch ? PITCH_FIXED : PITCH_VARIABLE;
638 : :
639 : : // encoding - only set if unknown
640 : 4214 : int nAdobeEncoding = 0;
641 [ + - ]: 4214 : if( pInfo->gfi->encodingScheme )
642 : : {
643 [ + + ]: 4214 : if( !strcmp( pInfo->gfi->encodingScheme, "AdobeStandardEncoding" ) )
644 : 3951 : nAdobeEncoding = 1;
645 [ - + ]: 263 : else if( !strcmp( pInfo->gfi->encodingScheme, "ISO10646-1" ) )
646 : : {
647 : 0 : nAdobeEncoding = 1;
648 : 0 : m_aEncoding = RTL_TEXTENCODING_UNICODE;
649 : : }
650 [ - + ]: 263 : else if( !strcmp( pInfo->gfi->encodingScheme, "Symbol") )
651 : 0 : nAdobeEncoding = 2;
652 [ + - ]: 263 : else if( !strcmp( pInfo->gfi->encodingScheme, "FontSpecific") )
653 : 263 : nAdobeEncoding = 3;
654 : :
655 [ + + ]: 4214 : if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW )
656 : : m_aEncoding = nAdobeEncoding == 1 ?
657 [ + + ]: 4197 : RTL_TEXTENCODING_ADOBE_STANDARD : RTL_TEXTENCODING_SYMBOL;
658 : : }
659 [ # # ]: 0 : else if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW )
660 : 0 : m_aEncoding = RTL_TEXTENCODING_ADOBE_STANDARD;
661 : :
662 : : // try to parse the font name and decide whether it might be a
663 : : // japanese font. Who invented this PITA ?
664 : 4214 : OUString aPSNameLastToken( aPSName.copy( aPSName.lastIndexOf( '-' )+1 ) );
665 [ - + ]: 8428 : if( ! aPSNameLastToken.compareToAscii( "H" ) ||
[ + - - + ]
666 : 4214 : ! aPSNameLastToken.compareToAscii( "V" ) )
667 : : {
668 : : static const char* pEncs[] =
669 : : {
670 : : "EUC",
671 : : "RKSJ",
672 : : "SJ"
673 : : };
674 : : static const rtl_TextEncoding aEncs[] =
675 : : {
676 : : RTL_TEXTENCODING_EUC_JP,
677 : : RTL_TEXTENCODING_SHIFT_JIS,
678 : : RTL_TEXTENCODING_JIS_X_0208
679 : : };
680 : :
681 [ # # ][ # # ]: 0 : for( unsigned int enc = 0; enc < SAL_N_ELEMENTS( aEncs ) && m_aEncoding == RTL_TEXTENCODING_DONTKNOW; enc++ )
[ # # ]
682 : : {
683 : 0 : sal_Int32 nIndex = 0, nOffset = 1;
684 [ # # ]: 0 : do
685 : : {
686 : 0 : OUString aToken( aPSName.getToken( nOffset, '-', nIndex ) );
687 [ # # ]: 0 : if( nIndex == -1 )
688 : : break;
689 : 0 : nOffset = 0;
690 [ # # ]: 0 : if( ! aToken.compareToAscii( pEncs[enc] ) )
691 : : {
692 : 0 : m_aEncoding = aEncs[ enc ];
693 : 0 : m_bFontEncodingOnly = true;
694 [ # # ]: 0 : }
695 : : } while( nIndex != -1 );
696 : : }
697 : :
698 : : // default is jis
699 [ # # ]: 0 : if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW )
700 : 0 : m_aEncoding = RTL_TEXTENCODING_JIS_X_0208;
701 : : #if OSL_DEBUG_LEVEL > 1
702 : : fprintf( stderr, "Encoding %d for %s\n", m_aEncoding, pInfo->gfi->fontName );
703 : : #endif
704 : : }
705 : :
706 : : // hack for GB encoded builtin fonts posing as FontSpecific
707 [ + + ][ + + ]: 4214 : if( m_eType == fonttype::Builtin && ( nAdobeEncoding == 3 || nAdobeEncoding == 0 ) )
[ - + ]
708 : : {
709 : 124 : int nLen = aFamily.getLength();
710 [ # # ][ - + ]: 248 : if( nLen > 2 &&
[ + - - +
# # ]
711 : 124 : aFamily.getStr()[ nLen-2 ] == 'G' &&
712 : 0 : aFamily.getStr()[ nLen-1 ] == 'B' &&
713 : : pInfo->numOfChars > 255 )
714 : : {
715 : 0 : m_aEncoding = RTL_TEXTENCODING_GBK;
716 : 0 : m_bFontEncodingOnly = true;
717 : : #if OSL_DEBUG_LEVEL > 1
718 : : fprintf( stderr, "found builtin font %s with GBK encoding\n", pInfo->gfi->fontName );
719 : : #endif
720 : : }
721 : : }
722 : :
723 : : // #i37313# check if Fontspecific is not rather some character encoding
724 [ + + ][ + - ]: 4214 : if( nAdobeEncoding == 3 && m_aEncoding == RTL_TEXTENCODING_SYMBOL )
725 : : {
726 : 263 : bool bYFound = false;
727 : 263 : bool bQFound = false;
728 : 263 : CharMetricInfo* pChar = pInfo->cmi;
729 [ + + ][ - + ]: 51861 : for( int j = 0; j < pInfo->numOfChars && ! (bYFound && bQFound); j++ )
[ # # ][ + + ]
730 : : {
731 [ + - ]: 51598 : if( pChar[j].name )
732 : : {
733 [ - + ][ # # ]: 51598 : if( pChar[j].name[0] == 'Y' && pChar[j].name[1] == 0 )
734 : 0 : bYFound = true;
735 [ - + ][ # # ]: 51598 : else if( pChar[j].name[0] == 'Q' && pChar[j].name[1] == 0 )
736 : 51598 : bQFound = true;
737 : : }
738 : : }
739 [ - + ][ # # ]: 263 : if( bQFound && bYFound )
740 : : {
741 : : #if OSL_DEBUG_LEVEL > 1
742 : : fprintf( stderr, "setting FontSpecific font %s (file %s) to unicode\n",
743 : : pInfo->gfi->fontName,
744 : : rFileName.getStr()
745 : : );
746 : : #endif
747 : 0 : nAdobeEncoding = 4;
748 : 0 : m_aEncoding = RTL_TEXTENCODING_UNICODE;
749 : 0 : bFillEncodingvector = false; // will be filled anyway, don't do the work twice
750 : : }
751 : : }
752 : :
753 : : // ascend
754 : 4214 : m_nAscend = pInfo->gfi->fontBBox.ury;
755 : :
756 : : // descend
757 : : // descends have opposite sign of our definition
758 : 4214 : m_nDescend = -pInfo->gfi->fontBBox.lly;
759 : :
760 : : // fallback to ascender, descender
761 : : // interesting: the BBox seems to describe Ascender and Descender better
762 : : // as we understand it
763 [ - + ]: 4214 : if( m_nAscend == 0 )
764 : 0 : m_nAscend = pInfo->gfi->ascender;
765 [ - + ]: 4214 : if( m_nDescend == 0)
766 : 0 : m_nDescend = -pInfo->gfi->descender;
767 : :
768 : 4214 : m_nLeading = m_nAscend + m_nDescend - 1000;
769 : :
770 [ - + ]: 4214 : if( m_pMetrics )
771 [ # # ][ # # ]: 0 : delete m_pMetrics;
772 [ + - ][ + - ]: 4214 : m_pMetrics = new PrintFontMetrics;
773 : : // mark all pages as queried (or clear if only global font info queiried)
774 [ + + ]: 4214 : memset( m_pMetrics->m_aPages, bOnlyGlobalAttributes ? 0 : 0xff, sizeof( m_pMetrics->m_aPages ) );
775 : :
776 : : m_aGlobalMetricX.width = m_aGlobalMetricY.width =
777 [ - + ]: 4214 : pInfo->gfi->charwidth ? pInfo->gfi->charwidth : pInfo->gfi->fontBBox.urx;
778 : : m_aGlobalMetricX.height = m_aGlobalMetricY.height =
779 [ + + ]: 4214 : pInfo->gfi->capHeight ? pInfo->gfi->capHeight : pInfo->gfi->fontBBox.ury;
780 : :
781 : 4214 : m_nXMin = pInfo->gfi->fontBBox.llx;
782 : 4214 : m_nYMin = pInfo->gfi->fontBBox.lly;
783 : 4214 : m_nXMax = pInfo->gfi->fontBBox.urx;
784 : 4214 : m_nYMax = pInfo->gfi->fontBBox.ury;
785 : :
786 [ + - ][ + + ]: 4214 : if( bFillEncodingvector || !bOnlyGlobalAttributes )
787 : : {
788 : : // fill in character metrics
789 : :
790 : : // first transform the character codes to unicode
791 : : // note: this only works with single byte encodings
792 : 17 : sal_Unicode* pUnicodes = (sal_Unicode*)alloca( pInfo->numOfChars * sizeof(sal_Unicode));
793 : 17 : CharMetricInfo* pChar = pInfo->cmi;
794 : : int i;
795 : :
796 [ + + ]: 6176 : for( i = 0; i < pInfo->numOfChars; i++, pChar++ )
797 : : {
798 [ - + ]: 6159 : if( nAdobeEncoding == 4 )
799 : : {
800 [ # # ]: 0 : if( pChar->name )
801 : : {
802 : 0 : pUnicodes[i] = 0;
803 [ # # ]: 0 : std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name );
804 [ # # ][ # # ]: 0 : for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it )
[ # # ][ # # ]
[ # # ]
805 : : {
806 [ # # ][ # # ]: 0 : if( *it != 0 )
807 : : {
808 [ # # ][ # # ]: 0 : m_aEncodingVector[ *it ] = pChar->code;
809 [ # # ]: 0 : if( pChar->code == -1 )
810 [ # # ][ # # ]: 0 : m_aNonEncoded[ *it ] = pChar->name;
811 [ # # ]: 0 : if( ! pUnicodes[i] ) // map the first
812 [ # # ]: 0 : pUnicodes[i] = *it;
813 : : }
814 : 0 : }
815 : : }
816 : : }
817 [ + + ]: 6159 : else if( pChar->code != -1 )
818 : : {
819 [ + + ][ + - ]: 2890 : if( nAdobeEncoding == 3 && m_aEncoding == RTL_TEXTENCODING_SYMBOL )
820 : : {
821 : 1698 : pUnicodes[i] = pChar->code + 0xf000;
822 [ - + ]: 1698 : if( bFillEncodingvector )
823 [ # # ]: 0 : m_aEncodingVector[ pUnicodes[i] ] = pChar->code;
824 : 1698 : continue;
825 : : }
826 : :
827 [ - + ]: 1192 : if( m_aEncoding == RTL_TEXTENCODING_UNICODE )
828 : : {
829 : 0 : pUnicodes[i] = (sal_Unicode)pChar->code;
830 : 0 : continue;
831 : : }
832 : :
833 : 1192 : rtl::OStringBuffer aTranslate;
834 [ - + ]: 1192 : if( pChar->code & 0xff000000 )
835 [ # # ]: 0 : aTranslate.append((char)(pChar->code >> 24));
836 [ - + ]: 1192 : if( pChar->code & 0xffff0000 )
837 [ # # ]: 0 : aTranslate.append((char)((pChar->code & 0x00ff0000) >> 16));
838 [ - + ]: 1192 : if( pChar->code & 0xffffff00 )
839 [ # # ]: 0 : aTranslate.append((char)((pChar->code & 0x0000ff00) >> 8 ));
840 [ + - ]: 1192 : aTranslate.append((char)(pChar->code & 0xff));
841 [ + - ]: 1192 : rtl::OUString aUni(rtl::OStringToOUString(aTranslate.makeStringAndClear(), m_aEncoding));
842 : 2890 : pUnicodes[i] = aUni.toChar();
843 : : }
844 : : else
845 : 3269 : pUnicodes[i] = 0;
846 : : }
847 : :
848 : : // now fill in the character metrics
849 : : // parseAFM.cxx effectively only supports direction 0 (horizontal)
850 : 17 : pChar = pInfo->cmi;
851 : 17 : CharacterMetric aMetric;
852 [ + + ]: 6176 : for( i = 0; i < pInfo->numOfChars; i++, pChar++ )
853 : : {
854 [ + + ][ - + ]: 6159 : if( pChar->code == -1 && ! pChar->name )
855 : 0 : continue;
856 : :
857 [ - + ][ # # ]: 6159 : if( bFillEncodingvector && pChar->name )
858 : : {
859 [ # # ]: 0 : std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name );
860 [ # # ][ # # ]: 0 : for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it )
[ # # ][ # # ]
[ # # ]
861 : : {
862 [ # # ][ # # ]: 0 : if( *it != 0 )
863 : : {
864 [ # # ][ # # ]: 0 : m_aEncodingVector[ *it ] = pChar->code;
865 [ # # ]: 0 : if( pChar->code == -1 )
866 [ # # ][ # # ]: 0 : m_aNonEncoded[ *it ] = pChar->name;
867 : : }
868 : 0 : }
869 : : }
870 : :
871 [ + - ]: 6159 : aMetric.width = pChar->wx ? pChar->wx : pChar->charBBox.urx;
872 [ - + ]: 6159 : aMetric.height = pChar->wy ? pChar->wy : pChar->charBBox.ury - pChar->charBBox.lly;
873 [ - + ][ # # ]: 6159 : if( aMetric.width == 0 && aMetric.height == 0 )
874 : : // guess something for e.g. space
875 : 0 : aMetric.width = m_aGlobalMetricX.width/4;
876 : :
877 [ + - ][ + + ]: 6159 : if( ( nAdobeEncoding == 0 ) ||
[ - + ]
878 : : ( ( nAdobeEncoding == 3 ) && ( m_aEncoding != RTL_TEXTENCODING_SYMBOL ) ) )
879 : : {
880 [ # # ]: 0 : if( pChar->code != -1 )
881 : : {
882 [ # # ]: 0 : m_pMetrics->m_aMetrics[ pUnicodes[i] ] = aMetric;
883 [ # # ]: 0 : if( bFillEncodingvector )
884 [ # # ]: 0 : m_aEncodingVector[ pUnicodes[i] ] = pChar->code;
885 : : }
886 [ # # ]: 0 : else if( pChar->name )
887 : : {
888 [ # # ]: 0 : std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name );
889 [ # # ][ # # ]: 0 : for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it )
[ # # ][ # # ]
[ # # ]
890 : : {
891 [ # # ][ # # ]: 0 : if( *it != 0 )
892 [ # # ][ # # ]: 0 : m_pMetrics->m_aMetrics[ *it ] = aMetric;
893 : 0 : }
894 : 0 : }
895 : : }
896 [ + + ][ + - ]: 6159 : else if( nAdobeEncoding == 1 || nAdobeEncoding == 2 || nAdobeEncoding == 4)
[ - + ]
897 : : {
898 [ + - ]: 4410 : if( pChar->name )
899 : : {
900 [ + - ]: 4410 : std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name );
901 [ + - ][ + - ]: 8908 : for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it )
[ + - ][ + + ]
[ + - ]
902 : : {
903 [ + - ][ + - ]: 4498 : if( *it != 0 )
904 [ + - ][ + - ]: 4498 : m_pMetrics->m_aMetrics[ *it ] = aMetric;
905 : 4410 : }
906 : : }
907 [ # # ]: 0 : else if( pChar->code != -1 )
908 : : {
909 : : ::std::pair< ::boost::unordered_multimap< sal_uInt8, sal_Unicode >::const_iterator,
910 : : ::boost::unordered_multimap< sal_uInt8, sal_Unicode >::const_iterator >
911 [ # # ]: 0 : aCodes = rManager.getUnicodeFromAdobeCode( pChar->code );
912 [ # # ]: 0 : while( aCodes.first != aCodes.second )
913 : : {
914 [ # # ][ # # ]: 0 : if( (*aCodes.first).second != 0 )
915 : : {
916 [ # # ][ # # ]: 0 : m_pMetrics->m_aMetrics[ (*aCodes.first).second ] = aMetric;
917 [ # # ]: 0 : if( bFillEncodingvector )
918 [ # # ][ # # ]: 0 : m_aEncodingVector[ (*aCodes.first).second ] = pChar->code;
919 : : }
920 : 0 : ++aCodes.first;
921 : : }
922 : 4410 : }
923 : : }
924 [ + - ]: 1749 : else if( nAdobeEncoding == 3 )
925 : : {
926 [ + + ]: 1749 : if( pChar->code != -1 )
927 : : {
928 : 1698 : sal_Unicode code = 0xf000 + pChar->code;
929 [ + - ]: 1698 : m_pMetrics->m_aMetrics[ code ] = aMetric;
930 : : // maybe should try to find the name in the convtabs ?
931 [ - + ]: 1698 : if( bFillEncodingvector )
932 [ # # ]: 1698 : m_aEncodingVector[ code ] = pChar->code;
933 : : }
934 : : }
935 : : }
936 : :
937 : 17 : m_pMetrics->m_aXKernPairs.clear();
938 : 17 : m_pMetrics->m_aYKernPairs.clear();
939 : :
940 : : // now fill in the kern pairs
941 : : // parseAFM.cxx effectively only supports direction 0 (horizontal)
942 : 17 : PairKernData* pKern = pInfo->pkd;
943 : 17 : KernPair aPair;
944 [ + + ]: 7867 : for( i = 0; i < pInfo->numOfPairs; i++, pKern++ )
945 : : {
946 : : // #i37703# broken kern table
947 [ + - ][ - + ]: 7850 : if( ! pKern->name1 || ! pKern->name2 )
948 : 0 : continue;
949 : :
950 : 7850 : aPair.first = 0;
951 : 7850 : aPair.second = 0;
952 : : // currently we have to find the adobe character names
953 : : // in the already parsed character metrics to find
954 : : // the corresponding UCS2 code which is a bit dangerous
955 : : // since the character names are not required
956 : : // in the metric descriptions
957 : 7850 : pChar = pInfo->cmi;
958 [ + + ][ + + ]: 2245187 : for( int j = 0;
[ + + ][ + + ]
959 : : j < pInfo->numOfChars && ( aPair.first == 0 || aPair.second == 0 );
960 : : j++, pChar++ )
961 : : {
962 [ + + ]: 2237337 : if( pChar->code != -1 )
963 : : {
964 [ + - ][ + + ]: 853838 : if( ! strcmp( pKern->name1, pChar->name ? pChar->name : "" ) )
965 : 6380 : aPair.first = pUnicodes[ j ];
966 [ + - ][ + + ]: 853838 : if( ! strcmp( pKern->name2, pChar->name ? pChar->name : "" ) )
967 : 5881 : aPair.second = pUnicodes[ j ];
968 : : }
969 : : }
970 [ + + ][ + + ]: 7850 : if( aPair.first && aPair.second )
971 : : {
972 : 4411 : aPair.kern_x = pKern->xamt;
973 : 4411 : aPair.kern_y = pKern->yamt;
974 [ + - ]: 4411 : m_pMetrics->m_aXKernPairs.push_back( aPair );
975 : : }
976 : : }
977 : 17 : m_pMetrics->m_bKernPairsQueried = true;
978 : : }
979 : :
980 [ + - ]: 4214 : freeFontInfo( pInfo );
981 : 4214 : return true;
982 : : }
983 : :
984 : : /*
985 : : * one instance only
986 : : */
987 : 41908 : PrintFontManager& PrintFontManager::get()
988 : : {
989 : : static PrintFontManager* pManager = NULL;
990 [ + + ]: 41908 : if( ! pManager )
991 : : {
992 [ + - ][ + - ]: 236 : static PrintFontManager theManager;
[ + - ][ # # ]
993 : 236 : pManager = &theManager;
994 : 236 : pManager->initialize();
995 : : }
996 : 41908 : return *pManager;
997 : : }
998 : :
999 : : // -------------------------------------------------------------------------
1000 : :
1001 : : /*
1002 : : * the PrintFontManager
1003 : : */
1004 : :
1005 : 236 : PrintFontManager::PrintFontManager()
1006 : : : m_nNextFontID( 1 )
1007 : 0 : , m_pAtoms( new MultiAtomProvider() )
1008 : : , m_nNextDirAtom( 1 )
1009 [ + - ][ + - ]: 236 : , m_pFontCache( NULL )
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1010 : : {
1011 [ + + ]: 248272 : for( unsigned int i = 0; i < SAL_N_ELEMENTS( aAdobeCodes ); i++ )
1012 : : {
1013 [ + - ][ + - ]: 248036 : m_aUnicodeToAdobename.insert( ::boost::unordered_multimap< sal_Unicode, ::rtl::OString >::value_type( aAdobeCodes[i].aUnicode, aAdobeCodes[i].pAdobename ) );
1014 [ + - ][ + - ]: 248036 : m_aAdobenameToUnicode.insert( ::boost::unordered_multimap< ::rtl::OString, sal_Unicode, ::rtl::OStringHash >::value_type( aAdobeCodes[i].pAdobename, aAdobeCodes[i].aUnicode ) );
1015 [ + + ]: 248036 : if( aAdobeCodes[i].aAdobeStandardCode )
1016 : : {
1017 [ + - ][ + - ]: 35636 : m_aUnicodeToAdobecode.insert( ::boost::unordered_multimap< sal_Unicode, sal_uInt8 >::value_type( aAdobeCodes[i].aUnicode, aAdobeCodes[i].aAdobeStandardCode ) );
1018 [ + - ][ + - ]: 35636 : m_aAdobecodeToUnicode.insert( ::boost::unordered_multimap< sal_uInt8, sal_Unicode >::value_type( aAdobeCodes[i].aAdobeStandardCode, aAdobeCodes[i].aUnicode ) );
1019 : : }
1020 : : }
1021 : 236 : }
1022 : :
1023 : : // -------------------------------------------------------------------------
1024 : :
1025 [ + - ][ + - ]: 236 : PrintFontManager::~PrintFontManager()
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1026 : : {
1027 [ + - ]: 236 : deinitFontconfig();
1028 [ + - ][ + - ]: 40096 : for( ::boost::unordered_map< fontID, PrintFont* >::const_iterator it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
[ + + ]
1029 [ + - ][ + - ]: 39860 : delete (*it).second;
[ + - ]
1030 [ + - ][ + - ]: 236 : delete m_pAtoms;
1031 [ + - ]: 236 : if( m_pFontCache )
1032 [ + - ][ + - ]: 236 : delete m_pFontCache;
1033 : 236 : }
1034 : :
1035 : : // -------------------------------------------------------------------------
1036 : :
1037 : 19271 : OString PrintFontManager::getDirectory( int nAtom ) const
1038 : : {
1039 [ + - ]: 19271 : ::boost::unordered_map< int, OString >::const_iterator it( m_aAtomToDir.find( nAtom ) );
1040 [ + - ][ + - ]: 19271 : return it != m_aAtomToDir.end() ? it->second : OString();
[ + - ]
1041 : : }
1042 : :
1043 : : // -------------------------------------------------------------------------
1044 : :
1045 : 51096 : int PrintFontManager::getDirectoryAtom( const OString& rDirectory, bool bCreate )
1046 : : {
1047 : 51096 : int nAtom = 0;
1048 : : ::boost::unordered_map< OString, int, OStringHash >::const_iterator it
1049 [ + - ]: 51096 : ( m_aDirToAtom.find( rDirectory ) );
1050 [ + + ][ + - ]: 51096 : if( it != m_aDirToAtom.end() )
1051 [ + - ]: 43418 : nAtom = it->second;
1052 [ + + ]: 7678 : else if( bCreate )
1053 : : {
1054 : 7551 : nAtom = m_nNextDirAtom++;
1055 [ + - ]: 7551 : m_aDirToAtom[ rDirectory ] = nAtom;
1056 [ + - ]: 7551 : m_aAtomToDir[ nAtom ] = rDirectory;
1057 : : }
1058 : 51096 : return nAtom;
1059 : : }
1060 : :
1061 : : // -------------------------------------------------------------------------
1062 : :
1063 : 0 : std::vector<fontID> PrintFontManager::addFontFile( const ::rtl::OString& rFileName )
1064 : : {
1065 [ # # ]: 0 : rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
1066 [ # # ][ # # ]: 0 : INetURLObject aPath( OStringToOUString( rFileName, aEncoding ), INET_PROT_FILE, INetURLObject::ENCODE_ALL );
1067 [ # # ][ # # ]: 0 : OString aName( OUStringToOString( aPath.GetName(), aEncoding ) );
1068 [ # # ][ # # ]: 0 : OString aDir( OUStringToOString( aPath.GetPath(), aEncoding ) );
1069 : :
1070 [ # # ]: 0 : int nDirID = getDirectoryAtom( aDir, true );
1071 [ # # ]: 0 : std::vector<fontID> aFontIds = findFontFileIDs( nDirID, aName );
1072 [ # # ]: 0 : if( aFontIds.empty() )
1073 : : {
1074 [ # # ]: 0 : ::std::list< PrintFont* > aNewFonts;
1075 [ # # ][ # # ]: 0 : if( analyzeFontFile( nDirID, aName, aNewFonts ) )
1076 : : {
1077 [ # # # # ]: 0 : for( ::std::list< PrintFont* >::iterator it = aNewFonts.begin();
[ # # ]
1078 : 0 : it != aNewFonts.end(); ++it )
1079 : : {
1080 : 0 : fontID nFontId = m_nNextFontID++;
1081 [ # # ][ # # ]: 0 : m_aFonts[nFontId] = *it;
1082 [ # # ][ # # ]: 0 : m_aFontFileToFontID[ aName ].insert( nFontId );
1083 [ # # ][ # # ]: 0 : m_pFontCache->updateFontCacheEntry( *it, true );
1084 [ # # ]: 0 : aFontIds.push_back(nFontId);
1085 : : }
1086 : 0 : }
1087 : : }
1088 [ # # ]: 0 : return aFontIds;
1089 : : }
1090 : :
1091 : : enum fontFormat
1092 : : {
1093 : : UNKNOWN, TRUETYPE, CFF, TYPE1, AFM
1094 : : };
1095 : :
1096 : 13113 : bool PrintFontManager::analyzeFontFile( int nDirID, const OString& rFontFile, ::std::list< PrintFontManager::PrintFont* >& rNewFonts, const char *pFormat ) const
1097 : : {
1098 : 13113 : rNewFonts.clear();
1099 : :
1100 [ + - ]: 13113 : OString aDir( getDirectory( nDirID ) );
1101 : :
1102 : 13113 : OString aFullPath( aDir );
1103 : 13113 : aFullPath += "/";
1104 : 13113 : aFullPath += rFontFile;
1105 : :
1106 : : // #i1872# reject unreadable files
1107 [ - + ]: 13113 : if( access( aFullPath.getStr(), R_OK ) )
1108 : 0 : return false;
1109 : :
1110 : 13113 : fontFormat eFormat = UNKNOWN;
1111 [ + + ]: 13113 : if (pFormat)
1112 : : {
1113 [ + + ]: 11191 : if (!strcmp(pFormat, "TrueType"))
1114 : 7582 : eFormat = TRUETYPE;
1115 [ + + ]: 3609 : else if (!strcmp(pFormat, "CFF"))
1116 : 390 : eFormat = CFF;
1117 [ + - ]: 3219 : else if (!strcmp(pFormat, "Type 1"))
1118 : 3219 : eFormat = TYPE1;
1119 : : }
1120 [ + + ]: 13113 : if (eFormat == UNKNOWN)
1121 : : {
1122 : 1922 : rtl::OString aExt( rFontFile.copy( rFontFile.lastIndexOf( '.' )+1 ) );
1123 [ - + ][ - + ]: 1922 : if( aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("pfb")) || aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("pfa")) )
[ + - ]
1124 : 0 : eFormat = TYPE1;
1125 [ + - ]: 1922 : else if( aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("afm")))
1126 : 1922 : eFormat = AFM;
1127 [ # # # # : 0 : else if( aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("ttf"))
# # ][ # # ]
1128 : 0 : || aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("ttc"))
1129 : 0 : || aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("tte")) ) // #i33947# for Gaiji support
1130 : 0 : eFormat = TRUETYPE;
1131 [ # # ]: 0 : else if( aExt.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("otf")) ) // check for TTF- and PS-OpenType too
1132 : 1922 : eFormat = CFF;
1133 : : }
1134 : :
1135 [ + + ]: 13113 : if (eFormat == TYPE1)
1136 : : {
1137 : : // check for corresponding afm metric
1138 : : // first look for an adjacent file
1139 : : static const char* pSuffix[] = { ".afm", ".AFM" };
1140 : :
1141 [ + + ]: 7382 : for( unsigned int i = 0; i < SAL_N_ELEMENTS(pSuffix); i++ )
1142 : : {
1143 : : rtl::OString aName = rtl::OStringBuffer(
1144 : 4163 : rFontFile.copy(0, rFontFile.getLength() - 4)).
1145 [ + - ][ + - ]: 4163 : append(pSuffix[i]).makeStringAndClear();
1146 : :
1147 [ + - ]: 4163 : rtl::OStringBuffer aFilePath(aDir);
1148 [ + - ][ + - ]: 4163 : aFilePath.append('/').append(aName);
1149 : :
1150 : 4163 : rtl::OString aAfmFile;
1151 [ + + ]: 4163 : if( access( aFilePath.makeStringAndClear().getStr(), R_OK ) )
1152 : : {
1153 : : // try in subdirectory afm instead
1154 [ + - ][ + - ]: 1888 : aFilePath.append(aDir).append(RTL_CONSTASCII_STRINGPARAM("/afm/")).append(aName);
[ + - ]
1155 : :
1156 [ - + ]: 1888 : if (!access(aFilePath.getStr(), R_OK))
1157 : 0 : aAfmFile = rtl::OString(RTL_CONSTASCII_STRINGPARAM("afm/")) + aName;
1158 : : }
1159 : : else
1160 : 2275 : aAfmFile = aName;
1161 : :
1162 [ + + ]: 4163 : if( !aAfmFile.isEmpty() )
1163 : : {
1164 [ + - ][ + - ]: 2275 : Type1FontFile* pFont = new Type1FontFile();
1165 : 2275 : pFont->m_nDirectory = nDirID;
1166 : :
1167 : 2275 : pFont->m_aFontFile = rFontFile;
1168 : 2275 : pFont->m_aMetricFile = aAfmFile;
1169 : :
1170 [ + - ][ - + ]: 2275 : if( ! pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true ) )
[ + - ]
1171 : : {
1172 [ # # ][ # # ]: 0 : delete pFont;
1173 : 0 : pFont = NULL;
1174 : : }
1175 [ + - ]: 2275 : if( pFont )
1176 [ + - ]: 4163 : rNewFonts.push_back( pFont );
1177 : : break;
1178 : : }
1179 [ + + ][ + + ]: 4163 : }
[ + + ]
1180 : : }
1181 [ + + ]: 9894 : else if (eFormat == AFM)
1182 : : {
1183 [ + - ]: 1922 : rtl::OStringBuffer aFilePath(aDir);
1184 [ + - ][ + - ]: 1922 : aFilePath.append('/').append(rFontFile);
1185 [ + - ][ + - ]: 1922 : BuiltinFont* pFont = new BuiltinFont();
1186 : 1922 : pFont->m_nDirectory = nDirID;
1187 : 1922 : pFont->m_aMetricFile = rFontFile;
1188 [ + - + - ]: 3844 : if( pFont->readAfmMetrics( aFilePath.makeStringAndClear(), m_pAtoms,
1189 : 3844 : false, true ) )
1190 : : {
1191 [ + - ]: 1922 : rNewFonts.push_back( pFont );
1192 : : }
1193 : : else
1194 [ # # ][ # # ]: 1922 : delete pFont;
1195 : : }
1196 [ + + ][ + - ]: 7972 : else if (eFormat == TRUETYPE || eFormat == CFF)
1197 : : {
1198 : : // get number of ttc entries
1199 [ + - ]: 7972 : int nLength = CountTTCFonts( aFullPath.getStr() );
1200 [ + + ]: 7972 : if( nLength )
1201 : : {
1202 : : #if OSL_DEBUG_LEVEL > 1
1203 : : fprintf( stderr, "ttc: %s contains %d fonts\n", aFullPath.getStr(), nLength );
1204 : : #endif
1205 [ + + ]: 585 : for( int i = 0; i < nLength; i++ )
1206 : : {
1207 [ + - ][ + - ]: 455 : TrueTypeFontFile* pFont = new TrueTypeFontFile();
1208 : 455 : pFont->m_nDirectory = nDirID;
1209 : 455 : pFont->m_aFontFile = rFontFile;
1210 : 455 : pFont->m_nCollectionEntry = i;
1211 [ - + ][ + - ]: 455 : if( ! analyzeTrueTypeFile( pFont ) )
1212 : : {
1213 [ # # ][ # # ]: 0 : delete pFont;
1214 : 0 : pFont = NULL;
1215 : : }
1216 : : else
1217 [ + - ]: 455 : rNewFonts.push_back( pFont );
1218 : : }
1219 : : }
1220 : : else
1221 : : {
1222 [ + - ][ + - ]: 7842 : TrueTypeFontFile* pFont = new TrueTypeFontFile();
1223 : 7842 : pFont->m_nDirectory = nDirID;
1224 : 7842 : pFont->m_aFontFile = rFontFile;
1225 : 7842 : pFont->m_nCollectionEntry = 0;
1226 : :
1227 : : // need to read the font anyway to get aliases inside the font file
1228 [ - + ][ + - ]: 7842 : if( ! analyzeTrueTypeFile( pFont ) )
1229 : : {
1230 [ # # ][ # # ]: 0 : delete pFont;
1231 : 0 : pFont = NULL;
1232 : : }
1233 : : else
1234 [ + - ]: 7842 : rNewFonts.push_back( pFont );
1235 : : }
1236 : : }
1237 : 13113 : return ! rNewFonts.empty();
1238 : : }
1239 : :
1240 : : // -------------------------------------------------------------------------
1241 : :
1242 : 1922 : fontID PrintFontManager::findFontBuiltinID( int nPSNameAtom ) const
1243 : : {
1244 : 1922 : fontID nID = 0;
1245 : 1922 : ::boost::unordered_map< fontID, PrintFont* >::const_iterator it;
1246 [ + - ][ + + ]: 347882 : for( it = m_aFonts.begin(); nID == 0 && it != m_aFonts.end(); ++it )
[ + - ][ + + ]
[ + - ]
1247 : : {
1248 [ + - ][ + + ]: 374790 : if( it->second->m_eType == fonttype::Builtin &&
[ - + ][ - + ]
1249 [ + - ]: 28830 : it->second->m_nPSName == nPSNameAtom )
1250 [ # # ]: 0 : nID = it->first;
1251 : : }
1252 : 1922 : return nID;
1253 : : }
1254 : :
1255 : : // -------------------------------------------------------------------------
1256 : :
1257 : 8749 : fontID PrintFontManager::findFontFileID( int nDirID, const OString& rFontFile, int nFaceIndex ) const
1258 : : {
1259 : 8749 : fontID nID = 0;
1260 : :
1261 [ + - ]: 8749 : ::boost::unordered_map< OString, ::std::set< fontID >, OStringHash >::const_iterator set_it = m_aFontFileToFontID.find( rFontFile );
1262 [ + - ][ - + ]: 8749 : if( set_it == m_aFontFileToFontID.end() )
1263 : 0 : return nID;
1264 : :
1265 [ + - ][ + - ]: 18340 : for( ::std::set< fontID >::const_iterator font_it = set_it->second.begin(); font_it != set_it->second.end() && ! nID; ++font_it )
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ]
[ + + # # ]
1266 : : {
1267 [ + - ][ + - ]: 9591 : ::boost::unordered_map< fontID, PrintFont* >::const_iterator it = m_aFonts.find( *font_it );
1268 [ - + ]: 9591 : if( it == m_aFonts.end() )
1269 : 0 : continue;
1270 [ + - ]: 9591 : switch( it->second->m_eType )
[ + + - - ]
1271 : : {
1272 : : case fonttype::Type1:
1273 : : {
1274 [ + - ]: 176 : Type1FontFile* const pFont = static_cast< Type1FontFile* const >((*it).second);
1275 [ + - + - ]: 352 : if( pFont->m_nDirectory == nDirID &&
[ + - ]
1276 : 176 : pFont->m_aFontFile == rFontFile )
1277 [ + - ]: 176 : nID = it->first;
1278 : : }
1279 : 176 : break;
1280 : : case fonttype::TrueType:
1281 : : {
1282 [ + - ]: 9415 : TrueTypeFontFile* const pFont = static_cast< TrueTypeFontFile* const >((*it).second);
1283 [ + - + - ]: 18830 : if( pFont->m_nDirectory == nDirID &&
[ + + ][ + + ]
1284 : 9415 : pFont->m_aFontFile == rFontFile && pFont->m_nCollectionEntry == nFaceIndex )
1285 [ + - ]: 8573 : nID = it->first;
1286 : : }
1287 : 9415 : break;
1288 : : case fonttype::Builtin:
1289 [ # # ]: 0 : if( static_cast<const BuiltinFont*>((*it).second)->m_nDirectory == nDirID &&
[ # # # # ]
[ # # ]
1290 [ # # ]: 0 : static_cast<const BuiltinFont*>((*it).second)->m_aMetricFile == rFontFile )
1291 [ # # ]: 0 : nID = it->first;
1292 : 0 : break;
1293 : : default:
1294 : 9591 : break;
1295 : : }
1296 : : }
1297 : :
1298 : 8749 : return nID;
1299 : : }
1300 : :
1301 : 0 : std::vector<fontID> PrintFontManager::findFontFileIDs( int nDirID, const OString& rFontFile ) const
1302 : : {
1303 [ # # ]: 0 : std::vector<fontID> aIds;
1304 : :
1305 [ # # ]: 0 : ::boost::unordered_map< OString, ::std::set< fontID >, OStringHash >::const_iterator set_it = m_aFontFileToFontID.find( rFontFile );
1306 [ # # ][ # # ]: 0 : if( set_it == m_aFontFileToFontID.end() )
1307 : : return aIds;
1308 : :
1309 [ # # ][ # # ]: 0 : for( ::std::set< fontID >::const_iterator font_it = set_it->second.begin(); font_it != set_it->second.end(); ++font_it )
[ # # ][ # # ]
[ # # ]
1310 : : {
1311 [ # # ][ # # ]: 0 : ::boost::unordered_map< fontID, PrintFont* >::const_iterator it = m_aFonts.find( *font_it );
1312 [ # # ]: 0 : if( it == m_aFonts.end() )
1313 : 0 : continue;
1314 [ # # ]: 0 : switch( it->second->m_eType )
[ # # # # ]
1315 : : {
1316 : : case fonttype::Type1:
1317 : : {
1318 [ # # ]: 0 : Type1FontFile* const pFont = static_cast< Type1FontFile* const >((*it).second);
1319 [ # # # # ]: 0 : if( pFont->m_nDirectory == nDirID &&
[ # # ]
1320 : 0 : pFont->m_aFontFile == rFontFile )
1321 [ # # ][ # # ]: 0 : aIds.push_back(it->first);
1322 : : }
1323 : 0 : break;
1324 : : case fonttype::TrueType:
1325 : : {
1326 [ # # ]: 0 : TrueTypeFontFile* const pFont = static_cast< TrueTypeFontFile* const >((*it).second);
1327 [ # # # # ]: 0 : if( pFont->m_nDirectory == nDirID &&
[ # # ]
1328 : 0 : pFont->m_aFontFile == rFontFile )
1329 [ # # ][ # # ]: 0 : aIds.push_back(it->first);
1330 : : }
1331 : 0 : break;
1332 : : case fonttype::Builtin:
1333 [ # # ]: 0 : if( static_cast<const BuiltinFont*>((*it).second)->m_nDirectory == nDirID &&
[ # # # # ]
[ # # ]
1334 [ # # ]: 0 : static_cast<const BuiltinFont*>((*it).second)->m_aMetricFile == rFontFile )
1335 [ # # ][ # # ]: 0 : aIds.push_back(it->first);
1336 : 0 : break;
1337 : : default:
1338 : 0 : break;
1339 : : }
1340 : : }
1341 : :
1342 : 0 : return aIds;
1343 : : }
1344 : :
1345 : : // -------------------------------------------------------------------------
1346 : :
1347 : 18461 : OUString PrintFontManager::convertTrueTypeName( void* pRecord ) const
1348 : : {
1349 : 18461 : NameRecord* pNameRecord = (NameRecord*)pRecord;
1350 : 18461 : OUString aValue;
1351 [ + - ][ - + ]: 18461 : if(
[ - + ][ + + ]
1352 : : ( pNameRecord->platformID == 3 && ( pNameRecord->encodingID == 0 || pNameRecord->encodingID == 1 ) ) // MS, Unicode
1353 : : ||
1354 : : ( pNameRecord->platformID == 0 ) // Apple, Unicode
1355 : : )
1356 : : {
1357 : 9653 : OUStringBuffer aName( pNameRecord->slen/2 );
1358 : 9653 : const sal_uInt8* pNameBuffer = pNameRecord->sptr;
1359 [ + + ]: 139798 : for(int n = 0; n < pNameRecord->slen/2; n++ )
1360 [ + - ]: 130145 : aName.append( (sal_Unicode)getUInt16BE( pNameBuffer ) );
1361 [ + - ]: 9653 : aValue = aName.makeStringAndClear();
1362 : : }
1363 [ - + ]: 8808 : else if( pNameRecord->platformID == 3 )
1364 : : {
1365 [ # # ][ # # ]: 0 : if( pNameRecord->encodingID >= 2 && pNameRecord->encodingID <= 6 )
1366 : : {
1367 : : /*
1368 : : * and now for a special kind of madness:
1369 : : * some fonts encode their byte value string as BE uint16
1370 : : * (leading to stray zero bytes in the string)
1371 : : * while others code two bytes as a uint16 and swap to BE
1372 : : */
1373 : 0 : OStringBuffer aName;
1374 : 0 : const sal_uInt8* pNameBuffer = pNameRecord->sptr;
1375 [ # # ]: 0 : for(int n = 0; n < pNameRecord->slen/2; n++ )
1376 : : {
1377 : 0 : sal_Unicode aCode = (sal_Unicode)getUInt16BE( pNameBuffer );
1378 : 0 : sal_Char aChar = aCode >> 8;
1379 [ # # ]: 0 : if( aChar )
1380 [ # # ]: 0 : aName.append( aChar );
1381 : 0 : aChar = aCode & 0x00ff;
1382 [ # # ]: 0 : if( aChar )
1383 [ # # ]: 0 : aName.append( aChar );
1384 : : }
1385 [ # # # # : 0 : switch( pNameRecord->encodingID )
# # ]
1386 : : {
1387 : : case 2:
1388 [ # # ]: 0 : aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_932 );
1389 : 0 : break;
1390 : : case 3:
1391 [ # # ]: 0 : aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_936 );
1392 : 0 : break;
1393 : : case 4:
1394 [ # # ]: 0 : aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_950 );
1395 : 0 : break;
1396 : : case 5:
1397 [ # # ]: 0 : aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_949 );
1398 : 0 : break;
1399 : : case 6:
1400 [ # # ]: 0 : aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_1361 );
1401 : 0 : break;
1402 : 0 : }
1403 : : }
1404 : : }
1405 : 18461 : return aValue;
1406 : : }
1407 : :
1408 : : //fdo#33349.There exists an archaic Berling Antiqua font which has a "Times New
1409 : : //Roman" name field in it. We don't want the "Times New Roman" name to take
1410 : : //precedence in this case. We take Berling Antiqua as a higher priority name,
1411 : : //and erase the "Times New Roman" name
1412 : : namespace
1413 : : {
1414 : 9848 : bool isBadTNR(const OUString &rName, ::std::set< OUString >& rSet)
1415 : : {
1416 : 9848 : bool bRet = false;
1417 [ - + ]: 9848 : if ( rName == "Berling Antiqua" )
1418 : : {
1419 : 0 : ::std::set< OUString >::iterator aEnd = rSet.end();
1420 [ # # ][ # # ]: 0 : ::std::set< OUString >::iterator aI = rSet.find(OUString(RTL_CONSTASCII_USTRINGPARAM("Times New Roman")));
1421 [ # # ]: 0 : if (aI != aEnd)
1422 : : {
1423 : 0 : bRet = true;
1424 [ # # ]: 0 : rSet.erase(aI);
1425 : : }
1426 : : }
1427 : 9848 : return bRet;
1428 : : }
1429 : : }
1430 : :
1431 : : // -------------------------------------------------------------------------
1432 : :
1433 : 8418 : void PrintFontManager::analyzeTrueTypeFamilyName( void* pTTFont, ::std::list< OUString >& rNames ) const
1434 : : {
1435 : 8418 : OUString aFamily;
1436 : :
1437 : 8418 : rNames.clear();
1438 [ + - ]: 8418 : ::std::set< OUString > aSet;
1439 : :
1440 : 8418 : NameRecord* pNameRecords = NULL;
1441 [ + - ]: 8418 : int nNameRecords = GetTTNameRecords( (TrueTypeFont*)pTTFont, &pNameRecords );
1442 [ + - ][ + - ]: 8418 : if( nNameRecords && pNameRecords )
1443 : : {
1444 [ + - ]: 8418 : LanguageType aLang = MsLangId::getSystemLanguage();
1445 : 8418 : int nLastMatch = -1;
1446 [ + + ]: 483726 : for( int i = 0; i < nNameRecords; i++ )
1447 : : {
1448 [ + + ][ - + ]: 475308 : if( pNameRecords[i].nameID != 1 || pNameRecords[i].sptr == NULL )
1449 : 456847 : continue;
1450 : 18461 : int nMatch = -1;
1451 [ - + ]: 18461 : if( pNameRecords[i].platformID == 0 ) // Unicode
1452 : 0 : nMatch = 4000;
1453 [ + + ]: 18461 : else if( pNameRecords[i].platformID == 3 )
1454 : : {
1455 : : // this bases on the LanguageType actually being a Win LCID
1456 [ + + ]: 9653 : if( pNameRecords[i].languageID == aLang )
1457 : 8418 : nMatch = 8000;
1458 [ - + ]: 1235 : else if( pNameRecords[i].languageID == LANGUAGE_ENGLISH_US )
1459 : 0 : nMatch = 2000;
1460 [ + - ][ - + ]: 1235 : else if( pNameRecords[i].languageID == LANGUAGE_ENGLISH ||
1461 : 1235 : pNameRecords[i].languageID == LANGUAGE_ENGLISH_UK )
1462 : 0 : nMatch = 1500;
1463 : : else
1464 : 9653 : nMatch = 1000;
1465 : : }
1466 [ + - ]: 18461 : OUString aName = convertTrueTypeName( pNameRecords + i );
1467 [ + - ]: 18461 : aSet.insert( aName );
1468 [ + + ][ + - ]: 18461 : if( nMatch > nLastMatch || isBadTNR(aName, aSet) )
[ - + ][ + + ]
1469 : : {
1470 : 8613 : nLastMatch = nMatch;
1471 : 8613 : aFamily = aName;
1472 : : }
1473 : 18461 : }
1474 [ + - ]: 8418 : DisposeNameRecords( pNameRecords, nNameRecords );
1475 : : }
1476 [ + - ]: 8418 : if( !aFamily.isEmpty() )
1477 : : {
1478 [ + - ]: 8418 : rNames.push_front( aFamily );
1479 [ + + ]: 25904 : for( ::std::set< OUString >::const_iterator it = aSet.begin(); it != aSet.end(); ++it )
1480 [ + + ]: 17486 : if( *it != aFamily )
1481 [ + - ]: 9068 : rNames.push_back( *it );
1482 : : }
1483 : 8418 : return;
1484 : : }
1485 : :
1486 : : // -------------------------------------------------------------------------
1487 : :
1488 : 8418 : bool PrintFontManager::analyzeTrueTypeFile( PrintFont* pFont ) const
1489 : : {
1490 : 8418 : bool bSuccess = false;
1491 [ + - ]: 8418 : rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
1492 [ + - ]: 8418 : rtl::OString aFile = getFontFile( pFont );
1493 : 8418 : TrueTypeFont* pTTFont = NULL;
1494 : :
1495 : 8418 : TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont);
1496 [ + - ][ + - ]: 8418 : if( OpenTTFontFile( aFile.getStr(), pTTFontFile->m_nCollectionEntry, &pTTFont ) == SF_OK )
1497 : : {
1498 : : TTGlobalFontInfo aInfo;
1499 [ + - ]: 8418 : GetTTGlobalFontInfo( pTTFont, & aInfo );
1500 : :
1501 [ + - ]: 8418 : ::std::list< OUString > aNames;
1502 [ + - ]: 8418 : analyzeTrueTypeFamilyName( pTTFont, aNames );
1503 : :
1504 : : // set family name from XLFD if possible
1505 [ + + ]: 8418 : if( ! pFont->m_nFamilyName )
1506 : : {
1507 [ + - ]: 8297 : if( aNames.begin() != aNames.end() )
1508 : : {
1509 [ + - ][ + - ]: 8297 : pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, aNames.front(), sal_True );
1510 [ + - ]: 8297 : aNames.pop_front();
1511 : : }
1512 : : else
1513 : : {
1514 : : sal_Int32 dotIndex;
1515 : :
1516 : : // poor font does not have a family name
1517 : : // name it to file name minus the extension
1518 : 0 : dotIndex = pTTFontFile->m_aFontFile.lastIndexOf( '.' );
1519 [ # # ]: 0 : if ( dotIndex == -1 )
1520 : 0 : dotIndex = pTTFontFile->m_aFontFile.getLength();
1521 : :
1522 [ # # ][ # # ]: 0 : pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, OStringToOUString( pTTFontFile->m_aFontFile.copy( 0, dotIndex ), aEncoding ), sal_True );
1523 : : }
1524 : : }
1525 [ + + ]: 17607 : for( ::std::list< OUString >::iterator it = aNames.begin(); it != aNames.end(); ++it )
1526 : : {
1527 [ + + ]: 9189 : if( !it->isEmpty() )
1528 : : {
1529 [ + - ]: 771 : int nAlias = m_pAtoms->getAtom( ATOM_FAMILYNAME, *it, sal_True );
1530 [ + + ]: 771 : if( nAlias != pFont->m_nFamilyName )
1531 : : {
1532 [ + - ]: 650 : std::list< int >::const_iterator al_it;
1533 [ + - ][ + - ]: 845 : for( al_it = pFont->m_aAliases.begin(); al_it != pFont->m_aAliases.end() && *al_it != nAlias; ++al_it )
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + - ][ + +
# # # # ]
1534 : : ;
1535 [ + - ][ + - ]: 650 : if( al_it == pFont->m_aAliases.end() )
[ + - ]
1536 [ + - ]: 771 : pFont->m_aAliases.push_back( nAlias );
1537 : : }
1538 : : }
1539 : : }
1540 : :
1541 [ - + ]: 8418 : if( aInfo.usubfamily )
1542 : 0 : pFont->m_aStyleName = OUString( aInfo.usubfamily );
1543 : :
1544 : : SAL_WARN_IF( !aInfo.psname, "vcl", "No PostScript name in font:" << aFile.getStr() );
1545 : :
1546 : : rtl::OUString sPSName = aInfo.psname ?
1547 : : rtl::OUString(aInfo.psname, rtl_str_getLength(aInfo.psname), aEncoding) :
1548 [ + - ][ + - ]: 8418 : m_pAtoms->getString(ATOM_FAMILYNAME, pFont->m_nFamilyName); // poor font does not have a postscript name
[ # # ]
1549 : :
1550 [ + - ]: 8418 : pFont->m_nPSName = m_pAtoms->getAtom( ATOM_PSNAME, sPSName, sal_True );
1551 : :
1552 [ - + + + : 8418 : switch( aInfo.weight )
+ + - -
+ ]
1553 : : {
1554 : 0 : case FW_THIN: pFont->m_eWeight = WEIGHT_THIN; break;
1555 : 127 : case FW_EXTRALIGHT: pFont->m_eWeight = WEIGHT_ULTRALIGHT; break;
1556 : 260 : case FW_LIGHT: pFont->m_eWeight = WEIGHT_LIGHT; break;
1557 : 325 : case FW_MEDIUM: pFont->m_eWeight = WEIGHT_MEDIUM; break;
1558 : 189 : case FW_SEMIBOLD: pFont->m_eWeight = WEIGHT_SEMIBOLD; break;
1559 : 3122 : case FW_BOLD: pFont->m_eWeight = WEIGHT_BOLD; break;
1560 : 0 : case FW_EXTRABOLD: pFont->m_eWeight = WEIGHT_ULTRABOLD; break;
1561 : 0 : case FW_BLACK: pFont->m_eWeight = WEIGHT_BLACK; break;
1562 : :
1563 : : case FW_NORMAL:
1564 : 4395 : default: pFont->m_eWeight = WEIGHT_NORMAL; break;
1565 : : }
1566 : :
1567 [ - - + + : 8418 : switch( aInfo.width )
- - - -
+ ]
1568 : : {
1569 : 0 : case FWIDTH_ULTRA_CONDENSED: pFont->m_eWidth = WIDTH_ULTRA_CONDENSED; break;
1570 : 0 : case FWIDTH_EXTRA_CONDENSED: pFont->m_eWidth = WIDTH_EXTRA_CONDENSED; break;
1571 : 378 : case FWIDTH_CONDENSED: pFont->m_eWidth = WIDTH_CONDENSED; break;
1572 : 954 : case FWIDTH_SEMI_CONDENSED: pFont->m_eWidth = WIDTH_SEMI_CONDENSED; break;
1573 : 0 : case FWIDTH_SEMI_EXPANDED: pFont->m_eWidth = WIDTH_SEMI_EXPANDED; break;
1574 : 0 : case FWIDTH_EXPANDED: pFont->m_eWidth = WIDTH_EXPANDED; break;
1575 : 0 : case FWIDTH_EXTRA_EXPANDED: pFont->m_eWidth = WIDTH_EXTRA_EXPANDED; break;
1576 : 0 : case FWIDTH_ULTRA_EXPANDED: pFont->m_eWidth = WIDTH_ULTRA_EXPANDED; break;
1577 : :
1578 : : case FWIDTH_NORMAL:
1579 : 7086 : default: pFont->m_eWidth = WIDTH_NORMAL; break;
1580 : : }
1581 : :
1582 [ + + ]: 8418 : pFont->m_ePitch = aInfo.pitch ? PITCH_FIXED : PITCH_VARIABLE;
1583 [ + + ][ + - ]: 8418 : pFont->m_eItalic = aInfo.italicAngle == 0 ? ITALIC_NONE : ( aInfo.italicAngle < 0 ? ITALIC_NORMAL : ITALIC_OBLIQUE );
1584 : : // #104264# there are fonts that set italic angle 0 although they are
1585 : : // italic; use macstyle bit here
1586 [ + + ][ - + ]: 8418 : if( aInfo.italicAngle == 0 && (aInfo.macStyle & 2) )
1587 : 0 : pFont->m_eItalic = ITALIC_NORMAL;
1588 : :
1589 [ - + ]: 8418 : pFont->m_aEncoding = aInfo.symbolEncoded ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UCS2;
1590 : :
1591 : 8418 : pFont->m_aGlobalMetricY.width = pFont->m_aGlobalMetricX.width = aInfo.xMax - aInfo.xMin;
1592 : 8418 : pFont->m_aGlobalMetricY.height = pFont->m_aGlobalMetricX.height = aInfo.yMax - aInfo.yMin;
1593 : :
1594 [ + - ][ + - ]: 8418 : if( aInfo.winAscent && aInfo.winDescent )
1595 : : {
1596 : 8418 : pFont->m_nAscend = aInfo.winAscent;
1597 : 8418 : pFont->m_nDescend = aInfo.winDescent;
1598 : 8418 : pFont->m_nLeading = pFont->m_nAscend + pFont->m_nDescend - 1000;
1599 : : }
1600 [ # # ][ # # ]: 0 : else if( aInfo.typoAscender && aInfo.typoDescender )
1601 : : {
1602 : 0 : pFont->m_nLeading = aInfo.typoLineGap;
1603 : 0 : pFont->m_nAscend = aInfo.typoAscender;
1604 : 0 : pFont->m_nDescend = -aInfo.typoDescender;
1605 : : }
1606 : : else
1607 : : {
1608 : 0 : pFont->m_nLeading = aInfo.linegap;
1609 : 0 : pFont->m_nAscend = aInfo.ascender;
1610 : 0 : pFont->m_nDescend = -aInfo.descender;
1611 : : }
1612 : :
1613 : : // last try: font bounding box
1614 [ - + ]: 8418 : if( pFont->m_nAscend == 0 )
1615 : 0 : pFont->m_nAscend = aInfo.yMax;
1616 [ - + ]: 8418 : if( pFont->m_nDescend == 0 )
1617 : 0 : pFont->m_nDescend = -aInfo.yMin;
1618 [ - + ]: 8418 : if( pFont->m_nLeading == 0 )
1619 : 0 : pFont->m_nLeading = 15 * (pFont->m_nAscend+pFont->m_nDescend) / 100;
1620 : :
1621 [ + - ]: 8418 : if( pFont->m_nAscend )
1622 : 8418 : pFont->m_aGlobalMetricX.height = pFont->m_aGlobalMetricY.height = pFont->m_nAscend + pFont->m_nDescend;
1623 : :
1624 : : // get bounding box
1625 : 8418 : pFont->m_nXMin = aInfo.xMin;
1626 : 8418 : pFont->m_nYMin = aInfo.yMin;
1627 : 8418 : pFont->m_nXMax = aInfo.xMax;
1628 : 8418 : pFont->m_nYMax = aInfo.yMax;
1629 : :
1630 : : // get type flags
1631 : 8418 : pTTFontFile->m_nTypeFlags = (unsigned int)aInfo.typeFlags;
1632 : :
1633 : : // get vertical substitutions flag
1634 [ + - ]: 8418 : pFont->m_bHaveVerticalSubstitutedGlyphs = DoesVerticalSubstitution( pTTFont, 1 );
1635 : :
1636 [ + - ]: 8418 : CloseTTFont( pTTFont );
1637 : 8418 : bSuccess = true;
1638 : : }
1639 : : #if OSL_DEBUG_LEVEL > 1
1640 : : else
1641 : : fprintf( stderr, "could not OpenTTFont \"%s\"\n", aFile.getStr() );
1642 : : #endif
1643 : :
1644 : 8418 : return bSuccess;
1645 : : }
1646 : :
1647 : 233 : static bool AreFCSubstitutionsEnabled()
1648 : : {
1649 : 233 : return (SalGenericInstance::FetchFontSubstitutionFlags() & 3) == 0;
1650 : : }
1651 : :
1652 : 236 : void PrintFontManager::initialize()
1653 : : {
1654 : : #ifdef CALLGRIND_COMPILE
1655 : : CALLGRIND_TOGGLE_COLLECT();
1656 : : CALLGRIND_ZERO_STATS();
1657 : : #endif
1658 : :
1659 : : long aDirEntBuffer[ (sizeof(struct dirent)+_PC_NAME_MAX)+1 ];
1660 : :
1661 [ + - ]: 236 : if( ! m_pFontCache )
1662 : : {
1663 : : #if OSL_DEBUG_LEVEL > 1
1664 : : fprintf( stderr, "creating font cache ... " );
1665 : : clock_t aStart;
1666 : : struct tms tms;
1667 : : aStart = times( &tms );
1668 : : #endif
1669 [ + - ][ + - ]: 236 : m_pFontCache = new FontCache();
1670 : : #if OSL_DEBUG_LEVEL > 1
1671 : : clock_t aStop = times( &tms );
1672 : : fprintf( stderr, "done in %lf s\n", (double)(aStop - aStart)/(double)sysconf( _SC_CLK_TCK ) );
1673 : : #endif
1674 : : }
1675 : :
1676 : : // initialize may be called twice in the future
1677 : : {
1678 [ + - ][ + - ]: 236 : for( ::boost::unordered_map< fontID, PrintFont* >::const_iterator it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
[ - + ]
1679 [ # # ][ # # ]: 0 : delete (*it).second;
[ # # ]
1680 : 236 : m_nNextFontID = 1;
1681 [ + - ]: 236 : m_aFonts.clear();
1682 : 236 : m_aFontDirectories.clear();
1683 : 236 : m_aPrivateFontDirectories.clear();
1684 : 236 : m_aOverrideFonts.clear();
1685 : : }
1686 : :
1687 : : #if OSL_DEBUG_LEVEL > 1
1688 : : clock_t aStart;
1689 : : clock_t aStep1;
1690 : : clock_t aStep2;
1691 : : clock_t aStep3;
1692 : : int nBuiltinFonts = 0;
1693 : : int nCached = 0;
1694 : :
1695 : : struct tms tms;
1696 : :
1697 : : aStart = times( &tms );
1698 : : #endif
1699 : :
1700 : : // first try fontconfig
1701 [ + - ]: 236 : initFontconfig();
1702 : :
1703 : : // part one - look for downloadable fonts
1704 [ + - ]: 236 : rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
1705 [ + - ]: 236 : const ::rtl::OUString &rSalPrivatePath = psp::getFontPath();
1706 : :
1707 : : // search for the fonts in SAL_PRIVATE_FONTPATH first; those are
1708 : : // the fonts installed with the office
1709 [ + + ]: 236 : if( !rSalPrivatePath.isEmpty() )
1710 : : {
1711 [ + - ]: 233 : OString aPath = rtl::OUStringToOString( rSalPrivatePath, aEncoding );
1712 [ + - ]: 233 : const bool bAreFCSubstitutionsEnabled = AreFCSubstitutionsEnabled();
1713 : 233 : sal_Int32 nIndex = 0;
1714 [ + + ]: 549 : do
1715 : : {
1716 : 549 : OString aToken = aPath.getToken( 0, ';', nIndex );
1717 [ + - ]: 549 : normPath( aToken );
1718 [ - + ]: 549 : if ( aToken.isEmpty() )
1719 : : {
1720 : 0 : continue;
1721 : : }
1722 : : // if registering an app-specific fontdir with fontconfig fails
1723 : : // and fontconfig-based substitutions are enabled
1724 : : // then trying to use these app-specific fonts doesn't make sense
1725 [ + - ][ - + ]: 549 : if( !addFontconfigDir( aToken ) )
1726 [ # # ]: 0 : if( bAreFCSubstitutionsEnabled )
1727 : 0 : continue;
1728 [ + - ]: 549 : m_aFontDirectories.push_back( aToken );
1729 [ + - ][ + - ]: 549 : m_aPrivateFontDirectories.push_back( getDirectoryAtom( aToken, true ) );
[ + - ]
1730 : 233 : } while( nIndex >= 0 );
1731 : : }
1732 : :
1733 : : // protect against duplicate paths
1734 [ + - ]: 236 : boost::unordered_map< OString, int, OStringHash > visited_dirs;
1735 : :
1736 : : // Don't search directories that fontconfig already did
1737 [ + - ]: 236 : countFontconfigFonts( visited_dirs );
1738 : :
1739 : : // search for font files in each path
1740 : 236 : std::list< OString >::iterator dir_it;
1741 [ + + ]: 785 : for( dir_it = m_aFontDirectories.begin(); dir_it != m_aFontDirectories.end(); ++dir_it )
1742 : : {
1743 : 549 : OString aPath( *dir_it );
1744 : : // see if we were here already
1745 [ + - ][ + + ]: 549 : if( visited_dirs.find( aPath ) != visited_dirs.end() )
[ + - ]
1746 : 158 : continue;
1747 [ + - ]: 391 : visited_dirs[ aPath ] = 1;
1748 : :
1749 : : // there may be ":unscaled" directories (see XFree86)
1750 : : // it should be safe to ignore them since they should not
1751 : : // contain any of our recognizeable fonts
1752 : :
1753 : : // ask the font cache whether it handles this directory
1754 [ + - ]: 391 : std::list< PrintFont* > aCacheFonts;
1755 [ + - ][ - + ]: 391 : if( m_pFontCache->listDirectory( aPath, aCacheFonts ) )
1756 : : {
1757 : : #if OSL_DEBUG_LEVEL > 1
1758 : : fprintf( stderr, "adding cache directory: %s\n", aPath.getStr() );
1759 : : #endif
1760 [ # # ][ # # ]: 0 : for( ::std::list< PrintFont* >::iterator it = aCacheFonts.begin(); it != aCacheFonts.end(); ++it )
[ # # ]
1761 : : {
1762 : 0 : fontID aFont = m_nNextFontID++;
1763 [ # # ][ # # ]: 0 : m_aFonts[ aFont ] = *it;
1764 [ # # ][ # # ]: 0 : if( (*it)->m_eType == fonttype::Type1 )
1765 [ # # ][ # # ]: 0 : m_aFontFileToFontID[ static_cast<Type1FontFile*>(*it)->m_aFontFile ].insert( aFont );
[ # # ]
1766 [ # # ][ # # ]: 0 : else if( (*it)->m_eType == fonttype::TrueType )
1767 [ # # ][ # # ]: 0 : m_aFontFileToFontID[ static_cast<TrueTypeFontFile*>(*it)->m_aFontFile ].insert( aFont );
[ # # ]
1768 [ # # ][ # # ]: 0 : else if( (*it)->m_eType == fonttype::Builtin )
1769 [ # # ][ # # ]: 0 : m_aFontFileToFontID[ static_cast<BuiltinFont*>(*it)->m_aMetricFile ].insert( aFont );
[ # # ]
1770 : : #if OSL_DEBUG_LEVEL > 1
1771 : : if( (*it)->m_eType == fonttype::Builtin )
1772 : : nBuiltinFonts++;
1773 : : nCached++;
1774 : : #if OSL_DEBUG_LEVEL > 2
1775 : : fprintf( stderr, "adding cached font %d: %s\n", aFont, getFontFileSysPath( aFont ).getStr() );
1776 : : #endif
1777 : : #endif
1778 : : }
1779 [ # # ][ # # ]: 0 : if( ! m_pFontCache->scanAdditionalFiles( aPath ) )
1780 : 391 : continue;
1781 : : }
1782 : :
1783 [ - + ][ + + ]: 549 : }
1784 : :
1785 : : #if OSL_DEBUG_LEVEL > 1
1786 : : aStep1 = times( &tms );
1787 : : #endif
1788 : :
1789 : : // part two - look for metrics for builtin printer fonts
1790 [ + - ]: 236 : std::list< OUString > aMetricDirs;
1791 [ + - ]: 236 : psp::getPrinterPathList( aMetricDirs, PRINTER_METRICDIR );
1792 : :
1793 [ + + ]: 630 : for( std::list< OUString >::const_iterator met_dir_it = aMetricDirs.begin(); met_dir_it != aMetricDirs.end(); ++met_dir_it )
1794 : : {
1795 [ + - ]: 394 : OString aDir = OUStringToOString( *met_dir_it, aEncoding );
1796 : :
1797 : : // ask the font cache whether it handles this directory
1798 [ + - ]: 394 : std::list< PrintFont* > aCacheFonts;
1799 : :
1800 [ + - ][ + + ]: 394 : if( m_pFontCache->listDirectory( aDir, aCacheFonts ) )
1801 : : {
1802 : : #if OSL_DEBUG_LEVEL > 1
1803 : : fprintf( stderr, "adding cache directory: %s\n", aDir.getStr() );
1804 : : #endif
1805 [ + - ][ + - ]: 3243 : for( ::std::list< PrintFont* >::iterator it = aCacheFonts.begin(); it != aCacheFonts.end(); ++it )
[ + + ]
1806 : : {
1807 : 2976 : fontID aFont = m_nNextFontID++;
1808 [ + - ][ + - ]: 2976 : m_aFonts[ aFont ] = *it;
1809 [ + - ][ - + ]: 2976 : if( (*it)->m_eType == fonttype::Type1 )
1810 [ # # ][ # # ]: 0 : m_aFontFileToFontID[ static_cast<Type1FontFile*>(*it)->m_aFontFile ].insert( aFont );
[ # # ]
1811 [ + - ][ - + ]: 2976 : else if( (*it)->m_eType == fonttype::TrueType )
1812 [ # # ][ # # ]: 0 : m_aFontFileToFontID[ static_cast<TrueTypeFontFile*>(*it)->m_aFontFile ].insert( aFont );
[ # # ]
1813 [ + - ][ + - ]: 2976 : else if( (*it)->m_eType == fonttype::Builtin )
1814 [ + - ][ + - ]: 2976 : m_aFontFileToFontID[ static_cast<BuiltinFont*>(*it)->m_aMetricFile ].insert( aFont );
[ + - ]
1815 : : #if OSL_DEBUG_LEVEL > 1
1816 : : if( (*it)->m_eType == fonttype::Builtin )
1817 : : nBuiltinFonts++;
1818 : : nCached++;
1819 : : #if OSL_DEBUG_LEVEL > 2
1820 : : fprintf( stderr, "adding cached font %d: from %s\n", aFont,
1821 : : getFontFileSysPath( aFont ).getStr() );
1822 : : #endif
1823 : : #endif
1824 : : }
1825 : 267 : continue;
1826 : : }
1827 : :
1828 [ + - ]: 127 : DIR* pDIR = opendir( aDir.getStr() );
1829 [ + - ]: 127 : if( pDIR )
1830 : : {
1831 : 127 : struct dirent* pDirEntry = (struct dirent*)aDirEntBuffer;
1832 [ + - ]: 127 : int nDirID = getDirectoryAtom( aDir, true );
1833 : 127 : int nDirFonts = 0;
1834 : :
1835 [ + - ][ + - ]: 2306 : while( ! readdir_r( pDIR, (struct dirent*)aDirEntBuffer, &pDirEntry ) && pDirEntry )
[ + + ][ + + ]
1836 : : {
1837 [ + - ]: 2179 : rtl::OStringBuffer aFile(aDir);
1838 [ + - ][ + - ]: 2179 : aFile.append('/').append(pDirEntry->d_name);
1839 : : struct stat aStat;
1840 [ + - ][ + + ]: 2179 : if( ! stat( aFile.getStr(), &aStat )
[ + + ]
1841 : : && S_ISREG( aStat.st_mode )
1842 : : )
1843 : : {
1844 : 1925 : OString aFileName( pDirEntry->d_name, strlen( pDirEntry->d_name ) );
1845 : 1925 : OString aExt( aFileName.copy( aFileName.lastIndexOf( '.' )+1 ) );
1846 [ + + ]: 1925 : if( aExt.equalsIgnoreAsciiCase( "afm" ) )
1847 : : {
1848 [ + - ]: 1922 : ::std::list< PrintFont* > aNewFonts;
1849 : :
1850 [ + - ]: 1922 : analyzeFontFile( nDirID, aFileName, aNewFonts );
1851 [ + - ][ + - ]: 3844 : for( ::std::list< PrintFont* >::iterator it = aNewFonts.begin(); it != aNewFonts.end(); ++it )
[ + + ]
1852 : : {
1853 [ + - ][ + - ]: 1922 : if( findFontBuiltinID( (*it)->m_nPSName ) == 0 )
[ + - ]
1854 : : {
1855 [ + - ][ + - ]: 1922 : m_aFontFileToFontID[ aFileName ].insert( m_nNextFontID );
1856 [ + - ][ + - ]: 1922 : m_aFonts[ m_nNextFontID++ ] = *it;
1857 [ + - ][ + - ]: 1922 : m_pFontCache->updateFontCacheEntry( *it, false );
1858 : : #if OSL_DEBUG_LEVEL > 2
1859 : : nBuiltinFonts++;
1860 : : #endif
1861 : : }
1862 : : else
1863 [ # # ][ # # ]: 0 : delete *it;
[ # # ]
1864 : 1922 : }
1865 : 1925 : }
1866 : : }
1867 : 2179 : }
1868 [ + - ]: 127 : closedir( pDIR );
1869 [ + - ]: 127 : if( ! nDirFonts )
1870 [ + - ]: 127 : m_pFontCache->markEmptyDir( nDirID );
1871 : : }
1872 [ + + ][ + + ]: 394 : }
1873 : :
1874 : : #if OSL_DEBUG_LEVEL > 1
1875 : : aStep2 = times( &tms );
1876 : : #endif
1877 : :
1878 : : // part three - fill in family styles
1879 : 236 : ::boost::unordered_map< fontID, PrintFont* >::iterator font_it;
1880 [ + - ][ + + ]: 40096 : for (font_it = m_aFonts.begin(); font_it != m_aFonts.end(); ++font_it)
[ + - ]
1881 : : {
1882 : : ::boost::unordered_map< int, FontFamily >::const_iterator it =
1883 [ + - ][ + - ]: 39860 : m_aFamilyTypes.find( font_it->second->m_nFamilyName );
1884 [ + + ][ + - ]: 39860 : if (it != m_aFamilyTypes.end())
1885 : 25060 : continue;
1886 : : const ::rtl::OUString& rFamily =
1887 [ + - ][ + - ]: 14800 : m_pAtoms->getString( ATOM_FAMILYNAME, font_it->second->m_nFamilyName);
1888 [ + - ]: 14800 : FontFamily eType = matchFamilyName( rFamily );
1889 [ + - ][ + - ]: 14800 : m_aFamilyTypes[ font_it->second->m_nFamilyName ] = eType;
1890 : : }
1891 : :
1892 : : #if OSL_DEBUG_LEVEL > 1
1893 : : aStep3 = times( &tms );
1894 : : fprintf( stderr, "PrintFontManager::initialize: collected %" SAL_PRI_SIZET "u fonts (%d builtin, %d cached)\n", m_aFonts.size(), nBuiltinFonts, nCached );
1895 : : double fTick = (double)sysconf( _SC_CLK_TCK );
1896 : : fprintf( stderr, "Step 1 took %lf seconds\n", (double)(aStep1 - aStart)/fTick );
1897 : : fprintf( stderr, "Step 2 took %lf seconds\n", (double)(aStep2 - aStep1)/fTick );
1898 : : fprintf( stderr, "Step 3 took %lf seconds\n", (double)(aStep3 - aStep2)/fTick );
1899 : : #endif
1900 : :
1901 [ + - ][ + - ]: 236 : m_pFontCache->flush();
1902 : :
1903 : : #ifdef CALLGRIND_COMPILE
1904 : : CALLGRIND_DUMP_STATS();
1905 : : CALLGRIND_TOGGLE_COLLECT();
1906 : : #endif
1907 : 236 : }
1908 : :
1909 : : // -------------------------------------------------------------------------
1910 : : inline bool
1911 : 0 : equalPitch (FontPitch from, FontPitch to)
1912 : : {
1913 : 0 : return from == to;
1914 : : }
1915 : :
1916 : : inline bool
1917 : 0 : equalWeight (FontWeight from, FontWeight to)
1918 : : {
1919 [ # # ]: 0 : return from > to ? (from - to) <= 3 : (to - from) <= 3;
1920 : : }
1921 : :
1922 : : inline bool
1923 : 0 : equalItalic (FontItalic from, FontItalic to)
1924 : : {
1925 [ # # ][ # # ]: 0 : if ( (from == ITALIC_NORMAL) || (from == ITALIC_OBLIQUE) )
1926 [ # # ][ # # ]: 0 : return (to == ITALIC_NORMAL) || (to == ITALIC_OBLIQUE);
1927 : 0 : return to == from;
1928 : : }
1929 : : inline bool
1930 : 0 : equalEncoding (rtl_TextEncoding from, rtl_TextEncoding to)
1931 : : {
1932 [ # # ][ # # ]: 0 : if ((from == RTL_TEXTENCODING_ISO_8859_1) || (from == RTL_TEXTENCODING_MS_1252))
1933 [ # # ][ # # ]: 0 : return (to == RTL_TEXTENCODING_ISO_8859_1) || (to == RTL_TEXTENCODING_MS_1252);
1934 : 0 : return from == to;
1935 : : }
1936 : :
1937 : : namespace {
1938 : 29412 : struct BuiltinFontIdentifier
1939 : : {
1940 : : OUString aFamily;
1941 : : FontItalic eItalic;
1942 : : FontWeight eWeight;
1943 : : FontPitch ePitch;
1944 : : rtl_TextEncoding aEncoding;
1945 : :
1946 : 22344 : BuiltinFontIdentifier( const OUString& rFam,
1947 : : FontItalic eIt,
1948 : : FontWeight eWg,
1949 : : FontPitch ePt,
1950 : : rtl_TextEncoding enc ) :
1951 : : aFamily( rFam ),
1952 : : eItalic( eIt ),
1953 : : eWeight( eWg ),
1954 : : ePitch( ePt ),
1955 : 22344 : aEncoding( enc )
1956 : 22344 : {}
1957 : :
1958 : 0 : bool operator==( const BuiltinFontIdentifier& rRight ) const
1959 : : {
1960 : 0 : return equalItalic( eItalic, rRight.eItalic ) &&
1961 : 0 : equalWeight( eWeight, rRight.eWeight ) &&
1962 : 0 : equalPitch( ePitch, rRight.ePitch ) &&
1963 : 0 : equalEncoding( aEncoding, rRight.aEncoding ) &&
1964 [ # # ][ # # : 0 : aFamily.equalsIgnoreAsciiCase( rRight.aFamily );
# # # # #
# ]
1965 : : }
1966 : : };
1967 : :
1968 : : struct BuiltinFontIdentifierHash
1969 : : {
1970 : 22344 : size_t operator()( const BuiltinFontIdentifier& rFont ) const
1971 : : {
1972 : 22344 : return rFont.aFamily.hashCode() ^ rFont.eItalic ^ rFont.eWeight ^ rFont.ePitch ^ rFont.aEncoding;
1973 : : }
1974 : : };
1975 : : }
1976 : :
1977 : 359 : void PrintFontManager::getFontList( ::std::list< fontID >& rFontIDs, const PPDParser* pParser, bool bUseOverrideMetrics )
1978 : : {
1979 : 359 : rFontIDs.clear();
1980 : 359 : boost::unordered_map< fontID, PrintFont* >::const_iterator it;
1981 : :
1982 : : /*
1983 : : * Note: there are two easy steps making this faster:
1984 : : * first: insert the printer builtins first, then the not builtins,
1985 : : * if they do not match.
1986 : : * drawback: this would change the sequence of fonts; this could have
1987 : : * subtle, unknown consequences in vcl font matching
1988 : : * second: instead of comparing attributes to see whether a softfont
1989 : : * is duplicate to a builtin one could simply compare the PSName (which is
1990 : : * supposed to be unique), which at this point is just an int.
1991 : : * drawback: this could change which fonts are listed; especially TrueType
1992 : : * fonts often have a rather dubious PSName, so this could change the
1993 : : * font list not so subtle.
1994 : : * Until getFontList for a printer becomes a performance issue (which is
1995 : : * currently not the case), best stay with the current algorithm.
1996 : : */
1997 : :
1998 : : // fill sets of printer supported fonts
1999 [ + + ]: 359 : if( pParser )
2000 : : {
2001 [ + - ]: 114 : std::set<int> aBuiltinPSNames;
2002 : : boost::unordered_set< BuiltinFontIdentifier,
2003 : : BuiltinFontIdentifierHash
2004 [ + - ]: 114 : > aBuiltinFonts;
2005 : :
2006 [ + - ]: 114 : std::map<int, fontID > aOverridePSNames;
2007 [ + + ]: 114 : if( bUseOverrideMetrics )
2008 : : {
2009 [ + - ]: 2 : readOverrideMetrics();
2010 [ + - ]: 4 : for( std::vector<fontID>::const_iterator over = m_aOverrideFonts.begin();
[ # # + - ]
[ - + ]
2011 : 2 : over != m_aOverrideFonts.end(); ++over )
2012 : : {
2013 [ # # ][ # # ]: 0 : boost::unordered_map<fontID,PrintFont*>::const_iterator font_it = m_aFonts.find( *over );
2014 : : DBG_ASSERT( font_it != m_aFonts.end(), "override to nonexistant font" );
2015 [ # # ][ # # ]: 0 : if( font_it != m_aFonts.end() )
2016 [ # # ][ # # ]: 0 : aOverridePSNames[ font_it->second->m_nPSName ] = *over;
[ # # ]
2017 : : }
2018 : : }
2019 : :
2020 [ + - ]: 114 : int nFonts = pParser->getFonts();
2021 [ + + ]: 4104 : for( int i = 0; i < nFonts; i++ )
2022 [ + - ][ + - ]: 3990 : aBuiltinPSNames.insert( m_pAtoms->getAtom( ATOM_PSNAME, pParser->getFont( i ) ) );
[ + - ][ + - ]
[ + - ]
2023 [ + - ][ + - ]: 22458 : for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
[ + + ]
2024 : : {
2025 [ + - ]: 22344 : PrintFont* pFont = it->second;
2026 [ + - ][ + + ]: 48222 : if( it->second->m_eType == fonttype::Builtin &&
[ + - ][ + + ]
2027 [ + - ][ + - ]: 25878 : aBuiltinPSNames.find( pFont->m_nPSName ) != aBuiltinPSNames.end() )
[ + + ][ + + ]
[ # # # # ]
2028 : : {
2029 : 3534 : bool bInsert = true;
2030 [ + + ]: 3534 : if( bUseOverrideMetrics )
2031 : : {
2032 : : // in override case only use the override fonts, not their counterparts
2033 [ + - ][ + - ]: 62 : std::map<int,fontID>::const_iterator over = aOverridePSNames.find( pFont->m_nPSName );
2034 [ + - ][ + - ]: 62 : if( over != aOverridePSNames.end() && over->second != it->first )
[ - + ][ # # ]
[ # # ][ # # ]
[ + - ][ + - ]
[ - + # #
# # ]
2035 : 62 : bInsert = false;
2036 : : }
2037 : : else
2038 : : {
2039 : : // do not insert override fonts in non override case
2040 [ + - ][ + - ]: 3472 : if( std::find( m_aOverrideFonts.begin(), m_aOverrideFonts.end(), it->first ) != m_aOverrideFonts.end() )
[ + - ][ - + ]
2041 : 0 : bInsert = false;
2042 : : }
2043 [ + - ]: 3534 : if( bInsert )
2044 : : {
2045 : : aBuiltinFonts.insert( BuiltinFontIdentifier(
2046 [ + - ]: 3534 : m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ),
2047 : : pFont->m_eItalic,
2048 : : pFont->m_eWeight,
2049 : : pFont->m_ePitch,
2050 : : pFont->m_aEncoding
2051 [ + - ]: 3534 : ) );
2052 : : }
2053 : : }
2054 : : }
2055 [ + - ][ + - ]: 22458 : for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
[ + + ]
2056 : : {
2057 [ + - ]: 22344 : PrintFont* pFont = it->second;
2058 [ + - ][ + + ]: 22344 : if( it->second->m_eType == fonttype::Builtin )
2059 : : {
2060 [ + - ][ + - ]: 3534 : if( aBuiltinPSNames.find( pFont->m_nPSName ) != aBuiltinPSNames.end() )
[ + - ]
2061 : : {
2062 : 3534 : bool bInsert = true;
2063 [ + + ]: 3534 : if( bUseOverrideMetrics )
2064 : : {
2065 : : // in override case only use the override fonts, not their counterparts
2066 [ + - ][ + - ]: 62 : std::map<int,fontID>::const_iterator over = aOverridePSNames.find( pFont->m_nPSName );
2067 [ + - ][ + - ]: 62 : if( over != aOverridePSNames.end() && over->second != it->first )
[ - + ][ # # ]
[ # # ][ # # ]
[ + - ][ + - ]
[ - + # #
# # ]
2068 : 62 : bInsert = false;
2069 : : }
2070 : : else
2071 : : {
2072 : : // do not insert override fonts in non override case
2073 [ + - ][ + - ]: 3472 : if( std::find( m_aOverrideFonts.begin(), m_aOverrideFonts.end(), it->first ) != m_aOverrideFonts.end() )
[ + - ][ - + ]
2074 : 0 : bInsert = false;
2075 : : }
2076 [ + - ]: 3534 : if( bInsert )
2077 [ + - ][ + - ]: 3534 : rFontIDs.push_back( it->first );
2078 : : }
2079 : : }
2080 [ + - ]: 37620 : else if( aBuiltinFonts.find( BuiltinFontIdentifier(
2081 [ + - ]: 18810 : m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ),
2082 : : pFont->m_eItalic,
2083 : : pFont->m_eWeight,
2084 : : pFont->m_ePitch,
2085 : : pFont->m_aEncoding
2086 [ + - ][ + - ]: 56430 : ) ) == aBuiltinFonts.end() )
2087 : : {
2088 [ + - ][ + - ]: 18810 : rFontIDs.push_back( it->first );
2089 : : }
2090 [ + - ]: 114 : }
2091 : : }
2092 : : else // no specific printer
2093 : : {
2094 [ + - ][ + - ]: 41131 : for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
[ + + ]
2095 [ + - ][ + - ]: 40886 : rFontIDs.push_back( it->first );
2096 : : }
2097 : 359 : }
2098 : :
2099 : : // -------------------------------------------------------------------------
2100 : :
2101 : 72100 : void PrintFontManager::fillPrintFontInfo( PrintFont* pFont, FastPrintFontInfo& rInfo ) const
2102 : : {
2103 : : ::boost::unordered_map< int, FontFamily >::const_iterator style_it =
2104 [ + - ]: 72100 : m_aFamilyTypes.find( pFont->m_nFamilyName );
2105 : 72100 : rInfo.m_eType = pFont->m_eType;
2106 [ + - ]: 72100 : rInfo.m_aFamilyName = m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName );
2107 : 72100 : rInfo.m_aStyleName = pFont->m_aStyleName;
2108 [ + - ][ + - ]: 72100 : rInfo.m_eFamilyStyle = style_it != m_aFamilyTypes.end() ? style_it->second : FAMILY_DONTKNOW;
[ + - ]
2109 : 72100 : rInfo.m_eItalic = pFont->m_eItalic;
2110 : 72100 : rInfo.m_eWidth = pFont->m_eWidth;
2111 : 72100 : rInfo.m_eWeight = pFont->m_eWeight;
2112 : 72100 : rInfo.m_ePitch = pFont->m_ePitch;
2113 : 72100 : rInfo.m_aEncoding = pFont->m_aEncoding;
2114 : :
2115 : 72100 : rInfo.m_bEmbeddable = (pFont->m_eType == fonttype::Type1);
2116 : 72100 : rInfo.m_bSubsettable = (pFont->m_eType == fonttype::TrueType); // TODO: rename to SfntType
2117 : :
2118 : 72100 : rInfo.m_aAliases.clear();
2119 [ + - ][ + - ]: 77006 : for( ::std::list< int >::iterator it = pFont->m_aAliases.begin(); it != pFont->m_aAliases.end(); ++it )
[ + + ]
2120 [ + - ][ + - ]: 4906 : rInfo.m_aAliases.push_back( m_pAtoms->getString( ATOM_FAMILYNAME, *it ) );
[ + - ]
2121 : 72100 : }
2122 : :
2123 : : // -------------------------------------------------------------------------
2124 : :
2125 : 121 : void PrintFontManager::fillPrintFontInfo( PrintFont* pFont, PrintFontInfo& rInfo ) const
2126 : : {
2127 [ - + ][ # # ]: 121 : if( ( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 ) ||
[ - + # # ]
[ + - ]
2128 : 0 : ! pFont->m_pMetrics || pFont->m_pMetrics->isEmpty()
2129 : : )
2130 : : {
2131 : : // might be a truetype font not analyzed or type1 without metrics read
2132 [ - + ]: 121 : if( pFont->m_eType == fonttype::Type1 )
2133 [ # # ]: 0 : pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, false );
2134 [ + - ]: 121 : else if( pFont->m_eType == fonttype::TrueType )
2135 : 121 : analyzeTrueTypeFile( pFont );
2136 : : }
2137 : :
2138 : 121 : fillPrintFontInfo( pFont, static_cast< FastPrintFontInfo& >( rInfo ) );
2139 : :
2140 : 121 : rInfo.m_nAscend = pFont->m_nAscend;
2141 : 121 : rInfo.m_nDescend = pFont->m_nDescend;
2142 : 121 : rInfo.m_nLeading = pFont->m_nLeading;
2143 : 121 : rInfo.m_nWidth = pFont->m_aGlobalMetricX.width < pFont->m_aGlobalMetricY.width ? pFont->m_aGlobalMetricY.width : pFont->m_aGlobalMetricX.width;
2144 : 121 : }
2145 : :
2146 : : // -------------------------------------------------------------------------
2147 : :
2148 : 0 : void PrintFontManager::getFontListWithFastInfo( ::std::list< FastPrintFontInfo >& rFonts, const PPDParser* pParser, bool bUseOverrideMetrics )
2149 : : {
2150 : 0 : rFonts.clear();
2151 [ # # ]: 0 : ::std::list< fontID > aFontList;
2152 [ # # ]: 0 : getFontList( aFontList, pParser, bUseOverrideMetrics );
2153 : :
2154 [ # # ]: 0 : ::std::list< fontID >::iterator it;
2155 [ # # ][ # # ]: 0 : for( it = aFontList.begin(); it != aFontList.end(); ++it )
[ # # ]
2156 : : {
2157 [ # # ]: 0 : FastPrintFontInfo aInfo;
2158 [ # # ]: 0 : aInfo.m_nID = *it;
2159 [ # # ][ # # ]: 0 : fillPrintFontInfo( getFont( *it ), aInfo );
[ # # ]
2160 [ # # ]: 0 : rFonts.push_back( aInfo );
2161 : 0 : }
2162 : 0 : }
2163 : :
2164 : : // -------------------------------------------------------------------------
2165 : :
2166 : 121 : bool PrintFontManager::getFontInfo( fontID nFontID, PrintFontInfo& rInfo ) const
2167 : : {
2168 : 121 : PrintFont* pFont = getFont( nFontID );
2169 [ + - ]: 121 : if( pFont )
2170 : : {
2171 : 121 : rInfo.m_nID = nFontID;
2172 : 121 : fillPrintFontInfo( pFont, rInfo );
2173 : : }
2174 : 121 : return pFont ? true : false;
2175 : : }
2176 : :
2177 : : // -------------------------------------------------------------------------
2178 : :
2179 : 71979 : bool PrintFontManager::getFontFastInfo( fontID nFontID, FastPrintFontInfo& rInfo ) const
2180 : : {
2181 : 71979 : PrintFont* pFont = getFont( nFontID );
2182 [ + - ]: 71979 : if( pFont )
2183 : : {
2184 : 71979 : rInfo.m_nID = nFontID;
2185 : 71979 : fillPrintFontInfo( pFont, rInfo );
2186 : : }
2187 : 71979 : return pFont ? true : false;
2188 : : }
2189 : :
2190 : : // -------------------------------------------------------------------------
2191 : :
2192 : 0 : bool PrintFontManager::getFontBoundingBox( fontID nFontID, int& xMin, int& yMin, int& xMax, int& yMax )
2193 : : {
2194 : 0 : bool bSuccess = false;
2195 : 0 : PrintFont* pFont = getFont( nFontID );
2196 [ # # ]: 0 : if( pFont )
2197 : : {
2198 [ # # ][ # # ]: 0 : if( pFont->m_nXMin == 0 && pFont->m_nYMin == 0 && pFont->m_nXMax == 0 && pFont->m_nYMax == 0 )
[ # # ][ # # ]
2199 : : {
2200 : : // might be a truetype font not analyzed or type1 without metrics read
2201 [ # # ][ # # ]: 0 : if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
2202 [ # # ]: 0 : pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true );
2203 [ # # ]: 0 : else if( pFont->m_eType == fonttype::TrueType )
2204 : 0 : analyzeTrueTypeFile( pFont );
2205 : : }
2206 : 0 : bSuccess = true;
2207 : 0 : xMin = pFont->m_nXMin;
2208 : 0 : yMin = pFont->m_nYMin;
2209 : 0 : xMax = pFont->m_nXMax;
2210 : 0 : yMax = pFont->m_nYMax;
2211 : : }
2212 : 0 : return bSuccess;
2213 : : }
2214 : :
2215 : : // -------------------------------------------------------------------------
2216 : :
2217 : 35988 : int PrintFontManager::getFontFaceNumber( fontID nFontID ) const
2218 : : {
2219 : 35988 : int nRet = 0;
2220 : 35988 : PrintFont* pFont = getFont( nFontID );
2221 [ + + ][ + - ]: 35988 : if( pFont && pFont->m_eType == fonttype::TrueType )
2222 : 27413 : nRet = static_cast< TrueTypeFontFile* >(pFont)->m_nCollectionEntry;
2223 [ - + ]: 35988 : if (nRet < 0)
2224 : 0 : nRet = 0;
2225 : 35988 : return nRet;
2226 : : }
2227 : :
2228 : : // -------------------------------------------------------------------------
2229 : :
2230 : :
2231 : 14800 : FontFamily PrintFontManager::matchFamilyName( const ::rtl::OUString& rFamily ) const
2232 : : {
2233 : : typedef struct {
2234 : : const char* mpName;
2235 : : sal_uInt16 mnLength;
2236 : : FontFamily meType;
2237 : : } family_t;
2238 : :
2239 : : #define InitializeClass( p, a ) p, sizeof(p) - 1, a
2240 : : const family_t pFamilyMatch[] = {
2241 : : { InitializeClass( "arial", FAMILY_SWISS ) },
2242 : : { InitializeClass( "arioso", FAMILY_SCRIPT ) },
2243 : : { InitializeClass( "avant garde", FAMILY_SWISS ) },
2244 : : { InitializeClass( "avantgarde", FAMILY_SWISS ) },
2245 : : { InitializeClass( "bembo", FAMILY_ROMAN ) },
2246 : : { InitializeClass( "bookman", FAMILY_ROMAN ) },
2247 : : { InitializeClass( "conga", FAMILY_ROMAN ) },
2248 : : { InitializeClass( "courier", FAMILY_MODERN ) },
2249 : : { InitializeClass( "curl", FAMILY_SCRIPT ) },
2250 : : { InitializeClass( "fixed", FAMILY_MODERN ) },
2251 : : { InitializeClass( "gill", FAMILY_SWISS ) },
2252 : : { InitializeClass( "helmet", FAMILY_MODERN ) },
2253 : : { InitializeClass( "helvetica", FAMILY_SWISS ) },
2254 : : { InitializeClass( "international", FAMILY_MODERN ) },
2255 : : { InitializeClass( "lucida", FAMILY_SWISS ) },
2256 : : { InitializeClass( "new century schoolbook", FAMILY_ROMAN ) },
2257 : : { InitializeClass( "palatino", FAMILY_ROMAN ) },
2258 : : { InitializeClass( "roman", FAMILY_ROMAN ) },
2259 : : { InitializeClass( "sans serif", FAMILY_SWISS ) },
2260 : : { InitializeClass( "sansserif", FAMILY_SWISS ) },
2261 : : { InitializeClass( "serf", FAMILY_ROMAN ) },
2262 : : { InitializeClass( "serif", FAMILY_ROMAN ) },
2263 : : { InitializeClass( "times", FAMILY_ROMAN ) },
2264 : : { InitializeClass( "utopia", FAMILY_ROMAN ) },
2265 : : { InitializeClass( "zapf chancery", FAMILY_SCRIPT ) },
2266 : : { InitializeClass( "zapfchancery", FAMILY_SCRIPT ) }
2267 : 14800 : };
2268 : :
2269 [ + - ]: 14800 : rtl::OString aFamily = rtl::OUStringToOString( rFamily, RTL_TEXTENCODING_ASCII_US );
2270 : 14800 : sal_uInt32 nLower = 0;
2271 : 14800 : sal_uInt32 nUpper = SAL_N_ELEMENTS(pFamilyMatch);
2272 : :
2273 [ + + ]: 86120 : while( nLower < nUpper )
2274 : : {
2275 : 72110 : sal_uInt32 nCurrent = (nLower + nUpper) / 2;
2276 : 72110 : const family_t* pHaystack = pFamilyMatch + nCurrent;
2277 : : sal_Int32 nComparison =
2278 : : rtl_str_compareIgnoreAsciiCase_WithLength
2279 : : (
2280 : : aFamily.getStr(), aFamily.getLength(),
2281 : : pHaystack->mpName, pHaystack->mnLength
2282 : 72110 : );
2283 : :
2284 [ + + ]: 72110 : if( nComparison < 0 )
2285 : 45972 : nUpper = nCurrent;
2286 : : else
2287 [ + + ]: 26138 : if( nComparison > 0 )
2288 : 25348 : nLower = nCurrent + 1;
2289 : : else
2290 : 790 : return pHaystack->meType;
2291 : : }
2292 : :
2293 : 14800 : return FAMILY_DONTKNOW;
2294 : : }
2295 : :
2296 : : // -------------------------------------------------------------------------
2297 : :
2298 : 2292 : OString PrintFontManager::getAfmFile( PrintFont* pFont ) const
2299 : : {
2300 : 2292 : OString aMetricPath;
2301 [ + - ]: 2292 : if( pFont )
2302 : : {
2303 [ + - - ]: 2292 : switch( pFont->m_eType )
2304 : : {
2305 : : case fonttype::Type1:
2306 : : {
2307 : 2292 : Type1FontFile* pPSFont = static_cast< Type1FontFile* >(pFont);
2308 [ + - ]: 2292 : aMetricPath = getDirectory( pPSFont->m_nDirectory );
2309 : 2292 : aMetricPath += "/";
2310 : 2292 : aMetricPath += pPSFont->m_aMetricFile;
2311 : : }
2312 : 2292 : break;
2313 : : case fonttype::Builtin:
2314 : : {
2315 : 0 : BuiltinFont* pBuiltinFont = static_cast< BuiltinFont* >(pFont);
2316 [ # # ]: 0 : aMetricPath = getDirectory( pBuiltinFont->m_nDirectory );
2317 : 0 : aMetricPath += "/";
2318 : 0 : aMetricPath += pBuiltinFont->m_aMetricFile;
2319 : : }
2320 : 0 : break;
2321 : 2292 : default: break;
2322 : : }
2323 : : }
2324 : 2292 : return aMetricPath;
2325 : : }
2326 : :
2327 : : // -------------------------------------------------------------------------
2328 : :
2329 : 59226 : OString PrintFontManager::getFontFile( PrintFont* pFont ) const
2330 : : {
2331 : 59226 : OString aPath;
2332 : :
2333 [ + + ][ + - ]: 59226 : if( pFont && pFont->m_eType == fonttype::Type1 )
2334 : : {
2335 : 8575 : Type1FontFile* pPSFont = static_cast< Type1FontFile* >(pFont);
2336 [ + - ]: 8575 : ::boost::unordered_map< int, OString >::const_iterator it = m_aAtomToDir.find( pPSFont->m_nDirectory );
2337 [ + - ]: 8575 : aPath = it->second;
2338 : 8575 : aPath += "/";
2339 : 8575 : aPath += pPSFont->m_aFontFile;
2340 : : }
2341 [ + - ][ + - ]: 50651 : else if( pFont && pFont->m_eType == fonttype::TrueType )
2342 : : {
2343 : 50651 : TrueTypeFontFile* pTTFont = static_cast< TrueTypeFontFile* >(pFont);
2344 [ + - ]: 50651 : ::boost::unordered_map< int, OString >::const_iterator it = m_aAtomToDir.find( pTTFont->m_nDirectory );
2345 [ + - ]: 50651 : aPath = it->second;
2346 : 50651 : aPath += "/";
2347 : 50651 : aPath += pTTFont->m_aFontFile;
2348 : : }
2349 : 59226 : return aPath;
2350 : : }
2351 : :
2352 : : // -------------------------------------------------------------------------
2353 : :
2354 : 0 : const ::rtl::OUString& PrintFontManager::getPSName( fontID nFontID ) const
2355 : : {
2356 : 0 : PrintFont* pFont = getFont( nFontID );
2357 [ # # ][ # # ]: 0 : if( pFont && pFont->m_nPSName == 0 )
2358 : : {
2359 [ # # ]: 0 : if( pFont->m_eType == fonttype::TrueType )
2360 : 0 : analyzeTrueTypeFile( pFont );
2361 : : }
2362 : :
2363 [ # # ]: 0 : return m_pAtoms->getString( ATOM_PSNAME, pFont ? pFont->m_nPSName : INVALID_ATOM );
2364 : : }
2365 : :
2366 : : // -------------------------------------------------------------------------
2367 : :
2368 : 0 : int PrintFontManager::getFontAscend( fontID nFontID ) const
2369 : : {
2370 : 0 : PrintFont* pFont = getFont( nFontID );
2371 [ # # ][ # # ]: 0 : if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
2372 : : {
2373 : : // might be a truetype font not yet analyzed
2374 [ # # ]: 0 : if( pFont->m_eType == fonttype::TrueType )
2375 : 0 : analyzeTrueTypeFile( pFont );
2376 [ # # ][ # # ]: 0 : else if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
2377 [ # # ]: 0 : pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true );
2378 : : }
2379 : 0 : return pFont->m_nAscend;
2380 : : }
2381 : :
2382 : : // -------------------------------------------------------------------------
2383 : :
2384 : 0 : int PrintFontManager::getFontDescend( fontID nFontID ) const
2385 : : {
2386 : 0 : PrintFont* pFont = getFont( nFontID );
2387 [ # # ][ # # ]: 0 : if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
2388 : : {
2389 : : // might be a truetype font not yet analyzed
2390 [ # # ]: 0 : if( pFont->m_eType == fonttype::TrueType )
2391 : 0 : analyzeTrueTypeFile( pFont );
2392 [ # # ][ # # ]: 0 : else if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
2393 [ # # ]: 0 : pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true );
2394 : : }
2395 : 0 : return pFont->m_nDescend;
2396 : : }
2397 : :
2398 : : // -------------------------------------------------------------------------
2399 : :
2400 : 0 : void PrintFontManager::hasVerticalSubstitutions( fontID nFontID,
2401 : : const sal_Unicode* pCharacters, int nCharacters, bool* pHasSubst ) const
2402 : : {
2403 : 0 : PrintFont* pFont = getFont( nFontID );
2404 [ # # ][ # # ]: 0 : if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
2405 : : {
2406 : : // might be a truetype font not yet analyzed
2407 [ # # ]: 0 : if( pFont->m_eType == fonttype::TrueType )
2408 : 0 : analyzeTrueTypeFile( pFont );
2409 : : }
2410 : :
2411 [ # # ]: 0 : if( ! pFont->m_bHaveVerticalSubstitutedGlyphs )
2412 : 0 : memset( pHasSubst, 0, sizeof(bool)*nCharacters );
2413 : : else
2414 : : {
2415 [ # # ]: 0 : for( int i = 0; i < nCharacters; i++ )
2416 : : {
2417 : 0 : sal_Unicode code = pCharacters[i];
2418 [ # # ][ # # ]: 0 : if( ! pFont->m_pMetrics ||
2419 : 0 : ! ( pFont->m_pMetrics->m_aPages[ code >> 11 ] & ( 1 << ( ( code >> 8 ) & 7 ) ) ) )
2420 [ # # ]: 0 : pFont->queryMetricPage( code >> 8, m_pAtoms );
2421 [ # # ]: 0 : ::boost::unordered_map< sal_Unicode, bool >::const_iterator it = pFont->m_pMetrics->m_bVerticalSubstitutions.find( code );
2422 [ # # ]: 0 : pHasSubst[i] = it != pFont->m_pMetrics->m_bVerticalSubstitutions.end();
2423 : : }
2424 : : }
2425 : 0 : }
2426 : :
2427 : : // -------------------------------------------------------------------------
2428 : :
2429 : 17 : const ::std::list< KernPair >& PrintFontManager::getKernPairs( fontID nFontID, bool bVertical ) const
2430 : : {
2431 [ + + ][ + - ]: 17 : static ::std::list< KernPair > aEmpty;
[ + - ][ # # ]
2432 : :
2433 : 17 : PrintFont* pFont = getFont( nFontID );
2434 [ - + ]: 17 : if( ! pFont )
2435 : 0 : return aEmpty;
2436 : :
2437 [ - + ][ # # ]: 17 : if( ! pFont->m_pMetrics || ! pFont->m_pMetrics->m_bKernPairsQueried )
2438 : 17 : pFont->queryMetricPage( 0, m_pAtoms );
2439 [ + - ][ - + ]: 17 : if( ! pFont->m_pMetrics || ! pFont->m_pMetrics->m_bKernPairsQueried )
2440 : 0 : return aEmpty;
2441 [ - + ]: 17 : return bVertical ? pFont->m_pMetrics->m_aYKernPairs : pFont->m_pMetrics->m_aXKernPairs;
2442 : : }
2443 : :
2444 : : // -------------------------------------------------------------------------
2445 : :
2446 : 0 : bool PrintFontManager::isFontDownloadingAllowed( fontID nFont ) const
2447 : : {
2448 [ # # ][ # # ]: 0 : static const char* pEnable = getenv( "PSPRINT_ENABLE_TTF_COPYRIGHTAWARENESS" );
2449 : 0 : bool bRet = true;
2450 : :
2451 [ # # ][ # # ]: 0 : if( pEnable && *pEnable )
2452 : : {
2453 : 0 : PrintFont* pFont = getFont( nFont );
2454 [ # # ][ # # ]: 0 : if( pFont && pFont->m_eType == fonttype::TrueType )
2455 : : {
2456 : 0 : TrueTypeFontFile* pTTFontFile = static_cast<TrueTypeFontFile*>(pFont);
2457 [ # # ]: 0 : if( pTTFontFile->m_nTypeFlags & TYPEFLAG_INVALID )
2458 : : {
2459 : 0 : TrueTypeFont* pTTFont = NULL;
2460 [ # # ]: 0 : rtl::OString aFile = getFontFile( pFont );
2461 [ # # ][ # # ]: 0 : if( OpenTTFontFile( aFile.getStr(), pTTFontFile->m_nCollectionEntry, &pTTFont ) == SF_OK )
2462 : : {
2463 : : // get type flags
2464 : : TTGlobalFontInfo aInfo;
2465 [ # # ]: 0 : GetTTGlobalFontInfo( pTTFont, & aInfo );
2466 : 0 : pTTFontFile->m_nTypeFlags = (unsigned int)aInfo.typeFlags;
2467 [ # # ]: 0 : CloseTTFont( pTTFont );
2468 : 0 : }
2469 : : }
2470 : :
2471 : 0 : unsigned int nCopyrightFlags = pTTFontFile->m_nTypeFlags & TYPEFLAG_COPYRIGHT_MASK;
2472 : :
2473 : : // font embedding is allowed if either
2474 : : // no restriction at all (bit 1 clear)
2475 : : // printing allowed (bit 1 set, bit 2 set )
2476 [ # # ][ # # ]: 0 : bRet = ! ( nCopyrightFlags & 0x02 ) || ( nCopyrightFlags & 0x04 );
2477 : : }
2478 : : }
2479 : 0 : return bRet;
2480 : : }
2481 : :
2482 : : // -------------------------------------------------------------------------
2483 : :
2484 : 0 : bool PrintFontManager::getMetrics( fontID nFontID, const sal_Unicode* pString, int nLen, CharacterMetric* pArray, bool bVertical ) const
2485 : : {
2486 : 0 : PrintFont* pFont = getFont( nFontID );
2487 [ # # ]: 0 : if( ! pFont )
2488 : 0 : return false;
2489 : :
2490 [ # # ][ # # ]: 0 : if( ( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
[ # # # # ]
[ # # ]
2491 : 0 : || ! pFont->m_pMetrics || pFont->m_pMetrics->isEmpty()
2492 : : )
2493 : : {
2494 : : // might be a font not yet analyzed
2495 [ # # ][ # # ]: 0 : if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
2496 [ # # ]: 0 : pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, false );
2497 [ # # ]: 0 : else if( pFont->m_eType == fonttype::TrueType )
2498 : 0 : analyzeTrueTypeFile( pFont );
2499 : : }
2500 : :
2501 [ # # ]: 0 : for( int i = 0; i < nLen; i++ )
2502 : : {
2503 [ # # ][ # # ]: 0 : if( ! pFont->m_pMetrics ||
2504 : 0 : ! ( pFont->m_pMetrics->m_aPages[ pString[i] >> 11 ] & ( 1 << ( ( pString[i] >> 8 ) & 7 ) ) ) )
2505 : 0 : pFont->queryMetricPage( pString[i] >> 8, m_pAtoms );
2506 : 0 : pArray[i].width = pArray[i].height = -1;
2507 [ # # ]: 0 : if( pFont->m_pMetrics )
2508 : : {
2509 : 0 : int effectiveCode = pString[i];
2510 [ # # ]: 0 : effectiveCode |= bVertical ? 1 << 16 : 0;
2511 : : ::boost::unordered_map< int, CharacterMetric >::const_iterator it =
2512 [ # # ]: 0 : pFont->m_pMetrics->m_aMetrics.find( effectiveCode );
2513 : : // if no vertical metrics are available assume rotated horizontal metrics
2514 [ # # ][ # # ]: 0 : if( bVertical && (it == pFont->m_pMetrics->m_aMetrics.end()) )
[ # # ][ # # ]
[ # # # #
# # ][ # # ]
2515 [ # # ]: 0 : it = pFont->m_pMetrics->m_aMetrics.find( pString[i] );
2516 : : // the character metrics are in it->second
2517 [ # # ][ # # ]: 0 : if( it != pFont->m_pMetrics->m_aMetrics.end() )
2518 [ # # ]: 0 : pArray[ i ] = it->second;
2519 : : }
2520 : : }
2521 : :
2522 : 0 : return true;
2523 : : }
2524 : :
2525 : : // -------------------------------------------------------------------------
2526 : :
2527 : 0 : bool PrintFontManager::getMetrics( fontID nFontID, sal_Unicode minCharacter, sal_Unicode maxCharacter, CharacterMetric* pArray, bool bVertical ) const
2528 : : {
2529 : : OSL_PRECOND(minCharacter <= maxCharacter, "invalid char. range");
2530 [ # # ]: 0 : if (minCharacter > maxCharacter)
2531 : 0 : return false;
2532 : :
2533 : 0 : PrintFont* pFont = getFont( nFontID );
2534 [ # # ]: 0 : if( ! pFont )
2535 : 0 : return false;
2536 : :
2537 [ # # ][ # # ]: 0 : if( ( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
[ # # # # ]
[ # # ]
2538 : 0 : || ! pFont->m_pMetrics || pFont->m_pMetrics->isEmpty()
2539 : : )
2540 : : {
2541 : : // might be a font not yet analyzed
2542 [ # # ][ # # ]: 0 : if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
2543 [ # # ]: 0 : pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, false );
2544 [ # # ]: 0 : else if( pFont->m_eType == fonttype::TrueType )
2545 : 0 : analyzeTrueTypeFile( pFont );
2546 : : }
2547 : :
2548 : 0 : sal_Unicode code = minCharacter;
2549 [ # # ]: 0 : do
2550 : : {
2551 [ # # ][ # # ]: 0 : if( ! pFont->m_pMetrics ||
2552 : 0 : ! ( pFont->m_pMetrics->m_aPages[ code >> 11 ] & ( 1 << ( ( code >> 8 ) & 7 ) ) ) )
2553 : 0 : pFont->queryMetricPage( code >> 8, m_pAtoms );
2554 : 0 : pArray[ code - minCharacter ].width = -1;
2555 : 0 : pArray[ code - minCharacter ].height = -1;
2556 [ # # ]: 0 : if( pFont->m_pMetrics )
2557 : : {
2558 : 0 : int effectiveCode = code;
2559 [ # # ]: 0 : effectiveCode |= bVertical ? 1 << 16 : 0;
2560 : : ::boost::unordered_map< int, CharacterMetric >::const_iterator it =
2561 [ # # ]: 0 : pFont->m_pMetrics->m_aMetrics.find( effectiveCode );
2562 : : // if no vertical metrics are available assume rotated horizontal metrics
2563 [ # # ][ # # ]: 0 : if( bVertical && (it == pFont->m_pMetrics->m_aMetrics.end()) )
[ # # ][ # # ]
[ # # # #
# # ][ # # ]
2564 [ # # ]: 0 : it = pFont->m_pMetrics->m_aMetrics.find( code );
2565 : : // the character metrics are in it->second
2566 [ # # ][ # # ]: 0 : if( it != pFont->m_pMetrics->m_aMetrics.end() )
2567 [ # # ]: 0 : pArray[ code - minCharacter ] = it->second;
2568 : : }
2569 : : } while( code++ != maxCharacter );
2570 : :
2571 : 0 : return true;
2572 : : }
2573 : :
2574 : : // -------------------------------------------------------------------------
2575 : :
2576 : : // TODO: move most of this stuff into the central font-subsetting code
2577 : 0 : bool PrintFontManager::createFontSubset(
2578 : : FontSubsetInfo& rInfo,
2579 : : fontID nFont,
2580 : : const OUString& rOutFile,
2581 : : sal_Int32* pGlyphIDs,
2582 : : sal_uInt8* pNewEncoding,
2583 : : sal_Int32* pWidths,
2584 : : int nGlyphs,
2585 : : bool bVertical
2586 : : )
2587 : : {
2588 [ # # ]: 0 : PrintFont* pFont = getFont( nFont );
2589 [ # # ]: 0 : if( !pFont )
2590 : 0 : return false;
2591 : :
2592 [ # # # ]: 0 : switch( pFont->m_eType )
2593 : : {
2594 : 0 : case psp::fonttype::TrueType: rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; break;
2595 : 0 : case psp::fonttype::Type1: rInfo.m_nFontType = FontSubsetInfo::ANY_TYPE1; break;
2596 : : default:
2597 : 0 : return false;
2598 : : }
2599 : : // TODO: remove when Type1 subsetting gets implemented
2600 [ # # ]: 0 : if( pFont->m_eType != fonttype::TrueType )
2601 : 0 : return false;
2602 : :
2603 : : // reshuffle array of requested glyphs to make sure glyph0==notdef
2604 : : sal_uInt8 pEnc[256];
2605 : : sal_uInt16 pGID[256];
2606 : : sal_uInt8 pOldIndex[256];
2607 : 0 : memset( pEnc, 0, sizeof( pEnc ) );
2608 : 0 : memset( pGID, 0, sizeof( pGID ) );
2609 : 0 : memset( pOldIndex, 0, sizeof( pOldIndex ) );
2610 [ # # ]: 0 : if( nGlyphs > 256 )
2611 : 0 : return false;
2612 : 0 : int nChar = 1;
2613 [ # # ]: 0 : for( int i = 0; i < nGlyphs; i++ )
2614 : : {
2615 [ # # ]: 0 : if( pNewEncoding[i] == 0 )
2616 : : {
2617 : 0 : pOldIndex[ 0 ] = i;
2618 : : }
2619 : : else
2620 : : {
2621 : : DBG_ASSERT( !(pGlyphIDs[i] & 0x007f0000), "overlong glyph id" );
2622 : : DBG_ASSERT( (int)pNewEncoding[i] < nGlyphs, "encoding wrong" );
2623 : : DBG_ASSERT( pEnc[pNewEncoding[i]] == 0 && pGID[pNewEncoding[i]] == 0, "duplicate encoded glyph" );
2624 : 0 : pEnc[ pNewEncoding[i] ] = pNewEncoding[i];
2625 : 0 : pGID[ pNewEncoding[i] ] = (sal_uInt16)pGlyphIDs[ i ];
2626 : 0 : pOldIndex[ pNewEncoding[i] ] = i;
2627 : 0 : nChar++;
2628 : : }
2629 : : }
2630 : 0 : nGlyphs = nChar; // either input value or increased by one
2631 : :
2632 : : // prepare system name for read access for subset source file
2633 : : // TODO: since this file is usually already mmapped there is no need to open it again
2634 [ # # ]: 0 : const rtl::OString aFromFile = getFontFile( pFont );
2635 : :
2636 : 0 : TrueTypeFont* pTTFont = NULL; // TODO: rename to SfntFont
2637 : 0 : TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont);
2638 [ # # ][ # # ]: 0 : if( OpenTTFontFile( aFromFile.getStr(), pTTFontFile->m_nCollectionEntry, &pTTFont ) != SF_OK )
2639 : 0 : return false;
2640 : :
2641 : : // prepare system name for write access for subset file target
2642 : 0 : OUString aSysPath;
2643 [ # # ][ # # ]: 0 : if( osl_File_E_None != osl_getSystemPathFromFileURL( rOutFile.pData, &aSysPath.pData ) )
2644 : 0 : return false;
2645 [ # # ]: 0 : const rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
2646 [ # # ]: 0 : const rtl::OString aToFile( OUStringToOString( aSysPath, aEncoding ) );
2647 : :
2648 : : // do CFF subsetting if possible
2649 : 0 : int nCffLength = 0;
2650 : 0 : const sal_uInt8* pCffBytes = NULL;
2651 [ # # ][ # # ]: 0 : if( GetSfntTable( pTTFont, O_CFF, &pCffBytes, &nCffLength ) )
2652 : : {
2653 [ # # ]: 0 : rInfo.LoadFont( FontSubsetInfo::CFF_FONT, pCffBytes, nCffLength );
2654 : : #if 1 // TODO: remove 16bit->long conversion when related methods handle non-16bit glyphids
2655 : : long aRequestedGlyphs[256];
2656 [ # # ]: 0 : for( int i = 0; i < nGlyphs; ++i )
2657 : 0 : aRequestedGlyphs[i] = pGID[i];
2658 : : #endif
2659 : : // create subset file at requested path
2660 [ # # ]: 0 : FILE* pOutFile = fopen( aToFile.getStr(), "wb" );
2661 : : // create font subset
2662 : 0 : const char* pGlyphSetName = NULL; // TODO: better name?
2663 : : const bool bOK = rInfo.CreateFontSubset(
2664 : : FontSubsetInfo::TYPE1_PFB,
2665 : : pOutFile, pGlyphSetName,
2666 [ # # ]: 0 : aRequestedGlyphs, pEnc, nGlyphs, pWidths );
2667 [ # # ]: 0 : fclose( pOutFile );
2668 : : // cleanup before early return
2669 [ # # ]: 0 : CloseTTFont( pTTFont );
2670 : 0 : return bOK;
2671 : : }
2672 : :
2673 : : // do TTF->Type42 or Type3 subsetting
2674 : : // fill in font info
2675 [ # # ]: 0 : psp::PrintFontInfo aFontInfo;
2676 [ # # ][ # # ]: 0 : if( ! getFontInfo( nFont, aFontInfo ) )
2677 : 0 : return false;
2678 : :
2679 : 0 : rInfo.m_nAscent = aFontInfo.m_nAscend;
2680 : 0 : rInfo.m_nDescent = aFontInfo.m_nDescend;
2681 [ # # ][ # # ]: 0 : rInfo.m_aPSName = getPSName( nFont );
2682 : :
2683 : : int xMin, yMin, xMax, yMax;
2684 [ # # ]: 0 : getFontBoundingBox( nFont, xMin, yMin, xMax, yMax );
2685 [ # # ]: 0 : rInfo.m_aFontBBox = Rectangle( Point( xMin, yMin ), Size( xMax-xMin, yMax-yMin ) );
2686 : 0 : rInfo.m_nCapHeight = yMax; // Well ...
2687 : :
2688 : : // fill in glyph advance widths
2689 : : TTSimpleGlyphMetrics* pMetrics = GetTTSimpleGlyphMetrics( pTTFont,
2690 : : pGID,
2691 : : nGlyphs,
2692 [ # # ][ # # ]: 0 : bVertical ? 1 : 0 );
2693 [ # # ]: 0 : if( pMetrics )
2694 : : {
2695 [ # # ]: 0 : for( int i = 0; i < nGlyphs; i++ )
2696 : 0 : pWidths[pOldIndex[i]] = pMetrics[i].adv;
2697 : 0 : free( pMetrics );
2698 : : }
2699 : : else
2700 : : {
2701 [ # # ]: 0 : CloseTTFont( pTTFont );
2702 : 0 : return false;
2703 : : }
2704 : :
2705 : : bool bSuccess = ( SF_OK == CreateTTFromTTGlyphs( pTTFont,
2706 : : aToFile.getStr(),
2707 : : pGID,
2708 : : pEnc,
2709 : : nGlyphs,
2710 : : 0,
2711 : : NULL,
2712 [ # # ]: 0 : 0 ) );
2713 [ # # ]: 0 : CloseTTFont( pTTFont );
2714 : :
2715 : 0 : return bSuccess;
2716 : : }
2717 : :
2718 : 0 : void PrintFontManager::getGlyphWidths( fontID nFont,
2719 : : bool bVertical,
2720 : : std::vector< sal_Int32 >& rWidths,
2721 : : std::map< sal_Unicode, sal_uInt32 >& rUnicodeEnc )
2722 : : {
2723 : 0 : PrintFont* pFont = getFont( nFont );
2724 [ # # ][ # # ]: 0 : if( !pFont ||
[ # # ]
2725 : : (pFont->m_eType != fonttype::TrueType && pFont->m_eType != fonttype::Type1) )
2726 : 0 : return;
2727 [ # # ]: 0 : if( pFont->m_eType == fonttype::TrueType )
2728 : : {
2729 : 0 : TrueTypeFont* pTTFont = NULL;
2730 : 0 : TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont);
2731 [ # # ]: 0 : rtl::OString aFromFile = getFontFile( pFont );
2732 [ # # ][ # # ]: 0 : if( OpenTTFontFile( aFromFile.getStr(), pTTFontFile->m_nCollectionEntry, &pTTFont ) != SF_OK )
2733 : : return;
2734 [ # # ]: 0 : int nGlyphs = GetTTGlyphCount( pTTFont );
2735 [ # # ]: 0 : if( nGlyphs > 0 )
2736 : : {
2737 [ # # ]: 0 : rWidths.resize(nGlyphs);
2738 [ # # ]: 0 : std::vector<sal_uInt16> aGlyphIds(nGlyphs);
2739 [ # # ]: 0 : for( int i = 0; i < nGlyphs; i++ )
2740 [ # # ]: 0 : aGlyphIds[i] = sal_uInt16(i);
2741 : : TTSimpleGlyphMetrics* pMetrics = GetTTSimpleGlyphMetrics( pTTFont,
2742 [ # # ]: 0 : &aGlyphIds[0],
2743 : : nGlyphs,
2744 [ # # ][ # # ]: 0 : bVertical ? 1 : 0 );
2745 [ # # ]: 0 : if( pMetrics )
2746 : : {
2747 [ # # ]: 0 : for( int i = 0; i< nGlyphs; i++ )
2748 [ # # ]: 0 : rWidths[i] = pMetrics[i].adv;
2749 : 0 : free( pMetrics );
2750 : 0 : rUnicodeEnc.clear();
2751 : : }
2752 : :
2753 : : // fill the unicode map
2754 : : // TODO: isn't this map already available elsewhere in the fontmanager?
2755 : 0 : const sal_uInt8* pCmapData = NULL;
2756 : 0 : int nCmapSize = 0;
2757 [ # # ][ # # ]: 0 : if( GetSfntTable( pTTFont, O_cmap, &pCmapData, &nCmapSize ) )
2758 : : {
2759 [ # # ]: 0 : CmapResult aCmapResult;
2760 [ # # ][ # # ]: 0 : if( ParseCMAP( pCmapData, nCmapSize, aCmapResult ) )
2761 : : {
2762 [ # # ]: 0 : const ImplFontCharMap aCharMap( aCmapResult );
2763 : 0 : for( sal_uInt32 cOld = 0;;)
2764 : : {
2765 : : // get next unicode covered by font
2766 [ # # ]: 0 : const sal_uInt32 c = aCharMap.GetNextChar( cOld );
2767 [ # # ]: 0 : if( c == cOld )
2768 : 0 : break;
2769 : 0 : cOld = c;
2770 : : #if 1 // TODO: remove when sal_Unicode covers all of unicode
2771 [ # # ]: 0 : if( c > (sal_Unicode)~0 )
2772 : 0 : break;
2773 : : #endif
2774 : : // get the matching glyph index
2775 [ # # ]: 0 : const sal_uInt32 nGlyphId = aCharMap.GetGlyphIndex( c );
2776 : : // update the requested map
2777 [ # # ]: 0 : rUnicodeEnc[ (sal_Unicode)c ] = nGlyphId;
2778 [ # # ]: 0 : }
2779 : : }
2780 : 0 : }
2781 : : }
2782 [ # # ][ # # ]: 0 : CloseTTFont( pTTFont );
2783 : : }
2784 [ # # ]: 0 : else if( pFont->m_eType == fonttype::Type1 )
2785 : : {
2786 [ # # ]: 0 : if( ! pFont->m_aEncodingVector.size() )
2787 [ # # ]: 0 : pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, true, true );
2788 [ # # ]: 0 : if( pFont->m_pMetrics )
2789 : : {
2790 : 0 : rUnicodeEnc.clear();
2791 : 0 : rWidths.clear();
2792 : 0 : rWidths.reserve( pFont->m_pMetrics->m_aMetrics.size() );
2793 [ # # ]: 0 : for( boost::unordered_map< int, CharacterMetric >::const_iterator it =
2794 [ # # ]: 0 : pFont->m_pMetrics->m_aMetrics.begin();
2795 [ # # ]: 0 : it != pFont->m_pMetrics->m_aMetrics.end(); ++it )
2796 : : {
2797 [ # # ][ # # ]: 0 : if( (it->first & 0x00010000) == 0 || bVertical )
[ # # ][ # # ]
2798 : : {
2799 [ # # ][ # # ]: 0 : rUnicodeEnc[ sal_Unicode(it->first & 0x0000ffff) ] = sal_uInt32(rWidths.size());
2800 [ # # ][ # # ]: 0 : rWidths.push_back( it->second.width );
2801 : : }
2802 : : }
2803 : : }
2804 : : }
2805 : : }
2806 : :
2807 : : // -------------------------------------------------------------------------
2808 : :
2809 : 0 : const std::map< sal_Unicode, sal_Int32 >* PrintFontManager::getEncodingMap( fontID nFont, const std::map< sal_Unicode, rtl::OString >** pNonEncoded ) const
2810 : : {
2811 : 0 : PrintFont* pFont = getFont( nFont );
2812 [ # # ][ # # ]: 0 : if( !pFont ||
[ # # ]
2813 : : (pFont->m_eType != fonttype::Type1 && pFont->m_eType != fonttype::Builtin)
2814 : : )
2815 : 0 : return NULL;
2816 : :
2817 [ # # ]: 0 : if( ! pFont->m_aEncodingVector.size() )
2818 [ # # ]: 0 : pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, true, true );
2819 : :
2820 [ # # ]: 0 : if( pNonEncoded )
2821 [ # # ]: 0 : *pNonEncoded = pFont->m_aNonEncoded.size() ? &pFont->m_aNonEncoded : NULL;
2822 : :
2823 [ # # ]: 0 : return pFont->m_aEncodingVector.size() ? &pFont->m_aEncodingVector : NULL;
2824 : : }
2825 : :
2826 : : // -------------------------------------------------------------------------
2827 : :
2828 : 0 : std::list< OString > PrintFontManager::getAdobeNameFromUnicode( sal_Unicode aChar ) const
2829 : : {
2830 : : std::pair< boost::unordered_multimap< sal_Unicode, rtl::OString >::const_iterator,
2831 : : boost::unordered_multimap< sal_Unicode, rtl::OString >::const_iterator > range
2832 [ # # ]: 0 : = m_aUnicodeToAdobename.equal_range( aChar );
2833 : :
2834 [ # # ]: 0 : std::list< OString > aRet;
2835 [ # # ]: 0 : for( ; range.first != range.second; ++range.first )
2836 [ # # ][ # # ]: 0 : aRet.push_back( range.first->second );
2837 : :
2838 [ # # ][ # # ]: 0 : if( aRet.begin() == aRet.end() && aChar != 0 )
[ # # ][ # # ]
[ # # ]
2839 : : {
2840 : : sal_Char aBuf[8];
2841 : 0 : sal_Int32 nChars = snprintf( (char*)aBuf, sizeof( aBuf ), "uni%.4hX", aChar );
2842 [ # # ]: 0 : aRet.push_back( OString( aBuf, nChars ) );
2843 : : }
2844 : :
2845 : 0 : return aRet;
2846 : : }
2847 : :
2848 : : // -------------------------------------------------------------------------
2849 : 4410 : std::list< sal_Unicode > PrintFontManager::getUnicodeFromAdobeName( const rtl::OString& rName ) const
2850 : : {
2851 : : std::pair< boost::unordered_multimap< rtl::OString, sal_Unicode, rtl::OStringHash >::const_iterator,
2852 : : boost::unordered_multimap< rtl::OString, sal_Unicode, rtl::OStringHash >::const_iterator > range
2853 [ + - ]: 4410 : = m_aAdobenameToUnicode.equal_range( rName );
2854 : :
2855 [ + - ]: 4410 : std::list< sal_Unicode > aRet;
2856 [ + + ]: 8132 : for( ; range.first != range.second; ++range.first )
2857 [ + - ][ + - ]: 3722 : aRet.push_back( range.first->second );
2858 : :
2859 [ + - ][ + + ]: 4410 : if( aRet.begin() == aRet.end() )
2860 : : {
2861 [ + - ][ + - ]: 776 : if( rName.getLength() == 7 && rName.indexOf( "uni" ) == 0 )
[ + - ]
2862 : : {
2863 : 776 : sal_Unicode aCode = (sal_Unicode)rName.copy( 3 ).toInt32( 16 );
2864 [ + - ]: 4410 : aRet.push_back( aCode );
2865 : : }
2866 : : }
2867 : :
2868 : 4410 : return aRet;
2869 : : }
2870 : :
2871 : : // -------------------------------------------------------------------------
2872 : : namespace
2873 : : {
2874 : 0 : OUString getString( const Any& rAny )
2875 : : {
2876 : 0 : OUString aStr;
2877 : 0 : rAny >>= aStr;
2878 : 0 : return aStr;
2879 : : }
2880 : 0 : bool getBool( const Any& rAny )
2881 : : {
2882 : 0 : sal_Bool bBool = sal_False;
2883 : 0 : rAny >>= bBool;
2884 : 0 : return static_cast<bool>(bBool);
2885 : : }
2886 : 0 : sal_Int32 getInt( const Any& rAny )
2887 : : {
2888 : 0 : sal_Int32 n = 0;
2889 : 0 : rAny >>= n;
2890 : 0 : return n;
2891 : : }
2892 : : }
2893 : 2 : bool PrintFontManager::readOverrideMetrics()
2894 : : {
2895 [ - + ]: 2 : if( ! m_aOverrideFonts.empty() )
2896 : 0 : return false;
2897 : :
2898 [ + - ]: 2 : css::uno::Reference< XMultiServiceFactory > xFact( comphelper::getProcessServiceFactory() );
2899 [ - + ]: 2 : if( !xFact.is() )
2900 : 0 : return false;
2901 : : css::uno::Reference< XMaterialHolder > xMat(
2902 [ + - ]: 2 : xFact->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.psprint.CompatMetricOverride" ) ) ),
2903 [ + - ][ + - ]: 2 : UNO_QUERY );
[ + - ]
2904 [ + - ]: 2 : if( !xMat.is() )
2905 : 2 : return false;
2906 : :
2907 [ # # ][ # # ]: 0 : Any aAny( xMat->getMaterial() );
2908 [ # # ]: 0 : Sequence< Any > aOverrideFonts;
2909 [ # # ][ # # ]: 0 : if( ! (aAny >>= aOverrideFonts ) )
2910 : 0 : return false;
2911 : 0 : sal_Int32 nFonts = aOverrideFonts.getLength();
2912 [ # # ]: 0 : for( sal_Int32 i = 0; i < nFonts; i++ )
2913 : : {
2914 [ # # ]: 0 : Sequence< NamedValue > aMetrics;
2915 [ # # ][ # # ]: 0 : if( ! (aOverrideFonts.getConstArray()[i] >>= aMetrics) )
2916 : 0 : continue;
2917 [ # # ][ # # ]: 0 : BuiltinFont* pFont = new BuiltinFont();
2918 : 0 : pFont->m_nDirectory = 0;
2919 : 0 : pFont->m_bUserOverride = false;
2920 [ # # ][ # # ]: 0 : pFont->m_pMetrics = new PrintFontMetrics;
2921 : 0 : memset( pFont->m_pMetrics->m_aPages, 0xff, sizeof( pFont->m_pMetrics->m_aPages ) );
2922 : 0 : pFont->m_pMetrics->m_bKernPairsQueried = true;
2923 : 0 : sal_Int32 nProps = aMetrics.getLength();
2924 : 0 : const NamedValue* pProps = aMetrics.getConstArray();
2925 [ # # ]: 0 : for( sal_Int32 n = 0; n < nProps; n++ )
2926 : : {
2927 [ # # ]: 0 : if ( pProps[n].Name == "FamilyName" )
2928 : : pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME,
2929 : 0 : getString(pProps[n].Value),
2930 [ # # ]: 0 : sal_True );
2931 [ # # ]: 0 : else if ( pProps[n].Name == "PSName" )
2932 : : pFont->m_nPSName = m_pAtoms->getAtom( ATOM_PSNAME,
2933 : 0 : getString(pProps[n].Value),
2934 [ # # ]: 0 : sal_True );
2935 [ # # ]: 0 : else if ( pProps[n].Name == "StyleName" )
2936 : 0 : pFont->m_aStyleName = getString(pProps[n].Value);
2937 [ # # ]: 0 : else if ( pProps[n].Name == "Italic" )
2938 : 0 : pFont->m_eItalic = static_cast<FontItalic>(getInt(pProps[n].Value));
2939 [ # # ]: 0 : else if ( pProps[n].Name == "Width" )
2940 : 0 : pFont->m_eWidth = static_cast<FontWidth>(getInt(pProps[n].Value));
2941 [ # # ]: 0 : else if ( pProps[n].Name == "Weight" )
2942 : 0 : pFont->m_eWeight = static_cast<FontWeight>(getInt(pProps[n].Value));
2943 [ # # ]: 0 : else if ( pProps[n].Name == "Pitch" )
2944 : 0 : pFont->m_ePitch = static_cast<FontPitch>(getInt(pProps[n].Value));
2945 [ # # ]: 0 : else if ( pProps[n].Name == "Encoding" )
2946 : 0 : pFont->m_aEncoding = static_cast<rtl_TextEncoding>(getInt(pProps[n].Value));
2947 [ # # ]: 0 : else if ( pProps[n].Name == "FontEncodingOnly" )
2948 : 0 : pFont->m_bFontEncodingOnly = getBool(pProps[n].Value);
2949 [ # # ]: 0 : else if ( pProps[n].Name == "GlobalMetricXWidth" )
2950 : 0 : pFont->m_aGlobalMetricX.width = getInt(pProps[n].Value);
2951 [ # # ]: 0 : else if ( pProps[n].Name == "GlobalMetricXHeight" )
2952 : 0 : pFont->m_aGlobalMetricX.height = getInt(pProps[n].Value);
2953 [ # # ]: 0 : else if ( pProps[n].Name == "GlobalMetricYWidth" )
2954 : 0 : pFont->m_aGlobalMetricY.width = getInt(pProps[n].Value);
2955 [ # # ]: 0 : else if ( pProps[n].Name == "GlobalMetricYHeight" )
2956 : 0 : pFont->m_aGlobalMetricY.height = getInt(pProps[n].Value);
2957 [ # # ]: 0 : else if ( pProps[n].Name == "Ascend" )
2958 : 0 : pFont->m_nAscend = getInt(pProps[n].Value);
2959 [ # # ]: 0 : else if ( pProps[n].Name == "Descend" )
2960 : 0 : pFont->m_nDescend = getInt(pProps[n].Value);
2961 [ # # ]: 0 : else if ( pProps[n].Name == "Leading" )
2962 : 0 : pFont->m_nLeading = getInt(pProps[n].Value);
2963 [ # # ]: 0 : else if ( pProps[n].Name == "XMin" )
2964 : 0 : pFont->m_nXMin = getInt(pProps[n].Value);
2965 [ # # ]: 0 : else if ( pProps[n].Name == "YMin" )
2966 : 0 : pFont->m_nYMin = getInt(pProps[n].Value);
2967 [ # # ]: 0 : else if ( pProps[n].Name == "XMax" )
2968 : 0 : pFont->m_nXMax = getInt(pProps[n].Value);
2969 [ # # ]: 0 : else if ( pProps[n].Name == "YMax" )
2970 : 0 : pFont->m_nYMax = getInt(pProps[n].Value);
2971 [ # # ]: 0 : else if ( pProps[n].Name == "VerticalSubstitutes" )
2972 : 0 : pFont->m_bHaveVerticalSubstitutedGlyphs = getBool(pProps[n].Value);
2973 [ # # ]: 0 : else if ( pProps[n].Name == "EncodingVector" )
2974 : : {
2975 [ # # ]: 0 : Sequence< NamedValue > aEncoding;
2976 [ # # ]: 0 : pProps[n].Value >>= aEncoding;
2977 : 0 : sal_Int32 nEnc = aEncoding.getLength();
2978 : 0 : const NamedValue* pEnc = aEncoding.getConstArray();
2979 [ # # ]: 0 : for( sal_Int32 m = 0; m < nEnc; m++ )
2980 : : {
2981 : 0 : sal_Unicode cCode = *pEnc[m].Name.getStr();
2982 : 0 : sal_Int32 nGlyph = getInt(pEnc[m].Value);
2983 [ # # ]: 0 : pFont->m_aEncodingVector[ cCode ] = nGlyph;
2984 [ # # ]: 0 : }
2985 : : }
2986 [ # # ]: 0 : else if ( pProps[n].Name == "NonEncoded" )
2987 : : {
2988 [ # # ]: 0 : Sequence< NamedValue > aEncoding;
2989 [ # # ]: 0 : pProps[n].Value >>= aEncoding;
2990 : 0 : sal_Int32 nEnc = aEncoding.getLength();
2991 : 0 : const NamedValue* pEnc = aEncoding.getConstArray();
2992 [ # # ]: 0 : for( sal_Int32 m = 0; m < nEnc; m++ )
2993 : : {
2994 : 0 : sal_Unicode cCode = *pEnc[m].Name.getStr();
2995 : 0 : OUString aGlyphName( getString(pEnc[m].Value) );
2996 [ # # ][ # # ]: 0 : pFont->m_aNonEncoded[ cCode ] = OUStringToOString(aGlyphName,RTL_TEXTENCODING_ASCII_US);
2997 [ # # ]: 0 : }
2998 : : }
2999 [ # # ]: 0 : else if ( pProps[n].Name == "CharacterMetrics" )
3000 : : {
3001 : : // fill pFont->m_pMetrics->m_aMetrics
3002 : : // expect triples of int: int -> CharacterMetric.{ width, height }
3003 [ # # ]: 0 : Sequence< sal_Int32 > aSeq;
3004 [ # # ]: 0 : pProps[n].Value >>= aSeq;
3005 : 0 : sal_Int32 nInts = aSeq.getLength();
3006 : 0 : const sal_Int32* pInts = aSeq.getConstArray();
3007 [ # # ]: 0 : for( sal_Int32 m = 0; m < nInts; m+=3 )
3008 : : {
3009 [ # # ]: 0 : pFont->m_pMetrics->m_aMetrics[ pInts[m] ].width = static_cast<short int>(pInts[m+1]);
3010 [ # # ]: 0 : pFont->m_pMetrics->m_aMetrics[ pInts[m] ].height = static_cast<short int>(pInts[m+2]);
3011 [ # # ]: 0 : }
3012 : : }
3013 [ # # ]: 0 : else if ( pProps[n].Name == "XKernPairs" )
3014 : : {
3015 : : // fill pFont->m_pMetrics->m_aXKernPairs
3016 : : // expection name: <unicode1><unicode2> value: ((height << 16)| width)
3017 [ # # ]: 0 : Sequence< NamedValue > aKern;
3018 [ # # ]: 0 : pProps[n].Value >>= aKern;
3019 : 0 : KernPair aPair;
3020 : 0 : const NamedValue* pVals = aKern.getConstArray();
3021 : 0 : int nPairs = aKern.getLength();
3022 [ # # ]: 0 : for( int m = 0; m < nPairs; m++ )
3023 : : {
3024 [ # # ]: 0 : if( pVals[m].Name.getLength() == 2 )
3025 : : {
3026 : 0 : aPair.first = pVals[m].Name.getStr()[0];
3027 : 0 : aPair.second = pVals[m].Name.getStr()[1];
3028 : 0 : sal_Int32 nKern = getInt( pVals[m].Value );
3029 : 0 : aPair.kern_x = static_cast<short int>(nKern & 0xffff);
3030 : 0 : aPair.kern_y = static_cast<short int>((sal_uInt32(nKern) >> 16) & 0xffff);
3031 [ # # ]: 0 : pFont->m_pMetrics->m_aXKernPairs.push_back( aPair );
3032 : : }
3033 [ # # ]: 0 : }
3034 : : }
3035 : : }
3036 : : // sanity check
3037 [ # # ]: 0 : if( pFont->m_nPSName &&
[ # # # # ]
[ # # ]
3038 : : pFont->m_nFamilyName &&
3039 : 0 : ! pFont->m_pMetrics->m_aMetrics.empty() )
3040 : : {
3041 [ # # ]: 0 : m_aOverrideFonts.push_back( m_nNextFontID );
3042 [ # # ]: 0 : m_aFonts[ m_nNextFontID++ ] = pFont;
3043 : : }
3044 : : else
3045 : : {
3046 : : DBG_ASSERT( 0, "override font failed" );
3047 [ # # ][ # # ]: 0 : delete pFont;
3048 : : }
3049 [ # # ][ # # ]: 0 : }
3050 : :
3051 [ # # ]: 2 : return true;
3052 : : }
3053 : :
3054 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|