예제 #1
0
 void fillPath(DrawingPointF begin, Action <GeometrySink> figureBuilder)
 {
     using (var geometry = createPath(true, begin, figureBuilder))
     {
         _target.FillGeometry(geometry, _fillBrush.Brush);
     }
 }
예제 #2
0
 void SimplifiedGeometrySink.AddLines(DrawingPointF[] ointsRef)
 {
     foreach(DrawingPointF point in ointsRef)
     {
         _Builder.LineTo(point.X, point.Y);
     }
 }
예제 #3
0
 void drawClosedPath(DrawingPointF begin, Action <GeometrySink> figureBuilder)
 {
     using (var geometry = createPath(true, begin, figureBuilder))
     {
         _target.DrawGeometry(geometry, _strokeBrush.Brush, StrokeWeight);
     }
 }
예제 #4
0
        // 繪圖主要方法
        public virtual void Render(TargetBase target)
        {
            var context2D = target.DeviceManager.ContextDirect2D;

            context2D.BeginDraw();
            context2D.Clear(Color.White);

            var sizeX = (float)target.RenderTargetBounds.Width;
            var sizeY = (float)target.RenderTargetBounds.Height;

            try
            {
                if (MainPage.pointers != null)
                {
                    for (int j = 0; j < MainPage.pointers.Count; j++)
                    {
                        // Different color for touch points
                        lineColorBrush = new SolidColorBrush(context2D, MainPage.pointers[j].color);

                        for (int i = 0; i < MainPage.pointers[j].Pointers.Count; i++)
                        {
                            if (i == MainPage.pointers[j].Pointers.Count - 1)
                            {
                                float x = (float)MainPage.pointers[j].Pointers[i].X;
                                float y = (float)MainPage.pointers[j].Pointers[i].Y;
                                // Pointers info
                                context2D.DrawText(string.Format("PointerID:{0}\nX:{1}\nY:{2}\n{3}", MainPage.pointers[j].PointerId, x, y, MainPage.pointers[j].DeviceType.ToString())
                                                   , textFormat, new RectangleF(x - 150, y - 100, x - 20, y - 20), sceneColorBrush);

                                // Draw horizontal line
                                context2D.DrawLine(new DrawingPointF(0, y), new DrawingPointF(context2D.PixelSize.Width, y), lineColorBrush);
                                // Draw vertical line
                                context2D.DrawLine(new DrawingPointF(x, 0), new DrawingPointF(x, context2D.PixelSize.Height), lineColorBrush);
                                // Draw a circle (and like a Crosshair :D )
                                ellipse = new Ellipse(new DrawingPointF(x, y), 30, 30);
                                context2D.DrawEllipse(ellipse, lineColorBrush);
                                continue;
                            }

                            var beginPoint = new DrawingPointF((float)MainPage.pointers[j].Pointers[i].X, (float)MainPage.pointers[j].Pointers[i].Y);
                            var endPoint   = new DrawingPointF((float)MainPage.pointers[j].Pointers[i + 1].X, (float)MainPage.pointers[j].Pointers[i + 1].Y);
                            context2D.DrawLine(beginPoint, endPoint, lineColorBrush, 10, strokeStyle);
                        }
                    }

                    // Update pointers contacts
                    context2D.DrawText(string.Format("Pointers Count:{0}/{1}", MainPage.pointers.Count, TouchCapabilities.Contacts), textFormat2, new RectangleF(8, 30, 8 + 200, 30 + 16), sceneColorBrush);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Error:" + ex);
            }

            context2D.EndDraw();
        }
예제 #5
0
 public static PathGeometry Figure(Factory factory, bool filled, DrawingPointF begin, Action <GeometrySink> figureBuilder)
 {
     return(Geometry(factory,
                     sink =>
     {
         sink.BeginFigure(begin, filled ? FigureBegin.Filled : FigureBegin.Hollow);
         figureBuilder(sink);
         sink.EndFigure(filled ? FigureEnd.Closed : FigureEnd.Open);
     }));
 }
 public void AddLines(DrawingPointF[] ointsRef)
 {
     AddLines_(ointsRef, ointsRef.Length);
 }
예제 #7
0
        public void Run()
        {
            var form = new RenderForm("2d and 3d combined...it's like magic");

            form.KeyDown += (sender, args) => { if (args.KeyCode == Keys.Escape)
                                                {
                                                    form.Close();
                                                }
            };

            // DirectX DXGI 1.1 factory
            var factory1 = new Factory1();

            // The 1st graphics adapter
            var adapter1 = factory1.GetAdapter1(0);

            // ---------------------------------------------------------------------------------------------
            // Setup direct 3d version 11. It's context will be used to combine the two elements
            // ---------------------------------------------------------------------------------------------

            var description = new SwapChainDescription
            {
                BufferCount       = 1,
                ModeDescription   = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm),
                IsWindowed        = true,
                OutputHandle      = form.Handle,
                SampleDescription = new SampleDescription(1, 0),
                SwapEffect        = SwapEffect.Discard,
                Usage             = Usage.RenderTargetOutput,
                Flags             = SwapChainFlags.AllowModeSwitch
            };

            Device11  device11;
            SwapChain swapChain;

            Device11.CreateWithSwapChain(adapter1, DeviceCreationFlags.None, description, out device11, out swapChain);

            // create a view of our render target, which is the backbuffer of the swap chain we just created
            RenderTargetView renderTargetView;

            using (var resource = Resource.FromSwapChain <Texture2D>(swapChain, 0))
                renderTargetView = new RenderTargetView(device11, resource);

            // setting a viewport is required if you want to actually see anything
            var context = device11.ImmediateContext;

            var viewport = new Viewport(0.0f, 0.0f, form.ClientSize.Width, form.ClientSize.Height);

            context.OutputMerger.SetTargets(renderTargetView);
            context.Rasterizer.SetViewports(viewport);

            //
            // Create the DirectX11 texture2D. This texture will be shared with the DirectX10 device.
            //
            // The DirectX10 device will be used to render text onto this texture.
            // DirectX11 will then draw this texture (blended) onto the screen.
            // The KeyedMutex flag is required in order to share this resource between the two devices.
            var textureD3D11 = new Texture2D(device11, new Texture2DDescription
            {
                Width             = form.ClientSize.Width,
                Height            = form.ClientSize.Height,
                MipLevels         = 1,
                ArraySize         = 1,
                Format            = Format.B8G8R8A8_UNorm,
                SampleDescription = new SampleDescription(1, 0),
                Usage             = ResourceUsage.Default,
                BindFlags         = BindFlags.RenderTarget | BindFlags.ShaderResource,
                CpuAccessFlags    = CpuAccessFlags.None,
                OptionFlags       = ResourceOptionFlags.SharedKeyedmutex
            });

            // ---------------------------------------------------------------------------------------------
            // Setup a direct 3d version 10.1 adapter
            // ---------------------------------------------------------------------------------------------
            var device10 = new Device10(adapter1, SharpDX.Direct3D10.DeviceCreationFlags.BgraSupport, FeatureLevel.Level_10_0);

            // ---------------------------------------------------------------------------------------------
            // Setup Direct 2d
            // ---------------------------------------------------------------------------------------------

            // Direct2D Factory
            var factory2D = new SharpDX.Direct2D1.Factory(FactoryType.SingleThreaded, DebugLevel.Information);

            // Here we bind the texture we've created on our direct3d11 device through the direct3d10
            // to the direct 2d render target....
            var sharedResource = textureD3D11.QueryInterface <SharpDX.DXGI.Resource>();
            var textureD3D10   = device10.OpenSharedResource <SharpDX.Direct3D10.Texture2D>(sharedResource.SharedHandle);

            var surface = textureD3D10.AsSurface();
            var rtp     = new RenderTargetProperties
            {
                MinLevel    = SharpDX.Direct2D1.FeatureLevel.Level_10,
                Type        = RenderTargetType.Hardware,
                PixelFormat = new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)
            };

            var renderTarget2D  = new RenderTarget(factory2D, surface, rtp);
            var solidColorBrush = new SolidColorBrush(renderTarget2D, Colors.Red);

            // ---------------------------------------------------------------------------------------------------
            // Setup the rendering data
            // ---------------------------------------------------------------------------------------------------

            // Load Effect. This includes both the vertex and pixel shaders.
            // Also can include more than one technique.
            ShaderBytecode shaderByteCode = ShaderBytecode.CompileFromFile(
                "effectDx11.fx",
                "fx_5_0",
                ShaderFlags.EnableStrictness);

            var effect = new Effect(device11, shaderByteCode);

            // create triangle vertex data, making sure to rewind the stream afterward
            var verticesTriangle = new DataStream(VertexPositionColor.SizeInBytes * 3, true, true);

            verticesTriangle.Write(new VertexPositionColor(new Vector3(0.0f, 0.5f, 0.5f), new Color4(1.0f, 0.0f, 0.0f, 1.0f)));
            verticesTriangle.Write(new VertexPositionColor(new Vector3(0.5f, -0.5f, 0.5f), new Color4(0.0f, 1.0f, 0.0f, 1.0f)));
            verticesTriangle.Write(new VertexPositionColor(new Vector3(-0.5f, -0.5f, 0.5f), new Color4(0.0f, 0.0f, 1.0f, 1.0f)));

            verticesTriangle.Position = 0;

            // create the triangle vertex layout and buffer
            var layoutColor       = new InputLayout(device11, effect.GetTechniqueByName("Color").GetPassByIndex(0).Description.Signature, VertexPositionColor.inputElements);
            var vertexBufferColor = new Buffer(device11, verticesTriangle, (int)verticesTriangle.Length, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);

            verticesTriangle.Close();

            // create overlay vertex data, making sure to rewind the stream afterward
            // Top Left of screen is -1, +1
            // Bottom Right of screen is +1, -1
            var verticesText = new DataStream(VertexPositionTexture.SizeInBytes * 4, true, true);

            verticesText.Write(new VertexPositionTexture(new Vector3(-1, 1, 0), new Vector2(0, 0f)));
            verticesText.Write(new VertexPositionTexture(new Vector3(1, 1, 0), new Vector2(1, 0)));
            verticesText.Write(new VertexPositionTexture(new Vector3(-1, -1, 0), new Vector2(0, 1)));
            verticesText.Write(new VertexPositionTexture(new Vector3(1, -1, 0), new Vector2(1, 1)));

            verticesText.Position = 0;

            // create the overlay vertex layout and buffer
            var layoutOverlay       = new InputLayout(device11, effect.GetTechniqueByName("Overlay").GetPassByIndex(0).Description.Signature, VertexPositionTexture.inputElements);
            var vertexBufferOverlay = new Buffer(device11, verticesText, (int)verticesText.Length, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);

            verticesText.Close();

            // Think of the shared textureD3D10 as an overlay.
            // The overlay needs to show the 2d content but let the underlying triangle (or whatever)
            // show thru, which is accomplished by blending.
            var bsd = new BlendStateDescription();

            bsd.RenderTarget[0].IsBlendEnabled        = true;
            bsd.RenderTarget[0].SourceBlend           = BlendOption.SourceColor;
            bsd.RenderTarget[0].DestinationBlend      = BlendOption.BlendFactor;
            bsd.RenderTarget[0].BlendOperation        = BlendOperation.Add;
            bsd.RenderTarget[0].SourceAlphaBlend      = BlendOption.One;
            bsd.RenderTarget[0].DestinationAlphaBlend = BlendOption.Zero;
            bsd.RenderTarget[0].AlphaBlendOperation   = BlendOperation.Add;
            bsd.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All;

            var blendStateTransparent = new BlendState(device11, bsd);

            // ---------------------------------------------------------------------------------------------------
            // Create and tesselate an ellipse
            // ---------------------------------------------------------------------------------------------------
            var center  = new DrawingPointF(form.ClientSize.Width / 2.0f, form.ClientSize.Height / 2.0f);
            var ellipse = new EllipseGeometry(factory2D, new Ellipse(center, form.ClientSize.Width / 2.0f, form.ClientSize.Height / 2.0f));

            // Populate a PathGeometry from Ellipse tessellation
            var tesselatedGeometry = new PathGeometry(factory2D);

            _geometrySink = tesselatedGeometry.Open();

            // Force RoundLineJoin otherwise the tesselated looks buggy at line joins
            _geometrySink.SetSegmentFlags(PathSegment.ForceRoundLineJoin);

            // Tesselate the ellipse to our TessellationSink
            ellipse.Tessellate(1, this);

            _geometrySink.Close();

            // ---------------------------------------------------------------------------------------------------
            // Acquire the mutexes. These are needed to assure the device in use has exclusive access to the surface
            // ---------------------------------------------------------------------------------------------------

            var device10Mutex = textureD3D10.QueryInterface <KeyedMutex>();
            var device11Mutex = textureD3D11.QueryInterface <KeyedMutex>();

            // ---------------------------------------------------------------------------------------------------
            // Main rendering loop
            // ---------------------------------------------------------------------------------------------------

            bool first = true;

            RenderLoop
            .Run(form,
                 () =>
            {
                if (first)
                {
                    form.Activate();
                    first = false;
                }

                // clear the render target to black
                context.ClearRenderTargetView(renderTargetView, Colors.DarkSlateGray);

                // Draw the triangle
                context.InputAssembler.InputLayout       = layoutColor;
                context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
                context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBufferColor, VertexPositionColor.SizeInBytes, 0));
                context.OutputMerger.BlendState = null;
                var currentTechnique            = effect.GetTechniqueByName("Color");
                for (var pass = 0; pass < currentTechnique.Description.PassCount; ++pass)
                {
                    using (var effectPass = currentTechnique.GetPassByIndex(pass))
                    {
                        System.Diagnostics.Debug.Assert(effectPass.IsValid, "Invalid EffectPass");
                        effectPass.Apply(context);
                    }
                    context.Draw(3, 0);
                }
                ;

                // Draw Ellipse on the shared Texture2D
                device10Mutex.Acquire(0, 100);
                renderTarget2D.BeginDraw();
                renderTarget2D.Clear(Colors.Black);
                renderTarget2D.DrawGeometry(tesselatedGeometry, solidColorBrush);
                renderTarget2D.DrawEllipse(new Ellipse(center, 200, 200), solidColorBrush, 20, null);
                renderTarget2D.EndDraw();
                device10Mutex.Release(0);

                // Draw the shared texture2D onto the screen, blending the 2d content in
                device11Mutex.Acquire(0, 100);
                var srv = new ShaderResourceView(device11, textureD3D11);
                effect.GetVariableByName("g_Overlay").AsShaderResource().SetResource(srv);
                context.InputAssembler.InputLayout       = layoutOverlay;
                context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip;
                context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBufferOverlay, VertexPositionTexture.SizeInBytes, 0));
                context.OutputMerger.BlendState = blendStateTransparent;
                currentTechnique = effect.GetTechniqueByName("Overlay");

                for (var pass = 0; pass < currentTechnique.Description.PassCount; ++pass)
                {
                    using (var effectPass = currentTechnique.GetPassByIndex(pass))
                    {
                        System.Diagnostics.Debug.Assert(effectPass.IsValid, "Invalid EffectPass");
                        effectPass.Apply(context);
                    }
                    context.Draw(4, 0);
                }
                srv.Dispose();
                device11Mutex.Release(0);

                swapChain.Present(0, PresentFlags.None);
            });

            // dispose everything
            vertexBufferColor.Dispose();
            vertexBufferOverlay.Dispose();
            layoutColor.Dispose();
            layoutOverlay.Dispose();
            effect.Dispose();
            shaderByteCode.Dispose();
            renderTarget2D.Dispose();
            swapChain.Dispose();
            device11.Dispose();
            device10.Dispose();
            textureD3D10.Dispose();
            textureD3D11.Dispose();
            factory1.Dispose();
            adapter1.Dispose();
            sharedResource.Dispose();
            factory2D.Dispose();
            surface.Dispose();
            solidColorBrush.Dispose();
            blendStateTransparent.Dispose();

            device10Mutex.Dispose();
            device11Mutex.Dispose();
        }
