Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

[Tizen] Added Shapes Tizen implementation #12537

Merged
merged 3 commits into from
Oct 22, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Stubs/Xamarin.Forms.Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ internal class _RefreshViewRenderer { }
[RenderWith(typeof(SwipeViewRenderer))]
internal class _SwipeViewRenderer { }

#if !TIZEN4_0
[RenderWith(typeof(PathRenderer))]
internal class _PathRenderer { }

Expand All @@ -207,7 +206,6 @@ internal class _PolygonRenderer { }

[RenderWith(typeof(RectangleRenderer))]
internal class _RectangleRenderer { }
#endif
}


Expand Down
37 changes: 24 additions & 13 deletions Xamarin.Forms.Platform.Tizen/Extensions/BrushExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,26 +52,37 @@ public static SKPaint GetBackgroundPaint(this VisualElement element, SKRectI bou
Style = SKPaintStyle.Fill
};

SKShader backgroundShader = null;
if (brush is GradientBrush fillGradientBrush)
{
if (fillGradientBrush is LinearGradientBrush linearGradientBrush)
backgroundShader = CreateLinearGradient(linearGradientBrush, bounds);
paint.Shader = fillGradientBrush.CreateShader(bounds);
}
else if (brush is SolidColorBrush solidColorBrush)
{
paint.Color = solidColorBrush.ToSolidColor();
}
return paint;
}

if (fillGradientBrush is RadialGradientBrush radialGradientBrush)
backgroundShader = CreateRadialGradient(radialGradientBrush, bounds);
public static SKShader CreateShader(this GradientBrush gradientBrush, SKRect bounds)
{
SKShader shader = null;

paint.Shader = backgroundShader;
}
else
if (gradientBrush is LinearGradientBrush linearGradientBrush)
{
SKColor fillColor = Color.Default.ToNative().ToSKColor();
if (brush is SolidColorBrush solidColorBrush && solidColorBrush.Color != Color.Default)
fillColor = solidColorBrush.Color.ToNative().ToSKColor();
shader = CreateLinearGradient(linearGradientBrush, bounds);
}

paint.Color = fillColor;
if (gradientBrush is RadialGradientBrush radialGradientBrush)
{
shader = CreateRadialGradient(radialGradientBrush, bounds);
}
return paint;

return shader;
}

public static SKColor ToSolidColor(this SolidColorBrush solidColorBrush)
{
return solidColorBrush.Color != Color.Default ? solidColorBrush.Color.ToNative().ToSKColor() : SKColor.Empty;
}

static SKShader CreateLinearGradient(LinearGradientBrush linearGradientBrush, SKRect pathBounds)
Expand Down
205 changes: 205 additions & 0 deletions Xamarin.Forms.Platform.Tizen/Extensions/GeometryExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
using System.Collections.Generic;
using Xamarin.Forms.Shapes;
using SkiaSharp;
using FormsRectangle = Xamarin.Forms.Rectangle;

