Commit graph

786 commits

Author SHA1 Message Date
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
Jeremy Soller
4fd11f0e5e 0.17.2 2026-02-18 15:41:27 -07:00
Jeremy Soller
82fadd954c Make Motion::Home and Motion::End operate on unwrapped lines, fixes #468 2026-02-18 15:39:41 -07:00
Jeremy Soller
d7dc22dd20
Fix 0.17.1 date in changelog 2026-01-30 15:58:56 -07:00
Jeremy Soller
ae8f1c0737
0.17.1
- Set correct rust-version to 1.89
- Update all dependencies to latest versions
2026-01-30 15:57:17 -07:00
Jeremy Soller
bdd6657fd7
0.17.0 2026-01-29 09:48:18 -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
ee702e5090 Reorder fields in FontMatchKey to fix fallback logic; Add comments 2026-01-20 08:40:39 -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
Todd York
e9075aeae8 Allow fallback to fonts with mismatched stretch or style 2026-01-16 10:43:22 -07:00
Todd York
cfb7224370 Fix variable font weight for SwashCache::get_outline_commands() 2026-01-16 10:24:38 -07:00
Jeremy Soller
0d9af4f7de
0.16.0 2025-12-29 14:19:32 -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
Benjamin Stigsen
7051682e70 Update Harfrust 2025-12-09 07:59:44 -07:00
Jeremy Soller
eebdd01a8e
Update harfrust and skrifa 2025-12-08 12:30:13 -07:00
Héctor Ramón Jiménez
a07a619054 Add set_hinting method to Buffer 2025-12-01 13:59:55 -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
9339446cfa
Add Renderer trait for more flexible rendering of buffers and editors 2025-11-06 11:23:11 -07:00
Jeremy Soller
8a7bc790e5
Round x_advance to nearest monospace width when requested, fixes #237 2025-11-03 15:09:58 -07:00
Jeremy Soller
40fee41332
Fix bench compilation 2025-11-01 08:32:01 -06:00
Jeremy Soller
c82ee1c5b5
0.15.0 2025-10-30 08:40:58 -06:00
Jeremy Soller
cffdea2b33
Fix delete ranges removing interior newlines 2025-10-16 13:54:20 -06:00
Jeremy Soller
d409ddd1d3
Improve handling of non-existant files in load_text 2025-10-14 09:55:48 -06:00
Jeremy Soller
646e04389e
Clippy lint 2025-10-09 12:26:48 -06:00
Jeremy Soller
5cc64c77c1
Better handling of newlines in editor insert and delete 2025-10-09 12:21:38 -06:00
Jeremy Soller
c5deb38cfe
If buffer is empty, do not set line ending 2025-10-09 11:02:00 -06:00
mikenu
6514323fbe Update README.md 2025-10-04 13:23:50 -06:00
mikenu-jp
73a0beedbf Fix: Add missing Urdu UDHR link with stable URL based on new OHCHR site structure (#350) 2025-10-04 13:23:50 -06:00
Nico Burns
1140ce89b0 Upgrade skrifa to 0.37, harfrust to 0.3.1
Signed-off-by: Nico Burns <nico@nicoburns.com>
2025-10-02 07:48:04 -06:00
Nico Burns
e04bfd098f
Use linebender_resource_handle instead of peniko (#424)
Signed-off-by: Nico Burns <nico@nicoburns.com>
2025-09-21 06:45:37 -06:00
valadaptive
355b7febb1
Update and fix cargo-deny (#421)
* Update and fix cargo-deny

* We are not free of syn

* More cargo-deny fixes
2025-09-09 07:51:08 -06: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
Erik McClure
3c1f6c9e8a
Add alignment parameter to set_text (#419)
* add alignment parameter to set_text

* Fix doc comment
2025-09-07 12:40:42 -06:00
shadow3
750e1a4dd1
feat(editor): Implement pixel-based scrolling for the Editor (#418)
Refactors the Editor's scrolling implementation to be pixel-based instead of line-based. This provides smoother and more granular scrolling, which works more consistently across different input devices (like trackpads).

- The `Action::Scroll` variant now takes `pixels: f32`.
- The `Editor` now processes scroll actions using pixel values directly.
- Examples have been updated to reflect the new scrolling behavior.
2025-09-07 12:39:38 -06:00
romanstingler
f7033bb043
Add explicit lifetimes to borrowed return types (#411) 2025-08-11 14:17:00 -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
e80dbc3607
Optimize BidiParagraphs with ASCII fast path (#408)
* Optimize BidiParagraphs with ASCII fast path - Added fast path for ASCII text that avoids BidiInfo allocation - Added some text shaping benchmarks

* refactor: fix clippy warnings and cleanup imports
2025-08-11 13:15:09 -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
Vancha
7646989d6f
Fixed Tab indenting the line instead of adding Tab or spaces (#403)
* Update editor.rs

* Makes sure indent_required is calculated according to the selection type

removed the redundant check for required_indent == 0,
introduced a slightly different path for when no selection = None, and calculated the required tab width and indent position accordingly.

* Undo typo

undid an accidental move of a redraw call outside of a loop

* Corrected indenting with rustfmt

formatted the code with rustfmt to pass the failing CI checks
2025-07-16 14:39:48 -06:00
callym
85b07b4c8c
Add pixel font flag (#402) 2025-07-08 08:58:24 -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
d15011fba5
Format code 2025-07-02 11:02:56 -06:00
Jeremy Soller
9c16ca004a
Fix doc comment on DISABLE_HINTING 2025-07-02 10:59:24 -06:00