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