SkDraw.cpp revision d3b65972aad96453ff4510caa3e25a2b847c6d1e
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.
49void FixGCC49Arm64Bug(int v) { }
50
51/** Helper for allocating small blitters on the stack.
52 */
53class SkAutoBlitterChoose : SkNoncopyable {
54public:
55    SkAutoBlitterChoose() {
56        fBlitter = nullptr;
57    }
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
63    SkBlitter*  operator->() { return fBlitter; }
64    SkBlitter*  get() const { return fBlitter; }
65
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
72private:
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
81static 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
92SkDraw::SkDraw() {
93    sk_bzero(this, sizeof(*this));
94}
95
96bool 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
115typedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data);
116
117static void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) {
118    sk_bzero(pixels, bytes);
119}
120
121static void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {}
122
123static void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
124    sk_memset32((uint32_t*)pixels, data, SkToInt(bytes >> 2));
125}
126
127static void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
128    sk_memset16((uint16_t*)pixels, data, SkToInt(bytes >> 1));
129}
130
131static void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
132    memset(pixels, data, bytes);
133}
134
135static 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
198static 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
229void 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
269struct 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
285private:
286    SkAAClipBlitterWrapper fWrapper;
287};
288
289static 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
303static 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
324static 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
345static 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
356static 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
363static 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
370static 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
377static 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
384static 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
401static 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
419bool 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
457PtProcRec::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
515void 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
710static 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
720static 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
731SkDraw::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
759static const SkPoint* rect_points(const SkRect& r) {
760    return SkTCast<const SkPoint*>(&r);
761}
762
763static SkPoint* rect_points(SkRect& r) {
764    return SkTCast<SkPoint*>(&r);
765}
766
767void 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
870void 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
900static 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
909bool 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
933void 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
969DRAW_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
976SkScalar 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
990void 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
1073void 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
1166void 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
1246static 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
1253static 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
1260static 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
1264void 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
1332void 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
1392bool 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
1407void 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
1437class DrawOneGlyph {
1438public:
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
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
1503private:
1504    static bool UsingRegionToDraw(const SkRasterClip* rClip) {
1505        return rClip->isBW() && !rClip->isRect();
1506    }
1507
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
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
1529    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
1553uint32_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
1561void 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
1593void 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
1639void 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
1676static SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) {
1677    return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
1678}
1679
1680static 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
1693class SkTriColorShader : public SkShader {
1694public:
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
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
1725    void bindSetupData(TriColorShaderData* setupData) { fSetupData = setupData; }
1726
1727    // Take the setup data from context when needed.
1728    TriColorShaderData* takeSetupData() {
1729        TriColorShaderData *data = fSetupData;
1730        fSetupData = NULL;
1731        return data;
1732    }
1733
1734protected:
1735    Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override {
1736        return alloc->make<TriColorShaderContext>(*this, rec);
1737    }
1738
1739private:
1740    TriColorShaderData *fSetupData;
1741
1742    typedef SkShader INHERITED;
1743};
1744
1745bool 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
1777static int ScalarTo256(SkScalar v) {
1778    return static_cast<int>(SkScalarPin(v, 0, 1) * 256 + 0.5);
1779}
1780
1781SkTriColorShader::SkTriColorShader()
1782    : INHERITED(NULL)
1783    , fSetupData(NULL) {}
1784
1785SkTriColorShader::TriColorShaderContext::TriColorShaderContext(const SkTriColorShader& shader,
1786                                                               const ContextRec& rec)
1787    : INHERITED(shader, rec)
1788    , fSetup(false) {}
1789
1790SkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {}
1791
1792void 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
1837void SkTriColorShader::toString(SkString* str) const {
1838    str->append("SkTriColorShader: (");
1839
1840    this->INHERITED::toString(str);
1841
1842    str->append(")");
1843}
1844#endif
1845
1846namespace {
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//
1855class SkLocalInnerMatrixShader final : public SkShader {
1856public:
1857    SkLocalInnerMatrixShader(sk_sp<SkShader> proxy, const SkMatrix& localMatrix)
1858    : INHERITED(&localMatrix)
1859    , fProxyShader(std::move(proxy)) {}
1860
1861    Factory getFactory() const override {
1862        SkASSERT(false);
1863        return nullptr;
1864    }
1865
1866protected:
1867    void flatten(SkWriteBuffer&) const override {
1868        SkASSERT(false);
1869    }
1870
1871    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
1878    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
1889private:
1890    sk_sp<SkShader> fProxyShader;
1891
1892    typedef SkShader INHERITED;
1893};
1894
1895sk_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
1946void 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
2070void 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
2090static 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
2132static 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
2163bool 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