Browse Source

Parse most of the vector-like types during XAML compilation.

pull/5053/head
Dariusz Komosinski 6 years ago
parent
commit
da1f3968ef
  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. 35
      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> /// <summary>
/// Provides math utilities not provided in System.Math. /// Provides math utilities not provided in System.Math.
/// </summary> /// </summary>
public static class MathUtilities #if !BUILDTASK
public
#endif
static class MathUtilities
{ {
// smallest such that 1.0+DoubleEpsilon != 1.0 // smallest such that 1.0+DoubleEpsilon != 1.0
internal static readonly double DoubleEpsilon = 2.2204460492503131e-016; 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 namespace Avalonia.Utilities
{ {
public struct StringTokenizer : IDisposable #if !BUILDTASK
public
#endif
struct StringTokenizer : IDisposable
{ {
private const char DefaultSeparatorChar = ','; private const char DefaultSeparatorChar = ',';

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

@ -45,6 +45,12 @@
<Compile Include="../Avalonia.Base/Utilities/IdentifierParser.cs"> <Compile Include="../Avalonia.Base/Utilities/IdentifierParser.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link> <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile> </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"> <Compile Include="..\Markup\Avalonia.Markup\Markup\Parsers\ArgumentListParser.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link> <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile> </Compile>
@ -57,6 +63,24 @@
<Compile Include="../Avalonia.Base/Utilities/StyleClassParser.cs"> <Compile Include="../Avalonia.Base/Utilities/StyleClassParser.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link> <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile> </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\**\obj\**\*.cs" />
<Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\src\XamlX\IL\SreTypeSystem.cs" /> <Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\src\XamlX\IL\SreTypeSystem.cs" />
<PackageReference Include="Mono.Cecil" Version="0.11.2" /> <PackageReference Include="Mono.Cecil" Version="0.11.2" />

9
src/Avalonia.Visuals/CornerRadius.cs

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

5
src/Avalonia.Visuals/Matrix.cs

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

9
src/Avalonia.Visuals/Point.cs

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

9
src/Avalonia.Visuals/Size.cs

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

9
src/Avalonia.Visuals/Thickness.cs

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

9
src/Avalonia.Visuals/Vector.cs

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

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

@ -0,0 +1,35 @@
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, IXamlType type, IXamlConstructor constructor, double[] values) : base(lineInfo)
{
_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); result = new AvaloniaXamlIlFontFamilyAstNode(types, text, node);
return true; return true;
} }
if (type.Equals(types.Thickness))
{
var thickness = Thickness.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types.Thickness, types.ThicknessFullConstructorName,
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.Point, types.PointFullConstructorName,
new[] { point.X, point.Y });
return true;
}
if (type.Equals(types.Vector))
{
var vector = Vector.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types.Vector, types.VectorFullConstructorName,
new[] { vector.X, vector.Y });
return true;
}
if (type.Equals(types.Size))
{
var size = Size.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types.Size, types.SizeFullConstructorName,
new[] { size.Width, size.Height });
return true;
}
if (type.Equals(types.Matrix))
{
var matrix = Matrix.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types.Matrix, types.MatrixFullConstructorName,
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.CornerRadius, types.CornerRadiusFullConstructorName,
new[] { cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft });
return true;
}
if (type.FullName == "Avalonia.AvaloniaProperty") 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.Collections.Generic;
using System.Linq;
using XamlX.Emit; using XamlX.Emit;
using XamlX.IL; using XamlX.IL;
using XamlX.Transform; using XamlX.Transform;
@ -52,7 +53,18 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlType Uri { get; } public IXamlType Uri { get; }
public IXamlType FontFamily { get; } public IXamlType FontFamily { get; }
public IXamlConstructor FontFamilyConstructorUriName { get; } public IXamlConstructor FontFamilyConstructorUriName { get; }
public IXamlType Thickness { get; }
public IXamlConstructor ThicknessFullConstructorName { get; }
public IXamlType Point { get; }
public IXamlConstructor PointFullConstructorName { get; }
public IXamlType Vector { get; }
public IXamlConstructor VectorFullConstructorName { get; }
public IXamlType Size { get; }
public IXamlConstructor SizeFullConstructorName { get; }
public IXamlType Matrix { get; }
public IXamlConstructor MatrixFullConstructorName { get; }
public IXamlType CornerRadius { get; }
public IXamlConstructor CornerRadiusFullConstructorName { get; }
public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg) public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg)
{ {
@ -113,7 +125,22 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
Long = cfg.TypeSystem.GetType("System.Int64"); Long = cfg.TypeSystem.GetType("System.Int64");
Uri = cfg.TypeSystem.GetType("System.Uri"); Uri = cfg.TypeSystem.GetType("System.Uri");
FontFamily = cfg.TypeSystem.GetType("Avalonia.Media.FontFamily"); 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, ThicknessFullConstructorName) = GetNumericTypeInfo("Avalonia.Thickness", XamlIlTypes.Double, 4);
(Point, PointFullConstructorName) = GetNumericTypeInfo("Avalonia.Point", XamlIlTypes.Double, 2);
(Vector, VectorFullConstructorName) = GetNumericTypeInfo("Avalonia.Vector", XamlIlTypes.Double, 2);
(Size, SizeFullConstructorName) = GetNumericTypeInfo("Avalonia.Size", XamlIlTypes.Double, 2);
(Matrix, MatrixFullConstructorName) = GetNumericTypeInfo("Avalonia.Matrix", XamlIlTypes.Double, 6);
(CornerRadius, CornerRadiusFullConstructorName) = GetNumericTypeInfo("Avalonia.CornerRadius", XamlIlTypes.Double, 4);
} }
} }

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

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