diff --git a/host/Generated/ObjectModel/.avalonia-projection.owned.json b/host/Generated/ObjectModel/.avalonia-projection.owned.json index 51bb1cc..9cd0608 100644 --- a/host/Generated/ObjectModel/.avalonia-projection.owned.json +++ b/host/Generated/ObjectModel/.avalonia-projection.owned.json @@ -211,7 +211,7 @@ }, { "path": "IAvnControlFactory.g.cs", - "sha256": "0b16561747ebc843651c90574e80d5b5d4047ed1de15580b1017579f521a3d0d" + "sha256": "07be8008a7c14ec38af1880e95e298db3d99e04842f58fd2f46504c591fb0cc7" }, { "path": "IAvnControlGotFocusHandler.g.cs", @@ -337,6 +337,10 @@ "path": "IAvnFlyoutBaseOpenedHandler.g.cs", "sha256": "c1cf785f23a37d4a3ce5855a5df4bdff1442b7a7674713f4e52bc110537b1234" }, + { + "path": "IAvnGradientBrush.g.cs", + "sha256": "01ffe32aea0231c96b18f33edf4e8555e5750690df40b3495a2527a6dcdd16b7" + }, { "path": "IAvnGrid.g.cs", "sha256": "7454a3819c730c3ce65e84e0c923321d052bdc231f8aabb178df4b522e4db447" @@ -855,7 +859,7 @@ }, { "path": "ProjectionAotRoots.g.cs", - "sha256": "849532b0244176520ffc5b3fd818e753cb461fd7370adc9a4a2106c4a6cb3293" + "sha256": "d20f7a57fa84c816ab3b8913217378172da893efa5470a710a323e05d740cfbc" }, { "path": "ProjectionRuntime.g.cs", @@ -863,7 +867,7 @@ }, { "path": "ProjectionStructs.g.cs", - "sha256": "e3179d44738612e7815e2c6823b7a5c7c3aabc9ea609bfca05cfee5cb16d0b56" + "sha256": "0be6a5d527ac6b2ae728fe016e4372b88bc09ecf6f3bf30b8bb34725b05bfb85" } ] } diff --git a/host/Generated/ObjectModel/IAvnControlFactory.g.cs b/host/Generated/ObjectModel/IAvnControlFactory.g.cs index f2e7fd1..bb082a4 100644 --- a/host/Generated/ObjectModel/IAvnControlFactory.g.cs +++ b/host/Generated/ObjectModel/IAvnControlFactory.g.cs @@ -7,7 +7,7 @@ namespace Avalonia.Host.Com; [GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)] -[Guid("15778134-9E9F-5BAF-98FF-5510778094BA")] +[Guid("C8BCE8E8-62C7-5E0E-8066-690059F55DFF")] public partial interface IAvnControlFactory { [PreserveSig] @@ -319,6 +319,12 @@ public partial interface IAvnControlFactory [PreserveSig] int CreateSolidColorBrush(AvnColor color, double opacity, out IAvnBrush? value); + [PreserveSig] + int CreateLinearGradientBrush(double opacity, int spreadMethod, int stopCount, AvnGradientStopBuffer stops, AvnRelativePoint startPoint, AvnRelativePoint endPoint, out IAvnLinearGradientBrush? value); + + [PreserveSig] + int CreateRadialGradientBrush(double opacity, int spreadMethod, int stopCount, AvnGradientStopBuffer stops, AvnRelativePoint center, AvnRelativePoint gradientOrigin, AvnRelativeScalar radiusX, AvnRelativeScalar radiusY, out IAvnRadialGradientBrush? value); + } [GeneratedComClass] @@ -1815,4 +1821,22 @@ public int CreateSolidColorBrush(AvnColor color, double opacity, out IAvnBrush? return global::Avalonia.Host.HResults.S_OK; } + public int CreateLinearGradientBrush(double opacity, int spreadMethod, int stopCount, AvnGradientStopBuffer stops, AvnRelativePoint startPoint, AvnRelativePoint endPoint, out IAvnLinearGradientBrush? value) + { + value = null; + if (stopCount < 0 || stopCount > 8) + return global::Avalonia.Host.HResults.E_INVALIDARG; + value = new AvnLinearGradientBrush(opacity, spreadMethod, stopCount, stops, startPoint, endPoint); + return global::Avalonia.Host.HResults.S_OK; + } + + public int CreateRadialGradientBrush(double opacity, int spreadMethod, int stopCount, AvnGradientStopBuffer stops, AvnRelativePoint center, AvnRelativePoint gradientOrigin, AvnRelativeScalar radiusX, AvnRelativeScalar radiusY, out IAvnRadialGradientBrush? value) + { + value = null; + if (stopCount < 0 || stopCount > 8) + return global::Avalonia.Host.HResults.E_INVALIDARG; + value = new AvnRadialGradientBrush(opacity, spreadMethod, stopCount, stops, center, gradientOrigin, radiusX, radiusY); + return global::Avalonia.Host.HResults.S_OK; + } + } diff --git a/host/Generated/ObjectModel/IAvnGradientBrush.g.cs b/host/Generated/ObjectModel/IAvnGradientBrush.g.cs new file mode 100644 index 0000000..7dea5a1 --- /dev/null +++ b/host/Generated/ObjectModel/IAvnGradientBrush.g.cs @@ -0,0 +1,305 @@ +// +#nullable enable +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace Avalonia.Host.Com; + +/// Capability shared by every gradient brush kind projected across the ABI. +/// +/// A gradient brush object also implements IAvnBrush so it satisfies every +/// brush-typed slot, but its GetColor still fails with AVN_E_NONSOLIDBRUSH; +/// callers must query for this interface (or a derived one) to read the gradient. +/// Stops beyond the fixed capacity of are rejected +/// when the brush is minted for the ABI. +/// +[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)] +[Guid("FDAA2353-BC44-5012-A5BE-A17C7C01F41A")] +public partial interface IAvnGradientBrush +{ + [PreserveSig] + int GetOpacity(out double value); + + /// 0 = Pad, 1 = Reflect, 2 = Repeat (mirrors Avalonia.Media.GradientSpreadMethod). + [PreserveSig] + int GetSpreadMethod(out int value); + + [PreserveSig] + int GetStopCount(out int value); + + [PreserveSig] + int GetStops(out AvnGradientStopBuffer value); +} + +/// A brush that draws with a linear gradient. +[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)] +[Guid("40B3D53D-330E-5D63-A040-37F1FF717FF8")] +public partial interface IAvnLinearGradientBrush : IAvnGradientBrush +{ + [PreserveSig] + int GetStartPoint(out AvnRelativePoint value); + + [PreserveSig] + int GetEndPoint(out AvnRelativePoint value); +} + +/// A brush that draws with a radial gradient. +[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)] +[Guid("AEC23FCE-9FEA-506C-ABC4-774143BE80C8")] +public partial interface IAvnRadialGradientBrush : IAvnGradientBrush +{ + [PreserveSig] + int GetCenter(out AvnRelativePoint value); + + [PreserveSig] + int GetGradientOrigin(out AvnRelativePoint value); + + [PreserveSig] + int GetRadiusX(out AvnRelativeScalar value); + + [PreserveSig] + int GetRadiusY(out AvnRelativeScalar value); +} + +[GeneratedComClass] +public sealed partial class AvnLinearGradientBrush : global::Avalonia.Host.Com.IAvnBrush, IAvnLinearGradientBrush +{ + private readonly double _opacity; + private readonly int _spreadMethod; + private readonly int _stopCount; + private readonly AvnGradientStopBuffer _stops; + private readonly AvnRelativePoint _startPoint; + private readonly AvnRelativePoint _endPoint; + + internal AvnLinearGradientBrush(double opacity, int spreadMethod, int stopCount, AvnGradientStopBuffer stops, AvnRelativePoint startPoint, AvnRelativePoint endPoint) + { + _opacity = opacity; + _spreadMethod = spreadMethod; + _stopCount = stopCount; + _stops = stops; + _startPoint = startPoint; + _endPoint = endPoint; + } + + public int GetColor(out AvnColor value) + { + value = default; + return global::Avalonia.Host.HResults.AVN_E_NONSOLIDBRUSH; + } + + public int GetOpacity(out double value) + { + value = _opacity; + return global::Avalonia.Host.HResults.S_OK; + } + + public int GetSpreadMethod(out int value) + { + value = _spreadMethod; + return global::Avalonia.Host.HResults.S_OK; + } + + public int GetStopCount(out int value) + { + value = _stopCount; + return global::Avalonia.Host.HResults.S_OK; + } + + public int GetStops(out AvnGradientStopBuffer value) + { + value = _stops; + return global::Avalonia.Host.HResults.S_OK; + } + + public int GetStartPoint(out AvnRelativePoint value) + { + value = _startPoint; + return global::Avalonia.Host.HResults.S_OK; + } + + public int GetEndPoint(out AvnRelativePoint value) + { + value = _endPoint; + return global::Avalonia.Host.HResults.S_OK; + } + + /// Projects a managed lineargradientbrush, minting the fixed-capacity stop buffer. + public static IAvnLinearGradientBrush FromLinearGradientBrush(global::Avalonia.Media.ILinearGradientBrush value) + { + var stops = value.GradientStops; + if (stops.Count > 8) + { + throw new global::System.NotSupportedException( + $"Gradient brush has {stops.Count} stops, more than the 8 supported across the ABI.") + { + HResult = global::Avalonia.Host.HResults.AVN_E_NONSOLIDBRUSH, + }; + } + var buffer = new AvnGradientStopBuffer(); + for (var i = 0; i < stops.Count; i++) + buffer[i] = AvnGradientStop.FromAvalonia(stops[i]); + return new AvnLinearGradientBrush(value.Opacity, (int)value.SpreadMethod, stops.Count, buffer, AvnRelativePoint.FromAvalonia(value.StartPoint), AvnRelativePoint.FromAvalonia(value.EndPoint)); + } + + /// Materialises an immutable lineargradientbrush from the members carried across. + public static global::Avalonia.Media.IBrush? ToLinearGradientBrush(IAvnLinearGradientBrush? value) + { + if (value is null) + return null; + var hr = value.GetOpacity(out var opacity); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + hr = value.GetSpreadMethod(out var spreadMethod); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + hr = value.GetStopCount(out var stopCount); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + hr = value.GetStops(out var stops); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + var managedStops = new global::Avalonia.Media.Immutable.ImmutableGradientStop[stopCount]; + for (var i = 0; i < stopCount; i++) + managedStops[i] = new global::Avalonia.Media.Immutable.ImmutableGradientStop(stops[i].Offset, stops[i].Color.ToAvalonia()); + hr = value.GetStartPoint(out var startPoint); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + hr = value.GetEndPoint(out var endPoint); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + return new global::Avalonia.Media.Immutable.ImmutableLinearGradientBrush(managedStops, opacity, transform: null, transformOrigin: null, (global::Avalonia.Media.GradientSpreadMethod)spreadMethod, startPoint.ToAvalonia(), endPoint.ToAvalonia()); + } +} + +[GeneratedComClass] +public sealed partial class AvnRadialGradientBrush : global::Avalonia.Host.Com.IAvnBrush, IAvnRadialGradientBrush +{ + private readonly double _opacity; + private readonly int _spreadMethod; + private readonly int _stopCount; + private readonly AvnGradientStopBuffer _stops; + private readonly AvnRelativePoint _center; + private readonly AvnRelativePoint _gradientOrigin; + private readonly AvnRelativeScalar _radiusX; + private readonly AvnRelativeScalar _radiusY; + + internal AvnRadialGradientBrush(double opacity, int spreadMethod, int stopCount, AvnGradientStopBuffer stops, AvnRelativePoint center, AvnRelativePoint gradientOrigin, AvnRelativeScalar radiusX, AvnRelativeScalar radiusY) + { + _opacity = opacity; + _spreadMethod = spreadMethod; + _stopCount = stopCount; + _stops = stops; + _center = center; + _gradientOrigin = gradientOrigin; + _radiusX = radiusX; + _radiusY = radiusY; + } + + public int GetColor(out AvnColor value) + { + value = default; + return global::Avalonia.Host.HResults.AVN_E_NONSOLIDBRUSH; + } + + public int GetOpacity(out double value) + { + value = _opacity; + return global::Avalonia.Host.HResults.S_OK; + } + + public int GetSpreadMethod(out int value) + { + value = _spreadMethod; + return global::Avalonia.Host.HResults.S_OK; + } + + public int GetStopCount(out int value) + { + value = _stopCount; + return global::Avalonia.Host.HResults.S_OK; + } + + public int GetStops(out AvnGradientStopBuffer value) + { + value = _stops; + return global::Avalonia.Host.HResults.S_OK; + } + + public int GetCenter(out AvnRelativePoint value) + { + value = _center; + return global::Avalonia.Host.HResults.S_OK; + } + + public int GetGradientOrigin(out AvnRelativePoint value) + { + value = _gradientOrigin; + return global::Avalonia.Host.HResults.S_OK; + } + + public int GetRadiusX(out AvnRelativeScalar value) + { + value = _radiusX; + return global::Avalonia.Host.HResults.S_OK; + } + + public int GetRadiusY(out AvnRelativeScalar value) + { + value = _radiusY; + return global::Avalonia.Host.HResults.S_OK; + } + + /// Projects a managed radialgradientbrush, minting the fixed-capacity stop buffer. + public static IAvnRadialGradientBrush FromRadialGradientBrush(global::Avalonia.Media.IRadialGradientBrush value) + { + var stops = value.GradientStops; + if (stops.Count > 8) + { + throw new global::System.NotSupportedException( + $"Gradient brush has {stops.Count} stops, more than the 8 supported across the ABI.") + { + HResult = global::Avalonia.Host.HResults.AVN_E_NONSOLIDBRUSH, + }; + } + var buffer = new AvnGradientStopBuffer(); + for (var i = 0; i < stops.Count; i++) + buffer[i] = AvnGradientStop.FromAvalonia(stops[i]); + return new AvnRadialGradientBrush(value.Opacity, (int)value.SpreadMethod, stops.Count, buffer, AvnRelativePoint.FromAvalonia(value.Center), AvnRelativePoint.FromAvalonia(value.GradientOrigin), AvnRelativeScalar.FromAvalonia(value.RadiusX), AvnRelativeScalar.FromAvalonia(value.RadiusY)); + } + + /// Materialises an immutable radialgradientbrush from the members carried across. + public static global::Avalonia.Media.IBrush? ToRadialGradientBrush(IAvnRadialGradientBrush? value) + { + if (value is null) + return null; + var hr = value.GetOpacity(out var opacity); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + hr = value.GetSpreadMethod(out var spreadMethod); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + hr = value.GetStopCount(out var stopCount); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + hr = value.GetStops(out var stops); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + var managedStops = new global::Avalonia.Media.Immutable.ImmutableGradientStop[stopCount]; + for (var i = 0; i < stopCount; i++) + managedStops[i] = new global::Avalonia.Media.Immutable.ImmutableGradientStop(stops[i].Offset, stops[i].Color.ToAvalonia()); + hr = value.GetCenter(out var center); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + hr = value.GetGradientOrigin(out var gradientOrigin); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + hr = value.GetRadiusX(out var radiusX); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + hr = value.GetRadiusY(out var radiusY); + if (hr < 0) + global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr); + return new global::Avalonia.Media.Immutable.ImmutableRadialGradientBrush(managedStops, opacity, transform: null, transformOrigin: null, (global::Avalonia.Media.GradientSpreadMethod)spreadMethod, center.ToAvalonia(), gradientOrigin.ToAvalonia(), radiusX.ToAvalonia(), radiusY.ToAvalonia()); + } +} + diff --git a/host/Generated/ObjectModel/ProjectionAotRoots.g.cs b/host/Generated/ObjectModel/ProjectionAotRoots.g.cs index 8df1973..f350368 100644 --- a/host/Generated/ObjectModel/ProjectionAotRoots.g.cs +++ b/host/Generated/ObjectModel/ProjectionAotRoots.g.cs @@ -10,6 +10,8 @@ internal static class ProjectionAotRoots { [global::System.Diagnostics.CodeAnalysis.DynamicDependency(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof(AvnControlFactory))] [global::System.Diagnostics.CodeAnalysis.DynamicDependency(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof(AvnBrush))] + [global::System.Diagnostics.CodeAnalysis.DynamicDependency(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof(AvnLinearGradientBrush))] + [global::System.Diagnostics.CodeAnalysis.DynamicDependency(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof(AvnRadialGradientBrush))] [global::System.Diagnostics.CodeAnalysis.DynamicDependency(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof(AvnCommand))] [global::System.Diagnostics.CodeAnalysis.DynamicDependency(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof(AvnDataTemplate))] [global::System.Diagnostics.CodeAnalysis.DynamicDependency(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof(AvnItemFilter))] diff --git a/host/Generated/ObjectModel/ProjectionStructs.g.cs b/host/Generated/ObjectModel/ProjectionStructs.g.cs index 2767986..aac38c9 100644 --- a/host/Generated/ObjectModel/ProjectionStructs.g.cs +++ b/host/Generated/ObjectModel/ProjectionStructs.g.cs @@ -362,3 +362,56 @@ public void FreeUtf16() _ => false, }; } + +/// Blittable ABI mirror of Avalonia.RelativePoint. +/// Unit mirrors Avalonia.RelativeUnit: 0 relative, 1 absolute. +[StructLayout(LayoutKind.Sequential)] +public struct AvnRelativePoint +{ + public double X; + public double Y; + public int Unit; + + public static AvnRelativePoint FromAvalonia(global::Avalonia.RelativePoint value) => + new AvnRelativePoint { X = value.Point.X, Y = value.Point.Y, Unit = (int)value.Unit }; + + public readonly global::Avalonia.RelativePoint ToAvalonia() => + new global::Avalonia.RelativePoint(X, Y, (global::Avalonia.RelativeUnit)Unit); +} + +/// Blittable ABI mirror of Avalonia.RelativeScalar. +/// Unit mirrors Avalonia.RelativeUnit: 0 relative, 1 absolute. +[StructLayout(LayoutKind.Sequential)] +public struct AvnRelativeScalar +{ + public double Scalar; + public int Unit; + + public static AvnRelativeScalar FromAvalonia(global::Avalonia.RelativeScalar value) => + new AvnRelativeScalar { Scalar = value.Scalar, Unit = (int)value.Unit }; + + public readonly global::Avalonia.RelativeScalar ToAvalonia() => + new global::Avalonia.RelativeScalar(Scalar, (global::Avalonia.RelativeUnit)Unit); +} + +/// Blittable ABI mirror of a single gradient stop (offset plus packed colour). +[StructLayout(LayoutKind.Sequential)] +public struct AvnGradientStop +{ + public double Offset; + public AvnColor Color; + + public static AvnGradientStop FromAvalonia(global::Avalonia.Media.IGradientStop value) => + new AvnGradientStop { Offset = value.Offset, Color = AvnColor.FromAvalonia(value.Color) }; +} + +/// Fixed-capacity buffer of up to 8 entries. +/// +/// Gradient brushes with more stops than this cannot cross the ABI; the count actually in +/// use is carried separately by IAvnGradientBrush.GetStopCount. +/// +[System.Runtime.CompilerServices.InlineArray(8)] +public struct AvnGradientStopBuffer +{ + private AvnGradientStop _element0; +} diff --git a/projection/Avalonia.Projection.Generator/ComSourceEmitter.cs b/projection/Avalonia.Projection.Generator/ComSourceEmitter.cs index ca98449..e01f998 100644 --- a/projection/Avalonia.Projection.Generator/ComSourceEmitter.cs +++ b/projection/Avalonia.Projection.Generator/ComSourceEmitter.cs @@ -37,6 +37,8 @@ public static IReadOnlyDictionary Emit(ProjectionIr ir) files["ProjectionStructs.g.cs"] = EmitGeometryStructs(ir); if (ir.BrushInterfaceName is not null) files[SimpleName(ir.BrushInterfaceName) + ".g.cs"] = EmitBrush(ir); + if (ir.GradientBrushInterfaceName is not null) + files[SimpleName(ir.GradientBrushInterfaceName) + ".g.cs"] = EmitGradientBrush(ir); if (ir.CommandInterfaceName is not null) files[SimpleName(ir.CommandInterfaceName) + ".g.cs"] = EmitCommand(ir); if (ir.TemplateInterfaceName is not null) @@ -437,6 +439,19 @@ public static string EmitFactory(ProjectionIr ir) $" int {BrushMarshalling.FactoryMethodName}({colorAbiName} color, double opacity, out {brushName}? value);"); sb.AppendLine(); } + if (ir.GradientBrushInterfaceName is not null) + { + var linearName = SimpleName(ir.LinearGradientBrushInterfaceName!); + var radialName = SimpleName(ir.RadialGradientBrushInterfaceName!); + sb.AppendLine(" [PreserveSig]"); + sb.AppendLine( + $" int {GradientBrushMarshalling.CreateLinearFactoryMethodName}(double opacity, int spreadMethod, int stopCount, AvnGradientStopBuffer stops, AvnRelativePoint startPoint, AvnRelativePoint endPoint, out {linearName}? value);"); + sb.AppendLine(); + sb.AppendLine(" [PreserveSig]"); + sb.AppendLine( + $" int {GradientBrushMarshalling.CreateRadialFactoryMethodName}(double opacity, int spreadMethod, int stopCount, AvnGradientStopBuffer stops, AvnRelativePoint center, AvnRelativePoint gradientOrigin, AvnRelativeScalar radiusX, AvnRelativeScalar radiusY, out {radialName}? value);"); + sb.AppendLine(); + } sb.AppendLine("}"); sb.AppendLine(); sb.AppendLine("[GeneratedComClass]"); @@ -488,6 +503,31 @@ public static string EmitFactory(ProjectionIr ir) sb.AppendLine(" }"); sb.AppendLine(); } + if (ir.GradientBrushInterfaceName is not null) + { + var linearName = SimpleName(ir.LinearGradientBrushInterfaceName!); + var radialName = SimpleName(ir.RadialGradientBrushInterfaceName!); + sb.AppendLine( + $" public int {GradientBrushMarshalling.CreateLinearFactoryMethodName}(double opacity, int spreadMethod, int stopCount, AvnGradientStopBuffer stops, AvnRelativePoint startPoint, AvnRelativePoint endPoint, out {linearName}? value)"); + sb.AppendLine(" {"); + sb.AppendLine(" value = null;"); + sb.AppendLine($" if (stopCount < 0 || stopCount > {GradientBrushMarshalling.MaxStops})"); + sb.AppendLine(" return global::Avalonia.Host.HResults.E_INVALIDARG;"); + sb.AppendLine($" value = new {linearName[1..]}(opacity, spreadMethod, stopCount, stops, startPoint, endPoint);"); + sb.AppendLine(" return global::Avalonia.Host.HResults.S_OK;"); + sb.AppendLine(" }"); + sb.AppendLine(); + sb.AppendLine( + $" public int {GradientBrushMarshalling.CreateRadialFactoryMethodName}(double opacity, int spreadMethod, int stopCount, AvnGradientStopBuffer stops, AvnRelativePoint center, AvnRelativePoint gradientOrigin, AvnRelativeScalar radiusX, AvnRelativeScalar radiusY, out {radialName}? value)"); + sb.AppendLine(" {"); + sb.AppendLine(" value = null;"); + sb.AppendLine($" if (stopCount < 0 || stopCount > {GradientBrushMarshalling.MaxStops})"); + sb.AppendLine(" return global::Avalonia.Host.HResults.E_INVALIDARG;"); + sb.AppendLine($" value = new {radialName[1..]}(opacity, spreadMethod, stopCount, stops, center, gradientOrigin, radiusX, radiusY);"); + sb.AppendLine(" return global::Avalonia.Host.HResults.S_OK;"); + sb.AppendLine(" }"); + sb.AppendLine(); + } sb.AppendLine("}"); return sb.ToString(); } @@ -507,6 +547,11 @@ public static string EmitAotRoots(ProjectionIr ir) { sb.AppendLine($" [global::System.Diagnostics.CodeAnalysis.DynamicDependency(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof({SimpleName(brushInterfaceName)[1..]}))]"); } + if (ir.GradientBrushInterfaceName is not null) + { + sb.AppendLine($" [global::System.Diagnostics.CodeAnalysis.DynamicDependency(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof({SimpleName(ir.LinearGradientBrushInterfaceName!)[1..]}))]"); + sb.AppendLine($" [global::System.Diagnostics.CodeAnalysis.DynamicDependency(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof({SimpleName(ir.RadialGradientBrushInterfaceName!)[1..]}))]"); + } if (ir.CommandInterfaceName is { } commandInterfaceName) { sb.AppendLine($" [global::System.Diagnostics.CodeAnalysis.DynamicDependency(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof({SimpleName(commandInterfaceName)[1..]}))]"); @@ -649,6 +694,246 @@ public static string EmitBrush(ProjectionIr ir) return sb.ToString(); } + public static string EmitGradientBrush(ProjectionIr ir) + { + var gradientName = SimpleName(ir.GradientBrushInterfaceName + ?? throw new InvalidOperationException("The IR declares no projected gradient brush interface.")); + var linearName = SimpleName(ir.LinearGradientBrushInterfaceName!); + var radialName = SimpleName(ir.RadialGradientBrushInterfaceName!); + var linearClassName = linearName[1..]; + var radialClassName = radialName[1..]; + var colorAbiName = GeometryMarshalling.All + .Single(geometry => geometry.Kind == MarshallingKind.Color).AbiName; + var sb = new StringBuilder(); + sb.AppendLine("// "); + sb.AppendLine("#nullable enable"); + sb.AppendLine("using System.Runtime.InteropServices;"); + sb.AppendLine("using System.Runtime.InteropServices.Marshalling;"); + sb.AppendLine(); + sb.AppendLine($"namespace {NamespaceOf(ir.GradientBrushInterfaceName)};"); + sb.AppendLine(); + sb.AppendLine("/// Capability shared by every gradient brush kind projected across the ABI."); + sb.AppendLine("/// "); + sb.AppendLine("/// A gradient brush object also implements IAvnBrush so it satisfies every"); + sb.AppendLine("/// brush-typed slot, but its GetColor still fails with AVN_E_NONSOLIDBRUSH;"); + sb.AppendLine("/// callers must query for this interface (or a derived one) to read the gradient."); + sb.AppendLine("/// Stops beyond the fixed capacity of are rejected"); + sb.AppendLine("/// when the brush is minted for the ABI."); + sb.AppendLine("/// "); + sb.AppendLine("[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)]"); + sb.AppendLine($"[Guid(\"{ir.GradientBrushInterfaceIid}\")]"); + sb.AppendLine($"public partial interface {gradientName}"); + sb.AppendLine("{"); + sb.AppendLine(" [PreserveSig]"); + sb.AppendLine(" int GetOpacity(out double value);"); + sb.AppendLine(); + sb.AppendLine(" /// 0 = Pad, 1 = Reflect, 2 = Repeat (mirrors Avalonia.Media.GradientSpreadMethod)."); + sb.AppendLine(" [PreserveSig]"); + sb.AppendLine(" int GetSpreadMethod(out int value);"); + sb.AppendLine(); + sb.AppendLine(" [PreserveSig]"); + sb.AppendLine(" int GetStopCount(out int value);"); + sb.AppendLine(); + sb.AppendLine(" [PreserveSig]"); + sb.AppendLine(" int GetStops(out AvnGradientStopBuffer value);"); + sb.AppendLine("}"); + sb.AppendLine(); + sb.AppendLine("/// A brush that draws with a linear gradient."); + sb.AppendLine("[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)]"); + sb.AppendLine($"[Guid(\"{ir.LinearGradientBrushInterfaceIid}\")]"); + sb.AppendLine($"public partial interface {linearName} : {gradientName}"); + sb.AppendLine("{"); + sb.AppendLine(" [PreserveSig]"); + sb.AppendLine(" int GetStartPoint(out AvnRelativePoint value);"); + sb.AppendLine(); + sb.AppendLine(" [PreserveSig]"); + sb.AppendLine(" int GetEndPoint(out AvnRelativePoint value);"); + sb.AppendLine("}"); + sb.AppendLine(); + sb.AppendLine("/// A brush that draws with a radial gradient."); + sb.AppendLine("[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)]"); + sb.AppendLine($"[Guid(\"{ir.RadialGradientBrushInterfaceIid}\")]"); + sb.AppendLine($"public partial interface {radialName} : {gradientName}"); + sb.AppendLine("{"); + sb.AppendLine(" [PreserveSig]"); + sb.AppendLine(" int GetCenter(out AvnRelativePoint value);"); + sb.AppendLine(); + sb.AppendLine(" [PreserveSig]"); + sb.AppendLine(" int GetGradientOrigin(out AvnRelativePoint value);"); + sb.AppendLine(); + sb.AppendLine(" [PreserveSig]"); + sb.AppendLine(" int GetRadiusX(out AvnRelativeScalar value);"); + sb.AppendLine(); + sb.AppendLine(" [PreserveSig]"); + sb.AppendLine(" int GetRadiusY(out AvnRelativeScalar value);"); + sb.AppendLine("}"); + sb.AppendLine(); + + EmitGradientBrushClass( + sb, + className: linearClassName, + interfaceName: linearName, + gradientInterfaceName: gradientName, + managedTypeName: GradientBrushMarshalling.LinearManagedTypeName, + immutableManagedTypeName: GradientBrushMarshalling.ImmutableLinearManagedTypeName, + colorAbiName: colorAbiName, + shapeFields: + [ + ("AvnRelativePoint", "StartPoint", "StartPoint"), + ("AvnRelativePoint", "EndPoint", "EndPoint"), + ]); + EmitGradientBrushClass( + sb, + className: radialClassName, + interfaceName: radialName, + gradientInterfaceName: gradientName, + managedTypeName: GradientBrushMarshalling.RadialManagedTypeName, + immutableManagedTypeName: GradientBrushMarshalling.ImmutableRadialManagedTypeName, + colorAbiName: colorAbiName, + shapeFields: + [ + ("AvnRelativePoint", "Center", "Center"), + ("AvnRelativePoint", "GradientOrigin", "GradientOrigin"), + ("AvnRelativeScalar", "RadiusX", "RadiusX"), + ("AvnRelativeScalar", "RadiusY", "RadiusY"), + ]); + return sb.ToString(); + } + + /// + /// Emits one gradient-kind CCW class (linear or radial). lists + /// the kind-specific geometry members as (abi struct type, ABI accessor suffix, managed + /// property name) tuples, in addition to the opacity/spread-method/stops shared by every + /// gradient brush. + /// + private static void EmitGradientBrushClass( + StringBuilder sb, + string className, + string interfaceName, + string gradientInterfaceName, + string managedTypeName, + string immutableManagedTypeName, + string colorAbiName, + (string AbiType, string Accessor, string ManagedProperty)[] shapeFields) + { + sb.AppendLine("[GeneratedComClass]"); + sb.AppendLine($"public sealed partial class {className} : global::Avalonia.Host.Com.IAvnBrush, {interfaceName}"); + sb.AppendLine("{"); + sb.AppendLine(" private readonly double _opacity;"); + sb.AppendLine(" private readonly int _spreadMethod;"); + sb.AppendLine(" private readonly int _stopCount;"); + sb.AppendLine(" private readonly AvnGradientStopBuffer _stops;"); + foreach (var (abiType, accessor, _) in shapeFields) + sb.AppendLine($" private readonly {abiType} _{FirstLower(accessor)};"); + sb.AppendLine(); + var ctorParams = string.Join(", ", new[] { "double opacity", "int spreadMethod", "int stopCount", "AvnGradientStopBuffer stops" } + .Concat(shapeFields.Select(f => $"{f.AbiType} {FirstLower(f.Accessor)}"))); + sb.AppendLine($" internal {className}({ctorParams})"); + sb.AppendLine(" {"); + sb.AppendLine(" _opacity = opacity;"); + sb.AppendLine(" _spreadMethod = spreadMethod;"); + sb.AppendLine(" _stopCount = stopCount;"); + sb.AppendLine(" _stops = stops;"); + foreach (var (_, accessor, _) in shapeFields) + sb.AppendLine($" _{FirstLower(accessor)} = {FirstLower(accessor)};"); + sb.AppendLine(" }"); + sb.AppendLine(); + sb.AppendLine($" public int GetColor(out {colorAbiName} value)"); + sb.AppendLine(" {"); + sb.AppendLine(" value = default;"); + sb.AppendLine(" return global::Avalonia.Host.HResults.AVN_E_NONSOLIDBRUSH;"); + sb.AppendLine(" }"); + sb.AppendLine(); + sb.AppendLine(" public int GetOpacity(out double value)"); + sb.AppendLine(" {"); + sb.AppendLine(" value = _opacity;"); + sb.AppendLine(" return global::Avalonia.Host.HResults.S_OK;"); + sb.AppendLine(" }"); + sb.AppendLine(); + sb.AppendLine(" public int GetSpreadMethod(out int value)"); + sb.AppendLine(" {"); + sb.AppendLine(" value = _spreadMethod;"); + sb.AppendLine(" return global::Avalonia.Host.HResults.S_OK;"); + sb.AppendLine(" }"); + sb.AppendLine(); + sb.AppendLine(" public int GetStopCount(out int value)"); + sb.AppendLine(" {"); + sb.AppendLine(" value = _stopCount;"); + sb.AppendLine(" return global::Avalonia.Host.HResults.S_OK;"); + sb.AppendLine(" }"); + sb.AppendLine(); + sb.AppendLine(" public int GetStops(out AvnGradientStopBuffer value)"); + sb.AppendLine(" {"); + sb.AppendLine(" value = _stops;"); + sb.AppendLine(" return global::Avalonia.Host.HResults.S_OK;"); + sb.AppendLine(" }"); + foreach (var (abiType, accessor, _) in shapeFields) + { + sb.AppendLine(); + sb.AppendLine($" public int Get{accessor}(out {abiType} value)"); + sb.AppendLine(" {"); + sb.AppendLine($" value = _{FirstLower(accessor)};"); + sb.AppendLine(" return global::Avalonia.Host.HResults.S_OK;"); + sb.AppendLine(" }"); + } + sb.AppendLine(); + sb.AppendLine($" /// Projects a managed {className[3..].ToLowerInvariant()}, minting the fixed-capacity stop buffer."); + sb.AppendLine($" public static {interfaceName} From{className[3..]}(global::{managedTypeName} value)"); + sb.AppendLine(" {"); + sb.AppendLine($" var stops = value.GradientStops;"); + sb.AppendLine($" if (stops.Count > {GradientBrushMarshalling.MaxStops})"); + sb.AppendLine(" {"); + sb.AppendLine(" throw new global::System.NotSupportedException("); + sb.AppendLine($" $\"Gradient brush has {{stops.Count}} stops, more than the {GradientBrushMarshalling.MaxStops} supported across the ABI.\")"); + sb.AppendLine(" {"); + sb.AppendLine(" HResult = global::Avalonia.Host.HResults.AVN_E_NONSOLIDBRUSH,"); + sb.AppendLine(" };"); + sb.AppendLine(" }"); + sb.AppendLine(" var buffer = new AvnGradientStopBuffer();"); + sb.AppendLine(" for (var i = 0; i < stops.Count; i++)"); + sb.AppendLine(" buffer[i] = AvnGradientStop.FromAvalonia(stops[i]);"); + var fromArgs = string.Join(", ", new[] { "value.Opacity", "(int)value.SpreadMethod", "stops.Count", "buffer" } + .Concat(shapeFields.Select(f => $"{f.AbiType}.FromAvalonia(value.{f.ManagedProperty})"))); + sb.AppendLine($" return new {className}({fromArgs});"); + sb.AppendLine(" }"); + sb.AppendLine(); + sb.AppendLine($" /// Materialises an immutable {className[3..].ToLowerInvariant()} from the members carried across."); + sb.AppendLine($" public static global::{BrushMarshalling.ManagedTypeName}? To{className[3..]}({interfaceName}? value)"); + sb.AppendLine(" {"); + sb.AppendLine(" if (value is null)"); + sb.AppendLine(" return null;"); + sb.AppendLine(" var hr = value.GetOpacity(out var opacity);"); + sb.AppendLine(" if (hr < 0)"); + sb.AppendLine(" global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr);"); + sb.AppendLine(" hr = value.GetSpreadMethod(out var spreadMethod);"); + sb.AppendLine(" if (hr < 0)"); + sb.AppendLine(" global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr);"); + sb.AppendLine(" hr = value.GetStopCount(out var stopCount);"); + sb.AppendLine(" if (hr < 0)"); + sb.AppendLine(" global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr);"); + sb.AppendLine(" hr = value.GetStops(out var stops);"); + sb.AppendLine(" if (hr < 0)"); + sb.AppendLine(" global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr);"); + sb.AppendLine($" var managedStops = new global::{GradientBrushMarshalling.ImmutableGradientStopManagedTypeName}[stopCount];"); + sb.AppendLine(" for (var i = 0; i < stopCount; i++)"); + sb.AppendLine($" managedStops[i] = new global::{GradientBrushMarshalling.ImmutableGradientStopManagedTypeName}(stops[i].Offset, stops[i].Color.ToAvalonia());"); + foreach (var (abiType, accessor, _) in shapeFields) + { + sb.AppendLine($" hr = value.Get{accessor}(out var {FirstLower(accessor)});"); + sb.AppendLine(" if (hr < 0)"); + sb.AppendLine(" global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr);"); + } + var toArgs = string.Join(", ", new[] { "managedStops", "opacity", "transform: null", "transformOrigin: null", "(global::Avalonia.Media.GradientSpreadMethod)spreadMethod" } + .Concat(shapeFields.Select(f => $"{FirstLower(f.Accessor)}.ToAvalonia()"))); + sb.AppendLine($" return new global::{immutableManagedTypeName}({toArgs});"); + sb.AppendLine(" }"); + sb.AppendLine("}"); + sb.AppendLine(); + } + + private static string FirstLower(string value) => + value.Length == 0 ? value : char.ToLowerInvariant(value[0]) + value[1..]; + public static string EmitCommand(ProjectionIr ir) { var interfaceName = SimpleName(ir.CommandInterfaceName @@ -1594,9 +1879,71 @@ public static string EmitGeometryStructs(ProjectionIr ir) sb.AppendLine(" };"); sb.AppendLine("}"); sb.AppendLine(); + if (ir.GradientBrushInterfaceName is not null) + EmitGradientStructs(sb); return sb.ToString().TrimEnd() + Environment.NewLine; } + private static void EmitGradientStructs(StringBuilder sb) + { + var colorAbiName = GeometryMarshalling.All + .Single(geometry => geometry.Kind == MarshallingKind.Color).AbiName; + + sb.AppendLine("/// Blittable ABI mirror of Avalonia.RelativePoint."); + sb.AppendLine("/// Unit mirrors Avalonia.RelativeUnit: 0 relative, 1 absolute."); + sb.AppendLine("[StructLayout(LayoutKind.Sequential)]"); + sb.AppendLine("public struct AvnRelativePoint"); + sb.AppendLine("{"); + sb.AppendLine(" public double X;"); + sb.AppendLine(" public double Y;"); + sb.AppendLine(" public int Unit;"); + sb.AppendLine(); + sb.AppendLine(" public static AvnRelativePoint FromAvalonia(global::Avalonia.RelativePoint value) =>"); + sb.AppendLine(" new AvnRelativePoint { X = value.Point.X, Y = value.Point.Y, Unit = (int)value.Unit };"); + sb.AppendLine(); + sb.AppendLine(" public readonly global::Avalonia.RelativePoint ToAvalonia() =>"); + sb.AppendLine(" new global::Avalonia.RelativePoint(X, Y, (global::Avalonia.RelativeUnit)Unit);"); + sb.AppendLine("}"); + sb.AppendLine(); + sb.AppendLine("/// Blittable ABI mirror of Avalonia.RelativeScalar."); + sb.AppendLine("/// Unit mirrors Avalonia.RelativeUnit: 0 relative, 1 absolute."); + sb.AppendLine("[StructLayout(LayoutKind.Sequential)]"); + sb.AppendLine("public struct AvnRelativeScalar"); + sb.AppendLine("{"); + sb.AppendLine(" public double Scalar;"); + sb.AppendLine(" public int Unit;"); + sb.AppendLine(); + sb.AppendLine(" public static AvnRelativeScalar FromAvalonia(global::Avalonia.RelativeScalar value) =>"); + sb.AppendLine(" new AvnRelativeScalar { Scalar = value.Scalar, Unit = (int)value.Unit };"); + sb.AppendLine(); + sb.AppendLine(" public readonly global::Avalonia.RelativeScalar ToAvalonia() =>"); + sb.AppendLine(" new global::Avalonia.RelativeScalar(Scalar, (global::Avalonia.RelativeUnit)Unit);"); + sb.AppendLine("}"); + sb.AppendLine(); + sb.AppendLine("/// Blittable ABI mirror of a single gradient stop (offset plus packed colour)."); + sb.AppendLine("[StructLayout(LayoutKind.Sequential)]"); + sb.AppendLine("public struct AvnGradientStop"); + sb.AppendLine("{"); + sb.AppendLine(" public double Offset;"); + sb.AppendLine($" public {colorAbiName} Color;"); + sb.AppendLine(); + sb.AppendLine($" public static AvnGradientStop FromAvalonia(global::{GradientBrushMarshalling.GradientStopManagedTypeName} value) =>"); + sb.AppendLine($" new AvnGradientStop {{ Offset = value.Offset, Color = {colorAbiName}.FromAvalonia(value.Color) }};"); + sb.AppendLine("}"); + sb.AppendLine(); + sb.AppendLine($"/// Fixed-capacity buffer of up to {GradientBrushMarshalling.MaxStops} entries."); + sb.AppendLine("/// "); + sb.AppendLine("/// Gradient brushes with more stops than this cannot cross the ABI; the count actually in"); + sb.AppendLine("/// use is carried separately by IAvnGradientBrush.GetStopCount."); + sb.AppendLine("/// "); + sb.AppendLine($"[System.Runtime.CompilerServices.InlineArray({GradientBrushMarshalling.MaxStops})]"); + sb.AppendLine("public struct AvnGradientStopBuffer"); + sb.AppendLine("{"); + sb.AppendLine(" private AvnGradientStop _element0;"); + sb.AppendLine("}"); + sb.AppendLine(); + } + public static string EmitCollection(ProjectionIr ir, ProjectedProperty collection) { var root = ir.Types.Single(t => t.Kind == ProjectedTypeKind.Class && t.BaseFullName is null); diff --git a/projection/Avalonia.Projection.Generator/NativeHeaderEmitter.cs b/projection/Avalonia.Projection.Generator/NativeHeaderEmitter.cs index ad9da44..a68d830 100644 --- a/projection/Avalonia.Projection.Generator/NativeHeaderEmitter.cs +++ b/projection/Avalonia.Projection.Generator/NativeHeaderEmitter.cs @@ -38,6 +38,14 @@ public static string Emit(ProjectionIr ir) .Concat(types.Select(type => type.Name)) .Concat(statics.Select(group => SimpleName(group.Key))) .Concat(ir.BrushInterfaceName is null ? [] : new[] { SimpleName(ir.BrushInterfaceName) }) + .Concat(ir.GradientBrushInterfaceName is null + ? [] + : new[] + { + SimpleName(ir.GradientBrushInterfaceName), + SimpleName(ir.LinearGradientBrushInterfaceName!), + SimpleName(ir.RadialGradientBrushInterfaceName!), + }) .Concat(ir.CommandInterfaceName is null ? [] : new[] @@ -107,6 +115,36 @@ public static string Emit(ProjectionIr ir) sb.AppendLine("} AvnOptionalTimeSpan;"); sb.AppendLine(); + if (ir.GradientBrushInterfaceName is not null) + { + var colorAbiName = GeometryMarshalling.All + .Single(geometry => geometry.Kind == MarshallingKind.Color).AbiName; + sb.AppendLine("/* Blittable ABI mirror of Avalonia.RelativePoint. unit: 0 relative, 1 absolute. */"); + sb.AppendLine("typedef struct AvnRelativePoint {"); + sb.AppendLine(" double x;"); + sb.AppendLine(" double y;"); + sb.AppendLine(" int32_t unit;"); + sb.AppendLine("} AvnRelativePoint;"); + sb.AppendLine(); + sb.AppendLine("/* Blittable ABI mirror of Avalonia.RelativeScalar. unit: 0 relative, 1 absolute. */"); + sb.AppendLine("typedef struct AvnRelativeScalar {"); + sb.AppendLine(" double scalar;"); + sb.AppendLine(" int32_t unit;"); + sb.AppendLine("} AvnRelativeScalar;"); + sb.AppendLine(); + sb.AppendLine("/* Blittable ABI mirror of a single gradient stop (offset plus packed colour). */"); + sb.AppendLine("typedef struct AvnGradientStop {"); + sb.AppendLine(" double offset;"); + sb.AppendLine($" {colorAbiName} color;"); + sb.AppendLine("} AvnGradientStop;"); + sb.AppendLine(); + sb.AppendLine($"/* Fixed-capacity buffer of up to {GradientBrushMarshalling.MaxStops} AvnGradientStop entries. */"); + sb.AppendLine("typedef struct AvnGradientStopBuffer {"); + sb.AppendLine($" AvnGradientStop stops[{GradientBrushMarshalling.MaxStops}];"); + sb.AppendLine("} AvnGradientStopBuffer;"); + sb.AppendLine(); + } + sb.AppendLine("/* Tagged scalar carrying object? command parameters. */"); sb.AppendLine("/* tag: 0 none, 1 utf16, 2 i32, 3 f64, 4 bool. */"); sb.AppendLine("typedef struct AvnVariant {"); @@ -168,6 +206,45 @@ public static string Emit(ProjectionIr ir) EndInterface(sb, brushName, 5); } + if (ir.GradientBrushInterfaceName is { } gradientBrushInterfaceName) + { + var gradientName = SimpleName(gradientBrushInterfaceName); + var linearName = SimpleName(ir.LinearGradientBrushInterfaceName!); + var radialName = SimpleName(ir.RadialGradientBrushInterfaceName!); + + EmitIid(sb, gradientName, ir.GradientBrushInterfaceIid!, 1); + BeginInterface(sb, gradientName); + EmitSlot(sb, 3, "get_opacity", gradientName, ["double* value"]); + EmitSlot(sb, 4, "get_spread_method", gradientName, ["int32_t* value"]); + EmitSlot(sb, 5, "get_stop_count", gradientName, ["int32_t* value"]); + EmitSlot(sb, 6, "get_stops", gradientName, ["AvnGradientStopBuffer* value"]); + EndInterface(sb, gradientName, 7); + + // Derived gradient interfaces flatten the base's four slots ahead of their own, + // mirroring the single-inheritance vtable layout produced for control interfaces. + EmitIid(sb, linearName, ir.LinearGradientBrushInterfaceIid!, 1); + BeginInterface(sb, linearName); + EmitSlot(sb, 3, "get_opacity", linearName, ["double* value"]); + EmitSlot(sb, 4, "get_spread_method", linearName, ["int32_t* value"]); + EmitSlot(sb, 5, "get_stop_count", linearName, ["int32_t* value"]); + EmitSlot(sb, 6, "get_stops", linearName, ["AvnGradientStopBuffer* value"]); + EmitSlot(sb, 7, "get_start_point", linearName, ["AvnRelativePoint* value"]); + EmitSlot(sb, 8, "get_end_point", linearName, ["AvnRelativePoint* value"]); + EndInterface(sb, linearName, 9); + + EmitIid(sb, radialName, ir.RadialGradientBrushInterfaceIid!, 1); + BeginInterface(sb, radialName); + EmitSlot(sb, 3, "get_opacity", radialName, ["double* value"]); + EmitSlot(sb, 4, "get_spread_method", radialName, ["int32_t* value"]); + EmitSlot(sb, 5, "get_stop_count", radialName, ["int32_t* value"]); + EmitSlot(sb, 6, "get_stops", radialName, ["AvnGradientStopBuffer* value"]); + EmitSlot(sb, 7, "get_center", radialName, ["AvnRelativePoint* value"]); + EmitSlot(sb, 8, "get_gradient_origin", radialName, ["AvnRelativePoint* value"]); + EmitSlot(sb, 9, "get_radius_x", radialName, ["AvnRelativeScalar* value"]); + EmitSlot(sb, 10, "get_radius_y", radialName, ["AvnRelativeScalar* value"]); + EndInterface(sb, radialName, 11); + } + if (ir.CommandInterfaceName is { } commandInterfaceName) { var commandName = SimpleName(commandInterfaceName); @@ -434,6 +511,41 @@ public static string Emit(ProjectionIr ir) "IAvnControlFactory", [$"{colorAbiName} color", "double opacity", $"{brushName}** value"]); } + if (ir.GradientBrushInterfaceName is not null) + { + var linearName = SimpleName(ir.LinearGradientBrushInterfaceName!); + var radialName = SimpleName(ir.RadialGradientBrushInterfaceName!); + EmitSlot( + sb, + factorySlot++, + Snake(GradientBrushMarshalling.CreateLinearFactoryMethodName), + "IAvnControlFactory", + [ + "double opacity", + "int32_t spread_method", + "int32_t stop_count", + "AvnGradientStopBuffer stops", + "AvnRelativePoint start_point", + "AvnRelativePoint end_point", + $"{linearName}** value", + ]); + EmitSlot( + sb, + factorySlot++, + Snake(GradientBrushMarshalling.CreateRadialFactoryMethodName), + "IAvnControlFactory", + [ + "double opacity", + "int32_t spread_method", + "int32_t stop_count", + "AvnGradientStopBuffer stops", + "AvnRelativePoint center", + "AvnRelativePoint gradient_origin", + "AvnRelativeScalar radius_x", + "AvnRelativeScalar radius_y", + $"{radialName}** value", + ]); + } EndInterface(sb, "IAvnControlFactory", factorySlot); sb.AppendLine("#endif /* AVALONIA_RUST_ABI_H */"); diff --git a/projection/Avalonia.Projection.Ir/AvaloniaProjectionProfiles.cs b/projection/Avalonia.Projection.Ir/AvaloniaProjectionProfiles.cs index 5613c66..ef975ed 100644 --- a/projection/Avalonia.Projection.Ir/AvaloniaProjectionProfiles.cs +++ b/projection/Avalonia.Projection.Ir/AvaloniaProjectionProfiles.cs @@ -137,7 +137,9 @@ public static class AvaloniaProjectionProfiles ["Avalonia.Host.Com.IAvnSector"] = 11, ["Avalonia.Host.Com.IAvnLayoutTransformControl"] = 11, ["Avalonia.Host.Com.IAvnThemeVariantScope"] = 11, - ["Avalonia.Host.Com.IAvnControlFactory"] = 13, + ["Avalonia.Host.Com.IAvnControlFactory"] = 14, + // Gradient brush wave: the factory grows CreateLinearGradientBrush/ + // CreateRadialGradientBrush slots, so it republishes at version 14. // Wave P. Payload-carrying replacements for the previously payload-less // handlers: the handler Invoke slots change shape, so each handler mints a // new IID at version 2. The advise/unadvise slots on the control interfaces diff --git a/projection/Avalonia.Projection.Ir/BrushMarshalling.cs b/projection/Avalonia.Projection.Ir/BrushMarshalling.cs index 2ebb58b..8baa7cd 100644 --- a/projection/Avalonia.Projection.Ir/BrushMarshalling.cs +++ b/projection/Avalonia.Projection.Ir/BrushMarshalling.cs @@ -4,11 +4,14 @@ namespace Avalonia.Projection.Ir; /// The object-model projection of Avalonia.Media.IBrush. /// /// -/// A brush crosses nano-COM as a solid colour only: the ABI interface carries a packed -/// AvnColor plus the brush opacity and nothing else. Gradient brushes, -/// DrawingBrush and VisualBrush are deliberately not projected — reading one +/// IAvnBrush itself still carries a solid colour only: a packed AvnColor +/// plus the brush opacity and nothing else, unchanged since it first shipped. Linear and radial +/// gradient brushes are projected as an additive sibling capability (see +/// ) that a gradient brush object also implements; +/// DrawingBrush, VisualBrush, ImageBrush and conic gradients remain out of +/// scope — reading any of those, or calling IAvnBrush.GetColor on a real gradient object, /// fails with AVN_E_NONSOLIDBRUSH rather than silently degrading to a nearest colour. -/// The interface is read-only because the managed side hands out immutable brushes; new +/// The interface is read-only because the managed side hands out immutable brushes; new solid /// brushes are minted through IAvnControlFactory.CreateSolidColorBrush. /// public static class BrushMarshalling diff --git a/projection/Avalonia.Projection.Ir/ClrTypeExtractor.cs b/projection/Avalonia.Projection.Ir/ClrTypeExtractor.cs index f52cca4..8993597 100644 --- a/projection/Avalonia.Projection.Ir/ClrTypeExtractor.cs +++ b/projection/Avalonia.Projection.Ir/ClrTypeExtractor.cs @@ -40,6 +40,9 @@ public static ProjectionIr Extract(IEnumerable sourceTypes, ProjectionPoli var brushInterfaceName = BrushMarshalling.QualifiedInterfaceName(policy.ProjectionNamespace); var usesBrush = types.Any(type => type.Properties.Any(property => property.Kind == MarshallingKind.Brush)); + var gradientBrushInterfaceName = GradientBrushMarshalling.QualifiedGradientInterfaceName(policy.ProjectionNamespace); + var linearGradientBrushInterfaceName = GradientBrushMarshalling.QualifiedLinearInterfaceName(policy.ProjectionNamespace); + var radialGradientBrushInterfaceName = GradientBrushMarshalling.QualifiedRadialInterfaceName(policy.ProjectionNamespace); var commandInterfaceName = CommandMarshalling.QualifiedInterfaceName(policy.ProjectionNamespace); var commandHandlerInterfaceName = CommandMarshalling.QualifiedHandlerInterfaceName(policy.ProjectionNamespace); var usesCommand = types.Any(type => @@ -91,6 +94,18 @@ public static ProjectionIr Extract(IEnumerable sourceTypes, ProjectionPoli ? CreateDeterministicIid(brushInterfaceName, policy.GetAbiVersion(brushInterfaceName)) : null, BrushAbiVersion = policy.GetAbiVersion(brushInterfaceName), + GradientBrushInterfaceName = usesBrush ? gradientBrushInterfaceName : null, + GradientBrushInterfaceIid = usesBrush + ? CreateDeterministicIid(gradientBrushInterfaceName, 1) + : null, + LinearGradientBrushInterfaceName = usesBrush ? linearGradientBrushInterfaceName : null, + LinearGradientBrushInterfaceIid = usesBrush + ? CreateDeterministicIid(linearGradientBrushInterfaceName, 1) + : null, + RadialGradientBrushInterfaceName = usesBrush ? radialGradientBrushInterfaceName : null, + RadialGradientBrushInterfaceIid = usesBrush + ? CreateDeterministicIid(radialGradientBrushInterfaceName, 1) + : null, CommandInterfaceName = usesCommand ? commandInterfaceName : null, CommandInterfaceIid = usesCommand ? CreateDeterministicIid(commandInterfaceName, policy.GetAbiVersion(commandInterfaceName)) diff --git a/projection/Avalonia.Projection.Ir/GradientBrushMarshalling.cs b/projection/Avalonia.Projection.Ir/GradientBrushMarshalling.cs new file mode 100644 index 0000000..972af2b --- /dev/null +++ b/projection/Avalonia.Projection.Ir/GradientBrushMarshalling.cs @@ -0,0 +1,62 @@ +namespace Avalonia.Projection.Ir; + +/// +/// The object-model projection of Avalonia.Media.IGradientBrush and its two supported +/// concrete shapes, ILinearGradientBrush and IRadialGradientBrush. +/// +/// +/// This is an additive capability layered next to : the existing +/// IAvnBrush (solid colour) interface, IID and vtable are unchanged. A gradient brush +/// projects as a second COM object that implements IAvnBrush (so it still satisfies every +/// brush-typed property slot) alongside the new IAvnGradientBrush capability, queryable +/// with a standard nano-COM QueryInterface. Calling IAvnBrush.GetColor on a real gradient +/// object still fails with AVN_E_NONSOLIDBRUSH — only GetOpacity and the new +/// gradient members are meaningful — so a caller that only understands solid brushes keeps +/// working unchanged. ConicGradientBrush, DrawingBrush, VisualBrush and +/// ImageBrush remain out of scope and keep failing the same way. +/// +/// Gradient stops cross as a fixed-capacity inline buffer ( entries) rather +/// than a dynamically sized collection, keeping the ABI shape a single blittable struct; a brush +/// with more stops than that is rejected when it is minted for the ABI. +/// +public static class GradientBrushMarshalling +{ + /// The maximum number of gradient stops a projected gradient brush can carry. + public const int MaxStops = 8; + + public const string GradientManagedTypeName = "Avalonia.Media.IGradientBrush"; + public const string LinearManagedTypeName = "Avalonia.Media.ILinearGradientBrush"; + public const string RadialManagedTypeName = "Avalonia.Media.IRadialGradientBrush"; + public const string GradientStopManagedTypeName = "Avalonia.Media.IGradientStop"; + + public const string ImmutableLinearManagedTypeName = + "Avalonia.Media.Immutable.ImmutableLinearGradientBrush"; + public const string ImmutableRadialManagedTypeName = + "Avalonia.Media.Immutable.ImmutableRadialGradientBrush"; + public const string ImmutableGradientStopManagedTypeName = + "Avalonia.Media.Immutable.ImmutableGradientStop"; + + /// The unqualified base capability interface name shared by C, C#, and Rust. + public const string GradientInterfaceName = "IAvnGradientBrush"; + + /// The unqualified linear-gradient interface name shared by C, C#, and Rust. + public const string LinearInterfaceName = "IAvnLinearGradientBrush"; + + /// The unqualified radial-gradient interface name shared by C, C#, and Rust. + public const string RadialInterfaceName = "IAvnRadialGradientBrush"; + + /// The factory method that mints a linear gradient brush. + public const string CreateLinearFactoryMethodName = "CreateLinearGradientBrush"; + + /// The factory method that mints a radial gradient brush. + public const string CreateRadialFactoryMethodName = "CreateRadialGradientBrush"; + + public static string QualifiedGradientInterfaceName(string projectionNamespace) => + $"{projectionNamespace}.{GradientInterfaceName}"; + + public static string QualifiedLinearInterfaceName(string projectionNamespace) => + $"{projectionNamespace}.{LinearInterfaceName}"; + + public static string QualifiedRadialInterfaceName(string projectionNamespace) => + $"{projectionNamespace}.{RadialInterfaceName}"; +} diff --git a/projection/Avalonia.Projection.Ir/ProjectionIr.cs b/projection/Avalonia.Projection.Ir/ProjectionIr.cs index 5fab4c1..bb082ee 100644 --- a/projection/Avalonia.Projection.Ir/ProjectionIr.cs +++ b/projection/Avalonia.Projection.Ir/ProjectionIr.cs @@ -6,7 +6,7 @@ namespace Avalonia.Projection.Ir; public sealed partial class ProjectionIr { public const int MinimumVersion = 1; - public const int CurrentVersion = 16; + public const int CurrentVersion = 17; public int Version { get; init; } = CurrentVersion; public string? SourceAssembly { get; init; } @@ -21,6 +21,18 @@ public sealed partial class ProjectionIr public string? BrushInterfaceIid { get; init; } public int BrushAbiVersion { get; init; } = 1; + /// + /// The projected gradient-brush capability interfaces (version 17), present only when a + /// member marshals as . Additive to + /// : the solid-brush interface, IID and vtable are unchanged. + /// + public string? GradientBrushInterfaceName { get; init; } + public string? GradientBrushInterfaceIid { get; init; } + public string? LinearGradientBrushInterfaceName { get; init; } + public string? LinearGradientBrushInterfaceIid { get; init; } + public string? RadialGradientBrushInterfaceName { get; init; } + public string? RadialGradientBrushInterfaceIid { get; init; } + /// /// The projected command interface, present only when a member marshals as /// . diff --git a/rust/.avalonia-projection.owned.json b/rust/.avalonia-projection.owned.json index 5de7d23..79468c0 100644 --- a/rust/.avalonia-projection.owned.json +++ b/rust/.avalonia-projection.owned.json @@ -7,7 +7,7 @@ }, { "path": "projection.ir.json", - "sha256": "780eb004b70506dc1a826f1d67a9f83777b270d971bb211cd49ddbb5a9d5b686" + "sha256": "eb22a33ab7409ee8b4c3f90f17d7d1aac3b625e649ba09ed4cd3cd36a8220e42" } ] } diff --git a/rust/COMPATIBILITY.md b/rust/COMPATIBILITY.md index 148ed70..2f3c1d2 100644 --- a/rust/COMPATIBILITY.md +++ b/rust/COMPATIBILITY.md @@ -58,6 +58,15 @@ bindgen can emit the handler interface and its CCW constructor without hardcoding the identity. Both fields are additive; a reader that ignores them sees the same vtables it always did. +Version 17 adds six optional root-level members, present whenever any member +marshals as `MarshallingKind.Brush`: `gradientBrushInterfaceName`/`Iid`, +`linearGradientBrushInterfaceName`/`Iid` and +`radialGradientBrushInterfaceName`/`Iid`. They are additive to +`BrushInterfaceName`/`BrushInterfaceIid` — the solid-brush interface, IID and +vtable are unchanged — and no `MarshallingKind` ordinal moves. A reader that +ignores the six new fields sees the same IR it always did; only a generator +that projects gradient brushes needs them. + Version 13 adds two optional members, both host-side only. A projected property and an attached property may carry `stringConverterTypeName`, naming the host type that converts the member between its CLR type and the UTF-16 string in its @@ -74,7 +83,7 @@ with a host from another. ## Native ABI -The overlay-chrome pass widens the leaf `IAvnWindow` ABI from 7 to 8 to expose only the safe, non-nullable window work-area and dialog members. This stays local to the window leaf: `IAvnContentControl` remains at 6 and the factory remains at 13, while blockers such as `Icon`, `Position`, nullable geometry, and cancelable `Closing` payloads stay out of scope. +The overlay-chrome pass widens the leaf `IAvnWindow` ABI from 7 to 8 to expose only the safe, non-nullable window work-area and dialog members. This stays local to the window leaf: `IAvnContentControl` remains at 6 and the factory remained at 13 as of this wave (the later gradient-brush pass below moves it again), while blockers such as `Icon`, `Position`, nullable geometry, and cancelable `Closing` payloads stay out of scope. The wave P event-payload pass grows `IAvnControl` with `KeyUp`, `GotFocus` and `LostFocus`, so `IAvnControl` and every interface below it republish on @@ -88,6 +97,15 @@ old/new value pair as fields. The advise/unadvise slots on the control interfaces keep their signatures throughout; only the handler identities move. Consumers compiled against the version 1 handlers fail `QueryInterface` loudly (`E_NOINTERFACE`) rather than being called through a stale vtable. + +The gradient-brush pass adds three brand-new interfaces — +`IAvnGradientBrush`, `IAvnLinearGradientBrush` and `IAvnRadialGradientBrush`, +each publishing at version 1 — and grows `IAvnControlFactory` with +`create_linear_gradient_brush`/`create_radial_gradient_brush`, so the factory +republishes on a fresh IID (from 13). `IAvnBrush` itself is untouched: it +keeps its published IID and vtable, and every gradient object also answers +`QueryInterface` for it. No other interface moves. + After an intentional ABI wave, regenerate the frozen snapshot with `pwsh ./rust/regenerate-and-build.ps1 -UpdateAbiBaseline` in the same change so `abi-baseline.json` stays the reviewed record of what is released. diff --git a/rust/MARSHALLING.md b/rust/MARSHALLING.md index 8b7679e..ab46c1a 100644 --- a/rust/MARSHALLING.md +++ b/rust/MARSHALLING.md @@ -150,9 +150,9 @@ on. Inbound, every brush is materialised as always a solid brush by construction and anything a source brush carried beyond colour and opacity (transforms, gradient stops) is dropped rather than guessed. -Gradients, `DrawingBrush` and `VisualBrush` are out of scope for this ABI. A -future wave that needs them must add a separately named, separately versioned -interface rather than widening `IAvnBrush`. +`DrawingBrush` and `VisualBrush` remain out of scope for this ABI. A future wave +that needs them must add a separately named, separately versioned interface +rather than widening `IAvnBrush`, following the pattern gradients use below. In safe Rust the brush is a plain value; only crossing the ABI needs the factory: @@ -172,6 +172,75 @@ so `None` clears the property and a `Brush` needs no `Some`. `Color::rgb` is a `const` opaque-colour constructor, so a consumer can define a palette as constants. +## Gradient brushes + +Linear and radial gradients follow the sibling-interface pattern rather than +widening `IAvnBrush`: `IAvnGradientBrush` carries the members every gradient +shares (`Opacity`, `SpreadMethod`, `StopCount`, `Stops`), and +`IAvnLinearGradientBrush`/`IAvnRadialGradientBrush` each derive from it and add +their own geometry (`StartPoint`/`EndPoint`, or `Center`/`GradientOrigin`/ +`RadiusX`/`RadiusY`). Every gradient object also answers `QueryInterface` for +plain `IAvnBrush`, so it can be assigned anywhere a solid brush could be — +reading `Color` back off it is what returns `AVN_E_NONSOLIDBRUSH`. + +Stops cross the ABI as a fixed-capacity buffer rather than a COM collection: + +```c +struct AvnGradientStop { double offset; AvnColor color; }; +struct AvnGradientStopBuffer { AvnGradientStop stops[8]; }; +``` + +Eight stops is enough for chrome gradients without a heap-allocated +marshalled array; `StopCount` says how many of the eight slots are populated, +so a wrapper must always read count and buffer together and never assume all +eight are meaningful. `IAvnControlFactory` mints both shapes: + +```c +AvnHResult (AVN_CALL *create_linear_gradient_brush)( + IAvnControlFactory* self, double opacity, int32_t spreadMethod, + int32_t stopCount, AvnGradientStopBuffer stops, + AvnRelativePoint startPoint, AvnRelativePoint endPoint, + IAvnLinearGradientBrush** value); + +AvnHResult (AVN_CALL *create_radial_gradient_brush)( + IAvnControlFactory* self, double opacity, int32_t spreadMethod, + int32_t stopCount, AvnGradientStopBuffer stops, + AvnRelativePoint center, AvnRelativePoint gradientOrigin, + AvnRelativeScalar radiusX, AvnRelativeScalar radiusY, + IAvnRadialGradientBrush** value); +``` + +`AvnRelativePoint`/`AvnRelativeScalar` carry a `RelativeUnit` ordinal +(`Relative = 0`, `Absolute = 1`) alongside their coordinates, mirroring +`Avalonia.RelativePoint`/`RelativeUnit`. Growing `IAvnControlFactory` to add +these two slots required minting a new IID for it (the ABI-baseline check +treats any slot-list change under a published IID as a break, even an +additive one) — see [Versioning of the widened vtables](#versioning-of-the-widened-vtables) +for the general rule. + +In safe Rust, `LinearGradientBrush` and `RadialGradientBrush` are plain values +alongside `Brush`, and `Paint` is the enum that spans all three shapes a +control property can hold: + +```rust +let sunset = LinearGradientBrush::new( + vec![ + GradientStop::new(0.0, Color::rgb(0xFF, 0x45, 0x00)), + GradientStop::new(1.0, Color::rgb(0xFF, 0xD7, 0x00)), + ], + RelativePoint::new(0.0, 0.0, RelativeUnit::Relative), + RelativePoint::new(1.0, 1.0, RelativeUnit::Relative), +); +let paint: Paint = sunset.into(); +``` + +`Paint`, `LinearGradientBrush` and `RadialGradientBrush` are additive: no +existing `Brush`-typed property getter or setter was rewired to accept or +return `Paint`. Reading `Background`/`BorderBrush`/`Foreground` off a +gradient-backed control still fails with `AVN_E_NONSOLIDBRUSH` today, matching +"reads fail rather than degrade" above; wiring chrome properties to accept a +`Paint` is left to a future wave. + ## Chrome members The chrome wave allowlists the members that make a control look like part of an @@ -631,6 +700,12 @@ by `query_interface` only. `IAvnBrush` is brand new, so it starts at version 1. The collection interfaces and the event handler interfaces are unchanged, because they carry interface pointers rather than the widened layouts. +The gradient wave grows `IAvnControlFactory` again, for +`create_linear_gradient_brush` and `create_radial_gradient_brush`, so it +publishes another new IID. `IAvnGradientBrush`, `IAvnLinearGradientBrush` and +`IAvnRadialGradientBrush` are brand new, so each starts at version 1; `IAvnBrush` +itself is untouched and keeps the IID it published with. + `Decorator` sits between `Control` and `Border`. The chrome wave added members to `Border`, not to `Decorator`, and nothing was added to `Decorator`'s bases either, so `IAvnDecorator` keeps the version 3 IID it published with the layout wave even diff --git a/rust/README.md b/rust/README.md index 9518ec4..d4019cb 100644 --- a/rust/README.md +++ b/rust/README.md @@ -35,6 +35,12 @@ only; a control-valued tip reads back as `null`. See `RefreshContainer` are projected too. Shapes (`Rectangle`, `Ellipse`, `Line`, `Path`, `Polygon`, `Polyline`, `Arc`, `Sector`) are projected too. Fill/Stroke are brushes; `Path.Data` is path markup. +`LinearGradientBrush` and `RadialGradientBrush` are projected as additive, +directly-constructible safe types built on the `IAvnControlFactory` creators +`create_linear_gradient_brush`/`create_radial_gradient_brush`; a `Paint` enum +spans solid and gradient shapes. Existing `Brush`-typed properties +(`Background`, `BorderBrush`, `Foreground`) are unchanged and stay solid-only; +see [Gradient brushes](MARSHALLING.md#gradient-brushes). `Carousel`, `TransitioningContentControl`, `Label`, `Separator`, `GroupBox`, `UserControl` and `LayoutTransformControl` are projected too. `Calendar` and `CalendarDatePicker` are projected too. Calendar days cross as diff --git a/rust/abi-baseline.json b/rust/abi-baseline.json index 668e414..59770e0 100644 --- a/rust/abi-baseline.json +++ b/rust/abi-baseline.json @@ -1,7 +1,7 @@ { "schemaVersion": 3, "kind": "released", - "projectionIrVersion": 16, + "projectionIrVersion": 17, "producerPin": "9654332a79f637473da96054f75b2a16deaa557e", "abiDefinitions": { "hresult": "int32_t", @@ -42,6 +42,28 @@ } ] }, + { + "name": "AvnGradientStop", + "fields": [ + { + "type": "double", + "name": "offset" + }, + { + "type": "AvnColor", + "name": "color" + } + ] + }, + { + "name": "AvnGradientStopBuffer", + "fields": [ + { + "type": "AvnGradientStop", + "name": "stops[8]" + } + ] + }, { "name": "AvnGuid", "fields": [ @@ -227,6 +249,36 @@ } ] }, + { + "name": "AvnRelativePoint", + "fields": [ + { + "type": "double", + "name": "x" + }, + { + "type": "double", + "name": "y" + }, + { + "type": "int32_t", + "name": "unit" + } + ] + }, + { + "name": "AvnRelativeScalar", + "fields": [ + { + "type": "double", + "name": "scalar" + }, + { + "type": "int32_t", + "name": "unit" + } + ] + }, { "name": "AvnSize", "fields": [ @@ -921,6 +973,141 @@ } ] }, + { + "name": "get_spread_method", + "callingConvention": "AVN_CALL", + "returnType": "AvnHResult", + "parameters": [ + { + "type": "$self", + "name": "self" + }, + { + "type": "int32_t*", + "name": "value" + } + ] + }, + { + "name": "get_stop_count", + "callingConvention": "AVN_CALL", + "returnType": "AvnHResult", + "parameters": [ + { + "type": "$self", + "name": "self" + }, + { + "type": "int32_t*", + "name": "value" + } + ] + }, + { + "name": "get_stops", + "callingConvention": "AVN_CALL", + "returnType": "AvnHResult", + "parameters": [ + { + "type": "$self", + "name": "self" + }, + { + "type": "AvnGradientStopBuffer*", + "name": "value" + } + ] + }, + { + "name": "get_start_point", + "callingConvention": "AVN_CALL", + "returnType": "AvnHResult", + "parameters": [ + { + "type": "$self", + "name": "self" + }, + { + "type": "AvnRelativePoint*", + "name": "value" + } + ] + }, + { + "name": "get_end_point", + "callingConvention": "AVN_CALL", + "returnType": "AvnHResult", + "parameters": [ + { + "type": "$self", + "name": "self" + }, + { + "type": "AvnRelativePoint*", + "name": "value" + } + ] + }, + { + "name": "get_center", + "callingConvention": "AVN_CALL", + "returnType": "AvnHResult", + "parameters": [ + { + "type": "$self", + "name": "self" + }, + { + "type": "AvnRelativePoint*", + "name": "value" + } + ] + }, + { + "name": "get_gradient_origin", + "callingConvention": "AVN_CALL", + "returnType": "AvnHResult", + "parameters": [ + { + "type": "$self", + "name": "self" + }, + { + "type": "AvnRelativePoint*", + "name": "value" + } + ] + }, + { + "name": "get_radius_x", + "callingConvention": "AVN_CALL", + "returnType": "AvnHResult", + "parameters": [ + { + "type": "$self", + "name": "self" + }, + { + "type": "AvnRelativeScalar*", + "name": "value" + } + ] + }, + { + "name": "get_radius_y", + "callingConvention": "AVN_CALL", + "returnType": "AvnHResult", + "parameters": [ + { + "type": "$self", + "name": "self" + }, + { + "type": "AvnRelativeScalar*", + "name": "value" + } + ] + }, { "name": "execute", "callingConvention": "AVN_CALL", @@ -17830,6 +18017,92 @@ "name": "value" } ] + }, + { + "name": "create_linear_gradient_brush", + "callingConvention": "AVN_CALL", + "returnType": "AvnHResult", + "parameters": [ + { + "type": "$self", + "name": "self" + }, + { + "type": "double", + "name": "opacity" + }, + { + "type": "int32_t", + "name": "spread_method" + }, + { + "type": "int32_t", + "name": "stop_count" + }, + { + "type": "AvnGradientStopBuffer", + "name": "stops" + }, + { + "type": "AvnRelativePoint", + "name": "start_point" + }, + { + "type": "AvnRelativePoint", + "name": "end_point" + }, + { + "type": "IAvnLinearGradientBrush**", + "name": "value" + } + ] + }, + { + "name": "create_radial_gradient_brush", + "callingConvention": "AVN_CALL", + "returnType": "AvnHResult", + "parameters": [ + { + "type": "$self", + "name": "self" + }, + { + "type": "double", + "name": "opacity" + }, + { + "type": "int32_t", + "name": "spread_method" + }, + { + "type": "int32_t", + "name": "stop_count" + }, + { + "type": "AvnGradientStopBuffer", + "name": "stops" + }, + { + "type": "AvnRelativePoint", + "name": "center" + }, + { + "type": "AvnRelativePoint", + "name": "gradient_origin" + }, + { + "type": "AvnRelativeScalar", + "name": "radius_x" + }, + { + "type": "AvnRelativeScalar", + "name": "radius_y" + }, + { + "type": "IAvnRadialGradientBrush**", + "name": "value" + } + ] } ], "irMemberCatalog": [ @@ -18545,15 +18818,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -18570,7 +18834,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -18580,6 +18843,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -18647,7 +18911,16 @@ 168, 169, 170, - 171 + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180 ], "irBases": [ "IAvnAvaloniaObject", @@ -18722,7 +18995,7 @@ 0, 1, 2, - 48 + 57 ] }, { @@ -18734,7 +19007,7 @@ 0, 1, 2, - 47 + 56 ] }, { @@ -18746,15 +19019,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -18771,7 +19035,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -18781,6 +19044,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -18827,15 +19091,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -18916,7 +19180,16 @@ 258, 259, 260, - 261 + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270 ], "irBases": [ "IAvnAvaloniaObject", @@ -19150,8 +19423,8 @@ 0, 1, 2, - 70, - 71 + 79, + 80 ], "irBases": [ "IAvnAvaloniaObject" @@ -19166,15 +19439,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -19191,7 +19455,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -19201,6 +19464,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -19247,23 +19511,32 @@ 147, 148, 149, - 262, - 263, - 198, - 199, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 271, + 272, + 207, + 208, 181, - 264, - 265, - 266 + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 273, + 274, + 275 ], "irBases": [ "IAvnAvaloniaObject", @@ -19349,15 +19622,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -19374,7 +19638,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -19384,6 +19647,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -19430,15 +19694,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -19458,15 +19722,15 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 275, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 276, 277, 278, @@ -19482,7 +19746,16 @@ 288, 289, 290, - 291 + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300 ], "irBases": [ "IAvnAvaloniaObject", @@ -19586,15 +19859,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -19611,7 +19875,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -19621,6 +19884,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -19667,15 +19931,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -19695,24 +19959,33 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 292, - 293, - 294, - 295, - 296, - 297, - 298, - 299, - 300, - 301 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310 ], "irBases": [ "IAvnAvaloniaObject", @@ -19801,15 +20074,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -19826,7 +20090,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -19836,6 +20099,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -19882,15 +20146,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -19910,15 +20174,15 @@ 197, 198, 199, - 302, - 303, - 304, - 305, - 306, - 307, - 308, - 309, - 310, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 311, 312, 313, @@ -19941,7 +20205,16 @@ 330, 331, 332, - 333 + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342 ], "irBases": [ "IAvnAvaloniaObject", @@ -20036,15 +20309,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -20061,7 +20325,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -20071,6 +20334,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -20117,15 +20381,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -20145,50 +20409,59 @@ 197, 198, 199, - 325, - 321, - 322, - 323, - 324, - 326, - 327, - 302, - 303, - 212, - 213, - 304, - 305, - 318, - 319, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 334, + 330, + 331, + 332, + 333, 335, 336, - 337, - 218, - 219, - 223, - 224, - 338, - 339, - 225, - 226, - 271, - 272, - 273, - 274, - 308, - 309, - 310, 311, - 60, - 340, - 341, - 342, + 312, + 221, + 222, + 313, + 314, + 327, + 328, 343, 344, 345, 346, - 347 + 227, + 228, + 232, + 233, + 347, + 348, + 234, + 235, + 280, + 281, + 282, + 283, + 317, + 318, + 319, + 320, + 69, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356 ], "irBases": [ "IAvnAvaloniaObject", @@ -20403,15 +20676,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -20428,7 +20692,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -20438,6 +20701,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -20484,9 +20748,18 @@ 147, 148, 149, - 348, - 172, - 173 + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 357, + 181, + 182 ], "irBases": [ "IAvnAvaloniaObject", @@ -20552,14 +20825,14 @@ 0, 1, 2, - 969, - 970, - 971, - 972, - 973, - 974, - 975, - 976 + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985 ] }, { @@ -20571,15 +20844,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -20596,7 +20860,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -20606,6 +20869,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -20652,15 +20916,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -20680,24 +20944,22 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 357, + 208, 358, 359, - 360, + 246, + 247, + 215, 216, - 217, + 360, 361, 362, 363, @@ -20705,14 +20967,25 @@ 365, 366, 367, - 261, 368, 369, + 225, + 226, 370, 371, 372, 373, - 374 + 374, + 375, + 376, + 270, + 377, + 378, + 379, + 380, + 381, + 382, + 383 ], "irBases": [ "IAvnAvaloniaObject", @@ -20814,15 +21087,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -20839,7 +21103,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -20849,6 +21112,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -20895,15 +21159,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -20923,15 +21187,15 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 275, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 276, 277, 278, @@ -20948,12 +21212,21 @@ 289, 290, 291, - 375, - 376, - 377, - 378, - 379, - 380 + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 384, + 385, + 386, + 387, + 388, + 389 ], "irBases": [ "IAvnAvaloniaObject", @@ -21050,15 +21323,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -21075,7 +21339,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -21085,6 +21348,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -21131,15 +21395,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -21159,24 +21423,22 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 357, + 208, 358, 359, - 360, + 246, + 247, + 215, 216, - 217, + 360, 361, 362, 363, @@ -21184,27 +21446,38 @@ 365, 366, 367, - 261, - 212, - 213, - 381, - 382, - 210, - 211, - 383, - 223, - 224, + 368, + 369, 225, 226, - 384, - 385, - 218, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 270, + 221, + 222, + 390, + 391, 219, - 60, - 386, - 259, - 387, - 255 + 220, + 392, + 232, + 233, + 234, + 235, + 393, + 394, + 227, + 228, + 69, + 395, + 268, + 396, + 264 ], "irBases": [ "IAvnAvaloniaObject", @@ -21336,15 +21609,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -21361,7 +21625,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -21371,6 +21634,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -21417,15 +21681,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -21445,16 +21709,25 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 388, - 389 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 397, + 398 ], "irBases": [ "IAvnAvaloniaObject", @@ -21539,10 +21812,10 @@ 0, 1, 2, - 36, - 37, - 38, - 39 + 45, + 46, + 47, + 48 ] }, { @@ -21554,15 +21827,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -21579,7 +21843,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -21589,6 +21852,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -21635,15 +21899,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -21663,23 +21927,23 @@ 197, 198, 199, - 390, - 391, - 392, - 393, - 394, - 395, - 267, - 268, - 396, - 397, - 398, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 399, 400, 401, 402, 403, 404, + 276, + 277, 405, 406, 407, @@ -21696,7 +21960,16 @@ 418, 419, 420, - 421 + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430 ], "irBases": [ "IAvnAvaloniaObject", @@ -21793,15 +22066,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -21818,7 +22082,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -21828,6 +22091,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -21874,15 +22138,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -21902,15 +22166,15 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 275, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 276, 277, 278, @@ -21927,18 +22191,27 @@ 289, 290, 291, - 422, - 423, - 424, - 425, - 426, - 427, - 428, - 429, - 430, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, 431, 432, - 433 + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442 ], "irBases": [ "IAvnAvaloniaObject", @@ -22085,15 +22358,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -22110,7 +22374,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -22120,6 +22383,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -22166,15 +22430,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -22194,10 +22458,19 @@ 197, 198, 199, - 426, - 427, - 432, - 433 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 435, + 436, + 441, + 442 ], "irBases": [ "IAvnAvaloniaObject", @@ -22278,15 +22551,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -22303,7 +22567,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -22313,6 +22576,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -22359,15 +22623,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -22387,15 +22651,15 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 275, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 276, 277, 278, @@ -22412,24 +22676,33 @@ 289, 290, 291, - 375, - 376, - 377, - 378, - 379, - 380, - 422, - 423, - 424, - 425, - 426, - 427, - 428, - 429, - 430, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 384, + 385, + 386, + 387, + 388, + 389, 431, 432, - 433 + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442 ], "irBases": [ "IAvnAvaloniaObject", @@ -22544,15 +22817,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -22569,7 +22833,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -22579,6 +22842,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -22625,15 +22889,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -22653,14 +22917,23 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283 ], "irBases": [ "IAvnAvaloniaObject", @@ -22742,15 +23015,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -22767,19 +23031,19 @@ 92, 93, 94, - 35, 95, 96, - 434, + 97, 98, 99, 100, 101, 102, 103, + 35, 104, 105, - 106, + 443, 107, 108, 109, @@ -22823,15 +23087,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -22851,24 +23115,22 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 357, + 208, 358, 359, - 360, + 246, + 247, + 215, 216, - 217, + 360, 361, 362, 363, @@ -22876,23 +23138,25 @@ 365, 366, 367, - 261, - 402, - 435, - 436, - 437, - 417, - 438, - 421, - 439, - 440, - 441, - 442, - 443, + 368, + 369, + 225, + 226, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 270, + 411, 444, 445, 446, + 426, 447, + 430, 448, 449, 450, @@ -22906,9 +23170,18 @@ 458, 459, 460, - 415, 461, - 419 + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 424, + 470, + 428 ], "irBases": [ "IAvnAvaloniaObject", @@ -23048,15 +23321,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -23073,7 +23337,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -23083,6 +23346,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -23128,7 +23392,16 @@ 146, 147, 148, - 149 + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158 ], "irBases": [ "IAvnAvaloniaObject", @@ -23195,22 +23468,13 @@ }, { "name": "IAvnControlFactory", - "iid": "15778134-9E9F-5BAF-98FF-5510778094BA", + "iid": "C8BCE8E8-62C7-5E0E-8066-690059F55DFF", "iidConstant": "I_AVN_CONTROL_FACTORY_IID", - "abiVersion": 13, + "abiVersion": 14, "slots": [ 0, 1, 2, - 1019, - 1020, - 1021, - 1022, - 1023, - 1024, - 1025, - 1026, - 1027, 1028, 1029, 1030, @@ -23304,7 +23568,18 @@ 1118, 1119, 1120, - 1121 + 1121, + 1122, + 1123, + 1124, + 1125, + 1126, + 1127, + 1128, + 1129, + 1130, + 1131, + 1132 ] }, { @@ -23352,12 +23627,12 @@ 0, 1, 2, - 55, - 56, - 57, - 58, - 59, - 60 + 64, + 65, + 66, + 67, + 68, + 69 ] }, { @@ -23465,8 +23740,8 @@ 0, 1, 2, - 40, - 41 + 49, + 50 ] }, { @@ -23478,15 +23753,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -23503,7 +23769,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -23513,6 +23778,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -23559,15 +23825,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -23587,17 +23853,17 @@ 197, 198, 199, - 273, - 274, - 462, - 463, - 464, - 465, - 466, - 467, - 468, - 469, - 470, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 282, + 283, 471, 472, 473, @@ -23605,11 +23871,20 @@ 475, 476, 477, - 318, - 319, - 60, 478, - 347 + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 327, + 328, + 69, + 487, + 356 ], "irBases": [ "IAvnAvaloniaObject", @@ -23711,12 +23986,12 @@ 0, 1, 2, - 55, - 61, - 62, - 63, - 59, - 60 + 64, + 70, + 71, + 72, + 68, + 69 ] }, { @@ -23728,15 +24003,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -23753,7 +24019,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -23763,6 +24028,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -23809,10 +24075,19 @@ 147, 148, 149, - 262, - 263, - 198, - 199 + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 271, + 272, + 207, + 208 ], "irBases": [ "IAvnAvaloniaObject", @@ -23877,15 +24152,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -23902,7 +24168,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -23912,6 +24177,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -23958,15 +24224,24 @@ 147, 148, 149, - 348, - 172, - 173, - 479, - 480, - 481, - 482, - 483, - 484 + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 357, + 181, + 182, + 488, + 489, + 490, + 491, + 492, + 493 ], "irBases": [ "IAvnAvaloniaObject", @@ -24035,8 +24310,8 @@ 0, 1, 2, - 977, - 978 + 986, + 987 ] }, { @@ -24048,15 +24323,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -24073,7 +24339,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -24083,6 +24348,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -24129,15 +24395,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -24157,15 +24423,15 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 275, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 276, 277, 278, @@ -24181,7 +24447,16 @@ 288, 289, 290, - 291 + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300 ], "irBases": [ "IAvnAvaloniaObject", @@ -24274,15 +24549,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -24299,7 +24565,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -24309,6 +24574,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -24372,7 +24638,16 @@ 164, 165, 166, - 167 + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176 ], "irBases": [ "IAvnAvaloniaObject", @@ -24445,15 +24720,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -24470,7 +24736,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -24480,6 +24745,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -24526,15 +24792,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -24554,30 +24820,39 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 485, - 486, - 487, - 488, - 489, - 490, - 491, - 492, - 493, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, 494, 495, 496, 497, 498, 499, - 500 + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509 ], "irBases": [ "IAvnAvaloniaObject", @@ -24717,15 +24992,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -24742,7 +25008,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -24752,6 +25017,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -24798,23 +25064,32 @@ 147, 148, 149, - 348, - 172, - 173, - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 357, + 181, + 182, 510, 511, 512, 513, - 514 + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523 ], "irBases": [ "IAvnAvaloniaObject", @@ -24887,47 +25162,47 @@ 0, 1, 2, - 70, - 71, - 402, - 403, - 515, - 516, - 517, - 518, - 417, - 519, - 421, - 520, - 449, - 450, - 447, - 448, - 443, - 444, - 439, - 440, - 441, - 442, - 457, - 458, - 521, - 522, - 523, + 79, + 80, + 411, + 412, 524, 525, 526, - 445, - 446, 527, + 426, 528, - 419, + 430, 529, - 415, - 267, - 268, - 269, - 270 + 458, + 459, + 456, + 457, + 452, + 453, + 448, + 449, + 450, + 451, + 466, + 467, + 530, + 531, + 532, + 533, + 534, + 535, + 454, + 455, + 536, + 537, + 428, + 538, + 424, + 276, + 277, + 278, + 279 ], "irBases": [ "IAvnAvaloniaObject", @@ -24969,17 +25244,17 @@ 0, 1, 2, - 70, - 71, - 402, - 403, - 515, - 516, - 517, - 518, - 417, - 519, - 421 + 79, + 80, + 411, + 412, + 524, + 525, + 526, + 527, + 426, + 528, + 430 ], "irBases": [ "IAvnAvaloniaObject", @@ -25018,6 +25293,21 @@ 3 ] }, + { + "name": "IAvnGradientBrush", + "iid": "FDAA2353-BC44-5012-A5BE-A17C7C01F41A", + "iidConstant": "I_AVN_GRADIENT_BRUSH_IID", + "abiVersion": 1, + "slots": [ + 0, + 1, + 2, + 35, + 36, + 37, + 38 + ] + }, { "name": "IAvnGrid", "iid": "028C589C-2C52-5505-9CD2-36A25B4F43A6", @@ -25027,15 +25317,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -25052,7 +25333,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -25062,6 +25342,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -25108,19 +25389,28 @@ 147, 148, 149, - 348, - 172, - 173, - 530, - 531, - 513, - 514, - 511, - 512, - 532, - 533, - 534, - 535 + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 357, + 181, + 182, + 539, + 540, + 522, + 523, + 520, + 521, + 541, + 542, + 543, + 544 ], "irBases": [ "IAvnAvaloniaObject", @@ -25191,15 +25481,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -25216,7 +25497,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -25226,6 +25506,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -25272,15 +25553,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -25300,22 +25581,31 @@ 197, 198, 199, - 536, - 537, - 538, - 539, - 540, - 541, - 542, - 543, - 544, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 545, 546, 547, 548, 549, 550, - 551 + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560 ], "irBases": [ "IAvnAvaloniaObject", @@ -25402,16 +25692,16 @@ 0, 1, 2, - 979, - 980, - 981, - 982, - 983, - 984, - 985, - 986, - 987, - 988 + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997 ] }, { @@ -25423,15 +25713,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -25448,7 +25729,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -25458,6 +25738,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -25504,15 +25785,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -25532,18 +25813,27 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 485, - 486, - 487, - 488 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 494, + 495, + 496, + 497 ], "irBases": [ "IAvnAvaloniaObject", @@ -25629,15 +25919,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -25654,7 +25935,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -25664,6 +25944,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -25710,15 +25991,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -25738,18 +26019,27 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 485, - 486, - 487, - 488 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 494, + 495, + 496, + 497 ], "irBases": [ "IAvnAvaloniaObject", @@ -25834,15 +26124,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -25859,7 +26140,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -25869,6 +26149,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -25915,15 +26196,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -25943,22 +26224,31 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 485, - 486, - 487, - 488 + 208, + 358, + 359, + 246, + 247, + 215, + 216, + 360, + 361, + 362, + 363, + 364, + 365, + 494, + 495, + 496, + 497 ], "irBases": [ "IAvnAvaloniaObject", @@ -26049,15 +26339,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -26074,7 +26355,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -26084,6 +26364,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -26130,15 +26411,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -26158,24 +26439,22 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 357, + 208, 358, 359, - 360, + 246, + 247, + 215, 216, - 217, + 360, 361, 362, 363, @@ -26183,11 +26462,22 @@ 365, 366, 367, - 261, - 485, - 486, - 487, - 488 + 368, + 369, + 225, + 226, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 270, + 494, + 495, + 496, + 497 ], "irBases": [ "IAvnAvaloniaObject", @@ -26286,15 +26576,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -26311,7 +26592,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -26321,6 +26601,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -26367,15 +26648,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -26395,15 +26676,15 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 275, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 276, 277, 278, @@ -26420,10 +26701,19 @@ 289, 290, 291, - 552, - 553, - 554, - 555 + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 561, + 562, + 563, + 564 ], "irBases": [ "IAvnAvaloniaObject", @@ -26518,15 +26808,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -26543,7 +26824,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -26553,6 +26833,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -26599,15 +26880,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -26626,7 +26907,16 @@ 196, 197, 198, - 199 + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208 ], "irBases": [ "IAvnAvaloniaObject", @@ -26704,15 +26994,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -26729,7 +27010,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -26739,6 +27019,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -26785,14 +27066,23 @@ 147, 148, 149, - 556, - 557, - 558, - 559, + 150, + 151, 152, 153, - 560, - 561 + 154, + 155, + 156, + 157, + 158, + 565, + 566, + 567, + 568, + 161, + 162, + 569, + 570 ], "irBases": [ "IAvnAvaloniaObject", @@ -26859,7 +27149,7 @@ 0, 1, 2, - 42 + 51 ] }, { @@ -26871,12 +27161,12 @@ 0, 1, 2, - 55, - 56, - 57, - 58, - 59, - 60 + 64, + 65, + 66, + 67, + 68, + 69 ] }, { @@ -26888,7 +27178,7 @@ 0, 1, 2, - 44 + 53 ] }, { @@ -26900,15 +27190,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -26925,7 +27206,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -26935,6 +27215,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -26981,15 +27262,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -27009,18 +27290,27 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356 + 208, + 358, + 359, + 246, + 247, + 215, + 216, + 360, + 361, + 362, + 363, + 364, + 365 ], "irBases": [ "IAvnAvaloniaObject", @@ -27108,15 +27398,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -27133,7 +27414,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -27143,6 +27423,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -27189,15 +27470,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -27217,16 +27498,25 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 515, - 562 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 524, + 571 ], "irBases": [ "IAvnAvaloniaObject", @@ -27310,15 +27600,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -27335,7 +27616,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -27345,6 +27625,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -27391,12 +27672,21 @@ 147, 148, 149, - 262, - 263, - 198, - 199, - 563, - 564 + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 271, + 272, + 207, + 208, + 572, + 573 ], "irBases": [ "IAvnAvaloniaObject", @@ -27463,15 +27753,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -27488,7 +27769,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -27498,6 +27778,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -27562,10 +27843,19 @@ 165, 166, 167, - 565, - 566, - 567, - 568 + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 574, + 575, + 576, + 577 ], "irBases": [ "IAvnAvaloniaObject", @@ -27631,6 +27921,23 @@ 335 ] }, + { + "name": "IAvnLinearGradientBrush", + "iid": "40B3D53D-330E-5D63-A040-37F1FF717FF8", + "iidConstant": "I_AVN_LINEAR_GRADIENT_BRUSH_IID", + "abiVersion": 1, + "slots": [ + 0, + 1, + 2, + 35, + 36, + 37, + 38, + 39, + 40 + ] + }, { "name": "IAvnListBox", "iid": "FD704B9F-4E33-516E-B48D-B1DC9AA44DCA", @@ -27640,15 +27947,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -27665,7 +27963,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -27675,6 +27972,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -27721,15 +28019,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -27749,24 +28047,22 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 357, + 208, 358, 359, - 360, + 246, + 247, + 215, 216, - 217, + 360, 361, 362, 363, @@ -27774,11 +28070,22 @@ 365, 366, 367, - 261, - 314, - 315, - 569, - 570 + 368, + 369, + 225, + 226, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 270, + 323, + 324, + 578, + 579 ], "irBases": [ "IAvnAvaloniaObject", @@ -27878,15 +28185,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -27903,7 +28201,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -27913,6 +28210,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -27959,15 +28257,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -27987,16 +28285,25 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 388, - 389 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 397, + 398 ], "irBases": [ "IAvnAvaloniaObject", @@ -28080,15 +28387,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -28105,7 +28403,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -28115,6 +28412,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -28161,15 +28459,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -28189,25 +28487,25 @@ 197, 198, 199, - 571, - 572, - 214, - 215, - 573, - 574, - 575, - 576, 200, 201, - 577, - 578, - 579, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 580, 581, + 223, + 224, 582, 583, 584, 585, + 209, + 210, 586, 587, 588, @@ -28215,43 +28513,43 @@ 590, 591, 592, - 239, - 240, 593, 594, 595, 596, 597, 598, - 218, - 219, 599, 600, - 271, - 272, - 273, - 274, 601, + 248, + 249, 602, - 223, - 224, - 338, - 339, - 225, - 226, - 241, - 242, - 243, - 244, 603, 604, 605, 606, 607, + 227, + 228, 608, 609, + 280, + 281, + 282, + 283, 610, 611, + 232, + 233, + 347, + 348, + 234, + 235, + 250, + 251, + 252, + 253, 612, 613, 614, @@ -28263,9 +28561,7 @@ 620, 621, 622, - 60, 623, - 569, 624, 625, 626, @@ -28274,8 +28570,9 @@ 629, 630, 631, + 69, 632, - 247, + 578, 633, 634, 635, @@ -28285,13 +28582,23 @@ 639, 640, 641, + 256, 642, 643, 644, 645, 646, 647, - 648 + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657 ], "irBases": [ "IAvnAvaloniaObject", @@ -28430,15 +28737,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -28455,7 +28753,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -28465,6 +28762,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -28511,15 +28809,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -28539,24 +28837,22 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 357, + 208, 358, 359, - 360, + 246, + 247, + 215, 216, - 217, + 360, 361, 362, 363, @@ -28564,14 +28860,25 @@ 365, 366, 367, - 261, - 402, - 435, - 436, - 437, - 417, - 438, - 421 + 368, + 369, + 225, + 226, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 270, + 411, + 444, + 445, + 446, + 426, + 447, + 430 ], "irBases": [ "IAvnAvaloniaObject", @@ -28674,15 +28981,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -28699,7 +28997,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -28709,6 +29006,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -28755,15 +29053,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -28783,24 +29081,22 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 357, + 208, 358, 359, - 360, + 246, + 247, + 215, 216, - 217, + 360, 361, 362, 363, @@ -28808,14 +29104,25 @@ 365, 366, 367, - 261, - 402, - 435, - 436, - 437, - 417, - 438, - 421 + 368, + 369, + 225, + 226, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 270, + 411, + 444, + 445, + 446, + 426, + 447, + 430 ], "irBases": [ "IAvnAvaloniaObject", @@ -28941,48 +29248,48 @@ 0, 1, 2, - 70, - 71, - 402, - 403, - 515, - 516, - 517, - 518, - 417, - 519, - 421, - 520, - 449, - 450, - 447, - 448, - 443, - 444, - 439, - 440, - 441, - 442, - 457, - 458, - 521, - 522, - 523, + 79, + 80, + 411, + 412, 524, 525, 526, - 445, - 446, 527, + 426, 528, - 419, + 430, 529, - 415, - 349, - 237, - 238, - 206, - 207 + 458, + 459, + 456, + 457, + 452, + 453, + 448, + 449, + 450, + 451, + 466, + 467, + 530, + 531, + 532, + 533, + 534, + 535, + 454, + 455, + 536, + 537, + 428, + 538, + 424, + 358, + 246, + 247, + 215, + 216 ], "irBases": [ "IAvnAvaloniaObject", @@ -29025,15 +29332,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -29050,7 +29348,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -29060,6 +29357,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -29106,15 +29404,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -29134,24 +29432,22 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 357, + 208, 358, 359, - 360, + 246, + 247, + 215, 216, - 217, + 360, 361, 362, 363, @@ -29159,41 +29455,52 @@ 365, 366, 367, - 261, - 485, - 486, - 487, - 488, - 277, - 278, - 279, - 280, - 281, - 282, - 649, - 650, - 651, - 652, - 388, - 389, - 653, - 654, - 655, - 656, - 657, - 658, + 368, + 369, + 225, + 226, + 370, + 371, + 372, + 373, + 374, 375, 376, + 270, + 494, + 495, + 496, + 497, + 286, + 287, + 288, + 289, + 290, + 291, + 658, 659, 660, 661, + 397, + 398, 662, - 436, - 435, 663, - 291, 664, - 665 + 665, + 666, + 667, + 384, + 385, + 668, + 669, + 670, + 671, + 445, + 444, + 672, + 300, + 673, + 674 ], "irBases": [ "IAvnAvaloniaObject", @@ -29334,12 +29641,12 @@ 0, 1, 2, - 49, - 50, - 51, - 52, - 53, - 54 + 58, + 59, + 60, + 61, + 62, + 63 ] }, { @@ -29363,15 +29670,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -29388,7 +29686,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -29398,6 +29695,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -29444,15 +29742,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -29472,22 +29770,31 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 666, - 667, - 668, - 669, - 670, - 435, - 671, - 672 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 675, + 676, + 677, + 678, + 679, + 444, + 680, + 681 ], "irBases": [ "IAvnAvaloniaObject", @@ -29587,15 +29894,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -29612,7 +29910,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -29622,6 +29919,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -29668,15 +29966,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -29696,46 +29994,55 @@ 197, 198, 199, - 296, - 297, - 300, - 301, - 298, - 299, - 673, - 674, - 675, - 676, - 677, - 678, - 577, - 578, - 679, - 680, - 681, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 305, + 306, + 309, + 310, + 307, + 308, 682, - 218, - 219, 683, 684, - 223, - 224, - 225, - 226, - 271, - 272, - 273, - 274, - 601, - 602, - 241, - 242, - 243, - 244, 685, 686, 687, - 688 + 586, + 587, + 688, + 689, + 690, + 691, + 227, + 228, + 692, + 693, + 232, + 233, + 234, + 235, + 280, + 281, + 282, + 283, + 610, + 611, + 250, + 251, + 252, + 253, + 694, + 695, + 696, + 697 ], "irBases": [ "IAvnAvaloniaObject", @@ -29857,15 +30164,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -29882,7 +30180,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -29892,6 +30189,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -29938,9 +30236,18 @@ 147, 148, 149, - 348, - 172, - 173 + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 357, + 181, + 182 ], "irBases": [ "IAvnAvaloniaObject", @@ -30005,15 +30312,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -30030,7 +30328,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -30040,6 +30337,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -30104,8 +30402,17 @@ 165, 166, 167, - 689, - 690 + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 698, + 699 ], "irBases": [ "IAvnAvaloniaObject", @@ -30179,15 +30486,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -30204,7 +30502,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -30214,6 +30511,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -30260,15 +30558,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -30288,8 +30586,17 @@ 197, 198, 199, - 689, - 690 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 698, + 699 ], "irBases": [ "IAvnAvaloniaObject", @@ -30369,15 +30676,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -30394,7 +30692,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -30404,6 +30701,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -30450,15 +30748,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -30478,20 +30776,29 @@ 197, 198, 199, - 691, - 692, - 693, - 694, - 695, - 696, - 697, - 698, - 699, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 700, 701, 702, 703, - 704 + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713 ], "irBases": [ "IAvnAvaloniaObject", @@ -30588,15 +30895,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -30613,7 +30911,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -30623,6 +30920,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -30687,10 +30985,19 @@ 165, 166, 167, - 705, - 706, - 707, - 708 + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 714, + 715, + 716, + 717 ], "irBases": [ "IAvnAvaloniaObject", @@ -30765,15 +31072,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -30790,7 +31088,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -30800,6 +31097,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -30864,10 +31162,19 @@ 165, 166, 167, - 705, - 706, - 707, - 708 + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 714, + 715, + 716, + 717 ], "irBases": [ "IAvnAvaloniaObject", @@ -30942,15 +31249,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -30967,7 +31265,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -30977,6 +31274,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -31023,52 +31321,61 @@ 147, 148, 149, - 451, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 460, + 461, + 271, + 272, + 718, + 719, + 720, + 721, + 411, + 412, 452, - 262, - 263, - 709, - 710, - 711, - 712, - 402, - 403, - 443, - 444, - 445, - 446, - 447, - 448, - 449, - 450, 453, 454, 455, 456, 457, 458, - 523, - 524, - 525, - 526, - 439, - 440, - 441, - 442, - 713, - 714, - 715, - 716, - 717, - 718, - 719, - 720, - 436, - 435, - 721, - 421, + 459, + 462, + 463, + 464, + 465, + 466, + 467, + 532, + 533, + 534, + 535, + 448, + 449, + 450, + 451, 722, - 417 + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 445, + 444, + 730, + 430, + 731, + 426 ], "irBases": [ "IAvnAvaloniaObject", @@ -31168,43 +31475,43 @@ 0, 1, 2, - 70, - 71, - 402, - 403, - 515, - 516, - 517, - 518, - 417, - 519, - 421, - 520, - 449, - 450, - 447, - 448, - 443, - 444, - 439, - 440, - 441, - 442, - 457, - 458, - 521, - 522, - 523, + 79, + 80, + 411, + 412, 524, 525, 526, - 445, - 446, 527, + 426, 528, - 419, + 430, 529, - 415 + 458, + 459, + 456, + 457, + 452, + 453, + 448, + 449, + 450, + 451, + 466, + 467, + 530, + 531, + 532, + 533, + 534, + 535, + 454, + 455, + 536, + 537, + 428, + 538, + 424 ], "irBases": [ "IAvnAvaloniaObject", @@ -31279,7 +31586,7 @@ 0, 1, 2, - 46 + 55 ] }, { @@ -31291,15 +31598,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -31316,7 +31614,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -31326,6 +31623,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -31372,15 +31670,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -31400,18 +31698,17 @@ 197, 198, 199, - 723, - 724, - 725, - 726, - 727, - 728, - 729, - 730, - 731, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 732, 733, - 688, 734, 735, 736, @@ -31419,8 +31716,18 @@ 738, 739, 740, + 741, + 742, 697, - 698 + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 706, + 707 ], "irBases": [ "IAvnAvaloniaObject", @@ -31501,6 +31808,25 @@ 492 ] }, + { + "name": "IAvnRadialGradientBrush", + "iid": "AEC23FCE-9FEA-506C-ABC4-774143BE80C8", + "iidConstant": "I_AVN_RADIAL_GRADIENT_BRUSH_IID", + "abiVersion": 1, + "slots": [ + 0, + 1, + 2, + 35, + 36, + 37, + 38, + 41, + 42, + 43, + 44 + ] + }, { "name": "IAvnRadioButton", "iid": "FBEA357A-8E1A-5579-A0CF-4FD48895DADB", @@ -31510,15 +31836,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -31535,7 +31852,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -31545,6 +31861,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -31591,15 +31908,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -31619,15 +31936,15 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 275, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 276, 277, 278, @@ -31644,14 +31961,23 @@ 289, 290, 291, - 375, - 376, - 377, - 378, - 379, - 380, - 659, - 660 + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 384, + 385, + 386, + 387, + 388, + 389, + 668, + 669 ], "irBases": [ "IAvnAvaloniaObject", @@ -31749,15 +32075,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -31774,7 +32091,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -31784,6 +32100,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -31830,15 +32147,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -31858,18 +32175,27 @@ 197, 198, 199, - 723, - 724, - 725, - 726, - 727, - 728, - 729, - 730, - 731, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 732, 733, - 688 + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 697 ], "irBases": [ "IAvnAvaloniaObject", @@ -31965,15 +32291,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -31990,7 +32307,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -32000,6 +32316,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -32064,10 +32381,19 @@ 165, 166, 167, - 741, - 742, - 743, - 744 + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 750, + 751, + 752, + 753 ], "irBases": [ "IAvnAvaloniaObject", @@ -32142,15 +32468,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -32167,7 +32484,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -32177,6 +32493,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -32223,15 +32540,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -32251,21 +32568,30 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 745, - 746, - 747, - 748, - 749, - 750, - 751 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 754, + 755, + 756, + 757, + 758, + 759, + 760 ], "irBases": [ "IAvnAvaloniaObject", @@ -32364,15 +32690,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -32389,7 +32706,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -32399,6 +32715,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -32445,9 +32762,18 @@ 147, 148, 149, - 348, - 172, - 173 + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 357, + 181, + 182 ], "irBases": [ "IAvnAvaloniaObject", @@ -32513,18 +32839,18 @@ 0, 1, 2, - 989, - 990, - 991, - 992, - 993, - 994, - 995, - 996, - 997, 998, 999, - 1000 + 1000, + 1001, + 1002, + 1003, + 1004, + 1005, + 1006, + 1007, + 1008, + 1009 ] }, { @@ -32536,15 +32862,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -32561,7 +32878,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -32571,6 +32887,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -32617,15 +32934,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -32645,15 +32962,15 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 275, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 276, 277, 278, @@ -32670,10 +32987,19 @@ 289, 290, 291, - 752, - 753, - 754, - 755 + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 761, + 762, + 763, + 764 ], "irBases": [ "IAvnAvaloniaObject", @@ -32768,15 +33094,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -32793,7 +33110,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -32803,6 +33119,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -32849,15 +33166,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -32877,29 +33194,28 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 756, - 757, - 758, - 759, - 760, - 761, - 762, - 763, - 764, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, 765, 766, 767, 768, 769, - 491, 770, 771, 772, @@ -32909,6 +33225,7 @@ 776, 777, 778, + 500, 779, 780, 781, @@ -32929,7 +33246,16 @@ 796, 797, 798, - 799 + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807, + 808 ], "irBases": [ "IAvnAvaloniaObject", @@ -33056,15 +33382,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -33081,7 +33398,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -33091,6 +33407,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -33158,7 +33475,16 @@ 168, 169, 170, - 171 + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180 ], "irBases": [ "IAvnAvaloniaObject", @@ -33233,15 +33559,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -33258,7 +33575,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -33268,6 +33584,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -33314,57 +33631,66 @@ 147, 148, 149, - 198, - 199, - 172, - 173, - 218, - 219, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 207, + 208, + 181, 182, - 183, - 186, - 187, - 188, - 189, - 190, + 227, + 228, 191, 192, - 193, - 194, 195, - 597, - 598, - 800, - 801, 196, 197, - 593, - 594, - 605, + 198, + 199, + 200, + 201, + 202, + 203, + 204, 606, - 802, - 803, - 601, + 607, + 809, + 810, + 205, + 206, 602, - 184, - 185, - 804, - 805, - 581, - 582, - 583, - 584, - 589, + 603, + 614, + 615, + 811, + 812, + 610, + 611, + 193, + 194, + 813, + 814, 590, 591, 592, + 593, + 598, 599, - 610, - 621, - 569, - 618, - 806, - 627 + 600, + 601, + 608, + 619, + 630, + 578, + 627, + 815, + 636 ], "irBases": [ "IAvnAvaloniaObject", @@ -33468,12 +33794,12 @@ 0, 1, 2, - 55, 64, - 65, - 66, - 59, - 60 + 73, + 74, + 75, + 68, + 69 ] }, { @@ -33485,15 +33811,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -33510,7 +33827,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -33520,6 +33836,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -33566,15 +33883,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -33594,24 +33911,22 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 357, + 208, 358, 359, - 360, + 246, + 247, + 215, 216, - 217, + 360, 361, 362, 363, @@ -33619,7 +33934,18 @@ 365, 366, 367, - 261 + 368, + 369, + 225, + 226, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 270 ], "irBases": [ "IAvnAvaloniaObject", @@ -33742,15 +34068,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -33767,7 +34084,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -33777,6 +34093,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -33823,15 +34140,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -33850,7 +34167,16 @@ 196, 197, 198, - 199 + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208 ], "irBases": [ "IAvnAvaloniaObject", @@ -33928,15 +34254,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -33953,7 +34270,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -33963,6 +34279,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -34026,7 +34343,16 @@ 164, 165, 166, - 167 + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176 ], "irBases": [ "IAvnAvaloniaObject", @@ -34098,15 +34424,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -34123,7 +34440,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -34133,6 +34449,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -34179,15 +34496,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -34207,30 +34524,39 @@ 197, 198, 199, - 723, - 724, - 725, - 726, - 727, - 728, - 729, - 730, - 731, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 732, 733, - 688, - 807, - 808, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, 697, - 698, - 809, - 810, - 811, - 812, - 813, - 814, - 815, - 816 + 816, + 817, + 706, + 707, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825 ], "irBases": [ "IAvnAvaloniaObject", @@ -34321,15 +34647,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -34346,7 +34663,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -34356,6 +34672,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -34402,15 +34719,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -34430,18 +34747,27 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 292, - 293, - 294, - 295 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 301, + 302, + 303, + 304 ], "irBases": [ "IAvnAvaloniaObject", @@ -34538,15 +34864,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -34563,7 +34880,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -34573,6 +34889,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -34619,15 +34936,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -34647,24 +34964,33 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, 277, 278, + 279, + 280, 281, 282, + 283, + 286, + 287, + 290, + 291, + 297, + 298, 288, 289, - 279, - 280, - 817, - 291 + 826, + 300 ], "irBases": [ "IAvnAvaloniaObject", @@ -34764,15 +35090,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -34789,7 +35106,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -34799,6 +35115,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -34845,15 +35162,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -34873,27 +35190,27 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 818, - 819, - 312, - 313, - 820, - 821, - 822, - 823, - 824, - 825, - 826, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, 827, 828, + 321, + 322, 829, 830, 831, @@ -34906,7 +35223,16 @@ 838, 839, 840, - 841 + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850 ], "irBases": [ "IAvnAvaloniaObject", @@ -35050,15 +35376,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -35075,7 +35392,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -35085,6 +35401,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -35131,17 +35448,26 @@ 147, 148, 149, - 348, - 172, - 173, - 842, - 843, - 697, - 698, - 844, - 845, - 846, - 847 + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 357, + 181, + 182, + 851, + 852, + 706, + 707, + 853, + 854, + 855, + 856 ], "irBases": [ "IAvnAvaloniaObject", @@ -35211,12 +35537,12 @@ 0, 1, 2, - 55, - 67, + 64, + 76, + 77, + 78, 68, - 69, - 59, - 60 + 69 ] }, { @@ -35228,15 +35554,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -35250,7 +35567,16 @@ 89, 90, 91, - 92 + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101 ], "irBases": [ "IAvnAvaloniaObject", @@ -35353,15 +35679,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -35378,7 +35695,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -35388,6 +35704,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -35434,15 +35751,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -35462,24 +35779,22 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 357, + 208, 358, 359, - 360, + 246, + 247, + 215, 216, - 217, + 360, 361, 362, 363, @@ -35487,19 +35802,30 @@ 365, 366, 367, - 261, - 271, - 272, - 273, - 274, - 848, - 849, - 269, + 368, + 369, + 225, + 226, + 370, + 371, + 372, + 373, + 374, + 375, + 376, 270, - 850, - 851, - 852, - 853 + 280, + 281, + 282, + 283, + 857, + 858, + 278, + 279, + 859, + 860, + 861, + 862 ], "irBases": [ "IAvnAvaloniaObject", @@ -35603,15 +35929,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -35628,7 +35945,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -35638,6 +35954,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -35684,15 +36001,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -35712,27 +36029,36 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 485, - 486, - 487, - 488, - 854, - 388, - 389, - 424, - 425, - 855, - 856, - 852, - 853 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 494, + 495, + 496, + 497, + 863, + 397, + 398, + 433, + 434, + 864, + 865, + 861, + 862 ], "irBases": [ "IAvnAvaloniaObject", @@ -35823,15 +36149,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -35848,7 +36165,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -35858,6 +36174,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -35904,15 +36221,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -35932,24 +36249,22 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 357, + 208, 358, 359, - 360, + 246, + 247, + 215, 216, - 217, + 360, 361, 362, 363, @@ -35957,15 +36272,26 @@ 365, 366, 367, - 261, - 314, - 315, - 569, - 570, - 857, - 858, - 859, - 860 + 368, + 369, + 225, + 226, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 270, + 323, + 324, + 578, + 579, + 866, + 867, + 868, + 869 ], "irBases": [ "IAvnAvaloniaObject", @@ -36068,15 +36394,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -36093,7 +36410,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -36103,6 +36419,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -36149,15 +36466,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -36177,14 +36494,23 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283 ], "irBases": [ "IAvnAvaloniaObject", @@ -36267,15 +36593,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -36290,24 +36607,33 @@ 90, 91, 92, - 487, - 488, - 485, - 486, - 861, - 862, - 107, - 108, - 109, - 110, 93, 94, - 863, - 864, - 271, - 272, - 865, - 866 + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 496, + 497, + 494, + 495, + 870, + 871, + 116, + 117, + 118, + 119, + 102, + 103, + 872, + 873, + 280, + 281, + 874, + 875 ], "irBases": [ "IAvnAvaloniaObject", @@ -36349,15 +36675,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -36374,7 +36691,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -36384,6 +36700,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -36430,15 +36747,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -36458,16 +36775,25 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 388, - 389 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 397, + 398 ], "irBases": [ "IAvnAvaloniaObject", @@ -36552,15 +36878,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -36577,7 +36894,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -36587,6 +36903,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -36633,15 +36950,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -36660,7 +36977,16 @@ 196, 197, 198, - 199 + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208 ], "irBases": [ "IAvnAvaloniaObject", @@ -36737,15 +37063,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -36762,7 +37079,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -36772,6 +37088,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -36818,42 +37135,51 @@ 147, 148, 149, - 198, - 199, - 172, - 173, - 218, - 219, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 207, + 208, + 181, 182, - 183, - 186, - 187, - 188, - 189, - 190, + 227, + 228, 191, 192, - 193, - 194, 195, - 597, - 598, - 800, - 801, 196, 197, - 593, - 594, - 605, + 198, + 199, + 200, + 201, + 202, + 203, + 204, 606, - 802, - 803, - 601, + 607, + 809, + 810, + 205, + 206, 602, - 184, - 185, - 804, - 805 + 603, + 614, + 615, + 811, + 812, + 610, + 611, + 193, + 194, + 813, + 814 ], "irBases": [ "IAvnAvaloniaObject", @@ -36934,15 +37260,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -36959,7 +37276,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -36969,6 +37285,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -37015,15 +37332,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -37043,25 +37360,25 @@ 197, 198, 199, - 571, - 572, - 214, - 215, - 573, - 574, - 575, - 576, 200, 201, - 577, - 578, - 579, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 580, 581, + 223, + 224, 582, 583, 584, 585, + 209, + 210, 586, 587, 588, @@ -37069,43 +37386,43 @@ 590, 591, 592, - 239, - 240, 593, 594, 595, 596, 597, 598, - 218, - 219, 599, 600, - 271, - 272, - 273, - 274, 601, + 248, + 249, 602, - 223, - 224, - 338, - 339, - 225, - 226, - 241, - 242, - 243, - 244, 603, 604, 605, 606, 607, + 227, + 228, 608, 609, + 280, + 281, + 282, + 283, 610, 611, + 232, + 233, + 347, + 348, + 234, + 235, + 250, + 251, + 252, + 253, 612, 613, 614, @@ -37117,9 +37434,7 @@ 620, 621, 622, - 60, 623, - 569, 624, 625, 626, @@ -37128,10 +37443,21 @@ 629, 630, 631, + 69, 632, - 247, + 578, 633, - 634 + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 256, + 642, + 643 ], "irBases": [ "IAvnAvaloniaObject", @@ -37321,7 +37647,7 @@ 0, 1, 2, - 43 + 52 ] }, { @@ -37333,7 +37659,7 @@ 0, 1, 2, - 45 + 54 ] }, { @@ -37345,15 +37671,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -37370,7 +37687,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -37380,6 +37696,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -37426,12 +37743,21 @@ 147, 148, 149, - 262, - 263, - 198, - 199, - 867, - 868 + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 271, + 272, + 207, + 208, + 876, + 877 ], "irBases": [ "IAvnAvaloniaObject", @@ -37498,15 +37824,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -37523,7 +37840,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -37533,6 +37849,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -37579,15 +37896,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -37607,12 +37924,21 @@ 197, 198, 199, - 536, - 537, - 538, - 539, - 540, - 541 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 545, + 546, + 547, + 548, + 549, + 550 ], "irBases": [ "IAvnAvaloniaObject", @@ -37729,15 +38055,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -37754,7 +38071,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -37764,6 +38080,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -37810,15 +38127,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -37838,21 +38155,30 @@ 197, 198, 199, - 273, - 274, - 869, - 870, - 871, - 872, - 873, - 874, - 875, - 876, - 877, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 282, + 283, 878, - 60, 879, - 880 + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 69, + 888, + 889 ], "irBases": [ "IAvnAvaloniaObject", @@ -37950,15 +38276,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -37975,7 +38292,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -37985,6 +38301,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -38031,15 +38348,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -38059,15 +38376,15 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 275, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 276, 277, 278, @@ -38084,12 +38401,21 @@ 289, 290, 291, - 375, - 376, - 377, - 378, - 379, - 380 + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 384, + 385, + 386, + 387, + 388, + 389 ], "irBases": [ "IAvnAvaloniaObject", @@ -38197,15 +38523,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -38222,7 +38539,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -38232,6 +38548,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -38278,15 +38595,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -38306,28 +38623,37 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, 277, 278, + 279, + 280, 281, 282, + 283, + 286, + 287, + 290, + 291, + 297, + 298, 288, 289, - 279, - 280, - 817, - 291, - 375, - 376, - 881, - 380 + 826, + 300, + 384, + 385, + 890, + 389 ], "irBases": [ "IAvnAvaloniaObject", @@ -38430,15 +38756,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -38455,7 +38772,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -38465,6 +38781,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -38511,15 +38828,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -38539,15 +38856,15 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 275, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, 276, 277, 278, @@ -38564,20 +38881,29 @@ 289, 290, 291, - 375, - 376, - 377, - 378, - 379, - 380, - 882, - 883, - 884, - 885, - 886, - 887, - 888, - 889 + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 384, + 385, + 386, + 387, + 388, + 389, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898 ], "irBases": [ "IAvnAvaloniaObject", @@ -38678,15 +39004,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -38703,7 +39020,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -38713,6 +39029,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -38759,15 +39076,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -38787,14 +39104,23 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283 ], "irBases": [ "IAvnAvaloniaObject", @@ -38877,15 +39203,6 @@ 0, 1, 2, - 1001, - 1002, - 1003, - 1004, - 1005, - 1006, - 1007, - 1008, - 1009, 1010, 1011, 1012, @@ -38894,7 +39211,16 @@ 1015, 1016, 1017, - 1018 + 1018, + 1019, + 1020, + 1021, + 1022, + 1023, + 1024, + 1025, + 1026, + 1027 ] }, { @@ -38906,15 +39232,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -38931,7 +39248,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -38941,6 +39257,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -38987,15 +39304,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -39015,18 +39332,27 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 890, - 891, - 892, - 893 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 899, + 900, + 901, + 902 ], "irBases": [ "IAvnAvaloniaObject", @@ -39123,20 +39449,20 @@ 0, 1, 2, - 70, - 71, - 277, - 278, - 281, - 282, - 894, - 895, - 896, - 897, - 93, - 94, - 898, - 899 + 79, + 80, + 286, + 287, + 290, + 291, + 903, + 904, + 905, + 906, + 102, + 103, + 907, + 908 ], "irBases": [ "IAvnAvaloniaObject", @@ -39172,15 +39498,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -39197,7 +39514,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -39207,6 +39523,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -39253,15 +39570,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -39281,34 +39598,43 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 357, + 208, 358, - 314, - 315, + 359, + 246, + 247, + 215, 216, - 217, - 900, - 901, - 902, - 903, - 569, - 570, - 904, - 905, - 906, - 261 + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 323, + 324, + 225, + 226, + 909, + 910, + 911, + 912, + 578, + 579, + 913, + 914, + 915, + 270 ], "irBases": [ "IAvnAvaloniaObject", @@ -39408,15 +39734,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -39433,7 +39750,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -39443,6 +39759,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -39489,15 +39806,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -39517,31 +39834,40 @@ 197, 198, 199, - 349, - 350, - 237, - 238, + 200, + 201, + 202, + 203, + 204, + 205, 206, 207, - 351, - 352, - 353, - 354, - 355, - 356, - 485, - 486, - 487, - 488, - 491, - 492, - 388, - 389, - 907, - 908, - 498, - 909, - 494 + 208, + 358, + 359, + 246, + 247, + 215, + 216, + 360, + 361, + 362, + 363, + 364, + 365, + 494, + 495, + 496, + 497, + 500, + 501, + 397, + 398, + 916, + 917, + 507, + 918, + 503 ], "irBases": [ "IAvnAvaloniaObject", @@ -39689,15 +40015,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -39714,7 +40031,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -39724,6 +40040,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -39770,19 +40087,28 @@ 147, 148, 149, - 348, - 172, - 173, - 910, - 911, - 912, - 913, - 914, - 915, - 513, - 514, - 511, - 512 + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 357, + 181, + 182, + 919, + 920, + 921, + 922, + 923, + 924, + 522, + 523, + 520, + 521 ], "irBases": [ "IAvnAvaloniaObject", @@ -39853,15 +40179,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -39878,7 +40195,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -39888,6 +40204,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -39934,15 +40251,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -39962,14 +40279,23 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283 ], "irBases": [ "IAvnAvaloniaObject", @@ -40052,12 +40378,12 @@ 0, 1, 2, - 55, 64, - 65, - 66, - 59, - 60 + 73, + 74, + 75, + 68, + 69 ] }, { @@ -40069,15 +40395,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -40094,7 +40411,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -40104,6 +40420,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -40150,12 +40467,21 @@ 147, 148, 149, + 150, + 151, 152, 153, - 560, - 561, - 262, - 263 + 154, + 155, + 156, + 157, + 158, + 161, + 162, + 569, + 570, + 271, + 272 ], "irBases": [ "IAvnAvaloniaObject", @@ -40221,15 +40547,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -40246,7 +40563,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -40256,6 +40572,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -40302,15 +40619,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -40330,23 +40647,23 @@ 197, 198, 199, - 267, - 268, - 269, - 270, - 271, - 272, - 273, - 274, - 916, - 917, - 918, - 919, - 920, - 921, - 922, - 923, - 924, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, 925, 926, 927, @@ -40365,20 +40682,29 @@ 940, 941, 942, - 894, - 895, 943, 944, 945, 946, 947, - 435, 948, - 517, 949, 950, 951, - 419 + 903, + 904, + 952, + 953, + 954, + 955, + 956, + 444, + 957, + 526, + 958, + 959, + 960, + 428 ], "irBases": [ "IAvnAvaloniaObject", @@ -40498,15 +40824,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -40523,7 +40840,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -40533,6 +40849,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -40579,15 +40896,15 @@ 147, 148, 149, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, 181, 182, 183, @@ -40607,15 +40924,24 @@ 197, 198, 199, - 952, - 953, - 954, - 955, - 956, - 957, - 958, - 959, - 960 + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 961, + 962, + 963, + 964, + 965, + 966, + 967, + 968, + 969 ], "irBases": [ "IAvnAvaloniaObject", @@ -40700,15 +41026,6 @@ 0, 1, 2, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, 79, 80, 81, @@ -40725,7 +41042,6 @@ 92, 93, 94, - 35, 95, 96, 97, @@ -40735,6 +41051,7 @@ 101, 102, 103, + 35, 104, 105, 106, @@ -40781,21 +41098,30 @@ 147, 148, 149, - 348, - 172, - 173, - 961, - 962, - 800, - 801, - 697, - 698, - 963, - 964, - 965, - 966, - 967, - 968 + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 357, + 181, + 182, + 970, + 971, + 809, + 810, + 706, + 707, + 972, + 973, + 974, + 975, + 976, + 977 ], "irBases": [ "IAvnAvaloniaObject", diff --git a/rust/avalonia-bindgen/src/emit.rs b/rust/avalonia-bindgen/src/emit.rs index 9208e71..27a2e7f 100644 --- a/rust/avalonia-bindgen/src/emit.rs +++ b/rust/avalonia-bindgen/src/emit.rs @@ -134,6 +134,10 @@ pub(crate) fn emit_sys_module(ir: &ProjectionIr) -> String { out.push_str(&emit_brush(ir)); out.push('\n'); } + if ir.gradient_brush_interface_name.is_some() { + out.push_str(&emit_gradient_brush(ir)); + out.push('\n'); + } if ir.command_interface_name.is_some() { out.push_str(&emit_command(ir)); out.push('\n'); @@ -414,6 +418,211 @@ fn emit_brush(ir: &ProjectionIr) -> String { ) } +fn emit_gradient_brush(ir: &ProjectionIr) -> String { + let gradient_name = simple_name( + ir.gradient_brush_interface_name + .as_deref() + .expect("gradientBrushInterfaceName"), + ); + let gradient_iid = ir + .gradient_brush_interface_iid + .as_deref() + .expect("gradientBrushInterfaceIid for a projected gradient brush"); + let linear_name = simple_name( + ir.linear_gradient_brush_interface_name + .as_deref() + .expect("linearGradientBrushInterfaceName"), + ); + let linear_iid = ir + .linear_gradient_brush_interface_iid + .as_deref() + .expect("linearGradientBrushInterfaceIid"); + let radial_name = simple_name( + ir.radial_gradient_brush_interface_name + .as_deref() + .expect("radialGradientBrushInterfaceName"), + ); + let radial_iid = ir + .radial_gradient_brush_interface_iid + .as_deref() + .expect("radialGradientBrushInterfaceIid"); + let color = geometry::find("Color") + .expect("Color geometry struct") + .abi_name; + + let mut out = String::from( + "/// Blittable ABI mirror of Avalonia.RelativePoint. unit: 0 relative, 1 absolute.\n\ + #[repr(C)]\n\ + #[derive(Clone, Copy, Debug, Default, PartialEq)]\n\ + pub struct AvnRelativePoint {\n\ + \x20 pub x: f64,\n\ + \x20 pub y: f64,\n\ + \x20 pub unit: i32,\n\ + }\n\n\ + /// Blittable ABI mirror of Avalonia.RelativeScalar. unit: 0 relative, 1 absolute.\n\ + #[repr(C)]\n\ + #[derive(Clone, Copy, Debug, Default, PartialEq)]\n\ + pub struct AvnRelativeScalar {\n\ + \x20 pub scalar: f64,\n\ + \x20 pub unit: i32,\n\ + }\n\n", + ); + out.push_str(&format!( + "/// Blittable ABI mirror of a single gradient stop (offset plus packed colour).\n\ + #[repr(C)]\n\ + #[derive(Clone, Copy, Debug, Default, PartialEq)]\n\ + pub struct AvnGradientStop {{\n\ + \x20 pub offset: f64,\n\ + \x20 pub color: {color},\n\ + }}\n\n\ + /// Fixed-capacity buffer of up to {max_stops} `AvnGradientStop` entries.\n\ + #[repr(C)]\n\ + #[derive(Clone, Copy, Debug)]\n\ + pub struct AvnGradientStopBuffer {{\n\ + \x20 pub stops: [AvnGradientStop; {max_stops}],\n\ + }}\n\n\ + impl Default for AvnGradientStopBuffer {{\n\ + \x20 fn default() -> Self {{\n\ + \x20 Self {{ stops: [AvnGradientStop::default(); {max_stops}] }}\n\ + \x20 }}\n\ + }}\n\n", + max_stops = GRADIENT_MAX_STOPS + )); + + out.push_str(&format!( + "/// Capability shared by every gradient brush kind projected across the ABI.\n\ + pub const {gradient_shouty}_IID: Guid = {gradient_iid_literal};\n\n\ + #[repr(C)]\n\ + struct {gradient_name}Vtbl {{\n\ + \x20 query_interface: unsafe extern \"system\" fn(*mut IUnknown, *const Guid, *mut *mut c_void) -> i32,\n\ + \x20 add_ref: unsafe extern \"system\" fn(*mut IUnknown) -> u32,\n\ + \x20 release: unsafe extern \"system\" fn(*mut IUnknown) -> u32,\n\ + \x20 get_opacity: unsafe extern \"system\" fn(*mut {gradient_name}, *mut f64) -> i32,\n\ + \x20 get_spread_method: unsafe extern \"system\" fn(*mut {gradient_name}, *mut i32) -> i32,\n\ + \x20 get_stop_count: unsafe extern \"system\" fn(*mut {gradient_name}, *mut i32) -> i32,\n\ + \x20 get_stops: unsafe extern \"system\" fn(*mut {gradient_name}, *mut AvnGradientStopBuffer) -> i32,\n\ + }}\n\n\ + #[repr(C)]\n\ + pub struct {gradient_name} {{\n\ + \x20 vtbl: *const {gradient_name}Vtbl,\n\ + }}\n\n\ + unsafe impl ComInterface for {gradient_name} {{\n\ + \x20 const IID: Guid = {gradient_shouty}_IID;\n\ + }}\n\n\ + impl ComPtr<{gradient_name}> {{\n\ + {gradient_getters}\ + }}\n\n", + gradient_shouty = to_shouty(gradient_name), + gradient_iid_literal = guid_literal(gradient_iid), + gradient_getters = emit_gradient_getters(gradient_name), + )); + + out.push_str(&emit_gradient_shape( + linear_name, + linear_iid, + &[ + ("get_start_point", "start_point", "AvnRelativePoint"), + ("get_end_point", "end_point", "AvnRelativePoint"), + ], + )); + out.push_str(&emit_gradient_shape( + radial_name, + radial_iid, + &[ + ("get_center", "center", "AvnRelativePoint"), + ("get_gradient_origin", "gradient_origin", "AvnRelativePoint"), + ("get_radius_x", "radius_x", "AvnRelativeScalar"), + ("get_radius_y", "radius_y", "AvnRelativeScalar"), + ], + )); + out +} + +/// The fixed capacity of `AvnGradientStopBuffer`; must match `GradientBrushMarshalling.MaxStops` +/// on the C# projection side. +const GRADIENT_MAX_STOPS: usize = 8; + +fn emit_gradient_getters(gradient_name: &str) -> String { + format!( + "\x20 pub fn opacity(&self) -> Result {{\n\ + \x20 unsafe {{\n\ + \x20 let mut value = 0.0;\n\ + \x20 let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_opacity)(self.as_raw(), &mut value);\n\ + \x20 hresult::check(hr).map(|_| value)\n\ + \x20 }}\n\ + \x20 }}\n\ + \x20 /// 0 = Pad, 1 = Reflect, 2 = Repeat.\n\ + \x20 pub fn spread_method(&self) -> Result {{\n\ + \x20 unsafe {{\n\ + \x20 let mut value = 0;\n\ + \x20 let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_spread_method)(self.as_raw(), &mut value);\n\ + \x20 hresult::check(hr).map(|_| value)\n\ + \x20 }}\n\ + \x20 }}\n\ + \x20 pub fn stop_count(&self) -> Result {{\n\ + \x20 unsafe {{\n\ + \x20 let mut value = 0;\n\ + \x20 let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_stop_count)(self.as_raw(), &mut value);\n\ + \x20 hresult::check(hr).map(|_| value)\n\ + \x20 }}\n\ + \x20 }}\n\ + \x20 pub fn stops(&self) -> Result {{\n\ + \x20 unsafe {{\n\ + \x20 let mut value = AvnGradientStopBuffer::default();\n\ + \x20 let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_stops)(self.as_raw(), &mut value);\n\ + \x20 hresult::check(hr).map(|_| value)\n\ + \x20 }}\n\ + \x20 }}\n", + ) + .replace("{gradient_name}", gradient_name) +} + +/// Emits one derived gradient-kind interface (linear or radial). The vtable flattens the +/// four base `IAvnGradientBrush` slots ahead of the kind-specific slots, mirroring the +/// single-inheritance layout produced for the native header and the generated C# interface. +fn emit_gradient_shape(name: &str, iid: &str, accessors: &[(&str, &str, &str)]) -> String { + let mut vtbl = format!( + "#[repr(C)]\nstruct {name}Vtbl {{\n\ + \x20 query_interface: unsafe extern \"system\" fn(*mut IUnknown, *const Guid, *mut *mut c_void) -> i32,\n\ + \x20 add_ref: unsafe extern \"system\" fn(*mut IUnknown) -> u32,\n\ + \x20 release: unsafe extern \"system\" fn(*mut IUnknown) -> u32,\n\ + \x20 get_opacity: unsafe extern \"system\" fn(*mut {name}, *mut f64) -> i32,\n\ + \x20 get_spread_method: unsafe extern \"system\" fn(*mut {name}, *mut i32) -> i32,\n\ + \x20 get_stop_count: unsafe extern \"system\" fn(*mut {name}, *mut i32) -> i32,\n\ + \x20 get_stops: unsafe extern \"system\" fn(*mut {name}, *mut AvnGradientStopBuffer) -> i32,\n" + ); + for (accessor, _field_name, field_type) in accessors { + vtbl.push_str(&format!( + " {accessor}: unsafe extern \"system\" fn(*mut {name}, *mut {field_type}) -> i32,\n" + )); + } + vtbl.push_str("}\n\n"); + + let mut out = format!( + "{vtbl}#[repr(C)]\npub struct {name} {{\n\x20 vtbl: *const {name}Vtbl,\n}}\n\n\ + unsafe impl ComInterface for {name} {{\n\x20 const IID: Guid = {shouty}_IID;\n}}\n\n\ + pub const {shouty}_IID: Guid = {iid_literal};\n\n\ + impl ComPtr<{name}> {{\n\ + {getters}", + shouty = to_shouty(name), + iid_literal = guid_literal(iid), + getters = emit_gradient_getters(name), + ); + for (accessor, field_name, field_type) in accessors { + out.push_str(&format!( + " pub fn {field_name}(&self) -> Result<{field_type}> {{\n\ + \x20 unsafe {{\n\ + \x20 let mut value = {field_type}::default();\n\ + \x20 let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().{accessor})(self.as_raw(), &mut value);\n\ + \x20 hresult::check(hr).map(|_| value)\n\ + \x20 }}\n\ + \x20 }}\n" + )); + } + out.push_str("}\n\n"); + out +} + fn emit_command(ir: &ProjectionIr) -> String { let name = simple_name( ir.command_interface_name @@ -1472,6 +1681,18 @@ fn emit_factory(ir: &ProjectionIr) -> String { " create_solid_color_brush: unsafe extern \"system\" fn(*mut IAvnControlFactory, {color}, f64, *mut *mut {brush}) -> i32,\n" )); } + if let Some(linear) = ir.linear_gradient_brush_interface_name.as_deref() { + let linear = simple_name(linear); + let radial = simple_name( + ir.radial_gradient_brush_interface_name + .as_deref() + .expect("radialGradientBrushInterfaceName"), + ); + out.push_str(&format!( + " create_linear_gradient_brush: unsafe extern \"system\" fn(*mut IAvnControlFactory, f64, i32, i32, AvnGradientStopBuffer, AvnRelativePoint, AvnRelativePoint, *mut *mut {linear}) -> i32,\n\ + \x20 create_radial_gradient_brush: unsafe extern \"system\" fn(*mut IAvnControlFactory, f64, i32, i32, AvnGradientStopBuffer, AvnRelativePoint, AvnRelativePoint, AvnRelativeScalar, AvnRelativeScalar, *mut *mut {radial}) -> i32,\n" + )); + } out.push_str("}\n\n#[repr(C)]\npub struct IAvnControlFactory {\n vtbl: *const IAvnControlFactoryVtbl,\n}\n\n"); out.push_str("unsafe impl ComInterface for IAvnControlFactory {\n const IID: Guid = IAVN_CONTROL_FACTORY_IID;\n}\n\n"); out.push_str("impl ComPtr {\n"); @@ -1522,6 +1743,56 @@ fn emit_factory(ir: &ProjectionIr) -> String { \x20 }}\n" )); } + if let Some(linear) = ir.linear_gradient_brush_interface_name.as_deref() { + let linear = simple_name(linear); + let radial = simple_name( + ir.radial_gradient_brush_interface_name + .as_deref() + .expect("radialGradientBrushInterfaceName"), + ); + out.push_str(&format!( + " #[allow(clippy::too_many_arguments)]\n\ + \x20 pub fn create_linear_gradient_brush(\n\ + \x20 &self,\n\ + \x20 opacity: f64,\n\ + \x20 spread_method: i32,\n\ + \x20 stop_count: i32,\n\ + \x20 stops: AvnGradientStopBuffer,\n\ + \x20 start_point: AvnRelativePoint,\n\ + \x20 end_point: AvnRelativePoint,\n\ + \x20 ) -> Result> {{\n\ + \x20 unsafe {{\n\ + \x20 let mut value = ptr::null_mut();\n\ + \x20 let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().create_linear_gradient_brush)(\n\ + \x20 self.as_raw(), opacity, spread_method, stop_count, stops, start_point, end_point, &mut value,\n\ + \x20 );\n\ + \x20 hresult::check(hr)?;\n\ + \x20 ComPtr::from_raw(value).ok_or(Error(hresult::E_POINTER))\n\ + \x20 }}\n\ + \x20 }}\n\ + \x20 #[allow(clippy::too_many_arguments)]\n\ + \x20 pub fn create_radial_gradient_brush(\n\ + \x20 &self,\n\ + \x20 opacity: f64,\n\ + \x20 spread_method: i32,\n\ + \x20 stop_count: i32,\n\ + \x20 stops: AvnGradientStopBuffer,\n\ + \x20 center: AvnRelativePoint,\n\ + \x20 gradient_origin: AvnRelativePoint,\n\ + \x20 radius_x: AvnRelativeScalar,\n\ + \x20 radius_y: AvnRelativeScalar,\n\ + \x20 ) -> Result> {{\n\ + \x20 unsafe {{\n\ + \x20 let mut value = ptr::null_mut();\n\ + \x20 let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().create_radial_gradient_brush)(\n\ + \x20 self.as_raw(), opacity, spread_method, stop_count, stops, center, gradient_origin, radius_x, radius_y, &mut value,\n\ + \x20 );\n\ + \x20 hresult::check(hr)?;\n\ + \x20 ComPtr::from_raw(value).ok_or(Error(hresult::E_POINTER))\n\ + \x20 }}\n\ + \x20 }}\n" + )); + } out.push_str("}\n"); out } diff --git a/rust/avalonia-bindgen/src/emit_safe.rs b/rust/avalonia-bindgen/src/emit_safe.rs index 34eca30..9bcd1b0 100644 --- a/rust/avalonia-bindgen/src/emit_safe.rs +++ b/rust/avalonia-bindgen/src/emit_safe.rs @@ -57,6 +57,9 @@ pub(crate) fn emit_safe_module(ir: &ProjectionIr) -> String { if ir.brush_interface_name.is_some() { out.push_str(&emit_brush()); } + if ir.gradient_brush_interface_name.is_some() { + out.push_str(&emit_gradient_brush()); + } let flags_enums: std::collections::HashSet<&str> = ir .enums @@ -198,6 +201,276 @@ fn emit_brush() -> String { ) } +fn emit_gradient_brush() -> String { + String::from( + "/// Spread behaviour for a gradient outside its `[0, 1]` stop range.\n\ + /// Mirrors `Avalonia.Media.GradientSpreadMethod`.\n\ + #[repr(i32)]\n\ + #[derive(Clone, Copy, Debug, PartialEq, Eq)]\n\ + pub enum SpreadMethod {\n\ + \x20 Pad = 0,\n\ + \x20 Reflect = 1,\n\ + \x20 Repeat = 2,\n\ + }\n\n\ + impl TryFrom for SpreadMethod {\n\ + \x20 type Error = crate::Error;\n\ + \x20 fn try_from(value: i32) -> Result {\n\ + \x20 match value {\n\ + \x20 0 => Ok(Self::Pad),\n\ + \x20 1 => Ok(Self::Reflect),\n\ + \x20 2 => Ok(Self::Repeat),\n\ + \x20 _ => Err(crate::Error::InvalidEnumValue(value)),\n\ + \x20 }\n\ + \x20 }\n\ + }\n\n\ + /// Whether a gradient coordinate is relative to the shape's bounding box or an\n\ + /// absolute value. Mirrors `Avalonia.RelativeUnit`.\n\ + #[repr(i32)]\n\ + #[derive(Clone, Copy, Debug, PartialEq, Eq)]\n\ + pub enum RelativeUnit {\n\ + \x20 Relative = 0,\n\ + \x20 Absolute = 1,\n\ + }\n\n\ + impl TryFrom for RelativeUnit {\n\ + \x20 type Error = crate::Error;\n\ + \x20 fn try_from(value: i32) -> Result {\n\ + \x20 match value {\n\ + \x20 0 => Ok(Self::Relative),\n\ + \x20 1 => Ok(Self::Absolute),\n\ + \x20 _ => Err(crate::Error::InvalidEnumValue(value)),\n\ + \x20 }\n\ + \x20 }\n\ + }\n\n\ + /// A point whose X/Y may each be relative to the shape's bounding box.\n\ + #[derive(Clone, Copy, Debug, PartialEq)]\n\ + pub struct RelativePoint {\n\ + \x20 pub x: f64,\n\ + \x20 pub y: f64,\n\ + \x20 pub unit: RelativeUnit,\n\ + }\n\n\ + impl RelativePoint {\n\ + \x20 pub const fn new(x: f64, y: f64, unit: RelativeUnit) -> Self {\n\ + \x20 Self { x, y, unit }\n\ + \x20 }\n\n\ + \x20 pub(crate) fn to_abi(self) -> sys::AvnRelativePoint {\n\ + \x20 sys::AvnRelativePoint { x: self.x, y: self.y, unit: self.unit as i32 }\n\ + \x20 }\n\n\ + \x20 pub(crate) fn from_abi(value: sys::AvnRelativePoint) -> Result {\n\ + \x20 Ok(Self { x: value.x, y: value.y, unit: RelativeUnit::try_from(value.unit)? })\n\ + \x20 }\n\ + }\n\n\ + /// A scalar (for example a radius) that may be relative to the shape's bounding box.\n\ + #[derive(Clone, Copy, Debug, PartialEq)]\n\ + pub struct RelativeScalar {\n\ + \x20 pub scalar: f64,\n\ + \x20 pub unit: RelativeUnit,\n\ + }\n\n\ + impl RelativeScalar {\n\ + \x20 pub const fn new(scalar: f64, unit: RelativeUnit) -> Self {\n\ + \x20 Self { scalar, unit }\n\ + \x20 }\n\n\ + \x20 pub(crate) fn to_abi(self) -> sys::AvnRelativeScalar {\n\ + \x20 sys::AvnRelativeScalar { scalar: self.scalar, unit: self.unit as i32 }\n\ + \x20 }\n\n\ + \x20 pub(crate) fn from_abi(value: sys::AvnRelativeScalar) -> Result {\n\ + \x20 Ok(Self { scalar: value.scalar, unit: RelativeUnit::try_from(value.unit)? })\n\ + \x20 }\n\ + }\n\n\ + /// A single colour stop along a gradient, at `offset` in `[0, 1]`.\n\ + #[derive(Clone, Copy, Debug, PartialEq)]\n\ + pub struct GradientStop {\n\ + \x20 pub offset: f64,\n\ + \x20 pub color: Color,\n\ + }\n\n\ + impl GradientStop {\n\ + \x20 pub const fn new(offset: f64, color: Color) -> Self {\n\ + \x20 Self { offset, color }\n\ + \x20 }\n\n\ + \x20 fn to_abi(self) -> sys::AvnGradientStop {\n\ + \x20 sys::AvnGradientStop { offset: self.offset, color: self.color.into() }\n\ + \x20 }\n\n\ + \x20 fn from_abi(value: sys::AvnGradientStop) -> Self {\n\ + \x20 Self { offset: value.offset, color: value.color.into() }\n\ + \x20 }\n\ + }\n\n\ + /// Packs up to the ABI's fixed capacity of stops into an `AvnGradientStopBuffer`.\n\ + /// Fails if `stops` carries more entries than the buffer can hold.\n\ + fn gradient_stops_to_abi(stops: &[GradientStop]) -> Result {\n\ + \x20 let mut buffer = sys::AvnGradientStopBuffer::default();\n\ + \x20 if stops.len() > buffer.stops.len() {\n\ + \x20 return Err(crate::Error::Abi(sys::Error(sys::E_INVALIDARG)));\n\ + \x20 }\n\ + \x20 for (slot, stop) in buffer.stops.iter_mut().zip(stops) {\n\ + \x20 *slot = stop.to_abi();\n\ + \x20 }\n\ + \x20 Ok(buffer)\n\ + }\n\n\ + fn gradient_stops_from_abi(buffer: sys::AvnGradientStopBuffer, count: i32) -> Vec {\n\ + \x20 let count = usize::try_from(count).unwrap_or(0).min(buffer.stops.len());\n\ + \x20 buffer.stops[..count].iter().copied().map(GradientStop::from_abi).collect()\n\ + }\n\n\ + /// A linear gradient brush: colour stops interpolated along a line from\n\ + /// `start_point` to `end_point`.\n\ + #[derive(Clone, Debug, PartialEq)]\n\ + pub struct LinearGradientBrush {\n\ + \x20 pub opacity: f64,\n\ + \x20 pub spread_method: SpreadMethod,\n\ + \x20 pub stops: Vec,\n\ + \x20 pub start_point: RelativePoint,\n\ + \x20 pub end_point: RelativePoint,\n\ + }\n\n\ + impl LinearGradientBrush {\n\ + \x20 /// A fully opaque linear gradient with `SpreadMethod::Pad`.\n\ + \x20 pub fn new(stops: Vec, start_point: RelativePoint, end_point: RelativePoint) -> Self {\n\ + \x20 Self {\n\ + \x20 opacity: 1.0,\n\ + \x20 spread_method: SpreadMethod::Pad,\n\ + \x20 stops,\n\ + \x20 start_point,\n\ + \x20 end_point,\n\ + \x20 }\n\ + \x20 }\n\n\ + \x20 pub(crate) fn to_raw(&self) -> Result> {\n\ + \x20 let buffer = gradient_stops_to_abi(&self.stops)?;\n\ + \x20 let stop_count = i32::try_from(self.stops.len()).unwrap_or(i32::MAX);\n\ + \x20 with_factory(|factory| {\n\ + \x20 factory.create_linear_gradient_brush(\n\ + \x20 self.opacity,\n\ + \x20 self.spread_method as i32,\n\ + \x20 stop_count,\n\ + \x20 buffer,\n\ + \x20 self.start_point.to_abi(),\n\ + \x20 self.end_point.to_abi(),\n\ + \x20 )\n\ + \x20 })\n\ + \x20 }\n\n\ + \x20 pub(crate) fn from_raw(raw: &sys::ComPtr) -> Result {\n\ + \x20 let count = raw.stop_count()?;\n\ + \x20 Ok(Self {\n\ + \x20 opacity: raw.opacity()?,\n\ + \x20 spread_method: SpreadMethod::try_from(raw.spread_method()?)?,\n\ + \x20 stops: gradient_stops_from_abi(raw.stops()?, count),\n\ + \x20 start_point: RelativePoint::from_abi(raw.start_point()?)?,\n\ + \x20 end_point: RelativePoint::from_abi(raw.end_point()?)?,\n\ + \x20 })\n\ + \x20 }\n\ + }\n\n\ + /// A radial gradient brush: colour stops interpolated outward from\n\ + /// `gradient_origin` through an ellipse centred at `center` with radii\n\ + /// `radius_x`/`radius_y`.\n\ + #[derive(Clone, Debug, PartialEq)]\n\ + pub struct RadialGradientBrush {\n\ + \x20 pub opacity: f64,\n\ + \x20 pub spread_method: SpreadMethod,\n\ + \x20 pub stops: Vec,\n\ + \x20 pub center: RelativePoint,\n\ + \x20 pub gradient_origin: RelativePoint,\n\ + \x20 pub radius_x: RelativeScalar,\n\ + \x20 pub radius_y: RelativeScalar,\n\ + }\n\n\ + impl RadialGradientBrush {\n\ + \x20 /// A fully opaque radial gradient with `SpreadMethod::Pad`.\n\ + \x20 pub fn new(\n\ + \x20 stops: Vec,\n\ + \x20 center: RelativePoint,\n\ + \x20 gradient_origin: RelativePoint,\n\ + \x20 radius_x: RelativeScalar,\n\ + \x20 radius_y: RelativeScalar,\n\ + \x20 ) -> Self {\n\ + \x20 Self {\n\ + \x20 opacity: 1.0,\n\ + \x20 spread_method: SpreadMethod::Pad,\n\ + \x20 stops,\n\ + \x20 center,\n\ + \x20 gradient_origin,\n\ + \x20 radius_x,\n\ + \x20 radius_y,\n\ + \x20 }\n\ + \x20 }\n\n\ + \x20 pub(crate) fn to_raw(&self) -> Result> {\n\ + \x20 let buffer = gradient_stops_to_abi(&self.stops)?;\n\ + \x20 let stop_count = i32::try_from(self.stops.len()).unwrap_or(i32::MAX);\n\ + \x20 with_factory(|factory| {\n\ + \x20 factory.create_radial_gradient_brush(\n\ + \x20 self.opacity,\n\ + \x20 self.spread_method as i32,\n\ + \x20 stop_count,\n\ + \x20 buffer,\n\ + \x20 self.center.to_abi(),\n\ + \x20 self.gradient_origin.to_abi(),\n\ + \x20 self.radius_x.to_abi(),\n\ + \x20 self.radius_y.to_abi(),\n\ + \x20 )\n\ + \x20 })\n\ + \x20 }\n\n\ + \x20 pub(crate) fn from_raw(raw: &sys::ComPtr) -> Result {\n\ + \x20 let count = raw.stop_count()?;\n\ + \x20 Ok(Self {\n\ + \x20 opacity: raw.opacity()?,\n\ + \x20 spread_method: SpreadMethod::try_from(raw.spread_method()?)?,\n\ + \x20 stops: gradient_stops_from_abi(raw.stops()?, count),\n\ + \x20 center: RelativePoint::from_abi(raw.center()?)?,\n\ + \x20 gradient_origin: RelativePoint::from_abi(raw.gradient_origin()?)?,\n\ + \x20 radius_x: RelativeScalar::from_abi(raw.radius_x()?)?,\n\ + \x20 radius_y: RelativeScalar::from_abi(raw.radius_y()?)?,\n\ + \x20 })\n\ + \x20 }\n\ + }\n\n\ + /// Any brush shape that can be assigned to a `Brush`-typed control property: a\n\ + /// solid colour, or one of the two projected gradient shapes.\n\ + #[derive(Clone, Debug, PartialEq)]\n\ + pub enum Paint {\n\ + \x20 Solid(Brush),\n\ + \x20 LinearGradient(LinearGradientBrush),\n\ + \x20 RadialGradient(RadialGradientBrush),\n\ + }\n\n\ + impl Paint {\n\ + \x20 pub(crate) fn to_raw(&self) -> Result> {\n\ + \x20 match self {\n\ + \x20 Self::Solid(brush) => brush.to_raw(),\n\ + \x20 Self::LinearGradient(brush) => Ok(brush.to_raw()?.query_interface()?),\n\ + \x20 Self::RadialGradient(brush) => Ok(brush.to_raw()?.query_interface()?),\n\ + \x20 }\n\ + \x20 }\n\n\ + \x20 pub(crate) fn from_raw(raw: &sys::ComPtr) -> Result {\n\ + \x20 match raw.color() {\n\ + \x20 Ok(color) => Ok(Self::Solid(Brush::new(color.into(), raw.opacity()?))),\n\ + \x20 Err(sys::Error(sys::AVN_E_NONSOLIDBRUSH)) => {\n\ + \x20 if let Ok(linear) = raw.query_interface::() {\n\ + \x20 return Ok(Self::LinearGradient(LinearGradientBrush::from_raw(&linear)?));\n\ + \x20 }\n\ + \x20 if let Ok(radial) = raw.query_interface::() {\n\ + \x20 return Ok(Self::RadialGradient(RadialGradientBrush::from_raw(&radial)?));\n\ + \x20 }\n\ + \x20 Err(crate::Error::Abi(sys::Error(sys::AVN_E_NONSOLIDBRUSH)))\n\ + \x20 }\n\ + \x20 Err(error) => Err(error.into()),\n\ + \x20 }\n\ + \x20 }\n\ + }\n\n\ + impl From for Paint {\n\ + \x20 fn from(brush: Brush) -> Self {\n\ + \x20 Self::Solid(brush)\n\ + \x20 }\n\ + }\n\n\ + impl From for Paint {\n\ + \x20 fn from(color: Color) -> Self {\n\ + \x20 Self::Solid(Brush::solid(color))\n\ + \x20 }\n\ + }\n\n\ + impl From for Paint {\n\ + \x20 fn from(brush: LinearGradientBrush) -> Self {\n\ + \x20 Self::LinearGradient(brush)\n\ + \x20 }\n\ + }\n\n\ + impl From for Paint {\n\ + \x20 fn from(brush: RadialGradientBrush) -> Self {\n\ + \x20 Self::RadialGradient(brush)\n\ + \x20 }\n\ + }\n\n", + ) +} + fn emit_collection(property: &ProjectedProperty) -> String { let name = simple_name(property.interface_name.as_deref().expect("interfaceName")); let safe_name = name.strip_prefix("IAvn").unwrap_or(name); diff --git a/rust/avalonia-bindgen/src/ir.rs b/rust/avalonia-bindgen/src/ir.rs index e055239..f3e6f2f 100644 --- a/rust/avalonia-bindgen/src/ir.rs +++ b/rust/avalonia-bindgen/src/ir.rs @@ -8,6 +8,18 @@ pub struct ProjectionIr { pub factory_iid: Option, pub brush_interface_name: Option, pub brush_interface_iid: Option, + #[serde(default)] + pub gradient_brush_interface_name: Option, + #[serde(default)] + pub gradient_brush_interface_iid: Option, + #[serde(default)] + pub linear_gradient_brush_interface_name: Option, + #[serde(default)] + pub linear_gradient_brush_interface_iid: Option, + #[serde(default)] + pub radial_gradient_brush_interface_name: Option, + #[serde(default)] + pub radial_gradient_brush_interface_iid: Option, pub command_interface_name: Option, pub command_interface_iid: Option, #[serde(default)] diff --git a/rust/avalonia-bindgen/src/lib.rs b/rust/avalonia-bindgen/src/lib.rs index 117679d..415359c 100644 --- a/rust/avalonia-bindgen/src/lib.rs +++ b/rust/avalonia-bindgen/src/lib.rs @@ -259,11 +259,11 @@ mod tests { #[test] fn future_schema_version_is_rejected_by_public_entrypoint() { - let error = generate_from_json(r#"{ "version": 17, "types": [] }"#) + let error = generate_from_json(r#"{ "version": 18, "types": [] }"#) .unwrap_err() .to_string(); - assert!(error.contains("Unsupported projection IR version 17")); - assert!(error.contains("1..=16")); + assert!(error.contains("Unsupported projection IR version 18")); + assert!(error.contains("1..=17")); } #[test] @@ -436,9 +436,9 @@ mod tests { #[test] fn generate_from_ir_rejects_future_version() { - let ir: ProjectionIr = serde_json::from_str(r#"{ "version": 17, "types": [] }"#).unwrap(); + let ir: ProjectionIr = serde_json::from_str(r#"{ "version": 18, "types": [] }"#).unwrap(); let error = generate_from_ir(&ir).unwrap_err().to_string(); - assert!(error.contains("Unsupported projection IR version 17")); + assert!(error.contains("Unsupported projection IR version 18")); } #[test] diff --git a/rust/avalonia-bindgen/src/validate.rs b/rust/avalonia-bindgen/src/validate.rs index 1e587e2..4c561b7 100644 --- a/rust/avalonia-bindgen/src/validate.rs +++ b/rust/avalonia-bindgen/src/validate.rs @@ -5,7 +5,7 @@ use crate::ir::{ }; pub const MINIMUM_VERSION: i32 = 1; -pub const CURRENT_VERSION: i32 = 16; +pub const CURRENT_VERSION: i32 = 17; const SUPPORTED_MARSHALLING_KINDS: &[&str] = &[ "Void", diff --git a/rust/avalonia-sys/include/.avalonia-projection.owned.json b/rust/avalonia-sys/include/.avalonia-projection.owned.json index 4e05010..44aff59 100644 --- a/rust/avalonia-sys/include/.avalonia-projection.owned.json +++ b/rust/avalonia-sys/include/.avalonia-projection.owned.json @@ -3,7 +3,7 @@ "files": [ { "path": "avalonia-rust-abi.h", - "sha256": "267a44997b95dde7426d3212bf5316652f7ba923a94a8c9150749f5b2ae33175" + "sha256": "d9046a8786e5917a3c205a4b773fe0e73252ca79f2e52020d6a9188ba5b105d2" } ] } diff --git a/rust/avalonia-sys/include/avalonia-rust-abi.h b/rust/avalonia-sys/include/avalonia-rust-abi.h index c36bf62..69cccf6 100644 --- a/rust/avalonia-sys/include/avalonia-rust-abi.h +++ b/rust/avalonia-sys/include/avalonia-rust-abi.h @@ -125,6 +125,30 @@ typedef struct AvnOptionalTimeSpan { int64_t ticks; } AvnOptionalTimeSpan; +/* Blittable ABI mirror of Avalonia.RelativePoint. unit: 0 relative, 1 absolute. */ +typedef struct AvnRelativePoint { + double x; + double y; + int32_t unit; +} AvnRelativePoint; + +/* Blittable ABI mirror of Avalonia.RelativeScalar. unit: 0 relative, 1 absolute. */ +typedef struct AvnRelativeScalar { + double scalar; + int32_t unit; +} AvnRelativeScalar; + +/* Blittable ABI mirror of a single gradient stop (offset plus packed colour). */ +typedef struct AvnGradientStop { + double offset; + AvnColor color; +} AvnGradientStop; + +/* Fixed-capacity buffer of up to 8 AvnGradientStop entries. */ +typedef struct AvnGradientStopBuffer { + AvnGradientStop stops[8]; +} AvnGradientStopBuffer; + /* Tagged scalar carrying object? command parameters. */ /* tag: 0 none, 1 utf16, 2 i32, 3 f64, 4 bool. */ typedef struct AvnVariant { @@ -302,6 +326,8 @@ typedef struct IAvnFlyoutBaseClosedHandler IAvnFlyoutBaseClosedHandler; typedef struct IAvnFlyoutBaseClosedHandlerVtbl IAvnFlyoutBaseClosedHandlerVtbl; typedef struct IAvnFlyoutBaseOpenedHandler IAvnFlyoutBaseOpenedHandler; typedef struct IAvnFlyoutBaseOpenedHandlerVtbl IAvnFlyoutBaseOpenedHandlerVtbl; +typedef struct IAvnGradientBrush IAvnGradientBrush; +typedef struct IAvnGradientBrushVtbl IAvnGradientBrushVtbl; typedef struct IAvnGrid IAvnGrid; typedef struct IAvnGridVtbl IAvnGridVtbl; typedef struct IAvnGridSplitter IAvnGridSplitter; @@ -332,6 +358,8 @@ typedef struct IAvnLayoutTransformControl IAvnLayoutTransformControl; typedef struct IAvnLayoutTransformControlVtbl IAvnLayoutTransformControlVtbl; typedef struct IAvnLine IAvnLine; typedef struct IAvnLineVtbl IAvnLineVtbl; +typedef struct IAvnLinearGradientBrush IAvnLinearGradientBrush; +typedef struct IAvnLinearGradientBrushVtbl IAvnLinearGradientBrushVtbl; typedef struct IAvnListBox IAvnListBox; typedef struct IAvnListBoxVtbl IAvnListBoxVtbl; typedef struct IAvnListBoxItem IAvnListBoxItem; @@ -392,6 +420,8 @@ typedef struct IAvnPopupOpenedHandler IAvnPopupOpenedHandler; typedef struct IAvnPopupOpenedHandlerVtbl IAvnPopupOpenedHandlerVtbl; typedef struct IAvnProgressBar IAvnProgressBar; typedef struct IAvnProgressBarVtbl IAvnProgressBarVtbl; +typedef struct IAvnRadialGradientBrush IAvnRadialGradientBrush; +typedef struct IAvnRadialGradientBrushVtbl IAvnRadialGradientBrushVtbl; typedef struct IAvnRadioButton IAvnRadioButton; typedef struct IAvnRadioButtonVtbl IAvnRadioButtonVtbl; typedef struct IAvnRangeBase IAvnRangeBase; @@ -2116,6 +2146,69 @@ struct IAvnBrushVtbl { struct IAvnBrush { const IAvnBrushVtbl* vtbl; }; #define I_AVN_BRUSH_VTABLE_SLOTS 5 +static const AvnGuid I_AVN_GRADIENT_BRUSH_IID = { + 0xFDAA2353, + 0xBC44, + 0x5012, + { 0xA5, 0xBE, 0xA1, 0x7C, 0x7C, 0x01, 0xF4, 0x1A } +}; +#define I_AVN_GRADIENT_BRUSH_ABI_VERSION 1 +struct IAvnGradientBrushVtbl { + AvnHResult (AVN_CALL *query_interface)(IAvnGradientBrush* self, const AvnGuid* iid, void** result); /* slot 0 */ + uint32_t (AVN_CALL *add_ref)(IAvnGradientBrush* self); /* slot 1 */ + uint32_t (AVN_CALL *release)(IAvnGradientBrush* self); /* slot 2 */ + AvnHResult (AVN_CALL *get_opacity)(IAvnGradientBrush* self, double* value); /* slot 3 */ + AvnHResult (AVN_CALL *get_spread_method)(IAvnGradientBrush* self, int32_t* value); /* slot 4 */ + AvnHResult (AVN_CALL *get_stop_count)(IAvnGradientBrush* self, int32_t* value); /* slot 5 */ + AvnHResult (AVN_CALL *get_stops)(IAvnGradientBrush* self, AvnGradientStopBuffer* value); /* slot 6 */ +}; +struct IAvnGradientBrush { const IAvnGradientBrushVtbl* vtbl; }; +#define I_AVN_GRADIENT_BRUSH_VTABLE_SLOTS 7 + +static const AvnGuid I_AVN_LINEAR_GRADIENT_BRUSH_IID = { + 0x40B3D53D, + 0x330E, + 0x5D63, + { 0xA0, 0x40, 0x37, 0xF1, 0xFF, 0x71, 0x7F, 0xF8 } +}; +#define I_AVN_LINEAR_GRADIENT_BRUSH_ABI_VERSION 1 +struct IAvnLinearGradientBrushVtbl { + AvnHResult (AVN_CALL *query_interface)(IAvnLinearGradientBrush* self, const AvnGuid* iid, void** result); /* slot 0 */ + uint32_t (AVN_CALL *add_ref)(IAvnLinearGradientBrush* self); /* slot 1 */ + uint32_t (AVN_CALL *release)(IAvnLinearGradientBrush* self); /* slot 2 */ + AvnHResult (AVN_CALL *get_opacity)(IAvnLinearGradientBrush* self, double* value); /* slot 3 */ + AvnHResult (AVN_CALL *get_spread_method)(IAvnLinearGradientBrush* self, int32_t* value); /* slot 4 */ + AvnHResult (AVN_CALL *get_stop_count)(IAvnLinearGradientBrush* self, int32_t* value); /* slot 5 */ + AvnHResult (AVN_CALL *get_stops)(IAvnLinearGradientBrush* self, AvnGradientStopBuffer* value); /* slot 6 */ + AvnHResult (AVN_CALL *get_start_point)(IAvnLinearGradientBrush* self, AvnRelativePoint* value); /* slot 7 */ + AvnHResult (AVN_CALL *get_end_point)(IAvnLinearGradientBrush* self, AvnRelativePoint* value); /* slot 8 */ +}; +struct IAvnLinearGradientBrush { const IAvnLinearGradientBrushVtbl* vtbl; }; +#define I_AVN_LINEAR_GRADIENT_BRUSH_VTABLE_SLOTS 9 + +static const AvnGuid I_AVN_RADIAL_GRADIENT_BRUSH_IID = { + 0xAEC23FCE, + 0x9FEA, + 0x506C, + { 0xAB, 0xC4, 0x77, 0x41, 0x43, 0xBE, 0x80, 0xC8 } +}; +#define I_AVN_RADIAL_GRADIENT_BRUSH_ABI_VERSION 1 +struct IAvnRadialGradientBrushVtbl { + AvnHResult (AVN_CALL *query_interface)(IAvnRadialGradientBrush* self, const AvnGuid* iid, void** result); /* slot 0 */ + uint32_t (AVN_CALL *add_ref)(IAvnRadialGradientBrush* self); /* slot 1 */ + uint32_t (AVN_CALL *release)(IAvnRadialGradientBrush* self); /* slot 2 */ + AvnHResult (AVN_CALL *get_opacity)(IAvnRadialGradientBrush* self, double* value); /* slot 3 */ + AvnHResult (AVN_CALL *get_spread_method)(IAvnRadialGradientBrush* self, int32_t* value); /* slot 4 */ + AvnHResult (AVN_CALL *get_stop_count)(IAvnRadialGradientBrush* self, int32_t* value); /* slot 5 */ + AvnHResult (AVN_CALL *get_stops)(IAvnRadialGradientBrush* self, AvnGradientStopBuffer* value); /* slot 6 */ + AvnHResult (AVN_CALL *get_center)(IAvnRadialGradientBrush* self, AvnRelativePoint* value); /* slot 7 */ + AvnHResult (AVN_CALL *get_gradient_origin)(IAvnRadialGradientBrush* self, AvnRelativePoint* value); /* slot 8 */ + AvnHResult (AVN_CALL *get_radius_x)(IAvnRadialGradientBrush* self, AvnRelativeScalar* value); /* slot 9 */ + AvnHResult (AVN_CALL *get_radius_y)(IAvnRadialGradientBrush* self, AvnRelativeScalar* value); /* slot 10 */ +}; +struct IAvnRadialGradientBrush { const IAvnRadialGradientBrushVtbl* vtbl; }; +#define I_AVN_RADIAL_GRADIENT_BRUSH_VTABLE_SLOTS 11 + static const AvnGuid I_AVN_COMMAND_CAN_EXECUTE_CHANGED_HANDLER_IID = { 0x13E58040, 0xB570, @@ -16239,12 +16332,12 @@ struct IAvnToolTipStatics { const IAvnToolTipStaticsVtbl* vtbl; }; #define I_AVN_TOOL_TIP_STATICS_VTABLE_SLOTS 21 static const AvnGuid I_AVN_CONTROL_FACTORY_IID = { - 0x15778134, - 0x9E9F, - 0x5BAF, - { 0x98, 0xFF, 0x55, 0x10, 0x77, 0x80, 0x94, 0xBA } + 0xC8BCE8E8, + 0x62C7, + 0x5E0E, + { 0x80, 0x66, 0x69, 0x00, 0x59, 0xF5, 0x5D, 0xFF } }; -#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13 +#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14 struct IAvnControlFactoryVtbl { AvnHResult (AVN_CALL *query_interface)(IAvnControlFactory* self, const AvnGuid* iid, void** result); /* slot 0 */ uint32_t (AVN_CALL *add_ref)(IAvnControlFactory* self); /* slot 1 */ @@ -16352,8 +16445,10 @@ struct IAvnControlFactoryVtbl { AvnHResult (AVN_CALL *get_relative_panel_statics)(IAvnControlFactory* self, IAvnRelativePanelStatics** value); /* slot 103 */ AvnHResult (AVN_CALL *get_tool_tip_statics)(IAvnControlFactory* self, IAvnToolTipStatics** value); /* slot 104 */ AvnHResult (AVN_CALL *create_solid_color_brush)(IAvnControlFactory* self, AvnColor color, double opacity, IAvnBrush** value); /* slot 105 */ + AvnHResult (AVN_CALL *create_linear_gradient_brush)(IAvnControlFactory* self, double opacity, int32_t spread_method, int32_t stop_count, AvnGradientStopBuffer stops, AvnRelativePoint start_point, AvnRelativePoint end_point, IAvnLinearGradientBrush** value); /* slot 106 */ + AvnHResult (AVN_CALL *create_radial_gradient_brush)(IAvnControlFactory* self, double opacity, int32_t spread_method, int32_t stop_count, AvnGradientStopBuffer stops, AvnRelativePoint center, AvnRelativePoint gradient_origin, AvnRelativeScalar radius_x, AvnRelativeScalar radius_y, IAvnRadialGradientBrush** value); /* slot 107 */ }; struct IAvnControlFactory { const IAvnControlFactoryVtbl* vtbl; }; -#define I_AVN_CONTROL_FACTORY_VTABLE_SLOTS 106 +#define I_AVN_CONTROL_FACTORY_VTABLE_SLOTS 108 #endif /* AVALONIA_RUST_ABI_H */ diff --git a/rust/avalonia-sys/src/.avalonia-bindgen.owned.json b/rust/avalonia-sys/src/.avalonia-bindgen.owned.json index 43f893d..656d4be 100644 --- a/rust/avalonia-sys/src/.avalonia-bindgen.owned.json +++ b/rust/avalonia-sys/src/.avalonia-bindgen.owned.json @@ -3,7 +3,7 @@ "files": [ { "path": "generated.rs", - "sha256": "268263810f8f0b26523e9b1991e9e47e9001c05007b04a0373fe2a44811a844a" + "sha256": "4db8abe8997bc5ac8b94e9aafbf282743c1dcee0302cc1ad62c1874c4d5e9544" } ] } diff --git a/rust/avalonia-sys/src/generated.rs b/rust/avalonia-sys/src/generated.rs index ffd2337..a7c3c25 100644 --- a/rust/avalonia-sys/src/generated.rs +++ b/rust/avalonia-sys/src/generated.rs @@ -305,6 +305,256 @@ impl ComPtr { } } +/// Blittable ABI mirror of Avalonia.RelativePoint. unit: 0 relative, 1 absolute. +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct AvnRelativePoint { + pub x: f64, + pub y: f64, + pub unit: i32, +} + +/// Blittable ABI mirror of Avalonia.RelativeScalar. unit: 0 relative, 1 absolute. +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct AvnRelativeScalar { + pub scalar: f64, + pub unit: i32, +} + +/// Blittable ABI mirror of a single gradient stop (offset plus packed colour). +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct AvnGradientStop { + pub offset: f64, + pub color: AvnColor, +} + +/// Fixed-capacity buffer of up to 8 `AvnGradientStop` entries. +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct AvnGradientStopBuffer { + pub stops: [AvnGradientStop; 8], +} + +impl Default for AvnGradientStopBuffer { + fn default() -> Self { + Self { stops: [AvnGradientStop::default(); 8] } + } +} + +/// Capability shared by every gradient brush kind projected across the ABI. +pub const I_AVN_GRADIENT_BRUSH_IID: Guid = Guid { data1: 0xFDAA2353, data2: 0xBC44, data3: 0x5012, data4: [0xA5, 0xBE, 0xA1, 0x7C, 0x7C, 0x01, 0xF4, 0x1A] }; + +#[repr(C)] +struct IAvnGradientBrushVtbl { + query_interface: unsafe extern "system" fn(*mut IUnknown, *const Guid, *mut *mut c_void) -> i32, + add_ref: unsafe extern "system" fn(*mut IUnknown) -> u32, + release: unsafe extern "system" fn(*mut IUnknown) -> u32, + get_opacity: unsafe extern "system" fn(*mut IAvnGradientBrush, *mut f64) -> i32, + get_spread_method: unsafe extern "system" fn(*mut IAvnGradientBrush, *mut i32) -> i32, + get_stop_count: unsafe extern "system" fn(*mut IAvnGradientBrush, *mut i32) -> i32, + get_stops: unsafe extern "system" fn(*mut IAvnGradientBrush, *mut AvnGradientStopBuffer) -> i32, +} + +#[repr(C)] +pub struct IAvnGradientBrush { + vtbl: *const IAvnGradientBrushVtbl, +} + +unsafe impl ComInterface for IAvnGradientBrush { + const IID: Guid = I_AVN_GRADIENT_BRUSH_IID; +} + +impl ComPtr { + pub fn opacity(&self) -> Result { + unsafe { + let mut value = 0.0; + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_opacity)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + /// 0 = Pad, 1 = Reflect, 2 = Repeat. + pub fn spread_method(&self) -> Result { + unsafe { + let mut value = 0; + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_spread_method)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + pub fn stop_count(&self) -> Result { + unsafe { + let mut value = 0; + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_stop_count)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + pub fn stops(&self) -> Result { + unsafe { + let mut value = AvnGradientStopBuffer::default(); + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_stops)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } +} + +#[repr(C)] +struct IAvnLinearGradientBrushVtbl { + query_interface: unsafe extern "system" fn(*mut IUnknown, *const Guid, *mut *mut c_void) -> i32, + add_ref: unsafe extern "system" fn(*mut IUnknown) -> u32, + release: unsafe extern "system" fn(*mut IUnknown) -> u32, + get_opacity: unsafe extern "system" fn(*mut IAvnLinearGradientBrush, *mut f64) -> i32, + get_spread_method: unsafe extern "system" fn(*mut IAvnLinearGradientBrush, *mut i32) -> i32, + get_stop_count: unsafe extern "system" fn(*mut IAvnLinearGradientBrush, *mut i32) -> i32, + get_stops: unsafe extern "system" fn(*mut IAvnLinearGradientBrush, *mut AvnGradientStopBuffer) -> i32, + get_start_point: unsafe extern "system" fn(*mut IAvnLinearGradientBrush, *mut AvnRelativePoint) -> i32, + get_end_point: unsafe extern "system" fn(*mut IAvnLinearGradientBrush, *mut AvnRelativePoint) -> i32, +} + +#[repr(C)] +pub struct IAvnLinearGradientBrush { + vtbl: *const IAvnLinearGradientBrushVtbl, +} + +unsafe impl ComInterface for IAvnLinearGradientBrush { + const IID: Guid = I_AVN_LINEAR_GRADIENT_BRUSH_IID; +} + +pub const I_AVN_LINEAR_GRADIENT_BRUSH_IID: Guid = Guid { data1: 0x40B3D53D, data2: 0x330E, data3: 0x5D63, data4: [0xA0, 0x40, 0x37, 0xF1, 0xFF, 0x71, 0x7F, 0xF8] }; + +impl ComPtr { + pub fn opacity(&self) -> Result { + unsafe { + let mut value = 0.0; + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_opacity)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + /// 0 = Pad, 1 = Reflect, 2 = Repeat. + pub fn spread_method(&self) -> Result { + unsafe { + let mut value = 0; + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_spread_method)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + pub fn stop_count(&self) -> Result { + unsafe { + let mut value = 0; + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_stop_count)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + pub fn stops(&self) -> Result { + unsafe { + let mut value = AvnGradientStopBuffer::default(); + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_stops)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + pub fn start_point(&self) -> Result { + unsafe { + let mut value = AvnRelativePoint::default(); + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_start_point)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + pub fn end_point(&self) -> Result { + unsafe { + let mut value = AvnRelativePoint::default(); + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_end_point)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } +} + +#[repr(C)] +struct IAvnRadialGradientBrushVtbl { + query_interface: unsafe extern "system" fn(*mut IUnknown, *const Guid, *mut *mut c_void) -> i32, + add_ref: unsafe extern "system" fn(*mut IUnknown) -> u32, + release: unsafe extern "system" fn(*mut IUnknown) -> u32, + get_opacity: unsafe extern "system" fn(*mut IAvnRadialGradientBrush, *mut f64) -> i32, + get_spread_method: unsafe extern "system" fn(*mut IAvnRadialGradientBrush, *mut i32) -> i32, + get_stop_count: unsafe extern "system" fn(*mut IAvnRadialGradientBrush, *mut i32) -> i32, + get_stops: unsafe extern "system" fn(*mut IAvnRadialGradientBrush, *mut AvnGradientStopBuffer) -> i32, + get_center: unsafe extern "system" fn(*mut IAvnRadialGradientBrush, *mut AvnRelativePoint) -> i32, + get_gradient_origin: unsafe extern "system" fn(*mut IAvnRadialGradientBrush, *mut AvnRelativePoint) -> i32, + get_radius_x: unsafe extern "system" fn(*mut IAvnRadialGradientBrush, *mut AvnRelativeScalar) -> i32, + get_radius_y: unsafe extern "system" fn(*mut IAvnRadialGradientBrush, *mut AvnRelativeScalar) -> i32, +} + +#[repr(C)] +pub struct IAvnRadialGradientBrush { + vtbl: *const IAvnRadialGradientBrushVtbl, +} + +unsafe impl ComInterface for IAvnRadialGradientBrush { + const IID: Guid = I_AVN_RADIAL_GRADIENT_BRUSH_IID; +} + +pub const I_AVN_RADIAL_GRADIENT_BRUSH_IID: Guid = Guid { data1: 0xAEC23FCE, data2: 0x9FEA, data3: 0x506C, data4: [0xAB, 0xC4, 0x77, 0x41, 0x43, 0xBE, 0x80, 0xC8] }; + +impl ComPtr { + pub fn opacity(&self) -> Result { + unsafe { + let mut value = 0.0; + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_opacity)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + /// 0 = Pad, 1 = Reflect, 2 = Repeat. + pub fn spread_method(&self) -> Result { + unsafe { + let mut value = 0; + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_spread_method)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + pub fn stop_count(&self) -> Result { + unsafe { + let mut value = 0; + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_stop_count)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + pub fn stops(&self) -> Result { + unsafe { + let mut value = AvnGradientStopBuffer::default(); + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_stops)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + pub fn center(&self) -> Result { + unsafe { + let mut value = AvnRelativePoint::default(); + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_center)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + pub fn gradient_origin(&self) -> Result { + unsafe { + let mut value = AvnRelativePoint::default(); + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_gradient_origin)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + pub fn radius_x(&self) -> Result { + unsafe { + let mut value = AvnRelativeScalar::default(); + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_radius_x)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } + pub fn radius_y(&self) -> Result { + unsafe { + let mut value = AvnRelativeScalar::default(); + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().get_radius_y)(self.as_raw(), &mut value); + hresult::check(hr).map(|_| value) + } + } +} + + pub const I_AVN_COMMAND_IID: Guid = Guid { data1: 0xE6F7AAF7, data2: 0xD5E7, data3: 0x503F, data4: [0x9B, 0xE6, 0x5A, 0xF8, 0xDB, 0x5B, 0x52, 0x73] }; #[repr(C)] @@ -104862,7 +105112,7 @@ impl ComPtr { } } -pub const IAVN_CONTROL_FACTORY_IID: Guid = Guid { data1: 0x15778134, data2: 0x9E9F, data3: 0x5BAF, data4: [0x98, 0xFF, 0x55, 0x10, 0x77, 0x80, 0x94, 0xBA] }; +pub const IAVN_CONTROL_FACTORY_IID: Guid = Guid { data1: 0xC8BCE8E8, data2: 0x62C7, data3: 0x5E0E, data4: [0x80, 0x66, 0x69, 0x00, 0x59, 0xF5, 0x5D, 0xFF] }; #[repr(C)] struct IAvnControlFactoryVtbl { @@ -104972,6 +105222,8 @@ struct IAvnControlFactoryVtbl { get_relative_panel_statics: unsafe extern "system" fn(*mut IAvnControlFactory, *mut *mut IAvnRelativePanelStatics) -> i32, get_tool_tip_statics: unsafe extern "system" fn(*mut IAvnControlFactory, *mut *mut IAvnToolTipStatics) -> i32, create_solid_color_brush: unsafe extern "system" fn(*mut IAvnControlFactory, AvnColor, f64, *mut *mut IAvnBrush) -> i32, + create_linear_gradient_brush: unsafe extern "system" fn(*mut IAvnControlFactory, f64, i32, i32, AvnGradientStopBuffer, AvnRelativePoint, AvnRelativePoint, *mut *mut IAvnLinearGradientBrush) -> i32, + create_radial_gradient_brush: unsafe extern "system" fn(*mut IAvnControlFactory, f64, i32, i32, AvnGradientStopBuffer, AvnRelativePoint, AvnRelativePoint, AvnRelativeScalar, AvnRelativeScalar, *mut *mut IAvnRadialGradientBrush) -> i32, } #[repr(C)] @@ -105808,4 +106060,44 @@ impl ComPtr { ComPtr::from_raw(value).ok_or(Error(hresult::E_POINTER)) } } + #[allow(clippy::too_many_arguments)] + pub fn create_linear_gradient_brush( + &self, + opacity: f64, + spread_method: i32, + stop_count: i32, + stops: AvnGradientStopBuffer, + start_point: AvnRelativePoint, + end_point: AvnRelativePoint, + ) -> Result> { + unsafe { + let mut value = ptr::null_mut(); + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().create_linear_gradient_brush)( + self.as_raw(), opacity, spread_method, stop_count, stops, start_point, end_point, &mut value, + ); + hresult::check(hr)?; + ComPtr::from_raw(value).ok_or(Error(hresult::E_POINTER)) + } + } + #[allow(clippy::too_many_arguments)] + pub fn create_radial_gradient_brush( + &self, + opacity: f64, + spread_method: i32, + stop_count: i32, + stops: AvnGradientStopBuffer, + center: AvnRelativePoint, + gradient_origin: AvnRelativePoint, + radius_x: AvnRelativeScalar, + radius_y: AvnRelativeScalar, + ) -> Result> { + unsafe { + let mut value = ptr::null_mut(); + let hr = ((*self.as_raw()).vtbl.as_ref().unwrap().create_radial_gradient_brush)( + self.as_raw(), opacity, spread_method, stop_count, stops, center, gradient_origin, radius_x, radius_y, &mut value, + ); + hresult::check(hr)?; + ComPtr::from_raw(value).ok_or(Error(hresult::E_POINTER)) + } + } } diff --git a/rust/avalonia-sys/src/hresult.rs b/rust/avalonia-sys/src/hresult.rs index bc7103d..cf7da18 100644 --- a/rust/avalonia-sys/src/hresult.rs +++ b/rust/avalonia-sys/src/hresult.rs @@ -5,6 +5,9 @@ pub const E_INVALIDARG: i32 = 0x8007_0057u32 as i32; pub const E_NOINTERFACE: i32 = 0x8000_4002u32 as i32; pub const E_NOTIMPL: i32 = 0x8000_4001u32 as i32; pub const AVN_E_FIXTURE: i32 = 0xA7A7_0001u32 as i32; +/// Returned by `IAvnBrush::GetColor` when the underlying brush is a gradient, +/// drawing, or visual brush rather than a solid colour. +pub const AVN_E_NONSOLIDBRUSH: i32 = 0xA7A7_0002u32 as i32; pub fn succeeded(hr: i32) -> bool { hr >= 0 diff --git a/rust/avalonia-sys/src/lib.rs b/rust/avalonia-sys/src/lib.rs index 5da6788..8baba3e 100644 --- a/rust/avalonia-sys/src/lib.rs +++ b/rust/avalonia-sys/src/lib.rs @@ -54,7 +54,8 @@ pub use filters::{item_filter, text_filter, ItemFilter, TextFilter}; pub use generated::*; pub use guid::Guid; pub use hresult::{ - Error, Result, AVN_E_FIXTURE, E_FAIL, E_INVALIDARG, E_NOINTERFACE, E_NOTIMPL, E_POINTER, S_OK, + Error, Result, AVN_E_FIXTURE, AVN_E_NONSOLIDBRUSH, E_FAIL, E_INVALIDARG, E_NOINTERFACE, + E_NOTIMPL, E_POINTER, S_OK, }; pub use notification::{notification, Notification, NotificationSpec}; pub use popup_placement::{popup_placement, PopupPlacement, PopupPlacementResult}; diff --git a/rust/avalonia-sys/tests/brush_abi.rs b/rust/avalonia-sys/tests/brush_abi.rs index 0df4998..d5109e7 100644 --- a/rust/avalonia-sys/tests/brush_abi.rs +++ b/rust/avalonia-sys/tests/brush_abi.rs @@ -30,7 +30,6 @@ fn brush_publishes_a_read_only_colour_and_opacity_vtable() { for forbidden in [ "*set_color)(IAvnBrush*", "*set_opacity)(IAvnBrush*", - "IAvnGradientBrush", "IAvnDrawingBrush", "IAvnVisualBrush", ] { @@ -78,8 +77,10 @@ fn chrome_wave_interfaces_publish_abi_version_four() { "#define I_AVN_TEMPLATED_CONTROL_ABI_VERSION 15", "#define I_AVN_TEXT_BLOCK_ABI_VERSION 17", // The factory grew create_solid_color_brush at version 2, a creator per wave A control - // at version 3, and a creator per constructible wave B type at version 4. - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + // at version 3, a creator per constructible wave B type at version 4, and the gradient + // brush creators (create_linear_gradient_brush/create_radial_gradient_brush) moved it + // to version 14. + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", // Nothing was added to StyledElement, Control or Decorator, and none of their bases // moved, so their flattened vtables are byte-identical to version 3. "#define I_AVN_STYLED_ELEMENT_ABI_VERSION 6", diff --git a/rust/avalonia-sys/tests/control_abi.rs b/rust/avalonia-sys/tests/control_abi.rs index 550b85a..95fcb78 100644 --- a/rust/avalonia-sys/tests/control_abi.rs +++ b/rust/avalonia-sys/tests/control_abi.rs @@ -116,7 +116,7 @@ fn widened_interfaces_publish_abi_version_five() { "#define I_AVN_AVALONIA_OBJECT_ABI_VERSION 2", // The factory gained a creator per wave A control plus get_tool_tip_statics at version // 3, and a creator per constructible wave B type at version 4. - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia-sys/tests/definitions_abi.rs b/rust/avalonia-sys/tests/definitions_abi.rs index ead1a44..3065d53 100644 --- a/rust/avalonia-sys/tests/definitions_abi.rs +++ b/rust/avalonia-sys/tests/definitions_abi.rs @@ -59,7 +59,7 @@ fn only_grid_moved_to_abi_version_five_for_the_definitions() { // The factory mints no definition object, but wave A gave it a creator per new control // and get_tool_tip_statics and wave B gave it seven more, so it now publishes at // version 4. - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia-sys/tests/gradient_brush_abi.rs b/rust/avalonia-sys/tests/gradient_brush_abi.rs new file mode 100644 index 0000000..e99632e --- /dev/null +++ b/rust/avalonia-sys/tests/gradient_brush_abi.rs @@ -0,0 +1,106 @@ +//! ABI guarantees for the gradient brush capability interfaces. +//! +//! Gradients follow the sibling-interface pattern rather than widening `IAvnBrush`: +//! `IAvnGradientBrush` carries the members every gradient shares, and +//! `IAvnLinearGradientBrush`/`IAvnRadialGradientBrush` each derive from it and add their own +//! geometry. `IAvnBrush` itself keeps the IID and vtable it published with in the solid-brush +//! wave (see `brush_abi.rs`); only `IAvnControlFactory` republishes, to gain the two new +//! creator slots. + +use avalonia_sys::{ + I_AVN_BRUSH_IID, I_AVN_GRADIENT_BRUSH_IID, I_AVN_LINEAR_GRADIENT_BRUSH_IID, + I_AVN_RADIAL_GRADIENT_BRUSH_IID, +}; + +const HEADER: &str = include_str!("../include/avalonia-rust-abi.h"); + +#[test] +fn gradient_brush_publishes_the_shared_read_only_members() { + for expected in [ + "typedef struct IAvnGradientBrush IAvnGradientBrush;", + "*get_opacity)(IAvnGradientBrush* self, double* value)", + "*get_spread_method)(IAvnGradientBrush* self, int32_t* value)", + "*get_stop_count)(IAvnGradientBrush* self, int32_t* value)", + "*get_stops)(IAvnGradientBrush* self, AvnGradientStopBuffer* value)", + "#define I_AVN_GRADIENT_BRUSH_VTABLE_SLOTS 7", + "#define I_AVN_GRADIENT_BRUSH_ABI_VERSION 1", + ] { + assert!(HEADER.contains(expected), "header is missing `{expected}`"); + } +} + +#[test] +fn linear_gradient_brush_adds_its_start_and_end_point() { + for expected in [ + "typedef struct IAvnLinearGradientBrush IAvnLinearGradientBrush;", + "*get_start_point)(IAvnLinearGradientBrush* self, AvnRelativePoint* value)", + "*get_end_point)(IAvnLinearGradientBrush* self, AvnRelativePoint* value)", + "#define I_AVN_LINEAR_GRADIENT_BRUSH_VTABLE_SLOTS 9", + "#define I_AVN_LINEAR_GRADIENT_BRUSH_ABI_VERSION 1", + ] { + assert!(HEADER.contains(expected), "header is missing `{expected}`"); + } +} + +#[test] +fn radial_gradient_brush_adds_its_ellipse_geometry() { + for expected in [ + "typedef struct IAvnRadialGradientBrush IAvnRadialGradientBrush;", + "*get_center)(IAvnRadialGradientBrush* self, AvnRelativePoint* value)", + "*get_gradient_origin)(IAvnRadialGradientBrush* self, AvnRelativePoint* value)", + "*get_radius_x)(IAvnRadialGradientBrush* self, AvnRelativeScalar* value)", + "*get_radius_y)(IAvnRadialGradientBrush* self, AvnRelativeScalar* value)", + "#define I_AVN_RADIAL_GRADIENT_BRUSH_VTABLE_SLOTS 11", + "#define I_AVN_RADIAL_GRADIENT_BRUSH_ABI_VERSION 1", + ] { + assert!(HEADER.contains(expected), "header is missing `{expected}`"); + } +} + +#[test] +fn gradients_are_minted_by_the_factory_and_carry_a_fixed_capacity_stop_buffer() { + assert!(HEADER.contains( + "*create_linear_gradient_brush)(IAvnControlFactory* self, double opacity, \ + int32_t spread_method, int32_t stop_count, AvnGradientStopBuffer stops, \ + AvnRelativePoint start_point, AvnRelativePoint end_point, \ + IAvnLinearGradientBrush** value)" + )); + assert!(HEADER.contains( + "*create_radial_gradient_brush)(IAvnControlFactory* self, double opacity, \ + int32_t spread_method, int32_t stop_count, AvnGradientStopBuffer stops, \ + AvnRelativePoint center, AvnRelativePoint gradient_origin, \ + AvnRelativeScalar radius_x, AvnRelativeScalar radius_y, \ + IAvnRadialGradientBrush** value)" + )); + assert!(HEADER.contains("AvnGradientStop stops[8];")); +} + +#[test] +fn gradient_interfaces_are_brand_new_and_distinct_from_each_other_and_from_brush() { + let iids = [ + ("IAvnBrush", I_AVN_BRUSH_IID), + ("IAvnGradientBrush", I_AVN_GRADIENT_BRUSH_IID), + ("IAvnLinearGradientBrush", I_AVN_LINEAR_GRADIENT_BRUSH_IID), + ("IAvnRadialGradientBrush", I_AVN_RADIAL_GRADIENT_BRUSH_IID), + ]; + for (i, (name_a, iid_a)) in iids.iter().enumerate() { + for (name_b, iid_b) in &iids[i + 1..] { + assert_ne!( + format_iid(iid_a), + format_iid(iid_b), + "{name_a} and {name_b} must not share an IID" + ); + } + } +} + +fn format_iid(iid: &avalonia_sys::Guid) -> String { + let mut out = format!("{:08X}-{:04X}-{:04X}-", iid.data1, iid.data2, iid.data3); + for (index, byte) in iid.data4.iter().enumerate() { + if index == 2 { + out.push('-'); + } + out.push_str(&format!("{byte:02X}")); + } + out +} diff --git a/rust/avalonia-sys/tests/wave_a_abi.rs b/rust/avalonia-sys/tests/wave_a_abi.rs index 41c9a4f..a1bc74f 100644 --- a/rust/avalonia-sys/tests/wave_a_abi.rs +++ b/rust/avalonia-sys/tests/wave_a_abi.rs @@ -80,7 +80,7 @@ fn wave_a_interfaces_publish_abi_version_one_and_nothing_else_moved() { "#define I_AVN_HEADERED_CONTENT_CONTROL_ABI_VERSION 16", // Only the factory grew slots. Wave B moved it again, from 3 to 4, for its own // creators; every wave A interface still publishes at version 1. - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia-sys/tests/wave_b_abi.rs b/rust/avalonia-sys/tests/wave_b_abi.rs index 641f569..ff42e19 100644 --- a/rust/avalonia-sys/tests/wave_b_abi.rs +++ b/rust/avalonia-sys/tests/wave_b_abi.rs @@ -151,7 +151,7 @@ fn the_factory_gains_a_creator_per_constructible_wave_b_type() { "*create_date_picker)(IAvnControlFactory* self, IAvnDatePicker** value)", "*create_time_picker)(IAvnControlFactory* self, IAvnTimePicker** value)", "*create_headered_selecting_items_control)(IAvnControlFactory* self, IAvnHeaderedSelectingItemsControl** value)", - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia-sys/tests/wave_c_abi.rs b/rust/avalonia-sys/tests/wave_c_abi.rs index 4517085..4f93e71 100644 --- a/rust/avalonia-sys/tests/wave_c_abi.rs +++ b/rust/avalonia-sys/tests/wave_c_abi.rs @@ -73,7 +73,7 @@ fn viewbox_child_is_a_control_and_grid_splitter_sits_on_thumb() { "*advise_drag_delta)(IAvnThumb* self, IAvnThumbDragDeltaHandler* handler, int64_t* subscription_id)", "*create_thumb)(IAvnControlFactory* self, IAvnThumb** value)", "*create_grid_splitter)(IAvnControlFactory* self, IAvnGridSplitter** value)", - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia-sys/tests/wave_d_abi.rs b/rust/avalonia-sys/tests/wave_d_abi.rs index 1a71b68..09a330e 100644 --- a/rust/avalonia-sys/tests/wave_d_abi.rs +++ b/rust/avalonia-sys/tests/wave_d_abi.rs @@ -36,7 +36,7 @@ fn split_button_carries_click_and_command() { "*create_menu_flyout)(IAvnControlFactory* self, IAvnMenuFlyout** value)", "#define I_AVN_SPLIT_BUTTON_ABI_VERSION 15", "#define I_AVN_TOGGLE_SPLIT_BUTTON_ABI_VERSION 15", - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia-sys/tests/wave_e_abi.rs b/rust/avalonia-sys/tests/wave_e_abi.rs index cbba856..71eddb3 100644 --- a/rust/avalonia-sys/tests/wave_e_abi.rs +++ b/rust/avalonia-sys/tests/wave_e_abi.rs @@ -11,7 +11,7 @@ fn numeric_up_down_decimals_are_utf16_strings() { "*set_increment)(IAvnNumericUpDown* self, const uint16_t* value)", "*create_numeric_up_down)(IAvnControlFactory* self, IAvnNumericUpDown** value)", "#define I_AVN_NUMERIC_UP_DOWN_ABI_VERSION 13", - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia-sys/tests/wave_f_abi.rs b/rust/avalonia-sys/tests/wave_f_abi.rs index f1b4ab7..feaa7a2 100644 --- a/rust/avalonia-sys/tests/wave_f_abi.rs +++ b/rust/avalonia-sys/tests/wave_f_abi.rs @@ -13,7 +13,7 @@ fn calendar_days_are_yyyy_mm_dd_strings() { "*create_calendar_date_picker)(IAvnControlFactory* self, IAvnCalendarDatePicker** value)", "#define I_AVN_CALENDAR_ABI_VERSION 15", "#define I_AVN_CALENDAR_DATE_PICKER_ABI_VERSION 14", - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia-sys/tests/wave_g_abi.rs b/rust/avalonia-sys/tests/wave_g_abi.rs index 3b2dcc7..d932bb1 100644 --- a/rust/avalonia-sys/tests/wave_g_abi.rs +++ b/rust/avalonia-sys/tests/wave_g_abi.rs @@ -18,7 +18,7 @@ fn content_chrome_publishes_at_version_one() { "*create_group_box)(IAvnControlFactory* self, IAvnGroupBox** value)", "*create_user_control)(IAvnControlFactory* self, IAvnUserControl** value)", "#define I_AVN_CAROUSEL_ABI_VERSION 16", - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia-sys/tests/wave_h_abi.rs b/rust/avalonia-sys/tests/wave_h_abi.rs index a5d1d24..b47a4fa 100644 --- a/rust/avalonia-sys/tests/wave_h_abi.rs +++ b/rust/avalonia-sys/tests/wave_h_abi.rs @@ -17,7 +17,7 @@ fn shapes_carry_brushes_points_and_path_data() { "*create_line)(IAvnControlFactory* self, IAvnLine** value)", "*create_path)(IAvnControlFactory* self, IAvnPath** value)", "#define I_AVN_SHAPE_ABI_VERSION 11", - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia-sys/tests/wave_i_abi.rs b/rust/avalonia-sys/tests/wave_i_abi.rs index 870f1bc..ecf98f0 100644 --- a/rust/avalonia-sys/tests/wave_i_abi.rs +++ b/rust/avalonia-sys/tests/wave_i_abi.rs @@ -22,7 +22,7 @@ fn overlay_controls_publish_at_version_one() { "*create_tray_icon)(IAvnControlFactory* self, IAvnTrayIcon** value)", "#define I_AVN_POPUP_ABI_VERSION 11", "#define I_AVN_TRAY_ICON_ABI_VERSION 3", - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia-sys/tests/wave_j_abi.rs b/rust/avalonia-sys/tests/wave_j_abi.rs index 2aadd0f..f9bc473 100644 --- a/rust/avalonia-sys/tests/wave_j_abi.rs +++ b/rust/avalonia-sys/tests/wave_j_abi.rs @@ -15,7 +15,7 @@ fn command_bar_family_publishes_at_version_one() { "*create_theme_variant_scope)(IAvnControlFactory* self, IAvnThemeVariantScope** value)", "#define I_AVN_COMMAND_BAR_ABI_VERSION 15", "#define I_AVN_PIPS_PAGER_ABI_VERSION 13", - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia-sys/tests/wave_k_abi.rs b/rust/avalonia-sys/tests/wave_k_abi.rs index 39d5acd..dc29ff1 100644 --- a/rust/avalonia-sys/tests/wave_k_abi.rs +++ b/rust/avalonia-sys/tests/wave_k_abi.rs @@ -13,7 +13,7 @@ fn icons_and_table_view_publish_at_version_one() { "*create_table_view_column)(IAvnControlFactory* self, IAvnTableViewColumn** value)", "#define I_AVN_PATH_ICON_ABI_VERSION 12", "#define I_AVN_TABLE_VIEW_ABI_VERSION 16", - "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 13", + "#define I_AVN_CONTROL_FACTORY_ABI_VERSION 14", ] { assert!(HEADER.contains(expected), "header is missing `{expected}`"); } diff --git a/rust/avalonia/src/.avalonia-bindgen.owned.json b/rust/avalonia/src/.avalonia-bindgen.owned.json index da09294..f1c6744 100644 --- a/rust/avalonia/src/.avalonia-bindgen.owned.json +++ b/rust/avalonia/src/.avalonia-bindgen.owned.json @@ -3,7 +3,7 @@ "files": [ { "path": "generated.rs", - "sha256": "b120c2c8d67b750704a9a5724e9cfcb784875021ae17b8963e127fa54dee55c9" + "sha256": "541283736e93b09b2b55c38e106e8bf29b026595cda766f7409bf31f0f588cd7" } ] } diff --git a/rust/avalonia/src/generated.rs b/rust/avalonia/src/generated.rs index 8e7bb20..7a98843 100644 --- a/rust/avalonia/src/generated.rs +++ b/rust/avalonia/src/generated.rs @@ -533,6 +533,304 @@ impl From for Brush { } } +/// Spread behaviour for a gradient outside its `[0, 1]` stop range. +/// Mirrors `Avalonia.Media.GradientSpreadMethod`. +#[repr(i32)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum SpreadMethod { + Pad = 0, + Reflect = 1, + Repeat = 2, +} + +impl TryFrom for SpreadMethod { + type Error = crate::Error; + fn try_from(value: i32) -> Result { + match value { + 0 => Ok(Self::Pad), + 1 => Ok(Self::Reflect), + 2 => Ok(Self::Repeat), + _ => Err(crate::Error::InvalidEnumValue(value)), + } + } +} + +/// Whether a gradient coordinate is relative to the shape's bounding box or an +/// absolute value. Mirrors `Avalonia.RelativeUnit`. +#[repr(i32)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum RelativeUnit { + Relative = 0, + Absolute = 1, +} + +impl TryFrom for RelativeUnit { + type Error = crate::Error; + fn try_from(value: i32) -> Result { + match value { + 0 => Ok(Self::Relative), + 1 => Ok(Self::Absolute), + _ => Err(crate::Error::InvalidEnumValue(value)), + } + } +} + +/// A point whose X/Y may each be relative to the shape's bounding box. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct RelativePoint { + pub x: f64, + pub y: f64, + pub unit: RelativeUnit, +} + +impl RelativePoint { + pub const fn new(x: f64, y: f64, unit: RelativeUnit) -> Self { + Self { x, y, unit } + } + + pub(crate) fn to_abi(self) -> sys::AvnRelativePoint { + sys::AvnRelativePoint { x: self.x, y: self.y, unit: self.unit as i32 } + } + + pub(crate) fn from_abi(value: sys::AvnRelativePoint) -> Result { + Ok(Self { x: value.x, y: value.y, unit: RelativeUnit::try_from(value.unit)? }) + } +} + +/// A scalar (for example a radius) that may be relative to the shape's bounding box. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct RelativeScalar { + pub scalar: f64, + pub unit: RelativeUnit, +} + +impl RelativeScalar { + pub const fn new(scalar: f64, unit: RelativeUnit) -> Self { + Self { scalar, unit } + } + + pub(crate) fn to_abi(self) -> sys::AvnRelativeScalar { + sys::AvnRelativeScalar { scalar: self.scalar, unit: self.unit as i32 } + } + + pub(crate) fn from_abi(value: sys::AvnRelativeScalar) -> Result { + Ok(Self { scalar: value.scalar, unit: RelativeUnit::try_from(value.unit)? }) + } +} + +/// A single colour stop along a gradient, at `offset` in `[0, 1]`. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct GradientStop { + pub offset: f64, + pub color: Color, +} + +impl GradientStop { + pub const fn new(offset: f64, color: Color) -> Self { + Self { offset, color } + } + + fn to_abi(self) -> sys::AvnGradientStop { + sys::AvnGradientStop { offset: self.offset, color: self.color.into() } + } + + fn from_abi(value: sys::AvnGradientStop) -> Self { + Self { offset: value.offset, color: value.color.into() } + } +} + +/// Packs up to the ABI's fixed capacity of stops into an `AvnGradientStopBuffer`. +/// Fails if `stops` carries more entries than the buffer can hold. +fn gradient_stops_to_abi(stops: &[GradientStop]) -> Result { + let mut buffer = sys::AvnGradientStopBuffer::default(); + if stops.len() > buffer.stops.len() { + return Err(crate::Error::Abi(sys::Error(sys::E_INVALIDARG))); + } + for (slot, stop) in buffer.stops.iter_mut().zip(stops) { + *slot = stop.to_abi(); + } + Ok(buffer) +} + +fn gradient_stops_from_abi(buffer: sys::AvnGradientStopBuffer, count: i32) -> Vec { + let count = usize::try_from(count).unwrap_or(0).min(buffer.stops.len()); + buffer.stops[..count].iter().copied().map(GradientStop::from_abi).collect() +} + +/// A linear gradient brush: colour stops interpolated along a line from +/// `start_point` to `end_point`. +#[derive(Clone, Debug, PartialEq)] +pub struct LinearGradientBrush { + pub opacity: f64, + pub spread_method: SpreadMethod, + pub stops: Vec, + pub start_point: RelativePoint, + pub end_point: RelativePoint, +} + +impl LinearGradientBrush { + /// A fully opaque linear gradient with `SpreadMethod::Pad`. + pub fn new(stops: Vec, start_point: RelativePoint, end_point: RelativePoint) -> Self { + Self { + opacity: 1.0, + spread_method: SpreadMethod::Pad, + stops, + start_point, + end_point, + } + } + + pub(crate) fn to_raw(&self) -> Result> { + let buffer = gradient_stops_to_abi(&self.stops)?; + let stop_count = i32::try_from(self.stops.len()).unwrap_or(i32::MAX); + with_factory(|factory| { + factory.create_linear_gradient_brush( + self.opacity, + self.spread_method as i32, + stop_count, + buffer, + self.start_point.to_abi(), + self.end_point.to_abi(), + ) + }) + } + + pub(crate) fn from_raw(raw: &sys::ComPtr) -> Result { + let count = raw.stop_count()?; + Ok(Self { + opacity: raw.opacity()?, + spread_method: SpreadMethod::try_from(raw.spread_method()?)?, + stops: gradient_stops_from_abi(raw.stops()?, count), + start_point: RelativePoint::from_abi(raw.start_point()?)?, + end_point: RelativePoint::from_abi(raw.end_point()?)?, + }) + } +} + +/// A radial gradient brush: colour stops interpolated outward from +/// `gradient_origin` through an ellipse centred at `center` with radii +/// `radius_x`/`radius_y`. +#[derive(Clone, Debug, PartialEq)] +pub struct RadialGradientBrush { + pub opacity: f64, + pub spread_method: SpreadMethod, + pub stops: Vec, + pub center: RelativePoint, + pub gradient_origin: RelativePoint, + pub radius_x: RelativeScalar, + pub radius_y: RelativeScalar, +} + +impl RadialGradientBrush { + /// A fully opaque radial gradient with `SpreadMethod::Pad`. + pub fn new( + stops: Vec, + center: RelativePoint, + gradient_origin: RelativePoint, + radius_x: RelativeScalar, + radius_y: RelativeScalar, + ) -> Self { + Self { + opacity: 1.0, + spread_method: SpreadMethod::Pad, + stops, + center, + gradient_origin, + radius_x, + radius_y, + } + } + + pub(crate) fn to_raw(&self) -> Result> { + let buffer = gradient_stops_to_abi(&self.stops)?; + let stop_count = i32::try_from(self.stops.len()).unwrap_or(i32::MAX); + with_factory(|factory| { + factory.create_radial_gradient_brush( + self.opacity, + self.spread_method as i32, + stop_count, + buffer, + self.center.to_abi(), + self.gradient_origin.to_abi(), + self.radius_x.to_abi(), + self.radius_y.to_abi(), + ) + }) + } + + pub(crate) fn from_raw(raw: &sys::ComPtr) -> Result { + let count = raw.stop_count()?; + Ok(Self { + opacity: raw.opacity()?, + spread_method: SpreadMethod::try_from(raw.spread_method()?)?, + stops: gradient_stops_from_abi(raw.stops()?, count), + center: RelativePoint::from_abi(raw.center()?)?, + gradient_origin: RelativePoint::from_abi(raw.gradient_origin()?)?, + radius_x: RelativeScalar::from_abi(raw.radius_x()?)?, + radius_y: RelativeScalar::from_abi(raw.radius_y()?)?, + }) + } +} + +/// Any brush shape that can be assigned to a `Brush`-typed control property: a +/// solid colour, or one of the two projected gradient shapes. +#[derive(Clone, Debug, PartialEq)] +pub enum Paint { + Solid(Brush), + LinearGradient(LinearGradientBrush), + RadialGradient(RadialGradientBrush), +} + +impl Paint { + pub(crate) fn to_raw(&self) -> Result> { + match self { + Self::Solid(brush) => brush.to_raw(), + Self::LinearGradient(brush) => Ok(brush.to_raw()?.query_interface()?), + Self::RadialGradient(brush) => Ok(brush.to_raw()?.query_interface()?), + } + } + + pub(crate) fn from_raw(raw: &sys::ComPtr) -> Result { + match raw.color() { + Ok(color) => Ok(Self::Solid(Brush::new(color.into(), raw.opacity()?))), + Err(sys::Error(sys::AVN_E_NONSOLIDBRUSH)) => { + if let Ok(linear) = raw.query_interface::() { + return Ok(Self::LinearGradient(LinearGradientBrush::from_raw(&linear)?)); + } + if let Ok(radial) = raw.query_interface::() { + return Ok(Self::RadialGradient(RadialGradientBrush::from_raw(&radial)?)); + } + Err(crate::Error::Abi(sys::Error(sys::AVN_E_NONSOLIDBRUSH))) + } + Err(error) => Err(error.into()), + } + } +} + +impl From for Paint { + fn from(brush: Brush) -> Self { + Self::Solid(brush) + } +} + +impl From for Paint { + fn from(color: Color) -> Self { + Self::Solid(Brush::solid(color)) + } +} + +impl From for Paint { + fn from(brush: LinearGradientBrush) -> Self { + Self::LinearGradient(brush) + } +} + +impl From for Paint { + fn from(brush: RadialGradientBrush) -> Self { + Self::RadialGradient(brush) + } +} + #[repr(i32)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum AutoCompleteFilterMode { diff --git a/rust/avalonia/tests/gradient_brush_round_trip.rs b/rust/avalonia/tests/gradient_brush_round_trip.rs new file mode 100644 index 0000000..ae4d936 --- /dev/null +++ b/rust/avalonia/tests/gradient_brush_round_trip.rs @@ -0,0 +1,91 @@ +//! The safe gradient brush types (`LinearGradientBrush`, `RadialGradientBrush`, `Paint`) and +//! their supporting value types (`GradientStop`, `SpreadMethod`, `RelativeUnit`, +//! `RelativePoint`, `RelativeScalar`). +//! +//! Like `Brush`, these are plain values in Rust; minting one across the ABI needs a live +//! host factory (`IAvnControlFactory::CreateLinearGradientBrush` / +//! `CreateRadialGradientBrush`). Neither shape is wired to a `Background`/`BorderBrush`/ +//! `Foreground` control property in this wave, so there is no public route to a real ABI +//! round trip from outside the crate; these tests cover the value semantics that the ABI +//! marshalling (`to_abi`/`from_abi`) builds on. + +use avalonia::{Color, GradientStop, LinearGradientBrush, Paint, RadialGradientBrush}; +use avalonia::{RelativePoint, RelativeScalar, RelativeUnit, SpreadMethod}; + +#[test] +fn new_linear_gradient_is_fully_opaque_with_pad_spread() { + let stops = vec![ + GradientStop::new(0.0, Color::rgb(0xFF, 0x00, 0x00)), + GradientStop::new(1.0, Color::rgb(0x00, 0x00, 0xFF)), + ]; + let start = RelativePoint::new(0.0, 0.0, RelativeUnit::Relative); + let end = RelativePoint::new(1.0, 1.0, RelativeUnit::Relative); + + let brush = LinearGradientBrush::new(stops.clone(), start, end); + + assert_eq!(brush.opacity, 1.0); + assert_eq!(brush.spread_method, SpreadMethod::Pad); + assert_eq!(brush.stops, stops); + assert_eq!(brush.start_point, start); + assert_eq!(brush.end_point, end); +} + +#[test] +fn new_radial_gradient_is_fully_opaque_with_pad_spread() { + let stops = vec![GradientStop::new(0.5, Color::rgb(0x10, 0x20, 0x30))]; + let center = RelativePoint::new(0.5, 0.5, RelativeUnit::Relative); + let origin = RelativePoint::new(0.5, 0.5, RelativeUnit::Relative); + let radius_x = RelativeScalar::new(0.5, RelativeUnit::Relative); + let radius_y = RelativeScalar::new(0.5, RelativeUnit::Relative); + + let brush = RadialGradientBrush::new(stops.clone(), center, origin, radius_x, radius_y); + + assert_eq!(brush.opacity, 1.0); + assert_eq!(brush.spread_method, SpreadMethod::Pad); + assert_eq!(brush.stops, stops); + assert_eq!(brush.center, center); + assert_eq!(brush.gradient_origin, origin); + assert_eq!(brush.radius_x, radius_x); + assert_eq!(brush.radius_y, radius_y); +} + +#[test] +fn spread_method_round_trips_through_its_abi_ordinal() { + assert_eq!(SpreadMethod::try_from(0).unwrap(), SpreadMethod::Pad); + assert_eq!(SpreadMethod::try_from(1).unwrap(), SpreadMethod::Reflect); + assert_eq!(SpreadMethod::try_from(2).unwrap(), SpreadMethod::Repeat); + assert!(SpreadMethod::try_from(3).is_err()); +} + +#[test] +fn relative_unit_round_trips_through_its_abi_ordinal() { + assert_eq!(RelativeUnit::try_from(0).unwrap(), RelativeUnit::Relative); + assert_eq!(RelativeUnit::try_from(1).unwrap(), RelativeUnit::Absolute); + assert!(RelativeUnit::try_from(2).is_err()); +} + +#[test] +fn a_colour_converts_into_a_solid_paint() { + let paint: Paint = Color::rgb(0x10, 0x20, 0x30).into(); + + assert_eq!(paint, Paint::Solid(Color::rgb(0x10, 0x20, 0x30).into())); +} + +#[test] +fn a_gradient_brush_converts_into_the_matching_paint_variant() { + let linear = LinearGradientBrush::new( + vec![GradientStop::new(0.0, Color::rgb(0xFF, 0xFF, 0xFF))], + RelativePoint::new(0.0, 0.0, RelativeUnit::Relative), + RelativePoint::new(1.0, 0.0, RelativeUnit::Relative), + ); + let radial = RadialGradientBrush::new( + vec![GradientStop::new(0.0, Color::rgb(0x00, 0x00, 0x00))], + RelativePoint::new(0.5, 0.5, RelativeUnit::Relative), + RelativePoint::new(0.5, 0.5, RelativeUnit::Relative), + RelativeScalar::new(0.5, RelativeUnit::Relative), + RelativeScalar::new(0.5, RelativeUnit::Relative), + ); + + assert_eq!(Paint::from(linear.clone()), Paint::LinearGradient(linear)); + assert_eq!(Paint::from(radial.clone()), Paint::RadialGradient(radial)); +} diff --git a/rust/projection.ir.json b/rust/projection.ir.json index b4dc214..6d6227c 100644 --- a/rust/projection.ir.json +++ b/rust/projection.ir.json @@ -1,11 +1,17 @@ { - "version": 16, + "version": 17, "sourceAssembly": "Avalonia.Base,Avalonia.Controls", - "factoryIid": "15778134-9E9F-5BAF-98FF-5510778094BA", - "factoryAbiVersion": 13, + "factoryIid": "C8BCE8E8-62C7-5E0E-8066-690059F55DFF", + "factoryAbiVersion": 14, "brushInterfaceName": "Avalonia.Host.Com.IAvnBrush", "brushInterfaceIid": "FC7CCBAE-ED75-5C6D-8516-DF706E137ED3", "brushAbiVersion": 1, + "gradientBrushInterfaceName": "Avalonia.Host.Com.IAvnGradientBrush", + "gradientBrushInterfaceIid": "FDAA2353-BC44-5012-A5BE-A17C7C01F41A", + "linearGradientBrushInterfaceName": "Avalonia.Host.Com.IAvnLinearGradientBrush", + "linearGradientBrushInterfaceIid": "40B3D53D-330E-5D63-A040-37F1FF717FF8", + "radialGradientBrushInterfaceName": "Avalonia.Host.Com.IAvnRadialGradientBrush", + "radialGradientBrushInterfaceIid": "AEC23FCE-9FEA-506C-ABC4-774143BE80C8", "commandInterfaceName": "Avalonia.Host.Com.IAvnCommand", "commandInterfaceIid": "E6F7AAF7-D5E7-503F-9BE6-5AF8DB5B5273", "commandAbiVersion": 2, diff --git a/rust/release-manifest.json b/rust/release-manifest.json index cdfe70e..e82a5f3 100644 --- a/rust/release-manifest.json +++ b/rust/release-manifest.json @@ -10,7 +10,7 @@ } ], "schemas": { - "projectionIr": 16, + "projectionIr": 17, "viewModelIr": 5, "abiBaseline": 3, "consumerAppManifest": 1 diff --git a/tests/Avalonia.Projection.Ir.Tests/ClrTypeExtractorTests.cs b/tests/Avalonia.Projection.Ir.Tests/ClrTypeExtractorTests.cs index dea6ce0..8b3548d 100644 --- a/tests/Avalonia.Projection.Ir.Tests/ClrTypeExtractorTests.cs +++ b/tests/Avalonia.Projection.Ir.Tests/ClrTypeExtractorTests.cs @@ -348,9 +348,9 @@ public void Chrome_members_keep_the_abi_version_of_the_interfaces_they_widened() // The factory grew a creator per wave A control plus GetToolTipStatics, then one per // constructible wave B type, then one per constructible wave C type, so it has moved // three times off the version 2 IID it published for CreateSolidColorBrush. - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); Assert.Equal( - ClrTypeExtractor.CreateDeterministicIid("Avalonia.Host.Com.IAvnControlFactory", 13), + ClrTypeExtractor.CreateDeterministicIid("Avalonia.Host.Com.IAvnControlFactory", 14), ir.FactoryIid); } @@ -1275,7 +1275,7 @@ public void Wave_c_layout_panels_publish_new_interfaces_at_version_one() property => property.Name is "Above" or "Below" or "LeftOf" or "RightOf" or "AlignLeftWith" or "Order" or "Grow" or "Shrink" or "Basis"); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1336,7 +1336,7 @@ public void Wave_d_button_family_publishes_new_interfaces_at_version_one() Assert.Equal(MarshallingKind.ComCollection, items.Kind); Assert.Equal("Avalonia.Host.Com.IAvnItemList", items.InterfaceName); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1381,7 +1381,7 @@ public void Wave_e_input_controls_publish_new_interfaces_at_version_one() Assert.True(selectedText.CanRead); Assert.False(selectedText.CanWrite); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1420,7 +1420,7 @@ public void Wave_f_calendar_family_publishes_new_interfaces_at_version_one() Assert.Equal("Avalonia.Host.Com.AvnDateList", selectedDates.HostImplementationTypeName); Assert.False(selectedDates.CanWrite); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1449,7 +1449,7 @@ public void Wave_g_content_chrome_publishes_new_interfaces_at_version_one() Type(ir, "IAvnLayoutTransformControl").Properties, p => p.Name == "LayoutTransform"); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1491,7 +1491,7 @@ public void Wave_h_shapes_publish_new_interfaces_at_version_one() Assert.Equal(MarshallingKind.StringUtf16, polygonPoints.Kind); Assert.Equal("Avalonia.Host.Com.AvnPointList", polygonPoints.StringConverterTypeName); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1517,7 +1517,7 @@ public void Wave_i_overlay_publishes_new_interfaces_at_version_one() MarshallingKind.Command, Type(ir, "IAvnTrayIcon").Properties.Single(p => p.Name == "Command").Kind); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1541,7 +1541,7 @@ public void Wave_j_command_bar_publishes_new_interfaces_at_version_one() var buttonIcon = Type(ir, "IAvnCommandBarButton").Properties.Single(p => p.Name == "Icon"); Assert.Equal(MarshallingKind.Variant, buttonIcon.Kind); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1572,7 +1572,7 @@ public void Wave_k_icons_and_table_view_publish_new_interfaces_at_version_one() var width = Type(ir, "IAvnTableViewColumn").Properties.Single(p => p.Name == "Width"); Assert.Equal(MarshallingKind.StringUtf16, width.Kind); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1635,7 +1635,7 @@ public void Wave_m_fonts_bump_templated_control_and_text_block() var trimming = textBlock.Properties.Single(p => p.Name == "TextTrimming"); Assert.Equal(MarshallingKind.StringUtf16, trimming.Kind); Assert.Equal("Avalonia.Host.Com.AvnTextTrimming", trimming.StringConverterTypeName); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1685,7 +1685,7 @@ public void Wave_r_numeric_up_down_value_changed_carries_the_decimal_pair_as_inv valueChanged.Parameters.Select(parameter => parameter.Name)); Assert.Contains(Type(ir, "IAvnMaskedTextBox").Properties, p => p.Name == "MaskCompleted"); Assert.Equal(15, Type(ir, "IAvnTemplatedControl").AbiVersion); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1707,7 +1707,7 @@ public void Wave_o_combo_and_scroll_use_vector_and_size() Assert.False(scroll.Properties.Single(p => p.Name == "Extent").CanWrite); Assert.True(scroll.Properties.Single(p => p.Name == "Offset").CanWrite); Assert.Equal(16, Type(ir, "IAvnContentControl").AbiVersion); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1731,7 +1731,7 @@ public void Wave_p_projects_instance_flyout_and_menu_item_open() Assert.Contains(menu.Methods, m => m.Name == "Open"); Assert.Contains(menu.Methods, m => m.Name == "Close"); Assert.Equal(16, Type(ir, "IAvnContentControl").AbiVersion); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1746,7 +1746,7 @@ public void Wave_q_sweeps_leaf_input_scalars() Assert.Contains(Type(ir, "IAvnCalendarDatePicker").Methods, m => m.Name == "Clear"); Assert.Equal(13, Type(ir, "IAvnNumericUpDown").AbiVersion); Assert.Contains(Type(ir, "IAvnNumericUpDown").Properties, p => p.Name == "TextAlignment"); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1765,7 +1765,7 @@ public void Items_control_leftovers_keep_items_and_selection() Assert.Contains(selecting.Properties, p => p.Name == "AutoScrollToSelectedItem"); Assert.Equal(16, Type(ir, "IAvnContentControl").AbiVersion); Assert.Equal(21, Type(ir, "IAvnWindow").AbiVersion); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1791,7 +1791,7 @@ public void Text_leftovers_project_line_metrics_and_scroll_to_line() Assert.Contains(lineCount.Parameters, p => p.Name == "value" && p.Direction == ParameterDirection.Out); Assert.Equal(MarshallingKind.CharUtf16, textBox.Properties.Single(p => p.Name == "PasswordChar").Kind); Assert.Equal(18, Type(ir, "IAvnMaskedTextBox").AbiVersion); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1812,7 +1812,7 @@ public void Leaf_leftovers_project_marshallable_scalars_and_commands() Assert.Equal(15, Type(ir, "IAvnStackPanel").AbiVersion); Assert.Equal(15, Type(ir, "IAvnBorder").AbiVersion); Assert.Contains(Type(ir, "IAvnBorder").Properties, p => p.Name == "ClipToBoundsRadius"); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1845,7 +1845,7 @@ public void Overlay_chrome_projects_popup_open_close_and_placement_target() Assert.Equal("Avalonia.Host.Com.IAvnControl", openWithControl.Parameters.Single().InterfaceName); Assert.True(openWithControl.Parameters.Single().IsNullable); Assert.Contains(Type(ir, "IAvnContextMenu").Events, e => e.Name == "Opening"); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact] @@ -1866,7 +1866,7 @@ public void Control_leftovers_project_context_menu_and_loaded() Assert.Equal(6, Type(ir, "IAvnStyledElement").AbiVersion); Assert.Equal(19, Type(ir, "IAvnButton").AbiVersion); Assert.Equal(4, Type(ir, "IAvnFlyout").AbiVersion); - Assert.Equal(13, ir.FactoryAbiVersion); + Assert.Equal(14, ir.FactoryAbiVersion); } [Fact]