Browse Source

Merge remote-tracking branch 'Perspex/master'

pull/532/head
Wiesław Šoltés 10 years ago
parent
commit
3cc4a91bd2
  1. 3
      .gitmodules
  2. 3
      Perspex.sln
  3. 19
      samples/ControlCatalog.Desktop/Program.cs
  4. 16
      samples/ControlCatalog/Pages/CanvasPage.xaml
  5. 21
      src/Markup/Perspex.Markup.Xaml/Context/PerspexObjectAssembler.cs
  6. 1
      src/Markup/Perspex.Markup.Xaml/Context/PerspexTypeFeatureProvider.cs
  7. 10
      src/Markup/Perspex.Markup.Xaml/Converters/BitmapTypeConverter.cs
  8. 32
      src/Markup/Perspex.Markup.Xaml/Converters/SizeTypeConverter.cs
  9. 2
      src/Markup/Perspex.Markup.Xaml/MarkupExtensions/StaticExtension.cs
  10. 2
      src/Markup/Perspex.Markup.Xaml/MarkupExtensions/TypeExtension.cs
  11. 2
      src/Markup/Perspex.Markup.Xaml/OmniXAML
  12. 29
      src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj
  13. 66
      src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs
  14. 14
      src/Markup/Perspex.Markup.Xaml/Styling/StyleInclude.cs
  15. 1
      src/Markup/Perspex.Markup.Xaml/glass
  16. 1
      src/Markup/Perspex.Markup.Xaml/packages.config
  17. 11
      src/Perspex.Base/Platform/IAssetLoader.cs
  18. 103
      src/Perspex.SceneGraph/Media/ArcSegment.cs
  19. 65
      src/Perspex.SceneGraph/Media/BezierSegment .cs
  20. 2
      src/Perspex.SceneGraph/Media/Geometry.cs
  21. 31
      src/Perspex.SceneGraph/Media/LineSegment.cs
  22. 102
      src/Perspex.SceneGraph/Media/PathFigure.cs
  23. 123
      src/Perspex.SceneGraph/Media/PathGeometry.cs
  24. 15
      src/Perspex.SceneGraph/Media/PathGeometryCollections.cs
  25. 10
      src/Perspex.SceneGraph/Media/PathSegment.cs
  26. 46
      src/Perspex.SceneGraph/Media/QuadraticBezierSegment .cs
  27. 57
      src/Perspex.SceneGraph/Media/TransformGroup.cs
  28. 9
      src/Perspex.SceneGraph/Perspex.SceneGraph.csproj
  29. 25
      src/Perspex.SceneGraph/Size.cs
  30. 187
      src/Shared/PlatformSupport/AssetLoader.cs
  31. 2
      src/Skia/Perspex.Skia.Android.TestApp/Perspex.Skia.Android.TestApp.csproj
  32. 4
      src/Skia/Perspex.Skia.Android/Perspex.Skia.Android.csproj
  33. 2
      src/Skia/Perspex.Skia.Android/packages.config
  34. 6
      src/Skia/Perspex.Skia.Desktop/Perspex.Skia.Desktop.csproj
  35. 2
      src/Skia/Perspex.Skia.Desktop/packages.config
  36. 2
      src/Skia/Perspex.Skia.iOS/Perspex.Skia.iOS.csproj
  37. 2
      src/Skia/Perspex.Skia.iOS/packages.config
  38. 10
      src/Skia/Perspex.Skia/DrawingContextImpl.cs
  39. 5
      src/Skia/Perspex.Skia/SkiaSharpExtensions.cs
  40. 40
      src/Skia/Perspex.Skia/StreamGeometryImpl.cs
  41. 7
      src/Skia/Perspex.Skia/readme.md
  42. 7
      src/Windows/Perspex.Direct2D1/Media/StreamGeometryContextImpl.cs
  43. 1
      src/Windows/Perspex.Direct2D1/Media/StreamGeometryImpl.cs

3
.gitmodules

@ -8,3 +8,6 @@
[submodule "src/Markup/Perspex.Markup.Xaml/OmniXAML"] [submodule "src/Markup/Perspex.Markup.Xaml/OmniXAML"]
path = src/Markup/Perspex.Markup.Xaml/OmniXAML path = src/Markup/Perspex.Markup.Xaml/OmniXAML
url = https://github.com/Perspex/OmniXAML.git url = https://github.com/Perspex/OmniXAML.git
[submodule "src/Markup/Perspex.Markup.Xaml/glass"]
path = src/Markup/Perspex.Markup.Xaml/glass
url = https://github.com/SuperJMN/glass

3
Perspex.sln

@ -60,9 +60,6 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Markup.Xaml", "src\Markup\Perspex.Markup.Xaml\Perspex.Markup.Xaml.csproj", "{3E53A01A-B331-47F3-B828-4A5717E77A24}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Markup.Xaml", "src\Markup\Perspex.Markup.Xaml\Perspex.Markup.Xaml.csproj", "{3E53A01A-B331-47F3-B828-4A5717E77A24}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{9B9E3891-2366-4253-A952-D08BCEB71098}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{9B9E3891-2366-4253-A952-D08BCEB71098}"
ProjectSection(SolutionItems) = preProject
samples\ControlCatalog\ControlCatalog.csproj = samples\ControlCatalog\ControlCatalog.csproj
EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication", "samples\TestApplication\TestApplication.csproj", "{E3A1060B-50D0-44E8-88B6-F44EF2E5BD72}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication", "samples\TestApplication\TestApplication.csproj", "{E3A1060B-50D0-44E8-88B6-F44EF2E5BD72}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject

19
samples/ControlCatalog.Desktop/Program.cs

@ -6,24 +6,6 @@ using Perspex;
using System.Reflection; using System.Reflection;
using Perspex.Platform; using Perspex.Platform;
// Not sure where the best home for this is
namespace Perspex
{
public static class SharedApplicationExtensions
{
// For true Portable apps we need to select the PCL assembly NOT the host platform exe. Unfortunately
// Win32 subsystem registers one by default (the wrong one) and so this can override that.
//
public static AppT UseAssetAssembly<AppT>(this AppT app, Assembly assembly) where AppT : Application
{
// Asset loading searches our own assembly?
PerspexLocator.CurrentMutable.GetService<IAssetLoader>().SetDefaultAssembly(assembly);
return app;
}
}
}
namespace ControlCatalog namespace ControlCatalog
{ {
internal class Program internal class Program
@ -34,7 +16,6 @@ namespace ControlCatalog
new App() new App()
.ConfigureRenderSystem(args) .ConfigureRenderSystem(args)
.UseAssetAssembly(typeof(App).Assembly)
.LoadFromXaml() .LoadFromXaml()
.RunWithMainWindow<MainWindow>(); .RunWithMainWindow<MainWindow>();
} }

16
samples/ControlCatalog/Pages/CanvasPage.xaml

@ -4,10 +4,22 @@
<TextBlock Classes="h2">A panel which lays out its children by explicit coordinates</TextBlock> <TextBlock Classes="h2">A panel which lays out its children by explicit coordinates</TextBlock>
<Canvas Background="Yellow" Width="300" Height="400"> <Canvas Background="Yellow" Width="300" Height="400">
<Rectangle Fill="Blue" Width="63" Height="41" Canvas.Left="40" Canvas.Top="31"/> <Rectangle Fill="Blue" Width="63" Height="41" Canvas.Left="40" Canvas.Top="31"/>
<Ellipse Fill="Green" Width="58" Height="58" Canvas.Left="160" Canvas.Top="79"/> <Ellipse Fill="Green" Width="58" Height="58" Canvas.Left="88" Canvas.Top="100"/>
<Path Fill="Orange" Data="M 0,0 c 50,0 50,-50 c 50,0 50,50 h -50 v 50 l -50,-50 Z" Canvas.Left="30" Canvas.Top="250"/> <Path Fill="Orange" Data="M 0,0 c 50,0 50,-50 c 50,0 50,50 h -50 v 50 l -50,-50 Z" Canvas.Left="30" Canvas.Top="250"/>
<Path Fill="OrangeRed" Canvas.Left="180" Canvas.Top="250">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="0,0" IsClosed="True">
<QuadraticBezierSegment Point1="50,0" Point2="50,-50" />
<QuadraticBezierSegment Point1="100,-50" Point2="100,0" />
<LineSegment Point="50,0" />
<LineSegment Point="50,50" />
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
<Line StartPoint="120,185" EndPoint="30,115" Stroke="Red" StrokeThickness="2"/> <Line StartPoint="120,185" EndPoint="30,115" Stroke="Red" StrokeThickness="2"/>
<Polygon Points="75,0 120,120 0,45 150,45 30,120" Stroke="DarkBlue" StrokeThickness="1" Fill="Violet" Canvas.Left="150" Canvas.Top="180"/> <Polygon Points="75,0 120,120 0,45 150,45 30,120" Stroke="DarkBlue" StrokeThickness="1" Fill="Violet" Canvas.Left="150" Canvas.Top="31"/>
<Polyline Points="0,0 65,0 78,-26 91,39 104,-39 117,13 130,0 195,0" Stroke="Brown" Canvas.Left="30" Canvas.Top="350"/> <Polyline Points="0,0 65,0 78,-26 91,39 104,-39 117,13 130,0 195,0" Stroke="Brown" Canvas.Left="30" Canvas.Top="350"/>
</Canvas> </Canvas>
</StackPanel> </StackPanel>

