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