diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
index d48bda9a5a3..a6ae7bae87b 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
@@ -269,9 +269,16 @@
PreserveNewest
+
+
+
+
+
+
+
@@ -505,6 +512,15 @@
FocusBehaviorPage.xaml
+
+ GeometryMaskSurfaceBrushPage.xaml
+
+
+ ImageMaskSurfaceBrushPage.xaml
+
+
+ ImageSurfaceBrushPage.xaml
+
MetadataControlPage.xaml
@@ -515,6 +531,9 @@
RichSuggestBoxPage.xaml
+
+ GeometrySurfaceBrushPage.xaml
+
TilesBrushPage.xaml
@@ -632,6 +651,10 @@
+
+
+
+
Designer
@@ -984,6 +1007,18 @@
Designer
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -1007,6 +1042,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
MSBuild:Compile
Designer
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs b/Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs
index e26a5076895..ab40135fce7 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs
@@ -480,156 +480,158 @@ public async Task PreparePropertyDescriptorAsync()
if (_propertyDescriptor == null)
{
- // Get Xaml code
- using (var codeStream = await StreamHelper.GetPackagedFileStreamAsync(XamlCodeFile.StartsWith('/') ? XamlCodeFile : $"SamplePages/{Name}/{XamlCodeFile}"))
+ try
{
- XamlCode = await codeStream.ReadTextAsync(Encoding.UTF8);
+ // Get Xaml code
+ using (var codeStream = await StreamHelper.GetPackagedFileStreamAsync(XamlCodeFile.StartsWith('/') ? XamlCodeFile : $"SamplePages/{Name}/{XamlCodeFile}"))
+ {
+ XamlCode = await codeStream.ReadTextAsync(Encoding.UTF8);
- // Look for @[] values and generate associated properties
- var regularExpression = new Regex("(?<=\\\")@\\[(?.+?)(:(?.+?):(?.+?)(:(?.+?))?(:(?.*))*)?\\]@?(?=\\\")");
+ // Look for @[] values and generate associated properties
+ var regularExpression = new Regex("(?<=\\\")@\\[(?.+?)(:(?.+?):(?.+?)(:(?.+?))?(:(?.*))*)?\\]@?(?=\\\")");
- _propertyDescriptor = new PropertyDescriptor { Expando = new ExpandoObject() };
- var proxy = (IDictionary)_propertyDescriptor.Expando;
+ _propertyDescriptor = new PropertyDescriptor { Expando = new ExpandoObject() };
+ var proxy = (IDictionary)_propertyDescriptor.Expando;
- foreach (Match match in regularExpression.Matches(XamlCode))
- {
- var label = match.Groups["name"].Value;
- var name = label.Replace(" ", string.Empty); // Allow us to have nicer display names, but create valid properties.
- var type = match.Groups["type"].Value;
- var value = match.Groups["value"].Value;
+ foreach (Match match in regularExpression.Matches(XamlCode))
+ {
+ var label = match.Groups["name"].Value;
+ var name = label.Replace(" ", string.Empty); // Allow us to have nicer display names, but create valid properties.
+ var type = match.Groups["type"].Value;
+ var value = match.Groups["value"].Value;
- var existingOption = _propertyDescriptor.Options.Where(o => o.Name == name).FirstOrDefault();
+ var existingOption = _propertyDescriptor.Options.Where(o => o.Name == name).FirstOrDefault();
- if (existingOption == null && string.IsNullOrWhiteSpace(type))
- {
- throw new NotSupportedException($"Unrecognized short identifier '{name}'; Define type and parameters of property in first occurrence in {XamlCodeFile}.");
- }
+ if (existingOption == null && string.IsNullOrWhiteSpace(type))
+ {
+ throw new NotSupportedException($"Unrecognized short identifier '{name}'; Define type and parameters of property in first occurrence in {XamlCodeFile}.");
+ }
- if (Enum.TryParse(type, out PropertyKind kind))
- {
- if (existingOption != null)
+ if (Enum.TryParse(type, out PropertyKind kind))
{
- if (existingOption.Kind != kind)
+ if (existingOption != null)
{
- throw new NotSupportedException($"Multiple options with same name but different type not supported: {XamlCodeFile}:{name}");
- }
+ if (existingOption.Kind != kind)
+ {
+ throw new NotSupportedException($"Multiple options with same name but different type not supported: {XamlCodeFile}:{name}");
+ }
- continue;
- }
+ continue;
+ }
- PropertyOptions options;
+ PropertyOptions options;
- switch (kind)
- {
- case PropertyKind.Slider:
- case PropertyKind.DoubleSlider:
- try
- {
- var sliderOptions = new SliderPropertyOptions { DefaultValue = double.Parse(value, CultureInfo.InvariantCulture) };
- var parameters = match.Groups["parameters"].Value;
- var split = parameters.Split('-');
- int minIndex = 0;
- int minMultiplier = 1;
- if (string.IsNullOrEmpty(split[0]))
+ switch (kind)
+ {
+ case PropertyKind.Slider:
+ case PropertyKind.DoubleSlider:
+ try
{
- minIndex = 1;
- minMultiplier = -1;
+ var sliderOptions = new SliderPropertyOptions { DefaultValue = double.Parse(value, CultureInfo.InvariantCulture) };
+ var parameters = match.Groups["parameters"].Value;
+ var split = parameters.Split('-');
+ int minIndex = 0;
+ int minMultiplier = 1;
+ if (string.IsNullOrEmpty(split[0]))
+ {
+ minIndex = 1;
+ minMultiplier = -1;
+ }
+
+ sliderOptions.MinValue = minMultiplier * double.Parse(split[minIndex], CultureInfo.InvariantCulture);
+ sliderOptions.MaxValue = double.Parse(split[minIndex + 1], CultureInfo.InvariantCulture);
+ if (split.Length > 2 + minIndex)
+ {
+ sliderOptions.Step = double.Parse(split[split.Length - 1], CultureInfo.InvariantCulture);
+ }
+
+ options = sliderOptions;
}
-
- sliderOptions.MinValue = minMultiplier * double.Parse(split[minIndex], CultureInfo.InvariantCulture);
- sliderOptions.MaxValue = double.Parse(split[minIndex + 1], CultureInfo.InvariantCulture);
- if (split.Length > 2 + minIndex)
+ catch (Exception ex)
{
- sliderOptions.Step = double.Parse(split[split.Length - 1], CultureInfo.InvariantCulture);
+ Debug.WriteLine($"Unable to extract slider info from {value}({ex.Message})");
+ TrackingManager.TrackException(ex);
+ continue;
}
- options = sliderOptions;
- }
- catch (Exception ex)
- {
- Debug.WriteLine($"Unable to extract slider info from {value}({ex.Message})");
- TrackingManager.TrackException(ex);
- continue;
- }
+ break;
- break;
-
- case PropertyKind.TimeSpan:
- try
- {
- var sliderOptions = new SliderPropertyOptions { DefaultValue = TimeSpan.FromMilliseconds(double.Parse(value, CultureInfo.InvariantCulture)) };
- var parameters = match.Groups["parameters"].Value;
- var split = parameters.Split('-');
- int minIndex = 0;
- int minMultiplier = 1;
- if (string.IsNullOrEmpty(split[0]))
+ case PropertyKind.TimeSpan:
+ try
{
- minIndex = 1;
- minMultiplier = -1;
+ var sliderOptions = new SliderPropertyOptions { DefaultValue = TimeSpan.FromMilliseconds(double.Parse(value, CultureInfo.InvariantCulture)) };
+ var parameters = match.Groups["parameters"].Value;
+ var split = parameters.Split('-');
+ int minIndex = 0;
+ int minMultiplier = 1;
+ if (string.IsNullOrEmpty(split[0]))
+ {
+ minIndex = 1;
+ minMultiplier = -1;
+ }
+
+ sliderOptions.MinValue = minMultiplier * double.Parse(split[minIndex], CultureInfo.InvariantCulture);
+ sliderOptions.MaxValue = double.Parse(split[minIndex + 1], CultureInfo.InvariantCulture);
+ if (split.Length > 2 + minIndex)
+ {
+ sliderOptions.Step = double.Parse(split[split.Length - 1], CultureInfo.InvariantCulture);
+ }
+
+ options = sliderOptions;
}
-
- sliderOptions.MinValue = minMultiplier * double.Parse(split[minIndex], CultureInfo.InvariantCulture);
- sliderOptions.MaxValue = double.Parse(split[minIndex + 1], CultureInfo.InvariantCulture);
- if (split.Length > 2 + minIndex)
+ catch (Exception ex)
{
- sliderOptions.Step = double.Parse(split[split.Length - 1], CultureInfo.InvariantCulture);
+ Debug.WriteLine($"Unable to extract slider info from {value}({ex.Message})");
+ TrackingManager.TrackException(ex);
+ continue;
}
- options = sliderOptions;
- }
- catch (Exception ex)
- {
- Debug.WriteLine($"Unable to extract slider info from {value}({ex.Message})");
- TrackingManager.TrackException(ex);
- continue;
- }
-
- break;
+ break;
- case PropertyKind.Enum:
- try
- {
- options = new PropertyOptions();
- var split = value.Split('.');
- var typeName = string.Join(".", split.Take(split.Length - 1));
- var enumType = LookForTypeByName(typeName);
- options.DefaultValue = Enum.Parse(enumType, split.Last());
- }
- catch (Exception ex)
- {
- Debug.WriteLine($"Unable to parse enum from {value}({ex.Message})");
- TrackingManager.TrackException(ex);
- continue;
- }
+ case PropertyKind.Enum:
+ try
+ {
+ options = new PropertyOptions();
+ var split = value.Split('.');
+ var typeName = string.Join(".", split.Take(split.Length - 1));
+ var enumType = LookForTypeByName(typeName);
+ options.DefaultValue = Enum.Parse(enumType, split.Last());
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"Unable to parse enum from {value}({ex.Message})");
+ TrackingManager.TrackException(ex);
+ continue;
+ }
- break;
+ break;
- case PropertyKind.Bool:
- try
- {
- options = new PropertyOptions { DefaultValue = bool.Parse(value) };
- }
- catch (Exception ex)
- {
- Debug.WriteLine($"Unable to parse bool from {value}({ex.Message})");
- continue;
- }
+ case PropertyKind.Bool:
+ try
+ {
+ options = new PropertyOptions { DefaultValue = bool.Parse(value) };
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"Unable to parse bool from {value}({ex.Message})");
+ continue;
+ }
- break;
+ break;
- case PropertyKind.Brush:
- try
- {
- options = new PropertyOptions { DefaultValue = value };
- }
- catch (Exception ex)
- {
- Debug.WriteLine($"Unable to parse bool from {value}({ex.Message})");
- TrackingManager.TrackException(ex);
- continue;
- }
+ case PropertyKind.Brush:
+ try
+ {
+ options = new PropertyOptions { DefaultValue = value };
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"Unable to parse bool from {value}({ex.Message})");
+ TrackingManager.TrackException(ex);
+ continue;
+ }
- break;
+ break;
case PropertyKind.Thickness:
try
@@ -659,24 +661,29 @@ public async Task PreparePropertyDescriptorAsync()
continue;
}
- break;
+ break;
- default:
- options = new PropertyOptions { DefaultValue = value };
- break;
- }
+ default:
+ options = new PropertyOptions { DefaultValue = value };
+ break;
+ }
- options.Label = label;
- options.Name = name;
- options.OriginalString = match.Value;
- options.Kind = kind;
- options.IsTwoWayBinding = options.OriginalString.EndsWith("@");
- proxy[name] = new ValueHolder(options.DefaultValue);
+ options.Label = label;
+ options.Name = name;
+ options.OriginalString = match.Value;
+ options.Kind = kind;
+ options.IsTwoWayBinding = options.OriginalString.EndsWith("@");
+ proxy[name] = new ValueHolder(options.DefaultValue);
- _propertyDescriptor.Options.Add(options);
+ _propertyDescriptor.Options.Add(options);
+ }
}
}
}
+ catch (Exception e)
+ {
+ var msg = e.Message;
+ }
}
}
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CanvasPathGeometry/CanvasPathGeometryPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CanvasPathGeometry/CanvasPathGeometryPage.xaml.cs
index 3cbdacb187c..8015c596a70 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CanvasPathGeometry/CanvasPathGeometryPage.xaml.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CanvasPathGeometry/CanvasPathGeometryPage.xaml.cs
@@ -9,6 +9,7 @@
using Microsoft.Graphics.Canvas.Geometry;
using Microsoft.Graphics.Canvas.UI.Xaml;
using Microsoft.Toolkit.Uwp.UI;
+using Microsoft.Toolkit.Uwp.UI.Media;
using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
using Windows.System;
using Windows.UI;
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrush.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrush.png
new file mode 100644
index 00000000000..44a3b5ff836
Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrush.png differ
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrushPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrushPage.xaml
new file mode 100644
index 00000000000..7f0e3a59ca2
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrushPage.xaml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrushPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrushPage.xaml.cs
new file mode 100644
index 00000000000..bac5cdfe5a1
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrushPage.xaml.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Windows.UI.Xaml.Controls;
+
+// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
+namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class GeometryMaskSurfaceBrushPage : Page
+ {
+ public GeometryMaskSurfaceBrushPage()
+ {
+ this.InitializeComponent();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrushXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrushXaml.bind
new file mode 100644
index 00000000000..f9261043039
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrushXaml.bind
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrush.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrush.png
new file mode 100644
index 00000000000..7ba968db969
Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrush.png differ
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrushPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrushPage.xaml
new file mode 100644
index 00000000000..9b1f4326ff7
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrushPage.xaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrushPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrushPage.xaml.cs
new file mode 100644
index 00000000000..e2f9531467e
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrushPage.xaml.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Windows.UI.Xaml.Controls;
+
+// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
+namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class GeometrySurfaceBrushPage : Page
+ {
+ public GeometrySurfaceBrushPage()
+ {
+ this.InitializeComponent();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrushXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrushXaml.bind
new file mode 100644
index 00000000000..b2e26d667b3
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrushXaml.bind
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrush.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrush.png
new file mode 100644
index 00000000000..9123372ad51
Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrush.png differ
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrushPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrushPage.xaml
new file mode 100644
index 00000000000..75d5b09ef4b
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrushPage.xaml
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrushPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrushPage.xaml.cs
new file mode 100644
index 00000000000..64bd9606512
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrushPage.xaml.cs
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+
+// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
+namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class ImageMaskSurfaceBrushPage : Page
+ {
+ private Dictionary _maskImages;
+ private Dictionary _targetImages;
+
+ public ImageMaskSurfaceBrushPage()
+ {
+ this.InitializeComponent();
+
+ _maskImages = new Dictionary
+ {
+ ["Image 1"] = "ms-appx:///SamplePages/ImageMaskSurfaceBrush/MaskImage1.png",
+ ["Image 2"] = "ms-appx:///SamplePages/ImageMaskSurfaceBrush/MaskImage2.png",
+ ["Image 3"] = "ms-appx:///SamplePages/ImageMaskSurfaceBrush/MaskImage3.png",
+ };
+
+ MaskImages.ItemsSource = _maskImages.Keys;
+
+ // Select the first Image as mask
+ MaskImages.SelectedIndex = 0;
+
+ _targetImages = new Dictionary
+ {
+ ["Image 1"] = "ms-appx:///Assets/Photos/PaintedHillsPathway.jpg",
+ ["Image 2"] = "ms-appx:///Assets/Photos/ShootingOnAutoOnTheDrone.jpg",
+ ["Image 3"] = "ms-appx:///Assets/Photos/NorthernCascadesReflection.jpg",
+ ["Image 4"] = "ms-appx:///Assets/Photos/Van.jpg",
+ };
+
+ TargetImages.ItemsSource = _targetImages.Keys;
+
+ // Select the first Image as target image.
+ TargetImages.SelectedIndex = 0;
+ }
+
+ private void OnMaskImageChanged(object sender, SelectionChangedEventArgs e)
+ {
+ var image = MaskImages.SelectedValue as string;
+ if (string.IsNullOrWhiteSpace(image))
+ {
+ return;
+ }
+
+ MaskImageBrush.Source = _maskImages[image];
+ }
+
+ private void OnTargetImageChanged(object sender, SelectionChangedEventArgs e)
+ {
+ var image = TargetImages.SelectedValue as string;
+ if (string.IsNullOrWhiteSpace(image))
+ {
+ return;
+ }
+
+ TargetImageBrush.Source = _targetImages[image];
+ }
+
+ private void OnBlurRadiusChanged(object sender, RangeBaseValueChangedEventArgs e)
+ {
+ MaskImageOptions.BlurRadius = e.NewValue;
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrushXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrushXaml.bind
new file mode 100644
index 00000000000..60560bf1e83
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrushXaml.bind
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/MaskImage1.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/MaskImage1.png
new file mode 100644
index 00000000000..a92ab65d842
Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/MaskImage1.png differ
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/MaskImage2.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/MaskImage2.png
new file mode 100644
index 00000000000..3b619a37a0e
Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/MaskImage2.png differ
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/MaskImage3.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/MaskImage3.png
new file mode 100644
index 00000000000..ad4cd9ebef7
Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageMaskSurfaceBrush/MaskImage3.png differ
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageSurfaceBrush/ImageSurfaceBrush.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageSurfaceBrush/ImageSurfaceBrush.png
new file mode 100644
index 00000000000..31334d7b2b7
Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageSurfaceBrush/ImageSurfaceBrush.png differ
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageSurfaceBrush/ImageSurfaceBrushPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageSurfaceBrush/ImageSurfaceBrushPage.xaml
new file mode 100644
index 00000000000..b31d88889cd
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageSurfaceBrush/ImageSurfaceBrushPage.xaml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageSurfaceBrush/ImageSurfaceBrushPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageSurfaceBrush/ImageSurfaceBrushPage.xaml.cs
new file mode 100644
index 00000000000..1761b4b184a
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageSurfaceBrush/ImageSurfaceBrushPage.xaml.cs
@@ -0,0 +1,90 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
+namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class ImageSurfaceBrushPage : Page
+ {
+ public ImageSurfaceBrushPage()
+ {
+ this.InitializeComponent();
+
+ StretchOptions.ItemsSource = new List
+ {
+ "None",
+ "Fill",
+ "Uniform",
+ "UniformToFill"
+ };
+
+ HAOptions.ItemsSource = new List
+ {
+ "Left",
+ "Center",
+ "Right"
+ };
+
+ VAOptions.ItemsSource = new List
+ {
+ "Top",
+ "Center",
+ "Bottom"
+ };
+
+ StretchOptions.SelectionChanged += OnStretchOptionsChanged;
+ StretchOptions.SelectedIndex = 2;
+
+ HAOptions.SelectionChanged += OnHorizontalAlignmentChanged;
+ HAOptions.SelectedIndex = 1;
+
+ VAOptions.SelectionChanged += OnVerticalAlignmentChanged;
+ VAOptions.SelectedIndex = 1;
+ }
+
+ private void OnStretchOptionsChanged(object sender, SelectionChangedEventArgs e)
+ {
+ var stretch = StretchOptions.SelectedValue as string;
+ if (!string.IsNullOrWhiteSpace(stretch))
+ {
+ if (Enum.TryParse(typeof(Stretch), stretch, out object stretchEnum))
+ {
+ ImageOptions.Stretch = (Stretch)stretchEnum;
+ }
+ }
+ }
+
+ private void OnHorizontalAlignmentChanged(object sender, SelectionChangedEventArgs e)
+ {
+ var align = HAOptions.SelectedValue as string;
+ if (!string.IsNullOrWhiteSpace(align))
+ {
+ if (Enum.TryParse(typeof(AlignmentX), align, out object alignEnum))
+ {
+ ImageOptions.HorizontalAlignment = (AlignmentX)alignEnum;
+ }
+ }
+ }
+
+ private void OnVerticalAlignmentChanged(object sender, SelectionChangedEventArgs e)
+ {
+ var align = VAOptions.SelectedValue as string;
+ if (!string.IsNullOrWhiteSpace(align))
+ {
+ if (Enum.TryParse(typeof(AlignmentY), align, out object alignEnum))
+ {
+ ImageOptions.VerticalAlignment = (AlignmentY)alignEnum;
+ }
+ }
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageSurfaceBrush/ImageSurfaceBrushXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageSurfaceBrush/ImageSurfaceBrushXaml.bind
new file mode 100644
index 00000000000..60560bf1e83
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ImageSurfaceBrush/ImageSurfaceBrushXaml.bind
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
index c1f45a20762..9c4258d58ab 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
@@ -1156,6 +1156,46 @@
"Icon": "/SamplePages/TilesBrush/TilesBrush.png",
"ApiCheck": "Windows.UI.Xaml.Media.XamlCompositionBrushBase",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/brushes/TilesBrush.md"
+ },
+ {
+ "Name": "GeometrySurfaceBrush",
+ "Type": "GeometrySurfaceBrushPage",
+ "About": "Brush which fills the contents with a CanvasCoreGeometry.",
+ "CodeUrl": "https://github.com/ratishphilip/WindowsCommunityToolkit/tree/feature/rendersurfaces/Microsoft.Toolkit.Uwp.UI.Media/Brushes/GeometrySurfaceBrush.cs",
+ "XamlCodeFile": "GeometrySurfaceBrushXaml.bind",
+ "Icon": "/SamplePages/GeometrySurfaceBrush/GeometrySurfaceBrush.png",
+ "ApiCheck": "Windows.UI.Xaml.Media.XamlCompositionBrushBase",
+ "DocumentationUrl": ""
+ },
+ {
+ "Name": "GeometryMaskSurfaceBrush",
+ "Type": "GeometryMaskSurfaceBrushPage",
+ "About": "Brush which fills the contents with a CanvasCoreGeometry.",
+ "CodeUrl": "https://github.com/ratishphilip/WindowsCommunityToolkit/tree/feature/rendersurfaces/Microsoft.Toolkit.Uwp.UI.Media/Brushes/GeometryMaskSurfaceBrush.cs",
+ "XamlCodeFile": "GeometryMaskSurfaceBrushXaml.bind",
+ "Icon": "/SamplePages/GeometryMaskSurfaceBrush/GeometryMaskSurfaceBrush.png",
+ "ApiCheck": "Windows.UI.Xaml.Media.XamlCompositionBrushBase",
+ "DocumentationUrl": ""
+ },
+ {
+ "Name": "ImageSurfaceBrush",
+ "Type": "ImageSurfaceBrushPage",
+ "About": "Brush which fills the contents with a Image.",
+ "CodeUrl": "https://github.com/ratishphilip/WindowsCommunityToolkit/tree/feature/rendersurfaces/Microsoft.Toolkit.Uwp.UI.Media/Brushes/ImageSurfaceBrush.cs",
+ "XamlCodeFile": "ImageSurfaceBrushXaml.bind",
+ "Icon": "/SamplePages/ImageSurfaceBrush/ImageSurfaceBrush.png",
+ "ApiCheck": "Windows.UI.Xaml.Media.XamlCompositionBrushBase",
+ "DocumentationUrl": ""
+ },
+ {
+ "Name": "ImageMaskSurfaceBrush",
+ "Type": "ImageMaskSurfaceBrushPage",
+ "About": "Brush which fills the contents with a Image.",
+ "CodeUrl": "https://github.com/ratishphilip/WindowsCommunityToolkit/tree/feature/rendersurfaces/Microsoft.Toolkit.Uwp.UI.Media/Brushes/ImageMaskSurfaceBrush.cs",
+ "XamlCodeFile": "ImageMaskSurfaceBrushXaml.bind",
+ "Icon": "/SamplePages/ImageMaskSurfaceBrush/ImageMaskSurfaceBrush.png",
+ "ApiCheck": "Windows.UI.Xaml.Media.XamlCompositionBrushBase",
+ "DocumentationUrl": ""
}
]
},
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Brushes/Base/RenderCanvasBrushBase.cs b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/Base/RenderCanvasBrushBase.cs
new file mode 100644
index 00000000000..aada20fffbe
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/Base/RenderCanvasBrushBase.cs
@@ -0,0 +1,127 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using Microsoft.Graphics.Canvas.Brushes;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media
+{
+ ///
+ /// Abstract base class for SolidColorCanvasBrush, LinearGradientCanvasBrush and RadialGradientCanvasBrush which are XAML equivalents of Win2d brushes.
+ ///
+ public abstract class RenderCanvasBrushBase : DependencyObject, IDisposable
+ {
+ ///
+ /// Event which indicates that the components of the brush have changed.
+ ///
+ public event EventHandler Updated;
+
+ private bool _disposedValue;
+
+ ///
+ /// Gets or sets the associated CanvasBrush.
+ ///
+ public ICanvasBrush CanvasBrush { get; protected set; }
+
+ ///
+ /// Opacity Dependency Property
+ ///
+ public static readonly DependencyProperty OpacityProperty = DependencyProperty.Register(
+ "Opacity",
+ typeof(double),
+ typeof(RenderCanvasBrushBase),
+ new PropertyMetadata(1d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the opacity of the brush.
+ ///
+ public double Opacity
+ {
+ get => (double)GetValue(OpacityProperty);
+ set => SetValue(OpacityProperty, value);
+ }
+
+ ///
+ /// Transform Dependency Property
+ ///
+ public static readonly DependencyProperty TransformProperty = DependencyProperty.Register(
+ "Transform",
+ typeof(MatrixTransform),
+ typeof(RenderCanvasBrushBase),
+ new PropertyMetadata(new MatrixTransform { Matrix = Matrix.Identity }, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the transform matrix applied to the brush.
+ ///
+ public MatrixTransform Transform
+ {
+ get => (MatrixTransform)GetValue(TransformProperty);
+ set => SetValue(TransformProperty, value);
+ }
+
+ ///
+ /// Refreshes the CanvasBrush when any of the properties are updated
+ ///
+ protected virtual void OnUpdated()
+ {
+ RaiseUpdatedEvent();
+ }
+
+ ///
+ /// Raises the Updated event.
+ ///
+ protected void RaiseUpdatedEvent()
+ {
+ Updated?.Invoke(this, null);
+ }
+
+ ///
+ /// Call this method to redraw its Geometry (usually when event is raised).
+ ///
+ public void Refresh()
+ {
+ OnUpdated();
+ }
+
+ ///
+ /// Disposes the resources used by the CanvasCoreGeometry and its derivatives
+ ///
+ /// Flag to indicate if we are disposing the managed objects.
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposedValue)
+ {
+ if (disposing)
+ {
+ }
+
+ _disposedValue = true;
+ }
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void Dispose()
+ {
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Method that is called whenever the dependency properties of the Brush changes
+ ///
+ /// The object whose property has changed
+ /// Event arguments
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var brush = (RenderCanvasBrushBase)d;
+
+ // Recreate the canvas brush on any property change.
+ brush.Refresh();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Brushes/Base/RenderSurfaceBrushBase.cs b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/Base/RenderSurfaceBrushBase.cs
new file mode 100644
index 00000000000..d3794ded81e
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/Base/RenderSurfaceBrushBase.cs
@@ -0,0 +1,206 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Windows.UI.Composition;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media
+{
+ ///
+ /// Base class for RenderSurface brushes.
+ ///
+ public abstract class RenderSurfaceBrushBase : XamlCompositionBrushBase
+ {
+ ///
+ /// Event which indicates that the components of the brush have changed.
+ ///
+ public event EventHandler Updated;
+
+ ///
+ /// Gets or sets the CompositionSurface associated with the brush.
+ ///
+ protected IRenderSurface RenderSurface { get; set; }
+
+ ///
+ /// The initialization instance.
+ ///
+ private readonly AsyncMutex connectedMutex = new();
+
+ ///
+ /// Gets the associated CompositionBrush
+ ///
+ internal CompositionBrush Brush
+ {
+ get
+ {
+ return CompositionBrush;
+ }
+ }
+
+ ///
+ /// SurfaceWidth Dependency Property
+ ///
+ public static readonly DependencyProperty SurfaceWidthProperty = DependencyProperty.Register(
+ "SurfaceWidth",
+ typeof(double),
+ typeof(RenderSurfaceBrushBase),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the width of the Brush Surface.
+ ///
+ public double SurfaceWidth
+ {
+ get => (double)GetValue(SurfaceWidthProperty);
+ set => SetValue(SurfaceWidthProperty, value);
+ }
+
+ ///
+ /// SurfaceHeight Dependency Property
+ ///
+ public static readonly DependencyProperty SurfaceHeightProperty = DependencyProperty.Register(
+ "SurfaceHeight",
+ typeof(double),
+ typeof(RenderSurfaceBrushBase),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the height of the Brush Surface.
+ ///
+ public double SurfaceHeight
+ {
+ get => (double)GetValue(SurfaceHeightProperty);
+ set => SetValue(SurfaceHeightProperty, value);
+ }
+
+ ///
+ /// Gets or sets the instance.
+ ///
+ protected ICompositionGenerator Generator { get; set; }
+
+ ///
+ /// Method that is called whenever the dependency properties of the Brush changes.
+ ///
+ /// The object whose property has changed.
+ /// Event arguments.
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var brush = (RenderSurfaceBrushBase)d;
+
+ if (brush.SurfaceWidth < 0d)
+ {
+ throw new ArgumentException("SurfaceWidth must be a positive number!");
+ }
+
+ if (brush.SurfaceHeight < 0d)
+ {
+ throw new ArgumentException("SurfaceHeight must be a positive number!");
+ }
+
+ // Recreate the Render Surface Brush on any property change.
+ brush.Refresh();
+ }
+
+ ///
+ /// Gets the CompositionGenerator Instance.
+ ///
+ protected void GetGeneratorInstance()
+ {
+ if (Window.Current != null)
+ {
+ Generator = CompositionGenerator.Instance;
+
+ Generator.DeviceReplaced += OnDeviceReplaced;
+ }
+ }
+
+ ///
+ protected override async void OnConnected()
+ {
+ using (await connectedMutex.LockAsync())
+ {
+ if (CompositionBrush == null)
+ {
+ GetGeneratorInstance();
+
+ OnSurfaceBrushUpdated(true);
+ }
+ }
+
+ base.OnConnected();
+ }
+
+ ///
+ protected override async void OnDisconnected()
+ {
+ using (await connectedMutex.LockAsync())
+ {
+ if (Generator != null)
+ {
+ Generator.DeviceReplaced -= OnDeviceReplaced;
+ Generator = null;
+ }
+
+ // Dispose Brush resources
+ OnSurfaceBrushDisposed();
+
+ // Dispose of composition resources when no longer in use.
+ if (CompositionBrush != null)
+ {
+ CompositionBrush.Dispose();
+ CompositionBrush = null;
+ }
+ }
+
+ base.OnDisconnected();
+ }
+
+ ///
+ /// Handler for the DeviceReplaced event.
+ ///
+ /// Sender.
+ /// EventArgs.
+ private void OnDeviceReplaced(object sender, object e)
+ {
+ OnDisconnected();
+ OnConnected();
+ }
+
+ ///
+ /// Invoked whenever any brush property is updated.
+ ///
+ /// Indicates whether the surface needs to be created.
+ protected virtual void OnSurfaceBrushUpdated(bool createSurface = false)
+ {
+ Updated?.Invoke(this, null);
+ }
+
+ ///
+ /// Invoked whenever any brush property is updated.
+ ///
+ protected virtual void OnSurfaceBrushDisposed()
+ {
+ }
+
+ ///
+ /// Redraws the brush content
+ ///
+ public void Refresh()
+ {
+ OnSurfaceBrushUpdated();
+ }
+
+ ///
+ /// Checks if the URI starts with http: or https:.
+ ///
+ /// URI.
+ /// True if it does, otherwise false.
+ protected static bool IsHttpUri(Uri uri)
+ {
+ return uri != null && uri.IsAbsoluteUri && (uri.Scheme == "http" || uri.Scheme == "https");
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Brushes/GeometryMaskSurfaceBrush.cs b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/GeometryMaskSurfaceBrush.cs
new file mode 100644
index 00000000000..80b77351e51
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/GeometryMaskSurfaceBrush.cs
@@ -0,0 +1,238 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Numerics;
+using Microsoft.Toolkit.Uwp.Helpers;
+using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
+using Windows.Foundation;
+using Windows.System;
+using Windows.UI.Composition;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media
+{
+ ///
+ /// Represents a brush which defines a as a mask to be applied on a derivative.
+ ///
+ public sealed class GeometryMaskSurfaceBrush : RenderSurfaceBrushBase
+ {
+ private CompositionMaskBrush _maskBrush;
+
+ private WeakEventListener _maskUpdateListener;
+ private WeakEventListener _targetUpdateListener;
+
+ ///
+ /// Target Dependency Property
+ ///
+ public static readonly DependencyProperty TargetProperty = DependencyProperty.Register(
+ "Target",
+ typeof(RenderSurfaceBrushBase),
+ typeof(GeometryMaskSurfaceBrush),
+ new PropertyMetadata(null, OnTargetChanged));
+
+ ///
+ /// Gets or sets the target on which the Mask is applied.
+ ///
+ public RenderSurfaceBrushBase Target
+ {
+ get => (RenderSurfaceBrushBase)GetValue(TargetProperty);
+ set => SetValue(TargetProperty, value);
+ }
+
+ ///
+ /// Handles changes to the Target property.
+ ///
+ /// .
+ /// DependencyProperty changed event arguments.
+ private static void OnTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometryMaskSurfaceBrush = (GeometryMaskSurfaceBrush)d;
+ geometryMaskSurfaceBrush.OnTargetChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the Target dependency property.
+ ///
+ private void OnTargetChanged()
+ {
+ _targetUpdateListener?.Detach();
+ _targetUpdateListener = null;
+
+ if (Target != null)
+ {
+ _targetUpdateListener = new WeakEventListener(Target)
+ {
+ OnEventAction = async (instance, source, args) =>
+ {
+ await DispatcherQueue.GetForCurrentThread().EnqueueAsync(() =>
+ {
+ OnSurfaceBrushUpdated();
+ });
+ }
+ };
+
+ Target.Updated += _targetUpdateListener.OnEvent;
+
+ OnSurfaceBrushUpdated();
+ }
+ }
+
+ ///
+ /// Mask Dependency Property
+ ///
+ public static readonly DependencyProperty MaskProperty = DependencyProperty.Register(
+ "Mask",
+ typeof(CanvasCoreGeometry),
+ typeof(GeometryMaskSurfaceBrush),
+ new PropertyMetadata(null, OnMaskChanged));
+
+ ///
+ /// Gets or sets the Mask Geometry that is applied on the Target Geometry.
+ ///
+ public CanvasCoreGeometry Mask
+ {
+ get => (CanvasCoreGeometry)GetValue(MaskProperty);
+ set => SetValue(MaskProperty, value);
+ }
+
+ ///
+ /// Handles changes to the Mask property.
+ ///
+ /// .
+ /// DependencyProperty changed event arguments.
+ private static void OnMaskChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometryMaskSurfaceBrush = (GeometryMaskSurfaceBrush)d;
+ geometryMaskSurfaceBrush.OnMaskChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the Mask dependency property.
+ ///
+ private void OnMaskChanged()
+ {
+ _maskUpdateListener?.Detach();
+ _maskUpdateListener = null;
+
+ if (Mask != null)
+ {
+ _maskUpdateListener = new WeakEventListener(Mask)
+ {
+ OnEventAction = async (instance, source, args) =>
+ {
+ await DispatcherQueue.GetForCurrentThread().EnqueueAsync(() =>
+ {
+ OnSurfaceBrushUpdated();
+ });
+ }
+ };
+
+ Mask.Updated += _maskUpdateListener.OnEvent;
+
+ OnSurfaceBrushUpdated();
+ }
+ }
+
+ ///
+ /// OffsetX Dependency Property
+ ///
+ public static readonly DependencyProperty OffsetXProperty = DependencyProperty.Register(
+ "OffsetX",
+ typeof(double),
+ typeof(GeometryMaskSurfaceBrush),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the offset on the x-axis from the top left corner of the Brush Surface where the Geometry is rendered.
+ ///
+ public double OffsetX
+ {
+ get => (double)GetValue(OffsetXProperty);
+ set => SetValue(OffsetXProperty, value);
+ }
+
+ ///
+ /// OffsetY Dependency Property
+ ///
+ public static readonly DependencyProperty OffsetYProperty = DependencyProperty.Register(
+ "OffsetY",
+ typeof(double),
+ typeof(GeometryMaskSurfaceBrush),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the offset on the y-axis from the top left corner of the Brush Surface where the Geometry is rendered.
+ ///
+ public double OffsetY
+ {
+ get => (double)GetValue(OffsetYProperty);
+ set => SetValue(OffsetYProperty, value);
+ }
+
+ ///
+ /// BlurRadius Dependency Property
+ ///
+ public static readonly DependencyProperty BlurRadiusProperty = DependencyProperty.Register(
+ "BlurRadius",
+ typeof(double),
+ typeof(GeometryMaskSurfaceBrush),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the radius of Gaussian Blur to be applied on the mask.
+ ///
+ public double BlurRadius
+ {
+ get => (double)GetValue(BlurRadiusProperty);
+ set => SetValue(BlurRadiusProperty, value);
+ }
+
+ ///
+ /// Method that is called whenever the dependency properties of the Brush changes.
+ ///
+ /// The object whose property has changed.
+ /// Event arguments.
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var brush = (GeometryMaskSurfaceBrush)d;
+
+ // Recreate the canvas brush on any property change.
+ brush.OnSurfaceBrushUpdated();
+ }
+
+ ///
+ protected override void OnSurfaceBrushUpdated(bool createSurface = false)
+ {
+ if (Generator == null)
+ {
+ GetGeneratorInstance();
+ }
+
+ if (Target == null || Target.Brush == null || Mask == null || Generator == null)
+ {
+ return;
+ }
+
+ var offset = new Vector2((float)OffsetX, (float)OffsetY);
+
+ _maskBrush = Window.Current.Compositor.CreateMaskBrush();
+ _maskBrush.Source = Target.Brush;
+
+ if (createSurface || (RenderSurface == null))
+ {
+ CompositionBrush?.Dispose();
+ RenderSurface = Generator.CreateGaussianMaskSurface(new Size(SurfaceWidth, SurfaceHeight), Mask.Geometry, offset, (float)BlurRadius);
+ _maskBrush.Mask = Window.Current.Compositor.CreateSurfaceBrush(RenderSurface.Surface);
+ CompositionBrush = _maskBrush;
+ }
+ else
+ {
+ ((IGaussianMaskSurface)RenderSurface).Redraw(new Size(SurfaceWidth, SurfaceHeight), Mask.Geometry, offset, (float)BlurRadius);
+ }
+
+ base.OnSurfaceBrushUpdated(createSurface);
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Brushes/GeometrySurfaceBrush.cs b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/GeometrySurfaceBrush.cs
new file mode 100644
index 00000000000..be803da5dc8
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/GeometrySurfaceBrush.cs
@@ -0,0 +1,384 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Graphics.Canvas.Brushes;
+using Microsoft.Graphics.Canvas.Geometry;
+using Microsoft.Toolkit.Uwp.Helpers;
+using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
+using Windows.Foundation;
+using Windows.System;
+using Windows.UI;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media
+{
+ ///
+ /// Brush which renders the provided .
+ ///
+ public sealed class GeometrySurfaceBrush : RenderSurfaceBrushBase
+ {
+ private WeakEventListener _geometryUpdateListener;
+ private WeakEventListener _strokeUpdateListener;
+ private WeakEventListener _fillBrushUpdateListener;
+ private WeakEventListener _bgBrushUpdateListener;
+ private WeakEventListener _strokeStyleUpdateListener;
+
+ ///
+ /// Geometry Dependency Property
+ ///
+ public static readonly DependencyProperty GeometryProperty = DependencyProperty.Register(
+ "Geometry",
+ typeof(CanvasCoreGeometry),
+ typeof(GeometrySurfaceBrush),
+ new PropertyMetadata(null, OnGeometryChanged));
+
+ ///
+ /// Gets or sets the that is used to paint the surface of the brush.
+ ///
+ public CanvasCoreGeometry Geometry
+ {
+ get => (CanvasCoreGeometry)GetValue(GeometryProperty);
+ set => SetValue(GeometryProperty, value);
+ }
+
+ ///
+ /// Handles changes to the Geometry property.
+ ///
+ /// .
+ /// DependencyProperty changed event arguments.
+ private static void OnGeometryChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var maskSurfaceBrush = (GeometrySurfaceBrush)d;
+ maskSurfaceBrush.OnGeometryChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the Geometry dependency property.
+ ///
+ private void OnGeometryChanged()
+ {
+ _geometryUpdateListener?.Detach();
+ _geometryUpdateListener = null;
+
+ if (Geometry != null)
+ {
+ _geometryUpdateListener = new WeakEventListener(Geometry)
+ {
+ OnEventAction = async (instance, source, args) =>
+ {
+ await DispatcherQueue.GetForCurrentThread().EnqueueAsync(() =>
+ {
+ OnSurfaceBrushUpdated();
+ });
+ }
+ };
+
+ Geometry.Updated += _geometryUpdateListener.OnEvent;
+
+ OnSurfaceBrushUpdated();
+ }
+ }
+
+ ///
+ /// Stroke Dependency Property
+ ///
+ public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
+ "Stroke",
+ typeof(RenderCanvasBrushBase),
+ typeof(GeometrySurfaceBrush),
+ new PropertyMetadata(null, OnStrokeChanged));
+
+ ///
+ /// Gets or sets the brush for rendering the outline stroke of the geometry.
+ ///
+ public RenderCanvasBrushBase Stroke
+ {
+ get => (RenderCanvasBrushBase)GetValue(StrokeProperty);
+ set => SetValue(StrokeProperty, value);
+ }
+
+ ///
+ /// Handles changes to the Stroke property.
+ ///
+ /// .
+ /// DependencyProperty changed event arguments.
+ private static void OnStrokeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometrySurfaceBrush = (GeometrySurfaceBrush)d;
+ geometrySurfaceBrush.OnStrokeChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the Stroke dependency property.
+ ///
+ private void OnStrokeChanged()
+ {
+ _strokeUpdateListener?.Detach();
+ _strokeUpdateListener = null;
+
+ if (Stroke != null)
+ {
+ _strokeUpdateListener = new WeakEventListener(Stroke)
+ {
+ OnEventAction = async (instance, source, args) =>
+ {
+ await DispatcherQueue.GetForCurrentThread().EnqueueAsync(() =>
+ {
+ OnSurfaceBrushUpdated();
+ });
+ }
+ };
+
+ Stroke.Updated += _strokeUpdateListener.OnEvent;
+
+ OnSurfaceBrushUpdated();
+ }
+ }
+
+ ///
+ /// StrokeThickness Dependency Property
+ ///
+ public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
+ "StrokeThickness",
+ typeof(double),
+ typeof(GeometrySurfaceBrush),
+ new PropertyMetadata(0d, OnStrokeThicknessChanged));
+
+ ///
+ /// Gets or sets the thickness of the outline of the geometry.
+ ///
+ public double StrokeThickness
+ {
+ get => (double)GetValue(StrokeThicknessProperty);
+ set => SetValue(StrokeThicknessProperty, value);
+ }
+
+ ///
+ /// Handles changes to the StrokeThickness property.
+ ///
+ /// .
+ /// DependencyProperty changed event arguments.
+ private static void OnStrokeThicknessChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometrySurfaceBrush = (GeometrySurfaceBrush)d;
+ geometrySurfaceBrush.OnStrokeThicknessChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the StrokeThickness dependency property.
+ ///
+ private void OnStrokeThicknessChanged()
+ {
+ if (StrokeThickness < 0d)
+ {
+ throw new ArgumentException("StrokeThickness must be a non-negative number.");
+ }
+
+ OnSurfaceBrushUpdated();
+ }
+
+ ///
+ /// RenderStrokeStyle Dependency Property
+ ///
+ public static readonly DependencyProperty RenderStrokeStyleProperty = DependencyProperty.Register(
+ "RenderStrokeStyle",
+ typeof(StrokeStyle),
+ typeof(GeometrySurfaceBrush),
+ new PropertyMetadata(null, OnRenderStrokeStyleChanged));
+
+ ///
+ /// Gets or sets the style of the outline for the Geometry.
+ ///
+ public StrokeStyle RenderStrokeStyle
+ {
+ get => (StrokeStyle)GetValue(RenderStrokeStyleProperty);
+ set => SetValue(RenderStrokeStyleProperty, value);
+ }
+
+ ///
+ /// Handles changes to the RenderStrokeStyle property.
+ ///
+ /// .
+ /// DependencyProperty changed event arguments.
+ private static void OnRenderStrokeStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometrySurfaceBrush = (GeometrySurfaceBrush)d;
+ geometrySurfaceBrush.OnRenderStrokeStyleChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the RenderStrokeStyle dependency property.
+ ///
+ private void OnRenderStrokeStyleChanged()
+ {
+ _strokeStyleUpdateListener?.Detach();
+ _strokeStyleUpdateListener = null;
+
+ if (RenderStrokeStyle != null)
+ {
+ _strokeStyleUpdateListener = new WeakEventListener(RenderStrokeStyle)
+ {
+ OnEventAction = async (instance, source, args) =>
+ {
+ await DispatcherQueue.GetForCurrentThread().EnqueueAsync(() =>
+ {
+ OnSurfaceBrushUpdated();
+ });
+ }
+ };
+
+ RenderStrokeStyle.Updated += _strokeStyleUpdateListener.OnEvent;
+
+ OnSurfaceBrushUpdated();
+ }
+ }
+
+ ///
+ /// FillBrush Dependency Property
+ ///
+ public static readonly DependencyProperty FillBrushProperty = DependencyProperty.Register(
+ "FillBrush",
+ typeof(RenderCanvasBrushBase),
+ typeof(GeometrySurfaceBrush),
+ new PropertyMetadata(null, OnFillBrushChanged));
+
+ ///
+ /// Gets or sets the brush which will be used to fill the geometry.
+ ///
+ public RenderCanvasBrushBase FillBrush
+ {
+ get => (RenderCanvasBrushBase)GetValue(FillBrushProperty);
+ set => SetValue(FillBrushProperty, value);
+ }
+
+ ///
+ /// Handles changes to the FillBrush property.
+ ///
+ /// .
+ /// DependencyProperty changed event arguments.
+ private static void OnFillBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometrySurfaceBrush = (GeometrySurfaceBrush)d;
+ geometrySurfaceBrush.OnFillBrushChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the FillBrush dependency property.
+ ///
+ private void OnFillBrushChanged()
+ {
+ _fillBrushUpdateListener?.Detach();
+ _fillBrushUpdateListener = null;
+
+ if (FillBrush != null)
+ {
+ _fillBrushUpdateListener = new WeakEventListener(FillBrush)
+ {
+ OnEventAction = async (instance, source, args) =>
+ {
+ await DispatcherQueue.GetForCurrentThread().EnqueueAsync(() =>
+ {
+ OnSurfaceBrushUpdated();
+ });
+ }
+ };
+
+ FillBrush.Updated += _fillBrushUpdateListener.OnEvent;
+
+ OnSurfaceBrushUpdated();
+ }
+ }
+
+ ///
+ /// BackgroundBrush Dependency Property
+ ///
+ public static readonly DependencyProperty BackgroundBrushProperty = DependencyProperty.Register(
+ "BackgroundBrush",
+ typeof(RenderCanvasBrushBase),
+ typeof(GeometrySurfaceBrush),
+ new PropertyMetadata(null, OnBackgroundBrushChanged));
+
+ ///
+ /// Gets or sets the brush with which the background of the Geometry surface will be rendered.
+ ///
+ public RenderCanvasBrushBase BackgroundBrush
+ {
+ get => (RenderCanvasBrushBase)GetValue(BackgroundBrushProperty);
+ set => SetValue(BackgroundBrushProperty, value);
+ }
+
+ ///
+ /// Handles changes to the BackgroundBrush property.
+ ///
+ /// .
+ /// DependencyProperty changed event arguments.
+ private static void OnBackgroundBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometrySurfaceBrush = (GeometrySurfaceBrush)d;
+ geometrySurfaceBrush.OnBackgroundBrushChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the BackgroundBrush dependency property.
+ ///
+ private void OnBackgroundBrushChanged()
+ {
+ _bgBrushUpdateListener?.Detach();
+ _bgBrushUpdateListener = null;
+
+ if (BackgroundBrush != null)
+ {
+ _bgBrushUpdateListener = new WeakEventListener(BackgroundBrush)
+ {
+ OnEventAction = async (instance, source, args) =>
+ {
+ await DispatcherQueue.GetForCurrentThread().EnqueueAsync(() =>
+ {
+ OnSurfaceBrushUpdated();
+ });
+ }
+ };
+
+ BackgroundBrush.Updated += _bgBrushUpdateListener.OnEvent;
+
+ OnSurfaceBrushUpdated();
+ }
+ }
+
+ ///
+ protected override void OnSurfaceBrushUpdated(bool createSurface = false)
+ {
+ if (Generator == null)
+ {
+ GetGeneratorInstance();
+ }
+
+ if (Geometry == null || Generator == null)
+ {
+ return;
+ }
+
+ var transparentBrush = new CanvasSolidColorBrush(Generator.Device, Colors.Transparent);
+ var strokeBrush = (Stroke == null) ? transparentBrush : Stroke.CanvasBrush;
+ var fillBrush = (FillBrush == null) ? transparentBrush : FillBrush.CanvasBrush;
+ var bgBrush = (BackgroundBrush == null) ? transparentBrush : BackgroundBrush.CanvasBrush;
+ var strokeStyle = (RenderStrokeStyle == null) ? new CanvasStrokeStyle() : RenderStrokeStyle.GetCanvasStrokeStyle();
+ var canvasStroke = new CanvasStroke(strokeBrush, (float)StrokeThickness, strokeStyle);
+
+ if (createSurface || (RenderSurface == null))
+ {
+ CompositionBrush?.Dispose();
+ RenderSurface = Generator.CreateGeometrySurface(new Size(SurfaceWidth, SurfaceHeight), Geometry.Geometry, canvasStroke, fillBrush, bgBrush);
+ CompositionBrush = Window.Current.Compositor.CreateSurfaceBrush(RenderSurface.Surface);
+ }
+ else
+ {
+ ((IGeometrySurface)RenderSurface).Redraw(new Size(SurfaceWidth, SurfaceHeight), Geometry.Geometry, canvasStroke, fillBrush, bgBrush);
+ }
+
+ base.OnSurfaceBrushUpdated(createSurface);
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Brushes/ImageMaskSurfaceBrush.cs b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/ImageMaskSurfaceBrush.cs
new file mode 100644
index 00000000000..61f1237aed2
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/ImageMaskSurfaceBrush.cs
@@ -0,0 +1,266 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Toolkit.Uwp.Helpers;
+using Windows.Foundation;
+using Windows.System;
+using Windows.UI.Composition;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media
+{
+ ///
+ /// Represents a brush which uses an Image to create a mask to be applied on a derivative.
+ ///
+ public sealed class ImageMaskSurfaceBrush : RenderSurfaceBrushBase
+ {
+ private WeakEventListener _targetUpdateListener;
+ private WeakEventListener _imageSurfaceOptionsUpdateListener;
+
+ private CompositionMaskBrush _maskBrush;
+ private Uri _uri;
+
+ ///
+ /// Target Dependency Property
+ ///
+ public static readonly DependencyProperty TargetProperty = DependencyProperty.Register(
+ "Target",
+ typeof(RenderSurfaceBrushBase),
+ typeof(ImageMaskSurfaceBrush),
+ new PropertyMetadata(null, OnTargetChanged));
+
+ ///
+ /// Gets or sets the RenderSurfaceBrush upon which the mask is applied.
+ ///
+ public RenderSurfaceBrushBase Target
+ {
+ get => (RenderSurfaceBrushBase)GetValue(TargetProperty);
+ set => SetValue(TargetProperty, value);
+ }
+
+ ///
+ /// Handles changes to the Target property.
+ ///
+ ///
+ /// DependencyProperty changed event arguments
+ private static void OnTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var imageMaskSurfaceBrush = (ImageMaskSurfaceBrush)d;
+ imageMaskSurfaceBrush.OnTargetChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the Target dependency property.
+ ///
+ private void OnTargetChanged()
+ {
+ _targetUpdateListener?.Detach();
+ _targetUpdateListener = null;
+
+ if (Target != null)
+ {
+ _targetUpdateListener = new WeakEventListener(Target)
+ {
+ OnEventAction = async (instance, source, args) =>
+ {
+ await DispatcherQueue.GetForCurrentThread().EnqueueAsync(() =>
+ {
+ OnSurfaceBrushUpdated(true);
+ });
+ }
+ };
+
+ Target.Updated += _targetUpdateListener.OnEvent;
+
+ OnSurfaceBrushUpdated(true);
+ }
+ }
+
+ ///
+ /// Mask Dependency Property
+ ///
+ public static readonly DependencyProperty MaskProperty = DependencyProperty.Register(
+ "Mask",
+ typeof(object),
+ typeof(ImageMaskSurfaceBrush),
+ new PropertyMetadata(null, OnMaskChanged));
+
+ ///
+ /// Gets or sets the URI of the image that is used to create the mask.
+ ///
+ public object Mask
+ {
+ get => (object)GetValue(MaskProperty);
+ set => SetValue(MaskProperty, value);
+ }
+
+ ///
+ /// Handles changes to the Mask property.
+ ///
+ ///
+ /// DependencyProperty changed event arguments
+ private static void OnMaskChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var imageMaskSurfaceBrush = (ImageMaskSurfaceBrush)d;
+ imageMaskSurfaceBrush.OnMaskChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the Mask dependency property.
+ ///
+ private void OnMaskChanged()
+ {
+ if (Mask == null)
+ {
+ return;
+ }
+
+ var uri = Mask as Uri;
+ if (uri == null)
+ {
+ var url = Mask as string ?? Mask.ToString();
+ if (!Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out uri))
+ {
+ _uri = null;
+ return;
+ }
+ }
+
+ if (!IsHttpUri(uri) && !uri.IsAbsoluteUri)
+ {
+ _uri = new Uri("ms-appx:///" + uri.OriginalString.TrimStart('/'));
+ }
+
+ _uri = uri;
+
+ OnSurfaceBrushUpdated(true);
+ }
+
+ ///
+ /// ImageOptions Dependency Property
+ ///
+ public static readonly DependencyProperty ImageOptionsProperty = DependencyProperty.Register(
+ "ImageOptions",
+ typeof(ImageSurfaceOptions),
+ typeof(ImageMaskSurfaceBrush),
+ new PropertyMetadata(null, OnImageOptionsChanged));
+
+ ///
+ /// Gets or sets the additional options that can be used to configure the image used to create the brush.
+ ///
+ public ImageSurfaceOptions ImageOptions
+ {
+ get => (ImageSurfaceOptions)GetValue(ImageOptionsProperty);
+ set => SetValue(ImageOptionsProperty, value);
+ }
+
+ ///
+ /// Handles changes to the ImageOptions property.
+ ///
+ ///
+ /// DependencyProperty changed event arguments
+ private static void OnImageOptionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var imageMaskSurfaceBrush = (ImageMaskSurfaceBrush)d;
+ imageMaskSurfaceBrush.OnImageOptionsChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the ImageOptions dependency property.
+ ///
+ private void OnImageOptionsChanged()
+ {
+ _imageSurfaceOptionsUpdateListener?.Detach();
+ _imageSurfaceOptionsUpdateListener = null;
+
+ if (ImageOptions != null)
+ {
+ _imageSurfaceOptionsUpdateListener = new WeakEventListener(ImageOptions)
+ {
+ OnEventAction = async (instance, source, args) =>
+ {
+ await DispatcherQueue.GetForCurrentThread().EnqueueAsync(() =>
+ {
+ OnSurfaceBrushUpdated();
+ });
+ }
+ };
+
+ ImageOptions.Updated += _imageSurfaceOptionsUpdateListener.OnEvent;
+
+ OnSurfaceBrushUpdated();
+ }
+ }
+
+ ///
+ /// Padding Dependency Property
+ ///
+ public static readonly DependencyProperty PaddingProperty = DependencyProperty.Register(
+ "Padding",
+ typeof(Thickness),
+ typeof(ImageMaskSurfaceBrush),
+ new PropertyMetadata(new Thickness(0d), OnPaddingChanged));
+
+ ///
+ /// Gets or sets the padding between the IImageMaskSurface outer bounds and the bounds of the area where the mask, created from the loaded image's alpha values, should be rendered.
+ ///
+ public Thickness Padding
+ {
+ get => (Thickness)GetValue(PaddingProperty);
+ set => SetValue(PaddingProperty, value);
+ }
+
+ ///
+ /// Handles changes to the Padding property.
+ ///
+ ///
+ /// DependencyProperty changed event arguments
+ private static void OnPaddingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var imageMaskSurfaceBrush = (ImageMaskSurfaceBrush)d;
+ imageMaskSurfaceBrush.OnPaddingChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the Padding dependency property.
+ ///
+ private void OnPaddingChanged()
+ {
+ OnSurfaceBrushUpdated();
+ }
+
+ ///
+ protected async override void OnSurfaceBrushUpdated(bool createSurface = false)
+ {
+ if (Generator == null)
+ {
+ GetGeneratorInstance();
+ }
+
+ if (Target == null || Target.Brush == null || _uri == null || Generator == null)
+ {
+ return;
+ }
+
+ if (createSurface || (RenderSurface == null))
+ {
+ CompositionBrush?.Dispose();
+
+ _maskBrush = Window.Current.Compositor.CreateMaskBrush();
+ _maskBrush.Source = Target.Brush;
+
+ RenderSurface = await Generator.CreateImageMaskSurfaceAsync(_uri, new Size(SurfaceWidth, SurfaceHeight), Padding, ImageOptions ?? ImageSurfaceOptions.DefaultImageMaskOptions);
+ _maskBrush.Mask = Window.Current.Compositor.CreateSurfaceBrush(RenderSurface.Surface);
+ CompositionBrush = _maskBrush;
+ }
+ else
+ {
+ ((IImageMaskSurface)RenderSurface)?.Redraw(new Size(SurfaceWidth, SurfaceHeight), Padding, ImageOptions ?? ImageSurfaceOptions.DefaultImageMaskOptions);
+ }
+
+ base.OnSurfaceBrushUpdated(createSurface);
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Brushes/ImageSurfaceBrush.cs b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/ImageSurfaceBrush.cs
new file mode 100644
index 00000000000..6f6a4c46841
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/ImageSurfaceBrush.cs
@@ -0,0 +1,204 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Toolkit.Uwp.Helpers;
+using Windows.Foundation;
+using Windows.System;
+using Windows.UI;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media
+{
+ ///
+ /// Creates a Render Surface brush using an image
+ ///
+ public class ImageSurfaceBrush : RenderSurfaceBrushBase
+ {
+ private WeakEventListener _imageSurfaceOptionsUpdateListener;
+
+ private Uri _uri;
+
+ ///
+ /// Background Dependency Property
+ ///
+ public static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register(
+ "Background",
+ typeof(Color),
+ typeof(ImageSurfaceBrush),
+ new PropertyMetadata(Colors.Transparent, OnBackgroundChanged));
+
+ ///
+ /// Gets or sets the color that is rendered in the transparent areas of the Image. The default value is Colors.Transparent.
+ ///
+ public Color Background
+ {
+ get => (Color)GetValue(BackgroundProperty);
+ set => SetValue(BackgroundProperty, value);
+ }
+
+ ///
+ /// Handles changes to the Background property.
+ ///
+ ///
+ /// DependencyProperty changed event arguments
+ private static void OnBackgroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var imageSurfaceBrush = (ImageSurfaceBrush)d;
+ imageSurfaceBrush.OnBackgroundChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the Background dependency property.
+ ///
+ private void OnBackgroundChanged()
+ {
+ OnSurfaceBrushUpdated();
+ }
+
+ ///
+ /// Source Dependency Property
+ ///
+ public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
+ "Source",
+ typeof(object),
+ typeof(ImageSurfaceBrush),
+ new PropertyMetadata(null, OnSourceChanged));
+
+ ///
+ /// Gets or sets the object representing the image source.
+ ///
+ public object Source
+ {
+ get => (object)GetValue(SourceProperty);
+ set => SetValue(SourceProperty, value);
+ }
+
+ ///
+ /// Handles changes to the Source property.
+ ///
+ ///
+ /// DependencyProperty changed event arguments
+ private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var target = (ImageSurfaceBrush)d;
+ target.OnSourceChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the Source dependency property.
+ ///
+ private void OnSourceChanged()
+ {
+ if (Source == null)
+ {
+ return;
+ }
+
+ var uri = Source as Uri;
+
+ if (uri == null)
+ {
+ var url = Source as string ?? Source.ToString();
+ if (!Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out uri))
+ {
+ _uri = null;
+ return;
+ }
+ }
+
+ if (!IsHttpUri(uri) && !uri.IsAbsoluteUri)
+ {
+ _uri = new Uri("ms-appx:///" + uri.OriginalString.TrimStart('/'));
+ }
+
+ _uri = uri;
+
+ OnSurfaceBrushUpdated(true);
+ }
+
+ ///
+ /// ImageOptions Dependency Property
+ ///
+ public static readonly DependencyProperty ImageOptionsProperty = DependencyProperty.Register(
+ "ImageOptions",
+ typeof(ImageSurfaceOptions),
+ typeof(ImageSurfaceBrush),
+ new PropertyMetadata(null, OnImageOptionsChanged));
+
+ ///
+ /// Gets or sets the additional options that can be used to configure the image used to create the brush.
+ ///
+ public ImageSurfaceOptions ImageOptions
+ {
+ get => (ImageSurfaceOptions)GetValue(ImageOptionsProperty);
+ set => SetValue(ImageOptionsProperty, value);
+ }
+
+ ///
+ /// Handles changes to the ImageOptions property.
+ ///
+ ///
+ /// DependencyProperty changed event arguments
+ private static void OnImageOptionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var imageSurfaceBrush = (ImageSurfaceBrush)d;
+ imageSurfaceBrush.OnImageOptionsChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the ImageOptions dependency property.
+ ///
+ private void OnImageOptionsChanged()
+ {
+ _imageSurfaceOptionsUpdateListener?.Detach();
+ _imageSurfaceOptionsUpdateListener = null;
+
+ if (ImageOptions != null)
+ {
+ _imageSurfaceOptionsUpdateListener = new WeakEventListener(ImageOptions)
+ {
+ OnEventAction = async (instance, source, args) =>
+ {
+ await DispatcherQueue.GetForCurrentThread().EnqueueAsync(() =>
+ {
+ OnSurfaceBrushUpdated();
+ });
+ }
+ };
+
+ ImageOptions.Updated += _imageSurfaceOptionsUpdateListener.OnEvent;
+
+ OnSurfaceBrushUpdated();
+ }
+ }
+
+ ///
+ protected async override void OnSurfaceBrushUpdated(bool createSurface = false)
+ {
+ if (Generator == null)
+ {
+ GetGeneratorInstance();
+ }
+
+ if (_uri == null || Generator == null)
+ {
+ return;
+ }
+
+ if (createSurface || (RenderSurface == null))
+ {
+ CompositionBrush?.Dispose();
+ RenderSurface = await Generator?.CreateImageSurfaceAsync(_uri, new Size(SurfaceWidth, SurfaceHeight), ImageOptions ?? ImageSurfaceOptions.Default);
+ CompositionBrush = Window.Current.Compositor.CreateSurfaceBrush(RenderSurface.Surface);
+ }
+ else
+ {
+ ((IImageSurface)RenderSurface)?.Redraw(new Size(SurfaceWidth, SurfaceHeight), ImageOptions ?? ImageSurfaceOptions.Default);
+ }
+
+ base.OnSurfaceBrushUpdated(createSurface);
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Brushes/LinearGradientCanvasBrush.cs b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/LinearGradientCanvasBrush.cs
new file mode 100644
index 00000000000..8d0e2261aa7
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/LinearGradientCanvasBrush.cs
@@ -0,0 +1,216 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Numerics;
+using Microsoft.Graphics.Canvas;
+using Microsoft.Graphics.Canvas.Brushes;
+using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
+using Windows.Foundation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Markup;
+using Windows.UI.Xaml.Media;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media.Brushes
+{
+ ///
+ /// XAML equivalent of Win2d's CanvasLinearGradientBrush class which paints in linear gradient.
+ ///
+ [ContentProperty(Name = nameof(Stops))]
+ public class LinearGradientCanvasBrush : RenderCanvasBrushBase
+ {
+ ///
+ /// AlphaMode Dependency Property
+ ///
+ public static readonly DependencyProperty AlphaModeProperty = DependencyProperty.Register(
+ "AlphaMode",
+ typeof(CanvasAlphaMode),
+ typeof(LinearGradientCanvasBrush),
+ new PropertyMetadata(CanvasAlphaMode.Premultiplied, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the way in which the Alpha channel affects color channels.
+ ///
+ public CanvasAlphaMode AlphaMode
+ {
+ get => (CanvasAlphaMode)GetValue(AlphaModeProperty);
+ set => SetValue(AlphaModeProperty, value);
+ }
+
+ ///
+ /// BufferPrecision Dependency Property
+ ///
+ public static readonly DependencyProperty BufferPrecisionProperty = DependencyProperty.Register(
+ "BufferPrecision",
+ typeof(CanvasBufferPrecision),
+ typeof(LinearGradientCanvasBrush),
+ new PropertyMetadata(CanvasBufferPrecision.Precision8UIntNormalized, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the precision used for computation.
+ ///
+ public CanvasBufferPrecision BufferPrecision
+ {
+ get => (CanvasBufferPrecision)GetValue(BufferPrecisionProperty);
+ set => SetValue(BufferPrecisionProperty, value);
+ }
+
+ ///
+ /// EdgeBehavior Dependency Property
+ ///
+ public static readonly DependencyProperty EdgeBehaviorProperty = DependencyProperty.Register(
+ "EdgeBehavior",
+ typeof(CanvasEdgeBehavior),
+ typeof(LinearGradientCanvasBrush),
+ new PropertyMetadata(CanvasEdgeBehavior.Clamp, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the behavior of the pixels which fall outside of the gradient's typical rendering area.
+ ///
+ public CanvasEdgeBehavior EdgeBehavior
+ {
+ get => (CanvasEdgeBehavior)GetValue(EdgeBehaviorProperty);
+ set => SetValue(EdgeBehaviorProperty, value);
+ }
+
+ ///
+ /// EndPoint Dependency Property
+ ///
+ public static readonly DependencyProperty EndPointProperty = DependencyProperty.Register(
+ "EndPoint",
+ typeof(Point),
+ typeof(LinearGradientCanvasBrush),
+ new PropertyMetadata(default(Point), OnPropertyChanged));
+
+ ///
+ /// Gets or sets the point on the Canvas where the gradient stops.
+ ///
+ public Point EndPoint
+ {
+ get => (Point)GetValue(EndPointProperty);
+ set => SetValue(EndPointProperty, value);
+ }
+
+ ///
+ /// PostInterpolationSpace Dependency Property
+ ///
+ public static readonly DependencyProperty PostInterpolationSpaceProperty = DependencyProperty.Register(
+ "PostInterpolationSpace",
+ typeof(CanvasColorSpace),
+ typeof(LinearGradientCanvasBrush),
+ new PropertyMetadata(CanvasColorSpace.Srgb, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the the color space to be used after interpolation.
+ ///
+ public CanvasColorSpace PostInterpolationSpace
+ {
+ get => (CanvasColorSpace)GetValue(PostInterpolationSpaceProperty);
+ set => SetValue(PostInterpolationSpaceProperty, value);
+ }
+
+ ///
+ /// PreInterpolationSpace Dependency Property
+ ///
+ public static readonly DependencyProperty PreInterpolationSpaceProperty = DependencyProperty.Register(
+ "PreInterpolationSpace",
+ typeof(CanvasColorSpace),
+ typeof(LinearGradientCanvasBrush),
+ new PropertyMetadata(CanvasColorSpace.Srgb, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the the color space to be used before interpolation.
+ ///
+ public CanvasColorSpace PreInterpolationSpace
+ {
+ get => (CanvasColorSpace)GetValue(PreInterpolationSpaceProperty);
+ set => SetValue(PreInterpolationSpaceProperty, value);
+ }
+
+ ///
+ /// StartPoint Dependency Property
+ ///
+ public static readonly DependencyProperty StartPointProperty = DependencyProperty.Register(
+ "StartPoint",
+ typeof(Point),
+ typeof(LinearGradientCanvasBrush),
+ new PropertyMetadata(default(Point), OnPropertyChanged));
+
+ ///
+ /// Gets or sets the point on the Canvas where the gradient starts.
+ ///
+ public Point StartPoint
+ {
+ get => (Point)GetValue(StartPointProperty);
+ set => SetValue(StartPointProperty, value);
+ }
+
+ ///
+ /// Stops Dependency Property
+ ///
+ public static readonly DependencyProperty StopsProperty = DependencyProperty.Register(
+ "Stops",
+ typeof(GradientStopCollection),
+ typeof(LinearGradientCanvasBrush),
+ new PropertyMetadata(null, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the gradient stops that comprise the brush.
+ ///
+ public GradientStopCollection Stops
+ {
+ get => (GradientStopCollection)GetValue(StopsProperty);
+ set => SetValue(StopsProperty, value);
+ }
+
+ ///
+ /// Method that is called whenever the dependency properties of the Brush changes
+ ///
+ /// The object whose property has changed.
+ /// Event arguments.
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var brush = (LinearGradientCanvasBrush)d;
+
+ // Recreate the canvas brush on any property change.
+ brush.OnUpdated();
+ }
+
+ ///
+ protected override void OnUpdated()
+ {
+ if (Stops == null)
+ {
+ return;
+ }
+
+ var canvasGradientStops = new List();
+ foreach (var stop in Stops)
+ {
+ canvasGradientStops.Add(new CanvasGradientStop()
+ {
+ Color = stop.Color,
+ Position = (float)stop.Offset
+ });
+ }
+
+ CanvasBrush = new CanvasLinearGradientBrush(
+ CompositionGenerator.Instance.Device,
+ canvasGradientStops.ToArray(),
+ EdgeBehavior,
+ AlphaMode,
+ PreInterpolationSpace,
+ PostInterpolationSpace,
+ BufferPrecision)
+ {
+ StartPoint = StartPoint.ToVector2(),
+ EndPoint = EndPoint.ToVector2(),
+ Opacity = (float)Opacity,
+ Transform = Transform.ToMatrix3x2()
+ };
+
+ base.OnUpdated();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Brushes/RadialGradientCanvasBrush.cs b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/RadialGradientCanvasBrush.cs
new file mode 100644
index 00000000000..0adfab9934b
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/RadialGradientCanvasBrush.cs
@@ -0,0 +1,263 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Numerics;
+using Microsoft.Graphics.Canvas;
+using Microsoft.Graphics.Canvas.Brushes;
+using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
+using Windows.Foundation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Markup;
+using Windows.UI.Xaml.Media;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media
+{
+ ///
+ /// XAML equivalent of Win2d's CanvasRadialGradientBrush class which paints in radial gradient.
+ ///
+ [ContentProperty(Name = nameof(Stops))]
+ public class RadialGradientCanvasBrush : RenderCanvasBrushBase
+ {
+ ///
+ /// AlphaMode Dependency Property
+ ///
+ public static readonly DependencyProperty AlphaModeProperty = DependencyProperty.Register(
+ "AlphaMode",
+ typeof(CanvasAlphaMode),
+ typeof(RadialGradientCanvasBrush),
+ new PropertyMetadata(CanvasAlphaMode.Premultiplied, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the way in which the Alpha channel affects color channels.
+ ///
+ public CanvasAlphaMode AlphaMode
+ {
+ get => (CanvasAlphaMode)GetValue(AlphaModeProperty);
+ set => SetValue(AlphaModeProperty, value);
+ }
+
+ ///
+ /// BufferPrecision Dependency Property
+ ///
+ public static readonly DependencyProperty BufferPrecisionProperty = DependencyProperty.Register(
+ "BufferPrecision",
+ typeof(CanvasBufferPrecision),
+ typeof(RadialGradientCanvasBrush),
+ new PropertyMetadata(CanvasBufferPrecision.Precision8UIntNormalized, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the precision used for computation.
+ ///
+ public CanvasBufferPrecision BufferPrecision
+ {
+ get => (CanvasBufferPrecision)GetValue(BufferPrecisionProperty);
+ set => SetValue(BufferPrecisionProperty, value);
+ }
+
+ ///
+ /// Center Dependency Property
+ ///
+ public static readonly DependencyProperty CenterProperty = DependencyProperty.Register(
+ "Center",
+ typeof(Point),
+ typeof(RadialGradientCanvasBrush),
+ new PropertyMetadata(default(Point), OnPropertyChanged));
+
+ ///
+ /// Gets or sets the center of the brush's radial gradient.
+ ///
+ public Point Center
+ {
+ get => (Point)GetValue(CenterProperty);
+ set => SetValue(CenterProperty, value);
+ }
+
+ ///
+ /// EdgeBehavior Dependency Property
+ ///
+ public static readonly DependencyProperty EdgeBehaviorProperty = DependencyProperty.Register(
+ "EdgeBehavior",
+ typeof(CanvasEdgeBehavior),
+ typeof(RadialGradientCanvasBrush),
+ new PropertyMetadata(CanvasEdgeBehavior.Clamp, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the behavior of the pixels which fall outside of the gradient's typical rendering area.
+ ///
+ public CanvasEdgeBehavior EdgeBehavior
+ {
+ get => (CanvasEdgeBehavior)GetValue(EdgeBehaviorProperty);
+ set => SetValue(EdgeBehaviorProperty, value);
+ }
+
+ ///
+ /// EndPoint Dependency Property
+ ///
+ public static readonly DependencyProperty EndPointProperty = DependencyProperty.Register(
+ "EndPoint",
+ typeof(Point),
+ typeof(RadialGradientCanvasBrush),
+ new PropertyMetadata(default(Point), OnPropertyChanged));
+
+ ///
+ /// OriginOffset Dependency Property
+ ///
+ public static readonly DependencyProperty OriginOffsetProperty = DependencyProperty.Register(
+ "OriginOffset",
+ typeof(Point),
+ typeof(RadialGradientCanvasBrush),
+ new PropertyMetadata(default(Point), OnPropertyChanged));
+
+ ///
+ /// Gets or sets the displacement from Center, used to form the brush's radial gradient.
+ ///
+ public Point OriginOffset
+ {
+ get => (Point)GetValue(OriginOffsetProperty);
+ set => SetValue(OriginOffsetProperty, value);
+ }
+
+ ///
+ /// PostInterpolationSpace Dependency Property
+ ///
+ public static readonly DependencyProperty PostInterpolationSpaceProperty = DependencyProperty.Register(
+ "PostInterpolationSpace",
+ typeof(CanvasColorSpace),
+ typeof(RadialGradientCanvasBrush),
+ new PropertyMetadata(CanvasColorSpace.Srgb, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the the color space to be used after interpolation.
+ ///
+ public CanvasColorSpace PostInterpolationSpace
+ {
+ get => (CanvasColorSpace)GetValue(PostInterpolationSpaceProperty);
+ set => SetValue(PostInterpolationSpaceProperty, value);
+ }
+
+ ///
+ /// PreInterpolationSpace Dependency Property
+ ///
+ public static readonly DependencyProperty PreInterpolationSpaceProperty = DependencyProperty.Register(
+ "PreInterpolationSpace",
+ typeof(CanvasColorSpace),
+ typeof(RadialGradientCanvasBrush),
+ new PropertyMetadata(CanvasColorSpace.Srgb, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the the color space to be used before interpolation.
+ ///
+ public CanvasColorSpace PreInterpolationSpace
+ {
+ get => (CanvasColorSpace)GetValue(PreInterpolationSpaceProperty);
+ set => SetValue(PreInterpolationSpaceProperty, value);
+ }
+
+ ///
+ /// RadiusX Dependency Property
+ ///
+ public static readonly DependencyProperty RadiusXProperty = DependencyProperty.Register(
+ "RadiusX",
+ typeof(double),
+ typeof(RadialGradientCanvasBrush),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the horizontal radius of the brush's radial gradient.
+ ///
+ public double RadiusX
+ {
+ get => (double)GetValue(RadiusXProperty);
+ set => SetValue(RadiusXProperty, value);
+ }
+
+ ///
+ /// RadiusY Dependency Property
+ ///
+ public static readonly DependencyProperty RadiusYProperty = DependencyProperty.Register(
+ "RadiusY",
+ typeof(double),
+ typeof(RadialGradientCanvasBrush),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the vertical radius of the brush's radial gradient.
+ ///
+ public double RadiusY
+ {
+ get => (double)GetValue(RadiusYProperty);
+ set => SetValue(RadiusYProperty, value);
+ }
+
+ ///
+ /// Stops Dependency Property
+ ///
+ public static readonly DependencyProperty StopsProperty = DependencyProperty.Register(
+ "Stops",
+ typeof(GradientStopCollection),
+ typeof(RadialGradientCanvasBrush),
+ new PropertyMetadata(null, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the gradient stops that comprise the brush.
+ ///
+ public GradientStopCollection Stops
+ {
+ get => (GradientStopCollection)GetValue(StopsProperty);
+ set => SetValue(StopsProperty, value);
+ }
+
+ ///
+ /// Method that is called whenever the dependency properties of the Brush changes.
+ ///
+ /// The object whose property has changed.
+ /// Event arguments.
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var brush = (RadialGradientCanvasBrush)d;
+
+ // Recreate the canvas brush on any property change.
+ brush.OnUpdated();
+ }
+
+ ///
+ protected override void OnUpdated()
+ {
+ if (Stops == null)
+ {
+ return;
+ }
+
+ var canvasGradientStops = new List();
+ foreach (var stop in Stops)
+ {
+ canvasGradientStops.Add(new CanvasGradientStop()
+ {
+ Color = stop.Color,
+ Position = (float)stop.Offset
+ });
+ }
+
+ CanvasBrush = new CanvasRadialGradientBrush(
+ CompositionGenerator.Instance.Device,
+ canvasGradientStops.ToArray(),
+ EdgeBehavior,
+ AlphaMode,
+ PreInterpolationSpace,
+ PostInterpolationSpace,
+ BufferPrecision)
+ {
+ Center = Center.ToVector2(),
+ RadiusX = (float)RadiusX,
+ RadiusY = (float)RadiusY,
+ OriginOffset = OriginOffset.ToVector2(),
+ Opacity = (float)Opacity,
+ Transform = Transform.ToMatrix3x2()
+ };
+
+ base.OnUpdated();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Brushes/SolidColorCanvasBrush.cs b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/SolidColorCanvasBrush.cs
new file mode 100644
index 00000000000..54a39a97a65
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Brushes/SolidColorCanvasBrush.cs
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Graphics.Canvas.Brushes;
+using Windows.UI;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media
+{
+ ///
+ /// XAML equivalent of Win2d's CanvasSolidColorBrush class which paints in solid color.
+ ///
+ public class SolidColorCanvasBrush : RenderCanvasBrushBase
+ {
+ ///
+ /// Color Dependency Property
+ ///
+ public static readonly DependencyProperty ColorProperty = DependencyProperty.Register(
+ "Color",
+ typeof(Color),
+ typeof(SolidColorCanvasBrush),
+ new PropertyMetadata(Colors.Transparent, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the color of the brush.
+ ///
+ public Color Color
+ {
+ get => (Color)GetValue(ColorProperty);
+ set => SetValue(ColorProperty, value);
+ }
+
+ ///
+ /// Method that is called whenever the dependency properties of the Brush changes
+ ///
+ /// The object whose property has changed
+ /// Event arguments
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var brush = (SolidColorCanvasBrush)d;
+
+ // Recreate the canvas brush on any property change.
+ brush.OnUpdated();
+ }
+
+ ///
+ protected override void OnUpdated()
+ {
+ CanvasBrush = new CanvasSolidColorBrush(CompositionGenerator.Instance.Device, Color);
+ base.OnUpdated();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasCircleGeometry.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasCircleGeometry.cs
new file mode 100644
index 00000000000..cf6d773dcf9
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasCircleGeometry.cs
@@ -0,0 +1,94 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Numerics;
+using Microsoft.Graphics.Canvas.Geometry;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
+{
+ ///
+ /// Represents a circle geometry object with the specified extents.
+ ///
+ public class CanvasCircleGeometry : CanvasCoreGeometry
+ {
+ ///
+ /// CenterX Dependency Property
+ ///
+ public static readonly DependencyProperty CenterXProperty = DependencyProperty.Register(
+ "CenterX",
+ typeof(double),
+ typeof(CanvasCircleGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the the x coordinate of the center.
+ ///
+ public double CenterX
+ {
+ get => (double)GetValue(CenterXProperty);
+ set => SetValue(CenterXProperty, value);
+ }
+
+ ///
+ /// CenterY Dependency Property
+ ///
+ public static readonly DependencyProperty CenterYProperty = DependencyProperty.Register(
+ "CenterY",
+ typeof(double),
+ typeof(CanvasCircleGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the y coordinate of the Center.
+ ///
+ public double CenterY
+ {
+ get => (double)GetValue(CenterYProperty);
+ set => SetValue(CenterYProperty, value);
+ }
+
+ ///
+ /// Radius Dependency Property
+ ///
+ public static readonly DependencyProperty RadiusProperty = DependencyProperty.Register(
+ "Radius",
+ typeof(double),
+ typeof(CanvasCircleGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the radius value of the .
+ ///
+ public double Radius
+ {
+ get => (double)GetValue(RadiusProperty);
+ set => SetValue(RadiusProperty, value);
+ }
+
+ ///
+ /// Method that is called whenever the dependency properties of the Brush .
+ ///
+ /// The object whose property has changed
+ /// Event arguments
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometry = (CanvasCircleGeometry)d;
+
+ // Recreate the geometry on any property change.
+ geometry.OnUpdateGeometry();
+ }
+
+ ///
+ protected override void OnUpdateGeometry()
+ {
+ Geometry?.Dispose();
+
+ var center = new Vector2((float)CenterX, (float)CenterY);
+ Geometry = CanvasGeometry.CreateCircle(CompositionGenerator.Instance.Device, center, (float)Radius);
+
+ base.OnUpdateGeometry();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasCombinedGeometry.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasCombinedGeometry.cs
new file mode 100644
index 00000000000..bdf9308ccc0
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasCombinedGeometry.cs
@@ -0,0 +1,197 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Numerics;
+using Microsoft.Graphics.Canvas.Geometry;
+using Microsoft.Toolkit.Uwp.Helpers;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
+{
+ ///
+ /// Represents a Geometry defined by the combination of two objects.
+ ///
+ public class CanvasCombinedGeometry : CanvasCoreGeometry
+ {
+ private WeakEventListener _geometry1UpdateListener;
+ private WeakEventListener _geometry2UpdateListener;
+
+ ///
+ /// Geometry1 Dependency Property
+ ///
+ public static readonly DependencyProperty Geometry1Property = DependencyProperty.Register(
+ "Geometry1",
+ typeof(CanvasCoreGeometry),
+ typeof(CanvasCombinedGeometry),
+ new PropertyMetadata(null, OnGeometry1Changed));
+
+ ///
+ /// Gets or sets the first object to combine.
+ ///
+ public CanvasCoreGeometry Geometry1
+ {
+ get => (CanvasCoreGeometry)GetValue(Geometry1Property);
+ set => SetValue(Geometry1Property, value);
+ }
+
+ ///
+ /// Handles changes to the Geometry1 property.
+ ///
+ /// .
+ /// DependencyProperty changed event arguments.
+ private static void OnGeometry1Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var combinedGeometry = (CanvasCombinedGeometry)d;
+ combinedGeometry.OnGeometry1Changed();
+ }
+
+ ///
+ /// Instance handler for the changes to the Geometry1 dependency property.
+ ///
+ private void OnGeometry1Changed()
+ {
+ _geometry1UpdateListener?.Detach();
+ _geometry1UpdateListener = null;
+
+ if (Geometry1 != null)
+ {
+ _geometry1UpdateListener = new WeakEventListener(Geometry1)
+ {
+ OnEventAction = async (instance, source, args) =>
+ {
+ await Window.Current.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ OnUpdateGeometry();
+ });
+ }
+ };
+
+ Geometry1.Updated += _geometry1UpdateListener.OnEvent;
+
+ OnUpdateGeometry();
+ }
+ }
+
+ ///
+ /// Geometry2 Dependency Property
+ ///
+ public static readonly DependencyProperty Geometry2Property = DependencyProperty.Register(
+ "Geometry2",
+ typeof(CanvasCoreGeometry),
+ typeof(CanvasCombinedGeometry),
+ new PropertyMetadata(null, OnGeometry2Changed));
+
+ ///
+ /// Gets or sets the second to combine.
+ ///
+ public CanvasCoreGeometry Geometry2
+ {
+ get => (CanvasCoreGeometry)GetValue(Geometry2Property);
+ set => SetValue(Geometry2Property, value);
+ }
+
+ ///
+ /// Handles changes to the Geometry2 property.
+ ///
+ /// .
+ /// DependencyProperty changed event arguments.
+ private static void OnGeometry2Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var combinedGeometry = (CanvasCombinedGeometry)d;
+ combinedGeometry.OnGeometry2Changed();
+ }
+
+ ///
+ /// Instance handler for the changes to the Geometry2 dependency property.
+ ///
+ private void OnGeometry2Changed()
+ {
+ _geometry2UpdateListener?.Detach();
+ _geometry2UpdateListener = null;
+
+ if (Geometry2 != null)
+ {
+ _geometry2UpdateListener = new WeakEventListener(Geometry2)
+ {
+ OnEventAction = async (instance, source, args) =>
+ {
+ await Window.Current.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ OnUpdateGeometry();
+ });
+ }
+ };
+
+ Geometry2.Updated += _geometry2UpdateListener.OnEvent;
+
+ OnUpdateGeometry();
+ }
+ }
+
+ ///
+ /// Transform Dependency Property
+ ///
+ public static readonly DependencyProperty TransformProperty = DependencyProperty.Register(
+ "Transform",
+ typeof(MatrixTransform),
+ typeof(CanvasCombinedGeometry),
+ new PropertyMetadata(Matrix3x2.Identity.ToMatrixTransform(), OnPropertyChanged));
+
+ ///
+ /// Gets or sets the MatrixTransform to be applied to Geometry2 before combining with Geometry1.
+ ///
+ public MatrixTransform Transform
+ {
+ get => (MatrixTransform)GetValue(TransformProperty);
+ set => SetValue(TransformProperty, value);
+ }
+
+ ///
+ /// GeometryCombineMode Dependency Property
+ ///
+ public static readonly DependencyProperty GeometryCombineModeProperty = DependencyProperty.Register(
+ "GeometryCombineMode",
+ typeof(CanvasGeometryCombine),
+ typeof(CanvasCombinedGeometry),
+ new PropertyMetadata(CanvasGeometryCombine.Union, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the method by which the geometries specified by and are meant to be combined.
+ ///
+ public CanvasGeometryCombine GeometryCombineMode
+ {
+ get => (CanvasGeometryCombine)GetValue(GeometryCombineModeProperty);
+ set => SetValue(GeometryCombineModeProperty, value);
+ }
+
+ ///
+ /// Method that is called whenever the dependency properties of the Brush changes
+ ///
+ /// The object whose property has changed
+ /// Event arguments
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometry = (CanvasCombinedGeometry)d;
+
+ // Recreate the geometry on any property change.
+ geometry.OnUpdateGeometry();
+ }
+
+ ///
+ protected override void OnUpdateGeometry()
+ {
+ if (Geometry1?.Geometry == null || Geometry2?.Geometry == null)
+ {
+ Geometry = null;
+ return;
+ }
+
+ Geometry = Geometry1.Geometry.CombineWith(Geometry2.Geometry, Transform.ToMatrix3x2(), GeometryCombineMode);
+
+ RaiseUpdatedEvent();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasCoreGeometry.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasCoreGeometry.cs
new file mode 100644
index 00000000000..788e30b7ab7
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasCoreGeometry.cs
@@ -0,0 +1,109 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using Microsoft.Graphics.Canvas.Geometry;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
+{
+ ///
+ /// Provides a base class for objects that define geometric shapes using .
+ ///
+ public abstract class CanvasCoreGeometry : DependencyObject, ICanvasPathGeometry, IDisposable
+ {
+ ///
+ /// Event to notify that the properties of this class have been updated.
+ ///
+ public event EventHandler Updated;
+
+ private bool _disposedValue;
+
+ ///
+ /// Geometry Dependency Property
+ ///
+ public static readonly DependencyProperty GeometryProperty = DependencyProperty.Register(
+ "Geometry",
+ typeof(CanvasGeometry),
+ typeof(CanvasCoreGeometry),
+ new PropertyMetadata(null, OnGeometryChanged));
+
+ ///
+ /// Gets or sets the associated Win2d CanvasGeometry.
+ ///
+ public CanvasGeometry Geometry
+ {
+ get => (CanvasGeometry)GetValue(GeometryProperty);
+ protected set => SetValue(GeometryProperty, value);
+ }
+
+ ///
+ /// Handles changes to the Geometry property.
+ ///
+ /// CanvasCoreGeometry.
+ /// DependencyProperty changed event arguments.
+ private static void OnGeometryChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var coreGeometry = (CanvasCoreGeometry)d;
+ coreGeometry.OnGeometryChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the Geometry dependency property.
+ ///
+ protected virtual void OnGeometryChanged()
+ {
+ }
+
+ ///
+ /// Method to be called when any of the parameters affecting the Geometry is updated.
+ ///
+ protected virtual void OnUpdateGeometry()
+ {
+ Updated?.Invoke(this, null);
+ }
+
+ ///
+ /// Raises the Updated event.
+ ///
+ protected void RaiseUpdatedEvent()
+ {
+ Updated?.Invoke(this, null);
+ }
+
+ ///
+ /// Call this method to redraw its Geometry (usually when event is raised).
+ ///
+ public void Refresh()
+ {
+ OnUpdateGeometry();
+ }
+
+ ///
+ /// Disposes the resources used by the CanvasCoreGeometry and its derivatives
+ ///
+ /// Flag to indicate if we are disposing the managed objects.
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposedValue)
+ {
+ if (disposing)
+ {
+ Geometry.Dispose();
+ }
+
+ _disposedValue = true;
+ }
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void Dispose()
+ {
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasDrawingSessionExtensions.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasDrawingSessionExtensions.cs
index bd297f71f89..c4f3a607916 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasDrawingSessionExtensions.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasDrawingSessionExtensions.cs
@@ -304,4 +304,4 @@ public static void FillSquircle(this CanvasDrawingSession session, float x, floa
session.FillGeometry(geometry, offset, brush);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasEllipseGeometry.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasEllipseGeometry.cs
new file mode 100644
index 00000000000..15d6cda6ca0
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasEllipseGeometry.cs
@@ -0,0 +1,109 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Numerics;
+using Microsoft.Graphics.Canvas.Geometry;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
+{
+ ///
+ /// Represents an Ellipse geometry object with the specified extents.
+ ///
+ public class CanvasEllipseGeometry : CanvasCoreGeometry
+ {
+ ///
+ /// CenterX Dependency Property
+ ///
+ public static readonly DependencyProperty CenterXProperty = DependencyProperty.Register(
+ "CenterX",
+ typeof(double),
+ typeof(CanvasEllipseGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the coordinate of the center of the on the x-axis.
+ ///
+ public double CenterX
+ {
+ get => (double)GetValue(CenterXProperty);
+ set => SetValue(CenterXProperty, value);
+ }
+
+ ///
+ /// CenterY Dependency Property
+ ///
+ public static readonly DependencyProperty CenterYProperty = DependencyProperty.Register(
+ "CenterY",
+ typeof(double),
+ typeof(CanvasEllipseGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the coordinate of the center of the on the y-axis.
+ ///
+ public double CenterY
+ {
+ get => (double)GetValue(CenterYProperty);
+ set => SetValue(CenterYProperty, value);
+ }
+
+ ///
+ /// RadiusX Dependency Property
+ ///
+ public static readonly DependencyProperty RadiusXProperty = DependencyProperty.Register(
+ "RadiusX",
+ typeof(float),
+ typeof(CanvasEllipseGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the x-radius value of the .
+ ///
+ public float RadiusX
+ {
+ get => (float)GetValue(RadiusXProperty);
+ set => SetValue(RadiusXProperty, value);
+ }
+
+ ///
+ /// RadiusY Dependency Property
+ ///
+ public static readonly DependencyProperty RadiusYProperty = DependencyProperty.Register(
+ "RadiusY",
+ typeof(float),
+ typeof(CanvasEllipseGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the y-radius value of the .
+ ///
+ public float RadiusY
+ {
+ get => (float)GetValue(RadiusYProperty);
+ set => SetValue(RadiusYProperty, value);
+ }
+
+ ///
+ /// Method that is called whenever the dependency properties of the Brush changes
+ ///
+ /// The object whose property has changed
+ /// Event arguments
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometry = (CanvasEllipseGeometry)d;
+
+ // Recreate the geometry on any property change.
+ geometry.OnUpdateGeometry();
+ }
+
+ ///
+ protected override void OnUpdateGeometry()
+ {
+ Geometry = CanvasGeometry.CreateEllipse(CompositionGenerator.Instance.Device, new Vector2((float)CenterX, (float)CenterY), RadiusX, RadiusY);
+
+ RaiseUpdatedEvent();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasPathBuilderExtensions.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasPathBuilderExtensions.cs
index d9878de510d..4bce7681c9b 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasPathBuilderExtensions.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasPathBuilderExtensions.cs
@@ -7,7 +7,6 @@
using System.Linq;
using System.Numerics;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
@@ -459,4 +458,4 @@ public static CanvasPathBuilder BuildPathWithLines(this CanvasPathBuilder builde
return BuildPathWithLines(builder, canvasFigureLoop, vectors);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasPathGeometry.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasPathGeometry.cs
index 37a717eb359..48a8318212f 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasPathGeometry.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasPathGeometry.cs
@@ -2,37 +2,103 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#pragma warning disable CS0419 // Ambiguous reference in cref attribute
+
+using System;
using System.Numerics;
-using System.Runtime.CompilerServices;
-using System.Text;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Parsers;
using Windows.UI;
+using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
- /// Helper Class for creating Win2d objects.
+ /// Represents a complex vector-based shape geometry that may be composed of arcs, curves, ellipses, lines, rectangles, rounded rectangles, squircles.
+ /// Also provides several helper methods to create Win2d objects.
///
- public static class CanvasPathGeometry
+ public class CanvasPathGeometry : CanvasCoreGeometry
{
///
- /// Parses the Path data string and converts it to CanvasGeometry.
+ /// Data Dependency Property
+ ///
+ public static readonly DependencyProperty DataProperty = DependencyProperty.Register(
+ "Data",
+ typeof(string),
+ typeof(CanvasPathGeometry),
+ new PropertyMetadata(string.Empty, OnDataChanged));
+
+ ///
+ /// Gets or sets the path data for the associated Win2d defined in the Win2d Path Mini Language.
+ ///
+ public string Data
+ {
+ get => (string)GetValue(DataProperty);
+ set => SetValue(DataProperty, value);
+ }
+
+ ///
+ /// Handles changes to the Data property.
+ ///
+ /// CanvasPathGeometry.
+ /// DependencyProperty changed event arguments.
+ private static void OnDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var pathGeometry = (CanvasPathGeometry)d;
+ pathGeometry.OnDataChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the Data dependency property.
+ ///
+ protected virtual void OnDataChanged()
+ {
+ OnUpdateGeometry();
+ }
+
+ ///
+ /// Initializes a new instance of the class.
///
- /// Path data
+ public CanvasPathGeometry()
+ {
+ this.Geometry = null;
+ }
+
+ ///
+ protected override void OnUpdateGeometry()
+ {
+ // Dispose previous CanvasGeometry (if any)
+ Geometry?.Dispose();
+ Geometry = null;
+
+ try
+ {
+ Geometry = CreateGeometry(CompositionGenerator.Instance.Device, Data);
+ }
+ catch (Exception)
+ {
+ Geometry = null;
+ }
+
+ RaiseUpdatedEvent();
+ }
+
+ ///
+ /// Parses the Path data string and converts it to .
+ ///
+ /// Path data.
///
public static CanvasGeometry CreateGeometry(string pathData)
{
- return CreateGeometry(null, pathData);
+ return CreateGeometry(CompositionGenerator.Instance.Device, pathData);
}
///
- /// Parses the Path data string and converts it to CanvasGeometry.
+ /// Parses the Path data string and converts it to .
///
- ///
- /// Path data
+ /// .
+ /// Path data.
///
public static CanvasGeometry CreateGeometry(ICanvasResourceCreator resourceCreator, string pathData)
{
@@ -46,13 +112,13 @@ public static CanvasGeometry CreateGeometry(ICanvasResourceCreator resourceCreat
///
/// Creates a Squircle geometry with the specified extents.
///
- /// Resource creator
- /// X offset of the TopLeft corner of the Squircle
- /// Y offset of the TopLeft corner of the Squircle
- /// Width of the Squircle
- /// Height of the Squircle
- /// Corner Radius on the x-axis
- /// Corner Radius on the y-axis
+ /// Resource creator.
+ /// X offset of the TopLeft corner of the Squircle.
+ /// Y offset of the TopLeft corner of the Squircle.
+ /// Width of the Squircle.
+ /// Height of the Squircle.
+ /// Corner Radius on the x-axis.
+ /// Corner Radius on the y-axis.
///
public static CanvasGeometry CreateSquircle(ICanvasResourceCreator resourceCreator, float x, float y, float width, float height, float radiusX, float radiusY)
{
@@ -62,10 +128,10 @@ public static CanvasGeometry CreateSquircle(ICanvasResourceCreator resourceCreat
}
///
- /// Parses the given Brush data string and converts it to ICanvasBrush.
+ /// Parses the given Brush data string and converts it to .
///
- /// ICanvasResourceCreator
- /// Brush data in string format
+ /// ICanvasResourceCreator.
+ /// Brush data in string format.
///
public static ICanvasBrush CreateBrush(ICanvasResourceCreator resourceCreator, string brushData)
{
@@ -76,10 +142,10 @@ public static ICanvasBrush CreateBrush(ICanvasResourceCreator resourceCreator, s
}
///
- /// Parses the given Stroke data string and converts it to ICanvasStroke.
+ /// Parses the given Stroke data string and converts it to .
///
- /// ICanvasResourceCreator
- /// Stroke data in string format
+ /// .
+ /// Stroke data in string format.
///
public static ICanvasStroke CreateStroke(ICanvasResourceCreator resourceCreator, string strokeData)
{
@@ -90,10 +156,10 @@ public static ICanvasStroke CreateStroke(ICanvasResourceCreator resourceCreator,
}
///
- /// Parses the give CanvasStrokeStyle data string and converts it to CanvasStrokeStyle.
+ /// Parses the give CanvasStrokeStyle data string and converts it to .
///
- /// CanvasStrokeStyle data in string format
- /// object
+ /// data in string format.
+ ///
public static CanvasStrokeStyle CreateStrokeStyle(string styleData)
{
using (new CultureShield("en-US"))
@@ -103,14 +169,14 @@ public static CanvasStrokeStyle CreateStrokeStyle(string styleData)
}
///
- /// Converts the color string in Hexadecimal or HDR color format to the corresponding Color object.
+ /// Converts the color string in Hexadecimal or HDR color format to the corresponding object.
/// The hexadecimal color string should be in #RRGGBB or #AARRGGBB format.
/// The '#' character is optional.
/// The HDR color string should be in R G B A format.
/// (R, G, B & A should have value in the range between 0 and 1, inclusive)
///
- /// Color string in Hexadecimal or HDR format
- /// Color
+ /// Color string in Hexadecimal or HDR format.
+ ///
public static Color CreateColor(string colorString)
{
using (new CultureShield("en-US"))
@@ -120,15 +186,15 @@ public static Color CreateColor(string colorString)
}
///
- /// Converts a Vector4 High Dynamic Range Color to Color object.
+ /// Converts a Vector4 High Dynamic Range Color to object.
/// Negative components of the Vector4 will be sanitized by taking the absolute
/// value of the component. The HDR Color components should have value in
/// the range between 0 and 1, inclusive. If they are more than 1, they
/// will be clamped at 1.
/// Vector4's X, Y, Z, W components match to Color's R, G, B, A components respectively.
///
- /// High Dynamic Range Color
- /// Color
+ /// High Dynamic Range Color.
+ ///
public static Color CreateColor(Vector4 hdrColor)
{
using (new CultureShield("en-US"))
@@ -137,4 +203,6 @@ public static Color CreateColor(Vector4 hdrColor)
}
}
}
-}
\ No newline at end of file
+}
+
+#pragma warning restore CS0419 // Ambiguous reference in cref attribute
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasRectangleGeometry.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasRectangleGeometry.cs
new file mode 100644
index 00000000000..c249ea4c654
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasRectangleGeometry.cs
@@ -0,0 +1,108 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Graphics.Canvas.Geometry;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
+{
+ ///
+ /// Represents a rectangular geometry object with the specified extents.
+ ///
+ public class CanvasRectangleGeometry : CanvasCoreGeometry
+ {
+ ///
+ /// X Dependency Property
+ ///
+ public static readonly DependencyProperty XProperty = DependencyProperty.Register(
+ "X",
+ typeof(double),
+ typeof(CanvasRectangleGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the x-coordinate of the upper-left corner of the rectangle geometry.
+ ///
+ public double X
+ {
+ get => (double)GetValue(XProperty);
+ set => SetValue(XProperty, value);
+ }
+
+ ///
+ /// Y Dependency Property
+ ///
+ public static readonly DependencyProperty YProperty = DependencyProperty.Register(
+ "Y",
+ typeof(double),
+ typeof(CanvasRectangleGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the y-coordinate of the upper-left corner of the rectangle geometry.
+ ///
+ public double Y
+ {
+ get => (double)GetValue(YProperty);
+ set => SetValue(YProperty, value);
+ }
+
+ ///
+ /// Width Dependency Property
+ ///
+ public static readonly DependencyProperty WidthProperty = DependencyProperty.Register(
+ "Width",
+ typeof(double),
+ typeof(CanvasRectangleGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the width of the rectangle geometry.
+ ///
+ public double Width
+ {
+ get => (double)GetValue(WidthProperty);
+ set => SetValue(WidthProperty, value);
+ }
+
+ ///
+ /// Height Dependency Property
+ ///
+ public static readonly DependencyProperty HeightProperty = DependencyProperty.Register(
+ "Height",
+ typeof(double),
+ typeof(CanvasRectangleGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the height of the rectangle geometry.
+ ///
+ public double Height
+ {
+ get => (double)GetValue(HeightProperty);
+ set => SetValue(HeightProperty, value);
+ }
+
+ ///
+ /// Method that is called whenever the dependency properties of the Brush changes
+ ///
+ /// The object whose property has changed
+ /// Event arguments
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometry = (CanvasRectangleGeometry)d;
+
+ // Recreate the geometry on any property change.
+ geometry.OnUpdateGeometry();
+ }
+
+ ///
+ protected override void OnUpdateGeometry()
+ {
+ Geometry = CanvasGeometry.CreateRectangle(CompositionGenerator.Instance.Device, (float)X, (float)Y, (float)Width, (float)Height);
+
+ RaiseUpdatedEvent();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasRoundedRectangleGeometry.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasRoundedRectangleGeometry.cs
new file mode 100644
index 00000000000..417dc487d23
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasRoundedRectangleGeometry.cs
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Graphics.Canvas.Geometry;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
+{
+ ///
+ /// Represents a rounded rectangle geometry object with the specified extents.
+ ///
+ public class CanvasRoundedRectangleGeometry : CanvasRectangleGeometry
+ {
+ ///
+ /// RadiusX Dependency Property
+ ///
+ public static readonly DependencyProperty RadiusXProperty = DependencyProperty.Register(
+ "RadiusX",
+ typeof(double),
+ typeof(CanvasRoundedRectangleGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the radius of the corners in the x-axis.
+ ///
+ public double RadiusX
+ {
+ get => (double)GetValue(RadiusXProperty);
+ set => SetValue(RadiusXProperty, value);
+ }
+
+ ///
+ /// RadiusY Dependency Property
+ ///
+ public static readonly DependencyProperty RadiusYProperty = DependencyProperty.Register(
+ "RadiusY",
+ typeof(double),
+ typeof(CanvasRoundedRectangleGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the radius of the corners in the x-axis.
+ ///
+ public double RadiusY
+ {
+ get => (double)GetValue(RadiusYProperty);
+ set => SetValue(RadiusYProperty, value);
+ }
+
+ ///
+ /// Method that is called whenever the dependency properties of the Brush changes
+ ///
+ /// The object whose property has changed
+ /// Event arguments
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometry = (CanvasRoundedRectangleGeometry)d;
+
+ // Recreate the geometry on any property change.
+ geometry.OnUpdateGeometry();
+ }
+
+ ///
+ protected override void OnUpdateGeometry()
+ {
+ Geometry = CanvasGeometry.CreateRoundedRectangle(CompositionGenerator.Instance.Device, (float)X, (float)Y, (float)Width, (float)Height, (float)RadiusX, (float)RadiusY);
+
+ RaiseUpdatedEvent();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasSquircleGeometry.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasSquircleGeometry.cs
new file mode 100644
index 00000000000..f2dc25a9c36
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasSquircleGeometry.cs
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
+{
+ ///
+ /// Represents a Squircle geometry object with the specified extents.
+ ///
+ public class CanvasSquircleGeometry : CanvasRectangleGeometry
+ {
+ ///
+ /// RadiusX Dependency Property
+ ///
+ public static readonly DependencyProperty RadiusXProperty = DependencyProperty.Register(
+ "RadiusX",
+ typeof(double),
+ typeof(CanvasSquircleGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the radius of the corners in the x-axis.
+ ///
+ public double RadiusX
+ {
+ get => (double)GetValue(RadiusXProperty);
+ set => SetValue(RadiusXProperty, value);
+ }
+
+ ///
+ /// RadiusY Dependency Property
+ ///
+ public static readonly DependencyProperty RadiusYProperty = DependencyProperty.Register(
+ "RadiusY",
+ typeof(double),
+ typeof(CanvasSquircleGeometry),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the radius of the corners in the x-axis.
+ ///
+ public double RadiusY
+ {
+ get => (double)GetValue(RadiusYProperty);
+ set => SetValue(RadiusYProperty, value);
+ }
+
+ ///
+ /// Method that is called whenever the dependency properties of the Brush changes
+ ///
+ /// The object whose property has changed
+ /// Event arguments
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var geometry = (CanvasSquircleGeometry)d;
+
+ // Recreate the geometry on any property change.
+ geometry.OnUpdateGeometry();
+ }
+
+ ///
+ protected override void OnUpdateGeometry()
+ {
+ Geometry = CanvasPathGeometry.CreateSquircle(CompositionGenerator.Instance.Device, (float)X, (float)Y, (float)Width, (float)Height, (float)RadiusX, (float)RadiusY);
+
+ RaiseUpdatedEvent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasStroke.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasStroke.cs
index 8704bbb3be4..2b2655cd39b 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasStroke.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CanvasStroke.cs
@@ -40,6 +40,16 @@ public Matrix3x2 Transform
set => SetTransform(value);
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public CanvasStroke()
+ {
+ Brush = null;
+ Width = 0;
+ Style = new CanvasStrokeStyle();
+ }
+
///
/// Initializes a new instance of the class.
///
@@ -109,4 +119,4 @@ private Matrix3x2 GetTransform()
return Brush?.Transform ?? Matrix3x2.Identity;
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CompositorGeometryExtensions.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CompositorGeometryExtensions.cs
index 1f6f0f8f518..c06592cbbb9 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CompositorGeometryExtensions.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CompositorGeometryExtensions.cs
@@ -93,4 +93,4 @@ public static CompositionGeometricClip CreateGeometricClip(this Compositor compo
return compositor.CreateGeometricClip(geometry);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/CanvasRoundRect.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/CanvasRoundRect.cs
index 5dae1483a6f..44a1bc2b3a5 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/CanvasRoundRect.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/CanvasRoundRect.cs
@@ -5,7 +5,7 @@
using System;
using System.Numerics;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Structure which encapsulates the details of each of the core points of the path of the rounded rectangle which is calculated based on
@@ -277,4 +277,4 @@ private void ComputeCoordinates(float originX, float originY)
TopLeftY = topLeftY + originY;
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/GeometryTypeDefinitions.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/GeometryTypeDefinitions.cs
index c50c8625f98..c7d4e63b36c 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/GeometryTypeDefinitions.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/GeometryTypeDefinitions.cs
@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Enum for the various PathFigures.
@@ -56,4 +56,4 @@ internal enum GradientStopAttributeType
MainHdr,
AdditionalHdr
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/PathElementFactory.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/PathElementFactory.cs
index 16c911f1f3a..aadd11a4311 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/PathElementFactory.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/PathElementFactory.cs
@@ -4,9 +4,8 @@
using System;
using System.Text.RegularExpressions;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Factory class to instantiate various PathElements.
@@ -154,4 +153,4 @@ private static ICanvasPathElement CreatePathElement(PathElementType elementType)
};
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/RegexFactory.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/RegexFactory.cs
index 8ee81f4bad4..92406b0611d 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/RegexFactory.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Core/RegexFactory.cs
@@ -8,7 +8,7 @@
[assembly: InternalsVisibleTo("UnitTests.UWP")]
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Contains all the Regular Expressions which are used for parsing the Win2d Path Mini Language.
@@ -599,4 +599,4 @@ internal static Regex GetAttributesRegex(GradientStopAttributeType gsAttrType)
return GradientStopAttributeRegexes[gsAttrType];
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CultureShield.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CultureShield.cs
index 763e34019bf..702cd9d2c51 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CultureShield.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/CultureShield.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using System.Globalization;
namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
@@ -56,4 +55,4 @@ public void Dispose()
CultureInfo.CurrentCulture = _prevCulture;
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/AbstractCanvasBrushElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/AbstractCanvasBrushElement.cs
index 46d1fd086d3..f38c958faff 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/AbstractCanvasBrushElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/AbstractCanvasBrushElement.cs
@@ -5,9 +5,8 @@
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Brush
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Abstract base class for all Brush Elements
@@ -69,4 +68,4 @@ public virtual void Initialize(Capture capture)
/// Match object
protected abstract void GetAttributes(Match match);
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/ICanvasBrushElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/ICanvasBrushElement.cs
index 75c34abcb8f..f51a2633df5 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/ICanvasBrushElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/ICanvasBrushElement.cs
@@ -6,7 +6,7 @@
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Brush
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Interface for a Brush Element
@@ -37,4 +37,4 @@ internal interface ICanvasBrushElement
/// ICanvasBrush
ICanvasBrush CreateBrush(ICanvasResourceCreator resourceCreator);
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/LinearGradientBrushElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/LinearGradientBrushElement.cs
index b27fe460aff..00249484980 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/LinearGradientBrushElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/LinearGradientBrushElement.cs
@@ -9,11 +9,9 @@
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Parsers;
using Windows.UI;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Brush
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Represents a CanvasLinearGradientBrush with GradientStops
@@ -203,4 +201,4 @@ protected override void GetAttributes(Match match)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/LinearGradientHdrBrushElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/LinearGradientHdrBrushElement.cs
index 49a1eef4553..19c3d98a1f2 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/LinearGradientHdrBrushElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/LinearGradientHdrBrushElement.cs
@@ -9,9 +9,8 @@
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Brush
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Represents a CanvasLinearGradientBrush with GradientStopHdrs
@@ -209,4 +208,4 @@ protected override void GetAttributes(Match match)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/RadialGradientBrushElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/RadialGradientBrushElement.cs
index 728d0782177..190e305645d 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/RadialGradientBrushElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/RadialGradientBrushElement.cs
@@ -9,11 +9,9 @@
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Parsers;
using Windows.UI;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Brush
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Represents a CanvasRadialGradientBrush with GradientStops
@@ -227,4 +225,4 @@ protected override void GetAttributes(Match match)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/RadialGradientHdrBrushElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/RadialGradientHdrBrushElement.cs
index 8ee430428e6..0b947f155ec 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/RadialGradientHdrBrushElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/RadialGradientHdrBrushElement.cs
@@ -9,9 +9,8 @@
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Brush
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Represents a CanvasRadialGradientBrush with GradientStopHdrs
@@ -234,4 +233,4 @@ protected override void GetAttributes(Match match)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/SolidColorBrushElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/SolidColorBrushElement.cs
index 078b4523836..feeedc9fa6f 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/SolidColorBrushElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Brush/SolidColorBrushElement.cs
@@ -5,11 +5,9 @@
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Parsers;
using Windows.UI;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Brush
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Represents a CanvasSolidColorBrush
@@ -70,4 +68,4 @@ protected override void GetAttributes(Match match)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/AbstractPathElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/AbstractPathElement.cs
index 0a1f9bb6de6..02951aa6836 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/AbstractPathElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/AbstractPathElement.cs
@@ -5,9 +5,8 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Abstract base class for all Path Elements
@@ -104,4 +103,4 @@ public virtual void InitializeAdditional(Capture capture, int index, bool isRela
/// Match object
protected abstract void GetAttributes(Match match);
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/ArcElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/ArcElement.cs
index 984aa224591..ef9f4cc8951 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/ArcElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/ArcElement.cs
@@ -6,9 +6,8 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the Arc Element in a Path Geometry
@@ -98,4 +97,4 @@ protected override void GetAttributes(Match match)
float.TryParse(match.Groups["Y"].Value, out _y);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasEllipseFigure.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasEllipseFigure.cs
index 9868ae2eddc..a4f769f3414 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasEllipseFigure.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasEllipseFigure.cs
@@ -6,9 +6,8 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the Ellipse Figure in a Path Geometry
@@ -80,4 +79,4 @@ protected override void GetAttributes(Match match)
float.TryParse(match.Groups["Y"].Value, out _y);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasPathFigure.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasPathFigure.cs
index 8c38c6a5a54..40b63b19b0d 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasPathFigure.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasPathFigure.cs
@@ -8,9 +8,8 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class which contains a collection of ICanvasPathElements
@@ -133,4 +132,4 @@ protected override void GetAttributes(Match match)
// Do nothing
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasPolygonFigure.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasPolygonFigure.cs
index 4bf4cc8184f..c448d49688c 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasPolygonFigure.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasPolygonFigure.cs
@@ -6,9 +6,9 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
+using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the Polygon Figure in a Path Geometry
@@ -82,4 +82,4 @@ protected override void GetAttributes(Match match)
float.TryParse(match.Groups["Y"].Value, out _y);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasRectangleFigure.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasRectangleFigure.cs
index 883ec7f847e..c45569e3f32 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasRectangleFigure.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasRectangleFigure.cs
@@ -6,9 +6,9 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
+using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the Rectangle Figure in a Path Geometry
@@ -87,4 +87,4 @@ protected override void GetAttributes(Match match)
_height = Math.Abs(_height);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasRoundRectangleFigure.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasRoundRectangleFigure.cs
index 3a0d7a1193c..7e8e1e5b4ec 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasRoundRectangleFigure.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CanvasRoundRectangleFigure.cs
@@ -6,9 +6,9 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
+using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the RoundRectangle Figure in a Path Geometry
@@ -101,4 +101,4 @@ protected override void GetAttributes(Match match)
_radiusY = Math.Abs(_radiusY);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/ClosePathElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/ClosePathElement.cs
index e66c387e4cb..bcbf2fb938e 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/ClosePathElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/ClosePathElement.cs
@@ -5,9 +5,8 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the ClosePath command in a Path Geometry
@@ -98,4 +97,4 @@ protected override void GetAttributes(Match match)
// Do Nothing
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CubicBezierElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CubicBezierElement.cs
index d4113e8f76b..708520b95eb 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CubicBezierElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/CubicBezierElement.cs
@@ -5,9 +5,8 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the Cubic Bezier Element in a Path Geometry
@@ -102,4 +101,4 @@ protected override void GetAttributes(Match match)
float.TryParse(match.Groups["Y"].Value, out _y);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/FillRuleElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/FillRuleElement.cs
index 6d7948bf4a1..40d7c332501 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/FillRuleElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/FillRuleElement.cs
@@ -7,7 +7,7 @@
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the Fill Rule Element in a Path Geometry
@@ -75,4 +75,4 @@ protected override void GetAttributes(Match match)
Enum.TryParse(match.Groups["FillValue"].Value, out _fillValue);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/HorizontalLineElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/HorizontalLineElement.cs
index bbd3201ff9f..4dec26cacb4 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/HorizontalLineElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/HorizontalLineElement.cs
@@ -5,9 +5,8 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the Horizontal Line Element in a Path Geometry
@@ -66,4 +65,4 @@ protected override void GetAttributes(Match match)
float.TryParse(match.Groups["X"].Value, out _x);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/ICanvasPathElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/ICanvasPathElement.cs
index 2bee7f24960..f9cfcd283fd 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/ICanvasPathElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/ICanvasPathElement.cs
@@ -3,11 +3,10 @@
// See the LICENSE file in the project root for more information.
using System.Numerics;
-using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Interface for a Path Element which serves
@@ -62,4 +61,4 @@ internal interface ICanvasPathElement
/// The current point on the path after the path element is added
Vector2 CreatePath(CanvasPathBuilder pathBuilder, Vector2 currentPoint, ref ICanvasPathElement lastElement);
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/LineElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/LineElement.cs
index 2f52bbce991..00e97dd3c09 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/LineElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/LineElement.cs
@@ -5,9 +5,8 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the Line Element in a Path Geometry
@@ -71,4 +70,4 @@ protected override void GetAttributes(Match match)
float.TryParse(match.Groups["Y"].Value, out _y);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/MoveToElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/MoveToElement.cs
index 73aa61b4571..64feb9d1721 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/MoveToElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/MoveToElement.cs
@@ -5,9 +5,8 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the MoveTo Command in a Path Geometry
@@ -84,4 +83,4 @@ protected override void GetAttributes(Match match)
float.TryParse(match.Groups["Y"].Value, out _y);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/QuadraticBezierElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/QuadraticBezierElement.cs
index 3dd5ce32bc8..46ea0a89915 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/QuadraticBezierElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/QuadraticBezierElement.cs
@@ -5,9 +5,8 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the Quadratic Bezier Element in a Path Geometry
@@ -94,4 +93,4 @@ protected override void GetAttributes(Match match)
float.TryParse(match.Groups["Y"].Value, out _y);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/SmoothCubicBezierElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/SmoothCubicBezierElement.cs
index d04112accae..1c16ec40fc5 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/SmoothCubicBezierElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/SmoothCubicBezierElement.cs
@@ -5,9 +5,9 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
+using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the Smooth Cubic Bezier Element in a Path Geometry
@@ -114,4 +114,4 @@ protected override void GetAttributes(Match match)
float.TryParse(match.Groups["Y"].Value, out _y);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/SmoothQuadraticBezierElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/SmoothQuadraticBezierElement.cs
index 538b2997b6f..3d61b4fba57 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/SmoothQuadraticBezierElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/SmoothQuadraticBezierElement.cs
@@ -5,9 +5,9 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
+using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the Smooth Quadratic Bezier Element in a Path Geometry
@@ -103,4 +103,4 @@ protected override void GetAttributes(Match match)
float.TryParse(match.Groups["Y"].Value, out _y);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/VerticalLineElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/VerticalLineElement.cs
index 538bc570556..ea3efa3b923 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/VerticalLineElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Path/VerticalLineElement.cs
@@ -5,9 +5,8 @@
using System.Numerics;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Class representing the Vertical Line Element in a Path Geometry
@@ -66,4 +65,4 @@ protected override void GetAttributes(Match match)
float.TryParse(match.Groups["Y"].Value, out _y);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/AbstractCanvasStrokeElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/AbstractCanvasStrokeElement.cs
index fa086874b9d..ff933b4b956 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/AbstractCanvasStrokeElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/AbstractCanvasStrokeElement.cs
@@ -4,9 +4,8 @@
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Stroke
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Abstract base class for Stroke Element.
@@ -62,4 +61,4 @@ protected virtual void Validate()
/// Match object
protected abstract void GetAttributes(Match match);
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/CanvasStrokeElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/CanvasStrokeElement.cs
index e526074af53..cc20c7ab27a 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/CanvasStrokeElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/CanvasStrokeElement.cs
@@ -5,11 +5,8 @@
using System;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Brush;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Parsers;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Stroke
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Represents a Stroke Element.
@@ -102,4 +99,4 @@ protected override void Validate()
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/CanvasStrokeStyleElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/CanvasStrokeStyleElement.cs
index 2780bc78732..aca39407bc2 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/CanvasStrokeStyleElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/CanvasStrokeStyleElement.cs
@@ -7,9 +7,8 @@
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Stroke
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Represents a CanvasStrokeStyle Element.
@@ -179,4 +178,4 @@ public void Initialize(Match match)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/ICanvasStrokeElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/ICanvasStrokeElement.cs
index 92029aaa7aa..c6d99fbd8d2 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/ICanvasStrokeElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/ICanvasStrokeElement.cs
@@ -5,7 +5,7 @@
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Stroke
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Interface for Stroke Element
@@ -34,4 +34,4 @@ internal interface ICanvasStrokeElement
/// ICanvasStroke
ICanvasStroke CreateStroke(ICanvasResourceCreator resourceCreator);
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/ICanvasStrokeStyleElement.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/ICanvasStrokeStyleElement.cs
index ec1fca39225..71e25056cc0 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/ICanvasStrokeStyleElement.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Elements/Stroke/ICanvasStrokeStyleElement.cs
@@ -5,7 +5,7 @@
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Stroke
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Interface for the CanvasStrokeStyle Element
@@ -33,4 +33,4 @@ internal interface ICanvasStrokeStyleElement
/// Match object
void Initialize(Match match);
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/ICanvasPathGeometry.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/ICanvasPathGeometry.cs
new file mode 100644
index 00000000000..899096159f5
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/ICanvasPathGeometry.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Graphics.Canvas.Geometry;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
+{
+ internal interface ICanvasPathGeometry
+ {
+ ///
+ /// Gets the associated .
+ ///
+ CanvasGeometry Geometry { get; }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/ICanvasStroke.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/ICanvasStroke.cs
index 9c9a0b7f41f..74be76ca1ab 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/ICanvasStroke.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/ICanvasStroke.cs
@@ -5,8 +5,9 @@
using System.Numerics;
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Geometry;
+using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
+namespace Microsoft.Toolkit.Uwp.UI.Media
{
///
/// Interface to represent the Stroke which can be used to render an outline on a .
@@ -33,4 +34,4 @@ public interface ICanvasStroke
///
Matrix3x2 Transform { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasBrushParser.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasBrushParser.cs
index 2a66728c9bc..b4d478c75ba 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasBrushParser.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasBrushParser.cs
@@ -6,10 +6,8 @@
using System.Runtime.CompilerServices;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Brush;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Parsers
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Parser for ICanvasBrush.
@@ -119,4 +117,4 @@ internal static ICanvasBrush Parse(ICanvasResourceCreator resourceCreator, strin
return brushElement.CreateBrush(resourceCreator);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasGeometryParser.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasGeometryParser.cs
index 76780d1e334..50c912e8757 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasGeometryParser.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasGeometryParser.cs
@@ -10,10 +10,8 @@
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Path;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Parsers
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Parser for CanvasGeometry.
@@ -66,7 +64,7 @@ internal static CanvasGeometry Parse(ICanvasResourceCreator resourceCreator, str
// Process the 'Additional' Group which contains just the attributes
figures.AddRange(from Capture capture in figureMatch.Groups["Additional"].Captures
- select PathElementFactory.CreateAdditionalPathFigure(type, capture, figureRootIndex + capture.Index, figure.IsRelative));
+ select PathElementFactory.CreateAdditionalPathFigure(type, capture, figureRootIndex + capture.Index, figure.IsRelative));
}
}
@@ -128,10 +126,11 @@ static void ThrowForInvalidCharacters(List pathFigures, stri
return CanvasGeometry.CreatePath(pathBuilder);
static void ThrowForZeroCount() => throw new ArgumentException("PATH_ERR000:Invalid Path data! No matching path data found!");
+
static void ThrowForNotOneCount() => throw new ArgumentException("PATH_ERR001:Multiple FillRule elements present in Path Data!\n" +
"There should be only one FillRule within the Path Data. " +
"You can either remove additional FillRule elements or split the Path Data " +
"into multiple Path Data and call the CanvasPathGeometry.CreateGeometry() method on each of them.");
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasStrokeParser.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasStrokeParser.cs
index e7c2fea9026..f9102b086a4 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasStrokeParser.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasStrokeParser.cs
@@ -5,10 +5,8 @@
using System;
using System.Runtime.CompilerServices;
using Microsoft.Graphics.Canvas;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Stroke;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Parsers
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Parser for CanvasStroke
@@ -95,4 +93,4 @@ internal static ICanvasStroke Parse(ICanvasResourceCreator resourceCreator, stri
return strokeElement.CreateStroke(resourceCreator);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasStrokeStyleParser.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasStrokeStyleParser.cs
index 25bce614f4e..54b4be50608 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasStrokeStyleParser.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/CanvasStrokeStyleParser.cs
@@ -6,10 +6,8 @@
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Elements.Stroke;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Parsers
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Parser for the CanvasStrokeStyle
@@ -90,4 +88,4 @@ internal static ICanvasStrokeStyleElement Parse(Match match)
return new CanvasStrokeStyleElement(match);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/ColorParser.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/ColorParser.cs
index e6bf1cb7192..a356fc9abed 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/ColorParser.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Parsers/ColorParser.cs
@@ -6,10 +6,9 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
-using Microsoft.Toolkit.Uwp.UI.Media.Geometry.Core;
using Windows.UI;
-namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry.Parsers
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
{
///
/// Parser for Color
@@ -143,4 +142,4 @@ internal static Color Parse(Match match)
return Colors.Transparent;
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Scalar.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Scalar.cs
index 773b4f46744..6067794e1a8 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Scalar.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Scalar.cs
@@ -61,4 +61,4 @@ internal static class Scalar
///
internal const float RadiansToDegrees = 180f / Pi;
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/StrokeStyle.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/StrokeStyle.cs
new file mode 100644
index 00000000000..c555501bbbe
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/StrokeStyle.cs
@@ -0,0 +1,318 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Graphics.Canvas.Geometry;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media.Geometry
+{
+ ///
+ /// Class which defines various properties which govern how the stroke is rendered.
+ ///
+ public class StrokeStyle : DependencyObject, IDisposable
+ {
+ private bool _disposedValue;
+ private CanvasStrokeStyle _canvasStrokeStyle;
+
+ ///
+ /// Event to notify that the properties of this class have been updated.
+ ///
+ public event EventHandler Updated;
+
+ ///
+ /// CustomDashStyle Dependency Property
+ ///
+ public static readonly DependencyProperty CustomDashStyleProperty = DependencyProperty.Register(
+ "CustomDashStyle",
+ typeof(string),
+ typeof(StrokeStyle),
+ new PropertyMetadata(string.Empty, OnCustomDashStyleChanged));
+
+ ///
+ /// Gets or sets the an array describing a custom dash pattern. This overrides the DashStyle property, which is only used when CustomDashStyle is set to null.
+ /// A custom dash style is an array whose elements specify the length of each dash and space in the pattern.
+ /// The first element sets the length of a dash, the second element sets the length of a space, the third element sets the length of a dash, and so on.
+ /// The length of each dash and space in the dash pattern is the product of the element value in the array and the stroke width.
+ /// This array must contain an even number of elements.
+ /// If the dash style is configured to contain a dash which is zero-length, that dash will only be visible with a cap style other than Flat.
+ ///
+ public string CustomDashStyle
+ {
+ get => (string)GetValue(CustomDashStyleProperty);
+ set => SetValue(CustomDashStyleProperty, value);
+ }
+
+ ///
+ /// Handles changes to the CustomDashStyle property.
+ ///
+ ///
+ /// DependencyProperty changed event arguments
+ private static void OnCustomDashStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var strokeStyle = (StrokeStyle)d;
+ strokeStyle.OnCustomDashStyleChanged();
+ }
+
+ ///
+ /// Instance handler for the changes to the CustomDashStyle dependency property.
+ ///
+ private void OnCustomDashStyleChanged()
+ {
+ var result = new List();
+
+ if (!string.IsNullOrWhiteSpace(CustomDashStyle))
+ {
+ var arr = CustomDashStyle.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+
+ if (arr.Any())
+ {
+ if (arr.Length % 2 != 0)
+ {
+ throw new ArgumentException("CustomDashStyle must contain an even number of elements!");
+ }
+
+ foreach (var token in arr)
+ {
+ if (float.TryParse(token, out float num))
+ {
+ result.Add(num);
+ }
+ else
+ {
+ throw new ArgumentException($"Invalid value! Cannot convert '{token}' to 'System.Single'!");
+ }
+ }
+ }
+ }
+
+ ParsedCustomDashStyle = result.Any() ? result.ToArray() : null;
+
+ OnUpdated();
+ }
+
+ ///
+ /// Gets the custom dash style parsed from the input string.
+ ///
+ public float[] ParsedCustomDashStyle { get; private set; } = null;
+
+ ///
+ /// DashCap Dependency Property
+ ///
+ public static readonly DependencyProperty DashCapProperty = DependencyProperty.Register(
+ "DashCap",
+ typeof(CanvasCapStyle),
+ typeof(StrokeStyle),
+ new PropertyMetadata(CanvasCapStyle.Square, OnPropertyChanged));
+
+ ///
+ /// Gets or sets how the ends of each dash are drawn. Defaults to Square.
+ /// If this is set to Flat, dots will have zero size so only dashes are visible.
+ ///
+ public CanvasCapStyle DashCap
+ {
+ get => (CanvasCapStyle)GetValue(DashCapProperty);
+ set => SetValue(DashCapProperty, value);
+ }
+
+ ///
+ /// DashOffset Dependency Property
+ ///
+ public static readonly DependencyProperty DashOffsetProperty = DependencyProperty.Register(
+ "DashOffset",
+ typeof(double),
+ typeof(StrokeStyle),
+ new PropertyMetadata(0d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets how far into the dash sequence the stroke will start.
+ ///
+ public double DashOffset
+ {
+ get => (double)GetValue(DashOffsetProperty);
+ set => SetValue(DashOffsetProperty, value);
+ }
+
+ ///
+ /// DashStyle Dependency Property
+ ///
+ public static readonly DependencyProperty DashStyleProperty = DependencyProperty.Register(
+ "DashStyle",
+ typeof(CanvasDashStyle),
+ typeof(StrokeStyle),
+ new PropertyMetadata(CanvasDashStyle.Solid, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the stroke's dash pattern. This is ignored if CustomDashStyle has been set.
+ ///
+ public CanvasDashStyle DashStyle
+ {
+ get => (CanvasDashStyle)GetValue(DashStyleProperty);
+ set => SetValue(DashStyleProperty, value);
+ }
+
+ ///
+ /// EndCap Dependency Property
+ ///
+ public static readonly DependencyProperty EndCapProperty = DependencyProperty.Register(
+ "EndCap",
+ typeof(CanvasCapStyle),
+ typeof(StrokeStyle),
+ new PropertyMetadata(CanvasCapStyle.Flat, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the type of shape used at the end of a stroke. Defaults to Flat.
+ ///
+ public CanvasCapStyle EndCap
+ {
+ get => (CanvasCapStyle)GetValue(EndCapProperty);
+ set => SetValue(EndCapProperty, value);
+ }
+
+ ///
+ /// LineJoin Dependency Property
+ ///
+ public static readonly DependencyProperty LineJoinProperty = DependencyProperty.Register(
+ "LineJoin",
+ typeof(CanvasLineJoin),
+ typeof(StrokeStyle),
+ new PropertyMetadata(CanvasLineJoin.Miter, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the type of joint used at the vertices of a shape's outline.
+ ///
+ public CanvasLineJoin LineJoin
+ {
+ get => (CanvasLineJoin)GetValue(LineJoinProperty);
+ set => SetValue(LineJoinProperty, value);
+ }
+
+ ///
+ /// MiterLimit Dependency Property
+ ///
+ public static readonly DependencyProperty MiterLimitProperty = DependencyProperty.Register(
+ "MiterLimit",
+ typeof(double),
+ typeof(StrokeStyle),
+ new PropertyMetadata(10d, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the limit on the ratio of the miter length to half the stroke's thickness.
+ ///
+ public double MiterLimit
+ {
+ get => (double)GetValue(MiterLimitProperty);
+ set => SetValue(MiterLimitProperty, value);
+ }
+
+ ///
+ /// StartCap Dependency Property
+ ///
+ public static readonly DependencyProperty StartCapProperty = DependencyProperty.Register(
+ "StartCap",
+ typeof(CanvasCapStyle),
+ typeof(StrokeStyle),
+ new PropertyMetadata(CanvasCapStyle.Flat, OnPropertyChanged));
+
+ ///
+ /// Gets or sets the type of shape used at the beginning of a stroke. Defaults to Flat.
+ ///
+ public CanvasCapStyle StartCap
+ {
+ get => (CanvasCapStyle)GetValue(StartCapProperty);
+ set => SetValue(StartCapProperty, value);
+ }
+
+ ///
+ /// TransformBehavior Dependency Property
+ ///
+ public static readonly DependencyProperty TransformBehaviorProperty = DependencyProperty.Register(
+ "TransformBehavior",
+ typeof(CanvasStrokeTransformBehavior),
+ typeof(StrokeStyle),
+ new PropertyMetadata(CanvasStrokeTransformBehavior.Normal, OnPropertyChanged));
+
+ ///
+ /// Gets or sets how the world transform, dots per inch (DPI), and stroke width affect the shape of the pen.
+ ///
+ public CanvasStrokeTransformBehavior TransformBehavior
+ {
+ get => (CanvasStrokeTransformBehavior)GetValue(TransformBehaviorProperty);
+ set => SetValue(TransformBehaviorProperty, value);
+ }
+
+ ///
+ /// Method that is called whenever the dependency properties of the StrokeStyle changes
+ ///
+ /// The object whose property has changed
+ /// Event arguments
+ private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var strokeStyle = (StrokeStyle)d;
+
+ // Recreate the canvas brush on any property change.
+ strokeStyle.OnUpdated();
+ }
+
+ private void OnUpdated()
+ {
+ _canvasStrokeStyle = new CanvasStrokeStyle()
+ {
+ CustomDashStyle = ParsedCustomDashStyle,
+ DashCap = DashCap,
+ DashOffset = (float)DashOffset,
+ DashStyle = DashStyle,
+ EndCap = EndCap,
+ LineJoin = LineJoin,
+ MiterLimit = (float)MiterLimit,
+ StartCap = StartCap,
+ TransformBehavior = TransformBehavior
+ };
+
+ Updated?.Invoke(this, null);
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public StrokeStyle()
+ {
+ ParsedCustomDashStyle = new float[0];
+ }
+
+ private void Dispose(bool disposing)
+ {
+ if (!_disposedValue)
+ {
+ if (disposing)
+ {
+ // Dispose managed state (managed objects)
+ ParsedCustomDashStyle = null;
+ }
+
+ // Free unmanaged resources (unmanaged objects), if any, and override finalizer
+ _disposedValue = true;
+ }
+ }
+
+ ///
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Gets the CanvasStrokeStyle.
+ ///
+ ///
+ public CanvasStrokeStyle GetCanvasStrokeStyle()
+ {
+ return _canvasStrokeStyle;
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Utils.cs b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Utils.cs
index b38e130e749..afbb05f730a 100644
--- a/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Utils.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Geometry/Utils.cs
@@ -4,7 +4,6 @@
using System;
using System.Numerics;
-using System.Runtime.InteropServices;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
@@ -31,7 +30,7 @@ public static class Utils
/// The first double to compare.
/// The second double to compare.
///
- /// bool - the result of the AreClose comparison.
+ /// bool - the result of the AreClose comparision.
///
public static bool IsCloseTo(this double value1, double value2)
{
@@ -55,7 +54,7 @@ public static bool IsCloseTo(this double value1, double value2)
/// The first double to compare.
/// The second double to compare.
///
- /// bool - the result of the LessThan comparison.
+ /// bool - the result of the LessThan comparision.
///
public static bool IsLessThan(this double value1, double value2)
{
@@ -68,7 +67,7 @@ public static bool IsLessThan(this double value1, double value2)
/// The first double to compare.
/// The second double to compare.
///
- /// bool - the result of the GreaterThan comparison.
+ /// bool - the result of the GreaterThan comparision.
///
public static bool IsGreaterThan(this double value1, double value2)
{
@@ -81,7 +80,7 @@ public static bool IsGreaterThan(this double value1, double value2)
///
/// The double to compare to 1.
///
- /// bool - the result of the AreClose comparison.
+ /// bool - the result of the AreClose comparision.
///
public static bool IsOne(this double value)
{
@@ -94,7 +93,7 @@ public static bool IsOne(this double value)
///
/// The double to compare to 0.
///
- /// bool - the result of the AreClose comparison.
+ /// bool - the result of the AreClose comparision.
///
public static bool IsZero(this double value)
{
@@ -107,7 +106,7 @@ public static bool IsZero(this double value)
/// The first float to compare.
/// The second float to compare.
///
- /// bool - the result of the AreClose comparison.
+ /// bool - the result of the AreClose comparision.
///
public static bool IsCloseTo(this float value1, float value2)
{
@@ -131,7 +130,7 @@ public static bool IsCloseTo(this float value1, float value2)
/// The first float to compare.
/// The second float to compare.
///
- /// bool - the result of the LessThan comparison.
+ /// bool - the result of the LessThan comparision.
///
public static bool IsLessThan(this float value1, float value2)
{
@@ -144,7 +143,7 @@ public static bool IsLessThan(this float value1, float value2)
/// The first float to compare.
/// The second float to compare.
///
- /// bool - the result of the GreaterThan comparison.
+ /// bool - the result of the GreaterThan comparision.
///
public static bool IsGreaterThan(this float value1, float value2)
{
@@ -157,7 +156,7 @@ public static bool IsGreaterThan(this float value1, float value2)
///
/// The float to compare to 1.
///
- /// bool - the result of the AreClose comparison.
+ /// bool - the result of the AreClose comparision.
///
public static bool IsOne(this float value)
{
@@ -170,7 +169,7 @@ public static bool IsOne(this float value)
///
/// The float to compare to 0.
///
- /// bool - the result of the AreClose comparison.
+ /// bool - the result of the AreClose comparision.
///
public static bool IsZero(this float value)
{
@@ -813,5 +812,40 @@ public static Rect GetOptimumSize(double srcWidth, double srcHeight, double dest
return new Rect(left, top, targetWidth, targetHeight);
}
+
+ ///
+ /// Converts to
+ ///
+ ///
+ ///
+ public static Matrix3x2 ToMatrix3x2(this MatrixTransform transform)
+ {
+ return new Matrix3x2(
+ (float)transform.Matrix.M11,
+ (float)transform.Matrix.M12,
+ (float)transform.Matrix.M21,
+ (float)transform.Matrix.M22,
+ (float)transform.Matrix.OffsetX,
+ (float)transform.Matrix.OffsetY);
+ }
+
+ ///
+ /// Converts to
+ ///
+ ///
+ ///
+ public static MatrixTransform ToMatrixTransform(this Matrix3x2 matrix)
+ {
+ return new MatrixTransform()
+ {
+ Matrix = new Matrix(
+ matrix.M11,
+ matrix.M12,
+ matrix.M21,
+ matrix.M22,
+ matrix.M31,
+ matrix.M32)
+ };
+ }
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Surface/CompositionGenerator.cs b/Microsoft.Toolkit.Uwp.UI.Media/Surface/CompositionGenerator.cs
new file mode 100644
index 00000000000..25fc0e5d8ce
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Media/Surface/CompositionGenerator.cs
@@ -0,0 +1,1147 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Linq;
+using System.Numerics;
+using System.Threading.Tasks;
+using Microsoft.Graphics.Canvas;
+using Microsoft.Graphics.Canvas.Brushes;
+using Microsoft.Graphics.Canvas.Effects;
+using Microsoft.Graphics.Canvas.Geometry;
+using Microsoft.Graphics.Canvas.UI.Composition;
+using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
+using Windows.Foundation;
+using Windows.Graphics.DirectX;
+using Windows.UI;
+using Windows.UI.Composition;
+using Windows.UI.Xaml;
+
+namespace Microsoft.Toolkit.Uwp.UI.Media
+{
+ ///
+ /// Core class which is used to create various RenderSurfaces like GeometrySurface, GeometryMaskSurface, GaussianMaskSurface, ImageSurface, ImageMaskSurface
+ ///
+ public sealed class CompositionGenerator : ICompositionGeneratorInternal
+ {
+ ///
+ /// Device Replaced event
+ ///
+ public event EventHandler