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