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