예제 #8
0
 /// <summary>	
 /// Determines whether the geometry's stroke contains the specified point given the specified stroke thickness, style, and transform. 	
 /// </summary>	
 /// <param name="point">The point to test for containment. </param>
 /// <param name="strokeWidth">The thickness of the stroke to apply. </param>
 /// <param name="strokeStyle">The style of stroke to apply. </param>
 /// <returns>When this method returns, contains a boolean value set to true if the geometry's stroke contains the specified point; otherwise, false. You must allocate storage for this parameter. </returns>
 /// <unmanaged>HRESULT ID2D1Geometry::StrokeContainsPoint([None] D2D1_POINT_2F point,[None] float strokeWidth,[In, Optional] ID2D1StrokeStyle* strokeStyle,[In, Optional] const D2D1_MATRIX_3X2_F* worldTransform,[None] float flatteningTolerance,[Out] BOOL* contains)</unmanaged>
 public bool StrokeContainsPoint(DrawingPointF point, float strokeWidth, StrokeStyle strokeStyle)
 {
     return StrokeContainsPoint(point, strokeWidth, strokeStyle, null, FlatteningTolerance);
 }
예제 #9
0
 /// <summary>	
 /// Indicates whether the area filled by the geometry would contain the specified point given the specified flattening tolerance. 	
 /// </summary>	
 /// <param name="point">The point to test. </param>
 /// <param name="flatteningTolerance">The numeric accuracy with which the precise geometric path and path intersection is calculated. Points missing the fill by less than the tolerance are still considered inside.  Smaller values produce more accurate results but cause slower execution.  </param>
 /// <returns>When this method returns, contains a bool value that is true if the area filled by the geometry contains point; otherwise, false.You must allocate storage for this parameter. </returns>
 /// <unmanaged>HRESULT ID2D1Geometry::FillContainsPoint([None] D2D1_POINT_2F point,[In, Optional] const D2D1_MATRIX_3X2_F* worldTransform,[None] float flatteningTolerance,[Out] BOOL* contains)</unmanaged>
 public bool FillContainsPoint(DrawingPointF point, float flatteningTolerance)
 {
     return FillContainsPoint(point, null, flatteningTolerance);
 }
