1212
1313namespace Pathfinder {
1414
15+ constexpr float SHADOW_DOWNSAMPLING_SCALE = 0 .5f ;
16+
1517struct ShadowBlurRenderTargetInfo {
1618 // / Render target ids.
1719 RenderTargetId id_x;
@@ -39,15 +41,18 @@ ShadowBlurRenderTargetInfo push_shadow_blur_render_targets(Scene &scene,
3941 return shadow_blur_info;
4042 }
4143
42- auto sigma = current_state.shadow_blur * 0 .5f ;
44+ float sigma_original = current_state.shadow_blur * 0 .5f ;
45+ float sigma_scaled = sigma_original * SHADOW_DOWNSAMPLING_SCALE ;
4346
4447 // Bounds expansion caused by blurring.
45- auto bounds = outline_bounds.dilate (sigma * 3 .f ).round_out ().to_i32 ();
48+ auto bounds = outline_bounds.dilate (sigma_original * 3 .f ).round_out ().to_i32 ();
49+
50+ Vec2I scaled_size = (bounds.size ().to_f32 () * SHADOW_DOWNSAMPLING_SCALE ).to_i32 ();
4651
47- shadow_blur_info.id_y = scene.push_render_target (RenderTargetDesc{bounds. size () , " shadow blur x" });
48- shadow_blur_info.id_x = scene.push_render_target (RenderTargetDesc{bounds. size () , " shadow blur y" });
52+ shadow_blur_info.id_y = scene.push_render_target (RenderTargetDesc{scaled_size , " shadow blur x" });
53+ shadow_blur_info.id_x = scene.push_render_target (RenderTargetDesc{scaled_size , " shadow blur y" });
4954
50- shadow_blur_info.sigma = sigma ;
55+ shadow_blur_info.sigma = sigma_scaled ;
5156 shadow_blur_info.bounds = bounds;
5257
5358 shadow_blur_info.color = current_state.shadow_color ;
@@ -65,9 +70,15 @@ void composite_shadow_blur_render_targets(Scene &scene, const ShadowBlurRenderTa
6570 return ;
6671 }
6772
68- auto pattern_x = Pattern::from_render_target (info.id_x , info.bounds .size ());
69- auto pattern_y = Pattern::from_render_target (info.id_y , info.bounds .size ());
70- pattern_y.apply_transform (Transform2::from_translation (info.bounds .origin ().to_f32 ()));
73+ Vec2I scaled_size = (info.bounds .size ().to_f32 () * SHADOW_DOWNSAMPLING_SCALE ).to_i32 ();
74+
75+ auto pattern_x = Pattern::from_render_target (info.id_x , scaled_size);
76+ auto pattern_y = Pattern::from_render_target (info.id_y , scaled_size);
77+
78+ Transform2 transform = Transform2::from_translation (info.bounds .origin ().to_f32 ()) *
79+ Transform2::from_scale (Vec2F (1.0 / SHADOW_DOWNSAMPLING_SCALE ));
80+
81+ pattern_y.apply_transform (transform);
7182
7283 auto filter = PatternFilter ();
7384
@@ -93,7 +104,7 @@ void composite_shadow_blur_render_targets(Scene &scene, const ShadowBlurRenderTa
93104 DrawPath path_x;
94105 {
95106 Path2d path2d;
96- path2d.add_rect ({{0 , 0 }, info. bounds . size () .to_f32 ()});
107+ path2d.add_rect ({{0 , 0 }, scaled_size .to_f32 ()});
97108 path_x.outline = path2d.into_outline ();
98109 }
99110 path_x.paint = paint_id_x;
@@ -170,7 +181,13 @@ void Canvas::push_path(Outline &outline, PathOp path_op, FillRule fill_rule) {
170181
171182 auto shadow_blur_info = push_shadow_blur_render_targets (*scene, current_state, shadow_outline.bounds );
172183
173- shadow_outline.transform (Transform2::from_translation (-shadow_blur_info.bounds .origin ().to_f32 ()));
184+ Vec2I scaled_size = (shadow_blur_info.bounds .size ().to_f32 () * SHADOW_DOWNSAMPLING_SCALE ).to_i32 ();
185+ float inv_scale_x = (float )shadow_blur_info.bounds .width () / (float )scaled_size.x ;
186+ float inv_scale_y = (float )shadow_blur_info.bounds .height () / (float )scaled_size.y ;
187+
188+ // 输入端:先平移到局部原点,再缩小。对应顺序:Scale * Translate
189+ shadow_outline.transform (Transform2::from_scale (Vec2F (1 .0f / inv_scale_x, 1 .0f / inv_scale_y)) *
190+ Transform2::from_translation (-shadow_blur_info.bounds .origin ().to_f32 ()));
174191
175192 // Per spec the shadow must respect the alpha of the shadowed path, but otherwise have
176193 // the color of the shadow paint.
0 commit comments