Skip to content

Commit 63f23d0

Browse files
committed
Add external span IDs
Signed-off-by: Nico Burns <[email protected]>
1 parent 9150f28 commit 63f23d0

File tree

8 files changed

+58
-26
lines changed

8 files changed

+58
-26
lines changed

examples/swash_render/src/main.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ fn main() {
8484
..Default::default()
8585
};
8686

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

89-
builder.push_style_modification_span(&[bold_style]);
89+
builder.push_style_modification_span(1, &[bold_style]);
9090
builder.push_text(&text[0..5]);
9191
builder.pop_style_span();
9292

@@ -111,14 +111,14 @@ fn main() {
111111
builder.push_text(&text[50..141]);
112112

113113
// Set the underline style
114-
builder.push_style_modification_span(&[underline_style]);
114+
builder.push_style_modification_span(2, &[underline_style]);
115115
builder.push_text(&text[141..150]);
116116

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

120120
// Set the strikethrough style
121-
builder.push_style_modification_span(&[strikethrough_style]);
121+
builder.push_style_modification_span(3, &[strikethrough_style]);
122122
builder.push_text(&text[155..168]);
123123

124124
// Build the builder into a Layout

parley/src/builder.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,24 @@ pub struct TreeBuilder<'a, B: Brush> {
6969
}
7070

