30 changed files with 771 additions and 114 deletions
@ -0,0 +1,132 @@ |
|||||
|
<UserControl xmlns="https://github.com/avaloniaui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||
|
<UserControl.Styles> |
||||
|
<Style> |
||||
|
<Style.Resources> |
||||
|
<DrawingGroup x:Key="Bulb"> |
||||
|
<DrawingGroup.Transform> |
||||
|
<MatrixTransform Matrix="1,0,0,1,0,-1028.4" /> |
||||
|
</DrawingGroup.Transform> |
||||
|
<DrawingGroup> |
||||
|
<DrawingGroup.Transform> |
||||
|
<MatrixTransform Matrix="1,0,0,1.25,-10,1031.4" /> |
||||
|
</DrawingGroup.Transform> |
||||
|
<GeometryDrawing Brush="#FF7F8C8D" |
||||
|
Geometry="F1 M24,14 A2,2,0,1,1,20,14 A2,2,0,1,1,24,14 z" /> |
||||
|
</DrawingGroup> |
||||
|
<GeometryDrawing Brush="#FFF39C12" |
||||
|
Geometry="F1 M12,1030.4 C8.134,1030.4 5,1033.6 5,1037.6 5,1040.7 8.125,1043.5 9,1045.4 9.875,1047.2 9,1050.4 9,1050.4 L12,1049.9 15,1050.4 C15,1050.4 14.125,1047.2 15,1045.4 15.875,1043.5 19,1040.7 19,1037.6 19,1033.6 15.866,1030.4 12,1030.4 z" /> |
||||
|
<GeometryDrawing Brush="#FFF1C40F" |
||||
|
Geometry="F1 M12,1030.4 C15.866,1030.4 19,1033.6 19,1037.6 19,1040.7 15.875,1043.5 15,1045.4 14.125,1047.2 15,1050.4 15,1050.4 L12,1049.9 12,1030.4 z" /> |
||||
|
<GeometryDrawing Brush="#FFE67E22" |
||||
|
Geometry="F1 M9,1036.4 L8,1037.4 12,1049.4 16,1037.4 15,1036.4 14,1037.4 13,1036.4 12,1037.4 11,1036.4 10,1037.4 9,1036.4 z M9,1037.4 L10,1038.4 10.5,1037.9 11,1037.4 11.5,1037.9 12,1038.4 12.5,1037.9 13,1037.4 13.5,1037.9 14,1038.4 15,1037.4 15.438,1037.8 12,1048.1 8.5625,1037.8 9,1037.4 z" /> |
||||
|
<DrawingGroup> |
||||
|
<DrawingGroup.Transform> |
||||
|
<MatrixTransform Matrix="1,0,0,1,9,1045.4" /> |
||||
|
</DrawingGroup.Transform> |
||||
|
<GeometryDrawing Brush="#FFBDC3C7"> |
||||
|
<GeometryDrawing.Geometry> |
||||
|
<RectangleGeometry Rect="0,0,6,5" /> |
||||
|
</GeometryDrawing.Geometry> |
||||
|
</GeometryDrawing> |
||||
|
</DrawingGroup> |
||||
|
<GeometryDrawing Brush="#FF95A5A6" |
||||
|
Geometry="F1 M9,1045.4 L9,1050.4 12,1050.4 12,1049.4 15,1049.4 15,1048.4 12,1048.4 12,1047.4 15,1047.4 15,1046.4 12,1046.4 12,1045.4 9,1045.4 z" /> |
||||
|
<GeometryDrawing Brush="#FF7F8C8D" |
||||
|
Geometry="F1 M9,1046.4 L9,1047.4 12,1047.4 12,1046.4 9,1046.4 z M9,1048.4 L9,1049.4 12,1049.4 12,1048.4 9,1048.4 z" /> |
||||
|
</DrawingGroup> |
||||
|
</Style.Resources> |
||||
|
</Style> |
||||
|
</UserControl.Styles> |
||||
|
<Grid RowDefinitions="Auto,Auto,Auto" |
||||
|
ColumnDefinitions="Auto,Auto,Auto,Auto"> |
||||
|
<TextBlock Text="None" |
||||
|
Margin="3" /> |
||||
|
<Border Grid.Column="0" |
||||
|
Grid.Row="1" |
||||
|
VerticalAlignment="Top" |
||||
|
HorizontalAlignment="Left" |
||||
|
BorderThickness="1" |
||||
|
BorderBrush="Gray" |
||||
|
Margin="5"> |
||||
|
<DrawingPresenter Drawing="{StyleResource Bulb}" /> |
||||
|
</Border> |
||||
|
<TextBlock Text="Fill" |
||||
|
Margin="3" |
||||
|
Grid.Column="1" /> |
||||
|
<Border Grid.Column="1" |
||||
|
Grid.Row="1" |
||||
|
VerticalAlignment="Top" |
||||
|
HorizontalAlignment="Left" |
||||
|
BorderThickness="1" |
||||
|
BorderBrush="Gray" |
||||
|
Margin="5"> |
||||
|
<DrawingPresenter Drawing="{StyleResource Bulb}" |
||||
|
Width="100" |
||||
|
Height="50" |
||||
|
Stretch="Fill" /> |
||||
|
</Border> |
||||
|
<TextBlock Text="Uniform" |
||||
|
Margin="3" |
||||
|
Grid.Column="2" /> |
||||
|
<Border Grid.Column="2" |
||||
|
Grid.Row="1" |
||||
|
VerticalAlignment="Top" |
||||
|
HorizontalAlignment="Left" |
||||
|
BorderThickness="1" |
||||
|
BorderBrush="Gray" |
||||
|
Margin="5"> |
||||
|
<DrawingPresenter Drawing="{StyleResource Bulb}" |
||||
|
Width="100" |
||||
|
Height="50" |
||||
|
Stretch="Uniform" /> |
||||
|
</Border> |
||||
|
<TextBlock Text="UniformToFill" |
||||
|
Margin="3" |
||||
|
Grid.Column="3" /> |
||||
|
<Border Grid.Column="3" |
||||
|
Grid.Row="1" |
||||
|
VerticalAlignment="Top" |
||||
|
HorizontalAlignment="Left" |
||||
|
BorderThickness="1" |
||||
|
BorderBrush="Gray" |
||||
|
Margin="5"> |
||||
|
<DrawingPresenter Drawing="{StyleResource Bulb}" |
||||
|
Width="100" |
||||
|
Height="50" |
||||
|
Stretch="UniformToFill" /> |
||||
|
</Border> |
||||
|
|
||||
|
<!-- For comparison --> |
||||
|
|
||||
|
<Ellipse Grid.Row="2" |
||||
|
Grid.Column="0" |
||||
|
Width="100" |
||||
|
Height="50" |
||||
|
Stretch="None" |
||||
|
Fill="Blue" |
||||
|
Margin="5"/> |
||||
|
<Ellipse Grid.Row="2" |
||||
|
Grid.Column="1" |
||||
|
Width="100" |
||||
|
Height="50" |
||||
|
Stretch="Fill" |
||||
|
Fill="Blue" |
||||
|
Margin="5" /> |
||||
|
<Ellipse Grid.Row="2" |
||||
|
Grid.Column="2" |
||||
|
Width="100" |
||||
|
Height="50" |
||||
|
Stretch="Uniform" |
||||
|
Fill="Blue" |
||||
|
Margin="5" /> |
||||
|
<Ellipse Grid.Row="2" |
||||
|
Grid.Column="3" |
||||
|
Width="100" |
||||
|
Height="50" |
||||
|
Stretch="UniformToFill" |
||||
|
Fill="Blue" |
||||
|
Margin="5" /> |
||||
|
|
||||
|
</Grid> |
||||
|
</UserControl> |
||||
@ -0,0 +1,18 @@ |
|||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Markup.Xaml; |
||||
|
|
||||
|
namespace RenderTest.Pages |
||||
|
{ |
||||
|
public class DrawingPage : UserControl |
||||
|
{ |
||||
|
public DrawingPage() |
||||
|
{ |
||||
|
InitializeComponent(); |
||||
|
} |
||||
|
|
||||
|
private void InitializeComponent() |
||||
|
{ |
||||
|
AvaloniaXamlLoader.Load(this); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,59 @@ |
|||||
|
using Avalonia.Controls.Shapes; |
||||
|
using Avalonia.Media; |
||||
|
using Avalonia.Metadata; |
||||
|
|
||||
|
namespace Avalonia.Controls |
||||
|
{ |
||||
|
public class DrawingPresenter : Control |
||||
|
{ |
||||
|
static DrawingPresenter() |
||||
|
{ |
||||
|
AffectsMeasure(DrawingProperty); |
||||
|
AffectsRender(DrawingProperty); |
||||
|
} |
||||
|
|
||||
|
public static readonly StyledProperty<Drawing> DrawingProperty = |
||||
|
AvaloniaProperty.Register<DrawingPresenter, Drawing>(nameof(Drawing)); |
||||
|
|
||||
|
public static readonly StyledProperty<Stretch> StretchProperty = |
||||
|
AvaloniaProperty.Register<DrawingPresenter, Stretch>(nameof(Stretch), Stretch.Uniform); |
||||
|
|
||||
|
[Content] |
||||
|
public Drawing Drawing |
||||
|
{ |
||||
|
get => GetValue(DrawingProperty); |
||||
|
set => SetValue(DrawingProperty, value); |
||||
|
} |
||||
|
|
||||
|
public Stretch Stretch |
||||
|
{ |
||||
|
get => GetValue(StretchProperty); |
||||
|
set => SetValue(StretchProperty, value); |
||||
|
} |
||||
|
|
||||
|
private Matrix _transform = Matrix.Identity; |
||||
|
|
||||
|
protected override Size MeasureOverride(Size availableSize) |
||||
|
{ |
||||
|
if (Drawing == null) return new Size(); |
||||
|
|
||||
|
var (size, transform) = Shape.CalculateSizeAndTransform(availableSize, Drawing.GetBounds(), Stretch); |
||||
|
|
||||
|
_transform = transform; |
||||
|
|
||||
|
return size; |
||||
|
} |
||||
|
|
||||
|
public override void Render(DrawingContext context) |
||||
|
{ |
||||
|
if (Drawing != null) |
||||
|
{ |
||||
|
using (context.PushPreTransform(_transform)) |
||||
|
using (context.PushClip(Bounds)) |
||||
|
{ |
||||
|
Drawing.Draw(context); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
namespace Avalonia.Media |
||||
|
{ |
||||
|
public abstract class Drawing : AvaloniaObject |
||||
|
{ |
||||
|
public abstract void Draw(DrawingContext context); |
||||
|
|
||||
|
public abstract Rect GetBounds(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
using Avalonia.Collections; |
||||
|
using Avalonia.Metadata; |
||||
|
|
||||
|
namespace Avalonia.Media |
||||
|
{ |
||||
|
public class DrawingGroup : Drawing |
||||
|
{ |
||||
|
public static readonly StyledProperty<double> OpacityProperty = |
||||
|
AvaloniaProperty.Register<DrawingGroup, double>(nameof(Opacity), 1); |
||||
|
|
||||
|
public static readonly StyledProperty<Transform> TransformProperty = |
||||
|
AvaloniaProperty.Register<DrawingGroup, Transform>(nameof(Transform)); |
||||
|
|
||||
|
public double Opacity |
||||
|
{ |
||||
|
get => GetValue(OpacityProperty); |
||||
|
set => SetValue(OpacityProperty, value); |
||||
|
} |
||||
|
|
||||
|
public Transform Transform |
||||
|
{ |
||||
|
get => GetValue(TransformProperty); |
||||
|
set => SetValue(TransformProperty, value); |
||||
|
} |
||||
|
|
||||
|
[Content] |
||||
|
public AvaloniaList<Drawing> Children { get; } = new AvaloniaList<Drawing>(); |
||||
|
|
||||
|
public override void Draw(DrawingContext context) |
||||
|
{ |
||||
|
using (context.PushPreTransform(Transform?.Value ?? Matrix.Identity)) |
||||
|
using (context.PushOpacity(Opacity)) |
||||
|
{ |
||||
|
foreach (var drawing in Children) |
||||
|
{ |
||||
|
drawing.Draw(context); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override Rect GetBounds() |
||||
|
{ |
||||
|
var rect = new Rect(); |
||||
|
|
||||
|
foreach (var drawing in Children) |
||||
|
{ |
||||
|
rect = rect.Union(drawing.GetBounds()); |
||||
|
} |
||||
|
|
||||
|
if (Transform != null) |
||||
|
{ |
||||
|
rect = rect.TransformToAABB(Transform.Value); |
||||
|
} |
||||
|
|
||||
|
return rect; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
namespace Avalonia.Media |
||||
|
{ |
||||
|
public class GeometryDrawing : Drawing |
||||
|
{ |
||||
|
public static readonly StyledProperty<Geometry> GeometryProperty = |
||||
|
AvaloniaProperty.Register<GeometryDrawing, Geometry>(nameof(Geometry)); |
||||
|
|
||||
|
public Geometry Geometry |
||||
|
{ |
||||
|
get => GetValue(GeometryProperty); |
||||
|
set => SetValue(GeometryProperty, value); |
||||
|
} |
||||
|
|
||||
|
public static readonly StyledProperty<IBrush> BrushProperty = |
||||
|
AvaloniaProperty.Register<GeometryDrawing, IBrush>(nameof(Brush), Brushes.Transparent); |
||||
|
|
||||
|
public IBrush Brush |
||||
|
{ |
||||
|
get => GetValue(BrushProperty); |
||||
|
set => SetValue(BrushProperty, value); |
||||
|
} |
||||
|
|
||||
|
public static readonly StyledProperty<Pen> PenProperty = |
||||
|
AvaloniaProperty.Register<GeometryDrawing, Pen>(nameof(Pen)); |
||||
|
|
||||
|
public Pen Pen |
||||
|
{ |
||||
|
get => GetValue(PenProperty); |
||||
|
set => SetValue(PenProperty, value); |
||||
|
} |
||||
|
|
||||
|
public override void Draw(DrawingContext context) |
||||
|
{ |
||||
|
context.DrawGeometry(Brush, Pen, Geometry); |
||||
|
} |
||||
|
|
||||
|
public override Rect GetBounds() |
||||
|
{ |
||||
|
// adding the Pen's stroke thickness here could yield wrong results due to transforms
|
||||
|
return Geometry?.GetRenderBounds(0) ?? new Rect(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
// 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.Collections; |
||||
|
|
||||
|
namespace Avalonia |
||||
|
{ |
||||
|
public sealed class Points : AvaloniaList<Point> { } |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
// 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 System.Globalization; |
||||
|
|
||||
|
namespace Avalonia.Markup.Xaml.Converters |
||||
|
{ |
||||
|
using System.ComponentModel; |
||||
|
|
||||
|
public class MatrixTypeConverter : TypeConverter |
||||
|
{ |
||||
|
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) |
||||
|
{ |
||||
|
return sourceType == typeof(string); |
||||
|
} |
||||
|
|
||||
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) |
||||
|
{ |
||||
|
return Matrix.Parse((string)value, culture); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
// 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 System.Globalization; |
||||
|
|
||||
|
namespace Avalonia.Markup.Xaml.Converters |
||||
|
{ |
||||
|
using System.ComponentModel; |
||||
|
|
||||
|
public class RectTypeConverter : TypeConverter |
||||
|
{ |
||||
|
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) |
||||
|
{ |
||||
|
return sourceType == typeof(string); |
||||
|
} |
||||
|
|
||||
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) |
||||
|
{ |
||||
|
return Rect.Parse((string)value, culture); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System.Globalization; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Avalonia.Visuals.UnitTests.Media |
||||
|
{ |
||||
|
public class MatrixTests |
||||
|
{ |
||||
|
[Fact] |
||||
|
public void Parse_Parses() |
||||
|
{ |
||||
|
var matrix = Matrix.Parse("1,2,3,-4,5 6", CultureInfo.CurrentCulture); |
||||
|
var expected = new Matrix(1, 2, 3, -4, 5, 6); |
||||
|
Assert.Equal(expected, matrix); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System.Globalization; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Avalonia.Visuals.UnitTests.Media |
||||
|
{ |
||||
|
public class RectTests |
||||
|
{ |
||||
|
[Fact] |
||||
|
public void Parse_Parses() |
||||
|
{ |
||||
|
var rect = Rect.Parse("1,2 3,-4", CultureInfo.CurrentCulture); |
||||
|
var expected = new Rect(1, 2, 3, -4); |
||||
|
Assert.Equal(expected, rect); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue