parley/lib.rs
1// Copyright 2021 the Parley Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Parley is a library for rich text layout.
5//!
6//! Some key types are:
7//! - [`FontContext`] and [`LayoutContext`] are resources which should be shared globally (or at coarse-grained boundaries).
8//! - [`FontContext`] is database of fonts.
9//! - [`LayoutContext`] is scratch space that allows for reuse of allocations between layouts.
10//! - Builders for creating a [`Layout`]:
11//! - [`RangedBuilder`]: styles specified as a flat `Vec` of property spans
12//! - [`TreeBuilder`]: styles specified as a tree of spans
13//! - [`StyleRunBuilder`]: styles specified as a shared style table plus non-overlapping indexed runs
14//!
15//! They are constructed using [`LayoutContext::ranged_builder`], [`LayoutContext::tree_builder`],
16//! and [`LayoutContext::style_run_builder`].
17//! - [`Layout`] which represents styled paragraph(s) of text and can perform shaping, line-breaking, bidi-reordering, and alignment of that text.
18//!
19//! `Layout` supports re-linebreaking and re-aligning many times (in case the width at which wrapping should occur changes). But if the text content or
20//! the styles applied to that content change then a new `Layout` must be created using a new
21//! `RangedBuilder`, `TreeBuilder`, or `StyleRunBuilder`.
22//!
23//! ## Usage Example
24//!
25//! See the [examples](https://github.com/linebender/parley/tree/main/examples) directory for more complete usage examples that include rendering.
26//!
27//! ```rust
28//! use parley::{
29//! Alignment, AlignmentOptions, FontContext, FontWeight, InlineBox, InlineBoxKind, Layout,
30//! LayoutContext, LineHeight, PositionedLayoutItem, StyleProperty,
31//! };
32//!
33//! // Create a FontContext (font database) and LayoutContext (scratch space).
34//! // These are both intended to be constructed rarely (perhaps even once per app):
35//! let mut font_cx = FontContext::new();
36//! let mut layout_cx = LayoutContext::new();
37//!
38//! // Create a `RangedBuilder` or a `TreeBuilder`, which are used to construct a `Layout`.
39//! const DISPLAY_SCALE : f32 = 1.0;
40//! const TEXT : &str = "Lorem Ipsum...";
41//! let mut builder = layout_cx.ranged_builder(&mut font_cx, &TEXT, DISPLAY_SCALE, true);
42//!
43//! // Set default styles that apply to the entire layout
44//! builder.push_default(StyleProperty::FontSize(16.0));
45//!
46//! // Set a style that applies to the first 4 characters
47//! builder.push(StyleProperty::FontWeight(FontWeight::new(600.0)), 0..4);
48//!
49//! // Add a box to be laid out inline with the text
50//! builder.push_inline_box(InlineBox { id: 0, kind: InlineBoxKind::InFlow, index: 5, width: 50.0, height: 50.0 });
51//!
52//! // Build the builder into a Layout
53//! let mut layout: Layout<()> = builder.build(&TEXT);
54//!
55//! // Run line-breaking and alignment on the Layout
56//! const MAX_WIDTH : Option<f32> = Some(100.0);
57//! layout.break_all_lines(MAX_WIDTH);
58//! layout.align(Alignment::Start, AlignmentOptions::default());
59//!
60//! // Inspect computed layout (see examples for more details)
61//! let width = layout.width();
62//! let height = layout.height();
63//! for line in layout.lines() {
64//! for item in line.items() {
65//! match item {
66//! PositionedLayoutItem::GlyphRun(glyph_run) => {
67//! // Render the glyph run
68//! }
69//! PositionedLayoutItem::InlineBox(inline_box) => {
70//! // Render the inline box
71//! }
72//! };
73//! }
74//! }
75//! ```
76
77// LINEBENDER LINT SET - lib.rs - v4
78// See https://linebender.org/wiki/canonical-lints/
79// These lints shouldn't apply to examples or tests.
80#![cfg_attr(not(test), warn(unused_crate_dependencies))]
81// These lints shouldn't apply to examples.
82#![warn(clippy::print_stdout, clippy::print_stderr)]
83// Targeting e.g. 32-bit means structs containing usize can give false positives for 64-bit.
84#![cfg_attr(target_pointer_width = "64", warn(clippy::trivially_copy_pass_by_ref))]
85// END LINEBENDER LINT SET
86#![cfg_attr(docsrs, feature(doc_cfg))]
87#![no_std]
88#![allow(missing_docs, reason = "We have many as-yet undocumented items.")]
89#![expect(
90 missing_debug_implementations,
91 clippy::allow_attributes_without_reason,
92 clippy::cast_possible_truncation,
93 clippy::missing_assert_message,
94 reason = "Deferred"
95)]
96#![expect(
97 single_use_lifetimes,
98 reason = "False positive: https://github.com/rust-lang/rust/issues/129255"
99)]
100
101#[cfg(not(any(feature = "std", feature = "libm")))]
102compile_error!("parley requires either the `std` or `libm` feature to be enabled");
103
104extern crate alloc;
105
106#[cfg(feature = "std")]
107extern crate std;
108
109pub use fontique;
110
111mod analysis;
112mod bidi;
113mod builder;
114mod context;
115mod convert;
116mod font;
117mod inline_box;
118mod lru_cache;
119mod resolve;
120mod shape;
121mod util;
122
123pub mod editing;
124pub mod layout;
125pub mod setting;
126pub mod style;
127
128#[cfg(test)]
129mod tests;
130
131pub use linebender_resource_handle::FontData;
132pub use util::BoundingBox;
133
134pub use builder::{RangedBuilder, StyleRunBuilder, TreeBuilder};
135pub use context::LayoutContext;
136pub use font::FontContext;
137pub use inline_box::{InlineBox, InlineBoxKind};
138#[doc(inline)]
139pub use layout::Layout;
140
141pub use editing::*;
142pub use layout::*;
143pub use style::*;
144
145#[deprecated(
146 note = "Old name for this type, use `parley::FontData` instead.",
147 since = "0.6.0"
148)]
149pub type Font = FontData;