Skip to content

Commit

Permalink
Functor-based API for char stuff (ForNeVeR#129)
Browse files Browse the repository at this point in the history
  • Loading branch information
ForNeVeR committed Apr 29, 2018
1 parent ab17032 commit a94c358
Show file tree
Hide file tree
Showing 20 changed files with 145 additions and 157 deletions.
7 changes: 4 additions & 3 deletions src/WpfMath.Tests/CharBoxTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type CharBoxTests() =
member __.``CharBox rendering calls to RenderGlyphRun``() =
let font = DefaultTexFont 20.0
let environment = TexEnvironment(TexStyle.Display, font, font)
let char = environment.MathFont.GetDefaultCharInfo('x', TexStyle.Display)
let char = environment.MathFont.GetDefaultCharInfo('x', TexStyle.Display).Value
let x = 0.5
let y = 1.0

Expand All @@ -28,7 +28,8 @@ type CharBoxTests() =
Mock.Verify(<@ mockedRenderer.RenderGlyphRun(any(), x, y, Brushes.Black) @>, once)

[<Fact>]
member __.``Currently unsupporteded characters like "Å" should throw TexCharacterMappingNotFoundException``() =
member __.``Currently unsupporteded characters like "Å" should result in TexCharacterMappingNotFoundException``() =
let font = DefaultTexFont 20.0
let environment = TexEnvironment(TexStyle.Display, font, font)
Assert.Throws<TexCharacterMappingNotFoundException>(Func<obj>(fun () -> upcast environment.MathFont.GetDefaultCharInfo('Å', TexStyle.Display)))
Assert.IsType<TexCharacterMappingNotFoundException>(
environment.MathFont.GetDefaultCharInfo('Å', TexStyle.Display).Error)
9 changes: 3 additions & 6 deletions src/WpfMath.Tests/DefaultTexFontTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,15 @@ type DefaultTexFontTests() =

[<Fact>]
member __.``GetCharInfo(char, string, TexStyle) throws a TextStyleMappingNotFoundException for unknown text style``() =
Assert.Throws<TextStyleMappingNotFoundException>(
fun () -> ignore <| font.GetCharInfo('x', "unknownStyle", TexStyle.Text))
Assert.IsType<TextStyleMappingNotFoundException>(font.GetCharInfo('x', "unknownStyle", TexStyle.Text).Error)

[<Fact>]
member __.``GetCharInfo(string, TexStyle) returns a CharInfo for existing symbol``() =
Assert.NotNull <| font.GetCharInfo("sqrt", TexStyle.Text)

[<Fact>]
member __.``GetCharInfo(string, TexStyle) throws a SymbolMappingNotFoundException for unknown symbol``() =
Assert.Throws<SymbolMappingNotFoundException>(
fun () -> ignore <| font.GetCharInfo("unknownSymbol", TexStyle.Text))
Assert.IsType<SymbolMappingNotFoundException>(font.GetCharInfo("unknownSymbol", TexStyle.Text).Error)

[<Fact>]
member __.``GetCharInfo(CharFont, TexStyle) returns a CharInfo for existing symbol``() =
Expand All @@ -36,5 +34,4 @@ type DefaultTexFontTests() =
[<Fact>]
member __.``GetCharInfo(CharFont, TexStyle) throws a TexCharacterMappingNotFoundException for unknown character``() =
let char = CharFont('й', 1)
Assert.Throws<TexCharacterMappingNotFoundException>(
fun () -> ignore <| font.GetCharInfo(char, TexStyle.Text))
Assert.IsType<TexCharacterMappingNotFoundException>(font.GetCharInfo(char, TexStyle.Text).Error)
2 changes: 1 addition & 1 deletion src/WpfMath.Tests/GeometryElementRendererTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type GeometryElementRendererTests() =
member __.``GeometryElementRenderer.RenderGlyphRun adds a PathGeometry group``() : unit =
let font = DefaultTexFont 20.0
let environment = TexEnvironment(TexStyle.Display, font, font)
let char = environment.MathFont.GetDefaultCharInfo('x', TexStyle.Display)
let char = environment.MathFont.GetDefaultCharInfo('x', TexStyle.Display).Value
let charBox = CharBox(environment, char)
let glyphRun = charBox.GetGlyphRun(1.0, 0.0, 0.0)
let factory = Func<double, GlyphRun>(fun s -> glyphRun)
Expand Down
4 changes: 2 additions & 2 deletions src/WpfMath/AccentedAtom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ CharSymbol GetBaseChar()

// Create box for base atom.
var baseBox = this.BaseAtom == null ? StrutBox.Empty : this.BaseAtom.CreateBox(environment.GetCrampedStyle());
var baseCharFont = GetBaseChar()?.GetCharFont(texFont);
var baseCharFont = GetBaseChar()?.GetCharFont(texFont).Value;
var skew = baseCharFont == null ? 0.0 : texFont.GetSkew(baseCharFont, style);

// Find character of best scale for accent symbol.
var accentChar = texFont.GetCharInfo(AccentAtom.Name, style);
var accentChar = texFont.GetCharInfo(AccentAtom.Name, style).Value;
while (texFont.HasNextLarger(accentChar))
{
var nextLargerChar = texFont.GetNextLargerCharInfo(accentChar, style);
Expand Down
2 changes: 1 addition & 1 deletion src/WpfMath/BigOperatorAtom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ protected override Box CreateBoxCore(TexEnvironment environment)
if (this.BaseAtom is SymbolAtom && this.BaseAtom.Type == TexAtomType.BigOperator)
{
// Find character of best scale for operator symbol.
var opChar = texFont.GetCharInfo(((SymbolAtom)this.BaseAtom).Name, style);
var opChar = texFont.GetCharInfo(((SymbolAtom)this.BaseAtom).Name, style).Value;
if (style < TexStyle.Text && texFont.HasNextLarger(opChar))
opChar = texFont.GetNextLargerCharInfo(opChar, style);
var charBox = new CharBox(environment, opChar) { Source = this.BaseAtom.Source };
Expand Down
22 changes: 5 additions & 17 deletions src/WpfMath/CharAtom.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using WpfMath.Utils;

namespace WpfMath
{
// Atom representing single character in specific text style.
Expand All @@ -17,30 +19,16 @@ public CharAtom(SourceSpan source, char character, string textStyle = null)

private bool IsDefaultTextStyle => this.TextStyle == null;

protected override Box CreateBoxCore(TexEnvironment environment)
{
var font = GetStyledFont(environment);
var charInfo = GetCharInfo(font, environment.Style);
return new CharBox(environment, charInfo);
}

public override ITeXFont GetStyledFont(TexEnvironment environment) =>
TextStyle == TexUtilities.TextStyleName ? environment.TextFont : base.GetStyledFont(environment);

public override bool IsSupportedByFont(ITeXFont font) =>
this.IsDefaultTextStyle
? font.SupportsDefaultCharacter(this.Character, TexStyle.Display)
: font.SupportsCharacter(this.Character, this.TextStyle, TexStyle.Display);

private CharInfo GetCharInfo(ITeXFont texFont, TexStyle style) =>
protected override Result<CharInfo> GetCharInfo(ITeXFont texFont, TexStyle style) =>
this.IsDefaultTextStyle
? texFont.GetDefaultCharInfo(this.Character, style)
: texFont.GetCharInfo(this.Character, this.TextStyle, style);

public override CharFont GetCharFont(ITeXFont texFont)
{
public override Result<CharFont> GetCharFont(ITeXFont texFont) =>
// Style is irrelevant here.
return GetCharInfo(texFont, TexStyle.Display).GetCharacterFont();
}
this.GetCharInfo(texFont, TexStyle.Display).Map(ci => ci.GetCharacterFont());
}
}
17 changes: 15 additions & 2 deletions src/WpfMath/CharSymbol.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using WpfMath.Utils;

namespace WpfMath
{
// Atom representing single character that can be marked as text symbol.
Expand All @@ -14,13 +16,24 @@ protected CharSymbol(SourceSpan source, TexAtomType type = TexAtomType.Ordinary)
/// <summary>Returns the preferred font to render this character.</summary>
public virtual ITeXFont GetStyledFont(TexEnvironment environment) => environment.MathFont;

/// <summary>Returns a <see cref="CharInfo"/> for this character.</summary>
protected abstract Result<CharInfo> GetCharInfo(ITeXFont font, TexStyle style);

protected sealed override Box CreateBoxCore(TexEnvironment environment)
{
var font = this.GetStyledFont(environment);
var charInfo = this.GetCharInfo(font, environment.Style);
return new CharBox(environment, charInfo.Value);
}

/// <summary>Checks if the symbol can be rendered by font.</summary>
public abstract bool IsSupportedByFont(ITeXFont font);
public bool IsSupportedByFont(ITeXFont font, TexStyle style) =>
this.GetCharInfo(font, style).IsSuccess;

/// <summary>
/// Returns the symbol rendered by font. Throws an exception if the symbol is not supported by font. Always
/// succeed if <see cref="IsSupportedByFont"/>.
/// </summary>
public abstract CharFont GetCharFont(ITeXFont texFont);
public abstract Result<CharFont> GetCharFont(ITeXFont texFont);
}
}
82 changes: 27 additions & 55 deletions src/WpfMath/DefaultTexFont.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using WpfMath.Exceptions;
using WpfMath.Utils;

namespace WpfMath
{
Expand Down Expand Up @@ -52,14 +53,6 @@ public DefaultTexFont(double size)

public bool SupportsMetrics => true;

public bool SupportsSymbol(string name) => symbolMappings.ContainsKey(name);

public bool SupportsDefaultCharacter(char character, TexStyle style) =>
this.GetDefaultCharInfo(character, style, false) != null;

public bool SupportsCharacter(char character, string textStyle, TexStyle style) =>
this.GetCharInfo(character, textStyle, style, false) != null;

public double Size
{
get;
Expand All @@ -84,12 +77,15 @@ public ExtensionChar GetExtension(CharInfo charInfo, TexStyle style)
if (extension[i] == (int)TexCharKind.None)
parts[i] = null;
else
{
var metrics = GetMetrics(new CharFont((char)extension[i], charInfo.FontId), sizeFactor).Value;
parts[i] = new CharInfo(
(char)extension[i],
charInfo.Font,
sizeFactor,
charInfo.FontId,
GetMetrics(new CharFont((char)extension[i], charInfo.FontId), sizeFactor, true));
metrics);
}
}

return new ExtensionChar(parts[TexFontUtilities.ExtensionTop], parts[TexFontUtilities.ExtensionMiddle],
Expand All @@ -115,7 +111,7 @@ public CharInfo GetNextLargerCharInfo(CharInfo charInfo, TexStyle style)
newFontInfo.Font,
GetSizeFactor(style),
charFont.FontId,
GetMetrics(charFont, GetSizeFactor(style), true));
GetMetrics(charFont, GetSizeFactor(style)).Value);
}

