• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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