units.rs (12879B)
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 = Box2D<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 pub type DeviceIntVector2D = Vector2D<i32, DevicePixel>; 34 35 pub type DeviceRect = Box2D<f32, DevicePixel>; 36 pub type DeviceBox2D = Box2D<f32, DevicePixel>; 37 pub type DevicePoint = Point2D<f32, DevicePixel>; 38 pub type DeviceVector2D = Vector2D<f32, DevicePixel>; 39 pub type DeviceSize = Size2D<f32, DevicePixel>; 40 pub 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)] 45 pub struct FramebufferPixel; 46 47 pub type FramebufferIntPoint = Point2D<i32, FramebufferPixel>; 48 pub type FramebufferIntSize = Size2D<i32, FramebufferPixel>; 49 pub 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)] 53 pub struct PicturePixel; 54 55 pub type PictureIntRect = Box2D<i32, PicturePixel>; 56 pub type PictureIntPoint = Point2D<i32, PicturePixel>; 57 pub type PictureIntSize = Size2D<i32, PicturePixel>; 58 pub type PictureRect = Box2D<f32, PicturePixel>; 59 pub type PicturePoint = Point2D<f32, PicturePixel>; 60 pub type PictureSize = Size2D<f32, PicturePixel>; 61 pub type PicturePoint3D = Point3D<f32, PicturePixel>; 62 pub type PictureVector2D = Vector2D<f32, PicturePixel>; 63 pub type PictureVector3D = Vector3D<f32, PicturePixel>; 64 pub 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)] 70 pub struct RasterPixel; 71 72 pub type RasterIntRect = Box2D<i32, RasterPixel>; 73 pub type RasterIntPoint = Point2D<i32, RasterPixel>; 74 pub type RasterIntSize = Size2D<i32, RasterPixel>; 75 pub type RasterRect = Box2D<f32, RasterPixel>; 76 pub type RasterPoint = Point2D<f32, RasterPixel>; 77 pub type RasterSize = Size2D<f32, RasterPixel>; 78 pub type RasterPoint3D = Point3D<f32, RasterPixel>; 79 pub type RasterVector2D = Vector2D<f32, RasterPixel>; 80 pub 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)] 84 pub struct LayoutPixel; 85 86 pub type LayoutRect = Box2D<f32, LayoutPixel>; 87 pub type LayoutPoint = Point2D<f32, LayoutPixel>; 88 pub type LayoutPoint3D = Point3D<f32, LayoutPixel>; 89 pub type LayoutVector2D = Vector2D<f32, LayoutPixel>; 90 pub type LayoutVector3D = Vector3D<f32, LayoutPixel>; 91 pub type LayoutSize = Size2D<f32, LayoutPixel>; 92 pub type LayoutSideOffsets = SideOffsets2D<f32, LayoutPixel>; 93 94 pub type LayoutIntRect = Box2D<i32, LayoutPixel>; 95 pub type LayoutIntPoint = Point2D<i32, LayoutPixel>; 96 pub 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)] 100 pub struct WorldPixel; 101 102 pub type WorldRect = Box2D<f32, WorldPixel>; 103 pub type WorldIntRect = Box2D<i32, WorldPixel>; 104 pub type WorldPoint = Point2D<f32, WorldPixel>; 105 pub type WorldSize = Size2D<f32, WorldPixel>; 106 pub type WorldPoint3D = Point3D<f32, WorldPixel>; 107 pub type WorldVector2D = Vector2D<f32, WorldPixel>; 108 pub 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)] 115 pub struct VisPixel; 116 117 pub type VisRect = Box2D<f32, VisPixel>; 118 119 /// TODO: Remove this once visibility rects have moved to raster space. 120 pub 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)] 127 pub struct Tiles; 128 pub type TileOffset = Point2D<i32, Tiles>; 129 pub type TileRange = Box2D<i32, Tiles>; 130 131 /// Scaling ratio from world pixels to device pixels. 132 pub 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. 135 pub type LayoutToWorldScale = Scale<f32, LayoutPixel, WorldPixel>; 136 /// A complete scaling ratio from layout space to device pixel space. 137 pub type LayoutToDeviceScale = Scale<f32, LayoutPixel, DevicePixel>; 138 139 pub type LayoutTransform = Transform3D<f32, LayoutPixel, LayoutPixel>; 140 pub type LayoutToWorldTransform = Transform3D<f32, LayoutPixel, WorldPixel>; 141 pub type WorldToLayoutTransform = Transform3D<f32, WorldPixel, LayoutPixel>; 142 pub type LayoutToVisTransform = Transform3D<f32, LayoutPixel, VisPixel>; 143 144 pub type LayoutToPictureTransform = Transform3D<f32, LayoutPixel, PicturePixel>; 145 pub type PictureToLayoutTransform = Transform3D<f32, PicturePixel, LayoutPixel>; 146 147 pub type LayoutToRasterTransform = Transform3D<f32, LayoutPixel, RasterPixel>; 148 pub type RasterToLayoutTransform = Transform3D<f32, RasterPixel, LayoutPixel>; 149 150 pub type PictureToRasterTransform = Transform3D<f32, PicturePixel, RasterPixel>; 151 pub 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). 154 pub type RasterPixelScale = Scale<f32, PicturePixel, RasterPixel>; 155 156 // Fixed position coordinates, to avoid float precision errors. 157 pub type LayoutPointAu = Point2D<Au, LayoutPixel>; 158 pub type LayoutRectAu = Box2D<Au, LayoutPixel>; 159 pub type LayoutSizeAu = Size2D<Au, LayoutPixel>; 160 pub type LayoutVector2DAu = Vector2D<Au, LayoutPixel>; 161 pub type LayoutSideOffsetsAu = SideOffsets2D<Au, LayoutPixel>; 162 163 pub type ImageDirtyRect = DirtyRect<i32, DevicePixel>; 164 pub type BlobDirtyRect = DirtyRect<i32, LayoutPixel>; 165 166 pub 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)] 175 pub struct TexelRect { 176 pub uv0: DevicePoint, 177 pub uv1: DevicePoint, 178 } 179 180 impl 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 pub fn to_array(&self) -> [f32; 4] { 196 [ 197 self.uv0.x, 198 self.uv0.y, 199 self.uv1.x, 200 self.uv1.y, 201 ] 202 } 203 } 204 205 impl Into<TexelRect> for DeviceIntRect { 206 fn into(self) -> TexelRect { 207 TexelRect { 208 uv0: self.min.to_f32(), 209 uv1: self.max.to_f32(), 210 } 211 } 212 } 213 214 const MAX_AU_FLOAT: f32 = 1.0e6; 215 216 pub trait AuHelpers<T> { 217 fn from_au(data: T) -> Self; 218 fn to_au(&self) -> T; 219 } 220 221 impl AuHelpers<LayoutSizeAu> for LayoutSize { 222 fn from_au(size: LayoutSizeAu) -> Self { 223 LayoutSize::new( 224 size.width.to_f32_px(), 225 size.height.to_f32_px(), 226 ) 227 } 228 229 fn to_au(&self) -> LayoutSizeAu { 230 let width = self.width.min(2.0 * MAX_AU_FLOAT); 231 let height = self.height.min(2.0 * MAX_AU_FLOAT); 232 233 LayoutSizeAu::new( 234 Au::from_f32_px(width), 235 Au::from_f32_px(height), 236 ) 237 } 238 } 239 240 impl AuHelpers<LayoutVector2DAu> for LayoutVector2D { 241 fn from_au(size: LayoutVector2DAu) -> Self { 242 LayoutVector2D::new( 243 size.x.to_f32_px(), 244 size.y.to_f32_px(), 245 ) 246 } 247 248 fn to_au(&self) -> LayoutVector2DAu { 249 LayoutVector2DAu::new( 250 Au::from_f32_px(self.x), 251 Au::from_f32_px(self.y), 252 ) 253 } 254 } 255 256 impl AuHelpers<LayoutPointAu> for LayoutPoint { 257 fn from_au(point: LayoutPointAu) -> Self { 258 LayoutPoint::new( 259 point.x.to_f32_px(), 260 point.y.to_f32_px(), 261 ) 262 } 263 264 fn to_au(&self) -> LayoutPointAu { 265 let x = self.x.clamp(-MAX_AU_FLOAT, MAX_AU_FLOAT); 266 let y = self.y.clamp(-MAX_AU_FLOAT, MAX_AU_FLOAT); 267 268 LayoutPointAu::new( 269 Au::from_f32_px(x), 270 Au::from_f32_px(y), 271 ) 272 } 273 } 274 275 impl AuHelpers<LayoutRectAu> for LayoutRect { 276 fn from_au(rect: LayoutRectAu) -> Self { 277 LayoutRect { 278 min: LayoutPoint::from_au(rect.min), 279 max: LayoutPoint::from_au(rect.max), 280 } 281 } 282 283 fn to_au(&self) -> LayoutRectAu { 284 LayoutRectAu { 285 min: self.min.to_au(), 286 max: self.max.to_au(), 287 } 288 } 289 } 290 291 impl AuHelpers<LayoutSideOffsetsAu> for LayoutSideOffsets { 292 fn from_au(offsets: LayoutSideOffsetsAu) -> Self { 293 LayoutSideOffsets::new( 294 offsets.top.to_f32_px(), 295 offsets.right.to_f32_px(), 296 offsets.bottom.to_f32_px(), 297 offsets.left.to_f32_px(), 298 ) 299 } 300 301 fn to_au(&self) -> LayoutSideOffsetsAu { 302 LayoutSideOffsetsAu::new( 303 Au::from_f32_px(self.top), 304 Au::from_f32_px(self.right), 305 Au::from_f32_px(self.bottom), 306 Au::from_f32_px(self.left), 307 ) 308 } 309 } 310 311 pub trait RectExt { 312 type Point; 313 fn top_left(&self) -> Self::Point; 314 fn top_right(&self) -> Self::Point; 315 fn bottom_left(&self) -> Self::Point; 316 fn bottom_right(&self) -> Self::Point; 317 } 318 319 impl<U> RectExt for Rect<f32, U> { 320 type Point = Point2D<f32, U>; 321 fn top_left(&self) -> Self::Point { 322 self.min() 323 } 324 fn top_right(&self) -> Self::Point { 325 Point2D::new(self.max_x(), self.min_y()) 326 } 327 fn bottom_left(&self) -> Self::Point { 328 Point2D::new(self.min_x(), self.max_y()) 329 } 330 fn bottom_right(&self) -> Self::Point { 331 self.max() 332 } 333 } 334 335 impl<U> RectExt for Box2D<f32, U> { 336 type Point = Point2D<f32, U>; 337 fn top_left(&self) -> Self::Point { 338 self.min 339 } 340 fn top_right(&self) -> Self::Point { 341 Point2D::new(self.max.x, self.min.y) 342 } 343 fn bottom_left(&self) -> Self::Point { 344 Point2D::new(self.min.x, self.max.y) 345 } 346 fn bottom_right(&self) -> Self::Point { 347 self.max 348 } 349 } 350 351 // A few helpers to convert to cast between coordinate spaces that are often equivalent. 352 353 #[inline] 354 pub fn layout_rect_as_picture_rect(layout_rect: &LayoutRect) -> PictureRect { 355 layout_rect.cast_unit() 356 } 357 358 #[inline] 359 pub fn layout_vector_as_picture_vector(layout_vector: LayoutVector2D) -> PictureVector2D { 360 layout_vector.cast_unit() 361 } 362 363 #[inline] 364 pub fn device_size_as_framebuffer_size(framebuffer_size: DeviceIntSize) -> FramebufferIntSize { 365 framebuffer_size.cast_unit() 366 } 367 368 #[inline] 369 pub fn device_rect_as_framebuffer_rect(framebuffer_rect: &DeviceIntRect) -> FramebufferIntRect { 370 framebuffer_rect.cast_unit() 371 }