Cross-platform LaTeX rendering!
CSharpMath is a C# port of the wonderful iosMath LaTeX engine.
The icon is a product of this library.
Current release | |
---|---|
Current prerelease |
Platform support
iOS (CSharpMath.Ios) was ironically the first front end, which was added in v0.0.
Xamarin.Forms (CSharpMath.Forms) support via SkiaSharp (CSharpMath.SkiaSharp) was added in v0.1 as development continued.
Avalonia (CSharpMath.Avalonia) support was also added in v0.4.
For Windows platforms, use https://github.com/ForNeVeR/wpf-math.
Usage and Examples
To get started, do something like this:
1. CSharpMath.Ios
var latexView = IosMathLabels.MathView(@"x = -b \pm \frac{\sqrt{b^2-4ac}}{2a}", 15);
latexView.ContentInsets = new UIEdgeInsets(10, 10, 10, 10);
var size = latexView.SizeThatFits(new CoreGraphics.CGSize(370, 180));
latexView.Frame = new CoreGraphics.CGRect(0, 20, size.Width, size.Height);
someSuperview.Add(latexView);
![]() |
![]() |
---|---|
![]() |
![]() |
2. CSharpMath.SkiaSharp
var painter = CSharpMath.SkiaSharp.MathPainter();
painter.LaTeX = @"\frac\sqrt23";
paiinter.Draw(someCanvas);
This is used by CSharpMath.Forms below.
3. CSharpMath.Forms
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:math="clr-namespace:CSharpMath.Forms;assembly=CSharpMath.Forms"
x:Class="Namespace.Class">
<math:MathView x:Name="View" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
\frac\sqrt23
</math:MathView>
</ContentPage>
or:
var view = new CSharpMath.Forms.MathView();
view.HorizontalOptions = view.VerticalOptions = LayoutOptions.FillAndExpand;
view.LaTeX = @"\frac\sqrt23";
someLayout.Children.Add(view);
iOS | Android | Windows UWP |
---|---|---|
![]() |
![]() |
![]() ![]() |
4. CSharpMath.Avalonia
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:math="clr-namespace:CSharpMath.Avalonia;assembly=CSharpMath.Avalonia"
x:Class="Namespace.Class">
<math:MathView LaTeX="x + 2 \sqrt{x} + 1 = (\sqrt x+1)^2" />
</UserControl>
or:
var view = new CSharpMath.Avalonia.MathView();
view.LaTeX = @"\frac\sqrt23";
somePanel.Children.Add(view);
But I want a button instead!
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.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:math="clr-namespace:CSharpMath.Forms;assembly=CSharpMath.Forms"
x:Class="Namespace.Class">
<math:MathButton x:Name="MathButton">
<math:MathView x:Name="MathView">
\frac\sqrt23
</math:MathView>
</math:MathButton>
</ContentPage>
For Avalonia, Avalonia.Controls.Button
already supports arbitrary content. Use it instead.
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:math="clr-namespace:CSharpMath.Avalonia;assembly=CSharpMath.Avalonia"
x:Class="Namespace.Class">
<Button x:Name="MathButton">
<math:MathView x:Name="MathView">
\frac\sqrt23
</math:MathView>
</Button>
</UserControl>
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:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:math="clr-namespace:CSharpMath.Forms;assembly=CSharpMath.Forms"
x:Class="Namespace.Class">
<math:TextView LaTeX="Text text text text text \( \frac{\sqrt a}{b} \) text text text text text" />
</ContentPage>
Avalonia:
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:math="clr-namespace:CSharpMath.Avalonia;assembly=CSharpMath.Avalonia"
x:Class="Namespace.Class">
<math:TextView LaTeX="Text text text text text \( \frac{\sqrt a}{b} \) text text text text text" />
</UserControl>
Xamarin.Forms | Avalonia |
---|---|
![]() |
![]() |
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 and this. However, it is already usable for the majority of cases.
For SkiaSharp:
using CSharpMath.SkiaSharp;
var painter = new MathPainter { LaTeX = @"\frac23" }; // or TextPainter
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.
For Xamarin.Forms:
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.
For Avalonia:
using CSharpMath.Avalonia;
var painter = someMathView.Painter; // or someTextView.Painter
// Due to limitations of the Avalonia API, you can only render as PNG to a target stream
painter.DrawAsPng(someStream);
![]() |
![]() |
![]() |
---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
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.MathListToEntity
to get an AngouriMath.Entity
that you can simplify. 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.
var keyboard = new CSharpMath.Rendering.FrontEnd.MathKeyboard();
keyboard.KeyPress(CSharpMath.Editor.MathKeyboardInput.Sine, CSharpMath.Editor.MathKeyboardInput.SmallTheta);
CSharpMath.Evaluation.MathListToEntity(keyboard.MathList)
.Match(entity => {
var resultLaTeX = CSharpMath.Evaluation.MathListFromEntity(entity.Simplify());
}, error => { /* Handle invalid math */ });
or more conveniently:
var keyboard = new CSharpMath.Rendering.FrontEnd.MathKeyboard();
keyboard.KeyPress(CSharpMath.Editor.MathKeyboardInput.Sine, CSharpMath.Editor.MathKeyboardInput.SmallTheta);
// Displays errors as red text, also automatically chooses between
// simplifying an expression and solving an equation depending on the presence of an equals sign
var resultLaTeX = CSharpMath.Evaluation.Interpret(keyboard.MathList);
Simplifying an expression | Solving an equation |
---|---|
![]() |
![]() |
Documentation
Project structure
<_Core>
CSharpMath
├── CSharpMath.CoreTests
│ <iOS>
├── CSharpMath.Apple
│ └── CSharpMath.Ios
│ └── CSharpMath.Ios.Example
└── CSharpMath.Editor
├── CSharpMath.Editor.Tests
│ └── CSharpMath.Editor.Tests.Visualizer
├── CSharpMath.Editor.Tests.FSharp
├── CSharpMath.Evaluation ───────────────────────┐
│ └── CSharpMath.Evaluation.Tests │
└── CSharpMath.Rendering │
├── CSharpMath.Rendering.Text.Tests │
│ <Avalonia> │
├── CSharpMath.Avalonia ─────────────────────────┬───┐
│ └── CSharpMath.Avalonia.Example │ │ │
│ <SkiaSharp> │ │ │
└── CSharpMath.SkiaSharp ────────────────────────┤ │
│ <Xamarin.Forms> │ │ │
└── CSharpMath.Forms ─────────────────────── │ ──┤
└── CSharpMath.Forms.Example ────────┘ │ │
├── CSharpMath.Forms.Example.Android │ │
├── CSharpMath.Forms.Example.iOS │ │
├── CSharpMath.Forms.Example.Ooui │ │
├── CSharpMath.Forms.Example.WPF │ │
└── CSharpMath.Forms.Example.UWP │ │
CSharpMath.Rendering.Tests ──┘ │
CSharpMath.Xaml.Tests ──┘
Extending to more platforms
There are a few ways to extend this to more platforms: (Hopefully, you would not need to touch the core typesetting engine. If you do, we would consider that a bug.)
1. Branching off from CSharpMath.Rendering (recommended)
As CSharpMath.Rendering provides font lookup through the Typography library, you would only need to write adapter classes to connect this library to your chosen graphics library.
You would have to implement ICanvas and feed it into the Draw method of MathPainter.
2. 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.
You would have to define your own TypesettingContext and write an implementation of IGraphicsContext.
The TypesettingContext in turn has several components, including choosing a font.
3. Referencing 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.
4. Building on top of CSharpMath.Apple
You can use this library on other appleOSes by making use of AppleMathView.
Project needs
We need more contributors! Maybe you can contribute something to this repository. Whether they are bug reports, feature proposals or pull requests, you are welcome to send them to us. We are sure that we will take a look at them!
Here is an idea list if you cannot think of anything right now:
- A new example for the Example projects (please open pull requests straight away)
- A new LaTeX command (please link documentation of it)
- A new front end (please describe what it is and why should it be supported)
- A new math syntax (please describe what it is and why should it be supported)
License
CSharpMath is licensed by the MIT license.
Dependency | Used by | License |
---|---|---|
Typography project | CSharpMath.Rendering | MIT |
AngouriMath project | CSharpMath.Evaluation | MIT |
Latin Modern Math font | CSharpMath.Ios, CSharpMath.Rendering | GUST Font License |
Cyrillic Modern font | CSharpMath.Rendering | SIL Open Font License |
AMS Capital Blackboard Bold font (extracted by @Happypig375 from the amsfonts package) | CSharpMath.Rendering | SIL Open Font License |
ComicNeue font | CSharpMath.Rendering.Tests, CSharpMath.Xaml.Tests | SIL Open Font License |
Authors
Thanks for reading.