[geany/geany] a58738: scintilla: Accessible: use the built-in character position cache

Colomban Wendling git-noreply at xxxxx
Wed Apr 17 21:12:35 UTC 2019


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Wed, 17 Apr 2019 21:12:35 UTC
Commit:      a587385de0b004399090480b852a907ced46f66f
             https://github.com/geany/geany/commit/a587385de0b004399090480b852a907ced46f66f

Log Message:
-----------
scintilla: Accessible: use the built-in character position cache

It's quite a lot faster even after trying and optimizing the custom
version, and it makes the code simpler.

Also improve ByteOffsetFromCharacterOffset() to make use of the cache,
making it drastically faster.

X-Scintilla-Bug-URL: https://sourceforge.net/p/scintilla/bugs/2094/
X-Scintilla-Commit-ID: 01aab5f24e50ed14551c8c9c8ecce7ece0594c09
X-Scintilla-Commit-ID: 2c8b52af4ae5de2abe7c00fd18e78be60340cbf9

Fixes #2092.


Modified Paths:
--------------
    scintilla/gtk/ScintillaGTK.cxx
    scintilla/gtk/ScintillaGTKAccessible.cxx
    scintilla/gtk/ScintillaGTKAccessible.h

Modified: scintilla/gtk/ScintillaGTK.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -859,7 +859,7 @@ sptr_t ScintillaGTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam
 			if (accessible) {
 				ScintillaGTKAccessible *sciAccessible = ScintillaGTKAccessible::FromAccessible(accessible);
 				if (sciAccessible) {
-					sciAccessible->SetAccessibility();
+					sciAccessible->SetAccessibility(accessibilityEnabled);
 				}
 			}
 			break;


Modified: scintilla/gtk/ScintillaGTKAccessible.cxx
16 lines changed, 6 insertions(+), 10 deletions(-)
===================================================================
@@ -158,6 +158,7 @@ ScintillaGTKAccessible::ScintillaGTKAccessible(GtkAccessible *accessible_, GtkWi
 		sci(ScintillaGTK::FromWidget(widget_)),
 		deletionLengthChar(0),
 		old_pos(-1) {
+	SetAccessibility(true);
 	g_signal_connect(widget_, "sci-notify", G_CALLBACK(SciNotify), this);
 }
 
@@ -861,24 +862,19 @@ void ScintillaGTKAccessible::NotifyReadOnly() {
 #endif
 }
 
-void ScintillaGTKAccessible::SetAccessibility() {
+void ScintillaGTKAccessible::SetAccessibility(bool enabled) {
 	// Called by ScintillaGTK when application has enabled or disabled accessibility
-	character_offsets.resize(0);
-	character_offsets.push_back(0);
+	if (enabled)
+		sci->pdoc->AllocateLineCharacterIndex(SC_LINECHARACTERINDEX_UTF32);
+	else
+		sci->pdoc->ReleaseLineCharacterIndex(SC_LINECHARACTERINDEX_UTF32);
 }
 
 void ScintillaGTKAccessible::Notify(GtkWidget *, gint, SCNotification *nt) {
 	if (!Enabled())
 		return;
 	switch (nt->nmhdr.code) {
 		case SCN_MODIFIED: {
-			if (nt->modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) {
-				// invalidate character offset cache if applicable
-				const Sci::Line line = sci->pdoc->LineFromPosition(nt->position);
-				if (character_offsets.size() > static_cast<size_t>(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);


Modified: scintilla/gtk/ScintillaGTKAccessible.h
32 lines changed, 18 insertions(+), 14 deletions(-)
===================================================================
@@ -18,9 +18,6 @@ class ScintillaGTKAccessible {
 	GtkAccessible *accessible;
 	ScintillaGTK *sci;
 
-	// cache holding character offset for each line start, see CharacterOffsetFromByteOffset()
-	std::vector<Sci::Position> character_offsets;
-
 	// cached length of the deletion, in characters (see Notify())
 	int deletionLengthChar;
 	// local state for comparing
@@ -37,6 +34,19 @@ class ScintillaGTKAccessible {
 	}
 
 	Sci::Position ByteOffsetFromCharacterOffset(Sci::Position startByte, int characterOffset) {
+		if (!(sci->pdoc->LineCharacterIndex() & SC_LINECHARACTERINDEX_UTF32)) {
+			return startByte + characterOffset;
+		}
+		if (characterOffset > 0) {
+			// Try and reduce the range by reverse-looking into the character offset cache
+			Sci::Line lineStart = sci->pdoc->LineFromPosition(startByte);
+			Sci::Position posStart = sci->pdoc->IndexLineStart(lineStart, SC_LINECHARACTERINDEX_UTF32);
+			Sci::Line line = sci->pdoc->LineFromPositionIndex(posStart + characterOffset, SC_LINECHARACTERINDEX_UTF32);
+			if (line != lineStart) {
+				startByte += sci->pdoc->LineStart(line) - sci->pdoc->LineStart(lineStart);
+				characterOffset -= sci->pdoc->IndexLineStart(line, SC_LINECHARACTERINDEX_UTF32) - posStart;
+			}
+		}
 		Sci::Position pos = sci->pdoc->GetRelativePosition(startByte, characterOffset);
 		if (pos == INVALID_POSITION) {
 			// clamp invalid positions inside the document
@@ -54,18 +64,12 @@ class ScintillaGTKAccessible {
 	}
 
 	Sci::Position CharacterOffsetFromByteOffset(Sci::Position byteOffset) {
-		const Sci::Line line = sci->pdoc->LineFromPosition(byteOffset);
-		if (character_offsets.size() <= static_cast<size_t>(line)) {
-			if (character_offsets.empty())
-				character_offsets.push_back(0);
-			for (Sci::Position i = character_offsets.size(); i <= line; i++) {
-				const Sci::Position start = sci->pdoc->LineStart(i - 1);
-				const Sci::Position end = sci->pdoc->LineStart(i);
-				character_offsets.push_back(character_offsets[i - 1] + sci->pdoc->CountCharacters(start, end));
-			}
+		if (!(sci->pdoc->LineCharacterIndex() & SC_LINECHARACTERINDEX_UTF32)) {
+			return byteOffset;
 		}
+		const Sci::Line line = sci->pdoc->LineFromPosition(byteOffset);
 		const Sci::Position lineStart = sci->pdoc->LineStart(line);
-		return character_offsets[line] + sci->pdoc->CountCharacters(lineStart, byteOffset);
+		return sci->pdoc->IndexLineStart(line, SC_LINECHARACTERINDEX_UTF32) + sci->pdoc->CountCharacters(lineStart, byteOffset);
 	}
 
 	void CharacterRangeFromByteRange(Sci::Position startByte, Sci::Position endByte, int *startChar, int *endChar) {
@@ -135,7 +139,7 @@ class ScintillaGTKAccessible {
 	// So ScintillaGTK can notify us
 	void ChangeDocument(Document *oldDoc, Document *newDoc);
 	void NotifyReadOnly();
-	void SetAccessibility();
+	void SetAccessibility(bool enabled);
 
 	// Helper GtkWidget methods
 	static AtkObject *WidgetGetAccessibleImpl(GtkWidget *widget, AtkObject **cache, gpointer widget_parent_class);



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list