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
38namespace WebCore {
39
40static 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
50static 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
62static 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
72static 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
81static 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
92static 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
103static 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
112SVGPathParserFactory* 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
121SVGPathParserFactory::SVGPathParserFactory()
122{
123}
124
125SVGPathParserFactory::~SVGPathParserFactory()
126{
127}
128
129bool 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
143bool 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
158bool 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
173bool 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
188bool 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
204bool 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
220bool 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
235bool 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
253bool 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