Skip to content

Commit

Permalink
Merge pull request #5052 from ajaxorg/fix-line-height-regression
Browse files Browse the repository at this point in the history
Fix line height regression
  • Loading branch information
nightwing authored Feb 7, 2023
2 parents 00f6089 + 75f5294 commit 4a6ae77
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 92 deletions.
8 changes: 4 additions & 4 deletions src/autocomplete_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ module.exports = {
editor.renderer.$themeId = "./theme/textmate";

editor.execCommand("insertstring", "a");
checkInnerHTML('<d "ace_line ace_selected" role="option" id="suggest-aria-id:0" aria-label="arraysort"><s "ace_completion-highlight">a</s><s "ace_">rraysort</s><s "ace_completion-meta">local</s></d><d "ace_line" role="option"><s "ace_completion-highlight">a</s><s "ace_">looooooooooooooooooooooooooooong_word</s><s "ace_completion-meta">local</s></d>', function() {
checkInnerHTML('<d "ace_line ace_selected" id="suggest-aria-id:0" aria-label="arraysort"><s "ace_completion-highlight">a</s><s "ace_">rraysort</s><s "ace_completion-meta">local</s></d><d "ace_line"><s "ace_completion-highlight">a</s><s "ace_">looooooooooooooooooooooooooooong_word</s><s "ace_completion-meta">local</s></d>', function() {
editor.execCommand("insertstring", "rr");
checkInnerHTML('<d "ace_line ace_selected" role="option" id="suggest-aria-id:0" aria-label="arraysort"><s "ace_completion-highlight">arr</s><s "ace_">aysort</s><s "ace_completion-meta">local</s></d>', function() {
checkInnerHTML('<d "ace_line ace_selected" id="suggest-aria-id:0" aria-label="arraysort"><s "ace_completion-highlight">arr</s><s "ace_">aysort</s><s "ace_completion-meta">local</s></d>', function() {
editor.execCommand("insertstring", "r");
checkInnerHTML('<d "ace_line ace_selected" role="option" id="suggest-aria-id:0" aria-label="arraysort"><s "ace_completion-highlight">arr</s><s "ace_">ayso</s><s "ace_completion-highlight">r</s><s "ace_">t</s><s "ace_completion-meta">local</s></d>', function() {
checkInnerHTML('<d "ace_line ace_selected" id="suggest-aria-id:0" aria-label="arraysort"><s "ace_completion-highlight">arr</s><s "ace_">ayso</s><s "ace_completion-highlight">r</s><s "ace_">t</s><s "ace_completion-meta">local</s></d>', function() {

editor.onCommandKey(null, 0, 13);
assert.equal(editor.getValue(), "arraysort\narraysort alooooooooooooooooooooooooooooong_word");
editor.execCommand("insertstring", " looooooooooooooooooooooooooooong_");
checkInnerHTML('<d "ace_line ace_selected" role="option" id="suggest-aria-id:0" aria-label="alooooooooooooooooooooooooooooong_word"><s "ace_">a</s><s "ace_completion-highlight">looooooooooooooooooooooooooooong_</s><s "ace_">word</s><s "ace_completion-meta">local</s></d>', function() {
checkInnerHTML('<d "ace_line ace_selected" id="suggest-aria-id:0" aria-label="alooooooooooooooooooooooooooooong_word"><s "ace_">a</s><s "ace_completion-highlight">looooooooooooooooooooooooooooong_</s><s "ace_">word</s><s "ace_completion-meta">local</s></d>', function() {
editor.onCommandKey(null, 0, 13);
editor.destroy();
editor.container.remove();
Expand Down
12 changes: 6 additions & 6 deletions src/ext/static_highlight_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ module.exports = {
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell'></span><span class='ace_comment ace_doc'>*</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell'></span><span class='ace_comment ace_doc'>*/</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell'></span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell'></span><span class='ace_storage ace_type'>function</span><span> </span><span class='ace_entity ace_name ace_function'>hello</span><span> </span><span class='ace_paren ace_lparen'>(</span><span class='ace_variable ace_parameter'>a</span><span class='ace_punctuation ace_operator'>,</span><span> </span><span class='ace_variable ace_parameter'>b</span><span class='ace_punctuation ace_operator'>,</span><span> </span><span class='ace_variable ace_parameter'>c</span><span class='ace_paren ace_rparen'>)</span><span> </span><span class='ace_paren ace_lparen'>{</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell'></span><span> </span><span class='ace_storage ace_type'>console</span><span class='ace_punctuation ace_operator'>.</span><span class='ace_support ace_function ace_firebug'>log</span><span class='ace_paren ace_lparen'>(</span><span class='ace_identifier'>a</span><span> </span><span class='ace_keyword ace_operator'>*</span><span> </span><span class='ace_identifier'>b</span><span> </span><span class='ace_keyword ace_operator'>+</span><span> </span><span class='ace_identifier'>c</span><span> </span><span class='ace_keyword ace_operator'>+</span><span> </span><span class='ace_string'>&#39;sup$&#39;</span><span class='ace_paren ace_rparen'>)</span><span class='ace_punctuation ace_operator'>;</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell'></span><span class='ace_indent-guide'> </span><span class='ace_indent-guide'> </span><span> </span><span class='ace_comment'>//</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell'></span><span class='ace_indent-guide'> </span><span class='ace_indent-guide'> </span><span> </span><span class='ace_comment'>//</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell'></span><span class='ace_storage ace_type'>function</span> <span class='ace_entity ace_name ace_function'>hello</span> <span class='ace_paren ace_lparen'>(</span><span class='ace_variable ace_parameter'>a</span><span class='ace_punctuation ace_operator'>,</span> <span class='ace_variable ace_parameter'>b</span><span class='ace_punctuation ace_operator'>,</span> <span class='ace_variable ace_parameter'>c</span><span class='ace_paren ace_rparen'>)</span> <span class='ace_paren ace_lparen'>{</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell'></span> <span class='ace_storage ace_type'>console</span><span class='ace_punctuation ace_operator'>.</span><span class='ace_support ace_function ace_firebug'>log</span><span class='ace_paren ace_lparen'>(</span><span class='ace_identifier'>a</span> <span class='ace_keyword ace_operator'>*</span> <span class='ace_identifier'>b</span> <span class='ace_keyword ace_operator'>+</span> <span class='ace_identifier'>c</span> <span class='ace_keyword ace_operator'>+</span> <span class='ace_string'>&#39;sup$&#39;</span><span class='ace_paren ace_rparen'>)</span><span class='ace_punctuation ace_operator'>;</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell'></span><span class='ace_indent-guide'> </span><span class='ace_indent-guide'> </span> <span class='ace_comment'>//</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell'></span><span class='ace_indent-guide'> </span><span class='ace_indent-guide'> </span> <span class='ace_comment'>//</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell'></span><span class='ace_paren ace_rparen'>}</span>\n</div>"
+ "</div></div>");
assert.ok(!!result.css);
Expand Down Expand Up @@ -97,7 +97,7 @@ module.exports = {
var mode = new TextMode();

var result = highlighter.render(snippet, mode, theme);
assert.ok(result.html.indexOf("</span><span>$&#39;$1$2$$$&#38;</span>\n</div>") != -1);
assert.ok(result.html.indexOf("</span>$&#39;$1$2$$$&#38;\n</div>") != -1);

next();
},
Expand All @@ -108,7 +108,7 @@ module.exports = {
var mode = new TextMode();

var result = highlighter.render(snippet, mode, theme);
assert.ok(result.html.indexOf("</span><span>&#38;&#60;>&#39;&#34;</span>\n</div>") != -1);
assert.ok(result.html.indexOf("</span>&#38;&#60;>&#39;&#34;\n</div>") != -1);

var mode = new JavaScriptMode();
var result = highlighter.render("/*" + snippet, mode, theme);
Expand Down
66 changes: 29 additions & 37 deletions src/layer/font_metrics.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,30 @@ var event = require("../lib/event");
var useragent = require("../lib/useragent");
var EventEmitter = require("../lib/event_emitter").EventEmitter;

var DEFAULT_CHAR_COUNT = 250;
var CHAR_COUNT = 512;
var USE_OBSERVER = typeof ResizeObserver == "function";
var L = 200;

var FontMetrics = exports.FontMetrics = function(parentEl, charCount) {
this.charCount = charCount || DEFAULT_CHAR_COUNT;

var FontMetrics = exports.FontMetrics = function(parentEl) {
this.el = dom.createElement("div");
this.$setMeasureNodeStyles(this.el.style, true);

this.$main = dom.createElement("div");
this.$setMeasureNodeStyles(this.$main.style);

this.$measureNode = dom.createElement("div");
this.$setMeasureNodeStyles(this.$measureNode.style);



this.el.appendChild(this.$main);
this.el.appendChild(this.$measureNode);
parentEl.appendChild(this.el);

this.$measureNode.textContent = lang.stringRepeat("X", this.charCount);

this.$measureNode.textContent = lang.stringRepeat("X", CHAR_COUNT);
this.$characterSize = {width: 0, height: 0};



if (USE_OBSERVER)
this.$addObserver();
else
Expand All @@ -38,9 +38,9 @@ var FontMetrics = exports.FontMetrics = function(parentEl, charCount) {
(function() {

oop.implement(this, EventEmitter);

this.$characterSize = {width: 0, height: 0};

this.$setMeasureNodeStyles = function(style, isRoot) {
style.width = style.height = "auto";
style.left = style.top = "0px";
Expand Down Expand Up @@ -69,7 +69,7 @@ var FontMetrics = exports.FontMetrics = function(parentEl, charCount) {
this._emit("changeCharacterSize", {data: size});
}
};

this.$addObserver = function() {
var self = this;
this.$observer = new window.ResizeObserver(function(e) {
Expand All @@ -83,13 +83,13 @@ var FontMetrics = exports.FontMetrics = function(parentEl, charCount) {
if (this.$pollSizeChangesTimer || this.$observer)
return this.$pollSizeChangesTimer;
var self = this;

return this.$pollSizeChangesTimer = event.onIdle(function cb() {
self.checkForSizeChanges();
event.onIdle(cb, 500);
}, 500);
};

this.setPolling = function(val) {
if (val) {
this.$pollSizeChanges();
Expand All @@ -100,32 +100,24 @@ var FontMetrics = exports.FontMetrics = function(parentEl, charCount) {
};

this.$measureSizes = function(node) {
node = node || this.$measureNode;

// Avoid `Element.clientWidth` since it is rounded to an integer (see
// https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth).
// Using it here can result in a noticeable cursor offset for long lines.
const rect = node.getBoundingClientRect();
const charSize = {
height: rect.height,
width: rect.width / this.charCount
var size = {
height: (node || this.$measureNode).clientHeight,
width: (node || this.$measureNode).clientWidth / CHAR_COUNT
};

// Size and width can be null if the editor is not visible or
// detached from the document
if (charSize.width === 0 || charSize.height === 0)
if (size.width === 0 || size.height === 0)
return null;
return charSize;
return size;
};

this.$measureCharWidth = function(ch) {
this.$main.textContent = lang.stringRepeat(ch, this.charCount);
// Avoid `Element.clientWidth` since it is rounded to an integer (see
// https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth).
this.$main.textContent = lang.stringRepeat(ch, CHAR_COUNT);
var rect = this.$main.getBoundingClientRect();
return rect.width / this.charCount;
return rect.width / CHAR_COUNT;
};

this.getCharacterWidth = function(ch) {
var w = this.charSizes[ch];
if (w === undefined) {
Expand All @@ -142,7 +134,7 @@ var FontMetrics = exports.FontMetrics = function(parentEl, charCount) {
this.el.parentNode.removeChild(this.el);
};


this.$getZoom = function getZoom(element) {
if (!element || !element.parentElement) return 1;
return (window.getComputedStyle(element).zoom || 1) * getZoom(element.parentElement);
Expand Down Expand Up @@ -179,7 +171,7 @@ var FontMetrics = exports.FontMetrics = function(parentEl, charCount) {

if (!this.els)
this.$initTransformMeasureNodes();

function p(el) {
var r = el.getBoundingClientRect();
return [r.left, r.top];
Expand All @@ -194,7 +186,7 @@ var FontMetrics = exports.FontMetrics = function(parentEl, charCount) {

var m1 = mul(1 + h[0], sub(b, a));
var m2 = mul(1 + h[1], sub(c, a));

if (elPos) {
var x = elPos;
var k = h[0] * x[0] / L + h[1] * x[1] / L + 1;
Expand All @@ -205,5 +197,5 @@ var FontMetrics = exports.FontMetrics = function(parentEl, charCount) {
var f = solve(sub(m1, mul(h[0], u)), sub(m2, mul(h[1], u)), u);
return mul(L, f);
};

}).call(FontMetrics.prototype);
50 changes: 15 additions & 35 deletions src/layer/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ var Text = function(parentEl) {
this.SPACE_CHAR = "\xB7";
this.$padding = 0;
this.MAX_LINE_LENGTH = 10000;
// Smaller chunks result in higher cursor precision at the cost of more DOM nodes
this.MAX_CHUNK_LENGTH = 250;

this.$updateEolChar = function() {
var doc = this.session.doc;
Expand Down Expand Up @@ -293,7 +291,6 @@ var Text = function(parentEl) {
lineEl.className = "ace_line_group";
} else {
lineEl.className = "ace_line";
lineEl.setAttribute("role", "option");
}
fragment.push(line);

Expand Down Expand Up @@ -323,19 +320,6 @@ var Text = function(parentEl) {
"lparen": true
};

this.$renderTokenInChunks = function(parent, screenColumn, token, value) {
var newScreenColumn;
for (var i = 0; i < value.length; i += this.MAX_CHUNK_LENGTH) {
var valueChunk = value.substring(i, i + this.MAX_CHUNK_LENGTH);
var tokenChunk = {
type: token.type,
value: valueChunk
};
newScreenColumn = this.$renderToken(parent, screenColumn + i, tokenChunk, valueChunk);
}
return newScreenColumn;
};

this.$renderToken = function(parent, screenColumn, token, value) {
var self = this;
var re = /(\t)|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\uFEFF\uFFF9-\uFFFC\u2066\u2067\u2068\u202A\u202B\u202D\u202E\u202C\u2069]+)|(\u3000)|([\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3001-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]|[\uD800-\uDBFF][\uDC00-\uDFFF])/g;
Expand Down Expand Up @@ -401,16 +385,20 @@ var Text = function(parentEl) {

valueFragment.appendChild(this.dom.createTextNode(i ? value.slice(i) : value, this.element));

var span = this.dom.createElement("span");
if (!this.$textToken[token.type]) {
var classes = "ace_" + token.type.replace(/\./g, " ace_");
var span = this.dom.createElement("span");
if (token.type == "fold")
span.style.width = (token.value.length * this.config.characterWidth) + "px";

span.className = classes;
span.appendChild(valueFragment);

parent.appendChild(span);
}
else {
parent.appendChild(valueFragment);
}
span.appendChild(valueFragment);
parent.appendChild(span);

return screenColumn + value.length;
};
Expand Down Expand Up @@ -577,11 +565,11 @@ var Text = function(parentEl) {
}

if (chars + value.length < splitChars) {
screenColumn = this.$renderTokenInChunks(lineEl, screenColumn, token, value);
screenColumn = this.$renderToken(lineEl, screenColumn, token, value);
chars += value.length;
} else {
while (chars + value.length >= splitChars) {
screenColumn = this.$renderTokenInChunks(
screenColumn = this.$renderToken(
lineEl, screenColumn,
token, value.substring(0, splitChars - chars)
);
Expand All @@ -599,7 +587,7 @@ var Text = function(parentEl) {
}
if (value.length != 0) {
chars += value.length;
screenColumn = this.$renderTokenInChunks(
screenColumn = this.$renderToken(
lineEl, screenColumn, token, value
);
}
Expand All @@ -621,23 +609,15 @@ var Text = function(parentEl) {
if (!value)
continue;
}
if (screenColumn + value.length > this.MAX_LINE_LENGTH) {
this.$renderOverflowMessage(parent, screenColumn, token, value);
return;
}
screenColumn = this.$renderTokenInChunks(parent, screenColumn, token, value);
if (screenColumn + value.length > this.MAX_LINE_LENGTH)
return this.$renderOverflowMessage(parent, screenColumn, token, value);
screenColumn = this.$renderToken(parent, screenColumn, token, value);
}
};

this.$renderOverflowMessage = function(parent, screenColumn, token, value, hide) {
if (token) {
this.$renderTokenInChunks(
parent,
screenColumn,
token,
value.slice(0, this.MAX_LINE_LENGTH - screenColumn)
);
}
token && this.$renderToken(parent, screenColumn, token,
value.slice(0, this.MAX_LINE_LENGTH - screenColumn));

var overflowEl = this.dom.createElement("span");
overflowEl.className = "ace_inline_button ace_keyword ace_toggle_wrap";
Expand Down
Loading

0 comments on commit 4a6ae77

Please sign in to comment.