freya_core/render/utils/
shadows.rs1use freya_engine::prelude::*;
2use torin::prelude::Area;
3
4use crate::{
5 states::StyleState,
6 values::{
7 CornerRadius,
8 Shadow,
9 ShadowPosition,
10 },
11};
12
13pub fn render_shadow(
14 canvas: &Canvas,
15 node_style: &StyleState,
16 path: &mut Path,
17 rounded_rect: RRect,
18 area: Area,
19 shadow: &Shadow,
20 corner_radius: &CornerRadius,
21) {
22 let mut shadow_path = Path::new();
23 let mut shadow_paint = Paint::default();
24 shadow_paint.set_anti_alias(true);
25
26 shadow.fill.apply_to_paint(&mut shadow_paint, area);
27
28 let outset: Point = match shadow.position {
32 ShadowPosition::Normal => {
33 shadow_paint.set_style(PaintStyle::Fill);
34 (shadow.spread, shadow.spread).into()
35 }
36 ShadowPosition::Inset => {
37 shadow_paint.set_style(PaintStyle::Stroke);
38 shadow_paint.set_stroke_width(shadow.blur / 2.0 + shadow.spread);
39 (-shadow.spread / 2.0, -shadow.spread / 2.0).into()
40 }
41 };
42
43 if shadow.blur > 0.0 {
45 shadow_paint.set_mask_filter(MaskFilter::blur(
46 BlurStyle::Normal,
47 shadow.blur / 2.0,
48 false,
49 ));
50 }
51
52 if corner_radius.smoothing > 0.0 {
54 shadow_path.add_path(
55 &node_style
56 .corner_radius
57 .smoothed_path(rounded_rect.with_outset(outset)),
58 Point::new(area.min_x(), area.min_y()) - outset,
59 None,
60 );
61 } else {
62 shadow_path.add_rrect(rounded_rect.with_outset(outset), None);
63 }
64
65 shadow_path.offset((shadow.x, shadow.y));
67
68 canvas.save();
70 canvas.clip_path(
71 path,
72 match shadow.position {
73 ShadowPosition::Normal => ClipOp::Difference,
74 ShadowPosition::Inset => ClipOp::Intersect,
75 },
76 true,
77 );
78 canvas.draw_path(&shadow_path, &shadow_paint);
79 canvas.restore();
80}