mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 17:57:35 +00:00
LibWeb+WebContent: Forbid access to underlying type of CSSPixels
Although DistinctNumeric, which is supposed to abstract the underlying type, was used to represent CSSPixels, we have a whole bunch of places in the layout code that assume CSSPixels::value() returns a floating-point type. This assumption makes it difficult to replace the underlying type in CSSPixels with a non-floating type. To make it easier to transition CSSPixels to fixed-point math, one step we can take is to prevent access to the underlying type using value() and instead use explicit conversions with the to_float(), to_double(), and to_int() methods.
This commit is contained in:
parent
5a54c686a7
commit
147c3b3d97
43 changed files with 340 additions and 220 deletions
|
@ -29,7 +29,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
inline void shrink(CSSPixels top, CSSPixels right, CSSPixels bottom, CSSPixels left)
|
||||
{
|
||||
rect.shrink(top, right, bottom, left);
|
||||
radii.shrink(top.value(), right.value(), bottom.value(), left.value());
|
||||
radii.shrink(top, right, bottom, left);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -137,8 +137,8 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
}
|
||||
|
||||
// FIXME: Implement proper default sizing algorithm: https://drafts.csswg.org/css-images/#default-sizing
|
||||
CSSPixels natural_image_width = image.natural_width().value_or(background_positioning_area.width().value());
|
||||
CSSPixels natural_image_height = image.natural_height().value_or(background_positioning_area.height().value());
|
||||
CSSPixels natural_image_width = image.natural_width().value_or(background_positioning_area.width());
|
||||
CSSPixels natural_image_height = image.natural_height().value_or(background_positioning_area.height());
|
||||
|
||||
// If any of these are zero, the NaNs will pop up in the painting code.
|
||||
if (background_positioning_area.is_empty() || natural_image_height <= 0 || natural_image_width <= 0)
|
||||
|
@ -148,15 +148,15 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
CSSPixelRect image_rect;
|
||||
switch (layer.size_type) {
|
||||
case CSS::BackgroundSize::Contain: {
|
||||
double max_width_ratio = (background_positioning_area.width() / natural_image_width).value();
|
||||
double max_height_ratio = (background_positioning_area.height() / natural_image_height).value();
|
||||
double max_width_ratio = (background_positioning_area.width() / natural_image_width).to_double();
|
||||
double max_height_ratio = (background_positioning_area.height() / natural_image_height).to_double();
|
||||
double ratio = min(max_width_ratio, max_height_ratio);
|
||||
image_rect.set_size(natural_image_width * ratio, natural_image_height * ratio);
|
||||
break;
|
||||
}
|
||||
case CSS::BackgroundSize::Cover: {
|
||||
double max_width_ratio = (background_positioning_area.width() / natural_image_width).value();
|
||||
double max_height_ratio = (background_positioning_area.height() / natural_image_height).value();
|
||||
double max_width_ratio = (background_positioning_area.width() / natural_image_width).to_double();
|
||||
double max_height_ratio = (background_positioning_area.height() / natural_image_height).to_double();
|
||||
double ratio = max(max_width_ratio, max_height_ratio);
|
||||
image_rect.set_size(natural_image_width * ratio, natural_image_height * ratio);
|
||||
break;
|
||||
|
@ -247,12 +247,12 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
repeat_x = true;
|
||||
break;
|
||||
case CSS::Repeat::Space: {
|
||||
int whole_images = (background_positioning_area.width() / image_rect.width()).value();
|
||||
int whole_images = (background_positioning_area.width() / image_rect.width()).to_int();
|
||||
if (whole_images <= 1) {
|
||||
x_step = image_rect.width();
|
||||
repeat_x = false;
|
||||
} else {
|
||||
auto space = fmod(background_positioning_area.width(), image_rect.width());
|
||||
auto space = fmod(background_positioning_area.width().to_float(), image_rect.width().to_float());
|
||||
x_step = image_rect.width() + (space / static_cast<double>(whole_images - 1));
|
||||
repeat_x = true;
|
||||
}
|
||||
|
@ -278,12 +278,12 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
repeat_y = true;
|
||||
break;
|
||||
case CSS::Repeat::Space: {
|
||||
int whole_images = (background_positioning_area.height() / image_rect.height()).value();
|
||||
int whole_images = (background_positioning_area.height() / image_rect.height()).to_int();
|
||||
if (whole_images <= 1) {
|
||||
y_step = image_rect.height();
|
||||
repeat_y = false;
|
||||
} else {
|
||||
auto space = fmod(background_positioning_area.height(), image_rect.height());
|
||||
auto space = fmod(background_positioning_area.height().to_float(), image_rect.height().to_float());
|
||||
y_step = image_rect.height() + (static_cast<double>(space) / static_cast<double>(whole_images - 1));
|
||||
repeat_y = true;
|
||||
}
|
||||
|
|
|
@ -33,14 +33,14 @@ BorderRadiiData normalized_border_radii_data(Layout::Node const& node, CSSPixelR
|
|||
|
||||
// Scale overlapping curves according to https://www.w3.org/TR/css-backgrounds-3/#corner-overlap
|
||||
CSSPixels f = 1.0f;
|
||||
auto width_reciprocal = 1.0 / rect.width().value();
|
||||
auto height_reciprocal = 1.0 / rect.height().value();
|
||||
auto width_reciprocal = 1.0 / rect.width().to_double();
|
||||
auto height_reciprocal = 1.0 / rect.height().to_double();
|
||||
f = max(f, width_reciprocal * (top_left_radius_px.horizontal_radius + top_right_radius_px.horizontal_radius));
|
||||
f = max(f, height_reciprocal * (top_right_radius_px.vertical_radius + bottom_right_radius_px.vertical_radius));
|
||||
f = max(f, width_reciprocal * (bottom_left_radius_px.horizontal_radius + bottom_right_radius_px.horizontal_radius));
|
||||
f = max(f, height_reciprocal * (top_left_radius_px.vertical_radius + bottom_left_radius_px.vertical_radius));
|
||||
|
||||
f = 1.0 / f.value();
|
||||
f = 1.0 / f.to_double();
|
||||
|
||||
top_left_radius_px.horizontal_radius *= f;
|
||||
top_left_radius_px.vertical_radius *= f;
|
||||
|
|
|
@ -115,7 +115,7 @@ LinearGradientData resolve_linear_gradient_data(Layout::Node const& node, CSSPix
|
|||
|
||||
auto resolved_color_stops = resolve_color_stop_positions(
|
||||
linear_gradient.color_stop_list(), [&](auto const& length_percentage) {
|
||||
return length_percentage.to_px(node, gradient_length_px).value() / static_cast<double>(gradient_length_px);
|
||||
return length_percentage.to_px(node, gradient_length_px).to_float() / static_cast<float>(gradient_length_px);
|
||||
},
|
||||
linear_gradient.is_repeating());
|
||||
|
||||
|
@ -138,7 +138,7 @@ RadialGradientData resolve_radial_gradient_data(Layout::Node const& node, CSSPix
|
|||
// Start center, goes right to ending point, where the gradient line intersects the ending shape
|
||||
auto resolved_color_stops = resolve_color_stop_positions(
|
||||
radial_gradient.color_stop_list(), [&](auto const& length_percentage) {
|
||||
return (length_percentage.to_px(node, gradient_size.width()) / gradient_size.width()).value();
|
||||
return (length_percentage.to_px(node, gradient_size.width()) / gradient_size.width()).to_float();
|
||||
},
|
||||
radial_gradient.is_repeating());
|
||||
return { resolved_color_stops };
|
||||
|
|
|
@ -44,8 +44,8 @@ void MarkerPaintable::paint(PaintContext& context, PaintPhase phase) const
|
|||
if (auto const* list_style_image = layout_box().list_style_image()) {
|
||||
CSSPixelRect image_rect {
|
||||
0, 0,
|
||||
list_style_image->natural_width().value_or(marker_width.value()),
|
||||
list_style_image->natural_height().value_or(marker_width.value())
|
||||
list_style_image->natural_width().value_or(marker_width),
|
||||
list_style_image->natural_height().value_or(marker_width)
|
||||
};
|
||||
image_rect.center_within(enclosing);
|
||||
|
||||
|
|
|
@ -47,68 +47,68 @@ CSSPixelRect PaintContext::css_viewport_rect() const
|
|||
|
||||
DevicePixels PaintContext::rounded_device_pixels(CSSPixels css_pixels) const
|
||||
{
|
||||
return roundf(css_pixels.value() * m_device_pixels_per_css_pixel);
|
||||
return roundf(css_pixels.to_double() * m_device_pixels_per_css_pixel);
|
||||
}
|
||||
|
||||
DevicePixels PaintContext::enclosing_device_pixels(CSSPixels css_pixels) const
|
||||
{
|
||||
return ceilf(css_pixels.value() * m_device_pixels_per_css_pixel);
|
||||
return ceilf(css_pixels.to_double() * m_device_pixels_per_css_pixel);
|
||||
}
|
||||
|
||||
DevicePixels PaintContext::floored_device_pixels(CSSPixels css_pixels) const
|
||||
{
|
||||
return floorf(css_pixels.value() * m_device_pixels_per_css_pixel);
|
||||
return floorf(css_pixels.to_double() * m_device_pixels_per_css_pixel);
|
||||
}
|
||||
|
||||
DevicePixelPoint PaintContext::rounded_device_point(CSSPixelPoint point) const
|
||||
{
|
||||
return {
|
||||
roundf(point.x().value() * m_device_pixels_per_css_pixel),
|
||||
roundf(point.y().value() * m_device_pixels_per_css_pixel)
|
||||
roundf(point.x().to_double() * m_device_pixels_per_css_pixel),
|
||||
roundf(point.y().to_double() * m_device_pixels_per_css_pixel)
|
||||
};
|
||||
}
|
||||
|
||||
DevicePixelPoint PaintContext::floored_device_point(CSSPixelPoint point) const
|
||||
{
|
||||
return {
|
||||
floorf(point.x().value() * m_device_pixels_per_css_pixel),
|
||||
floorf(point.y().value() * m_device_pixels_per_css_pixel)
|
||||
floorf(point.x().to_double() * m_device_pixels_per_css_pixel),
|
||||
floorf(point.y().to_double() * m_device_pixels_per_css_pixel)
|
||||
};
|
||||
}
|
||||
|
||||
DevicePixelRect PaintContext::enclosing_device_rect(CSSPixelRect rect) const
|
||||
{
|
||||
return {
|
||||
floorf(rect.x().value() * m_device_pixels_per_css_pixel),
|
||||
floorf(rect.y().value() * m_device_pixels_per_css_pixel),
|
||||
ceilf(rect.width().value() * m_device_pixels_per_css_pixel),
|
||||
ceilf(rect.height().value() * m_device_pixels_per_css_pixel)
|
||||
floorf(rect.x().to_double() * m_device_pixels_per_css_pixel),
|
||||
floorf(rect.y().to_double() * m_device_pixels_per_css_pixel),
|
||||
ceilf(rect.width().to_double() * m_device_pixels_per_css_pixel),
|
||||
ceilf(rect.height().to_double() * m_device_pixels_per_css_pixel)
|
||||
};
|
||||
}
|
||||
|
||||
DevicePixelRect PaintContext::rounded_device_rect(CSSPixelRect rect) const
|
||||
{
|
||||
return {
|
||||
roundf(rect.x().value() * m_device_pixels_per_css_pixel),
|
||||
roundf(rect.y().value() * m_device_pixels_per_css_pixel),
|
||||
roundf(rect.width().value() * m_device_pixels_per_css_pixel),
|
||||
roundf(rect.height().value() * m_device_pixels_per_css_pixel)
|
||||
roundf(rect.x().to_double() * m_device_pixels_per_css_pixel),
|
||||
roundf(rect.y().to_double() * m_device_pixels_per_css_pixel),
|
||||
roundf(rect.width().to_double() * m_device_pixels_per_css_pixel),
|
||||
roundf(rect.height().to_double() * m_device_pixels_per_css_pixel)
|
||||
};
|
||||
}
|
||||
|
||||
DevicePixelSize PaintContext::enclosing_device_size(CSSPixelSize size) const
|
||||
{
|
||||
return {
|
||||
ceilf(size.width().value() * m_device_pixels_per_css_pixel),
|
||||
ceilf(size.height().value() * m_device_pixels_per_css_pixel)
|
||||
ceilf(size.width().to_double() * m_device_pixels_per_css_pixel),
|
||||
ceilf(size.height().to_double() * m_device_pixels_per_css_pixel)
|
||||
};
|
||||
}
|
||||
|
||||
DevicePixelSize PaintContext::rounded_device_size(CSSPixelSize size) const
|
||||
{
|
||||
return {
|
||||
roundf(size.width().value() * m_device_pixels_per_css_pixel),
|
||||
roundf(size.height().value() * m_device_pixels_per_css_pixel)
|
||||
roundf(size.width().to_double() * m_device_pixels_per_css_pixel),
|
||||
roundf(size.height().to_double() * m_device_pixels_per_css_pixel)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -235,10 +235,10 @@ Gfx::FloatMatrix4x4 StackingContext::get_transformation_matrix(CSS::Transformati
|
|||
return transformation.values[index].visit(
|
||||
[this, reference_length](CSS::LengthPercentage const& value) -> double {
|
||||
if (reference_length.has_value()) {
|
||||
return value.resolved(m_box, reference_length.value()).to_px(m_box).value();
|
||||
return value.resolved(m_box, reference_length.value()).to_px(m_box).to_float();
|
||||
}
|
||||
|
||||
return value.length().to_px(m_box).value();
|
||||
return value.length().to_px(m_box).to_float();
|
||||
},
|
||||
[this](CSS::AngleOrCalculated const& value) {
|
||||
return value.resolved(m_box).to_degrees() * M_DEG2RAD;
|
||||
|
@ -431,7 +431,7 @@ Gfx::FloatPoint StackingContext::compute_transform_origin() const
|
|||
auto reference_box = paintable_box().absolute_border_box_rect();
|
||||
auto x = reference_box.left() + style_value.x.to_px(m_box, reference_box.width());
|
||||
auto y = reference_box.top() + style_value.y.to_px(m_box, reference_box.height());
|
||||
return { static_cast<float>(x.value()), static_cast<float>(y.value()) };
|
||||
return { x.to_float(), y.to_float() };
|
||||
}
|
||||
|
||||
template<typename U, typename Callback>
|
||||
|
@ -472,14 +472,14 @@ Optional<HitTestResult> StackingContext::hit_test(CSSPixelPoint position, HitTes
|
|||
auto transform_origin = this->transform_origin().to_type<CSSPixels>();
|
||||
// NOTE: This CSSPixels -> Float -> CSSPixels conversion is because we can't AffineTransform::map() a CSSPixelPoint.
|
||||
Gfx::FloatPoint offset_position {
|
||||
position.x().value() - transform_origin.x().value(),
|
||||
position.y().value() - transform_origin.y().value()
|
||||
(position.x() - transform_origin.x()).to_float(),
|
||||
(position.y() - transform_origin.y()).to_float()
|
||||
};
|
||||
auto transformed_position = affine_transform_matrix().inverse().value_or({}).map(offset_position).to_type<CSSPixels>() + transform_origin;
|
||||
|
||||
// FIXME: Support more overflow variations.
|
||||
if (paintable_box().computed_values().overflow_x() == CSS::Overflow::Hidden && paintable_box().computed_values().overflow_y() == CSS::Overflow::Hidden) {
|
||||
if (!paintable_box().absolute_border_box_rect().contains(transformed_position.x().value(), transformed_position.y().value()))
|
||||
if (!paintable_box().absolute_border_box_rect().contains(transformed_position.x(), transformed_position.y()))
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -502,7 +502,7 @@ Optional<HitTestResult> StackingContext::hit_test(CSSPixelPoint position, HitTes
|
|||
for_each_in_subtree_of_type_within_same_stacking_context_in_reverse<PaintableBox>(paintable_box(), [&](PaintableBox const& paintable_box) {
|
||||
// FIXME: Support more overflow variations.
|
||||
if (paintable_box.computed_values().overflow_x() == CSS::Overflow::Hidden && paintable_box.computed_values().overflow_y() == CSS::Overflow::Hidden) {
|
||||
if (!paintable_box.absolute_border_box_rect().contains(transformed_position.x().value(), transformed_position.y().value()))
|
||||
if (!paintable_box.absolute_border_box_rect().contains(transformed_position.x(), transformed_position.y()))
|
||||
return TraversalDecision::SkipChildrenAndContinue;
|
||||
}
|
||||
|
||||
|
@ -542,7 +542,7 @@ Optional<HitTestResult> StackingContext::hit_test(CSSPixelPoint position, HitTes
|
|||
for_each_in_subtree_of_type_within_same_stacking_context_in_reverse<PaintableBox>(paintable_box(), [&](PaintableBox const& paintable_box) {
|
||||
// FIXME: Support more overflow variations.
|
||||
if (paintable_box.computed_values().overflow_x() == CSS::Overflow::Hidden && paintable_box.computed_values().overflow_y() == CSS::Overflow::Hidden) {
|
||||
if (!paintable_box.absolute_border_box_rect().contains(transformed_position.x().value(), transformed_position.y().value()))
|
||||
if (!paintable_box.absolute_border_box_rect().contains(transformed_position.x(), transformed_position.y()))
|
||||
return TraversalDecision::SkipChildrenAndContinue;
|
||||
}
|
||||
|
||||
|
@ -563,7 +563,7 @@ Optional<HitTestResult> StackingContext::hit_test(CSSPixelPoint position, HitTes
|
|||
for_each_in_subtree_of_type_within_same_stacking_context_in_reverse<PaintableBox>(paintable_box(), [&](PaintableBox const& paintable_box) {
|
||||
// FIXME: Support more overflow variations.
|
||||
if (paintable_box.computed_values().overflow_x() == CSS::Overflow::Hidden && paintable_box.computed_values().overflow_y() == CSS::Overflow::Hidden) {
|
||||
if (!paintable_box.absolute_border_box_rect().contains(transformed_position.x().value(), transformed_position.y().value()))
|
||||
if (!paintable_box.absolute_border_box_rect().contains(transformed_position.x(), transformed_position.y()))
|
||||
return TraversalDecision::SkipChildrenAndContinue;
|
||||
}
|
||||
|
||||
|
@ -592,7 +592,7 @@ Optional<HitTestResult> StackingContext::hit_test(CSSPixelPoint position, HitTes
|
|||
}
|
||||
|
||||
// 1. the background and borders of the element forming the stacking context.
|
||||
if (paintable_box().absolute_border_box_rect().contains(transformed_position.x().value(), transformed_position.y().value())) {
|
||||
if (paintable_box().absolute_border_box_rect().contains(transformed_position.x(), transformed_position.y())) {
|
||||
return HitTestResult {
|
||||
.paintable = const_cast<PaintableBox&>(paintable_box()),
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue