summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-01-17 20:53:09 +0100
committerLaurenz <laurmaedje@gmail.com>2024-01-17 20:55:50 +0100
commit50741209a8f4c5e91d35281eb44b7425b3d022b2 (patch)
tree775ab71a0d2d4cff8e10f2b71059843991d9abd4 /crates
parentfe56fb29fa14d76647a02d25e125571154b122f6 (diff)
Handle metadata application where styles are managed
Diffstat (limited to 'crates')
-rw-r--r--crates/typst/src/introspection/mod.rs9
-rw-r--r--crates/typst/src/layout/container.rs2
-rw-r--r--crates/typst/src/layout/flow.rs36
-rw-r--r--crates/typst/src/layout/frame.rs24
-rw-r--r--crates/typst/src/layout/grid/layout.rs5
-rw-r--r--crates/typst/src/layout/inline/mod.rs11
-rw-r--r--crates/typst/src/layout/inline/shaping.rs3
-rw-r--r--crates/typst/src/math/equation.rs6
-rw-r--r--crates/typst/src/visualize/image/mod.rs4
-rw-r--r--crates/typst/src/visualize/line.rs1
-rw-r--r--crates/typst/src/visualize/polygon.rs1
-rw-r--r--crates/typst/src/visualize/shape.rs3
12 files changed, 59 insertions, 46 deletions
diff --git a/crates/typst/src/introspection/mod.rs b/crates/typst/src/introspection/mod.rs
index e9ea0291..25f67400 100644
--- a/crates/typst/src/introspection/mod.rs
+++ b/crates/typst/src/introspection/mod.rs
@@ -58,6 +58,15 @@ pub fn define(global: &mut Scope) {
pub struct MetaElem {
/// Metadata that should be attached to all elements affected by this style
/// property.
+ ///
+ /// This must be accessed and applied to all frames produced by elements
+ /// that manually handle styles (because their children can have varying
+ /// styles). This currently includes flow, par, and equation.
+ ///
+ /// Other elements don't manually need to handle it because their parents
+ /// that result from realization will take care of it and the metadata can
+ /// only apply to them as a whole, not part of it (because they don't manage
+ /// styles).
#[fold]
pub data: SmallVec<[Meta; 1]>,
}
diff --git a/crates/typst/src/layout/container.rs b/crates/typst/src/layout/container.rs
index 3905a37a..a8429e06 100644
--- a/crates/typst/src/layout/container.rs
+++ b/crates/typst/src/layout/container.rs
@@ -172,7 +172,6 @@ impl Layout for Packed<BoxElem> {
}
// Apply metadata.
- frame.meta(styles, false);
frame.set_kind(FrameKind::Hard);
Ok(Fragment::frame(frame))
@@ -454,7 +453,6 @@ impl Layout for Packed<BlockElem> {
// Apply metadata.
for frame in &mut frames {
frame.set_kind(FrameKind::Hard);
- frame.meta(styles, false);
}
Ok(Fragment::frames(frames))
diff --git a/crates/typst/src/layout/flow.rs b/crates/typst/src/layout/flow.rs
index d7b9880f..b4798cd8 100644
--- a/crates/typst/src/layout/flow.rs
+++ b/crates/typst/src/layout/flow.rs
@@ -71,14 +71,7 @@ impl Layout for Packed<FlowElem> {
let layoutable = child.with::<dyn Layout>().unwrap();
layouter.layout_single(engine, layoutable, styles)?;
} else if child.is::<MetaElem>() {
- let mut frame = Frame::soft(Size::zero());
- frame.meta(styles, true);
- layouter.items.push(FlowItem::Frame {
- frame,
- align: Axes::splat(FixedAlignment::Start),
- sticky: true,
- movable: false,
- });
+ layouter.layout_meta(styles);
} else if let Some(placed) = child.to_packed::<PlaceElem>() {
layouter.layout_placed(engine, placed, styles)?;
} else if child.can::<dyn Layout>() {
@@ -297,7 +290,8 @@ impl<'a> FlowLayouter<'a> {
let align = AlignElem::alignment_in(styles).resolve(styles);
let sticky = BlockElem::sticky_in(styles);
let pod = Regions::one(self.regions.base(), Axes::splat(false));
- let frame = content.layout(engine, styles, pod)?.into_frame();
+ let mut frame = content.layout(engine, styles, pod)?.into_frame();
+ frame.meta(styles, false);
self.layout_item(
engine,
FlowItem::Frame { frame, align, sticky, movable: true },
@@ -306,6 +300,18 @@ impl<'a> FlowLayouter<'a> {
Ok(())
}
+ /// Place explicit metadata into the flow.
+ fn layout_meta(&mut self, styles: StyleChain) {
+ let mut frame = Frame::soft(Size::zero());
+ frame.meta(styles, true);
+ self.items.push(FlowItem::Frame {
+ frame,
+ align: Axes::splat(FixedAlignment::Start),
+ sticky: true,
+ movable: false,
+ });
+ }
+
/// Layout a placed element.
fn layout_placed(
&mut self,
@@ -321,7 +327,8 @@ impl<'a> FlowLayouter<'a> {
align.x().unwrap_or_default().resolve(styles)
});
let y_align = alignment.map(|align| align.y().map(VAlignment::fix));
- let frame = placed.layout(engine, styles, self.regions)?.into_frame();
+ let mut frame = placed.layout(engine, styles, self.regions)?.into_frame();
+ frame.meta(styles, false);
let item = FlowItem::Placed { frame, x_align, y_align, delta, float, clearance };
self.layout_item(engine, item)
}
@@ -361,7 +368,7 @@ impl<'a> FlowLayouter<'a> {
let sticky = BlockElem::sticky_in(styles);
let fragment = block.layout(engine, styles, self.regions)?;
- for (i, frame) in fragment.into_iter().enumerate() {
+ for (i, mut frame) in fragment.into_iter().enumerate() {
// Find footnotes in the frame.
if self.root {
find_footnotes(&mut notes, &frame);
@@ -371,8 +378,11 @@ impl<'a> FlowLayouter<'a> {
self.finish_region(engine, false)?;
}
- let item = FlowItem::Frame { frame, align, sticky, movable: false };
- self.layout_item(engine, item)?;
+ frame.meta(styles, false);
+ self.layout_item(
+ engine,
+ FlowItem::Frame { frame, align, sticky, movable: false },
+ )?;
}
self.try_handle_footnotes(engine, notes)?;
diff --git a/crates/typst/src/layout/frame.rs b/crates/typst/src/layout/frame.rs
index 43cab1f4..3c6d88e7 100644
--- a/crates/typst/src/layout/frame.rs
+++ b/crates/typst/src/layout/frame.rs
@@ -289,20 +289,32 @@ impl Frame {
/// Attach metadata from an iterator.
pub fn meta_iter(&mut self, iter: impl IntoIterator<Item = Meta>) {
let mut hide = false;
- for meta in iter {
+ let size = self.size;
+ self.prepend_multiple(iter.into_iter().filter_map(|meta| {
if matches!(meta, Meta::Hide) {
hide = true;
+ None
} else {
- self.prepend(Point::zero(), FrameItem::Meta(meta, self.size));
+ Some((Point::zero(), FrameItem::Meta(meta, size)))
}
- }
+ }));
if hide {
- Arc::make_mut(&mut self.items).retain(|(_, item)| {
- matches!(item, FrameItem::Group(_) | FrameItem::Meta(Meta::Elem(_), _))
- });
+ self.hide();
}
}
+ /// Hide all content in the frame, but keep metadata.
+ pub fn hide(&mut self) {
+ Arc::make_mut(&mut self.items).retain_mut(|(_, item)| match item {
+ FrameItem::Group(group) => {
+ group.frame.hide();
+ !group.frame.is_empty()
+ }
+ FrameItem::Meta(Meta::Elem(_), _) => true,
+ _ => false,
+ });
+ }
+
/// Add a background fill.
pub fn fill(&mut self, fill: Paint) {
self.prepend(
diff --git a/crates/typst/src/layout/grid/layout.rs b/crates/typst/src/layout/grid/layout.rs
index b2490d1e..577baaeb 100644
--- a/crates/typst/src/layout/grid/layout.rs
+++ b/crates/typst/src/layout/grid/layout.rs
@@ -570,13 +570,8 @@ impl<'a> GridLayouter<'a> {
}
self.finish_region(engine)?;
-
self.render_fills_strokes()?;
- for frame in &mut self.finished {
- frame.meta(self.styles, false);
- }
-
Ok(Fragment::frames(self.finished))
}
diff --git a/crates/typst/src/layout/inline/mod.rs b/crates/typst/src/layout/inline/mod.rs
index 1c04d0ce..627265f7 100644
--- a/crates/typst/src/layout/inline/mod.rs
+++ b/crates/typst/src/layout/inline/mod.rs
@@ -501,7 +501,11 @@ fn collect<'a>(
Segment::Text(full.len() - prev)
} else if let Some(elem) = child.to_packed::<EquationElem>() {
let pod = Regions::one(region, Axes::splat(false));
- let items = elem.layout_inline(engine, styles, pod)?;
+ let mut items = elem.layout_inline(engine, styles, pod)?;
+ for item in &mut items {
+ let MathParItem::Frame(frame) = item else { continue };
+ frame.meta(styles, false);
+ }
full.extend(items.iter().map(MathParItem::text));
Segment::Equation(elem, items)
} else if let Some(elem) = child.to_packed::<BoxElem>() {
@@ -591,6 +595,7 @@ fn prepare<'a>(
} else {
let pod = Regions::one(region, Axes::splat(false));
let mut frame = elem.layout(engine, styles, pod)?.into_frame();
+ frame.meta(styles, false);
frame.translate(Point::with_y(TextElem::baseline_in(styles)));
items.push(Item::Frame(frame));
}
@@ -1315,6 +1320,7 @@ fn commit(
let region = Size::new(amount, full);
let pod = Regions::one(region, Axes::new(true, false));
let mut frame = elem.layout(engine, *styles, pod)?.into_frame();
+ frame.meta(*styles, false);
frame.translate(Point::with_y(TextElem::baseline_in(*styles)));
push(&mut offset, frame);
} else {
@@ -1322,8 +1328,9 @@ fn commit(
}
}
Item::Text(shaped) => {
- let frame =
+ let mut frame =
shaped.build(engine, justification_ratio, extra_justification);
+ frame.meta(shaped.styles, false);
push(&mut offset, frame);
}
Item::Frame(frame) | Item::Meta(frame) => {
diff --git a/crates/typst/src/layout/inline/shaping.rs b/crates/typst/src/layout/inline/shaping.rs
index 28aee7bd..6b1e2e93 100644
--- a/crates/typst/src/layout/inline/shaping.rs
+++ b/crates/typst/src/layout/inline/shaping.rs
@@ -322,9 +322,6 @@ impl<'a> ShapedText<'a> {
offset += width;
}
- // Apply metadata.
- frame.meta(self.styles, false);
-
frame
}
diff --git a/crates/typst/src/math/equation.rs b/crates/typst/src/math/equation.rs
index 9cd771e6..2f02dfe4 100644
--- a/crates/typst/src/math/equation.rs
+++ b/crates/typst/src/math/equation.rs
@@ -188,9 +188,6 @@ impl Packed<EquationElem> {
let descent = bottom_edge.max(frame.descent() - slack);
frame.translate(Point::with_y(ascent - frame.baseline()));
frame.size_mut().y = ascent + descent;
-
- // Apply metadata.
- frame.meta(styles, false);
}
Ok(items)
@@ -251,9 +248,6 @@ impl Layout for Packed<EquationElem> {
frame.push_frame(Point::new(x, y), counter)
}
- // Apply metadata.
- frame.meta(styles, false);
-
Ok(Fragment::frame(frame))
}
}
diff --git a/crates/typst/src/visualize/image/mod.rs b/crates/typst/src/visualize/image/mod.rs
index 9d26a8ed..613bb7d4 100644
--- a/crates/typst/src/visualize/image/mod.rs
+++ b/crates/typst/src/visualize/image/mod.rs
@@ -236,13 +236,9 @@ impl Layout for Packed<ImageElem> {
// Create a clipping group if only part of the image should be visible.
if fit == ImageFit::Cover && !target.fits(fitted) {
- frame.meta(styles, false);
frame.clip(Path::rect(frame.size()));
}
- // Apply metadata.
- frame.meta(styles, false);
-
Ok(Fragment::frame(frame))
}
}
diff --git a/crates/typst/src/visualize/line.rs b/crates/typst/src/visualize/line.rs
index 0c883500..b1707484 100644
--- a/crates/typst/src/visualize/line.rs
+++ b/crates/typst/src/visualize/line.rs
@@ -89,7 +89,6 @@ impl Layout for Packed<LineElem> {
let mut frame = Frame::soft(target);
let shape = Geometry::Line(delta.to_point()).stroked(stroke);
frame.push(start.to_point(), FrameItem::Shape(shape, self.span()));
- frame.meta(styles, false);
Ok(Fragment::frame(frame))
}
}
diff --git a/crates/typst/src/visualize/polygon.rs b/crates/typst/src/visualize/polygon.rs
index 1f6dce44..f375e8ca 100644
--- a/crates/typst/src/visualize/polygon.rs
+++ b/crates/typst/src/visualize/polygon.rs
@@ -171,7 +171,6 @@ impl Layout for Packed<PolygonElem> {
let shape = Shape { geometry: Geometry::Path(path), stroke, fill };
frame.push(Point::zero(), FrameItem::Shape(shape, self.span()));
- frame.meta(styles, false);
Ok(Fragment::frame(frame))
}
diff --git a/crates/typst/src/visualize/shape.rs b/crates/typst/src/visualize/shape.rs
index b8938d3b..dd559b47 100644
--- a/crates/typst/src/visualize/shape.rs
+++ b/crates/typst/src/visualize/shape.rs
@@ -523,9 +523,6 @@ fn layout(
}
}
- // Apply metadata.
- frame.meta(styles, false);
-
Ok(Fragment::frame(frame))
}