1use super::prelude::*;
2use crate::{AngleOrZero, Length, LengthPercentage, NoneOr, NumberOrPercentage};
3
4#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
7#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
8#[allow(clippy::large_enum_variant)] pub enum TransformFunction {
10 Matrix(MatrixFunction),
11 Matrix3d(Matrix3dFunction),
12 Translate(TranslateFunction),
13 Translate3d(Translate3dFunction),
14 TranslateX(TranslatexFunction),
15 TranslateY(TranslateyFunction),
16 TranslateZ(TranslatezFunction),
17 Scale(ScaleFunction),
18 Scale3d(Scale3dFunction),
19 ScaleX(ScalexFunction),
20 ScaleY(ScaleyFunction),
21 ScaleZ(ScalezFunction),
22 Rotate(RotateFunction),
23 Rotate3d(Rotate3dFunction),
24 RotateX(RotatexFunction),
25 RotateY(RotateyFunction),
26 RotateZ(RotatezFunction),
27 Skew(SkewFunction),
28 SkewX(SkewxFunction),
29 SkewY(SkewyFunction),
30 Perspective(PerspectiveFunction),
31}
32
33#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
39#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
40#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
41pub struct MatrixFunction {
42 #[atom(CssAtomSet::Matrix)]
43 pub name: T![Function],
44 pub params: MatrixFunctionParams,
45 pub close: T![')'],
46}
47
48#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
49#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
50pub struct MatrixFunctionParams(
51 pub T![Number],
52 pub Option<T![,]>,
53 pub T![Number],
54 pub Option<T![,]>,
55 pub T![Number],
56 pub Option<T![,]>,
57 pub T![Number],
58 pub Option<T![,]>,
59 pub T![Number],
60 pub Option<T![,]>,
61 pub T![Number],
62);
63
64#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
70#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
71#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
72pub struct Matrix3dFunction {
73 #[atom(CssAtomSet::Matrix3d)]
74 pub name: T![Function],
75 pub params: Matrix3dFunctionParams,
76 pub close: T![')'],
77}
78
79#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
80#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
81#[allow(clippy::type_complexity)] pub struct Matrix3dFunctionParams(
83 pub T![Number],
84 pub Option<T![,]>,
85 pub T![Number],
86 pub Option<T![,]>,
87 pub T![Number],
88 pub Option<T![,]>,
89 pub T![Number],
90 pub Option<T![,]>,
91 pub T![Number],
92 pub Option<T![,]>,
93 pub T![Number],
94 pub Option<T![,]>,
95 pub T![Number],
96 pub Option<T![,]>,
97 pub T![Number],
98 pub Option<T![,]>,
99 pub T![Number],
100 pub Option<T![,]>,
101 pub T![Number],
102 pub Option<T![,]>,
103 pub T![Number],
104 pub Option<T![,]>,
105 pub T![Number],
106 pub Option<T![,]>,
107 pub T![Number],
108 pub Option<T![,]>,
109 pub T![Number],
110 pub Option<T![,]>,
111 pub T![Number],
112 pub Option<T![,]>,
113 pub T![Number],
114);
115
116#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
122#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
123#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
124pub struct TranslateFunction {
125 #[atom(CssAtomSet::Translate)]
126 pub name: T![Function],
127 pub x: LengthPercentage,
128 pub comma: Option<T![,]>,
129 pub y: Option<LengthPercentage>,
130 pub close: T![')'],
131}
132
133#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
139#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
140#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
141pub struct Translate3dFunction {
142 #[atom(CssAtomSet::Translate3d)]
143 pub name: T![Function],
144 pub params: Translate3dFunctionParams,
145 pub close: T![')'],
146}
147
148#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
149#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
150pub struct Translate3dFunctionParams(
151 pub LengthPercentage,
152 pub Option<T![,]>,
153 pub LengthPercentage,
154 pub Option<T![,]>,
155 pub Length,
156);
157
158#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
164#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
165#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
166pub struct TranslatexFunction {
167 #[atom(CssAtomSet::Translatex)]
168 pub name: T![Function],
169 pub params: LengthPercentage,
170 pub close: T![')'],
171}
172
173#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
179#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
180#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
181pub struct TranslateyFunction {
182 #[atom(CssAtomSet::Translatey)]
183 pub name: T![Function],
184 pub params: LengthPercentage,
185 pub close: T![')'],
186}
187
188#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
194#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
195#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
196pub struct TranslatezFunction {
197 #[atom(CssAtomSet::Translatez)]
198 pub name: T![Function],
199 pub params: Length,
200 pub close: T![')'],
201}
202
203#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
209#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
210#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
211pub struct ScaleFunction {
212 #[atom(CssAtomSet::Scale)]
213 pub name: T![Function],
214 pub params: (NumberOrPercentage, Option<T![,]>, Option<NumberOrPercentage>),
215 pub close: T![')'],
216}
217
218#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
224#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
225#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
226pub struct Scale3dFunction {
227 #[atom(CssAtomSet::Scale3d)]
228 pub name: T![Function],
229 pub params: Scale3dFunctionParams,
230 pub close: T![')'],
231}
232
233#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
234#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
235pub struct Scale3dFunctionParams(
236 pub NumberOrPercentage,
237 pub Option<T![,]>,
238 pub NumberOrPercentage,
239 pub Option<T![,]>,
240 pub NumberOrPercentage,
241);
242
243#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
249#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
250#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
251pub struct ScalexFunction {
252 #[atom(CssAtomSet::Scalex)]
253 pub name: T![Function],
254 pub params: NumberOrPercentage,
255 pub close: T![')'],
256}
257
258#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
264#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
265#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
266pub struct ScaleyFunction {
267 #[atom(CssAtomSet::Scaley)]
268 pub name: T![Function],
269 pub params: NumberOrPercentage,
270 pub close: T![')'],
271}
272
273#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
279#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
280#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
281pub struct ScalezFunction {
282 #[atom(CssAtomSet::Scalez)]
283 pub name: T![Function],
284 pub params: NumberOrPercentage,
285 pub close: T![')'],
286}
287
288#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
294#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
295#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
296pub struct RotateFunction {
297 #[atom(CssAtomSet::Rotate)]
298 pub name: T![Function],
299 pub params: AngleOrZero,
300 pub close: T![')'],
301}
302
303#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
309#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
310#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
311pub struct Rotate3dFunction {
312 #[atom(CssAtomSet::Rotate3d)]
313 pub name: T![Function],
314 pub params: Rotate3dFunctionParams,
315 pub close: T![')'],
316}
317
318#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
319#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
320pub struct Rotate3dFunctionParams(
321 pub T![Number],
322 pub Option<T![,]>,
323 pub T![Number],
324 pub Option<T![,]>,
325 pub T![Number],
326 pub Option<T![,]>,
327 pub AngleOrZero,
328);
329
330#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
336#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
337#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
338pub struct RotatexFunction {
339 #[atom(CssAtomSet::Rotatex)]
340 pub name: T![Function],
341 pub params: AngleOrZero,
342 pub close: T![')'],
343}
344
345#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
351#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
352#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
353pub struct RotateyFunction {
354 #[atom(CssAtomSet::Rotatey)]
355 pub name: T![Function],
356 pub params: AngleOrZero,
357 pub close: T![')'],
358}
359
360#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
366#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
367#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
368pub struct RotatezFunction {
369 #[atom(CssAtomSet::Rotatez)]
370 pub name: T![Function],
371 pub params: AngleOrZero,
372 pub close: T![')'],
373}
374
375#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
381#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
382#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
383pub struct SkewFunction {
384 #[atom(CssAtomSet::Skew)]
385 pub name: T![Function],
386 pub params: (AngleOrZero, Option<T![,]>, Option<AngleOrZero>),
387 pub close: T![')'],
388}
389
390#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
396#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
397#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
398pub struct SkewxFunction {
399 #[atom(CssAtomSet::Skewx)]
400 pub name: T![Function],
401 pub params: AngleOrZero,
402 pub close: T![')'],
403}
404
405#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
411#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
412#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
413pub struct SkewyFunction {
414 #[atom(CssAtomSet::Skewy)]
415 pub name: T![Function],
416 pub params: AngleOrZero,
417 pub close: T![')'],
418}
419
420#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
426#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
427#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
428pub struct PerspectiveFunction {
429 #[atom(CssAtomSet::Perspective)]
430 pub name: T![Function],
431 pub params: NoneOr<Length>,
432 pub close: T![')'],
433}
434
435#[cfg(test)]
436mod tests {
437 use super::*;
438 use crate::CssAtomSet;
439 use css_parse::{assert_parse, assert_parse_error, assert_parse_span};
440
441 #[test]
442 fn size_test() {
443 assert_eq!(std::mem::size_of::<TransformFunction>(), 456);
444 }
445
446 #[test]
447 fn test_writes() {
448 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "matrix(1,2,3,4,5,6)");
449 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "matrix(1 2 3 4 5 6)");
450 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "matrix(0,0,0,0,0,0)");
451 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "matrix(-1,-2,-3,-4,-5,-6)");
452 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "matrix(1.5,2.5,3.5,4.5,5.5,6.5)");
453
454 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "translate(10px)");
455 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "translate(10px,20px)");
456 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "translate(45%)");
457 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "translate(2rem)");
458 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "translateX(1rem)");
459 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "translateY(1rem)");
460
461 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scale(1,2)");
462 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scale(0,0)");
463 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scale(1)");
464 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scale(1.5,2.5)");
465 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scaleX(2)");
466 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scaleY(2)");
467
468 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "rotate(45deg)");
469 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "rotate(0)");
470 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "rotate(2turn)");
471 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "rotate(20rad)");
472
473 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skew(1deg,2deg)");
474 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skew(0,0)");
475 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skew(1deg)");
476 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skewX(1deg)");
477 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skewX(0)");
478 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skewY(1deg)");
479 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skewY(0)");
480
481 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scale3d(10%,10%,10%)");
482 assert_parse!(CssAtomSet::ATOMS, TransformFunction, "rotate3d(1,2,3,10deg)");
483 }
484
485 #[test]
486 fn test_span() {
487 assert_parse_span!(
488 CssAtomSet::ATOMS,
489 TransformFunction,
490 r#"
491 matrix(1,2,3,4,5,6) translate(0)
492 ^^^^^^^^^^^^^^^^^^^
493 "#
494 );
495 assert_parse_span!(
496 CssAtomSet::ATOMS,
497 TransformFunction,
498 r#"
499 translate(0) foo
500 ^^^^^^^^^^^^
501 "#
502 );
503 assert_parse_span!(
504 CssAtomSet::ATOMS,
505 TranslateFunction,
506 r#"
507 translate(0) bar
508 ^^^^^^^^^^^^
509 "#
510 );
511 }
512
513 #[test]
514 fn test_errors() {
515 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "matrix()");
516 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "matrix(1)");
517 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "matrix(1,2)");
518 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "matrix(one,two,three,four,five,size)");
519
520 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "translate()");
521 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "translate(foo)");
522 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "translateX()");
523 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "translateX(foo)");
524 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "translateY()");
525 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "translateY(foo)");
526
527 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "scale()");
528 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "scale(foo)");
529 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "scaleX()");
530 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "scaleX(foo)");
531 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "scaleY()");
532 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "scaleY(foo)");
533
534 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "rotate()");
535 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "rotate(45px)");
536 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "rotate(all the way around)");
537
538 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "skew()");
539 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "skew(foo)");
540 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "skewX()");
541 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "skewX(foo)");
542 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "skewY()");
543 assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "skewY(foo)");
544 }
545}