Skip to content

Commit 6a3a8f0

Browse files
JoonghyunChorookiejava
authored andcommitted
[Tizen] Add Shadows (#233)
* [Tizen] Add Shadows * [Tizen] Apply review comments * [Tizen] Move updating shape in proper position * [Tizen] Update BackgroundDrawable * [Tizen] Apply review comments
1 parent 9954658 commit 6a3a8f0

File tree

8 files changed

+229
-32
lines changed

8 files changed

+229
-32
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
namespace Microsoft.Maui.Graphics
2+
{
3+
public class BackgroundDrawable : IDrawable
4+
{
5+
Paint _paint;
6+
PathF _path;
7+
8+
public BackgroundDrawable(Paint paint, PathF path)
9+
{
10+
_paint = paint;
11+
_path = path;
12+
}
13+
14+
public void UpdatePaint(Paint paint)
15+
{
16+
_paint = paint;
17+
}
18+
19+
public void UpdatePath(PathF path)
20+
{
21+
_path = path;
22+
}
23+
24+
public void Draw(ICanvas canvas, RectangleF dirtyRect)
25+
{
26+
canvas.SaveState();
27+
28+
canvas.SetFillPaint(_paint, dirtyRect);
29+
canvas.FillPath(_path);
30+
31+
canvas.RestoreState();
32+
}
33+
}
34+
}

src/Core/src/Graphics/PaintExtensions.Tizen.cs

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,9 @@
22
{
33
public static partial class PaintExtensions
44
{
5-
public static IDrawable ToDrawable(this Paint paint)
5+
public static IDrawable ToDrawable(this Paint paint, PathF path)
66
{
7-
return new BackgroundDrawable(paint);
8-
}
9-
10-
class BackgroundDrawable : IDrawable
11-
{
12-
Paint _paint;
13-
public BackgroundDrawable(Paint paint)
14-
{
15-
_paint = paint;
16-
}
17-
18-
public void Draw(ICanvas canvas, RectangleF dirtyRect)
19-
{
20-
canvas.SaveState();
21-
22-
canvas.SetFillPaint(_paint, dirtyRect);
23-
canvas.FillRectangle(dirtyRect);
24-
25-
canvas.RestoreState();
26-
}
7+
return new BackgroundDrawable(paint, path);
278
}
289
}
2910
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
namespace Microsoft.Maui.Graphics
2+
{
3+
public class ShadowDrawable : IDrawable
4+
{
5+
IShadow _shadow;
6+
PathF _path;
7+
8+
public ShadowDrawable(IShadow shadow, PathF path)
9+
{
10+
_shadow = shadow;
11+
_path = path;
12+
}
13+
14+
public void UpdateShadow(IShadow shadow, PathF path)
15+
{
16+
_shadow = shadow;
17+
_path = path;
18+
}
19+
20+
public void Draw(ICanvas canvas, RectangleF dirtyRect)
21+
{
22+
canvas.SaveState();
23+
Color color = _shadow.Paint.ToColor() != null ? _shadow.Paint.ToColor()!.MultiplyAlpha(_shadow.Opacity) : Colors.Black.MultiplyAlpha(_shadow.Opacity);
24+
canvas.SetShadow(
25+
new SizeF((float)_shadow.Offset.X, (float)_shadow.Offset.Y),
26+
(int)_shadow.Radius,
27+
color);
28+
canvas.FillPath(_path);
29+
canvas.RestoreState();
30+
31+
canvas.SaveState();
32+
canvas.StrokeColor = Colors.Transparent;
33+
canvas.DrawPath(_path);
34+
canvas.ClipPath(_path, WindingMode.EvenOdd);
35+
canvas.RestoreState();
36+
}
37+
}
38+
}

src/Core/src/Handlers/ShapeView/ShapeViewHandler.Tizen.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,16 @@ protected override MauiShapeView CreateNativeView()
1515
};
1616
}
1717

18+
protected override void SetupContainer()
19+
{
20+
base.SetupContainer();
21+
ContainerView?.UpdateShape(VirtualView.Shape);
22+
}
23+
1824
public static void MapShape(ShapeViewHandler handler, IShapeView shapeView)
1925
{
2026
handler.NativeView?.UpdateShape(shapeView);
27+
handler.ContainerView?.UpdateShape(shapeView.Shape);
2128
}
2229

