Serenity Operating System
1/*
2 * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibWeb/Bindings/Intrinsics.h>
8#include <LibWeb/Geometry/DOMMatrix.h>
9#include <LibWeb/Geometry/DOMMatrixReadOnly.h>
10#include <LibWeb/WebIDL/ExceptionOr.h>
11
12namespace Web::Geometry {
13
14WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrixReadOnly>> DOMMatrixReadOnly::construct_impl(JS::Realm& realm, Optional<Variant<String, Vector<double>>> const& init)
15{
16 auto& vm = realm.vm();
17
18 // https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-dommatrixreadonly
19 if (init.has_value()) {
20 // -> Otherwise
21 // Throw a TypeError exception.
22 // The only condition where this can be met is with a sequence type which doesn't have exactly 6 or 16 elements.
23 if (auto* double_sequence = init.value().get_pointer<Vector<double>>(); double_sequence && (double_sequence->size() != 6 && double_sequence->size() != 16))
24 return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, TRY_OR_THROW_OOM(vm, String::formatted("Sequence must contain exactly 6 or 16 elements, got {} element(s)", double_sequence->size())) };
25 }
26
27 return realm.heap().allocate<DOMMatrixReadOnly>(realm, realm, init).release_allocated_value_but_fixme_should_propagate_errors();
28}
29
30// https://drafts.fxtf.org/geometry/#create-a-dommatrixreadonly-from-the-2d-dictionary
31WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrixReadOnly>> DOMMatrixReadOnly::create_from_dom_matrix_2d_init(JS::Realm& realm, DOMMatrix2DInit& init)
32{
33 // 1. Validate and fixup (2D) other.
34 TRY(validate_and_fixup_dom_matrix_2d_init(init));
35
36 // These should all have values after calling `validate_and_fixup_dom_matrix_2d_init`
37 VERIFY(init.m11.has_value());
38 VERIFY(init.m12.has_value());
39 VERIFY(init.m21.has_value());
40 VERIFY(init.m22.has_value());
41 VERIFY(init.m41.has_value());
42 VERIFY(init.m42.has_value());
43
44 // 2. Return the result of invoking create a 2d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with a sequence of numbers,
45 // the values being the 6 elements m11, m12, m21, m22, m41 and m42 of other in the given order.
46 return realm.heap().allocate<DOMMatrixReadOnly>(realm, realm, init.m11.value(), init.m12.value(), init.m21.value(), init.m22.value(), init.m41.value(), init.m42.value()).release_allocated_value_but_fixme_should_propagate_errors();
47}
48
49DOMMatrixReadOnly::DOMMatrixReadOnly(JS::Realm& realm, double m11, double m12, double m21, double m22, double m41, double m42)
50 : Bindings::PlatformObject(realm)
51{
52 initialize_from_create_2d_matrix(m11, m12, m21, m22, m41, m42);
53}
54
55DOMMatrixReadOnly::DOMMatrixReadOnly(JS::Realm& realm, double m11, double m12, double m13, double m14, double m21, double m22, double m23, double m24, double m31, double m32, double m33, double m34, double m41, double m42, double m43, double m44)
56 : Bindings::PlatformObject(realm)
57{
58 initialize_from_create_3d_matrix(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
59}
60
61DOMMatrixReadOnly::DOMMatrixReadOnly(JS::Realm& realm, Optional<Variant<String, Vector<double>>> const& init)
62 : Bindings::PlatformObject(realm)
63{
64 // https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-dommatrixreadonly
65 // -> If init is omitted
66 if (!init.has_value()) {
67 // Return the result of invoking create a 2d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with the sequence [1, 0, 0, 1, 0, 0].
68 initialize_from_create_2d_matrix(1, 0, 0, 1, 0, 0);
69 return;
70 }
71 auto const& init_value = init.value();
72
73 // -> If init is a DOMString
74 if (init_value.has<String>()) {
75 dbgln("FIXME: Implement initializing DOMMatrix(ReadOnly) from DOMString: '{}'", init_value.get<String>());
76 // NOTE: This will result in an identity matrix for now.
77 return;
78 }
79
80 auto const& double_sequence = init_value.get<Vector<double>>();
81
82 // -> If init is a sequence with 6 elements
83 if (double_sequence.size() == 6) {
84 // Return the result of invoking create a 2d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with the sequence init.
85 initialize_from_create_2d_matrix(double_sequence[0], double_sequence[1], double_sequence[2], double_sequence[3], double_sequence[4], double_sequence[5]);
86 return;
87 }
88
89 // -> If init is a sequence with 16 elements
90 // NOTE: The "otherwise" case should be handled in construct_impl, leaving the only other possible condition here to be 16 elements.
91 VERIFY(double_sequence.size() == 16);
92
93 // Return the result of invoking create a 3d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with the sequence init.
94 initialize_from_create_3d_matrix(
95 double_sequence[0], double_sequence[1], double_sequence[2], double_sequence[3],
96 double_sequence[4], double_sequence[5], double_sequence[6], double_sequence[7],
97 double_sequence[8], double_sequence[9], double_sequence[10], double_sequence[11],
98 double_sequence[12], double_sequence[13], double_sequence[14], double_sequence[15]);
99}
100
101DOMMatrixReadOnly::DOMMatrixReadOnly(JS::Realm& realm, DOMMatrixReadOnly const& other)
102 : Bindings::PlatformObject(realm)
103 , m_matrix(other.m_matrix)
104 , m_is_2d(other.m_is_2d)
105{
106}
107
108DOMMatrixReadOnly::~DOMMatrixReadOnly() = default;
109
110JS::ThrowCompletionOr<void> DOMMatrixReadOnly::initialize(JS::Realm& realm)
111{
112 MUST_OR_THROW_OOM(Base::initialize(realm));
113 set_prototype(&Bindings::ensure_web_prototype<Bindings::DOMMatrixReadOnlyPrototype>(realm, "DOMMatrixReadOnly"));
114
115 return {};
116}
117
118// https://drafts.fxtf.org/geometry/#create-a-2d-matrix
119void DOMMatrixReadOnly::initialize_from_create_2d_matrix(double m11, double m12, double m21, double m22, double m41, double m42)
120{
121 // 1. Let matrix be a new instance of type.
122 // 2. Set m11 element, m12 element, m21 element, m22 element, m41 element and m42 element to the values of init in order starting with the first value.
123 auto* elements = m_matrix.elements();
124 elements[0][0] = m11;
125 elements[0][1] = m12;
126 elements[1][0] = m21;
127 elements[1][1] = m22;
128 elements[3][0] = m41;
129 elements[3][1] = m42;
130
131 // 3. Set m13 element, m14 element, m23 element, m24 element, m31 element, m32 element, m34 element, and m43 element to 0.
132 elements[0][2] = 0.0;
133 elements[0][3] = 0.0;
134 elements[1][2] = 0.0;
135 elements[1][3] = 0.0;
136 elements[2][0] = 0.0;
137 elements[2][1] = 0.0;
138 elements[2][3] = 0.0;
139 elements[3][2] = 0.0;
140
141 // 4. Set m33 element and m44 element to 1.
142 elements[2][2] = 1.0;
143 elements[3][3] = 1.0;
144
145 // 5. Set is 2D to true.
146 m_is_2d = true;
147
148 // 6. Return matrix
149}
150
151// https://drafts.fxtf.org/geometry/#create-a-3d-matrix
152void DOMMatrixReadOnly::initialize_from_create_3d_matrix(double m11, double m12, double m13, double m14, double m21, double m22, double m23, double m24, double m31, double m32, double m33, double m34, double m41, double m42, double m43, double m44)
153{
154 // 1. Let matrix be a new instance of type.
155 // 2. Set m11 element to m44 element to the values of init in column-major order.
156 auto* elements = m_matrix.elements();
157 elements[0][0] = m11;
158 elements[0][1] = m12;
159 elements[0][2] = m13;
160 elements[0][3] = m14;
161 elements[1][0] = m21;
162 elements[1][1] = m22;
163 elements[1][2] = m23;
164 elements[1][3] = m24;
165 elements[2][0] = m31;
166 elements[2][1] = m32;
167 elements[2][2] = m33;
168 elements[2][3] = m34;
169 elements[3][0] = m41;
170 elements[3][1] = m42;
171 elements[3][2] = m43;
172 elements[3][3] = m44;
173
174 // 3. Set is 2D to false.
175 m_is_2d = false;
176
177 // 4. Return matrix
178}
179
180// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-isidentity
181bool DOMMatrixReadOnly::is_identity() const
182{
183 // The isIdentity attribute must return true if
184 // m12 element, m13 element, m14 element,
185 // m21 element, m23 element, m24 element,
186 // m31 element, m32 element, m34 element
187 // m41 element, m42 element, m43 element
188 // are 0 or -0 and
189 // m11 element, m22 element, m33 element, m44 element are 1.
190 // Otherwise it must return false.
191 if (m12() != 0.0 && m12() != -0.0)
192 return false;
193
194 if (m13() != 0.0 && m13() != -0.0)
195 return false;
196
197 if (m14() != 0.0 && m14() != -0.0)
198 return false;
199
200 if (m21() != 0.0 && m21() != -0.0)
201 return false;
202
203 if (m23() != 0.0 && m24() != -0.0)
204 return false;
205
206 if (m31() != 0.0 && m32() != -0.0)
207 return false;
208
209 if (m34() != 0.0 && m34() != -0.0)
210 return false;
211
212 if (m41() != 0.0 && m42() != -0.0)
213 return false;
214
215 if (m43() != 0.0 && m43() != -0.0)
216 return false;
217
218 if (m11() != 1.0)
219 return false;
220
221 if (m22() != 1.0)
222 return false;
223
224 if (m33() != 1.0)
225 return false;
226
227 if (m44() != 1.0)
228 return false;
229
230 return true;
231}
232
233// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-inverse
234JS::NonnullGCPtr<DOMMatrix> DOMMatrixReadOnly::inverse() const
235{
236 // 1. Let result be the resulting matrix initialized to the values of the current matrix.
237 auto result = DOMMatrix::create_from_dom_matrix_read_only(realm(), *this);
238
239 // 2. Perform a invertSelf() transformation on result.
240 // 3. Return result.
241 // The current matrix is not modified.
242 return result->invert_self();
243}
244
245// https://drafts.fxtf.org/geometry/#dommatrixreadonly-stringification-behavior
246WebIDL::ExceptionOr<String> DOMMatrixReadOnly::to_string() const
247{
248 auto& vm = this->vm();
249
250 // 1. If one or more of m11 element through m44 element are a non-finite value, then throw an "InvalidStateError" DOMException.
251 // Spec Note: The CSS syntax cannot represent NaN or Infinity values.
252 if (!isfinite(m11()) || !isfinite(m12()) || !isfinite(m13()) || !isfinite(m14())
253 || !isfinite(m21()) || !isfinite(m22()) || !isfinite(m23()) || !isfinite(m24())
254 || !isfinite(m31()) || !isfinite(m32()) || !isfinite(m33()) || !isfinite(m34())
255 || !isfinite(m41()) || !isfinite(m42()) || !isfinite(m43()) || !isfinite(m44())) {
256 return WebIDL::InvalidStateError::create(realm(), "Cannot stringify non-finite matrix values");
257 }
258
259 // 2. Let string be the empty string.
260 StringBuilder builder;
261
262 // 3. If is 2D is true, then:
263 if (m_is_2d) {
264 // 1. Append "matrix(" to string.
265 TRY_OR_THROW_OOM(vm, builder.try_append("matrix("sv));
266
267 // 2. Append ! ToString(m11 element) to string.
268 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::Value(m11()).to_string_without_side_effects())));
269
270 // 3. Append ", " to string.
271 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
272
273 // 4. Append ! ToString(m12 element) to string.
274 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::Value(m12()).to_string_without_side_effects())));
275
276 // 5. Append ", " to string.
277 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
278
279 // 6. Append ! ToString(m21 element) to string.
280 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::Value(m21()).to_string_without_side_effects())));
281
282 // 7. Append ", " to string.
283 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
284
285 // 8. Append ! ToString(m22 element) to string.
286 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::Value(m22()).to_string_without_side_effects())));
287
288 // 9. Append ", " to string.
289 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
290
291 // 10. Append ! ToString(m41 element) to string.
292 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::Value(m41()).to_string_without_side_effects())));
293
294 // 11. Append ", " to string.
295 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
296
297 // 12. Append ! ToString(m42 element) to string.
298 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::Value(m42()).to_string_without_side_effects())));
299
300 // 13. Append ")" to string.
301 TRY_OR_THROW_OOM(vm, builder.try_append(")"sv));
302 } else {
303 // 1. Append "matrix3d(" to string.
304 TRY_OR_THROW_OOM(vm, builder.try_append("matrix3d("sv));
305
306 // 2. Append ! ToString(m11 element) to string.
307 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m11()))));
308
309 // 3. Append ", " to string.
310 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
311
312 // 4. Append ! ToString(m12 element) to string.
313 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m12()))));
314
315 // 5. Append ", " to string.
316 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
317
318 // 6. Append ! ToString(m13 element) to string.
319 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m13()))));
320
321 // 7. Append ", " to string.
322 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
323
324 // 8. Append ! ToString(m14 element) to string.
325 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m14()))));
326
327 // 9. Append ", " to string.
328 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
329
330 // 10. Append ! ToString(m21 element) to string.
331 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m21()))));
332
333 // 11. Append ", " to string.
334 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
335
336 // 12. Append ! ToString(m22 element) to string.
337 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m22()))));
338
339 // 13. Append ", " to string.
340 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
341
342 // 14. Append ! ToString(m23 element) to string.
343 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m23()))));
344
345 // 15. Append ", " to string.
346 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
347
348 // 16. Append ! ToString(m24 element) to string.
349 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m24()))));
350
351 // 17. Append ", " to string.
352 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
353
354 // NOTE: The spec doesn't include the steps to append m31 to m34, but they are required as matrix3d requires 16 elements.
355 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m31()))));
356 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
357 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m32()))));
358 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
359 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m33()))));
360 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
361 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m34()))));
362 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
363
364 // 18. Append ! ToString(m41 element) to string.
365 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m41()))));
366
367 // 19. Append ", " to string.
368 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
369
370 // 20. Append ! ToString(m42 element) to string.
371 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m42()))));
372
373 // 21. Append ", " to string.
374 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
375
376 // 22. Append ! ToString(m43 element) to string.
377 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m43()))));
378
379 // 23. Append ", " to string.
380 TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
381
382 // 24. Append ! ToString(m44 element) to string.
383 TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m44()))));
384
385 // 25. Append ")" to string.
386 TRY_OR_THROW_OOM(vm, builder.try_append(")"sv));
387 }
388
389 // 5. Return string.
390 return TRY_OR_THROW_OOM(vm, builder.to_string());
391}
392
393// https://drafts.fxtf.org/geometry/#matrix-validate-and-fixup-2d
394WebIDL::ExceptionOr<void> validate_and_fixup_dom_matrix_2d_init(DOMMatrix2DInit& init)
395{
396 // 1. If at least one of the following conditions are true for dict, then throw a TypeError exception and abort these steps.
397 // - a and m11 are both present and SameValueZero(a, m11) is false.
398 if (init.a.has_value() && init.m11.has_value() && !JS::same_value_zero(JS::Value(init.a.value()), JS::Value(init.m11.value())))
399 return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "DOMMatrix2DInit.a and DOMMatrix2DInit.m11 must have the same value if they are both present"sv };
400
401 // - b and m12 are both present and SameValueZero(b, m12) is false.
402 if (init.b.has_value() && init.m12.has_value() && !JS::same_value_zero(JS::Value(init.b.value()), JS::Value(init.m12.value())))
403 return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "DOMMatrix2DInit.b and DOMMatrix2DInit.m12 must have the same value if they are both present"sv };
404
405 // - c and m21 are both present and SameValueZero(c, m21) is false.
406 if (init.c.has_value() && init.m21.has_value() && !JS::same_value_zero(JS::Value(init.c.value()), JS::Value(init.m21.value())))
407 return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "DOMMatrix2DInit.c and DOMMatrix2DInit.m21 must have the same value if they are both present"sv };
408
409 // - d and m22 are both present and SameValueZero(d, m22) is false.
410 if (init.d.has_value() && init.m22.has_value() && !JS::same_value_zero(JS::Value(init.d.value()), JS::Value(init.m22.value())))
411 return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "DOMMatrix2DInit.d and DOMMatrix2DInit.m22 must have the same value if they are both present"sv };
412
413 // - e and m41 are both present and SameValueZero(e, m41) is false.
414 if (init.e.has_value() && init.m41.has_value() && !JS::same_value_zero(JS::Value(init.e.value()), JS::Value(init.m41.value())))
415 return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "DOMMatrix2DInit.e and DOMMatrix2DInit.m41 must have the same value if they are both present"sv };
416
417 // - f and m42 are both present and SameValueZero(f, m42) is false.
418 if (init.f.has_value() && init.m42.has_value() && !JS::same_value_zero(JS::Value(init.f.value()), JS::Value(init.m42.value())))
419 return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "DOMMatrix2DInit.f and DOMMatrix2DInit.m42 must have the same value if they are both present"sv };
420
421 // 2. If m11 is not present then set it to the value of member a, or value 1 if a is also not present.
422 if (!init.m11.has_value())
423 init.m11 = init.a.value_or(1.0);
424
425 // 3. If m12 is not present then set it to the value of member b, or value 0 if b is also not present.
426 if (!init.m12.has_value())
427 init.m12 = init.b.value_or(0.0);
428
429 // 4. If m21 is not present then set it to the value of member c, or value 0 if c is also not present.
430 if (!init.m21.has_value())
431 init.m21 = init.c.value_or(0.0);
432
433 // 5. If m22 is not present then set it to the value of member d, or value 1 if d is also not present.
434 if (!init.m22.has_value())
435 init.m22 = init.d.value_or(1.0);
436
437 // 6. If m41 is not present then set it to the value of member e, or value 0 if e is also not present.
438 if (!init.m41.has_value())
439 init.m41 = init.e.value_or(0.0);
440
441 // 7. If m42 is not present then set it to the value of member f, or value 0 if f is also not present.
442 if (!init.m42.has_value())
443 init.m42 = init.f.value_or(0.0);
444
445 return {};
446}
447
448// https://drafts.fxtf.org/geometry/#matrix-validate-and-fixup
449WebIDL::ExceptionOr<void> validate_and_fixup_dom_matrix_init(DOMMatrixInit& init)
450{
451 // 1. Validate and fixup (2D) dict.
452 TRY(validate_and_fixup_dom_matrix_2d_init(init));
453
454 // 2. If is2D is true and: at least one of m13, m14, m23, m24, m31, m32, m34, m43 are present with a value other than 0 or -0,
455 // or at least one of m33, m44 are present with a value other than 1, then throw a TypeError exception and abort these steps.
456 if (init.is2d.has_value() && init.is2d.value()) {
457 if ((init.m13 != 0.0 && init.m13 != -0.0)
458 || (init.m14 != 0.0 && init.m14 != -0.0)
459 || (init.m23 != 0.0 && init.m23 != -0.0)
460 || (init.m24 != 0.0 && init.m24 != -0.0)
461 || (init.m31 != 0.0 && init.m31 != -0.0)
462 || (init.m32 != 0.0 && init.m32 != -0.0)
463 || (init.m34 != 0.0 && init.m34 != -0.0)
464 || (init.m43 != 0.0 && init.m43 != -0.0)
465 || init.m33 != 1.0
466 || init.m44 != 1.0) {
467 return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "DOMMatrixInit.is2D is true, but the given matrix is not a 2D matrix"sv };
468 }
469 }
470
471 // If is2D is not present and at least one of m13, m14, m23, m24, m31, m32, m34, m43 are present with a value other than 0 or -0,
472 // or at least one of m33, m44 are present with a value other than 1, set is2D to false.
473 if (!init.is2d.has_value()) {
474 if ((init.m13 != 0.0 && init.m13 != -0.0)
475 || (init.m14 != 0.0 && init.m14 != -0.0)
476 || (init.m23 != 0.0 && init.m23 != -0.0)
477 || (init.m24 != 0.0 && init.m24 != -0.0)
478 || (init.m31 != 0.0 && init.m31 != -0.0)
479 || (init.m32 != 0.0 && init.m32 != -0.0)
480 || (init.m34 != 0.0 && init.m34 != -0.0)
481 || (init.m43 != 0.0 && init.m43 != -0.0)
482 || init.m33 != 1.0
483 || init.m44 != 1.0) {
484 init.is2d = false;
485 }
486 }
487
488 // 4. If is2D is still not present, set it to true.
489 if (!init.is2d.has_value())
490 init.is2d = true;
491
492 return {};
493}
494
495}