1
2/*
3 * Copyright 2011 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#include "SkPictureFlat.h"
9
10#include "SkChecksum.h"
11#include "SkColorFilter.h"
12#include "SkDrawLooper.h"
13#include "SkMaskFilter.h"
14#include "SkRasterizer.h"
15#include "SkShader.h"
16#include "SkTypeface.h"
17#include "SkXfermode.h"
18
19SK_DEFINE_INST_COUNT(SkFlatController)
20
21///////////////////////////////////////////////////////////////////////////////
22
23SkTypefacePlayback::SkTypefacePlayback() : fCount(0), fArray(NULL) {}
24
25SkTypefacePlayback::~SkTypefacePlayback() {
26    this->reset(NULL);
27}
28
29void SkTypefacePlayback::reset(const SkRefCntSet* rec) {
30    for (int i = 0; i < fCount; i++) {
31        SkASSERT(fArray[i]);
32        fArray[i]->unref();
33    }
34    SkDELETE_ARRAY(fArray);
35
36    if (rec!= NULL && rec->count() > 0) {
37        fCount = rec->count();
38        fArray = SkNEW_ARRAY(SkRefCnt*, fCount);
39        rec->copyToArray(fArray);
40        for (int i = 0; i < fCount; i++) {
41            fArray[i]->ref();
42        }
43    } else {
44        fCount = 0;
45        fArray = NULL;
46    }
47}
48
49void SkTypefacePlayback::setCount(int count) {
50    this->reset(NULL);
51
52    fCount = count;
53    fArray = SkNEW_ARRAY(SkRefCnt*, count);
54    sk_bzero(fArray, count * sizeof(SkRefCnt*));
55}
56
57SkRefCnt* SkTypefacePlayback::set(int index, SkRefCnt* obj) {
58    SkASSERT((unsigned)index < (unsigned)fCount);
59    SkRefCnt_SafeAssign(fArray[index], obj);
60    return obj;
61}
62
63///////////////////////////////////////////////////////////////////////////////
64
65SkFlatController::SkFlatController()
66: fBitmapHeap(NULL)
67, fTypefaceSet(NULL)
68, fTypefacePlayback(NULL)
69, fFactorySet(NULL)
70, fWriteBufferFlags(0) {}
71
72SkFlatController::~SkFlatController() {
73    SkSafeUnref(fBitmapHeap);
74    SkSafeUnref(fTypefaceSet);
75    SkSafeUnref(fFactorySet);
76}
77
78void SkFlatController::setBitmapHeap(SkBitmapHeap* heap) {
79    SkRefCnt_SafeAssign(fBitmapHeap, heap);
80}
81
82void SkFlatController::setTypefaceSet(SkRefCntSet *set) {
83    SkRefCnt_SafeAssign(fTypefaceSet, set);
84}
85
86void SkFlatController::setTypefacePlayback(SkTypefacePlayback* playback) {
87    fTypefacePlayback = playback;
88}
89
90SkNamedFactorySet* SkFlatController::setNamedFactorySet(SkNamedFactorySet* set) {
91    SkRefCnt_SafeAssign(fFactorySet, set);
92    return set;
93}
94
95///////////////////////////////////////////////////////////////////////////////
96
97SkFlatData* SkFlatData::Create(SkFlatController* controller, const void* obj,
98        int index, void (*flattenProc)(SkOrderedWriteBuffer&, const void*)) {
99    // a buffer of 256 bytes should be sufficient for most paints, regions,
100    // and matrices.
101    intptr_t storage[256];
102    SkOrderedWriteBuffer buffer(256, storage, sizeof(storage));
103
104    buffer.setBitmapHeap(controller->getBitmapHeap());
105    buffer.setTypefaceRecorder(controller->getTypefaceSet());
106    buffer.setNamedFactoryRecorder(controller->getNamedFactorySet());
107    buffer.setFlags(controller->getWriteBufferFlags());
108
109    flattenProc(buffer, obj);
110    uint32_t size = buffer.size();
111    SkASSERT(SkIsAlign4(size));
112
113    /**
114     *  Allocate enough memory to hold
115     *  1. SkFlatData struct
116     *  2. flattenProc's data (4-byte aligned)
117     *  3. 4-byte sentinel
118     */
119    size_t allocSize = sizeof(SkFlatData) + size + sizeof(uint32_t);
120    SkFlatData* result = (SkFlatData*) controller->allocThrow(allocSize);
121
122    result->fIndex = index;
123    result->setTopBotUnwritten();
124    result->fFlatSize = size;
125
126    // put the serialized contents into the data section of the new allocation
127    buffer.writeToMemory(result->data());
128    result->fChecksum = SkChecksum::Compute(result->data32(), size);
129    result->setSentinelAsCandidate();
130    return result;
131}
132
133void SkFlatData::unflatten(void* result,
134        void (*unflattenProc)(SkOrderedReadBuffer&, void*),
135        SkBitmapHeap* bitmapHeap,
136        SkTypefacePlayback* facePlayback) const {
137
138    SkOrderedReadBuffer buffer(this->data(), fFlatSize);
139
140    if (bitmapHeap) {
141        buffer.setBitmapStorage(bitmapHeap);
142    }
143    if (facePlayback) {
144        facePlayback->setupBuffer(buffer);
145    }
146
147    unflattenProc(buffer, result);
148    SkASSERT(fFlatSize == (int32_t)buffer.offset());
149}
150