예제 #10
0
 void SimplifiedGeometrySink.BeginFigure(DrawingPointF startPoint, FigureBegin figureBegin)
 {
     _Builder.MoveTo(startPoint.X, startPoint.Y);
 }
        // 繪圖主要方法
        public virtual void Render(TargetBase target)
        {
            var context2D = target.DeviceManager.ContextDirect2D;

            context2D.BeginDraw();
            context2D.Clear(Color.White);

            var sizeX = (float)target.RenderTargetBounds.Width;
            var sizeY = (float)target.RenderTargetBounds.Height;

            try
            {
                if (MainPage.pointers != null)
                {
                    for (int j = 0; j < MainPage.pointers.Count; j++)
                    {
                        // Different color for touch points
                        lineColorBrush = new SolidColorBrush(context2D, MainPage.pointers[j].color);

                        for (int i = 0; i < MainPage.pointers[j].Pointers.Count; i++)
                        {
                            if (i == MainPage.pointers[j].Pointers.Count - 1)
                            {
                                float x = (float)MainPage.pointers[j].Pointers[i].X;
                                float y = (float)MainPage.pointers[j].Pointers[i].Y;
                                // Pointers info
                                context2D.DrawText(string.Format("PointerID:{0}\nX:{1}\nY:{2}\n{3}", MainPage.pointers[j].PointerId, x, y, MainPage.pointers[j].DeviceType.ToString())
                                    , textFormat, new RectangleF(x - 150, y - 100, x - 20, y - 20), sceneColorBrush);

                                // Draw horizontal line
                                context2D.DrawLine(new DrawingPointF(0, y), new DrawingPointF(context2D.PixelSize.Width, y), lineColorBrush);
                                // Draw vertical line
                                context2D.DrawLine(new DrawingPointF(x, 0), new DrawingPointF(x, context2D.PixelSize.Height), lineColorBrush);
                                // Draw a circle (and like a Crosshair :D )
                                ellipse = new Ellipse(new DrawingPointF(x, y), 30, 30);
                                context2D.DrawEllipse(ellipse, lineColorBrush);
                                continue;
                            }

                            var beginPoint = new DrawingPointF((float)MainPage.pointers[j].Pointers[i].X, (float)MainPage.pointers[j].Pointers[i].Y);
                            var endPoint = new DrawingPointF((float)MainPage.pointers[j].Pointers[i + 1].X, (float)MainPage.pointers[j].Pointers[i + 1].Y);
                            context2D.DrawLine(beginPoint, endPoint, lineColorBrush, 10, strokeStyle);
                        }
                    }

                    // Update pointers contacts
                    context2D.DrawText(string.Format("Pointers Count:{0}/{1}", MainPage.pointers.Count, TouchCapabilities.Contacts), textFormat2, new RectangleF(8, 30, 8 + 200, 30 + 16), sceneColorBrush);
                }

            }
            catch (Exception ex)
            {
                Debug.WriteLine("Error:" + ex);
            }

            context2D.EndDraw();
        }
