Browse Source

Make RadialGradientBrush work

With immediate renderer. Also added a render test and fixed some
problems with D2D implementation.
scenegraph-after-breakage
Steven Kirk 9 years ago
parent
commit
e4eaf729a9
  1. 2
      src/Avalonia.Visuals/Avalonia.Visuals.csproj
  2. 23
      src/Avalonia.Visuals/Media/IRadialGradientBrush.cs
  3. 4
      src/Avalonia.Visuals/Media/Immutable/ImmutableLinearGradientBrush.cs
  4. 59
      src/Avalonia.Visuals/Media/Immutable/ImmutableRadialGradientBrush.cs
  5. 14
      src/Avalonia.Visuals/Media/RadialGradientBrush.cs
  6. 2
      src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
  7. 10
      src/Windows/Avalonia.Direct2D1/Media/RadialGradientBrushImpl.cs
  8. 3
      tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.v3.ncrunchproject
  9. 1
      tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems
  10. 56
      tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs
  11. BIN
      tests/TestFiles/Direct2D1/Media/RadialGradientBrush/RadialGradientBrush_RedBlue.expected.png

2
src/Avalonia.Visuals/Avalonia.Visuals.csproj

@ -73,10 +73,12 @@
<Compile Include="Media\IImageBrush.cs" /> <Compile Include="Media\IImageBrush.cs" />
<Compile Include="Media\ILinearGradientBrush.cs" /> <Compile Include="Media\ILinearGradientBrush.cs" />
<Compile Include="Media\Immutable\ImmutableGradientBrush.cs" /> <Compile Include="Media\Immutable\ImmutableGradientBrush.cs" />
<Compile Include="Media\Immutable\ImmutableRadialGradientBrush.cs" />
<Compile Include="Media\Immutable\ImmutableLinearGradientBrush.cs" /> <Compile Include="Media\Immutable\ImmutableLinearGradientBrush.cs" />
<Compile Include="Media\Immutable\ImmutableTileBrush.cs" /> <Compile Include="Media\Immutable\ImmutableTileBrush.cs" />
<Compile Include="Media\Immutable\ImmutableSolidColorBrush.cs" /> <Compile Include="Media\Immutable\ImmutableSolidColorBrush.cs" />
<Compile Include="Media\IMutableBrush.cs" /> <Compile Include="Media\IMutableBrush.cs" />
<Compile Include="Media\IRadialGradientBrush.cs" />
<Compile Include="Media\ITileBrush.cs" /> <Compile Include="Media\ITileBrush.cs" />
<Compile Include="Media\IVisualBrush.cs" /> <Compile Include="Media\IVisualBrush.cs" />
<Compile Include="Media\TextWrapping.cs" /> <Compile Include="Media\TextWrapping.cs" />

23
src/Avalonia.Visuals/Media/IRadialGradientBrush.cs

@ -0,0 +1,23 @@
namespace Avalonia.Media
{
/// <summary>
/// Paints an area with a radial gradient.
/// </summary>
public interface IRadialGradientBrush : IGradientBrush
{
/// <summary>
/// Gets the start point for the gradient.
/// </summary>
RelativePoint Center { get; }
/// <summary>
/// Gets the location of the two-dimensional focal point that defines the beginning of the gradient.
/// </summary>
RelativePoint GradientOrigin { get; }
/// <summary>
/// Gets the horizontal and vertical radius of the outermost circle of the radial gradient.
/// </summary>
double Radius { get; }
}
}

4
src/Avalonia.Visuals/Media/Immutable/ImmutableLinearGradientBrush.cs

@ -12,7 +12,7 @@ namespace Avalonia.Media.Immutable
public class ImmutableLinearGradientBrush : ImmutableGradientBrush, ILinearGradientBrush public class ImmutableLinearGradientBrush : ImmutableGradientBrush, ILinearGradientBrush
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ImmutableGradientBrush"/> class. /// Initializes a new instance of the <see cref="ImmutableLinearGradientBrush"/> class.
/// </summary> /// </summary>
/// <param name="gradientStops">The gradient stops.</param> /// <param name="gradientStops">The gradient stops.</param>
/// <param name="opacity">The opacity of the brush.</param> /// <param name="opacity">The opacity of the brush.</param>
@ -32,7 +32,7 @@ namespace Avalonia.Media.Immutable
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ImmutableGradientBrush"/> class. /// Initializes a new instance of the <see cref="ImmutableLinearGradientBrush"/> class.
/// </summary> /// </summary>
/// <param name="source">The brush from which this brush's properties should be copied.</param> /// <param name="source">The brush from which this brush's properties should be copied.</param>
public ImmutableLinearGradientBrush(ILinearGradientBrush source) public ImmutableLinearGradientBrush(ILinearGradientBrush source)

59
src/Avalonia.Visuals/Media/Immutable/ImmutableRadialGradientBrush.cs

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
namespace Avalonia.Media.Immutable
{
/// <summary>
/// A brush that draws with a radial gradient.
/// </summary>
public class ImmutableRadialGradientBrush : ImmutableGradientBrush, IRadialGradientBrush
{
/// <summary>
/// Initializes a new instance of the <see cref="ImmutableRadialGradientBrush"/> class.
/// </summary>
/// <param name="gradientStops">The gradient stops.</param>
/// <param name="opacity">The opacity of the brush.</param>
/// <param name="spreadMethod">The spread method.</param>
/// <param name="center">The start point for the gradient.</param>
/// <param name="gradientOrigin">
/// The location of the two-dimensional focal point that defines the beginning of the gradient.
/// </param>
/// <param name="radius">
/// The horizontal and vertical radius of the outermost circle of the radial gradient.
/// </param>
public ImmutableRadialGradientBrush(
IReadOnlyList<GradientStop> gradientStops,
double opacity = 1,
GradientSpreadMethod spreadMethod = GradientSpreadMethod.Pad,
RelativePoint? center = null,
RelativePoint? gradientOrigin = null,
double radius = 0.5)
: base(gradientStops, opacity, spreadMethod)
{
Center = center ?? RelativePoint.Center;
GradientOrigin = gradientOrigin ?? RelativePoint.Center;
Radius = radius;
}
/// <summary>
/// Initializes a new instance of the <see cref="ImmutableRadialGradientBrush"/> class.
/// </summary>
/// <param name="source">The brush from which this brush's properties should be copied.</param>
public ImmutableRadialGradientBrush(IRadialGradientBrush source)
: base(source)
{
Center = source.Center;
GradientOrigin = source.GradientOrigin;
Radius = source.Radius;
}
/// <inheritdoc/>
public RelativePoint Center { get; }
/// <inheritdoc/>
public RelativePoint GradientOrigin { get; }
/// <inheritdoc/>
public double Radius { get; }
}
}

14
src/Avalonia.Visuals/Media/RadialGradientBrush.cs

@ -1,13 +1,14 @@
// Copyright (c) The Avalonia Project. All rights reserved. // Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Media namespace Avalonia.Media
{ {
/// <summary> /// <summary>
/// Paints an area with a radial gradient. A focal point defines the beginning of the gradient, /// Paints an area with a radial gradient.
/// and a circle defines the end point of the gradient.
/// </summary> /// </summary>
public sealed class RadialGradientBrush : GradientBrush public sealed class RadialGradientBrush : GradientBrush, IRadialGradientBrush, IMutableBrush
{ {
/// <summary> /// <summary>
/// Defines the <see cref="Center"/> property. /// Defines the <see cref="Center"/> property.
@ -54,10 +55,17 @@ namespace Avalonia.Media
/// <summary> /// <summary>
/// Gets or sets the horizontal and vertical radius of the outermost circle of the radial gradient. /// Gets or sets the horizontal and vertical radius of the outermost circle of the radial gradient.
/// </summary> /// </summary>
// TODO: This appears to always be relative so should use a RelativeSize struct or something.
public double Radius public double Radius
{ {
get { return GetValue(RadiusProperty); } get { return GetValue(RadiusProperty); }
set { SetValue(RadiusProperty, value); } set { SetValue(RadiusProperty, value); }
} }
/// <inheritdoc/>
IBrush IMutableBrush.ToImmutable()
{
return new Immutable.ImmutableRadialGradientBrush(this);
}
} }
} }

2
src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

