Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes relative brush mapping mode #14598

Merged
merged 17 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from 13 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
1 change: 1 addition & 0 deletions Avalonia.Desktop.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"samples\\IntegrationTestApp\\IntegrationTestApp.csproj",
"samples\\MiniMvvm\\MiniMvvm.csproj",
"samples\\ReactiveUIDemo\\ReactiveUIDemo.csproj",
"samples\\RenderDemo\\RenderDemo.csproj",
"samples\\SampleControls\\ControlSamples.csproj",
"samples\\Sandbox\\Sandbox.csproj",
"src\\Avalonia.Base\\Avalonia.Base.csproj",
Expand Down
12 changes: 12 additions & 0 deletions api/Avalonia.nupkg.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1075,4 +1075,16 @@
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>P:Avalonia.Media.IRadialGradientBrush.RadiusX</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>P:Avalonia.Media.IRadialGradientBrush.RadiusY</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
</Suppressions>
10 changes: 5 additions & 5 deletions samples/RenderDemo/Pages/AnimationsPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -267,39 +267,39 @@
PlaybackDirection="Normal">
<KeyFrame Cue="0%">
<Setter Property="Background">
<RadialGradientBrush Center="0%,100%" Radius="0.8">
<RadialGradientBrush Center="0%,100%" RadiusX="80%" RadiusY="80%">
<GradientStop Offset="0" Color="Red"/>
<GradientStop Offset="1" Color="Blue"/>
</RadialGradientBrush>
</Setter>
</KeyFrame>
<KeyFrame Cue="25%">
<Setter Property="Background">
<RadialGradientBrush Center="0%,0%" Radius="1">
<RadialGradientBrush Center="0%,0%" RadiusX="100%" RadiusY="100%">
<GradientStop Offset="0" Color="Red"/>
<GradientStop Offset="1" Color="Blue"/>
</RadialGradientBrush>
</Setter>
</KeyFrame>
<KeyFrame Cue="50%">
<Setter Property="Background">
<RadialGradientBrush Center="100%,0%" Radius="0.8">
<RadialGradientBrush Center="100%,0%" RadiusX="80%" RadiusY="80%">
<GradientStop Offset="0" Color="Red"/>
<GradientStop Offset="1" Color="Blue"/>
</RadialGradientBrush>
</Setter>
</KeyFrame>
<KeyFrame Cue="75%">
<Setter Property="Background">
<RadialGradientBrush Center="100%,100%" Radius="1">
<RadialGradientBrush Center="100%,100%" RadiusX="100%" RadiusY="100%">
<GradientStop Offset="0" Color="Red"/>
<GradientStop Offset="1" Color="Blue"/>
</RadialGradientBrush>
</Setter>
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="Background">
<RadialGradientBrush Center="0%,100%" Radius="0.8">
<RadialGradientBrush Center="0%,100%" RadiusX="80%" RadiusY="80%">
<GradientStop Offset="0" Color="Red"/>
<GradientStop Offset="1" Color="Blue"/>
</RadialGradientBrush>
Expand Down
2 changes: 1 addition & 1 deletion samples/RenderDemo/Pages/BrushesPage.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<TextBlock Canvas.Left="20" Canvas.Top="70" FontSize="30" Text="scale(0.5) on gradient" />
<Rectangle Canvas.Left="20" Canvas.Top="110" Width="440" Height="50">
<Rectangle.Fill>
<RadialGradientBrush Center="0.0,0.0" GradientOrigin="0.0,0.0" Radius="0.13636364">
<RadialGradientBrush Center="0.0,0.0" GradientOrigin="0.0,0.0" RadiusX="13%" RadiusY="13%">
<RadialGradientBrush.Transform>
<TransformGroup>
<ScaleTransform />
Expand Down
4 changes: 2 additions & 2 deletions samples/RenderDemo/Pages/TransitionsPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@
</Transitions>
</Setter>
<Setter Property="Background" >
<RadialGradientBrush Center="50%,50%" Radius="0.5">
<RadialGradientBrush Center="50%,50%" RadiusX="50%" RadiusY="50%">
<GradientStop Offset="0" Color="Red"/>
<GradientStop Offset="1" Color="Blue"/>
</RadialGradientBrush>
Expand All @@ -237,7 +237,7 @@

