Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

Parley Engine

Low level text layout

Latest published version. Documentation build status. Apache 2.0 or MIT license.
Linebender Zulip chat. GitHub Actions CI status. Dependency staleness status.

Parley Engine provides low level APIs for shaping paragraphs of text.

Usage

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);
        }
    }
}

Features

  • std (enabled by default): This is currently unused and is provided for forward compatibility.
  • bytemuck: Forwarded to [parlance], which then implements traits from bytemuck on its types.

Minimum supported Rust Version (MSRV)

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.1

Community

Discussion 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.

License

Licensed under either of

at your option.