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 http://mozilla.org/MPL/2.0/. */
4
5 //! A collection of coordinate spaces and their corresponding Point, Size and Rect types.
6 //!
7 //! Physical pixels take into account the device pixel ratio and their dimensions tend
8 //! to correspond to the allocated size of resources in memory, while logical pixels
9 //! don't have the device pixel ratio applied which means they are agnostic to the usage
10 //! of hidpi screens and the like.
11 //!
12 //! The terms "layer" and "stacking context" can be used interchangeably
13 //! in the context of coordinate systems.
14
15 pub use app_units::Au;
16 use euclid::{Length, Rect, Scale, Size2D, Transform3D, Translation2D};
17 use euclid::{Point2D, Point3D, Vector2D, Vector3D, SideOffsets2D, Box2D};
18 use euclid::HomogeneousVector;
19 use peek_poke::PeekPoke;
20 // local imports
21 use crate::image::DirtyRect;
22
23 /// Geometry in the coordinate system of the render target (screen or intermediate
24 /// surface) in physical pixels.
25 #[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
26 pub struct DevicePixel;
27
28 pub type DeviceIntRect = Rect<i32, DevicePixel>;
29 pub type DeviceIntPoint = Point2D<i32, DevicePixel>;
30 pub type DeviceIntSize = Size2D<i32, DevicePixel>;
31 pub type DeviceIntLength = Length<i32, DevicePixel>;
32 pub type DeviceIntSideOffsets = SideOffsets2D<i32, DevicePixel>;
33
34 pub type DeviceRect = Rect<f32, DevicePixel>;
35 pub type DevicePoint = Point2D<f32, DevicePixel>;
36 pub type DeviceVector2D = Vector2D<f32, DevicePixel>;
37 pub type DeviceSize = Size2D<f32, DevicePixel>;
38 pub type DeviceHomogeneousVector = HomogeneousVector<f32, DevicePixel>;
39
40 /// Geometry in the coordinate system of the framebuffer in physical pixels.
41 /// It's Y-flipped comparing to DevicePixel.
42 #[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
43 pub struct FramebufferPixel;
44
45 pub type FramebufferIntPoint = Point2D<i32, FramebufferPixel>;
46 pub type FramebufferIntSize = Size2D<i32, FramebufferPixel>;
47 pub type FramebufferIntRect = Rect<i32, FramebufferPixel>;
48
49 /// Geometry in the coordinate system of a Picture (intermediate
50 /// surface) in physical pixels.
51 #[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
52 pub struct PicturePixel;
53
54 pub type PictureIntRect = Rect<i32, PicturePixel>;
55 pub type PictureIntPoint = Point2D<i32, PicturePixel>;
56 pub type PictureIntSize = Size2D<i32, PicturePixel>;
57 pub type PictureRect = Rect<f32, PicturePixel>;
58 pub type PicturePoint = Point2D<f32, PicturePixel>;
59 pub type PictureSize = Size2D<f32, PicturePixel>;
60 pub type PicturePoint3D = Point3D<f32, PicturePixel>;
61 pub type PictureVector2D = Vector2D<f32, PicturePixel>;
62 pub type PictureVector3D = Vector3D<f32, PicturePixel>;
63 pub type PictureBox2D = Box2D<f32, PicturePixel>;
64
65 /// Geometry gets rasterized in a given root coordinate space. This
66 /// is often the root spatial node (world space), but may be a local
67 /// space for a variety of reasons (e.g. perspective).
68 #[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
69 pub struct RasterPixel;
70
71 pub type RasterIntRect = Rect<i32, RasterPixel>;
72 pub type RasterIntPoint = Point2D<i32, RasterPixel>;
73 pub type RasterIntSize = Size2D<i32, RasterPixel>;
74 pub type RasterRect = Rect<f32, RasterPixel>;
75 pub type RasterPoint = Point2D<f32, RasterPixel>;
76 pub type RasterSize = Size2D<f32, RasterPixel>;
77 pub type RasterPoint3D = Point3D<f32, RasterPixel>;
78 pub type RasterVector2D = Vector2D<f32, RasterPixel>;
79 pub type RasterVector3D = Vector3D<f32, RasterPixel>;
80
81 /// Geometry in a stacking context's local coordinate space (logical pixels).
82 #[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize, PeekPoke)]
83 pub struct LayoutPixel;
84
85 pub type LayoutRect = Rect<f32, LayoutPixel>;
86 pub type LayoutPoint = Point2D<f32, LayoutPixel>;
87 pub type LayoutPoint3D = Point3D<f32, LayoutPixel>;
88 pub type LayoutVector2D = Vector2D<f32, LayoutPixel>;
89 pub type LayoutVector3D = Vector3D<f32, LayoutPixel>;
90 pub type LayoutSize = Size2D<f32, LayoutPixel>;
91 pub type LayoutSideOffsets = SideOffsets2D<f32, LayoutPixel>;
92
93 pub type LayoutIntRect = Rect<i32, LayoutPixel>;
94 pub type LayoutIntPoint = Point2D<i32, LayoutPixel>;
95 pub type LayoutIntSize = Size2D<i32, LayoutPixel>;
96
97 /// Geometry in the document's coordinate space (logical pixels).
98 #[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd)]
99 pub struct WorldPixel;
100
101 pub type WorldRect = Rect<f32, WorldPixel>;
102 pub type WorldPoint = Point2D<f32, WorldPixel>;
103 pub type WorldSize = Size2D<f32, WorldPixel>;
104 pub type WorldPoint3D = Point3D<f32, WorldPixel>;
105 pub type WorldVector2D = Vector2D<f32, WorldPixel>;
106 pub type WorldVector3D = Vector3D<f32, WorldPixel>;
107
108 /// Offset in number of tiles.
109 #[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
110 pub struct Tiles;
111 pub type TileOffset = Point2D<i32, Tiles>;
112 pub type TileRange = Rect<i32, Tiles>;
113
114 /// Scaling ratio from world pixels to device pixels.
115 pub type DevicePixelScale = Scale<f32, WorldPixel, DevicePixel>;
116 /// Scaling ratio from layout to world. Used for cases where we know the layout
117 /// is in world space, or specifically want to treat it this way.
118 pub type LayoutToWorldScale = Scale<f32, LayoutPixel, WorldPixel>;
119 /// A complete scaling ratio from layout space to device pixel space.
120 pub type LayoutToDeviceScale = Scale<f32, LayoutPixel, DevicePixel>;
121
122 pub type LayoutTransform = Transform3D<f32, LayoutPixel, LayoutPixel>;
123 pub type LayoutToWorldTransform = Transform3D<f32, LayoutPixel, WorldPixel>;
124 pub type WorldToLayoutTransform = Transform3D<f32, WorldPixel, LayoutPixel>;
125
126 pub type LayoutToPictureTransform = Transform3D<f32, LayoutPixel, PicturePixel>;
127 pub type PictureToLayoutTransform = Transform3D<f32, PicturePixel, LayoutPixel>;
128
129 pub type LayoutToRasterTransform = Transform3D<f32, LayoutPixel, RasterPixel>;
130 pub type RasterToLayoutTransform = Transform3D<f32, RasterPixel, LayoutPixel>;
131
132 pub type PictureToRasterTransform = Transform3D<f32, PicturePixel, RasterPixel>;
133 pub type RasterToPictureTransform = Transform3D<f32, RasterPixel, PicturePixel>;
134
135 // Fixed position coordinates, to avoid float precision errors.
136 pub type LayoutPointAu = Point2D<Au, LayoutPixel>;
137 pub type LayoutRectAu = Rect<Au, LayoutPixel>;
138 pub type LayoutSizeAu = Size2D<Au, LayoutPixel>;
139 pub type LayoutVector2DAu = Vector2D<Au, LayoutPixel>;
140 pub type LayoutSideOffsetsAu = SideOffsets2D<Au, LayoutPixel>;
141
142 pub type ImageDirtyRect = DirtyRect<i32, DevicePixel>;
143 pub type BlobDirtyRect = DirtyRect<i32, LayoutPixel>;
144
145 pub type BlobToDeviceTranslation = Translation2D<i32, LayoutPixel, DevicePixel>;
146
147 /// Stores two coordinates in texel space. The coordinates
148 /// are stored in texel coordinates because the texture atlas
149 /// may grow. Storing them as texel coords and normalizing
150 /// the UVs in the vertex shader means nothing needs to be
151 /// updated on the CPU when the texture size changes.
152 #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
153 pub struct TexelRect {
154 pub uv0: DevicePoint,
155 pub uv1: DevicePoint,
156 }
157
158 impl TexelRect {
new(u0: f32, v0: f32, u1: f32, v1: f32) -> Self159 pub fn new(u0: f32, v0: f32, u1: f32, v1: f32) -> Self {
160 TexelRect {
161 uv0: DevicePoint::new(u0, v0),
162 uv1: DevicePoint::new(u1, v1),
163 }
164 }
165
invalid() -> Self166 pub fn invalid() -> Self {
167 TexelRect {
168 uv0: DevicePoint::new(-1.0, -1.0),
169 uv1: DevicePoint::new(-1.0, -1.0),
170 }
171 }
172 }
173
174 impl Into<TexelRect> for DeviceIntRect {
into(self) -> TexelRect175 fn into(self) -> TexelRect {
176 TexelRect {
177 uv0: self.min().to_f32(),
178 uv1: self.max().to_f32(),
179 }
180 }
181 }
182
183 const MAX_AU_FLOAT: f32 = 1.0e6;
184
185 pub trait AuHelpers<T> {
from_au(data: T) -> Self186 fn from_au(data: T) -> Self;
to_au(&self) -> T187 fn to_au(&self) -> T;
188 }
189
190 impl AuHelpers<LayoutSizeAu> for LayoutSize {
from_au(size: LayoutSizeAu) -> Self191 fn from_au(size: LayoutSizeAu) -> Self {
192 LayoutSize::new(
193 size.width.to_f32_px(),
194 size.height.to_f32_px(),
195 )
196 }
197
to_au(&self) -> LayoutSizeAu198 fn to_au(&self) -> LayoutSizeAu {
199 let width = self.width.min(2.0 * MAX_AU_FLOAT);
200 let height = self.height.min(2.0 * MAX_AU_FLOAT);
201
202 LayoutSizeAu::new(
203 Au::from_f32_px(width),
204 Au::from_f32_px(height),
205 )
206 }
207 }
208
209 impl AuHelpers<LayoutVector2DAu> for LayoutVector2D {
from_au(size: LayoutVector2DAu) -> Self210 fn from_au(size: LayoutVector2DAu) -> Self {
211 LayoutVector2D::new(
212 size.x.to_f32_px(),
213 size.y.to_f32_px(),
214 )
215 }
216
to_au(&self) -> LayoutVector2DAu217 fn to_au(&self) -> LayoutVector2DAu {
218 LayoutVector2DAu::new(
219 Au::from_f32_px(self.x),
220 Au::from_f32_px(self.y),
221 )
222 }
223 }
224
225 impl AuHelpers<LayoutPointAu> for LayoutPoint {
from_au(point: LayoutPointAu) -> Self226 fn from_au(point: LayoutPointAu) -> Self {
227 LayoutPoint::new(
228 point.x.to_f32_px(),
229 point.y.to_f32_px(),
230 )
231 }
232
to_au(&self) -> LayoutPointAu233 fn to_au(&self) -> LayoutPointAu {
234 let x = self.x.min(MAX_AU_FLOAT).max(-MAX_AU_FLOAT);
235 let y = self.y.min(MAX_AU_FLOAT).max(-MAX_AU_FLOAT);
236
237 LayoutPointAu::new(
238 Au::from_f32_px(x),
239 Au::from_f32_px(y),
240 )
241 }
242 }
243
244 impl AuHelpers<LayoutRectAu> for LayoutRect {
from_au(rect: LayoutRectAu) -> Self245 fn from_au(rect: LayoutRectAu) -> Self {
246 LayoutRect::new(
247 LayoutPoint::from_au(rect.origin),
248 LayoutSize::from_au(rect.size),
249 )
250 }
251
to_au(&self) -> LayoutRectAu252 fn to_au(&self) -> LayoutRectAu {
253 LayoutRectAu::new(
254 self.origin.to_au(),
255 self.size.to_au(),
256 )
257 }
258 }
259
260 impl AuHelpers<LayoutSideOffsetsAu> for LayoutSideOffsets {
from_au(offsets: LayoutSideOffsetsAu) -> Self261 fn from_au(offsets: LayoutSideOffsetsAu) -> Self {
262 LayoutSideOffsets::new(
263 offsets.top.to_f32_px(),
264 offsets.right.to_f32_px(),
265 offsets.bottom.to_f32_px(),
266 offsets.left.to_f32_px(),
267 )
268 }
269
to_au(&self) -> LayoutSideOffsetsAu270 fn to_au(&self) -> LayoutSideOffsetsAu {
271 LayoutSideOffsetsAu::new(
272 Au::from_f32_px(self.top),
273 Au::from_f32_px(self.right),
274 Au::from_f32_px(self.bottom),
275 Au::from_f32_px(self.left),
276 )
277 }
278 }
279
280 pub trait RectExt {
281 type Point;
top_left(&self) -> Self::Point282 fn top_left(&self) -> Self::Point;
top_right(&self) -> Self::Point283 fn top_right(&self) -> Self::Point;
bottom_left(&self) -> Self::Point284 fn bottom_left(&self) -> Self::Point;
bottom_right(&self) -> Self::Point285 fn bottom_right(&self) -> Self::Point;
286 }
287
288 impl<U> RectExt for Rect<f32, U> {
289 type Point = Point2D<f32, U>;
top_left(&self) -> Self::Point290 fn top_left(&self) -> Self::Point {
291 self.min()
292 }
top_right(&self) -> Self::Point293 fn top_right(&self) -> Self::Point {
294 Point2D::new(self.max_x(), self.min_y())
295 }
bottom_left(&self) -> Self::Point296 fn bottom_left(&self) -> Self::Point {
297 Point2D::new(self.min_x(), self.max_y())
298 }
bottom_right(&self) -> Self::Point299 fn bottom_right(&self) -> Self::Point {
300 self.max()
301 }
302 }
303
304 // A few helpers to convert to cast between coordinate spaces that are often equivalent.
305
306 #[inline]
layout_rect_as_picture_rect(layout_rect: &LayoutRect) -> PictureRect307 pub fn layout_rect_as_picture_rect(layout_rect: &LayoutRect) -> PictureRect {
308 layout_rect.cast_unit()
309 }
310
311 #[inline]
layout_vector_as_picture_vector(layout_vector: LayoutVector2D) -> PictureVector2D312 pub fn layout_vector_as_picture_vector(layout_vector: LayoutVector2D) -> PictureVector2D {
313 layout_vector.cast_unit()
314 }
315
316 #[inline]
device_size_as_framebuffer_size(framebuffer_size: DeviceIntSize) -> FramebufferIntSize317 pub fn device_size_as_framebuffer_size(framebuffer_size: DeviceIntSize) -> FramebufferIntSize {
318 framebuffer_size.cast_unit()
319 }
320
321 #[inline]
device_rect_as_framebuffer_rect(framebuffer_rect: &DeviceIntRect) -> FramebufferIntRect322 pub fn device_rect_as_framebuffer_rect(framebuffer_rect: &DeviceIntRect) -> FramebufferIntRect {
323 framebuffer_rect.cast_unit()
324 }
325