예제 #12
0
 private static void AddLinesImpl(IntPtr thisPtr, IntPtr points, int pointsCount)
 {
     unsafe
     {
         var shadow = ToShadow<SimplifiedGeometrySinkShadow>(thisPtr);
         var callback = (SimplifiedGeometrySink)shadow.Callback;
         var managedPoints = new DrawingPointF[pointsCount];
         Utilities.Read(points, managedPoints, 0, pointsCount);
         callback.AddLines(managedPoints);
     }
 }
예제 #13
0
 /// <summary>	
 /// Draws the formatted text described by the specified <see cref="T:SharpDX.DirectWrite.TextLayout" /> object.	
 /// </summary>	
 /// <remarks>	
 /// When drawing the same text repeatedly, using the DrawTextLayout method is more efficient than using the {{DrawText}} method because the text doesn't need to be formatted and the layout processed with each call. This method doesn't return an error code if it fails. To determine whether a drawing operation (such as DrawTextLayout) failed, check the result returned by the <see cref="M:SharpDX.Direct2D1.RenderTarget.EndDraw(System.Int64@,System.Int64@)" /> or <see cref="M:SharpDX.Direct2D1.RenderTarget.Flush(System.Int64@,System.Int64@)" /> methods.  	
 /// </remarks>	
 /// <param name="origin">The point, described in device-independent pixels, at which the upper-left corner of the text described by textLayout is drawn. </param>
 /// <param name="textLayout">The formatted text to draw. Any drawing effects that do not inherit from <see cref="T:SharpDX.Direct2D1.Resource" /> are ignored. If there are drawing effects that inherit from ID2D1Resource that are not brushes, this method fails and the render target is put in an error state.  </param>
 /// <param name="defaultForegroundBrush">The brush used to paint any text in textLayout that does not already have a brush associated with it as a drawing effect (specified by the <see cref="M:SharpDX.DirectWrite.TextLayout.SetDrawingEffect(SharpDX.ComObject,SharpDX.DirectWrite.TextRange)" /> method).  </param>
 /// <unmanaged>void ID2D1RenderTarget::DrawTextLayout([None] D2D1_POINT_2F origin,[In] IDWriteTextLayout* textLayout,[In] ID2D1Brush* defaultForegroundBrush,[None] D2D1_DRAW_TEXT_OPTIONS options)</unmanaged>
 public void DrawTextLayout(DrawingPointF origin, TextLayout textLayout, Brush defaultForegroundBrush)
 {
     DrawTextLayout(origin, textLayout, defaultForegroundBrush, DrawTextOptions.None);
 }
예제 #14
0
 /// <summary>	
 /// Draws a line between the specified points. 	
 /// </summary>	
 /// <remarks>	
 /// This method doesn't return an error code if it fails. To determine whether a drawing operation (such as DrawLine) failed, check the result returned by the <see cref="M:SharpDX.Direct2D1.RenderTarget.EndDraw(System.Int64@,System.Int64@)" /> or <see cref="M:SharpDX.Direct2D1.RenderTarget.Flush(System.Int64@,System.Int64@)" /> methods.  	
 /// </remarks>	
 /// <param name="point0">The start point of the line, in device-independent pixels. </param>
 /// <param name="point1">The end point of the line, in device-independent pixels. </param>
 /// <param name="brush">The brush used to paint the line's stroke. </param>
 /// <param name="strokeWidth">A value greater than or equal to 0.0f that specifies the width of the stroke. If this parameter isn't specified, it defaults to 1.0f.  The stroke is centered on the line. </param>
 /// <unmanaged>void ID2D1RenderTarget::DrawLine([None] D2D1_POINT_2F point0,[None] D2D1_POINT_2F point1,[In] ID2D1Brush* brush,[None] float strokeWidth,[In, Optional] ID2D1StrokeStyle* strokeStyle)</unmanaged>
 public void DrawLine(DrawingPointF point0, DrawingPointF point1, Brush brush, float strokeWidth)
 {
     DrawLine(point0, point1, brush, strokeWidth, null);
 }
예제 #15
0
파일: Extensions.cs 프로젝트: fealty/Frost
        public static DrawingPointF ToPointF(this Point point)
        {
            DrawingPointF result = new DrawingPointF { X = point.X, Y = point.Y };

            return result;
        }
예제 #16
0
 private static unsafe void AddLineImpl(IntPtr thisPtr, DrawingPointF point)
 {
     var shadow = ToShadow<GeometrySinkShadow>(thisPtr);
     var callback = (GeometrySink)shadow.Callback; 
     callback.AddLine(point);
 }
