summaryrefslogtreecommitdiff
path: root/src/library/graphics/image.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-11-03 11:44:53 +0100
committerLaurenz <laurmaedje@gmail.com>2022-11-03 13:35:39 +0100
commit37a7afddfaffd44cb9bc013c9506599267e08983 (patch)
tree20e7d62d3c5418baff01a21d0406b91bf3096214 /src/library/graphics/image.rs
parent56342bd972a13ffe21beaf2b87ab7eb1597704b4 (diff)
Split crates
Diffstat (limited to 'src/library/graphics/image.rs')
-rw-r--r--src/library/graphics/image.rs120
1 files changed, 0 insertions, 120 deletions
diff --git a/src/library/graphics/image.rs b/src/library/graphics/image.rs
deleted file mode 100644
index e27ea488..00000000
--- a/src/library/graphics/image.rs
+++ /dev/null
@@ -1,120 +0,0 @@
-use std::ffi::OsStr;
-
-use crate::image::{Image, ImageFormat, RasterFormat, VectorFormat};
-use crate::library::prelude::*;
-use crate::library::text::TextNode;
-
-/// Show a raster or vector graphic.
-#[derive(Debug, Hash)]
-pub struct ImageNode(pub Image);
-
-#[node(LayoutInline)]
-impl ImageNode {
- /// How the image should adjust itself to a given area.
- pub const FIT: ImageFit = ImageFit::Cover;
-
- fn construct(vm: &mut Vm, args: &mut Args) -> SourceResult<Content> {
- let Spanned { v: path, span } =
- args.expect::<Spanned<EcoString>>("path to image file")?;
-
- let full = vm.locate(&path).at(span)?;
- let buffer = vm.world.file(&full).at(span)?;
- let ext = full.extension().and_then(OsStr::to_str).unwrap_or_default();
- let format = match ext.to_lowercase().as_str() {
- "png" => ImageFormat::Raster(RasterFormat::Png),
- "jpg" | "jpeg" => ImageFormat::Raster(RasterFormat::Jpg),
- "gif" => ImageFormat::Raster(RasterFormat::Gif),
- "svg" | "svgz" => ImageFormat::Vector(VectorFormat::Svg),
- _ => bail!(span, "unknown image format"),
- };
-
- let image = Image::new(buffer, format).at(span)?;
- let width = args.named("width")?;
- let height = args.named("height")?;
-
- Ok(ImageNode(image).pack().boxed(Axes::new(width, height)))
- }
-}
-
-impl LayoutInline for ImageNode {
- fn layout_inline(
- &self,
- _: Tracked<dyn World>,
- regions: &Regions,
- styles: StyleChain,
- ) -> SourceResult<Vec<Frame>> {
- let pxw = self.0.width() as f64;
- let pxh = self.0.height() as f64;
- let px_ratio = pxw / pxh;
-
- // Find out whether the image is wider or taller than the target size.
- let &Regions { first, expand, .. } = regions;
- let region_ratio = first.x / first.y;
- let wide = px_ratio > region_ratio;
-
- // The space into which the image will be placed according to its fit.
- let target = if expand.x && expand.y {
- first
- } else if expand.x || (!expand.y && wide && first.x.is_finite()) {
- Size::new(first.x, first.y.min(first.x.safe_div(px_ratio)))
- } else if first.y.is_finite() {
- Size::new(first.x.min(first.y * px_ratio), first.y)
- } else {
- Size::new(Abs::pt(pxw), Abs::pt(pxh))
- };
-
- // Compute the actual size of the fitted image.
- let fit = styles.get(Self::FIT);
- let fitted = match fit {
- ImageFit::Cover | ImageFit::Contain => {
- if wide == (fit == ImageFit::Contain) {
- Size::new(target.x, target.x / px_ratio)
- } else {
- Size::new(target.y * px_ratio, target.y)
- }
- }
- ImageFit::Stretch => target,
- };
-
- // First, place the image in a frame of exactly its size and then resize
- // the frame to the target size, center aligning the image in the
- // process.
- let mut frame = Frame::new(fitted);
- frame.push(Point::zero(), Element::Image(self.0.clone(), fitted));
- frame.resize(target, Align::CENTER_HORIZON);
-
- // Create a clipping group if only part of the image should be visible.
- if fit == ImageFit::Cover && !target.fits(fitted) {
- frame.clip();
- }
-
- // Apply link if it exists.
- if let Some(url) = styles.get(TextNode::LINK) {
- frame.link(url.clone());
- }
-
- Ok(vec![frame])
- }
-}
-
-/// How an image should adjust itself to a given area.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum ImageFit {
- /// The image should completely cover the area.
- Cover,
- /// The image should be fully contained in the area.
- Contain,
- /// The image should be stretched so that it exactly fills the area.
- Stretch,
-}
-
-castable! {
- ImageFit,
- Expected: "string",
- Value::Str(string) => match string.as_str() {
- "cover" => Self::Cover,
- "contain" => Self::Contain,
- "stretch" => Self::Stretch,
- _ => Err(r#"expected "cover", "contain" or "stretch""#)?,
- },
-}