2330
public static void MapAspect(ShapeViewHandler handler, IShapeView shapeView)

src/Core/src/Platform/Tizen/DPExtensions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ public static double ToScaledDP(this int pixel)
6565
return pixel / DeviceInfo.ScalingFactor;
6666
}
6767

68+
public static float ToScaledDP(this float pixel)
69+
{
70+
return pixel / (float)DeviceInfo.ScalingFactor;
71+
}
72+
6873
public static double ToScaledDP(this double pixel)
6974
{
7075
return pixel / DeviceInfo.ScalingFactor;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
using ElmSharp;
3+
4+
namespace Microsoft.Maui
5+
{
6+
internal static class GeometryExtensions
7+
{
8+
public static Rect ExpandTo(this Rect geometry, IShadow? shadow)
9+
{
10+
double left = 0;
11+
double top = 0;
12+
double right = 0;
13+
double bottom = 0;
14+
15+
var scaledOffsetX = shadow == null ? 0 : shadow.Offset.X.ToScaledPixel();
16+
var scaledOffsetY = shadow == null ? 0 : shadow.Offset.Y.ToScaledPixel();
17+
var scaledBlurRadius = shadow == null ? 0 : ((double)shadow.Radius).ToScaledPixel();
18+
var spreadSize = scaledBlurRadius * 3;
19+
var spreadLeft = scaledOffsetX - spreadSize;
20+
var spreadRight = scaledOffsetX + spreadSize;
21+
var spreadTop = scaledOffsetY - spreadSize;
22+
var spreadBottom = scaledOffsetY + spreadSize;
23+
if (left > spreadLeft)
24+
left = spreadLeft;
25+
if (top > spreadTop)
26+
top = spreadTop;
27+
if (right < spreadRight)
28+
right = spreadRight;
29+
if (bottom < spreadBottom)
30+
bottom = spreadBottom;
31+
32+
var canvasGeometry = new Rect(
33+
geometry.X + (int)left,
34+
geometry.Y + (int)top,
35+
geometry.Width + (int)right - (int)left,
36+
geometry.Height + (int)bottom - (int)top);
37+
38+
return canvasGeometry;
39+
}
40+
}
41+
}

src/Core/src/Platform/Tizen/ViewExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ public static bool ToNativeVisibility(this Visibility visibility)
4040

4141
public static void UpdateBackground(this EvasObject nativeView, IView view)
4242
{
43-
if (nativeView is IWrapperViewCanvas canvas)
43+
if (nativeView is WrapperView wrapperView)
4444
{
45-
canvas.Drawables.BackgroundDrawable = view.Background?.ToDrawable() ?? null;
45+
wrapperView.UpdateBackground(view.Background);
4646
}
4747
else
4848
{

src/Core/src/Platform/Tizen/WrapperView.cs

Lines changed: 100 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,24 @@ public partial class WrapperView : Canvas, IWrapperViewCanvas
1515
Lazy<SkiaGraphicsView> _drawableCanvas;
1616
Lazy<SKClipperView> _clipperView;
1717
EvasObject? _content;
18+
IShape? _shape;
1819

1920
public WrapperView(EvasObject parent) : base(parent)
2021
{
2122
_drawableCanvas = new Lazy<SkiaGraphicsView>(() =>
2223
{
23-
var view = new SkiaGraphicsView(parent);
24+
var view = new SkiaGraphicsView(parent)
25+
{
26+
IgnorePixelScaling = true
27+
};
2428
var _drawables = new WrapperViewDrawables();
2529
_drawables.Invalidated += (s, e) =>
2630
{
2731
view.Invalidate();
2832
};
2933
view.Drawable = _drawables;
3034
view.Show();
35+
view.PassEvents = true;
3136
Children.Add(view);
3237
view.Lower();
3338
Content?.RaiseTop();
@@ -50,9 +55,72 @@ public WrapperView(EvasObject parent) : base(parent)
5055
LayoutUpdated += OnLayout;
5156
}
5257

58+
public void UpdateBackground(Paint? paint)
59+
{
60+
if (paint == null)
61+
{
62+
Drawables.BackgroundDrawable = null;
63+
}
64+
else
65+
{
66+
if (Drawables.BackgroundDrawable == null)
67+
{
68+
Drawables.BackgroundDrawable = paint.ToDrawable(GetBoundaryPath());
69+
}
70+
else
71+
{
72+
(Drawables.BackgroundDrawable as BackgroundDrawable)!.UpdatePaint(paint);
73+
}
74+
}
75+
_drawableCanvas.Value.Invalidate();
76+
}
77+
78+
public void UpdateShape(IShape? shape)
79+
{
80+
_shape = shape;
81+
UpdateDrawableCanvas(false);
82+
}
83+
84+
partial void ShadowChanged()
85+
{
86+
if (Shadow == null)
87+
{
88+
Drawables.ShadowDrawable = null;
89+
return;
90+
}
91+
92+
if (Drawables.ShadowDrawable == null)
93+
{
94+
Drawables.ShadowDrawable = new ShadowDrawable(Shadow, GetBoundaryPath());
95+
_drawableCanvas.Value.SetClip(null);
96+
}
97+
UpdateDrawableCanvas(true);
98+
}
99+
53100
partial void ClipChanged()
54101
{
55102
_clipperView.Value.Invalidate();
103+
UpdateDrawableCanvas(false);
104+
}
105+
106+
void UpdateDrawableCanvas(bool isShadowUpdated)
107+
{
108+
if (isShadowUpdated)
109+
{
110+
UpdateDrawableCanvasGeometry();
111+
}
112+
UpdateDrawables();
113+
_drawableCanvas.Value.Invalidate();
114+
}
115+
116+
void UpdateDrawables()
117+
{
118+
var path = GetBoundaryPath();
119+
if (Shadow != null)
120+
{
121+
(Drawables.ShadowDrawable as ShadowDrawable)?.UpdateShadow(Shadow, path);
122+
}
123+
(Drawables.BackgroundDrawable as BackgroundDrawable)?.UpdatePath(path);
56124
}
57125

58126
void OnClipPaint(object? sender, DrawClipEventArgs e)
@@ -75,10 +143,6 @@ void OnClipPaint(object? sender, DrawClipEventArgs e)
75143

76144
canvas.FillPath(clipPath);
77145
Content?.SetClipperCanvas(_clipperView.Value);
78-
if (_drawableCanvas.IsValueCreated)
79-
{
80-
_drawableCanvas.Value.SetClipperCanvas(_clipperView.Value);
81-
}
82146
}
83147

84148
void OnLayout(object? sender, LayoutEventArgs e)
@@ -90,7 +154,7 @@ void OnLayout(object? sender, LayoutEventArgs e)
90154

91155
if (_drawableCanvas.IsValueCreated)
92156
{
93-
_drawableCanvas.Value.Geometry = Geometry;
157+
UpdateDrawableCanvas(true);
94158
}
95159

96160
if (_clipperView.IsValueCreated)
@@ -120,15 +184,42 @@ public EvasObject? Content
120184
}
121185
}
122186
}
187+
}
123188