<Style Selector="Border.Rect14:pointerover">
<Setter Property="Background" >
<RadialGradientBrush Center="30%,30%" Radius="0.2">
<RadialGradientBrush Center="30%,30%" RadiusX="20%" RadiusY="20%">
<GradientStop Offset="0" Color="Green"/>
<GradientStop Offset="1" Color="Yellow"/>
</RadialGradientBrush>
Expand Down
1 change: 1 addition & 0 deletions src/Avalonia.Base/Animation/Animation.AnimatorRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ static Animation()
RegisterAnimator<Point, PointAnimator>();
RegisterAnimator<Rect, RectAnimator>();
RegisterAnimator<RelativePoint, RelativePointAnimator>();
RegisterAnimator<RelativeScalar, RelativeScalarAnimator>();
RegisterAnimator<Size, SizeAnimator>();
RegisterAnimator<Thickness, ThicknessAnimator>();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace Avalonia.Animation.Animators
internal class GradientBrushAnimator : Animator<IGradientBrush?>
{
private static readonly RelativePointAnimator s_relativePointAnimator = new RelativePointAnimator();
private static readonly RelativeScalarAnimator s_relativeScalarAnimator = new RelativeScalarAnimator();
private static readonly DoubleAnimator s_doubleAnimator = new DoubleAnimator();

public override IGradientBrush? Interpolate(double progress, IGradientBrush? oldValue, IGradientBrush? newValue)
Expand All @@ -36,7 +37,9 @@ internal class GradientBrushAnimator : Animator<IGradientBrush?>
oldValue.SpreadMethod,
s_relativePointAnimator.Interpolate(progress, oldRadial.Center, newRadial.Center),
s_relativePointAnimator.Interpolate(progress, oldRadial.GradientOrigin, newRadial.GradientOrigin),
s_doubleAnimator.Interpolate(progress, oldRadial.Radius, newRadial.Radius));
s_relativeScalarAnimator.Interpolate(progress, oldRadial.RadiusX, newRadial.RadiusX),
s_relativeScalarAnimator.Interpolate(progress, oldRadial.RadiusY, newRadial.RadiusY)
);

case IConicGradientBrush oldConic when newValue is IConicGradientBrush newConic:
return new ImmutableConicGradientBrush(
Expand Down
20 changes: 20 additions & 0 deletions src/Avalonia.Base/Animation/Animators/RelativeScalarAnimator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Avalonia.Animation.Animators
{
/// <summary>
/// Animator that handles <see cref="RelativeScalar"/> properties.
/// </summary>
internal class RelativeScalarAnimator : Animator<RelativeScalar>
{
private static readonly DoubleAnimator s_scalarAnimator = new DoubleAnimator();

public override RelativeScalar Interpolate(double progress, RelativeScalar oldValue, RelativeScalar newValue)
{
if (oldValue.Unit != newValue.Unit)
{
return progress >= 0.5 ? newValue : oldValue;
}

return new RelativeScalar(s_scalarAnimator.Interpolate(progress, oldValue.Scalar, newValue.Scalar), oldValue.Unit);
}
}
}
14 changes: 11 additions & 3 deletions src/Avalonia.Base/Media/IRadialGradientBrush.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Avalonia.Metadata;
using System;
using Avalonia.Metadata;

namespace Avalonia.Media
{
Expand All @@ -19,9 +20,16 @@ public interface IRadialGradientBrush : IGradientBrush
/// </summary>
RelativePoint GradientOrigin { get; }

[Obsolete("Use RadiusX/RadiusY")] public double Radius { get; }

/// <summary>
/// Gets the horizontal radius of the outermost circle of the radial gradient.
/// </summary>
RelativeScalar RadiusX { get; }

/// <summary>
/// Gets the horizontal and vertical radius of the outermost circle of the radial gradient.
/// Gets the vertical radius of the outermost circle of the radial gradient.
/// </summary>
double Radius { get; }
RelativeScalar RadiusY { get; }
}
}
37 changes: 33 additions & 4 deletions src/Avalonia.Base/Media/Immutable/ImmutableRadialGradientBrush.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;

