Remove all uses of PassRefPtr in WebCore/svg
[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 #include "SVGPathUtilities.h"
22
23 #include "Path.h"
24 #include "PathTraversalState.h"
25 #include "SVGPathBlender.h"
26 #include "SVGPathBuilder.h"
27 #include "SVGPathByteStreamBuilder.h"
28 #include "SVGPathByteStreamSource.h"
29 #include "SVGPathConsumer.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
40 static SVGPathBuilder* globalSVGPathBuilder(Path& result)
41 {
42     static SVGPathBuilder* s_builder = nullptr;
43     if (!s_builder)
44         s_builder = new SVGPathBuilder;
45
46     s_builder->setCurrentPath(&result);
47     return s_builder;
48 }
49
50 static SVGPathSegListBuilder* globalSVGPathSegListBuilder(SVGPathElement* element, SVGPathSegRole role, SVGPathSegList& result)
51 {
52     static SVGPathSegListBuilder* s_builder = nullptr;
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
62 static SVGPathByteStreamBuilder* globalSVGPathByteStreamBuilder(SVGPathByteStream* result)
63 {
64     static SVGPathByteStreamBuilder* s_builder = nullptr;
65     if (!s_builder)
66         s_builder = new SVGPathByteStreamBuilder;
67
68     s_builder->setCurrentByteStream(result);
69     return s_builder;
70 }
71
72 static SVGPathStringBuilder* globalSVGPathStringBuilder()
73 {
74     static SVGPathStringBuilder* s_builder = nullptr;
75     if (!s_builder)
76         s_builder = new SVGPathStringBuilder;
77
78     return s_builder;
79 }
80
81 static SVGPathTraversalStateBuilder* globalSVGPathTraversalStateBuilder(PathTraversalState& traversalState, float length)
82 {
83     static SVGPathTraversalStateBuilder* s_builder = nullptr;
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
92 static SVGPathParser* globalSVGPathParser(SVGPathSource* source, SVGPathConsumer* consumer)
93 {
94     static SVGPathParser* s_parser = nullptr;
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
103 static SVGPathBlender* globalSVGPathBlender()
104 {
105     static SVGPathBlender* s_blender = nullptr;
106     if (!s_blender)
107         s_blender = new SVGPathBlender;
108
109     return s_blender;
110 }
111
112 bool buildPathFromString(const String& d, Path& result)
113 {
114     if (d.isEmpty())
115         return true;
116
117     SVGPathBuilder* builder = globalSVGPathBuilder(result);
118
119     auto source = std::make_unique<SVGPathStringSource>(d);
120     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
121     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
122     parser->cleanup();
123     return ok;
124 }
125
126 bool buildSVGPathByteStreamFromSVGPathSegList(const SVGPathSegList& list, SVGPathByteStream* result, PathParsingMode parsingMode)
127 {
128     ASSERT(result);
129     result->clear();
130     if (list.isEmpty())
131         return true;
132
133     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result);
134
135     auto source = std::make_unique<SVGPathSegListSource>(list);
136     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
137     bool ok = parser->parsePathDataFromSource(parsingMode);
138     parser->cleanup();
139     return ok;
140 }
141
142 bool appendSVGPathByteStreamFromSVGPathSeg(RefPtr<SVGPathSeg>&& pathSeg, SVGPathByteStream* result, PathParsingMode parsingMode)
143 {
144     ASSERT(result);
145     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=15412 - Implement normalized path segment lists!
146     ASSERT(parsingMode == UnalteredParsing);
147
148     SVGPathSegList appendedItemList(PathSegUnalteredRole);
149     appendedItemList.append(WTF::move(pathSeg));
150     auto appendedByteStream = std::make_unique<SVGPathByteStream>();
151
152     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(appendedByteStream.get());
153     auto source = std::make_unique<SVGPathSegListSource>(appendedItemList);
154     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
155     bool ok = parser->parsePathDataFromSource(parsingMode, false);
156     parser->cleanup();
157
158     if (ok)
159         result->append(*appendedByteStream);
160
161     return ok;
162 }
163
164 bool buildPathFromByteStream(SVGPathByteStream* stream, Path& result)
165 {
166     ASSERT(stream);
167     if (stream->isEmpty())
168         return true;
169
170     SVGPathBuilder* builder = globalSVGPathBuilder(result);
171
172     auto source = std::make_unique<SVGPathByteStreamSource>(stream);
173     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
174     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
175     parser->cleanup();
176     return ok;
177 }
178
179 bool buildSVGPathSegListFromByteStream(SVGPathByteStream* stream, SVGPathElement* element, SVGPathSegList& result, PathParsingMode parsingMode)
180 {
181     ASSERT(stream);
182     if (stream->isEmpty())
183         return true;
184
185     SVGPathSegListBuilder* builder = globalSVGPathSegListBuilder(element, parsingMode == NormalizedParsing ? PathSegNormalizedRole : PathSegUnalteredRole, result);
186
187     auto source = std::make_unique<SVGPathByteStreamSource>(stream);
188     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
189     bool ok = parser->parsePathDataFromSource(parsingMode);
190     parser->cleanup();
191     return ok;
192 }
193
194 bool buildStringFromByteStream(SVGPathByteStream* stream, String& result, PathParsingMode parsingMode)
195 {
196     ASSERT(stream);
197     if (stream->isEmpty())
198         return true;
199
200     SVGPathStringBuilder* builder = globalSVGPathStringBuilder();
201
202     auto source = std::make_unique<SVGPathByteStreamSource>(stream);
203     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
204     bool ok = parser->parsePathDataFromSource(parsingMode);
205     result = builder->result();
206     parser->cleanup();
207     return ok;
208 }
209
210 bool buildStringFromSVGPathSegList(const SVGPathSegList& list, String& result, PathParsingMode parsingMode)
211 {
212     result = String();
213     if (list.isEmpty())
214         return true;
215
216     SVGPathStringBuilder* builder = globalSVGPathStringBuilder();
217
218     auto source = std::make_unique<SVGPathSegListSource>(list);
219     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
220     bool ok = parser->parsePathDataFromSource(parsingMode);
221     result = builder->result();
222     parser->cleanup();
223     return ok;
224 }
225
226 bool buildSVGPathByteStreamFromString(const String& d, SVGPathByteStream* result, PathParsingMode parsingMode)
227 {
228     ASSERT(result);
229     result->clear();
230     if (d.isEmpty())
231         return true;
232
233     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result);
234
235     auto source = std::make_unique<SVGPathStringSource>(d);
236     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
237     bool ok = parser->parsePathDataFromSource(parsingMode);
238     parser->cleanup();
239     return ok;
240 }
241
242 bool buildAnimatedSVGPathByteStream(SVGPathByteStream* fromStream, SVGPathByteStream* toStream, SVGPathByteStream* result, float progress)
243 {
244     ASSERT(fromStream);
245     ASSERT(toStream);
246     ASSERT(result);
247     ASSERT(toStream != result);
248
249     result->clear();
250     if (toStream->isEmpty())
251         return true;
252
253     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result);
254
255     auto fromSource = std::make_unique<SVGPathByteStreamSource>(fromStream);
256     auto toSource = std::make_unique<SVGPathByteStreamSource>(toStream);
257     SVGPathBlender* blender = globalSVGPathBlender();
258     bool ok = blender->blendAnimatedPath(progress, fromSource.get(), toSource.get(), builder);
259     blender->cleanup();
260     return ok;
261 }
262
263 bool addToSVGPathByteStream(SVGPathByteStream* fromStream, SVGPathByteStream* byStream, unsigned repeatCount)
264 {
265     ASSERT(fromStream);
266     ASSERT(byStream);
267     if (fromStream->isEmpty() || byStream->isEmpty())
268         return true;
269
270     SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(fromStream);
271
272     auto fromStreamCopy = fromStream->copy();
273     fromStream->clear();
274
275     auto fromSource = std::make_unique<SVGPathByteStreamSource>(fromStreamCopy.get());
276     auto bySource = std::make_unique<SVGPathByteStreamSource>(byStream);
277     SVGPathBlender* blender = globalSVGPathBlender();
278     bool ok = blender->addAnimatedPath(fromSource.get(), bySource.get(), builder, repeatCount);
279     blender->cleanup();
280     return ok;
281 }
282
283 bool getSVGPathSegAtLengthFromSVGPathByteStream(SVGPathByteStream* stream, float length, unsigned& pathSeg)
284 {
285     ASSERT(stream);
286     if (stream->isEmpty())
287         return false;
288
289     PathTraversalState traversalState(PathTraversalState::Action::SegmentAtLength);
290     SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, length);
291
292     auto source = std::make_unique<SVGPathByteStreamSource>(stream);
293     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
294     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
295     pathSeg = builder->pathSegmentIndex();
296     parser->cleanup();
297     return ok;
298 }
299
300 bool getTotalLengthOfSVGPathByteStream(SVGPathByteStream* stream, float& totalLength)
301 {
302     ASSERT(stream);
303     if (stream->isEmpty())
304         return false;
305
306     PathTraversalState traversalState(PathTraversalState::Action::TotalLength);
307     SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, 0);
308
309     auto source = std::make_unique<SVGPathByteStreamSource>(stream);
310     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
311     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
312     totalLength = builder->totalLength();
313     parser->cleanup();
314     return ok;
315 }
316
317 bool getPointAtLengthOfSVGPathByteStream(SVGPathByteStream* stream, float length, SVGPoint& point)
318 {
319     ASSERT(stream);
320     if (stream->isEmpty())
321         return false;
322
323     PathTraversalState traversalState(PathTraversalState::Action::VectorAtLength);
324     SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, length);
325
326     auto source = std::make_unique<SVGPathByteStreamSource>(stream);
327     SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
328     bool ok = parser->parsePathDataFromSource(NormalizedParsing);
329     point = builder->currentPoint();
330     parser->cleanup();
331     return ok;
332 }
333
334 static void pathIteratorForBuildingString(SVGPathConsumer& consumer, const PathElement& pathElement)
335 {
336     switch (pathElement.type) {
337     case PathElementMoveToPoint:
338         consumer.moveTo(pathElement.points[0], false, AbsoluteCoordinates);
339         break;
340     case PathElementAddLineToPoint:
341         consumer.lineTo(pathElement.points[0], AbsoluteCoordinates);
342         break;
343     case PathElementAddQuadCurveToPoint:
344         consumer.curveToQuadratic(pathElement.points[0], pathElement.points[1], AbsoluteCoordinates);
345         break;
346     case PathElementAddCurveToPoint:
347         consumer.curveToCubic(pathElement.points[0], pathElement.points[1], pathElement.points[2], AbsoluteCoordinates);
348         break;
349     case PathElementCloseSubpath:
350         consumer.closePath();
351         break;
352
353     default:
354         ASSERT_NOT_REACHED();
355         break;
356     }
357 }
358
359 bool buildStringFromPath(const Path& path, String& string)
360 {
361     // Ideally we would have a SVGPathPlatformPathSource, but it's not possible to manually iterate
362     // a path, only apply a function to all path elements at once.
363
364     SVGPathStringBuilder* builder = globalSVGPathStringBuilder();
365     path.apply([builder](const PathElement& pathElement) {
366         pathIteratorForBuildingString(*builder, pathElement);
367     });
368     string = builder->result();
369     static_cast<SVGPathConsumer*>(builder)->cleanup();
370
371     return true;
372 }
373
374 }