summaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-11-20 16:36:22 +0100
committerLaurenz <laurmaedje@gmail.com>2020-11-20 16:36:22 +0100
commitf105663037c44740b5aa02dea72a9b368bc003e0 (patch)
treeee97638bfba2be3cfba8c1191919447262f181d0 /src/layout
parent2e6e6244ccf73795d7d74cbc286fb0b43b404315 (diff)
Basic image support 🖼
- [image] function - Image rendering in tests - Supports JPEG and PNG - No PDF export so far
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/graphics.rs62
-rw-r--r--src/layout/mod.rs15
2 files changed, 77 insertions, 0 deletions
diff --git a/src/layout/graphics.rs b/src/layout/graphics.rs
new file mode 100644
index 00000000..1fa05605
--- /dev/null
+++ b/src/layout/graphics.rs
@@ -0,0 +1,62 @@
+use std::fmt::{self, Debug, Formatter};
+
+use super::*;
+
+/// An image node.
+#[derive(Clone, PartialEq)]
+pub struct Image {
+ /// The image.
+ pub buf: RgbaImage,
+ /// The fixed width, if any.
+ pub width: Option<Linear>,
+ /// The fixed height, if any.
+ pub height: Option<Linear>,
+ /// How to align this image node in its parent.
+ pub align: BoxAlign,
+}
+
+impl Layout for Image {
+ fn layout(&self, _: &mut LayoutContext, areas: &Areas) -> Layouted {
+ let Area { rem, full } = areas.current;
+ let (pixel_width, pixel_height) = self.buf.dimensions();
+ let pixel_ratio = (pixel_width as f64) / (pixel_height as f64);
+
+ let width = self.width.map(|w| w.resolve(full.width));
+ let height = self.height.map(|w| w.resolve(full.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) => {
+ let ratio = rem.width / rem.height;
+ if ratio < pixel_ratio {
+ Size::new(rem.width, rem.width / pixel_ratio)
+ } else {
+ // TODO: Fix issue with line spacing.
+ Size::new(rem.height * pixel_ratio, rem.height)
+ }
+ }
+ };
+
+ let mut boxed = BoxLayout::new(size);
+ boxed.push(
+ Point::ZERO,
+ LayoutElement::Image(ImageElement { buf: self.buf.clone(), size }),
+ );
+
+ Layouted::Layout(boxed, self.align)
+ }
+}
+
+impl Debug for Image {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ f.pad("Image")
+ }
+}
+
+impl From<Image> for LayoutNode {
+ fn from(image: Image) -> Self {
+ Self::dynamic(image)
+ }
+}
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 4dd6184f..5586a1fd 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -2,6 +2,7 @@
mod document;
mod fixed;
+mod graphics;
mod node;
mod pad;
mod par;
@@ -9,12 +10,15 @@ mod spacing;
mod stack;
mod text;
+use image::RgbaImage;
+
use crate::font::SharedFontLoader;
use crate::geom::*;
use crate::shaping::Shaped;
pub use document::*;
pub use fixed::*;
+pub use graphics::*;
pub use node::*;
pub use pad::*;
pub use par::*;
@@ -179,4 +183,15 @@ impl BoxLayout {
pub enum LayoutElement {
/// Shaped text.
Text(Shaped),
+ /// An image.
+ Image(ImageElement),
+}
+
+/// An image.
+#[derive(Debug, Clone, PartialEq)]
+pub struct ImageElement {
+ /// The image.
+ pub buf: RgbaImage,
+ /// The document size of the image.
+ pub size: Size,
}