Bug 1909074. Don't pass OFFSET_BY_ORIGIN to GetResultingTransformMatrix when it's...
[gecko.git] / layout / style / FontFace.cpp
blob20769bf3787625533493ea764b6e31a27deb3f2b
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"
9 #include <algorithm>
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"
26 namespace mozilla {
27 namespace dom {
29 // -- Utility functions ------------------------------------------------------
31 template <typename T>
32 static void GetDataFrom(const T& aObject, uint8_t*& aBuffer,
33 uint32_t& aLength) {
34 MOZ_ASSERT(!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
37 // fine.
38 Maybe<Vector<uint8_t>> buffer =
39 aObject.template CreateFromData<Vector<uint8_t>>();
40 if (buffer.isNothing()) {
41 return;
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)
57 tmp->Destroy();
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)
68 NS_INTERFACE_MAP_END
70 NS_IMPL_CYCLE_COLLECTING_ADDREF(FontFace)
71 NS_IMPL_CYCLE_COLLECTING_RELEASE(FontFace)
73 FontFace::FontFace(nsIGlobalObject* aParent) : mLoadedRejection(NS_OK) {
74 BindToOwner(aParent);
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());
81 Destroy();
84 void FontFace::Destroy() { mImpl->Destroy(); }
86 void FontFace::DisconnectFromOwner() {
87 GlobalTeardownObserver::DisconnectFromOwner();
88 if (mImpl) {
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();
102 MOZ_ASSERT(setImpl);
104 RefPtr<FontFace> obj = new FontFace(aGlobal);
105 obj->mImpl = FontFaceImpl::CreateForRule(obj, setImpl, aRule);
106 return obj.forget();
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);
118 return nullptr;
121 FontFaceSetImpl* setImpl = set->GetImpl();
122 if (NS_WARN_IF(!setImpl)) {
123 aRv.Throw(NS_ERROR_FAILURE);
124 return nullptr;
127 RefPtr<FontFace> obj = new FontFace(global);
128 obj->mImpl = new FontFaceImpl(obj, setImpl);
129 if (!obj->mImpl->SetDescriptors(aFamily, aDescriptors)) {
130 return obj.forget();
133 if (aSource.IsUTF8String()) {
134 obj->mImpl->InitializeSourceURL(aSource.GetAsUTF8String());
135 } else {
136 uint8_t* buffer = nullptr;
137 uint32_t length = 0;
138 if (aSource.IsArrayBuffer()) {
139 GetDataFrom(aSource.GetAsArrayBuffer(), buffer, length);
140 } else if (aSource.IsArrayBufferView()) {
141 GetDataFrom(aSource.GetAsArrayBufferView(), buffer, length);
142 } else {
143 MOZ_ASSERT_UNREACHABLE("Unhandled source type!");
144 return nullptr;
147 obj->mImpl->InitializeSourceBuffer(buffer, length);
150 return obj.forget();
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,
204 ErrorResult& aRv) {
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) {
249 EnsurePromise();
251 if (!mLoaded) {
252 aRv.Throw(NS_ERROR_FAILURE);
253 return nullptr;
256 mImpl->Load(aRv);
257 return mLoaded;
260 Promise* FontFace::GetLoaded(ErrorResult& aRv) {
261 EnsurePromise();
263 if (!mLoaded) {
264 aRv.Throw(NS_ERROR_FAILURE);
265 return nullptr;
268 return mLoaded;
271 void FontFace::MaybeResolve() {
272 gfxFontUtils::AssertSafeThreadOrServoFontMetricsLocked();
274 if (!mLoaded) {
275 return;
278 if (ServoStyleSet* ss = gfxFontUtils::CurrentServoStyleSet()) {
279 // See comments in Gecko_GetFontMetrics.
280 ss->AppendTask(PostTraversalTask::ResolveFontFaceLoadedPromise(this));
281 return;
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.
292 ss->AppendTask(
293 PostTraversalTask::RejectFontFaceLoadedPromise(this, aResult));
294 return;
297 if (mLoaded) {
298 mLoaded->MaybeReject(aResult);
299 } else if (mLoadedRejection == NS_OK) {
300 mLoadedRejection = aResult;
304 void FontFace::EnsurePromise() {
305 if (mLoaded || !mImpl || !GetOwnerGlobal()) {
306 return;
309 ErrorResult rv;
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);
319 } // namespace dom
320 } // namespace mozilla