Commit graph

152 commits

Author SHA1 Message Date
Hojjat
af2d269636 fix: import ceil for no_std 2026-02-24 19:34:51 -07:00
Hojjat
78665aab3b perf: minimize the performance impact of text decoration
Boxed the decoration data to go from 40b to 8b.
The performance is almost unchanged for text without decoration.
2026-02-24 19:34:51 -07:00
Hojjat
c12b3a9bf2 improv: extract decoration metrics from the font 2026-02-24 19:34:51 -07:00
Hojjat
2758919c80 feat: add TextDecoration rendering 2026-02-24 19:34:51 -07:00
Hojjat
a8873a0536 improv: show ellipsis if nothing else fits
If buffer is small enough that char+ellipsis doesn't fit, then show
ellipsis alone. If buffer is smaller than ellipsis, show nothing.
2026-02-20 15:37:30 -07:00
Hojjat
d304a49536 fix: width 0.0 is valid,return ellipsized if there's non-zero content 2026-02-20 15:37:30 -07:00
Hojjat
a24c55a483 chore: remove unenecessary log and code
After previous fix, there is not need to check to see if ellipsize
middle actually happened. If we reach here, it happened.
2026-02-20 14:23:48 -07:00
Nick
9c2c84432d
Remove completely unnecessary boxing/dyn of ranges introduced in last change. (#473)
Update shape.rs
2026-02-20 13:40:22 -07:00
Hojjat Abdollahi
29ac278e76
fix: off by one in fit_glyphs (#474) 2026-02-20 13:27:42 -07:00
Hojjat Abdollahi
e83bd7f7bf
Merge pull request #471 from hojjatabdollahi/hojjat/fix-bidi-zw
Fix aggressive ellipsizing
2026-02-20 12:14:00 -07:00
Jeremy Soller
5528523182 Fix compilation for no_std 2026-02-19 09:15:06 -07:00
Hojjat Abdollahi
4819bc30fa
Ellipsize (#467)
* feat: add Ellipsize enum

* chore: API changes needed for ellipsize

Decided not to change "layout()" function for now to avoid breaking the
interface. For now.

* chore: shape ellipsis

* feat: Ellipsize::Start

Since it can only have 1 line, it's easier to implement.

* DROPME: temporarily change rich-text for testing

* test(ellipsize): Testing Ellipsize::Start

Long text in small buffer should produce ellipsis glyphs

* fix: do not need font_system anymore

We moved ellipsis shaping elsewhere so no need to pass font_system to
layout function (which also was recreating a new one in the tests every
time making them take forever).

* feat: Ellipsize::End

* improv(ellipsize): use a single ellipsis shape

* improv: Ellipsie::End && Wrap::None

There is no need to layout the whole line if it's not going to fit.

* fix: mixed bidi text when Ellipsize::End && Wrap::None

* chore: clean up and simplify when line.RTL==span.RTL

* fix(ellipsize): last word is not (word_count -1) if iter().rev()

* refactor(layout): extract the layout algorithm to make it more readable

* improv(ellipsize): Ellipsize::Start && Wrap::None

we iterate in reverse and only layout what's going to be visible

* Revert: delete the previous approach of post processing ellipsis

* doc: explain the interaction between Ellipsize and Wrap

* chore: lower the scope

* feat: Ellipsize the last line of a paragraph

For now only the number of lines is supported

* fix: clear ellipsized field on visual lines

This was causing ellipsis to show on random lines

* chore: remove old tests

will add better tests soon

* chore: clean up changes from previous attempt

* fix: consider the ellipsis width when doing alignment

* feat(ellipsize): add `Height` limit to `Ellipsize`

* fix: ellipsize the start of the last line correctly

* fix: ellipsize at the start of mixed bidi lines

* feat: Ellipsize::Middle

* fix: consider ellipsize::middle when calculating alignment correction

* refactor: improve readability

* refactor: deduplicate "fit_glyphs"

* refactor: combine backward and forward layout into one (wip)

* fix: Backward works in the unified layout_spans

* chore: clean up

* fix: Ellipsize::Middle

* fix: handle large words in bidi boundaries

* chore: clean up and some refactoring

* fix: ellipsis is now the same level as the surrounding text

* fix: try to fit more when ellipsizing::middle

* improv: ellipsis now have the same level as the neighbors

This makes ellipsized RTL text inside a LTR line more readable.

before:

Hello سلام...خوبی؟
Hello خولی؟...سلام

* fix: some extra words were being rendered in Ellipsize::Middle

This was causing the last word (if it's not the same level as the rest)
to be rendered outside the buffer.

* test: a few test cases for ellipsize

* fix: assign the correct byte range to ellipsis

this should fix the panic when selecting or clicking on or near the
ellipsis in the editor.
2026-02-19 09:11:22 -07:00
Adam Kowalski
d907e41bf3 fix: resolve no_std build issues in ligature handling 2026-01-29 09:04:48 -07:00
Adam Kowalski
723841f934 fix: improved dynamic ligature probing to handle contextual alternates 2026-01-29 09:04:48 -07:00
Adam Kowalski
c6ce5e69e5 fix: use dynamic font probing to preserve ligatures across break opportunities 2026-01-29 09:04:48 -07:00
Adam Kowalski
5d1db4992a chore: extend fix to != and ++ ligatures, match existing test style 2026-01-29 09:04:48 -07:00
Adam Kowalski
d391a3a166 chore: add unit test and improve comment 2026-01-29 09:04:48 -07:00
Adam Kowalski
8c8c41b05b fix: prevent line break splitting |> ligature sequence
The unicode-linebreak crate treats the pipe character '|' as a break opportunity (BA/AL class). This causes ShapeSpan::build to split text like '|>' into separate ShapeWords. When these words are shaped independently, the font shaping engine cannot form ligatures that cross the word boundary.

This patch manually checks for the '|>' sequence during segmentation and skips the break opportunity, ensuring they remain in the same shaping run.

Added a unit test 'ligature_segmentation' to verify that '|>' remains a single word.
2026-01-29 09:04:48 -07:00
Todd York
2729d2d49c Refactor override_fake_italic() 2026-01-16 10:43:22 -07:00
Todd York
a288f1d775 Shape as fake italic if no matching italic font exists 2026-01-16 10:43:22 -07:00
ickshonpe
8cd21a315a The ASCII fast path assumes that the current word has only one attributes span, when it can intersect multiple attribute spans.
This commit adds a check to ensure that all the attribute spans intersecting the word range are compatible before taking the fast path.
Fixes #445
2025-12-22 06:53:47 -07:00
Héctor Ramón Jiménez
d779057d9c Replace magic boolean with new Hinting enum 2025-12-01 13:59:55 -07:00
Héctor Ramón Jiménez
48eda6bd7d Draft metrics hinting support 2025-12-01 13:59:55 -07:00
Jeremy Soller
8a7bc790e5
Round x_advance to nearest monospace width when requested, fixes #237 2025-11-03 15:09:58 -07:00
valadaptive
2610c869f6
Replace rustybuzz with HarfRust (#417)
* Use HarfRust for shaping

* Replace ttf-parser with skrifa entirely

* Fix clippy lints

* Add shape plan cache

* Bump harfrust and skrifa

* Fix no_std build

* Simplify the shape plan cache

* Please the paperclip

* Cache font ID with plan

* Tune shape plan cache for "BiDi Processing" bench
2025-09-08 21:15:27 -06:00
romanstingler
a2f1f4b2a0
refactor: address clippy warnings and improve code quality (#409)
- Fix string formatting with modern interpolation syntax
- Improve Debug implementation with finish_non_exhaustive()
- Fix function placement in shape.rs to avoid items_after_statements warning
- Use more idiomatic Rust patterns (map_or_else, next_back)
- Clean up conditional imports in vi.rs
- Convert multiple methods to `const` functions for optimization and consistency
- Introduce `core_maths` for enhanced no-std compatibility
- Update `Cargo.toml` for the new optional dependency and feature adjustments
2025-08-11 13:58:59 -06:00
romanstingler
de355a1fd9
feat: add ASCII fast path optimization to ShapeWord::build() (#407)
- Skip expensive grapheme iteration for simple ASCII words
- 32% performance improvement for code-like text
- 5-7% improvement for general ASCII content
- No regressions for Unicode text processing
- Conservative ASCII detection maintains correctness
2025-08-04 13:49:52 -06:00
Wren [Undefined]
a03faa654d
Variable font support (#400)
* Variable font support

Here's a pretty naïve solution for variable fonts.

The iterator doesn't use the match keys' weight, but instead tries to
get the requested ideal weight, if the font is variable, otherwise it is
ignored and the actual (non-variable) weight is used. This is because I
didn't implement finding variable weight support for match keys; doing
so would be impossible without parsing TTF files when matching and I
didn't want to add that potentially expensive infrastructure if not
entirely necessary.

This is a breaking change, and I'm open for ideas on how to fix that
if it's an issue.

* cargo fmt

* Add variable font example to rich-text example
2025-07-07 08:50:40 -06:00
Jeremy Soller
bcfb05a390
Revert "Round glyph advance to integer sizes (#384)"
This reverts commit 987ff45ff2.
2025-06-22 13:05:00 -06:00
Taj Pereira
c597f3755b
Update peniko version to 0.4.0 (#387)
* Update peniko version

* Fix no_std build
2025-05-30 04:50:41 +08:00
mahkoh
987ff45ff2
Round glyph advance to integer sizes (#384)
This is in line with [1].

[1]: https://skia.googlesource.com/skia/+/refs/heads/chrome/m136/src/ports/SkTypeface_fontations.cpp#539
2025-05-14 15:00:30 -06:00
Stewart Connor
e828131c92 fix for test.sh 2025-03-31 17:03:51 +11:00
Stewart Connor
53763c157b Merge branch 'refs/heads/main' into stewart-add-kerning-ligatures
# Conflicts:
#	src/attrs.rs
2025-03-31 13:42:12 +11:00
Stewart Connor
08822cac2e add letter spacing 2025-03-28 15:55:47 +00:00
Stewart Connor
71b0680e6f revert the references 2025-03-26 17:06:24 +11:00
Stewart Connor
fb852d3ab5 changes before ref 2025-03-26 14:48:54 +11:00
Stewart Connor
1d7850099f pre-removing copy 2025-03-26 14:31:37 +11:00
Stewart Connor
f5879b3425 add contextual alternatives 2025-03-21 18:24:32 +11:00
Stewart Connor
50373cd6d7 formatting 2025-03-21 18:03:15 +11:00
Stewart Connor
2d67e31bf1 format 2025-03-21 17:56:14 +11:00
Stewart Connor
81ca98d5db more explicit about setting features 2025-03-21 17:12:38 +11:00
Stewart Connor
d071d1a1c3 add kerning ligatures 2025-03-19 17:45:30 +11:00
valadaptive
c7a426280b Use chr_idx for ShapeGlyph range in basic shaping
We want byte indices, not code point indices. Fixes a panic when
selecting the mixed-language text at the bottom of the rich-text example
when the shaping mode is set to "Basic".
2025-03-10 11:23:36 -06:00
valadaptive
db9033ba86 Fix glyph start+end indices in "Basic" shaping
These indices were previously relative to the start of the *run*, when
they should be relative to the start of the *line*.
2025-03-10 11:23:36 -06:00
dsgallups
485497973f chore: updating newfound lints 2025-01-22 17:00:01 -07:00
dsgallups
f05a69a9d9 resolve all lints, update MSRV 2025-01-22 17:00:01 -07:00
Jeremy Soller
1f4065c1c3
Drop ShapePlanCache
The ShapePlanCache was added to improve performance when shaping the same
strings over and over. However, it never had the ability to be trimmed
and when it was moved to FontSystem, this created a permanently growing
allocation. It is recommended to instead use the shape-run-cache feature
which supports trimming if it is desired to have higher performance for
repeated shaping, at the cost of manually specifying when to trim.
2024-11-06 18:59:56 -07:00
dekrain
4fe90bb612 Fix the character index used for getting a glyph attribute in basic shaping 2024-09-23 07:53:29 -06:00
koe
9dc024616b move ShapeBuffer to FontSystem 2024-09-03 15:59:15 -06:00
koe
c65f299e87 fix no_std 2024-09-01 15:00:17 -06:00