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
26 enum SkPath_Properties {
27 SK_PROPERTY(fillType),
28 SK_PROPERTY(length)
29 };
30
31 #if SK_USE_CONDENSED_INFO == 0
32
33 const 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
41 DEFINE_GET_MEMBER(SkDrawPath);
42
SkDrawPath()43 SkDrawPath::SkDrawPath()
44 {
45 fParent = NULL;
46 fLength = SK_ScalarNaN;
47 fChildHasID = false;
48 fDirty = false;
49 }
50
~SkDrawPath()51 SkDrawPath::~SkDrawPath() {
52 for (SkPathPart** part = fParts.begin(); part < fParts.end(); part++)
53 delete *part;
54 }
55
add(SkAnimateMaker & maker,SkDisplayable * child)56 bool 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
childrenNeedDisposing() const66 bool SkDrawPath::childrenNeedDisposing() const {
67 return false;
68 }
69
dirty()70 void SkDrawPath::dirty() {
71 fDirty = true;
72 fLength = SK_ScalarNaN;
73 if (fParent)
74 fParent->dirty();
75 }
76
draw(SkAnimateMaker & maker)77 bool 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
getParent() const84 SkDisplayable* SkDrawPath::getParent() const {
85 return fParent;
86 }
87
88 #ifdef SK_DUMP_ENABLED
dump(SkAnimateMaker * maker)89 void 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
getPath()109 SkPath& 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
onEndElement(SkAnimateMaker &)127 void 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
getProperty(int index,SkScriptValue * value) const142 bool 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
setChildHasID()164 void SkDrawPath::setChildHasID() {
165 fChildHasID = true;
166 }
167
setParent(SkDisplayable * parent)168 bool SkDrawPath::setParent(SkDisplayable* parent) {
169 fParent = parent;
170 return false;
171 }
172
setProperty(int index,SkScriptValue & value)173 bool 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
191 const SkMemberInfo SkPolyline::fInfo[] = {
192 SK_MEMBER_ARRAY(points, Float)
193 };
194
195 #endif
196
197 DEFINE_GET_MEMBER(SkPolyline);
198
add(SkAnimateMaker &,SkDisplayable *) const199 bool SkPolyline::add(SkAnimateMaker& , SkDisplayable*) const {
200 return false;
201 }
202
onEndElement(SkAnimateMaker & maker)203 void 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
217 const SkMemberInfo SkPolygon::fInfo[] = {
218 SK_MEMBER_INHERITED
219 };
220
221 #endif
222
223 DEFINE_GET_MEMBER(SkPolygon);
224
onEndElement(SkAnimateMaker & maker)225 void SkPolygon::onEndElement(SkAnimateMaker& maker) {
226 INHERITED::onEndElement(maker);
227 fPath.close();
228 }
229
230