epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 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 | */ |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 8 | #ifndef SkPictureFlat_DEFINED |
| 9 | #define SkPictureFlat_DEFINED |
| 10 | |
reed@google.com | e2589ae | 2012-07-10 19:38:01 +0000 | [diff] [blame] | 11 | //#define SK_DEBUG_SIZE |
| 12 | |
djsollen@google.com | 21830d9 | 2012-08-07 19:49:41 +0000 | [diff] [blame] | 13 | #include "SkBitmapHeap.h" |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 14 | #include "SkChecksum.h" |
| 15 | #include "SkChunkAlloc.h" |
commit-bot@chromium.org | 8b0e8ac | 2014-01-30 18:58:24 +0000 | [diff] [blame] | 16 | #include "SkReadBuffer.h" |
| 17 | #include "SkWriteBuffer.h" |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 18 | #include "SkPaint.h" |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 19 | #include "SkPicture.h" |
| 20 | #include "SkPtrRecorder.h" |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 21 | #include "SkTDynamicHash.h" |
reed@google.com | f4cc187 | 2012-07-23 15:04:45 +0000 | [diff] [blame] | 22 | #include "SkTRefArray.h" |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 23 | |
| 24 | enum DrawType { |
| 25 | UNUSED, |
| 26 | CLIP_PATH, |
| 27 | CLIP_REGION, |
| 28 | CLIP_RECT, |
reed@google.com | 4ed0fb7 | 2012-12-12 20:48:18 +0000 | [diff] [blame] | 29 | CLIP_RRECT, |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 30 | CONCAT, |
| 31 | DRAW_BITMAP, |
| 32 | DRAW_BITMAP_MATRIX, |
reed@google.com | f0b5e11 | 2011-09-07 11:57:34 +0000 | [diff] [blame] | 33 | DRAW_BITMAP_NINE, |
reed@google.com | 7112173 | 2012-09-18 15:14:33 +0000 | [diff] [blame] | 34 | DRAW_BITMAP_RECT_TO_RECT, |
reed@google.com | 2a98181 | 2011-04-14 18:59:28 +0000 | [diff] [blame] | 35 | DRAW_CLEAR, |
reed@android.com | cb60844 | 2009-12-04 21:32:27 +0000 | [diff] [blame] | 36 | DRAW_DATA, |
reed@google.com | 4ed0fb7 | 2012-12-12 20:48:18 +0000 | [diff] [blame] | 37 | DRAW_OVAL, |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 38 | DRAW_PAINT, |
| 39 | DRAW_PATH, |
| 40 | DRAW_PICTURE, |
| 41 | DRAW_POINTS, |
| 42 | DRAW_POS_TEXT, |
reed@google.com | 9efd9a0 | 2012-01-30 15:41:43 +0000 | [diff] [blame] | 43 | DRAW_POS_TEXT_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 44 | DRAW_POS_TEXT_H, |
| 45 | DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H |
| 46 | DRAW_RECT, |
reed@google.com | 4ed0fb7 | 2012-12-12 20:48:18 +0000 | [diff] [blame] | 47 | DRAW_RRECT, |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 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, |
reed@android.com | 6e073b9 | 2009-01-06 15:03:30 +0000 | [diff] [blame] | 58 | SET_MATRIX, |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 59 | SKEW, |
reed@google.com | ffacd3c | 2012-08-30 15:31:23 +0000 | [diff] [blame] | 60 | TRANSLATE, |
robertphillips@google.com | e4ce5b8 | 2013-02-15 17:19:15 +0000 | [diff] [blame] | 61 | NOOP, |
robertphillips@google.com | 0a4805e | 2013-05-29 13:24:23 +0000 | [diff] [blame] | 62 | BEGIN_COMMENT_GROUP, |
| 63 | COMMENT, |
| 64 | END_COMMENT_GROUP, |
reed@google.com | ffacd3c | 2012-08-30 15:31:23 +0000 | [diff] [blame] | 65 | |
robertphillips@google.com | 0a4805e | 2013-05-29 13:24:23 +0000 | [diff] [blame] | 66 | LAST_DRAWTYPE_ENUM = END_COMMENT_GROUP |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 67 | }; |
| 68 | |
robertphillips@google.com | b8f9610 | 2013-03-12 15:39:44 +0000 | [diff] [blame] | 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 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 72 | enum DrawVertexFlags { |
| 73 | DRAW_VERTICES_HAS_TEXS = 0x01, |
| 74 | DRAW_VERTICES_HAS_COLORS = 0x02, |
reed@google.com | 85e143c | 2013-12-30 15:51:25 +0000 | [diff] [blame] | 75 | DRAW_VERTICES_HAS_INDICES = 0x04, |
| 76 | DRAW_VERTICES_HAS_XFER = 0x08, |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 77 | }; |
| 78 | |
reed@google.com | 83ab495 | 2011-11-11 21:34:54 +0000 | [diff] [blame] | 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 | |
djsollen@google.com | 21830d9 | 2012-08-07 19:49:41 +0000 | [diff] [blame] | 98 | class SkTypefacePlayback { |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 99 | public: |
djsollen@google.com | 21830d9 | 2012-08-07 19:49:41 +0000 | [diff] [blame] | 100 | SkTypefacePlayback(); |
| 101 | virtual ~SkTypefacePlayback(); |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 102 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 103 | int count() const { return fCount; } |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 104 | |
mike@reedtribe.org | e9e08cc | 2011-04-29 01:44:52 +0000 | [diff] [blame] | 105 | void reset(const SkRefCntSet*); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 106 | |
| 107 | void setCount(int count); |
| 108 | SkRefCnt* set(int index, SkRefCnt*); |
| 109 | |
commit-bot@chromium.org | 8b0e8ac | 2014-01-30 18:58:24 +0000 | [diff] [blame] | 110 | void setupBuffer(SkReadBuffer& buffer) const { |
djsollen@google.com | 21830d9 | 2012-08-07 19:49:41 +0000 | [diff] [blame] | 111 | buffer.setTypefaceArray((SkTypeface**)fArray, fCount); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 112 | } |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 113 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 114 | protected: |
| 115 | int fCount; |
| 116 | SkRefCnt** fArray; |
| 117 | }; |
| 118 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 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 | } |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 128 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 129 | SkFlattenable::Factory* base() const { return fArray; } |
| 130 | |
commit-bot@chromium.org | 8b0e8ac | 2014-01-30 18:58:24 +0000 | [diff] [blame] | 131 | void setupBuffer(SkReadBuffer& buffer) const { |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 132 | buffer.setFactoryPlayback(fArray, fCount); |
| 133 | } |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 134 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 135 | private: |
| 136 | int fCount; |
| 137 | SkFlattenable::Factory* fArray; |
| 138 | }; |
| 139 | |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 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 |
commit-bot@chromium.org | fed2ab6 | 2014-01-23 15:16:05 +0000 | [diff] [blame] | 150 | // details of that operation are hidden in the provided traits |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 151 | // SkFlatDictionary: is an abstract templated dictionary that maintains a |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 152 | // searchable set of SkFlatData objects of type T. |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 153 | // SkFlatController: is an interface provided to SkFlatDictionary which handles |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 154 | // allocation (and unallocation in some cases). It also holds |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 155 | // ref count recorders and the like. |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 156 | // |
commit-bot@chromium.org | fed2ab6 | 2014-01-23 15:16:05 +0000 | [diff] [blame] | 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. |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 161 | // |
| 162 | // |
| 163 | /////////////////////////////////////////////////////////////////////////////// |
| 164 | |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 165 | class SkFlatData; |
| 166 | |
| 167 | class SkFlatController : public SkRefCnt { |
| 168 | public: |
robertphillips@google.com | a22e211 | 2012-08-16 14:58:06 +0000 | [diff] [blame] | 169 | SK_DECLARE_INST_COUNT(SkFlatController) |
| 170 | |
commit-bot@chromium.org | a2bd2d1 | 2014-01-30 22:16:32 +0000 | [diff] [blame] | 171 | SkFlatController(uint32_t writeBufferFlags = 0); |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 172 | virtual ~SkFlatController(); |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 173 | /** |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 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. |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 177 | */ |
| 178 | virtual void* allocThrow(size_t bytes) = 0; |
| 179 | |
| 180 | /** |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 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. |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 183 | */ |
| 184 | virtual void unalloc(void* ptr) = 0; |
scroggo@google.com | 0c3e5fe | 2012-08-01 19:34:20 +0000 | [diff] [blame] | 185 | |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 186 | /** |
djsollen@google.com | 21830d9 | 2012-08-07 19:49:41 +0000 | [diff] [blame] | 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. |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 191 | */ |
djsollen@google.com | 21830d9 | 2012-08-07 19:49:41 +0000 | [diff] [blame] | 192 | SkBitmapHeap* getBitmapHeap() { return fBitmapHeap; } |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 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 | |
scroggo@google.com | 664fab1 | 2012-08-14 19:22:05 +0000 | [diff] [blame] | 214 | /** |
| 215 | * Flags to use during creation of SkFlatData objects. Defaults to zero. |
| 216 | */ |
| 217 | uint32_t getWriteBufferFlags() { return fWriteBufferFlags; } |
| 218 | |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 219 | protected: |
| 220 | /** |
djsollen@google.com | 21830d9 | 2012-08-07 19:49:41 +0000 | [diff] [blame] | 221 | * Set an SkBitmapHeap to be used to store/read SkBitmaps. Ref counted. |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 222 | */ |
djsollen@google.com | 21830d9 | 2012-08-07 19:49:41 +0000 | [diff] [blame] | 223 | void setBitmapHeap(SkBitmapHeap*); |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 224 | |
| 225 | /** |
| 226 | * Set an SkRefCntSet to be used to store SkTypefaces during flattening. Ref |
| 227 | * counted. |
| 228 | */ |
| 229 | void setTypefaceSet(SkRefCntSet*); |
| 230 | |
| 231 | /** |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 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: |
djsollen@google.com | 21830d9 | 2012-08-07 19:49:41 +0000 | [diff] [blame] | 246 | SkBitmapHeap* fBitmapHeap; |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 247 | SkRefCntSet* fTypefaceSet; |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 248 | SkTypefacePlayback* fTypefacePlayback; |
| 249 | SkNamedFactorySet* fFactorySet; |
commit-bot@chromium.org | a2bd2d1 | 2014-01-30 22:16:32 +0000 | [diff] [blame] | 250 | const uint32_t fWriteBufferFlags; |
robertphillips@google.com | a22e211 | 2012-08-16 14:58:06 +0000 | [diff] [blame] | 251 | |
| 252 | typedef SkRefCnt INHERITED; |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 253 | }; |
| 254 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 255 | class SkFlatData { |
| 256 | public: |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 257 | // Flatten obj into an SkFlatData with this index. controller owns the SkFlatData*. |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 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]; |
commit-bot@chromium.org | a2bd2d1 | 2014-01-30 22:16:32 +0000 | [diff] [blame] | 262 | SkWriteBuffer buffer(storage, sizeof(storage), controller->getWriteBufferFlags()); |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 263 | |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 264 | buffer.setBitmapHeap(controller->getBitmapHeap()); |
| 265 | buffer.setTypefaceRecorder(controller->getTypefaceSet()); |
| 266 | buffer.setNamedFactoryRecorder(controller->getNamedFactorySet()); |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 267 | |
| 268 | Traits::flatten(buffer, obj); |
commit-bot@chromium.org | 8b0e8ac | 2014-01-30 18:58:24 +0000 | [diff] [blame] | 269 | size_t size = buffer.bytesWritten(); |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 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. |
reed@google.com | 7fa2a65 | 2014-01-27 13:42:58 +0000 | [diff] [blame] | 279 | result->stampHeader(index, SkToS32(size)); |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 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, |
djsollen@google.com | 21830d9 | 2012-08-07 19:49:41 +0000 | [diff] [blame] | 286 | SkBitmapHeap* bitmapHeap = NULL, |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 287 | SkTypefacePlayback* facePlayback = NULL) const { |
commit-bot@chromium.org | 8b0e8ac | 2014-01-30 18:58:24 +0000 | [diff] [blame] | 288 | SkReadBuffer buffer(this->data(), fFlatSize); |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 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 | } |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 300 | |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 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; |
reed@google.com | e2589ae | 2012-07-10 19:38:01 +0000 | [diff] [blame] | 307 | } |
| 308 | |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 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. |
bungeman@google.com | 148a396 | 2013-01-17 20:19:13 +0000 | [diff] [blame] | 315 | bool isTopBotWritten() const { |
| 316 | return !SkScalarIsNaN(fTopBot[0]); |
reed@google.com | 4595426 | 2012-12-07 17:14:40 +0000 | [diff] [blame] | 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. |
junov@chromium.org | f3b1223 | 2013-01-22 17:50:47 +0000 | [diff] [blame] | 321 | SkScalar* writableTopBot() const { |
bungeman@google.com | 148a396 | 2013-01-17 20:19:13 +0000 | [diff] [blame] | 322 | SkASSERT(!this->isTopBotWritten()); |
reed@google.com | 4595426 | 2012-12-07 17:14:40 +0000 | [diff] [blame] | 323 | return fTopBot; |
| 324 | } |
| 325 | |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 326 | // Return the topbot[] after it has been recorded. |
reed@google.com | 4595426 | 2012-12-07 17:14:40 +0000 | [diff] [blame] | 327 | const SkScalar* topBot() const { |
bungeman@google.com | 148a396 | 2013-01-17 20:19:13 +0000 | [diff] [blame] | 328 | SkASSERT(this->isTopBotWritten()); |
reed@google.com | 4595426 | 2012-12-07 17:14:40 +0000 | [diff] [blame] | 329 | return fTopBot; |
| 330 | } |
| 331 | |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 332 | private: |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 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 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 350 | int fIndex; |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 351 | int32_t fFlatSize; |
junov@chromium.org | ef76060 | 2012-06-27 20:03:16 +0000 | [diff] [blame] | 352 | uint32_t fChecksum; |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 353 | mutable SkScalar fTopBot[2]; // Cache of FontMetrics fTop, fBottom. Starts as [NaN,?]. |
| 354 | // uint32_t flattenedData[] implicitly hangs off the end. |
reed@google.com | b4ed017 | 2012-07-10 13:29:52 +0000 | [diff] [blame] | 355 | |
commit-bot@chromium.org | 1938242 | 2014-01-14 20:51:26 +0000 | [diff] [blame] | 356 | template <typename T, typename Traits> friend class SkFlatDictionary; |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 357 | }; |
| 358 | |
commit-bot@chromium.org | 1938242 | 2014-01-14 20:51:26 +0000 | [diff] [blame] | 359 | template <typename T, typename Traits> |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 360 | class SkFlatDictionary { |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 361 | public: |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 362 | explicit SkFlatDictionary(SkFlatController* controller) |
| 363 | : fController(SkRef(controller)) |
commit-bot@chromium.org | a2bd2d1 | 2014-01-30 22:16:32 +0000 | [diff] [blame] | 364 | , fScratch(controller->getWriteBufferFlags()) |
commit-bot@chromium.org | ff007e8 | 2014-01-09 16:45:45 +0000 | [diff] [blame] | 365 | , fReady(false) { |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 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(); |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 375 | } |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 376 | |
skia.committer@gmail.com | 0f12e1f | 2013-03-11 07:01:23 +0000 | [diff] [blame] | 377 | int count() const { |
commit-bot@chromium.org | 6e83423 | 2014-01-10 20:13:09 +0000 | [diff] [blame] | 378 | SkASSERT(fHash.count() == fIndexedData.count()); |
commit-bot@chromium.org | f85251c | 2014-01-10 19:37:00 +0000 | [diff] [blame] | 379 | return fHash.count(); |
robertphillips@google.com | 7d3451b | 2013-03-10 17:16:41 +0000 | [diff] [blame] | 380 | } |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 381 | |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 382 | // For testing only. Index is zero-based. |
| 383 | const SkFlatData* operator[](int index) { |
commit-bot@chromium.org | 6e83423 | 2014-01-10 20:13:09 +0000 | [diff] [blame] | 384 | return fIndexedData[index]; |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 385 | } |
| 386 | |
| 387 | /** |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 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 | * |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 392 | */ |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 393 | int find(const T& element) { |
| 394 | return this->findAndReturnFlat(element)->index(); |
reed@google.com | 83ca337 | 2012-07-12 15:27:54 +0000 | [diff] [blame] | 395 | } |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 396 | |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 397 | /** |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 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. |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 403 | */ |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 404 | const SkFlatData* findAndReplace(const T& element, |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 405 | const SkFlatData* toReplace, |
| 406 | bool* added, |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 407 | bool* replaced) { |
| 408 | SkASSERT(added != NULL && replaced != NULL); |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 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; |
reed@google.com | 83ca337 | 2012-07-12 15:27:54 +0000 | [diff] [blame] | 418 | } |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 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 | |
commit-bot@chromium.org | f85251c | 2014-01-10 19:37:00 +0000 | [diff] [blame] | 427 | // findAndReturnMutableFlat put flat at the back. Swap it into found->index() instead. |
commit-bot@chromium.org | 6e83423 | 2014-01-10 20:13:09 +0000 | [diff] [blame] | 428 | // indices in SkFlatData are 1-based, while fIndexedData is 0-based. Watch out! |
commit-bot@chromium.org | f85251c | 2014-01-10 19:37:00 +0000 | [diff] [blame] | 429 | SkASSERT(flat->index() == this->count()); |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 430 | flat->setIndex(found->index()); |
commit-bot@chromium.org | 6e83423 | 2014-01-10 20:13:09 +0000 | [diff] [blame] | 431 | fIndexedData.removeShuffle(found->index()-1); |
| 432 | SkASSERT(flat == fIndexedData[found->index()-1]); |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 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; |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 440 | return flat; |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 441 | } |
| 442 | |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 443 | /** |
reed@google.com | f4cc187 | 2012-07-23 15:04:45 +0000 | [diff] [blame] | 444 | * Unflatten the objects and return them in SkTRefArray, or return NULL |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 445 | * if there no objects. Caller takes ownership of result. |
reed@google.com | f4cc187 | 2012-07-23 15:04:45 +0000 | [diff] [blame] | 446 | */ |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 447 | SkTRefArray<T>* unflattenToArray() const { |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 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++) { |
commit-bot@chromium.org | 6e83423 | 2014-01-10 20:13:09 +0000 | [diff] [blame] | 454 | this->unflatten(&array->writableAt(i), fIndexedData[i]); |
reed@google.com | f4cc187 | 2012-07-23 15:04:45 +0000 | [diff] [blame] | 455 | } |
| 456 | return array; |
| 457 | } |
| 458 | |
robertphillips@google.com | e37ad35 | 2013-03-01 19:44:30 +0000 | [diff] [blame] | 459 | /** |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 460 | * Unflatten the specific object at the given index. |
| 461 | * Caller takes ownership of the result. |
robertphillips@google.com | e37ad35 | 2013-03-01 19:44:30 +0000 | [diff] [blame] | 462 | */ |
| 463 | T* unflatten(int index) const { |
commit-bot@chromium.org | 6e83423 | 2014-01-10 20:13:09 +0000 | [diff] [blame] | 464 | // index is 1-based, while fIndexedData is 0-based. |
| 465 | const SkFlatData* element = fIndexedData[index-1]; |
robertphillips@google.com | 7d3451b | 2013-03-10 17:16:41 +0000 | [diff] [blame] | 466 | SkASSERT(index == element->index()); |
robertphillips@google.com | e37ad35 | 2013-03-01 19:44:30 +0000 | [diff] [blame] | 467 | |
robertphillips@google.com | 7d3451b | 2013-03-10 17:16:41 +0000 | [diff] [blame] | 468 | T* dst = new T; |
| 469 | this->unflatten(dst, element); |
| 470 | return dst; |
robertphillips@google.com | e37ad35 | 2013-03-01 19:44:30 +0000 | [diff] [blame] | 471 | } |
| 472 | |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 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 | */ |
scroggo@google.com | 664fab1 | 2012-08-14 19:22:05 +0000 | [diff] [blame] | 477 | const SkFlatData* findAndReturnFlat(const T& element) { |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 478 | return this->findAndReturnMutableFlat(element); |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 479 | } |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 480 | |
junov@chromium.org | f3b1223 | 2013-01-22 17:50:47 +0000 | [diff] [blame] | 481 | private: |
commit-bot@chromium.org | 1938242 | 2014-01-14 20:51:26 +0000 | [diff] [blame] | 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. |
commit-bot@chromium.org | ff007e8 | 2014-01-09 16:45:45 +0000 | [diff] [blame] | 484 | void lazyInit() { |
| 485 | if (fReady) { |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 486 | return; |
| 487 | } |
commit-bot@chromium.org | ff007e8 | 2014-01-09 16:45:45 +0000 | [diff] [blame] | 488 | |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 489 | // Without a bitmap heap, we'll flatten bitmaps into paints. That's never what you want. |
| 490 | SkASSERT(fController->getBitmapHeap() != NULL); |
commit-bot@chromium.org | 1938242 | 2014-01-14 20:51:26 +0000 | [diff] [blame] | 491 | fScratch.setBitmapHeap(fController->getBitmapHeap()); |
| 492 | fScratch.setTypefaceRecorder(fController->getTypefaceSet()); |
| 493 | fScratch.setNamedFactoryRecorder(fController->getNamedFactorySet()); |
commit-bot@chromium.org | ff007e8 | 2014-01-09 16:45:45 +0000 | [diff] [blame] | 494 | fReady = true; |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 495 | } |
| 496 | |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 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(). |
commit-bot@chromium.org | f85251c | 2014-01-10 19:37:00 +0000 | [diff] [blame] | 500 | const SkFlatData& scratch = this->resetScratch(element, this->count()+1); |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 501 | |
| 502 | SkFlatData* candidate = fHash.find(scratch); |
| 503 | if (candidate != NULL) return candidate; |
| 504 | |
| 505 | SkFlatData* detached = this->detachScratch(); |
| 506 | fHash.add(detached); |
commit-bot@chromium.org | f85251c | 2014-01-10 19:37:00 +0000 | [diff] [blame] | 507 | *fIndexedData.append() = detached; |
| 508 | SkASSERT(fIndexedData.top()->index() == this->count()); |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 509 | return detached; |
| 510 | } |
| 511 | |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 512 | // This reference is valid only until the next call to resetScratch() or detachScratch(). |
| 513 | const SkFlatData& resetScratch(const T& element, int index) { |
commit-bot@chromium.org | ff007e8 | 2014-01-09 16:45:45 +0000 | [diff] [blame] | 514 | this->lazyInit(); |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 515 | |
commit-bot@chromium.org | 1938242 | 2014-01-14 20:51:26 +0000 | [diff] [blame] | 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); |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 521 | |
commit-bot@chromium.org | 1938242 | 2014-01-14 20:51:26 +0000 | [diff] [blame] | 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; |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 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. |
commit-bot@chromium.org | 1938242 | 2014-01-14 20:51:26 +0000 | [diff] [blame] | 534 | SkFlatData* detached = (SkFlatData*)fController->allocThrow(fScratch.bytesWritten()); |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 535 | |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 536 | // Copy scratch into the new SkFlatData. |
commit-bot@chromium.org | 1938242 | 2014-01-14 20:51:26 +0000 | [diff] [blame] | 537 | SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArray(); |
| 538 | SkASSERT(scratch != NULL); |
| 539 | memcpy(detached, scratch, fScratch.bytesWritten()); |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 540 | |
| 541 | // We can now reuse fScratch, and detached will live until fController dies. |
| 542 | return detached; |
| 543 | } |
| 544 | |
robertphillips@google.com | e37ad35 | 2013-03-01 19:44:30 +0000 | [diff] [blame] | 545 | void unflatten(T* dst, const SkFlatData* element) const { |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 546 | element->unflatten<Traits>(dst, |
| 547 | fController->getBitmapHeap(), |
| 548 | fController->getTypefacePlayback()); |
robertphillips@google.com | e37ad35 | 2013-03-01 19:44:30 +0000 | [diff] [blame] | 549 | } |
| 550 | |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 551 | // All SkFlatData* stored in fIndexedData and fHash are owned by the controller. |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 552 | SkAutoTUnref<SkFlatController> fController; |
commit-bot@chromium.org | 8b0e8ac | 2014-01-30 18:58:24 +0000 | [diff] [blame] | 553 | SkWriteBuffer fScratch; |
commit-bot@chromium.org | ff007e8 | 2014-01-09 16:45:45 +0000 | [diff] [blame] | 554 | bool fReady; |
robertphillips@google.com | 7d3451b | 2013-03-10 17:16:41 +0000 | [diff] [blame] | 555 | |
commit-bot@chromium.org | 6e83423 | 2014-01-10 20:13:09 +0000 | [diff] [blame] | 556 | // For index -> SkFlatData. 0-based, while all indices in the API are 1-based. Careful! |
robertphillips@google.com | 7d3451b | 2013-03-10 17:16:41 +0000 | [diff] [blame] | 557 | SkTDArray<const SkFlatData*> fIndexedData; |
reed@google.com | 83ca337 | 2012-07-12 15:27:54 +0000 | [diff] [blame] | 558 | |
mtklein@google.com | 9e3074e | 2013-08-20 16:48:47 +0000 | [diff] [blame] | 559 | // For SkFlatData -> cached SkFlatData, which has index(). |
| 560 | SkTDynamicHash<SkFlatData, SkFlatData, |
| 561 | SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fHash; |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 562 | }; |
| 563 | |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 564 | struct SkPaintTraits { |
commit-bot@chromium.org | 8b0e8ac | 2014-01-30 18:58:24 +0000 | [diff] [blame] | 565 | static void flatten(SkWriteBuffer& buffer, const SkPaint& paint) { |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 566 | paint.flatten(buffer); |
| 567 | } |
commit-bot@chromium.org | 8b0e8ac | 2014-01-30 18:58:24 +0000 | [diff] [blame] | 568 | static void unflatten(SkReadBuffer& buffer, SkPaint* paint) { |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 569 | paint->unflatten(buffer); |
| 570 | } |
| 571 | }; |
commit-bot@chromium.org | 1938242 | 2014-01-14 20:51:26 +0000 | [diff] [blame] | 572 | typedef SkFlatDictionary<SkPaint, SkPaintTraits> SkPaintDictionary; |
djsollen@google.com | d2700ee | 2012-05-30 16:54:13 +0000 | [diff] [blame] | 573 | |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 574 | class SkChunkFlatController : public SkFlatController { |
| 575 | public: |
| 576 | SkChunkFlatController(size_t minSize) |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 577 | : fHeap(minSize) |
commit-bot@chromium.org | 46724e4 | 2013-07-30 21:54:10 +0000 | [diff] [blame] | 578 | , fTypefaceSet(SkNEW(SkRefCntSet)) |
| 579 | , fLastAllocated(NULL) { |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 580 | this->setTypefaceSet(fTypefaceSet); |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 581 | this->setTypefacePlayback(&fTypefacePlayback); |
| 582 | } |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 583 | |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 584 | virtual void* allocThrow(size_t bytes) SK_OVERRIDE { |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 585 | fLastAllocated = fHeap.allocThrow(bytes); |
| 586 | return fLastAllocated; |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 587 | } |
| 588 | |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 589 | virtual void unalloc(void* ptr) SK_OVERRIDE { |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 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); |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 593 | } |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 594 | |
djsollen@google.com | 21830d9 | 2012-08-07 19:49:41 +0000 | [diff] [blame] | 595 | void setupPlaybacks() const { |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 596 | fTypefacePlayback.reset(fTypefaceSet.get()); |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 597 | } |
| 598 | |
djsollen@google.com | 21830d9 | 2012-08-07 19:49:41 +0000 | [diff] [blame] | 599 | void setBitmapStorage(SkBitmapHeap* heap) { |
| 600 | this->setBitmapHeap(heap); |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 601 | } |
| 602 | |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 603 | private: |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 604 | SkChunkAlloc fHeap; |
commit-bot@chromium.org | ff36a1d | 2013-07-24 20:37:30 +0000 | [diff] [blame] | 605 | SkAutoTUnref<SkRefCntSet> fTypefaceSet; |
| 606 | void* fLastAllocated; |
scroggo@google.com | 1554360 | 2012-08-02 18:49:49 +0000 | [diff] [blame] | 607 | mutable SkTypefacePlayback fTypefacePlayback; |
scroggo@google.com | 4dffc59 | 2012-07-17 16:49:40 +0000 | [diff] [blame] | 608 | }; |
| 609 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 610 | #endif |