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