diff options
Diffstat (limited to 'src/views/SkTextBox.cpp')
-rw-r--r-- | src/views/SkTextBox.cpp | 86 |
1 files changed, 82 insertions, 4 deletions
diff --git a/src/views/SkTextBox.cpp b/src/views/SkTextBox.cpp index 355944aef1..78828b6d85 100644 --- a/src/views/SkTextBox.cpp +++ b/src/views/SkTextBox.cpp @@ -13,9 +13,86 @@ static inline int is_ws(int c) return !((c - 1) >> 5); } -static size_t linebreak(const char text[], const char stop[], const SkPaint& paint, SkScalar margin) +static size_t linebreak(const char text[], const char stop[], + const SkPaint& paint, SkScalar margin, + size_t* trailing = NULL) { - return paint.breakText(text, stop - text, margin); + size_t lengthBreak = paint.breakText(text, stop - text, margin); + + //Check for white space or line breakers before the lengthBreak + const char* start = text; + const char* word_start = text; + int prevWS = true; + if (trailing) { + *trailing = 0; + } + + while (text < stop) { + const char* prevText = text; + SkUnichar uni = SkUTF8_NextUnichar(&text); + int currWS = is_ws(uni); + + if (!currWS && prevWS) { + word_start = prevText; + } + prevWS = currWS; + + if (text > start + lengthBreak) { + if (currWS) { + // eat the rest of the whitespace + while (text < stop && is_ws(SkUTF8_ToUnichar(text))) { + text += SkUTF8_CountUTF8Bytes(text); + } + if (trailing) { + *trailing = text - prevText; + } + } else { + // backup until a whitespace (or 1 char) + if (word_start == start) { + if (prevText > start) { + text = prevText; + } + } else { + text = word_start; + } + } + break; + } + + if ('\n' == uni) { + size_t ret = text - start; + size_t lineBreakSize = 1; + if (text < stop) { + uni = SkUTF8_NextUnichar(&text); + if ('\r' == uni) { + ret = text - start; + ++lineBreakSize; + } + } + if (trailing) { + *trailing = lineBreakSize; + } + return ret; + } + + if ('\r' == uni) { + size_t ret = text - start; + size_t lineBreakSize = 1; + if (text < stop) { + uni = SkUTF8_NextUnichar(&text); + if ('\n' == uni) { + ret = text - start; + ++lineBreakSize; + } + } + if (trailing) { + *trailing = lineBreakSize; + } + return ret; + } + } + + return text - start; } int SkTextLineBreaker::CountLines(const char text[], size_t len, const SkPaint& paint, SkScalar width) @@ -147,9 +224,10 @@ void SkTextBox::draw(SkCanvas* canvas, const char text[], size_t len, const SkPa for (;;) { - len = linebreak(text, textStop, paint, marginWidth); + size_t trailing; + len = linebreak(text, textStop, paint, marginWidth, &trailing); if (y + metrics.fDescent + metrics.fLeading > 0) - canvas->drawText(text, len, x, y, paint); + canvas->drawText(text, len - trailing, x, y, paint); text += len; if (text >= textStop) break; |