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 "SkGroupShape.h"
9
10SkGroupShape::SkGroupShape() {}
11
12SkGroupShape::~SkGroupShape() {
13    this->removeAllShapes();
14}
15
16int SkGroupShape::countShapes() const {
17    return fList.count();
18}
19
20SkShape* SkGroupShape::getShape(int index, SkMatrixRef** mr) const {
21    if ((unsigned)index < (unsigned)fList.count()) {
22        const Rec& rec = fList[index];
23        if (mr) {
24            *mr = rec.fMatrixRef;
25        }
26        return rec.fShape;
27    }
28    return NULL;
29}
30
31void SkGroupShape::addShape(int index, SkShape* shape, SkMatrixRef* mr) {
32    int count = fList.count();
33    if (NULL == shape || index < 0 || index > count) {
34        return;
35    }
36
37    shape->ref();
38    SkMatrixRef::SafeRef(mr);
39
40    Rec* rec;
41    if (index == count) {
42        rec = fList.append();
43    } else {
44        rec = fList.insert(index);
45    }
46    rec->fShape = shape;
47    rec->fMatrixRef = mr;
48}
49
50void SkGroupShape::removeShape(int index) {
51    if ((unsigned)index < (unsigned)fList.count()) {
52        Rec& rec = fList[index];
53        rec.fShape->unref();
54        SkMatrixRef::SafeUnref(rec.fMatrixRef);
55        fList.remove(index);
56    }
57}
58
59void SkGroupShape::removeAllShapes() {
60    Rec* rec = fList.begin();
61    Rec* stop = fList.end();
62    while (rec < stop) {
63        rec->fShape->unref();
64        SkMatrixRef::SafeUnref(rec->fMatrixRef);
65        rec++;
66    }
67    fList.reset();
68}
69
70///////////////////////////////////////////////////////////////////////////////
71
72void SkGroupShape::onDraw(SkCanvas* canvas) {
73    const Rec* rec = fList.begin();
74    const Rec* stop = fList.end();
75    while (rec < stop) {
76        SkShape* shape = rec->fShape;
77        if (rec->fMatrixRef) {
78            shape->drawMatrix(canvas, *rec->fMatrixRef);
79        } else {
80            shape->draw(canvas);
81        }
82        rec++;
83    }
84}
85
86SkFlattenable::Factory SkGroupShape::getFactory() {
87    return CreateProc;
88}
89
90void SkGroupShape::flatten(SkFlattenableWriteBuffer& buffer) {
91    this->INHERITED::flatten(buffer);
92
93    int count = fList.count();
94    buffer.write32(count);
95    const Rec* rec = fList.begin();
96    const Rec* stop = fList.end();
97    while (rec < stop) {
98        buffer.writeFlattenable(rec->fShape);
99        if (rec->fMatrixRef) {
100            char storage[SkMatrix::kMaxFlattenSize];
101            uint32_t size = rec->fMatrixRef->flatten(storage);
102            buffer.write32(size);
103            buffer.writePad(storage, size);
104        } else {
105            buffer.write32(0);
106        }
107        rec += 1;
108    }
109}
110
111SkGroupShape::SkGroupShape(SkFlattenableReadBuffer& buffer) : INHERITED(buffer){
112    int count = buffer.readS32();
113    for (int i = 0; i < count; i++) {
114        SkShape* shape = reinterpret_cast<SkShape*>(buffer.readFlattenable());
115        SkMatrixRef* mr = NULL;
116        uint32_t size = buffer.readS32();
117        if (size) {
118            char storage[SkMatrix::kMaxFlattenSize];
119            buffer.read(storage, SkAlign4(size));
120            mr = SkNEW(SkMatrixRef);
121            mr->unflatten(storage);
122        }
123        if (shape) {
124            this->appendShape(shape, mr)->unref();
125        }
126        SkSafeUnref(mr);
127    }
128}
129
130SkFlattenable* SkGroupShape::CreateProc(SkFlattenableReadBuffer& buffer) {
131    return SkNEW_ARGS(SkGroupShape, (buffer));
132}
133
134SK_DEFINE_FLATTENABLE_REGISTRAR(SkGroupShape)
135
136