1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
35 #include <osl/thread.h>
37 #include "unotools/atom.hxx"
39 #include "vcl/fontmanager.hxx"
40 #include "vcl/fontcache.hxx"
41 #include "vcl/fontcache.hxx"
42 #include "vcl/fontsubset.hxx"
43 #include "vcl/strhelper.hxx"
44 #include "vcl/ppdparser.hxx"
45 #include "vcl/svdata.hxx"
46 #include "vcl/salinst.hxx"
48 #include "tools/urlobj.hxx"
49 #include "tools/stream.hxx"
50 #include "tools/debug.hxx"
51 #include "tools/config.hxx"
53 #include "osl/file.hxx"
54 #include "osl/process.h"
56 #include "rtl/tencinfo.h"
57 #include "rtl/ustrbuf.hxx"
58 #include "rtl/strbuf.hxx"
60 #include "i18npool/mslangid.hxx"
63 #include "parseAFM.hxx"
66 #if OSL_DEBUG_LEVEL > 1
67 #include <sys/times.h>
71 #include "sal/alloca.h"
77 #include "adobeenc.tab" // get encoding table for AFM metrics
79 #ifdef CALLGRIND_COMPILE
80 #include <valgrind/callgrind.h>
83 #include "comphelper/processfactory.hxx"
84 #include "com/sun/star/beans/XMaterialHolder.hpp"
85 #include "com/sun/star/beans/NamedValue.hpp"
87 #define PRINTER_METRICDIR "fontmetric"
94 using namespace com::sun::star::uno
;
95 using namespace com::sun::star::beans
;
96 using namespace com::sun::star::lang
;
102 inline sal_uInt16
getUInt16BE( const sal_uInt8
*& pBuffer
)
104 sal_uInt16 nRet
= (sal_uInt16
)pBuffer
[1] |
105 (((sal_uInt16
)pBuffer
[0]) << 8);
110 inline sal_uInt32
getUInt32BE( const sal_uInt8
*& pBuffer
)
112 sal_uInt32 nRet
= (((sal_uInt32
)pBuffer
[0]) << 24) |
113 (((sal_uInt32
)pBuffer
[1]) << 16) |
114 (((sal_uInt32
)pBuffer
[2]) << 8) |
115 (((sal_uInt32
)pBuffer
[3]) );
120 static italic::type
parseItalic( const ByteString
& rItalic
)
122 italic::type eItalic
= italic::Unknown
;
123 if( rItalic
.EqualsIgnoreCaseAscii( "i" ) )
124 eItalic
= italic::Italic
;
125 else if( rItalic
.EqualsIgnoreCaseAscii( "o" ) )
126 eItalic
= italic::Oblique
;
128 eItalic
= italic::Upright
;
132 // -------------------------------------------------------------------------
134 static weight::type
parseWeight( const ByteString
& rWeight
)
136 weight::type eWeight
= weight::Unknown
;
137 if( rWeight
.Search( "bold" ) != STRING_NOTFOUND
)
139 if( rWeight
.Search( "emi" ) != STRING_NOTFOUND
) // semi, demi
140 eWeight
= weight::SemiBold
;
141 else if( rWeight
.Search( "ultra" ) != STRING_NOTFOUND
)
142 eWeight
= weight::UltraBold
;
144 eWeight
= weight::Bold
;
146 else if( rWeight
.Search( "heavy" ) != STRING_NOTFOUND
)
147 eWeight
= weight::Bold
;
148 else if( rWeight
.Search( "light" ) != STRING_NOTFOUND
)
150 if( rWeight
.Search( "emi" ) != STRING_NOTFOUND
) // semi, demi
151 eWeight
= weight::SemiLight
;
152 else if( rWeight
.Search( "ultra" ) != STRING_NOTFOUND
)
153 eWeight
= weight::UltraLight
;
155 eWeight
= weight::Light
;
157 else if( rWeight
.Search( "black" ) != STRING_NOTFOUND
)
158 eWeight
= weight::Black
;
159 else if( rWeight
.Equals( "demi" ) )
160 eWeight
= weight::SemiBold
;
161 else if( rWeight
.Equals( "book" ) ||
162 rWeight
.Equals( "semicondensed" ) )
163 eWeight
= weight::Light
;
164 else if( rWeight
.Equals( "medium" ) || rWeight
.Equals( "roman" ) )
165 eWeight
= weight::Medium
;
167 eWeight
= weight::Normal
;
171 // -------------------------------------------------------------------------
173 static width::type
parseWidth( const ByteString
& rWidth
)
175 width::type eWidth
= width::Unknown
;
176 if( rWidth
.Equals( "bold" ) ||
177 rWidth
.Equals( "semiexpanded" ) )
178 eWidth
= width::SemiExpanded
;
179 else if( rWidth
.Equals( "condensed" ) ||
180 rWidth
.Equals( "narrow" ) )
181 eWidth
= width::Condensed
;
182 else if( rWidth
.Equals( "double wide" ) ||
183 rWidth
.Equals( "extraexpanded" ) ||
184 rWidth
.Equals( "ultraexpanded" ) )
185 eWidth
= width::UltraExpanded
;
186 else if( rWidth
.Equals( "expanded" ) ||
187 rWidth
.Equals( "wide" ) )
188 eWidth
= width::Expanded
;
189 else if( rWidth
.Equals( "extracondensed" ) )
190 eWidth
= width::ExtraCondensed
;
191 else if( rWidth
.Equals( "semicondensed" ) )
192 eWidth
= width::SemiCondensed
;
193 else if( rWidth
.Equals( "ultracondensed" ) )
194 eWidth
= width::UltraCondensed
;
196 eWidth
= width::Normal
;
201 // -------------------------------------------------------------------------
202 bool PrintFontManager::XLFDEntry::operator<(const PrintFontManager::XLFDEntry
& rRight
) const
205 if( (nMask
& MaskFamily
) && (rRight
.nMask
& MaskFamily
) )
207 nCmp
= rtl_str_compareIgnoreAsciiCase_WithLength( aFamily
.pData
->buffer
,
208 aFamily
.pData
->length
,
209 rRight
.aFamily
.pData
->buffer
,
210 rRight
.aFamily
.pData
->length
);
215 if( (nMask
& MaskFoundry
) && (rRight
.nMask
& MaskFoundry
) )
217 nCmp
= rtl_str_compareIgnoreAsciiCase_WithLength( aFoundry
.pData
->buffer
,
218 aFoundry
.pData
->length
,
219 rRight
.aFoundry
.pData
->buffer
,
220 rRight
.aFoundry
.pData
->length
);
225 if( (nMask
& MaskItalic
) && (rRight
.nMask
& MaskItalic
) )
227 if( eItalic
!= rRight
.eItalic
)
228 return (int)eItalic
< (int)rRight
.eItalic
;
231 if( (nMask
& MaskWeight
) && (rRight
.nMask
& MaskWeight
) )
233 if( eWeight
!= rRight
.eWeight
)
234 return (int)eWeight
< (int)rRight
.eWeight
;
237 if( (nMask
& MaskWidth
) && (rRight
.nMask
& MaskWidth
) )
239 if( eWidth
!= rRight
.eWidth
)
240 return (int)eWidth
< (int)rRight
.eWidth
;
243 if( (nMask
& MaskPitch
) && (rRight
.nMask
& MaskPitch
) )
245 if( ePitch
!= rRight
.ePitch
)
246 return (int)ePitch
< (int)rRight
.ePitch
;
249 if( (nMask
& MaskAddStyle
) && (rRight
.nMask
& MaskAddStyle
) )
251 nCmp
= rtl_str_compareIgnoreAsciiCase_WithLength( aAddStyle
.pData
->buffer
,
252 aAddStyle
.pData
->length
,
253 rRight
.aAddStyle
.pData
->buffer
,
254 rRight
.aAddStyle
.pData
->length
);
259 if( (nMask
& MaskEncoding
) && (rRight
.nMask
& MaskEncoding
) )
261 if( aEncoding
!= rRight
.aEncoding
)
262 return aEncoding
< rRight
.aEncoding
;
268 bool PrintFontManager::XLFDEntry::operator==(const PrintFontManager::XLFDEntry
& rRight
) const
271 if( (nMask
& MaskFamily
) && (rRight
.nMask
& MaskFamily
) )
273 nCmp
= rtl_str_compareIgnoreAsciiCase_WithLength( aFamily
.pData
->buffer
,
274 aFamily
.pData
->length
,
275 rRight
.aFamily
.pData
->buffer
,
276 rRight
.aFamily
.pData
->length
);
281 if( (nMask
& MaskFoundry
) && (rRight
.nMask
& MaskFoundry
) )
283 nCmp
= rtl_str_compareIgnoreAsciiCase_WithLength( aFoundry
.pData
->buffer
,
284 aFoundry
.pData
->length
,
285 rRight
.aFoundry
.pData
->buffer
,
286 rRight
.aFoundry
.pData
->length
);
291 if( (nMask
& MaskItalic
) && (rRight
.nMask
& MaskItalic
) )
293 if( eItalic
!= rRight
.eItalic
)
297 if( (nMask
& MaskWeight
) && (rRight
.nMask
& MaskWeight
) )
299 if( eWeight
!= rRight
.eWeight
)
303 if( (nMask
& MaskWidth
) && (rRight
.nMask
& MaskWidth
) )
305 if( eWidth
!= rRight
.eWidth
)
309 if( (nMask
& MaskPitch
) && (rRight
.nMask
& MaskPitch
) )
311 if( ePitch
!= rRight
.ePitch
)
315 if( (nMask
& MaskAddStyle
) && (rRight
.nMask
& MaskAddStyle
) )
317 nCmp
= rtl_str_compareIgnoreAsciiCase_WithLength( aAddStyle
.pData
->buffer
,
318 aAddStyle
.pData
->length
,
319 rRight
.aAddStyle
.pData
->buffer
,
320 rRight
.aAddStyle
.pData
->length
);
325 if( (nMask
& MaskEncoding
) && (rRight
.nMask
& MaskEncoding
) )
327 if( aEncoding
!= rRight
.aEncoding
)
335 * PrintFont implementations
337 PrintFontManager::PrintFont::PrintFont( fonttype::type eType
) :
341 m_eItalic( italic::Unknown
),
342 m_eWidth( width::Unknown
),
343 m_eWeight( weight::Unknown
),
344 m_ePitch( pitch::Unknown
),
345 m_aEncoding( RTL_TEXTENCODING_DONTKNOW
),
346 m_bFontEncodingOnly( false ),
355 m_bHaveVerticalSubstitutedGlyphs( false ),
356 m_bUserOverride( false ),
357 m_eEmbeddedbitmap( fcstatus::isunset
),
358 m_eAntialias( fcstatus::isunset
)
362 // -------------------------------------------------------------------------
364 PrintFontManager::PrintFont::~PrintFont()
370 // -------------------------------------------------------------------------
372 PrintFontManager::Type1FontFile::~Type1FontFile()
376 // -------------------------------------------------------------------------
378 PrintFontManager::TrueTypeFontFile::TrueTypeFontFile()
379 : PrintFont( fonttype::TrueType
)
381 , m_nCollectionEntry(-1)
382 , m_nTypeFlags( TYPEFLAG_INVALID
)
385 // -------------------------------------------------------------------------
387 PrintFontManager::TrueTypeFontFile::~TrueTypeFontFile()
391 // -------------------------------------------------------------------------
393 PrintFontManager::BuiltinFont::~BuiltinFont()
397 // -------------------------------------------------------------------------
399 bool PrintFontManager::Type1FontFile::queryMetricPage( int /*nPage*/, MultiAtomProvider
* pProvider
)
401 return readAfmMetrics( PrintFontManager::get().getAfmFile( this ), pProvider
, false, false );
404 // -------------------------------------------------------------------------
406 bool PrintFontManager::BuiltinFont::queryMetricPage( int /*nPage*/, MultiAtomProvider
* pProvider
)
408 return readAfmMetrics( PrintFontManager::get().getAfmFile( this ), pProvider
, false, false );
411 // -------------------------------------------------------------------------
413 bool PrintFontManager::TrueTypeFontFile::queryMetricPage( int nPage
, MultiAtomProvider
* pProvider
)
415 bool bSuccess
= false;
417 ByteString
aFile( PrintFontManager::get().getFontFile( this ) );
419 TrueTypeFont
* pTTFont
= NULL
;
421 if( OpenTTFontFile( aFile
.GetBuffer(), m_nCollectionEntry
< 0 ? 0 : m_nCollectionEntry
, &pTTFont
) == SF_OK
)
425 m_pMetrics
= new PrintFontMetrics
;
426 memset (m_pMetrics
->m_aPages
, 0, sizeof(m_pMetrics
->m_aPages
));
428 m_pMetrics
->m_aPages
[ nPage
/8 ] |= (1 << ( nPage
& 7 ));
430 sal_uInt16 table
[256], table_vert
[256];
432 for( i
= 0; i
< 256; i
++ )
433 table
[ i
] = 256*nPage
+ i
;
435 int nCharacters
= nPage
< 255 ? 256 : 254;
436 MapString( pTTFont
, table
, nCharacters
, NULL
, 0 );
437 TTSimpleGlyphMetrics
* pMetrics
= GetTTSimpleCharMetrics( pTTFont
, nPage
*256, nCharacters
, 0 );
440 for( i
= 0; i
< nCharacters
; i
++ )
444 CharacterMetric
& rChar
= m_pMetrics
->m_aMetrics
[ nPage
*256 + i
];
445 rChar
.width
= pMetrics
[ i
].adv
;
446 rChar
.height
= m_aGlobalMetricX
.height
;
453 for( i
= 0; i
< 256; i
++ )
454 table_vert
[ i
] = 256*nPage
+ i
;
455 MapString( pTTFont
, table_vert
, nCharacters
, NULL
, 1 );
456 pMetrics
= GetTTSimpleCharMetrics( pTTFont
, nPage
*256, nCharacters
, 1 );
459 for( i
= 0; i
< nCharacters
; i
++ )
463 CharacterMetric
& rChar
= m_pMetrics
->m_aMetrics
[ nPage
*256 + i
+ ( 1 << 16 ) ];
464 rChar
.width
= m_aGlobalMetricY
.width
;
465 rChar
.height
= pMetrics
[ i
].adv
;
466 if( table_vert
[i
] != table
[i
] )
467 m_pMetrics
->m_bVerticalSubstitutions
[ nPage
*256 + i
] = 1;
473 if( ! m_pMetrics
->m_bKernPairsQueried
)
475 m_pMetrics
->m_bKernPairsQueried
= true;
476 // this is really a hack
477 // in future MapString/KernGlyphs should be used
478 // but vcl is not in a state where that could be used
479 // so currently we get kernpairs by accessing the raw data
480 struct _TrueTypeFont
* pImplTTFont
= (struct _TrueTypeFont
*)pTTFont
;
482 //-----------------------------------------------------------------
483 // Kerning: KT_MICROSOFT
484 //-----------------------------------------------------------------
485 if( pImplTTFont
->nkern
&& pImplTTFont
->kerntype
== KT_MICROSOFT
)
487 // create a glyph -> character mapping
488 ::std::hash_map
< sal_uInt16
, sal_Unicode
> aGlyphMap
;
489 ::std::hash_map
< sal_uInt16
, sal_Unicode
>::iterator left
, right
;
490 for( i
= 21; i
< 0xfffd; i
++ )
492 sal_uInt16 nGlyph
= MapChar( pTTFont
, (sal_Unicode
)i
, 0 ); // kerning for horz only
494 aGlyphMap
[ nGlyph
] = (sal_Unicode
)i
;
499 for( i
= 0; i
< (int)pImplTTFont
->nkern
; i
++ )
501 const sal_uInt8
* pTable
= pImplTTFont
->kerntables
[i
];
503 /*sal_uInt16 nVersion =*/ getUInt16BE( pTable
);
504 /*sal_uInt16 nLength =*/ getUInt16BE( pTable
);
505 sal_uInt16 nCoverage
= getUInt16BE( pTable
);
509 switch( nCoverage
>> 8 )
513 sal_uInt16 nPairs
= getUInt16BE( pTable
);
515 for( int n
= 0; n
< nPairs
; n
++ )
517 sal_uInt16 nLeftGlyph
= getUInt16BE( pTable
);
518 sal_uInt16 nRightGlyph
= getUInt16BE( pTable
);
519 sal_Int16 nKern
= (sal_Int16
)getUInt16BE( pTable
);
521 left
= aGlyphMap
.find( nLeftGlyph
);
522 right
= aGlyphMap
.find( nRightGlyph
);
523 if( left
!= aGlyphMap
.end() && right
!= aGlyphMap
.end() )
525 aPair
.first
= left
->second
;
526 aPair
.second
= right
->second
;
527 switch( nCoverage
& 1 )
530 aPair
.kern_x
= (int)nKern
* 1000 / pImplTTFont
->unitsPerEm
;
531 m_pMetrics
->m_aXKernPairs
.push_back( aPair
);
534 aPair
.kern_y
= (int)nKern
* 1000 / pImplTTFont
->unitsPerEm
;
535 m_pMetrics
->m_aYKernPairs
.push_back( aPair
);
545 const sal_uInt8
* pSubTable
= pTable
;
546 /*sal_uInt16 nRowWidth =*/ getUInt16BE( pTable
);
547 sal_uInt16 nOfLeft
= getUInt16BE( pTable
);
548 sal_uInt16 nOfRight
= getUInt16BE( pTable
);
549 /*sal_uInt16 nOfArray =*/ getUInt16BE( pTable
);
550 const sal_uInt8
* pTmp
= pSubTable
+ nOfLeft
;
551 sal_uInt16 nFirstLeft
= getUInt16BE( pTmp
);
552 sal_uInt16 nLastLeft
= getUInt16BE( pTmp
) + nFirstLeft
- 1;
553 pTmp
= pSubTable
+ nOfRight
;
554 sal_uInt16 nFirstRight
= getUInt16BE( pTmp
);
555 sal_uInt16 nLastRight
= getUInt16BE( pTmp
) + nFirstRight
-1;
557 // int nPairs = (int)(nLastLeft-nFirstLeft+1)*(int)(nLastRight-nFirstRight+1);
558 for( aPair
.first
= nFirstLeft
; aPair
.first
< nLastLeft
; aPair
.first
++ )
560 for( aPair
.second
= 0; aPair
.second
< nLastRight
; aPair
.second
++ )
562 sal_Int16 nKern
= (sal_Int16
)getUInt16BE( pTmp
);
563 switch( nCoverage
& 1 )
566 aPair
.kern_x
= (int)nKern
* 1000 / pImplTTFont
->unitsPerEm
;
567 m_pMetrics
->m_aXKernPairs
.push_back( aPair
);
570 aPair
.kern_y
= (int)nKern
* 1000 / pImplTTFont
->unitsPerEm
;
571 m_pMetrics
->m_aYKernPairs
.push_back( aPair
);
582 //-----------------------------------------------------------------
583 // Kerning: KT_APPLE_NEW
584 //-----------------------------------------------------------------
585 if( pImplTTFont
->nkern
&& pImplTTFont
->kerntype
== KT_APPLE_NEW
)
587 // create a glyph -> character mapping
588 ::std::hash_map
< sal_uInt16
, sal_Unicode
> aGlyphMap
;
589 ::std::hash_map
< sal_uInt16
, sal_Unicode
>::iterator left
, right
;
590 for( i
= 21; i
< 0xfffd; i
++ )
592 sal_uInt16 nGlyph
= MapChar( pTTFont
, (sal_Unicode
)i
, 0 ); // kerning for horz only
594 aGlyphMap
[ nGlyph
] = (sal_Unicode
)i
;
597 // Loop through each of the 'kern' subtables
599 for( i
= 0; (unsigned int)i
< pImplTTFont
->nkern
; i
++ )
601 const sal_uInt8
* pTable
= pImplTTFont
->kerntables
[i
];
603 /*sal_uInt32 nLength =*/ getUInt32BE( pTable
);
604 sal_uInt16 nCoverage
= getUInt16BE( pTable
);
605 /*sal_uInt16 nTupleIndex =*/ getUInt16BE( pTable
);
608 // sal_Bool bKernVertical = nCoverage & 0x8000;
609 // sal_Bool bKernCrossStream = nCoverage & 0x4000;
610 // sal_Bool bKernVariation = nCoverage & 0x2000;
612 // Kerning sub-table format, 0 through 3
613 sal_uInt8 nSubTableFormat
= nCoverage
& 0x00FF;
617 switch( nSubTableFormat
)
621 // Grab the # of kern pairs but skip over the:
625 sal_uInt16 nPairs
= getUInt16BE( pTable
);
628 for( int n
= 0; n
< nPairs
; n
++ )
630 sal_uInt16 nLeftGlyph
= getUInt16BE( pTable
);
631 sal_uInt16 nRightGlyph
= getUInt16BE( pTable
);
632 sal_Int16 nKern
= (sal_Int16
)getUInt16BE( pTable
);
634 left
= aGlyphMap
.find( nLeftGlyph
);
635 right
= aGlyphMap
.find( nRightGlyph
);
636 if( left
!= aGlyphMap
.end() && right
!= aGlyphMap
.end() )
638 aPair
.first
= left
->second
;
639 aPair
.second
= right
->second
;
641 // Only support horizontal kerning for now
642 aPair
.kern_x
= (int)nKern
* 1000 / pImplTTFont
->unitsPerEm
;
644 m_pMetrics
->m_aXKernPairs
.push_back( aPair
);
646 /* switch( nCoverage & 1 )
649 aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
650 m_pMetrics->m_aXKernPairs.push_back( aPair );
653 aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
654 m_pMetrics->m_aYKernPairs.push_back( aPair );
665 const sal_uInt8
* pSubTable
= pTable
;
666 /*sal_uInt16 nRowWidth =*/ getUInt16BE( pTable
);
667 sal_uInt16 nOfLeft
= getUInt16BE( pTable
);
668 sal_uInt16 nOfRight
= getUInt16BE( pTable
);
669 /*sal_uInt16 nOfArray =*/ getUInt16BE( pTable
);
670 const sal_uInt8
* pTmp
= pSubTable
+ nOfLeft
;
671 sal_uInt16 nFirstLeft
= getUInt16BE( pTmp
);
672 sal_uInt16 nLastLeft
= getUInt16BE( pTmp
) + nFirstLeft
- 1;
673 pTmp
= pSubTable
+ nOfRight
;
674 sal_uInt16 nFirstRight
= getUInt16BE( pTmp
);
675 sal_uInt16 nLastRight
= getUInt16BE( pTmp
) + nFirstRight
-1;
677 for( aPair
.first
= nFirstLeft
; aPair
.first
< nLastLeft
; aPair
.first
++ )
679 for( aPair
.second
= 0; aPair
.second
< nLastRight
; aPair
.second
++ )
681 sal_Int16 nKern
= (sal_Int16
)getUInt16BE( pTmp
);
682 switch( nCoverage
& 1 )
685 aPair
.kern_x
= (int)nKern
* 1000 / pImplTTFont
->unitsPerEm
;
686 m_pMetrics
->m_aXKernPairs
.push_back( aPair
);
689 aPair
.kern_y
= (int)nKern
* 1000 / pImplTTFont
->unitsPerEm
;
690 m_pMetrics
->m_aYKernPairs
.push_back( aPair
);
699 fprintf( stderr
, "Found unsupported Apple-style kern subtable type %d.\n", nSubTableFormat
);
705 #if OSL_DEBUG_LEVEL > 1
706 fprintf( stderr
, "found %d/%d kern pairs for %s\n",
707 m_pMetrics
->m_aXKernPairs
.size(),
708 m_pMetrics
->m_aYKernPairs
.size(),
709 OUStringToOString( pProvider
->getString( ATOM_FAMILYNAME
, m_nFamilyName
), RTL_TEXTENCODING_MS_1252
).getStr() );
711 (void) pProvider
; /* avoid warnings */
715 CloseTTFont( pTTFont
);
721 // -------------------------------------------------------------------------
723 /* #i73387# There seem to be fonts with a rather unwell chosen family name
724 * consider e.g. "Helvetica Narrow" which defines its family as "Helvetica"
725 * It can really only be distinguished by its PSName and FullName. Both of
726 * which are not user presentable in OOo. So replace it by something sensible.
728 * If other fonts feature this behaviour, insert them to the map.
730 static bool familyNameOverride( const OUString
& i_rPSname
, OUString
& o_rFamilyName
)
732 static std::hash_map
< OUString
, OUString
, OUStringHash
> aPSNameToFamily( 16 );
733 if( aPSNameToFamily
.empty() ) // initialization
735 aPSNameToFamily
[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow" ) ) ] =
736 OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
737 aPSNameToFamily
[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-Bold" ) ) ] =
738 OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
739 aPSNameToFamily
[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-BoldOblique" ) ) ] =
740 OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
741 aPSNameToFamily
[ OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica-Narrow-Oblique" ) ) ] =
742 OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica Narrow" ) );
744 std::hash_map
<OUString
,OUString
,OUStringHash
>::const_iterator it
=
745 aPSNameToFamily
.find( i_rPSname
);
746 bool bReplaced
= (it
!= aPSNameToFamily
.end() );
748 o_rFamilyName
= it
->second
;
752 bool PrintFontManager::PrintFont::readAfmMetrics( const OString
& rFileName
, MultiAtomProvider
* pProvider
, bool bFillEncodingvector
, bool bOnlyGlobalAttributes
)
754 PrintFontManager
& rManager( PrintFontManager::get() );
757 FontInfo
* pInfo
= NULL
;
758 parseFile( rFileName
.getStr(), &pInfo
, P_ALL
);
759 if( ! pInfo
|| ! pInfo
->numOfChars
)
762 freeFontInfo( pInfo
);
766 m_aEncodingVector
.clear();
767 // fill in global info
770 OUString
aPSName( OStringToOUString( pInfo
->gfi
->fontName
, RTL_TEXTENCODING_ISO_8859_1
) );
771 m_nPSName
= pProvider
->getAtom( ATOM_PSNAME
, aPSName
, sal_True
);
773 // family name (if not already set)
775 if( ! m_nFamilyName
)
777 aFamily
= OStringToOUString( pInfo
->gfi
->familyName
, RTL_TEXTENCODING_ISO_8859_1
);
778 if( ! aFamily
.getLength() )
780 aFamily
= OStringToOUString( pInfo
->gfi
->fontName
, RTL_TEXTENCODING_ISO_8859_1
);
781 sal_Int32 nIndex
= 0;
782 aFamily
= aFamily
.getToken( 0, '-', nIndex
);
784 familyNameOverride( aPSName
, aFamily
);
785 m_nFamilyName
= pProvider
->getAtom( ATOM_FAMILYNAME
, aFamily
, sal_True
);
788 aFamily
= pProvider
->getString( ATOM_FAMILYNAME
, m_nFamilyName
);
790 // style name: if fullname begins with family name
791 // interpret the rest of fullname as style
792 if( ! m_aStyleName
.getLength() && pInfo
->gfi
->fullName
&& *pInfo
->gfi
->fullName
)
794 OUString
aFullName( OStringToOUString( pInfo
->gfi
->fullName
, RTL_TEXTENCODING_ISO_8859_1
) );
795 if( aFullName
.indexOf( aFamily
) == 0 )
796 m_aStyleName
= WhitespaceToSpace( aFullName
.copy( aFamily
.getLength() ) );
800 if( pInfo
->gfi
->italicAngle
> 0 )
801 m_eItalic
= italic::Oblique
;
802 else if( pInfo
->gfi
->italicAngle
< 0 )
803 m_eItalic
= italic::Italic
;
805 m_eItalic
= italic::Upright
;
808 ByteString
aLowerWeight( pInfo
->gfi
->weight
);
809 aLowerWeight
.ToLowerAscii();
810 m_eWeight
= parseWeight( aLowerWeight
);
813 m_ePitch
= pInfo
->gfi
->isFixedPitch
? pitch::Fixed
: pitch::Variable
;
815 // encoding - only set if unknown
816 int nAdobeEncoding
= 0;
817 if( pInfo
->gfi
->encodingScheme
)
819 if( !strcmp( pInfo
->gfi
->encodingScheme
, "AdobeStandardEncoding" ) )
821 else if( !strcmp( pInfo
->gfi
->encodingScheme
, "ISO10646-1" ) )
824 m_aEncoding
= RTL_TEXTENCODING_UNICODE
;
826 else if( !strcmp( pInfo
->gfi
->encodingScheme
, "Symbol") )
828 else if( !strcmp( pInfo
->gfi
->encodingScheme
, "FontSpecific") )
831 if( m_aEncoding
== RTL_TEXTENCODING_DONTKNOW
)
832 m_aEncoding
= nAdobeEncoding
== 1 ?
833 RTL_TEXTENCODING_ADOBE_STANDARD
: RTL_TEXTENCODING_SYMBOL
;
835 else if( m_aEncoding
== RTL_TEXTENCODING_DONTKNOW
)
836 m_aEncoding
= RTL_TEXTENCODING_ADOBE_STANDARD
;
838 // try to parse the font name and decide wether it might be a
839 // japanese font. Who invented this PITA ?
840 OUString
aPSNameLastToken( aPSName
.copy( aPSName
.lastIndexOf( '-' )+1 ) );
841 if( ! aPSNameLastToken
.compareToAscii( "H" ) ||
842 ! aPSNameLastToken
.compareToAscii( "V" ) )
844 static const char* pEncs
[] =
850 static const rtl_TextEncoding aEncs
[] =
852 RTL_TEXTENCODING_EUC_JP
,
853 RTL_TEXTENCODING_SHIFT_JIS
,
854 RTL_TEXTENCODING_JIS_X_0208
857 for( unsigned int enc
= 0; enc
< sizeof( aEncs
)/sizeof(aEncs
[0]) && m_aEncoding
== RTL_TEXTENCODING_DONTKNOW
; enc
++ )
859 sal_Int32 nIndex
= 0, nOffset
= 1;
862 OUString
aToken( aPSName
.getToken( nOffset
, '-', nIndex
) );
866 if( ! aToken
.compareToAscii( pEncs
[enc
] ) )
868 m_aEncoding
= aEncs
[ enc
];
869 m_bFontEncodingOnly
= true;
871 } while( nIndex
!= -1 );
875 if( m_aEncoding
== RTL_TEXTENCODING_DONTKNOW
)
876 m_aEncoding
= RTL_TEXTENCODING_JIS_X_0208
;
877 #if OSL_DEBUG_LEVEL > 1
878 fprintf( stderr
, "Encoding %d for %s\n", m_aEncoding
, pInfo
->gfi
->fontName
);
882 // hack for GB encoded builtin fonts posing as FontSpecific
883 if( m_eType
== fonttype::Builtin
&& ( nAdobeEncoding
== 3 || nAdobeEncoding
== 0 ) )
885 int nLen
= aFamily
.getLength();
887 aFamily
.getStr()[ nLen
-2 ] == 'G' &&
888 aFamily
.getStr()[ nLen
-1 ] == 'B' &&
889 pInfo
->numOfChars
> 255 )
891 m_aEncoding
= RTL_TEXTENCODING_GBK
;
892 m_bFontEncodingOnly
= true;
893 #if OSL_DEBUG_LEVEL > 1
894 fprintf( stderr
, "found builtin font %s with GBK encoding\n", pInfo
->gfi
->fontName
);
899 // #i37313# check if Fontspecific is not rather some character encoding
900 if( nAdobeEncoding
== 3 && m_aEncoding
== RTL_TEXTENCODING_SYMBOL
)
902 bool bYFound
= false;
903 bool bQFound
= false;
904 CharMetricInfo
* pChar
= pInfo
->cmi
;
905 for( int j
= 0; j
< pInfo
->numOfChars
&& ! (bYFound
&& bQFound
); j
++ )
909 if( pChar
[j
].name
[0] == 'Y' && pChar
[j
].name
[1] == 0 )
911 else if( pChar
[j
].name
[0] == 'Q' && pChar
[j
].name
[1] == 0 )
915 if( bQFound
&& bYFound
)
917 #if OSL_DEBUG_LEVEL > 1
918 fprintf( stderr
, "setting FontSpecific font %s (file %s) to unicode\n",
919 pInfo
->gfi
->fontName
,
924 m_aEncoding
= RTL_TEXTENCODING_UNICODE
;
925 bFillEncodingvector
= false; // will be filled anyway, don't do the work twice
930 m_nAscend
= pInfo
->gfi
->fontBBox
.ury
;
933 // descends have opposite sign of our definition
934 m_nDescend
= -pInfo
->gfi
->fontBBox
.lly
;
936 // fallback to ascender, descender
937 // interesting: the BBox seems to describe Ascender and Descender better
938 // as we understand it
940 m_nAscend
= pInfo
->gfi
->ascender
;
942 m_nDescend
= -pInfo
->gfi
->descender
;
944 m_nLeading
= m_nAscend
+ m_nDescend
- 1000;
948 m_pMetrics
= new PrintFontMetrics
;
949 // mark all pages as queried (or clear if only global font info queiried)
950 memset( m_pMetrics
->m_aPages
, bOnlyGlobalAttributes
? 0 : 0xff, sizeof( m_pMetrics
->m_aPages
) );
952 m_aGlobalMetricX
.width
= m_aGlobalMetricY
.width
=
953 pInfo
->gfi
->charwidth
? pInfo
->gfi
->charwidth
: pInfo
->gfi
->fontBBox
.urx
;
954 m_aGlobalMetricX
.height
= m_aGlobalMetricY
.height
=
955 pInfo
->gfi
->capHeight
? pInfo
->gfi
->capHeight
: pInfo
->gfi
->fontBBox
.ury
;
957 m_nXMin
= pInfo
->gfi
->fontBBox
.llx
;
958 m_nYMin
= pInfo
->gfi
->fontBBox
.lly
;
959 m_nXMax
= pInfo
->gfi
->fontBBox
.urx
;
960 m_nYMax
= pInfo
->gfi
->fontBBox
.ury
;
962 if( bFillEncodingvector
|| !bOnlyGlobalAttributes
)
964 // fill in character metrics
966 // first transform the character codes to unicode
967 // note: this only works with single byte encodings
968 sal_Unicode
* pUnicodes
= (sal_Unicode
*)alloca( pInfo
->numOfChars
* sizeof(sal_Unicode
));
969 CharMetricInfo
* pChar
= pInfo
->cmi
;
971 for( i
= 0; i
< pInfo
->numOfChars
; i
++, pChar
++ )
973 if( nAdobeEncoding
== 4 )
978 std::list
< sal_Unicode
> aCodes
= rManager
.getUnicodeFromAdobeName( pChar
->name
);
979 for( std::list
< sal_Unicode
>::const_iterator it
= aCodes
.begin(); it
!= aCodes
.end(); ++it
)
983 m_aEncodingVector
[ *it
] = pChar
->code
;
984 if( pChar
->code
== -1 )
985 m_aNonEncoded
[ *it
] = pChar
->name
;
986 if( ! pUnicodes
[i
] ) // map the first
992 else if( pChar
->code
!= -1 )
994 if( nAdobeEncoding
== 3 && m_aEncoding
== RTL_TEXTENCODING_SYMBOL
)
996 pUnicodes
[i
] = pChar
->code
+ 0xf000;
997 if( bFillEncodingvector
)
998 m_aEncodingVector
[ pUnicodes
[i
] ] = pChar
->code
;
1002 if( m_aEncoding
== RTL_TEXTENCODING_UNICODE
)
1004 pUnicodes
[i
] = (sal_Unicode
)pChar
->code
;
1008 ByteString aTranslate
;
1009 if( pChar
->code
& 0xff000000 )
1010 aTranslate
+= (char)(pChar
->code
>> 24 );
1011 if( pChar
->code
& 0xffff0000 )
1012 aTranslate
+= (char)((pChar
->code
& 0x00ff0000) >> 16 );
1013 if( pChar
->code
& 0xffffff00 )
1014 aTranslate
+= (char)((pChar
->code
& 0x0000ff00) >> 8 );
1015 aTranslate
+= (char)(pChar
->code
& 0xff);
1016 String
aUni( aTranslate
, m_aEncoding
);
1017 pUnicodes
[i
] = *aUni
.GetBuffer();
1023 // now fill in the character metrics
1024 // parseAFM.cxx effectively only supports direction 0 (horizontal)
1026 CharacterMetric aMetric
;
1027 for( i
= 0; i
< pInfo
->numOfChars
; i
++, pChar
++ )
1029 if( pChar
->code
== -1 && ! pChar
->name
)
1032 if( bFillEncodingvector
&& pChar
->name
)
1034 std::list
< sal_Unicode
> aCodes
= rManager
.getUnicodeFromAdobeName( pChar
->name
);
1035 for( std::list
< sal_Unicode
>::const_iterator it
= aCodes
.begin(); it
!= aCodes
.end(); ++it
)
1039 m_aEncodingVector
[ *it
] = pChar
->code
;
1040 if( pChar
->code
== -1 )
1041 m_aNonEncoded
[ *it
] = pChar
->name
;
1046 aMetric
.width
= pChar
->wx
? pChar
->wx
: pChar
->charBBox
.urx
;
1047 aMetric
.height
= pChar
->wy
? pChar
->wy
: pChar
->charBBox
.ury
- pChar
->charBBox
.lly
;
1048 if( aMetric
.width
== 0 && aMetric
.height
== 0 )
1049 // guess something for e.g. space
1050 aMetric
.width
= m_aGlobalMetricX
.width
/4;
1052 if( ( nAdobeEncoding
== 0 ) ||
1053 ( ( nAdobeEncoding
== 3 ) && ( m_aEncoding
!= RTL_TEXTENCODING_SYMBOL
) ) )
1055 if( pChar
->code
!= -1 )
1057 m_pMetrics
->m_aMetrics
[ pUnicodes
[i
] ] = aMetric
;
1058 if( bFillEncodingvector
)
1059 m_aEncodingVector
[ pUnicodes
[i
] ] = pChar
->code
;
1061 else if( pChar
->name
)
1063 std::list
< sal_Unicode
> aCodes
= rManager
.getUnicodeFromAdobeName( pChar
->name
);
1064 for( std::list
< sal_Unicode
>::const_iterator it
= aCodes
.begin(); it
!= aCodes
.end(); ++it
)
1067 m_pMetrics
->m_aMetrics
[ *it
] = aMetric
;
1071 else if( nAdobeEncoding
== 1 || nAdobeEncoding
== 2 || nAdobeEncoding
== 4)
1075 std::list
< sal_Unicode
> aCodes
= rManager
.getUnicodeFromAdobeName( pChar
->name
);
1076 for( std::list
< sal_Unicode
>::const_iterator it
= aCodes
.begin(); it
!= aCodes
.end(); ++it
)
1079 m_pMetrics
->m_aMetrics
[ *it
] = aMetric
;
1082 else if( pChar
->code
!= -1 )
1084 ::std::pair
< ::std::hash_multimap
< sal_uInt8
, sal_Unicode
>::const_iterator
,
1085 ::std::hash_multimap
< sal_uInt8
, sal_Unicode
>::const_iterator
>
1086 aCodes
= rManager
.getUnicodeFromAdobeCode( pChar
->code
);
1087 while( aCodes
.first
!= aCodes
.second
)
1089 if( (*aCodes
.first
).second
!= 0 )
1091 m_pMetrics
->m_aMetrics
[ (*aCodes
.first
).second
] = aMetric
;
1092 if( bFillEncodingvector
)
1093 m_aEncodingVector
[ (*aCodes
.first
).second
] = pChar
->code
;
1099 else if( nAdobeEncoding
== 3 )
1101 if( pChar
->code
!= -1 )
1103 sal_Unicode code
= 0xf000 + pChar
->code
;
1104 m_pMetrics
->m_aMetrics
[ code
] = aMetric
;
1105 // maybe should try to find the name in the convtabs ?
1106 if( bFillEncodingvector
)
1107 m_aEncodingVector
[ code
] = pChar
->code
;
1112 m_pMetrics
->m_aXKernPairs
.clear();
1113 m_pMetrics
->m_aYKernPairs
.clear();
1115 // now fill in the kern pairs
1116 // parseAFM.cxx effectively only supports direction 0 (horizontal)
1117 PairKernData
* pKern
= pInfo
->pkd
;
1119 for( i
= 0; i
< pInfo
->numOfPairs
; i
++, pKern
++ )
1121 // #i37703# broken kern table
1122 if( ! pKern
->name1
|| ! pKern
->name2
)
1127 // currently we have to find the adobe character names
1128 // in the already parsed character metrics to find
1129 // the corresponding UCS2 code which is a bit dangerous
1130 // since the character names are not required
1131 // in the metric descriptions
1134 j
< pInfo
->numOfChars
&& ( aPair
.first
== 0 || aPair
.second
== 0 );
1137 if( pChar
->code
!= -1 )
1139 if( ! strcmp( pKern
->name1
, pChar
->name
? pChar
->name
: "" ) )
1140 aPair
.first
= pUnicodes
[ j
];
1141 if( ! strcmp( pKern
->name2
, pChar
->name
? pChar
->name
: "" ) )
1142 aPair
.second
= pUnicodes
[ j
];
1145 if( aPair
.first
&& aPair
.second
)
1147 aPair
.kern_x
= pKern
->xamt
;
1148 aPair
.kern_y
= pKern
->yamt
;
1149 m_pMetrics
->m_aXKernPairs
.push_back( aPair
);
1152 m_pMetrics
->m_bKernPairsQueried
= true;
1155 freeFontInfo( pInfo
);
1159 // -------------------------------------------------------------------------
1161 OString
PrintFontManager::s_aEmptyOString
;
1166 PrintFontManager
& PrintFontManager::get()
1168 static PrintFontManager
* theManager
= NULL
;
1171 theManager
= new PrintFontManager();
1172 theManager
->initialize();
1177 // -------------------------------------------------------------------------
1180 * the PrintFontManager
1183 PrintFontManager::PrintFontManager() :
1185 m_pAtoms( new MultiAtomProvider() ),
1186 m_nNextDirAtom( 1 ),
1187 m_pFontCache( NULL
),
1188 m_bFontconfigSuccess( false )
1190 for( unsigned int i
= 0; i
< sizeof( aAdobeCodes
)/sizeof( aAdobeCodes
[0] ); i
++ )
1192 m_aUnicodeToAdobename
.insert( ::std::hash_multimap
< sal_Unicode
, ::rtl::OString
>::value_type( aAdobeCodes
[i
].aUnicode
, aAdobeCodes
[i
].pAdobename
) );
1193 m_aAdobenameToUnicode
.insert( ::std::hash_multimap
< ::rtl::OString
, sal_Unicode
, ::rtl::OStringHash
>::value_type( aAdobeCodes
[i
].pAdobename
, aAdobeCodes
[i
].aUnicode
) );
1194 if( aAdobeCodes
[i
].aAdobeStandardCode
)
1196 m_aUnicodeToAdobecode
.insert( ::std::hash_multimap
< sal_Unicode
, sal_uInt8
>::value_type( aAdobeCodes
[i
].aUnicode
, aAdobeCodes
[i
].aAdobeStandardCode
) );
1197 m_aAdobecodeToUnicode
.insert( ::std::hash_multimap
< sal_uInt8
, sal_Unicode
>::value_type( aAdobeCodes
[i
].aAdobeStandardCode
, aAdobeCodes
[i
].aUnicode
) );
1200 m_aUnicodeToAdobename
[ aAdobeCodes
[i
].aUnicode
] = aAdobeCodes
[i
].pAdobename
;
1201 m_aAdobenameToUnicode
[ aAdobeCodes
[i
].pAdobename
] = aAdobeCodes
[i
].aUnicode
;
1202 if( aAdobeCodes
[i
].aAdobeStandardCode
)
1204 m_aUnicodeToAdobecode
[ aAdobeCodes
[i
].aUnicode
] = aAdobeCodes
[i
].aAdobeStandardCode
;
1205 m_aAdobecodeToUnicode
[ aAdobeCodes
[i
].aAdobeStandardCode
] = aAdobeCodes
[i
].aUnicode
;
1211 // -------------------------------------------------------------------------
1213 PrintFontManager::~PrintFontManager()
1216 for( ::std::hash_map
< fontID
, PrintFont
* >::const_iterator it
= m_aFonts
.begin(); it
!= m_aFonts
.end(); ++it
)
1217 delete (*it
).second
;
1220 delete m_pFontCache
;
1223 // -------------------------------------------------------------------------
1225 const OString
& PrintFontManager::getDirectory( int nAtom
) const
1227 ::std::hash_map
< int, OString
>::const_iterator
it( m_aAtomToDir
.find( nAtom
) );
1228 return it
!= m_aAtomToDir
.end() ? it
->second
: s_aEmptyOString
;
1231 // -------------------------------------------------------------------------
1233 int PrintFontManager::getDirectoryAtom( const OString
& rDirectory
, bool bCreate
)
1236 ::std::hash_map
< OString
, int, OStringHash
>::const_iterator it
1237 ( m_aDirToAtom
.find( rDirectory
) );
1238 if( it
!= m_aDirToAtom
.end() )
1242 nAtom
= m_nNextDirAtom
++;
1243 m_aDirToAtom
[ rDirectory
] = nAtom
;
1244 m_aAtomToDir
[ nAtom
] = rDirectory
;
1249 // -------------------------------------------------------------------------
1251 int PrintFontManager::addFontFile( const ::rtl::OString
& rFileName
, int /*nFaceNum*/ )
1253 rtl_TextEncoding aEncoding
= osl_getThreadTextEncoding();
1254 INetURLObject
aPath( OStringToOUString( rFileName
, aEncoding
), INET_PROT_FILE
, INetURLObject::ENCODE_ALL
);
1255 OString
aName( OUStringToOString( aPath
.GetName(), aEncoding
) );
1256 OString
aDir( OUStringToOString( aPath
.GetPath(), aEncoding
) );
1258 int nDirID
= getDirectoryAtom( aDir
, true );
1259 fontID nFontId
= findFontFileID( nDirID
, aName
);
1262 ::std::list
< PrintFont
* > aNewFonts
;
1263 if( analyzeFontFile( nDirID
, aName
, ::std::list
<OString
>(), aNewFonts
) )
1265 for( ::std::list
< PrintFont
* >::iterator it
= aNewFonts
.begin();
1266 it
!= aNewFonts
.end(); ++it
)
1268 m_aFonts
[ nFontId
= m_nNextFontID
++ ] = *it
;
1269 m_aFontFileToFontID
[ aName
].insert( nFontId
);
1270 m_pFontCache
->updateFontCacheEntry( *it
, true );
1277 // -------------------------------------------------------------------------
1279 bool PrintFontManager::analyzeFontFile( int nDirID
, const OString
& rFontFile
, const ::std::list
<OString
>& rXLFDs
, ::std::list
< PrintFontManager::PrintFont
* >& rNewFonts
) const
1283 OString
aDir( getDirectory( nDirID
) );
1285 OString
aFullPath( aDir
);
1287 aFullPath
+= rFontFile
;
1289 // #i1872# reject unreadable files
1290 if( access( aFullPath
.getStr(), R_OK
) )
1293 ByteString
aExt( rFontFile
.copy( rFontFile
.lastIndexOf( '.' )+1 ) );
1294 if( aExt
.EqualsIgnoreCaseAscii( "pfb" ) || aExt
.EqualsIgnoreCaseAscii( "pfa" ) )
1296 // check for corresponding afm metric
1297 // first look for an adjacent file
1298 static const char* pSuffix
[] = { ".afm", ".AFM" };
1300 for( unsigned int i
= 0; i
< sizeof(pSuffix
)/sizeof(pSuffix
[0]); i
++ )
1302 ByteString
aName( rFontFile
);
1303 aName
.Erase( aName
.Len()-4 );
1304 aName
.Append( pSuffix
[i
] );
1306 ByteString
aFilePath( aDir
);
1307 aFilePath
.Append( '/' );
1308 aFilePath
.Append( aName
);
1310 ByteString aAfmFile
;
1311 if( access( aFilePath
.GetBuffer(), R_OK
) )
1313 // try in subdirectory afm instead
1315 aFilePath
.Append( "/afm/" );
1316 aFilePath
.Append( aName
);
1318 if( ! access( aFilePath
.GetBuffer(), R_OK
) )
1327 if( aAfmFile
.Len() )
1329 Type1FontFile
* pFont
= new Type1FontFile();
1330 pFont
->m_nDirectory
= nDirID
;
1332 pFont
->m_aFontFile
= rFontFile
;
1333 pFont
->m_aMetricFile
= aAfmFile
;
1335 if( ! pFont
->readAfmMetrics( getAfmFile( pFont
), m_pAtoms
, false, true ) )
1340 if( pFont
&& rXLFDs
.size() )
1341 getFontAttributesFromXLFD( pFont
, rXLFDs
);
1343 rNewFonts
.push_back( pFont
);
1348 else if( aExt
.EqualsIgnoreCaseAscii( "afm" ) )
1350 ByteString
aFilePath( aDir
);
1351 aFilePath
.Append( '/' );
1352 aFilePath
.Append( ByteString( rFontFile
) );
1353 BuiltinFont
* pFont
= new BuiltinFont();
1354 pFont
->m_nDirectory
= nDirID
;
1355 pFont
->m_aMetricFile
= rFontFile
;
1356 if( pFont
->readAfmMetrics( aFilePath
, m_pAtoms
, false, true ) )
1357 rNewFonts
.push_back( pFont
);
1361 else if( aExt
.EqualsIgnoreCaseAscii( "ttf" )
1362 || aExt
.EqualsIgnoreCaseAscii( "tte" ) // #i33947# for Gaiji support
1363 || aExt
.EqualsIgnoreCaseAscii( "otf" ) ) // check for TTF- and PS-OpenType too
1365 TrueTypeFontFile
* pFont
= new TrueTypeFontFile();
1366 pFont
->m_nDirectory
= nDirID
;
1367 pFont
->m_aFontFile
= rFontFile
;
1368 pFont
->m_nCollectionEntry
= -1;
1371 getFontAttributesFromXLFD( pFont
, rXLFDs
);
1372 // need to read the font anyway to get aliases inside the font file
1373 if( ! analyzeTrueTypeFile( pFont
) )
1379 rNewFonts
.push_back( pFont
);
1381 else if( aExt
.EqualsIgnoreCaseAscii( "ttc" ) )
1383 // get number of ttc entries
1384 int nLength
= CountTTCFonts( aFullPath
.getStr() );
1387 #if OSL_DEBUG_LEVEL > 1
1388 fprintf( stderr
, "%s contains %d fonts\n", aFullPath
.getStr(), nLength
);
1390 for( int i
= 0; i
< nLength
; i
++ )
1392 TrueTypeFontFile
* pFont
= new TrueTypeFontFile();
1393 pFont
->m_nDirectory
= nDirID
;
1394 pFont
->m_aFontFile
= rFontFile
;
1395 pFont
->m_nCollectionEntry
= i
;
1397 getFontAttributesFromXLFD( pFont
, rXLFDs
);
1398 if( ! analyzeTrueTypeFile( pFont
) )
1404 rNewFonts
.push_back( pFont
);
1407 #if OSL_DEBUG_LEVEL > 1
1409 fprintf( stderr
, "CountTTCFonts( \"%s/%s\" ) failed\n", getDirectory(nDirID
).getStr(), rFontFile
.getStr() );
1412 return ! rNewFonts
.empty();
1415 // -------------------------------------------------------------------------
1417 fontID
PrintFontManager::findFontBuiltinID( int nPSNameAtom
) const
1420 ::std::hash_map
< fontID
, PrintFont
* >::const_iterator it
;
1421 for( it
= m_aFonts
.begin(); nID
== 0 && it
!= m_aFonts
.end(); ++it
)
1423 if( it
->second
->m_eType
== fonttype::Builtin
&&
1424 it
->second
->m_nPSName
== nPSNameAtom
)
1430 // -------------------------------------------------------------------------
1432 fontID
PrintFontManager::findFontFileID( int nDirID
, const OString
& rFontFile
) const
1436 ::std::hash_map
< OString
, ::std::set
< fontID
>, OStringHash
>::const_iterator set_it
= m_aFontFileToFontID
.find( rFontFile
);
1437 if( set_it
!= m_aFontFileToFontID
.end() )
1439 for( ::std::set
< fontID
>::const_iterator font_it
= set_it
->second
.begin(); font_it
!= set_it
->second
.end() && ! nID
; ++font_it
)
1441 ::std::hash_map
< fontID
, PrintFont
* >::const_iterator it
= m_aFonts
.find( *font_it
);
1442 if( it
!= m_aFonts
.end() )
1444 switch( it
->second
->m_eType
)
1446 case fonttype::Type1
:
1448 Type1FontFile
* const pFont
= static_cast< Type1FontFile
* const >((*it
).second
);
1449 if( pFont
->m_nDirectory
== nDirID
&&
1450 pFont
->m_aFontFile
== rFontFile
)
1454 case fonttype::TrueType
:
1456 TrueTypeFontFile
* const pFont
= static_cast< TrueTypeFontFile
* const >((*it
).second
);
1457 if( pFont
->m_nDirectory
== nDirID
&&
1458 pFont
->m_aFontFile
== rFontFile
)
1462 case fonttype::Builtin
:
1463 if( static_cast<const BuiltinFont
*>((*it
).second
)->m_nDirectory
== nDirID
&&
1464 static_cast<const BuiltinFont
*>((*it
).second
)->m_aMetricFile
== rFontFile
)
1476 // -------------------------------------------------------------------------
1478 bool PrintFontManager::parseXLFD( const OString
& rXLFD
, XLFDEntry
& rEntry
)
1480 sal_Int32 nIndex
= 0;
1481 OString aFoundry
= WhitespaceToSpace( rXLFD
.getToken( 1, '-', nIndex
) );
1482 if( nIndex
< 0 ) return false;
1483 OString aFamilyXLFD
= WhitespaceToSpace( rXLFD
.getToken( 0, '-', nIndex
) );
1484 if( nIndex
< 0 ) return false;
1485 OString aWeight
= rXLFD
.getToken( 0, '-', nIndex
).toAsciiLowerCase();
1486 if( nIndex
< 0 ) return false;
1487 OString aSlant
= rXLFD
.getToken( 0, '-', nIndex
).toAsciiLowerCase();
1488 if( nIndex
< 0 ) return false;
1489 OString aWidth
= rXLFD
.getToken( 0, '-', nIndex
).toAsciiLowerCase();
1490 if( nIndex
< 0 ) return false;
1491 OString aAddStyle
= rXLFD
.getToken( 0, '-', nIndex
).toAsciiLowerCase();
1492 if( nIndex
< 0 ) return false;
1493 OString aPitch
= rXLFD
.getToken( 4, '-', nIndex
).toAsciiLowerCase();
1494 if( nIndex
< 0 ) return false;
1495 OString aRegEnc
= WhitespaceToSpace( rXLFD
.getToken( 1, '-', nIndex
).toAsciiLowerCase() );
1496 if( nIndex
< 0 ) return false;
1497 OString aEnc
= WhitespaceToSpace( rXLFD
.getToken( 0, '-', nIndex
).toAsciiLowerCase() );
1500 sal_Int32 nFamIndex
= 0;
1501 OStringBuffer aFamilyName
;
1502 while( nFamIndex
>= 0 )
1504 OString aToken
= aFamilyXLFD
.getToken( 0, ' ', nFamIndex
);
1505 sal_Char aFirst
= aToken
.toChar();
1506 if( aFirst
>= 'a' && aFirst
<= 'z' )
1507 aFirst
= aFirst
- 'a' + 'A';
1508 OStringBuffer
aNewToken( aToken
.getLength() );
1509 aNewToken
.append( aToken
);
1510 aNewToken
.setCharAt( 0, aFirst
);
1511 if( aFamilyName
.getLength() > 0 )
1512 aFamilyName
.append( ' ' );
1513 aFamilyName
.append( aNewToken
.makeStringAndClear() );
1516 rEntry
.aFoundry
= aFoundry
;
1517 rEntry
.aFamily
= aFamilyName
.makeStringAndClear();
1518 rEntry
.aAddStyle
= aAddStyle
;
1520 rEntry
.eWeight
= parseWeight( aWeight
);
1522 rEntry
.eItalic
= parseItalic( aSlant
);
1524 rEntry
.eWidth
= parseWidth( aWidth
);
1527 if( aPitch
.toChar() == 'c' || aPitch
.toChar() == 'm' )
1528 rEntry
.ePitch
= pitch::Fixed
;
1530 rEntry
.ePitch
= pitch::Variable
;
1532 OString aToken
= aEnc
.toAsciiLowerCase();
1534 if( aAddStyle
.indexOf( "symbol" ) != -1 )
1535 rEntry
.aEncoding
= RTL_TEXTENCODING_SYMBOL
;
1538 if( aToken
.equals( "symbol" ) )
1539 rEntry
.aEncoding
= RTL_TEXTENCODING_SYMBOL
;
1542 OStringBuffer
aCharset( aRegEnc
.getLength() + aEnc
.getLength() + 1 );
1543 aCharset
.append( aRegEnc
);
1544 aCharset
.append( '-' );
1545 aCharset
.append( aEnc
);
1546 rEntry
.aEncoding
= rtl_getTextEncodingFromUnixCharset( aCharset
.getStr() );
1550 // set correct mask flags
1552 if( rEntry
.aFoundry
!= "*" ) rEntry
.nMask
|= XLFDEntry::MaskFoundry
;
1553 if( rEntry
.aFamily
!= "*" ) rEntry
.nMask
|= XLFDEntry::MaskFamily
;
1554 if( rEntry
.aAddStyle
!= "*" ) rEntry
.nMask
|= XLFDEntry::MaskAddStyle
;
1555 if( aWeight
!= "*" ) rEntry
.nMask
|= XLFDEntry::MaskWeight
;
1556 if( aSlant
!= "*" ) rEntry
.nMask
|= XLFDEntry::MaskItalic
;
1557 if( aWidth
!= "*" ) rEntry
.nMask
|= XLFDEntry::MaskWidth
;
1558 if( aPitch
!= "*" ) rEntry
.nMask
|= XLFDEntry::MaskPitch
;
1559 if( aRegEnc
!= "*" && aEnc
!= "*" ) rEntry
.nMask
|= XLFDEntry::MaskEncoding
;
1564 // -------------------------------------------------------------------------
1566 void PrintFontManager::parseXLFD_appendAliases( const std::list
< OString
>& rXLFDs
, std::list
< XLFDEntry
>& rEntries
) const
1568 for( std::list
< OString
>::const_iterator it
= rXLFDs
.begin(); it
!= rXLFDs
.end(); ++it
)
1571 if( ! parseXLFD(*it
, aEntry
) )
1573 rEntries
.push_back( aEntry
);
1574 std::map
< XLFDEntry
, std::list
< XLFDEntry
> >::const_iterator alias_it
=
1575 m_aXLFD_Aliases
.find( aEntry
);
1576 if( alias_it
!= m_aXLFD_Aliases
.end() )
1578 rEntries
.insert( rEntries
.end(), alias_it
->second
.begin(), alias_it
->second
.end() );
1583 // -------------------------------------------------------------------------
1585 void PrintFontManager::getFontAttributesFromXLFD( PrintFont
* pFont
, const std::list
< OString
>& rXLFDs
) const
1587 bool bFamilyName
= false;
1589 std::list
< XLFDEntry
> aXLFDs
;
1591 parseXLFD_appendAliases( rXLFDs
, aXLFDs
);
1593 for( std::list
< XLFDEntry
>::const_iterator it
= aXLFDs
.begin();
1594 it
!= aXLFDs
.end(); ++it
)
1596 // set family name or alias
1598 m_pAtoms
->getAtom( ATOM_FAMILYNAME
,
1599 OStringToOUString( it
->aFamily
, it
->aAddStyle
.indexOf( "utf8" ) != -1 ? RTL_TEXTENCODING_UTF8
: RTL_TEXTENCODING_ISO_8859_1
),
1604 pFont
->m_nFamilyName
= nFam
;
1605 switch( pFont
->m_eType
)
1607 case fonttype::Type1
:
1608 static_cast<Type1FontFile
*>(pFont
)->m_aXLFD
= rXLFDs
.front();
1610 case fonttype::TrueType
:
1611 static_cast<TrueTypeFontFile
*>(pFont
)->m_aXLFD
= rXLFDs
.front();
1619 // make sure that aliases are unique
1620 if( nFam
!= pFont
->m_nFamilyName
)
1622 std::list
< int >::const_iterator al_it
;
1623 for( al_it
= pFont
->m_aAliases
.begin(); al_it
!= pFont
->m_aAliases
.end() && *al_it
!= nFam
; ++al_it
)
1625 if( al_it
== pFont
->m_aAliases
.end() )
1626 pFont
->m_aAliases
.push_back( nFam
);
1629 // for the rest of the attributes there can only be one value;
1630 // we'll trust the first one
1635 pFont
->m_eWeight
= it
->eWeight
;
1637 pFont
->m_eItalic
= it
->eItalic
;
1639 pFont
->m_eWidth
= it
->eWidth
;
1641 pFont
->m_ePitch
= it
->ePitch
;
1643 pFont
->m_aEncoding
= it
->aEncoding
;
1646 // handle iso8859-1 as ms1252 to fill the "gap" starting at 0x80
1647 if( pFont
->m_aEncoding
== RTL_TEXTENCODING_ISO_8859_1
)
1648 pFont
->m_aEncoding
= RTL_TEXTENCODING_MS_1252
;
1649 if( rXLFDs
.begin() != rXLFDs
.end() )
1651 switch( pFont
->m_eType
)
1653 case fonttype::Type1
:
1654 static_cast<Type1FontFile
*>(pFont
)->m_aXLFD
= rXLFDs
.front();
1656 case fonttype::TrueType
:
1657 static_cast<TrueTypeFontFile
*>(pFont
)->m_aXLFD
= rXLFDs
.front();
1664 // -------------------------------------------------------------------------
1666 OString
PrintFontManager::getXLFD( PrintFont
* pFont
) const
1668 if( pFont
->m_eType
== fonttype::Type1
)
1670 if( static_cast<Type1FontFile
*>(pFont
)->m_aXLFD
.getLength() )
1671 return static_cast<Type1FontFile
*>(pFont
)->m_aXLFD
;
1673 if( pFont
->m_eType
== fonttype::TrueType
)
1675 if( static_cast<TrueTypeFontFile
*>(pFont
)->m_aXLFD
.getLength() )
1676 return static_cast<TrueTypeFontFile
*>(pFont
)->m_aXLFD
;
1679 OStringBuffer
aXLFD( 128 );
1681 aXLFD
.append( "-misc-" );
1682 ByteString
aFamily( String( m_pAtoms
->getString( ATOM_FAMILYNAME
, pFont
->m_nFamilyName
) ), RTL_TEXTENCODING_UTF8
);
1683 aFamily
.SearchAndReplaceAll( '-',' ' );
1684 aFamily
.SearchAndReplaceAll( '?',' ' );
1685 aFamily
.SearchAndReplaceAll( '*',' ' );
1686 aXLFD
.append( OString( aFamily
) );
1687 aXLFD
.append( '-' );
1688 switch( pFont
->m_eWeight
)
1690 case weight::Thin
: aXLFD
.append("thin");break;
1691 case weight::UltraLight
: aXLFD
.append("ultralight");break;
1692 case weight::Light
: aXLFD
.append("light");break;
1693 case weight::SemiLight
: aXLFD
.append("semilight");break;
1694 case weight::Normal
: aXLFD
.append("normal");break;
1695 case weight::Medium
: aXLFD
.append("medium");break;
1696 case weight::SemiBold
: aXLFD
.append("semibold");break;
1697 case weight::Bold
: aXLFD
.append("bold");break;
1698 case weight::UltraBold
: aXLFD
.append("ultrabold");break;
1699 case weight::Black
: aXLFD
.append("black");break;
1703 switch( pFont
->m_eItalic
)
1705 case italic::Upright
: aXLFD
.append('r');break;
1706 case italic::Oblique
: aXLFD
.append('o');break;
1707 case italic::Italic
: aXLFD
.append('i');break;
1711 switch( pFont
->m_eWidth
)
1713 case width::UltraCondensed
: aXLFD
.append("ultracondensed");break;
1714 case width::ExtraCondensed
: aXLFD
.append("extracondensed");break;
1715 case width::Condensed
: aXLFD
.append("condensed");break;
1716 case width::SemiCondensed
: aXLFD
.append("semicondensed");break;
1717 case width::Normal
: aXLFD
.append("normal");break;
1718 case width::SemiExpanded
: aXLFD
.append("semiexpanded");break;
1719 case width::Expanded
: aXLFD
.append("expanded");break;
1720 case width::ExtraExpanded
: aXLFD
.append("extraexpanded");break;
1721 case width::UltraExpanded
: aXLFD
.append("ultraexpanded");break;
1724 aXLFD
.append("-utf8-0-0-0-0-");
1725 aXLFD
.append( pFont
->m_ePitch
== pitch::Fixed
? "m" : "p" );
1726 aXLFD
.append("-0-");
1727 const char* pEnc
= rtl_getBestUnixCharsetFromTextEncoding( pFont
->m_aEncoding
);
1730 if( pFont
->m_aEncoding
== RTL_TEXTENCODING_ADOBE_STANDARD
)
1731 pEnc
= "adobe-standard";
1735 aXLFD
.append( pEnc
);
1737 return aXLFD
.makeStringAndClear();
1740 // -------------------------------------------------------------------------
1742 OUString
PrintFontManager::convertTrueTypeName( void* pRecord
) const
1744 NameRecord
* pNameRecord
= (NameRecord
*)pRecord
;
1747 ( pNameRecord
->platformID
== 3 && ( pNameRecord
->encodingID
== 0 || pNameRecord
->encodingID
== 1 ) ) // MS, Unicode
1749 ( pNameRecord
->platformID
== 0 ) // Apple, Unicode
1752 OUStringBuffer
aName( pNameRecord
->slen
/2 );
1753 const sal_uInt8
* pNameBuffer
= pNameRecord
->sptr
;
1754 for(int n
= 0; n
< pNameRecord
->slen
/2; n
++ )
1755 aName
.append( (sal_Unicode
)getUInt16BE( pNameBuffer
) );
1756 aValue
= aName
.makeStringAndClear();
1758 else if( pNameRecord
->platformID
== 3 )
1760 if( pNameRecord
->encodingID
>= 2 && pNameRecord
->encodingID
<= 6 )
1763 * and now for a special kind of madness:
1764 * some fonts encode their byte value string as BE uint16
1765 * (leading to stray zero bytes in the string)
1766 * while others code two bytes as a uint16 and swap to BE
1768 OStringBuffer aName
;
1769 const sal_uInt8
* pNameBuffer
= pNameRecord
->sptr
;
1770 for(int n
= 0; n
< pNameRecord
->slen
/2; n
++ )
1772 sal_Unicode aCode
= (sal_Unicode
)getUInt16BE( pNameBuffer
);
1773 sal_Char aChar
= aCode
>> 8;
1775 aName
.append( aChar
);
1776 aChar
= aCode
& 0x00ff;
1778 aName
.append( aChar
);
1780 switch( pNameRecord
->encodingID
)
1783 aValue
= OStringToOUString( aName
.makeStringAndClear(), RTL_TEXTENCODING_MS_932
);
1786 aValue
= OStringToOUString( aName
.makeStringAndClear(), RTL_TEXTENCODING_MS_936
);
1789 aValue
= OStringToOUString( aName
.makeStringAndClear(), RTL_TEXTENCODING_MS_950
);
1792 aValue
= OStringToOUString( aName
.makeStringAndClear(), RTL_TEXTENCODING_MS_949
);
1795 aValue
= OStringToOUString( aName
.makeStringAndClear(), RTL_TEXTENCODING_MS_1361
);
1803 // -------------------------------------------------------------------------
1805 void PrintFontManager::analyzeTrueTypeFamilyName( void* pTTFont
, ::std::list
< OUString
>& rNames
) const
1810 ::std::set
< OUString
> aSet
;
1812 NameRecord
* pNameRecords
= NULL
;
1813 int nNameRecords
= GetTTNameRecords( (TrueTypeFont
*)pTTFont
, &pNameRecords
);
1814 if( nNameRecords
&& pNameRecords
)
1816 LanguageType aLang
= MsLangId::getSystemLanguage();
1817 int nLastMatch
= -1;
1818 for( int i
= 0; i
< nNameRecords
; i
++ )
1820 if( pNameRecords
[i
].nameID
!= 1 || pNameRecords
[i
].sptr
== NULL
)
1823 if( pNameRecords
[i
].platformID
== 0 ) // Unicode
1825 else if( pNameRecords
[i
].platformID
== 3 )
1827 // this bases on the LanguageType actually being a Win LCID
1828 if( pNameRecords
[i
].languageID
== aLang
)
1830 else if( pNameRecords
[i
].languageID
== LANGUAGE_ENGLISH_US
)
1832 else if( pNameRecords
[i
].languageID
== LANGUAGE_ENGLISH
||
1833 pNameRecords
[i
].languageID
== LANGUAGE_ENGLISH_UK
)
1838 OUString aName
= convertTrueTypeName( pNameRecords
+ i
);
1839 aSet
.insert( aName
);
1840 if( nMatch
> nLastMatch
)
1842 nLastMatch
= nMatch
;
1846 DisposeNameRecords( pNameRecords
, nNameRecords
);
1848 if( aFamily
.getLength() )
1850 rNames
.push_front( aFamily
);
1851 for( ::std::set
< OUString
>::const_iterator it
= aSet
.begin(); it
!= aSet
.end(); ++it
)
1852 if( *it
!= aFamily
)
1853 rNames
.push_back( *it
);
1858 // -------------------------------------------------------------------------
1860 bool PrintFontManager::analyzeTrueTypeFile( PrintFont
* pFont
) const
1862 bool bSuccess
= false;
1863 rtl_TextEncoding aEncoding
= osl_getThreadTextEncoding();
1864 ByteString aFile
= getFontFile( pFont
);
1865 TrueTypeFont
* pTTFont
= NULL
;
1867 TrueTypeFontFile
* pTTFontFile
= static_cast< TrueTypeFontFile
* >(pFont
);
1868 if( OpenTTFontFile( aFile
.GetBuffer(), pTTFontFile
->m_nCollectionEntry
< 0 ? 0 : pTTFontFile
->m_nCollectionEntry
, &pTTFont
) == SF_OK
)
1870 TTGlobalFontInfo aInfo
;
1871 GetTTGlobalFontInfo( pTTFont
, & aInfo
);
1873 ::std::list
< OUString
> aNames
;
1874 analyzeTrueTypeFamilyName( pTTFont
, aNames
);
1876 // set family name from XLFD if possible
1877 if( ! pFont
->m_nFamilyName
)
1879 if( aNames
.begin() != aNames
.end() )
1881 pFont
->m_nFamilyName
= m_pAtoms
->getAtom( ATOM_FAMILYNAME
, aNames
.front(), sal_True
);
1888 // poor font does not have a family name
1889 // name it to file name minus the extension
1890 dotIndex
= pTTFontFile
->m_aFontFile
.lastIndexOf( '.' );
1891 if ( dotIndex
== -1 )
1892 dotIndex
= pTTFontFile
->m_aFontFile
.getLength();
1894 pFont
->m_nFamilyName
= m_pAtoms
->getAtom( ATOM_FAMILYNAME
, OStringToOUString( pTTFontFile
->m_aFontFile
.copy( 0, dotIndex
), aEncoding
), sal_True
);
1897 for( ::std::list
< OUString
>::iterator it
= aNames
.begin(); it
!= aNames
.end(); ++it
)
1899 if( it
->getLength() )
1901 int nAlias
= m_pAtoms
->getAtom( ATOM_FAMILYNAME
, *it
, sal_True
);
1902 if( nAlias
!= pFont
->m_nFamilyName
)
1904 std::list
< int >::const_iterator al_it
;
1905 for( al_it
= pFont
->m_aAliases
.begin(); al_it
!= pFont
->m_aAliases
.end() && *al_it
!= nAlias
; ++al_it
)
1907 if( al_it
== pFont
->m_aAliases
.end() )
1908 pFont
->m_aAliases
.push_back( nAlias
);
1913 if( aInfo
.usubfamily
)
1914 pFont
->m_aStyleName
= OUString( aInfo
.usubfamily
);
1916 pFont
->m_nPSName
= m_pAtoms
->getAtom( ATOM_PSNAME
, String( ByteString( aInfo
.psname
), aEncoding
), sal_True
);
1917 switch( aInfo
.weight
)
1919 case FW_THIN
: pFont
->m_eWeight
= weight::Thin
; break;
1920 case FW_EXTRALIGHT
: pFont
->m_eWeight
= weight::UltraLight
; break;
1921 case FW_LIGHT
: pFont
->m_eWeight
= weight::Light
; break;
1922 case FW_MEDIUM
: pFont
->m_eWeight
= weight::Medium
; break;
1923 case FW_SEMIBOLD
: pFont
->m_eWeight
= weight::SemiBold
; break;
1924 case FW_BOLD
: pFont
->m_eWeight
= weight::Bold
; break;
1925 case FW_EXTRABOLD
: pFont
->m_eWeight
= weight::UltraBold
; break;
1926 case FW_BLACK
: pFont
->m_eWeight
= weight::Black
; break;
1929 default: pFont
->m_eWeight
= weight::Normal
; break;
1932 switch( aInfo
.width
)
1934 case FWIDTH_ULTRA_CONDENSED
: pFont
->m_eWidth
= width::UltraCondensed
; break;
1935 case FWIDTH_EXTRA_CONDENSED
: pFont
->m_eWidth
= width::ExtraCondensed
; break;
1936 case FWIDTH_CONDENSED
: pFont
->m_eWidth
= width::Condensed
; break;
1937 case FWIDTH_SEMI_CONDENSED
: pFont
->m_eWidth
= width::SemiCondensed
; break;
1938 case FWIDTH_SEMI_EXPANDED
: pFont
->m_eWidth
= width::SemiExpanded
; break;
1939 case FWIDTH_EXPANDED
: pFont
->m_eWidth
= width::Expanded
; break;
1940 case FWIDTH_EXTRA_EXPANDED
: pFont
->m_eWidth
= width::ExtraExpanded
; break;
1941 case FWIDTH_ULTRA_EXPANDED
: pFont
->m_eWidth
= width::UltraExpanded
; break;
1944 default: pFont
->m_eWidth
= width::Normal
; break;
1947 pFont
->m_ePitch
= aInfo
.pitch
? pitch::Fixed
: pitch::Variable
;
1948 pFont
->m_eItalic
= aInfo
.italicAngle
== 0 ? italic::Upright
: ( aInfo
.italicAngle
< 0 ? italic::Italic
: italic::Oblique
);
1949 // #104264# there are fonts that set italic angle 0 although they are
1950 // italic; use macstyle bit here
1951 if( aInfo
.italicAngle
== 0 && (aInfo
.macStyle
& 2) )
1952 pFont
->m_eItalic
= italic::Italic
;
1954 pFont
->m_aEncoding
= aInfo
.symbolEncoded
? RTL_TEXTENCODING_SYMBOL
: RTL_TEXTENCODING_UCS2
;
1956 pFont
->m_aGlobalMetricY
.width
= pFont
->m_aGlobalMetricX
.width
= aInfo
.xMax
- aInfo
.xMin
;
1957 pFont
->m_aGlobalMetricY
.height
= pFont
->m_aGlobalMetricX
.height
= aInfo
.yMax
- aInfo
.yMin
;
1959 if( aInfo
.winAscent
&& aInfo
.winDescent
)
1961 pFont
->m_nAscend
= aInfo
.winAscent
;
1962 pFont
->m_nDescend
= aInfo
.winDescent
;
1963 pFont
->m_nLeading
= pFont
->m_nAscend
+ pFont
->m_nDescend
- 1000;
1965 else if( aInfo
.typoAscender
&& aInfo
.typoDescender
)
1967 pFont
->m_nLeading
= aInfo
.typoLineGap
;
1968 pFont
->m_nAscend
= aInfo
.typoAscender
;
1969 pFont
->m_nDescend
= -aInfo
.typoDescender
;
1973 pFont
->m_nLeading
= aInfo
.linegap
;
1974 pFont
->m_nAscend
= aInfo
.ascender
;
1975 pFont
->m_nDescend
= -aInfo
.descender
;
1978 // last try: font bounding box
1979 if( pFont
->m_nAscend
== 0 )
1980 pFont
->m_nAscend
= aInfo
.yMax
;
1981 if( pFont
->m_nDescend
== 0 )
1982 pFont
->m_nDescend
= -aInfo
.yMin
;
1983 if( pFont
->m_nLeading
== 0 )
1984 pFont
->m_nLeading
= 15 * (pFont
->m_nAscend
+pFont
->m_nDescend
) / 100;
1986 if( pFont
->m_nAscend
)
1987 pFont
->m_aGlobalMetricX
.height
= pFont
->m_aGlobalMetricY
.height
= pFont
->m_nAscend
+ pFont
->m_nDescend
;
1990 pFont
->m_nXMin
= aInfo
.xMin
;
1991 pFont
->m_nYMin
= aInfo
.yMin
;
1992 pFont
->m_nXMax
= aInfo
.xMax
;
1993 pFont
->m_nYMax
= aInfo
.yMax
;
1996 pTTFontFile
->m_nTypeFlags
= (unsigned int)aInfo
.typeFlags
;
1998 // get vertical substitutions flag
1999 pFont
->m_bHaveVerticalSubstitutedGlyphs
= DoesVerticalSubstitution( pTTFont
, 1 );
2001 CloseTTFont( pTTFont
);
2004 #if OSL_DEBUG_LEVEL > 1
2006 fprintf( stderr
, "could not OpenTTFont \"%s\"\n", aFile
.GetBuffer() );
2012 // -------------------------------------------------------------------------
2014 void PrintFontManager::initFontsAlias()
2016 m_aXLFD_Aliases
.clear();
2017 rtl_TextEncoding aEnc
= osl_getThreadTextEncoding();
2018 for( std::list
< OString
>::const_iterator dir_it
= m_aFontDirectories
.begin();
2019 dir_it
!= m_aFontDirectories
.end(); ++dir_it
)
2021 OStringBuffer
aDirName(512);
2022 aDirName
.append( *dir_it
);
2023 aDirName
.append( "/fonts.alias" );
2024 SvFileStream
aStream( OStringToOUString( aDirName
.makeStringAndClear(), aEnc
), STREAM_READ
);
2025 if( ! aStream
.IsOpen() )
2031 aStream
.ReadLine( aLine
);
2033 // get the alias and the pattern it gets translated to
2034 ByteString aAlias
= GetCommandLineToken( 0, aLine
);
2035 ByteString aMap
= GetCommandLineToken( 1, aLine
);
2037 // remove eventual quotes
2038 aAlias
.EraseLeadingChars( '"' );
2039 aAlias
.EraseTrailingChars( '"' );
2040 aMap
.EraseLeadingChars( '"' );
2041 aMap
.EraseTrailingChars( '"' );
2043 XLFDEntry aAliasEntry
, aMapEntry
;
2044 parseXLFD( aAlias
, aAliasEntry
);
2045 parseXLFD( aMap
, aMapEntry
);
2047 if( aAliasEntry
.nMask
&& aMapEntry
.nMask
)
2048 m_aXLFD_Aliases
[ aMapEntry
].push_back( aAliasEntry
);
2049 } while( ! aStream
.IsEof() );
2053 // code stolen from vcl's RegisterFontSubstitutors()
2054 // TODO: use that method once psprint gets merged into vcl
2055 static bool AreFCSubstitutionsEnabled()
2057 // init font substitution defaults
2058 int nDisableBits
= 0;
2060 // TODO: check the OS version and fc-data maintenance level
2061 nDisableBits
= 1; // disable "font fallback" here on default
2063 // apply the environment variable if any
2064 const char* pEnvStr
= ::getenv( "SAL_DISABLE_FC_SUBST" );
2068 if( (*pEnvStr
>= '0') && (*pEnvStr
<= '9') )
2069 nDisableBits
= (*pEnvStr
- '0');
2071 nDisableBits
= ~0U; // no specific bits set: disable all
2074 return ((nDisableBits
& 3) == 0);
2077 void PrintFontManager::initialize()
2079 #ifdef CALLGRIND_COMPILE
2080 CALLGRIND_TOGGLE_COLLECT();
2081 CALLGRIND_ZERO_STATS();
2084 long aDirEntBuffer
[ (sizeof(struct dirent
)+_PC_NAME_MAX
)+1 ];
2086 if( ! m_pFontCache
)
2088 #if OSL_DEBUG_LEVEL > 1
2089 fprintf( stderr
, "creating font cache ... " );
2092 aStart
= times( &tms
);
2094 m_pFontCache
= new FontCache();
2095 #if OSL_DEBUG_LEVEL > 1
2096 clock_t aStop
= times( &tms
);
2097 fprintf( stderr
, "done in %lf s\n", (double)(aStop
- aStart
)/(double)sysconf( _SC_CLK_TCK
) );
2101 // initialize may be called twice in the future
2103 for( ::std::hash_map
< fontID
, PrintFont
* >::const_iterator it
= m_aFonts
.begin(); it
!= m_aFonts
.end(); ++it
)
2104 delete (*it
).second
;
2107 m_aFontDirectories
.clear();
2108 m_aPrivateFontDirectories
.clear();
2109 m_aOverrideFonts
.clear();
2112 #if OSL_DEBUG_LEVEL > 1
2117 int nBuiltinFonts
= 0;
2122 aStart
= times( &tms
);
2125 // first try fontconfig
2126 m_bFontconfigSuccess
= initFontconfig();
2128 // part one - look for downloadable fonts
2129 rtl_TextEncoding aEncoding
= osl_getThreadTextEncoding();
2130 const ::rtl::OUString
&rSalPrivatePath
= psp::getFontPath();
2132 // search for the fonts in SAL_PRIVATE_FONTPATH first; those are
2133 // the fonts installed with the office
2134 if( rSalPrivatePath
.getLength() )
2136 OString aPath
= rtl::OUStringToOString( rSalPrivatePath
, aEncoding
);
2137 const bool bAreFCSubstitutionsEnabled
= AreFCSubstitutionsEnabled();
2138 sal_Int32 nIndex
= 0;
2141 OString aToken
= aPath
.getToken( 0, ';', nIndex
);
2143 // if registering an app-specific fontdir with fontconfig fails
2144 // and fontconfig-based substitutions are enabled
2145 // then trying to use these app-specific fonts doesn't make sense
2146 if( m_bFontconfigSuccess
&& !addFontconfigDir( aToken
) )
2147 if( bAreFCSubstitutionsEnabled
)
2149 m_aFontDirectories
.push_back( aToken
);
2150 m_aPrivateFontDirectories
.push_back( getDirectoryAtom( aToken
, true ) );
2151 } while( nIndex
>= 0 );
2154 // now that all global and local font dirs are known to fontconfig
2155 // check that there are fonts actually managed by fontconfig
2156 if( m_bFontconfigSuccess
)
2157 m_bFontconfigSuccess
= (countFontconfigFonts() > 0);
2159 // don't search through many directories fontconfig already told us about
2160 if( ! m_bFontconfigSuccess
)
2161 ImplGetSVData()->mpDefInst
->FillFontPathList( m_aFontDirectories
);
2163 // fill XLFD aliases from fonts.alias files
2166 // search for font files in each path
2167 std::list
< OString
>::iterator dir_it
;
2168 // protect against duplicate paths
2169 std::hash_map
< OString
, int, OStringHash
> visited_dirs
;
2170 for( dir_it
= m_aFontDirectories
.begin(); dir_it
!= m_aFontDirectories
.end(); ++dir_it
)
2172 OString
aPath( *dir_it
);
2173 // see if we were here already
2174 if( visited_dirs
.find( aPath
) != visited_dirs
.end() )
2176 visited_dirs
[ aPath
] = 1;
2178 // there may be ":unscaled" directories (see XFree86)
2179 // it should be safe to ignore them since they should not
2180 // contain any of our recognizeable fonts
2182 // ask the font cache whether it handles this directory
2183 std::list
< PrintFont
* > aCacheFonts
;
2184 if( m_pFontCache
->listDirectory( aPath
, aCacheFonts
) )
2186 #if OSL_DEBUG_LEVEL > 1
2187 fprintf( stderr
, "adding cache directory: %s\n", aPath
.getStr() );
2189 for( ::std::list
< PrintFont
* >::iterator it
= aCacheFonts
.begin(); it
!= aCacheFonts
.end(); ++it
)
2191 fontID aFont
= m_nNextFontID
++;
2192 m_aFonts
[ aFont
] = *it
;
2193 if( (*it
)->m_eType
== fonttype::Type1
)
2194 m_aFontFileToFontID
[ static_cast<Type1FontFile
*>(*it
)->m_aFontFile
].insert( aFont
);
2195 else if( (*it
)->m_eType
== fonttype::TrueType
)
2196 m_aFontFileToFontID
[ static_cast<TrueTypeFontFile
*>(*it
)->m_aFontFile
].insert( aFont
);
2197 else if( (*it
)->m_eType
== fonttype::Builtin
)
2198 m_aFontFileToFontID
[ static_cast<BuiltinFont
*>(*it
)->m_aMetricFile
].insert( aFont
);
2199 #if OSL_DEBUG_LEVEL > 1
2200 if( (*it
)->m_eType
== fonttype::Builtin
)
2203 #if OSL_DEBUG_LEVEL > 2
2204 fprintf( stderr
, "adding cached font %d: \"%s\" from %s\n", aFont
,
2205 OUStringToOString( getFontFamily( aFont
), RTL_TEXTENCODING_MS_1252
).getStr(),
2206 getFontFileSysPath( aFont
).getStr() );
2210 if( ! m_pFontCache
->scanAdditionalFiles( aPath
) )
2214 DIR* pDIR
= opendir( aPath
.getStr() );
2215 struct dirent
* pEntry
= (struct dirent
*)aDirEntBuffer
;
2218 // read fonts.dir if possible
2219 ::std::hash_map
< OString
, ::std::list
<OString
>, OStringHash
> aFontsDir
;
2220 int nDirID
= getDirectoryAtom( aPath
, true );
2221 // #i38367# no fonts.dir in our own directories anymore
2222 std::list
< int >::const_iterator priv_dir
;
2223 for( priv_dir
= m_aPrivateFontDirectories
.begin();
2224 priv_dir
!= m_aPrivateFontDirectories
.end() && *priv_dir
!= nDirID
;
2228 if( priv_dir
== m_aPrivateFontDirectories
.end() )
2230 ByteString
aGccDummy( aPath
);
2231 String
aFontsDirPath( aGccDummy
, aEncoding
);
2232 aFontsDirPath
.AppendAscii( "/fonts.dir" );
2233 SvFileStream
aStream( aFontsDirPath
, STREAM_READ
);
2234 if( aStream
.IsOpen() )
2237 while( ! aStream
.IsEof() )
2239 aStream
.ReadLine( aLine
);
2240 ByteString
aFileName( GetCommandLineToken( 0, aLine
) );
2241 ByteString
aXLFD( aLine
.Copy( aFileName
.Len() ) );
2242 if( aFileName
.Len() && aXLFD
.Len() )
2243 aFontsDir
[ aFileName
].push_back(aXLFD
);
2249 while( ! readdir_r( pDIR
, (struct dirent
*)aDirEntBuffer
, &pEntry
) && pEntry
)
2251 OString
aFileName( pEntry
->d_name
);
2252 // ignore .afm files here
2253 if( aFileName
.getLength() > 3 &&
2254 aFileName
.lastIndexOf( ".afm" ) == aFileName
.getLength()-4 )
2258 ByteString
aFilePath( aPath
);
2259 aFilePath
.Append( '/' );
2260 aFilePath
.Append( ByteString( aFileName
) );
2261 if( ! stat( aFilePath
.GetBuffer(), &aStat
) &&
2262 S_ISREG( aStat
.st_mode
) )
2264 if( findFontFileID( nDirID
, aFileName
) == 0 )
2266 ::std::list
<OString
> aXLFDs
;
2267 ::std::hash_map
< OString
, ::std::list
<OString
>, OStringHash
>::const_iterator it
=
2268 aFontsDir
.find( aFileName
);
2269 if( it
!= aFontsDir
.end() )
2270 aXLFDs
= (*it
).second
;
2272 // fill in font attributes from XLFD rather
2273 // than reading every file
2274 ::std::list
< PrintFont
* > aNewFonts
;
2275 if( analyzeFontFile( nDirID
, aFileName
, aXLFDs
, aNewFonts
) )
2277 for( ::std::list
< PrintFont
* >::iterator font_it
= aNewFonts
.begin(); font_it
!= aNewFonts
.end(); ++font_it
)
2279 fontID aFont
= m_nNextFontID
++;
2280 m_aFonts
[ aFont
] = *font_it
;
2281 m_aFontFileToFontID
[ aFileName
].insert( aFont
);
2282 m_pFontCache
->updateFontCacheEntry( *font_it
, false );
2284 #if OSL_DEBUG_LEVEL > 2
2285 fprintf( stderr
, "adding font %d: \"%s\" from %s\n", aFont
,
2286 OUStringToOString( getFontFamily( aFont
), RTL_TEXTENCODING_MS_1252
).getStr(),
2287 getFontFileSysPath( aFont
).getStr() );
2295 m_pFontCache
->updateDirTimestamp( nDirID
);
2297 m_pFontCache
->markEmptyDir( nDirID
);
2301 #if OSL_DEBUG_LEVEL > 1
2302 aStep1
= times( &tms
);
2305 // part two - look for metrics for builtin printer fonts
2306 std::list
< OUString
> aMetricDirs
;
2307 psp::getPrinterPathList( aMetricDirs
, PRINTER_METRICDIR
);
2309 std::list
< OString
> aEmptyFontsDir
;
2310 for( std::list
< OUString
>::const_iterator met_dir_it
= aMetricDirs
.begin(); met_dir_it
!= aMetricDirs
.end(); ++met_dir_it
)
2312 OString aDir
= OUStringToOString( *met_dir_it
, aEncoding
);
2314 // ask the font cache whether it handles this directory
2315 std::list
< PrintFont
* > aCacheFonts
;
2317 if( m_pFontCache
->listDirectory( aDir
, aCacheFonts
) )
2319 #if OSL_DEBUG_LEVEL > 1
2320 fprintf( stderr
, "adding cache directory: %s\n", aDir
.getStr() );
2322 for( ::std::list
< PrintFont
* >::iterator it
= aCacheFonts
.begin(); it
!= aCacheFonts
.end(); ++it
)
2324 fontID aFont
= m_nNextFontID
++;
2325 m_aFonts
[ aFont
] = *it
;
2326 if( (*it
)->m_eType
== fonttype::Type1
)
2327 m_aFontFileToFontID
[ static_cast<Type1FontFile
*>(*it
)->m_aFontFile
].insert( aFont
);
2328 else if( (*it
)->m_eType
== fonttype::TrueType
)
2329 m_aFontFileToFontID
[ static_cast<TrueTypeFontFile
*>(*it
)->m_aFontFile
].insert( aFont
);
2330 else if( (*it
)->m_eType
== fonttype::Builtin
)
2331 m_aFontFileToFontID
[ static_cast<BuiltinFont
*>(*it
)->m_aMetricFile
].insert( aFont
);
2332 #if OSL_DEBUG_LEVEL > 1
2333 if( (*it
)->m_eType
== fonttype::Builtin
)
2336 #if OSL_DEBUG_LEVEL > 2
2337 fprintf( stderr
, "adding cached font %d: \"%s\" from %s\n", aFont
,
2338 OUStringToOString( getFontFamily( aFont
), RTL_TEXTENCODING_MS_1252
).getStr(),
2339 getFontFileSysPath( aFont
).getStr() );
2346 DIR* pDIR
= opendir( aDir
.getStr() );
2349 struct dirent
* pDirEntry
= (struct dirent
*)aDirEntBuffer
;
2350 int nDirID
= getDirectoryAtom( aDir
, true );
2353 while( ! readdir_r( pDIR
, (struct dirent
*)aDirEntBuffer
, &pDirEntry
) && pDirEntry
)
2355 ByteString
aFile( aDir
);
2357 aFile
+= pDirEntry
->d_name
;
2359 if( ! stat( aFile
.GetBuffer(), &aStat
)
2360 && S_ISREG( aStat
.st_mode
)
2363 OString
aFileName( pDirEntry
->d_name
, strlen( pDirEntry
->d_name
) );
2364 OString
aExt( aFileName
.copy( aFileName
.lastIndexOf( '.' )+1 ) );
2365 if( aExt
.equalsIgnoreAsciiCase( "afm" ) )
2367 ::std::list
< PrintFont
* > aNewFonts
;
2369 analyzeFontFile( nDirID
, aFileName
, aEmptyFontsDir
, aNewFonts
);
2370 for( ::std::list
< PrintFont
* >::iterator it
= aNewFonts
.begin(); it
!= aNewFonts
.end(); ++it
)
2372 if( findFontBuiltinID( (*it
)->m_nPSName
) == 0 )
2374 m_aFontFileToFontID
[ aFileName
].insert( m_nNextFontID
);
2375 m_aFonts
[ m_nNextFontID
++ ] = *it
;
2376 m_pFontCache
->updateFontCacheEntry( *it
, false );
2377 #if OSL_DEBUG_LEVEL > 2
2389 m_pFontCache
->markEmptyDir( nDirID
);
2393 #if OSL_DEBUG_LEVEL > 1
2394 aStep2
= times( &tms
);
2397 // part three - fill in family styles
2398 ::std::hash_map
< fontID
, PrintFont
* >::iterator font_it
;
2399 for (font_it
= m_aFonts
.begin(); font_it
!= m_aFonts
.end(); ++font_it
)
2401 ::std::hash_map
< int, family::type
>::const_iterator it
=
2402 m_aFamilyTypes
.find( font_it
->second
->m_nFamilyName
);
2403 if (it
!= m_aFamilyTypes
.end())
2405 const ::rtl::OUString
& rFamily
=
2406 m_pAtoms
->getString( ATOM_FAMILYNAME
, font_it
->second
->m_nFamilyName
);
2407 family::type eType
= matchFamilyName( rFamily
);
2408 m_aFamilyTypes
[ font_it
->second
->m_nFamilyName
] = eType
;
2411 #if OSL_DEBUG_LEVEL > 1
2412 aStep3
= times( &tms
);
2413 fprintf( stderr
, "PrintFontManager::initialize: collected %d fonts (%d builtin, %d cached)\n", m_aFonts
.size(), nBuiltinFonts
, nCached
);
2414 double fTick
= (double)sysconf( _SC_CLK_TCK
);
2415 fprintf( stderr
, "Step 1 took %lf seconds\n", (double)(aStep1
- aStart
)/fTick
);
2416 fprintf( stderr
, "Step 2 took %lf seconds\n", (double)(aStep2
- aStep1
)/fTick
);
2417 fprintf( stderr
, "Step 3 took %lf seconds\n", (double)(aStep3
- aStep2
)/fTick
);
2420 m_pFontCache
->flush();
2422 #ifdef CALLGRIND_COMPILE
2423 CALLGRIND_DUMP_STATS();
2424 CALLGRIND_TOGGLE_COLLECT();
2428 // -------------------------------------------------------------------------
2430 equalPitch (psp::pitch::type from
, psp::pitch::type to
)
2436 equalWeight (psp::weight::type from
, psp::weight::type to
)
2438 return from
> to
? (from
- to
) <= 3 : (to
- from
) <= 3;
2442 equalItalic (psp::italic::type from
, psp::italic::type to
)
2444 if ( (from
== psp::italic::Italic
) || (from
== psp::italic::Oblique
) )
2445 return (to
== psp::italic::Italic
) || (to
== psp::italic::Oblique
);
2449 equalEncoding (rtl_TextEncoding from
, rtl_TextEncoding to
)
2451 if ((from
== RTL_TEXTENCODING_ISO_8859_1
) || (from
== RTL_TEXTENCODING_MS_1252
))
2452 return (to
== RTL_TEXTENCODING_ISO_8859_1
) || (to
== RTL_TEXTENCODING_MS_1252
);
2457 struct BuiltinFontIdentifier
2460 italic::type eItalic
;
2461 weight::type eWeight
;
2463 rtl_TextEncoding aEncoding
;
2465 BuiltinFontIdentifier( const OUString
& rFam
,
2469 rtl_TextEncoding enc
) :
2477 bool operator==( const BuiltinFontIdentifier
& rRight
) const
2479 return equalItalic( eItalic
, rRight
.eItalic
) &&
2480 equalWeight( eWeight
, rRight
.eWeight
) &&
2481 equalPitch( ePitch
, rRight
.ePitch
) &&
2482 equalEncoding( aEncoding
, rRight
.aEncoding
) &&
2483 aFamily
.equalsIgnoreAsciiCase( rRight
.aFamily
);
2487 struct BuiltinFontIdentifierHash
2489 size_t operator()( const BuiltinFontIdentifier
& rFont
) const
2491 return rFont
.aFamily
.hashCode() ^ rFont
.eItalic
^ rFont
.eWeight
^ rFont
.ePitch
^ rFont
.aEncoding
;
2496 void PrintFontManager::getFontList( ::std::list
< fontID
>& rFontIDs
, const PPDParser
* pParser
, bool bUseOverrideMetrics
)
2499 std::hash_map
< fontID
, PrintFont
* >::const_iterator it
;
2502 * Note: there are two easy steps making this faster:
2503 * first: insert the printer builtins first, then the not builtins,
2504 * if they do not match.
2505 * drawback: this would change the sequence of fonts; this could have
2506 * subtle, unknown consequences in vcl font matching
2507 * second: instead of comparing attributes to see whether a softfont
2508 * is duplicate to a builtin one could simply compare the PSName (which is
2509 * supposed to be unique), which at this point is just an int.
2510 * drawback: this could change which fonts are listed; especially TrueType
2511 * fonts often have a rather dubious PSName, so this could change the
2512 * font list not so subtle.
2513 * Until getFontList for a printer becomes a performance issue (which is
2514 * currently not the case), best stay with the current algorithm.
2517 // fill sets of printer supported fonts
2520 std::set
<int> aBuiltinPSNames
;
2521 std::hash_set
< BuiltinFontIdentifier
,
2522 BuiltinFontIdentifierHash
2525 std::map
<int, fontID
> aOverridePSNames
;
2526 if( bUseOverrideMetrics
)
2528 readOverrideMetrics();
2529 for( std::vector
<fontID
>::const_iterator over
= m_aOverrideFonts
.begin();
2530 over
!= m_aOverrideFonts
.end(); ++over
)
2532 std::hash_map
<fontID
,PrintFont
*>::const_iterator font_it
= m_aFonts
.find( *over
);
2533 DBG_ASSERT( font_it
!= m_aFonts
.end(), "override to nonexistant font" );
2534 if( font_it
!= m_aFonts
.end() )
2535 aOverridePSNames
[ font_it
->second
->m_nPSName
] = *over
;
2539 int nFonts
= pParser
->getFonts();
2540 for( int i
= 0; i
< nFonts
; i
++ )
2541 aBuiltinPSNames
.insert( m_pAtoms
->getAtom( ATOM_PSNAME
, pParser
->getFont( i
) ) );
2542 for( it
= m_aFonts
.begin(); it
!= m_aFonts
.end(); ++it
)
2544 PrintFont
* pFont
= it
->second
;
2545 if( it
->second
->m_eType
== fonttype::Builtin
&&
2546 aBuiltinPSNames
.find( pFont
->m_nPSName
) != aBuiltinPSNames
.end() )
2548 bool bInsert
= true;
2549 if( bUseOverrideMetrics
)
2551 // in override case only use the override fonts, not their counterparts
2552 std::map
<int,fontID
>::const_iterator over
= aOverridePSNames
.find( pFont
->m_nPSName
);
2553 if( over
!= aOverridePSNames
.end() && over
->second
!= it
->first
)
2558 // do not insert override fonts in non override case
2559 if( std::find( m_aOverrideFonts
.begin(), m_aOverrideFonts
.end(), it
->first
) != m_aOverrideFonts
.end() )
2564 aBuiltinFonts
.insert( BuiltinFontIdentifier(
2565 m_pAtoms
->getString( ATOM_FAMILYNAME
, pFont
->m_nFamilyName
),
2574 for( it
= m_aFonts
.begin(); it
!= m_aFonts
.end(); ++it
)
2576 PrintFont
* pFont
= it
->second
;
2577 if( it
->second
->m_eType
== fonttype::Builtin
)
2579 if( aBuiltinPSNames
.find( pFont
->m_nPSName
) != aBuiltinPSNames
.end() )
2581 bool bInsert
= true;
2582 if( bUseOverrideMetrics
)
2584 // in override case only use the override fonts, not their counterparts
2585 std::map
<int,fontID
>::const_iterator over
= aOverridePSNames
.find( pFont
->m_nPSName
);
2586 if( over
!= aOverridePSNames
.end() && over
->second
!= it
->first
)
2591 // do not insert override fonts in non override case
2592 if( std::find( m_aOverrideFonts
.begin(), m_aOverrideFonts
.end(), it
->first
) != m_aOverrideFonts
.end() )
2596 rFontIDs
.push_back( it
->first
);
2599 else if( aBuiltinFonts
.find( BuiltinFontIdentifier(
2600 m_pAtoms
->getString( ATOM_FAMILYNAME
, pFont
->m_nFamilyName
),
2605 ) ) == aBuiltinFonts
.end() )
2607 rFontIDs
.push_back( it
->first
);
2611 else // no specific printer
2613 for( it
= m_aFonts
.begin(); it
!= m_aFonts
.end(); ++it
)
2614 rFontIDs
.push_back( it
->first
);
2618 // -------------------------------------------------------------------------
2620 void PrintFontManager::fillPrintFontInfo( PrintFont
* pFont
, FastPrintFontInfo
& rInfo
) const
2622 ::std::hash_map
< int, family::type
>::const_iterator style_it
=
2623 m_aFamilyTypes
.find( pFont
->m_nFamilyName
);
2624 rInfo
.m_eType
= pFont
->m_eType
;
2625 rInfo
.m_aFamilyName
= m_pAtoms
->getString( ATOM_FAMILYNAME
, pFont
->m_nFamilyName
);
2626 rInfo
.m_aStyleName
= pFont
->m_aStyleName
;
2627 rInfo
.m_eFamilyStyle
= style_it
!= m_aFamilyTypes
.end() ? style_it
->second
: family::Unknown
;
2628 rInfo
.m_eItalic
= pFont
->m_eItalic
;
2629 rInfo
.m_eWidth
= pFont
->m_eWidth
;
2630 rInfo
.m_eWeight
= pFont
->m_eWeight
;
2631 rInfo
.m_ePitch
= pFont
->m_ePitch
;
2632 rInfo
.m_aEncoding
= pFont
->m_aEncoding
;
2633 rInfo
.m_eEmbeddedbitmap
= pFont
->m_eEmbeddedbitmap
;
2634 rInfo
.m_eAntialias
= pFont
->m_eAntialias
;
2636 rInfo
.m_bEmbeddable
= (pFont
->m_eType
== fonttype::Type1
);
2637 rInfo
.m_bSubsettable
= (pFont
->m_eType
== fonttype::TrueType
); // TODO: rename to SfntType
2639 rInfo
.m_aAliases
.clear();
2640 for( ::std::list
< int >::iterator it
= pFont
->m_aAliases
.begin(); it
!= pFont
->m_aAliases
.end(); ++it
)
2641 rInfo
.m_aAliases
.push_back( m_pAtoms
->getString( ATOM_FAMILYNAME
, *it
) );
2644 // -------------------------------------------------------------------------
2646 void PrintFontManager::fillPrintFontInfo( PrintFont
* pFont
, PrintFontInfo
& rInfo
) const
2648 if( ( pFont
->m_nAscend
== 0 && pFont
->m_nDescend
== 0 ) ||
2649 ! pFont
->m_pMetrics
|| pFont
->m_pMetrics
->isEmpty()
2652 // might be a truetype font not analyzed or type1 without metrics read
2653 if( pFont
->m_eType
== fonttype::Type1
)
2654 pFont
->readAfmMetrics( getAfmFile( pFont
), m_pAtoms
, false, false );
2655 else if( pFont
->m_eType
== fonttype::TrueType
)
2656 analyzeTrueTypeFile( pFont
);
2659 fillPrintFontInfo( pFont
, static_cast< FastPrintFontInfo
& >( rInfo
) );
2661 rInfo
.m_nAscend
= pFont
->m_nAscend
;
2662 rInfo
.m_nDescend
= pFont
->m_nDescend
;
2663 rInfo
.m_nLeading
= pFont
->m_nLeading
;
2664 rInfo
.m_nWidth
= pFont
->m_aGlobalMetricX
.width
< pFont
->m_aGlobalMetricY
.width
? pFont
->m_aGlobalMetricY
.width
: pFont
->m_aGlobalMetricX
.width
;
2667 // -------------------------------------------------------------------------
2669 void PrintFontManager::getFontListWithInfo( ::std::list
< PrintFontInfo
>& rFonts
, const PPDParser
* pParser
, bool bUseOverrideMetrics
)
2672 ::std::list
< fontID
> aFontList
;
2673 getFontList( aFontList
, pParser
, bUseOverrideMetrics
);
2675 ::std::list
< fontID
>::iterator it
;
2676 for( it
= aFontList
.begin(); it
!= aFontList
.end(); ++it
)
2678 PrintFontInfo aInfo
;
2680 fillPrintFontInfo( getFont( *it
), aInfo
);
2681 rFonts
.push_back( aInfo
);
2685 // -------------------------------------------------------------------------
2687 void PrintFontManager::getFontListWithFastInfo( ::std::list
< FastPrintFontInfo
>& rFonts
, const PPDParser
* pParser
, bool bUseOverrideMetrics
)
2690 ::std::list
< fontID
> aFontList
;
2691 getFontList( aFontList
, pParser
, bUseOverrideMetrics
);
2693 ::std::list
< fontID
>::iterator it
;
2694 for( it
= aFontList
.begin(); it
!= aFontList
.end(); ++it
)
2696 FastPrintFontInfo aInfo
;
2698 fillPrintFontInfo( getFont( *it
), aInfo
);
2699 rFonts
.push_back( aInfo
);
2703 // -------------------------------------------------------------------------
2705 bool PrintFontManager::getFontInfo( fontID nFontID
, PrintFontInfo
& rInfo
) const
2707 PrintFont
* pFont
= getFont( nFontID
);
2710 rInfo
.m_nID
= nFontID
;
2711 fillPrintFontInfo( pFont
, rInfo
);
2713 return pFont
? true : false;
2716 // -------------------------------------------------------------------------
2718 bool PrintFontManager::getFontFastInfo( fontID nFontID
, FastPrintFontInfo
& rInfo
) const
2720 PrintFont
* pFont
= getFont( nFontID
);
2723 rInfo
.m_nID
= nFontID
;
2724 fillPrintFontInfo( pFont
, rInfo
);
2726 return pFont
? true : false;
2729 // -------------------------------------------------------------------------
2731 bool PrintFontManager::getFontBoundingBox( fontID nFontID
, int& xMin
, int& yMin
, int& xMax
, int& yMax
)
2733 bool bSuccess
= false;
2734 PrintFont
* pFont
= getFont( nFontID
);
2737 if( pFont
->m_nXMin
== 0 && pFont
->m_nYMin
== 0 && pFont
->m_nXMax
== 0 && pFont
->m_nYMax
== 0 )
2739 // might be a truetype font not analyzed or type1 without metrics read
2740 if( pFont
->m_eType
== fonttype::Type1
|| pFont
->m_eType
== fonttype::Builtin
)
2741 pFont
->readAfmMetrics( getAfmFile( pFont
), m_pAtoms
, false, true );
2742 else if( pFont
->m_eType
== fonttype::TrueType
)
2743 analyzeTrueTypeFile( pFont
);
2746 xMin
= pFont
->m_nXMin
;
2747 yMin
= pFont
->m_nYMin
;
2748 xMax
= pFont
->m_nXMax
;
2749 yMax
= pFont
->m_nYMax
;
2754 // -------------------------------------------------------------------------
2756 int PrintFontManager::getFontFaceNumber( fontID nFontID
) const
2759 PrintFont
* pFont
= getFont( nFontID
);
2760 if( pFont
&& pFont
->m_eType
== fonttype::TrueType
)
2761 nRet
= static_cast< TrueTypeFontFile
* >(pFont
)->m_nCollectionEntry
;
2765 // -------------------------------------------------------------------------
2768 family::type
PrintFontManager::matchFamilyName( const ::rtl::OUString
& rFamily
) const
2772 sal_uInt16 mnLength
;
2773 family::type meType
;
2776 #define InitializeClass( p, a ) p, sizeof(p) - 1, a
2777 const family_t pFamilyMatch
[] = {
2778 { InitializeClass( "arial", family::Swiss
) },
2779 { InitializeClass( "arioso", family::Script
) },
2780 { InitializeClass( "avant garde", family::Swiss
) },
2781 { InitializeClass( "avantgarde", family::Swiss
) },
2782 { InitializeClass( "bembo", family::Roman
) },
2783 { InitializeClass( "bookman", family::Roman
) },
2784 { InitializeClass( "conga", family::Roman
) },
2785 { InitializeClass( "courier", family::Modern
) },
2786 { InitializeClass( "curl", family::Script
) },
2787 { InitializeClass( "fixed", family::Modern
) },
2788 { InitializeClass( "gill", family::Swiss
) },
2789 { InitializeClass( "helmet", family::Modern
) },
2790 { InitializeClass( "helvetica", family::Swiss
) },
2791 { InitializeClass( "international", family::Modern
) },
2792 { InitializeClass( "lucida", family::Swiss
) },
2793 { InitializeClass( "new century schoolbook", family::Roman
) },
2794 { InitializeClass( "palatino", family::Roman
) },
2795 { InitializeClass( "roman", family::Roman
) },
2796 { InitializeClass( "sans serif", family::Swiss
) },
2797 { InitializeClass( "sansserif", family::Swiss
) },
2798 { InitializeClass( "serf", family::Roman
) },
2799 { InitializeClass( "serif", family::Roman
) },
2800 { InitializeClass( "times", family::Roman
) },
2801 { InitializeClass( "utopia", family::Roman
) },
2802 { InitializeClass( "zapf chancery", family::Script
) },
2803 { InitializeClass( "zapfchancery", family::Script
) }
2806 rtl::OString aFamily
= rtl::OUStringToOString( rFamily
, RTL_TEXTENCODING_ASCII_US
);
2807 sal_uInt32 nLower
= 0;
2808 sal_uInt32 nUpper
= sizeof(pFamilyMatch
) / sizeof(pFamilyMatch
[0]);
2810 while( nLower
< nUpper
)
2812 sal_uInt32 nCurrent
= (nLower
+ nUpper
) / 2;
2813 const family_t
* pHaystack
= pFamilyMatch
+ nCurrent
;
2814 sal_Int32 nComparison
=
2815 rtl_str_compareIgnoreAsciiCase_WithLength
2817 aFamily
.getStr(), aFamily
.getLength(),
2818 pHaystack
->mpName
, pHaystack
->mnLength
2821 if( nComparison
< 0 )
2824 if( nComparison
> 0 )
2825 nLower
= nCurrent
+ 1;
2827 return pHaystack
->meType
;
2830 return family::Unknown
;
2833 // -------------------------------------------------------------------------
2835 family::type
PrintFontManager::getFontFamilyType( fontID nFontID
) const
2837 PrintFont
* pFont
= getFont( nFontID
);
2839 return family::Unknown
;
2841 ::std::hash_map
< int, family::type
>::const_iterator it
=
2842 m_aFamilyTypes
.find( pFont
->m_nFamilyName
);
2843 return (it
!= m_aFamilyTypes
.end()) ? it
->second
: family::Unknown
;
2847 // -------------------------------------------------------------------------
2849 const ::rtl::OUString
& PrintFontManager::getFontFamily( fontID nFontID
) const
2851 PrintFont
* pFont
= getFont( nFontID
);
2852 return m_pAtoms
->getString( ATOM_FAMILYNAME
, pFont
? pFont
->m_nFamilyName
: INVALID_ATOM
);
2855 // -------------------------------------------------------------------------
2857 OString
PrintFontManager::getAfmFile( PrintFont
* pFont
) const
2859 OString aMetricPath
;
2862 switch( pFont
->m_eType
)
2864 case fonttype::Type1
:
2866 Type1FontFile
* pPSFont
= static_cast< Type1FontFile
* >(pFont
);
2867 aMetricPath
= getDirectory( pPSFont
->m_nDirectory
);
2869 aMetricPath
+= pPSFont
->m_aMetricFile
;
2872 case fonttype::Builtin
:
2874 BuiltinFont
* pBuiltinFont
= static_cast< BuiltinFont
* >(pFont
);
2875 aMetricPath
= getDirectory( pBuiltinFont
->m_nDirectory
);
2877 aMetricPath
+= pBuiltinFont
->m_aMetricFile
;
2886 // -------------------------------------------------------------------------
2888 OString
PrintFontManager::getFontFile( PrintFont
* pFont
) const
2892 if( pFont
&& pFont
->m_eType
== fonttype::Type1
)
2894 Type1FontFile
* pPSFont
= static_cast< Type1FontFile
* >(pFont
);
2895 ::std::hash_map
< int, OString
>::const_iterator it
= m_aAtomToDir
.find( pPSFont
->m_nDirectory
);
2898 aPath
+= pPSFont
->m_aFontFile
;
2900 else if( pFont
&& pFont
->m_eType
== fonttype::TrueType
)
2902 TrueTypeFontFile
* pTTFont
= static_cast< TrueTypeFontFile
* >(pFont
);
2903 ::std::hash_map
< int, OString
>::const_iterator it
= m_aAtomToDir
.find( pTTFont
->m_nDirectory
);
2906 aPath
+= pTTFont
->m_aFontFile
;
2911 // -------------------------------------------------------------------------
2913 const ::rtl::OUString
& PrintFontManager::getPSName( fontID nFontID
) const
2915 PrintFont
* pFont
= getFont( nFontID
);
2916 if( pFont
&& pFont
->m_nPSName
== 0 )
2918 if( pFont
->m_eType
== fonttype::TrueType
)
2919 analyzeTrueTypeFile( pFont
);
2922 return m_pAtoms
->getString( ATOM_PSNAME
, pFont
? pFont
->m_nPSName
: INVALID_ATOM
);
2925 // -------------------------------------------------------------------------
2927 const CharacterMetric
& PrintFontManager::getGlobalFontMetric( fontID nFontID
, bool bHorizontal
) const
2929 static CharacterMetric aMetric
;
2930 PrintFont
* pFont
= getFont( nFontID
);
2931 return pFont
? ( bHorizontal
? pFont
->m_aGlobalMetricX
: pFont
->m_aGlobalMetricY
) : aMetric
;
2934 // -------------------------------------------------------------------------
2936 int PrintFontManager::getFontAscend( fontID nFontID
) const
2938 PrintFont
* pFont
= getFont( nFontID
);
2939 if( pFont
->m_nAscend
== 0 && pFont
->m_nDescend
== 0 )
2941 // might be a truetype font not yet analyzed
2942 if( pFont
->m_eType
== fonttype::TrueType
)
2943 analyzeTrueTypeFile( pFont
);
2944 else if( pFont
->m_eType
== fonttype::Type1
|| pFont
->m_eType
== fonttype::Builtin
)
2945 pFont
->readAfmMetrics( getAfmFile( pFont
), m_pAtoms
, false, true );
2947 return pFont
->m_nAscend
;
2950 // -------------------------------------------------------------------------
2952 int PrintFontManager::getFontDescend( fontID nFontID
) const
2954 PrintFont
* pFont
= getFont( nFontID
);
2955 if( pFont
->m_nAscend
== 0 && pFont
->m_nDescend
== 0 )
2957 // might be a truetype font not yet analyzed
2958 if( pFont
->m_eType
== fonttype::TrueType
)
2959 analyzeTrueTypeFile( pFont
);
2960 else if( pFont
->m_eType
== fonttype::Type1
|| pFont
->m_eType
== fonttype::Builtin
)
2961 pFont
->readAfmMetrics( getAfmFile( pFont
), m_pAtoms
, false, true );
2963 return pFont
->m_nDescend
;
2966 // -------------------------------------------------------------------------
2968 int PrintFontManager::getFontLeading( fontID nFontID
) const
2970 PrintFont
* pFont
= getFont( nFontID
);
2971 if( pFont
->m_nAscend
== 0 && pFont
->m_nDescend
== 0 )
2973 // might be a truetype font not yet analyzed
2974 if( pFont
->m_eType
== fonttype::TrueType
)
2975 analyzeTrueTypeFile( pFont
);
2977 return pFont
->m_nLeading
;
2980 // -------------------------------------------------------------------------
2982 bool PrintFontManager::hasVerticalSubstitutions( fontID nFontID
) const
2984 PrintFont
* pFont
= getFont( nFontID
);
2985 if( pFont
->m_nAscend
== 0 && pFont
->m_nDescend
== 0 )
2987 // might be a truetype font not yet analyzed
2988 if( pFont
->m_eType
== fonttype::TrueType
)
2989 analyzeTrueTypeFile( pFont
);
2991 return pFont
->m_bHaveVerticalSubstitutedGlyphs
;
2994 // -------------------------------------------------------------------------
2996 void PrintFontManager::hasVerticalSubstitutions( fontID nFontID
,
2997 const sal_Unicode
* pCharacters
, int nCharacters
, bool* pHasSubst
) const
2999 PrintFont
* pFont
= getFont( nFontID
);
3000 if( pFont
->m_nAscend
== 0 && pFont
->m_nDescend
== 0 )
3002 // might be a truetype font not yet analyzed
3003 if( pFont
->m_eType
== fonttype::TrueType
)
3004 analyzeTrueTypeFile( pFont
);
3007 if( ! pFont
->m_bHaveVerticalSubstitutedGlyphs
)
3008 memset( pHasSubst
, 0, sizeof(bool)*nCharacters
);
3011 for( int i
= 0; i
< nCharacters
; i
++ )
3013 sal_Unicode code
= pCharacters
[i
];
3014 if( ! pFont
->m_pMetrics
||
3015 ! ( pFont
->m_pMetrics
->m_aPages
[ code
>> 11 ] & ( 1 << ( ( code
>> 8 ) & 7 ) ) ) )
3016 pFont
->queryMetricPage( code
>> 8, m_pAtoms
);
3017 ::std::hash_map
< sal_Unicode
, bool >::const_iterator it
= pFont
->m_pMetrics
->m_bVerticalSubstitutions
.find( code
);
3018 pHasSubst
[i
] = it
!= pFont
->m_pMetrics
->m_bVerticalSubstitutions
.end();
3023 // -------------------------------------------------------------------------
3025 OUString
PrintFontManager::getFontXLFD( fontID nFontID
) const
3027 PrintFont
* pFont
= getFont( nFontID
);
3031 ByteString
aXLFD( getXLFD( pFont
) );
3032 rtl_TextEncoding aEncoding
= aXLFD
.GetToken( 6, '-' ).Search( "utf8" ) != STRING_NOTFOUND
? RTL_TEXTENCODING_UTF8
: RTL_TEXTENCODING_ISO_8859_1
;
3033 aRet
= OStringToOUString( aXLFD
, aEncoding
);
3038 // -------------------------------------------------------------------------
3040 const ::std::list
< KernPair
>& PrintFontManager::getKernPairs( fontID nFontID
, bool bVertical
) const
3042 static ::std::list
< KernPair
> aEmpty
;
3044 PrintFont
* pFont
= getFont( nFontID
);
3048 if( ! pFont
->m_pMetrics
|| ! pFont
->m_pMetrics
->m_bKernPairsQueried
)
3049 pFont
->queryMetricPage( 0, m_pAtoms
);
3050 if( ! pFont
->m_pMetrics
|| ! pFont
->m_pMetrics
->m_bKernPairsQueried
)
3052 return bVertical
? pFont
->m_pMetrics
->m_aYKernPairs
: pFont
->m_pMetrics
->m_aXKernPairs
;
3055 // -------------------------------------------------------------------------
3057 bool PrintFontManager::isFontDownloadingAllowed( fontID nFont
) const
3059 static const char* pEnable
= getenv( "PSPRINT_ENABLE_TTF_COPYRIGHTAWARENESS" );
3062 if( pEnable
&& *pEnable
)
3064 PrintFont
* pFont
= getFont( nFont
);
3065 if( pFont
&& pFont
->m_eType
== fonttype::TrueType
)
3067 TrueTypeFontFile
* pTTFontFile
= static_cast<TrueTypeFontFile
*>(pFont
);
3068 if( pTTFontFile
->m_nTypeFlags
& TYPEFLAG_INVALID
)
3070 TrueTypeFont
* pTTFont
= NULL
;
3071 ByteString aFile
= getFontFile( pFont
);
3072 if( OpenTTFontFile( aFile
.GetBuffer(), pTTFontFile
->m_nCollectionEntry
< 0 ? 0 : pTTFontFile
->m_nCollectionEntry
, &pTTFont
) == SF_OK
)
3075 TTGlobalFontInfo aInfo
;
3076 GetTTGlobalFontInfo( pTTFont
, & aInfo
);
3077 pTTFontFile
->m_nTypeFlags
= (unsigned int)aInfo
.typeFlags
;
3078 CloseTTFont( pTTFont
);
3082 unsigned int nCopyrightFlags
= pTTFontFile
->m_nTypeFlags
& TYPEFLAG_COPYRIGHT_MASK
;
3084 // font embedding is allowed if either
3085 // no restriction at all (bit 1 clear)
3086 // printing allowed (bit 1 set, bit 2 set )
3087 bRet
= ! ( nCopyrightFlags
& 0x02 ) || ( nCopyrightFlags
& 0x04 );
3093 // -------------------------------------------------------------------------
3095 bool PrintFontManager::getMetrics( fontID nFontID
, const sal_Unicode
* pString
, int nLen
, CharacterMetric
* pArray
, bool bVertical
) const
3097 PrintFont
* pFont
= getFont( nFontID
);
3101 if( ( pFont
->m_nAscend
== 0 && pFont
->m_nDescend
== 0 )
3102 || ! pFont
->m_pMetrics
|| pFont
->m_pMetrics
->isEmpty()
3105 // might be a font not yet analyzed
3106 if( pFont
->m_eType
== fonttype::Type1
|| pFont
->m_eType
== fonttype::Builtin
)
3107 pFont
->readAfmMetrics( getAfmFile( pFont
), m_pAtoms
, false, false );
3108 else if( pFont
->m_eType
== fonttype::TrueType
)
3109 analyzeTrueTypeFile( pFont
);
3112 for( int i
= 0; i
< nLen
; i
++ )
3114 if( ! pFont
->m_pMetrics
||
3115 ! ( pFont
->m_pMetrics
->m_aPages
[ pString
[i
] >> 11 ] & ( 1 << ( ( pString
[i
] >> 8 ) & 7 ) ) ) )
3116 pFont
->queryMetricPage( pString
[i
] >> 8, m_pAtoms
);
3117 pArray
[i
].width
= pArray
[i
].height
= -1;
3118 if( pFont
->m_pMetrics
)
3120 int effectiveCode
= pString
[i
];
3121 effectiveCode
|= bVertical
? 1 << 16 : 0;
3122 ::std::hash_map
< int, CharacterMetric
>::const_iterator it
=
3123 pFont
->m_pMetrics
->m_aMetrics
.find( effectiveCode
);
3124 // if no vertical metrics are available assume rotated horizontal metrics
3125 if( bVertical
&& (it
== pFont
->m_pMetrics
->m_aMetrics
.end()) )
3126 it
= pFont
->m_pMetrics
->m_aMetrics
.find( pString
[i
] );
3127 // the character metrics are in it->second
3128 if( it
!= pFont
->m_pMetrics
->m_aMetrics
.end() )
3129 pArray
[ i
] = it
->second
;
3136 // -------------------------------------------------------------------------
3138 bool PrintFontManager::getMetrics( fontID nFontID
, sal_Unicode minCharacter
, sal_Unicode maxCharacter
, CharacterMetric
* pArray
, bool bVertical
) const
3140 PrintFont
* pFont
= getFont( nFontID
);
3144 if( ( pFont
->m_nAscend
== 0 && pFont
->m_nDescend
== 0 )
3145 || ! pFont
->m_pMetrics
|| pFont
->m_pMetrics
->isEmpty()
3148 // might be a font not yet analyzed
3149 if( pFont
->m_eType
== fonttype::Type1
|| pFont
->m_eType
== fonttype::Builtin
)
3150 pFont
->readAfmMetrics( getAfmFile( pFont
), m_pAtoms
, false, false );
3151 else if( pFont
->m_eType
== fonttype::TrueType
)
3152 analyzeTrueTypeFile( pFont
);
3155 sal_Unicode code
= minCharacter
;
3158 if( ! pFont
->m_pMetrics
||
3159 ! ( pFont
->m_pMetrics
->m_aPages
[ code
>> 11 ] & ( 1 << ( ( code
>> 8 ) & 7 ) ) ) )
3160 pFont
->queryMetricPage( code
>> 8, m_pAtoms
);
3161 pArray
[ code
- minCharacter
].width
= -1;
3162 pArray
[ code
- minCharacter
].height
= -1;
3163 if( pFont
->m_pMetrics
)
3165 int effectiveCode
= code
;
3166 effectiveCode
|= bVertical
? 1 << 16 : 0;
3167 ::std::hash_map
< int, CharacterMetric
>::const_iterator it
=
3168 pFont
->m_pMetrics
->m_aMetrics
.find( effectiveCode
);
3169 // if no vertical metrics are available assume rotated horizontal metrics
3170 if( bVertical
&& (it
== pFont
->m_pMetrics
->m_aMetrics
.end()) )
3171 it
= pFont
->m_pMetrics
->m_aMetrics
.find( code
);
3172 // the character metrics are in it->second
3173 if( it
!= pFont
->m_pMetrics
->m_aMetrics
.end() )
3174 pArray
[ code
- minCharacter
] = it
->second
;
3176 } while( code
++ != maxCharacter
);
3181 // -------------------------------------------------------------------------
3183 static bool createWriteablePath( const ByteString
& rPath
)
3185 bool bSuccess
= false;
3187 if( access( rPath
.GetBuffer(), W_OK
) )
3189 int nPos
= rPath
.SearchBackward( '/' );
3190 if( nPos
!= STRING_NOTFOUND
)
3191 while( nPos
> 0 && rPath
.GetChar( nPos
) == '/' )
3194 if( nPos
!= STRING_NOTFOUND
&& nPos
!= 0 && createWriteablePath( rPath
.Copy( 0, nPos
+1 ) ) )
3196 bSuccess
= mkdir( rPath
.GetBuffer(), 0777 ) ? false : true;
3206 // -------------------------------------------------------------------------
3208 int PrintFontManager::importFonts( const ::std::list
< OString
>& rFiles
, bool bLinkOnly
, ImportFontCallback
* pCallback
)
3212 // find a directory with write access
3213 rtl_TextEncoding aEncoding
= osl_getThreadTextEncoding();
3214 bool bCanWrite
= false;
3217 for( ::std::list
< int >::const_iterator dir_it
= m_aPrivateFontDirectories
.begin();
3218 ! bCanWrite
&& dir_it
!= m_aPrivateFontDirectories
.end(); ++dir_it
)
3220 // check if we can create files in that directory
3221 ByteString aDirPath
= getDirectory( *dir_it
);
3222 if( createWriteablePath( aDirPath
) )
3224 aDir
= INetURLObject( OStringToOUString( aDirPath
, aEncoding
), INET_PROT_FILE
, INetURLObject::ENCODE_ALL
);
3231 for( ::std::list
< OString
>::const_iterator font_it
= rFiles
.begin();
3232 font_it
!= rFiles
.end(); ++font_it
)
3234 INetURLObject
aFrom( OStringToOUString( *font_it
, aEncoding
), INET_PROT_FILE
, INetURLObject::ENCODE_ALL
);
3235 INetURLObject
aTo( aDir
);
3236 aTo
.Append( aFrom
.GetName() );
3239 pCallback
->progress( aTo
.PathToFileName() );
3241 if( pCallback
&& pCallback
->isCanceled() )
3244 if( ! access( ByteString( String(aTo
.PathToFileName()), aEncoding
).GetBuffer(), F_OK
) )
3246 if( ! ( pCallback
? pCallback
->queryOverwriteFile( aTo
.PathToFileName() ) : false ) )
3249 // look for afm if necessary
3250 OUString aAfmCopied
;
3251 FileBase::RC nError
;
3252 if( aFrom
.getExtension().equalsIgnoreAsciiCaseAscii( "pfa" ) ||
3253 aFrom
.getExtension().equalsIgnoreAsciiCaseAscii( "pfb" ) )
3255 INetURLObject
aFromAfm( aFrom
);
3256 aFromAfm
.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) );
3257 if( access( ByteString( String(aFromAfm
.PathToFileName()), aEncoding
).GetBuffer(), F_OK
) )
3259 aFromAfm
.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AFM" ) ) );
3260 if( access( ByteString( String(aFromAfm
.PathToFileName()), aEncoding
).GetBuffer(), F_OK
) )
3262 aFromAfm
.removeSegment();
3263 aFromAfm
.Append( String( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) );
3264 aFromAfm
.Append( aTo
.GetName() );
3265 aFromAfm
.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) );
3266 if( access( ByteString( String(aFromAfm
.PathToFileName()), aEncoding
).GetBuffer(), F_OK
) )
3268 aFromAfm
.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AFM" ) ) );
3269 if( access( ByteString( String(aFromAfm
.PathToFileName()), aEncoding
).GetBuffer(), F_OK
) )
3273 pCallback
->importFontFailed( aTo
.PathToFileName(), ImportFontCallback::NoAfmMetric
);
3279 INetURLObject
aToAfm( aTo
);
3280 aToAfm
.setExtension( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) );
3281 OUString aFromPath
, aToPath
;
3284 ByteString
aLinkFromPath( String(aFromAfm
.PathToFileName()),
3286 ByteString
aLinkToPath( String(aToAfm
.PathToFileName()),
3288 nError
= (FileBase::RC
)symlink( aLinkFromPath
.GetBuffer(), aLinkToPath
.GetBuffer() );
3291 nError
= File::copy( aFromAfm
.GetMainURL(INetURLObject::DECODE_TO_IURI
), aToAfm
.GetMainURL(INetURLObject::DECODE_TO_IURI
) );
3295 pCallback
->importFontFailed( aTo
.PathToFileName(), ImportFontCallback::AfmCopyFailed
);
3298 aAfmCopied
= aToPath
;
3302 ByteString
aFromPath( String(aFrom
.PathToFileName()),
3304 ByteString
aToPath( String(aTo
.PathToFileName()), aEncoding
);
3305 nError
= (FileBase::RC
)symlink( aFromPath
.GetBuffer(),
3306 aToPath
.GetBuffer() );
3309 nError
= File::copy( aFrom
.GetMainURL(INetURLObject::DECODE_TO_IURI
), aTo
.GetMainURL(INetURLObject::DECODE_TO_IURI
) );
3313 if( aAfmCopied
.getLength() )
3314 File::remove( aAfmCopied
);
3316 pCallback
->importFontFailed( aTo
.PathToFileName(), ImportFontCallback::FontCopyFailed
);
3320 ::std::list
< PrintFont
* > aNewFonts
;
3321 ::std::list
< PrintFont
* >::iterator it
;
3322 if( analyzeFontFile( nDirID
, OUStringToOString( aTo
.GetName(), aEncoding
), ::std::list
<OString
>(), aNewFonts
) )
3324 // remove all fonts for the same file
3325 // discarding their font ids
3326 ::std::hash_map
< fontID
, PrintFont
* >::iterator current
, next
;
3327 current
= m_aFonts
.begin();
3328 OString
aFileName( OUStringToOString( aTo
.GetName(), aEncoding
) );
3329 while( current
!= m_aFonts
.end() )
3331 bool bRemove
= false;
3332 switch( current
->second
->m_eType
)
3334 case fonttype::Type1
:
3335 if( static_cast<Type1FontFile
*>(current
->second
)->m_aFontFile
== aFileName
)
3338 case fonttype::TrueType
:
3339 if( static_cast<TrueTypeFontFile
*>(current
->second
)->m_aFontFile
== aFileName
)
3348 m_aFontFileToFontID
[ aFileName
].erase( current
->first
);
3349 delete current
->second
;
3350 m_aFonts
.erase( current
);
3357 DBG_ASSERT( !findFontFileID( nDirID
, aFileName
), "not all fonts removed for file" );
3360 for( it
= aNewFonts
.begin(); it
!= aNewFonts
.end(); ++it
)
3362 m_aFontFileToFontID
[ aFileName
].insert( m_nNextFontID
);
3363 m_aFonts
[ m_nNextFontID
++ ] = *it
;
3364 m_pFontCache
->updateFontCacheEntry( *it
, false );
3369 m_pFontCache
->updateDirTimestamp( nDirID
);
3370 m_pFontCache
->flush();
3372 else if( pCallback
)
3373 pCallback
->importFontsFailed( ImportFontCallback::NoWritableDirectory
);
3378 // -------------------------------------------------------------------------
3380 bool PrintFontManager::checkImportPossible() const
3382 bool bSuccess
= false;
3384 // find a directory with write access
3386 for( std::list
< int >::const_iterator dir_it
= m_aPrivateFontDirectories
.begin();
3387 dir_it
!= m_aPrivateFontDirectories
.end(); ++dir_it
)
3389 aDir
= getDirectory( *dir_it
);
3390 if( createWriteablePath( aDir
) )
3397 #if OSL_DEBUG_LEVEL > 1
3399 fprintf( stderr
, "found writable %s\n", aDir
.GetBuffer() );
3405 // -------------------------------------------------------------------------
3407 bool PrintFontManager::checkChangeFontPropertiesPossible( fontID
/*nFontID*/ ) const
3409 // since font properties are changed in the font cache file only nowadays
3410 // they can always be changed
3414 // -------------------------------------------------------------------------
3416 bool PrintFontManager::changeFontProperties( fontID nFontID
, const ::rtl::OUString
& rXLFD
)
3418 ByteString
aXLFD( OUStringToOString( rXLFD
, RTL_TEXTENCODING_UTF8
) );
3419 ByteString aAddStyle
= aXLFD
.GetToken( '-', 6 );
3420 if( aAddStyle
.Search( "utf8" ) == STRING_NOTFOUND
)
3422 aAddStyle
.Append( aAddStyle
.Len() ? ";utf8" : "utf8" );
3423 aXLFD
.SetToken( 6, ';', aAddStyle
);
3425 PrintFont
* pFont
= getFont( nFontID
);
3426 std::list
< OString
> aDummyList
;
3427 aDummyList
.push_back( aXLFD
);
3428 getFontAttributesFromXLFD( pFont
, aDummyList
);
3429 pFont
->m_bUserOverride
= true;
3430 m_pFontCache
->updateFontCacheEntry( pFont
, true );
3435 // -------------------------------------------------------------------------
3437 bool PrintFontManager::
3438 getImportableFontProperties(
3439 const OString
& rFile
,
3440 ::std::list
< FastPrintFontInfo
>& rFontProps
3444 int nIndex
= rFile
.lastIndexOf( '/' );
3445 OString aDir
, aFile( rFile
.copy( nIndex
+1 ) );
3447 aDir
= rFile
.copy( 0, nIndex
);
3448 int nDirID
= getDirectoryAtom( aDir
, true );
3449 ::std::list
< PrintFont
* > aFonts
;
3450 bool bRet
= analyzeFontFile( nDirID
, aFile
, ::std::list
<OString
>(), aFonts
);
3451 while( aFonts
.begin() != aFonts
.end() )
3453 PrintFont
* pFont
= aFonts
.front();
3455 FastPrintFontInfo aInfo
;
3456 fillPrintFontInfo( pFont
, aInfo
);
3457 rFontProps
.push_back( aInfo
);
3463 // -------------------------------------------------------------------------
3465 bool PrintFontManager::getFileDuplicates( fontID nFont
, ::std::list
< fontID
>& rFonts
) const
3471 PrintFont
* pSearchFont
= getFont( nFont
);
3472 if( ! pSearchFont
||
3473 pSearchFont
->m_eType
!= fonttype::TrueType
||
3474 static_cast<TrueTypeFontFile
*>(pSearchFont
)->m_nCollectionEntry
== -1
3478 OString
aFile( getFontFileSysPath( nFont
) );
3479 if( ! aFile
.getLength() )
3482 for( ::std::hash_map
< fontID
, PrintFont
* >::const_iterator it
= m_aFonts
.begin(); it
!= m_aFonts
.end(); ++it
)
3484 if( nFont
!= it
->first
)
3486 OString
aCompFile( getFontFile( it
->second
) );
3487 if( aCompFile
== aFile
)
3489 rFonts
.push_back( it
->first
);
3497 // -------------------------------------------------------------------------
3499 bool PrintFontManager::removeFonts( const ::std::list
< fontID
>& rFonts
)
3502 ::std::list
< fontID
> aDuplicates
;
3503 for( ::std::list
< fontID
>::const_iterator it
= rFonts
.begin(); it
!= rFonts
.end(); ++it
)
3505 ::std::hash_map
< fontID
, PrintFont
* >::const_iterator haveFont
= m_aFonts
.find( *it
);
3506 if( haveFont
== m_aFonts
.end() )
3509 PrintFont
* pFont
= haveFont
->second
;
3510 bool bRemoveDuplicates
= getFileDuplicates( *it
, aDuplicates
);
3511 ByteString
aFile( getFontFile( pFont
) );
3514 #if OSL_DEBUG_LEVEL > 1
3515 fprintf( stderr
, "try unlink( \"%s\" ) ... ", aFile
.GetBuffer() );
3517 if( unlink( aFile
.GetBuffer() ) )
3520 #if OSL_DEBUG_LEVEL > 1
3521 fprintf( stderr
, "failed\n" );
3525 #if OSL_DEBUG_LEVEL > 1
3526 fprintf( stderr
, "succeeded\n" );
3528 OString
aAfm( getAfmFile( pFont
) );
3529 if( aAfm
.getLength() )
3531 #if OSL_DEBUG_LEVEL > 1
3532 fprintf( stderr
, "unlink( \"%s\" )\n", aAfm
.getStr() );
3534 unlink( aAfm
.getStr() );
3536 m_aFonts
.erase( *it
);
3538 if( bRemoveDuplicates
)
3540 for( ::std::list
< fontID
>::iterator dup
= aDuplicates
.begin(); dup
!= aDuplicates
.end(); ++dup
)
3542 m_aFontFileToFontID
[ aFile
].erase( *dup
);
3543 PrintFont
* pDup
= m_aFonts
[ *dup
];
3544 m_aFonts
.erase( *dup
);
3553 // -------------------------------------------------------------------------
3555 bool PrintFontManager::isPrivateFontFile( fontID nFont
) const
3559 PrintFont
* pFont
= getFont( nFont
);
3562 switch( pFont
->m_eType
)
3564 case fonttype::Type1
: nDirID
= static_cast< Type1FontFile
* >(pFont
)->m_nDirectory
;break;
3565 case fonttype::TrueType
: nDirID
= static_cast< TrueTypeFontFile
* >(pFont
)->m_nDirectory
;break;
3571 for( ::std::list
< int >::const_iterator it
= m_aPrivateFontDirectories
.begin(); it
!= m_aPrivateFontDirectories
.end(); ++it
)
3583 // -------------------------------------------------------------------------
3585 bool PrintFontManager::getAlternativeFamilyNames( fontID nFont
, ::std::list
< OUString
>& rNames
) const
3589 PrintFont
* pFont
= getFont( nFont
);
3590 if( pFont
&& pFont
->m_eType
== fonttype::TrueType
)
3592 TrueTypeFontFile
* pTTFontFile
= static_cast< TrueTypeFontFile
* >(pFont
);
3593 ByteString
aFile( getFontFile( pFont
) );
3594 TrueTypeFont
* pTTFont
;
3595 if( OpenTTFontFile( aFile
.GetBuffer(), pTTFontFile
->m_nCollectionEntry
< 0 ? 0 : pTTFontFile
->m_nCollectionEntry
, &pTTFont
) == SF_OK
)
3597 NameRecord
* pNameRecords
= NULL
;
3598 int nNameRecords
= GetTTNameRecords( pTTFont
, &pNameRecords
);
3599 for( int i
= 0; i
< nNameRecords
; i
++ )
3601 if( pNameRecords
[i
].nameID
!= 1 ) // family name
3604 OUString
aFamily( convertTrueTypeName( pNameRecords
+i
) );
3605 if( aFamily
.getLength()
3607 m_pAtoms
->getAtom( ATOM_FAMILYNAME
, aFamily
, sal_True
) != pFont
->m_nFamilyName
3610 rNames
.push_back( aFamily
);
3615 DisposeNameRecords( pNameRecords
, nNameRecords
);
3616 CloseTTFont( pTTFont
);
3619 return rNames
.begin() != rNames
.end();
3622 // -------------------------------------------------------------------------
3624 // TODO: move most of this stuff into the central font-subsetting code
3625 bool PrintFontManager::createFontSubset(
3626 FontSubsetInfo
& rInfo
,
3628 const OUString
& rOutFile
,
3629 sal_Int32
* pGlyphIDs
,
3630 sal_uInt8
* pNewEncoding
,
3636 PrintFont
* pFont
= getFont( nFont
);
3640 switch( pFont
->m_eType
)
3642 case psp::fonttype::TrueType
: rInfo
.m_nFontType
= FontSubsetInfo::SFNT_TTF
; break;
3643 case psp::fonttype::Type1
: rInfo
.m_nFontType
= FontSubsetInfo::ANY_TYPE1
; break;
3647 // TODO: remove when Type1 subsetting gets implemented
3648 if( pFont
->m_eType
!= fonttype::TrueType
)
3651 // reshuffle array of requested glyphs to make sure glyph0==notdef
3652 sal_uInt8 pEnc
[256];
3653 sal_uInt16 pGID
[256];
3654 sal_uInt8 pOldIndex
[256];
3655 memset( pEnc
, 0, sizeof( pEnc
) );
3656 memset( pGID
, 0, sizeof( pGID
) );
3657 memset( pOldIndex
, 0, sizeof( pOldIndex
) );
3661 for( int i
= 0; i
< nGlyphs
; i
++ )
3663 if( pNewEncoding
[i
] == 0 )
3669 DBG_ASSERT( !(pGlyphIDs
[i
] & 0x007f0000), "overlong glyph id" );
3670 DBG_ASSERT( (int)pNewEncoding
[i
] < nGlyphs
, "encoding wrong" );
3671 DBG_ASSERT( pEnc
[pNewEncoding
[i
]] == 0 && pGID
[pNewEncoding
[i
]] == 0, "duplicate encoded glyph" );
3672 pEnc
[ pNewEncoding
[i
] ] = pNewEncoding
[i
];
3673 pGID
[ pNewEncoding
[i
] ] = (sal_uInt16
)pGlyphIDs
[ i
];
3674 pOldIndex
[ pNewEncoding
[i
] ] = i
;
3678 nGlyphs
= nChar
; // either input value or increased by one
3680 // prepare system name for read access for subset source file
3681 // TODO: since this file is usually already mmapped there is no need to open it again
3682 const ByteString aFromFile
= getFontFile( pFont
);
3684 TrueTypeFont
* pTTFont
= NULL
; // TODO: rename to SfntFont
3685 TrueTypeFontFile
* pTTFontFile
= static_cast< TrueTypeFontFile
* >(pFont
);
3686 if( OpenTTFontFile( aFromFile
.GetBuffer(), pTTFontFile
->m_nCollectionEntry
< 0 ? 0 : pTTFontFile
->m_nCollectionEntry
, &pTTFont
) != SF_OK
)
3689 // prepare system name for write access for subset file target
3691 if( osl_File_E_None
!= osl_getSystemPathFromFileURL( rOutFile
.pData
, &aSysPath
.pData
) )
3693 const rtl_TextEncoding aEncoding
= osl_getThreadTextEncoding();
3694 const ByteString
aToFile( OUStringToOString( aSysPath
, aEncoding
) );
3696 // do CFF subsetting if possible
3698 const sal_uInt8
* pCffBytes
= NULL
;
3699 if( GetSfntTable( pTTFont
, O_CFF
, &pCffBytes
, &nCffLength
) )
3701 rInfo
.LoadFont( FontSubsetInfo::CFF_FONT
, pCffBytes
, nCffLength
);
3702 #if 1 // TODO: remove 16bit->long conversion when related methods handle non-16bit glyphids
3703 long aRequestedGlyphs
[256];
3704 for( int i
= 0; i
< nGlyphs
; ++i
)
3705 aRequestedGlyphs
[i
] = pGID
[i
];
3707 // create subset file at requested path
3708 FILE* pOutFile
= fopen( aToFile
.GetBuffer(), "wb" );
3709 // create font subset
3710 const char* pGlyphSetName
= NULL
; // TODO: better name?
3711 const bool bOK
= rInfo
.CreateFontSubset(
3712 FontSubsetInfo::TYPE1_PFB
,
3713 pOutFile
, pGlyphSetName
,
3714 aRequestedGlyphs
, pEnc
, nGlyphs
, pWidths
);
3716 // cleanup before early return
3717 CloseTTFont( pTTFont
);
3721 // do TTF->Type42 or Type3 subsetting
3722 // fill in font info
3723 psp::PrintFontInfo aFontInfo
;
3724 if( ! getFontInfo( nFont
, aFontInfo
) )
3727 rInfo
.m_nAscent
= aFontInfo
.m_nAscend
;
3728 rInfo
.m_nDescent
= aFontInfo
.m_nDescend
;
3729 rInfo
.m_aPSName
= getPSName( nFont
);
3731 int xMin
, yMin
, xMax
, yMax
;
3732 getFontBoundingBox( nFont
, xMin
, yMin
, xMax
, yMax
);
3733 rInfo
.m_aFontBBox
= Rectangle( Point( xMin
, yMin
), Size( xMax
-xMin
, yMax
-yMin
) );
3734 rInfo
.m_nCapHeight
= yMax
; // Well ...
3736 // fill in glyph advance widths
3737 TTSimpleGlyphMetrics
* pMetrics
= GetTTSimpleGlyphMetrics( pTTFont
,
3740 bVertical
? 1 : 0 );
3743 for( int i
= 0; i
< nGlyphs
; i
++ )
3744 pWidths
[pOldIndex
[i
]] = pMetrics
[i
].adv
;
3749 CloseTTFont( pTTFont
);
3753 bool bSuccess
= ( SF_OK
== CreateTTFromTTGlyphs( pTTFont
,
3754 aToFile
.GetBuffer(),
3761 CloseTTFont( pTTFont
);
3766 void PrintFontManager::getGlyphWidths( fontID nFont
,
3768 std::vector
< sal_Int32
>& rWidths
,
3769 std::map
< sal_Unicode
, sal_uInt32
>& rUnicodeEnc
)
3771 PrintFont
* pFont
= getFont( nFont
);
3773 (pFont
->m_eType
!= fonttype::TrueType
&& pFont
->m_eType
!= fonttype::Type1
) )
3775 if( pFont
->m_eType
== fonttype::TrueType
)
3777 TrueTypeFont
* pTTFont
= NULL
;
3778 TrueTypeFontFile
* pTTFontFile
= static_cast< TrueTypeFontFile
* >(pFont
);
3779 ByteString aFromFile
= getFontFile( pFont
);
3780 if( OpenTTFontFile( aFromFile
.GetBuffer(), pTTFontFile
->m_nCollectionEntry
< 0 ? 0 : pTTFontFile
->m_nCollectionEntry
, &pTTFont
) != SF_OK
)
3782 int nGlyphs
= GetTTGlyphCount( pTTFont
);
3785 rWidths
.resize(nGlyphs
);
3786 std::vector
<sal_uInt16
> aGlyphIds(nGlyphs
);
3787 for( int i
= 0; i
< nGlyphs
; i
++ )
3788 aGlyphIds
[i
] = sal_uInt16(i
);
3789 TTSimpleGlyphMetrics
* pMetrics
= GetTTSimpleGlyphMetrics( pTTFont
,
3792 bVertical
? 1 : 0 );
3795 for( int i
= 0; i
< nGlyphs
; i
++ )
3796 rWidths
[i
] = pMetrics
[i
].adv
;
3798 rUnicodeEnc
.clear();
3801 CloseTTFont( pTTFont
);
3803 else if( pFont
->m_eType
== fonttype::Type1
)
3805 if( ! pFont
->m_aEncodingVector
.size() )
3806 pFont
->readAfmMetrics( getAfmFile( pFont
), m_pAtoms
, true, true );
3807 if( pFont
->m_pMetrics
)
3809 rUnicodeEnc
.clear();
3811 rWidths
.reserve( pFont
->m_pMetrics
->m_aMetrics
.size() );
3812 for( std::hash_map
< int, CharacterMetric
>::const_iterator it
=
3813 pFont
->m_pMetrics
->m_aMetrics
.begin();
3814 it
!= pFont
->m_pMetrics
->m_aMetrics
.end(); ++it
)
3816 if( (it
->first
& 0x00010000) == 0 || bVertical
)
3818 rUnicodeEnc
[ sal_Unicode(it
->first
& 0x0000ffff) ] = sal_uInt32(rWidths
.size());
3819 rWidths
.push_back( it
->second
.width
);
3826 // -------------------------------------------------------------------------
3828 const std::map
< sal_Unicode
, sal_Int32
>* PrintFontManager::getEncodingMap( fontID nFont
, const std::map
< sal_Unicode
, rtl::OString
>** pNonEncoded
) const
3830 PrintFont
* pFont
= getFont( nFont
);
3832 (pFont
->m_eType
!= fonttype::Type1
&& pFont
->m_eType
!= fonttype::Builtin
)
3836 if( ! pFont
->m_aEncodingVector
.size() )
3837 pFont
->readAfmMetrics( getAfmFile( pFont
), m_pAtoms
, true, true );
3840 *pNonEncoded
= pFont
->m_aNonEncoded
.size() ? &pFont
->m_aNonEncoded
: NULL
;
3842 return pFont
->m_aEncodingVector
.size() ? &pFont
->m_aEncodingVector
: NULL
;
3845 // -------------------------------------------------------------------------
3847 std::list
< OString
> PrintFontManager::getAdobeNameFromUnicode( sal_Unicode aChar
) const
3849 std::pair
< std::hash_multimap
< sal_Unicode
, rtl::OString
>::const_iterator
,
3850 std::hash_multimap
< sal_Unicode
, rtl::OString
>::const_iterator
> range
3851 = m_aUnicodeToAdobename
.equal_range( aChar
);
3853 std::list
< OString
> aRet
;
3854 for( ; range
.first
!= range
.second
; ++range
.first
)
3855 aRet
.push_back( range
.first
->second
);
3857 if( aRet
.begin() == aRet
.end() && aChar
!= 0 )
3860 sal_Int32 nChars
= snprintf( (char*)aBuf
, sizeof( aBuf
), "uni%.4hX", aChar
);
3861 aRet
.push_back( OString( aBuf
, nChars
) );
3867 // -------------------------------------------------------------------------
3868 std::list
< sal_Unicode
> PrintFontManager::getUnicodeFromAdobeName( const rtl::OString
& rName
) const
3870 std::pair
< std::hash_multimap
< rtl::OString
, sal_Unicode
, rtl::OStringHash
>::const_iterator
,
3871 std::hash_multimap
< rtl::OString
, sal_Unicode
, rtl::OStringHash
>::const_iterator
> range
3872 = m_aAdobenameToUnicode
.equal_range( rName
);
3874 std::list
< sal_Unicode
> aRet
;
3875 for( ; range
.first
!= range
.second
; ++range
.first
)
3876 aRet
.push_back( range
.first
->second
);
3878 if( aRet
.begin() == aRet
.end() )
3880 if( rName
.getLength() == 7 && rName
.indexOf( "uni" ) == 0 )
3882 sal_Unicode aCode
= (sal_Unicode
)rName
.copy( 3 ).toInt32( 16 );
3883 aRet
.push_back( aCode
);
3890 // -------------------------------------------------------------------------
3893 OUString
getString( const Any
& rAny
)
3899 bool getBool( const Any
& rAny
)
3901 sal_Bool bBool
= sal_False
;
3903 return static_cast<bool>(bBool
);
3905 sal_Int32
getInt( const Any
& rAny
)
3912 bool PrintFontManager::readOverrideMetrics()
3914 if( ! m_aOverrideFonts
.empty() )
3917 Reference
< XMultiServiceFactory
> xFact( comphelper::getProcessServiceFactory() );
3920 Reference
< XMaterialHolder
> xMat(
3921 xFact
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.psprint.CompatMetricOverride" ) ) ),
3926 Any
aAny( xMat
->getMaterial() );
3927 Sequence
< Any
> aOverrideFonts
;
3928 if( ! (aAny
>>= aOverrideFonts
) )
3930 sal_Int32 nFonts
= aOverrideFonts
.getLength();
3931 for( sal_Int32 i
= 0; i
< nFonts
; i
++ )
3933 Sequence
< NamedValue
> aMetrics
;
3934 if( ! (aOverrideFonts
.getConstArray()[i
] >>= aMetrics
) )
3936 BuiltinFont
* pFont
= new BuiltinFont();
3937 pFont
->m_nDirectory
= 0;
3938 pFont
->m_bUserOverride
= false;
3939 pFont
->m_eEmbeddedbitmap
= fcstatus::isunset
;
3940 pFont
->m_eAntialias
= fcstatus::isunset
;
3941 pFont
->m_pMetrics
= new PrintFontMetrics
;
3942 memset( pFont
->m_pMetrics
->m_aPages
, 0xff, sizeof( pFont
->m_pMetrics
->m_aPages
) );
3943 pFont
->m_pMetrics
->m_bKernPairsQueried
= true;
3944 sal_Int32 nProps
= aMetrics
.getLength();
3945 const NamedValue
* pProps
= aMetrics
.getConstArray();
3946 for( sal_Int32 n
= 0; n
< nProps
; n
++ )
3948 if( pProps
[n
].Name
.equalsAscii( "FamilyName" ) )
3949 pFont
->m_nFamilyName
= m_pAtoms
->getAtom( ATOM_FAMILYNAME
,
3950 getString(pProps
[n
].Value
),
3952 else if( pProps
[n
].Name
.equalsAscii( "PSName" ) )
3953 pFont
->m_nPSName
= m_pAtoms
->getAtom( ATOM_PSNAME
,
3954 getString(pProps
[n
].Value
),
3956 else if( pProps
[n
].Name
.equalsAscii( "StyleName" ) )
3957 pFont
->m_aStyleName
= getString(pProps
[n
].Value
);
3958 else if( pProps
[n
].Name
.equalsAscii( "Italic" ) )
3959 pFont
->m_eItalic
= static_cast<italic::type
>(getInt(pProps
[n
].Value
));
3960 else if( pProps
[n
].Name
.equalsAscii( "Width" ) )
3961 pFont
->m_eWidth
= static_cast<width::type
>(getInt(pProps
[n
].Value
));
3962 else if( pProps
[n
].Name
.equalsAscii( "Weight" ) )
3963 pFont
->m_eWeight
= static_cast<weight::type
>(getInt(pProps
[n
].Value
));
3964 else if( pProps
[n
].Name
.equalsAscii( "Pitch" ) )
3965 pFont
->m_ePitch
= static_cast<pitch::type
>(getInt(pProps
[n
].Value
));
3966 else if( pProps
[n
].Name
.equalsAscii( "Encoding" ) )
3967 pFont
->m_aEncoding
= static_cast<rtl_TextEncoding
>(getInt(pProps
[n
].Value
));
3968 else if( pProps
[n
].Name
.equalsAscii( "FontEncodingOnly" ) )
3969 pFont
->m_bFontEncodingOnly
= getBool(pProps
[n
].Value
);
3970 else if( pProps
[n
].Name
.equalsAscii( "GlobalMetricXWidth" ) )
3971 pFont
->m_aGlobalMetricX
.width
= getInt(pProps
[n
].Value
);
3972 else if( pProps
[n
].Name
.equalsAscii( "GlobalMetricXHeight" ) )
3973 pFont
->m_aGlobalMetricX
.height
= getInt(pProps
[n
].Value
);
3974 else if( pProps
[n
].Name
.equalsAscii( "GlobalMetricYWidth" ) )
3975 pFont
->m_aGlobalMetricY
.width
= getInt(pProps
[n
].Value
);
3976 else if( pProps
[n
].Name
.equalsAscii( "GlobalMetricYHeight" ) )
3977 pFont
->m_aGlobalMetricY
.height
= getInt(pProps
[n
].Value
);
3978 else if( pProps
[n
].Name
.equalsAscii( "Ascend" ) )
3979 pFont
->m_nAscend
= getInt(pProps
[n
].Value
);
3980 else if( pProps
[n
].Name
.equalsAscii( "Descend" ) )
3981 pFont
->m_nDescend
= getInt(pProps
[n
].Value
);
3982 else if( pProps
[n
].Name
.equalsAscii( "Leading" ) )
3983 pFont
->m_nLeading
= getInt(pProps
[n
].Value
);
3984 else if( pProps
[n
].Name
.equalsAscii( "XMin" ) )
3985 pFont
->m_nXMin
= getInt(pProps
[n
].Value
);
3986 else if( pProps
[n
].Name
.equalsAscii( "YMin" ) )
3987 pFont
->m_nYMin
= getInt(pProps
[n
].Value
);
3988 else if( pProps
[n
].Name
.equalsAscii( "XMax" ) )
3989 pFont
->m_nXMax
= getInt(pProps
[n
].Value
);
3990 else if( pProps
[n
].Name
.equalsAscii( "YMax" ) )
3991 pFont
->m_nYMax
= getInt(pProps
[n
].Value
);
3992 else if( pProps
[n
].Name
.equalsAscii( "VerticalSubstitutes" ) )
3993 pFont
->m_bHaveVerticalSubstitutedGlyphs
= getBool(pProps
[n
].Value
);
3994 else if( pProps
[n
].Name
.equalsAscii( "EncodingVector" ) )
3996 Sequence
< NamedValue
> aEncoding
;
3997 pProps
[n
].Value
>>= aEncoding
;
3998 sal_Int32 nEnc
= aEncoding
.getLength();
3999 const NamedValue
* pEnc
= aEncoding
.getConstArray();
4000 for( sal_Int32 m
= 0; m
< nEnc
; m
++ )
4002 sal_Unicode cCode
= *pEnc
[m
].Name
.getStr();
4003 sal_Int32 nGlyph
= getInt(pEnc
[m
].Value
);
4004 pFont
->m_aEncodingVector
[ cCode
] = nGlyph
;
4007 else if( pProps
[n
].Name
.equalsAscii( "NonEncoded" ) )
4009 Sequence
< NamedValue
> aEncoding
;
4010 pProps
[n
].Value
>>= aEncoding
;
4011 sal_Int32 nEnc
= aEncoding
.getLength();
4012 const NamedValue
* pEnc
= aEncoding
.getConstArray();
4013 for( sal_Int32 m
= 0; m
< nEnc
; m
++ )
4015 sal_Unicode cCode
= *pEnc
[m
].Name
.getStr();
4016 OUString
aGlyphName( getString(pEnc
[m
].Value
) );
4017 pFont
->m_aNonEncoded
[ cCode
] = OUStringToOString(aGlyphName
,RTL_TEXTENCODING_ASCII_US
);
4020 else if( pProps
[n
].Name
.equalsAscii( "CharacterMetrics" ) )
4022 // fill pFont->m_pMetrics->m_aMetrics
4023 // expect triples of int: int -> CharacterMetric.{ width, height }
4024 Sequence
< sal_Int32
> aSeq
;
4025 pProps
[n
].Value
>>= aSeq
;
4026 sal_Int32 nInts
= aSeq
.getLength();
4027 const sal_Int32
* pInts
= aSeq
.getConstArray();
4028 for( sal_Int32 m
= 0; m
< nInts
; m
+=3 )
4030 pFont
->m_pMetrics
->m_aMetrics
[ pInts
[m
] ].width
= static_cast<short int>(pInts
[m
+1]);
4031 pFont
->m_pMetrics
->m_aMetrics
[ pInts
[m
] ].height
= static_cast<short int>(pInts
[m
+2]);
4034 else if( pProps
[n
].Name
.equalsAscii( "XKernPairs" ) )
4036 // fill pFont->m_pMetrics->m_aXKernPairs
4037 // expection name: <unicode1><unicode2> value: ((height << 16)| width)
4038 Sequence
< NamedValue
> aKern
;
4039 pProps
[n
].Value
>>= aKern
;
4041 const NamedValue
* pVals
= aKern
.getConstArray();
4042 int nPairs
= aKern
.getLength();
4043 for( int m
= 0; m
< nPairs
; m
++ )
4045 if( pVals
[m
].Name
.getLength() == 2 )
4047 aPair
.first
= pVals
[m
].Name
.getStr()[0];
4048 aPair
.second
= pVals
[m
].Name
.getStr()[1];
4049 sal_Int32 nKern
= getInt( pVals
[m
].Value
);
4050 aPair
.kern_x
= static_cast<short int>(nKern
& 0xffff);
4051 aPair
.kern_y
= static_cast<short int>((sal_uInt32(nKern
) >> 16) & 0xffff);
4052 pFont
->m_pMetrics
->m_aXKernPairs
.push_back( aPair
);
4058 if( pFont
->m_nPSName
&&
4059 pFont
->m_nFamilyName
&&
4060 ! pFont
->m_pMetrics
->m_aMetrics
.empty() )
4062 m_aOverrideFonts
.push_back( m_nNextFontID
);
4063 m_aFonts
[ m_nNextFontID
++ ] = pFont
;
4067 DBG_ASSERT( 0, "override font failed" );