[go: nahoru, domu]

blob: a3b7396b8bbddbed7240828a2494f39d13924163 [file] [log] [blame]
epoger@google.com685cfc02011-07-28 14:26:00 +00001
reed@android.combcd4d5a2008-12-17 15:59:43 +00002/*
epoger@google.com685cfc02011-07-28 14:26:00 +00003 * Copyright 2007 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
reed@android.combcd4d5a2008-12-17 15:59:43 +00009
10#include "SkPictureFlat.h"
11#include "SkPicturePlayback.h"
12#include "SkPictureRecord.h"
13
14#include "SkCanvas.h"
15#include "SkChunkAlloc.h"
16#include "SkPicture.h"
17#include "SkRegion.h"
18#include "SkStream.h"
19#include "SkTDArray.h"
20#include "SkTSearch.h"
21#include "SkTime.h"
22
23#include "SkReader32.h"
24#include "SkWriter32.h"
25
26#define DUMP_BUFFER_SIZE 65536
27
28//#define ENABLE_TIME_DRAW // dumps milliseconds for each draw
29
30
31#ifdef SK_DEBUG
reed@google.com91911482011-02-07 15:30:46 +000032// enable SK_DEBUG_TRACE to trace DrawType elements when
reed@android.combcd4d5a2008-12-17 15:59:43 +000033// recorded and played back
34// #define SK_DEBUG_TRACE
35// enable SK_DEBUG_SIZE to see the size of picture components
36// #define SK_DEBUG_SIZE
37// enable SK_DEBUG_DUMP to see the contents of recorded elements
38// #define SK_DEBUG_DUMP
39// enable SK_DEBUG_VALIDATE to check internal structures for consistency
40// #define SK_DEBUG_VALIDATE
41#endif
42
43#if defined SK_DEBUG_TRACE || defined SK_DEBUG_DUMP
44const char* DrawTypeToString(DrawType drawType) {
45 switch (drawType) {
46 case UNUSED: SkDebugf("DrawType UNUSED\n"); SkASSERT(0); break;
47 case CLIP_PATH: return "CLIP_PATH";
48 case CLIP_REGION: return "CLIP_REGION";
49 case CLIP_RECT: return "CLIP_RECT";
50 case CONCAT: return "CONCAT";
51 case DRAW_BITMAP: return "DRAW_BITMAP";
52 case DRAW_BITMAP_MATRIX: return "DRAW_BITMAP_MATRIX";
53 case DRAW_BITMAP_RECT: return "DRAW_BITMAP_RECT";
54 case DRAW_PAINT: return "DRAW_PAINT";
55 case DRAW_PATH: return "DRAW_PATH";
56 case DRAW_PICTURE: return "DRAW_PICTURE";
57 case DRAW_POINTS: return "DRAW_POINTS";
58 case DRAW_POS_TEXT: return "DRAW_POS_TEXT";
59 case DRAW_POS_TEXT_H: return "DRAW_POS_TEXT_H";
60 case DRAW_RECT_GENERAL: return "DRAW_RECT_GENERAL";
61 case DRAW_RECT_SIMPLE: return "DRAW_RECT_SIMPLE";
62 case DRAW_SPRITE: return "DRAW_SPRITE";
63 case DRAW_TEXT: return "DRAW_TEXT";
64 case DRAW_TEXT_ON_PATH: return "DRAW_TEXT_ON_PATH";
65 case RESTORE: return "RESTORE";
66 case ROTATE: return "ROTATE";
67 case SAVE: return "SAVE";
68 case SAVE_LAYER: return "SAVE_LAYER";
69 case SCALE: return "SCALE";
70 case SKEW: return "SKEW";
71 case TRANSLATE: return "TRANSLATE";
reed@google.com91911482011-02-07 15:30:46 +000072 default:
73 SkDebugf("DrawType error 0x%08x\n", drawType);
74 SkASSERT(0);
reed@android.combcd4d5a2008-12-17 15:59:43 +000075 break;
76 }
reed@google.com91911482011-02-07 15:30:46 +000077 SkASSERT(0);
reed@android.combcd4d5a2008-12-17 15:59:43 +000078 return NULL;
79}
80#endif
81
82#ifdef SK_DEBUG_VALIDATE
83static void validateMatrix(const SkMatrix* matrix) {
84 SkScalar scaleX = matrix->getScaleX();
85 SkScalar scaleY = matrix->getScaleY();
86 SkScalar skewX = matrix->getSkewX();
87 SkScalar skewY = matrix->getSkewY();
88 SkScalar perspX = matrix->getPerspX();
89 SkScalar perspY = matrix->getPerspY();
90 if (scaleX != 0 && skewX != 0)
91 SkDebugf("scaleX != 0 && skewX != 0\n");
92 SkASSERT(scaleX == 0 || skewX == 0);
93 SkASSERT(scaleY == 0 || skewY == 0);
94 SkASSERT(perspX == 0);
95 SkASSERT(perspY == 0);
96}
97#endif
98
99
100///////////////////////////////////////////////////////////////////////////////
101
102SkPicture::SkPicture() {
103 fRecord = NULL;
104 fPlayback = NULL;
105 fWidth = fHeight = 0;
106}
107
108SkPicture::SkPicture(const SkPicture& src) : SkRefCnt() {
109 fWidth = src.fWidth;
110 fHeight = src.fHeight;
111 fRecord = NULL;
112
113 /* We want to copy the src's playback. However, if that hasn't been built
114 yet, we need to fake a call to endRecording() without actually calling
115 it (since it is destructive, and we don't want to change src).
116 */
117 if (src.fPlayback) {
118 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback));
119 } else if (src.fRecord) {
120 // here we do a fake src.endRecording()
121 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord));
122 } else {
123 fPlayback = NULL;
124 }
125}
126
127SkPicture::~SkPicture() {
reed@google.com91911482011-02-07 15:30:46 +0000128 SkSafeUnref(fRecord);
reed@android.combcd4d5a2008-12-17 15:59:43 +0000129 SkDELETE(fPlayback);
130}
131
132void SkPicture::swap(SkPicture& other) {
133 SkTSwap(fRecord, other.fRecord);
134 SkTSwap(fPlayback, other.fPlayback);
135 SkTSwap(fWidth, other.fWidth);
136 SkTSwap(fHeight, other.fHeight);
137}
138
139///////////////////////////////////////////////////////////////////////////////
140
reed@android.comc4a55d72009-02-13 14:56:09 +0000141SkCanvas* SkPicture::beginRecording(int width, int height,
142 uint32_t recordingFlags) {
reed@android.combcd4d5a2008-12-17 15:59:43 +0000143 if (fPlayback) {
144 SkDELETE(fPlayback);
145 fPlayback = NULL;
146 }
147
148 if (NULL != fRecord) {
149 fRecord->unref();
150 fRecord = NULL;
151 }
152
reed@android.comc4a55d72009-02-13 14:56:09 +0000153 fRecord = SkNEW_ARGS(SkPictureRecord, (recordingFlags));
reed@android.combcd4d5a2008-12-17 15:59:43 +0000154
155 fWidth = width;
156 fHeight = height;
157
158 SkBitmap bm;
159 bm.setConfig(SkBitmap::kNo_Config, width, height);
160 fRecord->setBitmapDevice(bm);
reed@google.com91911482011-02-07 15:30:46 +0000161
reed@android.combcd4d5a2008-12-17 15:59:43 +0000162 return fRecord;
163}
164
165SkCanvas* SkPicture::getRecordingCanvas() const {
166 // will be null if we are not recording
167 return fRecord;
168}
169
170void SkPicture::endRecording() {
171 if (NULL == fPlayback) {
172 if (NULL != fRecord) {
173 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
174 fRecord->unref();
175 fRecord = NULL;
176 }
177 }
178 SkASSERT(NULL == fRecord);
179}
180
181void SkPicture::draw(SkCanvas* surface) {
182 this->endRecording();
183 if (fPlayback) {
184 fPlayback->draw(*surface);
185 }
186}
187
188///////////////////////////////////////////////////////////////////////////////
189
190#include "SkStream.h"
191
192#define PICTURE_VERSION 1
193
194SkPicture::SkPicture(SkStream* stream) : SkRefCnt() {
195 if (stream->readU32() != PICTURE_VERSION) {
196 sk_throw();
197 }
198
199 fWidth = stream->readU32();
200 fHeight = stream->readU32();
201
202 fRecord = NULL;
203 fPlayback = NULL;
204
205 if (stream->readBool()) {
206 fPlayback = SkNEW_ARGS(SkPicturePlayback, (stream));
207 }
208}
209
210void SkPicture::serialize(SkWStream* stream) const {
211 SkPicturePlayback* playback = fPlayback;
reed@google.com91911482011-02-07 15:30:46 +0000212
reed@android.combcd4d5a2008-12-17 15:59:43 +0000213 if (NULL == playback && fRecord) {
214 playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
215 }
216
217 stream->write32(PICTURE_VERSION);
218 stream->write32(fWidth);
219 stream->write32(fHeight);
220 if (playback) {
221 stream->writeBool(true);
222 playback->serialize(stream);
223 // delete playback if it is a local version (i.e. cons'd up just now)
224 if (playback != fPlayback) {
225 SkDELETE(playback);
226 }
227 } else {
228 stream->writeBool(false);
229 }
230}
231
232void SkPicture::abortPlayback() {
233 if (NULL == fPlayback) {
234 return;
235 }
236 fPlayback->abort();
237}
238
239