2008-09-30 20:04:10 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
2012-05-21 04:12:37 -07:00
|
|
|
* 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/. */
|
2008-09-30 20:04:10 -07:00
|
|
|
|
|
|
|
#ifndef GFX_USER_FONT_SET_H
|
|
|
|
#define GFX_USER_FONT_SET_H
|
|
|
|
|
|
|
|
#include "gfxFont.h"
|
|
|
|
#include "nsRefPtrHashtable.h"
|
|
|
|
#include "nsAutoPtr.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsIURI.h"
|
2012-12-10 01:31:07 -08:00
|
|
|
#include "nsIPrincipal.h"
|
2011-07-12 04:24:36 -07:00
|
|
|
#include "nsIScriptError.h"
|
2012-12-10 01:31:07 -08:00
|
|
|
#include "nsURIHashKey.h"
|
2008-09-30 20:04:10 -07:00
|
|
|
|
2012-04-26 10:50:41 -07:00
|
|
|
class nsFontFaceLoader;
|
2008-09-30 20:04:10 -07:00
|
|
|
|
2013-09-18 18:56:49 -07:00
|
|
|
//#define DEBUG_USERFONT_CACHE
|
|
|
|
|
2014-10-01 19:32:09 -07:00
|
|
|
class gfxFontFaceBufferSource
|
|
|
|
{
|
|
|
|
NS_INLINE_DECL_REFCOUNTING(gfxFontFaceBufferSource)
|
|
|
|
public:
|
|
|
|
virtual void TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength) = 0;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual ~gfxFontFaceBufferSource() {}
|
|
|
|
};
|
|
|
|
|
2008-09-30 20:04:10 -07:00
|
|
|
// parsed CSS @font-face rule information
|
|
|
|
// lifetime: from when @font-face rule processed until font is loaded
|
|
|
|
struct gfxFontFaceSrc {
|
2014-10-01 19:32:09 -07:00
|
|
|
|
|
|
|
enum SourceType {
|
|
|
|
eSourceType_Local,
|
|
|
|
eSourceType_URL,
|
|
|
|
eSourceType_Buffer
|
|
|
|
};
|
|
|
|
|
|
|
|
SourceType mSourceType;
|
2008-11-26 19:50:16 -08:00
|
|
|
|
|
|
|
// if url, whether to use the origin principal or not
|
2011-09-28 23:19:26 -07:00
|
|
|
bool mUseOriginPrincipal;
|
2008-09-30 20:04:10 -07:00
|
|
|
|
|
|
|
// format hint flags, union of all possible formats
|
|
|
|
// (e.g. TrueType, EOT, SVG, etc.)
|
|
|
|
// see FLAG_FORMAT_* enum values below
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t mFormatFlags;
|
2008-11-26 19:50:16 -08:00
|
|
|
|
|
|
|
nsString mLocalName; // full font name if local
|
2012-12-10 01:31:07 -08:00
|
|
|
nsCOMPtr<nsIURI> mURI; // uri if url
|
2008-11-26 19:50:16 -08:00
|
|
|
nsCOMPtr<nsIURI> mReferrer; // referrer url if url
|
2012-12-10 01:31:07 -08:00
|
|
|
nsCOMPtr<nsIPrincipal> mOriginPrincipal; // principal if url
|
2014-10-01 19:32:09 -07:00
|
|
|
|
|
|
|
nsRefPtr<gfxFontFaceBufferSource> mBuffer;
|
2008-09-30 20:04:10 -07:00
|
|
|
};
|
|
|
|
|
2013-08-12 02:07:55 -07:00
|
|
|
inline bool
|
|
|
|
operator==(const gfxFontFaceSrc& a, const gfxFontFaceSrc& b)
|
|
|
|
{
|
2014-10-01 19:32:09 -07:00
|
|
|
if (a.mSourceType != b.mSourceType) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
switch (a.mSourceType) {
|
|
|
|
case gfxFontFaceSrc::eSourceType_Local:
|
|
|
|
return a.mLocalName == b.mLocalName;
|
|
|
|
case gfxFontFaceSrc::eSourceType_URL: {
|
|
|
|
bool equals;
|
|
|
|
return a.mUseOriginPrincipal == b.mUseOriginPrincipal &&
|
|
|
|
a.mFormatFlags == b.mFormatFlags &&
|
|
|
|
NS_SUCCEEDED(a.mURI->Equals(b.mURI, &equals)) && equals &&
|
|
|
|
NS_SUCCEEDED(a.mReferrer->Equals(b.mReferrer, &equals)) &&
|
|
|
|
equals &&
|
|
|
|
a.mOriginPrincipal->Equals(b.mOriginPrincipal);
|
|
|
|
}
|
|
|
|
case gfxFontFaceSrc::eSourceType_Buffer:
|
|
|
|
return a.mBuffer == b.mBuffer;
|
|
|
|
}
|
|
|
|
NS_WARNING("unexpected mSourceType");
|
|
|
|
return false;
|
2013-08-12 02:07:55 -07:00
|
|
|
}
|
|
|
|
|
2011-06-15 23:31:37 -07:00
|
|
|
// Subclassed to store platform-specific code cleaned out when font entry is
|
|
|
|
// deleted.
|
|
|
|
// Lifetime: from when platform font is created until it is deactivated.
|
|
|
|
// If the platform does not need to add any platform-specific code/data here,
|
|
|
|
// then the gfxUserFontSet will allocate a base gfxUserFontData and attach
|
|
|
|
// to the entry to track the basic user font info fields here.
|
2008-09-30 20:04:10 -07:00
|
|
|
class gfxUserFontData {
|
|
|
|
public:
|
2011-06-15 23:31:37 -07:00
|
|
|
gfxUserFontData()
|
2014-08-04 09:26:55 -07:00
|
|
|
: mSrcIndex(0), mFormat(0), mMetaOrigLen(0),
|
2014-10-04 03:46:54 -07:00
|
|
|
mCRC32(0), mLength(0), mCompression(kUnknownCompression),
|
|
|
|
mPrivate(false), mIsBuffer(false)
|
2011-06-15 23:31:37 -07:00
|
|
|
{ }
|
2008-09-30 20:04:10 -07:00
|
|
|
virtual ~gfxUserFontData() { }
|
2011-06-15 23:31:37 -07:00
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
nsTArray<uint8_t> mMetadata; // woff metadata block (compressed), if any
|
2011-06-15 23:31:37 -07:00
|
|
|
nsCOMPtr<nsIURI> mURI; // URI of the source, if it was url()
|
2012-12-10 01:31:07 -08:00
|
|
|
nsCOMPtr<nsIPrincipal> mPrincipal; // principal for the download, if url()
|
2011-06-15 23:31:37 -07:00
|
|
|
nsString mLocalName; // font name used for the source, if local()
|
2011-06-15 23:31:37 -07:00
|
|
|
nsString mRealName; // original fullname from the font resource
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t mSrcIndex; // index in the rule's source list
|
|
|
|
uint32_t mFormat; // format hint for the source used, if any
|
|
|
|
uint32_t mMetaOrigLen; // length needed to decompress metadata
|
2014-08-04 09:26:55 -07:00
|
|
|
uint32_t mCRC32; // Checksum
|
|
|
|
uint32_t mLength; // Font length
|
2014-10-04 03:46:54 -07:00
|
|
|
uint8_t mCompression; // compression type
|
2013-05-21 23:42:30 -07:00
|
|
|
bool mPrivate; // whether font belongs to a private window
|
2014-10-01 19:32:09 -07:00
|
|
|
bool mIsBuffer; // whether the font source was a buffer
|
2014-10-04 03:46:54 -07:00
|
|
|
|
|
|
|
enum {
|
|
|
|
kUnknownCompression = 0,
|
|
|
|
kZlibCompression = 1,
|
|
|
|
kBrotliCompression = 2
|
|
|
|
};
|
2008-09-30 20:04:10 -07:00
|
|
|
};
|
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
// initially contains a set of userfont font entry objects, replaced with
|
2008-09-30 20:04:10 -07:00
|
|
|
// platform/user fonts as downloaded
|
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
class gfxUserFontFamily : public gfxFontFamily {
|
2008-09-30 20:04:10 -07:00
|
|
|
public:
|
2009-08-16 06:52:12 -07:00
|
|
|
friend class gfxUserFontSet;
|
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
explicit gfxUserFontFamily(const nsAString& aName)
|
2009-08-16 06:52:12 -07:00
|
|
|
: gfxFontFamily(aName) { }
|
2008-09-30 20:04:10 -07:00
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
virtual ~gfxUserFontFamily() { }
|
2008-09-30 20:04:10 -07:00
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
// add the given font entry to the end of the family's list
|
|
|
|
void AddFontEntry(gfxFontEntry* aFontEntry) {
|
|
|
|
// keep ref while removing existing entry
|
|
|
|
nsRefPtr<gfxFontEntry> fe = aFontEntry;
|
|
|
|
// remove existing entry, if already present
|
|
|
|
mAvailableFonts.RemoveElement(aFontEntry);
|
2013-08-12 02:07:55 -07:00
|
|
|
mAvailableFonts.AppendElement(aFontEntry);
|
2014-09-08 00:23:20 -07:00
|
|
|
|
2014-07-09 00:08:54 -07:00
|
|
|
if (aFontEntry->mFamilyName.IsEmpty()) {
|
|
|
|
aFontEntry->mFamilyName = Name();
|
|
|
|
} else {
|
2014-07-22 23:09:56 -07:00
|
|
|
#ifdef DEBUG
|
|
|
|
nsString thisName = Name();
|
|
|
|
nsString entryName = aFontEntry->mFamilyName;
|
|
|
|
ToLowerCase(thisName);
|
|
|
|
ToLowerCase(entryName);
|
|
|
|
MOZ_ASSERT(thisName.Equals(entryName));
|
|
|
|
#endif
|
2014-07-09 00:08:54 -07:00
|
|
|
}
|
2011-08-09 01:06:01 -07:00
|
|
|
ResetCharacterMap();
|
2008-09-30 20:04:10 -07:00
|
|
|
}
|
|
|
|
|
2013-08-12 02:07:55 -07:00
|
|
|
// Remove all font entries from the family
|
2012-02-02 03:24:22 -08:00
|
|
|
void DetachFontEntries() {
|
|
|
|
mAvailableFonts.Clear();
|
|
|
|
}
|
2008-09-30 20:04:10 -07:00
|
|
|
};
|
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
class gfxUserFontEntry;
|
2014-08-23 07:12:00 -07:00
|
|
|
class gfxOTSContext;
|
2008-09-30 20:04:10 -07:00
|
|
|
|
2013-05-29 14:59:24 -07:00
|
|
|
class gfxUserFontSet {
|
2014-09-08 00:23:20 -07:00
|
|
|
friend class gfxUserFontEntry;
|
2014-08-23 07:12:00 -07:00
|
|
|
friend class gfxOTSContext;
|
2008-09-30 20:04:10 -07:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2010-04-01 11:05:40 -07:00
|
|
|
NS_INLINE_DECL_REFCOUNTING(gfxUserFontSet)
|
2008-09-30 20:04:10 -07:00
|
|
|
|
2008-12-11 23:31:51 -08:00
|
|
|
gfxUserFontSet();
|
2008-09-30 20:04:10 -07:00
|
|
|
|
|
|
|
enum {
|
2009-01-12 21:16:58 -08:00
|
|
|
// no flags ==> no hint set
|
|
|
|
// unknown ==> unknown format hint set
|
|
|
|
FLAG_FORMAT_UNKNOWN = 1,
|
|
|
|
FLAG_FORMAT_OPENTYPE = 1 << 1,
|
|
|
|
FLAG_FORMAT_TRUETYPE = 1 << 2,
|
|
|
|
FLAG_FORMAT_TRUETYPE_AAT = 1 << 3,
|
|
|
|
FLAG_FORMAT_EOT = 1 << 4,
|
|
|
|
FLAG_FORMAT_SVG = 1 << 5,
|
2009-09-17 04:03:12 -07:00
|
|
|
FLAG_FORMAT_WOFF = 1 << 6,
|
2014-10-04 03:36:05 -07:00
|
|
|
FLAG_FORMAT_WOFF2 = 1 << 7,
|
|
|
|
|
|
|
|
// the common formats that we support everywhere
|
|
|
|
FLAG_FORMATS_COMMON = FLAG_FORMAT_OPENTYPE |
|
|
|
|
FLAG_FORMAT_TRUETYPE |
|
|
|
|
FLAG_FORMAT_WOFF |
|
|
|
|
FLAG_FORMAT_WOFF2,
|
2009-09-17 04:03:12 -07:00
|
|
|
|
2009-01-12 21:16:58 -08:00
|
|
|
// mask of all unused bits, update when adding new formats
|
2014-10-04 03:36:05 -07:00
|
|
|
FLAG_FORMAT_NOT_USED = ~((1 << 8)-1)
|
2008-09-30 20:04:10 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-07-22 22:05:50 -07:00
|
|
|
// creates a font face without adding it to a particular family
|
2014-06-29 21:25:11 -07:00
|
|
|
// weight - [100, 900] (multiples of 100)
|
2013-08-12 02:07:55 -07:00
|
|
|
// stretch = [NS_FONT_STRETCH_ULTRA_CONDENSED, NS_FONT_STRETCH_ULTRA_EXPANDED]
|
2009-01-29 12:39:18 -08:00
|
|
|
// italic style = constants in gfxFontConstants.h, e.g. NS_FONT_STYLE_NORMAL
|
2014-06-29 21:25:21 -07:00
|
|
|
// language override = result of calling gfxFontStyle::ParseFontLanguageOverride
|
2008-09-30 20:04:10 -07:00
|
|
|
// TODO: support for unicode ranges not yet implemented
|
2014-10-01 19:32:07 -07:00
|
|
|
virtual already_AddRefed<gfxUserFontEntry> CreateUserFontEntry(
|
2011-04-12 03:53:20 -07:00
|
|
|
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aWeight,
|
2013-08-12 02:07:55 -07:00
|
|
|
int32_t aStretch,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aItalicStyle,
|
2012-04-25 23:24:26 -07:00
|
|
|
const nsTArray<gfxFontFeature>& aFeatureSettings,
|
2014-06-29 21:25:21 -07:00
|
|
|
uint32_t aLanguageOverride,
|
2014-10-01 19:32:06 -07:00
|
|
|
gfxSparseBitSet* aUnicodeRanges) = 0;
|
2014-07-22 22:05:50 -07:00
|
|
|
|
|
|
|
// creates a font face for the specified family, or returns an existing
|
|
|
|
// matching entry on the family if there is one
|
2014-10-01 19:32:07 -07:00
|
|
|
already_AddRefed<gfxUserFontEntry> FindOrCreateUserFontEntry(
|
2014-07-22 22:05:50 -07:00
|
|
|
const nsAString& aFamilyName,
|
|
|
|
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
|
|
|
|
uint32_t aWeight,
|
|
|
|
int32_t aStretch,
|
|
|
|
uint32_t aItalicStyle,
|
|
|
|
const nsTArray<gfxFontFeature>& aFeatureSettings,
|
|
|
|
uint32_t aLanguageOverride,
|
|
|
|
gfxSparseBitSet* aUnicodeRanges);
|
2011-04-12 03:53:20 -07:00
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
// add in a font face for which we have the gfxUserFontEntry already
|
2014-10-01 19:32:07 -07:00
|
|
|
void AddUserFontEntry(const nsAString& aFamilyName,
|
|
|
|
gfxUserFontEntry* aUserFontEntry);
|
2008-09-30 20:04:10 -07:00
|
|
|
|
2008-12-05 15:19:27 -08:00
|
|
|
// Whether there is a face with this family name
|
2011-09-28 23:19:26 -07:00
|
|
|
bool HasFamily(const nsAString& aFamilyName) const
|
2008-12-05 15:19:27 -08:00
|
|
|
{
|
2014-07-09 00:08:55 -07:00
|
|
|
return LookupFamily(aFamilyName) != nullptr;
|
2008-12-05 15:19:27 -08:00
|
|
|
}
|
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
// Look up and return the gfxUserFontFamily in mFontFamilies with
|
2014-07-09 00:08:55 -07:00
|
|
|
// the given name
|
2014-09-08 00:23:20 -07:00
|
|
|
gfxUserFontFamily* LookupFamily(const nsAString& aName) const;
|
2012-12-19 01:42:25 -08:00
|
|
|
|
2014-09-24 20:16:54 -07:00
|
|
|
// Lookup a font entry for a given style, returns null if not loaded.
|
|
|
|
// aFamily must be a family returned by our LookupFamily method.
|
|
|
|
// (only used by gfxPangoFontGroup for now)
|
|
|
|
gfxUserFontEntry* FindUserFontEntryAndLoad(gfxFontFamily* aFamily,
|
|
|
|
const gfxFontStyle& aFontStyle,
|
|
|
|
bool& aNeedsBold,
|
|
|
|
bool& aWaitForUserFont);
|
2013-01-02 14:27:49 -08:00
|
|
|
|
2013-05-21 21:39:39 -07:00
|
|
|
// check whether the given source is allowed to be loaded;
|
|
|
|
// returns the Principal (for use in the key when caching the loaded font),
|
|
|
|
// and whether the load should bypass the cache (force-reload).
|
2014-09-08 00:23:20 -07:00
|
|
|
virtual nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
|
|
|
|
nsIPrincipal** aPrincipal,
|
|
|
|
bool* aBypassCache) = 0;
|
2012-12-10 01:31:07 -08:00
|
|
|
|
2014-09-24 20:16:53 -07:00
|
|
|
// initialize the process that loads external font data, which upon
|
|
|
|
// completion will call FontDataDownloadComplete method
|
2014-09-08 00:23:20 -07:00
|
|
|
virtual nsresult StartLoad(gfxUserFontEntry* aUserFontEntry,
|
|
|
|
const gfxFontFaceSrc* aFontFaceSrc) = 0;
|
2011-04-12 03:53:20 -07:00
|
|
|
|
2008-09-30 20:04:10 -07:00
|
|
|
// generation - each time a face is loaded, generation is
|
2014-09-24 20:16:53 -07:00
|
|
|
// incremented so that the change can be recognized
|
2012-08-22 08:56:38 -07:00
|
|
|
uint64_t GetGeneration() { return mGeneration; }
|
2008-09-30 20:04:10 -07:00
|
|
|
|
2011-01-05 13:48:48 -08:00
|
|
|
// increment the generation on font load
|
2014-09-24 20:16:54 -07:00
|
|
|
void IncrementGeneration(bool aIsRebuild = false);
|
|
|
|
|
|
|
|
// Generation is bumped on font loads but that doesn't affect name-style
|
|
|
|
// mappings. Rebuilds do however affect name-style mappings so need to
|
|
|
|
// lookup fontlists again when that happens.
|
|
|
|
uint64_t GetRebuildGeneration() { return mRebuildGeneration; }
|
2011-01-05 13:48:48 -08:00
|
|
|
|
2014-04-17 07:17:22 -07:00
|
|
|
// rebuild if local rules have been used
|
|
|
|
void RebuildLocalRules();
|
|
|
|
|
2012-12-10 01:31:07 -08:00
|
|
|
class UserFontCache {
|
|
|
|
public:
|
2014-06-30 11:05:28 -07:00
|
|
|
// Flag passed when caching a font entry, to specify whether the entry
|
|
|
|
// should persist in the cache or be discardable.
|
|
|
|
typedef enum {
|
|
|
|
kDiscardable,
|
|
|
|
kPersistent
|
|
|
|
} EntryPersistence;
|
|
|
|
|
2012-12-10 01:31:07 -08:00
|
|
|
// Record a loaded user-font in the cache. This requires that the
|
|
|
|
// font-entry's userFontData has been set up already, as it relies
|
|
|
|
// on the URI and Principal recorded there.
|
2014-06-30 11:05:28 -07:00
|
|
|
// If aPersistence is Persistent, the entry will remain in the cache
|
|
|
|
// across cacheservice:empty-cache notifications. This is used for
|
|
|
|
// "preloaded hidden fonts" on FxOS.
|
2014-09-08 00:23:20 -07:00
|
|
|
static void CacheFont(gfxFontEntry* aFontEntry,
|
2014-06-30 11:05:28 -07:00
|
|
|
EntryPersistence aPersistence = kDiscardable);
|
2012-12-10 01:31:07 -08:00
|
|
|
|
|
|
|
// The given gfxFontEntry is being destroyed, so remove any record that
|
|
|
|
// refers to it.
|
2014-09-08 00:23:20 -07:00
|
|
|
static void ForgetFont(gfxFontEntry* aFontEntry);
|
2012-12-10 01:31:07 -08:00
|
|
|
|
|
|
|
// Return the gfxFontEntry corresponding to a given URI and principal,
|
2014-09-08 00:23:20 -07:00
|
|
|
// and the features of the given userfont entry, or nullptr if none is available.
|
2013-05-21 23:42:30 -07:00
|
|
|
// The aPrivate flag is set for requests coming from private windows,
|
|
|
|
// so we can avoid leaking fonts cached in private windows mode out to
|
|
|
|
// normal windows.
|
2014-09-08 00:23:20 -07:00
|
|
|
static gfxFontEntry* GetFont(nsIURI* aSrcURI,
|
|
|
|
nsIPrincipal* aPrincipal,
|
|
|
|
gfxUserFontEntry* aUserFontEntry,
|
2014-09-08 00:23:20 -07:00
|
|
|
bool aPrivate);
|
2012-12-10 01:31:07 -08:00
|
|
|
|
|
|
|
// Clear everything so that we don't leak URIs and Principals.
|
|
|
|
static void Shutdown();
|
|
|
|
|
2013-09-18 18:56:49 -07:00
|
|
|
#ifdef DEBUG_USERFONT_CACHE
|
|
|
|
// dump contents
|
|
|
|
static void Dump();
|
|
|
|
#endif
|
|
|
|
|
2012-12-10 01:31:07 -08:00
|
|
|
private:
|
2013-05-21 21:39:47 -07:00
|
|
|
// Helper that we use to observe the empty-cache notification
|
|
|
|
// from nsICacheService.
|
|
|
|
class Flusher : public nsIObserver
|
|
|
|
{
|
2014-06-23 11:49:07 -07:00
|
|
|
virtual ~Flusher() {}
|
2013-05-21 21:39:47 -07:00
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
Flusher() {}
|
|
|
|
};
|
|
|
|
|
2012-12-10 01:31:07 -08:00
|
|
|
// Key used to look up entries in the user-font cache.
|
|
|
|
// Note that key comparison does *not* use the mFontEntry field
|
|
|
|
// as a whole; it only compares specific fields within the entry
|
|
|
|
// (weight/width/style/features) that could affect font selection
|
2014-09-08 00:23:20 -07:00
|
|
|
// or rendering, and that must match between a font-set's userfont
|
2012-12-10 01:31:07 -08:00
|
|
|
// entry and the corresponding "real" font entry.
|
|
|
|
struct Key {
|
|
|
|
nsCOMPtr<nsIURI> mURI;
|
2014-06-27 08:19:28 -07:00
|
|
|
nsCOMPtr<nsIPrincipal> mPrincipal; // use nullptr with data: URLs
|
2014-09-08 00:23:20 -07:00
|
|
|
gfxFontEntry* mFontEntry;
|
2014-08-04 09:26:55 -07:00
|
|
|
uint32_t mCRC32;
|
|
|
|
uint32_t mLength;
|
2013-05-21 23:42:30 -07:00
|
|
|
bool mPrivate;
|
2014-06-30 11:05:28 -07:00
|
|
|
EntryPersistence mPersistence;
|
2012-12-10 01:31:07 -08:00
|
|
|
|
|
|
|
Key(nsIURI* aURI, nsIPrincipal* aPrincipal,
|
2014-06-30 11:05:28 -07:00
|
|
|
gfxFontEntry* aFontEntry, bool aPrivate,
|
|
|
|
EntryPersistence aPersistence = kDiscardable)
|
2012-12-10 01:31:07 -08:00
|
|
|
: mURI(aURI),
|
|
|
|
mPrincipal(aPrincipal),
|
2013-05-21 23:42:30 -07:00
|
|
|
mFontEntry(aFontEntry),
|
2014-08-04 09:26:55 -07:00
|
|
|
mCRC32(0),
|
|
|
|
mLength(0),
|
|
|
|
mPrivate(aPrivate),
|
|
|
|
mPersistence(aPersistence)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
Key(uint32_t aCRC32, uint32_t aLength,
|
|
|
|
gfxFontEntry* aFontEntry, bool aPrivate,
|
|
|
|
EntryPersistence aPersistence = kDiscardable)
|
|
|
|
: mURI(nullptr),
|
|
|
|
mPrincipal(nullptr),
|
|
|
|
mFontEntry(aFontEntry),
|
|
|
|
mCRC32(aCRC32),
|
|
|
|
mLength(aLength),
|
2014-06-30 11:05:28 -07:00
|
|
|
mPrivate(aPrivate),
|
|
|
|
mPersistence(aPersistence)
|
2012-12-10 01:31:07 -08:00
|
|
|
{ }
|
|
|
|
};
|
|
|
|
|
|
|
|
class Entry : public PLDHashEntryHdr {
|
|
|
|
public:
|
|
|
|
typedef const Key& KeyType;
|
|
|
|
typedef const Key* KeyTypePointer;
|
|
|
|
|
2014-08-07 18:17:30 -07:00
|
|
|
explicit Entry(KeyTypePointer aKey)
|
2012-12-10 01:31:07 -08:00
|
|
|
: mURI(aKey->mURI),
|
|
|
|
mPrincipal(aKey->mPrincipal),
|
2014-08-04 09:26:55 -07:00
|
|
|
mCRC32(aKey->mCRC32),
|
|
|
|
mLength(aKey->mLength),
|
2014-08-11 14:53:06 -07:00
|
|
|
mFontEntry(aKey->mFontEntry),
|
2014-06-30 11:05:28 -07:00
|
|
|
mPrivate(aKey->mPrivate),
|
|
|
|
mPersistence(aKey->mPersistence)
|
2012-12-10 01:31:07 -08:00
|
|
|
{ }
|
|
|
|
|
|
|
|
Entry(const Entry& aOther)
|
|
|
|
: mURI(aOther.mURI),
|
|
|
|
mPrincipal(aOther.mPrincipal),
|
2014-08-04 09:26:55 -07:00
|
|
|
mCRC32(aOther.mCRC32),
|
|
|
|
mLength(aOther.mLength),
|
2014-08-11 14:53:06 -07:00
|
|
|
mFontEntry(aOther.mFontEntry),
|
2014-06-30 11:05:28 -07:00
|
|
|
mPrivate(aOther.mPrivate),
|
|
|
|
mPersistence(aOther.mPersistence)
|
2012-12-10 01:31:07 -08:00
|
|
|
{ }
|
|
|
|
|
|
|
|
~Entry() { }
|
|
|
|
|
|
|
|
bool KeyEquals(const KeyTypePointer aKey) const;
|
|
|
|
|
|
|
|
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
|
|
|
|
|
|
|
static PLDHashNumber HashKey(const KeyTypePointer aKey) {
|
2014-08-04 09:26:55 -07:00
|
|
|
if (aKey->mLength) {
|
|
|
|
return aKey->mCRC32;
|
|
|
|
}
|
2014-06-27 08:19:28 -07:00
|
|
|
uint32_t principalHash = 0;
|
|
|
|
if (aKey->mPrincipal) {
|
|
|
|
aKey->mPrincipal->GetHashValue(&principalHash);
|
|
|
|
}
|
2013-05-21 23:42:30 -07:00
|
|
|
return mozilla::HashGeneric(principalHash + int(aKey->mPrivate),
|
2012-12-10 01:31:07 -08:00
|
|
|
nsURIHashKey::HashKey(aKey->mURI),
|
|
|
|
HashFeatures(aKey->mFontEntry->mFeatureSettings),
|
2013-02-17 18:22:55 -08:00
|
|
|
mozilla::HashString(aKey->mFontEntry->mFamilyName),
|
2012-12-19 01:42:25 -08:00
|
|
|
((uint32_t)aKey->mFontEntry->mItalic |
|
2012-12-10 01:31:07 -08:00
|
|
|
(aKey->mFontEntry->mWeight << 1) |
|
|
|
|
(aKey->mFontEntry->mStretch << 10) ) ^
|
|
|
|
aKey->mFontEntry->mLanguageOverride);
|
|
|
|
}
|
|
|
|
|
|
|
|
enum { ALLOW_MEMMOVE = false };
|
|
|
|
|
|
|
|
gfxFontEntry* GetFontEntry() const { return mFontEntry; }
|
|
|
|
|
2014-06-30 11:05:28 -07:00
|
|
|
static PLDHashOperator
|
|
|
|
RemoveUnlessPersistent(Entry* aEntry, void* aUserData);
|
|
|
|
static PLDHashOperator
|
|
|
|
RemoveIfPrivate(Entry* aEntry, void* aUserData);
|
|
|
|
static PLDHashOperator
|
|
|
|
RemoveIfMatches(Entry* aEntry, void* aUserData);
|
|
|
|
static PLDHashOperator
|
|
|
|
DisconnectSVG(Entry* aEntry, void* aUserData);
|
2013-05-21 23:42:30 -07:00
|
|
|
|
2013-09-18 18:56:49 -07:00
|
|
|
#ifdef DEBUG_USERFONT_CACHE
|
|
|
|
static PLDHashOperator DumpEntry(Entry* aEntry, void* aUserData);
|
|
|
|
#endif
|
|
|
|
|
2012-12-10 01:31:07 -08:00
|
|
|
private:
|
|
|
|
static uint32_t
|
|
|
|
HashFeatures(const nsTArray<gfxFontFeature>& aFeatures) {
|
|
|
|
return mozilla::HashBytes(aFeatures.Elements(),
|
|
|
|
aFeatures.Length() * sizeof(gfxFontFeature));
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> mURI;
|
2014-06-27 08:19:28 -07:00
|
|
|
nsCOMPtr<nsIPrincipal> mPrincipal; // or nullptr for data: URLs
|
2012-12-10 01:31:07 -08:00
|
|
|
|
2014-08-04 09:26:55 -07:00
|
|
|
uint32_t mCRC32;
|
|
|
|
uint32_t mLength;
|
|
|
|
|
2012-12-10 01:31:07 -08:00
|
|
|
// The "real" font entry corresponding to this downloaded font.
|
|
|
|
// The font entry MUST notify the cache when it is destroyed
|
|
|
|
// (by calling Forget()).
|
2014-09-08 00:23:20 -07:00
|
|
|
gfxFontEntry* mFontEntry;
|
2013-05-21 23:42:30 -07:00
|
|
|
|
|
|
|
// Whether this font was loaded from a private window.
|
|
|
|
bool mPrivate;
|
2014-06-30 11:05:28 -07:00
|
|
|
|
|
|
|
// Whether this entry should survive cache-flushing.
|
|
|
|
EntryPersistence mPersistence;
|
2012-12-10 01:31:07 -08:00
|
|
|
};
|
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
static nsTHashtable<Entry>* sUserFonts;
|
2012-12-10 01:31:07 -08:00
|
|
|
};
|
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
void SetLocalRulesUsed() {
|
|
|
|
mLocalRulesUsed = true;
|
|
|
|
}
|
|
|
|
|
2014-10-16 17:15:29 -07:00
|
|
|
#ifdef PR_LOGGING
|
|
|
|
static PRLogModuleInfo* GetUserFontsLog();
|
|
|
|
#endif
|
|
|
|
|
2008-09-30 20:04:10 -07:00
|
|
|
protected:
|
2014-04-04 09:27:02 -07:00
|
|
|
// Protected destructor, to discourage deletion outside of Release():
|
|
|
|
virtual ~gfxUserFontSet();
|
|
|
|
|
2013-05-21 23:42:30 -07:00
|
|
|
// Return whether the font set is associated with a private-browsing tab.
|
|
|
|
virtual bool GetPrivateBrowsing() = 0;
|
|
|
|
|
2012-03-15 20:31:01 -07:00
|
|
|
// parse data for a data URL
|
2014-09-08 00:23:20 -07:00
|
|
|
virtual nsresult SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
|
|
|
|
const gfxFontFaceSrc* aFontFaceSrc,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint8_t* &aBuffer,
|
2012-12-10 01:31:07 -08:00
|
|
|
uint32_t &aBufferLength) = 0;
|
2012-03-15 20:31:01 -07:00
|
|
|
|
2011-07-12 04:24:36 -07:00
|
|
|
// report a problem of some kind (implemented in nsUserFontSet)
|
2014-09-08 00:23:20 -07:00
|
|
|
virtual nsresult LogMessage(gfxUserFontEntry* aUserFontEntry,
|
|
|
|
const char* aMessage,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aFlags = nsIScriptError::errorFlag,
|
2012-07-27 06:59:29 -07:00
|
|
|
nsresult aStatus = NS_OK) = 0;
|
2011-07-12 04:24:36 -07:00
|
|
|
|
2014-04-17 07:17:22 -07:00
|
|
|
// helper method for performing the actual userfont set rebuild
|
|
|
|
virtual void DoRebuildUserFontSet() = 0;
|
|
|
|
|
2014-10-01 19:32:07 -07:00
|
|
|
// helper method for FindOrCreateUserFontEntry
|
2014-09-08 00:23:20 -07:00
|
|
|
gfxUserFontEntry* FindExistingUserFontEntry(
|
|
|
|
gfxUserFontFamily* aFamily,
|
2014-07-22 22:05:50 -07:00
|
|
|
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
|
|
|
|
uint32_t aWeight,
|
|
|
|
int32_t aStretch,
|
|
|
|
uint32_t aItalicStyle,
|
|
|
|
const nsTArray<gfxFontFeature>& aFeatureSettings,
|
|
|
|
uint32_t aLanguageOverride,
|
|
|
|
gfxSparseBitSet* aUnicodeRanges);
|
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
// creates a new gfxUserFontFamily in mFontFamilies, or returns an existing
|
2014-07-09 00:08:55 -07:00
|
|
|
// family if there is one
|
2014-09-08 00:23:20 -07:00
|
|
|
gfxUserFontFamily* GetFamily(const nsAString& aFamilyName);
|
2014-07-09 00:08:55 -07:00
|
|
|
|
2008-09-30 20:04:10 -07:00
|
|
|
// font families defined by @font-face rules
|
2014-09-08 00:23:20 -07:00
|
|
|
nsRefPtrHashtable<nsStringHashKey, gfxUserFontFamily> mFontFamilies;
|
2008-09-30 20:04:10 -07:00
|
|
|
|
2014-09-24 20:16:54 -07:00
|
|
|
uint64_t mGeneration; // bumped on any font load change
|
|
|
|
uint64_t mRebuildGeneration; // only bumped on rebuilds
|
2011-07-12 04:24:36 -07:00
|
|
|
|
2014-04-17 07:17:22 -07:00
|
|
|
// true when local names have been looked up, false otherwise
|
|
|
|
bool mLocalRulesUsed;
|
2008-09-30 20:04:10 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
// acts a placeholder until the real font is downloaded
|
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
class gfxUserFontEntry : public gfxFontEntry {
|
2009-08-16 06:52:12 -07:00
|
|
|
friend class gfxUserFontSet;
|
2014-07-09 00:08:52 -07:00
|
|
|
friend class nsUserFontSet;
|
|
|
|
friend class nsFontFaceLoader;
|
2014-08-23 07:12:00 -07:00
|
|
|
friend class gfxOTSContext;
|
2008-09-30 20:04:10 -07:00
|
|
|
|
|
|
|
public:
|
2014-09-24 20:16:53 -07:00
|
|
|
enum UserFontLoadState {
|
|
|
|
STATUS_NOT_LOADED = 0,
|
|
|
|
STATUS_LOADING,
|
2014-07-09 00:08:52 -07:00
|
|
|
STATUS_LOADED,
|
2014-09-24 20:16:53 -07:00
|
|
|
STATUS_FAILED
|
2014-07-09 00:08:52 -07:00
|
|
|
};
|
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
gfxUserFontEntry(gfxUserFontSet* aFontSet,
|
2014-09-08 00:23:20 -07:00
|
|
|
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
|
|
|
|
uint32_t aWeight,
|
|
|
|
int32_t aStretch,
|
|
|
|
uint32_t aItalicStyle,
|
|
|
|
const nsTArray<gfxFontFeature>& aFeatureSettings,
|
|
|
|
uint32_t aLanguageOverride,
|
2014-09-08 00:23:20 -07:00
|
|
|
gfxSparseBitSet* aUnicodeRanges);
|
2008-09-30 20:04:10 -07:00
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
virtual ~gfxUserFontEntry();
|
2008-09-30 20:04:10 -07:00
|
|
|
|
2013-08-12 02:07:55 -07:00
|
|
|
// Return whether the entry matches the given list of attributes
|
|
|
|
bool Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
|
|
|
|
uint32_t aWeight,
|
|
|
|
int32_t aStretch,
|
|
|
|
uint32_t aItalicStyle,
|
|
|
|
const nsTArray<gfxFontFeature>& aFeatureSettings,
|
|
|
|
uint32_t aLanguageOverride,
|
2014-09-08 00:23:20 -07:00
|
|
|
gfxSparseBitSet* aUnicodeRanges);
|
|
|
|
|
2014-09-24 20:16:53 -07:00
|
|
|
virtual gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle,
|
|
|
|
bool aNeedsBold);
|
2013-08-12 02:07:55 -07:00
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
gfxFontEntry* GetPlatformFontEntry() { return mPlatformFontEntry; }
|
|
|
|
|
2014-09-24 20:16:53 -07:00
|
|
|
// is the font loading or loaded, or did it fail?
|
|
|
|
UserFontLoadState LoadState() const { return mUserFontLoadState; }
|
|
|
|
|
|
|
|
// whether to wait before using fallback font or not
|
|
|
|
bool WaitForUserFont() const {
|
|
|
|
return mUserFontLoadState == STATUS_LOADING &&
|
|
|
|
mFontDataLoadingState < LOADING_SLOWLY;
|
|
|
|
}
|
|
|
|
|
2014-11-05 20:42:50 -08:00
|
|
|
// for userfonts, cmap is used to store the unicode range data
|
|
|
|
// no cmap ==> all codepoints permitted
|
|
|
|
bool CharacterInUnicodeRange(uint32_t ch) const {
|
|
|
|
if (mCharacterMap) {
|
|
|
|
return mCharacterMap->test(ch);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
gfxCharacterMap* GetUnicodeRangeMap() const {
|
|
|
|
return mCharacterMap.get();
|
|
|
|
}
|
|
|
|
|
2014-09-24 20:16:53 -07:00
|
|
|
// load the font - starts the loading of sources which continues until
|
|
|
|
// a valid font resource is found or all sources fail
|
|
|
|
void Load();
|
2009-10-07 08:26:58 -07:00
|
|
|
|
2014-10-01 19:32:05 -07:00
|
|
|
// methods to expose some information to FontFaceSet::UserFontSet
|
|
|
|
// since we can't make that class a friend
|
|
|
|
void SetLoader(nsFontFaceLoader* aLoader) { mLoader = aLoader; }
|
|
|
|
nsFontFaceLoader* GetLoader() { return mLoader; }
|
|
|
|
nsIPrincipal* GetPrincipal() { return mPrincipal; }
|
|
|
|
uint32_t GetSrcIndex() { return mSrcIndex; }
|
|
|
|
void GetFamilyNameAndURIForLogging(nsACString& aFamilyName,
|
|
|
|
nsACString& aURI);
|
|
|
|
|
2014-07-09 00:08:52 -07:00
|
|
|
protected:
|
2014-09-08 00:23:20 -07:00
|
|
|
const uint8_t* SanitizeOpenTypeData(const uint8_t* aData,
|
2014-07-09 00:08:52 -07:00
|
|
|
uint32_t aLength,
|
|
|
|
uint32_t& aSaneLength,
|
2014-10-04 03:36:05 -07:00
|
|
|
gfxUserFontType aFontType);
|
2014-07-09 00:08:52 -07:00
|
|
|
|
2014-09-24 20:16:53 -07:00
|
|
|
// attempt to load the next resource in the src list.
|
|
|
|
void LoadNextSrc();
|
|
|
|
|
|
|
|
// change the load state
|
2014-10-01 19:32:06 -07:00
|
|
|
virtual void SetLoadState(UserFontLoadState aLoadState);
|
2014-09-24 20:16:53 -07:00
|
|
|
|
|
|
|
// when download has been completed, pass back data here
|
|
|
|
// aDownloadStatus == NS_OK ==> download succeeded, error otherwise
|
|
|
|
// returns true if platform font creation sucessful (or local()
|
|
|
|
// reference was next in line)
|
|
|
|
// Ownership of aFontData is passed in here; the font set must
|
|
|
|
// ensure that it is eventually deleted with NS_Free().
|
|
|
|
bool FontDataDownloadComplete(const uint8_t* aFontData, uint32_t aLength,
|
|
|
|
nsresult aDownloadStatus);
|
2014-07-09 00:08:52 -07:00
|
|
|
|
|
|
|
// helper method for creating a platform font
|
2014-09-08 00:23:20 -07:00
|
|
|
// returns true if platform font creation successful
|
2014-07-09 00:08:52 -07:00
|
|
|
// Ownership of aFontData is passed in here; the font must
|
|
|
|
// ensure that it is eventually deleted with NS_Free().
|
2014-09-24 20:16:53 -07:00
|
|
|
bool LoadPlatformFont(const uint8_t* aFontData, uint32_t& aLength);
|
2014-07-09 00:08:52 -07:00
|
|
|
|
|
|
|
// store metadata and src details for current src into aFontEntry
|
|
|
|
void StoreUserFontData(gfxFontEntry* aFontEntry,
|
|
|
|
bool aPrivate,
|
|
|
|
const nsAString& aOriginalName,
|
|
|
|
FallibleTArray<uint8_t>* aMetadata,
|
2014-10-04 03:46:54 -07:00
|
|
|
uint32_t aMetaOrigLen,
|
|
|
|
uint8_t aCompression);
|
2014-07-09 00:08:52 -07:00
|
|
|
|
2014-09-24 20:16:53 -07:00
|
|
|
// general load state
|
|
|
|
UserFontLoadState mUserFontLoadState;
|
|
|
|
|
|
|
|
// detailed load state while font data is loading
|
|
|
|
// used to determine whether to use fallback font or not
|
2011-01-05 13:48:48 -08:00
|
|
|
// note that code depends on the ordering of these values!
|
2014-09-24 20:16:53 -07:00
|
|
|
enum FontDataLoadingState {
|
2011-01-05 13:48:48 -08:00
|
|
|
NOT_LOADING = 0, // not started to load any font resources yet
|
|
|
|
LOADING_STARTED, // loading has started; hide fallback font
|
|
|
|
LOADING_ALMOST_DONE, // timeout happened but we're nearly done,
|
|
|
|
// so keep hiding fallback font
|
2011-03-23 20:01:50 -07:00
|
|
|
LOADING_SLOWLY, // timeout happened and we're not nearly done,
|
2011-01-05 13:48:48 -08:00
|
|
|
// so use the fallback font
|
2011-03-23 20:01:50 -07:00
|
|
|
LOADING_FAILED // failed to load any source: use fallback
|
2011-01-05 13:48:48 -08:00
|
|
|
};
|
2014-09-24 20:16:53 -07:00
|
|
|
FontDataLoadingState mFontDataLoadingState;
|
|
|
|
|
2012-01-05 02:14:11 -08:00
|
|
|
bool mUnsupportedFormat;
|
2011-01-05 13:48:48 -08:00
|
|
|
|
2014-09-08 00:23:20 -07:00
|
|
|
nsRefPtr<gfxFontEntry> mPlatformFontEntry;
|
2011-01-05 13:48:48 -08:00
|
|
|
nsTArray<gfxFontFaceSrc> mSrcList;
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t mSrcIndex; // index of loading src item
|
2014-09-08 00:23:20 -07:00
|
|
|
nsFontFaceLoader* mLoader; // current loader for this entry, if any
|
|
|
|
gfxUserFontSet* mFontSet; // font-set to which the userfont entry belongs
|
2012-12-10 01:31:07 -08:00
|
|
|
nsCOMPtr<nsIPrincipal> mPrincipal;
|
2008-09-30 20:04:10 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* GFX_USER_FONT_SET_H */
|