Home | History | Annotate | Download | only in svg
      1 /*
      2     Copyright (C) 2007 Rob Buis <buis (at) kde.org>
      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 #if ENABLE(SVG)
     22 #include "SVGViewSpec.h"
     23 
     24 #include "Document.h"
     25 #include "PlatformString.h"
     26 #include "SVGParserUtilities.h"
     27 #include "SVGPreserveAspectRatio.h"
     28 #include "SVGSVGElement.h"
     29 #include "SVGTransformList.h"
     30 #include "SVGTransformable.h"
     31 
     32 namespace WebCore {
     33 
     34 SVGViewSpec::SVGViewSpec(const SVGSVGElement* contextElement)
     35     : SVGFitToViewBox()
     36     , SVGZoomAndPan()
     37     , m_contextElement(contextElement)
     38     , m_transform(SVGTransformList::create(SVGNames::transformAttr))
     39 {
     40 }
     41 
     42 SVGViewSpec::~SVGViewSpec()
     43 {
     44 }
     45 
     46 void SVGViewSpec::setTransform(const String& transform)
     47 {
     48     SVGTransformable::parseTransformAttribute(m_transform.get(), transform);
     49 }
     50 
     51 void SVGViewSpec::setViewBoxString(const String& viewBox)
     52 {
     53     float x, y, w, h;
     54     const UChar* c = viewBox.characters();
     55     const UChar* end = c + viewBox.length();
     56     if (!parseViewBox(m_contextElement->document(), c, end, x, y, w, h, false))
     57         return;
     58     setViewBoxBaseValue(FloatRect(x, y, w, h));
     59 }
     60 
     61 void SVGViewSpec::setPreserveAspectRatioString(const String& preserve)
     62 {
     63     SVGPreserveAspectRatio::parsePreserveAspectRatio(this, preserve);
     64 }
     65 
     66 void SVGViewSpec::setViewTargetString(const String& viewTargetString)
     67 {
     68     m_viewTargetString = viewTargetString;
     69 }
     70 
     71 SVGElement* SVGViewSpec::viewTarget() const
     72 {
     73     return static_cast<SVGElement*>(m_contextElement->document()->getElementById(m_viewTargetString));
     74 }
     75 
     76 static const UChar svgViewSpec[] = {'s', 'v', 'g', 'V', 'i', 'e', 'w'};
     77 static const UChar viewBoxSpec[] = {'v', 'i', 'e', 'w', 'B', 'o', 'x'};
     78 static const UChar preserveAspectRatioSpec[] = {'p', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'A', 's', 'p', 'e', 'c', 't', 'R', 'a', 't', 'i', 'o'};
     79 static const UChar transformSpec[] = {'t', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm'};
     80 static const UChar zoomAndPanSpec[] = {'z', 'o', 'o', 'm', 'A', 'n', 'd', 'P', 'a', 'n'};
     81 static const UChar viewTargetSpec[] =  {'v', 'i', 'e', 'w', 'T', 'a', 'r', 'g', 'e', 't'};
     82 
     83 bool SVGViewSpec::parseViewSpec(const String& viewSpec)
     84 {
     85     const UChar* currViewSpec = viewSpec.characters();
     86     const UChar* end = currViewSpec + viewSpec.length();
     87 
     88     if (currViewSpec >= end)
     89         return false;
     90 
     91     if (!skipString(currViewSpec, end, svgViewSpec, sizeof(svgViewSpec) / sizeof(UChar)))
     92         return false;
     93 
     94     if (currViewSpec >= end || *currViewSpec != '(' )
     95         return false;
     96     currViewSpec++;
     97 
     98     while (currViewSpec < end && *currViewSpec != ')') {
     99         if (*currViewSpec == 'v') {
    100             if (skipString(currViewSpec, end, viewBoxSpec, sizeof(viewBoxSpec) / sizeof(UChar))) {
    101                 if (currViewSpec >= end || *currViewSpec != '(')
    102                     return false;
    103                 currViewSpec++;
    104                 float x, y, w, h;
    105                 if (!parseViewBox(m_contextElement->document(), currViewSpec, end, x, y, w, h, false))
    106                     return false;
    107                 setViewBoxBaseValue(FloatRect(x, y, w, h));
    108                 if (currViewSpec >= end || *currViewSpec != ')')
    109                     return false;
    110                 currViewSpec++;
    111             } else if (skipString(currViewSpec, end, viewTargetSpec, sizeof(viewTargetSpec) / sizeof(UChar))) {
    112                 if (currViewSpec >= end || *currViewSpec != '(')
    113                     return false;
    114                 const UChar* viewTargetStart = ++currViewSpec;
    115                 while (currViewSpec < end && *currViewSpec != ')')
    116                     currViewSpec++;
    117                 if (currViewSpec >= end)
    118                     return false;
    119                 setViewTargetString(String(viewTargetStart, currViewSpec - viewTargetStart));
    120                 currViewSpec++;
    121             } else
    122                 return false;
    123         } else if (*currViewSpec == 'z') {
    124             if (!skipString(currViewSpec, end, zoomAndPanSpec, sizeof(zoomAndPanSpec) / sizeof(UChar)))
    125                 return false;
    126             if (currViewSpec >= end || *currViewSpec != '(')
    127                 return false;
    128             currViewSpec++;
    129             if (!parseZoomAndPan(currViewSpec, end))
    130                 return false;
    131             if (currViewSpec >= end || *currViewSpec != ')')
    132                 return false;
    133             currViewSpec++;
    134         } else if (*currViewSpec == 'p') {
    135             if (!skipString(currViewSpec, end, preserveAspectRatioSpec, sizeof(preserveAspectRatioSpec) / sizeof(UChar)))
    136                 return false;
    137             if (currViewSpec >= end || *currViewSpec != '(')
    138                 return false;
    139             currViewSpec++;
    140             bool result = false;
    141             setPreserveAspectRatioBaseValue(SVGPreserveAspectRatio::parsePreserveAspectRatio(currViewSpec, end, false, result));
    142             if (!result)
    143                 return false;
    144             if (currViewSpec >= end || *currViewSpec != ')')
    145                 return false;
    146             currViewSpec++;
    147         } else if (*currViewSpec == 't') {
    148             if (!skipString(currViewSpec, end, transformSpec, sizeof(transformSpec) / sizeof(UChar)))
    149                 return false;
    150             if (currViewSpec >= end || *currViewSpec != '(')
    151                 return false;
    152             currViewSpec++;
    153             SVGTransformable::parseTransformAttribute(m_transform.get(), currViewSpec, end, SVGTransformable::DoNotClearList);
    154             if (currViewSpec >= end || *currViewSpec != ')')
    155                 return false;
    156             currViewSpec++;
    157         } else
    158             return false;
    159 
    160         if (currViewSpec < end && *currViewSpec == ';')
    161             currViewSpec++;
    162     }
    163 
    164     if (currViewSpec >= end || *currViewSpec != ')')
    165         return false;
    166 
    167     return true;
    168 }
    169 
    170 }
    171 
    172 #endif // ENABLE(SVG)
    173