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);
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;
var transform = CalculateIntermediateTransform(
@ -111,12 +111,12 @@ namespace Perspex.Cairo.Media
scale,
translate,
out drawRect);
var renderer = new RenderTarget(intermediate);
context.Rectangle(drawRect.ToCairo());
context.Clip();
context.Transform(transform.ToCairo());
renderer.Render(visual, transform, drawRect);
using (ctx.PushClip(drawRect))
using (ctx.PushTransform(transform))
{
ctx.Render(visual);
}
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\TileBrush.cs" />
<Compile Include="Media\ImageBush.cs" />
<Compile Include="Media\ValidatingDrawingContext.cs" />
<Compile Include="Media\VisualBrush.cs" />
<Compile Include="RelativePoint.cs" />
<Compile Include="Platform\IFormattedTextImpl.cs" />

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

@ -27,31 +27,7 @@ namespace Perspex.Rendering
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>
/// Renders the specified visual.
@ -60,65 +36,29 @@ namespace Perspex.Rendering
///
/// <param name="context">The drawing context.</param>
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;
if (visual.IsVisible && opacity > 0)
{
// Translate any existing transform into this controls coordinate system.
Matrix offset = Matrix.CreateTranslation(visual.Bounds.Position);
transform = offset * transform * -offset;
var m = Matrix.CreateTranslation(visual.Bounds.Position);
// Update the current offset.
translation *= Matrix.CreateTranslation(visual.Bounds.Position);
var renderTransform = Matrix.Identity;
// Apply the control's render transform, if any.
if (visual.RenderTransform != null)
{
offset = Matrix.CreateTranslation(visual.TransformOrigin.ToPixels(visual.Bounds.Size));
transform *= -offset * visual.RenderTransform.Value * offset;
var offset = -Matrix.CreateTranslation(visual.TransformOrigin.ToPixels(visual.Bounds.Size));
renderTransform = offset*visual.RenderTransform.Value;
}
m = context.CurrentTransform.Invert()*renderTransform*m*context.CurrentTransform;
// Draw the control and its children.
var m = transform * translation;
var d = context.PushTransform(m);
using (context.PushTransform(m))
using (context.PushOpacity(opacity))
using (visual.ClipToBounds ? context.PushClip(new Rect(visual.Bounds.Size)) : null)
{
visual.Render(context);
d.Dispose();
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);
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(
target,
intermediate.Bitmap,

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

@ -91,13 +91,23 @@ namespace Perspex.Direct2D1
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>
/// Creates a drawing context for a rendering session.
/// </summary>
/// <returns>An <see cref="IDrawingContext"/>.</returns>
public IDrawingContext CreateDrawingContext()
{
return new DrawingContext(_renderTarget, DirectWriteFactory);
return Wrap(new DrawingContext(_renderTarget, DirectWriteFactory));
}
public void Dispose()

Loading…
Cancel
Save