DOMMatrix.cpp 10 KB

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