예제 #17
0
 private void DrawLines(VertexPositionColor start, VertexPositionColor end)
 {
     var sharpStart = new DrawingPointF(start.Position.X, start.Position.Y);
     var sharpEnd = new DrawingPointF(end.Position.X, end.Position.Y);
     device.RenderTarget.DrawLine(sharpStart, sharpEnd, brush);
 }
        public void path(double x, double y, IPathCommand[] path, bool filled)
        {
            var ptr = _target.NativePointer;
            var pathGeometry = new PathGeometry(ptr);
            var sink = pathGeometry.Open();
            var fromPoint = new DrawingPointF(f(x), f(y));
            sink.BeginFigure(fromPoint, FigureBegin.Hollow);

            bool newGeometryStarting = false;

            foreach (var command in path)
            {
                if (newGeometryStarting)
                {
                    pathGeometry = new PathGeometry(ptr);
                    sink = pathGeometry.Open();
                    sink.BeginFigure(fromPoint, FigureBegin.Hollow);
                }

                if (command.Command == PathCommand.LineTo)
                {
                    var toPoint = new DrawingPointF(f(command.X), f(command.Y));
                    sink.AddLine(new DrawingPointF(f(command.X), f(command.Y)));
                    fromPoint = toPoint;
                }
                else if (command.Command == PathCommand.CurveTo)
                {
                    var toPoint = new DrawingPointF(f(command.X), f(command.Y));
                    var firstControlPoint = new DrawingPointF(f(command.XC1), f(command.YC1));
                    var secondControlPoint = new DrawingPointF(f(command.XC2), f(command.YC2));

                    sink.AddBezier(new BezierSegment()
                    {
                        Point1 = firstControlPoint,
                        Point2 = secondControlPoint,
                        Point3 = toPoint
                    });
                    fromPoint = toPoint;
                }
                else if (command.Command == PathCommand.MoveTo)
                {
                    sink.EndFigure(FigureEnd.Open);
                    fromPoint = new DrawingPointF(f(command.X), f(command.Y));
                    _target.FillGeometry(pathGeometry, _strokeBrush);
                    newGeometryStarting = true;
                }
                else
                    throw new Exception(string.Format(CultureInfo.InvariantCulture, "Unknown PathCommand: '{0}'", command.Command));
            }
            sink.EndFigure(FigureEnd.Open);
            _target.FillGeometry(pathGeometry, _strokeBrush);
        }
예제 #19
0
 private static void BeginFigureImpl(IntPtr thisPtr, DrawingPointF startPoint, SharpDX.Direct2D1.FigureBegin figureBegin)
 {
     var shadow = ToShadow<SimplifiedGeometrySinkShadow>(thisPtr);
     var callback = (SimplifiedGeometrySink)shadow.Callback;
     callback.BeginFigure(startPoint, figureBegin);
 }
예제 #20
0
파일: Ellipse.cs 프로젝트: Nezz/SharpDX
 /// <summary>
 /// Initializes a new instance of the <see cref="Ellipse"/> struct.
 /// </summary>
 /// <param name="center">The center.</param>
 /// <param name="radiusX">The radius X.</param>
 /// <param name="radiusY">The radius Y.</param>
 public Ellipse(DrawingPointF center, float radiusX, float radiusY)
 {
     Point = center;
     RadiusX = radiusX;
     RadiusY = radiusY;
 }
예제 #21
0
파일: Drawer.cs 프로젝트: fealty/Frost
        public void Stroke(
			Point lineStart, Point lineEnd, Brush brush, StrokeStyle style, float strokeWidth)
        {
            Contract.Requires(brush != null);
            Contract.Requires(style != null);
            Contract.Requires(Check.IsPositive(strokeWidth));
            Contract.Assert(_Target != null);

            DrawingPointF start = new DrawingPointF { X = lineStart.X, Y = lineStart.Y };
            DrawingPointF end = new DrawingPointF { X = lineEnd.X, Y = lineEnd.Y };

            _Target.DrawLine(start, end, brush, strokeWidth, style);
        }
예제 #22
0
 void GeometrySink.AddLine(DrawingPointF point)
 {
     throw new NotSupportedException();
 }
예제 #23
0
        public virtual void Render(TargetBase target)
        {
            if (!Show)
                return;

            var context2D = target.DeviceManager.ContextDirect2D;

            context2D.BeginDraw();

            if (EnableClear)
                context2D.Clear(Colors.Black);

            var sizeX = (float)target.RenderTargetBounds.Width;
            var sizeY = (float)target.RenderTargetBounds.Height;
            var globalScaling = Matrix.Scaling(Math.Min(sizeX, sizeY));

            var centerX = (float)(target.RenderTargetBounds.X + sizeX / 2.0f);
            var centerY = (float)(target.RenderTargetBounds.Y + sizeY / 2.0f);

            if (textFormat == null)
            {
                // Initialize a TextFormat
                textFormat = new TextFormat(target.DeviceManager.FactoryDirectWrite, "Calibri", 96 * sizeX / 1920) { TextAlignment = TextAlignment.Center, ParagraphAlignment = ParagraphAlignment.Center };
            }

            if (pathGeometry1 == null)
            {
                var sizeShape = sizeX / 4.0f;

                // Creates a random geometry inside a circle
                pathGeometry1 = new PathGeometry1(target.DeviceManager.FactoryDirect2D);
                var pathSink = pathGeometry1.Open();
                var startingPoint = new DrawingPointF(sizeShape * 0.5f, 0.0f);
                pathSink.BeginFigure(startingPoint, FigureBegin.Hollow);
                for (int i = 0; i < 128; i++)
                {
                    float angle = (float)i / 128.0f * (float)Math.PI * 2.0f;
                    float R = (float)(Math.Cos(angle) * 0.1f + 0.4f);
                    R *= sizeShape;
                    DrawingPointF point1 = new DrawingPointF(R * (float)Math.Cos(angle), R * (float)Math.Sin(angle));

                    if ((i & 1) > 0)
                    {
                        R = (float)(Math.Sin(angle * 6.0f) * 0.1f + 0.9f);
                        R *= sizeShape;
                        point1 = new DrawingPointF(R * (float)Math.Cos(angle + Math.PI / 12), R * (float)Math.Sin(angle + Math.PI / 12));
                    }
                    pathSink.AddLine(point1);
                }
                pathSink.EndFigure(FigureEnd.Open);
                pathSink.Close();
            }

            context2D.TextAntialiasMode = TextAntialiasMode.Grayscale;
            float t = clock.ElapsedMilliseconds / 1000.0f;

            context2D.Transform = Matrix.RotationZ((float)(Math.Cos(t * 2.0f * Math.PI * 0.5f))) * Matrix.Translation(centerX, centerY, 0);

            context2D.DrawText("SharpDX\nDirect2D1\nDirectWrite", textFormat, new RectangleF(-sizeX / 2.0f, -sizeY / 2.0f, +sizeX/2.0f, sizeY/2.0f), sceneColorBrush);

            float scaling = (float)(Math.Cos(t * 2.0 * Math.PI * 0.25) * 0.5f + 0.5f) * 0.5f + 0.5f;
            context2D.Transform = Matrix.Scaling(scaling) * Matrix.RotationZ(t * 1.5f) * Matrix.Translation(centerX, centerY, 0);

            context2D.DrawGeometry(pathGeometry1, sceneColorBrush, 2.0f);

            context2D.EndDraw();
        }
예제 #24
0
 PathGeometry createPath(bool filled, DrawingPointF begin, Action <GeometrySink> figureBuilder)
 {
     return(Path.Figure(_target.Factory, filled, begin, figureBuilder));
 }
예제 #25
0
 public void AddLine(DrawingPointF point)
 {
     AddLine_(point);
 }
예제 #26
0
        public void Run()
        {
            var form = new RenderForm("2d and 3d combined...it's like magic");
            form.KeyDown += (sender, args) => { if (args.KeyCode == Keys.Escape) form.Close(); };

            // DirectX DXGI 1.1 factory
            var factory1 = new Factory1();

            // The 1st graphics adapter
            var adapter1 = factory1.GetAdapter1(0);

            // ---------------------------------------------------------------------------------------------
            // Setup direct 3d version 11. It's context will be used to combine the two elements
            // ---------------------------------------------------------------------------------------------

            var description = new SwapChainDescription
                {
                    BufferCount = 1,
                    ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm),
                    IsWindowed = true,
                    OutputHandle = form.Handle,
                    SampleDescription = new SampleDescription(1, 0),
                    SwapEffect = SwapEffect.Discard,
                    Usage = Usage.RenderTargetOutput,
                    Flags = SwapChainFlags.AllowModeSwitch
                };

            Device11 device11;
            SwapChain swapChain;

            Device11.CreateWithSwapChain(adapter1, DeviceCreationFlags.None, description, out device11, out swapChain);

            // create a view of our render target, which is the backbuffer of the swap chain we just created
            RenderTargetView renderTargetView;
            using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0))
                renderTargetView = new RenderTargetView(device11, resource);

            // setting a viewport is required if you want to actually see anything
            var context = device11.ImmediateContext;

            var viewport = new Viewport(0.0f, 0.0f, form.ClientSize.Width, form.ClientSize.Height);
            context.OutputMerger.SetTargets(renderTargetView);
            context.Rasterizer.SetViewports(viewport);

            //
            // Create the DirectX11 texture2D. This texture will be shared with the DirectX10 device.
            //
            // The DirectX10 device will be used to render text onto this texture.
            // DirectX11 will then draw this texture (blended) onto the screen.
            // The KeyedMutex flag is required in order to share this resource between the two devices.
            var textureD3D11 = new Texture2D(device11, new Texture2DDescription
            {
                Width = form.ClientSize.Width,
                Height = form.ClientSize.Height,
                MipLevels = 1,
                ArraySize = 1,
                Format = Format.B8G8R8A8_UNorm,
                SampleDescription = new SampleDescription(1, 0),
                Usage = ResourceUsage.Default,
                BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
                CpuAccessFlags = CpuAccessFlags.None,
                OptionFlags = ResourceOptionFlags.SharedKeyedmutex
            });

            // ---------------------------------------------------------------------------------------------
            // Setup a direct 3d version 10.1 adapter
            // ---------------------------------------------------------------------------------------------
            var device10 = new Device10(adapter1, SharpDX.Direct3D10.DeviceCreationFlags.BgraSupport, FeatureLevel.Level_10_0);

            // ---------------------------------------------------------------------------------------------
            // Setup Direct 2d
            // ---------------------------------------------------------------------------------------------

            // Direct2D Factory
            var factory2D = new SharpDX.Direct2D1.Factory(FactoryType.SingleThreaded, DebugLevel.Information);

            // Here we bind the texture we've created on our direct3d11 device through the direct3d10
            // to the direct 2d render target....
            var sharedResource = textureD3D11.QueryInterface<SharpDX.DXGI.Resource>();
            var textureD3D10 = device10.OpenSharedResource<SharpDX.Direct3D10.Texture2D>(sharedResource.SharedHandle);

            var surface = textureD3D10.AsSurface();
            var rtp = new RenderTargetProperties
                {
                    MinLevel = SharpDX.Direct2D1.FeatureLevel.Level_10,
                    Type = RenderTargetType.Hardware,
                    PixelFormat = new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)
                };

            var renderTarget2D = new RenderTarget(factory2D, surface, rtp);
            var solidColorBrush = new SolidColorBrush(renderTarget2D, Colors.Red);

            // ---------------------------------------------------------------------------------------------------
            // Setup the rendering data
            // ---------------------------------------------------------------------------------------------------

            // Load Effect. This includes both the vertex and pixel shaders.
            // Also can include more than one technique.
            ShaderBytecode shaderByteCode = ShaderBytecode.CompileFromFile(
                "effectDx11.fx",
                "fx_5_0",
                ShaderFlags.EnableStrictness);

            var effect = new Effect(device11, shaderByteCode);

            // create triangle vertex data, making sure to rewind the stream afterward
            var verticesTriangle = new DataStream(VertexPositionColor.SizeInBytes * 3, true, true);
            verticesTriangle.Write(new VertexPositionColor(new Vector3(0.0f, 0.5f, 0.5f),new Color4(1.0f, 0.0f, 0.0f, 1.0f)));
            verticesTriangle.Write(new VertexPositionColor(new Vector3(0.5f, -0.5f, 0.5f),new Color4(0.0f, 1.0f, 0.0f, 1.0f)));
            verticesTriangle.Write(new VertexPositionColor(new Vector3(-0.5f, -0.5f, 0.5f),new Color4(0.0f, 0.0f, 1.0f, 1.0f)));

            verticesTriangle.Position = 0;

            // create the triangle vertex layout and buffer
            var layoutColor = new InputLayout(device11, effect.GetTechniqueByName("Color").GetPassByIndex(0).Description.Signature, VertexPositionColor.inputElements);
            var vertexBufferColor = new Buffer(device11, verticesTriangle, (int)verticesTriangle.Length, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
            verticesTriangle.Close();

            // create overlay vertex data, making sure to rewind the stream afterward
            // Top Left of screen is -1, +1
            // Bottom Right of screen is +1, -1
            var verticesText = new DataStream(VertexPositionTexture.SizeInBytes * 4, true, true);
            verticesText.Write(new VertexPositionTexture(new Vector3(-1, 1, 0),new Vector2(0, 0f)));
            verticesText.Write(new VertexPositionTexture(new Vector3(1, 1, 0),new Vector2(1, 0)));
            verticesText.Write(new VertexPositionTexture(new Vector3(-1, -1, 0),new Vector2(0, 1)));
            verticesText.Write(new VertexPositionTexture(new Vector3(1, -1, 0),new Vector2(1, 1)));

            verticesText.Position = 0;

            // create the overlay vertex layout and buffer
            var layoutOverlay = new InputLayout(device11, effect.GetTechniqueByName("Overlay").GetPassByIndex(0).Description.Signature, VertexPositionTexture.inputElements);
            var vertexBufferOverlay = new Buffer(device11, verticesText, (int)verticesText.Length, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
            verticesText.Close();

            // Think of the shared textureD3D10 as an overlay.
            // The overlay needs to show the 2d content but let the underlying triangle (or whatever)
            // show thru, which is accomplished by blending.
            var bsd = new BlendStateDescription();
            bsd.RenderTarget[0].IsBlendEnabled = true;
            bsd.RenderTarget[0].SourceBlend = BlendOption.SourceColor;
            bsd.RenderTarget[0].DestinationBlend = BlendOption.BlendFactor;
            bsd.RenderTarget[0].BlendOperation = BlendOperation.Add;
            bsd.RenderTarget[0].SourceAlphaBlend = BlendOption.One;
            bsd.RenderTarget[0].DestinationAlphaBlend = BlendOption.Zero;
            bsd.RenderTarget[0].AlphaBlendOperation = BlendOperation.Add;
            bsd.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All;

            var blendStateTransparent = new BlendState(device11, bsd);

            // ---------------------------------------------------------------------------------------------------
            // Create and tesselate an ellipse
            // ---------------------------------------------------------------------------------------------------
            var center = new DrawingPointF(form.ClientSize.Width/2.0f, form.ClientSize.Height/2.0f);
            var ellipse = new EllipseGeometry(factory2D, new Ellipse(center, form.ClientSize.Width / 2.0f, form.ClientSize.Height / 2.0f));

            // Populate a PathGeometry from Ellipse tessellation
            var tesselatedGeometry = new PathGeometry(factory2D);
            _geometrySink = tesselatedGeometry.Open();

            // Force RoundLineJoin otherwise the tesselated looks buggy at line joins
            _geometrySink.SetSegmentFlags(PathSegment.ForceRoundLineJoin);

            // Tesselate the ellipse to our TessellationSink
            ellipse.Tessellate(1, this);

            _geometrySink.Close();

            // ---------------------------------------------------------------------------------------------------
            // Acquire the mutexes. These are needed to assure the device in use has exclusive access to the surface
            // ---------------------------------------------------------------------------------------------------

            var device10Mutex = textureD3D10.QueryInterface<KeyedMutex>();
            var device11Mutex = textureD3D11.QueryInterface<KeyedMutex>();

            // ---------------------------------------------------------------------------------------------------
            // Main rendering loop
            // ---------------------------------------------------------------------------------------------------

            bool first = true;

            RenderLoop
                .Run(form,
                     () =>
                         {
                             if(first)
                             {
                                 form.Activate();
                                 first = false;
                             }

                             // clear the render target to black
                             context.ClearRenderTargetView(renderTargetView, Colors.DarkSlateGray);

                             // Draw the triangle
                             context.InputAssembler.InputLayout = layoutColor;
                             context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
                             context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBufferColor, VertexPositionColor.SizeInBytes, 0));
                             context.OutputMerger.BlendState = null;
                             var currentTechnique = effect.GetTechniqueByName("Color");
                             for (var pass = 0; pass < currentTechnique.Description.PassCount; ++pass)
                             {
                                 using (var effectPass = currentTechnique.GetPassByIndex(pass))
                                 {
                                     System.Diagnostics.Debug.Assert(effectPass.IsValid, "Invalid EffectPass");
                                     effectPass.Apply(context);
                                 }
                                 context.Draw(3, 0);
                             };

                             // Draw Ellipse on the shared Texture2D
                             device10Mutex.Acquire(0, 100);
                             renderTarget2D.BeginDraw();
                             renderTarget2D.Clear(Colors.Black);
                             renderTarget2D.DrawGeometry(tesselatedGeometry, solidColorBrush);
                             renderTarget2D.DrawEllipse(new Ellipse(center, 200, 200), solidColorBrush, 20, null);
                             renderTarget2D.EndDraw();
                             device10Mutex.Release(0);

                             // Draw the shared texture2D onto the screen, blending the 2d content in
                             device11Mutex.Acquire(0, 100);
                             var srv = new ShaderResourceView(device11, textureD3D11);
                             effect.GetVariableByName("g_Overlay").AsShaderResource().SetResource(srv);
                             context.InputAssembler.InputLayout = layoutOverlay;
                             context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip;
                             context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBufferOverlay, VertexPositionTexture.SizeInBytes, 0));
                             context.OutputMerger.BlendState = blendStateTransparent;
                             currentTechnique = effect.GetTechniqueByName("Overlay");

                             for (var pass = 0; pass < currentTechnique.Description.PassCount; ++pass)
                             {
                                 using (var effectPass = currentTechnique.GetPassByIndex(pass))
                                 {
                                     System.Diagnostics.Debug.Assert(effectPass.IsValid, "Invalid EffectPass");
                                     effectPass.Apply(context);
                                 }
                                 context.Draw(4, 0);
                             }
                             srv.Dispose();
                             device11Mutex.Release(0);

                             swapChain.Present(0, PresentFlags.None);
                         });

            // dispose everything
            vertexBufferColor.Dispose();
            vertexBufferOverlay.Dispose();
            layoutColor.Dispose();
            layoutOverlay.Dispose();
            effect.Dispose();
            shaderByteCode.Dispose();
            renderTarget2D.Dispose();
            swapChain.Dispose();
            device11.Dispose();
            device10.Dispose();
            textureD3D10.Dispose();
            textureD3D11.Dispose();
            factory1.Dispose();
            adapter1.Dispose();
            sharedResource.Dispose();
            factory2D.Dispose();
            surface.Dispose();
            solidColorBrush.Dispose();
            blendStateTransparent.Dispose();

            device10Mutex.Dispose();
            device11Mutex.Dispose();
        }
