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