diff --git a/CSharpMath.slnx b/CSharpMath.slnx index fa6326953..c6c1387d6 100644 --- a/CSharpMath.slnx +++ b/CSharpMath.slnx @@ -28,16 +28,22 @@ + + + + + + - + @@ -52,49 +58,43 @@ - - - - - - - + + + + - + - + - + - + - - - - + \ No newline at end of file diff --git a/NuGet.Config b/NuGet.Config deleted file mode 100644 index 3f0e00340..000000000 --- a/NuGet.Config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Projects.png b/Projects.png new file mode 100644 index 000000000..a3a20a080 Binary files /dev/null and b/Projects.png differ diff --git a/ReadMe.md b/ReadMe.md index 0301d2e0b..79b52d29e 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -3,7 +3,7 @@


CSharpMath icon

CSharpMath is a C# port of the wonderful iosMath LaTeX engine.
-The icon is a product of this library. +Icon generated from CSharpMath.SkiaSharp.Example.

[Current release][NuGet]|[![NuGet release shield](https://img.shields.io/nuget/v/CSharpMath.svg)][NuGet] [![GitHub release shield](https://img.shields.io/github/release/verybadcat/CSharpMath.svg)][GitHub] [![GitHub release date shield](https://img.shields.io/github/release-date/verybadcat/CSharpMath.svg)][GitHub] [![GitHub commits since last release shield](https://img.shields.io/github/commits-since/verybadcat/CSharpMath/latest.svg)][GitHub] @@ -11,185 +11,76 @@ CSharpMath is a C# port of the wonderful -[![NuGet downloads shield](https://img.shields.io/nuget/dt/CSharpMath.svg)][NuGet] [![GitHub contributors shield](https://img.shields.io/github/contributors/verybadcat/CSharpMath.svg)](https://github.com/verybadcat/CSharpMath/graphs/contributors) [![GitHub license shield](https://img.shields.io/github/license/verybadcat/CSharpMath.svg)](https://github.com/verybadcat/CSharpMath/blob/master/License) [![GitHub last commit shield](https://img.shields.io/github/last-commit/verybadcat/CSharpMath.svg)](https://github.com/verybadcat/CSharpMath/commits/master) [![GitHub Build workflow shield](https://img.shields.io/github/actions/workflow/status/verybadcat/CSharpMath/Build.yml?branch=main) [![GitHub Test workflow shield](https://img.shields.io/github/actions/workflow/status/verybadcat/CSharpMath/Test.yml?branch=main) [![codecov.io badge](https://codecov.io/github/verybadcat/CSharpMath/coverage.svg?branch=master)](https://codecov.io/github/verybadcat/CSharpMath?branch=master) +[![NuGet downloads shield](https://img.shields.io/nuget/dt/CSharpMath.svg)][NuGet] [![GitHub contributors shield](https://img.shields.io/github/contributors/verybadcat/CSharpMath.svg)](https://github.com/verybadcat/CSharpMath/graphs/contributors) [![GitHub license shield](https://img.shields.io/github/license/verybadcat/CSharpMath.svg)](License) [![GitHub last commit shield](https://img.shields.io/github/last-commit/verybadcat/CSharpMath.svg)](https://github.com/verybadcat/CSharpMath/commits/master) [![GitHub Test workflow shield](https://img.shields.io/github/actions/workflow/status/verybadcat/CSharpMath/Test.yml?branch=master)](https://github.com/verybadcat/CSharpMath/actions/workflows/Test.yml) [![codecov.io badge](https://codecov.io/github/verybadcat/CSharpMath/coverage.svg?branch=master)](https://codecov.io/github/verybadcat/CSharpMath?branch=master) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/verybadcat/CSharpMath.svg)](http://isitmaintained.com/project/verybadcat/CSharpMath "Average time to resolve an issue") [![Percentage of issues still open](http://isitmaintained.com/badge/open/verybadcat/CSharpMath.svg)](http://isitmaintained.com/project/verybadcat/CSharpMath "Percentage of issues still open") [![Issues welcome](https://img.shields.io/badge/issues-welcome-success)](https://github.com/verybadcat/CSharpMath/issues) [![Pull Requests welcome](https://img.shields.io/badge/pull_requests-welcome-success)](https://github.com/verybadcat/CSharpMath/issues) [![❤](https://img.shields.io/badge/made%20with-%e2%9d%a4-ff69b4.svg)](https://www.youtube.com/watch?v=dQw4w9WgXcQ "") [NuGet]: https://www.nuget.org/packages/CSharpMath/ [NuGet-pre]: https://www.nuget.org/packages/CSharpMath/absoluteLatest [GitHub]: https://github.com/verybadcat/CSharpMath/releases/latest -[GitHub-pre]: https://github.com/verybadcat/CSharpMath/releases +[GitHub-pre]: https://github.com/verybadcat/CSharpMath/releas/latest +[the WebAssembly version of CSharpMath.Uno.Example]: https://verybadcat.github.io/CSharpMath - - -# Platform support - -Xamarin.Forms (CSharpMath.Forms) support via SkiaSharp (CSharpMath.SkiaSharp) was added in v0.1. - -Avalonia (CSharpMath.Avalonia) support was also added in v0.4. - -For Windows platforms, use https://github.com/ForNeVeR/wpf-math. - -For Unity3D, use https://assetstore.unity.com/packages/tools/gui/texdraw-51426. (paid: USD$50) - -_The above projects are independent of CSharpMath._ - -# Usage and Examples - -To get started, do something like this: - -### 1. CSharpMath.SkiaSharp -```cs -var painter = CSharpMath.SkiaSharp.MathPainter(); -painter.LaTeX = @"\frac\sqrt23"; -paiinter.Draw(someCanvas); -``` -This is used by CSharpMath.Forms below. - -### 2. CSharpMath.Forms - -```xaml - - - \frac\sqrt23 - - -``` -or: -```cs -var view = new CSharpMath.Forms.MathView(); -view.HorizontalOptions = view.VerticalOptions = LayoutOptions.FillAndExpand; -view.LaTeX = @"\frac\sqrt23"; -someLayout.Children.Add(view); -``` +### MathButton -[See an example project](CSharpMath.Forms.Example) - -Android | Windows UWP ---------|------------ -![1+1](https://user-images.githubusercontent.com/19922066/40575043-183a6970-6110-11e8-887f-820e14efc588.jpeg) | ![Panning a view](https://user-images.githubusercontent.com/19922066/40731183-18a09b68-6463-11e8-8095-1a4cc9df9eae.gif) ![Colors!](https://user-images.githubusercontent.com/19922066/40972206-8abc247c-68f2-11e8-8684-561b5e833c21.png) +For MAUI, you can make use of `CSharpMath.Maui.MathButton` to make a clickable math button. It wraps a `MathView` inside and will use its properties to draw math on the button. Refer to [this example](CSharpMath.Maui.Example/MathKeyboard.xaml). For Avalonia and Uno, their buttons already support wrapping arbitrary content, refer to [this example](CSharpMath.Avalonia.Example/Pages/MathButtonPage.xaml). -### 3. CSharpMath.Avalonia +## Text -```xaml - - - -``` -or: -```cs -var view = new CSharpMath.Avalonia.MathView(); -view.LaTeX = @"\frac\sqrt23"; -somePanel.Children.Add(view); -``` +Check out the "Text" page of [the WebAssembly version of CSharpMath.Uno.Example]! -[See an example project](CSharpMath.Avalonia.Example) +Example code: +- [Avalonia Example](CSharpMath.Avalonia.Example/Pages/TextViewPage.xaml) +- [MAUI Example](CSharpMath.Maui.Example/TextPage.xaml) +- [Uno Example](CSharpMath.Uno.Example/Pages/TextPage.xaml) +- [VectSharp Example](CSharpMath.VectSharp.Example/Program.cs) (same API for SkiaSharp) -![MathViewPage](https://user-images.githubusercontent.com/19922066/78373612-692db400-75fd-11ea-89c3-2f2a4f47784a.png) +You can use `$`, `\(` and `\)` to delimit inline math and `$$`, `\[` and `\]` to delimit display math. +There is also a `TextButton` for the MAUI equivalent of `MathButton`. -## But I want a button instead! +## Saving to an image file -For Xamarin.Forms, you can make use of `CSharpMath.Forms.MathButton` to make a clickable math button. It wraps a `MathView` inside and will use its properties to draw math on the button. -```xaml - - - - \frac\sqrt23 - - - -``` -For Avalonia, `Avalonia.Controls.Button` already supports arbitrary content. Use it instead. -```xaml - - - -``` - -## But I want to display a majority of normal text with a minority of math! -CSharpMath also provides a `TextView` exactly for this purpose. You can use `$`, `\(` and `\)` to delimit inline math and `$$`, `\[` and `\]` to delimit display math. -There is also a `TextButton` for the Xamarin.Forms equivalent of `MathButton`. -Xamarin.Forms: -```xaml - - - -``` -Avalonia: -```xaml - - - -``` -Xamarin.Forms|Avalonia --|- -![Xamarin.Forms](https://user-images.githubusercontent.com/19922066/80187259-e7e8a080-8641-11ea-8c15-63e36b85047e.png)|![Avalonia](https://user-images.githubusercontent.com/19922066/80187422-31d18680-8642-11ea-81b3-aea7e027a7ea.png) - -## What about rendering to an image instead of displaying in a view? -Warning: There are still some rough edges on image rendering to be resolved, such as [this](CSharpMath.Rendering.Tests/MathDisplay/AccentOverF.png) and [this](CSharpMath.Rendering.Tests/TextLeft/WideDisplayMaths.png). However, it is already usable for the majority of cases. +The image may be cut off, such as [this](CSharpMath.Rendering.Tests/MathDisplay/AccentOverF.png) and [this](CSharpMath.Rendering.Tests/TextLeft/WideDisplayMaths.png). However, it is directly usable for the majority of cases. For SkiaSharp: ```cs using CSharpMath.SkiaSharp; var painter = new MathPainter { LaTeX = @"\frac23" }; // or TextPainter -using var png = painter.DrawAsStream(); +using var png = painter.DrawAsStream(); // defaults to PNG // or painter.DrawAsStream(format: SkiaSharp.SKEncodedImageFormat.Jpeg) for JPEG // or painter.DrawAsStream(format: SkiaSharp.SKEncodedImageFormat.Gif) for GIF // or painter.DrawAsStream(format: SkiaSharp.SKEncodedImageFormat.Bmp) for BMP // or... you get it. ``` -For Xamarin.Forms: +For MAUI: ```cs -using CSharpMath.SkiaSharp; -var painter = someMathView.Painter; // or someTextView.Painter -using var png = painter.DrawAsStream(); -// or painter.DrawAsStream(format: SkiaSharp.SKEncodedImageFormat.Jpeg) for JPEG -// or painter.DrawAsStream(format: SkiaSharp.SKEncodedImageFormat.Gif) for GIF -// or painter.DrawAsStream(format: SkiaSharp.SKEncodedImageFormat.Bmp) for BMP -// or... you get it. +using CSharpMath.Maui; +var painter = someMathView.Painter; // or someTextView.Painter or new MathPainter { LaTeX = @"some LaTeX" } +using var stream = new System.IO.MemoryStream(); +await painter.DrawToStreamAsync(stream); // defaults to PNG ``` For Avalonia: ```cs @@ -204,11 +95,11 @@ painter.DrawAsPng(someStream); ![Cell 4](CSharpMath.Rendering.Tests/MathDisplay/RaiseBox.png)|![Cell 5](CSharpMath.Rendering.Tests/MathDisplay/SomeLimit.png)|![Cell 6](CSharpMath.Rendering.Tests/MathDisplay/VectorProjection.png) ![Cell 7](CSharpMath.Rendering.Tests/MathDisplay/Matrix3.png)|![Cell 8](CSharpMath.Rendering.Tests/MathDisplay/IntegralColorBoxCorrect.png)|![Cell 9](CSharpMath.Rendering.Tests/MathDisplay/Taylor.png) +## Math editing and evaluation +Check out the "Calculate" button on the "Try" page of [the WebAssembly version of CSharpMath.Uno.Example]! Supported evaluation operations can be found [here](CSharpMath.Evaluation/Evaluation.cs). -## This looks great and all, but is there a way to edit and evaluate the math? -Yes! You can use a `CSharpMath.Rendering.FrontEnd.MathKeyboard` to process key presses and generate a `CSharpMath.Atom.MathList` or a LaTeX string. You can then call `CSharpMath.Evaluation.Evaluate` to get a `CSharpMath.Evaluation.MathItem`, which can be a `CSharpMath.Evaluation.MathItem.Entity` containing an `AngouriMath.Entity` that you can simplify, a `CSharpMath.Evaluation.Comma` containing a comma-delimited collection of `CSharpMath.Evaluation.MathItem`, or a `CSharpMath.Evaluation.MathItem.SetNode` containing an `AngouriMath.Core.SetNode`. For all uses of an `AngouriMath.Entity` or an `AngouriMath.Core.SetNode`, check out https://github.com/asc-community/AngouriMath. +You can use a `CSharpMath.Rendering.FrontEnd.MathKeyboard` to process key presses and generate a `CSharpMath.Atom.MathList` or a LaTeX string. You can then call `CSharpMath.Evaluation.Evaluate` to get a `CSharpMath.Evaluation.MathItem`, which can be a `CSharpMath.Evaluation.MathItem.Entity` containing an `AngouriMath.Entity` that you can simplify, a `CSharpMath.Evaluation.Comma` containing a comma-delimited collection of `CSharpMath.Evaluation.MathItem`. For all uses of an `AngouriMath.Entity`, check out https://github.com/asc-community/AngouriMath. -NOTE: `CSharpMath.Evaluation` is not released yet. It will be part of the 0.5.0 update. ```cs var keyboard = new CSharpMath.Rendering.FrontEnd.MathKeyboard(); keyboard.KeyPress(CSharpMath.Editor.MathKeyboardInput.Sine, CSharpMath.Editor.MathKeyboardInput.SmallTheta); @@ -224,12 +115,9 @@ else case CSharpMath.Evaluation.MathItem.Comma comma: // comma is a System.Collections.Generic.IEnumerable break; - case CSharpMath.Evaluation.MathItem.Set { Content: var set }: - // set is an AngouriMath.Core.Set - break; } ``` -or more conveniently: +The evaluator used in Example projects is also exposed: ```cs var keyboard = new CSharpMath.Rendering.FrontEnd.MathKeyboard(); keyboard.KeyPress(CSharpMath.Editor.MathKeyboardInput.Sine, CSharpMath.Editor.MathKeyboardInput.SmallTheta); @@ -242,8 +130,6 @@ Analyzing an expression | Solving an equation -|- ![Analyzing an expression](https://user-images.githubusercontent.com/19922066/82801930-a8b3a680-9eb0-11ea-9947-8da278d24e9f.jpeg)|![Solving an equation](https://user-images.githubusercontent.com/19922066/82801937-abae9700-9eb0-11ea-8c3e-82fa27463ff4.jpeg) -# [Documentation](https://github.com/verybadcat/CSharpMath/wiki/Documentation-of-public-facing-APIs-of-CSharpMath.Rendering,-CSharpMath.SkiaSharp-and-CSharpMath.Forms-MathViews) - # Opting in to the nightly feed For those who wish to be even more updated than prereleases, you can opt in to the nightly feed which is updated whenever the master branch has a new commit. @@ -285,6 +171,12 @@ Unfortunately, non-NuGet.org feeds do not support `.snupkg`s, so you will have t # Project structure +![Project structure](Projects.png) + +🟥 Main functionality +🟨 Tests, Examples, Benchmarks + +## Major processes of drawing LaTeX -![Project structure](https://quickchart.io/chart?cht=gv&chl=graph{node[shape=box];{rank=same;"Typography.OpenFont";"Typography.TextBreak";CSharpMath};"Typography.OpenFont"[shape=record,label="{_Dependencies|Typography.OpenFont}"];"Typography.TextBreak"[shape=record,label="{_Dependencies|Typography.TextBreak}"];CSharpMath[shape=record,label="{_Core|CSharpMath}"];"CSharpMath.Avalonia"[shape=record,label="{Avalonia|CSharpMath.Avalonia}"];"CSharpMath.SkiaSharp"[shape=record,label="{SkiaSharp|CSharpMath.SkiaSharp}"];"CSharpMath.Forms"[shape=record,label="{Xamarin.Forms|CSharpMath.Forms}"];"Typography.OpenFont"--"Typography.GlyphLayout";"Typography.TextBreak"--"TextBreakTests";CSharpMath--"CSharpMath.CoreTests";CSharpMath--"CSharpMath.Editor"--"CSharpMath.Editor.Tests"--"CSharpMath.Editor.Tests.Visualizer";"CSharpMath.Editor"--"CSharpMath.Editor.Tests.FSharp";CSharpMath--"CSharpMath.Evaluation"--{"CSharpMath.Evaluation.Tests";"CSharpMath.Forms.Example"};{"CSharpMath.Editor";"Typography.GlyphLayout";"Typography.TextBreak"}--"CSharpMath.Rendering"--"CSharpMath.Rendering.Text.Tests";"CSharpMath.Rendering"--"CSharpMath.Avalonia"--"CSharpMath.Avalonia.Example";"CSharpMath.Rendering"--"CSharpMath.SkiaSharp"--"CSharpMath.Forms"--"CSharpMath.Forms.Example";"CSharpMath.Forms.Example"--{"CSharpMath.Forms.Example.Android";"CSharpMath.Forms.Example.UWP"};{"CSharpMath.Avalonia";"CSharpMath.SkiaSharp"}--"CSharpMath.Rendering.Tests";"CSharpMath.Xaml"--{"CSharpMath.Avalonia";"CSharpMath.Forms"}--"CSharpMath.Xaml.Tests"}) - -## Major processes of drawing LaTeX ![Major processes of drawing LaTeX](https://quickchart.io/chart?cht=gv&chl=digraph{edge[label="%20"];{rank=same;"string%20(LaTeX%20math)";"string%20(LaTeX%20text)"};"string%20(LaTeX%20math)"->"CSharpMath.Atom.MathList"[taillabel="CSharpMath.Atom.LaTeXParser.MathListFromLaTeX%20"];"CSharpMath.Atom.MathList"->"string%20(LaTeX%20math)"[label="CSharpMath.Atom.LaTeXParser.MathListToLaTeX"];"CSharpMath.Atom.MathList"->"CSharpMath.Evaluation.MathItem"[label="CSharpMath.Evaluation.Evaluate"];"CSharpMath.Evaluation.MathItem"->"CSharpMath.Atom.MathList"[taillabel="CSharpMath.Evaluation.Visualize%20%20"];"CSharpMath.Atom.MathList"->"CSharpMath.Display.IDisplay%3CTFont,%20TGlyph>"[label="CSharpMath.Display.Typesetter.CreateLine"];"string%20(LaTeX%20text)"->"CSharpMath.Rendering.Text.TextAtom"[label="CSharpMath.Rendering.Text.TextLaTeXParser.TextAtomFromLaTeX"];"CSharpMath.Rendering.Text.TextAtom"->"string%20(LaTeX%20text)"[taillabel="CSharpMath.Rendering.Text.TextLaTeXParser.TextAtomToLaTeX%20"];"CSharpMath.Rendering.Text.TextAtom"->"CSharpMath.Display.IDisplay%3CTFont,%20TGlyph>"[label="CSharpMath.Rendering.Text.TextTypesetter.Layout"];"CSharpMath.Display.IDisplay%3CTFont,%20TGlyph>"->"(Rendered%20output)"[label="CSharpMath.Display.IDisplay%3CTFont,%20TGlyph>.Draw"];"(Platform%20canvas)"->"CSharpMath.Rendering.FrontEnd.ICanvas"[label="%20CSharpMath.Rendering.FrontEnd.Painter%3CTCanvas,%20TContent,%20TColor>.WrapCanvas"];"CSharpMath.Rendering.FrontEnd.ICanvas"->"CSharpMath.Rendering.BackEnd.GraphicsContext"[label="%20new%20CSharpMath.Rendering.BackEnd.GraphicsContext"];"CSharpMath.Rendering.BackEnd.GraphicsContext"->"(Rendered%20output)"}) @@ -313,7 +202,11 @@ As CSharpMath.Rendering provides font lookup through [the Typography library](ht You would have to implement [ICanvas](CSharpMath.Rendering/FrontEnd/ICanvas.cs) and feed it into the Draw method of [MathPainter](CSharpMath.Rendering/FrontEnd/MathPainter.cs). -### 2. Forking from CSharpMath the project +### 2. Building on top of CSharpMath.SkiaSharp + +You can extend this library to other SkiaSharp-supported platforms by feeding the SKCanvas given in the OnPaintSurface override of a SkiaSharp view into the Draw method of [MathPainter](CSharpMath.SkiaSharp/MathPainter.cs). + +### 3. Forking from CSharpMath the project This path would require the most effort to implement, but allows you to plug in any font library and graphics library. @@ -321,9 +214,6 @@ You would have to define your own [TypesettingContext](CSharpMath/Display/FrontE The TypesettingContext in turn has several components, including choosing a font. -### 3. Building on top of CSharpMath.SkiaSharp - -You can extend this library to other SkiaSharp-supported platforms by feeding the SKCanvas given in the OnPaintSurface override of a SkiaSharp view into the Draw method of [MathPainter](CSharpMath.SkiaSharp/MathPainter.cs). # Project needs