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