Fixed build, adapted fallback process for cached TextStyle

This commit is contained in:
MarcinZiabek
2022-09-15 15:09:30 +02:00
parent 4650c2a4ea
commit fbebbd85eb
4 changed files with 63 additions and 26 deletions
+1 -1
View File
@@ -172,7 +172,7 @@ namespace QuestPDF.Drawing
{
if (textBlockItem is TextBlockSpan textSpan)
{
textSpan.Style = textSpan.Style.ApplyGlobalStyle(TextStyle.LibraryDefault);
textSpan.Style = textSpan.Style.ApplyGlobalStyle(documentDefaultTextStyle);
}
else if (textBlockItem is TextBlockElement textElement)
{
+8 -4
View File
@@ -85,22 +85,26 @@ namespace QuestPDF.Elements.Text
if (fallbackOption.Font.ContainsGlyph(codepoint))
return fallbackOption;
}
throw CreateNotMatchingFontException(codepoint);
}
static Exception CreateNotMatchingFontException(int codepoint)
{
var character = char.ConvertFromUtf32(codepoint);
var unicode = $"U-{codepoint:X4}";
var proposedFonts = FindFontsContainingGlyph(codepoint);
var proposedFontsFormatted = proposedFonts.Any() ? string.Join(", ", proposedFonts) : "no fonts available";
throw new DocumentDrawingException(
return new DocumentDrawingException(
$"Could not find an appropriate font fallback for glyph: {unicode} '{character}'. " +
$"Font families available on current environment that contain this glyph: {proposedFontsFormatted}. " +
$"Possible solutions: " +
$"1) Use one of the listed fonts as the primary font in your document. " +
$"2) Configure the fallback TextStyle using the 'TextStyle.Fallback' method with one of the listed fonts. ");
}
static IEnumerable<string> FindFontsContainingGlyph(int codepoint)
{
var fontManager = SKFontManager.Default;
+1 -1
View File
@@ -156,7 +156,7 @@ namespace QuestPDF.Fluent
public static TextStyle Fallback(this TextStyle style, TextStyle? value = null)
{
return style.Mutate(x => x.Fallback = value);
return style.Mutate(TextStyleProperty.Fallback, value);
}
public static TextStyle Fallback(this TextStyle style, Func<TextStyle, TextStyle> handler)
+53 -20
View File
@@ -16,13 +16,15 @@ namespace QuestPDF.Infrastructure
IsItalic,
HasStrikethrough,
HasUnderline,
WrapAnywhere
WrapAnywhere,
Fallback
}
internal static class TextStyleManager
{
public static ConcurrentDictionary<(TextStyle origin, TextStyleProperty property, object value), TextStyle> TextStyleMutateCache = new();
public static ConcurrentDictionary<(TextStyle origin, TextStyle parent, bool overrideValue), TextStyle> TextStyleApplyCache = new();
private static readonly ConcurrentDictionary<(TextStyle origin, TextStyleProperty property, object value), TextStyle> TextStyleMutateCache = new();
private static readonly ConcurrentDictionary<(TextStyle origin, TextStyle parent), TextStyle> TextStyleApplyGlobalCache = new();
private static readonly ConcurrentDictionary<(TextStyle origin, TextStyle parent), TextStyle> TextStyleOverrideCache = new();
public static TextStyle Mutate(this TextStyle origin, TextStyleProperty property, object value)
{
@@ -30,7 +32,7 @@ namespace QuestPDF.Infrastructure
return TextStyleMutateCache.GetOrAdd(cacheKey, x => MutateStyle(x.origin, x.property, x.value));
}
private static TextStyle MutateStyle(TextStyle origin, TextStyleProperty property, object value, bool overrideValue = true)
private static TextStyle MutateStyle(TextStyle origin, TextStyleProperty property, object? value, bool overrideValue = true)
{
if (overrideValue && value == null)
return origin;
@@ -177,38 +179,69 @@ namespace QuestPDF.Infrastructure
return origin with { WrapAnywhere = castedValue };
}
if (property == TextStyleProperty.Fallback)
{
if (!overrideValue && origin.Fallback != null)
return origin;
var castedValue = (TextStyle?)value;
if (origin.Fallback == castedValue)
return origin;
return origin with { Fallback = castedValue };
}
throw new ArgumentOutOfRangeException(nameof(property), property, "Expected to mutate the TextStyle object. Provided property type is not supported.");
}
internal static TextStyle ApplyGlobalStyle(this TextStyle style, TextStyle parent)
{
var cacheKey = (style, parent, false);
return TextStyleApplyCache.GetOrAdd(cacheKey, key => ApplyStyle(key.origin, key.parent, key.overrideValue));
var cacheKey = (style, parent);
return TextStyleApplyGlobalCache.GetOrAdd(cacheKey, key => ApplyStyle(key.origin, key.parent, overrideStyle: false).ApplyFontFallback());
}
private static TextStyle ApplyFontFallback(this TextStyle style)
{
var targetFallbackStyle = style
?.Fallback
?.ApplyStyle(style, overrideStyle: false, applyFallback: false)
?.ApplyFontFallback();
return MutateStyle(style, TextStyleProperty.Fallback, targetFallbackStyle);
}
internal static TextStyle OverrideStyle(this TextStyle style, TextStyle parent)
{
var cacheKey = (style, parent, true);
return TextStyleApplyCache.GetOrAdd(cacheKey, key => ApplyStyle(key.origin, key.parent, key.overrideValue));
var cacheKey = (style, parent);
return TextStyleOverrideCache.GetOrAdd(cacheKey, key =>
{
var result = ApplyStyle(key.origin, key.parent);
return MutateStyle(result, TextStyleProperty.Fallback, key.parent.Fallback);
});
}
private static TextStyle ApplyStyle(TextStyle style, TextStyle parent, bool overrideValue)
private static TextStyle ApplyStyle(this TextStyle style, TextStyle parent, bool overrideStyle = true, bool applyFallback = true)
{
var result = style;
result = MutateStyle(result, TextStyleProperty.Color, parent.Color, overrideValue);
result = MutateStyle(result, TextStyleProperty.BackgroundColor, parent.BackgroundColor, overrideValue);
result = MutateStyle(result, TextStyleProperty.FontFamily, parent.FontFamily, overrideValue);
result = MutateStyle(result, TextStyleProperty.Size, parent.Size, overrideValue);
result = MutateStyle(result, TextStyleProperty.LineHeight, parent.LineHeight, overrideValue);
result = MutateStyle(result, TextStyleProperty.FontWeight, parent.FontWeight, overrideValue);
result = MutateStyle(result, TextStyleProperty.FontPosition, parent.FontPosition, overrideValue);
result = MutateStyle(result, TextStyleProperty.IsItalic, parent.IsItalic, overrideValue);
result = MutateStyle(result, TextStyleProperty.HasStrikethrough, parent.HasStrikethrough, overrideValue);
result = MutateStyle(result, TextStyleProperty.HasUnderline, parent.HasUnderline, overrideValue);
result = MutateStyle(result, TextStyleProperty.WrapAnywhere, parent.WrapAnywhere, overrideValue);
result = MutateStyle(result, TextStyleProperty.Color, parent.Color, overrideStyle);
result = MutateStyle(result, TextStyleProperty.BackgroundColor, parent.BackgroundColor, overrideStyle);
result = MutateStyle(result, TextStyleProperty.FontFamily, parent.FontFamily, overrideStyle);
result = MutateStyle(result, TextStyleProperty.Size, parent.Size, overrideStyle);
result = MutateStyle(result, TextStyleProperty.LineHeight, parent.LineHeight, overrideStyle);
result = MutateStyle(result, TextStyleProperty.FontWeight, parent.FontWeight, overrideStyle);
result = MutateStyle(result, TextStyleProperty.FontPosition, parent.FontPosition, overrideStyle);
result = MutateStyle(result, TextStyleProperty.IsItalic, parent.IsItalic, overrideStyle);
result = MutateStyle(result, TextStyleProperty.HasStrikethrough, parent.HasStrikethrough, overrideStyle);
result = MutateStyle(result, TextStyleProperty.HasUnderline, parent.HasUnderline, overrideStyle);
result = MutateStyle(result, TextStyleProperty.WrapAnywhere, parent.WrapAnywhere, overrideStyle);
if (applyFallback)
result = MutateStyle(result, TextStyleProperty.Fallback, parent.Fallback, overrideStyle);
return result;
}
}