| /* | |
| * Copyright 2016 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "src/core/SkRecordedDrawable.h" | |
| #include "include/core/SkPicture.h" | |
| #include "include/core/SkPictureRecorder.h" | |
| #include "include/core/SkSize.h" | |
| #include "src/core/SkPictureData.h" | |
| #include "src/core/SkPicturePlayback.h" | |
| #include "src/core/SkPicturePriv.h" | |
| #include "src/core/SkPictureRecord.h" | |
| #include "src/core/SkReadBuffer.h" | |
| #include "src/core/SkRecordDraw.h" | |
| #include "src/core/SkWriteBuffer.h" | |
| class SkCanvas; | |
| size_t SkRecordedDrawable::onApproximateBytesUsed() { | |
| size_t drawablesSize = 0; | |
| if (fDrawableList) { | |
| for (auto&& drawable : *fDrawableList) { | |
| drawablesSize += drawable->approximateBytesUsed(); | |
| } | |
| } | |
| return sizeof(*this) + | |
| (fRecord ? fRecord->bytesUsed() : 0) + | |
| (fBBH ? fBBH->bytesUsed() : 0) + | |
| drawablesSize; | |
| } | |
| void SkRecordedDrawable::onDraw(SkCanvas* canvas) { | |
| SkDrawable* const* drawables = nullptr; | |
| int drawableCount = 0; | |
| if (fDrawableList) { | |
| drawables = fDrawableList->begin(); | |
| drawableCount = fDrawableList->count(); | |
| } | |
| SkRecordDraw(*fRecord, canvas, nullptr, drawables, drawableCount, fBBH.get(), nullptr); | |
| } | |
| sk_sp<SkPicture> SkRecordedDrawable::onMakePictureSnapshot() { | |
| // TODO: should we plumb-down the BBHFactory and recordFlags from our host | |
| // PictureRecorder? | |
| std::unique_ptr<SkSnapshotArray> pictList{fDrawableList ? fDrawableList->newDrawableSnapshot() | |
| : nullptr}; | |
| size_t subPictureBytes = 0; | |
| for (int i = 0; pictList && i < pictList->count(); i++) { | |
| subPictureBytes += pictList->begin()[i]->approximateBytesUsed(); | |
| } | |
| return SkPicturePriv::MakePicture(fBounds, fRecord, std::move(pictList), fBBH, subPictureBytes); | |
| } | |
| void SkRecordedDrawable::flatten(SkWriteBuffer& buffer) const { | |
| // Write the bounds. | |
| buffer.writeRect(fBounds); | |
| // Create an SkPictureRecord to record the draw commands. | |
| SkPictInfo info; | |
| SkPictureRecord pictureRecord(SkISize::Make(fBounds.width(), fBounds.height()), 0); | |
| // If the query contains the whole picture, don't bother with the bounding box hierarchy. | |
| SkBBoxHierarchy* bbh; | |
| if (pictureRecord.getLocalClipBounds().contains(fBounds)) { | |
| bbh = nullptr; | |
| } else { | |
| bbh = fBBH.get(); | |
| } | |
| // Record the draw commands. | |
| SkDrawable* const* drawables = fDrawableList ? fDrawableList->begin() : nullptr; | |
| int drawableCount = fDrawableList ? fDrawableList->count() : 0; | |
| pictureRecord.beginRecording(); | |
| SkRecordDraw(*fRecord, &pictureRecord, nullptr, drawables, drawableCount, bbh, nullptr); | |
| pictureRecord.endRecording(); | |
| // Flatten the recorded commands and drawables. | |
| SkPictureData pictureData(pictureRecord, info); | |
| pictureData.flatten(buffer); | |
| } | |
| sk_sp<SkFlattenable> SkRecordedDrawable::CreateProc(SkReadBuffer& buffer) { | |
| if (!buffer.isValid()) { | |
| return nullptr; | |
| } | |
| // Read the bounds. | |
| SkRect bounds; | |
| buffer.readRect(&bounds); | |
| // Unflatten into a SkPictureData. | |
| SkPictInfo info; | |
| info.setVersion(buffer.getVersion()); | |
| info.fCullRect = bounds; | |
| std::unique_ptr<SkPictureData> pictureData(SkPictureData::CreateFromBuffer(buffer, info)); | |
| if (!pictureData) { | |
| return nullptr; | |
| } | |
| // Create a drawable. | |
| SkPicturePlayback playback(pictureData.get()); | |
| SkPictureRecorder recorder; | |
| playback.draw(recorder.beginRecording(bounds), nullptr, &buffer); | |
| return recorder.finishRecordingAsDrawable(); | |
| } |