1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 21:57:35 +00:00

LibWeb: Make CSSPixels and Length use 64-bit (double) floating point

This fixes a plethora of rounding problems on many websites.
In the future, we may want to replace this with fixed-point arithmetic
(bug #18566) for performance (and consistency with other engines),
but in the meantime this makes the web look a bit better. :^)

There's a lot more things that could be converted to doubles, which
would reduce the amount of casting necessary in this patch.
We can do that incrementally, however.
This commit is contained in:
Andreas Kling 2023-05-24 10:50:57 +02:00
parent 30262d7023
commit 655d9d1462
80 changed files with 298 additions and 299 deletions

View file

@ -994,7 +994,7 @@ void BlockFormattingContext::layout_list_item_marker(ListItemBox const& list_ite
marker_state.set_content_height(max(image_height, marker.font().pixel_size_rounded_up() + 1).value());
marker_state.set_content_offset({ -(marker_state.content_width() + default_marker_width),
max(CSSPixels(0.f), (CSSPixels(marker.line_height()) - marker_state.content_height()) / 2.f) });
max(CSSPixels(0), (CSSPixels(marker.line_height()) - marker_state.content_height()) / 2) });
if (marker_state.content_height() > list_item_state.content_height())
list_item_state.set_content_height(marker_state.content_height());

View file

