// ----------------------------------------------------------------------- // // Copyright 2013 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex.Direct2D1 { using System; using System.Linq; using Perspex.Direct2D1.Media; using Perspex.Media; using Perspex.Platform; using SharpDX; using SharpDX.Direct2D1; using Splat; using DwFactory = SharpDX.DirectWrite.Factory; using Matrix = Perspex.Matrix; using Point = Perspex.Point; public class Renderer : IRenderer { /// /// The render target. /// private RenderTarget renderTarget; /// /// Initializes a new instance of the class. /// /// The window handle. /// The width of the window. /// The height of the window. public Renderer(IntPtr hwnd, double width, double height) { this.Direct2DFactory = Locator.Current.GetService(); this.DirectWriteFactory = Locator.Current.GetService(); RenderTargetProperties renderTargetProperties = new RenderTargetProperties { }; HwndRenderTargetProperties hwndProperties = new HwndRenderTargetProperties { Hwnd = hwnd, PixelSize = new Size2((int)width, (int)height), PresentOptions = PresentOptions.Immediately, }; this.renderTarget = new WindowRenderTarget( this.Direct2DFactory, renderTargetProperties, hwndProperties); } /// /// Initializes a new instance of the class. /// /// The render target. public Renderer(RenderTarget renderTarget) { this.Direct2DFactory = Locator.Current.GetService(); this.DirectWriteFactory = Locator.Current.GetService(); this.renderTarget = renderTarget; } /// /// Gets the Direct2D factory. /// public Factory Direct2DFactory { get; private set; } /// /// Gets the DirectWrite factory. /// public DwFactory DirectWriteFactory { get; private set; } /// /// Gets the number of times has been called. /// public int RenderCount { get; private set; } /// /// Renders the specified visual. /// /// The visual to render. /// Unused. public void Render(IVisual visual, IPlatformHandle handle) { using (DrawingContext context = new DrawingContext(this.renderTarget, this.DirectWriteFactory)) { this.Render(visual, context, Matrix.Identity, Matrix.Identity); } ++this.RenderCount; } /// /// Resizes the renderer. /// /// The new width. /// The new height. public void Resize(int width, int height) { WindowRenderTarget window = this.renderTarget as WindowRenderTarget; if (window == null) { throw new InvalidOperationException(string.Format( "A renderer with a target of type '{0}' cannot be resized.", this.renderTarget.GetType().Name)); } window.Resize(new Size2(width, height)); } /// /// Renders the specified visual. /// /// The visual to render. /// The drawing context. private void Render(IVisual visual, DrawingContext context, Matrix translation, Matrix transform) { if (visual.IsVisible && visual.Opacity > 0) { // Translate any existing transform into this controls coordinate system. Matrix offset = Matrix.Translation(visual.Bounds.Position); transform = offset * transform * -offset; // Update the current offset. translation *= Matrix.Translation(visual.Bounds.Position); // Apply the control's render transform, if any. if (visual.RenderTransform != null) { offset = Matrix.Translation(visual.TransformOrigin.ToPixels(visual.Bounds.Size)); transform *= -offset * visual.RenderTransform.Value * offset; } // Draw the control and its children. var m = transform * translation; var d = context.PushTransform(m); using (visual.ClipToBounds ? context.PushClip(visual.Bounds) : null) { visual.Render(context); d.Dispose(); foreach (var child in visual.VisualChildren) { this.Render(child, context, translation, transform); } } } } } }