Home | History | Annotate | Download | only in svg
      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