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