Browse Source

Added ArcTo implementation based on Bezier curves

pull/302/head
Thehx 10 years ago
parent
commit
2bb67f3553
  1. 34
      src/Gtk/Perspex.Cairo/Media/StreamGeometryContextImpl.cs
  2. 7
      src/Perspex.SceneGraph/Platform/IStreamGeometryContextImpl.cs
  3. 24
      src/Perspex.SceneGraph/Point.cs
  4. 19
      src/Perspex.SceneGraph/Vector.cs
  5. 1118
      src/Shared/RenderHelpers/ArcToHelper.cs
  6. 13
      src/Shared/RenderHelpers/QuadBezierHelper.cs
  7. 2
      src/Shared/RenderHelpers/RenderHelpers.projitems
  8. 9
      src/Windows/Perspex.Direct2D1/Media/StreamGeometryContextImpl.cs

34
src/Gtk/Perspex.Cairo/Media/StreamGeometryContextImpl.cs

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using Perspex.Media;
using Perspex.Platform;
using Perspex.RenderHelpers;
namespace Perspex.Cairo.Media
{
@ -12,6 +13,7 @@ namespace Perspex.Cairo.Media
public class StreamGeometryContextImpl : IStreamGeometryContextImpl
{
private Point _currentPoint;
public StreamGeometryContextImpl(Cairo.Path path = null)
{
@ -27,24 +29,44 @@ namespace Perspex.Cairo.Media
public void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection)
{
ArcToHelper.ArcTo(this, _currentPoint, point, size, rotationAngle, isLargeArc, sweepDirection);
_currentPoint = point;
}
public void BeginFigure(Point startPoint, bool isFilled)
{
if (this.Path == null)
_context.MoveTo(startPoint.ToCairo());
if (this.Path == null)
{
_context.MoveTo(startPoint.ToCairo());
_currentPoint = startPoint;
}
}
public void BezierTo(Point point1, Point point2, Point point3)
{
if (this.Path == null)
_context.CurveTo(point1.ToCairo(), point2.ToCairo(), point3.ToCairo());
if (this.Path == null)
{
_context.CurveTo(point1.ToCairo(), point2.ToCairo(), point3.ToCairo());
_currentPoint = point3;
}
}
public void QuadTo(Point control, Point endPoint)
{
if (this.Path == null)
{
QuadBezierHelper.QuadTo(this, _currentPoint, control, endPoint);
_currentPoint = endPoint;
}
}
public void LineTo(Point point)
{
if (this.Path == null)
_context.LineTo(point.ToCairo());
if (this.Path == null)
{
_context.LineTo(point.ToCairo());
_currentPoint = point;
}
}
private readonly Cairo.Context _context;

7
src/Perspex.SceneGraph/Platform/IStreamGeometryContextImpl.cs

@ -38,6 +38,13 @@ namespace Perspex.Platform
/// <param name="point3">The destination point for the end of the curve.</param>
void BezierTo(Point point1, Point point2, Point point3);
/// <summary>
/// Draws a quadratic Bezier curve to the specified point
/// </summary>
/// <param name="control">Control point</param>
/// <param name="endPoint">DestinationPoint</param>
void QuadTo(Point control, Point endPoint);
/// <summary>
/// Draws a line to the specified point.
/// </summary>

24
src/Perspex.SceneGraph/Point.cs

@ -128,6 +128,30 @@ namespace Perspex
return new Point(a._x - b.X, a._y - b.Y);
}
/// <summary>
/// Multiplies a point by a factor coordinate-wise
/// </summary>
/// <param name="p">Point to multiply</param>
/// <param name="k">Factor</param>
/// <returns>Points having its coordinates multiplied</returns>
public static Point operator *(Point p, double k) => new Point(p.X*k, p.Y*k);
/// <summary>
/// Multiplies a point by a factor coordinate-wise
/// </summary>
/// <param name="p">Point to multiply</param>
/// <param name="k">Factor</param>
/// <returns>Points having its coordinates multiplied</returns>
public static Point operator *(double k, Point p) => new Point(p.X*k, p.Y*k);
/// <summary>
/// Divides a point by a factor coordinate-wise
/// </summary>
/// <param name="p">Point to divide by</param>
/// <param name="k">Factor</param>
/// <returns>Points having its coordinates divided</returns>
public static Point operator /(Point p, double k) => new Point(p.X/k, p.Y/k);
/// <summary>
/// Applies a matrix to a point.
/// </summary>

19
src/Perspex.SceneGraph/Vector.cs

@ -3,6 +3,7 @@
using System;
using System.Globalization;
using System.Xml.Linq;
namespace Perspex
{
@ -51,6 +52,24 @@ namespace Perspex
return new Point(a._x, a._y);
}
/// <summary>
/// Calculates the dot product of two vectors
/// </summary>
/// <param name="a">First vector</param>
/// <param name="b">Second vector</param>
/// <returns>The dot product</returns>
public static double operator *(Vector a, Vector b)
{
return a.X*b.X + a.Y*b.Y;
}
/// <summary>
/// Length of the vector
/// </summary>
public double Length => Math.Sqrt(X*X + Y*Y);
/// <summary>
/// Negates a vector.
/// </summary>

1118
src/Shared/RenderHelpers/ArcToHelper.cs

File diff suppressed because it is too large

13
src/Shared/RenderHelpers/QuadBezierHelper.cs

@ -0,0 +1,13 @@
using Perspex.Platform;
namespace Perspex.RenderHelpers
{
static class QuadBezierHelper
{
public static void QuadTo(IStreamGeometryContextImpl context, Point current, Point controlPoint, Point endPoint)
{
//(s, (s + 2c)/ 3, (e + 2c)/ 3, e)
context.BezierTo((current + 2*controlPoint)/3, (endPoint + 2*controlPoint)/3, endPoint);
}
}
}

2
src/Shared/RenderHelpers/RenderHelpers.projitems

@ -9,6 +9,8 @@
<Import_RootNamespace>Perspex.RenderHelpers</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)ArcToHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)QuadBezierHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TileBrushImplHelper.cs" />
</ItemGroup>
</Project>

9
src/Windows/Perspex.Direct2D1/Media/StreamGeometryContextImpl.cs

@ -47,6 +47,15 @@ namespace Perspex.Direct2D1.Media
});
}
public void QuadTo(Point control, Point dest)
{
_sink.AddQuadraticBezier(new QuadraticBezierSegment
{
Point1 = control.ToSharpDX(),
Point2 = dest.ToSharpDX()
});
}
public void LineTo(Point point)
{
_sink.AddLine(point.ToSharpDX());

Loading…
Cancel
Save