mirror of
https://github.com/lexmount/moli.git
synced 2026-10-08 08:01:01 +00:00
fix(svg): align matrix factories with DOMMatrix
This commit is contained in:
@@ -617,6 +617,23 @@ struct DomMatrixInit {
|
||||
m44: Option<f64>,
|
||||
}
|
||||
|
||||
#[derive(Default, webidl::WebIdlDictionary)]
|
||||
#[webidl(prefix = "DOMMatrix2DInit")]
|
||||
struct DomMatrix2DInit {
|
||||
a: Option<f64>,
|
||||
b: Option<f64>,
|
||||
c: Option<f64>,
|
||||
d: Option<f64>,
|
||||
e: Option<f64>,
|
||||
f: Option<f64>,
|
||||
m11: Option<f64>,
|
||||
m12: Option<f64>,
|
||||
m21: Option<f64>,
|
||||
m22: Option<f64>,
|
||||
m41: Option<f64>,
|
||||
m42: Option<f64>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct DomMatrixValue {
|
||||
components: DomMatrixComponents,
|
||||
@@ -1070,6 +1087,37 @@ fn dom_matrix_init_arg<'s>(
|
||||
dom_matrix_init_value(scope, args.get(index), prefix, (index + 1) as usize)
|
||||
}
|
||||
|
||||
pub(in crate::context_bootstrap) fn dom_matrix_2d_init_arg<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: &v8::FunctionCallbackArguments<'s>,
|
||||
index: i32,
|
||||
prefix: &'static str,
|
||||
) -> Option<[f64; 6]> {
|
||||
if index >= args.length() || args.get(index).is_undefined() {
|
||||
return Some([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]);
|
||||
}
|
||||
let init = match webidl::parse_dictionary::<DomMatrix2DInit>(
|
||||
scope,
|
||||
args.get(index),
|
||||
webidl::Context::argument(prefix, (index + 1) as usize),
|
||||
) {
|
||||
Ok(Some(init)) => init,
|
||||
Ok(None) => DomMatrix2DInit::default(),
|
||||
Err(error) => {
|
||||
webidl::throw_error(scope, &error);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
Some([
|
||||
validated_dom_matrix_alias(scope, "DOMMatrix2DInit", "a", init.a, "m11", init.m11, 1.0)?,
|
||||
validated_dom_matrix_alias(scope, "DOMMatrix2DInit", "b", init.b, "m12", init.m12, 0.0)?,
|
||||
validated_dom_matrix_alias(scope, "DOMMatrix2DInit", "c", init.c, "m21", init.m21, 0.0)?,
|
||||
validated_dom_matrix_alias(scope, "DOMMatrix2DInit", "d", init.d, "m22", init.m22, 1.0)?,
|
||||
validated_dom_matrix_alias(scope, "DOMMatrix2DInit", "e", init.e, "m41", init.m41, 0.0)?,
|
||||
validated_dom_matrix_alias(scope, "DOMMatrix2DInit", "f", init.f, "m42", init.m42, 0.0)?,
|
||||
])
|
||||
}
|
||||
|
||||
fn dom_matrix_init_value<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
value: v8::Local<'s, v8::Value>,
|
||||
@@ -1095,12 +1143,18 @@ fn validated_dom_matrix_init(
|
||||
scope: &mut v8::PinScope<'_, '_>,
|
||||
init: DomMatrixInit,
|
||||
) -> Option<DomMatrixValue> {
|
||||
let m11 = validated_dom_matrix_alias(scope, "a", init.a, "m11", init.m11, 1.0)?;
|
||||
let m12 = validated_dom_matrix_alias(scope, "b", init.b, "m12", init.m12, 0.0)?;
|
||||
let m21 = validated_dom_matrix_alias(scope, "c", init.c, "m21", init.m21, 0.0)?;
|
||||
let m22 = validated_dom_matrix_alias(scope, "d", init.d, "m22", init.m22, 1.0)?;
|
||||
let m41 = validated_dom_matrix_alias(scope, "e", init.e, "m41", init.m41, 0.0)?;
|
||||
let m42 = validated_dom_matrix_alias(scope, "f", init.f, "m42", init.m42, 0.0)?;
|
||||
let m11 =
|
||||
validated_dom_matrix_alias(scope, "DOMMatrixInit", "a", init.a, "m11", init.m11, 1.0)?;
|
||||
let m12 =
|
||||
validated_dom_matrix_alias(scope, "DOMMatrixInit", "b", init.b, "m12", init.m12, 0.0)?;
|
||||
let m21 =
|
||||
validated_dom_matrix_alias(scope, "DOMMatrixInit", "c", init.c, "m21", init.m21, 0.0)?;
|
||||
let m22 =
|
||||
validated_dom_matrix_alias(scope, "DOMMatrixInit", "d", init.d, "m22", init.m22, 1.0)?;
|
||||
let m41 =
|
||||
validated_dom_matrix_alias(scope, "DOMMatrixInit", "e", init.e, "m41", init.m41, 0.0)?;
|
||||
let m42 =
|
||||
validated_dom_matrix_alias(scope, "DOMMatrixInit", "f", init.f, "m42", init.m42, 0.0)?;
|
||||
let components = DomMatrixComponents {
|
||||
m11,
|
||||
m12,
|
||||
@@ -1135,6 +1189,7 @@ fn validated_dom_matrix_init(
|
||||
|
||||
fn validated_dom_matrix_alias(
|
||||
scope: &mut v8::PinScope<'_, '_>,
|
||||
dictionary_name: &'static str,
|
||||
alias_name: &'static str,
|
||||
alias: Option<f64>,
|
||||
matrix_name: &'static str,
|
||||
@@ -1146,7 +1201,7 @@ fn validated_dom_matrix_alias(
|
||||
{
|
||||
throw_type_error(
|
||||
scope,
|
||||
&format!("DOMMatrixInit {alias_name} and {matrix_name} values differ."),
|
||||
&format!("{dictionary_name} {alias_name} and {matrix_name} values differ."),
|
||||
);
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ struct SvgTransformListTemplateMethodsDeclaration {
|
||||
|
||||
#[webapi(
|
||||
method = "createSVGTransformFromMatrix",
|
||||
length = 1,
|
||||
length = 0,
|
||||
callback = svg_transform_list_create_transform_from_matrix_callback
|
||||
)]
|
||||
create_svg_transform_from_matrix: (),
|
||||
@@ -236,7 +236,7 @@ struct SvgTransformTemplateMethodsDeclaration {
|
||||
#[webapi(constant = "SVG_TRANSFORM_SKEWY", value = SVG_TRANSFORM_TYPE_SKEWY)]
|
||||
transform_skew_y: (),
|
||||
|
||||
#[webapi(method = "setMatrix", length = 1, callback = svg_transform_set_matrix_callback)]
|
||||
#[webapi(method = "setMatrix", length = 0, callback = svg_transform_set_matrix_callback)]
|
||||
set_matrix: (),
|
||||
|
||||
#[webapi(
|
||||
@@ -451,7 +451,7 @@ struct SvgSvgElementTemplateMethodsDeclaration {
|
||||
|
||||
#[webapi(
|
||||
method = "createSVGTransformFromMatrix",
|
||||
length = 1,
|
||||
length = 0,
|
||||
callback = svg_svg_element_create_transform_from_matrix_callback
|
||||
)]
|
||||
create_svg_transform_from_matrix: (),
|
||||
|
||||
@@ -232,7 +232,7 @@ struct SvgTransformListObjectDeclaration<'scope> {
|
||||
#[webapi(
|
||||
method = "createSVGTransformFromMatrix",
|
||||
callback = svg_transform_list_create_transform_from_matrix_callback,
|
||||
length = 1
|
||||
length = 0
|
||||
)]
|
||||
create_svg_transform_from_matrix: (),
|
||||
#[webapi(method, callback = svg_transform_list_consolidate_callback, length = 0)]
|
||||
@@ -248,7 +248,7 @@ struct SvgTransformObjectDeclaration<'scope> {
|
||||
angle: f64,
|
||||
#[webapi(slot = SVG_TRANSFORM_MATRIX_SLOT)]
|
||||
matrix: v8::Local<'scope, v8::Object>,
|
||||
#[webapi(method, callback = svg_transform_set_matrix_callback, length = 1)]
|
||||
#[webapi(method, callback = svg_transform_set_matrix_callback, length = 0)]
|
||||
set_matrix: (),
|
||||
#[webapi(method, callback = svg_transform_set_translate_callback, length = 2)]
|
||||
set_translate: (),
|
||||
@@ -1038,15 +1038,6 @@ pub(super) fn svg_matrix_value_or_throw<'s>(
|
||||
None
|
||||
}
|
||||
|
||||
pub(super) fn cloned_svg_matrix_value_or_throw<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
value: v8::Local<'s, v8::Value>,
|
||||
) -> Option<v8::Local<'s, v8::Object>> {
|
||||
let matrix = svg_matrix_value_or_throw(scope, value)?;
|
||||
let components = svg_matrix_components(scope, matrix);
|
||||
Some(build_svg_matrix(scope, components))
|
||||
}
|
||||
|
||||
pub(super) fn svg_value_list_item_or_default<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
value: v8::Local<'s, v8::Value>,
|
||||
|
||||
@@ -17,6 +17,16 @@ const SVG_ANIMATED_ACCESSOR_NAMES: &[&str] = &["baseVal", "animVal"];
|
||||
const SVG_TRANSFORM_ACCESSOR_NAMES: &[&str] = &["type", "matrix", "angle"];
|
||||
const SVG_MATRIX_ACCESSOR_NAMES: &[&str] = &["a", "b", "c", "d", "e", "f"];
|
||||
|
||||
fn svg_dom_matrix_2d_init_arg<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: &v8::FunctionCallbackArguments<'s>,
|
||||
prefix: &'static str,
|
||||
) -> Option<SvgMatrixComponents> {
|
||||
let [a, b, c, d, e, f] =
|
||||
super::super::geometry_runtime::dom_matrix_2d_init_arg(scope, args, 0, prefix)?;
|
||||
Some(SvgMatrixComponents { a, b, c, d, e, f })
|
||||
}
|
||||
|
||||
const SVG_TEXT_POSITIONING_LIST_ATTRIBUTES: &[(&str, &str, SvgListKind)] = &[
|
||||
("x", SVG_TEXT_POSITIONING_X_SLOT, SvgListKind::Length),
|
||||
("y", SVG_TEXT_POSITIONING_Y_SLOT, SvgListKind::Length),
|
||||
@@ -1363,13 +1373,13 @@ pub(super) fn svg_transform_list_create_transform_from_matrix_callback<'s>(
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
let Some(parsed) = webidl::parse_args::<SvgListItemArgs>(scope, &args) else {
|
||||
let Some(components) = svg_dom_matrix_2d_init_arg(
|
||||
scope,
|
||||
&args,
|
||||
"SVGTransformList.createSVGTransformFromMatrix",
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
let Some(matrix) = cloned_svg_matrix_value_or_throw(scope, parsed.item) else {
|
||||
return;
|
||||
};
|
||||
let components = svg_matrix_components(scope, matrix);
|
||||
rv.set(build_svg_transform(scope, SvgTransform::matrix(components)).into());
|
||||
}
|
||||
|
||||
@@ -1442,13 +1452,10 @@ pub(super) fn svg_transform_set_matrix_callback<'s>(
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
let Some(parsed) = webidl::parse_args::<SvgMatrixArg>(scope, &args) else {
|
||||
let Some(components) = svg_dom_matrix_2d_init_arg(scope, &args, "SVGTransform.setMatrix")
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(matrix) = cloned_svg_matrix_value_or_throw(scope, parsed.matrix) else {
|
||||
return;
|
||||
};
|
||||
let components = svg_matrix_components(scope, matrix);
|
||||
set_svg_transform_state(scope, args.this(), SvgTransform::matrix(components));
|
||||
reflect_svg_transform_item_to_owner_list(scope, args.this());
|
||||
rv.set_undefined();
|
||||
@@ -1459,7 +1466,7 @@ pub(super) fn svg_svg_element_create_matrix_callback<'s>(
|
||||
_args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
rv.set(build_svg_matrix(scope, SvgMatrixComponents::identity()).into());
|
||||
rv.set(super::super::geometry_runtime::build_dom_matrix_identity_object(scope).into());
|
||||
}
|
||||
|
||||
pub(super) fn svg_svg_element_create_transform_callback<'s>(
|
||||
@@ -1477,13 +1484,11 @@ pub(super) fn svg_svg_element_create_transform_from_matrix_callback<'s>(
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
let Some(parsed) = webidl::parse_args::<SvgMatrixArg>(scope, &args) else {
|
||||
let Some(components) =
|
||||
svg_dom_matrix_2d_init_arg(scope, &args, "SVGSVGElement.createSVGTransformFromMatrix")
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(matrix) = cloned_svg_matrix_value_or_throw(scope, parsed.matrix) else {
|
||||
return;
|
||||
};
|
||||
let components = svg_matrix_components(scope, matrix);
|
||||
rv.set(build_svg_transform(scope, SvgTransform::matrix(components)).into());
|
||||
}
|
||||
|
||||
|
||||
@@ -5539,6 +5539,7 @@ fn geometry_exposes_legacy_window_aliases() {
|
||||
const rect = new SVGRect(3, 4, 5, 6);
|
||||
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
const matrix = svg.createSVGMatrix();
|
||||
const multiplied = matrix.multiply({a: 3, d: 2});
|
||||
matrix.a = 2;
|
||||
return JSON.stringify({
|
||||
identities: [
|
||||
@@ -5552,8 +5553,11 @@ fn geometry_exposes_legacy_window_aliases() {
|
||||
matrix: [
|
||||
matrix instanceof DOMMatrix,
|
||||
matrix instanceof SVGMatrix,
|
||||
DOMMatrix.prototype.isPrototypeOf(matrix),
|
||||
Object.getPrototypeOf(matrix) === DOMMatrix.prototype,
|
||||
!Object.hasOwn(matrix, "multiply"),
|
||||
matrix.a,
|
||||
multiplied.a,
|
||||
multiplied.d,
|
||||
Object.prototype.toString.call(matrix)
|
||||
].join(","),
|
||||
descriptors: aliases.map(descriptorShape).join("|")
|
||||
@@ -5566,13 +5570,61 @@ fn geometry_exposes_legacy_window_aliases() {
|
||||
assert_eq!(
|
||||
result,
|
||||
concat!(
|
||||
r#"{"identities":"true,true,true,true","point":"true,1,2,[object DOMPoint]","rect":"true,3,6,[object DOMRect]","matrix":"true,true,true,2,[object SVGMatrix]","descriptors":""#,
|
||||
r#"{"identities":"true,true,true,true","point":"true,1,2,[object DOMPoint]","rect":"true,3,6,[object DOMRect]","matrix":"true,true,true,true,2,3,2,[object DOMMatrix]","descriptors":""#,
|
||||
"true,true,false,true|true,true,false,true|",
|
||||
"true,true,false,true|true,true,false,true\"}"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn svg_transform_factories_convert_optional_dom_matrix_2d_init() {
|
||||
let mut vm = new_storage_test_vm("https://svg-transform-dom-matrix-init.test/");
|
||||
|
||||
let result = vm
|
||||
.eval(
|
||||
r#"
|
||||
(() => {
|
||||
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||
const svg = document.createElementNS(SVG_NS, "svg");
|
||||
const group = document.createElementNS(SVG_NS, "g");
|
||||
const fromElement = svg.createSVGTransformFromMatrix({a: 2, e: 5});
|
||||
const defaultElement = svg.createSVGTransformFromMatrix();
|
||||
const fromFactory = svg.createSVGTransformFromMatrix(svg.createSVGMatrix().translate(9, 10));
|
||||
const transform = svg.createSVGTransform();
|
||||
transform.setMatrix({b: 4, f: 6});
|
||||
const fromList = group.transform.baseVal.createSVGTransformFromMatrix({c: 7, d: 8});
|
||||
let mismatch;
|
||||
try {
|
||||
transform.setMatrix({a: 1, m11: 2});
|
||||
mismatch = "none";
|
||||
} catch (error) {
|
||||
mismatch = error.name;
|
||||
}
|
||||
return JSON.stringify({
|
||||
fromElement: [fromElement.matrix.a, fromElement.matrix.e].join(","),
|
||||
defaultElement: [defaultElement.matrix.a, defaultElement.matrix.d].join(","),
|
||||
fromFactory: [fromFactory.matrix.e, fromFactory.matrix.f].join(","),
|
||||
setMatrix: [transform.matrix.b, transform.matrix.f].join(","),
|
||||
fromList: [fromList.matrix.c, fromList.matrix.d].join(","),
|
||||
mismatch,
|
||||
lengths: [
|
||||
SVGSVGElement.prototype.createSVGTransformFromMatrix.length,
|
||||
SVGTransform.prototype.setMatrix.length,
|
||||
SVGTransformList.prototype.createSVGTransformFromMatrix.length
|
||||
].join(",")
|
||||
});
|
||||
})()
|
||||
"#,
|
||||
)
|
||||
.expect("SVG transform DOMMatrix2DInit conversion should evaluate");
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
r#"{"fromElement":"2,5","defaultElement":"1,1","fromFactory":"9,10","setMatrix":"4,6","fromList":"7,8","mismatch":"TypeError","lengths":"0,0,0"}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dom_matrix_window_operations_use_webidl_descriptors() {
|
||||
let mut vm = new_storage_test_vm("https://dommatrix-operation-descriptors.test/");
|
||||
|
||||
@@ -8174,6 +8174,7 @@ fn svg_list_matrix_and_transform_declared_methods_keep_descriptors() {
|
||||
numberInsertItemBefore: methodDescriptor(numberList, "insertItemBefore"),
|
||||
transformListCreate: methodDescriptor(transformList, "createSVGTransformFromMatrix"),
|
||||
transformListConsolidate: methodDescriptor(transformList, "consolidate"),
|
||||
transformSetMatrix: methodDescriptor(transform, "setMatrix"),
|
||||
transformSetRotate: methodDescriptor(transform, "setRotate"),
|
||||
transformSetSkewX: methodDescriptor(transform, "setSkewX"),
|
||||
matrixScaleNonUniform: methodDescriptor(matrix, "scaleNonUniform"),
|
||||
@@ -8193,7 +8194,7 @@ fn svg_list_matrix_and_transform_declared_methods_keep_descriptors() {
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
r#"{"lengthGetItem":"false,true,true,getItem,1","lengthAppendItem":"false,true,true,appendItem,1","numberInsertItemBefore":"false,true,true,insertItemBefore,2","transformListCreate":"false,true,true,createSVGTransformFromMatrix,1","transformListConsolidate":"false,true,true,consolidate,0","transformSetRotate":"false,true,true,setRotate,3","transformSetSkewX":"false,true,true,setSkewX,1","matrixScaleNonUniform":"false,true,true,scaleNonUniform,2","matrixRotateFromVector":"false,true,true,rotateFromVector,2","matrixFlipX":"false,true,true,flipX,0","transformOwnMethods":["setMatrix","setRotate","setScale","setSkewX","setSkewY","setTranslate"],"matrixOwnMethods":["flipX","flipY","inverse","multiply","rotate","rotateFromVector","scale","scaleNonUniform","skewX","skewY","translate"]}"#
|
||||
r#"{"lengthGetItem":"false,true,true,getItem,1","lengthAppendItem":"false,true,true,appendItem,1","numberInsertItemBefore":"false,true,true,insertItemBefore,2","transformListCreate":"false,true,true,createSVGTransformFromMatrix,0","transformListConsolidate":"false,true,true,consolidate,0","transformSetMatrix":"false,true,true,setMatrix,0","transformSetRotate":"false,true,true,setRotate,3","transformSetSkewX":"false,true,true,setSkewX,1","matrixScaleNonUniform":"false,true,true,scaleNonUniform,2","matrixRotateFromVector":"false,true,true,rotateFromVector,2","matrixFlipX":"false,true,true,flipX,0","transformOwnMethods":["setMatrix","setRotate","setScale","setSkewX","setSkewY","setTranslate"],"matrixOwnMethods":["flipX","flipY","inverse","multiply","rotate","rotateFromVector","scale","scaleNonUniform","skewX","skewY","translate"]}"#
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user