[go: nahoru, domu]

grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk/src@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/core/SkPicture.cpp b/core/SkPicture.cpp
new file mode 100644
index 0000000..07cb0a6
--- /dev/null
+++ b/core/SkPicture.cpp
@@ -0,0 +1,246 @@
+/*
+**
+** 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) {
+    if (fPlayback) {
+        SkDELETE(fPlayback);
+        fPlayback = NULL;
+    }
+
+    if (NULL != fRecord) {
+        fRecord->unref();
+        fRecord = NULL;
+    }
+
+    fRecord = SkNEW(SkPictureRecord);
+
+    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();
+}
+
+