예제 #27
0
 /// <summary>	
 /// Calculates the point and tangent vector at the specified distance along the geometry after it has been transformed by the specified matrix and flattened using the specified tolerance.	
 /// </summary>	
 /// <param name="length">The distance along the geometry of the point and tangent to find. If this distance is less then 0, this method calculates the first point in the geometry. If this distance is greater than the length of the geometry, this method calculates the last point in the geometry. </param>
 /// <param name="flatteningTolerance">The maximum bounds on the distance between points in the polygonal approximation of the geometry. Smaller values produce more accurate results but cause slower execution. </param>
 /// <param name="unitTangentVector">Whenthis method returns, contains a reference to the tangent vector at the specified distance along the geometry. If the geometry is empty,  this vector contains NaN as its x and y values. You must allocate storage for this parameter. </param>
 /// <returns>The location at the specified distance along the geometry. If the geometry is empty,  this point contains NaN as its x and y values. </returns>
 /// <unmanaged>HRESULT ID2D1Geometry::ComputePointAtLength([None] float length,[In, Optional] const D2D1_MATRIX_3X2_F* worldTransform,[None] float flatteningTolerance,[Out, Optional] D2D1_POINT_2F* point,[Out, Optional] D2D1_POINT_2F* unitTangentVector)</unmanaged>
 public DrawingPointF ComputePointAtLength(float length, float flatteningTolerance, out DrawingPointF unitTangentVector)
 {
     return ComputePointAtLength(length, null, flatteningTolerance, out unitTangentVector);
 }
            public void Draw(RenderTarget renderTarget)
            {
                renderTarget.FillRectangle(OutputRectangle, _backgroundColor.Resource);

                var bufferedLine = _buffer.First;
                // Move to current line
                for (int i = 0; i < _currentLine; i++)
                    bufferedLine = bufferedLine.Next;

                DrawingPointF origin = new DrawingPointF(0f, OutputRectangle.Bottom);
                while (origin.Y > 0f && bufferedLine != null) {
                    origin.Y -= bufferedLine.Value.Text.Metrics.Height;
                    renderTarget.DrawTextLayout(origin, bufferedLine.Value.Text, bufferedLine.Value.TextColor);
                    bufferedLine = bufferedLine.Next;
                }
            }
