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