Browse Source

Initial implementation of ImageBrush on D2D.

pull/145/head
Steven Kirk 11 years ago
parent
commit
f2378b035f
  1. 395
      Tests/Perspex.RenderTests/Media/ImageBrushTests.cs
  2. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png
  3. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png
  4. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png
  5. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png
  6. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png
  7. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png
  8. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png
  9. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png
  10. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png
  11. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png
  12. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png
  13. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png
  14. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png
  15. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/github_icon.png
  16. 44
      src/Perspex.SceneGraph/Media/ImageBush.cs
  17. 3
      src/Perspex.SceneGraph/Perspex.SceneGraph.csproj
  18. 5
      src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs
  19. 93
      src/Windows/Perspex.Direct2D1/Media/ImageBrushImpl.cs
  20. 135
      src/Windows/Perspex.Direct2D1/Media/TileBrushImpl.cs
  21. 45
      src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs
  22. 2
      src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
  23. 1
      tests/Perspex.RenderTests/Perspex.Direct2D1.RenderTests.csproj
  24. BIN
      tests/Perspex.RenderTests/TestBase.cs

395
Tests/Perspex.RenderTests/Media/ImageBrushTests.cs

@ -0,0 +1,395 @@
// 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"); }
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
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();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
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();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
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();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
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();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
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();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
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();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
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();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
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();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
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();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
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 = "ImageBrush not yet implemented 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 = "ImageBrush not yet implemented 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();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
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();
}
}
}

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/github_icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

44
src/Perspex.SceneGraph/Media/ImageBush.cs

@ -0,0 +1,44 @@
// 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.Media.Imaging;
namespace Perspex.Media
{
/// <summary>
/// Paints an area with an <see cref="IBitmap"/>.
/// </summary>
public class ImageBrush : TileBrush
{
/// <summary>
/// Defines the <see cref="Visual"/> property.
/// </summary>
public static readonly PerspexProperty<IBitmap> SourceProperty =
PerspexProperty.Register<ImageBrush, IBitmap>("Source");
/// <summary>
/// Initializes a new instance of the <see cref="VisualBrush"/> class.
/// </summary>
public ImageBrush()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="VisualBrush"/> class.
/// </summary>
/// <param name="source">The image to draw.</param>
public ImageBrush(IBitmap source)
{
Source = source;
}
/// <summary>
/// Gets or sets the image to draw.
/// </summary>
public IBitmap Source
{
get { return GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
}
}

3
src/Perspex.SceneGraph/Perspex.SceneGraph.csproj

@ -64,11 +64,11 @@
<Compile Include="Media\Color.cs" />
<Compile Include="Media\Colors.cs" />
<Compile Include="Media\DashStyle.cs" />
<Compile Include="Media\MediaExtensions.cs" />
<Compile Include="Media\GradientBrush.cs" />
<Compile Include="Media\GradientSpreadMethod.cs" />
<Compile Include="Media\GradientStop.cs" />
<Compile Include="Media\LinearGradientBrush.cs" />
<Compile Include="Media\MediaExtensions.cs" />
<Compile Include="Media\PenLineCap.cs" />
<Compile Include="Media\PenLineJoin.cs" />
<Compile Include="Media\TextAlignment.cs" />
@ -97,6 +97,7 @@
<Compile Include="Media\TextHitTestResult.cs" />
<Compile Include="Media\Transform.cs" />
<Compile Include="Media\TileBrush.cs" />
<Compile Include="Media\ImageBush.cs" />
<Compile Include="Media\VisualBrush.cs" />
<Compile Include="RelativePoint.cs" />
<Compile Include="Platform\IFormattedTextImpl.cs" />

5
src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs

@ -303,6 +303,7 @@ namespace Perspex.Direct2D1.Media
{
var solidColorBrush = brush as Perspex.Media.SolidColorBrush;
var linearGradientBrush = brush as Perspex.Media.LinearGradientBrush;
var imageBrush = brush as ImageBrush;
var visualBrush = brush as VisualBrush;
if (solidColorBrush != null)
@ -313,6 +314,10 @@ namespace Perspex.Direct2D1.Media
{
return new LinearGradientBrushImpl(linearGradientBrush, _renderTarget, destinationSize);
}
else if (imageBrush != null)
{
return new ImageBrushImpl(imageBrush, _renderTarget, destinationSize);
}
else if (visualBrush != null)
{
return new VisualBrushImpl(visualBrush, _renderTarget, destinationSize);

93
src/Windows/Perspex.Direct2D1/Media/ImageBrushImpl.cs

@ -0,0 +1,93 @@
// 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 Perspex.Media;
using SharpDX.Direct2D1;
namespace Perspex.Direct2D1.Media
{
public class ImageBrushImpl : TileBrushImpl
{
public ImageBrushImpl(
ImageBrush brush,
RenderTarget target,
Size targetSize)
{
if (brush.Source == null)
{
return;
}
var image = ((BitmapImpl)brush.Source.PlatformImpl).GetDirect2DBitmap(target);
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 brtOpts = CompatibleRenderTargetOptions.None;
// TODO: There are times where we don't need to draw an intermediate bitmap. Identify
// them and directly use 'image' in those cases.
using (var intermediate = new BitmapRenderTarget(target, brtOpts, intermediateSize))
{
SharpDX.RectangleF drawRect;
intermediate.BeginDraw();
intermediate.Transform = CalculateIntermediateTransform(
tileMode,
sourceRect,
destinationRect,
scale,
translate,
out drawRect);
intermediate.PushAxisAlignedClip(drawRect, AntialiasMode.Aliased);
intermediate.DrawBitmap(image, 1, BitmapInterpolationMode.Linear);
intermediate.PopAxisAlignedClip();
intermediate.EndDraw();
this.PlatformBrush = new BitmapBrush(
target,
intermediate.Bitmap,
GetBitmapBrushProperties(brush),
GetBrushProperties(brush, destinationRect));
}
}
private BitmapBrush CreateDirectBrush(
ImageBrush brush,
RenderTarget target,
Bitmap image,
Rect sourceRect,
Rect destinationRect)
{
var tileMode = brush.TileMode;
var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size);
var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale);
var transform = Matrix.CreateTranslation(-sourceRect.Position) *
Matrix.CreateScale(scale) *
Matrix.CreateTranslation(translate);
var opts = new BrushProperties
{
Transform = transform.ToDirect2D(),
Opacity = (float)brush.Opacity,
};
var bitmapOpts = new BitmapBrushProperties
{
ExtendModeX = GetExtendModeX(tileMode),
ExtendModeY = GetExtendModeY(tileMode),
};
return new BitmapBrush(target, image, bitmapOpts, opts);
}
private BitmapBrush CreateIndirectBrush()
{
throw new NotImplementedException();
}
}
}

135
src/Windows/Perspex.Direct2D1/Media/TileBrushImpl.cs

@ -0,0 +1,135 @@
// 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 Perspex.Layout;
using Perspex.Media;
using SharpDX;
using SharpDX.Direct2D1;
namespace Perspex.Direct2D1.Media
{
public class TileBrushImpl : BrushImpl
{
/// <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>
protected 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);
}
protected static Size2F CalculateIntermediateSize(
TileMode tileMode,
Size targetSize,
Size destinationSize)
{
var result = tileMode == TileMode.None ? targetSize : destinationSize;
return result.ToSharpDX();
}
protected static Matrix3x2 CalculateIntermediateTransform(
TileMode tileMode,
Rect sourceRect,
Rect destinationRect,
Vector scale,
Vector translate,
out SharpDX.RectangleF 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 * -transform).ToSharpDX();
return transform.ToDirect2D();
}
protected static BrushProperties GetBrushProperties(TileBrush brush, Rect destinationRect)
{
var tileMode = brush.TileMode;
return new BrushProperties
{
Opacity = (float)brush.Opacity,
Transform = brush.TileMode != TileMode.None ?
SharpDX.Matrix3x2.Translation(
(float)destinationRect.X,
(float)destinationRect.Y) :
SharpDX.Matrix3x2.Identity,
};
}
protected static BitmapBrushProperties GetBitmapBrushProperties(TileBrush brush)
{
var tileMode = brush.TileMode;
return new BitmapBrushProperties
{
ExtendModeX = GetExtendModeX(tileMode),
ExtendModeY = GetExtendModeY(tileMode),
};
}
protected static ExtendMode GetExtendModeX(TileMode tileMode)
{
return (tileMode & TileMode.FlipX) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap;
}
protected static ExtendMode GetExtendModeY(TileMode tileMode)
{
return (tileMode & TileMode.FlipY) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap;
}
public override void Dispose()
{
((BitmapBrush)PlatformBrush)?.Bitmap.Dispose();
base.Dispose();
}
}
}

