Browse Source

Started implementing VisualBrush.

pull/111/head
Steven Kirk 11 years ago
parent
commit
79422fc45b
  1. 2
      Perspex.sln
  2. 2
      src/Perspex.SceneGraph/Media/Brush.cs
  3. 29
      src/Perspex.SceneGraph/Media/VisualBrush.cs
  4. 1
      src/Perspex.SceneGraph/Perspex.SceneGraph.csproj
  5. 39
      src/Windows/Perspex.Direct2D1/Disposable.cs
  6. 74
      src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs
  7. 7
      src/Windows/Perspex.Direct2D1/Media/PerspexTextRenderer.cs
  8. 5
      src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
  9. 21
      src/Windows/Perspex.Direct2D1/PrimitiveExtensions.cs
  10. 58
      tests/Perspex.RenderTests/Brushes/VisualBrushTests.cs

2
Perspex.sln

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.22823.1
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Win32", "src\Windows\Perspex.Win32\Perspex.Win32.csproj", "{811A76CF-1CF6-440F-963B-BBE31BD72A82}"
EndProject

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

@ -9,7 +9,7 @@ namespace Perspex.Media
/// <summary>
/// Describes how an area is painted.
/// </summary>
public abstract class Brush
public abstract class Brush : PerspexObject
{
}
}

29
src/Perspex.SceneGraph/Media/VisualBrush.cs

@ -0,0 +1,29 @@
// -----------------------------------------------------------------------
// <copyright file="VisualBrush.cs" company="Steven Kirk">
// Copyright 2015 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
public class VisualBrush : Brush
{
public static readonly PerspexProperty<IVisual> VisualProperty =
PerspexProperty.Register<VisualBrush, IVisual>("Visual");
public VisualBrush()
{
}
public VisualBrush(IVisual visual)
{
this.Visual = visual;
}
public IVisual Visual
{
get { return this.GetValue(VisualProperty); }
set { this.SetValue(VisualProperty, value); }
}
}
}

1
src/Perspex.SceneGraph/Perspex.SceneGraph.csproj

@ -86,6 +86,7 @@
<Compile Include="Media\SweepDirection.cs" />
<Compile Include="Media\TextHitTestResult.cs" />
<Compile Include="Media\Transform.cs" />
<Compile Include="Media\VisualBrush.cs" />
<Compile Include="Origin.cs" />
<Compile Include="Platform\IFormattedTextImpl.cs" />
<Compile Include="Platform\IBitmapImpl.cs" />

39
src/Windows/Perspex.Direct2D1/Disposable.cs

@ -0,0 +1,39 @@
// -----------------------------------------------------------------------
// <copyright file="Disposable.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Direct2D1
{
using System;
public class Disposable<T> : IDisposable where T : IDisposable
{
private IDisposable extra;
public Disposable(T inner)
{
this.Inner = inner;
}
public Disposable(T inner, IDisposable extra)
{
this.Inner = inner;
this.extra = extra;
}
public T Inner { get; }
public static implicit operator T(Disposable<T> i)
{
return i.Inner;
}
public void Dispose()
{
this.Inner.Dispose();
this.extra?.Dispose();
}
}
}

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

@ -8,6 +8,7 @@ namespace Perspex.Direct2D1.Media
{
using System;
using System.Reactive.Disposables;
using Layout;
using Perspex.Media;
using SharpDX;
using SharpDX.Direct2D1;
@ -89,7 +90,7 @@ namespace Perspex.Direct2D1.Media
{
if (pen != null)
{
using (var d2dBrush = pen.Brush.ToDirect2D(this.renderTarget))
using (var d2dBrush = this.CreateBrush(pen.Brush))
using (var d2dStroke = pen.ToDirect2DStrokeStyle(this.renderTarget))
{
this.renderTarget.DrawLine(
@ -112,7 +113,7 @@ namespace Perspex.Direct2D1.Media
{
if (brush != null)
{
using (var d2dBrush = brush.ToDirect2D(this.renderTarget))
using (var d2dBrush = this.CreateBrush(brush))
{
GeometryImpl impl = (GeometryImpl)geometry.PlatformImpl;
this.renderTarget.FillGeometry(impl.Geometry, d2dBrush);
@ -121,7 +122,7 @@ namespace Perspex.Direct2D1.Media
if (pen != null)
{
using (var d2dBrush = pen.Brush.ToDirect2D(this.renderTarget))
using (var d2dBrush = this.CreateBrush(pen.Brush))
using (var d2dStroke = pen.ToDirect2DStrokeStyle(this.renderTarget))
{
GeometryImpl impl = (GeometryImpl)geometry.PlatformImpl;
@ -138,7 +139,7 @@ namespace Perspex.Direct2D1.Media
/// <param name="cornerRadius">The corner radius.</param>
public void DrawRectange(Pen pen, Rect rect, float cornerRadius)
{
using (var brush = pen.Brush.ToDirect2D(this.renderTarget))
using (var brush = this.CreateBrush(pen.Brush))
using (var d2dStroke = pen.ToDirect2DStrokeStyle(this.renderTarget))
{
this.renderTarget.DrawRoundedRectangle(
@ -161,7 +162,8 @@ namespace Perspex.Direct2D1.Media
{
var impl = (FormattedTextImpl)text.PlatformImpl;
using (var renderer = new PerspexTextRenderer(this.renderTarget, foreground.ToDirect2D(this.renderTarget)))
using (var brush = this.CreateBrush(foreground))
using (var renderer = new PerspexTextRenderer(this, this.renderTarget, brush))
{
impl.TextLayout.Draw(renderer, (float)origin.X, (float)origin.Y);
}
@ -176,7 +178,7 @@ namespace Perspex.Direct2D1.Media
/// <param name="cornerRadius">The corner radius.</param>
public void FillRectange(Perspex.Media.Brush brush, Rect rect, float cornerRadius)
{
using (var b = brush.ToDirect2D(this.renderTarget))
using (var b = this.CreateBrush(brush))
{
this.renderTarget.FillRoundedRectangle(
new RoundedRectangle
@ -256,5 +258,65 @@ namespace Perspex.Direct2D1.Media
this.renderTarget.Transform = transform * m3x2;
});
}
/// <summary>
/// Creates a Direct2D brush from a Perspex brush.
/// </summary>
/// <param name="brush">The perspex brush.</param>
/// <returns>The Direct2D brush.</returns>
public Disposable<SharpDX.Direct2D1.Brush> CreateBrush(Perspex.Media.Brush brush)
{
var solidColorBrush = brush as Perspex.Media.SolidColorBrush;
var visualBrush = brush as Perspex.Media.VisualBrush;
if (solidColorBrush != null)
{
return new Disposable<SharpDX.Direct2D1.Brush>(
new SharpDX.Direct2D1.SolidColorBrush(
this.renderTarget,
solidColorBrush.Color.ToDirect2D()));
}
else if (visualBrush != null)
{
return this.CreateBrush(visualBrush);
}
else
{
// TODO: Implement other brushes.
return new Disposable<SharpDX.Direct2D1.Brush>(
new SharpDX.Direct2D1.SolidColorBrush(this.renderTarget, new Color4()));
}
}
/// <summary>
/// Creates a Direct2D <see cref="BitmapBrush"/> from a Perspex <see cref="VisualBrush"/>.
/// </summary>
/// <param name="brush">The perspex brush.</param>
/// <returns>The Direct2D brush.</returns>
private Disposable<SharpDX.Direct2D1.Brush> CreateBrush(VisualBrush brush)
{
var visual = brush.Visual;
var layoutable = visual as ILayoutable;
if (layoutable?.IsArrangeValid == false)
{
layoutable.Measure(Size.Infinity);
layoutable.Arrange(new Rect(layoutable.DesiredSize));
}
using (var target = new BitmapRenderTarget(
this.renderTarget,
CompatibleRenderTargetOptions.None,
visual.Bounds.Size.ToSharpDX()))
{
var renderer = new Renderer(target);
renderer.Render(visual, null);
var result = new BitmapBrush(this.renderTarget, target.Bitmap);
result.ExtendModeX = ExtendMode.Wrap;
result.ExtendModeY = ExtendMode.Wrap;
return new Disposable<SharpDX.Direct2D1.Brush>(result, target);
}
}
}
}

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

@ -13,14 +13,18 @@ namespace Perspex.Direct2D1.Media
internal class PerspexTextRenderer : TextRenderer
{
private DrawingContext context;
private RenderTarget renderTarget;
private Brush foreground;
public PerspexTextRenderer(
DrawingContext context,
RenderTarget target,
Brush foreground)
{
this.context = context;
this.renderTarget = target;
this.foreground = foreground;
}
@ -33,7 +37,6 @@ namespace Perspex.Direct2D1.Media
public void Dispose()
{
this.foreground.Dispose();
}
public Result DrawGlyphRun(
@ -48,7 +51,7 @@ namespace Perspex.Direct2D1.Media
var wrapper = clientDrawingEffect as BrushWrapper;
var brush = (wrapper == null) ?
this.foreground :
wrapper.Brush.ToDirect2D(this.renderTarget);
this.context.CreateBrush(wrapper.Brush);
this.renderTarget.DrawGlyphRun(
new Vector2(baselineOriginX, baselineOriginY),

5
src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj

@ -74,6 +74,7 @@
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Direct2D1Platform.cs" />
<Compile Include="Disposable.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="Media\BrushWrapper.cs" />
<Compile Include="Media\DrawingContext.cs" />
@ -101,6 +102,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>

21
src/Windows/Perspex.Direct2D1/PrimitiveExtensions.cs

@ -34,27 +34,6 @@ namespace Perspex.Direct2D1
return new Size2F((float)p.Width, (float)p.Height);
}
/// <summary>
/// Converts a brush to Direct2D.
/// </summary>
/// <param name="brush">The brush to convert.</param>
/// <param name="target">The render target.</param>
/// <returns>The Direct2D brush.</returns>
public static SharpDX.Direct2D1.Brush ToDirect2D(this Perspex.Media.Brush brush, RenderTarget target)
{
Perspex.Media.SolidColorBrush solidColorBrush = brush as Perspex.Media.SolidColorBrush;
if (solidColorBrush != null)
{
return new SharpDX.Direct2D1.SolidColorBrush(target, solidColorBrush.Color.ToDirect2D());
}
else
{
// TODO: Implement other brushes.
return new SharpDX.Direct2D1.SolidColorBrush(target, new Color4());
}
}
/// <summary>
/// Converts a pen to a Direct2D stroke style.
/// </summary>

58
tests/Perspex.RenderTests/Brushes/VisualBrushTests.cs

@ -0,0 +1,58 @@
// -----------------------------------------------------------------------
// <copyright file="VisualBrushTests.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Direct2D1.RenderTests.Controls
{
using Perspex.Controls;
using Perspex.Controls.Shapes;
using Perspex.Layout;
using Perspex.Media;
using Xunit;
public class VisualBrushTests : TestBase
{
public VisualBrushTests()
: base(@"Brushes\VisualBrush")
{
}
[Fact]
public void VisualBrush_Should_Draw_Visual()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 200,
Height = 200,
Child = new Rectangle
{
Fill = new VisualBrush
{
Visual = new Border
{
Width = 92,
Height = 92,
Background = Brushes.Red,
BorderBrush = Brushes.Black,
BorderThickness = 2,
Child = new TextBlock
{
Text = "Perspex",
FontSize = 12,
FontFamily = "Arial",
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
}
}
}
}
};
this.RenderToFile(target);
this.CompareImages();
}
}
}
Loading…
Cancel
Save