1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTextBox.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int is_ws(int c)
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return !((c - 1) >> 5);
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
160d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.comstatic size_t linebreak(const char text[], const char stop[],
170d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                        const SkPaint& paint, SkScalar margin,
180d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                        size_t* trailing = NULL)
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
200d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com    size_t lengthBreak = paint.breakText(text, stop - text, margin);
210d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com
220d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com    //Check for white space or line breakers before the lengthBreak
230d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com    const char* start = text;
240d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com    const char* word_start = text;
250d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com    int prevWS = true;
260d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com    if (trailing) {
270d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        *trailing = 0;
280d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com    }
290d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com
300d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com    while (text < stop) {
310d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        const char* prevText = text;
320d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        SkUnichar uni = SkUTF8_NextUnichar(&text);
330d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        int currWS = is_ws(uni);
340d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com
350d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        if (!currWS && prevWS) {
360d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            word_start = prevText;
370d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        }
380d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        prevWS = currWS;
390d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com
400d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        if (text > start + lengthBreak) {
410d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            if (currWS) {
420d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                // eat the rest of the whitespace
430d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                while (text < stop && is_ws(SkUTF8_ToUnichar(text))) {
440d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                    text += SkUTF8_CountUTF8Bytes(text);
450d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                }
460d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                if (trailing) {
470d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                    *trailing = text - prevText;
480d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                }
490d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            } else {
500d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                // backup until a whitespace (or 1 char)
510d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                if (word_start == start) {
520d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                    if (prevText > start) {
530d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                        text = prevText;
540d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                    }
550d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                } else {
560d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                    text = word_start;
570d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                }
580d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            }
590d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            break;
600d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        }
610d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com
620d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        if ('\n' == uni) {
630d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            size_t ret = text - start;
640d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            size_t lineBreakSize = 1;
650d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            if (text < stop) {
660d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                uni = SkUTF8_NextUnichar(&text);
670d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                if ('\r' == uni) {
680d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                    ret = text - start;
690d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                    ++lineBreakSize;
700d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                }
710d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            }
720d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            if (trailing) {
730d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                *trailing = lineBreakSize;
740d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            }
750d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            return ret;
760d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        }
770d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com
780d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        if ('\r' == uni) {
790d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            size_t ret = text - start;
800d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            size_t lineBreakSize = 1;
810d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            if (text < stop) {
820d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                uni = SkUTF8_NextUnichar(&text);
830d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                if ('\n' == uni) {
840d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                    ret = text - start;
850d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                    ++lineBreakSize;
860d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                }
870d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            }
880d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            if (trailing) {
890d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com                *trailing = lineBreakSize;
900d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            }
910d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            return ret;
920d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        }
930d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com    }
940d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com
950d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com    return text - start;
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkTextLineBreaker::CountLines(const char text[], size_t len, const SkPaint& paint, SkScalar width)
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* stop = text + len;
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int         count = 0;
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (width > 0)
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count += 1;
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            text += linebreak(text, stop, paint, width);
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (text < stop);
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkTextBox::SkTextBox()
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBox.setEmpty();
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSpacingMul = SK_Scalar1;
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSpacingAdd = 0;
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMode = kLineBreak_Mode;
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSpacingAlign = kStart_SpacingAlign;
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkTextBox::setMode(Mode mode)
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)mode < kModeCount);
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMode = SkToU8(mode);
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkTextBox::setSpacingAlign(SpacingAlign align)
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)align < kSpacingAlignCount);
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSpacingAlign = SkToU8(align);
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkTextBox::getBox(SkRect* box) const
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (box)
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *box = fBox;
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkTextBox::setBox(const SkRect& box)
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBox = box;
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkTextBox::setBox(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom)
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBox.set(left, top, right, bottom);
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkTextBox::getSpacing(SkScalar* mul, SkScalar* add) const
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mul)
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *mul = fSpacingMul;
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (add)
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *add = fSpacingAdd;
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkTextBox::setSpacing(SkScalar mul, SkScalar add)
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSpacingMul = mul;
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSpacingAdd = add;
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////////////////////
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkTextBox::draw(SkCanvas* canvas, const char text[], size_t len, const SkPaint& paint)
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
170a10742c69ce47d346e3cf23e7be909c9f29b401ecaryclark    SkASSERT(canvas && (text || len == 0));
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar marginWidth = fBox.width();
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (marginWidth <= 0 || len == 0)
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* textStop = text + len;
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar                x, y, scaledSpacing, height, fontHeight;
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint::FontMetrics    metrics;
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (paint.getTextAlign()) {
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case SkPaint::kLeft_Align:
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x = 0;
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        break;
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case SkPaint::kCenter_Align:
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x = SkScalarHalf(marginWidth);
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        break;
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    default:
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x = marginWidth;
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        break;
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    x += fBox.fLeft;
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fontHeight = paint.getFontMetrics(&metrics);
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    scaledSpacing = SkScalarMul(fontHeight, fSpacingMul) + fSpacingAdd;
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    height = fBox.height();
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    //  compute Y position for first line
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar textHeight = fontHeight;
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fMode == kLineBreak_Mode && fSpacingAlign != kStart_SpacingAlign)
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        {
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = SkTextLineBreaker::CountLines(text, textStop - text, paint, marginWidth);
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count > 0);
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            textHeight += scaledSpacing * (count - 1);
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        switch (fSpacingAlign) {
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kStart_SpacingAlign:
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            y = 0;
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kCenter_SpacingAlign:
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            y = SkScalarHalf(height - textHeight);
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(fSpacingAlign == kEnd_SpacingAlign);
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            y = height - textHeight;
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        y += fBox.fTop - metrics.fAscent;
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;)
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
2270d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        size_t trailing;
2280d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com        len = linebreak(text, textStop, paint, marginWidth, &trailing);
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (y + metrics.fDescent + metrics.fLeading > 0)
2300d50bc14901ee87552224ee4f1ec84f2f1db7320bungeman@google.com            canvas->drawText(text, len - trailing, x, y, paint);
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        text += len;
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (text >= textStop)
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        y += scaledSpacing;
23548821fc31c3987a68268139850ebc1b8d326ade5scroggo@google.com        if (y + metrics.fAscent >= fBox.fBottom)
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
237d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    }
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
240033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com///////////////////////////////////////////////////////////////////////////////
241033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com
242033e03cb191aff56e06e5d6aab917f60740dba63reed@android.comvoid SkTextBox::setText(const char text[], size_t len, const SkPaint& paint) {
243033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com    fText = text;
244033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com    fLen = len;
245033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com    fPaint = &paint;
246033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com}
247033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com
248033e03cb191aff56e06e5d6aab917f60740dba63reed@android.comvoid SkTextBox::draw(SkCanvas* canvas) {
249033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com    this->draw(canvas, fText, fLen, *fPaint);
250033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com}
251033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com
252033e03cb191aff56e06e5d6aab917f60740dba63reed@android.comint SkTextBox::countLines() const {
253033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com    return SkTextLineBreaker::CountLines(fText, fLen, *fPaint, fBox.width());
254033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com}
255033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com
256033e03cb191aff56e06e5d6aab917f60740dba63reed@android.comSkScalar SkTextBox::getTextHeight() const {
257033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com    SkScalar spacing = SkScalarMul(fPaint->getTextSize(), fSpacingMul) + fSpacingAdd;
258033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com    return this->countLines() * spacing;
259033e03cb191aff56e06e5d6aab917f60740dba63reed@android.com}
260