diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-04-25 15:50:13 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-04-25 15:50:13 +0200 |
| commit | 09aabc3a21e403e0b09a6d6ba517e34a303b217c (patch) | |
| tree | 590a26bdfe3c5c3c1a48a0271ba54ee3b076a791 /src/model | |
| parent | 649c101f07f6de4791dc9b6091dff4a85112a15c (diff) | |
Public style entry enum
Diffstat (limited to 'src/model')
| -rw-r--r-- | src/model/collapse.rs | 16 | ||||
| -rw-r--r-- | src/model/content.rs | 18 | ||||
| -rw-r--r-- | src/model/layout.rs | 6 | ||||
| -rw-r--r-- | src/model/styles.rs | 170 |
4 files changed, 98 insertions, 112 deletions
diff --git a/src/model/collapse.rs b/src/model/collapse.rs index 5e7a25f8..18cfae8b 100644 --- a/src/model/collapse.rs +++ b/src/model/collapse.rs @@ -2,8 +2,12 @@ use super::{StyleChain, StyleVec, StyleVecBuilder}; /// A wrapper around a [`StyleVecBuilder`] that allows to collapse items. pub struct CollapsingBuilder<'a, T> { + /// The internal builder. builder: StyleVecBuilder<'a, T>, + /// Staged weak and ignorant items that we can't yet commit to the builder. + /// The option is `Some(_)` for weak items and `None` for ignorant items. staged: Vec<(T, StyleChain<'a>, Option<u8>)>, + /// What the last non-ignorant item was. last: Last, } @@ -51,14 +55,14 @@ impl<'a, T> CollapsingBuilder<'a, T> { /// Forces nearby weak items to collapse. pub fn destructive(&mut self, item: T, styles: StyleChain<'a>) { self.flush(false); - self.push(item, styles); + self.builder.push(item, styles); self.last = Last::Destructive; } /// Allows nearby weak items to exist. pub fn supportive(&mut self, item: T, styles: StyleChain<'a>) { self.flush(true); - self.push(item, styles); + self.builder.push(item, styles); self.last = Last::Supportive; } @@ -78,7 +82,8 @@ impl<'a, T> CollapsingBuilder<'a, T> { self.builder.finish() } - /// Push the staged items, filtering out weak items if `supportive` is false. + /// Push the staged items, filtering out weak items if `supportive` is + /// false. fn flush(&mut self, supportive: bool) { for (item, styles, strength) in self.staged.drain(..) { if supportive || strength.is_none() { @@ -86,11 +91,6 @@ impl<'a, T> CollapsingBuilder<'a, T> { } } } - - /// Push a new item into the style vector. - fn push(&mut self, item: T, styles: StyleChain<'a>) { - self.builder.push(item, styles); - } } impl<'a, T> Default for CollapsingBuilder<'a, T> { diff --git a/src/model/content.rs b/src/model/content.rs index 04d5fc5f..a7eb906a 100644 --- a/src/model/content.rs +++ b/src/model/content.rs @@ -238,19 +238,11 @@ impl Debug for Content { Self::Horizontal(kind) => write!(f, "Horizontal({kind:?})"), Self::Text(text) => write!(f, "Text({text:?})"), Self::Quote(double) => write!(f, "Quote({double})"), - Self::Inline(node) => { - f.write_str("Inline(")?; - node.fmt(f)?; - f.write_str(")") - } + Self::Inline(node) => node.fmt(f), Self::Parbreak => f.pad("Parbreak"), Self::Colbreak => f.pad("Colbreak"), Self::Vertical(kind) => write!(f, "Vertical({kind:?})"), - Self::Block(node) => { - f.write_str("Block(")?; - node.fmt(f)?; - f.write_str(")") - } + Self::Block(node) => node.fmt(f), Self::List(item) => { f.write_str("- ")?; item.body.fmt(f) @@ -264,11 +256,7 @@ impl Debug for Content { } Self::Pagebreak(soft) => write!(f, "Pagebreak({soft})"), Self::Page(page) => page.fmt(f), - Self::Show(node) => { - f.write_str("Show(")?; - node.fmt(f)?; - f.write_str(")") - } + Self::Show(node) => node.fmt(f), Self::Styled(styled) => { let (sub, map) = styled.as_ref(); map.fmt(f)?; diff --git a/src/model/layout.rs b/src/model/layout.rs index 9a4d5df3..78bfedc7 100644 --- a/src/model/layout.rs +++ b/src/model/layout.rs @@ -5,7 +5,7 @@ use std::fmt::{self, Debug, Formatter}; use std::hash::Hash; use std::sync::Arc; -use super::{Barrier, NodeId, Resolve, StyleChain, StyleSlot}; +use super::{Barrier, NodeId, Resolve, StyleChain, StyleEntry}; use crate::diag::TypResult; use crate::eval::{RawAlign, RawLength}; use crate::frame::{Element, Frame, Geometry}; @@ -220,8 +220,8 @@ impl Layout for LayoutNode { styles: StyleChain, ) -> TypResult<Vec<Arc<Frame>>> { ctx.query((self, regions, styles), |ctx, (node, regions, styles)| { - let slot = StyleSlot::from(Barrier::new(node.id())); - node.0.layout(ctx, regions, slot.chain(&styles)) + let entry = StyleEntry::Barrier(Barrier::new(node.id())); + node.0.layout(ctx, regions, entry.chain(&styles)) }) .clone() } diff --git a/src/model/styles.rs b/src/model/styles.rs index 8c9092a4..7e5bfe94 100644 --- a/src/model/styles.rs +++ b/src/model/styles.rs @@ -16,7 +16,7 @@ use crate::Context; /// A map of style properties. #[derive(Default, Clone, PartialEq, Hash)] -pub struct StyleMap(Vec<Entry>); +pub struct StyleMap(Vec<StyleEntry>); impl StyleMap { /// Create a new, empty style map. @@ -29,6 +29,11 @@ impl StyleMap { self.0.is_empty() } + /// Push an arbitary style entry. + pub fn push(&mut self, style: StyleEntry) { + self.0.push(style); + } + /// Create a style map from a single property-value pair. pub fn with<'a, K: Key<'a>>(key: K, value: K::Value) -> Self { let mut styles = Self::new(); @@ -42,7 +47,7 @@ impl StyleMap { /// style map, `self` contributes the outer values and `value` is the inner /// one. pub fn set<'a, K: Key<'a>>(&mut self, key: K, value: K::Value) { - self.0.push(Entry::Property(Property::new(key, value))); + self.push(StyleEntry::Property(Property::new(key, value))); } /// Set an inner value for a style property if it is `Some(_)`. @@ -65,7 +70,7 @@ impl StyleMap { /// Set a show rule recipe for a node. pub fn set_recipe<T: Node>(&mut self, func: Func, span: Span) { - self.0.push(Entry::Recipe(Recipe::new::<T>(func, span))); + self.push(StyleEntry::Recipe(Recipe::new::<T>(func, span))); } /// Whether the map contains a style property for the given key. @@ -98,7 +103,7 @@ impl StyleMap { /// Like [`chain`](Self::chain) or [`apply_map`](Self::apply_map), but with /// only a single property. pub fn apply<'a, K: Key<'a>>(&mut self, key: K, value: K::Value) { - self.0.insert(0, Entry::Property(Property::new(key, value))); + self.0.insert(0, StyleEntry::Property(Property::new(key, value))); } /// Apply styles from `tail` in-place. The resulting style map is equivalent @@ -115,7 +120,7 @@ impl StyleMap { /// not its children, too. This is used by [constructors](Node::construct). pub fn scoped(mut self) -> Self { for entry in &mut self.0 { - if let Entry::Property(property) = entry { + if let StyleEntry::Property(property) = entry { property.scoped = true; } } @@ -132,6 +137,12 @@ impl StyleMap { } } +impl From<StyleEntry> for StyleMap { + fn from(entry: StyleEntry) -> Self { + Self(vec![entry]) + } +} + impl Debug for StyleMap { fn fmt(&self, f: &mut Formatter) -> fmt::Result { for entry in self.0.iter().rev() { @@ -141,38 +152,43 @@ impl Debug for StyleMap { } } -/// A stack-allocated slot for a single style property or barrier. -pub struct StyleSlot(Entry); +/// A unique identifier for a node. +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct NodeId(ReadableTypeId); -impl StyleSlot { - /// Make this slot the first link of the `tail` chain. - pub fn chain<'a>(&'a self, tail: &'a StyleChain) -> StyleChain<'a> { - if let Entry::Barrier(barrier) = &self.0 { - if !tail - .entries() - .filter_map(Entry::property) - .any(|p| p.scoped && p.node == barrier.0) - { - return *tail; - } - } +impl NodeId { + /// The id of the given node. + pub fn of<T: 'static>() -> Self { + Self(ReadableTypeId::of::<T>()) + } +} - StyleChain { - head: std::slice::from_ref(&self.0), - tail: Some(tail), - } +impl Debug for NodeId { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + self.0.fmt(f) } } -impl From<Barrier> for StyleSlot { - fn from(barrier: Barrier) -> Self { - Self(Entry::Barrier(barrier)) +/// A unique identifier for a property key. +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct KeyId(ReadableTypeId); + +impl KeyId { + /// The id of the given key. + pub fn of<'a, T: Key<'a>>() -> Self { + Self(ReadableTypeId::of::<T>()) + } +} + +impl Debug for KeyId { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + self.0.fmt(f) } } /// An entry for a single style property, recipe or barrier. #[derive(Clone, PartialEq, Hash)] -enum Entry { +pub enum StyleEntry { /// A style property originating from a set rule or constructor. Property(Property), /// A barrier for scoped styles. @@ -181,9 +197,9 @@ enum Entry { Recipe(Recipe), } -impl Entry { +impl StyleEntry { /// If this is a property, return it. - fn property(&self) -> Option<&Property> { + pub fn property(&self) -> Option<&Property> { match self { Self::Property(property) => Some(property), _ => None, @@ -191,15 +207,33 @@ impl Entry { } /// If this is a recipe, return it. - fn recipe(&self) -> Option<&Recipe> { + pub fn recipe(&self) -> Option<&Recipe> { match self { Self::Recipe(recipe) => Some(recipe), _ => None, } } + + /// Make this style the first link of the `tail` chain. + pub fn chain<'a>(&'a self, tail: &'a StyleChain) -> StyleChain<'a> { + if let StyleEntry::Barrier(barrier) = self { + if !tail + .entries() + .filter_map(StyleEntry::property) + .any(|p| p.scoped && p.node == barrier.0) + { + return *tail; + } + } + + StyleChain { + head: std::slice::from_ref(self), + tail: Some(tail), + } + } } -impl Debug for Entry { +impl Debug for StyleEntry { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.write_str("#[")?; match self { @@ -211,43 +245,9 @@ impl Debug for Entry { } } -/// A unique identifier for a node. -#[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub struct NodeId(ReadableTypeId); - -impl NodeId { - /// The id of the given node. - pub fn of<T: 'static>() -> Self { - Self(ReadableTypeId::of::<T>()) - } -} - -impl Debug for NodeId { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - -/// A unique identifier for a property key. -#[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub struct KeyId(ReadableTypeId); - -impl KeyId { - /// The id of the given key. - pub fn of<'a, T: Key<'a>>() -> Self { - Self(ReadableTypeId::of::<T>()) - } -} - -impl Debug for KeyId { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - /// A style property originating from a set rule or constructor. #[derive(Clone, Hash)] -struct Property { +pub struct Property { /// The id of the property's [key](Key). key: KeyId, /// The id of the node the property belongs to. @@ -264,7 +264,7 @@ struct Property { impl Property { /// Create a new property from a key-value pair. - fn new<'a, K: Key<'a>>(_: K, value: K::Value) -> Self { + pub fn new<'a, K: Key<'a>>(_: K, value: K::Value) -> Self { Self { key: KeyId::of::<K>(), node: K::node(), @@ -276,7 +276,7 @@ impl Property { } /// What kind of structure the property interrupts. - fn interruption(&self) -> Option<Interruption> { + pub fn interruption(&self) -> Option<Interruption> { if self.is_of::<PageNode>() { Some(Interruption::Page) } else if self.is_of::<ParNode>() { @@ -287,7 +287,7 @@ impl Property { } /// Access the property's value if it is of the given key. - fn downcast<'a, K: Key<'a>>(&'a self) -> Option<&'a K::Value> { + pub fn downcast<'a, K: Key<'a>>(&'a self) -> Option<&'a K::Value> { if self.key == KeyId::of::<K>() { (**self.value).as_any().downcast_ref() } else { @@ -296,7 +296,7 @@ impl Property { } /// Whether this property belongs to the node `T`. - fn is_of<T: Node>(&self) -> bool { + pub fn is_of<T: 'static>(&self) -> bool { self.node == NodeId::of::<T>() } } @@ -478,7 +478,7 @@ impl Debug for Barrier { /// A show rule recipe. #[derive(Clone, PartialEq, Hash)] -struct Recipe { +pub struct Recipe { /// The affected node. node: NodeId, /// The function that defines the recipe. @@ -489,7 +489,7 @@ struct Recipe { impl Recipe { /// Create a new recipe for the node `T`. - fn new<T: Node>(func: Func, span: Span) -> Self { + pub fn new<T: Node>(func: Func, span: Span) -> Self { Self { node: NodeId::of::<T>(), func, span } } } @@ -519,7 +519,7 @@ pub enum Interruption { #[derive(Default, Clone, Copy, Hash)] pub struct StyleChain<'a> { /// The first link of this chain. - head: &'a [Entry], + head: &'a [StyleEntry], /// The remaining links in the chain. tail: Option<&'a Self>, } @@ -553,7 +553,7 @@ impl<'a> StyleChain<'a> { let id = node.id(); if let Some(recipe) = self .entries() - .filter_map(Entry::recipe) + .filter_map(StyleEntry::recipe) .find(|recipe| recipe.node == id) { let dict = node.encode(); @@ -563,16 +563,14 @@ impl<'a> StyleChain<'a> { Ok(None) } } -} -impl<'a> StyleChain<'a> { - /// Return the chain, but without the trailing scoped property for the given - /// `node`. This is a 90% hack fix for show node constructor scoping. - pub(super) fn unscoped(mut self, node: NodeId) -> Self { + /// Return the chain, but without trailing scoped properties for the given + /// `node`. + pub fn unscoped(mut self, node: NodeId) -> Self { while self .head .last() - .and_then(Entry::property) + .and_then(StyleEntry::property) .map_or(false, |p| p.scoped && p.node == node) { let len = self.head.len(); @@ -651,17 +649,17 @@ impl<'a, K: Key<'a>> Iterator for Values<'a, K> { fn next(&mut self) -> Option<Self::Item> { while let Some(entry) = self.entries.next() { match entry { - Entry::Property(property) => { + StyleEntry::Property(property) => { if let Some(value) = property.downcast::<K>() { if !property.scoped || self.depth <= 1 { return Some(value); } } } - Entry::Barrier(barrier) => { + StyleEntry::Barrier(barrier) => { self.depth += (barrier.0 == K::node()) as usize; } - Entry::Recipe(_) => {} + StyleEntry::Recipe(_) => {} } } @@ -671,12 +669,12 @@ impl<'a, K: Key<'a>> Iterator for Values<'a, K> { /// An iterator over the entries in a style chain. struct Entries<'a> { - inner: std::slice::Iter<'a, Entry>, + inner: std::slice::Iter<'a, StyleEntry>, links: Links<'a>, } impl<'a> Iterator for Entries<'a> { - type Item = &'a Entry; + type Item = &'a StyleEntry; fn next(&mut self) -> Option<Self::Item> { loop { @@ -696,7 +694,7 @@ impl<'a> Iterator for Entries<'a> { struct Links<'a>(Option<StyleChain<'a>>); impl<'a> Iterator for Links<'a> { - type Item = &'a [Entry]; + type Item = &'a [StyleEntry]; fn next(&mut self) -> Option<Self::Item> { let StyleChain { head, tail } = self.0?; |