21
src/Markup/Perspex.Markup.Xaml/Context/PerspexObjectAssembler.cs

@ -7,6 +7,8 @@ using OmniXaml.ObjectAssembler;
using OmniXaml.ObjectAssembler.Commands; using OmniXaml.ObjectAssembler.Commands;
using OmniXaml.TypeConversion; using OmniXaml.TypeConversion;
using Perspex.Markup.Xaml.Templates; using Perspex.Markup.Xaml.Templates;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace Perspex.Markup.Xaml.Context namespace Perspex.Markup.Xaml.Context
{ {
@ -27,7 +29,8 @@ namespace Perspex.Markup.Xaml.Context
mapping.Map<TreeDataTemplate>(x => x.Content, new TemplateLoader()); mapping.Map<TreeDataTemplate>(x => x.Content, new TemplateLoader());
mapping.Map<ItemsPanelTemplate>(x => x.Content, new TemplateLoader()); mapping.Map<ItemsPanelTemplate>(x => x.Content, new TemplateLoader());
var valueContext = new ValueContext(typeSource, topDownValueContext); var parsingDictionary = GetDictionary(settings);
var valueContext = new ValueContext(typeSource, topDownValueContext, parsingDictionary);
assembler = new ObjectAssembler(typeSource, valueContext, settings); assembler = new ObjectAssembler(typeSource, valueContext, settings);
objectAssembler = new TemplateHostingObjectAssembler(assembler, mapping); objectAssembler = new TemplateHostingObjectAssembler(assembler, mapping);
} }
@ -55,5 +58,21 @@ namespace Perspex.Markup.Xaml.Context
{ {
objectAssembler.OverrideInstance(instance); objectAssembler.OverrideInstance(instance);
} }
private static IReadOnlyDictionary<string, object> GetDictionary(Settings settings)
{
IReadOnlyDictionary<string, object> dict;
if (settings != null)
{
dict = settings.ParsingContext;
}
else
{
dict = new ReadOnlyDictionary<string, object>(new Dictionary<string, object>());
}
return dict;
}
} }
} }

1
src/Markup/Perspex.Markup.Xaml/Context/PerspexTypeFeatureProvider.cs

@ -165,6 +165,7 @@ namespace Perspex.Markup.Xaml.Context
RegisterTypeConverter(typeof(RelativePoint), new RelativePointTypeConverter()); RegisterTypeConverter(typeof(RelativePoint), new RelativePointTypeConverter());
RegisterTypeConverter(typeof(RelativeRect), new RelativeRectTypeConverter()); RegisterTypeConverter(typeof(RelativeRect), new RelativeRectTypeConverter());
RegisterTypeConverter(typeof(RowDefinitions), new RowDefinitionsTypeConverter()); RegisterTypeConverter(typeof(RowDefinitions), new RowDefinitionsTypeConverter());
RegisterTypeConverter(typeof(Size), new SizeTypeConverter());
RegisterTypeConverter(typeof(Selector), new SelectorTypeConverter()); RegisterTypeConverter(typeof(Selector), new SelectorTypeConverter());
RegisterTypeConverter(typeof(SolidColorBrush), new BrushTypeConverter()); RegisterTypeConverter(typeof(SolidColorBrush), new BrushTypeConverter());
RegisterTypeConverter(typeof(Thickness), new ThicknessTypeConverter()); RegisterTypeConverter(typeof(Thickness), new ThicknessTypeConverter());

10
src/Markup/Perspex.Markup.Xaml/Converters/BitmapTypeConverter.cs

@ -24,6 +24,7 @@ namespace Perspex.Markup.Xaml.Converters
public object ConvertFrom(IValueContext context, CultureInfo culture, object value) public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{ {
var uri = new Uri((string)value, UriKind.RelativeOrAbsolute); var uri = new Uri((string)value, UriKind.RelativeOrAbsolute);
var baseUri = GetBaseUri(context);
var scheme = uri.IsAbsoluteUri ? uri.Scheme : "file"; var scheme = uri.IsAbsoluteUri ? uri.Scheme : "file";
switch (scheme) switch (scheme)
@ -32,7 +33,7 @@ namespace Perspex.Markup.Xaml.Converters
return new Bitmap((string)value); return new Bitmap((string)value);
default: default:
var assets = PerspexLocator.Current.GetService<IAssetLoader>(); var assets = PerspexLocator.Current.GetService<IAssetLoader>();
return new Bitmap(assets.Open(uri)); return new Bitmap(assets.Open(uri, baseUri));
} }
} }
@ -40,5 +41,12 @@ namespace Perspex.Markup.Xaml.Converters
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
private Uri GetBaseUri(IValueContext context)
{
object result;
context.ParsingDictionary.TryGetValue("Uri", out result);
return result as Uri;
}
} }
} }

32
src/Markup/Perspex.Markup.Xaml/Converters/SizeTypeConverter.cs

@ -0,0 +1,32 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Globalization;
using OmniXaml.TypeConversion;
namespace Perspex.Markup.Xaml.Converters
{
public class SizeTypeConverter : ITypeConverter
{
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return Size.Parse((string)value, culture);
}
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
}
}

2
src/Markup/Perspex.Markup.Xaml/MarkupExtensions/StaticExtension.cs

@ -24,7 +24,7 @@ namespace Perspex.Markup.Xaml.MarkupExtensions
public override object ProvideValue(MarkupExtensionContext markupExtensionContext) public override object ProvideValue(MarkupExtensionContext markupExtensionContext)
{ {
var typeRepository = markupExtensionContext.TypeRepository; var typeRepository = markupExtensionContext.ValueContext.TypeRepository;
var typeAndMember = GetTypeAndMember(Identifier); var typeAndMember = GetTypeAndMember(Identifier);
var prefixAndType = GetPrefixAndType(typeAndMember.Item1); var prefixAndType = GetPrefixAndType(typeAndMember.Item1);
var xamlType = typeRepository.GetByPrefix(prefixAndType.Item1, prefixAndType.Item2); var xamlType = typeRepository.GetByPrefix(prefixAndType.Item1, prefixAndType.Item2);

2
src/Markup/Perspex.Markup.Xaml/MarkupExtensions/TypeExtension.cs

@ -43,7 +43,7 @@ namespace Perspex.Markup.Xaml.MarkupExtensions
return Type; return Type;
} }
return ResolveFromString(TypeName, markupExtensionContext.TypeRepository); return ResolveFromString(TypeName, markupExtensionContext.ValueContext.TypeRepository);
} }
} }
} }

2
src/Markup/Perspex.Markup.Xaml/OmniXAML

@ -1 +1 @@
Subproject commit 75e0dc32fe9a6d97f5b59d2b7d689db2475f444f Subproject commit b122549406107170bbe6e67c0d6a1a4252beef77

29
src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj

