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