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(mParent
)
53 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoaded
)
54 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
56 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FontFace
)
57 NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent
)
58 NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoaded
)
60 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
61 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
63 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(FontFace
)
64 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
65 NS_IMPL_CYCLE_COLLECTION_TRACE_END
67 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FontFace
)
68 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
69 NS_INTERFACE_MAP_ENTRY(nsISupports
)
72 NS_IMPL_CYCLE_COLLECTING_ADDREF(FontFace
)
73 NS_IMPL_CYCLE_COLLECTING_RELEASE(FontFace
)
75 FontFace::FontFace(nsIGlobalObject
* aParent
)
76 : mParent(aParent
), mLoadedRejection(NS_OK
) {}
78 FontFace::~FontFace() {
79 // Assert that we don't drop any FontFace objects during a Servo traversal,
80 // since PostTraversalTask objects can hold raw pointers to FontFaces.
81 MOZ_ASSERT(!gfxFontUtils::IsInServoTraversal());
85 void FontFace::Destroy() { mImpl
->Destroy(); }
87 JSObject
* FontFace::WrapObject(JSContext
* aCx
,
88 JS::Handle
<JSObject
*> aGivenProto
) {
89 return FontFace_Binding::Wrap(aCx
, this, aGivenProto
);
92 already_AddRefed
<FontFace
> FontFace::CreateForRule(
93 nsIGlobalObject
* aGlobal
, FontFaceSet
* aFontFaceSet
,
94 StyleLockedFontFaceRule
* aRule
) {
95 FontFaceSetImpl
* setImpl
= aFontFaceSet
->GetImpl();
98 RefPtr
<FontFace
> obj
= new FontFace(aGlobal
);
99 obj
->mImpl
= FontFaceImpl::CreateForRule(obj
, setImpl
, aRule
);
103 already_AddRefed
<FontFace
> FontFace::Constructor(
104 const GlobalObject
& aGlobal
, const nsACString
& aFamily
,
105 const UTF8StringOrArrayBufferOrArrayBufferView
& aSource
,
106 const FontFaceDescriptors
& aDescriptors
, ErrorResult
& aRv
) {
107 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
109 FontFaceSet
* set
= global
->GetFonts();
110 if (NS_WARN_IF(!set
)) {
111 aRv
.Throw(NS_ERROR_FAILURE
);
115 FontFaceSetImpl
* setImpl
= set
->GetImpl();
116 if (NS_WARN_IF(!setImpl
)) {
117 aRv
.Throw(NS_ERROR_FAILURE
);
121 RefPtr
<FontFace
> obj
= new FontFace(global
);
122 obj
->mImpl
= new FontFaceImpl(obj
, setImpl
);
123 if (!obj
->mImpl
->SetDescriptors(aFamily
, aDescriptors
)) {
127 if (aSource
.IsUTF8String()) {
128 obj
->mImpl
->InitializeSourceURL(aSource
.GetAsUTF8String());
130 uint8_t* buffer
= nullptr;
132 if (aSource
.IsArrayBuffer()) {
133 GetDataFrom(aSource
.GetAsArrayBuffer(), buffer
, length
);
134 } else if (aSource
.IsArrayBufferView()) {
135 GetDataFrom(aSource
.GetAsArrayBufferView(), buffer
, length
);
137 MOZ_ASSERT_UNREACHABLE("Unhandled source type!");
141 obj
->mImpl
->InitializeSourceBuffer(buffer
, length
);
147 void FontFace::GetFamily(nsACString
& aResult
) { mImpl
->GetFamily(aResult
); }
149 void FontFace::SetFamily(const nsACString
& aValue
, ErrorResult
& aRv
) {
150 mImpl
->SetFamily(aValue
, aRv
);
153 void FontFace::GetStyle(nsACString
& aResult
) { mImpl
->GetStyle(aResult
); }
155 void FontFace::SetStyle(const nsACString
& aValue
, ErrorResult
& aRv
) {
156 mImpl
->SetStyle(aValue
, aRv
);
159 void FontFace::GetWeight(nsACString
& aResult
) { mImpl
->GetWeight(aResult
); }
161 void FontFace::SetWeight(const nsACString
& aValue
, ErrorResult
& aRv
) {
162 mImpl
->SetWeight(aValue
, aRv
);
165 void FontFace::GetStretch(nsACString
& aResult
) { mImpl
->GetStretch(aResult
); }
167 void FontFace::SetStretch(const nsACString
& aValue
, ErrorResult
& aRv
) {
168 mImpl
->SetStretch(aValue
, aRv
);
171 void FontFace::GetUnicodeRange(nsACString
& aResult
) {
172 mImpl
->GetUnicodeRange(aResult
);
175 void FontFace::SetUnicodeRange(const nsACString
& aValue
, ErrorResult
& aRv
) {
176 mImpl
->SetUnicodeRange(aValue
, aRv
);
179 void FontFace::GetVariant(nsACString
& aResult
) { mImpl
->GetVariant(aResult
); }
181 void FontFace::SetVariant(const nsACString
& aValue
, ErrorResult
& aRv
) {
182 mImpl
->SetVariant(aValue
, aRv
);
185 void FontFace::GetFeatureSettings(nsACString
& aResult
) {
186 mImpl
->GetFeatureSettings(aResult
);
189 void FontFace::SetFeatureSettings(const nsACString
& aValue
, ErrorResult
& aRv
) {
190 mImpl
->SetFeatureSettings(aValue
, aRv
);
193 void FontFace::GetVariationSettings(nsACString
& aResult
) {
194 mImpl
->GetVariationSettings(aResult
);
197 void FontFace::SetVariationSettings(const nsACString
& aValue
,
199 mImpl
->SetVariationSettings(aValue
, aRv
);
202 void FontFace::GetDisplay(nsACString
& aResult
) { mImpl
->GetDisplay(aResult
); }
204 void FontFace::SetDisplay(const nsACString
& aValue
, ErrorResult
& aRv
) {
205 mImpl
->SetDisplay(aValue
, aRv
);
208 void FontFace::GetAscentOverride(nsACString
& aResult
) {
209 mImpl
->GetAscentOverride(aResult
);
212 void FontFace::SetAscentOverride(const nsACString
& aValue
, ErrorResult
& aRv
) {
213 mImpl
->SetAscentOverride(aValue
, aRv
);
216 void FontFace::GetDescentOverride(nsACString
& aResult
) {
217 mImpl
->GetDescentOverride(aResult
);
220 void FontFace::SetDescentOverride(const nsACString
& aValue
, ErrorResult
& aRv
) {
221 mImpl
->SetDescentOverride(aValue
, aRv
);
224 void FontFace::GetLineGapOverride(nsACString
& aResult
) {
225 mImpl
->GetLineGapOverride(aResult
);
228 void FontFace::SetLineGapOverride(const nsACString
& aValue
, ErrorResult
& aRv
) {
229 mImpl
->SetLineGapOverride(aValue
, aRv
);
232 void FontFace::GetSizeAdjust(nsACString
& aResult
) {
233 mImpl
->GetSizeAdjust(aResult
);
236 void FontFace::SetSizeAdjust(const nsACString
& aValue
, ErrorResult
& aRv
) {
237 mImpl
->SetSizeAdjust(aValue
, aRv
);
240 FontFaceLoadStatus
FontFace::Status() { return mImpl
->Status(); }
242 Promise
* FontFace::Load(ErrorResult
& aRv
) {
246 aRv
.Throw(NS_ERROR_FAILURE
);
254 Promise
* FontFace::GetLoaded(ErrorResult
& aRv
) {
258 aRv
.Throw(NS_ERROR_FAILURE
);
265 void FontFace::MaybeResolve() {
266 gfxFontUtils::AssertSafeThreadOrServoFontMetricsLocked();
272 if (ServoStyleSet
* ss
= gfxFontUtils::CurrentServoStyleSet()) {
273 // See comments in Gecko_GetFontMetrics.
274 ss
->AppendTask(PostTraversalTask::ResolveFontFaceLoadedPromise(this));
278 mLoaded
->MaybeResolve(this);
281 void FontFace::MaybeReject(nsresult aResult
) {
282 gfxFontUtils::AssertSafeThreadOrServoFontMetricsLocked();
284 if (ServoStyleSet
* ss
= gfxFontUtils::CurrentServoStyleSet()) {
285 // See comments in Gecko_GetFontMetrics.
287 PostTraversalTask::RejectFontFaceLoadedPromise(this, aResult
));
292 mLoaded
->MaybeReject(aResult
);
293 } else if (mLoadedRejection
== NS_OK
) {
294 mLoadedRejection
= aResult
;
298 void FontFace::EnsurePromise() {
299 if (mLoaded
|| !mImpl
|| !mParent
) {
304 mLoaded
= Promise::Create(mParent
, rv
);
306 if (mImpl
->Status() == FontFaceLoadStatus::Loaded
) {
307 mLoaded
->MaybeResolve(this);
308 } else if (mLoadedRejection
!= NS_OK
) {
309 mLoaded
->MaybeReject(mLoadedRejection
);
314 } // namespace mozilla