1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Simon Hausmann <hausmann@kde.org>
5 * Copyright (C) 2003, 2006, 2008, 2010 Apple Inc. All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23#include "config.h"
24#include "HTMLFontElement.h"
25
26#include "CSSPropertyNames.h"
27#include "CSSStyleSheet.h"
28#include "CSSValueKeywords.h"
29#include "CSSValueList.h"
30#include "CSSValuePool.h"
31#include "HTMLNames.h"
32#include "HTMLParserIdioms.h"
33#include "StyleProperties.h"
34#include <wtf/IsoMallocInlines.h>
35#include <wtf/text/StringBuilder.h>
36
37namespace WebCore {
38
39WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLFontElement);
40
41using namespace HTMLNames;
42
43HTMLFontElement::HTMLFontElement(const QualifiedName& tagName, Document& document)
44 : HTMLElement(tagName, document)
45{
46 ASSERT(hasTagName(fontTag));
47}
48
49Ref<HTMLFontElement> HTMLFontElement::create(const QualifiedName& tagName, Document& document)
50{
51 return adoptRef(*new HTMLFontElement(tagName, document));
52}
53
54// http://www.whatwg.org/specs/web-apps/current-work/multipage/rendering.html#fonts-and-colors
55template <typename CharacterType>
56static bool parseFontSize(const CharacterType* characters, unsigned length, int& size)
57{
58
59 // Step 1
60 // Step 2
61 const CharacterType* position = characters;
62 const CharacterType* end = characters + length;
63
64 // Step 3
65 while (position < end) {
66 if (!isHTMLSpace(*position))
67 break;
68 ++position;
69 }
70
71 // Step 4
72 if (position == end)
73 return false;
74 ASSERT_WITH_SECURITY_IMPLICATION(position < end);
75
76 // Step 5
77 enum {
78 RelativePlus,
79 RelativeMinus,
80 Absolute
81 } mode;
82
83 switch (*position) {
84 case '+':
85 mode = RelativePlus;
86 ++position;
87 break;
88 case '-':
89 mode = RelativeMinus;
90 ++position;
91 break;
92 default:
93 mode = Absolute;
94 break;
95 }
96
97 // Step 6
98 StringBuilder digits;
99 digits.reserveCapacity(16);
100 while (position < end) {
101 if (!isASCIIDigit(*position))
102 break;
103 digits.append(*position++);
104 }
105
106 // Step 7
107 if (digits.isEmpty())
108 return false;
109
110 // Step 8
111 int value;
112
113 if (digits.is8Bit())
114 value = charactersToIntStrict(digits.characters8(), digits.length());
115 else
116 value = charactersToIntStrict(digits.characters16(), digits.length());
117
118 // Step 9
119 if (mode == RelativePlus)
120 value += 3;
121 else if (mode == RelativeMinus)
122 value = 3 - value;
123
124 // Step 10
125 if (value > 7)
126 value = 7;
127
128 // Step 11
129 if (value < 1)
130 value = 1;
131
132 size = value;
133 return true;
134}
135
136static bool parseFontSize(const String& input, int& size)
137{
138 if (input.isEmpty())
139 return false;
140
141 if (input.is8Bit())
142 return parseFontSize(input.characters8(), input.length(), size);
143
144 return parseFontSize(input.characters16(), input.length(), size);
145}
146
147bool HTMLFontElement::cssValueFromFontSizeNumber(const String& s, CSSValueID& size)
148{
149 int num = 0;
150 if (!parseFontSize(s, num))
151 return false;
152
153 switch (num) {
154 case 1:
155 // FIXME: The spec says that we're supposed to use CSSValueXxSmall here.
156 size = CSSValueXSmall;
157 break;
158 case 2:
159 size = CSSValueSmall;
160 break;
161 case 3:
162 size = CSSValueMedium;
163 break;
164 case 4:
165 size = CSSValueLarge;
166 break;
167 case 5:
168 size = CSSValueXLarge;
169 break;
170 case 6:
171 size = CSSValueXxLarge;
172 break;
173 case 7:
174 size = CSSValueWebkitXxxLarge;
175 break;
176 default:
177 ASSERT_NOT_REACHED();
178 }
179 return true;
180}
181
182bool HTMLFontElement::isPresentationAttribute(const QualifiedName& name) const
183{
184 if (name == sizeAttr || name == colorAttr || name == faceAttr)
185 return true;
186 return HTMLElement::isPresentationAttribute(name);
187}
188
189void HTMLFontElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStyleProperties& style)
190{
191 if (name == sizeAttr) {
192 CSSValueID size = CSSValueInvalid;
193 if (cssValueFromFontSizeNumber(value, size))
194 addPropertyToPresentationAttributeStyle(style, CSSPropertyFontSize, size);
195 } else if (name == colorAttr)
196 addHTMLColorToStyle(style, CSSPropertyColor, value);
197 else if (name == faceAttr) {
198 if (auto fontFaceValue = CSSValuePool::singleton().createFontFaceValue(value))
199 style.setProperty(CSSProperty(CSSPropertyFontFamily, WTFMove(fontFaceValue)));
200 } else
201 HTMLElement::collectStyleForPresentationAttribute(name, value, style);
202}
203
204}
205