Skip to main content

servo_geometry/
lib.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 std::f32;
6
7use app_units::{Au, MAX_AU, MIN_AU};
8use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as UntypedSize2D};
9use euclid::{Box2D, Length, Point2D, Rect, Scale, SideOffsets2D, Size2D, Vector2D};
10use malloc_size_of_derive::MallocSizeOf;
11use webrender::FastTransform;
12use webrender_api::units::{
13    DeviceIntRect, DeviceIntSize, DevicePixel, FramebufferPixel, LayoutPixel, LayoutPoint,
14    LayoutRect, LayoutSize,
15};
16
17// Units for use with euclid::length and euclid::scale_factor.
18
19pub type FramebufferUintLength = Length<u32, FramebufferPixel>;
20
21/// A normalized "pixel" at the default resolution for the display.
22///
23/// Like the CSS "px" unit, the exact physical size of this unit may vary between devices, but it
24/// should approximate a device-independent reference length.  This unit corresponds to Android's
25/// "density-independent pixel" (dip), Mac OS X's "point", and Windows "device-independent pixel."
26///
27/// The relationship between DevicePixel and DeviceIndependentPixel is defined by the OS.  On most low-dpi
28/// screens, one DeviceIndependentPixel is equal to one DevicePixel.  But on high-density screens it can be
29/// some larger number.  For example, by default on Apple "retina" displays, one DeviceIndependentPixel equals
30/// two DevicePixels.  On Android "MDPI" displays, one DeviceIndependentPixel equals 1.5 device pixels.
31///
32/// The ratio between DeviceIndependentPixel and DevicePixel for a given display be found by calling
33/// `servo::windowing::WindowMethods::hidpi_factor`.
34#[derive(Clone, Copy, Debug, MallocSizeOf)]
35pub enum DeviceIndependentPixel {}
36
37pub type DeviceIndependentIntRect = Box2D<i32, DeviceIndependentPixel>;
38pub type DeviceIndependentIntPoint = Point2D<i32, DeviceIndependentPixel>;
39pub type DeviceIndependentIntSize = Size2D<i32, DeviceIndependentPixel>;
40pub type DeviceIndependentIntLength = Length<i32, DeviceIndependentPixel>;
41pub type DeviceIndependentIntSideOffsets = SideOffsets2D<i32, DeviceIndependentPixel>;
42pub type DeviceIndependentIntVector2D = Vector2D<i32, DeviceIndependentPixel>;
43
44pub type DeviceIndependentRect = Box2D<f32, DeviceIndependentPixel>;
45pub type DeviceIndependentBox2D = Box2D<f32, DeviceIndependentPixel>;
46pub type DeviceIndependentPoint = Point2D<f32, DeviceIndependentPixel>;
47pub type DeviceIndependentVector2D = Vector2D<f32, DeviceIndependentPixel>;
48pub type DeviceIndependentSize = Size2D<f32, DeviceIndependentPixel>;
49
50pub type FastLayoutTransform = FastTransform<LayoutPixel, LayoutPixel>;
51
52// An Au is an "App Unit" and represents 1/60th of a CSS pixel.  It was
53// originally proposed in 2002 as a standard unit of measure in Gecko.
54// See https://bugzilla.mozilla.org/show_bug.cgi?id=177805 for more info.
55
56pub trait MaxRect {
57    fn max_rect() -> Self;
58}
59
60/// A helper function to convert a Device rect to CSS pixels.
61pub fn convert_rect_to_css_pixel(
62    rect: DeviceIntRect,
63    scale: Scale<f32, DeviceIndependentPixel, DevicePixel>,
64) -> DeviceIndependentIntRect {
65    (rect.to_f32() / scale).round().to_i32()
66}
67
68/// A helper function to convert a Device size to CSS pixels.
69pub fn convert_size_to_css_pixel(
70    size: DeviceIntSize,
71    scale: Scale<f32, DeviceIndependentPixel, DevicePixel>,
72) -> DeviceIndependentIntSize {
73    (size.to_f32() / scale).round().to_i32()
74}
75
76impl MaxRect for UntypedRect<Au> {
77    #[inline]
78    fn max_rect() -> Self {
79        Self::new(
80            UntypedPoint2D::new(MIN_AU / 2, MIN_AU / 2),
81            UntypedSize2D::new(MAX_AU, MAX_AU),
82        )
83    }
84}
85
86impl MaxRect for LayoutRect {
87    #[inline]
88    fn max_rect() -> Self {
89        // `LayoutRect` is always consumed by WebRender. WebRender does not accept coordinates
90        // outside of the range of 1e9 * 2. We duplicate this range here.
91        //
92        // See webrender/src/util.rs in the WebRender source directory:
93        // <https://github.com/servo/webrender/blob/fa9f41d84b903b43faa129e2bedbd4e1cc54f2e2/webrender/src/util.rs#L968>
94        const MAX_COORDINATE: f32 = 1.0e9;
95        Self::from_origin_and_size(
96            LayoutPoint::new(-MAX_COORDINATE, -MAX_COORDINATE),
97            LayoutSize::new(2.0 * MAX_COORDINATE, 2.0 * MAX_COORDINATE),
98        )
99    }
100}
101
102/// A helper function to convert a rect of `f32` pixels to a rect of app units.
103pub fn f32_rect_to_au_rect<T>(rect: Rect<f32, T>) -> Rect<Au, T> {
104    Rect::new(
105        Point2D::new(
106            Au::from_f32_px(rect.origin.x),
107            Au::from_f32_px(rect.origin.y),
108        ),
109        Size2D::new(
110            Au::from_f32_px(rect.size.width),
111            Au::from_f32_px(rect.size.height),
112        ),
113    )
114}
115
116/// A helper function to convert a rect of `Au` pixels to a rect of f32 units.
117pub fn au_rect_to_f32_rect<T>(rect: Rect<Au, T>) -> Rect<f32, T> {
118    Rect::new(
119        Point2D::new(rect.origin.x.to_f32_px(), rect.origin.y.to_f32_px()),
120        Size2D::new(rect.size.width.to_f32_px(), rect.size.height.to_f32_px()),
121    )
122}