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 ToTyped,
117)]
118#[animation(no_bound(U))]
119#[repr(u8)]
120pub enum GenericClipPath<BasicShape, U> {
121 #[animation(error)]
122 None,
123 #[animation(error)]
124 Url(U),
125 Shape(
126 Box<BasicShape>,
127 #[css(skip_if = "is_default_box_for_clip_path")] ShapeGeometryBox,
128 ),
129 #[animation(error)]
130 Box(ShapeGeometryBox),
131}
132
133pub use self::GenericClipPath as ClipPath;
134
135#[allow(missing_docs)]
137#[derive(
138 Animate,
139 Clone,
140 ComputeSquaredDistance,
141 Debug,
142 MallocSizeOf,
143 PartialEq,
144 SpecifiedValueInfo,
145 ToAnimatedValue,
146 ToComputedValue,
147 ToCss,
148 ToResolvedValue,
149 ToShmem,
150 ToTyped,
151)]
152#[animation(no_bound(I))]
153#[repr(u8)]
154pub enum GenericShapeOutside<BasicShape, I> {
155 #[animation(error)]
156 None,
157 #[animation(error)]
158 Image(I),
159 Shape(Box<BasicShape>, #[css(skip_if = "is_default")] ShapeBox),
160 #[animation(error)]
161 Box(ShapeBox),
162}
163
164pub use self::GenericShapeOutside as ShapeOutside;
165
166#[derive(
170 Animate,
171 Clone,
172 ComputeSquaredDistance,
173 Debug,
174 Deserialize,
175 MallocSizeOf,
176 PartialEq,
177 Serialize,
178 SpecifiedValueInfo,
179 ToAnimatedValue,
180 ToComputedValue,
181 ToCss,
182 ToResolvedValue,
183 ToShmem,
184)]
185#[repr(C, u8)]
186pub enum GenericBasicShape<
187 Angle,
188 Position,
189 LengthPercentage,
190 NonNegativeLengthPercentage,
191 BasicShapeRect,
192> {
193 Rect(BasicShapeRect),
195 Circle(
197 #[css(field_bound)]
198 #[shmem(field_bound)]
199 Circle<Position, NonNegativeLengthPercentage>,
200 ),
201 Ellipse(
203 #[css(field_bound)]
204 #[shmem(field_bound)]
205 Ellipse<Position, NonNegativeLengthPercentage>,
206 ),
207 Polygon(GenericPolygon<LengthPercentage>),
209 PathOrShape(
211 #[animation(field_bound)]
212 #[css(field_bound)]
213 GenericPathOrShapeFunction<Angle, LengthPercentage>,
214 ),
215}
216
217pub use self::GenericBasicShape as BasicShape;
218
219#[allow(missing_docs)]
221#[derive(
222 Animate,
223 Clone,
224 ComputeSquaredDistance,
225 Debug,
226 Deserialize,
227 MallocSizeOf,
228 PartialEq,
229 Serialize,
230 SpecifiedValueInfo,
231 ToAnimatedValue,
232 ToComputedValue,
233 ToResolvedValue,
234 ToShmem,
235)]
236#[css(function = "inset")]
237#[repr(C)]
238pub struct GenericInsetRect<LengthPercentage, NonNegativeLengthPercentage> {
239 pub rect: Rect<LengthPercentage>,
240 #[shmem(field_bound)]
241 pub round: GenericBorderRadius<NonNegativeLengthPercentage>,
242}
243
244pub use self::GenericInsetRect as InsetRect;
245
246#[allow(missing_docs)]
248#[derive(
249 Animate,
250 Clone,
251 ComputeSquaredDistance,
252 Copy,
253 Debug,
254 Deserialize,
255 MallocSizeOf,
256 PartialEq,
257 Serialize,
258 SpecifiedValueInfo,
259 ToAnimatedValue,
260 ToComputedValue,
261 ToResolvedValue,
262 ToShmem,
263)]
264#[css(function)]
265#[repr(C)]
266pub struct Circle<Position, NonNegativeLengthPercentage> {
267 pub position: GenericPositionOrAuto<Position>,
268 pub radius: GenericShapeRadius<NonNegativeLengthPercentage>,
269}
270
271#[allow(missing_docs)]
273#[derive(
274 Animate,
275 Clone,
276 ComputeSquaredDistance,
277 Copy,
278 Debug,
279 Deserialize,
280 MallocSizeOf,
281 PartialEq,
282 Serialize,
283 SpecifiedValueInfo,
284 ToAnimatedValue,
285 ToComputedValue,
286 ToResolvedValue,
287 ToShmem,
288)]
289#[css(function)]
290#[repr(C)]
291pub struct Ellipse<Position, NonNegativeLengthPercentage> {
292 pub position: GenericPositionOrAuto<Position>,
293 pub semiaxis_x: GenericShapeRadius<NonNegativeLengthPercentage>,
294 pub semiaxis_y: GenericShapeRadius<NonNegativeLengthPercentage>,
295}
296
297#[allow(missing_docs)]
299#[derive(
300 Animate,
301 Clone,
302 ComputeSquaredDistance,
303 Copy,
304 Debug,
305 Deserialize,
306 MallocSizeOf,
307 Parse,
308 PartialEq,
309 Serialize,
310 SpecifiedValueInfo,
311 ToAnimatedValue,
312 ToComputedValue,
313 ToCss,
314 ToResolvedValue,
315 ToShmem,
316)]
317#[repr(C, u8)]
318pub enum GenericShapeRadius<NonNegativeLengthPercentage> {
319 Length(NonNegativeLengthPercentage),
320 #[animation(error)]
321 ClosestSide,
322 #[animation(error)]
323 FarthestSide,
324}
325
326pub use self::GenericShapeRadius as ShapeRadius;
327
328#[derive(
332 Clone,
333 Debug,
334 Deserialize,
335 MallocSizeOf,
336 PartialEq,
337 Serialize,
338 SpecifiedValueInfo,
339 ToAnimatedValue,
340 ToComputedValue,
341 ToCss,
342 ToResolvedValue,
343 ToShmem,
344)]
345#[css(comma, function = "polygon")]
346#[repr(C)]
347pub struct GenericPolygon<LengthPercentage> {
348 #[css(skip_if = "is_default")]
350 pub fill: FillRule,
351 #[css(iterable)]
353 pub coordinates: crate::OwnedSlice<PolygonCoord<LengthPercentage>>,
354}
355
356pub use self::GenericPolygon as Polygon;
357
358#[derive(
360 Animate,
361 Clone,
362 ComputeSquaredDistance,
363 Debug,
364 Deserialize,
365 MallocSizeOf,
366 PartialEq,
367 Serialize,
368 SpecifiedValueInfo,
369 ToAnimatedValue,
370 ToComputedValue,
371 ToCss,
372 ToResolvedValue,
373 ToShmem,
374)]
375#[repr(C)]
376pub struct PolygonCoord<LengthPercentage>(pub LengthPercentage, pub LengthPercentage);
377
378#[derive(
380 Clone,
381 ComputeSquaredDistance,
382 Debug,
383 Deserialize,
384 MallocSizeOf,
385 PartialEq,
386 Serialize,
387 SpecifiedValueInfo,
388 ToAnimatedValue,
389 ToComputedValue,
390 ToCss,
391 ToResolvedValue,
392 ToShmem,
393)]
394#[repr(C, u8)]
395pub enum GenericPathOrShapeFunction<Angle, LengthPercentage> {
396 Path(Path),
398 Shape(#[css(field_bound)] Shape<Angle, LengthPercentage>),
400}
401
402#[allow(missing_docs)]
407#[derive(
408 Animate,
409 Clone,
410 ComputeSquaredDistance,
411 Copy,
412 Debug,
413 Deserialize,
414 Eq,
415 MallocSizeOf,
416 Parse,
417 PartialEq,
418 Serialize,
419 SpecifiedValueInfo,
420 ToAnimatedValue,
421 ToComputedValue,
422 ToCss,
423 ToResolvedValue,
424 ToShmem,
425 ToTyped,
426)]
427#[repr(u8)]
428pub enum FillRule {
429 Nonzero,
430 Evenodd,
431}
432
433#[derive(
437 Animate,
438 Clone,
439 ComputeSquaredDistance,
440 Debug,
441 Deserialize,
442 MallocSizeOf,
443 PartialEq,
444 Serialize,
445 SpecifiedValueInfo,
446 ToAnimatedValue,
447 ToComputedValue,
448 ToCss,
449 ToResolvedValue,
450 ToShmem,
451)]
452#[css(comma, function = "path")]
453#[repr(C)]
454pub struct Path {
455 #[css(skip_if = "is_default")]
457 pub fill: FillRule,
458 pub path: SVGPathData,
460}
461
462impl Path {
463 #[inline]
465 pub fn commands(&self) -> &[PathCommand] {
466 self.path.commands()
467 }
468}
469
470impl<B, U> ToAnimatedZero for ClipPath<B, U> {
471 fn to_animated_zero(&self) -> Result<Self, ()> {
472 Err(())
473 }
474}
475
476impl<B, U> ToAnimatedZero for ShapeOutside<B, U> {
477 fn to_animated_zero(&self) -> Result<Self, ()> {
478 Err(())
479 }
480}
481
482impl<Length, NonNegativeLength> ToCss for InsetRect<Length, NonNegativeLength>
483where
484 Length: ToCss + PartialEq,
485 NonNegativeLength: ToCss + PartialEq + Zero,
486{
487 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
488 where
489 W: Write,
490 {
491 dest.write_str("inset(")?;
492 self.rect.to_css(dest)?;
493 if !self.round.is_zero() {
494 dest.write_str(" round ")?;
495 self.round.to_css(dest)?;
496 }
497 dest.write_char(')')
498 }
499}
500
501impl<Position, NonNegativeLengthPercentage> ToCss for Circle<Position, NonNegativeLengthPercentage>
502where
503 Position: ToCss,
504 NonNegativeLengthPercentage: ToCss + PartialEq,
505{
506 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
507 where
508 W: Write,
509 {
510 let has_radius = self.radius != Default::default();
511
512 dest.write_str("circle(")?;
513 if has_radius {
514 self.radius.to_css(dest)?;
515 }
516
517 if !matches!(self.position, GenericPositionOrAuto::Auto) {
520 if has_radius {
521 dest.write_char(' ')?;
522 }
523 dest.write_str("at ")?;
524 self.position.to_css(dest)?;
525 }
526 dest.write_char(')')
527 }
528}
529
530impl<Position, NonNegativeLengthPercentage> ToCss for Ellipse<Position, NonNegativeLengthPercentage>
531where
532 Position: ToCss,
533 NonNegativeLengthPercentage: ToCss + PartialEq,
534{
535 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
536 where
537 W: Write,
538 {
539 let has_radii =
540 self.semiaxis_x != Default::default() || self.semiaxis_y != Default::default();
541
542 dest.write_str("ellipse(")?;
543 if has_radii {
544 self.semiaxis_x.to_css(dest)?;
545 dest.write_char(' ')?;
546 self.semiaxis_y.to_css(dest)?;
547 }
548
549 if !matches!(self.position, GenericPositionOrAuto::Auto) {
552 if has_radii {
553 dest.write_char(' ')?;
554 }
555 dest.write_str("at ")?;
556 self.position.to_css(dest)?;
557 }
558 dest.write_char(')')
559 }
560}
561
562impl<L> Default for ShapeRadius<L> {
563 #[inline]
564 fn default() -> Self {
565 ShapeRadius::ClosestSide
566 }
567}
568
569impl<L> Animate for Polygon<L>
570where
571 L: Animate,
572{
573 fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
574 if self.fill != other.fill {
575 return Err(());
576 }
577 let coordinates =
578 lists::by_computed_value::animate(&self.coordinates, &other.coordinates, procedure)?;
579 Ok(Polygon {
580 fill: self.fill,
581 coordinates,
582 })
583 }
584}
585
586impl<L> ComputeSquaredDistance for Polygon<L>
587where
588 L: ComputeSquaredDistance,
589{
590 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
591 if self.fill != other.fill {
592 return Err(());
593 }
594 lists::by_computed_value::squared_distance(&self.coordinates, &other.coordinates)
595 }
596}
597
598impl Default for FillRule {
599 #[inline]
600 fn default() -> Self {
601 FillRule::Nonzero
602 }
603}
604
605#[inline]
606fn is_default<T: Default + PartialEq>(fill: &T) -> bool {
607 *fill == Default::default()
608}
609
610#[derive(
615 Clone,
616 Debug,
617 Deserialize,
618 MallocSizeOf,
619 PartialEq,
620 Serialize,
621 SpecifiedValueInfo,
622 ToAnimatedValue,
623 ToComputedValue,
624 ToResolvedValue,
625 ToShmem,
626)]
627#[repr(C)]
628pub struct Shape<Angle, LengthPercentage> {
629 pub fill: FillRule,
631 pub commands: crate::OwnedSlice<GenericShapeCommand<Angle, LengthPercentage>>,
635}
636
637impl<Angle, LengthPercentage> Shape<Angle, LengthPercentage> {
638 #[inline]
640 pub fn commands(&self) -> &[GenericShapeCommand<Angle, LengthPercentage>] {
641 &self.commands
642 }
643}
644
645impl<Angle, LengthPercentage> Animate for Shape<Angle, LengthPercentage>
646where
647 Angle: Animate,
648 LengthPercentage: Animate,
649{
650 fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
651 if self.fill != other.fill {
652 return Err(());
653 }
654 let commands =
655 lists::by_computed_value::animate(&self.commands, &other.commands, procedure)?;
656 Ok(Self {
657 fill: self.fill,
658 commands,
659 })
660 }
661}
662
663impl<Angle, LengthPercentage> ComputeSquaredDistance for Shape<Angle, LengthPercentage>
664where
665 Angle: ComputeSquaredDistance,
666 LengthPercentage: ComputeSquaredDistance,
667{
668 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
669 if self.fill != other.fill {
670 return Err(());
671 }
672 lists::by_computed_value::squared_distance(&self.commands, &other.commands)
673 }
674}
675
676impl<Angle, LengthPercentage> ToCss for Shape<Angle, LengthPercentage>
677where
678 Angle: ToCss + Zero,
679 LengthPercentage: PartialEq + ToCss,
680{
681 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
682 where
683 W: Write,
684 {
685 use style_traits::values::SequenceWriter;
686
687 debug_assert!(self.commands.len() > 1);
689
690 dest.write_str("shape(")?;
691 if !is_default(&self.fill) {
692 self.fill.to_css(dest)?;
693 dest.write_char(' ')?;
694 }
695 dest.write_str("from ")?;
696 match self.commands[0] {
697 ShapeCommand::Move {
698 by_to: _,
699 ref point,
700 } => point.to_css(dest)?,
701 _ => unreachable!("The first command must be move"),
702 }
703 dest.write_str(", ")?;
704 {
705 let mut writer = SequenceWriter::new(dest, ", ");
706 for command in self.commands.iter().skip(1) {
707 writer.item(command)?;
708 }
709 }
710 dest.write_char(')')
711 }
712}
713
714#[derive(
719 Animate,
720 Clone,
721 ComputeSquaredDistance,
722 Copy,
723 Debug,
724 Deserialize,
725 MallocSizeOf,
726 PartialEq,
727 Serialize,
728 SpecifiedValueInfo,
729 ToAnimatedValue,
730 ToAnimatedZero,
731 ToComputedValue,
732 ToResolvedValue,
733 ToShmem,
734)]
735#[allow(missing_docs)]
736#[repr(C, u8)]
737pub enum GenericShapeCommand<Angle, LengthPercentage> {
738 Move {
740 by_to: ByTo,
741 point: CoordinatePair<LengthPercentage>,
742 },
743 Line {
745 by_to: ByTo,
746 point: CoordinatePair<LengthPercentage>,
747 },
748 HLine { by_to: ByTo, x: LengthPercentage },
750 VLine { by_to: ByTo, y: LengthPercentage },
752 CubicCurve {
754 by_to: ByTo,
755 point: CoordinatePair<LengthPercentage>,
756 control1: CoordinatePair<LengthPercentage>,
757 control2: CoordinatePair<LengthPercentage>,
758 },
759 QuadCurve {
761 by_to: ByTo,
762 point: CoordinatePair<LengthPercentage>,
763 control1: CoordinatePair<LengthPercentage>,
764 },
765 SmoothCubic {
767 by_to: ByTo,
768 point: CoordinatePair<LengthPercentage>,
769 control2: CoordinatePair<LengthPercentage>,
770 },
771 SmoothQuad {
773 by_to: ByTo,
774 point: CoordinatePair<LengthPercentage>,
775 },
776 Arc {
778 by_to: ByTo,
779 point: CoordinatePair<LengthPercentage>,
780 radii: CoordinatePair<LengthPercentage>,
781 arc_sweep: ArcSweep,
782 arc_size: ArcSize,
783 rotate: Angle,
784 },
785 Close,
787}
788
789pub use self::GenericShapeCommand as ShapeCommand;
790
791impl<Angle, LengthPercentage> ToCss for ShapeCommand<Angle, LengthPercentage>
792where
793 Angle: ToCss + Zero,
794 LengthPercentage: PartialEq + ToCss,
795{
796 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
797 where
798 W: fmt::Write,
799 {
800 use self::ShapeCommand::*;
801 match *self {
802 Move { by_to, ref point } => {
803 dest.write_str("move ")?;
804 by_to.to_css(dest)?;
805 dest.write_char(' ')?;
806 point.to_css(dest)
807 },
808 Line { by_to, ref point } => {
809 dest.write_str("line ")?;
810 by_to.to_css(dest)?;
811 dest.write_char(' ')?;
812 point.to_css(dest)
813 },
814 HLine { by_to, ref x } => {
815 dest.write_str("hline ")?;
816 by_to.to_css(dest)?;
817 dest.write_char(' ')?;
818 x.to_css(dest)
819 },
820 VLine { by_to, ref y } => {
821 dest.write_str("vline ")?;
822 by_to.to_css(dest)?;
823 dest.write_char(' ')?;
824 y.to_css(dest)
825 },
826 CubicCurve {
827 by_to,
828 ref point,
829 ref control1,
830 ref control2,
831 } => {
832 dest.write_str("curve ")?;
833 by_to.to_css(dest)?;
834 dest.write_char(' ')?;
835 point.to_css(dest)?;
836 dest.write_str(" via ")?;
837 control1.to_css(dest)?;
838 dest.write_char(' ')?;
839 control2.to_css(dest)
840 },
841 QuadCurve {
842 by_to,
843 ref point,
844 ref control1,
845 } => {
846 dest.write_str("curve ")?;
847 by_to.to_css(dest)?;
848 dest.write_char(' ')?;
849 point.to_css(dest)?;
850 dest.write_str(" via ")?;
851 control1.to_css(dest)
852 },
853 SmoothCubic {
854 by_to,
855 ref point,
856 ref control2,
857 } => {
858 dest.write_str("smooth ")?;
859 by_to.to_css(dest)?;
860 dest.write_char(' ')?;
861 point.to_css(dest)?;
862 dest.write_str(" via ")?;
863 control2.to_css(dest)
864 },
865 SmoothQuad { by_to, ref point } => {
866 dest.write_str("smooth ")?;
867 by_to.to_css(dest)?;
868 dest.write_char(' ')?;
869 point.to_css(dest)
870 },
871 Arc {
872 by_to,
873 ref point,
874 ref radii,
875 arc_sweep,
876 arc_size,
877 ref rotate,
878 } => {
879 dest.write_str("arc ")?;
880 by_to.to_css(dest)?;
881 dest.write_char(' ')?;
882 point.to_css(dest)?;
883 dest.write_str(" of ")?;
884 radii.x.to_css(dest)?;
885 if radii.x != radii.y {
886 dest.write_char(' ')?;
887 radii.y.to_css(dest)?;
888 }
889
890 if matches!(arc_sweep, ArcSweep::Cw) {
891 dest.write_str(" cw")?;
892 }
893
894 if matches!(arc_size, ArcSize::Large) {
895 dest.write_str(" large")?;
896 }
897
898 if !rotate.is_zero() {
899 dest.write_str(" rotate ")?;
900 rotate.to_css(dest)?;
901 }
902 Ok(())
903 },
904 Close => dest.write_str("close"),
905 }
906 }
907}
908
909#[derive(
912 Animate,
913 Clone,
914 ComputeSquaredDistance,
915 Copy,
916 Debug,
917 Deserialize,
918 MallocSizeOf,
919 Parse,
920 PartialEq,
921 Serialize,
922 SpecifiedValueInfo,
923 ToAnimatedValue,
924 ToAnimatedZero,
925 ToComputedValue,
926 ToCss,
927 ToResolvedValue,
928 ToShmem,
929)]
930#[repr(u8)]
931pub enum ByTo {
932 By,
934 To,
936}
937
938impl ByTo {
939 #[inline]
941 pub fn is_abs(&self) -> bool {
942 matches!(self, ByTo::To)
943 }
944
945 #[inline]
947 pub fn new(is_abs: bool) -> Self {
948 if is_abs {
949 Self::To
950 } else {
951 Self::By
952 }
953 }
954}
955
956#[allow(missing_docs)]
961#[derive(
962 AddAssign,
963 Animate,
964 Clone,
965 ComputeSquaredDistance,
966 Copy,
967 Debug,
968 Deserialize,
969 MallocSizeOf,
970 PartialEq,
971 Serialize,
972 SpecifiedValueInfo,
973 ToAnimatedValue,
974 ToAnimatedZero,
975 ToComputedValue,
976 ToCss,
977 ToResolvedValue,
978 ToShmem,
979)]
980#[repr(C)]
981pub struct CoordinatePair<LengthPercentage> {
982 pub x: LengthPercentage,
983 pub y: LengthPercentage,
984}
985
986impl<LengthPercentage> CoordinatePair<LengthPercentage> {
987 #[inline]
989 pub fn new(x: LengthPercentage, y: LengthPercentage) -> Self {
990 Self { x, y }
991 }
992}
993
994#[derive(
998 Clone,
999 Copy,
1000 Debug,
1001 Deserialize,
1002 FromPrimitive,
1003 MallocSizeOf,
1004 Parse,
1005 PartialEq,
1006 Serialize,
1007 SpecifiedValueInfo,
1008 ToAnimatedValue,
1009 ToAnimatedZero,
1010 ToComputedValue,
1011 ToCss,
1012 ToResolvedValue,
1013 ToShmem,
1014)]
1015#[repr(u8)]
1016pub enum ArcSweep {
1017 Ccw = 0,
1019 Cw = 1,
1021}
1022
1023impl Animate for ArcSweep {
1024 fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
1025 use num_traits::FromPrimitive;
1026 (*self as i32)
1029 .animate(&(*other as i32), procedure)
1030 .map(|v| ArcSweep::from_u8((v > 0) as u8).unwrap_or(ArcSweep::Ccw))
1031 }
1032}
1033
1034impl ComputeSquaredDistance for ArcSweep {
1035 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
1036 (*self as i32).compute_squared_distance(&(*other as i32))
1037 }
1038}
1039
1040#[derive(
1044 Clone,
1045 Copy,
1046 Debug,
1047 Deserialize,
1048 FromPrimitive,
1049 MallocSizeOf,
1050 Parse,
1051 PartialEq,
1052 Serialize,
1053 SpecifiedValueInfo,
1054 ToAnimatedValue,
1055 ToAnimatedZero,
1056 ToComputedValue,
1057 ToCss,
1058 ToResolvedValue,
1059 ToShmem,
1060)]
1061#[repr(u8)]
1062pub enum ArcSize {
1063 Small = 0,
1065 Large = 1,
1067}
1068
1069impl Animate for ArcSize {
1070 fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
1071 use num_traits::FromPrimitive;
1072 (*self as i32)
1075 .animate(&(*other as i32), procedure)
1076 .map(|v| ArcSize::from_u8((v > 0) as u8).unwrap_or(ArcSize::Small))
1077 }
1078}
1079
1080impl ComputeSquaredDistance for ArcSize {
1081 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
1082 (*self as i32).compute_squared_distance(&(*other as i32))
1083 }
1084}