Skip to content

Commit

Permalink
Help IE cache layout information in measureLineInner
Browse files Browse the repository at this point in the history
Issue #990
  • Loading branch information
marijnh committed Nov 26, 2012
1 parent 77a5e68 commit 16e1955
Showing 1 changed file with 31 additions and 5 deletions.
36 changes: 31 additions & 5 deletions lib/codemirror.js
Expand Up @@ -864,12 +864,38 @@ window.CodeMirror = (function() {
function measureLineInner(cm, line) {
var display = cm.display, measure = emptyArray(line.text.length);
var pre = lineContent(cm, line, measure);

// IE does not cache element positions of inline elements between
// calls to getBoundingClientRect. This makes the loop below,
// which gathers the positions of all the characters on the line,
// do an amount of layout work quadratic to the number of
// characters. When line wrapping is off, we try to improve things
// by first subdividing the line into a bunch of inline blocks, so
// that IE can reuse most of the layout information from caches
// for those blocks. This does interfere with line wrapping, so it
// doesn't work when wrapping is on, but in that case the
// situation is slightly better, since IE does cache line-wrapping
// information and only recomputes per-line.
if (ie && !cm.options.lineWrapping && pre.childNodes.length > 100) {
var fragment = document.createDocumentFragment();
var chunk = 10, n = pre.childNodes.length;
for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
var wrap = elt("div", null, null, "display: inline-block");
for (var j = 0; j < chunk && n; ++j) {
wrap.appendChild(pre.firstChild);
--n;
}
fragment.appendChild(wrap);
}
pre.appendChild(fragment);
}

removeChildrenAndAdd(display.measure, pre);

var outer = display.lineDiv.getBoundingClientRect();
var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;
for (var i = 0, elt; i < measure.length; ++i) if (elt = measure[i]) {
var size = measure[i].getBoundingClientRect();
for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
var size = cur.getBoundingClientRect();
var top = Math.max(0, size.top - outer.top), bot = Math.min(size.bottom - outer.top, maxBot);
for (var j = 0; j < vranges.length; j += 2) {
var rtop = vranges[j], rbot = vranges[j+1];
Expand All @@ -885,9 +911,9 @@ window.CodeMirror = (function() {
if (j == vranges.length) vranges.push(top, bot);
data[i] = {left: size.left - outer.left, right: size.right - outer.left, top: j};
}
for (var i = 0, elt; i < data.length; ++i) if (elt = data[i]) {
var vr = elt.top;
elt.top = vranges[vr]; elt.bottom = vranges[vr+1];
for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
var vr = cur.top;
cur.top = vranges[vr]; cur.bottom = vranges[vr+1];
}
return data;
}
Expand Down

0 comments on commit 16e1955

Please sign in to comment.