mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Reduce style chain bloat
This commit is contained in:
parent
a7a4cae294
commit
12a59963b0
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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(())
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user