1/* libs/graphics/animator/SkDrawPath.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkDrawPath.h"
19#include "SkAnimateMaker.h"
20#include "SkCanvas.h"
21#include "SkMath.h"
22#include "SkMatrixParts.h"
23#include "SkPaint.h"
24#include "SkPathParts.h"
25
26enum SkPath_Properties {
27    SK_PROPERTY(fillType),
28    SK_PROPERTY(length)
29};
30
31#if SK_USE_CONDENSED_INFO == 0
32
33const SkMemberInfo SkDrawPath::fInfo[] = {
34    SK_MEMBER(d, String),
35    SK_MEMBER_PROPERTY(fillType, FillType),
36    SK_MEMBER_PROPERTY(length, Float)
37};
38
39#endif
40
41DEFINE_GET_MEMBER(SkDrawPath);
42
43SkDrawPath::SkDrawPath()
44{
45    fParent = NULL;
46    fLength = SK_ScalarNaN;
47    fChildHasID = false;
48    fDirty = false;
49}
50
51SkDrawPath::~SkDrawPath() {
52    for (SkPathPart** part = fParts.begin(); part < fParts.end();  part++)
53        delete *part;
54}
55
56bool SkDrawPath::add(SkAnimateMaker& maker, SkDisplayable* child) {
57    SkASSERT(child && child->isPathPart());
58    SkPathPart* part = (SkPathPart*) child;
59    *fParts.append() = part;
60    if (part->add())
61        maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingToPath);
62    fDirty = false;
63    return true;
64}
65
66bool SkDrawPath::childrenNeedDisposing() const {
67    return false;
68}
69
70void SkDrawPath::dirty() {
71    fDirty = true;
72    fLength = SK_ScalarNaN;
73    if (fParent)
74        fParent->dirty();
75}
76
77bool SkDrawPath::draw(SkAnimateMaker& maker) {
78    SkPath& path = getPath();
79    SkBoundableAuto boundable(this, maker);
80    maker.fCanvas->drawPath(path, *maker.fPaint);
81    return false;
82}
83
84SkDisplayable* SkDrawPath::getParent() const {
85    return fParent;
86}
87
88#ifdef SK_DUMP_ENABLED
89void SkDrawPath::dump(SkAnimateMaker* maker) {
90    dumpBase(maker);
91    dumpAttrs(maker);
92    bool closedYet = false;
93    SkDisplayList::fIndent += 4;
94    for(SkPathPart** part = fParts.begin(); part < fParts.end(); part++) {
95        if (closedYet == false) {
96            SkDebugf(">\n");
97            closedYet = true;
98        }
99        (*part)->dump(maker);
100    }
101    SkDisplayList::fIndent -= 4;
102    if (closedYet)
103        dumpEnd(maker);
104    else
105        SkDebugf("/>\n");
106}
107#endif
108
109SkPath& SkDrawPath::getPath() {
110    if (fDirty == false)
111        return fPath;
112    if (d.size() > 0)
113    {
114        parseSVG();
115        d.reset();
116    }
117    else
118    {
119        fPath.reset();
120        for (SkPathPart** part = fParts.begin(); part < fParts.end();  part++)
121            (*part)->add();
122    }
123    fDirty = false;
124    return fPath;
125}
126
127void SkDrawPath::onEndElement(SkAnimateMaker& ) {
128    if (d.size() > 0) {
129        parseSVG();
130        d.reset();
131        fDirty = false;
132        return;
133    }
134    if (fChildHasID == false) {
135        for (SkPathPart** part = fParts.begin(); part < fParts.end();  part++)
136            delete *part;
137        fParts.reset();
138        fDirty = false;
139    }
140}
141
142bool SkDrawPath::getProperty(int index, SkScriptValue* value) const {
143    switch (index) {
144        case SK_PROPERTY(length):
145            if (SkScalarIsNaN(fLength)) {
146                const SkPath& path = ((SkDrawPath*) this)->getPath();
147                SkPathMeasure pathMeasure(path, false);
148                fLength = pathMeasure.getLength();
149            }
150            value->fType = SkType_Float;
151            value->fOperand.fScalar = fLength;
152            break;
153        case SK_PROPERTY(fillType):
154            value->fType = SkType_FillType;
155            value->fOperand.fS32 = (int) fPath.getFillType();
156            break;
157        default:
158            SkASSERT(0);
159            return false;
160    }
161    return true;
162}
163
164void SkDrawPath::setChildHasID() {
165    fChildHasID = true;
166}
167
168bool SkDrawPath::setParent(SkDisplayable* parent) {
169    fParent = parent;
170    return false;
171}
172
173bool SkDrawPath::setProperty(int index, SkScriptValue& value)
174{
175    switch (index) {
176        case SK_PROPERTY(fillType):
177            SkASSERT(value.fType == SkType_FillType);
178            SkASSERT(value.fOperand.fS32 >= SkPath::kWinding_FillType &&
179                value.fOperand.fS32 <= SkPath::kEvenOdd_FillType);
180            fPath.setFillType((SkPath::FillType) value.fOperand.fS32);
181            break;
182        default:
183            SkASSERT(0);
184            return false;
185    }
186    return true;
187}
188
189#if SK_USE_CONDENSED_INFO == 0
190
191const SkMemberInfo SkPolyline::fInfo[] = {
192    SK_MEMBER_ARRAY(points, Float)
193};
194
195#endif
196
197DEFINE_GET_MEMBER(SkPolyline);
198
199bool SkPolyline::add(SkAnimateMaker& , SkDisplayable*) const {
200    return false;
201}
202
203void SkPolyline::onEndElement(SkAnimateMaker& maker) {
204    INHERITED::onEndElement(maker);
205    if (points.count() <= 0)
206        return;
207    fPath.reset();
208    fPath.moveTo(points[0], points[1]);
209    int count = points.count();
210    for (int index = 2; index < count; index += 2)
211        fPath.lineTo(points[index], points[index+1]);
212}
213
214
215#if SK_USE_CONDENSED_INFO == 0
216
217const SkMemberInfo SkPolygon::fInfo[] = {
218    SK_MEMBER_INHERITED
219};
220
221#endif
222
223DEFINE_GET_MEMBER(SkPolygon);
224
225void SkPolygon::onEndElement(SkAnimateMaker& maker) {
226    INHERITED::onEndElement(maker);
227    fPath.close();
228}
229
230