1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_VCL_INC_FONTMANAGER_HXX
21 #define INCLUDED_VCL_INC_FONTMANAGER_HXX
26 #include <unordered_map>
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"
37 #define ATOM_FAMILYNAME 2
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
45 namespace utl
{ class MultiAtomProvider
; }
48 class ImplFontOptions
;
49 class FontSelectPattern
;
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
73 struct FastPrintFontInfo
75 fontID m_nID
; // FontID
76 fonttype::type m_eType
;
79 OUString m_aFamilyName
;
80 OUString m_aStyleName
;
81 std::list
< OUString
> m_aAliases
;
82 FontFamily m_eFamilyStyle
;
87 rtl_TextEncoding m_aEncoding
;
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 , m_bEmbeddable(false)
105 struct PrintFontInfo
: public FastPrintFontInfo
121 // the values are per thousand of the font size
122 // note: width, height contain advances, not bounding box
123 struct CharacterMetric
125 short int width
, height
;
127 CharacterMetric() : width( 0 ), height( 0 ) {}
128 bool operator==( const CharacterMetric
& rOther
) const
129 { return rOther
.width
== width
&& rOther
.height
== height
; }
130 bool operator!=( const CharacterMetric
& rOther
) const
131 { return rOther
.width
!= width
|| rOther
.height
!= height
; }
136 // a class to manage printable fonts
137 // aims are type1 and truetype fonts
141 class VCL_PLUGIN_PUBLIC PrintFontManager
144 struct TrueTypeFontFile
;
145 struct Type1FontFile
;
146 friend struct PrintFont
;
147 friend struct TrueTypeFontFile
;
148 friend struct Type1FontFile
;
149 friend class FontCache
;
151 struct PrintFontMetrics
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
170 std::unordered_map
< sal_Unicode
, bool > m_bVerticalSubstitutions
;
172 PrintFontMetrics() {}
174 bool isEmpty() const { return m_aMetrics
.empty(); }
179 fonttype::type m_eType
;
182 int m_nFamilyName
; // atom
183 std::list
< int > m_aAliases
;
184 int m_nPSName
; // atom
185 OUString m_aStyleName
;
186 FontItalic m_eItalic
;
188 FontWeight m_eWeight
;
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
;
198 int m_nXMin
; // font bounding box
202 bool m_bHaveVerticalSubstitutedGlyphs
;
203 bool m_bUserOverride
;
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
;
213 explicit PrintFont( fonttype::type eType
);
214 virtual ~PrintFont();
215 virtual bool queryMetricPage( int nPage
, utl::MultiAtomProvider
* pProvider
) = 0;
217 bool readAfmMetrics( utl::MultiAtomProvider
* pProvider
, bool bFillEncodingvector
, bool bOnlyGlobalAttributes
);
220 struct Type1FontFile
: public PrintFont
222 int m_nDirectory
; // atom containing system dependent path
223 OString m_aFontFile
; // relative to directory
224 OString m_aMetricFile
; // dito
226 /* note: m_aFontFile and Metric file are not atoms
227 because they should be fairly unique */
229 Type1FontFile() : PrintFont( fonttype::Type1
), m_nDirectory( 0 ) {}
230 virtual ~Type1FontFile();
231 virtual bool queryMetricPage( int nPage
, utl::MultiAtomProvider
* pProvider
) SAL_OVERRIDE
;
234 struct TrueTypeFontFile
: public PrintFont
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
242 virtual ~TrueTypeFontFile();
243 virtual bool queryMetricPage( int nPage
, utl::MultiAtomProvider
* pProvider
) SAL_OVERRIDE
;
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
>
257 std::unordered_map
< OString
, int, OStringHash
>
259 std::unordered_map
< int, OString
> m_aAtomToDir
;
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
;
269 mutable FontCache
* m_pFontCache
;
271 OString
getAfmFile( PrintFont
* pFont
) const;
272 OString
getFontFile( PrintFont
* pFont
) const;
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;
282 // There may be multiple font ids for TrueType collections
283 std::vector
<fontID
> findFontFileIDs( int nDirID
, const OString
& rFile
) const;
285 bool knownFontFile( int nDirID
, const OString
& rFile
) const
287 return findFontFileID(nDirID
, rFile
, 0) != 0;
290 static FontFamily
matchFamilyName( const OUString
& rFamily
);
292 PrintFont
* getFont( fontID nID
) const
294 std::unordered_map
< fontID
, PrintFont
* >::const_iterator it
;
295 it
= m_aFonts
.find( nID
);
296 return it
== m_aFonts
.end() ? NULL
: it
->second
;
298 void fillPrintFontInfo( PrintFont
* pFont
, FastPrintFontInfo
& rInfo
) const;
299 void fillPrintFontInfo( PrintFont
* pFont
, PrintFontInfo
& rInfo
) const;
301 OString
getDirectory( int nAtom
) const;
302 int getDirectoryAtom( const OString
& rDirectory
, bool bCreate
= false );
304 /* try to initialize fonts from libfontconfig
306 called from <code>initialize()</code>
308 static void initFontconfig();
309 void countFontconfigFonts( std::unordered_map
<OString
, int, OStringHash
>& o_rVisitedPaths
);
310 /* deinitialize fontconfig
312 static void deinitFontconfig();
314 /* register an application specific font directory for libfontconfig
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
321 true if libfontconfig accepted the directory
322 false else (e.g. no libfontconfig found)
324 static bool addFontconfigDir(const OString
& rDirectory
);
326 std::set
<OString
> m_aPreviousLangSupportRequests
;
327 std::vector
<OString
> m_aCurrentRequests
;
328 Timer m_aFontInstallerTimer
;
330 DECL_LINK_TYPED( autoInstallFontLangSupport
, Timer
*, void );
335 static PrintFontManager
& get(); // one instance only
337 // There may be multiple font ids for TrueType collections
338 std::vector
<fontID
> addFontFile( const OString
& rFileName
);
342 // returns the number of managed fonts
343 int getFontCount() const { return m_aFonts
.size(); }
345 // returns the ids of all managed fonts.
346 void getFontList( std::list
< fontID
>& rFontIDs
);
348 // get font info for a specific font
349 bool getFontInfo( fontID nFontID
, PrintFontInfo
& rInfo
) const;
350 // get fast font info for a specific font
351 bool getFontFastInfo( fontID nFontID
, FastPrintFontInfo
& rInfo
) const;
353 // routines to get font info in small pieces
355 // get a specific fonts PSName name
356 const OUString
& getPSName( fontID nFontID
) const;
358 // get a specific fonts family name aliases
359 void getFontFamilyAliases( fontID nFontID
) const;
361 // get a specific fonts type
362 fonttype::type
getFontType( fontID nFontID
) const
364 PrintFont
* pFont
= getFont( nFontID
);
365 return pFont
? pFont
->m_eType
: fonttype::Unknown
;
368 // get a specific fonts italic type
369 FontItalic
getFontItalic( fontID nFontID
) const
371 PrintFont
* pFont
= getFont( nFontID
);
372 return pFont
? pFont
->m_eItalic
: ITALIC_DONTKNOW
;
375 // get a specific fonts width type
376 FontWidth
getFontWidth( fontID nFontID
) const
378 PrintFont
* pFont
= getFont( nFontID
);
379 return pFont
? pFont
->m_eWidth
: WIDTH_DONTKNOW
;
382 // get a specific fonts weight type
383 FontWeight
getFontWeight( fontID nFontID
) const
385 PrintFont
* pFont
= getFont( nFontID
);
386 return pFont
? pFont
->m_eWeight
: WEIGHT_DONTKNOW
;
389 // get a specific fonts pitch type
390 FontPitch
getFontPitch( fontID nFontID
) const
392 PrintFont
* pFont
= getFont( nFontID
);
393 return pFont
? pFont
->m_ePitch
: PITCH_DONTKNOW
;
396 // get a specific fonts encoding
397 rtl_TextEncoding
getFontEncoding( fontID nFontID
) const
399 PrintFont
* pFont
= getFont( nFontID
);
400 return pFont
? pFont
->m_aEncoding
: RTL_TEXTENCODING_DONTKNOW
;
403 // should i only use font's builtin encoding ?
404 bool getUseOnlyFontEncoding( fontID nFontID
) const
406 PrintFont
* pFont
= getFont( nFontID
);
407 return pFont
&& pFont
->m_bFontEncodingOnly
;
410 // get a specific fonts system dependent filename
411 OString
getFontFileSysPath( fontID nFontID
) const
413 return getFontFile( getFont( nFontID
) );
416 // get the ttc face number
417 int getFontFaceNumber( fontID nFontID
) const;
419 // get a specific fonts ascend
420 int getFontAscend( fontID nFontID
) const;
422 // get a specific fonts descent
423 int getFontDescend( fontID nFontID
) const;
425 // get a fonts glyph bounding box
426 bool getFontBoundingBox( fontID nFont
, int& xMin
, int& yMin
, int& xMax
, int& yMax
);
428 // info whether an array of glyphs has vertical substitutions
429 void hasVerticalSubstitutions( fontID nFontID
, const sal_Unicode
* pCharacters
,
430 int nCharacters
, bool* pHasSubst
) const;
432 // get a specific fonts metrics
434 // get metrics for a sal_Unicode range
435 // the user is responsible to allocate pArray large enough
436 bool getMetrics( fontID nFontID
, sal_Unicode minCharacter
, sal_Unicode maxCharacter
, CharacterMetric
* pArray
, bool bVertical
= false ) const;
437 // get metrics for an array of sal_Unicode characters
438 // the user is responsible to allocate pArray large enough
439 bool getMetrics( fontID nFontID
, const sal_Unicode
* pString
, int nLen
, CharacterMetric
* pArray
, bool bVertical
= false ) const;
441 // get encoding vector of font, currently only for Type1 fonts
442 // returns NULL if encoding vector is empty or font is not type1;
443 // if ppNonEncoded is set and non encoded type1 glyphs exist
444 // then *ppNonEncoded is set to the mapping for nonencoded glyphs.
445 // the encoding vector contains -1 for non encoded glyphs
446 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 // evaluates copyright flags for TrueType fonts for printing/viewing
449 // type1 fonts do not have such a feature, so return for them is true
450 bool isFontDownloadingAllowedForPrinting( fontID nFont
) const;
452 // helper for type 1 fonts
453 std::list
< OString
> getAdobeNameFromUnicode( sal_Unicode aChar
) const;
455 std::pair
< std::unordered_multimap
< sal_Unicode
, sal_uInt8
>::const_iterator
,
456 std::unordered_multimap
< sal_Unicode
, sal_uInt8
>::const_iterator
>
457 getAdobeCodeFromUnicode( sal_Unicode aChar
) const
459 return m_aUnicodeToAdobecode
.equal_range( aChar
);
461 std::list
< sal_Unicode
> getUnicodeFromAdobeName( const OString
& rName
) const;
462 std::pair
< std::unordered_multimap
< sal_uInt8
, sal_Unicode
>::const_iterator
,
463 std::unordered_multimap
< sal_uInt8
, sal_Unicode
>::const_iterator
>
464 getUnicodeFromAdobeCode( sal_uInt8 aChar
) const
466 return m_aAdobecodeToUnicode
.equal_range( aChar
);
469 // creates a new font subset of an existing TrueType font
470 // returns true in case of success, else false
471 // nFont: the font to be subsetted
472 // rOutFile: the file to put the new subset into;
473 // must be a valid osl file URL
474 // pGlyphIDs: input array of glyph ids for new font
475 // pNewEncoding: the corresponding encoding in the new font
476 // pWidths: output array of widths of requested glyphs
477 // nGlyphs: number of glyphs in arrays
478 // pCapHeight:: capital height of the produced font
479 // pXMin, pYMin, pXMax, pYMax: outgoing font bounding box
480 // TODO: callers of this method should use its FontSubsetInfo counterpart directly
481 bool createFontSubset( FontSubsetInfo
&,
483 const OUString
& rOutFile
,
484 const sal_GlyphId
* pGlyphIDs
,
485 const sal_uInt8
* pNewEncoding
,
488 bool bVertical
= false
490 void getGlyphWidths( fontID nFont
,
492 std::vector
< sal_Int32
>& rWidths
,
493 std::map
< sal_Unicode
, sal_uInt32
>& rUnicodeEnc
);
495 // font administration functions
497 /* system dependendent font matching
500 <code>matchFont</code> matches a pattern of font characteristics
501 and returns the closest match if possibe. If a match was found
502 the <code>FastPrintFontInfo</code> passed in as parameter
503 will be update to the found matching font.
506 implementation note: currently the function is only implemented
511 out of the FastPrintFontInfo structure the following
512 fields will be used for the match:
522 if <code>rLocal</code> contains non empty strings the corresponding
523 locale will be used for font matching also; e.g. "Sans" can result
524 in different fonts in e.g. english and japanese
527 true if a match was found
530 bool matchFont( FastPrintFontInfo
& rInfo
, const com::sun::star::lang::Locale
& rLocale
);
531 static ImplFontOptions
* getFontOptions( const FastPrintFontInfo
&, int nSize
, void (*subcallback
)(void*));
533 bool Substitute( FontSelectPattern
&rPattern
, OUString
& rMissingCodes
);
535 int FreeTypeCharIndex( void *pFace
, sal_uInt32 aChar
);
540 #endif // INCLUDED_VCL_INC_FONTMANAGER_HXX
542 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */