OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde
.org> | |
3 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> | |
4 * Copyright (C) 2007 Eric Seidel <eric@webkit.org> | |
5 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | |
6 * | |
7 * This library is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Library General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2 of the License, or (at your option) any later version. | |
11 * | |
12 * This library is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Library General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Library General Public License | |
18 * along with this library; see the file COPYING.LIB. If not, write to | |
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
20 * Boston, MA 02110-1301, USA. | |
21 */ | |
22 | |
23 #include "config.h" | |
24 | |
25 #include "core/svg/SVGPathSegList.h" | |
26 | |
27 #include "core/SVGNames.h" | |
28 #include "core/svg/SVGAnimationElement.h" | |
29 #include "core/svg/SVGPathBlender.h" | |
30 #include "core/svg/SVGPathByteStreamBuilder.h" | |
31 #include "core/svg/SVGPathByteStreamSource.h" | |
32 #include "core/svg/SVGPathElement.h" | |
33 #include "core/svg/SVGPathParser.h" | |
34 #include "core/svg/SVGPathSegListBuilder.h" | |
35 #include "core/svg/SVGPathSegListSource.h" | |
36 #include "core/svg/SVGPathUtilities.h" | |
37 | |
38 namespace blink { | |
39 | |
40 SVGPathSegList::SVGPathSegList(SVGPathElement* contextElement) | |
41 : m_contextElement(contextElement) | |
42 , m_listSyncedToByteStream(true) | |
43 { | |
44 ASSERT(contextElement); | |
45 } | |
46 | |
47 SVGPathSegList::SVGPathSegList(SVGPathElement* contextElement, PassOwnPtr<SVGPat
hByteStream> byteStream) | |
48 : m_contextElement(contextElement) | |
49 , m_byteStream(byteStream) | |
50 , m_listSyncedToByteStream(true) | |
51 { | |
52 ASSERT(contextElement); | |
53 } | |
54 | |
55 SVGPathSegList::~SVGPathSegList() | |
56 { | |
57 } | |
58 | |
59 DEFINE_TRACE(SVGPathSegList) | |
60 { | |
61 SVGListPropertyHelper<SVGPathSegList, SVGPathSeg>::trace(visitor); | |
62 } | |
63 | |
64 PassRefPtrWillBeRawPtr<SVGPathSegList> SVGPathSegList::clone() | |
65 { | |
66 RefPtrWillBeRawPtr<SVGPathSegList> svgPathSegList = adoptRefWillBeNoop(new S
VGPathSegList(m_contextElement, byteStream().copy())); | |
67 svgPathSegList->invalidateList(); | |
68 return svgPathSegList.release(); | |
69 } | |
70 | |
71 PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGPathSegList::cloneForAnimation(const
String& value) const | |
72 { | |
73 RefPtrWillBeRawPtr<SVGPathSegList> svgPathSegList = SVGPathSegList::create(m
_contextElement); | |
74 svgPathSegList->setValueAsString(value, IGNORE_EXCEPTION); | |
75 return svgPathSegList; | |
76 } | |
77 | |
78 const SVGPathByteStream& SVGPathSegList::byteStream() const | |
79 { | |
80 if (!m_byteStream) { | |
81 m_byteStream = SVGPathByteStream::create(); | |
82 | |
83 if (!Base::isEmpty()) { | |
84 SVGPathByteStreamBuilder builder(*m_byteStream); | |
85 SVGPathSegListSource source(begin(), end()); | |
86 SVGPathParser parser(&source, &builder); | |
87 parser.parsePathDataFromSource(UnalteredParsing); | |
88 } | |
89 } | |
90 | |
91 return *m_byteStream.get(); | |
92 } | |
93 | |
94 SVGPathByteStream& SVGPathSegList::mutableByteStream() | |
95 { | |
96 ASSERT(Base::isEmpty()); | |
97 if (!m_byteStream) | |
98 m_byteStream = SVGPathByteStream::create(); | |
99 return *m_byteStream.get(); | |
100 } | |
101 | |
102 void SVGPathSegList::updateListFromByteStream() | |
103 { | |
104 if (m_listSyncedToByteStream) | |
105 return; | |
106 | |
107 Base::clear(); | |
108 | |
109 if (m_byteStream && !m_byteStream->isEmpty()) { | |
110 SVGPathSegListBuilder builder(m_contextElement, this); | |
111 SVGPathByteStreamSource source(*m_byteStream); | |
112 SVGPathParser parser(&source, &builder); | |
113 parser.parsePathDataFromSource(UnalteredParsing); | |
114 } | |
115 | |
116 m_listSyncedToByteStream = true; | |
117 } | |
118 | |
119 void SVGPathSegList::invalidateList() | |
120 { | |
121 m_listSyncedToByteStream = false; | |
122 Base::clear(); | |
123 } | |
124 | |
125 PassRefPtrWillBeRawPtr<SVGPathSeg> SVGPathSegList::appendItem(PassRefPtrWillBeRa
wPtr<SVGPathSeg> passItem) | |
126 { | |
127 updateListFromByteStream(); | |
128 RefPtrWillBeRawPtr<SVGPathSeg> item = Base::appendItem(passItem); | |
129 | |
130 if (m_byteStream) { | |
131 SVGPathByteStreamBuilder builder(*m_byteStream); | |
132 SVGPathSegListSource source(lastAppended(), end()); | |
133 SVGPathParser parser(&source, &builder); | |
134 parser.parsePathDataFromSource(UnalteredParsing, false); | |
135 } | |
136 | |
137 return item.release(); | |
138 } | |
139 | |
140 String SVGPathSegList::valueAsString() const | |
141 { | |
142 String string; | |
143 buildStringFromByteStream(byteStream(), string, UnalteredParsing); | |
144 return string; | |
145 } | |
146 | |
147 void SVGPathSegList::setValueAsString(const String& string, ExceptionState& exce
ptionState) | |
148 { | |
149 invalidateList(); | |
150 if (!m_byteStream) | |
151 m_byteStream = SVGPathByteStream::create(); | |
152 if (!buildSVGPathByteStreamFromString(string, *m_byteStream, UnalteredParsin
g)) | |
153 exceptionState.throwDOMException(SyntaxError, "Problem parsing path \""
+ string + "\""); | |
154 } | |
155 | |
156 void SVGPathSegList::add(PassRefPtrWillBeRawPtr<SVGPropertyBase> other, SVGEleme
nt*) | |
157 { | |
158 RefPtrWillBeRawPtr<SVGPathSegList> otherList = toSVGPathSegList(other); | |
159 if (length() != otherList->length()) | |
160 return; | |
161 | |
162 byteStream(); // create |m_byteStream| if it does not exist. | |
163 addToSVGPathByteStream(*m_byteStream, otherList->byteStream()); | |
164 invalidateList(); | |
165 } | |
166 | |
167 void SVGPathSegList::calculateAnimatedValue(SVGAnimationElement* animationElemen
t, float percentage, unsigned repeatCount, PassRefPtrWillBeRawPtr<SVGPropertyBas
e> fromValue, PassRefPtrWillBeRawPtr<SVGPropertyBase> toValue, PassRefPtrWillBeR
awPtr<SVGPropertyBase> toAtEndOfDurationValue, SVGElement*) | |
168 { | |
169 invalidateList(); | |
170 | |
171 ASSERT(animationElement); | |
172 bool isToAnimation = animationElement->animationMode() == ToAnimation; | |
173 | |
174 const RefPtrWillBeRawPtr<SVGPathSegList> from = toSVGPathSegList(fromValue); | |
175 const RefPtrWillBeRawPtr<SVGPathSegList> to = toSVGPathSegList(toValue); | |
176 const RefPtrWillBeRawPtr<SVGPathSegList> toAtEndOfDuration = toSVGPathSegLis
t(toAtEndOfDurationValue); | |
177 | |
178 const SVGPathByteStream& toStream = to->byteStream(); | |
179 const SVGPathByteStream* fromStream = &from->byteStream(); | |
180 OwnPtr<SVGPathByteStream> copy; | |
181 | |
182 // If no 'to' value is given, nothing to animate. | |
183 if (!toStream.size()) | |
184 return; | |
185 | |
186 if (isToAnimation) { | |
187 copy = byteStream().copy(); | |
188 fromStream = copy.get(); | |
189 } | |
190 | |
191 // If the 'from' value is given and it's length doesn't match the 'to' value
list length, fallback to a discrete animation. | |
192 if (fromStream->size() != toStream.size() && fromStream->size()) { | |
193 if (percentage < 0.5) { | |
194 if (!isToAnimation) { | |
195 m_byteStream = fromStream->copy(); | |
196 return; | |
197 } | |
198 } else { | |
199 m_byteStream = toStream.copy(); | |
200 return; | |
201 } | |
202 } | |
203 | |
204 OwnPtr<SVGPathByteStream> lastAnimatedStream = m_byteStream.release(); | |
205 | |
206 m_byteStream = SVGPathByteStream::create(); | |
207 SVGPathByteStreamBuilder builder(*m_byteStream); | |
208 | |
209 SVGPathByteStreamSource fromSource(*fromStream); | |
210 SVGPathByteStreamSource toSource(toStream); | |
211 | |
212 SVGPathBlender blender(&fromSource, &toSource, &builder); | |
213 blender.blendAnimatedPath(percentage); | |
214 | |
215 // Handle additive='sum'. | |
216 if (!fromStream->size() || (animationElement->isAdditive() && !isToAnimation
)) | |
217 addToSVGPathByteStream(*m_byteStream, *lastAnimatedStream); | |
218 | |
219 // Handle accumulate='sum'. | |
220 if (animationElement->isAccumulated() && repeatCount) | |
221 addToSVGPathByteStream(*m_byteStream, toAtEndOfDuration->byteStream(), r
epeatCount); | |
222 } | |
223 | |
224 float SVGPathSegList::calculateDistance(PassRefPtrWillBeRawPtr<SVGPropertyBase>
to, SVGElement*) | |
225 { | |
226 // FIXME: Support paced animations. | |
227 return -1; | |
228 } | |
229 | |
230 } | |
OLD | NEW |