2017-10-27 20:33:53 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2014-10-02 06:32:05 +04: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/. */
|
|
|
|
|
|
|
|
#include "mozilla/dom/FontFace.h"
|
|
|
|
|
2015-10-16 09:10:14 +03:00
|
|
|
#include <algorithm>
|
2014-10-02 06:32:05 +04:00
|
|
|
#include "mozilla/dom/FontFaceBinding.h"
|
2014-10-02 06:32:06 +04:00
|
|
|
#include "mozilla/dom/FontFaceSet.h"
|
2014-10-02 06:32:05 +04:00
|
|
|
#include "mozilla/dom/Promise.h"
|
2014-10-02 06:32:09 +04:00
|
|
|
#include "mozilla/dom/TypedArray.h"
|
|
|
|
#include "mozilla/dom/UnionTypes.h"
|
2016-09-14 16:47:32 +03:00
|
|
|
#include "mozilla/CycleCollectedJSContext.h"
|
2017-04-30 09:51:29 +03:00
|
|
|
#include "mozilla/ServoStyleSet.h"
|
|
|
|
#include "mozilla/ServoUtils.h"
|
2017-03-29 02:20:40 +03:00
|
|
|
#include "nsCSSFontFaceRule.h"
|
2014-10-02 06:32:07 +04:00
|
|
|
#include "nsCSSParser.h"
|
2014-10-02 06:32:06 +04:00
|
|
|
#include "nsIDocument.h"
|
2014-10-02 06:32:07 +04:00
|
|
|
#include "nsStyleUtil.h"
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
// -- 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:
|
2014-09-24 17:16:53 +04:00
|
|
|
explicit FontFaceBufferSource(FontFace* aFontFace)
|
2014-10-02 06:32:09 +04:00
|
|
|
: mFontFace(aFontFace) {}
|
|
|
|
virtual void TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength);
|
|
|
|
|
|
|
|
private:
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<FontFace> mFontFace;
|
2014-10-02 06:32:09 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFaceBufferSource::TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength)
|
|
|
|
{
|
2015-05-11 04:24:49 +03:00
|
|
|
MOZ_ASSERT(mFontFace, "only call TakeBuffer once on a given "
|
|
|
|
"FontFaceBufferSource object");
|
2014-10-02 06:32:09 +04:00
|
|
|
mFontFace->TakeBuffer(aBuffer, aLength);
|
2015-05-11 04:24:49 +03:00
|
|
|
mFontFace = nullptr;
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
2015-03-27 13:13:21 +03:00
|
|
|
// -- Utility functions ------------------------------------------------------
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
template<typename T>
|
|
|
|
static void
|
|
|
|
GetDataFrom(const T& aObject, uint8_t*& aBuffer, uint32_t& aLength)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!aBuffer);
|
|
|
|
aObject.ComputeLengthAndData();
|
2015-02-19 07:51:06 +03:00
|
|
|
// We use malloc here rather than a FallibleTArray or fallible
|
|
|
|
// operator new[] since the gfxUserFontEntry will be calling free
|
2014-10-02 06:32:09 +04:00
|
|
|
// on it.
|
2015-02-19 07:51:06 +03:00
|
|
|
aBuffer = (uint8_t*) malloc(aObject.Length());
|
2014-10-02 06:32:09 +04:00
|
|
|
if (!aBuffer) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
memcpy((void*) aBuffer, aObject.Data(), aObject.Length());
|
|
|
|
aLength = aObject.Length();
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
// -- FontFace ---------------------------------------------------------------
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(FontFace)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(FontFace)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoaded)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRule)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFontFaceSet)
|
2015-10-16 09:10:14 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOtherFontFaceSets)
|
2014-10-02 06:32:08 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FontFace)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoaded)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRule)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFontFaceSet)
|
2015-10-16 09:10:14 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOtherFontFaceSets)
|
2014-10-02 06:32:08 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(FontFace)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
2014-10-02 06:32:05 +04: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)
|
|
|
|
|
2015-06-27 04:39:54 +03:00
|
|
|
FontFace::FontFace(nsISupports* aParent, FontFaceSet* aFontFaceSet)
|
2014-10-02 06:32:05 +04:00
|
|
|
: mParent(aParent)
|
2016-10-14 02:01:52 +03:00
|
|
|
, mLoadedRejection(NS_OK)
|
2014-10-02 06:32:06 +04:00
|
|
|
, mStatus(FontFaceLoadStatus::Unloaded)
|
2014-10-02 06:32:09 +04:00
|
|
|
, mSourceType(SourceType(0))
|
|
|
|
, mSourceBuffer(nullptr)
|
|
|
|
, mSourceBufferLength(0)
|
2015-06-27 04:39:54 +03:00
|
|
|
, mFontFaceSet(aFontFaceSet)
|
2017-04-20 10:00:59 +03:00
|
|
|
, mUnicodeRangeDirty(true)
|
2014-10-02 06:32:08 +04:00
|
|
|
, mInFontFaceSet(false)
|
2014-10-02 06:32:05 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
FontFace::~FontFace()
|
|
|
|
{
|
2017-04-30 09:51:29 +03:00
|
|
|
// Assert that we don't drop any FontFace objects during a Servo traversal,
|
|
|
|
// since PostTraversalTask objects can hold raw pointers to FontFaces.
|
|
|
|
MOZ_ASSERT(!ServoStyleSet::IsInServoTraversal());
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
SetUserFontEntry(nullptr);
|
2014-10-02 06:32:08 +04:00
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
if (mSourceBuffer) {
|
2015-04-01 08:29:55 +03:00
|
|
|
free(mSourceBuffer);
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
JSObject*
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
FontFace::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
2014-10-02 06:32:05 +04:00
|
|
|
{
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
return FontFaceBinding::Wrap(aCx, this, aGivenProto);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:06 +04:00
|
|
|
static FontFaceLoadStatus
|
|
|
|
LoadStateToStatus(gfxUserFontEntry::UserFontLoadState aLoadState)
|
|
|
|
{
|
|
|
|
switch (aLoadState) {
|
|
|
|
case gfxUserFontEntry::UserFontLoadState::STATUS_NOT_LOADED:
|
|
|
|
return FontFaceLoadStatus::Unloaded;
|
Bug 1356103 - Part 9: Use a PostTraversalTask to deal with downloadable fonts in gfxUserFontSet. r=bholley,jfkthame
Here we add a new UserFontLoadState value, STATUS_LOAD_PENDING, which
represents the state just after a gfxUserFontEntry's url()-valued source
would being loading, except that we can't start the load due to being
on a Servo style worker thread. In that case, we defer the work of
initiating the load until just after the Servo traversal is finished.
URLs that can normally be loaded synchronously, such as data: URLs
and script-implemented protocols marked as synchronous, must be
handled asynchronously when encountered during Servo traversal, since
various main-thread only work (in FontFaceSet::SyncLoadFontData) must
happen. This is a user visible change from stock Gecko, but should
only happen when font metrics for a data: URL font are requested
due to ch/ex unit resolution when layout hasn't previously requested
the font load. Hopefully nobody relies on synchronous resolution of
ch/ex units with data: URLs.
We unfortunately also can't pick gfxUserFontEntry objects out of the
UserFontCache during Servo traversal, since validating the cache
entry involves doing content policy checking, which is not thread-safe
(due in part to taking strong references to nsIPrincipals).
Platform fonts and ArrayBuffer-backed DOM FontFace objects continue
to be handled synchronously.
The PostTraversalTask does not take a strong reference to the
gfxUserFontEntry object, since it is held on to by the DOM FontFace
object, which itself won't go away before the PostTraversalTask
is run.
MozReview-Commit-ID: J9ODLsusrNV
--HG--
extra : rebase_source : d3e3d1dc187cb252750b57bcecd0b1ed77a15a7c
2017-04-30 09:57:25 +03:00
|
|
|
case gfxUserFontEntry::UserFontLoadState::STATUS_LOAD_PENDING:
|
2014-10-02 06:32:06 +04:00
|
|
|
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-02 06:32:06 +04:00
|
|
|
already_AddRefed<FontFace>
|
2014-10-02 06:32:06 +04:00
|
|
|
FontFace::CreateForRule(nsISupports* aGlobal,
|
2015-06-27 04:39:54 +03:00
|
|
|
FontFaceSet* aFontFaceSet,
|
2014-10-09 11:03:56 +04:00
|
|
|
nsCSSFontFaceRule* aRule)
|
2014-10-02 06:32:06 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<FontFace> obj = new FontFace(aGlobal, aFontFaceSet);
|
2014-10-02 06:32:06 +04:00
|
|
|
obj->mRule = aRule;
|
2014-10-02 06:32:09 +04:00
|
|
|
obj->mSourceType = eSourceType_FontFaceRule;
|
2014-10-02 06:32:08 +04:00
|
|
|
obj->mInFontFaceSet = true;
|
2014-10-02 06:32:06 +04:00
|
|
|
return obj.forget();
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
already_AddRefed<FontFace>
|
|
|
|
FontFace::Constructor(const GlobalObject& aGlobal,
|
|
|
|
const nsAString& aFamily,
|
|
|
|
const StringOrArrayBufferOrArrayBufferView& aSource,
|
|
|
|
const FontFaceDescriptors& aDescriptors,
|
2014-10-02 06:32:06 +04:00
|
|
|
ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
nsISupports* global = aGlobal.GetAsSupports();
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global);
|
2014-10-02 06:32:06 +04:00
|
|
|
nsIDocument* doc = window->GetDoc();
|
|
|
|
if (!doc) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<FontFace> obj = new FontFace(global, doc->Fonts());
|
2014-10-02 06:32:09 +04:00
|
|
|
if (!obj->SetDescriptors(aFamily, aDescriptors)) {
|
|
|
|
return obj.forget();
|
|
|
|
}
|
|
|
|
|
2015-03-27 13:13:21 +03:00
|
|
|
obj->InitializeSource(aSource);
|
2014-10-02 06:32:05 +04:00
|
|
|
return obj.forget();
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
void
|
2015-03-27 13:13:21 +03:00
|
|
|
FontFace::InitializeSource(const StringOrArrayBufferOrArrayBufferView& aSource)
|
2014-10-02 06:32:09 +04:00
|
|
|
{
|
2015-03-27 13:13:21 +03:00
|
|
|
if (aSource.IsString()) {
|
2014-10-02 06:32:09 +04:00
|
|
|
if (!ParseDescriptor(eCSSFontDesc_Src,
|
2015-03-27 13:13:21 +03:00
|
|
|
aSource.GetAsString(),
|
2014-10-02 06:32:09 +04:00
|
|
|
mDescriptors->mSrc)) {
|
2016-10-14 02:01:52 +03:00
|
|
|
Reject(NS_ERROR_DOM_SYNTAX_ERR);
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2015-03-27 13:13:21 +03:00
|
|
|
SetStatus(FontFaceLoadStatus::Error);
|
2014-10-02 06:32:09 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mSourceType = eSourceType_URLs;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-27 13:13:21 +03:00
|
|
|
mSourceType = FontFace::eSourceType_Buffer;
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2015-03-27 13:13:21 +03:00
|
|
|
if (aSource.IsArrayBuffer()) {
|
|
|
|
GetDataFrom(aSource.GetAsArrayBuffer(),
|
|
|
|
mSourceBuffer, mSourceBufferLength);
|
|
|
|
} else {
|
|
|
|
MOZ_ASSERT(aSource.IsArrayBufferView());
|
|
|
|
GetDataFrom(aSource.GetAsArrayBufferView(),
|
|
|
|
mSourceBuffer, mSourceBufferLength);
|
|
|
|
}
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2015-03-27 13:13:21 +03:00
|
|
|
SetStatus(FontFaceLoadStatus::Loading);
|
|
|
|
DoLoad();
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
void
|
|
|
|
FontFace::GetFamily(nsString& aResult)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
|
|
|
|
// Serialize the same way as in nsCSSFontFaceStyleDecl::GetPropertyValue.
|
|
|
|
nsCSSValue value;
|
|
|
|
GetDesc(eCSSFontDesc_Family, value);
|
|
|
|
|
|
|
|
aResult.Truncate();
|
2015-03-24 11:34:32 +03:00
|
|
|
|
|
|
|
if (value.GetUnit() == eCSSUnit_Null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:07 +04:00
|
|
|
nsDependentString family(value.GetStringBufferValue());
|
2014-10-02 06:32:09 +04:00
|
|
|
if (!family.IsEmpty()) {
|
|
|
|
// The string length can be zero when the author passed an invalid
|
|
|
|
// family name or an invalid descriptor to the JS FontFace constructor.
|
|
|
|
nsStyleUtil::AppendEscapedCSSString(family, aResult);
|
|
|
|
}
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetFamily(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
SetDescriptor(eCSSFontDesc_Family, aValue, aRv);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetStyle(nsString& aResult)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
GetDesc(eCSSFontDesc_Style, eCSSProperty_font_style, aResult);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetStyle(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
SetDescriptor(eCSSFontDesc_Style, aValue, aRv);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetWeight(nsString& aResult)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
GetDesc(eCSSFontDesc_Weight, eCSSProperty_font_weight, aResult);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetWeight(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
SetDescriptor(eCSSFontDesc_Weight, aValue, aRv);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetStretch(nsString& aResult)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
GetDesc(eCSSFontDesc_Stretch, eCSSProperty_font_stretch, aResult);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetStretch(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
SetDescriptor(eCSSFontDesc_Stretch, aValue, aRv);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetUnicodeRange(nsString& aResult)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
|
2015-03-17 10:15:42 +03:00
|
|
|
// There is no eCSSProperty_unicode_range for us to pass in to GetDesc
|
|
|
|
// to get a serialized (possibly defaulted) value, but that function
|
|
|
|
// doesn't use the property ID for this descriptor anyway.
|
|
|
|
GetDesc(eCSSFontDesc_UnicodeRange, eCSSProperty_UNKNOWN, aResult);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetUnicodeRange(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
SetDescriptor(eCSSFontDesc_UnicodeRange, aValue, aRv);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetVariant(nsString& aResult)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
|
|
|
|
// XXX Just expose the font-variant descriptor as "normal" until we
|
|
|
|
// support it properly (bug 1055385).
|
|
|
|
aResult.AssignLiteral("normal");
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetVariant(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
|
|
|
|
// XXX Ignore assignments to variant until we support font-variant
|
|
|
|
// descriptors (bug 1055385).
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetFeatureSettings(nsString& aResult)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2015-03-17 10:15:42 +03:00
|
|
|
GetDesc(eCSSFontDesc_FontFeatureSettings, eCSSProperty_font_feature_settings,
|
|
|
|
aResult);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetFeatureSettings(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
SetDescriptor(eCSSFontDesc_FontFeatureSettings, aValue, aRv);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2016-01-07 08:03:05 +03:00
|
|
|
void
|
|
|
|
FontFace::GetDisplay(nsString& aResult)
|
|
|
|
{
|
|
|
|
mFontFaceSet->FlushUserFontSet();
|
|
|
|
GetDesc(eCSSFontDesc_Display, eCSSProperty_UNKNOWN, aResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetDisplay(const nsAString& aValue, ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
mFontFaceSet->FlushUserFontSet();
|
|
|
|
SetDescriptor(eCSSFontDesc_Display, aValue, aRv);
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
FontFaceLoadStatus
|
|
|
|
FontFace::Status()
|
|
|
|
{
|
2014-10-02 06:32:06 +04:00
|
|
|
return mStatus;
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
Promise*
|
2014-10-02 06:32:07 +04:00
|
|
|
FontFace::Load(ErrorResult& aRv)
|
2014-10-02 06:32:05 +04:00
|
|
|
{
|
2017-04-30 09:51:29 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
|
2016-10-14 02:01:52 +03:00
|
|
|
EnsurePromise();
|
|
|
|
|
2014-10-02 06:32:07 +04:00
|
|
|
if (!mLoaded) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
// Calling Load on a FontFace constructed with an ArrayBuffer data source,
|
|
|
|
// or on one that is already loading (or has finished loading), has no
|
|
|
|
// effect.
|
|
|
|
if (mSourceType == eSourceType_Buffer ||
|
|
|
|
mStatus != FontFaceLoadStatus::Unloaded) {
|
2014-10-02 06:32:07 +04:00
|
|
|
return mLoaded;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
// Calling the user font entry's Load method will end up setting our
|
|
|
|
// status to Loading, but the spec requires us to set it to Loading
|
|
|
|
// here.
|
2014-10-02 06:32:07 +04:00
|
|
|
SetStatus(FontFaceLoadStatus::Loading);
|
|
|
|
|
2015-03-27 13:13:21 +03:00
|
|
|
DoLoad();
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2014-10-02 06:32:07 +04:00
|
|
|
return mLoaded;
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2015-06-27 04:41:10 +03:00
|
|
|
gfxUserFontEntry*
|
|
|
|
FontFace::CreateUserFontEntry()
|
2014-10-02 06:32:09 +04:00
|
|
|
{
|
|
|
|
if (!mUserFontEntry) {
|
2014-10-02 06:32:10 +04:00
|
|
|
MOZ_ASSERT(!HasRule(),
|
|
|
|
"Rule backed FontFace objects should already have a user font "
|
2014-10-02 06:32:09 +04:00
|
|
|
"entry by the time Load() can be called on them");
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxUserFontEntry> newEntry =
|
2014-10-02 06:32:09 +04:00
|
|
|
mFontFaceSet->FindOrCreateUserFontEntryFromFontFace(this);
|
2015-06-27 04:41:10 +03:00
|
|
|
if (newEntry) {
|
|
|
|
SetUserFontEntry(newEntry);
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-27 04:41:10 +03:00
|
|
|
return mUserFontEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::DoLoad()
|
|
|
|
{
|
|
|
|
if (!CreateUserFontEntry()) {
|
|
|
|
return;
|
|
|
|
}
|
2014-10-02 06:32:09 +04:00
|
|
|
mUserFontEntry->Load();
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
Promise*
|
2014-10-02 06:32:07 +04:00
|
|
|
FontFace::GetLoaded(ErrorResult& aRv)
|
2014-10-02 06:32:05 +04:00
|
|
|
{
|
2017-04-30 09:51:29 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
2015-06-27 04:39:54 +03:00
|
|
|
mFontFaceSet->FlushUserFontSet();
|
2014-10-02 06:32:07 +04:00
|
|
|
|
2016-10-14 02:01:52 +03:00
|
|
|
EnsurePromise();
|
|
|
|
|
2014-10-02 06:32:07 +04:00
|
|
|
if (!mLoaded) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mLoaded;
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
2014-10-02 06:32:06 +04:00
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetStatus(FontFaceLoadStatus aStatus)
|
|
|
|
{
|
2017-04-30 09:51:29 +03:00
|
|
|
AssertIsMainThreadOrServoFontMetricsLocked();
|
|
|
|
|
2014-10-02 06:32:07 +04:00
|
|
|
if (mStatus == aStatus) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
if (aStatus < mStatus) {
|
|
|
|
// We're being asked to go backwards in status! Normally, this shouldn't
|
|
|
|
// happen. But it can if the FontFace had a user font entry that had
|
|
|
|
// loaded, but then was given a new one by FontFaceSet::InsertRuleFontFace
|
|
|
|
// if we used a local() rule. For now, just ignore the request to
|
|
|
|
// go backwards in status.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:06 +04:00
|
|
|
mStatus = aStatus;
|
2014-10-02 06:32:07 +04:00
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
if (mInFontFaceSet) {
|
|
|
|
mFontFaceSet->OnFontFaceStatusChanged(this);
|
|
|
|
}
|
|
|
|
|
2015-10-16 09:10:14 +03:00
|
|
|
for (FontFaceSet* otherSet : mOtherFontFaceSets) {
|
|
|
|
otherSet->OnFontFaceStatusChanged(this);
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:07 +04:00
|
|
|
if (mStatus == FontFaceLoadStatus::Loaded) {
|
2016-10-14 02:01:52 +03:00
|
|
|
if (mLoaded) {
|
2017-04-30 09:51:29 +03:00
|
|
|
DoResolve();
|
2016-10-14 02:01:52 +03:00
|
|
|
}
|
2014-10-02 06:32:07 +04:00
|
|
|
} else if (mStatus == FontFaceLoadStatus::Error) {
|
2014-10-02 06:32:09 +04:00
|
|
|
if (mSourceType == eSourceType_Buffer) {
|
2016-10-14 02:01:52 +03:00
|
|
|
Reject(NS_ERROR_DOM_SYNTAX_ERR);
|
2014-10-02 06:32:09 +04:00
|
|
|
} else {
|
2016-10-14 02:01:52 +03:00
|
|
|
Reject(NS_ERROR_DOM_NETWORK_ERR);
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
2014-10-02 06:32:07 +04:00
|
|
|
}
|
2014-10-02 06:32:06 +04:00
|
|
|
}
|
|
|
|
|
2017-04-30 09:51:29 +03:00
|
|
|
void
|
|
|
|
FontFace::DoResolve()
|
|
|
|
{
|
|
|
|
AssertIsMainThreadOrServoFontMetricsLocked();
|
|
|
|
|
|
|
|
if (ServoStyleSet* ss = ServoStyleSet::Current()) {
|
|
|
|
// See comments in Gecko_GetFontMetrics.
|
|
|
|
ss->AppendTask(PostTraversalTask::ResolveFontFaceLoadedPromise(this));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mLoaded->MaybeResolve(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::DoReject(nsresult aResult)
|
|
|
|
{
|
|
|
|
AssertIsMainThreadOrServoFontMetricsLocked();
|
|
|
|
|
|
|
|
if (ServoStyleSet* ss = ServoStyleSet::Current()) {
|
|
|
|
// See comments in Gecko_GetFontMetrics.
|
|
|
|
ss->AppendTask(PostTraversalTask::RejectFontFaceLoadedPromise(this, aResult));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mLoaded->MaybeReject(aResult);
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:07 +04:00
|
|
|
bool
|
|
|
|
FontFace::ParseDescriptor(nsCSSFontDesc aDescID,
|
|
|
|
const nsAString& aString,
|
|
|
|
nsCSSValue& aResult)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mParent);
|
|
|
|
nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull();
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mParent);
|
2015-05-05 12:55:28 +03:00
|
|
|
nsCOMPtr<nsIURI> docURI = window->GetDocumentURI();
|
2014-10-02 06:32:07 +04:00
|
|
|
nsCOMPtr<nsIURI> base = window->GetDocBaseURI();
|
|
|
|
|
2017-12-05 08:48:23 +03:00
|
|
|
if (mFontFaceSet->Document()->IsStyledByServo()) {
|
|
|
|
RefPtr<URLExtraData> url = new URLExtraData(base, docURI, principal);
|
|
|
|
return Servo_ParseFontDescriptor(aDescID, &aString, url, &aResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCSSParser parser;
|
2014-10-02 06:32:07 +04:00
|
|
|
if (!parser.ParseFontFaceDescriptor(aDescID, aString,
|
2015-05-05 12:55:28 +03:00
|
|
|
docURI, // aSheetURL
|
2014-10-02 06:32:07 +04:00
|
|
|
base,
|
|
|
|
principal,
|
|
|
|
aResult)) {
|
|
|
|
aResult.Reset();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::SetDescriptor(nsCSSFontDesc aFontDesc,
|
|
|
|
const nsAString& aValue,
|
|
|
|
ErrorResult& aRv)
|
|
|
|
{
|
2014-10-02 06:32:10 +04:00
|
|
|
NS_ASSERTION(!HasRule(),
|
|
|
|
"we don't handle rule backed FontFace objects yet");
|
|
|
|
if (HasRule()) {
|
2014-10-02 06:32:07 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCSSValue parsedValue;
|
|
|
|
if (!ParseDescriptor(aFontDesc, aValue, parsedValue)) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mDescriptors->Get(aFontDesc) = parsedValue;
|
|
|
|
|
2017-04-20 10:00:59 +03:00
|
|
|
if (aFontDesc == eCSSFontDesc_UnicodeRange) {
|
|
|
|
mUnicodeRangeDirty = true;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:07 +04:00
|
|
|
// XXX Setting descriptors doesn't actually have any effect on FontFace
|
|
|
|
// objects that have started loading or have already been loaded.
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
bool
|
|
|
|
FontFace::SetDescriptors(const nsAString& aFamily,
|
|
|
|
const FontFaceDescriptors& aDescriptors)
|
|
|
|
{
|
2014-10-02 06:32:10 +04:00
|
|
|
MOZ_ASSERT(!HasRule());
|
2014-10-02 06:32:09 +04:00
|
|
|
MOZ_ASSERT(!mDescriptors);
|
|
|
|
|
|
|
|
mDescriptors = new CSSFontFaceDescriptors;
|
|
|
|
|
|
|
|
// Parse all of the mDescriptors in aInitializer, which are the values
|
|
|
|
// we got from the JS constructor.
|
|
|
|
if (!ParseDescriptor(eCSSFontDesc_Family,
|
|
|
|
aFamily,
|
|
|
|
mDescriptors->mFamily) ||
|
|
|
|
*mDescriptors->mFamily.GetStringBufferValue() == 0 ||
|
|
|
|
!ParseDescriptor(eCSSFontDesc_Style,
|
|
|
|
aDescriptors.mStyle,
|
|
|
|
mDescriptors->mStyle) ||
|
|
|
|
!ParseDescriptor(eCSSFontDesc_Weight,
|
|
|
|
aDescriptors.mWeight,
|
|
|
|
mDescriptors->mWeight) ||
|
|
|
|
!ParseDescriptor(eCSSFontDesc_Stretch,
|
|
|
|
aDescriptors.mStretch,
|
|
|
|
mDescriptors->mStretch) ||
|
|
|
|
!ParseDescriptor(eCSSFontDesc_UnicodeRange,
|
|
|
|
aDescriptors.mUnicodeRange,
|
|
|
|
mDescriptors->mUnicodeRange) ||
|
|
|
|
!ParseDescriptor(eCSSFontDesc_FontFeatureSettings,
|
|
|
|
aDescriptors.mFeatureSettings,
|
2016-01-07 08:03:05 +03:00
|
|
|
mDescriptors->mFontFeatureSettings) ||
|
|
|
|
!ParseDescriptor(eCSSFontDesc_Display,
|
|
|
|
aDescriptors.mDisplay,
|
|
|
|
mDescriptors->mDisplay)) {
|
2014-10-02 06:32:09 +04:00
|
|
|
// XXX Handle font-variant once we support it (bug 1055385).
|
|
|
|
|
|
|
|
// If any of the descriptors failed to parse, none of them should be set
|
|
|
|
// on the FontFace.
|
|
|
|
mDescriptors = new CSSFontFaceDescriptors;
|
|
|
|
|
2016-10-14 02:01:52 +03:00
|
|
|
Reject(NS_ERROR_DOM_SYNTAX_ERR);
|
2014-10-02 06:32:09 +04:00
|
|
|
|
|
|
|
SetStatus(FontFaceLoadStatus::Error);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:07 +04:00
|
|
|
void
|
|
|
|
FontFace::GetDesc(nsCSSFontDesc aDescID, nsCSSValue& aResult) const
|
|
|
|
{
|
2014-10-02 06:32:10 +04:00
|
|
|
if (HasRule()) {
|
2014-10-02 06:32:09 +04:00
|
|
|
MOZ_ASSERT(mRule);
|
2014-10-02 06:32:07 +04:00
|
|
|
MOZ_ASSERT(!mDescriptors);
|
|
|
|
mRule->GetDesc(aDescID, aResult);
|
|
|
|
} else {
|
|
|
|
aResult = mDescriptors->Get(aDescID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::GetDesc(nsCSSFontDesc aDescID,
|
2016-08-17 04:37:48 +03:00
|
|
|
nsCSSPropertyID aPropID,
|
2014-10-02 06:32:07 +04:00
|
|
|
nsString& aResult) const
|
|
|
|
{
|
2015-03-17 10:15:42 +03:00
|
|
|
MOZ_ASSERT(aDescID == eCSSFontDesc_UnicodeRange ||
|
2016-01-07 08:03:05 +03:00
|
|
|
aDescID == eCSSFontDesc_Display ||
|
2015-03-17 10:15:42 +03:00
|
|
|
aPropID != eCSSProperty_UNKNOWN,
|
|
|
|
"only pass eCSSProperty_UNKNOWN for eCSSFontDesc_UnicodeRange");
|
|
|
|
|
2014-10-02 06:32:07 +04:00
|
|
|
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");
|
2016-01-07 08:03:05 +03:00
|
|
|
} else if (aDescID == eCSSFontDesc_Display) {
|
|
|
|
aResult.AssignLiteral("auto");
|
2014-10-02 06:32:07 +04:00
|
|
|
} else if (aDescID != eCSSFontDesc_Family &&
|
|
|
|
aDescID != eCSSFontDesc_Src) {
|
|
|
|
aResult.AssignLiteral("normal");
|
|
|
|
}
|
2015-03-17 10:15:42 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aDescID == eCSSFontDesc_UnicodeRange) {
|
|
|
|
// Since there's no unicode-range property, we can't use
|
|
|
|
// nsCSSValue::AppendToString to serialize this descriptor.
|
|
|
|
nsStyleUtil::AppendUnicodeRange(value, aResult);
|
2016-01-07 08:03:05 +03:00
|
|
|
} else if (aDescID == eCSSFontDesc_Display) {
|
|
|
|
AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(value.GetIntValue(),
|
|
|
|
nsCSSProps::kFontDisplayKTable),
|
|
|
|
aResult);
|
2014-10-02 06:32:07 +04:00
|
|
|
} else {
|
2017-07-22 03:26:35 +03:00
|
|
|
value.AppendToString(aPropID, aResult);
|
2014-10-02 06:32:07 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
void
|
|
|
|
FontFace::SetUserFontEntry(gfxUserFontEntry* aEntry)
|
|
|
|
{
|
|
|
|
if (mUserFontEntry) {
|
|
|
|
mUserFontEntry->mFontFaces.RemoveElement(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
mUserFontEntry = static_cast<Entry*>(aEntry);
|
|
|
|
if (mUserFontEntry) {
|
|
|
|
mUserFontEntry->mFontFaces.AppendElement(this);
|
|
|
|
|
|
|
|
// Our newly assigned user font entry might be in the process of or
|
|
|
|
// finished loading, so set our status accordingly. But only do so
|
|
|
|
// if we're not going "backwards" in status, which could otherwise
|
|
|
|
// happen in this case:
|
|
|
|
//
|
|
|
|
// new FontFace("ABC", "url(x)").load();
|
|
|
|
//
|
|
|
|
// where the SetUserFontEntry call (from the after-initialization
|
2014-10-02 06:32:09 +04:00
|
|
|
// DoLoad call) comes after the author's call to load(), which set mStatus
|
|
|
|
// to Loading.
|
2014-10-02 06:32:08 +04:00
|
|
|
FontFaceLoadStatus newStatus =
|
|
|
|
LoadStateToStatus(mUserFontEntry->LoadState());
|
|
|
|
if (newStatus > mStatus) {
|
|
|
|
SetStatus(newStatus);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
bool
|
|
|
|
FontFace::GetFamilyName(nsString& aResult)
|
|
|
|
{
|
|
|
|
nsCSSValue value;
|
|
|
|
GetDesc(eCSSFontDesc_Family, value);
|
|
|
|
|
|
|
|
if (value.GetUnit() == eCSSUnit_String) {
|
|
|
|
nsString familyname;
|
|
|
|
value.GetStringValue(familyname);
|
|
|
|
aResult.Append(familyname);
|
|
|
|
}
|
|
|
|
|
|
|
|
return !aResult.IsEmpty();
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
void
|
|
|
|
FontFace::DisconnectFromRule()
|
|
|
|
{
|
2014-10-02 06:32:10 +04:00
|
|
|
MOZ_ASSERT(HasRule());
|
2014-10-02 06:32:08 +04:00
|
|
|
|
|
|
|
// Make a copy of the descriptors.
|
|
|
|
mDescriptors = new CSSFontFaceDescriptors;
|
|
|
|
mRule->GetDescriptors(*mDescriptors);
|
|
|
|
mRule = nullptr;
|
|
|
|
mInFontFaceSet = false;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
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()
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<FontFaceBufferSource> bufferSource = new FontFaceBufferSource(this);
|
2014-10-02 06:32:09 +04:00
|
|
|
return bufferSource.forget();
|
|
|
|
}
|
|
|
|
|
2015-10-16 09:10:14 +03:00
|
|
|
bool
|
|
|
|
FontFace::IsInFontFaceSet(FontFaceSet* aFontFaceSet) const
|
|
|
|
{
|
|
|
|
if (mFontFaceSet == aFontFaceSet) {
|
|
|
|
return mInFontFaceSet;
|
|
|
|
}
|
|
|
|
return mOtherFontFaceSets.Contains(aFontFaceSet);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::AddFontFaceSet(FontFaceSet* aFontFaceSet)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!IsInFontFaceSet(aFontFaceSet));
|
|
|
|
|
|
|
|
if (mFontFaceSet == aFontFaceSet) {
|
|
|
|
mInFontFaceSet = true;
|
|
|
|
} else {
|
|
|
|
mOtherFontFaceSets.AppendElement(aFontFaceSet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::RemoveFontFaceSet(FontFaceSet* aFontFaceSet)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(IsInFontFaceSet(aFontFaceSet));
|
|
|
|
|
|
|
|
if (mFontFaceSet == aFontFaceSet) {
|
|
|
|
mInFontFaceSet = false;
|
|
|
|
} else {
|
|
|
|
mOtherFontFaceSets.RemoveElement(aFontFaceSet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-14 02:01:52 +03:00
|
|
|
void
|
|
|
|
FontFace::Reject(nsresult aResult)
|
|
|
|
{
|
2017-04-30 09:51:29 +03:00
|
|
|
AssertIsMainThreadOrServoFontMetricsLocked();
|
|
|
|
|
2016-10-14 02:01:52 +03:00
|
|
|
if (mLoaded) {
|
2017-04-30 09:51:29 +03:00
|
|
|
DoReject(aResult);
|
2016-10-14 02:01:52 +03:00
|
|
|
} else if (mLoadedRejection == NS_OK) {
|
|
|
|
mLoadedRejection = aResult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFace::EnsurePromise()
|
|
|
|
{
|
2017-04-30 09:51:29 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
2016-10-14 02:01:52 +03:00
|
|
|
if (mLoaded) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mParent);
|
|
|
|
|
|
|
|
// If the pref is not set, don't create the Promise (which the page wouldn't
|
|
|
|
// be able to get to anyway) as it causes the window.FontFace constructor
|
|
|
|
// to be created.
|
|
|
|
if (global && FontFaceSet::PrefEnabled()) {
|
|
|
|
ErrorResult rv;
|
|
|
|
mLoaded = Promise::Create(global, rv);
|
|
|
|
|
|
|
|
if (mStatus == FontFaceLoadStatus::Loaded) {
|
|
|
|
mLoaded->MaybeResolve(this);
|
|
|
|
} else if (mLoadedRejection != NS_OK) {
|
|
|
|
mLoaded->MaybeReject(mLoadedRejection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-20 10:00:59 +03:00
|
|
|
gfxCharacterMap*
|
|
|
|
FontFace::GetUnicodeRangeAsCharacterMap()
|
|
|
|
{
|
|
|
|
if (!mUnicodeRangeDirty) {
|
|
|
|
return mUnicodeRange;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCSSValue val;
|
|
|
|
GetDesc(eCSSFontDesc_UnicodeRange, val);
|
|
|
|
|
|
|
|
if (val.GetUnit() == eCSSUnit_Array) {
|
|
|
|
mUnicodeRange = new gfxCharacterMap();
|
|
|
|
const nsCSSValue::Array& sources = *val.GetArrayValue();
|
|
|
|
MOZ_ASSERT(sources.Count() % 2 == 0,
|
|
|
|
"odd number of entries in a unicode-range: array");
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < sources.Count(); i += 2) {
|
|
|
|
uint32_t min = sources[i].GetIntValue();
|
|
|
|
uint32_t max = sources[i+1].GetIntValue();
|
|
|
|
mUnicodeRange->SetRange(min, max);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mUnicodeRange = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
mUnicodeRangeDirty = false;
|
|
|
|
return mUnicodeRange;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:06 +04:00
|
|
|
// -- FontFace::Entry --------------------------------------------------------
|
|
|
|
|
|
|
|
/* virtual */ void
|
|
|
|
FontFace::Entry::SetLoadState(UserFontLoadState aLoadState)
|
|
|
|
{
|
|
|
|
gfxUserFontEntry::SetLoadState(aLoadState);
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
for (size_t i = 0; i < mFontFaces.Length(); i++) {
|
|
|
|
mFontFaces[i]->SetStatus(LoadStateToStatus(aLoadState));
|
2014-10-02 06:32:06 +04:00
|
|
|
}
|
|
|
|
}
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2015-10-16 09:10:14 +03:00
|
|
|
/* virtual */ void
|
|
|
|
FontFace::Entry::GetUserFontSets(nsTArray<gfxUserFontSet*>& aResult)
|
|
|
|
{
|
|
|
|
aResult.Clear();
|
|
|
|
|
|
|
|
for (FontFace* f : mFontFaces) {
|
|
|
|
if (f->mInFontFaceSet) {
|
|
|
|
aResult.AppendElement(f->mFontFaceSet->GetUserFontSet());
|
|
|
|
}
|
|
|
|
for (FontFaceSet* s : f->mOtherFontFaceSets) {
|
|
|
|
aResult.AppendElement(s->GetUserFontSet());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove duplicates.
|
|
|
|
aResult.Sort();
|
|
|
|
auto it = std::unique(aResult.begin(), aResult.end());
|
|
|
|
aResult.TruncateLength(it - aResult.begin());
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|