script/dom/
domrectreadonly.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use 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    // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-domrectreadonly
96    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    // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-fromrect
111    #[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    // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-x
123    fn X(&self) -> f64 {
124        self.x.get()
125    }
126
127    // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-y
128    fn Y(&self) -> f64 {
129        self.y.get()
130    }
131
132    // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-width
133    fn Width(&self) -> f64 {
134        self.width.get()
135    }
136
137    // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-height
138    fn Height(&self) -> f64 {
139        self.height.get()
140    }
141
142    // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-top
143    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    // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-right
153    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    // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-bottom
163    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    // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-left
173    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/// <https://drafts.fxtf.org/geometry/#ref-for-create-a-domrectreadonly-from-the-dictionary>
184#[cfg_attr(crown, allow(crown::unrooted_must_root))]
185pub(super) fn create_a_domrectreadonly_from_the_dictionary(other: &DOMRectInit) -> DOMRectReadOnly {
186    // NOTE: We trivially combine all three steps into one
187
188    // Step 1. Let rect be a new DOMRectReadOnly or DOMRect as appropriate.
189
190    // Step 2. Set rect’s variables x coordinate to other’s x dictionary member, y coordinate to other’s y
191    // dictionary member, width dimension to other’s width dictionary member and height dimension to
192    // other’s height dictionary member.
193
194    // Step 3. Return rect.
195
196    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}