perf(input-field): O(n) cursor hit test via Font::NearestCursorByte (#56) #90
No reviewers
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Catcrafts/Crafter.Graphics!90
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "claude/issue-56"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
InputField_HitTestCursormapped a click x-coord to a cursor byte offset by callingFont::GetLineWidthon every prefixvalue[0..i]fori = 1..size. Each call re-walks from byte 0 — O(n²) glyph-metric lookups (each an uncachedstbtt_GetCodepointHMetricscmap binary search). It also iterated raw byte boundaries, so on multibyte UTF-8 input it could return an offset that splits a codepoint, an invalid position for the byte-basedcursorPos.Fix
Font::NearestCursorByte(text, size, target): a single left-to-right cumulative-advance pass (O(n) metrics, scale computed once) over codepoint boundaries, returning the byte offset of the boundary whose cumulative advance is nearesttarget. Cumulative advance is monotonic (advances are non-negative), so the scan stops at the first boundary past the closest one — and offsets always land on codepoint boundaries, the valid cursor positions.InputField_HitTestCursornow delegates to it.Tests
New
tests/InputFieldHitTest— pure CPU over a TrueType file, no Vulkan device or window:GetLineWidth, no early break — so it also catches any over-eager break);value.size(), and glyph-edge resolution.crafter-build test→ 8 passed (including the new test).Resolves #56
🤖 Generated with Claude Code