namespace Avalonia.Media.Immutable
{
Expand Down Expand Up @@ -31,13 +32,35 @@ public ImmutableRadialGradientBrush(
RelativePoint? center = null,
RelativePoint? gradientOrigin = null,
double radius = 0.5)
: this(gradientStops, opacity, transform, transformOrigin, spreadMethod,
center, gradientOrigin,
new RelativeScalar(radius, RelativeUnit.Relative),
new RelativeScalar(radius, RelativeUnit.Relative)
)
{

}

public ImmutableRadialGradientBrush(
IReadOnlyList<ImmutableGradientStop> gradientStops,
double opacity = 1,
ImmutableTransform? transform = null,
RelativePoint? transformOrigin = null,
GradientSpreadMethod spreadMethod = GradientSpreadMethod.Pad,
RelativePoint? center = null,
RelativePoint? gradientOrigin = null,
RelativeScalar? radiusX = null,
RelativeScalar? radiusY = null
)
: base(gradientStops, opacity, transform, transformOrigin, spreadMethod)
{
Center = center ?? RelativePoint.Center;
GradientOrigin = gradientOrigin ?? RelativePoint.Center;
Radius = radius;
RadiusX = radiusX ?? RelativeScalar.Middle;
RadiusY = radiusY ?? RelativeScalar.Middle;
}


/// <summary>
/// Initializes a new instance of the <see cref="ImmutableRadialGradientBrush"/> class.
/// </summary>
Expand All @@ -47,7 +70,8 @@ public ImmutableRadialGradientBrush(RadialGradientBrush source)
{
Center = source.Center;
GradientOrigin = source.GradientOrigin;
Radius = source.Radius;
RadiusX = source.RadiusX;
RadiusY = source.RadiusX;
}

/// <inheritdoc/>
Expand All @@ -57,6 +81,11 @@ public ImmutableRadialGradientBrush(RadialGradientBrush source)
public RelativePoint GradientOrigin { get; }

/// <inheritdoc/>
public double Radius { get; }
public RelativeScalar RadiusX { get; }

/// <inheritdoc/>
public RelativeScalar RadiusY { get; }

[Obsolete("Use RadiusX/RadiusY")] public double Radius => RadiusX.Scalar;
}
}
52 changes: 50 additions & 2 deletions src/Avalonia.Base/Media/RadialGradientBrush.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using Avalonia.Media.Immutable;
using Avalonia.Metadata;
using Avalonia.Rendering.Composition;
using Avalonia.Rendering.Composition.Server;
using Avalonia.Rendering.Composition.Transport;
Expand Down Expand Up @@ -35,6 +36,20 @@ public sealed class RadialGradientBrush : GradientBrush, IRadialGradientBrush
nameof(Radius),
0.5);

/// <summary>
/// Defines the <see cref="RadiusX"/> property.
/// </summary>
public static readonly StyledProperty<RelativeScalar> RadiusXProperty =
AvaloniaProperty.Register<RadialGradientBrush, RelativeScalar>(
nameof(RadiusX), RelativeScalar.Middle);

/// <summary>
/// Defines the <see cref="RadiusX"/> property.
/// </summary>
public static readonly StyledProperty<RelativeScalar> RadiusYProperty =
AvaloniaProperty.Register<RadialGradientBrush, RelativeScalar>(
nameof(RadiusY), RelativeScalar.Middle);