private static string GetDefaultTextStyleMapping(char character)
Expand All @@ -133,10 +129,10 @@ TexCharKind GetCharKind()
return defaultTextStyleMappings[(int)GetCharKind()];
}

public CharInfo GetDefaultCharInfo(char character, TexStyle style, bool assert = true) =>
this.GetCharInfo(character, GetDefaultTextStyleMapping(character), style, assert);
public Result<CharInfo> GetDefaultCharInfo(char character, TexStyle style) =>
this.GetCharInfo(character, GetDefaultTextStyleMapping(character), style);

private CharInfo GetCharInfo(char character, CharFont[] charFont, TexStyle style, bool assert)
private Result<CharInfo> GetCharInfo(char character, CharFont[] charFont, TexStyle style)
{
TexCharKind charKind;
int charIndexOffset;
Expand All @@ -157,46 +153,30 @@ private CharInfo GetCharInfo(char character, CharFont[] charFont, TexStyle style
}

return charFont[(int)charKind] == null
? this.GetDefaultCharInfo(character, style, assert)
? this.GetDefaultCharInfo(character, style)
: this.GetCharInfo(
new CharFont(
(char)(charFont[(int)charKind].Character + charIndexOffset),
charFont[(int)charKind].FontId),
style,
assert);
style);
}

