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