예제 #29
0
 /// <summary>	
 /// Determines whether the geometry's stroke contains the specified point given the specified stroke thickness, style, and transform. 	
 /// </summary>	
 /// <param name="point">The point to test for containment. </param>
 /// <param name="strokeWidth">The thickness of the stroke to apply. </param>
 /// <returns>When this method returns, contains a boolean value set to true if the geometry's stroke contains the specified point; otherwise, false. You must allocate storage for this parameter. </returns>
 /// <unmanaged>HRESULT ID2D1Geometry::StrokeContainsPoint([None] D2D1_POINT_2F point,[None] float strokeWidth,[In, Optional] ID2D1StrokeStyle* strokeStyle,[In, Optional] const D2D1_MATRIX_3X2_F* worldTransform,[None] float flatteningTolerance,[Out] BOOL* contains)</unmanaged>
 public bool StrokeContainsPoint(DrawingPointF point, float strokeWidth)
 {
     return StrokeContainsPoint(point, strokeWidth, null);
 }
 public void BeginFigure(DrawingPointF startPoint, FigureBegin figureBegin)
 {
     BeginFigure_(startPoint, figureBegin);
 }
예제 #31
0
 /// <summary>	
 /// Determines whether the geometry's stroke contains the specified point given the specified stroke thickness, style, and transform. 	
 /// </summary>	
 /// <param name="point">The point to test for containment. </param>
 /// <param name="strokeWidth">The thickness of the stroke to apply. </param>
 /// <param name="strokeStyle">The style of stroke to apply. </param>
 /// <param name="transform">The transform to apply to the stroked geometry.  </param>
 /// <returns>When this method returns, contains a boolean value set to true if the geometry's stroke contains the specified point; otherwise, false. You must allocate storage for this parameter. </returns>
 /// <unmanaged>HRESULT ID2D1Geometry::StrokeContainsPoint([None] D2D1_POINT_2F point,[None] float strokeWidth,[In, Optional] ID2D1StrokeStyle* strokeStyle,[In, Optional] const D2D1_MATRIX_3X2_F* worldTransform,[None] float flatteningTolerance,[Out] BOOL* contains)</unmanaged>
 public bool StrokeContainsPoint(DrawingPointF point, float strokeWidth, StrokeStyle strokeStyle, Matrix3x2 transform)
 {
     return StrokeContainsPoint(point, strokeWidth, strokeStyle, transform, FlatteningTolerance);            
 }
            public void Update(long ticks)
            {
                _cursorAnimCounter += ticks;
                if (_cursorAnimCounter >= CURSOR_BLINK_DURATION) {
                    _cursorAnimCounter -= CURSOR_BLINK_DURATION;
                    _drawCursor = !_drawCursor;
                }

                // Calculate draw position for input cursor
                float hitX, hitY;
                _currentLayout.HitTestTextPosition(_text.Length - _cursorPosition, false, out hitX, out hitY);
                _cursorDrawingPoint = new DrawingPointF(OutputRectangle.Left + hitX, OutputRectangle.Top + hitY);

                if (!_hasTextChanged) return;  // If the text hasn't changed, nothing below needs to be done
                RemoveAndDispose<TextLayout>(ref _currentLayout);

                _currentLayout = ToDispose<TextLayout>(_assetManager.MakeTextLayout(_font.Resource, _text.ToString(), OutputRectangle.Width, float.MaxValue));
                OutputRectangle.Top = _outputView.OutputRectangle.Bottom;
                OutputRectangle.Bottom = OutputRectangle.Top + _currentLayout.Metrics.Height;

                // Resize the output view as necessary (input field can grow)
                if (OutputRectangle.Bottom > _outputView.Bounds.Height) {
                    _outputView.OutputRectangle.Bottom = _outputView.Bounds.Height - _currentLayout.Metrics.Height;
                    OutputRectangle.Top = _outputView.OutputRectangle.Bottom;
                    OutputRectangle.Bottom = OutputRectangle.Top + _currentLayout.Metrics.Height;
                }
                _hasTextChanged = false;
            }