(cm, line)
| 1049 | } |
| 1050 | |
| 1051 | function measureLineInner(cm, line) { |
| 1052 | if (!cm.options.lineWrapping && line.text.length >= cm.options.crudeMeasuringFrom) |
| 1053 | return crudelyMeasureLine(cm, line); |
| 1054 | |
| 1055 | var display = cm.display, measure = emptyArray(line.text.length); |
| 1056 | var pre = buildLineContent(cm, line, measure, true).pre; |
| 1057 | |
| 1058 | // IE does not cache element positions of inline elements between |
| 1059 | // calls to getBoundingClientRect. This makes the loop below, |
| 1060 | // which gathers the positions of all the characters on the line, |
| 1061 | // do an amount of layout work quadratic to the number of |
| 1062 | // characters. When line wrapping is off, we try to improve things |
| 1063 | // by first subdividing the line into a bunch of inline blocks, so |
| 1064 | // that IE can reuse most of the layout information from caches |
| 1065 | // for those blocks. This does interfere with line wrapping, so it |
| 1066 | // doesn't work when wrapping is on, but in that case the |
| 1067 | // situation is slightly better, since IE does cache line-wrapping |
| 1068 | // information and only recomputes per-line. |
| 1069 | if (old_ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) { |
| 1070 | var fragment = document.createDocumentFragment(); |
| 1071 | var chunk = 10, n = pre.childNodes.length; |
| 1072 | for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) { |
| 1073 | var wrap = elt("div", null, null, "display: inline-block"); |
| 1074 | for (var j = 0; j < chunk && n; ++j) { |
| 1075 | wrap.appendChild(pre.firstChild); |
| 1076 | --n; |
| 1077 | } |
| 1078 | fragment.appendChild(wrap); |
| 1079 | } |
| 1080 | pre.appendChild(fragment); |
| 1081 | } |
| 1082 | |
| 1083 | removeChildrenAndAdd(display.measure, pre); |
| 1084 | |
| 1085 | var outer = getRect(display.lineDiv); |
| 1086 | var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight; |
| 1087 | // Work around an IE7/8 bug where it will sometimes have randomly |
| 1088 | // replaced our pre with a clone at this point. |
| 1089 | if (ie_lt9 && display.measure.first != pre) |
| 1090 | removeChildrenAndAdd(display.measure, pre); |
| 1091 | |
| 1092 | function measureRect(rect) { |
| 1093 | var top = rect.top - outer.top, bot = rect.bottom - outer.top; |
| 1094 | if (bot > maxBot) bot = maxBot; |
| 1095 | if (top < 0) top = 0; |
| 1096 | for (var i = vranges.length - 2; i >= 0; i -= 2) { |
| 1097 | var rtop = vranges[i], rbot = vranges[i+1]; |
| 1098 | if (rtop > bot || rbot < top) continue; |
| 1099 | if (rtop <= top && rbot >= bot || |
| 1100 | top <= rtop && bot >= rbot || |
| 1101 | Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) { |
| 1102 | vranges[i] = Math.min(top, rtop); |
| 1103 | vranges[i+1] = Math.max(bot, rbot); |
| 1104 | break; |
| 1105 | } |
| 1106 | } |
| 1107 | if (i < 0) { i = vranges.length; vranges.push(top, bot); } |
| 1108 | return {left: rect.left - outer.left, |
no test coverage detected