1 :
2 : /*
3 : * Copyright 2006 The Android Open Source Project
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 :
10 : #include "SkRegionPriv.h"
11 : #include "SkTemplates.h"
12 : #include "SkThread.h"
13 :
14 : SkDEBUGCODE(int32_t gRgnAllocCounter;)
15 :
16 : /////////////////////////////////////////////////////////////////////////////////////////////////
17 :
18 : /* Pass in a scanline, beginning with the Left value of the pair (i.e. not the Y beginning)
19 : */
20 0 : static SkRegion::RunType* skip_scanline(const SkRegion::RunType runs[])
21 : {
22 0 : while (runs[0] != SkRegion::kRunTypeSentinel)
23 : {
24 0 : SkASSERT(runs[0] < runs[1]); // valid span
25 0 : runs += 2;
26 : }
27 0 : return (SkRegion::RunType*)(runs + 1); // return past the X-sentinel
28 : }
29 :
30 : // returns true if runs are just a rect
31 0 : bool SkRegion::ComputeRunBounds(const SkRegion::RunType runs[], int count, SkIRect* bounds)
32 : {
33 0 : assert_sentinel(runs[0], false); // top
34 :
35 0 : if (count == kRectRegionRuns)
36 : {
37 0 : assert_sentinel(runs[1], false); // bottom
38 0 : assert_sentinel(runs[2], false); // left
39 0 : assert_sentinel(runs[3], false); // right
40 0 : assert_sentinel(runs[4], true);
41 0 : assert_sentinel(runs[5], true);
42 :
43 0 : SkASSERT(runs[0] < runs[1]); // valid height
44 0 : SkASSERT(runs[2] < runs[3]); // valid width
45 :
46 0 : bounds->set(runs[2], runs[0], runs[3], runs[1]);
47 0 : return true;
48 : }
49 :
50 0 : int left = SK_MaxS32;
51 0 : int rite = SK_MinS32;
52 : int bot;
53 :
54 0 : bounds->fTop = *runs++;
55 0 : do {
56 0 : bot = *runs++;
57 0 : if (*runs < SkRegion::kRunTypeSentinel)
58 : {
59 0 : if (left > *runs)
60 0 : left = *runs;
61 0 : runs = skip_scanline(runs);
62 0 : if (rite < runs[-2])
63 0 : rite = runs[-2];
64 : }
65 : else
66 0 : runs += 1; // skip X-sentinel
67 0 : } while (runs[0] < SkRegion::kRunTypeSentinel);
68 0 : bounds->fLeft = left;
69 0 : bounds->fRight = rite;
70 0 : bounds->fBottom = bot;
71 0 : return false;
72 : }
73 :
74 : //////////////////////////////////////////////////////////////////////////
75 :
76 0 : SkRegion::SkRegion() {
77 0 : fBounds.set(0, 0, 0, 0);
78 0 : fRunHead = SkRegion_gEmptyRunHeadPtr;
79 0 : }
80 :
81 0 : SkRegion::SkRegion(const SkRegion& src) {
82 0 : fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead)
83 0 : this->setRegion(src);
84 0 : }
85 :
86 0 : SkRegion::SkRegion(const SkIRect& rect) {
87 0 : fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead)
88 0 : this->setRect(rect);
89 0 : }
90 :
91 0 : SkRegion::~SkRegion() {
92 0 : this->freeRuns();
93 0 : }
94 :
95 0 : void SkRegion::freeRuns() {
96 0 : if (fRunHead->isComplex()) {
97 0 : SkASSERT(fRunHead->fRefCnt >= 1);
98 0 : if (sk_atomic_dec(&fRunHead->fRefCnt) == 1) {
99 : //SkASSERT(gRgnAllocCounter > 0);
100 : //SkDEBUGCODE(sk_atomic_dec(&gRgnAllocCounter));
101 : //SkDEBUGF(("************** gRgnAllocCounter::free %d\n", gRgnAllocCounter));
102 0 : sk_free(fRunHead);
103 : }
104 : }
105 0 : }
106 :
107 0 : void SkRegion::allocateRuns(int count) {
108 0 : fRunHead = RunHead::Alloc(count);
109 0 : }
110 :
111 0 : SkRegion& SkRegion::operator=(const SkRegion& src) {
112 0 : (void)this->setRegion(src);
113 0 : return *this;
114 : }
115 :
116 0 : void SkRegion::swap(SkRegion& other) {
117 0 : SkTSwap<SkIRect>(fBounds, other.fBounds);
118 0 : SkTSwap<RunHead*>(fRunHead, other.fRunHead);
119 0 : }
120 :
121 0 : bool SkRegion::setEmpty() {
122 0 : this->freeRuns();
123 0 : fBounds.set(0, 0, 0, 0);
124 0 : fRunHead = SkRegion_gEmptyRunHeadPtr;
125 0 : return false;
126 : }
127 :
128 0 : bool SkRegion::setRect(int32_t left, int32_t top,
129 : int32_t right, int32_t bottom) {
130 0 : if (left >= right || top >= bottom) {
131 0 : return this->setEmpty();
132 : }
133 0 : this->freeRuns();
134 0 : fBounds.set(left, top, right, bottom);
135 0 : fRunHead = SkRegion_gRectRunHeadPtr;
136 0 : return true;
137 : }
138 :
139 0 : bool SkRegion::setRect(const SkIRect& r) {
140 0 : return this->setRect(r.fLeft, r.fTop, r.fRight, r.fBottom);
141 : }
142 :
143 0 : bool SkRegion::setRegion(const SkRegion& src) {
144 0 : if (this != &src) {
145 0 : this->freeRuns();
146 :
147 0 : fBounds = src.fBounds;
148 0 : fRunHead = src.fRunHead;
149 0 : if (fRunHead->isComplex()) {
150 0 : sk_atomic_inc(&fRunHead->fRefCnt);
151 : }
152 : }
153 0 : return fRunHead != SkRegion_gEmptyRunHeadPtr;
154 : }
155 :
156 0 : bool SkRegion::op(const SkIRect& rect, const SkRegion& rgn, Op op) {
157 0 : SkRegion tmp(rect);
158 :
159 0 : return this->op(tmp, rgn, op);
160 : }
161 :
162 0 : bool SkRegion::op(const SkRegion& rgn, const SkIRect& rect, Op op) {
163 0 : SkRegion tmp(rect);
164 :
165 0 : return this->op(rgn, tmp, op);
166 : }
167 :
168 : ///////////////////////////////////////////////////////////////////////////////
169 :
170 : #ifdef SK_BUILD_FOR_ANDROID
171 : char* SkRegion::toString()
172 : {
173 : Iterator iter(*this);
174 : int count = 0;
175 : while (!iter.done()) {
176 : count++;
177 : iter.next();
178 : }
179 : // 4 ints, up to 10 digits each plus sign, 3 commas, '(', ')', SkRegion() and '\0'
180 : const int max = (count*((11*4)+5))+11+1;
181 : char* result = (char*)malloc(max);
182 : if (result == NULL) {
183 : return NULL;
184 : }
185 : count = sprintf(result, "SkRegion(");
186 : iter.reset(*this);
187 : while (!iter.done()) {
188 : const SkIRect& r = iter.rect();
189 : count += sprintf(result+count, "(%d,%d,%d,%d)", r.fLeft, r.fTop, r.fRight, r.fBottom);
190 : iter.next();
191 : }
192 : count += sprintf(result+count, ")");
193 : return result;
194 : }
195 : #endif
196 :
197 : //////////////////////////////////////////////////////////////////////////////////////
198 :
199 0 : int SkRegion::count_runtype_values(int* itop, int* ibot) const
200 : {
201 0 : if (this == NULL)
202 : {
203 0 : *itop = SK_MinS32;
204 0 : *ibot = SK_MaxS32;
205 0 : return 0;
206 : }
207 :
208 : int maxT;
209 :
210 0 : if (this->isRect())
211 0 : maxT = 2;
212 : else
213 : {
214 0 : SkASSERT(this->isComplex());
215 : // skip the top
216 0 : const RunType* runs = fRunHead->readonly_runs() + 1;
217 0 : maxT = 0;
218 :
219 0 : do {
220 0 : const RunType* next = skip_scanline(runs + 1);
221 0 : SkASSERT(next > runs);
222 0 : int T = (int)(next - runs - 1);
223 0 : if (maxT < T)
224 0 : maxT = T;
225 0 : runs = next;
226 0 : } while (runs[0] < SkRegion::kRunTypeSentinel);
227 : }
228 0 : *itop = fBounds.fTop;
229 0 : *ibot = fBounds.fBottom;
230 0 : return maxT;
231 : }
232 :
233 0 : bool SkRegion::setRuns(RunType runs[], int count)
234 : {
235 0 : SkDEBUGCODE(this->validate();)
236 0 : SkASSERT(count > 0);
237 :
238 0 : if (count <= 2)
239 : {
240 : // SkDEBUGF(("setRuns: empty\n"));
241 0 : assert_sentinel(runs[count-1], true);
242 0 : return this->setEmpty();
243 : }
244 :
245 : // trim off any empty spans from the top and bottom
246 : // weird I should need this, perhaps op() could be smarter...
247 0 : if (count > kRectRegionRuns)
248 : {
249 0 : RunType* stop = runs + count;
250 0 : assert_sentinel(runs[0], false); // top
251 0 : assert_sentinel(runs[1], false); // bottom
252 0 : if (runs[2] == SkRegion::kRunTypeSentinel) // should be first left...
253 : {
254 0 : runs += 2; // skip empty initial span
255 0 : runs[0] = runs[-1]; // set new top to prev bottom
256 0 : assert_sentinel(runs[1], false); // bot: a sentinal would mean two in a row
257 0 : assert_sentinel(runs[2], false); // left
258 0 : assert_sentinel(runs[3], false); // right
259 : }
260 :
261 : // now check for a trailing empty span
262 0 : assert_sentinel(stop[-1], true);
263 0 : assert_sentinel(stop[-2], true);
264 0 : assert_sentinel(stop[-3], false); // should be last right
265 0 : if (stop[-4] == SkRegion::kRunTypeSentinel) // eek, stop[-3] was a bottom with no x-runs
266 : {
267 0 : stop[-3] = SkRegion::kRunTypeSentinel; // kill empty last span
268 0 : stop -= 2;
269 0 : assert_sentinel(stop[-1], true);
270 0 : assert_sentinel(stop[-2], true);
271 0 : assert_sentinel(stop[-3], false);
272 0 : assert_sentinel(stop[-4], false);
273 0 : assert_sentinel(stop[-5], false);
274 : }
275 0 : count = (int)(stop - runs);
276 : }
277 :
278 0 : SkASSERT(count >= kRectRegionRuns);
279 :
280 0 : if (ComputeRunBounds(runs, count, &fBounds))
281 : {
282 : // SkDEBUGF(("setRuns: rect[%d %d %d %d]\n", fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom));
283 0 : return this->setRect(fBounds);
284 : }
285 :
286 : // if we get here, we need to become a complex region
287 :
288 0 : if (!fRunHead->isComplex() || fRunHead->fRunCount != count)
289 : {
290 : #ifdef SK_DEBUGx
291 : SkDebugf("setRuns: rgn [");
292 : {
293 : const RunType* r = runs;
294 :
295 : SkDebugf(" top: %d\n", *r++);
296 : while (*r < SkRegion::kRunTypeSentinel)
297 : {
298 : SkDebugf(" bottom: %d", *r++);
299 : while (*r < SkRegion::kRunTypeSentinel)
300 : {
301 : SkDebugf(" [%d %d]", r[0], r[1]);
302 : r += 2;
303 : }
304 : SkDebugf("\n");
305 : }
306 : }
307 : #endif
308 0 : this->freeRuns();
309 0 : this->allocateRuns(count);
310 : }
311 :
312 : // must call this before we can write directly into runs()
313 : // in case we are sharing the buffer with another region (copy on write)
314 0 : fRunHead = fRunHead->ensureWritable();
315 0 : memcpy(fRunHead->writable_runs(), runs, count * sizeof(RunType));
316 :
317 0 : SkDEBUGCODE(this->validate();)
318 :
319 0 : return true;
320 : }
321 :
322 0 : void SkRegion::BuildRectRuns(const SkIRect& bounds,
323 : RunType runs[kRectRegionRuns])
324 : {
325 0 : runs[0] = bounds.fTop;
326 0 : runs[1] = bounds.fBottom;
327 0 : runs[2] = bounds.fLeft;
328 0 : runs[3] = bounds.fRight;
329 0 : runs[4] = kRunTypeSentinel;
330 0 : runs[5] = kRunTypeSentinel;
331 0 : }
332 :
333 0 : static SkRegion::RunType* find_scanline(const SkRegion::RunType runs[], int y)
334 : {
335 0 : SkASSERT(y >= runs[0]); // if this fails, we didn't do a quick check on the boudns
336 :
337 0 : runs += 1; // skip top-Y
338 0 : for (;;)
339 : {
340 0 : if (runs[0] == SkRegion::kRunTypeSentinel)
341 : break;
342 0 : if (y < runs[0])
343 0 : return (SkRegion::RunType*)&runs[1];
344 0 : runs = skip_scanline(runs + 1); // skip the Y value before calling
345 : }
346 0 : return NULL;
347 : }
348 :
349 0 : bool SkRegion::contains(int32_t x, int32_t y) const
350 : {
351 0 : if (!fBounds.contains(x, y))
352 0 : return false;
353 :
354 0 : if (this->isRect())
355 0 : return true;
356 :
357 0 : SkASSERT(this->isComplex());
358 0 : const RunType* runs = find_scanline(fRunHead->readonly_runs(), y);
359 :
360 0 : if (runs)
361 0 : { for (;;)
362 0 : { if (x < runs[0])
363 : break;
364 0 : if (x < runs[1])
365 0 : return true;
366 0 : runs += 2;
367 : }
368 : }
369 0 : return false;
370 : }
371 :
372 0 : bool SkRegion::contains(const SkIRect& r) const
373 : {
374 0 : SkRegion tmp(r);
375 :
376 0 : return this->contains(tmp);
377 : }
378 :
379 0 : bool SkRegion::contains(const SkRegion& rgn) const
380 : {
381 0 : if (this->isEmpty() || rgn.isEmpty() || !fBounds.contains(rgn.fBounds))
382 0 : return false;
383 :
384 0 : if (this->isRect())
385 0 : return true;
386 :
387 0 : SkRegion tmp;
388 :
389 0 : tmp.op(*this, rgn, kUnion_Op);
390 0 : return tmp == *this;
391 : }
392 :
393 0 : const SkRegion::RunType* SkRegion::getRuns(RunType tmpStorage[], int* count) const
394 : {
395 0 : SkASSERT(tmpStorage && count);
396 0 : const RunType* runs = tmpStorage;
397 :
398 0 : if (this->isEmpty())
399 : {
400 0 : tmpStorage[0] = kRunTypeSentinel;
401 0 : *count = 1;
402 : }
403 0 : else if (this->isRect())
404 : {
405 0 : BuildRectRuns(fBounds, tmpStorage);
406 0 : *count = kRectRegionRuns;
407 : }
408 : else
409 : {
410 0 : *count = fRunHead->fRunCount;
411 0 : runs = fRunHead->readonly_runs();
412 : }
413 0 : return runs;
414 : }
415 :
416 : /////////////////////////////////////////////////////////////////////////////////////
417 :
418 0 : bool SkRegion::intersects(const SkIRect& r) const {
419 0 : if (this->isEmpty() || r.isEmpty()) {
420 0 : return false;
421 : }
422 :
423 0 : if (!SkIRect::Intersects(fBounds, r)) {
424 0 : return false;
425 : }
426 :
427 0 : if (this->isRect()) {
428 0 : return true;
429 : }
430 :
431 : // we are complex
432 0 : SkRegion tmp;
433 0 : return tmp.op(*this, r, kIntersect_Op);
434 : }
435 :
436 0 : bool SkRegion::intersects(const SkRegion& rgn) const {
437 0 : if (this->isEmpty() || rgn.isEmpty()) {
438 0 : return false;
439 : }
440 :
441 0 : if (!SkIRect::Intersects(fBounds, rgn.fBounds)) {
442 0 : return false;
443 : }
444 :
445 0 : if (this->isRect() && rgn.isRect()) {
446 0 : return true;
447 : }
448 :
449 : // one or both of us is complex
450 : // TODO: write a faster version that aborts as soon as we write the first
451 : // non-empty span, to avoid build the entire result
452 0 : SkRegion tmp;
453 0 : return tmp.op(*this, rgn, kIntersect_Op);
454 : }
455 :
456 : /////////////////////////////////////////////////////////////////////////////////////
457 :
458 0 : bool operator==(const SkRegion& a, const SkRegion& b) {
459 0 : SkDEBUGCODE(a.validate();)
460 0 : SkDEBUGCODE(b.validate();)
461 :
462 0 : if (&a == &b) {
463 0 : return true;
464 : }
465 0 : if (a.fBounds != b.fBounds) {
466 0 : return false;
467 : }
468 :
469 0 : const SkRegion::RunHead* ah = a.fRunHead;
470 0 : const SkRegion::RunHead* bh = b.fRunHead;
471 :
472 : // this catches empties and rects being equal
473 0 : if (ah == bh) {
474 0 : return true;
475 : }
476 : // now we insist that both are complex (but different ptrs)
477 0 : if (!ah->isComplex() || !bh->isComplex()) {
478 0 : return false;
479 : }
480 : return ah->fRunCount == bh->fRunCount &&
481 0 : !memcmp(ah->readonly_runs(), bh->readonly_runs(),
482 0 : ah->fRunCount * sizeof(SkRegion::RunType));
483 : }
484 :
485 0 : void SkRegion::translate(int dx, int dy, SkRegion* dst) const {
486 0 : SkDEBUGCODE(this->validate();)
487 :
488 0 : if (NULL == dst) {
489 0 : return;
490 : }
491 0 : if (this->isEmpty()) {
492 0 : dst->setEmpty();
493 0 : } else if (this->isRect()) {
494 : dst->setRect(fBounds.fLeft + dx, fBounds.fTop + dy,
495 0 : fBounds.fRight + dx, fBounds.fBottom + dy);
496 : } else {
497 0 : if (this == dst) {
498 0 : dst->fRunHead = dst->fRunHead->ensureWritable();
499 : } else {
500 0 : SkRegion tmp;
501 0 : tmp.allocateRuns(fRunHead->fRunCount);
502 0 : tmp.fBounds = fBounds;
503 0 : dst->swap(tmp);
504 : }
505 :
506 0 : dst->fBounds.offset(dx, dy);
507 :
508 0 : const RunType* sruns = fRunHead->readonly_runs();
509 0 : RunType* druns = dst->fRunHead->writable_runs();
510 :
511 0 : *druns++ = (SkRegion::RunType)(*sruns++ + dy); // top
512 0 : for (;;) {
513 0 : int bottom = *sruns++;
514 0 : if (bottom == kRunTypeSentinel) {
515 : break;
516 : }
517 0 : *druns++ = (SkRegion::RunType)(bottom + dy); // bottom;
518 0 : for (;;) {
519 0 : int x = *sruns++;
520 0 : if (x == kRunTypeSentinel) {
521 : break;
522 : }
523 0 : *druns++ = (SkRegion::RunType)(x + dx);
524 0 : *druns++ = (SkRegion::RunType)(*sruns++ + dx);
525 : }
526 0 : *druns++ = kRunTypeSentinel; // x sentinel
527 : }
528 0 : *druns++ = kRunTypeSentinel; // y sentinel
529 :
530 0 : SkASSERT(sruns - fRunHead->readonly_runs() == fRunHead->fRunCount);
531 0 : SkASSERT(druns - dst->fRunHead->readonly_runs() == dst->fRunHead->fRunCount);
532 : }
533 :
534 0 : SkDEBUGCODE(this->validate();)
535 : }
536 :
537 : ///////////////////////////////////////////////////////////////////////////////
538 :
539 0 : bool SkRegion::setRects(const SkIRect rects[], int count) {
540 0 : if (0 == count) {
541 0 : this->setEmpty();
542 : } else {
543 0 : this->setRect(rects[0]);
544 0 : for (int i = 1; i < count; i++) {
545 0 : this->op(rects[i], kUnion_Op);
546 : }
547 : }
548 0 : return !this->isEmpty();
549 : }
550 :
551 : ///////////////////////////////////////////////////////////////////////////////
552 :
553 : #if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized
554 : #pragma warning ( push )
555 : #pragma warning ( disable : 4701 )
556 : #endif
557 :
558 : #ifdef SK_DEBUG
559 0 : static void assert_valid_pair(int left, int rite)
560 : {
561 0 : SkASSERT(left == SkRegion::kRunTypeSentinel || left < rite);
562 0 : }
563 : #else
564 : #define assert_valid_pair(left, rite)
565 : #endif
566 :
567 : struct spanRec {
568 : const SkRegion::RunType* fA_runs;
569 : const SkRegion::RunType* fB_runs;
570 : int fA_left, fA_rite, fB_left, fB_rite;
571 : int fLeft, fRite, fInside;
572 :
573 0 : void init(const SkRegion::RunType a_runs[], const SkRegion::RunType b_runs[])
574 : {
575 0 : fA_left = *a_runs++;
576 0 : fA_rite = *a_runs++;
577 0 : fB_left = *b_runs++;
578 0 : fB_rite = *b_runs++;
579 :
580 0 : fA_runs = a_runs;
581 0 : fB_runs = b_runs;
582 0 : }
583 :
584 0 : bool done() const
585 : {
586 : SkASSERT(fA_left <= SkRegion::kRunTypeSentinel);
587 : SkASSERT(fB_left <= SkRegion::kRunTypeSentinel);
588 0 : return fA_left == SkRegion::kRunTypeSentinel && fB_left == SkRegion::kRunTypeSentinel;
589 : }
590 :
591 0 : void next()
592 : {
593 0 : assert_valid_pair(fA_left, fA_rite);
594 0 : assert_valid_pair(fB_left, fB_rite);
595 :
596 0 : int inside, left, rite SK_INIT_TO_AVOID_WARNING;
597 0 : bool a_flush = false;
598 0 : bool b_flush = false;
599 :
600 0 : int a_left = fA_left;
601 0 : int a_rite = fA_rite;
602 0 : int b_left = fB_left;
603 0 : int b_rite = fB_rite;
604 :
605 0 : if (a_left < b_left)
606 : {
607 0 : inside = 1;
608 0 : left = a_left;
609 0 : if (a_rite <= b_left) // [...] <...>
610 : {
611 0 : rite = a_rite;
612 0 : a_flush = true;
613 : }
614 : else // [...<..]...> or [...<...>...]
615 0 : rite = a_left = b_left;
616 : }
617 0 : else if (b_left < a_left)
618 : {
619 0 : inside = 2;
620 0 : left = b_left;
621 0 : if (b_rite <= a_left) // [...] <...>
622 : {
623 0 : rite = b_rite;
624 0 : b_flush = true;
625 : }
626 : else // [...<..]...> or [...<...>...]
627 0 : rite = b_left = a_left;
628 : }
629 : else // a_left == b_left
630 : {
631 0 : inside = 3;
632 0 : left = a_left; // or b_left
633 0 : if (a_rite <= b_rite)
634 : {
635 0 : rite = b_left = a_rite;
636 0 : a_flush = true;
637 : }
638 0 : if (b_rite <= a_rite)
639 : {
640 0 : rite = a_left = b_rite;
641 0 : b_flush = true;
642 : }
643 : }
644 :
645 0 : if (a_flush)
646 : {
647 0 : a_left = *fA_runs++;
648 0 : a_rite = *fA_runs++;
649 : }
650 0 : if (b_flush)
651 : {
652 0 : b_left = *fB_runs++;
653 0 : b_rite = *fB_runs++;
654 : }
655 :
656 0 : SkASSERT(left <= rite);
657 :
658 : // now update our state
659 0 : fA_left = a_left;
660 0 : fA_rite = a_rite;
661 0 : fB_left = b_left;
662 0 : fB_rite = b_rite;
663 :
664 0 : fLeft = left;
665 0 : fRite = rite;
666 0 : fInside = inside;
667 0 : }
668 : };
669 :
670 0 : static SkRegion::RunType* operate_on_span(const SkRegion::RunType a_runs[],
671 : const SkRegion::RunType b_runs[],
672 : SkRegion::RunType dst[],
673 : int min, int max)
674 : {
675 : spanRec rec;
676 0 : bool firstInterval = true;
677 :
678 0 : rec.init(a_runs, b_runs);
679 :
680 0 : while (!rec.done())
681 : {
682 0 : rec.next();
683 :
684 0 : int left = rec.fLeft;
685 0 : int rite = rec.fRite;
686 :
687 : // add left,rite to our dst buffer (checking for coincidence
688 0 : if ((unsigned)(rec.fInside - min) <= (unsigned)(max - min) &&
689 : left < rite) // skip if equal
690 : {
691 0 : if (firstInterval || dst[-1] < left)
692 : {
693 0 : *dst++ = (SkRegion::RunType)(left);
694 0 : *dst++ = (SkRegion::RunType)(rite);
695 0 : firstInterval = false;
696 : }
697 : else // update the right edge
698 0 : dst[-1] = (SkRegion::RunType)(rite);
699 : }
700 : }
701 :
702 0 : *dst++ = SkRegion::kRunTypeSentinel;
703 0 : return dst;
704 : }
705 :
706 : #if defined _WIN32 && _MSC_VER >= 1300
707 : #pragma warning ( pop )
708 : #endif
709 :
710 : static const struct {
711 : uint8_t fMin;
712 : uint8_t fMax;
713 : } gOpMinMax[] = {
714 : { 1, 1 }, // Difference
715 : { 3, 3 }, // Intersection
716 : { 1, 3 }, // Union
717 : { 1, 2 } // XOR
718 : };
719 :
720 : class RgnOper {
721 : public:
722 0 : RgnOper(int top, SkRegion::RunType dst[], SkRegion::Op op)
723 : {
724 : // need to ensure that the op enum lines up with our minmax array
725 : SkASSERT(SkRegion::kDifference_Op == 0);
726 : SkASSERT(SkRegion::kIntersect_Op == 1);
727 : SkASSERT(SkRegion::kUnion_Op == 2);
728 : SkASSERT(SkRegion::kXOR_Op == 3);
729 0 : SkASSERT((unsigned)op <= 3);
730 :
731 0 : fStartDst = dst;
732 0 : fPrevDst = dst + 1;
733 0 : fPrevLen = 0; // will never match a length from operate_on_span
734 0 : fTop = (SkRegion::RunType)(top); // just a first guess, we might update this
735 :
736 0 : fMin = gOpMinMax[op].fMin;
737 0 : fMax = gOpMinMax[op].fMax;
738 0 : }
739 :
740 0 : void addSpan(int bottom, const SkRegion::RunType a_runs[], const SkRegion::RunType b_runs[])
741 : {
742 0 : SkRegion::RunType* start = fPrevDst + fPrevLen + 1; // skip X values and slot for the next Y
743 0 : SkRegion::RunType* stop = operate_on_span(a_runs, b_runs, start, fMin, fMax);
744 0 : size_t len = stop - start;
745 :
746 0 : if (fPrevLen == len && !memcmp(fPrevDst, start, len * sizeof(SkRegion::RunType))) // update Y value
747 0 : fPrevDst[-1] = (SkRegion::RunType)(bottom);
748 : else // accept the new span
749 : {
750 0 : if (len == 1 && fPrevLen == 0) {
751 0 : fTop = (SkRegion::RunType)(bottom); // just update our bottom
752 : } else {
753 0 : start[-1] = (SkRegion::RunType)(bottom);
754 0 : fPrevDst = start;
755 0 : fPrevLen = len;
756 : }
757 : }
758 0 : }
759 :
760 0 : int flush()
761 : {
762 0 : fStartDst[0] = fTop;
763 0 : fPrevDst[fPrevLen] = SkRegion::kRunTypeSentinel;
764 0 : return (int)(fPrevDst - fStartDst + fPrevLen + 1);
765 : }
766 :
767 : uint8_t fMin, fMax;
768 :
769 : private:
770 : SkRegion::RunType* fStartDst;
771 : SkRegion::RunType* fPrevDst;
772 : size_t fPrevLen;
773 : SkRegion::RunType fTop;
774 : };
775 :
776 0 : static int operate(const SkRegion::RunType a_runs[],
777 : const SkRegion::RunType b_runs[],
778 : SkRegion::RunType dst[],
779 : SkRegion::Op op) {
780 : const SkRegion::RunType gSentinel[] = {
781 : SkRegion::kRunTypeSentinel,
782 : // just need a 2nd value, since spanRec.init() reads 2 values, even
783 : // though if the first value is the sentinel, it ignores the 2nd value.
784 : // w/o the 2nd value here, we might read uninitialized memory.
785 : 0,
786 0 : };
787 :
788 0 : int a_top = *a_runs++;
789 0 : int a_bot = *a_runs++;
790 0 : int b_top = *b_runs++;
791 0 : int b_bot = *b_runs++;
792 :
793 0 : assert_sentinel(a_top, false);
794 0 : assert_sentinel(a_bot, false);
795 0 : assert_sentinel(b_top, false);
796 0 : assert_sentinel(b_bot, false);
797 :
798 0 : RgnOper oper(SkMin32(a_top, b_top), dst, op);
799 :
800 0 : bool firstInterval = true;
801 0 : int prevBot = SkRegion::kRunTypeSentinel; // so we fail the first test
802 :
803 0 : while (a_bot < SkRegion::kRunTypeSentinel ||
804 : b_bot < SkRegion::kRunTypeSentinel) {
805 0 : int top, bot SK_INIT_TO_AVOID_WARNING;
806 0 : const SkRegion::RunType* run0 = gSentinel;
807 0 : const SkRegion::RunType* run1 = gSentinel;
808 0 : bool a_flush = false;
809 0 : bool b_flush = false;
810 :
811 0 : if (a_top < b_top) {
812 0 : top = a_top;
813 0 : run0 = a_runs;
814 0 : if (a_bot <= b_top) { // [...] <...>
815 0 : bot = a_bot;
816 0 : a_flush = true;
817 : } else { // [...<..]...> or [...<...>...]
818 0 : bot = a_top = b_top;
819 : }
820 0 : } else if (b_top < a_top) {
821 0 : top = b_top;
822 0 : run1 = b_runs;
823 0 : if (b_bot <= a_top) { // [...] <...>
824 0 : bot = b_bot;
825 0 : b_flush = true;
826 : } else { // [...<..]...> or [...<...>...]
827 0 : bot = b_top = a_top;
828 : }
829 : } else { // a_top == b_top
830 0 : top = a_top; // or b_top
831 0 : run0 = a_runs;
832 0 : run1 = b_runs;
833 0 : if (a_bot <= b_bot) {
834 0 : bot = b_top = a_bot;
835 0 : a_flush = true;
836 : }
837 0 : if (b_bot <= a_bot) {
838 0 : bot = a_top = b_bot;
839 0 : b_flush = true;
840 : }
841 : }
842 :
843 0 : if (top > prevBot) {
844 0 : oper.addSpan(top, gSentinel, gSentinel);
845 : }
846 0 : oper.addSpan(bot, run0, run1);
847 0 : firstInterval = false;
848 :
849 0 : if (a_flush) {
850 0 : a_runs = skip_scanline(a_runs);
851 0 : a_top = a_bot;
852 0 : a_bot = *a_runs++;
853 0 : if (a_bot == SkRegion::kRunTypeSentinel) {
854 0 : a_top = a_bot;
855 : }
856 : }
857 0 : if (b_flush) {
858 0 : b_runs = skip_scanline(b_runs);
859 0 : b_top = b_bot;
860 0 : b_bot = *b_runs++;
861 0 : if (b_bot == SkRegion::kRunTypeSentinel) {
862 0 : b_top = b_bot;
863 : }
864 : }
865 :
866 0 : prevBot = bot;
867 : }
868 0 : return oper.flush();
869 : }
870 :
871 : ///////////////////////////////////////////////////////////////////////////////
872 :
873 : /* Given count RunTypes in a complex region, return the worst case number of
874 : logical intervals that represents (i.e. number of rects that would be
875 : returned from the iterator).
876 :
877 : We could just return count/2, since there must be at least 2 values per
878 : interval, but we can first trim off the const overhead of the initial TOP
879 : value, plus the final BOTTOM + 2 sentinels.
880 : */
881 0 : static int count_to_intervals(int count) {
882 0 : SkASSERT(count >= 6); // a single rect is 6 values
883 0 : return (count - 4) >> 1;
884 : }
885 :
886 : /* Given a number of intervals, what is the worst case representation of that
887 : many intervals?
888 :
889 : Worst case (from a storage perspective), is a vertical stack of single
890 : intervals: TOP + N * (BOTTOM LEFT RIGHT SENTINEL) + SENTINEL
891 : */
892 0 : static int intervals_to_count(int intervals) {
893 0 : return 1 + intervals * 4 + 1;
894 : }
895 :
896 : /* Given the counts of RunTypes in two regions, return the worst-case number
897 : of RunTypes need to store the result after a region-op.
898 : */
899 0 : static int compute_worst_case_count(int a_count, int b_count) {
900 0 : int a_intervals = count_to_intervals(a_count);
901 0 : int b_intervals = count_to_intervals(b_count);
902 : // Our heuristic worst case is ai * (bi + 1) + bi * (ai + 1)
903 0 : int intervals = 2 * a_intervals * b_intervals + a_intervals + b_intervals;
904 : // convert back to number of RunType values
905 0 : return intervals_to_count(intervals);
906 : }
907 :
908 0 : bool SkRegion::op(const SkRegion& rgnaOrig, const SkRegion& rgnbOrig, Op op)
909 : {
910 0 : SkDEBUGCODE(this->validate();)
911 :
912 0 : SkASSERT((unsigned)op < kOpCount);
913 :
914 0 : if (kReplace_Op == op)
915 0 : return this->set(rgnbOrig);
916 :
917 : // swith to using pointers, so we can swap them as needed
918 0 : const SkRegion* rgna = &rgnaOrig;
919 0 : const SkRegion* rgnb = &rgnbOrig;
920 : // after this point, do not refer to rgnaOrig or rgnbOrig!!!
921 :
922 : // collaps difference and reverse-difference into just difference
923 0 : if (kReverseDifference_Op == op)
924 : {
925 0 : SkTSwap<const SkRegion*>(rgna, rgnb);
926 0 : op = kDifference_Op;
927 : }
928 :
929 : SkIRect bounds;
930 0 : bool a_empty = rgna->isEmpty();
931 0 : bool b_empty = rgnb->isEmpty();
932 0 : bool a_rect = rgna->isRect();
933 0 : bool b_rect = rgnb->isRect();
934 :
935 0 : switch (op) {
936 : case kDifference_Op:
937 0 : if (a_empty)
938 0 : return this->setEmpty();
939 0 : if (b_empty || !SkIRect::Intersects(rgna->fBounds, rgnb->fBounds))
940 0 : return this->setRegion(*rgna);
941 0 : break;
942 :
943 : case kIntersect_Op:
944 0 : if ((a_empty | b_empty)
945 0 : || !bounds.intersect(rgna->fBounds, rgnb->fBounds))
946 0 : return this->setEmpty();
947 0 : if (a_rect & b_rect)
948 0 : return this->setRect(bounds);
949 0 : break;
950 :
951 : case kUnion_Op:
952 0 : if (a_empty)
953 0 : return this->setRegion(*rgnb);
954 0 : if (b_empty)
955 0 : return this->setRegion(*rgna);
956 0 : if (a_rect && rgna->fBounds.contains(rgnb->fBounds))
957 0 : return this->setRegion(*rgna);
958 0 : if (b_rect && rgnb->fBounds.contains(rgna->fBounds))
959 0 : return this->setRegion(*rgnb);
960 0 : break;
961 :
962 : case kXOR_Op:
963 0 : if (a_empty)
964 0 : return this->setRegion(*rgnb);
965 0 : if (b_empty)
966 0 : return this->setRegion(*rgna);
967 0 : break;
968 : default:
969 0 : SkDEBUGFAIL("unknown region op");
970 0 : return !this->isEmpty();
971 : }
972 :
973 : RunType tmpA[kRectRegionRuns];
974 : RunType tmpB[kRectRegionRuns];
975 :
976 : int a_count, b_count;
977 0 : const RunType* a_runs = rgna->getRuns(tmpA, &a_count);
978 0 : const RunType* b_runs = rgnb->getRuns(tmpB, &b_count);
979 :
980 0 : int dstCount = compute_worst_case_count(a_count, b_count);
981 0 : SkAutoSTMalloc<32, RunType> array(dstCount);
982 :
983 0 : int count = operate(a_runs, b_runs, array.get(), op);
984 0 : SkASSERT(count <= dstCount);
985 0 : return this->setRuns(array.get(), count);
986 : }
987 :
988 : //////////////////////////////////////////////////////////////////////////////////////////////////////////
989 :
990 : #include "SkBuffer.h"
991 :
992 0 : uint32_t SkRegion::flatten(void* storage) const {
993 0 : if (NULL == storage) {
994 0 : uint32_t size = sizeof(int32_t); // -1 (empty), 0 (rect), runCount
995 0 : if (!this->isEmpty()) {
996 0 : size += sizeof(fBounds);
997 0 : if (this->isComplex()) {
998 0 : size += fRunHead->fRunCount * sizeof(RunType);
999 : }
1000 : }
1001 0 : return size;
1002 : }
1003 :
1004 0 : SkWBuffer buffer(storage);
1005 :
1006 0 : if (this->isEmpty()) {
1007 0 : buffer.write32(-1);
1008 : } else {
1009 0 : bool isRect = this->isRect();
1010 :
1011 0 : buffer.write32(isRect ? 0 : fRunHead->fRunCount);
1012 0 : buffer.write(&fBounds, sizeof(fBounds));
1013 :
1014 0 : if (!isRect) {
1015 0 : buffer.write(fRunHead->readonly_runs(),
1016 0 : fRunHead->fRunCount * sizeof(RunType));
1017 : }
1018 : }
1019 0 : return buffer.pos();
1020 : }
1021 :
1022 0 : uint32_t SkRegion::unflatten(const void* storage) {
1023 0 : SkRBuffer buffer(storage);
1024 0 : SkRegion tmp;
1025 : int32_t count;
1026 :
1027 0 : count = buffer.readS32();
1028 0 : if (count >= 0) {
1029 0 : buffer.read(&tmp.fBounds, sizeof(tmp.fBounds));
1030 0 : if (count == 0) {
1031 0 : tmp.fRunHead = SkRegion_gRectRunHeadPtr;
1032 : } else {
1033 0 : tmp.allocateRuns(count);
1034 0 : buffer.read(tmp.fRunHead->writable_runs(), count * sizeof(RunType));
1035 : }
1036 : }
1037 0 : this->swap(tmp);
1038 0 : return buffer.pos();
1039 : }
1040 :
1041 : ///////////////////////////////////////////////////////////////////////////////
1042 :
1043 0 : const SkRegion& SkRegion::GetEmptyRegion() {
1044 0 : static SkRegion gEmpty;
1045 0 : return gEmpty;
1046 : }
1047 :
1048 : ///////////////////////////////////////////////////////////////////////////////
1049 :
1050 : #ifdef SK_DEBUG
1051 :
1052 0 : static const SkRegion::RunType* validate_line(const SkRegion::RunType run[], const SkIRect& bounds)
1053 : {
1054 : // *run is the bottom of the current span
1055 0 : SkASSERT(*run > bounds.fTop);
1056 0 : SkASSERT(*run <= bounds.fBottom);
1057 0 : run += 1;
1058 :
1059 : // check for empty span
1060 0 : if (*run != SkRegion::kRunTypeSentinel)
1061 : {
1062 0 : int prevRite = bounds.fLeft - 1;
1063 0 : do {
1064 0 : int left = *run++;
1065 0 : int rite = *run++;
1066 0 : SkASSERT(left < rite);
1067 0 : SkASSERT(left > prevRite);
1068 0 : SkASSERT(rite <= bounds.fRight);
1069 0 : prevRite = rite;
1070 : } while (*run < SkRegion::kRunTypeSentinel);
1071 : }
1072 0 : return run + 1; // skip sentinel
1073 : }
1074 :
1075 0 : void SkRegion::validate() const
1076 : {
1077 0 : if (this->isEmpty())
1078 : {
1079 : // check for explicit empty (the zero rect), so we can compare rects to know when
1080 : // two regions are equal (i.e. emptyRectA == emptyRectB)
1081 : // this is stricter than just asserting fBounds.isEmpty()
1082 0 : SkASSERT(fBounds.fLeft == 0 && fBounds.fTop == 0 && fBounds.fRight == 0 && fBounds.fBottom == 0);
1083 : }
1084 : else
1085 : {
1086 0 : SkASSERT(!fBounds.isEmpty());
1087 0 : if (!this->isRect())
1088 : {
1089 0 : SkASSERT(fRunHead->fRefCnt >= 1);
1090 0 : SkASSERT(fRunHead->fRunCount >= kRectRegionRuns);
1091 :
1092 0 : const RunType* run = fRunHead->readonly_runs();
1093 0 : const RunType* stop = run + fRunHead->fRunCount;
1094 :
1095 : // check that our bounds match our runs
1096 : {
1097 : SkIRect bounds;
1098 0 : bool isARect = ComputeRunBounds(run, stop - run, &bounds);
1099 0 : SkASSERT(!isARect);
1100 0 : SkASSERT(bounds == fBounds);
1101 : }
1102 :
1103 0 : SkASSERT(*run == fBounds.fTop);
1104 0 : run++;
1105 0 : do {
1106 0 : run = validate_line(run, fBounds);
1107 : } while (*run < kRunTypeSentinel);
1108 0 : SkASSERT(run + 1 == stop);
1109 : }
1110 : }
1111 0 : }
1112 :
1113 0 : void SkRegion::dump() const
1114 : {
1115 0 : if (this->isEmpty())
1116 0 : SkDebugf(" rgn: empty\n");
1117 : else
1118 : {
1119 0 : SkDebugf(" rgn: [%d %d %d %d]", fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
1120 0 : if (this->isComplex())
1121 : {
1122 0 : const RunType* runs = fRunHead->readonly_runs();
1123 0 : for (int i = 0; i < fRunHead->fRunCount; i++)
1124 0 : SkDebugf(" %d", runs[i]);
1125 : }
1126 0 : SkDebugf("\n");
1127 : }
1128 0 : }
1129 :
1130 : #endif
1131 :
1132 : /////////////////////////////////////////////////////////////////////////////////////
1133 :
1134 0 : SkRegion::Iterator::Iterator(const SkRegion& rgn) {
1135 0 : this->reset(rgn);
1136 0 : }
1137 :
1138 0 : bool SkRegion::Iterator::rewind() {
1139 0 : if (fRgn) {
1140 0 : this->reset(*fRgn);
1141 0 : return true;
1142 : }
1143 0 : return false;
1144 : }
1145 :
1146 0 : void SkRegion::Iterator::reset(const SkRegion& rgn) {
1147 0 : fRgn = &rgn;
1148 0 : if (rgn.isEmpty()) {
1149 0 : fDone = true;
1150 : } else {
1151 0 : fDone = false;
1152 0 : if (rgn.isRect()) {
1153 0 : fRect = rgn.fBounds;
1154 0 : fRuns = NULL;
1155 : } else {
1156 0 : fRuns = rgn.fRunHead->readonly_runs();
1157 0 : fRect.set(fRuns[2], fRuns[0], fRuns[3], fRuns[1]);
1158 0 : fRuns += 4;
1159 : }
1160 : }
1161 0 : }
1162 :
1163 0 : void SkRegion::Iterator::next() {
1164 0 : if (fDone) {
1165 0 : return;
1166 : }
1167 :
1168 0 : if (fRuns == NULL) { // rect case
1169 0 : fDone = true;
1170 0 : return;
1171 : }
1172 :
1173 0 : const RunType* runs = fRuns;
1174 :
1175 0 : if (runs[0] < kRunTypeSentinel) { // valid X value
1176 0 : fRect.fLeft = runs[0];
1177 0 : fRect.fRight = runs[1];
1178 0 : runs += 2;
1179 : } else { // we're at the end of a line
1180 0 : runs += 1;
1181 0 : if (runs[0] < kRunTypeSentinel) { // valid Y value
1182 0 : if (runs[1] == kRunTypeSentinel) { // empty line
1183 0 : fRect.fTop = runs[0];
1184 0 : runs += 2;
1185 : } else {
1186 0 : fRect.fTop = fRect.fBottom;
1187 : }
1188 :
1189 0 : fRect.fBottom = runs[0];
1190 0 : assert_sentinel(runs[1], false);
1191 0 : fRect.fLeft = runs[1];
1192 0 : fRect.fRight = runs[2];
1193 0 : runs += 3;
1194 : } else { // end of rgn
1195 0 : fDone = true;
1196 : }
1197 : }
1198 0 : fRuns = runs;
1199 : }
1200 :
1201 0 : SkRegion::Cliperator::Cliperator(const SkRegion& rgn, const SkIRect& clip)
1202 0 : : fIter(rgn), fClip(clip), fDone(true) {
1203 0 : const SkIRect& r = fIter.rect();
1204 :
1205 0 : while (!fIter.done()) {
1206 0 : if (r.fTop >= clip.fBottom) {
1207 0 : break;
1208 : }
1209 0 : if (fRect.intersect(clip, r)) {
1210 0 : fDone = false;
1211 0 : break;
1212 : }
1213 0 : fIter.next();
1214 : }
1215 0 : }
1216 :
1217 0 : void SkRegion::Cliperator::next() {
1218 0 : if (fDone) {
1219 0 : return;
1220 : }
1221 :
1222 0 : const SkIRect& r = fIter.rect();
1223 :
1224 0 : fDone = true;
1225 0 : fIter.next();
1226 0 : while (!fIter.done()) {
1227 0 : if (r.fTop >= fClip.fBottom) {
1228 0 : break;
1229 : }
1230 0 : if (fRect.intersect(fClip, r)) {
1231 0 : fDone = false;
1232 0 : break;
1233 : }
1234 0 : fIter.next();
1235 : }
1236 : }
1237 :
1238 : ///////////////////////////////////////////////////////////////////////////////
1239 :
1240 0 : static SkRegion::RunType* find_y(const SkRegion::RunType runs[], int y) {
1241 0 : int top = *runs++;
1242 0 : if (top <= y) {
1243 0 : for (;;) {
1244 0 : int bot = *runs++;
1245 0 : if (bot > y) {
1246 0 : if (bot == SkRegion::kRunTypeSentinel ||
1247 : *runs == SkRegion::kRunTypeSentinel) {
1248 : break;
1249 : }
1250 0 : return (SkRegion::RunType*)runs;
1251 : }
1252 0 : runs = skip_scanline(runs);
1253 : }
1254 : }
1255 0 : return NULL;
1256 : }
1257 :
1258 0 : SkRegion::Spanerator::Spanerator(const SkRegion& rgn, int y, int left,
1259 : int right) {
1260 0 : SkDEBUGCODE(rgn.validate();)
1261 :
1262 0 : const SkIRect& r = rgn.getBounds();
1263 :
1264 0 : fDone = true;
1265 0 : if (!rgn.isEmpty() && y >= r.fTop && y < r.fBottom &&
1266 : right > r.fLeft && left < r.fRight) {
1267 0 : if (rgn.isRect()) {
1268 0 : if (left < r.fLeft) {
1269 0 : left = r.fLeft;
1270 : }
1271 0 : if (right > r.fRight) {
1272 0 : right = r.fRight;
1273 : }
1274 0 : fLeft = left;
1275 0 : fRight = right;
1276 0 : fRuns = NULL; // means we're a rect, not a rgn
1277 0 : fDone = false;
1278 : } else {
1279 : const SkRegion::RunType* runs = find_y(
1280 0 : rgn.fRunHead->readonly_runs(), y);
1281 0 : if (runs) {
1282 0 : for (;;) {
1283 : // runs[0..1] is to the right of the span, so we're done
1284 0 : if (runs[0] >= right) {
1285 0 : break;
1286 : }
1287 : // runs[0..1] is to the left of the span, so continue
1288 0 : if (runs[1] <= left) {
1289 0 : runs += 2;
1290 0 : continue;
1291 : }
1292 : // runs[0..1] intersects the span
1293 0 : fRuns = runs;
1294 0 : fLeft = left;
1295 0 : fRight = right;
1296 0 : fDone = false;
1297 0 : break;
1298 : }
1299 : }
1300 : }
1301 : }
1302 0 : }
1303 :
1304 0 : bool SkRegion::Spanerator::next(int* left, int* right) {
1305 0 : if (fDone) {
1306 0 : return false;
1307 : }
1308 :
1309 0 : if (fRuns == NULL) { // we're a rect
1310 0 : fDone = true; // ok, now we're done
1311 0 : if (left) {
1312 0 : *left = fLeft;
1313 : }
1314 0 : if (right) {
1315 0 : *right = fRight;
1316 : }
1317 0 : return true; // this interval is legal
1318 : }
1319 :
1320 0 : const SkRegion::RunType* runs = fRuns;
1321 :
1322 0 : if (runs[0] >= fRight) {
1323 0 : fDone = true;
1324 0 : return false;
1325 : }
1326 :
1327 0 : SkASSERT(runs[1] > fLeft);
1328 :
1329 0 : if (left) {
1330 0 : *left = SkMax32(fLeft, runs[0]);
1331 : }
1332 0 : if (right) {
1333 0 : *right = SkMin32(fRight, runs[1]);
1334 : }
1335 0 : fRuns = runs + 2;
1336 0 : return true;
1337 : }
1338 :
1339 : ///////////////////////////////////////////////////////////////////////////////
1340 :
1341 : #ifdef SK_DEBUG
1342 :
1343 0 : bool SkRegion::debugSetRuns(const RunType runs[], int count) {
1344 : // we need to make a copy, since the real method may modify the array, and
1345 : // so it cannot be const.
1346 :
1347 0 : SkAutoTArray<RunType> storage(count);
1348 0 : memcpy(storage.get(), runs, count * sizeof(RunType));
1349 0 : return this->setRuns(storage.get(), count);
1350 : }
1351 :
1352 : #endif
|