• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
DrawTypeToString(DrawType drawType)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
validateMatrix(const SkMatrix * matrix)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 
SkPicture()110 SkPicture::SkPicture() {
111     fRecord = NULL;
112     fPlayback = NULL;
113     fWidth = fHeight = 0;
114 }
115 
SkPicture(const SkPicture & src)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 
~SkPicture()135 SkPicture::~SkPicture() {
136     fRecord->safeUnref();
137     SkDELETE(fPlayback);
138 }
139 
swap(SkPicture & other)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 
beginRecording(int width,int height,uint32_t recordingFlags)149 SkCanvas* SkPicture::beginRecording(int width, int height,
150                                     uint32_t recordingFlags) {
151     if (fPlayback) {
152         SkDELETE(fPlayback);
153         fPlayback = NULL;
154     }
155 
156     if (NULL != fRecord) {
157         fRecord->unref();
158         fRecord = NULL;
159     }
160 
161     fRecord = SkNEW_ARGS(SkPictureRecord, (recordingFlags));
162 
163     fWidth = width;
164     fHeight = height;
165 
166     SkBitmap bm;
167     bm.setConfig(SkBitmap::kNo_Config, width, height);
168     fRecord->setBitmapDevice(bm);
169 
170     return fRecord;
171 }
172 
getRecordingCanvas() const173 SkCanvas* SkPicture::getRecordingCanvas() const {
174     // will be null if we are not recording
175     return fRecord;
176 }
177 
endRecording()178 void SkPicture::endRecording() {
179     if (NULL == fPlayback) {
180         if (NULL != fRecord) {
181             fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
182             fRecord->unref();
183             fRecord = NULL;
184         }
185     }
186     SkASSERT(NULL == fRecord);
187 }
188 
draw(SkCanvas * surface)189 void SkPicture::draw(SkCanvas* surface) {
190     this->endRecording();
191     if (fPlayback) {
192         fPlayback->draw(*surface);
193     }
194 }
195 
196 ///////////////////////////////////////////////////////////////////////////////
197 
198 #include "SkStream.h"
199 
200 #define PICTURE_VERSION     1
201 
SkPicture(SkStream * stream)202 SkPicture::SkPicture(SkStream* stream) : SkRefCnt() {
203     if (stream->readU32() != PICTURE_VERSION) {
204         sk_throw();
205     }
206 
207     fWidth = stream->readU32();
208     fHeight = stream->readU32();
209 
210     fRecord = NULL;
211     fPlayback = NULL;
212 
213     if (stream->readBool()) {
214         fPlayback = SkNEW_ARGS(SkPicturePlayback, (stream));
215     }
216 }
217 
serialize(SkWStream * stream) const218 void SkPicture::serialize(SkWStream* stream) const {
219     SkPicturePlayback* playback = fPlayback;
220 
221     if (NULL == playback && fRecord) {
222         playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
223     }
224 
225     stream->write32(PICTURE_VERSION);
226     stream->write32(fWidth);
227     stream->write32(fHeight);
228     if (playback) {
229         stream->writeBool(true);
230         playback->serialize(stream);
231         // delete playback if it is a local version (i.e. cons'd up just now)
232         if (playback != fPlayback) {
233             SkDELETE(playback);
234         }
235     } else {
236         stream->writeBool(false);
237     }
238 }
239 
abortPlayback()240 void SkPicture::abortPlayback() {
241     if (NULL == fPlayback) {
242         return;
243     }
244     fPlayback->abort();
245 }
246 
247 
248