Manage SVGPathByteStream through std::unique_ptr
[WebKit-https.git] / Source / WebCore / svg / SVGPathUtilities.cpp
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 #if ENABLE(SVG)
23 #include "SVGPathUtilities.h"
24
25 #include "Path.h"
26 #include "PathTraversalState.h"
27 #include "SVGPathBlender.h"
28 #include "SVGPathBuilder.h"
29 #include "SVGPathByteStreamBuilder.h"
30 #include "SVGPathByteStreamSource.h"
31 #include "SVGPathElement.h"
32 #include "SVGPathParser.h"
33 #include "SVGPathSegListBuilder.h"
34 #include "SVGPathSegListSource.h"
35 #include "SVGPathStringBuilder.h"
36 #include "SVGPathStringSource.h"
37 #include "SVGPathTraversalStateBuilder.h"
38
39 namespace WebCore {
40
41 static SVGPathBuilder* globalSVGPathBuilder(Path& result)
42 {
43     static SVGPathBuilder* s_builder = 0;
44     if (!s_builder)
45         s_builder = new SVGPathBuilder;
46
47     s_builder->setCurrentPath(&result);
48     return s_builder;
49 }
50
51 static SVGPathSegListBuilder* globalSVGPathSegListBuilder(SVGPathElement* element, SVGPathSegRole role, SVGPathSegList& result)
52 {
53     static SVGPathSegListBuilder* s_builder = 0;
54     if (!s_builder)
55         s_builder = new SVGPathSegListBuilder;
56
57     s_builder->setCurrentSVGPathElement(element);
58     s_builder->setCurrentSVGPathSegList(result);
59     s_builder->setCurrentSVGPathSegRole(role);
60     return s_builder;
61 }
62
63 static SVGPathByteStreamBuilder* globalSVGPathByteStreamBuilder(SVGPathByteStream* result)
64 {
65     static SVGPathByteStreamBuilder* s_builder = 0;
66     if (!s_builder)
67         s_builder = new SVGPathByteStreamBuilder;
68
69     s_builder->setCurrentByteStream(result);
70     return s_builder;
71 }
72
73 static SVGPathStringBuilder* globalSVGPathStringBuilder()
74 {
75     static SVGPathStringBuilder* s_builder = 0;
76     if (!s_builder)
77         s_builder = new SVGPathStringBuilder;
78
79     return s_builder;
80 }
81
82 static SVGPathTraversalStateBuilder* globalSVGPathTraversalStateBuilder(PathTraversalState& traversalState, float length)
83 {
84     static SVGPathTraversalStateBuilder* s_builder = 0;
85     if (!s_builder)
86         s_builder = new SVGPathTraversalStateBuilder;
87
88     s_builder->setCurrentTraversalState(&traversalState);
89     s_builder->setDesiredLength(length);
90     return s_builder;
91 }
92
93 static SVGPathParser* globalSVGPathParser(SVGPathSource* source, SVGPathConsumer* consumer)
94 {
95     static SVGPathParser* s_parser = 0;
96     if (!s_parser)
97         s_parser = new SVGPathParser;
98
99     s_parser->setCurrentSource(source);
100     s_parser->setCurrentConsumer(consumer);
101     return s_parser;
102 }
103
104 static SVGPathBlender* globalSVGPathBlender()
105 {
106     static SVGPathBlender* s_blender = 0;
107     if (!s_blender)
108         s_blender = new SVGPathBlender;
109
110     return s_blender;
111 }
112
113 bool buildPathFromString(const String& d, Path& result)
114 {
115     if (d.isEmpty())
116         return true;
117
118     SVGPathBuilder* builder = globalSVGPathBuilder(result);
119
120     OwnPtr<SVGPathStringSource> source = SVGPathStringSource::create(d);
121     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
122     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
123     parser->cleanup();
124     return ok;
125 }
126
127 bool buildSVGPathByteStreamFromSVGPathSegList(const SVGPathSegList& list, SVGPathByteStream* result, PathParsingMode parsingMode)
128 {
129     ASSERT(result);
130     result->clear();
131     if (list.isEmpty())
132         return true;
133
134     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result);
135
136     OwnPtr<SVGPathSegListSource> source = SVGPathSegListSource::create(list);
137     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
138     bool ok = parser->parsePathDataFromSource(parsingMode);
139     parser->cleanup();
140     return ok;
141 }
142
143 bool appendSVGPathByteStreamFromSVGPathSeg(PassRefPtr<SVGPathSeg> pathSeg, SVGPathByteStream* result, PathParsingMode parsingMode)
144 {
145     ASSERT(result);
146     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=15412 - Implement normalized path segment lists!
147     ASSERT(parsingMode == UnalteredParsing);
148
149     SVGPathSegList appendedItemList(PathSegUnalteredRole);
150     appendedItemList.append(pathSeg);
151     auto appendedByteStream = std::make_unique<SVGPathByteStream>();
152
153     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(appendedByteStream.get());
154     OwnPtr<SVGPathSegListSource> source = SVGPathSegListSource::create(appendedItemList);
155     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
156     bool ok = parser->parsePathDataFromSource(parsingMode, false);
157     parser->cleanup();
158
159     if (ok)
160         result->append(appendedByteStream.get());
161
162     return ok;
163 }
164
165 bool buildPathFromByteStream(SVGPathByteStream* stream, Path& result)
166 {
167     ASSERT(stream);
168     if (stream->isEmpty())
169         return true;
170
171     SVGPathBuilder* builder = globalSVGPathBuilder(result);
172
173     OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
174     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
175     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
176     parser->cleanup();
177     return ok;
178 }
179
180 bool buildSVGPathSegListFromByteStream(SVGPathByteStream* stream, SVGPathElement* element, SVGPathSegList& result, PathParsingMode parsingMode)
181 {
182     ASSERT(stream);
183     if (stream->isEmpty())
184         return true; 
185
186     SVGPathSegListBuilder* builder = globalSVGPathSegListBuilder(element, parsingMode == NormalizedParsing ? PathSegNormalizedRole : PathSegUnalteredRole, result);
187
188     OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
189     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
190     bool ok = parser->parsePathDataFromSource(parsingMode);
191     parser->cleanup();
192     return ok;
193 }
194
195 bool buildStringFromByteStream(SVGPathByteStream* stream, String& result, PathParsingMode parsingMode)
196 {
197     ASSERT(stream);
198     if (stream->isEmpty())
199         return true; 
200
201     SVGPathStringBuilder* builder = globalSVGPathStringBuilder();
202
203     OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
204     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
205     bool ok = parser->parsePathDataFromSource(parsingMode);
206     result = builder->result();
207     parser->cleanup();
208     return ok;
209 }
210
211 bool buildStringFromSVGPathSegList(const SVGPathSegList& list, String& result, PathParsingMode parsingMode)
212 {
213     result = String();
214     if (list.isEmpty())
215         return true;
216
217     SVGPathStringBuilder* builder = globalSVGPathStringBuilder();
218
219     OwnPtr<SVGPathSegListSource> source = SVGPathSegListSource::create(list);
220     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
221     bool ok = parser->parsePathDataFromSource(parsingMode);
222     result = builder->result();
223     parser->cleanup();
224     return ok;
225 }
226
227 bool buildSVGPathByteStreamFromString(const String& d, SVGPathByteStream* result, PathParsingMode parsingMode)
228 {
229     ASSERT(result);
230     result->clear();
231     if (d.isEmpty())
232         return true;
233
234     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result);
235
236     OwnPtr<SVGPathStringSource> source = SVGPathStringSource::create(d);
237     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
238     bool ok = parser->parsePathDataFromSource(parsingMode);
239     parser->cleanup();
240     return ok;
241 }
242
243 bool buildAnimatedSVGPathByteStream(SVGPathByteStream* fromStream, SVGPathByteStream* toStream, SVGPathByteStream* result, float progress)
244 {
245     ASSERT(fromStream);
246     ASSERT(toStream);
247     ASSERT(result);
248     ASSERT(toStream != result);
249
250     result->clear();
251     if (toStream->isEmpty())
252         return true;
253
254     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result);
255
256     OwnPtr<SVGPathByteStreamSource> fromSource = SVGPathByteStreamSource::create(fromStream);
257     OwnPtr<SVGPathByteStreamSource> toSource = SVGPathByteStreamSource::create(toStream);
258     SVGPathBlender* blender = globalSVGPathBlender();
259     bool ok = blender->blendAnimatedPath(progress, fromSource.get(), toSource.get(), builder);
260     blender->cleanup();
261     return ok;
262 }
263
264 bool addToSVGPathByteStream(SVGPathByteStream* fromStream, SVGPathByteStream* byStream, unsigned repeatCount)
265 {
266     ASSERT(fromStream);
267     ASSERT(byStream);
268     if (fromStream->isEmpty() || byStream->isEmpty())
269         return true;
270
271     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(fromStream);
272
273     auto fromStreamCopy = fromStream->copy();
274     fromStream->clear();
275
276     OwnPtr<SVGPathByteStreamSource> fromSource = SVGPathByteStreamSource::create(fromStreamCopy.get());
277     OwnPtr<SVGPathByteStreamSource> bySource = SVGPathByteStreamSource::create(byStream);
278     SVGPathBlender* blender = globalSVGPathBlender();
279     bool ok = blender->addAnimatedPath(fromSource.get(), bySource.get(), builder, repeatCount);
280     blender->cleanup();
281     return ok;
282 }
283
284 bool getSVGPathSegAtLengthFromSVGPathByteStream(SVGPathByteStream* stream, float length, unsigned& pathSeg)
285 {
286     ASSERT(stream);
287     if (stream->isEmpty())
288         return false;
289
290     PathTraversalState traversalState(PathTraversalState::TraversalSegmentAtLength);
291     SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, length);
292
293     OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
294     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
295     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
296     pathSeg = builder->pathSegmentIndex();
297     parser->cleanup();
298     return ok;
299 }
300
301 bool getTotalLengthOfSVGPathByteStream(SVGPathByteStream* stream, float& totalLength)
302 {
303     ASSERT(stream);
304     if (stream->isEmpty())
305         return false;
306     
307     PathTraversalState traversalState(PathTraversalState::TraversalTotalLength);
308     SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, 0);
309     
310     OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
311     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
312     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
313     totalLength = builder->totalLength();
314     parser->cleanup();
315     return ok;
316 }
317
318 bool getPointAtLengthOfSVGPathByteStream(SVGPathByteStream* stream, float length, SVGPoint& point)
319 {
320     ASSERT(stream);
321     if (stream->isEmpty())
322         return false;
323     
324     PathTraversalState traversalState(PathTraversalState::TraversalPointAtLength);
325     SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, length);
326     
327     OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
328     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
329     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
330     point = builder->currentPoint();
331     parser->cleanup();
332     return ok;
333 }
334
335 }
336
337 #endif