1use std::cell::Cell;
6use std::collections::HashMap;
7
8use base::id::{DomPointId, DomPointIndex};
9use constellation_traits::DomPoint;
10use dom_struct::dom_struct;
11use js::rust::HandleObject;
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
36#[allow(non_snake_case)]
37impl DOMPointReadOnly {
38 pub(crate) fn new_inherited(x: f64, y: f64, z: f64, w: f64) -> DOMPointReadOnly {
39 DOMPointReadOnly {
40 x: Cell::new(x),
41 y: Cell::new(y),
42 z: Cell::new(z),
43 w: Cell::new(w),
44 reflector_: Reflector::new(),
45 }
46 }
47
48 pub(crate) fn new(
49 global: &GlobalScope,
50 x: f64,
51 y: f64,
52 z: f64,
53 w: f64,
54 can_gc: CanGc,
55 ) -> DomRoot<DOMPointReadOnly> {
56 Self::new_with_proto(global, None, x, y, z, w, can_gc)
57 }
58
59 fn new_with_proto(
60 global: &GlobalScope,
61 proto: Option<HandleObject>,
62 x: f64,
63 y: f64,
64 z: f64,
65 w: f64,
66 can_gc: CanGc,
67 ) -> DomRoot<DOMPointReadOnly> {
68 reflect_dom_object_with_proto(
69 Box::new(DOMPointReadOnly::new_inherited(x, y, z, w)),
70 global,
71 proto,
72 can_gc,
73 )
74 }
75}
76
77#[allow(non_snake_case)]
78impl DOMPointReadOnlyMethods<crate::DomTypeHolder> for DOMPointReadOnly {
79 fn Constructor(
81 global: &GlobalScope,
82 proto: Option<HandleObject>,
83 can_gc: CanGc,
84 x: f64,
85 y: f64,
86 z: f64,
87 w: f64,
88 ) -> Fallible<DomRoot<DOMPointReadOnly>> {
89 Ok(DOMPointReadOnly::new_with_proto(
90 global, proto, x, y, z, w, can_gc,
91 ))
92 }
93
94 fn FromPoint(global: &GlobalScope, init: &DOMPointInit, can_gc: CanGc) -> DomRoot<Self> {
96 Self::new(global, init.x, init.y, init.z, init.w, can_gc)
97 }
98
99 fn X(&self) -> f64 {
101 self.x.get()
102 }
103
104 fn Y(&self) -> f64 {
106 self.y.get()
107 }
108
109 fn Z(&self) -> f64 {
111 self.z.get()
112 }
113
114 fn W(&self) -> f64 {
116 self.w.get()
117 }
118
119 fn MatrixTransform(
122 &self,
123 matrix: &DOMMatrixInit,
124 can_gc: CanGc,
125 ) -> Fallible<DomRoot<DOMPoint>> {
126 let matrix_object = match dommatrixinit_to_matrix(matrix) {
128 Ok(converted) => converted,
129 Err(exception) => {
130 return Err(exception);
131 },
132 };
133 let x = self.X();
135 let y = self.Y();
136 let z = self.Z();
137 let w = self.W();
138 let m = &matrix_object.1;
140 let transformed_point = DOMPointInit {
141 x: m.m11 * x + m.m21 * y + m.m31 * z + m.m41 * w,
142 y: m.m12 * x + m.m22 * y + m.m32 * z + m.m42 * w,
143 z: m.m13 * x + m.m23 * y + m.m33 * z + m.m43 * w,
144 w: m.m14 * x + m.m24 * y + m.m34 * z + m.m44 * w,
145 };
146 Ok(DOMPoint::new_from_init(
149 &self.global(),
150 &transformed_point,
151 can_gc,
152 ))
153 }
154}
155
156#[allow(non_snake_case)]
157pub(crate) trait DOMPointWriteMethods {
158 fn SetX(&self, value: f64);
159 fn SetY(&self, value: f64);
160 fn SetZ(&self, value: f64);
161 fn SetW(&self, value: f64);
162}
163
164impl DOMPointWriteMethods for DOMPointReadOnly {
165 fn SetX(&self, value: f64) {
166 self.x.set(value);
167 }
168
169 fn SetY(&self, value: f64) {
170 self.y.set(value);
171 }
172
173 fn SetZ(&self, value: f64) {
174 self.z.set(value);
175 }
176
177 fn SetW(&self, value: f64) {
178 self.w.set(value);
179 }
180}
181
182impl Serializable for DOMPointReadOnly {
183 type Index = DomPointIndex;
184 type Data = DomPoint;
185
186 fn serialize(&self) -> Result<(DomPointId, Self::Data), ()> {
187 let serialized = DomPoint {
188 x: self.x.get(),
189 y: self.y.get(),
190 z: self.z.get(),
191 w: self.w.get(),
192 };
193 Ok((DomPointId::new(), serialized))
194 }
195
196 fn deserialize(
197 owner: &GlobalScope,
198 serialized: Self::Data,
199 can_gc: CanGc,
200 ) -> Result<DomRoot<Self>, ()>
201 where
202 Self: Sized,
203 {
204 Ok(Self::new(
205 owner,
206 serialized.x,
207 serialized.y,
208 serialized.z,
209 serialized.w,
210 can_gc,
211 ))
212 }
213
214 fn serialized_storage<'a>(
215 data: StructuredData<'a, '_>,
216 ) -> &'a mut Option<HashMap<DomPointId, Self::Data>> {
217 match data {
218 StructuredData::Reader(r) => &mut r.points,
219 StructuredData::Writer(w) => &mut w.points,
220 }
221 }
222}