summaryrefslogtreecommitdiff
path: root/src/library/layout
diff options
context:
space:
mode:
Diffstat (limited to 'src/library/layout')
-rw-r--r--src/library/layout/columns.rs5
-rw-r--r--src/library/layout/flow.rs20
-rw-r--r--src/library/layout/grid.rs16
-rw-r--r--src/library/layout/pad.rs11
-rw-r--r--src/library/layout/page.rs24
-rw-r--r--src/library/layout/place.rs6
-rw-r--r--src/library/layout/spacing.rs2
-rw-r--r--src/library/layout/stack.rs16
8 files changed, 54 insertions, 46 deletions
diff --git a/src/library/layout/columns.rs b/src/library/layout/columns.rs
index 1cb45c37..3ef66b40 100644
--- a/src/library/layout/columns.rs
+++ b/src/library/layout/columns.rs
@@ -14,7 +14,8 @@ pub struct ColumnsNode {
#[node]
impl ColumnsNode {
/// The size of the gutter space between each column.
- pub const GUTTER: Relative<Length> = Ratio::new(0.04).into();
+ #[property(resolve)]
+ pub const GUTTER: Relative<RawLength> = Ratio::new(0.04).into();
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::block(Self {
@@ -39,7 +40,7 @@ impl Layout for ColumnsNode {
// Determine the width of the gutter and each column.
let columns = self.columns.get();
- let gutter = styles.get(Self::GUTTER).resolve(regions.base.x);
+ let gutter = styles.get(Self::GUTTER).relative_to(regions.base.x);
let width = (regions.first.x - gutter * (columns - 1) as f64) / columns as f64;
// Create the pod regions.
diff --git a/src/library/layout/flow.rs b/src/library/layout/flow.rs
index a53b0304..a3947e34 100644
--- a/src/library/layout/flow.rs
+++ b/src/library/layout/flow.rs
@@ -1,6 +1,6 @@
use super::{AlignNode, PlaceNode, Spacing};
use crate::library::prelude::*;
-use crate::library::text::{ParNode, TextNode};
+use crate::library::text::ParNode;
/// Arrange spacing, paragraphs and other block-level nodes into a flow.
///
@@ -37,22 +37,20 @@ impl Layout for FlowNode {
let styles = map.chain(&styles);
match child {
FlowChild::Leading => {
- let em = styles.get(TextNode::SIZE);
- let amount = styles.get(ParNode::LEADING).resolve(em);
- layouter.layout_spacing(amount.into());
+ let amount = styles.get(ParNode::LEADING);
+ layouter.layout_spacing(amount.into(), styles);
}
FlowChild::Parbreak => {
- let em = styles.get(TextNode::SIZE);
let leading = styles.get(ParNode::LEADING);
let spacing = styles.get(ParNode::SPACING);
- let amount = (leading + spacing).resolve(em);
- layouter.layout_spacing(amount.into());
+ let amount = leading + spacing;
+ layouter.layout_spacing(amount.into(), styles);
}
FlowChild::Colbreak => {
layouter.finish_region();
}
FlowChild::Spacing(kind) => {
- layouter.layout_spacing(*kind);
+ layouter.layout_spacing(*kind, styles);
}
FlowChild::Node(ref node) => {
layouter.layout_node(ctx, node, styles)?;
@@ -142,11 +140,11 @@ impl FlowLayouter {
}
/// Layout spacing.
- pub fn layout_spacing(&mut self, spacing: Spacing) {
+ pub fn layout_spacing(&mut self, spacing: Spacing, styles: StyleChain) {
match spacing {
Spacing::Relative(v) => {
// Resolve the spacing and limit it to the remaining space.
- let resolved = v.resolve(self.full.y);
+ let resolved = v.resolve(styles).relative_to(self.full.y);
let limited = resolved.min(self.regions.first.y);
self.regions.first.y -= limited;
self.used.y += limited;
@@ -235,7 +233,7 @@ impl FlowLayouter {
offset += v;
}
FlowItem::Fractional(v) => {
- offset += v.resolve(self.fr, remaining);
+ offset += v.share(self.fr, remaining);
}
FlowItem::Frame(frame, aligns) => {
ruler = ruler.max(aligns.y);
diff --git a/src/library/layout/grid.rs b/src/library/layout/grid.rs
index b1e5e54c..ad6323d5 100644
--- a/src/library/layout/grid.rs
+++ b/src/library/layout/grid.rs
@@ -58,7 +58,7 @@ pub enum TrackSizing {
Auto,
/// A track size specified in absolute terms and relative to the parent's
/// size.
- Relative(Relative<Length>),
+ Relative(Relative<RawLength>),
/// A track size specified as a fraction of the remaining free space in the
/// parent.
Fractional(Fraction),
@@ -236,7 +236,8 @@ impl<'a> GridLayouter<'a> {
match col {
TrackSizing::Auto => {}
TrackSizing::Relative(v) => {
- let resolved = v.resolve(self.regions.base.x);
+ let resolved =
+ v.resolve(self.styles).relative_to(self.regions.base.x);
*rcol = resolved;
rel += resolved;
}
@@ -295,7 +296,8 @@ impl<'a> GridLayouter<'a> {
// base, for auto it's already correct and for fr we could
// only guess anyway.
if let TrackSizing::Relative(v) = self.rows[y] {
- pod.base.y = v.resolve(self.regions.base.y);
+ pod.base.y =
+ v.resolve(self.styles).relative_to(self.regions.base.y);
}
let frame = node.layout(ctx, &pod, self.styles)?.remove(0);
@@ -315,7 +317,7 @@ impl<'a> GridLayouter<'a> {
fn grow_fractional_columns(&mut self, remaining: Length, fr: Fraction) {
for (&col, rcol) in self.cols.iter().zip(&mut self.rcols) {
if let TrackSizing::Fractional(v) = col {
- *rcol = v.resolve(fr, remaining);
+ *rcol = v.share(fr, remaining);
}
}
}
@@ -422,10 +424,10 @@ impl<'a> GridLayouter<'a> {
fn layout_relative_row(
&mut self,
ctx: &mut Context,
- v: Relative<Length>,
+ v: Relative<RawLength>,
y: usize,
) -> TypResult<()> {
- let resolved = v.resolve(self.regions.base.y);
+ let resolved = v.resolve(self.styles).relative_to(self.regions.base.y);
let frame = self.layout_single_row(ctx, resolved, y)?;
// Skip to fitting region.
@@ -543,7 +545,7 @@ impl<'a> GridLayouter<'a> {
Row::Frame(frame) => frame,
Row::Fr(v, y) => {
let remaining = self.full - self.used.y;
- let height = v.resolve(self.fr, remaining);
+ let height = v.share(self.fr, remaining);
self.layout_single_row(ctx, height, y)?
}
};
diff --git a/src/library/layout/pad.rs b/src/library/layout/pad.rs
index b7470540..e688e423 100644
--- a/src/library/layout/pad.rs
+++ b/src/library/layout/pad.rs
@@ -4,7 +4,7 @@ use crate::library::prelude::*;
#[derive(Debug, Hash)]
pub struct PadNode {
/// The amount of padding.
- pub padding: Sides<Relative<Length>>,
+ pub padding: Sides<Relative<RawLength>>,
/// The child node whose sides to pad.
pub child: LayoutNode,
}
@@ -33,14 +33,15 @@ impl Layout for PadNode {
styles: StyleChain,
) -> TypResult<Vec<Arc<Frame>>> {
// Layout child into padded regions.
- let pod = regions.map(|size| shrink(size, self.padding));
+ let padding = self.padding.resolve(styles);
+ let pod = regions.map(|size| shrink(size, padding));
let mut frames = self.child.layout(ctx, &pod, styles)?;
for frame in &mut frames {
// Apply the padding inversely such that the grown size padded
// yields the frame's size.
- let padded = grow(frame.size, self.padding);
- let padding = self.padding.resolve(padded);
+ let padded = grow(frame.size, padding);
+ let padding = padding.relative_to(padded);
let offset = Point::new(padding.left, padding.top);
// Grow the frame and translate everything in the frame inwards.
@@ -55,7 +56,7 @@ impl Layout for PadNode {
/// Shrink a size by padding relative to the size itself.
fn shrink(size: Size, padding: Sides<Relative<Length>>) -> Size {
- size - padding.resolve(size).sum_by_axis()
+ size - padding.relative_to(size).sum_by_axis()
}
/// Grow a size by padding relative to the grown size.
diff --git a/src/library/layout/page.rs b/src/library/layout/page.rs
index 37a87ae2..7aa53b23 100644
--- a/src/library/layout/page.rs
+++ b/src/library/layout/page.rs
@@ -10,19 +10,21 @@ pub struct PageNode(pub LayoutNode);
#[node]
impl PageNode {
/// The unflipped width of the page.
- pub const WIDTH: Smart<Length> = Smart::Custom(Paper::A4.width());
+ #[property(resolve)]
+ pub const WIDTH: Smart<RawLength> = Smart::Custom(Paper::A4.width().into());
/// The unflipped height of the page.
- pub const HEIGHT: Smart<Length> = Smart::Custom(Paper::A4.height());
+ #[property(resolve)]
+ pub const HEIGHT: Smart<RawLength> = Smart::Custom(Paper::A4.height().into());
/// Whether the page is flipped into landscape orientation.
pub const FLIPPED: bool = false;
/// The left margin.
- pub const LEFT: Smart<Relative<Length>> = Smart::Auto;
+ pub const LEFT: Smart<Relative<RawLength>> = Smart::Auto;
/// The right margin.
- pub const RIGHT: Smart<Relative<Length>> = Smart::Auto;
+ pub const RIGHT: Smart<Relative<RawLength>> = Smart::Auto;
/// The top margin.
- pub const TOP: Smart<Relative<Length>> = Smart::Auto;
+ pub const TOP: Smart<Relative<RawLength>> = Smart::Auto;
/// The bottom margin.
- pub const BOTTOM: Smart<Relative<Length>> = Smart::Auto;
+ pub const BOTTOM: Smart<Relative<RawLength>> = Smart::Auto;
/// The page's background color.
pub const FILL: Option<Paint> = None;
/// How many columns the page has.
@@ -42,8 +44,8 @@ impl PageNode {
let mut styles = StyleMap::new();
if let Some(paper) = args.named_or_find::<Paper>("paper")? {
- styles.set(Self::WIDTH, Smart::Custom(paper.width()));
- styles.set(Self::HEIGHT, Smart::Custom(paper.height()));
+ styles.set(Self::WIDTH, Smart::Custom(paper.width().into()));
+ styles.set(Self::HEIGHT, Smart::Custom(paper.height().into()));
}
styles.set_opt(Self::WIDTH, args.named("width")?);
@@ -115,7 +117,7 @@ impl PageNode {
}
// Layout the child.
- let regions = Regions::repeat(size, size, size.map(Numeric::is_finite));
+ let regions = Regions::repeat(size, size, size.map(Length::is_finite));
let mut frames = child.layout(ctx, &regions, styles)?;
let header = styles.get(Self::HEADER);
@@ -124,7 +126,7 @@ impl PageNode {
// Realize header and footer.
for frame in &mut frames {
let size = frame.size;
- let padding = padding.resolve(size);
+ let padding = padding.resolve(styles).relative_to(size);
for (y, h, marginal) in [
(Length::zero(), padding.top, header),
(size.y - padding.bottom, padding.bottom, footer),
@@ -133,7 +135,7 @@ impl PageNode {
let pos = Point::new(padding.left, y);
let w = size.x - padding.left - padding.right;
let area = Size::new(w, h);
- let pod = Regions::one(area, area, area.map(Numeric::is_finite));
+ let pod = Regions::one(area, area, area.map(Length::is_finite));
let sub = Layout::layout(&content, ctx, &pod, styles)?.remove(0);
Arc::make_mut(frame).push_frame(pos, sub);
}
diff --git a/src/library/layout/place.rs b/src/library/layout/place.rs
index eefa6a9b..e74776db 100644
--- a/src/library/layout/place.rs
+++ b/src/library/layout/place.rs
@@ -8,12 +8,12 @@ pub struct PlaceNode(pub LayoutNode);
#[node]
impl PlaceNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
- let tx = args.named("dx")?.unwrap_or_default();
- let ty = args.named("dy")?.unwrap_or_default();
let aligns = args.find()?.unwrap_or(Spec::with_x(Some(RawAlign::Start)));
+ let dx = args.named("dx")?.unwrap_or_default();
+ let dy = args.named("dy")?.unwrap_or_default();
let body: LayoutNode = args.expect("body")?;
Ok(Content::block(Self(
- body.moved(Point::new(tx, ty)).aligned(aligns),
+ body.moved(Spec::new(dx, dy)).aligned(aligns),
)))
}
}
diff --git a/src/library/layout/spacing.rs b/src/library/layout/spacing.rs
index e9837ef5..3468af5e 100644
--- a/src/library/layout/spacing.rs
+++ b/src/library/layout/spacing.rs
@@ -24,7 +24,7 @@ impl VNode {
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Spacing {
/// Spacing specified in absolute terms and relative to the parent's size.
- Relative(Relative<Length>),
+ Relative(Relative<RawLength>),
/// Spacing specified as a fraction of the remaining free space in the parent.
Fractional(Fraction),
}
diff --git a/src/library/layout/stack.rs b/src/library/layout/stack.rs
index 312757f3..f915c215 100644
--- a/src/library/layout/stack.rs
+++ b/src/library/layout/stack.rs
@@ -30,7 +30,7 @@ impl Layout for StackNode {
regions: &Regions,
styles: StyleChain,
) -> TypResult<Vec<Arc<Frame>>> {
- let mut layouter = StackLayouter::new(self.dir, regions);
+ let mut layouter = StackLayouter::new(self.dir, regions, styles);
// Spacing to insert before the next node.
let mut deferred = None;
@@ -85,13 +85,15 @@ castable! {
}
/// Performs stack layout.
-pub struct StackLayouter {
+pub struct StackLayouter<'a> {
/// The stacking direction.
dir: Dir,
/// The axis of the stacking direction.
axis: SpecAxis,
/// The regions to layout children into.
regions: Regions,
+ /// The inherited styles.
+ styles: StyleChain<'a>,
/// Whether the stack itself should expand to fill the region.
expand: Spec<bool>,
/// The full size of the current region that was available at the start.
@@ -117,9 +119,9 @@ enum StackItem {
Frame(Arc<Frame>, Align),
}
-impl StackLayouter {
+impl<'a> StackLayouter<'a> {
/// Create a new stack layouter.
- pub fn new(dir: Dir, regions: &Regions) -> Self {
+ pub fn new(dir: Dir, regions: &Regions, styles: StyleChain<'a>) -> Self {
let axis = dir.axis();
let expand = regions.expand;
let full = regions.first;
@@ -132,6 +134,7 @@ impl StackLayouter {
dir,
axis,
regions,
+ styles,
expand,
full,
used: Gen::zero(),
@@ -146,7 +149,8 @@ impl StackLayouter {
match spacing {
Spacing::Relative(v) => {
// Resolve the spacing and limit it to the remaining space.
- let resolved = v.resolve(self.regions.base.get(self.axis));
+ let resolved =
+ v.resolve(self.styles).relative_to(self.regions.base.get(self.axis));
let remaining = self.regions.first.get_mut(self.axis);
let limited = resolved.min(*remaining);
*remaining -= limited;
@@ -219,7 +223,7 @@ impl StackLayouter {
for item in self.items.drain(..) {
match item {
StackItem::Absolute(v) => cursor += v,
- StackItem::Fractional(v) => cursor += v.resolve(self.fr, remaining),
+ StackItem::Fractional(v) => cursor += v.share(self.fr, remaining),
StackItem::Frame(frame, align) => {
if self.dir.is_positive() {
ruler = ruler.max(align);