gfx/thebes/gfxUserFontSet.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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_USER_FONT_SET_H
     7 #define GFX_USER_FONT_SET_H
     9 #include "gfxFont.h"
    10 #include "nsPresContext.h"
    11 #include "nsRefPtrHashtable.h"
    12 #include "nsAutoPtr.h"
    13 #include "nsCOMPtr.h"
    14 #include "nsIURI.h"
    15 #include "nsIPrincipal.h"
    16 #include "nsIScriptError.h"
    17 #include "nsURIHashKey.h"
    19 class nsFontFaceLoader;
    21 //#define DEBUG_USERFONT_CACHE
    23 // parsed CSS @font-face rule information
    24 // lifetime: from when @font-face rule processed until font is loaded
    25 struct gfxFontFaceSrc {
    26     bool                   mIsLocal;       // url or local
    28     // if url, whether to use the origin principal or not
    29     bool                   mUseOriginPrincipal;
    31     // format hint flags, union of all possible formats
    32     // (e.g. TrueType, EOT, SVG, etc.)
    33     // see FLAG_FORMAT_* enum values below
    34     uint32_t               mFormatFlags;
    36     nsString               mLocalName;     // full font name if local
    37     nsCOMPtr<nsIURI>       mURI;           // uri if url
    38     nsCOMPtr<nsIURI>       mReferrer;      // referrer url if url
    39     nsCOMPtr<nsIPrincipal> mOriginPrincipal; // principal if url
    40 };
    42 inline bool
    43 operator==(const gfxFontFaceSrc& a, const gfxFontFaceSrc& b)
    44 {
    45     bool equals;
    46     return (a.mIsLocal && b.mIsLocal &&
    47             a.mLocalName == b.mLocalName) ||
    48            (!a.mIsLocal && !b.mIsLocal &&
    49             a.mUseOriginPrincipal == b.mUseOriginPrincipal &&
    50             a.mFormatFlags == b.mFormatFlags &&
    51             NS_SUCCEEDED(a.mURI->Equals(b.mURI, &equals)) && equals &&
    52             NS_SUCCEEDED(a.mReferrer->Equals(b.mReferrer, &equals)) && equals &&
    53             a.mOriginPrincipal->Equals(b.mOriginPrincipal));
    54 }
    56 // Subclassed to store platform-specific code cleaned out when font entry is
    57 // deleted.
    58 // Lifetime: from when platform font is created until it is deactivated.
    59 // If the platform does not need to add any platform-specific code/data here,
    60 // then the gfxUserFontSet will allocate a base gfxUserFontData and attach
    61 // to the entry to track the basic user font info fields here.
    62 class gfxUserFontData {
    63 public:
    64     gfxUserFontData()
    65         : mSrcIndex(0), mFormat(0), mMetaOrigLen(0)
    66     { }
    67     virtual ~gfxUserFontData() { }
    69     nsTArray<uint8_t> mMetadata;  // woff metadata block (compressed), if any
    70     nsCOMPtr<nsIURI>  mURI;       // URI of the source, if it was url()
    71     nsCOMPtr<nsIPrincipal> mPrincipal; // principal for the download, if url()
    72     nsString          mLocalName; // font name used for the source, if local()
    73     nsString          mRealName;  // original fullname from the font resource
    74     uint32_t          mSrcIndex;  // index in the rule's source list
    75     uint32_t          mFormat;    // format hint for the source used, if any
    76     uint32_t          mMetaOrigLen; // length needed to decompress metadata
    77     bool              mPrivate;   // whether font belongs to a private window
    78 };
    80 // initially contains a set of proxy font entry objects, replaced with
    81 // platform/user fonts as downloaded
    83 class gfxMixedFontFamily : public gfxFontFamily {
    84 public:
    85     friend class gfxUserFontSet;
    87     gfxMixedFontFamily(const nsAString& aName)
    88         : gfxFontFamily(aName) { }
    90     virtual ~gfxMixedFontFamily() { }
    92     // Add the given font entry to the end of the family's list.
    93     // Any earlier occurrence is removed, so this has the effect of "advancing"
    94     // the entry to the end of the list.
    95     void AddFontEntry(gfxFontEntry *aFontEntry) {
    96         // We append to mAvailableFonts -before- searching for and removing
    97         // any existing reference to avoid the risk that we'll remove the last
    98         // reference to the font entry, and thus delete it.
    99         mAvailableFonts.AppendElement(aFontEntry);
   100         uint32_t i = mAvailableFonts.Length() - 1;
   101         while (i > 0) {
   102             if (mAvailableFonts[--i] == aFontEntry) {
   103                 mAvailableFonts.RemoveElementAt(i);
   104                 break;
   105             }
   106         }
   107         aFontEntry->mFamilyName = Name();
   108         ResetCharacterMap();
   109     }
   111     // Replace aProxyFontEntry in the family's list with aRealFontEntry.
   112     void ReplaceFontEntry(gfxFontEntry *aProxyFontEntry,
   113                           gfxFontEntry *aRealFontEntry) {
   114         uint32_t numFonts = mAvailableFonts.Length();
   115         uint32_t i;
   116         for (i = 0; i < numFonts; i++) {
   117             gfxFontEntry *fe = mAvailableFonts[i];
   118             if (fe == aProxyFontEntry) {
   119                 // Note that this may delete aProxyFontEntry, if there's no
   120                 // other reference to it except from its family.
   121                 mAvailableFonts[i] = aRealFontEntry;
   122                 aRealFontEntry->mFamilyName = Name();
   123                 break;
   124             }
   125         }
   126         NS_ASSERTION(i < numFonts, "font entry not found in family!");
   127         ResetCharacterMap();
   128     }
   130     // Remove all font entries from the family
   131     void DetachFontEntries() {
   132         mAvailableFonts.Clear();
   133     }
   134 };
   136 class gfxProxyFontEntry;
   138 class gfxUserFontSet {
   140 public:
   142     NS_INLINE_DECL_REFCOUNTING(gfxUserFontSet)
   144     gfxUserFontSet();
   146     enum {
   147         // no flags ==> no hint set
   148         // unknown ==> unknown format hint set
   149         FLAG_FORMAT_UNKNOWN        = 1,
   150         FLAG_FORMAT_OPENTYPE       = 1 << 1,
   151         FLAG_FORMAT_TRUETYPE       = 1 << 2,
   152         FLAG_FORMAT_TRUETYPE_AAT   = 1 << 3,
   153         FLAG_FORMAT_EOT            = 1 << 4,
   154         FLAG_FORMAT_SVG            = 1 << 5,
   155         FLAG_FORMAT_WOFF           = 1 << 6,
   157         // mask of all unused bits, update when adding new formats
   158         FLAG_FORMAT_NOT_USED       = ~((1 << 7)-1)
   159     };
   161     enum LoadStatus {
   162         STATUS_LOADING = 0,
   163         STATUS_LOADED,
   164         STATUS_FORMAT_NOT_SUPPORTED,
   165         STATUS_ERROR,
   166         STATUS_END_OF_LIST
   167     };
   170     // add in a font face
   171     // weight - 0 == unknown, [100, 900] otherwise (multiples of 100)
   172     // stretch = [NS_FONT_STRETCH_ULTRA_CONDENSED, NS_FONT_STRETCH_ULTRA_EXPANDED]
   173     // italic style = constants in gfxFontConstants.h, e.g. NS_FONT_STYLE_NORMAL
   174     // TODO: support for unicode ranges not yet implemented
   175     gfxFontEntry *AddFontFace(const nsAString& aFamilyName,
   176                               const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
   177                               uint32_t aWeight,
   178                               int32_t aStretch,
   179                               uint32_t aItalicStyle,
   180                               const nsTArray<gfxFontFeature>& aFeatureSettings,
   181                               const nsString& aLanguageOverride,
   182                               gfxSparseBitSet *aUnicodeRanges = nullptr);
   184     // add in a font face for which we have the gfxFontEntry already
   185     void AddFontFace(const nsAString& aFamilyName, gfxFontEntry* aFontEntry);
   187     // Whether there is a face with this family name
   188     bool HasFamily(const nsAString& aFamilyName) const
   189     {
   190         return GetFamily(aFamilyName) != nullptr;
   191     }
   193     gfxFontFamily *GetFamily(const nsAString& aName) const;
   195     // Lookup a font entry for a given style, returns null if not loaded.
   196     // aFamily must be a family returned by our GetFamily method.
   197     gfxFontEntry *FindFontEntry(gfxFontFamily *aFamily,
   198                                 const gfxFontStyle& aFontStyle,
   199                                 bool& aNeedsBold,
   200                                 bool& aWaitForUserFont);
   202     // Find a family (possibly one of several!) that owns the given entry.
   203     // This may be somewhat expensive, as it enumerates all the fonts in
   204     // the set. Currently used only by the Linux (gfxPangoFontGroup) backend,
   205     // which does not directly track families in the font group's list.
   206     gfxFontFamily *FindFamilyFor(gfxFontEntry *aFontEntry) const;
   208     // check whether the given source is allowed to be loaded;
   209     // returns the Principal (for use in the key when caching the loaded font),
   210     // and whether the load should bypass the cache (force-reload).
   211     virtual nsresult CheckFontLoad(const gfxFontFaceSrc *aFontFaceSrc,
   212                                    nsIPrincipal **aPrincipal,
   213                                    bool *aBypassCache) = 0;
   215     // initialize the process that loads external font data, which upon 
   216     // completion will call OnLoadComplete method
   217     virtual nsresult StartLoad(gfxMixedFontFamily *aFamily,
   218                                gfxProxyFontEntry *aProxy,
   219                                const gfxFontFaceSrc *aFontFaceSrc) = 0;
   221     // when download has been completed, pass back data here
   222     // aDownloadStatus == NS_OK ==> download succeeded, error otherwise
   223     // returns true if platform font creation sucessful (or local()
   224     // reference was next in line)
   225     // Ownership of aFontData is passed in here; the font set must
   226     // ensure that it is eventually deleted with NS_Free().
   227     bool OnLoadComplete(gfxMixedFontFamily *aFamily,
   228                         gfxProxyFontEntry *aProxy,
   229                         const uint8_t *aFontData, uint32_t aLength,
   230                         nsresult aDownloadStatus);
   232     // Replace a proxy with a real fontEntry; this is implemented in
   233     // nsUserFontSet in order to keep track of the entry corresponding
   234     // to each @font-face rule.
   235     virtual void ReplaceFontEntry(gfxMixedFontFamily *aFamily,
   236                                   gfxProxyFontEntry *aProxy,
   237                                   gfxFontEntry *aFontEntry) = 0;
   239     // generation - each time a face is loaded, generation is
   240     // incremented so that the change can be recognized 
   241     uint64_t GetGeneration() { return mGeneration; }
   243     // increment the generation on font load
   244     void IncrementGeneration();
   246     // rebuild if local rules have been used
   247     void RebuildLocalRules();
   249     virtual nsPresContext *GetPresContext() { return NULL; }
   251     class UserFontCache {
   252     public:
   253         // Record a loaded user-font in the cache. This requires that the
   254         // font-entry's userFontData has been set up already, as it relies
   255         // on the URI and Principal recorded there.
   256         static void CacheFont(gfxFontEntry *aFontEntry);
   258         // The given gfxFontEntry is being destroyed, so remove any record that
   259         // refers to it.
   260         static void ForgetFont(gfxFontEntry *aFontEntry);
   262         // Return the gfxFontEntry corresponding to a given URI and principal,
   263         // and the features of the given proxy, or nullptr if none is available.
   264         // The aPrivate flag is set for requests coming from private windows,
   265         // so we can avoid leaking fonts cached in private windows mode out to
   266         // normal windows.
   267         static gfxFontEntry* GetFont(nsIURI            *aSrcURI,
   268                                      nsIPrincipal      *aPrincipal,
   269                                      gfxProxyFontEntry *aProxy,
   270                                      bool               aPrivate);
   272         // Clear everything so that we don't leak URIs and Principals.
   273         static void Shutdown();
   275 #ifdef DEBUG_USERFONT_CACHE
   276         // dump contents
   277         static void Dump();
   278 #endif
   280     private:
   281         // Helper that we use to observe the empty-cache notification
   282         // from nsICacheService.
   283         class Flusher : public nsIObserver
   284         {
   285         public:
   286             NS_DECL_ISUPPORTS
   287             NS_DECL_NSIOBSERVER
   288             Flusher() {}
   289             virtual ~Flusher() {}
   290         };
   292         // Key used to look up entries in the user-font cache.
   293         // Note that key comparison does *not* use the mFontEntry field
   294         // as a whole; it only compares specific fields within the entry
   295         // (weight/width/style/features) that could affect font selection
   296         // or rendering, and that must match between a font-set's proxy
   297         // entry and the corresponding "real" font entry.
   298         struct Key {
   299             nsCOMPtr<nsIURI>        mURI;
   300             nsCOMPtr<nsIPrincipal>  mPrincipal;
   301             gfxFontEntry           *mFontEntry;
   302             bool                    mPrivate;
   304             Key(nsIURI* aURI, nsIPrincipal* aPrincipal,
   305                 gfxFontEntry* aFontEntry, bool aPrivate)
   306                 : mURI(aURI),
   307                   mPrincipal(aPrincipal),
   308                   mFontEntry(aFontEntry),
   309                   mPrivate(aPrivate)
   310             { }
   311         };
   313         class Entry : public PLDHashEntryHdr {
   314         public:
   315             typedef const Key& KeyType;
   316             typedef const Key* KeyTypePointer;
   318             Entry(KeyTypePointer aKey)
   319                 : mURI(aKey->mURI),
   320                   mPrincipal(aKey->mPrincipal),
   321                   mFontEntry(aKey->mFontEntry),
   322                   mPrivate(aKey->mPrivate)
   323             { }
   325             Entry(const Entry& aOther)
   326                 : mURI(aOther.mURI),
   327                   mPrincipal(aOther.mPrincipal),
   328                   mFontEntry(aOther.mFontEntry),
   329                   mPrivate(aOther.mPrivate)
   330             { }
   332             ~Entry() { }
   334             bool KeyEquals(const KeyTypePointer aKey) const;
   336             static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
   338             static PLDHashNumber HashKey(const KeyTypePointer aKey) {
   339                 uint32_t principalHash;
   340                 aKey->mPrincipal->GetHashValue(&principalHash);
   341                 return mozilla::HashGeneric(principalHash + int(aKey->mPrivate),
   342                                             nsURIHashKey::HashKey(aKey->mURI),
   343                                             HashFeatures(aKey->mFontEntry->mFeatureSettings),
   344                                             mozilla::HashString(aKey->mFontEntry->mFamilyName),
   345                                             ((uint32_t)aKey->mFontEntry->mItalic |
   346                                              (aKey->mFontEntry->mWeight << 1) |
   347                                              (aKey->mFontEntry->mStretch << 10) ) ^
   348                                              aKey->mFontEntry->mLanguageOverride);
   349             }
   351             enum { ALLOW_MEMMOVE = false };
   353             gfxFontEntry* GetFontEntry() const { return mFontEntry; }
   355             static PLDHashOperator RemoveIfPrivate(Entry* aEntry, void* aUserData);
   356             static PLDHashOperator RemoveIfMatches(Entry* aEntry, void* aUserData);
   357             static PLDHashOperator DisconnectSVG(Entry* aEntry, void* aUserData);
   359 #ifdef DEBUG_USERFONT_CACHE
   360             static PLDHashOperator DumpEntry(Entry* aEntry, void* aUserData);
   361 #endif
   363         private:
   364             static uint32_t
   365             HashFeatures(const nsTArray<gfxFontFeature>& aFeatures) {
   366                 return mozilla::HashBytes(aFeatures.Elements(),
   367                                           aFeatures.Length() * sizeof(gfxFontFeature));
   368             }
   370             nsCOMPtr<nsIURI>       mURI;
   371             nsCOMPtr<nsIPrincipal> mPrincipal;
   373             // The "real" font entry corresponding to this downloaded font.
   374             // The font entry MUST notify the cache when it is destroyed
   375             // (by calling Forget()).
   376             gfxFontEntry          *mFontEntry;
   378             // Whether this font was loaded from a private window.
   379             bool                   mPrivate;
   380         };
   382         static nsTHashtable<Entry> *sUserFonts;
   383     };
   385 protected:
   386     // Protected destructor, to discourage deletion outside of Release():
   387     virtual ~gfxUserFontSet();
   389     // Return whether the font set is associated with a private-browsing tab.
   390     virtual bool GetPrivateBrowsing() = 0;
   392     // for a given proxy font entry, attempt to load the next resource
   393     // in the src list
   394     LoadStatus LoadNext(gfxMixedFontFamily *aFamily,
   395                         gfxProxyFontEntry *aProxyEntry);
   397     // helper method for creating a platform font
   398     // returns font entry if platform font creation successful
   399     // Ownership of aFontData is passed in here; the font set must
   400     // ensure that it is eventually deleted with NS_Free().
   401     gfxFontEntry* LoadFont(gfxMixedFontFamily *aFamily,
   402                            gfxProxyFontEntry *aProxy,
   403                            const uint8_t *aFontData, uint32_t &aLength);
   405     // parse data for a data URL
   406     virtual nsresult SyncLoadFontData(gfxProxyFontEntry *aFontToLoad,
   407                                       const gfxFontFaceSrc *aFontFaceSrc,
   408                                       uint8_t* &aBuffer,
   409                                       uint32_t &aBufferLength) = 0;
   411     // report a problem of some kind (implemented in nsUserFontSet)
   412     virtual nsresult LogMessage(gfxMixedFontFamily *aFamily,
   413                                 gfxProxyFontEntry *aProxy,
   414                                 const char *aMessage,
   415                                 uint32_t aFlags = nsIScriptError::errorFlag,
   416                                 nsresult aStatus = NS_OK) = 0;
   418     const uint8_t* SanitizeOpenTypeData(gfxMixedFontFamily *aFamily,
   419                                         gfxProxyFontEntry *aProxy,
   420                                         const uint8_t* aData,
   421                                         uint32_t aLength,
   422                                         uint32_t& aSaneLength,
   423                                         bool aIsCompressed);
   425     static bool OTSMessage(void *aUserData, const char *format, ...);
   427     // helper method for performing the actual userfont set rebuild
   428     virtual void DoRebuildUserFontSet() = 0;
   430     // font families defined by @font-face rules
   431     nsRefPtrHashtable<nsStringHashKey, gfxMixedFontFamily> mFontFamilies;
   433     uint64_t        mGeneration;
   435     // true when local names have been looked up, false otherwise
   436     bool mLocalRulesUsed;
   438     static PRLogModuleInfo* GetUserFontsLog();
   440 private:
   441     static void CopyWOFFMetadata(const uint8_t* aFontData,
   442                                  uint32_t aLength,
   443                                  FallibleTArray<uint8_t>* aMetadata,
   444                                  uint32_t* aMetaOrigLen);
   445 };
   447 // acts a placeholder until the real font is downloaded
   449 class gfxProxyFontEntry : public gfxFontEntry {
   450     friend class gfxUserFontSet;
   452 public:
   453     gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
   454                       uint32_t aWeight,
   455                       int32_t aStretch,
   456                       uint32_t aItalicStyle,
   457                       const nsTArray<gfxFontFeature>& aFeatureSettings,
   458                       uint32_t aLanguageOverride,
   459                       gfxSparseBitSet *aUnicodeRanges);
   461     virtual ~gfxProxyFontEntry();
   463     // Return whether the entry matches the given list of attributes
   464     bool Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
   465                  uint32_t aWeight,
   466                  int32_t aStretch,
   467                  uint32_t aItalicStyle,
   468                  const nsTArray<gfxFontFeature>& aFeatureSettings,
   469                  uint32_t aLanguageOverride,
   470                  gfxSparseBitSet *aUnicodeRanges);
   472     virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold);
   474     // note that code depends on the ordering of these values!
   475     enum LoadingState {
   476         NOT_LOADING = 0,     // not started to load any font resources yet
   477         LOADING_STARTED,     // loading has started; hide fallback font
   478         LOADING_ALMOST_DONE, // timeout happened but we're nearly done,
   479                              // so keep hiding fallback font
   480         LOADING_SLOWLY,      // timeout happened and we're not nearly done,
   481                              // so use the fallback font
   482         LOADING_FAILED       // failed to load any source: use fallback
   483     };
   484     LoadingState             mLoadingState;
   485     bool                     mUnsupportedFormat;
   487     nsTArray<gfxFontFaceSrc> mSrcList;
   488     uint32_t                 mSrcIndex; // index of loading src item
   489     nsFontFaceLoader        *mLoader; // current loader for this entry, if any
   490     nsCOMPtr<nsIPrincipal>   mPrincipal;
   491 };
   494 #endif /* GFX_USER_FONT_SET_H */

mercurial