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 = nullptr;
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