1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Copyright 2006 The Android Open Source Project 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * found in the LICENSE file. 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "SkTextBox.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "SkUtils.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochstatic inline int is_ws(int c) 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){ 135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) return !((c - 1) >> 5); 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static size_t linebreak(const char text[], const char stop[], 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const SkPaint& paint, SkScalar margin, 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t* trailing = NULL) 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){ 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t lengthBreak = paint.breakText(text, stop - text, margin); 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) //Check for white space or line breakers before the lengthBreak 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* start = text; 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* word_start = text; 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int prevWS = true; 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (trailing) { 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *trailing = 0; 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) while (text < stop) { 31e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const char* prevText = text; 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SkUnichar uni = SkUTF8_NextUnichar(&text); 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int currWS = is_ws(uni); 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!currWS && prevWS) { 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) word_start = prevText; 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) prevWS = currWS; 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (text > start + lengthBreak) { 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (currWS) { 42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // eat the rest of the whitespace 43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while (text < stop && is_ws(SkUTF8_ToUnichar(text))) { 44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) text += SkUTF8_CountUTF8Bytes(text); 45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (trailing) { 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *trailing = text - prevText; 48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else { 50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // backup until a whitespace (or 1 char) 51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (word_start == start) { 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (prevText > start) { 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) text = prevText; 54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) text = word_start; 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) break; 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if ('\n' == uni) { 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t ret = text - start; 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t lineBreakSize = 1; 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (text < stop) { 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uni = SkUTF8_NextUnichar(&text); 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if ('\r' == uni) { 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret = text - start; 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ++lineBreakSize; 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (trailing) { 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *trailing = lineBreakSize; 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ret; 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ('\r' == uni) { 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t ret = text - start; 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t lineBreakSize = 1; 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (text < stop) { 82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) uni = SkUTF8_NextUnichar(&text); 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ('\n' == uni) { 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ret = text - start; 85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ++lineBreakSize; 86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (trailing) { 89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *trailing = lineBreakSize; 90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return ret; 92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 94b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return text - start; 96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int SkTextLineBreaker::CountLines(const char text[], size_t len, const SkPaint& paint, SkScalar width) 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){ 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* stop = text + len; 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int count = 0; 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (width > 0) 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) do { 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) count += 1; 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) text += linebreak(text, stop, paint, width); 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } while (text < stop); 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return count; 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////// 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SkTextBox::SkTextBox() 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){ 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fBox.setEmpty(); 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fSpacingMul = SK_Scalar1; 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fSpacingAdd = 0; 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fMode = kLineBreak_Mode; 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fSpacingAlign = kStart_SpacingAlign; 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SkTextBox::setMode(Mode mode) 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){ 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SkASSERT((unsigned)mode < kModeCount); 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fMode = SkToU8(mode); 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SkTextBox::setSpacingAlign(SpacingAlign align) 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){ 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SkASSERT((unsigned)align < kSpacingAlignCount); 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) fSpacingAlign = SkToU8(align); 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SkTextBox::getBox(SkRect* box) const 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){ 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (box) 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *box = fBox; 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SkTextBox::setBox(const SkRect& box) 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){ 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) fBox = box; 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SkTextBox::setBox(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){ 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fBox.set(left, top, right, bottom); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SkTextBox::getSpacing(SkScalar* mul, SkScalar* add) const 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){ 154a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (mul) 1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) *mul = fSpacingMul; 156a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (add) 157a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) *add = fSpacingAdd; 158a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 160a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void SkTextBox::setSpacing(SkScalar mul, SkScalar add) 161a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles){ 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fSpacingMul = mul; 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fSpacingAdd = add; 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)///////////////////////////////////////////////////////////////////////////////////////////// 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SkTextBox::draw(SkCanvas* canvas, const char text[], size_t len, const SkPaint& paint) 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){ 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SkASSERT(canvas && &paint && (text || len == 0)); 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SkScalar marginWidth = fBox.width(); 173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (marginWidth <= 0 || len == 0) 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const char* textStop = text + len; 178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) SkScalar x, y, scaledSpacing, height, fontHeight; 1800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) SkPaint::FontMetrics metrics; 1810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) switch (paint.getTextAlign()) { 1830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) case SkPaint::kLeft_Align: 1840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) x = 0; 1850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 1860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) case SkPaint::kCenter_Align: 1870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) x = SkScalarHalf(marginWidth); 1880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 1890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) default: 1900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) x = marginWidth; 1910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 1920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) x += fBox.fLeft; 1940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) fontHeight = paint.getFontMetrics(&metrics); 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scaledSpacing = SkScalarMul(fontHeight, fSpacingMul) + fSpacingAdd; 1970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) height = fBox.height(); 1980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // compute Y position for first line 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SkScalar textHeight = fontHeight; 2020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (fMode == kLineBreak_Mode && fSpacingAlign != kStart_SpacingAlign) 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int count = SkTextLineBreaker::CountLines(text, textStop - text, paint, marginWidth); 2060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) SkASSERT(count > 0); 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) textHeight += scaledSpacing * (count - 1); 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (fSpacingAlign) { 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case kStart_SpacingAlign: 2120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) y = 0; 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case kCenter_SpacingAlign: 2150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) y = SkScalarHalf(height - textHeight); 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default: 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SkASSERT(fSpacingAlign == kEnd_SpacingAlign); 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) y = height - textHeight; 2200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) y += fBox.fTop - metrics.fAscent; 2230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (;;) 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t trailing; 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) len = linebreak(text, textStop, paint, marginWidth, &trailing); 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (y + metrics.fDescent + metrics.fLeading > 0) 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) canvas->drawText(text, len - trailing, x, y, paint); 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) text += len; 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (text >= textStop) 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) y += scaledSpacing; 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (y + metrics.fAscent >= fBox.fBottom) 2360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SkTextBox::setText(const char text[], size_t len, const SkPaint& paint) { 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fText = text; 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fLen = len; 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fPaint = &paint; 2460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 2470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void SkTextBox::draw(SkCanvas* canvas) { 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this->draw(canvas, fText, fLen, *fPaint); 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 2510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int SkTextBox::countLines() const { 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return SkTextLineBreaker::CountLines(fText, fLen, *fPaint, fBox.width()); 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SkScalar SkTextBox::getTextHeight() const { 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SkScalar spacing = SkScalarMul(fPaint->getTextSize(), fSpacingMul) + fSpacingAdd; 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return this->countLines() * spacing; 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)