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