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