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 "core/html/HTMLFontElement.h"
25
26#include "core/CSSPropertyNames.h"
27#include "core/CSSValueKeywords.h"
28#include "core/HTMLNames.h"
29#include "core/css/CSSValueList.h"
30#include "core/css/CSSValuePool.h"
31#include "core/css/StylePropertySet.h"
32#include "core/html/parser/HTMLParserIdioms.h"
33#include "wtf/text/StringBuilder.h"
34
35using namespace WTF;
36
37namespace blink {
38
39using namespace HTMLNames;
40
41inline HTMLFontElement::HTMLFontElement(Document& document)
42    : HTMLElement(fontTag, document)
43{
44}
45
46DEFINE_NODE_FACTORY(HTMLFontElement)
47
48// http://www.whatwg.org/specs/web-apps/current-work/multipage/rendering.html#fonts-and-colors
49template <typename CharacterType>
50static bool parseFontSize(const CharacterType* characters, unsigned length, int& size)
51{
52
53    // Step 1
54    // Step 2
55    const CharacterType* position = characters;
56    const CharacterType* end = characters + length;
57
58    // Step 3
59    while (position < end) {
60        if (!isHTMLSpace<CharacterType>(*position))
61            break;
62        ++position;
63    }
64
65    // Step 4
66    if (position == end)
67        return false;
68    ASSERT(position < end);
69
70    // Step 5
71    enum {
72        RelativePlus,
73        RelativeMinus,
74        Absolute
75    } mode;
76
77    switch (*position) {
78    case '+':
79        mode = RelativePlus;
80        ++position;
81        break;
82    case '-':
83        mode = RelativeMinus;
84        ++position;
85        break;
86    default:
87        mode = Absolute;
88        break;
89    }
90
91    // Step 6
92    StringBuilder digits;
93    digits.reserveCapacity(16);
94    while (position < end) {
95        if (!isASCIIDigit(*position))
96            break;
97        digits.append(*position++);
98    }
99
100    // Step 7
101    if (digits.isEmpty())
102        return false;
103
104    // Step 8
105    int value;
106
107    if (digits.is8Bit())
108        value = charactersToIntStrict(digits.characters8(), digits.length());
109    else
110        value = charactersToIntStrict(digits.characters16(), digits.length());
111
112    // Step 9
113    if (mode == RelativePlus)
114        value += 3;
115    else if (mode == RelativeMinus)
116        value = 3 - value;
117
118    // Step 10
119    if (value > 7)
120        value = 7;
121
122    // Step 11
123    if (value < 1)
124        value = 1;
125
126    size = value;
127    return true;
128}
129
130static bool parseFontSize(const String& input, int& size)
131{
132    if (input.isEmpty())
133        return false;
134
135    if (input.is8Bit())
136        return parseFontSize(input.characters8(), input.length(), size);
137
138    return parseFontSize(input.characters16(), input.length(), size);
139}
140
141bool HTMLFontElement::cssValueFromFontSizeNumber(const String& s, CSSValueID& size)
142{
143    int num = 0;
144    if (!parseFontSize(s, num))
145        return false;
146
147    switch (num) {
148    case 1:
149        // FIXME: The spec says that we're supposed to use CSSValueXxSmall here.
150        size = CSSValueXSmall;
151        break;
152    case 2:
153        size = CSSValueSmall;
154        break;
155    case 3:
156        size = CSSValueMedium;
157        break;
158    case 4:
159        size = CSSValueLarge;
160        break;
161    case 5:
162        size = CSSValueXLarge;
163        break;
164    case 6:
165        size = CSSValueXxLarge;
166        break;
167    case 7:
168        size = CSSValueWebkitXxxLarge;
169        break;
170    default:
171        ASSERT_NOT_REACHED();
172    }
173    return true;
174}
175
176bool HTMLFontElement::isPresentationAttribute(const QualifiedName& name) const
177{
178    if (name == sizeAttr || name == colorAttr || name == faceAttr)
179        return true;
180    return HTMLElement::isPresentationAttribute(name);
181}
182
183void HTMLFontElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
184{
185    if (name == sizeAttr) {
186        CSSValueID size = CSSValueInvalid;
187        if (cssValueFromFontSizeNumber(value, size))
188            addPropertyToPresentationAttributeStyle(style, CSSPropertyFontSize, size);
189    } else if (name == colorAttr)
190        addHTMLColorToStyle(style, CSSPropertyColor, value);
191    else if (name == faceAttr) {
192        if (RefPtrWillBeRawPtr<CSSValueList> fontFaceValue = cssValuePool().createFontFaceValue(value))
193            style->setProperty(CSSProperty(CSSPropertyFontFamily, fontFaceValue.release()));
194    } else
195        HTMLElement::collectStyleForPresentationAttribute(name, value, style);
196}
197
198}
199