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 <list>
24 : #include <map>
25 : #include <set>
26 : #include <unordered_map>
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 : namespace utl { class MultiAtomProvider; }
46 :
47 : class FontSubsetInfo;
48 : class ImplFontOptions;
49 : class FontSelectPattern;
50 :
51 : namespace psp {
52 : class PPDParser;
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 12497 : 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 12497 : 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 12497 : , m_bEmbeddable(false)
102 12497 : {}
103 : };
104 :
105 271 : struct PrintFontInfo : public FastPrintFontInfo
106 : {
107 : int m_nAscend;
108 : int m_nDescend;
109 : int m_nLeading;
110 : int m_nWidth;
111 :
112 271 : PrintFontInfo() :
113 : FastPrintFontInfo(),
114 : m_nAscend( 0 ),
115 : m_nDescend( 0 ),
116 : m_nLeading( 0 ),
117 271 : m_nWidth( 0 )
118 271 : {}
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 198266 : CharacterMetric() : width( 0 ), height( 0 ) {}
128 : bool operator==( const CharacterMetric& rOther ) const
129 : { return rOther.width == width && rOther.height == height; }
130 69794 : bool operator!=( const CharacterMetric& rOther ) const
131 69794 : { 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 3655 : 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 : std::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 : std::unordered_map< sal_Unicode, bool > m_bVerticalSubstitutions;
171 :
172 3655 : PrintFontMetrics() {}
173 :
174 4174 : 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 : /// mapping from unicode (well, UCS-2) to font code
206 : std::map< sal_Unicode, sal_Int32 > m_aEncodingVector;
207 : /// HACK for Type 1 fonts: if multiple UCS-2 codes map to the same
208 : /// font code, this set contains the preferred one, i.e., the one that
209 : /// is specified explicitly via "C" or "CH" in the AFM file
210 : std::set<sal_Unicode> m_aEncodingVectorPriority;
211 : std::map< sal_Unicode, OString > m_aNonEncoded;
212 :
213 : explicit PrintFont( fonttype::type eType );
214 : virtual ~PrintFont();
215 : virtual bool queryMetricPage( int nPage, utl::MultiAtomProvider* pProvider ) = 0;
216 :
217 : bool readAfmMetrics( utl::MultiAtomProvider* pProvider, bool bFillEncodingvector, bool bOnlyGlobalAttributes );
218 : };
219 :
220 : struct Type1FontFile : public PrintFont
221 : {
222 : int m_nDirectory; // atom containing system dependent path
223 : OString m_aFontFile; // relative to directory
224 : OString m_aMetricFile; // dito
225 :
226 : /* note: m_aFontFile and Metric file are not atoms
227 : because they should be fairly unique */
228 :
229 25830 : Type1FontFile() : PrintFont( fonttype::Type1 ), m_nDirectory( 0 ) {}
230 : virtual ~Type1FontFile();
231 : virtual bool queryMetricPage( int nPage, utl::MultiAtomProvider* pProvider ) SAL_OVERRIDE;
232 : };
233 :
234 : struct TrueTypeFontFile : public PrintFont
235 : {
236 : int m_nDirectory; // atom containing system dependent path
237 : OString m_aFontFile; // relative to directory
238 : int m_nCollectionEntry; // 0 for regular fonts, 0 to ... for fonts stemming from collections
239 : unsigned int m_nTypeFlags; // copyright bits and PS-OpenType flag
240 :
241 : TrueTypeFontFile();
242 : virtual ~TrueTypeFontFile();
243 : virtual bool queryMetricPage( int nPage, utl::MultiAtomProvider* pProvider ) SAL_OVERRIDE;
244 : };
245 :
246 : fontID m_nNextFontID;
247 : std::unordered_map< fontID, PrintFont* > m_aFonts;
248 : std::unordered_map< int, FontFamily > m_aFamilyTypes;
249 : std::list< OUString > m_aPrinterDrivers;
250 : std::list< OString > m_aFontDirectories;
251 : std::list< int > m_aPrivateFontDirectories;
252 : utl::MultiAtomProvider* m_pAtoms;
253 : // for speeding up findFontFileID
254 : std::unordered_map< OString, std::set< fontID >, OStringHash >
255 : m_aFontFileToFontID;
256 :
257 : std::unordered_map< OString, int, OStringHash >
258 : m_aDirToAtom;
259 : std::unordered_map< int, OString > m_aAtomToDir;
260 : int m_nNextDirAtom;
261 :
262 : std::unordered_multimap< OString, sal_Unicode, OStringHash >
263 : m_aAdobenameToUnicode;
264 : std::unordered_multimap< sal_Unicode, OString >
265 : m_aUnicodeToAdobename;
266 : std::unordered_multimap< sal_Unicode, sal_uInt8 > m_aUnicodeToAdobecode;
267 : std::unordered_multimap< sal_uInt8, sal_Unicode > m_aAdobecodeToUnicode;
268 :
269 : mutable FontCache* m_pFontCache;
270 :
271 : OString getAfmFile( PrintFont* pFont ) const;
272 : OString getFontFile( PrintFont* pFont ) const;
273 :
274 : bool analyzeFontFile( int nDirID, const OString& rFileName, std::list< PrintFont* >& rNewFonts, const char *pFormat=NULL ) const;
275 : static OUString convertTrueTypeName( void* pNameRecord ); // actually a NameRecord* formt font subsetting code
276 : static void analyzeTrueTypeFamilyName( void* pTTFont, std::list< OUString >& rnames ); // actually a TrueTypeFont* from font subsetting code
277 : bool analyzeTrueTypeFile( PrintFont* pFont ) const;
278 : // finds the font id for the nFaceIndex face in this font file
279 : // There may be multiple font ids for TrueType collections
280 : fontID findFontFileID( int nDirID, const OString& rFile, int nFaceIndex ) const;
281 :
282 : // There may be multiple font ids for TrueType collections
283 : std::vector<fontID> findFontFileIDs( int nDirID, const OString& rFile ) const;
284 :
285 : bool knownFontFile( int nDirID, const OString& rFile ) const
286 : {
287 : return findFontFileID(nDirID, rFile, 0) != 0;
288 : }
289 :
290 : static FontFamily matchFamilyName( const OUString& rFamily );
291 :
292 479858 : PrintFont* getFont( fontID nID ) const
293 : {
294 479858 : std::unordered_map< fontID, PrintFont* >::const_iterator it;
295 479858 : it = m_aFonts.find( nID );
296 479858 : return it == m_aFonts.end() ? NULL : it->second;
297 : }
298 : void fillPrintFontInfo( PrintFont* pFont, FastPrintFontInfo& rInfo ) const;
299 : void fillPrintFontInfo( PrintFont* pFont, PrintFontInfo& rInfo ) const;
300 :
301 : OString getDirectory( int nAtom ) const;
302 : int getDirectoryAtom( const OString& rDirectory, bool bCreate = false );
303 :
304 : /* try to initialize fonts from libfontconfig
305 :
306 : called from <code>initialize()</code>
307 : */
308 : static void initFontconfig();
309 : void countFontconfigFonts( std::unordered_map<OString, int, OStringHash>& o_rVisitedPaths );
310 : /* deinitialize fontconfig
311 : */
312 : static void deinitFontconfig();
313 :
314 : /* register an application specific font directory for libfontconfig
315 :
316 : since fontconfig is asked for font substitutes before OOo will check for font availability
317 : and fontconfig will happily substitute fonts it doesn't know (e.g. "Arial Narrow" -> "DejaVu Sans Book"!)
318 : it becomes necessary to tell the library about all the hidden font treasures
319 :
320 : @returns
321 : true if libfontconfig accepted the directory
322 : false else (e.g. no libfontconfig found)
323 : */
324 : static bool addFontconfigDir(const OString& rDirectory);
325 :
326 : std::set<OString> m_aPreviousLangSupportRequests;
327 : std::vector<OString> m_aCurrentRequests;
328 : Timer m_aFontInstallerTimer;
329 :
330 : #if defined(ENABLE_DBUS) && defined(ENABLE_PACKAGEKIT)
331 : DECL_LINK_TYPED( autoInstallFontLangSupport, Timer*, void );
332 : #endif
333 : PrintFontManager();
334 : ~PrintFontManager();
335 : public:
336 : static PrintFontManager& get(); // one instance only
337 :
338 : // There may be multiple font ids for TrueType collections
339 : std::vector<fontID> addFontFile( const OString& rFileName );
340 :
341 : void initialize();
342 :
343 : // returns the number of managed fonts
344 : int getFontCount() const { return m_aFonts.size(); }
345 :
346 : // returns the ids of all managed fonts.
347 : void getFontList( std::list< fontID >& rFontIDs );
348 :
349 : // get font info for a specific font
350 : bool getFontInfo( fontID nFontID, PrintFontInfo& rInfo ) const;
351 : // get fast font info for a specific font
352 : bool getFontFastInfo( fontID nFontID, FastPrintFontInfo& rInfo ) const;
353 :
354 : // routines to get font info in small pieces
355 :
356 : // get a specific fonts PSName name
357 : const OUString& getPSName( fontID nFontID ) const;
358 :
359 : // get a specific fonts family name aliases
360 : void getFontFamilyAliases( fontID nFontID ) const;
361 :
362 : // get a specific fonts type
363 3043 : fonttype::type getFontType( fontID nFontID ) const
364 : {
365 3043 : PrintFont* pFont = getFont( nFontID );
366 3043 : return pFont ? pFont->m_eType : fonttype::Unknown;
367 : }
368 :
369 : // get a specific fonts italic type
370 73 : FontItalic getFontItalic( fontID nFontID ) const
371 : {
372 73 : PrintFont* pFont = getFont( nFontID );
373 73 : return pFont ? pFont->m_eItalic : ITALIC_DONTKNOW;
374 : }
375 :
376 : // get a specific fonts width type
377 : FontWidth getFontWidth( fontID nFontID ) const
378 : {
379 : PrintFont* pFont = getFont( nFontID );
380 : return pFont ? pFont->m_eWidth : WIDTH_DONTKNOW;
381 : }
382 :
383 : // get a specific fonts weight type
384 753 : FontWeight getFontWeight( fontID nFontID ) const
385 : {
386 753 : PrintFont* pFont = getFont( nFontID );
387 753 : return pFont ? pFont->m_eWeight : WEIGHT_DONTKNOW;
388 : }
389 :
390 : // get a specific fonts pitch type
391 : FontPitch getFontPitch( fontID nFontID ) const
392 : {
393 : PrintFont* pFont = getFont( nFontID );
394 : return pFont ? pFont->m_ePitch : PITCH_DONTKNOW;
395 : }
396 :
397 : // get a specific fonts encoding
398 2131 : rtl_TextEncoding getFontEncoding( fontID nFontID ) const
399 : {
400 2131 : PrintFont* pFont = getFont( nFontID );
401 2131 : return pFont ? pFont->m_aEncoding : RTL_TEXTENCODING_DONTKNOW;
402 : }
403 :
404 : // should i only use font's builtin encoding ?
405 0 : bool getUseOnlyFontEncoding( fontID nFontID ) const
406 : {
407 0 : PrintFont* pFont = getFont( nFontID );
408 0 : return pFont && pFont->m_bFontEncodingOnly;
409 : }
410 :
411 : // get a specific fonts system dependent filename
412 170680 : OString getFontFileSysPath( fontID nFontID ) const
413 : {
414 170680 : return getFontFile( getFont( nFontID ) );
415 : }
416 :
417 : // get the ttc face number
418 : int getFontFaceNumber( fontID nFontID ) const;
419 :
420 : // get a specific fonts ascend
421 : int getFontAscend( fontID nFontID ) const;
422 :
423 : // get a specific fonts descent
424 : int getFontDescend( fontID nFontID ) const;
425 :
426 : // get a fonts glyph bounding box
427 : bool getFontBoundingBox( fontID nFont, int& xMin, int& yMin, int& xMax, int& yMax );
428 :
429 : // info whether an array of glyphs has vertical substitutions
430 : void hasVerticalSubstitutions( fontID nFontID, const sal_Unicode* pCharacters,
431 : int nCharacters, bool* pHasSubst ) const;
432 :
433 : // get a specific fonts metrics
434 :
435 : // get metrics for a sal_Unicode range
436 : // the user is responsible to allocate pArray large enough
437 : bool getMetrics( fontID nFontID, sal_Unicode minCharacter, sal_Unicode maxCharacter, CharacterMetric* pArray, bool bVertical = false ) const;
438 : // get metrics for an array of sal_Unicode characters
439 : // the user is responsible to allocate pArray large enough
440 : bool getMetrics( fontID nFontID, const sal_Unicode* pString, int nLen, CharacterMetric* pArray, bool bVertical = false ) const;
441 :
442 : // get encoding vector of font, currently only for Type1 fonts
443 : // returns NULL if encoding vector is empty or font is not type1;
444 : // if ppNonEncoded is set and non encoded type1 glyphs exist
445 : // then *ppNonEncoded is set to the mapping for nonencoded glyphs.
446 : // the encoding vector contains -1 for non encoded glyphs
447 : const std::map< sal_Unicode, sal_Int32 >* getEncodingMap( fontID nFontID, const std::map< sal_Unicode, OString >** ppNonEncoded, std::set<sal_Unicode> const ** ppPriority ) const;
448 :
449 : // evaluates copyright flags for TrueType fonts for printing/viewing
450 : // type1 fonts do not have such a feature, so return for them is true
451 : bool isFontDownloadingAllowedForPrinting( fontID nFont ) const;
452 :
453 : // helper for type 1 fonts
454 : std::list< OString > getAdobeNameFromUnicode( sal_Unicode aChar ) const;
455 :
456 : std::pair< std::unordered_multimap< sal_Unicode, sal_uInt8 >::const_iterator,
457 : std::unordered_multimap< sal_Unicode, sal_uInt8 >::const_iterator >
458 : getAdobeCodeFromUnicode( sal_Unicode aChar ) const
459 : {
460 : return m_aUnicodeToAdobecode.equal_range( aChar );
461 : }
462 : std::list< sal_Unicode > getUnicodeFromAdobeName( const OString& rName ) const;
463 : std::pair< std::unordered_multimap< sal_uInt8, sal_Unicode >::const_iterator,
464 : std::unordered_multimap< sal_uInt8, sal_Unicode >::const_iterator >
465 0 : getUnicodeFromAdobeCode( sal_uInt8 aChar ) const
466 : {
467 0 : return m_aAdobecodeToUnicode.equal_range( aChar );
468 : }
469 :
470 : // creates a new font subset of an existing TrueType font
471 : // returns true in case of success, else false
472 : // nFont: the font to be subsetted
473 : // rOutFile: the file to put the new subset into;
474 : // must be a valid osl file URL
475 : // pGlyphIDs: input array of glyph ids for new font
476 : // pNewEncoding: the corresponding encoding in the new font
477 : // pWidths: output array of widths of requested glyphs
478 : // nGlyphs: number of glyphs in arrays
479 : // pCapHeight:: capital height of the produced font
480 : // pXMin, pYMin, pXMax, pYMax: outgoing font bounding box
481 : // TODO: callers of this method should use its FontSubsetInfo counterpart directly
482 : bool createFontSubset( FontSubsetInfo&,
483 : fontID nFont,
484 : const OUString& rOutFile,
485 : const sal_GlyphId* pGlyphIDs,
486 : const sal_uInt8* pNewEncoding,
487 : sal_Int32* pWidths,
488 : int nGlyphs,
489 : bool bVertical = false
490 : );
491 : void getGlyphWidths( fontID nFont,
492 : bool bVertical,
493 : std::vector< sal_Int32 >& rWidths,
494 : std::map< sal_Unicode, sal_uInt32 >& rUnicodeEnc );
495 :
496 : // font administration functions
497 :
498 : /* system dependendent font matching
499 :
500 : <p>
501 : <code>matchFont</code> matches a pattern of font characteristics
502 : and returns the closest match if possibe. If a match was found
503 : the <code>FastPrintFontInfo</code> passed in as parameter
504 : will be update to the found matching font.
505 : </p>
506 : <p>
507 : implementation note: currently the function is only implemented
508 : for fontconfig.
509 : </p>
510 :
511 : @param rInfo
512 : out of the FastPrintFontInfo structure the following
513 : fields will be used for the match:
514 : <ul>
515 : <li>family name</li>
516 : <li>italic</li>
517 : <li>width</li>
518 : <li>weight</li>
519 : <li>pitch</li>
520 : </ul>
521 :
522 : @param rLocale
523 : if <code>rLocal</code> contains non empty strings the corresponding
524 : locale will be used for font matching also; e.g. "Sans" can result
525 : in different fonts in e.g. english and japanese
526 :
527 : @returns
528 : true if a match was found
529 : false else
530 : */
531 : bool matchFont( FastPrintFontInfo& rInfo, const com::sun::star::lang::Locale& rLocale );
532 : static ImplFontOptions* getFontOptions( const FastPrintFontInfo&, int nSize, void (*subcallback)(void*));
533 :
534 : bool Substitute( FontSelectPattern &rPattern, OUString& rMissingCodes );
535 :
536 : int FreeTypeCharIndex( void *pFace, sal_uInt32 aChar );
537 : };
538 :
539 : } // namespace
540 :
541 : #endif // INCLUDED_VCL_INC_FONTMANAGER_HXX
542 :
543 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|