Skip to main content

freya_core/style/
render_callback.rs

1use std::{
2    cell::RefCell,
3    fmt,
4    hash::{
5        Hash,
6        Hasher,
7    },
8    rc::Rc,
9};
10
11use freya_engine::prelude::{
12    Canvas,
13    FontCollection,
14    Paint,
15    TextStyle,
16};
17use torin::prelude::{
18    Point2D,
19    Size2D,
20};
21
22use crate::{
23    data::TextStyleState,
24    prelude::Color,
25};
26
27/// Custom fill target.
28pub enum RenderTarget<'a> {
29    /// Draw the background.
30    Background {
31        canvas: &'a Canvas,
32        font_collection: &'a mut FontCollection,
33    },
34    /// Set the text paint.
35    TextStyle(&'a mut TextStyle),
36}
37
38/// Context for drawing a background or configuring text paint.
39pub struct RenderContext<'a> {
40    pub target: RenderTarget<'a>,
41    /// Display scale factor for converting logical coordinates to physical pixels.
42    pub scale_factor: f64,
43    /// Background position in logical coordinates or text fill position within the paragraph.
44    pub origin: Point2D,
45    /// Background size in logical coordinates or text fill size in physical coordinates.
46    pub size: Size2D,
47    pub text_style_state: &'a TextStyleState,
48}
49
50impl RenderContext<'_> {
51    /// Draws with this paint or applies it to the text foreground.
52    pub fn set_paint(&mut self, paint: &Paint) {
53        match &mut self.target {
54            RenderTarget::Background { canvas, .. } => {
55                canvas.draw_paint(paint);
56            }
57            RenderTarget::TextStyle(text_style) => {
58                text_style.set_foreground_paint(paint);
59            }
60        }
61    }
62
63    /// Fills the background or sets the text color.
64    pub fn set_color(&mut self, color: impl Into<Color>) {
65        let color = color.into();
66        match &mut self.target {
67            RenderTarget::Background { canvas, .. } => {
68                let mut paint = Paint::default();
69                paint.set_color(color);
70                canvas.draw_paint(&paint);
71            }
72            RenderTarget::TextStyle(text_style) => {
73                text_style.clear_foreground_color();
74                text_style.set_color(color);
75            }
76        }
77    }
78}
79
80type Callback = Rc<RefCell<dyn FnMut(&mut RenderContext)>>;
81
82#[derive(Clone)]
83pub struct RenderCallback(Callback);
84
85impl RenderCallback {
86    pub fn new(callback: impl FnMut(&mut RenderContext) + 'static) -> Self {
87        Self(Rc::new(RefCell::new(callback)))
88    }
89
90    pub fn call(&self, context: &mut RenderContext) {
91        (self.0.borrow_mut())(context);
92    }
93}
94
95impl Default for RenderCallback {
96    fn default() -> Self {
97        Self::new(|_| {})
98    }
99}
100
101impl<F: FnMut(&mut RenderContext) + 'static> From<F> for RenderCallback {
102    fn from(callback: F) -> Self {
103        Self::new(callback)
104    }
105}
106
107impl PartialEq for RenderCallback {
108    fn eq(&self, other: &Self) -> bool {
109        Rc::ptr_eq(&self.0, &other.0)
110    }
111}
112
113impl Hash for RenderCallback {
114    fn hash<H: Hasher>(&self, state: &mut H) {
115        Rc::as_ptr(&self.0).hash(state);
116    }
117}
118
119impl fmt::Debug for RenderCallback {
120    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
121        formatter.debug_tuple("RenderCallback").finish()
122    }
123}
124
125impl fmt::Display for RenderCallback {
126    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
127        write!(formatter, "RenderCallback({:p})", Rc::as_ptr(&self.0))
128    }
129}