1/*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
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#pragma once
23
24#include "CSSParser.h"
25#include "Color.h"
26#include "FloatPoint.h"
27#include "FloatRect.h"
28#include "QualifiedName.h"
29#include "SVGParserUtilities.h"
30#include <wtf/text/StringBuilder.h>
31#include <wtf/text/WTFString.h>
32
33namespace WebCore {
34
35template<typename PropertyType>
36struct SVGPropertyTraits { };
37
38template<>
39struct SVGPropertyTraits<bool> {
40 static bool initialValue() { return false; }
41 static bool fromString(const String& string) { return string == "true"; }
42 static Optional<bool> parse(const QualifiedName&, const String&) { ASSERT_NOT_REACHED(); return initialValue(); }
43 static String toString(bool type) { return type ? "true" : "false"; }
44};
45
46template<>
47struct SVGPropertyTraits<Color> {
48 static Color initialValue() { return Color(); }
49 static Color fromString(const String& string) { return CSSParser::parseColor(string.stripWhiteSpace()); }
50 static Optional<Color> parse(const QualifiedName&, const String& string)
51 {
52 Color color = CSSParser::parseColor(string.stripWhiteSpace());
53 if (!color.isValid())
54 return WTF::nullopt;
55 return color;
56 }
57 static String toString(const Color& type) { return type.serialized(); }
58};
59
60template<>
61struct SVGPropertyTraits<unsigned> {
62 static unsigned initialValue() { return 0; }
63 static Optional<unsigned> parse(const QualifiedName&, const String&) { ASSERT_NOT_REACHED(); return initialValue(); }
64 static String toString(unsigned type) { return String::number(type); }
65};
66
67template<>
68struct SVGPropertyTraits<int> {
69 static int initialValue() { return 0; }
70 static int fromString(const String&string) { return string.toIntStrict(); }
71 static Optional<int> parse(const QualifiedName&, const String&) { ASSERT_NOT_REACHED(); return initialValue(); }
72 static String toString(int type) { return String::number(type); }
73};
74
75template<>
76struct SVGPropertyTraits<std::pair<int, int>> {
77 static std::pair<int, int> initialValue() { return { }; }
78 static std::pair<int, int> fromString(const String& string)
79 {
80 float firstNumber = 0, secondNumber = 0;
81 if (!parseNumberOptionalNumber(string, firstNumber, secondNumber))
82 return { };
83 return std::make_pair(static_cast<int>(roundf(firstNumber)), static_cast<int>(roundf(secondNumber)));
84 }
85 static Optional<std::pair<int, int>> parse(const QualifiedName&, const String&) { ASSERT_NOT_REACHED(); return initialValue(); }
86 static String toString(std::pair<int, int>) { ASSERT_NOT_REACHED(); return emptyString(); }
87};
88
89template<>
90struct SVGPropertyTraits<float> {
91 static float initialValue() { return 0; }
92 static float fromString(const String& string)
93 {
94 float number = 0;
95 if (!parseNumberFromString(string, number))
96 return 0;
97 return number;
98 }
99 static Optional<float> parse(const QualifiedName&, const String& string)
100 {
101 float number;
102 if (!parseNumberFromString(string, number))
103 return WTF::nullopt;
104 return number;
105 }
106 static String toString(float type) { return String::numberToStringFixedPrecision(type); }
107};
108
109template<>
110struct SVGPropertyTraits<std::pair<float, float>> {
111 static std::pair<float, float> initialValue() { return { }; }
112 static std::pair<float, float> fromString(const String& string)
113 {
114 float firstNumber = 0, secondNumber = 0;
115 if (!parseNumberOptionalNumber(string, firstNumber, secondNumber))
116 return { };
117 return std::make_pair(firstNumber, secondNumber);
118 }
119 static Optional<std::pair<float, float>> parse(const QualifiedName&, const String&) { ASSERT_NOT_REACHED(); return initialValue(); }
120 static String toString(std::pair<float, float>) { ASSERT_NOT_REACHED(); return emptyString(); }
121};
122
123template<>
124struct SVGPropertyTraits<FloatPoint> {
125 static FloatPoint initialValue() { return FloatPoint(); }
126 static FloatPoint fromString(const String& string)
127 {
128 FloatPoint point;
129 if (!parsePoint(string, point))
130 return { };
131 return point;
132 }
133 static Optional<FloatPoint> parse(const QualifiedName&, const String& string)
134 {
135 FloatPoint point;
136 if (!parsePoint(string, point))
137 return WTF::nullopt;
138 return point;
139 }
140 static String toString(const FloatPoint& type)
141 {
142 StringBuilder builder;
143 builder.appendFixedPrecisionNumber(type.x());
144 builder.append(' ');
145 builder.appendFixedPrecisionNumber(type.y());
146 return builder.toString();
147 }
148};
149
150template<>
151struct SVGPropertyTraits<FloatRect> {
152 static FloatRect initialValue() { return FloatRect(); }
153 static FloatRect fromString(const String& string)
154 {
155 FloatRect rect;
156 if (!parseRect(string, rect))
157 return { };
158 return rect;
159 }
160 static Optional<FloatRect> parse(const QualifiedName&, const String& string)
161 {
162 FloatRect rect;
163 if (!parseRect(string, rect))
164 return WTF::nullopt;
165 return rect;
166 }
167 static String toString(const FloatRect& type)
168 {
169 StringBuilder builder;
170 builder.appendFixedPrecisionNumber(type.x());
171 builder.append(' ');
172 builder.appendFixedPrecisionNumber(type.y());
173 builder.append(' ');
174 builder.appendFixedPrecisionNumber(type.width());
175 builder.append(' ');
176 builder.appendFixedPrecisionNumber(type.height());
177 return builder.toString();
178 }
179};
180
181template<>
182struct SVGPropertyTraits<String> {
183 static String initialValue() { return String(); }
184 static String fromString(const String& string) { return string; }
185 static Optional<String> parse(const QualifiedName&, const String& string) { return string; }
186 static String toString(const String& string) { return string; }
187};
188
189template<typename EnumType>
190struct SVGIDLEnumLimits {
191 // Specialize this function for a particular enumeration to limit the values that are exposed through the DOM.
192 static unsigned highestExposedEnumValue() { return SVGPropertyTraits<EnumType>::highestEnumValue(); }
193};
194
195} // namespace WebCore
196