epaint/
shape_transform.rs

1use std::sync::Arc;
2
3use crate::{
4    color, CircleShape, Color32, ColorMode, CubicBezierShape, EllipseShape, Mesh, PathShape,
5    QuadraticBezierShape, RectShape, Shape, TextShape,
6};
7
8/// Remember to handle [`Color32::PLACEHOLDER`] specially!
9pub fn adjust_colors(
10    shape: &mut Shape,
11    adjust_color: impl Fn(&mut Color32) + Send + Sync + Copy + 'static,
12) {
13    #![allow(clippy::match_same_arms)]
14    match shape {
15        Shape::Noop => {}
16
17        Shape::Vec(shapes) => {
18            for shape in shapes {
19                adjust_colors(shape, adjust_color);
20            }
21        }
22
23        Shape::LineSegment { stroke, points: _ } => {
24            adjust_color(&mut stroke.color);
25        }
26
27        Shape::Path(PathShape {
28            points: _,
29            closed: _,
30            fill,
31            stroke,
32        })
33        | Shape::QuadraticBezier(QuadraticBezierShape {
34            points: _,
35            closed: _,
36            fill,
37            stroke,
38        })
39        | Shape::CubicBezier(CubicBezierShape {
40            points: _,
41            closed: _,
42            fill,
43            stroke,
44        }) => {
45            adjust_color(fill);
46            adjust_color_mode(&mut stroke.color, adjust_color);
47        }
48
49        Shape::Circle(CircleShape {
50            center: _,
51            radius: _,
52            fill,
53            stroke,
54        })
55        | Shape::Ellipse(EllipseShape {
56            center: _,
57            radius: _,
58            fill,
59            stroke,
60        })
61        | Shape::Rect(RectShape {
62            rect: _,
63            corner_radius: _,
64            fill,
65            stroke,
66            stroke_kind: _,
67            round_to_pixels: _,
68            blur_width: _,
69            brush: _,
70        }) => {
71            adjust_color(fill);
72            adjust_color(&mut stroke.color);
73        }
74
75        Shape::Text(TextShape {
76            pos: _,
77            galley,
78            underline,
79            fallback_color,
80            override_text_color,
81            opacity_factor: _,
82            angle: _,
83        }) => {
84            adjust_color(&mut underline.color);
85            adjust_color(fallback_color);
86            if let Some(override_text_color) = override_text_color {
87                adjust_color(override_text_color);
88            }
89
90            if !galley.is_empty() {
91                let galley = Arc::make_mut(galley);
92                for row in &mut galley.rows {
93                    for vertex in &mut row.visuals.mesh.vertices {
94                        adjust_color(&mut vertex.color);
95                    }
96                }
97            }
98        }
99
100        Shape::Mesh(mesh) => {
101            let Mesh {
102                indices: _,
103                vertices,
104                texture_id: _,
105            } = Arc::make_mut(mesh);
106
107            for v in vertices {
108                adjust_color(&mut v.color);
109            }
110        }
111
112        Shape::Callback(_) => {
113            // Can't tint user callback code
114        }
115    }
116}
117
118fn adjust_color_mode(
119    color_mode: &mut ColorMode,
120    adjust_color: impl Fn(&mut Color32) + Send + Sync + Copy + 'static,
121) {
122    match color_mode {
123        color::ColorMode::Solid(color) => adjust_color(color),
124        color::ColorMode::UV(callback) => {
125            let callback = callback.clone();
126            *color_mode = color::ColorMode::UV(Arc::new(Box::new(move |rect, pos| {
127                let mut color = callback(rect, pos);
128                adjust_color(&mut color);
129                color
130            })));
131        }
132    }
133}