@ -66,6 +66,7 @@
<Compile Include="Converters\PerspexListTypeConverter.cs" /> <Compile Include="Converters\PerspexListTypeConverter.cs" />
<Compile Include="Converters\PerspexPropertyTypeConverter.cs" /> <Compile Include="Converters\PerspexPropertyTypeConverter.cs" />
<Compile Include="Converters\PointsListTypeConverter.cs" /> <Compile Include="Converters\PointsListTypeConverter.cs" />
<Compile Include="Converters\SizeTypeConverter.cs" />
<Compile Include="Converters\PointTypeConverter.cs" /> <Compile Include="Converters\PointTypeConverter.cs" />
<Compile Include="Converters\RelativePointTypeConverter.cs" /> <Compile Include="Converters\RelativePointTypeConverter.cs" />
<Compile Include="Converters\RelativeRectTypeConverter.cs" /> <Compile Include="Converters\RelativeRectTypeConverter.cs" />
@ -81,22 +82,22 @@
<Compile Include="Data\SourceBindingEndpoint.cs" /> <Compile Include="Data\SourceBindingEndpoint.cs" />
<Compile Include="Data\StyleResourceBinding.cs" /> <Compile Include="Data\StyleResourceBinding.cs" />
<Compile Include="Data\TargetBindingEndpoint.cs" /> <Compile Include="Data\TargetBindingEndpoint.cs" />
<Compile Include="glass\Glass.Core\AutoKeyDictionary.cs" />
<Compile Include="glass\Glass.Core\DependencySorter.cs" />
<Compile Include="glass\Glass.Core\EnumExtensions.cs" />
<Compile Include="glass\Glass.Core\Extensions.cs" />
<Compile Include="glass\Glass.Core\Guard.cs" />
<Compile Include="glass\Glass.Core\IAdd.cs" />
<Compile Include="glass\Glass.Core\IDependency.cs" />
<Compile Include="glass\Glass.Core\ReflectionExtensions.cs" />
<Compile Include="glass\Glass.Core\StackingLinkedList.cs" />
<Compile Include="glass\Glass.Core\StackingLinkedListMixin.cs" />
<Compile Include="MarkupExtensions\StyleResourceExtension.cs" /> <Compile Include="MarkupExtensions\StyleResourceExtension.cs" />
<Compile Include="MarkupExtensions\BindingExtension.cs" /> <Compile Include="MarkupExtensions\BindingExtension.cs" />
<Compile Include="MarkupExtensions\RelativeSourceExtension.cs" /> <Compile Include="MarkupExtensions\RelativeSourceExtension.cs" />
<Compile Include="MarkupExtensions\StaticExtension.cs" /> <Compile Include="MarkupExtensions\StaticExtension.cs" />
<Compile Include="MarkupExtensions\TemplateBindingExtension.cs" /> <Compile Include="MarkupExtensions\TemplateBindingExtension.cs" />
<Compile Include="MarkupExtensions\TypeExtension.cs" /> <Compile Include="MarkupExtensions\TypeExtension.cs" />
<Compile Include="OmniXAML\Source\Glass\AutoKeyDictionary.cs" />
<Compile Include="OmniXAML\Source\Glass\DependencySorter.cs" />
<Compile Include="OmniXAML\Source\Glass\EnumExtensions.cs" />
<Compile Include="OmniXAML\Source\Glass\Extensions.cs" />
<Compile Include="OmniXAML\Source\Glass\Guard.cs" />
<Compile Include="OmniXAML\Source\Glass\IAdd.cs" />
<Compile Include="OmniXAML\Source\Glass\IDependency.cs" />
<Compile Include="OmniXAML\Source\Glass\ReflectionExtensions.cs" />
<Compile Include="OmniXAML\Source\Glass\StackingLinkedList.cs" />
<Compile Include="OmniXAML\Source\Glass\StackingLinkedListMixin.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Attributes\ContentPropertyAttribute.cs" /> <Compile Include="OmniXAML\Source\OmniXaml\Attributes\ContentPropertyAttribute.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Attributes\DependsOnAttribute.cs" /> <Compile Include="OmniXAML\Source\OmniXaml\Attributes\DependsOnAttribute.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Attributes\XmlnsDefinitionAttribute.cs" /> <Compile Include="OmniXAML\Source\OmniXaml\Attributes\XmlnsDefinitionAttribute.cs" />
@ -275,6 +276,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="app.config" /> <None Include="app.config" />
<None Include="glass\Glass.Core\Glass.Core.nuspec" />
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -316,6 +318,10 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Glass, Version=1.6.0.113, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Glass.1.6.0.113\lib\portable45-net45+win8\Glass.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Sprache, Version=2.0.0.50, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Sprache, Version=2.0.0.50, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Sprache.2.0.0.50\lib\portable-net4+netcore45+win8+wp8+sl5+MonoAndroid+Xamarin.iOS10+MonoTouch\Sprache.dll</HintPath> <HintPath>..\..\..\packages\Sprache.2.0.0.50\lib\portable-net4+netcore45+win8+wp8+sl5+MonoAndroid+Xamarin.iOS10+MonoTouch\Sprache.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -333,6 +339,9 @@
<HintPath>..\..\..\packages\Rx-PlatformServices.2.2.5\lib\portable-windows8+net45+wp8\System.Reactive.PlatformServices.dll</HintPath> <HintPath>..\..\..\packages\Rx-PlatformServices.2.2.5\lib\portable-windows8+net45+wp8\System.Reactive.PlatformServices.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="glass\Glass.Core\Glass.Core.csproj" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

66
src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs

@ -15,7 +15,7 @@ namespace Perspex.Markup.Xaml
using Controls; using Controls;
using Data; using Data;
using OmniXaml.ObjectAssembler; using OmniXaml.ObjectAssembler;
using System.Linq;
/// <summary> /// <summary>
/// Loads XAML for a perspex application. /// Loads XAML for a perspex application.
/// </summary> /// </summary>
@ -23,6 +23,7 @@ namespace Perspex.Markup.Xaml
{ {
private static PerspexParserFactory s_parserFactory; private static PerspexParserFactory s_parserFactory;
private static IInstanceLifeCycleListener s_lifeCycleListener = new PerspexLifeCycleListener(); private static IInstanceLifeCycleListener s_lifeCycleListener = new PerspexLifeCycleListener();
private static Stack<Uri> s_uriStack = new Stack<Uri>();
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="PerspexXamlLoader"/> class. /// Initializes a new instance of the <see cref="PerspexXamlLoader"/> class.
@ -41,6 +42,18 @@ namespace Perspex.Markup.Xaml
{ {
} }
/// <summary>
/// Gets the URI of the XAML file currently being loaded.
/// </summary>
/// <remarks>
/// TODO: Making this internal for now as I'm not sure that this is the correct
/// thing to do, but its needd by <see cref="StyleInclude"/> to get the URL of
/// the currently loading XAML file, as we can't use the OmniXAML parsing context
/// there. Maybe we need a way to inject OmniXAML context into the objects its
/// constructing?
/// </remarks>
internal static Uri UriContext => s_uriStack.Count > 0 ? s_uriStack.Peek() : null;
/// <summary> /// <summary>
/// Loads the XAML into a Perspex component. /// Loads the XAML into a Perspex component.
/// </summary> /// </summary>
@ -84,7 +97,7 @@ namespace Perspex.Markup.Xaml
{ {
var initialize = rootInstance as ISupportInitialize; var initialize = rootInstance as ISupportInitialize;
initialize?.BeginInit(); initialize?.BeginInit();
return Load(stream, rootInstance); return Load(stream, rootInstance, uri);
} }
} }
} }
@ -96,11 +109,14 @@ namespace Perspex.Markup.Xaml
/// Loads XAML from a URI. /// Loads XAML from a URI.
/// </summary> /// </summary>
/// <param name="uri">The URI of the XAML file.</param> /// <param name="uri">The URI of the XAML file.</param>
/// <param name="baseUri">
/// A base URI to use if <paramref name="uri"/> is relative.
/// </param>
/// <param name="rootInstance"> /// <param name="rootInstance">
/// The optional instance into which the XAML should be loaded. /// The optional instance into which the XAML should be loaded.
/// </param> /// </param>
/// <returns>The loaded object.</returns> /// <returns>The loaded object.</returns>
public object Load(Uri uri, object rootInstance = null) public object Load(Uri uri, Uri baseUri = null, object rootInstance = null)
{ {
Contract.Requires<ArgumentNullException>(uri != null); Contract.Requires<ArgumentNullException>(uri != null);
@ -112,9 +128,9 @@ namespace Perspex.Markup.Xaml
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?"); "Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?");
} }
using (var stream = assetLocator.Open(uri)) using (var stream = assetLocator.Open(uri, baseUri))
{ {
return Load(stream, rootInstance); return Load(stream, rootInstance, uri);
} }
} }
@ -143,23 +159,43 @@ namespace Perspex.Markup.Xaml
/// <param name="rootInstance"> /// <param name="rootInstance">
/// The optional instance into which the XAML should be loaded. /// The optional instance into which the XAML should be loaded.
/// </param> /// </param>
/// <param name="uri">The URI of the XAML</param>
/// <returns>The loaded object.</returns> /// <returns>The loaded object.</returns>
public object Load(Stream stream, object rootInstance = null) public object Load(Stream stream, object rootInstance = null, Uri uri = null)
{ {
var result = base.Load(stream, new Settings try
{ {
RootInstance = rootInstance, if (uri != null)
InstanceLifeCycleListener = s_lifeCycleListener, {
}); s_uriStack.Push(uri);
}
var topLevel = result as TopLevel; var result = base.Load(stream, new Settings
{
RootInstance = rootInstance,
InstanceLifeCycleListener = s_lifeCycleListener,
ParsingContext = new Dictionary<string, object>
{
{ "Uri", uri }
}
});
var topLevel = result as TopLevel;
if (topLevel != null)
{
DelayedBinding.ApplyBindings(topLevel);
}
if (topLevel != null) return result;
}
finally
{ {
DelayedBinding.ApplyBindings(topLevel); if (uri != null)
{
s_uriStack.Pop();
}
} }
return result;
} }
private static PerspexParserFactory GetParserFactory() private static PerspexParserFactory GetParserFactory()

