diff options
Diffstat (limited to 'src/layout/image.rs')
| -rw-r--r-- | src/layout/image.rs | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/layout/image.rs b/src/layout/image.rs new file mode 100644 index 00000000..9ba8cd82 --- /dev/null +++ b/src/layout/image.rs @@ -0,0 +1,65 @@ +use super::*; +use crate::image::ImageId; + +use ::image::GenericImageView; + +/// An image node. +#[derive(Debug, Copy, Clone, PartialEq, 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 Layout for ImageNode { + fn layout( + &self, + ctx: &mut LayoutContext, + regions: &Regions, + ) -> Vec<Constrained<Rc<Frame>>> { + let Regions { current, base, .. } = regions; + let mut constraints = Constraints::new(regions.expand); + constraints.set_base_using_linears(Spec::new(self.width, self.height), regions); + + let width = self.width.map(|w| w.resolve(base.width)); + let height = self.height.map(|w| w.resolve(base.height)); + + let dimensions = ctx.cache.image.get(self.id).buf.dimensions(); + let pixel_width = dimensions.0 as f64; + let pixel_height = dimensions.1 as f64; + let pixel_ratio = pixel_width / pixel_height; + + 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) => { + constraints.exact = current.to_spec().map(Some); + + let ratio = current.width / current.height; + if ratio < pixel_ratio && current.width.is_finite() { + Size::new(current.width, current.width / pixel_ratio) + } else if current.height.is_finite() { + // TODO: Fix issue with line spacing. + Size::new(current.height * pixel_ratio, current.height) + } else { + // Totally unbounded region, we have to make up something. + Size::new(Length::pt(pixel_width), Length::pt(pixel_height)) + } + } + }; + + let mut frame = Frame::new(size, size.height); + frame.push(Point::zero(), Element::Image(self.id, size)); + vec![frame.constrain(constraints)] + } +} + +impl From<ImageNode> for AnyNode { + fn from(image: ImageNode) -> Self { + Self::new(image) + } +} |
