mirror of
https://github.com/typst/typst
synced 2025-05-16 01:55:28 +08:00
Handle metadata application where styles are managed
This commit is contained in:
parent
fe56fb29fa
commit
50741209a8
@ -58,6 +58,15 @@ pub fn define(global: &mut Scope) {
|
|||||||
pub struct MetaElem {
|
pub struct MetaElem {
|
||||||
/// Metadata that should be attached to all elements affected by this style
|
/// Metadata that should be attached to all elements affected by this style
|
||||||
/// property.
|
/// 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]
|
#[fold]
|
||||||
pub data: SmallVec<[Meta; 1]>,
|
pub data: SmallVec<[Meta; 1]>,
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,6 @@ impl Layout for Packed<BoxElem> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply metadata.
|
// Apply metadata.
|
||||||
frame.meta(styles, false);
|
|
||||||
frame.set_kind(FrameKind::Hard);
|
frame.set_kind(FrameKind::Hard);
|
||||||
|
|
||||||
Ok(Fragment::frame(frame))
|
Ok(Fragment::frame(frame))
|
||||||
@ -454,7 +453,6 @@ impl Layout for Packed<BlockElem> {
|
|||||||
// Apply metadata.
|
// Apply metadata.
|
||||||
for frame in &mut frames {
|
for frame in &mut frames {
|
||||||
frame.set_kind(FrameKind::Hard);
|
frame.set_kind(FrameKind::Hard);
|
||||||
frame.meta(styles, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Fragment::frames(frames))
|
Ok(Fragment::frames(frames))
|
||||||
|
@ -71,14 +71,7 @@ impl Layout for Packed<FlowElem> {
|
|||||||
let layoutable = child.with::<dyn Layout>().unwrap();
|
let layoutable = child.with::<dyn Layout>().unwrap();
|
||||||
layouter.layout_single(engine, layoutable, styles)?;
|
layouter.layout_single(engine, layoutable, styles)?;
|
||||||
} else if child.is::<MetaElem>() {
|
} else if child.is::<MetaElem>() {
|
||||||
let mut frame = Frame::soft(Size::zero());
|
layouter.layout_meta(styles);
|
||||||
frame.meta(styles, true);
|
|
||||||
layouter.items.push(FlowItem::Frame {
|
|
||||||
frame,
|
|
||||||
align: Axes::splat(FixedAlignment::Start),
|
|
||||||
sticky: true,
|
|
||||||
movable: false,
|
|
||||||
});
|
|
||||||
} else if let Some(placed) = child.to_packed::<PlaceElem>() {
|
} else if let Some(placed) = child.to_packed::<PlaceElem>() {
|
||||||
layouter.layout_placed(engine, placed, styles)?;
|
layouter.layout_placed(engine, placed, styles)?;
|
||||||
} else if child.can::<dyn Layout>() {
|
} else if child.can::<dyn Layout>() {
|
||||||
@ -297,7 +290,8 @@ impl<'a> FlowLayouter<'a> {
|
|||||||
let align = AlignElem::alignment_in(styles).resolve(styles);
|
let align = AlignElem::alignment_in(styles).resolve(styles);
|
||||||
let sticky = BlockElem::sticky_in(styles);
|
let sticky = BlockElem::sticky_in(styles);
|
||||||
let pod = Regions::one(self.regions.base(), Axes::splat(false));
|
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(
|
self.layout_item(
|
||||||
engine,
|
engine,
|
||||||
FlowItem::Frame { frame, align, sticky, movable: true },
|
FlowItem::Frame { frame, align, sticky, movable: true },
|
||||||
@ -306,6 +300,18 @@ impl<'a> FlowLayouter<'a> {
|
|||||||
Ok(())
|
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.
|
/// Layout a placed element.
|
||||||
fn layout_placed(
|
fn layout_placed(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -321,7 +327,8 @@ impl<'a> FlowLayouter<'a> {
|
|||||||
align.x().unwrap_or_default().resolve(styles)
|
align.x().unwrap_or_default().resolve(styles)
|
||||||
});
|
});
|
||||||
let y_align = alignment.map(|align| align.y().map(VAlignment::fix));
|
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 };
|
let item = FlowItem::Placed { frame, x_align, y_align, delta, float, clearance };
|
||||||
self.layout_item(engine, item)
|
self.layout_item(engine, item)
|
||||||
}
|
}
|
||||||
@ -361,7 +368,7 @@ impl<'a> FlowLayouter<'a> {
|
|||||||
let sticky = BlockElem::sticky_in(styles);
|
let sticky = BlockElem::sticky_in(styles);
|
||||||
let fragment = block.layout(engine, styles, self.regions)?;
|
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.
|
// Find footnotes in the frame.
|
||||||
if self.root {
|
if self.root {
|
||||||
find_footnotes(&mut notes, &frame);
|
find_footnotes(&mut notes, &frame);
|
||||||
@ -371,8 +378,11 @@ impl<'a> FlowLayouter<'a> {
|
|||||||
self.finish_region(engine, false)?;
|
self.finish_region(engine, false)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let item = FlowItem::Frame { frame, align, sticky, movable: false };
|
frame.meta(styles, false);
|
||||||
self.layout_item(engine, item)?;
|
self.layout_item(
|
||||||
|
engine,
|
||||||
|
FlowItem::Frame { frame, align, sticky, movable: false },
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.try_handle_footnotes(engine, notes)?;
|
self.try_handle_footnotes(engine, notes)?;
|
||||||
|
@ -289,20 +289,32 @@ impl Frame {
|
|||||||
/// Attach metadata from an iterator.
|
/// Attach metadata from an iterator.
|
||||||
pub fn meta_iter(&mut self, iter: impl IntoIterator<Item = Meta>) {
|
pub fn meta_iter(&mut self, iter: impl IntoIterator<Item = Meta>) {
|
||||||
let mut hide = false;
|
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) {
|
if matches!(meta, Meta::Hide) {
|
||||||
hide = true;
|
hide = true;
|
||||||
|
None
|
||||||
} else {
|
} else {
|
||||||
self.prepend(Point::zero(), FrameItem::Meta(meta, self.size));
|
Some((Point::zero(), FrameItem::Meta(meta, size)))
|
||||||
}
|
}
|
||||||
}
|
}));
|
||||||
if hide {
|
if hide {
|
||||||
Arc::make_mut(&mut self.items).retain(|(_, item)| {
|
self.hide();
|
||||||
matches!(item, FrameItem::Group(_) | FrameItem::Meta(Meta::Elem(_), _))
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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.
|
/// Add a background fill.
|
||||||
pub fn fill(&mut self, fill: Paint) {
|
pub fn fill(&mut self, fill: Paint) {
|
||||||
self.prepend(
|
self.prepend(
|
||||||
|
@ -570,13 +570,8 @@ impl<'a> GridLayouter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.finish_region(engine)?;
|
self.finish_region(engine)?;
|
||||||
|
|
||||||
self.render_fills_strokes()?;
|
self.render_fills_strokes()?;
|
||||||
|
|
||||||
for frame in &mut self.finished {
|
|
||||||
frame.meta(self.styles, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Fragment::frames(self.finished))
|
Ok(Fragment::frames(self.finished))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,7 +501,11 @@ fn collect<'a>(
|
|||||||
Segment::Text(full.len() - prev)
|
Segment::Text(full.len() - prev)
|
||||||
} else if let Some(elem) = child.to_packed::<EquationElem>() {
|
} else if let Some(elem) = child.to_packed::<EquationElem>() {
|
||||||
let pod = Regions::one(region, Axes::splat(false));
|
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));
|
full.extend(items.iter().map(MathParItem::text));
|
||||||
Segment::Equation(elem, items)
|
Segment::Equation(elem, items)
|
||||||
} else if let Some(elem) = child.to_packed::<BoxElem>() {
|
} else if let Some(elem) = child.to_packed::<BoxElem>() {
|
||||||
@ -591,6 +595,7 @@ fn prepare<'a>(
|
|||||||
} else {
|
} else {
|
||||||
let pod = Regions::one(region, Axes::splat(false));
|
let pod = Regions::one(region, Axes::splat(false));
|
||||||
let mut frame = elem.layout(engine, styles, pod)?.into_frame();
|
let mut frame = elem.layout(engine, styles, pod)?.into_frame();
|
||||||
|
frame.meta(styles, false);
|
||||||
frame.translate(Point::with_y(TextElem::baseline_in(styles)));
|
frame.translate(Point::with_y(TextElem::baseline_in(styles)));
|
||||||
items.push(Item::Frame(frame));
|
items.push(Item::Frame(frame));
|
||||||
}
|
}
|
||||||
@ -1315,6 +1320,7 @@ fn commit(
|
|||||||
let region = Size::new(amount, full);
|
let region = Size::new(amount, full);
|
||||||
let pod = Regions::one(region, Axes::new(true, false));
|
let pod = Regions::one(region, Axes::new(true, false));
|
||||||
let mut frame = elem.layout(engine, *styles, pod)?.into_frame();
|
let mut frame = elem.layout(engine, *styles, pod)?.into_frame();
|
||||||
|
frame.meta(*styles, false);
|
||||||
frame.translate(Point::with_y(TextElem::baseline_in(*styles)));
|
frame.translate(Point::with_y(TextElem::baseline_in(*styles)));
|
||||||
push(&mut offset, frame);
|
push(&mut offset, frame);
|
||||||
} else {
|
} else {
|
||||||
@ -1322,8 +1328,9 @@ fn commit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item::Text(shaped) => {
|
Item::Text(shaped) => {
|
||||||
let frame =
|
let mut frame =
|
||||||
shaped.build(engine, justification_ratio, extra_justification);
|
shaped.build(engine, justification_ratio, extra_justification);
|
||||||
|
frame.meta(shaped.styles, false);
|
||||||
push(&mut offset, frame);
|
push(&mut offset, frame);
|
||||||
}
|
}
|
||||||
Item::Frame(frame) | Item::Meta(frame) => {
|
Item::Frame(frame) | Item::Meta(frame) => {
|
||||||
|
@ -322,9 +322,6 @@ impl<'a> ShapedText<'a> {
|
|||||||
offset += width;
|
offset += width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply metadata.
|
|
||||||
frame.meta(self.styles, false);
|
|
||||||
|
|
||||||
frame
|
frame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,9 +188,6 @@ impl Packed<EquationElem> {
|
|||||||
let descent = bottom_edge.max(frame.descent() - slack);
|
let descent = bottom_edge.max(frame.descent() - slack);
|
||||||
frame.translate(Point::with_y(ascent - frame.baseline()));
|
frame.translate(Point::with_y(ascent - frame.baseline()));
|
||||||
frame.size_mut().y = ascent + descent;
|
frame.size_mut().y = ascent + descent;
|
||||||
|
|
||||||
// Apply metadata.
|
|
||||||
frame.meta(styles, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(items)
|
Ok(items)
|
||||||
@ -251,9 +248,6 @@ impl Layout for Packed<EquationElem> {
|
|||||||
frame.push_frame(Point::new(x, y), counter)
|
frame.push_frame(Point::new(x, y), counter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply metadata.
|
|
||||||
frame.meta(styles, false);
|
|
||||||
|
|
||||||
Ok(Fragment::frame(frame))
|
Ok(Fragment::frame(frame))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,13 +236,9 @@ impl Layout for Packed<ImageElem> {
|
|||||||
|
|
||||||
// Create a clipping group if only part of the image should be visible.
|
// Create a clipping group if only part of the image should be visible.
|
||||||
if fit == ImageFit::Cover && !target.fits(fitted) {
|
if fit == ImageFit::Cover && !target.fits(fitted) {
|
||||||
frame.meta(styles, false);
|
|
||||||
frame.clip(Path::rect(frame.size()));
|
frame.clip(Path::rect(frame.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply metadata.
|
|
||||||
frame.meta(styles, false);
|
|
||||||
|
|
||||||
Ok(Fragment::frame(frame))
|
Ok(Fragment::frame(frame))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,6 @@ impl Layout for Packed<LineElem> {
|
|||||||
let mut frame = Frame::soft(target);
|
let mut frame = Frame::soft(target);
|
||||||
let shape = Geometry::Line(delta.to_point()).stroked(stroke);
|
let shape = Geometry::Line(delta.to_point()).stroked(stroke);
|
||||||
frame.push(start.to_point(), FrameItem::Shape(shape, self.span()));
|
frame.push(start.to_point(), FrameItem::Shape(shape, self.span()));
|
||||||
frame.meta(styles, false);
|
|
||||||
Ok(Fragment::frame(frame))
|
Ok(Fragment::frame(frame))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,6 @@ impl Layout for Packed<PolygonElem> {
|
|||||||
|
|
||||||
let shape = Shape { geometry: Geometry::Path(path), stroke, fill };
|
let shape = Shape { geometry: Geometry::Path(path), stroke, fill };
|
||||||
frame.push(Point::zero(), FrameItem::Shape(shape, self.span()));
|
frame.push(Point::zero(), FrameItem::Shape(shape, self.span()));
|
||||||
frame.meta(styles, false);
|
|
||||||
|
|
||||||
Ok(Fragment::frame(frame))
|
Ok(Fragment::frame(frame))
|
||||||
}
|
}
|
||||||
|
@ -523,9 +523,6 @@ fn layout(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply metadata.
|
|
||||||
frame.meta(styles, false);
|
|
||||||
|
|
||||||
Ok(Fragment::frame(frame))
|
Ok(Fragment::frame(frame))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user