14
src/Markup/Perspex.Markup.Xaml/Styling/StyleInclude.cs

@ -11,8 +11,20 @@ namespace Perspex.Markup.Xaml.Styling
/// </summary> /// </summary>
public class StyleInclude : IStyle public class StyleInclude : IStyle
{ {
private Uri _baseUri;
private IStyle _loaded; private IStyle _loaded;
/// <summary>
/// Initializes a new instance of the <see cref="StyleInclude"/> class.
/// </summary>
public StyleInclude()
{
// StyleInclude will usually be loaded from XAML and its URI can be relative to the
// XAML file that its included in, so store the current XAML file's URI if any as
// a base URI.
_baseUri = PerspexXamlLoader.UriContext;
}
/// <summary> /// <summary>
/// Gets or sets the source URL. /// Gets or sets the source URL.
/// </summary> /// </summary>
@ -28,7 +40,7 @@ namespace Perspex.Markup.Xaml.Styling
if (_loaded == null) if (_loaded == null)
{ {
var loader = new PerspexXamlLoader(); var loader = new PerspexXamlLoader();
_loaded = (IStyle)loader.Load(Source); _loaded = (IStyle)loader.Load(Source, _baseUri);
} }
return _loaded; return _loaded;

1
src/Markup/Perspex.Markup.Xaml/glass

@ -0,0 +1 @@
Subproject commit 9e17adbd3ac0b342e7922ee2d5a11e5d50b7e687

1
src/Markup/Perspex.Markup.Xaml/packages.config

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Glass" version="1.6.0.113" targetFramework="portable45-net45+win8" />
<package id="Rx-Core" version="2.2.5" targetFramework="portable46-net451+win81" /> <package id="Rx-Core" version="2.2.5" targetFramework="portable46-net451+win81" />
<package id="Rx-Interfaces" version="2.2.5" targetFramework="portable46-net451+win81" /> <package id="Rx-Interfaces" version="2.2.5" targetFramework="portable46-net451+win81" />
<package id="Rx-Linq" version="2.2.5" targetFramework="portable46-net451+win81" /> <package id="Rx-Linq" version="2.2.5" targetFramework="portable46-net451+win81" />

11
src/Perspex.Base/Platform/IAssetLoader.cs

@ -21,22 +21,27 @@ namespace Perspex.Platform
/// <param name="asm"></param> /// <param name="asm"></param>
void SetDefaultAssembly(Assembly asm); void SetDefaultAssembly(Assembly asm);
/// <summary> /// <summary>
/// Checks if an asset with the specified URI exists. /// Checks if an asset with the specified URI exists.
/// </summary> /// </summary>
/// <param name="uri">The URI.</param> /// <param name="uri">The URI.</param>
/// <param name="baseUri">
/// A base URI to use if <paramref name="uri"/> is relative.
/// </param>
/// <returns>True if the asset could be found; otherwise false.</returns> /// <returns>True if the asset could be found; otherwise false.</returns>
bool Exists(Uri uri); bool Exists(Uri uri, Uri baseUri = null);
/// <summary> /// <summary>
/// Opens the resource with the requested URI. /// Opens the resource with the requested URI.
/// </summary> /// </summary>
/// <param name="uri">The URI.</param> /// <param name="uri">The URI.</param>
/// <param name="baseUri">
/// A base URI to use if <paramref name="uri"/> is relative.
/// </param>
/// <returns>A stream containing the resource contents.</returns> /// <returns>A stream containing the resource contents.</returns>
/// <exception cref="FileNotFoundException"> /// <exception cref="FileNotFoundException">
/// The resource was not found. /// The resource was not found.
/// </exception> /// </exception>
Stream Open(Uri uri); Stream Open(Uri uri, Uri baseUri = null);
} }
} }

103
src/Perspex.SceneGraph/Media/ArcSegment.cs

@ -0,0 +1,103 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Perspex.Media
{
public sealed class ArcSegment : PathSegment
{
/// <summary>
/// Defines the <see cref="IsLargeArc"/> property.
/// </summary>
public static readonly StyledProperty<bool> IsLargeArcProperty
= PerspexProperty.Register<ArcSegment, bool>(nameof(IsLargeArc), false);
/// <summary>
/// Defines the <see cref="Point"/> property.
/// </summary>
public static readonly StyledProperty<Point> PointProperty
= PerspexProperty.Register<ArcSegment, Point>(nameof(Point));
/// <summary>
/// Defines the <see cref="RotationAngle"/> property.
/// </summary>
public static readonly StyledProperty<double> RotationAngleProperty
= PerspexProperty.Register<ArcSegment, double>(nameof(RotationAngle), 0);
/// <summary>
/// Defines the <see cref="Size"/> property.
/// </summary>
public static readonly StyledProperty<Size> SizeProperty
= PerspexProperty.Register<ArcSegment, Size>(nameof(Size));
/// <summary>
/// Defines the <see cref="SweepDirection"/> property.
/// </summary>
public static readonly StyledProperty<SweepDirection> SweepDirectionProperty
= PerspexProperty.Register<ArcSegment, SweepDirection>(nameof(SweepDirection), SweepDirection.Clockwise);
/// <summary>
/// Gets or sets a value indicating whether this instance is large arc.
/// </summary>
/// <value>
/// <c>true</c> if this instance is large arc; otherwise, <c>false</c>.
/// </value>
public bool IsLargeArc
{
get { return GetValue(IsLargeArcProperty); }
set { SetValue(IsLargeArcProperty, value); }
}
/// <summary>
/// Gets or sets the point.
/// </summary>
/// <value>
/// The point.
/// </value>
public Point Point
{
get { return GetValue(PointProperty); }
set { SetValue(PointProperty, value); }
}
/// <summary>
/// Gets or sets the rotation angle.
/// </summary>
/// <value>
/// The rotation angle.
/// </value>
public double RotationAngle
{
get { return GetValue(RotationAngleProperty); }
set { SetValue(RotationAngleProperty, value); }
}
/// <summary>
/// Gets or sets the size.
/// </summary>
/// <value>
/// The size.
/// </value>
public Size Size
{
get { return GetValue(SizeProperty); }
set { SetValue(SizeProperty, value); }
}
/// <summary>
/// Gets or sets the sweep direction.
/// </summary>
/// <value>
/// The sweep direction.
/// </value>
public SweepDirection SweepDirection
{
get { return GetValue(SweepDirectionProperty); }
set { SetValue(SweepDirectionProperty, value); }
}
protected internal override void ApplyTo(StreamGeometryContext ctx)
{
ctx.ArcTo(Point, Size, RotationAngle, IsLargeArc, SweepDirection);
}
}
}

65
src/Perspex.SceneGraph/Media/BezierSegment .cs

