| OLD | NEW |
| (Empty) | |
| 1 /* |
| 2 * Copyright (C) 2007 The Android Open Source Project |
| 3 * |
| 4 * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 * you may not use this file except in compliance with the License. |
| 6 * You may obtain a copy of the License at |
| 7 * |
| 8 * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 * |
| 10 * Unless required by applicable law or agreed to in writing, software |
| 11 * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 * See the License for the specific language governing permissions and |
| 14 * limitations under the License. |
| 15 */ |
| 16 |
| 17 #include "cc/android_region.h" |
| 18 |
| 19 #include <limits> |
| 20 |
| 21 #include "cc/android_region_helper.h" |
| 22 #include "third_party/skia/include/core/SkRect.h" |
| 23 #include "ui/gfx/rect.h" |
| 24 |
| 25 // ---------------------------------------------------------------------------- |
| 26 #define VALIDATE_REGIONS (false) |
| 27 #define VALIDATE_WITH_CORECG (false) |
| 28 // ---------------------------------------------------------------------------- |
| 29 |
| 30 #if VALIDATE_WITH_CORECG |
| 31 #include <core/SkRegion.h> |
| 32 #endif |
| 33 |
| 34 namespace android { |
| 35 // ---------------------------------------------------------------------------- |
| 36 |
| 37 enum { |
| 38 op_nand = region_operator<SkIRect, int>::op_nand, |
| 39 op_and = region_operator<SkIRect, int>::op_and, |
| 40 op_or = region_operator<SkIRect, int>::op_or, |
| 41 op_xor = region_operator<SkIRect, int>::op_xor |
| 42 }; |
| 43 |
| 44 // ---------------------------------------------------------------------------- |
| 45 |
| 46 Region::Region() |
| 47 : mBounds(SkIRect::MakeWH(0,0)) |
| 48 { |
| 49 } |
| 50 |
| 51 Region::Region(const Region& rhs) |
| 52 : mBounds(rhs.mBounds), mStorage(rhs.mStorage) |
| 53 { |
| 54 #if VALIDATE_REGIONS |
| 55 validate(rhs, "rhs copy-ctor"); |
| 56 #endif |
| 57 } |
| 58 |
| 59 Region::Region(const SkIRect& rhs) |
| 60 : mBounds(rhs) |
| 61 { |
| 62 } |
| 63 |
| 64 #if 0 |
| 65 Region::Region(const void* buffer) |
| 66 { |
| 67 status_t err = read(buffer); |
| 68 ALOGE_IF(err<0, "error %s reading Region from buffer", strerror(err)); |
| 69 } |
| 70 #endif |
| 71 |
| 72 Region::~Region() |
| 73 { |
| 74 } |
| 75 |
| 76 Region& Region::operator = (const Region& rhs) |
| 77 { |
| 78 #if VALIDATE_REGIONS |
| 79 validate(*this, "this->operator="); |
| 80 validate(rhs, "rhs.operator="); |
| 81 #endif |
| 82 mBounds = rhs.mBounds; |
| 83 mStorage = rhs.mStorage; |
| 84 return *this; |
| 85 } |
| 86 |
| 87 Region& Region::makeBoundsSelf() |
| 88 { |
| 89 mStorage.clear(); |
| 90 return *this; |
| 91 } |
| 92 |
| 93 void Region::clear() |
| 94 { |
| 95 mBounds.setEmpty(); |
| 96 mStorage.clear(); |
| 97 } |
| 98 |
| 99 void Region::set(const SkIRect& r) |
| 100 { |
| 101 mBounds = r; |
| 102 mStorage.clear(); |
| 103 } |
| 104 |
| 105 void Region::set(int w, int h) |
| 106 { |
| 107 mBounds = SkIRect::MakeWH(w, h); |
| 108 mStorage.clear(); |
| 109 } |
| 110 |
| 111 // ---------------------------------------------------------------------------- |
| 112 |
| 113 void Region::addRectUnchecked(int l, int t, int r, int b) |
| 114 { |
| 115 mStorage.push_back(SkIRect::MakeLTRB(l,t,r,b)); |
| 116 #if VALIDATE_REGIONS |
| 117 validate(*this, "addRectUnchecked"); |
| 118 #endif |
| 119 } |
| 120 |
| 121 // ---------------------------------------------------------------------------- |
| 122 |
| 123 Region& Region::orSelf(const SkIRect& r) { |
| 124 return operationSelf(r, op_or); |
| 125 } |
| 126 Region& Region::xorSelf(const SkIRect& r) { |
| 127 return operationSelf(r, op_xor); |
| 128 } |
| 129 Region& Region::andSelf(const SkIRect& r) { |
| 130 return operationSelf(r, op_and); |
| 131 } |
| 132 Region& Region::subtractSelf(const SkIRect& r) { |
| 133 return operationSelf(r, op_nand); |
| 134 } |
| 135 Region& Region::operationSelf(const SkIRect& r, int op) { |
| 136 Region lhs(*this); |
| 137 boolean_operation(op, *this, lhs, r); |
| 138 return *this; |
| 139 } |
| 140 |
| 141 // ---------------------------------------------------------------------------- |
| 142 |
| 143 Region& Region::orSelf(const Region& rhs) { |
| 144 return operationSelf(rhs, op_or); |
| 145 } |
| 146 Region& Region::xorSelf(const Region& rhs) { |
| 147 return operationSelf(rhs, op_xor); |
| 148 } |
| 149 Region& Region::andSelf(const Region& rhs) { |
| 150 return operationSelf(rhs, op_and); |
| 151 } |
| 152 Region& Region::subtractSelf(const Region& rhs) { |
| 153 return operationSelf(rhs, op_nand); |
| 154 } |
| 155 Region& Region::operationSelf(const Region& rhs, int op) { |
| 156 Region lhs(*this); |
| 157 boolean_operation(op, *this, lhs, rhs); |
| 158 return *this; |
| 159 } |
| 160 |
| 161 Region& Region::translateSelf(int x, int y) { |
| 162 if (x|y) translate(*this, x, y); |
| 163 return *this; |
| 164 } |
| 165 |
| 166 // ---------------------------------------------------------------------------- |
| 167 |
| 168 const Region Region::merge(const SkIRect& rhs) const { |
| 169 return operation(rhs, op_or); |
| 170 } |
| 171 const Region Region::mergeExclusive(const SkIRect& rhs) const { |
| 172 return operation(rhs, op_xor); |
| 173 } |
| 174 const Region Region::intersect(const SkIRect& rhs) const { |
| 175 return operation(rhs, op_and); |
| 176 } |
| 177 const Region Region::subtract(const SkIRect& rhs) const { |
| 178 return operation(rhs, op_nand); |
| 179 } |
| 180 const Region Region::operation(const SkIRect& rhs, int op) const { |
| 181 Region result; |
| 182 boolean_operation(op, result, *this, rhs); |
| 183 return result; |
| 184 } |
| 185 |
| 186 // ---------------------------------------------------------------------------- |
| 187 |
| 188 const Region Region::merge(const Region& rhs) const { |
| 189 return operation(rhs, op_or); |
| 190 } |
| 191 const Region Region::mergeExclusive(const Region& rhs) const { |
| 192 return operation(rhs, op_xor); |
| 193 } |
| 194 const Region Region::intersect(const Region& rhs) const { |
| 195 return operation(rhs, op_and); |
| 196 } |
| 197 const Region Region::subtract(const Region& rhs) const { |
| 198 return operation(rhs, op_nand); |
| 199 } |
| 200 const Region Region::operation(const Region& rhs, int op) const { |
| 201 Region result; |
| 202 boolean_operation(op, result, *this, rhs); |
| 203 return result; |
| 204 } |
| 205 |
| 206 const Region Region::translate(int x, int y) const { |
| 207 Region result; |
| 208 translate(result, *this, x, y); |
| 209 return result; |
| 210 } |
| 211 |
| 212 // ---------------------------------------------------------------------------- |
| 213 |
| 214 Region& Region::orSelf(const Region& rhs, int dx, int dy) { |
| 215 return operationSelf(rhs, dx, dy, op_or); |
| 216 } |
| 217 Region& Region::xorSelf(const Region& rhs, int dx, int dy) { |
| 218 return operationSelf(rhs, dx, dy, op_xor); |
| 219 } |
| 220 Region& Region::andSelf(const Region& rhs, int dx, int dy) { |
| 221 return operationSelf(rhs, dx, dy, op_and); |
| 222 } |
| 223 Region& Region::subtractSelf(const Region& rhs, int dx, int dy) { |
| 224 return operationSelf(rhs, dx, dy, op_nand); |
| 225 } |
| 226 Region& Region::operationSelf(const Region& rhs, int dx, int dy, int op) { |
| 227 Region lhs(*this); |
| 228 boolean_operation(op, *this, lhs, rhs, dx, dy); |
| 229 return *this; |
| 230 } |
| 231 |
| 232 // ---------------------------------------------------------------------------- |
| 233 |
| 234 const Region Region::merge(const Region& rhs, int dx, int dy) const { |
| 235 return operation(rhs, dx, dy, op_or); |
| 236 } |
| 237 const Region Region::mergeExclusive(const Region& rhs, int dx, int dy) const { |
| 238 return operation(rhs, dx, dy, op_xor); |
| 239 } |
| 240 const Region Region::intersect(const Region& rhs, int dx, int dy) const { |
| 241 return operation(rhs, dx, dy, op_and); |
| 242 } |
| 243 const Region Region::subtract(const Region& rhs, int dx, int dy) const { |
| 244 return operation(rhs, dx, dy, op_nand); |
| 245 } |
| 246 const Region Region::operation(const Region& rhs, int dx, int dy, int op) const
{ |
| 247 Region result; |
| 248 boolean_operation(op, result, *this, rhs, dx, dy); |
| 249 return result; |
| 250 } |
| 251 |
| 252 // ---------------------------------------------------------------------------- |
| 253 |
| 254 // This is our region rasterizer, which merges rects and spans together |
| 255 // to obtain an optimal region. |
| 256 class Region::rasterizer : public region_operator<SkIRect, int>::region_rasteriz
er |
| 257 { |
| 258 SkIRect& bounds; |
| 259 std::vector<SkIRect>& storage; |
| 260 SkIRect* head; |
| 261 SkIRect* tail; |
| 262 std::vector<SkIRect> span; |
| 263 SkIRect* cur; |
| 264 public: |
| 265 rasterizer(Region& reg) |
| 266 : bounds(reg.mBounds), storage(reg.mStorage), head(), tail(), cur() { |
| 267 bounds.fTop = bounds.fBottom = 0; |
| 268 bounds.fLeft = INT_MAX; |
| 269 bounds.fRight = INT_MIN; |
| 270 storage.clear(); |
| 271 } |
| 272 |
| 273 ~rasterizer() { |
| 274 if (span.size()) { |
| 275 flushSpan(); |
| 276 } |
| 277 if (storage.size()) { |
| 278 bounds.fTop = storage.front().fTop; |
| 279 bounds.fBottom = storage.back().fBottom; |
| 280 if (storage.size() == 1) { |
| 281 storage.clear(); |
| 282 } |
| 283 } else { |
| 284 bounds.fLeft = 0; |
| 285 bounds.fRight = 0; |
| 286 } |
| 287 } |
| 288 |
| 289 virtual void operator()(const SkIRect& rect) { |
| 290 //ALOGD(">>> %3d, %3d, %3d, %3d", |
| 291 // rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); |
| 292 if (span.size()) { |
| 293 if (cur->fTop != rect.fTop) { |
| 294 flushSpan(); |
| 295 } else if (cur->fRight == rect.fLeft) { |
| 296 cur->fRight = rect.fRight; |
| 297 return; |
| 298 } |
| 299 } |
| 300 span.push_back(rect); |
| 301 cur = &span.front() + (span.size() - 1); |
| 302 } |
| 303 private: |
| 304 template<typename T> |
| 305 static inline T min(T rhs, T lhs) { return rhs < lhs ? rhs : lhs; } |
| 306 template<typename T> |
| 307 static inline T max(T rhs, T lhs) { return rhs > lhs ? rhs : lhs; } |
| 308 void flushSpan() { |
| 309 bool merge = false; |
| 310 if (tail-head == ssize_t(span.size())) { |
| 311 SkIRect const* p = &span.front(); |
| 312 SkIRect const* q = head; |
| 313 if (p->fTop == q->fBottom) { |
| 314 merge = true; |
| 315 while (q != tail) { |
| 316 if ((p->fLeft != q->fLeft) || (p->fRight != q->fRight)) { |
| 317 merge = false; |
| 318 break; |
| 319 } |
| 320 p++, q++; |
| 321 } |
| 322 } |
| 323 } |
| 324 if (merge) { |
| 325 const int bottom = span[0].fBottom; |
| 326 SkIRect* r = head; |
| 327 while (r != tail) { |
| 328 r->fBottom = bottom; |
| 329 r++; |
| 330 } |
| 331 } else { |
| 332 bounds.fLeft = min(span.front().fLeft, bounds.fLeft); |
| 333 bounds.fRight = max(span.back().fRight, bounds.fRight); |
| 334 storage.insert(storage.end(), span.begin(), span.end()); |
| 335 tail = &storage.front() + storage.size(); |
| 336 head = tail - span.size(); |
| 337 } |
| 338 span.clear(); |
| 339 } |
| 340 }; |
| 341 |
| 342 bool Region::validate(const Region& reg, const char* name) |
| 343 { |
| 344 #if !VALIDATE_REGIONS |
| 345 return true; |
| 346 #else |
| 347 bool result = true; |
| 348 const_iterator cur = reg.begin(); |
| 349 const_iterator const tail = reg.end(); |
| 350 const_iterator prev = cur++; |
| 351 SkIRect b(*prev); |
| 352 while (cur != tail) { |
| 353 b.fLeft = b.fLeft < cur->fLeft ? b.fLeft : cur->fLeft; |
| 354 b.fTop = b.fTop < cur->fTop ? b.fTop : cur->fTop; |
| 355 b.fRight = b.fRight > cur->fRight ? b.fRight : cur->fRight; |
| 356 b.fBottom = b.fBottom > cur->fBottom ? b.fBottom : cur->fBottom; |
| 357 if (cur->fTop == prev->fTop) { |
| 358 if (cur->fBottom != prev->fBottom) { |
| 359 ALOGE("%s: invalid span %p", name, cur); |
| 360 result = false; |
| 361 } else if (cur->fLeft < prev->fRight) { |
| 362 ALOGE("%s: spans overlap horizontally prev=%p, cur=%p", |
| 363 name, prev, cur); |
| 364 result = false; |
| 365 } |
| 366 } else if (cur->fTop < prev->fBottom) { |
| 367 ALOGE("%s: spans overlap vertically prev=%p, cur=%p", |
| 368 name, prev, cur); |
| 369 result = false; |
| 370 } |
| 371 prev = cur; |
| 372 cur++; |
| 373 } |
| 374 if (b != reg.getBounds()) { |
| 375 result = false; |
| 376 ALOGE("%s: invalid bounds [%d,%d,%d,%d] vs. [%d,%d,%d,%d]", name, |
| 377 b.fLeft, b.fTop, b.fRight, b.fBottom, |
| 378 reg.getBounds().fLeft, reg.getBounds().fTop, |
| 379 reg.getBounds().fRight, reg.getBounds().fBottom); |
| 380 } |
| 381 if (result == false) { |
| 382 reg.dump(name); |
| 383 } |
| 384 return result; |
| 385 #endif |
| 386 } |
| 387 |
| 388 void Region::boolean_operation(int op, Region& dst, |
| 389 const Region& lhs, |
| 390 const Region& rhs, int dx, int dy) |
| 391 { |
| 392 #if VALIDATE_REGIONS |
| 393 validate(lhs, "boolean_operation (before): lhs"); |
| 394 validate(rhs, "boolean_operation (before): rhs"); |
| 395 validate(dst, "boolean_operation (before): dst"); |
| 396 #endif |
| 397 |
| 398 size_t lhs_count; |
| 399 SkIRect const * const lhs_rects = lhs.getArray(&lhs_count); |
| 400 |
| 401 size_t rhs_count; |
| 402 SkIRect const * const rhs_rects = rhs.getArray(&rhs_count); |
| 403 |
| 404 region_operator<SkIRect, int>::region lhs_region(lhs_rects, lhs_count); |
| 405 region_operator<SkIRect, int>::region rhs_region(rhs_rects, rhs_count, dx, d
y); |
| 406 region_operator<SkIRect, int> operation(op, lhs_region, rhs_region); |
| 407 { // scope for rasterizer (dtor has side effects) |
| 408 rasterizer r(dst); |
| 409 operation(r); |
| 410 } |
| 411 |
| 412 #if VALIDATE_REGIONS |
| 413 validate(lhs, "boolean_operation: lhs"); |
| 414 validate(rhs, "boolean_operation: rhs"); |
| 415 validate(dst, "boolean_operation: dst"); |
| 416 #endif |
| 417 |
| 418 #if VALIDATE_WITH_CORECG |
| 419 SkRegion sk_lhs; |
| 420 SkRegion sk_rhs; |
| 421 SkRegion sk_dst; |
| 422 |
| 423 for (size_t i=0 ; i<lhs_count ; i++) |
| 424 sk_lhs.op( |
| 425 lhs_rects[i].fLeft + dx, |
| 426 lhs_rects[i].fTop + dy, |
| 427 lhs_rects[i].fRight + dx, |
| 428 lhs_rects[i].fBottom + dy, |
| 429 SkRegion::kUnion_Op); |
| 430 |
| 431 for (size_t i=0 ; i<rhs_count ; i++) |
| 432 sk_rhs.op( |
| 433 rhs_rects[i].fLeft + dx, |
| 434 rhs_rects[i].fTop + dy, |
| 435 rhs_rects[i].fRight + dx, |
| 436 rhs_rects[i].fBottom + dy, |
| 437 SkRegion::kUnion_Op); |
| 438 |
| 439 const char* name = "---"; |
| 440 SkRegion::Op sk_op; |
| 441 switch (op) { |
| 442 case op_or: sk_op = SkRegion::kUnion_Op; name="OR"; break; |
| 443 case op_xor: sk_op = SkRegion::kUnion_XOR; name="XOR"; break; |
| 444 case op_and: sk_op = SkRegion::kIntersect_Op; name="AND"; break; |
| 445 case op_nand: sk_op = SkRegion::kDifference_Op; name="NAND"; break; |
| 446 } |
| 447 sk_dst.op(sk_lhs, sk_rhs, sk_op); |
| 448 |
| 449 if (sk_dst.isEmpty() && dst.isEmpty()) |
| 450 return; |
| 451 |
| 452 bool same = true; |
| 453 Region::const_iterator head = dst.begin(); |
| 454 Region::const_iterator const tail = dst.end(); |
| 455 SkRegion::Iterator it(sk_dst); |
| 456 while (!it.done()) { |
| 457 if (head != tail) { |
| 458 if ( |
| 459 head->fLeft != it.rect().fLeft || |
| 460 head->fTop != it.rect().fTop || |
| 461 head->fRight != it.rect().fRight || |
| 462 head->fBottom != it.rect().fBottom |
| 463 ) { |
| 464 same = false; |
| 465 break; |
| 466 } |
| 467 } else { |
| 468 same = false; |
| 469 break; |
| 470 } |
| 471 head++; |
| 472 it.next(); |
| 473 } |
| 474 |
| 475 if (head != tail) { |
| 476 same = false; |
| 477 } |
| 478 |
| 479 if(!same) { |
| 480 ALOGD("---\nregion boolean %s failed", name); |
| 481 lhs.dump("lhs"); |
| 482 rhs.dump("rhs"); |
| 483 dst.dump("dst"); |
| 484 ALOGD("should be"); |
| 485 SkRegion::Iterator it(sk_dst); |
| 486 while (!it.done()) { |
| 487 ALOGD(" [%3d, %3d, %3d, %3d]", |
| 488 it.rect().fLeft, |
| 489 it.rect().fTop, |
| 490 it.rect().fRight, |
| 491 it.rect().fBottom); |
| 492 it.next(); |
| 493 } |
| 494 } |
| 495 #endif |
| 496 } |
| 497 |
| 498 void Region::boolean_operation(int op, Region& dst, |
| 499 const Region& lhs, |
| 500 const SkIRect& rhs, int dx, int dy) |
| 501 { |
| 502 if (rhs.width() < 0 || rhs.height() < 0) { |
| 503 #if 0 |
| 504 ALOGE("Region::boolean_operation(op=%d) invalid SkIRect={%d,%d,%d,%d}", |
| 505 op, rhs.fLeft, rhs.fTop, rhs.fRight, rhs.fBottom); |
| 506 #endif |
| 507 return; |
| 508 } |
| 509 |
| 510 #if VALIDATE_WITH_CORECG || VALIDATE_REGIONS |
| 511 boolean_operation(op, dst, lhs, Region(rhs), dx, dy); |
| 512 #else |
| 513 size_t lhs_count; |
| 514 SkIRect const * const lhs_rects = lhs.getArray(&lhs_count); |
| 515 |
| 516 region_operator<SkIRect, int>::region lhs_region(lhs_rects, lhs_count); |
| 517 region_operator<SkIRect, int>::region rhs_region(&rhs, 1, dx, dy); |
| 518 region_operator<SkIRect, int> operation(op, lhs_region, rhs_region); |
| 519 { // scope for rasterizer (dtor has side effects) |
| 520 rasterizer r(dst); |
| 521 operation(r); |
| 522 } |
| 523 |
| 524 #endif |
| 525 } |
| 526 |
| 527 void Region::boolean_operation(int op, Region& dst, |
| 528 const Region& lhs, const Region& rhs) |
| 529 { |
| 530 boolean_operation(op, dst, lhs, rhs, 0, 0); |
| 531 } |
| 532 |
| 533 void Region::boolean_operation(int op, Region& dst, |
| 534 const Region& lhs, const SkIRect& rhs) |
| 535 { |
| 536 boolean_operation(op, dst, lhs, rhs, 0, 0); |
| 537 } |
| 538 |
| 539 void Region::translate(Region& reg, int dx, int dy) |
| 540 { |
| 541 if (!reg.isEmpty()) { |
| 542 #if VALIDATE_REGIONS |
| 543 validate(reg, "translate (before)"); |
| 544 #endif |
| 545 reg.mBounds.offset(dx, dy); |
| 546 size_t count = reg.mStorage.size(); |
| 547 SkIRect* rects = ®.mStorage.front(); |
| 548 while (count) { |
| 549 rects->offset(dx, dy); |
| 550 rects++; |
| 551 count--; |
| 552 } |
| 553 #if VALIDATE_REGIONS |
| 554 validate(reg, "translate (after)"); |
| 555 #endif |
| 556 } |
| 557 } |
| 558 |
| 559 void Region::translate(Region& dst, const Region& reg, int dx, int dy) |
| 560 { |
| 561 dst = reg; |
| 562 translate(dst, dx, dy); |
| 563 } |
| 564 |
| 565 // ---------------------------------------------------------------------------- |
| 566 #if 0 |
| 567 ssize_t Region::write(void* buffer, size_t size) const |
| 568 { |
| 569 #if VALIDATE_REGIONS |
| 570 validate(*this, "write(buffer)"); |
| 571 #endif |
| 572 const size_t count = mStorage.size(); |
| 573 const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(SkIRect); |
| 574 if (buffer != NULL) { |
| 575 if (sizeNeeded > size) return NO_MEMORY; |
| 576 int32_t* const p = static_cast<int32_t*>(buffer); |
| 577 *p = count; |
| 578 memcpy(p+1, &mBounds, sizeof(SkIRect)); |
| 579 if (count) { |
| 580 memcpy(p+5, &mStorage.front(), count*sizeof(SkIRect)); |
| 581 } |
| 582 } |
| 583 return ssize_t(sizeNeeded); |
| 584 } |
| 585 |
| 586 ssize_t Region::read(const void* buffer) |
| 587 { |
| 588 int32_t const* const p = static_cast<int32_t const*>(buffer); |
| 589 const size_t count = *p; |
| 590 memcpy(&mBounds, p+1, sizeof(SkIRect)); |
| 591 mStorage.clear(); |
| 592 if (count) { |
| 593 mStorage.insertAt(0, count); |
| 594 memcpy(&mStorage.front(), p+5, count*sizeof(SkIRect)); |
| 595 } |
| 596 #if VALIDATE_REGIONS |
| 597 validate(*this, "read(buffer)"); |
| 598 #endif |
| 599 return ssize_t(sizeof(int32_t) + (1+count)*sizeof(SkIRect)); |
| 600 } |
| 601 |
| 602 ssize_t Region::writeEmpty(void* buffer, size_t size) |
| 603 { |
| 604 const size_t sizeNeeded = sizeof(int32_t) + sizeof(SkIRect); |
| 605 if (sizeNeeded > size) return NO_MEMORY; |
| 606 int32_t* const p = static_cast<int32_t*>(buffer); |
| 607 memset(p, 0, sizeNeeded); |
| 608 return ssize_t(sizeNeeded); |
| 609 } |
| 610 |
| 611 bool Region::isEmpty(void* buffer) |
| 612 { |
| 613 int32_t const* const p = static_cast<int32_t const*>(buffer); |
| 614 SkIRect const* const b = reinterpret_cast<SkIRect const *>(p+1); |
| 615 return b->isEmpty(); |
| 616 } |
| 617 #endif |
| 618 // ---------------------------------------------------------------------------- |
| 619 |
| 620 Region::const_iterator Region::begin() const { |
| 621 return isRect() ? &mBounds : &mStorage.front(); |
| 622 } |
| 623 |
| 624 Region::const_iterator Region::end() const { |
| 625 if (isRect()) { |
| 626 if (isEmpty()) { |
| 627 return &mBounds; |
| 628 } else { |
| 629 return &mBounds + 1; |
| 630 } |
| 631 } else { |
| 632 return &mStorage.front() + mStorage.size(); |
| 633 } |
| 634 } |
| 635 |
| 636 SkIRect const* Region::getArray(size_t* count) const { |
| 637 const_iterator const b(begin()); |
| 638 const_iterator const e(end()); |
| 639 if (count) *count = e-b; |
| 640 return b; |
| 641 } |
| 642 |
| 643 size_t Region::getRects(std::vector<SkIRect>& rectList) const |
| 644 { |
| 645 rectList = mStorage; |
| 646 if (rectList.empty()) { |
| 647 rectList.clear(); |
| 648 rectList.push_back(mBounds); |
| 649 } |
| 650 return rectList.size(); |
| 651 } |
| 652 |
| 653 // ---------------------------------------------------------------------------- |
| 654 #if 0 |
| 655 void Region::dump(String8& out, const char* what, uint32_t flags) const |
| 656 { |
| 657 (void)flags; |
| 658 const_iterator head = begin(); |
| 659 const_iterator const tail = end(); |
| 660 |
| 661 size_t SIZE = 256; |
| 662 char buffer[SIZE]; |
| 663 |
| 664 snprintf(buffer, SIZE, " Region %s (this=%p, count=%d)\n", |
| 665 what, this, tail-head); |
| 666 out.append(buffer); |
| 667 while (head != tail) { |
| 668 snprintf(buffer, SIZE, " [%3d, %3d, %3d, %3d]\n", |
| 669 head->fLeft, head->fTop, head->fRight, head->fBottom); |
| 670 out.append(buffer); |
| 671 head++; |
| 672 } |
| 673 } |
| 674 |
| 675 void Region::dump(const char* what, uint32_t flags) const |
| 676 { |
| 677 (void)flags; |
| 678 const_iterator head = begin(); |
| 679 const_iterator const tail = end(); |
| 680 ALOGD(" Region %s (this=%p, count=%d)\n", what, this, tail-head); |
| 681 while (head != tail) { |
| 682 ALOGD(" [%3d, %3d, %3d, %3d]\n", |
| 683 head->fLeft, head->fTop, head->fRight, head->fBottom); |
| 684 head++; |
| 685 } |
| 686 } |
| 687 #endif |
| 688 // ---------------------------------------------------------------------------- |
| 689 |
| 690 }; // namespace android |
| OLD | NEW |