diff --git a/Libraries/LibWeb/CSS/Length.cpp b/Libraries/LibWeb/CSS/Length.cpp index 713005dfcf1..11d97db9ed2 100644 --- a/Libraries/LibWeb/CSS/Length.cpp +++ b/Libraries/LibWeb/CSS/Length.cpp @@ -38,74 +38,84 @@ Length Length::percentage_of(Percentage const& percentage) const } CSSPixels Length::font_relative_length_to_px(Length::FontMetrics const& font_metrics, Length::FontMetrics const& root_font_metrics) const +{ + return CSSPixels::nearest_value_for(font_relative_length_to_px_without_rounding(font_metrics, root_font_metrics)); +} + +double Length::font_relative_length_to_px_without_rounding(Length::FontMetrics const& font_metrics, Length::FontMetrics const& root_font_metrics) const { switch (m_unit) { case LengthUnit::Em: - return CSSPixels::nearest_value_for(m_value * font_metrics.font_size.to_double()); + return m_value * font_metrics.font_size.to_double(); case LengthUnit::Rem: - return CSSPixels::nearest_value_for(m_value * root_font_metrics.font_size.to_double()); + return m_value * root_font_metrics.font_size.to_double(); case LengthUnit::Ex: - return CSSPixels::nearest_value_for(m_value * font_metrics.x_height.to_double()); + return m_value * font_metrics.x_height.to_double(); case LengthUnit::Rex: - return CSSPixels::nearest_value_for(m_value * root_font_metrics.x_height.to_double()); + return m_value * root_font_metrics.x_height.to_double(); case LengthUnit::Cap: - return CSSPixels::nearest_value_for(m_value * font_metrics.cap_height.to_double()); + return m_value * font_metrics.cap_height.to_double(); case LengthUnit::Rcap: - return CSSPixels::nearest_value_for(m_value * root_font_metrics.cap_height.to_double()); + return m_value * root_font_metrics.cap_height.to_double(); case LengthUnit::Ch: - return CSSPixels::nearest_value_for(m_value * font_metrics.zero_advance.to_double()); + return m_value * font_metrics.zero_advance.to_double(); case LengthUnit::Rch: - return CSSPixels::nearest_value_for(m_value * root_font_metrics.zero_advance.to_double()); + return m_value * root_font_metrics.zero_advance.to_double(); case LengthUnit::Ic: // FIXME: Use the "advance measure of the “水” (CJK water ideograph, U+6C34) glyph" - return CSSPixels::nearest_value_for(m_value * font_metrics.font_size.to_double()); + return m_value * font_metrics.font_size.to_double(); case LengthUnit::Ric: // FIXME: Use the "advance measure of the “水” (CJK water ideograph, U+6C34) glyph" - return CSSPixels::nearest_value_for(m_value * root_font_metrics.font_size.to_double()); + return m_value * root_font_metrics.font_size.to_double(); case LengthUnit::Lh: - return CSSPixels::nearest_value_for(m_value * font_metrics.line_height.to_double()); + return m_value * font_metrics.line_height.to_double(); case LengthUnit::Rlh: - return CSSPixels::nearest_value_for(m_value * root_font_metrics.line_height.to_double()); + return m_value * root_font_metrics.line_height.to_double(); default: VERIFY_NOT_REACHED(); } } CSSPixels Length::viewport_relative_length_to_px(CSSPixelRect const& viewport_rect) const +{ + return CSSPixels::nearest_value_for(viewport_relative_length_to_px_without_rounding(viewport_rect)); +} + +double Length::viewport_relative_length_to_px_without_rounding(CSSPixelRect const& viewport_rect) const { switch (m_unit) { case LengthUnit::Vw: case LengthUnit::Svw: case LengthUnit::Lvw: case LengthUnit::Dvw: - return viewport_rect.width() * (CSSPixels::nearest_value_for(m_value) / 100); + return viewport_rect.width() * m_value / 100; case LengthUnit::Vh: case LengthUnit::Svh: case LengthUnit::Lvh: case LengthUnit::Dvh: - return viewport_rect.height() * (CSSPixels::nearest_value_for(m_value) / 100); + return viewport_rect.height() * m_value / 100; case LengthUnit::Vi: case LengthUnit::Svi: case LengthUnit::Lvi: case LengthUnit::Dvi: // FIXME: Select the width or height based on which is the inline axis. - return viewport_rect.width() * (CSSPixels::nearest_value_for(m_value) / 100); + return viewport_rect.width() * m_value / 100; case LengthUnit::Vb: case LengthUnit::Svb: case LengthUnit::Lvb: case LengthUnit::Dvb: // FIXME: Select the width or height based on which is the block axis. - return viewport_rect.height() * (CSSPixels::nearest_value_for(m_value) / 100); + return viewport_rect.height() * m_value / 100; case LengthUnit::Vmin: case LengthUnit::Svmin: case LengthUnit::Lvmin: case LengthUnit::Dvmin: - return min(viewport_rect.width(), viewport_rect.height()) * (CSSPixels::nearest_value_for(m_value) / 100); + return min(viewport_rect.width(), viewport_rect.height()) * m_value / 100; case LengthUnit::Vmax: case LengthUnit::Svmax: case LengthUnit::Lvmax: case LengthUnit::Dvmax: - return max(viewport_rect.width(), viewport_rect.height()) * (CSSPixels::nearest_value_for(m_value) / 100); + return max(viewport_rect.width(), viewport_rect.height()) * m_value / 100; default: VERIFY_NOT_REACHED(); } diff --git a/Libraries/LibWeb/CSS/Length.h b/Libraries/LibWeb/CSS/Length.h index 234867442fd..a30e1a72bda 100644 --- a/Libraries/LibWeb/CSS/Length.h +++ b/Libraries/LibWeb/CSS/Length.h @@ -78,6 +78,18 @@ public: return to_px_slow_case(node); } + ALWAYS_INLINE double to_px_without_rounding(ResolutionContext const& context) const + { + if (is_absolute()) + return absolute_length_to_px_without_rounding(); + if (is_font_relative()) + return font_relative_length_to_px_without_rounding(context.font_metrics, context.root_font_metrics); + if (is_viewport_relative()) + return viewport_relative_length_to_px_without_rounding(context.viewport_rect); + + VERIFY_NOT_REACHED(); + } + ALWAYS_INLINE CSSPixels to_px(CSSPixelRect const& viewport_rect, FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const { if (is_absolute()) @@ -108,7 +120,9 @@ public: } CSSPixels font_relative_length_to_px(FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const; + double font_relative_length_to_px_without_rounding(FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const; CSSPixels viewport_relative_length_to_px(CSSPixelRect const& viewport_rect) const; + double viewport_relative_length_to_px_without_rounding(CSSPixelRect const& viewport_rect) const; // Returns empty optional if it's already absolute. Optional absolutize(CSSPixelRect const& viewport_rect, FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const; diff --git a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp index 71ba6b59a22..9de0fede3f1 100644 --- a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp @@ -2531,7 +2531,7 @@ CalculatedStyleValue::CalculationResult CalculatedStyleValue::CalculationResult: return AK::NaN; } - return length.to_px(context.length_resolution_context.value()).to_double(); + return length.to_px_without_rounding(context.length_resolution_context.value()); }, [](Resolution const& resolution) { return resolution.to_dots_per_pixel(); }, [](Time const& time) { return time.to_seconds(); }, @@ -2900,7 +2900,7 @@ NonnullRefPtr simplify_a_calculation_tree(CalculationNode if (length.is_absolute()) return NumericCalculationNode::create(Length::make_px(length.absolute_length_to_px()).percentage_of(*percentage), context); if (resolution_context.length_resolution_context.has_value()) - return NumericCalculationNode::create(Length::make_px(length.to_px(resolution_context.length_resolution_context.value())).percentage_of(*percentage), context); + return NumericCalculationNode::create(Length::make_px(length.to_px_without_rounding(resolution_context.length_resolution_context.value())).percentage_of(*percentage), context); return nullptr; }, [&](Time const& time) -> RefPtr { @@ -2938,9 +2938,9 @@ NonnullRefPtr simplify_a_calculation_tree(CalculationNode if (length.unit() == LengthUnit::Px) return nullptr; if (length.is_absolute()) - return NumericCalculationNode::create(Length::make_px(length.absolute_length_to_px()), context); + return NumericCalculationNode::create(Length::make_px(length.absolute_length_to_px_without_rounding()), context); if (resolution_context.length_resolution_context.has_value()) - return NumericCalculationNode::create(Length::make_px(length.to_px(resolution_context.length_resolution_context.value())), context); + return NumericCalculationNode::create(Length::make_px(length.to_px_without_rounding(resolution_context.length_resolution_context.value())), context); return nullptr; }, [&](Number const&) -> RefPtr { diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/round-mod-rem-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/round-mod-rem-computed.txt index 18e5f9f1059..f3f41c3629c 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/round-mod-rem-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/round-mod-rem-computed.txt @@ -2,8 +2,8 @@ Harness status: OK Found 229 tests -217 Pass -12 Fail +219 Pass +10 Fail Pass round(10,10) should be used-value-equivalent to 10 Pass mod(1,1) should be used-value-equivalent to 0 Pass rem(1,1) should be used-value-equivalent to 0 @@ -61,8 +61,8 @@ Pass calc(rem(mod(18,5),mod(17,5))) should be used-value-equivalent to 1 Pass calc(mod(-140,-90)) should be used-value-equivalent to -50 Pass calc(mod(rem(1,18)* -1,5)) should be used-value-equivalent to 4 Pass round(10px,6px) should be used-value-equivalent to 12px -Fail round(10cm,6cm) should be used-value-equivalent to 12cm -Fail round(10mm,6mm) should be used-value-equivalent to 12mm +Pass round(10cm,6cm) should be used-value-equivalent to 12cm +Pass round(10mm,6mm) should be used-value-equivalent to 12mm Pass round(10Q, 6Q) should be used-value-equivalent to 12Q Pass round(10in,6in) should be used-value-equivalent to 12in Pass round(10pc,6pc) should be used-value-equivalent to 12pc diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/signs-abs-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/signs-abs-computed.txt index dc5f913bcda..817c3a19c6a 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/signs-abs-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/signs-abs-computed.txt @@ -2,8 +2,8 @@ Harness status: OK Found 233 tests -221 Pass -12 Fail +227 Pass +6 Fail Pass abs(1) should be used-value-equivalent to 1 Pass sign(1) should be used-value-equivalent to 1 Pass abs(-1) should be used-value-equivalent to 1 @@ -114,17 +114,17 @@ Pass clamp(-1, calc( 1 / sign(sign(0vmax))), 1) should be used-value-equivalent Pass calc(sign(-0px)) should be used-value-equivalent to 0 Pass clamp(-1, calc( 1 / sign(sign(-0px))), 1) should be used-value-equivalent to -1 Pass calc(sign(-0cm)) should be used-value-equivalent to 0 -Fail clamp(-1, calc( 1 / sign(sign(-0cm))), 1) should be used-value-equivalent to -1 +Pass clamp(-1, calc( 1 / sign(sign(-0cm))), 1) should be used-value-equivalent to -1 Pass calc(sign(-0mm)) should be used-value-equivalent to 0 -Fail clamp(-1, calc( 1 / sign(sign(-0mm))), 1) should be used-value-equivalent to -1 +Pass clamp(-1, calc( 1 / sign(sign(-0mm))), 1) should be used-value-equivalent to -1 Pass calc(sign(-0Q)) should be used-value-equivalent to 0 -Fail clamp(-1, calc( 1 / sign(sign(-0Q))), 1) should be used-value-equivalent to -1 +Pass clamp(-1, calc( 1 / sign(sign(-0Q))), 1) should be used-value-equivalent to -1 Pass calc(sign(-0in)) should be used-value-equivalent to 0 -Fail clamp(-1, calc( 1 / sign(sign(-0in))), 1) should be used-value-equivalent to -1 +Pass clamp(-1, calc( 1 / sign(sign(-0in))), 1) should be used-value-equivalent to -1 Pass calc(sign(-0pc)) should be used-value-equivalent to 0 -Fail clamp(-1, calc( 1 / sign(sign(-0pc))), 1) should be used-value-equivalent to -1 +Pass clamp(-1, calc( 1 / sign(sign(-0pc))), 1) should be used-value-equivalent to -1 Pass calc(sign(-0pt)) should be used-value-equivalent to 0 -Fail clamp(-1, calc( 1 / sign(sign(-0pt))), 1) should be used-value-equivalent to -1 +Pass clamp(-1, calc( 1 / sign(sign(-0pt))), 1) should be used-value-equivalent to -1 Pass calc(sign(-0em)) should be used-value-equivalent to 0 Pass clamp(-1, calc( 1 / sign(sign(-0em))), 1) should be used-value-equivalent to -1 Pass calc(sign(-0ex)) should be used-value-equivalent to 0 diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/typed_arithmetic.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/typed_arithmetic.txt index 2395f220209..cc68ddd1f75 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/typed_arithmetic.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/typed_arithmetic.txt @@ -2,8 +2,8 @@ Harness status: OK Found 35 tests -29 Pass -6 Fail +32 Pass +3 Fail Pass min(1em, 110px / 10px * 1px) should be used-value-equivalent to 10px Pass max(10px, 110px / 10px * 1px) should be used-value-equivalent to 11px Pass max(1em + 2px, 110px / 10px * 1px) should be used-value-equivalent to 12px @@ -26,14 +26,14 @@ Pass e.style['width'] = "calc((1% * 1deg) / 1px)" should not set the property va Pass e.style['width'] = "calc((1% * 1% * 1%) / 1px)" should not set the property value Pass Property width value 'calc(1px * 10em / 0em)' Pass Property width value 'calc(1px / 1px * 10em * infinity)' -Fail Property margin-left value 'calc(1px * 10em / -0em)' +Pass Property margin-left value 'calc(1px * 10em / -0em)' Pass Property z-index value 'calc(10em / 0em)' Pass sign(-0em / 1px) should be used-value-equivalent to 0 -Fail clamp(-1, 1 / sign(-0em / 1px), 1) should be used-value-equivalent to -1 +Pass clamp(-1, 1 / sign(-0em / 1px), 1) should be used-value-equivalent to -1 Fail sign( 0cqi / 1px) should be used-value-equivalent to 0 Fail clamp(-1, 1 / sign( 0cqi / 1px), 1) should be used-value-equivalent to 1 Pass sign(atan2(-0cap / 1px, 0em / 1px)) should be used-value-equivalent to 0 -Fail clamp(-1, 1 / sign(atan2(-0cap / 1px, 0em / 1px)), 1) should be used-value-equivalent to -1 +Pass clamp(-1, 1 / sign(atan2(-0cap / 1px, 0em / 1px)), 1) should be used-value-equivalent to -1 Pass sign(exp(-1vh / 0px)) should be used-value-equivalent to 0 Pass clamp(-1, 1 / sign(exp(-1vh / 0px)), 1) should be used-value-equivalent to 1 Fail calc(20cqw / 1rem) should be used-value-equivalent to 2