@ -0,0 +1,65 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Perspex.Media
{
public sealed class BezierSegment : PathSegment
{
/// <summary>
/// Defines the <see cref="Point1"/> property.
/// </summary>
public static readonly StyledProperty<Point> Point1Property
= PerspexProperty.Register<BezierSegment, Point>(nameof(Point1));
/// <summary>
/// Defines the <see cref="Point2"/> property.
/// </summary>
public static readonly StyledProperty<Point> Point2Property
= PerspexProperty.Register<BezierSegment, Point>(nameof(Point2));
/// <summary>
/// Defines the <see cref="Point3"/> property.
/// </summary>
public static readonly StyledProperty<Point> Point3Property
= PerspexProperty.Register<BezierSegment, Point>(nameof(Point3));
/// <summary>
/// Gets or sets the point1.
/// </summary>
/// <value>
/// The point1.
/// </value>
public Point Point1
{
get { return GetValue(Point1Property); }
set { SetValue(Point1Property, value); }
}
/// <summary>
/// Gets or sets the point2.
/// </summary>
/// <value>
/// The point2.
/// </value>
public Point Point2
{
get { return GetValue(Point2Property); }
set { SetValue(Point2Property, value); }
}
/// <summary>
/// Gets or sets the point3.
/// </summary>
/// <value>
/// The point3.
/// </value>
public Point Point3
{
get { return GetValue(Point3Property); }
set { SetValue(Point3Property, value); }
}
protected internal override void ApplyTo(StreamGeometryContext ctx)
{
ctx.CubicBezierTo(Point1, Point2, Point3);
}
}
}

2
src/Perspex.SceneGraph/Media/Geometry.cs

@ -36,7 +36,7 @@ namespace Perspex.Media
/// <summary> /// <summary>
/// Gets the platform-specific implementation of the geometry. /// Gets the platform-specific implementation of the geometry.
/// </summary> /// </summary>
public IGeometryImpl PlatformImpl public virtual IGeometryImpl PlatformImpl
{ {
get; get;
protected set; protected set;

31
src/Perspex.SceneGraph/Media/LineSegment.cs

@ -0,0 +1,31 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Perspex.Media
{
public sealed class LineSegment : PathSegment
{
/// <summary>
/// Defines the <see cref="Point"/> property.
/// </summary>
public static readonly StyledProperty<Point> PointProperty
= PerspexProperty.Register<LineSegment, Point>(nameof(Point));
/// <summary>
/// Gets or sets the point.
/// </summary>
/// <value>
/// The point.
/// </value>
public Point Point
{
get { return GetValue(PointProperty); }
set { SetValue(PointProperty, value); }
}
protected internal override void ApplyTo(StreamGeometryContext ctx)
{
ctx.LineTo(Point);
}
}
}

102
src/Perspex.SceneGraph/Media/PathFigure.cs

@ -0,0 +1,102 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Perspex.Metadata;
namespace Perspex.Media
{
public sealed class PathFigure : PerspexObject
{
/// <summary>
/// Defines the <see cref="IsClosed"/> property.
/// </summary>
public static readonly StyledProperty<bool> IsClosedProperty
= PerspexProperty.Register<PathFigure, bool>(nameof(IsClosed), true);
/// <summary>
/// Defines the <see cref="IsFilled"/> property.
/// </summary>
public static readonly StyledProperty<bool> IsFilledProperty
= PerspexProperty.Register<PathFigure, bool>(nameof(IsFilled), true);
/// <summary>
/// Defines the <see cref="Segments"/> property.
/// </summary>
public static readonly DirectProperty<PathFigure, PathSegments> SegmentsProperty
= PerspexProperty.RegisterDirect<PathFigure, PathSegments>(nameof(Segments), f => f.Segments, (f, s) => f.Segments = s);
/// <summary>
/// Defines the <see cref="StartPoint"/> property.
/// </summary>
public static readonly StyledProperty<Point> StartPointProperty
= PerspexProperty.Register<PathFigure, Point>(nameof(StartPoint));
/// <summary>
/// Initializes a new instance of the <see cref="PathFigure"/> class.
/// </summary>
public PathFigure()
{
Segments = new PathSegments();
}
/// <summary>
/// Gets or sets a value indicating whether this instance is closed.
/// </summary>
/// <value>
/// <c>true</c> if this instance is closed; otherwise, <c>false</c>.
/// </value>
public bool IsClosed
{
get { return GetValue(IsClosedProperty); }
set { SetValue(IsClosedProperty, value); }
}
/// <summary>
/// Gets or sets a value indicating whether this instance is filled.
/// </summary>
/// <value>
/// <c>true</c> if this instance is filled; otherwise, <c>false</c>.
/// </value>
public bool IsFilled
{
get { return GetValue(IsFilledProperty); }
set { SetValue(IsFilledProperty, value); }
}
/// <summary>
/// Gets or sets the segments.
/// </summary>
/// <value>
/// The segments.
/// </value>
[Content]
public PathSegments Segments
{
get { return _segments; }
set { SetAndRaise(SegmentsProperty, ref _segments, value); }
}
/// <summary>
/// Gets or sets the start point.
/// </summary>
/// <value>
/// The start point.
/// </value>
public Point StartPoint
{
get { return GetValue(StartPointProperty); }
set { SetValue(StartPointProperty, value); }
}
internal void ApplyTo(StreamGeometryContext ctx)
{
ctx.BeginFigure(StartPoint, IsFilled);
foreach (var segment in Segments)
{
segment.ApplyTo(ctx);
}
ctx.EndFigure(IsClosed);
}
private PathSegments _segments;
}
}

123
src/Perspex.SceneGraph/Media/PathGeometry.cs

@ -0,0 +1,123 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Perspex.Collections;
using Perspex.Metadata;
using Perspex.Platform;
using System;
namespace Perspex.Media
{
public class PathGeometry : StreamGeometry
{
/// <summary>
/// Defines the <see cref="Figures"/> property.
/// </summary>
public static readonly DirectProperty<PathGeometry, PathFigures> FiguresProperty =
PerspexProperty.RegisterDirect<PathGeometry, PathFigures>(nameof(Figures), g => g.Figures, (g, f) => g.Figures = f);
/// <summary>
/// Defines the <see cref="FillRule"/> property.
/// </summary>
public static readonly StyledProperty<FillRule> FillRuleProperty =
PerspexProperty.Register<PathGeometry, FillRule>(nameof(FillRule));
static PathGeometry()
{
FiguresProperty.Changed.Subscribe(onNext: v =>
{
(v.Sender as PathGeometry)?.OnFiguresChanged(v.OldValue as PathFigures, v.NewValue as PathFigures);
});
}
/// <summary>
/// Initializes a new instance of the <see cref="PathGeometry"/> class.
/// </summary>
public PathGeometry()
{
Figures = new PathFigures();
}
/// <summary>
/// Gets or sets the figures.
/// </summary>
/// <value>
/// The figures.
/// </value>
[Content]
public PathFigures Figures
{
get { return _figures; }
set { SetAndRaise(FiguresProperty, ref _figures, value); }
}
/// <summary>
/// Gets or sets the fill rule.
/// </summary>
/// <value>
/// The fill rule.
/// </value>
public FillRule FillRule
{
get { return GetValue(FillRuleProperty); }
set { SetValue(FillRuleProperty, value); }
}
public override IGeometryImpl PlatformImpl
{
get
{
PrepareIfNeeded();
return base.PlatformImpl;
}
protected set
{
base.PlatformImpl = value;
}
}
public override Geometry Clone()
{
PrepareIfNeeded();
return base.Clone();
}
public void PrepareIfNeeded()
{
if (_isDirty)
{
_isDirty = false;
using (var ctx = Open())
{
ctx.SetFillRule(FillRule);
foreach (var f in Figures)
{
f.ApplyTo(ctx);
}
}
}
}
internal void NotifyChanged()
{
_isDirty = true;
}
private PathFigures _figures;
private IDisposable _figuresObserver = null;
private IDisposable _figuresPropertiesObserver = null;
private bool _isDirty = true;
private void OnFiguresChanged(PathFigures oldValue, PathFigures newValue)
{
_figuresObserver?.Dispose();
_figuresPropertiesObserver?.Dispose();
_figuresObserver = newValue?.ForEachItem(f => NotifyChanged(), f => NotifyChanged(), () => NotifyChanged());
_figuresPropertiesObserver = newValue?.TrackItemPropertyChanged(t => NotifyChanged());
}
}
}

15
src/Perspex.SceneGraph/Media/PathGeometryCollections.cs

@ -0,0 +1,15 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Perspex.Collections;
namespace Perspex.Media
{
public sealed class PathFigures : PerspexList<PathFigure>
{
}
public sealed class PathSegments : PerspexList<PathSegment>
{
}
}

10
src/Perspex.SceneGraph/Media/PathSegment.cs

@ -0,0 +1,10 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Perspex.Media
{
public abstract class PathSegment : PerspexObject
{
protected internal abstract void ApplyTo(StreamGeometryContext ctx);
}
}

46
src/Perspex.SceneGraph/Media/QuadraticBezierSegment .cs

@ -0,0 +1,46 @@
namespace Perspex.Media
{
public sealed class QuadraticBezierSegment : PathSegment
{
/// <summary>
/// Defines the <see cref="Point1"/> property.
/// </summary>
public static readonly StyledProperty<Point> Point1Property
= PerspexProperty.Register<QuadraticBezierSegment, Point>(nameof(Point1));
/// <summary>
/// Defines the <see cref="Point2"/> property.
/// </summary>
public static readonly StyledProperty<Point> Point2Property
= PerspexProperty.Register<QuadraticBezierSegment, Point>(nameof(Point2));
/// <summary>
/// Gets or sets the point1.
/// </summary>
/// <value>
/// The point1.
/// </value>
public Point Point1
{
get { return GetValue(Point1Property); }
set { SetValue(Point1Property, value); }
}
/// <summary>
/// Gets or sets the point2.
/// </summary>
/// <value>
/// The point2.
/// </value>
public Point Point2
{
get { return GetValue(Point2Property); }
set { SetValue(Point2Property, value); }
}
protected internal override void ApplyTo(StreamGeometryContext ctx)
{
ctx.QuadraticBezierTo(Point1, Point2);
}
}
}

57
src/Perspex.SceneGraph/Media/TransformGroup.cs

@ -0,0 +1,57 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Perspex.Collections;
using Perspex.Metadata;
namespace Perspex.Media
{
public class TransformGroup : Transform
{
/// <summary>
/// Defines the <see cref="Children"/> property.
/// </summary>
public static readonly PerspexProperty<Transforms> ChildrenProperty =
PerspexProperty.Register<TransformGroup, Transforms>(nameof(Children));
public TransformGroup()
{
Children = new Transforms();
}
/// <summary>
/// Gets or sets the children.
/// </summary>
/// <value>
/// The children.
/// </value>
[Content]
public Transforms Children
{
get { return GetValue(ChildrenProperty); }
set { SetValue(ChildrenProperty, value); }
}
/// <summary>
/// Gets the tranform's <see cref="Matrix" />.
/// </summary>
public override Matrix Value
{
get
{
Matrix result = Matrix.Identity;
foreach (var t in Children)
{
result *= t.Value;
}
return result;
}
}
}
public sealed class Transforms : PerspexList<Transform>
{
}
}

9
src/Perspex.SceneGraph/Perspex.SceneGraph.csproj

@ -61,11 +61,14 @@
<Compile Include="Matrix.cs" /> <Compile Include="Matrix.cs" />
<Compile Include="Media\AlignmentY.cs" /> <Compile Include="Media\AlignmentY.cs" />
<Compile Include="Media\AlignmentX.cs" /> <Compile Include="Media\AlignmentX.cs" />
<Compile Include="Media\ArcSegment.cs" />
<Compile Include="Media\BezierSegment .cs" />
<Compile Include="Media\Brush.cs" /> <Compile Include="Media\Brush.cs" />
<Compile Include="Media\Brushes.cs" /> <Compile Include="Media\Brushes.cs" />
<Compile Include="Media\BrushMappingMode.cs" /> <Compile Include="Media\BrushMappingMode.cs" />
<Compile Include="Media\Color.cs" /> <Compile Include="Media\Color.cs" />
<Compile Include="Media\Colors.cs" /> <Compile Include="Media\Colors.cs" />
<Compile Include="Media\TransformGroup.cs" />
<Compile Include="Media\DashStyle.cs" /> <Compile Include="Media\DashStyle.cs" />
<Compile Include="Media\DrawingContext.cs" /> <Compile Include="Media\DrawingContext.cs" />
<Compile Include="Media\FillRule.cs" /> <Compile Include="Media\FillRule.cs" />
@ -75,9 +78,15 @@
<Compile Include="Media\IBrush.cs" /> <Compile Include="Media\IBrush.cs" />
<Compile Include="Media\ISolidColorBrush.cs" /> <Compile Include="Media\ISolidColorBrush.cs" />
<Compile Include="Media\LineGeometry.cs" /> <Compile Include="Media\LineGeometry.cs" />
<Compile Include="Media\LineSegment.cs" />
<Compile Include="Media\Mutable\SolidColorBrush.cs" /> <Compile Include="Media\Mutable\SolidColorBrush.cs" />
<Compile Include="Media\PathGeometryCollections.cs" />
<Compile Include="Media\PathFigure.cs" />
<Compile Include="Media\PathGeometry.cs" />
<Compile Include="Media\PathSegment.cs" />
<Compile Include="Media\PenLineJoin.cs" /> <Compile Include="Media\PenLineJoin.cs" />
<Compile Include="Media\PolylineGeometry.cs" /> <Compile Include="Media\PolylineGeometry.cs" />
<Compile Include="Media\QuadraticBezierSegment .cs" />
<Compile Include="Media\RadialGradientBrush.cs" /> <Compile Include="Media\RadialGradientBrush.cs" />
<Compile Include="Media\LinearGradientBrush.cs" /> <Compile Include="Media\LinearGradientBrush.cs" />
<Compile Include="Media\MediaExtensions.cs" /> <Compile Include="Media\MediaExtensions.cs" />

25
src/Perspex.SceneGraph/Size.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Linq;
namespace Perspex namespace Perspex
{ {
@ -128,6 +129,28 @@ namespace Perspex
return new Size(size._width - toSubstract._width, size._height - toSubstract._height); return new Size(size._width - toSubstract._width, size._height - toSubstract._height);
} }
/// <summary>
/// Parses a <see cref="Size"/> string.
/// </summary>
/// <param name="s">The string.</param>
/// <param name="culture">The current culture.</param>
/// <returns>The <see cref="Size"/>.</returns>
public static Size Parse(string s, CultureInfo culture)
{
var parts = s.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Trim())
.ToList();
if (parts.Count == 2)
{
return new Size(double.Parse(parts[0], culture), double.Parse(parts[1], culture));
}
else
{
throw new FormatException("Invalid Size.");
}
}
/// <summary> /// <summary>
/// Constrains the size. /// Constrains the size.
/// </summary> /// </summary>
@ -227,4 +250,4 @@ namespace Perspex
return string.Format(CultureInfo.InvariantCulture, "{0}, {1}", _width, _height); return string.Format(CultureInfo.InvariantCulture, "{0}, {1}", _width, _height);
} }
} }
} }