namespace Xamarin.Forms.Platform.Tizen
{
public static class GeometryExtensions
{
public static SKPath ToSKPath(this Geometry geometry)
{
return MakePath((dynamic)geometry);
}

static SKPath MakePath(Geometry geometry)
{
return new SKPath();
}

static SKPath MakePath(LineGeometry lineGeometry)
{
var path = new SKPath();
path.MoveTo(
Forms.ConvertToScaledPixel(lineGeometry.StartPoint.X),
Forms.ConvertToScaledPixel(lineGeometry.StartPoint.Y));

path.LineTo(
Forms.ConvertToScaledPixel(lineGeometry.EndPoint.X),
Forms.ConvertToScaledPixel(lineGeometry.EndPoint.Y));

return path;
}

static SKPath MakePath(RectangleGeometry rectangleGeometry)
{
var path = new SKPath();
FormsRectangle rect = rectangleGeometry.Rect;

path.AddRect(new SKRect(
Forms.ConvertToScaledPixel(rect.Left),
Forms.ConvertToScaledPixel(rect.Top),
Forms.ConvertToScaledPixel(rect.Right),
Forms.ConvertToScaledPixel(rect.Bottom)),
SKPathDirection.Clockwise);

return path;
}

static SKPath MakePath(EllipseGeometry ellipseGeometry)
{
var path = new SKPath();
path.AddOval(new SKRect(
Forms.ConvertToScaledPixel(ellipseGeometry.Center.X - ellipseGeometry.RadiusX),
Forms.ConvertToScaledPixel(ellipseGeometry.Center.Y - ellipseGeometry.RadiusY),
Forms.ConvertToScaledPixel(ellipseGeometry.Center.X + ellipseGeometry.RadiusX),
Forms.ConvertToScaledPixel(ellipseGeometry.Center.Y + ellipseGeometry.RadiusY)),
SKPathDirection.Clockwise);

return path;
}

static SKPath MakePath(GeometryGroup geometryGroup)
{
var path = new SKPath();
path.FillType = geometryGroup.FillRule == FillRule.Nonzero ? SKPathFillType.Winding : SKPathFillType.EvenOdd;

foreach (Geometry child in geometryGroup.Children)
{
SKPath childPath = MakePath((dynamic)child);
path.AddPath(childPath);
}

return path;
}

static SKPath MakePath(PathGeometry pathGeometry)
{
var path = new SKPath();
path.FillType = pathGeometry.FillRule == FillRule.Nonzero ? SKPathFillType.Winding : SKPathFillType.EvenOdd;

foreach (PathFigure pathFigure in pathGeometry.Figures)
{
path.MoveTo(
Forms.ConvertToScaledPixel(pathFigure.StartPoint.X),
Forms.ConvertToScaledPixel(pathFigure.StartPoint.Y));

Point lastPoint = pathFigure.StartPoint;

foreach (PathSegment pathSegment in pathFigure.Segments)
{
// LineSegment
if (pathSegment is LineSegment)
{
LineSegment lineSegment = pathSegment as LineSegment;

path.LineTo(
Forms.ConvertToScaledPixel(lineSegment.Point.X),
Forms.ConvertToScaledPixel(lineSegment.Point.Y));
lastPoint = lineSegment.Point;
}
// PolylineSegment
else if (pathSegment is PolyLineSegment)
{
PolyLineSegment polylineSegment = pathSegment as PolyLineSegment;
PointCollection points = polylineSegment.Points;

for (int i = 0; i < points.Count; i++)
{
path.LineTo(
Forms.ConvertToScaledPixel(points[i].X),
Forms.ConvertToScaledPixel(points[i].Y));
}
lastPoint = points[points.Count - 1];
}
// BezierSegment
else if (pathSegment is BezierSegment)
{
BezierSegment bezierSegment = pathSegment as BezierSegment;

path.CubicTo(
Forms.ConvertToScaledPixel(bezierSegment.Point1.X), Forms.ConvertToScaledPixel(bezierSegment.Point1.Y),
Forms.ConvertToScaledPixel(bezierSegment.Point2.X), Forms.ConvertToScaledPixel(bezierSegment.Point2.Y),
Forms.ConvertToScaledPixel(bezierSegment.Point3.X), Forms.ConvertToScaledPixel(bezierSegment.Point3.Y));

lastPoint = bezierSegment.Point3;
}
// PolyBezierSegment
else if (pathSegment is PolyBezierSegment)
{
PolyBezierSegment polyBezierSegment = pathSegment as PolyBezierSegment;
PointCollection points = polyBezierSegment.Points;

for (int i = 0; i < points.Count; i += 3)
{
path.CubicTo(
Forms.ConvertToScaledPixel(points[i + 0].X), Forms.ConvertToScaledPixel(points[i + 0].Y),
Forms.ConvertToScaledPixel(points[i + 1].X), Forms.ConvertToScaledPixel(points[i + 1].Y),
Forms.ConvertToScaledPixel(points[i + 2].X), Forms.ConvertToScaledPixel(points[i + 2].Y));
}

lastPoint = points[points.Count - 1];
}
// QuadraticBezierSegment
else if (pathSegment is QuadraticBezierSegment)
{
QuadraticBezierSegment bezierSegment = pathSegment as QuadraticBezierSegment;

path.QuadTo(
Forms.ConvertToScaledPixel(bezierSegment.Point1.X), Forms.ConvertToScaledPixel(bezierSegment.Point1.Y),
Forms.ConvertToScaledPixel(bezierSegment.Point2.X), Forms.ConvertToScaledPixel(bezierSegment.Point2.Y));

lastPoint = bezierSegment.Point2;
}
// PolyQuadraticBezierSegment
else if (pathSegment is PolyQuadraticBezierSegment)
{
PolyQuadraticBezierSegment polyBezierSegment = pathSegment as PolyQuadraticBezierSegment;
PointCollection points = polyBezierSegment.Points;

for (int i = 0; i < points.Count; i += 2)
{
path.QuadTo(
Forms.ConvertToScaledPixel(points[i + 0].X), Forms.ConvertToScaledPixel(points[i + 0].Y),
Forms.ConvertToScaledPixel(points[i + 1].X), Forms.ConvertToScaledPixel(points[i + 1].Y));
}

lastPoint = points[points.Count - 1];
}
// ArcSegment
else if (pathSegment is ArcSegment)
{
ArcSegment arcSegment = pathSegment as ArcSegment;

List<Point> points = new List<Point>();

GeometryHelper.FlattenArc(points,
lastPoint,
arcSegment.Point,
arcSegment.Size.Width,
arcSegment.Size.Height,
arcSegment.RotationAngle,
arcSegment.IsLargeArc,
arcSegment.SweepDirection == SweepDirection.CounterClockwise,
1);

for (int i = 0; i < points.Count; i++)
{
path.LineTo(
Forms.ConvertToScaledPixel(points[i].X),
Forms.ConvertToScaledPixel(points[i].Y));
}

if (points.Count > 0)
lastPoint = points[points.Count - 1];
}
}

if (pathFigure.IsClosed)
path.Close();
}

return path;
}
}
}
31 changes: 31 additions & 0 deletions Xamarin.Forms.Platform.Tizen/Extensions/TransformExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using SkiaSharp;
using Xamarin.Forms.Shapes;

