blob: f62f7c04dd86f1130597964ed7d644dcb66bcc1f [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
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
18enum SkPath_Properties {
19 SK_PROPERTY(fillType),
20 SK_PROPERTY(length)
21};
22
23#if SK_USE_CONDENSED_INFO == 0
24
25const 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
33DEFINE_GET_MEMBER(SkDrawPath);
34
35SkDrawPath::SkDrawPath()
36{
37 fParent = NULL;
38 fLength = SK_ScalarNaN;
39 fChildHasID = false;
40 fDirty = false;
41}
42
43SkDrawPath::~SkDrawPath() {
44 for (SkPathPart** part = fParts.begin(); part < fParts.end(); part++)
45 delete *part;
46}
47
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +000048bool SkDrawPath::addChild(SkAnimateMaker& maker, SkDisplayable* child) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000049 SkASSERT(child && child->isPathPart());
50 SkPathPart* part = (SkPathPart*) child;
51 *fParts.append() = part;
52 if (part->add())
rmistry@google.comd6176b02012-08-23 18:14:13 +000053 maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingToPath);
reed@android.com8a1c16f2008-12-17 15:59:43 +000054 fDirty = false;
55 return true;
56}
57
rmistry@google.comd6176b02012-08-23 18:14:13 +000058bool SkDrawPath::childrenNeedDisposing() const {
59 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +000060}
61
rmistry@google.comd6176b02012-08-23 18:14:13 +000062void SkDrawPath::dirty() {
63 fDirty = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +000064 fLength = SK_ScalarNaN;
65 if (fParent)
66 fParent->dirty();
67}
68
69bool 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
76SkDisplayable* SkDrawPath::getParent() const {
77 return fParent;
78}
79
80#ifdef SK_DUMP_ENABLED
81void 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
101SkPath& 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}
rmistry@google.comd6176b02012-08-23 18:14:13 +0000118
reed@android.com8a1c16f2008-12-17 15:59:43 +0000119void 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
134bool 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
rmistry@google.comd6176b02012-08-23 18:14:13 +0000156void SkDrawPath::setChildHasID() {
157 fChildHasID = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000158}
159
160bool SkDrawPath::setParent(SkDisplayable* parent) {
161 fParent = parent;
162 return false;
163}
164
165bool 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
183const SkMemberInfo SkPolyline::fInfo[] = {
184 SK_MEMBER_ARRAY(points, Float)
185};
186
187#endif
188
189DEFINE_GET_MEMBER(SkPolyline);
190
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +0000191bool SkPolyline::addChild(SkAnimateMaker& , SkDisplayable*) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000192 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000193}
194
195void 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
209const SkMemberInfo SkPolygon::fInfo[] = {
210 SK_MEMBER_INHERITED
211};
212
213#endif
214
215DEFINE_GET_MEMBER(SkPolygon);
216
217void SkPolygon::onEndElement(SkAnimateMaker& maker) {
218 INHERITED::onEndElement(maker);
219 fPath.close();
220}