12b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com/* 2c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com * Copyright 2012 Google Inc. 32b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com * 42b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com * Use of this source code is governed by a BSD-style license that can be 52b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com * found in the LICENSE file. 62b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com */ 72b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com 88b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 9ce65f385a0d31a93a31ffd57478de4b8c4e833b3junov@chromium.org#include "SkBitmap.h" 107c9d539d8843ad75a1c249633bbc8bb331f5035escroggo@google.com#include "SkData.h" 1154dc4878b02765efea39e68b218df1e4bfff4b88reed#include "SkDeduper.h" 1275ae421c24ee7ab5a86334e43404b24a6a6fb1f4Mike Reed#include "SkPaint.h" 13672588b684d484dce6ae251e9e163e4a46924322reed@google.com#include "SkPixelRef.h" 14227b516f233df5870d79d3f8dcbdaa02336b7356mike@reedtribe.org#include "SkPtrRecorder.h" 155a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com#include "SkStream.h" 162b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com#include "SkTypeface.h" 172b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com 1854dc4878b02765efea39e68b218df1e4bfff4b88reed/////////////////////////////////////////////////////////////////////////////////////////////////// 1954dc4878b02765efea39e68b218df1e4bfff4b88reed 20d1c65d6708de536a5971575809d7172fa4f54b37Mike ReedSkBinaryWriteBuffer::SkBinaryWriteBuffer() 21d1c65d6708de536a5971575809d7172fa4f54b37Mike Reed : fFactorySet(nullptr) 2296fcdcc219d2a0d3579719b84b28bede76efba64halcanary , fTFSet(nullptr) { 232b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com} 242b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com 25d1c65d6708de536a5971575809d7172fa4f54b37Mike ReedSkBinaryWriteBuffer::SkBinaryWriteBuffer(void* storage, size_t storageSize) 26d1c65d6708de536a5971575809d7172fa4f54b37Mike Reed : fFactorySet(nullptr) 2719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org , fWriter(storage, storageSize) 2896fcdcc219d2a0d3579719b84b28bede76efba64halcanary , fTFSet(nullptr) { 29c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 30c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 31fad98562d8f9db63839a8d902a301b174320f27fbrianosmanSkBinaryWriteBuffer::~SkBinaryWriteBuffer() { 32c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com SkSafeUnref(fFactorySet); 33c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com SkSafeUnref(fTFSet); 34c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 35c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 36fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeByteArray(const void* data, size_t size) { 376fcd28ba1de83b72f4c8343ccec27d26c127de32reed@google.com fWriter.write32(SkToU32(size)); 38c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.writePad(data, size); 39c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 40c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 41fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeBool(bool value) { 42c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.writeBool(value); 43c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 44c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 45fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeScalar(SkScalar value) { 46c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.writeScalar(value); 47c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 48c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 49fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeScalarArray(const SkScalar* value, uint32_t count) { 50c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write32(count); 51c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write(value, count * sizeof(SkScalar)); 52c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 53c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 54fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeInt(int32_t value) { 55c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write32(value); 56c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 57c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 58fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeIntArray(const int32_t* value, uint32_t count) { 59c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write32(count); 60c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write(value, count * sizeof(int32_t)); 61c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 62c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 63fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeUInt(uint32_t value) { 64c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write32(value); 65c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 66c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 67fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeString(const char* value) { 68c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.writeString(value); 69c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 70c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 71fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeColor(SkColor color) { 72c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write32(color); 73c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 74c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 75fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeColorArray(const SkColor* color, uint32_t count) { 76c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write32(count); 77c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write(color, count * sizeof(SkColor)); 78c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 79c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 8097bbf8211fa35bbb0811d5835cb0eaaf37cc679ebrianosmanvoid SkBinaryWriteBuffer::writeColor4f(const SkColor4f& color) { 8197bbf8211fa35bbb0811d5835cb0eaaf37cc679ebrianosman fWriter.write(&color, sizeof(SkColor4f)); 8297bbf8211fa35bbb0811d5835cb0eaaf37cc679ebrianosman} 8397bbf8211fa35bbb0811d5835cb0eaaf37cc679ebrianosman 8497bbf8211fa35bbb0811d5835cb0eaaf37cc679ebrianosmanvoid SkBinaryWriteBuffer::writeColor4fArray(const SkColor4f* color, uint32_t count) { 8597bbf8211fa35bbb0811d5835cb0eaaf37cc679ebrianosman fWriter.write32(count); 8697bbf8211fa35bbb0811d5835cb0eaaf37cc679ebrianosman fWriter.write(color, count * sizeof(SkColor4f)); 8797bbf8211fa35bbb0811d5835cb0eaaf37cc679ebrianosman} 8897bbf8211fa35bbb0811d5835cb0eaaf37cc679ebrianosman 89fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writePoint(const SkPoint& point) { 90c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.writeScalar(point.fX); 91c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.writeScalar(point.fY); 92c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 93c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 94fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writePointArray(const SkPoint* point, uint32_t count) { 95c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write32(count); 96c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write(point, count * sizeof(SkPoint)); 97c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 98c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 99fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeMatrix(const SkMatrix& matrix) { 100c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.writeMatrix(matrix); 101c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 102c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 103fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeIRect(const SkIRect& rect) { 104c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write(&rect, sizeof(SkIRect)); 105c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 106c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 107fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeRect(const SkRect& rect) { 108c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.writeRect(rect); 109c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 110c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 111fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeRegion(const SkRegion& region) { 112c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.writeRegion(region); 113c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 114c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 115fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writePath(const SkPath& path) { 116c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.writePath(path); 117c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 118c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 119fad98562d8f9db63839a8d902a301b174320f27fbrianosmansize_t SkBinaryWriteBuffer::writeStream(SkStream* stream, size_t length) { 1206fcd28ba1de83b72f4c8343ccec27d26c127de32reed@google.com fWriter.write32(SkToU32(length)); 121e782f5ee472db5e05f3a63607a8c5cdfe838e464djsollen@google.com size_t bytesWritten = fWriter.readFromStream(stream, length); 122e782f5ee472db5e05f3a63607a8c5cdfe838e464djsollen@google.com if (bytesWritten < length) { 123e782f5ee472db5e05f3a63607a8c5cdfe838e464djsollen@google.com fWriter.reservePad(length - bytesWritten); 124e782f5ee472db5e05f3a63607a8c5cdfe838e464djsollen@google.com } 125e782f5ee472db5e05f3a63607a8c5cdfe838e464djsollen@google.com return bytesWritten; 126c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 127c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 128fad98562d8f9db63839a8d902a301b174320f27fbrianosmanbool SkBinaryWriteBuffer::writeToStream(SkWStream* stream) { 129c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com return fWriter.writeToStream(stream); 130c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 131c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 132fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeImage(const SkImage* image) { 13354dc4878b02765efea39e68b218df1e4bfff4b88reed if (fDeduper) { 13454dc4878b02765efea39e68b218df1e4bfff4b88reed this->write32(fDeduper->findOrDefineImage(const_cast<SkImage*>(image))); 13554dc4878b02765efea39e68b218df1e4bfff4b88reed return; 13654dc4878b02765efea39e68b218df1e4bfff4b88reed } 13754dc4878b02765efea39e68b218df1e4bfff4b88reed 138871872f3f247f6b699617f6d9ef50ef5da6fbe74reed this->writeInt(image->width()); 139871872f3f247f6b699617f6d9ef50ef5da6fbe74reed this->writeInt(image->height()); 140871872f3f247f6b699617f6d9ef50ef5da6fbe74reed 14160691a5127852631b03250f15fa6cda9a504befcMike Reed auto write_data = [this](sk_sp<SkData> data, int sign) { 14264f73764b7553148f7660e06b57d623542c63d5bMike Reed size_t size = data ? data->size() : 0; 14364f73764b7553148f7660e06b57d623542c63d5bMike Reed if (!sk_64_isS32(size)) { 14464f73764b7553148f7660e06b57d623542c63d5bMike Reed size = 0; // too big to store 14564f73764b7553148f7660e06b57d623542c63d5bMike Reed } 14664f73764b7553148f7660e06b57d623542c63d5bMike Reed if (size) { 14764f73764b7553148f7660e06b57d623542c63d5bMike Reed this->write32(SkToS32(size) * sign); 14864f73764b7553148f7660e06b57d623542c63d5bMike Reed this->writePad32(data->data(), size); // does nothing if size == 0 14964f73764b7553148f7660e06b57d623542c63d5bMike Reed this->write32(0); // origin-x 15064f73764b7553148f7660e06b57d623542c63d5bMike Reed this->write32(0); // origin-y 15164f73764b7553148f7660e06b57d623542c63d5bMike Reed } else { 15264f73764b7553148f7660e06b57d623542c63d5bMike Reed this->write32(0); // signal no image 15360691a5127852631b03250f15fa6cda9a504befcMike Reed } 15460691a5127852631b03250f15fa6cda9a504befcMike Reed }; 15560691a5127852631b03250f15fa6cda9a504befcMike Reed 15660691a5127852631b03250f15fa6cda9a504befcMike Reed /* 15760691a5127852631b03250f15fa6cda9a504befcMike Reed * What follows is a 32bit encoded size. 15860691a5127852631b03250f15fa6cda9a504befcMike Reed * 0 : failure, nothing else to do 15960691a5127852631b03250f15fa6cda9a504befcMike Reed * <0 : negative (int32_t) of a custom encoded blob using SerialProcs 16060691a5127852631b03250f15fa6cda9a504befcMike Reed * >0 : standard encoded blob size (use MakeFromEncoded) 16160691a5127852631b03250f15fa6cda9a504befcMike Reed */ 16264f73764b7553148f7660e06b57d623542c63d5bMike Reed sk_sp<SkData> data; 16364f73764b7553148f7660e06b57d623542c63d5bMike Reed int sign = 1; // +1 signals standard encoder 16460691a5127852631b03250f15fa6cda9a504befcMike Reed if (fProcs.fImageProc) { 16564f73764b7553148f7660e06b57d623542c63d5bMike Reed data = fProcs.fImageProc(const_cast<SkImage*>(image), fProcs.fImageCtx); 16664f73764b7553148f7660e06b57d623542c63d5bMike Reed sign = -1; // +1 signals custom encoder 16764f73764b7553148f7660e06b57d623542c63d5bMike Reed } 16864f73764b7553148f7660e06b57d623542c63d5bMike Reed // We check data, since a custom proc can return nullptr, in which case we behave as if 16964f73764b7553148f7660e06b57d623542c63d5bMike Reed // there was no custom proc. 17064f73764b7553148f7660e06b57d623542c63d5bMike Reed if (!data) { 17164f73764b7553148f7660e06b57d623542c63d5bMike Reed data = image->encodeToData(); 17264f73764b7553148f7660e06b57d623542c63d5bMike Reed sign = 1; 173871872f3f247f6b699617f6d9ef50ef5da6fbe74reed } 17464f73764b7553148f7660e06b57d623542c63d5bMike Reed write_data(std::move(data), sign); 175871872f3f247f6b699617f6d9ef50ef5da6fbe74reed} 176871872f3f247f6b699617f6d9ef50ef5da6fbe74reed 177fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeTypeface(SkTypeface* obj) { 17854dc4878b02765efea39e68b218df1e4bfff4b88reed if (fDeduper) { 17954dc4878b02765efea39e68b218df1e4bfff4b88reed this->write32(fDeduper->findOrDefineTypeface(obj)); 18054dc4878b02765efea39e68b218df1e4bfff4b88reed return; 18154dc4878b02765efea39e68b218df1e4bfff4b88reed } 18254dc4878b02765efea39e68b218df1e4bfff4b88reed 1838e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed // Write 32 bits (signed) 1848e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed // 0 -- default font 1858e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed // >0 -- index 1868e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed // <0 -- custom (serial procs) 1878e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed 1888e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed if (obj == nullptr) { 189c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com fWriter.write32(0); 1908e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed } else if (fProcs.fTypefaceProc) { 1918e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed auto data = fProcs.fTypefaceProc(obj, fProcs.fTypefaceCtx); 1928e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed if (data) { 1938e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed size_t size = data->size(); 1948e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed if (!sk_64_isS32(size)) { 1958e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed size = 0; // fall back to default font 1968e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed } 1978e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed int32_t ssize = SkToS32(size); 1988e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed fWriter.write32(-ssize); // negative to signal custom 1998e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed if (size) { 2008e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed this->writePad32(data->data(), size); 2018e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed } 2028e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed return; 2038e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed } 2048e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed // no data means fall through for std behavior 205c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com } 2068e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed fWriter.write32(fTFSet ? fTFSet->add(obj) : 0); 207c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 208c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 209fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writePaint(const SkPaint& paint) { 210fad98562d8f9db63839a8d902a301b174320f27fbrianosman paint.flatten(*this); 211fad98562d8f9db63839a8d902a301b174320f27fbrianosman} 212fad98562d8f9db63839a8d902a301b174320f27fbrianosman 213fad98562d8f9db63839a8d902a301b174320f27fbrianosmanSkFactorySet* SkBinaryWriteBuffer::setFactoryRecorder(SkFactorySet* rec) { 214c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com SkRefCnt_SafeAssign(fFactorySet, rec); 215c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com return rec; 216c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com} 217c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 218fad98562d8f9db63839a8d902a301b174320f27fbrianosmanSkRefCntSet* SkBinaryWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) { 219c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com SkRefCnt_SafeAssign(fTFSet, rec); 220c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com return rec; 221e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com} 222e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com 223fad98562d8f9db63839a8d902a301b174320f27fbrianosmanvoid SkBinaryWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) { 22496fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == flattenable) { 225a3b3b238f507a6ec7f43febc6bf0bb17e04e770fmsarett this->write32(0); 2262b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com return; 2272b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com } 2282b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com 22954dc4878b02765efea39e68b218df1e4bfff4b88reed if (fDeduper) { 23054dc4878b02765efea39e68b218df1e4bfff4b88reed this->write32(fDeduper->findOrDefineFactory(const_cast<SkFlattenable*>(flattenable))); 2312b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com } else { 23254dc4878b02765efea39e68b218df1e4bfff4b88reed /* 23354dc4878b02765efea39e68b218df1e4bfff4b88reed * We can write 1 of 2 versions of the flattenable: 23454dc4878b02765efea39e68b218df1e4bfff4b88reed * 1. index into fFactorySet : This assumes the writer will later 23554dc4878b02765efea39e68b218df1e4bfff4b88reed * resolve the function-ptrs into strings for its reader. SkPicture 23654dc4878b02765efea39e68b218df1e4bfff4b88reed * does exactly this, by writing a table of names (matching the indices) 23754dc4878b02765efea39e68b218df1e4bfff4b88reed * up front in its serialized form. 23854dc4878b02765efea39e68b218df1e4bfff4b88reed * 2. string name of the flattenable or index into fFlattenableDict: We 23954dc4878b02765efea39e68b218df1e4bfff4b88reed * store the string to allow the reader to specify its own factories 24054dc4878b02765efea39e68b218df1e4bfff4b88reed * after write time. In order to improve compression, if we have 24154dc4878b02765efea39e68b218df1e4bfff4b88reed * already written the string, we write its index instead. 24254dc4878b02765efea39e68b218df1e4bfff4b88reed */ 24354dc4878b02765efea39e68b218df1e4bfff4b88reed if (fFactorySet) { 24454dc4878b02765efea39e68b218df1e4bfff4b88reed SkFlattenable::Factory factory = flattenable->getFactory(); 24554dc4878b02765efea39e68b218df1e4bfff4b88reed SkASSERT(factory); 24654dc4878b02765efea39e68b218df1e4bfff4b88reed this->write32(fFactorySet->add(factory)); 247a3b3b238f507a6ec7f43febc6bf0bb17e04e770fmsarett } else { 24854dc4878b02765efea39e68b218df1e4bfff4b88reed const char* name = flattenable->getTypeName(); 24954dc4878b02765efea39e68b218df1e4bfff4b88reed SkASSERT(name); 25054dc4878b02765efea39e68b218df1e4bfff4b88reed SkString key(name); 25154dc4878b02765efea39e68b218df1e4bfff4b88reed if (uint32_t* indexPtr = fFlattenableDict.find(key)) { 25254dc4878b02765efea39e68b218df1e4bfff4b88reed // We will write the index as a 32-bit int. We want the first byte 25354dc4878b02765efea39e68b218df1e4bfff4b88reed // that we send to be zero - this will act as a sentinel that we 25454dc4878b02765efea39e68b218df1e4bfff4b88reed // have an index (not a string). This means that we will send the 25554dc4878b02765efea39e68b218df1e4bfff4b88reed // the index shifted left by 8. The remaining 24-bits should be 25654dc4878b02765efea39e68b218df1e4bfff4b88reed // plenty to store the index. Note that this strategy depends on 25754dc4878b02765efea39e68b218df1e4bfff4b88reed // being little endian. 25854dc4878b02765efea39e68b218df1e4bfff4b88reed SkASSERT(0 == *indexPtr >> 24); 25954dc4878b02765efea39e68b218df1e4bfff4b88reed this->write32(*indexPtr << 8); 26054dc4878b02765efea39e68b218df1e4bfff4b88reed } else { 26154dc4878b02765efea39e68b218df1e4bfff4b88reed // Otherwise write the string. Clients should not use the empty 26254dc4878b02765efea39e68b218df1e4bfff4b88reed // string as a name, or we will have a problem. 26354dc4878b02765efea39e68b218df1e4bfff4b88reed SkASSERT(strcmp("", name)); 26454dc4878b02765efea39e68b218df1e4bfff4b88reed this->writeString(name); 26554dc4878b02765efea39e68b218df1e4bfff4b88reed 26654dc4878b02765efea39e68b218df1e4bfff4b88reed // Add key to dictionary. 26754dc4878b02765efea39e68b218df1e4bfff4b88reed fFlattenableDict.set(key, fFlattenableDict.count() + 1); 26854dc4878b02765efea39e68b218df1e4bfff4b88reed } 269a3b3b238f507a6ec7f43febc6bf0bb17e04e770fmsarett } 2702b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com } 2712b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com 272d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com // make room for the size of the flattened object 273c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com (void)fWriter.reserve(sizeof(uint32_t)); 2742b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com // record the current size, so we can subtract after the object writes. 2756fcd28ba1de83b72f4c8343ccec27d26c127de32reed@google.com size_t offset = fWriter.bytesWritten(); 2762b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com // now flatten the object 2778b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org flattenable->flatten(*this); 2786fcd28ba1de83b72f4c8343ccec27d26c127de32reed@google.com size_t objSize = fWriter.bytesWritten() - offset; 2792b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com // record the obj's size 280536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org fWriter.overwriteTAt(offset - sizeof(uint32_t), SkToU32(objSize)); 2812b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com} 282