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/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