Skip to content

Commit

Permalink
Add external span IDs
Browse files Browse the repository at this point in the history
Signed-off-by: Nico Burns <[email protected]>
  • Loading branch information
nicoburns committed Dec 16, 2024
1 parent eb6d5e5 commit c4c0947
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 26 deletions.
8 changes: 4 additions & 4 deletions examples/swash_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ fn main() {
..Default::default()
};

let mut builder = layout_cx.tree_builder(&mut font_cx, display_scale, &root_style);
let mut builder = layout_cx.tree_builder(&mut font_cx, display_scale, 0, &root_style);

builder.push_style_modification_span(&[bold_style]);
builder.push_style_modification_span(1, &[bold_style]);
builder.push_text(&text[0..5]);
builder.pop_style_span();

Expand All @@ -108,14 +108,14 @@ fn main() {
builder.push_text(&text[50..141]);

// Set the underline style
builder.push_style_modification_span(&[underline_style]);
builder.push_style_modification_span(2, &[underline_style]);
builder.push_text(&text[141..150]);

builder.pop_style_span();
builder.push_text(&text[150..155]);

// Set the strikethrough style
builder.push_style_modification_span(&[strikethrough_style]);
builder.push_style_modification_span(3, &[strikethrough_style]);
builder.push_text(&text[155..168]);

// Build the builder into a Layout
Expand Down
8 changes: 5 additions & 3 deletions parley/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,24 @@ pub struct TreeBuilder<'a, B: Brush> {
}

