52 lines
3.8 KiB
C#
52 lines
3.8 KiB
C#
using System.Reflection;
|
|
using System.Text;
|
|
|
|
namespace JobTrackerApi.Services;
|
|
|
|
// Self-contained document fonts keep local-file PDF export and srcDoc preview on the same metrics.
|
|
internal static class CvDocumentFonts
|
|
{
|
|
private static readonly Dictionary<string, string> Styles = new()
|
|
{
|
|
["Selawik"] = Faces("selawik", ("selawk.ttf", "400", "normal"), ("selawksb.ttf", "600", "normal"), ("selawkb.ttf", "700", "normal")),
|
|
["Arimo"] = Faces("arimo", ("Arimo-Regular.ttf", "400", "normal"), ("Arimo-Italic.ttf", "400", "italic"), ("Arimo-Bold.ttf", "700", "normal"), ("Arimo-BoldItalic.ttf", "700", "italic")),
|
|
["Gelasio"] = Faces("gelasio", ("Gelasio-Regular.ttf", "400", "normal"), ("Gelasio-Italic.ttf", "400", "italic"), ("Gelasio-SemiBold.ttf", "600", "normal"), ("Gelasio-SemiBoldItalic.ttf", "600", "italic"), ("Gelasio-Bold.ttf", "700", "normal"), ("Gelasio-BoldItalic.ttf", "700", "italic")),
|
|
["Roboto"] = Faces("roboto", ("Roboto-Regular.ttf", "400", "normal"), ("Roboto-Italic.ttf", "400", "italic"), ("Roboto-Medium.ttf", "500", "normal"), ("Roboto-MediumItalic.ttf", "500", "italic"), ("Roboto-Bold.ttf", "700", "normal"), ("Roboto-BoldItalic.ttf", "700", "italic")),
|
|
["Poppins"] = Faces("poppins", ("Poppins-Regular.ttf", "400", "normal"), ("Poppins-Italic.ttf", "400", "italic"), ("Poppins-SemiBold.ttf", "600", "normal"), ("Poppins-SemiBoldItalic.ttf", "600", "italic"), ("Poppins-Bold.ttf", "700", "normal"), ("Poppins-BoldItalic.ttf", "700", "italic")),
|
|
["Roboto Mono"] = Faces("robotomono", ("RobotoMono-Regular.ttf", "400", "normal"), ("RobotoMono-Italic.ttf", "400", "italic"), ("RobotoMono-Medium.ttf", "500", "normal"), ("RobotoMono-MediumItalic.ttf", "500", "italic"), ("RobotoMono-Bold.ttf", "700", "normal"), ("RobotoMono-BoldItalic.ttf", "700", "italic")),
|
|
};
|
|
|
|
internal static string Family(string stack) => stack.TrimStart() switch
|
|
{
|
|
var s when s.StartsWith("Georgia", StringComparison.Ordinal) => "Gelasio",
|
|
var s when s.StartsWith("'Roboto Mono'", StringComparison.Ordinal) || s.StartsWith("Consolas", StringComparison.Ordinal) => "Roboto Mono",
|
|
var s when s.StartsWith("'Roboto'", StringComparison.Ordinal) => "Roboto",
|
|
var s when s.StartsWith("'Poppins'", StringComparison.Ordinal) => "Poppins",
|
|
var s when s.StartsWith("'Segoe UI'", StringComparison.Ordinal) => "Selawik",
|
|
_ => "Arimo",
|
|
};
|
|
|
|
internal static string Stack(string original) => $"'{Family(original)}', {original}";
|
|
|
|
internal static string Embed(params string[] stacks) => string.Concat(stacks.Select(Family).Distinct().Select(family => Styles[family]));
|
|
|
|
private static string Faces(string family, params (string File, string Weight, string Style)[] faces)
|
|
{
|
|
var names = new Dictionary<string, string> { ["selawik"] = "Selawik", ["arimo"] = "Arimo", ["gelasio"] = "Gelasio", ["roboto"] = "Roboto", ["poppins"] = "Poppins", ["robotomono"] = "Roboto Mono" };
|
|
var css = new StringBuilder();
|
|
using var license = new StreamReader(Resource(family + ".OFL.txt"));
|
|
css.Append("/*\n").Append(license.ReadToEnd()).Append("\n*/\n");
|
|
foreach (var face in faces)
|
|
{
|
|
using var stream = Resource(face.File);
|
|
using var bytes = new MemoryStream();
|
|
stream.CopyTo(bytes);
|
|
css.Append($"@font-face{{font-family:'{names[family]}';font-style:{face.Style};font-weight:{face.Weight};font-display:block;src:url(data:font/ttf;base64,{Convert.ToBase64String(bytes.ToArray())}) format('truetype');}}\n");
|
|
}
|
|
return css.ToString();
|
|
}
|
|
|
|
private static Stream Resource(string name) => typeof(CvDocumentFonts).Assembly.GetManifestResourceStream("CvFonts." + name)
|
|
?? throw new InvalidOperationException("Required document font resource is missing: " + name);
|
|
}
|