-
Notifications
You must be signed in to change notification settings - Fork 742
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Added CompositionRadialGradientBrush implementation
- Loading branch information
1 parent
ab93de0
commit 031eae3
Showing
3 changed files
with
174 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
src/Uno.UWP/UI/Composition/CompositionRadialGradientBrush.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#nullable enable | ||
|
||
using System.Numerics; | ||
|
||
namespace Windows.UI.Composition | ||
{ | ||
public partial class CompositionRadialGradientBrush : CompositionGradientBrush | ||
{ | ||
private Vector2 _gradientOriginOffset = Vector2.Zero; | ||
private Vector2 _ellipseRadius = new Vector2(0.5f, 0.5f); | ||
private Vector2 _ellipseCenter = new Vector2(0.5f, 0.5f); | ||
|
||
internal CompositionRadialGradientBrush(Compositor compositor) | ||
: base(compositor) | ||
{ | ||
|
||
} | ||
|
||
public Vector2 GradientOriginOffset | ||
{ | ||
get => _gradientOriginOffset; | ||
set => SetProperty(ref _gradientOriginOffset, value); | ||
} | ||
|
||
public Vector2 EllipseRadius | ||
{ | ||
get => _ellipseRadius; | ||
set => SetProperty(ref _ellipseRadius, value); | ||
} | ||
|
||
public Vector2 EllipseCenter | ||
{ | ||
get => _ellipseCenter; | ||
set => SetProperty(ref _ellipseCenter, value); | ||
} | ||
} | ||
} |
133 changes: 133 additions & 0 deletions
133
src/Uno.UWP/UI/Composition/CompositionRadialGradientBrush.skia.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
#nullable enable | ||
|
||
using SkiaSharp; | ||
|
||
namespace Windows.UI.Composition | ||
{ | ||
public partial class CompositionRadialGradientBrush : CompositionGradientBrush | ||
{ | ||
private protected override void UpdatePaintCore(SKPaint paint, SKRect bounds) | ||
{ | ||
var center = EllipseCenter.ToSKPoint(); | ||
var gradientOrigin = EllipseCenter.ToSKPoint() + GradientOriginOffset.ToSKPoint(); | ||
var radius = EllipseRadius.ToSKPoint(); | ||
var transform = CreateTransformMatrix(bounds); | ||
|
||
// Transform the points into absolute coordinates. | ||
if (MappingMode == CompositionMappingMode.Relative) | ||
{ | ||
// If the point are provided relative they must be multiplied by bounds. | ||
center.X *= bounds.Width; | ||
center.Y *= bounds.Height; | ||
|
||
gradientOrigin.X *= bounds.Width; | ||
gradientOrigin.Y *= bounds.Height; | ||
|
||
radius.X *= bounds.Width; | ||
radius.Y *= bounds.Height; | ||
} | ||
|
||
// Translate gradient points by bounds offset. | ||
center.X += bounds.Left; | ||
center.Y += bounds.Top; | ||
|
||
gradientOrigin.X += bounds.Left; | ||
gradientOrigin.Y += bounds.Top; | ||
// | ||
|
||
// SkiaSharp does not allow explicit definition of RadiusX and RadiusY. | ||
// Compute transformation matrix to compensate. | ||
ComputeRadiusAndScale(center, radius.X, radius.Y, out float gradientRadius, out SKMatrix matrix); | ||
|
||
// Clean up old shader | ||
if (paint.Shader != null) | ||
{ | ||
paint.Shader.Dispose(); | ||
paint.Shader = null; | ||
} | ||
|
||
if (gradientRadius > 0) | ||
{ | ||
// Create radial gradient shader. | ||
SKShader shader = | ||
SKShader.CreateTwoPointConicalGradient( | ||
/* start */ gradientOrigin, /* start radius */ 0, | ||
/* end */ center, /* gradient radius */ gradientRadius, | ||
Colors, ColorPositions, | ||
TileMode, transform.PreConcat(matrix)); | ||
|
||
paint.Shader = shader; | ||
} | ||
else | ||
{ | ||
// With radius equal to 0, SkiaSharp does not draw anything. | ||
// But we expect last gradient color. | ||
|
||
// If there are no gradient stops available, use transparent. | ||
SKColor color = SKColors.Transparent; | ||
if (Colors!.Length > 0) | ||
{ | ||
color = Colors[Colors.Length - 1]; | ||
} | ||
|
||
paint.Color = color; | ||
} | ||
} | ||
|
||
private void ComputeRadiusAndScale(SKPoint center, float radiusX, float radiusY, out float radius, out SKMatrix matrix) | ||
{ | ||
matrix = SKMatrix.Identity; | ||
if (radiusX == 0 || radiusY == 0) | ||
{ | ||
// Handle this specific case as zero division would cause us troubles. | ||
radius = 0; | ||
return; | ||
} | ||
|
||
float scaleDownRatio; | ||
if (radiusX >= radiusY) | ||
{ | ||
// radiusX is larger, use it and scale down radiusY. | ||
radius = radiusX; | ||
|
||
scaleDownRatio = radiusY / radiusX; | ||
|
||
SetScaleTranslate( | ||
ref matrix, | ||
/* scale x */ 1, | ||
/* scale y */ scaleDownRatio, | ||
/* translate x */ 0, | ||
/* translate y */ center.Y - scaleDownRatio * center.Y); | ||
} | ||
else | ||
{ | ||
// radiusY is larger, use it and scale down radiusX. | ||
radius = radiusY; | ||
|
||
scaleDownRatio = radiusX / radiusY; | ||
|
||
SetScaleTranslate( | ||
ref matrix, | ||
/* scale x */ scaleDownRatio, | ||
/* scale y */ 1, | ||
/* translate x */ center.X - scaleDownRatio * center.X, | ||
/* translate y */ 0); | ||
} | ||
} | ||
|
||
private void SetScaleTranslate(ref SKMatrix matrix, float sx, float sy, float tx, float ty) | ||
{ | ||
matrix.ScaleX = sx; | ||
matrix.SkewX = 0; | ||
matrix.TransX = tx; | ||
|
||
matrix.SkewY = 0; | ||
matrix.ScaleY = sy; | ||
matrix.TransY = ty; | ||
|
||
matrix.Persp0 = 0; | ||
matrix.Persp1 = 0; | ||
matrix.Persp2 = 1; | ||
} | ||
} | ||
} |