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