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