diff options
author | Neil <nyamatongwe@gmail.com> | 2013-08-07 15:52:25 +1000 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2013-08-07 15:52:25 +1000 |
commit | 85441d442a67ecae557e7ec74409d0dc1e3c1cac (patch) | |
tree | e603496a70f0391882ca1d29f7e0fc47b6636f94 /src/PositionCache.cxx | |
parent | 445144addd4854d8f99d9c87a9c4955556faaa19 (diff) | |
download | scintilla-mirror-85441d442a67ecae557e7ec74409d0dc1e3c1cac.tar.gz |
Optimize performance with many control characters such as when opening
a binary file.
Simplify use of BreakFinder and use for layout as well as drawing.
Diffstat (limited to 'src/PositionCache.cxx')
-rw-r--r-- | src/PositionCache.cxx | 116 |
1 files changed, 50 insertions, 66 deletions
diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx index 009ed7cfa..d833ac982 100644 --- a/src/PositionCache.cxx +++ b/src/PositionCache.cxx @@ -13,6 +13,7 @@ #include <string> #include <vector> #include <map> +#include <algorithm> #include "Platform.h" @@ -343,7 +344,7 @@ static inline int KeyFromString(const char *charBytes, size_t len) { int k=0; for (size_t i=0; i<len && charBytes[i]; i++) { k = k * 0x100; - k += charBytes[i]; + k += static_cast<unsigned char>(charBytes[i]); } return k; } @@ -394,33 +395,15 @@ void SpecialRepresentations::Clear() { } void BreakFinder::Insert(int val) { - if (val >= nextBreak) { - for (std::vector<int>::iterator it = selAndEdge.begin(); it != selAndEdge.end(); ++it) { - if (val == *it) { - return; - } - if (val <*it) { - selAndEdge.insert(it, 1, val); - return; - } + if (val > nextBreak) { + const std::vector<int>::iterator it = std::lower_bound(selAndEdge.begin(), selAndEdge.end(), val); + if (it == selAndEdge.end()) { + selAndEdge.push_back(val); + } else if (*it != val) { + selAndEdge.insert(it, 1, val); } - // Not less than any so append - selAndEdge.push_back(val); - } -} - -/* -extern bool BadUTF(const char *s, int len, int &trailBytes); - -static int NextBadU(const char *s, int p, int len, int &trailBytes) { - while (p < len) { - p++; - if (BadUTF(s + p, len - p, trailBytes)) - return p; } - return -1; } -*/ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, int xStart, bool breakForSelection, Document *pdoc_, SpecialRepresentations *preprs_) : @@ -433,11 +416,13 @@ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posL saeNext(0), subBreak(-1), pdoc(pdoc_), + encodingFamily(pdoc_->CodePageFamily()), preprs(preprs_) { // Search for first visible break // First find the first visible character - nextBreak = ll->FindBefore(xStart, lineStart, lineEnd); + if (xStart > 0.0f) + nextBreak = ll->FindBefore(xStart, lineStart, lineEnd); // Now back to a style break while ((nextBreak > lineStart) && (ll->styles[nextBreak] == ll->styles[nextBreak - 1])) { nextBreak--; @@ -451,81 +436,80 @@ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posL SelectionSegment portion = ll->psel->Range(r).Intersect(segmentLine); if (!(portion.start == portion.end)) { if (portion.start.IsValid()) - Insert(portion.start.Position() - posLineStart - 1); + Insert(portion.start.Position() - posLineStart); if (portion.end.IsValid()) - Insert(portion.end.Position() - posLineStart - 1); + Insert(portion.end.Position() - posLineStart); } } } - Insert(ll->edgeColumn - 1); - Insert(lineEnd - 1); - - if (pdoc && preprs) { - EncodingFamily encodingFamily = pdoc->CodePageFamily(); - for (int posRepr=0; posRepr<lineEnd;) { - int charWidth = 1; - if (encodingFamily == efUnicode) - charWidth = UTF8DrawBytes(reinterpret_cast<unsigned char *>(ll->chars) + posRepr, lineEnd - posRepr); - else if (encodingFamily == efDBCS) - charWidth = pdoc->IsDBCSLeadByte(ll->chars[posRepr]) ? 2 : 1; - if (preprs->Contains(ll->chars + posRepr, charWidth)) { - Insert(posRepr - 1); - Insert(posRepr + charWidth - 1); - } - posRepr += charWidth; - } - } + Insert(ll->edgeColumn); + Insert(lineEnd); saeNext = (!selAndEdge.empty()) ? selAndEdge[0] : -1; } BreakFinder::~BreakFinder() { } -int BreakFinder::First() const { - return nextBreak; -} - -int BreakFinder::Next() { +TextSegment BreakFinder::Next() { if (subBreak == -1) { int prev = nextBreak; - while (nextBreak < lineEnd) { - if ((ll->styles[nextBreak] != ll->styles[nextBreak + 1]) || - (nextBreak == saeNext) || - IsControlCharacter(ll->chars[nextBreak]) || IsControlCharacter(ll->chars[nextBreak + 1])) { - if (nextBreak == saeNext) { + while (nextBreak < lineEnd) { + int charWidth = 1; + if (encodingFamily == efUnicode) + charWidth = UTF8DrawBytes(reinterpret_cast<unsigned char *>(ll->chars) + nextBreak, lineEnd - nextBreak); + else if (encodingFamily == efDBCS) + charWidth = pdoc->IsDBCSLeadByte(ll->chars[nextBreak]) ? 2 : 1; + Representation *repr = preprs->RepresentationFromCharacter(ll->chars + nextBreak, charWidth); + if ((ll->styles[nextBreak] != ll->styles[nextBreak - 1]) || + repr || + (nextBreak == saeNext)) { + while ((nextBreak >= saeNext) && (saeNext < lineEnd)) { saeCurrentPos++; - saeNext = (saeCurrentPos < selAndEdge.size()) ? selAndEdge[saeCurrentPos] : -1; + saeNext = (saeCurrentPos < selAndEdge.size()) ? selAndEdge[saeCurrentPos] : lineEnd; } - nextBreak++; - if ((nextBreak - prev) < lengthStartSubdivision) { - return nextBreak; + if ((nextBreak > prev) || repr) { + // Have a segment to report + if (nextBreak == prev) { + nextBreak += charWidth; + } else { + repr = 0; // Optimize -> should remember repr + } + if ((nextBreak - prev) < lengthStartSubdivision) { + return TextSegment(prev, nextBreak - prev, repr); + } else { + break; + } } - break; } - nextBreak++; + nextBreak += charWidth; } if ((nextBreak - prev) < lengthStartSubdivision) { - return nextBreak; + return TextSegment(prev, nextBreak - prev); } subBreak = prev; } // Splitting up a long run from prev to nextBreak in lots of approximately lengthEachSubdivision. // For very long runs add extra breaks after spaces or if no spaces before low punctuation. + int startSegment = subBreak; if ((nextBreak - subBreak) <= lengthEachSubdivision) { subBreak = -1; - return nextBreak; + return TextSegment(startSegment, nextBreak - startSegment); } else { subBreak += pdoc->SafeSegment(ll->chars + subBreak, nextBreak-subBreak, lengthEachSubdivision); if (subBreak >= nextBreak) { subBreak = -1; - return nextBreak; + return TextSegment(startSegment, nextBreak - startSegment); } else { - return subBreak; + return TextSegment(startSegment, subBreak - startSegment); } } } +bool BreakFinder::More() const { + return (subBreak >= 0) || (nextBreak < lineEnd); +} + PositionCacheEntry::PositionCacheEntry() : styleNumber(0), len(0), clock(0), positions(0) { } |