2014-10-01 19:32:05 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* 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/. */
|
|
|
|
|
|
|
|
#include "mozilla/dom/FontFace.h"
|
|
|
|
|
|
|
|
#include "mozilla/dom/FontFaceBinding.h"
|
2014-10-01 19:32:06 -07:00
|
|
|
#include "mozilla/dom/FontFaceSet.h"
|
2014-10-01 19:32:05 -07:00
|
|
|
#include "mozilla/dom/Promise.h"
|
2014-10-01 19:32:07 -07:00
|
|
|
#include "nsCSSParser.h"
|
2014-10-01 19:32:06 -07:00
|
|
|
#include "nsCSSRules.h"
|
2014-10-01 19:32:06 -07:00
|
|
|
#include "nsIDocument.h"
|
2014-10-01 19:32:07 -07:00
|
|
|
#include "nsStyleUtil.h"
|
2014-10-01 19:32:05 -07:00
|
|
|
|
|
|
|
using namespace mozilla::dom;
|
|
|
|
|
2014-10-01 19:32:06 -07:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FontFace, mParent, mLoaded, mRule)
|
2014-10-01 19:32:05 -07:00
|
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FontFace)
|
|
|
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(FontFace)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(FontFace)
|
|
|
|
|
2014-10-01 19:32:06 -07:00
|
|
|
FontFace::FontFace(nsISupports* aParent, nsPresContext* aPresContext)
|
2014-10-01 19:32:05 -07:00
|
|
|
: mParent(aParent)
|
2014-10-01 19:32:06 -07:00
|
|
|
, mPresContext(aPresContext)
|
|
|
|
, mStatus(FontFaceLoadStatus::Unloaded)
|
2014-10-01 19:32:05 -07:00
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(FontFace);
|
|
|
|
|
2014-10-01 19:32:06 -07:00
|
|
|
MOZ_ASSERT(mPresContext);
|
|
|
|
|
2014-10-01 19:32:05 -07:00
|
|
|
SetIsDOMBinding();
|
2014-10-01 19:32:07 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aParent);
|
|
|
|
|
|
|
|
if (global) {
|
|
|
|
ErrorResult rv;
|
|
|
|
mLoaded = Promise::Create(global, rv);
|
|
|
|
}
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
FontFace::~FontFace()
|
|
|
|
{
|
|
|
|
MOZ_COUNT_DTOR(FontFace);
|
|
|
|
}
|
|
|
|
|
|
|
|
JSObject*
|
|
|
|
FontFace::WrapObject(JSContext* aCx)
|
|
|
|
{
|
|
|
|
return FontFaceBinding::Wrap(aCx, this);
|
|
|
|
}
|
|
|
|
|
2014-10-01 19:32:06 -07:00
|
|
|
static FontFaceLoadStatus
|
|
|
|
LoadStateToStatus(gfxUserFontEntry::UserFontLoadState aLoadState)
|
|
|
|
{
|
|
|
|
switch (aLoadState) {
|
|
|
|
case gfxUserFontEntry::UserFontLoadState::STATUS_NOT_LOADED:
|
|
|
|
return FontFaceLoadStatus::Unloaded;
|
|
|
|
case gfxUserFontEntry::UserFontLoadState::STATUS_LOADING:
|
|
|
|
return FontFaceLoadStatus::Loading;
|
|
|
|
case gfxUserFontEntry::UserFontLoadState::STATUS_LOADED:
|
|
|
|
return FontFaceLoadStatus::Loaded;
|
|
|
|
case gfxUserFontEntry::UserFontLoadState::STATUS_FAILED:
|
|
|
|
return FontFaceLoadStatus::Error;
|
|
|
|
}
|
|
|
|
NS_NOTREACHED("invalid aLoadState value");
|
|
|
|
return FontFaceLoadStatus::Error;
|
|
|
|
}
|
|
|
|
|
2014-10-01 19:32:06 -07:00
|
|
|
already_AddRefed<FontFace>
|
2014-10-01 19:32:06 -07:00
|
|
|
FontFace::CreateForRule(nsISupports* aGlobal,
|
|
|
|
nsPresContext* aPresContext,
|
|
|
|
nsCSSFontFaceRule* aRule,
|
|
|
|
gfxUserFontEntry* aUserFontEntry)
|
2014-10-01 19:32:06 -07:00
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
nsCOMPtr<nsIGlobalObject> globalObject = do_QueryInterface(aGlobal);
|
|
|
|
|
2014-10-01 19:32:06 -07:00
|
|
|
nsRefPtr<FontFace> obj = new FontFace(aGlobal, aPresContext);
|
2014-10-01 19:32:06 -07:00
|
|
|
obj->mRule = aRule;
|
2014-10-01 19:32:07 -07:00
|
|
|
obj->SetStatus(LoadStateToStatus(aUserFontEntry->LoadState()));
|
2014-10-01 19:32:06 -07:00
|
|
|
return obj.forget();
|
|
|
|
}
|
|
|
|
|
2014-10-01 19:32:05 -07:00
|
|
|
already_AddRefed<FontFace>
|
|
|
|
FontFace::Constructor(const GlobalObject& aGlobal,
|
|
|
|
const nsAString& aFamily,
|
|
|
|
const StringOrArrayBufferOrArrayBufferView& aSource,
|
|
|
|
const FontFaceDescriptors& aDescriptors,
|
2014-10-01 19:32:06 -07:00
|
|
|
ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
nsISupports* global = aGlobal.GetAsSupports();
|
|
|
|
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(global);
|
|
|
|
nsIDocument* doc = window->GetDoc();
|
|
|
|
if (!doc) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIPresShell* shell = doc->GetShell();
|
|
|
|
if (!shell) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPresContext* presContext = shell->GetPresContext();
|
|
|
|
if (!presContext) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRefPtr<FontFace> obj = new FontFace(global, presContext);
|
2014-10-01 19:32:05 -07:00
|
|
|
return obj.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetFamily(nsString& aResult)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
|
|
|
|
// Serialize the same way as in nsCSSFontFaceStyleDecl::GetPropertyValue.
|
|
|
|
nsCSSValue value;
|
|
|
|
GetDesc(eCSSFontDesc_Family, value);
|
|
|
|
|
|
|
|
aResult.Truncate();
|
|
|
|
nsDependentString family(value.GetStringBufferValue());
|
|
|
|
nsStyleUtil::AppendEscapedCSSString(family, aResult);
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetFamily(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
SetDescriptor(eCSSFontDesc_Family, aValue, aRv);
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetStyle(nsString& aResult)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
GetDesc(eCSSFontDesc_Style, eCSSProperty_font_style, aResult);
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetStyle(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
SetDescriptor(eCSSFontDesc_Style, aValue, aRv);
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetWeight(nsString& aResult)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
GetDesc(eCSSFontDesc_Weight, eCSSProperty_font_weight, aResult);
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetWeight(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
SetDescriptor(eCSSFontDesc_Weight, aValue, aRv);
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetStretch(nsString& aResult)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
GetDesc(eCSSFontDesc_Stretch, eCSSProperty_font_stretch, aResult);
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetStretch(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
SetDescriptor(eCSSFontDesc_Stretch, aValue, aRv);
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetUnicodeRange(nsString& aResult)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
|
|
|
|
nsCSSValue value;
|
|
|
|
GetDesc(eCSSFontDesc_UnicodeRange, value);
|
|
|
|
|
|
|
|
aResult.Truncate();
|
|
|
|
nsStyleUtil::AppendUnicodeRange(value, aResult);
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetUnicodeRange(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
SetDescriptor(eCSSFontDesc_UnicodeRange, aValue, aRv);
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetVariant(nsString& aResult)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
|
|
|
|
// XXX Just expose the font-variant descriptor as "normal" until we
|
|
|
|
// support it properly (bug 1055385).
|
|
|
|
aResult.AssignLiteral("normal");
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetVariant(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
|
|
|
|
// XXX Ignore assignments to variant until we support font-variant
|
|
|
|
// descriptors (bug 1055385).
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetFeatureSettings(nsString& aResult)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
|
|
|
|
nsCSSValue value;
|
|
|
|
GetDesc(eCSSFontDesc_FontFeatureSettings, value);
|
|
|
|
|
|
|
|
aResult.Truncate();
|
|
|
|
nsStyleUtil::AppendFontFeatureSettings(value, aResult);
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetFeatureSettings(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
SetDescriptor(eCSSFontDesc_FontFeatureSettings, aValue, aRv);
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
FontFaceLoadStatus
|
|
|
|
FontFace::Status()
|
|
|
|
{
|
2014-10-01 19:32:06 -07:00
|
|
|
return mStatus;
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Promise*
|
2014-10-01 19:32:07 -07:00
|
|
|
FontFace::Load(ErrorResult& aRv)
|
2014-10-01 19:32:05 -07:00
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
if (!mLoaded) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mLoaded;
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Promise*
|
2014-10-01 19:32:07 -07:00
|
|
|
FontFace::GetLoaded(ErrorResult& aRv)
|
2014-10-01 19:32:05 -07:00
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
mPresContext->FlushUserFontSet();
|
|
|
|
|
|
|
|
if (!mLoaded) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mLoaded;
|
2014-10-01 19:32:05 -07:00
|
|
|
}
|
2014-10-01 19:32:06 -07:00
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetStatus(FontFaceLoadStatus aStatus)
|
|
|
|
{
|
2014-10-01 19:32:07 -07:00
|
|
|
if (mStatus == aStatus) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-01 19:32:06 -07:00
|
|
|
mStatus = aStatus;
|
2014-10-01 19:32:07 -07:00
|
|
|
|
|
|
|
if (!mLoaded) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2014-10-01 19:32:06 -07:00
|
|
|
}
|
|
|
|
|
2014-10-01 19:32:07 -07:00
|
|
|
bool
|
|
|
|
FontFace::ParseDescriptor(nsCSSFontDesc aDescID,
|
|
|
|
const nsAString& aString,
|
|
|
|
nsCSSValue& aResult)
|
|
|
|
{
|
|
|
|
nsCSSParser parser;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mParent);
|
|
|
|
nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull();
|
|
|
|
|
|
|
|
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mParent);
|
|
|
|
nsCOMPtr<nsIURI> base = window->GetDocBaseURI();
|
|
|
|
|
|
|
|
if (!parser.ParseFontFaceDescriptor(aDescID, aString,
|
|
|
|
nullptr, // aSheetURL
|
|
|
|
base,
|
|
|
|
principal,
|
|
|
|
aResult)) {
|
|
|
|
aResult.Reset();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetDescriptor(nsCSSFontDesc aFontDesc,
|
|
|
|
const nsAString& aValue,
|
|
|
|
ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(!mRule, "we don't handle rule-connected FontFace objects yet");
|
|
|
|
if (mRule) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCSSValue parsedValue;
|
|
|
|
if (!ParseDescriptor(aFontDesc, aValue, parsedValue)) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mDescriptors->Get(aFontDesc) = parsedValue;
|
|
|
|
|
|
|
|
// XXX Setting descriptors doesn't actually have any effect on FontFace
|
|
|
|
// objects that have started loading or have already been loaded.
|
|
|
|
}
|
|
|
|
|
2014-10-01 19:32:07 -07:00
|
|
|
void
|
|
|
|
FontFace::GetDesc(nsCSSFontDesc aDescID, nsCSSValue& aResult) const
|
|
|
|
{
|
|
|
|
if (mRule) {
|
|
|
|
MOZ_ASSERT(!mDescriptors);
|
|
|
|
mRule->GetDesc(aDescID, aResult);
|
|
|
|
} else {
|
|
|
|
aResult = mDescriptors->Get(aDescID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetDesc(nsCSSFontDesc aDescID,
|
|
|
|
nsCSSProperty aPropID,
|
|
|
|
nsString& aResult) const
|
|
|
|
{
|
|
|
|
nsCSSValue value;
|
|
|
|
GetDesc(aDescID, value);
|
|
|
|
|
|
|
|
aResult.Truncate();
|
|
|
|
|
|
|
|
// Fill in a default value for missing descriptors.
|
|
|
|
if (value.GetUnit() == eCSSUnit_Null) {
|
|
|
|
if (aDescID == eCSSFontDesc_UnicodeRange) {
|
|
|
|
aResult.AssignLiteral("U+0-10FFFF");
|
|
|
|
} else if (aDescID != eCSSFontDesc_Family &&
|
|
|
|
aDescID != eCSSFontDesc_Src) {
|
|
|
|
aResult.AssignLiteral("normal");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
value.AppendToString(aPropID, aResult, nsCSSValue::eNormalized);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-01 19:32:06 -07:00
|
|
|
// -- FontFace::Entry --------------------------------------------------------
|
|
|
|
|
|
|
|
/* virtual */ void
|
|
|
|
FontFace::Entry::SetLoadState(UserFontLoadState aLoadState)
|
|
|
|
{
|
|
|
|
gfxUserFontEntry::SetLoadState(aLoadState);
|
|
|
|
|
|
|
|
FontFace* face = GetFontFace();
|
|
|
|
if (face) {
|
|
|
|
face->SetStatus(LoadStateToStatus(aLoadState));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FontFace*
|
|
|
|
FontFace::Entry::GetFontFace()
|
|
|
|
{
|
|
|
|
FontFaceSet* fontFaceSet =
|
|
|
|
static_cast<FontFaceSet::UserFontSet*>(mFontSet)->GetFontFaceSet();
|
|
|
|
if (!fontFaceSet) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fontFaceSet->FindFontFaceForEntry(this);
|
|
|
|
}
|