45
src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs

@ -8,7 +8,7 @@ using SharpDX.Direct2D1;
namespace Perspex.Direct2D1.Media
{
public class VisualBrushImpl : BrushImpl
public class VisualBrushImpl : TileBrushImpl
{
public VisualBrushImpl(
VisualBrush brush,
@ -59,8 +59,8 @@ namespace Perspex.Direct2D1.Media
renderer.Render(visual, null, transform, drawRect);
var result = new BitmapBrush(brt, brt.Bitmap);
result.ExtendModeX = (brush.TileMode & TileMode.FlipX) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap;
result.ExtendModeY = (brush.TileMode & TileMode.FlipY) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap;
result.ExtendModeX = GetExtendModeX(brush.TileMode);
result.ExtendModeY = GetExtendModeY(brush.TileMode);
if (brush.TileMode != TileMode.None)
{
@ -72,44 +72,5 @@ namespace Perspex.Direct2D1.Media
PlatformBrush = result;
}
}
private static Vector CalculateTranslate(
VisualBrush 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);
}
public override void Dispose()
{
((BitmapBrush)PlatformBrush)?.Bitmap.Dispose();
base.Dispose();
}
}
}

2
src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj

@ -82,6 +82,8 @@
<Compile Include="Media\Imaging\BitmapImpl.cs" />
<Compile Include="Media\LinearGradientBrushImpl.cs" />
<Compile Include="Media\PerspexTextRenderer.cs" />
<Compile Include="Media\ImageBrushImpl.cs" />
<Compile Include="Media\TileBrushImpl.cs" />
<Compile Include="Media\VisualBrushImpl.cs" />
<Compile Include="Media\SolidColorBrushImpl.cs" />
<Compile Include="Media\StreamGeometryContextImpl.cs" />

1
tests/Perspex.RenderTests/Perspex.Direct2D1.RenderTests.csproj

@ -75,6 +75,7 @@
<Otherwise />
</Choose>
<ItemGroup>
<Compile Include="Media\ImageBrushTests.cs" />
<Compile Include="Media\VisualBrushTests.cs" />
<Compile Include="Controls\ImageTests.cs" />
<Compile Include="Controls\BorderTests.cs" />

BIN
tests/Perspex.RenderTests/TestBase.cs

Binary file not shown.
Loading…
Cancel
Save