Improved font matching and exception message. Refactored tests.
This commit is contained in:
Родитель
8db283d559
Коммит
a92cc25fb1
|
@ -1,123 +1,146 @@
|
|||
using NUnit.Framework;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Drawing;
|
||||
using SkiaSharp;
|
||||
using static SkiaSharp.SKFontStyleSlant;
|
||||
|
||||
namespace QuestPDF.UnitTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class FontStyleSetTests
|
||||
{
|
||||
private void ExpectComparisonOrder(SKFontStyle target, params SKFontStyle[] styles)
|
||||
private void ExpectComparisonOrder(SKFontStyle target, SKFontStyle[] styles)
|
||||
{
|
||||
for (int i = 0; i < styles.Length - 1; i++)
|
||||
for (var i = 0; i < styles.Length - 1; i++)
|
||||
{
|
||||
Assert.True(FontStyleSet.IsBetterMatch(target, styles[i], styles[i + 1]));
|
||||
Assert.False(FontStyleSet.IsBetterMatch(target, styles[i + 1], styles[i]));
|
||||
var currentStyle = styles[i];
|
||||
var nextStyle = styles[i + 1];
|
||||
|
||||
FontStyleSet.IsBetterMatch(target, currentStyle, nextStyle).Should().BeTrue();
|
||||
FontStyleSet.IsBetterMatch(target, nextStyle, currentStyle).Should().BeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FontStyleSet_IsBetterMatch_CondensedWidth()
|
||||
{
|
||||
ExpectComparisonOrder(
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 4, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 3, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 6, SKFontStyleSlant.Upright)
|
||||
);
|
||||
var styles = new[]
|
||||
{
|
||||
new SKFontStyle(500, 5, Upright),
|
||||
new SKFontStyle(500, 4, Upright),
|
||||
new SKFontStyle(500, 3, Upright),
|
||||
new SKFontStyle(500, 6, Upright)
|
||||
};
|
||||
|
||||
ExpectComparisonOrder(new SKFontStyle(500, 5, Upright), styles);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FontStyleSet_IsBetterMatch_ExpandedWidth()
|
||||
{
|
||||
ExpectComparisonOrder(
|
||||
new SKFontStyle(500, 6, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 6, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 7, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 8, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Upright)
|
||||
);
|
||||
var styles = new[]
|
||||
{
|
||||
new SKFontStyle(500, 6, Upright),
|
||||
new SKFontStyle(500, 7, Upright),
|
||||
new SKFontStyle(500, 8, Upright),
|
||||
new SKFontStyle(500, 5, Upright)
|
||||
};
|
||||
|
||||
ExpectComparisonOrder(new SKFontStyle(500, 6, Upright), styles);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FontStyleSet_IsBetterMatch_ItalicSlant()
|
||||
{
|
||||
ExpectComparisonOrder(
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Italic),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Italic),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Oblique),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Upright)
|
||||
);
|
||||
var styles = new[]
|
||||
{
|
||||
new SKFontStyle(500, 5, Italic),
|
||||
new SKFontStyle(500, 5, Oblique),
|
||||
new SKFontStyle(500, 5, Upright)
|
||||
};
|
||||
|
||||
ExpectComparisonOrder(new SKFontStyle(500, 5, Italic), styles);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FontStyleSet_IsBetterMatch_ObliqueSlant()
|
||||
{
|
||||
ExpectComparisonOrder(
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Oblique),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Oblique),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Italic),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Upright)
|
||||
);
|
||||
var styles = new[]
|
||||
{
|
||||
new SKFontStyle(500, 5, Oblique),
|
||||
new SKFontStyle(500, 5, Italic),
|
||||
new SKFontStyle(500, 5, Upright)
|
||||
};
|
||||
|
||||
ExpectComparisonOrder(new SKFontStyle(500, 5, Oblique), styles);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FontStyleSet_IsBetterMatch_UprightSlant()
|
||||
{
|
||||
ExpectComparisonOrder(
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Oblique),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Italic)
|
||||
);
|
||||
var styles = new[]
|
||||
{
|
||||
new SKFontStyle(500, 5, Upright),
|
||||
new SKFontStyle(500, 5, Oblique),
|
||||
new SKFontStyle(500, 5, Italic)
|
||||
};
|
||||
|
||||
ExpectComparisonOrder(new SKFontStyle(500, 5, Upright), styles);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FontStyleSet_IsBetterMatch_ThinWeight()
|
||||
{
|
||||
ExpectComparisonOrder(
|
||||
new SKFontStyle(300, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(300, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(200, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(100, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(400, 5, SKFontStyleSlant.Upright)
|
||||
);
|
||||
var styles = new[]
|
||||
{
|
||||
new SKFontStyle(300, 5, Upright),
|
||||
new SKFontStyle(200, 5, Upright),
|
||||
new SKFontStyle(100, 5, Upright),
|
||||
new SKFontStyle(400, 5, Upright)
|
||||
};
|
||||
|
||||
ExpectComparisonOrder(new SKFontStyle(300, 5, Upright), styles);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FontStyleSet_IsBetterMatch_RegularWeight()
|
||||
{
|
||||
ExpectComparisonOrder(
|
||||
new SKFontStyle(400, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(300, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(100, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(600, 5, SKFontStyleSlant.Upright)
|
||||
);
|
||||
var styles = new[]
|
||||
{
|
||||
new SKFontStyle(500, 5, Upright),
|
||||
new SKFontStyle(300, 5, Upright),
|
||||
new SKFontStyle(100, 5, Upright),
|
||||
new SKFontStyle(600, 5, Upright)
|
||||
};
|
||||
|
||||
ExpectComparisonOrder(new SKFontStyle(400, 5, Upright), styles);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FontStyleSet_IsBetterMatch_BoldWeight()
|
||||
{
|
||||
ExpectComparisonOrder(
|
||||
new SKFontStyle(600, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(600, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(700, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(800, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Upright)
|
||||
);
|
||||
var styles = new[]
|
||||
{
|
||||
new SKFontStyle(600, 5, Upright),
|
||||
new SKFontStyle(700, 5, Upright),
|
||||
new SKFontStyle(800, 5, Upright),
|
||||
new SKFontStyle(500, 5, Upright)
|
||||
};
|
||||
|
||||
ExpectComparisonOrder(new SKFontStyle(600, 5, Upright), styles);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FontStyleSet_RespectsPriority()
|
||||
{
|
||||
ExpectComparisonOrder(
|
||||
new SKFontStyle(500, 5, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(600, 5, SKFontStyleSlant.Italic),
|
||||
new SKFontStyle(600, 6, SKFontStyleSlant.Upright),
|
||||
new SKFontStyle(500, 6, SKFontStyleSlant.Italic)
|
||||
);
|
||||
var styles = new[]
|
||||
{
|
||||
new SKFontStyle(600, 5, Italic),
|
||||
new SKFontStyle(600, 6, Upright),
|
||||
new SKFontStyle(500, 6, Italic)
|
||||
};
|
||||
|
||||
ExpectComparisonOrder(new SKFontStyle(500, 5, Upright), styles);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,8 +10,8 @@ namespace QuestPDF.Drawing
|
|||
public static class FontManager
|
||||
{
|
||||
private static ConcurrentDictionary<string, FontStyleSet> StyleSets = new();
|
||||
private static ConcurrentDictionary<string, SKFontMetrics> FontMetrics = new();
|
||||
private static ConcurrentDictionary<string, SKPaint> Paints = new();
|
||||
private static ConcurrentDictionary<object, SKFontMetrics> FontMetrics = new();
|
||||
private static ConcurrentDictionary<object, SKPaint> Paints = new();
|
||||
private static ConcurrentDictionary<string, SKPaint> ColorPaint = new();
|
||||
|
||||
private static void RegisterFontType(SKData fontData, string? customName = null)
|
||||
|
@ -59,7 +59,7 @@ namespace QuestPDF.Drawing
|
|||
|
||||
internal static SKPaint ToPaint(this TextStyle style)
|
||||
{
|
||||
return Paints.GetOrAdd(style.Key, key => Convert(style));
|
||||
return Paints.GetOrAdd(style.PaintKey, key => Convert(style));
|
||||
|
||||
static SKPaint Convert(TextStyle style)
|
||||
{
|
||||
|
@ -67,8 +67,7 @@ namespace QuestPDF.Drawing
|
|||
{
|
||||
Color = SKColor.Parse(style.Color),
|
||||
Typeface = GetTypeface(style),
|
||||
TextSize = style.Size ?? 12,
|
||||
TextEncoding = SKTextEncoding.Utf32
|
||||
TextSize = style.Size ?? 12
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -77,19 +76,27 @@ namespace QuestPDF.Drawing
|
|||
var weight = (SKFontStyleWeight)(style.FontWeight ?? FontWeight.Normal);
|
||||
var slant = (style.IsItalic ?? false) ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright;
|
||||
|
||||
var skFontStyle = new SKFontStyle(weight, SKFontStyleWidth.Normal, slant);
|
||||
var fontStyle = new SKFontStyle(weight, SKFontStyleWidth.Normal, slant);
|
||||
|
||||
if (StyleSets.TryGetValue(style.FontType, out var set))
|
||||
return set.Match(skFontStyle);
|
||||
if (StyleSets.TryGetValue(style.FontType, out var fontStyleSet))
|
||||
return fontStyleSet.Match(fontStyle);
|
||||
|
||||
return SKTypeface.FromFamilyName(style.FontType, skFontStyle)
|
||||
?? throw new ArgumentException($"The typeface {style.FontType} could not be found. Please consider installing the font file on your system or loading it from a file using the FontManager.RegisterFontType() static method.");
|
||||
var fontFromDefaultSource = SKFontManager.Default.MatchFamily(style.FontType, fontStyle);
|
||||
|
||||
if (fontFromDefaultSource != null)
|
||||
return fontFromDefaultSource;
|
||||
|
||||
throw new ArgumentException(
|
||||
$"The typeface '{style.FontType}' could not be found. " +
|
||||
$"Please consider the following options: " +
|
||||
$"1) install the font on your operating system or execution environment. " +
|
||||
$"2) load a font file specifically for QuestPDF usage via the QuestPDF.Drawing.FontManager.RegisterFontType(Stream fileContentStream) static method.");
|
||||
}
|
||||
}
|
||||
|
||||
internal static SKFontMetrics ToFontMetrics(this TextStyle style)
|
||||
{
|
||||
return FontMetrics.GetOrAdd(style.Key, key => style.ToPaint().FontMetrics);
|
||||
return FontMetrics.GetOrAdd(style.FontMetricsKey, key => style.ToPaint().FontMetrics);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,8 @@ namespace QuestPDF.Infrastructure
|
|||
internal bool? HasStrikethrough { get; set; }
|
||||
internal bool? HasUnderline { get; set; }
|
||||
|
||||
internal string? Key { get; private set; }
|
||||
internal object PaintKey { get; private set; }
|
||||
internal object FontMetricsKey { get; private set; }
|
||||
|
||||
internal static TextStyle LibraryDefault => new TextStyle
|
||||
{
|
||||
|
@ -42,7 +43,8 @@ namespace QuestPDF.Infrastructure
|
|||
HasGlobalStyleApplied = true;
|
||||
|
||||
ApplyParentStyle(globalStyle);
|
||||
Key ??= $"{Color}|{BackgroundColor}|{FontType}|{Size}|{LineHeight}|{FontWeight}|{IsItalic}|{HasStrikethrough}|{HasUnderline}";
|
||||
PaintKey ??= (FontType, Size, FontWeight, IsItalic, Color);
|
||||
FontMetricsKey ??= (FontType, Size, FontWeight, IsItalic);
|
||||
}
|
||||
|
||||
internal void ApplyParentStyle(TextStyle parentStyle)
|
||||
|
|
Загрузка…
Ссылка в новой задаче