mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +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::geom::*;
|
||||||
use typst::model::{
|
use typst::model::{
|
||||||
capability, Barrier, Content, Node, SequenceNode, Show, StyleChain, StyleEntry,
|
capability, Barrier, Content, Node, SequenceNode, Show, StyleChain, StyleEntry,
|
||||||
StyleMap, StyleVec, StyleVecBuilder, StyledNode, Target,
|
StyleVec, StyleVecBuilder, StyledNode, Target,
|
||||||
};
|
};
|
||||||
use typst::World;
|
use typst::World;
|
||||||
|
|
||||||
@ -253,8 +253,10 @@ struct Builder<'a> {
|
|||||||
struct Scratch<'a> {
|
struct Scratch<'a> {
|
||||||
/// An arena where intermediate style chains are stored.
|
/// An arena where intermediate style chains are stored.
|
||||||
styles: Arena<StyleChain<'a>>,
|
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.
|
/// 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.
|
/// Determines whether a style could interrupt some composable structure.
|
||||||
@ -305,7 +307,7 @@ impl<'a> Builder<'a> {
|
|||||||
) -> SourceResult<()> {
|
) -> SourceResult<()> {
|
||||||
if let Some(text) = content.downcast::<TextNode>() {
|
if let Some(text) = content.downcast::<TextNode>() {
|
||||||
if let Some(realized) = styles.apply(self.world, Target::Text(&text.0))? {
|
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);
|
return self.accept(stored, styles);
|
||||||
}
|
}
|
||||||
} else if let Some(styled) = content.downcast::<StyledNode>() {
|
} else if let Some(styled) = content.downcast::<StyledNode>() {
|
||||||
@ -357,16 +359,18 @@ impl<'a> Builder<'a> {
|
|||||||
content: &'a Content,
|
content: &'a Content,
|
||||||
styles: StyleChain<'a>,
|
styles: StyleChain<'a>,
|
||||||
) -> SourceResult<bool> {
|
) -> 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);
|
return Ok(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut map = StyleMap::new();
|
let stored = self.scratch.content.alloc(realized);
|
||||||
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);
|
|
||||||
self.accept(stored, styles)?;
|
self.accept(stored, styles)?;
|
||||||
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
@ -680,7 +684,7 @@ impl<'a> ListBuilder<'a> {
|
|||||||
DESC | _ => ListNode::<DESC> { tight, attached, items }.pack(),
|
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)?;
|
parent.accept(stored, shared)?;
|
||||||
|
|
||||||
for (content, styles) in self.staged {
|
for (content, styles) in self.staged {
|
||||||
|
@ -25,7 +25,7 @@ use self::quotes::*;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// A single run of text with the same style.
|
/// A single run of text with the same style.
|
||||||
#[derive(Debug, Clone, Hash)]
|
#[derive(Clone, Hash)]
|
||||||
pub struct TextNode(pub EcoString);
|
pub struct TextNode(pub EcoString);
|
||||||
|
|
||||||
impl TextNode {
|
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".
|
/// A lowercased font family like "arial".
|
||||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct FontFamily(EcoString);
|
pub struct FontFamily(EcoString);
|
||||||
|
@ -115,10 +115,14 @@ impl Content {
|
|||||||
pub fn styled_with_entry(mut self, entry: StyleEntry) -> Self {
|
pub fn styled_with_entry(mut self, entry: StyleEntry) -> Self {
|
||||||
if let Some(styled) = self.try_downcast_mut::<StyledNode>() {
|
if let Some(styled) = self.try_downcast_mut::<StyledNode>() {
|
||||||
styled.map.apply(entry);
|
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.
|
/// 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
|
/// Like [`chain`](Self::chain) or [`apply_map`](Self::apply_map), but with
|
||||||
/// only a entry.
|
/// only a entry.
|
||||||
pub fn apply(&mut self, entry: StyleEntry) {
|
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);
|
self.0.insert(0, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +133,7 @@ impl From<StyleEntry> for StyleMap {
|
|||||||
|
|
||||||
impl Debug for StyleMap {
|
impl Debug for StyleMap {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
for entry in self.0.iter().rev() {
|
for entry in self.0.iter() {
|
||||||
writeln!(f, "{:?}", entry)?;
|
writeln!(f, "{:?}", entry)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -351,7 +360,7 @@ impl<'a> StyleChain<'a> {
|
|||||||
|
|
||||||
impl Debug for StyleChain<'_> {
|
impl Debug for StyleChain<'_> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
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)?;
|
writeln!(f, "{:?}", entry)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -161,9 +161,13 @@ impl ReadableTypeId {
|
|||||||
impl Debug for ReadableTypeId {
|
impl Debug for ReadableTypeId {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
f.pad(self.name)?;
|
if let Some(part) = self.name.split("::").last() {
|
||||||
|
f.pad(part)?;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
f.pad("ReadableTypeId")?;
|
f.pad("ReadableTypeId")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user