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