Browse Source

Implemented retained brush impls for Cairo to match D2D

pull/148/head
Nelson Carrillo 11 years ago
committed by Nelson Carrillo
parent
commit
a84d7189ea
  1. 17
      src/Gtk/Perspex.Cairo/Media/BrushImpl.cs
  2. 118
      src/Gtk/Perspex.Cairo/Media/DrawingContext.cs
  3. 14
      src/Gtk/Perspex.Cairo/Media/ImageBrushImpl.cs
  4. 5
      src/Gtk/Perspex.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs
  5. 22
      src/Gtk/Perspex.Cairo/Media/LinearGradientBrushImpl.cs
  6. 20
      src/Gtk/Perspex.Cairo/Media/SolidColorBrushImpl.cs
  7. 6
      src/Gtk/Perspex.Cairo/Media/TileBrushes.cs
  8. 14
      src/Gtk/Perspex.Cairo/Media/VisualBrushImpl.cs
  9. 25
      src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj
  10. 2
      src/Gtk/Perspex.Cairo/Renderer.cs
  11. 16
      src/Gtk/Perspex.Gtk/Perspex.Gtk.csproj
  12. BIN
      tests/Perspex.RenderTests/TestBase.cs

17
src/Gtk/Perspex.Cairo/Media/BrushImpl.cs

@ -0,0 +1,17 @@
using System;
using global::Cairo;
namespace Perspex.Cairo
{
public abstract class BrushImpl : IDisposable
{
public Pattern PlatformBrush { get; protected set; }
public void Dispose()
{
if (this.PlatformBrush != null)
this.PlatformBrush.Dispose();
}
}
}

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

@ -95,11 +95,12 @@ namespace Perspex.Cairo.Media
{
var size = new Rect(p1, p2).Size;
SetPen(pen, size);
_context.MoveTo(p1.ToCairo());
_context.LineTo(p2.ToCairo());
_context.Stroke();
using (var p = SetPen(pen, size))
{
_context.MoveTo(p1.ToCairo());
_context.LineTo(p2.ToCairo());
_context.Stroke();
}
}
/// <summary>
@ -118,19 +119,22 @@ namespace Perspex.Cairo.Media
if (brush != null)
{
SetBrush(brush, geometry.Bounds.Size);
if (pen != null)
_context.FillPreserve();
else
_context.Fill();
using (var b = SetBrush(brush, geometry.Bounds.Size))
{
if (pen != null)
_context.FillPreserve();
else
_context.Fill();
}
}
}
if (pen != null)
{
SetPen(pen, geometry.Bounds.Size);
_context.Stroke();
using (var p = SetPen(pen, geometry.Bounds.Size))
{
_context.Stroke();
}
}
}
@ -141,9 +145,11 @@ namespace Perspex.Cairo.Media
/// <param name="rect">The rectangle bounds.</param>
public void DrawRectange(Pen pen, Rect rect, float cornerRadius)
{
SetPen(pen, rect.Size);
_context.Rectangle(rect.ToCairo());
_context.Stroke();
using (var p = SetPen(pen, rect.Size))
{
_context.Rectangle(rect.ToCairo ());
_context.Stroke();
}
}
/// <summary>
@ -157,8 +163,10 @@ namespace Perspex.Cairo.Media
var layout = ((FormattedTextImpl)text.PlatformImpl).Layout;
_context.MoveTo(origin.X, origin.Y);
SetBrush(foreground, new Size(0, 0));
Pango.CairoHelper.ShowLayout(_context, layout);
using (var b = SetBrush(foreground, new Size(0, 0)))
{
Pango.CairoHelper.ShowLayout(_context, layout);
}
}
/// <summary>
@ -168,9 +176,11 @@ namespace Perspex.Cairo.Media
/// <param name="rect">The rectangle bounds.</param>
public void FillRectange(Brush brush, Rect rect, float cornerRadius)
{
SetBrush(brush, rect.Size);
_context.Rectangle(rect.ToCairo());
_context.Fill();
using (var b = SetBrush(brush, rect.Size))
{
_context.Rectangle(rect.ToCairo ());
_context.Fill();
}
}
/// <summary>
@ -212,48 +222,44 @@ namespace Perspex.Cairo.Media
});
}
private void SetBrush(Brush brush, Size destinationSize)
private double opacityOverride = 1.0f;
private BrushImpl SetBrush(Brush brush, Size destinationSize)
{
var solid = brush as SolidColorBrush;
var linearGradientBrush = brush as LinearGradientBrush;
var imageBrush = brush as ImageBrush;
var visualBrush = brush as VisualBrush;
if (solid != null)
{
_context.SetSourceRGBA(
solid.Color.R / 255.0,
solid.Color.G / 255.0,
solid.Color.B / 255.0,
solid.Color.A / 255.0);
}
else if (linearGradientBrush != null)
{
var start = linearGradientBrush.StartPoint.ToPixels(destinationSize);
var end = linearGradientBrush.EndPoint.ToPixels(destinationSize);
Cairo.LinearGradient g = new Cairo.LinearGradient(start.X, start.Y, end.X, end.Y);
foreach (var s in linearGradientBrush.GradientStops)
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));
}
BrushImpl impl = null;
if (solid != null)
{
impl = new SolidColorBrushImpl(solid, opacityOverride);
}
else if (linearGradientBrush != null)
{
impl = new LinearGradientBrushImpl(linearGradientBrush, destinationSize);
}
else if (imageBrush != null)
{
impl = new ImageBrushImpl(imageBrush, destinationSize);
}
else if (visualBrush != null)
{
impl = new VisualBrushImpl(visualBrush, destinationSize);
}
else
{
impl = new SolidColorBrushImpl(null, 1.0f);
}
_context.SetSource(impl.PlatformBrush);
return impl;
}
private void SetPen(Pen pen, Size destinationSize)
private BrushImpl SetPen(Pen pen, Size destinationSize)
{
SetBrush(pen.Brush, destinationSize);
if (pen.DashStyle != null)
{
if (pen.DashStyle.Dashes != null && pen.DashStyle.Dashes.Count > 0)
@ -271,6 +277,8 @@ namespace Perspex.Cairo.Media
// TODO: Figure out a solution for this.
_context.LineJoin = Cairo.LineJoin.Miter;
_context.LineCap = Cairo.LineCap.Butt;
return SetBrush(pen.Brush, destinationSize);
}
}
}

