1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_vcl.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <unistd.h>
32*cdf0e10cSrcweir #include <sys/stat.h>
33*cdf0e10cSrcweir #include <dirent.h>
34*cdf0e10cSrcweir #include <stdlib.h>
35*cdf0e10cSrcweir #include <osl/thread.h>
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir #include "unotools/atom.hxx"
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir #include "fontcache.hxx"
40*cdf0e10cSrcweir #include "fontsubset.hxx"
41*cdf0e10cSrcweir #include "impfont.hxx"
42*cdf0e10cSrcweir #include "svdata.hxx"
43*cdf0e10cSrcweir #include "salinst.hxx"
44*cdf0e10cSrcweir #include "vcl/fontmanager.hxx"
45*cdf0e10cSrcweir #include "vcl/strhelper.hxx"
46*cdf0e10cSrcweir #include "vcl/ppdparser.hxx"
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir #include "tools/urlobj.hxx"
49*cdf0e10cSrcweir #include "tools/stream.hxx"
50*cdf0e10cSrcweir #include "tools/debug.hxx"
51*cdf0e10cSrcweir #include "tools/config.hxx"
52*cdf0e10cSrcweir 
53*cdf0e10cSrcweir #include "osl/file.hxx"
54*cdf0e10cSrcweir #include "osl/process.h"
55*cdf0e10cSrcweir 
56*cdf0e10cSrcweir #include "rtl/tencinfo.h"
57*cdf0e10cSrcweir #include "rtl/ustrbuf.hxx"
58*cdf0e10cSrcweir #include "rtl/strbuf.hxx"
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir #include "i18npool/mslangid.hxx"
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir #include "parseAFM.hxx"
64*cdf0e10cSrcweir #include "sft.hxx"
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
67*cdf0e10cSrcweir #include <sys/times.h>
68*cdf0e10cSrcweir #include <stdio.h>
69*cdf0e10cSrcweir #endif
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir #include "sal/alloca.h"
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir #include <set>
74*cdf0e10cSrcweir #include <hash_set>
75*cdf0e10cSrcweir #include <algorithm>
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir #include "adobeenc.tab" // get encoding table for AFM metrics
78*cdf0e10cSrcweir 
79*cdf0e10cSrcweir #ifdef CALLGRIND_COMPILE
80*cdf0e10cSrcweir #include <valgrind/callgrind.h>
81*cdf0e10cSrcweir #endif
82*cdf0e10cSrcweir 
83*cdf0e10cSrcweir #include "comphelper/processfactory.hxx"
84*cdf0e10cSrcweir #include "com/sun/star/beans/XMaterialHolder.hpp"
85*cdf0e10cSrcweir #include "com/sun/star/beans/NamedValue.hpp"
86*cdf0e10cSrcweir 
87*cdf0e10cSrcweir #define PRINTER_METRICDIR "fontmetric"
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir namespace {
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir namespace css = com::sun::star;
92*cdf0e10cSrcweir 
93*cdf0e10cSrcweir }
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir using namespace vcl;
96*cdf0e10cSrcweir using namespace utl;
97*cdf0e10cSrcweir using namespace psp;
98*cdf0e10cSrcweir using namespace osl;
99*cdf0e10cSrcweir using namespace rtl;
100*cdf0e10cSrcweir using namespace com::sun::star::uno;
101*cdf0e10cSrcweir using namespace com::sun::star::beans;
102*cdf0e10cSrcweir using namespace com::sun::star::lang;
103*cdf0e10cSrcweir 
104*cdf0e10cSrcweir /*
105*cdf0e10cSrcweir  *  static helpers
106*cdf0e10cSrcweir  */
107*cdf0e10cSrcweir 
108*cdf0e10cSrcweir inline sal_uInt16 getUInt16BE( const sal_uInt8*& pBuffer )
109*cdf0e10cSrcweir {
110*cdf0e10cSrcweir     sal_uInt16 nRet = (sal_uInt16)pBuffer[1] |
111*cdf0e10cSrcweir         (((sal_uInt16)pBuffer[0]) << 8);
112*cdf0e10cSrcweir     pBuffer+=2;
113*cdf0e10cSrcweir     return nRet;
114*cdf0e10cSrcweir }
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir inline sal_uInt32 getUInt32BE( const sal_uInt8*& pBuffer )
117*cdf0e10cSrcweir {
118*cdf0e10cSrcweir     sal_uInt32 nRet = (((sal_uInt32)pBuffer[0]) << 24) |
119*cdf0e10cSrcweir                       (((sal_uInt32)pBuffer[1]) << 16) |
120*cdf0e10cSrcweir                       (((sal_uInt32)pBuffer[2]) << 8)  |
121*cdf0e10cSrcweir                       (((sal_uInt32)pBuffer[3]) );
122*cdf0e10cSrcweir     pBuffer += 4;
123*cdf0e10cSrcweir     return nRet;
124*cdf0e10cSrcweir }
125*cdf0e10cSrcweir 
126*cdf0e10cSrcweir static italic::type parseItalic( const ByteString& rItalic )
127*cdf0e10cSrcweir {
128*cdf0e10cSrcweir     italic::type eItalic = italic::Unknown;
129*cdf0e10cSrcweir     if( rItalic.EqualsIgnoreCaseAscii( "i" ) )
130*cdf0e10cSrcweir         eItalic = italic::Italic;
131*cdf0e10cSrcweir     else if( rItalic.EqualsIgnoreCaseAscii( "o" ) )
132*cdf0e10cSrcweir         eItalic = italic::Oblique;
133*cdf0e10cSrcweir     else
134*cdf0e10cSrcweir         eItalic = italic::Upright;
135*cdf0e10cSrcweir     return eItalic;
136*cdf0e10cSrcweir }
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir // -------------------------------------------------------------------------
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir static weight::type parseWeight( const ByteString& rWeight )
141*cdf0e10cSrcweir {
142*cdf0e10cSrcweir     weight::type eWeight = weight::Unknown;
143*cdf0e10cSrcweir     if( rWeight.Search( "bold" ) != STRING_NOTFOUND )
144*cdf0e10cSrcweir     {
145*cdf0e10cSrcweir         if( rWeight.Search( "emi" ) != STRING_NOTFOUND ) // semi, demi
146*cdf0e10cSrcweir             eWeight = weight::SemiBold;
147*cdf0e10cSrcweir         else if( rWeight.Search( "ultra" ) != STRING_NOTFOUND )
148*cdf0e10cSrcweir             eWeight = weight::UltraBold;
149*cdf0e10cSrcweir         else
150*cdf0e10cSrcweir             eWeight = weight::Bold;
151*cdf0e10cSrcweir     }
152*cdf0e10cSrcweir     else if( rWeight.Search( "heavy" ) != STRING_NOTFOUND )
153*cdf0e10cSrcweir         eWeight = weight::Bold;
154*cdf0e10cSrcweir     else if( rWeight.Search( "light" ) != STRING_NOTFOUND )
155*cdf0e10cSrcweir     {
156*cdf0e10cSrcweir         if( rWeight.Search( "emi" ) != STRING_NOTFOUND ) // semi, demi
157*cdf0e10cSrcweir             eWeight = weight::SemiLight;
158*cdf0e10cSrcweir         else if( rWeight.Search( "ultra" ) != STRING_NOTFOUND )
159*cdf0e10cSrcweir             eWeight = weight::UltraLight;
160*cdf0e10cSrcweir         else
161*cdf0e10cSrcweir             eWeight = weight::Light;
162*cdf0e10cSrcweir     }
163*cdf0e10cSrcweir     else if( rWeight.Search( "black" ) != STRING_NOTFOUND )
164*cdf0e10cSrcweir         eWeight = weight::Black;
165*cdf0e10cSrcweir     else if( rWeight.Equals( "demi" ) )
166*cdf0e10cSrcweir         eWeight = weight::SemiBold;
167*cdf0e10cSrcweir     else if( rWeight.Equals( "book" ) ||
168*cdf0e10cSrcweir              rWeight.Equals( "semicondensed" ) )
169*cdf0e10cSrcweir         eWeight = weight::Light;
170*cdf0e10cSrcweir     else if( rWeight.Equals( "medium" ) || rWeight.Equals( "roman" ) )
171*cdf0e10cSrcweir         eWeight = weight::Medium;
172*cdf0e10cSrcweir     else
173*cdf0e10cSrcweir         eWeight = weight::Normal;
174*cdf0e10cSrcweir     return eWeight;
175*cdf0e10cSrcweir }
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir // -------------------------------------------------------------------------
178*cdf0e10cSrcweir 
179*cdf0e10cSrcweir static width::type parseWidth( const ByteString& rWidth )
180*cdf0e10cSrcweir {
181*cdf0e10cSrcweir     width::type eWidth = width::Unknown;
182*cdf0e10cSrcweir     if( rWidth.Equals( "bold" ) ||
183*cdf0e10cSrcweir         rWidth.Equals( "semiexpanded" ) )
184*cdf0e10cSrcweir         eWidth = width::SemiExpanded;
185*cdf0e10cSrcweir     else if( rWidth.Equals( "condensed" ) ||
186*cdf0e10cSrcweir              rWidth.Equals( "narrow" ) )
187*cdf0e10cSrcweir         eWidth = width::Condensed;
188*cdf0e10cSrcweir     else if( rWidth.Equals( "double wide" ) ||
189*cdf0e10cSrcweir              rWidth.Equals( "extraexpanded" ) ||
190*cdf0e10cSrcweir              rWidth.Equals( "ultraexpanded" ) )
191*cdf0e10cSrcweir         eWidth = width::UltraExpanded;
192*cdf0e10cSrcweir     else if( rWidth.Equals( "expanded" ) ||
193*cdf0e10cSrcweir              rWidth.Equals( "wide" ) )
194*cdf0e10cSrcweir         eWidth = width::Expanded;
195*cdf0e10cSrcweir     else if( rWidth.Equals( "extracondensed" ) )
196*cdf0e10cSrcweir         eWidth = width::ExtraCondensed;
197*cdf0e10cSrcweir     else if( rWidth.Equals( "semicondensed" ) )
198*cdf0e10cSrcweir         eWidth = width::SemiCondensed;
199*cdf0e10cSrcweir     else if( rWidth.Equals( "ultracondensed" ) )
200*cdf0e10cSrcweir         eWidth = width::UltraCondensed;
201*cdf0e10cSrcweir     else
202*cdf0e10cSrcweir         eWidth = width::Normal;
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir     return eWidth;
205*cdf0e10cSrcweir }
206*cdf0e10cSrcweir 
207*cdf0e10cSrcweir // -------------------------------------------------------------------------
208*cdf0e10cSrcweir bool PrintFontManager::XLFDEntry::operator<(const PrintFontManager::XLFDEntry& rRight) const
209*cdf0e10cSrcweir {
210*cdf0e10cSrcweir     sal_Int32 nCmp = 0;
211*cdf0e10cSrcweir     if( (nMask & MaskFamily) && (rRight.nMask & MaskFamily) )
212*cdf0e10cSrcweir     {
213*cdf0e10cSrcweir         nCmp =  rtl_str_compareIgnoreAsciiCase_WithLength( aFamily.pData->buffer,
214*cdf0e10cSrcweir                                                            aFamily.pData->length,
215*cdf0e10cSrcweir                                                            rRight.aFamily.pData->buffer,
216*cdf0e10cSrcweir                                                            rRight.aFamily.pData->length );
217*cdf0e10cSrcweir         if( nCmp != 0 )
218*cdf0e10cSrcweir             return nCmp < 0;
219*cdf0e10cSrcweir     }
220*cdf0e10cSrcweir 
221*cdf0e10cSrcweir     if( (nMask & MaskFoundry) && (rRight.nMask & MaskFoundry) )
222*cdf0e10cSrcweir     {
223*cdf0e10cSrcweir         nCmp =  rtl_str_compareIgnoreAsciiCase_WithLength( aFoundry.pData->buffer,
224*cdf0e10cSrcweir                                                            aFoundry.pData->length,
225*cdf0e10cSrcweir                                                            rRight.aFoundry.pData->buffer,
226*cdf0e10cSrcweir                                                            rRight.aFoundry.pData->length );
227*cdf0e10cSrcweir         if( nCmp != 0 )
228*cdf0e10cSrcweir             return nCmp < 0;
229*cdf0e10cSrcweir     }
230*cdf0e10cSrcweir 
231*cdf0e10cSrcweir     if( (nMask & MaskItalic) && (rRight.nMask & MaskItalic) )
232*cdf0e10cSrcweir     {
233*cdf0e10cSrcweir         if( eItalic != rRight.eItalic )
234*cdf0e10cSrcweir             return (int)eItalic < (int)rRight.eItalic;
235*cdf0e10cSrcweir     }
236*cdf0e10cSrcweir 
237*cdf0e10cSrcweir     if( (nMask & MaskWeight) && (rRight.nMask & MaskWeight) )
238*cdf0e10cSrcweir     {
239*cdf0e10cSrcweir         if( eWeight != rRight.eWeight )
240*cdf0e10cSrcweir             return (int)eWeight < (int)rRight.eWeight;
241*cdf0e10cSrcweir     }
242*cdf0e10cSrcweir 
243*cdf0e10cSrcweir     if( (nMask & MaskWidth) && (rRight.nMask & MaskWidth) )
244*cdf0e10cSrcweir     {
245*cdf0e10cSrcweir         if( eWidth != rRight.eWidth )
246*cdf0e10cSrcweir             return (int)eWidth < (int)rRight.eWidth;
247*cdf0e10cSrcweir     }
248*cdf0e10cSrcweir 
249*cdf0e10cSrcweir     if( (nMask & MaskPitch) && (rRight.nMask & MaskPitch) )
250*cdf0e10cSrcweir     {
251*cdf0e10cSrcweir         if( ePitch != rRight.ePitch )
252*cdf0e10cSrcweir             return (int)ePitch < (int)rRight.ePitch;
253*cdf0e10cSrcweir     }
254*cdf0e10cSrcweir 
255*cdf0e10cSrcweir     if( (nMask & MaskAddStyle) && (rRight.nMask & MaskAddStyle) )
256*cdf0e10cSrcweir     {
257*cdf0e10cSrcweir         nCmp =  rtl_str_compareIgnoreAsciiCase_WithLength( aAddStyle.pData->buffer,
258*cdf0e10cSrcweir                                                            aAddStyle.pData->length,
259*cdf0e10cSrcweir                                                            rRight.aAddStyle.pData->buffer,
260*cdf0e10cSrcweir                                                            rRight.aAddStyle.pData->length );
261*cdf0e10cSrcweir         if( nCmp != 0 )
262*cdf0e10cSrcweir             return nCmp < 0;
263*cdf0e10cSrcweir     }
264*cdf0e10cSrcweir 
265*cdf0e10cSrcweir     if( (nMask & MaskEncoding) && (rRight.nMask & MaskEncoding) )
266*cdf0e10cSrcweir     {
267*cdf0e10cSrcweir         if( aEncoding != rRight.aEncoding )
268*cdf0e10cSrcweir             return aEncoding < rRight.aEncoding;
269*cdf0e10cSrcweir     }
270*cdf0e10cSrcweir 
271*cdf0e10cSrcweir     return false;
272*cdf0e10cSrcweir }
273*cdf0e10cSrcweir 
274*cdf0e10cSrcweir bool PrintFontManager::XLFDEntry::operator==(const PrintFontManager::XLFDEntry& rRight) const
275*cdf0e10cSrcweir {
276*cdf0e10cSrcweir     sal_Int32 nCmp = 0;
277*cdf0e10cSrcweir     if( (nMask & MaskFamily) && (rRight.nMask & MaskFamily) )
278*cdf0e10cSrcweir     {
279*cdf0e10cSrcweir         nCmp =  rtl_str_compareIgnoreAsciiCase_WithLength( aFamily.pData->buffer,
280*cdf0e10cSrcweir                                                            aFamily.pData->length,
281*cdf0e10cSrcweir                                                            rRight.aFamily.pData->buffer,
282*cdf0e10cSrcweir                                                            rRight.aFamily.pData->length );
283*cdf0e10cSrcweir         if( nCmp != 0 )
284*cdf0e10cSrcweir             return false;
285*cdf0e10cSrcweir     }
286*cdf0e10cSrcweir 
287*cdf0e10cSrcweir     if( (nMask & MaskFoundry) && (rRight.nMask & MaskFoundry) )
288*cdf0e10cSrcweir     {
289*cdf0e10cSrcweir         nCmp =  rtl_str_compareIgnoreAsciiCase_WithLength( aFoundry.pData->buffer,
290*cdf0e10cSrcweir                                                            aFoundry.pData->length,
291*cdf0e10cSrcweir                                                            rRight.aFoundry.pData->buffer,
292*cdf0e10cSrcweir                                                            rRight.aFoundry.pData->length );
293*cdf0e10cSrcweir         if( nCmp != 0 )
294*cdf0e10cSrcweir             return false;
295*cdf0e10cSrcweir     }
296*cdf0e10cSrcweir 
297*cdf0e10cSrcweir     if( (nMask & MaskItalic) && (rRight.nMask & MaskItalic) )
298*cdf0e10cSrcweir     {
299*cdf0e10cSrcweir         if( eItalic != rRight.eItalic )
300*cdf0e10cSrcweir             return false;
301*cdf0e10cSrcweir     }
302*cdf0e10cSrcweir 
303*cdf0e10cSrcweir     if( (nMask & MaskWeight) && (rRight.nMask & MaskWeight) )
304*cdf0e10cSrcweir     {
305*cdf0e10cSrcweir         if( eWeight != rRight.eWeight )
306*cdf0e10cSrcweir             return false;
307*cdf0e10cSrcweir     }
308*cdf0e10cSrcweir 
309*cdf0e10cSrcweir     if( (nMask & MaskWidth) && (rRight.nMask & MaskWidth) )
310*cdf0e10cSrcweir     {
311*cdf0e10cSrcweir         if( eWidth != rRight.eWidth )
312*cdf0e10cSrcweir             return false;
313*cdf0e10cSrcweir     }
314*cdf0e10cSrcweir 
315*cdf0e10cSrcweir     if( (nMask & MaskPitch) && (rRight.nMask & MaskPitch) )
316*cdf0e10cSrcweir     {
317*cdf0e10cSrcweir         if( ePitch != rRight.ePitch )
318*cdf0e10cSrcweir             return false;
319*cdf0e10cSrcweir     }
320*cdf0e10cSrcweir 
321*cdf0e10cSrcweir     if( (nMask & MaskAddStyle) && (rRight.nMask & MaskAddStyle) )
322*cdf0e10cSrcweir     {
323*cdf0e10cSrcweir         nCmp =  rtl_str_compareIgnoreAsciiCase_WithLength( aAddStyle.pData->buffer,
324*cdf0e10cSrcweir                                                            aAddStyle.pData->length,
325*cdf0e10cSrcweir                                                            rRight.aAddStyle.pData->buffer,
326*cdf0e10cSrcweir                                                            rRight.aAddStyle.pData->length );
327*cdf0e10cSrcweir         if( nCmp != 0 )
328*cdf0e10cSrcweir             return false;
329*cdf0e10cSrcweir     }
330*cdf0e10cSrcweir 
331*cdf0e10cSrcweir     if( (nMask & MaskEncoding) && (rRight.nMask & MaskEncoding) )
332*cdf0e10cSrcweir     {
333*cdf0e10cSrcweir         if( aEncoding != rRight.aEncoding )
334*cdf0e10cSrcweir             return false;
335*cdf0e10cSrcweir     }
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir     return true;
338*cdf0e10cSrcweir }
339*cdf0e10cSrcweir 
340*cdf0e10cSrcweir /*
341*cdf0e10cSrcweir  *  PrintFont implementations
342*cdf0e10cSrcweir  */
343*cdf0e10cSrcweir PrintFontManager::PrintFont::PrintFont( fonttype::type eType ) :
344*cdf0e10cSrcweir         m_eType( eType ),
345*cdf0e10cSrcweir         m_nFamilyName( 0 ),
346*cdf0e10cSrcweir         m_nPSName( 0 ),
347*cdf0e10cSrcweir         m_eItalic( italic::Unknown ),
348*cdf0e10cSrcweir         m_eWidth( width::Unknown ),
349*cdf0e10cSrcweir         m_eWeight( weight::Unknown ),
350*cdf0e10cSrcweir         m_ePitch( pitch::Unknown ),
351*cdf0e10cSrcweir         m_aEncoding( RTL_TEXTENCODING_DONTKNOW ),
352*cdf0e10cSrcweir         m_bFontEncodingOnly( false ),
353*cdf0e10cSrcweir         m_pMetrics( NULL ),
354*cdf0e10cSrcweir         m_nAscend( 0 ),
355*cdf0e10cSrcweir         m_nDescend( 0 ),
356*cdf0e10cSrcweir         m_nLeading( 0 ),
357*cdf0e10cSrcweir         m_nXMin( 0 ),
358*cdf0e10cSrcweir         m_nYMin( 0 ),
359*cdf0e10cSrcweir         m_nXMax( 0 ),
360*cdf0e10cSrcweir         m_nYMax( 0 ),
361*cdf0e10cSrcweir         m_bHaveVerticalSubstitutedGlyphs( false ),
362*cdf0e10cSrcweir         m_bUserOverride( false )
363*cdf0e10cSrcweir {
364*cdf0e10cSrcweir }
365*cdf0e10cSrcweir 
366*cdf0e10cSrcweir // -------------------------------------------------------------------------
367*cdf0e10cSrcweir 
368*cdf0e10cSrcweir PrintFontManager::PrintFont::~PrintFont()
369*cdf0e10cSrcweir {
370*cdf0e10cSrcweir     if( m_pMetrics )
371*cdf0e10cSrcweir         delete m_pMetrics;
372*cdf0e10cSrcweir }
373*cdf0e10cSrcweir 
374*cdf0e10cSrcweir // -------------------------------------------------------------------------
375*cdf0e10cSrcweir 
376*cdf0e10cSrcweir PrintFontManager::Type1FontFile::~Type1FontFile()
377*cdf0e10cSrcweir {
378*cdf0e10cSrcweir }
379*cdf0e10cSrcweir 
380*cdf0e10cSrcweir // -------------------------------------------------------------------------
381*cdf0e10cSrcweir 
382*cdf0e10cSrcweir PrintFontManager::TrueTypeFontFile::TrueTypeFontFile()
383*cdf0e10cSrcweir :	PrintFont( fonttype::TrueType )
384*cdf0e10cSrcweir ,	m_nDirectory( 0 )
385*cdf0e10cSrcweir ,	m_nCollectionEntry(-1)
386*cdf0e10cSrcweir ,	m_nTypeFlags( TYPEFLAG_INVALID )
387*cdf0e10cSrcweir {}
388*cdf0e10cSrcweir 
389*cdf0e10cSrcweir // -------------------------------------------------------------------------
390*cdf0e10cSrcweir 
391*cdf0e10cSrcweir PrintFontManager::TrueTypeFontFile::~TrueTypeFontFile()
392*cdf0e10cSrcweir {
393*cdf0e10cSrcweir }
394*cdf0e10cSrcweir 
395*cdf0e10cSrcweir // -------------------------------------------------------------------------
396*cdf0e10cSrcweir 
397*cdf0e10cSrcweir PrintFontManager::BuiltinFont::~BuiltinFont()
398*cdf0e10cSrcweir {
399*cdf0e10cSrcweir }
400*cdf0e10cSrcweir 
401*cdf0e10cSrcweir // -------------------------------------------------------------------------
402*cdf0e10cSrcweir 
403*cdf0e10cSrcweir bool PrintFontManager::Type1FontFile::queryMetricPage( int /*nPage*/, MultiAtomProvider* pProvider )
404*cdf0e10cSrcweir {
405*cdf0e10cSrcweir     return readAfmMetrics( PrintFontManager::get().getAfmFile( this ), pProvider, false, false );
406*cdf0e10cSrcweir }
407*cdf0e10cSrcweir 
408*cdf0e10cSrcweir // -------------------------------------------------------------------------
409*cdf0e10cSrcweir 
410*cdf0e10cSrcweir bool PrintFontManager::BuiltinFont::queryMetricPage( int /*nPage*/, MultiAtomProvider* pProvider )
411*cdf0e10cSrcweir {
412*cdf0e10cSrcweir     return readAfmMetrics( PrintFontManager::get().getAfmFile( this ), pProvider, false, false );
413*cdf0e10cSrcweir }
414*cdf0e10cSrcweir 
415*cdf0e10cSrcweir // -------------------------------------------------------------------------
416*cdf0e10cSrcweir 
417*cdf0e10cSrcweir bool PrintFontManager::TrueTypeFontFile::queryMetricPage( int nPage, MultiAtomProvider* pProvider )
418*cdf0e10cSrcweir {
419*cdf0e10cSrcweir     bool bSuccess = false;
420*cdf0e10cSrcweir 
421*cdf0e10cSrcweir     ByteString aFile( PrintFontManager::get().getFontFile( this ) );
422*cdf0e10cSrcweir 
423*cdf0e10cSrcweir     TrueTypeFont* pTTFont = NULL;
424*cdf0e10cSrcweir 
425*cdf0e10cSrcweir     if( OpenTTFontFile( aFile.GetBuffer(), m_nCollectionEntry < 0 ? 0 : m_nCollectionEntry, &pTTFont ) == SF_OK )
426*cdf0e10cSrcweir     {
427*cdf0e10cSrcweir         if( ! m_pMetrics )
428*cdf0e10cSrcweir         {
429*cdf0e10cSrcweir             m_pMetrics = new PrintFontMetrics;
430*cdf0e10cSrcweir             memset (m_pMetrics->m_aPages, 0, sizeof(m_pMetrics->m_aPages));
431*cdf0e10cSrcweir         }
432*cdf0e10cSrcweir         m_pMetrics->m_aPages[ nPage/8 ] |= (1 << ( nPage & 7 ));
433*cdf0e10cSrcweir         int i;
434*cdf0e10cSrcweir         sal_uInt16 table[256], table_vert[256];
435*cdf0e10cSrcweir 
436*cdf0e10cSrcweir         for( i = 0; i < 256; i++ )
437*cdf0e10cSrcweir             table[ i ] = 256*nPage + i;
438*cdf0e10cSrcweir 
439*cdf0e10cSrcweir         int nCharacters = nPage < 255 ? 256 : 254;
440*cdf0e10cSrcweir         MapString( pTTFont, table, nCharacters, NULL, 0 );
441*cdf0e10cSrcweir         TTSimpleGlyphMetrics* pMetrics = GetTTSimpleCharMetrics( pTTFont, nPage*256, nCharacters, 0 );
442*cdf0e10cSrcweir         if( pMetrics )
443*cdf0e10cSrcweir         {
444*cdf0e10cSrcweir             for( i = 0; i < nCharacters; i++ )
445*cdf0e10cSrcweir             {
446*cdf0e10cSrcweir                 if( table[i] )
447*cdf0e10cSrcweir                 {
448*cdf0e10cSrcweir                     CharacterMetric& rChar = m_pMetrics->m_aMetrics[ nPage*256 + i ];
449*cdf0e10cSrcweir                     rChar.width = pMetrics[ i ].adv;
450*cdf0e10cSrcweir                     rChar.height = m_aGlobalMetricX.height;
451*cdf0e10cSrcweir                 }
452*cdf0e10cSrcweir             }
453*cdf0e10cSrcweir 
454*cdf0e10cSrcweir             free( pMetrics );
455*cdf0e10cSrcweir         }
456*cdf0e10cSrcweir 
457*cdf0e10cSrcweir         for( i = 0; i < 256; i++ )
458*cdf0e10cSrcweir             table_vert[ i ] = 256*nPage + i;
459*cdf0e10cSrcweir         MapString( pTTFont, table_vert, nCharacters, NULL, 1 );
460*cdf0e10cSrcweir         pMetrics = GetTTSimpleCharMetrics( pTTFont, nPage*256, nCharacters, 1 );
461*cdf0e10cSrcweir         if( pMetrics )
462*cdf0e10cSrcweir         {
463*cdf0e10cSrcweir             for( i = 0; i < nCharacters; i++ )
464*cdf0e10cSrcweir             {
465*cdf0e10cSrcweir                 if( table_vert[i] )
466*cdf0e10cSrcweir                 {
467*cdf0e10cSrcweir                     CharacterMetric& rChar = m_pMetrics->m_aMetrics[ nPage*256 + i + ( 1 << 16 ) ];
468*cdf0e10cSrcweir                     rChar.width = m_aGlobalMetricY.width;
469*cdf0e10cSrcweir                     rChar.height = pMetrics[ i ].adv;
470*cdf0e10cSrcweir                     if( table_vert[i] != table[i] )
471*cdf0e10cSrcweir                         m_pMetrics->m_bVerticalSubstitutions[ nPage*256 + i ] = 1;
472*cdf0e10cSrcweir                 }
473*cdf0e10cSrcweir             }
474*cdf0e10cSrcweir             free( pMetrics );
475*cdf0e10cSrcweir         }
476*cdf0e10cSrcweir 
477*cdf0e10cSrcweir         if( ! m_pMetrics->m_bKernPairsQueried )
478*cdf0e10cSrcweir         {
479*cdf0e10cSrcweir             m_pMetrics->m_bKernPairsQueried = true;
480*cdf0e10cSrcweir             // this is really a hack
481*cdf0e10cSrcweir             // in future MapString/KernGlyphs should be used
482*cdf0e10cSrcweir             // but vcl is not in a state where that could be used
483*cdf0e10cSrcweir             // so currently we get kernpairs by accessing the raw data
484*cdf0e10cSrcweir             struct _TrueTypeFont* pImplTTFont = (struct _TrueTypeFont*)pTTFont;
485*cdf0e10cSrcweir 
486*cdf0e10cSrcweir             //-----------------------------------------------------------------
487*cdf0e10cSrcweir             // Kerning:  KT_MICROSOFT
488*cdf0e10cSrcweir             //-----------------------------------------------------------------
489*cdf0e10cSrcweir             if( pImplTTFont->nkern && pImplTTFont->kerntype == KT_MICROSOFT )
490*cdf0e10cSrcweir             {
491*cdf0e10cSrcweir                 // create a glyph -> character mapping
492*cdf0e10cSrcweir                 ::std::hash_map< sal_uInt16, sal_Unicode > aGlyphMap;
493*cdf0e10cSrcweir                 ::std::hash_map< sal_uInt16, sal_Unicode >::iterator left, right;
494*cdf0e10cSrcweir                 for( i = 21; i < 0xfffd; i++ )
495*cdf0e10cSrcweir                 {
496*cdf0e10cSrcweir                     sal_uInt16 nGlyph = MapChar( pTTFont, (sal_Unicode)i, 0 ); // kerning for horz only
497*cdf0e10cSrcweir                     if( nGlyph != 0 )
498*cdf0e10cSrcweir                         aGlyphMap[ nGlyph ] = (sal_Unicode)i;
499*cdf0e10cSrcweir                 }
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir 
502*cdf0e10cSrcweir                 KernPair aPair;
503*cdf0e10cSrcweir                 for( i = 0; i < (int)pImplTTFont->nkern; i++ )
504*cdf0e10cSrcweir                 {
505*cdf0e10cSrcweir                     const sal_uInt8* pTable = pImplTTFont->kerntables[i];
506*cdf0e10cSrcweir 
507*cdf0e10cSrcweir                     /*sal_uInt16 nVersion     =*/ getUInt16BE( pTable );
508*cdf0e10cSrcweir                     /*sal_uInt16 nLength      =*/ getUInt16BE( pTable );
509*cdf0e10cSrcweir                     sal_uInt16 nCoverage    = getUInt16BE( pTable );
510*cdf0e10cSrcweir 
511*cdf0e10cSrcweir                     aPair.kern_x    = 0;
512*cdf0e10cSrcweir                     aPair.kern_y    = 0;
513*cdf0e10cSrcweir                     switch( nCoverage >> 8 )
514*cdf0e10cSrcweir                     {
515*cdf0e10cSrcweir                         case 0:
516*cdf0e10cSrcweir                         {
517*cdf0e10cSrcweir                             sal_uInt16 nPairs = getUInt16BE( pTable );
518*cdf0e10cSrcweir                             pTable += 6;
519*cdf0e10cSrcweir                             for( int n = 0; n < nPairs; n++ )
520*cdf0e10cSrcweir                             {
521*cdf0e10cSrcweir                                 sal_uInt16 nLeftGlyph   = getUInt16BE( pTable );
522*cdf0e10cSrcweir                                 sal_uInt16 nRightGlyph  = getUInt16BE( pTable );
523*cdf0e10cSrcweir                                 sal_Int16 nKern         = (sal_Int16)getUInt16BE( pTable );
524*cdf0e10cSrcweir 
525*cdf0e10cSrcweir                                 left = aGlyphMap.find( nLeftGlyph );
526*cdf0e10cSrcweir                                 right = aGlyphMap.find( nRightGlyph );
527*cdf0e10cSrcweir                                 if( left != aGlyphMap.end() && right != aGlyphMap.end() )
528*cdf0e10cSrcweir                                 {
529*cdf0e10cSrcweir                                     aPair.first     = left->second;
530*cdf0e10cSrcweir                                     aPair.second    = right->second;
531*cdf0e10cSrcweir                                     switch( nCoverage & 1 )
532*cdf0e10cSrcweir                                     {
533*cdf0e10cSrcweir                                         case 1:
534*cdf0e10cSrcweir                                             aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
535*cdf0e10cSrcweir                                             m_pMetrics->m_aXKernPairs.push_back( aPair );
536*cdf0e10cSrcweir                                             break;
537*cdf0e10cSrcweir                                         case 0:
538*cdf0e10cSrcweir                                             aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
539*cdf0e10cSrcweir                                             m_pMetrics->m_aYKernPairs.push_back( aPair );
540*cdf0e10cSrcweir                                             break;
541*cdf0e10cSrcweir                                     }
542*cdf0e10cSrcweir                                 }
543*cdf0e10cSrcweir                             }
544*cdf0e10cSrcweir                         }
545*cdf0e10cSrcweir                         break;
546*cdf0e10cSrcweir 
547*cdf0e10cSrcweir                         case 2:
548*cdf0e10cSrcweir                         {
549*cdf0e10cSrcweir                             const sal_uInt8* pSubTable = pTable;
550*cdf0e10cSrcweir                             /*sal_uInt16 nRowWidth    =*/ getUInt16BE( pTable );
551*cdf0e10cSrcweir                             sal_uInt16 nOfLeft      = getUInt16BE( pTable );
552*cdf0e10cSrcweir                             sal_uInt16 nOfRight     = getUInt16BE( pTable );
553*cdf0e10cSrcweir                             /*sal_uInt16 nOfArray     =*/ getUInt16BE( pTable );
554*cdf0e10cSrcweir                             const sal_uInt8* pTmp = pSubTable + nOfLeft;
555*cdf0e10cSrcweir                             sal_uInt16 nFirstLeft   = getUInt16BE( pTmp );
556*cdf0e10cSrcweir                             sal_uInt16 nLastLeft    = getUInt16BE( pTmp ) + nFirstLeft - 1;
557*cdf0e10cSrcweir                             pTmp = pSubTable + nOfRight;
558*cdf0e10cSrcweir                             sal_uInt16 nFirstRight  = getUInt16BE( pTmp );
559*cdf0e10cSrcweir                             sal_uInt16 nLastRight   = getUInt16BE( pTmp ) + nFirstRight -1;
560*cdf0e10cSrcweir 
561*cdf0e10cSrcweir                             // int nPairs = (int)(nLastLeft-nFirstLeft+1)*(int)(nLastRight-nFirstRight+1);
562*cdf0e10cSrcweir                             for( aPair.first = nFirstLeft; aPair.first < nLastLeft; aPair.first++ )
563*cdf0e10cSrcweir                             {
564*cdf0e10cSrcweir                                 for( aPair.second = 0; aPair.second < nLastRight; aPair.second++ )
565*cdf0e10cSrcweir                                 {
566*cdf0e10cSrcweir                                     sal_Int16 nKern = (sal_Int16)getUInt16BE( pTmp );
567*cdf0e10cSrcweir                                     switch( nCoverage & 1 )
568*cdf0e10cSrcweir                                     {
569*cdf0e10cSrcweir                                         case 1:
570*cdf0e10cSrcweir                                             aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
571*cdf0e10cSrcweir                                             m_pMetrics->m_aXKernPairs.push_back( aPair );
572*cdf0e10cSrcweir                                             break;
573*cdf0e10cSrcweir                                         case 0:
574*cdf0e10cSrcweir                                             aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
575*cdf0e10cSrcweir                                             m_pMetrics->m_aYKernPairs.push_back( aPair );
576*cdf0e10cSrcweir                                             break;
577*cdf0e10cSrcweir                                     }
578*cdf0e10cSrcweir                                 }
579*cdf0e10cSrcweir                             }
580*cdf0e10cSrcweir                         }
581*cdf0e10cSrcweir                         break;
582*cdf0e10cSrcweir                     }
583*cdf0e10cSrcweir                 }
584*cdf0e10cSrcweir             }
585*cdf0e10cSrcweir 
586*cdf0e10cSrcweir             //-----------------------------------------------------------------
587*cdf0e10cSrcweir             // Kerning:  KT_APPLE_NEW
588*cdf0e10cSrcweir             //-----------------------------------------------------------------
589*cdf0e10cSrcweir             if( pImplTTFont->nkern && pImplTTFont->kerntype == KT_APPLE_NEW )
590*cdf0e10cSrcweir             {
591*cdf0e10cSrcweir                 // create a glyph -> character mapping
592*cdf0e10cSrcweir                 ::std::hash_map< sal_uInt16, sal_Unicode > aGlyphMap;
593*cdf0e10cSrcweir                 ::std::hash_map< sal_uInt16, sal_Unicode >::iterator left, right;
594*cdf0e10cSrcweir                 for( i = 21; i < 0xfffd; i++ )
595*cdf0e10cSrcweir                 {
596*cdf0e10cSrcweir                     sal_uInt16 nGlyph = MapChar( pTTFont, (sal_Unicode)i, 0 ); // kerning for horz only
597*cdf0e10cSrcweir                     if( nGlyph != 0 )
598*cdf0e10cSrcweir                         aGlyphMap[ nGlyph ] = (sal_Unicode)i;
599*cdf0e10cSrcweir                 }
600*cdf0e10cSrcweir 
601*cdf0e10cSrcweir                 // Loop through each of the 'kern' subtables
602*cdf0e10cSrcweir                 KernPair aPair;
603*cdf0e10cSrcweir                 for( i = 0; (unsigned int)i < pImplTTFont->nkern; i++ )
604*cdf0e10cSrcweir                 {
605*cdf0e10cSrcweir                     const sal_uInt8* pTable = pImplTTFont->kerntables[i];
606*cdf0e10cSrcweir 
607*cdf0e10cSrcweir                     /*sal_uInt32 nLength      =*/ getUInt32BE( pTable );
608*cdf0e10cSrcweir                     sal_uInt16 nCoverage    = getUInt16BE( pTable );
609*cdf0e10cSrcweir                     /*sal_uInt16 nTupleIndex  =*/ getUInt16BE( pTable );
610*cdf0e10cSrcweir 
611*cdf0e10cSrcweir                     // Get kerning type
612*cdf0e10cSrcweir                     // sal_Bool bKernVertical     = nCoverage & 0x8000;
613*cdf0e10cSrcweir                     // sal_Bool bKernCrossStream  = nCoverage & 0x4000;
614*cdf0e10cSrcweir                     // sal_Bool bKernVariation    = nCoverage & 0x2000;
615*cdf0e10cSrcweir 
616*cdf0e10cSrcweir                     // Kerning sub-table format, 0 through 3
617*cdf0e10cSrcweir                     sal_uInt8 nSubTableFormat  = nCoverage & 0x00FF;
618*cdf0e10cSrcweir 
619*cdf0e10cSrcweir                     aPair.kern_x    = 0;
620*cdf0e10cSrcweir                     aPair.kern_y    = 0;
621*cdf0e10cSrcweir                     switch( nSubTableFormat )
622*cdf0e10cSrcweir                     {
623*cdf0e10cSrcweir                         case 0:
624*cdf0e10cSrcweir                         {
625*cdf0e10cSrcweir                             // Grab the # of kern pairs but skip over the:
626*cdf0e10cSrcweir                             //   searchRange
627*cdf0e10cSrcweir                             //   entrySelector
628*cdf0e10cSrcweir                             //   rangeShift
629*cdf0e10cSrcweir                             sal_uInt16 nPairs = getUInt16BE( pTable );
630*cdf0e10cSrcweir                             pTable += 6;
631*cdf0e10cSrcweir 
632*cdf0e10cSrcweir                             for( int n = 0; n < nPairs; n++ )
633*cdf0e10cSrcweir                             {
634*cdf0e10cSrcweir                                 sal_uInt16 nLeftGlyph   = getUInt16BE( pTable );
635*cdf0e10cSrcweir                                 sal_uInt16 nRightGlyph  = getUInt16BE( pTable );
636*cdf0e10cSrcweir                                 sal_Int16  nKern         = (sal_Int16)getUInt16BE( pTable );
637*cdf0e10cSrcweir 
638*cdf0e10cSrcweir                                 left = aGlyphMap.find( nLeftGlyph );
639*cdf0e10cSrcweir                                 right = aGlyphMap.find( nRightGlyph );
640*cdf0e10cSrcweir                                 if( left != aGlyphMap.end() && right != aGlyphMap.end() )
641*cdf0e10cSrcweir                                 {
642*cdf0e10cSrcweir                                     aPair.first     = left->second;
643*cdf0e10cSrcweir                                     aPair.second    = right->second;
644*cdf0e10cSrcweir 
645*cdf0e10cSrcweir                                     // Only support horizontal kerning for now
646*cdf0e10cSrcweir                                     aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
647*cdf0e10cSrcweir                                     aPair.kern_y = 0;
648*cdf0e10cSrcweir                                     m_pMetrics->m_aXKernPairs.push_back( aPair );
649*cdf0e10cSrcweir 
650*cdf0e10cSrcweir /*                                  switch( nCoverage & 1 )
651*cdf0e10cSrcweir                                     {
652*cdf0e10cSrcweir                                         case 1:
653*cdf0e10cSrcweir                                             aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
654*cdf0e10cSrcweir                                             m_pMetrics->m_aXKernPairs.push_back( aPair );
655*cdf0e10cSrcweir                                             break;
656*cdf0e10cSrcweir                                         case 0:
657*cdf0e10cSrcweir                                             aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
658*cdf0e10cSrcweir                                             m_pMetrics->m_aYKernPairs.push_back( aPair );
659*cdf0e10cSrcweir                                             break;
660*cdf0e10cSrcweir                                     }
661*cdf0e10cSrcweir */
662*cdf0e10cSrcweir                                 }
663*cdf0e10cSrcweir                             }
664*cdf0e10cSrcweir                         }
665*cdf0e10cSrcweir                         break;
666*cdf0e10cSrcweir 
667*cdf0e10cSrcweir                         case 2:
668*cdf0e10cSrcweir                         {
669*cdf0e10cSrcweir                             const sal_uInt8* pSubTable = pTable;
670*cdf0e10cSrcweir                             /*sal_uInt16 nRowWidth    =*/ getUInt16BE( pTable );
671*cdf0e10cSrcweir                             sal_uInt16 nOfLeft      = getUInt16BE( pTable );
672*cdf0e10cSrcweir                             sal_uInt16 nOfRight     = getUInt16BE( pTable );
673*cdf0e10cSrcweir                             /*sal_uInt16 nOfArray     =*/ getUInt16BE( pTable );
674*cdf0e10cSrcweir                             const sal_uInt8* pTmp = pSubTable + nOfLeft;
675*cdf0e10cSrcweir                             sal_uInt16 nFirstLeft   = getUInt16BE( pTmp );
676*cdf0e10cSrcweir                             sal_uInt16 nLastLeft    = getUInt16BE( pTmp ) + nFirstLeft - 1;
677*cdf0e10cSrcweir                             pTmp = pSubTable + nOfRight;
678*cdf0e10cSrcweir                             sal_uInt16 nFirstRight  = getUInt16BE( pTmp );
679*cdf0e10cSrcweir                             sal_uInt16 nLastRight   = getUInt16BE( pTmp ) + nFirstRight -1;
680*cdf0e10cSrcweir 
681*cdf0e10cSrcweir                             for( aPair.first = nFirstLeft; aPair.first < nLastLeft; aPair.first++ )
682*cdf0e10cSrcweir                             {
683*cdf0e10cSrcweir                                 for( aPair.second = 0; aPair.second < nLastRight; aPair.second++ )
684*cdf0e10cSrcweir                                 {
685*cdf0e10cSrcweir                                     sal_Int16 nKern = (sal_Int16)getUInt16BE( pTmp );
686*cdf0e10cSrcweir                                     switch( nCoverage & 1 )
687*cdf0e10cSrcweir                                     {
688*cdf0e10cSrcweir                                         case 1:
689*cdf0e10cSrcweir                                             aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
690*cdf0e10cSrcweir                                             m_pMetrics->m_aXKernPairs.push_back( aPair );
691*cdf0e10cSrcweir                                             break;
692*cdf0e10cSrcweir                                         case 0:
693*cdf0e10cSrcweir                                             aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
694*cdf0e10cSrcweir                                             m_pMetrics->m_aYKernPairs.push_back( aPair );
695*cdf0e10cSrcweir                                             break;
696*cdf0e10cSrcweir                                     }
697*cdf0e10cSrcweir                                 }
698*cdf0e10cSrcweir                             }
699*cdf0e10cSrcweir                         }
700*cdf0e10cSrcweir                         break;
701*cdf0e10cSrcweir 
702*cdf0e10cSrcweir                         default:
703*cdf0e10cSrcweir                             fprintf( stderr, "Found unsupported Apple-style kern subtable type %d.\n", nSubTableFormat );
704*cdf0e10cSrcweir                             break;
705*cdf0e10cSrcweir                     }
706*cdf0e10cSrcweir                 }
707*cdf0e10cSrcweir             }
708*cdf0e10cSrcweir 
709*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
710*cdf0e10cSrcweir             fprintf( stderr, "found %d/%d kern pairs for %s\n",
711*cdf0e10cSrcweir                      m_pMetrics->m_aXKernPairs.size(),
712*cdf0e10cSrcweir                      m_pMetrics->m_aYKernPairs.size(),
713*cdf0e10cSrcweir                      OUStringToOString( pProvider->getString( ATOM_FAMILYNAME, m_nFamilyName ), RTL_TEXTENCODING_MS_1252 ).getStr() );
714*cdf0e10cSrcweir #else
715*cdf0e10cSrcweir             (void) pProvider; /* avoid warnings */
716*cdf0e10cSrcweir #endif
717*cdf0e10cSrcweir         }
718*cdf0e10cSrcweir 
719*cdf0e10cSrcweir         CloseTTFont( pTTFont );
720*cdf0e10cSrcweir         bSuccess = true;
721*cdf0e10cSrcweir     }
722*cdf0e10cSrcweir     return bSuccess;
723*cdf0e10cSrcweir }
724*cdf0e10cSrcweir 
725*cdf0e10cSrcweir // -------------------------------------------------------------------------
726*cdf0e10cSrcweir 
727*cdf0e10cSrcweir /* #i73387# There seem to be fonts with a rather unwell chosen family name
728*cdf0e10cSrcweir *  consider e.g. "Helvetica Narrow" which defines its family as "Helvetica"
729*cdf0e10cSrcweir *  It can really only be distinguished by its PSName and FullName. Both of
730*cdf0e10cSrcweir *  which are not user presentable in OOo. So replace it by something sensible.
731*cdf0e10cSrcweir *
732*cdf0e10cSrcweir *  If other fonts feature this behaviour, insert them to the map.
733*cdf0e10cSrcweir */
734*cdf0e10cSrcweir static bool familyNameOverride( const OUString& i_rPSname, OUString& o_rFamilyName )
735*cdf0e10cSrcweir {
736*cdf0e10cSrcweir     static std::hash_map< OUString, OUString, OUStringHash > aPSNameToFamily( 16 );
737*cdf0e10cSrcweir     if( aPSNameToFamily.empty() ) // initialization
738*cdf0e10cSrcweir     {
739*cdf0e10cSrcweir         aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow" ) ) ] =
740*cdf0e10cSrcweir                          OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
741*cdf0e10cSrcweir         aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-Bold" ) ) ] =
742*cdf0e10cSrcweir                          OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
743*cdf0e10cSrcweir         aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-BoldOblique" ) ) ] =
744*cdf0e10cSrcweir                          OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
745*cdf0e10cSrcweir         aPSNameToFamily[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-Oblique" ) ) ] =
746*cdf0e10cSrcweir                          OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
747*cdf0e10cSrcweir     }
748*cdf0e10cSrcweir     std::hash_map<OUString,OUString,OUStringHash>::const_iterator it =
749*cdf0e10cSrcweir        aPSNameToFamily.find( i_rPSname );
750*cdf0e10cSrcweir     bool bReplaced = (it != aPSNameToFamily.end() );
751*cdf0e10cSrcweir     if( bReplaced )
752*cdf0e10cSrcweir         o_rFamilyName = it->second;
753*cdf0e10cSrcweir     return bReplaced;
754*cdf0e10cSrcweir };
755*cdf0e10cSrcweir 
756*cdf0e10cSrcweir bool PrintFontManager::PrintFont::readAfmMetrics( const OString& rFileName, MultiAtomProvider* pProvider, bool bFillEncodingvector, bool bOnlyGlobalAttributes )
757*cdf0e10cSrcweir {
758*cdf0e10cSrcweir     PrintFontManager& rManager( PrintFontManager::get() );
759*cdf0e10cSrcweir 
760*cdf0e10cSrcweir     int i;
761*cdf0e10cSrcweir     FontInfo* pInfo = NULL;
762*cdf0e10cSrcweir     parseFile( rFileName.getStr(), &pInfo, P_ALL );
763*cdf0e10cSrcweir     if( ! pInfo || ! pInfo->numOfChars )
764*cdf0e10cSrcweir     {
765*cdf0e10cSrcweir         if( pInfo )
766*cdf0e10cSrcweir             freeFontInfo( pInfo );
767*cdf0e10cSrcweir         return false;
768*cdf0e10cSrcweir     }
769*cdf0e10cSrcweir 
770*cdf0e10cSrcweir     m_aEncodingVector.clear();
771*cdf0e10cSrcweir     // fill in global info
772*cdf0e10cSrcweir 
773*cdf0e10cSrcweir     // PSName
774*cdf0e10cSrcweir     OUString aPSName( OStringToOUString( pInfo->gfi->fontName, RTL_TEXTENCODING_ISO_8859_1 ) );
775*cdf0e10cSrcweir     m_nPSName = pProvider->getAtom( ATOM_PSNAME, aPSName, sal_True );
776*cdf0e10cSrcweir 
777*cdf0e10cSrcweir     // family name (if not already set)
778*cdf0e10cSrcweir     OUString aFamily;
779*cdf0e10cSrcweir     if( ! m_nFamilyName )
780*cdf0e10cSrcweir     {
781*cdf0e10cSrcweir         aFamily = OStringToOUString( pInfo->gfi->familyName, RTL_TEXTENCODING_ISO_8859_1 );
782*cdf0e10cSrcweir         if( ! aFamily.getLength() )
783*cdf0e10cSrcweir         {
784*cdf0e10cSrcweir             aFamily = OStringToOUString( pInfo->gfi->fontName, RTL_TEXTENCODING_ISO_8859_1 );
785*cdf0e10cSrcweir             sal_Int32 nIndex  = 0;
786*cdf0e10cSrcweir             aFamily = aFamily.getToken( 0, '-', nIndex );
787*cdf0e10cSrcweir         }
788*cdf0e10cSrcweir         familyNameOverride( aPSName, aFamily );
789*cdf0e10cSrcweir         m_nFamilyName = pProvider->getAtom( ATOM_FAMILYNAME, aFamily, sal_True );
790*cdf0e10cSrcweir     }
791*cdf0e10cSrcweir     else
792*cdf0e10cSrcweir         aFamily = pProvider->getString( ATOM_FAMILYNAME, m_nFamilyName );
793*cdf0e10cSrcweir 
794*cdf0e10cSrcweir     // style name: if fullname begins with family name
795*cdf0e10cSrcweir     // interpret the rest of fullname as style
796*cdf0e10cSrcweir     if( ! m_aStyleName.getLength() && pInfo->gfi->fullName && *pInfo->gfi->fullName )
797*cdf0e10cSrcweir     {
798*cdf0e10cSrcweir         OUString aFullName( OStringToOUString( pInfo->gfi->fullName, RTL_TEXTENCODING_ISO_8859_1 ) );
799*cdf0e10cSrcweir         if( aFullName.indexOf( aFamily ) == 0 )
800*cdf0e10cSrcweir             m_aStyleName = WhitespaceToSpace( aFullName.copy( aFamily.getLength() ) );
801*cdf0e10cSrcweir     }
802*cdf0e10cSrcweir 
803*cdf0e10cSrcweir     // italic
804*cdf0e10cSrcweir     if( pInfo->gfi->italicAngle > 0 )
805*cdf0e10cSrcweir         m_eItalic = italic::Oblique;
806*cdf0e10cSrcweir     else if( pInfo->gfi->italicAngle < 0 )
807*cdf0e10cSrcweir         m_eItalic = italic::Italic;
808*cdf0e10cSrcweir     else
809*cdf0e10cSrcweir         m_eItalic = italic::Upright;
810*cdf0e10cSrcweir 
811*cdf0e10cSrcweir     // weight
812*cdf0e10cSrcweir     ByteString aLowerWeight( pInfo->gfi->weight );
813*cdf0e10cSrcweir     aLowerWeight.ToLowerAscii();
814*cdf0e10cSrcweir     m_eWeight = parseWeight( aLowerWeight );
815*cdf0e10cSrcweir 
816*cdf0e10cSrcweir     // pitch
817*cdf0e10cSrcweir     m_ePitch = pInfo->gfi->isFixedPitch ? pitch::Fixed : pitch::Variable;
818*cdf0e10cSrcweir 
819*cdf0e10cSrcweir     // encoding - only set if unknown
820*cdf0e10cSrcweir     int nAdobeEncoding = 0;
821*cdf0e10cSrcweir     if( pInfo->gfi->encodingScheme )
822*cdf0e10cSrcweir     {
823*cdf0e10cSrcweir         if( !strcmp( pInfo->gfi->encodingScheme, "AdobeStandardEncoding" ) )
824*cdf0e10cSrcweir             nAdobeEncoding = 1;
825*cdf0e10cSrcweir         else if( !strcmp( pInfo->gfi->encodingScheme, "ISO10646-1" ) )
826*cdf0e10cSrcweir         {
827*cdf0e10cSrcweir             nAdobeEncoding = 1;
828*cdf0e10cSrcweir             m_aEncoding = RTL_TEXTENCODING_UNICODE;
829*cdf0e10cSrcweir         }
830*cdf0e10cSrcweir         else if( !strcmp( pInfo->gfi->encodingScheme, "Symbol") )
831*cdf0e10cSrcweir             nAdobeEncoding = 2;
832*cdf0e10cSrcweir         else if( !strcmp( pInfo->gfi->encodingScheme, "FontSpecific") )
833*cdf0e10cSrcweir             nAdobeEncoding = 3;
834*cdf0e10cSrcweir 
835*cdf0e10cSrcweir         if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW )
836*cdf0e10cSrcweir             m_aEncoding = nAdobeEncoding == 1 ?
837*cdf0e10cSrcweir                 RTL_TEXTENCODING_ADOBE_STANDARD : RTL_TEXTENCODING_SYMBOL;
838*cdf0e10cSrcweir     }
839*cdf0e10cSrcweir     else if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW )
840*cdf0e10cSrcweir         m_aEncoding = RTL_TEXTENCODING_ADOBE_STANDARD;
841*cdf0e10cSrcweir 
842*cdf0e10cSrcweir     // try to parse the font name and decide wether it might be a
843*cdf0e10cSrcweir     // japanese font. Who invented this PITA ?
844*cdf0e10cSrcweir     OUString aPSNameLastToken( aPSName.copy( aPSName.lastIndexOf( '-' )+1 ) );
845*cdf0e10cSrcweir     if( ! aPSNameLastToken.compareToAscii( "H" )    ||
846*cdf0e10cSrcweir         ! aPSNameLastToken.compareToAscii( "V" )  )
847*cdf0e10cSrcweir     {
848*cdf0e10cSrcweir         static const char* pEncs[] =
849*cdf0e10cSrcweir             {
850*cdf0e10cSrcweir                 "EUC",
851*cdf0e10cSrcweir                 "RKSJ",
852*cdf0e10cSrcweir                 "SJ"
853*cdf0e10cSrcweir             };
854*cdf0e10cSrcweir         static const rtl_TextEncoding aEncs[] =
855*cdf0e10cSrcweir             {
856*cdf0e10cSrcweir                 RTL_TEXTENCODING_EUC_JP,
857*cdf0e10cSrcweir                 RTL_TEXTENCODING_SHIFT_JIS,
858*cdf0e10cSrcweir                 RTL_TEXTENCODING_JIS_X_0208
859*cdf0e10cSrcweir             };
860*cdf0e10cSrcweir 
861*cdf0e10cSrcweir         for( unsigned int enc = 0; enc < sizeof( aEncs )/sizeof(aEncs[0]) && m_aEncoding == RTL_TEXTENCODING_DONTKNOW; enc++ )
862*cdf0e10cSrcweir         {
863*cdf0e10cSrcweir             sal_Int32 nIndex = 0, nOffset = 1;
864*cdf0e10cSrcweir             do
865*cdf0e10cSrcweir             {
866*cdf0e10cSrcweir                 OUString aToken( aPSName.getToken( nOffset, '-', nIndex ) );
867*cdf0e10cSrcweir                 if( nIndex == -1 )
868*cdf0e10cSrcweir                     break;
869*cdf0e10cSrcweir                 nOffset = 0;
870*cdf0e10cSrcweir                 if( ! aToken.compareToAscii( pEncs[enc] ) )
871*cdf0e10cSrcweir                 {
872*cdf0e10cSrcweir                     m_aEncoding = aEncs[ enc ];
873*cdf0e10cSrcweir                     m_bFontEncodingOnly = true;
874*cdf0e10cSrcweir                 }
875*cdf0e10cSrcweir             } while( nIndex != -1 );
876*cdf0e10cSrcweir         }
877*cdf0e10cSrcweir 
878*cdf0e10cSrcweir         // default is jis
879*cdf0e10cSrcweir         if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW )
880*cdf0e10cSrcweir             m_aEncoding = RTL_TEXTENCODING_JIS_X_0208;
881*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
882*cdf0e10cSrcweir         fprintf( stderr, "Encoding %d for %s\n", m_aEncoding, pInfo->gfi->fontName );
883*cdf0e10cSrcweir #endif
884*cdf0e10cSrcweir     }
885*cdf0e10cSrcweir 
886*cdf0e10cSrcweir     // hack for GB encoded builtin fonts posing as FontSpecific
887*cdf0e10cSrcweir     if( m_eType == fonttype::Builtin && ( nAdobeEncoding == 3 || nAdobeEncoding == 0 ) )
888*cdf0e10cSrcweir     {
889*cdf0e10cSrcweir         int nLen = aFamily.getLength();
890*cdf0e10cSrcweir         if( nLen > 2 &&
891*cdf0e10cSrcweir             aFamily.getStr()[ nLen-2 ] == 'G' &&
892*cdf0e10cSrcweir             aFamily.getStr()[ nLen-1 ] == 'B' &&
893*cdf0e10cSrcweir             pInfo->numOfChars > 255 )
894*cdf0e10cSrcweir         {
895*cdf0e10cSrcweir             m_aEncoding = RTL_TEXTENCODING_GBK;
896*cdf0e10cSrcweir             m_bFontEncodingOnly = true;
897*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
898*cdf0e10cSrcweir             fprintf( stderr, "found builtin font %s with GBK encoding\n", pInfo->gfi->fontName );
899*cdf0e10cSrcweir #endif
900*cdf0e10cSrcweir         }
901*cdf0e10cSrcweir     }
902*cdf0e10cSrcweir 
903*cdf0e10cSrcweir     // #i37313# check if Fontspecific is not rather some character encoding
904*cdf0e10cSrcweir     if( nAdobeEncoding == 3 && m_aEncoding == RTL_TEXTENCODING_SYMBOL )
905*cdf0e10cSrcweir     {
906*cdf0e10cSrcweir         bool bYFound = false;
907*cdf0e10cSrcweir         bool bQFound = false;
908*cdf0e10cSrcweir         CharMetricInfo* pChar = pInfo->cmi;
909*cdf0e10cSrcweir         for( int j = 0; j < pInfo->numOfChars && ! (bYFound && bQFound); j++ )
910*cdf0e10cSrcweir         {
911*cdf0e10cSrcweir             if( pChar[j].name )
912*cdf0e10cSrcweir             {
913*cdf0e10cSrcweir                 if( pChar[j].name[0] == 'Y' && pChar[j].name[1] == 0 )
914*cdf0e10cSrcweir                     bYFound = true;
915*cdf0e10cSrcweir                 else if( pChar[j].name[0] == 'Q' && pChar[j].name[1] == 0 )
916*cdf0e10cSrcweir                     bQFound = true;
917*cdf0e10cSrcweir             }
918*cdf0e10cSrcweir         }
919*cdf0e10cSrcweir         if( bQFound && bYFound )
920*cdf0e10cSrcweir         {
921*cdf0e10cSrcweir             #if OSL_DEBUG_LEVEL > 1
922*cdf0e10cSrcweir             fprintf( stderr, "setting FontSpecific font %s (file %s) to unicode\n",
923*cdf0e10cSrcweir                      pInfo->gfi->fontName,
924*cdf0e10cSrcweir                      rFileName.getStr()
925*cdf0e10cSrcweir                      );
926*cdf0e10cSrcweir             #endif
927*cdf0e10cSrcweir             nAdobeEncoding = 4;
928*cdf0e10cSrcweir             m_aEncoding = RTL_TEXTENCODING_UNICODE;
929*cdf0e10cSrcweir             bFillEncodingvector = false; // will be filled anyway, don't do the work twice
930*cdf0e10cSrcweir         }
931*cdf0e10cSrcweir     }
932*cdf0e10cSrcweir 
933*cdf0e10cSrcweir     // ascend
934*cdf0e10cSrcweir     m_nAscend = pInfo->gfi->fontBBox.ury;
935*cdf0e10cSrcweir 
936*cdf0e10cSrcweir     // descend
937*cdf0e10cSrcweir     // descends have opposite sign of our definition
938*cdf0e10cSrcweir     m_nDescend = -pInfo->gfi->fontBBox.lly;
939*cdf0e10cSrcweir 
940*cdf0e10cSrcweir     // fallback to ascender, descender
941*cdf0e10cSrcweir     // interesting: the BBox seems to describe Ascender and Descender better
942*cdf0e10cSrcweir     // as we understand it
943*cdf0e10cSrcweir     if( m_nAscend == 0 )
944*cdf0e10cSrcweir         m_nAscend = pInfo->gfi->ascender;
945*cdf0e10cSrcweir     if( m_nDescend == 0)
946*cdf0e10cSrcweir         m_nDescend = -pInfo->gfi->descender;
947*cdf0e10cSrcweir 
948*cdf0e10cSrcweir     m_nLeading = m_nAscend + m_nDescend - 1000;
949*cdf0e10cSrcweir 
950*cdf0e10cSrcweir     if( m_pMetrics )
951*cdf0e10cSrcweir         delete m_pMetrics;
952*cdf0e10cSrcweir     m_pMetrics = new PrintFontMetrics;
953*cdf0e10cSrcweir     // mark all pages as queried (or clear if only global font info queiried)
954*cdf0e10cSrcweir     memset( m_pMetrics->m_aPages, bOnlyGlobalAttributes ? 0 : 0xff, sizeof( m_pMetrics->m_aPages ) );
955*cdf0e10cSrcweir 
956*cdf0e10cSrcweir     m_aGlobalMetricX.width = m_aGlobalMetricY.width =
957*cdf0e10cSrcweir         pInfo->gfi->charwidth ? pInfo->gfi->charwidth : pInfo->gfi->fontBBox.urx;
958*cdf0e10cSrcweir     m_aGlobalMetricX.height = m_aGlobalMetricY.height =
959*cdf0e10cSrcweir         pInfo->gfi->capHeight ? pInfo->gfi->capHeight : pInfo->gfi->fontBBox.ury;
960*cdf0e10cSrcweir 
961*cdf0e10cSrcweir     m_nXMin = pInfo->gfi->fontBBox.llx;
962*cdf0e10cSrcweir     m_nYMin = pInfo->gfi->fontBBox.lly;
963*cdf0e10cSrcweir     m_nXMax = pInfo->gfi->fontBBox.urx;
964*cdf0e10cSrcweir     m_nYMax = pInfo->gfi->fontBBox.ury;
965*cdf0e10cSrcweir 
966*cdf0e10cSrcweir     if( bFillEncodingvector || !bOnlyGlobalAttributes )
967*cdf0e10cSrcweir     {
968*cdf0e10cSrcweir         // fill in character metrics
969*cdf0e10cSrcweir 
970*cdf0e10cSrcweir         // first transform the character codes to unicode
971*cdf0e10cSrcweir         // note: this only works with single byte encodings
972*cdf0e10cSrcweir         sal_Unicode* pUnicodes = (sal_Unicode*)alloca( pInfo->numOfChars * sizeof(sal_Unicode));
973*cdf0e10cSrcweir         CharMetricInfo* pChar = pInfo->cmi;
974*cdf0e10cSrcweir 
975*cdf0e10cSrcweir         for( i = 0; i < pInfo->numOfChars; i++, pChar++ )
976*cdf0e10cSrcweir         {
977*cdf0e10cSrcweir             if( nAdobeEncoding == 4 )
978*cdf0e10cSrcweir             {
979*cdf0e10cSrcweir                 if( pChar->name )
980*cdf0e10cSrcweir                 {
981*cdf0e10cSrcweir                     pUnicodes[i] = 0;
982*cdf0e10cSrcweir                     std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name );
983*cdf0e10cSrcweir                     for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it )
984*cdf0e10cSrcweir                     {
985*cdf0e10cSrcweir                         if( *it != 0 )
986*cdf0e10cSrcweir                         {
987*cdf0e10cSrcweir                             m_aEncodingVector[ *it ] = pChar->code;
988*cdf0e10cSrcweir                             if( pChar->code == -1 )
989*cdf0e10cSrcweir                                 m_aNonEncoded[ *it ] = pChar->name;
990*cdf0e10cSrcweir                             if( ! pUnicodes[i] ) // map the first
991*cdf0e10cSrcweir                                 pUnicodes[i] = *it;
992*cdf0e10cSrcweir                         }
993*cdf0e10cSrcweir                     }
994*cdf0e10cSrcweir                 }
995*cdf0e10cSrcweir             }
996*cdf0e10cSrcweir             else if( pChar->code != -1 )
997*cdf0e10cSrcweir             {
998*cdf0e10cSrcweir                 if( nAdobeEncoding == 3 && m_aEncoding == RTL_TEXTENCODING_SYMBOL )
999*cdf0e10cSrcweir                 {
1000*cdf0e10cSrcweir                     pUnicodes[i] = pChar->code + 0xf000;
1001*cdf0e10cSrcweir                     if( bFillEncodingvector )
1002*cdf0e10cSrcweir                         m_aEncodingVector[ pUnicodes[i] ] = pChar->code;
1003*cdf0e10cSrcweir                     continue;
1004*cdf0e10cSrcweir                 }
1005*cdf0e10cSrcweir 
1006*cdf0e10cSrcweir                 if( m_aEncoding == RTL_TEXTENCODING_UNICODE )
1007*cdf0e10cSrcweir                 {
1008*cdf0e10cSrcweir                     pUnicodes[i] = (sal_Unicode)pChar->code;
1009*cdf0e10cSrcweir                     continue;
1010*cdf0e10cSrcweir                 }
1011*cdf0e10cSrcweir 
1012*cdf0e10cSrcweir                 ByteString aTranslate;
1013*cdf0e10cSrcweir                 if( pChar->code & 0xff000000 )
1014*cdf0e10cSrcweir                     aTranslate += (char)(pChar->code >> 24 );
1015*cdf0e10cSrcweir                 if( pChar->code & 0xffff0000 )
1016*cdf0e10cSrcweir                     aTranslate += (char)((pChar->code & 0x00ff0000) >> 16 );
1017*cdf0e10cSrcweir                 if( pChar->code & 0xffffff00 )
1018*cdf0e10cSrcweir                     aTranslate += (char)((pChar->code & 0x0000ff00) >> 8 );
1019*cdf0e10cSrcweir                 aTranslate += (char)(pChar->code & 0xff);
1020*cdf0e10cSrcweir                 String aUni( aTranslate, m_aEncoding );
1021*cdf0e10cSrcweir                 pUnicodes[i] = *aUni.GetBuffer();
1022*cdf0e10cSrcweir             }
1023*cdf0e10cSrcweir             else
1024*cdf0e10cSrcweir                 pUnicodes[i] = 0;
1025*cdf0e10cSrcweir         }
1026*cdf0e10cSrcweir 
1027*cdf0e10cSrcweir         // now fill in the character metrics
1028*cdf0e10cSrcweir         // parseAFM.cxx effectively only supports direction 0 (horizontal)
1029*cdf0e10cSrcweir         pChar = pInfo->cmi;
1030*cdf0e10cSrcweir         CharacterMetric aMetric;
1031*cdf0e10cSrcweir         for( i = 0; i < pInfo->numOfChars; i++, pChar++ )
1032*cdf0e10cSrcweir         {
1033*cdf0e10cSrcweir             if( pChar->code == -1 && ! pChar->name )
1034*cdf0e10cSrcweir                 continue;
1035*cdf0e10cSrcweir 
1036*cdf0e10cSrcweir             if( bFillEncodingvector && pChar->name )
1037*cdf0e10cSrcweir             {
1038*cdf0e10cSrcweir                 std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name );
1039*cdf0e10cSrcweir                 for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it )
1040*cdf0e10cSrcweir                 {
1041*cdf0e10cSrcweir                     if( *it != 0 )
1042*cdf0e10cSrcweir                     {
1043*cdf0e10cSrcweir                         m_aEncodingVector[ *it ] = pChar->code;
1044*cdf0e10cSrcweir                         if( pChar->code == -1 )
1045*cdf0e10cSrcweir                             m_aNonEncoded[ *it ] = pChar->name;
1046*cdf0e10cSrcweir                     }
1047*cdf0e10cSrcweir                 }
1048*cdf0e10cSrcweir             }
1049*cdf0e10cSrcweir 
1050*cdf0e10cSrcweir             aMetric.width   = pChar->wx ? pChar->wx : pChar->charBBox.urx;
1051*cdf0e10cSrcweir             aMetric.height  = pChar->wy ? pChar->wy : pChar->charBBox.ury - pChar->charBBox.lly;
1052*cdf0e10cSrcweir             if( aMetric.width == 0 && aMetric.height == 0 )
1053*cdf0e10cSrcweir                 // guess something for e.g. space
1054*cdf0e10cSrcweir                 aMetric.width = m_aGlobalMetricX.width/4;
1055*cdf0e10cSrcweir 
1056*cdf0e10cSrcweir             if( ( nAdobeEncoding == 0 ) ||
1057*cdf0e10cSrcweir                 ( ( nAdobeEncoding == 3 ) && ( m_aEncoding != RTL_TEXTENCODING_SYMBOL ) ) )
1058*cdf0e10cSrcweir             {
1059*cdf0e10cSrcweir                 if( pChar->code != -1 )
1060*cdf0e10cSrcweir                 {
1061*cdf0e10cSrcweir                     m_pMetrics->m_aMetrics[ pUnicodes[i] ] = aMetric;
1062*cdf0e10cSrcweir                     if( bFillEncodingvector )
1063*cdf0e10cSrcweir                         m_aEncodingVector[ pUnicodes[i] ] = pChar->code;
1064*cdf0e10cSrcweir                 }
1065*cdf0e10cSrcweir                 else if( pChar->name )
1066*cdf0e10cSrcweir                 {
1067*cdf0e10cSrcweir                     std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name );
1068*cdf0e10cSrcweir                     for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it )
1069*cdf0e10cSrcweir                     {
1070*cdf0e10cSrcweir                         if( *it != 0 )
1071*cdf0e10cSrcweir                             m_pMetrics->m_aMetrics[ *it ] = aMetric;
1072*cdf0e10cSrcweir                     }
1073*cdf0e10cSrcweir                 }
1074*cdf0e10cSrcweir             }
1075*cdf0e10cSrcweir             else if( nAdobeEncoding == 1 || nAdobeEncoding == 2 || nAdobeEncoding == 4)
1076*cdf0e10cSrcweir             {
1077*cdf0e10cSrcweir                 if( pChar->name )
1078*cdf0e10cSrcweir                 {
1079*cdf0e10cSrcweir                     std::list< sal_Unicode > aCodes = rManager.getUnicodeFromAdobeName( pChar->name );
1080*cdf0e10cSrcweir                     for( std::list< sal_Unicode >::const_iterator it = aCodes.begin(); it != aCodes.end(); ++it )
1081*cdf0e10cSrcweir                     {
1082*cdf0e10cSrcweir                         if( *it != 0 )
1083*cdf0e10cSrcweir                             m_pMetrics->m_aMetrics[ *it ] = aMetric;
1084*cdf0e10cSrcweir                     }
1085*cdf0e10cSrcweir                 }
1086*cdf0e10cSrcweir                 else if( pChar->code != -1 )
1087*cdf0e10cSrcweir                 {
1088*cdf0e10cSrcweir                     ::std::pair< ::std::hash_multimap< sal_uInt8, sal_Unicode >::const_iterator,
1089*cdf0e10cSrcweir                           ::std::hash_multimap< sal_uInt8, sal_Unicode >::const_iterator >
1090*cdf0e10cSrcweir                           aCodes = rManager.getUnicodeFromAdobeCode( pChar->code );
1091*cdf0e10cSrcweir                     while( aCodes.first != aCodes.second )
1092*cdf0e10cSrcweir                     {
1093*cdf0e10cSrcweir                         if( (*aCodes.first).second != 0 )
1094*cdf0e10cSrcweir                         {
1095*cdf0e10cSrcweir                             m_pMetrics->m_aMetrics[ (*aCodes.first).second ] = aMetric;
1096*cdf0e10cSrcweir                             if( bFillEncodingvector )
1097*cdf0e10cSrcweir                                 m_aEncodingVector[ (*aCodes.first).second ] = pChar->code;
1098*cdf0e10cSrcweir                         }
1099*cdf0e10cSrcweir                         ++aCodes.first;
1100*cdf0e10cSrcweir                     }
1101*cdf0e10cSrcweir                 }
1102*cdf0e10cSrcweir             }
1103*cdf0e10cSrcweir             else if( nAdobeEncoding == 3 )
1104*cdf0e10cSrcweir             {
1105*cdf0e10cSrcweir                 if( pChar->code != -1 )
1106*cdf0e10cSrcweir                 {
1107*cdf0e10cSrcweir                     sal_Unicode code = 0xf000 + pChar->code;
1108*cdf0e10cSrcweir                     m_pMetrics->m_aMetrics[ code ] = aMetric;
1109*cdf0e10cSrcweir                     // maybe should try to find the name in the convtabs ?
1110*cdf0e10cSrcweir                     if( bFillEncodingvector )
1111*cdf0e10cSrcweir                         m_aEncodingVector[ code ] = pChar->code;
1112*cdf0e10cSrcweir                 }
1113*cdf0e10cSrcweir             }
1114*cdf0e10cSrcweir         }
1115*cdf0e10cSrcweir 
1116*cdf0e10cSrcweir         m_pMetrics->m_aXKernPairs.clear();
1117*cdf0e10cSrcweir         m_pMetrics->m_aYKernPairs.clear();
1118*cdf0e10cSrcweir 
1119*cdf0e10cSrcweir         // now fill in the kern pairs
1120*cdf0e10cSrcweir         // parseAFM.cxx effectively only supports direction 0 (horizontal)
1121*cdf0e10cSrcweir         PairKernData* pKern = pInfo->pkd;
1122*cdf0e10cSrcweir         KernPair aPair;
1123*cdf0e10cSrcweir         for( i = 0; i < pInfo->numOfPairs; i++, pKern++ )
1124*cdf0e10cSrcweir         {
1125*cdf0e10cSrcweir             // #i37703# broken kern table
1126*cdf0e10cSrcweir             if( ! pKern->name1 || ! pKern->name2 )
1127*cdf0e10cSrcweir                 continue;
1128*cdf0e10cSrcweir 
1129*cdf0e10cSrcweir             aPair.first = 0;
1130*cdf0e10cSrcweir             aPair.second = 0;
1131*cdf0e10cSrcweir             // currently we have to find the adobe character names
1132*cdf0e10cSrcweir             // in the already parsed character metrics to find
1133*cdf0e10cSrcweir             // the corresponding UCS2 code which is a bit dangerous
1134*cdf0e10cSrcweir             // since the character names are not required
1135*cdf0e10cSrcweir             // in the metric descriptions
1136*cdf0e10cSrcweir             pChar = pInfo->cmi;
1137*cdf0e10cSrcweir             for( int j = 0;
1138*cdf0e10cSrcweir                  j < pInfo->numOfChars && ( aPair.first == 0 || aPair.second == 0 );
1139*cdf0e10cSrcweir                  j++, pChar++ )
1140*cdf0e10cSrcweir             {
1141*cdf0e10cSrcweir                 if( pChar->code != -1 )
1142*cdf0e10cSrcweir                 {
1143*cdf0e10cSrcweir                     if( ! strcmp( pKern->name1, pChar->name ? pChar->name : "" ) )
1144*cdf0e10cSrcweir                         aPair.first = pUnicodes[ j ];
1145*cdf0e10cSrcweir                     if( ! strcmp( pKern->name2, pChar->name ? pChar->name : "" ) )
1146*cdf0e10cSrcweir                         aPair.second = pUnicodes[ j ];
1147*cdf0e10cSrcweir                 }
1148*cdf0e10cSrcweir             }
1149*cdf0e10cSrcweir             if( aPair.first && aPair.second )
1150*cdf0e10cSrcweir             {
1151*cdf0e10cSrcweir                 aPair.kern_x = pKern->xamt;
1152*cdf0e10cSrcweir                 aPair.kern_y = pKern->yamt;
1153*cdf0e10cSrcweir                 m_pMetrics->m_aXKernPairs.push_back( aPair );
1154*cdf0e10cSrcweir             }
1155*cdf0e10cSrcweir         }
1156*cdf0e10cSrcweir         m_pMetrics->m_bKernPairsQueried = true;
1157*cdf0e10cSrcweir     }
1158*cdf0e10cSrcweir 
1159*cdf0e10cSrcweir     freeFontInfo( pInfo );
1160*cdf0e10cSrcweir     return true;
1161*cdf0e10cSrcweir }
1162*cdf0e10cSrcweir 
1163*cdf0e10cSrcweir // -------------------------------------------------------------------------
1164*cdf0e10cSrcweir 
1165*cdf0e10cSrcweir OString PrintFontManager::s_aEmptyOString;
1166*cdf0e10cSrcweir 
1167*cdf0e10cSrcweir /*
1168*cdf0e10cSrcweir  *  one instance only
1169*cdf0e10cSrcweir  */
1170*cdf0e10cSrcweir PrintFontManager& PrintFontManager::get()
1171*cdf0e10cSrcweir {
1172*cdf0e10cSrcweir     static PrintFontManager* theManager = NULL;
1173*cdf0e10cSrcweir     if( ! theManager )
1174*cdf0e10cSrcweir     {
1175*cdf0e10cSrcweir         theManager = new PrintFontManager();
1176*cdf0e10cSrcweir         theManager->initialize();
1177*cdf0e10cSrcweir     }
1178*cdf0e10cSrcweir     return *theManager;
1179*cdf0e10cSrcweir }
1180*cdf0e10cSrcweir 
1181*cdf0e10cSrcweir // -------------------------------------------------------------------------
1182*cdf0e10cSrcweir 
1183*cdf0e10cSrcweir /*
1184*cdf0e10cSrcweir  *  the PrintFontManager
1185*cdf0e10cSrcweir  */
1186*cdf0e10cSrcweir 
1187*cdf0e10cSrcweir PrintFontManager::PrintFontManager() :
1188*cdf0e10cSrcweir         m_nNextFontID( 1 ),
1189*cdf0e10cSrcweir         m_pAtoms( new MultiAtomProvider() ),
1190*cdf0e10cSrcweir         m_nNextDirAtom( 1 ),
1191*cdf0e10cSrcweir         m_pFontCache( NULL ),
1192*cdf0e10cSrcweir         m_bFontconfigSuccess( false )
1193*cdf0e10cSrcweir {
1194*cdf0e10cSrcweir     for( unsigned int i = 0; i < sizeof( aAdobeCodes )/sizeof( aAdobeCodes[0] ); i++ )
1195*cdf0e10cSrcweir     {
1196*cdf0e10cSrcweir         m_aUnicodeToAdobename.insert( ::std::hash_multimap< sal_Unicode, ::rtl::OString >::value_type( aAdobeCodes[i].aUnicode, aAdobeCodes[i].pAdobename ) );
1197*cdf0e10cSrcweir         m_aAdobenameToUnicode.insert( ::std::hash_multimap< ::rtl::OString, sal_Unicode, ::rtl::OStringHash >::value_type( aAdobeCodes[i].pAdobename, aAdobeCodes[i].aUnicode ) );
1198*cdf0e10cSrcweir         if( aAdobeCodes[i].aAdobeStandardCode )
1199*cdf0e10cSrcweir         {
1200*cdf0e10cSrcweir             m_aUnicodeToAdobecode.insert( ::std::hash_multimap< sal_Unicode, sal_uInt8 >::value_type( aAdobeCodes[i].aUnicode, aAdobeCodes[i].aAdobeStandardCode ) );
1201*cdf0e10cSrcweir             m_aAdobecodeToUnicode.insert( ::std::hash_multimap< sal_uInt8, sal_Unicode >::value_type( aAdobeCodes[i].aAdobeStandardCode, aAdobeCodes[i].aUnicode ) );
1202*cdf0e10cSrcweir         }
1203*cdf0e10cSrcweir #if 0
1204*cdf0e10cSrcweir         m_aUnicodeToAdobename[ aAdobeCodes[i].aUnicode ] = aAdobeCodes[i].pAdobename;
1205*cdf0e10cSrcweir         m_aAdobenameToUnicode[ aAdobeCodes[i].pAdobename ] = aAdobeCodes[i].aUnicode;
1206*cdf0e10cSrcweir         if( aAdobeCodes[i].aAdobeStandardCode )
1207*cdf0e10cSrcweir         {
1208*cdf0e10cSrcweir             m_aUnicodeToAdobecode[ aAdobeCodes[i].aUnicode ] = aAdobeCodes[i].aAdobeStandardCode;
1209*cdf0e10cSrcweir             m_aAdobecodeToUnicode[ aAdobeCodes[i].aAdobeStandardCode ] = aAdobeCodes[i].aUnicode;
1210*cdf0e10cSrcweir         }
1211*cdf0e10cSrcweir #endif
1212*cdf0e10cSrcweir     }
1213*cdf0e10cSrcweir }
1214*cdf0e10cSrcweir 
1215*cdf0e10cSrcweir // -------------------------------------------------------------------------
1216*cdf0e10cSrcweir 
1217*cdf0e10cSrcweir PrintFontManager::~PrintFontManager()
1218*cdf0e10cSrcweir {
1219*cdf0e10cSrcweir     deinitFontconfig();
1220*cdf0e10cSrcweir     for( ::std::hash_map< fontID, PrintFont* >::const_iterator it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
1221*cdf0e10cSrcweir         delete (*it).second;
1222*cdf0e10cSrcweir     delete m_pAtoms;
1223*cdf0e10cSrcweir     if( m_pFontCache )
1224*cdf0e10cSrcweir         delete m_pFontCache;
1225*cdf0e10cSrcweir }
1226*cdf0e10cSrcweir 
1227*cdf0e10cSrcweir // -------------------------------------------------------------------------
1228*cdf0e10cSrcweir 
1229*cdf0e10cSrcweir const OString& PrintFontManager::getDirectory( int nAtom ) const
1230*cdf0e10cSrcweir {
1231*cdf0e10cSrcweir     ::std::hash_map< int, OString >::const_iterator it( m_aAtomToDir.find( nAtom ) );
1232*cdf0e10cSrcweir     return it != m_aAtomToDir.end() ? it->second : s_aEmptyOString;
1233*cdf0e10cSrcweir }
1234*cdf0e10cSrcweir 
1235*cdf0e10cSrcweir // -------------------------------------------------------------------------
1236*cdf0e10cSrcweir 
1237*cdf0e10cSrcweir int PrintFontManager::getDirectoryAtom( const OString& rDirectory, bool bCreate )
1238*cdf0e10cSrcweir {
1239*cdf0e10cSrcweir     int nAtom = 0;
1240*cdf0e10cSrcweir     ::std::hash_map< OString, int, OStringHash >::const_iterator it
1241*cdf0e10cSrcweir           ( m_aDirToAtom.find( rDirectory ) );
1242*cdf0e10cSrcweir     if( it != m_aDirToAtom.end() )
1243*cdf0e10cSrcweir         nAtom = it->second;
1244*cdf0e10cSrcweir     else if( bCreate )
1245*cdf0e10cSrcweir     {
1246*cdf0e10cSrcweir         nAtom = m_nNextDirAtom++;
1247*cdf0e10cSrcweir         m_aDirToAtom[ rDirectory ] = nAtom;
1248*cdf0e10cSrcweir         m_aAtomToDir[ nAtom ] = rDirectory;
1249*cdf0e10cSrcweir     }
1250*cdf0e10cSrcweir     return nAtom;
1251*cdf0e10cSrcweir }
1252*cdf0e10cSrcweir 
1253*cdf0e10cSrcweir // -------------------------------------------------------------------------
1254*cdf0e10cSrcweir 
1255*cdf0e10cSrcweir int PrintFontManager::addFontFile( const ::rtl::OString& rFileName, int /*nFaceNum*/ )
1256*cdf0e10cSrcweir {
1257*cdf0e10cSrcweir     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
1258*cdf0e10cSrcweir     INetURLObject aPath( OStringToOUString( rFileName, aEncoding ), INET_PROT_FILE, INetURLObject::ENCODE_ALL );
1259*cdf0e10cSrcweir     OString aName( OUStringToOString( aPath.GetName(), aEncoding ) );
1260*cdf0e10cSrcweir     OString aDir( OUStringToOString( aPath.GetPath(), aEncoding ) );
1261*cdf0e10cSrcweir 
1262*cdf0e10cSrcweir     int nDirID = getDirectoryAtom( aDir, true );
1263*cdf0e10cSrcweir     fontID nFontId = findFontFileID( nDirID, aName );
1264*cdf0e10cSrcweir     if( !nFontId )
1265*cdf0e10cSrcweir     {
1266*cdf0e10cSrcweir         ::std::list< PrintFont* > aNewFonts;
1267*cdf0e10cSrcweir         if( analyzeFontFile( nDirID, aName, ::std::list<OString>(), aNewFonts ) )
1268*cdf0e10cSrcweir         {
1269*cdf0e10cSrcweir             for( ::std::list< PrintFont* >::iterator it = aNewFonts.begin();
1270*cdf0e10cSrcweir                  it != aNewFonts.end(); ++it )
1271*cdf0e10cSrcweir             {
1272*cdf0e10cSrcweir                 m_aFonts[ nFontId = m_nNextFontID++ ] = *it;
1273*cdf0e10cSrcweir                 m_aFontFileToFontID[ aName ].insert( nFontId );
1274*cdf0e10cSrcweir                 m_pFontCache->updateFontCacheEntry( *it, true );
1275*cdf0e10cSrcweir             }
1276*cdf0e10cSrcweir         }
1277*cdf0e10cSrcweir     }
1278*cdf0e10cSrcweir     return nFontId;
1279*cdf0e10cSrcweir }
1280*cdf0e10cSrcweir 
1281*cdf0e10cSrcweir // -------------------------------------------------------------------------
1282*cdf0e10cSrcweir 
1283*cdf0e10cSrcweir bool PrintFontManager::analyzeFontFile( int nDirID, const OString& rFontFile, const ::std::list<OString>& rXLFDs, ::std::list< PrintFontManager::PrintFont* >& rNewFonts ) const
1284*cdf0e10cSrcweir {
1285*cdf0e10cSrcweir     rNewFonts.clear();
1286*cdf0e10cSrcweir 
1287*cdf0e10cSrcweir     OString aDir( getDirectory( nDirID ) );
1288*cdf0e10cSrcweir 
1289*cdf0e10cSrcweir     OString aFullPath( aDir );
1290*cdf0e10cSrcweir     aFullPath += "/";
1291*cdf0e10cSrcweir     aFullPath += rFontFile;
1292*cdf0e10cSrcweir 
1293*cdf0e10cSrcweir     // #i1872# reject unreadable files
1294*cdf0e10cSrcweir     if( access( aFullPath.getStr(), R_OK ) )
1295*cdf0e10cSrcweir         return false;
1296*cdf0e10cSrcweir 
1297*cdf0e10cSrcweir     ByteString aExt( rFontFile.copy( rFontFile.lastIndexOf( '.' )+1 ) );
1298*cdf0e10cSrcweir     if( aExt.EqualsIgnoreCaseAscii( "pfb" ) || aExt.EqualsIgnoreCaseAscii( "pfa" ) )
1299*cdf0e10cSrcweir     {
1300*cdf0e10cSrcweir         // check for corresponding afm metric
1301*cdf0e10cSrcweir         // first look for an adjacent file
1302*cdf0e10cSrcweir         static const char* pSuffix[] = { ".afm", ".AFM" };
1303*cdf0e10cSrcweir 
1304*cdf0e10cSrcweir         for( unsigned int i = 0; i < sizeof(pSuffix)/sizeof(pSuffix[0]); i++ )
1305*cdf0e10cSrcweir         {
1306*cdf0e10cSrcweir             ByteString aName( rFontFile );
1307*cdf0e10cSrcweir             aName.Erase( aName.Len()-4 );
1308*cdf0e10cSrcweir             aName.Append( pSuffix[i] );
1309*cdf0e10cSrcweir 
1310*cdf0e10cSrcweir             ByteString aFilePath( aDir );
1311*cdf0e10cSrcweir             aFilePath.Append( '/' );
1312*cdf0e10cSrcweir             aFilePath.Append( aName );
1313*cdf0e10cSrcweir 
1314*cdf0e10cSrcweir             ByteString aAfmFile;
1315*cdf0e10cSrcweir             if( access( aFilePath.GetBuffer(), R_OK ) )
1316*cdf0e10cSrcweir             {
1317*cdf0e10cSrcweir                 // try in subdirectory afm instead
1318*cdf0e10cSrcweir                 aFilePath = aDir;
1319*cdf0e10cSrcweir                 aFilePath.Append( "/afm/" );
1320*cdf0e10cSrcweir                 aFilePath.Append( aName );
1321*cdf0e10cSrcweir 
1322*cdf0e10cSrcweir                 if( ! access( aFilePath.GetBuffer(), R_OK ) )
1323*cdf0e10cSrcweir                 {
1324*cdf0e10cSrcweir                     aAfmFile = "afm/";
1325*cdf0e10cSrcweir                     aAfmFile += aName;
1326*cdf0e10cSrcweir                 }
1327*cdf0e10cSrcweir             }
1328*cdf0e10cSrcweir             else
1329*cdf0e10cSrcweir                 aAfmFile = aName;
1330*cdf0e10cSrcweir 
1331*cdf0e10cSrcweir             if( aAfmFile.Len() )
1332*cdf0e10cSrcweir             {
1333*cdf0e10cSrcweir                 Type1FontFile* pFont = new Type1FontFile();
1334*cdf0e10cSrcweir                 pFont->m_nDirectory     = nDirID;
1335*cdf0e10cSrcweir 
1336*cdf0e10cSrcweir                 pFont->m_aFontFile      = rFontFile;
1337*cdf0e10cSrcweir                 pFont->m_aMetricFile    = aAfmFile;
1338*cdf0e10cSrcweir 
1339*cdf0e10cSrcweir                 if( ! pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true ) )
1340*cdf0e10cSrcweir                 {
1341*cdf0e10cSrcweir                     delete pFont;
1342*cdf0e10cSrcweir                     pFont = NULL;
1343*cdf0e10cSrcweir                 }
1344*cdf0e10cSrcweir                 if( pFont && rXLFDs.size() )
1345*cdf0e10cSrcweir                     getFontAttributesFromXLFD( pFont, rXLFDs );
1346*cdf0e10cSrcweir                 if( pFont )
1347*cdf0e10cSrcweir                     rNewFonts.push_back( pFont );
1348*cdf0e10cSrcweir                 break;
1349*cdf0e10cSrcweir             }
1350*cdf0e10cSrcweir         }
1351*cdf0e10cSrcweir     }
1352*cdf0e10cSrcweir     else if( aExt.EqualsIgnoreCaseAscii( "afm" ) )
1353*cdf0e10cSrcweir     {
1354*cdf0e10cSrcweir         ByteString aFilePath( aDir );
1355*cdf0e10cSrcweir         aFilePath.Append( '/' );
1356*cdf0e10cSrcweir         aFilePath.Append( ByteString( rFontFile ) );
1357*cdf0e10cSrcweir         BuiltinFont* pFont = new BuiltinFont();
1358*cdf0e10cSrcweir         pFont->m_nDirectory		= nDirID;
1359*cdf0e10cSrcweir         pFont->m_aMetricFile	= rFontFile;
1360*cdf0e10cSrcweir         if( pFont->readAfmMetrics( aFilePath, m_pAtoms, false, true ) )
1361*cdf0e10cSrcweir             rNewFonts.push_back( pFont );
1362*cdf0e10cSrcweir         else
1363*cdf0e10cSrcweir             delete pFont;
1364*cdf0e10cSrcweir     }
1365*cdf0e10cSrcweir     else if( aExt.EqualsIgnoreCaseAscii( "ttf" )
1366*cdf0e10cSrcweir          ||  aExt.EqualsIgnoreCaseAscii( "tte" )   // #i33947# for Gaiji support
1367*cdf0e10cSrcweir          ||  aExt.EqualsIgnoreCaseAscii( "otf" ) ) // check for TTF- and PS-OpenType too
1368*cdf0e10cSrcweir     {
1369*cdf0e10cSrcweir         TrueTypeFontFile* pFont     = new TrueTypeFontFile();
1370*cdf0e10cSrcweir         pFont->m_nDirectory         = nDirID;
1371*cdf0e10cSrcweir         pFont->m_aFontFile          = rFontFile;
1372*cdf0e10cSrcweir         pFont->m_nCollectionEntry   = -1;
1373*cdf0e10cSrcweir 
1374*cdf0e10cSrcweir         if( rXLFDs.size() )
1375*cdf0e10cSrcweir             getFontAttributesFromXLFD( pFont, rXLFDs );
1376*cdf0e10cSrcweir         // need to read the font anyway to get aliases inside the font file
1377*cdf0e10cSrcweir         if( ! analyzeTrueTypeFile( pFont ) )
1378*cdf0e10cSrcweir         {
1379*cdf0e10cSrcweir             delete pFont;
1380*cdf0e10cSrcweir             pFont = NULL;
1381*cdf0e10cSrcweir         }
1382*cdf0e10cSrcweir         else
1383*cdf0e10cSrcweir             rNewFonts.push_back( pFont );
1384*cdf0e10cSrcweir     }
1385*cdf0e10cSrcweir     else if( aExt.EqualsIgnoreCaseAscii( "ttc" ) )
1386*cdf0e10cSrcweir     {
1387*cdf0e10cSrcweir         // get number of ttc entries
1388*cdf0e10cSrcweir         int nLength = CountTTCFonts( aFullPath.getStr() );
1389*cdf0e10cSrcweir         if( nLength )
1390*cdf0e10cSrcweir         {
1391*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1392*cdf0e10cSrcweir             fprintf( stderr, "%s contains %d fonts\n", aFullPath.getStr(), nLength );
1393*cdf0e10cSrcweir #endif
1394*cdf0e10cSrcweir             for( int i = 0; i < nLength; i++ )
1395*cdf0e10cSrcweir             {
1396*cdf0e10cSrcweir                 TrueTypeFontFile* pFont     = new TrueTypeFontFile();
1397*cdf0e10cSrcweir                 pFont->m_nDirectory         = nDirID;
1398*cdf0e10cSrcweir                 pFont->m_aFontFile          = rFontFile;
1399*cdf0e10cSrcweir                 pFont->m_nCollectionEntry   = i;
1400*cdf0e10cSrcweir                 if( nLength == 1 )
1401*cdf0e10cSrcweir                     getFontAttributesFromXLFD( pFont, rXLFDs );
1402*cdf0e10cSrcweir                 if( ! analyzeTrueTypeFile( pFont ) )
1403*cdf0e10cSrcweir                 {
1404*cdf0e10cSrcweir                     delete pFont;
1405*cdf0e10cSrcweir                     pFont = NULL;
1406*cdf0e10cSrcweir                 }
1407*cdf0e10cSrcweir                 else
1408*cdf0e10cSrcweir                     rNewFonts.push_back( pFont );
1409*cdf0e10cSrcweir             }
1410*cdf0e10cSrcweir         }
1411*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1412*cdf0e10cSrcweir         else
1413*cdf0e10cSrcweir             fprintf( stderr, "CountTTCFonts( \"%s/%s\" ) failed\n", getDirectory(nDirID).getStr(), rFontFile.getStr() );
1414*cdf0e10cSrcweir #endif
1415*cdf0e10cSrcweir     }
1416*cdf0e10cSrcweir     return ! rNewFonts.empty();
1417*cdf0e10cSrcweir }
1418*cdf0e10cSrcweir 
1419*cdf0e10cSrcweir // -------------------------------------------------------------------------
1420*cdf0e10cSrcweir 
1421*cdf0e10cSrcweir fontID PrintFontManager::findFontBuiltinID( int nPSNameAtom ) const
1422*cdf0e10cSrcweir {
1423*cdf0e10cSrcweir     fontID nID = 0;
1424*cdf0e10cSrcweir     ::std::hash_map< fontID, PrintFont* >::const_iterator it;
1425*cdf0e10cSrcweir     for( it = m_aFonts.begin(); nID == 0 && it != m_aFonts.end(); ++it )
1426*cdf0e10cSrcweir     {
1427*cdf0e10cSrcweir         if( it->second->m_eType == fonttype::Builtin &&
1428*cdf0e10cSrcweir             it->second->m_nPSName == nPSNameAtom )
1429*cdf0e10cSrcweir             nID = it->first;
1430*cdf0e10cSrcweir     }
1431*cdf0e10cSrcweir     return nID;
1432*cdf0e10cSrcweir }
1433*cdf0e10cSrcweir 
1434*cdf0e10cSrcweir // -------------------------------------------------------------------------
1435*cdf0e10cSrcweir 
1436*cdf0e10cSrcweir fontID PrintFontManager::findFontFileID( int nDirID, const OString& rFontFile ) const
1437*cdf0e10cSrcweir {
1438*cdf0e10cSrcweir     fontID nID = 0;
1439*cdf0e10cSrcweir 
1440*cdf0e10cSrcweir     ::std::hash_map< OString, ::std::set< fontID >, OStringHash >::const_iterator set_it = m_aFontFileToFontID.find( rFontFile );
1441*cdf0e10cSrcweir     if( set_it != m_aFontFileToFontID.end() )
1442*cdf0e10cSrcweir     {
1443*cdf0e10cSrcweir         for( ::std::set< fontID >::const_iterator font_it = set_it->second.begin(); font_it != set_it->second.end() && ! nID; ++font_it )
1444*cdf0e10cSrcweir         {
1445*cdf0e10cSrcweir             ::std::hash_map< fontID, PrintFont* >::const_iterator it = m_aFonts.find( *font_it );
1446*cdf0e10cSrcweir             if( it != m_aFonts.end() )
1447*cdf0e10cSrcweir             {
1448*cdf0e10cSrcweir                 switch( it->second->m_eType )
1449*cdf0e10cSrcweir                 {
1450*cdf0e10cSrcweir                     case fonttype::Type1:
1451*cdf0e10cSrcweir                     {
1452*cdf0e10cSrcweir                         Type1FontFile* const pFont = static_cast< Type1FontFile* const >((*it).second);
1453*cdf0e10cSrcweir                         if( pFont->m_nDirectory == nDirID &&
1454*cdf0e10cSrcweir                             pFont->m_aFontFile == rFontFile )
1455*cdf0e10cSrcweir                             nID = it->first;
1456*cdf0e10cSrcweir                     }
1457*cdf0e10cSrcweir                     break;
1458*cdf0e10cSrcweir                     case fonttype::TrueType:
1459*cdf0e10cSrcweir                     {
1460*cdf0e10cSrcweir                         TrueTypeFontFile* const pFont = static_cast< TrueTypeFontFile* const >((*it).second);
1461*cdf0e10cSrcweir                         if( pFont->m_nDirectory == nDirID &&
1462*cdf0e10cSrcweir                             pFont->m_aFontFile == rFontFile )
1463*cdf0e10cSrcweir                             nID = it->first;
1464*cdf0e10cSrcweir                     }
1465*cdf0e10cSrcweir                     break;
1466*cdf0e10cSrcweir                     case fonttype::Builtin:
1467*cdf0e10cSrcweir                         if( static_cast<const BuiltinFont*>((*it).second)->m_nDirectory == nDirID &&
1468*cdf0e10cSrcweir                             static_cast<const BuiltinFont*>((*it).second)->m_aMetricFile == rFontFile )
1469*cdf0e10cSrcweir                             nID = it->first;
1470*cdf0e10cSrcweir                         break;
1471*cdf0e10cSrcweir                     default:
1472*cdf0e10cSrcweir                         break;
1473*cdf0e10cSrcweir                 }
1474*cdf0e10cSrcweir             }
1475*cdf0e10cSrcweir         }
1476*cdf0e10cSrcweir     }
1477*cdf0e10cSrcweir     return nID;
1478*cdf0e10cSrcweir }
1479*cdf0e10cSrcweir 
1480*cdf0e10cSrcweir // -------------------------------------------------------------------------
1481*cdf0e10cSrcweir 
1482*cdf0e10cSrcweir bool PrintFontManager::parseXLFD( const OString& rXLFD, XLFDEntry& rEntry )
1483*cdf0e10cSrcweir {
1484*cdf0e10cSrcweir     sal_Int32 nIndex = 0;
1485*cdf0e10cSrcweir     OString aFoundry		= WhitespaceToSpace( rXLFD.getToken( 1, '-', nIndex ) );
1486*cdf0e10cSrcweir     if( nIndex < 0 ) return false;
1487*cdf0e10cSrcweir     OString aFamilyXLFD		= WhitespaceToSpace( rXLFD.getToken( 0, '-', nIndex ) );
1488*cdf0e10cSrcweir     if( nIndex < 0 ) return false;
1489*cdf0e10cSrcweir     OString aWeight			= rXLFD.getToken( 0, '-', nIndex ).toAsciiLowerCase();
1490*cdf0e10cSrcweir     if( nIndex < 0 ) return false;
1491*cdf0e10cSrcweir     OString aSlant			= rXLFD.getToken( 0, '-', nIndex ).toAsciiLowerCase();
1492*cdf0e10cSrcweir     if( nIndex < 0 ) return false;
1493*cdf0e10cSrcweir     OString aWidth			= rXLFD.getToken( 0, '-', nIndex ).toAsciiLowerCase();
1494*cdf0e10cSrcweir     if( nIndex < 0 ) return false;
1495*cdf0e10cSrcweir     OString aAddStyle		= rXLFD.getToken( 0, '-', nIndex ).toAsciiLowerCase();
1496*cdf0e10cSrcweir     if( nIndex < 0 ) return false;
1497*cdf0e10cSrcweir     OString aPitch			= rXLFD.getToken( 4, '-', nIndex ).toAsciiLowerCase();
1498*cdf0e10cSrcweir     if( nIndex < 0 ) return false;
1499*cdf0e10cSrcweir     OString aRegEnc			= WhitespaceToSpace( rXLFD.getToken( 1, '-', nIndex ).toAsciiLowerCase() );
1500*cdf0e10cSrcweir     if( nIndex < 0 ) return false;
1501*cdf0e10cSrcweir     OString aEnc			= WhitespaceToSpace( rXLFD.getToken( 0, '-', nIndex ).toAsciiLowerCase() );
1502*cdf0e10cSrcweir 
1503*cdf0e10cSrcweir     // capitalize words
1504*cdf0e10cSrcweir     sal_Int32 nFamIndex = 0;
1505*cdf0e10cSrcweir     OStringBuffer aFamilyName;
1506*cdf0e10cSrcweir     while( nFamIndex >= 0 )
1507*cdf0e10cSrcweir     {
1508*cdf0e10cSrcweir         OString aToken = aFamilyXLFD.getToken( 0, ' ', nFamIndex );
1509*cdf0e10cSrcweir         sal_Char aFirst = aToken.toChar();
1510*cdf0e10cSrcweir         if( aFirst >= 'a' && aFirst <= 'z' )
1511*cdf0e10cSrcweir             aFirst = aFirst - 'a' + 'A';
1512*cdf0e10cSrcweir         OStringBuffer aNewToken( aToken.getLength() );
1513*cdf0e10cSrcweir         aNewToken.append( aToken );
1514*cdf0e10cSrcweir         aNewToken.setCharAt( 0, aFirst );
1515*cdf0e10cSrcweir         if( aFamilyName.getLength() > 0 )
1516*cdf0e10cSrcweir             aFamilyName.append( ' ' );
1517*cdf0e10cSrcweir         aFamilyName.append( aNewToken.makeStringAndClear() );
1518*cdf0e10cSrcweir     }
1519*cdf0e10cSrcweir 
1520*cdf0e10cSrcweir     rEntry.aFoundry		= aFoundry;
1521*cdf0e10cSrcweir     rEntry.aFamily		= aFamilyName.makeStringAndClear();
1522*cdf0e10cSrcweir     rEntry.aAddStyle	= aAddStyle;
1523*cdf0e10cSrcweir     // evaluate weight
1524*cdf0e10cSrcweir     rEntry.eWeight = parseWeight( aWeight );
1525*cdf0e10cSrcweir     // evaluate slant
1526*cdf0e10cSrcweir     rEntry.eItalic = parseItalic( aSlant );
1527*cdf0e10cSrcweir     // evaluate width
1528*cdf0e10cSrcweir     rEntry.eWidth = parseWidth( aWidth );
1529*cdf0e10cSrcweir 
1530*cdf0e10cSrcweir     // evaluate pitch
1531*cdf0e10cSrcweir     if( aPitch.toChar() == 'c' || aPitch.toChar() == 'm' )
1532*cdf0e10cSrcweir         rEntry.ePitch = pitch::Fixed;
1533*cdf0e10cSrcweir     else
1534*cdf0e10cSrcweir         rEntry.ePitch = pitch::Variable;
1535*cdf0e10cSrcweir 
1536*cdf0e10cSrcweir     OString aToken = aEnc.toAsciiLowerCase();
1537*cdf0e10cSrcweir     // get encoding
1538*cdf0e10cSrcweir     if( aAddStyle.indexOf( "symbol" ) != -1 )
1539*cdf0e10cSrcweir         rEntry.aEncoding = RTL_TEXTENCODING_SYMBOL;
1540*cdf0e10cSrcweir     else
1541*cdf0e10cSrcweir     {
1542*cdf0e10cSrcweir         if( aToken.equals( "symbol" ) )
1543*cdf0e10cSrcweir             rEntry.aEncoding = RTL_TEXTENCODING_SYMBOL;
1544*cdf0e10cSrcweir         else
1545*cdf0e10cSrcweir         {
1546*cdf0e10cSrcweir             OStringBuffer aCharset( aRegEnc.getLength() + aEnc.getLength() + 1 );
1547*cdf0e10cSrcweir             aCharset.append( aRegEnc );
1548*cdf0e10cSrcweir             aCharset.append( '-' );
1549*cdf0e10cSrcweir             aCharset.append( aEnc );
1550*cdf0e10cSrcweir             rEntry.aEncoding = rtl_getTextEncodingFromUnixCharset( aCharset.getStr() );
1551*cdf0e10cSrcweir         }
1552*cdf0e10cSrcweir     }
1553*cdf0e10cSrcweir 
1554*cdf0e10cSrcweir     // set correct mask flags
1555*cdf0e10cSrcweir     rEntry.nMask = 0;
1556*cdf0e10cSrcweir     if( rEntry.aFoundry != "*" )		rEntry.nMask |= XLFDEntry::MaskFoundry;
1557*cdf0e10cSrcweir     if( rEntry.aFamily != "*" )			rEntry.nMask |= XLFDEntry::MaskFamily;
1558*cdf0e10cSrcweir     if( rEntry.aAddStyle != "*" )		rEntry.nMask |= XLFDEntry::MaskAddStyle;
1559*cdf0e10cSrcweir     if( aWeight != "*" )				rEntry.nMask |= XLFDEntry::MaskWeight;
1560*cdf0e10cSrcweir     if( aSlant != "*" )					rEntry.nMask |= XLFDEntry::MaskItalic;
1561*cdf0e10cSrcweir     if( aWidth != "*" )					rEntry.nMask |= XLFDEntry::MaskWidth;
1562*cdf0e10cSrcweir     if( aPitch != "*" )					rEntry.nMask |= XLFDEntry::MaskPitch;
1563*cdf0e10cSrcweir     if( aRegEnc != "*" && aEnc != "*" )	rEntry.nMask |= XLFDEntry::MaskEncoding;
1564*cdf0e10cSrcweir 
1565*cdf0e10cSrcweir     return true;
1566*cdf0e10cSrcweir }
1567*cdf0e10cSrcweir 
1568*cdf0e10cSrcweir // -------------------------------------------------------------------------
1569*cdf0e10cSrcweir 
1570*cdf0e10cSrcweir void PrintFontManager::parseXLFD_appendAliases( const std::list< OString >& rXLFDs, std::list< XLFDEntry >& rEntries ) const
1571*cdf0e10cSrcweir {
1572*cdf0e10cSrcweir     for( std::list< OString >::const_iterator it = rXLFDs.begin(); it != rXLFDs.end(); ++it )
1573*cdf0e10cSrcweir     {
1574*cdf0e10cSrcweir         XLFDEntry aEntry;
1575*cdf0e10cSrcweir         if( ! parseXLFD(*it, aEntry) )
1576*cdf0e10cSrcweir             continue;
1577*cdf0e10cSrcweir         rEntries.push_back( aEntry );
1578*cdf0e10cSrcweir         std::map< XLFDEntry, std::list< XLFDEntry > >::const_iterator alias_it =
1579*cdf0e10cSrcweir             m_aXLFD_Aliases.find( aEntry );
1580*cdf0e10cSrcweir         if( alias_it != m_aXLFD_Aliases.end() )
1581*cdf0e10cSrcweir         {
1582*cdf0e10cSrcweir             rEntries.insert( rEntries.end(), alias_it->second.begin(), alias_it->second.end() );
1583*cdf0e10cSrcweir         }
1584*cdf0e10cSrcweir     }
1585*cdf0e10cSrcweir }
1586*cdf0e10cSrcweir 
1587*cdf0e10cSrcweir // -------------------------------------------------------------------------
1588*cdf0e10cSrcweir 
1589*cdf0e10cSrcweir void PrintFontManager::getFontAttributesFromXLFD( PrintFont* pFont, const std::list< OString >& rXLFDs ) const
1590*cdf0e10cSrcweir {
1591*cdf0e10cSrcweir     bool bFamilyName = false;
1592*cdf0e10cSrcweir 
1593*cdf0e10cSrcweir     std::list< XLFDEntry > aXLFDs;
1594*cdf0e10cSrcweir 
1595*cdf0e10cSrcweir     parseXLFD_appendAliases( rXLFDs, aXLFDs );
1596*cdf0e10cSrcweir 
1597*cdf0e10cSrcweir     for( std::list< XLFDEntry >::const_iterator it = aXLFDs.begin();
1598*cdf0e10cSrcweir          it != aXLFDs.end(); ++it )
1599*cdf0e10cSrcweir     {
1600*cdf0e10cSrcweir         // set family name or alias
1601*cdf0e10cSrcweir         int nFam =
1602*cdf0e10cSrcweir             m_pAtoms->getAtom( ATOM_FAMILYNAME,
1603*cdf0e10cSrcweir                                OStringToOUString( it->aFamily, it->aAddStyle.indexOf( "utf8" ) != -1 ? RTL_TEXTENCODING_UTF8 : RTL_TEXTENCODING_ISO_8859_1 ),
1604*cdf0e10cSrcweir                                sal_True );
1605*cdf0e10cSrcweir         if( ! bFamilyName )
1606*cdf0e10cSrcweir         {
1607*cdf0e10cSrcweir             bFamilyName = true;
1608*cdf0e10cSrcweir             pFont->m_nFamilyName = nFam;
1609*cdf0e10cSrcweir             switch( pFont->m_eType )
1610*cdf0e10cSrcweir             {
1611*cdf0e10cSrcweir                 case fonttype::Type1:
1612*cdf0e10cSrcweir                     static_cast<Type1FontFile*>(pFont)->m_aXLFD = rXLFDs.front();
1613*cdf0e10cSrcweir                     break;
1614*cdf0e10cSrcweir                 case fonttype::TrueType:
1615*cdf0e10cSrcweir                     static_cast<TrueTypeFontFile*>(pFont)->m_aXLFD = rXLFDs.front();
1616*cdf0e10cSrcweir                     break;
1617*cdf0e10cSrcweir                 default:
1618*cdf0e10cSrcweir                     break;
1619*cdf0e10cSrcweir             }
1620*cdf0e10cSrcweir         }
1621*cdf0e10cSrcweir         else
1622*cdf0e10cSrcweir         {
1623*cdf0e10cSrcweir             // make sure that aliases are unique
1624*cdf0e10cSrcweir             if( nFam != pFont->m_nFamilyName )
1625*cdf0e10cSrcweir             {
1626*cdf0e10cSrcweir                 std::list< int >::const_iterator al_it;
1627*cdf0e10cSrcweir                 for( al_it = pFont->m_aAliases.begin(); al_it != pFont->m_aAliases.end() && *al_it != nFam; ++al_it )
1628*cdf0e10cSrcweir                     ;
1629*cdf0e10cSrcweir                 if( al_it == pFont->m_aAliases.end() )
1630*cdf0e10cSrcweir                     pFont->m_aAliases.push_back( nFam );
1631*cdf0e10cSrcweir 
1632*cdf0e10cSrcweir             }
1633*cdf0e10cSrcweir             // for the rest of the attributes there can only be one value;
1634*cdf0e10cSrcweir             // we'll trust the first one
1635*cdf0e10cSrcweir             continue;
1636*cdf0e10cSrcweir         }
1637*cdf0e10cSrcweir 
1638*cdf0e10cSrcweir         // fill in weight
1639*cdf0e10cSrcweir         pFont->m_eWeight	= it->eWeight;
1640*cdf0e10cSrcweir         // fill in slant
1641*cdf0e10cSrcweir         pFont->m_eItalic	= it->eItalic;
1642*cdf0e10cSrcweir         // fill in width
1643*cdf0e10cSrcweir         pFont->m_eWidth		= it->eWidth;
1644*cdf0e10cSrcweir         // fill in pitch
1645*cdf0e10cSrcweir         pFont->m_ePitch		= it->ePitch;
1646*cdf0e10cSrcweir         // fill in encoding
1647*cdf0e10cSrcweir         pFont->m_aEncoding	= it->aEncoding;
1648*cdf0e10cSrcweir     }
1649*cdf0e10cSrcweir 
1650*cdf0e10cSrcweir     // handle iso8859-1 as ms1252 to fill the "gap" starting at 0x80
1651*cdf0e10cSrcweir     if( pFont->m_aEncoding == RTL_TEXTENCODING_ISO_8859_1 )
1652*cdf0e10cSrcweir         pFont->m_aEncoding = RTL_TEXTENCODING_MS_1252;
1653*cdf0e10cSrcweir     if( rXLFDs.begin() != rXLFDs.end() )
1654*cdf0e10cSrcweir     {
1655*cdf0e10cSrcweir         switch( pFont->m_eType )
1656*cdf0e10cSrcweir         {
1657*cdf0e10cSrcweir             case fonttype::Type1:
1658*cdf0e10cSrcweir                 static_cast<Type1FontFile*>(pFont)->m_aXLFD = rXLFDs.front();
1659*cdf0e10cSrcweir                 break;
1660*cdf0e10cSrcweir             case fonttype::TrueType:
1661*cdf0e10cSrcweir                 static_cast<TrueTypeFontFile*>(pFont)->m_aXLFD = rXLFDs.front();
1662*cdf0e10cSrcweir                 break;
1663*cdf0e10cSrcweir             default: break;
1664*cdf0e10cSrcweir         }
1665*cdf0e10cSrcweir     }
1666*cdf0e10cSrcweir }
1667*cdf0e10cSrcweir 
1668*cdf0e10cSrcweir // -------------------------------------------------------------------------
1669*cdf0e10cSrcweir 
1670*cdf0e10cSrcweir OString PrintFontManager::getXLFD( PrintFont* pFont ) const
1671*cdf0e10cSrcweir {
1672*cdf0e10cSrcweir     if( pFont->m_eType == fonttype::Type1 )
1673*cdf0e10cSrcweir     {
1674*cdf0e10cSrcweir         if( static_cast<Type1FontFile*>(pFont)->m_aXLFD.getLength() )
1675*cdf0e10cSrcweir             return static_cast<Type1FontFile*>(pFont)->m_aXLFD;
1676*cdf0e10cSrcweir     }
1677*cdf0e10cSrcweir     if( pFont->m_eType == fonttype::TrueType )
1678*cdf0e10cSrcweir     {
1679*cdf0e10cSrcweir         if( static_cast<TrueTypeFontFile*>(pFont)->m_aXLFD.getLength() )
1680*cdf0e10cSrcweir             return static_cast<TrueTypeFontFile*>(pFont)->m_aXLFD;
1681*cdf0e10cSrcweir     }
1682*cdf0e10cSrcweir 
1683*cdf0e10cSrcweir     OStringBuffer aXLFD( 128 );
1684*cdf0e10cSrcweir 
1685*cdf0e10cSrcweir     aXLFD.append( "-misc-" );
1686*cdf0e10cSrcweir     ByteString aFamily( String( m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ) ), RTL_TEXTENCODING_UTF8 );
1687*cdf0e10cSrcweir     aFamily.SearchAndReplaceAll( '-',' ' );
1688*cdf0e10cSrcweir     aFamily.SearchAndReplaceAll( '?',' ' );
1689*cdf0e10cSrcweir     aFamily.SearchAndReplaceAll( '*',' ' );
1690*cdf0e10cSrcweir     aXLFD.append( OString( aFamily ) );
1691*cdf0e10cSrcweir     aXLFD.append( '-' );
1692*cdf0e10cSrcweir     switch( pFont->m_eWeight )
1693*cdf0e10cSrcweir     {
1694*cdf0e10cSrcweir         case weight::Thin:          aXLFD.append("thin");break;
1695*cdf0e10cSrcweir         case weight::UltraLight:    aXLFD.append("ultralight");break;
1696*cdf0e10cSrcweir         case weight::Light:         aXLFD.append("light");break;
1697*cdf0e10cSrcweir         case weight::SemiLight:     aXLFD.append("semilight");break;
1698*cdf0e10cSrcweir         case weight::Normal:        aXLFD.append("normal");break;
1699*cdf0e10cSrcweir         case weight::Medium:        aXLFD.append("medium");break;
1700*cdf0e10cSrcweir         case weight::SemiBold:      aXLFD.append("semibold");break;
1701*cdf0e10cSrcweir         case weight::Bold:          aXLFD.append("bold");break;
1702*cdf0e10cSrcweir         case weight::UltraBold:     aXLFD.append("ultrabold");break;
1703*cdf0e10cSrcweir         case weight::Black:         aXLFD.append("black");break;
1704*cdf0e10cSrcweir         default: break;
1705*cdf0e10cSrcweir     }
1706*cdf0e10cSrcweir     aXLFD.append('-');
1707*cdf0e10cSrcweir     switch( pFont->m_eItalic )
1708*cdf0e10cSrcweir     {
1709*cdf0e10cSrcweir         case italic::Upright:       aXLFD.append('r');break;
1710*cdf0e10cSrcweir         case italic::Oblique:       aXLFD.append('o');break;
1711*cdf0e10cSrcweir         case italic::Italic:        aXLFD.append('i');break;
1712*cdf0e10cSrcweir         default: break;
1713*cdf0e10cSrcweir     }
1714*cdf0e10cSrcweir     aXLFD.append('-');
1715*cdf0e10cSrcweir     switch( pFont->m_eWidth )
1716*cdf0e10cSrcweir     {
1717*cdf0e10cSrcweir         case width::UltraCondensed: aXLFD.append("ultracondensed");break;
1718*cdf0e10cSrcweir         case width::ExtraCondensed: aXLFD.append("extracondensed");break;
1719*cdf0e10cSrcweir         case width::Condensed:      aXLFD.append("condensed");break;
1720*cdf0e10cSrcweir         case width::SemiCondensed:  aXLFD.append("semicondensed");break;
1721*cdf0e10cSrcweir         case width::Normal:         aXLFD.append("normal");break;
1722*cdf0e10cSrcweir         case width::SemiExpanded:   aXLFD.append("semiexpanded");break;
1723*cdf0e10cSrcweir         case width::Expanded:       aXLFD.append("expanded");break;
1724*cdf0e10cSrcweir         case width::ExtraExpanded:  aXLFD.append("extraexpanded");break;
1725*cdf0e10cSrcweir         case width::UltraExpanded:  aXLFD.append("ultraexpanded");break;
1726*cdf0e10cSrcweir         default: break;
1727*cdf0e10cSrcweir     }
1728*cdf0e10cSrcweir     aXLFD.append("-utf8-0-0-0-0-");
1729*cdf0e10cSrcweir     aXLFD.append( pFont->m_ePitch == pitch::Fixed ? "m" : "p" );
1730*cdf0e10cSrcweir     aXLFD.append("-0-");
1731*cdf0e10cSrcweir     const char* pEnc = rtl_getBestUnixCharsetFromTextEncoding( pFont->m_aEncoding );
1732*cdf0e10cSrcweir     if( ! pEnc )
1733*cdf0e10cSrcweir     {
1734*cdf0e10cSrcweir         if( pFont->m_aEncoding == RTL_TEXTENCODING_ADOBE_STANDARD )
1735*cdf0e10cSrcweir             pEnc = "adobe-standard";
1736*cdf0e10cSrcweir         else
1737*cdf0e10cSrcweir             pEnc = "iso8859-1";
1738*cdf0e10cSrcweir     }
1739*cdf0e10cSrcweir     aXLFD .append( pEnc );
1740*cdf0e10cSrcweir 
1741*cdf0e10cSrcweir     return aXLFD.makeStringAndClear();
1742*cdf0e10cSrcweir }
1743*cdf0e10cSrcweir 
1744*cdf0e10cSrcweir // -------------------------------------------------------------------------
1745*cdf0e10cSrcweir 
1746*cdf0e10cSrcweir OUString PrintFontManager::convertTrueTypeName( void* pRecord ) const
1747*cdf0e10cSrcweir {
1748*cdf0e10cSrcweir     NameRecord* pNameRecord = (NameRecord*)pRecord;
1749*cdf0e10cSrcweir     OUString aValue;
1750*cdf0e10cSrcweir     if(
1751*cdf0e10cSrcweir        ( pNameRecord->platformID == 3 && ( pNameRecord->encodingID == 0 || pNameRecord->encodingID == 1 ) )  // MS, Unicode
1752*cdf0e10cSrcweir        ||
1753*cdf0e10cSrcweir        ( pNameRecord->platformID == 0 ) // Apple, Unicode
1754*cdf0e10cSrcweir        )
1755*cdf0e10cSrcweir     {
1756*cdf0e10cSrcweir         OUStringBuffer aName( pNameRecord->slen/2 );
1757*cdf0e10cSrcweir         const sal_uInt8* pNameBuffer = pNameRecord->sptr;
1758*cdf0e10cSrcweir         for(int n = 0; n < pNameRecord->slen/2; n++ )
1759*cdf0e10cSrcweir             aName.append( (sal_Unicode)getUInt16BE( pNameBuffer ) );
1760*cdf0e10cSrcweir         aValue = aName.makeStringAndClear();
1761*cdf0e10cSrcweir     }
1762*cdf0e10cSrcweir     else if( pNameRecord->platformID == 3 )
1763*cdf0e10cSrcweir     {
1764*cdf0e10cSrcweir         if( pNameRecord->encodingID >= 2 && pNameRecord->encodingID <= 6 )
1765*cdf0e10cSrcweir         {
1766*cdf0e10cSrcweir             /*
1767*cdf0e10cSrcweir              *  and now for a special kind of madness:
1768*cdf0e10cSrcweir              *  some fonts encode their byte value string as BE uint16
1769*cdf0e10cSrcweir              *  (leading to stray zero bytes in the string)
1770*cdf0e10cSrcweir              *  while others code two bytes as a uint16 and swap to BE
1771*cdf0e10cSrcweir              */
1772*cdf0e10cSrcweir             OStringBuffer aName;
1773*cdf0e10cSrcweir             const sal_uInt8* pNameBuffer = pNameRecord->sptr;
1774*cdf0e10cSrcweir             for(int n = 0; n < pNameRecord->slen/2; n++ )
1775*cdf0e10cSrcweir             {
1776*cdf0e10cSrcweir                 sal_Unicode aCode = (sal_Unicode)getUInt16BE( pNameBuffer );
1777*cdf0e10cSrcweir                 sal_Char aChar = aCode >> 8;
1778*cdf0e10cSrcweir                 if( aChar )
1779*cdf0e10cSrcweir                     aName.append( aChar );
1780*cdf0e10cSrcweir                 aChar = aCode & 0x00ff;
1781*cdf0e10cSrcweir                 if( aChar )
1782*cdf0e10cSrcweir                     aName.append( aChar );
1783*cdf0e10cSrcweir             }
1784*cdf0e10cSrcweir             switch( pNameRecord->encodingID )
1785*cdf0e10cSrcweir             {
1786*cdf0e10cSrcweir                 case 2:
1787*cdf0e10cSrcweir                     aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_932 );
1788*cdf0e10cSrcweir                     break;
1789*cdf0e10cSrcweir                 case 3:
1790*cdf0e10cSrcweir                     aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_936 );
1791*cdf0e10cSrcweir                     break;
1792*cdf0e10cSrcweir                 case 4:
1793*cdf0e10cSrcweir                     aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_950 );
1794*cdf0e10cSrcweir                     break;
1795*cdf0e10cSrcweir                 case 5:
1796*cdf0e10cSrcweir                     aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_949 );
1797*cdf0e10cSrcweir                     break;
1798*cdf0e10cSrcweir                 case 6:
1799*cdf0e10cSrcweir                     aValue = OStringToOUString( aName.makeStringAndClear(), RTL_TEXTENCODING_MS_1361 );
1800*cdf0e10cSrcweir                     break;
1801*cdf0e10cSrcweir             }
1802*cdf0e10cSrcweir         }
1803*cdf0e10cSrcweir     }
1804*cdf0e10cSrcweir     return aValue;
1805*cdf0e10cSrcweir }
1806*cdf0e10cSrcweir 
1807*cdf0e10cSrcweir // -------------------------------------------------------------------------
1808*cdf0e10cSrcweir 
1809*cdf0e10cSrcweir void PrintFontManager::analyzeTrueTypeFamilyName( void* pTTFont, ::std::list< OUString >& rNames ) const
1810*cdf0e10cSrcweir {
1811*cdf0e10cSrcweir     OUString aFamily;
1812*cdf0e10cSrcweir 
1813*cdf0e10cSrcweir     rNames.clear();
1814*cdf0e10cSrcweir     ::std::set< OUString > aSet;
1815*cdf0e10cSrcweir 
1816*cdf0e10cSrcweir     NameRecord* pNameRecords = NULL;
1817*cdf0e10cSrcweir     int nNameRecords = GetTTNameRecords( (TrueTypeFont*)pTTFont, &pNameRecords );
1818*cdf0e10cSrcweir     if( nNameRecords && pNameRecords )
1819*cdf0e10cSrcweir     {
1820*cdf0e10cSrcweir         LanguageType aLang = MsLangId::getSystemLanguage();
1821*cdf0e10cSrcweir         int nLastMatch = -1;
1822*cdf0e10cSrcweir         for( int i = 0; i < nNameRecords; i++ )
1823*cdf0e10cSrcweir         {
1824*cdf0e10cSrcweir             if( pNameRecords[i].nameID != 1 || pNameRecords[i].sptr == NULL )
1825*cdf0e10cSrcweir                 continue;
1826*cdf0e10cSrcweir             int nMatch = -1;
1827*cdf0e10cSrcweir             if( pNameRecords[i].platformID == 0 ) // Unicode
1828*cdf0e10cSrcweir                 nMatch = 4000;
1829*cdf0e10cSrcweir             else if( pNameRecords[i].platformID == 3 )
1830*cdf0e10cSrcweir             {
1831*cdf0e10cSrcweir                 // this bases on the LanguageType actually being a Win LCID
1832*cdf0e10cSrcweir                 if( pNameRecords[i].languageID == aLang )
1833*cdf0e10cSrcweir                     nMatch = 8000;
1834*cdf0e10cSrcweir                 else if( pNameRecords[i].languageID == LANGUAGE_ENGLISH_US )
1835*cdf0e10cSrcweir                     nMatch = 2000;
1836*cdf0e10cSrcweir                 else if( pNameRecords[i].languageID == LANGUAGE_ENGLISH ||
1837*cdf0e10cSrcweir                          pNameRecords[i].languageID == LANGUAGE_ENGLISH_UK )
1838*cdf0e10cSrcweir                     nMatch = 1500;
1839*cdf0e10cSrcweir                 else
1840*cdf0e10cSrcweir                     nMatch = 1000;
1841*cdf0e10cSrcweir             }
1842*cdf0e10cSrcweir             OUString aName = convertTrueTypeName( pNameRecords + i );
1843*cdf0e10cSrcweir             aSet.insert( aName );
1844*cdf0e10cSrcweir             if( nMatch > nLastMatch )
1845*cdf0e10cSrcweir             {
1846*cdf0e10cSrcweir                 nLastMatch = nMatch;
1847*cdf0e10cSrcweir                 aFamily = aName;
1848*cdf0e10cSrcweir             }
1849*cdf0e10cSrcweir         }
1850*cdf0e10cSrcweir         DisposeNameRecords( pNameRecords, nNameRecords );
1851*cdf0e10cSrcweir     }
1852*cdf0e10cSrcweir     if( aFamily.getLength() )
1853*cdf0e10cSrcweir     {
1854*cdf0e10cSrcweir         rNames.push_front( aFamily );
1855*cdf0e10cSrcweir         for( ::std::set< OUString >::const_iterator it = aSet.begin(); it != aSet.end(); ++it )
1856*cdf0e10cSrcweir             if( *it != aFamily )
1857*cdf0e10cSrcweir                 rNames.push_back( *it );
1858*cdf0e10cSrcweir     }
1859*cdf0e10cSrcweir     return;
1860*cdf0e10cSrcweir }
1861*cdf0e10cSrcweir 
1862*cdf0e10cSrcweir // -------------------------------------------------------------------------
1863*cdf0e10cSrcweir 
1864*cdf0e10cSrcweir bool PrintFontManager::analyzeTrueTypeFile( PrintFont* pFont ) const
1865*cdf0e10cSrcweir {
1866*cdf0e10cSrcweir     bool bSuccess = false;
1867*cdf0e10cSrcweir     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
1868*cdf0e10cSrcweir     ByteString aFile = getFontFile( pFont );
1869*cdf0e10cSrcweir     TrueTypeFont* pTTFont = NULL;
1870*cdf0e10cSrcweir 
1871*cdf0e10cSrcweir     TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont);
1872*cdf0e10cSrcweir     if( OpenTTFontFile( aFile.GetBuffer(), pTTFontFile->m_nCollectionEntry < 0 ? 0 : pTTFontFile->m_nCollectionEntry, &pTTFont ) == SF_OK )
1873*cdf0e10cSrcweir     {
1874*cdf0e10cSrcweir         TTGlobalFontInfo aInfo;
1875*cdf0e10cSrcweir         GetTTGlobalFontInfo( pTTFont, & aInfo );
1876*cdf0e10cSrcweir 
1877*cdf0e10cSrcweir         ::std::list< OUString > aNames;
1878*cdf0e10cSrcweir         analyzeTrueTypeFamilyName( pTTFont, aNames );
1879*cdf0e10cSrcweir 
1880*cdf0e10cSrcweir         // set family name from XLFD if possible
1881*cdf0e10cSrcweir         if( ! pFont->m_nFamilyName )
1882*cdf0e10cSrcweir         {
1883*cdf0e10cSrcweir             if( aNames.begin() != aNames.end() )
1884*cdf0e10cSrcweir             {
1885*cdf0e10cSrcweir                 pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, aNames.front(), sal_True );
1886*cdf0e10cSrcweir                 aNames.pop_front();
1887*cdf0e10cSrcweir             }
1888*cdf0e10cSrcweir             else
1889*cdf0e10cSrcweir             {
1890*cdf0e10cSrcweir                  sal_Int32   dotIndex;
1891*cdf0e10cSrcweir 
1892*cdf0e10cSrcweir                  // poor font does not have a family name
1893*cdf0e10cSrcweir                  // name it to file name minus the extension
1894*cdf0e10cSrcweir                  dotIndex = pTTFontFile->m_aFontFile.lastIndexOf( '.' );
1895*cdf0e10cSrcweir                  if ( dotIndex == -1 )
1896*cdf0e10cSrcweir                      dotIndex = pTTFontFile->m_aFontFile.getLength();
1897*cdf0e10cSrcweir 
1898*cdf0e10cSrcweir                  pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, OStringToOUString( pTTFontFile->m_aFontFile.copy( 0, dotIndex ), aEncoding ), sal_True );
1899*cdf0e10cSrcweir             }
1900*cdf0e10cSrcweir         }
1901*cdf0e10cSrcweir         for( ::std::list< OUString >::iterator it = aNames.begin(); it != aNames.end(); ++it )
1902*cdf0e10cSrcweir         {
1903*cdf0e10cSrcweir             if( it->getLength() )
1904*cdf0e10cSrcweir             {
1905*cdf0e10cSrcweir                 int nAlias = m_pAtoms->getAtom( ATOM_FAMILYNAME, *it, sal_True );
1906*cdf0e10cSrcweir                 if( nAlias != pFont->m_nFamilyName )
1907*cdf0e10cSrcweir                 {
1908*cdf0e10cSrcweir                     std::list< int >::const_iterator al_it;
1909*cdf0e10cSrcweir                     for( al_it = pFont->m_aAliases.begin(); al_it != pFont->m_aAliases.end() && *al_it != nAlias; ++al_it )
1910*cdf0e10cSrcweir                         ;
1911*cdf0e10cSrcweir                     if( al_it == pFont->m_aAliases.end() )
1912*cdf0e10cSrcweir                         pFont->m_aAliases.push_back( nAlias );
1913*cdf0e10cSrcweir                 }
1914*cdf0e10cSrcweir             }
1915*cdf0e10cSrcweir         }
1916*cdf0e10cSrcweir 
1917*cdf0e10cSrcweir         if( aInfo.usubfamily )
1918*cdf0e10cSrcweir             pFont->m_aStyleName = OUString( aInfo.usubfamily );
1919*cdf0e10cSrcweir 
1920*cdf0e10cSrcweir         pFont->m_nPSName = m_pAtoms->getAtom( ATOM_PSNAME, String( ByteString( aInfo.psname ), aEncoding ), sal_True );
1921*cdf0e10cSrcweir         switch( aInfo.weight )
1922*cdf0e10cSrcweir         {
1923*cdf0e10cSrcweir             case FW_THIN:           pFont->m_eWeight = weight::Thin; break;
1924*cdf0e10cSrcweir             case FW_EXTRALIGHT: pFont->m_eWeight = weight::UltraLight; break;
1925*cdf0e10cSrcweir             case FW_LIGHT:          pFont->m_eWeight = weight::Light; break;
1926*cdf0e10cSrcweir             case FW_MEDIUM:     pFont->m_eWeight = weight::Medium; break;
1927*cdf0e10cSrcweir             case FW_SEMIBOLD:       pFont->m_eWeight = weight::SemiBold; break;
1928*cdf0e10cSrcweir             case FW_BOLD:           pFont->m_eWeight = weight::Bold; break;
1929*cdf0e10cSrcweir             case FW_EXTRABOLD:      pFont->m_eWeight = weight::UltraBold; break;
1930*cdf0e10cSrcweir             case FW_BLACK:          pFont->m_eWeight = weight::Black; break;
1931*cdf0e10cSrcweir 
1932*cdf0e10cSrcweir             case FW_NORMAL:
1933*cdf0e10cSrcweir             default:        pFont->m_eWeight = weight::Normal; break;
1934*cdf0e10cSrcweir         }
1935*cdf0e10cSrcweir 
1936*cdf0e10cSrcweir         switch( aInfo.width )
1937*cdf0e10cSrcweir         {
1938*cdf0e10cSrcweir             case FWIDTH_ULTRA_CONDENSED:    pFont->m_eWidth = width::UltraCondensed; break;
1939*cdf0e10cSrcweir             case FWIDTH_EXTRA_CONDENSED:    pFont->m_eWidth = width::ExtraCondensed; break;
1940*cdf0e10cSrcweir             case FWIDTH_CONDENSED:          pFont->m_eWidth = width::Condensed; break;
1941*cdf0e10cSrcweir             case FWIDTH_SEMI_CONDENSED: pFont->m_eWidth = width::SemiCondensed; break;
1942*cdf0e10cSrcweir             case FWIDTH_SEMI_EXPANDED:      pFont->m_eWidth = width::SemiExpanded; break;
1943*cdf0e10cSrcweir             case FWIDTH_EXPANDED:           pFont->m_eWidth = width::Expanded; break;
1944*cdf0e10cSrcweir             case FWIDTH_EXTRA_EXPANDED: pFont->m_eWidth = width::ExtraExpanded; break;
1945*cdf0e10cSrcweir             case FWIDTH_ULTRA_EXPANDED: pFont->m_eWidth = width::UltraExpanded; break;
1946*cdf0e10cSrcweir 
1947*cdf0e10cSrcweir             case FWIDTH_NORMAL:
1948*cdf0e10cSrcweir             default:                        pFont->m_eWidth = width::Normal; break;
1949*cdf0e10cSrcweir         }
1950*cdf0e10cSrcweir 
1951*cdf0e10cSrcweir         pFont->m_ePitch = aInfo.pitch ? pitch::Fixed : pitch::Variable;
1952*cdf0e10cSrcweir         pFont->m_eItalic = aInfo.italicAngle == 0 ? italic::Upright : ( aInfo.italicAngle < 0 ? italic::Italic : italic::Oblique );
1953*cdf0e10cSrcweir         // #104264# there are fonts that set italic angle 0 although they are
1954*cdf0e10cSrcweir         // italic; use macstyle bit here
1955*cdf0e10cSrcweir         if( aInfo.italicAngle == 0 && (aInfo.macStyle & 2) )
1956*cdf0e10cSrcweir             pFont->m_eItalic = italic::Italic;
1957*cdf0e10cSrcweir 
1958*cdf0e10cSrcweir         pFont->m_aEncoding = aInfo.symbolEncoded ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UCS2;
1959*cdf0e10cSrcweir 
1960*cdf0e10cSrcweir         pFont->m_aGlobalMetricY.width = pFont->m_aGlobalMetricX.width = aInfo.xMax - aInfo.xMin;
1961*cdf0e10cSrcweir         pFont->m_aGlobalMetricY.height = pFont->m_aGlobalMetricX.height = aInfo.yMax - aInfo.yMin;
1962*cdf0e10cSrcweir 
1963*cdf0e10cSrcweir         if( aInfo.winAscent && aInfo.winDescent )
1964*cdf0e10cSrcweir         {
1965*cdf0e10cSrcweir             pFont->m_nAscend    = aInfo.winAscent;
1966*cdf0e10cSrcweir             pFont->m_nDescend   = aInfo.winDescent;
1967*cdf0e10cSrcweir             pFont->m_nLeading   = pFont->m_nAscend + pFont->m_nDescend - 1000;
1968*cdf0e10cSrcweir         }
1969*cdf0e10cSrcweir         else if( aInfo.typoAscender && aInfo.typoDescender )
1970*cdf0e10cSrcweir         {
1971*cdf0e10cSrcweir             pFont->m_nLeading   = aInfo.typoLineGap;
1972*cdf0e10cSrcweir             pFont->m_nAscend    = aInfo.typoAscender;
1973*cdf0e10cSrcweir             pFont->m_nDescend   = -aInfo.typoDescender;
1974*cdf0e10cSrcweir         }
1975*cdf0e10cSrcweir         else
1976*cdf0e10cSrcweir         {
1977*cdf0e10cSrcweir             pFont->m_nLeading   = aInfo.linegap;
1978*cdf0e10cSrcweir             pFont->m_nAscend    = aInfo.ascender;
1979*cdf0e10cSrcweir             pFont->m_nDescend   = -aInfo.descender;
1980*cdf0e10cSrcweir         }
1981*cdf0e10cSrcweir 
1982*cdf0e10cSrcweir         // last try: font bounding box
1983*cdf0e10cSrcweir         if( pFont->m_nAscend == 0 )
1984*cdf0e10cSrcweir             pFont->m_nAscend = aInfo.yMax;
1985*cdf0e10cSrcweir         if( pFont->m_nDescend == 0 )
1986*cdf0e10cSrcweir             pFont->m_nDescend = -aInfo.yMin;
1987*cdf0e10cSrcweir         if( pFont->m_nLeading == 0 )
1988*cdf0e10cSrcweir             pFont->m_nLeading = 15 * (pFont->m_nAscend+pFont->m_nDescend) / 100;
1989*cdf0e10cSrcweir 
1990*cdf0e10cSrcweir         if( pFont->m_nAscend )
1991*cdf0e10cSrcweir             pFont->m_aGlobalMetricX.height = pFont->m_aGlobalMetricY.height = pFont->m_nAscend + pFont->m_nDescend;
1992*cdf0e10cSrcweir 
1993*cdf0e10cSrcweir         // get bounding box
1994*cdf0e10cSrcweir         pFont->m_nXMin = aInfo.xMin;
1995*cdf0e10cSrcweir         pFont->m_nYMin = aInfo.yMin;
1996*cdf0e10cSrcweir         pFont->m_nXMax = aInfo.xMax;
1997*cdf0e10cSrcweir         pFont->m_nYMax = aInfo.yMax;
1998*cdf0e10cSrcweir 
1999*cdf0e10cSrcweir         // get type flags
2000*cdf0e10cSrcweir         pTTFontFile->m_nTypeFlags = (unsigned int)aInfo.typeFlags;
2001*cdf0e10cSrcweir 
2002*cdf0e10cSrcweir         // get vertical substitutions flag
2003*cdf0e10cSrcweir         pFont->m_bHaveVerticalSubstitutedGlyphs = DoesVerticalSubstitution( pTTFont, 1 );
2004*cdf0e10cSrcweir 
2005*cdf0e10cSrcweir         CloseTTFont( pTTFont );
2006*cdf0e10cSrcweir         bSuccess = true;
2007*cdf0e10cSrcweir     }
2008*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2009*cdf0e10cSrcweir     else
2010*cdf0e10cSrcweir         fprintf( stderr, "could not OpenTTFont \"%s\"\n", aFile.GetBuffer() );
2011*cdf0e10cSrcweir #endif
2012*cdf0e10cSrcweir 
2013*cdf0e10cSrcweir     return bSuccess;
2014*cdf0e10cSrcweir }
2015*cdf0e10cSrcweir 
2016*cdf0e10cSrcweir // -------------------------------------------------------------------------
2017*cdf0e10cSrcweir 
2018*cdf0e10cSrcweir void PrintFontManager::initFontsAlias()
2019*cdf0e10cSrcweir {
2020*cdf0e10cSrcweir     m_aXLFD_Aliases.clear();
2021*cdf0e10cSrcweir     rtl_TextEncoding aEnc = osl_getThreadTextEncoding();
2022*cdf0e10cSrcweir     for( std::list< OString >::const_iterator dir_it = m_aFontDirectories.begin();
2023*cdf0e10cSrcweir          dir_it != m_aFontDirectories.end(); ++dir_it )
2024*cdf0e10cSrcweir     {
2025*cdf0e10cSrcweir         OStringBuffer aDirName(512);
2026*cdf0e10cSrcweir         aDirName.append( *dir_it );
2027*cdf0e10cSrcweir         aDirName.append( "/fonts.alias" );
2028*cdf0e10cSrcweir         SvFileStream aStream( OStringToOUString( aDirName.makeStringAndClear(), aEnc ), STREAM_READ );
2029*cdf0e10cSrcweir         if( ! aStream.IsOpen() )
2030*cdf0e10cSrcweir             continue;
2031*cdf0e10cSrcweir 
2032*cdf0e10cSrcweir         do
2033*cdf0e10cSrcweir         {
2034*cdf0e10cSrcweir             ByteString aLine;
2035*cdf0e10cSrcweir             aStream.ReadLine( aLine );
2036*cdf0e10cSrcweir 
2037*cdf0e10cSrcweir             // get the alias and the pattern it gets translated to
2038*cdf0e10cSrcweir             ByteString aAlias	= GetCommandLineToken( 0, aLine );
2039*cdf0e10cSrcweir             ByteString aMap		= GetCommandLineToken( 1, aLine );
2040*cdf0e10cSrcweir 
2041*cdf0e10cSrcweir             // remove eventual quotes
2042*cdf0e10cSrcweir             aAlias.EraseLeadingChars( '"' );
2043*cdf0e10cSrcweir             aAlias.EraseTrailingChars( '"' );
2044*cdf0e10cSrcweir             aMap.EraseLeadingChars( '"' );
2045*cdf0e10cSrcweir             aMap.EraseTrailingChars( '"' );
2046*cdf0e10cSrcweir 
2047*cdf0e10cSrcweir             XLFDEntry aAliasEntry, aMapEntry;
2048*cdf0e10cSrcweir             parseXLFD( aAlias, aAliasEntry );
2049*cdf0e10cSrcweir             parseXLFD( aMap, aMapEntry );
2050*cdf0e10cSrcweir 
2051*cdf0e10cSrcweir             if( aAliasEntry.nMask && aMapEntry.nMask )
2052*cdf0e10cSrcweir                 m_aXLFD_Aliases[ aMapEntry ].push_back( aAliasEntry );
2053*cdf0e10cSrcweir         } while( ! aStream.IsEof() );
2054*cdf0e10cSrcweir     }
2055*cdf0e10cSrcweir }
2056*cdf0e10cSrcweir 
2057*cdf0e10cSrcweir // code stolen from vcl's RegisterFontSubstitutors()
2058*cdf0e10cSrcweir // TODO: use that method once psprint gets merged into vcl
2059*cdf0e10cSrcweir static bool AreFCSubstitutionsEnabled()
2060*cdf0e10cSrcweir {
2061*cdf0e10cSrcweir     // init font substitution defaults
2062*cdf0e10cSrcweir     int nDisableBits = 0;
2063*cdf0e10cSrcweir #ifdef SOLARIS
2064*cdf0e10cSrcweir     // TODO: check the OS version and fc-data maintenance level
2065*cdf0e10cSrcweir     nDisableBits = 1; // disable "font fallback" here on default
2066*cdf0e10cSrcweir #endif
2067*cdf0e10cSrcweir     // apply the environment variable if any
2068*cdf0e10cSrcweir     const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" );
2069*cdf0e10cSrcweir     if( pEnvStr )
2070*cdf0e10cSrcweir     {
2071*cdf0e10cSrcweir         //
2072*cdf0e10cSrcweir         if( (*pEnvStr >= '0') && (*pEnvStr <= '9') )
2073*cdf0e10cSrcweir             nDisableBits = (*pEnvStr - '0');
2074*cdf0e10cSrcweir         else
2075*cdf0e10cSrcweir             nDisableBits = ~0U; // no specific bits set: disable all
2076*cdf0e10cSrcweir     }
2077*cdf0e10cSrcweir 
2078*cdf0e10cSrcweir     return ((nDisableBits & 3) == 0);
2079*cdf0e10cSrcweir }
2080*cdf0e10cSrcweir 
2081*cdf0e10cSrcweir void PrintFontManager::initialize()
2082*cdf0e10cSrcweir {
2083*cdf0e10cSrcweir     #ifdef CALLGRIND_COMPILE
2084*cdf0e10cSrcweir     CALLGRIND_TOGGLE_COLLECT();
2085*cdf0e10cSrcweir     CALLGRIND_ZERO_STATS();
2086*cdf0e10cSrcweir     #endif
2087*cdf0e10cSrcweir 
2088*cdf0e10cSrcweir     long aDirEntBuffer[ (sizeof(struct dirent)+_PC_NAME_MAX)+1 ];
2089*cdf0e10cSrcweir 
2090*cdf0e10cSrcweir     if( ! m_pFontCache )
2091*cdf0e10cSrcweir     {
2092*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2093*cdf0e10cSrcweir         fprintf( stderr, "creating font cache ... " );
2094*cdf0e10cSrcweir         clock_t aStart;
2095*cdf0e10cSrcweir         struct tms tms;
2096*cdf0e10cSrcweir         aStart = times( &tms );
2097*cdf0e10cSrcweir #endif
2098*cdf0e10cSrcweir         m_pFontCache = new FontCache();
2099*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2100*cdf0e10cSrcweir         clock_t aStop = times( &tms );
2101*cdf0e10cSrcweir         fprintf( stderr, "done in %lf s\n", (double)(aStop - aStart)/(double)sysconf( _SC_CLK_TCK ) );
2102*cdf0e10cSrcweir #endif
2103*cdf0e10cSrcweir     }
2104*cdf0e10cSrcweir 
2105*cdf0e10cSrcweir     // initialize may be called twice in the future
2106*cdf0e10cSrcweir     {
2107*cdf0e10cSrcweir         for( ::std::hash_map< fontID, PrintFont* >::const_iterator it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
2108*cdf0e10cSrcweir             delete (*it).second;
2109*cdf0e10cSrcweir         m_nNextFontID = 1;
2110*cdf0e10cSrcweir         m_aFonts.clear();
2111*cdf0e10cSrcweir         m_aFontDirectories.clear();
2112*cdf0e10cSrcweir         m_aPrivateFontDirectories.clear();
2113*cdf0e10cSrcweir         m_aOverrideFonts.clear();
2114*cdf0e10cSrcweir     }
2115*cdf0e10cSrcweir 
2116*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2117*cdf0e10cSrcweir     clock_t aStart;
2118*cdf0e10cSrcweir     clock_t aStep1;
2119*cdf0e10cSrcweir     clock_t aStep2;
2120*cdf0e10cSrcweir     clock_t aStep3;
2121*cdf0e10cSrcweir     int nBuiltinFonts = 0;
2122*cdf0e10cSrcweir     int nCached = 0;
2123*cdf0e10cSrcweir 
2124*cdf0e10cSrcweir     struct tms tms;
2125*cdf0e10cSrcweir 
2126*cdf0e10cSrcweir     aStart = times( &tms );
2127*cdf0e10cSrcweir #endif
2128*cdf0e10cSrcweir 
2129*cdf0e10cSrcweir     // first try fontconfig
2130*cdf0e10cSrcweir     m_bFontconfigSuccess = initFontconfig();
2131*cdf0e10cSrcweir 
2132*cdf0e10cSrcweir     // part one - look for downloadable fonts
2133*cdf0e10cSrcweir     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
2134*cdf0e10cSrcweir     const ::rtl::OUString &rSalPrivatePath = psp::getFontPath();
2135*cdf0e10cSrcweir 
2136*cdf0e10cSrcweir     // search for the fonts in SAL_PRIVATE_FONTPATH first; those are
2137*cdf0e10cSrcweir     // the fonts installed with the office
2138*cdf0e10cSrcweir     if( rSalPrivatePath.getLength() )
2139*cdf0e10cSrcweir     {
2140*cdf0e10cSrcweir         OString aPath = rtl::OUStringToOString( rSalPrivatePath, aEncoding );
2141*cdf0e10cSrcweir         const bool bAreFCSubstitutionsEnabled = AreFCSubstitutionsEnabled();
2142*cdf0e10cSrcweir         sal_Int32 nIndex = 0;
2143*cdf0e10cSrcweir         do
2144*cdf0e10cSrcweir         {
2145*cdf0e10cSrcweir             OString aToken = aPath.getToken( 0, ';', nIndex );
2146*cdf0e10cSrcweir             normPath( aToken );
2147*cdf0e10cSrcweir             // if registering an app-specific fontdir with fontconfig fails
2148*cdf0e10cSrcweir             // and fontconfig-based substitutions are enabled
2149*cdf0e10cSrcweir             // then trying to use these app-specific fonts doesn't make sense
2150*cdf0e10cSrcweir             if( m_bFontconfigSuccess && !addFontconfigDir( aToken ) )
2151*cdf0e10cSrcweir                 if( bAreFCSubstitutionsEnabled )
2152*cdf0e10cSrcweir                     continue;
2153*cdf0e10cSrcweir             m_aFontDirectories.push_back( aToken );
2154*cdf0e10cSrcweir             m_aPrivateFontDirectories.push_back( getDirectoryAtom( aToken, true ) );
2155*cdf0e10cSrcweir         } while( nIndex >= 0 );
2156*cdf0e10cSrcweir     }
2157*cdf0e10cSrcweir 
2158*cdf0e10cSrcweir     // protect against duplicate paths
2159*cdf0e10cSrcweir     std::hash_map< OString, int, OStringHash > visited_dirs;
2160*cdf0e10cSrcweir 
2161*cdf0e10cSrcweir     // now that all global and local font dirs are known to fontconfig
2162*cdf0e10cSrcweir     // check that there are fonts actually managed by fontconfig
2163*cdf0e10cSrcweir     // also don't search directories that fontconfig already did
2164*cdf0e10cSrcweir     if( m_bFontconfigSuccess )
2165*cdf0e10cSrcweir         m_bFontconfigSuccess = (countFontconfigFonts( visited_dirs ) > 0);
2166*cdf0e10cSrcweir 
2167*cdf0e10cSrcweir     // don't search through many directories fontconfig already told us about
2168*cdf0e10cSrcweir     if( ! m_bFontconfigSuccess )
2169*cdf0e10cSrcweir         ImplGetSVData()->mpDefInst->FillFontPathList( m_aFontDirectories );
2170*cdf0e10cSrcweir 
2171*cdf0e10cSrcweir     // fill XLFD aliases from fonts.alias files
2172*cdf0e10cSrcweir     initFontsAlias();
2173*cdf0e10cSrcweir 
2174*cdf0e10cSrcweir     // search for font files in each path
2175*cdf0e10cSrcweir     std::list< OString >::iterator dir_it;
2176*cdf0e10cSrcweir     for( dir_it = m_aFontDirectories.begin(); dir_it != m_aFontDirectories.end(); ++dir_it )
2177*cdf0e10cSrcweir     {
2178*cdf0e10cSrcweir         OString aPath( *dir_it );
2179*cdf0e10cSrcweir         // see if we were here already
2180*cdf0e10cSrcweir         if( visited_dirs.find( aPath ) != visited_dirs.end() )
2181*cdf0e10cSrcweir             continue;
2182*cdf0e10cSrcweir         visited_dirs[ aPath ] = 1;
2183*cdf0e10cSrcweir 
2184*cdf0e10cSrcweir         // there may be ":unscaled" directories (see XFree86)
2185*cdf0e10cSrcweir         // it should be safe to ignore them since they should not
2186*cdf0e10cSrcweir         // contain any of our recognizeable fonts
2187*cdf0e10cSrcweir 
2188*cdf0e10cSrcweir         // ask the font cache whether it handles this directory
2189*cdf0e10cSrcweir         std::list< PrintFont* > aCacheFonts;
2190*cdf0e10cSrcweir         if( m_pFontCache->listDirectory( aPath, aCacheFonts ) )
2191*cdf0e10cSrcweir         {
2192*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2193*cdf0e10cSrcweir             fprintf( stderr, "adding cache directory: %s\n", aPath.getStr() );
2194*cdf0e10cSrcweir #endif
2195*cdf0e10cSrcweir             for( ::std::list< PrintFont* >::iterator it = aCacheFonts.begin(); it != aCacheFonts.end(); ++it )
2196*cdf0e10cSrcweir             {
2197*cdf0e10cSrcweir                 fontID aFont = m_nNextFontID++;
2198*cdf0e10cSrcweir                 m_aFonts[ aFont ] = *it;
2199*cdf0e10cSrcweir                 if( (*it)->m_eType == fonttype::Type1 )
2200*cdf0e10cSrcweir                     m_aFontFileToFontID[ static_cast<Type1FontFile*>(*it)->m_aFontFile ].insert( aFont );
2201*cdf0e10cSrcweir                 else if( (*it)->m_eType == fonttype::TrueType )
2202*cdf0e10cSrcweir                     m_aFontFileToFontID[ static_cast<TrueTypeFontFile*>(*it)->m_aFontFile ].insert( aFont );
2203*cdf0e10cSrcweir                 else if( (*it)->m_eType == fonttype::Builtin )
2204*cdf0e10cSrcweir                     m_aFontFileToFontID[ static_cast<BuiltinFont*>(*it)->m_aMetricFile ].insert( aFont );
2205*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2206*cdf0e10cSrcweir                 if( (*it)->m_eType == fonttype::Builtin )
2207*cdf0e10cSrcweir                     nBuiltinFonts++;
2208*cdf0e10cSrcweir                 nCached++;
2209*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 2
2210*cdf0e10cSrcweir                 fprintf( stderr, "adding cached font %d: \"%s\" from %s\n", aFont,
2211*cdf0e10cSrcweir                          OUStringToOString( getFontFamily( aFont ), RTL_TEXTENCODING_MS_1252 ).getStr(),
2212*cdf0e10cSrcweir                          getFontFileSysPath( aFont ).getStr() );
2213*cdf0e10cSrcweir #endif
2214*cdf0e10cSrcweir #endif
2215*cdf0e10cSrcweir             }
2216*cdf0e10cSrcweir             if( ! m_pFontCache->scanAdditionalFiles( aPath ) )
2217*cdf0e10cSrcweir                 continue;
2218*cdf0e10cSrcweir         }
2219*cdf0e10cSrcweir 
2220*cdf0e10cSrcweir         DIR* pDIR = opendir( aPath.getStr() );
2221*cdf0e10cSrcweir         struct dirent* pEntry = (struct dirent*)aDirEntBuffer;
2222*cdf0e10cSrcweir         if( pDIR )
2223*cdf0e10cSrcweir         {
2224*cdf0e10cSrcweir             // read fonts.dir if possible
2225*cdf0e10cSrcweir             ::std::hash_map< OString, ::std::list<OString>, OStringHash > aFontsDir;
2226*cdf0e10cSrcweir             int nDirID = getDirectoryAtom( aPath, true );
2227*cdf0e10cSrcweir             // #i38367# no fonts.dir in our own directories anymore
2228*cdf0e10cSrcweir             std::list< int >::const_iterator priv_dir;
2229*cdf0e10cSrcweir             for( priv_dir = m_aPrivateFontDirectories.begin();
2230*cdf0e10cSrcweir                  priv_dir != m_aPrivateFontDirectories.end() && *priv_dir != nDirID;
2231*cdf0e10cSrcweir                  ++priv_dir )
2232*cdf0e10cSrcweir                  ;
2233*cdf0e10cSrcweir 
2234*cdf0e10cSrcweir             if( priv_dir == m_aPrivateFontDirectories.end() )
2235*cdf0e10cSrcweir             {
2236*cdf0e10cSrcweir                 ByteString aGccDummy( aPath );
2237*cdf0e10cSrcweir                 String aFontsDirPath( aGccDummy, aEncoding );
2238*cdf0e10cSrcweir                 aFontsDirPath.AppendAscii( "/fonts.dir" );
2239*cdf0e10cSrcweir                 SvFileStream aStream( aFontsDirPath, STREAM_READ );
2240*cdf0e10cSrcweir                 if( aStream.IsOpen() )
2241*cdf0e10cSrcweir                 {
2242*cdf0e10cSrcweir                     ByteString aLine;
2243*cdf0e10cSrcweir                     while( ! aStream.IsEof() )
2244*cdf0e10cSrcweir                     {
2245*cdf0e10cSrcweir                         aStream.ReadLine( aLine );
2246*cdf0e10cSrcweir                         ByteString aFileName( GetCommandLineToken( 0, aLine ) );
2247*cdf0e10cSrcweir                         ByteString aXLFD( aLine.Copy( aFileName.Len() ) );
2248*cdf0e10cSrcweir                         if( aFileName.Len() && aXLFD.Len() )
2249*cdf0e10cSrcweir                             aFontsDir[ aFileName ].push_back(aXLFD);
2250*cdf0e10cSrcweir                     }
2251*cdf0e10cSrcweir                 }
2252*cdf0e10cSrcweir             }
2253*cdf0e10cSrcweir 
2254*cdf0e10cSrcweir             int nDirFonts = 0;
2255*cdf0e10cSrcweir             while( ! readdir_r( pDIR, (struct dirent*)aDirEntBuffer, &pEntry ) && pEntry )
2256*cdf0e10cSrcweir             {
2257*cdf0e10cSrcweir                 OString aFileName( pEntry->d_name );
2258*cdf0e10cSrcweir                 // ignore .afm files here
2259*cdf0e10cSrcweir                 if( aFileName.getLength() > 3 &&
2260*cdf0e10cSrcweir                     aFileName.lastIndexOf( ".afm" ) == aFileName.getLength()-4 )
2261*cdf0e10cSrcweir                     continue;
2262*cdf0e10cSrcweir 
2263*cdf0e10cSrcweir                 struct stat aStat;
2264*cdf0e10cSrcweir                 ByteString aFilePath( aPath );
2265*cdf0e10cSrcweir                 aFilePath.Append( '/' );
2266*cdf0e10cSrcweir                 aFilePath.Append( ByteString( aFileName ) );
2267*cdf0e10cSrcweir                 if( ! stat( aFilePath.GetBuffer(), &aStat )     &&
2268*cdf0e10cSrcweir                     S_ISREG( aStat.st_mode ) )
2269*cdf0e10cSrcweir                 {
2270*cdf0e10cSrcweir                     if( findFontFileID( nDirID, aFileName ) == 0 )
2271*cdf0e10cSrcweir                     {
2272*cdf0e10cSrcweir                         ::std::list<OString> aXLFDs;
2273*cdf0e10cSrcweir                         ::std::hash_map< OString, ::std::list<OString>, OStringHash >::const_iterator it =
2274*cdf0e10cSrcweir                               aFontsDir.find( aFileName );
2275*cdf0e10cSrcweir                         if( it != aFontsDir.end() )
2276*cdf0e10cSrcweir                             aXLFDs = (*it).second;
2277*cdf0e10cSrcweir 
2278*cdf0e10cSrcweir                         // fill in font attributes from XLFD rather
2279*cdf0e10cSrcweir                         // than reading every file
2280*cdf0e10cSrcweir                         ::std::list< PrintFont* > aNewFonts;
2281*cdf0e10cSrcweir                         if( analyzeFontFile( nDirID, aFileName, aXLFDs, aNewFonts ) )
2282*cdf0e10cSrcweir                         {
2283*cdf0e10cSrcweir                             for( ::std::list< PrintFont* >::iterator font_it = aNewFonts.begin(); font_it != aNewFonts.end(); ++font_it )
2284*cdf0e10cSrcweir                             {
2285*cdf0e10cSrcweir                                 fontID aFont = m_nNextFontID++;
2286*cdf0e10cSrcweir                                 m_aFonts[ aFont ] = *font_it;
2287*cdf0e10cSrcweir                                 m_aFontFileToFontID[ aFileName ].insert( aFont );
2288*cdf0e10cSrcweir                                 m_pFontCache->updateFontCacheEntry( *font_it, false );
2289*cdf0e10cSrcweir                                 nDirFonts++;
2290*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 2
2291*cdf0e10cSrcweir                                 fprintf( stderr, "adding font %d: \"%s\" from %s\n", aFont,
2292*cdf0e10cSrcweir                                          OUStringToOString( getFontFamily( aFont ), RTL_TEXTENCODING_MS_1252 ).getStr(),
2293*cdf0e10cSrcweir                                          getFontFileSysPath( aFont ).getStr() );
2294*cdf0e10cSrcweir #endif
2295*cdf0e10cSrcweir                             }
2296*cdf0e10cSrcweir                         }
2297*cdf0e10cSrcweir                     }
2298*cdf0e10cSrcweir                 }
2299*cdf0e10cSrcweir             }
2300*cdf0e10cSrcweir             closedir( pDIR );
2301*cdf0e10cSrcweir             m_pFontCache->updateDirTimestamp( nDirID );
2302*cdf0e10cSrcweir             if( ! nDirFonts )
2303*cdf0e10cSrcweir                 m_pFontCache->markEmptyDir( nDirID );
2304*cdf0e10cSrcweir         }
2305*cdf0e10cSrcweir     }
2306*cdf0e10cSrcweir 
2307*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2308*cdf0e10cSrcweir     aStep1 = times( &tms );
2309*cdf0e10cSrcweir #endif
2310*cdf0e10cSrcweir 
2311*cdf0e10cSrcweir     // part two - look for metrics for builtin printer fonts
2312*cdf0e10cSrcweir     std::list< OUString > aMetricDirs;
2313*cdf0e10cSrcweir     psp::getPrinterPathList( aMetricDirs, PRINTER_METRICDIR );
2314*cdf0e10cSrcweir 
2315*cdf0e10cSrcweir     std::list< OString > aEmptyFontsDir;
2316*cdf0e10cSrcweir     for( std::list< OUString >::const_iterator met_dir_it = aMetricDirs.begin(); met_dir_it != aMetricDirs.end(); ++met_dir_it )
2317*cdf0e10cSrcweir     {
2318*cdf0e10cSrcweir         OString aDir = OUStringToOString( *met_dir_it, aEncoding );
2319*cdf0e10cSrcweir 
2320*cdf0e10cSrcweir         // ask the font cache whether it handles this directory
2321*cdf0e10cSrcweir         std::list< PrintFont* > aCacheFonts;
2322*cdf0e10cSrcweir 
2323*cdf0e10cSrcweir         if( m_pFontCache->listDirectory( aDir, aCacheFonts ) )
2324*cdf0e10cSrcweir         {
2325*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2326*cdf0e10cSrcweir             fprintf( stderr, "adding cache directory: %s\n", aDir.getStr() );
2327*cdf0e10cSrcweir #endif
2328*cdf0e10cSrcweir             for( ::std::list< PrintFont* >::iterator it = aCacheFonts.begin(); it != aCacheFonts.end(); ++it )
2329*cdf0e10cSrcweir             {
2330*cdf0e10cSrcweir                 fontID aFont = m_nNextFontID++;
2331*cdf0e10cSrcweir                 m_aFonts[ aFont ] = *it;
2332*cdf0e10cSrcweir                 if( (*it)->m_eType == fonttype::Type1 )
2333*cdf0e10cSrcweir                     m_aFontFileToFontID[ static_cast<Type1FontFile*>(*it)->m_aFontFile ].insert( aFont );
2334*cdf0e10cSrcweir                 else if( (*it)->m_eType == fonttype::TrueType )
2335*cdf0e10cSrcweir                     m_aFontFileToFontID[ static_cast<TrueTypeFontFile*>(*it)->m_aFontFile ].insert( aFont );
2336*cdf0e10cSrcweir                 else if( (*it)->m_eType == fonttype::Builtin )
2337*cdf0e10cSrcweir                     m_aFontFileToFontID[ static_cast<BuiltinFont*>(*it)->m_aMetricFile ].insert( aFont );
2338*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2339*cdf0e10cSrcweir                 if( (*it)->m_eType == fonttype::Builtin )
2340*cdf0e10cSrcweir                     nBuiltinFonts++;
2341*cdf0e10cSrcweir                 nCached++;
2342*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 2
2343*cdf0e10cSrcweir                 fprintf( stderr, "adding cached font %d: \"%s\" from %s\n", aFont,
2344*cdf0e10cSrcweir                          OUStringToOString( getFontFamily( aFont ), RTL_TEXTENCODING_MS_1252 ).getStr(),
2345*cdf0e10cSrcweir                          getFontFileSysPath( aFont ).getStr() );
2346*cdf0e10cSrcweir #endif
2347*cdf0e10cSrcweir #endif
2348*cdf0e10cSrcweir             }
2349*cdf0e10cSrcweir             continue;
2350*cdf0e10cSrcweir         }
2351*cdf0e10cSrcweir 
2352*cdf0e10cSrcweir         DIR* pDIR = opendir( aDir.getStr() );
2353*cdf0e10cSrcweir         if( pDIR )
2354*cdf0e10cSrcweir         {
2355*cdf0e10cSrcweir             struct dirent* pDirEntry = (struct dirent*)aDirEntBuffer;
2356*cdf0e10cSrcweir             int nDirID = getDirectoryAtom( aDir, true );
2357*cdf0e10cSrcweir             int nDirFonts = 0;
2358*cdf0e10cSrcweir 
2359*cdf0e10cSrcweir             while( ! readdir_r( pDIR, (struct dirent*)aDirEntBuffer, &pDirEntry ) && pDirEntry )
2360*cdf0e10cSrcweir             {
2361*cdf0e10cSrcweir                 ByteString aFile( aDir );
2362*cdf0e10cSrcweir                 aFile += '/';
2363*cdf0e10cSrcweir                 aFile += pDirEntry->d_name;
2364*cdf0e10cSrcweir                 struct stat aStat;
2365*cdf0e10cSrcweir                 if( ! stat( aFile.GetBuffer(), &aStat )
2366*cdf0e10cSrcweir                     && S_ISREG( aStat.st_mode )
2367*cdf0e10cSrcweir                     )
2368*cdf0e10cSrcweir                 {
2369*cdf0e10cSrcweir                     OString aFileName( pDirEntry->d_name, strlen( pDirEntry->d_name ) );
2370*cdf0e10cSrcweir                     OString aExt( aFileName.copy( aFileName.lastIndexOf( '.' )+1 ) );
2371*cdf0e10cSrcweir                     if( aExt.equalsIgnoreAsciiCase( "afm" ) )
2372*cdf0e10cSrcweir                     {
2373*cdf0e10cSrcweir                         ::std::list< PrintFont* > aNewFonts;
2374*cdf0e10cSrcweir 
2375*cdf0e10cSrcweir                         analyzeFontFile( nDirID, aFileName, aEmptyFontsDir, aNewFonts );
2376*cdf0e10cSrcweir                         for( ::std::list< PrintFont* >::iterator it = aNewFonts.begin(); it != aNewFonts.end(); ++it )
2377*cdf0e10cSrcweir                         {
2378*cdf0e10cSrcweir                             if( findFontBuiltinID( (*it)->m_nPSName ) == 0 )
2379*cdf0e10cSrcweir                             {
2380*cdf0e10cSrcweir                                 m_aFontFileToFontID[ aFileName ].insert( m_nNextFontID );
2381*cdf0e10cSrcweir                                 m_aFonts[ m_nNextFontID++ ] = *it;
2382*cdf0e10cSrcweir                                 m_pFontCache->updateFontCacheEntry( *it, false );
2383*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 2
2384*cdf0e10cSrcweir                                 nBuiltinFonts++;
2385*cdf0e10cSrcweir #endif
2386*cdf0e10cSrcweir                             }
2387*cdf0e10cSrcweir                             else
2388*cdf0e10cSrcweir                                 delete *it;
2389*cdf0e10cSrcweir                         }
2390*cdf0e10cSrcweir                     }
2391*cdf0e10cSrcweir                 }
2392*cdf0e10cSrcweir             }
2393*cdf0e10cSrcweir             closedir( pDIR );
2394*cdf0e10cSrcweir             if( ! nDirFonts )
2395*cdf0e10cSrcweir                 m_pFontCache->markEmptyDir( nDirID );
2396*cdf0e10cSrcweir         }
2397*cdf0e10cSrcweir     }
2398*cdf0e10cSrcweir 
2399*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2400*cdf0e10cSrcweir     aStep2 = times( &tms );
2401*cdf0e10cSrcweir #endif
2402*cdf0e10cSrcweir 
2403*cdf0e10cSrcweir     // part three - fill in family styles
2404*cdf0e10cSrcweir     ::std::hash_map< fontID, PrintFont* >::iterator font_it;
2405*cdf0e10cSrcweir     for (font_it = m_aFonts.begin(); font_it != m_aFonts.end(); ++font_it)
2406*cdf0e10cSrcweir     {
2407*cdf0e10cSrcweir         ::std::hash_map< int, family::type >::const_iterator it =
2408*cdf0e10cSrcweir               m_aFamilyTypes.find( font_it->second->m_nFamilyName );
2409*cdf0e10cSrcweir         if (it != m_aFamilyTypes.end())
2410*cdf0e10cSrcweir             continue;
2411*cdf0e10cSrcweir         const ::rtl::OUString& rFamily =
2412*cdf0e10cSrcweir             m_pAtoms->getString( ATOM_FAMILYNAME, font_it->second->m_nFamilyName);
2413*cdf0e10cSrcweir         family::type eType = matchFamilyName( rFamily );
2414*cdf0e10cSrcweir         m_aFamilyTypes[ font_it->second->m_nFamilyName ] = eType;
2415*cdf0e10cSrcweir     }
2416*cdf0e10cSrcweir 
2417*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2418*cdf0e10cSrcweir     aStep3 = times( &tms );
2419*cdf0e10cSrcweir     fprintf( stderr, "PrintFontManager::initialize: collected %d fonts (%d builtin, %d cached)\n", m_aFonts.size(), nBuiltinFonts, nCached );
2420*cdf0e10cSrcweir     double fTick = (double)sysconf( _SC_CLK_TCK );
2421*cdf0e10cSrcweir     fprintf( stderr, "Step 1 took %lf seconds\n", (double)(aStep1 - aStart)/fTick );
2422*cdf0e10cSrcweir     fprintf( stderr, "Step 2 took %lf seconds\n", (double)(aStep2 - aStep1)/fTick );
2423*cdf0e10cSrcweir     fprintf( stderr, "Step 3 took %lf seconds\n", (double)(aStep3 - aStep2)/fTick );
2424*cdf0e10cSrcweir #endif
2425*cdf0e10cSrcweir 
2426*cdf0e10cSrcweir     m_pFontCache->flush();
2427*cdf0e10cSrcweir 
2428*cdf0e10cSrcweir     #ifdef CALLGRIND_COMPILE
2429*cdf0e10cSrcweir     CALLGRIND_DUMP_STATS();
2430*cdf0e10cSrcweir     CALLGRIND_TOGGLE_COLLECT();
2431*cdf0e10cSrcweir     #endif
2432*cdf0e10cSrcweir }
2433*cdf0e10cSrcweir 
2434*cdf0e10cSrcweir // -------------------------------------------------------------------------
2435*cdf0e10cSrcweir inline bool
2436*cdf0e10cSrcweir equalPitch (psp::pitch::type from, psp::pitch::type to)
2437*cdf0e10cSrcweir {
2438*cdf0e10cSrcweir     return from == to;
2439*cdf0e10cSrcweir }
2440*cdf0e10cSrcweir 
2441*cdf0e10cSrcweir inline bool
2442*cdf0e10cSrcweir equalWeight (psp::weight::type from, psp::weight::type to)
2443*cdf0e10cSrcweir {
2444*cdf0e10cSrcweir     return from > to ? (from - to) <= 3 : (to - from) <= 3;
2445*cdf0e10cSrcweir }
2446*cdf0e10cSrcweir 
2447*cdf0e10cSrcweir inline bool
2448*cdf0e10cSrcweir equalItalic (psp::italic::type from, psp::italic::type to)
2449*cdf0e10cSrcweir {
2450*cdf0e10cSrcweir     if ( (from == psp::italic::Italic) || (from == psp::italic::Oblique) )
2451*cdf0e10cSrcweir         return (to == psp::italic::Italic) || (to == psp::italic::Oblique);
2452*cdf0e10cSrcweir     return to == from;
2453*cdf0e10cSrcweir }
2454*cdf0e10cSrcweir inline bool
2455*cdf0e10cSrcweir equalEncoding (rtl_TextEncoding from, rtl_TextEncoding to)
2456*cdf0e10cSrcweir {
2457*cdf0e10cSrcweir     if ((from == RTL_TEXTENCODING_ISO_8859_1) || (from == RTL_TEXTENCODING_MS_1252))
2458*cdf0e10cSrcweir         return (to == RTL_TEXTENCODING_ISO_8859_1) || (to == RTL_TEXTENCODING_MS_1252);
2459*cdf0e10cSrcweir     return from == to;
2460*cdf0e10cSrcweir }
2461*cdf0e10cSrcweir 
2462*cdf0e10cSrcweir namespace {
2463*cdf0e10cSrcweir     struct BuiltinFontIdentifier
2464*cdf0e10cSrcweir     {
2465*cdf0e10cSrcweir         OUString            aFamily;
2466*cdf0e10cSrcweir         italic::type        eItalic;
2467*cdf0e10cSrcweir         weight::type        eWeight;
2468*cdf0e10cSrcweir         pitch::type         ePitch;
2469*cdf0e10cSrcweir         rtl_TextEncoding    aEncoding;
2470*cdf0e10cSrcweir 
2471*cdf0e10cSrcweir         BuiltinFontIdentifier( const OUString& rFam,
2472*cdf0e10cSrcweir                                italic::type eIt,
2473*cdf0e10cSrcweir                                weight::type eWg,
2474*cdf0e10cSrcweir                                pitch::type ePt,
2475*cdf0e10cSrcweir                                rtl_TextEncoding enc ) :
2476*cdf0e10cSrcweir             aFamily( rFam ),
2477*cdf0e10cSrcweir             eItalic( eIt ),
2478*cdf0e10cSrcweir             eWeight( eWg ),
2479*cdf0e10cSrcweir             ePitch( ePt ),
2480*cdf0e10cSrcweir             aEncoding( enc )
2481*cdf0e10cSrcweir         {}
2482*cdf0e10cSrcweir 
2483*cdf0e10cSrcweir         bool operator==( const BuiltinFontIdentifier& rRight ) const
2484*cdf0e10cSrcweir         {
2485*cdf0e10cSrcweir             return equalItalic( eItalic, rRight.eItalic ) &&
2486*cdf0e10cSrcweir                    equalWeight( eWeight, rRight.eWeight ) &&
2487*cdf0e10cSrcweir                    equalPitch( ePitch, rRight.ePitch ) &&
2488*cdf0e10cSrcweir                    equalEncoding( aEncoding, rRight.aEncoding ) &&
2489*cdf0e10cSrcweir                    aFamily.equalsIgnoreAsciiCase( rRight.aFamily );
2490*cdf0e10cSrcweir         }
2491*cdf0e10cSrcweir     };
2492*cdf0e10cSrcweir 
2493*cdf0e10cSrcweir     struct BuiltinFontIdentifierHash
2494*cdf0e10cSrcweir     {
2495*cdf0e10cSrcweir         size_t operator()( const BuiltinFontIdentifier& rFont ) const
2496*cdf0e10cSrcweir         {
2497*cdf0e10cSrcweir             return rFont.aFamily.hashCode() ^ rFont.eItalic ^ rFont.eWeight ^ rFont.ePitch ^ rFont.aEncoding;
2498*cdf0e10cSrcweir         }
2499*cdf0e10cSrcweir     };
2500*cdf0e10cSrcweir }
2501*cdf0e10cSrcweir 
2502*cdf0e10cSrcweir void PrintFontManager::getFontList( ::std::list< fontID >& rFontIDs, const PPDParser* pParser, bool bUseOverrideMetrics )
2503*cdf0e10cSrcweir {
2504*cdf0e10cSrcweir     rFontIDs.clear();
2505*cdf0e10cSrcweir     std::hash_map< fontID, PrintFont* >::const_iterator it;
2506*cdf0e10cSrcweir 
2507*cdf0e10cSrcweir     /*
2508*cdf0e10cSrcweir     * Note: there are two easy steps making this faster:
2509*cdf0e10cSrcweir     * first: insert the printer builtins first, then the not builtins,
2510*cdf0e10cSrcweir     * if they do not match.
2511*cdf0e10cSrcweir     * drawback: this would change the sequence of fonts; this could have
2512*cdf0e10cSrcweir     * subtle, unknown consequences in vcl font matching
2513*cdf0e10cSrcweir     * second: instead of comparing attributes to see whether a softfont
2514*cdf0e10cSrcweir     * is duplicate to a builtin one could simply compare the PSName (which is
2515*cdf0e10cSrcweir     * supposed to be unique), which at this point is just an int.
2516*cdf0e10cSrcweir     * drawback: this could change which fonts are listed; especially TrueType
2517*cdf0e10cSrcweir     * fonts often have a rather dubious PSName, so this could change the
2518*cdf0e10cSrcweir     * font list not so subtle.
2519*cdf0e10cSrcweir     * Until getFontList for a printer becomes a performance issue (which is
2520*cdf0e10cSrcweir     * currently not the case), best stay with the current algorithm.
2521*cdf0e10cSrcweir     */
2522*cdf0e10cSrcweir 
2523*cdf0e10cSrcweir     // fill sets of printer supported fonts
2524*cdf0e10cSrcweir     if( pParser )
2525*cdf0e10cSrcweir     {
2526*cdf0e10cSrcweir         std::set<int> aBuiltinPSNames;
2527*cdf0e10cSrcweir         std::hash_set< BuiltinFontIdentifier,
2528*cdf0e10cSrcweir                        BuiltinFontIdentifierHash
2529*cdf0e10cSrcweir                        > aBuiltinFonts;
2530*cdf0e10cSrcweir 
2531*cdf0e10cSrcweir         std::map<int, fontID > aOverridePSNames;
2532*cdf0e10cSrcweir         if( bUseOverrideMetrics )
2533*cdf0e10cSrcweir         {
2534*cdf0e10cSrcweir             readOverrideMetrics();
2535*cdf0e10cSrcweir             for( std::vector<fontID>::const_iterator over = m_aOverrideFonts.begin();
2536*cdf0e10cSrcweir                  over != m_aOverrideFonts.end(); ++over )
2537*cdf0e10cSrcweir             {
2538*cdf0e10cSrcweir                 std::hash_map<fontID,PrintFont*>::const_iterator font_it = m_aFonts.find( *over );
2539*cdf0e10cSrcweir                 DBG_ASSERT( font_it != m_aFonts.end(), "override to nonexistant font" );
2540*cdf0e10cSrcweir                 if( font_it != m_aFonts.end() )
2541*cdf0e10cSrcweir                     aOverridePSNames[ font_it->second->m_nPSName ] = *over;
2542*cdf0e10cSrcweir             }
2543*cdf0e10cSrcweir         }
2544*cdf0e10cSrcweir 
2545*cdf0e10cSrcweir         int nFonts = pParser->getFonts();
2546*cdf0e10cSrcweir         for( int i = 0; i < nFonts; i++ )
2547*cdf0e10cSrcweir             aBuiltinPSNames.insert( m_pAtoms->getAtom( ATOM_PSNAME, pParser->getFont( i ) ) );
2548*cdf0e10cSrcweir         for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
2549*cdf0e10cSrcweir         {
2550*cdf0e10cSrcweir             PrintFont* pFont = it->second;
2551*cdf0e10cSrcweir             if( it->second->m_eType == fonttype::Builtin &&
2552*cdf0e10cSrcweir                 aBuiltinPSNames.find( pFont->m_nPSName ) != aBuiltinPSNames.end() )
2553*cdf0e10cSrcweir             {
2554*cdf0e10cSrcweir                 bool bInsert = true;
2555*cdf0e10cSrcweir                 if( bUseOverrideMetrics )
2556*cdf0e10cSrcweir                 {
2557*cdf0e10cSrcweir                     // in override case only use the override fonts, not their counterparts
2558*cdf0e10cSrcweir                     std::map<int,fontID>::const_iterator over = aOverridePSNames.find( pFont->m_nPSName );
2559*cdf0e10cSrcweir                     if( over != aOverridePSNames.end() && over->second != it->first )
2560*cdf0e10cSrcweir                         bInsert = false;
2561*cdf0e10cSrcweir                 }
2562*cdf0e10cSrcweir                 else
2563*cdf0e10cSrcweir                 {
2564*cdf0e10cSrcweir                     // do not insert override fonts in non override case
2565*cdf0e10cSrcweir                     if( std::find( m_aOverrideFonts.begin(), m_aOverrideFonts.end(), it->first ) != m_aOverrideFonts.end() )
2566*cdf0e10cSrcweir                         bInsert = false;
2567*cdf0e10cSrcweir                 }
2568*cdf0e10cSrcweir                 if( bInsert )
2569*cdf0e10cSrcweir                 {
2570*cdf0e10cSrcweir                     aBuiltinFonts.insert( BuiltinFontIdentifier(
2571*cdf0e10cSrcweir                         m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ),
2572*cdf0e10cSrcweir                         pFont->m_eItalic,
2573*cdf0e10cSrcweir                         pFont->m_eWeight,
2574*cdf0e10cSrcweir                         pFont->m_ePitch,
2575*cdf0e10cSrcweir                         pFont->m_aEncoding
2576*cdf0e10cSrcweir                         ) );
2577*cdf0e10cSrcweir                 }
2578*cdf0e10cSrcweir             }
2579*cdf0e10cSrcweir         }
2580*cdf0e10cSrcweir         for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
2581*cdf0e10cSrcweir         {
2582*cdf0e10cSrcweir             PrintFont* pFont = it->second;
2583*cdf0e10cSrcweir             if( it->second->m_eType == fonttype::Builtin )
2584*cdf0e10cSrcweir             {
2585*cdf0e10cSrcweir                 if( aBuiltinPSNames.find( pFont->m_nPSName ) != aBuiltinPSNames.end() )
2586*cdf0e10cSrcweir                 {
2587*cdf0e10cSrcweir                     bool bInsert = true;
2588*cdf0e10cSrcweir                     if( bUseOverrideMetrics )
2589*cdf0e10cSrcweir                     {
2590*cdf0e10cSrcweir                         // in override case only use the override fonts, not their counterparts
2591*cdf0e10cSrcweir                         std::map<int,fontID>::const_iterator over = aOverridePSNames.find( pFont->m_nPSName );
2592*cdf0e10cSrcweir                         if( over != aOverridePSNames.end() && over->second != it->first )
2593*cdf0e10cSrcweir                             bInsert = false;
2594*cdf0e10cSrcweir                     }
2595*cdf0e10cSrcweir                     else
2596*cdf0e10cSrcweir                     {
2597*cdf0e10cSrcweir                         // do not insert override fonts in non override case
2598*cdf0e10cSrcweir                         if( std::find( m_aOverrideFonts.begin(), m_aOverrideFonts.end(), it->first ) != m_aOverrideFonts.end() )
2599*cdf0e10cSrcweir                             bInsert = false;
2600*cdf0e10cSrcweir                     }
2601*cdf0e10cSrcweir                     if( bInsert )
2602*cdf0e10cSrcweir                         rFontIDs.push_back( it->first );
2603*cdf0e10cSrcweir                 }
2604*cdf0e10cSrcweir             }
2605*cdf0e10cSrcweir             else if( aBuiltinFonts.find( BuiltinFontIdentifier(
2606*cdf0e10cSrcweir                 m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ),
2607*cdf0e10cSrcweir                 pFont->m_eItalic,
2608*cdf0e10cSrcweir                 pFont->m_eWeight,
2609*cdf0e10cSrcweir                 pFont->m_ePitch,
2610*cdf0e10cSrcweir                 pFont->m_aEncoding
2611*cdf0e10cSrcweir                 ) ) == aBuiltinFonts.end() )
2612*cdf0e10cSrcweir             {
2613*cdf0e10cSrcweir                 rFontIDs.push_back( it->first );
2614*cdf0e10cSrcweir             }
2615*cdf0e10cSrcweir         }
2616*cdf0e10cSrcweir     }
2617*cdf0e10cSrcweir     else // no specific printer
2618*cdf0e10cSrcweir     {
2619*cdf0e10cSrcweir         for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
2620*cdf0e10cSrcweir             rFontIDs.push_back( it->first );
2621*cdf0e10cSrcweir     }
2622*cdf0e10cSrcweir }
2623*cdf0e10cSrcweir 
2624*cdf0e10cSrcweir // -------------------------------------------------------------------------
2625*cdf0e10cSrcweir 
2626*cdf0e10cSrcweir void PrintFontManager::fillPrintFontInfo( PrintFont* pFont, FastPrintFontInfo& rInfo ) const
2627*cdf0e10cSrcweir {
2628*cdf0e10cSrcweir     ::std::hash_map< int, family::type >::const_iterator style_it =
2629*cdf0e10cSrcweir           m_aFamilyTypes.find( pFont->m_nFamilyName );
2630*cdf0e10cSrcweir     rInfo.m_eType           = pFont->m_eType;
2631*cdf0e10cSrcweir     rInfo.m_aFamilyName     = m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName );
2632*cdf0e10cSrcweir     rInfo.m_aStyleName      = pFont->m_aStyleName;
2633*cdf0e10cSrcweir     rInfo.m_eFamilyStyle    = style_it != m_aFamilyTypes.end() ? style_it->second : family::Unknown;
2634*cdf0e10cSrcweir     rInfo.m_eItalic         = pFont->m_eItalic;
2635*cdf0e10cSrcweir     rInfo.m_eWidth          = pFont->m_eWidth;
2636*cdf0e10cSrcweir     rInfo.m_eWeight         = pFont->m_eWeight;
2637*cdf0e10cSrcweir     rInfo.m_ePitch          = pFont->m_ePitch;
2638*cdf0e10cSrcweir     rInfo.m_aEncoding       = pFont->m_aEncoding;
2639*cdf0e10cSrcweir 
2640*cdf0e10cSrcweir     rInfo.m_bEmbeddable  = (pFont->m_eType == fonttype::Type1);
2641*cdf0e10cSrcweir     rInfo.m_bSubsettable = (pFont->m_eType == fonttype::TrueType); // TODO: rename to SfntType
2642*cdf0e10cSrcweir 
2643*cdf0e10cSrcweir     rInfo.m_aAliases.clear();
2644*cdf0e10cSrcweir     for( ::std::list< int >::iterator it = pFont->m_aAliases.begin(); it != pFont->m_aAliases.end(); ++it )
2645*cdf0e10cSrcweir         rInfo.m_aAliases.push_back( m_pAtoms->getString( ATOM_FAMILYNAME, *it ) );
2646*cdf0e10cSrcweir }
2647*cdf0e10cSrcweir 
2648*cdf0e10cSrcweir // -------------------------------------------------------------------------
2649*cdf0e10cSrcweir 
2650*cdf0e10cSrcweir void PrintFontManager::fillPrintFontInfo( PrintFont* pFont, PrintFontInfo& rInfo ) const
2651*cdf0e10cSrcweir {
2652*cdf0e10cSrcweir     if( ( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 ) ||
2653*cdf0e10cSrcweir         ! pFont->m_pMetrics || pFont->m_pMetrics->isEmpty()
2654*cdf0e10cSrcweir         )
2655*cdf0e10cSrcweir     {
2656*cdf0e10cSrcweir         // might be a truetype font not analyzed or type1 without metrics read
2657*cdf0e10cSrcweir         if( pFont->m_eType == fonttype::Type1 )
2658*cdf0e10cSrcweir             pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, false );
2659*cdf0e10cSrcweir         else if( pFont->m_eType == fonttype::TrueType )
2660*cdf0e10cSrcweir             analyzeTrueTypeFile( pFont );
2661*cdf0e10cSrcweir     }
2662*cdf0e10cSrcweir 
2663*cdf0e10cSrcweir     fillPrintFontInfo( pFont, static_cast< FastPrintFontInfo& >( rInfo ) );
2664*cdf0e10cSrcweir 
2665*cdf0e10cSrcweir     rInfo.m_nAscend         = pFont->m_nAscend;
2666*cdf0e10cSrcweir     rInfo.m_nDescend        = pFont->m_nDescend;
2667*cdf0e10cSrcweir     rInfo.m_nLeading        = pFont->m_nLeading;
2668*cdf0e10cSrcweir     rInfo.m_nWidth          = pFont->m_aGlobalMetricX.width < pFont->m_aGlobalMetricY.width ? pFont->m_aGlobalMetricY.width : pFont->m_aGlobalMetricX.width;
2669*cdf0e10cSrcweir }
2670*cdf0e10cSrcweir 
2671*cdf0e10cSrcweir // -------------------------------------------------------------------------
2672*cdf0e10cSrcweir 
2673*cdf0e10cSrcweir void PrintFontManager::getFontListWithInfo( ::std::list< PrintFontInfo >& rFonts, const PPDParser* pParser, bool bUseOverrideMetrics )
2674*cdf0e10cSrcweir {
2675*cdf0e10cSrcweir     rFonts.clear();
2676*cdf0e10cSrcweir     ::std::list< fontID > aFontList;
2677*cdf0e10cSrcweir     getFontList( aFontList, pParser, bUseOverrideMetrics );
2678*cdf0e10cSrcweir 
2679*cdf0e10cSrcweir     ::std::list< fontID >::iterator it;
2680*cdf0e10cSrcweir     for( it = aFontList.begin(); it != aFontList.end(); ++it )
2681*cdf0e10cSrcweir     {
2682*cdf0e10cSrcweir         PrintFontInfo aInfo;
2683*cdf0e10cSrcweir         aInfo.m_nID = *it;
2684*cdf0e10cSrcweir         fillPrintFontInfo( getFont( *it ), aInfo );
2685*cdf0e10cSrcweir         rFonts.push_back( aInfo );
2686*cdf0e10cSrcweir     }
2687*cdf0e10cSrcweir }
2688*cdf0e10cSrcweir 
2689*cdf0e10cSrcweir // -------------------------------------------------------------------------
2690*cdf0e10cSrcweir 
2691*cdf0e10cSrcweir void PrintFontManager::getFontListWithFastInfo( ::std::list< FastPrintFontInfo >& rFonts, const PPDParser* pParser, bool bUseOverrideMetrics )
2692*cdf0e10cSrcweir {
2693*cdf0e10cSrcweir     rFonts.clear();
2694*cdf0e10cSrcweir     ::std::list< fontID > aFontList;
2695*cdf0e10cSrcweir     getFontList( aFontList, pParser, bUseOverrideMetrics );
2696*cdf0e10cSrcweir 
2697*cdf0e10cSrcweir     ::std::list< fontID >::iterator it;
2698*cdf0e10cSrcweir     for( it = aFontList.begin(); it != aFontList.end(); ++it )
2699*cdf0e10cSrcweir     {
2700*cdf0e10cSrcweir         FastPrintFontInfo aInfo;
2701*cdf0e10cSrcweir         aInfo.m_nID = *it;
2702*cdf0e10cSrcweir         fillPrintFontInfo( getFont( *it ), aInfo );
2703*cdf0e10cSrcweir         rFonts.push_back( aInfo );
2704*cdf0e10cSrcweir     }
2705*cdf0e10cSrcweir }
2706*cdf0e10cSrcweir 
2707*cdf0e10cSrcweir // -------------------------------------------------------------------------
2708*cdf0e10cSrcweir 
2709*cdf0e10cSrcweir bool PrintFontManager::getFontInfo( fontID nFontID, PrintFontInfo& rInfo ) const
2710*cdf0e10cSrcweir {
2711*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
2712*cdf0e10cSrcweir     if( pFont )
2713*cdf0e10cSrcweir     {
2714*cdf0e10cSrcweir         rInfo.m_nID = nFontID;
2715*cdf0e10cSrcweir         fillPrintFontInfo( pFont, rInfo );
2716*cdf0e10cSrcweir     }
2717*cdf0e10cSrcweir     return pFont ? true : false;
2718*cdf0e10cSrcweir }
2719*cdf0e10cSrcweir 
2720*cdf0e10cSrcweir // -------------------------------------------------------------------------
2721*cdf0e10cSrcweir 
2722*cdf0e10cSrcweir bool PrintFontManager::getFontFastInfo( fontID nFontID, FastPrintFontInfo& rInfo ) const
2723*cdf0e10cSrcweir {
2724*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
2725*cdf0e10cSrcweir     if( pFont )
2726*cdf0e10cSrcweir     {
2727*cdf0e10cSrcweir         rInfo.m_nID = nFontID;
2728*cdf0e10cSrcweir         fillPrintFontInfo( pFont, rInfo );
2729*cdf0e10cSrcweir     }
2730*cdf0e10cSrcweir     return pFont ? true : false;
2731*cdf0e10cSrcweir }
2732*cdf0e10cSrcweir 
2733*cdf0e10cSrcweir // -------------------------------------------------------------------------
2734*cdf0e10cSrcweir 
2735*cdf0e10cSrcweir bool PrintFontManager::getFontBoundingBox( fontID nFontID, int& xMin, int& yMin, int& xMax, int& yMax )
2736*cdf0e10cSrcweir {
2737*cdf0e10cSrcweir     bool bSuccess = false;
2738*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
2739*cdf0e10cSrcweir     if( pFont )
2740*cdf0e10cSrcweir     {
2741*cdf0e10cSrcweir         if( pFont->m_nXMin == 0 && pFont->m_nYMin == 0 && pFont->m_nXMax == 0 && pFont->m_nYMax == 0 )
2742*cdf0e10cSrcweir         {
2743*cdf0e10cSrcweir             // might be a truetype font not analyzed or type1 without metrics read
2744*cdf0e10cSrcweir             if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
2745*cdf0e10cSrcweir                 pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true );
2746*cdf0e10cSrcweir             else if( pFont->m_eType == fonttype::TrueType )
2747*cdf0e10cSrcweir                 analyzeTrueTypeFile( pFont );
2748*cdf0e10cSrcweir         }
2749*cdf0e10cSrcweir         bSuccess = true;
2750*cdf0e10cSrcweir         xMin = pFont->m_nXMin;
2751*cdf0e10cSrcweir         yMin = pFont->m_nYMin;
2752*cdf0e10cSrcweir         xMax = pFont->m_nXMax;
2753*cdf0e10cSrcweir         yMax = pFont->m_nYMax;
2754*cdf0e10cSrcweir     }
2755*cdf0e10cSrcweir     return bSuccess;
2756*cdf0e10cSrcweir }
2757*cdf0e10cSrcweir 
2758*cdf0e10cSrcweir // -------------------------------------------------------------------------
2759*cdf0e10cSrcweir 
2760*cdf0e10cSrcweir int PrintFontManager::getFontFaceNumber( fontID nFontID ) const
2761*cdf0e10cSrcweir {
2762*cdf0e10cSrcweir     int nRet = -1;
2763*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
2764*cdf0e10cSrcweir     if( pFont && pFont->m_eType == fonttype::TrueType )
2765*cdf0e10cSrcweir         nRet = static_cast< TrueTypeFontFile* >(pFont)->m_nCollectionEntry;
2766*cdf0e10cSrcweir     return nRet;
2767*cdf0e10cSrcweir }
2768*cdf0e10cSrcweir 
2769*cdf0e10cSrcweir // -------------------------------------------------------------------------
2770*cdf0e10cSrcweir 
2771*cdf0e10cSrcweir 
2772*cdf0e10cSrcweir family::type PrintFontManager::matchFamilyName( const ::rtl::OUString& rFamily ) const
2773*cdf0e10cSrcweir {
2774*cdf0e10cSrcweir     typedef struct {
2775*cdf0e10cSrcweir         const char*  mpName;
2776*cdf0e10cSrcweir         sal_uInt16   mnLength;
2777*cdf0e10cSrcweir         family::type meType;
2778*cdf0e10cSrcweir     } family_t;
2779*cdf0e10cSrcweir 
2780*cdf0e10cSrcweir #define InitializeClass( p, a ) p, sizeof(p) - 1, a
2781*cdf0e10cSrcweir     const family_t pFamilyMatch[] =  {
2782*cdf0e10cSrcweir         { InitializeClass( "arial",                  family::Swiss )  },
2783*cdf0e10cSrcweir         { InitializeClass( "arioso",                 family::Script ) },
2784*cdf0e10cSrcweir         { InitializeClass( "avant garde",            family::Swiss )  },
2785*cdf0e10cSrcweir         { InitializeClass( "avantgarde",             family::Swiss )  },
2786*cdf0e10cSrcweir         { InitializeClass( "bembo",                  family::Roman )  },
2787*cdf0e10cSrcweir         { InitializeClass( "bookman",                family::Roman )  },
2788*cdf0e10cSrcweir         { InitializeClass( "conga",                  family::Roman )  },
2789*cdf0e10cSrcweir         { InitializeClass( "courier",                family::Modern ) },
2790*cdf0e10cSrcweir         { InitializeClass( "curl",                   family::Script ) },
2791*cdf0e10cSrcweir         { InitializeClass( "fixed",                  family::Modern ) },
2792*cdf0e10cSrcweir         { InitializeClass( "gill",                   family::Swiss )  },
2793*cdf0e10cSrcweir         { InitializeClass( "helmet",                 family::Modern ) },
2794*cdf0e10cSrcweir         { InitializeClass( "helvetica",              family::Swiss )  },
2795*cdf0e10cSrcweir         { InitializeClass( "international",          family::Modern ) },
2796*cdf0e10cSrcweir         { InitializeClass( "lucida",                 family::Swiss )  },
2797*cdf0e10cSrcweir         { InitializeClass( "new century schoolbook", family::Roman )  },
2798*cdf0e10cSrcweir         { InitializeClass( "palatino",               family::Roman )  },
2799*cdf0e10cSrcweir         { InitializeClass( "roman",                  family::Roman )  },
2800*cdf0e10cSrcweir         { InitializeClass( "sans serif",             family::Swiss )  },
2801*cdf0e10cSrcweir         { InitializeClass( "sansserif",              family::Swiss )  },
2802*cdf0e10cSrcweir         { InitializeClass( "serf",                   family::Roman )  },
2803*cdf0e10cSrcweir         { InitializeClass( "serif",                  family::Roman )  },
2804*cdf0e10cSrcweir         { InitializeClass( "times",                  family::Roman )  },
2805*cdf0e10cSrcweir         { InitializeClass( "utopia",                 family::Roman )  },
2806*cdf0e10cSrcweir         { InitializeClass( "zapf chancery",          family::Script ) },
2807*cdf0e10cSrcweir         { InitializeClass( "zapfchancery",           family::Script ) }
2808*cdf0e10cSrcweir     };
2809*cdf0e10cSrcweir 
2810*cdf0e10cSrcweir     rtl::OString aFamily = rtl::OUStringToOString( rFamily, RTL_TEXTENCODING_ASCII_US );
2811*cdf0e10cSrcweir     sal_uInt32 nLower = 0;
2812*cdf0e10cSrcweir     sal_uInt32 nUpper = sizeof(pFamilyMatch) / sizeof(pFamilyMatch[0]);
2813*cdf0e10cSrcweir 
2814*cdf0e10cSrcweir     while( nLower < nUpper )
2815*cdf0e10cSrcweir     {
2816*cdf0e10cSrcweir         sal_uInt32 nCurrent = (nLower + nUpper) / 2;
2817*cdf0e10cSrcweir         const family_t* pHaystack = pFamilyMatch + nCurrent;
2818*cdf0e10cSrcweir         sal_Int32  nComparison =
2819*cdf0e10cSrcweir             rtl_str_compareIgnoreAsciiCase_WithLength
2820*cdf0e10cSrcweir             (
2821*cdf0e10cSrcweir              aFamily.getStr(), aFamily.getLength(),
2822*cdf0e10cSrcweir              pHaystack->mpName, pHaystack->mnLength
2823*cdf0e10cSrcweir              );
2824*cdf0e10cSrcweir 
2825*cdf0e10cSrcweir         if( nComparison < 0 )
2826*cdf0e10cSrcweir             nUpper = nCurrent;
2827*cdf0e10cSrcweir         else
2828*cdf0e10cSrcweir             if( nComparison > 0 )
2829*cdf0e10cSrcweir                 nLower = nCurrent + 1;
2830*cdf0e10cSrcweir             else
2831*cdf0e10cSrcweir                 return pHaystack->meType;
2832*cdf0e10cSrcweir     }
2833*cdf0e10cSrcweir 
2834*cdf0e10cSrcweir     return family::Unknown;
2835*cdf0e10cSrcweir }
2836*cdf0e10cSrcweir 
2837*cdf0e10cSrcweir // -------------------------------------------------------------------------
2838*cdf0e10cSrcweir 
2839*cdf0e10cSrcweir family::type PrintFontManager::getFontFamilyType( fontID nFontID ) const
2840*cdf0e10cSrcweir {
2841*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
2842*cdf0e10cSrcweir     if( !pFont )
2843*cdf0e10cSrcweir         return family::Unknown;
2844*cdf0e10cSrcweir 
2845*cdf0e10cSrcweir     ::std::hash_map< int, family::type >::const_iterator it =
2846*cdf0e10cSrcweir           m_aFamilyTypes.find( pFont->m_nFamilyName );
2847*cdf0e10cSrcweir     return (it != m_aFamilyTypes.end()) ? it->second : family::Unknown;
2848*cdf0e10cSrcweir }
2849*cdf0e10cSrcweir 
2850*cdf0e10cSrcweir 
2851*cdf0e10cSrcweir // -------------------------------------------------------------------------
2852*cdf0e10cSrcweir 
2853*cdf0e10cSrcweir const ::rtl::OUString& PrintFontManager::getFontFamily( fontID nFontID ) const
2854*cdf0e10cSrcweir {
2855*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
2856*cdf0e10cSrcweir     return m_pAtoms->getString( ATOM_FAMILYNAME, pFont ? pFont->m_nFamilyName : INVALID_ATOM );
2857*cdf0e10cSrcweir }
2858*cdf0e10cSrcweir 
2859*cdf0e10cSrcweir // -------------------------------------------------------------------------
2860*cdf0e10cSrcweir 
2861*cdf0e10cSrcweir OString PrintFontManager::getAfmFile( PrintFont* pFont ) const
2862*cdf0e10cSrcweir {
2863*cdf0e10cSrcweir     OString aMetricPath;
2864*cdf0e10cSrcweir     if( pFont )
2865*cdf0e10cSrcweir     {
2866*cdf0e10cSrcweir         switch( pFont->m_eType )
2867*cdf0e10cSrcweir         {
2868*cdf0e10cSrcweir             case fonttype::Type1:
2869*cdf0e10cSrcweir             {
2870*cdf0e10cSrcweir                 Type1FontFile* pPSFont = static_cast< Type1FontFile* >(pFont);
2871*cdf0e10cSrcweir                 aMetricPath = getDirectory( pPSFont->m_nDirectory );
2872*cdf0e10cSrcweir                 aMetricPath += "/";
2873*cdf0e10cSrcweir                 aMetricPath += pPSFont->m_aMetricFile;
2874*cdf0e10cSrcweir             }
2875*cdf0e10cSrcweir             break;
2876*cdf0e10cSrcweir             case fonttype::Builtin:
2877*cdf0e10cSrcweir             {
2878*cdf0e10cSrcweir                 BuiltinFont* pBuiltinFont = static_cast< BuiltinFont* >(pFont);
2879*cdf0e10cSrcweir                 aMetricPath = getDirectory( pBuiltinFont->m_nDirectory );
2880*cdf0e10cSrcweir                 aMetricPath += "/";
2881*cdf0e10cSrcweir                 aMetricPath += pBuiltinFont->m_aMetricFile;
2882*cdf0e10cSrcweir             }
2883*cdf0e10cSrcweir             break;
2884*cdf0e10cSrcweir             default: break;
2885*cdf0e10cSrcweir         }
2886*cdf0e10cSrcweir     }
2887*cdf0e10cSrcweir     return aMetricPath;
2888*cdf0e10cSrcweir }
2889*cdf0e10cSrcweir 
2890*cdf0e10cSrcweir // -------------------------------------------------------------------------
2891*cdf0e10cSrcweir 
2892*cdf0e10cSrcweir OString PrintFontManager::getFontFile( PrintFont* pFont ) const
2893*cdf0e10cSrcweir {
2894*cdf0e10cSrcweir     OString aPath;
2895*cdf0e10cSrcweir 
2896*cdf0e10cSrcweir     if( pFont && pFont->m_eType == fonttype::Type1 )
2897*cdf0e10cSrcweir     {
2898*cdf0e10cSrcweir         Type1FontFile* pPSFont = static_cast< Type1FontFile* >(pFont);
2899*cdf0e10cSrcweir         ::std::hash_map< int, OString >::const_iterator it = m_aAtomToDir.find( pPSFont->m_nDirectory );
2900*cdf0e10cSrcweir         aPath = it->second;
2901*cdf0e10cSrcweir         aPath += "/";
2902*cdf0e10cSrcweir         aPath += pPSFont->m_aFontFile;
2903*cdf0e10cSrcweir     }
2904*cdf0e10cSrcweir     else if( pFont && pFont->m_eType == fonttype::TrueType )
2905*cdf0e10cSrcweir     {
2906*cdf0e10cSrcweir         TrueTypeFontFile* pTTFont = static_cast< TrueTypeFontFile* >(pFont);
2907*cdf0e10cSrcweir         ::std::hash_map< int, OString >::const_iterator it = m_aAtomToDir.find( pTTFont->m_nDirectory );
2908*cdf0e10cSrcweir         aPath = it->second;
2909*cdf0e10cSrcweir         aPath += "/";
2910*cdf0e10cSrcweir         aPath += pTTFont->m_aFontFile;
2911*cdf0e10cSrcweir     }
2912*cdf0e10cSrcweir     return aPath;
2913*cdf0e10cSrcweir }
2914*cdf0e10cSrcweir 
2915*cdf0e10cSrcweir // -------------------------------------------------------------------------
2916*cdf0e10cSrcweir 
2917*cdf0e10cSrcweir const ::rtl::OUString& PrintFontManager::getPSName( fontID nFontID ) const
2918*cdf0e10cSrcweir {
2919*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
2920*cdf0e10cSrcweir     if( pFont && pFont->m_nPSName == 0 )
2921*cdf0e10cSrcweir     {
2922*cdf0e10cSrcweir         if( pFont->m_eType == fonttype::TrueType )
2923*cdf0e10cSrcweir             analyzeTrueTypeFile( pFont );
2924*cdf0e10cSrcweir     }
2925*cdf0e10cSrcweir 
2926*cdf0e10cSrcweir     return m_pAtoms->getString( ATOM_PSNAME, pFont ? pFont->m_nPSName : INVALID_ATOM );
2927*cdf0e10cSrcweir }
2928*cdf0e10cSrcweir 
2929*cdf0e10cSrcweir // -------------------------------------------------------------------------
2930*cdf0e10cSrcweir 
2931*cdf0e10cSrcweir const CharacterMetric& PrintFontManager::getGlobalFontMetric( fontID nFontID, bool bHorizontal ) const
2932*cdf0e10cSrcweir {
2933*cdf0e10cSrcweir     static CharacterMetric aMetric;
2934*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
2935*cdf0e10cSrcweir     return pFont ? ( bHorizontal ? pFont->m_aGlobalMetricX : pFont->m_aGlobalMetricY ) : aMetric;
2936*cdf0e10cSrcweir }
2937*cdf0e10cSrcweir 
2938*cdf0e10cSrcweir // -------------------------------------------------------------------------
2939*cdf0e10cSrcweir 
2940*cdf0e10cSrcweir int PrintFontManager::getFontAscend( fontID nFontID ) const
2941*cdf0e10cSrcweir {
2942*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
2943*cdf0e10cSrcweir     if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
2944*cdf0e10cSrcweir     {
2945*cdf0e10cSrcweir         // might be a truetype font not yet analyzed
2946*cdf0e10cSrcweir         if( pFont->m_eType == fonttype::TrueType )
2947*cdf0e10cSrcweir             analyzeTrueTypeFile( pFont );
2948*cdf0e10cSrcweir         else if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
2949*cdf0e10cSrcweir             pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true );
2950*cdf0e10cSrcweir     }
2951*cdf0e10cSrcweir     return pFont->m_nAscend;
2952*cdf0e10cSrcweir }
2953*cdf0e10cSrcweir 
2954*cdf0e10cSrcweir // -------------------------------------------------------------------------
2955*cdf0e10cSrcweir 
2956*cdf0e10cSrcweir int PrintFontManager::getFontDescend( fontID nFontID ) const
2957*cdf0e10cSrcweir {
2958*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
2959*cdf0e10cSrcweir     if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
2960*cdf0e10cSrcweir     {
2961*cdf0e10cSrcweir         // might be a truetype font not yet analyzed
2962*cdf0e10cSrcweir         if( pFont->m_eType == fonttype::TrueType )
2963*cdf0e10cSrcweir             analyzeTrueTypeFile( pFont );
2964*cdf0e10cSrcweir         else if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
2965*cdf0e10cSrcweir             pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, true );
2966*cdf0e10cSrcweir     }
2967*cdf0e10cSrcweir     return pFont->m_nDescend;
2968*cdf0e10cSrcweir }
2969*cdf0e10cSrcweir 
2970*cdf0e10cSrcweir // -------------------------------------------------------------------------
2971*cdf0e10cSrcweir 
2972*cdf0e10cSrcweir int PrintFontManager::getFontLeading( fontID nFontID ) const
2973*cdf0e10cSrcweir {
2974*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
2975*cdf0e10cSrcweir     if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
2976*cdf0e10cSrcweir     {
2977*cdf0e10cSrcweir         // might be a truetype font not yet analyzed
2978*cdf0e10cSrcweir         if( pFont->m_eType == fonttype::TrueType )
2979*cdf0e10cSrcweir             analyzeTrueTypeFile( pFont );
2980*cdf0e10cSrcweir     }
2981*cdf0e10cSrcweir     return pFont->m_nLeading;
2982*cdf0e10cSrcweir }
2983*cdf0e10cSrcweir 
2984*cdf0e10cSrcweir // -------------------------------------------------------------------------
2985*cdf0e10cSrcweir 
2986*cdf0e10cSrcweir bool PrintFontManager::hasVerticalSubstitutions( fontID nFontID ) const
2987*cdf0e10cSrcweir {
2988*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
2989*cdf0e10cSrcweir     if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
2990*cdf0e10cSrcweir     {
2991*cdf0e10cSrcweir         // might be a truetype font not yet analyzed
2992*cdf0e10cSrcweir         if( pFont->m_eType == fonttype::TrueType )
2993*cdf0e10cSrcweir             analyzeTrueTypeFile( pFont );
2994*cdf0e10cSrcweir     }
2995*cdf0e10cSrcweir     return pFont->m_bHaveVerticalSubstitutedGlyphs;
2996*cdf0e10cSrcweir }
2997*cdf0e10cSrcweir 
2998*cdf0e10cSrcweir // -------------------------------------------------------------------------
2999*cdf0e10cSrcweir 
3000*cdf0e10cSrcweir void PrintFontManager::hasVerticalSubstitutions( fontID nFontID,
3001*cdf0e10cSrcweir     const sal_Unicode* pCharacters, int nCharacters, bool* pHasSubst ) const
3002*cdf0e10cSrcweir {
3003*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
3004*cdf0e10cSrcweir     if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
3005*cdf0e10cSrcweir     {
3006*cdf0e10cSrcweir         // might be a truetype font not yet analyzed
3007*cdf0e10cSrcweir         if( pFont->m_eType == fonttype::TrueType )
3008*cdf0e10cSrcweir             analyzeTrueTypeFile( pFont );
3009*cdf0e10cSrcweir     }
3010*cdf0e10cSrcweir 
3011*cdf0e10cSrcweir     if( ! pFont->m_bHaveVerticalSubstitutedGlyphs )
3012*cdf0e10cSrcweir         memset( pHasSubst, 0, sizeof(bool)*nCharacters );
3013*cdf0e10cSrcweir     else
3014*cdf0e10cSrcweir     {
3015*cdf0e10cSrcweir         for( int i = 0; i < nCharacters; i++ )
3016*cdf0e10cSrcweir         {
3017*cdf0e10cSrcweir             sal_Unicode code = pCharacters[i];
3018*cdf0e10cSrcweir             if( ! pFont->m_pMetrics ||
3019*cdf0e10cSrcweir                 ! ( pFont->m_pMetrics->m_aPages[ code >> 11 ] & ( 1 << ( ( code >> 8 ) & 7 ) ) ) )
3020*cdf0e10cSrcweir                 pFont->queryMetricPage( code >> 8, m_pAtoms );
3021*cdf0e10cSrcweir             ::std::hash_map< sal_Unicode, bool >::const_iterator it = pFont->m_pMetrics->m_bVerticalSubstitutions.find( code );
3022*cdf0e10cSrcweir             pHasSubst[i] = it != pFont->m_pMetrics->m_bVerticalSubstitutions.end();
3023*cdf0e10cSrcweir         }
3024*cdf0e10cSrcweir     }
3025*cdf0e10cSrcweir }
3026*cdf0e10cSrcweir 
3027*cdf0e10cSrcweir // -------------------------------------------------------------------------
3028*cdf0e10cSrcweir 
3029*cdf0e10cSrcweir OUString PrintFontManager::getFontXLFD( fontID nFontID ) const
3030*cdf0e10cSrcweir {
3031*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
3032*cdf0e10cSrcweir     OUString aRet;
3033*cdf0e10cSrcweir     if( pFont )
3034*cdf0e10cSrcweir     {
3035*cdf0e10cSrcweir         ByteString aXLFD( getXLFD( pFont ) );
3036*cdf0e10cSrcweir         rtl_TextEncoding aEncoding = aXLFD.GetToken( 6, '-' ).Search( "utf8" ) != STRING_NOTFOUND ? RTL_TEXTENCODING_UTF8 : RTL_TEXTENCODING_ISO_8859_1;
3037*cdf0e10cSrcweir         aRet = OStringToOUString( aXLFD, aEncoding );
3038*cdf0e10cSrcweir     }
3039*cdf0e10cSrcweir     return aRet;
3040*cdf0e10cSrcweir }
3041*cdf0e10cSrcweir 
3042*cdf0e10cSrcweir // -------------------------------------------------------------------------
3043*cdf0e10cSrcweir 
3044*cdf0e10cSrcweir const ::std::list< KernPair >& PrintFontManager::getKernPairs( fontID nFontID, bool bVertical ) const
3045*cdf0e10cSrcweir {
3046*cdf0e10cSrcweir     static ::std::list< KernPair > aEmpty;
3047*cdf0e10cSrcweir 
3048*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
3049*cdf0e10cSrcweir     if( ! pFont )
3050*cdf0e10cSrcweir         return aEmpty;
3051*cdf0e10cSrcweir 
3052*cdf0e10cSrcweir     if( ! pFont->m_pMetrics || ! pFont->m_pMetrics->m_bKernPairsQueried )
3053*cdf0e10cSrcweir         pFont->queryMetricPage( 0, m_pAtoms );
3054*cdf0e10cSrcweir     if( ! pFont->m_pMetrics || ! pFont->m_pMetrics->m_bKernPairsQueried )
3055*cdf0e10cSrcweir         return aEmpty;
3056*cdf0e10cSrcweir     return bVertical ? pFont->m_pMetrics->m_aYKernPairs : pFont->m_pMetrics->m_aXKernPairs;
3057*cdf0e10cSrcweir }
3058*cdf0e10cSrcweir 
3059*cdf0e10cSrcweir // -------------------------------------------------------------------------
3060*cdf0e10cSrcweir 
3061*cdf0e10cSrcweir bool PrintFontManager::isFontDownloadingAllowed( fontID nFont ) const
3062*cdf0e10cSrcweir {
3063*cdf0e10cSrcweir     static const char* pEnable = getenv( "PSPRINT_ENABLE_TTF_COPYRIGHTAWARENESS" );
3064*cdf0e10cSrcweir     bool bRet = true;
3065*cdf0e10cSrcweir 
3066*cdf0e10cSrcweir     if( pEnable && *pEnable )
3067*cdf0e10cSrcweir     {
3068*cdf0e10cSrcweir         PrintFont* pFont = getFont( nFont );
3069*cdf0e10cSrcweir         if( pFont && pFont->m_eType == fonttype::TrueType )
3070*cdf0e10cSrcweir         {
3071*cdf0e10cSrcweir             TrueTypeFontFile* pTTFontFile = static_cast<TrueTypeFontFile*>(pFont);
3072*cdf0e10cSrcweir             if( pTTFontFile->m_nTypeFlags & TYPEFLAG_INVALID )
3073*cdf0e10cSrcweir             {
3074*cdf0e10cSrcweir                 TrueTypeFont* pTTFont = NULL;
3075*cdf0e10cSrcweir                 ByteString aFile = getFontFile( pFont );
3076*cdf0e10cSrcweir                 if( OpenTTFontFile( aFile.GetBuffer(), pTTFontFile->m_nCollectionEntry < 0 ? 0 : pTTFontFile->m_nCollectionEntry, &pTTFont ) == SF_OK )
3077*cdf0e10cSrcweir                 {
3078*cdf0e10cSrcweir                     // get type flags
3079*cdf0e10cSrcweir                     TTGlobalFontInfo aInfo;
3080*cdf0e10cSrcweir                     GetTTGlobalFontInfo( pTTFont, & aInfo );
3081*cdf0e10cSrcweir                     pTTFontFile->m_nTypeFlags = (unsigned int)aInfo.typeFlags;
3082*cdf0e10cSrcweir                     CloseTTFont( pTTFont );
3083*cdf0e10cSrcweir                 }
3084*cdf0e10cSrcweir             }
3085*cdf0e10cSrcweir 
3086*cdf0e10cSrcweir             unsigned int nCopyrightFlags = pTTFontFile->m_nTypeFlags & TYPEFLAG_COPYRIGHT_MASK;
3087*cdf0e10cSrcweir 
3088*cdf0e10cSrcweir             // font embedding is allowed if either
3089*cdf0e10cSrcweir             //   no restriction at all (bit 1 clear)
3090*cdf0e10cSrcweir             //   printing allowed (bit 1 set, bit 2 set )
3091*cdf0e10cSrcweir             bRet = ! ( nCopyrightFlags & 0x02 ) || ( nCopyrightFlags & 0x04 );
3092*cdf0e10cSrcweir         }
3093*cdf0e10cSrcweir     }
3094*cdf0e10cSrcweir     return bRet;
3095*cdf0e10cSrcweir }
3096*cdf0e10cSrcweir 
3097*cdf0e10cSrcweir // -------------------------------------------------------------------------
3098*cdf0e10cSrcweir 
3099*cdf0e10cSrcweir bool PrintFontManager::getMetrics( fontID nFontID, const sal_Unicode* pString, int nLen, CharacterMetric* pArray, bool bVertical ) const
3100*cdf0e10cSrcweir {
3101*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
3102*cdf0e10cSrcweir     if( ! pFont )
3103*cdf0e10cSrcweir         return false;
3104*cdf0e10cSrcweir 
3105*cdf0e10cSrcweir     if( ( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
3106*cdf0e10cSrcweir         || ! pFont->m_pMetrics || pFont->m_pMetrics->isEmpty()
3107*cdf0e10cSrcweir         )
3108*cdf0e10cSrcweir     {
3109*cdf0e10cSrcweir         // might be a font not yet analyzed
3110*cdf0e10cSrcweir         if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
3111*cdf0e10cSrcweir             pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, false );
3112*cdf0e10cSrcweir         else if( pFont->m_eType == fonttype::TrueType )
3113*cdf0e10cSrcweir             analyzeTrueTypeFile( pFont );
3114*cdf0e10cSrcweir     }
3115*cdf0e10cSrcweir 
3116*cdf0e10cSrcweir     for( int i = 0; i < nLen; i++ )
3117*cdf0e10cSrcweir     {
3118*cdf0e10cSrcweir         if( ! pFont->m_pMetrics ||
3119*cdf0e10cSrcweir             ! ( pFont->m_pMetrics->m_aPages[ pString[i] >> 11 ] & ( 1 << ( ( pString[i] >> 8 ) & 7 ) ) ) )
3120*cdf0e10cSrcweir             pFont->queryMetricPage( pString[i] >> 8, m_pAtoms );
3121*cdf0e10cSrcweir         pArray[i].width = pArray[i].height = -1;
3122*cdf0e10cSrcweir         if( pFont->m_pMetrics )
3123*cdf0e10cSrcweir         {
3124*cdf0e10cSrcweir             int effectiveCode = pString[i];
3125*cdf0e10cSrcweir             effectiveCode |= bVertical ? 1 << 16 : 0;
3126*cdf0e10cSrcweir             ::std::hash_map< int, CharacterMetric >::const_iterator it =
3127*cdf0e10cSrcweir                   pFont->m_pMetrics->m_aMetrics.find( effectiveCode );
3128*cdf0e10cSrcweir 	    // if no vertical metrics are available assume rotated horizontal metrics
3129*cdf0e10cSrcweir 	    if( bVertical && (it == pFont->m_pMetrics->m_aMetrics.end()) )
3130*cdf0e10cSrcweir                   it = pFont->m_pMetrics->m_aMetrics.find( pString[i] );
3131*cdf0e10cSrcweir 	    // the character metrics are in it->second
3132*cdf0e10cSrcweir             if( it != pFont->m_pMetrics->m_aMetrics.end() )
3133*cdf0e10cSrcweir                 pArray[ i ] = it->second;
3134*cdf0e10cSrcweir         }
3135*cdf0e10cSrcweir     }
3136*cdf0e10cSrcweir 
3137*cdf0e10cSrcweir     return true;
3138*cdf0e10cSrcweir }
3139*cdf0e10cSrcweir 
3140*cdf0e10cSrcweir // -------------------------------------------------------------------------
3141*cdf0e10cSrcweir 
3142*cdf0e10cSrcweir bool PrintFontManager::getMetrics( fontID nFontID, sal_Unicode minCharacter, sal_Unicode maxCharacter, CharacterMetric* pArray, bool bVertical ) const
3143*cdf0e10cSrcweir {
3144*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
3145*cdf0e10cSrcweir     if( ! pFont )
3146*cdf0e10cSrcweir         return false;
3147*cdf0e10cSrcweir 
3148*cdf0e10cSrcweir     if( ( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
3149*cdf0e10cSrcweir         || ! pFont->m_pMetrics || pFont->m_pMetrics->isEmpty()
3150*cdf0e10cSrcweir         )
3151*cdf0e10cSrcweir     {
3152*cdf0e10cSrcweir         // might be a font not yet analyzed
3153*cdf0e10cSrcweir         if( pFont->m_eType == fonttype::Type1 || pFont->m_eType == fonttype::Builtin )
3154*cdf0e10cSrcweir             pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, false, false );
3155*cdf0e10cSrcweir         else if( pFont->m_eType == fonttype::TrueType )
3156*cdf0e10cSrcweir             analyzeTrueTypeFile( pFont );
3157*cdf0e10cSrcweir     }
3158*cdf0e10cSrcweir 
3159*cdf0e10cSrcweir     sal_Unicode code = minCharacter;
3160*cdf0e10cSrcweir     do
3161*cdf0e10cSrcweir     {
3162*cdf0e10cSrcweir         if( ! pFont->m_pMetrics ||
3163*cdf0e10cSrcweir             ! ( pFont->m_pMetrics->m_aPages[ code >> 11 ] & ( 1 << ( ( code >> 8 ) & 7 ) ) ) )
3164*cdf0e10cSrcweir             pFont->queryMetricPage( code >> 8, m_pAtoms );
3165*cdf0e10cSrcweir         pArray[ code - minCharacter ].width     = -1;
3166*cdf0e10cSrcweir         pArray[ code - minCharacter ].height    = -1;
3167*cdf0e10cSrcweir         if( pFont->m_pMetrics )
3168*cdf0e10cSrcweir         {
3169*cdf0e10cSrcweir             int effectiveCode = code;
3170*cdf0e10cSrcweir             effectiveCode |= bVertical ? 1 << 16 : 0;
3171*cdf0e10cSrcweir             ::std::hash_map< int, CharacterMetric >::const_iterator it =
3172*cdf0e10cSrcweir                   pFont->m_pMetrics->m_aMetrics.find( effectiveCode );
3173*cdf0e10cSrcweir             // if no vertical metrics are available assume rotated horizontal metrics
3174*cdf0e10cSrcweir             if( bVertical && (it == pFont->m_pMetrics->m_aMetrics.end()) )
3175*cdf0e10cSrcweir                 it = pFont->m_pMetrics->m_aMetrics.find( code );
3176*cdf0e10cSrcweir             // the character metrics are in it->second
3177*cdf0e10cSrcweir             if( it != pFont->m_pMetrics->m_aMetrics.end() )
3178*cdf0e10cSrcweir                 pArray[ code - minCharacter ] = it->second;
3179*cdf0e10cSrcweir         }
3180*cdf0e10cSrcweir     } while( code++ != maxCharacter );
3181*cdf0e10cSrcweir 
3182*cdf0e10cSrcweir     return true;
3183*cdf0e10cSrcweir }
3184*cdf0e10cSrcweir 
3185*cdf0e10cSrcweir // -------------------------------------------------------------------------
3186*cdf0e10cSrcweir 
3187*cdf0e10cSrcweir static bool createWriteablePath( const ByteString& rPath )
3188*cdf0e10cSrcweir {
3189*cdf0e10cSrcweir     bool bSuccess = false;
3190*cdf0e10cSrcweir 
3191*cdf0e10cSrcweir     if( access( rPath.GetBuffer(), W_OK ) )
3192*cdf0e10cSrcweir     {
3193*cdf0e10cSrcweir         int nPos = rPath.SearchBackward( '/' );
3194*cdf0e10cSrcweir         if( nPos != STRING_NOTFOUND )
3195*cdf0e10cSrcweir             while( nPos > 0 && rPath.GetChar( nPos ) == '/' )
3196*cdf0e10cSrcweir                 nPos--;
3197*cdf0e10cSrcweir 
3198*cdf0e10cSrcweir         if( nPos != STRING_NOTFOUND && nPos != 0 && createWriteablePath( rPath.Copy( 0, nPos+1 ) ) )
3199*cdf0e10cSrcweir         {
3200*cdf0e10cSrcweir             bSuccess = mkdir( rPath.GetBuffer(), 0777 ) ? false : true;
3201*cdf0e10cSrcweir         }
3202*cdf0e10cSrcweir     }
3203*cdf0e10cSrcweir     else
3204*cdf0e10cSrcweir         bSuccess = true;
3205*cdf0e10cSrcweir 
3206*cdf0e10cSrcweir     return bSuccess;
3207*cdf0e10cSrcweir }
3208*cdf0e10cSrcweir 
3209*cdf0e10cSrcweir 
3210*cdf0e10cSrcweir // -------------------------------------------------------------------------
3211*cdf0e10cSrcweir 
3212*cdf0e10cSrcweir int PrintFontManager::importFonts( const ::std::list< OString >& rFiles, bool bLinkOnly, ImportFontCallback* pCallback )
3213*cdf0e10cSrcweir {
3214*cdf0e10cSrcweir     int nSuccess = 0;
3215*cdf0e10cSrcweir 
3216*cdf0e10cSrcweir     // find a directory with write access
3217*cdf0e10cSrcweir     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
3218*cdf0e10cSrcweir     bool bCanWrite = false;
3219*cdf0e10cSrcweir     int nDirID = 0;
3220*cdf0e10cSrcweir     INetURLObject aDir;
3221*cdf0e10cSrcweir     for( ::std::list< int >::const_iterator dir_it = m_aPrivateFontDirectories.begin();
3222*cdf0e10cSrcweir          ! bCanWrite && dir_it != m_aPrivateFontDirectories.end(); ++dir_it )
3223*cdf0e10cSrcweir     {
3224*cdf0e10cSrcweir         // check if we can create files in that directory
3225*cdf0e10cSrcweir         ByteString aDirPath = getDirectory( *dir_it );
3226*cdf0e10cSrcweir         if( createWriteablePath( aDirPath ) )
3227*cdf0e10cSrcweir         {
3228*cdf0e10cSrcweir             aDir = INetURLObject( OStringToOUString( aDirPath, aEncoding ), INET_PROT_FILE, INetURLObject::ENCODE_ALL );
3229*cdf0e10cSrcweir             nDirID = *dir_it;
3230*cdf0e10cSrcweir             bCanWrite = true;
3231*cdf0e10cSrcweir         }
3232*cdf0e10cSrcweir     }
3233*cdf0e10cSrcweir     if( bCanWrite )
3234*cdf0e10cSrcweir     {
3235*cdf0e10cSrcweir         for( ::std::list< OString >::const_iterator font_it = rFiles.begin();
3236*cdf0e10cSrcweir              font_it != rFiles.end(); ++font_it )
3237*cdf0e10cSrcweir         {
3238*cdf0e10cSrcweir             INetURLObject aFrom( OStringToOUString( *font_it, aEncoding ), INET_PROT_FILE, INetURLObject::ENCODE_ALL );
3239*cdf0e10cSrcweir             INetURLObject aTo( aDir );
3240*cdf0e10cSrcweir             aTo.Append( aFrom.GetName() );
3241*cdf0e10cSrcweir 
3242*cdf0e10cSrcweir             if( pCallback )
3243*cdf0e10cSrcweir                 pCallback->progress( aTo.PathToFileName() );
3244*cdf0e10cSrcweir 
3245*cdf0e10cSrcweir             if( pCallback && pCallback->isCanceled() )
3246*cdf0e10cSrcweir                 break;
3247*cdf0e10cSrcweir 
3248*cdf0e10cSrcweir             if( ! access( ByteString( String(aTo.PathToFileName()), aEncoding ).GetBuffer(), F_OK ) )
3249*cdf0e10cSrcweir             {
3250*cdf0e10cSrcweir                 if( ! ( pCallback ? pCallback->queryOverwriteFile( aTo.PathToFileName() ) : false ) )
3251*cdf0e10cSrcweir                     continue;
3252*cdf0e10cSrcweir             }
3253*cdf0e10cSrcweir             // look for afm if necessary
3254*cdf0e10cSrcweir             OUString aAfmCopied;
3255*cdf0e10cSrcweir             FileBase::RC nError;
3256*cdf0e10cSrcweir             if( aFrom.getExtension().equalsIgnoreAsciiCaseAscii( "pfa" ) ||
3257*cdf0e10cSrcweir                 aFrom.getExtension().equalsIgnoreAsciiCaseAscii( "pfb" ) )
3258*cdf0e10cSrcweir             {
3259*cdf0e10cSrcweir                 INetURLObject aFromAfm( aFrom );
3260*cdf0e10cSrcweir                 aFromAfm.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) );
3261*cdf0e10cSrcweir                 if( access( ByteString( String(aFromAfm.PathToFileName()), aEncoding ).GetBuffer(), F_OK ) )
3262*cdf0e10cSrcweir                 {
3263*cdf0e10cSrcweir                     aFromAfm.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AFM" ) ) );
3264*cdf0e10cSrcweir                     if( access( ByteString( String(aFromAfm.PathToFileName()), aEncoding ).GetBuffer(), F_OK ) )
3265*cdf0e10cSrcweir                     {
3266*cdf0e10cSrcweir                         aFromAfm.removeSegment();
3267*cdf0e10cSrcweir                         aFromAfm.Append( String( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) );
3268*cdf0e10cSrcweir                         aFromAfm.Append( aTo.GetName() );
3269*cdf0e10cSrcweir                         aFromAfm.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) );
3270*cdf0e10cSrcweir                         if( access( ByteString( String(aFromAfm.PathToFileName()), aEncoding ).GetBuffer(), F_OK ) )
3271*cdf0e10cSrcweir                         {
3272*cdf0e10cSrcweir                             aFromAfm.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AFM" ) ) );
3273*cdf0e10cSrcweir                             if( access( ByteString( String(aFromAfm.PathToFileName()), aEncoding ).GetBuffer(), F_OK ) )
3274*cdf0e10cSrcweir                             {
3275*cdf0e10cSrcweir                                 // give up
3276*cdf0e10cSrcweir                                 if( pCallback )
3277*cdf0e10cSrcweir                                     pCallback->importFontFailed( aTo.PathToFileName(), ImportFontCallback::NoAfmMetric );
3278*cdf0e10cSrcweir                                 continue;
3279*cdf0e10cSrcweir                             }
3280*cdf0e10cSrcweir                         }
3281*cdf0e10cSrcweir                     }
3282*cdf0e10cSrcweir                 }
3283*cdf0e10cSrcweir                 INetURLObject aToAfm( aTo );
3284*cdf0e10cSrcweir                 aToAfm.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) );
3285*cdf0e10cSrcweir                 OUString aFromPath, aToPath;
3286*cdf0e10cSrcweir                 if( bLinkOnly )
3287*cdf0e10cSrcweir                 {
3288*cdf0e10cSrcweir                     ByteString aLinkFromPath( String(aFromAfm.PathToFileName()),
3289*cdf0e10cSrcweir 						aEncoding );
3290*cdf0e10cSrcweir                     ByteString aLinkToPath( String(aToAfm.PathToFileName()),
3291*cdf0e10cSrcweir 						aEncoding );
3292*cdf0e10cSrcweir                     nError = (FileBase::RC)symlink( aLinkFromPath.GetBuffer(), aLinkToPath.GetBuffer() );
3293*cdf0e10cSrcweir                 }
3294*cdf0e10cSrcweir                 else
3295*cdf0e10cSrcweir                     nError = File::copy( aFromAfm.GetMainURL(INetURLObject::DECODE_TO_IURI), aToAfm.GetMainURL(INetURLObject::DECODE_TO_IURI) );
3296*cdf0e10cSrcweir                 if( nError )
3297*cdf0e10cSrcweir                 {
3298*cdf0e10cSrcweir                     if( pCallback )
3299*cdf0e10cSrcweir                         pCallback->importFontFailed( aTo.PathToFileName(), ImportFontCallback::AfmCopyFailed );
3300*cdf0e10cSrcweir                     continue;
3301*cdf0e10cSrcweir                 }
3302*cdf0e10cSrcweir                 aAfmCopied = aToPath;
3303*cdf0e10cSrcweir             }
3304*cdf0e10cSrcweir             if( bLinkOnly )
3305*cdf0e10cSrcweir             {
3306*cdf0e10cSrcweir                 ByteString aFromPath( String(aFrom.PathToFileName()),
3307*cdf0e10cSrcweir 					aEncoding );
3308*cdf0e10cSrcweir                 ByteString aToPath( String(aTo.PathToFileName()), aEncoding );
3309*cdf0e10cSrcweir                 nError = (FileBase::RC)symlink( aFromPath.GetBuffer(),
3310*cdf0e10cSrcweir 					aToPath.GetBuffer() );
3311*cdf0e10cSrcweir             }
3312*cdf0e10cSrcweir             else
3313*cdf0e10cSrcweir                 nError = File::copy( aFrom.GetMainURL(INetURLObject::DECODE_TO_IURI), aTo.GetMainURL(INetURLObject::DECODE_TO_IURI) );
3314*cdf0e10cSrcweir             // copy font file
3315*cdf0e10cSrcweir 			if( nError )
3316*cdf0e10cSrcweir             {
3317*cdf0e10cSrcweir                 if( aAfmCopied.getLength() )
3318*cdf0e10cSrcweir                     File::remove( aAfmCopied );
3319*cdf0e10cSrcweir                 if( pCallback )
3320*cdf0e10cSrcweir                     pCallback->importFontFailed( aTo.PathToFileName(), ImportFontCallback::FontCopyFailed );
3321*cdf0e10cSrcweir                 continue;
3322*cdf0e10cSrcweir             }
3323*cdf0e10cSrcweir 
3324*cdf0e10cSrcweir             ::std::list< PrintFont* > aNewFonts;
3325*cdf0e10cSrcweir             ::std::list< PrintFont* >::iterator it;
3326*cdf0e10cSrcweir             if( analyzeFontFile( nDirID, OUStringToOString( aTo.GetName(), aEncoding ), ::std::list<OString>(), aNewFonts ) )
3327*cdf0e10cSrcweir             {
3328*cdf0e10cSrcweir                 // remove all fonts for the same file
3329*cdf0e10cSrcweir                 // discarding their font ids
3330*cdf0e10cSrcweir                 ::std::hash_map< fontID, PrintFont* >::iterator current, next;
3331*cdf0e10cSrcweir                 current = m_aFonts.begin();
3332*cdf0e10cSrcweir                 OString aFileName( OUStringToOString( aTo.GetName(), aEncoding ) );
3333*cdf0e10cSrcweir                 while( current != m_aFonts.end() )
3334*cdf0e10cSrcweir                 {
3335*cdf0e10cSrcweir                     bool bRemove = false;
3336*cdf0e10cSrcweir                     switch( current->second->m_eType )
3337*cdf0e10cSrcweir                     {
3338*cdf0e10cSrcweir                         case fonttype::Type1:
3339*cdf0e10cSrcweir                             if( static_cast<Type1FontFile*>(current->second)->m_aFontFile == aFileName )
3340*cdf0e10cSrcweir                                 bRemove = true;
3341*cdf0e10cSrcweir                             break;
3342*cdf0e10cSrcweir                         case fonttype::TrueType:
3343*cdf0e10cSrcweir                             if( static_cast<TrueTypeFontFile*>(current->second)->m_aFontFile == aFileName )
3344*cdf0e10cSrcweir                                 bRemove = true;
3345*cdf0e10cSrcweir                             break;
3346*cdf0e10cSrcweir                         default: break;
3347*cdf0e10cSrcweir                     }
3348*cdf0e10cSrcweir                     if( bRemove )
3349*cdf0e10cSrcweir                     {
3350*cdf0e10cSrcweir                         next = current;
3351*cdf0e10cSrcweir                         ++next;
3352*cdf0e10cSrcweir                         m_aFontFileToFontID[ aFileName ].erase( current->first );
3353*cdf0e10cSrcweir                         delete current->second;
3354*cdf0e10cSrcweir                         m_aFonts.erase( current );
3355*cdf0e10cSrcweir                         current = next;
3356*cdf0e10cSrcweir                     }
3357*cdf0e10cSrcweir                     else
3358*cdf0e10cSrcweir                         ++current;
3359*cdf0e10cSrcweir                 }
3360*cdf0e10cSrcweir 
3361*cdf0e10cSrcweir                 DBG_ASSERT( !findFontFileID( nDirID, aFileName ), "not all fonts removed for file" );
3362*cdf0e10cSrcweir 
3363*cdf0e10cSrcweir                 nSuccess++;
3364*cdf0e10cSrcweir                 for( it = aNewFonts.begin(); it != aNewFonts.end(); ++it )
3365*cdf0e10cSrcweir                 {
3366*cdf0e10cSrcweir                     m_aFontFileToFontID[ aFileName ].insert( m_nNextFontID );
3367*cdf0e10cSrcweir                     m_aFonts[ m_nNextFontID++ ] = *it;
3368*cdf0e10cSrcweir                     m_pFontCache->updateFontCacheEntry( *it, false );
3369*cdf0e10cSrcweir                 }
3370*cdf0e10cSrcweir             }
3371*cdf0e10cSrcweir         }
3372*cdf0e10cSrcweir 
3373*cdf0e10cSrcweir         m_pFontCache->updateDirTimestamp( nDirID );
3374*cdf0e10cSrcweir         m_pFontCache->flush();
3375*cdf0e10cSrcweir     }
3376*cdf0e10cSrcweir     else if( pCallback )
3377*cdf0e10cSrcweir         pCallback->importFontsFailed( ImportFontCallback::NoWritableDirectory );
3378*cdf0e10cSrcweir 
3379*cdf0e10cSrcweir     return nSuccess;
3380*cdf0e10cSrcweir }
3381*cdf0e10cSrcweir 
3382*cdf0e10cSrcweir // -------------------------------------------------------------------------
3383*cdf0e10cSrcweir 
3384*cdf0e10cSrcweir bool PrintFontManager::checkImportPossible() const
3385*cdf0e10cSrcweir {
3386*cdf0e10cSrcweir     bool bSuccess = false;
3387*cdf0e10cSrcweir 
3388*cdf0e10cSrcweir     // find a directory with write access
3389*cdf0e10cSrcweir     ByteString aDir;
3390*cdf0e10cSrcweir     for( std::list< int >::const_iterator dir_it = m_aPrivateFontDirectories.begin();
3391*cdf0e10cSrcweir          dir_it != m_aPrivateFontDirectories.end(); ++dir_it )
3392*cdf0e10cSrcweir     {
3393*cdf0e10cSrcweir         aDir = getDirectory( *dir_it );
3394*cdf0e10cSrcweir         if( createWriteablePath( aDir ) )
3395*cdf0e10cSrcweir         {
3396*cdf0e10cSrcweir             bSuccess = true;
3397*cdf0e10cSrcweir             break;
3398*cdf0e10cSrcweir         }
3399*cdf0e10cSrcweir     }
3400*cdf0e10cSrcweir 
3401*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3402*cdf0e10cSrcweir     if( bSuccess )
3403*cdf0e10cSrcweir         fprintf( stderr, "found writable %s\n", aDir.GetBuffer() );
3404*cdf0e10cSrcweir #endif
3405*cdf0e10cSrcweir 
3406*cdf0e10cSrcweir     return bSuccess;
3407*cdf0e10cSrcweir }
3408*cdf0e10cSrcweir 
3409*cdf0e10cSrcweir // -------------------------------------------------------------------------
3410*cdf0e10cSrcweir 
3411*cdf0e10cSrcweir bool PrintFontManager::checkChangeFontPropertiesPossible( fontID /*nFontID*/ ) const
3412*cdf0e10cSrcweir {
3413*cdf0e10cSrcweir     // since font properties are changed in the font cache file only nowadays
3414*cdf0e10cSrcweir     // they can always be changed
3415*cdf0e10cSrcweir     return true;
3416*cdf0e10cSrcweir }
3417*cdf0e10cSrcweir 
3418*cdf0e10cSrcweir // -------------------------------------------------------------------------
3419*cdf0e10cSrcweir 
3420*cdf0e10cSrcweir bool PrintFontManager::changeFontProperties( fontID nFontID, const ::rtl::OUString& rXLFD )
3421*cdf0e10cSrcweir {
3422*cdf0e10cSrcweir     ByteString aXLFD( OUStringToOString( rXLFD, RTL_TEXTENCODING_UTF8 ) );
3423*cdf0e10cSrcweir     ByteString aAddStyle = aXLFD.GetToken( '-', 6 );
3424*cdf0e10cSrcweir     if( aAddStyle.Search( "utf8" ) == STRING_NOTFOUND )
3425*cdf0e10cSrcweir     {
3426*cdf0e10cSrcweir         aAddStyle.Append( aAddStyle.Len() ? ";utf8" : "utf8" );
3427*cdf0e10cSrcweir         aXLFD.SetToken( 6, ';', aAddStyle );
3428*cdf0e10cSrcweir     }
3429*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFontID );
3430*cdf0e10cSrcweir     std::list< OString > aDummyList;
3431*cdf0e10cSrcweir     aDummyList.push_back( aXLFD );
3432*cdf0e10cSrcweir     getFontAttributesFromXLFD( pFont, aDummyList );
3433*cdf0e10cSrcweir     pFont->m_bUserOverride = true;
3434*cdf0e10cSrcweir     m_pFontCache->updateFontCacheEntry( pFont, true );
3435*cdf0e10cSrcweir 
3436*cdf0e10cSrcweir     return true;
3437*cdf0e10cSrcweir }
3438*cdf0e10cSrcweir 
3439*cdf0e10cSrcweir // -------------------------------------------------------------------------
3440*cdf0e10cSrcweir 
3441*cdf0e10cSrcweir bool PrintFontManager::
3442*cdf0e10cSrcweir getImportableFontProperties(
3443*cdf0e10cSrcweir                             const OString& rFile,
3444*cdf0e10cSrcweir                             ::std::list< FastPrintFontInfo >& rFontProps
3445*cdf0e10cSrcweir                             )
3446*cdf0e10cSrcweir {
3447*cdf0e10cSrcweir     rFontProps.clear();
3448*cdf0e10cSrcweir     int nIndex = rFile.lastIndexOf( '/' );
3449*cdf0e10cSrcweir     OString aDir, aFile( rFile.copy( nIndex+1 ) );
3450*cdf0e10cSrcweir     if( nIndex != -1 )
3451*cdf0e10cSrcweir         aDir = rFile.copy( 0, nIndex );
3452*cdf0e10cSrcweir     int nDirID = getDirectoryAtom( aDir, true );
3453*cdf0e10cSrcweir     ::std::list< PrintFont* > aFonts;
3454*cdf0e10cSrcweir     bool bRet = analyzeFontFile( nDirID, aFile, ::std::list<OString>(), aFonts );
3455*cdf0e10cSrcweir     while( aFonts.begin() != aFonts.end() )
3456*cdf0e10cSrcweir     {
3457*cdf0e10cSrcweir         PrintFont* pFont = aFonts.front();
3458*cdf0e10cSrcweir         aFonts.pop_front();
3459*cdf0e10cSrcweir         FastPrintFontInfo aInfo;
3460*cdf0e10cSrcweir         fillPrintFontInfo( pFont, aInfo );
3461*cdf0e10cSrcweir         rFontProps.push_back( aInfo );
3462*cdf0e10cSrcweir         delete pFont;
3463*cdf0e10cSrcweir     }
3464*cdf0e10cSrcweir     return bRet;
3465*cdf0e10cSrcweir }
3466*cdf0e10cSrcweir 
3467*cdf0e10cSrcweir // -------------------------------------------------------------------------
3468*cdf0e10cSrcweir 
3469*cdf0e10cSrcweir bool PrintFontManager::getFileDuplicates( fontID nFont, ::std::list< fontID >& rFonts ) const
3470*cdf0e10cSrcweir {
3471*cdf0e10cSrcweir     bool bRet = false;
3472*cdf0e10cSrcweir 
3473*cdf0e10cSrcweir     rFonts.clear();
3474*cdf0e10cSrcweir 
3475*cdf0e10cSrcweir     PrintFont* pSearchFont = getFont( nFont );
3476*cdf0e10cSrcweir     if( ! pSearchFont ||
3477*cdf0e10cSrcweir         pSearchFont->m_eType != fonttype::TrueType ||
3478*cdf0e10cSrcweir         static_cast<TrueTypeFontFile*>(pSearchFont)->m_nCollectionEntry == -1
3479*cdf0e10cSrcweir         )
3480*cdf0e10cSrcweir         return false;
3481*cdf0e10cSrcweir 
3482*cdf0e10cSrcweir     OString aFile( getFontFileSysPath( nFont ) );
3483*cdf0e10cSrcweir     if( ! aFile.getLength() )
3484*cdf0e10cSrcweir         return false;
3485*cdf0e10cSrcweir 
3486*cdf0e10cSrcweir     for( ::std::hash_map< fontID, PrintFont* >::const_iterator it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
3487*cdf0e10cSrcweir     {
3488*cdf0e10cSrcweir         if( nFont != it->first )
3489*cdf0e10cSrcweir         {
3490*cdf0e10cSrcweir             OString aCompFile( getFontFile( it->second ) );
3491*cdf0e10cSrcweir             if( aCompFile == aFile )
3492*cdf0e10cSrcweir             {
3493*cdf0e10cSrcweir                 rFonts.push_back( it->first );
3494*cdf0e10cSrcweir                 bRet = true;
3495*cdf0e10cSrcweir             }
3496*cdf0e10cSrcweir         }
3497*cdf0e10cSrcweir     }
3498*cdf0e10cSrcweir     return bRet;
3499*cdf0e10cSrcweir }
3500*cdf0e10cSrcweir 
3501*cdf0e10cSrcweir // -------------------------------------------------------------------------
3502*cdf0e10cSrcweir 
3503*cdf0e10cSrcweir bool PrintFontManager::removeFonts( const ::std::list< fontID >& rFonts )
3504*cdf0e10cSrcweir {
3505*cdf0e10cSrcweir     bool bRet = true;
3506*cdf0e10cSrcweir     ::std::list< fontID > aDuplicates;
3507*cdf0e10cSrcweir     for( ::std::list< fontID >::const_iterator it = rFonts.begin(); it != rFonts.end(); ++it )
3508*cdf0e10cSrcweir     {
3509*cdf0e10cSrcweir         ::std::hash_map< fontID, PrintFont* >::const_iterator haveFont = m_aFonts.find( *it );
3510*cdf0e10cSrcweir         if( haveFont == m_aFonts.end() )
3511*cdf0e10cSrcweir             continue;
3512*cdf0e10cSrcweir 
3513*cdf0e10cSrcweir         PrintFont* pFont = haveFont->second;
3514*cdf0e10cSrcweir         bool bRemoveDuplicates = getFileDuplicates( *it, aDuplicates );
3515*cdf0e10cSrcweir         ByteString aFile( getFontFile( pFont ) );
3516*cdf0e10cSrcweir         if( aFile.Len() )
3517*cdf0e10cSrcweir         {
3518*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3519*cdf0e10cSrcweir             fprintf( stderr, "try unlink( \"%s\" ) ... ", aFile.GetBuffer() );
3520*cdf0e10cSrcweir #endif
3521*cdf0e10cSrcweir             if( unlink( aFile.GetBuffer() ) )
3522*cdf0e10cSrcweir             {
3523*cdf0e10cSrcweir                 bRet = false;
3524*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3525*cdf0e10cSrcweir                 fprintf( stderr, "failed\n" );
3526*cdf0e10cSrcweir #endif
3527*cdf0e10cSrcweir                 continue;
3528*cdf0e10cSrcweir             }
3529*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3530*cdf0e10cSrcweir             fprintf( stderr, "succeeded\n" );
3531*cdf0e10cSrcweir #endif
3532*cdf0e10cSrcweir             OString aAfm( getAfmFile( pFont ) );
3533*cdf0e10cSrcweir             if( aAfm.getLength() )
3534*cdf0e10cSrcweir             {
3535*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3536*cdf0e10cSrcweir                 fprintf( stderr, "unlink( \"%s\" )\n", aAfm.getStr() );
3537*cdf0e10cSrcweir #endif
3538*cdf0e10cSrcweir                 unlink( aAfm.getStr() );
3539*cdf0e10cSrcweir             }
3540*cdf0e10cSrcweir             m_aFonts.erase( *it );
3541*cdf0e10cSrcweir             delete pFont;
3542*cdf0e10cSrcweir             if( bRemoveDuplicates )
3543*cdf0e10cSrcweir             {
3544*cdf0e10cSrcweir                 for( ::std::list< fontID >::iterator dup = aDuplicates.begin(); dup != aDuplicates.end(); ++dup )
3545*cdf0e10cSrcweir                 {
3546*cdf0e10cSrcweir                     m_aFontFileToFontID[ aFile ].erase( *dup );
3547*cdf0e10cSrcweir                     PrintFont* pDup = m_aFonts[ *dup ];
3548*cdf0e10cSrcweir                     m_aFonts.erase( *dup );
3549*cdf0e10cSrcweir                     delete pDup;
3550*cdf0e10cSrcweir                 }
3551*cdf0e10cSrcweir             }
3552*cdf0e10cSrcweir         }
3553*cdf0e10cSrcweir     }
3554*cdf0e10cSrcweir     return bRet;
3555*cdf0e10cSrcweir }
3556*cdf0e10cSrcweir 
3557*cdf0e10cSrcweir // -------------------------------------------------------------------------
3558*cdf0e10cSrcweir 
3559*cdf0e10cSrcweir bool PrintFontManager::isPrivateFontFile( fontID nFont ) const
3560*cdf0e10cSrcweir {
3561*cdf0e10cSrcweir     bool bRet = false;
3562*cdf0e10cSrcweir     int nDirID = -1;
3563*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFont );
3564*cdf0e10cSrcweir     if( pFont )
3565*cdf0e10cSrcweir     {
3566*cdf0e10cSrcweir         switch( pFont->m_eType )
3567*cdf0e10cSrcweir         {
3568*cdf0e10cSrcweir             case fonttype::Type1: nDirID = static_cast< Type1FontFile* >(pFont)->m_nDirectory;break;
3569*cdf0e10cSrcweir             case fonttype::TrueType: nDirID = static_cast< TrueTypeFontFile* >(pFont)->m_nDirectory;break;
3570*cdf0e10cSrcweir             default: break;
3571*cdf0e10cSrcweir         }
3572*cdf0e10cSrcweir     }
3573*cdf0e10cSrcweir     if( nDirID != -1 )
3574*cdf0e10cSrcweir     {
3575*cdf0e10cSrcweir         for( ::std::list< int >::const_iterator it = m_aPrivateFontDirectories.begin(); it != m_aPrivateFontDirectories.end(); ++it )
3576*cdf0e10cSrcweir         {
3577*cdf0e10cSrcweir             if( nDirID == *it )
3578*cdf0e10cSrcweir             {
3579*cdf0e10cSrcweir                 bRet = true;
3580*cdf0e10cSrcweir                 break;
3581*cdf0e10cSrcweir             }
3582*cdf0e10cSrcweir         }
3583*cdf0e10cSrcweir     }
3584*cdf0e10cSrcweir     return bRet;
3585*cdf0e10cSrcweir }
3586*cdf0e10cSrcweir 
3587*cdf0e10cSrcweir // -------------------------------------------------------------------------
3588*cdf0e10cSrcweir 
3589*cdf0e10cSrcweir bool PrintFontManager::getAlternativeFamilyNames( fontID nFont, ::std::list< OUString >& rNames ) const
3590*cdf0e10cSrcweir {
3591*cdf0e10cSrcweir     rNames.clear();
3592*cdf0e10cSrcweir 
3593*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFont );
3594*cdf0e10cSrcweir     if( pFont && pFont->m_eType == fonttype::TrueType )
3595*cdf0e10cSrcweir     {
3596*cdf0e10cSrcweir         TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont);
3597*cdf0e10cSrcweir         ByteString aFile( getFontFile( pFont ) );
3598*cdf0e10cSrcweir         TrueTypeFont* pTTFont;
3599*cdf0e10cSrcweir         if( OpenTTFontFile( aFile.GetBuffer(), pTTFontFile->m_nCollectionEntry < 0 ? 0 : pTTFontFile->m_nCollectionEntry, &pTTFont ) == SF_OK )
3600*cdf0e10cSrcweir         {
3601*cdf0e10cSrcweir             NameRecord* pNameRecords = NULL;
3602*cdf0e10cSrcweir             int nNameRecords = GetTTNameRecords( pTTFont, &pNameRecords );
3603*cdf0e10cSrcweir             for( int i = 0; i < nNameRecords; i++ )
3604*cdf0e10cSrcweir             {
3605*cdf0e10cSrcweir                 if( pNameRecords[i].nameID != 1 ) // family name
3606*cdf0e10cSrcweir                     continue;
3607*cdf0e10cSrcweir 
3608*cdf0e10cSrcweir                 OUString aFamily( convertTrueTypeName( pNameRecords+i ) );
3609*cdf0e10cSrcweir                 if( aFamily.getLength()
3610*cdf0e10cSrcweir                     &&
3611*cdf0e10cSrcweir                     m_pAtoms->getAtom( ATOM_FAMILYNAME, aFamily, sal_True ) != pFont->m_nFamilyName
3612*cdf0e10cSrcweir                     )
3613*cdf0e10cSrcweir                 {
3614*cdf0e10cSrcweir                     rNames.push_back( aFamily );
3615*cdf0e10cSrcweir                 }
3616*cdf0e10cSrcweir             }
3617*cdf0e10cSrcweir 
3618*cdf0e10cSrcweir             if( nNameRecords )
3619*cdf0e10cSrcweir                 DisposeNameRecords( pNameRecords, nNameRecords );
3620*cdf0e10cSrcweir             CloseTTFont( pTTFont );
3621*cdf0e10cSrcweir         }
3622*cdf0e10cSrcweir     }
3623*cdf0e10cSrcweir     return rNames.begin() != rNames.end();
3624*cdf0e10cSrcweir }
3625*cdf0e10cSrcweir 
3626*cdf0e10cSrcweir // -------------------------------------------------------------------------
3627*cdf0e10cSrcweir 
3628*cdf0e10cSrcweir // TODO: move most of this stuff into the central font-subsetting code
3629*cdf0e10cSrcweir bool PrintFontManager::createFontSubset(
3630*cdf0e10cSrcweir                                         FontSubsetInfo& rInfo,
3631*cdf0e10cSrcweir                                         fontID nFont,
3632*cdf0e10cSrcweir                                         const OUString& rOutFile,
3633*cdf0e10cSrcweir                                         sal_Int32* pGlyphIDs,
3634*cdf0e10cSrcweir                                         sal_uInt8* pNewEncoding,
3635*cdf0e10cSrcweir                                         sal_Int32* pWidths,
3636*cdf0e10cSrcweir                                         int nGlyphs,
3637*cdf0e10cSrcweir                                         bool bVertical
3638*cdf0e10cSrcweir                                         )
3639*cdf0e10cSrcweir {
3640*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFont );
3641*cdf0e10cSrcweir     if( !pFont )
3642*cdf0e10cSrcweir         return false;
3643*cdf0e10cSrcweir 
3644*cdf0e10cSrcweir     switch( pFont->m_eType )
3645*cdf0e10cSrcweir     {
3646*cdf0e10cSrcweir         case psp::fonttype::TrueType: rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; break;
3647*cdf0e10cSrcweir         case psp::fonttype::Type1: rInfo.m_nFontType = FontSubsetInfo::ANY_TYPE1; break;
3648*cdf0e10cSrcweir         default:
3649*cdf0e10cSrcweir             return false;
3650*cdf0e10cSrcweir     }
3651*cdf0e10cSrcweir 	// TODO: remove when Type1 subsetting gets implemented
3652*cdf0e10cSrcweir     if( pFont->m_eType != fonttype::TrueType )
3653*cdf0e10cSrcweir         return false;
3654*cdf0e10cSrcweir 
3655*cdf0e10cSrcweir 	// reshuffle array of requested glyphs to make sure glyph0==notdef
3656*cdf0e10cSrcweir     sal_uInt8  pEnc[256];
3657*cdf0e10cSrcweir     sal_uInt16 pGID[256];
3658*cdf0e10cSrcweir     sal_uInt8  pOldIndex[256];
3659*cdf0e10cSrcweir     memset( pEnc, 0, sizeof( pEnc ) );
3660*cdf0e10cSrcweir     memset( pGID, 0, sizeof( pGID ) );
3661*cdf0e10cSrcweir     memset( pOldIndex, 0, sizeof( pOldIndex ) );
3662*cdf0e10cSrcweir     if( nGlyphs > 256 )
3663*cdf0e10cSrcweir         return false;
3664*cdf0e10cSrcweir     int nChar = 1;
3665*cdf0e10cSrcweir     for( int i = 0; i < nGlyphs; i++ )
3666*cdf0e10cSrcweir     {
3667*cdf0e10cSrcweir         if( pNewEncoding[i] == 0 )
3668*cdf0e10cSrcweir         {
3669*cdf0e10cSrcweir             pOldIndex[ 0 ] = i;
3670*cdf0e10cSrcweir         }
3671*cdf0e10cSrcweir         else
3672*cdf0e10cSrcweir         {
3673*cdf0e10cSrcweir             DBG_ASSERT( !(pGlyphIDs[i] & 0x007f0000), "overlong glyph id" );
3674*cdf0e10cSrcweir             DBG_ASSERT( (int)pNewEncoding[i] < nGlyphs, "encoding wrong" );
3675*cdf0e10cSrcweir             DBG_ASSERT( pEnc[pNewEncoding[i]] == 0 && pGID[pNewEncoding[i]] == 0, "duplicate encoded glyph" );
3676*cdf0e10cSrcweir             pEnc[ pNewEncoding[i] ] = pNewEncoding[i];
3677*cdf0e10cSrcweir             pGID[ pNewEncoding[i] ] = (sal_uInt16)pGlyphIDs[ i ];
3678*cdf0e10cSrcweir             pOldIndex[ pNewEncoding[i] ] = i;
3679*cdf0e10cSrcweir             nChar++;
3680*cdf0e10cSrcweir         }
3681*cdf0e10cSrcweir     }
3682*cdf0e10cSrcweir     nGlyphs = nChar; // either input value or increased by one
3683*cdf0e10cSrcweir 
3684*cdf0e10cSrcweir 	// prepare system name for read access for subset source file
3685*cdf0e10cSrcweir     // TODO: since this file is usually already mmapped there is no need to open it again
3686*cdf0e10cSrcweir     const ByteString aFromFile = getFontFile( pFont );
3687*cdf0e10cSrcweir 
3688*cdf0e10cSrcweir     TrueTypeFont* pTTFont = NULL; // TODO: rename to SfntFont
3689*cdf0e10cSrcweir     TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont);
3690*cdf0e10cSrcweir     if( OpenTTFontFile( aFromFile.GetBuffer(), pTTFontFile->m_nCollectionEntry < 0 ? 0 : pTTFontFile->m_nCollectionEntry, &pTTFont ) != SF_OK )
3691*cdf0e10cSrcweir         return false;
3692*cdf0e10cSrcweir 
3693*cdf0e10cSrcweir 	// prepare system name for write access for subset file target
3694*cdf0e10cSrcweir     OUString aSysPath;
3695*cdf0e10cSrcweir     if( osl_File_E_None != osl_getSystemPathFromFileURL( rOutFile.pData, &aSysPath.pData ) )
3696*cdf0e10cSrcweir         return false;
3697*cdf0e10cSrcweir     const rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
3698*cdf0e10cSrcweir     const ByteString aToFile( OUStringToOString( aSysPath, aEncoding ) );
3699*cdf0e10cSrcweir 
3700*cdf0e10cSrcweir 	// do CFF subsetting if possible
3701*cdf0e10cSrcweir 	int nCffLength = 0;
3702*cdf0e10cSrcweir 	const sal_uInt8* pCffBytes = NULL;
3703*cdf0e10cSrcweir 	if( GetSfntTable( pTTFont, O_CFF, &pCffBytes, &nCffLength ) )
3704*cdf0e10cSrcweir 	{
3705*cdf0e10cSrcweir 		rInfo.LoadFont( FontSubsetInfo::CFF_FONT, pCffBytes, nCffLength );
3706*cdf0e10cSrcweir #if 1 // TODO: remove 16bit->long conversion when related methods handle non-16bit glyphids
3707*cdf0e10cSrcweir 		long aRequestedGlyphs[256];
3708*cdf0e10cSrcweir 		for( int i = 0; i < nGlyphs; ++i )
3709*cdf0e10cSrcweir 			aRequestedGlyphs[i] = pGID[i];
3710*cdf0e10cSrcweir #endif
3711*cdf0e10cSrcweir 	    // create subset file at requested path
3712*cdf0e10cSrcweir 		FILE* pOutFile = fopen( aToFile.GetBuffer(), "wb" );
3713*cdf0e10cSrcweir 		// create font subset
3714*cdf0e10cSrcweir 		const char* pGlyphSetName = NULL; // TODO: better name?
3715*cdf0e10cSrcweir 		const bool bOK = rInfo.CreateFontSubset(
3716*cdf0e10cSrcweir 			FontSubsetInfo::TYPE1_PFB,
3717*cdf0e10cSrcweir 			pOutFile, pGlyphSetName,
3718*cdf0e10cSrcweir 			aRequestedGlyphs, pEnc, nGlyphs, pWidths );
3719*cdf0e10cSrcweir 		fclose( pOutFile );
3720*cdf0e10cSrcweir 		// cleanup before early return
3721*cdf0e10cSrcweir 		CloseTTFont( pTTFont );
3722*cdf0e10cSrcweir 		return bOK;
3723*cdf0e10cSrcweir 	}
3724*cdf0e10cSrcweir 
3725*cdf0e10cSrcweir 	// do TTF->Type42 or Type3 subsetting
3726*cdf0e10cSrcweir     // fill in font info
3727*cdf0e10cSrcweir     psp::PrintFontInfo aFontInfo;
3728*cdf0e10cSrcweir     if( ! getFontInfo( nFont, aFontInfo ) )
3729*cdf0e10cSrcweir         return false;
3730*cdf0e10cSrcweir 
3731*cdf0e10cSrcweir     rInfo.m_nAscent     = aFontInfo.m_nAscend;
3732*cdf0e10cSrcweir     rInfo.m_nDescent    = aFontInfo.m_nDescend;
3733*cdf0e10cSrcweir     rInfo.m_aPSName     = getPSName( nFont );
3734*cdf0e10cSrcweir 
3735*cdf0e10cSrcweir     int xMin, yMin, xMax, yMax;
3736*cdf0e10cSrcweir     getFontBoundingBox( nFont, xMin, yMin, xMax, yMax );
3737*cdf0e10cSrcweir     rInfo.m_aFontBBox	= Rectangle( Point( xMin, yMin ), Size( xMax-xMin, yMax-yMin ) );
3738*cdf0e10cSrcweir     rInfo.m_nCapHeight	= yMax; // Well ...
3739*cdf0e10cSrcweir 
3740*cdf0e10cSrcweir 	// fill in glyph advance widths
3741*cdf0e10cSrcweir     TTSimpleGlyphMetrics* pMetrics = GetTTSimpleGlyphMetrics( pTTFont,
3742*cdf0e10cSrcweir                                                               pGID,
3743*cdf0e10cSrcweir                                                               nGlyphs,
3744*cdf0e10cSrcweir                                                               bVertical ? 1 : 0 );
3745*cdf0e10cSrcweir     if( pMetrics )
3746*cdf0e10cSrcweir     {
3747*cdf0e10cSrcweir         for( int i = 0; i < nGlyphs; i++ )
3748*cdf0e10cSrcweir             pWidths[pOldIndex[i]] = pMetrics[i].adv;
3749*cdf0e10cSrcweir         free( pMetrics );
3750*cdf0e10cSrcweir     }
3751*cdf0e10cSrcweir     else
3752*cdf0e10cSrcweir     {
3753*cdf0e10cSrcweir         CloseTTFont( pTTFont );
3754*cdf0e10cSrcweir         return false;
3755*cdf0e10cSrcweir     }
3756*cdf0e10cSrcweir 
3757*cdf0e10cSrcweir     bool bSuccess = ( SF_OK == CreateTTFromTTGlyphs( pTTFont,
3758*cdf0e10cSrcweir                                                      aToFile.GetBuffer(),
3759*cdf0e10cSrcweir                                                      pGID,
3760*cdf0e10cSrcweir                                                      pEnc,
3761*cdf0e10cSrcweir                                                      nGlyphs,
3762*cdf0e10cSrcweir                                                      0,
3763*cdf0e10cSrcweir                                                      NULL,
3764*cdf0e10cSrcweir                                                      0 ) );
3765*cdf0e10cSrcweir     CloseTTFont( pTTFont );
3766*cdf0e10cSrcweir 
3767*cdf0e10cSrcweir     return bSuccess;
3768*cdf0e10cSrcweir }
3769*cdf0e10cSrcweir 
3770*cdf0e10cSrcweir void PrintFontManager::getGlyphWidths( fontID nFont,
3771*cdf0e10cSrcweir                                        bool bVertical,
3772*cdf0e10cSrcweir                                        std::vector< sal_Int32 >& rWidths,
3773*cdf0e10cSrcweir                                        std::map< sal_Unicode, sal_uInt32 >& rUnicodeEnc )
3774*cdf0e10cSrcweir {
3775*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFont );
3776*cdf0e10cSrcweir     if( !pFont ||
3777*cdf0e10cSrcweir         (pFont->m_eType != fonttype::TrueType && pFont->m_eType != fonttype::Type1) )
3778*cdf0e10cSrcweir         return;
3779*cdf0e10cSrcweir     if( pFont->m_eType == fonttype::TrueType )
3780*cdf0e10cSrcweir     {
3781*cdf0e10cSrcweir         TrueTypeFont* pTTFont = NULL;
3782*cdf0e10cSrcweir         TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont);
3783*cdf0e10cSrcweir         ByteString aFromFile = getFontFile( pFont );
3784*cdf0e10cSrcweir         if( OpenTTFontFile( aFromFile.GetBuffer(), pTTFontFile->m_nCollectionEntry < 0 ? 0 : pTTFontFile->m_nCollectionEntry, &pTTFont ) != SF_OK )
3785*cdf0e10cSrcweir             return;
3786*cdf0e10cSrcweir         int nGlyphs = GetTTGlyphCount( pTTFont );
3787*cdf0e10cSrcweir         if( nGlyphs > 0 )
3788*cdf0e10cSrcweir         {
3789*cdf0e10cSrcweir             rWidths.resize(nGlyphs);
3790*cdf0e10cSrcweir             std::vector<sal_uInt16> aGlyphIds(nGlyphs);
3791*cdf0e10cSrcweir             for( int i = 0; i < nGlyphs; i++ )
3792*cdf0e10cSrcweir                 aGlyphIds[i] = sal_uInt16(i);
3793*cdf0e10cSrcweir             TTSimpleGlyphMetrics* pMetrics = GetTTSimpleGlyphMetrics( pTTFont,
3794*cdf0e10cSrcweir                                                                       &aGlyphIds[0],
3795*cdf0e10cSrcweir                                                                       nGlyphs,
3796*cdf0e10cSrcweir                                                                       bVertical ? 1 : 0 );
3797*cdf0e10cSrcweir             if( pMetrics )
3798*cdf0e10cSrcweir             {
3799*cdf0e10cSrcweir                 for( int i = 0; i< nGlyphs; i++ )
3800*cdf0e10cSrcweir                     rWidths[i] = pMetrics[i].adv;
3801*cdf0e10cSrcweir                 free( pMetrics );
3802*cdf0e10cSrcweir                 rUnicodeEnc.clear();
3803*cdf0e10cSrcweir             }
3804*cdf0e10cSrcweir 
3805*cdf0e10cSrcweir 			// fill the unicode map
3806*cdf0e10cSrcweir 			// TODO: isn't this map already available elsewhere in the fontmanager?
3807*cdf0e10cSrcweir 			const sal_uInt8* pCmapData = NULL;
3808*cdf0e10cSrcweir 			int nCmapSize = 0;
3809*cdf0e10cSrcweir 			if( GetSfntTable( pTTFont, O_cmap, &pCmapData, &nCmapSize ) )
3810*cdf0e10cSrcweir 			{
3811*cdf0e10cSrcweir 				CmapResult aCmapResult;
3812*cdf0e10cSrcweir 				if( ParseCMAP( pCmapData, nCmapSize, aCmapResult ) )
3813*cdf0e10cSrcweir 				{
3814*cdf0e10cSrcweir 					const ImplFontCharMap aCharMap( aCmapResult );
3815*cdf0e10cSrcweir 					for( sal_uInt32 cOld = 0;;)
3816*cdf0e10cSrcweir 					{
3817*cdf0e10cSrcweir 						// get next unicode covered by font
3818*cdf0e10cSrcweir 						const sal_uInt32 c = aCharMap.GetNextChar( cOld );
3819*cdf0e10cSrcweir 						if( c == cOld )
3820*cdf0e10cSrcweir 							break;
3821*cdf0e10cSrcweir 						cOld = c;
3822*cdf0e10cSrcweir #if 1 // TODO: remove when sal_Unicode covers all of unicode
3823*cdf0e10cSrcweir 						if( c > (sal_Unicode)~0 )
3824*cdf0e10cSrcweir 							break;
3825*cdf0e10cSrcweir #endif
3826*cdf0e10cSrcweir 						// get the matching glyph index
3827*cdf0e10cSrcweir 						const sal_uInt32 nGlyphId = aCharMap.GetGlyphIndex( c );
3828*cdf0e10cSrcweir 						// update the requested map
3829*cdf0e10cSrcweir 						rUnicodeEnc[ (sal_Unicode)c ] = nGlyphId;
3830*cdf0e10cSrcweir 					}
3831*cdf0e10cSrcweir 				}
3832*cdf0e10cSrcweir 			}
3833*cdf0e10cSrcweir         }
3834*cdf0e10cSrcweir         CloseTTFont( pTTFont );
3835*cdf0e10cSrcweir     }
3836*cdf0e10cSrcweir     else if( pFont->m_eType == fonttype::Type1 )
3837*cdf0e10cSrcweir     {
3838*cdf0e10cSrcweir         if( ! pFont->m_aEncodingVector.size() )
3839*cdf0e10cSrcweir             pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, true, true );
3840*cdf0e10cSrcweir         if( pFont->m_pMetrics )
3841*cdf0e10cSrcweir         {
3842*cdf0e10cSrcweir             rUnicodeEnc.clear();
3843*cdf0e10cSrcweir             rWidths.clear();
3844*cdf0e10cSrcweir             rWidths.reserve( pFont->m_pMetrics->m_aMetrics.size() );
3845*cdf0e10cSrcweir             for( std::hash_map< int, CharacterMetric >::const_iterator it =
3846*cdf0e10cSrcweir                  pFont->m_pMetrics->m_aMetrics.begin();
3847*cdf0e10cSrcweir                  it != pFont->m_pMetrics->m_aMetrics.end(); ++it )
3848*cdf0e10cSrcweir             {
3849*cdf0e10cSrcweir                 if( (it->first & 0x00010000) == 0 || bVertical )
3850*cdf0e10cSrcweir                 {
3851*cdf0e10cSrcweir                     rUnicodeEnc[ sal_Unicode(it->first & 0x0000ffff) ] = sal_uInt32(rWidths.size());
3852*cdf0e10cSrcweir                     rWidths.push_back( it->second.width );
3853*cdf0e10cSrcweir                 }
3854*cdf0e10cSrcweir             }
3855*cdf0e10cSrcweir         }
3856*cdf0e10cSrcweir     }
3857*cdf0e10cSrcweir }
3858*cdf0e10cSrcweir 
3859*cdf0e10cSrcweir // -------------------------------------------------------------------------
3860*cdf0e10cSrcweir 
3861*cdf0e10cSrcweir const std::map< sal_Unicode, sal_Int32 >* PrintFontManager::getEncodingMap( fontID nFont, const std::map< sal_Unicode, rtl::OString >** pNonEncoded ) const
3862*cdf0e10cSrcweir {
3863*cdf0e10cSrcweir     PrintFont* pFont = getFont( nFont );
3864*cdf0e10cSrcweir     if( !pFont ||
3865*cdf0e10cSrcweir         (pFont->m_eType != fonttype::Type1 && pFont->m_eType != fonttype::Builtin)
3866*cdf0e10cSrcweir         )
3867*cdf0e10cSrcweir         return NULL;
3868*cdf0e10cSrcweir 
3869*cdf0e10cSrcweir     if( ! pFont->m_aEncodingVector.size() )
3870*cdf0e10cSrcweir         pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms, true, true );
3871*cdf0e10cSrcweir 
3872*cdf0e10cSrcweir     if( pNonEncoded )
3873*cdf0e10cSrcweir         *pNonEncoded = pFont->m_aNonEncoded.size() ? &pFont->m_aNonEncoded : NULL;
3874*cdf0e10cSrcweir 
3875*cdf0e10cSrcweir     return pFont->m_aEncodingVector.size() ? &pFont->m_aEncodingVector : NULL;
3876*cdf0e10cSrcweir }
3877*cdf0e10cSrcweir 
3878*cdf0e10cSrcweir // -------------------------------------------------------------------------
3879*cdf0e10cSrcweir 
3880*cdf0e10cSrcweir std::list< OString > PrintFontManager::getAdobeNameFromUnicode( sal_Unicode aChar ) const
3881*cdf0e10cSrcweir {
3882*cdf0e10cSrcweir     std::pair< std::hash_multimap< sal_Unicode, rtl::OString >::const_iterator,
3883*cdf0e10cSrcweir         std::hash_multimap< sal_Unicode, rtl::OString >::const_iterator > range
3884*cdf0e10cSrcweir         =  m_aUnicodeToAdobename.equal_range( aChar );
3885*cdf0e10cSrcweir 
3886*cdf0e10cSrcweir     std::list< OString > aRet;
3887*cdf0e10cSrcweir     for( ; range.first != range.second; ++range.first )
3888*cdf0e10cSrcweir         aRet.push_back( range.first->second );
3889*cdf0e10cSrcweir 
3890*cdf0e10cSrcweir     if( aRet.begin() == aRet.end() && aChar != 0 )
3891*cdf0e10cSrcweir     {
3892*cdf0e10cSrcweir         sal_Char aBuf[8];
3893*cdf0e10cSrcweir         sal_Int32 nChars = snprintf( (char*)aBuf, sizeof( aBuf ), "uni%.4hX", aChar );
3894*cdf0e10cSrcweir         aRet.push_back( OString( aBuf, nChars ) );
3895*cdf0e10cSrcweir     }
3896*cdf0e10cSrcweir 
3897*cdf0e10cSrcweir     return aRet;
3898*cdf0e10cSrcweir }
3899*cdf0e10cSrcweir 
3900*cdf0e10cSrcweir // -------------------------------------------------------------------------
3901*cdf0e10cSrcweir std::list< sal_Unicode >  PrintFontManager::getUnicodeFromAdobeName( const rtl::OString& rName ) const
3902*cdf0e10cSrcweir {
3903*cdf0e10cSrcweir     std::pair< std::hash_multimap< rtl::OString, sal_Unicode, rtl::OStringHash >::const_iterator,
3904*cdf0e10cSrcweir         std::hash_multimap< rtl::OString, sal_Unicode, rtl::OStringHash >::const_iterator > range
3905*cdf0e10cSrcweir         =  m_aAdobenameToUnicode.equal_range( rName );
3906*cdf0e10cSrcweir 
3907*cdf0e10cSrcweir     std::list< sal_Unicode > aRet;
3908*cdf0e10cSrcweir     for( ; range.first != range.second; ++range.first )
3909*cdf0e10cSrcweir         aRet.push_back( range.first->second );
3910*cdf0e10cSrcweir 
3911*cdf0e10cSrcweir     if( aRet.begin() == aRet.end() )
3912*cdf0e10cSrcweir     {
3913*cdf0e10cSrcweir         if( rName.getLength() == 7 && rName.indexOf( "uni" ) == 0 )
3914*cdf0e10cSrcweir         {
3915*cdf0e10cSrcweir             sal_Unicode aCode = (sal_Unicode)rName.copy( 3 ).toInt32( 16 );
3916*cdf0e10cSrcweir             aRet.push_back( aCode );
3917*cdf0e10cSrcweir         }
3918*cdf0e10cSrcweir     }
3919*cdf0e10cSrcweir 
3920*cdf0e10cSrcweir     return aRet;
3921*cdf0e10cSrcweir }
3922*cdf0e10cSrcweir 
3923*cdf0e10cSrcweir // -------------------------------------------------------------------------
3924*cdf0e10cSrcweir namespace
3925*cdf0e10cSrcweir {
3926*cdf0e10cSrcweir     OUString getString( const Any& rAny )
3927*cdf0e10cSrcweir     {
3928*cdf0e10cSrcweir         OUString aStr;
3929*cdf0e10cSrcweir         rAny >>= aStr;
3930*cdf0e10cSrcweir         return aStr;
3931*cdf0e10cSrcweir     }
3932*cdf0e10cSrcweir     bool getBool( const Any& rAny )
3933*cdf0e10cSrcweir     {
3934*cdf0e10cSrcweir         sal_Bool bBool = sal_False;
3935*cdf0e10cSrcweir         rAny >>= bBool;
3936*cdf0e10cSrcweir         return static_cast<bool>(bBool);
3937*cdf0e10cSrcweir     }
3938*cdf0e10cSrcweir     sal_Int32 getInt( const Any& rAny )
3939*cdf0e10cSrcweir     {
3940*cdf0e10cSrcweir         sal_Int32 n = 0;
3941*cdf0e10cSrcweir         rAny >>= n;
3942*cdf0e10cSrcweir         return n;
3943*cdf0e10cSrcweir     }
3944*cdf0e10cSrcweir }
3945*cdf0e10cSrcweir bool PrintFontManager::readOverrideMetrics()
3946*cdf0e10cSrcweir {
3947*cdf0e10cSrcweir     if( ! m_aOverrideFonts.empty() )
3948*cdf0e10cSrcweir         return false;
3949*cdf0e10cSrcweir 
3950*cdf0e10cSrcweir     css::uno::Reference< XMultiServiceFactory > xFact( comphelper::getProcessServiceFactory() );
3951*cdf0e10cSrcweir     if( !xFact.is() )
3952*cdf0e10cSrcweir         return false;
3953*cdf0e10cSrcweir     css::uno::Reference< XMaterialHolder > xMat(
3954*cdf0e10cSrcweir                 xFact->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.psprint.CompatMetricOverride" ) ) ),
3955*cdf0e10cSrcweir                 UNO_QUERY );
3956*cdf0e10cSrcweir     if( !xMat.is() )
3957*cdf0e10cSrcweir         return false;
3958*cdf0e10cSrcweir 
3959*cdf0e10cSrcweir     Any aAny( xMat->getMaterial() );
3960*cdf0e10cSrcweir     Sequence< Any > aOverrideFonts;
3961*cdf0e10cSrcweir     if( ! (aAny >>= aOverrideFonts ) )
3962*cdf0e10cSrcweir         return false;
3963*cdf0e10cSrcweir     sal_Int32 nFonts = aOverrideFonts.getLength();
3964*cdf0e10cSrcweir     for( sal_Int32 i = 0; i < nFonts; i++ )
3965*cdf0e10cSrcweir     {
3966*cdf0e10cSrcweir         Sequence< NamedValue > aMetrics;
3967*cdf0e10cSrcweir         if( ! (aOverrideFonts.getConstArray()[i] >>= aMetrics) )
3968*cdf0e10cSrcweir             continue;
3969*cdf0e10cSrcweir         BuiltinFont* pFont = new BuiltinFont();
3970*cdf0e10cSrcweir         pFont->m_nDirectory = 0;
3971*cdf0e10cSrcweir         pFont->m_bUserOverride = false;
3972*cdf0e10cSrcweir         pFont->m_pMetrics = new PrintFontMetrics;
3973*cdf0e10cSrcweir         memset( pFont->m_pMetrics->m_aPages, 0xff, sizeof( pFont->m_pMetrics->m_aPages ) );
3974*cdf0e10cSrcweir         pFont->m_pMetrics->m_bKernPairsQueried = true;
3975*cdf0e10cSrcweir         sal_Int32 nProps = aMetrics.getLength();
3976*cdf0e10cSrcweir         const NamedValue* pProps = aMetrics.getConstArray();
3977*cdf0e10cSrcweir         for( sal_Int32 n = 0; n < nProps; n++ )
3978*cdf0e10cSrcweir         {
3979*cdf0e10cSrcweir             if( pProps[n].Name.equalsAscii( "FamilyName" ) )
3980*cdf0e10cSrcweir                 pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME,
3981*cdf0e10cSrcweir                                                           getString(pProps[n].Value),
3982*cdf0e10cSrcweir                                                           sal_True );
3983*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "PSName" ) )
3984*cdf0e10cSrcweir                 pFont->m_nPSName = m_pAtoms->getAtom( ATOM_PSNAME,
3985*cdf0e10cSrcweir                                                       getString(pProps[n].Value),
3986*cdf0e10cSrcweir                                                       sal_True );
3987*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "StyleName" ) )
3988*cdf0e10cSrcweir                 pFont->m_aStyleName = getString(pProps[n].Value);
3989*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "Italic" ) )
3990*cdf0e10cSrcweir                 pFont->m_eItalic = static_cast<italic::type>(getInt(pProps[n].Value));
3991*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "Width" ) )
3992*cdf0e10cSrcweir                 pFont->m_eWidth = static_cast<width::type>(getInt(pProps[n].Value));
3993*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "Weight" ) )
3994*cdf0e10cSrcweir                 pFont->m_eWeight = static_cast<weight::type>(getInt(pProps[n].Value));
3995*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "Pitch" ) )
3996*cdf0e10cSrcweir                 pFont->m_ePitch = static_cast<pitch::type>(getInt(pProps[n].Value));
3997*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "Encoding" ) )
3998*cdf0e10cSrcweir                 pFont->m_aEncoding = static_cast<rtl_TextEncoding>(getInt(pProps[n].Value));
3999*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "FontEncodingOnly" ) )
4000*cdf0e10cSrcweir                 pFont->m_bFontEncodingOnly = getBool(pProps[n].Value);
4001*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "GlobalMetricXWidth" ) )
4002*cdf0e10cSrcweir                 pFont->m_aGlobalMetricX.width = getInt(pProps[n].Value);
4003*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "GlobalMetricXHeight" ) )
4004*cdf0e10cSrcweir                 pFont->m_aGlobalMetricX.height = getInt(pProps[n].Value);
4005*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "GlobalMetricYWidth" ) )
4006*cdf0e10cSrcweir                 pFont->m_aGlobalMetricY.width = getInt(pProps[n].Value);
4007*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "GlobalMetricYHeight" ) )
4008*cdf0e10cSrcweir                 pFont->m_aGlobalMetricY.height = getInt(pProps[n].Value);
4009*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "Ascend" ) )
4010*cdf0e10cSrcweir                 pFont->m_nAscend = getInt(pProps[n].Value);
4011*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "Descend" ) )
4012*cdf0e10cSrcweir                 pFont->m_nDescend = getInt(pProps[n].Value);
4013*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "Leading" ) )
4014*cdf0e10cSrcweir                 pFont->m_nLeading = getInt(pProps[n].Value);
4015*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "XMin" ) )
4016*cdf0e10cSrcweir                 pFont->m_nXMin = getInt(pProps[n].Value);
4017*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "YMin" ) )
4018*cdf0e10cSrcweir                 pFont->m_nYMin = getInt(pProps[n].Value);
4019*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "XMax" ) )
4020*cdf0e10cSrcweir                 pFont->m_nXMax = getInt(pProps[n].Value);
4021*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "YMax" ) )
4022*cdf0e10cSrcweir                 pFont->m_nYMax = getInt(pProps[n].Value);
4023*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "VerticalSubstitutes" ) )
4024*cdf0e10cSrcweir                 pFont->m_bHaveVerticalSubstitutedGlyphs = getBool(pProps[n].Value);
4025*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "EncodingVector" ) )
4026*cdf0e10cSrcweir             {
4027*cdf0e10cSrcweir                 Sequence< NamedValue > aEncoding;
4028*cdf0e10cSrcweir                 pProps[n].Value >>= aEncoding;
4029*cdf0e10cSrcweir                 sal_Int32 nEnc = aEncoding.getLength();
4030*cdf0e10cSrcweir                 const NamedValue* pEnc = aEncoding.getConstArray();
4031*cdf0e10cSrcweir                 for( sal_Int32 m = 0; m < nEnc; m++ )
4032*cdf0e10cSrcweir                 {
4033*cdf0e10cSrcweir                     sal_Unicode cCode = *pEnc[m].Name.getStr();
4034*cdf0e10cSrcweir                     sal_Int32 nGlyph = getInt(pEnc[m].Value);
4035*cdf0e10cSrcweir                     pFont->m_aEncodingVector[ cCode ] = nGlyph;
4036*cdf0e10cSrcweir                 }
4037*cdf0e10cSrcweir             }
4038*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "NonEncoded" ) )
4039*cdf0e10cSrcweir             {
4040*cdf0e10cSrcweir                 Sequence< NamedValue > aEncoding;
4041*cdf0e10cSrcweir                 pProps[n].Value >>= aEncoding;
4042*cdf0e10cSrcweir                 sal_Int32 nEnc = aEncoding.getLength();
4043*cdf0e10cSrcweir                 const NamedValue* pEnc = aEncoding.getConstArray();
4044*cdf0e10cSrcweir                 for( sal_Int32 m = 0; m < nEnc; m++ )
4045*cdf0e10cSrcweir                 {
4046*cdf0e10cSrcweir                     sal_Unicode cCode = *pEnc[m].Name.getStr();
4047*cdf0e10cSrcweir                     OUString aGlyphName( getString(pEnc[m].Value) );
4048*cdf0e10cSrcweir                     pFont->m_aNonEncoded[ cCode ] = OUStringToOString(aGlyphName,RTL_TEXTENCODING_ASCII_US);
4049*cdf0e10cSrcweir                 }
4050*cdf0e10cSrcweir             }
4051*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "CharacterMetrics" ) )
4052*cdf0e10cSrcweir             {
4053*cdf0e10cSrcweir                 // fill pFont->m_pMetrics->m_aMetrics
4054*cdf0e10cSrcweir                 // expect triples of int: int -> CharacterMetric.{ width, height }
4055*cdf0e10cSrcweir                 Sequence< sal_Int32 > aSeq;
4056*cdf0e10cSrcweir                 pProps[n].Value >>= aSeq;
4057*cdf0e10cSrcweir                 sal_Int32 nInts = aSeq.getLength();
4058*cdf0e10cSrcweir                 const sal_Int32* pInts = aSeq.getConstArray();
4059*cdf0e10cSrcweir                 for( sal_Int32 m = 0; m < nInts; m+=3 )
4060*cdf0e10cSrcweir                 {
4061*cdf0e10cSrcweir                     pFont->m_pMetrics->m_aMetrics[ pInts[m] ].width = static_cast<short int>(pInts[m+1]);
4062*cdf0e10cSrcweir                     pFont->m_pMetrics->m_aMetrics[ pInts[m] ].height = static_cast<short int>(pInts[m+2]);
4063*cdf0e10cSrcweir                 }
4064*cdf0e10cSrcweir             }
4065*cdf0e10cSrcweir             else if( pProps[n].Name.equalsAscii( "XKernPairs" ) )
4066*cdf0e10cSrcweir             {
4067*cdf0e10cSrcweir                 // fill pFont->m_pMetrics->m_aXKernPairs
4068*cdf0e10cSrcweir                 // expection name: <unicode1><unicode2> value: ((height << 16)| width)
4069*cdf0e10cSrcweir                 Sequence< NamedValue > aKern;
4070*cdf0e10cSrcweir                 pProps[n].Value >>= aKern;
4071*cdf0e10cSrcweir                 KernPair aPair;
4072*cdf0e10cSrcweir                 const NamedValue* pVals = aKern.getConstArray();
4073*cdf0e10cSrcweir                 int nPairs = aKern.getLength();
4074*cdf0e10cSrcweir                 for( int m = 0; m < nPairs; m++ )
4075*cdf0e10cSrcweir                 {
4076*cdf0e10cSrcweir                     if( pVals[m].Name.getLength() == 2 )
4077*cdf0e10cSrcweir                     {
4078*cdf0e10cSrcweir                         aPair.first = pVals[m].Name.getStr()[0];
4079*cdf0e10cSrcweir                         aPair.second = pVals[m].Name.getStr()[1];
4080*cdf0e10cSrcweir                         sal_Int32 nKern = getInt( pVals[m].Value );
4081*cdf0e10cSrcweir                         aPair.kern_x = static_cast<short int>(nKern & 0xffff);
4082*cdf0e10cSrcweir                         aPair.kern_y = static_cast<short int>((sal_uInt32(nKern) >> 16) & 0xffff);
4083*cdf0e10cSrcweir                         pFont->m_pMetrics->m_aXKernPairs.push_back( aPair );
4084*cdf0e10cSrcweir                     }
4085*cdf0e10cSrcweir                 }
4086*cdf0e10cSrcweir             }
4087*cdf0e10cSrcweir         }
4088*cdf0e10cSrcweir         // sanity check
4089*cdf0e10cSrcweir         if( pFont->m_nPSName                        &&
4090*cdf0e10cSrcweir             pFont->m_nFamilyName                    &&
4091*cdf0e10cSrcweir             ! pFont->m_pMetrics->m_aMetrics.empty() )
4092*cdf0e10cSrcweir         {
4093*cdf0e10cSrcweir             m_aOverrideFonts.push_back( m_nNextFontID );
4094*cdf0e10cSrcweir             m_aFonts[ m_nNextFontID++ ] = pFont;
4095*cdf0e10cSrcweir         }
4096*cdf0e10cSrcweir         else
4097*cdf0e10cSrcweir         {
4098*cdf0e10cSrcweir             DBG_ASSERT( 0, "override font failed" );
4099*cdf0e10cSrcweir             delete pFont;
4100*cdf0e10cSrcweir         }
4101*cdf0e10cSrcweir     }
4102*cdf0e10cSrcweir 
4103*cdf0e10cSrcweir     return true;
4104*cdf0e10cSrcweir }
4105