187
src/Shared/PlatformSupport/AssetLoader.cs

@ -15,26 +15,6 @@ namespace Perspex.Shared.PlatformSupport
/// </summary> /// </summary>
public class AssetLoader : IAssetLoader public class AssetLoader : IAssetLoader
{ {
class AssemblyDescriptor
{
public AssemblyDescriptor(Assembly assembly)
{
Assembly = assembly;
if (assembly != null)
{
Resources = assembly.GetManifestResourceNames()
.ToDictionary(n => n, n => (IAssetDescriptor)new AssemblyResourceDescriptor(assembly, n));
Name = assembly.GetName().Name;
}
}
public Assembly Assembly { get; }
public Dictionary<string, IAssetDescriptor> Resources { get; }
public string Name { get; }
}
private static readonly Dictionary<string, AssemblyDescriptor> AssemblyNameCache private static readonly Dictionary<string, AssemblyDescriptor> AssemblyNameCache
= new Dictionary<string, AssemblyDescriptor>(); = new Dictionary<string, AssemblyDescriptor>();
@ -53,7 +33,94 @@ namespace Perspex.Shared.PlatformSupport
_defaultAssembly = new AssemblyDescriptor(assembly); _defaultAssembly = new AssemblyDescriptor(assembly);
} }
AssemblyDescriptor GetAssembly(string name) /// <summary>
/// Checks if an asset with the specified URI exists.
/// </summary>
/// <param name="uri">The URI.</param>
/// <param name="baseUri">
/// A base URI to use if <paramref name="uri"/> is relative.
/// </param>
/// <returns>True if the asset could be found; otherwise false.</returns>
public bool Exists(Uri uri, Uri baseUri = null)
{
return GetAsset(uri, baseUri) != null;
}
/// <summary>
/// Opens the resource with the requested URI.
/// </summary>
/// <param name="uri">The URI.</param>
/// <param name="baseUri">
/// A base URI to use if <paramref name="uri"/> is relative.
/// </param>
/// <returns>A stream containing the resource contents.</returns>
/// <exception cref="FileNotFoundException">
/// The resource was not found.
/// </exception>
public Stream Open(Uri uri, Uri baseUri = null)
{
var asset = GetAsset(uri, baseUri);
if (asset == null)
{
throw new FileNotFoundException($"The resource {uri} could not be found.");
}
return asset.GetStream();
}
private IAssetDescriptor GetAsset(Uri uri, Uri baseUri)
{
if (!uri.IsAbsoluteUri || uri.Scheme == "resm")
{
var uriQueryParams = ParseQueryString(uri);
var baseUriQueryParams = uri != null ? ParseQueryString(uri) : null;
var asm = GetAssembly(uri) ?? GetAssembly(baseUri) ?? _defaultAssembly;
if (asm == null && _defaultAssembly == null)
{
throw new ArgumentException(
"No default assembly, entry assembly or explicit assembly specified; " +
"don't know where to look up for the resource, try specifiyng assembly explicitly.");
}
IAssetDescriptor rv;
var resourceKey = uri.AbsolutePath;
#if __IOS__
// TODO: HACK: to get iOS up and running. Using Shared projects for resources
// is flawed as this alters the reource key locations across platforms
// I think we need to use Portable libraries from now on to avoid that.
if(asm.Name.Contains("iOS"))
{
resourceKey = resourceKey.Replace("TestApplication", "Perspex.iOSTestApplication");
}
#endif
asm.Resources.TryGetValue(resourceKey, out rv);
return rv;
}
throw new ArgumentException($"Invalid uri, see https://github.com/Perspex/Perspex/issues/282#issuecomment-166982104", nameof(uri));
}
private AssemblyDescriptor GetAssembly(Uri uri)
{
if (uri != null)
{
var qs = ParseQueryString(uri);
string assemblyName;
if (qs.TryGetValue("assembly", out assemblyName))
{
return GetAssembly(assemblyName);
}
}
return null;
}
private AssemblyDescriptor GetAssembly(string name)
{ {
if (name == null) if (name == null)
{ {
@ -82,13 +149,20 @@ namespace Perspex.Shared.PlatformSupport
return rv; return rv;
} }
interface IAssetDescriptor private Dictionary<string, string> ParseQueryString(Uri uri)
{ {
Stream GetStream(); return uri.Query.TrimStart('?')
.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries)
.Select(p => p.Split('='))
.ToDictionary(p => p[0], p => p[1]);
} }
private interface IAssetDescriptor
{
Stream GetStream();
}
class AssemblyResourceDescriptor : IAssetDescriptor private class AssemblyResourceDescriptor : IAssetDescriptor
{ {
private readonly Assembly _asm; private readonly Assembly _asm;
private readonly string _name; private readonly string _name;
@ -104,69 +178,24 @@ namespace Perspex.Shared.PlatformSupport
return _asm.GetManifestResourceStream(_name); return _asm.GetManifestResourceStream(_name);
} }
} }
IAssetDescriptor GetAsset(Uri uri) private class AssemblyDescriptor
{ {
if (!uri.IsAbsoluteUri || uri.Scheme == "resm") public AssemblyDescriptor(Assembly assembly)
{ {
var qs = uri.Query.TrimStart('?') Assembly = assembly;
.Split(new[] {'&'}, StringSplitOptions.RemoveEmptyEntries)
.Select(p => p.Split('='))
.ToDictionary(p => p[0], p => p[1]);
//TODO: Replace _defaultAssembly by current one (need support from OmniXAML)
var asm = _defaultAssembly;
if (qs.ContainsKey("assembly"))
asm = GetAssembly(qs["assembly"]);
if (asm == null && _defaultAssembly == null)
throw new ArgumentException(
"No defaultAssembly, entry assembly or explicit assembly specified, don't know where to look up for the resource, try specifiyng assembly explicitly");
IAssetDescriptor rv;
var resourceKey = uri.AbsolutePath;
#if __IOS__ if (assembly != null)
// TODO: HACK: to get iOS up and running. Using Shared projects for resources
// is flawed as this alters the reource key locations across platforms
// I think we need to use Portable libraries from now on to avoid that.
if(asm.Name.Contains("iOS"))
{ {
resourceKey = resourceKey.Replace("TestApplication", "Perspex.iOSTestApplication"); Resources = assembly.GetManifestResourceNames()
.ToDictionary(n => n, n => (IAssetDescriptor)new AssemblyResourceDescriptor(assembly, n));
Name = assembly.GetName().Name;
} }
#endif
asm.Resources.TryGetValue(resourceKey, out rv);
return rv;
} }
throw new ArgumentException($"Invalid uri, see https://github.com/Perspex/Perspex/issues/282#issuecomment-166982104", nameof(uri));
}
/// <summary>
/// Checks if an asset with the specified URI exists.
/// </summary>
/// <param name="uri">The URI.</param>
/// <returns>True if the asset could be found; otherwise false.</returns>
public bool Exists(Uri uri)
{
return GetAsset(uri) != null;
}
/// <summary> public Assembly Assembly { get; }
/// Opens the resource with the requested URI. public Dictionary<string, IAssetDescriptor> Resources { get; }
/// </summary> public string Name { get; }
/// <param name="uri">The URI.</param>
/// <returns>A stream containing the resource contents.</returns>
/// <exception cref="FileNotFoundException">
/// The resource was not found.
/// </exception>
public Stream Open(Uri uri)
{
var asset = GetAsset(uri);
if (asset == null)
throw new FileNotFoundException($"The resource {uri} could not be found.");
return asset.GetStream();
} }
} }
} }

