Skip to content

Initial support for using range.getClientRects to measure text. - #5922

Merged
nightwing merged 28 commits into
masterfrom
varchar3
Jul 27, 2026
Merged

Initial support for using range.getClientRects to measure text.#5922
nightwing merged 28 commits into
masterfrom
varchar3

Conversation

Comment thread src/layer/font_metrics.js Outdated
Comment thread src/layer/font_metrics.js Outdated
Comment thread src/virtual_renderer.js
Comment thread src/layer/font_metrics.js Outdated
Comment thread src/layer/font_metrics.js Outdated
Comment thread src/layer/font_metrics.js Outdated
Comment thread src/layer/font_metrics.js
Comment thread src/layer/font_metrics.js Outdated
Comment thread src/layer/font_metrics.js Outdated
Comment thread src/layer/font_metrics.js Outdated
Comment thread src/layer/font_metrics.js Outdated

@xyos xyos left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@github-actions

github-actions Bot commented May 2, 2026

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@codecov

codecov Bot commented May 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.21687% with 48 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.95%. Comparing base (f82010e) to head (bd38fd5).
⚠️ Report is 3 commits behind head on master.

Files with missing lines Patch % Lines
src/layer/font_metrics.js 93.62% 34 Missing ⚠️
src/virtual_renderer.js 89.01% 10 Missing ⚠️
src/ext/diff/inline_diff_view.js 77.77% 2 Missing ⚠️
src/ace_test.js 96.29% 1 Missing ⚠️
src/layer/marker.js 93.75% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5922      +/-   ##
==========================================
+ Coverage   93.73%   93.95%   +0.21%     
==========================================
  Files         641      647       +6     
  Lines      138167   140305    +2138     
  Branches    14561    14706     +145     
==========================================
+ Hits       129510   131820    +2310     
+ Misses       8657     8485     -172     
Flag Coverage Δ
unittests 93.95% <94.21%> (+0.21%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented May 2, 2026

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

github-actions Bot commented May 3, 2026

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

1 similar comment
@github-actions

github-actions Bot commented May 4, 2026

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

github-actions Bot commented May 5, 2026

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@xyos xyos left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, this is awesome!

I built #5988 on an earlier snapshot of this branch, so below are a few things I hit while testing grapheme/bidi edge cases against real browser measurements. Most are small and cherry-pickable from #5988. Details inline.

Once this merges I'd like us to review and maybe do a follow-up PR picking up the rest of #5988: the grapheme-cluster model (Intl.Segmenter-based helpers in lib/lang, cluster-snapping moveCursorTo, cluster-aware $getDisplayTokens/$computeWrapSplits, $alignTokensToClusters). It touches the same code this PR rewrites, so rebasing it on top of merged master is cleaner than growing this PR's scope. With the current branch a wrap limit crossing 👨‍👩‍👧‍👦 still splits its 11 code units across screen rows, and moveCursorTo only snaps surrogate pairs, not ZWJ/combining-mark clusters; the follow-up addresses #460, #4142, #5431, #4602, #3753, #3866, #3617.

Comment thread src/layer/text.js Outdated
Comment thread src/layer/font_metrics.js Outdated
Comment thread src/layer/font_metrics.js
maxDistance = d;
}
}
if (blockCursor) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (blockCursor) { // TODO } is a no-op, so vim block-cursor mode gets round-to-nearest instead of floor semantics. Either implement or drop the branch and note the limitation.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment thread src/layer/cursor.js

var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) *
this.config.lineHeight;
var cursorWidth = this.config.fontMetrics.textWidth(pos.row, pos.column + 1) - textWidth;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If textWidth(col+1) and textWidth(col) measure equal (zero-width cluster tail, or a measurement fallback), cursorWidth is 0 and the cursor becomes invisible. Suggest (... - textWidth) || this.config.characterWidth.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, done

Comment thread src/bidihandler.js
this.updateBidiMap();
}
return this.bidiMap.bidiLevels;
return true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isBidiRow now returns true for every row once the document contains any bidi character. One Hebrew word in a 10k-line file routes every marker on every line through drawBidiSingleLineMarkergetRects → DOM range measurement. A cheap per-line bidiRE.test(line) here would keep the fast path for the 99% of lines that aren't bidi.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that when calling isBidiRow we only have screenLine, so finding the line is quite expensive. drawBidiSingleLineMarker on the other hand is not very slow, so we end up with similar performance in both cases.

Comment thread src/selection.js
if (useFontMetrics && this.$desiredColumn == null) {
offsetX = fontMetrics.textWidth(screenPos.row, screenPos.column);
if (isFinite(offsetX))
this.$desiredColumn = offsetX / fontMetrics.config.characterWidth;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$desiredColumn now stores a fractional pixel-derived value (offsetX / characterWidth). When the target row isn't rendered, $pixelToColumn returns it unchanged and a non-integer column flows into screenToDocumentPosition. It works in the cases I tested, but rounding the fallback would keep the column contract integer-valued.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should allow fractional screenColumn for reasons similar to screenRow, also because fractional screenColumns were allowed in the old implementation of varchar https://github.com/ajaxorg/ace/blob/master/src/edit_session.js#L2507C19-L2507C34

}

var rowCount = 10;
var rowCount = 5.5;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rowCount = 5.5 looks like a leftover from testing fractional row heights; intentional?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fractional row heights were intentional, without that all linewidgets are forced to have heights in multtiples of line height, and our api doesn't enforce that.

Comment thread src/layer/font_metrics.js Outdated
}

/**
* Calculates the width of the text up to a specific scrrenColumn on a given screen row.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: typo, scrrenColumn (also ends up in the generated types/ace-modules.d.ts)

Comment thread src/virtual_renderer_test.js Outdated
var m0 = 0.7, m1 = 0.1, m2 = 0.3, m3 = 0.82;
var t1 = 100, t2 = 20;
function testTransform() {
fontMetrics.config.$transformData = null; //FIXME

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove this comment

Comment thread types/ace-modules.d.ts
* @related EditSession.documentToScreenPosition
**/
screenToDocumentPosition(screenRow: number, screenColumn: number, offsetX?: number): Point;
screenToDocumentPosition(screenRow: number, screenColumn: number): Point;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a public API break: screenToDocumentPosition loses its documented offsetX param, and BidiHandler loses getPosLeft/getSelections/offsetToCol/updateCharacterWidths. Embedders calling these will break at runtime, not just in types. Probably fine given the old bidi pixel model is gone, but worth a changelog note and a decision on whether this ships as a minor or major bump.

@github-actions

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@github-actions

Copy link
Copy Markdown

One of the public type files has been updated, plase make sure there are no backwards incompatible changes done in the PR.

@nightwing
nightwing merged commit 054a3d6 into master Jul 27, 2026
8 checks passed
@nightwing
nightwing deleted the varchar3 branch July 27, 2026 11:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants