1 /*
2  * Copyright (C) Research In Motion Limited 2010. 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 #if ENABLE(SVG)
23 #include "SVGPathParserFactory.h"
24 
25 #include "PathTraversalState.h"
26 #include "SVGPathBlender.h"
27 #include "SVGPathBuilder.h"
28 #include "SVGPathByteStreamBuilder.h"
29 #include "SVGPathByteStreamSource.h"
30 #include "SVGPathElement.h"
31 #include "SVGPathParser.h"
32 #include "SVGPathSegListBuilder.h"
33 #include "SVGPathSegListSource.h"
34 #include "SVGPathStringBuilder.h"
35 #include "SVGPathStringSource.h"
36 #include "SVGPathTraversalStateBuilder.h"
37 
38 namespace WebCore {
39 
globalSVGPathBuilder(Path & result)40 static SVGPathBuilder* globalSVGPathBuilder(Path& result)
41 {
42     static SVGPathBuilder* s_builder = 0;
43     if (!s_builder)
44         s_builder = new SVGPathBuilder;
45 
46     s_builder->setCurrentPath(&result);
47     return s_builder;
48 }
49 
globalSVGPathSegListBuilder(SVGPathElement * element,SVGPathSegRole role,SVGPathSegList & result)50 static SVGPathSegListBuilder* globalSVGPathSegListBuilder(SVGPathElement* element, SVGPathSegRole role, SVGPathSegList& result)
51 {
52     static SVGPathSegListBuilder* s_builder = 0;
53     if (!s_builder)
54         s_builder = new SVGPathSegListBuilder;
55 
56     s_builder->setCurrentSVGPathElement(element);
57     s_builder->setCurrentSVGPathSegList(result);
58     s_builder->setCurrentSVGPathSegRole(role);
59     return s_builder;
60 }
61 
globalSVGPathByteStreamBuilder(SVGPathByteStream * result)62 static SVGPathByteStreamBuilder* globalSVGPathByteStreamBuilder(SVGPathByteStream* result)
63 {
64     static SVGPathByteStreamBuilder* s_builder = 0;
65     if (!s_builder)
66         s_builder = new SVGPathByteStreamBuilder;
67 
68     s_builder->setCurrentByteStream(result);
69     return s_builder;
70 }
71 
globalSVGPathStringBuilder()72 static SVGPathStringBuilder* globalSVGPathStringBuilder()
73 {
74     static SVGPathStringBuilder* s_builder = 0;
75     if (!s_builder)
76         s_builder = new SVGPathStringBuilder;
77 
78     return s_builder;
79 }
80 
globalSVGPathTraversalStateBuilder(PathTraversalState & traversalState,float length)81 static SVGPathTraversalStateBuilder* globalSVGPathTraversalStateBuilder(PathTraversalState& traversalState, float length)
82 {
83     static SVGPathTraversalStateBuilder* s_builder = 0;
84     if (!s_builder)
85         s_builder = new SVGPathTraversalStateBuilder;
86 
87     s_builder->setCurrentTraversalState(&traversalState);
88     s_builder->setDesiredLength(length);
89     return s_builder;
90 }
91 
globalSVGPathParser(SVGPathSource * source,SVGPathConsumer * consumer)92 static SVGPathParser* globalSVGPathParser(SVGPathSource* source, SVGPathConsumer* consumer)
93 {
94     static SVGPathParser* s_parser = 0;
95     if (!s_parser)
96         s_parser = new SVGPathParser;
97 
98     s_parser->setCurrentSource(source);
99     s_parser->setCurrentConsumer(consumer);
100     return s_parser;
101 }
102 
globalSVGPathBlender()103 static SVGPathBlender* globalSVGPathBlender()
104 {
105     static SVGPathBlender* s_blender = 0;
106     if (!s_blender)
107         s_blender = new SVGPathBlender;
108 
109     return s_blender;
110 }
111 
self()112 SVGPathParserFactory* SVGPathParserFactory::self()
113 {
114     static SVGPathParserFactory* s_instance = 0;
115     if (!s_instance)
116         s_instance = new SVGPathParserFactory;
117 
118     return s_instance;
119 }
120 
SVGPathParserFactory()121 SVGPathParserFactory::SVGPathParserFactory()
122 {
123 }
124 
~SVGPathParserFactory()125 SVGPathParserFactory::~SVGPathParserFactory()
126 {
127 }
128 
buildPathFromString(const String & d,Path & result)129 bool SVGPathParserFactory::buildPathFromString(const String& d, Path& result)
130 {
131     if (d.isEmpty())
132         return false;
133 
134     SVGPathBuilder* builder = globalSVGPathBuilder(result);
135 
136     OwnPtr<SVGPathStringSource> source = SVGPathStringSource::create(d);
137     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
138     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
139     parser->cleanup();
140     return ok;
141 }
142 
buildSVGPathByteStreamFromSVGPathSegList(const SVGPathSegList & list,OwnPtr<SVGPathByteStream> & result,PathParsingMode parsingMode)143 bool SVGPathParserFactory::buildSVGPathByteStreamFromSVGPathSegList(const SVGPathSegList& list, OwnPtr<SVGPathByteStream>& result, PathParsingMode parsingMode)
144 {
145     result = SVGPathByteStream::create();
146     if (list.isEmpty())
147         return false;
148 
149     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result.get());
150 
151     OwnPtr<SVGPathSegListSource> source = SVGPathSegListSource::create(list);
152     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
153     bool ok = parser->parsePathDataFromSource(parsingMode);
154     parser->cleanup();
155     return ok;
156 }
157 
buildPathFromByteStream(SVGPathByteStream * stream,Path & result)158 bool SVGPathParserFactory::buildPathFromByteStream(SVGPathByteStream* stream, Path& result)
159 {
160     ASSERT(stream);
161     if (stream->isEmpty())
162         return false;
163 
164     SVGPathBuilder* builder = globalSVGPathBuilder(result);
165 
166     OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
167     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
168     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
169     parser->cleanup();
170     return ok;
171 }
172 
buildSVGPathSegListFromByteStream(SVGPathByteStream * stream,SVGPathElement * element,SVGPathSegList & result,PathParsingMode parsingMode)173 bool SVGPathParserFactory::buildSVGPathSegListFromByteStream(SVGPathByteStream* stream, SVGPathElement* element, SVGPathSegList& result, PathParsingMode parsingMode)
174 {
175     ASSERT(stream);
176     if (stream->isEmpty())
177         return false;
178 
179     SVGPathSegListBuilder* builder = globalSVGPathSegListBuilder(element, parsingMode == NormalizedParsing ? PathSegNormalizedRole : PathSegUnalteredRole, result);
180 
181     OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
182     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
183     bool ok = parser->parsePathDataFromSource(parsingMode);
184     parser->cleanup();
185     return ok;
186 }
187 
buildStringFromByteStream(SVGPathByteStream * stream,String & result,PathParsingMode parsingMode)188 bool SVGPathParserFactory::buildStringFromByteStream(SVGPathByteStream* stream, String& result, PathParsingMode parsingMode)
189 {
190     ASSERT(stream);
191     if (stream->isEmpty())
192         return false;
193 
194     SVGPathStringBuilder* builder = globalSVGPathStringBuilder();
195 
196     OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
197     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
198     bool ok = parser->parsePathDataFromSource(parsingMode);
199     result = builder->result();
200     parser->cleanup();
201     return ok;
202 }
203 
buildStringFromSVGPathSegList(const SVGPathSegList & list,String & result,PathParsingMode parsingMode)204 bool SVGPathParserFactory::buildStringFromSVGPathSegList(const SVGPathSegList& list, String& result, PathParsingMode parsingMode)
205 {
206     result = String();
207     if (list.isEmpty())
208         return false;
209 
210     SVGPathStringBuilder* builder = globalSVGPathStringBuilder();
211 
212     OwnPtr<SVGPathSegListSource> source = SVGPathSegListSource::create(list);
213     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
214     bool ok = parser->parsePathDataFromSource(parsingMode);
215     result = builder->result();
216     parser->cleanup();
217     return ok;
218 }
219 
buildSVGPathByteStreamFromString(const String & d,OwnPtr<SVGPathByteStream> & result,PathParsingMode parsingMode)220 bool SVGPathParserFactory::buildSVGPathByteStreamFromString(const String& d, OwnPtr<SVGPathByteStream>& result, PathParsingMode parsingMode)
221 {
222     result = SVGPathByteStream::create();
223     if (d.isEmpty())
224         return false;
225 
226     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result.get());
227 
228     OwnPtr<SVGPathStringSource> source = SVGPathStringSource::create(d);
229     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
230     bool ok = parser->parsePathDataFromSource(parsingMode);
231     parser->cleanup();
232     return ok;
233 }
234 
buildAnimatedSVGPathByteStream(SVGPathByteStream * fromStream,SVGPathByteStream * toStream,OwnPtr<SVGPathByteStream> & result,float progress)235 bool SVGPathParserFactory::buildAnimatedSVGPathByteStream(SVGPathByteStream* fromStream, SVGPathByteStream* toStream, OwnPtr<SVGPathByteStream>& result, float progress)
236 {
237     ASSERT(fromStream);
238     ASSERT(toStream);
239     result = SVGPathByteStream::create();
240     if (fromStream->isEmpty() || toStream->isEmpty())
241         return false;
242 
243     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result.get());
244 
245     OwnPtr<SVGPathByteStreamSource> fromSource = SVGPathByteStreamSource::create(fromStream);
246     OwnPtr<SVGPathByteStreamSource> toSource = SVGPathByteStreamSource::create(toStream);
247     SVGPathBlender* blender = globalSVGPathBlender();
248     bool ok = blender->blendAnimatedPath(progress, fromSource.get(), toSource.get(), builder);
249     blender->cleanup();
250     return ok;
251 }
252 
getSVGPathSegAtLengthFromSVGPathByteStream(SVGPathByteStream * stream,float length,unsigned long & pathSeg)253 bool SVGPathParserFactory::getSVGPathSegAtLengthFromSVGPathByteStream(SVGPathByteStream* stream, float length, unsigned long& pathSeg)
254 {
255     ASSERT(stream);
256     if (stream->isEmpty())
257         return false;
258 
259     PathTraversalState traversalState(PathTraversalState::TraversalSegmentAtLength);
260     SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, length);
261 
262     OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
263     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
264     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
265     pathSeg = builder->pathSegmentIndex();
266     parser->cleanup();
267     return ok;
268 }
269 
270 }
271 
272 #endif
273