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 |