From 0cf093422878653e174d57c0c02ffe4880c6be7a Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Tue, 21 Feb 2017 22:30:05 +0100 Subject: Bug [#1910]. GTK a11y: Speed up converting byte offsets to character offsets Use a per-line cache to avoid re-computing the offset from the start of the buffer each time. This dramatically speeds up multiple replacements on large files. --- gtk/ScintillaGTKAccessible.cxx | 7 +++++++ gtk/ScintillaGTKAccessible.h | 16 +++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/gtk/ScintillaGTKAccessible.cxx b/gtk/ScintillaGTKAccessible.cxx index 948b19575..11966bf20 100644 --- a/gtk/ScintillaGTKAccessible.cxx +++ b/gtk/ScintillaGTKAccessible.cxx @@ -856,6 +856,13 @@ void ScintillaGTKAccessible::NotifyReadOnly() { void ScintillaGTKAccessible::Notify(GtkWidget *, gint, SCNotification *nt) { switch (nt->nmhdr.code) { case SCN_MODIFIED: { + if (nt->modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) { + // invalidate character offset cache if applicable + const Position line = sci->pdoc->LineFromPosition(nt->position); + if (character_offsets.size() > static_cast(line + 1)) { + character_offsets.resize(line + 1); + } + } if (nt->modificationType & SC_MOD_INSERTTEXT) { int startChar = CharacterOffsetFromByteOffset(nt->position); int lengthChar = sci->pdoc->CountCharacters(nt->position, nt->position + nt->length); diff --git a/gtk/ScintillaGTKAccessible.h b/gtk/ScintillaGTKAccessible.h index fa9698417..88256e0ca 100644 --- a/gtk/ScintillaGTKAccessible.h +++ b/gtk/ScintillaGTKAccessible.h @@ -20,6 +20,9 @@ private: GtkAccessible *accessible; ScintillaGTK *sci; + // cache holding character offset for each line start, see CharacterOffsetFromByteOffset() + std::vector character_offsets; + // cached length of the deletion, in characters (see Notify()) int deletionLengthChar; // local state for comparing @@ -52,7 +55,18 @@ private: } int CharacterOffsetFromByteOffset(Position byteOffset) { - return sci->pdoc->CountCharacters(0, byteOffset); + const Position line = sci->pdoc->LineFromPosition(byteOffset); + if (character_offsets.size() <= static_cast(line)) { + if (character_offsets.empty()) + character_offsets.push_back(0); + for (Position i = character_offsets.size(); i <= line; i++) { + const Position start = sci->pdoc->LineStart(i - 1); + const Position end = sci->pdoc->LineStart(i); + character_offsets.push_back(character_offsets[i - 1] + sci->pdoc->CountCharacters(start, end)); + } + } + const Position lineStart = sci->pdoc->LineStart(line); + return character_offsets[line] + sci->pdoc->CountCharacters(lineStart, byteOffset); } void CharacterRangeFromByteRange(Position startByte, Position endByte, int *startChar, int *endChar) { -- cgit v1.2.3 From bc31bdeb3b5437171af42ef2921f9bb7080b3b64 Mon Sep 17 00:00:00 2001 From: Neil Hodgson Date: Fri, 3 Mar 2017 16:40:44 +1100 Subject: Change log. --- doc/ScintillaHistory.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index c63563c7f..ab03e7f3e 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -545,6 +545,11 @@ Bug #1915.
  • + Improved speed of accessibility code on GTK+ by using additional memory + as a cache. + Bug #1910. +
  • +
  • Fix crash in accessibility code on GTK+ < 3.3.6 caused by previous bug fix. Bug #1907.
  • -- cgit v1.2.3