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