1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkWriteBuffer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,322 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2012 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 +#include "SkWriteBuffer.h" 1.13 +#include "SkBitmap.h" 1.14 +#include "SkData.h" 1.15 +#include "SkPixelRef.h" 1.16 +#include "SkPtrRecorder.h" 1.17 +#include "SkStream.h" 1.18 +#include "SkTypeface.h" 1.19 + 1.20 +SkWriteBuffer::SkWriteBuffer(uint32_t flags) 1.21 + : fFlags(flags) 1.22 + , fFactorySet(NULL) 1.23 + , fNamedFactorySet(NULL) 1.24 + , fBitmapHeap(NULL) 1.25 + , fTFSet(NULL) 1.26 + , fBitmapEncoder(NULL) { 1.27 +} 1.28 + 1.29 +SkWriteBuffer::SkWriteBuffer(void* storage, size_t storageSize, uint32_t flags) 1.30 + : fFlags(flags) 1.31 + , fFactorySet(NULL) 1.32 + , fNamedFactorySet(NULL) 1.33 + , fWriter(storage, storageSize) 1.34 + , fBitmapHeap(NULL) 1.35 + , fTFSet(NULL) 1.36 + , fBitmapEncoder(NULL) { 1.37 +} 1.38 + 1.39 +SkWriteBuffer::~SkWriteBuffer() { 1.40 + SkSafeUnref(fFactorySet); 1.41 + SkSafeUnref(fNamedFactorySet); 1.42 + SkSafeUnref(fBitmapHeap); 1.43 + SkSafeUnref(fTFSet); 1.44 +} 1.45 + 1.46 +void SkWriteBuffer::writeByteArray(const void* data, size_t size) { 1.47 + fWriter.write32(SkToU32(size)); 1.48 + fWriter.writePad(data, size); 1.49 +} 1.50 + 1.51 +void SkWriteBuffer::writeBool(bool value) { 1.52 + fWriter.writeBool(value); 1.53 +} 1.54 + 1.55 +void SkWriteBuffer::writeFixed(SkFixed value) { 1.56 + fWriter.write32(value); 1.57 +} 1.58 + 1.59 +void SkWriteBuffer::writeScalar(SkScalar value) { 1.60 + fWriter.writeScalar(value); 1.61 +} 1.62 + 1.63 +void SkWriteBuffer::writeScalarArray(const SkScalar* value, uint32_t count) { 1.64 + fWriter.write32(count); 1.65 + fWriter.write(value, count * sizeof(SkScalar)); 1.66 +} 1.67 + 1.68 +void SkWriteBuffer::writeInt(int32_t value) { 1.69 + fWriter.write32(value); 1.70 +} 1.71 + 1.72 +void SkWriteBuffer::writeIntArray(const int32_t* value, uint32_t count) { 1.73 + fWriter.write32(count); 1.74 + fWriter.write(value, count * sizeof(int32_t)); 1.75 +} 1.76 + 1.77 +void SkWriteBuffer::writeUInt(uint32_t value) { 1.78 + fWriter.write32(value); 1.79 +} 1.80 + 1.81 +void SkWriteBuffer::write32(int32_t value) { 1.82 + fWriter.write32(value); 1.83 +} 1.84 + 1.85 +void SkWriteBuffer::writeString(const char* value) { 1.86 + fWriter.writeString(value); 1.87 +} 1.88 + 1.89 +void SkWriteBuffer::writeEncodedString(const void* value, size_t byteLength, 1.90 + SkPaint::TextEncoding encoding) { 1.91 + fWriter.writeInt(encoding); 1.92 + fWriter.writeInt(SkToU32(byteLength)); 1.93 + fWriter.write(value, byteLength); 1.94 +} 1.95 + 1.96 + 1.97 +void SkWriteBuffer::writeColor(const SkColor& color) { 1.98 + fWriter.write32(color); 1.99 +} 1.100 + 1.101 +void SkWriteBuffer::writeColorArray(const SkColor* color, uint32_t count) { 1.102 + fWriter.write32(count); 1.103 + fWriter.write(color, count * sizeof(SkColor)); 1.104 +} 1.105 + 1.106 +void SkWriteBuffer::writePoint(const SkPoint& point) { 1.107 + fWriter.writeScalar(point.fX); 1.108 + fWriter.writeScalar(point.fY); 1.109 +} 1.110 + 1.111 +void SkWriteBuffer::writePointArray(const SkPoint* point, uint32_t count) { 1.112 + fWriter.write32(count); 1.113 + fWriter.write(point, count * sizeof(SkPoint)); 1.114 +} 1.115 + 1.116 +void SkWriteBuffer::writeMatrix(const SkMatrix& matrix) { 1.117 + fWriter.writeMatrix(matrix); 1.118 +} 1.119 + 1.120 +void SkWriteBuffer::writeIRect(const SkIRect& rect) { 1.121 + fWriter.write(&rect, sizeof(SkIRect)); 1.122 +} 1.123 + 1.124 +void SkWriteBuffer::writeRect(const SkRect& rect) { 1.125 + fWriter.writeRect(rect); 1.126 +} 1.127 + 1.128 +void SkWriteBuffer::writeRegion(const SkRegion& region) { 1.129 + fWriter.writeRegion(region); 1.130 +} 1.131 + 1.132 +void SkWriteBuffer::writePath(const SkPath& path) { 1.133 + fWriter.writePath(path); 1.134 +} 1.135 + 1.136 +size_t SkWriteBuffer::writeStream(SkStream* stream, size_t length) { 1.137 + fWriter.write32(SkToU32(length)); 1.138 + size_t bytesWritten = fWriter.readFromStream(stream, length); 1.139 + if (bytesWritten < length) { 1.140 + fWriter.reservePad(length - bytesWritten); 1.141 + } 1.142 + return bytesWritten; 1.143 +} 1.144 + 1.145 +bool SkWriteBuffer::writeToStream(SkWStream* stream) { 1.146 + return fWriter.writeToStream(stream); 1.147 +} 1.148 + 1.149 +static void write_encoded_bitmap(SkWriteBuffer* buffer, SkData* data, 1.150 + const SkIPoint& origin) { 1.151 + buffer->writeUInt(SkToU32(data->size())); 1.152 + buffer->getWriter32()->writePad(data->data(), data->size()); 1.153 + buffer->write32(origin.fX); 1.154 + buffer->write32(origin.fY); 1.155 +} 1.156 + 1.157 +void SkWriteBuffer::writeBitmap(const SkBitmap& bitmap) { 1.158 + // Record the width and height. This way if readBitmap fails a dummy bitmap can be drawn at the 1.159 + // right size. 1.160 + this->writeInt(bitmap.width()); 1.161 + this->writeInt(bitmap.height()); 1.162 + 1.163 + // Record information about the bitmap in one of three ways, in order of priority: 1.164 + // 1. If there is an SkBitmapHeap, store it in the heap. The client can avoid serializing the 1.165 + // bitmap entirely or serialize it later as desired. A boolean value of true will be written 1.166 + // to the stream to signify that a heap was used. 1.167 + // 2. If there is a function for encoding bitmaps, use it to write an encoded version of the 1.168 + // bitmap. After writing a boolean value of false, signifying that a heap was not used, write 1.169 + // the size of the encoded data. A non-zero size signifies that encoded data was written. 1.170 + // 3. Call SkBitmap::flatten. After writing a boolean value of false, signifying that a heap was 1.171 + // not used, write a zero to signify that the data was not encoded. 1.172 + bool useBitmapHeap = fBitmapHeap != NULL; 1.173 + // Write a bool: true if the SkBitmapHeap is to be used, in which case the reader must use an 1.174 + // SkBitmapHeapReader to read the SkBitmap. False if the bitmap was serialized another way. 1.175 + this->writeBool(useBitmapHeap); 1.176 + if (useBitmapHeap) { 1.177 + SkASSERT(NULL == fBitmapEncoder); 1.178 + int32_t slot = fBitmapHeap->insert(bitmap); 1.179 + fWriter.write32(slot); 1.180 + // crbug.com/155875 1.181 + // The generation ID is not required information. We write it to prevent collisions 1.182 + // in SkFlatDictionary. It is possible to get a collision when a previously 1.183 + // unflattened (i.e. stale) instance of a similar flattenable is in the dictionary 1.184 + // and the instance currently being written is re-using the same slot from the 1.185 + // bitmap heap. 1.186 + fWriter.write32(bitmap.getGenerationID()); 1.187 + return; 1.188 + } 1.189 + 1.190 + // see if the pixelref already has an encoded version 1.191 + if (bitmap.pixelRef()) { 1.192 + SkAutoDataUnref data(bitmap.pixelRef()->refEncodedData()); 1.193 + if (data.get() != NULL) { 1.194 + write_encoded_bitmap(this, data, bitmap.pixelRefOrigin()); 1.195 + return; 1.196 + } 1.197 + } 1.198 + 1.199 + // see if the caller wants to manually encode 1.200 + if (fBitmapEncoder != NULL) { 1.201 + SkASSERT(NULL == fBitmapHeap); 1.202 + size_t offset = 0; // this parameter is deprecated/ignored 1.203 + // if we have to "encode" the bitmap, then we assume there is no 1.204 + // offset to share, since we are effectively creating a new pixelref 1.205 + SkAutoDataUnref data(fBitmapEncoder(&offset, bitmap)); 1.206 + if (data.get() != NULL) { 1.207 + write_encoded_bitmap(this, data, SkIPoint::Make(0, 0)); 1.208 + return; 1.209 + } 1.210 + } 1.211 + 1.212 + // Bitmap was not encoded. Record a zero, implying that the reader need not decode. 1.213 + this->writeUInt(0); 1.214 + bitmap.flatten(*this); 1.215 +} 1.216 + 1.217 +void SkWriteBuffer::writeTypeface(SkTypeface* obj) { 1.218 + if (NULL == obj || NULL == fTFSet) { 1.219 + fWriter.write32(0); 1.220 + } else { 1.221 + fWriter.write32(fTFSet->add(obj)); 1.222 + } 1.223 +} 1.224 + 1.225 +SkFactorySet* SkWriteBuffer::setFactoryRecorder(SkFactorySet* rec) { 1.226 + SkRefCnt_SafeAssign(fFactorySet, rec); 1.227 + if (fNamedFactorySet != NULL) { 1.228 + fNamedFactorySet->unref(); 1.229 + fNamedFactorySet = NULL; 1.230 + } 1.231 + return rec; 1.232 +} 1.233 + 1.234 +SkNamedFactorySet* SkWriteBuffer::setNamedFactoryRecorder(SkNamedFactorySet* rec) { 1.235 + SkRefCnt_SafeAssign(fNamedFactorySet, rec); 1.236 + if (fFactorySet != NULL) { 1.237 + fFactorySet->unref(); 1.238 + fFactorySet = NULL; 1.239 + } 1.240 + return rec; 1.241 +} 1.242 + 1.243 +SkRefCntSet* SkWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) { 1.244 + SkRefCnt_SafeAssign(fTFSet, rec); 1.245 + return rec; 1.246 +} 1.247 + 1.248 +void SkWriteBuffer::setBitmapHeap(SkBitmapHeap* bitmapHeap) { 1.249 + SkRefCnt_SafeAssign(fBitmapHeap, bitmapHeap); 1.250 + if (bitmapHeap != NULL) { 1.251 + SkASSERT(NULL == fBitmapEncoder); 1.252 + fBitmapEncoder = NULL; 1.253 + } 1.254 +} 1.255 + 1.256 +void SkWriteBuffer::setBitmapEncoder(SkPicture::EncodeBitmap bitmapEncoder) { 1.257 + fBitmapEncoder = bitmapEncoder; 1.258 + if (bitmapEncoder != NULL) { 1.259 + SkASSERT(NULL == fBitmapHeap); 1.260 + SkSafeUnref(fBitmapHeap); 1.261 + fBitmapHeap = NULL; 1.262 + } 1.263 +} 1.264 + 1.265 +void SkWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) { 1.266 + /* 1.267 + * If we have a factoryset, then the first 32bits tell us... 1.268 + * 0: failure to write the flattenable 1.269 + * >0: (1-based) index into the SkFactorySet or SkNamedFactorySet 1.270 + * If we don't have a factoryset, then the first "ptr" is either the 1.271 + * factory, or null for failure. 1.272 + * 1.273 + * The distinction is important, since 0-index is 32bits (always), but a 1.274 + * 0-functionptr might be 32 or 64 bits. 1.275 + */ 1.276 + if (NULL == flattenable) { 1.277 + if (this->isValidating()) { 1.278 + this->writeString(""); 1.279 + } else if (fFactorySet != NULL || fNamedFactorySet != NULL) { 1.280 + this->write32(0); 1.281 + } else { 1.282 + this->writeFunctionPtr(NULL); 1.283 + } 1.284 + return; 1.285 + } 1.286 + 1.287 + SkFlattenable::Factory factory = flattenable->getFactory(); 1.288 + SkASSERT(factory != NULL); 1.289 + 1.290 + /* 1.291 + * We can write 1 of 3 versions of the flattenable: 1.292 + * 1. function-ptr : this is the fastest for the reader, but assumes that 1.293 + * the writer and reader are in the same process. 1.294 + * 2. index into fFactorySet : This is assumes the writer will later 1.295 + * resolve the function-ptrs into strings for its reader. SkPicture 1.296 + * does exactly this, by writing a table of names (matching the indices) 1.297 + * up front in its serialized form. 1.298 + * 3. index into fNamedFactorySet. fNamedFactorySet will also store the 1.299 + * name. SkGPipe uses this technique so it can write the name to its 1.300 + * stream before writing the flattenable. 1.301 + */ 1.302 + if (this->isValidating()) { 1.303 + this->writeString(flattenable->getTypeName()); 1.304 + } else if (fFactorySet) { 1.305 + this->write32(fFactorySet->add(factory)); 1.306 + } else if (fNamedFactorySet) { 1.307 + int32_t index = fNamedFactorySet->find(factory); 1.308 + this->write32(index); 1.309 + if (0 == index) { 1.310 + return; 1.311 + } 1.312 + } else { 1.313 + this->writeFunctionPtr((void*)factory); 1.314 + } 1.315 + 1.316 + // make room for the size of the flattened object 1.317 + (void)fWriter.reserve(sizeof(uint32_t)); 1.318 + // record the current size, so we can subtract after the object writes. 1.319 + size_t offset = fWriter.bytesWritten(); 1.320 + // now flatten the object 1.321 + flattenable->flatten(*this); 1.322 + size_t objSize = fWriter.bytesWritten() - offset; 1.323 + // record the obj's size 1.324 + fWriter.overwriteTAt(offset - sizeof(uint32_t), SkToU32(objSize)); 1.325 +}