зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1028497 - Part 25: Support loading of fonts from ArrayBuffer{,View}s. r=bzbarsky,jdaggett
This commit is contained in:
Родитель
1ea00788ea
Коммит
103bb77e68
|
@ -251,11 +251,17 @@ gfxUserFontEntry::StoreUserFontData(gfxFontEntry* aFontEntry,
|
|||
gfxUserFontData* userFontData = aFontEntry->mUserFontData;
|
||||
userFontData->mSrcIndex = mSrcIndex;
|
||||
const gfxFontFaceSrc& src = mSrcList[mSrcIndex];
|
||||
if (src.mIsLocal) {
|
||||
userFontData->mLocalName = src.mLocalName;
|
||||
} else {
|
||||
userFontData->mURI = src.mURI;
|
||||
userFontData->mPrincipal = mPrincipal;
|
||||
switch (src.mSourceType) {
|
||||
case gfxFontFaceSrc::eSourceType_Local:
|
||||
userFontData->mLocalName = src.mLocalName;
|
||||
break;
|
||||
case gfxFontFaceSrc::eSourceType_URL:
|
||||
userFontData->mURI = src.mURI;
|
||||
userFontData->mPrincipal = mPrincipal;
|
||||
break;
|
||||
case gfxFontFaceSrc::eSourceType_Buffer:
|
||||
userFontData->mIsBuffer = true;
|
||||
break;
|
||||
}
|
||||
userFontData->mPrivate = aPrivate;
|
||||
userFontData->mFormat = src.mFormatFlags;
|
||||
|
@ -357,11 +363,11 @@ gfxUserFontEntry::LoadNextSrc()
|
|||
// load each src entry in turn, until a local face is found
|
||||
// or a download begins successfully
|
||||
while (mSrcIndex < numSrc) {
|
||||
const gfxFontFaceSrc& currSrc = mSrcList[mSrcIndex];
|
||||
gfxFontFaceSrc& currSrc = mSrcList[mSrcIndex];
|
||||
|
||||
// src local ==> lookup and load immediately
|
||||
|
||||
if (currSrc.mIsLocal) {
|
||||
if (currSrc.mSourceType == gfxFontFaceSrc::eSourceType_Local) {
|
||||
gfxFontEntry* fe =
|
||||
gfxPlatform::GetPlatform()->LookupLocalFont(currSrc.mLocalName,
|
||||
mWeight,
|
||||
|
@ -393,7 +399,7 @@ gfxUserFontEntry::LoadNextSrc()
|
|||
}
|
||||
|
||||
// src url ==> start the load process
|
||||
else {
|
||||
else if (currSrc.mSourceType == gfxFontFaceSrc::eSourceType_URL) {
|
||||
if (gfxPlatform::GetPlatform()->IsFontFormatSupported(currSrc.mURI,
|
||||
currSrc.mFormatFlags)) {
|
||||
|
||||
|
@ -480,6 +486,28 @@ gfxUserFontEntry::LoadNextSrc()
|
|||
}
|
||||
}
|
||||
|
||||
// FontFace buffer ==> load immediately
|
||||
|
||||
else {
|
||||
MOZ_ASSERT(currSrc.mSourceType == gfxFontFaceSrc::eSourceType_Buffer);
|
||||
|
||||
uint8_t* buffer = nullptr;
|
||||
uint32_t bufferLength = 0;
|
||||
|
||||
// sync load font immediately
|
||||
currSrc.mBuffer->TakeBuffer(buffer, bufferLength);
|
||||
if (buffer && LoadPlatformFont(buffer, bufferLength)) {
|
||||
// LoadPlatformFont takes ownership of the buffer, so no need
|
||||
// to free it here.
|
||||
SetLoadState(STATUS_LOADED);
|
||||
return;
|
||||
} else {
|
||||
mFontSet->LogMessage(this,
|
||||
"font load failed",
|
||||
nsIScriptError::errorFlag);
|
||||
}
|
||||
}
|
||||
|
||||
mSrcIndex++;
|
||||
}
|
||||
|
||||
|
@ -597,7 +625,7 @@ gfxUserFontEntry::LoadPlatformFont(const uint8_t* aFontData, uint32_t& aLength)
|
|||
|
||||
// The downloaded data can now be discarded; the font entry is using the
|
||||
// sanitized copy
|
||||
NS_Free((void*)aFontData);
|
||||
moz_free((void*)aFontData);
|
||||
|
||||
return fe != nullptr;
|
||||
}
|
||||
|
@ -612,7 +640,7 @@ gfxUserFontEntry::Load()
|
|||
|
||||
// This is called when a font download finishes.
|
||||
// Ownership of aFontData passes in here, and the font set must
|
||||
// ensure that it is eventually deleted via NS_Free().
|
||||
// ensure that it is eventually deleted via moz_free().
|
||||
bool
|
||||
gfxUserFontEntry::FontDataDownloadComplete(const uint8_t* aFontData,
|
||||
uint32_t aLength,
|
||||
|
@ -1008,6 +1036,16 @@ gfxUserFontSet::UserFontCache::CacheFont(gfxFontEntry* aFontEntry,
|
|||
{
|
||||
NS_ASSERTION(aFontEntry->mFamilyName.Length() != 0,
|
||||
"caching a font associated with no family yet");
|
||||
|
||||
gfxUserFontData* data = aFontEntry->mUserFontData;
|
||||
if (data->mIsBuffer) {
|
||||
#ifdef DEBUG_USERFONT_CACHE
|
||||
printf("userfontcache skipped fontentry with buffer source: %p\n",
|
||||
aFontEntry);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sUserFonts) {
|
||||
sUserFonts = new nsTHashtable<Entry>;
|
||||
|
||||
|
@ -1022,7 +1060,6 @@ gfxUserFontSet::UserFontCache::CacheFont(gfxFontEntry* aFontEntry,
|
|||
}
|
||||
}
|
||||
|
||||
gfxUserFontData* data = aFontEntry->mUserFontData;
|
||||
if (data->mLength) {
|
||||
MOZ_ASSERT(aPersistence == kPersistent);
|
||||
MOZ_ASSERT(!data->mPrivate);
|
||||
|
|
|
@ -19,10 +19,27 @@ class nsFontFaceLoader;
|
|||
|
||||
//#define DEBUG_USERFONT_CACHE
|
||||
|
||||
class gfxFontFaceBufferSource
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(gfxFontFaceBufferSource)
|
||||
public:
|
||||
virtual void TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~gfxFontFaceBufferSource() {}
|
||||
};
|
||||
|
||||
// parsed CSS @font-face rule information
|
||||
// lifetime: from when @font-face rule processed until font is loaded
|
||||
struct gfxFontFaceSrc {
|
||||
bool mIsLocal; // url or local
|
||||
|
||||
enum SourceType {
|
||||
eSourceType_Local,
|
||||
eSourceType_URL,
|
||||
eSourceType_Buffer
|
||||
};
|
||||
|
||||
SourceType mSourceType;
|
||||
|
||||
// if url, whether to use the origin principal or not
|
||||
bool mUseOriginPrincipal;
|
||||
|
@ -36,20 +53,33 @@ struct gfxFontFaceSrc {
|
|||
nsCOMPtr<nsIURI> mURI; // uri if url
|
||||
nsCOMPtr<nsIURI> mReferrer; // referrer url if url
|
||||
nsCOMPtr<nsIPrincipal> mOriginPrincipal; // principal if url
|
||||
|
||||
nsRefPtr<gfxFontFaceBufferSource> mBuffer;
|
||||
};
|
||||
|
||||
inline bool
|
||||
operator==(const gfxFontFaceSrc& a, const gfxFontFaceSrc& b)
|
||||
{
|
||||
bool equals;
|
||||
return (a.mIsLocal && b.mIsLocal &&
|
||||
a.mLocalName == b.mLocalName) ||
|
||||
(!a.mIsLocal && !b.mIsLocal &&
|
||||
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));
|
||||
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;
|
||||
}
|
||||
|
||||
// Subclassed to store platform-specific code cleaned out when font entry is
|
||||
|
@ -62,7 +92,7 @@ class gfxUserFontData {
|
|||
public:
|
||||
gfxUserFontData()
|
||||
: mSrcIndex(0), mFormat(0), mMetaOrigLen(0),
|
||||
mCRC32(0), mLength(0), mPrivate(false)
|
||||
mCRC32(0), mLength(0), mPrivate(false), mIsBuffer(false)
|
||||
{ }
|
||||
virtual ~gfxUserFontData() { }
|
||||
|
||||
|
@ -77,6 +107,7 @@ public:
|
|||
uint32_t mCRC32; // Checksum
|
||||
uint32_t mLength; // Font length
|
||||
bool mPrivate; // whether font belongs to a private window
|
||||
bool mIsBuffer; // whether the font source was a buffer
|
||||
};
|
||||
|
||||
// initially contains a set of userfont font entry objects, replaced with
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "nsCSSParser.h"
|
||||
#include "nsCSSRules.h"
|
||||
#include "nsIDocument.h"
|
||||
|
@ -18,8 +19,48 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// -- FontFaceBufferSource ---------------------------------------------------
|
||||
|
||||
/**
|
||||
* An object that wraps a FontFace object and exposes its ArrayBuffer
|
||||
* or ArrayBufferView data in a form the user font set can consume.
|
||||
*/
|
||||
class FontFaceBufferSource : public gfxFontFaceBufferSource
|
||||
{
|
||||
public:
|
||||
FontFaceBufferSource(FontFace* aFontFace)
|
||||
: mFontFace(aFontFace) {}
|
||||
virtual void TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength);
|
||||
|
||||
private:
|
||||
nsRefPtr<FontFace> mFontFace;
|
||||
};
|
||||
|
||||
void
|
||||
FontFaceBufferSource::TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength)
|
||||
{
|
||||
mFontFace->TakeBuffer(aBuffer, aLength);
|
||||
}
|
||||
|
||||
// -- FontFaceInitializer ----------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
static void
|
||||
GetDataFrom(const T& aObject, uint8_t*& aBuffer, uint32_t& aLength)
|
||||
{
|
||||
MOZ_ASSERT(!aBuffer);
|
||||
aObject.ComputeLengthAndData();
|
||||
// We use moz_malloc here rather than a FallibleTArray or fallible
|
||||
// operator new[] since the gfxUserFontEntry will be calling moz_free
|
||||
// on it.
|
||||
aBuffer = (uint8_t*) moz_malloc(aObject.Length());
|
||||
if (!aBuffer) {
|
||||
return;
|
||||
}
|
||||
memcpy((void*) aBuffer, aObject.Data(), aObject.Length());
|
||||
aLength = aObject.Length();
|
||||
}
|
||||
|
||||
/**
|
||||
* A task that is dispatched to the event queue to call Initialize() on a
|
||||
* FontFace object with the source information that was passed to the JS
|
||||
|
@ -40,6 +81,7 @@ public:
|
|||
void SetSource(const ArrayBufferView& aArrayBufferView);
|
||||
|
||||
NS_IMETHOD Run();
|
||||
void TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength);
|
||||
|
||||
nsRefPtr<FontFace> mFontFace;
|
||||
FontFace::SourceType mSourceType;
|
||||
|
@ -71,14 +113,14 @@ void
|
|||
FontFaceInitializer::SetSource(const ArrayBuffer& aArrayBuffer)
|
||||
{
|
||||
mSourceType = FontFace::eSourceType_Buffer;
|
||||
// XXX Do something with the array buffer data.
|
||||
GetDataFrom(aArrayBuffer, mSourceBuffer, mSourceBufferLength);
|
||||
}
|
||||
|
||||
void
|
||||
FontFaceInitializer::SetSource(const ArrayBufferView& aArrayBufferView)
|
||||
{
|
||||
mSourceType = FontFace::eSourceType_Buffer;
|
||||
// XXX Do something with the array buffer data.
|
||||
GetDataFrom(aArrayBufferView, mSourceBuffer, mSourceBufferLength);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -88,6 +130,16 @@ FontFaceInitializer::Run()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
FontFaceInitializer::TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength)
|
||||
{
|
||||
aBuffer = mSourceBuffer;
|
||||
aLength = mSourceBufferLength;
|
||||
|
||||
mSourceBuffer = nullptr;
|
||||
mSourceBufferLength = 0;
|
||||
}
|
||||
|
||||
// -- FontFaceStatusSetter ---------------------------------------------------
|
||||
|
||||
/**
|
||||
|
@ -321,7 +373,23 @@ FontFace::Initialize(FontFaceInitializer* aInitializer)
|
|||
// We've been given an ArrayBuffer or ArrayBufferView as the source.
|
||||
MOZ_ASSERT(aInitializer->mSourceType == eSourceType_Buffer);
|
||||
|
||||
// XXX Handle array buffers.
|
||||
mSourceType = aInitializer->mSourceType;
|
||||
aInitializer->TakeBuffer(mSourceBuffer, mSourceBufferLength);
|
||||
|
||||
// Queue a task to set the status to "loading".
|
||||
nsCOMPtr<nsIRunnable> statusSetterTask =
|
||||
new FontFaceStatusSetter(this, FontFaceLoadStatus::Loading);
|
||||
NS_DispatchToMainThread(statusSetterTask);
|
||||
|
||||
// We are initialized.
|
||||
OnInitialized();
|
||||
|
||||
// ArrayBuffer(View)-backed FontFace objects are loaded on construction,
|
||||
// but we need to do this after going through the event loop so that the
|
||||
// FontFaceStatusSetter runs before us.
|
||||
nsCOMPtr<nsIRunnable> loaderTask =
|
||||
NS_NewRunnableMethod(this, &FontFace::DoLoad);
|
||||
NS_DispatchToMainThread(loaderTask);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -552,8 +620,11 @@ FontFace::SetStatus(FontFaceLoadStatus aStatus)
|
|||
if (mStatus == FontFaceLoadStatus::Loaded) {
|
||||
mLoaded->MaybeResolve(this);
|
||||
} else if (mStatus == FontFaceLoadStatus::Error) {
|
||||
// XXX Use NS_ERROR_DOM_SYNTAX_ERR for array buffer backed FontFaces.
|
||||
mLoaded->MaybeReject(NS_ERROR_DOM_NETWORK_ERR);
|
||||
if (mSourceType == eSourceType_Buffer) {
|
||||
mLoaded->MaybeReject(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
} else {
|
||||
mLoaded->MaybeReject(NS_ERROR_DOM_NETWORK_ERR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -764,6 +835,31 @@ FontFace::DisconnectFromRule()
|
|||
mInFontFaceSet = false;
|
||||
}
|
||||
|
||||
bool
|
||||
FontFace::HasFontData() const
|
||||
{
|
||||
return mSourceType == eSourceType_Buffer && mSourceBuffer;
|
||||
}
|
||||
|
||||
void
|
||||
FontFace::TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength)
|
||||
{
|
||||
MOZ_ASSERT(HasFontData());
|
||||
|
||||
aBuffer = mSourceBuffer;
|
||||
aLength = mSourceBufferLength;
|
||||
|
||||
mSourceBuffer = nullptr;
|
||||
mSourceBufferLength = 0;
|
||||
}
|
||||
|
||||
already_AddRefed<gfxFontFaceBufferSource>
|
||||
FontFace::CreateBufferSource()
|
||||
{
|
||||
nsRefPtr<FontFaceBufferSource> bufferSource = new FontFaceBufferSource(this);
|
||||
return bufferSource.forget();
|
||||
}
|
||||
|
||||
// -- FontFace::Entry --------------------------------------------------------
|
||||
|
||||
/* virtual */ void
|
||||
|
|
|
@ -12,12 +12,14 @@
|
|||
#include "nsCSSValue.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class gfxFontFaceBufferSource;
|
||||
class nsCSSFontFaceRule;
|
||||
class nsPresContext;
|
||||
|
||||
namespace mozilla {
|
||||
struct CSSFontFaceDescriptors;
|
||||
namespace dom {
|
||||
class FontFaceBufferSource;
|
||||
struct FontFaceDescriptors;
|
||||
class FontFaceSet;
|
||||
class FontFaceInitializer;
|
||||
|
@ -33,6 +35,7 @@ namespace dom {
|
|||
class FontFace MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
friend class mozilla::dom::FontFaceBufferSource;
|
||||
friend class mozilla::dom::FontFaceInitializer;
|
||||
friend class mozilla::dom::FontFaceStatusSetter;
|
||||
friend class Entry;
|
||||
|
@ -126,6 +129,24 @@ public:
|
|||
*/
|
||||
void DisconnectFromRule();
|
||||
|
||||
/**
|
||||
* Returns whether there is an ArrayBuffer or ArrayBufferView of font
|
||||
* data.
|
||||
*/
|
||||
bool HasFontData() const;
|
||||
|
||||
/**
|
||||
* Creates a gfxFontFaceBufferSource to represent the font data
|
||||
* in this object.
|
||||
*/
|
||||
already_AddRefed<gfxFontFaceBufferSource> CreateBufferSource();
|
||||
|
||||
/**
|
||||
* Gets a pointer to and the length of the font data stored in the
|
||||
* ArrayBuffer or ArrayBufferView.
|
||||
*/
|
||||
bool GetData(uint8_t*& aBuffer, uint32_t& aLength);
|
||||
|
||||
// Web IDL
|
||||
static already_AddRefed<FontFace>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
|
@ -202,6 +223,11 @@ private:
|
|||
nsCSSProperty aPropID,
|
||||
nsString& aResult) const;
|
||||
|
||||
/**
|
||||
* Returns and takes ownership of the buffer storing the font data.
|
||||
*/
|
||||
void TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength);
|
||||
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
nsPresContext* mPresContext;
|
||||
|
||||
|
|
|
@ -853,80 +853,89 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(const nsAString& aFamilyName,
|
|||
// set up src array
|
||||
nsTArray<gfxFontFaceSrc> srcArray;
|
||||
|
||||
aFontFace->GetDesc(eCSSFontDesc_Src, val);
|
||||
unit = val.GetUnit();
|
||||
if (unit == eCSSUnit_Array) {
|
||||
nsCSSValue::Array* srcArr = val.GetArrayValue();
|
||||
size_t numSrc = srcArr->Count();
|
||||
if (aFontFace->HasFontData()) {
|
||||
gfxFontFaceSrc* face = srcArray.AppendElement();
|
||||
if (!face)
|
||||
return nullptr;
|
||||
|
||||
for (size_t i = 0; i < numSrc; i++) {
|
||||
val = srcArr->Item(i);
|
||||
unit = val.GetUnit();
|
||||
gfxFontFaceSrc* face = srcArray.AppendElements(1);
|
||||
if (!face)
|
||||
return nullptr;
|
||||
|
||||
switch (unit) {
|
||||
|
||||
case eCSSUnit_Local_Font:
|
||||
val.GetStringValue(face->mLocalName);
|
||||
face->mIsLocal = true;
|
||||
face->mURI = nullptr;
|
||||
face->mFormatFlags = 0;
|
||||
break;
|
||||
case eCSSUnit_URL:
|
||||
face->mIsLocal = false;
|
||||
face->mURI = val.GetURLValue();
|
||||
face->mReferrer = val.GetURLStructValue()->mReferrer;
|
||||
face->mOriginPrincipal = val.GetURLStructValue()->mOriginPrincipal;
|
||||
NS_ASSERTION(face->mOriginPrincipal, "null origin principal in @font-face rule");
|
||||
|
||||
// agent and user stylesheets are treated slightly differently,
|
||||
// the same-site origin check and access control headers are
|
||||
// enforced against the sheet principal rather than the document
|
||||
// principal to allow user stylesheets to include @font-face rules
|
||||
face->mUseOriginPrincipal = (aSheetType == nsStyleSet::eUserSheet ||
|
||||
aSheetType == nsStyleSet::eAgentSheet);
|
||||
|
||||
face->mLocalName.Truncate();
|
||||
face->mFormatFlags = 0;
|
||||
while (i + 1 < numSrc && (val = srcArr->Item(i+1),
|
||||
val.GetUnit() == eCSSUnit_Font_Format)) {
|
||||
nsDependentString valueString(val.GetStringBufferValue());
|
||||
if (valueString.LowerCaseEqualsASCII("woff")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_WOFF;
|
||||
} else if (valueString.LowerCaseEqualsASCII("opentype")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_OPENTYPE;
|
||||
} else if (valueString.LowerCaseEqualsASCII("truetype")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE;
|
||||
} else if (valueString.LowerCaseEqualsASCII("truetype-aat")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT;
|
||||
} else if (valueString.LowerCaseEqualsASCII("embedded-opentype")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_EOT;
|
||||
} else if (valueString.LowerCaseEqualsASCII("svg")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_SVG;
|
||||
} else {
|
||||
// unknown format specified, mark to distinguish from the
|
||||
// case where no format hints are specified
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_UNKNOWN;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!face->mURI) {
|
||||
// if URI not valid, omit from src array
|
||||
srcArray.RemoveElementAt(srcArray.Length() - 1);
|
||||
NS_WARNING("null url in @font-face rule");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NS_ASSERTION(unit == eCSSUnit_Local_Font || unit == eCSSUnit_URL,
|
||||
"strange unit type in font-face src array");
|
||||
break;
|
||||
}
|
||||
}
|
||||
face->mSourceType = gfxFontFaceSrc::eSourceType_Buffer;
|
||||
face->mBuffer = aFontFace->CreateBufferSource();
|
||||
} else {
|
||||
NS_ASSERTION(unit == eCSSUnit_Null, "@font-face src has unexpected unit");
|
||||
aFontFace->GetDesc(eCSSFontDesc_Src, val);
|
||||
unit = val.GetUnit();
|
||||
if (unit == eCSSUnit_Array) {
|
||||
nsCSSValue::Array* srcArr = val.GetArrayValue();
|
||||
size_t numSrc = srcArr->Count();
|
||||
|
||||
for (size_t i = 0; i < numSrc; i++) {
|
||||
val = srcArr->Item(i);
|
||||
unit = val.GetUnit();
|
||||
gfxFontFaceSrc* face = srcArray.AppendElements(1);
|
||||
if (!face)
|
||||
return nullptr;
|
||||
|
||||
switch (unit) {
|
||||
|
||||
case eCSSUnit_Local_Font:
|
||||
val.GetStringValue(face->mLocalName);
|
||||
face->mSourceType = gfxFontFaceSrc::eSourceType_Local;
|
||||
face->mURI = nullptr;
|
||||
face->mFormatFlags = 0;
|
||||
break;
|
||||
case eCSSUnit_URL:
|
||||
face->mSourceType = gfxFontFaceSrc::eSourceType_URL;
|
||||
face->mURI = val.GetURLValue();
|
||||
face->mReferrer = val.GetURLStructValue()->mReferrer;
|
||||
face->mOriginPrincipal = val.GetURLStructValue()->mOriginPrincipal;
|
||||
NS_ASSERTION(face->mOriginPrincipal, "null origin principal in @font-face rule");
|
||||
|
||||
// agent and user stylesheets are treated slightly differently,
|
||||
// the same-site origin check and access control headers are
|
||||
// enforced against the sheet principal rather than the document
|
||||
// principal to allow user stylesheets to include @font-face rules
|
||||
face->mUseOriginPrincipal = (aSheetType == nsStyleSet::eUserSheet ||
|
||||
aSheetType == nsStyleSet::eAgentSheet);
|
||||
|
||||
face->mLocalName.Truncate();
|
||||
face->mFormatFlags = 0;
|
||||
while (i + 1 < numSrc && (val = srcArr->Item(i+1),
|
||||
val.GetUnit() == eCSSUnit_Font_Format)) {
|
||||
nsDependentString valueString(val.GetStringBufferValue());
|
||||
if (valueString.LowerCaseEqualsASCII("woff")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_WOFF;
|
||||
} else if (valueString.LowerCaseEqualsASCII("opentype")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_OPENTYPE;
|
||||
} else if (valueString.LowerCaseEqualsASCII("truetype")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE;
|
||||
} else if (valueString.LowerCaseEqualsASCII("truetype-aat")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT;
|
||||
} else if (valueString.LowerCaseEqualsASCII("embedded-opentype")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_EOT;
|
||||
} else if (valueString.LowerCaseEqualsASCII("svg")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_SVG;
|
||||
} else {
|
||||
// unknown format specified, mark to distinguish from the
|
||||
// case where no format hints are specified
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_UNKNOWN;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!face->mURI) {
|
||||
// if URI not valid, omit from src array
|
||||
srcArray.RemoveElementAt(srcArray.Length() - 1);
|
||||
NS_WARNING("null url in @font-face rule");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NS_ASSERTION(unit == eCSSUnit_Local_Font || unit == eCSSUnit_URL,
|
||||
"strange unit type in font-face src array");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NS_ASSERTION(unit == eCSSUnit_Null, "@font-face src has unexpected unit");
|
||||
}
|
||||
}
|
||||
|
||||
if (srcArray.IsEmpty()) {
|
||||
|
@ -1092,7 +1101,8 @@ FontFaceSet::CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
|
|||
if (!ps)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ASSERTION(aFontFaceSrc && !aFontFaceSrc->mIsLocal,
|
||||
NS_ASSERTION(aFontFaceSrc &&
|
||||
aFontFaceSrc->mSourceType == gfxFontFaceSrc::eSourceType_URL,
|
||||
"bad font face url passed to fontloader");
|
||||
NS_ASSERTION(aFontFaceSrc->mURI, "null font uri");
|
||||
if (!aFontFaceSrc->mURI)
|
||||
|
|
Загрузка…
Ссылка в новой задаче