@ -577,7 +577,7 @@ CSS::FlexBasisData FlexFormattingContext::used_flex_basis_for_item(FlexItem cons
return flex_basis;
}
CSSPixels FlexFormattingContext::calculate_main_size_from_cross_size_and_aspect_ratio(CSSPixels cross_size, float aspect_ratio) const
CSSPixels FlexFormattingContext::calculate_main_size_from_cross_size_and_aspect_ratio(CSSPixels cross_size, double aspect_ratio) const
{
if (is_row_layout())
return cross_size * aspect_ratio;
@ -717,7 +717,7 @@ void FlexFormattingContext::determine_flex_base_size_and_hypothetical_main_size(
// The hypothetical main size is the items flex base size clamped according to its used min and max main sizes (and flooring the content box size at zero).
auto clamp_min = has_main_min_size(child_box) ? specified_main_min_size(child_box) : automatic_minimum_size(item);
auto clamp_max = has_main_max_size(child_box) ? specified_main_max_size(child_box) : NumericLimits<float>::max();
item.hypothetical_main_size = max(CSSPixels(0.0f), css_clamp(item.flex_base_size, clamp_min, clamp_max));
item.hypothetical_main_size = max(CSSPixels(0), css_clamp(item.flex_base_size, clamp_min, clamp_max));
// NOTE: At this point, we set the hypothetical main size as the flex item's *temporary* main size.
// The size may change again when we resolve flexible lengths, but this is necessary in order for
@ -1006,7 +1006,7 @@ void FlexFormattingContext::resolve_flexible_lengths_for_line(FlexLine& line)
for (auto& item : line.items) {
if (item.frozen)
continue;
float ratio = item.flex_factor.value() / sum_of_flex_factor_of_unfrozen_items;
double ratio = item.flex_factor.value() / sum_of_flex_factor_of_unfrozen_items;
// Set the items target main size to its flex base size plus a fraction of the remaining free space proportional to the ratio.
item.target_main_size = item.flex_base_size + (line.remaining_free_space * ratio);
}
@ -1024,7 +1024,7 @@ void FlexFormattingContext::resolve_flexible_lengths_for_line(FlexLine& line)
if (item.frozen)
continue;
// Find the ratio of the items scaled flex shrink factor to the sum of the scaled flex shrink factors of all unfrozen items on the line.
float ratio = 1.0f;
double ratio = 1.0;
if (sum_of_scaled_flex_shrink_factors_of_all_unfrozen_items_on_line != 0)
ratio = item.scaled_flex_shrink_factor / sum_of_scaled_flex_shrink_factors_of_all_unfrozen_items_on_line;
@ -1207,7 +1207,7 @@ void FlexFormattingContext::calculate_cross_size_of_each_flex_line()
}
// 3. The used cross-size of the flex line is the largest of the numbers found in the previous two steps and zero.
flex_line.cross_size = max(CSSPixels(0.0f), largest_hypothetical_cross_size);
flex_line.cross_size = max(CSSPixels(0), largest_hypothetical_cross_size);
}
// If the flex container is single-line, then clamp the lines cross-size to be within the containers computed min and max cross sizes.
@ -1276,7 +1276,7 @@ void FlexFormattingContext::distribute_any_remaining_free_space()
used_main_space += main_gap() * (flex_line.items.size() - 1);
if (flex_line.remaining_free_space > 0) {
CSSPixels size_per_auto_margin = flex_line.remaining_free_space / (float)auto_margins;
CSSPixels size_per_auto_margin = flex_line.remaining_free_space / static_cast<double>(auto_margins);
for (auto& item : flex_line.items) {
if (item.margins.main_before_is_auto)
set_main_axis_first_margin(item, size_per_auto_margin);
@ -1317,7 +1317,7 @@ void FlexFormattingContext::distribute_any_remaining_free_space()
}
break;
case CSS::JustifyContent::Center:
initial_offset = (inner_main_size(flex_container()) - used_main_space) / 2.0f;
initial_offset = (inner_main_size(flex_container()) - used_main_space) / 2.0;
if (is_direction_reverse()) {
initial_offset = inner_main_size(flex_container()) - initial_offset;
}
@ -1327,7 +1327,7 @@ void FlexFormattingContext::distribute_any_remaining_free_space()
break;
case CSS::JustifyContent::SpaceAround:
space_between_items = flex_line.remaining_free_space / number_of_items;
initial_offset = space_between_items / 2.0f;
initial_offset = space_between_items / 2.0;
break;
}
}
@ -1443,7 +1443,7 @@ void FlexFormattingContext::align_all_flex_items_along_the_cross_axis()
// FIXME: Take better care of margins
for (auto& flex_line : m_flex_lines) {
for (auto& item : flex_line.items) {
CSSPixels half_line_size = flex_line.cross_size / 2.0f;
CSSPixels half_line_size = flex_line.cross_size / 2.0;
switch (alignment_for_item(item.box)) {
case CSS::AlignItems::Baseline:
// FIXME: Implement this
@ -1456,7 +1456,7 @@ void FlexFormattingContext::align_all_flex_items_along_the_cross_axis()
item.cross_offset = half_line_size - item.cross_size.value() - item.margins.cross_after - item.borders.cross_after - item.padding.cross_after;
break;
case CSS::AlignItems::Center:
item.cross_offset = -(item.cross_size.value() / 2.0f);
item.cross_offset = -(item.cross_size.value() / 2.0);
break;
default:
break;
@ -1511,7 +1511,7 @@ void FlexFormattingContext::align_all_flex_lines()
if (is_single_line()) {
// For single-line flex containers, we only need to center the line along the cross axis.
auto& flex_line = m_flex_lines[0];
CSSPixels center_of_line = cross_size_of_flex_container / 2.0f;
CSSPixels center_of_line = cross_size_of_flex_container / 2.0;
for (auto& item : flex_line.items) {
item.cross_offset += center_of_line;
}
@ -1711,9 +1711,9 @@ CSSPixels FlexFormattingContext::calculate_intrinsic_main_size_of_flex_container
// and the chosen flex fraction, then clamp that result by the max main size floored by the min main size.
CSSPixels sum = 0;
for (auto& item : flex_line.items) {
float product = 0;
double product = 0;
if (item.desired_flex_fraction > 0)
product = flex_line.chosen_flex_fraction * item.box->computed_values().flex_grow();
product = flex_line.chosen_flex_fraction * static_cast<double>(item.box->computed_values().flex_grow());
else if (item.desired_flex_fraction < 0)
product = flex_line.chosen_flex_fraction * item.scaled_flex_shrink_factor;
auto result = item.flex_base_size + product;
@ -2036,8 +2036,8 @@ void FlexFormattingContext::resolve_cross_axis_auto_margins()
if (outer_cross_size < line.cross_size) {
CSSPixels remainder = line.cross_size - outer_cross_size;
if (item.margins.cross_before_is_auto && item.margins.cross_after_is_auto) {
item.margins.cross_before = remainder / 2.0f;
item.margins.cross_after = remainder / 2.0f;
item.margins.cross_before = remainder / 2.0;
item.margins.cross_after = remainder / 2.0;
} else if (item.margins.cross_before_is_auto) {
item.margins.cross_before = remainder;
} else {
@ -2110,13 +2110,13 @@ CSSPixelPoint FlexFormattingContext::calculate_static_position(Box const& box) c
cross_offset = half_line_size - inner_cross_size(box) - cross_margin_after - cross_border_after - cross_padding_after;
break;
case CSS::AlignItems::Center:
cross_offset = -(inner_cross_size(box) / 2.0f);
cross_offset = -(inner_cross_size(box) / 2.0);
break;
default:
break;
}
cross_offset += inner_cross_size(flex_container()) / 2.0f;
cross_offset += inner_cross_size(flex_container()) / 2.0;
// The main-axis edges of the static-position rectangle are where the margin edges of the child
// would be positioned if it were the sole flex item in the flex container,
@ -2161,7 +2161,7 @@ CSSPixelPoint FlexFormattingContext::calculate_static_position(Box const& box) c
break;
case CSS::JustifyContent::Center:
case CSS::JustifyContent::SpaceAround:
main_offset = inner_main_size(flex_container()) / 2.0f - inner_main_size(box) / 2.0f;
main_offset = inner_main_size(flex_container()) / 2.0 - inner_main_size(box) / 2.0;
break;
}
@ -2185,9 +2185,9 @@ CSSPixelPoint FlexFormattingContext::calculate_static_position(Box const& box) c
return static_position_offset + diff;
}
float FlexFormattingContext::FlexLine::sum_of_flex_factor_of_unfrozen_items() const
double FlexFormattingContext::FlexLine::sum_of_flex_factor_of_unfrozen_items() const
{
float sum = 0;
double sum = 0;
for (auto const& item : items) {
if (!item.frozen)
sum += item.flex_factor.value();
@ -2195,9 +2195,9 @@ float FlexFormattingContext::FlexLine::sum_of_flex_factor_of_unfrozen_items() co
return sum;
}
float FlexFormattingContext::FlexLine::sum_of_scaled_flex_shrink_factor_of_unfrozen_items() const
double FlexFormattingContext::FlexLine::sum_of_scaled_flex_shrink_factor_of_unfrozen_items() const
{
float sum = 0;
double sum = 0;
for (auto const& item : items) {
if (!item.frozen)
sum += item.scaled_flex_shrink_factor;

View file

@ -35,7 +35,7 @@ private:
[[nodiscard]] bool should_treat_cross_size_as_auto(Box const&) const;
[[nodiscard]] CSSPixels adjust_main_size_through_aspect_ratio_for_cross_size_min_max_constraints(Box const&, CSSPixels main_size, CSS::Size const& min_cross_size, CSS::Size const& max_cross_size) const;
[[nodiscard]] CSSPixels calculate_main_size_from_cross_size_and_aspect_ratio(CSSPixels cross_size, float aspect_ratio) const;
[[nodiscard]] CSSPixels calculate_main_size_from_cross_size_and_aspect_ratio(CSSPixels cross_size, double aspect_ratio) const;
void dump_items() const;
@ -61,9 +61,9 @@ private:
CSSPixels hypothetical_cross_size_with_margins() { return hypothetical_cross_size + margins.cross_before + margins.cross_after + borders.cross_after + borders.cross_before + padding.cross_after + padding.cross_before; }
CSSPixels target_main_size { 0 };
bool frozen { false };
Optional<float> flex_factor {};
float scaled_flex_shrink_factor { 0 };
float desired_flex_fraction { 0 };
Optional<double> flex_factor {};
double scaled_flex_shrink_factor { 0 };
double desired_flex_fraction { 0 };
CSSPixels outer_hypothetical_main_size() const
{
@ -109,10 +109,10 @@ private:
Vector<FlexItem&> items;
CSSPixels cross_size { 0 };
CSSPixels remaining_free_space { 0 };
float chosen_flex_fraction { 0 };
double chosen_flex_fraction { 0 };
float sum_of_flex_factor_of_unfrozen_items() const;
float sum_of_scaled_flex_shrink_factor_of_unfrozen_items() const;
double sum_of_flex_factor_of_unfrozen_items() const;
double sum_of_scaled_flex_shrink_factor_of_unfrozen_items() const;
};
CSSPixels main_gap() const;

View file

@ -391,7 +391,7 @@ CSSPixels FormattingContext::tentative_width_for_replaced_element(LayoutState co
// (used height) * (intrinsic ratio)
if ((computed_height.is_auto() && computed_width.is_auto() && !box.has_intrinsic_width() && box.has_intrinsic_height() && box.has_intrinsic_aspect_ratio())
|| (computed_width.is_auto() && !computed_height.is_auto() && box.has_intrinsic_aspect_ratio())) {
return compute_height_for_replaced_element(state, box, available_space) * box.intrinsic_aspect_ratio().value();
return compute_height_for_replaced_element(state, box, available_space) * static_cast<double>(box.intrinsic_aspect_ratio().value());
}
// If 'height' and 'width' both have computed values of 'auto' and the element has an intrinsic ratio but no intrinsic height or width,
@ -486,7 +486,7 @@ CSSPixels FormattingContext::tentative_height_for_replaced_element(LayoutState c
//
// (used width) / (intrinsic ratio)
if (computed_height.is_auto() && box.has_intrinsic_aspect_ratio())
return state.get(box).content_width() / box.intrinsic_aspect_ratio().value();
return state.get(box).content_width() / static_cast<double>(box.intrinsic_aspect_ratio().value());
// Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic height, then that intrinsic height is the used value of 'height'.
if (computed_height.is_auto() && box.has_intrinsic_height())
@ -1280,7 +1280,7 @@ CSSPixels FormattingContext::calculate_min_content_height(Layout::Box const& box
CSSPixels FormattingContext::calculate_max_content_height(Layout::Box const& box, AvailableSize const& available_width) const
{
if (box.has_intrinsic_aspect_ratio() && available_width.is_definite())
return available_width.to_px() / *box.intrinsic_aspect_ratio();
return available_width.to_px() / static_cast<double>(*box.intrinsic_aspect_ratio());
if (box.has_intrinsic_height())
return *box.intrinsic_height();

View file

@ -751,7 +751,7 @@ void GridFormattingContext::resolve_intrinsic_track_sizes(AvailableSpace const&
// 5. If any track still has an infinite growth limit (because, for example, it had no items placed in
// it or it is a flexible track), set its growth limit to its base size.
for (auto& track : tracks_and_gaps) {
if (track.growth_limit == INFINITY) {
if (!isfinite(track.growth_limit.value())) {
track.growth_limit = track.base_size;
}
}
@ -774,7 +774,7 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_si
// 2. Distribute space up to limits:
// FIXME: If a fixed-point type were used to represent CSS pixels, it would be possible to compare with 0
// instead of epsilon.
while (extra_space > NumericLimits<float>().epsilon()) {
while (extra_space > NumericLimits<double>().epsilon()) {
auto all_frozen = all_of(spanned_tracks, [](auto const& track) { return track.base_size_frozen; });
if (all_frozen)
break;
@ -816,7 +816,7 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks_growth_
// 1. Find the space to distribute:
CSSPixels spanned_tracks_sizes_sum = 0;
for (auto& track : spanned_tracks) {
if (track.growth_limit != INFINITY) {
if (isfinite(track.growth_limit.value())) {
spanned_tracks_sizes_sum += track.growth_limit;
} else {
spanned_tracks_sizes_sum += track.base_size;
@ -830,7 +830,7 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks_growth_
// 2. Distribute space up to limits:
// FIXME: If a fixed-point type were used to represent CSS pixels, it would be possible to compare with 0
// instead of epsilon.
while (extra_space > NumericLimits<float>().epsilon()) {
while (extra_space > NumericLimits<double>().epsilon()) {
auto all_frozen = all_of(spanned_tracks, [](auto const& track) { return track.growth_limit_frozen; });
if (all_frozen)
break;
@ -957,7 +957,7 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin
}
distribute_extra_space_across_spanned_tracks_growth_limit(item_min_content_contribution, intrinsic_maximum_tracks);
for (auto& track : spanned_tracks) {
if (track.growth_limit == INFINITY) {
if (!isfinite(track.growth_limit.value())) {
// If the affected size is an infinite growth limit, set it to the tracks base size plus the planned increase.
track.growth_limit = track.base_size + track.planned_increase;
// Mark any tracks whose growth limit changed from infinite to finite in this step as infinitely growable
@ -982,7 +982,7 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin
auto item_max_content_contribution = calculate_max_content_contribution(item, dimension);
distribute_extra_space_across_spanned_tracks_growth_limit(item_max_content_contribution, max_content_maximum_tracks);
for (auto& track : spanned_tracks) {
if (track.growth_limit == INFINITY) {
if (!isfinite(track.growth_limit.value())) {
// If the affected size is an infinite growth limit, set it to the tracks base size plus the planned increase.
track.growth_limit = track.base_size + track.planned_increase;
} else {
@ -1058,7 +1058,7 @@ void GridFormattingContext::maximize_tracks(AvailableSpace const& available_spac
while (free_space_px > 0) {
auto free_space_to_distribute_per_track = free_space_px / tracks.size();
for (auto& track : tracks) {
VERIFY(track.growth_limit != INFINITY);
VERIFY(isfinite(track.growth_limit.value()));
track.base_size = min(track.growth_limit, track.base_size + free_space_to_distribute_per_track);
}
if (get_free_space_px() == free_space_px)

View file

@ -18,7 +18,7 @@
namespace Web::Layout {
constexpr float text_justification_threshold = 0.1;
constexpr double text_justification_threshold = 0.1;
InlineFormattingContext::InlineFormattingContext(LayoutState& state, BlockContainer const& containing_block, BlockFormattingContext& parent)
: FormattingContext(Type::Inline, state, containing_block, &parent)
@ -209,7 +209,7 @@ void InlineFormattingContext::apply_justification_to_fragments(CSS::TextJustify
}
}
CSSPixels justified_space_width = whitespace_count > 0 ? (excess_horizontal_space_including_whitespace / static_cast<float>(whitespace_count)) : 0;
CSSPixels justified_space_width = whitespace_count > 0 ? (excess_horizontal_space_including_whitespace / static_cast<double>(whitespace_count)) : 0;
// This is the amount that each fragment will be offset by. If a whitespace
// fragment is shorter than the justified space width, it increases to push

View file

@ -320,7 +320,7 @@ void LayoutState::UsedValues::set_node(NodeWithStyleAndBoxModelMetrics& node, Us
if (size.is_percentage()) {
if (containing_block_has_definite_size) {
auto containing_block_size = width ? containing_block_used_values->content_width() : containing_block_used_values->content_height();
resolved_definite_size = adjust_for_box_sizing(containing_block_size * size.percentage().as_fraction(), size, width);
resolved_definite_size = adjust_for_box_sizing(containing_block_size * static_cast<double>(size.percentage().as_fraction()), size, width);
return true;
}
return false;

View file

@ -223,7 +223,7 @@ void LineBuilder::update_last_line()
if (length_percentage->is_length())
fragment_baseline += length_percentage->length().to_px(fragment.layout_node());
else if (length_percentage->is_percentage())
fragment_baseline += length_percentage->percentage().as_fraction() * line_height;
fragment_baseline += static_cast<double>(length_percentage->percentage().as_fraction()) * line_height;
}
line_box_baseline = max(line_box_baseline, fragment_baseline);
@ -277,7 +277,7 @@ void LineBuilder::update_last_line()
auto vertical_align_amount = length_percentage->length().to_px(fragment.layout_node());
new_fragment_y = y_value_for_alignment(CSS::VerticalAlign::Baseline) - vertical_align_amount;
} else if (length_percentage->is_percentage()) {
auto vertical_align_amount = length_percentage->percentage().as_fraction() * m_context.containing_block().line_height();
auto vertical_align_amount = static_cast<double>(length_percentage->percentage().as_fraction()) * m_context.containing_block().line_height();
new_fragment_y = y_value_for_alignment(CSS::VerticalAlign::Baseline) - vertical_align_amount;
}
}
@ -305,7 +305,7 @@ void LineBuilder::update_last_line()
if (length_percentage->is_length())
bottom_of_inline_box += length_percentage->length().to_px(fragment.layout_node());
else if (length_percentage->is_percentage())
bottom_of_inline_box += length_percentage->percentage().as_fraction() * m_context.containing_block().line_height();
bottom_of_inline_box += static_cast<double>(length_percentage->percentage().as_fraction()) * m_context.containing_block().line_height();
}
}

View file

@ -609,7 +609,7 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style)
if (border.line_style == CSS::LineStyle::None || border.line_style == CSS::LineStyle::Hidden) {
border.width = 0;
} else {
auto resolve_border_width = [&]() {
auto resolve_border_width = [&]() -> double {
auto value = computed_style.property(width_property);
if (value->is_calculated())
return value->as_calculated().resolve_length(*this)->to_px(*this).value();
@ -619,11 +619,11 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style)
// https://www.w3.org/TR/css-backgrounds-3/#valdef-line-width-thin
switch (value->to_identifier()) {
case CSS::ValueID::Thin:
return 1.0f;
return 1.0;
case CSS::ValueID::Medium:
return 3.0f;
return 3.0;
case CSS::ValueID::Thick:
return 5.0f;
return 5.0;
default:
VERIFY_NOT_REACHED();
}

View file

@ -35,7 +35,7 @@ CSSPixels SVGFormattingContext::automatic_content_height() const
struct ViewBoxTransform {
CSSPixelPoint offset;
float scale_factor;
double scale_factor;
};
// https://svgwg.org/svg2-draft/coords.html#PreserveAspectRatioAttribute
@ -156,7 +156,7 @@ void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, Available
auto& path = dom_node.get_path();
auto path_transform = dom_node.get_transform();
float viewbox_scale = 1;
double viewbox_scale = 1;
auto& maybe_view_box = svg_svg_element.view_box();
if (maybe_view_box.has_value()) {
// FIXME: This should allow just one of width or height to be specified.
@ -172,13 +172,13 @@ void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, Available
// The initial value for preserveAspectRatio is xMidYMid meet.
auto preserve_aspect_ratio = svg_svg_element.preserve_aspect_ratio().value_or(SVG::PreserveAspectRatio {});
auto viewbox_transform = scale_and_align_viewbox_content(preserve_aspect_ratio, view_box, { scale_width, scale_height }, svg_box_state);
path_transform = Gfx::AffineTransform {}.translate(viewbox_transform.offset.to_type<float>()).scale(viewbox_transform.scale_factor, viewbox_transform.scale_factor).translate({ -view_box.min_x, -view_box.min_y }).multiply(path_transform);
path_transform = Gfx::AffineTransform {}.translate(viewbox_transform.offset.to_type<double>().to_type<float>()).scale(viewbox_transform.scale_factor, viewbox_transform.scale_factor).translate({ -view_box.min_x, -view_box.min_y }).multiply(path_transform);
viewbox_scale = viewbox_transform.scale_factor;
}
// Stroke increases the path's size by stroke_width/2 per side.
auto path_bounding_box = path_transform.map(path.bounding_box()).to_type<CSSPixels>();
CSSPixels stroke_width = geometry_box.dom_node().visible_stroke_width() * viewbox_scale;
CSSPixels stroke_width = static_cast<double>(geometry_box.dom_node().visible_stroke_width()) * viewbox_scale;
path_bounding_box.inflate(stroke_width, stroke_width);
geometry_box_state.set_content_offset(path_bounding_box.top_left());
geometry_box_state.set_content_width(path_bounding_box.width());

View file

@ -30,8 +30,8 @@ Optional<Gfx::AffineTransform> SVGGeometryBox::layout_transform() const
auto& geometry_element = dom_node();
auto transform = geometry_element.get_transform();
auto* svg_box = geometry_element.first_ancestor_of_type<SVG::SVGSVGElement>();
float scaling = 1;
auto origin = viewbox_origin().to_type<float>();
double scaling = 1;
auto origin = viewbox_origin().to_type<double>().to_type<float>();
Gfx::FloatPoint paint_offset = {};
if (svg_box && svg_box->view_box().has_value()) {
// Note: SVGFormattingContext has already done the scaling based on the viewbox,
@ -45,9 +45,9 @@ Optional<Gfx::AffineTransform> SVGGeometryBox::layout_transform() const
return {};
auto scaled_width = paintable_box()->content_width().value();
auto scaled_height = paintable_box()->content_height().value();
scaling = min(scaled_width / original_bounding_box.width(), scaled_height / original_bounding_box.height());
scaling = min(scaled_width / static_cast<double>(original_bounding_box.width()), scaled_height / static_cast<double>(original_bounding_box.height()));
auto scaled_bounding_box = original_bounding_box.scaled(scaling, scaling);
paint_offset = (paintable_box()->absolute_rect().location() - svg_box->paintable_box()->absolute_rect().location()).to_type<float>() - scaled_bounding_box.location();
paint_offset = (paintable_box()->absolute_rect().location() - svg_box->paintable_box()->absolute_rect().location()).to_type<double>().to_type<float>() - scaled_bounding_box.location();
}
return Gfx::AffineTransform {}.translate(paint_offset).scale(scaling, scaling).translate(-origin).multiply(transform);
}

View file

@ -56,7 +56,7 @@ private:
CSSPixels min_width { 0 };
CSSPixels max_width { 0 };
CSSPixels used_width { 0 };
float percentage_width { 0 };
double percentage_width { 0 };
};
struct Row {