diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-10-13 18:33:10 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-10-23 20:22:47 +0200 |
| commit | 1e74f7c407e42174b631cb7477f3c88252da7e25 (patch) | |
| tree | 53c0510b6503c434c9ba470b188d9e737ce1c3cf | |
| parent | 5f4dde0a6b32c7620b29af30f69591cf3995af9b (diff) | |
New `ShapeNode`
Replaces `BackgroundNode` and `FixedNode`
| -rw-r--r-- | src/layout/background.rs | 55 | ||||
| -rw-r--r-- | src/layout/fixed.rs | 99 | ||||
| -rw-r--r-- | src/layout/mod.rs | 6 | ||||
| -rw-r--r-- | src/layout/shape.rs | 141 | ||||
| -rw-r--r-- | src/layout/tree.rs | 21 | ||||
| -rw-r--r-- | src/library/elements.rs | 108 | ||||
| -rw-r--r-- | src/library/layout.rs | 12 | ||||
| -rw-r--r-- | src/library/mod.rs | 1 | ||||
| -rw-r--r-- | tests/ref/elements/circle.png | bin | 12600 -> 12965 bytes | |||
| -rw-r--r-- | tests/ref/elements/ellipse.png | bin | 7359 -> 7717 bytes | |||
| -rw-r--r-- | tests/ref/elements/rect.png | bin | 2542 -> 2866 bytes | |||
| -rw-r--r-- | tests/ref/elements/square.png | bin | 6124 -> 6983 bytes | |||
| -rw-r--r-- | tests/typ/coma.typ | 18 | ||||
| -rw-r--r-- | tests/typ/elements/circle.typ | 17 | ||||
| -rw-r--r-- | tests/typ/elements/ellipse.typ | 4 | ||||
| -rw-r--r-- | tests/typ/elements/rect.typ | 24 | ||||
| -rw-r--r-- | tests/typ/elements/square.typ | 10 | ||||
| -rw-r--r-- | tests/typ/layout/grid-1.typ | 31 |
18 files changed, 253 insertions, 294 deletions
diff --git a/src/layout/background.rs b/src/layout/background.rs deleted file mode 100644 index 09282260..00000000 --- a/src/layout/background.rs +++ /dev/null @@ -1,55 +0,0 @@ -use super::*; - -/// A node that places a rectangular filled background behind its child. -#[derive(Debug)] -#[cfg_attr(feature = "layout-cache", derive(Hash))] -pub struct BackgroundNode { - /// The kind of shape to use as a background. - pub shape: BackgroundShape, - /// Background color / texture. - pub fill: Paint, - /// The child node to be filled. - pub child: LayoutNode, -} - -/// The kind of shape to use as a background. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum BackgroundShape { - Rect, - Ellipse, -} - -impl Layout for BackgroundNode { - fn layout( - &self, - ctx: &mut LayoutContext, - regions: &Regions, - ) -> Vec<Constrained<Rc<Frame>>> { - let mut frames = self.child.layout(ctx, regions); - - for Constrained { item: frame, .. } in &mut frames { - let (point, geometry) = match self.shape { - BackgroundShape::Rect => (Point::zero(), Geometry::Rect(frame.size)), - BackgroundShape::Ellipse => { - (frame.size.to_point() / 2.0, Geometry::Ellipse(frame.size)) - } - }; - - // Create a new frame with the background geometry and the child's - // frame. - let empty = Frame::new(frame.size, frame.baseline); - let prev = std::mem::replace(frame, Rc::new(empty)); - let new = Rc::make_mut(frame); - new.push(point, Element::Geometry(geometry, self.fill)); - new.push_frame(Point::zero(), prev); - } - - frames - } -} - -impl From<BackgroundNode> for LayoutNode { - fn from(background: BackgroundNode) -> Self { - Self::new(background) - } -} diff --git a/src/layout/fixed.rs b/src/layout/fixed.rs deleted file mode 100644 index f0528643..00000000 --- a/src/layout/fixed.rs +++ /dev/null @@ -1,99 +0,0 @@ -use decorum::N64; - -use super::*; - -/// A node that can fix its child's width and height. -#[derive(Debug)] -#[cfg_attr(feature = "layout-cache", derive(Hash))] -pub struct FixedNode { - /// The fixed width, if any. - pub width: Option<Linear>, - /// The fixed height, if any. - pub height: Option<Linear>, - /// The fixed aspect ratio between width and height. - /// - /// The resulting frame will satisfy `width = aspect * height`. - pub aspect: Option<N64>, - /// The child node whose size to fix. - pub child: LayoutNode, -} - -impl Layout for FixedNode { - fn layout( - &self, - ctx: &mut LayoutContext, - regions: &Regions, - ) -> Vec<Constrained<Rc<Frame>>> { - // Fill in width or height if aspect ratio and the other is given. - let aspect = self.aspect.map(N64::into_inner); - let width = self.width.or(self.height.zip(aspect).map(|(h, a)| a * h)); - let height = self.height.or(self.width.zip(aspect).map(|(w, a)| w / a)); - - // Resolve the linears based on the current width and height. - let mut child_size = Size::new( - width.map_or(regions.current.w, |w| w.resolve(regions.base.w)), - height.map_or(regions.current.h, |h| h.resolve(regions.base.h)), - ); - - // If width or height aren't set for an axis, the base should be - // inherited from the parent for that axis. - let child_base = Size::new( - if width.is_some() { child_size.w } else { regions.base.w }, - if height.is_some() { child_size.h } else { regions.base.h }, - ); - - // Prepare constraints. - let mut constraints = Constraints::new(regions.expand); - constraints.set_base_if_linear(regions.base, Spec::new(width, height)); - - // If the size for one axis isn't specified, the `current` size along - // that axis needs to remain the same for the result to be reusable. - if width.is_none() { - constraints.exact.x = Some(regions.current.w); - } - if height.is_none() { - constraints.exact.y = Some(regions.current.h); - } - - // Apply the aspect ratio. - if let Some(aspect) = aspect { - let width = child_size.w.min(aspect * child_size.h); - child_size = Size::new(width, width / aspect); - constraints.exact = regions.current.to_spec().map(Some); - constraints.min = Spec::splat(None); - constraints.max = Spec::splat(None); - } - - // If width or height are fixed, the child should fill the available - // space along that axis. - let child_expand = Spec::new(width.is_some(), height.is_some()); - - // Layout the child. - let mut regions = Regions::one(child_size, child_base, child_expand); - let mut frames = self.child.layout(ctx, ®ions); - - // If we have an aspect ratio and the child is content-sized, we need to - // relayout with expansion. - if let Some(aspect) = aspect { - if width.is_none() && height.is_none() { - let needed = frames[0].item.size.cap(child_size); - let width = needed.w.max(aspect * needed.h); - regions.current = Size::new(width, width / aspect); - regions.expand = Spec::splat(true); - frames = self.child.layout(ctx, ®ions); - } - } - - // Overwrite the child's constraints with ours. - assert_eq!(frames.len(), 1); - frames[0].constraints = constraints; - - frames - } -} - -impl From<FixedNode> for LayoutNode { - fn from(fixed: FixedNode) -> Self { - Self::new(fixed) - } -} diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 1ca9001d..cd59e3d2 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1,8 +1,6 @@ //! Layouting. -mod background; mod constraints; -mod fixed; mod frame; mod grid; mod image; @@ -11,14 +9,13 @@ mod incremental; mod pad; mod par; mod regions; +mod shape; mod shaping; mod stack; mod tree; pub use self::image::*; -pub use background::*; pub use constraints::*; -pub use fixed::*; pub use frame::*; pub use grid::*; #[cfg(feature = "layout-cache")] @@ -26,6 +23,7 @@ pub use incremental::*; pub use pad::*; pub use par::*; pub use regions::*; +pub use shape::*; pub use shaping::*; pub use stack::*; pub use tree::*; diff --git a/src/layout/shape.rs b/src/layout/shape.rs new file mode 100644 index 00000000..aa90707c --- /dev/null +++ b/src/layout/shape.rs @@ -0,0 +1,141 @@ +use std::f64::consts::SQRT_2; + +use super::*; + +/// Places its child into a sizable and fillable shape. +#[derive(Debug)] +#[cfg_attr(feature = "layout-cache", derive(Hash))] +pub struct ShapeNode { + /// Which shape to place the child into. + pub shape: ShapeKind, + /// The width, if any. + pub width: Option<Linear>, + /// The height, if any. + pub height: Option<Linear>, + /// How to fill the shape, if at all. + pub fill: Option<Paint>, + /// The child node to place into the shape, if any. + pub child: Option<LayoutNode>, +} + +/// The type of a shape. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum ShapeKind { + /// A rectangle with equal side lengths. + Square, + /// A quadrilateral with four right angles. + Rect, + /// An ellipse with coinciding foci. + Circle, + /// A curve around two focal points. + Ellipse, +} + +impl Layout for ShapeNode { + fn layout( + &self, + ctx: &mut LayoutContext, + regions: &Regions, + ) -> Vec<Constrained<Rc<Frame>>> { + // Resolve width and height relative to the region's base. + let width = self.width.map(|w| w.resolve(regions.base.w)); + let height = self.height.map(|h| h.resolve(regions.base.h)); + + // Generate constraints. + let constraints = { + let mut cts = Constraints::new(regions.expand); + cts.set_base_if_linear(regions.base, Spec::new(self.width, self.height)); + + // Set exact and base constraint if child is automatically sized. + if self.width.is_none() { + cts.exact.x = Some(regions.current.w); + cts.base.x = Some(regions.base.w); + } + + // Same here. + if self.height.is_none() { + cts.exact.y = Some(regions.current.h); + cts.base.y = Some(regions.base.h); + } + + cts + }; + + // Layout. + let mut frames = if let Some(child) = &self.child { + let mut node: &dyn Layout = child; + + let padded; + if matches!(self.shape, ShapeKind::Circle | ShapeKind::Ellipse) { + // Padding with this ratio ensures that a rectangular child fits + // perfectly into a circle / an ellipse. + padded = PadNode { + padding: Sides::splat(Relative::new(0.5 - SQRT_2 / 4.0).into()), + child: child.clone(), + }; + node = &padded; + } + + // The "pod" is the region into which the child will be layouted. + let mut pod = { + let size = Size::new( + width.unwrap_or(regions.current.w), + height.unwrap_or(regions.current.h), + ); + + let base = Size::new( + if width.is_some() { size.w } else { regions.base.w }, + if height.is_some() { size.h } else { regions.base.h }, + ); + + let expand = Spec::new(width.is_some(), height.is_some()); + Regions::one(size, base, expand) + }; + + // Now, layout the child. + let mut frames = node.layout(ctx, &pod); + + if matches!(self.shape, ShapeKind::Square | ShapeKind::Circle) { + // Relayout with full expansion into square region to make sure + // the result is really a square or circle. + let size = frames[0].item.size; + pod.current.w = size.w.max(size.h).min(pod.current.w); + pod.current.h = pod.current.w; + pod.expand = Spec::splat(true); + frames = node.layout(ctx, &pod); + } + + // Validate and set constraints. + assert_eq!(frames.len(), 1); + frames[0].constraints = constraints; + frames + } else { + // Resolve shape size. + let size = Size::new(width.unwrap_or_default(), height.unwrap_or_default()); + vec![Frame::new(size, size.h).constrain(constraints)] + }; + + // Add background shape if desired. + if let Some(fill) = self.fill { + let frame = Rc::make_mut(&mut frames[0].item); + let (pos, geometry) = match self.shape { + ShapeKind::Square | ShapeKind::Rect => { + (Point::zero(), Geometry::Rect(frame.size)) + } + ShapeKind::Circle | ShapeKind::Ellipse => { + (frame.size.to_point() / 2.0, Geometry::Ellipse(frame.size)) + } + }; + + frame.prepend(pos, Element::Geometry(geometry, fill)); + } + + frames + } +} + +impl From<ShapeNode> for LayoutNode { + fn from(shape: ShapeNode) -> Self { + Self::new(shape) + } +} diff --git a/src/layout/tree.rs b/src/layout/tree.rs index 38ba6e85..900eb1a9 100644 --- a/src/layout/tree.rs +++ b/src/layout/tree.rs @@ -50,8 +50,9 @@ impl PageRun { } /// A dynamic layouting node. +#[derive(Clone)] pub struct LayoutNode { - node: Box<dyn Layout>, + node: Rc<dyn Layout>, #[cfg(feature = "layout-cache")] hash: u64, } @@ -63,7 +64,7 @@ impl LayoutNode { where T: Layout + 'static, { - Self { node: Box::new(node) } + Self { node: Rc::new(node) } } /// Create a new instance from any node that satisifies the required bounds. @@ -79,7 +80,7 @@ impl LayoutNode { state.finish() }; - Self { node: Box::new(node), hash } + Self { node: Rc::new(node), hash } } } @@ -99,10 +100,16 @@ impl Layout for LayoutNode { ctx.level -= 1; let entry = FramesEntry::new(frames.clone(), ctx.level); - debug_assert!( - entry.check(regions), - "constraints did not match regions they were created for", - ); + + #[cfg(debug_assertions)] + if !entry.check(regions) { + eprintln!("regions: {:#?}", regions); + eprintln!( + "constraints: {:#?}", + frames.iter().map(|c| c.constraints).collect::<Vec<_>>() + ); + panic!("constraints did not match regions they were created for"); + } ctx.layouts.insert(self.hash, entry); frames diff --git a/src/library/elements.rs b/src/library/elements.rs index 51f8dc98..5d87d65d 100644 --- a/src/library/elements.rs +++ b/src/library/elements.rs @@ -1,11 +1,8 @@ -use std::f64::consts::SQRT_2; use std::io; -use decorum::N64; - use super::*; use crate::diag::Error; -use crate::layout::{BackgroundNode, BackgroundShape, FixedNode, ImageNode, PadNode}; +use crate::layout::{ImageNode, ShapeKind, ShapeNode}; /// `image`: An image. pub fn image(ctx: &mut EvalContext, args: &mut Args) -> TypResult<Value> { @@ -33,52 +30,24 @@ pub fn rect(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { let width = args.named("width")?; let height = args.named("height")?; let fill = args.named("fill")?; - let body = args.eat().unwrap_or_default(); - Ok(rect_impl(width, height, None, fill, body)) + let body = args.eat(); + Ok(shape_impl(ShapeKind::Rect, width, height, fill, body)) } /// `square`: A square with optional content. pub fn square(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { let size = args.named::<Length>("size")?.map(Linear::from); let width = match size { - Some(size) => Some(size), None => args.named("width")?, + size => size, }; - let height = match width { - Some(_) => None, + let height = match size { None => args.named("height")?, + size => size, }; - let aspect = Some(N64::from(1.0)); let fill = args.named("fill")?; - let body = args.eat().unwrap_or_default(); - Ok(rect_impl(width, height, aspect, fill, body)) -} - -fn rect_impl( - width: Option<Linear>, - height: Option<Linear>, - aspect: Option<N64>, - fill: Option<Color>, - body: Template, -) -> Value { - Value::Template(Template::from_inline(move |style| { - let mut node = LayoutNode::new(FixedNode { - width, - height, - aspect, - child: body.to_stack(style).into(), - }); - - if let Some(fill) = fill { - node = LayoutNode::new(BackgroundNode { - shape: BackgroundShape::Rect, - fill: Paint::Color(fill), - child: node, - }); - } - - node - })) + let body = args.eat(); + Ok(shape_impl(ShapeKind::Square, width, height, fill, body)) } /// `ellipse`: An ellipse with optional content. @@ -86,8 +55,8 @@ pub fn ellipse(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { let width = args.named("width")?; let height = args.named("height")?; let fill = args.named("fill")?; - let body = args.eat().unwrap_or_default(); - Ok(ellipse_impl(width, height, None, fill, body)) + let body = args.eat(); + Ok(shape_impl(ShapeKind::Ellipse, width, height, fill, body)) } /// `circle`: A circle with optional content. @@ -97,46 +66,39 @@ pub fn circle(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { None => args.named("width")?, diameter => diameter, }; - let height = match width { + let height = match diameter { None => args.named("height")?, - width => width, + diameter => diameter, }; - let aspect = Some(N64::from(1.0)); let fill = args.named("fill")?; - let body = args.eat().unwrap_or_default(); - Ok(ellipse_impl(width, height, aspect, fill, body)) + let body = args.eat(); + Ok(shape_impl(ShapeKind::Circle, width, height, fill, body)) } -fn ellipse_impl( - width: Option<Linear>, - height: Option<Linear>, - aspect: Option<N64>, +fn shape_impl( + shape: ShapeKind, + mut width: Option<Linear>, + mut height: Option<Linear>, fill: Option<Color>, - body: Template, + body: Option<Template>, ) -> Value { - Value::Template(Template::from_inline(move |style| { - // This padding ratio ensures that the rectangular padded region fits - // perfectly into the ellipse. - const PAD: f64 = 0.5 - SQRT_2 / 4.0; - - let mut node = LayoutNode::new(FixedNode { - width, - height, - aspect, - child: LayoutNode::new(PadNode { - padding: Sides::splat(Relative::new(PAD).into()), - child: body.to_stack(style).into(), - }), + // Set default shape size if there's no body. + if body.is_none() { + let v = Length::pt(30.0).into(); + height.get_or_insert(v); + width.get_or_insert(match shape { + ShapeKind::Square | ShapeKind::Circle => v, + ShapeKind::Rect | ShapeKind::Ellipse => 1.5 * v, }); + } - if let Some(fill) = fill { - node = LayoutNode::new(BackgroundNode { - shape: BackgroundShape::Ellipse, - fill: Paint::Color(fill), - child: node, - }); - } - - node + Value::Template(Template::from_inline(move |style| ShapeNode { + shape, + width, + height, + fill: Some(Paint::Color( + fill.unwrap_or(Color::Rgba(RgbaColor::new(175, 175, 175, 255))), + )), + child: body.as_ref().map(|template| template.to_stack(style).into()), })) } diff --git a/src/library/layout.rs b/src/library/layout.rs index efa012b9..b98b08f1 100644 --- a/src/library/layout.rs +++ b/src/library/layout.rs @@ -1,5 +1,7 @@ use super::*; -use crate::layout::{FixedNode, GridNode, PadNode, StackChild, StackNode, TrackSizing}; +use crate::layout::{ + GridNode, PadNode, ShapeKind, ShapeNode, StackChild, StackNode, TrackSizing, +}; use crate::style::{Paper, PaperClass}; /// `page`: Configure pages. @@ -146,13 +148,15 @@ pub fn v(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { pub fn boxed(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { let width = args.named("width")?; let height = args.named("height")?; + let fill = args.named("fill")?; let body: Template = args.eat().unwrap_or_default(); Ok(Value::Template(Template::from_inline(move |style| { - FixedNode { + ShapeNode { + shape: ShapeKind::Rect, width, height, - aspect: None, - child: body.to_stack(style).into(), + fill: fill.map(Paint::Color), + child: Some(body.to_stack(style).into()), } }))) } diff --git a/src/library/mod.rs b/src/library/mod.rs index 7c8f4a93..430e260b 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -20,7 +20,6 @@ use crate::diag::{At, TypResult}; use crate::eval::{Args, Array, EvalContext, Scope, Str, Template, Value}; use crate::font::{FontFamily, FontStretch, FontStyle, FontWeight, VerticalFontMetric}; use crate::geom::*; -use crate::layout::LayoutNode; use crate::style::Style; use crate::syntax::{Span, Spanned}; diff --git a/tests/ref/elements/circle.png b/tests/ref/elements/circle.png Binary files differindex 65b087ed..41079fda 100644 --- a/tests/ref/elements/circle.png +++ b/tests/ref/elements/circle.png diff --git a/tests/ref/elements/ellipse.png b/tests/ref/elements/ellipse.png Binary files differindex d429f66e..98e66902 100644 --- a/tests/ref/elements/ellipse.png +++ b/tests/ref/elements/ellipse.png diff --git a/tests/ref/elements/rect.png b/tests/ref/elements/rect.png Binary files differindex ad4c48e6..b6d40545 100644 --- a/tests/ref/elements/rect.png +++ b/tests/ref/elements/rect.png diff --git a/tests/ref/elements/square.png b/tests/ref/elements/square.png Binary files differindex a7343a10..a12e1a12 100644 --- a/tests/ref/elements/square.png +++ b/tests/ref/elements/square.png diff --git a/tests/typ/coma.typ b/tests/typ/coma.typ index 8f47a749..54f80cf6 100644 --- a/tests/typ/coma.typ +++ b/tests/typ/coma.typ @@ -10,18 +10,12 @@ #let university = [*Technische Universität {city}*] #let faculty = [*Fakultät II, Institut for Mathematik*] -// The `box` function just places content into a rectangular container. When -// the only argument to a function is a template, the parentheses can be omitted -// (i.e. `f[a]` is the same as `f([a])`). -#box[ - // Backslash adds a forced line break. - #university \ - #faculty \ - Sekretariat MA \ - Dr. Max Mustermann \ - Ola Nordmann, John Doe -] -#align(right, box[*WiSe 2019/2020* \ Woche 3]) +// Backslashs add forced line breaks. +#university #align(right)[*WiSe 2019/2020*] \ +#faculty #align(right)[Woche 3] \ +Sekretariat MA \ +Dr. Max Mustermann \ +Ola Nordmann, John Doe // Adds vertical spacing. #v(6mm) diff --git a/tests/typ/elements/circle.typ b/tests/typ/elements/circle.typ index c46d37e4..c36f9f94 100644 --- a/tests/typ/elements/circle.typ +++ b/tests/typ/elements/circle.typ @@ -1,6 +1,10 @@ // Test the `circle` function. --- +// Default circle. +#circle() + +--- // Test auto sizing. Auto-sized circle. \ @@ -29,20 +33,15 @@ Expanded by height. --- // Test relative sizing. -#rect(width: 100%, height: 50pt, fill: rgb("aaa"))[ +#rect(width: 100pt, height: 50pt, fill: rgb("aaa"))[ #align(center, center) #font(fill: white) - #circle(radius: 10pt, fill: eastern)[A] - #circle(height: 60%, fill: eastern)[B] - #circle(width: 20% + 20pt, fill: eastern)[C] + #circle(radius: 10pt, fill: eastern)[A] // D=20pt + #circle(height: 60%, fill: eastern)[B] // D=30pt + #circle(width: 20% + 20pt, fill: eastern)[C] // D=40pt ] --- // Radius wins over width and height. // Error: 23-34 unexpected argument #circle(radius: 10pt, width: 50pt, height: 100pt, fill: eastern) - ---- -// Width wins over height. -// Error: 9-21 unexpected argument -#circle(height: 50pt, width: 20pt, fill: eastern) diff --git a/tests/typ/elements/ellipse.typ b/tests/typ/elements/ellipse.typ index 33ba727f..106a8172 100644 --- a/tests/typ/elements/ellipse.typ +++ b/tests/typ/elements/ellipse.typ @@ -1,6 +1,10 @@ // Test the `ellipse` function. --- +// Default ellipse. +#ellipse() + +--- 100% rect in 100% ellipse in fixed rect. \ #rect(width: 3cm, height: 2cm, fill: rgb("2a631a"), ellipse(width: 100%, height: 100%, fill: forest, diff --git a/tests/typ/elements/rect.typ b/tests/typ/elements/rect.typ index 4824095a..59dd4ee0 100644 --- a/tests/typ/elements/rect.typ +++ b/tests/typ/elements/rect.typ @@ -1,27 +1,25 @@ -// Test shapes. +// Test the `rect` function. --- -// Test the `rect` function. +// Default rectangle. +#rect() +--- #page(width: 150pt) // Fit to text. #rect(fill: conifer)[Textbox] // Empty with fixed width and height. -#rect(width: 3cm, height: 12pt, fill: rgb("CB4CED")) +#rect(width: 3cm, height: 12pt, fill: rgb("ed8a4c")) // Fixed width, text height. -#rect(width: 2cm, fill: rgb("9650D6"), pad(5pt)[Fixed and padded]) +#rect(width: 2cm, fill: rgb("9650d6"), pad(5pt)[Fixed and padded]) // Page width, fixed height. -#rect(height: 1cm, width: 100%, fill: rgb("734CED"))[Topleft] - -// Not visible, but creates a gap between the boxes above and below -// due to line spacing. -#rect(width: 1in, fill: rgb("ff0000")) +#rect(height: 1cm, width: 100%, fill: rgb("734ced"))[Topleft] -// These are in a row! -#rect(width: 0.5in, height: 10pt, fill: rgb("D6CD67")) -#rect(width: 0.5in, height: 10pt, fill: rgb("EDD466")) -#rect(width: 0.5in, height: 10pt, fill: rgb("E3BE62")) +// These are inline with text. +\{#rect(width: 0.5in, height: 7pt, fill: rgb("d6cd67")) + #rect(width: 0.5in, height: 7pt, fill: rgb("edd466")) + #rect(width: 0.5in, height: 7pt, fill: rgb("e3be62"))\} diff --git a/tests/typ/elements/square.typ b/tests/typ/elements/square.typ index 7597cb22..0e9c3c55 100644 --- a/tests/typ/elements/square.typ +++ b/tests/typ/elements/square.typ @@ -1,12 +1,18 @@ // Test the `square` function. --- +// Default square. +#square() +#square[hey!] + +--- // Test auto-sized square. #square(fill: eastern)[ #font(fill: white, weight: bold) #align(center) #pad(5pt)[Typst] ] + --- // Test relative-sized child. #square(fill: eastern)[ @@ -15,14 +21,14 @@ ] --- -// Test height overflow. +// Test text overflowing height. #page(width: 75pt, height: 100pt) #square(fill: conifer)[ But, soft! what light through yonder window breaks? ] --- -// Test width overflow. +// Test required height overflowing page. #page(width: 100pt, height: 75pt) #square(fill: conifer)[ But, soft! what light through yonder window breaks? diff --git a/tests/typ/layout/grid-1.typ b/tests/typ/layout/grid-1.typ index 3d0412c2..43a3883d 100644 --- a/tests/typ/layout/grid-1.typ +++ b/tests/typ/layout/grid-1.typ @@ -1,23 +1,23 @@ // Test grid layouts. --- -#let rect(width, fill) = rect(width: width, height: 2cm, fill: fill) +#let cell(width, color) = rect(width: width, height: 2cm, fill: color) #page(width: 100pt, height: 140pt) #grid( columns: (auto, 1fr, 3fr, 0.25cm, 3%, 2mm + 10%), - rect(0.5cm, rgb("2a631a")), - rect(100%, forest), - rect(100%, conifer), - rect(100%, rgb("ff0000")), - rect(100%, rgb("00ff00")), - rect(80%, rgb("00faf0")), - rect(1cm, rgb("00ff00")), - rect(0.5cm, rgb("2a631a")), - rect(100%, forest), - rect(100%, conifer), - rect(100%, rgb("ff0000")), - rect(100%, rgb("00ff00")), + cell(0.5cm, rgb("2a631a")), + cell(100%, forest), + cell(100%, conifer), + cell(100%, rgb("ff0000")), + cell(100%, rgb("00ff00")), + cell(80%, rgb("00faf0")), + cell(1cm, rgb("00ff00")), + cell(0.5cm, rgb("2a631a")), + cell(100%, forest), + cell(100%, conifer), + cell(100%, rgb("ff0000")), + cell(100%, rgb("00ff00")), ) #grid() @@ -51,6 +51,7 @@ #grid( columns: (1fr,), rows: (1fr, auto, 2fr), - [], rect(width: 100%)[A bit more to the top], [], + [], + box(width: 100%)[A bit more to the top], + [], ) - |
