Browse Source

Merge pull request #5053 from MarchingCube/compile-time-vector-like-parsing

Parse most of the vector-like types during XAML compilation.
pull/5056/head
Jumar Macato 6 years ago
committed by GitHub
parent
commit
cd41f7f558
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      src/Avalonia.Base/Utilities/MathUtilities.cs
  2. 5
      src/Avalonia.Base/Utilities/StringTokenizer.cs
  3. 24
      src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
  4. 9
      src/Avalonia.Visuals/CornerRadius.cs
  5. 5
      src/Avalonia.Visuals/Matrix.cs
  6. 9
      src/Avalonia.Visuals/Point.cs
  7. 9
      src/Avalonia.Visuals/Size.cs
  8. 9
      src/Avalonia.Visuals/Thickness.cs
  9. 9
      src/Avalonia.Visuals/Vector.cs
  10. 54
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlVectorLikeConstantAstNode.cs
  11. 60
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs
  12. 31
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
  13. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github

5
src/Avalonia.Base/Utilities/MathUtilities.cs

@ -5,7 +5,10 @@ namespace Avalonia.Utilities
/// <summary>
/// Provides math utilities not provided in System.Math.
/// </summary>
public static class MathUtilities
#if !BUILDTASK
public
#endif
static class MathUtilities
{
// smallest such that 1.0+DoubleEpsilon != 1.0
internal static readonly double DoubleEpsilon = 2.2204460492503131e-016;

5
src/Avalonia.Base/Utilities/StringTokenizer.cs

@ -4,7 +4,10 @@ using static System.Char;
namespace Avalonia.Utilities
{
public struct StringTokenizer : IDisposable
#if !BUILDTASK
public
#endif
struct StringTokenizer : IDisposable
{
private const char DefaultSeparatorChar = ',';

24
src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj

@ -45,6 +45,12 @@
<Compile Include="../Avalonia.Base/Utilities/IdentifierParser.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="../Avalonia.Base/Utilities/StringTokenizer.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="../Avalonia.Base/Utilities/MathUtilities.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="..\Markup\Avalonia.Markup\Markup\Parsers\ArgumentListParser.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
@ -57,6 +63,24 @@
<Compile Include="../Avalonia.Base/Utilities/StyleClassParser.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="../Avalonia.Visuals/Thickness.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="../Avalonia.Visuals/Size.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="../Avalonia.Visuals/Vector.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="../Avalonia.Visuals/Point.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="../Avalonia.Visuals/Matrix.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="../Avalonia.Visuals/CornerRadius.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\**\obj\**\*.cs" />
<Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\src\XamlX\IL\SreTypeSystem.cs" />
<PackageReference Include="Mono.Cecil" Version="0.11.2" />

9
src/Avalonia.Visuals/CornerRadius.cs

@ -1,6 +1,8 @@
using System;
using System.Globalization;
#if !BUILDTASK
using Avalonia.Animation.Animators;
#endif
using Avalonia.Utilities;
namespace Avalonia
@ -8,11 +10,16 @@ namespace Avalonia
/// <summary>
/// Represents the radii of a rectangle's corners.
/// </summary>
public readonly struct CornerRadius : IEquatable<CornerRadius>
#if !BUILDTASK
public
#endif
readonly struct CornerRadius : IEquatable<CornerRadius>
{
static CornerRadius()
{
#if !BUILDTASK
Animation.Animation.RegisterAnimator<CornerRadiusAnimator>(prop => typeof(CornerRadius).IsAssignableFrom(prop.PropertyType));
#endif
}
public CornerRadius(double uniformRadius)

5
src/Avalonia.Visuals/Matrix.cs

@ -7,7 +7,10 @@ namespace Avalonia
/// <summary>
/// A 2x3 matrix.
/// </summary>
public readonly struct Matrix : IEquatable<Matrix>
#if !BUILDTASK
public
#endif
readonly struct Matrix : IEquatable<Matrix>
{
private readonly double _m11;
private readonly double _m12;

9
src/Avalonia.Visuals/Point.cs

@ -1,6 +1,8 @@
using System;
using System.Globalization;
#if !BUILDTASK
using Avalonia.Animation.Animators;
#endif
using Avalonia.Utilities;
namespace Avalonia
@ -8,11 +10,16 @@ namespace Avalonia
/// <summary>
/// Defines a point.
/// </summary>
public readonly struct Point : IEquatable<Point>
#if !BUILDTASK
public
#endif
readonly struct Point : IEquatable<Point>
{
static Point()
{
#if !BUILDTASK
Animation.Animation.RegisterAnimator<PointAnimator>(prop => typeof(Point).IsAssignableFrom(prop.PropertyType));
#endif
}
/// <summary>

9
src/Avalonia.Visuals/Size.cs

@ -1,6 +1,8 @@
using System;
using System.Globalization;
#if !BUILDTASK
using Avalonia.Animation.Animators;
#endif
using Avalonia.Utilities;
namespace Avalonia
@ -8,11 +10,16 @@ namespace Avalonia
/// <summary>
/// Defines a size.
/// </summary>
public readonly struct Size : IEquatable<Size>
#if !BUILDTASK
public
#endif
readonly struct Size : IEquatable<Size>
{
static Size()
{
#if !BUILDTASK
Animation.Animation.RegisterAnimator<SizeAnimator>(prop => typeof(Size).IsAssignableFrom(prop.PropertyType));
#endif
}
/// <summary>

9
src/Avalonia.Visuals/Thickness.cs

@ -1,6 +1,8 @@
using System;
using System.Globalization;
#if !BUILDTASK
using Avalonia.Animation.Animators;
#endif
using Avalonia.Utilities;
namespace Avalonia
@ -8,11 +10,16 @@ namespace Avalonia
/// <summary>
/// Describes the thickness of a frame around a rectangle.
/// </summary>
public readonly struct Thickness : IEquatable<Thickness>
#if !BUILDTASK
public
#endif
readonly struct Thickness : IEquatable<Thickness>
{
static Thickness()
{
#if !BUILDTASK
Animation.Animation.RegisterAnimator<ThicknessAnimator>(prop => typeof(Thickness).IsAssignableFrom(prop.PropertyType));
#endif
}
/// <summary>

9
src/Avalonia.Visuals/Vector.cs

@ -1,6 +1,8 @@
using System;
using System.Globalization;
#if !BUILDTASK
using Avalonia.Animation.Animators;
#endif
using Avalonia.Utilities;
#nullable enable
@ -10,11 +12,16 @@ namespace Avalonia
/// <summary>
/// Defines a vector.
/// </summary>
public readonly struct Vector : IEquatable<Vector>
#if !BUILDTASK
public
#endif
readonly struct Vector : IEquatable<Vector>
{
static Vector()
{
#if !BUILDTASK
Animation.Animation.RegisterAnimator<VectorAnimator>(prop => typeof(Vector).IsAssignableFrom(prop.PropertyType));
#endif
}
/// <summary>

54
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlVectorLikeConstantAstNode.cs

@ -0,0 +1,54 @@
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
using XamlX;
using XamlX.Ast;
using XamlX.Emit;
using XamlX.IL;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes
{
class AvaloniaXamlIlVectorLikeConstantAstNode : XamlAstNode, IXamlAstValueNode, IXamlAstILEmitableNode
{
private readonly IXamlConstructor _constructor;
private readonly double[] _values;
public AvaloniaXamlIlVectorLikeConstantAstNode(IXamlLineInfo lineInfo, AvaloniaXamlIlWellKnownTypes types, IXamlType type, IXamlConstructor constructor, double[] values) : base(lineInfo)
{
var parameters = constructor.Parameters;
if (parameters.Count != values.Length)
{
throw new XamlTypeSystemException($"Constructor that takes {values.Length} parameters is expected, got {parameters.Count} instead.");
}
var elementType = types.XamlIlTypes.Double;
foreach (var parameter in parameters)
{
if (parameter != elementType)
{
throw new XamlTypeSystemException($"Expected parameter of type {elementType}, got {parameter} instead.");
}
}
_constructor = constructor;
_values = values;
Type = new XamlAstClrTypeReference(lineInfo, type, false);
}
public IXamlAstTypeReference Type { get; }
public XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
foreach (var value in _values)
{
codeGen.Ldc_R8(value);
}
codeGen.Newobj(_constructor);
return XamlILNodeEmitResult.Type(0, Type.GetClrType());
}
}
}

60
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs

@ -205,6 +205,66 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
result = new AvaloniaXamlIlFontFamilyAstNode(types, text, node);
return true;
}
if (type.Equals(types.Thickness))
{
var thickness = Thickness.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Thickness, types.ThicknessFullConstructor,
new[] { thickness.Left, thickness.Top, thickness.Right, thickness.Bottom });
return true;
}
if (type.Equals(types.Point))
{
var point = Point.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Point, types.PointFullConstructor,
new[] { point.X, point.Y });
return true;
}
if (type.Equals(types.Vector))
{
var vector = Vector.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Vector, types.VectorFullConstructor,
new[] { vector.X, vector.Y });
return true;
}
if (type.Equals(types.Size))
{
var size = Size.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Size, types.SizeFullConstructor,
new[] { size.Width, size.Height });
return true;
}
if (type.Equals(types.Matrix))
{
var matrix = Matrix.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Matrix, types.MatrixFullConstructor,
new[] { matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.M31, matrix.M32 });
return true;
}
if (type.Equals(types.CornerRadius))
{
var cornerRadius = CornerRadius.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.CornerRadius, types.CornerRadiusFullConstructor,
new[] { cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft });
return true;
}
if (type.FullName == "Avalonia.AvaloniaProperty")
{

31
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using XamlX.Emit;
using XamlX.IL;
using XamlX.Transform;
@ -52,7 +53,18 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlType Uri { get; }
public IXamlType FontFamily { get; }
public IXamlConstructor FontFamilyConstructorUriName { get; }
public IXamlType Thickness { get; }
public IXamlConstructor ThicknessFullConstructor { get; }
public IXamlType Point { get; }
public IXamlConstructor PointFullConstructor { get; }
public IXamlType Vector { get; }
public IXamlConstructor VectorFullConstructor { get; }
public IXamlType Size { get; }
public IXamlConstructor SizeFullConstructor { get; }
public IXamlType Matrix { get; }
public IXamlConstructor MatrixFullConstructor { get; }
public IXamlType CornerRadius { get; }
public IXamlConstructor CornerRadiusFullConstructor { get; }
public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg)
{
@ -113,7 +125,22 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
Long = cfg.TypeSystem.GetType("System.Int64");
Uri = cfg.TypeSystem.GetType("System.Uri");
FontFamily = cfg.TypeSystem.GetType("Avalonia.Media.FontFamily");
FontFamilyConstructorUriName = FontFamily.FindConstructor(new List<IXamlType> { Uri, XamlIlTypes.String });
FontFamilyConstructorUriName = FontFamily.GetConstructor(new List<IXamlType> { Uri, XamlIlTypes.String });
(IXamlType, IXamlConstructor) GetNumericTypeInfo(string name, IXamlType componentType, int componentCount)
{
var type = cfg.TypeSystem.GetType(name);
var ctor = type.GetConstructor(Enumerable.Range(0, componentCount).Select(_ => componentType).ToList());
return (type, ctor);
}
(Thickness, ThicknessFullConstructor) = GetNumericTypeInfo("Avalonia.Thickness", XamlIlTypes.Double, 4);
(Point, PointFullConstructor) = GetNumericTypeInfo("Avalonia.Point", XamlIlTypes.Double, 2);
(Vector, VectorFullConstructor) = GetNumericTypeInfo("Avalonia.Vector", XamlIlTypes.Double, 2);
(Size, SizeFullConstructor) = GetNumericTypeInfo("Avalonia.Size", XamlIlTypes.Double, 2);
(Matrix, MatrixFullConstructor) = GetNumericTypeInfo("Avalonia.Matrix", XamlIlTypes.Double, 6);
(CornerRadius, CornerRadiusFullConstructor) = GetNumericTypeInfo("Avalonia.CornerRadius", XamlIlTypes.Double, 4);
}
}

2
src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github

@ -1 +1 @@
Subproject commit 5420df861ce6f2be5ead9efa078fe7242ce88f18
Subproject commit ea80a607c5e9d8f000160dbbb48c27ed4cfafbc9
Loading…
Cancel
Save