1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/HTMLHRElement.h"
8 #include "mozilla/dom/HTMLHRElementBinding.h"
10 #include "nsCSSProps.h"
11 #include "nsStyleConsts.h"
12 #include "mozilla/MappedDeclarations.h"
14 NS_IMPL_NS_NEW_HTML_ELEMENT(HR
)
16 namespace mozilla::dom
{
18 HTMLHRElement::HTMLHRElement(
19 already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
)
20 : nsGenericHTMLElement(std::move(aNodeInfo
)) {}
22 HTMLHRElement::~HTMLHRElement() = default;
24 NS_IMPL_ELEMENT_CLONE(HTMLHRElement
)
26 bool HTMLHRElement::ParseAttribute(int32_t aNamespaceID
, nsAtom
* aAttribute
,
27 const nsAString
& aValue
,
28 nsIPrincipal
* aMaybeScriptedPrincipal
,
29 nsAttrValue
& aResult
) {
30 static const nsAttrValue::EnumTable kAlignTable
[] = {
31 {"left", StyleTextAlign::Left
},
32 {"right", StyleTextAlign::Right
},
33 {"center", StyleTextAlign::Center
},
36 if (aNamespaceID
== kNameSpaceID_None
) {
37 if (aAttribute
== nsGkAtoms::width
) {
38 return aResult
.ParseHTMLDimension(aValue
);
40 if (aAttribute
== nsGkAtoms::size
) {
41 return aResult
.ParseIntWithBounds(aValue
, 1, 1000);
43 if (aAttribute
== nsGkAtoms::align
) {
44 return aResult
.ParseEnumValue(aValue
, kAlignTable
, false);
46 if (aAttribute
== nsGkAtoms::color
) {
47 return aResult
.ParseColor(aValue
);
51 return nsGenericHTMLElement::ParseAttribute(aNamespaceID
, aAttribute
, aValue
,
52 aMaybeScriptedPrincipal
, aResult
);
55 void HTMLHRElement::MapAttributesIntoRule(const nsMappedAttributes
* aAttributes
,
56 MappedDeclarations
& aDecls
) {
59 const nsAttrValue
* colorValue
= aAttributes
->GetAttr(nsGkAtoms::color
);
61 bool colorIsSet
= colorValue
&& colorValue
->GetColorValue(color
);
66 noshade
= !!aAttributes
->GetAttr(nsGkAtoms::noshade
);
70 const nsAttrValue
* value
= aAttributes
->GetAttr(nsGkAtoms::align
);
71 if (value
&& value
->Type() == nsAttrValue::eEnum
) {
72 // Map align attribute into auto side margins
73 switch (StyleTextAlign(value
->GetEnumValue())) {
74 case StyleTextAlign::Left
:
75 aDecls
.SetPixelValueIfUnset(eCSSProperty_margin_left
, 0.0f
);
76 aDecls
.SetAutoValueIfUnset(eCSSProperty_margin_right
);
78 case StyleTextAlign::Right
:
79 aDecls
.SetAutoValueIfUnset(eCSSProperty_margin_left
);
80 aDecls
.SetPixelValueIfUnset(eCSSProperty_margin_right
, 0.0f
);
82 case StyleTextAlign::Center
:
83 aDecls
.SetAutoValueIfUnset(eCSSProperty_margin_left
);
84 aDecls
.SetAutoValueIfUnset(eCSSProperty_margin_right
);
87 MOZ_ASSERT_UNREACHABLE("Unknown <hr align> value");
91 if (!aDecls
.PropertyIsSet(eCSSProperty_height
)) {
94 // noshade case: size is set using the border
95 aDecls
.SetAutoValue(eCSSProperty_height
);
98 // the height includes the top and bottom borders that are initially 1px.
99 // for size=1, html.css has a special case rule that makes this work by
100 // removing all but the top border.
101 const nsAttrValue
* value
= aAttributes
->GetAttr(nsGkAtoms::size
);
102 if (value
&& value
->Type() == nsAttrValue::eInteger
) {
103 aDecls
.SetPixelValue(eCSSProperty_height
,
104 (float)value
->GetIntegerValue());
105 } // else use default value from html.css
109 // if not noshade, border styles are dealt with by html.css
112 // if a size is set, use half of it per side, otherwise, use 1px per side
114 bool allSides
= true;
115 value
= aAttributes
->GetAttr(nsGkAtoms::size
);
116 if (value
&& value
->Type() == nsAttrValue::eInteger
) {
117 sizePerSide
= (float)value
->GetIntegerValue() / 2.0f
;
118 if (sizePerSide
< 1.0f
) {
119 // XXX When the pixel bug is fixed, all the special casing for
120 // subpixel borders should be removed.
121 // In the meantime, this makes http://www.microsoft.com/ look right.
126 sizePerSide
= 1.0f
; // default to a 2px high line
128 aDecls
.SetPixelValueIfUnset(eCSSProperty_border_top_width
, sizePerSide
);
130 aDecls
.SetPixelValueIfUnset(eCSSProperty_border_right_width
, sizePerSide
);
131 aDecls
.SetPixelValueIfUnset(eCSSProperty_border_bottom_width
,
133 aDecls
.SetPixelValueIfUnset(eCSSProperty_border_left_width
, sizePerSide
);
136 if (!aDecls
.PropertyIsSet(eCSSProperty_border_top_style
))
137 aDecls
.SetKeywordValue(eCSSProperty_border_top_style
,
138 StyleBorderStyle::Solid
);
140 aDecls
.SetKeywordValueIfUnset(eCSSProperty_border_right_style
,
141 StyleBorderStyle::Solid
);
142 aDecls
.SetKeywordValueIfUnset(eCSSProperty_border_bottom_style
,
143 StyleBorderStyle::Solid
);
144 aDecls
.SetKeywordValueIfUnset(eCSSProperty_border_left_style
,
145 StyleBorderStyle::Solid
);
147 // If it would be noticeable, set the border radius to
148 // 10000px on all corners; this triggers the clamping to make
149 // circular ends. This assumes the <hr> isn't larger than
150 // that in *both* dimensions.
151 for (const nsCSSPropertyID
* props
=
152 nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_radius
);
153 *props
!= eCSSProperty_UNKNOWN
; ++props
) {
154 aDecls
.SetPixelValueIfUnset(*props
, 10000.0f
);
159 // (we got the color attribute earlier)
161 aDecls
.SetColorValueIfUnset(eCSSProperty_color
, color
);
164 nsGenericHTMLElement::MapWidthAttributeInto(aAttributes
, aDecls
);
165 nsGenericHTMLElement::MapCommonAttributesInto(aAttributes
, aDecls
);
169 HTMLHRElement::IsAttributeMapped(const nsAtom
* aAttribute
) const {
170 static const MappedAttributeEntry attributes
[] = {
171 {nsGkAtoms::align
}, {nsGkAtoms::width
}, {nsGkAtoms::size
},
172 {nsGkAtoms::color
}, {nsGkAtoms::noshade
}, {nullptr},
175 static const MappedAttributeEntry
* const map
[] = {
180 return FindAttributeDependence(aAttribute
, map
);
183 nsMapRuleToAttributesFunc
HTMLHRElement::GetAttributeMappingFunction() const {
184 return &MapAttributesIntoRule
;
187 JSObject
* HTMLHRElement::WrapNode(JSContext
* aCx
,
188 JS::Handle
<JSObject
*> aGivenProto
) {
189 return HTMLHRElement_Binding::Wrap(aCx
, this, aGivenProto
);
192 } // namespace mozilla::dom