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