2
src/Skia/Perspex.Skia.Android.TestApp/Perspex.Skia.Android.TestApp.csproj

@ -15,7 +15,7 @@
<AndroidApplication>true</AndroidApplication> <AndroidApplication>true</AndroidApplication>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile> <AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies> <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk> <AndroidUseLatestPlatformSdk>False</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion> <TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest> <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
</PropertyGroup> </PropertyGroup>

4
src/Skia/Perspex.Skia.Android/Perspex.Skia.Android.csproj

@ -14,7 +14,7 @@
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile> <AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies> <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk> <AndroidUseLatestPlatformSdk>False</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion> <TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@ -40,7 +40,7 @@
<Reference Include="Mono.Android" /> <Reference Include="Mono.Android" />
<Reference Include="mscorlib" /> <Reference Include="mscorlib" />
<Reference Include="SkiaSharp, Version=1.49.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SkiaSharp, Version=1.49.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\SkiaSharp.1.49.2.0-beta\lib\MonoAndroid\SkiaSharp.dll</HintPath> <HintPath>..\..\..\packages\SkiaSharp.1.49.2.1-beta\lib\MonoAndroid\SkiaSharp.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />

2
src/Skia/Perspex.Skia.Android/packages.config

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="SkiaSharp" version="1.49.2.0-beta" targetFramework="monoandroid60" /> <package id="SkiaSharp" version="1.49.2.1-beta" targetFramework="monoandroid50" />
</packages> </packages>

6
src/Skia/Perspex.Skia.Desktop/Perspex.Skia.Desktop.csproj

@ -57,7 +57,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="SkiaSharp, Version=1.49.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SkiaSharp, Version=1.49.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\SkiaSharp.1.49.2.0-beta\lib\net45\SkiaSharp.dll</HintPath> <HintPath>..\..\..\packages\SkiaSharp.1.49.2.1-beta\lib\net45\SkiaSharp.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
@ -116,12 +116,12 @@
<Import Project="..\Perspex.Skia\Perspex.Skia.projitems" Label="Shared" /> <Import Project="..\Perspex.Skia\Perspex.Skia.projitems" Label="Shared" />
<Import Project="..\..\Shared\RenderHelpers\RenderHelpers.projitems" Label="Shared" /> <Import Project="..\..\Shared\RenderHelpers\RenderHelpers.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\..\packages\SkiaSharp.1.49.2.0-beta\build\net45\SkiaSharp.targets" Condition="Exists('..\..\..\packages\SkiaSharp.1.49.2.0-beta\build\net45\SkiaSharp.targets')" /> <Import Project="..\..\..\packages\SkiaSharp.1.49.2.1-beta\build\net45\SkiaSharp.targets" Condition="Exists('..\..\..\packages\SkiaSharp.1.49.2.1-beta\build\net45\SkiaSharp.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\SkiaSharp.1.49.2.0-beta\build\net45\SkiaSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\SkiaSharp.1.49.2.0-beta\build\net45\SkiaSharp.targets'))" /> <Error Condition="!Exists('..\..\..\packages\SkiaSharp.1.49.2.1-beta\build\net45\SkiaSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\SkiaSharp.1.49.2.1-beta\build\net45\SkiaSharp.targets'))" />
</Target> </Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

