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