All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
- Reject GSUB/GPOS lookups with an out-of-range
lookupTypeinstead of truncating it tou8. A malformed font could have e.g. type 3586 dispatched as MultipleSubst, expanding a single character into thousands of glyphs and costing up to a second pershapecall. HarfBuzz rejects such tables. - When a variation selector is replaced by the not-found variation selector glyph, reset that selector's Unicode properties instead of the first glyph's, matching HarfBuzz.
- Document that glyph IDs are not limited to
u16: glyphs supplied by the caller, such as the not-found variation selector glyph, are passed through unchanged. Shaping tests now cover values aboveu16::MAX.
0.14.0 - 2026-10-03
This release matches HarfBuzz v14.5.1, and has an MSRV (minimum supported Rust version) of 1.85.
- Replace
UnicodeBufferandGlyphBufferwith oneBufferthat holds input Unicode code points before shaping and glyphs afterward.ContentTypereports which state the buffer is in. The old buffer types and their conversion methods have been removed. - Replace the
FontRefentry point withFontfromread-fonts, re-exported asharfrust::Font. Create aShaperFontfrom aFont(or one of its instances) before shaping. - Replace the old
Shaper,ShaperBuilder,ShaperInstance, andShaperDataAPI withShaperFont. - Configure scale and custom
FontFuncsonShaperFontinstead ofShapeOptions. - Shape in place with
harfrust::shape(&shaper_font, &mut buffer, options). It returnsResult<(), ShapeError>for invalid shaping state or properties, rather than returning a separate glyph buffer. CheckBuffer::allocation_successful()separately for allocation or shaping-limit failure.
Replace UnicodeBuffer construction and the returned GlyphBuffer with a
single mutable Buffer. For example, with font_data containing font bytes:
use harfrust::{shape, Buffer, Font, ShapeOptions, ShaperFont};
let font = Font::new(font_data, 0).expect("invalid font");
let shaper_font = ShaperFont::new(&font);
let mut buffer = Buffer::new();
buffer.push_str("Hello");
buffer.guess_segment_properties();
shape(&shaper_font, &mut buffer, ShapeOptions::new()).expect("shaping failed");
let glyphs = buffer.glyph_infos();
let positions = buffer.glyph_positions();Use buffer.clear() to reuse its allocation for another run, then push new
text. Call guess_segment_properties() or set the direction and other segment
properties explicitly before shaping.
Use ShaperFont::set_scale or set_scale_separate for scaling, and
ShaperFont::set_font_funcs for custom font callbacks. ShaperFont borrows the
Font and any supplied callbacks, so it is intended as a short-lived shaping
view; keep the Font and callbacks alive and construct a ShaperFont as needed.
ShapeOptions holds per-call features, an optional plan, and point size.
- Update
read-fontsto 0.45.0 and use its current font model API. - Update the built-in Unicode data to 18.0. Add Jurchen, Proto-Cuneiform, and Seal script constants to the Rust and C APIs and route them through USE.
- Treat U+180F as default ignorable during shaping.
- Support hexadecimal OpenType language and script overrides in
x-hbot-andx-hbsc-private-use subtags, such asx-hbot-4d4f4e54forMONT. - Expose Unicode composition, one-step canonical decomposition, and canonical
combining classes through the public
harfrust::unicodemodule. Decomposition returns aDecomposedenum. - Add the
harfrust_capicrate, a C API mirroring the shaping half of HarfBuzz's API with anhr_prefix in place ofhb_. - Speed up repeated
hr-shaperuns and contextual lookup matching. - Reduce OpenType subtable cache memory by boxing the two large contextual cache variants.
- Leave a GPOS mark unattached when it is more than 32767 glyphs from its base,
as HarfBuzz does, instead of storing a truncated
attach_chainthat mispositioned the mark. - Fix
would_applyfor format 3 (coverage-based) contextual lookups, which never matched, so the Indic shaper missed features built from them. Noto Sans Bengali's ra-phala (e.g. গ্র) came out as consonant, visible hasant and ra.
0.13.3 - 2026-08-25
This release matches HarfBuzz v14.3.1, and has an MSRV (minimum supported Rust version) of 1.85.
- Add support for shaping legacy AAT
morttables, including language-specific morph features (#451, #453). - Handle tuple kerning in AAT
kerxtables (#452). - Fix a debug assertion for legacy
kernstate tables that declare more than 256 classes (#455). - Synthesize Arabic fallback GSUB lookups, including legacy Windows-1256
glyph layouts and
no_stdbuilds (#454, #456). - Update
read-fontsto 0.43.3.
0.13.2 - 2026-08-23
This release matches HarfBuzz v14.3.1, and has an MSRV (minimum supported Rust version) of 1.85.
- Speed up contextual and chained-context lookup matching by probing raw rule offsets and reusing parsed coverage tables (#437).
- Skip the redundant per-subtable digest test for single-subtable lookups (#438).
- Set up glyph-set acceleration before applying legacy
kerntables (#439). - Precompute and pack AAT state-machine safe-to-break probes in the face cache (#445).
- Cache reusable shaping table metadata and avoid moving shaper and buffer temporaries on every shape (#446, #447).
0.13.1 - 2026-08-21
This release matches HarfBuzz v14.3.1, and has an MSRV (minimum supported Rust version) of 1.85.
- Saturate shaping and positioning math across GPOS, kerx, trak, fallback, shaping, metrics, and font scaling paths to avoid overflow and better match HarfBuzz behavior (#420).
- Cache GDEF mark filtering sets in bitmaps (#421).
- Lock
icu_propertiesto 2.2.0 (#422). - Optimize hot loops in contextual and layout matching by probing rules before parsing, hoisting invariants, moving recursion state instead of cloning, and replacing per-element copies with block copies (#423, #424, #425).
- Optimize buffer internals by copying small counts inline and charging
move_tooperations againstmax_ops(#426, #429). - Improve AAT shaping performance by walking
morxsubtables through packed descriptors, resolving subtable kinds from cached parts, and adding a state-machine fast path (#428, #430, #431). - Skip the post-
morxdigest update when GPOS is not present (#433). - Add a batched nominal-glyph callback to
FontFuncs(#434). - Update
read-fontsto 0.43.2 (#432, #435).
0.13.0 - 2026-08-12
This release matches HarfBuzz v14.3.1, and has an MSRV (minimum supported Rust version) of 1.85.
- Guard GPOS cursive attachment against out-of-bounds
attach_chainoffsets that could panic on buffers longer than 32767 glyphs (#411). - Apply
caltto non-Hangul characters in Hangul runs while continuing to suppress it for Jamo. - Preserve the correct component assignments when MultipleSubst output is ligated and positioned with mark attachment lookups.
- Apply cross-direction mark attachment offsets immediately.
- Bound syllables to 64 glyphs during shaping.
- Map the collective ISO 15924
Hrktscript to the OpenTypekanascript tag. - Update
read-fontsto 0.43.0 (#418).
0.12.0 - 2026-07-03
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Update
read-fontsto 0.41.0 (#403). - Saturate AAT kerning position accumulation to avoid overflow (#400).
- Regenerate the Unicode data tables with the latest
packtab(#401). - Keep GPOS variation-index deltas fractional to match HarfBuzz, avoiding sub-font-unit advance and placement differences on variable fonts (#403).
- Keep AAT
traktracking fractional to match HarfBuzz (#404).
0.11.0 - 2026-06-29
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Parse contextual lookup rules in a single pass in the apply path for improved performance (#383).
- Fix integer overflow in fallback positioning shaper (#395).
- Fix overflow panic in skipping_iterator_t when shaping extremely long lines (#397).
- Fix custom nominal glyph cmap caching (#399).
0.10.0 - 2026-06-20
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Add support for the new
read-fontsFont API behind theexperimental_font_apifeature flag in bothread-fontsandharfrust, and updateread-fontsto 0.40.2. - Reject recursive extension lookups.
- Bound ligature cache construction.
0.9.0 - 2026-06-15
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Fix GPOS attachment offset overflow #384
- Require read-fonts 0.40.
0.8.4 - 2026-06-02
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Use bytes instead of str storage for language tag table.
0.8.3 - 2026-06-01
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Add method for appending bulk glyph infos to UnicodeBuffer.
0.8.2 - 2026-05-31
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Allow setting pre- and post-context from codepoints.
- Added
Language::newconstructor that accepts strings or bytes. - Re-export
GlyphIdso thatFontFuncsimplementors don't need to add extra dependencies to name the type. - Reify glyph flags into a
GlyphFlagstype. Existing methods onGlyphInforemain for now to avoid a breaking change but will be removed in a future version. - Fix AAT in place glyph deletion.
0.8.1 - 2026-05-28
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Added support for font function overrides to enable injection of hinted metrics and control
over character mapping. See
FontFuncsandShapeOptions::font_funcs. - Added internal scaling support. See
ShapeOptions::scaleandShapeOptions::scale_separate.
0.8.0 - 2026-05-26
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Refactor ot shape context functions into methods.
- Added
ShapeOptionstype as argument to shape calls, preparation for being able to pass font functions.ShapeOptionsaccepts shape plan, point size, features.shape_with_plan()function removed in favor of new builder-style API. - Document release process to avoid missing LICENSE files.
Release 0.7.1 was released prematurely and yanked from crates.io.
0.7.1 - 2026-05-26
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Document release process to avoid missing LICENSE files.
0.7.0 - 2026-05-21
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Make core_maths dependency optional and add new libm feature to control it. One of libm or std features is now required to build harfrust, matching the behavior of the fontations crates. This is a breaking change.
0.6.2 - 2026-05-21
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Do not hardcode requirement on libm for read-fonts dependency. Libm is required for read-fonts only in nostd environments.
0.6.1 - 2026-05-21
This release matches HarfBuzz v14.2.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Blocklist broken fonts in GDEF. This ports feature from HarfBuzz that was missing before.
- Add LICENSE file symlink to each crate.
0.6.0 - 2026-04-09
This release matches HarfBuzz v14.1.0, and has an MSRV (minimum supported Rust version) of 1.85.
Roll to read-fonts 0.39.0.
0.5.2 - 2026-03-04
This release matches HarfBuzz v13.0.0, and has an MSRV (minimum supported Rust version) of 1.85.
Fix hr-shape dependency, so we can publish on crates.io.
0.5.1 - 2026-03-04
This release matches HarfBuzz v13.0.0, and has an MSRV (minimum supported Rust version) of 1.85.
- New command-line tool
hr-shapethat is a limited counterpart to HarfBuzzhb-shape, in its ownhr-shapecrate. - As a result of the above, source directory turned into a workspace, with new
harfrustandhr-shapedirectories. - Fix bug regarding cluster-level=3.
- Various small performance improvements.
- We stand by the people of Iran.
0.5.0 - 2026-01-07
This release matches HarfBuzz v12.3.0, and has an MSRV (minimum supported Rust version) of 1.85.
- Update to read-fonts 0.37.0 (and bump MSRV to 1.85).
- Various performance improvements.
0.4.1 - 2025-12-08
This release matches HarfBuzz v12.2.0, and has an MSRV (minimum supported Rust version) of 1.82.
- Make Script::from_iso15924_tag const.
- Avoid panic when saving syllable indices.
0.4.0 - 2025-11-10
This release matches HarfBuzz v12.2.0, and has an MSRV (minimum supported Rust version) of 1.82.
- Enable more HarfBuzz tests.
- Fix bug from HarfBust puzzle.
- Update to read-fonts 0.36.0.
0.3.2 - 2025-10-15
This release matches HarfBuzz v12.1.0, and has an MSRV (minimum supported Rust version) of 1.82.
- Fix "would apply" logic for chained sequence context format 3. This bug was preventing accurate classification of characters in Indic syllables for some fonts.
- Various optimizations.
0.3.1 - 2025-09-12
This release matches HarfBuzz v11.5.0, and has an MSRV (minimum supported Rust version) of 1.82.
- Actually bump MSRV from 1.80 to 1.82.
0.3.0 - 2025-09-12
This release matches HarfBuzz v11.5.0, and has an MSRV (minimum supported Rust version) of 1.82.
- Update to read-fonts 0.35.0.
- Bump MSRV from 1.80 to 1.82.
0.2.1 - 2025-09-12
This release matches HarfBuzz v11.5.0, and has an MSRV (minimum supported Rust version) of 1.80.
- Update to Unicode 17.0.
- Fix panic when processing chained sequence context format 3.
- Add accessors for script, language and direction to
ShapePlan. - Various optimizations.
0.2.0 - 2025-08-29
This release matches HarfBuzz v11.4.4, and has an MSRV (minimum supported Rust version) of 1.80.
- Major optimizations to speed up AAT shaping.
0.1.2 - 2025-08-20
This release matches HarfBuzz v11.3.3, and has an MSRV (minimum supported Rust version) of 1.80.
- Major optimizations to speed up shaping.
- Initial support for shape plan caching in the form of
ShapePlanKey.
0.1.1 - 2025-08-11
This release matches HarfBuzz v11.3.3, and has an MSRV (minimum supported Rust version) of 1.75.
- Major optimizations to speed up shaping.
0.1.0 - 2025-06-10
This release matches HarfBuzz v11.2.1, and has an MSRV (minimum supported Rust version) of 1.75.
- Initial Release of HarfRuzz.
HarfRust is a fork of RustyBuzz. See their changelog for details of prior releases.