summaryrefslogtreecommitdiff
path: root/src/model
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-04-25 15:50:13 +0200
committerLaurenz <laurmaedje@gmail.com>2022-04-25 15:50:13 +0200
commit09aabc3a21e403e0b09a6d6ba517e34a303b217c (patch)
tree590a26bdfe3c5c3c1a48a0271ba54ee3b076a791 /src/model
parent649c101f07f6de4791dc9b6091dff4a85112a15c (diff)
Public style entry enum
Diffstat (limited to 'src/model')
-rw-r--r--src/model/collapse.rs16
-rw-r--r--src/model/content.rs18
-rw-r--r--src/model/layout.rs6
-rw-r--r--src/model/styles.rs170
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?;