/* * 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/SkBigPicture.h" #include "src/core/SkPictureData.h" #include "src/core/SkPicturePlayback.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 SkRecordedDrawable::onMakePictureSnapshot() { // TODO: should we plumb-down the BBHFactory and recordFlags from our host // PictureRecorder? std::unique_ptr pictList{ fDrawableList ? fDrawableList->newDrawableSnapshot() : nullptr }; size_t subPictureBytes = 0; for (int i = 0; pictList && i < pictList->count(); i++) { subPictureBytes += pictList->begin()[i]->approximateBytesUsed(); } return sk_make_sp(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 SkRecordedDrawable::CreateProc(SkReadBuffer& buffer) { // Read the bounds. SkRect bounds; buffer.readRect(&bounds); // Unflatten into a SkPictureData. SkPictInfo info; info.setVersion(buffer.getVersion()); info.fCullRect = bounds; std::unique_ptr 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(); }