1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/core/SkScanPriv.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h"
11cb93a386Sopenharmony_ci#include "include/core/SkPath.h"
12cb93a386Sopenharmony_ci#include "include/core/SkRegion.h"
13cb93a386Sopenharmony_ci#include "include/private/SkTo.h"
14cb93a386Sopenharmony_ci#include "src/core/SkAntiRun.h"
15cb93a386Sopenharmony_ci#include "src/core/SkBlitter.h"
16cb93a386Sopenharmony_ci#include "src/core/SkPathPriv.h"
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci#ifdef SK_ENABLE_PATH_COMPLEXITY_DFX
19cb93a386Sopenharmony_ci#include "src/core/SkPathComplexityDfx.h"
20cb93a386Sopenharmony_ci#endif
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_ci#define SHIFT   SK_SUPERSAMPLE_SHIFT
23cb93a386Sopenharmony_ci#define SCALE   (1 << SHIFT)
24cb93a386Sopenharmony_ci#define MASK    (SCALE - 1)
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_ci/** @file
27cb93a386Sopenharmony_ci    We have two techniques for capturing the output of the supersampler:
28cb93a386Sopenharmony_ci    - SUPERMASK, which records a large mask-bitmap
29cb93a386Sopenharmony_ci        this is often faster for small, complex objects
30cb93a386Sopenharmony_ci    - RLE, which records a rle-encoded scanline
31cb93a386Sopenharmony_ci        this is often faster for large objects with big spans
32cb93a386Sopenharmony_ci
33cb93a386Sopenharmony_ci    These blitters use two coordinate systems:
34cb93a386Sopenharmony_ci    - destination coordinates, scale equal to the output - often
35cb93a386Sopenharmony_ci        abbreviated with 'i' or 'I' in variable names
36cb93a386Sopenharmony_ci    - supersampled coordinates, scale equal to the output * SCALE
37cb93a386Sopenharmony_ci */
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ci//#define FORCE_SUPERMASK
40cb93a386Sopenharmony_ci//#define FORCE_RLE
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci/// Base class for a single-pass supersampled blitter.
45cb93a386Sopenharmony_ciclass BaseSuperBlitter : public SkBlitter {
46cb93a386Sopenharmony_cipublic:
47cb93a386Sopenharmony_ci    BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
48cb93a386Sopenharmony_ci                     const SkIRect& clipBounds, bool isInverse);
49cb93a386Sopenharmony_ci
50cb93a386Sopenharmony_ci    /// Must be explicitly defined on subclasses.
51cb93a386Sopenharmony_ci    void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
52cb93a386Sopenharmony_ci        SkDEBUGFAIL("How did I get here?");
53cb93a386Sopenharmony_ci    }
54cb93a386Sopenharmony_ci    /// May not be called on BaseSuperBlitter because it blits out of order.
55cb93a386Sopenharmony_ci    void blitV(int x, int y, int height, SkAlpha alpha) override {
56cb93a386Sopenharmony_ci        SkDEBUGFAIL("How did I get here?");
57cb93a386Sopenharmony_ci    }
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ciprotected:
60cb93a386Sopenharmony_ci    SkBlitter*  fRealBlitter;
61cb93a386Sopenharmony_ci    /// Current y coordinate, in destination coordinates.
62cb93a386Sopenharmony_ci    int         fCurrIY;
63cb93a386Sopenharmony_ci    /// Widest row of region to be blitted, in destination coordinates.
64cb93a386Sopenharmony_ci    int         fWidth;
65cb93a386Sopenharmony_ci    /// Leftmost x coordinate in any row, in destination coordinates.
66cb93a386Sopenharmony_ci    int         fLeft;
67cb93a386Sopenharmony_ci    /// Leftmost x coordinate in any row, in supersampled coordinates.
68cb93a386Sopenharmony_ci    int         fSuperLeft;
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    SkDEBUGCODE(int fCurrX;)
71cb93a386Sopenharmony_ci    /// Current y coordinate in supersampled coordinates.
72cb93a386Sopenharmony_ci    int fCurrY;
73cb93a386Sopenharmony_ci    /// Initial y coordinate (top of bounds).
74cb93a386Sopenharmony_ci    int fTop;
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_ci    SkIRect fSectBounds;
77cb93a386Sopenharmony_ci};
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_ciBaseSuperBlitter::BaseSuperBlitter(SkBlitter* realBlit, const SkIRect& ir,
80cb93a386Sopenharmony_ci                                   const SkIRect& clipBounds, bool isInverse) {
81cb93a386Sopenharmony_ci    fRealBlitter = realBlit;
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_ci    SkIRect sectBounds;
84cb93a386Sopenharmony_ci    if (isInverse) {
85cb93a386Sopenharmony_ci        // We use the clip bounds instead of the ir, since we may be asked to
86cb93a386Sopenharmony_ci        //draw outside of the rect when we're a inverse filltype
87cb93a386Sopenharmony_ci        sectBounds = clipBounds;
88cb93a386Sopenharmony_ci    } else {
89cb93a386Sopenharmony_ci        if (!sectBounds.intersect(ir, clipBounds)) {
90cb93a386Sopenharmony_ci            sectBounds.setEmpty();
91cb93a386Sopenharmony_ci        }
92cb93a386Sopenharmony_ci    }
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_ci    const int left = sectBounds.left();
95cb93a386Sopenharmony_ci    const int right = sectBounds.right();
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ci    fLeft = left;
98cb93a386Sopenharmony_ci    fSuperLeft = SkLeftShift(left, SHIFT);
99cb93a386Sopenharmony_ci    fWidth = right - left;
100cb93a386Sopenharmony_ci    fTop = sectBounds.top();
101cb93a386Sopenharmony_ci    fCurrIY = fTop - 1;
102cb93a386Sopenharmony_ci    fCurrY = SkLeftShift(fTop, SHIFT) - 1;
103cb93a386Sopenharmony_ci
104cb93a386Sopenharmony_ci    SkDEBUGCODE(fCurrX = -1;)
105cb93a386Sopenharmony_ci}
106cb93a386Sopenharmony_ci
107cb93a386Sopenharmony_ci/// Run-length-encoded supersampling antialiased blitter.
108cb93a386Sopenharmony_ciclass SuperBlitter : public BaseSuperBlitter {
109cb93a386Sopenharmony_cipublic:
110cb93a386Sopenharmony_ci    SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds,
111cb93a386Sopenharmony_ci                 bool isInverse);
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_ci    ~SuperBlitter() override {
114cb93a386Sopenharmony_ci        this->flush();
115cb93a386Sopenharmony_ci    }
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci    /// Once fRuns contains a complete supersampled row, flush() blits
118cb93a386Sopenharmony_ci    /// it out through the wrapped blitter.
119cb93a386Sopenharmony_ci    void flush();
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci    /// Blits a row of pixels, with location and width specified
122cb93a386Sopenharmony_ci    /// in supersampled coordinates.
123cb93a386Sopenharmony_ci    void blitH(int x, int y, int width) override;
124cb93a386Sopenharmony_ci    /// Blits a rectangle of pixels, with location and size specified
125cb93a386Sopenharmony_ci    /// in supersampled coordinates.
126cb93a386Sopenharmony_ci    void blitRect(int x, int y, int width, int height) override;
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_ciprivate:
129cb93a386Sopenharmony_ci    // The next three variables are used to track a circular buffer that
130cb93a386Sopenharmony_ci    // contains the values used in SkAlphaRuns. These variables should only
131cb93a386Sopenharmony_ci    // ever be updated in advanceRuns(), and fRuns should always point to
132cb93a386Sopenharmony_ci    // a valid SkAlphaRuns...
133cb93a386Sopenharmony_ci    int         fRunsToBuffer;
134cb93a386Sopenharmony_ci    void*       fRunsBuffer;
135cb93a386Sopenharmony_ci    int         fCurrentRun;
136cb93a386Sopenharmony_ci    SkAlphaRuns fRuns;
137cb93a386Sopenharmony_ci
138cb93a386Sopenharmony_ci    // extra one to store the zero at the end
139cb93a386Sopenharmony_ci    int getRunsSz() const { return (fWidth + 1 + (fWidth + 2)/2) * sizeof(int16_t); }
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_ci    // This function updates the fRuns variable to point to the next buffer space
142cb93a386Sopenharmony_ci    // with adequate storage for a SkAlphaRuns. It mostly just advances fCurrentRun
143cb93a386Sopenharmony_ci    // and resets fRuns to point to an empty scanline.
144cb93a386Sopenharmony_ci    void advanceRuns() {
145cb93a386Sopenharmony_ci        const size_t kRunsSz = this->getRunsSz();
146cb93a386Sopenharmony_ci        fCurrentRun = (fCurrentRun + 1) % fRunsToBuffer;
147cb93a386Sopenharmony_ci        fRuns.fRuns = reinterpret_cast<int16_t*>(
148cb93a386Sopenharmony_ci            reinterpret_cast<uint8_t*>(fRunsBuffer) + fCurrentRun * kRunsSz);
149cb93a386Sopenharmony_ci        fRuns.fAlpha = reinterpret_cast<SkAlpha*>(fRuns.fRuns + fWidth + 1);
150cb93a386Sopenharmony_ci        fRuns.reset(fWidth);
151cb93a386Sopenharmony_ci    }
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_ci    int         fOffsetX;
154cb93a386Sopenharmony_ci};
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_ciSuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds,
157cb93a386Sopenharmony_ci                           bool isInverse)
158cb93a386Sopenharmony_ci        : BaseSuperBlitter(realBlitter, ir, clipBounds, isInverse)
159cb93a386Sopenharmony_ci{
160cb93a386Sopenharmony_ci    fRunsToBuffer = realBlitter->requestRowsPreserved();
161cb93a386Sopenharmony_ci    fRunsBuffer = realBlitter->allocBlitMemory(fRunsToBuffer * this->getRunsSz());
162cb93a386Sopenharmony_ci    fCurrentRun = -1;
163cb93a386Sopenharmony_ci
164cb93a386Sopenharmony_ci    this->advanceRuns();
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_ci    fOffsetX = 0;
167cb93a386Sopenharmony_ci}
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_civoid SuperBlitter::flush() {
170cb93a386Sopenharmony_ci    if (fCurrIY >= fTop) {
171cb93a386Sopenharmony_ci
172cb93a386Sopenharmony_ci        SkASSERT(fCurrentRun < fRunsToBuffer);
173cb93a386Sopenharmony_ci        if (!fRuns.empty()) {
174cb93a386Sopenharmony_ci            // SkDEBUGCODE(fRuns.dump();)
175cb93a386Sopenharmony_ci            fRealBlitter->blitAntiH(fLeft, fCurrIY, fRuns.fAlpha, fRuns.fRuns);
176cb93a386Sopenharmony_ci            this->advanceRuns();
177cb93a386Sopenharmony_ci            fOffsetX = 0;
178cb93a386Sopenharmony_ci        }
179cb93a386Sopenharmony_ci
180cb93a386Sopenharmony_ci        fCurrIY = fTop - 1;
181cb93a386Sopenharmony_ci        SkDEBUGCODE(fCurrX = -1;)
182cb93a386Sopenharmony_ci    }
183cb93a386Sopenharmony_ci}
184cb93a386Sopenharmony_ci
185cb93a386Sopenharmony_ci/** coverage_to_partial_alpha() is being used by SkAlphaRuns, which
186cb93a386Sopenharmony_ci    *accumulates* SCALE pixels worth of "alpha" in [0,(256/SCALE)]
187cb93a386Sopenharmony_ci    to produce a final value in [0, 255] and handles clamping 256->255
188cb93a386Sopenharmony_ci    itself, with the same (alpha - (alpha >> 8)) correction as
189cb93a386Sopenharmony_ci    coverage_to_exact_alpha().
190cb93a386Sopenharmony_ci*/
191cb93a386Sopenharmony_cistatic inline int coverage_to_partial_alpha(int aa) {
192cb93a386Sopenharmony_ci    aa <<= 8 - 2*SHIFT;
193cb93a386Sopenharmony_ci    return aa;
194cb93a386Sopenharmony_ci}
195cb93a386Sopenharmony_ci
196cb93a386Sopenharmony_ci/** coverage_to_exact_alpha() is being used by our blitter, which wants
197cb93a386Sopenharmony_ci    a final value in [0, 255].
198cb93a386Sopenharmony_ci*/
199cb93a386Sopenharmony_cistatic inline int coverage_to_exact_alpha(int aa) {
200cb93a386Sopenharmony_ci    int alpha = (256 >> SHIFT) * aa;
201cb93a386Sopenharmony_ci    // clamp 256->255
202cb93a386Sopenharmony_ci    return alpha - (alpha >> 8);
203cb93a386Sopenharmony_ci}
204cb93a386Sopenharmony_ci
205cb93a386Sopenharmony_civoid SuperBlitter::blitH(int x, int y, int width) {
206cb93a386Sopenharmony_ci    SkASSERT(width > 0);
207cb93a386Sopenharmony_ci
208cb93a386Sopenharmony_ci    int iy = y >> SHIFT;
209cb93a386Sopenharmony_ci    SkASSERT(iy >= fCurrIY);
210cb93a386Sopenharmony_ci
211cb93a386Sopenharmony_ci    x -= fSuperLeft;
212cb93a386Sopenharmony_ci    // hack, until I figure out why my cubics (I think) go beyond the bounds
213cb93a386Sopenharmony_ci    if (x < 0) {
214cb93a386Sopenharmony_ci        width += x;
215cb93a386Sopenharmony_ci        x = 0;
216cb93a386Sopenharmony_ci    }
217cb93a386Sopenharmony_ci
218cb93a386Sopenharmony_ci#ifdef SK_DEBUG
219cb93a386Sopenharmony_ci    SkASSERT(y != fCurrY || x >= fCurrX);
220cb93a386Sopenharmony_ci#endif
221cb93a386Sopenharmony_ci    SkASSERT(y >= fCurrY);
222cb93a386Sopenharmony_ci    if (fCurrY != y) {
223cb93a386Sopenharmony_ci        fOffsetX = 0;
224cb93a386Sopenharmony_ci        fCurrY = y;
225cb93a386Sopenharmony_ci    }
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_ci    if (iy != fCurrIY) {  // new scanline
228cb93a386Sopenharmony_ci        this->flush();
229cb93a386Sopenharmony_ci        fCurrIY = iy;
230cb93a386Sopenharmony_ci    }
231cb93a386Sopenharmony_ci
232cb93a386Sopenharmony_ci    int start = x;
233cb93a386Sopenharmony_ci    int stop = x + width;
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci    SkASSERT(start >= 0 && stop > start);
236cb93a386Sopenharmony_ci    // integer-pixel-aligned ends of blit, rounded out
237cb93a386Sopenharmony_ci    int fb = start & MASK;
238cb93a386Sopenharmony_ci    int fe = stop & MASK;
239cb93a386Sopenharmony_ci    int n = (stop >> SHIFT) - (start >> SHIFT) - 1;
240cb93a386Sopenharmony_ci
241cb93a386Sopenharmony_ci    if (n < 0) {
242cb93a386Sopenharmony_ci        fb = fe - fb;
243cb93a386Sopenharmony_ci        n = 0;
244cb93a386Sopenharmony_ci        fe = 0;
245cb93a386Sopenharmony_ci    } else {
246cb93a386Sopenharmony_ci        if (fb == 0) {
247cb93a386Sopenharmony_ci            n += 1;
248cb93a386Sopenharmony_ci        } else {
249cb93a386Sopenharmony_ci            fb = SCALE - fb;
250cb93a386Sopenharmony_ci        }
251cb93a386Sopenharmony_ci    }
252cb93a386Sopenharmony_ci
253cb93a386Sopenharmony_ci    fOffsetX = fRuns.add(x >> SHIFT, coverage_to_partial_alpha(fb),
254cb93a386Sopenharmony_ci                         n, coverage_to_partial_alpha(fe),
255cb93a386Sopenharmony_ci                         (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT),
256cb93a386Sopenharmony_ci                         fOffsetX);
257cb93a386Sopenharmony_ci
258cb93a386Sopenharmony_ci#ifdef SK_DEBUG
259cb93a386Sopenharmony_ci    fRuns.assertValid(y & MASK, (1 << (8 - SHIFT)));
260cb93a386Sopenharmony_ci    fCurrX = x + width;
261cb93a386Sopenharmony_ci#endif
262cb93a386Sopenharmony_ci}
263cb93a386Sopenharmony_ci
264cb93a386Sopenharmony_ci#if 0 // UNUSED
265cb93a386Sopenharmony_cistatic void set_left_rite_runs(SkAlphaRuns& runs, int ileft, U8CPU leftA,
266cb93a386Sopenharmony_ci                               int n, U8CPU riteA) {
267cb93a386Sopenharmony_ci    SkASSERT(leftA <= 0xFF);
268cb93a386Sopenharmony_ci    SkASSERT(riteA <= 0xFF);
269cb93a386Sopenharmony_ci
270cb93a386Sopenharmony_ci    int16_t* run = runs.fRuns;
271cb93a386Sopenharmony_ci    uint8_t* aa = runs.fAlpha;
272cb93a386Sopenharmony_ci
273cb93a386Sopenharmony_ci    if (ileft > 0) {
274cb93a386Sopenharmony_ci        run[0] = ileft;
275cb93a386Sopenharmony_ci        aa[0] = 0;
276cb93a386Sopenharmony_ci        run += ileft;
277cb93a386Sopenharmony_ci        aa += ileft;
278cb93a386Sopenharmony_ci    }
279cb93a386Sopenharmony_ci
280cb93a386Sopenharmony_ci    SkASSERT(leftA < 0xFF);
281cb93a386Sopenharmony_ci    if (leftA > 0) {
282cb93a386Sopenharmony_ci        *run++ = 1;
283cb93a386Sopenharmony_ci        *aa++ = leftA;
284cb93a386Sopenharmony_ci    }
285cb93a386Sopenharmony_ci
286cb93a386Sopenharmony_ci    if (n > 0) {
287cb93a386Sopenharmony_ci        run[0] = n;
288cb93a386Sopenharmony_ci        aa[0] = 0xFF;
289cb93a386Sopenharmony_ci        run += n;
290cb93a386Sopenharmony_ci        aa += n;
291cb93a386Sopenharmony_ci    }
292cb93a386Sopenharmony_ci
293cb93a386Sopenharmony_ci    SkASSERT(riteA < 0xFF);
294cb93a386Sopenharmony_ci    if (riteA > 0) {
295cb93a386Sopenharmony_ci        *run++ = 1;
296cb93a386Sopenharmony_ci        *aa++ = riteA;
297cb93a386Sopenharmony_ci    }
298cb93a386Sopenharmony_ci    run[0] = 0;
299cb93a386Sopenharmony_ci}
300cb93a386Sopenharmony_ci#endif
301cb93a386Sopenharmony_ci
302cb93a386Sopenharmony_civoid SuperBlitter::blitRect(int x, int y, int width, int height) {
303cb93a386Sopenharmony_ci    SkASSERT(width > 0);
304cb93a386Sopenharmony_ci    SkASSERT(height > 0);
305cb93a386Sopenharmony_ci
306cb93a386Sopenharmony_ci    // blit leading rows
307cb93a386Sopenharmony_ci    while ((y & MASK)) {
308cb93a386Sopenharmony_ci        this->blitH(x, y++, width);
309cb93a386Sopenharmony_ci        if (--height <= 0) {
310cb93a386Sopenharmony_ci            return;
311cb93a386Sopenharmony_ci        }
312cb93a386Sopenharmony_ci    }
313cb93a386Sopenharmony_ci    SkASSERT(height > 0);
314cb93a386Sopenharmony_ci
315cb93a386Sopenharmony_ci    // Since this is a rect, instead of blitting supersampled rows one at a
316cb93a386Sopenharmony_ci    // time and then resolving to the destination canvas, we can blit
317cb93a386Sopenharmony_ci    // directly to the destintion canvas one row per SCALE supersampled rows.
318cb93a386Sopenharmony_ci    int start_y = y >> SHIFT;
319cb93a386Sopenharmony_ci    int stop_y = (y + height) >> SHIFT;
320cb93a386Sopenharmony_ci    int count = stop_y - start_y;
321cb93a386Sopenharmony_ci    if (count > 0) {
322cb93a386Sopenharmony_ci        y += count << SHIFT;
323cb93a386Sopenharmony_ci        height -= count << SHIFT;
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_ci        // save original X for our tail blitH() loop at the bottom
326cb93a386Sopenharmony_ci        int origX = x;
327cb93a386Sopenharmony_ci
328cb93a386Sopenharmony_ci        x -= fSuperLeft;
329cb93a386Sopenharmony_ci        // hack, until I figure out why my cubics (I think) go beyond the bounds
330cb93a386Sopenharmony_ci        if (x < 0) {
331cb93a386Sopenharmony_ci            width += x;
332cb93a386Sopenharmony_ci            x = 0;
333cb93a386Sopenharmony_ci        }
334cb93a386Sopenharmony_ci
335cb93a386Sopenharmony_ci        // There is always a left column, a middle, and a right column.
336cb93a386Sopenharmony_ci        // ileft is the destination x of the first pixel of the entire rect.
337cb93a386Sopenharmony_ci        // xleft is (SCALE - # of covered supersampled pixels) in that
338cb93a386Sopenharmony_ci        // destination pixel.
339cb93a386Sopenharmony_ci        int ileft = x >> SHIFT;
340cb93a386Sopenharmony_ci        int xleft = x & MASK;
341cb93a386Sopenharmony_ci        // irite is the destination x of the last pixel of the OPAQUE section.
342cb93a386Sopenharmony_ci        // xrite is the number of supersampled pixels extending beyond irite;
343cb93a386Sopenharmony_ci        // xrite/SCALE should give us alpha.
344cb93a386Sopenharmony_ci        int irite = (x + width) >> SHIFT;
345cb93a386Sopenharmony_ci        int xrite = (x + width) & MASK;
346cb93a386Sopenharmony_ci        if (!xrite) {
347cb93a386Sopenharmony_ci            xrite = SCALE;
348cb93a386Sopenharmony_ci            irite--;
349cb93a386Sopenharmony_ci        }
350cb93a386Sopenharmony_ci
351cb93a386Sopenharmony_ci        // Need to call flush() to clean up pending draws before we
352cb93a386Sopenharmony_ci        // even consider blitV(), since otherwise it can look nonmonotonic.
353cb93a386Sopenharmony_ci        SkASSERT(start_y > fCurrIY);
354cb93a386Sopenharmony_ci        this->flush();
355cb93a386Sopenharmony_ci
356cb93a386Sopenharmony_ci        int n = irite - ileft - 1;
357cb93a386Sopenharmony_ci        if (n < 0) {
358cb93a386Sopenharmony_ci            // If n < 0, we'll only have a single partially-transparent column
359cb93a386Sopenharmony_ci            // of pixels to render.
360cb93a386Sopenharmony_ci            xleft = xrite - xleft;
361cb93a386Sopenharmony_ci            SkASSERT(xleft <= SCALE);
362cb93a386Sopenharmony_ci            SkASSERT(xleft > 0);
363cb93a386Sopenharmony_ci            fRealBlitter->blitV(ileft + fLeft, start_y, count,
364cb93a386Sopenharmony_ci                coverage_to_exact_alpha(xleft));
365cb93a386Sopenharmony_ci        } else {
366cb93a386Sopenharmony_ci            // With n = 0, we have two possibly-transparent columns of pixels
367cb93a386Sopenharmony_ci            // to render; with n > 0, we have opaque columns between them.
368cb93a386Sopenharmony_ci
369cb93a386Sopenharmony_ci            xleft = SCALE - xleft;
370cb93a386Sopenharmony_ci
371cb93a386Sopenharmony_ci            // Using coverage_to_exact_alpha is not consistent with blitH()
372cb93a386Sopenharmony_ci            const int coverageL = coverage_to_exact_alpha(xleft);
373cb93a386Sopenharmony_ci            const int coverageR = coverage_to_exact_alpha(xrite);
374cb93a386Sopenharmony_ci
375cb93a386Sopenharmony_ci            SkASSERT(coverageL > 0 || n > 0 || coverageR > 0);
376cb93a386Sopenharmony_ci            SkASSERT((coverageL != 0) + n + (coverageR != 0) <= fWidth);
377cb93a386Sopenharmony_ci
378cb93a386Sopenharmony_ci            fRealBlitter->blitAntiRect(ileft + fLeft, start_y, n, count,
379cb93a386Sopenharmony_ci                                       coverageL, coverageR);
380cb93a386Sopenharmony_ci        }
381cb93a386Sopenharmony_ci
382cb93a386Sopenharmony_ci        // preamble for our next call to blitH()
383cb93a386Sopenharmony_ci        fCurrIY = stop_y - 1;
384cb93a386Sopenharmony_ci        fOffsetX = 0;
385cb93a386Sopenharmony_ci        fCurrY = y - 1;
386cb93a386Sopenharmony_ci        fRuns.reset(fWidth);
387cb93a386Sopenharmony_ci        x = origX;
388cb93a386Sopenharmony_ci    }
389cb93a386Sopenharmony_ci
390cb93a386Sopenharmony_ci    // catch any remaining few rows
391cb93a386Sopenharmony_ci    SkASSERT(height <= MASK);
392cb93a386Sopenharmony_ci    while (--height >= 0) {
393cb93a386Sopenharmony_ci        this->blitH(x, y++, width);
394cb93a386Sopenharmony_ci    }
395cb93a386Sopenharmony_ci}
396cb93a386Sopenharmony_ci
397cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
398cb93a386Sopenharmony_ci
399cb93a386Sopenharmony_ci/// Masked supersampling antialiased blitter.
400cb93a386Sopenharmony_ciclass MaskSuperBlitter : public BaseSuperBlitter {
401cb93a386Sopenharmony_cipublic:
402cb93a386Sopenharmony_ci    MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect&, bool isInverse);
403cb93a386Sopenharmony_ci    ~MaskSuperBlitter() override {
404cb93a386Sopenharmony_ci        fRealBlitter->blitMask(fMask, fClipRect);
405cb93a386Sopenharmony_ci    }
406cb93a386Sopenharmony_ci
407cb93a386Sopenharmony_ci    void blitH(int x, int y, int width) override;
408cb93a386Sopenharmony_ci
409cb93a386Sopenharmony_ci    static bool CanHandleRect(const SkIRect& bounds) {
410cb93a386Sopenharmony_ci#ifdef FORCE_RLE
411cb93a386Sopenharmony_ci        return false;
412cb93a386Sopenharmony_ci#endif
413cb93a386Sopenharmony_ci        int width = bounds.width();
414cb93a386Sopenharmony_ci        int64_t rb = SkAlign4(width);
415cb93a386Sopenharmony_ci        // use 64bits to detect overflow
416cb93a386Sopenharmony_ci        int64_t storage = rb * bounds.height();
417cb93a386Sopenharmony_ci
418cb93a386Sopenharmony_ci        return (width <= MaskSuperBlitter::kMAX_WIDTH) &&
419cb93a386Sopenharmony_ci               (storage <= MaskSuperBlitter::kMAX_STORAGE);
420cb93a386Sopenharmony_ci    }
421cb93a386Sopenharmony_ci
422cb93a386Sopenharmony_ciprivate:
423cb93a386Sopenharmony_ci    enum {
424cb93a386Sopenharmony_ci#ifdef FORCE_SUPERMASK
425cb93a386Sopenharmony_ci        kMAX_WIDTH = 2048,
426cb93a386Sopenharmony_ci        kMAX_STORAGE = 1024 * 1024 * 2
427cb93a386Sopenharmony_ci#else
428cb93a386Sopenharmony_ci        kMAX_WIDTH = 32,    // so we don't try to do very wide things, where the RLE blitter would be faster
429cb93a386Sopenharmony_ci        kMAX_STORAGE = 1024
430cb93a386Sopenharmony_ci#endif
431cb93a386Sopenharmony_ci    };
432cb93a386Sopenharmony_ci
433cb93a386Sopenharmony_ci    SkMask      fMask;
434cb93a386Sopenharmony_ci    SkIRect     fClipRect;
435cb93a386Sopenharmony_ci    // we add 1 because add_aa_span can write (unchanged) 1 extra byte at the end, rather than
436cb93a386Sopenharmony_ci    // perform a test to see if stopAlpha != 0
437cb93a386Sopenharmony_ci    uint32_t    fStorage[(kMAX_STORAGE >> 2) + 1];
438cb93a386Sopenharmony_ci};
439cb93a386Sopenharmony_ci
440cb93a386Sopenharmony_ciMaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
441cb93a386Sopenharmony_ci                                   const SkIRect& clipBounds, bool isInverse)
442cb93a386Sopenharmony_ci    : BaseSuperBlitter(realBlitter, ir, clipBounds, isInverse)
443cb93a386Sopenharmony_ci{
444cb93a386Sopenharmony_ci    SkASSERT(CanHandleRect(ir));
445cb93a386Sopenharmony_ci    SkASSERT(!isInverse);
446cb93a386Sopenharmony_ci
447cb93a386Sopenharmony_ci    fMask.fImage    = (uint8_t*)fStorage;
448cb93a386Sopenharmony_ci    fMask.fBounds   = ir;
449cb93a386Sopenharmony_ci    fMask.fRowBytes = ir.width();
450cb93a386Sopenharmony_ci    fMask.fFormat   = SkMask::kA8_Format;
451cb93a386Sopenharmony_ci
452cb93a386Sopenharmony_ci    fClipRect = ir;
453cb93a386Sopenharmony_ci    if (!fClipRect.intersect(clipBounds)) {
454cb93a386Sopenharmony_ci        SkASSERT(0);
455cb93a386Sopenharmony_ci        fClipRect.setEmpty();
456cb93a386Sopenharmony_ci    }
457cb93a386Sopenharmony_ci
458cb93a386Sopenharmony_ci    // For valgrind, write 1 extra byte at the end so we don't read
459cb93a386Sopenharmony_ci    // uninitialized memory. See comment in add_aa_span and fStorage[].
460cb93a386Sopenharmony_ci    memset(fStorage, 0, fMask.fBounds.height() * fMask.fRowBytes + 1);
461cb93a386Sopenharmony_ci}
462cb93a386Sopenharmony_ci
463cb93a386Sopenharmony_cistatic void add_aa_span(uint8_t* alpha, U8CPU startAlpha) {
464cb93a386Sopenharmony_ci    /*  I should be able to just add alpha[x] + startAlpha.
465cb93a386Sopenharmony_ci        However, if the trailing edge of the previous span and the leading
466cb93a386Sopenharmony_ci        edge of the current span round to the same super-sampled x value,
467cb93a386Sopenharmony_ci        I might overflow to 256 with this add, hence the funny subtract.
468cb93a386Sopenharmony_ci    */
469cb93a386Sopenharmony_ci    unsigned tmp = *alpha + startAlpha;
470cb93a386Sopenharmony_ci    SkASSERT(tmp <= 256);
471cb93a386Sopenharmony_ci    *alpha = SkToU8(tmp - (tmp >> 8));
472cb93a386Sopenharmony_ci}
473cb93a386Sopenharmony_ci
474cb93a386Sopenharmony_cistatic inline uint32_t quadplicate_byte(U8CPU value) {
475cb93a386Sopenharmony_ci    uint32_t pair = (value << 8) | value;
476cb93a386Sopenharmony_ci    return (pair << 16) | pair;
477cb93a386Sopenharmony_ci}
478cb93a386Sopenharmony_ci
479cb93a386Sopenharmony_ci// Perform this tricky subtract, to avoid overflowing to 256. Our caller should
480cb93a386Sopenharmony_ci// only ever call us with at most enough to hit 256 (never larger), so it is
481cb93a386Sopenharmony_ci// enough to just subtract the high-bit. Actually clamping with a branch would
482cb93a386Sopenharmony_ci// be slower (e.g. if (tmp > 255) tmp = 255;)
483cb93a386Sopenharmony_ci//
484cb93a386Sopenharmony_cistatic inline void saturated_add(uint8_t* ptr, U8CPU add) {
485cb93a386Sopenharmony_ci    unsigned tmp = *ptr + add;
486cb93a386Sopenharmony_ci    SkASSERT(tmp <= 256);
487cb93a386Sopenharmony_ci    *ptr = SkToU8(tmp - (tmp >> 8));
488cb93a386Sopenharmony_ci}
489cb93a386Sopenharmony_ci
490cb93a386Sopenharmony_ci// minimum count before we want to setup an inner loop, adding 4-at-a-time
491cb93a386Sopenharmony_ci#define MIN_COUNT_FOR_QUAD_LOOP  16
492cb93a386Sopenharmony_ci
493cb93a386Sopenharmony_cistatic void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount,
494cb93a386Sopenharmony_ci                        U8CPU stopAlpha, U8CPU maxValue) {
495cb93a386Sopenharmony_ci    SkASSERT(middleCount >= 0);
496cb93a386Sopenharmony_ci
497cb93a386Sopenharmony_ci    saturated_add(alpha, startAlpha);
498cb93a386Sopenharmony_ci    alpha += 1;
499cb93a386Sopenharmony_ci
500cb93a386Sopenharmony_ci    if (middleCount >= MIN_COUNT_FOR_QUAD_LOOP) {
501cb93a386Sopenharmony_ci        // loop until we're quad-byte aligned
502cb93a386Sopenharmony_ci        while (reinterpret_cast<intptr_t>(alpha) & 0x3) {
503cb93a386Sopenharmony_ci            alpha[0] = SkToU8(alpha[0] + maxValue);
504cb93a386Sopenharmony_ci            alpha += 1;
505cb93a386Sopenharmony_ci            middleCount -= 1;
506cb93a386Sopenharmony_ci        }
507cb93a386Sopenharmony_ci
508cb93a386Sopenharmony_ci        int bigCount = middleCount >> 2;
509cb93a386Sopenharmony_ci        uint32_t* qptr = reinterpret_cast<uint32_t*>(alpha);
510cb93a386Sopenharmony_ci        uint32_t qval = quadplicate_byte(maxValue);
511cb93a386Sopenharmony_ci        do {
512cb93a386Sopenharmony_ci            *qptr++ += qval;
513cb93a386Sopenharmony_ci        } while (--bigCount > 0);
514cb93a386Sopenharmony_ci
515cb93a386Sopenharmony_ci        middleCount &= 3;
516cb93a386Sopenharmony_ci        alpha = reinterpret_cast<uint8_t*> (qptr);
517cb93a386Sopenharmony_ci        // fall through to the following while-loop
518cb93a386Sopenharmony_ci    }
519cb93a386Sopenharmony_ci
520cb93a386Sopenharmony_ci    while (--middleCount >= 0) {
521cb93a386Sopenharmony_ci        alpha[0] = SkToU8(alpha[0] + maxValue);
522cb93a386Sopenharmony_ci        alpha += 1;
523cb93a386Sopenharmony_ci    }
524cb93a386Sopenharmony_ci
525cb93a386Sopenharmony_ci    // potentially this can be off the end of our "legal" alpha values, but that
526cb93a386Sopenharmony_ci    // only happens if stopAlpha is also 0. Rather than test for stopAlpha != 0
527cb93a386Sopenharmony_ci    // every time (slow), we just do it, and ensure that we've allocated extra space
528cb93a386Sopenharmony_ci    // (see the + 1 comment in fStorage[]
529cb93a386Sopenharmony_ci    saturated_add(alpha, stopAlpha);
530cb93a386Sopenharmony_ci}
531cb93a386Sopenharmony_ci
532cb93a386Sopenharmony_civoid MaskSuperBlitter::blitH(int x, int y, int width) {
533cb93a386Sopenharmony_ci    int iy = (y >> SHIFT);
534cb93a386Sopenharmony_ci
535cb93a386Sopenharmony_ci    SkASSERT(iy >= fMask.fBounds.fTop && iy < fMask.fBounds.fBottom);
536cb93a386Sopenharmony_ci    iy -= fMask.fBounds.fTop;   // make it relative to 0
537cb93a386Sopenharmony_ci
538cb93a386Sopenharmony_ci    // This should never happen, but it does.  Until the true cause is
539cb93a386Sopenharmony_ci    // discovered, let's skip this span instead of crashing.
540cb93a386Sopenharmony_ci    // See http://crbug.com/17569.
541cb93a386Sopenharmony_ci    if (iy < 0) {
542cb93a386Sopenharmony_ci        return;
543cb93a386Sopenharmony_ci    }
544cb93a386Sopenharmony_ci
545cb93a386Sopenharmony_ci#ifdef SK_DEBUG
546cb93a386Sopenharmony_ci    {
547cb93a386Sopenharmony_ci        int ix = x >> SHIFT;
548cb93a386Sopenharmony_ci        SkASSERT(ix >= fMask.fBounds.fLeft && ix < fMask.fBounds.fRight);
549cb93a386Sopenharmony_ci    }
550cb93a386Sopenharmony_ci#endif
551cb93a386Sopenharmony_ci
552cb93a386Sopenharmony_ci    x -= SkLeftShift(fMask.fBounds.fLeft, SHIFT);
553cb93a386Sopenharmony_ci
554cb93a386Sopenharmony_ci    // hack, until I figure out why my cubics (I think) go beyond the bounds
555cb93a386Sopenharmony_ci    if (x < 0) {
556cb93a386Sopenharmony_ci        width += x;
557cb93a386Sopenharmony_ci        x = 0;
558cb93a386Sopenharmony_ci    }
559cb93a386Sopenharmony_ci
560cb93a386Sopenharmony_ci    uint8_t* row = fMask.fImage + iy * fMask.fRowBytes + (x >> SHIFT);
561cb93a386Sopenharmony_ci
562cb93a386Sopenharmony_ci    int start = x;
563cb93a386Sopenharmony_ci    int stop = x + width;
564cb93a386Sopenharmony_ci
565cb93a386Sopenharmony_ci    SkASSERT(start >= 0 && stop > start);
566cb93a386Sopenharmony_ci    int fb = start & MASK;
567cb93a386Sopenharmony_ci    int fe = stop & MASK;
568cb93a386Sopenharmony_ci    int n = (stop >> SHIFT) - (start >> SHIFT) - 1;
569cb93a386Sopenharmony_ci
570cb93a386Sopenharmony_ci
571cb93a386Sopenharmony_ci    if (n < 0) {
572cb93a386Sopenharmony_ci        SkASSERT(row >= fMask.fImage);
573cb93a386Sopenharmony_ci        SkASSERT(row < fMask.fImage + kMAX_STORAGE + 1);
574cb93a386Sopenharmony_ci        add_aa_span(row, coverage_to_partial_alpha(fe - fb));
575cb93a386Sopenharmony_ci    } else {
576cb93a386Sopenharmony_ci        fb = SCALE - fb;
577cb93a386Sopenharmony_ci        SkASSERT(row >= fMask.fImage);
578cb93a386Sopenharmony_ci        SkASSERT(row + n + 1 < fMask.fImage + kMAX_STORAGE + 1);
579cb93a386Sopenharmony_ci        add_aa_span(row,  coverage_to_partial_alpha(fb),
580cb93a386Sopenharmony_ci                    n, coverage_to_partial_alpha(fe),
581cb93a386Sopenharmony_ci                    (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT));
582cb93a386Sopenharmony_ci    }
583cb93a386Sopenharmony_ci
584cb93a386Sopenharmony_ci#ifdef SK_DEBUG
585cb93a386Sopenharmony_ci    fCurrX = x + width;
586cb93a386Sopenharmony_ci#endif
587cb93a386Sopenharmony_ci}
588cb93a386Sopenharmony_ci
589cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
590cb93a386Sopenharmony_ci
591cb93a386Sopenharmony_cistatic SkIRect safeRoundOut(const SkRect& src) {
592cb93a386Sopenharmony_ci    // roundOut will pin huge floats to max/min int
593cb93a386Sopenharmony_ci    SkIRect dst = src.roundOut();
594cb93a386Sopenharmony_ci
595cb93a386Sopenharmony_ci    // intersect with a smaller huge rect, so the rect will not be considered empty for being
596cb93a386Sopenharmony_ci    // too large. e.g. { -SK_MaxS32 ... SK_MaxS32 } is considered empty because its width
597cb93a386Sopenharmony_ci    // exceeds signed 32bit.
598cb93a386Sopenharmony_ci    const int32_t limit = SK_MaxS32 >> SK_SUPERSAMPLE_SHIFT;
599cb93a386Sopenharmony_ci    (void)dst.intersect({ -limit, -limit, limit, limit});
600cb93a386Sopenharmony_ci
601cb93a386Sopenharmony_ci    return dst;
602cb93a386Sopenharmony_ci}
603cb93a386Sopenharmony_ci
604cb93a386Sopenharmony_ciconstexpr int kSampleSize = 8;
605cb93a386Sopenharmony_ci#if !defined(SK_DISABLE_AAA)
606cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_OHOS
607cb93a386Sopenharmony_ci    constexpr SkScalar kComplexityThreshold = 8.0;
608cb93a386Sopenharmony_ci#else
609cb93a386Sopenharmony_ci    constexpr SkScalar kComplexityThreshold = 0.25;
610cb93a386Sopenharmony_ci#endif
611cb93a386Sopenharmony_ci#endif
612cb93a386Sopenharmony_ci
613cb93a386Sopenharmony_civoid compute_complexity(const SkPath& path, SkScalar& avgLength, SkScalar& complexity) {
614cb93a386Sopenharmony_ci    int n = path.countPoints();
615cb93a386Sopenharmony_ci    if (n < kSampleSize || path.getBounds().isEmpty()) {
616cb93a386Sopenharmony_ci        // set to invalid value to indicate that we failed to compute
617cb93a386Sopenharmony_ci        avgLength = complexity = -1;
618cb93a386Sopenharmony_ci        return;
619cb93a386Sopenharmony_ci    }
620cb93a386Sopenharmony_ci
621cb93a386Sopenharmony_ci    SkScalar sumLength = 0;
622cb93a386Sopenharmony_ci    SkPoint lastPoint = path.getPoint(0);
623cb93a386Sopenharmony_ci    for(int i = 1; i < kSampleSize; ++i) {
624cb93a386Sopenharmony_ci        SkPoint point = path.getPoint(i);
625cb93a386Sopenharmony_ci        sumLength += SkPoint::Distance(lastPoint, point);
626cb93a386Sopenharmony_ci        lastPoint = point;
627cb93a386Sopenharmony_ci    }
628cb93a386Sopenharmony_ci    avgLength = sumLength / (kSampleSize - 1);
629cb93a386Sopenharmony_ci
630cb93a386Sopenharmony_ci    auto sqr = [](SkScalar x) { return x*x; };
631cb93a386Sopenharmony_ci
632cb93a386Sopenharmony_ci    SkScalar diagonalSqr = sqr(path.getBounds().width()) + sqr(path.getBounds().height());
633cb93a386Sopenharmony_ci
634cb93a386Sopenharmony_ci    // If the path consists of random line segments, the number of intersections should be
635cb93a386Sopenharmony_ci    // proportional to this.
636cb93a386Sopenharmony_ci    SkScalar intersections = sk_ieee_float_divide(sqr(n) * sqr(avgLength), diagonalSqr);
637cb93a386Sopenharmony_ci
638cb93a386Sopenharmony_ci    // The number of intersections per scanline should be proportional to this number.
639cb93a386Sopenharmony_ci    complexity = sk_ieee_float_divide(intersections, path.getBounds().height());
640cb93a386Sopenharmony_ci
641cb93a386Sopenharmony_ci    if (sk_float_isnan(complexity)) {  // it may be possible to have 0.0 / 0.0; inf is fine for us.
642cb93a386Sopenharmony_ci        complexity = -1;
643cb93a386Sopenharmony_ci    }
644cb93a386Sopenharmony_ci}
645cb93a386Sopenharmony_ci
646cb93a386Sopenharmony_cistatic bool ShouldUseAAA(const SkPath& path, SkScalar avgLength, SkScalar complexity) {
647cb93a386Sopenharmony_ci#if defined(SK_DISABLE_AAA)
648cb93a386Sopenharmony_ci    return false;
649cb93a386Sopenharmony_ci#else
650cb93a386Sopenharmony_ci    if (gSkForceAnalyticAA) {
651cb93a386Sopenharmony_ci        return true;
652cb93a386Sopenharmony_ci    }
653cb93a386Sopenharmony_ci    if (!gSkUseAnalyticAA) {
654cb93a386Sopenharmony_ci        return false;
655cb93a386Sopenharmony_ci    }
656cb93a386Sopenharmony_ci    if (path.isRect(nullptr)) {
657cb93a386Sopenharmony_ci        return true;
658cb93a386Sopenharmony_ci    }
659cb93a386Sopenharmony_ci
660cb93a386Sopenharmony_ci    #ifdef SK_SUPPORT_LEGACY_AAA_CHOICE
661cb93a386Sopenharmony_ci        const SkRect& bounds = path.getBounds();
662cb93a386Sopenharmony_ci        // When the path have so many points compared to the size of its
663cb93a386Sopenharmony_ci        // bounds/resolution, it indicates that the path is not quite smooth in
664cb93a386Sopenharmony_ci        // the current resolution: the expected number of turning points in
665cb93a386Sopenharmony_ci        // every pixel row/column is significantly greater than zero. Hence
666cb93a386Sopenharmony_ci        // Aanlytic AA is not likely to produce visible quality improvements,
667cb93a386Sopenharmony_ci        // and Analytic AA might be slower than supersampling.
668cb93a386Sopenharmony_ci        return path.countPoints() < std::max(bounds.width(), bounds.height()) / 2 - 10;
669cb93a386Sopenharmony_ci    #else
670cb93a386Sopenharmony_ci#ifndef SK_BUILD_FOR_OHOS
671cb93a386Sopenharmony_ci        if (path.countPoints() >= path.getBounds().height()) {
672cb93a386Sopenharmony_ci            // SAA is faster than AAA in this case even if there are no
673cb93a386Sopenharmony_ci            // intersections because AAA will have too many scan lines. See
674cb93a386Sopenharmony_ci            // skbug.com/8272
675cb93a386Sopenharmony_ci            return false;
676cb93a386Sopenharmony_ci        }
677cb93a386Sopenharmony_ci#endif
678cb93a386Sopenharmony_ci#ifdef SK_ENABLE_PATH_COMPLEXITY_DFX
679cb93a386Sopenharmony_ci        SkPathComplexityDfx::AddPathComplexityTrace(complexity);
680cb93a386Sopenharmony_ci#endif
681cb93a386Sopenharmony_ci        // We will use AAA if the number of verbs < kSampleSize and therefore complexity < 0
682cb93a386Sopenharmony_ci        return complexity < kComplexityThreshold;
683cb93a386Sopenharmony_ci    #endif
684cb93a386Sopenharmony_ci#endif
685cb93a386Sopenharmony_ci}
686cb93a386Sopenharmony_ci
687cb93a386Sopenharmony_civoid SkScan::SAAFillPath(const SkPath& path, SkBlitter* blitter, const SkIRect& ir,
688cb93a386Sopenharmony_ci                  const SkIRect& clipBounds, bool forceRLE) {
689cb93a386Sopenharmony_ci    bool containedInClip = clipBounds.contains(ir);
690cb93a386Sopenharmony_ci    bool isInverse = path.isInverseFillType();
691cb93a386Sopenharmony_ci
692cb93a386Sopenharmony_ci    // MaskSuperBlitter can't handle drawing outside of ir, so we can't use it
693cb93a386Sopenharmony_ci    // if we're an inverse filltype
694cb93a386Sopenharmony_ci    if (!isInverse && MaskSuperBlitter::CanHandleRect(ir) && !forceRLE) {
695cb93a386Sopenharmony_ci        MaskSuperBlitter superBlit(blitter, ir, clipBounds, isInverse);
696cb93a386Sopenharmony_ci        SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop);
697cb93a386Sopenharmony_ci        sk_fill_path(path, clipBounds, &superBlit, ir.fTop, ir.fBottom, SHIFT, containedInClip);
698cb93a386Sopenharmony_ci    } else {
699cb93a386Sopenharmony_ci        SuperBlitter superBlit(blitter, ir, clipBounds, isInverse);
700cb93a386Sopenharmony_ci        sk_fill_path(path, clipBounds, &superBlit, ir.fTop, ir.fBottom, SHIFT, containedInClip);
701cb93a386Sopenharmony_ci    }
702cb93a386Sopenharmony_ci}
703cb93a386Sopenharmony_ci
704cb93a386Sopenharmony_cistatic int overflows_short_shift(int value, int shift) {
705cb93a386Sopenharmony_ci    const int s = 16 + shift;
706cb93a386Sopenharmony_ci    return (SkLeftShift(value, s) >> s) - value;
707cb93a386Sopenharmony_ci}
708cb93a386Sopenharmony_ci
709cb93a386Sopenharmony_ci/**
710cb93a386Sopenharmony_ci  Would any of the coordinates of this rectangle not fit in a short,
711cb93a386Sopenharmony_ci  when left-shifted by shift?
712cb93a386Sopenharmony_ci*/
713cb93a386Sopenharmony_cistatic int rect_overflows_short_shift(SkIRect rect, int shift) {
714cb93a386Sopenharmony_ci    SkASSERT(!overflows_short_shift(8191, shift));
715cb93a386Sopenharmony_ci    SkASSERT(overflows_short_shift(8192, shift));
716cb93a386Sopenharmony_ci    SkASSERT(!overflows_short_shift(32767, 0));
717cb93a386Sopenharmony_ci    SkASSERT(overflows_short_shift(32768, 0));
718cb93a386Sopenharmony_ci
719cb93a386Sopenharmony_ci    // Since we expect these to succeed, we bit-or together
720cb93a386Sopenharmony_ci    // for a tiny extra bit of speed.
721cb93a386Sopenharmony_ci    return overflows_short_shift(rect.fLeft, shift) |
722cb93a386Sopenharmony_ci           overflows_short_shift(rect.fRight, shift) |
723cb93a386Sopenharmony_ci           overflows_short_shift(rect.fTop, shift) |
724cb93a386Sopenharmony_ci           overflows_short_shift(rect.fBottom, shift);
725cb93a386Sopenharmony_ci}
726cb93a386Sopenharmony_ci
727cb93a386Sopenharmony_civoid SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
728cb93a386Sopenharmony_ci                          SkBlitter* blitter, bool forceRLE) {
729cb93a386Sopenharmony_ci    if (origClip.isEmpty()) {
730cb93a386Sopenharmony_ci        return;
731cb93a386Sopenharmony_ci    }
732cb93a386Sopenharmony_ci
733cb93a386Sopenharmony_ci    const bool isInverse = path.isInverseFillType();
734cb93a386Sopenharmony_ci    SkIRect ir = safeRoundOut(path.getBounds());
735cb93a386Sopenharmony_ci    if (ir.isEmpty()) {
736cb93a386Sopenharmony_ci        if (isInverse) {
737cb93a386Sopenharmony_ci            blitter->blitRegion(origClip);
738cb93a386Sopenharmony_ci        }
739cb93a386Sopenharmony_ci        return;
740cb93a386Sopenharmony_ci    }
741cb93a386Sopenharmony_ci
742cb93a386Sopenharmony_ci    // If the intersection of the path bounds and the clip bounds
743cb93a386Sopenharmony_ci    // will overflow 32767 when << by SHIFT, we can't supersample,
744cb93a386Sopenharmony_ci    // so draw without antialiasing.
745cb93a386Sopenharmony_ci    SkIRect clippedIR;
746cb93a386Sopenharmony_ci    if (isInverse) {
747cb93a386Sopenharmony_ci       // If the path is an inverse fill, it's going to fill the entire
748cb93a386Sopenharmony_ci       // clip, and we care whether the entire clip exceeds our limits.
749cb93a386Sopenharmony_ci       clippedIR = origClip.getBounds();
750cb93a386Sopenharmony_ci    } else {
751cb93a386Sopenharmony_ci       if (!clippedIR.intersect(ir, origClip.getBounds())) {
752cb93a386Sopenharmony_ci           return;
753cb93a386Sopenharmony_ci       }
754cb93a386Sopenharmony_ci    }
755cb93a386Sopenharmony_ci    if (rect_overflows_short_shift(clippedIR, SHIFT)) {
756cb93a386Sopenharmony_ci        SkScan::FillPath(path, origClip, blitter);
757cb93a386Sopenharmony_ci        return;
758cb93a386Sopenharmony_ci    }
759cb93a386Sopenharmony_ci
760cb93a386Sopenharmony_ci    // Our antialiasing can't handle a clip larger than 32767, so we restrict
761cb93a386Sopenharmony_ci    // the clip to that limit here. (the runs[] uses int16_t for its index).
762cb93a386Sopenharmony_ci    //
763cb93a386Sopenharmony_ci    // A more general solution (one that could also eliminate the need to
764cb93a386Sopenharmony_ci    // disable aa based on ir bounds (see overflows_short_shift) would be
765cb93a386Sopenharmony_ci    // to tile the clip/target...
766cb93a386Sopenharmony_ci    SkRegion tmpClipStorage;
767cb93a386Sopenharmony_ci    const SkRegion* clipRgn = &origClip;
768cb93a386Sopenharmony_ci    {
769cb93a386Sopenharmony_ci        static const int32_t kMaxClipCoord = 32767;
770cb93a386Sopenharmony_ci        const SkIRect& bounds = origClip.getBounds();
771cb93a386Sopenharmony_ci        if (bounds.fRight > kMaxClipCoord || bounds.fBottom > kMaxClipCoord) {
772cb93a386Sopenharmony_ci            SkIRect limit = { 0, 0, kMaxClipCoord, kMaxClipCoord };
773cb93a386Sopenharmony_ci            tmpClipStorage.op(origClip, limit, SkRegion::kIntersect_Op);
774cb93a386Sopenharmony_ci            clipRgn = &tmpClipStorage;
775cb93a386Sopenharmony_ci        }
776cb93a386Sopenharmony_ci    }
777cb93a386Sopenharmony_ci    // for here down, use clipRgn, not origClip
778cb93a386Sopenharmony_ci
779cb93a386Sopenharmony_ci    SkScanClipper   clipper(blitter, clipRgn, ir);
780cb93a386Sopenharmony_ci
781cb93a386Sopenharmony_ci    if (clipper.getBlitter() == nullptr) { // clipped out
782cb93a386Sopenharmony_ci        if (isInverse) {
783cb93a386Sopenharmony_ci            blitter->blitRegion(*clipRgn);
784cb93a386Sopenharmony_ci        }
785cb93a386Sopenharmony_ci        return;
786cb93a386Sopenharmony_ci    }
787cb93a386Sopenharmony_ci
788cb93a386Sopenharmony_ci    SkASSERT(clipper.getClipRect() == nullptr ||
789cb93a386Sopenharmony_ci            *clipper.getClipRect() == clipRgn->getBounds());
790cb93a386Sopenharmony_ci
791cb93a386Sopenharmony_ci    // now use the (possibly wrapped) blitter
792cb93a386Sopenharmony_ci    blitter = clipper.getBlitter();
793cb93a386Sopenharmony_ci
794cb93a386Sopenharmony_ci    if (isInverse) {
795cb93a386Sopenharmony_ci        sk_blit_above(blitter, ir, *clipRgn);
796cb93a386Sopenharmony_ci    }
797cb93a386Sopenharmony_ci
798cb93a386Sopenharmony_ci    SkScalar avgLength, complexity;
799cb93a386Sopenharmony_ci    compute_complexity(path, avgLength, complexity);
800cb93a386Sopenharmony_ci
801cb93a386Sopenharmony_ci    if (ShouldUseAAA(path, avgLength, complexity)) {
802cb93a386Sopenharmony_ci        // Do not use AAA if path is too complicated:
803cb93a386Sopenharmony_ci        // there won't be any speedup or significant visual improvement.
804cb93a386Sopenharmony_ci        SkScan::AAAFillPath(path, blitter, ir, clipRgn->getBounds(), forceRLE);
805cb93a386Sopenharmony_ci    } else {
806cb93a386Sopenharmony_ci        SkScan::SAAFillPath(path, blitter, ir, clipRgn->getBounds(), forceRLE);
807cb93a386Sopenharmony_ci    }
808cb93a386Sopenharmony_ci
809cb93a386Sopenharmony_ci    if (isInverse) {
810cb93a386Sopenharmony_ci        sk_blit_below(blitter, ir, *clipRgn);
811cb93a386Sopenharmony_ci    }
812cb93a386Sopenharmony_ci}
813cb93a386Sopenharmony_ci
814cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
815cb93a386Sopenharmony_ci
816cb93a386Sopenharmony_ci#include "src/core/SkRasterClip.h"
817cb93a386Sopenharmony_ci
818cb93a386Sopenharmony_civoid SkScan::FillPath(const SkPath& path, const SkRasterClip& clip, SkBlitter* blitter) {
819cb93a386Sopenharmony_ci    if (clip.isEmpty() || !path.isFinite()) {
820cb93a386Sopenharmony_ci        return;
821cb93a386Sopenharmony_ci    }
822cb93a386Sopenharmony_ci
823cb93a386Sopenharmony_ci    if (clip.isBW()) {
824cb93a386Sopenharmony_ci        FillPath(path, clip.bwRgn(), blitter);
825cb93a386Sopenharmony_ci    } else {
826cb93a386Sopenharmony_ci        SkRegion        tmp;
827cb93a386Sopenharmony_ci        SkAAClipBlitter aaBlitter;
828cb93a386Sopenharmony_ci
829cb93a386Sopenharmony_ci        tmp.setRect(clip.getBounds());
830cb93a386Sopenharmony_ci        aaBlitter.init(blitter, &clip.aaRgn());
831cb93a386Sopenharmony_ci        SkScan::FillPath(path, tmp, &aaBlitter);
832cb93a386Sopenharmony_ci    }
833cb93a386Sopenharmony_ci}
834cb93a386Sopenharmony_ci
835cb93a386Sopenharmony_civoid SkScan::AntiFillPath(const SkPath& path, const SkRasterClip& clip, SkBlitter* blitter) {
836cb93a386Sopenharmony_ci    if (clip.isEmpty() || !path.isFinite()) {
837cb93a386Sopenharmony_ci        return;
838cb93a386Sopenharmony_ci    }
839cb93a386Sopenharmony_ci
840cb93a386Sopenharmony_ci    if (clip.isBW()) {
841cb93a386Sopenharmony_ci        AntiFillPath(path, clip.bwRgn(), blitter, false);
842cb93a386Sopenharmony_ci    } else {
843cb93a386Sopenharmony_ci        SkRegion        tmp;
844cb93a386Sopenharmony_ci        SkAAClipBlitter aaBlitter;
845cb93a386Sopenharmony_ci
846cb93a386Sopenharmony_ci        tmp.setRect(clip.getBounds());
847cb93a386Sopenharmony_ci        aaBlitter.init(blitter, &clip.aaRgn());
848cb93a386Sopenharmony_ci        AntiFillPath(path, tmp, &aaBlitter, true); // SkAAClipBlitter can blitMask, why forceRLE?
849cb93a386Sopenharmony_ci    }
850cb93a386Sopenharmony_ci}
851