OLD | NEW |
| (Empty) |
1 /* | |
2 ** | |
3 ** Copyright 2007, The Android Open Source Project | |
4 ** | |
5 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
6 ** you may not use this file except in compliance with the License. | |
7 ** You may obtain a copy of the License at | |
8 ** | |
9 ** http://www.apache.org/licenses/LICENSE-2.0 | |
10 ** | |
11 ** Unless required by applicable law or agreed to in writing, software | |
12 ** distributed under the License is distributed on an "AS IS" BASIS, | |
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 ** See the License for the specific language governing permissions and | |
15 ** limitations under the License. | |
16 */ | |
17 | |
18 #include "SkPictureFlat.h" | |
19 #include "SkPicturePlayback.h" | |
20 #include "SkPictureRecord.h" | |
21 | |
22 #include "SkCanvas.h" | |
23 #include "SkChunkAlloc.h" | |
24 #include "SkPicture.h" | |
25 #include "SkRegion.h" | |
26 #include "SkStream.h" | |
27 #include "SkTDArray.h" | |
28 #include "SkTSearch.h" | |
29 #include "SkTime.h" | |
30 | |
31 #include "SkReader32.h" | |
32 #include "SkWriter32.h" | |
33 | |
34 #define DUMP_BUFFER_SIZE 65536 | |
35 | |
36 //#define ENABLE_TIME_DRAW // dumps milliseconds for each draw | |
37 | |
38 | |
39 #ifdef SK_DEBUG | |
40 // enable SK_DEBUG_TRACE to trace DrawType elements when | |
41 // recorded and played back | |
42 // #define SK_DEBUG_TRACE | |
43 // enable SK_DEBUG_SIZE to see the size of picture components | |
44 // #define SK_DEBUG_SIZE | |
45 // enable SK_DEBUG_DUMP to see the contents of recorded elements | |
46 // #define SK_DEBUG_DUMP | |
47 // enable SK_DEBUG_VALIDATE to check internal structures for consistency | |
48 // #define SK_DEBUG_VALIDATE | |
49 #endif | |
50 | |
51 #if defined SK_DEBUG_TRACE || defined SK_DEBUG_DUMP | |
52 const char* DrawTypeToString(DrawType drawType) { | |
53 switch (drawType) { | |
54 case UNUSED: SkDebugf("DrawType UNUSED\n"); SkASSERT(0); break; | |
55 case CLIP_PATH: return "CLIP_PATH"; | |
56 case CLIP_REGION: return "CLIP_REGION"; | |
57 case CLIP_RECT: return "CLIP_RECT"; | |
58 case CONCAT: return "CONCAT"; | |
59 case DRAW_BITMAP: return "DRAW_BITMAP"; | |
60 case DRAW_BITMAP_MATRIX: return "DRAW_BITMAP_MATRIX"; | |
61 case DRAW_BITMAP_RECT: return "DRAW_BITMAP_RECT"; | |
62 case DRAW_PAINT: return "DRAW_PAINT"; | |
63 case DRAW_PATH: return "DRAW_PATH"; | |
64 case DRAW_PICTURE: return "DRAW_PICTURE"; | |
65 case DRAW_POINTS: return "DRAW_POINTS"; | |
66 case DRAW_POS_TEXT: return "DRAW_POS_TEXT"; | |
67 case DRAW_POS_TEXT_H: return "DRAW_POS_TEXT_H"; | |
68 case DRAW_RECT_GENERAL: return "DRAW_RECT_GENERAL"; | |
69 case DRAW_RECT_SIMPLE: return "DRAW_RECT_SIMPLE"; | |
70 case DRAW_SPRITE: return "DRAW_SPRITE"; | |
71 case DRAW_TEXT: return "DRAW_TEXT"; | |
72 case DRAW_TEXT_ON_PATH: return "DRAW_TEXT_ON_PATH"; | |
73 case RESTORE: return "RESTORE"; | |
74 case ROTATE: return "ROTATE"; | |
75 case SAVE: return "SAVE"; | |
76 case SAVE_LAYER: return "SAVE_LAYER"; | |
77 case SCALE: return "SCALE"; | |
78 case SKEW: return "SKEW"; | |
79 case TRANSLATE: return "TRANSLATE"; | |
80 default: | |
81 SkDebugf("DrawType error 0x%08x\n", drawType); | |
82 SkASSERT(0); | |
83 break; | |
84 } | |
85 SkASSERT(0); | |
86 return NULL; | |
87 } | |
88 #endif | |
89 | |
90 #ifdef SK_DEBUG_VALIDATE | |
91 static void validateMatrix(const SkMatrix* matrix) { | |
92 SkScalar scaleX = matrix->getScaleX(); | |
93 SkScalar scaleY = matrix->getScaleY(); | |
94 SkScalar skewX = matrix->getSkewX(); | |
95 SkScalar skewY = matrix->getSkewY(); | |
96 SkScalar perspX = matrix->getPerspX(); | |
97 SkScalar perspY = matrix->getPerspY(); | |
98 if (scaleX != 0 && skewX != 0) | |
99 SkDebugf("scaleX != 0 && skewX != 0\n"); | |
100 SkASSERT(scaleX == 0 || skewX == 0); | |
101 SkASSERT(scaleY == 0 || skewY == 0); | |
102 SkASSERT(perspX == 0); | |
103 SkASSERT(perspY == 0); | |
104 } | |
105 #endif | |
106 | |
107 | |
108 /////////////////////////////////////////////////////////////////////////////// | |
109 | |
110 SkPicture::SkPicture() { | |
111 fRecord = NULL; | |
112 fPlayback = NULL; | |
113 fWidth = fHeight = 0; | |
114 } | |
115 | |
116 SkPicture::SkPicture(const SkPicture& src) : SkRefCnt() { | |
117 fWidth = src.fWidth; | |
118 fHeight = src.fHeight; | |
119 fRecord = NULL; | |
120 | |
121 /* We want to copy the src's playback. However, if that hasn't been built | |
122 yet, we need to fake a call to endRecording() without actually calling | |
123 it (since it is destructive, and we don't want to change src). | |
124 */ | |
125 if (src.fPlayback) { | |
126 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback)); | |
127 } else if (src.fRecord) { | |
128 // here we do a fake src.endRecording() | |
129 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord)); | |
130 } else { | |
131 fPlayback = NULL; | |
132 } | |
133 } | |
134 | |
135 SkPicture::~SkPicture() { | |
136 fRecord->safeUnref(); | |
137 SkDELETE(fPlayback); | |
138 } | |
139 | |
140 void SkPicture::swap(SkPicture& other) { | |
141 SkTSwap(fRecord, other.fRecord); | |
142 SkTSwap(fPlayback, other.fPlayback); | |
143 SkTSwap(fWidth, other.fWidth); | |
144 SkTSwap(fHeight, other.fHeight); | |
145 } | |
146 | |
147 /////////////////////////////////////////////////////////////////////////////// | |
148 | |
149 SkCanvas* SkPicture::beginRecording(int width, int height) { | |
150 if (fPlayback) { | |
151 SkDELETE(fPlayback); | |
152 fPlayback = NULL; | |
153 } | |
154 | |
155 if (NULL != fRecord) { | |
156 fRecord->unref(); | |
157 fRecord = NULL; | |
158 } | |
159 | |
160 fRecord = SkNEW(SkPictureRecord); | |
161 | |
162 fWidth = width; | |
163 fHeight = height; | |
164 | |
165 SkBitmap bm; | |
166 bm.setConfig(SkBitmap::kNo_Config, width, height); | |
167 fRecord->setBitmapDevice(bm); | |
168 | |
169 return fRecord; | |
170 } | |
171 | |
172 SkCanvas* SkPicture::getRecordingCanvas() const { | |
173 // will be null if we are not recording | |
174 return fRecord; | |
175 } | |
176 | |
177 void SkPicture::endRecording() { | |
178 if (NULL == fPlayback) { | |
179 if (NULL != fRecord) { | |
180 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord)); | |
181 fRecord->unref(); | |
182 fRecord = NULL; | |
183 } | |
184 } | |
185 SkASSERT(NULL == fRecord); | |
186 } | |
187 | |
188 void SkPicture::draw(SkCanvas* surface) { | |
189 this->endRecording(); | |
190 if (fPlayback) { | |
191 fPlayback->draw(*surface); | |
192 } | |
193 } | |
194 | |
195 /////////////////////////////////////////////////////////////////////////////// | |
196 | |
197 #include "SkStream.h" | |
198 | |
199 #define PICTURE_VERSION 1 | |
200 | |
201 SkPicture::SkPicture(SkStream* stream) : SkRefCnt() { | |
202 if (stream->readU32() != PICTURE_VERSION) { | |
203 sk_throw(); | |
204 } | |
205 | |
206 fWidth = stream->readU32(); | |
207 fHeight = stream->readU32(); | |
208 | |
209 fRecord = NULL; | |
210 fPlayback = NULL; | |
211 | |
212 if (stream->readBool()) { | |
213 fPlayback = SkNEW_ARGS(SkPicturePlayback, (stream)); | |
214 } | |
215 } | |
216 | |
217 void SkPicture::serialize(SkWStream* stream) const { | |
218 SkPicturePlayback* playback = fPlayback; | |
219 | |
220 if (NULL == playback && fRecord) { | |
221 playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord)); | |
222 } | |
223 | |
224 stream->write32(PICTURE_VERSION); | |
225 stream->write32(fWidth); | |
226 stream->write32(fHeight); | |
227 if (playback) { | |
228 stream->writeBool(true); | |
229 playback->serialize(stream); | |
230 // delete playback if it is a local version (i.e. cons'd up just now) | |
231 if (playback != fPlayback) { | |
232 SkDELETE(playback); | |
233 } | |
234 } else { | |
235 stream->writeBool(false); | |
236 } | |
237 } | |
238 | |
239 void SkPicture::abortPlayback() { | |
240 if (NULL == fPlayback) { | |
241 return; | |
242 } | |
243 fPlayback->abort(); | |
244 } | |
245 | |
246 | |
OLD | NEW |