diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | ad18d877ddd2a44d98fa12ccd3dbbcf4d0ac4299 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /gfx/thebes/gfxFontconfigUtils.h | |
parent | 15477ed9af4859dacb069040b5d4de600803d3bc (diff) | |
download | uxp-ad18d877ddd2a44d98fa12ccd3dbbcf4d0ac4299.tar.gz |
Add m-esr52 at 52.6.0
Diffstat (limited to 'gfx/thebes/gfxFontconfigUtils.h')
-rw-r--r-- | gfx/thebes/gfxFontconfigUtils.h | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/gfx/thebes/gfxFontconfigUtils.h b/gfx/thebes/gfxFontconfigUtils.h new file mode 100644 index 0000000000..eee69e4816 --- /dev/null +++ b/gfx/thebes/gfxFontconfigUtils.h @@ -0,0 +1,330 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef GFX_FONTCONFIG_UTILS_H +#define GFX_FONTCONFIG_UTILS_H + +#include "gfxPlatform.h" + +#include "mozilla/MathAlgorithms.h" +#include "nsAutoRef.h" +#include "nsTArray.h" +#include "nsTHashtable.h" +#include "nsISupportsImpl.h" +#include "gfxFT2FontBase.h" + +#include <fontconfig/fontconfig.h> + + +template <> +class nsAutoRefTraits<FcPattern> : public nsPointerRefTraits<FcPattern> +{ +public: + static void Release(FcPattern *ptr) { FcPatternDestroy(ptr); } + static void AddRef(FcPattern *ptr) { FcPatternReference(ptr); } +}; + +template <> +class nsAutoRefTraits<FcFontSet> : public nsPointerRefTraits<FcFontSet> +{ +public: + static void Release(FcFontSet *ptr) { FcFontSetDestroy(ptr); } +}; + +template <> +class nsAutoRefTraits<FcCharSet> : public nsPointerRefTraits<FcCharSet> +{ +public: + static void Release(FcCharSet *ptr) { FcCharSetDestroy(ptr); } +}; + +class gfxIgnoreCaseCStringComparator +{ + public: + bool Equals(const nsACString& a, const nsACString& b) const + { + return nsCString(a).Equals(b, nsCaseInsensitiveCStringComparator()); + } + + bool LessThan(const nsACString& a, const nsACString& b) const + { + return a < b; + } +}; + +class gfxFontconfigUtils { +public: + gfxFontconfigUtils(); + + static gfxFontconfigUtils* GetFontconfigUtils() { + if (!sUtils) + sUtils = new gfxFontconfigUtils(); + return sUtils; + } + + static void Shutdown(); + + nsresult GetFontList(nsIAtom *aLangGroup, + const nsACString& aGenericFamily, + nsTArray<nsString>& aListOfFonts); + + nsresult UpdateFontList(); + + nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName); + + const nsTArray< nsCountedRef<FcPattern> >& + GetFontsForFamily(const FcChar8 *aFamilyName); + + const nsTArray< nsCountedRef<FcPattern> >& + GetFontsForFullname(const FcChar8 *aFullname); + + // Returns the best support that any font offers for |aLang|. + FcLangResult GetBestLangSupport(const FcChar8 *aLang); + // Returns the fonts offering this best level of support. + const nsTArray< nsCountedRef<FcPattern> >& + GetFontsForLang(const FcChar8 *aLang); + + // Retuns the language support for a fontconfig font pattern + static FcLangResult GetLangSupport(FcPattern *aFont, const FcChar8 *aLang); + + // Conversions between FcChar8*, which is unsigned char*, + // and (signed) char*, that check the type of the argument. + static const FcChar8 *ToFcChar8(const char *aCharPtr) + { + return reinterpret_cast<const FcChar8*>(aCharPtr); + } + static const FcChar8 *ToFcChar8(const nsCString& aCString) + { + return ToFcChar8(aCString.get()); + } + static const char *ToCString(const FcChar8 *aChar8Ptr) + { + return reinterpret_cast<const char*>(aChar8Ptr); + } + + static uint8_t FcSlantToThebesStyle(int aFcSlant); + static uint8_t GetThebesStyle(FcPattern *aPattern); // slant + static uint16_t GetThebesWeight(FcPattern *aPattern); + static int16_t GetThebesStretch(FcPattern *aPattern); + + static int GetFcSlant(const gfxFontStyle& aFontStyle); + // Returns a precise FC_WEIGHT from |aBaseWeight|, + // which is a CSS absolute weight / 100. + static int FcWeightForBaseWeight(int8_t aBaseWeight); + + static int FcWidthForThebesStretch(int16_t aStretch); + + static bool GetFullnameFromFamilyAndStyle(FcPattern *aFont, + nsACString *aFullname); + + // This doesn't consider which faces exist, and so initializes the pattern + // using a guessed weight, and doesn't consider sizeAdjust. + static nsReturnRef<FcPattern> + NewPattern(const nsTArray<nsString>& aFamilies, + const gfxFontStyle& aFontStyle, const char *aLang); + + /** + * @param aLangGroup [in] a Mozilla langGroup. + * @param aFcLang [out] returns a language suitable for fontconfig + * matching |aLangGroup| or an empty string if no match is found. + */ + static void GetSampleLangForGroup(nsIAtom *aLangGroup, + nsACString *aFcLang); + +protected: + // Base class for hash table entries with case-insensitive FcChar8 + // string keys. + class FcStrEntryBase : public PLDHashEntryHdr { + public: + typedef const FcChar8 *KeyType; + typedef const FcChar8 *KeyTypePointer; + + static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; } + // Case-insensitive hash. + // + // fontconfig always ignores case of ASCII characters in family + // names and languages, but treatment of whitespace in families is + // not consistent. FcFontSort and FcFontMatch ignore whitespace + // except for whitespace in the first character, while FcFontList + // and config subsitution tests require whitespace to match + // exactly. CSS 2.1 implies that whitespace is important in the + // font-family property. FcStrCmpIgnoreCase considers whitespace + // important. + static PLDHashNumber HashKey(const FcChar8 *aKey) { + uint32_t hash = 0; + for (const FcChar8 *c = aKey; *c != '\0'; ++c) { + hash = mozilla::RotateLeft(hash, 3) ^ FcToLower(*c); + } + return hash; + } + enum { ALLOW_MEMMOVE = true }; + }; + +public: + // Hash entry with a dependent const FcChar8* pointer to an external + // string for a key (and no data). The user must ensure that the string + // associated with the pointer is not destroyed. This entry type is + // useful for family name keys as the family name string is held in the + // font pattern. + class DepFcStrEntry : public FcStrEntryBase { + public: + // When constructing a new entry in the hashtable, the key is left + // nullptr. The caller of PutEntry() must fill in mKey when nullptr. + // This provides a mechanism for the caller of PutEntry() to determine + // whether the entry has been initialized. + explicit DepFcStrEntry(KeyTypePointer aName) + : mKey(nullptr) { } + + DepFcStrEntry(const DepFcStrEntry& toCopy) + : mKey(toCopy.mKey) { } + + bool KeyEquals(KeyTypePointer aKey) const { + return FcStrCmpIgnoreCase(aKey, mKey) == 0; + } + + const FcChar8 *mKey; + }; + + // Hash entry that uses a copy of an FcChar8 string to store the key. + // This entry type is useful for language keys, as languages are usually + // not stored as strings in font patterns. + class CopiedFcStrEntry : public FcStrEntryBase { + public: + // When constructing a new entry in the hashtable, the key is void. + // The caller of PutEntry() must call InitKey() when IsKeyInitialized() + // returns false. This provides a mechanism for the caller of + // PutEntry() to determine whether the entry has been initialized. + explicit CopiedFcStrEntry(KeyTypePointer aName) { + mKey.SetIsVoid(true); + } + + CopiedFcStrEntry(const CopiedFcStrEntry& toCopy) + : mKey(toCopy.mKey) { } + + bool KeyEquals(KeyTypePointer aKey) const { + return FcStrCmpIgnoreCase(aKey, ToFcChar8(mKey)) == 0; + } + + bool IsKeyInitialized() { return !mKey.IsVoid(); } + void InitKey(const FcChar8* aKey) { mKey.Assign(ToCString(aKey)); } + + private: + nsCString mKey; + }; + +protected: + class FontsByFcStrEntry : public DepFcStrEntry { + public: + explicit FontsByFcStrEntry(KeyTypePointer aName) + : DepFcStrEntry(aName) { } + + FontsByFcStrEntry(const FontsByFcStrEntry& toCopy) + : DepFcStrEntry(toCopy), mFonts(toCopy.mFonts) { } + + bool AddFont(FcPattern *aFont) { + return mFonts.AppendElement(aFont) != nullptr; + } + const nsTArray< nsCountedRef<FcPattern> >& GetFonts() { + return mFonts; + } + private: + nsTArray< nsCountedRef<FcPattern> > mFonts; + }; + + // FontsByFullnameEntry is similar to FontsByFcStrEntry (used for + // mFontsByFamily) except for two differences: + // + // * The font does not always contain a single string for the fullname, so + // the key is sometimes a combination of family and style. + // + // * There is usually only one font. + class FontsByFullnameEntry : public DepFcStrEntry { + public: + // When constructing a new entry in the hashtable, the key is left + // nullptr. The caller of PutEntry() is must fill in mKey when adding + // the first font if the key is not derived from the family and style. + // If the key is derived from family and style, a font must be added. + explicit FontsByFullnameEntry(KeyTypePointer aName) + : DepFcStrEntry(aName) { } + + FontsByFullnameEntry(const FontsByFullnameEntry& toCopy) + : DepFcStrEntry(toCopy), mFonts(toCopy.mFonts) { } + + bool KeyEquals(KeyTypePointer aKey) const; + + bool AddFont(FcPattern *aFont) { + return mFonts.AppendElement(aFont) != nullptr; + } + const nsTArray< nsCountedRef<FcPattern> >& GetFonts() { + return mFonts; + } + + // Don't memmove the AutoTArray. + enum { ALLOW_MEMMOVE = false }; + private: + // There is usually only one font, but sometimes more. + AutoTArray<nsCountedRef<FcPattern>,1> mFonts; + }; + + class LangSupportEntry : public CopiedFcStrEntry { + public: + explicit LangSupportEntry(KeyTypePointer aName) + : CopiedFcStrEntry(aName) { } + + LangSupportEntry(const LangSupportEntry& toCopy) + : CopiedFcStrEntry(toCopy), mSupport(toCopy.mSupport) { } + + FcLangResult mSupport; + nsTArray< nsCountedRef<FcPattern> > mFonts; + }; + + static gfxFontconfigUtils* sUtils; + + bool IsExistingFamily(const nsCString& aFamilyName); + + nsresult GetFontListInternal(nsTArray<nsCString>& aListOfFonts, + nsIAtom *aLangGroup); + nsresult UpdateFontListInternal(bool aForce = false); + + void AddFullnameEntries(); + + LangSupportEntry *GetLangSupportEntry(const FcChar8 *aLang, + bool aWithFonts); + + // mFontsByFamily and mFontsByFullname contain entries only for families + // and fullnames for which there are fonts. + nsTHashtable<FontsByFcStrEntry> mFontsByFamily; + nsTHashtable<FontsByFullnameEntry> mFontsByFullname; + // mLangSupportTable contains an entry for each language that has been + // looked up through GetLangSupportEntry, even when the language is not + // supported. + nsTHashtable<LangSupportEntry> mLangSupportTable; + const nsTArray< nsCountedRef<FcPattern> > mEmptyPatternArray; + + FcConfig *mLastConfig; + +#ifdef MOZ_BUNDLED_FONTS + void ActivateBundledFonts(); + + nsCString mBundledFontsPath; + bool mBundledFontsInitialized; +#endif +}; + +class gfxFontconfigFontBase : public gfxFT2FontBase { +public: + gfxFontconfigFontBase(cairo_scaled_font_t *aScaledFont, + FcPattern *aPattern, + gfxFontEntry *aFontEntry, + const gfxFontStyle *aFontStyle); + + virtual FontType GetType() const override { return FONT_TYPE_FONTCONFIG; } + virtual FcPattern *GetPattern() const { return mPattern; } + +private: + nsCountedRef<FcPattern> mPattern; +}; + +#endif /* GFX_FONTCONFIG_UTILS_H */ |