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