Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkPictureFlat.h
1
2 /*
3  * Copyright 2011 Google Inc.
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 #ifndef SkPictureFlat_DEFINED
9 #define SkPictureFlat_DEFINED
10
11 //#define SK_DEBUG_SIZE
12
13 #include "SkBitmapHeap.h"
14 #include "SkChecksum.h"
15 #include "SkChunkAlloc.h"
16 #include "SkReadBuffer.h"
17 #include "SkWriteBuffer.h"
18 #include "SkPaint.h"
19 #include "SkPicture.h"
20 #include "SkPtrRecorder.h"
21 #include "SkTDynamicHash.h"
22 #include "SkTRefArray.h"
23
24 enum DrawType {
25     UNUSED,
26     CLIP_PATH,
27     CLIP_REGION,
28     CLIP_RECT,
29     CLIP_RRECT,
30     CONCAT,
31     DRAW_BITMAP,
32     DRAW_BITMAP_MATRIX,
33     DRAW_BITMAP_NINE,
34     DRAW_BITMAP_RECT_TO_RECT,
35     DRAW_CLEAR,
36     DRAW_DATA,
37     DRAW_OVAL,
38     DRAW_PAINT,
39     DRAW_PATH,
40     DRAW_PICTURE,
41     DRAW_POINTS,
42     DRAW_POS_TEXT,
43     DRAW_POS_TEXT_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT
44     DRAW_POS_TEXT_H,
45     DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H
46     DRAW_RECT,
47     DRAW_RRECT,
48     DRAW_SPRITE,
49     DRAW_TEXT,
50     DRAW_TEXT_ON_PATH,
51     DRAW_TEXT_TOP_BOTTOM,   // fast variant of DRAW_TEXT
52     DRAW_VERTICES,
53     RESTORE,
54     ROTATE,
55     SAVE,
56     SAVE_LAYER,
57     SCALE,
58     SET_MATRIX,
59     SKEW,
60     TRANSLATE,
61     NOOP,
62     BEGIN_COMMENT_GROUP,
63     COMMENT,
64     END_COMMENT_GROUP,
65
66     LAST_DRAWTYPE_ENUM = END_COMMENT_GROUP
67 };
68
69 // In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
70 static const int kDRAW_BITMAP_FLAVOR = LAST_DRAWTYPE_ENUM+1;
71
72 enum DrawVertexFlags {
73     DRAW_VERTICES_HAS_TEXS    = 0x01,
74     DRAW_VERTICES_HAS_COLORS  = 0x02,
75     DRAW_VERTICES_HAS_INDICES = 0x04,
76     DRAW_VERTICES_HAS_XFER    = 0x08,
77 };
78
79 ///////////////////////////////////////////////////////////////////////////////
80 // clipparams are packed in 5 bits
81 //  doAA:1 | regionOp:4
82
83 static inline uint32_t ClipParams_pack(SkRegion::Op op, bool doAA) {
84     unsigned doAABit = doAA ? 1 : 0;
85     return (doAABit << 4) | op;
86 }
87
88 static inline SkRegion::Op ClipParams_unpackRegionOp(uint32_t packed) {
89     return (SkRegion::Op)(packed & 0xF);
90 }
91
92 static inline bool ClipParams_unpackDoAA(uint32_t packed) {
93     return SkToBool((packed >> 4) & 1);
94 }
95
96 ///////////////////////////////////////////////////////////////////////////////
97
98 class SkTypefacePlayback {
99 public:
100     SkTypefacePlayback();
101     virtual ~SkTypefacePlayback();
102
103     int count() const { return fCount; }
104
105     void reset(const SkRefCntSet*);
106
107     void setCount(int count);
108     SkRefCnt* set(int index, SkRefCnt*);
109
110     void setupBuffer(SkReadBuffer& buffer) const {
111         buffer.setTypefaceArray((SkTypeface**)fArray, fCount);
112     }
113
114 protected:
115     int fCount;
116     SkRefCnt** fArray;
117 };
118
119 class SkFactoryPlayback {
120 public:
121     SkFactoryPlayback(int count) : fCount(count) {
122         fArray = SkNEW_ARRAY(SkFlattenable::Factory, count);
123     }
124
125     ~SkFactoryPlayback() {
126         SkDELETE_ARRAY(fArray);
127     }
128
129     SkFlattenable::Factory* base() const { return fArray; }
130
131     void setupBuffer(SkReadBuffer& buffer) const {
132         buffer.setFactoryPlayback(fArray, fCount);
133     }
134
135 private:
136     int fCount;
137     SkFlattenable::Factory* fArray;
138 };
139
140 ///////////////////////////////////////////////////////////////////////////////
141 //
142 //
143 // The following templated classes provide an efficient way to store and compare
144 // objects that have been flattened (i.e. serialized in an ordered binary
145 // format).
146 //
147 // SkFlatData:       is a simple indexable container for the flattened data
148 //                   which is agnostic to the type of data is is indexing. It is
149 //                   also responsible for flattening/unflattening objects but
150 //                   details of that operation are hidden in the provided traits
151 // SkFlatDictionary: is an abstract templated dictionary that maintains a
152 //                   searchable set of SkFlatData objects of type T.
153 // SkFlatController: is an interface provided to SkFlatDictionary which handles
154 //                   allocation (and unallocation in some cases). It also holds
155 //                   ref count recorders and the like.
156 //
157 // NOTE: any class that wishes to be used in conjunction with SkFlatDictionary must subclass the
158 // dictionary and provide the necessary flattening traits.  SkFlatController must also be
159 // implemented, or SkChunkFlatController can be used to use an SkChunkAllocator and never do
160 // replacements.
161 //
162 //
163 ///////////////////////////////////////////////////////////////////////////////
164
165 class SkFlatData;
166
167 class SkFlatController : public SkRefCnt {
168 public:
169     SK_DECLARE_INST_COUNT(SkFlatController)
170
171     SkFlatController(uint32_t writeBufferFlags = 0);
172     virtual ~SkFlatController();
173     /**
174      * Return a new block of memory for the SkFlatDictionary to use.
175      * This memory is owned by the controller and has the same lifetime unless you
176      * call unalloc(), in which case it may be freed early.
177      */
178     virtual void* allocThrow(size_t bytes) = 0;
179
180     /**
181      * Hint that this block, which was allocated with allocThrow, is no longer needed.
182      * The implementation may choose to free this memory any time beteween now and destruction.
183      */
184     virtual void unalloc(void* ptr) = 0;
185
186     /**
187      * Used during creation and unflattening of SkFlatData objects. If the
188      * objects being flattened contain bitmaps they are stored in this heap
189      * and the flattenable stores the index to the bitmap on the heap.
190      * This should be set by the protected setBitmapHeap.
191      */
192     SkBitmapHeap* getBitmapHeap() { return fBitmapHeap; }
193
194     /**
195      * Used during creation of SkFlatData objects. If a typeface recorder is
196      * required to flatten the objects being flattened (i.e. for SkPaints), this
197      * should be set by the protected setTypefaceSet.
198      */
199     SkRefCntSet* getTypefaceSet() { return fTypefaceSet; }
200
201     /**
202      * Used during unflattening of the SkFlatData objects in the
203      * SkFlatDictionary. Needs to be set by the protected setTypefacePlayback
204      * and needs to be reset to the SkRefCntSet passed to setTypefaceSet.
205      */
206     SkTypefacePlayback* getTypefacePlayback() { return fTypefacePlayback; }
207
208     /**
209      * Optional factory recorder used during creation of SkFlatData objects. Set
210      * using the protected method setNamedFactorySet.
211      */
212     SkNamedFactorySet* getNamedFactorySet() { return fFactorySet; }
213
214     /**
215      * Flags to use during creation of SkFlatData objects. Defaults to zero.
216      */
217     uint32_t getWriteBufferFlags() { return fWriteBufferFlags; }
218
219 protected:
220     /**
221      * Set an SkBitmapHeap to be used to store/read SkBitmaps. Ref counted.
222      */
223     void setBitmapHeap(SkBitmapHeap*);
224
225     /**
226      * Set an SkRefCntSet to be used to store SkTypefaces during flattening. Ref
227      * counted.
228      */
229     void setTypefaceSet(SkRefCntSet*);
230
231     /**
232      * Set an SkTypefacePlayback to be used to find references to SkTypefaces
233      * during unflattening. Should be reset to the set provided to
234      * setTypefaceSet.
235      */
236     void setTypefacePlayback(SkTypefacePlayback*);
237
238     /**
239      * Set an SkNamedFactorySet to be used to store Factorys and their
240      * corresponding names during flattening. Ref counted. Returns the same
241      * set as a convenience.
242      */
243     SkNamedFactorySet* setNamedFactorySet(SkNamedFactorySet*);
244
245 private:
246     SkBitmapHeap*       fBitmapHeap;
247     SkRefCntSet*        fTypefaceSet;
248     SkTypefacePlayback* fTypefacePlayback;
249     SkNamedFactorySet*  fFactorySet;
250     const uint32_t      fWriteBufferFlags;
251
252     typedef SkRefCnt INHERITED;
253 };
254
255 class SkFlatData {
256 public:
257     // Flatten obj into an SkFlatData with this index.  controller owns the SkFlatData*.
258     template <typename Traits, typename T>
259     static SkFlatData* Create(SkFlatController* controller, const T& obj, int index) {
260         // A buffer of 256 bytes should fit most paints, regions, and matrices.
261         uint32_t storage[64];
262         SkWriteBuffer buffer(storage, sizeof(storage), controller->getWriteBufferFlags());
263
264         buffer.setBitmapHeap(controller->getBitmapHeap());
265         buffer.setTypefaceRecorder(controller->getTypefaceSet());
266         buffer.setNamedFactoryRecorder(controller->getNamedFactorySet());
267
268         Traits::flatten(buffer, obj);
269         size_t size = buffer.bytesWritten();
270         SkASSERT(SkIsAlign4(size));
271
272         // Allocate enough memory to hold SkFlatData struct and the flat data itself.
273         size_t allocSize = sizeof(SkFlatData) + size;
274         SkFlatData* result = (SkFlatData*) controller->allocThrow(allocSize);
275
276         // Put the serialized contents into the data section of the new allocation.
277         buffer.writeToMemory(result->data());
278         // Stamp the index, size and checksum in the header.
279         result->stampHeader(index, SkToS32(size));
280         return result;
281     }
282
283     // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps and fonts if given
284     template <typename Traits, typename T>
285     void unflatten(T* result,
286                    SkBitmapHeap* bitmapHeap = NULL,
287                    SkTypefacePlayback* facePlayback = NULL) const {
288         SkReadBuffer buffer(this->data(), fFlatSize);
289
290         if (bitmapHeap) {
291             buffer.setBitmapStorage(bitmapHeap);
292         }
293         if (facePlayback) {
294             facePlayback->setupBuffer(buffer);
295         }
296
297         Traits::unflatten(buffer, result);
298         SkASSERT(fFlatSize == (int32_t)buffer.offset());
299     }
300
301     // Do these contain the same data?  Ignores index() and topBot().
302     bool operator==(const SkFlatData& that) const {
303         if (this->checksum() != that.checksum() || this->flatSize() != that.flatSize()) {
304             return false;
305         }
306         return memcmp(this->data(), that.data(), this->flatSize()) == 0;
307     }
308
309     int index() const { return fIndex; }
310     const uint8_t* data() const { return (const uint8_t*)this + sizeof(*this); }
311     size_t flatSize() const { return fFlatSize; }
312     uint32_t checksum() const { return fChecksum; }
313
314     // Returns true if fTopBot[] has been recorded.
315     bool isTopBotWritten() const {
316         return !SkScalarIsNaN(fTopBot[0]);
317     }
318
319     // Returns fTopBot array, so it can be passed to a routine to compute them.
320     // For efficiency, we assert that fTopBot have not been recorded yet.
321     SkScalar* writableTopBot() const {
322         SkASSERT(!this->isTopBotWritten());
323         return fTopBot;
324     }
325
326     // Return the topbot[] after it has been recorded.
327     const SkScalar* topBot() const {
328         SkASSERT(this->isTopBotWritten());
329         return fTopBot;
330     }
331
332 private:
333     // For SkTDynamicHash.
334     static const SkFlatData& Identity(const SkFlatData& flat) { return flat; }
335     static uint32_t Hash(const SkFlatData& flat) { return flat.checksum(); }
336     static bool Equal(const SkFlatData& a, const SkFlatData& b) { return a == b; }
337
338     void setIndex(int index) { fIndex = index; }
339     uint8_t* data() { return (uint8_t*)this + sizeof(*this); }
340
341     // This assumes the payload flat data has already been written and does not modify it.
342     void stampHeader(int index, int32_t size) {
343         SkASSERT(SkIsAlign4(size));
344         fIndex     = index;
345         fFlatSize  = size;
346         fTopBot[0] = SK_ScalarNaN;  // Mark as unwritten.
347         fChecksum  = SkChecksum::Compute((uint32_t*)this->data(), size);
348     }
349
350     int fIndex;
351     int32_t fFlatSize;
352     uint32_t fChecksum;
353     mutable SkScalar fTopBot[2];  // Cache of FontMetrics fTop, fBottom.  Starts as [NaN,?].
354     // uint32_t flattenedData[] implicitly hangs off the end.
355
356     template <typename T, typename Traits> friend class SkFlatDictionary;
357 };
358
359 template <typename T, typename Traits>
360 class SkFlatDictionary {
361 public:
362     explicit SkFlatDictionary(SkFlatController* controller)
363     : fController(SkRef(controller))
364     , fScratch(controller->getWriteBufferFlags())
365     , fReady(false) {
366         this->reset();
367     }
368
369     /**
370      * Clears the dictionary of all entries. However, it does NOT free the
371      * memory that was allocated for each entry (that's owned by controller).
372      */
373     void reset() {
374         fIndexedData.rewind();
375     }
376
377     int count() const {
378         SkASSERT(fHash.count() == fIndexedData.count());
379         return fHash.count();
380     }
381
382     // For testing only.  Index is zero-based.
383     const SkFlatData* operator[](int index) {
384         return fIndexedData[index];
385     }
386
387     /**
388      * Given an element of type T return its 1-based index in the dictionary. If
389      * the element wasn't previously in the dictionary it is automatically
390      * added.
391      *
392      */
393     int find(const T& element) {
394         return this->findAndReturnFlat(element)->index();
395     }
396
397     /**
398      * Similar to find. Allows the caller to specify an SkFlatData to replace in
399      * the case of an add. Also tells the caller whether a new SkFlatData was
400      * added and whether the old one was replaced. The parameters added and
401      * replaced are required to be non-NULL. Rather than returning the index of
402      * the entry in the dictionary, it returns the actual SkFlatData.
403      */
404     const SkFlatData* findAndReplace(const T& element,
405                                      const SkFlatData* toReplace,
406                                      bool* added,
407                                      bool* replaced) {
408         SkASSERT(added != NULL && replaced != NULL);
409
410         const int oldCount = this->count();
411         SkFlatData* flat = this->findAndReturnMutableFlat(element);
412         *added = this->count() > oldCount;
413
414         // If we don't want to replace anything, we're done.
415         if (!*added || toReplace == NULL) {
416             *replaced = false;
417             return flat;
418         }
419
420         // If we don't have the thing to replace, we're done.
421         const SkFlatData* found = fHash.find(*toReplace);
422         if (found == NULL) {
423             *replaced = false;
424             return flat;
425         }
426
427         // findAndReturnMutableFlat put flat at the back.  Swap it into found->index() instead.
428         // indices in SkFlatData are 1-based, while fIndexedData is 0-based.  Watch out!
429         SkASSERT(flat->index() == this->count());
430         flat->setIndex(found->index());
431         fIndexedData.removeShuffle(found->index()-1);
432         SkASSERT(flat == fIndexedData[found->index()-1]);
433
434         // findAndReturnMutableFlat already called fHash.add(), so we just clean up the old entry.
435         fHash.remove(*found);
436         fController->unalloc((void*)found);
437         SkASSERT(this->count() == oldCount);
438
439         *replaced = true;
440         return flat;
441     }
442
443     /**
444      *  Unflatten the objects and return them in SkTRefArray, or return NULL
445      *  if there no objects.  Caller takes ownership of result.
446      */
447     SkTRefArray<T>* unflattenToArray() const {
448         const int count = this->count();
449         if (count == 0) {
450             return NULL;
451         }
452         SkTRefArray<T>* array = SkTRefArray<T>::Create(count);
453         for (int i = 0; i < count; i++) {
454             this->unflatten(&array->writableAt(i), fIndexedData[i]);
455         }
456         return array;
457     }
458
459     /**
460      * Unflatten the specific object at the given index.
461      * Caller takes ownership of the result.
462      */
463     T* unflatten(int index) const {
464         // index is 1-based, while fIndexedData is 0-based.
465         const SkFlatData* element = fIndexedData[index-1];
466         SkASSERT(index == element->index());
467
468         T* dst = new T;
469         this->unflatten(dst, element);
470         return dst;
471     }
472
473     /**
474      * Find or insert a flattened version of element into the dictionary.
475      * Caller does not take ownership of the result.  This will not return NULL.
476      */
477     const SkFlatData* findAndReturnFlat(const T& element) {
478         return this->findAndReturnMutableFlat(element);
479     }
480
481 private:
482     // We have to delay fScratch's initialization until its first use; fController might not
483     // be fully set up by the time we get it in the constructor.
484     void lazyInit() {
485         if (fReady) {
486             return;
487         }
488
489         // Without a bitmap heap, we'll flatten bitmaps into paints.  That's never what you want.
490         SkASSERT(fController->getBitmapHeap() != NULL);
491         fScratch.setBitmapHeap(fController->getBitmapHeap());
492         fScratch.setTypefaceRecorder(fController->getTypefaceSet());
493         fScratch.setNamedFactoryRecorder(fController->getNamedFactorySet());
494         fReady = true;
495     }
496
497     // As findAndReturnFlat, but returns a mutable pointer for internal use.
498     SkFlatData* findAndReturnMutableFlat(const T& element) {
499         // Only valid until the next call to resetScratch().
500         const SkFlatData& scratch = this->resetScratch(element, this->count()+1);
501
502         SkFlatData* candidate = fHash.find(scratch);
503         if (candidate != NULL) return candidate;
504
505         SkFlatData* detached = this->detachScratch();
506         fHash.add(detached);
507         *fIndexedData.append() = detached;
508         SkASSERT(fIndexedData.top()->index() == this->count());
509         return detached;
510     }
511
512     // This reference is valid only until the next call to resetScratch() or detachScratch().
513     const SkFlatData& resetScratch(const T& element, int index) {
514         this->lazyInit();
515
516         // Layout of fScratch: [ SkFlatData header, 20 bytes ] [ data ..., 4-byte aligned ]
517         fScratch.reset();
518         fScratch.reserve(sizeof(SkFlatData));
519         Traits::flatten(fScratch, element);
520         const size_t dataSize = fScratch.bytesWritten() - sizeof(SkFlatData);
521
522         // Reinterpret data in fScratch as an SkFlatData.
523         SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArray();
524         SkASSERT(scratch != NULL);
525         scratch->stampHeader(index, dataSize);
526         return *scratch;
527     }
528
529     // This result is owned by fController and lives as long as it does (unless unalloc'd).
530     SkFlatData* detachScratch() {
531         // Allocate a new SkFlatData exactly big enough to hold our current scratch.
532         // We use the controller for this allocation to extend the allocation's lifetime and allow
533         // the controller to do whatever memory management it wants.
534         SkFlatData* detached = (SkFlatData*)fController->allocThrow(fScratch.bytesWritten());
535
536         // Copy scratch into the new SkFlatData.
537         SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArray();
538         SkASSERT(scratch != NULL);
539         memcpy(detached, scratch, fScratch.bytesWritten());
540
541         // We can now reuse fScratch, and detached will live until fController dies.
542         return detached;
543     }
544
545     void unflatten(T* dst, const SkFlatData* element) const {
546         element->unflatten<Traits>(dst,
547                                    fController->getBitmapHeap(),
548                                    fController->getTypefacePlayback());
549     }
550
551     // All SkFlatData* stored in fIndexedData and fHash are owned by the controller.
552     SkAutoTUnref<SkFlatController> fController;
553     SkWriteBuffer fScratch;
554     bool fReady;
555
556     // For index -> SkFlatData.  0-based, while all indices in the API are 1-based.  Careful!
557     SkTDArray<const SkFlatData*> fIndexedData;
558
559     // For SkFlatData -> cached SkFlatData, which has index().
560     SkTDynamicHash<SkFlatData, SkFlatData,
561                    SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fHash;
562 };
563
564 struct SkPaintTraits {
565     static void flatten(SkWriteBuffer& buffer, const SkPaint& paint) {
566         paint.flatten(buffer);
567     }
568     static void unflatten(SkReadBuffer& buffer, SkPaint* paint) {
569         paint->unflatten(buffer);
570     }
571 };
572 typedef SkFlatDictionary<SkPaint, SkPaintTraits> SkPaintDictionary;
573
574 class SkChunkFlatController : public SkFlatController {
575 public:
576     SkChunkFlatController(size_t minSize)
577     : fHeap(minSize)
578     , fTypefaceSet(SkNEW(SkRefCntSet))
579     , fLastAllocated(NULL) {
580         this->setTypefaceSet(fTypefaceSet);
581         this->setTypefacePlayback(&fTypefacePlayback);
582     }
583
584     virtual void* allocThrow(size_t bytes) SK_OVERRIDE {
585         fLastAllocated = fHeap.allocThrow(bytes);
586         return fLastAllocated;
587     }
588
589     virtual void unalloc(void* ptr) SK_OVERRIDE {
590         // fHeap can only free a pointer if it was the last one allocated.  Otherwise, we'll just
591         // have to wait until fHeap is destroyed.
592         if (ptr == fLastAllocated) (void)fHeap.unalloc(ptr);
593     }
594
595     void setupPlaybacks() const {
596         fTypefacePlayback.reset(fTypefaceSet.get());
597     }
598
599     void setBitmapStorage(SkBitmapHeap* heap) {
600         this->setBitmapHeap(heap);
601     }
602
603 private:
604     SkChunkAlloc               fHeap;
605     SkAutoTUnref<SkRefCntSet>  fTypefaceSet;
606     void*                      fLastAllocated;
607     mutable SkTypefacePlayback fTypefacePlayback;
608 };
609
610 #endif