1use std::cell::Cell;
6
7use base::id::{DomPointId, DomPointIndex};
8use constellation_traits::DomPoint;
9use dom_struct::dom_struct;
10use js::rust::HandleObject;
11use rustc_hash::FxHashMap;
12
13use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrixInit;
14use crate::dom::bindings::codegen::Bindings::DOMPointBinding::DOMPointInit;
15use crate::dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::DOMPointReadOnlyMethods;
16use crate::dom::bindings::error::Fallible;
17use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
18use crate::dom::bindings::root::DomRoot;
19use crate::dom::bindings::serializable::Serializable;
20use crate::dom::bindings::structuredclone::StructuredData;
21use crate::dom::dommatrixreadonly::dommatrixinit_to_matrix;
22use crate::dom::globalscope::GlobalScope;
23use crate::dom::types::DOMPoint;
24use crate::script_runtime::CanGc;
25
26#[dom_struct]
28pub(crate) struct DOMPointReadOnly {
29 reflector_: Reflector,
30 x: Cell<f64>,
31 y: Cell<f64>,
32 z: Cell<f64>,
33 w: Cell<f64>,
34}
35
36impl DOMPointReadOnly {
37 pub(crate) fn new_inherited(x: f64, y: f64, z: f64, w: f64) -> DOMPointReadOnly {
38 DOMPointReadOnly {
39 x: Cell::new(x),
40 y: Cell::new(y),
41 z: Cell::new(z),
42 w: Cell::new(w),
43 reflector_: Reflector::new(),
44 }
45 }
46
47 pub(crate) fn new(
48 global: &GlobalScope,
49 x: f64,
50 y: f64,
51 z: f64,
52 w: f64,
53 can_gc: CanGc,
54 ) -> DomRoot<DOMPointReadOnly> {
55 Self::new_with_proto(global, None, x, y, z, w, can_gc)
56 }
57
58 fn new_with_proto(
59 global: &GlobalScope,
60 proto: Option<HandleObject>,
61 x: f64,
62 y: f64,
63 z: f64,
64 w: f64,
65 can_gc: CanGc,
66 ) -> DomRoot<DOMPointReadOnly> {
67 reflect_dom_object_with_proto(
68 Box::new(DOMPointReadOnly::new_inherited(x, y, z, w)),
69 global,
70 proto,
71 can_gc,
72 )
73 }
74}
75
76impl DOMPointReadOnlyMethods<crate::DomTypeHolder> for DOMPointReadOnly {
77 fn Constructor(
79 global: &GlobalScope,
80 proto: Option<HandleObject>,
81 can_gc: CanGc,
82 x: f64,
83 y: f64,
84 z: f64,
85 w: f64,
86 ) -> Fallible<DomRoot<DOMPointReadOnly>> {
87 Ok(DOMPointReadOnly::new_with_proto(
88 global, proto, x, y, z, w, can_gc,
89 ))
90 }
91
92 fn FromPoint(global: &GlobalScope, init: &DOMPointInit, can_gc: CanGc) -> DomRoot<Self> {
94 Self::new(global, init.x, init.y, init.z, init.w, can_gc)
95 }
96
97 fn X(&self) -> f64 {
99 self.x.get()
100 }
101
102 fn Y(&self) -> f64 {
104 self.y.get()
105 }
106
107 fn Z(&self) -> f64 {
109 self.z.get()
110 }
111
112 fn W(&self) -> f64 {
114 self.w.get()
115 }
116
117 fn MatrixTransform(
120 &self,
121 matrix: &DOMMatrixInit,
122 can_gc: CanGc,
123 ) -> Fallible<DomRoot<DOMPoint>> {
124 let matrix_object = match dommatrixinit_to_matrix(matrix) {
126 Ok(converted) => converted,
127 Err(exception) => {
128 return Err(exception);
129 },
130 };
131 let x = self.X();
133 let y = self.Y();
134 let z = self.Z();
135 let w = self.W();
136 let m = &matrix_object.1;
138 let transformed_point = DOMPointInit {
139 x: m.m11 * x + m.m21 * y + m.m31 * z + m.m41 * w,
140 y: m.m12 * x + m.m22 * y + m.m32 * z + m.m42 * w,
141 z: m.m13 * x + m.m23 * y + m.m33 * z + m.m43 * w,
142 w: m.m14 * x + m.m24 * y + m.m34 * z + m.m44 * w,
143 };
144 Ok(DOMPoint::new_from_init(
147 &self.global(),
148 &transformed_point,
149 can_gc,
150 ))
151 }
152}
153
154#[expect(non_snake_case)]
155pub(crate) trait DOMPointWriteMethods {
156 fn SetX(&self, value: f64);
157 fn SetY(&self, value: f64);
158 fn SetZ(&self, value: f64);
159 fn SetW(&self, value: f64);
160}
161
162impl DOMPointWriteMethods for DOMPointReadOnly {
163 fn SetX(&self, value: f64) {
164 self.x.set(value);
165 }
166
167 fn SetY(&self, value: f64) {
168 self.y.set(value);
169 }
170
171 fn SetZ(&self, value: f64) {
172 self.z.set(value);
173 }
174
175 fn SetW(&self, value: f64) {
176 self.w.set(value);
177 }
178}
179
180impl Serializable for DOMPointReadOnly {
181 type Index = DomPointIndex;
182 type Data = DomPoint;
183
184 fn serialize(&self) -> Result<(DomPointId, Self::Data), ()> {
185 let serialized = DomPoint {
186 x: self.x.get(),
187 y: self.y.get(),
188 z: self.z.get(),
189 w: self.w.get(),
190 };
191 Ok((DomPointId::new(), serialized))
192 }
193
194 fn deserialize(
195 owner: &GlobalScope,
196 serialized: Self::Data,
197 can_gc: CanGc,
198 ) -> Result<DomRoot<Self>, ()>
199 where
200 Self: Sized,
201 {
202 Ok(Self::new(
203 owner,
204 serialized.x,
205 serialized.y,
206 serialized.z,
207 serialized.w,
208 can_gc,
209 ))
210 }
211
212 fn serialized_storage<'a>(
213 data: StructuredData<'a, '_>,
214 ) -> &'a mut Option<FxHashMap<DomPointId, Self::Data>> {
215 match data {
216 StructuredData::Reader(r) => &mut r.points,
217 StructuredData::Writer(w) => &mut w.points,
218 }
219 }
220}