@ -0,0 +1,11 @@ |
|||
; This file is for unifying the coding style for different editors and IDEs. |
|||
; More information at http://EditorConfig.org |
|||
|
|||
root = true |
|||
|
|||
[*] |
|||
end_of_line = CRLF |
|||
|
|||
[*.cs] |
|||
indent_style = space |
|||
indent_size = 4 |
|||
@ -0,0 +1,63 @@ |
|||
// 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 Moq; |
|||
using OmniXaml; |
|||
using OmniXaml.TypeConversion; |
|||
using OmniXaml.Typing; |
|||
using Perspex.Markup.Xaml.Converters; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Markup.Xaml.UnitTests.Converters |
|||
{ |
|||
public class PerspexPropertyConverterTest |
|||
{ |
|||
public PerspexPropertyConverterTest() |
|||
{ |
|||
// Ensure properties are registered.
|
|||
var foo = Class1.FooProperty; |
|||
var attached = AttachedOwner.AttachedProperty; |
|||
} |
|||
|
|||
[Fact] |
|||
public void ConvertFrom_Finds_Fully_Qualified_Property() |
|||
{ |
|||
var target = new PerspexPropertyTypeConverter(); |
|||
var context = CreateContext(); |
|||
var result = target.ConvertFrom(context, null, "Class1.Foo"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ConvertFrom_Finds_Attached_Property() |
|||
{ |
|||
var target = new PerspexPropertyTypeConverter(); |
|||
var context = CreateContext(); |
|||
var result = target.ConvertFrom(context, null, "AttachedOwner.Attached"); |
|||
} |
|||
|
|||
private IXamlTypeConverterContext CreateContext() |
|||
{ |
|||
var context = new Mock<IXamlTypeConverterContext>(); |
|||
var typeRepository = new Mock<IXamlTypeRepository>(); |
|||
var featureProvider = new Mock<ITypeFeatureProvider>(); |
|||
var class1XamlType = new XamlType(typeof(Class1), typeRepository.Object, null, featureProvider.Object); |
|||
var attachedOwnerXamlType = new XamlType(typeof(AttachedOwner), typeRepository.Object, null, featureProvider.Object); |
|||
context.Setup(x => x.TypeRepository).Returns(typeRepository.Object); |
|||
typeRepository.Setup(x => x.GetByQualifiedName("Class1")).Returns(class1XamlType); |
|||
typeRepository.Setup(x => x.GetByQualifiedName("AttachedOwner")).Returns(attachedOwnerXamlType); |
|||
return context.Object; |
|||
} |
|||
|
|||
private class Class1 : PerspexObject |
|||
{ |
|||
public static readonly PerspexProperty<string> FooProperty = |
|||
PerspexProperty.Register<Class1, string>("Foo"); |
|||
} |
|||
|
|||
private class AttachedOwner |
|||
{ |
|||
public static readonly PerspexProperty<string> AttachedProperty = |
|||
PerspexProperty.RegisterAttached<AttachedOwner, Class1, string>("Attached"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,189 @@ |
|||
// 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.Linq; |
|||
using Perspex.Markup.Xaml.Parsers; |
|||
using Sprache; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Xaml.Base.UnitTest.Parsers |
|||
{ |
|||
public class SelectorGrammarTests |
|||
{ |
|||
[Fact] |
|||
public void OfType() |
|||
{ |
|||
var result = SelectorGrammar.Selector.Parse("Button").ToList(); |
|||
|
|||
Assert.Equal( |
|||
new[] { new SelectorGrammar.OfTypeSyntax { TypeName = "Button", Xmlns = null } }, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void NamespacedOfType() |
|||
{ |
|||
var result = SelectorGrammar.Selector.Parse("x|Button").ToList(); |
|||
|
|||
Assert.Equal( |
|||
new[] { new SelectorGrammar.OfTypeSyntax { TypeName = "Button", Xmlns = "x" } }, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Name() |
|||
{ |
|||
var result = SelectorGrammar.Selector.Parse("#foo").ToList(); |
|||
|
|||
Assert.Equal( |
|||
new[] { new SelectorGrammar.NameSyntax { Name = "foo" }, }, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void OfType_Name() |
|||
{ |
|||
var result = SelectorGrammar.Selector.Parse("Button#foo").ToList(); |
|||
|
|||
Assert.Equal( |
|||
new SelectorGrammar.ISyntax[] |
|||
{ |
|||
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, |
|||
new SelectorGrammar.NameSyntax { Name = "foo" }, |
|||
}, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Class() |
|||
{ |
|||
var result = SelectorGrammar.Selector.Parse(".foo").ToList(); |
|||
|
|||
Assert.Equal( |
|||
new[] { new SelectorGrammar.ClassSyntax { Class = "foo" } }, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Pseudoclass() |
|||
{ |
|||
var result = SelectorGrammar.Selector.Parse(":foo").ToList(); |
|||
|
|||
Assert.Equal( |
|||
new[] { new SelectorGrammar.ClassSyntax { Class = ":foo" } }, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void OfType_Class() |
|||
{ |
|||
var result = SelectorGrammar.Selector.Parse("Button.foo").ToList(); |
|||
|
|||
Assert.Equal( |
|||
new SelectorGrammar.ISyntax[] |
|||
{ |
|||
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, |
|||
new SelectorGrammar.ClassSyntax { Class = "foo" }, |
|||
}, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void OfType_Child_Class() |
|||
{ |
|||
var result = SelectorGrammar.Selector.Parse("Button < .foo").ToList(); |
|||
|
|||
Assert.Equal( |
|||
new SelectorGrammar.ISyntax[] |
|||
{ |
|||
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, |
|||
new SelectorGrammar.ChildSyntax { }, |
|||
new SelectorGrammar.ClassSyntax { Class = "foo" }, |
|||
}, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void OfType_Child_Class_No_Spaces() |
|||
{ |
|||
var result = SelectorGrammar.Selector.Parse("Button<.foo").ToList(); |
|||
|
|||
Assert.Equal( |
|||
new SelectorGrammar.ISyntax[] |
|||
{ |
|||
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, |
|||
new SelectorGrammar.ChildSyntax { }, |
|||
new SelectorGrammar.ClassSyntax { Class = "foo" }, |
|||
}, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void OfType_Descendent_Class() |
|||
{ |
|||
var result = SelectorGrammar.Selector.Parse("Button .foo").ToList(); |
|||
|
|||
Assert.Equal( |
|||
new SelectorGrammar.ISyntax[] |
|||
{ |
|||
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, |
|||
new SelectorGrammar.DescendentSyntax { }, |
|||
new SelectorGrammar.ClassSyntax { Class = "foo" }, |
|||
}, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void OfType_Template_Class() |
|||
{ |
|||
var result = SelectorGrammar.Selector.Parse("Button /template/ .foo").ToList(); |
|||
|
|||
Assert.Equal( |
|||
new SelectorGrammar.ISyntax[] |
|||
{ |
|||
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, |
|||
new SelectorGrammar.TemplateSyntax { }, |
|||
new SelectorGrammar.ClassSyntax { Class = "foo" }, |
|||
}, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void OfType_Property() |
|||
{ |
|||
var result = SelectorGrammar.Selector.Parse("Button[Foo=bar]").ToList(); |
|||
|
|||
Assert.Equal( |
|||
new SelectorGrammar.ISyntax[] |
|||
{ |
|||
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, |
|||
new SelectorGrammar.PropertySyntax { Property = "Foo", Value = "bar" }, |
|||
}, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Namespace_Alone_Fails() |
|||
{ |
|||
Assert.Throws<ParseException>(() => SelectorGrammar.Selector.Parse("ns|").ToList()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Dot_Alone_Fails() |
|||
{ |
|||
Assert.Throws<ParseException>(() => SelectorGrammar.Selector.Parse(". dot").ToList()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Invalid_Identifier_Fails() |
|||
{ |
|||
Assert.Throws<ParseException>(() => SelectorGrammar.Selector.Parse("%foo").ToList()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Invalid_Class_Fails() |
|||
{ |
|||
Assert.Throws<ParseException>(() => SelectorGrammar.Selector.Parse(".%foo").ToList()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,351 @@ |
|||
// 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.Controls; |
|||
using Perspex.Controls.Shapes; |
|||
using Perspex.Layout; |
|||
using Perspex.Media; |
|||
using Perspex.Media.Imaging; |
|||
using Xunit; |
|||
|
|||
#if PERSPEX_CAIRO
|
|||
namespace Perspex.Cairo.RenderTests.Media |
|||
#else
|
|||
namespace Perspex.Direct2D1.RenderTests.Media |
|||
#endif
|
|||
{ |
|||
public class ImageBrushTests : TestBase |
|||
{ |
|||
public ImageBrushTests() |
|||
: base(@"Media\ImageBrush") |
|||
{ |
|||
} |
|||
|
|||
private string BitmapPath |
|||
{ |
|||
get { return System.IO.Path.Combine(OutputPath, "github_icon.png"); } |
|||
} |
|||
|
|||
[Fact] |
|||
public void ImageBrush_NoStretch_NoTile_Alignment_TopLeft() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 200, |
|||
Height = 200, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.None, |
|||
TileMode = TileMode.None, |
|||
AlignmentX = AlignmentX.Left, |
|||
AlignmentY = AlignmentY.Top, |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ImageBrush_NoStretch_NoTile_Alignment_Center() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 200, |
|||
Height = 200, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.None, |
|||
TileMode = TileMode.None, |
|||
AlignmentX = AlignmentX.Center, |
|||
AlignmentY = AlignmentY.Center, |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ImageBrush_NoStretch_NoTile_Alignment_BottomRight() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 200, |
|||
Height = 200, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.None, |
|||
TileMode = TileMode.None, |
|||
AlignmentX = AlignmentX.Right, |
|||
AlignmentY = AlignmentY.Bottom, |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ImageBrush_Fill_NoTile() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 920, |
|||
Height = 920, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.Fill, |
|||
TileMode = TileMode.None, |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ImageBrush_Uniform_NoTile() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 300, |
|||
Height = 200, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.Uniform, |
|||
TileMode = TileMode.None, |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ImageBrush_UniformToFill_NoTile() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 300, |
|||
Height = 200, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.UniformToFill, |
|||
TileMode = TileMode.None, |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ImageBrush_NoStretch_NoTile_BottomRightQuarterSource() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 200, |
|||
Height = 200, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.None, |
|||
TileMode = TileMode.None, |
|||
SourceRect = new RelativeRect(250, 250, 250, 250, RelativeUnit.Absolute), |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ImageBrush_NoStretch_NoTile_BottomRightQuarterDest() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 200, |
|||
Height = 200, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.None, |
|||
TileMode = TileMode.None, |
|||
DestinationRect = new RelativeRect(92, 92, 92, 92, RelativeUnit.Absolute), |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 200, |
|||
Height = 200, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.None, |
|||
TileMode = TileMode.None, |
|||
SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative), |
|||
DestinationRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative), |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 200, |
|||
Height = 200, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.None, |
|||
TileMode = TileMode.Tile, |
|||
SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative), |
|||
DestinationRect = new RelativeRect(0.25, 0.25, 0.5, 0.5, RelativeUnit.Relative), |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
|
|||
#if PERSPEX_CAIRO
|
|||
[Fact(Skip = "TileMode.FlipX not yet supported on cairo")] |
|||
#else
|
|||
[Fact] |
|||
#endif
|
|||
public void ImageBrush_NoStretch_FlipX_TopLeftDest() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 200, |
|||
Height = 200, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.None, |
|||
TileMode = TileMode.FlipX, |
|||
DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative), |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
|
|||
#if PERSPEX_CAIRO
|
|||
[Fact(Skip = "TileMode.FlipY not yet supported on cairo")] |
|||
#else
|
|||
[Fact] |
|||
#endif
|
|||
public void ImageBrush_NoStretch_FlipY_TopLeftDest() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 200, |
|||
Height = 200, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.None, |
|||
TileMode = TileMode.FlipY, |
|||
DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative), |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ImageBrush_NoStretch_FlipXY_TopLeftDest() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 200, |
|||
Height = 200, |
|||
Child = new Rectangle |
|||
{ |
|||
Fill = new ImageBrush |
|||
{ |
|||
Stretch = Stretch.None, |
|||
TileMode = TileMode.FlipXY, |
|||
DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative), |
|||
Source = new Bitmap(BitmapPath), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
// 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.Globalization; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.SceneGraph.UnitTests |
|||
{ |
|||
public class RelativePointTests |
|||
{ |
|||
[Fact] |
|||
public void Parse_Should_Accept_Absolute_Value() |
|||
{ |
|||
var result = RelativePoint.Parse("4,5", CultureInfo.InvariantCulture); |
|||
|
|||
Assert.Equal(new RelativePoint(4, 5, RelativeUnit.Absolute), result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Parse_Should_Accept_Relative_Value() |
|||
{ |
|||
var result = RelativePoint.Parse("25%, 50%", CultureInfo.InvariantCulture); |
|||
|
|||
Assert.Equal(new RelativePoint(0.25, 0.5, RelativeUnit.Relative), result); |
|||
} |
|||
} |
|||
} |
|||
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 930 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 928 B |
|
Before Width: | Height: | Size: 924 B |
|
Before Width: | Height: | Size: 934 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 930 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 928 B |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 930 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 930 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,224 @@ |
|||
// 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 Cairo; |
|||
using Perspex.Cairo.Media.Imaging; |
|||
using Perspex.Layout; |
|||
using Perspex.Media; |
|||
using Perspex.Platform; |
|||
|
|||
namespace Perspex.Cairo.Media |
|||
{ |
|||
internal static class TileBrushes |
|||
{ |
|||
public static SurfacePattern CreateImageBrush(ImageBrush brush, Size targetSize) |
|||
{ |
|||
if (brush.Source == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
// TODO: This is directly ported from Direct2D and could probably be made more
|
|||
// efficient on cairo by taking advantage of the fact that cairo has Extend.None.
|
|||
var image = ((BitmapImpl)brush.Source.PlatformImpl).Surface; |
|||
var imageSize = new Size(brush.Source.PixelWidth, brush.Source.PixelHeight); |
|||
var tileMode = brush.TileMode; |
|||
var sourceRect = brush.SourceRect.ToPixels(imageSize); |
|||
var destinationRect = brush.DestinationRect.ToPixels(targetSize); |
|||
var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size); |
|||
var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale); |
|||
var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size); |
|||
var intermediate = new ImageSurface(Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height); |
|||
|
|||
using (var context = new Context(intermediate)) |
|||
{ |
|||
Rect drawRect; |
|||
var transform = CalculateIntermediateTransform( |
|||
tileMode, |
|||
sourceRect, |
|||
destinationRect, |
|||
scale, |
|||
translate, |
|||
out drawRect); |
|||
context.Rectangle(drawRect.ToCairo()); |
|||
context.Clip(); |
|||
context.Transform(transform.ToCairo()); |
|||
Gdk.CairoHelper.SetSourcePixbuf(context, image, 0, 0); |
|||
context.Rectangle(0, 0, imageSize.Width, imageSize.Height); |
|||
context.Fill(); |
|||
|
|||
var result = new SurfacePattern(intermediate); |
|||
|
|||
if ((brush.TileMode & TileMode.FlipXY) != 0) |
|||
{ |
|||
// TODO: Currently always FlipXY as that's all cairo supports natively.
|
|||
// Support separate FlipX and FlipY by drawing flipped images to intermediate
|
|||
// surface.
|
|||
result.Extend = Extend.Reflect; |
|||
} |
|||
else |
|||
{ |
|||
result.Extend = Extend.Repeat; |
|||
} |
|||
|
|||
if (brush.TileMode != TileMode.None) |
|||
{ |
|||
var matrix = result.Matrix; |
|||
matrix.InitTranslate(-destinationRect.X, -destinationRect.Y); |
|||
result.Matrix = matrix; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
|
|||
public static SurfacePattern CreateVisualBrush(VisualBrush brush, Size targetSize) |
|||
{ |
|||
var visual = brush.Visual; |
|||
|
|||
if (visual == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var layoutable = visual as ILayoutable; |
|||
|
|||
if (layoutable?.IsArrangeValid == false) |
|||
{ |
|||
layoutable.Measure(Size.Infinity); |
|||
layoutable.Arrange(new Rect(layoutable.DesiredSize)); |
|||
} |
|||
|
|||
// TODO: This is directly ported from Direct2D and could probably be made more
|
|||
// efficient on cairo by taking advantage of the fact that cairo has Extend.None.
|
|||
var tileMode = brush.TileMode; |
|||
var sourceRect = brush.SourceRect.ToPixels(layoutable.Bounds.Size); |
|||
var destinationRect = brush.DestinationRect.ToPixels(targetSize); |
|||
var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size); |
|||
var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale); |
|||
var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size); |
|||
var intermediate = new ImageSurface(Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height); |
|||
|
|||
using (var context = new Context(intermediate)) |
|||
{ |
|||
Rect drawRect; |
|||
var transform = CalculateIntermediateTransform( |
|||
tileMode, |
|||
sourceRect, |
|||
destinationRect, |
|||
scale, |
|||
translate, |
|||
out drawRect); |
|||
var renderer = new Renderer(intermediate); |
|||
|
|||
context.Rectangle(drawRect.ToCairo()); |
|||
context.Clip(); |
|||
context.Transform(transform.ToCairo()); |
|||
renderer.Render(visual, new PlatformHandle(IntPtr.Zero, "RTB"), transform, drawRect); |
|||
|
|||
var result = new SurfacePattern(intermediate); |
|||
|
|||
if ((brush.TileMode & TileMode.FlipXY) != 0) |
|||
{ |
|||
// TODO: Currently always FlipXY as that's all cairo supports natively.
|
|||
// Support separate FlipX and FlipY by drawing flipped images to intermediate
|
|||
// surface.
|
|||
result.Extend = Extend.Reflect; |
|||
} |
|||
else |
|||
{ |
|||
result.Extend = Extend.Repeat; |
|||
} |
|||
|
|||
if (brush.TileMode != TileMode.None) |
|||
{ |
|||
var matrix = result.Matrix; |
|||
matrix.InitTranslate(-destinationRect.X, -destinationRect.Y); |
|||
result.Matrix = matrix; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Calculates a translate based on a <see cref="TileBrush"/>, a source and destination
|
|||
/// rectangle and a scale.
|
|||
/// </summary>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="sourceRect">The source rectangle.</param>
|
|||
/// <param name="destinationRect">The destination rectangle.</param>
|
|||
/// <param name="scale">The scale factor.</param>
|
|||
/// <returns>A vector with the X and Y translate.</returns>
|
|||
private static Vector CalculateTranslate( |
|||
TileBrush brush, |
|||
Rect sourceRect, |
|||
Rect destinationRect, |
|||
Vector scale) |
|||
{ |
|||
var x = 0.0; |
|||
var y = 0.0; |
|||
var size = sourceRect.Size * scale; |
|||
|
|||
switch (brush.AlignmentX) |
|||
{ |
|||
case AlignmentX.Center: |
|||
x += (destinationRect.Width - size.Width) / 2; |
|||
break; |
|||
case AlignmentX.Right: |
|||
x += destinationRect.Width - size.Width; |
|||
break; |
|||
} |
|||
|
|||
switch (brush.AlignmentY) |
|||
{ |
|||
case AlignmentY.Center: |
|||
y += (destinationRect.Height - size.Height) / 2; |
|||
break; |
|||
case AlignmentY.Bottom: |
|||
y += destinationRect.Height - size.Height; |
|||
break; |
|||
} |
|||
|
|||
return new Vector(x, y); |
|||
} |
|||
|
|||
private static Size CalculateIntermediateSize( |
|||
TileMode tileMode, |
|||
Size targetSize, |
|||
Size destinationSize) |
|||
{ |
|||
var result = tileMode == TileMode.None ? targetSize : destinationSize; |
|||
return result; |
|||
} |
|||
|
|||
private static Matrix CalculateIntermediateTransform( |
|||
TileMode tileMode, |
|||
Rect sourceRect, |
|||
Rect destinationRect, |
|||
Vector scale, |
|||
Vector translate, |
|||
out Rect drawRect) |
|||
{ |
|||
var transform = Matrix.CreateTranslation(-sourceRect.Position) * |
|||
Matrix.CreateScale(scale) * |
|||
Matrix.CreateTranslation(translate); |
|||
Rect dr; |
|||
|
|||
if (tileMode == TileMode.None) |
|||
{ |
|||
dr = destinationRect; |
|||
transform *= Matrix.CreateTranslation(destinationRect.Position); |
|||
} |
|||
else |
|||
{ |
|||
dr = new Rect(destinationRect.Size); |
|||
} |
|||
|
|||
drawRect = dr; |
|||
|
|||
return transform; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
// 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; |
|||
using Perspex.Styling; |
|||
|
|||
namespace Perspex.Markup.Xaml.Converters |
|||
{ |
|||
public class ClassesTypeConverter : ITypeConverter |
|||
{ |
|||
public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType) |
|||
{ |
|||
return sourceType == typeof(string); |
|||
} |
|||
|
|||
public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value) |
|||
{ |
|||
return new Classes(((string)value).Split(' ')); |
|||
} |
|||
|
|||
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
// 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; |
|||
using Perspex.Media; |
|||
|
|||
namespace Perspex.Markup.Xaml.Converters |
|||
{ |
|||
public class ColorTypeConverter : ITypeConverter |
|||
{ |
|||
public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType) |
|||
{ |
|||
return sourceType == typeof(string); |
|||
} |
|||
|
|||
public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value) |
|||
{ |
|||
return Color.Parse((string)value); |
|||
} |
|||
|
|||
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
// 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 System.Linq; |
|||
using OmniXaml; |
|||
using OmniXaml.TypeConversion; |
|||
using Perspex.Styling; |
|||
|
|||
namespace Perspex.Markup.Xaml.Converters |
|||
{ |
|||
public class PerspexPropertyTypeConverter : ITypeConverter |
|||
{ |
|||
public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType) |
|||
{ |
|||
return sourceType == typeof(string); |
|||
} |
|||
|
|||
public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value) |
|||
{ |
|||
var s = (string)value; |
|||
var lastDot = s.LastIndexOf('.'); |
|||
|
|||
if (lastDot == -1) |
|||
{ |
|||
throw new NotSupportedException("PerspexProperties must currently be fully qualified."); |
|||
} |
|||
|
|||
var typeName = s.Substring(0, lastDot); |
|||
var propertyName = s.Substring(lastDot + 1); |
|||
var type = context.TypeRepository.GetByQualifiedName(typeName)?.UnderlyingType; |
|||
var styleType = context.TypeRepository.GetXamlType(typeof(Style)); |
|||
|
|||
// ATTN: SuperJMN
|
|||
//var style = ((XamlTypeConverterContext)context).TopDownValueContext.GetLastInstance(styleType);
|
|||
|
|||
if (type == null) |
|||
{ |
|||
throw new XamlParseException($"Could not find type '{typeName}'."); |
|||
} |
|||
|
|||
// First look for non-attached property on the type and then look for an attached property.
|
|||
var property = PerspexObject.GetRegisteredProperties(type) |
|||
.FirstOrDefault(x => x.Name == propertyName); |
|||
|
|||
if (property == null) |
|||
{ |
|||
property = PerspexObject.GetAttachedProperties(type) |
|||
.FirstOrDefault(x => x.Name == propertyName); |
|||
} |
|||
|
|||
if (property == null) |
|||
{ |
|||
throw new XamlParseException( |
|||
$"Could not find PerspexProperty '{typeName}'.{propertyName}."); |
|||
} |
|||
|
|||
return property; |
|||
} |
|||
|
|||
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
} |
|||
} |
|||
@ -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 PointTypeConverter : ITypeConverter |
|||
{ |
|||
public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType) |
|||
{ |
|||
return sourceType == typeof(string); |
|||
} |
|||
|
|||
public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value) |
|||
{ |
|||
return Point.Parse((string)value, culture); |
|||
} |
|||
|
|||
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
} |
|||
} |
|||
@ -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 RelativePointTypeConverter : ITypeConverter |
|||
{ |
|||
public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType) |
|||
{ |
|||
return sourceType == typeof(string); |
|||
} |
|||
|
|||
public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value) |
|||
{ |
|||
return RelativePoint.Parse((string)value, culture); |
|||
} |
|||
|
|||
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
// 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; |
|||
using Perspex.Markup.Xaml.Parsers; |
|||
|
|||
namespace Perspex.Markup.Xaml.Converters |
|||
{ |
|||
public class SelectorTypeConverter : ITypeConverter |
|||
{ |
|||
public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType) |
|||
{ |
|||
return sourceType == typeof(string); |
|||
} |
|||
|
|||
public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value) |
|||
{ |
|||
var parser = new SelectorParser((t, ns) => context.TypeRepository.GetByPrefix(ns ?? "", t).UnderlyingType); |
|||
return parser.Parse((string)value); |
|||
} |
|||
|
|||
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
} |
|||
} |
|||