parley_engine/lib.rs
1// Copyright 2025 the Parley Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Parley Engine provides low level APIs for shaping paragraphs of text.
5//!
6//! ## Usage
7//!
8//! Use [`Analyzer`], [`Analysis`], [`Shaper`] and [`ShapedText`] to shape a paragraph of text into
9//! glyphs. Correct reshaping of lines is in progress; in the meantime you can break text at
10//! [`Atom`] or [`ShapedCluster`][crate::shape::ShapedCluster] boundaries.
11//!
12//! Text analysis is performed before shaping, and the same source string must be passed to each
13//! stage.
14//!
15//! Higher-level users may prefer using [`parley`][parley], which uses this crate and implements
16//! layout and styling.
17//!
18//! ```rust,no_run
19//! # // We only compile this doctest because we don't have a font available.
20//! # use parley_engine::{Analysis, AnalysisOptions, Analyzer, FontInstanceRef, FontSelector, ShapedText, ShapeOptions, Shaper};
21//! # use parley_engine::shape::CharCluster;
22//! # use parley_engine::itemize::{Item, Segment};
23//! #
24//! # struct NoFont;
25//! # impl FontSelector for NoFont {
26//! # fn select_font(
27//! # &mut self,
28//! # _segment: &Segment,
29//! # _options: &ShapeOptions<'_>,
30//! # _cluster: &mut CharCluster,
31//! # ) -> Option<FontInstanceRef<'_>> {
32//! # unimplemented!()
33//! # }
34//! # }
35//! #
36//! # let select_font = NoFont;
37//! let mut analysis = Analysis::default();
38//! let mut analyzer = Analyzer::default();
39//! let mut shaped_text = ShapedText::default();
40//! let mut shaper = Shaper::default();
41//!
42//! let text = "The quick brown ثعلب jumps over the lazy dog.";
43//! let char_count = text.chars().count();
44//! let char_style_indices = vec![0; char_count];
45//!
46//! analyzer.analyze(text, &AnalysisOptions::default(), &mut analysis);
47//! shaper.shape_text(
48//! text,
49//! &analysis,
50//! &char_style_indices,
51//! [Item {
52//! char_end: char_count.try_into().unwrap(),
53//! options: ShapeOptions {
54//! font_size: 16.0,
55//! language: None,
56//! features: &[],
57//! variations: &[],
58//! },
59//! }],
60//! select_font, // Selects fonts covering each cluster.
61//! &mut shaped_text,
62//! );
63//!
64//! for (run_idx, run) in shaped_text.runs().iter().enumerate() {
65//! let slice = shaped_text.run_slice(run_idx as u32);
66//! // You can, for example, measure grapheme advances for hit-testing or
67//! // placing carets.
68//! for atom in slice.atoms_start() {
69//! for grapheme in atom.graphemes_start() {
70//! std::dbg!(grapheme);
71//! }
72//! }
73//!
74//! // Or get glyphs for rendering (for simplicity, this iterates clusters in
75//! // logical order, but for rendering you'd want to reorder runs and clusters
76//! // according to their `run.bidi_level`).
77//! for cluster in slice.shaped_clusters_range() {
78//! for glyph in slice.shaped_cluster_glyphs(cluster) {
79//! std::dbg!(glyph);
80//! }
81//! }
82//! }
83//! ```
84//!
85//! ## Features
86//!
87//! - `std` (enabled by default): This is currently unused and is provided for forward compatibility.
88//! - `bytemuck`: Forwarded to [`parlance`], which then implements traits from `bytemuck` on its
89//! types.
90//!
91//! [parley]: https://docs.rs/parley
92
93// LINEBENDER LINT SET - lib.rs - v3
94// See https://linebender.org/wiki/canonical-lints/
95// These lints shouldn't apply to examples or tests.
96#![cfg_attr(not(test), warn(unused_crate_dependencies))]
97// These lints shouldn't apply to examples.
98#![warn(clippy::print_stdout, clippy::print_stderr)]
99// Targeting e.g. 32-bit means structs containing usize can give false positives for 64-bit.
100#![cfg_attr(target_pointer_width = "64", warn(clippy::trivially_copy_pass_by_ref))]
101// END LINEBENDER LINT SET
102#![cfg_attr(docsrs, feature(doc_cfg))]
103#![no_std]
104#[cfg(feature = "std")]
105extern crate std;
106
107extern crate alloc;
108
109mod analysis;
110mod analyzer;
111mod bidi;
112pub mod break_overrides;
113mod glyph;
114pub mod itemize;
115mod lru_cache;
116pub mod shape;
117
118pub use linebender_resource_handle::FontData;
119pub use parlance::{BaseDirection, NormalizedCoord};
120
121pub use analysis::{Analysis, AnalysisDataSources, CharInfo};
122pub use analyzer::{AnalysisOptions, Analyzer, LineBreakConfig};
123pub use glyph::Glyph;
124pub use shape::atom::{Atom, Atoms, Grapheme, Graphemes, ShapedClusterGlyphs, ShapedSlice};
125pub use shape::shaped_text::{FontMetrics, ShapedRun, ShapedText};
126pub use shape::shaper::{FontInstance, FontInstanceRef, FontSelector, ShapeOptions, Shaper};