blob: 895e5972adaa6e7890cd739600fdf9199b2d9729 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* 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