namespace Xamarin.Forms.Platform.Tizen
{
public static class TransformExtensions
{
public static SKMatrix ToSkia(this Transform transform)
{
SKMatrix skMatrix = SKMatrix.CreateIdentity();

if (transform == null)
return skMatrix;

Matrix matrix = transform.Value;

skMatrix.Values = new float[] {
(float)matrix.M11,
(float)matrix.M21,
Forms.ConvertToScaledPixel(matrix.OffsetX),
(float)matrix.M12,
(float)matrix.M22,
Forms.ConvertToScaledPixel(matrix.OffsetY),
0,
0,
1 };

return skMatrix;
}
}
}
8 changes: 8 additions & 0 deletions Xamarin.Forms.Platform.Tizen/Forms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using ElmSharp;
using ElmSharp.Wearable;
using Tizen.Applications;
using Xamarin.Forms.Shapes;
using Xamarin.Forms.Internals;
using Xamarin.Forms.Platform.Tizen;
using DeviceOrientation = Xamarin.Forms.Internals.DeviceOrientation;
Expand Down Expand Up @@ -581,6 +582,13 @@ static void RegisterSkiaSharpRenderers()
Registrar.Registered.Register(typeof(Frame), typeof(Platform.Tizen.SkiaSharp.FrameRenderer));
Registrar.Registered.Register(typeof(BoxView), typeof(Platform.Tizen.SkiaSharp.BoxViewRenderer));
Registrar.Registered.Register(typeof(Image), typeof(Platform.Tizen.SkiaSharp.ImageRenderer));

Registrar.Registered.Register(typeof(Ellipse), typeof(Platform.Tizen.SkiaSharp.EllipseRenderer));
Registrar.Registered.Register(typeof(Line), typeof(Platform.Tizen.SkiaSharp.LineRenderer));
Registrar.Registered.Register(typeof(Path), typeof(Platform.Tizen.SkiaSharp.PathRenderer));
Registrar.Registered.Register(typeof(Shapes.Polygon), typeof(Platform.Tizen.SkiaSharp.PolygonRenderer));
Registrar.Registered.Register(typeof(Polyline), typeof(Platform.Tizen.SkiaSharp.PolylineRenderer));
Registrar.Registered.Register(typeof(Shapes.Rectangle), typeof(Platform.Tizen.SkiaSharp.RectangleRenderer));
}

static Color GetAccentColor(string profile)
Expand Down
10 changes: 9 additions & 1 deletion Xamarin.Forms.Platform.Tizen/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Xamarin.Forms;
using Xamarin.Forms.Platform.Tizen;
using Xamarin.Forms.Shapes;

[assembly: Dependency(typeof(ResourcesProvider))]
[assembly: Dependency(typeof(Deserializer))]
Expand Down Expand Up @@ -65,4 +66,11 @@
[assembly: ExportHandler(typeof(PanGestureRecognizer), typeof(PanGestureHandler))]
[assembly: ExportHandler(typeof(SwipeGestureRecognizer), typeof(SwipeGestureHandler))]

[assembly: ExportRenderer(typeof(Shell), typeof(Xamarin.Forms.Platform.Tizen.Watch.ShellRenderer), TargetIdiom.Watch)]
[assembly: ExportRenderer(typeof(Shell), typeof(Xamarin.Forms.Platform.Tizen.Watch.ShellRenderer), TargetIdiom.Watch)]

[assembly: ExportRenderer(typeof(Ellipse), typeof(EllipseRenderer))]
[assembly: ExportRenderer(typeof(Line), typeof(LineRenderer))]
[assembly: ExportRenderer(typeof(Path), typeof(PathRenderer))]
[assembly: ExportRenderer(typeof(Polygon), typeof(PolygonRenderer))]
[assembly: ExportRenderer(typeof(Polyline), typeof(PolylineRenderer))]
[assembly: ExportRenderer(typeof(Xamarin.Forms.Shapes.Rectangle), typeof(RectangleRenderer))]
29 changes: 28 additions & 1 deletion Xamarin.Forms.Platform.Tizen/Renderers/DefaultRenderer.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Xamarin.Forms.Shapes;
using ElmSharp;
using ELayout = ElmSharp.Layout;

Expand All @@ -15,4 +16,30 @@ protected override void OnElementChanged(ElementChangedEventArgs<VisualElement>
base.OnElementChanged(e);
}
}
}

public class EllipseRenderer : ShapeRenderer { }

public class LineRenderer : ShapeRenderer { }

public class PathRenderer : ShapeRenderer { }

public class PolygonRenderer : ShapeRenderer { }

public class PolylineRenderer : ShapeRenderer { }

public class RectangleRenderer : ShapeRenderer { }

public class ShapeRenderer : VisualElementRenderer<VisualElement>
{
protected override void OnElementChanged(ElementChangedEventArgs<VisualElement> e)
{
Log.Info("Use skia render mode (InitializationOptions.UseSkiaSharp=true) to use Shape.");
if (NativeView == null)
{
var control = new ELayout(Forms.NativeParent);
SetNativeView(control);
}
base.OnElementChanged(e);
}
}
}
Loading