1 :
2 : /*
3 : * 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 :
9 :
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
32 : // enable SK_DEBUG_TRACE to trace DrawType elements when
33 : // 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
44 : const 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";
72 : default:
73 : SkDebugf("DrawType error 0x%08x\n", drawType);
74 : SkASSERT(0);
75 : break;
76 : }
77 : SkASSERT(0);
78 : return NULL;
79 : }
80 : #endif
81 :
82 : #ifdef SK_DEBUG_VALIDATE
83 : static 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 :
102 0 : SkPicture::SkPicture() {
103 0 : fRecord = NULL;
104 0 : fPlayback = NULL;
105 0 : fWidth = fHeight = 0;
106 0 : }
107 :
108 0 : SkPicture::SkPicture(const SkPicture& src) : SkRefCnt() {
109 0 : fWidth = src.fWidth;
110 0 : fHeight = src.fHeight;
111 0 : 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 0 : if (src.fPlayback) {
118 0 : fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback));
119 0 : } else if (src.fRecord) {
120 : // here we do a fake src.endRecording()
121 0 : fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord));
122 : } else {
123 0 : fPlayback = NULL;
124 : }
125 0 : }
126 :
127 0 : SkPicture::~SkPicture() {
128 0 : SkSafeUnref(fRecord);
129 0 : SkDELETE(fPlayback);
130 0 : }
131 :
132 0 : void SkPicture::swap(SkPicture& other) {
133 0 : SkTSwap(fRecord, other.fRecord);
134 0 : SkTSwap(fPlayback, other.fPlayback);
135 0 : SkTSwap(fWidth, other.fWidth);
136 0 : SkTSwap(fHeight, other.fHeight);
137 0 : }
138 :
139 : ///////////////////////////////////////////////////////////////////////////////
140 :
141 0 : SkCanvas* SkPicture::beginRecording(int width, int height,
142 : uint32_t recordingFlags) {
143 0 : if (fPlayback) {
144 0 : SkDELETE(fPlayback);
145 0 : fPlayback = NULL;
146 : }
147 :
148 0 : if (NULL != fRecord) {
149 0 : fRecord->unref();
150 0 : fRecord = NULL;
151 : }
152 :
153 0 : fRecord = SkNEW_ARGS(SkPictureRecord, (recordingFlags));
154 :
155 0 : fWidth = width;
156 0 : fHeight = height;
157 :
158 0 : SkBitmap bm;
159 0 : bm.setConfig(SkBitmap::kNo_Config, width, height);
160 0 : fRecord->setBitmapDevice(bm);
161 :
162 0 : return fRecord;
163 : }
164 :
165 0 : SkCanvas* SkPicture::getRecordingCanvas() const {
166 : // will be null if we are not recording
167 0 : return fRecord;
168 : }
169 :
170 0 : void SkPicture::endRecording() {
171 0 : if (NULL == fPlayback) {
172 0 : if (NULL != fRecord) {
173 0 : fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
174 0 : fRecord->unref();
175 0 : fRecord = NULL;
176 : }
177 : }
178 0 : SkASSERT(NULL == fRecord);
179 0 : }
180 :
181 0 : void SkPicture::draw(SkCanvas* surface) {
182 0 : this->endRecording();
183 0 : if (fPlayback) {
184 0 : fPlayback->draw(*surface);
185 : }
186 0 : }
187 :
188 : ///////////////////////////////////////////////////////////////////////////////
189 :
190 : #include "SkStream.h"
191 :
192 : #define PICTURE_VERSION 1
193 :
194 0 : SkPicture::SkPicture(SkStream* stream) : SkRefCnt() {
195 0 : if (stream->readU32() != PICTURE_VERSION) {
196 0 : sk_throw();
197 : }
198 :
199 0 : fWidth = stream->readU32();
200 0 : fHeight = stream->readU32();
201 :
202 0 : fRecord = NULL;
203 0 : fPlayback = NULL;
204 :
205 0 : if (stream->readBool()) {
206 0 : fPlayback = SkNEW_ARGS(SkPicturePlayback, (stream));
207 : }
208 0 : }
209 :
210 0 : void SkPicture::serialize(SkWStream* stream) const {
211 0 : SkPicturePlayback* playback = fPlayback;
212 :
213 0 : if (NULL == playback && fRecord) {
214 0 : playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
215 : }
216 :
217 0 : stream->write32(PICTURE_VERSION);
218 0 : stream->write32(fWidth);
219 0 : stream->write32(fHeight);
220 0 : if (playback) {
221 0 : stream->writeBool(true);
222 0 : playback->serialize(stream);
223 : // delete playback if it is a local version (i.e. cons'd up just now)
224 0 : if (playback != fPlayback) {
225 0 : SkDELETE(playback);
226 : }
227 : } else {
228 0 : stream->writeBool(false);
229 : }
230 0 : }
231 :
232 0 : void SkPicture::abortPlayback() {
233 0 : if (NULL == fPlayback) {
234 0 : return;
235 : }
236 0 : fPlayback->abort();
237 : }
238 :
239 :
|