14
src/Gtk/Perspex.Cairo/Media/ImageBrushImpl.cs

@ -0,0 +1,14 @@
using System;
using global::Cairo;
namespace Perspex.Cairo.Media
{
public class ImageBrushImpl : BrushImpl
{
public ImageBrushImpl(Perspex.Media.ImageBrush brush, Size destinationSize)
{
this.PlatformBrush = TileBrushes.CreateImageBrush(brush, destinationSize);
}
}
}

5
src/Gtk/Perspex.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs

@ -13,6 +13,7 @@ namespace Perspex.Cairo.Media.Imaging
public RenderTargetBitmapImpl(Cairo.ImageSurface surface)
{
Surface = surface;
renderer = new Renderer(Surface);
}
public int PixelWidth => Surface.Width;
@ -21,7 +22,7 @@ namespace Perspex.Cairo.Media.Imaging
public void Dispose()
{
Surface.Dispose();
renderer.Dispose();
}
public Cairo.ImageSurface Surface
@ -29,9 +30,9 @@ namespace Perspex.Cairo.Media.Imaging
get;
}
private Renderer renderer;
public void Render(IVisual visual)
{
Renderer renderer = new Renderer(Surface);
renderer.Render(visual, new PlatformHandle(IntPtr.Zero, "RTB"));
}

22
src/Gtk/Perspex.Cairo/Media/LinearGradientBrushImpl.cs

@ -0,0 +1,22 @@
using System;
using global::Cairo;
namespace Perspex.Cairo
{
public class LinearGradientBrushImpl : BrushImpl
{
public LinearGradientBrushImpl(Perspex.Media.LinearGradientBrush brush, Size destinationSize)
{
var start = brush.StartPoint.ToPixels(destinationSize);
var end = brush.EndPoint.ToPixels(destinationSize);
this.PlatformBrush = new LinearGradient(start.X, start.Y, end.X, end.Y);
foreach (var stop in brush.GradientStops)
((LinearGradient)this.PlatformBrush).AddColorStop(stop.Offset, stop.Color.ToCairo());
((LinearGradient)this.PlatformBrush).Extend = Extend.Pad;
}
}
}

20
src/Gtk/Perspex.Cairo/Media/SolidColorBrushImpl.cs

@ -0,0 +1,20 @@
using System;
using global::Cairo;
namespace Perspex.Cairo
{
public class SolidColorBrushImpl : BrushImpl
{
public SolidColorBrushImpl(Perspex.Media.SolidColorBrush brush, double opacityOverride = 1.0f)
{
var color = brush?.Color.ToCairo() ?? new Color();
if (brush != null && brush.Opacity > 1)
color.A = Math.Min(brush.Opacity, color.A);
color.A = Math.Min(opacityOverride, color.A);
this.PlatformBrush = new SolidPattern(brush?.Color.ToCairo() ?? new Color());
}
}
}

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

@ -29,8 +29,8 @@ namespace Perspex.Cairo.Media
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 intermediate = new ImageSurface(Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height))
using (var context = new Context(intermediate))
{
Rect drawRect;
@ -98,8 +98,8 @@ namespace Perspex.Cairo.Media
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 intermediate = new ImageSurface(Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height))
using (var context = new Context(intermediate))
{
Rect drawRect;

14
src/Gtk/Perspex.Cairo/Media/VisualBrushImpl.cs

@ -0,0 +1,14 @@
using System;
using global::Cairo;
namespace Perspex.Cairo.Media
{
public class VisualBrushImpl : BrushImpl
{
public VisualBrushImpl(Perspex.Media.VisualBrush brush, Size destinationSize)
{
this.PlatformBrush = TileBrushes.CreateVisualBrush(brush, destinationSize);
}
}
}

25
src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj

@ -32,18 +32,10 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL">
<Package>gtk-sharp-2.0</Package>
</Reference>
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL">
<Package>glib-sharp-2.0</Package>
</Reference>
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL">
<Package>gtk-sharp-2.0</Package>
</Reference>
<Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL">
<Package>gtk-sharp-2.0</Package>
</Reference>
<Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL" />
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL" />
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL" />
<Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
@ -58,9 +50,7 @@
<Reference Include="System.Reactive.Interfaces">
<HintPath>..\..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
</Reference>
<Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
<Package>gtk-sharp-2.0</Package>
</Reference>
<Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath>
</Reference>
@ -77,6 +67,11 @@
<Compile Include="CairoExtensions.cs" />
<Compile Include="Media\StreamGeometryContextImpl.cs" />
<Compile Include="Media\StreamGeometryImpl.cs" />
<Compile Include="Media\BrushImpl.cs" />
<Compile Include="Media\SolidColorBrushImpl.cs" />
<Compile Include="Media\LinearGradientBrushImpl.cs" />
<Compile Include="Media\ImageBrushImpl.cs" />
<Compile Include="Media\VisualBrushImpl.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Perspex.Animation\Perspex.Animation.csproj">

2
src/Gtk/Perspex.Cairo/Renderer.cs

@ -74,6 +74,8 @@ namespace Perspex.Cairo
public override void Dispose()
{
if (_surface != null)
_surface.Dispose();
}
}
}

16
src/Gtk/Perspex.Gtk/Perspex.Gtk.csproj

@ -31,15 +31,9 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
<Package>gtk-sharp-2.0</Package>
</Reference>
<Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
<Package>gtk-sharp-2.0</Package>
</Reference>
<Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
<Package>gtk-sharp-2.0</Package>
</Reference>
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="System.Reactive.Interfaces">
<HintPath>..\..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
</Reference>
@ -49,9 +43,7 @@
<Reference Include="System.Reactive.Linq">
<HintPath>..\..\..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath>
</Reference>
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
<Package>glib-sharp-2.0</Package>
</Reference>
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath>
</Reference>

BIN
tests/Perspex.RenderTests/TestBase.cs

Binary file not shown.
Loading…
Cancel
Save