From 712c00ecb72b67da2c0788e5d3eb4dcc6366b2a7 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Fri, 8 Apr 2022 15:08:26 +0200 Subject: Em units --- src/library/layout/columns.rs | 5 +++-- src/library/layout/flow.rs | 20 +++++++++----------- src/library/layout/grid.rs | 16 +++++++++------- src/library/layout/pad.rs | 11 ++++++----- src/library/layout/page.rs | 24 +++++++++++++----------- src/library/layout/place.rs | 6 +++--- src/library/layout/spacing.rs | 2 +- src/library/layout/stack.rs | 16 ++++++++++------ 8 files changed, 54 insertions(+), 46 deletions(-) (limited to 'src/library/layout') 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 = Ratio::new(0.04).into(); + #[property(resolve)] + pub const GUTTER: Relative = Ratio::new(0.04).into(); fn construct(_: &mut Context, args: &mut Args) -> TypResult { 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), + Relative(Relative), /// 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, + v: Relative, 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>, + pub padding: Sides>, /// The child node whose sides to pad. pub child: LayoutNode, } @@ -33,14 +33,15 @@ impl Layout for PadNode { styles: StyleChain, ) -> TypResult>> { // 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>) -> 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 = Smart::Custom(Paper::A4.width()); + #[property(resolve)] + pub const WIDTH: Smart = Smart::Custom(Paper::A4.width().into()); /// The unflipped height of the page. - pub const HEIGHT: Smart = Smart::Custom(Paper::A4.height()); + #[property(resolve)] + pub const HEIGHT: Smart = 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> = Smart::Auto; + pub const LEFT: Smart> = Smart::Auto; /// The right margin. - pub const RIGHT: Smart> = Smart::Auto; + pub const RIGHT: Smart> = Smart::Auto; /// The top margin. - pub const TOP: Smart> = Smart::Auto; + pub const TOP: Smart> = Smart::Auto; /// The bottom margin. - pub const BOTTOM: Smart> = Smart::Auto; + pub const BOTTOM: Smart> = Smart::Auto; /// The page's background color. pub const FILL: Option = 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")? { - 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, ®ions, 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 { - 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), + Relative(Relative), /// 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>> { - 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, /// The full size of the current region that was available at the start. @@ -117,9 +119,9 @@ enum StackItem { Frame(Arc, 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); -- cgit v1.2.3