@ -320,7 +320,7 @@ namespace Avalonia.Direct2D1.Media
{ {
var solidColorBrush = brush as Avalonia.Media.ISolidColorBrush; var solidColorBrush = brush as Avalonia.Media.ISolidColorBrush;
var linearGradientBrush = brush as Avalonia.Media.ILinearGradientBrush; var linearGradientBrush = brush as Avalonia.Media.ILinearGradientBrush;
var radialGradientBrush = brush as Avalonia.Media.RadialGradientBrush; var radialGradientBrush = brush as Avalonia.Media.IRadialGradientBrush;
var imageBrush = brush as Avalonia.Media.IImageBrush; var imageBrush = brush as Avalonia.Media.IImageBrush;
var visualBrush = brush as Avalonia.Media.IVisualBrush; var visualBrush = brush as Avalonia.Media.IVisualBrush;

10
src/Windows/Avalonia.Direct2D1/Media/RadialGradientBrushImpl.cs

@ -8,7 +8,7 @@ namespace Avalonia.Direct2D1.Media
public class RadialGradientBrushImpl : BrushImpl public class RadialGradientBrushImpl : BrushImpl
{ {
public RadialGradientBrushImpl( public RadialGradientBrushImpl(
Avalonia.Media.RadialGradientBrush brush, Avalonia.Media.IRadialGradientBrush brush,
SharpDX.Direct2D1.RenderTarget target, SharpDX.Direct2D1.RenderTarget target,
Size destinationSize) Size destinationSize)
{ {
@ -24,11 +24,11 @@ namespace Avalonia.Direct2D1.Media
}).ToArray(); }).ToArray();
var centerPoint = brush.Center.ToPixels(destinationSize); var centerPoint = brush.Center.ToPixels(destinationSize);
var GradientOriginOffset = brush.GradientOrigin.ToPixels(destinationSize); var gradientOrigin = brush.GradientOrigin.ToPixels(destinationSize) - centerPoint;
// Note: Direct2D supports RadiusX and RadiusY but Cairo backend supports only Radius property // Note: Direct2D supports RadiusX and RadiusY but Cairo backend supports only Radius property
var radiusX = brush.Radius; var radiusX = brush.Radius * destinationSize.Width;
var radiusY = brush.Radius; var radiusY = brush.Radius * destinationSize.Height;
using (var stops = new SharpDX.Direct2D1.GradientStopCollection( using (var stops = new SharpDX.Direct2D1.GradientStopCollection(
target, target,
@ -40,7 +40,7 @@ namespace Avalonia.Direct2D1.Media
new SharpDX.Direct2D1.RadialGradientBrushProperties new SharpDX.Direct2D1.RadialGradientBrushProperties
{ {
Center = centerPoint.ToSharpDX(), Center = centerPoint.ToSharpDX(),
GradientOriginOffset = GradientOriginOffset.ToSharpDX(), GradientOriginOffset = gradientOrigin.ToSharpDX(),
RadiusX = (float)radiusX, RadiusX = (float)radiusX,
RadiusY = (float)radiusY RadiusY = (float)radiusY
}, },

3
tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.v3.ncrunchproject

@ -70,6 +70,9 @@
<NamedTestSelector> <NamedTestSelector>
<TestName>Avalonia.Cairo.RenderTests.Media.LinearGradientBrushTests.LinearGradientBrush_RedBlue_Horizontal_Fill</TestName> <TestName>Avalonia.Cairo.RenderTests.Media.LinearGradientBrushTests.LinearGradientBrush_RedBlue_Horizontal_Fill</TestName>
</NamedTestSelector> </NamedTestSelector>
<NamedTestSelector>
<TestName>Avalonia.Cairo.RenderTests.Media.RadialGradientBrushTests.RadialGradientBrush_RedBlue</TestName>
</NamedTestSelector>
</IgnoredTests> </IgnoredTests>
<PreviouslyBuiltSuccessfully>True</PreviouslyBuiltSuccessfully> <PreviouslyBuiltSuccessfully>True</PreviouslyBuiltSuccessfully>
</Settings> </Settings>

1
tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems

@ -10,6 +10,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)GeometryClippingTests.cs" /> <Compile Include="$(MSBuildThisFileDirectory)GeometryClippingTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\RadialGradientBrushTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)OpacityMaskTests.cs" /> <Compile Include="$(MSBuildThisFileDirectory)OpacityMaskTests.cs" />
<Compile Include="Media\FormattedTextImplTests.cs" /> <Compile Include="Media\FormattedTextImplTests.cs" />
<Compile Include="Controls\ImageTests.cs" /> <Compile Include="Controls\ImageTests.cs" />

56
tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs

@ -0,0 +1,56 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Controls;
using Avalonia.Media;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
#if AVALONIA_CAIRO
namespace Avalonia.Cairo.RenderTests.Media
#elif AVALONIA_SKIA
namespace Avalonia.Skia.RenderTests
#else
namespace Avalonia.Direct2D1.RenderTests.Media
#endif
{
public class RadialGradientBrushTests : TestBase
{
public RadialGradientBrushTests() : base(@"Media\RadialGradientBrush")
{
}
#if AVALONIA_SKIA_SKIP_FAIL
[Fact(Skip = "FIXME")]
#else
[Fact]
#endif
public async Task RadialGradientBrush_RedBlue()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 200,
Height = 200,
Child = new Border
{
Background = new RadialGradientBrush
{
GradientStops =
{
new GradientStop { Color = Colors.Red, Offset = 0 },
new GradientStop { Color = Colors.Blue, Offset = 1 }
}
}
}
};
await RenderToFile(target);
CompareImages();
}
}
}

BIN
tests/TestFiles/Direct2D1/Media/RadialGradientBrush/RadialGradientBrush_RedBlue.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Loading…
Cancel
Save