impl<B: Brush> TreeBuilder<'_, B> {
pub fn push_style_span(&mut self, style: TextStyle<'_, B>) {
pub fn push_style_span(&mut self, id: u64, style: TextStyle<'_, B>) {
let resolved = self
.lcx
.rcx
.resolve_entire_style_set(self.fcx, &style, self.scale);
self.lcx.tree_style_builder.push_style_span(resolved);
self.lcx.tree_style_builder.push_style_span(id, resolved);
}

pub fn push_style_modification_span<'s, 'iter>(
&mut self,
id: u64,
properties: impl IntoIterator<Item = &'iter StyleProperty<'s, B>>,
) where
's: 'iter,
B: 'iter,
{
self.lcx.tree_style_builder.push_style_modification_span(
id,
properties
.into_iter()
.map(|p| self.lcx.rcx.resolve_property(self.fcx, p, self.scale)),
Expand Down Expand Up @@ -156,7 +158,7 @@ fn build_into_layout<B: Brush>(
layout
.data
.styles
.extend(lcx.styles.iter().map(|s| s.style.as_layout_style()));
.extend(lcx.styles.iter().map(|s| s.as_layout_style()));

// Sort the inline boxes as subsequent code assumes that they are in text index order.
// Note: It's important that this is a stable sort to allow users to control the order of contiguous inline boxes
Expand Down
4 changes: 3 additions & 1 deletion parley/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,14 @@ impl<B: Brush> LayoutContext<B> {
&'a mut self,
fcx: &'a mut FontContext,
scale: f32,
root_node_id: u64,
raw_style: &TextStyle<'_, B>,
) -> TreeBuilder<'a, B> {
self.begin();

let resolved_root_style = self.resolve_style_set(fcx, scale, raw_style);
self.tree_style_builder.begin(resolved_root_style);
self.tree_style_builder
.begin(root_node_id, resolved_root_style);

fcx.source_cache.prune(128, false);

Expand Down
8 changes: 8 additions & 0 deletions parley/src/layout/cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ impl<'a, B: Brush> Cluster<'a, B> {
self.run.clone()
}

/// The external ID associated with the cluster.
/// - For layouts built with the `RangedBuilder` this will always be 0
/// - For layouts built with the `TreeBuilder` this will the ID associated with the
/// deepest style span that contains this cluster.
pub fn external_span_id(&self) -> u64 {
self.run.layout.data.styles[self.data.style_index as usize].id
}

/// Returns the path that contains the set of indices to reach the cluster
/// from a layout.
pub fn path(&self) -> ClusterPath {
Expand Down
2 changes: 2 additions & 0 deletions parley/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ pub struct Line<'a, B: Brush> {
/// Style properties.
#[derive(Clone, Debug)]
pub struct Style<B: Brush> {
/// External ID for the style span
pub id: u64,
/// Brush for drawing glyphs.
pub brush: B,
/// Underline decoration.
Expand Down
23 changes: 14 additions & 9 deletions parley/src/resolve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,24 @@ use swash::text::Language;
/// Style with an associated range.
#[derive(Debug, Clone)]
pub(crate) struct RangedStyle<B: Brush> {
pub(crate) id: u64,
pub(crate) style: ResolvedStyle<B>,
pub(crate) range: Range<usize>,
}

impl<B: Brush> RangedStyle<B> {
pub(crate) fn as_layout_style(&self) -> layout::Style<B> {
let style = &self.style;
layout::Style {
id: self.id,
brush: style.brush.clone(),
underline: style.underline.as_layout_decoration(&style.brush),
strikethrough: style.strikethrough.as_layout_decoration(&style.brush),
line_height: style.line_height * style.font_size,
}
}
}

#[derive(Clone)]
struct RangedProperty<B: Brush> {
property: ResolvedProperty<B>,
Expand Down Expand Up @@ -475,15 +489,6 @@ impl<B: Brush> ResolvedStyle<B> {
LetterSpacing(value) => nearly_eq(self.letter_spacing, *value),
}
}

pub(crate) fn as_layout_style(&self) -> layout::Style<B> {
layout::Style {
brush: self.brush.clone(),
underline: self.underline.as_layout_decoration(&self.brush),
strikethrough: self.strikethrough.as_layout_decoration(&self.brush),
line_height: self.line_height * self.font_size,
}
}
}

/// Underline or strikethrough decoration.
Expand Down
2 changes: 2 additions & 0 deletions parley/src/resolve/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ impl<B: Brush> RangedStyleBuilder<B> {
return;
}
styles.push(RangedStyle {
// TODO: Implement external IDs for RangedBuilder
id: 0,
style: self.default_style.clone(),
range: 0..self.len,
});
Expand Down
29 changes: 20 additions & 9 deletions parley/src/resolve/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ use super::{Brush, RangedStyle, ResolvedProperty, ResolvedStyle};

#[derive(Debug, Clone)]
struct StyleTreeNode<B: Brush> {
parent: Option<usize>,
// An external id provided by the user
id: u64,
// The index of the parent in the tree Vec (*not* the id of the parent node)
parent_idx: Option<usize>,
// The styles associated with the node
style: ResolvedStyle<B>,
}

Expand All @@ -28,6 +32,9 @@ pub(crate) struct TreeStyleBuilder<B: Brush> {
}

impl<B: Brush> TreeStyleBuilder<B> {
fn current_span_id(&self) -> u64 {
self.tree[self.current_span].id
}
fn current_style(&self) -> ResolvedStyle<B> {
self.tree[self.current_span].style.clone()
}
Expand All @@ -49,15 +56,16 @@ impl<B: Brush> Default for TreeStyleBuilder<B> {

impl<B: Brush> TreeStyleBuilder<B> {
/// Prepares the builder for accepting a style tree for text of the specified length.
pub(crate) fn begin(&mut self, root_style: ResolvedStyle<B>) {
pub(crate) fn begin(&mut self, id: u64, root_style: ResolvedStyle<B>) {
self.tree.clear();
self.flatted_styles.clear();
self.white_space_collapse = WhiteSpaceCollapse::Preserve;
self.text.clear();
self.uncommitted_text.clear();

self.tree.push(StyleTreeNode {
parent: None,
id,
parent_idx: None,
style: root_style,
});
self.current_span = 0;
Expand Down Expand Up @@ -113,8 +121,9 @@ impl<B: Brush> TreeStyleBuilder<B> {
}

let range = self.text.len()..(self.text.len() + span_text.len());
let id = self.current_span_id();
let style = self.current_style();
self.flatted_styles.push(RangedStyle { style, range });
self.flatted_styles.push(RangedStyle { id, style, range });
self.text.push_str(span_text);
self.uncommitted_text.clear();
self.is_span_first = false;
Expand All @@ -124,11 +133,12 @@ impl<B: Brush> TreeStyleBuilder<B> {
self.text.len()
}

pub(crate) fn push_style_span(&mut self, style: ResolvedStyle<B>) {
pub(crate) fn push_style_span(&mut self, id: u64, style: ResolvedStyle<B>) {
self.push_uncommitted_text(false);

self.tree.push(StyleTreeNode {
parent: Some(self.current_span),
id,
parent_idx: Some(self.current_span),
style,
});
self.current_span = self.tree.len() - 1;
Expand All @@ -137,20 +147,21 @@ impl<B: Brush> TreeStyleBuilder<B> {

pub(crate) fn push_style_modification_span(
&mut self,
id: u64,
properties: impl Iterator<Item = ResolvedProperty<B>>,
) {
let mut style = self.current_style();
for prop in properties {
style.apply(prop.clone());
}
self.push_style_span(style);
self.push_style_span(id, style);
}

pub(crate) fn pop_style_span(&mut self) {
self.push_uncommitted_text(true);

self.current_span = self.tree[self.current_span]
.parent
.parent_idx
.expect("Popped root style");
}

Expand All @@ -163,7 +174,7 @@ impl<B: Brush> TreeStyleBuilder<B> {

/// Computes the sequence of ranged styles.
pub(crate) fn finish(&mut self, styles: &mut Vec<RangedStyle<B>>) -> String {
while self.tree[self.current_span].parent.is_some() {
while self.tree[self.current_span].parent_idx.is_some() {
self.pop_style_span();
}

Expand Down

0 comments on commit c4c0947

Please sign in to comment.