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