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