Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef GFX_FONTCONFIG_UTILS_H
7 #define GFX_FONTCONFIG_UTILS_H
9 #include "gfxPlatform.h"
11 #include "mozilla/MathAlgorithms.h"
12 #include "nsAutoRef.h"
13 #include "nsTArray.h"
14 #include "nsTHashtable.h"
15 #include "nsISupportsImpl.h"
17 #include <fontconfig/fontconfig.h>
20 template <>
21 class nsAutoRefTraits<FcPattern> : public nsPointerRefTraits<FcPattern>
22 {
23 public:
24 static void Release(FcPattern *ptr) { FcPatternDestroy(ptr); }
25 static void AddRef(FcPattern *ptr) { FcPatternReference(ptr); }
26 };
28 template <>
29 class nsAutoRefTraits<FcFontSet> : public nsPointerRefTraits<FcFontSet>
30 {
31 public:
32 static void Release(FcFontSet *ptr) { FcFontSetDestroy(ptr); }
33 };
35 template <>
36 class nsAutoRefTraits<FcCharSet> : public nsPointerRefTraits<FcCharSet>
37 {
38 public:
39 static void Release(FcCharSet *ptr) { FcCharSetDestroy(ptr); }
40 };
42 class gfxIgnoreCaseCStringComparator
43 {
44 public:
45 bool Equals(const nsACString& a, const nsACString& b) const
46 {
47 return nsCString(a).Equals(b, nsCaseInsensitiveCStringComparator());
48 }
50 bool LessThan(const nsACString& a, const nsACString& b) const
51 {
52 return a < b;
53 }
54 };
56 class gfxFontconfigUtils {
57 public:
58 gfxFontconfigUtils();
60 static gfxFontconfigUtils* GetFontconfigUtils() {
61 if (!sUtils)
62 sUtils = new gfxFontconfigUtils();
63 return sUtils;
64 }
66 static void Shutdown();
68 nsresult GetFontList(nsIAtom *aLangGroup,
69 const nsACString& aGenericFamily,
70 nsTArray<nsString>& aListOfFonts);
72 nsresult UpdateFontList();
74 nsresult ResolveFontName(const nsAString& aFontName,
75 gfxPlatform::FontResolverCallback aCallback,
76 void *aClosure, bool& aAborted);
78 nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
80 const nsTArray< nsCountedRef<FcPattern> >&
81 GetFontsForFamily(const FcChar8 *aFamilyName);
83 const nsTArray< nsCountedRef<FcPattern> >&
84 GetFontsForFullname(const FcChar8 *aFullname);
86 // Returns the best support that any font offers for |aLang|.
87 FcLangResult GetBestLangSupport(const FcChar8 *aLang);
88 // Returns the fonts offering this best level of support.
89 const nsTArray< nsCountedRef<FcPattern> >&
90 GetFontsForLang(const FcChar8 *aLang);
92 // Retuns the language support for a fontconfig font pattern
93 static FcLangResult GetLangSupport(FcPattern *aFont, const FcChar8 *aLang);
95 // Conversions between FcChar8*, which is unsigned char*,
96 // and (signed) char*, that check the type of the argument.
97 static const FcChar8 *ToFcChar8(const char *aCharPtr)
98 {
99 return reinterpret_cast<const FcChar8*>(aCharPtr);
100 }
101 static const FcChar8 *ToFcChar8(const nsCString& aCString)
102 {
103 return ToFcChar8(aCString.get());
104 }
105 static const char *ToCString(const FcChar8 *aChar8Ptr)
106 {
107 return reinterpret_cast<const char*>(aChar8Ptr);
108 }
110 static uint8_t FcSlantToThebesStyle(int aFcSlant);
111 static uint8_t GetThebesStyle(FcPattern *aPattern); // slant
112 static uint16_t GetThebesWeight(FcPattern *aPattern);
113 static int16_t GetThebesStretch(FcPattern *aPattern);
115 static int GetFcSlant(const gfxFontStyle& aFontStyle);
116 // Returns a precise FC_WEIGHT from |aBaseWeight|,
117 // which is a CSS absolute weight / 100.
118 static int FcWeightForBaseWeight(int8_t aBaseWeight);
120 static int FcWidthForThebesStretch(int16_t aStretch);
122 static bool GetFullnameFromFamilyAndStyle(FcPattern *aFont,
123 nsACString *aFullname);
125 // This doesn't consider which faces exist, and so initializes the pattern
126 // using a guessed weight, and doesn't consider sizeAdjust.
127 static nsReturnRef<FcPattern>
128 NewPattern(const nsTArray<nsString>& aFamilies,
129 const gfxFontStyle& aFontStyle, const char *aLang);
131 /**
132 * @param aLangGroup [in] a Mozilla langGroup.
133 * @param aFcLang [out] returns a language suitable for fontconfig
134 * matching |aLangGroup| or an empty string if no match is found.
135 */
136 static void GetSampleLangForGroup(nsIAtom *aLangGroup,
137 nsACString *aFcLang);
139 protected:
140 // Base class for hash table entries with case-insensitive FcChar8
141 // string keys.
142 class FcStrEntryBase : public PLDHashEntryHdr {
143 public:
144 typedef const FcChar8 *KeyType;
145 typedef const FcChar8 *KeyTypePointer;
147 static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
148 // Case-insensitive hash.
149 //
150 // fontconfig always ignores case of ASCII characters in family
151 // names and languages, but treatment of whitespace in families is
152 // not consistent. FcFontSort and FcFontMatch ignore whitespace
153 // except for whitespace in the first character, while FcFontList
154 // and config subsitution tests require whitespace to match
155 // exactly. CSS 2.1 implies that whitespace is important in the
156 // font-family property. FcStrCmpIgnoreCase considers whitespace
157 // important.
158 static PLDHashNumber HashKey(const FcChar8 *aKey) {
159 uint32_t hash = 0;
160 for (const FcChar8 *c = aKey; *c != '\0'; ++c) {
161 hash = mozilla::RotateLeft(hash, 3) ^ FcToLower(*c);
162 }
163 return hash;
164 }
165 enum { ALLOW_MEMMOVE = true };
166 };
168 public:
169 // Hash entry with a dependent const FcChar8* pointer to an external
170 // string for a key (and no data). The user must ensure that the string
171 // associated with the pointer is not destroyed. This entry type is
172 // useful for family name keys as the family name string is held in the
173 // font pattern.
174 class DepFcStrEntry : public FcStrEntryBase {
175 public:
176 // When constructing a new entry in the hashtable, the key is left
177 // nullptr. The caller of PutEntry() must fill in mKey when nullptr.
178 // This provides a mechanism for the caller of PutEntry() to determine
179 // whether the entry has been initialized.
180 DepFcStrEntry(KeyTypePointer aName)
181 : mKey(nullptr) { }
183 DepFcStrEntry(const DepFcStrEntry& toCopy)
184 : mKey(toCopy.mKey) { }
186 bool KeyEquals(KeyTypePointer aKey) const {
187 return FcStrCmpIgnoreCase(aKey, mKey) == 0;
188 }
190 const FcChar8 *mKey;
191 };
193 // Hash entry that uses a copy of an FcChar8 string to store the key.
194 // This entry type is useful for language keys, as languages are usually
195 // not stored as strings in font patterns.
196 class CopiedFcStrEntry : public FcStrEntryBase {
197 public:
198 // When constructing a new entry in the hashtable, the key is void.
199 // The caller of PutEntry() must call InitKey() when IsKeyInitialized()
200 // returns false. This provides a mechanism for the caller of
201 // PutEntry() to determine whether the entry has been initialized.
202 CopiedFcStrEntry(KeyTypePointer aName) {
203 mKey.SetIsVoid(true);
204 }
206 CopiedFcStrEntry(const CopiedFcStrEntry& toCopy)
207 : mKey(toCopy.mKey) { }
209 bool KeyEquals(KeyTypePointer aKey) const {
210 return FcStrCmpIgnoreCase(aKey, ToFcChar8(mKey)) == 0;
211 }
213 bool IsKeyInitialized() { return !mKey.IsVoid(); }
214 void InitKey(const FcChar8* aKey) { mKey.Assign(ToCString(aKey)); }
216 private:
217 nsCString mKey;
218 };
220 protected:
221 class FontsByFcStrEntry : public DepFcStrEntry {
222 public:
223 FontsByFcStrEntry(KeyTypePointer aName)
224 : DepFcStrEntry(aName) { }
226 FontsByFcStrEntry(const FontsByFcStrEntry& toCopy)
227 : DepFcStrEntry(toCopy), mFonts(toCopy.mFonts) { }
229 bool AddFont(FcPattern *aFont) {
230 return mFonts.AppendElement(aFont) != nullptr;
231 }
232 const nsTArray< nsCountedRef<FcPattern> >& GetFonts() {
233 return mFonts;
234 }
235 private:
236 nsTArray< nsCountedRef<FcPattern> > mFonts;
237 };
239 // FontsByFullnameEntry is similar to FontsByFcStrEntry (used for
240 // mFontsByFamily) except for two differences:
241 //
242 // * The font does not always contain a single string for the fullname, so
243 // the key is sometimes a combination of family and style.
244 //
245 // * There is usually only one font.
246 class FontsByFullnameEntry : public DepFcStrEntry {
247 public:
248 // When constructing a new entry in the hashtable, the key is left
249 // nullptr. The caller of PutEntry() is must fill in mKey when adding
250 // the first font if the key is not derived from the family and style.
251 // If the key is derived from family and style, a font must be added.
252 FontsByFullnameEntry(KeyTypePointer aName)
253 : DepFcStrEntry(aName) { }
255 FontsByFullnameEntry(const FontsByFullnameEntry& toCopy)
256 : DepFcStrEntry(toCopy), mFonts(toCopy.mFonts) { }
258 bool KeyEquals(KeyTypePointer aKey) const;
260 bool AddFont(FcPattern *aFont) {
261 return mFonts.AppendElement(aFont) != nullptr;
262 }
263 const nsTArray< nsCountedRef<FcPattern> >& GetFonts() {
264 return mFonts;
265 }
267 // Don't memmove the nsAutoTArray.
268 enum { ALLOW_MEMMOVE = false };
269 private:
270 // There is usually only one font, but sometimes more.
271 nsAutoTArray<nsCountedRef<FcPattern>,1> mFonts;
272 };
274 class LangSupportEntry : public CopiedFcStrEntry {
275 public:
276 LangSupportEntry(KeyTypePointer aName)
277 : CopiedFcStrEntry(aName) { }
279 LangSupportEntry(const LangSupportEntry& toCopy)
280 : CopiedFcStrEntry(toCopy), mSupport(toCopy.mSupport) { }
282 FcLangResult mSupport;
283 nsTArray< nsCountedRef<FcPattern> > mFonts;
284 };
286 static gfxFontconfigUtils* sUtils;
288 bool IsExistingFamily(const nsCString& aFamilyName);
290 nsresult GetFontListInternal(nsTArray<nsCString>& aListOfFonts,
291 nsIAtom *aLangGroup);
292 nsresult UpdateFontListInternal(bool aForce = false);
294 void AddFullnameEntries();
296 LangSupportEntry *GetLangSupportEntry(const FcChar8 *aLang,
297 bool aWithFonts);
299 // mFontsByFamily and mFontsByFullname contain entries only for families
300 // and fullnames for which there are fonts.
301 nsTHashtable<FontsByFcStrEntry> mFontsByFamily;
302 nsTHashtable<FontsByFullnameEntry> mFontsByFullname;
303 // mLangSupportTable contains an entry for each language that has been
304 // looked up through GetLangSupportEntry, even when the language is not
305 // supported.
306 nsTHashtable<LangSupportEntry> mLangSupportTable;
307 const nsTArray< nsCountedRef<FcPattern> > mEmptyPatternArray;
309 nsTArray<nsCString> mAliasForMultiFonts;
311 FcConfig *mLastConfig;
312 };
314 #endif /* GFX_FONTCONFIG_UTILS_H */