1 /*
2 * Copyright (C) Research In Motion Limited 2010, 2012. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21
22 #include "core/svg/SVGPathUtilities.h"
23
24 #include "core/svg/SVGPathBlender.h"
25 #include "core/svg/SVGPathBuilder.h"
26 #include "core/svg/SVGPathByteStreamBuilder.h"
27 #include "core/svg/SVGPathByteStreamSource.h"
28 #include "core/svg/SVGPathParser.h"
29 #include "core/svg/SVGPathSegListBuilder.h"
30 #include "core/svg/SVGPathSegListSource.h"
31 #include "core/svg/SVGPathStringBuilder.h"
32 #include "core/svg/SVGPathStringSource.h"
33 #include "core/svg/SVGPathTraversalStateBuilder.h"
34 #include "platform/graphics/PathTraversalState.h"
35
36 namespace WebCore {
37
globalSVGPathBuilder(Path & result)38 static SVGPathBuilder* globalSVGPathBuilder(Path& result)
39 {
40 static SVGPathBuilder* s_builder = 0;
41 if (!s_builder)
42 s_builder = new SVGPathBuilder;
43
44 s_builder->setCurrentPath(&result);
45 return s_builder;
46 }
47
globalSVGPathByteStreamBuilder(SVGPathByteStream * result)48 static SVGPathByteStreamBuilder* globalSVGPathByteStreamBuilder(SVGPathByteStream* result)
49 {
50 static SVGPathByteStreamBuilder* s_builder = 0;
51 if (!s_builder)
52 s_builder = new SVGPathByteStreamBuilder;
53
54 s_builder->setCurrentByteStream(result);
55 return s_builder;
56 }
57
globalSVGPathStringBuilder()58 static SVGPathStringBuilder* globalSVGPathStringBuilder()
59 {
60 static SVGPathStringBuilder* s_builder = 0;
61 if (!s_builder)
62 s_builder = new SVGPathStringBuilder;
63
64 return s_builder;
65 }
66
globalSVGPathTraversalStateBuilder(PathTraversalState & traversalState,float length)67 static SVGPathTraversalStateBuilder* globalSVGPathTraversalStateBuilder(PathTraversalState& traversalState, float length)
68 {
69 static SVGPathTraversalStateBuilder* s_builder = 0;
70 if (!s_builder)
71 s_builder = new SVGPathTraversalStateBuilder;
72
73 s_builder->setCurrentTraversalState(&traversalState);
74 s_builder->setDesiredLength(length);
75 return s_builder;
76 }
77
globalSVGPathParser(SVGPathSource * source,SVGPathConsumer * consumer)78 static SVGPathParser* globalSVGPathParser(SVGPathSource* source, SVGPathConsumer* consumer)
79 {
80 static SVGPathParser* s_parser = 0;
81 if (!s_parser)
82 s_parser = new SVGPathParser;
83
84 s_parser->setCurrentSource(source);
85 s_parser->setCurrentConsumer(consumer);
86 return s_parser;
87 }
88
globalSVGPathBlender()89 static SVGPathBlender* globalSVGPathBlender()
90 {
91 static SVGPathBlender* s_blender = 0;
92 if (!s_blender)
93 s_blender = new SVGPathBlender;
94
95 return s_blender;
96 }
97
buildPathFromString(const String & d,Path & result)98 bool buildPathFromString(const String& d, Path& result)
99 {
100 if (d.isEmpty())
101 return false;
102
103 SVGPathBuilder* builder = globalSVGPathBuilder(result);
104
105 OwnPtr<SVGPathStringSource> source = SVGPathStringSource::create(d);
106 SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
107 bool ok = parser->parsePathDataFromSource(NormalizedParsing);
108 parser->cleanup();
109 return ok;
110 }
111
buildPathFromByteStream(const SVGPathByteStream * stream,Path & result)112 bool buildPathFromByteStream(const SVGPathByteStream* stream, Path& result)
113 {
114 ASSERT(stream);
115 if (stream->isEmpty())
116 return false;
117
118 SVGPathBuilder* builder = globalSVGPathBuilder(result);
119
120 SVGPathByteStreamSource source(stream);
121 SVGPathParser* parser = globalSVGPathParser(&source, builder);
122 bool ok = parser->parsePathDataFromSource(NormalizedParsing);
123 parser->cleanup();
124 return ok;
125 }
126
buildStringFromByteStream(const SVGPathByteStream * stream,String & result,PathParsingMode parsingMode)127 bool buildStringFromByteStream(const SVGPathByteStream* stream, String& result, PathParsingMode parsingMode)
128 {
129 ASSERT(stream);
130 if (stream->isEmpty())
131 return false;
132
133 SVGPathStringBuilder* builder = globalSVGPathStringBuilder();
134
135 SVGPathByteStreamSource source(stream);
136 SVGPathParser* parser = globalSVGPathParser(&source, builder);
137 bool ok = parser->parsePathDataFromSource(parsingMode);
138 result = builder->result();
139 parser->cleanup();
140 return ok;
141 }
142
buildSVGPathByteStreamFromString(const String & d,SVGPathByteStream * result,PathParsingMode parsingMode)143 bool buildSVGPathByteStreamFromString(const String& d, SVGPathByteStream* result, PathParsingMode parsingMode)
144 {
145 ASSERT(result);
146 result->clear();
147 if (d.isEmpty())
148 return false;
149
150 // The string length is typically a minor overestimate of eventual byte stream size, so it avoids us a lot of reallocs.
151 result->reserveInitialCapacity(d.length());
152
153 SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result);
154
155 OwnPtr<SVGPathStringSource> source = SVGPathStringSource::create(d);
156 SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
157 bool ok = parser->parsePathDataFromSource(parsingMode);
158 parser->cleanup();
159
160 result->shrinkToFit();
161
162 return ok;
163 }
164
addToSVGPathByteStream(SVGPathByteStream * fromStream,const SVGPathByteStream * byStream,unsigned repeatCount)165 bool addToSVGPathByteStream(SVGPathByteStream* fromStream, const SVGPathByteStream* byStream, unsigned repeatCount)
166 {
167 ASSERT(fromStream);
168 ASSERT(byStream);
169 if (fromStream->isEmpty() || byStream->isEmpty())
170 return false;
171
172 SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(fromStream);
173
174 OwnPtr<SVGPathByteStream> fromStreamCopy = fromStream->copy();
175 fromStream->clear();
176
177 SVGPathByteStreamSource fromSource(fromStreamCopy.get());
178 SVGPathByteStreamSource bySource(byStream);
179 SVGPathBlender* blender = globalSVGPathBlender();
180 bool ok = blender->addAnimatedPath(&fromSource, &bySource, builder, repeatCount);
181 blender->cleanup();
182 return ok;
183 }
184
getSVGPathSegAtLengthFromSVGPathByteStream(const SVGPathByteStream * stream,float length,unsigned & pathSeg)185 bool getSVGPathSegAtLengthFromSVGPathByteStream(const SVGPathByteStream* stream, float length, unsigned& pathSeg)
186 {
187 ASSERT(stream);
188 if (stream->isEmpty())
189 return false;
190
191 PathTraversalState traversalState(PathTraversalState::TraversalSegmentAtLength);
192 SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, length);
193
194 SVGPathByteStreamSource source(stream);
195 SVGPathParser* parser = globalSVGPathParser(&source, builder);
196 bool ok = parser->parsePathDataFromSource(NormalizedParsing);
197 pathSeg = builder->pathSegmentIndex();
198 parser->cleanup();
199 return ok;
200 }
201
getTotalLengthOfSVGPathByteStream(const SVGPathByteStream * stream,float & totalLength)202 bool getTotalLengthOfSVGPathByteStream(const SVGPathByteStream* stream, float& totalLength)
203 {
204 ASSERT(stream);
205 if (stream->isEmpty())
206 return false;
207
208 PathTraversalState traversalState(PathTraversalState::TraversalTotalLength);
209 SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, 0);
210
211 SVGPathByteStreamSource source(stream);
212 SVGPathParser* parser = globalSVGPathParser(&source, builder);
213 bool ok = parser->parsePathDataFromSource(NormalizedParsing);
214 totalLength = builder->totalLength();
215 parser->cleanup();
216 return ok;
217 }
218
getPointAtLengthOfSVGPathByteStream(const SVGPathByteStream * stream,float length,FloatPoint & point)219 bool getPointAtLengthOfSVGPathByteStream(const SVGPathByteStream* stream, float length, FloatPoint& point)
220 {
221 ASSERT(stream);
222 if (stream->isEmpty())
223 return false;
224
225 PathTraversalState traversalState(PathTraversalState::TraversalPointAtLength);
226 SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, length);
227
228 SVGPathByteStreamSource source(stream);
229 SVGPathParser* parser = globalSVGPathParser(&source, builder);
230 bool ok = parser->parsePathDataFromSource(NormalizedParsing);
231 point = builder->currentPoint();
232 parser->cleanup();
233 return ok;
234 }
235
236 }
237