From 86dee29c62f729ee4f0592b219919413aee5fed8 Mon Sep 17 00:00:00 2001 From: Giorgio Bianchini Date: Thu, 1 Sep 2022 18:14:39 +0100 Subject: [PATCH] Added new frontend CSharpMath.VectSharp. --- CSharpMath.CrossPlatform.slnf | 1 + .../CSharpMath.VectSharp.csproj | 14 ++++ CSharpMath.VectSharp/Extensions.cs | 35 ++++++++++ CSharpMath.VectSharp/MathPainter.cs | 65 +++++++++++++++++++ CSharpMath.VectSharp/TextPainter.cs | 15 +++++ CSharpMath.VectSharp/VectSharpCanvas.cs | 53 +++++++++++++++ CSharpMath.VectSharp/VectSharpPath.cs | 39 +++++++++++ CSharpMath.sln | 50 ++++++++++++++ 8 files changed, 272 insertions(+) create mode 100644 CSharpMath.VectSharp/CSharpMath.VectSharp.csproj create mode 100644 CSharpMath.VectSharp/Extensions.cs create mode 100644 CSharpMath.VectSharp/MathPainter.cs create mode 100644 CSharpMath.VectSharp/TextPainter.cs create mode 100644 CSharpMath.VectSharp/VectSharpCanvas.cs create mode 100644 CSharpMath.VectSharp/VectSharpPath.cs diff --git a/CSharpMath.CrossPlatform.slnf b/CSharpMath.CrossPlatform.slnf index bd27cd96..e596b012 100644 --- a/CSharpMath.CrossPlatform.slnf +++ b/CSharpMath.CrossPlatform.slnf @@ -27,6 +27,7 @@ "CSharpMath.Avalonia/CSharpMath.Avalonia.csproj", "CSharpMath.Avalonia.Example/CSharpMath.Avalonia.Example.csproj", "CSharpMath.SkiaSharp/CSharpMath.SkiaSharp.csproj", + "CSharpMath.VectSharp/CSharpMath.VectSharp.csproj", "CSharpMath.Forms/CSharpMath.Forms.csproj", "CSharpMath.Forms.Example/CSharpMath.Forms.Example/CSharpMath.Forms.Example.csproj", "CSharpMath.Forms.Tests/CSharpMath.Forms.Tests.csproj" diff --git a/CSharpMath.VectSharp/CSharpMath.VectSharp.csproj b/CSharpMath.VectSharp/CSharpMath.VectSharp.csproj new file mode 100644 index 00000000..c9ed0e5a --- /dev/null +++ b/CSharpMath.VectSharp/CSharpMath.VectSharp.csproj @@ -0,0 +1,14 @@ + + + + netstandard2.0 + The VectSharp front end for CSharpMath. + $(PackageTags) vectsharp + + + + + + + + \ No newline at end of file diff --git a/CSharpMath.VectSharp/Extensions.cs b/CSharpMath.VectSharp/Extensions.cs new file mode 100644 index 00000000..43d79011 --- /dev/null +++ b/CSharpMath.VectSharp/Extensions.cs @@ -0,0 +1,35 @@ +// Adapted after https://github.com/verybadcat/CSharpMath/blob/master/CSharpMath.SkiaSharp/Extensions.cs + +using System; +using CSharpMath.Rendering.FrontEnd; + +namespace CSharpMath.VectSharp +{ + public static class Extensions + { + internal static global::VectSharp.Colour ToNative(this System.Drawing.Color color) + { + return global::VectSharp.Colour.FromRgba(color.R, color.G, color.B, color.A); + } + + internal static System.Drawing.Color FromNative(this global::VectSharp.Colour colour) + { + return System.Drawing.Color.FromArgb((int)Math.Round(colour.A * 255), (int)Math.Round(colour.R * 255), (int)Math.Round(colour.G * 255), (int)Math.Round(colour.B * 255)); + } + + public static global::VectSharp.Page DrawToPage(this Painter painter, float textPainterCanvasWidth = TextPainter.DefaultCanvasWidth, TextAlignment alignment = TextAlignment.TopLeft) where TContent : class + { + var size = painter.Measure(textPainterCanvasWidth).Size; + + global::VectSharp.Page pag = new global::VectSharp.Page(size.Width, size.Height); + + pag.Graphics.Save(); + + painter.Draw(pag, alignment); + + pag.Graphics.Restore(); + + return pag; + } + } +} diff --git a/CSharpMath.VectSharp/MathPainter.cs b/CSharpMath.VectSharp/MathPainter.cs new file mode 100644 index 00000000..174da363 --- /dev/null +++ b/CSharpMath.VectSharp/MathPainter.cs @@ -0,0 +1,65 @@ +// Adapted after https://github.com/verybadcat/CSharpMath/blob/master/CSharpMath.SkiaSharp/MathPainter.cs + +using System.Drawing; +using CSharpMath.Rendering.FrontEnd; +using CSharpMath.Rendering.BackEnd; +using CSharpMath.Structures; +using VectSharp; + +namespace CSharpMath.VectSharp +{ + public class MathPainter : MathPainter + { + public bool AntiAlias { get; set; } = true; + public void Draw(Page canvas, global::VectSharp.Point point) => Draw(canvas, (float)point.X, (float)point.Y); + public override Colour UnwrapColor(Color color) => color.ToNative(); + public override Color WrapColor(Colour color) => color.FromNative(); + public override ICanvas WrapCanvas(Page canvas) => + new VectSharpCanvas(canvas, AntiAlias); + /// + /// Ignores the MathList and LaTeX of the provided. + /// Repositions the . + /// + public static void DrawDisplay(MathPainter settings, Display.IDisplay display, Page canvas, PointF position) + { + DrawDisplay(settings, display, _ => _.Draw(canvas, position)); + } + + /// + /// Ignores the MathList and LaTeX of the provided. + /// Repositions the . + /// + public static void DrawDisplay(MathPainter settings, Display.IDisplay display, + Page canvas, global::VectSharp.Point position) + { + DrawDisplay(settings, display, _ => _.Draw(canvas, position)); + } + + /// + /// Ignores the MathList and LaTeX of the provided. + /// Repositions the . + /// + public static void DrawDisplay(MathPainter settings, Display.IDisplay display, Page canvas, float x, float y) + { + DrawDisplay(settings, display, _ => _.Draw(canvas, x, y)); + } + + /// + /// Ignores the MathList and LaTeX of the provided. + /// Repositions the . + /// + public static void DrawDisplay(MathPainter settings, Display.IDisplay display, Page canvas, TextAlignment textAlignment = TextAlignment.Center, Thickness padding = default, float offsetX = 0, float offsetY = 0) + { + DrawDisplay(settings, display, _ => _.Draw(canvas, textAlignment, padding, offsetX, offsetY)); + } + + private static void DrawDisplay(MathPainter settings, Display.IDisplay display, System.Action draw) + { + if (display is null) return; + var original = (settings.Display, settings._displayChanged); + (settings.Display, settings._displayChanged) = (display, false); + draw(settings); + (settings.Display, settings._displayChanged) = original; + } + } +} diff --git a/CSharpMath.VectSharp/TextPainter.cs b/CSharpMath.VectSharp/TextPainter.cs new file mode 100644 index 00000000..72c8a0b0 --- /dev/null +++ b/CSharpMath.VectSharp/TextPainter.cs @@ -0,0 +1,15 @@ +// Adapted after https://github.com/verybadcat/CSharpMath/blob/master/CSharpMath.SkiaSharp/TextPainter.cs + +using System.Drawing; +using CSharpMath.Rendering.FrontEnd; + +namespace CSharpMath.VectSharp +{ + public class TextPainter : TextPainter + { + public override Color WrapColor(global::VectSharp.Colour color) => color.FromNative(); + public override global::VectSharp.Colour UnwrapColor(Color color) => color.ToNative(); + public override ICanvas WrapCanvas(global::VectSharp.Page canvas) => + new VectSharpCanvas(canvas, true); + } +} diff --git a/CSharpMath.VectSharp/VectSharpCanvas.cs b/CSharpMath.VectSharp/VectSharpCanvas.cs new file mode 100644 index 00000000..ee2842f8 --- /dev/null +++ b/CSharpMath.VectSharp/VectSharpCanvas.cs @@ -0,0 +1,53 @@ +// Adapted after https://github.com/verybadcat/CSharpMath/blob/master/CSharpMath.SkiaSharp/SkiaCanvas.cs + +using System.Drawing; +using CSharpMath.Rendering.FrontEnd; +using VectSharp; + +namespace CSharpMath.VectSharp +{ + public sealed class VectSharpCanvas : ICanvas + { + public VectSharpCanvas(Page canvas, bool antiAlias) + { + Canvas = canvas; + this._isAntialias = antiAlias; + } + public Page Canvas { get; } + public float Width => (float)Canvas.Width; + public float Height => (float)Canvas.Height; + public Color DefaultColor { get; set; } + public Color? CurrentColor { get; set; } + public PaintStyle CurrentStyle { get; set; } + + private readonly bool _isAntialias; + + // Canvas methods + public void StrokeRect(float left, float top, float width, float height) + { + this.Canvas.Graphics.StrokeRectangle(left, top, width, height, (this.CurrentColor ?? this.DefaultColor).ToNative()); + } + + public void FillRect(float left, float top, float width, float height) + { + this.Canvas.Graphics.FillRectangle(left, top, width, height, (this.CurrentColor ?? this.DefaultColor).ToNative()); + } + + public void DrawLine(float x1, float y1, float x2, float y2, float lineThickness) + { + if (CurrentStyle == PaintStyle.Fill) + { + this.Canvas.Graphics.StrokePath(new GraphicsPath().MoveTo(x1, y1).LineTo(x2, y2), (this.CurrentColor ?? this.DefaultColor).ToNative(), lineThickness); + } + else + { + this.StrokeLineOutline(x1, y1, x2, y2, lineThickness); + } + } + public void Save() => this.Canvas.Graphics.Save(); + public void Translate(float dx, float dy) => this.Canvas.Graphics.Translate(dx, dy); + public void Scale(float sx, float sy) => this.Canvas.Graphics.Scale(sx, sy); + public void Restore() => this.Canvas.Graphics.Restore(); + public Path StartNewPath() => new VectSharpPath(this); + } +} diff --git a/CSharpMath.VectSharp/VectSharpPath.cs b/CSharpMath.VectSharp/VectSharpPath.cs new file mode 100644 index 00000000..cc7da300 --- /dev/null +++ b/CSharpMath.VectSharp/VectSharpPath.cs @@ -0,0 +1,39 @@ +// Adapted after https://github.com/verybadcat/CSharpMath/blob/master/CSharpMath.SkiaSharp/SkiaPath.cs + +using System.Drawing; +using VectSharp; + +namespace CSharpMath.VectSharp +{ + public sealed class VectSharpPath : Rendering.FrontEnd.Path + { + public VectSharpPath(VectSharpCanvas owner) => _owner = owner; + public override Color? Foreground { get; set; } + private readonly VectSharpCanvas _owner; + private readonly GraphicsPath _path = new GraphicsPath(); + public override void MoveTo(float x0, float y0) { _path.Close(); _path.MoveTo(x0, y0); } + public override void LineTo(float x1, float y1) => _path.LineTo(x1, y1); + public override void Curve3(float x1, float y1, float x2, float y2) + { + _path.QuadraticBezierTo(x1, y1, x2, y2); + } + + public override void Curve4(float x1, float y1, float x2, float y2, float x3, float y3) + { + _path.CubicBezierTo(x1, y1, x2, y2, x3, y3); + } + + public override void CloseContour() => _path.Close(); + public override void Dispose() + { + if (_owner.CurrentStyle == Rendering.FrontEnd.PaintStyle.Fill) + { + _owner.Canvas.Graphics.FillPath(this._path, (this.Foreground ?? _owner.CurrentColor ?? _owner.DefaultColor).ToNative()); + } + else + { + _owner.Canvas.Graphics.StrokePath(this._path, (this.Foreground ?? _owner.CurrentColor ?? _owner.DefaultColor).ToNative()); + } + } + } +} diff --git a/CSharpMath.sln b/CSharpMath.sln index b240a067..6eff562c 100644 --- a/CSharpMath.sln +++ b/CSharpMath.sln @@ -28,6 +28,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Ios", "CSharpMat EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.SkiaSharp", "CSharpMath.SkiaSharp\CSharpMath.SkiaSharp.csproj", "{35B4BB5B-2202-436E-9AFE-00997CA2CC65}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.VectSharp", "CSharpMath.VectSharp\CSharpMath.VectSharp.csproj", "{58F936BB-645A-4419-B621-2EC38FF41E34}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Playground", "CSharpMath.Playground\CSharpMath.Playground.csproj", "{20986A1A-BF57-4EA7-92E1-E88D3C70874B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Forms", "CSharpMath.Forms\CSharpMath.Forms.csproj", "{9BAD6846-0B1D-4446-BF62-FCF85C6E9A9F}" @@ -387,6 +389,54 @@ Global {35B4BB5B-2202-436E-9AFE-00997CA2CC65}.Release|x64.Build.0 = Release|Any CPU {35B4BB5B-2202-436E-9AFE-00997CA2CC65}.Release|x86.ActiveCfg = Release|Any CPU {35B4BB5B-2202-436E-9AFE-00997CA2CC65}.Release|x86.Build.0 = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Ad-Hoc|ARM.Build.0 = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Ad-Hoc|x64.Build.0 = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Ad-Hoc|x86.Build.0 = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.AppStore|ARM.ActiveCfg = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.AppStore|ARM.Build.0 = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.AppStore|iPhone.Build.0 = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.AppStore|x64.ActiveCfg = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.AppStore|x64.Build.0 = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.AppStore|x86.ActiveCfg = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.AppStore|x86.Build.0 = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Debug|ARM.ActiveCfg = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Debug|ARM.Build.0 = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Debug|iPhone.Build.0 = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Debug|x64.ActiveCfg = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Debug|x64.Build.0 = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Debug|x86.ActiveCfg = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Debug|x86.Build.0 = Debug|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Release|Any CPU.ActiveCfg = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Release|Any CPU.Build.0 = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Release|ARM.ActiveCfg = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Release|ARM.Build.0 = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Release|iPhone.ActiveCfg = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Release|iPhone.Build.0 = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Release|x64.ActiveCfg = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Release|x64.Build.0 = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Release|x86.ActiveCfg = Release|Any CPU + {58F936BB-645A-4419-B621-2EC38FF41E34}.Release|x86.Build.0 = Release|Any CPU {20986A1A-BF57-4EA7-92E1-E88D3C70874B}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU {20986A1A-BF57-4EA7-92E1-E88D3C70874B}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU {20986A1A-BF57-4EA7-92E1-E88D3C70874B}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU