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