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