allsorts/
lib.rs

1#![warn(rust_2018_idioms)]
2#![doc(html_logo_url = "https://github.com/yeslogic/allsorts/raw/master/allsorts.svg?sanitize=1")]
3
4//! # Font parser, shaping engine, and subsetter
5//!
6//! Allsorts is a font parser, shaping engine, and subsetter for OpenType, WOFF, and WOFF2
7//! written entirely in Rust. It was extracted from
8//! [Prince](https://www.princexml.com/), a tool that typesets and lays out HTML
9//! and CSS documents into PDF.
10//!
11//! The Allsorts shaping engine was developed in conjunction with [a specification
12//! for OpenType shaping](https://github.com/n8willis/opentype-shaping-documents/),
13//! which aims to specify OpenType font shaping behaviour.
14//!
15//! ## Features
16//!
17//! * **Parse** TrueType (`ttf`), OpenType (`otf`), WOFF, and WOFF2 files.
18//! * **Shape** Arabic, Cyrillic, Greek, Hebrew, [Indic
19//!   scripts](https://en.wikipedia.org/wiki/Languages_of_India) (Bengali,
20//!   Devanagari, Gujarati, Gurmukhi, Kannada, Malayalam, Oriya, Sinhala, Tamil,
21//!   Telugu), Khmer, Lao, Latin, Syriac, Thai, and other scripts.
22//! * **Subset** from TrueType, OpenType, WOFF, and WOFF2 files into OpenType.
23//!
24//! ## What is font shaping?
25//!
26//! Font shaping is the process of taking text in the form of Unicode codepoints
27//! and a font, and laying out glyphs from the font according to the text. This
28//! involves honouring kerning, ligatures, and substitutions specified by the font.
29//! For some languages this is relatively straightforward. For others, such as
30//! Indic scripts it is quite complex. After shaping, another library such as
31//! [Pathfinder](https://github.com/servo/pathfinder) or
32//! [FreeType](https://www.freetype.org/) is responsible for rendering the glyphs.
33//! To learn more about text rendering, Andrea Cognolato has a good [overview of
34//! modern font rendering on
35//! Linux](https://mrandri19.github.io/2019/07/24/modern-text-rendering-linux-overview.html).
36//! The concepts remain similar on other platforms.
37//!
38//! ## Examples
39//!
40//! Refer to the [Allsorts Tools repository](https://github.com/yeslogic/allsorts-tools) for
41//! a set of tools that exercise Allsorts font parsing, shaping, and subsetting.
42//!
43//! ## Unimplemented Features / Known Issues
44//!
45//! We don't currently support:
46//!
47//! * Shaping Mongolian, and Tibetan.
48//! * Apple's [morx table](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html).
49//! * Unicode normalisation.
50//!
51//! Known limitations:
52//!
53//! * The crate is not extensively documented yet ([#5](https://github.com/yeslogic/allsorts/issues/5)).
54//! * Allsorts does not do font lookup/matching. For this something like
55//!   [font-kit](https://github.com/pcwalton/font-kit) is recommended.
56//!
57//! ## Development Status
58//!
59//! Allsorts is still under active development but reached its first release
60//! milestone with its inclusion in Prince 13. In Prince it is responsible for
61//! all font loading, and font shaping.
62//!
63//! Currently, the font parsing code is handwritten. It is planned for this to
64//! eventually be replaced by machine generated code via our [declarative data
65//! definition language project](https://github.com/yeslogic/fathom).
66//!
67//! ## Platform Support
68//!
69//! Allsorts CI runs tests on Linux, macOS, and Windows. Via Prince it is also
70//! built for FreeBSD.
71//!
72//! ## Building and Testing
73//!
74//! **Minimum Supported Rust Version:** 1.66.0
75//!
76//! To build the crate ensure you have [Rust 1.66.0 or newer installed](https://www.rust-lang.org/tools/install).
77//!
78//! Build with `cargo build` and run the tests with `cargo test`.
79//!
80//! ### Cargo Features
81//!
82//! | Feature       | Description                              | Default Enabled | Extra Dependencies    |
83//! |---------------|------------------------------------------|:---------------:|-----------------------|
84//! | `outline`     | Enable code for accessing glyph outlines |        ✅       | `pathfinder_geometry` |
85//! | `flate2_zlib` | Use the zlib backend to flate2           |        ✅       | `zlib`                |
86//! | `flate2_rust` | Use the Rust backend to flate2           |        ❌       | `miniz_oxide`         |
87//! | `prince`      | Enable Prince specific tests and code    |        ❌       |                       |
88//!
89//! **Note:** In our testing the `zlib` `flate2` backend was faster but you may
90//! prefer the Rust backend for a pure Rust solution when compiling to WASM or
91//! similar.
92//!
93//! ## Contributing
94//!
95//! Contributions are welcome, please refer to the
96//! [contributing document](https://github.com/yeslogic/allsorts/blob/master/CONTRIBUTING.md)
97//! for more details.
98//!
99//! ## Code of Conduct
100//!
101//! We aim to uphold the Rust community standards:
102//!
103//! > We are committed to providing a friendly, safe and welcoming environment for
104//! > all, regardless of gender, sexual orientation, disability, ethnicity,
105//! > religion, or similar personal characteristic.
106//!
107//! We follow the [Rust code of conduct](https://www.rust-lang.org/policies/code-of-conduct).
108//!
109//! ## Acknowledgements
110//!
111//! * [OpenType shaping documents](https://github.com/n8willis/opentype-shaping-documents/)
112//!   forms the specification from which the shaping engine is implemented.
113//! * [HarfBuzz](https://github.com/harfbuzz/harfbuzz) the widely used open source
114//!   font shaping engine was used as reference for test output.
115//! * The [Adobe Annotated OpenType Specification](https://github.com/adobe-type-tools/aots)
116//!   test suite is used as part of the Allsorts test suite.
117//! * [ttf-parser](https://github.com/RazrFalcon/ttf-parser) for CFF CharString parsing code.
118//!
119//! ## License
120//!
121//! Allsorts is distributed under the terms of the Apache License (Version 2.0).
122//!
123//! See [LICENSE](https://github.com/yeslogic/allsorts/blob/master/LICENSE) for details.
124
125pub mod big5;
126pub mod binary;
127pub mod bitmap;
128pub mod cff;
129pub mod checksum;
130pub mod context;
131pub mod error;
132pub mod font;
133pub mod font_data;
134#[cfg(feature = "specimen")]
135pub mod font_specimen;
136pub mod gdef;
137pub mod get_name;
138pub mod glyph_info;
139pub mod glyph_position;
140pub mod gpos;
141pub mod gsub;
142pub mod layout;
143pub mod macroman;
144#[cfg(feature = "outline")]
145pub mod outline;
146pub mod post;
147pub mod scripts;
148pub mod size;
149pub mod subset;
150pub mod tables;
151pub mod tag;
152#[cfg(test)]
153pub mod tests;
154pub mod unicode;
155pub mod variations;
156pub mod woff;
157pub mod woff2;
158
159pub use font::Font;
160#[cfg(feature = "outline")]
161pub use pathfinder_geometry;
162pub use tinyvec;
163
164pub const DOTTED_CIRCLE: char = '◌';
165pub const VERSION: &str = env!("CARGO_PKG_VERSION");
166
167#[macro_export]
168macro_rules! read_table {
169    ($source:expr, $tag:path, $t:ty, $index:expr) => {
170        $source
171            .read_table($tag, $index)?
172            .ok_or(ParseError::MissingValue)?
173            .scope()
174            .read::<$t>()
175    };
176}
177
178#[cfg(not(any(feature = "flate2_zlib", feature = "flate2_rust")))]
179compile_error!("Allsorts is being built without one of `flate2_zlib` or `flate2_rust` Cargo features enabled. One of these must be enabled");
180
181/// A trait for safe casting from u32 to usize
182///
183/// Rust doesn't implement `From<u32> for usize` because of 16-bit targets. They aren't supported
184/// by Allsorts though, so this trait allows safe casting on 32-bit and greater platforms whilst
185/// producing a compile time error on less than 32-bit targets.
186pub(crate) trait SafeFrom<T>: Sized {
187    /// A safe From impl for u32 into usize.
188    fn safe_from(_: T) -> Self;
189}
190
191impl SafeFrom<u32> for usize {
192    #[inline]
193    fn safe_from(v: u32) -> Self {
194        #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
195        {
196            v as usize
197        }
198
199        // Compiler error on 16-bit targets
200    }
201}