7171
impl<B: Brush> TreeBuilder<'_, B> {
72-
pub fn push_style_span(&mut self, style: TextStyle<'_, B>) {
72+
pub fn push_style_span(&mut self, id: u64, style: TextStyle<'_, B>) {
7373
let resolved = self
7474
.lcx
7575
.rcx
7676
.resolve_entire_style_set(self.fcx, &style, self.scale);
77-
self.lcx.tree_style_builder.push_style_span(resolved);
77+
self.lcx.tree_style_builder.push_style_span(id, resolved);
7878
}
7979

8080
pub fn push_style_modification_span<'s, 'iter>(
8181
&mut self,
82+
id: u64,
8283
properties: impl IntoIterator<Item = &'iter StyleProperty<'s, B>>,
8384
) where
8485
's: 'iter,
8586
B: 'iter,
8687
{
8788
self.lcx.tree_style_builder.push_style_modification_span(
89+
id,
8890
properties
8991
.into_iter()
9092
.map(|p| self.lcx.rcx.resolve_property(self.fcx, p, self.scale)),
@@ -157,7 +159,7 @@ fn build_into_layout<B: Brush>(
157159
layout
158160
.data
159161
.styles
160-
.extend(lcx.styles.iter().map(|s| s.style.as_layout_style()));
162+
.extend(lcx.styles.iter().map(|s| s.as_layout_style()));
161163

162164
// Sort the inline boxes as subsequent code assumes that they are in text index order.
163165
// Note: It's important that this is a stable sort to allow users to control the order of contiguous inline boxes

parley/src/context.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,14 @@ impl<B: Brush> LayoutContext<B> {
8383
&'a mut self,
8484
fcx: &'a mut FontContext,
8585
scale: f32,
86+
root_node_id: u64,
8687
raw_style: &TextStyle<'_, B>,
8788
) -> TreeBuilder<'a, B> {
8889
self.begin();
8990

9091
let resolved_root_style = self.resolve_style_set(fcx, scale, raw_style);
91-
self.tree_style_builder.begin(resolved_root_style);
92+
self.tree_style_builder
93+
.begin(root_node_id, resolved_root_style);
9294

9395
fcx.source_cache.prune(128, false);
9496

parley/src/layout/cluster.rs

+8
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@ impl<'a, B: Brush> Cluster<'a, B> {
9090
self.run.clone()
9191
}
9292

93+
/// The external ID associated with the cluster.
94+
/// - For layouts built with the `RangedBuilder` this will always be 0
95+
/// - For layouts built with the `TreeBuilder` this will the ID associated with the
96+
/// deepest style span that contains this cluster.
97+
pub fn external_span_id(&self) -> u64 {
98+
self.run.layout.data.styles[self.data.style_index as usize].id
99+
}
100+
93101
/// Returns the path that contains the set of indices to reach the cluster
94102
/// from a layout.
95103
pub fn path(&self) -> ClusterPath {

parley/src/layout/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@ pub struct Line<'a, B: Brush> {
249249
/// Style properties.
250250
#[derive(Clone, Debug)]
251251
pub struct Style<B: Brush> {
252+
/// External ID for the style span
253+
pub id: u64,
252254
/// Brush for drawing glyphs.
253255
pub brush: B,
254256
/// Underline decoration.

parley/src/resolve/mod.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,24 @@ use swash::text::Language;
2626
/// Style with an associated range.
2727
#[derive(Debug, Clone)]
2828
pub(crate) struct RangedStyle<B: Brush> {
29+
pub(crate) id: u64,
2930
pub(crate) style: ResolvedStyle<B>,
3031
pub(crate) range: Range<usize>,
3132
}
3233

34+
impl<B: Brush> RangedStyle<B> {
35+
pub(crate) fn as_layout_style(&self) -> layout::Style<B> {
36+
let style = &self.style;
37+
layout::Style {
38+
id: self.id,
39+
brush: style.brush.clone(),
40+
underline: style.underline.as_layout_decoration(&style.brush),
41+
strikethrough: style.strikethrough.as_layout_decoration(&style.brush),
42+
line_height: style.line_height * style.font_size,
43+
}
44+
}
45+
}
46+
3347
#[derive(Clone)]
3448
struct RangedProperty<B: Brush> {
3549
property: ResolvedProperty<B>,
@@ -475,15 +489,6 @@ impl<B: Brush> ResolvedStyle<B> {
475489
LetterSpacing(value) => nearly_eq(self.letter_spacing, *value),
476490
}
477491
}
478-
479-
pub(crate) fn as_layout_style(&self) -> layout::Style<B> {
480-
layout::Style {
481-
brush: self.brush.clone(),
482-
underline: self.underline.as_layout_decoration(&self.brush),
483-
strikethrough: self.strikethrough.as_layout_decoration(&self.brush),
484-
line_height: self.line_height * self.font_size,
485-
}
486-
}
487492
}
488493

489494
/// Underline or strikethrough decoration.

parley/src/resolve/range.rs

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ impl<B: Brush> RangedStyleBuilder<B> {
5757
return;
5858
}
5959
styles.push(RangedStyle {
60+
// TODO: Implement external IDs for RangedBuilder
61+
id: 0,
6062
style: self.default_style.clone(),
6163
range: 0..self.len,
6264
});

parley/src/resolve/tree.rs

+20-9
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ use super::{Brush, RangedStyle, ResolvedProperty, ResolvedStyle};
1111

1212
#[derive(Debug, Clone)]
1313
struct StyleTreeNode<B: Brush> {
14-
parent: Option<usize>,
14+
// An external id provided by the user
15+
id: u64,
16+
// The index of the parent in the tree Vec (*not* the id of the parent node)
17+
parent_idx: Option<usize>,
18+
// The styles associated with the node
1519
style: ResolvedStyle<B>,
1620
}
1721

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

3034
impl<B: Brush> TreeStyleBuilder<B> {
35+
fn current_span_id(&self) -> u64 {
36+
self.tree[self.current_span].id
37+
}
3138
fn current_style(&self) -> ResolvedStyle<B> {
3239
self.tree[self.current_span].style.clone()
3340
}
@@ -49,15 +56,16 @@ impl<B: Brush> Default for TreeStyleBuilder<B> {
4956

5057
impl<B: Brush> TreeStyleBuilder<B> {
5158
/// Prepares the builder for accepting a style tree for text of the specified length.
52-
pub(crate) fn begin(&mut self, root_style: ResolvedStyle<B>) {
59+
pub(crate) fn begin(&mut self, id: u64, root_style: ResolvedStyle<B>) {
5360
self.tree.clear();
5461
self.flatted_styles.clear();
5562
self.white_space_collapse = WhiteSpaceCollapse::Preserve;
5663
self.text.clear();
5764
self.uncommitted_text.clear();
5865

5966
self.tree.push(StyleTreeNode {
60-
parent: None,
67+
id,
68+
parent_idx: None,
6169
style: root_style,
6270
});
6371
self.current_span = 0;
@@ -118,8 +126,9 @@ impl<B: Brush> TreeStyleBuilder<B> {
118126
}
119127

120128
let range = self.text.len()..(self.text.len() + span_text.len());
129+
let id = self.current_span_id();
121130
let style = self.current_style();
122-
self.flatted_styles.push(RangedStyle { style, range });
131+
self.flatted_styles.push(RangedStyle { id, style, range });
123132
self.text.push_str(span_text);
124133
self.uncommitted_text.clear();
125134
self.is_span_first = false;
@@ -129,11 +138,12 @@ impl<B: Brush> TreeStyleBuilder<B> {
129138
self.text.len()
130139
}
131140

132-
pub(crate) fn push_style_span(&mut self, style: ResolvedStyle<B>) {
141+
pub(crate) fn push_style_span(&mut self, id: u64, style: ResolvedStyle<B>) {
133142
self.push_uncommitted_text(false);
134143

135144
self.tree.push(StyleTreeNode {
136-
parent: Some(self.current_span),
145+
id,
146+
parent_idx: Some(self.current_span),
137147
style,
138148
});
139149
self.current_span = self.tree.len() - 1;
@@ -142,20 +152,21 @@ impl<B: Brush> TreeStyleBuilder<B> {
142152

143153
pub(crate) fn push_style_modification_span(
144154
&mut self,
155+
id: u64,
145156
properties: impl Iterator<Item = ResolvedProperty<B>>,
146157
) {
147158
let mut style = self.current_style();
148159
for prop in properties {
149160
style.apply(prop.clone());
150161
}
151-
self.push_style_span(style);
162+
self.push_style_span(id, style);
152163
}
153164

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

157168
self.current_span = self.tree[self.current_span]
158-
.parent
169+
.parent_idx
159170
.expect("Popped root style");
160171
}
161172

@@ -168,7 +179,7 @@ impl<B: Brush> TreeStyleBuilder<B> {
168179

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

0 commit comments

Comments
 (0)