mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibWeb: Reimplement transform interpolation according to spec
We had a partial implementation of transformation function interpolation that did not support numerical interpolation of simple functions (e.g. `scale(0)` -> `scale(1)`). This refactors the interpolation to follow the spec more closely. Gains us 267 WPT subtest passes in `css/css-transforms`. Fixes #6774.
This commit is contained in:
parent
911ecf1450
commit
e4dc2663ba
Notes:
github-actions[bot]
2025-11-18 13:37:43 +00:00
Author: https://github.com/gmta
Commit: e4dc2663ba
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6826
Reviewed-by: https://github.com/AtkinsSJ
Reviewed-by: https://github.com/nico
6 changed files with 610 additions and 89 deletions
|
|
@ -4,11 +4,11 @@
|
|||
* Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
|
||||
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
|
||||
* Copyright (c) 2024, Steffen T. Larssen <dudedbz@gmail.com>
|
||||
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "TransformationStyleValue.h"
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibWeb/CSS/CSSMatrixComponent.h>
|
||||
#include <LibWeb/CSS/CSSPerspective.h>
|
||||
|
|
@ -23,14 +23,79 @@
|
|||
#include <LibWeb/CSS/PropertyID.h>
|
||||
#include <LibWeb/CSS/Serialize.h>
|
||||
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/KeywordStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>
|
||||
#include <LibWeb/CSS/Transformation.h>
|
||||
#include <LibWeb/Geometry/DOMMatrix.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
ValueComparingNonnullRefPtr<TransformationStyleValue const> TransformationStyleValue::identity_transformation(
|
||||
TransformFunction transform_function)
|
||||
{
|
||||
// https://drafts.csswg.org/css-transforms-1/#identity-transform-function
|
||||
// A transform function that is equivalent to a identity 4x4 matrix (see Mathematical Description of Transform
|
||||
// Functions). Examples for identity transform functions are translate(0), translateX(0), translateY(0), scale(1),
|
||||
// scaleX(1), scaleY(1), rotate(0), skew(0, 0), skewX(0), skewY(0) and matrix(1, 0, 0, 1, 0, 0).
|
||||
|
||||
// https://drafts.csswg.org/css-transforms-2/#identity-transform-function
|
||||
// In addition to the identity transform function in CSS Transforms, examples for identity transform functions
|
||||
// include translate3d(0, 0, 0), translateZ(0), scaleZ(1), rotate3d(1, 1, 1, 0), rotateX(0), rotateY(0), rotateZ(0)
|
||||
// and matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1). A special case is perspective: perspective(none).
|
||||
// The value of m34 becomes infinitesimal small and the transform function is therefore assumed to be equal to the
|
||||
// identity matrix.
|
||||
|
||||
auto identity_parameters = [&] -> StyleValueVector {
|
||||
auto const number_zero = NumberStyleValue::create(0.);
|
||||
auto const number_one = NumberStyleValue::create(1.);
|
||||
|
||||
switch (transform_function) {
|
||||
case TransformFunction::Matrix:
|
||||
return { number_one, number_zero, number_zero, number_one, number_zero, number_zero };
|
||||
case TransformFunction::Matrix3d:
|
||||
return { number_one, number_zero, number_zero, number_zero,
|
||||
number_zero, number_one, number_zero, number_zero,
|
||||
number_zero, number_zero, number_one, number_zero,
|
||||
number_zero, number_zero, number_zero, number_one };
|
||||
case TransformFunction::Perspective:
|
||||
return { KeywordStyleValue::create(Keyword::None) };
|
||||
case TransformFunction::Rotate:
|
||||
case TransformFunction::RotateX:
|
||||
case TransformFunction::RotateY:
|
||||
case TransformFunction::RotateZ:
|
||||
return { AngleStyleValue::create(Angle::make_degrees(0.)) };
|
||||
case TransformFunction::Rotate3d:
|
||||
return { number_one, number_one, number_one, AngleStyleValue::create(Angle::make_degrees(0.)) };
|
||||
case TransformFunction::Skew:
|
||||
case TransformFunction::SkewX:
|
||||
case TransformFunction::SkewY:
|
||||
case TransformFunction::Translate:
|
||||
case TransformFunction::TranslateX:
|
||||
case TransformFunction::TranslateY:
|
||||
case TransformFunction::TranslateZ:
|
||||
return { LengthStyleValue::create(Length::make_px(0.)) };
|
||||
case TransformFunction::Translate3d:
|
||||
return {
|
||||
LengthStyleValue::create(Length::make_px(0.)),
|
||||
LengthStyleValue::create(Length::make_px(0.)),
|
||||
LengthStyleValue::create(Length::make_px(0.)),
|
||||
};
|
||||
case TransformFunction::Scale:
|
||||
case TransformFunction::ScaleX:
|
||||
case TransformFunction::ScaleY:
|
||||
case TransformFunction::ScaleZ:
|
||||
return { number_one };
|
||||
case TransformFunction::Scale3d:
|
||||
return { number_one, number_one, number_one };
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
};
|
||||
return create(PropertyID::Transform, transform_function, identity_parameters());
|
||||
}
|
||||
|
||||
Transformation TransformationStyleValue::to_transformation() const
|
||||
{
|
||||
auto function_metadata = transform_function_metadata(m_properties.transform_function);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ public:
|
|||
}
|
||||
virtual ~TransformationStyleValue() override = default;
|
||||
|
||||
static ValueComparingNonnullRefPtr<TransformationStyleValue const> identity_transformation(TransformFunction);
|
||||
|
||||
TransformFunction transform_function() const { return m_properties.transform_function; }
|
||||
StyleValueVector const& values() const { return m_properties.values; }
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue