Skip to main content

ferroui_base/media/
i_pen.rs

1use crate::media::immutable::ImmutablePen;
2use crate::media::{IBrush, IDashStyle, Pen, PenLineCap, PenLineJoin};
3use crate::media::ref_adapter::RefAdapter;
4use crate::{FerroObject, ObjectType, Ref, Upcast};
5use std::any::Any;
6use std::rc::Rc;
7
8/// Describes how a stroke is drawn.
9///
10/// Implemented by [`ImmutablePen`] and, through an adapter, by handles ([`Ref`]) of [`Pen`].
11pub trait IPen: 'static {
12    /// The brush used to draw the stroke.
13    fn brush(&self) -> Option<Rc<dyn IBrush>>;
14
15    /// The style of dashed lines drawn with the pen.
16    fn dash_style(&self) -> Option<Rc<dyn IDashStyle>>;
17
18    /// The type of shape to use on both ends of a line.
19    fn line_cap(&self) -> PenLineCap;
20
21    /// A value describing how to join consecutive line or curve segments.
22    fn line_join(&self) -> PenLineJoin;
23
24    /// The limit of the ratio of the miter length to half this pen's
25    /// thickness.
26    fn miter_limit(&self) -> f64;
27
28    /// The stroke thickness.
29    fn thickness(&self) -> f64;
30
31    /// The implementing value, for downcasts to [`ImmutablePen`].
32    fn as_any(&self) -> &dyn Any;
33
34    /// The pen viewed as an [`ImmutablePen`], when it is one (the `is
35    /// ImmutablePen` test of upstream, which a class deriving from it
36    /// passes).
37    fn as_immutable_pen(&self) -> Option<&ImmutablePen> {
38        self.as_any().downcast_ref::<ImmutablePen>()
39    }
40
41    /// The object behind the pen when it is a mutable [`Pen`].
42    fn as_object(&self) -> Option<&FerroObject> {
43        None
44    }
45
46    /// The composition render resource behind the object, if it is a
47    /// mutable object with server-side counterparts on the compositors it
48    /// is drawn with.
49    fn as_composition_render_resource(
50        &self,
51    ) -> Option<&dyn crate::rendering::composition::drawing::ICompositionRenderResource> {
52        None
53    }
54
55    /// Converts the pen to an immutable pen; an immutable pen returns itself.
56    fn into_immutable_pen(self: Rc<Self>) -> Rc<ImmutablePen>;
57
58    /// The form of the pen that is sent to the render thread, when the
59    /// type keeps one: see [`SharedPen`](crate::media::SharedPen).
60    fn to_shared(&self) -> Option<crate::media::SharedPen> {
61        None
62    }
63
64    /// The identity of the pen, used for reference equality.
65    #[doc(hidden)]
66    fn reference_id(&self) -> *const () {
67        self as *const Self as *const ()
68    }
69
70    /// Whether the pen equals `other`. Mutable pens compare by reference,
71    /// immutable ones structurally (against any pen).
72    fn equals(&self, other: &dyn IPen) -> bool {
73        self.reference_id() == other.reference_id()
74    }
75}
76
77impl PartialEq for dyn IPen {
78    #[inline]
79    fn eq(&self, other: &Self) -> bool {
80        self.equals(other)
81    }
82}
83
84impl std::fmt::Debug for dyn IPen {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        f.debug_struct("IPen")
87            .field("brush", &self.brush())
88            .field("thickness", &self.thickness())
89            .field("dash_style", &self.dash_style())
90            .field("line_cap", &self.line_cap())
91            .field("line_join", &self.line_join())
92            .field("miter_limit", &self.miter_limit())
93            .finish()
94    }
95}
96
97impl<T: ObjectType + Upcast<Pen>> IPen for RefAdapter<T> {
98    fn brush(&self) -> Option<Rc<dyn IBrush>> {
99        Upcast::<Pen>::upcast(&*self.0).brush()
100    }
101
102    fn dash_style(&self) -> Option<Rc<dyn IDashStyle>> {
103        Upcast::<Pen>::upcast(&*self.0).dash_style()
104    }
105
106    #[inline]
107    fn line_cap(&self) -> PenLineCap {
108        Upcast::<Pen>::upcast(&*self.0).line_cap()
109    }
110
111    #[inline]
112    fn line_join(&self) -> PenLineJoin {
113        Upcast::<Pen>::upcast(&*self.0).line_join()
114    }
115
116    #[inline]
117    fn miter_limit(&self) -> f64 {
118        Upcast::<Pen>::upcast(&*self.0).miter_limit()
119    }
120
121    #[inline]
122    fn thickness(&self) -> f64 {
123        Upcast::<Pen>::upcast(&*self.0).thickness()
124    }
125
126    fn as_any(&self) -> &dyn Any {
127        Upcast::<Pen>::upcast(&*self.0)
128    }
129
130    fn as_object(&self) -> Option<&FerroObject> {
131        Some(self.object())
132    }
133
134    fn as_composition_render_resource(
135        &self,
136    ) -> Option<&dyn crate::rendering::composition::drawing::ICompositionRenderResource> {
137        Some(Upcast::<Pen>::upcast(&*self.0))
138    }
139
140    fn into_immutable_pen(self: Rc<Self>) -> Rc<ImmutablePen> {
141        Rc::new(Upcast::<Pen>::upcast(&*self.0).to_immutable())
142    }
143
144    fn reference_id(&self) -> *const () {
145        RefAdapter::reference_id(self)
146    }
147}
148
149impl<T: ObjectType + Upcast<Pen>> From<Ref<T>> for Rc<dyn IPen> {
150    #[inline]
151    fn from(value: Ref<T>) -> Self {
152        Rc::new(RefAdapter(value))
153    }
154}
155
156impl<T: ObjectType + Upcast<Pen>> From<&Ref<T>> for Rc<dyn IPen> {
157    #[inline]
158    fn from(value: &Ref<T>) -> Self {
159        Rc::new(RefAdapter(value.clone()))
160    }
161}