zng_webrender_api/
units.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 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
15pub use app_units::Au;
16use euclid::{Length, Rect, Scale, Size2D, Transform3D, Translation2D};
17use euclid::{Point2D, Point3D, Vector2D, Vector3D, SideOffsets2D, Box2D};
18use euclid::HomogeneousVector;
19use peek_poke::PeekPoke;
20// local imports
21use 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)]
26pub struct DevicePixel;
27
28pub type DeviceIntRect = Box2D<i32, DevicePixel>;
29pub type DeviceIntPoint = Point2D<i32, DevicePixel>;
30pub type DeviceIntSize = Size2D<i32, DevicePixel>;
31pub type DeviceIntLength = Length<i32, DevicePixel>;
32pub type DeviceIntSideOffsets = SideOffsets2D<i32, DevicePixel>;
33pub type DeviceIntVector2D = Vector2D<i32, DevicePixel>;
34
35pub type DeviceRect = Box2D<f32, DevicePixel>;
36pub type DeviceBox2D = Box2D<f32, DevicePixel>;
37pub type DevicePoint = Point2D<f32, DevicePixel>;
38pub type DeviceVector2D = Vector2D<f32, DevicePixel>;
39pub type DeviceSize = Size2D<f32, DevicePixel>;
40pub type DeviceHomogeneousVector = HomogeneousVector<f32, DevicePixel>;
41
42/// Geometry in the coordinate system of the framebuffer in physical pixels.
43/// It's Y-flipped comparing to DevicePixel.
44#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
45pub struct FramebufferPixel;
46
47pub type FramebufferIntPoint = Point2D<i32, FramebufferPixel>;
48pub type FramebufferIntSize = Size2D<i32, FramebufferPixel>;
49pub type FramebufferIntRect = Box2D<i32, FramebufferPixel>;
50
51/// Geometry in the coordinate system of a Picture.
52#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
53pub struct PicturePixel;
54
55pub type PictureIntRect = Box2D<i32, PicturePixel>;
56pub type PictureIntPoint = Point2D<i32, PicturePixel>;
57pub type PictureIntSize = Size2D<i32, PicturePixel>;
58pub type PictureRect = Box2D<f32, PicturePixel>;
59pub type PicturePoint = Point2D<f32, PicturePixel>;
60pub type PictureSize = Size2D<f32, PicturePixel>;
61pub type PicturePoint3D = Point3D<f32, PicturePixel>;
62pub type PictureVector2D = Vector2D<f32, PicturePixel>;
63pub type PictureVector3D = Vector3D<f32, PicturePixel>;
64pub type PictureBox2D = Box2D<f32, PicturePixel>;
65
66/// Geometry gets rasterized in a given root coordinate space. This
67/// is often the root spatial node (world space), but may be a local
68/// space for a variety of reasons (e.g. perspective).
69#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
70pub struct RasterPixel;
71
72pub type RasterIntRect = Box2D<i32, RasterPixel>;
73pub type RasterIntPoint = Point2D<i32, RasterPixel>;
74pub type RasterIntSize = Size2D<i32, RasterPixel>;
75pub type RasterRect = Box2D<f32, RasterPixel>;
76pub type RasterPoint = Point2D<f32, RasterPixel>;
77pub type RasterSize = Size2D<f32, RasterPixel>;
78pub type RasterPoint3D = Point3D<f32, RasterPixel>;
79pub type RasterVector2D = Vector2D<f32, RasterPixel>;
80pub type RasterVector3D = Vector3D<f32, RasterPixel>;
81
82/// Geometry in a stacking context's local coordinate space (logical pixels).
83#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize, PeekPoke)]
84pub struct LayoutPixel;
85
86pub type LayoutRect = Box2D<f32, LayoutPixel>;
87pub type LayoutPoint = Point2D<f32, LayoutPixel>;
88pub type LayoutPoint3D = Point3D<f32, LayoutPixel>;
89pub type LayoutVector2D = Vector2D<f32, LayoutPixel>;
90pub type LayoutVector3D = Vector3D<f32, LayoutPixel>;
91pub type LayoutSize = Size2D<f32, LayoutPixel>;
92pub type LayoutSideOffsets = SideOffsets2D<f32, LayoutPixel>;
93
94pub type LayoutIntRect = Box2D<i32, LayoutPixel>;
95pub type LayoutIntPoint = Point2D<i32, LayoutPixel>;
96pub type LayoutIntSize = Size2D<i32, LayoutPixel>;
97
98/// Geometry in the document's coordinate space (logical pixels).
99#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
100pub struct WorldPixel;
101
102pub type WorldRect = Box2D<f32, WorldPixel>;
103pub type WorldIntRect = Box2D<i32, WorldPixel>;
104pub type WorldPoint = Point2D<f32, WorldPixel>;
105pub type WorldSize = Size2D<f32, WorldPixel>;
106pub type WorldPoint3D = Point3D<f32, WorldPixel>;
107pub type WorldVector2D = Vector2D<f32, WorldPixel>;
108pub type WorldVector3D = Vector3D<f32, WorldPixel>;
109
110/// Geometry in the space in which we decided to perform visibility/clipping/invalidation
111/// calculations.
112/// This is intended to be a temporary type while transitioning some calculation from world
113/// to raster space.
114#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize, PeekPoke)]
115pub struct VisPixel;
116
117pub type VisRect = Box2D<f32, VisPixel>;
118
119/// TODO: Remove this once visibility rects have moved to raster space.
120pub fn vis_rect_as_world(r: VisRect) -> WorldRect {
121    r.cast_unit()
122}
123
124
125/// Offset in number of tiles.
126#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
127pub struct Tiles;
128pub type TileOffset = Point2D<i32, Tiles>;
129pub type TileRange = Box2D<i32, Tiles>;
130
131/// Scaling ratio from world pixels to device pixels.
132pub type DevicePixelScale = Scale<f32, WorldPixel, DevicePixel>;
133/// Scaling ratio from layout to world. Used for cases where we know the layout
134/// is in world space, or specifically want to treat it this way.
135pub type LayoutToWorldScale = Scale<f32, LayoutPixel, WorldPixel>;
136/// A complete scaling ratio from layout space to device pixel space.
137pub type LayoutToDeviceScale = Scale<f32, LayoutPixel, DevicePixel>;
138
139pub type LayoutTransform = Transform3D<f32, LayoutPixel, LayoutPixel>;
140pub type LayoutToWorldTransform = Transform3D<f32, LayoutPixel, WorldPixel>;
141pub type WorldToLayoutTransform = Transform3D<f32, WorldPixel, LayoutPixel>;
142pub type LayoutToVisTransform = Transform3D<f32, LayoutPixel, VisPixel>;
143
144pub type LayoutToPictureTransform = Transform3D<f32, LayoutPixel, PicturePixel>;
145pub type PictureToLayoutTransform = Transform3D<f32, PicturePixel, LayoutPixel>;
146
147pub type LayoutToRasterTransform = Transform3D<f32, LayoutPixel, RasterPixel>;
148pub type RasterToLayoutTransform = Transform3D<f32, RasterPixel, LayoutPixel>;
149
150pub type PictureToRasterTransform = Transform3D<f32, PicturePixel, RasterPixel>;
151pub type RasterToPictureTransform = Transform3D<f32, RasterPixel, PicturePixel>;
152
153/// Scaling ratio from picture pixels to raster pixels (e.g. if scaling a picture surface up/down).
154pub type RasterPixelScale = Scale<f32, PicturePixel, RasterPixel>;
155
156// Fixed position coordinates, to avoid float precision errors.
157pub type LayoutPointAu = Point2D<Au, LayoutPixel>;
158pub type LayoutRectAu = Box2D<Au, LayoutPixel>;
159pub type LayoutSizeAu = Size2D<Au, LayoutPixel>;
160pub type LayoutVector2DAu = Vector2D<Au, LayoutPixel>;
161pub type LayoutSideOffsetsAu = SideOffsets2D<Au, LayoutPixel>;
162
163pub type ImageDirtyRect = DirtyRect<i32, DevicePixel>;
164pub type BlobDirtyRect = DirtyRect<i32, LayoutPixel>;
165
166pub type BlobToDeviceTranslation = Translation2D<i32, LayoutPixel, DevicePixel>;
167
168/// Stores two coordinates in texel space. The coordinates
169/// are stored in texel coordinates because the texture atlas
170/// may grow. Storing them as texel coords and normalizing
171/// the UVs in the vertex shader means nothing needs to be
172/// updated on the CPU when the texture size changes.
173#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
174#[repr(C)]
175pub struct TexelRect {
176    pub uv0: DevicePoint,
177    pub uv1: DevicePoint,
178}
179
180impl TexelRect {
181    pub fn new(u0: f32, v0: f32, u1: f32, v1: f32) -> Self {
182        TexelRect {
183            uv0: DevicePoint::new(u0, v0),
184            uv1: DevicePoint::new(u1, v1),
185        }
186    }
187
188    pub fn invalid() -> Self {
189        TexelRect {
190            uv0: DevicePoint::new(-1.0, -1.0),
191            uv1: DevicePoint::new(-1.0, -1.0),
192        }
193    }
194}
195
196impl Into<TexelRect> for DeviceIntRect {
197    fn into(self) -> TexelRect {
198        TexelRect {
199            uv0: self.min.to_f32(),
200            uv1: self.max.to_f32(),
201        }
202    }
203}
204
205const MAX_AU_FLOAT: f32 = 1.0e6;
206
207pub trait AuHelpers<T> {
208    fn from_au(data: T) -> Self;
209    fn to_au(&self) -> T;
210}
211
212impl AuHelpers<LayoutSizeAu> for LayoutSize {
213    fn from_au(size: LayoutSizeAu) -> Self {
214        LayoutSize::new(
215            size.width.to_f32_px(),
216            size.height.to_f32_px(),
217        )
218    }
219
220    fn to_au(&self) -> LayoutSizeAu {
221        let width = self.width.min(2.0 * MAX_AU_FLOAT);
222        let height = self.height.min(2.0 * MAX_AU_FLOAT);
223
224        LayoutSizeAu::new(
225            Au::from_f32_px(width),
226            Au::from_f32_px(height),
227        )
228    }
229}
230
231impl AuHelpers<LayoutVector2DAu> for LayoutVector2D {
232    fn from_au(size: LayoutVector2DAu) -> Self {
233        LayoutVector2D::new(
234            size.x.to_f32_px(),
235            size.y.to_f32_px(),
236        )
237    }
238
239    fn to_au(&self) -> LayoutVector2DAu {
240        LayoutVector2DAu::new(
241            Au::from_f32_px(self.x),
242            Au::from_f32_px(self.y),
243        )
244    }
245}
246
247impl AuHelpers<LayoutPointAu> for LayoutPoint {
248    fn from_au(point: LayoutPointAu) -> Self {
249        LayoutPoint::new(
250            point.x.to_f32_px(),
251            point.y.to_f32_px(),
252        )
253    }
254
255    fn to_au(&self) -> LayoutPointAu {
256        let x = self.x.clamp(-MAX_AU_FLOAT, MAX_AU_FLOAT);
257        let y = self.y.clamp(-MAX_AU_FLOAT, MAX_AU_FLOAT);
258
259        LayoutPointAu::new(
260            Au::from_f32_px(x),
261            Au::from_f32_px(y),
262        )
263    }
264}
265
266impl AuHelpers<LayoutRectAu> for LayoutRect {
267    fn from_au(rect: LayoutRectAu) -> Self {
268        LayoutRect {
269            min: LayoutPoint::from_au(rect.min),
270            max: LayoutPoint::from_au(rect.max),
271        }
272    }
273
274    fn to_au(&self) -> LayoutRectAu {
275        LayoutRectAu {
276            min: self.min.to_au(),
277            max: self.max.to_au(),
278        }
279    }
280}
281
282impl AuHelpers<LayoutSideOffsetsAu> for LayoutSideOffsets {
283    fn from_au(offsets: LayoutSideOffsetsAu) -> Self {
284        LayoutSideOffsets::new(
285            offsets.top.to_f32_px(),
286            offsets.right.to_f32_px(),
287            offsets.bottom.to_f32_px(),
288            offsets.left.to_f32_px(),
289        )
290    }
291
292    fn to_au(&self) -> LayoutSideOffsetsAu {
293        LayoutSideOffsetsAu::new(
294            Au::from_f32_px(self.top),
295            Au::from_f32_px(self.right),
296            Au::from_f32_px(self.bottom),
297            Au::from_f32_px(self.left),
298        )
299    }
300}
301
302pub trait RectExt {
303    type Point;
304    fn top_left(&self) -> Self::Point;
305    fn top_right(&self) -> Self::Point;
306    fn bottom_left(&self) -> Self::Point;
307    fn bottom_right(&self) -> Self::Point;
308}
309
310impl<U> RectExt for Rect<f32, U> {
311    type Point = Point2D<f32, U>;
312    fn top_left(&self) -> Self::Point {
313        self.min()
314    }
315    fn top_right(&self) -> Self::Point {
316        Point2D::new(self.max_x(), self.min_y())
317    }
318    fn bottom_left(&self) -> Self::Point {
319        Point2D::new(self.min_x(), self.max_y())
320    }
321    fn bottom_right(&self) -> Self::Point {
322        self.max()
323    }
324}
325
326impl<U> RectExt for Box2D<f32, U> {
327    type Point = Point2D<f32, U>;
328    fn top_left(&self) -> Self::Point {
329        self.min
330    }
331    fn top_right(&self) -> Self::Point {
332        Point2D::new(self.max.x, self.min.y)
333    }
334    fn bottom_left(&self) -> Self::Point {
335        Point2D::new(self.min.x, self.max.y)
336    }
337    fn bottom_right(&self) -> Self::Point {
338        self.max
339    }
340}
341
342// A few helpers to convert to cast between coordinate spaces that are often equivalent.
343
344#[inline]
345pub fn layout_rect_as_picture_rect(layout_rect: &LayoutRect) -> PictureRect {
346    layout_rect.cast_unit()
347}
348
349#[inline]
350pub fn layout_vector_as_picture_vector(layout_vector: LayoutVector2D) -> PictureVector2D {
351    layout_vector.cast_unit()
352}
353
354#[inline]
355pub fn device_size_as_framebuffer_size(framebuffer_size: DeviceIntSize) -> FramebufferIntSize {
356    framebuffer_size.cast_unit()
357}
358
359#[inline]
360pub fn device_rect_as_framebuffer_rect(framebuffer_rect: &DeviceIntRect) -> FramebufferIntRect {
361    framebuffer_rect.cast_unit()
362}