summaryrefslogtreecommitdiff
path: root/src/layout/image.rs
blob: b410895b59267f1f1b8f925fe1c8d4d3e7360297 (plain) (blame)
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
use super::*;
use crate::image::ImageId;

/// An image node.
#[derive(Debug, Hash)]
pub struct ImageNode {
    /// The id of the image file.
    pub id: ImageId,
    /// The fixed width, if any.
    pub width: Option<Linear>,
    /// The fixed height, if any.
    pub height: Option<Linear>,
}

impl InlineLevel for ImageNode {
    fn layout(&self, ctx: &mut LayoutContext, space: Length, base: Size) -> Frame {
        let img = ctx.images.get(self.id);
        let pixel_size = Spec::new(img.width() as f64, img.height() as f64);
        let pixel_ratio = pixel_size.x / pixel_size.y;

        let width = self.width.map(|w| w.resolve(base.w));
        let height = self.height.map(|w| w.resolve(base.h));

        let size = match (width, height) {
            (Some(width), Some(height)) => Size::new(width, height),
            (Some(width), None) => Size::new(width, width / pixel_ratio),
            (None, Some(height)) => Size::new(height * pixel_ratio, height),
            (None, None) => {
                if space.is_finite() {
                    // Fit to width.
                    Size::new(space, space / pixel_ratio)
                } else {
                    // Unbounded width, we have to make up something,
                    // so it is 1pt per pixel.
                    pixel_size.map(Length::pt).to_size()
                }
            }
        };

        let mut frame = Frame::new(size, size.h);
        frame.push(Point::zero(), Element::Image(self.id, size));
        frame
    }
}