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 blink { 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 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 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 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 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 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 98 bool 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 112 bool 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 127 bool 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 143 bool 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 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 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 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 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 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