aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/PositionCache.cxx
diff options
context:
space:
mode:
authornyamatongwe <unknown>2011-05-13 10:27:30 +1000
committernyamatongwe <unknown>2011-05-13 10:27:30 +1000
commitef61afe500f7ba58b1fcefaa1ab0205ccb66b5c2 (patch)
tree1ec46b88ebe5ce2651a1bd1642a5e6cf77c53c02 /src/PositionCache.cxx
parent67e0bd9337d9592fbc1199e3ab6f063ea1e62b45 (diff)
downloadscintilla-mirror-ef61afe500f7ba58b1fcefaa1ab0205ccb66b5c2.tar.gz
Break measurement of text into reasonable sized segments similar
to drawing. Drawing will now always be broken up at a character boundary even when there is a large number of alphabetic characters. Fixes bug #3165743.
Diffstat (limited to 'src/PositionCache.cxx')
-rw-r--r--src/PositionCache.cxx62
1 files changed, 24 insertions, 38 deletions
diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx
index 52c4326c0..e59c12630 100644
--- a/src/PositionCache.cxx
+++ b/src/PositionCache.cxx
@@ -391,18 +391,19 @@ static int NextBadU(const char *s, int p, int len, int &trailBytes) {
return -1;
}
-BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, bool utf8_, int xStart, bool breakForSelection) :
+BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_,
+ int xStart, bool breakForSelection, Document *pdoc_) :
ll(ll_),
lineStart(lineStart_),
lineEnd(lineEnd_),
posLineStart(posLineStart_),
- utf8(utf8_),
nextBreak(lineStart_),
saeSize(0),
saeLen(0),
saeCurrentPos(0),
saeNext(0),
- subBreak(-1) {
+ subBreak(-1),
+ pdoc(pdoc_) {
saeSize = 8;
selAndEdge = new int[saeSize];
for (unsigned int j=0; j < saeSize; j++) {
@@ -435,7 +436,7 @@ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posL
Insert(ll->edgeColumn - 1);
Insert(lineEnd - 1);
- if (utf8) {
+ if (pdoc && (SC_CP_UTF8 == pdoc->dbcsCodePage)) {
int trailBytes=0;
for (int pos = -1;;) {
pos = NextBadU(ll->chars, pos, lineEnd, trailBytes);
@@ -456,10 +457,6 @@ int BreakFinder::First() const {
return nextBreak;
}
-static bool IsTrailByte(int ch) {
- return (ch >= 0x80) && (ch < (0x80 + 0x40));
-}
-
int BreakFinder::Next() {
if (subBreak == -1) {
int prev = nextBreak;
@@ -490,34 +487,7 @@ int BreakFinder::Next() {
subBreak = -1;
return nextBreak;
} else {
- int lastGoodBreak = -1;
- int lastOKBreak = -1;
- int lastUTF8Break = -1;
- int j;
- for (j = subBreak + 1; j <= nextBreak; j++) {
- if (IsSpaceOrTab(ll->chars[j - 1]) && !IsSpaceOrTab(ll->chars[j])) {
- lastGoodBreak = j;
- }
- if (static_cast<unsigned char>(ll->chars[j]) < 'A') {
- lastOKBreak = j;
- }
- if (utf8 && !IsTrailByte(static_cast<unsigned char>(ll->chars[j]))) {
- lastUTF8Break = j;
- }
- if (((j - subBreak) >= lengthEachSubdivision) &&
- ((lastGoodBreak >= 0) || (lastOKBreak >= 0) || (lastUTF8Break >= 0))) {
- break;
- }
- }
- if (lastGoodBreak >= 0) {
- subBreak = lastGoodBreak;
- } else if (lastOKBreak >= 0) {
- subBreak = lastOKBreak;
- } else if (lastUTF8Break >= 0) {
- subBreak = lastUTF8Break;
- } else {
- subBreak = nextBreak;
- }
+ subBreak += pdoc->SafeSegment(ll->chars + subBreak, nextBreak-subBreak, lengthEachSubdivision);
if (subBreak >= nextBreak) {
subBreak = -1;
return nextBreak;
@@ -624,7 +594,8 @@ void PositionCache::SetSize(size_t size_) {
}
void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber,
- const char *s, unsigned int len, int *positions) {
+ const char *s, unsigned int len, int *positions, Document *pdoc) {
+
allClear = false;
int probe = -1;
if ((size > 0) && (len < 30)) {
@@ -646,7 +617,22 @@ void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned
probe = probe2;
}
}
- surface->MeasureWidths(vstyle.styles[styleNumber].font, s, len, positions);
+ if (len > BreakFinder::lengthStartSubdivision) {
+ // Break up into segments
+ unsigned int startSegment = 0;
+ int xStartSegment = 0;
+ while (startSegment < len) {
+ unsigned int lenSegment = pdoc->SafeSegment(s + startSegment, len - startSegment, BreakFinder::lengthEachSubdivision);
+ surface->MeasureWidths(vstyle.styles[styleNumber].font, s + startSegment, lenSegment, positions + startSegment);
+ for (unsigned int inSeg = 0; inSeg < lenSegment; inSeg++) {
+ positions[startSegment + inSeg] += xStartSegment;
+ }
+ xStartSegment = positions[startSegment + lenSegment - 1];
+ startSegment += lenSegment;
+ }
+ } else {
+ surface->MeasureWidths(vstyle.styles[styleNumber].font, s, len, positions);
+ }
if (probe >= 0) {
clock++;
if (clock > 60000) {