Skip to content

Commit

Permalink
feat(gradient): Added Radial Gradient for Android
Browse files Browse the repository at this point in the history
  • Loading branch information
carldebilly committed May 7, 2020
1 parent 92aa150 commit 171f9e4
Show file tree
Hide file tree
Showing 8 changed files with 292 additions and 216 deletions.

Large diffs are not rendered by default.

18 changes: 6 additions & 12 deletions src/Uno.UI/UI/Xaml/Controls/Border/BorderLayerRenderer.iOSmacOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,10 @@ private static IDisposable InnerCreateLayer(UIElement owner, CALayer parent, Lay

var outerPath = GetRoundedPath(cornerRadius, area);

var lgbBackground = background as LinearGradientBrush;
var scbBackground = background as SolidColorBrush;
var imgBackground = background as ImageBrush;
var insertionIndex = 0;

if (lgbBackground != null)
if (background is LinearGradientBrush lgbBackground)
{
var fillMask = new CAShapeLayer()
{
Expand All @@ -134,12 +132,12 @@ private static IDisposable InnerCreateLayer(UIElement owner, CALayer parent, Lay

CreateLinearGradientBrushLayers(area, adjustedArea, parent, sublayers, ref insertionIndex, lgbBackground, fillMask);
}
else if (scbBackground != null)
else if (background is SolidColorBrush scbBackground)
{
Brush.AssignAndObserveBrush(scbBackground, color => layer.FillColor = color)
.DisposeWith(disposables);
}
else if (imgBackground != null)
else if (background is ImageBrush imgBackground)
{
var uiImage = imgBackground.ImageSource?.ImageData;
if (uiImage != null && uiImage.Size != CGSize.Empty)
Expand Down Expand Up @@ -184,11 +182,7 @@ private static IDisposable InnerCreateLayer(UIElement owner, CALayer parent, Lay
}
else
{
var lgbBackground = background as LinearGradientBrush;
var scbBackground = background as SolidColorBrush;
var imgBackground = background as ImageBrush;

if (lgbBackground != null)
if (background is LinearGradientBrush lgbBackground)
{
var fullArea = new CGRect(
area.X + borderThickness.Left,
Expand All @@ -201,7 +195,7 @@ private static IDisposable InnerCreateLayer(UIElement owner, CALayer parent, Lay

CreateLinearGradientBrushLayers(fullArea, insideArea, parent, sublayers, ref insertionIndex, lgbBackground, fillMask: null);
}
else if (scbBackground != null)
else if (background is SolidColorBrush scbBackground)
{
Brush.AssignAndObserveBrush(scbBackground, c => parent.BackgroundColor = c)
.DisposeWith(disposables);
Expand All @@ -211,7 +205,7 @@ private static IDisposable InnerCreateLayer(UIElement owner, CALayer parent, Lay
Disposable.Create(() => parent.BackgroundColor = null)
.DisposeWith(disposables);
}
else if (imgBackground != null)
else if (background is ImageBrush imgBackground)
{
var uiImage = imgBackground.ImageSource?.ImageData;
if (uiImage != null && uiImage.Size != CGSize.Empty)
Expand Down
9 changes: 8 additions & 1 deletion src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,20 @@ private void UpdatePaint()
return;
}

var foreground = Foreground switch
{
SolidColorBrush scb => scb.ColorWithOpacity,
GradientBrush gb => gb.FallbackColor,
_ => Colors.Transparent
};

_paint = TextPaintPool.GetPaint(
FontWeight,
FontStyle,
FontFamily,
FontSize,
CharacterSpacing,
(Foreground as SolidColorBrush)?.Color ?? Colors.Transparent,
foreground,
BaseLineAlignment.Baseline,
TextDecorations
);
Expand Down
14 changes: 9 additions & 5 deletions src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -364,17 +364,21 @@ private void OnTextTrimmingChanged()
#endif
Brush Foreground
{
get { return (Brush)this.GetValue(ForegroundProperty); }
get => (Brush)GetValue(ForegroundProperty);
set
{
#if !__WASM__
if (!(Foreground is SolidColorBrush))
if (Foreground is SolidColorBrush || Foreground is GradientBrush)
{
throw new NotSupportedException();
SetValue(ForegroundProperty, value);
}
#endif

else
{
throw new NotSupportedException("Only SolidColorBrush or GradientBrush's FallbackColor are supported.");
}
#else
this.SetValue(ForegroundProperty, value);
#endif
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UI/UI/Xaml/Media/GradientBrush.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public Color FallbackColor
public static readonly DependencyProperty GradientStopsProperty = DependencyProperty.Register(
"GradientStops",
typeof(GradientStopCollection),
typeof(LinearGradientBrush),
typeof(GradientBrush),
new PropertyMetadata(null)
);
public GradientStopCollection GradientStops
Expand Down
31 changes: 21 additions & 10 deletions src/Uno.UI/UI/Xaml/Media/LinearGradientBrush.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Android.Graphics;
using System.Linq;
using System.Drawing;
using Uno.Extensions;

namespace Windows.UI.Xaml.Media
{
Expand All @@ -17,24 +18,34 @@ protected override Paint GetPaintInner(Windows.Foundation.Rect destinationRect)
// Android LinearGradient requires two ore more stop points.
if (GradientStops.Count >= 2)
{
var colors = GradientStops.Select(s => ((Android.Graphics.Color)s.Color).ToArgb()).ToArray();
var locations = GradientStops.Select(s => (float)s.Offset).ToArray();
var colors = GradientStops.SelectToArray(s => ((Android.Graphics.Color)s.Color).ToArgb());
var locations = GradientStops.SelectToArray(s => (float)s.Offset);

var width = destinationRect.Width;
var height = destinationRect.Height;

var transform = RelativeTransform?.ToNative(size: new Windows.Foundation.Size(width, height), isBrush: true);
var transform =
RelativeTransform?.ToNative(size: new Windows.Foundation.Size(width, height), isBrush: true);

//Matrix .MapPoints takes an array of floats
var pts = new[] { StartPoint, EndPoint }
.Select(p => new float[] { (float)(p.X * width), (float)(p.Y * height) })
.SelectMany(p => p)
.ToArray();
var pts = MappingMode == BrushMappingMode.RelativeToBoundingBox
? new []
{
(float)(StartPoint.X * width),
(float)(StartPoint.Y * height),
(float)(EndPoint.X * width),
(float)(EndPoint.Y * height)
}
: new []
{
(float)StartPoint.X,
(float)StartPoint.Y,
(float)EndPoint.X,
(float)EndPoint.Y
};

transform?.MapPoints(pts);


var shader = new LinearGradient(pts[0], pts[1], pts[2], pts[3], colors, locations, Shader.TileMode.Mirror);
var shader = new LinearGradient(pts[0], pts[1], pts[2], pts[3], colors, locations, Shader.TileMode.Clamp);

paint.SetShader(shader);
}
Expand Down
61 changes: 61 additions & 0 deletions src/Uno.UI/UI/Xaml/Media/RadialGradientBrush.Android.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System.Linq;
using Android.Graphics;
using Uno.Extensions;
using Uno.UI;
using Point = Windows.Foundation.Point;

namespace Windows.UI.Xaml.Media
{
partial class RadialGradientBrush
{
protected override Paint GetPaintInner(Windows.Foundation.Rect destinationRect)
{
var paint = new Paint();

var center = Center;
var radiusX = RadiusX;
var radiusY = RadiusY;

float radius;

if (MappingMode == BrushMappingMode.RelativeToBoundingBox)
{
var size = destinationRect.Size;

center = new Point(center.X * size.Width, Center.Y * size.Height);
radius = (float)(radiusX * size.Width + radiusY * size.Height) / 4.0f; // We take the avg
}
else
{
center = center.LogicalToPhysicalPixels();
radius = ViewHelper.LogicalToPhysicalPixels((radiusX + radiusY) / 2.0d); // We take the avg
}


// Android RadialGradient requires two ore more stop points.
if (GradientStops.Count >= 2)
{
var colors = GradientStops.SelectToArray(s => ((Android.Graphics.Color)s.Color).ToArgb());
var locations = GradientStops.SelectToArray(s => (float)s.Offset);

var width = destinationRect.Width;
var height = destinationRect.Height;

var transform = RelativeTransform?.ToNative(size: new Windows.Foundation.Size(width, height), isBrush: true);

var shader = new RadialGradient(
(float)center.X,
(float)center.Y,
radius,
colors,
locations,
Shader.TileMode.Clamp);

paint.SetShader(shader);
}

return paint;
}

}
}
3 changes: 0 additions & 3 deletions src/Uno.UI/UI/Xaml/Media/RadialGradientBrush.wasm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,9 @@ partial class RadialGradientBrush
internal override string ToCssString(Size size)
{
var center = Center;

var radiusX = RadiusX;
var radiusY = RadiusY;

var ratio = size.AspectRatio();

if (MappingMode != BrushMappingMode.RelativeToBoundingBox)
{
center = new Point(center.X * size.Width, Center.Y * size.Height);
Expand Down

0 comments on commit 171f9e4

Please sign in to comment.