189+
public IWrapperViewDrawables Drawables => (IWrapperViewDrawables)_drawableCanvas.Value.Drawable;
190+
191+
void UpdateDrawableCanvasGeometry()
192+
{
193+
if (_drawableCanvas.IsValueCreated)
194+
{
195+
_drawableCanvas.Value.Geometry = Geometry.ExpandTo(Shadow);
196+
}
124197
}
125198

126-
public IWrapperViewDrawables Drawables
199+
PathF GetBoundaryPath()
127200
{
128-
get
201+
var drawableGeometry = _drawableCanvas.Value.Geometry;
202+
var left = Geometry.Left - drawableGeometry.Left;
203+
var top = Geometry.Top - drawableGeometry.Top;
204+
var width = Geometry.Width;
205+
var height = Geometry.Height;
206+
var bounds = new Tizen.UIExtensions.Common.Rect(left, top, width, height).ToDP();
207+
208+
if (Clip != null)
209+
{
210+
var clipPath = Clip.PathForBounds(bounds);
211+
clipPath.Move((float)bounds.Left, (float)bounds.Top);
212+
return clipPath;
213+
}
214+
215+
if (_shape != null)
129216
{
130-
return (_drawableCanvas.Value.Drawable as IWrapperViewDrawables)!;
217+
return _shape.PathForBounds(bounds);
131218
}
219+
220+
var path = new PathF();
221+
path.AppendRectangle(bounds);
222+
return path;
132223
}
133224
}
134225

0 commit comments

Comments
 (0)