| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2007 The Android Open Source Project | 3 * Copyright 2007 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "SkPictureFlat.h" | 10 #include "SkPictureFlat.h" |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 >= kNumAAConcavePathsTol) | 250 >= kNumAAConcavePathsTol) |
| 251 *reason = "Too many anti-aliased concave paths."; | 251 *reason = "Too many anti-aliased concave paths."; |
| 252 else | 252 else |
| 253 *reason = "Unknown reason for GPU unsuitability."; | 253 *reason = "Unknown reason for GPU unsuitability."; |
| 254 } | 254 } |
| 255 return ret; | 255 return ret; |
| 256 } | 256 } |
| 257 | 257 |
| 258 /////////////////////////////////////////////////////////////////////////////// | 258 /////////////////////////////////////////////////////////////////////////////// |
| 259 | 259 |
| 260 // fRecord OK | |
| 261 SkPicture::SkPicture(SkScalar width, SkScalar height, | |
| 262 const SkPictureRecord& record, | |
| 263 bool deepCopyOps) | |
| 264 : fCullWidth(width) | |
| 265 , fCullHeight(height) | |
| 266 , fAnalysis() { | |
| 267 this->needsNewGenID(); | |
| 268 | |
| 269 SkPictInfo info; | |
| 270 this->createHeader(&info); | |
| 271 fData.reset(SkNEW_ARGS(SkPictureData, (record, info, deepCopyOps))); | |
| 272 } | |
| 273 | |
| 274 // Create an SkPictureData-backed SkPicture from an SkRecord. | |
| 275 // This for compatibility with serialization code only. This is not cheap. | |
| 276 SkPicture* SkPicture::Backport(const SkRecord& src, const SkRect& cullRect) { | |
| 277 SkPictureRecord rec(SkISize::Make(cullRect.width(), cullRect.height()), 0/*f
lags*/); | |
| 278 rec.beginRecording(); | |
| 279 SkRecordDraw(src, &rec, NULL/*bbh*/, NULL/*callback*/); | |
| 280 rec.endRecording(); | |
| 281 return SkNEW_ARGS(SkPicture, (cullRect.width(), cullRect.height(), rec, fals
e/*deepCopyOps*/)); | |
| 282 } | |
| 283 | |
| 284 // fRecord OK | |
| 285 SkPicture::~SkPicture() { | 260 SkPicture::~SkPicture() { |
| 286 this->callDeletionListeners(); | 261 this->callDeletionListeners(); |
| 287 } | 262 } |
| 288 | 263 |
| 289 // fRecord OK | |
| 290 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) cons
t { | 264 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) cons
t { |
| 291 fAccelData.reset(SkRef(data)); | 265 fAccelData.reset(SkRef(data)); |
| 292 } | 266 } |
| 293 | 267 |
| 294 // fRecord OK | |
| 295 const SkPicture::AccelData* SkPicture::EXPERIMENTAL_getAccelData( | 268 const SkPicture::AccelData* SkPicture::EXPERIMENTAL_getAccelData( |
| 296 SkPicture::AccelData::Key key) const { | 269 SkPicture::AccelData::Key key) const { |
| 297 if (fAccelData.get() && fAccelData->getKey() == key) { | 270 if (fAccelData.get() && fAccelData->getKey() == key) { |
| 298 return fAccelData.get(); | 271 return fAccelData.get(); |
| 299 } | 272 } |
| 300 return NULL; | 273 return NULL; |
| 301 } | 274 } |
| 302 | 275 |
| 303 // fRecord OK | |
| 304 SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() { | 276 SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() { |
| 305 static int32_t gNextID = 0; | 277 static int32_t gNextID = 0; |
| 306 | 278 |
| 307 int32_t id = sk_atomic_inc(&gNextID); | 279 int32_t id = sk_atomic_inc(&gNextID); |
| 308 if (id >= 1 << (8 * sizeof(Domain))) { | 280 if (id >= 1 << (8 * sizeof(Domain))) { |
| 309 SK_CRASH(); | 281 SK_CRASH(); |
| 310 } | 282 } |
| 311 | 283 |
| 312 return static_cast<Domain>(id); | 284 return static_cast<Domain>(id); |
| 313 } | 285 } |
| 314 | 286 |
| 315 /////////////////////////////////////////////////////////////////////////////// | 287 /////////////////////////////////////////////////////////////////////////////// |
| 316 | 288 |
| 317 // fRecord OK | |
| 318 void SkPicture::playback(SkCanvas* canvas, SkDrawPictureCallback* callback) cons
t { | 289 void SkPicture::playback(SkCanvas* canvas, SkDrawPictureCallback* callback) cons
t { |
| 319 SkASSERT(canvas); | 290 SkASSERT(canvas); |
| 320 SkASSERT(fData.get() || fRecord.get()); | |
| 321 | 291 |
| 322 if (fData.get()) { | 292 // If the query contains the whole picture, don't bother with the BBH. |
| 323 SkPicturePlayback playback(this); | 293 SkRect clipBounds = { 0, 0, 0, 0 }; |
| 324 playback.draw(canvas, callback); | 294 (void)canvas->getClipBounds(&clipBounds); |
| 325 } | 295 const bool useBBH = !clipBounds.contains(this->cullRect()); |
| 326 if (fRecord.get()) { | |
| 327 // If the query contains the whole picture, don't bother with the BBH. | |
| 328 SkRect clipBounds = { 0, 0, 0, 0 }; | |
| 329 (void)canvas->getClipBounds(&clipBounds); | |
| 330 const bool useBBH = !clipBounds.contains(this->cullRect()); | |
| 331 | 296 |
| 332 SkRecordDraw(*fRecord, canvas, useBBH ? fBBH.get() : NULL, callback); | 297 SkRecordDraw(*fRecord, canvas, useBBH ? fBBH.get() : NULL, callback); |
| 333 } | |
| 334 } | 298 } |
| 335 | 299 |
| 336 /////////////////////////////////////////////////////////////////////////////// | 300 /////////////////////////////////////////////////////////////////////////////// |
| 337 | 301 |
| 338 #include "SkStream.h" | 302 #include "SkStream.h" |
| 339 | 303 |
| 340 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' }; | 304 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' }; |
| 341 | 305 |
| 342 // fRecord OK | |
| 343 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) { | 306 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) { |
| 344 if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) { | 307 if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) { |
| 345 return false; | 308 return false; |
| 346 } | 309 } |
| 347 | 310 |
| 348 if (info.fVersion < MIN_PICTURE_VERSION || | 311 if (info.fVersion < MIN_PICTURE_VERSION || |
| 349 info.fVersion > CURRENT_PICTURE_VERSION) { | 312 info.fVersion > CURRENT_PICTURE_VERSION) { |
| 350 return false; | 313 return false; |
| 351 } | 314 } |
| 352 | 315 |
| 353 return true; | 316 return true; |
| 354 } | 317 } |
| 355 | 318 |
| 356 // fRecord OK | |
| 357 bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) { | 319 bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) { |
| 358 if (NULL == stream) { | 320 if (NULL == stream) { |
| 359 return false; | 321 return false; |
| 360 } | 322 } |
| 361 | 323 |
| 362 // Check magic bytes. | 324 // Check magic bytes. |
| 363 SkPictInfo info; | 325 SkPictInfo info; |
| 364 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); | 326 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); |
| 365 | 327 |
| 366 if (!stream->read(&info.fMagic, sizeof(kMagic))) { | 328 if (!stream->read(&info.fMagic, sizeof(kMagic))) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 390 if (!IsValidPictInfo(info)) { | 352 if (!IsValidPictInfo(info)) { |
| 391 return false; | 353 return false; |
| 392 } | 354 } |
| 393 | 355 |
| 394 if (pInfo != NULL) { | 356 if (pInfo != NULL) { |
| 395 *pInfo = info; | 357 *pInfo = info; |
| 396 } | 358 } |
| 397 return true; | 359 return true; |
| 398 } | 360 } |
| 399 | 361 |
| 400 // fRecord OK | |
| 401 bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo
) { | 362 bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo
) { |
| 402 // Check magic bytes. | 363 // Check magic bytes. |
| 403 SkPictInfo info; | 364 SkPictInfo info; |
| 404 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); | 365 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); |
| 405 | 366 |
| 406 if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) { | 367 if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) { |
| 407 return false; | 368 return false; |
| 408 } | 369 } |
| 409 | 370 |
| 410 info.fVersion = buffer->readUInt(); | 371 info.fVersion = buffer->readUInt(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 427 if (!IsValidPictInfo(info)) { | 388 if (!IsValidPictInfo(info)) { |
| 428 return false; | 389 return false; |
| 429 } | 390 } |
| 430 | 391 |
| 431 if (pInfo != NULL) { | 392 if (pInfo != NULL) { |
| 432 *pInfo = info; | 393 *pInfo = info; |
| 433 } | 394 } |
| 434 return true; | 395 return true; |
| 435 } | 396 } |
| 436 | 397 |
| 437 // fRecord OK | 398 SkPicture* SkPicture::Forwardport(const SkPictInfo& info, const SkPictureData* d
ata) { |
| 438 SkPicture::SkPicture(SkPictureData* data, SkScalar width, SkScalar height) | 399 if (!data) { |
| 439 : fData(data) | 400 return NULL; |
| 440 , fCullWidth(width) | 401 } |
| 441 , fCullHeight(height) | 402 SkPicturePlayback playback(data); |
| 442 , fAnalysis() { | 403 SkPictureRecorder r; |
| 443 this->needsNewGenID(); | 404 playback.draw(r.beginRecording(SkScalarCeilToInt(info.fCullRect.width()), |
| 405 SkScalarCeilToInt(info.fCullRect.height())), |
| 406 NULL/*no callback*/); |
| 407 return r.endRecording(); |
| 444 } | 408 } |
| 445 | 409 |
| 446 SkPicture* SkPicture::Forwardport(const SkPicture& src) { | 410 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro
c) { |
| 447 SkAutoTDelete<SkRecord> record(SkNEW(SkRecord)); | 411 SkPictInfo info; |
| 448 SkRecorder canvas(record.get(), src.cullRect().width(), src.cullRect().heigh
t()); | 412 if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) { |
| 449 src.playback(&canvas); | 413 return NULL; |
| 450 return SkNEW_ARGS(SkPicture, (src.cullRect().width(), src.cullRect().height(
), | 414 } |
| 451 record.detach(), NULL/*bbh*/)); | 415 SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromStream(stream, in
fo, proc)); |
| 416 return Forwardport(info, data); |
| 452 } | 417 } |
| 453 | 418 |
| 454 // fRecord OK | 419 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) { |
| 455 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro
c) { | |
| 456 SkPictInfo info; | 420 SkPictInfo info; |
| 457 | 421 if (!InternalOnly_BufferIsSKP(&buffer, &info) || !buffer.readBool()) { |
| 458 if (!InternalOnly_StreamIsSKP(stream, &info)) { | |
| 459 return NULL; | 422 return NULL; |
| 460 } | 423 } |
| 461 | 424 SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, in
fo)); |
| 462 // Check to see if there is a playback to recreate. | 425 return Forwardport(info, data); |
| 463 if (stream->readBool()) { | |
| 464 SkPictureData* data = SkPictureData::CreateFromStream(stream, info, proc
); | |
| 465 if (NULL == data) { | |
| 466 return NULL; | |
| 467 } | |
| 468 const SkPicture src(data, info.fCullRect.width(), info.fCullRect.height(
)); | |
| 469 return Forwardport(src); | |
| 470 } | |
| 471 | |
| 472 return NULL; | |
| 473 } | 426 } |
| 474 | 427 |
| 475 // fRecord OK | |
| 476 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) { | |
| 477 SkPictInfo info; | |
| 478 | |
| 479 if (!InternalOnly_BufferIsSKP(&buffer, &info)) { | |
| 480 return NULL; | |
| 481 } | |
| 482 | |
| 483 // Check to see if there is a playback to recreate. | |
| 484 if (buffer.readBool()) { | |
| 485 SkPictureData* data = SkPictureData::CreateFromBuffer(buffer, info); | |
| 486 if (NULL == data) { | |
| 487 return NULL; | |
| 488 } | |
| 489 const SkPicture src(data, info.fCullRect.width(), info.fCullRect.height(
)); | |
| 490 return Forwardport(src); | |
| 491 } | |
| 492 | |
| 493 return NULL; | |
| 494 } | |
| 495 | |
| 496 // fRecord OK | |
| 497 void SkPicture::createHeader(SkPictInfo* info) const { | 428 void SkPicture::createHeader(SkPictInfo* info) const { |
| 498 // Copy magic bytes at the beginning of the header | 429 // Copy magic bytes at the beginning of the header |
| 499 SkASSERT(sizeof(kMagic) == 8); | 430 SkASSERT(sizeof(kMagic) == 8); |
| 500 SkASSERT(sizeof(kMagic) == sizeof(info->fMagic)); | 431 SkASSERT(sizeof(kMagic) == sizeof(info->fMagic)); |
| 501 memcpy(info->fMagic, kMagic, sizeof(kMagic)); | 432 memcpy(info->fMagic, kMagic, sizeof(kMagic)); |
| 502 | 433 |
| 503 // Set picture info after magic bytes in the header | 434 // Set picture info after magic bytes in the header |
| 504 info->fVersion = CURRENT_PICTURE_VERSION; | 435 info->fVersion = CURRENT_PICTURE_VERSION; |
| 505 info->fCullRect = this->cullRect(); | 436 info->fCullRect = this->cullRect(); |
| 506 info->fFlags = SkPictInfo::kCrossProcess_Flag; | 437 info->fFlags = SkPictInfo::kCrossProcess_Flag; |
| 507 // TODO: remove this flag, since we're always float (now) | 438 // TODO: remove this flag, since we're always float (now) |
| 508 info->fFlags |= SkPictInfo::kScalarIsFloat_Flag; | 439 info->fFlags |= SkPictInfo::kScalarIsFloat_Flag; |
| 509 | 440 |
| 510 if (8 == sizeof(void*)) { | 441 if (8 == sizeof(void*)) { |
| 511 info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag; | 442 info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag; |
| 512 } | 443 } |
| 513 } | 444 } |
| 514 | 445 |
| 515 // fRecord OK | 446 // This for compatibility with serialization code only. This is not cheap. |
| 447 SkPictureData* SkPicture::Backport(const SkRecord& src, const SkPictInfo& info)
{ |
| 448 SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.hei
ght()), 0/*flags*/); |
| 449 rec.beginRecording(); |
| 450 SkRecordDraw(src, &rec, NULL/*bbh*/, NULL/*callback*/); |
| 451 rec.endRecording(); |
| 452 return SkNEW_ARGS(SkPictureData, (rec, info, false/*deep copy ops?*/)); |
| 453 } |
| 454 |
| 455 |
| 516 void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const { | 456 void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const { |
| 517 const SkPictureData* data = fData.get(); | |
| 518 | |
| 519 // If we're a new-format picture, backport to old format for serialization. | |
| 520 SkAutoTDelete<SkPicture> oldFormat; | |
| 521 if (NULL == data && fRecord.get()) { | |
| 522 oldFormat.reset(Backport(*fRecord, this->cullRect())); | |
| 523 data = oldFormat->fData.get(); | |
| 524 SkASSERT(data); | |
| 525 } | |
| 526 | |
| 527 SkPictInfo info; | 457 SkPictInfo info; |
| 528 this->createHeader(&info); | 458 this->createHeader(&info); |
| 529 SkASSERT(sizeof(SkPictInfo) == 32); | 459 SkAutoTDelete<SkPictureData> data(Backport(*fRecord, info)); |
| 460 |
| 530 stream->write(&info, sizeof(info)); | 461 stream->write(&info, sizeof(info)); |
| 531 | |
| 532 if (data) { | 462 if (data) { |
| 533 stream->writeBool(true); | 463 stream->writeBool(true); |
| 534 data->serialize(stream, encoder); | 464 data->serialize(stream, encoder); |
| 535 } else { | 465 } else { |
| 536 stream->writeBool(false); | 466 stream->writeBool(false); |
| 537 } | 467 } |
| 538 } | 468 } |
| 539 | 469 |
| 540 // fRecord OK | |
| 541 void SkPicture::flatten(SkWriteBuffer& buffer) const { | 470 void SkPicture::flatten(SkWriteBuffer& buffer) const { |
| 542 const SkPictureData* data = fData.get(); | |
| 543 | |
| 544 // If we're a new-format picture, backport to old format for serialization. | |
| 545 SkAutoTDelete<SkPicture> oldFormat; | |
| 546 if (NULL == data && fRecord.get()) { | |
| 547 oldFormat.reset(Backport(*fRecord, this->cullRect())); | |
| 548 data = oldFormat->fData.get(); | |
| 549 SkASSERT(data); | |
| 550 } | |
| 551 | |
| 552 SkPictInfo info; | 471 SkPictInfo info; |
| 553 this->createHeader(&info); | 472 this->createHeader(&info); |
| 473 SkAutoTDelete<SkPictureData> data(Backport(*fRecord, info)); |
| 474 |
| 554 buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic)); | 475 buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic)); |
| 555 buffer.writeUInt(info.fVersion); | 476 buffer.writeUInt(info.fVersion); |
| 556 buffer.writeRect(info.fCullRect); | 477 buffer.writeRect(info.fCullRect); |
| 557 buffer.writeUInt(info.fFlags); | 478 buffer.writeUInt(info.fFlags); |
| 558 | |
| 559 if (data) { | 479 if (data) { |
| 560 buffer.writeBool(true); | 480 buffer.writeBool(true); |
| 561 data->flatten(buffer); | 481 data->flatten(buffer); |
| 562 } else { | 482 } else { |
| 563 buffer.writeBool(false); | 483 buffer.writeBool(false); |
| 564 } | 484 } |
| 565 } | 485 } |
| 566 | 486 |
| 567 #if SK_SUPPORT_GPU | 487 #if SK_SUPPORT_GPU |
| 568 // fRecord OK | 488 bool SkPicture::suitableForGpuRasterization(GrContext*, const char **reason) con
st { |
| 569 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **rea
son) const { | 489 return fAnalysis.suitableForGpuRasterization(reason, 0); |
| 570 if (fRecord.get()) { | |
| 571 return fAnalysis.suitableForGpuRasterization(reason, 0); | |
| 572 } | |
| 573 if (NULL == fData.get()) { | |
| 574 if (reason) { | |
| 575 *reason = "Missing internal data."; | |
| 576 } | |
| 577 return false; | |
| 578 } | |
| 579 | |
| 580 return fData->suitableForGpuRasterization(context, reason); | |
| 581 } | 490 } |
| 582 #endif | 491 #endif |
| 583 | 492 |
| 584 // fRecord OK | 493 bool SkPicture::hasText() const { return fAnalysis.fHasText; } |
| 585 bool SkPicture::hasText() const { | 494 bool SkPicture::willPlayBackBitmaps() const { return fAnalysis.fWillPlaybackBitm
aps; } |
| 586 if (fRecord.get()) { | 495 int SkPicture::approximateOpCount() const { return fRecord->count(); } |
| 587 return fAnalysis.fHasText; | |
| 588 } | |
| 589 if (fData.get()) { | |
| 590 return fData->hasText(); | |
| 591 } | |
| 592 SkFAIL("Unreachable"); | |
| 593 return false; | |
| 594 } | |
| 595 | 496 |
| 596 // fRecord OK | 497 static int32_t gPictureGenerationID = SK_InvalidGenID; // This will be set at l
ink time. |
| 597 bool SkPicture::willPlayBackBitmaps() const { | |
| 598 if (fRecord.get()) { | |
| 599 return fAnalysis.fWillPlaybackBitmaps; | |
| 600 } | |
| 601 if (fData.get()) { | |
| 602 return fData->containsBitmaps(); | |
| 603 } | |
| 604 SkFAIL("Unreachable"); | |
| 605 return false; | |
| 606 } | |
| 607 | 498 |
| 608 // fRecord OK | |
| 609 static int32_t next_picture_generation_id() { | 499 static int32_t next_picture_generation_id() { |
| 610 static int32_t gPictureGenerationID = 0; | 500 // Loop in case our global wraps around. |
| 611 // do a loop in case our global wraps around, as we never want to | |
| 612 // return a 0 | |
| 613 int32_t genID; | 501 int32_t genID; |
| 614 do { | 502 do { |
| 615 genID = sk_atomic_inc(&gPictureGenerationID) + 1; | 503 genID = sk_atomic_inc(&gPictureGenerationID) + 1; |
| 616 } while (SK_InvalidGenID == genID); | 504 } while (SK_InvalidGenID == genID); |
| 617 return genID; | 505 return genID; |
| 618 } | 506 } |
| 619 | 507 |
| 620 // fRecord OK | |
| 621 uint32_t SkPicture::uniqueID() const { | 508 uint32_t SkPicture::uniqueID() const { |
| 622 if (SK_InvalidGenID == fUniqueID) { | 509 if (SK_InvalidGenID == fUniqueID) { |
| 623 fUniqueID = next_picture_generation_id(); | 510 fUniqueID = next_picture_generation_id(); |
| 624 } | 511 } |
| 625 return fUniqueID; | 512 return fUniqueID; |
| 626 } | 513 } |
| 627 | 514 |
| 628 // fRecord OK | |
| 629 SkPicture::SkPicture(SkScalar width, SkScalar height, SkRecord* record, SkBBoxHi
erarchy* bbh) | 515 SkPicture::SkPicture(SkScalar width, SkScalar height, SkRecord* record, SkBBoxHi
erarchy* bbh) |
| 630 : fCullWidth(width) | 516 : fCullWidth(width) |
| 631 , fCullHeight(height) | 517 , fCullHeight(height) |
| 632 , fRecord(record) | 518 , fRecord(record) |
| 633 , fBBH(SkSafeRef(bbh)) | 519 , fBBH(SkSafeRef(bbh)) |
| 634 , fAnalysis(*fRecord) { | 520 , fAnalysis(*fRecord) { |
| 635 this->needsNewGenID(); | 521 this->needsNewGenID(); |
| 636 } | 522 } |
| 637 | 523 |
| 638 // Note that we are assuming that this entry point will only be called from | 524 // Note that we are assuming that this entry point will only be called from |
| 639 // one thread. Currently the only client of this method is | 525 // one thread. Currently the only client of this method is |
| 640 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single | 526 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single |
| 641 // thread. | 527 // thread. |
| 642 void SkPicture::addDeletionListener(DeletionListener* listener) const { | 528 void SkPicture::addDeletionListener(DeletionListener* listener) const { |
| 643 SkASSERT(listener); | 529 SkASSERT(listener); |
| 644 | 530 |
| 645 *fDeletionListeners.append() = SkRef(listener); | 531 *fDeletionListeners.append() = SkRef(listener); |
| 646 } | 532 } |
| 647 | 533 |
| 648 void SkPicture::callDeletionListeners() { | 534 void SkPicture::callDeletionListeners() { |
| 649 for (int i = 0; i < fDeletionListeners.count(); ++i) { | 535 for (int i = 0; i < fDeletionListeners.count(); ++i) { |
| 650 fDeletionListeners[i]->onDeletion(this->uniqueID()); | 536 fDeletionListeners[i]->onDeletion(this->uniqueID()); |
| 651 } | 537 } |
| 652 | 538 |
| 653 fDeletionListeners.unrefAll(); | 539 fDeletionListeners.unrefAll(); |
| 654 } | 540 } |
| 655 | |
| 656 // fRecord OK | |
| 657 int SkPicture::approximateOpCount() const { | |
| 658 SkASSERT(fRecord.get() || fData.get()); | |
| 659 if (fRecord.get()) { | |
| 660 return fRecord->count(); | |
| 661 } | |
| 662 if (fData.get()) { | |
| 663 return fData->opCount(); | |
| 664 } | |
| 665 return 0; | |
| 666 } | |
| OLD | NEW |