aboutsummaryrefslogtreecommitdiffstats
path: root/src/core/SkPicture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/SkPicture.cpp')
-rw-r--r--src/core/SkPicture.cpp247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp
new file mode 100644
index 0000000..343ca2b
--- /dev/null
+++ b/src/core/SkPicture.cpp
@@ -0,0 +1,247 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "SkPictureFlat.h"
+#include "SkPicturePlayback.h"
+#include "SkPictureRecord.h"
+
+#include "SkCanvas.h"
+#include "SkChunkAlloc.h"
+#include "SkPicture.h"
+#include "SkRegion.h"
+#include "SkStream.h"
+#include "SkTDArray.h"
+#include "SkTSearch.h"
+#include "SkTime.h"
+
+#include "SkReader32.h"
+#include "SkWriter32.h"
+
+#define DUMP_BUFFER_SIZE 65536
+
+//#define ENABLE_TIME_DRAW // dumps milliseconds for each draw
+
+
+#ifdef SK_DEBUG
+// enable SK_DEBUG_TRACE to trace DrawType elements when
+// recorded and played back
+// #define SK_DEBUG_TRACE
+// enable SK_DEBUG_SIZE to see the size of picture components
+// #define SK_DEBUG_SIZE
+// enable SK_DEBUG_DUMP to see the contents of recorded elements
+// #define SK_DEBUG_DUMP
+// enable SK_DEBUG_VALIDATE to check internal structures for consistency
+// #define SK_DEBUG_VALIDATE
+#endif
+
+#if defined SK_DEBUG_TRACE || defined SK_DEBUG_DUMP
+const char* DrawTypeToString(DrawType drawType) {
+ switch (drawType) {
+ case UNUSED: SkDebugf("DrawType UNUSED\n"); SkASSERT(0); break;
+ case CLIP_PATH: return "CLIP_PATH";
+ case CLIP_REGION: return "CLIP_REGION";
+ case CLIP_RECT: return "CLIP_RECT";
+ case CONCAT: return "CONCAT";
+ case DRAW_BITMAP: return "DRAW_BITMAP";
+ case DRAW_BITMAP_MATRIX: return "DRAW_BITMAP_MATRIX";
+ case DRAW_BITMAP_RECT: return "DRAW_BITMAP_RECT";
+ case DRAW_PAINT: return "DRAW_PAINT";
+ case DRAW_PATH: return "DRAW_PATH";
+ case DRAW_PICTURE: return "DRAW_PICTURE";
+ case DRAW_POINTS: return "DRAW_POINTS";
+ case DRAW_POS_TEXT: return "DRAW_POS_TEXT";
+ case DRAW_POS_TEXT_H: return "DRAW_POS_TEXT_H";
+ case DRAW_RECT_GENERAL: return "DRAW_RECT_GENERAL";
+ case DRAW_RECT_SIMPLE: return "DRAW_RECT_SIMPLE";
+ case DRAW_SPRITE: return "DRAW_SPRITE";
+ case DRAW_TEXT: return "DRAW_TEXT";
+ case DRAW_TEXT_ON_PATH: return "DRAW_TEXT_ON_PATH";
+ case RESTORE: return "RESTORE";
+ case ROTATE: return "ROTATE";
+ case SAVE: return "SAVE";
+ case SAVE_LAYER: return "SAVE_LAYER";
+ case SCALE: return "SCALE";
+ case SKEW: return "SKEW";
+ case TRANSLATE: return "TRANSLATE";
+ default:
+ SkDebugf("DrawType error 0x%08x\n", drawType);
+ SkASSERT(0);
+ break;
+ }
+ SkASSERT(0);
+ return NULL;
+}
+#endif
+
+#ifdef SK_DEBUG_VALIDATE
+static void validateMatrix(const SkMatrix* matrix) {
+ SkScalar scaleX = matrix->getScaleX();
+ SkScalar scaleY = matrix->getScaleY();
+ SkScalar skewX = matrix->getSkewX();
+ SkScalar skewY = matrix->getSkewY();
+ SkScalar perspX = matrix->getPerspX();
+ SkScalar perspY = matrix->getPerspY();
+ if (scaleX != 0 && skewX != 0)
+ SkDebugf("scaleX != 0 && skewX != 0\n");
+ SkASSERT(scaleX == 0 || skewX == 0);
+ SkASSERT(scaleY == 0 || skewY == 0);
+ SkASSERT(perspX == 0);
+ SkASSERT(perspY == 0);
+}
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkPicture::SkPicture() {
+ fRecord = NULL;
+ fPlayback = NULL;
+ fWidth = fHeight = 0;
+}
+
+SkPicture::SkPicture(const SkPicture& src) : SkRefCnt() {
+ fWidth = src.fWidth;
+ fHeight = src.fHeight;
+ fRecord = NULL;
+
+ /* We want to copy the src's playback. However, if that hasn't been built
+ yet, we need to fake a call to endRecording() without actually calling
+ it (since it is destructive, and we don't want to change src).
+ */
+ if (src.fPlayback) {
+ fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback));
+ } else if (src.fRecord) {
+ // here we do a fake src.endRecording()
+ fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord));
+ } else {
+ fPlayback = NULL;
+ }
+}
+
+SkPicture::~SkPicture() {
+ fRecord->safeUnref();
+ SkDELETE(fPlayback);
+}
+
+void SkPicture::swap(SkPicture& other) {
+ SkTSwap(fRecord, other.fRecord);
+ SkTSwap(fPlayback, other.fPlayback);
+ SkTSwap(fWidth, other.fWidth);
+ SkTSwap(fHeight, other.fHeight);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkCanvas* SkPicture::beginRecording(int width, int height,
+ uint32_t recordingFlags) {
+ if (fPlayback) {
+ SkDELETE(fPlayback);
+ fPlayback = NULL;
+ }
+
+ if (NULL != fRecord) {
+ fRecord->unref();
+ fRecord = NULL;
+ }
+
+ fRecord = SkNEW_ARGS(SkPictureRecord, (recordingFlags));
+
+ fWidth = width;
+ fHeight = height;
+
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kNo_Config, width, height);
+ fRecord->setBitmapDevice(bm);
+
+ return fRecord;
+}
+
+SkCanvas* SkPicture::getRecordingCanvas() const {
+ // will be null if we are not recording
+ return fRecord;
+}
+
+void SkPicture::endRecording() {
+ if (NULL == fPlayback) {
+ if (NULL != fRecord) {
+ fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
+ fRecord->unref();
+ fRecord = NULL;
+ }
+ }
+ SkASSERT(NULL == fRecord);
+}
+
+void SkPicture::draw(SkCanvas* surface) {
+ this->endRecording();
+ if (fPlayback) {
+ fPlayback->draw(*surface);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkStream.h"
+
+#define PICTURE_VERSION 1
+
+SkPicture::SkPicture(SkStream* stream) : SkRefCnt() {
+ if (stream->readU32() != PICTURE_VERSION) {
+ sk_throw();
+ }
+
+ fWidth = stream->readU32();
+ fHeight = stream->readU32();
+
+ fRecord = NULL;
+ fPlayback = NULL;
+
+ if (stream->readBool()) {
+ fPlayback = SkNEW_ARGS(SkPicturePlayback, (stream));
+ }
+}
+
+void SkPicture::serialize(SkWStream* stream) const {
+ SkPicturePlayback* playback = fPlayback;
+
+ if (NULL == playback && fRecord) {
+ playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
+ }
+
+ stream->write32(PICTURE_VERSION);
+ stream->write32(fWidth);
+ stream->write32(fHeight);
+ if (playback) {
+ stream->writeBool(true);
+ playback->serialize(stream);
+ // delete playback if it is a local version (i.e. cons'd up just now)
+ if (playback != fPlayback) {
+ SkDELETE(playback);
+ }
+ } else {
+ stream->writeBool(false);
+ }
+}
+
+void SkPicture::abortPlayback() {
+ if (NULL == fPlayback) {
+ return;
+ }
+ fPlayback->abort();
+}
+
+