Skip to content

Commit

Permalink
(#63) TexFormula: move to the Shared assembly
Browse files Browse the repository at this point in the history
  • Loading branch information
ForNeVeR committed Jan 8, 2023
1 parent bb4e1fd commit 44d3bac
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 63 deletions.
8 changes: 5 additions & 3 deletions src/WpfMath.Example/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Windows.Media.Imaging;
using Microsoft.Win32;
using WpfMath.Converters;
using WpfMath.Rendering;

namespace WpfMath.Example;

Expand Down Expand Up @@ -68,15 +69,16 @@ private void saveButton_Click(object sender, RoutedEventArgs e)
// Create formula object from input text.
var formula = ParseFormula(InputTextBox.Text);
if (formula == null) return;
var renderer = formula.GetRenderer(TexStyle.Display, Formula.Scale, "Arial");
var scale = Formula.Scale;
var environment = WpfTeXEnvironment.Create(scale: scale);

// Open stream
var filename = saveFileDialog.FileName;
using var stream = new FileStream(filename, FileMode.Create);
switch (saveFileDialog.FilterIndex)
{
case 1:
var geometry = renderer.RenderToGeometry(0, 0);
var geometry = formula.RenderToGeometry(environment, scale: scale);
var converter = new SVGConverter();
var svgPathText = converter.ConvertGeometry(geometry);
var svgText = AddSvgHeader(svgPathText);
Expand All @@ -85,7 +87,7 @@ private void saveButton_Click(object sender, RoutedEventArgs e)
break;

case 2:
var bitmap = renderer.RenderToBitmap(0, 0, 300);
var bitmap = formula.RenderToBitmap(environment, scale, dpi: 300);
var encoder = new PngBitmapEncoder
{
Frames = { BitmapFrame.Create(bitmap) }
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
40 changes: 10 additions & 30 deletions src/WpfMath/TexFormula.cs → src/WpfMath.Shared/TexFormula.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Media;
using WpfMath.Atoms;
using WpfMath.Boxes;
using WpfMath.Fonts;
using WpfMath.Rendering;

namespace WpfMath
{
// Represents mathematical formula that can be rendered.
/// <summary>Represents mathematical formula that can be rendered.</summary>
public sealed class TexFormula
{
public string? TextStyle
Expand All @@ -27,18 +24,8 @@ internal Atom? RootAtom

public SourceSpan? Source { get; set; }

[Obsolete("Use extension methods from WpfMath.Rendering.TeXFormulaExtensions and WpfMath.Rendering.WpfTeXFormulaExtensions instead.")]
public TexRenderer GetRenderer(TexStyle style, // TODO: Revise internal usages of this method.
double scale,
string? systemTextFontName,
Brush? background = null,
Brush? foreground = null)
{
var mathFont = new DefaultTexFont(WpfMathFontProvider.Instance, scale);
var textFont = systemTextFontName == null ? (ITeXFont)mathFont : GetSystemFont(systemTextFontName, scale);
var environment = new TexEnvironment(style, mathFont, textFont, WpfBrush.FromBrush(background), WpfBrush.FromBrush(foreground));
return new TexRenderer(CreateBox(environment), scale);
}
// TODO: Document the absence of TexFormula.GetRenderer method (that should be replaced with
// WpfMath.Rendering.TeXFormulaExtensions and WpfMath.Rendering.WpfTeXFormulaExtensions).

public void Add(TexFormula formula, SourceSpan? source = null)
{
Expand Down Expand Up @@ -74,43 +61,36 @@ internal void Add(Atom atom, SourceSpan? rowSource)
}
}

public void SetForeground(Brush brush)
public void SetForeground(IPlatformBrush brush)
{
if (this.RootAtom is StyledAtom sa)
{
this.RootAtom = sa with { Foreground = brush.ToPlatform() };
this.RootAtom = sa with { Foreground = brush };
}
else
{
RootAtom = new StyledAtom(RootAtom?.Source, RootAtom, null, brush.ToPlatform());
RootAtom = new StyledAtom(RootAtom?.Source, RootAtom, null, brush);
}
}

public void SetBackground(Brush brush)
public void SetBackground(IPlatformBrush brush)
{
if (this.RootAtom is StyledAtom sa)
{
this.RootAtom = sa with { Background = brush.ToPlatform() };
this.RootAtom = sa with { Background = brush };
}
else
{
this.RootAtom = new StyledAtom(this.RootAtom?.Source, this.RootAtom, brush.ToPlatform(), null);
this.RootAtom = new StyledAtom(this.RootAtom?.Source, this.RootAtom, brush, null);
}
}

internal Box CreateBox(TexEnvironment environment)
public Box CreateBox(TexEnvironment environment)
{
if (this.RootAtom == null)
return StrutBox.Empty;
else
return this.RootAtom.CreateBox(environment);
}

internal static SystemFont GetSystemFont(string fontName, double size)
{
var fontFamily = System.Windows.Media.Fonts.SystemFontFamilies.First(
ff => ff.ToString() == fontName || ff.FamilyNames.Values?.Contains(fontName) == true);
return new SystemFont(size, fontFamily);
}
}
}
7 changes: 2 additions & 5 deletions src/WpfMath.Tests/BoxTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ open Xunit
open WpfMath
open WpfMath.Atoms
open WpfMath.Boxes
open WpfMath.Fonts
open WpfMath.Rendering
open WpfMath.Tests.ApprovalTestUtils

let private parse(text: string) =
Expand All @@ -18,10 +18,7 @@ let private parse(text: string) =

let private src (string: string) (start: int) (len: int) = SourceSpan("User input", string, start, len)

let private environment =
let mathFont = DefaultTexFont(WpfMathFontProvider.Instance, 20.0)
let textFont = TexFormula.GetSystemFont("Arial", 20.0)
TexEnvironment(TexStyle.Display, mathFont, textFont)
let private environment = WpfTeXEnvironment.Create()

[<Fact>]
let ``AccentedAtom should have a skew according to the char``() =
Expand Down
5 changes: 1 addition & 4 deletions src/WpfMath.Tests/CharBoxTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ type CharBoxTests() =
let result = parser.Parse text
result.RootAtom

let environment =
let mathFont = DefaultTexFont(WpfMathFontProvider.Instance, 20.0)
let textFont = TexFormula.GetSystemFont("Arial", 20.0)
TexEnvironment(TexStyle.Display, mathFont, textFont)
let environment = WpfTeXEnvironment.Create()

[<Fact>]
member _.``CharBox rendering calls to RenderCharacter``() =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
module WpfMath.Tests.TexRendererTests
module WpfMath.Tests.RenderingTests

open WpfMath
open Xunit

open WpfMath
open WpfMath.Rendering

[<Fact>]
let ``TexRenderer.RenderToBitmap should create an image of proper size``() =
let parser = TexFormulaParser()
let formula = parser.Parse "2+2=2"
let renderer = formula.GetRenderer(TexStyle.Display, 20.0, "Arial")
let bitmap = renderer.RenderToBitmap(0.0, 0.0)
let environment = WpfTeXEnvironment.Create()
let bitmap = formula.RenderToBitmap environment
Assert.Equal(82, bitmap.PixelWidth)
Assert.Equal(17, bitmap.PixelHeight)

[<Fact>]
let ``TexRenderer.RenderToBitmap should create an image of proper size with offset``() =
let parser = TexFormulaParser()
let formula = parser.Parse "2+2=2"
let renderer = formula.GetRenderer(TexStyle.Display, 20.0, "Arial")
let environment = WpfTeXEnvironment.Create()
let margin = 50
let bitmap = renderer.RenderToBitmap(float(margin), float(margin))
let bitmap = formula.RenderToBitmap(environment, x = float margin, y = float margin)

let formulaWidth = 82
let formulaHeight = 16
Expand All @@ -29,8 +31,8 @@ let ``TexRenderer.RenderToBitmap should create an image of proper size with offs
let ``TexRenderer.RenderToBitmap should work with different DPI``() =
let parser = TexFormulaParser()
let formula = parser.Parse "2+2=2"
let renderer = formula.GetRenderer(TexStyle.Display, 20.0, "Arial")
let bitmap = renderer.RenderToBitmap(0.0, 0.0, 192.0)
let environment = WpfTeXEnvironment.Create()
let bitmap = formula.RenderToBitmap(environment, dpi = 192.0)
Assert.Equal(163, bitmap.PixelWidth)
Assert.Equal(34, bitmap.PixelHeight)
Assert.Equal(192.0, bitmap.DpiX)
Expand Down
2 changes: 1 addition & 1 deletion src/WpfMath.Tests/WpfMath.Tests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
<Compile Include="OverUnderBoxTests.fs" />
<Compile Include="ParserTests.fs" />
<Compile Include="ParserExceptionTests.fs" />
<Compile Include="TexRendererTests.fs" />
<Compile Include="RenderingTests.fs" />
<Compile Include="TransformationTests.fs" />
<Compile Include="VerticalBoxTests.fs" />
<Compile Include="WpfRendererTests.fs" />
Expand Down
17 changes: 11 additions & 6 deletions src/WpfMath/Controls/FormulaControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace WpfMath.Controls
/// </summary>
public partial class FormulaControl : UserControl
{
private static TexFormulaParser formulaParser = new TexFormulaParser();
private static TexFormulaParser _formulaParser = new();
private TexFormula? texFormula;

public string Formula
Expand Down Expand Up @@ -136,15 +136,20 @@ private void Render()
// Render formula to visual.
var visual = new DrawingVisual();

// Pass transparent background, since the control background will be effectively used anyway.
var renderer = texFormula.GetRenderer(TexStyle.Display, Scale, SystemTextFontName, Brushes.Transparent, Foreground);
// Omit passing the background, since the control background will be effectively used anyway.
var environment = WpfTeXEnvironment.Create(
scale: Scale,
systemTextFontName: SystemTextFontName,
foreground: Foreground);

var formulaSource = texFormula.Source;
var formulaBox = texFormula.CreateBox(environment);
if (formulaSource != null)
{
var selectionBrush = SelectionBrush;
if (selectionBrush != null)
{
var allBoxes = new List<Box>(renderer.Box.Children);
var allBoxes = new List<Box>(formulaBox.Children);
var selectionStart = SelectionStart;
var selectionEnd = selectionStart + SelectionLength;
for (var idx = 0; idx < allBoxes.Count; idx++)
Expand All @@ -168,7 +173,7 @@ private void Render()

using (var drawingContext = visual.RenderOpen())
{
renderer.Render(drawingContext, 0, 0);
texFormula.RenderTo(drawingContext, environment, Scale, 0, 0);
}
formulaContainerElement.Visual = visual;
}
Expand All @@ -181,7 +186,7 @@ private static object CoerceFormula(DependencyObject d, object baseValue)
{
control.HasError = false;
control.Errors.Clear();
control.texFormula = formulaParser.Parse(formula);
control.texFormula = _formulaParser.Parse(formula);
return baseValue;
}
catch (TexException e)
Expand Down
5 changes: 3 additions & 2 deletions src/WpfMath/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.IO;
using System.Windows.Media.Imaging;
using WpfMath.Rendering;

namespace WpfMath
{
Expand All @@ -11,8 +12,8 @@ public static byte[] RenderToPng(this TexFormula texForm,
double y,
string systemTextFontName)
{
var trnder = texForm.GetRenderer(TexStyle.Display, scale, systemTextFontName);
BitmapSource image = trnder.RenderToBitmap(x, y);
var environment = WpfTeXEnvironment.Create();
BitmapSource image = texForm.RenderToBitmap(environment, scale, x, y);

PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(image));
Expand Down
39 changes: 39 additions & 0 deletions src/WpfMath/Rendering/WpfTeXEnvironment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Linq;
using System.Windows.Media;
using WpfMath.Fonts;

namespace WpfMath.Rendering;

public static class WpfTeXEnvironment
{
/// <summary>Creates an instance of <see cref="TexEnvironment"/> for a WPF program.</summary>
/// <param name="style">Initial style for the formula content.</param>
/// <param name="scale">Formula font size.</param>
/// <param name="systemTextFontName">Name of the system font to use for the <code>\text</code> blocks.</param>
/// <param name="foreground">Foreground color. Black if not specified.</param>
/// <param name="background">Background color.</param>
public static TexEnvironment Create(
TexStyle style = TexStyle.Display,
double scale = 20.0,
string systemTextFontName = "Arial",
Brush? foreground = null,
Brush? background = null)
{
var mathFont = new DefaultTexFont(WpfMathFontProvider.Instance, scale);
var textFont = GetSystemFont(systemTextFontName, scale);

return new TexEnvironment(
style,
mathFont,
textFont,
background.ToPlatform(),
foreground.ToPlatform());
}

private static SystemFont GetSystemFont(string fontName, double size)
{
var fontFamily = System.Windows.Media.Fonts.SystemFontFamilies.First(
ff => ff.ToString() == fontName || ff.FamilyNames.Values?.Contains(fontName) == true);
return new SystemFont(size, fontFamily);
}
}
8 changes: 4 additions & 4 deletions src/WpfMath/Rendering/WpfTeXFormulaExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static class WpfTeXFormulaExtensions
public static Geometry RenderToGeometry( // TODO: Tests for this method.
this TexFormula formula,
TexEnvironment environment,
double scale, // TODO: Get rid of this; it is already encoded in the renderer anyway.
double scale = 20.0,
double x = 0.0,
double y = 0.0)
{
Expand All @@ -25,9 +25,9 @@ public static class WpfTeXFormulaExtensions
public static BitmapSource RenderToBitmap( // TODO: Tests for this method.
this TexFormula formula,
TexEnvironment environment,
double scale, // TODO: Get rid of this; it is already encoded in the renderer anyway.
double x,
double y,
double scale = 20.0,
double x = 0,
double y = 0,
double dpi = DefaultDpi)
{
var visual = new DrawingVisual();
Expand Down

0 comments on commit 44d3bac

Please sign in to comment.