From 7aa0dcc03ea20b544b2463d97fe4a78af699589c Mon Sep 17 00:00:00 2001 From: Ben Hansell Date: Mon, 18 Oct 2021 17:02:46 +0000 Subject: [PATCH] lib/common: add character width lookup tables for more fonts and variants This allows Graphviz to estimate the widths of text spans more accurately when built without a textlayout plugin. The textlayout plugins are platform-specific and can be difficult to build for obscure platforms (e.g. Graphviz Online), resulting in node labels not fitting within their nodes nicely. lib/common: add new source file and header lib/common: don't install new header lib/common: redesign hard-coded font metrics lib/common: remove unused variables lib/common: format new source file with clang-format lib/common: add more fonts lib/common: add warning spam guards lib/common: improve code style and comments lib/common: improve code style and comments lib/common: fix const compiler error lib/common: reuse existing isalpha_no_locale function lib/common: fix another const compilation error lib/common: fix yet another const compilation error update changelog update changelog --- CHANGELOG.md | 5 + lib/common/CMakeLists.txt | 2 + lib/common/Makefile.am | 4 +- lib/common/textspan.c | 134 +----- lib/common/textspan_lut.c | 833 ++++++++++++++++++++++++++++++++++++++ lib/common/textspan_lut.h | 10 + lib/gvc.vcxproj | 2 + lib/gvc.vcxproj.filters | 6 + 8 files changed, 868 insertions(+), 128 deletions(-) create mode 100644 lib/common/textspan_lut.c create mode 100644 lib/common/textspan_lut.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b1aba029..02e6b55d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased (2.49.4)] +### Added + +- hard-coded lookup tables for fallback font metrics for more fonts and font + variants + ## [2.49.3] – 2021-10-22 ### Fixed diff --git a/lib/common/CMakeLists.txt b/lib/common/CMakeLists.txt index d153c7fb4..b858ededa 100644 --- a/lib/common/CMakeLists.txt +++ b/lib/common/CMakeLists.txt @@ -58,6 +58,7 @@ add_library(common_obj OBJECT ps_font_equiv.h render.h textspan.h + textspan_lut.h types.h usershape.h utils.h @@ -86,6 +87,7 @@ add_library(common_obj OBJECT splines.c taper.c textspan.c + textspan_lut.c timing.c utils.c xml.c diff --git a/lib/common/Makefile.am b/lib/common/Makefile.am index 34b9b1ab0..16d81e876 100644 --- a/lib/common/Makefile.am +++ b/lib/common/Makefile.am @@ -21,10 +21,10 @@ pkginclude_HEADERS = arith.h geom.h color.h types.h textspan.h usershape.h noinst_HEADERS = render.h utils.h memory.h \ geomprocs.h colorprocs.h colortbl.h entities.h globals.h \ logic.h const.h macros.h htmllex.h htmltable.h pointset.h intset.h \ - timing.h ps_font_equiv.h + textspan_lut.h timing.h ps_font_equiv.h noinst_LTLIBRARIES = libcommon_C.la -libcommon_C_la_SOURCES = arrows.c colxlate.c ellipse.c textspan.c \ +libcommon_C_la_SOURCES = arrows.c colxlate.c ellipse.c textspan.c textspan_lut.c \ args.c memory.c globals.c htmllex.c htmlparse.y htmltable.c input.c \ pointset.c intset.c postproc.c routespl.c splines.c psusershape.c \ timing.c labels.c ns.c shapes.c utils.c geom.c taper.c \ diff --git a/lib/common/textspan.c b/lib/common/textspan.c index 2cc1c6b9e..46c77252f 100644 --- a/lib/common/textspan.c +++ b/lib/common/textspan.c @@ -13,121 +13,21 @@ #include #include #include +#include #include -static double timesFontWidth[] = { - 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */ - 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */ - 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */ - 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */ - 0.2500, 0.3329, 0.4079, 0.5000, 0.5000, 0.8329, 0.7779, 0.3329, /* !"#$%&' */ - 0.3329, 0.3329, 0.5000, 0.5639, 0.2500, 0.3329, 0.2500, 0.2779, /* ()*+,-./ */ - 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, /* 01234567 */ - 0.5000, 0.5000, 0.2779, 0.2779, 0.5639, 0.5639, 0.5639, 0.4439, /* 89:;<=>? */ - 0.9209, 0.7219, 0.6669, 0.6669, 0.7219, 0.6109, 0.5559, 0.7219, /* @ABCDEFG */ - 0.7219, 0.3329, 0.3889, 0.7219, 0.6109, 0.8889, 0.7219, 0.7219, /* HIJKLMNO */ - 0.5559, 0.7219, 0.6669, 0.5559, 0.6109, 0.7219, 0.7219, 0.9439, /* PQRSTUVW */ - 0.7219, 0.7219, 0.6109, 0.3329, 0.2779, 0.3329, 0.4689, 0.5000, /* XYZ[\]^_ */ - 0.3329, 0.4439, 0.5000, 0.4439, 0.5000, 0.4439, 0.3329, 0.5000, /* `abcdefg */ - 0.5000, 0.2779, 0.2779, 0.5000, 0.2779, 0.7779, 0.5000, 0.5000, /* hijklmno */ - 0.5000, 0.5000, 0.3329, 0.3889, 0.2779, 0.5000, 0.5000, 0.7219, /* pqrstuvw */ - 0.5000, 0.5000, 0.4439, 0.4799, 0.1999, 0.4799, 0.5409, 0.2500, /* xyz{|}~ */ - 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */ - 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */ - 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */ - 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */ - 0.2500, 0.3329, 0.5000, 0.5000, 0.1669, 0.5000, 0.5000, 0.5000, /* ¡¢£¤¥¦§ */ - 0.5000, 0.1799, 0.4439, 0.5000, 0.3329, 0.3329, 0.5559, 0.5559, /* ¨©ª«¬­®¯ */ - 0.2500, 0.5000, 0.5000, 0.5000, 0.2500, 0.2500, 0.4529, 0.3499, /* ±²³´ ¶· */ - 0.3329, 0.4439, 0.4439, 0.5000, 1.0000, 1.0000, 0.2500, 0.4439, /* ¸¹º»¼½ ¿ */ - 0.2500, 0.3329, 0.3329, 0.3329, 0.3329, 0.3329, 0.3329, 0.3329, /* ÁÂÃÄÅÆÇ */ - 0.3329, 0.2500, 0.3329, 0.3329, 0.2500, 0.3329, 0.3329, 0.3329, /* È ÊË ÍÎÏ */ - 1.0000, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* Ð */ - 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, 0.2500, /* */ - 0.2500, 0.8889, 0.2500, 0.2759, 0.2500, 0.2500, 0.2500, 0.2500, /* á ã */ - 0.6109, 0.7219, 0.8889, 0.3099, 0.2500, 0.2500, 0.2500, 0.2500, /* èéêë */ - 0.2500, 0.6669, 0.2500, 0.2500, 0.2500, 0.2779, 0.2500, 0.2500, /* ñ õ */ - 0.2779, 0.5000, 0.7219, 0.5000, 0.2500, 0.2500, 0.2500, 0.2500, /* øùúû */ -}; -static double arialFontWidth[] = { - 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */ - 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */ - 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */ - 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */ - 0.2779, 0.2779, 0.3549, 0.5559, 0.5559, 0.8889, 0.6669, 0.2209, /* !"#$%&' */ - 0.3329, 0.3329, 0.3889, 0.5839, 0.2779, 0.3329, 0.2779, 0.2779, /* ()*+,-./ */ - 0.5559, 0.5559, 0.5559, 0.5559, 0.5559, 0.5559, 0.5559, 0.5559, /* 01234567 */ - 0.5559, 0.5559, 0.2779, 0.2779, 0.5839, 0.5839, 0.5839, 0.5559, /* 89:;<=>? */ - 1.0149, 0.6669, 0.6669, 0.7219, 0.7219, 0.6669, 0.6109, 0.7779, /* @ABCDEFG */ - 0.7219, 0.2779, 0.5000, 0.6669, 0.5559, 0.8329, 0.7219, 0.7779, /* HIJKLMNO */ - 0.6669, 0.7779, 0.7219, 0.6669, 0.6109, 0.7219, 0.6669, 0.9439, /* PQRSTUVW */ - 0.6669, 0.6669, 0.6109, 0.2779, 0.2779, 0.2779, 0.4689, 0.5559, /* XYZ[\]^_ */ - 0.2219, 0.5559, 0.5559, 0.5000, 0.5559, 0.5559, 0.2779, 0.5559, /* `abcdefg */ - 0.5559, 0.2219, 0.2219, 0.5000, 0.2219, 0.8329, 0.5559, 0.5559, /* hijklmno */ - 0.5559, 0.5559, 0.3329, 0.5000, 0.2779, 0.5559, 0.5000, 0.7219, /* pqrstuvw */ - 0.5000, 0.5000, 0.5000, 0.3339, 0.2599, 0.3339, 0.5839, 0.2779, /* xyz{|}~ */ - 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */ - 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */ - 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */ - 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */ - 0.2779, 0.3329, 0.5559, 0.5559, 0.1669, 0.5559, 0.5559, 0.5559, /* ¡¢£¤¥¦§ */ - 0.5559, 0.1909, 0.3329, 0.5559, 0.3329, 0.3329, 0.5000, 0.5000, /* ¨©ª«¬­®¯ */ - 0.2779, 0.5559, 0.5559, 0.5559, 0.2779, 0.2779, 0.5369, 0.3499, /* ±²³´ ¶· */ - 0.2219, 0.3329, 0.3329, 0.5559, 1.0000, 1.0000, 0.2779, 0.6109, /* ¸¹º»¼½ ¿ */ - 0.2779, 0.3329, 0.3329, 0.3329, 0.3329, 0.3329, 0.3329, 0.3329, /* ÁÂÃÄÅÆÇ */ - 0.3329, 0.2779, 0.3329, 0.3329, 0.2779, 0.3329, 0.3329, 0.3329, /* È ÊË ÍÎÏ */ - 1.0000, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* Ð */ - 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* */ - 0.2779, 1.0000, 0.2779, 0.3699, 0.2779, 0.2779, 0.2779, 0.2779, /* á ã */ - 0.5559, 0.7779, 1.0000, 0.3649, 0.2779, 0.2779, 0.2779, 0.2779, /* èéêë */ - 0.2779, 0.8889, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, 0.2779, /* ñ õ */ - 0.2219, 0.6109, 0.9439, 0.6109, 0.2779, 0.2779, 0.2779, 0.2779, /* øùúû */ -}; -static double courFontWidth[] = { - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* !"#$%&' */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ()*+,-./ */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* 01234567 */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* 89:;<=>? */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* @ABCDEFG */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* HIJKLMNO */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* PQRSTUVW */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* XYZ[\]^_ */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* `abcdefg */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* hijklmno */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* pqrstuvw */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* xyz{|}~ */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ¡¢£¤¥¦§ */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ¨©ª«¬­®¯ */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ±²³´ ¶· */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ¸¹º»¼½ ¿ */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ÁÂÃÄÅÆÇ */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* È ÊË ÍÎÏ */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* Ð */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* á ã */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* èéêë */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* ñ õ */ - 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, 0.5999, /* øùúû */ -}; - /* estimate_textspan_size: * Estimate size of textspan, for given face and size, in points. */ static void estimate_textspan_size(textspan_t * span, char **fontpath) { - double *Fontwidth, fontsize; - char c, *p, *fpp, *fontname; + double fontsize; + + int flags = span->font->flags; + bool bold = (flags & HTML_BF) != 0; + bool italic = (flags & HTML_IF) != 0; - fontname = span->font->name; fontsize = span->font->size; span->size.x = 0.0; @@ -136,28 +36,10 @@ estimate_textspan_size(textspan_t * span, char **fontpath) span->yoffset_centerline = 0.1 * fontsize; span->layout = NULL; span->free_layout = NULL; + span->size.x = fontsize * estimate_text_width_1pt(span->font->name, span->str, bold, italic); - if (!strncasecmp(fontname, "cour", 4)) { - fpp = "[internal courier]"; - Fontwidth = courFontWidth; - } else if (!strncasecmp(fontname, "arial", 5) - || !strncasecmp(fontname, "helvetica", 9)) { - fpp = "[internal arial]"; - Fontwidth = arialFontWidth; - } else { - fpp = "[internal times]"; - Fontwidth = timesFontWidth; - } if (fontpath) - *fontpath = fpp; - if ((p = span->str)) { - while ((c = *p++)) - span->size.x += Fontwidth[(unsigned char) c]; - /* NOTE: Tables are based on a font of size 1. Need to multiply by - * fontsize to get appropriate value. - */ - span->size.x *= fontsize; - } + *fontpath = "[internal hard-coded]"; } /* diff --git a/lib/common/textspan_lut.c b/lib/common/textspan_lut.c new file mode 100644 index 000000000..dea7690d8 --- /dev/null +++ b/lib/common/textspan_lut.c @@ -0,0 +1,833 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Currently we just store the width of every ASCII character, which seems to +// produce good enough results. We could also store kerning metrics and line +// heights for each font if we want to be more thorough. +struct FontFamilyMetrics { + // A pipe-separated, case-insensitive list of font family names which these + // metrics correspond to. If multiple font families are listed, they should be + // metrically equivalent. + const char *font_name; + // Widths are stored in (units_per_em * 1) pt. (that is how TrueType works + // internally). A value of -1 indicates that the width for that character is + // unknown. + double units_per_em; + short widths_regular[128]; + short widths_bold[128]; + short widths_italic[128]; + short widths_bold_italic[128]; +}; + +static const struct FontFamilyMetrics all_font_metrics[] = { + // Times_New_Roman.ttf (+ variants) from ttf-mscorefonts-installer. + { + "times|timesroman|timesnewroman|freeserif|liberationserif|nimbusroman|" + "texgyretermes|tinos|thorndale", + 2048, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 512, + 682, 836, 1024, 1024, 1706, 1593, 369, 682, 682, 1024, 1155, + 512, 682, 512, 569, 1024, 1024, 1024, 1024, 1024, 1024, 1024, + 1024, 1024, 1024, 569, 569, 1155, 1155, 1155, 909, 1886, 1479, + 1366, 1366, 1479, 1251, 1139, 1479, 1479, 682, 797, 1479, 1251, + 1821, 1479, 1479, 1139, 1479, 1366, 1139, 1251, 1479, 1479, 1933, + 1479, 1479, 1251, 682, 569, 682, 961, 1024, 682, 909, 1024, + 909, 1024, 909, 682, 1024, 1024, 569, 569, 1024, 569, 1593, + 1024, 1024, 1024, 1024, 682, 797, 569, 1024, 1024, 1479, 1024, + 1024, 909, 983, 410, 983, 1108, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 512, + 682, 1137, 1024, 1024, 2048, 1706, 569, 682, 682, 1024, 1167, + 512, 682, 512, 569, 1024, 1024, 1024, 1024, 1024, 1024, 1024, + 1024, 1024, 1024, 682, 682, 1167, 1167, 1167, 1024, 1905, 1479, + 1366, 1479, 1479, 1366, 1251, 1593, 1593, 797, 1024, 1593, 1366, + 1933, 1479, 1593, 1251, 1593, 1479, 1139, 1366, 1479, 1479, 2048, + 1479, 1479, 1366, 682, 569, 682, 1190, 1024, 682, 1024, 1139, + 909, 1139, 909, 682, 1024, 1139, 569, 682, 1139, 569, 1706, + 1139, 1024, 1139, 1139, 909, 797, 682, 1139, 1024, 1479, 1024, + 1024, 909, 807, 451, 807, 1065, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 512, + 682, 860, 1024, 1024, 1706, 1593, 438, 682, 682, 1024, 1382, + 512, 682, 512, 569, 1024, 1024, 1024, 1024, 1024, 1024, 1024, + 1024, 1024, 1024, 682, 682, 1382, 1382, 1382, 1024, 1884, 1251, + 1251, 1366, 1479, 1251, 1251, 1479, 1479, 682, 909, 1366, 1139, + 1706, 1366, 1479, 1251, 1479, 1251, 1024, 1139, 1479, 1251, 1706, + 1251, 1139, 1139, 797, 569, 797, 864, 1024, 682, 1024, 1024, + 909, 1024, 909, 569, 1024, 1024, 569, 569, 909, 569, 1479, + 1024, 1024, 1024, 1024, 797, 797, 569, 1024, 909, 1366, 909, + 909, 797, 819, 563, 819, 1108, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 512, + 797, 1137, 1024, 1024, 1706, 1593, 569, 682, 682, 1024, 1167, + 512, 682, 512, 569, 1024, 1024, 1024, 1024, 1024, 1024, 1024, + 1024, 1024, 1024, 682, 682, 1167, 1167, 1167, 1024, 1704, 1366, + 1366, 1366, 1479, 1366, 1366, 1479, 1593, 797, 1024, 1366, 1251, + 1821, 1479, 1479, 1251, 1479, 1366, 1139, 1251, 1479, 1366, 1821, + 1366, 1251, 1251, 682, 569, 682, 1167, 1024, 682, 1024, 1024, + 909, 1024, 909, 682, 1024, 1139, 569, 569, 1024, 569, 1593, + 1139, 1024, 1024, 1024, 797, 797, 569, 1139, 909, 1366, 1024, + 909, 797, 713, 451, 713, 1167, -1, + }, + }, + // Arial.ttf (+ variants) from ttf-mscorefonts-installer. + { + "helvetica|arial|arialmt|freesans|liberationsans|arimo|albany|" + "nimbussans|nimbussansa|texgyreheros|albany|arimo", + 2048, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 569, + 569, 727, 1139, 1139, 1821, 1366, 391, 682, 682, 797, 1196, + 569, 682, 569, 569, 1139, 1139, 1139, 1139, 1139, 1139, 1139, + 1139, 1139, 1139, 569, 569, 1196, 1196, 1196, 1139, 2079, 1366, + 1366, 1479, 1479, 1366, 1251, 1593, 1479, 569, 1024, 1366, 1139, + 1706, 1479, 1593, 1366, 1593, 1479, 1366, 1251, 1479, 1366, 1933, + 1366, 1366, 1251, 569, 569, 569, 961, 1139, 682, 1139, 1139, + 1024, 1139, 1139, 569, 1139, 1139, 455, 455, 1024, 455, 1706, + 1139, 1139, 1139, 1139, 682, 1024, 569, 1139, 1024, 1479, 1024, + 1024, 1024, 684, 532, 684, 1196, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 569, + 682, 971, 1139, 1139, 1821, 1479, 487, 682, 682, 797, 1196, + 569, 682, 569, 569, 1139, 1139, 1139, 1139, 1139, 1139, 1139, + 1139, 1139, 1139, 682, 682, 1196, 1196, 1196, 1251, 1997, 1479, + 1479, 1479, 1479, 1366, 1251, 1593, 1479, 569, 1139, 1479, 1251, + 1706, 1479, 1593, 1366, 1593, 1479, 1366, 1251, 1479, 1366, 1933, + 1366, 1366, 1251, 682, 569, 682, 1196, 1139, 682, 1139, 1251, + 1139, 1251, 1139, 682, 1251, 1251, 569, 569, 1139, 569, 1821, + 1251, 1251, 1251, 1251, 797, 1139, 682, 1251, 1139, 1593, 1139, + 1139, 1024, 797, 573, 797, 1196, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 569, + 569, 727, 1139, 1139, 1821, 1366, 391, 682, 682, 797, 1196, + 569, 682, 569, 569, 1139, 1139, 1139, 1139, 1139, 1139, 1139, + 1139, 1139, 1139, 569, 569, 1196, 1196, 1196, 1139, 2079, 1366, + 1366, 1479, 1479, 1366, 1251, 1593, 1479, 569, 1024, 1366, 1139, + 1706, 1479, 1593, 1366, 1593, 1479, 1366, 1251, 1479, 1366, 1933, + 1366, 1366, 1251, 569, 569, 569, 961, 1139, 682, 1139, 1139, + 1024, 1139, 1139, 569, 1139, 1139, 455, 455, 1024, 455, 1706, + 1139, 1139, 1139, 1139, 682, 1024, 569, 1139, 1024, 1479, 1024, + 1024, 1024, 684, 532, 684, 1196, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 569, + 682, 971, 1139, 1139, 1821, 1479, 487, 682, 682, 797, 1196, + 569, 682, 569, 569, 1139, 1139, 1139, 1139, 1139, 1139, 1139, + 1139, 1139, 1139, 682, 682, 1196, 1196, 1196, 1251, 1997, 1479, + 1479, 1479, 1479, 1366, 1251, 1593, 1479, 569, 1139, 1479, 1251, + 1706, 1479, 1593, 1366, 1593, 1479, 1366, 1251, 1479, 1366, 1933, + 1366, 1366, 1251, 682, 569, 682, 1196, 1139, 682, 1139, 1251, + 1139, 1251, 1139, 682, 1251, 1251, 569, 569, 1139, 569, 1821, + 1251, 1251, 1251, 1251, 797, 1139, 682, 1251, 1139, 1593, 1139, + 1139, 1024, 797, 573, 797, 1196, -1, + }, + }, + // Courier_New.ttf (+ variants) from ttf-mscorefonts-installer. + { + "cour|courier|couriernew|nimbusmono|texgyrecursor|freemono|" + "liberationmono|cousine|cumberland", + 2048, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, -1, + }, + }, + // https://fonts.google.com/specimen/Nunito + { + "Nunito", + 1000, + { + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 258, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 258, 228, 392, 600, 600, 930, 693, + 221, 317, 317, 450, 600, 228, 424, 228, 283, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 228, 228, 600, 600, 600, 443, 946, + 729, 676, 673, 742, 583, 548, 726, 761, 257, 324, 625, 543, 855, + 740, 767, 633, 767, 669, 615, 602, 728, 689, 1101, 650, 596, 589, + 315, 283, 315, 600, 500, 500, 530, 583, 463, 583, 532, 333, 586, + 568, 232, 236, 500, 296, 856, 568, 556, 583, 583, 358, 481, 350, + 561, 515, 841, 525, 514, 463, 352, 265, 352, 600, -1, + }, + { + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 271, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 271, 248, 448, 600, 600, 945, 726, + 243, 358, 358, 453, 600, 248, 434, 248, 313, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 248, 248, 600, 600, 600, 459, 950, + 744, 688, 680, 762, 597, 562, 736, 773, 282, 354, 665, 562, 868, + 748, 785, 652, 785, 686, 631, 621, 738, 713, 1113, 672, 618, 605, + 354, 313, 354, 600, 500, 500, 547, 600, 472, 600, 542, 364, 604, + 585, 255, 259, 536, 319, 877, 585, 576, 600, 600, 392, 488, 384, + 579, 527, 853, 546, 526, 474, 391, 288, 391, 600, -1, + }, + { + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 258, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 258, 228, 392, 600, 600, 930, 693, + 221, 317, 317, 450, 600, 228, 424, 228, 283, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 228, 228, 600, 600, 600, 443, 946, + 729, 676, 673, 742, 583, 548, 726, 761, 257, 324, 625, 543, 856, + 739, 767, 633, 767, 669, 615, 602, 728, 688, 1101, 650, 596, 589, + 315, 283, 315, 600, 500, 500, 530, 583, 463, 583, 532, 333, 586, + 568, 232, 236, 500, 296, 856, 568, 556, 583, 583, 358, 481, 350, + 561, 515, 841, 525, 514, 463, 352, 265, 352, 600, -1, + }, + { + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 271, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 271, 248, 448, 600, 600, 945, 726, + 243, 358, 358, 453, 600, 248, 434, 248, 313, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 248, 248, 600, 600, 600, 459, 950, + 744, 688, 680, 762, 597, 562, 736, 773, 282, 354, 664, 562, 869, + 747, 785, 652, 785, 686, 631, 621, 738, 713, 1113, 672, 618, 605, + 354, 313, 354, 600, 500, 500, 547, 600, 472, 600, 542, 364, 604, + 585, 255, 259, 536, 319, 877, 585, 576, 600, 600, 392, 488, 384, + 579, 527, 853, 546, 526, 474, 391, 288, 391, 600, -1, + }, + }, + // Based on DejaVuSans, DejaVuSans-Bold, DejaVuSans-Oblique and + // DejaVuSans-BoldOblique (as opposed to italic) + { + "dejavusans", + 2048, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 651, + 821, 942, 1716, 1303, 1946, 1597, 563, 799, 799, 1024, 1716, + 651, 739, 651, 690, 1303, 1303, 1303, 1303, 1303, 1303, 1303, + 1303, 1303, 1303, 690, 690, 1716, 1716, 1716, 1087, 2048, 1401, + 1405, 1430, 1577, 1294, 1178, 1587, 1540, 604, 604, 1343, 1141, + 1767, 1532, 1612, 1235, 1612, 1423, 1300, 1251, 1499, 1401, 2025, + 1403, 1251, 1403, 799, 690, 799, 1716, 1024, 1024, 1255, 1300, + 1126, 1300, 1260, 721, 1300, 1298, 569, 569, 1186, 569, 1995, + 1298, 1253, 1300, 1300, 842, 1067, 803, 1298, 1212, 1675, 1212, + 1212, 1075, 1303, 690, 1303, 1716, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 713, + 934, 1067, 1716, 1425, 2052, 1786, 627, 936, 936, 1071, 1716, + 778, 850, 778, 748, 1425, 1425, 1425, 1425, 1425, 1425, 1425, + 1425, 1425, 1425, 819, 819, 1716, 1716, 1716, 1188, 2048, 1585, + 1561, 1503, 1700, 1399, 1399, 1681, 1714, 762, 762, 1587, 1305, + 2038, 1714, 1741, 1501, 1741, 1577, 1475, 1397, 1663, 1585, 2259, + 1579, 1483, 1485, 936, 748, 936, 1716, 1024, 1024, 1382, 1466, + 1214, 1466, 1389, 891, 1466, 1458, 702, 702, 1362, 702, 2134, + 1458, 1407, 1466, 1466, 1010, 1219, 979, 1458, 1335, 1892, 1321, + 1335, 1192, 1458, 748, 1458, 1716, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 651, + 821, 942, 1716, 1303, 1946, 1597, 563, 799, 799, 1024, 1716, + 651, 739, 651, 690, 1303, 1303, 1303, 1303, 1303, 1303, 1303, + 1303, 1303, 1303, 690, 690, 1716, 1716, 1716, 1087, 2048, 1401, + 1405, 1430, 1577, 1294, 1178, 1587, 1540, 604, 604, 1343, 1141, + 1767, 1532, 1612, 1235, 1612, 1423, 1300, 1251, 1499, 1401, 2025, + 1403, 1251, 1403, 799, 690, 799, 1716, 1024, 1024, 1255, 1300, + 1126, 1300, 1260, 721, 1300, 1298, 569, 569, 1186, 569, 1995, + 1298, 1253, 1300, 1300, 842, 1067, 803, 1298, 1212, 1675, 1212, + 1212, 1075, 1303, 690, 1303, 1716, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 713, + 934, 1067, 1425, 1425, 2052, 1786, 627, 936, 936, 1071, 1716, + 778, 850, 778, 748, 1425, 1425, 1425, 1425, 1425, 1425, 1425, + 1425, 1425, 1425, 819, 819, 1716, 1716, 1716, 1188, 2048, 1585, + 1561, 1503, 1700, 1399, 1399, 1681, 1714, 762, 762, 1587, 1305, + 2038, 1714, 1741, 1501, 1741, 1577, 1475, 1397, 1663, 1585, 2259, + 1579, 1483, 1485, 936, 748, 936, 1716, 1024, 1024, 1382, 1466, + 1214, 1466, 1389, 891, 1466, 1458, 702, 702, 1362, 702, 2134, + 1458, 1407, 1466, 1466, 1010, 1219, 979, 1458, 1335, 1892, 1321, + 1335, 1192, 1458, 748, 1458, 1716, -1, + }, + }, + { + "consola|consolas", + 2048, + { + 1126, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, -1, + }, + { + 1126, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, -1, + }, + { + 1126, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, -1, + }, + }, + { + "Trebuchet MS|Trebuchet", + 2048, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 617, + 752, 665, 1074, 1074, 1229, 1446, 327, 752, 752, 752, 1074, + 752, 752, 752, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, + 1074, 1074, 1074, 752, 752, 1074, 1074, 1074, 752, 1578, 1208, + 1159, 1225, 1256, 1097, 1075, 1385, 1340, 570, 976, 1179, 1037, + 1453, 1307, 1380, 1142, 1384, 1192, 985, 1189, 1328, 1203, 1745, + 1140, 1168, 1127, 752, 728, 752, 1074, 1074, 1074, 1076, 1141, + 1014, 1141, 1117, 757, 1028, 1119, 584, 751, 1033, 604, 1700, + 1119, 1099, 1141, 1141, 796, 829, 812, 1119, 1003, 1524, 1026, + 1010, 972, 752, 1074, 752, 1074, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 617, + 752, 751, 1200, 1200, 1401, 1446, 470, 752, 752, 885, 1200, + 752, 752, 752, 799, 1200, 1200, 1200, 1200, 1200, 1200, 1200, + 1200, 1200, 1200, 752, 752, 1200, 1200, 1200, 897, 1578, 1297, + 1219, 1253, 1316, 1165, 1195, 1375, 1400, 570, 1091, 1264, 1132, + 1526, 1367, 1440, 1202, 1452, 1251, 1047, 1253, 1388, 1273, 1810, + 1230, 1256, 1147, 823, 728, 823, 1200, 1200, 1200, 1091, 1191, + 1048, 1189, 1177, 757, 1028, 1214, 611, 751, 1122, 604, 1760, + 1209, 1159, 1193, 1196, 875, 882, 812, 1210, 1080, 1605, 1131, + 1093, 1082, 888, 1200, 888, 1200, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 617, + 752, 665, 1074, 985, 1229, 1446, 327, 752, 752, 752, 1074, + 752, 752, 752, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, + 1074, 1074, 1074, 752, 752, 1074, 1074, 1074, 752, 1578, 1251, + 1159, 1225, 1256, 1097, 1075, 1385, 1340, 570, 976, 1179, 1037, + 1559, 1307, 1380, 1113, 1380, 1192, 985, 1189, 1328, 1203, 1745, + 1140, 1168, 1127, 752, 728, 752, 1074, 1074, 1074, 1076, 1141, + 942, 1141, 1100, 822, 1028, 1141, 628, 751, 1033, 656, 1700, + 1119, 1099, 1141, 1141, 853, 829, 860, 1140, 1003, 1524, 1026, + 1010, 972, 752, 1074, 752, 1074, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 617, + 752, 800, 1200, 1200, 1500, 1446, 617, 752, 752, 885, 1200, + 752, 752, 752, 813, 1200, 1200, 1200, 1200, 1200, 1200, 1200, + 1200, 1200, 1200, 752, 752, 1200, 1200, 1200, 813, 1578, 1257, + 1208, 1255, 1295, 1215, 1199, 1385, 1389, 570, 1021, 1331, 1082, + 1610, 1352, 1438, 1195, 1576, 1277, 1027, 1403, 1355, 1399, 1897, + 1345, 1400, 1252, 994, 978, 994, 1200, 1200, 1200, 1214, 1215, + 1009, 1215, 1130, 840, 1096, 1151, 669, 794, 1105, 655, 1700, + 1151, 1167, 1226, 1226, 915, 940, 897, 1141, 1131, 1584, 1179, + 1155, 1091, 994, 1200, 994, 1200, -1, + }, + }, + { + "Verdana", + 2048, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 720, + 806, 940, 1676, 1302, 2204, 1488, 550, 930, 930, 1302, 1676, + 745, 930, 745, 930, 1302, 1302, 1302, 1302, 1302, 1302, 1302, + 1302, 1302, 1302, 930, 930, 1676, 1676, 1676, 1117, 2048, 1400, + 1404, 1430, 1578, 1295, 1177, 1588, 1539, 862, 931, 1419, 1140, + 1726, 1532, 1612, 1235, 1612, 1424, 1400, 1262, 1499, 1400, 2025, + 1403, 1260, 1403, 930, 930, 930, 1676, 1302, 1302, 1230, 1276, + 1067, 1276, 1220, 720, 1276, 1296, 562, 705, 1212, 562, 1992, + 1296, 1243, 1276, 1276, 874, 1067, 807, 1296, 1212, 1676, 1212, + 1212, 1076, 1300, 930, 1300, 1676, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 700, + 824, 1203, 1776, 1456, 2605, 1766, 680, 1113, 1113, 1456, 1776, + 740, 983, 740, 1412, 1456, 1456, 1456, 1456, 1456, 1456, 1456, + 1456, 1456, 1456, 824, 824, 1776, 1776, 1776, 1263, 1974, 1590, + 1560, 1482, 1700, 1399, 1332, 1661, 1715, 1118, 1137, 1579, 1305, + 1941, 1734, 1741, 1501, 1741, 1602, 1455, 1396, 1663, 1564, 2311, + 1564, 1509, 1417, 1113, 1412, 1113, 1776, 1456, 1456, 1368, 1432, + 1205, 1432, 1360, 865, 1432, 1459, 700, 825, 1374, 700, 2167, + 1459, 1406, 1432, 1432, 1018, 1215, 933, 1459, 1331, 2006, 1370, + 1333, 1222, 1456, 1113, 1456, 1776, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 720, + 806, 940, 1676, 1302, 2204, 1488, 550, 930, 930, 1302, 1676, + 745, 930, 745, 930, 1302, 1302, 1302, 1302, 1302, 1302, 1302, + 1302, 1302, 1302, 930, 930, 1676, 1676, 1676, 1117, 2048, 1398, + 1404, 1430, 1568, 1295, 1177, 1588, 1539, 862, 931, 1419, 1140, + 1726, 1532, 1612, 1235, 1612, 1424, 1400, 1262, 1499, 1398, 2028, + 1403, 1260, 1403, 930, 930, 930, 1676, 1302, 1302, 1230, 1276, + 1067, 1276, 1220, 720, 1273, 1296, 562, 705, 1202, 562, 1993, + 1296, 1243, 1276, 1276, 874, 1067, 807, 1296, 1210, 1676, 1212, + 1210, 1076, 1300, 930, 1300, 1676, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 700, + 824, 1203, 1776, 1456, 2605, 1766, 680, 1113, 1113, 1456, 1776, + 740, 983, 740, 1412, 1456, 1456, 1456, 1456, 1456, 1456, 1456, + 1456, 1456, 1456, 824, 824, 1776, 1776, 1776, 1263, 1974, 1590, + 1560, 1482, 1700, 1399, 1332, 1661, 1715, 1118, 1137, 1579, 1305, + 1941, 1734, 1741, 1501, 1741, 1602, 1455, 1396, 1663, 1564, 2311, + 1564, 1509, 1417, 1113, 1412, 1113, 1776, 1456, 1456, 1368, 1432, + 1205, 1432, 1360, 865, 1432, 1459, 700, 825, 1374, 700, 2167, + 1459, 1404, 1432, 1432, 1018, 1215, 933, 1459, 1329, 2006, 1370, + 1333, 1222, 1456, 1113, 1456, 1776, -1, + }, + }, + { + "OpenSans", + 2048, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 532, + 547, 821, 1323, 1171, 1686, 1495, 453, 606, 606, 1130, 1171, + 502, 659, 545, 752, 1171, 1171, 1171, 1171, 1171, 1171, 1171, + 1171, 1171, 1171, 545, 545, 1171, 1171, 1171, 879, 1841, 1296, + 1327, 1292, 1493, 1139, 1057, 1491, 1511, 571, 547, 1257, 1063, + 1849, 1544, 1595, 1233, 1595, 1266, 1124, 1133, 1491, 1219, 1896, + 1182, 1147, 1169, 674, 752, 674, 1110, 918, 1182, 1139, 1255, + 975, 1255, 1149, 694, 1122, 1257, 518, 518, 1075, 518, 1905, + 1257, 1237, 1255, 1255, 836, 977, 723, 1257, 1026, 1593, 1073, + 1032, 958, 776, 1128, 776, 1171, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 532, + 586, 967, 1323, 1169, 1845, 1536, 545, 694, 694, 1116, 1169, + 594, 659, 584, 846, 1169, 1169, 1169, 1169, 1169, 1169, 1169, + 1169, 1169, 1169, 584, 594, 1169, 1169, 1169, 977, 1837, 1413, + 1376, 1305, 1516, 1147, 1124, 1483, 1567, 678, 678, 1360, 1157, + 1931, 1665, 1630, 1286, 1630, 1352, 1128, 1186, 1548, 1331, 1980, + 1366, 1278, 1186, 678, 846, 678, 1090, 842, 1243, 1237, 1296, + 1053, 1296, 1210, 793, 1157, 1346, 625, 625, 1270, 625, 2011, + 1346, 1268, 1296, 1296, 930, 1018, 889, 1346, 1165, 1753, 1184, + 1165, 999, 807, 1128, 807, 1169, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 532, + 530, 791, 1323, 1128, 1624, 1372, 444, 584, 584, 1130, 1128, + 492, 639, 518, 717, 1128, 1128, 1128, 1128, 1128, 1128, 1128, + 1128, 1128, 1128, 518, 518, 1128, 1128, 1128, 874, 1735, 1137, + 1225, 1198, 1364, 1047, 967, 1386, 1389, 559, 547, 1141, 971, + 1714, 1438, 1475, 1159, 1475, 1165, 1028, 1020, 1384, 1122, 1745, + 1063, 1030, 1087, 586, 717, 586, 1059, 807, 1135, 1157, 1182, + 922, 1182, 1010, 641, 1026, 1182, 520, 520, 999, 520, 1786, + 1182, 1149, 1182, 1182, 811, 877, 664, 1182, 946, 1468, 979, + 946, 909, 715, 1128, 715, 1128, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 532, + 586, 928, 1323, 1128, 1753, 1450, 522, 694, 694, 1116, 1128, + 569, 659, 584, 862, 1128, 1128, 1128, 1128, 1128, 1128, 1128, + 1128, 1128, 1128, 584, 584, 1128, 1128, 1128, 940, 1753, 1286, + 1270, 1253, 1386, 1110, 1087, 1413, 1434, 659, 678, 1255, 1061, + 1802, 1546, 1495, 1188, 1495, 1247, 1085, 1087, 1415, 1208, 1831, + 1241, 1155, 1098, 678, 862, 678, 1081, 819, 1135, 1217, 1219, + 989, 1217, 1141, 764, 1108, 1237, 608, 608, 1163, 608, 1853, + 1237, 1198, 1219, 1217, 862, 969, 840, 1237, 1049, 1614, 1087, + 1063, 932, 727, 1128, 727, 1128, -1, + }, + }, + { + "Georgia", + 2048, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 494, + 678, 843, 1317, 1249, 1674, 1455, 441, 768, 768, 967, 1317, + 552, 766, 552, 960, 1257, 880, 1144, 1130, 1157, 1082, 1159, + 1029, 1221, 1159, 640, 640, 1317, 1317, 1317, 980, 1902, 1374, + 1339, 1315, 1534, 1338, 1227, 1485, 1669, 798, 1060, 1422, 1236, + 1899, 1571, 1524, 1249, 1524, 1437, 1149, 1267, 1549, 1365, 1998, + 1455, 1260, 1232, 768, 960, 768, 1317, 1317, 1024, 1032, 1147, + 930, 1176, 990, 666, 1043, 1192, 600, 598, 1097, 586, 1804, + 1210, 1104, 1170, 1146, 839, 885, 707, 1178, 1017, 1510, 1034, + 1008, 909, 881, 768, 881, 1317, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 520, + 771, 1044, 1440, 1312, 1801, 1637, 551, 915, 915, 987, 1440, + 672, 776, 672, 966, 1436, 1003, 1283, 1279, 1330, 1227, 1327, + 1135, 1385, 1327, 752, 752, 1440, 1440, 1440, 1123, 1980, 1553, + 1551, 1465, 1708, 1477, 1375, 1653, 1870, 913, 1219, 1673, 1404, + 2096, 1719, 1679, 1436, 1679, 1633, 1329, 1401, 1707, 1561, 2307, + 1656, 1499, 1412, 915, 966, 915, 1440, 1440, 1024, 1220, 1322, + 1088, 1358, 1171, 805, 1181, 1392, 724, 709, 1294, 705, 2080, + 1413, 1302, 1347, 1328, 1065, 1050, 814, 1386, 1161, 1768, 1204, + 1151, 1076, 1024, 794, 1024, 1440, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 494, + 678, 843, 1317, 1249, 1674, 1455, 441, 768, 768, 967, 1317, + 552, 766, 552, 960, 1257, 880, 1144, 1130, 1157, 1082, 1159, + 1017, 1221, 1159, 786, 786, 1317, 1317, 1317, 980, 1902, 1374, + 1339, 1315, 1534, 1338, 1227, 1485, 1669, 798, 1060, 1422, 1236, + 1899, 1571, 1496, 1249, 1496, 1437, 1149, 1267, 1549, 1365, 1998, + 1455, 1260, 1232, 768, 960, 768, 1317, 1317, 1024, 1173, 1134, + 929, 1178, 966, 673, 1173, 1152, 609, 596, 1081, 584, 1801, + 1208, 1100, 1184, 1137, 945, 883, 711, 1178, 1102, 1684, 1026, + 1146, 909, 881, 768, 881, 1317, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 520, + 771, 1044, 1440, 1312, 1801, 1637, 551, 915, 915, 987, 1440, + 672, 776, 672, 966, 1436, 1003, 1283, 1279, 1330, 1227, 1327, + 1160, 1385, 1327, 752, 752, 1440, 1440, 1440, 1123, 1980, 1553, + 1555, 1465, 1708, 1477, 1375, 1653, 1870, 923, 1219, 1673, 1404, + 2116, 1699, 1679, 1446, 1679, 1633, 1337, 1401, 1707, 1561, 2307, + 1643, 1499, 1412, 915, 966, 915, 1440, 1440, 1024, 1352, 1329, + 1097, 1357, 1141, 780, 1330, 1383, 749, 747, 1313, 726, 2052, + 1413, 1302, 1357, 1331, 1093, 1059, 854, 1403, 1254, 1912, 1195, + 1371, 1059, 1024, 794, 1024, 1440, -1, + }, + }, + { + "Calibri", + 2048, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 463, + 667, 821, 1020, 1038, 1464, 1397, 452, 621, 621, 1020, 1020, + 511, 627, 517, 791, 1038, 1038, 1038, 1038, 1038, 1038, 1038, + 1038, 1038, 1038, 548, 548, 1020, 1020, 1020, 949, 1831, 1185, + 1114, 1092, 1260, 1000, 941, 1292, 1276, 516, 653, 1064, 861, + 1751, 1322, 1356, 1058, 1378, 1112, 941, 998, 1314, 1162, 1822, + 1063, 998, 959, 628, 791, 628, 1020, 1020, 596, 981, 1076, + 866, 1076, 1019, 625, 964, 1076, 470, 490, 931, 470, 1636, + 1076, 1080, 1076, 1076, 714, 801, 686, 1076, 925, 1464, 887, + 927, 809, 644, 943, 644, 1020, -1, + }, + { + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 463, + 667, 898, 1020, 1038, 1493, 1443, 478, 638, 638, 1020, 1020, + 528, 627, 547, 880, 1038, 1038, 1038, 1038, 1038, 1038, 1038, + 1038, 1038, 1038, 565, 565, 1020, 1020, 1020, 949, 1840, 1241, + 1148, 1084, 1291, 999, 940, 1305, 1292, 546, 678, 1120, 866, + 1790, 1349, 1385, 1090, 1405, 1153, 968, 1014, 1337, 1211, 1856, + 1128, 1064, 979, 665, 880, 665, 1020, 1020, 615, 1011, 1099, + 857, 1099, 1031, 648, 971, 1099, 503, 523, 983, 503, 1666, + 1099, 1101, 1099, 1099, 728, 817, 710, 1099, 969, 1526, 941, + 970, 814, 704, 973, 704, 1020, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 463, + 667, 821, 1020, 1038, 1464, 1397, 452, 621, 621, 1020, 1020, + 511, 627, 517, 794, 1038, 1038, 1038, 1038, 1038, 1038, 1038, + 1038, 1038, 1038, 548, 548, 1020, 1020, 1020, 949, 1831, 1185, + 1114, 1070, 1260, 1000, 941, 1292, 1276, 516, 653, 1064, 861, + 1751, 1320, 1340, 1058, 1360, 1112, 926, 998, 1314, 1162, 1823, + 1063, 998, 959, 628, 787, 628, 1020, 1020, 596, 1053, 1053, + 852, 1053, 978, 625, 1053, 1053, 470, 490, 931, 470, 1620, + 1053, 1051, 1053, 1053, 702, 797, 686, 1053, 913, 1464, 887, + 916, 809, 644, 943, 644, 1020, -1, + }, + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 463, + 667, 898, 1020, 1038, 1493, 1443, 478, 638, 638, 1020, 1020, + 528, 627, 547, 889, 1038, 1038, 1038, 1038, 1038, 1038, 1038, + 1038, 1038, 1038, 565, 565, 1020, 1020, 1020, 949, 1840, 1241, + 1148, 1062, 1291, 999, 940, 1305, 1292, 546, 678, 1120, 866, + 1790, 1344, 1369, 1090, 1387, 1153, 953, 1014, 1337, 1211, 1857, + 1128, 1064, 979, 665, 870, 665, 1020, 1020, 615, 1081, 1081, + 843, 1081, 1006, 648, 1081, 1080, 503, 523, 983, 503, 1646, + 1080, 1080, 1081, 1081, 721, 807, 710, 1080, 961, 1526, 941, + 963, 814, 704, 973, 704, 1020, -1, + }, + }, +}; + +const static size_t all_font_metrics_len = + sizeof(all_font_metrics) / sizeof(all_font_metrics[0]); + +/// Compares two font names for equality, ignoring case and special characters. +/// +/// E.g. "timesroman", "Times-Roman", "times ROMAN", "times_roman" and +/// "tim8esroman" are all considered equal to eachother, but not equal to "Times +/// New Roman". +static bool font_name_equal_permissive(const char *a, const char *b, + const size_t b_length) { + assert(strlen(b) >= b_length); + size_t a_length = strlen(a); + size_t a_pos = 0; + size_t b_pos = 0; + while (a_pos != a_length && b_pos != b_length) { + if (!isalpha_no_locale(a[a_pos])) { + ++a_pos; + continue; + } + if (!isalpha_no_locale(b[b_pos])) { + ++b_pos; + continue; + } + if (tolower(a[a_pos]) != tolower(b[b_pos])) { + return false; + } + ++a_pos; + ++b_pos; + } + while (a_pos != a_length) { + if (isalpha_no_locale(a[a_pos])) { + return false; + } + ++a_pos; + } + while (b_pos != b_length) { + if (isalpha_no_locale(b[b_pos])) { + return false; + } + ++b_pos; + } + return true; +} + +/// Checks whether a font name is in a pipe-separated list of font names, +/// ignoring case and special characters. +/// +/// E.g. "Times-Roman" and "TimesNewRoman" are both in +/// "times|timesroman|timesnewroman", but "Arial" is not. +static bool font_in_list_permissive(const char *value, const char *list) { + assert(value && strlen(value)); + assert(list && strlen(list)); + + do { + const char *next_pipe = strchr(list, '|'); + size_t next_pipe_or_end_pos = next_pipe ? next_pipe - list : strlen(list); + if (font_name_equal_permissive(value, list, next_pipe_or_end_pos)) { + return true; + } + list = next_pipe ? next_pipe + 1 : NULL; + } while (list); + + return false; +} + +static const struct FontFamilyMetrics * +get_metrics_for_font_family(const char *font_name) { + for (size_t i = 0; i < all_font_metrics_len; i++) { + if (font_in_list_permissive(font_name, all_font_metrics[i].font_name)) { + return &all_font_metrics[i]; + } + } + fprintf(stderr, + "Warning: no hard-coded metrics for '%s'. Falling back to 'Times' " + "metrics\n", + font_name); + return get_metrics_for_font_family("Times"); +} + +static const short * +get_metrics_for_font_variant(const struct FontFamilyMetrics *family_metrics, + bool bold, bool italic) { + if (bold && italic) { + return family_metrics->widths_bold_italic; + } + if (bold) { + return family_metrics->widths_bold; + } + if (italic) { + return family_metrics->widths_italic; + } + return family_metrics->widths_regular; +} + +/// @returns the width of the character in (units_per_em * 1) points. +static unsigned short +estimate_character_width_canonical(const short variant_metrics[128], + unsigned character) { + if (character >= 128) { + static bool warning_already_reported = false; + if (!warning_already_reported) { // stderr spam prevention + warning_already_reported = true; + fprintf(stderr, + "Warning: no value for width of non-ASCII character %u. Falling " + "back to width of space character\n", + character); + } + character = ' '; + } + short width = variant_metrics[character]; + if (width == -1) { + static bool warning_already_reported = false; + if (!warning_already_reported) { // stderr spam prevention + warning_already_reported = true; + fprintf(stderr, + "Warning: no value for width of ASCII character %u. Falling back " + "to 0\n", + character); + } + width = 0; + } + assert(width >= 0); + return width; +} + +double estimate_text_width_1pt(const char *font_name, const char *text, + bool bold, bool italic) { + assert(font_name); + assert(text); + + const struct FontFamilyMetrics *family_metrics = + get_metrics_for_font_family(font_name); + const short *variant_metrics = + get_metrics_for_font_variant(family_metrics, bold, italic); + unsigned text_width_canonical = 0; + for (const char *c = text; *c != '\0'; c++) { + text_width_canonical += + estimate_character_width_canonical(variant_metrics, (unsigned char)*c); + } + return (double)text_width_canonical / family_metrics->units_per_em; +} diff --git a/lib/common/textspan_lut.h b/lib/common/textspan_lut.h new file mode 100644 index 000000000..38ab1bd6d --- /dev/null +++ b/lib/common/textspan_lut.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +// LUT is short for lookup table. + +/// @param text a single line of ASCII text which should contain no control characters. +/// @returns the estimated width of `text` in 1 point. A value is always returned, falling back to Times-Roman metrics +/// if there is no hard-coded lookup table for the given `font_name`. +double estimate_text_width_1pt(const char* font_name, const char* text, bool bold, bool italic); diff --git a/lib/gvc.vcxproj b/lib/gvc.vcxproj index 7c4436fdc..6385a6f3a 100644 --- a/lib/gvc.vcxproj +++ b/lib/gvc.vcxproj @@ -134,6 +134,7 @@ awk -f $(SolutionDir)awk\colortbl.awk color_lib > common\colortbl.h + @@ -177,6 +178,7 @@ awk -f $(SolutionDir)awk\colortbl.awk color_lib > common\colortbl.h + diff --git a/lib/gvc.vcxproj.filters b/lib/gvc.vcxproj.filters index 600aa1ba2..3a23b79c5 100644 --- a/lib/gvc.vcxproj.filters +++ b/lib/gvc.vcxproj.filters @@ -75,6 +75,9 @@ Header Files + + Header Files + Header Files @@ -146,6 +149,9 @@ Source Files + + Source Files + Source Files -- 2.40.0