Reduce style chain bloat

This commit is contained in:
Laurenz 2022-11-08 15:31:15 +01:00
parent a7a4cae294
commit 12a59963b0
5 changed files with 45 additions and 18 deletions

View File

@ -33,7 +33,7 @@ use typst::frame::Frame;
use typst::geom::*;
use typst::model::{
capability, Barrier, Content, Node, SequenceNode, Show, StyleChain, StyleEntry,
StyleMap, StyleVec, StyleVecBuilder, StyledNode, Target,
StyleVec, StyleVecBuilder, StyledNode, Target,
};
use typst::World;
@ -253,8 +253,10 @@ struct Builder<'a> {
struct Scratch<'a> {
/// An arena where intermediate style chains are stored.
styles: Arena<StyleChain<'a>>,
/// An arena for individual intermediate style entries.
entries: Arena<StyleEntry>,
/// An arena where intermediate content resulting from show rules is stored.
templates: Arena<Content>,
content: Arena<Content>,
}
/// Determines whether a style could interrupt some composable structure.
@ -305,7 +307,7 @@ impl<'a> Builder<'a> {
) -> SourceResult<()> {
if let Some(text) = content.downcast::<TextNode>() {
if let Some(realized) = styles.apply(self.world, Target::Text(&text.0))? {
let stored = self.scratch.templates.alloc(realized);
let stored = self.scratch.content.alloc(realized);
return self.accept(stored, styles);
}
} else if let Some(styled) = content.downcast::<StyledNode>() {
@ -357,16 +359,18 @@ impl<'a> Builder<'a> {
content: &'a Content,
styles: StyleChain<'a>,
) -> SourceResult<bool> {
let Some(mut realized) = styles.apply(self.world, Target::Node(content))? else {
let barrier = StyleEntry::Barrier(Barrier::new(content.id()));
let styles = self
.scratch
.entries
.alloc(barrier)
.chain(self.scratch.styles.alloc(styles));
let Some(realized) = styles.apply(self.world, Target::Node(content))? else {
return Ok(false);
};
let mut map = StyleMap::new();
let barrier = Barrier::new(content.id());
map.push(StyleEntry::Barrier(barrier));
map.push(StyleEntry::Barrier(barrier));
realized = realized.styled_with_map(map);
let stored = self.scratch.templates.alloc(realized);
let stored = self.scratch.content.alloc(realized);
self.accept(stored, styles)?;
Ok(true)
@ -680,7 +684,7 @@ impl<'a> ListBuilder<'a> {
DESC | _ => ListNode::<DESC> { tight, attached, items }.pack(),
};
let stored = parent.scratch.templates.alloc(content);
let stored = parent.scratch.content.alloc(content);
parent.accept(stored, shared)?;
for (content, styles) in self.staged {

View File

@ -25,7 +25,7 @@ use self::quotes::*;
use crate::prelude::*;
/// A single run of text with the same style.
#[derive(Debug, Clone, Hash)]
#[derive(Clone, Hash)]
pub struct TextNode(pub EcoString);
impl TextNode {
@ -169,6 +169,12 @@ impl TextNode {
}
}
impl Debug for TextNode {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Text({:?})", self.0)
}
}
/// A lowercased font family like "arial".
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct FontFamily(EcoString);

View File

@ -115,10 +115,14 @@ impl Content {
pub fn styled_with_entry(mut self, entry: StyleEntry) -> Self {
if let Some(styled) = self.try_downcast_mut::<StyledNode>() {
styled.map.apply(entry);
return self;
self
} else if let Some(styled) = self.downcast::<StyledNode>() {
let mut map = styled.map.clone();
map.apply(entry);
StyledNode { sub: styled.sub.clone(), map }.pack()
} else {
StyledNode { sub: self, map: entry.into() }.pack()
}
StyledNode { sub: self, map: entry.into() }.pack()
}
/// Style this content with a full style map.

View File

@ -85,6 +85,15 @@ impl StyleMap {
/// Like [`chain`](Self::chain) or [`apply_map`](Self::apply_map), but with
/// only a entry.
pub fn apply(&mut self, entry: StyleEntry) {
if let StyleEntry::Guard(a) = &entry {
if let [StyleEntry::Unguard(b), ..] = self.0.as_slice() {
if a == b {
self.0.remove(0);
return;
}
}
}
self.0.insert(0, entry);
}
@ -124,7 +133,7 @@ impl From<StyleEntry> for StyleMap {
impl Debug for StyleMap {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
for entry in self.0.iter().rev() {
for entry in self.0.iter() {
writeln!(f, "{:?}", entry)?;
}
Ok(())
@ -351,7 +360,7 @@ impl<'a> StyleChain<'a> {
impl Debug for StyleChain<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
for entry in self.entries() {
for entry in self.entries().collect::<Vec<_>>().into_iter().rev() {
writeln!(f, "{:?}", entry)?;
}
Ok(())

View File

@ -161,9 +161,13 @@ impl ReadableTypeId {
impl Debug for ReadableTypeId {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
#[cfg(debug_assertions)]
f.pad(self.name)?;
if let Some(part) = self.name.split("::").last() {
f.pad(part)?;
}
#[cfg(not(debug_assertions))]
f.pad("ReadableTypeId")?;
Ok(())
}
}