summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Haug <mhaug@live.de>2021-02-06 12:30:44 +0100
committerMartin Haug <mhaug@live.de>2021-02-06 12:30:44 +0100
commit80e076814dde330fb2136172580f11e939bc6601 (patch)
tree6cd3474ffa5e2aced38e47a7ef563ab8940612be /src
parent8469bad7487e111c8e5a0ec542f0232a0ebb4bdc (diff)
Merge `rect` and `box` 🦚
Diffstat (limited to 'src')
-rw-r--r--src/export/pdf.rs18
-rw-r--r--src/layout/background.rs37
-rw-r--r--src/layout/mod.rs23
-rw-r--r--src/layout/rect.rs71
-rw-r--r--src/library/insert.rs37
-rw-r--r--src/library/layout.rs20
-rw-r--r--src/library/mod.rs1
7 files changed, 69 insertions, 138 deletions
diff --git a/src/export/pdf.rs b/src/export/pdf.rs
index 7556e370..e5124c21 100644
--- a/src/export/pdf.rs
+++ b/src/export/pdf.rs
@@ -156,19 +156,19 @@ impl<'a> PdfExporter<'a> {
c.b as f32 / 255.,
);
}
- Fill::Image(_) => unimplemented!(),
+ Fill::Image(_) => todo!(),
}
+ let x = pos.x.to_pt() as f32;
+
match &geometry.shape {
Shape::Rect(r) => {
- content.rect(
- pos.x.to_pt() as f32,
- (page.size.height - pos.y - r.size.height).to_pt() as f32,
- r.size.width.to_pt() as f32,
- r.size.height.to_pt() as f32,
- false,
- true,
- );
+ let w = r.width.to_pt() as f32;
+ let h = r.height.to_pt() as f32;
+ let y = (page.size.height - pos.y - r.height).to_pt() as f32;
+ if w > 0.0 && h > 0.0 {
+ content.rect(x, y, w, h, false, true);
+ }
}
}
diff --git a/src/layout/background.rs b/src/layout/background.rs
new file mode 100644
index 00000000..94d5bf45
--- /dev/null
+++ b/src/layout/background.rs
@@ -0,0 +1,37 @@
+use super::*;
+
+/// A node that represents a rectangular box.
+#[derive(Debug, Clone, PartialEq)]
+pub struct NodeBackground {
+ /// The background fill.
+ pub fill: Fill,
+ /// The child node whose sides to pad.
+ pub child: NodeFixed,
+}
+
+impl Layout for NodeBackground {
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
+ let mut layouted = self.child.layout(ctx, areas);
+
+ if let Some(first) = layouted.frames_mut().first_mut() {
+ first.elements.insert(
+ 0,
+ (
+ Point::ZERO,
+ Element::Geometry(Geometry {
+ shape: Shape::Rect(first.size),
+ fill: self.fill.clone(),
+ }),
+ ),
+ )
+ }
+
+ layouted
+ }
+}
+
+impl From<NodeBackground> for NodeAny {
+ fn from(background: NodeBackground) -> Self {
+ Self::new(background)
+ }
+}
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 1bb4419d..0c7a6a68 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -4,7 +4,7 @@ mod fixed;
mod node;
mod pad;
mod par;
-mod rect;
+mod background;
mod spacing;
mod stack;
mod text;
@@ -18,7 +18,7 @@ pub use fixed::*;
pub use node::*;
pub use pad::*;
pub use par::*;
-pub use rect::*;
+pub use background::*;
pub use spacing::*;
pub use stack::*;
pub use text::*;
@@ -236,7 +236,6 @@ pub enum Fill {
Color(Color),
/// The fill is an image.
Image(Image),
- // Gradient(Gradient),
}
/// A shape with some kind of fill.
@@ -245,10 +244,10 @@ pub struct Geometry {
/// The shape to draw.
pub shape: Shape,
/// How the shape looks on the inside.
- ///
- /// **TODO:** This could be made into a Vec<Fill> or something such that
- /// the user can compose multiple fills with alpha values less
- /// than one to achieve cool effects.
+ //
+ // TODO: This could be made into a Vec<Fill> or something such that
+ // the user can compose multiple fills with alpha values less
+ // than one to achieve cool effects.
pub fill: Fill,
}
@@ -256,15 +255,7 @@ pub struct Geometry {
#[derive(Debug, Clone, PartialEq)]
pub enum Shape {
/// A rectangle.
- Rect(Rect),
- // Ellipse(Ellipse),
-}
-
-/// An rectangle.
-#[derive(Debug, Clone, PartialEq)]
-pub struct Rect {
- /// The dimensions of the rectangle.
- pub size: Size,
+ Rect(Size),
}
/// An image element.
diff --git a/src/layout/rect.rs b/src/layout/rect.rs
deleted file mode 100644
index ab8e3b07..00000000
--- a/src/layout/rect.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-use std::cmp::Ordering;
-
-use super::*;
-use crate::{color::RgbaColor, geom::Linear};
-
-/// A node that represents a rectangular box.
-#[derive(Debug, Clone, PartialEq)]
-pub struct NodeRect {
- /// The fixed width, if any.
- pub width: Option<Linear>,
- /// The fixed height, if any.
- pub height: Option<Linear>,
- /// The background color.
- pub color: Option<Color>,
- /// The child node whose sides to pad.
- pub child: Node,
-}
-
-impl Layout for NodeRect {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
- let Areas { current, full, .. } = areas;
-
- let height_opt = self.height.map(|h| h.resolve(full.height));
- let mut size = Size::new(
- self.width.map(|w| w.resolve(full.width)).unwrap_or(current.width),
- height_opt.unwrap_or(current.height),
- );
-
- let areas = Areas::once(size);
- let mut layouted = self.child.layout(ctx, &areas);
-
- // If the children have some height, apply that,
- // otherwise fall back to zero or the height property.
- if let Some(max) = layouted
- .frames()
- .iter()
- .map(|f| f.size.height)
- .max_by(|x, y| x.partial_cmp(y).unwrap_or(Ordering::Equal))
- {
- size.height = max;
- } else {
- size.height = height_opt.unwrap_or(Length::ZERO)
- }
-
- if let Some(first) = layouted.frames_mut().first_mut() {
- first.elements.insert(
- 0,
- (
- Point::ZERO,
- Element::Geometry(Geometry {
- shape: Shape::Rect(Rect { size }),
- fill: Fill::Color(self.color.unwrap_or(Color::Rgba(RgbaColor {
- r: 255,
- g: 255,
- b: 255,
- a: 0,
- }))),
- }),
- ),
- )
- }
-
- layouted
- }
-}
-
-impl From<NodeRect> for NodeAny {
- fn from(pad: NodeRect) -> Self {
- Self::new(pad)
- }
-}
diff --git a/src/library/insert.rs b/src/library/insert.rs
index 169fad97..58e8a11c 100644
--- a/src/library/insert.rs
+++ b/src/library/insert.rs
@@ -4,43 +4,6 @@ use crate::env::{ImageResource, ResourceId};
use crate::layout::*;
use crate::prelude::*;
-/// `rect`: Layout content into a rectangle that also might have a fill.
-///
-/// # Named arguments
-/// - Width of the box: `width`, of type `linear` relative to parent width.
-/// - Height of the box: `height`, of type `linear` relative to parent height.
-pub fn rect(ctx: &mut EvalContext, args: &mut Args) -> Value {
- let snapshot = ctx.state.clone();
-
- let width = args.get(ctx, "width");
- let height = args.get(ctx, "height");
- let color = args.get(ctx, "color");
-
- let dirs = ctx.state.dirs;
- let align = ctx.state.align;
-
- ctx.start_content_group();
-
- if let Some(body) = args.find::<ValueTemplate>(ctx) {
- body.eval(ctx);
- }
-
- let children = ctx.end_content_group();
-
- let fill_if = |c| if c { Expansion::Fill } else { Expansion::Fit };
- let expand = Spec::new(fill_if(width.is_some()), fill_if(height.is_some()));
-
- ctx.push(NodeRect {
- width,
- height,
- color,
- child: NodeStack { dirs, align, expand, children }.into(),
- });
-
- ctx.state = snapshot;
- Value::None
-}
-
/// `image`: Insert an image.
///
/// Supports PNG and JPEG files.
diff --git a/src/library/layout.rs b/src/library/layout.rs
index 0e04c507..bbcd7898 100644
--- a/src/library/layout.rs
+++ b/src/library/layout.rs
@@ -1,7 +1,7 @@
use std::fmt::{self, Display, Formatter};
-use crate::eval::Softness;
-use crate::layout::{Expansion, NodeFixed, NodeSpacing, NodeStack};
+use crate::{eval::Softness, layout::NodeBackground};
+use crate::layout::{Expansion, Fill, NodeFixed, NodeSpacing, NodeStack};
use crate::paper::{Paper, PaperClass};
use crate::prelude::*;
@@ -175,6 +175,7 @@ impl Display for Alignment {
/// # Named arguments
/// - Width of the box: `width`, of type `linear` relative to parent width.
/// - Height of the box: `height`, of type `linear` relative to parent height.
+/// - Background color of the box: `color`, of type `color`.
pub fn box_(ctx: &mut EvalContext, args: &mut Args) -> Value {
let snapshot = ctx.state.clone();
@@ -182,6 +183,7 @@ pub fn box_(ctx: &mut EvalContext, args: &mut Args) -> Value {
let height = args.get(ctx, "height");
let main = args.get(ctx, "main-dir");
let cross = args.get(ctx, "cross-dir");
+ let color = args.get(ctx, "color");
ctx.set_dirs(Gen::new(main, cross));
@@ -199,11 +201,21 @@ pub fn box_(ctx: &mut EvalContext, args: &mut Args) -> Value {
let fill_if = |c| if c { Expansion::Fill } else { Expansion::Fit };
let expand = Spec::new(fill_if(width.is_some()), fill_if(height.is_some()));
- ctx.push(NodeFixed {
+ let fixed_node = NodeFixed {
width,
height,
child: NodeStack { dirs, align, expand, children }.into(),
- });
+ };
+
+ if let Some(color) = color {
+ ctx.push(NodeBackground {
+ fill: Fill::Color(color),
+ child: fixed_node,
+ })
+ } else {
+ ctx.push(fixed_node);
+ }
+
ctx.state = snapshot;
Value::None
diff --git a/src/library/mod.rs b/src/library/mod.rs
index 7e20f5fb..48da093b 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -38,7 +38,6 @@ pub fn new() -> Scope {
set!(func: "image", image);
set!(func: "page", page);
set!(func: "pagebreak", pagebreak);
- set!(func: "rect", rect);
set!(func: "rgb", rgb);
set!(func: "type", type_);
set!(func: "v", v);