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