From 683ab362d8a4a6aa456646c921645715c5d264ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zi=C4=85bek?= Date: Sun, 29 Aug 2021 20:14:48 +0200 Subject: [PATCH] Added support for registering font types based on the suggestion of brendonparker --- QuestPDF.Examples/BarCode.cs | 32 ++++++++++++++++++ QuestPDF.Examples/LibreBarcode39-Regular.ttf | Bin 0 -> 14776 bytes QuestPDF.Examples/QuestPDF.Examples.csproj | 6 ++++ .../{CanvasCache.cs => FontManager.cs} | 27 ++++++++++++--- 4 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 QuestPDF.Examples/BarCode.cs create mode 100644 QuestPDF.Examples/LibreBarcode39-Regular.ttf rename QuestPDF/Drawing/{CanvasCache.cs => FontManager.cs} (69%) diff --git a/QuestPDF.Examples/BarCode.cs b/QuestPDF.Examples/BarCode.cs new file mode 100644 index 0000000..dd83261 --- /dev/null +++ b/QuestPDF.Examples/BarCode.cs @@ -0,0 +1,32 @@ +using System.IO; +using NUnit.Framework; +using QuestPDF.Drawing; +using QuestPDF.Examples.Engine; +using QuestPDF.Fluent; +using QuestPDF.Helpers; +using QuestPDF.Infrastructure; + +namespace QuestPDF.Examples +{ + public class BarCode + { + [Test] + public void Example() + { + FontManager.RegisterFontType("LibreBarcode39", File.OpenRead("LibreBarcode39-Regular.ttf")); + + RenderingTest + .Create() + .PageSize(400, 100) + .FileName() + .Render(container => + { + container + .Background(Colors.White) + .AlignCenter() + .AlignMiddle() + .Text("*QuestPDF*", TextStyle.Default.FontType("LibreBarcode39").Size(64)); + }); + } + } +} \ No newline at end of file diff --git a/QuestPDF.Examples/LibreBarcode39-Regular.ttf b/QuestPDF.Examples/LibreBarcode39-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5fcfc55a2f03742e261096304f137e03f4fdb252 GIT binary patch literal 14776 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 + + + PreserveNewest + + + diff --git a/QuestPDF/Drawing/CanvasCache.cs b/QuestPDF/Drawing/FontManager.cs similarity index 69% rename from QuestPDF/Drawing/CanvasCache.cs rename to QuestPDF/Drawing/FontManager.cs index 9037309..4bdace2 100644 --- a/QuestPDF/Drawing/CanvasCache.cs +++ b/QuestPDF/Drawing/FontManager.cs @@ -1,15 +1,23 @@ -using System.Collections.Concurrent; +using System; +using System.Collections.Concurrent; +using System.IO; using QuestPDF.Drawing.SpacePlan; using QuestPDF.Infrastructure; using SkiaSharp; namespace QuestPDF.Drawing { - internal static class CanvasCache + public static class FontManager { + private static ConcurrentDictionary Typefaces = new ConcurrentDictionary(); private static ConcurrentDictionary Paints = new ConcurrentDictionary(); private static ConcurrentDictionary ColorPaint = new ConcurrentDictionary(); + public static void RegisterFontType(string fontName, Stream stream) + { + Typefaces.TryAdd(fontName, SKTypeface.FromStream(stream)); + } + internal static SKPaint ColorToPaint(this string color) { return ColorPaint.GetOrAdd(color, Convert); @@ -29,12 +37,10 @@ namespace QuestPDF.Drawing static SKPaint Convert(TextStyle style) { - var slant = style.IsItalic ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright; - return new SKPaint { Color = SKColor.Parse(style.Color), - Typeface = SKTypeface.FromFamilyName(style.FontType, (int)style.FontWeight, (int)SKFontStyleWidth.Normal, slant), + Typeface = GetTypeface(style), TextSize = style.Size, TextEncoding = SKTextEncoding.Utf32, @@ -47,6 +53,17 @@ namespace QuestPDF.Drawing } }; } + + static SKTypeface GetTypeface(TextStyle style) + { + if (Typefaces.TryGetValue(style.FontType, out var result)) + return result; + + var slant = style.IsItalic ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright; + + return SKTypeface.FromFamilyName(style.FontType, (int)style.FontWeight, (int)SKFontStyleWidth.Normal, slant) + ?? throw new ArgumentException($"The typeface {style.FontType} could not be found."); + } } internal static TextMeasurement BreakText(this TextStyle style, string text, float availableWidth)