Browse Source

Merge branch 'imagebrush-visualbrush-cairo'

pull/148/head
Steven Kirk 11 years ago
parent
commit
c18a604661
  1. 48
      Tests/Perspex.RenderTests/Media/ImageBrushTests.cs
  2. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png
  3. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png
  4. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png
  5. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png
  6. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png
  7. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png
  8. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png
  9. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png
  10. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png
  11. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png
  12. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png
  13. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png
  14. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png
  15. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/github_icon.png
  16. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Align_BottomRight.expected.png
  17. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Align_Center.expected.png
  18. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Align_TopLeft.expected.png
  19. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_DestinationRect_Absolute.expected.png
  20. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png
  21. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_FlipX.expected.png
  22. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_FlipXY.expected.png
  23. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_FlipY.expected.png
  24. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipXY_TopLeftDest.expected.png
  25. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipX_TopLeftDest.expected.png
  26. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipY_TopLeftDest.expected.png
  27. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png
  28. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_Center.expected.png
  29. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png
  30. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png
  31. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png
  32. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png
  33. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png
  34. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_SourceRect_Absolute.expected.png
  35. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Absolute.expected.png
  36. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Percent.expected.png
  37. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Stretch_Fill_Large.expected.png
  38. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Stretch_Uniform.expected.png
  39. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Stretch_UniformToFill.expected.png
  40. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Tile.expected.png
  41. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Tile_Alignment_BottomRight.expected.png
  42. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png
  43. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png
  44. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/github_icon.png
  45. 12
      src/Gtk/Perspex.Cairo/Media/DrawingContext.cs
  46. 224
      src/Gtk/Perspex.Cairo/Media/TileBrushes.cs
  47. 5
      src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj
  48. 48
      tests/Perspex.RenderTests/Media/VisualBrushTests.cs
  49. 1
      tests/Perspex.RenderTests/Perspex.Cairo.RenderTests.csproj

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

@ -26,11 +26,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
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
@ -55,11 +51,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
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
@ -84,11 +76,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
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
@ -113,11 +101,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void ImageBrush_Fill_NoTile()
{
Decorator target = new Decorator
@ -140,11 +124,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void ImageBrush_Uniform_NoTile()
{
Decorator target = new Decorator
@ -167,11 +147,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void ImageBrush_UniformToFill_NoTile()
{
Decorator target = new Decorator
@ -194,11 +170,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
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
@ -222,11 +194,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
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
@ -250,11 +218,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
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
@ -279,11 +243,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
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
@ -309,7 +269,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
[Fact(Skip = "TileMode.FlipX not yet supported on cairo")]
#else
[Fact]
#endif
@ -337,7 +297,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
}
#if PERSPEX_CAIRO
[Fact(Skip = "ImageBrush not yet implemented on Cairo")]
[Fact(Skip = "TileMode.FlipY not yet supported on cairo")]
#else
[Fact]
#endif
@ -364,11 +324,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Align_BottomRight.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 928 B

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Align_Center.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 924 B

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Align_TopLeft.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 934 B

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_DestinationRect_Absolute.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_FlipX.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_FlipXY.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_FlipY.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipXY_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipX_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipY_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_Center.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_SourceRect_Absolute.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Absolute.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Percent.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Stretch_Fill_Large.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Stretch_Uniform.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Stretch_UniformToFill.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Tile.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Tile_Alignment_BottomRight.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 928 B

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/github_icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

12
src/Gtk/Perspex.Cairo/Media/DrawingContext.cs

@ -216,6 +216,8 @@ namespace Perspex.Cairo.Media
{
var solid = brush as SolidColorBrush;
var linearGradientBrush = brush as LinearGradientBrush;
var imageBrush = brush as ImageBrush;
var visualBrush = brush as VisualBrush;
if (solid != null)
{
@ -236,9 +238,17 @@ namespace Perspex.Cairo.Media
g.AddColorStop(s.Offset, s.Color.ToCairo());
g.Extend = Cairo.Extend.Pad;
_context.SetSource(g);
}
else if (imageBrush != null)
{
_context.SetSource(TileBrushes.CreateImageBrush(imageBrush, destinationSize));
}
else if (visualBrush != null)
{
_context.SetSource(TileBrushes.CreateVisualBrush(visualBrush, destinationSize));
}
}
private void SetPen(Pen pen, Size destinationSize)

224
src/Gtk/Perspex.Cairo/Media/TileBrushes.cs

@ -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;
}
}
}

