1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use super::{Element, LayoutMode, RenderContext};
use crate::layout::FixedBox;
/// Scaling / fitting mode for an image inside a `FixedImageBox`.
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub enum ImageFit {
/// Scale to fit entirely within the box, preserving aspect ratio.
#[default]
Contain,
/// Scale to fill the box, preserving aspect ratio (may crop).
Cover,
/// Stretch to fill the box exactly (ignores aspect ratio).
Stretch,
/// Render at original pixel size; apply `OverflowPolicy` if it exceeds the box.
Original,
}
/// An image element placed at a fixed position on the page.
///
/// Does not participate in `PageFlow`.
#[derive(Debug, Clone)]
pub struct FixedImageBox {
pub image_box: FixedBox,
/// Raw PNG or JPEG bytes.
pub data: Vec<u8>,
pub fit: ImageFit,
}
impl FixedImageBox {
pub fn new(image_box: FixedBox, data: Vec<u8>) -> Self {
Self {
image_box,
data,
fit: ImageFit::Contain,
}
}
pub fn fit(mut self, fit: ImageFit) -> Self {
self.fit = fit;
self
}
}
impl Element for FixedImageBox {
fn layout_mode(&self) -> LayoutMode {
LayoutMode::Fixed(self.image_box.clone())
}
fn estimated_height_mm(&self) -> f64 {
0.0
}
fn render(&self, ctx: &mut RenderContext) -> crate::Result<super::RenderResult> {
let ua = ctx.ua_config.enabled;
if ua {
match &self.image_box.ua_role {
Some(tag) => {
let mcid = ctx.ua_tag_element(tag.clone(), self.image_box.ua_alt.clone());
ctx.backend.begin_tagged_content(tag.pdf_name().as_bytes(), mcid);
}
None => {
ctx.backend.begin_artifact_content();
}
}
}
// TODO: decode image bytes, compute rendered dimensions per ImageFit,
// create printpdf image op, place at image_box coordinates.
if ua { ctx.backend.end_tagged_content(); }
Ok(super::RenderResult::done())
}
}