Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions examples/swash_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,15 +245,15 @@ fn render_glyph_run(
let normalized_coords = run.normalized_coords();

// Convert from parley::Font to swash::FontRef
let font_ref = FontRef::from_index(font.data.as_ref(), font.index as usize).unwrap();
let font_ref = FontRef::from_index(font.font.data.as_ref(), font.font.index as usize).unwrap();

// Build a scaler. As the font properties are constant across an entire run of glyphs
// we can build one scaler for the run and reuse it for each glyph.
let mut scaler = context
.builder(font_ref)
.size(font_size)
.hint(true)
.normalized_coords(normalized_coords)
.normalized_coords(normalized_coords.iter().map(|c| c.to_bits()))
.build();

// Iterates over the glyphs in the GlyphRun
Expand All @@ -267,7 +267,7 @@ fn render_glyph_run(

// Draw decorations: underline & strikethrough
let style = glyph_run.style();
let run_metrics = run.metrics();
let run_metrics = run.font_metrics();
if let Some(decoration) = &style.underline {
let offset = decoration.offset.unwrap_or(run_metrics.underline_offset);
let size = decoration.size.unwrap_or(run_metrics.underline_size);
Expand Down
8 changes: 4 additions & 4 deletions examples/tiny_skia_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,12 @@ fn render_glyph_run(glyph_run: &GlyphRun<'_, ColorBrush>, pen: &mut TinySkiaPen<
let normalized_coords = run
.normalized_coords()
.iter()
.map(|coord| NormalizedCoord::from_bits(*coord))
.map(|coord| NormalizedCoord::from_bits(coord.to_bits()))
.collect::<Vec<_>>();

// Get glyph outlines using Skrifa. This can be cached in production code.
let font_collection_ref = font.data.as_ref();
let font_ref = ReadFontsRef::from_index(font_collection_ref, font.index).unwrap();
let font_collection_ref = font.font.data.as_ref();
let font_ref = ReadFontsRef::from_index(font_collection_ref, font.font.index).unwrap();
let outlines = font_ref.outline_glyphs();

// Iterates over the glyphs in the GlyphRun
Expand All @@ -187,7 +187,7 @@ fn render_glyph_run(glyph_run: &GlyphRun<'_, ColorBrush>, pen: &mut TinySkiaPen<

// Draw decorations: underline & strikethrough
let style = glyph_run.style();
let run_metrics = run.metrics();
let run_metrics = run.font_metrics();
if let Some(decoration) = &style.underline {
let offset = decoration.offset.unwrap_or(run_metrics.underline_offset);
let size = decoration.size.unwrap_or(run_metrics.underline_size);
Expand Down
18 changes: 12 additions & 6 deletions examples/vello_cpu_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,14 @@ fn render_frame(
let run = glyph_run.run();

stats.start("fill_glyphs");
let normalized_coords =
&Vec::from_iter(run.normalized_coords().iter().map(|c| c.to_bits()));
Comment on lines +92 to +93

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allocation is unfortunate! Do we want to have a bytemuck feature or similar so that we can:

let normalized_coords: &[i16] =
      bytemuck::cast_slice(run.normalized_coords());

@tomcur tomcur Jul 21, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think so, though Nico also requested the type to live in parlance, which probably makes sense. See the comment thread at #679 (comment).

I'll merge this for now and follow up in a separate PR.

renderer.set_paint(glyph_run.style().brush.color);
renderer
.glyph_run(run.font())
.glyph_run(&run.font().font)
.font_size(run.font_size())
.hint(config.hint)
.normalized_coords(run.normalized_coords())
.normalized_coords(normalized_coords)
.fill_glyphs(glyph_run.positioned_glyphs().map(|glyph| Glyph {
id: glyph.id,
x: glyph.x,
Expand All @@ -104,8 +106,10 @@ fn render_frame(

let style = glyph_run.style();
if let Some(decoration) = &style.underline {
let offset = decoration.offset.unwrap_or(run.metrics().underline_offset);
let size = decoration.size.unwrap_or(run.metrics().underline_size);
let offset = decoration
.offset
.unwrap_or(run.font_metrics().underline_offset);
let size = decoration.size.unwrap_or(run.font_metrics().underline_size);

stats.start("render_underline");
render_decoration(renderer, &decoration.brush, &glyph_run, offset, size);
Expand All @@ -114,8 +118,10 @@ fn render_frame(
if let Some(decoration) = &style.strikethrough {
let offset = decoration
.offset
.unwrap_or(run.metrics().strikethrough_offset);
let size = decoration.size.unwrap_or(run.metrics().strikethrough_size);
.unwrap_or(run.font_metrics().strikethrough_offset);
let size = decoration
.size
.unwrap_or(run.font_metrics().strikethrough_size);

stats.start("render_strikethrough");
render_decoration(renderer, &decoration.brush, &glyph_run, offset, size);
Expand Down
10 changes: 6 additions & 4 deletions examples/vello_editor/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ impl Editor {
// https://drafts.csswg.org/css-text-decor/#painting-order
if let Some(underline) = &style.underline {
let underline_brush = &style.brush;
let run_metrics = glyph_run.run().metrics();
let run_metrics = glyph_run.run().font_metrics();
let offset = match underline.offset {
Some(offset) => offset,
None => run_metrics.underline_offset,
Expand Down Expand Up @@ -444,13 +444,15 @@ impl Editor {
.skew()
.map(|angle| Affine::skew(angle.to_radians().tan() as f64, 0.0));
scene
.draw_glyphs(font)
.draw_glyphs(&font.font)
.brush(&style.brush)
.hint(true)
.transform(transform)
.glyph_transform(glyph_xform)
.font_size(font_size)
.normalized_coords(run.normalized_coords())
.normalized_coords(&Vec::from_iter(
run.normalized_coords().iter().map(|c| c.to_bits()),
))
.draw(
Fill::NonZero,
glyph_run.glyphs().map(|glyph| {
Expand All @@ -466,7 +468,7 @@ impl Editor {
);
if let Some(strikethrough) = &style.strikethrough {
let strikethrough_brush = &style.brush;
let run_metrics = glyph_run.run().metrics();
let run_metrics = glyph_run.run().font_metrics();
let offset = match strikethrough.offset {
Some(offset) => offset,
None => run_metrics.strikethrough_offset,
Expand Down
16 changes: 4 additions & 12 deletions parley/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,24 @@ workspace = true

[features]
default = ["system"]
std = [
"fontique/std",
"harfrust/std",
"parley_core/std",
"peniko/std",
"skrifa/std",
"parlance/std",
]
libm = ["fontique/libm", "harfrust/libm", "peniko/libm", "skrifa/libm", "dep:core_maths"]
std = ["fontique/std", "parley_core/std", "peniko/std", "skrifa?/std", "parlance/std"]
libm = ["fontique/libm", "parley_core/libm", "peniko/libm", "skrifa?/libm", "dep:core_maths"]
# Enables support for system font backends
system = ["std", "fontique/system"]
accesskit = ["dep:accesskit"]
accesskit = ["dep:accesskit", "dep:skrifa"]
# Enables dictionary-based line and word breaking for complex scripts (CJK, Thai, Khmer, Lao, Myanmar).
# When disabled, a lightweight segmenter is used that falls back to character-level breaks for those scripts.
complex-scripts = ["parley_core/complex-scripts"]

[dependencies]
skrifa = { workspace = true }
skrifa = { workspace = true, optional = true }
linebender_resource_handle = { workspace = true }
fontique = { workspace = true }
parlance = { workspace = true }
parley_core = { workspace = true }
core_maths = { version = "0.1.1", optional = true }
accesskit = { workspace = true, optional = true }
hashbrown = { workspace = true }
harfrust = { workspace = true }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉


[dev-dependencies]
parley_dev = { workspace = true }
Expand Down
3 changes: 2 additions & 1 deletion parley/src/editing/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,8 @@ impl Cursor {
let (span_path, character_index) = if self.index == layout.data.text_len
&& layout
.data
.clusters
.shaped_text
.clusters()
.last()
.map(|cluster| cluster.info.whitespace() == Whitespace::Newline)
.unwrap_or_default()
Expand Down
4 changes: 2 additions & 2 deletions parley/src/editing/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,8 +562,8 @@ impl Selection {
"Expected the line's last logical run to be a newline cluster."
);
let run = newline_cluster.run();
let run_metrics = run.metrics();
(run_metrics.ascent as f64 + run_metrics.descent as f64)
let font_metrics = run.font_metrics();
(font_metrics.ascent as f64 + font_metrics.descent as f64)
* NEWLINE_WHITESPACE_WIDTH_RATIO
}
None => 0.0,
Expand Down
2 changes: 1 addition & 1 deletion parley/src/layout/accessibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl LayoutAccessibility {
});

let font = run.font();
if let Ok(font_ref) = FontRef::from_index(font.data.as_ref(), font.index)
if let Ok(font_ref) = FontRef::from_index(font.font.data.as_ref(), font.font.index)
&& let Ok(name) = font_ref.name()
{
for n in name.name_record().iter() {
Expand Down
3 changes: 2 additions & 1 deletion parley/src/layout/alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ fn align_impl<B: Brush, const UNDO_JUSTIFICATION: bool>(
line_items
.filter(|item| item.is_text_run())
.for_each(|line_item| {
let clusters = &mut layout.clusters[line_item.cluster_range.clone()];
let clusters =
&mut layout.shaped_text.clusters_mut()[line_item.cluster_range.clone()];
Comment on lines +171 to +172

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙈 - don't look here! 😆

Agree with PR description - you're right we should just expose this as a mutable until we finish the migration and discussion above.

let line_item_is_rtl = line_item.bidi_level & 1 != 0;
let clusters: &mut dyn Iterator<Item = &mut ClusterData> =
if line_item_is_rtl {
Expand Down
8 changes: 5 additions & 3 deletions parley/src/layout/cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ impl<'a, B: Brush> Cluster<'a, B> {

/// Returns the range of text that defines the cluster.
pub fn text_range(&self) -> Range<usize> {
let start = self.run.data.text_range.start + self.data.text_offset as usize;
let start = self.run.shaped.range.byte_range.start + self.data.text_offset as usize;
start..start + self.data.text_len as usize
}

Expand Down Expand Up @@ -226,9 +226,11 @@ impl<'a, B: Brush> Cluster<'a, B> {
advance: self.data.advance,
}))
} else {
let start = self.run.data.glyph_start + self.data.glyph_offset as usize;
let start = self.run.shaped.glyphs_range.start + self.data.glyph_offset as usize;
GlyphIter::Slice(
self.run.layout.data.glyphs[start..start + self.data.glyph_len as usize].iter(),
self.run.layout.data.shaped_text.glyphs()
[start..start + self.data.glyph_len as usize]
.iter(),
)
}
}
Expand Down
Loading
Loading