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