1use crate::values::animated::{lists, Animate, Procedure, ToAnimatedZero};
9use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
10use crate::values::generics::border::GenericBorderRadius;
11use crate::values::generics::position::GenericPositionOrAuto;
12use crate::values::generics::rect::Rect;
13use crate::values::specified::svg_path::{PathCommand, SVGPathData};
14use crate::Zero;
15use std::fmt::{self, Write};
16use style_traits::{CssWriter, ToCss};
17
18#[allow(missing_docs)]
20#[derive(
21 Animate,
22 Clone,
23 ComputeSquaredDistance,
24 Copy,
25 Debug,
26 MallocSizeOf,
27 PartialEq,
28 Parse,
29 SpecifiedValueInfo,
30 ToAnimatedValue,
31 ToComputedValue,
32 ToCss,
33 ToResolvedValue,
34 ToShmem,
35)]
36#[repr(u8)]
37pub enum ShapeGeometryBox {
38 #[css(skip)]
45 ElementDependent,
46 FillBox,
47 StrokeBox,
48 ViewBox,
49 ShapeBox(ShapeBox),
50}
51
52impl Default for ShapeGeometryBox {
53 fn default() -> Self {
54 Self::ElementDependent
55 }
56}
57
58#[inline]
60fn is_default_box_for_clip_path(b: &ShapeGeometryBox) -> bool {
61 matches!(b, ShapeGeometryBox::ElementDependent)
64 || matches!(b, ShapeGeometryBox::ShapeBox(ShapeBox::BorderBox))
65}
66
67#[allow(missing_docs)]
69#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
70#[derive(
71 Animate,
72 Clone,
73 Copy,
74 ComputeSquaredDistance,
75 Debug,
76 Eq,
77 MallocSizeOf,
78 Parse,
79 PartialEq,
80 SpecifiedValueInfo,
81 ToAnimatedValue,
82 ToComputedValue,
83 ToCss,
84 ToResolvedValue,
85 ToShmem,
86)]
87#[repr(u8)]
88pub enum ShapeBox {
89 MarginBox,
90 BorderBox,
91 PaddingBox,
92 ContentBox,
93}
94
95impl Default for ShapeBox {
96 fn default() -> Self {
97 ShapeBox::MarginBox
98 }
99}
100
101#[allow(missing_docs)]
103#[derive(
104 Animate,
105 Clone,
106 ComputeSquaredDistance,
107 Debug,
108 MallocSizeOf,
109 PartialEq,
110 SpecifiedValueInfo,
111 ToAnimatedValue,
112 ToComputedValue,
113 ToCss,
114 ToResolvedValue,
115 ToShmem,
116)]
117#[animation(no_bound(U))]
118#[repr(u8)]
119pub enum GenericClipPath<BasicShape, U> {
120 #[animation(error)]
121 None,
122 #[animation(error)]
123 Url(U),
124 Shape(
125 Box<BasicShape>,
126 #[css(skip_if = "is_default_box_for_clip_path")] ShapeGeometryBox,
127 ),
128 #[animation(error)]
129 Box(ShapeGeometryBox),
130}
131
132pub use self::GenericClipPath as ClipPath;
133
134#[allow(missing_docs)]
136#[derive(
137 Animate,
138 Clone,
139 ComputeSquaredDistance,
140 Debug,
141 MallocSizeOf,
142 PartialEq,
143 SpecifiedValueInfo,
144 ToAnimatedValue,
145 ToComputedValue,
146 ToCss,
147 ToResolvedValue,
148 ToShmem,
149)]
150#[animation(no_bound(I))]
151#[repr(u8)]
152pub enum GenericShapeOutside<BasicShape, I> {
153 #[animation(error)]
154 None,
155 #[animation(error)]
156 Image(I),
157 Shape(Box<BasicShape>, #[css(skip_if = "is_default")] ShapeBox),
158 #[animation(error)]
159 Box(ShapeBox),
160}
161
162pub use self::GenericShapeOutside as ShapeOutside;
163
164#[derive(
168 Animate,
169 Clone,
170 ComputeSquaredDistance,
171 Debug,
172 Deserialize,
173 MallocSizeOf,
174 PartialEq,
175 Serialize,
176 SpecifiedValueInfo,
177 ToAnimatedValue,
178 ToComputedValue,
179 ToCss,
180 ToResolvedValue,
181 ToShmem,
182)]
183#[repr(C, u8)]
184pub enum GenericBasicShape<
185 Angle,
186 Position,
187 LengthPercentage,
188 NonNegativeLengthPercentage,
189 BasicShapeRect,
190> {
191 Rect(BasicShapeRect),
193 Circle(
195 #[css(field_bound)]
196 #[shmem(field_bound)]
197 Circle<Position, NonNegativeLengthPercentage>,
198 ),
199 Ellipse(
201 #[css(field_bound)]
202 #[shmem(field_bound)]
203 Ellipse<Position, NonNegativeLengthPercentage>,
204 ),
205 Polygon(GenericPolygon<LengthPercentage>),
207 PathOrShape(
209 #[animation(field_bound)]
210 #[css(field_bound)]
211 GenericPathOrShapeFunction<Angle, LengthPercentage>,
212 ),
213}
214
215pub use self::GenericBasicShape as BasicShape;
216
217#[allow(missing_docs)]
219#[derive(
220 Animate,
221 Clone,
222 ComputeSquaredDistance,
223 Debug,
224 Deserialize,
225 MallocSizeOf,
226 PartialEq,
227 Serialize,
228 SpecifiedValueInfo,
229 ToAnimatedValue,
230 ToComputedValue,
231 ToResolvedValue,
232 ToShmem,
233)]
234#[css(function = "inset")]
235#[repr(C)]
236pub struct GenericInsetRect<LengthPercentage, NonNegativeLengthPercentage> {
237 pub rect: Rect<LengthPercentage>,
238 #[shmem(field_bound)]
239 pub round: GenericBorderRadius<NonNegativeLengthPercentage>,
240}
241
242pub use self::GenericInsetRect as InsetRect;
243
244#[allow(missing_docs)]
246#[derive(
247 Animate,
248 Clone,
249 ComputeSquaredDistance,
250 Copy,
251 Debug,
252 Deserialize,
253 MallocSizeOf,
254 PartialEq,
255 Serialize,
256 SpecifiedValueInfo,
257 ToAnimatedValue,
258 ToComputedValue,
259 ToResolvedValue,
260 ToShmem,
261)]
262#[css(function)]
263#[repr(C)]
264pub struct Circle<Position, NonNegativeLengthPercentage> {
265 pub position: GenericPositionOrAuto<Position>,
266 pub radius: GenericShapeRadius<NonNegativeLengthPercentage>,
267}
268
269#[allow(missing_docs)]
271#[derive(
272 Animate,
273 Clone,
274 ComputeSquaredDistance,
275 Copy,
276 Debug,
277 Deserialize,
278 MallocSizeOf,
279 PartialEq,
280 Serialize,
281 SpecifiedValueInfo,
282 ToAnimatedValue,
283 ToComputedValue,
284 ToResolvedValue,
285 ToShmem,
286)]
287#[css(function)]
288#[repr(C)]
289pub struct Ellipse<Position, NonNegativeLengthPercentage> {
290 pub position: GenericPositionOrAuto<Position>,
291 pub semiaxis_x: GenericShapeRadius<NonNegativeLengthPercentage>,
292 pub semiaxis_y: GenericShapeRadius<NonNegativeLengthPercentage>,
293}
294
295#[allow(missing_docs)]
297#[derive(
298 Animate,
299 Clone,
300 ComputeSquaredDistance,
301 Copy,
302 Debug,
303 Deserialize,
304 MallocSizeOf,
305 Parse,
306 PartialEq,
307 Serialize,
308 SpecifiedValueInfo,
309 ToAnimatedValue,
310 ToComputedValue,
311 ToCss,
312 ToResolvedValue,
313 ToShmem,
314)]
315#[repr(C, u8)]
316pub enum GenericShapeRadius<NonNegativeLengthPercentage> {
317 Length(NonNegativeLengthPercentage),
318 #[animation(error)]
319 ClosestSide,
320 #[animation(error)]
321 FarthestSide,
322}
323
324pub use self::GenericShapeRadius as ShapeRadius;
325
326#[derive(
330 Clone,
331 Debug,
332 Deserialize,
333 MallocSizeOf,
334 PartialEq,
335 Serialize,
336 SpecifiedValueInfo,
337 ToAnimatedValue,
338 ToComputedValue,
339 ToCss,
340 ToResolvedValue,
341 ToShmem,
342)]
343#[css(comma, function = "polygon")]
344#[repr(C)]
345pub struct GenericPolygon<LengthPercentage> {
346 #[css(skip_if = "is_default")]
348 pub fill: FillRule,
349 #[css(iterable)]
351 pub coordinates: crate::OwnedSlice<PolygonCoord<LengthPercentage>>,
352}
353
354pub use self::GenericPolygon as Polygon;
355
356#[derive(
358 Animate,
359 Clone,
360 ComputeSquaredDistance,
361 Debug,
362 Deserialize,
363 MallocSizeOf,
364 PartialEq,
365 Serialize,
366 SpecifiedValueInfo,
367 ToAnimatedValue,
368 ToComputedValue,
369 ToCss,
370 ToResolvedValue,
371 ToShmem,
372)]
373#[repr(C)]
374pub struct PolygonCoord<LengthPercentage>(pub LengthPercentage, pub LengthPercentage);
375
376#[derive(
378 Clone,
379 ComputeSquaredDistance,
380 Debug,
381 Deserialize,
382 MallocSizeOf,
383 PartialEq,
384 Serialize,
385 SpecifiedValueInfo,
386 ToAnimatedValue,
387 ToComputedValue,
388 ToCss,
389 ToResolvedValue,
390 ToShmem,
391)]
392#[repr(C, u8)]
393pub enum GenericPathOrShapeFunction<Angle, LengthPercentage> {
394 Path(Path),
396 Shape(#[css(field_bound)] Shape<Angle, LengthPercentage>),
398}
399
400#[allow(missing_docs)]
405#[derive(
406 Animate,
407 Clone,
408 ComputeSquaredDistance,
409 Copy,
410 Debug,
411 Deserialize,
412 Eq,
413 MallocSizeOf,
414 Parse,
415 PartialEq,
416 Serialize,
417 SpecifiedValueInfo,
418 ToAnimatedValue,
419 ToComputedValue,
420 ToCss,
421 ToResolvedValue,
422 ToShmem,
423)]
424#[repr(u8)]
425pub enum FillRule {
426 Nonzero,
427 Evenodd,
428}
429
430#[derive(
434 Animate,
435 Clone,
436 ComputeSquaredDistance,
437 Debug,
438 Deserialize,
439 MallocSizeOf,
440 PartialEq,
441 Serialize,
442 SpecifiedValueInfo,
443 ToAnimatedValue,
444 ToComputedValue,
445 ToCss,
446 ToResolvedValue,
447 ToShmem,
448)]
449#[css(comma, function = "path")]
450#[repr(C)]
451pub struct Path {
452 #[css(skip_if = "is_default")]
454 pub fill: FillRule,
455 pub path: SVGPathData,
457}
458
459impl Path {
460 #[inline]
462 pub fn commands(&self) -> &[PathCommand] {
463 self.path.commands()
464 }
465}
466
467impl<B, U> ToAnimatedZero for ClipPath<B, U> {
468 fn to_animated_zero(&self) -> Result<Self, ()> {
469 Err(())
470 }
471}
472
473impl<B, U> ToAnimatedZero for ShapeOutside<B, U> {
474 fn to_animated_zero(&self) -> Result<Self, ()> {
475 Err(())
476 }
477}
478
479impl<Length, NonNegativeLength> ToCss for InsetRect<Length, NonNegativeLength>
480where
481 Length: ToCss + PartialEq,
482 NonNegativeLength: ToCss + PartialEq + Zero,
483{
484 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
485 where
486 W: Write,
487 {
488 dest.write_str("inset(")?;
489 self.rect.to_css(dest)?;
490 if !self.round.is_zero() {
491 dest.write_str(" round ")?;
492 self.round.to_css(dest)?;
493 }
494 dest.write_char(')')
495 }
496}
497
498impl<Position, NonNegativeLengthPercentage> ToCss for Circle<Position, NonNegativeLengthPercentage>
499where
500 Position: ToCss,
501 NonNegativeLengthPercentage: ToCss + PartialEq,
502{
503 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
504 where
505 W: Write,
506 {
507 let has_radius = self.radius != Default::default();
508
509 dest.write_str("circle(")?;
510 if has_radius {
511 self.radius.to_css(dest)?;
512 }
513
514 if !matches!(self.position, GenericPositionOrAuto::Auto) {
517 if has_radius {
518 dest.write_char(' ')?;
519 }
520 dest.write_str("at ")?;
521 self.position.to_css(dest)?;
522 }
523 dest.write_char(')')
524 }
525}
526
527impl<Position, NonNegativeLengthPercentage> ToCss for Ellipse<Position, NonNegativeLengthPercentage>
528where
529 Position: ToCss,
530 NonNegativeLengthPercentage: ToCss + PartialEq,
531{
532 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
533 where
534 W: Write,
535 {
536 let has_radii =
537 self.semiaxis_x != Default::default() || self.semiaxis_y != Default::default();
538
539 dest.write_str("ellipse(")?;
540 if has_radii {
541 self.semiaxis_x.to_css(dest)?;
542 dest.write_char(' ')?;
543 self.semiaxis_y.to_css(dest)?;
544 }
545
546 if !matches!(self.position, GenericPositionOrAuto::Auto) {
549 if has_radii {
550 dest.write_char(' ')?;
551 }
552 dest.write_str("at ")?;
553 self.position.to_css(dest)?;
554 }
555 dest.write_char(')')
556 }
557}
558
559impl<L> Default for ShapeRadius<L> {
560 #[inline]
561 fn default() -> Self {
562 ShapeRadius::ClosestSide
563 }
564}
565
566impl<L> Animate for Polygon<L>
567where
568 L: Animate,
569{
570 fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
571 if self.fill != other.fill {
572 return Err(());
573 }
574 let coordinates =
575 lists::by_computed_value::animate(&self.coordinates, &other.coordinates, procedure)?;
576 Ok(Polygon {
577 fill: self.fill,
578 coordinates,
579 })
580 }
581}
582
583impl<L> ComputeSquaredDistance for Polygon<L>
584where
585 L: ComputeSquaredDistance,
586{
587 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
588 if self.fill != other.fill {
589 return Err(());
590 }
591 lists::by_computed_value::squared_distance(&self.coordinates, &other.coordinates)
592 }
593}
594
595impl Default for FillRule {
596 #[inline]
597 fn default() -> Self {
598 FillRule::Nonzero
599 }
600}
601
602#[inline]
603fn is_default<T: Default + PartialEq>(fill: &T) -> bool {
604 *fill == Default::default()
605}
606
607#[derive(
612 Clone,
613 Debug,
614 Deserialize,
615 MallocSizeOf,
616 PartialEq,
617 Serialize,
618 SpecifiedValueInfo,
619 ToAnimatedValue,
620 ToComputedValue,
621 ToResolvedValue,
622 ToShmem,
623)]
624#[repr(C)]
625pub struct Shape<Angle, LengthPercentage> {
626 pub fill: FillRule,
628 pub commands: crate::OwnedSlice<GenericShapeCommand<Angle, LengthPercentage>>,
632}
633
634impl<Angle, LengthPercentage> Shape<Angle, LengthPercentage> {
635 #[inline]
637 pub fn commands(&self) -> &[GenericShapeCommand<Angle, LengthPercentage>] {
638 &self.commands
639 }
640}
641
642impl<Angle, LengthPercentage> Animate for Shape<Angle, LengthPercentage>
643where
644 Angle: Animate,
645 LengthPercentage: Animate,
646{
647 fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
648 if self.fill != other.fill {
649 return Err(());
650 }
651 let commands =
652 lists::by_computed_value::animate(&self.commands, &other.commands, procedure)?;
653 Ok(Self {
654 fill: self.fill,
655 commands,
656 })
657 }
658}
659
660impl<Angle, LengthPercentage> ComputeSquaredDistance for Shape<Angle, LengthPercentage>
661where
662 Angle: ComputeSquaredDistance,
663 LengthPercentage: ComputeSquaredDistance,
664{
665 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
666 if self.fill != other.fill {
667 return Err(());
668 }
669 lists::by_computed_value::squared_distance(&self.commands, &other.commands)
670 }
671}
672
673impl<Angle, LengthPercentage> ToCss for Shape<Angle, LengthPercentage>
674where
675 Angle: ToCss + Zero,
676 LengthPercentage: PartialEq + ToCss,
677{
678 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
679 where
680 W: Write,
681 {
682 use style_traits::values::SequenceWriter;
683
684 debug_assert!(self.commands.len() > 1);
686
687 dest.write_str("shape(")?;
688 if !is_default(&self.fill) {
689 self.fill.to_css(dest)?;
690 dest.write_char(' ')?;
691 }
692 dest.write_str("from ")?;
693 match self.commands[0] {
694 ShapeCommand::Move {
695 by_to: _,
696 ref point,
697 } => point.to_css(dest)?,
698 _ => unreachable!("The first command must be move"),
699 }
700 dest.write_str(", ")?;
701 {
702 let mut writer = SequenceWriter::new(dest, ", ");
703 for command in self.commands.iter().skip(1) {
704 writer.item(command)?;
705 }
706 }
707 dest.write_char(')')
708 }
709}
710
711#[derive(
716 Animate,
717 Clone,
718 ComputeSquaredDistance,
719 Copy,
720 Debug,
721 Deserialize,
722 MallocSizeOf,
723 PartialEq,
724 Serialize,
725 SpecifiedValueInfo,
726 ToAnimatedValue,
727 ToAnimatedZero,
728 ToComputedValue,
729 ToResolvedValue,
730 ToShmem,
731)]
732#[allow(missing_docs)]
733#[repr(C, u8)]
734pub enum GenericShapeCommand<Angle, LengthPercentage> {
735 Move {
737 by_to: ByTo,
738 point: CoordinatePair<LengthPercentage>,
739 },
740 Line {
742 by_to: ByTo,
743 point: CoordinatePair<LengthPercentage>,
744 },
745 HLine { by_to: ByTo, x: LengthPercentage },
747 VLine { by_to: ByTo, y: LengthPercentage },
749 CubicCurve {
751 by_to: ByTo,
752 point: CoordinatePair<LengthPercentage>,
753 control1: CoordinatePair<LengthPercentage>,
754 control2: CoordinatePair<LengthPercentage>,
755 },
756 QuadCurve {
758 by_to: ByTo,
759 point: CoordinatePair<LengthPercentage>,
760 control1: CoordinatePair<LengthPercentage>,
761 },
762 SmoothCubic {
764 by_to: ByTo,
765 point: CoordinatePair<LengthPercentage>,
766 control2: CoordinatePair<LengthPercentage>,
767 },
768 SmoothQuad {
770 by_to: ByTo,
771 point: CoordinatePair<LengthPercentage>,
772 },
773 Arc {
775 by_to: ByTo,
776 point: CoordinatePair<LengthPercentage>,
777 radii: CoordinatePair<LengthPercentage>,
778 arc_sweep: ArcSweep,
779 arc_size: ArcSize,
780 rotate: Angle,
781 },
782 Close,
784}
785
786pub use self::GenericShapeCommand as ShapeCommand;
787
788impl<Angle, LengthPercentage> ToCss for ShapeCommand<Angle, LengthPercentage>
789where
790 Angle: ToCss + Zero,
791 LengthPercentage: PartialEq + ToCss,
792{
793 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
794 where
795 W: fmt::Write,
796 {
797 use self::ShapeCommand::*;
798 match *self {
799 Move { by_to, ref point } => {
800 dest.write_str("move ")?;
801 by_to.to_css(dest)?;
802 dest.write_char(' ')?;
803 point.to_css(dest)
804 },
805 Line { by_to, ref point } => {
806 dest.write_str("line ")?;
807 by_to.to_css(dest)?;
808 dest.write_char(' ')?;
809 point.to_css(dest)
810 },
811 HLine { by_to, ref x } => {
812 dest.write_str("hline ")?;
813 by_to.to_css(dest)?;
814 dest.write_char(' ')?;
815 x.to_css(dest)
816 },
817 VLine { by_to, ref y } => {
818 dest.write_str("vline ")?;
819 by_to.to_css(dest)?;
820 dest.write_char(' ')?;
821 y.to_css(dest)
822 },
823 CubicCurve {
824 by_to,
825 ref point,
826 ref control1,
827 ref control2,
828 } => {
829 dest.write_str("curve ")?;
830 by_to.to_css(dest)?;
831 dest.write_char(' ')?;
832 point.to_css(dest)?;
833 dest.write_str(" via ")?;
834 control1.to_css(dest)?;
835 dest.write_char(' ')?;
836 control2.to_css(dest)
837 },
838 QuadCurve {
839 by_to,
840 ref point,
841 ref control1,
842 } => {
843 dest.write_str("curve ")?;
844 by_to.to_css(dest)?;
845 dest.write_char(' ')?;
846 point.to_css(dest)?;
847 dest.write_str(" via ")?;
848 control1.to_css(dest)
849 },
850 SmoothCubic {
851 by_to,
852 ref point,
853 ref control2,
854 } => {
855 dest.write_str("smooth ")?;
856 by_to.to_css(dest)?;
857 dest.write_char(' ')?;
858 point.to_css(dest)?;
859 dest.write_str(" via ")?;
860 control2.to_css(dest)
861 },
862 SmoothQuad { by_to, ref point } => {
863 dest.write_str("smooth ")?;
864 by_to.to_css(dest)?;
865 dest.write_char(' ')?;
866 point.to_css(dest)
867 },
868 Arc {
869 by_to,
870 ref point,
871 ref radii,
872 arc_sweep,
873 arc_size,
874 ref rotate,
875 } => {
876 dest.write_str("arc ")?;
877 by_to.to_css(dest)?;
878 dest.write_char(' ')?;
879 point.to_css(dest)?;
880 dest.write_str(" of ")?;
881 radii.x.to_css(dest)?;
882 if radii.x != radii.y {
883 dest.write_char(' ')?;
884 radii.y.to_css(dest)?;
885 }
886
887 if matches!(arc_sweep, ArcSweep::Cw) {
888 dest.write_str(" cw")?;
889 }
890
891 if matches!(arc_size, ArcSize::Large) {
892 dest.write_str(" large")?;
893 }
894
895 if !rotate.is_zero() {
896 dest.write_str(" rotate ")?;
897 rotate.to_css(dest)?;
898 }
899 Ok(())
900 },
901 Close => dest.write_str("close"),
902 }
903 }
904}
905
906#[derive(
909 Animate,
910 Clone,
911 ComputeSquaredDistance,
912 Copy,
913 Debug,
914 Deserialize,
915 MallocSizeOf,
916 Parse,
917 PartialEq,
918 Serialize,
919 SpecifiedValueInfo,
920 ToAnimatedValue,
921 ToAnimatedZero,
922 ToComputedValue,
923 ToCss,
924 ToResolvedValue,
925 ToShmem,
926)]
927#[repr(u8)]
928pub enum ByTo {
929 By,
931 To,
933}
934
935impl ByTo {
936 #[inline]
938 pub fn is_abs(&self) -> bool {
939 matches!(self, ByTo::To)
940 }
941
942 #[inline]
944 pub fn new(is_abs: bool) -> Self {
945 if is_abs {
946 Self::To
947 } else {
948 Self::By
949 }
950 }
951}
952
953#[allow(missing_docs)]
958#[derive(
959 AddAssign,
960 Animate,
961 Clone,
962 ComputeSquaredDistance,
963 Copy,
964 Debug,
965 Deserialize,
966 MallocSizeOf,
967 PartialEq,
968 Serialize,
969 SpecifiedValueInfo,
970 ToAnimatedValue,
971 ToAnimatedZero,
972 ToComputedValue,
973 ToCss,
974 ToResolvedValue,
975 ToShmem,
976)]
977#[repr(C)]
978pub struct CoordinatePair<LengthPercentage> {
979 pub x: LengthPercentage,
980 pub y: LengthPercentage,
981}
982
983impl<LengthPercentage> CoordinatePair<LengthPercentage> {
984 #[inline]
986 pub fn new(x: LengthPercentage, y: LengthPercentage) -> Self {
987 Self { x, y }
988 }
989}
990
991#[derive(
995 Clone,
996 Copy,
997 Debug,
998 Deserialize,
999 FromPrimitive,
1000 MallocSizeOf,
1001 Parse,
1002 PartialEq,
1003 Serialize,
1004 SpecifiedValueInfo,
1005 ToAnimatedValue,
1006 ToAnimatedZero,
1007 ToComputedValue,
1008 ToCss,
1009 ToResolvedValue,
1010 ToShmem,
1011)]
1012#[repr(u8)]
1013pub enum ArcSweep {
1014 Ccw = 0,
1016 Cw = 1,
1018}
1019
1020impl Animate for ArcSweep {
1021 fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
1022 use num_traits::FromPrimitive;
1023 (*self as i32)
1026 .animate(&(*other as i32), procedure)
1027 .map(|v| ArcSweep::from_u8((v > 0) as u8).unwrap_or(ArcSweep::Ccw))
1028 }
1029}
1030
1031impl ComputeSquaredDistance for ArcSweep {
1032 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
1033 (*self as i32).compute_squared_distance(&(*other as i32))
1034 }
1035}
1036
1037#[derive(
1041 Clone,
1042 Copy,
1043 Debug,
1044 Deserialize,
1045 FromPrimitive,
1046 MallocSizeOf,
1047 Parse,
1048 PartialEq,
1049 Serialize,
1050 SpecifiedValueInfo,
1051 ToAnimatedValue,
1052 ToAnimatedZero,
1053 ToComputedValue,
1054 ToCss,
1055 ToResolvedValue,
1056 ToShmem,
1057)]
1058#[repr(u8)]
1059pub enum ArcSize {
1060 Small = 0,
1062 Large = 1,
1064}
1065
1066impl Animate for ArcSize {
1067 fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
1068 use num_traits::FromPrimitive;
1069 (*self as i32)
1072 .animate(&(*other as i32), procedure)
1073 .map(|v| ArcSize::from_u8((v > 0) as u8).unwrap_or(ArcSize::Small))
1074 }
1075}
1076
1077impl ComputeSquaredDistance for ArcSize {
1078 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
1079 (*self as i32).compute_squared_distance(&(*other as i32))
1080 }
1081}