gfx/thebes/gfxFontconfigUtils.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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 */

mercurial