1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/FontFace.h"
10 #include "gfxFontUtils.h"
11 #include "mozilla/dom/CSSFontFaceRule.h"
12 #include "mozilla/dom/FontFaceBinding.h"
13 #include "mozilla/dom/FontFaceImpl.h"
14 #include "mozilla/dom/FontFaceSet.h"
15 #include "mozilla/dom/Promise.h"
16 #include "mozilla/dom/TypedArray.h"
17 #include "mozilla/dom/UnionTypes.h"
18 #include "mozilla/CycleCollectedJSContext.h"
19 #include "mozilla/ServoBindings.h"
20 #include "mozilla/ServoCSSParser.h"
21 #include "mozilla/ServoStyleSet.h"
22 #include "mozilla/ServoUtils.h"
23 #include "mozilla/StaticPrefs_layout.h"
24 #include "nsStyleUtil.h"
29 // -- Utility functions ------------------------------------------------------
32 static void GetDataFrom(const T
& aObject
, uint8_t*& aBuffer
,
35 // We need to use malloc here because the gfxUserFontEntry will be calling
36 // free on it, so the Vector's default AllocPolicy (MallocAllocPolicy) is
38 Maybe
<Vector
<uint8_t>> buffer
=
39 aObject
.template CreateFromData
<Vector
<uint8_t>>();
40 if (buffer
.isNothing()) {
43 aLength
= buffer
->length();
44 aBuffer
= buffer
->extractOrCopyRawBuffer();
47 // -- FontFace ---------------------------------------------------------------
49 NS_IMPL_CYCLE_COLLECTION_CLASS(FontFace
)
51 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(FontFace
)
52 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoaded
)
53 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
55 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FontFace
)
56 NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoaded
)
58 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
59 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
61 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(FontFace
)
62 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
63 NS_IMPL_CYCLE_COLLECTION_TRACE_END
65 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FontFace
)
66 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
67 NS_INTERFACE_MAP_ENTRY(nsISupports
)
70 NS_IMPL_CYCLE_COLLECTING_ADDREF(FontFace
)
71 NS_IMPL_CYCLE_COLLECTING_RELEASE(FontFace
)
73 FontFace::FontFace(nsIGlobalObject
* aParent
) : mLoadedRejection(NS_OK
) {
77 FontFace::~FontFace() {
78 // Assert that we don't drop any FontFace objects during a Servo traversal,
79 // since PostTraversalTask objects can hold raw pointers to FontFaces.
80 MOZ_ASSERT(!gfxFontUtils::IsInServoTraversal());
84 void FontFace::Destroy() { mImpl
->Destroy(); }
86 void FontFace::DisconnectFromOwner() {
87 GlobalTeardownObserver::DisconnectFromOwner();
89 mImpl
->StopKeepingOwnerAlive();
93 JSObject
* FontFace::WrapObject(JSContext
* aCx
,
94 JS::Handle
<JSObject
*> aGivenProto
) {
95 return FontFace_Binding::Wrap(aCx
, this, aGivenProto
);
98 already_AddRefed
<FontFace
> FontFace::CreateForRule(
99 nsIGlobalObject
* aGlobal
, FontFaceSet
* aFontFaceSet
,
100 StyleLockedFontFaceRule
* aRule
) {
101 FontFaceSetImpl
* setImpl
= aFontFaceSet
->GetImpl();
104 RefPtr
<FontFace
> obj
= new FontFace(aGlobal
);
105 obj
->mImpl
= FontFaceImpl::CreateForRule(obj
, setImpl
, aRule
);
109 already_AddRefed
<FontFace
> FontFace::Constructor(
110 const GlobalObject
& aGlobal
, const nsACString
& aFamily
,
111 const UTF8StringOrArrayBufferOrArrayBufferView
& aSource
,
112 const FontFaceDescriptors
& aDescriptors
, ErrorResult
& aRv
) {
113 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
115 FontFaceSet
* set
= global
->GetFonts();
116 if (NS_WARN_IF(!set
)) {
117 aRv
.Throw(NS_ERROR_FAILURE
);
121 FontFaceSetImpl
* setImpl
= set
->GetImpl();
122 if (NS_WARN_IF(!setImpl
)) {
123 aRv
.Throw(NS_ERROR_FAILURE
);
127 RefPtr
<FontFace
> obj
= new FontFace(global
);
128 obj
->mImpl
= new FontFaceImpl(obj
, setImpl
);
129 if (!obj
->mImpl
->SetDescriptors(aFamily
, aDescriptors
)) {
133 if (aSource
.IsUTF8String()) {
134 obj
->mImpl
->InitializeSourceURL(aSource
.GetAsUTF8String());
136 uint8_t* buffer
= nullptr;
138 if (aSource
.IsArrayBuffer()) {
139 GetDataFrom(aSource
.GetAsArrayBuffer(), buffer
, length
);
140 } else if (aSource
.IsArrayBufferView()) {
141 GetDataFrom(aSource
.GetAsArrayBufferView(), buffer
, length
);
143 MOZ_ASSERT_UNREACHABLE("Unhandled source type!");
147 obj
->mImpl
->InitializeSourceBuffer(buffer
, length
);
153 void FontFace::GetFamily(nsACString
& aResult
) { mImpl
->GetFamily(aResult
); }
155 void FontFace::SetFamily(const nsACString
& aValue
, ErrorResult
& aRv
) {
156 mImpl
->SetFamily(aValue
, aRv
);
159 void FontFace::GetStyle(nsACString
& aResult
) { mImpl
->GetStyle(aResult
); }
161 void FontFace::SetStyle(const nsACString
& aValue
, ErrorResult
& aRv
) {
162 mImpl
->SetStyle(aValue
, aRv
);
165 void FontFace::GetWeight(nsACString
& aResult
) { mImpl
->GetWeight(aResult
); }
167 void FontFace::SetWeight(const nsACString
& aValue
, ErrorResult
& aRv
) {
168 mImpl
->SetWeight(aValue
, aRv
);
171 void FontFace::GetStretch(nsACString
& aResult
) { mImpl
->GetStretch(aResult
); }
173 void FontFace::SetStretch(const nsACString
& aValue
, ErrorResult
& aRv
) {
174 mImpl
->SetStretch(aValue
, aRv
);
177 void FontFace::GetUnicodeRange(nsACString
& aResult
) {
178 mImpl
->GetUnicodeRange(aResult
);
181 void FontFace::SetUnicodeRange(const nsACString
& aValue
, ErrorResult
& aRv
) {
182 mImpl
->SetUnicodeRange(aValue
, aRv
);
185 void FontFace::GetVariant(nsACString
& aResult
) { mImpl
->GetVariant(aResult
); }
187 void FontFace::SetVariant(const nsACString
& aValue
, ErrorResult
& aRv
) {
188 mImpl
->SetVariant(aValue
, aRv
);
191 void FontFace::GetFeatureSettings(nsACString
& aResult
) {
192 mImpl
->GetFeatureSettings(aResult
);
195 void FontFace::SetFeatureSettings(const nsACString
& aValue
, ErrorResult
& aRv
) {
196 mImpl
->SetFeatureSettings(aValue
, aRv
);
199 void FontFace::GetVariationSettings(nsACString
& aResult
) {
200 mImpl
->GetVariationSettings(aResult
);
203 void FontFace::SetVariationSettings(const nsACString
& aValue
,
205 mImpl
->SetVariationSettings(aValue
, aRv
);
208 void FontFace::GetDisplay(nsACString
& aResult
) { mImpl
->GetDisplay(aResult
); }
210 void FontFace::SetDisplay(const nsACString
& aValue
, ErrorResult
& aRv
) {
211 mImpl
->SetDisplay(aValue
, aRv
);
214 void FontFace::GetAscentOverride(nsACString
& aResult
) {
215 mImpl
->GetAscentOverride(aResult
);
218 void FontFace::SetAscentOverride(const nsACString
& aValue
, ErrorResult
& aRv
) {
219 mImpl
->SetAscentOverride(aValue
, aRv
);
222 void FontFace::GetDescentOverride(nsACString
& aResult
) {
223 mImpl
->GetDescentOverride(aResult
);
226 void FontFace::SetDescentOverride(const nsACString
& aValue
, ErrorResult
& aRv
) {
227 mImpl
->SetDescentOverride(aValue
, aRv
);
230 void FontFace::GetLineGapOverride(nsACString
& aResult
) {
231 mImpl
->GetLineGapOverride(aResult
);
234 void FontFace::SetLineGapOverride(const nsACString
& aValue
, ErrorResult
& aRv
) {
235 mImpl
->SetLineGapOverride(aValue
, aRv
);
238 void FontFace::GetSizeAdjust(nsACString
& aResult
) {
239 mImpl
->GetSizeAdjust(aResult
);
242 void FontFace::SetSizeAdjust(const nsACString
& aValue
, ErrorResult
& aRv
) {
243 mImpl
->SetSizeAdjust(aValue
, aRv
);
246 FontFaceLoadStatus
FontFace::Status() { return mImpl
->Status(); }
248 Promise
* FontFace::Load(ErrorResult
& aRv
) {
252 aRv
.Throw(NS_ERROR_FAILURE
);
260 Promise
* FontFace::GetLoaded(ErrorResult
& aRv
) {
264 aRv
.Throw(NS_ERROR_FAILURE
);
271 void FontFace::MaybeResolve() {
272 gfxFontUtils::AssertSafeThreadOrServoFontMetricsLocked();
278 if (ServoStyleSet
* ss
= gfxFontUtils::CurrentServoStyleSet()) {
279 // See comments in Gecko_GetFontMetrics.
280 ss
->AppendTask(PostTraversalTask::ResolveFontFaceLoadedPromise(this));
284 mLoaded
->MaybeResolve(this);
287 void FontFace::MaybeReject(nsresult aResult
) {
288 gfxFontUtils::AssertSafeThreadOrServoFontMetricsLocked();
290 if (ServoStyleSet
* ss
= gfxFontUtils::CurrentServoStyleSet()) {
291 // See comments in Gecko_GetFontMetrics.
293 PostTraversalTask::RejectFontFaceLoadedPromise(this, aResult
));
298 mLoaded
->MaybeReject(aResult
);
299 } else if (mLoadedRejection
== NS_OK
) {
300 mLoadedRejection
= aResult
;
304 void FontFace::EnsurePromise() {
305 if (mLoaded
|| !mImpl
|| !GetOwnerGlobal()) {
310 mLoaded
= Promise::Create(GetOwnerGlobal(), rv
);
312 if (mImpl
->Status() == FontFaceLoadStatus::Loaded
) {
313 mLoaded
->MaybeResolve(this);
314 } else if (mLoadedRejection
!= NS_OK
) {
315 mLoaded
->MaybeReject(mLoadedRejection
);
320 } // namespace mozilla