public CharInfo GetCharInfo(char character, string textStyle, TexStyle style, bool assert = true)
{
if (textStyleMappings.TryGetValue(textStyle, out var mapping))
{
return this.GetCharInfo(character, mapping, style, assert);
}

return assert ? throw new TextStyleMappingNotFoundException(textStyle) : (CharInfo)null;
}
public Result<CharInfo> GetCharInfo(char character, string textStyle, TexStyle style) =>
textStyleMappings.TryGetValue(textStyle, out var mapping)
? this.GetCharInfo(character, mapping, style)
: Result.Error<CharInfo>(new TextStyleMappingNotFoundException(textStyle));

public CharInfo GetCharInfo(string symbolName, TexStyle style) =>
public Result<CharInfo> GetCharInfo(string symbolName, TexStyle style) =>
symbolMappings.TryGetValue(symbolName, out var mapping)
? this.GetCharInfo(mapping, style)
: throw new SymbolMappingNotFoundException(symbolName);
: Result.Error<CharInfo>(new SymbolMappingNotFoundException(symbolName));

public CharInfo GetCharInfo(CharFont charFont, TexStyle style, bool assert = true)
public Result<CharInfo> GetCharInfo(CharFont charFont, TexStyle style)
{
var size = GetSizeFactor(style);
var fontInfo = fontInfoList[charFont.FontId];
var metrics = GetMetrics(charFont, size, assert);
if (metrics == null)
{
return null;
}

return new CharInfo(
charFont.Character,
fontInfo.Font,
size,
charFont.FontId,
metrics);
var metrics = GetMetrics(charFont, size);
return metrics.Map(m => new CharInfo(charFont.Character, fontInfo.Font, size, charFont.FontId, m));
}

