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