5
src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj

@ -72,6 +72,7 @@
<Compile Include="Media\FormattedTextImpl.cs" />
<Compile Include="Media\Imaging\BitmapImpl.cs" />
<Compile Include="Media\Imaging\RenderTargetBitmapImpl.cs" />
<Compile Include="Media\TileBrushes.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Renderer.cs" />
<Compile Include="CairoExtensions.cs" />
@ -87,6 +88,10 @@
<Project>{B09B78D8-9B26-48B0-9149-D64A2F120F3F}</Project>
<Name>Perspex.Base</Name>
</ProjectReference>
<ProjectReference Include="..\..\Perspex.Layout\Perspex.Layout.csproj">
<Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project>
<Name>Perspex.Layout</Name>
</ProjectReference>
<ProjectReference Include="..\..\Perspex.SceneGraph\Perspex.SceneGraph.csproj">
<Project>{EB582467-6ABB-43A1-B052-E981BA910E3A}</Project>
<Name>Perspex.SceneGraph</Name>

48
tests/Perspex.RenderTests/Media/VisualBrushTests.cs

@ -58,11 +58,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
}
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void VisualBrush_NoStretch_NoTile_Alignment_TopLeft()
{
Decorator target = new Decorator
@ -87,11 +83,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void VisualBrush_NoStretch_NoTile_Alignment_Center()
{
Decorator target = new Decorator
@ -116,11 +108,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void VisualBrush_NoStretch_NoTile_Alignment_BottomRight()
{
Decorator target = new Decorator
@ -145,11 +133,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void VisualBrush_Fill_NoTile()
{
Decorator target = new Decorator
@ -172,11 +156,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void VisualBrush_Uniform_NoTile()
{
Decorator target = new Decorator
@ -199,11 +179,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void VisualBrush_UniformToFill_NoTile()
{
Decorator target = new Decorator
@ -226,11 +202,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void VisualBrush_NoStretch_NoTile_BottomRightQuarterSource()
{
Decorator target = new Decorator
@ -254,11 +226,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void VisualBrush_NoStretch_NoTile_BottomRightQuarterDest()
{
Decorator target = new Decorator
@ -282,11 +250,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest()
{
Decorator target = new Decorator
@ -311,11 +275,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest()
{
Decorator target = new Decorator
@ -341,7 +301,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
[Fact(Skip = "TileMode.FlipX not yet supported on cairo")]
#else
[Fact]
#endif
@ -369,7 +329,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
[Fact(Skip = "TileMode.FlipY not yet supported on cairo")]
#else
[Fact]
#endif
@ -396,11 +356,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "VisualBrush not yet implemented on Cairo")]
#else
[Fact]
#endif
public void VisualBrush_NoStretch_FlipXY_TopLeftDest()
{
Decorator target = new Decorator

1
tests/Perspex.RenderTests/Perspex.Cairo.RenderTests.csproj

@ -74,6 +74,7 @@
<ItemGroup>
<Compile Include="Controls\ImageTests.cs" />
<Compile Include="Controls\BorderTests.cs" />
<Compile Include="Media\ImageBrushTests.cs" />
<Compile Include="Media\LinearGradientBrushTests.cs" />
<Compile Include="Media\VisualBrushTests.cs" />
<Compile Include="Shapes\PathTests.cs" />

Loading…
Cancel
Save