1use std::cell::Cell;
6
7use base::id::{DomRectId, DomRectIndex};
8use constellation_traits::DomRect;
9use dom_struct::dom_struct;
10use js::rust::HandleObject;
11use rustc_hash::FxHashMap;
12
13use crate::dom::bindings::codegen::Bindings::DOMRectReadOnlyBinding::{
14 DOMRectInit, DOMRectReadOnlyMethods,
15};
16use crate::dom::bindings::error::Fallible;
17use crate::dom::bindings::reflector::{
18 Reflector, reflect_dom_object, reflect_dom_object_with_proto,
19};
20use crate::dom::bindings::root::DomRoot;
21use crate::dom::bindings::serializable::Serializable;
22use crate::dom::bindings::structuredclone::StructuredData;
23use crate::dom::globalscope::GlobalScope;
24use crate::script_runtime::CanGc;
25
26#[dom_struct]
27pub(crate) struct DOMRectReadOnly {
28 reflector_: Reflector,
29 x: Cell<f64>,
30 y: Cell<f64>,
31 width: Cell<f64>,
32 height: Cell<f64>,
33}
34
35impl DOMRectReadOnly {
36 pub(crate) fn new_inherited(x: f64, y: f64, width: f64, height: f64) -> DOMRectReadOnly {
37 DOMRectReadOnly {
38 x: Cell::new(x),
39 y: Cell::new(y),
40 width: Cell::new(width),
41 height: Cell::new(height),
42 reflector_: Reflector::new(),
43 }
44 }
45
46 pub(crate) fn new(
47 global: &GlobalScope,
48 proto: Option<HandleObject>,
49 x: f64,
50 y: f64,
51 width: f64,
52 height: f64,
53 can_gc: CanGc,
54 ) -> DomRoot<DOMRectReadOnly> {
55 reflect_dom_object_with_proto(
56 Box::new(DOMRectReadOnly::new_inherited(x, y, width, height)),
57 global,
58 proto,
59 can_gc,
60 )
61 }
62
63 pub(crate) fn new_from_dictionary(
64 global: &GlobalScope,
65 proto: Option<HandleObject>,
66 dictionary: &DOMRectInit,
67 can_gc: CanGc,
68 ) -> DomRoot<DOMRectReadOnly> {
69 reflect_dom_object_with_proto(
70 Box::new(create_a_domrectreadonly_from_the_dictionary(dictionary)),
71 global,
72 proto,
73 can_gc,
74 )
75 }
76
77 pub(crate) fn set_x(&self, value: f64) {
78 self.x.set(value);
79 }
80
81 pub(crate) fn set_y(&self, value: f64) {
82 self.y.set(value);
83 }
84
85 pub(crate) fn set_width(&self, value: f64) {
86 self.width.set(value);
87 }
88
89 pub(crate) fn set_height(&self, value: f64) {
90 self.height.set(value);
91 }
92}
93
94impl DOMRectReadOnlyMethods<crate::DomTypeHolder> for DOMRectReadOnly {
95 fn Constructor(
97 global: &GlobalScope,
98 proto: Option<HandleObject>,
99 can_gc: CanGc,
100 x: f64,
101 y: f64,
102 width: f64,
103 height: f64,
104 ) -> Fallible<DomRoot<DOMRectReadOnly>> {
105 Ok(DOMRectReadOnly::new(
106 global, proto, x, y, width, height, can_gc,
107 ))
108 }
109
110 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
112 fn FromRect(
113 global: &GlobalScope,
114 other: &DOMRectInit,
115 can_gc: CanGc,
116 ) -> DomRoot<DOMRectReadOnly> {
117 let dom_rect = create_a_domrectreadonly_from_the_dictionary(other);
118
119 reflect_dom_object(Box::new(dom_rect), global, can_gc)
120 }
121
122 fn X(&self) -> f64 {
124 self.x.get()
125 }
126
127 fn Y(&self) -> f64 {
129 self.y.get()
130 }
131
132 fn Width(&self) -> f64 {
134 self.width.get()
135 }
136
137 fn Height(&self) -> f64 {
139 self.height.get()
140 }
141
142 fn Top(&self) -> f64 {
144 let height = self.height.get();
145 if height >= 0f64 {
146 self.y.get()
147 } else {
148 self.y.get() + height
149 }
150 }
151
152 fn Right(&self) -> f64 {
154 let width = self.width.get();
155 if width < 0f64 {
156 self.x.get()
157 } else {
158 self.x.get() + width
159 }
160 }
161
162 fn Bottom(&self) -> f64 {
164 let height = self.height.get();
165 if height < 0f64 {
166 self.y.get()
167 } else {
168 self.y.get() + height
169 }
170 }
171
172 fn Left(&self) -> f64 {
174 let width = self.width.get();
175 if width >= 0f64 {
176 self.x.get()
177 } else {
178 self.x.get() + width
179 }
180 }
181}
182
183#[cfg_attr(crown, allow(crown::unrooted_must_root))]
185pub(super) fn create_a_domrectreadonly_from_the_dictionary(other: &DOMRectInit) -> DOMRectReadOnly {
186 DOMRectReadOnly {
197 reflector_: Reflector::new(),
198 x: Cell::new(other.x),
199 y: Cell::new(other.y),
200 width: Cell::new(other.width),
201 height: Cell::new(other.height),
202 }
203}
204
205type Type = DomRectId;
206
207impl Serializable for DOMRectReadOnly {
208 type Index = DomRectIndex;
209 type Data = DomRect;
210
211 fn serialize(&self) -> Result<(DomRectId, Self::Data), ()> {
212 let serialized = DomRect {
213 x: self.X(),
214 y: self.Y(),
215 width: self.Width(),
216 height: self.Height(),
217 };
218 Ok((DomRectId::new(), serialized))
219 }
220
221 fn deserialize(
222 owner: &GlobalScope,
223 serialized: Self::Data,
224 can_gc: CanGc,
225 ) -> Result<DomRoot<Self>, ()>
226 where
227 Self: Sized,
228 {
229 Ok(Self::new(
230 owner,
231 None,
232 serialized.x,
233 serialized.y,
234 serialized.width,
235 serialized.height,
236 can_gc,
237 ))
238 }
239
240 fn serialized_storage<'a>(
241 data: StructuredData<'a, '_>,
242 ) -> &'a mut Option<FxHashMap<Type, Self::Data>> {
243 match data {
244 StructuredData::Reader(reader) => &mut reader.rects,
245 StructuredData::Writer(writer) => &mut writer.rects,
246 }
247 }
248}