Implement size presentational hint for hr elements

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
Simon Wülker 2025-06-01 23:37:19 +02:00
parent f710e2cab4
commit da53390f13
3 changed files with 105 additions and 11 deletions

View file

@ -121,7 +121,7 @@ use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmlfieldsetelement::HTMLFieldSetElement;
use crate::dom::htmlfontelement::{HTMLFontElement, HTMLFontElementLayoutHelpers};
use crate::dom::htmlformelement::FormControlElementHelpers;
use crate::dom::htmlhrelement::{HTMLHRElement, HTMLHRLayoutHelpers};
use crate::dom::htmlhrelement::{HTMLHRElement, HTMLHRLayoutHelpers, SizePresentationalHint};
use crate::dom::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementLayoutMethods};
use crate::dom::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers};
use crate::dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers};
@ -1306,6 +1306,47 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
PropertyDeclaration::PaddingRight(cellpadding),
));
}
// https://html.spec.whatwg.org/multipage/rendering.html#the-hr-element-2
if let Some(size_info) = self
.downcast::<HTMLHRElement>()
.and_then(|hr_element| hr_element.get_size_info())
{
match size_info {
SizePresentationalHint::SetHeightTo(height) => {
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::Height(height),
));
},
SizePresentationalHint::SetAllBorderWidthValuesTo(border_width) => {
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BorderLeftWidth(border_width.clone()),
));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BorderRightWidth(border_width.clone()),
));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BorderTopWidth(border_width.clone()),
));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BorderBottomWidth(border_width),
));
},
SizePresentationalHint::SetBottomBorderWidthToZero => {
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BorderBottomWidth(
specified::border::BorderSideWidth::from_px(0.),
),
));
},
}
}
}
fn get_span(self) -> Option<u32> {

View file

@ -2,11 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::str::FromStr;
use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix, local_name, ns};
use js::rust::HandleObject;
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
use style::color::AbsoluteColor;
use style::values::generics::NonNegative;
use style::values::specified::border::BorderSideWidth;
use style::values::specified::length::Size;
use style::values::specified::{LengthPercentage, NoCalcLength};
use crate::dom::bindings::codegen::Bindings::HTMLHRElementBinding::HTMLHRElementMethods;
use crate::dom::bindings::inheritance::Castable;
@ -65,6 +71,18 @@ impl HTMLHRElementMethods<crate::DomTypeHolder> for HTMLHRElement {
// https://html.spec.whatwg.org/multipage/#dom-hr-color
make_legacy_color_setter!(SetColor, "color");
// https://html.spec.whatwg.org/multipage/#dom-hr-noshade
make_bool_getter!(NoShade, "noshade");
// https://html.spec.whatwg.org/multipage/#dom-hr-noshade
make_bool_setter!(SetNoShade, "noshade");
// https://html.spec.whatwg.org/multipage/#dom-hr-size
make_getter!(Size, "size");
// https://html.spec.whatwg.org/multipage/#dom-hr-size
make_dimension_setter!(SetSize, "size");
// https://html.spec.whatwg.org/multipage/#dom-hr-width
make_getter!(Width, "width");
@ -72,9 +90,20 @@ impl HTMLHRElementMethods<crate::DomTypeHolder> for HTMLHRElement {
make_dimension_setter!(SetWidth, "width");
}
/// The result of applying the the presentational hint for the `size` attribute.
///
/// (This attribute can mean different things depending on it's value and other attributes)
#[allow(clippy::enum_variant_names)]
pub(crate) enum SizePresentationalHint {
SetHeightTo(Size),
SetAllBorderWidthValuesTo(BorderSideWidth),
SetBottomBorderWidthToZero,
}
pub(crate) trait HTMLHRLayoutHelpers {
fn get_color(self) -> Option<AbsoluteColor>;
fn get_width(self) -> LengthOrPercentageOrAuto;
fn get_size_info(self) -> Option<SizePresentationalHint>;
}
impl HTMLHRLayoutHelpers for LayoutDom<'_, HTMLHRElement> {
@ -92,6 +121,35 @@ impl HTMLHRLayoutHelpers for LayoutDom<'_, HTMLHRElement> {
.cloned()
.unwrap_or(LengthOrPercentageOrAuto::Auto)
}
fn get_size_info(self) -> Option<SizePresentationalHint> {
// https://html.spec.whatwg.org/multipage/rendering.html#the-hr-element-2
let element = self.upcast::<Element>();
let size_value = element
.get_attr_val_for_layout(&ns!(), &local_name!("size"))
.and_then(|value| usize::from_str(value).ok())
.filter(|value| *value != 0)?;
let hint = if element
.get_attr_for_layout(&ns!(), &local_name!("color"))
.is_some() ||
element
.get_attr_for_layout(&ns!(), &local_name!("noshade"))
.is_some()
{
SizePresentationalHint::SetAllBorderWidthValuesTo(BorderSideWidth::from_px(
size_value as f32 / 2.0,
))
} else if size_value == 1 {
SizePresentationalHint::SetBottomBorderWidthToZero
} else {
SizePresentationalHint::SetHeightTo(Size::LengthPercentage(NonNegative(
LengthPercentage::Length(NoCalcLength::from_px((size_value - 2) as f32)),
)))
};
Some(hint)
}
}
impl VirtualMethods for HTMLHRElement {