summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-01-13 23:19:44 +0100
committerLaurenz <laurmaedje@gmail.com>2021-01-13 23:19:44 +0100
commit272a4c228976466e9fa6cc100ad89f93dc5cc371 (patch)
treead02a6e57b07da061432d58ff0ca46d6777bdb97
parent1b53e27f270e3c040ee095573af9a5243980191a (diff)
Unbounded pages 🌌
-rw-r--r--src/eval/context.rs4
-rw-r--r--src/eval/mod.rs4
-rw-r--r--src/eval/state.rs6
-rw-r--r--src/geom/length.rs10
-rw-r--r--src/geom/relative.rs7
-rw-r--r--src/geom/size.rs10
-rw-r--r--src/layout/fixed.rs6
-rw-r--r--src/layout/mod.rs63
-rw-r--r--src/layout/pad.rs6
-rw-r--r--src/layout/par.rs21
-rw-r--r--src/layout/stack.rs21
-rw-r--r--src/library/insert.rs20
-rw-r--r--src/library/layout.rs13
-rw-r--r--tests/ref/arrays.pngbin3601 -> 3479 bytes
-rw-r--r--tests/ref/basics.pngbin5623 -> 5179 bytes
-rw-r--r--tests/ref/comments.pngbin1469 -> 1332 bytes
-rw-r--r--tests/ref/dictionaries.pngbin1857 -> 1769 bytes
-rw-r--r--tests/ref/empty.pngbin120 -> 94 bytes
-rw-r--r--tests/ref/escaping.pngbin4401 -> 4148 bytes
-rw-r--r--tests/ref/func-font.pngbin5517 -> 5386 bytes
-rw-r--r--tests/ref/func-hv.pngbin4449 -> 3961 bytes
-rw-r--r--tests/ref/func-image.pngbin301847 -> 220343 bytes
-rw-r--r--tests/ref/func-page.pngbin8858 -> 8099 bytes
-rw-r--r--tests/ref/func-pagebreak.pngbin1039 -> 821 bytes
-rw-r--r--tests/ref/func-rgb.pngbin2727 -> 2688 bytes
-rw-r--r--tests/ref/headings.pngbin8197 -> 7850 bytes
-rw-r--r--tests/typ/func-hv.typ10
-rw-r--r--tests/typ/func-image.typ4
-rw-r--r--tests/typ/func-page.typ28
-rw-r--r--tests/typ/headings.typ5
-rw-r--r--tests/typeset.rs20
31 files changed, 155 insertions, 103 deletions
diff --git a/src/eval/context.rs b/src/eval/context.rs
index 64a8fbbe..1e09aaaf 100644
--- a/src/eval/context.rs
+++ b/src/eval/context.rs
@@ -95,6 +95,7 @@ impl EvalContext {
pub fn start_page_group(&mut self, softness: Softness) {
self.start_group(PageGroup {
size: self.state.page.size,
+ expand: self.state.page.expand,
padding: self.state.page.margins(),
dirs: self.state.dirs,
align: self.state.align,
@@ -124,7 +125,7 @@ impl EvalContext {
child: NodeStack {
dirs: group.dirs,
align: group.align,
- expansion: Gen::uniform(Expansion::Fill),
+ expand: group.expand,
children,
}
.into(),
@@ -281,6 +282,7 @@ pub enum Softness {
#[derive(Debug)]
struct PageGroup {
size: Size,
+ expand: Spec<Expansion>,
padding: Sides<Linear>,
dirs: LayoutDirs,
align: ChildAlign,
diff --git a/src/eval/mod.rs b/src/eval/mod.rs
index 0e6fa79f..9abc1074 100644
--- a/src/eval/mod.rs
+++ b/src/eval/mod.rs
@@ -19,7 +19,7 @@ use std::rc::Rc;
use crate::color::Color;
use crate::diag::Pass;
use crate::env::SharedEnv;
-use crate::geom::{Angle, Gen, Length, Relative};
+use crate::geom::{Angle, Length, Relative, Spec};
use crate::layout::{self, Expansion, NodeSpacing, NodeStack};
use crate::syntax::*;
@@ -137,7 +137,7 @@ impl Eval for Spanned<&NodeRaw> {
ctx.push(NodeStack {
dirs: ctx.state.dirs,
align: ctx.state.align,
- expansion: Gen::uniform(Expansion::Fit),
+ expand: Spec::uniform(Expansion::Fit),
children,
});
diff --git a/src/eval/state.rs b/src/eval/state.rs
index 2a8ee2f0..ce6bd009 100644
--- a/src/eval/state.rs
+++ b/src/eval/state.rs
@@ -4,8 +4,9 @@ use fontdock::{fallback, FallbackTree, FontStretch, FontStyle, FontVariant, Font
use super::Scope;
use crate::geom::{
- Align, ChildAlign, Dir, LayoutDirs, Length, Linear, Relative, Sides, Size,
+ Align, ChildAlign, Dir, LayoutDirs, Length, Linear, Relative, Sides, Size, Spec,
};
+use crate::layout::Expansion;
use crate::paper::{Paper, PaperClass, PAPER_A4};
/// The evaluation state.
@@ -45,6 +46,8 @@ pub struct StatePage {
pub class: PaperClass,
/// The width and height of the page.
pub size: Size,
+ /// Whether the expand the pages to the `size` or to fit the content.
+ pub expand: Spec<Expansion>,
/// The amount of white space in the order [left, top, right, bottom]. If a
/// side is set to `None`, the default for the paper class is used.
pub margins: Sides<Option<Linear>>,
@@ -56,6 +59,7 @@ impl StatePage {
Self {
class: paper.class,
size: paper.size(),
+ expand: Spec::uniform(Expansion::Fill),
margins: Sides::uniform(None),
}
}
diff --git a/src/geom/length.rs b/src/geom/length.rs
index f4d8682e..bfb1d668 100644
--- a/src/geom/length.rs
+++ b/src/geom/length.rs
@@ -81,6 +81,16 @@ impl Length {
Self { raw: self.raw.max(other.raw) }
}
+ /// Whether the length is finite.
+ pub fn is_finite(self) -> bool {
+ self.raw.is_finite()
+ }
+
+ /// Whether the length is infinite.
+ pub fn is_infinite(self) -> bool {
+ self.raw.is_infinite()
+ }
+
/// Whether the length is `NaN`.
pub fn is_nan(self) -> bool {
self.raw.is_nan()
diff --git a/src/geom/relative.rs b/src/geom/relative.rs
index 8fd430af..d39ead3a 100644
--- a/src/geom/relative.rs
+++ b/src/geom/relative.rs
@@ -26,7 +26,12 @@ impl Relative {
/// Resolve this relative to the given `length`.
pub fn resolve(self, length: Length) -> Length {
- self.get() * length
+ // Zero wins over infinity.
+ if self.0 == 0.0 {
+ Length::ZERO
+ } else {
+ self.get() * length
+ }
}
}
diff --git a/src/geom/size.rs b/src/geom/size.rs
index 1dfc8b97..caba3d8b 100644
--- a/src/geom/size.rs
+++ b/src/geom/size.rs
@@ -31,6 +31,16 @@ impl Size {
self.width >= other.width && self.height >= other.height
}
+ /// Whether both components are finite.
+ pub fn is_finite(self) -> bool {
+ self.width.is_finite() && self.height.is_finite()
+ }
+
+ /// Whether any of the two components is infinite.
+ pub fn is_infinite(self) -> bool {
+ self.width.is_infinite() || self.height.is_infinite()
+ }
+
/// Whether any of the two components is `NaN`.
pub fn is_nan(self) -> bool {
self.width.is_nan() || self.height.is_nan()
diff --git a/src/layout/fixed.rs b/src/layout/fixed.rs
index cb69b178..60dbe4d6 100644
--- a/src/layout/fixed.rs
+++ b/src/layout/fixed.rs
@@ -14,10 +14,10 @@ pub struct NodeFixed {
impl Layout for NodeFixed {
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
- let Area { rem, full } = areas.current;
+ let Areas { current, full, .. } = areas;
let size = Size::new(
- self.width.map(|w| w.resolve(full.width)).unwrap_or(rem.width),
- self.height.map(|h| h.resolve(full.height)).unwrap_or(rem.height),
+ self.width.map(|w| w.resolve(full.width)).unwrap_or(current.width),
+ self.height.map(|h| h.resolve(full.height)).unwrap_or(current.height),
);
let areas = Areas::once(size);
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 30026b9f..714bac4b 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -71,27 +71,13 @@ pub struct LayoutContext {
pub env: SharedEnv,
}
-/// An area into which content can be laid out.
-#[derive(Debug, Copy, Clone, PartialEq)]
-pub struct Area {
- /// The remaining size of this area.
- pub rem: Size,
- /// The full size this area once had (used for relative sizing).
- pub full: Size,
-}
-
-impl Area {
- /// Create a new area.
- pub fn new(size: Size) -> Self {
- Self { rem: size, full: size }
- }
-}
-
/// A collection of areas to layout into.
#[derive(Debug, Clone, PartialEq)]
pub struct Areas {
- /// The current area.
- pub current: Area,
+ /// The remaining size of the current area.
+ pub current: Size,
+ /// The full size the current area once had (used for relative sizing).
+ pub full: Size,
/// A stack of followup areas (the next area is the last element).
pub backlog: Vec<Size>,
/// The final area that is repeated when the backlog is empty.
@@ -102,7 +88,8 @@ impl Areas {
/// Create a new length-1 sequence of areas with just one `area`.
pub fn once(size: Size) -> Self {
Self {
- current: Area::new(size),
+ current: size,
+ full: size,
backlog: vec![],
last: None,
}
@@ -111,7 +98,8 @@ impl Areas {
/// Create a new sequence of areas that repeats `area` indefinitely.
pub fn repeat(size: Size) -> Self {
Self {
- current: Area::new(size),
+ current: size,
+ full: size,
backlog: vec![],
last: Some(size),
}
@@ -120,7 +108,8 @@ impl Areas {
/// Advance to the next area if there is any.
pub fn next(&mut self) {
if let Some(size) = self.backlog.pop().or(self.last) {
- self.current = Area::new(size);
+ self.current = size;
+ self.full = size;
}
}
@@ -130,11 +119,32 @@ impl Areas {
pub fn in_full_last(&self) -> bool {
self.backlog.is_empty()
&& self.last.map_or(true, |size| {
- self.current.rem.is_nan() || size.is_nan() || self.current.rem == size
+ self.current.is_nan() || size.is_nan() || self.current == size
})
}
}
+/// Whether to expand or shrink a node along an axis.
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum Expansion {
+ /// Fit the content.
+ Fit,
+ /// Fill the available space.
+ Fill,
+}
+
+impl Expansion {
+ /// Resolve the expansion to either the `fit` or `fill` length.
+ ///
+ /// Prefers `fit` if `fill` is infinite.
+ pub fn resolve(self, fit: Length, fill: Length) -> Length {
+ match self {
+ Self::Fill if fill.is_finite() => fill,
+ _ => fit,
+ }
+ }
+}
+
/// The result of layouting a node.
#[derive(Debug, Clone, PartialEq)]
pub enum Layouted {
@@ -158,15 +168,6 @@ impl Layouted {
}
}
-/// Whether to expand or shrink a node along an axis.
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub enum Expansion {
- /// Fit the content.
- Fit,
- /// Fill the available space.
- Fill,
-}
-
/// A finished layout with elements at fixed positions.
#[derive(Debug, Clone, PartialEq)]
pub struct Frame {
diff --git a/src/layout/pad.rs b/src/layout/pad.rs
index 9e2718c3..f8a623e3 100644
--- a/src/layout/pad.rs
+++ b/src/layout/pad.rs
@@ -39,10 +39,8 @@ impl From<NodePad> for NodeAny {
fn shrink(areas: &Areas, padding: Sides<Linear>) -> Areas {
let shrink = |size| size - padding.resolve(size).size();
Areas {
- current: Area {
- rem: shrink(areas.current.rem),
- full: shrink(areas.current.full),
- },
+ current: shrink(areas.current),
+ full: shrink(areas.full),
backlog: areas.backlog.iter().copied().map(shrink).collect(),
last: areas.last.map(shrink),
}
diff --git a/src/layout/par.rs b/src/layout/par.rs
index 7b2e4e92..2a1ad941 100644
--- a/src/layout/par.rs
+++ b/src/layout/par.rs
@@ -74,7 +74,7 @@ impl<'a> ParLayouter<'a> {
}
fn push_spacing(&mut self, amount: Length) {
- let cross_max = self.areas.current.rem.get(self.cross);
+ let cross_max = self.areas.current.get(self.cross);
self.run_size.cross = (self.run_size.cross + amount).min(cross_max);
}
@@ -84,7 +84,7 @@ impl<'a> ParLayouter<'a> {
}
let fits = {
- let mut usable = self.areas.current.rem;
+ let mut usable = self.areas.current;
*usable.get_mut(self.cross) -= self.run_size.cross;
usable.fits(frame.size)
};
@@ -92,7 +92,7 @@ impl<'a> ParLayouter<'a> {
if !fits {
self.finish_run();
- while !self.areas.current.rem.fits(frame.size) {
+ while !self.areas.current.fits(frame.size) {
if self.areas.in_full_last() {
// TODO: Diagnose once the necessary spans exist.
let _ = warning!("cannot fit frame into any area");
@@ -112,10 +112,15 @@ impl<'a> ParLayouter<'a> {
}
fn finish_run(&mut self) {
- let full_size = Gen::new(self.run_size.main, match self.par.cross_expansion {
- Expansion::Fill => self.areas.current.full.get(self.cross),
- Expansion::Fit => self.run_size.cross,
- });
+ let full_size = {
+ let full = self.areas.full.switch(self.dirs);
+ Gen::new(
+ self.run_size.main,
+ self.par
+ .cross_expansion
+ .resolve(self.run_size.cross.min(full.cross), full.cross),
+ )
+ };
let mut output = Frame::new(full_size.switch(self.dirs).to_size());
@@ -139,7 +144,7 @@ impl<'a> ParLayouter<'a> {
self.lines.push((self.lines_size.main, output, self.run_ruler));
let main_offset = full_size.main + self.par.line_spacing;
- *self.areas.current.rem.get_mut(self.main) -= main_offset;
+ *self.areas.current.get_mut(self.main) -= main_offset;
self.lines_size.main += main_offset;
self.lines_size.cross = self.lines_size.cross.max(full_size.cross);
diff --git a/src/layout/stack.rs b/src/layout/stack.rs
index eac631d9..bfb93a94 100644
--- a/src/layout/stack.rs
+++ b/src/layout/stack.rs
@@ -11,7 +11,7 @@ pub struct NodeStack {
/// How to align this stack in _its_ parent.
pub align: ChildAlign,
/// Whether to expand the axes to fill the area or to fit the content.
- pub expansion: Gen<Expansion>,
+ pub expand: Spec<Expansion>,
/// The nodes to be stacked.
pub children: Vec<Node>,
}
@@ -66,7 +66,7 @@ impl<'a> StackLayouter<'a> {
}
fn push_spacing(&mut self, amount: Length) {
- let main_rest = self.areas.current.rem.get_mut(self.main);
+ let main_rest = self.areas.current.get_mut(self.main);
let capped = amount.min(*main_rest);
*main_rest -= capped;
self.used.main += capped;
@@ -77,7 +77,7 @@ impl<'a> StackLayouter<'a> {
self.finish_area();
}
- while !self.areas.current.rem.fits(frame.size) {
+ while !self.areas.current.fits(frame.size) {
if self.areas.in_full_last() {
// TODO: Diagnose once the necessary spans exist.
let _ = warning!("cannot fit frame into any area");
@@ -90,7 +90,7 @@ impl<'a> StackLayouter<'a> {
let size = frame.size.switch(self.dirs);
self.frames.push((self.used.main, frame, align));
- *self.areas.current.rem.get_mut(self.main) -= size.main;
+ *self.areas.current.get_mut(self.main) -= size.main;
self.used.main += size.main;
self.used.cross = self.used.cross.max(size.cross);
self.ruler = align.main;
@@ -98,16 +98,11 @@ impl<'a> StackLayouter<'a> {
fn finish_area(&mut self) {
let full_size = {
- let full = self.areas.current.full.switch(self.dirs);
+ let expand = self.stack.expand.switch(self.dirs);
+ let full = self.areas.full.switch(self.dirs);
Gen::new(
- match self.stack.expansion.main {
- Expansion::Fill => full.main,
- Expansion::Fit => self.used.main.min(full.main),
- },
- match self.stack.expansion.cross {
- Expansion::Fill => full.cross,
- Expansion::Fit => self.used.cross.min(full.cross),
- },
+ expand.main.resolve(self.used.main.min(full.main), full.main),
+ expand.cross.resolve(self.used.cross.min(full.cross), full.cross),
)
};
diff --git a/src/library/insert.rs b/src/library/insert.rs
index 8d60927a..51cbbf52 100644
--- a/src/library/insert.rs
+++ b/src/library/insert.rs
@@ -55,8 +55,11 @@ struct NodeImage {
impl Layout for NodeImage {
fn layout(&self, _: &mut LayoutContext, areas: &Areas) -> Layouted {
- let Area { rem, full } = areas.current;
- let pixel_ratio = (self.dimensions.0 as f64) / (self.dimensions.1 as f64);
+ let Areas { current, full, .. } = areas;
+
+ let pixel_width = self.dimensions.0 as f64;
+ let pixel_height = self.dimensions.1 as f64;
+ let pixel_ratio = pixel_width / pixel_height;
let width = self.width.map(|w| w.resolve(full.width));
let height = self.height.map(|w| w.resolve(full.height));
@@ -66,12 +69,15 @@ impl Layout for NodeImage {
(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 {
+ 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(rem.height * pixel_ratio, rem.height)
+ Size::new(current.height * pixel_ratio, current.height)
+ } else {
+ // Totally unbounded area, we have to make up something.
+ Size::new(Length::pt(pixel_width), Length::pt(pixel_height))
}
}
};
diff --git a/src/library/layout.rs b/src/library/layout.rs
index 59c1954b..0e04c507 100644
--- a/src/library/layout.rs
+++ b/src/library/layout.rs
@@ -197,13 +197,12 @@ pub fn box_(ctx: &mut EvalContext, args: &mut Args) -> Value {
let children = ctx.end_content_group();
let fill_if = |c| if c { Expansion::Fill } else { Expansion::Fit };
- let expansion =
- Spec::new(fill_if(width.is_some()), fill_if(height.is_some())).switch(dirs);
+ let expand = Spec::new(fill_if(width.is_some()), fill_if(height.is_some()));
ctx.push(NodeFixed {
width,
height,
- child: NodeStack { dirs, align, expansion, children }.into(),
+ child: NodeStack { dirs, align, expand, children }.into(),
});
ctx.state = snapshot;
@@ -271,6 +270,7 @@ pub fn page(ctx: &mut EvalContext, args: &mut Args) -> Value {
if let Some(paper) = Paper::from_name(&name.v) {
ctx.state.page.class = paper.class;
ctx.state.page.size = paper.size();
+ ctx.state.page.expand = Spec::uniform(Expansion::Fill);
} else {
ctx.diag(error!(name.span, "invalid paper name"));
}
@@ -279,11 +279,13 @@ pub fn page(ctx: &mut EvalContext, args: &mut Args) -> Value {
if let Some(width) = args.get(ctx, "width") {
ctx.state.page.class = PaperClass::Custom;
ctx.state.page.size.width = width;
+ ctx.state.page.expand.horizontal = Expansion::Fill;
}
if let Some(height) = args.get(ctx, "height") {
ctx.state.page.class = PaperClass::Custom;
ctx.state.page.size.height = height;
+ ctx.state.page.expand.vertical = Expansion::Fill;
}
if let Some(margins) = args.get(ctx, "margins") {
@@ -307,8 +309,9 @@ pub fn page(ctx: &mut EvalContext, args: &mut Args) -> Value {
}
if args.get(ctx, "flip").unwrap_or(false) {
- let size = &mut ctx.state.page.size;
- std::mem::swap(&mut size.width, &mut size.height);
+ let page = &mut ctx.state.page;
+ std::mem::swap(&mut page.size.width, &mut page.size.height);
+ std::mem::swap(&mut page.expand.horizontal, &mut page.expand.vertical);
}
let main = args.get(ctx, "main-dir");
diff --git a/tests/ref/arrays.png b/tests/ref/arrays.png
index 8fda7cf6..2d70a3f6 100644
--- a/tests/ref/arrays.png
+++ b/tests/ref/arrays.png
Binary files differ
diff --git a/tests/ref/basics.png b/tests/ref/basics.png
index d65b7fe5..fbe85320 100644
--- a/tests/ref/basics.png
+++ b/tests/ref/basics.png
Binary files differ
diff --git a/tests/ref/comments.png b/tests/ref/comments.png
index 399d25a1..e3e42d23 100644
--- a/tests/ref/comments.png
+++ b/tests/ref/comments.png
Binary files differ
diff --git a/tests/ref/dictionaries.png b/tests/ref/dictionaries.png
index 42cb431d..aa40549e 100644
--- a/tests/ref/dictionaries.png
+++ b/tests/ref/dictionaries.png
Binary files differ
diff --git a/tests/ref/empty.png b/tests/ref/empty.png
index 812a3758..87c06b0a 100644
--- a/tests/ref/empty.png
+++ b/tests/ref/empty.png
Binary files differ
diff --git a/tests/ref/escaping.png b/tests/ref/escaping.png
index 06c0310d..575a4b2f 100644
--- a/tests/ref/escaping.png
+++ b/tests/ref/escaping.png
Binary files differ
diff --git a/tests/ref/func-font.png b/tests/ref/func-font.png
index 18841490..1e025c6f 100644
--- a/tests/ref/func-font.png
+++ b/tests/ref/func-font.png
Binary files differ
diff --git a/tests/ref/func-hv.png b/tests/ref/func-hv.png
index 6f47ae09..ee649fb6 100644
--- a/tests/ref/func-hv.png
+++ b/tests/ref/func-hv.png
Binary files differ
diff --git a/tests/ref/func-image.png b/tests/ref/func-image.png
index e2b647bf..70f263e6 100644
--- a/tests/ref/func-image.png
+++ b/tests/ref/func-image.png
Binary files differ
diff --git a/tests/ref/func-page.png b/tests/ref/func-page.png
index 9bde2dae..fb1b7b39 100644
--- a/tests/ref/func-page.png
+++ b/tests/ref/func-page.png
Binary files differ
diff --git a/tests/ref/func-pagebreak.png b/tests/ref/func-pagebreak.png
index 50686ff9..16eae0e4 100644
--- a/tests/ref/func-pagebreak.png
+++ b/tests/ref/func-pagebreak.png
Binary files differ
diff --git a/tests/ref/func-rgb.png b/tests/ref/func-rgb.png
index 239a9e5a..3060e42c 100644
--- a/tests/ref/func-rgb.png
+++ b/tests/ref/func-rgb.png
Binary files differ
diff --git a/tests/ref/headings.png b/tests/ref/headings.png
index 3deecf8f..1f374cce 100644
--- a/tests/ref/headings.png
+++ b/tests/ref/headings.png
Binary files differ
diff --git a/tests/typ/func-hv.typ b/tests/typ/func-hv.typ
index f930bc12..b32a645c 100644
--- a/tests/typ/func-hv.typ
+++ b/tests/typ/func-hv.typ
@@ -12,13 +12,13 @@ Add [h 10pt] [h 10pt] up
// Relative to font size.
Relative [h 100%] spacing
+// Missing spacing.
+// Error: 1:11-1:11 missing argument: spacing
+Totally [h] ignored
+
// Swapped axes.
-[page main-dir: rtl, cross-dir: ttb][
+[page main-dir: rtl, cross-dir: ttb, height: 80pt][
1 [h 1cm] 2
3 [v 1cm] 4 [v -1cm] 5
]
-
-// Missing spacing.
-// Error: 1:11-1:11 missing argument: spacing
-Totally [h] ignored
diff --git a/tests/typ/func-image.typ b/tests/typ/func-image.typ
index b0ca0357..1f94a66f 100644
--- a/tests/typ/func-image.typ
+++ b/tests/typ/func-image.typ
@@ -14,7 +14,7 @@
[image "res/rhino.png"]
// Fit to height of page.
-[page width: 270pt][
+[page height: 40pt][
[image "res/rhino.png"]
]
@@ -29,7 +29,7 @@
// Make sure the bounding-box of the image is correct.
[align bottom, right][
- [image "res/tiger.jpg"]
+ [image "res/tiger.jpg", width: 60pt]
]
---
diff --git a/tests/typ/func-page.typ b/tests/typ/func-page.typ
index 465a3469..49671e14 100644
--- a/tests/typ/func-page.typ
+++ b/tests/typ/func-page.typ
@@ -1,28 +1,36 @@
// Test configuring page sizes and margins.
-// Set width.
-[page width: 50pt][High]
-
-// Set height.
-[page height: 50pt][Wide]
+// Set width and height.
+[page width: 120pt, height: 120pt]
+[page width: 40pt][High]
+[page height: 40pt][Wide]
// Set all margins at once.
-[page margins: 40pt][
+[page margins: 30pt][
[align top, left][TL]
[align bottom, right][BR]
]
// Set individual margins.
+[page height: 40pt]
[page left: 0pt | align left][Left]
[page right: 0pt | align right][Right]
[page top: 0pt | align top][Top]
[page bottom: 0pt | align bottom][Bottom]
// Ensure that specific margins override general margins.
-[page margins: 0pt, left: 40pt][Overriden]
+[page margins: 0pt, left: 20pt][Overriden]
+
+---
+// Test flipping.
+
+// Flipped predefined paper.
+[page "a11", flip: true][Flipped A11]
-// Flip the page.
-[page "a10", flip: true][Flipped]
+// Flipped custom page size.
+[page width: 40pt, height: 120pt]
+[page flip: true]
+Wide
---
// Test a combination of pages with bodies and normal content.
@@ -40,7 +48,7 @@ Sixth
---
// Test changing the layouting directions of pages.
-[page main-dir: btt, cross-dir: rtl]
+[page height: 50pt, main-dir: btt, cross-dir: rtl]
Right to left!
diff --git a/tests/typ/headings.typ b/tests/typ/headings.typ
index de98eddb..0f364a9b 100644
--- a/tests/typ/headings.typ
+++ b/tests/typ/headings.typ
@@ -8,15 +8,12 @@
####### Seven
---
-// Is a heading.
+// Heading vs. no heading.
/**/ # Heading
{[## Heading]}
[box][### Heading]
----
-// Is no heading.
-
\# No heading
Text with # hashtag
diff --git a/tests/typeset.rs b/tests/typeset.rs
index 499c5c04..f67649b0 100644
--- a/tests/typeset.rs
+++ b/tests/typeset.rs
@@ -18,8 +18,8 @@ use typst::env::{Env, ImageResource, ResourceLoader, SharedEnv};
use typst::eval::{Args, EvalContext, State, Value, ValueFunc};
use typst::export::pdf;
use typst::font::FontLoader;
-use typst::geom::{Length, Point, Sides, Size};
-use typst::layout::{Element, Frame, Image};
+use typst::geom::{Length, Point, Sides, Size, Spec};
+use typst::layout::{Element, Expansion, Frame, Image};
use typst::parse::{LineMap, Scanner};
use typst::shaping::Shaped;
use typst::syntax::{Location, Pos, SpanVec, Spanned, WithSpan};
@@ -153,12 +153,12 @@ fn test(
let env = env.borrow();
if !frames.is_empty() {
- let canvas = draw(&frames, &env, 2.0);
- canvas.pixmap.save_png(png_path).unwrap();
-
let pdf_data = pdf::export(&frames, &env);
fs::write(pdf_path, pdf_data).unwrap();
+ let canvas = draw(&frames, &env, 2.0);
+ canvas.pixmap.save_png(png_path).unwrap();
+
if let Some(ref_path) = ref_path {
if let Ok(ref_pixmap) = Pixmap::load_png(ref_path) {
if canvas.pixmap != ref_pixmap {
@@ -184,7 +184,11 @@ fn test_part(i: usize, src: &str, env: &SharedEnv) -> (bool, Vec<Frame>) {
let (compare_ref, ref_diags) = parse_metadata(src, &map);
let mut state = State::default();
- state.page.size = Size::uniform(Length::pt(120.0));
+
+ // We want to have "unbounded" pages, so we allow them to be infinitely
+ // large and fit them to match their content.
+ state.page.size = Size::new(Length::pt(120.0), Length::raw(f64::INFINITY));
+ state.page.expand = Spec::new(Expansion::Fill, Expansion::Fit);
state.page.margins = Sides::uniform(Some(Length::pt(10.0).into()));
pub fn dump(_: &mut EvalContext, args: &mut Args) -> Value {
@@ -283,6 +287,10 @@ fn draw(frames: &[Frame], env: &Env, pixel_per_pt: f32) -> Canvas {
let pixel_width = (pixel_per_pt * width.to_pt() as f32) as u32;
let pixel_height = (pixel_per_pt * height.to_pt() as f32) as u32;
+ if pixel_width > 4000 || pixel_height > 4000 {
+ panic!("overlarge image: {} by {}", pixel_width, pixel_height);
+ }
+
let mut canvas = Canvas::new(pixel_width, pixel_height).unwrap();
canvas.scale(pixel_per_pt, pixel_per_pt);
canvas.pixmap.fill(Color::BLACK);