public double GetKern(CharFont leftCharFont, CharFont rightCharFont, TexStyle style)
Expand Down Expand Up @@ -355,24 +335,16 @@ public double GetDefaultLineThickness(TexStyle style)
return GetParameter("defaultrulethickness") * GetSizeFactor(style) * TexFontUtilities.PixelsPerPoint;
}

private static TexFontMetrics GetMetrics(CharFont charFont, double size, bool assert)
private static Result<TexFontMetrics> GetMetrics(CharFont charFont, double size)
{
var fontInfo = fontInfoList[charFont.FontId];
var metrics = fontInfo.GetMetrics(charFont.Character);
if (metrics == null)
{
if (assert)
throw new TexCharacterMappingNotFoundException(
$"Cannot determine metrics for '{charFont.Character}' character in font {charFont.FontId}");
return null;
}

return new TexFontMetrics(
metrics[TexFontUtilities.MetricsWidth],
metrics[TexFontUtilities.MetricsHeight],
metrics[TexFontUtilities.MetricsDepth],
metrics[TexFontUtilities.MetricsItalic],
size * TexFontUtilities.PixelsPerPoint);
return metrics.Map(m => new TexFontMetrics(
m[TexFontUtilities.MetricsWidth],
m[TexFontUtilities.MetricsHeight],
m[TexFontUtilities.MetricsDepth],
m[TexFontUtilities.MetricsItalic],
size * TexFontUtilities.PixelsPerPoint));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/WpfMath/DelimiterFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static Box CreateBox(string symbol, double minHeight, TexEnvironment envi
{
var texFont = environment.MathFont;
var style = environment.Style;
var charInfo = texFont.GetCharInfo(symbol, style);
var charInfo = texFont.GetCharInfo(symbol, style).Value;

// Find first version of character that has at least minimum height.
var metrics = charInfo.Metrics;
Expand Down
8 changes: 4 additions & 4 deletions src/WpfMath/DummyAtom.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using WpfMath.Utils;

namespace WpfMath
{
// Dummy atom representing atom whose type can change or which can be replaced by a ligature.
Expand Down Expand Up @@ -43,10 +45,8 @@ public bool IsKern
get { return this.Atom is SpaceAtom; }
}

public CharFont GetCharFont(ITeXFont texFont)
{
return ((CharSymbol)this.Atom).GetCharFont(texFont);
}
public Result<CharFont> GetCharFont(ITeXFont texFont) =>
((CharSymbol)this.Atom).GetCharFont(texFont);

protected override Box CreateBoxCore(TexEnvironment environment) =>
this.Atom.CreateBox(environment);
Expand Down
19 changes: 6 additions & 13 deletions src/WpfMath/FixedCharAtom.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using WpfMath.Utils;

namespace WpfMath
{
// Atom representing character that does not depend on text style.
Expand All @@ -11,19 +13,10 @@ public FixedCharAtom(SourceSpan source, CharFont charFont)

public CharFont CharFont { get; }

public override bool IsSupportedByFont(ITeXFont font) =>
// Always "supported" because it ignores the font.
true;

public override CharFont GetCharFont(ITeXFont texFont)
{
return this.CharFont;
}
protected override Result<CharInfo> GetCharInfo(ITeXFont font, TexStyle style) =>
font.GetCharInfo(this.CharFont, style);

protected override Box CreateBoxCore(TexEnvironment environment)
{
var charInfo = environment.MathFont.GetCharInfo(this.CharFont, environment.Style);
return new CharBox(environment, charInfo);
}
public override Result<CharFont> GetCharFont(ITeXFont texFont) =>
Result.Ok(this.CharFont);
}
}
Loading

0 comments on commit a94c358

Please sign in to comment.