Rename AtomicString to AtomString
[WebKit-https.git] / Source / WebCore / svg / SVGFitToViewBox.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2006, 2007, 2010 Rob Buis <buis@kde.org>
4  * Copyright (C) 2018 Apple Inc. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #include "config.h"
23 #include "SVGFitToViewBox.h"
24
25 #include "AffineTransform.h"
26 #include "Document.h"
27 #include "FloatRect.h"
28 #include "SVGDocumentExtensions.h"
29 #include "SVGElement.h"
30 #include "SVGNames.h"
31 #include "SVGParserUtilities.h"
32 #include "SVGPreserveAspectRatioValue.h"
33 #include <wtf/text/StringView.h>
34
35 namespace WebCore {
36
37 SVGFitToViewBox::SVGFitToViewBox(SVGElement* contextElement, SVGPropertyAccess access)
38     : m_viewBox(SVGAnimatedRect::create(contextElement, access))
39     , m_preserveAspectRatio(SVGAnimatedPreserveAspectRatio::create(contextElement, access))
40 {
41     static std::once_flag onceFlag;
42     std::call_once(onceFlag, [] {
43         PropertyRegistry::registerProperty<SVGNames::viewBoxAttr, &SVGFitToViewBox::m_viewBox>();
44         PropertyRegistry::registerProperty<SVGNames::preserveAspectRatioAttr, &SVGFitToViewBox::m_preserveAspectRatio>();
45     });
46 }
47
48 void SVGFitToViewBox::setViewBox(const FloatRect& viewBox)
49 {
50     m_viewBox->setBaseValInternal(viewBox);
51     m_isViewBoxValid = true;
52 }
53
54 void SVGFitToViewBox::resetViewBox()
55 {
56     m_viewBox->setBaseValInternal({ });
57     m_isViewBoxValid = false;
58 }
59
60 void SVGFitToViewBox::reset()
61 {
62     resetViewBox();
63     resetPreserveAspectRatio();
64 }
65
66 bool SVGFitToViewBox::parseAttribute(const QualifiedName& name, const AtomString& value)
67 {
68     if (name == SVGNames::viewBoxAttr) {
69         FloatRect viewBox;
70         if (!value.isNull() && parseViewBox(value, viewBox))
71             setViewBox(viewBox);
72         else
73             resetViewBox();
74         return true;
75     }
76
77     if (name == SVGNames::preserveAspectRatioAttr) {
78         SVGPreserveAspectRatioValue preserveAspectRatio;
79         preserveAspectRatio.parse(value);
80         setPreserveAspectRatio(preserveAspectRatio);
81         return true;
82     }
83
84     return false;
85 }
86
87 bool SVGFitToViewBox::parseViewBox(const AtomString& value, FloatRect& viewBox)
88 {
89     auto upconvertedCharacters = StringView(value).upconvertedCharacters();
90     const UChar* characters = upconvertedCharacters;
91     return parseViewBox(characters, characters + value.length(), viewBox);
92 }
93
94 bool SVGFitToViewBox::parseViewBox(const UChar*& c, const UChar* end, FloatRect& viewBox, bool validate)
95 {
96     String str(c, end - c);
97
98     skipOptionalSVGSpaces(c, end);
99
100     float x = 0.0f;
101     float y = 0.0f;
102     float width = 0.0f;
103     float height = 0.0f;
104     bool valid = parseNumber(c, end, x) && parseNumber(c, end, y) && parseNumber(c, end, width) && parseNumber(c, end, height, false);
105
106     if (validate) {
107         Document& document = m_viewBox->contextElement()->document();
108
109         if (!valid) {
110             document.accessSVGExtensions().reportWarning("Problem parsing viewBox=\"" + str + "\"");
111             return false;
112         }
113
114         // Check that width is positive.
115         if (width < 0.0) {
116             document.accessSVGExtensions().reportError("A negative value for ViewBox width is not allowed");
117             return false;
118         }
119
120         // Check that height is positive.
121         if (height < 0.0) {
122             document.accessSVGExtensions().reportError("A negative value for ViewBox height is not allowed");
123             return false;
124         }
125
126         // Nothing should come after the last, fourth number.
127         skipOptionalSVGSpaces(c, end);
128         if (c < end) {
129             document.accessSVGExtensions().reportWarning("Problem parsing viewBox=\"" + str + "\"");
130             return false;
131         }
132     }
133
134     viewBox = { x, y, width, height };
135     return true;
136 }
137
138 AffineTransform SVGFitToViewBox::viewBoxToViewTransform(const FloatRect& viewBoxRect, const SVGPreserveAspectRatioValue& preserveAspectRatio, float viewWidth, float viewHeight)
139 {
140     if (!viewBoxRect.width() || !viewBoxRect.height() || !viewWidth || !viewHeight)
141         return AffineTransform();
142
143     return preserveAspectRatio.getCTM(viewBoxRect.x(), viewBoxRect.y(), viewBoxRect.width(), viewBoxRect.height(), viewWidth, viewHeight);
144 }
145
146 }