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