/// <summary>
/// Gets or sets the start point for the gradient.
/// </summary>
Expand All @@ -54,11 +69,33 @@ public RelativePoint GradientOrigin
set { SetValue(GradientOriginProperty, value); }
}

/// <summary>
/// Gets or sets the horizontal radius of the outermost circle of the radial
/// gradient.
/// </summary>
[DependsOn(nameof(Radius))]
public RelativeScalar RadiusX
{
get { return GetValue(RadiusXProperty); }
set { SetValue(RadiusXProperty, value); }
}

/// <summary>
/// Gets or sets the vertical radius of the outermost circle of the radial
/// gradient.
/// </summary>
[DependsOn(nameof(Radius))]
public RelativeScalar RadiusY
{
get { return GetValue(RadiusYProperty); }
set { SetValue(RadiusYProperty, value); }
}

/// <summary>
/// Gets or sets the horizontal and vertical radius of the outermost circle of the radial
/// gradient.
/// </summary>
// TODO: This appears to always be relative so should use a RelativeSize struct or something.
[Obsolete("Use RadiusX/RadiusY")]
public double Radius
{
get { return GetValue(RadiusProperty); }
Expand All @@ -77,7 +114,18 @@ public override IImmutableBrush ToImmutable()
private protected override void SerializeChanges(Compositor c, BatchStreamWriter writer)
{
base.SerializeChanges(c, writer);
ServerCompositionSimpleRadialGradientBrush.SerializeAllChanges(writer, Center, GradientOrigin, Radius);
ServerCompositionSimpleRadialGradientBrush.SerializeAllChanges(writer, Center, GradientOrigin, RadiusX, RadiusY);
}

protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
if (change.IsEffectiveValueChange && change.Property == RadiusProperty)
{
var compatibilityValue = new RelativeScalar(Radius, RelativeUnit.Relative);
SetCurrentValue(RadiusXProperty, compatibilityValue);
SetCurrentValue(RadiusYProperty, compatibilityValue);
}
base.OnPropertyChanged(change);
}
}
}
16 changes: 15 additions & 1 deletion src/Avalonia.Base/RelativePoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,27 @@ public override int GetHashCode()
/// </summary>
/// <param name="size">The size of the visual.</param>
/// <returns>The origin point in pixels.</returns>
[Obsolete("Use ToPixels(Rect) overload to properly map relative points")]
public Point ToPixels(Size size)
{
return _unit == RelativeUnit.Absolute ?
_point :
new Point(_point.X * size.Width, _point.Y * size.Height);
}


#if !BUILDTASK
/// <summary>
/// Converts a <see cref="RelativePoint"/> into pixels.
/// </summary>
/// <param name="rect">The bounding box of the rendering primitive.</param>
/// <returns>The origin point in pixels.</returns>
public Point ToPixels(Rect rect)
{
return _unit == RelativeUnit.Absolute
? _point
: new Point(rect.X + _point.X * rect.Width, rect.Y + _point.Y * rect.Height);
}
#endif
/// <summary>
/// Parses a <see cref="RelativePoint"/> string.
/// </summary>
Expand Down
16 changes: 16 additions & 0 deletions src/Avalonia.Base/RelativeRect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,22 @@ public Rect ToPixels(Size size)
Rect.Width * size.Width,
Rect.Height * size.Height);
}

/// <summary>
/// Converts a <see cref="RelativeRect"/> into pixels.
/// </summary>
/// <param name="boundingBox">The bounding box of the visual.</param>
/// <returns>The origin point in pixels.</returns>
public Rect ToPixels(Rect boundingBox)
{
return Unit == RelativeUnit.Absolute ?
Rect :
new Rect(
boundingBox.X + Rect.X * boundingBox.Width,
boundingBox.Y + Rect.Y * boundingBox.Height,
Rect.Width * boundingBox.Width,
Rect.Height * boundingBox.Height);
}

/// <summary>
/// Parses a <see cref="RelativeRect"/> string.
Expand Down
Loading