gecko/layout/style/FontFace.cpp

296 lines
6.7 KiB
C++
Raw Normal View History

/* -*- 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"
#include "mozilla/dom/FontFaceSet.h"
#include "mozilla/dom/Promise.h"
#include "nsCSSRules.h"
#include "nsIDocument.h"
#include "nsStyleUtil.h"
using namespace mozilla::dom;
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FontFace, mParent, mLoaded, mRule)
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)
FontFace::FontFace(nsISupports* aParent, nsPresContext* aPresContext)
: mParent(aParent)
, mPresContext(aPresContext)
, mStatus(FontFaceLoadStatus::Unloaded)
{
MOZ_COUNT_CTOR(FontFace);
MOZ_ASSERT(mPresContext);
SetIsDOMBinding();
}
FontFace::~FontFace()
{
MOZ_COUNT_DTOR(FontFace);
}
JSObject*
FontFace::WrapObject(JSContext* aCx)
{
return FontFaceBinding::Wrap(aCx, this);
}
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;
}
already_AddRefed<FontFace>
FontFace::CreateForRule(nsISupports* aGlobal,
nsPresContext* aPresContext,
nsCSSFontFaceRule* aRule,
gfxUserFontEntry* aUserFontEntry)
{
nsRefPtr<FontFace> obj = new FontFace(aGlobal, aPresContext);
obj->mRule = aRule;
obj->mStatus = LoadStateToStatus(aUserFontEntry->LoadState());
return obj.forget();
}
already_AddRefed<FontFace>
FontFace::Constructor(const GlobalObject& aGlobal,
const nsAString& aFamily,
const StringOrArrayBufferOrArrayBufferView& aSource,
const FontFaceDescriptors& aDescriptors,
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);
return obj.forget();
}
void
FontFace::GetFamily(nsString& aResult)
{
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);
}
void
FontFace::SetFamily(const nsAString& aValue, ErrorResult& aRv)
{
}
void
FontFace::GetStyle(nsString& aResult)
{
mPresContext->FlushUserFontSet();
GetDesc(eCSSFontDesc_Style, eCSSProperty_font_style, aResult);
}
void
FontFace::SetStyle(const nsAString& aValue, ErrorResult& aRv)
{
}
void
FontFace::GetWeight(nsString& aResult)
{
mPresContext->FlushUserFontSet();
GetDesc(eCSSFontDesc_Weight, eCSSProperty_font_weight, aResult);
}
void
FontFace::SetWeight(const nsAString& aValue, ErrorResult& aRv)
{
}
void
FontFace::GetStretch(nsString& aResult)
{
mPresContext->FlushUserFontSet();
GetDesc(eCSSFontDesc_Stretch, eCSSProperty_font_stretch, aResult);
}
void
FontFace::SetStretch(const nsAString& aValue, ErrorResult& aRv)
{
}
void
FontFace::GetUnicodeRange(nsString& aResult)
{
mPresContext->FlushUserFontSet();
nsCSSValue value;
GetDesc(eCSSFontDesc_UnicodeRange, value);
aResult.Truncate();
nsStyleUtil::AppendUnicodeRange(value, aResult);
}
void
FontFace::SetUnicodeRange(const nsAString& aValue, ErrorResult& aRv)
{
}
void
FontFace::GetVariant(nsString& aResult)
{
mPresContext->FlushUserFontSet();
// XXX Just expose the font-variant descriptor as "normal" until we
// support it properly (bug 1055385).
aResult.AssignLiteral("normal");
}
void
FontFace::SetVariant(const nsAString& aValue, ErrorResult& aRv)
{
}
void
FontFace::GetFeatureSettings(nsString& aResult)
{
mPresContext->FlushUserFontSet();
nsCSSValue value;
GetDesc(eCSSFontDesc_FontFeatureSettings, value);
aResult.Truncate();
nsStyleUtil::AppendFontFeatureSettings(value, aResult);
}
void
FontFace::SetFeatureSettings(const nsAString& aValue, ErrorResult& aRv)
{
}
FontFaceLoadStatus
FontFace::Status()
{
return mStatus;
}
Promise*
FontFace::Load()
{
return Loaded();
}
Promise*
FontFace::Loaded()
{
return nullptr;
}
void
FontFace::SetStatus(FontFaceLoadStatus aStatus)
{
mStatus = aStatus;
}
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);
}
}
// -- 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);
}