This release has an MSRV of 1.88.
BidiLevelto encode bidirectional text embedding levels. (#710 by @tomcur)Script::is_cursivereturning whether a script is cursive. (#728 by @tomcur)
This can be used to decide, for example, whether to apply letter spacing.
- Breaking change: the
Glyph::style_indexfield was removed. UseCluster::{style, style_index}orGlyphRun::{style, style_index}instead. (#661 by @tomcur) - Breaking change:
Clusternow spans a full grapheme cluster instead of a single character. (#715 by @tomcur)
Shaped clusters that cross grapheme boundaries are represented using the existingCluster::is_ligature_startandCluster::is_ligature_continuation; note these methods previously encoded graphemes as well. Shaped clusters' advances are split evenly over the grapheme clusters they overlap.Run::cluster_rangenow returns grapheme cluster indices relative to the run's shaped run. - Breaking change: lines with mixed inline content, like different fonts or sizes, or inline boxes, are now sized more closely to the CSS line-box model. (#697 by @tomcur)
TheLineMetrics::{ascent,descent,leading}fields were removed, andLineMetrics::block_{min,max}_coordnow describe the block-axis layout bounds of each line box. Glyphs may overflow these layout bounds, especially when a small line height is used.LineMetrics::content_block_{min,max}_coordprovide the typographic content bounds, covering typographic ascent and descent as well as inline boxes, ignoring the specified line height. Note glyphs overflow these content bounds as well, for example when many combining marks are stacked. The union of the line-box and content bounds is close to the oldLineMetrics::block_{min,max}_coordfields. parley::editing::Cursor::{previous,next}_logical_wordnow land at the previous/next logical start of a word and skip over whitespace. (#215 by @tomcur)
- Fix compilation on 32-bit platforms without 64-bit atomics (e.g.
mipsel-unknown-linux-gnu). (#671 by @nicoburns) - Don't panic when fontconfig exposes no fonts. (#717 by @ogoffart)
0.11.0 - 2026-06-24
This release has an MSRV of 1.88.
- Line break opportunity override (#640 by @taj-p).
The builders now have a
set_line_break_overridemethod which can be used to customise where Parley detects line-breaking opportunities. It can be called withSome(parley::CHROMIUM_LINE_BREAK_OVERRIDE)to make line-breaking match Chromium, or with a custom instance ofAsciiLineBreakTablecreated withAsciiLineBreakTableBuilder. If you do not call the function then you will get the existing standard ICU-defined behavior. Fromconversions intoStylePropertyforFontWidth,FontStyle,FontWeight,WordBreak,OverflowWrap, andTextWrapMode, matching the existing conversions for font family, variations, features, and line height. (#643 by @waywardmonkeys)
- Upgrade to
read-fonts0.40,skrifa0.43,harfrust0.10 (#650 by @nicoburns)
- Fix font selection for emoji followed by a variation selector (#637 by @kane50613)
0.10.0 - 2026-06-01
This release has an MSRV of 1.88.
- Add
complex-scriptsCargo feature to enable dictionary-based line and word breaking for complex scripts (CJK, Thai, Khmer, Lao, Myanmar). When disabled, the lightweight segmenter is used (no change in default behavior) (#621 by @Linktime) PlainEditor,Layout,LayoutAccessibility, andGenerationnow implementDebug. (#615 by @NandishwarSingh) Note: TheLayoutimplementation provides a compact summary by default; the alternate form ({:#?}) formats the full underlying data.- Add
StyleSet::clearmethod (#614 by @lainon1) - Restore the ability to use a different alignment width than breaking width (#618 by @DJMcNab)
StyleRunBuildernow handles a first style run that references a non-zero style table index. (#626 by @waywardmonkeys)- Fix color emoji matching when emoji with non printing variation selector (#617 by @fundon)
- Upgrade to harfrust 0.8 (#632 by @nicoburns)
0.9.0 - 2026-04-21
This release has an MSRV of 1.88.
-
Floating boxes and other advanced layouts. (#421 by @nicoburns)
This comes with a few changes to the API. Additionally, it brings a number of additional advanced capabilities to users who are calling the
break_lines()function to use theBreakLinesstruct directly:- The
Layout::alignmethod no longer accepts awidthparameter. Text will now automatically be aligned relative to themax_advancepassed tobreak_all_lines(), unless that isInfinite(orf32::MAXwhich we treat as infinite) in which case it will be aligned relative to the width of the longest line in the layout. Additionally, if a line is given a (non-infinite) line-specificline_max_advanceusing the advancedBreakLinesAPI, then it will aligned relative to that width instead. - The
min_coordandmax_coordfields ofLineMetricswhich record the start and end position of the line in the block/y axis are renamed toblock_min_coordandinline_min_coord, and there are newinline_min_coordandinline_max_coordwhich record the start and end position of the line in the x/inline axis. - Inline boxes now have an additional
InlineBoxKindfield.InFlowbehaves like inline boxes in previous versions of Parley.OutOfFlowgets positioned like anInFlowbox, but does not take up space (likeposition:absolutein CSS), andCustomOutOfFlowcan be used in conjunction with the low-level.break_lines()API to implement floated boxes (like CSSfloat) which position depends on the state of line breaking. - Each line can have it's x/y/width/height set individually, and text will lay out into that box (the width for each line must be less than or equal to the width of the overall layout). This enables text to be laid out around "excluded regions", by setting a line box that avoids those regions. The logic for computing the positions of each line is left to the user.
- The
- Updated to
hashbrown0.17. (#506 by @waywardmonkeys) - Updated to
read-fonts0.39,skrifa0.42, andharfrust0.6. (#600 by @nicoburns)
- Going to the start of text when moving up on a single line. (#609 by @jordanhalase)
0.8.0 - 2026-03-27
This release has an MSRV of 1.88.
- CSS
text-indentsupport. (#551 by @devunt) break_line_with_nextmethod which implements a new line-breaking algorithm based on the number of characters rather than the width of the text. (#575 by @taj-p)Layout::linesnow returns an iterator that also implementsExactSizeIteratorandDoubleEndedIterator. (#554, #560 by @xStrom)BoundingBoxnow implementsDebug. (#486 by @taj-p)- Lower-level
StyleRunBuilderto go along with the existingRangedBuilderandTreeBuilder.StyleRunBuilderaccept non-overlapping ranges of styles. (#516 by @waywardmonkeys) - X-height, cap-height to RunMetrics. (#523 by @elbaro)
- All possible AccessKit text properties. (#563 by @mwcampbell)
- PlainEditor getters
scale,font_size, anddefault_style. (#571 by @zeophlite)
load_system_fontsandload_fonts_from_pathsmethods. (#540 by @nicoburns)- Method to convert non-shared
Collection/SourceCacheto shared variants. (#541 by @nicoburns)
- Max-content width being reset to 0 by mandatory line breaks. (#531 by @nicoburns)
- Cursor rectangle calculation for last line. (#547 by @areopagitics)
- Treat Line Separator and Paragraph Separator as mandatory break. (#549 by @xorgy)
- Justification space count for non-space line breaks. (#565 by @devunt)
- Font fallback by computing
map_leninfill_cluster_in_place. (#566 by @devunt)
- Clear fallback_families cache on attribute change. (#562 by @dqii)
- Fix font family name override being ignored during registration. (#564 by @devunt)
- Reset fallback cache when fallback families are modified. (#567 by @devunt)
- Panic on Windows 7. (#589 by @guiguiprim)
-
AccessKit has been updated to v0.24. (#532 by @nicoburns)
-
Fontations has updated: harfrust (0.5), skrifa (0.40), read-fonts (0.37). (#510 by @waywardmonkeys)
-
Parley now uses
icu4xrather thanswashfor text analysis. (#436 by @conor-93 and @taj-p) -
TextStylenow uses separate lifetimes for family vs settings. This lets callers keep a long-lived font-family value while borrowing per-run settings without forcing both to share a single lifetime. (#519 by @waywardmonkeys) -
Breaking change:
Glyph::yis now in Y-down coordinate space instead of Y-up coordinate space. (#528 by @valadaptive)This does not change the API surface, but will change the behavior of existing code! If you're iterating over non-positioned glyphs using the
GlyphRun::glyphsmethod and positioning each glyph yourself, with code like:let run_y = glyph_run.baseline(); for glyph in glyph_run.glyphs() { let glyph_y = run_y - glyph.y; ... }
You'll need to update your code to add
glyph.y, instead of subtracting it:let run_y = glyph_run.baseline(); for glyph in glyph_run.glyphs() { let glyph_y = run_y + glyph.y; ... }
If you instead use the
GlyphRun::positioned_glyphsmethod, your code will not need to change.
- The
windowscrate was updated to 0.62. (#518 by @nicoburns) - On macOS: Enumerate system fonts via CoreText. (#536 by @raiscui, #568 by @grebmeg)
- Fontique no longer has conversions between it's script type and that of
icu4xandunicode_properties. If you need these then you will now need to implement the conversions yourself (see linked PR for removed implementation). (#512 by @waywardmonkeys)
0.7.0 - 2025-11-24
This release has an MSRV of 1.83.
#448 by @taj-p) and (#449 by @nicoburns collectively fix a significant performance bug that occurred when laying out large paragraphs of text. Previously the time to perform layout was non-linear with respect to the input size and laying out paragraphs of text with more than ~1k characters was very slow.
The new TextWrapMode style implements the semantics of the text-wrap-mode
CSS property and allows text-wrapping to be disabled completely for a span of text.
Some modules have been moved:
parley::editorandparley::layout::editorare nowparley::editing.parley::layout::cursoris nowparley::cursor.
Fontique no longer sets the dlopen feature of yeslogic-fontconfig-sys by default. If you wish to run Fontique on a Linux system
without fontconfig installed then you will need to enable the new fontconfig-dlopen feature of the fontique crate.
If you wish to compile Fontique on a Linux system without the fontconfig-dlopen enabled then you will need the fontconfig dev
package (e.g. libfontconfig1-dev on Ubuntu) installed.
- Add
TextWrapModestyle. This allow line wrapping to be disabled completely for a span of text (excluding explicit line breaks). (#367 by @nicoburns) - Add
Cluster::from_point_exactmethod for hit-testing spans of text. This is useful for implementing "hover" or "click" functionality. (#447 by @nicoburns)
- Split off various modules into "editing" folder. (#440 by @PoignardAzur)
- Split contents of layout/mod.rs file. (#444 by @PoignardAzur)
- Running line height calculation. (#448 by @taj-p)
- Optimise line height computation. (#449 by @nicoburns)
- Add word and letter spacing to text layout based on style properties. (#468 by @dolsup)
- Hang trailing whitespace preceding explicit newline. (#276 by @wfdewith)
- Fix build on platforms without 64bit atomics. (#451 by @nicoburns)
0.6.0 - 2025-10-06
This release has an MSRV of 1.82.
Parley now uses HarfRust rather than Swash. This means that Parley now has production-quality shaping for all scripts and can be recommended for general usage.
As Parley now uses it's own parley::BoundingBox in place of kurbo::Rect, you may need to convert the type if you were
previously passing one of these values into a function that expects kurbo::Rect.
The following function may be used to perform this conversion:
fn bounding_box_to_rect(bb: parley::BoundingBox) -> kurbo::Rect {
kurbo::Rect::new(bb.x0, bb.y0, bb.x1, bb.y1)
}- Shift-click support through
Selection::shift_click_extensionandPlainEditorDriver::shift_click_extension. (#385 by @kekelp) - Add some benchmarks using Tango. (#405 by @taj-p)
- Cache character mapping metadata for each font to improve performance of font selection. (#413 by @dfrg)
- Upgrade
icu4xdependencies to v2.x. (#418 by @nicoburns) - Added an
unregister_fontmethod to remove a font from a collection. (#395 by @taj-p)
- Breaking change:
Alignmentvariants have been renamed to better match CSS.Alignment::Justifiedis nowAlignment::JustifyandAlignment::Middleis nowAlignment::Center. (#389 by @waywardmonkeys) - In the
PlainEditor, triple-click now selects paragraphs rather than words (#381 by @DJMcNab) - Updated to
accesskit0.21. (#390 by @mwcampbell) - Uses
HarfRustfor text shaping. (#400 by @taj-p) - Parley no longer depends on
penikoorkurbo. (#414 by @nicoburns):- Breaking change: The use of
peniko::Fonthas been replaced withlinebender_resource_handle::FontData, as suchparley::Fontis now calledParley::FontData. Note that this is the same type as in previous releases, and so is fully backwards-compatible, just with a different name. - Breaking change: The use of
kurbo::Recthas been replaced with a newparley::BoundingBoxtype.
- Breaking change: The use of
- The fontconfig backend, used to enumerate system fonts on Linux, has been rewritten to call into the system's fontconfig library instead of parsing fontconfig's configuration files itself. This should significantly improve the behavior of system fonts and generic families on Linux. (#378 by @valadaptive)
- Fontique no longer depends on
peniko. The use ofpeniko::Blobhas been replaced withlinebender_resource_handle::Blob. This is unlikely to affect users of the crate. (#414 by @nicoburns)
- Selection extension moves the focus to the side being extended. (#385 by @kekelp)
- Ranged builder default style not respecting
scale. (#368 by @xStrom) - Cluster source character not correct. (#402 by @taj-p)
- Don't justify the last line of a paragraph. (#410 by @taj-p)
- Font family name aliases (secondary names for font families, often in another language) not being registered. (#380 by @valadaptive)
0.5.0 - 2025-06-01
This release has an MSRV of 1.82.
- Editor features required by Android IME. (#334 by @mwcampbell)
- Breaking change:
Layout::min_content_width,Layout::max_content_width, andLayout::content_widthshave been replaced withLayout::calculate_content_widths, which does not internally cache the widths. This means thatLayoutis nowSyncagain, but callers will have to cache the min and max content widths themselves. (#353 by @valadaptive) - Breaking change: the line height style property (
StyleProperty::LineHeightand theline_heightfield onTextStyle) is now aLineHeightenum that allows you to specify absolute, font-size-relative, and font-metrics-relative line heights. Previously, it was always font-size-relative. (#362 by @valadaptive)- The default line height was previously
LineHeight::FontSizeRelative(1.0)if you usedRangedStyleBuilder, orLineHeight::FontSizeRelative(1.2)if you usedTreeStyleBuilder. It is nowLineHeight::MetricsRelative(1.0)in both cases. This will affect layout if you don't specify your own line height.
- The default line height was previously
- Breaking change:
{RangedBuilder, TreeBuilder}::{build_into, build}methods now consumeself. (#369 by @dhardy)
0.4.0 - 2025-05-08
This release has an MSRV of 1.82.
Quantization of vertical layout metrics is now optional.
For an easy upgrade we recommend enabling it by setting quantize to true when calling LayoutContext::ranged_builder or LayoutContext::tree_builder.
- Option to skip quantization of vertical layout metrics for advanced rendering use cases. (#297 by @valadaptive, #344 by @xStrom)
- The
WordBreakandOverflowWrapstyle properties for controlling line wrapping. (#315 by @valadaptive) PlainEditormethodsraw_selectionandraw_text. (#316, #317 by @mwcampbell)PlainEditor::selection_geometry_with, the equivalent ofSelection::geometry_withmethod. (#318 by @valadaptive)BreakLines::is_donemethod to check if all the text has been placed into lines. (#319 by @valadaptive)
- Breaking change:
Selection::geometry,Selection::geometry_with, andPlainEditor::selection_geometrynow include the line indices that the selection rectangles belong to. (#318 by @valadaptive) - Updated to
accesskit0.19. (#294 by @waywardmonkeys, #348 by @xStrom) - Now displaying selected newlines as whitespace in the selection highlight. (#296 by @valadaptive)
- Made
BreakReasonpublic. (#300 by @valadaptive)
- Breaking change:
Collection::register_fontsnow takes aBlob<u8>instead of aVec<u8>. (#306 by @valadaptive) - Breaking change:
Collection::register_fontsnow takes an optional second parameter which allows overriding the metadata used for matching the font. (#312 by @valadaptive)
- Text editing for layouts which contain inline boxes. (#299 by @valadaptive)
- Cursor navigation in RTL text sometimes getting stuck within a line. (#331 by @valadaptive)
- Using
Layout::alignon an aligned layout without breaking lines again. (#342 by @xStrom) - Selection box height going below ascent + descent with small line heights. (#344 by @xStrom)
- Rounding error accumulation of vertical layout metrics. (#344 by @xStrom)
0.3.0 - 2025-02-27
This release has an MSRV of 1.82.
GenerationonPlainEditorto help implement lazy drawing. (#143 by @xorgy)- Support for preedit for input methods in
PlainEditor. (#192 by @DJMcNab, #198 by @tomcur) PlainEditormethod to get a cursor area for use by the platform's input method. (#224 by @tomcur)Layoutmethods to calculate minimum and maximum content widths. (#259 by @wfdewith)PlainEditornow implementsClone. (#133 by @nicoburns)- Navigation and byte selection operations for
PlainEditor. (#146 by @xorgy) - AccessKit integration. (#166 by @mwcampbell)
first_stylemethod toCluster. (#264 by @nicoburns)
FontStretch,FontStyle, andFontWeightget helper functionsfrom_fontconfig. (#212 by @waywardmonkeys)- Impl
bytemucktraits forGenericFamily. (#213 by @waywardmonkeys)
- Breaking change: The cursor API has been completely reworked. (#170 by @dfrg)
- Breaking change:
PlainEditors API is now method-based rather than enum based. (#154 by @mwcampbell) - Breaking change:
PlainEditor's semantics are no longer transactional. (#192 by @DJMcNab) - Breaking change:
Alignment::StartandAlignment::Endnow depend on text base direction.Alignment::LeftandAlignment::Rightare introduced for text direction-independent alignment. (#250 by @tomcur) - Breaking change:
Layoutis no longerSync. (#259 by @wfdewith) - Breaking change:
PlainEditor's width is nowOption<f32>rather thanf32. (#137 by @nicoburns) - Breaking change: Make alignment when free space is negative configurable. (#241 by @nicoburns)
- Allow Bidi
base_levelto be determined from text. (#245 by @tomcur)
- Breaking change:
Stretch,Style, andWeightrenamed toFontWidth,FontStyle,FontWeight. (#211, #223 by @waywardmonkeys) - Depend on
read-fontsinstead ofskrifa. (#162 by @nicoburns)
- Alignment of right-to-left text. (#250, #268 by @tomcur)
- Performing line breaking or aligning a layout again, after justified alignment had been applied previously. (#271 by @tomcur)
- Placement of inline boxes. (#163 by @spirali)
- Cursor position for lines that are not left-aligned. (#169 by @mwcampbell)
Cursor::from_pointnot using the line's offset. (#176 by @DJMcNab)- Off-by-one error in
PlainEditor::cursor_at. (#187 by @tomcur) - Binary search in
Layout::line_for_offset. (#188 by @tomcur) - Whitespace collapsing at the start of inline spans. (#191 by @nicoburns)
- Collapsing selection. (#201 by @tomcur)
- Affinities not being ignored in
Selection::is_collapsed. (#202 by @tomcur) - Misc. inline box layout issues. (#207 by @nicoburns)
- Linebreaking for lines without text runs. (#249 by @wfdewith)
- Calculating trailing whitespace for all lines. (#256 by @wfdewith)
- Strip whitespace following a newline when whitespace collapsing is enabled. (#254 by @nicoburns)
- Account for inline boxes when collapsing whitespace after newlines. (#280 by @nicoburns)
- Skip adding font family as fallback if it has zero coverage for given script. (#182 by @richardhozak)
0.2.0 - 2024-10-10
This release has an MSRV of 1.75.
- Example using
tiny-skiawhich renders into a PNG. (#55 by @nicoburns)- Breaking change: There is now a blanket implementation for
Brush.
- Breaking change: There is now a blanket implementation for
- A Swash example which renders into a PNG. (#54 by @nicoburns)
- An example with Vello on Winit which shows a basic text editor .(#106 by @dfrg)
PlainEditor, a basic action-based text editor based on ParleySelectionandCursor. (#126 by @xorgy)- Tree style builder. (#76 by @nicoburns)
- Conversions for
FontFamily,FontStack, andStylePropertyto make styling more ergonomic. (#129 by @xorgy)
- Repository layout updated to match Linebender standard. (#59 by @waywardmonkeys)
- Emoji clusters now get an Emoji family added by default. (#56 by @dfrg)
- Style builders now accept
Into<StyleProperty<'a, B: Brush>>so you can push aGenericFamilyorFontStackdirectly. (#129 by @xorgy)
- Removed unsafe code from fontconfig cache. (#78 by @waywardmonkeys)
- Switched to
windows-rsfordwritebackend. (#85 by @dfrg)
- Search correct paths for fonts on Apple platforms. (#71 by @waywardmonkeys)
- Breaking change: removed conversion to/from
icu_properties::Scriptforfontique::Script. (#72 by @waywardmonkeys)- This can be restored by using the
icu_propertiesfeature offontique.
- This can be restored by using the
0.1.0 - 2024-05-01
This release has an MSRV of 1.70.
- Initial release