Serenity Operating System
at master 271 lines 10 kB view raw
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/WebIDL/ExceptionOr.h> 10 11namespace Web::Geometry { 12 13WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrix>> DOMMatrix::construct_impl(JS::Realm& realm, Optional<Variant<String, Vector<double>>> const& init) 14{ 15 auto& vm = realm.vm(); 16 17 // https://drafts.fxtf.org/geometry/#dom-dommatrix-dommatrix 18 if (init.has_value()) { 19 // -> Otherwise 20 // Throw a TypeError exception. 21 // The only condition where this can be met is with a sequence type which doesn't have exactly 6 or 16 elements. 22 if (auto* double_sequence = init.value().get_pointer<Vector<double>>(); double_sequence && (double_sequence->size() != 6 && double_sequence->size() != 16)) 23 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())) }; 24 } 25 26 return realm.heap().allocate<DOMMatrix>(realm, realm, init).release_allocated_value_but_fixme_should_propagate_errors(); 27} 28 29// https://drafts.fxtf.org/geometry/#create-a-dommatrix-from-the-2d-dictionary 30WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrix>> DOMMatrix::create_from_dom_matrix_2d_init(JS::Realm& realm, DOMMatrix2DInit& init) 31{ 32 // 1. Validate and fixup (2D) other. 33 TRY(validate_and_fixup_dom_matrix_2d_init(init)); 34 35 // These should all have values after calling `validate_and_fixup_dom_matrix_2d_init` 36 VERIFY(init.m11.has_value()); 37 VERIFY(init.m12.has_value()); 38 VERIFY(init.m21.has_value()); 39 VERIFY(init.m22.has_value()); 40 VERIFY(init.m41.has_value()); 41 VERIFY(init.m42.has_value()); 42 43 // 2. Return the result of invoking create a 2d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with a sequence of numbers, 44 // the values being the 6 elements m11, m12, m21, m22, m41 and m42 of other in the given order. 45 return realm.heap().allocate<DOMMatrix>(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(); 46} 47 48JS::NonnullGCPtr<DOMMatrix> DOMMatrix::create_from_dom_matrix_read_only(JS::Realm& realm, DOMMatrixReadOnly const& read_only_matrix) 49{ 50 return realm.heap().allocate<DOMMatrix>(realm, realm, read_only_matrix).release_allocated_value_but_fixme_should_propagate_errors(); 51} 52 53DOMMatrix::DOMMatrix(JS::Realm& realm, double m11, double m12, double m21, double m22, double m41, double m42) 54 : DOMMatrixReadOnly(realm, m11, m12, m21, m22, m41, m42) 55{ 56} 57 58DOMMatrix::DOMMatrix(JS::Realm& realm, Optional<Variant<String, Vector<double>>> const& init) 59 : DOMMatrixReadOnly(realm, init) 60{ 61} 62 63DOMMatrix::DOMMatrix(JS::Realm& realm, DOMMatrixReadOnly const& read_only_matrix) 64 : DOMMatrixReadOnly(realm, read_only_matrix) 65{ 66} 67 68DOMMatrix::~DOMMatrix() = default; 69 70JS::ThrowCompletionOr<void> DOMMatrix::initialize(JS::Realm& realm) 71{ 72 MUST_OR_THROW_OOM(Base::initialize(realm)); 73 set_prototype(&Bindings::ensure_web_prototype<Bindings::DOMMatrixPrototype>(realm, "DOMMatrix")); 74 75 return {}; 76} 77 78// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m11 79void DOMMatrix::set_m11(double value) 80{ 81 // For the DOMMatrix interface, setting the m11 or the a attribute must set the m11 element to the new value. 82 m_matrix.elements()[0][0] = value; 83} 84 85// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m12 86void DOMMatrix::set_m12(double value) 87{ 88 // For the DOMMatrix interface, setting the m12 or the b attribute must set the m12 element to the new value. 89 m_matrix.elements()[0][1] = value; 90} 91 92// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m13 93void DOMMatrix::set_m13(double value) 94{ 95 // For the DOMMatrix interface, setting the m13 attribute must set the m13 element to the new value and, if the new value is not 0 or -0, set is 2D to false. 96 m_matrix.elements()[0][2] = value; 97 if (value != 0.0 && value != -0.0) 98 m_is_2d = false; 99} 100 101// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m14 102void DOMMatrix::set_m14(double value) 103{ 104 // For the DOMMatrix interface, setting the m14 attribute must set the m14 element to the new value and, if the new value is not 0 or -0, set is 2D to false. 105 m_matrix.elements()[0][3] = value; 106 if (value != 0.0 && value != -0.0) 107 m_is_2d = false; 108} 109 110// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m21 111void DOMMatrix::set_m21(double value) 112{ 113 // For the DOMMatrix interface, setting the m21 or the c attribute must set the m21 element to the new value. 114 m_matrix.elements()[1][0] = value; 115} 116 117// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m22 118void DOMMatrix::set_m22(double value) 119{ 120 // For the DOMMatrix interface, setting the m22 or the d attribute must set the m22 element to the new value. 121 m_matrix.elements()[1][1] = value; 122} 123 124// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m23 125void DOMMatrix::set_m23(double value) 126{ 127 // For the DOMMatrix interface, setting the m23 attribute must set the m23 element to the new value and, if the new value is not 0 or -0, set is 2D to false. 128 m_matrix.elements()[1][2] = value; 129 if (value != 0.0 && value != -0.0) 130 m_is_2d = false; 131} 132 133// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m24 134void DOMMatrix::set_m24(double value) 135{ 136 // For the DOMMatrix interface, setting the m24 attribute must set the m24 element to the new value and, if the new value is not 0 or -0, set is 2D to false. 137 m_matrix.elements()[1][3] = value; 138 if (value != 0.0 && value != -0.0) 139 m_is_2d = false; 140} 141 142// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m31 143void DOMMatrix::set_m31(double value) 144{ 145 // For the DOMMatrix interface, setting the m31 attribute must set the m31 element to the new value and, if the new value is not 0 or -0, set is 2D to false. 146 m_matrix.elements()[2][0] = value; 147 if (value != 0.0 && value != -0.0) 148 m_is_2d = false; 149} 150 151// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m32 152void DOMMatrix::set_m32(double value) 153{ 154 // For the DOMMatrix interface, setting the m32 attribute must set the m32 element to the new value and, if the new value is not 0 or -0, set is 2D to false. 155 m_matrix.elements()[2][1] = value; 156 if (value != 0.0 && value != -0.0) 157 m_is_2d = false; 158} 159 160// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m33 161void DOMMatrix::set_m33(double value) 162{ 163 // For the DOMMatrix interface, setting the m33 attribute must set the m33 element to the new value and, if the new value is not 1, set is 2D to false. 164 m_matrix.elements()[2][2] = value; 165 if (value != 1.0) 166 m_is_2d = false; 167} 168 169// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m34 170void DOMMatrix::set_m34(double value) 171{ 172 // For the DOMMatrix interface, setting the m34 attribute must set the m34 element to the new value and, if the new value is not 0 or -0, set is 2D to false. 173 m_matrix.elements()[2][3] = value; 174 if (value != 0.0 && value != -0.0) 175 m_is_2d = false; 176} 177 178// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m41 179void DOMMatrix::set_m41(double value) 180{ 181 // For the DOMMatrix interface, setting the m41 or the e attribute must set the m41 element to the new value. 182 m_matrix.elements()[3][0] = value; 183} 184 185// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m42 186void DOMMatrix::set_m42(double value) 187{ 188 // For the DOMMatrix interface, setting the m42 or the f attribute must set the m42 element to the new value. 189 m_matrix.elements()[3][1] = value; 190} 191 192// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m43 193void DOMMatrix::set_m43(double value) 194{ 195 // For the DOMMatrix interface, setting the m43 attribute must set the m43 element to the new value and, if the new value is not 0 or -0, set is 2D to false. 196 m_matrix.elements()[3][2] = value; 197 if (value != 0.0 && value != -0.0) 198 m_is_2d = false; 199} 200 201// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m44 202void DOMMatrix::set_m44(double value) 203{ 204 // For the DOMMatrix interface, setting the m44 attribute must set the m44 element to the new value and, if the new value is not 1, set is 2D to false. 205 m_matrix.elements()[3][3] = value; 206 if (value != 1.0) 207 m_is_2d = false; 208} 209 210// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-a 211void DOMMatrix::set_a(double value) 212{ 213 // For the DOMMatrix interface, setting the m11 or the a attribute must set the m11 element to the new value. 214 set_m11(value); 215} 216 217// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-b 218void DOMMatrix::set_b(double value) 219{ 220 // For the DOMMatrix interface, setting the m12 or the b attribute must set the m12 element to the new value. 221 set_m12(value); 222} 223 224// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-c 225void DOMMatrix::set_c(double value) 226{ 227 // For the DOMMatrix interface, setting the m21 or the c attribute must set the m21 element to the new value. 228 set_m21(value); 229} 230 231// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-d 232void DOMMatrix::set_d(double value) 233{ 234 // For the DOMMatrix interface, setting the m22 or the d attribute must set the m22 element to the new value. 235 set_m22(value); 236} 237 238// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-e 239void DOMMatrix::set_e(double value) 240{ 241 // For the DOMMatrix interface, setting the m41 or the e attribute must set the m41 element to the new value. 242 set_m41(value); 243} 244 245// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-f 246void DOMMatrix::set_f(double value) 247{ 248 // For the DOMMatrix interface, setting the m42 or the f attribute must set the m42 element to the new value. 249 set_m42(value); 250} 251 252// https://drafts.fxtf.org/geometry/#dom-dommatrix-invertself 253JS::NonnullGCPtr<DOMMatrix> DOMMatrix::invert_self() 254{ 255 // 1. Invert the current matrix. 256 m_matrix = m_matrix.inverse(); 257 258 // 2. If the current matrix is not invertible set all attributes to NaN and set is 2D to false. 259 if (!m_matrix.is_invertible()) { 260 for (u8 i = 0; i < 4; i++) { 261 for (u8 j = 0; j < 4; j++) 262 m_matrix.elements()[i][j] = NAN; 263 } 264 m_is_2d = false; 265 } 266 267 // 3. Return the current matrix. 268 return *this; 269} 270 271}