headless_chrome/browser/tab/element/
box_model.rs1use crate::protocol::cdp::Page;
2
3use crate::browser::tab::point::Point;
4
5#[derive(Debug, Copy, Clone)]
6pub struct ElementQuad {
7 pub top_left: Point,
8 pub top_right: Point,
9 pub bottom_left: Point,
10 pub bottom_right: Point,
11}
12
13impl ElementQuad {
14 pub fn from_raw_points(raw_quad: &[f64]) -> Self {
15 Self {
16 top_left: Point {
17 x: raw_quad[0],
18 y: raw_quad[1],
19 },
20 top_right: Point {
21 x: raw_quad[2],
22 y: raw_quad[3],
23 },
24 bottom_right: Point {
25 x: raw_quad[4],
26 y: raw_quad[5],
27 },
28 bottom_left: Point {
29 x: raw_quad[6],
30 y: raw_quad[7],
31 },
32 }
33 }
34
35 pub fn height(&self) -> f64 {
36 self.bottom_left.y - self.top_left.y
37 }
38
39 pub fn width(&self) -> f64 {
40 self.top_right.x - self.top_left.x
41 }
42
43 pub fn aspect_ratio(&self) -> f64 {
45 self.width() / self.height()
46 }
47
48 pub fn most_left(&self) -> f64 {
50 self.top_right
51 .x
52 .min(self.top_left.x)
53 .min(self.bottom_right.x)
54 .min(self.bottom_left.x)
55 }
56
57 pub fn most_right(&self) -> f64 {
59 self.top_right
60 .x
61 .max(self.top_left.x)
62 .max(self.bottom_right.x)
63 .max(self.bottom_left.x)
64 }
65
66 pub fn most_top(&self) -> f64 {
68 self.top_right
69 .y
70 .min(self.top_left.y)
71 .min(self.bottom_right.y)
72 .min(self.bottom_left.y)
73 }
74
75 fn most_bottom(&self) -> f64 {
77 self.top_right
78 .y
79 .max(self.top_left.y)
80 .max(self.bottom_right.y)
81 .max(self.bottom_left.y)
82 }
83
84 pub fn strictly_above(&self, other: &Self) -> bool {
86 self.most_bottom() < other.most_top()
87 }
88
89 pub fn above(&self, other: &Self) -> bool {
92 self.most_bottom() <= other.most_top()
93 }
94
95 pub fn strictly_below(&self, other: &Self) -> bool {
97 self.most_top() > other.most_bottom()
98 }
99
100 pub fn below(&self, other: &Self) -> bool {
103 self.most_top() >= other.most_bottom()
104 }
105
106 pub fn strictly_left_of(&self, other: &Self) -> bool {
108 self.most_right() < other.most_left()
109 }
110
111 pub fn left_of(&self, other: &Self) -> bool {
114 self.most_right() <= other.most_left()
115 }
116
117 pub fn strictly_right_of(&self, other: &Self) -> bool {
119 self.most_left() > other.most_right()
120 }
121
122 pub fn right_of(&self, other: &Self) -> bool {
125 self.most_left() >= other.most_right()
126 }
127
128 pub fn within_horizontal_bounds_of(&self, other: &Self) -> bool {
130 self.most_left() >= other.most_left() && self.most_right() <= other.most_right()
131 }
132
133 pub fn within_vertical_bounds_of(&self, other: &Self) -> bool {
135 self.most_top() >= other.most_top() && self.most_bottom() <= other.most_bottom()
136 }
137
138 pub fn within_bounds_of(&self, other: &Self) -> bool {
140 self.within_horizontal_bounds_of(other) && self.within_vertical_bounds_of(other)
141 }
142}
143
144#[derive(Debug, Clone)]
145pub struct BoxModel {
146 pub content: ElementQuad,
147 pub padding: ElementQuad,
148 pub border: ElementQuad,
149 pub margin: ElementQuad,
150 pub width: f64,
151 pub height: f64,
152}
153
154impl BoxModel {
155 pub fn content_viewport(&self) -> Page::Viewport {
157 Page::Viewport {
158 x: self.content.top_left.x,
159 y: self.content.top_left.y,
160 width: self.content.width(),
161 height: self.content.height(),
162 scale: 1.0,
163 }
164 }
165
166 pub fn padding_viewport(&self) -> Page::Viewport {
168 Page::Viewport {
169 x: self.padding.top_left.x,
170 y: self.padding.top_left.y,
171 width: self.padding.width(),
172 height: self.padding.height(),
173 scale: 1.0,
174 }
175 }
176
177 pub fn border_viewport(&self) -> Page::Viewport {
179 Page::Viewport {
180 x: self.border.top_left.x,
181 y: self.border.top_left.y,
182 width: self.border.width(),
183 height: self.border.height(),
184 scale: 1.0,
185 }
186 }
187
188 pub fn margin_viewport(&self) -> Page::Viewport {
190 Page::Viewport {
191 x: self.margin.top_left.x,
192 y: self.margin.top_left.y,
193 width: self.margin.width(),
194 height: self.margin.height(),
195 scale: 1.0,
196 }
197 }
198}