2
src/Skia/Perspex.Skia.Desktop/packages.config

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="SkiaSharp" version="1.49.2.0-beta" targetFramework="net45" /> <package id="SkiaSharp" version="1.49.2.1-beta" targetFramework="net45" />
</packages> </packages>

2
src/Skia/Perspex.Skia.iOS/Perspex.Skia.iOS.csproj

@ -41,7 +41,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="SkiaSharp, Version=1.49.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SkiaSharp, Version=1.49.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\SkiaSharp.1.49.2.0-beta\lib\XamariniOS\SkiaSharp.dll</HintPath> <HintPath>..\..\..\packages\SkiaSharp.1.49.2.1-beta\lib\XamariniOS\SkiaSharp.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />

2
src/Skia/Perspex.Skia.iOS/packages.config

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="SkiaSharp" version="1.49.2.0-beta" targetFramework="xamarinios10" /> <package id="SkiaSharp" version="1.49.2.1-beta" targetFramework="xamarinios10" />
</packages> </packages>

10
src/Skia/Perspex.Skia/DrawingContextImpl.cs

@ -229,10 +229,7 @@ namespace Perspex.Skia
} }
else else
{ {
// TODO: DrawRRect (ore DrawRoundedRect) is not accesible in SkiaSharp yet. We should add that Canvas.DrawRoundRect(rc, cornerRadius, cornerRadius, paint.Paint);
// to SkiaSharp and initiate a PR....
Canvas.DrawRect(rc, paint.Paint);
//Canvas.DrawRoundedRect(rc, cornerRadius, cornerRadius, paint);
} }
} }
} }
@ -248,10 +245,7 @@ namespace Perspex.Skia
} }
else else
{ {
// TODO: this does not exist in SkiaSharp yet Canvas.DrawRoundRect(rc, cornerRadius, cornerRadius, paint.Paint);
//throw new NotImplementedException();
//Canvas.DrawRoundedRect(rc, cornerRadius, cornerRadius, paint);
Canvas.DrawRect(rc, paint.Paint);
} }
} }
} }

5
src/Skia/Perspex.Skia/SkiaSharpExtensions.cs

@ -65,5 +65,10 @@ namespace Perspex.Skia
case TextAlignment.Right: return SKTextAlign.Right; case TextAlignment.Right: return SKTextAlign.Right;
} }
} }
public static SKPath Clone(this SKPath src)
{
return src != null ? new SKPath(src) : null;
}
} }
} }

40
src/Skia/Perspex.Skia/StreamGeometryImpl.cs

@ -50,28 +50,23 @@ namespace Perspex.Skia
_transformedPath.Dispose(); _transformedPath.Dispose();
_transformedPath = null; _transformedPath = null;
} }
// TODO: SkiaSharp does not expose Transform yet!!! if (!Transform.IsIdentity)
//if (!Transform.IsIdentity) {
//{ _transformedPath = new SKPath(_path);
// _transformedPath = new SKPath(); _transformedPath.Transform(Transform.ToSKMatrix());
// _path.Transform(Transform.ToSKMatrix(), _transformedPath); }
//}
} }
public IStreamGeometryImpl Clone() public IStreamGeometryImpl Clone()
{ {
// TODO: there is no SKPath.Clone yet!!!!!!!!!!!!! return new StreamGeometryImpl
// {
//return new StreamGeometryImpl _path = _path?.Clone(),
//{ _transformedPath = _transformedPath?.Clone(),
// _path = _path?.Clone(), _transform = Transform,
// _transformedPath = _transformedPath?.Clone(), Bounds = Bounds
// _transform = Transform, };
// Bounds = Bounds
//};
return this; // this will probably end bad!!
} }
public IStreamGeometryContextImpl Open() public IStreamGeometryContextImpl Open()
@ -94,15 +89,6 @@ namespace Perspex.Skia
public void Dispose() public void Dispose()
{ {
// TODO: Not sure what we need to do here. This code left here for reference.
//
// var arr = _elements.ToArray();
// SkRect rc;
// _path?.Dispose();
// _path = new SKPath(new SkPath(MethodTable.Instance.CreatePath(arr, arr.Length, out rc)));
// _geometryImpl.ApplyTransform();
// _geometryImpl.Bounds = rc.ToRect();
SKRect rc; SKRect rc;
_path.GetBounds(out rc); _path.GetBounds(out rc);
_geometryImpl.ApplyTransform(); _geometryImpl.ApplyTransform();

7
src/Skia/Perspex.Skia/readme.md

@ -5,7 +5,6 @@ BitmapImpl
- Save - Save
DrawingContextImpl DrawingContextImpl
- DrawRoundRect is not properly implemented due to lack of support in SkiaSharp
- Alpha support missing as SkiaSharp does not expose this - Alpha support missing as SkiaSharp does not expose this
- Gradient Shader caching? - Gradient Shader caching?
- TileBrushes - TileBrushes
@ -18,12 +17,6 @@ RenderTarget
- Figure out a cleaner implementation across all platforms - Figure out a cleaner implementation across all platforms
- HW acceleration - HW acceleration
StreamGeometry
- Paths within Paths may not work right
- Paths cannot be Cloned (lack of SkiaSupport)
- Paths cannot be transformed (lack of SkiaSupport)
- ArcTo
App Bootstrapping App Bootstrapping
- Cleanup the testapplications across all platforms - Cleanup the testapplications across all platforms
- Add a cleaner Fluent API for the subsystems - Add a cleaner Fluent API for the subsystems

7
src/Windows/Perspex.Direct2D1/Media/StreamGeometryContextImpl.cs

@ -5,6 +5,7 @@ using Perspex.Media;
using Perspex.Platform; using Perspex.Platform;
using SharpDX.Direct2D1; using SharpDX.Direct2D1;
using SweepDirection = SharpDX.Direct2D1.SweepDirection; using SweepDirection = SharpDX.Direct2D1.SweepDirection;
using D2D = SharpDX.Direct2D1;
namespace Perspex.Direct2D1.Media namespace Perspex.Direct2D1.Media
{ {
@ -24,7 +25,7 @@ namespace Perspex.Direct2D1.Media
bool isLargeArc, bool isLargeArc,
Perspex.Media.SweepDirection sweepDirection) Perspex.Media.SweepDirection sweepDirection)
{ {
_sink.AddArc(new ArcSegment _sink.AddArc(new D2D.ArcSegment
{ {
Point = point.ToSharpDX(), Point = point.ToSharpDX(),
Size = size.ToSharpDX(), Size = size.ToSharpDX(),
@ -41,7 +42,7 @@ namespace Perspex.Direct2D1.Media
public void CubicBezierTo(Point point1, Point point2, Point point3) public void CubicBezierTo(Point point1, Point point2, Point point3)
{ {
_sink.AddBezier(new BezierSegment _sink.AddBezier(new D2D.BezierSegment
{ {
Point1 = point1.ToSharpDX(), Point1 = point1.ToSharpDX(),
Point2 = point2.ToSharpDX(), Point2 = point2.ToSharpDX(),
@ -51,7 +52,7 @@ namespace Perspex.Direct2D1.Media
public void QuadraticBezierTo(Point control, Point dest) public void QuadraticBezierTo(Point control, Point dest)
{ {
_sink.AddQuadraticBezier(new QuadraticBezierSegment _sink.AddQuadraticBezier(new D2D.QuadraticBezierSegment
{ {
Point1 = control.ToSharpDX(), Point1 = control.ToSharpDX(),
Point2 = dest.ToSharpDX() Point2 = dest.ToSharpDX()

1
src/Windows/Perspex.Direct2D1/Media/StreamGeometryImpl.cs

@ -1,7 +1,6 @@
// Copyright (c) The Perspex Project. All rights reserved. // Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using Perspex.Media;
using Perspex.Platform; using Perspex.Platform;
using SharpDX.Direct2D1; using SharpDX.Direct2D1;
using D2DGeometry = SharpDX.Direct2D1.Geometry; using D2DGeometry = SharpDX.Direct2D1.Geometry;

Loading…
Cancel
Save