Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #ifndef _PSPRINT_FONTMANAGER_HXX_
21 : #define _PSPRINT_FONTMANAGER_HXX_
22 :
23 : #include <boost/unordered_map.hpp>
24 : #include <map>
25 : #include <list>
26 : #include <set>
27 :
28 : #include "vcl/dllapi.h"
29 : #include "vcl/helper.hxx"
30 : #include "vcl/timer.hxx"
31 : #include "vcl/vclenum.hxx"
32 : #include "com/sun/star/lang/Locale.hpp"
33 :
34 : #include <vector>
35 :
36 : #define ATOM_FAMILYNAME 2
37 : #define ATOM_PSNAME 3
38 :
39 : /*
40 : * some words on metrics: every length returned by PrintFontManager and
41 : * friends are PostScript afm style, that is they are 1/1000 font height
42 : */
43 :
44 : // forward declarations
45 : namespace utl { class MultiAtomProvider; } // see unotools/atom.hxx
46 : class FontSubsetInfo;
47 : class ImplFontOptions;
48 : class FontSelectPattern;
49 :
50 : namespace psp {
51 : class PPDParser; // see ppdparser.hxx
52 :
53 : namespace fonttype
54 : {
55 : enum type {
56 : Unknown = 0,
57 : Type1 = 1,
58 : TrueType = 2,
59 : Builtin = 3
60 : };
61 : }
62 :
63 : /*
64 : * the difference between FastPrintFontInfo and PrintFontInfo
65 : * is that the information in FastPrintFontInfo can usually
66 : * be gathered without openening either the font file or
67 : * an afm metric file. they are gathered from fonts.dir alone.
68 : * if only FastPrintFontInfo is gathered and PrintFontInfo
69 : * on demand and for less fonts, then performance in startup
70 : * increases considerably
71 : */
72 :
73 12742 : struct FastPrintFontInfo
74 : {
75 : fontID m_nID; // FontID
76 : fonttype::type m_eType;
77 :
78 : // font attributes
79 : OUString m_aFamilyName;
80 : OUString m_aStyleName;
81 : std::list< OUString > m_aAliases;
82 : FontFamily m_eFamilyStyle;
83 : FontItalic m_eItalic;
84 : FontWidth m_eWidth;
85 : FontWeight m_eWeight;
86 : FontPitch m_ePitch;
87 : rtl_TextEncoding m_aEncoding;
88 : bool m_bSubsettable;
89 : bool m_bEmbeddable;
90 :
91 12742 : FastPrintFontInfo() :
92 : m_nID( 0 ),
93 : m_eType( fonttype::Unknown ),
94 : m_eFamilyStyle( FAMILY_DONTKNOW ),
95 : m_eItalic( ITALIC_DONTKNOW ),
96 : m_eWidth( WIDTH_DONTKNOW ),
97 : m_eWeight( WEIGHT_DONTKNOW ),
98 : m_ePitch( PITCH_DONTKNOW ),
99 12742 : m_aEncoding( RTL_TEXTENCODING_DONTKNOW )
100 12742 : {}
101 : };
102 :
103 64 : struct PrintFontInfo : public FastPrintFontInfo
104 : {
105 : int m_nAscend;
106 : int m_nDescend;
107 : int m_nLeading;
108 : int m_nWidth;
109 :
110 64 : PrintFontInfo() :
111 : FastPrintFontInfo(),
112 : m_nAscend( 0 ),
113 : m_nDescend( 0 ),
114 : m_nLeading( 0 ),
115 64 : m_nWidth( 0 )
116 64 : {}
117 : };
118 :
119 : // the values are per thousand of the font size
120 : // note: width, height contain advances, not bounding box
121 : struct CharacterMetric
122 : {
123 : short int width, height;
124 :
125 101936 : CharacterMetric() : width( 0 ), height( 0 ) {}
126 : bool operator==( const CharacterMetric& rOther ) const
127 : { return rOther.width == width && rOther.height == height; }
128 3250 : bool operator!=( const CharacterMetric& rOther ) const
129 3250 : { return rOther.width != width || rOther.height != height; }
130 : };
131 :
132 : struct KernPair
133 : {
134 : sal_Unicode first, second;
135 : short int kern_x, kern_y;
136 :
137 0 : KernPair() : first( 0 ), second( 0 ), kern_x( 0 ), kern_y( 0 ) {}
138 : };
139 :
140 : class FontCache;
141 :
142 : // a class to manage printable fonts
143 : // aims are type1 and truetype fonts
144 :
145 : class FontCache;
146 :
147 : class VCL_PLUGIN_PUBLIC PrintFontManager
148 : {
149 : struct PrintFont;
150 : struct TrueTypeFontFile;
151 : struct Type1FontFile;
152 : struct BuiltinFont;
153 : friend struct PrintFont;
154 : friend struct TrueTypeFontFile;
155 : friend struct Type1FontFile;
156 : friend struct BuiltinFont;
157 : friend class FontCache;
158 :
159 8479 : struct PrintFontMetrics
160 : {
161 : // character metrics are stored by the following keys:
162 : // lower two bytes contain a sal_Unicode (a UCS2 character)
163 : // upper byte contains: 0 for horizontal metric
164 : // 1 for vertical metric
165 : // highest byte: 0 for now
166 : boost::unordered_map< int, CharacterMetric > m_aMetrics;
167 : // contains the unicode blocks for which metrics were queried
168 : // this implies that metrics should be queried in terms of
169 : // unicode blocks. here a unicode block is identified
170 : // by the upper byte of the UCS2 encoding.
171 : // note that the corresponding bit should be set even
172 : // if the font does not support a single character of that page
173 : // this map shows, which pages were queried already
174 : // if (like in AFM metrics) all metrics are queried in
175 : // a single pass, then all bits should be set
176 : char m_aPages[32];
177 :
178 : bool m_bKernPairsQueried;
179 : std::list< KernPair > m_aXKernPairs;
180 : std::list< KernPair > m_aYKernPairs;
181 : boost::unordered_map< sal_Unicode, bool > m_bVerticalSubstitutions;
182 :
183 8479 : PrintFontMetrics() : m_bKernPairsQueried( false ) {}
184 :
185 0 : bool isEmpty() const { return m_aMetrics.empty(); }
186 : };
187 :
188 : struct PrintFont
189 : {
190 : fonttype::type m_eType;
191 :
192 : // font attributes
193 : int m_nFamilyName; // atom
194 : std::list< int > m_aAliases;
195 : int m_nPSName; // atom
196 : OUString m_aStyleName;
197 : FontItalic m_eItalic;
198 : FontWidth m_eWidth;
199 : FontWeight m_eWeight;
200 : FontPitch m_ePitch;
201 : rtl_TextEncoding m_aEncoding;
202 : bool m_bFontEncodingOnly; // set if font should be only accessed by builtin encoding
203 : CharacterMetric m_aGlobalMetricX;
204 : CharacterMetric m_aGlobalMetricY;
205 : PrintFontMetrics* m_pMetrics;
206 : int m_nAscend;
207 : int m_nDescend;
208 : int m_nLeading;
209 : int m_nXMin; // font bounding box
210 : int m_nYMin;
211 : int m_nXMax;
212 : int m_nYMax;
213 : bool m_bHaveVerticalSubstitutedGlyphs;
214 : bool m_bUserOverride;
215 :
216 : std::map< sal_Unicode, sal_Int32 > m_aEncodingVector;
217 : std::map< sal_Unicode, OString > m_aNonEncoded;
218 :
219 : explicit PrintFont( fonttype::type eType );
220 : virtual ~PrintFont();
221 : virtual bool queryMetricPage( int nPage, utl::MultiAtomProvider* pProvider ) = 0;
222 :
223 : bool readAfmMetrics( utl::MultiAtomProvider* pProvider, bool bFillEncodingvector, bool bOnlyGlobalAttributes );
224 : };
225 :
226 : struct Type1FontFile : public PrintFont
227 : {
228 : int m_nDirectory; // atom containing system dependent path
229 : OString m_aFontFile; // relative to directory
230 : OString m_aMetricFile; // dito
231 :
232 : /* note: m_aFontFile and Metric file are not atoms
233 : because they should be fairly unique */
234 :
235 11750 : Type1FontFile() : PrintFont( fonttype::Type1 ), m_nDirectory( 0 ) {}
236 : virtual ~Type1FontFile();
237 : virtual bool queryMetricPage( int nPage, utl::MultiAtomProvider* pProvider );
238 : };
239 :
240 : struct TrueTypeFontFile : public PrintFont
241 : {
242 : int m_nDirectory; // atom containing system dependent path
243 : OString m_aFontFile; // relative to directory
244 : int m_nCollectionEntry; // 0 for regular fonts, 0 to ... for fonts stemming from collections
245 : unsigned int m_nTypeFlags; // copyright bits and PS-OpenType flag
246 :
247 : TrueTypeFontFile();
248 : virtual ~TrueTypeFontFile();
249 : virtual bool queryMetricPage( int nPage, utl::MultiAtomProvider* pProvider );
250 : };
251 :
252 : struct BuiltinFont : public PrintFont
253 : {
254 : int m_nDirectory; // atom containing system dependent path
255 : OString m_aMetricFile;
256 :
257 5208 : BuiltinFont() : PrintFont( fonttype::Builtin ) {}
258 : virtual ~BuiltinFont();
259 : virtual bool queryMetricPage( int nPage, utl::MultiAtomProvider* pProvider );
260 : };
261 :
262 : fontID m_nNextFontID;
263 : boost::unordered_map< fontID, PrintFont* > m_aFonts;
264 : boost::unordered_map< int, FontFamily > m_aFamilyTypes;
265 : std::list< OUString > m_aPrinterDrivers;
266 : std::list< OString > m_aFontDirectories;
267 : std::list< int > m_aPrivateFontDirectories;
268 : utl::MultiAtomProvider* m_pAtoms;
269 : // for speeding up findFontFileID
270 : boost::unordered_map< OString, std::set< fontID >, OStringHash >
271 : m_aFontFileToFontID;
272 :
273 : boost::unordered_map< OString, int, OStringHash >
274 : m_aDirToAtom;
275 : boost::unordered_map< int, OString > m_aAtomToDir;
276 : int m_nNextDirAtom;
277 :
278 : boost::unordered_multimap< OString, sal_Unicode, OStringHash >
279 : m_aAdobenameToUnicode;
280 : boost::unordered_multimap< sal_Unicode, OString >
281 : m_aUnicodeToAdobename;
282 : boost::unordered_multimap< sal_Unicode, sal_uInt8 > m_aUnicodeToAdobecode;
283 : boost::unordered_multimap< sal_uInt8, sal_Unicode > m_aAdobecodeToUnicode;
284 :
285 : mutable FontCache* m_pFontCache;
286 :
287 : OString getAfmFile( PrintFont* pFont ) const;
288 : OString getFontFile( PrintFont* pFont ) const;
289 :
290 : bool analyzeFontFile( int nDirID, const OString& rFileName, std::list< PrintFont* >& rNewFonts, const char *pFormat=NULL ) const;
291 : OUString convertTrueTypeName( void* pNameRecord ) const; // actually a NameRecord* formt font subsetting code
292 : void analyzeTrueTypeFamilyName( void* pTTFont, std::list< OUString >& rnames ) const; // actually a TrueTypeFont* from font subsetting code
293 : bool analyzeTrueTypeFile( PrintFont* pFont ) const;
294 : // finds the font id for the nFaceIndex face in this font file
295 : // There may be multiple font ids for TrueType collections
296 : fontID findFontFileID( int nDirID, const OString& rFile, int nFaceIndex ) const;
297 :
298 : // There may be multiple font ids for TrueType collections
299 : std::vector<fontID> findFontFileIDs( int nDirID, const OString& rFile ) const;
300 :
301 : bool knownFontFile( int nDirID, const OString& rFile ) const
302 : {
303 : return findFontFileID(nDirID, rFile, 0) != 0;
304 : }
305 :
306 : fontID findFontBuiltinID( int nPSNameAtom ) const;
307 :
308 : FontFamily matchFamilyName( const OUString& rFamily ) const;
309 :
310 112596 : PrintFont* getFont( fontID nID ) const
311 : {
312 112596 : boost::unordered_map< fontID, PrintFont* >::const_iterator it;
313 112596 : it = m_aFonts.find( nID );
314 112596 : return it == m_aFonts.end() ? NULL : it->second;
315 : }
316 : void fillPrintFontInfo( PrintFont* pFont, FastPrintFontInfo& rInfo ) const;
317 : void fillPrintFontInfo( PrintFont* pFont, PrintFontInfo& rInfo ) const;
318 :
319 : OString getDirectory( int nAtom ) const;
320 : int getDirectoryAtom( const OString& rDirectory, bool bCreate = false );
321 :
322 : /* try to initialize fonts from libfontconfig
323 :
324 : called from <code>initialize()</code>
325 : */
326 : void initFontconfig();
327 : void countFontconfigFonts( boost::unordered_map<OString, int, OStringHash>& o_rVisitedPaths );
328 : /* deinitialize fontconfig
329 : */
330 : void deinitFontconfig();
331 :
332 : /* register an application specific font directory for libfontconfig
333 :
334 : since fontconfig is asked for font substitutes before OOo will check for font availability
335 : and fontconfig will happily substitute fonts it doesn't know (e.g. "Arial Narrow" -> "DejaVu Sans Book"!)
336 : it becomes necessary to tell the library about all the hidden font treasures
337 :
338 : @returns
339 : true if libfontconfig accepted the directory
340 : false else (e.g. no libfontconfig found)
341 : */
342 : bool addFontconfigDir(const OString& rDirectory);
343 :
344 : std::set<OString> m_aPreviousLangSupportRequests;
345 : std::vector<OString> m_aCurrentRequests;
346 : Timer m_aFontInstallerTimer;
347 :
348 : DECL_LINK( autoInstallFontLangSupport, void* );
349 :
350 : PrintFontManager();
351 : ~PrintFontManager();
352 : public:
353 : static PrintFontManager& get(); // one instance only
354 :
355 : // There may be multiple font ids for TrueType collections
356 : std::vector<fontID> addFontFile( const OString& rFileName );
357 :
358 : void initialize();
359 :
360 : // returns the number of managed fonts
361 : int getFontCount() const { return m_aFonts.size(); }
362 :
363 : // caution: the getFontList* methods can change the font list on demand
364 : // depending on the pParser argument. That is getFontCount() may
365 : // return a larger value after getFontList()
366 :
367 : // returns the ids of all managed fonts. on pParser != NULL
368 : // all fonttype::Builtin type fonts are not listed
369 : // which do not occur in the PPD of pParser
370 : void getFontList( std::list< fontID >& rFontIDs, const PPDParser* pParser = NULL );
371 : // get the font list and fast font info. see getFontList for pParser
372 : void getFontListWithFastInfo( std::list< FastPrintFontInfo >& rFonts, const PPDParser* pParser = NULL );
373 :
374 : // get font info for a specific font
375 : bool getFontInfo( fontID nFontID, PrintFontInfo& rInfo ) const;
376 : // get fast font info for a specific font
377 : bool getFontFastInfo( fontID nFontID, FastPrintFontInfo& rInfo ) const;
378 :
379 : // routines to get font info in small pieces
380 :
381 : // get a specific fonts PSName name
382 : const OUString& getPSName( fontID nFontID ) const;
383 :
384 : // get a specific fonts family name aliases
385 : void getFontFamilyAliases( fontID nFontID ) const;
386 :
387 : // get a specific fonts type
388 1051 : fonttype::type getFontType( fontID nFontID ) const
389 : {
390 1051 : PrintFont* pFont = getFont( nFontID );
391 1051 : return pFont ? pFont->m_eType : fonttype::Unknown;
392 : }
393 :
394 : // get a specific fonts italic type
395 30 : FontItalic getFontItalic( fontID nFontID ) const
396 : {
397 30 : PrintFont* pFont = getFont( nFontID );
398 30 : return pFont ? pFont->m_eItalic : ITALIC_DONTKNOW;
399 : }
400 :
401 : // get a specific fonts width type
402 : FontWidth getFontWidth( fontID nFontID ) const
403 : {
404 : PrintFont* pFont = getFont( nFontID );
405 : return pFont ? pFont->m_eWidth : WIDTH_DONTKNOW;
406 : }
407 :
408 : // get a specific fonts weight type
409 109 : FontWeight getFontWeight( fontID nFontID ) const
410 : {
411 109 : PrintFont* pFont = getFont( nFontID );
412 109 : return pFont ? pFont->m_eWeight : WEIGHT_DONTKNOW;
413 : }
414 :
415 : // get a specific fonts pitch type
416 : FontPitch getFontPitch( fontID nFontID ) const
417 : {
418 : PrintFont* pFont = getFont( nFontID );
419 : return pFont ? pFont->m_ePitch : PITCH_DONTKNOW;
420 : }
421 :
422 : // get a specific fonts encoding
423 0 : rtl_TextEncoding getFontEncoding( fontID nFontID ) const
424 : {
425 0 : PrintFont* pFont = getFont( nFontID );
426 0 : return pFont ? pFont->m_aEncoding : RTL_TEXTENCODING_DONTKNOW;
427 : }
428 :
429 : // should i only use font's builtin encoding ?
430 0 : bool getUseOnlyFontEncoding( fontID nFontID ) const
431 : {
432 0 : PrintFont* pFont = getFont( nFontID );
433 0 : return pFont ? pFont->m_bFontEncodingOnly : false;
434 : }
435 :
436 : // get a specific fonts system dependent filename
437 34009 : OString getFontFileSysPath( fontID nFontID ) const
438 : {
439 34009 : return getFontFile( getFont( nFontID ) );
440 : }
441 :
442 : // get the ttc face number
443 : int getFontFaceNumber( fontID nFontID ) const;
444 :
445 : // get a specific fonts ascend
446 : int getFontAscend( fontID nFontID ) const;
447 :
448 : // get a specific fonts descent
449 : int getFontDescend( fontID nFontID ) const;
450 :
451 : // get a fonts glyph bounding box
452 : bool getFontBoundingBox( fontID nFont, int& xMin, int& yMin, int& xMax, int& yMax );
453 :
454 : // info whether an array of glyphs has vertical substitutions
455 : void hasVerticalSubstitutions( fontID nFontID, const sal_Unicode* pCharacters,
456 : int nCharacters, bool* pHasSubst ) const;
457 :
458 : // get a specific fonts metrics
459 :
460 : // get metrics for a sal_Unicode range
461 : // the user is responsible to allocate pArray large enough
462 : bool getMetrics( fontID nFontID, sal_Unicode minCharacter, sal_Unicode maxCharacter, CharacterMetric* pArray, bool bVertical = false ) const;
463 : // get metrics for an array of sal_Unicode characters
464 : // the user is responsible to allocate pArray large enough
465 : bool getMetrics( fontID nFontID, const sal_Unicode* pString, int nLen, CharacterMetric* pArray, bool bVertical = false ) const;
466 :
467 : // get encoding vector of font, currently only for Type1 and Builtin fonts
468 : // returns NULL if encoding vector is empty or font is neither type1 or
469 : // builtin; if ppNonEncoded is set and non encoded type1 glyphs exist
470 : // then *ppNonEncoded is set to the mapping for nonencoded glyphs.
471 : // the encoding vector contains -1 for non encoded glyphs
472 : const std::map< sal_Unicode, sal_Int32 >* getEncodingMap( fontID nFontID, const std::map< sal_Unicode, OString >** ppNonEncoded ) const;
473 :
474 : // to get font substitution transparently use the
475 : // getKernPairs method of PrinterGfx
476 : const std::list< KernPair >& getKernPairs( fontID nFontID, bool bVertical = false ) const;
477 :
478 : // evaluates copyright flags for TrueType fonts for printing/viewing
479 : // type1 fonts do not have such a feature, so return for them is true
480 : // returns true for builtin fonts (surprise!)
481 : bool isFontDownloadingAllowedForPrinting( fontID nFont ) const;
482 :
483 : // helper for type 1 fonts
484 : std::list< OString > getAdobeNameFromUnicode( sal_Unicode aChar ) const;
485 :
486 : std::pair< boost::unordered_multimap< sal_Unicode, sal_uInt8 >::const_iterator,
487 : boost::unordered_multimap< sal_Unicode, sal_uInt8 >::const_iterator >
488 : getAdobeCodeFromUnicode( sal_Unicode aChar ) const
489 : {
490 : return m_aUnicodeToAdobecode.equal_range( aChar );
491 : }
492 : std::list< sal_Unicode > getUnicodeFromAdobeName( const OString& rName ) const;
493 : std::pair< boost::unordered_multimap< sal_uInt8, sal_Unicode >::const_iterator,
494 : boost::unordered_multimap< sal_uInt8, sal_Unicode >::const_iterator >
495 0 : getUnicodeFromAdobeCode( sal_uInt8 aChar ) const
496 : {
497 0 : return m_aAdobecodeToUnicode.equal_range( aChar );
498 : }
499 :
500 : // creates a new font subset of an existing TrueType font
501 : // returns true in case of success, else false
502 : // nFont: the font to be subsetted
503 : // rOutFile: the file to put the new subset into;
504 : // must be a valid osl file URL
505 : // pGlyphIDs: input array of glyph ids for new font
506 : // pNewEncoding: the corresponding encoding in the new font
507 : // pWidths: output array of widths of requested glyphs
508 : // nGlyphs: number of glyphs in arrays
509 : // pCapHeight:: capital height of the produced font
510 : // pXMin, pYMin, pXMax, pYMax: outgoing font bounding box
511 : // TODO: callers of this method should use its FontSubsetInfo counterpart directly
512 : bool createFontSubset( FontSubsetInfo&,
513 : fontID nFont,
514 : const OUString& rOutFile,
515 : sal_Int32* pGlyphIDs,
516 : sal_uInt8* pNewEncoding,
517 : sal_Int32* pWidths,
518 : int nGlyphs,
519 : bool bVertical = false
520 : );
521 : void getGlyphWidths( fontID nFont,
522 : bool bVertical,
523 : std::vector< sal_Int32 >& rWidths,
524 : std::map< sal_Unicode, sal_uInt32 >& rUnicodeEnc );
525 :
526 :
527 : // font administration functions
528 :
529 : /* system dependendent font matching
530 :
531 : <p>
532 : <code>matchFont</code> matches a pattern of font characteristics
533 : and returns the closest match if possibe. If a match was found
534 : the <code>FastPrintFontInfo</code> passed in as parameter
535 : will be update to the found matching font.
536 : </p>
537 : <p>
538 : implementation note: currently the function is only implemented
539 : for fontconfig.
540 : </p>
541 :
542 : @param rInfo
543 : out of the FastPrintFontInfo structure the following
544 : fields will be used for the match:
545 : <ul>
546 : <li>family name</li>
547 : <li>italic</li>
548 : <li>width</li>
549 : <li>weight</li>
550 : <li>pitch</li>
551 : </ul>
552 :
553 : @param rLocale
554 : if <code>rLocal</code> contains non empty strings the corresponding
555 : locale will be used for font matching also; e.g. "Sans" can result
556 : in different fonts in e.g. english and japanese
557 :
558 : @returns
559 : true if a match was found
560 : false else
561 : */
562 : bool matchFont( FastPrintFontInfo& rInfo, const com::sun::star::lang::Locale& rLocale );
563 : ImplFontOptions* getFontOptions( const FastPrintFontInfo&, int nSize, void (*subcallback)(void*)) const;
564 :
565 : bool Substitute( FontSelectPattern &rPattern, OUString& rMissingCodes );
566 :
567 : int FreeTypeCharIndex( void *pFace, sal_uInt32 aChar );
568 : };
569 :
570 : } // namespace
571 :
572 : #endif // _PSPRINT_FONTMANAGER_HXX_
573 :
574 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|