ab00000de411a3efc663e0cd34c8e16ed381a641
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkPicture.cpp
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 "SkPictureData.h"
12 #include "SkPicturePlayback.h"
13 #include "SkPictureRecord.h"
14 #include "SkPictureRecorder.h"
15 #include "SkPictureStateTree.h"
16
17 #include "SkBitmapDevice.h"
18 #include "SkCanvas.h"
19 #include "SkChunkAlloc.h"
20 #include "SkDrawPictureCallback.h"
21 #include "SkPaintPriv.h"
22 #include "SkPicture.h"
23 #include "SkRecordAnalysis.h"
24 #include "SkRegion.h"
25 #include "SkStream.h"
26 #include "SkTDArray.h"
27 #include "SkTSearch.h"
28 #include "SkTime.h"
29
30 #include "SkReader32.h"
31 #include "SkWriter32.h"
32 #include "SkRTree.h"
33 #include "SkBBoxHierarchyRecord.h"
34
35 #if SK_SUPPORT_GPU
36 #include "GrContext.h"
37 #endif
38
39 #include "SkRecord.h"
40 #include "SkRecordDraw.h"
41 #include "SkRecorder.h"
42
43 template <typename T> int SafeCount(const T* obj) {
44     return obj ? obj->count() : 0;
45 }
46
47 ///////////////////////////////////////////////////////////////////////////////
48
49 #ifdef SK_SUPPORT_LEGACY_DEFAULT_PICTURE_CTOR
50 // fRecord OK
51 SkPicture::SkPicture()
52     : fWidth(0)
53     , fHeight(0)
54     , fRecordWillPlayBackBitmaps(false) {
55     this->needsNewGenID();
56 }
57 #endif
58
59 // fRecord OK
60 SkPicture::SkPicture(int width, int height,
61                      const SkPictureRecord& record,
62                      bool deepCopyOps)
63     : fWidth(width)
64     , fHeight(height)
65     , fRecordWillPlayBackBitmaps(false) {
66     this->needsNewGenID();
67
68     SkPictInfo info;
69     this->createHeader(&info);
70     fData.reset(SkNEW_ARGS(SkPictureData, (record, info, deepCopyOps)));
71 }
72
73 // Create an SkPictureData-backed SkPicture from an SkRecord.
74 // This for compatibility with serialization code only.  This is not cheap.
75 static SkPicture* backport(const SkRecord& src, int width, int height) {
76     SkPictureRecorder recorder;
77     SkRecordDraw(src, recorder.beginRecording(width, height), NULL/*bbh*/, NULL/*callback*/);
78     return recorder.endRecording();
79 }
80
81 // fRecord OK
82 SkPicture::~SkPicture() {
83     this->callDeletionListeners();
84 }
85
86 #ifdef SK_SUPPORT_LEGACY_PICTURE_CLONE
87 // fRecord TODO, fix by deleting this method
88 SkPicture* SkPicture::clone() const {
89 #ifdef SK_PICTURE_CLONE_NOOP
90     return SkRef(const_cast<SkPicture*>(this));
91 #else
92     SkAutoTDelete<SkPictureData> newData;
93
94     if (fData.get()) {
95         SkPictCopyInfo copyInfo;
96
97         int paintCount = SafeCount(fData->fPaints);
98
99         /* The alternative to doing this is to have a clone method on the paint and have it
100          * make the deep copy of its internal structures as needed. The holdup to doing
101          * that is at this point we would need to pass the SkBitmapHeap so that we don't
102          * unnecessarily flatten the pixels in a bitmap shader.
103          */
104         copyInfo.paintData.setCount(paintCount);
105
106         /* Use an SkBitmapHeap to avoid flattening bitmaps in shaders. If there already is
107          * one, use it. If this SkPictureData was created from a stream, fBitmapHeap
108          * will be NULL, so create a new one.
109          */
110         if (fData->fBitmapHeap.get() == NULL) {
111             // FIXME: Put this on the stack inside SkPicture::clone.
112             SkBitmapHeap* heap = SkNEW(SkBitmapHeap);
113             copyInfo.controller.setBitmapStorage(heap);
114             heap->unref();
115         } else {
116             copyInfo.controller.setBitmapStorage(fData->fBitmapHeap);
117         }
118
119         SkDEBUGCODE(int heapSize = SafeCount(fData->fBitmapHeap.get());)
120         for (int i = 0; i < paintCount; i++) {
121             if (NeedsDeepCopy(fData->fPaints->at(i))) {
122                 copyInfo.paintData[i] =
123                     SkFlatData::Create<SkPaint::FlatteningTraits>(&copyInfo.controller,
124                     fData->fPaints->at(i), 0);
125
126             } else {
127                 // this is our sentinel, which we use in the unflatten loop
128                 copyInfo.paintData[i] = NULL;
129             }
130         }
131         SkASSERT(SafeCount(fData->fBitmapHeap.get()) == heapSize);
132
133         // needed to create typeface playback
134         copyInfo.controller.setupPlaybacks();
135
136         newData.reset(SkNEW_ARGS(SkPictureData, (*fData, &copyInfo)));
137     }
138
139     SkPicture* clone = SkNEW_ARGS(SkPicture, (newData.detach(), fWidth, fHeight));
140     clone->fRecordWillPlayBackBitmaps = fRecordWillPlayBackBitmaps;
141     clone->fUniqueID = this->uniqueID(); // need to call method to ensure != 0
142
143     return clone;
144 #endif
145 }
146 #endif//SK_SUPPORT_LEGACY_PICTURE_CLONE
147
148 // fRecord OK
149 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) const {
150     fAccelData.reset(SkRef(data));
151 }
152
153 // fRecord OK
154 const SkPicture::AccelData* SkPicture::EXPERIMENTAL_getAccelData(
155         SkPicture::AccelData::Key key) const {
156     if (NULL != fAccelData.get() && fAccelData->getKey() == key) {
157         return fAccelData.get();
158     }
159     return NULL;
160 }
161
162 // fRecord OK
163 SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() {
164     static int32_t gNextID = 0;
165
166     int32_t id = sk_atomic_inc(&gNextID);
167     if (id >= 1 << (8 * sizeof(Domain))) {
168         SK_CRASH();
169     }
170
171     return static_cast<Domain>(id);
172 }
173
174 ///////////////////////////////////////////////////////////////////////////////
175
176 uint32_t SkPicture::OperationList::offset(int index) const {
177     SkASSERT(index < fOps.count());
178     return ((SkPictureStateTree::Draw*)fOps[index])->fOffset;
179 }
180
181 const SkMatrix& SkPicture::OperationList::matrix(int index) const {
182     SkASSERT(index < fOps.count());
183     return *((SkPictureStateTree::Draw*)fOps[index])->fMatrix;
184 }
185
186 // fRecord TODO
187 const SkPicture::OperationList* SkPicture::EXPERIMENTAL_getActiveOps(const SkIRect& queryRect) const {
188     SkASSERT(NULL != fData.get());
189     if (NULL != fData.get()) {
190         return fData->getActiveOps(queryRect);
191     }
192     return NULL;
193 }
194
195 // fRecord OK
196 void SkPicture::draw(SkCanvas* canvas, SkDrawPictureCallback* callback) const {
197     SkASSERT(NULL != canvas);
198     SkASSERT(NULL != fData.get() || NULL != fRecord.get());
199
200     if (NULL != fData.get()) {
201         SkPicturePlayback playback(this);
202         playback.draw(canvas, callback);
203     }
204     if (NULL != fRecord.get()) {
205         SkRecordDraw(*fRecord, canvas, fBBH.get(), callback);
206     }
207 }
208
209 ///////////////////////////////////////////////////////////////////////////////
210
211 #include "SkStream.h"
212
213 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
214
215 // fRecord OK
216 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) {
217     if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) {
218         return false;
219     }
220
221     if (info.fVersion < MIN_PICTURE_VERSION ||
222         info.fVersion > CURRENT_PICTURE_VERSION) {
223         return false;
224     }
225
226     return true;
227 }
228
229 // fRecord OK
230 bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
231     if (NULL == stream) {
232         return false;
233     }
234
235     // Check magic bytes.
236     SkPictInfo info;
237     SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
238     if (!stream->read(&info, sizeof(info)) || !IsValidPictInfo(info)) {
239         return false;
240     }
241
242     if (pInfo != NULL) {
243         *pInfo = info;
244     }
245     return true;
246 }
247
248 // fRecord OK
249 bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer& buffer, SkPictInfo* pInfo) {
250     // Check magic bytes.
251     SkPictInfo info;
252     SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
253     if (!buffer.readByteArray(&info, sizeof(info)) || !IsValidPictInfo(info)) {
254         return false;
255     }
256
257     if (pInfo != NULL) {
258         *pInfo = info;
259     }
260     return true;
261 }
262
263 // fRecord OK
264 SkPicture::SkPicture(SkPictureData* data, int width, int height)
265     : fData(data)
266     , fWidth(width)
267     , fHeight(height)
268     , fRecordWillPlayBackBitmaps(false) {
269     this->needsNewGenID();
270 }
271
272 // fRecord OK
273 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc proc) {
274     SkPictInfo info;
275
276     if (!InternalOnly_StreamIsSKP(stream, &info)) {
277         return NULL;
278     }
279
280     // Check to see if there is a playback to recreate.
281     if (stream->readBool()) {
282         SkPictureData* data = SkPictureData::CreateFromStream(stream, info, proc);
283         if (NULL == data) {
284             return NULL;
285         }
286
287         return SkNEW_ARGS(SkPicture, (data, info.fWidth, info.fHeight));
288     }
289
290     return NULL;
291 }
292
293 // fRecord OK
294 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
295     SkPictInfo info;
296
297     if (!InternalOnly_BufferIsSKP(buffer, &info)) {
298         return NULL;
299     }
300
301     // Check to see if there is a playback to recreate.
302     if (buffer.readBool()) {
303         SkPictureData* data = SkPictureData::CreateFromBuffer(buffer, info);
304         if (NULL == data) {
305             return NULL;
306         }
307
308         return SkNEW_ARGS(SkPicture, (data, info.fWidth, info.fHeight));
309     }
310
311     return NULL;
312 }
313
314 // fRecord OK
315 void SkPicture::createHeader(SkPictInfo* info) const {
316     // Copy magic bytes at the beginning of the header
317     SkASSERT(sizeof(kMagic) == 8);
318     SkASSERT(sizeof(kMagic) == sizeof(info->fMagic));
319     memcpy(info->fMagic, kMagic, sizeof(kMagic));
320
321     // Set picture info after magic bytes in the header
322     info->fVersion = CURRENT_PICTURE_VERSION;
323     info->fWidth = fWidth;
324     info->fHeight = fHeight;
325     info->fFlags = SkPictInfo::kCrossProcess_Flag;
326     // TODO: remove this flag, since we're always float (now)
327     info->fFlags |= SkPictInfo::kScalarIsFloat_Flag;
328
329     if (8 == sizeof(void*)) {
330         info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
331     }
332 }
333
334 // fRecord OK
335 void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
336     const SkPictureData* data = fData.get();
337
338     // If we're a new-format picture, backport to old format for serialization.
339     SkAutoTDelete<SkPicture> oldFormat;
340     if (NULL == data && NULL != fRecord.get()) {
341         oldFormat.reset(backport(*fRecord, fWidth, fHeight));
342         data = oldFormat->fData.get();
343         SkASSERT(NULL != data);
344     }
345
346     SkPictInfo info;
347     this->createHeader(&info);
348     stream->write(&info, sizeof(info));
349
350     if (NULL != data) {
351         stream->writeBool(true);
352         data->serialize(stream, encoder);
353     } else {
354         stream->writeBool(false);
355     }
356 }
357
358 // fRecord OK
359 void SkPicture::flatten(SkWriteBuffer& buffer) const {
360     const SkPictureData* data = fData.get();
361
362     // If we're a new-format picture, backport to old format for serialization.
363     SkAutoTDelete<SkPicture> oldFormat;
364     if (NULL == data && NULL != fRecord.get()) {
365         oldFormat.reset(backport(*fRecord, fWidth, fHeight));
366         data = oldFormat->fData.get();
367         SkASSERT(NULL != data);
368     }
369
370     SkPictInfo info;
371     this->createHeader(&info);
372     buffer.writeByteArray(&info, sizeof(info));
373
374     if (NULL != data) {
375         buffer.writeBool(true);
376         data->flatten(buffer);
377     } else {
378         buffer.writeBool(false);
379     }
380 }
381
382 #if SK_SUPPORT_GPU
383 // fRecord TODO
384 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **reason) const {
385     if (NULL == fData.get()) {
386         if (NULL != reason) {
387             *reason = "Missing internal data.";
388         }
389         return false;
390     }
391
392     return fData->suitableForGpuRasterization(context, reason);
393 }
394 #endif
395
396 // fRecord OK
397 bool SkPicture::willPlayBackBitmaps() const {
398     if (fRecord.get()) {
399         return fRecordWillPlayBackBitmaps;
400     }
401     if (!fData.get()) {
402         return false;
403     }
404     return fData->containsBitmaps();
405 }
406
407 // fRecord OK
408 static int32_t next_picture_generation_id() {
409     static int32_t  gPictureGenerationID = 0;
410     // do a loop in case our global wraps around, as we never want to
411     // return a 0
412     int32_t genID;
413     do {
414         genID = sk_atomic_inc(&gPictureGenerationID) + 1;
415     } while (SK_InvalidGenID == genID);
416     return genID;
417 }
418
419 // fRecord OK
420 uint32_t SkPicture::uniqueID() const {
421     if (SK_InvalidGenID == fUniqueID) {
422         fUniqueID = next_picture_generation_id();
423     }
424     return fUniqueID;
425 }
426
427 // fRecord OK
428 SkPicture::SkPicture(int width, int height, SkRecord* record, SkBBoxHierarchy* bbh)
429     : fWidth(width)
430     , fHeight(height)
431     , fRecord(record)
432     , fBBH(SkSafeRef(bbh))
433     , fRecordWillPlayBackBitmaps(SkRecordWillPlaybackBitmaps(*record)) {
434     // TODO: delay as much of this work until just before first playback?
435     if (fBBH.get()) {
436         SkRecordFillBounds(*record, fBBH.get());
437     }
438     this->needsNewGenID();
439 }
440
441 // Note that we are assuming that this entry point will only be called from
442 // one thread. Currently the only client of this method is
443 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single
444 // thread.
445 void SkPicture::addDeletionListener(DeletionListener* listener) const {
446     SkASSERT(NULL != listener);
447
448     *fDeletionListeners.append() = SkRef(listener);
449 }
450
451 void SkPicture::callDeletionListeners() {
452     for (int i = 0; i < fDeletionListeners.count(); ++i) {
453         fDeletionListeners[i]->onDeletion(this->uniqueID());
454     }
455
456     fDeletionListeners.unrefAll();
457 }
458
459 // fRecord OK
460 int SkPicture::approximateOpCount() const {
461     SkASSERT(fRecord.get() || fData.get());
462     if (fRecord.get()) {
463         return fRecord->count();
464     }
465     if (fData.get()) {
466         return fData->opCount();
467     }
468     return 0;
469 }