1 2 /* 3 * Copyright 2012 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 9 #include "SkOrderedWriteBuffer.h" 10 #include "SkBitmap.h" 11 #include "SkData.h" 12 #include "SkPixelRef.h" 13 #include "SkPtrRecorder.h" 14 #include "SkStream.h" 15 #include "SkTypeface.h" 16 17 SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize) 18 : INHERITED() 19 , fFactorySet(NULL) 20 , fNamedFactorySet(NULL) 21 , fWriter(minSize) 22 , fBitmapHeap(NULL) 23 , fTFSet(NULL) 24 , fBitmapEncoder(NULL) { 25 } 26 27 SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize, void* storage, size_t storageSize) 28 : INHERITED() 29 , fFactorySet(NULL) 30 , fNamedFactorySet(NULL) 31 , fWriter(minSize, storage, storageSize) 32 , fBitmapHeap(NULL) 33 , fTFSet(NULL) 34 , fBitmapEncoder(NULL) { 35 } 36 37 SkOrderedWriteBuffer::~SkOrderedWriteBuffer() { 38 SkSafeUnref(fFactorySet); 39 SkSafeUnref(fNamedFactorySet); 40 SkSafeUnref(fBitmapHeap); 41 SkSafeUnref(fTFSet); 42 } 43 44 void SkOrderedWriteBuffer::writeByteArray(const void* data, size_t size) { 45 fWriter.write32(size); 46 fWriter.writePad(data, size); 47 } 48 49 void SkOrderedWriteBuffer::writeBool(bool value) { 50 fWriter.writeBool(value); 51 } 52 53 void SkOrderedWriteBuffer::writeFixed(SkFixed value) { 54 fWriter.write32(value); 55 } 56 57 void SkOrderedWriteBuffer::writeScalar(SkScalar value) { 58 fWriter.writeScalar(value); 59 } 60 61 void SkOrderedWriteBuffer::writeScalarArray(const SkScalar* value, uint32_t count) { 62 fWriter.write32(count); 63 fWriter.write(value, count * sizeof(SkScalar)); 64 } 65 66 void SkOrderedWriteBuffer::writeInt(int32_t value) { 67 fWriter.write32(value); 68 } 69 70 void SkOrderedWriteBuffer::writeIntArray(const int32_t* value, uint32_t count) { 71 fWriter.write32(count); 72 fWriter.write(value, count * sizeof(int32_t)); 73 } 74 75 void SkOrderedWriteBuffer::writeUInt(uint32_t value) { 76 fWriter.write32(value); 77 } 78 79 void SkOrderedWriteBuffer::write32(int32_t value) { 80 fWriter.write32(value); 81 } 82 83 void SkOrderedWriteBuffer::writeString(const char* value) { 84 fWriter.writeString(value); 85 } 86 87 void SkOrderedWriteBuffer::writeEncodedString(const void* value, size_t byteLength, 88 SkPaint::TextEncoding encoding) { 89 fWriter.writeInt(encoding); 90 fWriter.writeInt(byteLength); 91 fWriter.write(value, byteLength); 92 } 93 94 95 void SkOrderedWriteBuffer::writeColor(const SkColor& color) { 96 fWriter.write32(color); 97 } 98 99 void SkOrderedWriteBuffer::writeColorArray(const SkColor* color, uint32_t count) { 100 fWriter.write32(count); 101 fWriter.write(color, count * sizeof(SkColor)); 102 } 103 104 void SkOrderedWriteBuffer::writePoint(const SkPoint& point) { 105 fWriter.writeScalar(point.fX); 106 fWriter.writeScalar(point.fY); 107 } 108 109 void SkOrderedWriteBuffer::writePointArray(const SkPoint* point, uint32_t count) { 110 fWriter.write32(count); 111 fWriter.write(point, count * sizeof(SkPoint)); 112 } 113 114 void SkOrderedWriteBuffer::writeMatrix(const SkMatrix& matrix) { 115 fWriter.writeMatrix(matrix); 116 } 117 118 void SkOrderedWriteBuffer::writeIRect(const SkIRect& rect) { 119 fWriter.write(&rect, sizeof(SkIRect)); 120 } 121 122 void SkOrderedWriteBuffer::writeRect(const SkRect& rect) { 123 fWriter.writeRect(rect); 124 } 125 126 void SkOrderedWriteBuffer::writeRegion(const SkRegion& region) { 127 fWriter.writeRegion(region); 128 } 129 130 void SkOrderedWriteBuffer::writePath(const SkPath& path) { 131 fWriter.writePath(path); 132 } 133 134 size_t SkOrderedWriteBuffer::writeStream(SkStream* stream, size_t length) { 135 fWriter.write32(length); 136 size_t bytesWritten = fWriter.readFromStream(stream, length); 137 if (bytesWritten < length) { 138 fWriter.reservePad(length - bytesWritten); 139 } 140 return bytesWritten; 141 } 142 143 bool SkOrderedWriteBuffer::writeToStream(SkWStream* stream) { 144 return fWriter.writeToStream(stream); 145 } 146 147 void SkOrderedWriteBuffer::writeBitmap(const SkBitmap& bitmap) { 148 // Record information about the bitmap in one of three ways, in order of priority: 149 // 1. If there is an SkBitmapHeap, store it in the heap. The client can avoid serializing the 150 // bitmap entirely or serialize it later as desired. 151 // 2. Write an encoded version of the bitmap. Afterwards the width and height are written, so 152 // a reader without a decoder can draw a dummy bitmap of the right size. 153 // A. If the bitmap has an encoded representation, write it to the stream. 154 // B. If there is a function for encoding bitmaps, use it. 155 // 3. Call SkBitmap::flatten. 156 // For an encoded bitmap, write the size first. Otherwise store a 0 so the reader knows not to 157 // decode. 158 if (fBitmapHeap != NULL) { 159 SkASSERT(NULL == fBitmapEncoder); 160 // Bitmap was not encoded. Record a zero, implying that the reader need not decode. 161 this->writeUInt(0); 162 int32_t slot = fBitmapHeap->insert(bitmap); 163 fWriter.write32(slot); 164 // crbug.com/155875 165 // The generation ID is not required information. We write it to prevent collisions 166 // in SkFlatDictionary. It is possible to get a collision when a previously 167 // unflattened (i.e. stale) instance of a similar flattenable is in the dictionary 168 // and the instance currently being written is re-using the same slot from the 169 // bitmap heap. 170 fWriter.write32(bitmap.getGenerationID()); 171 return; 172 } 173 bool encoded = false; 174 // Before attempting to encode the SkBitmap, check to see if there is already an encoded 175 // version. 176 SkPixelRef* ref = bitmap.pixelRef(); 177 if (ref != NULL) { 178 SkAutoDataUnref data(ref->refEncodedData()); 179 if (data.get() != NULL) { 180 // Write the length to indicate that the bitmap was encoded successfully, followed 181 // by the actual data. This must match the case where fBitmapEncoder is used so the 182 // reader need not know the difference. 183 this->writeUInt(data->size()); 184 fWriter.writePad(data->data(), data->size()); 185 encoded = true; 186 } 187 } 188 if (fBitmapEncoder != NULL && !encoded) { 189 SkASSERT(NULL == fBitmapHeap); 190 SkDynamicMemoryWStream stream; 191 if (fBitmapEncoder(&stream, bitmap)) { 192 uint32_t offset = fWriter.bytesWritten(); 193 // Write the length to indicate that the bitmap was encoded successfully, followed 194 // by the actual data. This must match the case where the original data is used so the 195 // reader need not know the difference. 196 size_t length = stream.getOffset(); 197 this->writeUInt(length); 198 if (stream.read(fWriter.reservePad(length), 0, length)) { 199 encoded = true; 200 } else { 201 // Writing the stream failed, so go back to original state to store another way. 202 fWriter.rewindToOffset(offset); 203 } 204 } 205 } 206 if (encoded) { 207 // Write the width and height in case the reader does not have a decoder. 208 this->writeInt(bitmap.width()); 209 this->writeInt(bitmap.height()); 210 } else { 211 // Bitmap was not encoded. Record a zero, implying that the reader need not decode. 212 this->writeUInt(0); 213 bitmap.flatten(*this); 214 } 215 } 216 217 void SkOrderedWriteBuffer::writeTypeface(SkTypeface* obj) { 218 if (NULL == obj || NULL == fTFSet) { 219 fWriter.write32(0); 220 } else { 221 fWriter.write32(fTFSet->add(obj)); 222 } 223 } 224 225 SkFactorySet* SkOrderedWriteBuffer::setFactoryRecorder(SkFactorySet* rec) { 226 SkRefCnt_SafeAssign(fFactorySet, rec); 227 if (fNamedFactorySet != NULL) { 228 fNamedFactorySet->unref(); 229 fNamedFactorySet = NULL; 230 } 231 return rec; 232 } 233 234 SkNamedFactorySet* SkOrderedWriteBuffer::setNamedFactoryRecorder(SkNamedFactorySet* rec) { 235 SkRefCnt_SafeAssign(fNamedFactorySet, rec); 236 if (fFactorySet != NULL) { 237 fFactorySet->unref(); 238 fFactorySet = NULL; 239 } 240 return rec; 241 } 242 243 SkRefCntSet* SkOrderedWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) { 244 SkRefCnt_SafeAssign(fTFSet, rec); 245 return rec; 246 } 247 248 void SkOrderedWriteBuffer::setBitmapHeap(SkBitmapHeap* bitmapHeap) { 249 SkRefCnt_SafeAssign(fBitmapHeap, bitmapHeap); 250 if (bitmapHeap != NULL) { 251 SkASSERT(NULL == fBitmapEncoder); 252 fBitmapEncoder = NULL; 253 } 254 } 255 256 void SkOrderedWriteBuffer::setBitmapEncoder(SkSerializationHelpers::EncodeBitmap bitmapEncoder) { 257 fBitmapEncoder = bitmapEncoder; 258 if (bitmapEncoder != NULL) { 259 SkASSERT(NULL == fBitmapHeap); 260 SkSafeUnref(fBitmapHeap); 261 fBitmapHeap = NULL; 262 } 263 } 264 265 void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) { 266 /* 267 * If we have a factoryset, then the first 32bits tell us... 268 * 0: failure to write the flattenable 269 * >0: (1-based) index into the SkFactorySet or SkNamedFactorySet 270 * If we don't have a factoryset, then the first "ptr" is either the 271 * factory, or null for failure. 272 * 273 * The distinction is important, since 0-index is 32bits (always), but a 274 * 0-functionptr might be 32 or 64 bits. 275 */ 276 277 SkFlattenable::Factory factory = NULL; 278 if (flattenable) { 279 factory = flattenable->getFactory(); 280 } 281 if (NULL == factory) { 282 if (fFactorySet != NULL || fNamedFactorySet != NULL) { 283 this->write32(0); 284 } else { 285 this->writeFunctionPtr(NULL); 286 } 287 return; 288 } 289 290 /* 291 * We can write 1 of 3 versions of the flattenable: 292 * 1. function-ptr : this is the fastest for the reader, but assumes that 293 * the writer and reader are in the same process. 294 * 2. index into fFactorySet : This is assumes the writer will later 295 * resolve the function-ptrs into strings for its reader. SkPicture 296 * does exactly this, by writing a table of names (matching the indices) 297 * up front in its serialized form. 298 * 3. index into fNamedFactorySet. fNamedFactorySet will also store the 299 * name. SkGPipe uses this technique so it can write the name to its 300 * stream before writing the flattenable. 301 */ 302 if (fFactorySet) { 303 this->write32(fFactorySet->add(factory)); 304 } else if (fNamedFactorySet) { 305 int32_t index = fNamedFactorySet->find(factory); 306 this->write32(index); 307 if (0 == index) { 308 return; 309 } 310 } else { 311 this->writeFunctionPtr((void*)factory); 312 } 313 314 // make room for the size of the flattened object 315 (void)fWriter.reserve(sizeof(uint32_t)); 316 // record the current size, so we can subtract after the object writes. 317 uint32_t offset = fWriter.size(); 318 // now flatten the object 319 flattenObject(flattenable, *this); 320 uint32_t objSize = fWriter.size() - offset; 321 // record the obj's size 322 *fWriter.peek32(offset - sizeof(uint32_t)) = objSize; 323 } 324