18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
2dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2007, 2010 Rob Buis <buis@kde.org>
3dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch *
4dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * This library is free software; you can redistribute it and/or
5dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * modify it under the terms of the GNU Library General Public
6dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * License as published by the Free Software Foundation; either
7dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * version 2 of the License, or (at your option) any later version.
8dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch *
9dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * This library is distributed in the hope that it will be useful,
10dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * but WITHOUT ANY WARRANTY; without even the implied warranty of
11dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Library General Public License for more details.
13dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch *
14dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * You should have received a copy of the GNU Library General Public License
15dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * along with this library; see the file COPYING.LIB.  If not, write to
16dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Boston, MA 02110-1301, USA.
18dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch */
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
21f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(SVG)
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGViewSpec.h"
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h"
26f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "SVGNames.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGParserUtilities.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGSVGElement.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGTransformable.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
33f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// Animated property definitions
34f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochDEFINE_ANIMATED_RECT(SVGViewSpec, SVGNames::viewBoxAttr, ViewBox, viewBox)
35f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochDEFINE_ANIMATED_PRESERVEASPECTRATIO(SVGViewSpec, SVGNames::preserveAspectRatioAttr, PreserveAspectRatio, preserveAspectRatio)
36f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
37e14391e94c850b8bd03680c23b38978db68687a8John ReckSVGViewSpec::SVGViewSpec(SVGElement* contextElement)
385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    : m_contextElement(contextElement)
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGViewSpec::setTransform(const String& transform)
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    SVGTransformable::parseTransformAttribute(m_transform, transform);
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
47545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochvoid SVGViewSpec::setViewBoxString(const String& viewBoxStr)
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
49545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    FloatRect viewBox;
50545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    const UChar* c = viewBoxStr.characters();
51545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    const UChar* end = c + viewBoxStr.length();
52545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    if (!parseViewBox(m_contextElement->document(), c, end, viewBox, false))
53545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch         return;
54545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    setViewBoxBaseValue(viewBox);
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGViewSpec::setPreserveAspectRatioString(const String& preserve)
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
59d0825bca7fe65beaee391d30da42e937db621564Steve Block    SVGPreserveAspectRatio::parsePreserveAspectRatio(this, preserve);
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGViewSpec::setViewTargetString(const String& viewTargetString)
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_viewTargetString = viewTargetString;
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSVGElement* SVGViewSpec::viewTarget() const
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
69cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    return static_cast<SVGElement*>(m_contextElement->document()->getElementById(m_viewTargetString));
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic const UChar svgViewSpec[] = {'s', 'v', 'g', 'V', 'i', 'e', 'w'};
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const UChar viewBoxSpec[] = {'v', 'i', 'e', 'w', 'B', 'o', 'x'};
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const UChar preserveAspectRatioSpec[] = {'p', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'A', 's', 'p', 'e', 'c', 't', 'R', 'a', 't', 'i', 'o'};
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const UChar transformSpec[] = {'t', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm'};
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const UChar zoomAndPanSpec[] = {'z', 'o', 'o', 'm', 'A', 'n', 'd', 'P', 'a', 'n'};
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const UChar viewTargetSpec[] =  {'v', 'i', 'e', 'w', 'T', 'a', 'r', 'g', 'e', 't'};
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool SVGViewSpec::parseViewSpec(const String& viewSpec)
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const UChar* currViewSpec = viewSpec.characters();
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const UChar* end = currViewSpec + viewSpec.length();
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (currViewSpec >= end)
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
874576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    if (!skipString(currViewSpec, end, svgViewSpec, WTF_ARRAY_LENGTH(svgViewSpec)))
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
90cad810f21b803229eb11403f9209855525a25d57Steve Block    if (currViewSpec >= end || *currViewSpec != '(')
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    currViewSpec++;
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (currViewSpec < end && *currViewSpec != ')') {
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (*currViewSpec == 'v') {
964576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            if (skipString(currViewSpec, end, viewBoxSpec, WTF_ARRAY_LENGTH(viewBoxSpec))) {
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (currViewSpec >= end || *currViewSpec != '(')
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    return false;
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                currViewSpec++;
100545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                FloatRect viewBox;
101545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                if (!parseViewBox(m_contextElement->document(), currViewSpec, end, viewBox, false))
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    return false;
103545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                setViewBoxBaseValue(viewBox);
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (currViewSpec >= end || *currViewSpec != ')')
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    return false;
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                currViewSpec++;
1074576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            } else if (skipString(currViewSpec, end, viewTargetSpec, WTF_ARRAY_LENGTH(viewTargetSpec))) {
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (currViewSpec >= end || *currViewSpec != '(')
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    return false;
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                const UChar* viewTargetStart = ++currViewSpec;
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                while (currViewSpec < end && *currViewSpec != ')')
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    currViewSpec++;
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (currViewSpec >= end)
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    return false;
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                setViewTargetString(String(viewTargetStart, currViewSpec - viewTargetStart));
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                currViewSpec++;
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (*currViewSpec == 'z') {
1204576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            if (!skipString(currViewSpec, end, zoomAndPanSpec, WTF_ARRAY_LENGTH(zoomAndPanSpec)))
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (currViewSpec >= end || *currViewSpec != '(')
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            currViewSpec++;
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!parseZoomAndPan(currViewSpec, end))
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (currViewSpec >= end || *currViewSpec != ')')
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            currViewSpec++;
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (*currViewSpec == 'p') {
1314576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            if (!skipString(currViewSpec, end, preserveAspectRatioSpec, WTF_ARRAY_LENGTH(preserveAspectRatioSpec)))
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (currViewSpec >= end || *currViewSpec != '(')
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            currViewSpec++;
136d0825bca7fe65beaee391d30da42e937db621564Steve Block            bool result = false;
137d0825bca7fe65beaee391d30da42e937db621564Steve Block            setPreserveAspectRatioBaseValue(SVGPreserveAspectRatio::parsePreserveAspectRatio(currViewSpec, end, false, result));
138d0825bca7fe65beaee391d30da42e937db621564Steve Block            if (!result)
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (currViewSpec >= end || *currViewSpec != ')')
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            currViewSpec++;
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (*currViewSpec == 't') {
1444576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            if (!skipString(currViewSpec, end, transformSpec, WTF_ARRAY_LENGTH(transformSpec)))
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (currViewSpec >= end || *currViewSpec != '(')
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            currViewSpec++;
1496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            SVGTransformable::parseTransformAttribute(m_transform, currViewSpec, end, SVGTransformable::DoNotClearList);
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (currViewSpec >= end || *currViewSpec != ')')
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            currViewSpec++;
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (currViewSpec < end && *currViewSpec == ';')
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            currViewSpec++;
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (currViewSpec >= end || *currViewSpec != ')')
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif // ENABLE(SVG)
169