1 /*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkDraw.h"
9 #include "SkBlitter.h"
10 #include "SkBounder.h"
11 #include "SkCanvas.h"
12 #include "SkColorPriv.h"
13 #include "SkDevice.h"
14 #include "SkDeviceLooper.h"
15 #include "SkFixed.h"
16 #include "SkMaskFilter.h"
17 #include "SkPaint.h"
18 #include "SkPathEffect.h"
19 #include "SkRasterClip.h"
20 #include "SkRasterizer.h"
21 #include "SkRRect.h"
22 #include "SkScan.h"
23 #include "SkShader.h"
24 #include "SkString.h"
25 #include "SkStroke.h"
26 #include "SkTemplatesPriv.h"
27 #include "SkTLazy.h"
28 #include "SkUtils.h"
29
30 #include "SkAutoKern.h"
31 #include "SkBitmapProcShader.h"
32 #include "SkDrawProcs.h"
33 #include "SkMatrixUtils.h"
34
ShouldDrawTextAsPaths(const SkPaint & paint,const SkMatrix & ctm)35 bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) {
36 // we don't cache hairlines in the cache
37 if (SkPaint::kStroke_Style == paint.getStyle() &&
38 0 == paint.getStrokeWidth()) {
39 return true;
40 }
41
42 // we don't cache perspective
43 if (ctm.hasPerspective()) {
44 return true;
45 }
46
47 SkMatrix textM;
48 return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM));
49 }
50
51 //#define TRACE_BITMAP_DRAWS
52
53 #define kBlitterStorageLongCount (sizeof(SkBitmapProcShader) >> 2)
54
55 /** Helper for allocating small blitters on the stack.
56 */
57 class SkAutoBlitterChoose : SkNoncopyable {
58 public:
SkAutoBlitterChoose()59 SkAutoBlitterChoose() {
60 fBlitter = NULL;
61 }
SkAutoBlitterChoose(const SkBitmap & device,const SkMatrix & matrix,const SkPaint & paint,bool drawCoverage=false)62 SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix,
63 const SkPaint& paint, bool drawCoverage = false) {
64 fBlitter = SkBlitter::Choose(device, matrix, paint,
65 fStorage, sizeof(fStorage), drawCoverage);
66 }
67
~SkAutoBlitterChoose()68 ~SkAutoBlitterChoose() {
69 if ((void*)fBlitter == (void*)fStorage) {
70 fBlitter->~SkBlitter();
71 } else {
72 SkDELETE(fBlitter);
73 }
74 }
75
operator ->()76 SkBlitter* operator->() { return fBlitter; }
get() const77 SkBlitter* get() const { return fBlitter; }
78
choose(const SkBitmap & device,const SkMatrix & matrix,const SkPaint & paint)79 void choose(const SkBitmap& device, const SkMatrix& matrix,
80 const SkPaint& paint) {
81 SkASSERT(!fBlitter);
82 fBlitter = SkBlitter::Choose(device, matrix, paint,
83 fStorage, sizeof(fStorage));
84 }
85
86 private:
87 SkBlitter* fBlitter;
88 uint32_t fStorage[kBlitterStorageLongCount];
89 };
90 #define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose)
91
92 /**
93 * Since we are providing the storage for the shader (to avoid the perf cost
94 * of calling new) we insist that in our destructor we can account for all
95 * owners of the shader.
96 */
97 class SkAutoBitmapShaderInstall : SkNoncopyable {
98 public:
SkAutoBitmapShaderInstall(const SkBitmap & src,const SkPaint & paint)99 SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint)
100 : fPaint(paint) /* makes a copy of the paint */ {
101 fPaint.setShader(SkShader::CreateBitmapShader(src,
102 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
103 fStorage, sizeof(fStorage)));
104 // we deliberately left the shader with an owner-count of 2
105 SkASSERT(2 == fPaint.getShader()->getRefCnt());
106 }
107
~SkAutoBitmapShaderInstall()108 ~SkAutoBitmapShaderInstall() {
109 SkShader* shader = fPaint.getShader();
110 // since we manually destroy shader, we insist that owners == 2
111 SkASSERT(2 == shader->getRefCnt());
112
113 fPaint.setShader(NULL); // unref the shader by 1
114
115 // now destroy to take care of the 2nd owner-count
116 if ((void*)shader == (void*)fStorage) {
117 shader->~SkShader();
118 } else {
119 SkDELETE(shader);
120 }
121 }
122
123 // return the new paint that has the shader applied
paintWithShader() const124 const SkPaint& paintWithShader() const { return fPaint; }
125
126 private:
127 SkPaint fPaint; // copy of caller's paint (which we then modify)
128 uint32_t fStorage[kBlitterStorageLongCount];
129 };
130 #define SkAutoBitmapShaderInstall(...) SK_REQUIRE_LOCAL_VAR(SkAutoBitmapShaderInstall)
131
132 ///////////////////////////////////////////////////////////////////////////////
133
SkDraw()134 SkDraw::SkDraw() {
135 sk_bzero(this, sizeof(*this));
136 }
137
SkDraw(const SkDraw & src)138 SkDraw::SkDraw(const SkDraw& src) {
139 memcpy(this, &src, sizeof(*this));
140 }
141
computeConservativeLocalClipBounds(SkRect * localBounds) const142 bool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const {
143 if (fRC->isEmpty()) {
144 return false;
145 }
146
147 SkMatrix inverse;
148 if (!fMatrix->invert(&inverse)) {
149 return false;
150 }
151
152 SkIRect devBounds = fRC->getBounds();
153 // outset to have slop for antialasing and hairlines
154 devBounds.outset(1, 1);
155 inverse.mapRect(localBounds, SkRect::Make(devBounds));
156 return true;
157 }
158
159 ///////////////////////////////////////////////////////////////////////////////
160
161 typedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data);
162
D_Clear_BitmapXferProc(void * pixels,size_t bytes,uint32_t)163 static void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) {
164 sk_bzero(pixels, bytes);
165 }
166
D_Dst_BitmapXferProc(void *,size_t,uint32_t data)167 static void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {}
168
D32_Src_BitmapXferProc(void * pixels,size_t bytes,uint32_t data)169 static void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
170 sk_memset32((uint32_t*)pixels, data, bytes >> 2);
171 }
172
D16_Src_BitmapXferProc(void * pixels,size_t bytes,uint32_t data)173 static void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
174 sk_memset16((uint16_t*)pixels, data, bytes >> 1);
175 }
176
DA8_Src_BitmapXferProc(void * pixels,size_t bytes,uint32_t data)177 static void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
178 memset(pixels, data, bytes);
179 }
180
ChooseBitmapXferProc(const SkBitmap & bitmap,const SkPaint & paint,uint32_t * data)181 static BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap,
182 const SkPaint& paint,
183 uint32_t* data) {
184 // todo: we can apply colorfilter up front if no shader, so we wouldn't
185 // need to abort this fastpath
186 if (paint.getShader() || paint.getColorFilter()) {
187 return NULL;
188 }
189
190 SkXfermode::Mode mode;
191 if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) {
192 return NULL;
193 }
194
195 SkColor color = paint.getColor();
196
197 // collaps modes based on color...
198 if (SkXfermode::kSrcOver_Mode == mode) {
199 unsigned alpha = SkColorGetA(color);
200 if (0 == alpha) {
201 mode = SkXfermode::kDst_Mode;
202 } else if (0xFF == alpha) {
203 mode = SkXfermode::kSrc_Mode;
204 }
205 }
206
207 switch (mode) {
208 case SkXfermode::kClear_Mode:
209 // SkDebugf("--- D_Clear_BitmapXferProc\n");
210 return D_Clear_BitmapXferProc; // ignore data
211 case SkXfermode::kDst_Mode:
212 // SkDebugf("--- D_Dst_BitmapXferProc\n");
213 return D_Dst_BitmapXferProc; // ignore data
214 case SkXfermode::kSrc_Mode: {
215 /*
216 should I worry about dithering for the lower depths?
217 */
218 SkPMColor pmc = SkPreMultiplyColor(color);
219 switch (bitmap.config()) {
220 case SkBitmap::kARGB_8888_Config:
221 if (data) {
222 *data = pmc;
223 }
224 // SkDebugf("--- D32_Src_BitmapXferProc\n");
225 return D32_Src_BitmapXferProc;
226 case SkBitmap::kRGB_565_Config:
227 if (data) {
228 *data = SkPixel32ToPixel16(pmc);
229 }
230 // SkDebugf("--- D16_Src_BitmapXferProc\n");
231 return D16_Src_BitmapXferProc;
232 case SkBitmap::kA8_Config:
233 if (data) {
234 *data = SkGetPackedA32(pmc);
235 }
236 // SkDebugf("--- DA8_Src_BitmapXferProc\n");
237 return DA8_Src_BitmapXferProc;
238 default:
239 break;
240 }
241 break;
242 }
243 default:
244 break;
245 }
246 return NULL;
247 }
248
CallBitmapXferProc(const SkBitmap & bitmap,const SkIRect & rect,BitmapXferProc proc,uint32_t procData)249 static void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect,
250 BitmapXferProc proc, uint32_t procData) {
251 int shiftPerPixel;
252 switch (bitmap.config()) {
253 case SkBitmap::kARGB_8888_Config:
254 shiftPerPixel = 2;
255 break;
256 case SkBitmap::kRGB_565_Config:
257 shiftPerPixel = 1;
258 break;
259 case SkBitmap::kA8_Config:
260 shiftPerPixel = 0;
261 break;
262 default:
263 SkDEBUGFAIL("Can't use xferproc on this config");
264 return;
265 }
266
267 uint8_t* pixels = (uint8_t*)bitmap.getPixels();
268 SkASSERT(pixels);
269 const size_t rowBytes = bitmap.rowBytes();
270 const int widthBytes = rect.width() << shiftPerPixel;
271
272 // skip down to the first scanline and X position
273 pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel);
274 for (int scans = rect.height() - 1; scans >= 0; --scans) {
275 proc(pixels, widthBytes, procData);
276 pixels += rowBytes;
277 }
278 }
279
drawPaint(const SkPaint & paint) const280 void SkDraw::drawPaint(const SkPaint& paint) const {
281 SkDEBUGCODE(this->validate();)
282
283 if (fRC->isEmpty()) {
284 return;
285 }
286
287 SkIRect devRect;
288 devRect.set(0, 0, fBitmap->width(), fBitmap->height());
289 if (fBounder && !fBounder->doIRect(devRect)) {
290 return;
291 }
292
293 if (fRC->isBW()) {
294 /* If we don't have a shader (i.e. we're just a solid color) we may
295 be faster to operate directly on the device bitmap, rather than invoking
296 a blitter. Esp. true for xfermodes, which require a colorshader to be
297 present, which is just redundant work. Since we're drawing everywhere
298 in the clip, we don't have to worry about antialiasing.
299 */
300 uint32_t procData = 0; // to avoid the warning
301 BitmapXferProc proc = ChooseBitmapXferProc(*fBitmap, paint, &procData);
302 if (proc) {
303 if (D_Dst_BitmapXferProc == proc) { // nothing to do
304 return;
305 }
306
307 SkRegion::Iterator iter(fRC->bwRgn());
308 while (!iter.done()) {
309 CallBitmapXferProc(*fBitmap, iter.rect(), proc, procData);
310 iter.next();
311 }
312 return;
313 }
314 }
315
316 // normal case: use a blitter
317 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
318 SkScan::FillIRect(devRect, *fRC, blitter.get());
319 }
320
321 ///////////////////////////////////////////////////////////////////////////////
322
323 struct PtProcRec {
324 SkCanvas::PointMode fMode;
325 const SkPaint* fPaint;
326 const SkRegion* fClip;
327 const SkRasterClip* fRC;
328
329 // computed values
330 SkFixed fRadius;
331
332 typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count,
333 SkBlitter*);
334
335 bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix,
336 const SkRasterClip*);
337 Proc chooseProc(SkBlitter** blitter);
338
339 private:
340 SkAAClipBlitterWrapper fWrapper;
341 };
342
bw_pt_rect_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)343 static void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
344 int count, SkBlitter* blitter) {
345 SkASSERT(rec.fClip->isRect());
346 const SkIRect& r = rec.fClip->getBounds();
347
348 for (int i = 0; i < count; i++) {
349 int x = SkScalarFloorToInt(devPts[i].fX);
350 int y = SkScalarFloorToInt(devPts[i].fY);
351 if (r.contains(x, y)) {
352 blitter->blitH(x, y, 1);
353 }
354 }
355 }
356
bw_pt_rect_16_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)357 static void bw_pt_rect_16_hair_proc(const PtProcRec& rec,
358 const SkPoint devPts[], int count,
359 SkBlitter* blitter) {
360 SkASSERT(rec.fRC->isRect());
361 const SkIRect& r = rec.fRC->getBounds();
362 uint32_t value;
363 const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value);
364 SkASSERT(bitmap);
365
366 uint16_t* addr = bitmap->getAddr16(0, 0);
367 size_t rb = bitmap->rowBytes();
368
369 for (int i = 0; i < count; i++) {
370 int x = SkScalarFloorToInt(devPts[i].fX);
371 int y = SkScalarFloorToInt(devPts[i].fY);
372 if (r.contains(x, y)) {
373 ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value);
374 }
375 }
376 }
377
bw_pt_rect_32_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)378 static void bw_pt_rect_32_hair_proc(const PtProcRec& rec,
379 const SkPoint devPts[], int count,
380 SkBlitter* blitter) {
381 SkASSERT(rec.fRC->isRect());
382 const SkIRect& r = rec.fRC->getBounds();
383 uint32_t value;
384 const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value);
385 SkASSERT(bitmap);
386
387 SkPMColor* addr = bitmap->getAddr32(0, 0);
388 size_t rb = bitmap->rowBytes();
389
390 for (int i = 0; i < count; i++) {
391 int x = SkScalarFloorToInt(devPts[i].fX);
392 int y = SkScalarFloorToInt(devPts[i].fY);
393 if (r.contains(x, y)) {
394 ((SkPMColor*)((char*)addr + y * rb))[x] = value;
395 }
396 }
397 }
398
bw_pt_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)399 static void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
400 int count, SkBlitter* blitter) {
401 for (int i = 0; i < count; i++) {
402 int x = SkScalarFloor(devPts[i].fX);
403 int y = SkScalarFloor(devPts[i].fY);
404 if (rec.fClip->contains(x, y)) {
405 blitter->blitH(x, y, 1);
406 }
407 }
408 }
409
bw_line_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)410 static void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
411 int count, SkBlitter* blitter) {
412 for (int i = 0; i < count; i += 2) {
413 SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
414 }
415 }
416
bw_poly_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)417 static void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
418 int count, SkBlitter* blitter) {
419 for (int i = 0; i < count - 1; i++) {
420 SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
421 }
422 }
423
424 // aa versions
425
aa_line_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)426 static void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
427 int count, SkBlitter* blitter) {
428 for (int i = 0; i < count; i += 2) {
429 SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
430 }
431 }
432
aa_poly_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)433 static void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
434 int count, SkBlitter* blitter) {
435 for (int i = 0; i < count - 1; i++) {
436 SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
437 }
438 }
439
440 // square procs (strokeWidth > 0 but matrix is square-scale (sx == sy)
441
bw_square_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)442 static void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[],
443 int count, SkBlitter* blitter) {
444 const SkFixed radius = rec.fRadius;
445 for (int i = 0; i < count; i++) {
446 SkFixed x = SkScalarToFixed(devPts[i].fX);
447 SkFixed y = SkScalarToFixed(devPts[i].fY);
448
449 SkXRect r;
450 r.fLeft = x - radius;
451 r.fTop = y - radius;
452 r.fRight = x + radius;
453 r.fBottom = y + radius;
454
455 SkScan::FillXRect(r, *rec.fRC, blitter);
456 }
457 }
458
aa_square_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)459 static void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[],
460 int count, SkBlitter* blitter) {
461 const SkFixed radius = rec.fRadius;
462 for (int i = 0; i < count; i++) {
463 SkFixed x = SkScalarToFixed(devPts[i].fX);
464 SkFixed y = SkScalarToFixed(devPts[i].fY);
465
466 SkXRect r;
467 r.fLeft = x - radius;
468 r.fTop = y - radius;
469 r.fRight = x + radius;
470 r.fBottom = y + radius;
471
472 SkScan::AntiFillXRect(r, *rec.fRC, blitter);
473 }
474 }
475
476 // If this guy returns true, then chooseProc() must return a valid proc
init(SkCanvas::PointMode mode,const SkPaint & paint,const SkMatrix * matrix,const SkRasterClip * rc)477 bool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint,
478 const SkMatrix* matrix, const SkRasterClip* rc) {
479 if (paint.getPathEffect()) {
480 return false;
481 }
482 SkScalar width = paint.getStrokeWidth();
483 if (0 == width) {
484 fMode = mode;
485 fPaint = &paint;
486 fClip = NULL;
487 fRC = rc;
488 fRadius = SK_FixedHalf;
489 return true;
490 }
491 if (paint.getStrokeCap() != SkPaint::kRound_Cap &&
492 matrix->rectStaysRect() && SkCanvas::kPoints_PointMode == mode) {
493 SkScalar sx = matrix->get(SkMatrix::kMScaleX);
494 SkScalar sy = matrix->get(SkMatrix::kMScaleY);
495 if (SkScalarNearlyZero(sx - sy)) {
496 if (sx < 0) {
497 sx = -sx;
498 }
499
500 fMode = mode;
501 fPaint = &paint;
502 fClip = NULL;
503 fRC = rc;
504 fRadius = SkScalarToFixed(SkScalarMul(width, sx)) >> 1;
505 return true;
506 }
507 }
508 return false;
509 }
510
chooseProc(SkBlitter ** blitterPtr)511 PtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) {
512 Proc proc = NULL;
513
514 SkBlitter* blitter = *blitterPtr;
515 if (fRC->isBW()) {
516 fClip = &fRC->bwRgn();
517 } else {
518 fWrapper.init(*fRC, blitter);
519 fClip = &fWrapper.getRgn();
520 blitter = fWrapper.getBlitter();
521 *blitterPtr = blitter;
522 }
523
524 // for our arrays
525 SkASSERT(0 == SkCanvas::kPoints_PointMode);
526 SkASSERT(1 == SkCanvas::kLines_PointMode);
527 SkASSERT(2 == SkCanvas::kPolygon_PointMode);
528 SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode);
529
530 if (fPaint->isAntiAlias()) {
531 if (0 == fPaint->getStrokeWidth()) {
532 static const Proc gAAProcs[] = {
533 aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc
534 };
535 proc = gAAProcs[fMode];
536 } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) {
537 SkASSERT(SkCanvas::kPoints_PointMode == fMode);
538 proc = aa_square_proc;
539 }
540 } else { // BW
541 if (fRadius <= SK_FixedHalf) { // small radii and hairline
542 if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) {
543 uint32_t value;
544 const SkBitmap* bm = blitter->justAnOpaqueColor(&value);
545 if (bm && SkBitmap::kRGB_565_Config == bm->config()) {
546 proc = bw_pt_rect_16_hair_proc;
547 } else if (bm && SkBitmap::kARGB_8888_Config == bm->config()) {
548 proc = bw_pt_rect_32_hair_proc;
549 } else {
550 proc = bw_pt_rect_hair_proc;
551 }
552 } else {
553 static Proc gBWProcs[] = {
554 bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc
555 };
556 proc = gBWProcs[fMode];
557 }
558 } else {
559 proc = bw_square_proc;
560 }
561 }
562 return proc;
563 }
564
bounder_points(SkBounder * bounder,SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint,const SkMatrix & matrix)565 static bool bounder_points(SkBounder* bounder, SkCanvas::PointMode mode,
566 size_t count, const SkPoint pts[],
567 const SkPaint& paint, const SkMatrix& matrix) {
568 SkIRect ibounds;
569 SkRect bounds;
570 SkScalar inset = paint.getStrokeWidth();
571
572 bounds.set(pts, count);
573 bounds.inset(-inset, -inset);
574 matrix.mapRect(&bounds);
575
576 bounds.roundOut(&ibounds);
577 return bounder->doIRect(ibounds);
578 }
579
580 // each of these costs 8-bytes of stack space, so don't make it too large
581 // must be even for lines/polygon to work
582 #define MAX_DEV_PTS 32
583
drawPoints(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint,bool forceUseDevice) const584 void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
585 const SkPoint pts[], const SkPaint& paint,
586 bool forceUseDevice) const {
587 // if we're in lines mode, force count to be even
588 if (SkCanvas::kLines_PointMode == mode) {
589 count &= ~(size_t)1;
590 }
591
592 if ((long)count <= 0) {
593 return;
594 }
595
596 SkASSERT(pts != NULL);
597 SkDEBUGCODE(this->validate();)
598
599 // nothing to draw
600 if (fRC->isEmpty()) {
601 return;
602 }
603
604 if (fBounder) {
605 if (!bounder_points(fBounder, mode, count, pts, paint, *fMatrix)) {
606 return;
607 }
608
609 // clear the bounder and call this again, so we don't invoke the bounder
610 // later if we happen to call ourselves for drawRect, drawPath, etc.
611 SkDraw noBounder(*this);
612 noBounder.fBounder = NULL;
613 noBounder.drawPoints(mode, count, pts, paint, forceUseDevice);
614 return;
615 }
616
617 PtProcRec rec;
618 if (!forceUseDevice && rec.init(mode, paint, fMatrix, fRC)) {
619 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
620
621 SkPoint devPts[MAX_DEV_PTS];
622 const SkMatrix* matrix = fMatrix;
623 SkBlitter* bltr = blitter.get();
624 PtProcRec::Proc proc = rec.chooseProc(&bltr);
625 // we have to back up subsequent passes if we're in polygon mode
626 const size_t backup = (SkCanvas::kPolygon_PointMode == mode);
627
628 do {
629 size_t n = count;
630 if (n > MAX_DEV_PTS) {
631 n = MAX_DEV_PTS;
632 }
633 matrix->mapPoints(devPts, pts, n);
634 proc(rec, devPts, n, bltr);
635 pts += n - backup;
636 SkASSERT(count >= n);
637 count -= n;
638 if (count > 0) {
639 count += backup;
640 }
641 } while (count != 0);
642 } else {
643 switch (mode) {
644 case SkCanvas::kPoints_PointMode: {
645 // temporarily mark the paint as filling.
646 SkPaint newPaint(paint);
647 newPaint.setStyle(SkPaint::kFill_Style);
648
649 SkScalar width = newPaint.getStrokeWidth();
650 SkScalar radius = SkScalarHalf(width);
651
652 if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) {
653 SkPath path;
654 SkMatrix preMatrix;
655
656 path.addCircle(0, 0, radius);
657 for (size_t i = 0; i < count; i++) {
658 preMatrix.setTranslate(pts[i].fX, pts[i].fY);
659 // pass true for the last point, since we can modify
660 // then path then
661 if (fDevice) {
662 fDevice->drawPath(*this, path, newPaint, &preMatrix,
663 (count-1) == i);
664 } else {
665 this->drawPath(path, newPaint, &preMatrix,
666 (count-1) == i);
667 }
668 }
669 } else {
670 SkRect r;
671
672 for (size_t i = 0; i < count; i++) {
673 r.fLeft = pts[i].fX - radius;
674 r.fTop = pts[i].fY - radius;
675 r.fRight = r.fLeft + width;
676 r.fBottom = r.fTop + width;
677 if (fDevice) {
678 fDevice->drawRect(*this, r, newPaint);
679 } else {
680 this->drawRect(r, newPaint);
681 }
682 }
683 }
684 break;
685 }
686 case SkCanvas::kLines_PointMode:
687 #ifndef SK_DISABLE_DASHING_OPTIMIZATION
688 if (2 == count && NULL != paint.getPathEffect()) {
689 // most likely a dashed line - see if it is one of the ones
690 // we can accelerate
691 SkStrokeRec rec(paint);
692 SkPathEffect::PointData pointData;
693
694 SkPath path;
695 path.moveTo(pts[0]);
696 path.lineTo(pts[1]);
697
698 SkRect cullRect = SkRect::Make(fRC->getBounds());
699
700 if (paint.getPathEffect()->asPoints(&pointData, path, rec,
701 *fMatrix, &cullRect)) {
702 // 'asPoints' managed to find some fast path
703
704 SkPaint newP(paint);
705 newP.setPathEffect(NULL);
706 newP.setStyle(SkPaint::kFill_Style);
707
708 if (!pointData.fFirst.isEmpty()) {
709 if (fDevice) {
710 fDevice->drawPath(*this, pointData.fFirst, newP);
711 } else {
712 this->drawPath(pointData.fFirst, newP);
713 }
714 }
715
716 if (!pointData.fLast.isEmpty()) {
717 if (fDevice) {
718 fDevice->drawPath(*this, pointData.fLast, newP);
719 } else {
720 this->drawPath(pointData.fLast, newP);
721 }
722 }
723
724 if (pointData.fSize.fX == pointData.fSize.fY) {
725 // The rest of the dashed line can just be drawn as points
726 SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth()));
727
728 if (SkPathEffect::PointData::kCircles_PointFlag & pointData.fFlags) {
729 newP.setStrokeCap(SkPaint::kRound_Cap);
730 } else {
731 newP.setStrokeCap(SkPaint::kButt_Cap);
732 }
733
734 if (fDevice) {
735 fDevice->drawPoints(*this,
736 SkCanvas::kPoints_PointMode,
737 pointData.fNumPoints,
738 pointData.fPoints,
739 newP);
740 } else {
741 this->drawPoints(SkCanvas::kPoints_PointMode,
742 pointData.fNumPoints,
743 pointData.fPoints,
744 newP,
745 forceUseDevice);
746 }
747 break;
748 } else {
749 // The rest of the dashed line must be drawn as rects
750 SkASSERT(!(SkPathEffect::PointData::kCircles_PointFlag &
751 pointData.fFlags));
752
753 SkRect r;
754
755 for (int i = 0; i < pointData.fNumPoints; ++i) {
756 r.set(pointData.fPoints[i].fX - pointData.fSize.fX,
757 pointData.fPoints[i].fY - pointData.fSize.fY,
758 pointData.fPoints[i].fX + pointData.fSize.fX,
759 pointData.fPoints[i].fY + pointData.fSize.fY);
760 if (fDevice) {
761 fDevice->drawRect(*this, r, newP);
762 } else {
763 this->drawRect(r, newP);
764 }
765 }
766 }
767
768 break;
769 }
770 }
771 #endif // DISABLE_DASHING_OPTIMIZATION
772 // couldn't take fast path so fall through!
773 case SkCanvas::kPolygon_PointMode: {
774 count -= 1;
775 SkPath path;
776 SkPaint p(paint);
777 p.setStyle(SkPaint::kStroke_Style);
778 size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1;
779 for (size_t i = 0; i < count; i += inc) {
780 path.moveTo(pts[i]);
781 path.lineTo(pts[i+1]);
782 if (fDevice) {
783 fDevice->drawPath(*this, path, p, NULL, true);
784 } else {
785 this->drawPath(path, p, NULL, true);
786 }
787 path.rewind();
788 }
789 break;
790 }
791 }
792 }
793 }
794
easy_rect_join(const SkPaint & paint,const SkMatrix & matrix,SkPoint * strokeSize)795 static bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix,
796 SkPoint* strokeSize) {
797 if (SkPaint::kMiter_Join != paint.getStrokeJoin() ||
798 paint.getStrokeMiter() < SK_ScalarSqrt2) {
799 return false;
800 }
801
802 SkASSERT(matrix.rectStaysRect());
803 SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() };
804 matrix.mapVectors(strokeSize, &pt, 1);
805 strokeSize->fX = SkScalarAbs(strokeSize->fX);
806 strokeSize->fY = SkScalarAbs(strokeSize->fY);
807 return true;
808 }
809
ComputeRectType(const SkPaint & paint,const SkMatrix & matrix,SkPoint * strokeSize)810 SkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint,
811 const SkMatrix& matrix,
812 SkPoint* strokeSize) {
813 RectType rtype;
814 const SkScalar width = paint.getStrokeWidth();
815 const bool zeroWidth = (0 == width);
816 SkPaint::Style style = paint.getStyle();
817
818 if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) {
819 style = SkPaint::kFill_Style;
820 }
821
822 if (paint.getPathEffect() || paint.getMaskFilter() ||
823 paint.getRasterizer() || !matrix.rectStaysRect() ||
824 SkPaint::kStrokeAndFill_Style == style) {
825 rtype = kPath_RectType;
826 } else if (SkPaint::kFill_Style == style) {
827 rtype = kFill_RectType;
828 } else if (zeroWidth) {
829 rtype = kHair_RectType;
830 } else if (easy_rect_join(paint, matrix, strokeSize)) {
831 rtype = kStroke_RectType;
832 } else {
833 rtype = kPath_RectType;
834 }
835 return rtype;
836 }
837
rect_points(const SkRect & r)838 static const SkPoint* rect_points(const SkRect& r) {
839 return SkTCast<const SkPoint*>(&r);
840 }
841
rect_points(SkRect & r)842 static SkPoint* rect_points(SkRect& r) {
843 return SkTCast<SkPoint*>(&r);
844 }
845
drawRect(const SkRect & rect,const SkPaint & paint) const846 void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const {
847 SkDEBUGCODE(this->validate();)
848
849 // nothing to draw
850 if (fRC->isEmpty()) {
851 return;
852 }
853
854 SkPoint strokeSize;
855 RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize);
856
857 if (kPath_RectType == rtype) {
858 SkPath tmp;
859 tmp.addRect(rect);
860 tmp.setFillType(SkPath::kWinding_FillType);
861 this->drawPath(tmp, paint, NULL, true);
862 return;
863 }
864
865 const SkMatrix& matrix = *fMatrix;
866 SkRect devRect;
867
868 // transform rect into devRect
869 matrix.mapPoints(rect_points(devRect), rect_points(rect), 2);
870 devRect.sort();
871
872 if (fBounder && !fBounder->doRect(devRect, paint)) {
873 return;
874 }
875
876 // look for the quick exit, before we build a blitter
877 SkIRect ir;
878 devRect.roundOut(&ir);
879 if (paint.getStyle() != SkPaint::kFill_Style) {
880 // extra space for hairlines
881 ir.inset(-1, -1);
882 }
883 if (fRC->quickReject(ir)) {
884 return;
885 }
886
887 SkDeviceLooper looper(*fBitmap, *fRC, ir, paint.isAntiAlias());
888 while (looper.next()) {
889 SkRect localDevRect;
890 looper.mapRect(&localDevRect, devRect);
891 SkMatrix localMatrix;
892 looper.mapMatrix(&localMatrix, matrix);
893
894 SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix,
895 paint);
896 const SkRasterClip& clip = looper.getRC();
897 SkBlitter* blitter = blitterStorage.get();
898
899 // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
900 // case we are also hairline (if we've gotten to here), which devolves to
901 // effectively just kFill
902 switch (rtype) {
903 case kFill_RectType:
904 if (paint.isAntiAlias()) {
905 SkScan::AntiFillRect(localDevRect, clip, blitter);
906 } else {
907 SkScan::FillRect(localDevRect, clip, blitter);
908 }
909 break;
910 case kStroke_RectType:
911 if (paint.isAntiAlias()) {
912 SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter);
913 } else {
914 SkScan::FrameRect(localDevRect, strokeSize, clip, blitter);
915 }
916 break;
917 case kHair_RectType:
918 if (paint.isAntiAlias()) {
919 SkScan::AntiHairRect(localDevRect, clip, blitter);
920 } else {
921 SkScan::HairRect(localDevRect, clip, blitter);
922 }
923 break;
924 default:
925 SkDEBUGFAIL("bad rtype");
926 }
927 }
928 }
929
drawDevMask(const SkMask & srcM,const SkPaint & paint) const930 void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const {
931 if (srcM.fBounds.isEmpty()) {
932 return;
933 }
934
935 const SkMask* mask = &srcM;
936
937 SkMask dstM;
938 if (paint.getMaskFilter() &&
939 paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) {
940 mask = &dstM;
941 } else {
942 dstM.fImage = NULL;
943 }
944 SkAutoMaskFreeImage ami(dstM.fImage);
945
946 if (fBounder && !fBounder->doIRect(mask->fBounds)) {
947 return;
948 }
949
950 SkAutoBlitterChoose blitterChooser(*fBitmap, *fMatrix, paint);
951 SkBlitter* blitter = blitterChooser.get();
952
953 SkAAClipBlitterWrapper wrapper;
954 const SkRegion* clipRgn;
955
956 if (fRC->isBW()) {
957 clipRgn = &fRC->bwRgn();
958 } else {
959 wrapper.init(*fRC, blitter);
960 clipRgn = &wrapper.getRgn();
961 blitter = wrapper.getBlitter();
962 }
963 blitter->blitMaskRegion(*mask, *clipRgn);
964 }
965
fast_len(const SkVector & vec)966 static SkScalar fast_len(const SkVector& vec) {
967 SkScalar x = SkScalarAbs(vec.fX);
968 SkScalar y = SkScalarAbs(vec.fY);
969 if (x < y) {
970 SkTSwap(x, y);
971 }
972 return x + SkScalarHalf(y);
973 }
974
xfermodeSupportsCoverageAsAlpha(SkXfermode * xfer)975 static bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) {
976 SkXfermode::Coeff dc;
977 if (!SkXfermode::AsCoeff(xfer, NULL, &dc)) {
978 return false;
979 }
980
981 switch (dc) {
982 case SkXfermode::kOne_Coeff:
983 case SkXfermode::kISA_Coeff:
984 case SkXfermode::kISC_Coeff:
985 return true;
986 default:
987 return false;
988 }
989 }
990
SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth,const SkMatrix & matrix,SkScalar * coverage)991 bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix,
992 SkScalar* coverage) {
993 SkASSERT(strokeWidth > 0);
994 // We need to try to fake a thick-stroke with a modulated hairline.
995
996 if (matrix.hasPerspective()) {
997 return false;
998 }
999
1000 SkVector src[2], dst[2];
1001 src[0].set(strokeWidth, 0);
1002 src[1].set(0, strokeWidth);
1003 matrix.mapVectors(dst, src, 2);
1004 SkScalar len0 = fast_len(dst[0]);
1005 SkScalar len1 = fast_len(dst[1]);
1006 if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
1007 if (NULL != coverage) {
1008 *coverage = SkScalarAve(len0, len1);
1009 }
1010 return true;
1011 }
1012 return false;
1013 }
1014
drawRRect(const SkRRect & rrect,const SkPaint & paint) const1015 void SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const {
1016 SkDEBUGCODE(this->validate());
1017
1018 if (fRC->isEmpty()) {
1019 return;
1020 }
1021
1022 {
1023 // TODO: Investigate optimizing these options. They are in the same
1024 // order as SkDraw::drawPath, which handles each case. It may be
1025 // that there is no way to optimize for these using the SkRRect path.
1026 SkScalar coverage;
1027 if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) {
1028 goto DRAW_PATH;
1029 }
1030
1031 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
1032 goto DRAW_PATH;
1033 }
1034
1035 if (paint.getRasterizer()) {
1036 goto DRAW_PATH;
1037 }
1038 }
1039
1040 if (paint.getMaskFilter()) {
1041 // Transform the rrect into device space.
1042 SkRRect devRRect;
1043 if (rrect.transform(*fMatrix, &devRRect)) {
1044 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
1045 if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC,
1046 fBounder, blitter.get(),
1047 SkPaint::kFill_Style)) {
1048 return; // filterRRect() called the blitter, so we're done
1049 }
1050 }
1051 }
1052
1053 DRAW_PATH:
1054 // Now fall back to the default case of using a path.
1055 SkPath path;
1056 path.addRRect(rrect);
1057 this->drawPath(path, paint, NULL, true);
1058 }
1059
drawPath(const SkPath & origSrcPath,const SkPaint & origPaint,const SkMatrix * prePathMatrix,bool pathIsMutable,bool drawCoverage) const1060 void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
1061 const SkMatrix* prePathMatrix, bool pathIsMutable,
1062 bool drawCoverage) const {
1063 SkDEBUGCODE(this->validate();)
1064
1065 // nothing to draw
1066 if (fRC->isEmpty()) {
1067 return;
1068 }
1069
1070 SkPath* pathPtr = (SkPath*)&origSrcPath;
1071 bool doFill = true;
1072 SkPath tmpPath;
1073 SkMatrix tmpMatrix;
1074 const SkMatrix* matrix = fMatrix;
1075
1076 if (prePathMatrix) {
1077 if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style ||
1078 origPaint.getRasterizer()) {
1079 SkPath* result = pathPtr;
1080
1081 if (!pathIsMutable) {
1082 result = &tmpPath;
1083 pathIsMutable = true;
1084 }
1085 pathPtr->transform(*prePathMatrix, result);
1086 pathPtr = result;
1087 } else {
1088 if (!tmpMatrix.setConcat(*matrix, *prePathMatrix)) {
1089 // overflow
1090 return;
1091 }
1092 matrix = &tmpMatrix;
1093 }
1094 }
1095 // at this point we're done with prePathMatrix
1096 SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
1097
1098 SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
1099
1100 {
1101 SkScalar coverage;
1102 if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
1103 if (SK_Scalar1 == coverage) {
1104 paint.writable()->setStrokeWidth(0);
1105 } else if (xfermodeSupportsCoverageAsAlpha(origPaint.getXfermode())) {
1106 U8CPU newAlpha;
1107 #if 0
1108 newAlpha = SkToU8(SkScalarRoundToInt(coverage *
1109 origPaint.getAlpha()));
1110 #else
1111 // this is the old technique, which we preserve for now so
1112 // we don't change previous results (testing)
1113 // the new way seems fine, its just (a tiny bit) different
1114 int scale = (int)SkScalarMul(coverage, 256);
1115 newAlpha = origPaint.getAlpha() * scale >> 8;
1116 #endif
1117 SkPaint* writablePaint = paint.writable();
1118 writablePaint->setStrokeWidth(0);
1119 writablePaint->setAlpha(newAlpha);
1120 }
1121 }
1122 }
1123
1124 if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) {
1125 SkRect cullRect;
1126 const SkRect* cullRectPtr = NULL;
1127 if (this->computeConservativeLocalClipBounds(&cullRect)) {
1128 cullRectPtr = &cullRect;
1129 }
1130 doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr);
1131 pathPtr = &tmpPath;
1132 }
1133
1134 if (paint->getRasterizer()) {
1135 SkMask mask;
1136 if (paint->getRasterizer()->rasterize(*pathPtr, *matrix,
1137 &fRC->getBounds(), paint->getMaskFilter(), &mask,
1138 SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
1139 this->drawDevMask(mask, *paint);
1140 SkMask::FreeImage(mask.fImage);
1141 }
1142 return;
1143 }
1144
1145 // avoid possibly allocating a new path in transform if we can
1146 SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
1147
1148 // transform the path into device space
1149 pathPtr->transform(*matrix, devPathPtr);
1150
1151 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, *paint, drawCoverage);
1152
1153 if (paint->getMaskFilter()) {
1154 SkPaint::Style style = doFill ? SkPaint::kFill_Style :
1155 SkPaint::kStroke_Style;
1156 if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC,
1157 fBounder, blitter.get(),
1158 style)) {
1159 return; // filterPath() called the blitter, so we're done
1160 }
1161 }
1162
1163 if (fBounder && !fBounder->doPath(*devPathPtr, *paint, doFill)) {
1164 return;
1165 }
1166
1167 void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*);
1168 if (doFill) {
1169 if (paint->isAntiAlias()) {
1170 proc = SkScan::AntiFillPath;
1171 } else {
1172 proc = SkScan::FillPath;
1173 }
1174 } else { // hairline
1175 if (paint->isAntiAlias()) {
1176 proc = SkScan::AntiHairPath;
1177 } else {
1178 proc = SkScan::HairPath;
1179 }
1180 }
1181 proc(*devPathPtr, *fRC, blitter.get());
1182 }
1183
1184 /** For the purposes of drawing bitmaps, if a matrix is "almost" translate
1185 go ahead and treat it as if it were, so that subsequent code can go fast.
1186 */
just_translate(const SkMatrix & matrix,const SkBitmap & bitmap)1187 static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
1188 unsigned bits = 0; // TODO: find a way to allow the caller to tell us to
1189 // respect filtering.
1190 return SkTreatAsSprite(matrix, bitmap.width(), bitmap.height(), bits);
1191 }
1192
drawBitmapAsMask(const SkBitmap & bitmap,const SkPaint & paint) const1193 void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
1194 const SkPaint& paint) const {
1195 SkASSERT(bitmap.config() == SkBitmap::kA8_Config);
1196
1197 if (just_translate(*fMatrix, bitmap)) {
1198 int ix = SkScalarRound(fMatrix->getTranslateX());
1199 int iy = SkScalarRound(fMatrix->getTranslateY());
1200
1201 SkAutoLockPixels alp(bitmap);
1202 if (!bitmap.readyToDraw()) {
1203 return;
1204 }
1205
1206 SkMask mask;
1207 mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1208 mask.fFormat = SkMask::kA8_Format;
1209 mask.fRowBytes = SkToU32(bitmap.rowBytes());
1210 mask.fImage = bitmap.getAddr8(0, 0);
1211
1212 this->drawDevMask(mask, paint);
1213 } else { // need to xform the bitmap first
1214 SkRect r;
1215 SkMask mask;
1216
1217 r.set(0, 0,
1218 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
1219 fMatrix->mapRect(&r);
1220 r.round(&mask.fBounds);
1221
1222 // set the mask's bounds to the transformed bitmap-bounds,
1223 // clipped to the actual device
1224 {
1225 SkIRect devBounds;
1226 devBounds.set(0, 0, fBitmap->width(), fBitmap->height());
1227 // need intersect(l, t, r, b) on irect
1228 if (!mask.fBounds.intersect(devBounds)) {
1229 return;
1230 }
1231 }
1232
1233 mask.fFormat = SkMask::kA8_Format;
1234 mask.fRowBytes = SkAlign4(mask.fBounds.width());
1235 size_t size = mask.computeImageSize();
1236 if (0 == size) {
1237 // the mask is too big to allocated, draw nothing
1238 return;
1239 }
1240
1241 // allocate (and clear) our temp buffer to hold the transformed bitmap
1242 SkAutoMalloc storage(size);
1243 mask.fImage = (uint8_t*)storage.get();
1244 memset(mask.fImage, 0, size);
1245
1246 // now draw our bitmap(src) into mask(dst), transformed by the matrix
1247 {
1248 SkBitmap device;
1249 device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
1250 mask.fBounds.height(), mask.fRowBytes);
1251 device.setPixels(mask.fImage);
1252
1253 SkCanvas c(device);
1254 // need the unclipped top/left for the translate
1255 c.translate(-SkIntToScalar(mask.fBounds.fLeft),
1256 -SkIntToScalar(mask.fBounds.fTop));
1257 c.concat(*fMatrix);
1258
1259 // We can't call drawBitmap, or we'll infinitely recurse. Instead
1260 // we manually build a shader and draw that into our new mask
1261 SkPaint tmpPaint;
1262 tmpPaint.setFlags(paint.getFlags());
1263 SkAutoBitmapShaderInstall install(bitmap, tmpPaint);
1264 SkRect rr;
1265 rr.set(0, 0, SkIntToScalar(bitmap.width()),
1266 SkIntToScalar(bitmap.height()));
1267 c.drawRect(rr, install.paintWithShader());
1268 }
1269 this->drawDevMask(mask, paint);
1270 }
1271 }
1272
clipped_out(const SkMatrix & m,const SkRasterClip & c,const SkRect & srcR)1273 static bool clipped_out(const SkMatrix& m, const SkRasterClip& c,
1274 const SkRect& srcR) {
1275 SkRect dstR;
1276 SkIRect devIR;
1277
1278 m.mapRect(&dstR, srcR);
1279 dstR.roundOut(&devIR);
1280 return c.quickReject(devIR);
1281 }
1282
clipped_out(const SkMatrix & matrix,const SkRasterClip & clip,int width,int height)1283 static bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip,
1284 int width, int height) {
1285 SkRect r;
1286 r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
1287 return clipped_out(matrix, clip, r);
1288 }
1289
clipHandlesSprite(const SkRasterClip & clip,int x,int y,const SkBitmap & bitmap)1290 static bool clipHandlesSprite(const SkRasterClip& clip, int x, int y,
1291 const SkBitmap& bitmap) {
1292 return clip.isBW() ||
1293 clip.quickContains(x, y, x + bitmap.width(), y + bitmap.height());
1294 }
1295
drawBitmap(const SkBitmap & bitmap,const SkMatrix & prematrix,const SkPaint & origPaint) const1296 void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
1297 const SkPaint& origPaint) const {
1298 SkDEBUGCODE(this->validate();)
1299
1300 // nothing to draw
1301 if (fRC->isEmpty() ||
1302 bitmap.width() == 0 || bitmap.height() == 0 ||
1303 bitmap.config() == SkBitmap::kNo_Config) {
1304 return;
1305 }
1306
1307 SkPaint paint(origPaint);
1308 paint.setStyle(SkPaint::kFill_Style);
1309
1310 SkMatrix matrix;
1311 if (!matrix.setConcat(*fMatrix, prematrix)) {
1312 return;
1313 }
1314
1315 if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) {
1316 return;
1317 }
1318
1319 if (fBounder && just_translate(matrix, bitmap)) {
1320 SkIRect ir;
1321 int32_t ix = SkScalarRound(matrix.getTranslateX());
1322 int32_t iy = SkScalarRound(matrix.getTranslateY());
1323 ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1324 if (!fBounder->doIRect(ir)) {
1325 return;
1326 }
1327 }
1328
1329 if (bitmap.config() != SkBitmap::kA8_Config &&
1330 just_translate(matrix, bitmap)) {
1331 //
1332 // It is safe to call lock pixels now, since we know the matrix is
1333 // (more or less) identity.
1334 //
1335 SkAutoLockPixels alp(bitmap);
1336 if (!bitmap.readyToDraw()) {
1337 return;
1338 }
1339 int ix = SkScalarRound(matrix.getTranslateX());
1340 int iy = SkScalarRound(matrix.getTranslateY());
1341 if (clipHandlesSprite(*fRC, ix, iy, bitmap)) {
1342 uint32_t storage[kBlitterStorageLongCount];
1343 SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1344 ix, iy, storage, sizeof(storage));
1345 if (blitter) {
1346 SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage);
1347
1348 SkIRect ir;
1349 ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1350
1351 SkScan::FillIRect(ir, *fRC, blitter);
1352 return;
1353 }
1354 }
1355 }
1356
1357 // now make a temp draw on the stack, and use it
1358 //
1359 SkDraw draw(*this);
1360 draw.fMatrix = &matrix;
1361
1362 if (bitmap.config() == SkBitmap::kA8_Config) {
1363 draw.drawBitmapAsMask(bitmap, paint);
1364 } else {
1365 SkAutoBitmapShaderInstall install(bitmap, paint);
1366
1367 SkRect r;
1368 r.set(0, 0, SkIntToScalar(bitmap.width()),
1369 SkIntToScalar(bitmap.height()));
1370 // is this ok if paint has a rasterizer?
1371 draw.drawRect(r, install.paintWithShader());
1372 }
1373 }
1374
drawSprite(const SkBitmap & bitmap,int x,int y,const SkPaint & origPaint) const1375 void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
1376 const SkPaint& origPaint) const {
1377 SkDEBUGCODE(this->validate();)
1378
1379 // nothing to draw
1380 if (fRC->isEmpty() ||
1381 bitmap.width() == 0 || bitmap.height() == 0 ||
1382 bitmap.config() == SkBitmap::kNo_Config) {
1383 return;
1384 }
1385
1386 SkIRect bounds;
1387 bounds.set(x, y, x + bitmap.width(), y + bitmap.height());
1388
1389 if (fRC->quickReject(bounds)) {
1390 return; // nothing to draw
1391 }
1392
1393 SkPaint paint(origPaint);
1394 paint.setStyle(SkPaint::kFill_Style);
1395
1396 if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) {
1397 uint32_t storage[kBlitterStorageLongCount];
1398 SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1399 x, y, storage, sizeof(storage));
1400
1401 if (blitter) {
1402 SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage);
1403
1404 if (fBounder && !fBounder->doIRect(bounds)) {
1405 return;
1406 }
1407
1408 SkScan::FillIRect(bounds, *fRC, blitter);
1409 return;
1410 }
1411 }
1412
1413 SkAutoBitmapShaderInstall install(bitmap, paint);
1414 const SkPaint& shaderPaint = install.paintWithShader();
1415
1416 SkMatrix matrix;
1417 SkRect r;
1418
1419 // get a scalar version of our rect
1420 r.set(bounds);
1421
1422 // tell the shader our offset
1423 matrix.setTranslate(r.fLeft, r.fTop);
1424 shaderPaint.getShader()->setLocalMatrix(matrix);
1425
1426 SkDraw draw(*this);
1427 matrix.reset();
1428 draw.fMatrix = &matrix;
1429 // call ourself with a rect
1430 // is this OK if paint has a rasterizer?
1431 draw.drawRect(r, shaderPaint);
1432 }
1433
1434 ///////////////////////////////////////////////////////////////////////////////
1435
1436 #include "SkScalerContext.h"
1437 #include "SkGlyphCache.h"
1438 #include "SkTextToPathIter.h"
1439 #include "SkUtils.h"
1440
measure_text(SkGlyphCache * cache,SkDrawCacheProc glyphCacheProc,const char text[],size_t byteLength,SkVector * stopVector)1441 static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
1442 const char text[], size_t byteLength, SkVector* stopVector) {
1443 SkFixed x = 0, y = 0;
1444 const char* stop = text + byteLength;
1445
1446 SkAutoKern autokern;
1447
1448 while (text < stop) {
1449 // don't need x, y here, since all subpixel variants will have the
1450 // same advance
1451 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1452
1453 x += autokern.adjust(glyph) + glyph.fAdvanceX;
1454 y += glyph.fAdvanceY;
1455 }
1456 stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
1457
1458 SkASSERT(text == stop);
1459 }
1460
drawText_asPaths(const char text[],size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint) const1461 void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
1462 SkScalar x, SkScalar y,
1463 const SkPaint& paint) const {
1464 SkDEBUGCODE(this->validate();)
1465
1466 SkTextToPathIter iter(text, byteLength, paint, true);
1467
1468 SkMatrix matrix;
1469 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1470 matrix.postTranslate(x, y);
1471
1472 const SkPath* iterPath;
1473 SkScalar xpos, prevXPos = 0;
1474
1475 while (iter.next(&iterPath, &xpos)) {
1476 matrix.postTranslate(xpos - prevXPos, 0);
1477 if (iterPath) {
1478 const SkPaint& pnt = iter.getPaint();
1479 if (fDevice) {
1480 fDevice->drawPath(*this, *iterPath, pnt, &matrix, false);
1481 } else {
1482 this->drawPath(*iterPath, pnt, &matrix, false);
1483 }
1484 }
1485 prevXPos = xpos;
1486 }
1487 }
1488
1489 // disable warning : local variable used without having been initialized
1490 #if defined _WIN32 && _MSC_VER >= 1300
1491 #pragma warning ( push )
1492 #pragma warning ( disable : 4701 )
1493 #endif
1494
1495 //////////////////////////////////////////////////////////////////////////////
1496
D1G_NoBounder_RectClip(const SkDraw1Glyph & state,SkFixed fx,SkFixed fy,const SkGlyph & glyph)1497 static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
1498 SkFixed fx, SkFixed fy,
1499 const SkGlyph& glyph) {
1500 int left = SkFixedFloor(fx);
1501 int top = SkFixedFloor(fy);
1502 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1503 SkASSERT(NULL == state.fBounder);
1504 SkASSERT((NULL == state.fClip && state.fAAClip) ||
1505 (state.fClip && NULL == state.fAAClip && state.fClip->isRect()));
1506
1507 left += glyph.fLeft;
1508 top += glyph.fTop;
1509
1510 int right = left + glyph.fWidth;
1511 int bottom = top + glyph.fHeight;
1512
1513 SkMask mask;
1514 SkIRect storage;
1515 SkIRect* bounds = &mask.fBounds;
1516
1517 mask.fBounds.set(left, top, right, bottom);
1518
1519 // this extra test is worth it, assuming that most of the time it succeeds
1520 // since we can avoid writing to storage
1521 if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
1522 if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
1523 return;
1524 bounds = &storage;
1525 }
1526
1527 uint8_t* aa = (uint8_t*)glyph.fImage;
1528 if (NULL == aa) {
1529 aa = (uint8_t*)state.fCache->findImage(glyph);
1530 if (NULL == aa) {
1531 return; // can't rasterize glyph
1532 }
1533 }
1534
1535 mask.fRowBytes = glyph.rowBytes();
1536 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1537 mask.fImage = aa;
1538 state.blitMask(mask, *bounds);
1539 }
1540
D1G_NoBounder_RgnClip(const SkDraw1Glyph & state,SkFixed fx,SkFixed fy,const SkGlyph & glyph)1541 static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
1542 SkFixed fx, SkFixed fy,
1543 const SkGlyph& glyph) {
1544 int left = SkFixedFloor(fx);
1545 int top = SkFixedFloor(fy);
1546 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1547 SkASSERT(!state.fClip->isRect());
1548 SkASSERT(NULL == state.fBounder);
1549
1550 SkMask mask;
1551
1552 left += glyph.fLeft;
1553 top += glyph.fTop;
1554
1555 mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1556 SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1557
1558 if (!clipper.done()) {
1559 const SkIRect& cr = clipper.rect();
1560 const uint8_t* aa = (const uint8_t*)glyph.fImage;
1561 if (NULL == aa) {
1562 aa = (uint8_t*)state.fCache->findImage(glyph);
1563 if (NULL == aa) {
1564 return;
1565 }
1566 }
1567
1568 mask.fRowBytes = glyph.rowBytes();
1569 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1570 mask.fImage = (uint8_t*)aa;
1571 do {
1572 state.blitMask(mask, cr);
1573 clipper.next();
1574 } while (!clipper.done());
1575 }
1576 }
1577
D1G_Bounder(const SkDraw1Glyph & state,SkFixed fx,SkFixed fy,const SkGlyph & glyph)1578 static void D1G_Bounder(const SkDraw1Glyph& state,
1579 SkFixed fx, SkFixed fy,
1580 const SkGlyph& glyph) {
1581 int left = SkFixedFloor(fx);
1582 int top = SkFixedFloor(fy);
1583 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1584
1585 SkMask mask;
1586
1587 left += glyph.fLeft;
1588 top += glyph.fTop;
1589
1590 mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1591 SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1592
1593 if (!clipper.done()) {
1594 const SkIRect& cr = clipper.rect();
1595 const uint8_t* aa = (const uint8_t*)glyph.fImage;
1596 if (NULL == aa) {
1597 aa = (uint8_t*)state.fCache->findImage(glyph);
1598 if (NULL == aa) {
1599 return;
1600 }
1601 }
1602
1603 // we need to pass the origin, which we approximate with our
1604 // (unadjusted) left,top coordinates (the caller called fixedfloor)
1605 if (state.fBounder->doIRectGlyph(cr,
1606 left - glyph.fLeft,
1607 top - glyph.fTop, glyph)) {
1608 mask.fRowBytes = glyph.rowBytes();
1609 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1610 mask.fImage = (uint8_t*)aa;
1611 do {
1612 state.blitMask(mask, cr);
1613 clipper.next();
1614 } while (!clipper.done());
1615 }
1616 }
1617 }
1618
D1G_Bounder_AAClip(const SkDraw1Glyph & state,SkFixed fx,SkFixed fy,const SkGlyph & glyph)1619 static void D1G_Bounder_AAClip(const SkDraw1Glyph& state,
1620 SkFixed fx, SkFixed fy,
1621 const SkGlyph& glyph) {
1622 int left = SkFixedFloor(fx);
1623 int top = SkFixedFloor(fy);
1624 SkIRect bounds;
1625 bounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1626
1627 if (state.fBounder->doIRectGlyph(bounds, left, top, glyph)) {
1628 D1G_NoBounder_RectClip(state, fx, fy, glyph);
1629 }
1630 }
1631
hasCustomD1GProc(const SkDraw & draw)1632 static bool hasCustomD1GProc(const SkDraw& draw) {
1633 return draw.fProcs && draw.fProcs->fD1GProc;
1634 }
1635
needsRasterTextBlit(const SkDraw & draw)1636 static bool needsRasterTextBlit(const SkDraw& draw) {
1637 return !hasCustomD1GProc(draw);
1638 }
1639
init(const SkDraw * draw,SkBlitter * blitter,SkGlyphCache * cache,const SkPaint & pnt)1640 SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter,
1641 SkGlyphCache* cache, const SkPaint& pnt) {
1642 fDraw = draw;
1643 fBounder = draw->fBounder;
1644 fBlitter = blitter;
1645 fCache = cache;
1646 fPaint = &pnt;
1647
1648 if (cache->isSubpixel()) {
1649 fHalfSampleX = fHalfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
1650 } else {
1651 fHalfSampleX = fHalfSampleY = SK_FixedHalf;
1652 }
1653
1654 if (hasCustomD1GProc(*draw)) {
1655 // todo: fix this assumption about clips w/ custom
1656 fClip = draw->fClip;
1657 fClipBounds = fClip->getBounds();
1658 return draw->fProcs->fD1GProc;
1659 }
1660
1661 if (draw->fRC->isBW()) {
1662 fAAClip = NULL;
1663 fClip = &draw->fRC->bwRgn();
1664 fClipBounds = fClip->getBounds();
1665 if (NULL == fBounder) {
1666 if (fClip->isRect()) {
1667 return D1G_NoBounder_RectClip;
1668 } else {
1669 return D1G_NoBounder_RgnClip;
1670 }
1671 } else {
1672 return D1G_Bounder;
1673 }
1674 } else { // aaclip
1675 fAAClip = &draw->fRC->aaRgn();
1676 fClip = NULL;
1677 fClipBounds = fAAClip->getBounds();
1678 if (NULL == fBounder) {
1679 return D1G_NoBounder_RectClip;
1680 } else {
1681 return D1G_Bounder_AAClip;
1682 }
1683 }
1684 }
1685
blitMaskAsSprite(const SkMask & mask) const1686 void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
1687 SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
1688
1689 SkBitmap bm;
1690 bm.setConfig(SkBitmap::kARGB_8888_Config,
1691 mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
1692 bm.setPixels((SkPMColor*)mask.fImage);
1693
1694 fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
1695 }
1696
1697 ///////////////////////////////////////////////////////////////////////////////
1698
drawText(const char text[],size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint) const1699 void SkDraw::drawText(const char text[], size_t byteLength,
1700 SkScalar x, SkScalar y, const SkPaint& paint) const {
1701 SkASSERT(byteLength == 0 || text != NULL);
1702
1703 SkDEBUGCODE(this->validate();)
1704
1705 // nothing to draw
1706 if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1707 return;
1708 }
1709
1710 // SkScalarRec doesn't currently have a way of representing hairline stroke and
1711 // will fill if its frame-width is 0.
1712 if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1713 this->drawText_asPaths(text, byteLength, x, y, paint);
1714 return;
1715 }
1716
1717 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1718
1719 #if SK_DISTANCEFIELD_FONTS
1720 const SkMatrix* ctm = fMatrix;
1721 const SkPaint* paintRef = &paint;
1722 SkPaint paintCopy;
1723 uint32_t procFlags = fProcs ? fProcs->fFlags : 0;
1724 if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
1725 paintCopy = paint;
1726 paintCopy.setTextSize(SkDrawProcs::kBaseDFFontSize);
1727 paintCopy.setLCDRenderText(false);
1728 paintRef = &paintCopy;
1729 }
1730 if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) {
1731 ctm = NULL;
1732 }
1733 SkAutoGlyphCache autoCache(*paintRef, &fDevice->fLeakyProperties, ctm);
1734 #else
1735 SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix);
1736 #endif
1737 SkGlyphCache* cache = autoCache.getCache();
1738
1739 // transform our starting point
1740 #if SK_DISTANCEFIELD_FONTS
1741 if (!(procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag))
1742 #endif
1743 {
1744 SkPoint loc;
1745 fMatrix->mapXY(x, y, &loc);
1746 x = loc.fX;
1747 y = loc.fY;
1748 }
1749
1750 // need to measure first
1751 if (paint.getTextAlign() != SkPaint::kLeft_Align) {
1752 SkVector stop;
1753
1754 measure_text(cache, glyphCacheProc, text, byteLength, &stop);
1755
1756 SkScalar stopX = stop.fX;
1757 SkScalar stopY = stop.fY;
1758
1759 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1760 stopX = SkScalarHalf(stopX);
1761 stopY = SkScalarHalf(stopY);
1762 }
1763 x -= stopX;
1764 y -= stopY;
1765 }
1766
1767 const char* stop = text + byteLength;
1768
1769 SkAAClipBlitter aaBlitter;
1770 SkAutoBlitterChoose blitterChooser;
1771 SkBlitter* blitter = NULL;
1772 if (needsRasterTextBlit(*this)) {
1773 blitterChooser.choose(*fBitmap, *fMatrix, paint);
1774 blitter = blitterChooser.get();
1775 if (fRC->isAA()) {
1776 aaBlitter.init(blitter, &fRC->aaRgn());
1777 blitter = &aaBlitter;
1778 }
1779 }
1780
1781 SkAutoKern autokern;
1782 SkDraw1Glyph d1g;
1783 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
1784
1785 SkFixed fxMask = ~0;
1786 SkFixed fyMask = ~0;
1787 if (cache->isSubpixel()) {
1788 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
1789 if (kX_SkAxisAlignment == baseline) {
1790 fyMask = 0;
1791 d1g.fHalfSampleY = SK_FixedHalf;
1792 } else if (kY_SkAxisAlignment == baseline) {
1793 fxMask = 0;
1794 d1g.fHalfSampleX = SK_FixedHalf;
1795 }
1796 }
1797
1798 SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX;
1799 SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY;
1800
1801 #if SK_DISTANCEFIELD_FONTS
1802 SkFixed fixedScale;
1803 if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
1804 fixedScale = SkScalarToFixed(paint.getTextSize()/(float)SkDrawProcs::kBaseDFFontSize);
1805 }
1806 #endif
1807 while (text < stop) {
1808 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
1809
1810 #if SK_DISTANCEFIELD_FONTS
1811 if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
1812 fx += SkFixedMul_portable(autokern.adjust(glyph), fixedScale);
1813 } else {
1814 fx += autokern.adjust(glyph);
1815 }
1816 #else
1817 fx += autokern.adjust(glyph);
1818 #endif
1819
1820 if (glyph.fWidth) {
1821 proc(d1g, fx, fy, glyph);
1822 }
1823
1824 #if SK_DISTANCEFIELD_FONTS
1825 if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
1826 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
1827 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
1828 } else {
1829 fx += glyph.fAdvanceX;
1830 fy += glyph.fAdvanceY;
1831 }
1832 #else
1833 fx += glyph.fAdvanceX;
1834 fy += glyph.fAdvanceY;
1835 #endif
1836 }
1837 }
1838
1839 // last parameter is interpreted as SkFixed [x, y]
1840 // return the fixed position, which may be rounded or not by the caller
1841 // e.g. subpixel doesn't round
1842 typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
1843
leftAlignProc(const SkPoint & loc,const SkGlyph & glyph,SkIPoint * dst)1844 static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
1845 dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
1846 }
1847
centerAlignProc(const SkPoint & loc,const SkGlyph & glyph,SkIPoint * dst)1848 static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
1849 dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
1850 SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
1851 }
1852
rightAlignProc(const SkPoint & loc,const SkGlyph & glyph,SkIPoint * dst)1853 static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
1854 dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
1855 SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
1856 }
1857
pick_align_proc(SkPaint::Align align)1858 static AlignProc pick_align_proc(SkPaint::Align align) {
1859 static const AlignProc gProcs[] = {
1860 leftAlignProc, centerAlignProc, rightAlignProc
1861 };
1862
1863 SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
1864
1865 return gProcs[align];
1866 }
1867
1868 typedef void (*AlignProc_scalar)(const SkPoint&, const SkGlyph&, SkPoint*);
1869
leftAlignProc_scalar(const SkPoint & loc,const SkGlyph & glyph,SkPoint * dst)1870 static void leftAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
1871 dst->set(loc.fX, loc.fY);
1872 }
1873
centerAlignProc_scalar(const SkPoint & loc,const SkGlyph & glyph,SkPoint * dst)1874 static void centerAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
1875 dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX >> 1),
1876 loc.fY - SkFixedToScalar(glyph.fAdvanceY >> 1));
1877 }
1878
rightAlignProc_scalar(const SkPoint & loc,const SkGlyph & glyph,SkPoint * dst)1879 static void rightAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
1880 dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX),
1881 loc.fY - SkFixedToScalar(glyph.fAdvanceY));
1882 }
1883
pick_align_proc_scalar(SkPaint::Align align)1884 static AlignProc_scalar pick_align_proc_scalar(SkPaint::Align align) {
1885 static const AlignProc_scalar gProcs[] = {
1886 leftAlignProc_scalar, centerAlignProc_scalar, rightAlignProc_scalar
1887 };
1888
1889 SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
1890
1891 return gProcs[align];
1892 }
1893
1894 class TextMapState {
1895 public:
1896 mutable SkPoint fLoc;
1897
TextMapState(const SkMatrix & matrix,SkScalar y)1898 TextMapState(const SkMatrix& matrix, SkScalar y)
1899 : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
1900
1901 typedef void (*Proc)(const TextMapState&, const SkScalar pos[]);
1902
1903 Proc pickProc(int scalarsPerPosition);
1904
1905 private:
1906 const SkMatrix& fMatrix;
1907 SkMatrix::MapXYProc fProc;
1908 SkScalar fY; // ignored by MapXYProc
1909 // these are only used by Only... procs
1910 SkScalar fScaleX, fTransX, fTransformedY;
1911
MapXProc(const TextMapState & state,const SkScalar pos[])1912 static void MapXProc(const TextMapState& state, const SkScalar pos[]) {
1913 state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
1914 }
1915
MapXYProc(const TextMapState & state,const SkScalar pos[])1916 static void MapXYProc(const TextMapState& state, const SkScalar pos[]) {
1917 state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
1918 }
1919
MapOnlyScaleXProc(const TextMapState & state,const SkScalar pos[])1920 static void MapOnlyScaleXProc(const TextMapState& state,
1921 const SkScalar pos[]) {
1922 state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
1923 state.fTransformedY);
1924 }
1925
MapOnlyTransXProc(const TextMapState & state,const SkScalar pos[])1926 static void MapOnlyTransXProc(const TextMapState& state,
1927 const SkScalar pos[]) {
1928 state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
1929 }
1930 };
1931
pickProc(int scalarsPerPosition)1932 TextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) {
1933 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1934
1935 if (1 == scalarsPerPosition) {
1936 unsigned mtype = fMatrix.getType();
1937 if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
1938 return MapXProc;
1939 } else {
1940 fScaleX = fMatrix.getScaleX();
1941 fTransX = fMatrix.getTranslateX();
1942 fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
1943 fMatrix.getTranslateY();
1944 return (mtype & SkMatrix::kScale_Mask) ?
1945 MapOnlyScaleXProc : MapOnlyTransXProc;
1946 }
1947 } else {
1948 return MapXYProc;
1949 }
1950 }
1951
1952 //////////////////////////////////////////////////////////////////////////////
1953
drawPosText_asPaths(const char text[],size_t byteLength,const SkScalar pos[],SkScalar constY,int scalarsPerPosition,const SkPaint & origPaint) const1954 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
1955 const SkScalar pos[], SkScalar constY,
1956 int scalarsPerPosition,
1957 const SkPaint& origPaint) const {
1958 // setup our std paint, in hopes of getting hits in the cache
1959 SkPaint paint(origPaint);
1960 SkScalar matrixScale = paint.setupForAsPaths();
1961
1962 SkMatrix matrix;
1963 matrix.setScale(matrixScale, matrixScale);
1964
1965 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1966 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1967 SkGlyphCache* cache = autoCache.getCache();
1968
1969 const char* stop = text + byteLength;
1970 AlignProc_scalar alignProc = pick_align_proc_scalar(paint.getTextAlign());
1971 TextMapState tms(SkMatrix::I(), constY);
1972 TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
1973
1974 while (text < stop) {
1975 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1976 if (glyph.fWidth) {
1977 const SkPath* path = cache->findPath(glyph);
1978 if (path) {
1979 tmsProc(tms, pos);
1980 SkPoint loc;
1981 alignProc(tms.fLoc, glyph, &loc);
1982
1983 matrix[SkMatrix::kMTransX] = loc.fX;
1984 matrix[SkMatrix::kMTransY] = loc.fY;
1985 if (fDevice) {
1986 fDevice->drawPath(*this, *path, paint, &matrix, false);
1987 } else {
1988 this->drawPath(*path, paint, &matrix, false);
1989 }
1990 }
1991 }
1992 pos += scalarsPerPosition;
1993 }
1994 }
1995
drawPosText(const char text[],size_t byteLength,const SkScalar pos[],SkScalar constY,int scalarsPerPosition,const SkPaint & paint) const1996 void SkDraw::drawPosText(const char text[], size_t byteLength,
1997 const SkScalar pos[], SkScalar constY,
1998 int scalarsPerPosition, const SkPaint& paint) const {
1999 SkASSERT(byteLength == 0 || text != NULL);
2000 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
2001
2002 SkDEBUGCODE(this->validate();)
2003
2004 // nothing to draw
2005 if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
2006 return;
2007 }
2008
2009 if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
2010 this->drawPosText_asPaths(text, byteLength, pos, constY,
2011 scalarsPerPosition, paint);
2012 return;
2013 }
2014
2015 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
2016 #if SK_DISTANCEFIELD_FONTS
2017 const SkMatrix* ctm = fMatrix;
2018 const SkPaint* paintRef = &paint;
2019 SkPaint paintCopy;
2020 uint32_t procFlags = fProcs ? fProcs->fFlags : 0;
2021 if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
2022 paintCopy = paint;
2023 paintCopy.setTextSize(SkDrawProcs::kBaseDFFontSize);
2024 paintRef = &paintCopy;
2025 }
2026 if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) {
2027 ctm = &SkMatrix::I();
2028 }
2029 SkAutoGlyphCache autoCache(*paintRef, &fDevice->fLeakyProperties, ctm);
2030 #else
2031 SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix);
2032 #endif
2033 SkGlyphCache* cache = autoCache.getCache();
2034
2035 SkAAClipBlitterWrapper wrapper;
2036 SkAutoBlitterChoose blitterChooser;
2037 SkBlitter* blitter = NULL;
2038 if (needsRasterTextBlit(*this)) {
2039 blitterChooser.choose(*fBitmap, *fMatrix, paint);
2040 blitter = blitterChooser.get();
2041 if (fRC->isAA()) {
2042 wrapper.init(*fRC, blitter);
2043 blitter = wrapper.getBlitter();
2044 }
2045 }
2046
2047 const char* stop = text + byteLength;
2048 AlignProc alignProc = pick_align_proc(paint.getTextAlign());
2049 SkDraw1Glyph d1g;
2050 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
2051 #if SK_DISTANCEFIELD_FONTS
2052 TextMapState tms(*ctm, constY);
2053 #else
2054 TextMapState tms(*fMatrix, constY);
2055 #endif
2056 TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
2057
2058 if (cache->isSubpixel()) {
2059 // maybe we should skip the rounding if linearText is set
2060 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
2061
2062 SkFixed fxMask = ~0;
2063 SkFixed fyMask = ~0;
2064 if (kX_SkAxisAlignment == baseline) {
2065 fyMask = 0;
2066 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
2067 d1g.fHalfSampleY = SK_FixedHalf;
2068 #endif
2069 } else if (kY_SkAxisAlignment == baseline) {
2070 fxMask = 0;
2071 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
2072 d1g.fHalfSampleX = SK_FixedHalf;
2073 #endif
2074 }
2075
2076 if (SkPaint::kLeft_Align == paint.getTextAlign()) {
2077 while (text < stop) {
2078 #if SK_DISTANCEFIELD_FONTS
2079 if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) {
2080 tms.fLoc.fX = *pos;
2081 tms.fLoc.fY = *(pos+1);
2082 } else {
2083 tmsProc(tms, pos);
2084 }
2085 #else
2086 tmsProc(tms, pos);
2087 #endif
2088 SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX;
2089 SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY;
2090
2091 const SkGlyph& glyph = glyphCacheProc(cache, &text,
2092 fx & fxMask, fy & fyMask);
2093
2094 if (glyph.fWidth) {
2095 proc(d1g, fx, fy, glyph);
2096 }
2097 pos += scalarsPerPosition;
2098 }
2099 } else {
2100 while (text < stop) {
2101 const char* currentText = text;
2102 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
2103
2104 if (metricGlyph.fWidth) {
2105 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
2106 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
2107
2108 tmsProc(tms, pos);
2109 SkIPoint fixedLoc;
2110 alignProc(tms.fLoc, metricGlyph, &fixedLoc);
2111
2112 SkFixed fx = fixedLoc.fX + d1g.fHalfSampleX;
2113 SkFixed fy = fixedLoc.fY + d1g.fHalfSampleY;
2114
2115 // have to call again, now that we've been "aligned"
2116 const SkGlyph& glyph = glyphCacheProc(cache, ¤tText,
2117 fx & fxMask, fy & fyMask);
2118 // the assumption is that the metrics haven't changed
2119 SkASSERT(prevAdvX == glyph.fAdvanceX);
2120 SkASSERT(prevAdvY == glyph.fAdvanceY);
2121 SkASSERT(glyph.fWidth);
2122
2123 proc(d1g, fx, fy, glyph);
2124 }
2125 pos += scalarsPerPosition;
2126 }
2127 }
2128 } else { // not subpixel
2129 if (SkPaint::kLeft_Align == paint.getTextAlign()) {
2130 while (text < stop) {
2131 // the last 2 parameters are ignored
2132 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
2133
2134 if (glyph.fWidth) {
2135 tmsProc(tms, pos);
2136
2137 proc(d1g,
2138 SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf, //d1g.fHalfSampleX,
2139 SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf, //d1g.fHalfSampleY,
2140 glyph);
2141 }
2142 pos += scalarsPerPosition;
2143 }
2144 } else {
2145 while (text < stop) {
2146 // the last 2 parameters are ignored
2147 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
2148
2149 if (glyph.fWidth) {
2150 tmsProc(tms, pos);
2151
2152 SkIPoint fixedLoc;
2153 alignProc(tms.fLoc, glyph, &fixedLoc);
2154
2155 proc(d1g,
2156 fixedLoc.fX + SK_FixedHalf, //d1g.fHalfSampleX,
2157 fixedLoc.fY + SK_FixedHalf, //d1g.fHalfSampleY,
2158 glyph);
2159 }
2160 pos += scalarsPerPosition;
2161 }
2162 }
2163 }
2164 }
2165
2166 #if defined _WIN32 && _MSC_VER >= 1300
2167 #pragma warning ( pop )
2168 #endif
2169
2170 ///////////////////////////////////////////////////////////////////////////////
2171
2172 #include "SkPathMeasure.h"
2173
morphpoints(SkPoint dst[],const SkPoint src[],int count,SkPathMeasure & meas,const SkMatrix & matrix)2174 static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
2175 SkPathMeasure& meas, const SkMatrix& matrix) {
2176 SkMatrix::MapXYProc proc = matrix.getMapXYProc();
2177
2178 for (int i = 0; i < count; i++) {
2179 SkPoint pos;
2180 SkVector tangent;
2181
2182 proc(matrix, src[i].fX, src[i].fY, &pos);
2183 SkScalar sx = pos.fX;
2184 SkScalar sy = pos.fY;
2185
2186 if (!meas.getPosTan(sx, &pos, &tangent)) {
2187 // set to 0 if the measure failed, so that we just set dst == pos
2188 tangent.set(0, 0);
2189 }
2190
2191 /* This is the old way (that explains our approach but is way too slow
2192 SkMatrix matrix;
2193 SkPoint pt;
2194
2195 pt.set(sx, sy);
2196 matrix.setSinCos(tangent.fY, tangent.fX);
2197 matrix.preTranslate(-sx, 0);
2198 matrix.postTranslate(pos.fX, pos.fY);
2199 matrix.mapPoints(&dst[i], &pt, 1);
2200 */
2201 dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy),
2202 pos.fY + SkScalarMul(tangent.fX, sy));
2203 }
2204 }
2205
2206 /* TODO
2207
2208 Need differentially more subdivisions when the follow-path is curvy. Not sure how to
2209 determine that, but we need it. I guess a cheap answer is let the caller tell us,
2210 but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
2211 */
morphpath(SkPath * dst,const SkPath & src,SkPathMeasure & meas,const SkMatrix & matrix)2212 static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
2213 const SkMatrix& matrix) {
2214 SkPath::Iter iter(src, false);
2215 SkPoint srcP[4], dstP[3];
2216 SkPath::Verb verb;
2217
2218 while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
2219 switch (verb) {
2220 case SkPath::kMove_Verb:
2221 morphpoints(dstP, srcP, 1, meas, matrix);
2222 dst->moveTo(dstP[0]);
2223 break;
2224 case SkPath::kLine_Verb:
2225 // turn lines into quads to look bendy
2226 srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
2227 srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
2228 morphpoints(dstP, srcP, 2, meas, matrix);
2229 dst->quadTo(dstP[0], dstP[1]);
2230 break;
2231 case SkPath::kQuad_Verb:
2232 morphpoints(dstP, &srcP[1], 2, meas, matrix);
2233 dst->quadTo(dstP[0], dstP[1]);
2234 break;
2235 case SkPath::kCubic_Verb:
2236 morphpoints(dstP, &srcP[1], 3, meas, matrix);
2237 dst->cubicTo(dstP[0], dstP[1], dstP[2]);
2238 break;
2239 case SkPath::kClose_Verb:
2240 dst->close();
2241 break;
2242 default:
2243 SkDEBUGFAIL("unknown verb");
2244 break;
2245 }
2246 }
2247 }
2248
drawTextOnPath(const char text[],size_t byteLength,const SkPath & follow,const SkMatrix * matrix,const SkPaint & paint) const2249 void SkDraw::drawTextOnPath(const char text[], size_t byteLength,
2250 const SkPath& follow, const SkMatrix* matrix,
2251 const SkPaint& paint) const {
2252 SkASSERT(byteLength == 0 || text != NULL);
2253
2254 // nothing to draw
2255 if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
2256 return;
2257 }
2258
2259 SkTextToPathIter iter(text, byteLength, paint, true);
2260 SkPathMeasure meas(follow, false);
2261 SkScalar hOffset = 0;
2262
2263 // need to measure first
2264 if (paint.getTextAlign() != SkPaint::kLeft_Align) {
2265 SkScalar pathLen = meas.getLength();
2266 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2267 pathLen = SkScalarHalf(pathLen);
2268 }
2269 hOffset += pathLen;
2270 }
2271
2272 const SkPath* iterPath;
2273 SkScalar xpos;
2274 SkMatrix scaledMatrix;
2275 SkScalar scale = iter.getPathScale();
2276
2277 scaledMatrix.setScale(scale, scale);
2278
2279 while (iter.next(&iterPath, &xpos)) {
2280 if (iterPath) {
2281 SkPath tmp;
2282 SkMatrix m(scaledMatrix);
2283
2284 m.postTranslate(xpos + hOffset, 0);
2285 if (matrix) {
2286 m.postConcat(*matrix);
2287 }
2288 morphpath(&tmp, *iterPath, meas, m);
2289 if (fDevice) {
2290 fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true);
2291 } else {
2292 this->drawPath(tmp, iter.getPaint(), NULL, true);
2293 }
2294 }
2295 }
2296 }
2297
2298 ///////////////////////////////////////////////////////////////////////////////
2299
2300 struct VertState {
2301 int f0, f1, f2;
2302
VertStateVertState2303 VertState(int vCount, const uint16_t indices[], int indexCount)
2304 : fIndices(indices) {
2305 fCurrIndex = 0;
2306 if (indices) {
2307 fCount = indexCount;
2308 } else {
2309 fCount = vCount;
2310 }
2311 }
2312
2313 typedef bool (*Proc)(VertState*);
2314 Proc chooseProc(SkCanvas::VertexMode mode);
2315
2316 private:
2317 int fCount;
2318 int fCurrIndex;
2319 const uint16_t* fIndices;
2320
2321 static bool Triangles(VertState*);
2322 static bool TrianglesX(VertState*);
2323 static bool TriangleStrip(VertState*);
2324 static bool TriangleStripX(VertState*);
2325 static bool TriangleFan(VertState*);
2326 static bool TriangleFanX(VertState*);
2327 };
2328
Triangles(VertState * state)2329 bool VertState::Triangles(VertState* state) {
2330 int index = state->fCurrIndex;
2331 if (index + 3 > state->fCount) {
2332 return false;
2333 }
2334 state->f0 = index + 0;
2335 state->f1 = index + 1;
2336 state->f2 = index + 2;
2337 state->fCurrIndex = index + 3;
2338 return true;
2339 }
2340
TrianglesX(VertState * state)2341 bool VertState::TrianglesX(VertState* state) {
2342 const uint16_t* indices = state->fIndices;
2343 int index = state->fCurrIndex;
2344 if (index + 3 > state->fCount) {
2345 return false;
2346 }
2347 state->f0 = indices[index + 0];
2348 state->f1 = indices[index + 1];
2349 state->f2 = indices[index + 2];
2350 state->fCurrIndex = index + 3;
2351 return true;
2352 }
2353
TriangleStrip(VertState * state)2354 bool VertState::TriangleStrip(VertState* state) {
2355 int index = state->fCurrIndex;
2356 if (index + 3 > state->fCount) {
2357 return false;
2358 }
2359 state->f2 = index + 2;
2360 if (index & 1) {
2361 state->f0 = index + 1;
2362 state->f1 = index + 0;
2363 } else {
2364 state->f0 = index + 0;
2365 state->f1 = index + 1;
2366 }
2367 state->fCurrIndex = index + 1;
2368 return true;
2369 }
2370
TriangleStripX(VertState * state)2371 bool VertState::TriangleStripX(VertState* state) {
2372 const uint16_t* indices = state->fIndices;
2373 int index = state->fCurrIndex;
2374 if (index + 3 > state->fCount) {
2375 return false;
2376 }
2377 state->f2 = indices[index + 2];
2378 if (index & 1) {
2379 state->f0 = indices[index + 1];
2380 state->f1 = indices[index + 0];
2381 } else {
2382 state->f0 = indices[index + 0];
2383 state->f1 = indices[index + 1];
2384 }
2385 state->fCurrIndex = index + 1;
2386 return true;
2387 }
2388
TriangleFan(VertState * state)2389 bool VertState::TriangleFan(VertState* state) {
2390 int index = state->fCurrIndex;
2391 if (index + 3 > state->fCount) {
2392 return false;
2393 }
2394 state->f0 = 0;
2395 state->f1 = index + 1;
2396 state->f2 = index + 2;
2397 state->fCurrIndex = index + 1;
2398 return true;
2399 }
2400
TriangleFanX(VertState * state)2401 bool VertState::TriangleFanX(VertState* state) {
2402 const uint16_t* indices = state->fIndices;
2403 int index = state->fCurrIndex;
2404 if (index + 3 > state->fCount) {
2405 return false;
2406 }
2407 state->f0 = indices[0];
2408 state->f1 = indices[index + 1];
2409 state->f2 = indices[index + 2];
2410 state->fCurrIndex = index + 1;
2411 return true;
2412 }
2413
chooseProc(SkCanvas::VertexMode mode)2414 VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) {
2415 switch (mode) {
2416 case SkCanvas::kTriangles_VertexMode:
2417 return fIndices ? TrianglesX : Triangles;
2418 case SkCanvas::kTriangleStrip_VertexMode:
2419 return fIndices ? TriangleStripX : TriangleStrip;
2420 case SkCanvas::kTriangleFan_VertexMode:
2421 return fIndices ? TriangleFanX : TriangleFan;
2422 default:
2423 return NULL;
2424 }
2425 }
2426
2427 typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&,
2428 SkBlitter*);
2429
ChooseHairProc(bool doAntiAlias)2430 static HairProc ChooseHairProc(bool doAntiAlias) {
2431 return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
2432 }
2433
texture_to_matrix(const VertState & state,const SkPoint verts[],const SkPoint texs[],SkMatrix * matrix)2434 static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
2435 const SkPoint texs[], SkMatrix* matrix) {
2436 SkPoint src[3], dst[3];
2437
2438 src[0] = texs[state.f0];
2439 src[1] = texs[state.f1];
2440 src[2] = texs[state.f2];
2441 dst[0] = verts[state.f0];
2442 dst[1] = verts[state.f1];
2443 dst[2] = verts[state.f2];
2444 return matrix->setPolyToPoly(src, dst, 3);
2445 }
2446
2447 class SkTriColorShader : public SkShader {
2448 public:
SkTriColorShader()2449 SkTriColorShader() {}
2450
2451 bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
2452
2453 virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
2454
2455 SK_DEVELOPER_TO_STRING()
2456 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader)
2457
2458 protected:
SkTriColorShader(SkFlattenableReadBuffer & buffer)2459 SkTriColorShader(SkFlattenableReadBuffer& buffer) : SkShader(buffer) {}
2460
2461 private:
2462 SkMatrix fDstToUnit;
2463 SkPMColor fColors[3];
2464
2465 typedef SkShader INHERITED;
2466 };
2467
setup(const SkPoint pts[],const SkColor colors[],int index0,int index1,int index2)2468 bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[],
2469 int index0, int index1, int index2) {
2470
2471 fColors[0] = SkPreMultiplyColor(colors[index0]);
2472 fColors[1] = SkPreMultiplyColor(colors[index1]);
2473 fColors[2] = SkPreMultiplyColor(colors[index2]);
2474
2475 SkMatrix m, im;
2476 m.reset();
2477 m.set(0, pts[index1].fX - pts[index0].fX);
2478 m.set(1, pts[index2].fX - pts[index0].fX);
2479 m.set(2, pts[index0].fX);
2480 m.set(3, pts[index1].fY - pts[index0].fY);
2481 m.set(4, pts[index2].fY - pts[index0].fY);
2482 m.set(5, pts[index0].fY);
2483 if (!m.invert(&im)) {
2484 return false;
2485 }
2486 return fDstToUnit.setConcat(im, this->getTotalInverse());
2487 }
2488
2489 #include "SkColorPriv.h"
2490 #include "SkComposeShader.h"
2491
ScalarTo256(SkScalar v)2492 static int ScalarTo256(SkScalar v) {
2493 int scale = SkScalarToFixed(v) >> 8;
2494 if (scale < 0) {
2495 scale = 0;
2496 }
2497 if (scale > 255) {
2498 scale = 255;
2499 }
2500 return SkAlpha255To256(scale);
2501 }
2502
shadeSpan(int x,int y,SkPMColor dstC[],int count)2503 void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
2504 SkPoint src;
2505
2506 for (int i = 0; i < count; i++) {
2507 fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src);
2508 x += 1;
2509
2510 int scale1 = ScalarTo256(src.fX);
2511 int scale2 = ScalarTo256(src.fY);
2512 int scale0 = 256 - scale1 - scale2;
2513 if (scale0 < 0) {
2514 if (scale1 > scale2) {
2515 scale2 = 256 - scale1;
2516 } else {
2517 scale1 = 256 - scale2;
2518 }
2519 scale0 = 0;
2520 }
2521
2522 dstC[i] = SkAlphaMulQ(fColors[0], scale0) +
2523 SkAlphaMulQ(fColors[1], scale1) +
2524 SkAlphaMulQ(fColors[2], scale2);
2525 }
2526 }
2527
2528 #ifdef SK_DEVELOPER
toString(SkString * str) const2529 void SkTriColorShader::toString(SkString* str) const {
2530 str->append("SkTriColorShader: (");
2531
2532 this->INHERITED::toString(str);
2533
2534 str->append(")");
2535 }
2536 #endif
2537
drawVertices(SkCanvas::VertexMode vmode,int count,const SkPoint vertices[],const SkPoint textures[],const SkColor colors[],SkXfermode * xmode,const uint16_t indices[],int indexCount,const SkPaint & paint) const2538 void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
2539 const SkPoint vertices[], const SkPoint textures[],
2540 const SkColor colors[], SkXfermode* xmode,
2541 const uint16_t indices[], int indexCount,
2542 const SkPaint& paint) const {
2543 SkASSERT(0 == count || NULL != vertices);
2544
2545 // abort early if there is nothing to draw
2546 if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) {
2547 return;
2548 }
2549
2550 // transform out vertices into device coordinates
2551 SkAutoSTMalloc<16, SkPoint> storage(count);
2552 SkPoint* devVerts = storage.get();
2553 fMatrix->mapPoints(devVerts, vertices, count);
2554
2555 if (fBounder) {
2556 SkRect bounds;
2557 bounds.set(devVerts, count);
2558 if (!fBounder->doRect(bounds, paint)) {
2559 return;
2560 }
2561 }
2562
2563 /*
2564 We can draw the vertices in 1 of 4 ways:
2565
2566 - solid color (no shader/texture[], no colors[])
2567 - just colors (no shader/texture[], has colors[])
2568 - just texture (has shader/texture[], no colors[])
2569 - colors * texture (has shader/texture[], has colors[])
2570
2571 Thus for texture drawing, we need both texture[] and a shader.
2572 */
2573
2574 SkTriColorShader triShader; // must be above declaration of p
2575 SkPaint p(paint);
2576
2577 SkShader* shader = p.getShader();
2578 if (NULL == shader) {
2579 // if we have no shader, we ignore the texture coordinates
2580 textures = NULL;
2581 } else if (NULL == textures) {
2582 // if we don't have texture coordinates, ignore the shader
2583 p.setShader(NULL);
2584 shader = NULL;
2585 }
2586
2587 // setup the custom shader (if needed)
2588 if (NULL != colors) {
2589 if (NULL == textures) {
2590 // just colors (no texture)
2591 shader = p.setShader(&triShader);
2592 } else {
2593 // colors * texture
2594 SkASSERT(shader);
2595 bool releaseMode = false;
2596 if (NULL == xmode) {
2597 xmode = SkXfermode::Create(SkXfermode::kModulate_Mode);
2598 releaseMode = true;
2599 }
2600 SkShader* compose = SkNEW_ARGS(SkComposeShader,
2601 (&triShader, shader, xmode));
2602 p.setShader(compose)->unref();
2603 if (releaseMode) {
2604 xmode->unref();
2605 }
2606 shader = compose;
2607 }
2608 }
2609
2610 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p);
2611 // important that we abort early, as below we may manipulate the shader
2612 // and that is only valid if the shader returned true from setContext.
2613 // If it returned false, then our blitter will be the NullBlitter.
2614 if (blitter->isNullBlitter()) {
2615 return;
2616 }
2617
2618 // setup our state and function pointer for iterating triangles
2619 VertState state(count, indices, indexCount);
2620 VertState::Proc vertProc = state.chooseProc(vmode);
2621
2622 if (NULL != textures || NULL != colors) {
2623 SkMatrix tempM;
2624 SkMatrix savedLocalM;
2625 if (shader) {
2626 savedLocalM = shader->getLocalMatrix();
2627 }
2628
2629 // setContext has already been called and verified to return true
2630 // by the constructor of SkAutoBlitterChoose
2631 bool prevContextSuccess = true;
2632 while (vertProc(&state)) {
2633 if (NULL != textures) {
2634 if (texture_to_matrix(state, vertices, textures, &tempM)) {
2635 tempM.postConcat(savedLocalM);
2636 shader->setLocalMatrix(tempM);
2637 // Need to recall setContext since we changed the local matrix.
2638 // However, we also need to balance the calls this with a
2639 // call to endContext which requires tracking the result of
2640 // the previous call to setContext.
2641 if (prevContextSuccess) {
2642 shader->endContext();
2643 }
2644 prevContextSuccess = shader->setContext(*fBitmap, p, *fMatrix);
2645 if (!prevContextSuccess) {
2646 continue;
2647 }
2648 }
2649 }
2650 if (NULL != colors) {
2651 if (!triShader.setup(vertices, colors,
2652 state.f0, state.f1, state.f2)) {
2653 continue;
2654 }
2655 }
2656
2657 SkPoint tmp[] = {
2658 devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
2659 };
2660 SkScan::FillTriangle(tmp, *fRC, blitter.get());
2661 }
2662
2663 // now restore the shader's original local matrix
2664 if (NULL != shader) {
2665 shader->setLocalMatrix(savedLocalM);
2666 }
2667
2668 // If the final call to setContext fails we must make it suceed so that the
2669 // call to endContext in the destructor for SkAutoBlitterChoose is balanced.
2670 if (!prevContextSuccess) {
2671 prevContextSuccess = shader->setContext(*fBitmap, paint, SkMatrix::I());
2672 SkASSERT(prevContextSuccess);
2673 }
2674 } else {
2675 // no colors[] and no texture
2676 HairProc hairProc = ChooseHairProc(paint.isAntiAlias());
2677 const SkRasterClip& clip = *fRC;
2678 while (vertProc(&state)) {
2679 hairProc(devVerts[state.f0], devVerts[state.f1], clip, blitter.get());
2680 hairProc(devVerts[state.f1], devVerts[state.f2], clip, blitter.get());
2681 hairProc(devVerts[state.f2], devVerts[state.f0], clip, blitter.get());
2682 }
2683 }
2684 }
2685
2686 ///////////////////////////////////////////////////////////////////////////////
2687 ///////////////////////////////////////////////////////////////////////////////
2688
2689 #ifdef SK_DEBUG
2690
validate() const2691 void SkDraw::validate() const {
2692 SkASSERT(fBitmap != NULL);
2693 SkASSERT(fMatrix != NULL);
2694 SkASSERT(fClip != NULL);
2695 SkASSERT(fRC != NULL);
2696
2697 const SkIRect& cr = fRC->getBounds();
2698 SkIRect br;
2699
2700 br.set(0, 0, fBitmap->width(), fBitmap->height());
2701 SkASSERT(cr.isEmpty() || br.contains(cr));
2702 }
2703
2704 #endif
2705
2706 ///////////////////////////////////////////////////////////////////////////////
2707
SkBounder()2708 SkBounder::SkBounder() {
2709 // initialize up front. This gets reset by SkCanvas before each draw call.
2710 fClip = &SkRegion::GetEmptyRegion();
2711 }
2712
doIRect(const SkIRect & r)2713 bool SkBounder::doIRect(const SkIRect& r) {
2714 SkIRect rr;
2715 return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr);
2716 }
2717
2718 // TODO: change the prototype to take fixed, and update the callers
doIRectGlyph(const SkIRect & r,int x,int y,const SkGlyph & glyph)2719 bool SkBounder::doIRectGlyph(const SkIRect& r, int x, int y,
2720 const SkGlyph& glyph) {
2721 SkIRect rr;
2722 if (!rr.intersect(fClip->getBounds(), r)) {
2723 return false;
2724 }
2725 GlyphRec rec;
2726 rec.fLSB.set(SkIntToFixed(x), SkIntToFixed(y));
2727 rec.fRSB.set(rec.fLSB.fX + glyph.fAdvanceX,
2728 rec.fLSB.fY + glyph.fAdvanceY);
2729 rec.fGlyphID = glyph.getGlyphID();
2730 rec.fFlags = 0;
2731 return this->onIRectGlyph(rr, rec);
2732 }
2733
doHairline(const SkPoint & pt0,const SkPoint & pt1,const SkPaint & paint)2734 bool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1,
2735 const SkPaint& paint) {
2736 SkIRect r;
2737 SkScalar v0, v1;
2738
2739 v0 = pt0.fX;
2740 v1 = pt1.fX;
2741 if (v0 > v1) {
2742 SkTSwap<SkScalar>(v0, v1);
2743 }
2744 r.fLeft = SkScalarFloor(v0);
2745 r.fRight = SkScalarCeil(v1);
2746
2747 v0 = pt0.fY;
2748 v1 = pt1.fY;
2749 if (v0 > v1) {
2750 SkTSwap<SkScalar>(v0, v1);
2751 }
2752 r.fTop = SkScalarFloor(v0);
2753 r.fBottom = SkScalarCeil(v1);
2754
2755 if (paint.isAntiAlias()) {
2756 r.inset(-1, -1);
2757 }
2758 return this->doIRect(r);
2759 }
2760
doRect(const SkRect & rect,const SkPaint & paint)2761 bool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) {
2762 SkIRect r;
2763
2764 if (paint.getStyle() == SkPaint::kFill_Style) {
2765 rect.round(&r);
2766 } else {
2767 int rad = -1;
2768 rect.roundOut(&r);
2769 if (paint.isAntiAlias()) {
2770 rad = -2;
2771 }
2772 r.inset(rad, rad);
2773 }
2774 return this->doIRect(r);
2775 }
2776
doPath(const SkPath & path,const SkPaint & paint,bool doFill)2777 bool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) {
2778 SkIRect r;
2779 const SkRect& bounds = path.getBounds();
2780
2781 if (doFill) {
2782 bounds.round(&r);
2783 } else { // hairline
2784 bounds.roundOut(&r);
2785 }
2786
2787 if (paint.isAntiAlias()) {
2788 r.inset(-1, -1);
2789 }
2790 return this->doIRect(r);
2791 }
2792
commit()2793 void SkBounder::commit() {
2794 // override in subclass
2795 }
2796
2797 ////////////////////////////////////////////////////////////////////////////////////////////////
2798
2799 #include "SkPath.h"
2800 #include "SkDraw.h"
2801 #include "SkRegion.h"
2802 #include "SkBlitter.h"
2803
compute_bounds(const SkPath & devPath,const SkIRect * clipBounds,const SkMaskFilter * filter,const SkMatrix * filterMatrix,SkIRect * bounds)2804 static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
2805 const SkMaskFilter* filter, const SkMatrix* filterMatrix,
2806 SkIRect* bounds) {
2807 if (devPath.isEmpty()) {
2808 return false;
2809 }
2810
2811 // init our bounds from the path
2812 {
2813 SkRect pathBounds = devPath.getBounds();
2814 pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf);
2815 pathBounds.roundOut(bounds);
2816 }
2817
2818 SkIPoint margin = SkIPoint::Make(0, 0);
2819 if (filter) {
2820 SkASSERT(filterMatrix);
2821
2822 SkMask srcM, dstM;
2823
2824 srcM.fBounds = *bounds;
2825 srcM.fFormat = SkMask::kA8_Format;
2826 srcM.fImage = NULL;
2827 if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
2828 return false;
2829 }
2830 }
2831
2832 // (possibly) trim the bounds to reflect the clip
2833 // (plus whatever slop the filter needs)
2834 if (clipBounds) {
2835 SkIRect tmp = *clipBounds;
2836 // Ugh. Guard against gigantic margins from wacky filters. Without this
2837 // check we can request arbitrary amounts of slop beyond our visible
2838 // clip, and bring down the renderer (at least on finite RAM machines
2839 // like handsets, etc.). Need to balance this invented value between
2840 // quality of large filters like blurs, and the corresponding memory
2841 // requests.
2842 static const int MAX_MARGIN = 128;
2843 tmp.inset(-SkMin32(margin.fX, MAX_MARGIN),
2844 -SkMin32(margin.fY, MAX_MARGIN));
2845 if (!bounds->intersect(tmp)) {
2846 return false;
2847 }
2848 }
2849
2850 return true;
2851 }
2852
draw_into_mask(const SkMask & mask,const SkPath & devPath,SkPaint::Style style)2853 static void draw_into_mask(const SkMask& mask, const SkPath& devPath,
2854 SkPaint::Style style) {
2855 SkBitmap bm;
2856 SkDraw draw;
2857 SkRasterClip clip;
2858 SkMatrix matrix;
2859 SkPaint paint;
2860
2861 bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
2862 bm.setPixels(mask.fImage);
2863
2864 clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height()));
2865 matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
2866 -SkIntToScalar(mask.fBounds.fTop));
2867
2868 draw.fBitmap = &bm;
2869 draw.fRC = &clip;
2870 draw.fClip = &clip.bwRgn();
2871 draw.fMatrix = &matrix;
2872 draw.fBounder = NULL;
2873 paint.setAntiAlias(true);
2874 paint.setStyle(style);
2875 draw.drawPath(devPath, paint);
2876 }
2877
DrawToMask(const SkPath & devPath,const SkIRect * clipBounds,const SkMaskFilter * filter,const SkMatrix * filterMatrix,SkMask * mask,SkMask::CreateMode mode,SkPaint::Style style)2878 bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
2879 const SkMaskFilter* filter, const SkMatrix* filterMatrix,
2880 SkMask* mask, SkMask::CreateMode mode,
2881 SkPaint::Style style) {
2882 if (SkMask::kJustRenderImage_CreateMode != mode) {
2883 if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds))
2884 return false;
2885 }
2886
2887 if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
2888 mask->fFormat = SkMask::kA8_Format;
2889 mask->fRowBytes = mask->fBounds.width();
2890 size_t size = mask->computeImageSize();
2891 if (0 == size) {
2892 // we're too big to allocate the mask, abort
2893 return false;
2894 }
2895 mask->fImage = SkMask::AllocImage(size);
2896 memset(mask->fImage, 0, mask->computeImageSize());
2897 }
2898
2899 if (SkMask::kJustComputeBounds_CreateMode != mode) {
2900 draw_into_mask(*mask, devPath, style);
2901 }
2902
2903 return true;
2904 }
2905
2906