Browse Source

Merge pull request #1446 from jmacato/master

SkewTransform Implementation
pull/1451/head
Steven Kirk 8 years ago
committed by GitHub
parent
commit
07fbb43544
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      src/Avalonia.Visuals/Matrix.cs
  2. 69
      src/Avalonia.Visuals/Media/SkewTransform.cs
  3. 94
      tests/Avalonia.Controls.UnitTests/LayoutTransformControlTests.cs

14
src/Avalonia.Visuals/Matrix.cs

@ -150,6 +150,19 @@ namespace Avalonia
return new Matrix(cos, sin, -sin, cos, 0, 0);
}
/// <summary>
/// Creates a skew matrix from the given axis skew angles in radians.
/// </summary>
/// <param name="xAngle">The amount of skew along the X-axis, in radians.</param>
/// <param name="yAngle">The amount of skew along the Y-axis, in radians.</param>
/// <returns>A rotation matrix.</returns>
public static Matrix CreateSkew(double xAngle, double yAngle)
{
double tanX = Math.Tan(xAngle);
double tanY = Math.Tan(yAngle);
return new Matrix(1.0, tanY, tanX, 1.0, 0.0, 0.0);
}
/// <summary>
/// Creates a scale matrix from the given X and Y components.
/// </summary>
@ -215,7 +228,6 @@ namespace Avalonia
return (_m11 * _m22) - (_m12 * _m21);
}
/// <summary>
/// Returns a boolean indicating whether the matrix is equal to the other given matrix.
/// </summary>

69
src/Avalonia.Visuals/Media/SkewTransform.cs

@ -0,0 +1,69 @@
// 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 System;
using Avalonia.VisualTree;
namespace Avalonia.Media
{
/// <summary>
/// Skews an <see cref="IVisual"/>.
/// </summary>
public class SkewTransform : Transform
{
/// <summary>
/// Defines the <see cref="AngleX"/> property.
/// </summary>
public static readonly StyledProperty<double> AngleXProperty =
AvaloniaProperty.Register<SkewTransform, double>(nameof(AngleX));
/// <summary>
/// Defines the <see cref="AngleY"/> property.
/// </summary>
public static readonly StyledProperty<double> AngleYProperty =
AvaloniaProperty.Register<SkewTransform, double>(nameof(AngleY));
/// <summary>
/// Initializes a new instance of the <see cref="SkewTransform"/> class.
/// </summary>
public SkewTransform()
{
this.GetObservable(AngleXProperty).Subscribe(_ => RaiseChanged());
this.GetObservable(AngleYProperty).Subscribe(_ => RaiseChanged());
}
/// <summary>
/// Initializes a new instance of the <see cref="SkewTransform"/> class.
/// </summary>
/// <param name="angleX">The skew angle of X-axis, in degrees.</param>
/// <param name="angleY">The skew angle of Y-axis, in degrees.</param>
public SkewTransform(double angleX, double angleY) : this()
{
AngleX = angleX;
AngleY = angleY;
}
/// <summary>
/// Gets or sets the AngleX property.
/// </summary>
public double AngleX
{
get { return GetValue(AngleXProperty); }
set { SetValue(AngleXProperty, value); }
}
/// <summary>
/// Gets or sets the AngleY property.
/// </summary>
public double AngleY
{
get { return GetValue(AngleYProperty); }
set { SetValue(AngleYProperty, value); }
}
/// <summary>
/// Gets the tranform's <see cref="Matrix"/>.
/// </summary>
public override Matrix Value => Matrix.CreateSkew(Matrix.ToRadians(AngleX), Matrix.ToRadians(AngleY));
}
}

94
tests/Avalonia.Controls.UnitTests/LayoutTransformControlTests.cs

@ -30,6 +30,52 @@ namespace Avalonia.Controls.UnitTests
new Size(50, 25));
}
[Fact]
public void Measure_On_Skew_X_axis_45_degrees_Is_Correct()
{
TransformMeasureSizeTest(
new Size(100, 100),
new SkewTransform() { AngleX = 45 },
new Size(200, 100));
}
[Fact]
public void Measure_On_Skew_Y_axis_45_degrees_Is_Correct()
{
TransformMeasureSizeTest(
new Size(100, 100),
new SkewTransform() { AngleY = 45 },
new Size(100, 200));
}
[Fact]
public void Measure_On_Skew_X_axis_minus_45_degrees_Is_Correct()
{
TransformMeasureSizeTest(
new Size(100, 100),
new SkewTransform() { AngleX = -45 },
new Size(200, 100));
}
[Fact]
public void Measure_On_Skew_Y_axis_minus_45_degrees_Is_Correct()
{
TransformMeasureSizeTest(
new Size(100, 100),
new SkewTransform() { AngleY = -45 },
new Size(100, 200));
}
[Fact]
public void Measure_On_Skew_0_degrees_Is_Correct()
{
TransformMeasureSizeTest(
new Size(100, 100),
new SkewTransform() { AngleX = 0, AngleY = 0 },
new Size(100, 100));
}
[Fact]
public void Measure_On_Rotate_90_degrees_Is_Correct()
{
@ -125,7 +171,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void Should_Generate_RenderTransform_90_degrees()
public void Should_Generate_RotateTransform_90_degrees()
{
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
@ -147,7 +193,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void Should_Generate_RenderTransform_minus_90_degrees()
public void Should_Generate_RotateTransform_minus_90_degrees()
{
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
@ -189,6 +235,50 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(m.M32, res.M32, 3);
}
[Fact]
public void Should_Generate_SkewTransform_45_degrees()
{
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
100,
new SkewTransform() { AngleX = 45, AngleY = 45 });
Assert.NotNull(lt.TransformRoot.RenderTransform);
Matrix m = lt.TransformRoot.RenderTransform.Value;
Matrix res = Matrix.CreateSkew(Matrix.ToRadians(45), Matrix.ToRadians(45));
Assert.Equal(m.M11, res.M11, 3);
Assert.Equal(m.M12, res.M12, 3);
Assert.Equal(m.M21, res.M21, 3);
Assert.Equal(m.M22, res.M22, 3);
Assert.Equal(m.M31, res.M31, 3);
Assert.Equal(m.M32, res.M32, 3);
}
[Fact]
public void Should_Generate_SkewTransform_minus_45_degrees()
{
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
100,
new SkewTransform() { AngleX = -45, AngleY = -45 });
Assert.NotNull(lt.TransformRoot.RenderTransform);
Matrix m = lt.TransformRoot.RenderTransform.Value;
Matrix res = Matrix.CreateSkew(Matrix.ToRadians(-45), Matrix.ToRadians(-45));
Assert.Equal(m.M11, res.M11, 3);
Assert.Equal(m.M12, res.M12, 3);
Assert.Equal(m.M21, res.M21, 3);
Assert.Equal(m.M22, res.M22, 3);
Assert.Equal(m.M31, res.M31, 3);
Assert.Equal(m.M32, res.M32, 3);
}
private static void TransformMeasureSizeTest(Size size, Transform transform, Size expectedSize)
{
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(

Loading…
Cancel
Save