xref: /aosp_15_r20/external/skia/src/core/SkAAClip.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2011 Google Inc.
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 "src/core/SkAAClip.h"
9 
10 #include "include/core/SkClipOp.h"
11 #include "include/core/SkPath.h"
12 #include "include/core/SkRegion.h"
13 #include "include/core/SkTypes.h"
14 #include "include/private/SkColorData.h"
15 #include "include/private/base/SkCPUTypes.h"
16 #include "include/private/base/SkDebug.h"
17 #include "include/private/base/SkMacros.h"
18 #include "include/private/base/SkMalloc.h"
19 #include "include/private/base/SkMath.h"
20 #include "include/private/base/SkTDArray.h"
21 #include "include/private/base/SkTo.h"
22 #include "src/core/SkBlitter.h"
23 #include "src/core/SkMask.h"
24 #include "src/core/SkScan.h"
25 
26 #include <algorithm>
27 #include <atomic>
28 #include <cstring>
29 
30 namespace {
31 
32 class AutoAAClipValidate {
33 public:
AutoAAClipValidate(const SkAAClip & clip)34     AutoAAClipValidate(const SkAAClip& clip) : fClip(clip) {
35         fClip.validate();
36     }
~AutoAAClipValidate()37     ~AutoAAClipValidate() {
38         fClip.validate();
39     }
40 private:
41     const SkAAClip& fClip;
42 };
43 
44 #ifdef SK_DEBUG
45     #define AUTO_AACLIP_VALIDATE(clip)  AutoAAClipValidate acv(clip)
46 #else
47     #define AUTO_AACLIP_VALIDATE(clip)
48 #endif
49 
50 ///////////////////////////////////////////////////////////////////////////////
51 
52 static constexpr int32_t kMaxInt32 = 0x7FFFFFFF;
53 
54 #ifdef SK_DEBUG
55 // assert we're exactly width-wide, and then return the number of bytes used
compute_row_length(const uint8_t row[],int width)56 static size_t compute_row_length(const uint8_t row[], int width) {
57     const uint8_t* origRow = row;
58     while (width > 0) {
59         int n = row[0];
60         SkASSERT(n > 0);
61         SkASSERT(n <= width);
62         row += 2;
63         width -= n;
64     }
65     SkASSERT(0 == width);
66     return row - origRow;
67 }
68 #endif
69 
70 /*
71  *  Data runs are packed [count, alpha]
72  */
73 struct YOffset {
74     int32_t  fY;
75     uint32_t fOffset;
76 };
77 
78 class RowIter {
79 public:
RowIter(const uint8_t * row,const SkIRect & bounds)80     RowIter(const uint8_t* row, const SkIRect& bounds) {
81         fRow = row;
82         fLeft = bounds.fLeft;
83         fBoundsRight = bounds.fRight;
84         if (row) {
85             fRight = bounds.fLeft + row[0];
86             SkASSERT(fRight <= fBoundsRight);
87             fAlpha = row[1];
88             fDone = false;
89         } else {
90             fDone = true;
91             fRight = kMaxInt32;
92             fAlpha = 0;
93         }
94     }
95 
done() const96     bool done() const { return fDone; }
left() const97     int left() const { return fLeft; }
right() const98     int right() const { return fRight; }
alpha() const99     U8CPU alpha() const { return fAlpha; }
next()100     void next() {
101         if (!fDone) {
102             fLeft = fRight;
103             if (fRight == fBoundsRight) {
104                 fDone = true;
105                 fRight = kMaxInt32;
106                 fAlpha = 0;
107             } else {
108                 fRow += 2;
109                 fRight += fRow[0];
110                 fAlpha = fRow[1];
111                 SkASSERT(fRight <= fBoundsRight);
112             }
113         }
114     }
115 
116 private:
117     const uint8_t*  fRow;
118     int             fLeft;
119     int             fRight;
120     int             fBoundsRight;
121     bool            fDone;
122     uint8_t         fAlpha;
123 };
124 
125 class Iter {
126 public:
127     Iter() = default;
128 
Iter(int y,const uint8_t * data,const YOffset * start,const YOffset * end)129     Iter(int y, const uint8_t* data, const YOffset* start, const YOffset* end)
130             : fCurrYOff(start)
131             , fStopYOff(end)
132             , fData(data + start->fOffset)
133             , fTop(y)
134             , fBottom(y + start->fY + 1)
135             , fDone(false) {}
136 
done() const137     bool done() const { return fDone; }
top() const138     int top() const { return fTop; }
bottom() const139     int bottom() const { return fBottom; }
data() const140     const uint8_t* data() const { return fData; }
141 
next()142     void next() {
143         if (!fDone) {
144             const YOffset* prev = fCurrYOff;
145             const YOffset* curr = prev + 1;
146             SkASSERT(curr <= fStopYOff);
147 
148             fTop = fBottom;
149             if (curr >= fStopYOff) {
150                 fDone = true;
151                 fBottom = kMaxInt32;
152                 fData = nullptr;
153             } else {
154                 fBottom += curr->fY - prev->fY;
155                 fData += curr->fOffset - prev->fOffset;
156                 fCurrYOff = curr;
157             }
158         }
159     }
160 
161 private:
162     const YOffset* fCurrYOff = nullptr;
163     const YOffset* fStopYOff = nullptr;
164     const uint8_t* fData = nullptr;
165 
166     int fTop = kMaxInt32;
167     int fBottom = kMaxInt32;
168     bool fDone = true;
169 };
170 
171 }  // namespace
172 
173 ///////////////////////////////////////////////////////////////////////////////
174 
175 struct SkAAClip::RunHead {
176     std::atomic<int32_t> fRefCnt;
177     int32_t fRowCount;
178     size_t  fDataSize;
179 
yoffsetsSkAAClip::RunHead180     YOffset* yoffsets() {
181         return (YOffset*)((char*)this + sizeof(RunHead));
182     }
yoffsetsSkAAClip::RunHead183     const YOffset* yoffsets() const {
184         return (const YOffset*)((const char*)this + sizeof(RunHead));
185     }
dataSkAAClip::RunHead186     uint8_t* data() {
187         return (uint8_t*)(this->yoffsets() + fRowCount);
188     }
dataSkAAClip::RunHead189     const uint8_t* data() const {
190         return (const uint8_t*)(this->yoffsets() + fRowCount);
191     }
192 
AllocSkAAClip::RunHead193     static RunHead* Alloc(int rowCount, size_t dataSize) {
194         size_t size = sizeof(RunHead) + rowCount * sizeof(YOffset) + dataSize;
195         RunHead* head = (RunHead*)sk_malloc_throw(size);
196         head->fRefCnt.store(1);
197         head->fRowCount = rowCount;
198         head->fDataSize = dataSize;
199         return head;
200     }
201 
ComputeRowSizeForWidthSkAAClip::RunHead202     static int ComputeRowSizeForWidth(int width) {
203         // 2 bytes per segment, where each segment can store up to 255 for count
204         int segments = 0;
205         while (width > 0) {
206             segments += 1;
207             int n = std::min(width, 255);
208             width -= n;
209         }
210         return segments * 2;    // each segment is row[0] + row[1] (n + alpha)
211     }
212 
AllocRectSkAAClip::RunHead213     static RunHead* AllocRect(const SkIRect& bounds) {
214         SkASSERT(!bounds.isEmpty());
215         int width = bounds.width();
216         size_t rowSize = ComputeRowSizeForWidth(width);
217         RunHead* head = RunHead::Alloc(1, rowSize);
218         YOffset* yoff = head->yoffsets();
219         yoff->fY = bounds.height() - 1;
220         yoff->fOffset = 0;
221         uint8_t* row = head->data();
222         while (width > 0) {
223             int n = std::min(width, 255);
224             row[0] = n;
225             row[1] = 0xFF;
226             width -= n;
227             row += 2;
228         }
229         return head;
230     }
231 
IterateSkAAClip::RunHead232     static Iter Iterate(const SkAAClip& clip) {
233         const RunHead* head = clip.fRunHead;
234         if (!clip.fRunHead) {
235             // A null run head is an empty clip, so return aan already finished iterator.
236             return Iter();
237         }
238 
239         return Iter(clip.getBounds().fTop, head->data(), head->yoffsets(),
240                     head->yoffsets() + head->fRowCount);
241     }
242 };
243 
244 ///////////////////////////////////////////////////////////////////////////////
245 
246 class SkAAClip::Builder {
247     class Blitter;
248 
249     SkIRect fBounds;
250     struct Row {
251         int fY;
252         int fWidth;
253         SkTDArray<uint8_t>* fData;
254     };
255     SkTDArray<Row>  fRows;
256     Row* fCurrRow;
257     int fPrevY;
258     int fWidth;
259     int fMinY;
260 
261 public:
Builder(const SkIRect & bounds)262     Builder(const SkIRect& bounds) : fBounds(bounds) {
263         fPrevY = -1;
264         fWidth = bounds.width();
265         fCurrRow = nullptr;
266         fMinY = bounds.fTop;
267     }
268 
~Builder()269     ~Builder() {
270         Row* row = fRows.begin();
271         Row* stop = fRows.end();
272         while (row < stop) {
273             delete row->fData;
274             row += 1;
275         }
276     }
277 
278     bool applyClipOp(SkAAClip* target, const SkAAClip& other, SkClipOp op);
279     bool blitPath(SkAAClip* target, const SkPath& path, bool doAA);
280 
281 private:
282     using AlphaProc = U8CPU (*)(U8CPU alphaA, U8CPU alphaB);
283     void operateX(int lastY, RowIter& iterA, RowIter& iterB, AlphaProc proc);
284     void operateY(const SkAAClip& A, const SkAAClip& B, SkClipOp op);
285 
addRun(int x,int y,U8CPU alpha,int count)286     void addRun(int x, int y, U8CPU alpha, int count) {
287         SkASSERT(count > 0);
288         SkASSERT(fBounds.contains(x, y));
289         SkASSERT(fBounds.contains(x + count - 1, y));
290 
291         x -= fBounds.left();
292         y -= fBounds.top();
293 
294         Row* row = fCurrRow;
295         if (y != fPrevY) {
296             SkASSERT(y > fPrevY);
297             fPrevY = y;
298             row = this->flushRow(true);
299             row->fY = y;
300             row->fWidth = 0;
301             SkASSERT(row->fData);
302             SkASSERT(row->fData->empty());
303             fCurrRow = row;
304         }
305 
306         SkASSERT(row->fWidth <= x);
307         SkASSERT(row->fWidth < fBounds.width());
308 
309         SkTDArray<uint8_t>& data = *row->fData;
310 
311         int gap = x - row->fWidth;
312         if (gap) {
313             AppendRun(data, 0, gap);
314             row->fWidth += gap;
315             SkASSERT(row->fWidth < fBounds.width());
316         }
317 
318         AppendRun(data, alpha, count);
319         row->fWidth += count;
320         SkASSERT(row->fWidth <= fBounds.width());
321     }
322 
addColumn(int x,int y,U8CPU alpha,int height)323     void addColumn(int x, int y, U8CPU alpha, int height) {
324         SkASSERT(fBounds.contains(x, y + height - 1));
325 
326         this->addRun(x, y, alpha, 1);
327         this->flushRowH(fCurrRow);
328         y -= fBounds.fTop;
329         SkASSERT(y == fCurrRow->fY);
330         fCurrRow->fY = y + height - 1;
331     }
332 
addRectRun(int x,int y,int width,int height)333     void addRectRun(int x, int y, int width, int height) {
334         SkASSERT(fBounds.contains(x + width - 1, y + height - 1));
335         this->addRun(x, y, 0xFF, width);
336 
337         // we assum the rect must be all we'll see for these scanlines
338         // so we ensure our row goes all the way to our right
339         this->flushRowH(fCurrRow);
340 
341         y -= fBounds.fTop;
342         SkASSERT(y == fCurrRow->fY);
343         fCurrRow->fY = y + height - 1;
344     }
345 
addAntiRectRun(int x,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)346     void addAntiRectRun(int x, int y, int width, int height,
347                         SkAlpha leftAlpha, SkAlpha rightAlpha) {
348         // According to SkBlitter.cpp, no matter whether leftAlpha is 0 or positive,
349         // we should always consider [x, x+1] as the left-most column and [x+1, x+1+width]
350         // as the rect with full alpha.
351         SkASSERT(fBounds.contains(x + width + (rightAlpha > 0 ? 1 : 0),
352                  y + height - 1));
353         SkASSERT(width >= 0);
354 
355         // Conceptually we're always adding 3 runs, but we should
356         // merge or omit them if possible.
357         if (leftAlpha == 0xFF) {
358             width++;
359         } else if (leftAlpha > 0) {
360           this->addRun(x++, y, leftAlpha, 1);
361         } else {
362           // leftAlpha is 0, ignore the left column
363           x++;
364         }
365         if (rightAlpha == 0xFF) {
366             width++;
367         }
368         if (width > 0) {
369             this->addRun(x, y, 0xFF, width);
370         }
371         if (rightAlpha > 0 && rightAlpha < 255) {
372             this->addRun(x + width, y, rightAlpha, 1);
373         }
374 
375         // if we never called addRun, we might not have a fCurrRow yet
376         if (fCurrRow) {
377             // we assume the rect must be all we'll see for these scanlines
378             // so we ensure our row goes all the way to our right
379             this->flushRowH(fCurrRow);
380 
381             y -= fBounds.fTop;
382             SkASSERT(y == fCurrRow->fY);
383             fCurrRow->fY = y + height - 1;
384         }
385     }
386 
finish(SkAAClip * target)387     bool finish(SkAAClip* target) {
388         this->flushRow(false);
389 
390         const Row* row = fRows.begin();
391         const Row* stop = fRows.end();
392 
393         size_t dataSize = 0;
394         while (row < stop) {
395             dataSize += row->fData->size();
396             row += 1;
397         }
398 
399         if (0 == dataSize) {
400             return target->setEmpty();
401         }
402 
403         SkASSERT(fMinY >= fBounds.fTop);
404         SkASSERT(fMinY < fBounds.fBottom);
405         int adjustY = fMinY - fBounds.fTop;
406         fBounds.fTop = fMinY;
407 
408         RunHead* head = RunHead::Alloc(fRows.size(), dataSize);
409         YOffset* yoffset = head->yoffsets();
410         uint8_t* data = head->data();
411         uint8_t* baseData = data;
412 
413         row = fRows.begin();
414         SkDEBUGCODE(int prevY = row->fY - 1;)
415         while (row < stop) {
416             SkASSERT(prevY < row->fY);  // must be monotonic
417             SkDEBUGCODE(prevY = row->fY);
418 
419             yoffset->fY = row->fY - adjustY;
420             yoffset->fOffset = SkToU32(data - baseData);
421             yoffset += 1;
422 
423             size_t n = row->fData->size();
424             memcpy(data, row->fData->begin(), n);
425             SkASSERT(compute_row_length(data, fBounds.width()) == n);
426             data += n;
427 
428             row += 1;
429         }
430 
431         target->freeRuns();
432         target->fBounds = fBounds;
433         target->fRunHead = head;
434         return target->trimBounds();
435     }
436 
dump()437     void dump() {
438         this->validate();
439         int y;
440         for (y = 0; y < fRows.size(); ++y) {
441             const Row& row = fRows[y];
442             SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth);
443             const SkTDArray<uint8_t>& data = *row.fData;
444             int count = data.size();
445             SkASSERT(!(count & 1));
446             const uint8_t* ptr = data.begin();
447             for (int x = 0; x < count; x += 2) {
448                 SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]);
449                 ptr += 2;
450             }
451             SkDebugf("\n");
452         }
453     }
454 
validate()455     void validate() {
456 #ifdef SK_DEBUG
457         int prevY = -1;
458         for (int i = 0; i < fRows.size(); ++i) {
459             const Row& row = fRows[i];
460             SkASSERT(prevY < row.fY);
461             SkASSERT(fWidth == row.fWidth);
462             int count = row.fData->size();
463             const uint8_t* ptr = row.fData->begin();
464             SkASSERT(!(count & 1));
465             int w = 0;
466             for (int x = 0; x < count; x += 2) {
467                 int n = ptr[0];
468                 SkASSERT(n > 0);
469                 w += n;
470                 SkASSERT(w <= fWidth);
471                 ptr += 2;
472             }
473             SkASSERT(w == fWidth);
474             prevY = row.fY;
475         }
476 #endif
477     }
478 
flushRowH(Row * row)479     void flushRowH(Row* row) {
480         // flush current row if needed
481         if (row->fWidth < fWidth) {
482             AppendRun(*row->fData, 0, fWidth - row->fWidth);
483             row->fWidth = fWidth;
484         }
485     }
486 
flushRow(bool readyForAnother)487     Row* flushRow(bool readyForAnother) {
488         Row* next = nullptr;
489         int count = fRows.size();
490         if (count > 0) {
491             this->flushRowH(&fRows[count - 1]);
492         }
493         if (count > 1) {
494             // are our last two runs the same?
495             Row* prev = &fRows[count - 2];
496             Row* curr = &fRows[count - 1];
497             SkASSERT(prev->fWidth == fWidth);
498             SkASSERT(curr->fWidth == fWidth);
499             if (*prev->fData == *curr->fData) {
500                 prev->fY = curr->fY;
501                 if (readyForAnother) {
502                     curr->fData->clear();
503                     next = curr;
504                 } else {
505                     delete curr->fData;
506                     fRows.removeShuffle(count - 1);
507                 }
508             } else {
509                 if (readyForAnother) {
510                     next = fRows.append();
511                     next->fData = new SkTDArray<uint8_t>;
512                 }
513             }
514         } else {
515             if (readyForAnother) {
516                 next = fRows.append();
517                 next->fData = new SkTDArray<uint8_t>;
518             }
519         }
520         return next;
521     }
522 
AppendRun(SkTDArray<uint8_t> & data,U8CPU alpha,int count)523     static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) {
524         do {
525             int n = count;
526             if (n > 255) {
527                 n = 255;
528             }
529             uint8_t* ptr = data.append(2);
530             ptr[0] = n;
531             ptr[1] = alpha;
532             count -= n;
533         } while (count > 0);
534     }
535 };
536 
operateX(int lastY,RowIter & iterA,RowIter & iterB,AlphaProc proc)537 void SkAAClip::Builder::operateX(int lastY, RowIter& iterA, RowIter& iterB, AlphaProc proc) {
538     auto advanceRowIter = [](RowIter& iter, int& iterLeft, int& iterRite, int rite) {
539         if (rite == iterRite) {
540             iter.next();
541             iterLeft = iter.left();
542             iterRite = iter.right();
543         }
544     };
545 
546     int leftA = iterA.left();
547     int riteA = iterA.right();
548     int leftB = iterB.left();
549     int riteB = iterB.right();
550 
551     int prevRite = fBounds.fLeft;
552 
553     do {
554         U8CPU alphaA = 0;
555         U8CPU alphaB = 0;
556         int left, rite;
557 
558         if (leftA < leftB) {
559             left = leftA;
560             alphaA = iterA.alpha();
561             if (riteA <= leftB) {
562                 rite = riteA;
563             } else {
564                 rite = leftA = leftB;
565             }
566         } else if (leftB < leftA) {
567             left = leftB;
568             alphaB = iterB.alpha();
569             if (riteB <= leftA) {
570                 rite = riteB;
571             } else {
572                 rite = leftB = leftA;
573             }
574         } else {
575             left = leftA;   // or leftB, since leftA == leftB
576             rite = leftA = leftB = std::min(riteA, riteB);
577             alphaA = iterA.alpha();
578             alphaB = iterB.alpha();
579         }
580 
581         if (left >= fBounds.fRight) {
582             break;
583         }
584         if (rite > fBounds.fRight) {
585             rite = fBounds.fRight;
586         }
587 
588         if (left >= fBounds.fLeft) {
589             SkASSERT(rite > left);
590             this->addRun(left, lastY, proc(alphaA, alphaB), rite - left);
591             prevRite = rite;
592         }
593 
594         advanceRowIter(iterA, leftA, riteA, rite);
595         advanceRowIter(iterB, leftB, riteB, rite);
596     } while (!iterA.done() || !iterB.done());
597 
598     if (prevRite < fBounds.fRight) {
599         this->addRun(prevRite, lastY, 0, fBounds.fRight - prevRite);
600     }
601 }
602 
operateY(const SkAAClip & A,const SkAAClip & B,SkClipOp op)603 void SkAAClip::Builder::operateY(const SkAAClip& A, const SkAAClip& B, SkClipOp op) {
604     static const AlphaProc kDiff = [](U8CPU a, U8CPU b) { return SkMulDiv255Round(a, 0xFF - b); };
605     static const AlphaProc kIntersect = [](U8CPU a, U8CPU b) { return SkMulDiv255Round(a, b); };
606     AlphaProc proc = (op == SkClipOp::kDifference) ? kDiff : kIntersect;
607 
608     Iter iterA = RunHead::Iterate(A);
609     Iter iterB = RunHead::Iterate(B);
610 
611     SkASSERT(!iterA.done());
612     int topA = iterA.top();
613     int botA = iterA.bottom();
614     SkASSERT(!iterB.done());
615     int topB = iterB.top();
616     int botB = iterB.bottom();
617 
618     auto advanceIter = [](Iter& iter, int& iterTop, int& iterBot, int bot) {
619         if (bot == iterBot) {
620             iter.next();
621             iterTop = iterBot;
622             SkASSERT(iterBot == iter.top());
623             iterBot = iter.bottom();
624         }
625     };
626 
627 #if defined(SK_BUILD_FOR_FUZZER)
628     if ((botA - topA) > 100000 || (botB - topB) > 100000) {
629         return;
630     }
631 #endif
632 
633     do {
634         const uint8_t* rowA = nullptr;
635         const uint8_t* rowB = nullptr;
636         int top, bot;
637 
638         if (topA < topB) {
639             top = topA;
640             rowA = iterA.data();
641             if (botA <= topB) {
642                 bot = botA;
643             } else {
644                 bot = topA = topB;
645             }
646 
647         } else if (topB < topA) {
648             top = topB;
649             rowB = iterB.data();
650             if (botB <= topA) {
651                 bot = botB;
652             } else {
653                 bot = topB = topA;
654             }
655         } else {
656             top = topA;   // or topB, since topA == topB
657             bot = topA = topB = std::min(botA, botB);
658             rowA = iterA.data();
659             rowB = iterB.data();
660         }
661 
662         if (top >= fBounds.fBottom) {
663             break;
664         }
665 
666         if (bot > fBounds.fBottom) {
667             bot = fBounds.fBottom;
668         }
669         SkASSERT(top < bot);
670 
671         if (!rowA && !rowB) {
672             this->addRun(fBounds.fLeft, bot - 1, 0, fBounds.width());
673         } else if (top >= fBounds.fTop) {
674             SkASSERT(bot <= fBounds.fBottom);
675             RowIter rowIterA(rowA, rowA ? A.getBounds() : fBounds);
676             RowIter rowIterB(rowB, rowB ? B.getBounds() : fBounds);
677             this->operateX(bot - 1, rowIterA, rowIterB, proc);
678         }
679 
680         advanceIter(iterA, topA, botA, bot);
681         advanceIter(iterB, topB, botB, bot);
682     } while (!iterA.done() || !iterB.done());
683 }
684 
685 class SkAAClip::Builder::Blitter final : public SkBlitter {
686     int fLastY;
687 
688     /*
689         If we see a gap of 1 or more empty scanlines while building in Y-order,
690         we inject an explicit empty scanline (alpha==0)
691 
692         See AAClipTest.cpp : test_path_with_hole()
693      */
checkForYGap(int y)694     void checkForYGap(int y) {
695         SkASSERT(y >= fLastY);
696         if (fLastY > -SK_MaxS32) {
697             int gap = y - fLastY;
698             if (gap > 1) {
699                 fBuilder->addRun(fLeft, y - 1, 0, fRight - fLeft);
700             }
701         }
702         fLastY = y;
703     }
704 
705 public:
Blitter(Builder * builder)706     Blitter(Builder* builder) {
707         fBuilder = builder;
708         fLeft = builder->fBounds.fLeft;
709         fRight = builder->fBounds.fRight;
710         fMinY = SK_MaxS32;
711         fLastY = -SK_MaxS32;    // sentinel
712     }
713 
finish()714     void finish() {
715         if (fMinY < SK_MaxS32) {
716             fBuilder->fMinY = fMinY;
717         }
718     }
719 
720     /**
721        Must evaluate clips in scan-line order, so don't want to allow blitV(),
722        but an AAClip can be clipped down to a single pixel wide, so we
723        must support it (given AntiRect semantics: minimum width is 2).
724        Instead we'll rely on the runtime asserts to guarantee Y monotonicity;
725        any failure cases that misses may have minor artifacts.
726     */
blitV(int x,int y,int height,SkAlpha alpha)727     void blitV(int x, int y, int height, SkAlpha alpha) override {
728         if (height == 1) {
729             // We're still in scan-line order if height is 1
730             // This is useful for Analytic AA
731             const SkAlpha alphas[2] = {alpha, 0};
732             const int16_t runs[2] = {1, 0};
733             this->blitAntiH(x, y, alphas, runs);
734         } else {
735             this->recordMinY(y);
736             fBuilder->addColumn(x, y, alpha, height);
737             fLastY = y + height - 1;
738         }
739     }
740 
blitRect(int x,int y,int width,int height)741     void blitRect(int x, int y, int width, int height) override {
742         this->recordMinY(y);
743         this->checkForYGap(y);
744         fBuilder->addRectRun(x, y, width, height);
745         fLastY = y + height - 1;
746     }
747 
blitAntiRect(int x,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)748     void blitAntiRect(int x, int y, int width, int height,
749                       SkAlpha leftAlpha, SkAlpha rightAlpha) override {
750         this->recordMinY(y);
751         this->checkForYGap(y);
752         fBuilder->addAntiRectRun(x, y, width, height, leftAlpha, rightAlpha);
753         fLastY = y + height - 1;
754     }
755 
blitMask(const SkMask &,const SkIRect & clip)756     void blitMask(const SkMask&, const SkIRect& clip) override
757         { unexpected(); }
758 
blitH(int x,int y,int width)759     void blitH(int x, int y, int width) override {
760         this->recordMinY(y);
761         this->checkForYGap(y);
762         fBuilder->addRun(x, y, 0xFF, width);
763     }
764 
blitAntiH(int x,int y,const SkAlpha alpha[],const int16_t runs[])765     void blitAntiH(int x, int y, const SkAlpha alpha[], const int16_t runs[]) override {
766         this->recordMinY(y);
767         this->checkForYGap(y);
768         for (;;) {
769             int count = *runs;
770             if (count <= 0) {
771                 return;
772             }
773 
774             // The supersampler's buffer can be the width of the device, so
775             // we may have to trim the run to our bounds. Previously, we assert that
776             // the extra spans are always alpha==0.
777             // However, the analytic AA is too sensitive to precision errors
778             // so it may have extra spans with very tiny alpha because after several
779             // arithmatic operations, the edge may bleed the path boundary a little bit.
780             // Therefore, instead of always asserting alpha==0, we assert alpha < 0x10.
781             int localX = x;
782             int localCount = count;
783             if (x < fLeft) {
784                 SkASSERT(0x10 > *alpha);
785                 int gap = fLeft - x;
786                 SkASSERT(gap <= count);
787                 localX += gap;
788                 localCount -= gap;
789             }
790             int right = x + count;
791             if (right > fRight) {
792                 SkASSERT(0x10 > *alpha);
793                 localCount -= right - fRight;
794                 SkASSERT(localCount >= 0);
795             }
796 
797             if (localCount) {
798                 fBuilder->addRun(localX, y, *alpha, localCount);
799             }
800             // Next run
801             runs += count;
802             alpha += count;
803             x += count;
804         }
805     }
806 
807 private:
808     Builder* fBuilder;
809     int      fLeft; // cache of builder's bounds' left edge
810     int      fRight;
811     int      fMinY;
812 
813     /*
814      *  We track this, in case the scan converter skipped some number of
815      *  scanlines at the (relative to the bounds it was given). This allows
816      *  the builder, during its finish, to trip its bounds down to the "real"
817      *  top.
818      */
recordMinY(int y)819     void recordMinY(int y) {
820         if (y < fMinY) {
821             fMinY = y;
822         }
823     }
824 
unexpected()825     void unexpected() {
826         SK_ABORT("---- did not expect to get called here");
827     }
828 };
829 
applyClipOp(SkAAClip * target,const SkAAClip & other,SkClipOp op)830 bool SkAAClip::Builder::applyClipOp(SkAAClip* target, const SkAAClip& other, SkClipOp op) {
831     this->operateY(*target, other, op);
832     return this->finish(target);
833 }
834 
blitPath(SkAAClip * target,const SkPath & path,bool doAA)835 bool SkAAClip::Builder::blitPath(SkAAClip* target, const SkPath& path, bool doAA) {
836     Blitter blitter(this);
837     SkRegion clip(fBounds);
838 
839     if (doAA) {
840         SkScan::AntiFillPath(path, clip, &blitter, true);
841     } else {
842         SkScan::FillPath(path, clip, &blitter);
843     }
844 
845     blitter.finish();
846     return this->finish(target);
847 }
848 
849 ///////////////////////////////////////////////////////////////////////////////
850 
copyToMask(SkMaskBuilder * mask) const851 void SkAAClip::copyToMask(SkMaskBuilder* mask) const {
852     auto expandRowToMask = [](uint8_t* dst, const uint8_t* row, int width) {
853         while (width > 0) {
854             int n = row[0];
855             SkASSERT(width >= n);
856             memset(dst, row[1], n);
857             dst += n;
858             row += 2;
859             width -= n;
860         }
861         SkASSERT(0 == width);
862     };
863 
864     mask->format() = SkMask::kA8_Format;
865     if (this->isEmpty()) {
866         mask->bounds().setEmpty();
867         mask->image() = nullptr;
868         mask->rowBytes() = 0;
869         return;
870     }
871 
872     mask->bounds() = fBounds;
873     mask->rowBytes() = fBounds.width();
874     size_t size = mask->computeImageSize();
875     mask->image() = SkMaskBuilder::AllocImage(size);
876 
877     Iter iter = RunHead::Iterate(*this);
878     uint8_t* dst = mask->image();
879     const int width = fBounds.width();
880 
881     int y = fBounds.fTop;
882     while (!iter.done()) {
883         do {
884             expandRowToMask(dst, iter.data(), width);
885             dst += mask->fRowBytes;
886         } while (++y < iter.bottom());
887         iter.next();
888     }
889 }
890 
891 #ifdef SK_DEBUG
892 
validate() const893 void SkAAClip::validate() const {
894     if (nullptr == fRunHead) {
895         SkASSERT(fBounds.isEmpty());
896         return;
897     }
898     SkASSERT(!fBounds.isEmpty());
899 
900     const RunHead* head = fRunHead;
901     SkASSERT(head->fRefCnt.load() > 0);
902     SkASSERT(head->fRowCount > 0);
903 
904     const YOffset* yoff = head->yoffsets();
905     const YOffset* ystop = yoff + head->fRowCount;
906     const int lastY = fBounds.height() - 1;
907 
908     // Y and offset must be monotonic
909     int prevY = -1;
910     int32_t prevOffset = -1;
911     while (yoff < ystop) {
912         SkASSERT(prevY < yoff->fY);
913         SkASSERT(yoff->fY <= lastY);
914         prevY = yoff->fY;
915         SkASSERT(prevOffset < (int32_t)yoff->fOffset);
916         prevOffset = yoff->fOffset;
917         const uint8_t* row = head->data() + yoff->fOffset;
918         size_t rowLength = compute_row_length(row, fBounds.width());
919         SkASSERT(yoff->fOffset + rowLength <= head->fDataSize);
920         yoff += 1;
921     }
922     // check the last entry;
923     --yoff;
924     SkASSERT(yoff->fY == lastY);
925 }
926 
dump_one_row(const uint8_t * SK_RESTRICT row,int width,int leading_num)927 static void dump_one_row(const uint8_t* SK_RESTRICT row,
928                          int width, int leading_num) {
929     if (leading_num) {
930         SkDebugf( "%03d ", leading_num );
931     }
932     while (width > 0) {
933         int n = row[0];
934         int val = row[1];
935         char out = '.';
936         if (val == 0xff) {
937             out = '*';
938         } else if (val > 0) {
939             out = '+';
940         }
941         for (int i = 0 ; i < n ; i++) {
942             SkDebugf( "%c", out );
943         }
944         row += 2;
945         width -= n;
946     }
947     SkDebugf( "\n" );
948 }
949 
debug(bool compress_y) const950 void SkAAClip::debug(bool compress_y) const {
951     Iter iter = RunHead::Iterate(*this);
952     const int width = fBounds.width();
953 
954     int y = fBounds.fTop;
955     while (!iter.done()) {
956         if (compress_y) {
957             dump_one_row(iter.data(), width, iter.bottom() - iter.top() + 1);
958         } else {
959             do {
960                 dump_one_row(iter.data(), width, 0);
961             } while (++y < iter.bottom());
962         }
963         iter.next();
964     }
965 }
966 #endif
967 
968 ///////////////////////////////////////////////////////////////////////////////
969 
970 // Count the number of zeros on the left and right edges of the passed in
971 // RLE row. If 'row' is all zeros return 'width' in both variables.
count_left_right_zeros(const uint8_t * row,int width,int * leftZ,int * riteZ)972 static void count_left_right_zeros(const uint8_t* row, int width,
973                                    int* leftZ, int* riteZ) {
974     int zeros = 0;
975     do {
976         if (row[1]) {
977             break;
978         }
979         int n = row[0];
980         SkASSERT(n > 0);
981         SkASSERT(n <= width);
982         zeros += n;
983         row += 2;
984         width -= n;
985     } while (width > 0);
986     *leftZ = zeros;
987 
988     if (0 == width) {
989         // this line is completely empty return 'width' in both variables
990         *riteZ = *leftZ;
991         return;
992     }
993 
994     zeros = 0;
995     while (width > 0) {
996         int n = row[0];
997         SkASSERT(n > 0);
998         if (0 == row[1]) {
999             zeros += n;
1000         } else {
1001             zeros = 0;
1002         }
1003         row += 2;
1004         width -= n;
1005     }
1006     *riteZ = zeros;
1007 }
1008 
1009 // modify row in place, trimming off (zeros) from the left and right sides.
1010 // return the number of bytes that were completely eliminated from the left
trim_row_left_right(uint8_t * row,int width,int leftZ,int riteZ)1011 static int trim_row_left_right(uint8_t* row, int width, int leftZ, int riteZ) {
1012     int trim = 0;
1013     while (leftZ > 0) {
1014         SkASSERT(0 == row[1]);
1015         int n = row[0];
1016         SkASSERT(n > 0);
1017         SkASSERT(n <= width);
1018         width -= n;
1019         row += 2;
1020         if (n > leftZ) {
1021             row[-2] = n - leftZ;
1022             break;
1023         }
1024         trim += 2;
1025         leftZ -= n;
1026         SkASSERT(leftZ >= 0);
1027     }
1028 
1029     if (riteZ) {
1030         // walk row to the end, and then we'll back up to trim riteZ
1031         while (width > 0) {
1032             int n = row[0];
1033             SkASSERT(n <= width);
1034             width -= n;
1035             row += 2;
1036         }
1037         // now skip whole runs of zeros
1038         do {
1039             row -= 2;
1040             SkASSERT(0 == row[1]);
1041             int n = row[0];
1042             SkASSERT(n > 0);
1043             if (n > riteZ) {
1044                 row[0] = n - riteZ;
1045                 break;
1046             }
1047             riteZ -= n;
1048             SkASSERT(riteZ >= 0);
1049         } while (riteZ > 0);
1050     }
1051 
1052     return trim;
1053 }
1054 
trimLeftRight()1055 bool SkAAClip::trimLeftRight() {
1056     if (this->isEmpty()) {
1057         return false;
1058     }
1059 
1060     AUTO_AACLIP_VALIDATE(*this);
1061 
1062     const int width = fBounds.width();
1063     RunHead* head = fRunHead;
1064     YOffset* yoff = head->yoffsets();
1065     YOffset* stop = yoff + head->fRowCount;
1066     uint8_t* base = head->data();
1067 
1068     // After this loop, 'leftZeros' & 'rightZeros' will contain the minimum
1069     // number of zeros on the left and right of the clip. This information
1070     // can be used to shrink the bounding box.
1071     int leftZeros = width;
1072     int riteZeros = width;
1073     while (yoff < stop) {
1074         int L, R;
1075         count_left_right_zeros(base + yoff->fOffset, width, &L, &R);
1076         SkASSERT(L + R < width || (L == width && R == width));
1077         if (L < leftZeros) {
1078             leftZeros = L;
1079         }
1080         if (R < riteZeros) {
1081             riteZeros = R;
1082         }
1083         if (0 == (leftZeros | riteZeros)) {
1084             // no trimming to do
1085             return true;
1086         }
1087         yoff += 1;
1088     }
1089 
1090     SkASSERT(leftZeros || riteZeros);
1091     if (width == leftZeros) {
1092         SkASSERT(width == riteZeros);
1093         return this->setEmpty();
1094     }
1095 
1096     this->validate();
1097 
1098     fBounds.fLeft += leftZeros;
1099     fBounds.fRight -= riteZeros;
1100     SkASSERT(!fBounds.isEmpty());
1101 
1102     // For now we don't realloc the storage (for time), we just shrink in place
1103     // This means we don't have to do any memmoves either, since we can just
1104     // play tricks with the yoff->fOffset for each row
1105     yoff = head->yoffsets();
1106     while (yoff < stop) {
1107         uint8_t* row = base + yoff->fOffset;
1108         SkDEBUGCODE((void)compute_row_length(row, width);)
1109         yoff->fOffset += trim_row_left_right(row, width, leftZeros, riteZeros);
1110         SkDEBUGCODE((void)compute_row_length(base + yoff->fOffset, width - leftZeros - riteZeros);)
1111         yoff += 1;
1112     }
1113     return true;
1114 }
1115 
row_is_all_zeros(const uint8_t * row,int width)1116 static bool row_is_all_zeros(const uint8_t* row, int width) {
1117     SkASSERT(width > 0);
1118     do {
1119         if (row[1]) {
1120             return false;
1121         }
1122         int n = row[0];
1123         SkASSERT(n <= width);
1124         width -= n;
1125         row += 2;
1126     } while (width > 0);
1127     SkASSERT(0 == width);
1128     return true;
1129 }
1130 
trimTopBottom()1131 bool SkAAClip::trimTopBottom() {
1132     if (this->isEmpty()) {
1133         return false;
1134     }
1135 
1136     this->validate();
1137 
1138     const int width = fBounds.width();
1139     RunHead* head = fRunHead;
1140     YOffset* yoff = head->yoffsets();
1141     YOffset* stop = yoff + head->fRowCount;
1142     const uint8_t* base = head->data();
1143 
1144     //  Look to trim away empty rows from the top.
1145     //
1146     int skip = 0;
1147     while (yoff < stop) {
1148         const uint8_t* data = base + yoff->fOffset;
1149         if (!row_is_all_zeros(data, width)) {
1150             break;
1151         }
1152         skip += 1;
1153         yoff += 1;
1154     }
1155     SkASSERT(skip <= head->fRowCount);
1156     if (skip == head->fRowCount) {
1157         return this->setEmpty();
1158     }
1159     if (skip > 0) {
1160         // adjust fRowCount and fBounds.fTop, and slide all the data up
1161         // as we remove [skip] number of YOffset entries
1162         yoff = head->yoffsets();
1163         int dy = yoff[skip - 1].fY + 1;
1164         for (int i = skip; i < head->fRowCount; ++i) {
1165             SkASSERT(yoff[i].fY >= dy);
1166             yoff[i].fY -= dy;
1167         }
1168         YOffset* dst = head->yoffsets();
1169         size_t size = head->fRowCount * sizeof(YOffset) + head->fDataSize;
1170         memmove(dst, dst + skip, size - skip * sizeof(YOffset));
1171 
1172         fBounds.fTop += dy;
1173         SkASSERT(!fBounds.isEmpty());
1174         head->fRowCount -= skip;
1175         SkASSERT(head->fRowCount > 0);
1176 
1177         this->validate();
1178         // need to reset this after the memmove
1179         base = head->data();
1180     }
1181 
1182     //  Look to trim away empty rows from the bottom.
1183     //  We know that we have at least one non-zero row, so we can just walk
1184     //  backwards without checking for running past the start.
1185     //
1186     stop = yoff = head->yoffsets() + head->fRowCount;
1187     do {
1188         yoff -= 1;
1189     } while (row_is_all_zeros(base + yoff->fOffset, width));
1190     skip = SkToInt(stop - yoff - 1);
1191     SkASSERT(skip >= 0 && skip < head->fRowCount);
1192     if (skip > 0) {
1193         // removing from the bottom is easier than from the top, as we don't
1194         // have to adjust any of the Y values, we just have to trim the array
1195         memmove(stop - skip, stop, head->fDataSize);
1196 
1197         fBounds.fBottom = fBounds.fTop + yoff->fY + 1;
1198         SkASSERT(!fBounds.isEmpty());
1199         head->fRowCount -= skip;
1200         SkASSERT(head->fRowCount > 0);
1201     }
1202     this->validate();
1203 
1204     return true;
1205 }
1206 
1207 // can't validate before we're done, since trimming is part of the process of
1208 // making us valid after the Builder. Since we build from top to bottom, its
1209 // possible our fBounds.fBottom is bigger than our last scanline of data, so
1210 // we trim fBounds.fBottom back up.
1211 //
1212 // TODO: check for duplicates in X and Y to further compress our data
1213 //
trimBounds()1214 bool SkAAClip::trimBounds() {
1215     if (this->isEmpty()) {
1216         return false;
1217     }
1218 
1219     const RunHead* head = fRunHead;
1220     const YOffset* yoff = head->yoffsets();
1221 
1222     SkASSERT(head->fRowCount > 0);
1223     const YOffset& lastY = yoff[head->fRowCount - 1];
1224     SkASSERT(lastY.fY + 1 <= fBounds.height());
1225     fBounds.fBottom = fBounds.fTop + lastY.fY + 1;
1226     SkASSERT(lastY.fY + 1 == fBounds.height());
1227     SkASSERT(!fBounds.isEmpty());
1228 
1229     return this->trimTopBottom() && this->trimLeftRight();
1230 }
1231 
1232 ///////////////////////////////////////////////////////////////////////////////
1233 
SkAAClip()1234 SkAAClip::SkAAClip() {
1235     fBounds.setEmpty();
1236     fRunHead = nullptr;
1237 }
1238 
SkAAClip(const SkAAClip & src)1239 SkAAClip::SkAAClip(const SkAAClip& src) {
1240     SkDEBUGCODE(fBounds.setEmpty();)    // need this for validate
1241     fRunHead = nullptr;
1242     *this = src;
1243 }
1244 
~SkAAClip()1245 SkAAClip::~SkAAClip() {
1246     this->freeRuns();
1247 }
1248 
operator =(const SkAAClip & src)1249 SkAAClip& SkAAClip::operator=(const SkAAClip& src) {
1250     AUTO_AACLIP_VALIDATE(*this);
1251     src.validate();
1252 
1253     if (this != &src) {
1254         this->freeRuns();
1255         fBounds = src.fBounds;
1256         fRunHead = src.fRunHead;
1257         if (fRunHead) {
1258             fRunHead->fRefCnt++;
1259         }
1260     }
1261     return *this;
1262 }
1263 
setEmpty()1264 bool SkAAClip::setEmpty() {
1265     this->freeRuns();
1266     fBounds.setEmpty();
1267     fRunHead = nullptr;
1268     return false;
1269 }
1270 
setRect(const SkIRect & bounds)1271 bool SkAAClip::setRect(const SkIRect& bounds) {
1272     if (bounds.isEmpty()) {
1273         return this->setEmpty();
1274     }
1275 
1276     AUTO_AACLIP_VALIDATE(*this);
1277 
1278     this->freeRuns();
1279     fBounds = bounds;
1280     fRunHead = RunHead::AllocRect(bounds);
1281     SkASSERT(!this->isEmpty());
1282     return true;
1283 }
1284 
isRect() const1285 bool SkAAClip::isRect() const {
1286     if (this->isEmpty()) {
1287         return false;
1288     }
1289 
1290     const RunHead* head = fRunHead;
1291     if (head->fRowCount != 1) {
1292         return false;
1293     }
1294     const YOffset* yoff = head->yoffsets();
1295     if (yoff->fY != fBounds.fBottom - 1) {
1296         return false;
1297     }
1298 
1299     const uint8_t* row = head->data() + yoff->fOffset;
1300     int width = fBounds.width();
1301     do {
1302         if (row[1] != 0xFF) {
1303             return false;
1304         }
1305         int n = row[0];
1306         SkASSERT(n <= width);
1307         width -= n;
1308         row += 2;
1309     } while (width > 0);
1310     return true;
1311 }
1312 
setRegion(const SkRegion & rgn)1313 bool SkAAClip::setRegion(const SkRegion& rgn) {
1314     if (rgn.isEmpty()) {
1315         return this->setEmpty();
1316     }
1317     if (rgn.isRect()) {
1318         return this->setRect(rgn.getBounds());
1319     }
1320 
1321 
1322     const SkIRect& bounds = rgn.getBounds();
1323     const int offsetX = bounds.fLeft;
1324     const int offsetY = bounds.fTop;
1325 
1326     SkTDArray<YOffset> yArray;
1327     SkTDArray<uint8_t> xArray;
1328 
1329     yArray.reserve(std::min(bounds.height(), 1024));
1330     xArray.reserve(std::min(bounds.width(), 512) * 128);
1331 
1332     auto appendXRun = [&xArray](uint8_t value, int count) {
1333         SkASSERT(count >= 0);
1334         while (count > 0) {
1335             int n = count;
1336             if (n > 255) {
1337                 n = 255;
1338             }
1339             uint8_t* data = xArray.append(2);
1340             data[0] = n;
1341             data[1] = value;
1342             count -= n;
1343         }
1344     };
1345 
1346     SkRegion::Iterator iter(rgn);
1347     int prevRight = 0;
1348     int prevBot = 0;
1349     YOffset* currY = nullptr;
1350 
1351     for (; !iter.done(); iter.next()) {
1352         const SkIRect& r = iter.rect();
1353         SkASSERT(bounds.contains(r));
1354 
1355         int bot = r.fBottom - offsetY;
1356         SkASSERT(bot >= prevBot);
1357         if (bot > prevBot) {
1358             if (currY) {
1359                 // flush current row
1360                 appendXRun(0, bounds.width() - prevRight);
1361             }
1362             // did we introduce an empty-gap from the prev row?
1363             int top = r.fTop - offsetY;
1364             if (top > prevBot) {
1365                 currY = yArray.append();
1366                 currY->fY = top - 1;
1367                 currY->fOffset = xArray.size();
1368                 appendXRun(0, bounds.width());
1369             }
1370             // create a new record for this Y value
1371             currY = yArray.append();
1372             currY->fY = bot - 1;
1373             currY->fOffset = xArray.size();
1374             prevRight = 0;
1375             prevBot = bot;
1376         }
1377 
1378         int x = r.fLeft - offsetX;
1379         appendXRun(0, x - prevRight);
1380 
1381         int w = r.fRight - r.fLeft;
1382         appendXRun(0xFF, w);
1383         prevRight = x + w;
1384         SkASSERT(prevRight <= bounds.width());
1385     }
1386     // flush last row
1387     appendXRun(0, bounds.width() - prevRight);
1388 
1389     // now pack everything into a RunHead
1390     RunHead* head = RunHead::Alloc(yArray.size(), xArray.size_bytes());
1391     memcpy(head->yoffsets(), yArray.begin(), yArray.size_bytes());
1392     memcpy(head->data(), xArray.begin(), xArray.size_bytes());
1393 
1394     this->setEmpty();
1395     fBounds = bounds;
1396     fRunHead = head;
1397     this->validate();
1398     return true;
1399 }
1400 
setPath(const SkPath & path,const SkIRect & clip,bool doAA)1401 bool SkAAClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) {
1402     AUTO_AACLIP_VALIDATE(*this);
1403 
1404     if (clip.isEmpty()) {
1405         return this->setEmpty();
1406     }
1407 
1408     SkIRect ibounds;
1409     // Since we assert that the BuilderBlitter will never blit outside the intersection
1410     // of clip and ibounds, we create the builder with the snug bounds.
1411     if (path.isInverseFillType()) {
1412         ibounds = clip;
1413     } else {
1414         path.getBounds().roundOut(&ibounds);
1415         if (ibounds.isEmpty() || !ibounds.intersect(clip)) {
1416             return this->setEmpty();
1417         }
1418     }
1419 
1420     Builder builder(ibounds);
1421     return builder.blitPath(this, path, doAA);
1422 }
1423 
1424 ///////////////////////////////////////////////////////////////////////////////
1425 
op(const SkAAClip & other,SkClipOp op)1426 bool SkAAClip::op(const SkAAClip& other, SkClipOp op) {
1427     AUTO_AACLIP_VALIDATE(*this);
1428 
1429     if (this->isEmpty()) {
1430         // Once the clip is empty, it cannot become un-empty.
1431         return false;
1432     }
1433 
1434     SkIRect bounds = fBounds;
1435     switch(op) {
1436         case SkClipOp::kDifference:
1437             if (other.isEmpty() || !SkIRect::Intersects(fBounds, other.fBounds)) {
1438                 // this remains unmodified and isn't empty
1439                 return true;
1440             }
1441             break;
1442 
1443         case SkClipOp::kIntersect:
1444             if (other.isEmpty() || !bounds.intersect(other.fBounds)) {
1445                 // the intersected clip becomes empty
1446                 return this->setEmpty();
1447             }
1448             break;
1449     }
1450 
1451 
1452     SkASSERT(SkIRect::Intersects(bounds, fBounds));
1453     SkASSERT(SkIRect::Intersects(bounds, other.fBounds));
1454 
1455     Builder builder(bounds);
1456     return builder.applyClipOp(this, other, op);
1457 }
1458 
op(const SkIRect & rect,SkClipOp op)1459 bool SkAAClip::op(const SkIRect& rect, SkClipOp op) {
1460     // It can be expensive to build a local aaclip before applying the op, so
1461     // we first see if we can restrict the bounds of new rect to our current
1462     // bounds, or note that the new rect subsumes our current clip.
1463     SkIRect pixelBounds = fBounds;
1464     if (!pixelBounds.intersect(rect)) {
1465         // No change or clip becomes empty depending on 'op'
1466         switch(op) {
1467             case SkClipOp::kDifference: return !this->isEmpty();
1468             case SkClipOp::kIntersect:  return this->setEmpty();
1469         }
1470         SkUNREACHABLE;
1471     } else if (pixelBounds == fBounds) {
1472         // Wholly inside 'rect', so clip becomes empty or remains unchanged
1473         switch(op) {
1474             case SkClipOp::kDifference: return this->setEmpty();
1475             case SkClipOp::kIntersect:  return !this->isEmpty();
1476         }
1477         SkUNREACHABLE;
1478     } else if (op == SkClipOp::kIntersect && this->quickContains(pixelBounds)) {
1479         // We become just the remaining rectangle
1480         return this->setRect(pixelBounds);
1481     } else {
1482         SkAAClip clip;
1483         clip.setRect(rect);
1484         return this->op(clip, op);
1485     }
1486 }
1487 
op(const SkRect & rect,SkClipOp op,bool doAA)1488 bool SkAAClip::op(const SkRect& rect, SkClipOp op, bool doAA) {
1489     if (!doAA) {
1490         return this->op(rect.round(), op);
1491     } else {
1492         // Tighten bounds for "path" aaclip of the rect
1493         SkIRect pixelBounds = fBounds;
1494         if (!pixelBounds.intersect(rect.roundOut())) {
1495             // No change or clip becomes empty depending on 'op'
1496             switch(op) {
1497                 case SkClipOp::kDifference: return !this->isEmpty();
1498                 case SkClipOp::kIntersect:  return this->setEmpty();
1499             }
1500             SkUNREACHABLE;
1501         } else if (rect.contains(SkRect::Make(fBounds))) {
1502             // Wholly inside 'rect', so clip becomes empty or remains unchanged
1503             switch(op) {
1504                 case SkClipOp::kDifference: return this->setEmpty();
1505                 case SkClipOp::kIntersect:  return !this->isEmpty();
1506             }
1507             SkUNREACHABLE;
1508         } else if (op == SkClipOp::kIntersect && this->quickContains(pixelBounds)) {
1509             // We become just the rect intersected with pixel bounds (preserving fractional coords
1510             // for AA edges).
1511             return this->setPath(SkPath::Rect(rect), pixelBounds, /*doAA=*/true);
1512         } else {
1513             SkAAClip rectClip;
1514             rectClip.setPath(SkPath::Rect(rect),
1515                              op == SkClipOp::kDifference ? fBounds : pixelBounds,
1516                              /*doAA=*/true);
1517             return this->op(rectClip, op);
1518         }
1519     }
1520 }
1521 
1522 ///////////////////////////////////////////////////////////////////////////////
1523 
translate(int dx,int dy,SkAAClip * dst) const1524 bool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const {
1525     if (nullptr == dst) {
1526         return !this->isEmpty();
1527     }
1528 
1529     if (this->isEmpty()) {
1530         return dst->setEmpty();
1531     }
1532 
1533     if (this != dst) {
1534         fRunHead->fRefCnt++;
1535         dst->freeRuns();
1536         dst->fRunHead = fRunHead;
1537         dst->fBounds = fBounds;
1538     }
1539     dst->fBounds.offset(dx, dy);
1540     return true;
1541 }
1542 
freeRuns()1543 void SkAAClip::freeRuns() {
1544     if (fRunHead) {
1545         SkASSERT(fRunHead->fRefCnt.load() >= 1);
1546         if (1 == fRunHead->fRefCnt--) {
1547             sk_free(fRunHead);
1548         }
1549     }
1550 }
1551 
findRow(int y,int * lastYForRow) const1552 const uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const {
1553     SkASSERT(fRunHead);
1554 
1555     if (y < fBounds.fTop || y >= fBounds.fBottom) {
1556         return nullptr;
1557     }
1558     y -= fBounds.y();  // our yoffs values are relative to the top
1559 
1560     const YOffset* yoff = fRunHead->yoffsets();
1561     while (yoff->fY < y) {
1562         yoff += 1;
1563         SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount);
1564     }
1565 
1566     if (lastYForRow) {
1567         *lastYForRow = fBounds.y() + yoff->fY;
1568     }
1569     return fRunHead->data() + yoff->fOffset;
1570 }
1571 
findX(const uint8_t data[],int x,int * initialCount) const1572 const uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const {
1573     SkASSERT(x >= fBounds.fLeft && x < fBounds.fRight);
1574     x -= fBounds.x();
1575 
1576     // first skip up to X
1577     for (;;) {
1578         int n = data[0];
1579         if (x < n) {
1580             if (initialCount) {
1581                 *initialCount = n - x;
1582             }
1583             break;
1584         }
1585         data += 2;
1586         x -= n;
1587     }
1588     return data;
1589 }
1590 
quickContains(int left,int top,int right,int bottom) const1591 bool SkAAClip::quickContains(int left, int top, int right, int bottom) const {
1592     if (this->isEmpty()) {
1593         return false;
1594     }
1595     if (!fBounds.contains(SkIRect{left, top, right, bottom})) {
1596         return false;
1597     }
1598 
1599     int lastY SK_INIT_TO_AVOID_WARNING;
1600     const uint8_t* row = this->findRow(top, &lastY);
1601     if (lastY < bottom) {
1602         return false;
1603     }
1604     // now just need to check in X
1605     int count;
1606     row = this->findX(row, left, &count);
1607 
1608     int rectWidth = right - left;
1609     while (0xFF == row[1]) {
1610         if (count >= rectWidth) {
1611             return true;
1612         }
1613         rectWidth -= count;
1614         row += 2;
1615         count = row[0];
1616     }
1617     return false;
1618 }
1619 
1620 ///////////////////////////////////////////////////////////////////////////////
1621 
expandToRuns(const uint8_t * SK_RESTRICT data,int initialCount,int width,int16_t * SK_RESTRICT runs,SkAlpha * SK_RESTRICT aa)1622 static void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width,
1623                          int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) {
1624     // we don't read our initial n from data, since the caller may have had to
1625     // clip it, hence the initialCount parameter.
1626     int n = initialCount;
1627     for (;;) {
1628         if (n > width) {
1629             n = width;
1630         }
1631         SkASSERT(n > 0);
1632         runs[0] = n;
1633         runs += n;
1634 
1635         aa[0] = data[1];
1636         aa += n;
1637 
1638         data += 2;
1639         width -= n;
1640         if (0 == width) {
1641             break;
1642         }
1643         // load the next count
1644         n = data[0];
1645     }
1646     runs[0] = 0;    // sentinel
1647 }
1648 
~SkAAClipBlitter()1649 SkAAClipBlitter::~SkAAClipBlitter() {
1650     sk_free(fScanlineScratch);
1651 }
1652 
ensureRunsAndAA()1653 void SkAAClipBlitter::ensureRunsAndAA() {
1654     if (nullptr == fScanlineScratch) {
1655         // add 1 so we can store the terminating run count of 0
1656         int count = fAAClipBounds.width() + 1;
1657         // we use this either for fRuns + fAA, or a scaline of a mask
1658         // which may be as deep as 32bits
1659         fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor));
1660         fRuns = (int16_t*)fScanlineScratch;
1661         fAA = (SkAlpha*)(fRuns + count);
1662     }
1663 }
1664 
blitH(int x,int y,int width)1665 void SkAAClipBlitter::blitH(int x, int y, int width) {
1666     SkASSERT(width > 0);
1667     SkASSERT(fAAClipBounds.contains(x, y));
1668     SkASSERT(fAAClipBounds.contains(x + width  - 1, y));
1669 
1670     const uint8_t* row = fAAClip->findRow(y);
1671     int initialCount;
1672     row = fAAClip->findX(row, x, &initialCount);
1673 
1674     if (initialCount >= width) {
1675         SkAlpha alpha = row[1];
1676         if (0 == alpha) {
1677             return;
1678         }
1679         if (0xFF == alpha) {
1680             fBlitter->blitH(x, y, width);
1681             return;
1682         }
1683     }
1684 
1685     this->ensureRunsAndAA();
1686     expandToRuns(row, initialCount, width, fRuns, fAA);
1687 
1688     fBlitter->blitAntiH(x, y, fAA, fRuns);
1689 }
1690 
merge(const uint8_t * SK_RESTRICT row,int rowN,const SkAlpha * SK_RESTRICT srcAA,const int16_t * SK_RESTRICT srcRuns,SkAlpha * SK_RESTRICT dstAA,int16_t * SK_RESTRICT dstRuns,int width)1691 static void merge(const uint8_t* SK_RESTRICT row, int rowN,
1692                   const SkAlpha* SK_RESTRICT srcAA,
1693                   const int16_t* SK_RESTRICT srcRuns,
1694                   SkAlpha* SK_RESTRICT dstAA,
1695                   int16_t* SK_RESTRICT dstRuns,
1696                   int width) {
1697     SkDEBUGCODE(int accumulated = 0;)
1698     int srcN = srcRuns[0];
1699     // do we need this check?
1700     if (0 == srcN) {
1701         return;
1702     }
1703 
1704     for (;;) {
1705         SkASSERT(rowN > 0);
1706         SkASSERT(srcN > 0);
1707 
1708         unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]);
1709         int minN = std::min(srcN, rowN);
1710         dstRuns[0] = minN;
1711         dstRuns += minN;
1712         dstAA[0] = newAlpha;
1713         dstAA += minN;
1714 
1715         if (0 == (srcN -= minN)) {
1716             srcN = srcRuns[0];  // refresh
1717             srcRuns += srcN;
1718             srcAA += srcN;
1719             srcN = srcRuns[0];  // reload
1720             if (0 == srcN) {
1721                 break;
1722             }
1723         }
1724         if (0 == (rowN -= minN)) {
1725             row += 2;
1726             rowN = row[0];  // reload
1727         }
1728 
1729         SkDEBUGCODE(accumulated += minN;)
1730         SkASSERT(accumulated <= width);
1731     }
1732     dstRuns[0] = 0;
1733 }
1734 
blitAntiH(int x,int y,const SkAlpha aa[],const int16_t runs[])1735 void SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
1736                                 const int16_t runs[]) {
1737 
1738     const uint8_t* row = fAAClip->findRow(y);
1739     int initialCount;
1740     row = fAAClip->findX(row, x, &initialCount);
1741 
1742     this->ensureRunsAndAA();
1743 
1744     merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width());
1745     fBlitter->blitAntiH(x, y, fAA, fRuns);
1746 }
1747 
blitV(int x,int y,int height,SkAlpha alpha)1748 void SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
1749     if (fAAClip->quickContains(x, y, x + 1, y + height)) {
1750         fBlitter->blitV(x, y, height, alpha);
1751         return;
1752     }
1753 
1754     for (;;) {
1755         int lastY SK_INIT_TO_AVOID_WARNING;
1756         const uint8_t* row = fAAClip->findRow(y, &lastY);
1757         int dy = lastY - y + 1;
1758         if (dy > height) {
1759             dy = height;
1760         }
1761         height -= dy;
1762 
1763         row = fAAClip->findX(row, x);
1764         SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]);
1765         if (newAlpha) {
1766             fBlitter->blitV(x, y, dy, newAlpha);
1767         }
1768         SkASSERT(height >= 0);
1769         if (height <= 0) {
1770             break;
1771         }
1772         y = lastY + 1;
1773     }
1774 }
1775 
blitRect(int x,int y,int width,int height)1776 void SkAAClipBlitter::blitRect(int x, int y, int width, int height) {
1777     if (fAAClip->quickContains(x, y, x + width, y + height)) {
1778         fBlitter->blitRect(x, y, width, height);
1779         return;
1780     }
1781 
1782     while (--height >= 0) {
1783         this->blitH(x, y, width);
1784         y += 1;
1785     }
1786 }
1787 
1788 typedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row,
1789                             int initialRowCount, void* dst);
1790 
small_memcpy(void * dst,const void * src,size_t n)1791 static void small_memcpy(void* dst, const void* src, size_t n) {
1792     memcpy(dst, src, n);
1793 }
1794 
small_bzero(void * dst,size_t n)1795 static void small_bzero(void* dst, size_t n) {
1796     sk_bzero(dst, n);
1797 }
1798 
mergeOne(uint8_t value,unsigned alpha)1799 static inline uint8_t mergeOne(uint8_t value, unsigned alpha) {
1800     return SkMulDiv255Round(value, alpha);
1801 }
1802 
mergeOne(uint16_t value,unsigned alpha)1803 static inline uint16_t mergeOne(uint16_t value, unsigned alpha) {
1804     unsigned r = SkGetPackedR16(value);
1805     unsigned g = SkGetPackedG16(value);
1806     unsigned b = SkGetPackedB16(value);
1807     return SkPackRGB16(SkMulDiv255Round(r, alpha),
1808                        SkMulDiv255Round(g, alpha),
1809                        SkMulDiv255Round(b, alpha));
1810 }
1811 
1812 template <typename T>
mergeT(const void * inSrc,int srcN,const uint8_t * SK_RESTRICT row,int rowN,void * inDst)1813 void mergeT(const void* inSrc, int srcN, const uint8_t* SK_RESTRICT row, int rowN, void* inDst) {
1814     const T* SK_RESTRICT src = static_cast<const T*>(inSrc);
1815     T* SK_RESTRICT       dst = static_cast<T*>(inDst);
1816     for (;;) {
1817         SkASSERT(rowN > 0);
1818         SkASSERT(srcN > 0);
1819 
1820         int n = std::min(rowN, srcN);
1821         unsigned rowA = row[1];
1822         if (0xFF == rowA) {
1823             small_memcpy(dst, src, n * sizeof(T));
1824         } else if (0 == rowA) {
1825             small_bzero(dst, n * sizeof(T));
1826         } else {
1827             for (int i = 0; i < n; ++i) {
1828                 dst[i] = mergeOne(src[i], rowA);
1829             }
1830         }
1831 
1832         if (0 == (srcN -= n)) {
1833             break;
1834         }
1835 
1836         src += n;
1837         dst += n;
1838 
1839         SkASSERT(rowN == n);
1840         row += 2;
1841         rowN = row[0];
1842     }
1843 }
1844 
find_merge_aa_proc(SkMask::Format format)1845 static MergeAAProc find_merge_aa_proc(SkMask::Format format) {
1846     switch (format) {
1847         case SkMask::kBW_Format:
1848             SkDEBUGFAIL("unsupported");
1849             return nullptr;
1850         case SkMask::kA8_Format:
1851         case SkMask::k3D_Format:
1852             return mergeT<uint8_t> ;
1853         case SkMask::kLCD16_Format:
1854             return mergeT<uint16_t>;
1855         default:
1856             SkDEBUGFAIL("unsupported");
1857             return nullptr;
1858     }
1859 }
1860 
bit2byte(int bitInAByte)1861 static U8CPU bit2byte(int bitInAByte) {
1862     SkASSERT(bitInAByte <= 0xFF);
1863     // negation turns any non-zero into 0xFFFFFF??, so we just shift down
1864     // some value >= 8 to get a full FF value
1865     return -bitInAByte >> 8;
1866 }
1867 
upscaleBW2A8(SkMask * dstMask,const SkMask & srcMask)1868 static void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) {
1869     SkASSERT(SkMask::kBW_Format == srcMask.fFormat);
1870     SkASSERT(SkMask::kA8_Format == dstMask->fFormat);
1871 
1872     const int width = srcMask.fBounds.width();
1873     const int height = srcMask.fBounds.height();
1874 
1875     const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage;
1876     const size_t srcRB = srcMask.fRowBytes;
1877     uint8_t* SK_RESTRICT dst = const_cast<uint8_t*>(dstMask->fImage);
1878     const size_t dstRB = dstMask->fRowBytes;
1879 
1880     const int wholeBytes = width >> 3;
1881     const int leftOverBits = width & 7;
1882 
1883     for (int y = 0; y < height; ++y) {
1884         uint8_t* SK_RESTRICT d = dst;
1885         for (int i = 0; i < wholeBytes; ++i) {
1886             int srcByte = src[i];
1887             d[0] = bit2byte(srcByte & (1 << 7));
1888             d[1] = bit2byte(srcByte & (1 << 6));
1889             d[2] = bit2byte(srcByte & (1 << 5));
1890             d[3] = bit2byte(srcByte & (1 << 4));
1891             d[4] = bit2byte(srcByte & (1 << 3));
1892             d[5] = bit2byte(srcByte & (1 << 2));
1893             d[6] = bit2byte(srcByte & (1 << 1));
1894             d[7] = bit2byte(srcByte & (1 << 0));
1895             d += 8;
1896         }
1897         if (leftOverBits) {
1898             int srcByte = src[wholeBytes];
1899             for (int x = 0; x < leftOverBits; ++x) {
1900                 *d++ = bit2byte(srcByte & 0x80);
1901                 srcByte <<= 1;
1902             }
1903         }
1904         src += srcRB;
1905         dst += dstRB;
1906     }
1907 }
1908 
blitMask(const SkMask & origMask,const SkIRect & clip)1909 void SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) {
1910     SkASSERT(fAAClip->getBounds().contains(clip));
1911 
1912     if (fAAClip->quickContains(clip)) {
1913         fBlitter->blitMask(origMask, clip);
1914         return;
1915     }
1916 
1917     const SkMask* mask = &origMask;
1918 
1919     // if we're BW, we need to upscale to A8 (ugh)
1920     SkMaskBuilder  grayMask;
1921     if (SkMask::kBW_Format == origMask.fFormat) {
1922         grayMask.format() = SkMask::kA8_Format;
1923         grayMask.bounds() = origMask.fBounds;
1924         grayMask.rowBytes() = origMask.fBounds.width();
1925         size_t size = grayMask.computeImageSize();
1926         grayMask.image() = reinterpret_cast<uint8_t*>(
1927             fGrayMaskScratch.reset(size, SkAutoMalloc::kReuse_OnShrink));
1928 
1929         upscaleBW2A8(&grayMask, origMask);
1930         mask = &grayMask;
1931     }
1932 
1933     this->ensureRunsAndAA();
1934 
1935     // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D
1936     // data into a temp block to support it better (ugh)
1937 
1938     const void* src = mask->getAddr(clip.fLeft, clip.fTop);
1939     const size_t srcRB = mask->fRowBytes;
1940     const int width = clip.width();
1941     MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat);
1942 
1943     SkMaskBuilder rowMask;
1944     rowMask.format() = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat;
1945     rowMask.bounds().fLeft = clip.fLeft;
1946     rowMask.bounds().fRight = clip.fRight;
1947     rowMask.rowBytes() = mask->fRowBytes; // doesn't matter, since our height==1
1948     rowMask.image() = (uint8_t*)fScanlineScratch;
1949 
1950     int y = clip.fTop;
1951     const int stopY = y + clip.height();
1952 
1953     do {
1954         int localStopY SK_INIT_TO_AVOID_WARNING;
1955         const uint8_t* row = fAAClip->findRow(y, &localStopY);
1956         // findRow returns last Y, not stop, so we add 1
1957         localStopY = std::min(localStopY + 1, stopY);
1958 
1959         int initialCount;
1960         row = fAAClip->findX(row, clip.fLeft, &initialCount);
1961         do {
1962             mergeProc(src, width, row, initialCount, rowMask.image());
1963             rowMask.bounds().fTop = y;
1964             rowMask.bounds().fBottom = y + 1;
1965             fBlitter->blitMask(rowMask, rowMask.fBounds);
1966             src = (const void*)((const char*)src + srcRB);
1967         } while (++y < localStopY);
1968     } while (y < stopY);
1969 }
1970