Skip to main content

script/dom/geometry/
domrect.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 dom_struct::dom_struct;
6use js::context::JSContext;
7use js::rust::HandleObject;
8use rustc_hash::FxHashMap;
9use script_bindings::reflector::{
10    reflect_dom_object_with_cx, reflect_dom_object_with_proto_and_cx,
11};
12use servo_base::id::{DomRectId, DomRectIndex};
13use servo_constellation_traits::DomRect;
14
15use crate::dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
16use crate::dom::bindings::codegen::Bindings::DOMRectReadOnlyBinding::{
17    DOMRectInit, DOMRectReadOnlyMethods,
18};
19use crate::dom::bindings::error::Fallible;
20use crate::dom::bindings::root::DomRoot;
21use crate::dom::bindings::serializable::Serializable;
22use crate::dom::bindings::structuredclone::StructuredData;
23use crate::dom::domrectreadonly::{DOMRectReadOnly, create_a_domrectreadonly_from_the_dictionary};
24use crate::dom::globalscope::GlobalScope;
25
26#[dom_struct]
27pub(crate) struct DOMRect {
28    rect: DOMRectReadOnly,
29}
30
31impl DOMRect {
32    fn new_inherited(x: f64, y: f64, width: f64, height: f64) -> DOMRect {
33        DOMRect {
34            rect: DOMRectReadOnly::new_inherited(x, y, width, height),
35        }
36    }
37
38    pub(crate) fn new(
39        cx: &mut JSContext,
40        global: &GlobalScope,
41        x: f64,
42        y: f64,
43        width: f64,
44        height: f64,
45    ) -> DomRoot<DOMRect> {
46        Self::new_with_proto(cx, global, None, x, y, width, height)
47    }
48
49    fn new_with_proto(
50        cx: &mut JSContext,
51        global: &GlobalScope,
52        proto: Option<HandleObject>,
53        x: f64,
54        y: f64,
55        width: f64,
56        height: f64,
57    ) -> DomRoot<DOMRect> {
58        reflect_dom_object_with_proto_and_cx(
59            Box::new(DOMRect::new_inherited(x, y, width, height)),
60            global,
61            proto,
62            cx,
63        )
64    }
65}
66
67impl DOMRectMethods<crate::DomTypeHolder> for DOMRect {
68    /// <https://drafts.fxtf.org/geometry/#dom-domrect-domrect>
69    fn Constructor(
70        cx: &mut JSContext,
71        global: &GlobalScope,
72        proto: Option<HandleObject>,
73        x: f64,
74        y: f64,
75        width: f64,
76        height: f64,
77    ) -> Fallible<DomRoot<DOMRect>> {
78        Ok(DOMRect::new_with_proto(
79            cx, global, proto, x, y, width, height,
80        ))
81    }
82
83    // https://drafts.fxtf.org/geometry/#dom-domrect-fromrect
84    #[cfg_attr(crown, expect(crown::unrooted_must_root))]
85    fn FromRect(cx: &mut JSContext, global: &GlobalScope, other: &DOMRectInit) -> DomRoot<DOMRect> {
86        let rect = create_a_domrectreadonly_from_the_dictionary(other);
87
88        reflect_dom_object_with_cx(Box::new(Self { rect }), global, cx)
89    }
90
91    /// <https://drafts.fxtf.org/geometry/#dom-domrect-x>
92    fn X(&self) -> f64 {
93        self.rect.X()
94    }
95
96    /// <https://drafts.fxtf.org/geometry/#dom-domrect-x>
97    fn SetX(&self, value: f64) {
98        self.rect.set_x(value);
99    }
100
101    /// <https://drafts.fxtf.org/geometry/#dom-domrect-y>
102    fn Y(&self) -> f64 {
103        self.rect.Y()
104    }
105
106    /// <https://drafts.fxtf.org/geometry/#dom-domrect-y>
107    fn SetY(&self, value: f64) {
108        self.rect.set_y(value);
109    }
110
111    /// <https://drafts.fxtf.org/geometry/#dom-domrect-width>
112    fn Width(&self) -> f64 {
113        self.rect.Width()
114    }
115
116    /// <https://drafts.fxtf.org/geometry/#dom-domrect-width>
117    fn SetWidth(&self, value: f64) {
118        self.rect.set_width(value);
119    }
120
121    /// <https://drafts.fxtf.org/geometry/#dom-domrect-height>
122    fn Height(&self) -> f64 {
123        self.rect.Height()
124    }
125
126    /// <https://drafts.fxtf.org/geometry/#dom-domrect-height>
127    fn SetHeight(&self, value: f64) {
128        self.rect.set_height(value);
129    }
130}
131
132impl Serializable for DOMRect {
133    type Index = DomRectIndex;
134    type Data = DomRect;
135
136    fn serialize(&self) -> Result<(DomRectId, Self::Data), ()> {
137        let serialized = DomRect {
138            x: self.X(),
139            y: self.Y(),
140            width: self.Width(),
141            height: self.Height(),
142        };
143        Ok((DomRectId::new(), serialized))
144    }
145
146    fn deserialize(
147        cx: &mut JSContext,
148        owner: &GlobalScope,
149        serialized: Self::Data,
150    ) -> Result<DomRoot<Self>, ()>
151    where
152        Self: Sized,
153    {
154        Ok(Self::new(
155            cx,
156            owner,
157            serialized.x,
158            serialized.y,
159            serialized.width,
160            serialized.height,
161        ))
162    }
163
164    fn serialized_storage<'a>(
165        data: StructuredData<'a, '_>,
166    ) -> &'a mut Option<FxHashMap<DomRectId, Self::Data>> {
167        match data {
168            StructuredData::Reader(reader) => &mut reader.rects,
169            StructuredData::Writer(writer) => &mut writer.rects,
170        }
171    }
172}