xref: /aosp_15_r20/external/skia/src/core/SkScan_AAAPath.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2016 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkColor.h"
9 #include "include/core/SkPath.h"
10 #include "include/core/SkPathTypes.h"
11 #include "include/core/SkRect.h"
12 #include "include/private/base/SkAlign.h"
13 #include "include/private/base/SkAssert.h"
14 #include "include/private/base/SkDebug.h"
15 #include "include/private/base/SkFixed.h"
16 #include "include/private/base/SkMath.h"
17 #include "include/private/base/SkSafe32.h"
18 #include "include/private/base/SkTo.h"
19 #include "src/base/SkTSort.h"
20 #include "src/core/SkAlphaRuns.h"
21 #include "src/core/SkAnalyticEdge.h"
22 #include "src/core/SkBlitter.h"
23 #include "src/core/SkEdge.h"
24 #include "src/core/SkEdgeBuilder.h"
25 #include "src/core/SkMask.h"
26 #include "src/core/SkScan.h"
27 #include "src/core/SkScanPriv.h"
28 
29 #include <algorithm>
30 #include <cstdint>
31 #include <cstring>
32 
33 /*
34 
35 The following is a high-level overview of our analytic anti-aliasing
36 algorithm. We consider a path as a collection of line segments, as
37 quadratic/cubic curves are converted to small line segments. Without loss of
38 generality, let's assume that the draw region is [0, W] x [0, H].
39 
40 Our algorithm is based on horizontal scan lines (y = c_i) as the previous
41 sampling-based algorithm did. However, our algorithm uses non-equal-spaced
42 scan lines, while the previous method always uses equal-spaced scan lines,
43 such as (y = 1/2 + 0, 1/2 + 1, 1/2 + 2, ...) in the previous non-AA algorithm,
44 and (y = 1/8 + 1/4, 1/8 + 2/4, 1/8 + 3/4, ...) in the previous
45 16-supersampling AA algorithm.
46 
47 Our algorithm contains scan lines y = c_i for c_i that is either:
48 
49 1. an integer between [0, H]
50 
51 2. the y value of a line segment endpoint
52 
53 3. the y value of an intersection of two line segments
54 
55 For two consecutive scan lines y = c_i, y = c_{i+1}, we analytically computes
56 the coverage of this horizontal strip of our path on each pixel. This can be
57 done very efficiently because the strip of our path now only consists of
58 trapezoids whose top and bottom edges are y = c_i, y = c_{i+1} (this includes
59 rectangles and triangles as special cases).
60 
61 We now describe how the coverage of single pixel is computed against such a
62 trapezoid. That coverage is essentially the intersection area of a rectangle
63 (e.g., [0, 1] x [c_i, c_{i+1}]) and our trapezoid. However, that intersection
64 could be complicated, as shown in the example region A below:
65 
66 +-----------\----+
67 |            \  C|
68 |             \  |
69 \              \ |
70 |\      A       \|
71 | \              \
72 |  \             |
73 | B \            |
74 +----\-----------+
75 
76 However, we don't have to compute the area of A directly. Instead, we can
77 compute the excluded area, which are B and C, quite easily, because they're
78 just triangles. In fact, we can prove that an excluded region (take B as an
79 example) is either itself a simple trapezoid (including rectangles, triangles,
80 and empty regions), or its opposite (the opposite of B is A + C) is a simple
81 trapezoid. In any case, we can compute its area efficiently.
82 
83 In summary, our algorithm has a higher quality because it generates ground-
84 truth coverages analytically. It is also faster because it has much fewer
85 unnessasary horizontal scan lines. For example, given a triangle path, the
86 number of scan lines in our algorithm is only about 3 + H while the
87 16-supersampling algorithm has about 4H scan lines.
88 
89 */
90 
add_alpha(SkAlpha * alpha,SkAlpha delta)91 static void add_alpha(SkAlpha* alpha, SkAlpha delta) {
92     SkASSERT(*alpha + delta <= 256);
93     *alpha = SkAlphaRuns::CatchOverflow(*alpha + delta);
94 }
95 
safely_add_alpha(SkAlpha * alpha,SkAlpha delta)96 static void safely_add_alpha(SkAlpha* alpha, SkAlpha delta) {
97     *alpha = std::min(0xFF, *alpha + delta);
98 }
99 
100 class AdditiveBlitter : public SkBlitter {
101 public:
~AdditiveBlitter()102     ~AdditiveBlitter() override {}
103 
104     virtual SkBlitter* getRealBlitter(bool forceRealBlitter = false) = 0;
105 
106     virtual void blitAntiH(int x, int y, const SkAlpha antialias[], int len) = 0;
107     virtual void blitAntiH(int x, int y, const SkAlpha alpha)                = 0;
108     virtual void blitAntiH(int x, int y, int width, const SkAlpha alpha)     = 0;
109 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])110     void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
111         SkDEBUGFAIL("Please call real blitter's blitAntiH instead.");
112     }
113 
blitV(int x,int y,int height,SkAlpha alpha)114     void blitV(int x, int y, int height, SkAlpha alpha) override {
115         SkDEBUGFAIL("Please call real blitter's blitV instead.");
116     }
117 
blitH(int x,int y,int width)118     void blitH(int x, int y, int width) override {
119         SkDEBUGFAIL("Please call real blitter's blitH instead.");
120     }
121 
blitRect(int x,int y,int width,int height)122     void blitRect(int x, int y, int width, int height) override {
123         SkDEBUGFAIL("Please call real blitter's blitRect instead.");
124     }
125 
blitAntiRect(int x,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)126     void blitAntiRect(int x, int y, int width, int height, SkAlpha leftAlpha, SkAlpha rightAlpha)
127             override {
128         SkDEBUGFAIL("Please call real blitter's blitAntiRect instead.");
129     }
130 
131     virtual int getWidth() = 0;
132 
133     // Flush the additive alpha cache if floor(y) and floor(nextY) is different
134     // (i.e., we'll start working on a new pixel row).
135     virtual void flush_if_y_changed(SkFixed y, SkFixed nextY) = 0;
136 };
137 
138 // We need this mask blitter because it significantly accelerates small path filling.
139 class MaskAdditiveBlitter : public AdditiveBlitter {
140 public:
141     MaskAdditiveBlitter(SkBlitter*     realBlitter,
142                         const SkIRect& ir,
143                         const SkIRect& clipBounds,
144                         bool           isInverse);
~MaskAdditiveBlitter()145     ~MaskAdditiveBlitter() override { fRealBlitter->blitMask(fMask, fClipRect); }
146 
147     // Most of the time, we still consider this mask blitter as the real blitter
148     // so we can accelerate blitRect and others. But sometimes we want to return
149     // the absolute real blitter (e.g., when we fall back to the old code path).
getRealBlitter(bool forceRealBlitter)150     SkBlitter* getRealBlitter(bool forceRealBlitter) override {
151         return forceRealBlitter ? fRealBlitter : this;
152     }
153 
154     // Virtual function is slow. So don't use this. Directly add alpha to the mask instead.
155     void blitAntiH(int x, int y, const SkAlpha antialias[], int len) override;
156 
157     // Allowing following methods are used to blit rectangles during aaa_walk_convex_edges
158     // Since there aren't many rectangles, we can still bear the slow speed of virtual functions.
159     void blitAntiH(int x, int y, const SkAlpha alpha) override;
160     void blitAntiH(int x, int y, int width, const SkAlpha alpha) override;
161     void blitV(int x, int y, int height, SkAlpha alpha) override;
162     void blitRect(int x, int y, int width, int height) override;
163     void blitAntiRect(int x, int y, int width, int height, SkAlpha leftAlpha, SkAlpha rightAlpha)
164             override;
165 
166     // The flush is only needed for RLE (RunBasedAdditiveBlitter)
flush_if_y_changed(SkFixed y,SkFixed nextY)167     void flush_if_y_changed(SkFixed y, SkFixed nextY) override {}
168 
getWidth()169     int getWidth() override { return fClipRect.width(); }
170 
CanHandleRect(const SkIRect & bounds)171     static bool CanHandleRect(const SkIRect& bounds) {
172         int width = bounds.width();
173         if (width > MaskAdditiveBlitter::kMAX_WIDTH) {
174             return false;
175         }
176         int64_t rb = SkAlign4(width);
177         // use 64bits to detect overflow
178         int64_t storage = rb * bounds.height();
179 
180         return (width <= MaskAdditiveBlitter::kMAX_WIDTH) &&
181                (storage <= MaskAdditiveBlitter::kMAX_STORAGE);
182     }
183 
184     // Return a pointer where pointer[x] corresonds to the alpha of (x, y)
getRow(int y)185     uint8_t* getRow(int y) {
186         if (y != fY) {
187             fY   = y;
188             fRow = fMask.image() + (y - fMask.fBounds.fTop) * fMask.fRowBytes - fMask.fBounds.fLeft;
189         }
190         return fRow;
191     }
192 
193 private:
194     // so we don't try to do very wide things, where the RLE blitter would be faster
195     static const int kMAX_WIDTH   = 32;
196     static const int kMAX_STORAGE = 1024;
197 
198     SkBlitter* fRealBlitter;
199     SkMaskBuilder fMask;
200     SkIRect    fClipRect;
201     // we add 2 because we can write 1 extra byte at either end due to precision error
202     uint32_t fStorage[(kMAX_STORAGE >> 2) + 2];
203 
204     uint8_t* fRow;
205     int      fY;
206 };
207 
MaskAdditiveBlitter(SkBlitter * realBlitter,const SkIRect & ir,const SkIRect & clipBounds,bool isInverse)208 MaskAdditiveBlitter::MaskAdditiveBlitter(SkBlitter*     realBlitter,
209                                          const SkIRect& ir,
210                                          const SkIRect& clipBounds,
211                                          bool           isInverse)
212     : fRealBlitter(realBlitter)
213     , fMask((uint8_t*)fStorage + 1, ir, ir.width(), SkMask::kA8_Format)
214     , fRow(nullptr)
215     , fY(ir.fTop - 1)
216     {
217     SkASSERT(CanHandleRect(ir));
218     SkASSERT(!isInverse);
219 
220     fClipRect = ir;
221     if (!fClipRect.intersect(clipBounds)) {
222         SkASSERT(0);
223         fClipRect.setEmpty();
224     }
225 
226     memset(fStorage, 0, fMask.fBounds.height() * fMask.fRowBytes + 2);
227 }
228 
blitAntiH(int x,int y,const SkAlpha antialias[],int len)229 void MaskAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], int len) {
230     SK_ABORT("Don't use this; directly add alphas to the mask.");
231 }
232 
blitAntiH(int x,int y,const SkAlpha alpha)233 void MaskAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha alpha) {
234     SkASSERT(x >= fMask.fBounds.fLeft - 1);
235     add_alpha(&this->getRow(y)[x], alpha);
236 }
237 
blitAntiH(int x,int y,int width,const SkAlpha alpha)238 void MaskAdditiveBlitter::blitAntiH(int x, int y, int width, const SkAlpha alpha) {
239     SkASSERT(x >= fMask.fBounds.fLeft - 1);
240     uint8_t* row = this->getRow(y);
241     for (int i = 0; i < width; ++i) {
242         add_alpha(&row[x + i], alpha);
243     }
244 }
245 
blitV(int x,int y,int height,SkAlpha alpha)246 void MaskAdditiveBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
247     if (alpha == 0) {
248         return;
249     }
250     SkASSERT(x >= fMask.fBounds.fLeft - 1);
251     // This must be called as if this is a real blitter.
252     // So we directly set alpha rather than adding it.
253     uint8_t* row = this->getRow(y);
254     for (int i = 0; i < height; ++i) {
255         row[x] = alpha;
256         row += fMask.fRowBytes;
257     }
258 }
259 
blitRect(int x,int y,int width,int height)260 void MaskAdditiveBlitter::blitRect(int x, int y, int width, int height) {
261     SkASSERT(x >= fMask.fBounds.fLeft - 1);
262     // This must be called as if this is a real blitter.
263     // So we directly set alpha rather than adding it.
264     uint8_t* row = this->getRow(y);
265     for (int i = 0; i < height; ++i) {
266         memset(row + x, 0xFF, width);
267         row += fMask.fRowBytes;
268     }
269 }
270 
blitAntiRect(int x,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)271 void MaskAdditiveBlitter::blitAntiRect(int     x,
272                                        int     y,
273                                        int     width,
274                                        int     height,
275                                        SkAlpha leftAlpha,
276                                        SkAlpha rightAlpha) {
277     blitV(x, y, height, leftAlpha);
278     blitV(x + 1 + width, y, height, rightAlpha);
279     blitRect(x + 1, y, width, height);
280 }
281 
282 class RunBasedAdditiveBlitter : public AdditiveBlitter {
283 public:
284     RunBasedAdditiveBlitter(SkBlitter*     realBlitter,
285                             const SkIRect& ir,
286                             const SkIRect& clipBounds,
287                             bool           isInverse);
288 
~RunBasedAdditiveBlitter()289     ~RunBasedAdditiveBlitter() override { this->flush(); }
290 
getRealBlitter(bool forceRealBlitter)291     SkBlitter* getRealBlitter(bool forceRealBlitter) override { return fRealBlitter; }
292 
293     void blitAntiH(int x, int y, const SkAlpha antialias[], int len) override;
294     void blitAntiH(int x, int y, const SkAlpha alpha) override;
295     void blitAntiH(int x, int y, int width, const SkAlpha alpha) override;
296 
getWidth()297     int getWidth() override { return fWidth; }
298 
flush_if_y_changed(SkFixed y,SkFixed nextY)299     void flush_if_y_changed(SkFixed y, SkFixed nextY) override {
300         if (SkFixedFloorToInt(y) != SkFixedFloorToInt(nextY)) {
301             this->flush();
302         }
303     }
304 
305 protected:
306     SkBlitter* fRealBlitter;
307 
308     int fCurrY;  // Current y coordinate.
309     int fWidth;  // Widest row of region to be blitted
310     int fLeft;   // Leftmost x coordinate in any row
311     int fTop;    // Initial y coordinate (top of bounds)
312 
313     // The next three variables are used to track a circular buffer that
314     // contains the values used in SkAlphaRuns. These variables should only
315     // ever be updated in advanceRuns(), and fRuns should always point to
316     // a valid SkAlphaRuns...
317     int         fRunsToBuffer;
318     void*       fRunsBuffer;
319     int         fCurrentRun;
320     SkAlphaRuns fRuns;
321 
322     int fOffsetX;
323 
check(int x,int width) const324     bool check(int x, int width) const { return x >= 0 && x + width <= fWidth; }
325 
326     // extra one to store the zero at the end
getRunsSz() const327     int getRunsSz() const { return (fWidth + 1 + (fWidth + 2) / 2) * sizeof(int16_t); }
328 
329     // This function updates the fRuns variable to point to the next buffer space
330     // with adequate storage for a SkAlphaRuns. It mostly just advances fCurrentRun
331     // and resets fRuns to point to an empty scanline.
advanceRuns()332     void advanceRuns() {
333         const size_t kRunsSz = this->getRunsSz();
334         fCurrentRun          = (fCurrentRun + 1) % fRunsToBuffer;
335         fRuns.fRuns          = reinterpret_cast<int16_t*>(reinterpret_cast<uint8_t*>(fRunsBuffer) +
336                                                  fCurrentRun * kRunsSz);
337         fRuns.fAlpha         = reinterpret_cast<SkAlpha*>(fRuns.fRuns + fWidth + 1);
338         fRuns.reset(fWidth);
339     }
340 
341     // Blitting 0xFF and 0 is much faster so we snap alphas close to them
snapAlpha(SkAlpha alpha)342     SkAlpha snapAlpha(SkAlpha alpha) { return alpha > 247 ? 0xFF : alpha < 8 ? 0x00 : alpha; }
343 
flush()344     void flush() {
345         if (fCurrY >= fTop) {
346             SkASSERT(fCurrentRun < fRunsToBuffer);
347             for (int x = 0; fRuns.fRuns[x]; x += fRuns.fRuns[x]) {
348                 // It seems that blitting 255 or 0 is much faster than blitting 254 or 1
349                 fRuns.fAlpha[x] = snapAlpha(fRuns.fAlpha[x]);
350             }
351             if (!fRuns.empty()) {
352                 // SkDEBUGCODE(fRuns.dump();)
353                 fRealBlitter->blitAntiH(fLeft, fCurrY, fRuns.fAlpha, fRuns.fRuns);
354                 this->advanceRuns();
355                 fOffsetX = 0;
356             }
357             fCurrY = fTop - 1;
358         }
359     }
360 
checkY(int y)361     void checkY(int y) {
362         if (y != fCurrY) {
363             this->flush();
364             fCurrY = y;
365         }
366     }
367 };
368 
RunBasedAdditiveBlitter(SkBlitter * realBlitter,const SkIRect & ir,const SkIRect & clipBounds,bool isInverse)369 RunBasedAdditiveBlitter::RunBasedAdditiveBlitter(SkBlitter*     realBlitter,
370                                                  const SkIRect& ir,
371                                                  const SkIRect& clipBounds,
372                                                  bool           isInverse) {
373     fRealBlitter = realBlitter;
374 
375     SkIRect sectBounds;
376     if (isInverse) {
377         // We use the clip bounds instead of the ir, since we may be asked to
378         // draw outside of the rect when we're a inverse filltype
379         sectBounds = clipBounds;
380     } else {
381         if (!sectBounds.intersect(ir, clipBounds)) {
382             sectBounds.setEmpty();
383         }
384     }
385 
386     const int left  = sectBounds.left();
387     const int right = sectBounds.right();
388 
389     fLeft  = left;
390     fWidth = right - left;
391     fTop   = sectBounds.top();
392     fCurrY = fTop - 1;
393 
394     fRunsToBuffer = realBlitter->requestRowsPreserved();
395     fRunsBuffer   = realBlitter->allocBlitMemory(fRunsToBuffer * this->getRunsSz());
396     fCurrentRun   = -1;
397 
398     this->advanceRuns();
399 
400     fOffsetX = 0;
401 }
402 
blitAntiH(int x,int y,const SkAlpha antialias[],int len)403 void RunBasedAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], int len) {
404     checkY(y);
405     x -= fLeft;
406 
407     if (x < 0) {
408         len += x;
409         antialias -= x;
410         x = 0;
411     }
412     len = std::min(len, fWidth - x);
413     SkASSERT(check(x, len));
414 
415     if (x < fOffsetX) {
416         fOffsetX = 0;
417     }
418 
419     fOffsetX = fRuns.add(x, 0, len, 0, 0, fOffsetX);  // Break the run
420     for (int i = 0; i < len; i += fRuns.fRuns[x + i]) {
421         for (int j = 1; j < fRuns.fRuns[x + i]; j++) {
422             fRuns.fRuns[x + i + j]  = 1;
423             fRuns.fAlpha[x + i + j] = fRuns.fAlpha[x + i];
424         }
425         fRuns.fRuns[x + i] = 1;
426     }
427     for (int i = 0; i < len; ++i) {
428         add_alpha(&fRuns.fAlpha[x + i], antialias[i]);
429     }
430 }
431 
blitAntiH(int x,int y,const SkAlpha alpha)432 void RunBasedAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha alpha) {
433     checkY(y);
434     x -= fLeft;
435 
436     if (x < fOffsetX) {
437         fOffsetX = 0;
438     }
439 
440     if (this->check(x, 1)) {
441         fOffsetX = fRuns.add(x, 0, 1, 0, alpha, fOffsetX);
442     }
443 }
444 
blitAntiH(int x,int y,int width,const SkAlpha alpha)445 void RunBasedAdditiveBlitter::blitAntiH(int x, int y, int width, const SkAlpha alpha) {
446     checkY(y);
447     x -= fLeft;
448 
449     if (x < fOffsetX) {
450         fOffsetX = 0;
451     }
452 
453     if (this->check(x, width)) {
454         fOffsetX = fRuns.add(x, 0, width, 0, alpha, fOffsetX);
455     }
456 }
457 
458 // This exists specifically for concave path filling.
459 // In those cases, we can easily accumulate alpha greater than 0xFF.
460 class SafeRLEAdditiveBlitter : public RunBasedAdditiveBlitter {
461 public:
SafeRLEAdditiveBlitter(SkBlitter * realBlitter,const SkIRect & ir,const SkIRect & clipBounds,bool isInverse)462     SafeRLEAdditiveBlitter(SkBlitter*     realBlitter,
463                            const SkIRect& ir,
464                            const SkIRect& clipBounds,
465                            bool           isInverse)
466             : RunBasedAdditiveBlitter(realBlitter, ir, clipBounds, isInverse) {}
467 
468     void blitAntiH(int x, int y, const SkAlpha antialias[], int len) override;
469     void blitAntiH(int x, int y, const SkAlpha alpha) override;
470     void blitAntiH(int x, int y, int width, const SkAlpha alpha) override;
471 };
472 
blitAntiH(int x,int y,const SkAlpha antialias[],int len)473 void SafeRLEAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], int len) {
474     checkY(y);
475     x -= fLeft;
476 
477     if (x < 0) {
478         len += x;
479         antialias -= x;
480         x = 0;
481     }
482     len = std::min(len, fWidth - x);
483     SkASSERT(check(x, len));
484 
485     if (x < fOffsetX) {
486         fOffsetX = 0;
487     }
488 
489     fOffsetX = fRuns.add(x, 0, len, 0, 0, fOffsetX);  // Break the run
490     for (int i = 0; i < len; i += fRuns.fRuns[x + i]) {
491         for (int j = 1; j < fRuns.fRuns[x + i]; j++) {
492             fRuns.fRuns[x + i + j]  = 1;
493             fRuns.fAlpha[x + i + j] = fRuns.fAlpha[x + i];
494         }
495         fRuns.fRuns[x + i] = 1;
496     }
497     for (int i = 0; i < len; ++i) {
498         safely_add_alpha(&fRuns.fAlpha[x + i], antialias[i]);
499     }
500 }
501 
blitAntiH(int x,int y,const SkAlpha alpha)502 void SafeRLEAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha alpha) {
503     checkY(y);
504     x -= fLeft;
505 
506     if (x < fOffsetX) {
507         fOffsetX = 0;
508     }
509 
510     if (check(x, 1)) {
511         // Break the run
512         fOffsetX = fRuns.add(x, 0, 1, 0, 0, fOffsetX);
513         safely_add_alpha(&fRuns.fAlpha[x], alpha);
514     }
515 }
516 
blitAntiH(int x,int y,int width,const SkAlpha alpha)517 void SafeRLEAdditiveBlitter::blitAntiH(int x, int y, int width, const SkAlpha alpha) {
518     checkY(y);
519     x -= fLeft;
520 
521     if (x < fOffsetX) {
522         fOffsetX = 0;
523     }
524 
525     if (check(x, width)) {
526         // Break the run
527         fOffsetX = fRuns.add(x, 0, width, 0, 0, fOffsetX);
528         for (int i = x; i < x + width; i += fRuns.fRuns[i]) {
529             safely_add_alpha(&fRuns.fAlpha[i], alpha);
530         }
531     }
532 }
533 
534 // Return the alpha of a trapezoid whose height is 1
trapezoid_to_alpha(SkFixed l1,SkFixed l2)535 static SkAlpha trapezoid_to_alpha(SkFixed l1, SkFixed l2) {
536     SkASSERT(l1 >= 0 && l2 >= 0);
537     SkFixed area = (l1 + l2) / 2;
538     return SkTo<SkAlpha>(area >> 8);
539 }
540 
541 // The alpha of right-triangle (a, a*b)
partial_triangle_to_alpha(SkFixed a,SkFixed b)542 static SkAlpha partial_triangle_to_alpha(SkFixed a, SkFixed b) {
543     SkASSERT(a <= SK_Fixed1);
544 #if 0
545     // TODO(mtklein): skia:8877
546     SkASSERT(b <= SK_Fixed1);
547 #endif
548 
549     // Approximating...
550     // SkFixed area = SkFixedMul(a, SkFixedMul(a,b)) / 2;
551     SkFixed area = (a >> 11) * (a >> 11) * (b >> 11);
552 
553 #if 0
554     // TODO(mtklein): skia:8877
555     return SkTo<SkAlpha>(area >> 8);
556 #else
557     return SkTo<SkAlpha>((area >> 8) & 0xFF);
558 #endif
559 }
560 
get_partial_alpha(SkAlpha alpha,SkFixed partialHeight)561 static SkAlpha get_partial_alpha(SkAlpha alpha, SkFixed partialHeight) {
562     return SkToU8(SkFixedRoundToInt(alpha * partialHeight));
563 }
564 
get_partial_alpha(SkAlpha alpha,SkAlpha fullAlpha)565 static SkAlpha get_partial_alpha(SkAlpha alpha, SkAlpha fullAlpha) {
566     return (alpha * fullAlpha) >> 8;
567 }
568 
569 // For SkFixed that's close to SK_Fixed1, we can't convert it to alpha by just shifting right.
570 // For example, when f = SK_Fixed1, right shifting 8 will get 256, but we need 255.
571 // This is rarely the problem so we'll only use this for blitting rectangles.
fixed_to_alpha(SkFixed f)572 static SkAlpha fixed_to_alpha(SkFixed f) {
573     SkASSERT(f <= SK_Fixed1);
574     return get_partial_alpha(0xFF, f);
575 }
576 
577 // Suppose that line (l1, y)-(r1, y+1) intersects with (l2, y)-(r2, y+1),
578 // approximate (very coarsely) the x coordinate of the intersection.
approximate_intersection(SkFixed l1,SkFixed r1,SkFixed l2,SkFixed r2)579 static SkFixed approximate_intersection(SkFixed l1, SkFixed r1, SkFixed l2, SkFixed r2) {
580     if (l1 > r1) {
581         std::swap(l1, r1);
582     }
583     if (l2 > r2) {
584         std::swap(l2, r2);
585     }
586     return (std::max(l1, l2) + std::min(r1, r2)) / 2;
587 }
588 
589 // Here we always send in l < SK_Fixed1, and the first alpha we want to compute is alphas[0]
compute_alpha_above_line(SkAlpha * alphas,SkFixed l,SkFixed r,SkFixed dY,SkAlpha fullAlpha)590 static void compute_alpha_above_line(SkAlpha* alphas,
591                                      SkFixed  l,
592                                      SkFixed  r,
593                                      SkFixed  dY,
594                                      SkAlpha  fullAlpha) {
595     SkASSERT(l <= r);
596     SkASSERT(l >> 16 == 0);
597     int R = SkFixedCeilToInt(r);
598     if (R == 0) {
599         return;
600     } else if (R == 1) {
601         alphas[0] = get_partial_alpha(((R << 17) - l - r) >> 9, fullAlpha);
602     } else {
603         SkFixed first   = SK_Fixed1 - l;        // horizontal edge length of the left-most triangle
604         SkFixed last    = r - ((R - 1) << 16);  // horizontal edge length of the right-most triangle
605         SkFixed firstH  = SkFixedMul(first, dY);  // vertical edge of the left-most triangle
606         alphas[0]       = SkFixedMul(first, firstH) >> 9;  // triangle alpha
607         SkFixed alpha16 = Sk32_sat_add(firstH, dY >> 1);                // rectangle plus triangle
608         for (int i = 1; i < R - 1; ++i) {
609             alphas[i] = alpha16 >> 8;
610             alpha16 = Sk32_sat_add(alpha16, dY);
611         }
612         alphas[R - 1] = fullAlpha - partial_triangle_to_alpha(last, dY);
613     }
614 }
615 
616 // Here we always send in l < SK_Fixed1, and the first alpha we want to compute is alphas[0]
compute_alpha_below_line(SkAlpha * alphas,SkFixed l,SkFixed r,SkFixed dY,SkAlpha fullAlpha)617 static void compute_alpha_below_line(SkAlpha* alphas,
618                                      SkFixed  l,
619                                      SkFixed  r,
620                                      SkFixed  dY,
621                                      SkAlpha  fullAlpha) {
622     SkASSERT(l <= r);
623     SkASSERT(l >> 16 == 0);
624     int R = SkFixedCeilToInt(r);
625     if (R == 0) {
626         return;
627     } else if (R == 1) {
628         alphas[0] = get_partial_alpha(trapezoid_to_alpha(l, r), fullAlpha);
629     } else {
630         SkFixed first   = SK_Fixed1 - l;        // horizontal edge length of the left-most triangle
631         SkFixed last    = r - ((R - 1) << 16);  // horizontal edge length of the right-most triangle
632         SkFixed lastH   = SkFixedMul(last, dY);          // vertical edge of the right-most triangle
633         alphas[R - 1]   = SkFixedMul(last, lastH) >> 9;  // triangle alpha
634         SkFixed alpha16 = Sk32_sat_add(lastH, dY >> 1);             // rectangle plus triangle
635         for (int i = R - 2; i > 0; i--) {
636             alphas[i] = (alpha16 >> 8) & 0xFF;
637             alpha16 = Sk32_sat_add(alpha16, dY);
638         }
639         alphas[0] = fullAlpha - partial_triangle_to_alpha(first, dY);
640     }
641 }
642 
643 // Note that if fullAlpha != 0xFF, we'll multiply alpha by fullAlpha
blit_single_alpha(AdditiveBlitter * blitter,int y,int x,SkAlpha alpha,SkAlpha fullAlpha,SkAlpha * maskRow,bool noRealBlitter)644 static void blit_single_alpha(AdditiveBlitter* blitter,
645                               int y,
646                               int x,
647                               SkAlpha alpha,
648                               SkAlpha fullAlpha,
649                               SkAlpha* maskRow,
650                               bool noRealBlitter) {
651     if (maskRow) {
652         if (fullAlpha == 0xFF && !noRealBlitter) {  // noRealBlitter is needed for concave paths
653             maskRow[x] = alpha;
654         } else {
655             safely_add_alpha(&maskRow[x], get_partial_alpha(alpha, fullAlpha));
656         }
657     } else {
658         if (fullAlpha == 0xFF && !noRealBlitter) {
659             blitter->getRealBlitter()->blitV(x, y, 1, alpha);
660         } else {
661             blitter->blitAntiH(x, y, get_partial_alpha(alpha, fullAlpha));
662         }
663     }
664 }
665 
blit_two_alphas(AdditiveBlitter * blitter,int y,int x,SkAlpha a1,SkAlpha a2,SkAlpha fullAlpha,SkAlpha * maskRow,bool noRealBlitter)666 static void blit_two_alphas(AdditiveBlitter* blitter,
667                             int y,
668                             int x,
669                             SkAlpha a1,
670                             SkAlpha a2,
671                             SkAlpha fullAlpha,
672                             SkAlpha* maskRow,
673                             bool noRealBlitter) {
674     if (maskRow) {
675         safely_add_alpha(&maskRow[x], a1);
676         safely_add_alpha(&maskRow[x + 1], a2);
677     } else {
678         if (fullAlpha == 0xFF && !noRealBlitter) {
679             blitter->getRealBlitter()->blitAntiH2(x, y, a1, a2);
680         } else {
681             blitter->blitAntiH(x, y, a1);
682             blitter->blitAntiH(x + 1, y, a2);
683         }
684     }
685 }
686 
blit_full_alpha(AdditiveBlitter * blitter,int y,int x,int len,SkAlpha fullAlpha,SkAlpha * maskRow,bool noRealBlitter)687 static void blit_full_alpha(AdditiveBlitter* blitter,
688                             int y,
689                             int x,
690                             int len,
691                             SkAlpha fullAlpha,
692                             SkAlpha* maskRow,
693                             bool noRealBlitter) {
694     if (maskRow) {
695         for (int i = 0; i < len; ++i) {
696             safely_add_alpha(&maskRow[x + i], fullAlpha);
697         }
698     } else {
699         if (fullAlpha == 0xFF && !noRealBlitter) {
700             blitter->getRealBlitter()->blitH(x, y, len);
701         } else {
702             blitter->blitAntiH(x, y, len, fullAlpha);
703         }
704     }
705 }
706 
blit_aaa_trapezoid_row(AdditiveBlitter * blitter,int y,SkFixed ul,SkFixed ur,SkFixed ll,SkFixed lr,SkFixed lDY,SkFixed rDY,SkAlpha fullAlpha,SkAlpha * maskRow,bool noRealBlitter)707 static void blit_aaa_trapezoid_row(AdditiveBlitter* blitter,
708                                    int              y,
709                                    SkFixed          ul,
710                                    SkFixed          ur,
711                                    SkFixed          ll,
712                                    SkFixed          lr,
713                                    SkFixed          lDY,
714                                    SkFixed          rDY,
715                                    SkAlpha          fullAlpha,
716                                    SkAlpha*         maskRow,
717                                    bool             noRealBlitter) {
718     int L = SkFixedFloorToInt(ul), R = SkFixedCeilToInt(lr);
719     int len = R - L;
720 
721     if (len == 1) {
722         SkAlpha alpha = trapezoid_to_alpha(ur - ul, lr - ll);
723         blit_single_alpha(blitter, y, L, alpha, fullAlpha, maskRow, noRealBlitter);
724         return;
725     }
726 
727     const int kQuickLen = 31;
728     alignas(2) char quickMemory[(sizeof(SkAlpha) * 2 + sizeof(int16_t)) * (kQuickLen + 1)];
729     SkAlpha*  alphas;
730 
731     if (len <= kQuickLen) {
732         alphas = (SkAlpha*)quickMemory;
733     } else {
734         alphas = new SkAlpha[(len + 1) * (sizeof(SkAlpha) * 2 + sizeof(int16_t))];
735     }
736 
737     SkAlpha* tempAlphas = alphas + len + 1;
738     int16_t* runs       = (int16_t*)(alphas + (len + 1) * 2);
739 
740     for (int i = 0; i < len; ++i) {
741         runs[i]   = 1;
742         alphas[i] = fullAlpha;
743     }
744     runs[len] = 0;
745 
746     int uL = SkFixedFloorToInt(ul);
747     int lL = SkFixedCeilToInt(ll);
748     if (uL + 2 == lL) {  // We only need to compute two triangles, accelerate this special case
749         SkFixed first  = SkIntToFixed(uL) + SK_Fixed1 - ul;
750         SkFixed second = ll - ul - first;
751         SkAlpha a1     = fullAlpha - partial_triangle_to_alpha(first, lDY);
752         SkAlpha a2     = partial_triangle_to_alpha(second, lDY);
753         alphas[0]      = alphas[0] > a1 ? alphas[0] - a1 : 0;
754         alphas[1]      = alphas[1] > a2 ? alphas[1] - a2 : 0;
755     } else {
756         compute_alpha_below_line(
757                 tempAlphas + uL - L, ul - SkIntToFixed(uL), ll - SkIntToFixed(uL), lDY, fullAlpha);
758         for (int i = uL; i < lL; ++i) {
759             if (alphas[i - L] > tempAlphas[i - L]) {
760                 alphas[i - L] -= tempAlphas[i - L];
761             } else {
762                 alphas[i - L] = 0;
763             }
764         }
765     }
766 
767     int uR = SkFixedFloorToInt(ur);
768     int lR = SkFixedCeilToInt(lr);
769     if (uR + 2 == lR) {  // We only need to compute two triangles, accelerate this special case
770         SkFixed first   = SkIntToFixed(uR) + SK_Fixed1 - ur;
771         SkFixed second  = lr - ur - first;
772         SkAlpha a1      = partial_triangle_to_alpha(first, rDY);
773         SkAlpha a2      = fullAlpha - partial_triangle_to_alpha(second, rDY);
774         alphas[len - 2] = alphas[len - 2] > a1 ? alphas[len - 2] - a1 : 0;
775         alphas[len - 1] = alphas[len - 1] > a2 ? alphas[len - 1] - a2 : 0;
776     } else {
777         compute_alpha_above_line(
778                 tempAlphas + uR - L, ur - SkIntToFixed(uR), lr - SkIntToFixed(uR), rDY, fullAlpha);
779         for (int i = uR; i < lR; ++i) {
780             if (alphas[i - L] > tempAlphas[i - L]) {
781                 alphas[i - L] -= tempAlphas[i - L];
782             } else {
783                 alphas[i - L] = 0;
784             }
785         }
786     }
787 
788     if (maskRow) {
789         for (int i = 0; i < len; ++i) {
790             safely_add_alpha(&maskRow[L + i], alphas[i]);
791         }
792     } else {
793         if (fullAlpha == 0xFF && !noRealBlitter) {
794             // Real blitter is faster than RunBasedAdditiveBlitter
795             blitter->getRealBlitter()->blitAntiH(L, y, alphas, runs);
796         } else {
797             blitter->blitAntiH(L, y, alphas, len);
798         }
799     }
800 
801     if (len > kQuickLen) {
802         delete[] alphas;
803     }
804 }
805 
blit_trapezoid_row(AdditiveBlitter * blitter,int y,SkFixed ul,SkFixed ur,SkFixed ll,SkFixed lr,SkFixed lDY,SkFixed rDY,SkAlpha fullAlpha,SkAlpha * maskRow,bool noRealBlitter)806 static void blit_trapezoid_row(AdditiveBlitter* blitter,
807                                int y,
808                                SkFixed ul,
809                                SkFixed ur,
810                                SkFixed ll,
811                                SkFixed lr,
812                                SkFixed lDY,
813                                SkFixed rDY,
814                                SkAlpha fullAlpha,
815                                SkAlpha* maskRow,
816                                bool noRealBlitter) {
817     SkASSERT(lDY >= 0 && rDY >= 0);  // We should only send in the absolte value
818 
819     if (ul > ur) {
820         return;
821     }
822 
823     // Edge crosses. Approximate it. This should only happend due to precision limit,
824     // so the approximation could be very coarse.
825     if (ll > lr) {
826         ll = lr = approximate_intersection(ul, ll, ur, lr);
827     }
828 
829     if (ul == ur && ll == lr) {
830         return;  // empty trapzoid
831     }
832 
833     // We're going to use the left line ul-ll and the rite line ur-lr
834     // to exclude the area that's not covered by the path.
835     // Swapping (ul, ll) or (ur, lr) won't affect that exclusion
836     // so we'll do that for simplicity.
837     if (ul > ll) {
838         std::swap(ul, ll);
839     }
840     if (ur > lr) {
841         std::swap(ur, lr);
842     }
843 
844     SkFixed joinLeft = SkFixedCeilToFixed(ll);
845     SkFixed joinRite = SkFixedFloorToFixed(ur);
846     if (joinLeft <= joinRite) {  // There's a rect from joinLeft to joinRite that we can blit
847         if (ul < joinLeft) {
848             int len = SkFixedCeilToInt(joinLeft - ul);
849             if (len == 1) {
850                 SkAlpha alpha = trapezoid_to_alpha(joinLeft - ul, joinLeft - ll);
851                 blit_single_alpha(blitter,
852                                   y,
853                                   ul >> 16,
854                                   alpha,
855                                   fullAlpha,
856                                   maskRow,
857                                   noRealBlitter);
858             } else if (len == 2) {
859                 SkFixed first  = joinLeft - SK_Fixed1 - ul;
860                 SkFixed second = ll - ul - first;
861                 SkAlpha a1     = partial_triangle_to_alpha(first, lDY);
862                 SkAlpha a2     = fullAlpha - partial_triangle_to_alpha(second, lDY);
863                 blit_two_alphas(blitter,
864                                 y,
865                                 ul >> 16,
866                                 a1,
867                                 a2,
868                                 fullAlpha,
869                                 maskRow,
870                                 noRealBlitter);
871             } else {
872                 blit_aaa_trapezoid_row(blitter,
873                                        y,
874                                        ul,
875                                        joinLeft,
876                                        ll,
877                                        joinLeft,
878                                        lDY,
879                                        SK_MaxS32,
880                                        fullAlpha,
881                                        maskRow,
882                                        noRealBlitter);
883             }
884         }
885         // SkAAClip requires that we blit from left to right.
886         // Hence we must blit [ul, joinLeft] before blitting [joinLeft, joinRite]
887         if (joinLeft < joinRite) {
888             blit_full_alpha(blitter,
889                             y,
890                             SkFixedFloorToInt(joinLeft),
891                             SkFixedFloorToInt(joinRite - joinLeft),
892                             fullAlpha,
893                             maskRow,
894                             noRealBlitter);
895         }
896         if (lr > joinRite) {
897             int len = SkFixedCeilToInt(lr - joinRite);
898             if (len == 1) {
899                 SkAlpha alpha = trapezoid_to_alpha(ur - joinRite, lr - joinRite);
900                 blit_single_alpha(blitter,
901                                   y,
902                                   joinRite >> 16,
903                                   alpha,
904                                   fullAlpha,
905                                   maskRow,
906                                   noRealBlitter);
907             } else if (len == 2) {
908                 SkFixed first  = joinRite + SK_Fixed1 - ur;
909                 SkFixed second = lr - ur - first;
910                 SkAlpha a1     = fullAlpha - partial_triangle_to_alpha(first, rDY);
911                 SkAlpha a2     = partial_triangle_to_alpha(second, rDY);
912                 blit_two_alphas(blitter,
913                                 y,
914                                 joinRite >> 16,
915                                 a1,
916                                 a2,
917                                 fullAlpha,
918                                 maskRow,
919                                 noRealBlitter);
920             } else {
921                 blit_aaa_trapezoid_row(blitter,
922                                        y,
923                                        joinRite,
924                                        ur,
925                                        joinRite,
926                                        lr,
927                                        SK_MaxS32,
928                                        rDY,
929                                        fullAlpha,
930                                        maskRow,
931                                        noRealBlitter);
932             }
933         }
934     } else {
935         blit_aaa_trapezoid_row(blitter,
936                                y,
937                                ul,
938                                ur,
939                                ll,
940                                lr,
941                                lDY,
942                                rDY,
943                                fullAlpha,
944                                maskRow,
945                                noRealBlitter);
946     }
947 }
948 
operator <(const SkAnalyticEdge & a,const SkAnalyticEdge & b)949 static bool operator<(const SkAnalyticEdge& a, const SkAnalyticEdge& b) {
950     int valuea = a.fUpperY;
951     int valueb = b.fUpperY;
952 
953     if (valuea == valueb) {
954         valuea = a.fX;
955         valueb = b.fX;
956     }
957 
958     if (valuea == valueb) {
959         valuea = a.fDX;
960         valueb = b.fDX;
961     }
962 
963     return valuea < valueb;
964 }
965 
sort_edges(SkAnalyticEdge * list[],int count,SkAnalyticEdge ** last)966 static SkAnalyticEdge* sort_edges(SkAnalyticEdge* list[], int count, SkAnalyticEdge** last) {
967     SkTQSort(list, list + count);
968 
969     // now make the edges linked in sorted order
970     for (int i = 1; i < count; ++i) {
971         list[i - 1]->fNext = list[i];
972         list[i]->fPrev     = list[i - 1];
973     }
974 
975     *last = list[count - 1];
976     return list[0];
977 }
978 
validate_sort(const SkAnalyticEdge * edge)979 static void validate_sort(const SkAnalyticEdge* edge) {
980 #ifdef SK_DEBUG
981     SkFixed y = SkIntToFixed(-32768);
982 
983     while (edge->fUpperY != SK_MaxS32) {
984         edge->validate();
985         SkASSERT(y <= edge->fUpperY);
986 
987         y    = edge->fUpperY;
988         edge = (SkAnalyticEdge*)edge->fNext;
989     }
990 #endif
991 }
992 
993 // For an edge, we consider it smooth if the Dx doesn't change much, and Dy is large enough
994 // For curves that are updating, the Dx is not changing much if fQDx/fCDx and fQDy/fCDy are
995 // relatively large compared to fQDDx/QCDDx and fQDDy/fCDDy
is_smooth_enough(SkAnalyticEdge * thisEdge,SkAnalyticEdge * nextEdge,int stop_y)996 static bool is_smooth_enough(SkAnalyticEdge* thisEdge, SkAnalyticEdge* nextEdge, int stop_y) {
997     if (thisEdge->fCurveCount < 0) {
998         const SkCubicEdge& cEdge   = static_cast<SkAnalyticCubicEdge*>(thisEdge)->fCEdge;
999         int                ddshift = cEdge.fCurveShift;
1000         return SkAbs32(cEdge.fCDx) >> 1 >= SkAbs32(cEdge.fCDDx) >> ddshift &&
1001                SkAbs32(cEdge.fCDy) >> 1 >= SkAbs32(cEdge.fCDDy) >> ddshift &&
1002                // current Dy is (fCDy - (fCDDy >> ddshift)) >> dshift
1003                (cEdge.fCDy - (cEdge.fCDDy >> ddshift)) >> cEdge.fCubicDShift >= SK_Fixed1;
1004     } else if (thisEdge->fCurveCount > 0) {
1005         const SkQuadraticEdge& qEdge = static_cast<SkAnalyticQuadraticEdge*>(thisEdge)->fQEdge;
1006         return SkAbs32(qEdge.fQDx) >> 1 >= SkAbs32(qEdge.fQDDx) &&
1007                SkAbs32(qEdge.fQDy) >> 1 >= SkAbs32(qEdge.fQDDy) &&
1008                // current Dy is (fQDy - fQDDy) >> shift
1009                (qEdge.fQDy - qEdge.fQDDy) >> qEdge.fCurveShift >= SK_Fixed1;
1010     }
1011     // DDx should be small and Dy should be large
1012     return SkAbs32(Sk32_sat_sub(nextEdge->fDX, thisEdge->fDX)) <= SK_Fixed1 &&
1013            nextEdge->fLowerY - nextEdge->fUpperY >= SK_Fixed1;
1014 }
1015 
1016 // Check if the leftE and riteE are changing smoothly in terms of fDX.
1017 // If yes, we can later skip the fractional y and directly jump to integer y.
is_smooth_enough(SkAnalyticEdge * leftE,SkAnalyticEdge * riteE,SkAnalyticEdge * currE,int stop_y)1018 static bool is_smooth_enough(SkAnalyticEdge* leftE,
1019                              SkAnalyticEdge* riteE,
1020                              SkAnalyticEdge* currE,
1021                              int             stop_y) {
1022     if (currE->fUpperY >= SkLeftShift(stop_y, 16)) {
1023         return false;  // We're at the end so we won't skip anything
1024     }
1025     if (leftE->fLowerY + SK_Fixed1 < riteE->fLowerY) {
1026         return is_smooth_enough(leftE, currE, stop_y);  // Only leftE is changing
1027     } else if (leftE->fLowerY > riteE->fLowerY + SK_Fixed1) {
1028         return is_smooth_enough(riteE, currE, stop_y);  // Only riteE is changing
1029     }
1030 
1031     // Now both edges are changing, find the second next edge
1032     SkAnalyticEdge* nextCurrE = currE->fNext;
1033     if (nextCurrE->fUpperY >= stop_y << 16) {  // Check if we're at the end
1034         return false;
1035     }
1036     // Ensure that currE is the next left edge and nextCurrE is the next right edge. Swap if not.
1037     if (nextCurrE->fUpperX < currE->fUpperX) {
1038         std::swap(currE, nextCurrE);
1039     }
1040     return is_smooth_enough(leftE, currE, stop_y) && is_smooth_enough(riteE, nextCurrE, stop_y);
1041 }
1042 
aaa_walk_convex_edges(SkAnalyticEdge * prevHead,AdditiveBlitter * blitter,int start_y,int stop_y,SkFixed leftBound,SkFixed riteBound,bool isUsingMask)1043 static void aaa_walk_convex_edges(SkAnalyticEdge*  prevHead,
1044                                   AdditiveBlitter* blitter,
1045                                   int              start_y,
1046                                   int              stop_y,
1047                                   SkFixed          leftBound,
1048                                   SkFixed          riteBound,
1049                                   bool             isUsingMask) {
1050     validate_sort((SkAnalyticEdge*)prevHead->fNext);
1051 
1052     SkAnalyticEdge* leftE = (SkAnalyticEdge*)prevHead->fNext;
1053     SkAnalyticEdge* riteE = (SkAnalyticEdge*)leftE->fNext;
1054     SkAnalyticEdge* currE = (SkAnalyticEdge*)riteE->fNext;
1055 
1056     SkFixed y = std::max(leftE->fUpperY, riteE->fUpperY);
1057 
1058     for (;;) {
1059         // We have to check fLowerY first because some edges might be alone (e.g., there's only
1060         // a left edge but no right edge in a given y scan line) due to precision limit.
1061         while (leftE->fLowerY <= y) {  // Due to smooth jump, we may pass multiple short edges
1062             if (!leftE->update(y)) {
1063                 if (SkFixedFloorToInt(currE->fUpperY) >= stop_y) {
1064                     goto END_WALK;
1065                 }
1066                 leftE = currE;
1067                 currE = (SkAnalyticEdge*)currE->fNext;
1068             }
1069         }
1070         while (riteE->fLowerY <= y) {  // Due to smooth jump, we may pass multiple short edges
1071             if (!riteE->update(y)) {
1072                 if (SkFixedFloorToInt(currE->fUpperY) >= stop_y) {
1073                     goto END_WALK;
1074                 }
1075                 riteE = currE;
1076                 currE = (SkAnalyticEdge*)currE->fNext;
1077             }
1078         }
1079 
1080         SkASSERT(leftE);
1081         SkASSERT(riteE);
1082 
1083         // check our bottom clip
1084         if (SkFixedFloorToInt(y) >= stop_y) {
1085             break;
1086         }
1087 
1088         SkASSERT(SkFixedFloorToInt(leftE->fUpperY) <= stop_y);
1089         SkASSERT(SkFixedFloorToInt(riteE->fUpperY) <= stop_y);
1090 
1091         leftE->goY(y);
1092         riteE->goY(y);
1093 
1094         if (leftE->fX > riteE->fX || (leftE->fX == riteE->fX && leftE->fDX > riteE->fDX)) {
1095             std::swap(leftE, riteE);
1096         }
1097 
1098         SkFixed local_bot_fixed = std::min(leftE->fLowerY, riteE->fLowerY);
1099         if (is_smooth_enough(leftE, riteE, currE, stop_y)) {
1100             local_bot_fixed = SkFixedCeilToFixed(local_bot_fixed);
1101         }
1102         local_bot_fixed = std::min(local_bot_fixed, SkIntToFixed(stop_y));
1103 
1104         SkFixed left  = std::max(leftBound, leftE->fX);
1105         SkFixed dLeft = leftE->fDX;
1106         SkFixed rite  = std::min(riteBound, riteE->fX);
1107         SkFixed dRite = riteE->fDX;
1108         if (0 == (dLeft | dRite)) {
1109             int     fullLeft    = SkFixedCeilToInt(left);
1110             int     fullRite    = SkFixedFloorToInt(rite);
1111             SkFixed partialLeft = SkIntToFixed(fullLeft) - left;
1112             SkFixed partialRite = rite - SkIntToFixed(fullRite);
1113             int     fullTop     = SkFixedCeilToInt(y);
1114             int     fullBot     = SkFixedFloorToInt(local_bot_fixed);
1115             SkFixed partialTop  = SkIntToFixed(fullTop) - y;
1116             SkFixed partialBot  = local_bot_fixed - SkIntToFixed(fullBot);
1117             if (fullTop > fullBot) {  // The rectangle is within one pixel height...
1118                 partialTop -= (SK_Fixed1 - partialBot);
1119                 partialBot = 0;
1120             }
1121 
1122             if (fullRite >= fullLeft) {
1123                 if (partialTop > 0) {  // blit first partial row
1124                     if (partialLeft > 0) {
1125                         blitter->blitAntiH(fullLeft - 1,
1126                                            fullTop - 1,
1127                                            fixed_to_alpha(SkFixedMul(partialTop, partialLeft)));
1128                     }
1129                     blitter->blitAntiH(
1130                             fullLeft, fullTop - 1, fullRite - fullLeft, fixed_to_alpha(partialTop));
1131                     if (partialRite > 0) {
1132                         blitter->blitAntiH(fullRite,
1133                                            fullTop - 1,
1134                                            fixed_to_alpha(SkFixedMul(partialTop, partialRite)));
1135                     }
1136                     blitter->flush_if_y_changed(y, y + partialTop);
1137                 }
1138 
1139                 // Blit all full-height rows from fullTop to fullBot
1140                 if (fullBot > fullTop &&
1141                     // SkAAClip cannot handle the empty rect so check the non-emptiness here
1142                     // (bug chromium:662800)
1143                     (fullRite > fullLeft || fixed_to_alpha(partialLeft) > 0 ||
1144                      fixed_to_alpha(partialRite) > 0)) {
1145                     blitter->getRealBlitter()->blitAntiRect(fullLeft - 1,
1146                                                             fullTop,
1147                                                             fullRite - fullLeft,
1148                                                             fullBot - fullTop,
1149                                                             fixed_to_alpha(partialLeft),
1150                                                             fixed_to_alpha(partialRite));
1151                 }
1152 
1153                 if (partialBot > 0) {  // blit last partial row
1154                     if (partialLeft > 0) {
1155                         blitter->blitAntiH(fullLeft - 1,
1156                                            fullBot,
1157                                            fixed_to_alpha(SkFixedMul(partialBot, partialLeft)));
1158                     }
1159                     blitter->blitAntiH(
1160                             fullLeft, fullBot, fullRite - fullLeft, fixed_to_alpha(partialBot));
1161                     if (partialRite > 0) {
1162                         blitter->blitAntiH(fullRite,
1163                                            fullBot,
1164                                            fixed_to_alpha(SkFixedMul(partialBot, partialRite)));
1165                     }
1166                 }
1167             } else {
1168                 // Normal conditions, this means left and rite are within the same pixel, but if
1169                 // both left and rite were < leftBounds or > rightBounds, both edges are clipped and
1170                 // we should not do any blitting (particularly since the negative width saturates to
1171                 // full alpha).
1172                 SkFixed width = rite - left;
1173                 if (width > 0) {
1174                     if (partialTop > 0) {
1175                         blitter->blitAntiH(fullLeft - 1,
1176                                            fullTop - 1,
1177                                            1,
1178                                            fixed_to_alpha(SkFixedMul(partialTop, width)));
1179                         blitter->flush_if_y_changed(y, y + partialTop);
1180                     }
1181                     if (fullBot > fullTop) {
1182                         blitter->getRealBlitter()->blitV(
1183                                 fullLeft - 1, fullTop, fullBot - fullTop, fixed_to_alpha(width));
1184                     }
1185                     if (partialBot > 0) {
1186                         blitter->blitAntiH(fullLeft - 1,
1187                                            fullBot,
1188                                            1,
1189                                            fixed_to_alpha(SkFixedMul(partialBot, width)));
1190                     }
1191                 }
1192             }
1193 
1194             y = local_bot_fixed;
1195         } else {
1196             // The following constant are used to snap X
1197             // We snap X mainly for speedup (no tiny triangle) and
1198             // avoiding edge cases caused by precision errors
1199             const SkFixed kSnapDigit = SK_Fixed1 >> 4;
1200             const SkFixed kSnapHalf  = kSnapDigit >> 1;
1201             const SkFixed kSnapMask  = (-1 ^ (kSnapDigit - 1));
1202             left += kSnapHalf;
1203             rite += kSnapHalf;  // For fast rounding
1204 
1205             // Number of blit_trapezoid_row calls we'll have
1206             int count = SkFixedCeilToInt(local_bot_fixed) - SkFixedFloorToInt(y);
1207 
1208             // If we're using mask blitter, we advance the mask row in this function
1209             // to save some "if" condition checks.
1210             SkAlpha* maskRow = isUsingMask
1211                                        ? static_cast<MaskAdditiveBlitter*>(blitter)->getRow(y >> 16)
1212                                        : nullptr;
1213 
1214             // Instead of writing one loop that handles both partial-row blit_trapezoid_row
1215             // and full-row trapezoid_row together, we use the following 3-stage flow to
1216             // handle partial-row blit and full-row blit separately. It will save us much time
1217             // on changing y, left, and rite.
1218             if (count > 1) {
1219                 if ((int)(y & 0xFFFF0000) != y) {  // There's a partial-row on the top
1220                     count--;
1221                     SkFixed nextY    = SkFixedCeilToFixed(y + 1);
1222                     SkFixed dY       = nextY - y;
1223                     SkFixed nextLeft = left + SkFixedMul(dLeft, dY);
1224                     SkFixed nextRite = rite + SkFixedMul(dRite, dY);
1225                     SkASSERT((left & kSnapMask) >= leftBound && (rite & kSnapMask) <= riteBound &&
1226                              (nextLeft & kSnapMask) >= leftBound &&
1227                              (nextRite & kSnapMask) <= riteBound);
1228                     blit_trapezoid_row(blitter,
1229                                        y >> 16,
1230                                        left & kSnapMask,
1231                                        rite & kSnapMask,
1232                                        nextLeft & kSnapMask,
1233                                        nextRite & kSnapMask,
1234                                        leftE->fDY,
1235                                        riteE->fDY,
1236                                        get_partial_alpha(0xFF, dY),
1237                                        maskRow,
1238                                        /*noRealBlitter=*/false);
1239                     blitter->flush_if_y_changed(y, nextY);
1240                     left = nextLeft;
1241                     rite = nextRite;
1242                     y    = nextY;
1243                 }
1244 
1245                 while (count > 1) {  // Full rows in the middle
1246                     count--;
1247                     if (isUsingMask) {
1248                         maskRow = static_cast<MaskAdditiveBlitter*>(blitter)->getRow(y >> 16);
1249                     }
1250                     SkFixed nextY = y + SK_Fixed1, nextLeft = left + dLeft, nextRite = rite + dRite;
1251                     SkASSERT((left & kSnapMask) >= leftBound && (rite & kSnapMask) <= riteBound &&
1252                              (nextLeft & kSnapMask) >= leftBound &&
1253                              (nextRite & kSnapMask) <= riteBound);
1254                     blit_trapezoid_row(blitter,
1255                                        y >> 16,
1256                                        left & kSnapMask,
1257                                        rite & kSnapMask,
1258                                        nextLeft & kSnapMask,
1259                                        nextRite & kSnapMask,
1260                                        leftE->fDY,
1261                                        riteE->fDY,
1262                                        0xFF,
1263                                        maskRow,
1264                                        /*noRealBlitter=*/false);
1265                     blitter->flush_if_y_changed(y, nextY);
1266                     left = nextLeft;
1267                     rite = nextRite;
1268                     y    = nextY;
1269                 }
1270             }
1271 
1272             if (isUsingMask) {
1273                 maskRow = static_cast<MaskAdditiveBlitter*>(blitter)->getRow(y >> 16);
1274             }
1275 
1276             SkFixed dY = local_bot_fixed - y;  // partial-row on the bottom
1277             SkASSERT(dY <= SK_Fixed1);
1278             // Smooth jumping to integer y may make the last nextLeft/nextRite out of bound.
1279             // Take them back into the bound here.
1280             // Note that we substract kSnapHalf later so we have to add them to leftBound/riteBound
1281             SkFixed nextLeft = std::max(left + SkFixedMul(dLeft, dY), leftBound + kSnapHalf);
1282             SkFixed nextRite = std::min(rite + SkFixedMul(dRite, dY), riteBound + kSnapHalf);
1283             SkASSERT((left & kSnapMask) >= leftBound && (rite & kSnapMask) <= riteBound &&
1284                      (nextLeft & kSnapMask) >= leftBound && (nextRite & kSnapMask) <= riteBound);
1285             blit_trapezoid_row(blitter,
1286                                y >> 16,
1287                                left & kSnapMask,
1288                                rite & kSnapMask,
1289                                nextLeft & kSnapMask,
1290                                nextRite & kSnapMask,
1291                                leftE->fDY,
1292                                riteE->fDY,
1293                                get_partial_alpha(0xFF, dY),
1294                                maskRow,
1295                                /*noRealBlitter=*/false);
1296             blitter->flush_if_y_changed(y, local_bot_fixed);
1297             left = nextLeft;
1298             rite = nextRite;
1299             y    = local_bot_fixed;
1300             left -= kSnapHalf;
1301             rite -= kSnapHalf;
1302         }
1303 
1304         leftE->fX = left;
1305         riteE->fX = rite;
1306         leftE->fY = riteE->fY = y;
1307     }
1308 
1309 END_WALK:;
1310 }
1311 
update_next_next_y(SkFixed y,SkFixed nextY,SkFixed * nextNextY)1312 static void update_next_next_y(SkFixed y, SkFixed nextY, SkFixed* nextNextY) {
1313     *nextNextY = y > nextY && y < *nextNextY ? y : *nextNextY;
1314 }
1315 
check_intersection(const SkAnalyticEdge * edge,SkFixed nextY,SkFixed * nextNextY)1316 static void check_intersection(const SkAnalyticEdge* edge, SkFixed nextY, SkFixed* nextNextY) {
1317     if (edge->fPrev->fPrev && edge->fPrev->fX + edge->fPrev->fDX > edge->fX + edge->fDX) {
1318         *nextNextY = nextY + (SK_Fixed1 >> SkAnalyticEdge::kDefaultAccuracy);
1319     }
1320 }
1321 
check_intersection_fwd(const SkAnalyticEdge * edge,SkFixed nextY,SkFixed * nextNextY)1322 static void check_intersection_fwd(const SkAnalyticEdge* edge, SkFixed nextY, SkFixed* nextNextY) {
1323     if (edge->fNext->fNext && edge->fX + edge->fDX > edge->fNext->fX + edge->fNext->fDX) {
1324         *nextNextY = nextY + (SK_Fixed1 >> SkAnalyticEdge::kDefaultAccuracy);
1325     }
1326 }
1327 
insert_new_edges(SkAnalyticEdge * newEdge,SkFixed y,SkFixed * nextNextY)1328 static void insert_new_edges(SkAnalyticEdge* newEdge, SkFixed y, SkFixed* nextNextY) {
1329     if (newEdge->fUpperY > y) {
1330         update_next_next_y(newEdge->fUpperY, y, nextNextY);
1331         return;
1332     }
1333     SkAnalyticEdge* prev = newEdge->fPrev;
1334     if (prev->fX <= newEdge->fX) {
1335         while (newEdge->fUpperY <= y) {
1336             check_intersection(newEdge, y, nextNextY);
1337             update_next_next_y(newEdge->fLowerY, y, nextNextY);
1338             newEdge = newEdge->fNext;
1339         }
1340         update_next_next_y(newEdge->fUpperY, y, nextNextY);
1341         return;
1342     }
1343     // find first x pos to insert
1344     SkAnalyticEdge* start = backward_insert_start(prev, newEdge->fX);
1345     // insert the lot, fixing up the links as we go
1346     do {
1347         SkAnalyticEdge* next = newEdge->fNext;
1348         do {
1349             if (start->fNext == newEdge) {
1350                 goto nextEdge;
1351             }
1352             SkAnalyticEdge* after = start->fNext;
1353             if (after->fX >= newEdge->fX) {
1354                 break;
1355             }
1356             SkASSERT(start != after);
1357             start = after;
1358         } while (true);
1359         remove_edge(newEdge);
1360         insert_edge_after(newEdge, start);
1361     nextEdge:
1362         check_intersection(newEdge, y, nextNextY);
1363         check_intersection_fwd(newEdge, y, nextNextY);
1364         update_next_next_y(newEdge->fLowerY, y, nextNextY);
1365         start   = newEdge;
1366         newEdge = next;
1367     } while (newEdge->fUpperY <= y);
1368     update_next_next_y(newEdge->fUpperY, y, nextNextY);
1369 }
1370 
validate_edges_for_y(const SkAnalyticEdge * edge,SkFixed y)1371 static void validate_edges_for_y(const SkAnalyticEdge* edge, SkFixed y) {
1372 #ifdef SK_DEBUG
1373     while (edge->fUpperY <= y) {
1374         SkASSERT(edge->fPrev && edge->fNext);
1375         SkASSERT(edge->fPrev->fNext == edge);
1376         SkASSERT(edge->fNext->fPrev == edge);
1377         SkASSERT(edge->fUpperY <= edge->fLowerY);
1378         SkASSERT(edge->fPrev->fPrev == nullptr || edge->fPrev->fX <= edge->fX);
1379         edge = edge->fNext;
1380     }
1381 #endif
1382 }
1383 
1384 // Return true if prev->fX, next->fX are too close in the current pixel row.
edges_too_close(SkAnalyticEdge * prev,SkAnalyticEdge * next,SkFixed lowerY)1385 static bool edges_too_close(SkAnalyticEdge* prev, SkAnalyticEdge* next, SkFixed lowerY) {
1386     // When next->fDX == 0, prev->fX >= next->fX - SkAbs32(next->fDX) would be false
1387     // even if prev->fX and next->fX are close and within one pixel (e.g., prev->fX == 0.1,
1388     // next->fX == 0.9). Adding SLACK = 1 to the formula would guarantee it to be true if two
1389     // edges prev and next are within one pixel.
1390     constexpr SkFixed SLACK = SK_Fixed1;
1391 
1392     // Note that even if the following test failed, the edges might still be very close to each
1393     // other at some point within the current pixel row because of prev->fDX and next->fDX.
1394     // However, to handle that case, we have to sacrafice more performance.
1395     // I think the current quality is good enough (mainly by looking at Nebraska-StateSeal.svg)
1396     // so I'll ignore fDX for performance tradeoff.
1397     return next && prev && next->fUpperY < lowerY &&
1398            prev->fX + SLACK >= next->fX - SkAbs32(next->fDX);
1399     // The following is more accurate but also slower.
1400     // return (prev && prev->fPrev && next && next->fNext != nullptr && next->fUpperY < lowerY &&
1401     //     prev->fX + SkAbs32(prev->fDX) + SLACK >= next->fX - SkAbs32(next->fDX));
1402 }
1403 
1404 // This function exists for the case where the previous rite edge is removed because
1405 // its fLowerY <= nextY
edges_too_close(int prevRite,SkFixed ul,SkFixed ll)1406 static bool edges_too_close(int prevRite, SkFixed ul, SkFixed ll) {
1407     return prevRite > SkFixedFloorToInt(ul) || prevRite > SkFixedFloorToInt(ll);
1408 }
1409 
aaa_walk_edges(SkAnalyticEdge * prevHead,SkAnalyticEdge * nextTail,SkPathFillType fillType,AdditiveBlitter * blitter,int start_y,int stop_y,SkFixed leftClip,SkFixed rightClip,bool isUsingMask,bool forceRLE,bool skipIntersect)1410 static void aaa_walk_edges(SkAnalyticEdge*  prevHead,
1411                            SkAnalyticEdge*  nextTail,
1412                            SkPathFillType   fillType,
1413                            AdditiveBlitter* blitter,
1414                            int              start_y,
1415                            int              stop_y,
1416                            SkFixed          leftClip,
1417                            SkFixed          rightClip,
1418                            bool             isUsingMask,
1419                            bool             forceRLE,
1420                            bool             skipIntersect) {
1421     prevHead->fX = prevHead->fUpperX = leftClip;
1422     nextTail->fX = nextTail->fUpperX = rightClip;
1423     SkFixed y                        = std::max(prevHead->fNext->fUpperY, SkIntToFixed(start_y));
1424     SkFixed nextNextY                = SK_MaxS32;
1425 
1426     {
1427         SkAnalyticEdge* edge;
1428         for (edge = prevHead->fNext; edge->fUpperY <= y; edge = edge->fNext) {
1429             edge->goY(y);
1430             update_next_next_y(edge->fLowerY, y, &nextNextY);
1431         }
1432         update_next_next_y(edge->fUpperY, y, &nextNextY);
1433     }
1434 
1435     int windingMask = SkPathFillType_IsEvenOdd(fillType) ? 1 : -1;
1436     bool isInverse  = SkPathFillType_IsInverse(fillType);
1437 
1438     if (isInverse && SkIntToFixed(start_y) != y) {
1439         int width = SkFixedFloorToInt(rightClip - leftClip);
1440         if (SkFixedFloorToInt(y) != start_y) {
1441             blitter->getRealBlitter()->blitRect(
1442                     SkFixedFloorToInt(leftClip), start_y, width, SkFixedFloorToInt(y) - start_y);
1443             start_y = SkFixedFloorToInt(y);
1444         }
1445         SkAlpha* maskRow =
1446                 isUsingMask ? static_cast<MaskAdditiveBlitter*>(blitter)->getRow(start_y) : nullptr;
1447         blit_full_alpha(blitter,
1448                         start_y,
1449                         SkFixedFloorToInt(leftClip),
1450                         width,
1451                         fixed_to_alpha(y - SkIntToFixed(start_y)),
1452                         maskRow,
1453                         false);
1454     }
1455 
1456     while (true) {
1457         int             w               = 0;
1458         bool            in_interval     = isInverse;
1459         SkFixed         prevX           = prevHead->fX;
1460         SkFixed         nextY           = std::min(nextNextY, SkFixedCeilToFixed(y + 1));
1461         SkAnalyticEdge* currE           = prevHead->fNext;
1462         SkAnalyticEdge* leftE           = prevHead;
1463         SkFixed         left            = leftClip;
1464         SkFixed         leftDY          = 0;
1465         int             prevRite        = SkFixedFloorToInt(leftClip);
1466 
1467         nextNextY = SK_MaxS32;
1468 
1469         SkASSERT((nextY & ((SK_Fixed1 >> 2) - 1)) == 0);
1470         int yShift = 0;
1471         if ((nextY - y) & (SK_Fixed1 >> 2)) {
1472             yShift = 2;
1473             nextY  = y + (SK_Fixed1 >> 2);
1474         } else if ((nextY - y) & (SK_Fixed1 >> 1)) {
1475             yShift = 1;
1476             SkASSERT(nextY == y + (SK_Fixed1 >> 1));
1477         }
1478 
1479         SkAlpha fullAlpha = fixed_to_alpha(nextY - y);
1480 
1481         // If we're using mask blitter, we advance the mask row in this function
1482         // to save some "if" condition checks.
1483         SkAlpha* maskRow =
1484                 isUsingMask
1485                         ? static_cast<MaskAdditiveBlitter*>(blitter)->getRow(SkFixedFloorToInt(y))
1486                         : nullptr;
1487 
1488         SkASSERT(currE->fPrev == prevHead);
1489         validate_edges_for_y(currE, y);
1490 
1491         // Even if next - y == SK_Fixed1, we can still break the left-to-right order requirement
1492         // of the SKAAClip: |\| (two trapezoids with overlapping middle wedges)
1493         bool noRealBlitter = forceRLE;  // forceRLE && (nextY - y != SK_Fixed1);
1494 
1495         while (currE->fUpperY <= y) {
1496             SkASSERT(currE->fLowerY >= nextY);
1497             SkASSERT(currE->fY == y);
1498 
1499             w += currE->fWinding;
1500             bool prev_in_interval = in_interval;
1501             in_interval           = !(w & windingMask) == isInverse;
1502 
1503             bool isLeft   = in_interval && !prev_in_interval;
1504             bool isRite   = !in_interval && prev_in_interval;
1505 
1506             if (isRite) {
1507                 SkFixed rite = currE->fX;
1508                 currE->goY(nextY, yShift);
1509                 SkFixed nextLeft = std::max(leftClip, leftE->fX);
1510                 rite = std::min(rightClip, rite);
1511                 SkFixed nextRite = std::min(rightClip, currE->fX);
1512                 blit_trapezoid_row(
1513                         blitter,
1514                         y >> 16,
1515                         left,
1516                         rite,
1517                         nextLeft,
1518                         nextRite,
1519                         leftDY,
1520                         currE->fDY,
1521                         fullAlpha,
1522                         maskRow,
1523                         noRealBlitter || (fullAlpha == 0xFF &&
1524                                           (edges_too_close(prevRite, left, leftE->fX) ||
1525                                            edges_too_close(currE, currE->fNext, nextY))));
1526                 prevRite = SkFixedCeilToInt(std::max(rite, currE->fX));
1527             } else {
1528                 if (isLeft) {
1529                     left     = std::max(currE->fX, leftClip);
1530                     leftDY   = currE->fDY;
1531                     leftE    = currE;
1532                 }
1533                 currE->goY(nextY, yShift);
1534             }
1535 
1536             SkAnalyticEdge* next = currE->fNext;
1537             SkFixed         newX;
1538 
1539             while (currE->fLowerY <= nextY) {
1540                 if (currE->fCurveCount < 0) {
1541                     SkAnalyticCubicEdge* cubicEdge = (SkAnalyticCubicEdge*)currE;
1542                     cubicEdge->keepContinuous();
1543                     if (!cubicEdge->updateCubic()) {
1544                         break;
1545                     }
1546                 } else if (currE->fCurveCount > 0) {
1547                     SkAnalyticQuadraticEdge* quadEdge = (SkAnalyticQuadraticEdge*)currE;
1548                     quadEdge->keepContinuous();
1549                     if (!quadEdge->updateQuadratic()) {
1550                         break;
1551                     }
1552                 } else {
1553                     break;
1554                 }
1555             }
1556             SkASSERT(currE->fY == nextY);
1557 
1558             if (currE->fLowerY <= nextY) {
1559                 remove_edge(currE);
1560             } else {
1561                 update_next_next_y(currE->fLowerY, nextY, &nextNextY);
1562                 newX = currE->fX;
1563                 SkASSERT(currE->fLowerY > nextY);
1564                 if (newX < prevX) {
1565                     // ripple currE backwards until it is x-sorted
1566                     backward_insert_edge_based_on_x(currE);
1567                 } else {
1568                     prevX = newX;
1569                 }
1570                 if (!skipIntersect) {
1571                     check_intersection(currE, nextY, &nextNextY);
1572                 }
1573             }
1574 
1575             currE = next;
1576             SkASSERT(currE);
1577         }
1578 
1579         // was our right-edge culled away?
1580         if (in_interval) {
1581             blit_trapezoid_row(blitter,
1582                                y >> 16,
1583                                left,
1584                                rightClip,
1585                                std::max(leftClip, leftE->fX),
1586                                rightClip,
1587                                leftDY,
1588                                0,
1589                                fullAlpha,
1590                                maskRow,
1591                                noRealBlitter || (fullAlpha == 0xFF &&
1592                                                  edges_too_close(leftE->fPrev, leftE, nextY)));
1593         }
1594 
1595         if (forceRLE) {
1596             ((RunBasedAdditiveBlitter*)blitter)->flush_if_y_changed(y, nextY);
1597         }
1598 
1599         y = nextY;
1600         if (y >= SkIntToFixed(stop_y)) {
1601             break;
1602         }
1603 
1604         // now currE points to the first edge with a fUpperY larger than the previous y
1605         insert_new_edges(currE, y, &nextNextY);
1606     }
1607 }
1608 
aaa_fill_path(const SkPath & path,const SkIRect & clipRect,AdditiveBlitter * blitter,int start_y,int stop_y,bool pathContainedInClip,bool isUsingMask,bool forceRLE)1609 static void aaa_fill_path(const SkPath& path,
1610                           const SkIRect& clipRect,
1611                           AdditiveBlitter* blitter,
1612                           int start_y,
1613                           int stop_y,
1614                           bool pathContainedInClip,
1615                           bool isUsingMask,
1616                           bool forceRLE) {  // forceRLE implies that SkAAClip is calling us
1617     SkASSERT(blitter);
1618 
1619     SkAnalyticEdgeBuilder builder;
1620     int              count = builder.buildEdges(path, pathContainedInClip ? nullptr : &clipRect);
1621     SkAnalyticEdge** list  = builder.analyticEdgeList();
1622 
1623     SkIRect rect = clipRect;
1624     if (0 == count) {
1625         if (path.isInverseFillType()) {
1626             /*
1627              *  Since we are in inverse-fill, our caller has already drawn above
1628              *  our top (start_y) and will draw below our bottom (stop_y). Thus
1629              *  we need to restrict our drawing to the intersection of the clip
1630              *  and those two limits.
1631              */
1632             if (rect.fTop < start_y) {
1633                 rect.fTop = start_y;
1634             }
1635             if (rect.fBottom > stop_y) {
1636                 rect.fBottom = stop_y;
1637             }
1638             if (!rect.isEmpty()) {
1639                 blitter->getRealBlitter()->blitRect(
1640                         rect.fLeft, rect.fTop, rect.width(), rect.height());
1641             }
1642         }
1643         return;
1644     }
1645 
1646     SkAnalyticEdge headEdge, tailEdge, *last;
1647     // this returns the first and last edge after they're sorted into a dlink list
1648     SkAnalyticEdge* edge = sort_edges(list, count, &last);
1649 
1650     headEdge.fPrev   = nullptr;
1651     headEdge.fNext   = edge;
1652     headEdge.fUpperY = headEdge.fLowerY = SK_MinS32;
1653     headEdge.fX                         = SK_MinS32;
1654     headEdge.fDX                        = 0;
1655     headEdge.fDY                        = SK_MaxS32;
1656     headEdge.fUpperX                    = SK_MinS32;
1657     edge->fPrev                         = &headEdge;
1658 
1659     tailEdge.fPrev   = last;
1660     tailEdge.fNext   = nullptr;
1661     tailEdge.fUpperY = tailEdge.fLowerY = SK_MaxS32;
1662     tailEdge.fX                         = SK_MaxS32;
1663     tailEdge.fDX                        = 0;
1664     tailEdge.fDY                        = SK_MaxS32;
1665     tailEdge.fUpperX                    = SK_MaxS32;
1666     last->fNext                         = &tailEdge;
1667 
1668     // now edge is the head of the sorted linklist
1669 
1670     if (!pathContainedInClip && start_y < clipRect.fTop) {
1671         start_y = clipRect.fTop;
1672     }
1673     if (!pathContainedInClip && stop_y > clipRect.fBottom) {
1674         stop_y = clipRect.fBottom;
1675     }
1676 
1677     SkFixed leftBound  = SkIntToFixed(rect.fLeft);
1678     SkFixed rightBound = SkIntToFixed(rect.fRight);
1679     if (isUsingMask) {
1680         // If we're using mask, then we have to limit the bound within the path bounds.
1681         // Otherwise, the edge drift may access an invalid address inside the mask.
1682         SkIRect ir;
1683         path.getBounds().roundOut(&ir);
1684         leftBound  = std::max(leftBound, SkIntToFixed(ir.fLeft));
1685         rightBound = std::min(rightBound, SkIntToFixed(ir.fRight));
1686     }
1687 
1688     if (!path.isInverseFillType() && path.isConvex() && count >= 2) {
1689         aaa_walk_convex_edges(
1690                 &headEdge, blitter, start_y, stop_y, leftBound, rightBound, isUsingMask);
1691     } else {
1692         // We skip intersection computation if there are many points which probably already
1693         // give us enough fractional scan lines.
1694         bool skipIntersect = path.countPoints() > (stop_y - start_y) * 2;
1695 
1696         aaa_walk_edges(&headEdge,
1697                        &tailEdge,
1698                        path.getFillType(),
1699                        blitter,
1700                        start_y,
1701                        stop_y,
1702                        leftBound,
1703                        rightBound,
1704                        isUsingMask,
1705                        forceRLE,
1706                        skipIntersect);
1707     }
1708 }
1709 
1710 // Check if the path is a rect and fat enough after clipping; if so, blit it.
try_blit_fat_anti_rect(SkBlitter * blitter,const SkPath & path,const SkIRect & clip)1711 static inline bool try_blit_fat_anti_rect(SkBlitter* blitter,
1712                                           const SkPath& path,
1713                                           const SkIRect& clip) {
1714     SkRect rect;
1715     if (!path.isRect(&rect)) {
1716         return false; // not rect
1717     }
1718     if (!rect.intersect(SkRect::Make(clip))) {
1719         return true; // The intersection is empty. Hence consider it done.
1720     }
1721     SkIRect bounds = rect.roundOut();
1722     if (bounds.width() < 3) {
1723         return false; // not fat
1724     }
1725     blitter->blitFatAntiRect(rect);
1726     return true;
1727 }
1728 
AAAFillPath(const SkPath & path,SkBlitter * blitter,const SkIRect & ir,const SkIRect & clipBounds,bool forceRLE)1729 void SkScan::AAAFillPath(const SkPath&  path,
1730                          SkBlitter*     blitter,
1731                          const SkIRect& ir,
1732                          const SkIRect& clipBounds,
1733                          bool           forceRLE) {
1734     bool containedInClip = clipBounds.contains(ir);
1735     bool isInverse       = path.isInverseFillType();
1736 
1737     // The mask blitter (where we store intermediate alpha values directly in a mask, and then call
1738     // the real blitter once in the end to blit the whole mask) is faster than the RLE blitter when
1739     // the blit region is small enough (i.e., CanHandleRect(ir)). When isInverse is true, the blit
1740     // region is no longer the rectangle ir so we won't use the mask blitter. The caller may also
1741     // use the forceRLE flag to force not using the mask blitter. Also, when the path is a simple
1742     // rect, preparing a mask and blitting it might have too much overhead. Hence we'll use
1743     // blitFatAntiRect to avoid the mask and its overhead.
1744     if (MaskAdditiveBlitter::CanHandleRect(ir) && !isInverse && !forceRLE) {
1745         // blitFatAntiRect is slower than the normal AAA flow without MaskAdditiveBlitter.
1746         // Hence only tryBlitFatAntiRect when MaskAdditiveBlitter would have been used.
1747         if (!try_blit_fat_anti_rect(blitter, path, clipBounds)) {
1748             MaskAdditiveBlitter additiveBlitter(blitter, ir, clipBounds, isInverse);
1749             aaa_fill_path(path,
1750                           clipBounds,
1751                           &additiveBlitter,
1752                           ir.fTop,
1753                           ir.fBottom,
1754                           containedInClip,
1755                           true,
1756                           forceRLE);
1757         }
1758     } else if (!isInverse && path.isConvex()) {
1759         // If the filling area is convex (i.e., path.isConvex && !isInverse), our simpler
1760         // aaa_walk_convex_edges won't generate alphas above 255. Hence we don't need
1761         // SafeRLEAdditiveBlitter (which is slow due to clamping). The basic RLE blitter
1762         // RunBasedAdditiveBlitter would suffice.
1763         RunBasedAdditiveBlitter additiveBlitter(blitter, ir, clipBounds, isInverse);
1764         aaa_fill_path(path,
1765                       clipBounds,
1766                       &additiveBlitter,
1767                       ir.fTop,
1768                       ir.fBottom,
1769                       containedInClip,
1770                       false,
1771                       forceRLE);
1772     } else {
1773         // If the filling area might not be convex, the more involved aaa_walk_edges would
1774         // be called and we have to clamp the alpha downto 255. The SafeRLEAdditiveBlitter
1775         // does that at a cost of performance.
1776         SafeRLEAdditiveBlitter additiveBlitter(blitter, ir, clipBounds, isInverse);
1777         aaa_fill_path(path,
1778                       clipBounds,
1779                       &additiveBlitter,
1780                       ir.fTop,
1781                       ir.fBottom,
1782                       containedInClip,
1783                       false,
1784                       forceRLE);
1785     }
1786 }
1787