Skip to content

Commit

Permalink
feat(imagebrush): add support for RelativeTransform on skia
Browse files Browse the repository at this point in the history
  • Loading branch information
ramezgerges committed Jul 8, 2024
1 parent d0fe28b commit 2a0ed53
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 2 deletions.
7 changes: 7 additions & 0 deletions src/Uno.UI.Composition/Composition/CompositionSurfaceBrush.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Microsoft.UI.Composition
public partial class CompositionSurfaceBrush : CompositionBrush, I2DTransformableObject
{
private Matrix3x2 _transformMatrix = Matrix3x2.Identity;
private Matrix3x2 _relativeTransform = Matrix3x2.Identity;
private Vector2 _scale;
private float _rotationAngle;
private Vector2 _offset;
Expand Down Expand Up @@ -66,6 +67,12 @@ public Matrix3x2 TransformMatrix
set => SetProperty(ref _transformMatrix, value);
}

internal Matrix3x2 RelativeTransform
{
get => _relativeTransform;
set => SetProperty(ref _relativeTransform, value);
}

public Vector2 Scale
{
get => _scale;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Windows.Foundation;
using System.Diagnostics.CodeAnalysis;
using Windows.Graphics.Display;
using Uno.Extensions;

namespace Microsoft.UI.Composition
{
Expand Down Expand Up @@ -88,8 +89,19 @@ internal override void UpdatePaint(SKPaint fillPaint, SKRect bounds)
}
else
{
var matrix = Matrix3x2.CreateTranslation((float)backgroundArea.Left, (float)backgroundArea.Top);
// Relevant doc snippet from WPF: https://learn.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/brush-transformation-overview#differences-between-the-transform-and-relativetransform-properties
// When you apply a transform to a brush's RelativeTransform property, that transform is applied to the brush before its output is mapped to the painted area. The following list describes the order in which a brush’s contents are processed and transformed.
// * Process the brush’s contents. For a GradientBrush, this means determining the gradient area. For a TileBrush, the Viewbox is mapped to the Viewport. This becomes the brush’s output.
// * Project the brush’s output onto the 1 x 1 transformation rectangle.
// * Apply the brush’s RelativeTransform, if it has one.
// * Project the transformed output onto the area to paint.
// * Apply the brush’s Transform, if it has one.
var matrix = Matrix3x2.Identity;
matrix *= Matrix3x2.CreateTranslation((float)backgroundArea.Left, (float)backgroundArea.Top);
matrix *= TransformMatrix;
matrix *= Matrix3x2.CreateScale(bounds.Width, bounds.Height).Inverse();
matrix *= RelativeTransform;
matrix *= Matrix3x2.CreateScale(bounds.Width, bounds.Height);

// The brush is not tied to a specific window, so we can't get the scaling of a specific XamlRoot and
// instead we settle for the main window's scaling which should hopefully be the same.
Expand Down
4 changes: 3 additions & 1 deletion src/Uno.UI/UI/Xaml/Media/ImageBrush.skia.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.UI.Composition;
using System.Numerics;
using Microsoft.UI.Composition;

namespace Microsoft.UI.Xaml.Media;

Expand All @@ -23,6 +24,7 @@ internal override void SynchronizeCompositionBrush()
surfaceBrush.HorizontalAlignmentRatio = GetHorizontalAlignmentRatio(AlignmentX);
surfaceBrush.VerticalAlignmentRatio = GetVerticalAlignmentRatio(AlignmentY);
surfaceBrush.Surface = data.CompositionSurface;
surfaceBrush.RelativeTransform = RelativeTransform?.MatrixCore ?? Matrix3x2.Identity;
}
}

Expand Down

0 comments on commit 2a0ed53

Please sign in to comment.