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 36namespace blink { 37 38static 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 48static 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 58static 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 67static 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 78static 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 89static 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 98bool buildPathFromString(const String& d, Path& result) 99{ 100 if (d.isEmpty()) 101 return true; 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 112bool buildPathFromByteStream(const SVGPathByteStream* stream, Path& result) 113{ 114 ASSERT(stream); 115 if (stream->isEmpty()) 116 return true; 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 127bool buildStringFromByteStream(const SVGPathByteStream* stream, String& result, PathParsingMode parsingMode) 128{ 129 ASSERT(stream); 130 if (stream->isEmpty()) 131 return true; 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 143bool buildSVGPathByteStreamFromString(const String& d, SVGPathByteStream* result, PathParsingMode parsingMode) 144{ 145 ASSERT(result); 146 result->clear(); 147 if (d.isEmpty()) 148 return true; 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 165bool addToSVGPathByteStream(SVGPathByteStream* fromStream, const SVGPathByteStream* byStream, unsigned repeatCount) 166{ 167 ASSERT(fromStream); 168 ASSERT(byStream); 169 if (fromStream->isEmpty() || byStream->isEmpty()) 170 return true; 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 185bool 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 202bool 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 219bool 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