From 2ba7b2c3daafbfda05d4f25aba03eb6422d3b1d7 Mon Sep 17 00:00:00 2001 From: Adrian Heine <mail@adrianheine.de> Date: Mon, 22 May 2017 11:45:07 +0200 Subject: [PATCH] Faster coordsChar for bidi content This closes #4691 and is based on an idea by Joel <joel.einbinder@gmail.com>. --- src/measurement/position_measurement.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/measurement/position_measurement.js b/src/measurement/position_measurement.js index 5fb6a653..b4bcfda5 100644 --- a/src/measurement/position_measurement.js +++ b/src/measurement/position_measurement.js @@ -456,20 +456,30 @@ function coordsCharInner(cm, lineObj, lineNo, x, y) { if (cm.options.lineWrapping) { ;({begin, end} = wrappedLineExtent(cm, lineObj, preparedMeasure, y)) } - pos = new Pos(lineNo, begin) + pos = new Pos(lineNo, Math.floor(begin + (end - begin) / 2)) let beginLeft = cursorCoords(cm, pos, "line", lineObj, preparedMeasure).left let dir = beginLeft < x ? 1 : -1 let prevDiff, diff = beginLeft - x, prevPos - do { + let steps = Math.ceil((end - begin) / 4) + outer: do { prevDiff = diff prevPos = pos - pos = moveVisually(cm, lineObj, pos, dir) - if (pos == null || pos.ch < begin || end <= (pos.sticky == "before" ? pos.ch - 1 : pos.ch)) { - pos = prevPos - break + let i = 0 + for (; i < steps; ++i) { + let prevPos = pos + pos = moveVisually(cm, lineObj, pos, dir) + if (pos == null || pos.ch < begin || end <= (pos.sticky == "before" ? pos.ch - 1 : pos.ch)) { + pos = prevPos + break outer + } } diff = cursorCoords(cm, pos, "line", lineObj, preparedMeasure).left - x - } while ((dir < 0) != (diff < 0) && (Math.abs(diff) <= Math.abs(prevDiff))) + if (steps > 1) { + let diff_change_per_step = Math.abs(diff - prevDiff) / steps + steps = Math.min(steps, Math.ceil(Math.abs(diff) / diff_change_per_step)) + dir = diff < 0 ? 1 : -1 + } + } while (steps > 1 || ((dir < 0) != (diff < 0) && (Math.abs(diff) <= Math.abs(prevDiff)))) if (Math.abs(diff) > Math.abs(prevDiff)) { if ((diff < 0) == (prevDiff < 0)) throw new Error("Broke out of infinite loop in coordsCharInner") pos = prevPos -- GitLab