cdp_html_shot/
types.rs

1/// Viewport configuration for controlling page dimensions and device emulation.
2#[derive(Debug, Clone)]
3pub struct Viewport {
4    /// Viewport width in pixels.
5    pub width: u32,
6    /// Viewport height in pixels.
7    pub height: u32,
8    /// Device scale factor (DPR). Higher values (e.g., 2.0, 3.0) produce sharper images.
9    /// Default is 1.0.
10    pub device_scale_factor: f64,
11    /// Whether to emulate a mobile device. Default is false.
12    pub is_mobile: bool,
13    /// Whether touch events are supported. Default is false.
14    pub has_touch: bool,
15    /// Whether viewport is in landscape mode. Default is false.
16    pub is_landscape: bool,
17}
18
19impl Default for Viewport {
20    fn default() -> Self {
21        Self {
22            width: 800,
23            height: 600,
24            device_scale_factor: 1.0,
25            is_mobile: false,
26            has_touch: false,
27            is_landscape: false,
28        }
29    }
30}
31
32impl Viewport {
33    /// Creates a new viewport with specified dimensions and default settings.
34    pub fn new(width: u32, height: u32) -> Self {
35        Self {
36            width,
37            height,
38            ..Default::default()
39        }
40    }
41
42    /// Creates a new viewport builder for fluent configuration.
43    pub fn builder() -> ViewportBuilder {
44        ViewportBuilder::default()
45    }
46
47    pub fn with_device_scale_factor(mut self, factor: f64) -> Self {
48        self.device_scale_factor = factor;
49        self
50    }
51
52    pub fn with_mobile(mut self, is_mobile: bool) -> Self {
53        self.is_mobile = is_mobile;
54        self
55    }
56
57    pub fn with_touch(mut self, has_touch: bool) -> Self {
58        self.has_touch = has_touch;
59        self
60    }
61
62    pub fn with_landscape(mut self, is_landscape: bool) -> Self {
63        self.is_landscape = is_landscape;
64        self
65    }
66}
67
68/// Builder for creating Viewport configurations with a fluent API.
69#[derive(Debug, Clone, Default)]
70pub struct ViewportBuilder {
71    width: Option<u32>,
72    height: Option<u32>,
73    device_scale_factor: Option<f64>,
74    is_mobile: Option<bool>,
75    has_touch: Option<bool>,
76    is_landscape: Option<bool>,
77}
78
79impl ViewportBuilder {
80    pub fn width(mut self, width: u32) -> Self {
81        self.width = Some(width);
82        self
83    }
84
85    pub fn height(mut self, height: u32) -> Self {
86        self.height = Some(height);
87        self
88    }
89
90    pub fn device_scale_factor(mut self, factor: f64) -> Self {
91        self.device_scale_factor = Some(factor);
92        self
93    }
94
95    pub fn is_mobile(mut self, mobile: bool) -> Self {
96        self.is_mobile = Some(mobile);
97        self
98    }
99
100    pub fn has_touch(mut self, touch: bool) -> Self {
101        self.has_touch = Some(touch);
102        self
103    }
104
105    pub fn is_landscape(mut self, landscape: bool) -> Self {
106        self.is_landscape = Some(landscape);
107        self
108    }
109
110    pub fn build(self) -> Viewport {
111        let default = Viewport::default();
112        Viewport {
113            width: self.width.unwrap_or(default.width),
114            height: self.height.unwrap_or(default.height),
115            device_scale_factor: self
116                .device_scale_factor
117                .unwrap_or(default.device_scale_factor),
118            is_mobile: self.is_mobile.unwrap_or(default.is_mobile),
119            has_touch: self.has_touch.unwrap_or(default.has_touch),
120            is_landscape: self.is_landscape.unwrap_or(default.is_landscape),
121        }
122    }
123}
124
125/// Screenshot format options.
126#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
127pub enum ImageFormat {
128    #[default]
129    Jpeg,
130    Png,
131    WebP,
132}
133
134impl ImageFormat {
135    pub fn as_str(&self) -> &'static str {
136        match self {
137            ImageFormat::Jpeg => "jpeg",
138            ImageFormat::Png => "png",
139            ImageFormat::WebP => "webp",
140        }
141    }
142}
143
144/// Defines a rectangular region for clipping screenshots.
145#[derive(Debug, Clone, Copy)]
146pub struct ClipRegion {
147    pub x: f64,
148    pub y: f64,
149    pub width: f64,
150    pub height: f64,
151    pub scale: f64,
152}
153
154impl ClipRegion {
155    pub fn new(x: f64, y: f64, width: f64, height: f64) -> Self {
156        Self {
157            x,
158            y,
159            width,
160            height,
161            scale: 1.0,
162        }
163    }
164
165    pub fn with_scale(mut self, scale: f64) -> Self {
166        self.scale = scale;
167        self
168    }
169}
170
171/// Configuration options for HTML screenshot capture.
172#[derive(Debug, Clone, Default)]
173pub struct CaptureOptions {
174    pub(crate) format: ImageFormat,
175    pub(crate) quality: Option<u8>,
176    pub(crate) viewport: Option<Viewport>,
177    pub(crate) full_page: bool,
178    pub(crate) omit_background: bool,
179    pub(crate) clip: Option<ClipRegion>,
180}
181
182impl CaptureOptions {
183    pub fn new() -> Self {
184        Self::default()
185    }
186
187    pub fn with_format(mut self, format: ImageFormat) -> Self {
188        self.format = format;
189        self
190    }
191
192    pub fn with_quality(mut self, quality: u8) -> Self {
193        self.quality = Some(quality.min(100));
194        self
195    }
196
197    pub fn with_viewport(mut self, viewport: Viewport) -> Self {
198        self.viewport = Some(viewport);
199        self
200    }
201
202    pub fn with_full_page(mut self, full_page: bool) -> Self {
203        self.full_page = full_page;
204        self
205    }
206
207    pub fn with_omit_background(mut self, omit: bool) -> Self {
208        self.omit_background = omit;
209        self
210    }
211
212    pub fn with_clip(mut self, clip: ClipRegion) -> Self {
213        self.clip = Some(clip);
214        self
215    }
216
217    pub fn raw_png() -> Self {
218        Self::new().with_format(ImageFormat::Png)
219    }
220
221    pub fn high_quality_jpeg() -> Self {
222        Self::new().with_format(ImageFormat::Jpeg).with_quality(95)
223    }
224
225    pub fn hidpi() -> Self {
226        Self::new().with_viewport(Viewport::default().with_device_scale_factor(2.0))
227    }
228
229    pub fn ultra_hidpi() -> Self {
230        Self::new().with_viewport(Viewport::default().with_device_scale_factor(3.0))
231    }
232
233    #[deprecated(since = "0.2.0", note = "Use `with_format()` instead")]
234    pub fn with_raw_png(mut self, raw: bool) -> Self {
235        self.format = if raw {
236            ImageFormat::Png
237        } else {
238            ImageFormat::Jpeg
239        };
240        self
241    }
242}