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