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 "Attribute.h" 27#include "CSSPropertyNames.h" 28#include "CSSStyleSheet.h" 29#include "CSSValueKeywords.h" 30#include "CSSValueList.h" 31#include "CSSValuePool.h" 32#include "HTMLNames.h" 33#include "HTMLParserIdioms.h" 34#include "StyleProperties.h" 35#include <wtf/text/StringBuilder.h> 36 37using namespace WTF; 38 39namespace WebCore { 40 41using namespace HTMLNames; 42 43HTMLFontElement::HTMLFontElement(const QualifiedName& tagName, Document& document) 44 : HTMLElement(tagName, document) 45{ 46 ASSERT(hasTagName(fontTag)); 47} 48 49PassRefPtr<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 (RefPtr<CSSValueList> fontFaceValue = cssValuePool().createFontFaceValue(value)) 199 style.setProperty(CSSProperty(CSSPropertyFontFamily, fontFaceValue.release())); 200 } else 201 HTMLElement::collectStyleForPresentationAttribute(name, value, style); 202} 203 204} 205