Parley Engine provides low level APIs for shaping paragraphs of text.
Use [Analyzer], [Analysis], [Shaper] and [ShapedText] to shape a paragraph of text into
glyphs. Correct reshaping of lines is in progress; in the meantime you can break text at
[Atom] or [ShapedCluster][crate::shape::ShapedCluster] boundaries.
Text analysis is performed before shaping, and the same source string must be passed to each stage.
Higher-level users may prefer using parley, which uses this crate and implements
layout and styling.
let mut analysis = Analysis::default();
let mut analyzer = Analyzer::default();
let mut shaped_text = ShapedText::default();
let mut shaper = Shaper::default();
let text = "The quick brown ثعلب jumps over the lazy dog.";
let char_count = text.chars().count();
let char_style_indices = vec![0; char_count];
analyzer.analyze(text, &AnalysisOptions::default(), &mut analysis);
shaper.shape_text(
text,
&analysis,
&char_style_indices,
[Item {
char_end: char_count.try_into().unwrap(),
options: ShapeOptions {
font_size: 16.0,
language: None,
features: &[],
variations: &[],
},
}],
select_font, // Selects fonts covering each cluster.
&mut shaped_text,
);
for (run_idx, run) in shaped_text.runs().iter().enumerate() {
let slice = shaped_text.run_slice(run_idx as u32);
// You can, for example, measure grapheme advances for hit-testing or
// placing carets.
for atom in slice.atoms_start() {
for grapheme in atom.graphemes_start() {
std::dbg!(grapheme);
}
}
// Or get glyphs for rendering (for simplicity, this iterates clusters in
// logical order, but for rendering you'd want to reorder runs and clusters
// according to their `run.bidi_level`).
for cluster in slice.shaped_clusters_range() {
for glyph in slice.shaped_cluster_glyphs(cluster) {
std::dbg!(glyph);
}
}
}std(enabled by default): This is currently unused and is provided for forward compatibility.bytemuck: Forwarded to [parlance], which then implements traits frombytemuckon its types.
This version of Parley Engine has been verified to compile with Rust 1.88 and later.
Future versions of Parley Engine might increase the Rust version requirement. It will not be treated as a breaking change and as such can even happen with small patch releases.
Click here if compiling fails.
As time has passed, some of Parley Engine's dependencies could have released versions with a higher Rust requirement. If you encounter a compilation issue due to a dependency and don't want to upgrade your Rust toolchain, then you could downgrade the dependency.
# Use the problematic dependency's name and version
cargo update -p package_name --precise 0.1.1Discussion of Parley Engine development happens in the Linebender Zulip, specifically the #parley channel. All public content can be read without logging in.
Contributions are welcome by pull request. The Rust code of conduct applies.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache 2.0 license, shall be licensed as noted in the License section, without any additional terms or conditions.
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.