| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkTextBox.h" | 8 #include "SkTextBox.h" |
| 9 #include "SkUtils.h" | 9 #include "SkUtils.h" |
| 10 | 10 |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 } | 158 } |
| 159 | 159 |
| 160 void SkTextBox::setSpacing(SkScalar mul, SkScalar add) | 160 void SkTextBox::setSpacing(SkScalar mul, SkScalar add) |
| 161 { | 161 { |
| 162 fSpacingMul = mul; | 162 fSpacingMul = mul; |
| 163 fSpacingAdd = add; | 163 fSpacingAdd = add; |
| 164 } | 164 } |
| 165 | 165 |
| 166 ////////////////////////////////////////////////////////////////////////////////
///////////// | 166 ////////////////////////////////////////////////////////////////////////////////
///////////// |
| 167 | 167 |
| 168 void SkTextBox::draw(SkCanvas* canvas, const char text[], size_t len, const SkPa
int& paint) | 168 SkScalar SkTextBox::visit(Visitor& visitor, const char text[], size_t len, |
| 169 { | 169 const SkPaint& paint) const { |
| 170 SkASSERT(canvas && (text || len == 0)); | |
| 171 | |
| 172 SkScalar marginWidth = fBox.width(); | 170 SkScalar marginWidth = fBox.width(); |
| 173 | 171 |
| 174 if (marginWidth <= 0 || len == 0) | 172 if (marginWidth <= 0 || len == 0) { |
| 175 return; | 173 return fBox.top(); |
| 174 } |
| 176 | 175 |
| 177 const char* textStop = text + len; | 176 const char* textStop = text + len; |
| 178 | 177 |
| 179 SkScalar x, y, scaledSpacing, height, fontHeight; | 178 SkScalar x, y, scaledSpacing, height, fontHeight; |
| 180 SkPaint::FontMetrics metrics; | 179 SkPaint::FontMetrics metrics; |
| 181 | 180 |
| 182 switch (paint.getTextAlign()) { | 181 switch (paint.getTextAlign()) { |
| 183 case SkPaint::kLeft_Align: | 182 case SkPaint::kLeft_Align: |
| 184 x = 0; | 183 x = 0; |
| 185 break; | 184 break; |
| 186 case SkPaint::kCenter_Align: | 185 case SkPaint::kCenter_Align: |
| 187 x = SkScalarHalf(marginWidth); | 186 x = SkScalarHalf(marginWidth); |
| 188 break; | 187 break; |
| 189 default: | 188 default: |
| 190 x = marginWidth; | 189 x = marginWidth; |
| 191 break; | 190 break; |
| 192 } | 191 } |
| 193 x += fBox.fLeft; | 192 x += fBox.fLeft; |
| 194 | 193 |
| 195 fontHeight = paint.getFontMetrics(&metrics); | 194 fontHeight = paint.getFontMetrics(&metrics); |
| 196 scaledSpacing = SkScalarMul(fontHeight, fSpacingMul) + fSpacingAdd; | 195 scaledSpacing = SkScalarMul(fontHeight, fSpacingMul) + fSpacingAdd; |
| 197 height = fBox.height(); | 196 height = fBox.height(); |
| 198 | 197 |
| 199 // compute Y position for first line | 198 // compute Y position for first line |
| 200 { | 199 { |
| 201 SkScalar textHeight = fontHeight; | 200 SkScalar textHeight = fontHeight; |
| 202 | 201 |
| 203 if (fMode == kLineBreak_Mode && fSpacingAlign != kStart_SpacingAlign) | 202 if (fMode == kLineBreak_Mode && fSpacingAlign != kStart_SpacingAlign) { |
| 204 { | |
| 205 int count = SkTextLineBreaker::CountLines(text, textStop - text, pai
nt, marginWidth); | 203 int count = SkTextLineBreaker::CountLines(text, textStop - text, pai
nt, marginWidth); |
| 206 SkASSERT(count > 0); | 204 SkASSERT(count > 0); |
| 207 textHeight += scaledSpacing * (count - 1); | 205 textHeight += scaledSpacing * (count - 1); |
| 208 } | 206 } |
| 209 | 207 |
| 210 switch (fSpacingAlign) { | 208 switch (fSpacingAlign) { |
| 211 case kStart_SpacingAlign: | 209 case kStart_SpacingAlign: |
| 212 y = 0; | 210 y = 0; |
| 213 break; | 211 break; |
| 214 case kCenter_SpacingAlign: | 212 case kCenter_SpacingAlign: |
| 215 y = SkScalarHalf(height - textHeight); | 213 y = SkScalarHalf(height - textHeight); |
| 216 break; | 214 break; |
| 217 default: | 215 default: |
| 218 SkASSERT(fSpacingAlign == kEnd_SpacingAlign); | 216 SkASSERT(fSpacingAlign == kEnd_SpacingAlign); |
| 219 y = height - textHeight; | 217 y = height - textHeight; |
| 220 break; | 218 break; |
| 221 } | 219 } |
| 222 y += fBox.fTop - metrics.fAscent; | 220 y += fBox.fTop - metrics.fAscent; |
| 223 } | 221 } |
| 224 | 222 |
| 225 for (;;) | 223 for (;;) { |
| 226 { | |
| 227 size_t trailing; | 224 size_t trailing; |
| 228 len = linebreak(text, textStop, paint, marginWidth, &trailing); | 225 len = linebreak(text, textStop, paint, marginWidth, &trailing); |
| 229 if (y + metrics.fDescent + metrics.fLeading > 0) | 226 if (y + metrics.fDescent + metrics.fLeading > 0) { |
| 230 canvas->drawText(text, len - trailing, x, y, paint); | 227 visitor(text, len - trailing, x, y, paint); |
| 228 } |
| 231 text += len; | 229 text += len; |
| 232 if (text >= textStop) | 230 if (text >= textStop) { |
| 233 break; | 231 break; |
| 232 } |
| 234 y += scaledSpacing; | 233 y += scaledSpacing; |
| 235 if (y + metrics.fAscent >= fBox.fBottom) | 234 if (y + metrics.fAscent >= fBox.fBottom) { |
| 236 break; | 235 break; |
| 236 } |
| 237 } | 237 } |
| 238 return y + metrics.fDescent + metrics.fLeading; |
| 238 } | 239 } |
| 239 | 240 |
| 240 /////////////////////////////////////////////////////////////////////////////// | 241 /////////////////////////////////////////////////////////////////////////////// |
| 241 | 242 |
| 243 class CanvasVisitor : public SkTextBox::Visitor { |
| 244 SkCanvas* fCanvas; |
| 245 public: |
| 246 CanvasVisitor(SkCanvas* canvas) : fCanvas(canvas) {} |
| 247 |
| 248 virtual void operator()(const char text[], size_t length, SkScalar x, SkScal
ar y, |
| 249 const SkPaint& paint) SK_OVERRIDE { |
| 250 fCanvas->drawText(text, length, x, y, paint); |
| 251 } |
| 252 }; |
| 253 |
| 242 void SkTextBox::setText(const char text[], size_t len, const SkPaint& paint) { | 254 void SkTextBox::setText(const char text[], size_t len, const SkPaint& paint) { |
| 243 fText = text; | 255 fText = text; |
| 244 fLen = len; | 256 fLen = len; |
| 245 fPaint = &paint; | 257 fPaint = &paint; |
| 246 } | 258 } |
| 247 | 259 |
| 260 void SkTextBox::draw(SkCanvas* canvas, const char text[], size_t len, const SkPa
int& paint) { |
| 261 CanvasVisitor sink(canvas); |
| 262 this->visit(sink, text, len, paint); |
| 263 } |
| 264 |
| 248 void SkTextBox::draw(SkCanvas* canvas) { | 265 void SkTextBox::draw(SkCanvas* canvas) { |
| 249 this->draw(canvas, fText, fLen, *fPaint); | 266 this->draw(canvas, fText, fLen, *fPaint); |
| 250 } | 267 } |
| 251 | 268 |
| 252 int SkTextBox::countLines() const { | 269 int SkTextBox::countLines() const { |
| 253 return SkTextLineBreaker::CountLines(fText, fLen, *fPaint, fBox.width()); | 270 return SkTextLineBreaker::CountLines(fText, fLen, *fPaint, fBox.width()); |
| 254 } | 271 } |
| 255 | 272 |
| 256 SkScalar SkTextBox::getTextHeight() const { | 273 SkScalar SkTextBox::getTextHeight() const { |
| 257 SkScalar spacing = SkScalarMul(fPaint->getTextSize(), fSpacingMul) + fSpacin
gAdd; | 274 SkScalar spacing = SkScalarMul(fPaint->getTextSize(), fSpacingMul) + fSpacin
gAdd; |
| 258 return this->countLines() * spacing; | 275 return this->countLines() * spacing; |
| 259 } | 276 } |
| 277 |
| 278 /////////////////////////////////////////////////////////////////////////////// |
| 279 |
| 280 #include "SkTextBlob.h" |
| 281 |
| 282 class TextBlobVisitor : public SkTextBox::Visitor { |
| 283 public: |
| 284 SkTextBlobBuilder fBuilder; |
| 285 |
| 286 virtual void operator()(const char text[], size_t length, SkScalar x, SkScal
ar y, |
| 287 const SkPaint& paint) SK_OVERRIDE { |
| 288 SkPaint p(paint); |
| 289 p.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
| 290 const int count = paint.countText(text, length); |
| 291 paint.textToGlyphs(text, length, fBuilder.allocRun(p, count, x, y).glyph
s); |
| 292 } |
| 293 }; |
| 294 |
| 295 SkTextBlob* SkTextBox::snapshotTextBlob(SkScalar* computedBottom) const { |
| 296 TextBlobVisitor visitor; |
| 297 SkScalar newB = this->visit(visitor, fText, fLen, *fPaint); |
| 298 if (computedBottom) { |
| 299 *computedBottom = newB; |
| 300 } |
| 301 return (SkTextBlob*)visitor.fBuilder.build(); |
| 302 } |
| 303 |
| OLD | NEW |