Skip to main content

takumi_css/
viewport.rs

1use taffy::{AvailableSpace, Size};
2
3/// The default font size in pixels.
4pub const DEFAULT_FONT_SIZE: f32 = 16.0;
5
6/// The default device pixel ratio.
7pub const DEFAULT_DEVICE_PIXEL_RATIO: f32 = 1.0;
8
9/// The viewport for the image renderer.
10#[derive(Debug, Clone, Copy)]
11pub struct Viewport {
12  /// Size of the viewport
13  pub size: ViewportSize,
14  /// Initial font size in pixels, used as the fallback when no root element
15  /// has set its computed `font-size` (see CSS Values 4 ยง6.1 for `rem`).
16  pub font_size: f32,
17  /// The device pixel ratio.
18  pub device_pixel_ratio: f32,
19}
20
21impl From<Viewport> for Size<AvailableSpace> {
22  fn from(value: Viewport) -> Self {
23    Self {
24      width: if let Some(width) = value.size.width {
25        AvailableSpace::Definite(width as f32)
26      } else {
27        AvailableSpace::MaxContent
28      },
29      height: if let Some(height) = value.size.height {
30        AvailableSpace::Definite(height as f32)
31      } else {
32        AvailableSpace::MaxContent
33      },
34    }
35  }
36}
37
38impl Default for Viewport {
39  fn default() -> Self {
40    Self::new((None, None))
41  }
42}
43
44impl Viewport {
45  /// Creates a new viewport with the default font size.
46  pub fn new(size: impl Into<ViewportSize>) -> Self {
47    Self {
48      size: size.into(),
49      font_size: DEFAULT_FONT_SIZE,
50      device_pixel_ratio: DEFAULT_DEVICE_PIXEL_RATIO,
51    }
52  }
53
54  /// Sets the font size in pixels.
55  pub const fn with_font_size(mut self, font_size: f32) -> Self {
56    self.font_size = font_size;
57    self
58  }
59
60  /// Sets the device pixel ratio.
61  pub const fn with_device_pixel_ratio(mut self, device_pixel_ratio: f32) -> Self {
62    self.device_pixel_ratio = device_pixel_ratio;
63    self
64  }
65}
66
67/// Represents Viewport size
68#[derive(Debug, Clone, Copy, Default)]
69pub struct ViewportSize {
70  /// The width of the viewport in pixels.
71  pub width: Option<u32>,
72  /// The height of the viewport in pixels.
73  pub height: Option<u32>,
74}
75
76impl From<(u32, u32)> for ViewportSize {
77  fn from(value: (u32, u32)) -> Self {
78    Self {
79      width: Some(value.0),
80      height: Some(value.1),
81    }
82  }
83}
84
85impl From<(Option<u32>, u32)> for ViewportSize {
86  fn from(value: (Option<u32>, u32)) -> Self {
87    Self {
88      width: value.0,
89      height: Some(value.1),
90    }
91  }
92}
93
94impl From<(u32, Option<u32>)> for ViewportSize {
95  fn from(value: (u32, Option<u32>)) -> Self {
96    Self {
97      width: Some(value.0),
98      height: value.1,
99    }
100  }
101}
102
103impl From<(Option<u32>, Option<u32>)> for ViewportSize {
104  fn from(value: (Option<u32>, Option<u32>)) -> Self {
105    Self {
106      width: value.0,
107      height: value.1,
108    }
109  }
110}
111
112#[cfg(test)]
113mod tests {
114  use super::*;
115
116  #[test]
117  fn test_viewport_new_defaults() {
118    let v = Viewport::new((800, 600));
119    assert_eq!(v.size.width, Some(800));
120    assert_eq!(v.size.height, Some(600));
121    assert_eq!(v.font_size, DEFAULT_FONT_SIZE);
122  }
123}