gfx/thebes/gfxFontconfigUtils.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial