Browse Source

Simplified render loop, added guard drawing context wrapper

droid
Nikita Tsukanov 11 years ago
parent
commit
476f853be5
  1. 12
      src/Gtk/Perspex.Cairo/Media/TileBrushes.cs
  2. 76
      src/Perspex.SceneGraph/Media/ValidatingDrawingContext.cs
  3. 1
      src/Perspex.SceneGraph/Perspex.SceneGraph.csproj
  4. 74
      src/Perspex.SceneGraph/Rendering/RendererBase.cs
  5. 8
      src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs
  6. 12
      src/Windows/Perspex.Direct2D1/RenderTarget.cs

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

@ -101,7 +101,7 @@ namespace Perspex.Cairo.Media
var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size); var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size);
using (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)) using (var ctx = new RenderTarget(intermediate).CreateDrawingContext())
{ {
Rect drawRect; Rect drawRect;
var transform = CalculateIntermediateTransform( var transform = CalculateIntermediateTransform(
@ -111,12 +111,12 @@ namespace Perspex.Cairo.Media
scale, scale,
translate, translate,
out drawRect); out drawRect);
var renderer = new RenderTarget(intermediate);
context.Rectangle(drawRect.ToCairo()); using (ctx.PushClip(drawRect))
context.Clip(); using (ctx.PushTransform(transform))
context.Transform(transform.ToCairo()); {
renderer.Render(visual, transform, drawRect); ctx.Render(visual);
}
var result = new SurfacePattern(intermediate); var result = new SurfacePattern(intermediate);

76
src/Perspex.SceneGraph/Media/ValidatingDrawingContext.cs

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Reactive.Disposables;
using Perspex.Media.Imaging;
namespace Perspex.Media
{
public class ValidatingDrawingContext : IDrawingContext
{
private readonly IDrawingContext _base;
public ValidatingDrawingContext(IDrawingContext @base)
{
_base = @base;
}
public void Dispose()
{
_base.Dispose();
}
public Matrix CurrentTransform => _base.CurrentTransform;
public void DrawImage(IBitmap source, double opacity, Rect sourceRect, Rect destRect)
{
_base.DrawImage(source, opacity, sourceRect, destRect);
}
public void DrawLine(Pen pen, Point p1, Point p2)
{
_base.DrawLine(pen, p1, p2);
}
public void DrawGeometry(Brush brush, Pen pen, Geometry geometry)
{
_base.DrawGeometry(brush, pen, geometry);
}
public void DrawRectangle(Pen pen, Rect rect, float cornerRadius = 0)
{
_base.DrawRectangle(pen, rect, cornerRadius);
}
public void DrawText(Brush foreground, Point origin, FormattedText text)
{
_base.DrawText(foreground, origin, text);
}
public void FillRectangle(Brush brush, Rect rect, float cornerRadius = 0)
{
_base.FillRectangle(brush, rect, cornerRadius);
}
Stack<IDisposable> _stateStack = new Stack<IDisposable>();
IDisposable Transform(IDisposable disposable)
{
_stateStack.Push(disposable);
return Disposable.Create(() =>
{
var current = _stateStack.Peek();
if (current != disposable)
throw new InvalidOperationException("Invalid push/pop order");
current.Dispose();
_stateStack.Pop();
});
}
public IDisposable PushClip(Rect clip) => Transform(_base.PushClip(clip));
public IDisposable PushOpacity(double opacity) => Transform(_base.PushOpacity(opacity));
public IDisposable PushTransform(Matrix matrix) => Transform(_base.PushTransform(matrix));
}
}

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

@ -99,6 +99,7 @@
<Compile Include="Media\Transform.cs" /> <Compile Include="Media\Transform.cs" />
<Compile Include="Media\TileBrush.cs" /> <Compile Include="Media\TileBrush.cs" />
<Compile Include="Media\ImageBush.cs" /> <Compile Include="Media\ImageBush.cs" />
<Compile Include="Media\ValidatingDrawingContext.cs" />
<Compile Include="Media\VisualBrush.cs" /> <Compile Include="Media\VisualBrush.cs" />
<Compile Include="RelativePoint.cs" /> <Compile Include="RelativePoint.cs" />
<Compile Include="Platform\IFormattedTextImpl.cs" /> <Compile Include="Platform\IFormattedTextImpl.cs" />

74
src/Perspex.SceneGraph/Rendering/RendererBase.cs

@ -27,31 +27,7 @@ namespace Perspex.Rendering
ctx.Render(visual); ctx.Render(visual);
} }
/// <summary>
/// Renders the specified visual.
/// </summary>
/// <param name="renderTarget">IRenderer instance</param>
/// <param name="visual">The visual to render.</param>
/// <param name="translation">The current translation.</param>
/// <param name="transform">The current transform.</param>
public static void Render(this IRenderTarget renderTarget, IVisual visual, Matrix translation, Matrix transform)
{
using (var ctx = renderTarget.CreateDrawingContext())
ctx.Render(visual, translation, transform);
}
/// <summary>
/// Renders the specified visual with the specified transform and clip.
/// </summary>
/// <param name="renderTarget">IRenderer instance</param>
/// <param name="visual">The visual to render.</param>
/// <param name="transform">The transform.</param>
/// <param name="clip">An optional clip rectangle.</param>
public static void Render(this IRenderTarget renderTarget, IVisual visual, Matrix transform, Rect? clip = null)
{
using (var context = renderTarget.CreateDrawingContext())
context.Render(visual, transform, clip);
}
/// <summary> /// <summary>
/// Renders the specified visual. /// Renders the specified visual.
@ -60,65 +36,29 @@ namespace Perspex.Rendering
/// ///
/// <param name="context">The drawing context.</param> /// <param name="context">The drawing context.</param>
public static void Render(this IDrawingContext context, IVisual visual) public static void Render(this IDrawingContext context, IVisual visual)
{
context.Render(visual, Matrix.Identity);
}
/// <summary>
/// Renders the specified visual with the specified transform and clip.
/// </summary>
/// <param name="visual">The visual to render.</param>
/// <param name="context">The drawing context.</param>
/// <param name="transform">The transform.</param>
/// <param name="clip">An optional clip rectangle.</param>
public static void Render(this IDrawingContext context, IVisual visual, Matrix transform, Rect? clip = null)
{
using (clip.HasValue ? context.PushClip(clip.Value) : null)
{
context.Render(visual, Matrix.Identity, transform);
}
}
/// <summary>
/// Renders the specified visual.
/// </summary>
/// <param name="visual">The visual to render.</param>
/// <param name="context">The drawing context.</param>
/// <param name="translation">The current translation.</param>
/// <param name="transform">The current transform.</param>
public static void Render(this IDrawingContext context, IVisual visual, Matrix translation, Matrix transform)
{ {
var opacity = visual.Opacity; var opacity = visual.Opacity;
if (visual.IsVisible && opacity > 0) if (visual.IsVisible && opacity > 0)
{ {
// Translate any existing transform into this controls coordinate system. var m = Matrix.CreateTranslation(visual.Bounds.Position);
Matrix offset = Matrix.CreateTranslation(visual.Bounds.Position);
transform = offset * transform * -offset;
// Update the current offset. var renderTransform = Matrix.Identity;
translation *= Matrix.CreateTranslation(visual.Bounds.Position);
// Apply the control's render transform, if any.
if (visual.RenderTransform != null) if (visual.RenderTransform != null)
{ {
offset = Matrix.CreateTranslation(visual.TransformOrigin.ToPixels(visual.Bounds.Size)); var offset = -Matrix.CreateTranslation(visual.TransformOrigin.ToPixels(visual.Bounds.Size));
transform *= -offset * visual.RenderTransform.Value * offset; renderTransform = offset*visual.RenderTransform.Value;
} }
m = context.CurrentTransform.Invert()*renderTransform*m*context.CurrentTransform;
// Draw the control and its children. using (context.PushTransform(m))
var m = transform * translation;
var d = context.PushTransform(m);
using (context.PushOpacity(opacity)) using (context.PushOpacity(opacity))
using (visual.ClipToBounds ? context.PushClip(new Rect(visual.Bounds.Size)) : null) using (visual.ClipToBounds ? context.PushClip(new Rect(visual.Bounds.Size)) : null)
{ {
visual.Render(context); visual.Render(context);
d.Dispose();
foreach (var child in visual.VisualChildren.OrderBy(x => x.ZIndex)) foreach (var child in visual.VisualChildren.OrderBy(x => x.ZIndex))
{ {
context.Render(child, translation, transform); context.Render(child);
} }
} }
} }

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

@ -53,8 +53,12 @@ namespace Perspex.Direct2D1.Media
out drawRect); out drawRect);
var renderer = new RenderTarget(intermediate); var renderer = new RenderTarget(intermediate);
renderer.Render(visual, transform, drawRect); using (var ctx = renderer.CreateDrawingContext())
using (ctx.PushClip(drawRect))
using (ctx.PushTransform(transform))
{
ctx.Render(visual);
}
this.PlatformBrush = new BitmapBrush( this.PlatformBrush = new BitmapBrush(
target, target,
intermediate.Bitmap, intermediate.Bitmap,

12
src/Windows/Perspex.Direct2D1/RenderTarget.cs

@ -91,13 +91,23 @@ namespace Perspex.Direct2D1
window.Resize(new Size2(width, height)); window.Resize(new Size2(width, height));
} }
IDrawingContext Wrap(IDrawingContext ctx)
{
#if DEBUG
return new ValidatingDrawingContext(ctx);
#endif
#pragma warning disable 162
return ctx;
#pragma warning restore 162
}
/// <summary> /// <summary>
/// Creates a drawing context for a rendering session. /// Creates a drawing context for a rendering session.
/// </summary> /// </summary>
/// <returns>An <see cref="IDrawingContext"/>.</returns> /// <returns>An <see cref="IDrawingContext"/>.</returns>
public IDrawingContext CreateDrawingContext() public IDrawingContext CreateDrawingContext()
{ {
return new DrawingContext(_renderTarget, DirectWriteFactory); return Wrap(new DrawingContext(_renderTarget, DirectWriteFactory));
} }
public void Dispose() public void Dispose()

Loading…
Cancel
Save