1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "mozilla/Util.h"
39 :
40 : #include "nsCOMPtr.h"
41 : #include "nsIDOMHTMLFontElement.h"
42 : #include "nsIDOMEventTarget.h"
43 : #include "nsGenericHTMLElement.h"
44 : #include "nsGkAtoms.h"
45 : #include "nsStyleConsts.h"
46 : #include "nsPresContext.h"
47 : #include "nsMappedAttributes.h"
48 : #include "nsRuleData.h"
49 : #include "nsIDocument.h"
50 : #include "nsAlgorithm.h"
51 :
52 : using namespace mozilla;
53 :
54 : class nsHTMLFontElement : public nsGenericHTMLElement,
55 : public nsIDOMHTMLFontElement
56 : {
57 : public:
58 : nsHTMLFontElement(already_AddRefed<nsINodeInfo> aNodeInfo);
59 : virtual ~nsHTMLFontElement();
60 :
61 : // nsISupports
62 : NS_DECL_ISUPPORTS_INHERITED
63 :
64 : // nsIDOMNode
65 0 : NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
66 :
67 : // nsIDOMElement
68 0 : NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
69 :
70 : // nsIDOMHTMLElement
71 0 : NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
72 :
73 : // nsIDOMHTMLFontElement
74 : NS_DECL_NSIDOMHTMLFONTELEMENT
75 :
76 : virtual bool ParseAttribute(PRInt32 aNamespaceID,
77 : nsIAtom* aAttribute,
78 : const nsAString& aValue,
79 : nsAttrValue& aResult);
80 : NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
81 : virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
82 : virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
83 : virtual nsXPCClassInfo* GetClassInfo();
84 : };
85 :
86 :
87 0 : NS_IMPL_NS_NEW_HTML_ELEMENT(Font)
88 :
89 :
90 0 : nsHTMLFontElement::nsHTMLFontElement(already_AddRefed<nsINodeInfo> aNodeInfo)
91 0 : : nsGenericHTMLElement(aNodeInfo)
92 : {
93 0 : }
94 :
95 0 : nsHTMLFontElement::~nsHTMLFontElement()
96 : {
97 0 : }
98 :
99 0 : NS_IMPL_ADDREF_INHERITED(nsHTMLFontElement, nsGenericElement)
100 0 : NS_IMPL_RELEASE_INHERITED(nsHTMLFontElement, nsGenericElement)
101 :
102 0 : DOMCI_NODE_DATA(HTMLFontElement, nsHTMLFontElement)
103 :
104 : // QueryInterface implementation for nsHTMLFontElement
105 0 : NS_INTERFACE_TABLE_HEAD(nsHTMLFontElement)
106 0 : NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLFontElement, nsIDOMHTMLFontElement)
107 0 : NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLFontElement,
108 : nsGenericHTMLElement)
109 0 : NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFontElement)
110 :
111 :
112 0 : NS_IMPL_ELEMENT_CLONE(nsHTMLFontElement)
113 :
114 :
115 0 : NS_IMPL_STRING_ATTR(nsHTMLFontElement, Color, color)
116 0 : NS_IMPL_STRING_ATTR(nsHTMLFontElement, Face, face)
117 0 : NS_IMPL_STRING_ATTR(nsHTMLFontElement, Size, size)
118 :
119 : static const nsAttrValue::EnumTable kRelFontSizeTable[] = {
120 : { "-10", -10 },
121 : { "-9", -9 },
122 : { "-8", -8 },
123 : { "-7", -7 },
124 : { "-6", -6 },
125 : { "-5", -5 },
126 : { "-4", -4 },
127 : { "-3", -3 },
128 : { "-2", -2 },
129 : { "-1", -1 },
130 : { "-0", 0 },
131 : { "+0", 0 },
132 : { "+1", 1 },
133 : { "+2", 2 },
134 : { "+3", 3 },
135 : { "+4", 4 },
136 : { "+5", 5 },
137 : { "+6", 6 },
138 : { "+7", 7 },
139 : { "+8", 8 },
140 : { "+9", 9 },
141 : { "+10", 10 },
142 : { 0 }
143 : };
144 :
145 :
146 : bool
147 0 : nsHTMLFontElement::ParseAttribute(PRInt32 aNamespaceID,
148 : nsIAtom* aAttribute,
149 : const nsAString& aValue,
150 : nsAttrValue& aResult)
151 : {
152 0 : if (aNamespaceID == kNameSpaceID_None) {
153 0 : if (aAttribute == nsGkAtoms::size) {
154 0 : nsAutoString tmp(aValue);
155 0 : tmp.CompressWhitespace(true, true);
156 0 : PRUnichar ch = tmp.IsEmpty() ? 0 : tmp.First();
157 0 : if ((ch == '+' || ch == '-')) {
158 0 : if (aResult.ParseEnumValue(aValue, kRelFontSizeTable, false))
159 0 : return true;
160 :
161 : // truncate after digit, then parse it again.
162 : PRUint32 i;
163 0 : for (i = 1; i < tmp.Length(); i++) {
164 0 : ch = tmp.CharAt(i);
165 0 : if (!nsCRT::IsAsciiDigit(ch)) {
166 0 : tmp.Truncate(i);
167 0 : break;
168 : }
169 : }
170 0 : return aResult.ParseEnumValue(tmp, kRelFontSizeTable, false);
171 : }
172 :
173 0 : return aResult.ParseIntValue(aValue);
174 : }
175 0 : if (aAttribute == nsGkAtoms::pointSize ||
176 : aAttribute == nsGkAtoms::fontWeight) {
177 0 : return aResult.ParseIntValue(aValue);
178 : }
179 0 : if (aAttribute == nsGkAtoms::color) {
180 0 : return aResult.ParseColor(aValue);
181 : }
182 : }
183 :
184 : return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
185 0 : aResult);
186 : }
187 :
188 : static void
189 0 : MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
190 : nsRuleData* aData)
191 : {
192 0 : if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) {
193 : // face: string list
194 0 : nsCSSValue* family = aData->ValueForFontFamily();
195 0 : if (family->GetUnit() == eCSSUnit_Null) {
196 0 : const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::face);
197 0 : if (value && value->Type() == nsAttrValue::eString &&
198 0 : !value->IsEmptyString()) {
199 0 : family->SetStringValue(value->GetStringValue(), eCSSUnit_Families);
200 : }
201 : }
202 :
203 : // pointSize: int
204 0 : nsCSSValue* fontSize = aData->ValueForFontSize();
205 0 : if (fontSize->GetUnit() == eCSSUnit_Null) {
206 0 : const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::pointSize);
207 0 : if (value && value->Type() == nsAttrValue::eInteger)
208 0 : fontSize->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Point);
209 : else {
210 : // size: int, enum ,
211 0 : value = aAttributes->GetAttr(nsGkAtoms::size);
212 0 : if (value) {
213 0 : nsAttrValue::ValueType unit = value->Type();
214 0 : if (unit == nsAttrValue::eInteger || unit == nsAttrValue::eEnum) {
215 : PRInt32 size;
216 0 : if (unit == nsAttrValue::eEnum) // int (+/-)
217 0 : size = value->GetEnumValue() + 3;
218 : else
219 0 : size = value->GetIntegerValue();
220 :
221 0 : size = clamped(size, 1, 7);
222 0 : fontSize->SetIntValue(size, eCSSUnit_Enumerated);
223 : }
224 : }
225 : }
226 : }
227 :
228 : // fontWeight: int
229 0 : nsCSSValue* fontWeight = aData->ValueForFontWeight();
230 0 : if (fontWeight->GetUnit() == eCSSUnit_Null) {
231 0 : const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::fontWeight);
232 0 : if (value && value->Type() == nsAttrValue::eInteger) // +/-
233 0 : fontWeight->SetIntValue(value->GetIntegerValue(), eCSSUnit_Integer);
234 : }
235 : }
236 0 : if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Color)) {
237 0 : nsCSSValue* colorValue = aData->ValueForColor();
238 0 : if (colorValue->GetUnit() == eCSSUnit_Null &&
239 0 : aData->mPresContext->UseDocumentColors()) {
240 : // color: color
241 0 : const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::color);
242 : nscolor color;
243 0 : if (value && value->GetColorValue(color)) {
244 0 : colorValue->SetColorValue(color);
245 : }
246 : }
247 : }
248 0 : if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TextReset) &&
249 0 : aData->mPresContext->CompatibilityMode() == eCompatibility_NavQuirks) {
250 : // Make <a><font color="red">text</font></a> give the text a red underline
251 : // in quirks mode. The NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL flag only
252 : // affects quirks mode rendering.
253 0 : const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::color);
254 : nscolor color;
255 0 : if (value && value->GetColorValue(color)) {
256 0 : nsCSSValue* decoration = aData->ValueForTextDecorationLine();
257 0 : PRInt32 newValue = NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL;
258 0 : if (decoration->GetUnit() == eCSSUnit_Enumerated) {
259 0 : newValue |= decoration->GetIntValue();
260 : }
261 0 : decoration->SetIntValue(newValue, eCSSUnit_Enumerated);
262 : }
263 : }
264 :
265 0 : nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
266 0 : }
267 :
268 : NS_IMETHODIMP_(bool)
269 0 : nsHTMLFontElement::IsAttributeMapped(const nsIAtom* aAttribute) const
270 : {
271 : static const MappedAttributeEntry attributes[] = {
272 : { &nsGkAtoms::face },
273 : { &nsGkAtoms::pointSize },
274 : { &nsGkAtoms::size },
275 : { &nsGkAtoms::fontWeight },
276 : { &nsGkAtoms::color },
277 : { nsnull }
278 : };
279 :
280 : static const MappedAttributeEntry* const map[] = {
281 : attributes,
282 : sCommonAttributeMap,
283 : };
284 :
285 0 : return FindAttributeDependence(aAttribute, map);
286 : }
287 :
288 :
289 : nsMapRuleToAttributesFunc
290 0 : nsHTMLFontElement::GetAttributeMappingFunction() const
291 : {
292 0 : return &MapAttributesIntoRule;
293 : }
|