From 9b74560b1d4574c04954d81c37a6bed13368e050 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Sat, 4 Jul 2026 10:24:16 +0200 Subject: [PATCH 1/5] PDF stage 4.12: non-embedded font substitution + standard-14 AFM widths A font with no `/FontFile*` was rendered in the browser's default family with `advance_width` returning `/MissingWidth` (usually 0), so base-14 text (the common non-embedded case) placed and spaced wrong. - `pdf_afm_data.{hpp,cpp}`: the Adobe Core-14 AFM glyph metrics (name->width, the built-in code->width table, header ascent/descent/cap-height), generated by `tools/pdf/generate_afm_data.py` from a pinned Apache PDFBox tag (no build-time dependency; regenerate on demand like the AGL/CMap generators). - `pdf_afm.{hpp,cpp}`: `resolve_font_substitute` maps a `/BaseFont` name + `/FontDescriptor` hints (`/Flags`, `/FontWeight`, `/ItalicAngle`) to a CSS `font-family` stack (serif/sans/mono + bold/italic) and the standard-14 font whose AFM widths back placement; `afm_width`/`afm_code_width` look them up. - `Font::substitute` resolved at parse time for non-embedded simple fonts; `advance_width` falls back to the AFM (via the `/Encoding` glyph name, or the built-in encoding for Symbol/ZapfDingbats) when `/Widths` does not cover a code. A substitute also supplies the baseline shift when the descriptor declares no `/Ascent`. - HTML: fallback (`font == 0`) runs carry an interned `ff` font-family class in both the dual-layer visual layer and the single-layer path (the substitute is folded into the single-layer flow key so two families never share a block). Verified end-to-end: a non-embedded serif form renders `.ff1{font-family:'Times New Roman',Times,serif}` in both text modes. Unit tests cover the classifier, the AFM lookups and the `advance_width` fallback. Note: corpus reference output changes (added `ff` classes, corrected widths) and must be regenerated. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_018g7RqxjUq8rKTBTMwMfWMy --- .gitignore | 2 + CMakeLists.txt | 2 + src/odr/internal/html/pdf_file.cpp | 32 +- src/odr/internal/pdf/pdf_afm.cpp | 196 + src/odr/internal/pdf/pdf_afm.hpp | 72 + src/odr/internal/pdf/pdf_afm_data.cpp | 4512 +++++++++++++++++ src/odr/internal/pdf/pdf_afm_data.hpp | 40 + src/odr/internal/pdf/pdf_document.cpp | 21 + src/odr/internal/pdf/pdf_document_element.hpp | 8 + src/odr/internal/pdf/pdf_document_parser.cpp | 49 + test/src/internal/pdf/pdf_font.cpp | 103 + tools/pdf/THIRD_PARTY_LICENSES.md | 16 + tools/pdf/generate_afm_data.py | 261 + 13 files changed, 5313 insertions(+), 1 deletion(-) create mode 100644 src/odr/internal/pdf/pdf_afm.cpp create mode 100644 src/odr/internal/pdf/pdf_afm.hpp create mode 100644 src/odr/internal/pdf/pdf_afm_data.cpp create mode 100644 src/odr/internal/pdf/pdf_afm_data.hpp create mode 100644 tools/pdf/generate_afm_data.py diff --git a/.gitignore b/.gitignore index 992668a2..9b1a06b3 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,8 @@ offline/ tools/pdf/cmap-resources/ ## Adobe Glyph List (fetched by tools/pdf/generate_encoding_data.py) tools/pdf/glyphlist.txt +## Adobe Core-14 AFM metrics (fetched by tools/pdf/generate_afm_data.py) +tools/pdf/afm/ *.zip *.svg diff --git a/CMakeLists.txt b/CMakeLists.txt index ba7369e6..66a5a17f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -180,6 +180,8 @@ set(ODR_SOURCE_FILES "src/odr/internal/ooxml/ooxml_meta.cpp" "src/odr/internal/ooxml/ooxml_util.cpp" + "src/odr/internal/pdf/pdf_afm.cpp" + "src/odr/internal/pdf/pdf_afm_data.cpp" "src/odr/internal/pdf/pdf_cid.cpp" "src/odr/internal/pdf/pdf_cmap.cpp" "src/odr/internal/pdf/pdf_cmap_parser.cpp" diff --git a/src/odr/internal/html/pdf_file.cpp b/src/odr/internal/html/pdf_file.cpp index 3b16550d..ed709e49 100644 --- a/src/odr/internal/html/pdf_file.cpp +++ b/src/odr/internal/html/pdf_file.cpp @@ -107,6 +107,21 @@ std::string rgb_to_css(const std::array &rgb) { return std::move(s).str(); } +/// The CSS declaration a non-embedded font renders through: its substitute +/// `font-family` stack plus the weight/style implied by the `/BaseFont` name +/// and `/FontDescriptor` flags. Interned as an `ff` atomic class on the +/// fallback (`font == 0`) runs of either text mode. +std::string font_substitute_declaration(const pdf::FontSubstitute &substitute) { + std::string declaration = "font-family:" + substitute.css_family; + if (substitute.bold) { + declaration += ";font-weight:bold"; + } + if (substitute.italic) { + declaration += ";font-style:italic"; + } + return declaration; +} + /// Build an SVG `d` attribute from a path's subpaths, each point mapped through /// `to_box` (PDF user space -> the page box, y-down). Lines become `L`, cubic /// Béziers `C`, and an explicitly closed subpath ends with `Z`. @@ -788,6 +803,11 @@ class HtmlServiceImpl final : public HtmlService { if (font != 0) { run_classes += ' '; run_classes += font_class(font_class_used, font, invisible); + } else if (text.font != nullptr && text.font->substitute) { + // Non-embedded font: render the real Unicode in the substitute + // family (embedded fonts carry the family in `font_class`). + add_class(run_classes, "ff", + font_substitute_declaration(*text.font->substitute)); } if (vis_margin_pt != 0) { add_class(run_classes, "ml", pt_decl("margin-left", vis_margin_pt)); @@ -1366,9 +1386,17 @@ class HtmlServiceImpl final : public HtmlService { } // ---- Flow grouping ----------------------------------------------- + // The visible substitute family of a non-embedded font (`font == 0`); + // part of the flow key so two different substitutes (e.g. a Helvetica + // run then a Times run) never share one line block's `font_class`. + const std::string substitute_declaration = + (font == 0 && !invisible && text.font != nullptr && + text.font->substitute) + ? font_substitute_declaration(*text.font->substitute) + : std::string(); std::ostringstream fk; fk << font << '|' << invisible << '|' << font_size_pt << '|' << cs_pt - << '|' << ws_pt; + << '|' << ws_pt << '|' << substitute_declaration; const std::string flow_key = std::move(fk).str(); bool new_line = is_matrix || prev_was_matrix || cur_line < 0 || flow_key != cur_flow_key; @@ -1407,6 +1435,8 @@ class HtmlServiceImpl final : public HtmlService { line.classes = std::move(base); if (font != 0) { line.font_class = font_class(font_class_used, font, invisible); + } else if (!substitute_declaration.empty()) { + line.font_class = styles.intern("ff", substitute_declaration); } line.runs.push_back(std::move(run)); page_out.items.push_back(std::move(line)); diff --git a/src/odr/internal/pdf/pdf_afm.cpp b/src/odr/internal/pdf/pdf_afm.cpp new file mode 100644 index 00000000..b78597b2 --- /dev/null +++ b/src/odr/internal/pdf/pdf_afm.cpp @@ -0,0 +1,196 @@ +#include + +#include + +#include +#include +#include + +namespace odr::internal::pdf { + +namespace { + +const afm_data::FontMetrics &metrics_of(const StandardFont font) { + return afm_data::fonts[static_cast(font)]; +} + +/// ISO 32000-1 Table 121 `/FontDescriptor` `/Flags` bits used here. +constexpr std::uint32_t flag_fixed_pitch = 1U << 0; +constexpr std::uint32_t flag_serif = 1U << 1; +constexpr std::uint32_t flag_italic = 1U << 6; +constexpr std::uint32_t flag_force_bold = 1U << 18; + +/// The `/BaseFont` name with a subset prefix (`ABCDEF+`) stripped, lowercased +/// for case-insensitive substring matching. +std::string normalize_name(std::string_view base_font) { + if (base_font.size() > 7 && base_font[6] == '+') { + bool prefix = true; + for (std::size_t i = 0; i < 6; ++i) { + if (base_font[i] < 'A' || base_font[i] > 'Z') { + prefix = false; + break; + } + } + if (prefix) { + base_font.remove_prefix(7); + } + } + std::string result(base_font); + for (char &c : result) { + c = static_cast(std::tolower(static_cast(c))); + } + return result; +} + +bool contains(const std::string &haystack, std::string_view needle) { + return haystack.find(needle) != std::string::npos; +} + +enum class Family { sans, serif, mono, symbol, zapf }; + +Family classify_family(const std::string &name, const std::uint32_t flags) { + if (contains(name, "zapfdingbats") || contains(name, "dingbats")) { + return Family::zapf; + } + if (contains(name, "symbol")) { + return Family::symbol; + } + if (contains(name, "courier") || contains(name, "mono") || + contains(name, "consol")) { + return Family::mono; + } + if (contains(name, "times") || contains(name, "georgia") || + contains(name, "roman") || contains(name, "serif") || + contains(name, "minion") || contains(name, "garamond")) { + return Family::serif; + } + if (contains(name, "arial") || contains(name, "helvetica") || + contains(name, "verdana") || contains(name, "tahoma") || + contains(name, "segoe") || contains(name, "sans")) { + return Family::sans; + } + // No name hint: fall back to the descriptor flags. + if ((flags & flag_fixed_pitch) != 0) { + return Family::mono; + } + if ((flags & flag_serif) != 0) { + return Family::serif; + } + return Family::sans; +} + +StandardFont pick_metrics(const Family family, const bool bold, + const bool italic) { + switch (family) { + case Family::serif: + if (bold && italic) { + return StandardFont::times_bold_italic; + } + if (bold) { + return StandardFont::times_bold; + } + if (italic) { + return StandardFont::times_italic; + } + return StandardFont::times_roman; + case Family::mono: + if (bold && italic) { + return StandardFont::courier_bold_oblique; + } + if (bold) { + return StandardFont::courier_bold; + } + if (italic) { + return StandardFont::courier_oblique; + } + return StandardFont::courier; + case Family::symbol: + return StandardFont::symbol; + case Family::zapf: + return StandardFont::zapf_dingbats; + case Family::sans: + default: + if (bold && italic) { + return StandardFont::helvetica_bold_oblique; + } + if (bold) { + return StandardFont::helvetica_bold; + } + if (italic) { + return StandardFont::helvetica_oblique; + } + return StandardFont::helvetica; + } +} + +std::string_view family_stack(const Family family) { + switch (family) { + case Family::serif: + return "'Times New Roman',Times,serif"; + case Family::mono: + return "'Courier New',Courier,monospace"; + case Family::symbol: + return "Symbol,serif"; + case Family::zapf: + return "'Zapf Dingbats',fantasy"; + case Family::sans: + default: + return "Helvetica,Arial,sans-serif"; + } +} + +} // namespace + +FontSubstitute resolve_font_substitute(const std::string_view base_font, + const std::uint32_t flags, + const int font_weight, + const double italic_angle) { + const std::string name = normalize_name(base_font); + const Family family = classify_family(name, flags); + + const bool bold = contains(name, "bold") || font_weight >= 600 || + (flags & flag_force_bold) != 0; + // Symbol and ZapfDingbats have no bold/italic AFM variant; the name may still + // carry the words, but there is nothing to select. + const bool italic = family != Family::symbol && family != Family::zapf && + (contains(name, "italic") || contains(name, "oblique") || + (flags & flag_italic) != 0 || italic_angle != 0); + + FontSubstitute substitute; + substitute.css_family = std::string(family_stack(family)); + substitute.bold = bold; + substitute.italic = italic; + substitute.metrics = pick_metrics(family, bold, italic); + return substitute; +} + +std::optional afm_width(const StandardFont font, + const std::string_view glyph_name) { + const afm_data::FontMetrics &m = metrics_of(font); + const afm_data::GlyphWidth *const begin = m.glyphs; + const afm_data::GlyphWidth *const end = m.glyphs + m.glyph_count; + const auto *const it = std::lower_bound( + begin, end, glyph_name, + [](const afm_data::GlyphWidth &g, const std::string_view name) { + return g.name < name; + }); + if (it != end && it->name == glyph_name) { + return it->width; + } + return std::nullopt; +} + +std::optional afm_code_width(const StandardFont font, + const std::uint8_t code) { + const std::int16_t width = metrics_of(font).code_widths[code]; + if (width < 0) { + return std::nullopt; + } + return width; +} + +double afm_ascender(const StandardFont font) { + return metrics_of(font).ascender / 1000.0; +} + +} // namespace odr::internal::pdf diff --git a/src/odr/internal/pdf/pdf_afm.hpp b/src/odr/internal/pdf/pdf_afm.hpp new file mode 100644 index 00000000..df3c74e8 --- /dev/null +++ b/src/odr/internal/pdf/pdf_afm.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include +#include + +namespace odr::internal::pdf { + +/// The 14 standard fonts (ISO 32000-1 9.6.2.2) whose glyph metrics ship in the +/// Core AFM tables (`pdf_afm_data`). The order matches `afm_data::fonts`. +enum class StandardFont : std::uint8_t { + helvetica, + helvetica_bold, + helvetica_oblique, + helvetica_bold_oblique, + times_roman, + times_bold, + times_italic, + times_bold_italic, + courier, + courier_bold, + courier_oblique, + courier_bold_oblique, + symbol, + zapf_dingbats, +}; + +/// How a non-embedded font is rendered: with the browser's own fonts, chosen by +/// a CSS `font-family` stack, and placed with the standard-14 AFM advance +/// widths (`metrics`) when the font maps onto one of them. Resolved once at +/// parse time (`resolve_font_substitute`) and carried on `Font::substitute`. +struct FontSubstitute { + /// A generic CSS `font-family` value, e.g. `"Helvetica,Arial,sans-serif"`. + /// Generic families always resolve, so a viewer never sees a missing glyph + /// box; the shapes are approximate, the metrics (below) make placement exact. + std::string css_family; + bool bold{false}; + bool italic{false}; + /// The standard-14 font whose AFM widths drive `advance_width`, or `nullopt` + /// when the font resembles none of them (then `/Widths`/`/MissingWidth` are + /// the only metric source, as before). + std::optional metrics; +}; + +/// Choose a substitute for a non-embedded simple font from its `/BaseFont` name +/// and `/FontDescriptor` hints (`/Flags`, `/FontWeight`, `/ItalicAngle`; +/// `font_weight <= 0` and `italic_angle == 0` mean "absent"). A subset prefix +/// (`ABCDEF+`) on the name is ignored. Never fails: an unrecognized font falls +/// back to a sans-serif stack with Helvetica metrics. +[[nodiscard]] FontSubstitute resolve_font_substitute(std::string_view base_font, + std::uint32_t flags, + int font_weight, + double italic_angle); + +/// The advance width of a glyph (by name) in `font`, glyph space (1/1000 em), +/// or `nullopt` when the font has no such glyph. +[[nodiscard]] std::optional afm_width(StandardFont font, + std::string_view glyph_name); + +/// The advance width of a code in `font`'s built-in encoding, glyph space +/// (1/1000 em), or `nullopt` when the slot is empty. The fallback when a font +/// carries no `/Encoding` (notably Symbol/ZapfDingbats). +[[nodiscard]] std::optional afm_code_width(StandardFont font, + std::uint8_t code); + +/// The font's `Ascender` metric, em units (glyph space / 1000); used as the +/// baseline-shift fallback for a substitute with no `/FontDescriptor` +/// `/Ascent`. +[[nodiscard]] double afm_ascender(StandardFont font); + +} // namespace odr::internal::pdf diff --git a/src/odr/internal/pdf/pdf_afm_data.cpp b/src/odr/internal/pdf/pdf_afm_data.cpp new file mode 100644 index 00000000..42a0f82b --- /dev/null +++ b/src/odr/internal/pdf/pdf_afm_data.cpp @@ -0,0 +1,4512 @@ +// Auto-generated by tools/pdf/generate_afm_data.py -- DO NOT EDIT. +// Regenerate by rerunning the script; see its header for the source data. +// Adobe Core-14 AFM metrics, redistributed by Apache PDFBox (Apache-2.0); +// see tools/pdf/THIRD_PARTY_LICENSES.md. + +// clang-format off + +#include + +namespace odr::internal::pdf::afm_data { +namespace { + +constexpr GlyphWidth glyphs_helvetica[] = { + {"A", 667}, + {"AE", 1000}, + {"Aacute", 667}, + {"Abreve", 667}, + {"Acircumflex", 667}, + {"Adieresis", 667}, + {"Agrave", 667}, + {"Amacron", 667}, + {"Aogonek", 667}, + {"Aring", 667}, + {"Atilde", 667}, + {"B", 667}, + {"C", 722}, + {"Cacute", 722}, + {"Ccaron", 722}, + {"Ccedilla", 722}, + {"D", 722}, + {"Dcaron", 722}, + {"Dcroat", 722}, + {"Delta", 612}, + {"E", 667}, + {"Eacute", 667}, + {"Ecaron", 667}, + {"Ecircumflex", 667}, + {"Edieresis", 667}, + {"Edotaccent", 667}, + {"Egrave", 667}, + {"Emacron", 667}, + {"Eogonek", 667}, + {"Eth", 722}, + {"Euro", 556}, + {"F", 611}, + {"G", 778}, + {"Gbreve", 778}, + {"Gcommaaccent", 778}, + {"H", 722}, + {"I", 278}, + {"Iacute", 278}, + {"Icircumflex", 278}, + {"Idieresis", 278}, + {"Idotaccent", 278}, + {"Igrave", 278}, + {"Imacron", 278}, + {"Iogonek", 278}, + {"J", 500}, + {"K", 667}, + {"Kcommaaccent", 667}, + {"L", 556}, + {"Lacute", 556}, + {"Lcaron", 556}, + {"Lcommaaccent", 556}, + {"Lslash", 556}, + {"M", 833}, + {"N", 722}, + {"Nacute", 722}, + {"Ncaron", 722}, + {"Ncommaaccent", 722}, + {"Ntilde", 722}, + {"O", 778}, + {"OE", 1000}, + {"Oacute", 778}, + {"Ocircumflex", 778}, + {"Odieresis", 778}, + {"Ograve", 778}, + {"Ohungarumlaut", 778}, + {"Omacron", 778}, + {"Oslash", 778}, + {"Otilde", 778}, + {"P", 667}, + {"Q", 778}, + {"R", 722}, + {"Racute", 722}, + {"Rcaron", 722}, + {"Rcommaaccent", 722}, + {"S", 667}, + {"Sacute", 667}, + {"Scaron", 667}, + {"Scedilla", 667}, + {"Scommaaccent", 667}, + {"T", 611}, + {"Tcaron", 611}, + {"Tcommaaccent", 611}, + {"Thorn", 667}, + {"U", 722}, + {"Uacute", 722}, + {"Ucircumflex", 722}, + {"Udieresis", 722}, + {"Ugrave", 722}, + {"Uhungarumlaut", 722}, + {"Umacron", 722}, + {"Uogonek", 722}, + {"Uring", 722}, + {"V", 667}, + {"W", 944}, + {"X", 667}, + {"Y", 667}, + {"Yacute", 667}, + {"Ydieresis", 667}, + {"Z", 611}, + {"Zacute", 611}, + {"Zcaron", 611}, + {"Zdotaccent", 611}, + {"a", 556}, + {"aacute", 556}, + {"abreve", 556}, + {"acircumflex", 556}, + {"acute", 333}, + {"adieresis", 556}, + {"ae", 889}, + {"agrave", 556}, + {"amacron", 556}, + {"ampersand", 667}, + {"aogonek", 556}, + {"aring", 556}, + {"asciicircum", 469}, + {"asciitilde", 584}, + {"asterisk", 389}, + {"at", 1015}, + {"atilde", 556}, + {"b", 556}, + {"backslash", 278}, + {"bar", 260}, + {"braceleft", 334}, + {"braceright", 334}, + {"bracketleft", 278}, + {"bracketright", 278}, + {"breve", 333}, + {"brokenbar", 260}, + {"bullet", 350}, + {"c", 500}, + {"cacute", 500}, + {"caron", 333}, + {"ccaron", 500}, + {"ccedilla", 500}, + {"cedilla", 333}, + {"cent", 556}, + {"circumflex", 333}, + {"colon", 278}, + {"comma", 278}, + {"commaaccent", 250}, + {"copyright", 737}, + {"currency", 556}, + {"d", 556}, + {"dagger", 556}, + {"daggerdbl", 556}, + {"dcaron", 643}, + {"dcroat", 556}, + {"degree", 400}, + {"dieresis", 333}, + {"divide", 584}, + {"dollar", 556}, + {"dotaccent", 333}, + {"dotlessi", 278}, + {"e", 556}, + {"eacute", 556}, + {"ecaron", 556}, + {"ecircumflex", 556}, + {"edieresis", 556}, + {"edotaccent", 556}, + {"egrave", 556}, + {"eight", 556}, + {"ellipsis", 1000}, + {"emacron", 556}, + {"emdash", 1000}, + {"endash", 556}, + {"eogonek", 556}, + {"equal", 584}, + {"eth", 556}, + {"exclam", 278}, + {"exclamdown", 333}, + {"f", 278}, + {"fi", 500}, + {"five", 556}, + {"fl", 500}, + {"florin", 556}, + {"four", 556}, + {"fraction", 167}, + {"g", 556}, + {"gbreve", 556}, + {"gcommaaccent", 556}, + {"germandbls", 611}, + {"grave", 333}, + {"greater", 584}, + {"greaterequal", 549}, + {"guillemotleft", 556}, + {"guillemotright", 556}, + {"guilsinglleft", 333}, + {"guilsinglright", 333}, + {"h", 556}, + {"hungarumlaut", 333}, + {"hyphen", 333}, + {"i", 222}, + {"iacute", 278}, + {"icircumflex", 278}, + {"idieresis", 278}, + {"igrave", 278}, + {"imacron", 278}, + {"iogonek", 222}, + {"j", 222}, + {"k", 500}, + {"kcommaaccent", 500}, + {"l", 222}, + {"lacute", 222}, + {"lcaron", 299}, + {"lcommaaccent", 222}, + {"less", 584}, + {"lessequal", 549}, + {"logicalnot", 584}, + {"lozenge", 471}, + {"lslash", 222}, + {"m", 833}, + {"macron", 333}, + {"minus", 584}, + {"mu", 556}, + {"multiply", 584}, + {"n", 556}, + {"nacute", 556}, + {"ncaron", 556}, + {"ncommaaccent", 556}, + {"nine", 556}, + {"notequal", 549}, + {"ntilde", 556}, + {"numbersign", 556}, + {"o", 556}, + {"oacute", 556}, + {"ocircumflex", 556}, + {"odieresis", 556}, + {"oe", 944}, + {"ogonek", 333}, + {"ograve", 556}, + {"ohungarumlaut", 556}, + {"omacron", 556}, + {"one", 556}, + {"onehalf", 834}, + {"onequarter", 834}, + {"onesuperior", 333}, + {"ordfeminine", 370}, + {"ordmasculine", 365}, + {"oslash", 611}, + {"otilde", 556}, + {"p", 556}, + {"paragraph", 537}, + {"parenleft", 333}, + {"parenright", 333}, + {"partialdiff", 476}, + {"percent", 889}, + {"period", 278}, + {"periodcentered", 278}, + {"perthousand", 1000}, + {"plus", 584}, + {"plusminus", 584}, + {"q", 556}, + {"question", 556}, + {"questiondown", 611}, + {"quotedbl", 355}, + {"quotedblbase", 333}, + {"quotedblleft", 333}, + {"quotedblright", 333}, + {"quoteleft", 222}, + {"quoteright", 222}, + {"quotesinglbase", 222}, + {"quotesingle", 191}, + {"r", 333}, + {"racute", 333}, + {"radical", 453}, + {"rcaron", 333}, + {"rcommaaccent", 333}, + {"registered", 737}, + {"ring", 333}, + {"s", 500}, + {"sacute", 500}, + {"scaron", 500}, + {"scedilla", 500}, + {"scommaaccent", 500}, + {"section", 556}, + {"semicolon", 278}, + {"seven", 556}, + {"six", 556}, + {"slash", 278}, + {"space", 278}, + {"sterling", 556}, + {"summation", 600}, + {"t", 278}, + {"tcaron", 317}, + {"tcommaaccent", 278}, + {"thorn", 556}, + {"three", 556}, + {"threequarters", 834}, + {"threesuperior", 333}, + {"tilde", 333}, + {"trademark", 1000}, + {"two", 556}, + {"twosuperior", 333}, + {"u", 556}, + {"uacute", 556}, + {"ucircumflex", 556}, + {"udieresis", 556}, + {"ugrave", 556}, + {"uhungarumlaut", 556}, + {"umacron", 556}, + {"underscore", 556}, + {"uogonek", 556}, + {"uring", 556}, + {"v", 500}, + {"w", 722}, + {"x", 500}, + {"y", 500}, + {"yacute", 500}, + {"ydieresis", 500}, + {"yen", 556}, + {"z", 500}, + {"zacute", 500}, + {"zcaron", 500}, + {"zdotaccent", 500}, + {"zero", 556}, +}; + +constexpr std::int16_t code_widths_helvetica[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 278, 278, 355, 556, 556, 889, 667, 222, 333, 333, 389, 584, 278, 333, 278, 278, + 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, + 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, + 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, + 222, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, + 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 333, 556, 556, 167, 556, 556, 556, 556, 191, 333, 556, 333, 333, 500, 500, + -1, 556, 556, 556, 278, -1, 537, 350, 222, 333, 333, 556, 1000, 1000, -1, 611, + -1, 333, 333, 333, 333, 333, 333, 333, 333, -1, 333, 333, -1, 333, 333, 333, + 1000, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1000, -1, 370, -1, -1, -1, -1, 556, 778, 1000, 365, -1, -1, -1, -1, + -1, 889, -1, -1, -1, 278, -1, -1, 222, 611, 944, 611, -1, -1, -1, -1, +}; + +constexpr GlyphWidth glyphs_helvetica_bold[] = { + {"A", 722}, + {"AE", 1000}, + {"Aacute", 722}, + {"Abreve", 722}, + {"Acircumflex", 722}, + {"Adieresis", 722}, + {"Agrave", 722}, + {"Amacron", 722}, + {"Aogonek", 722}, + {"Aring", 722}, + {"Atilde", 722}, + {"B", 722}, + {"C", 722}, + {"Cacute", 722}, + {"Ccaron", 722}, + {"Ccedilla", 722}, + {"D", 722}, + {"Dcaron", 722}, + {"Dcroat", 722}, + {"Delta", 612}, + {"E", 667}, + {"Eacute", 667}, + {"Ecaron", 667}, + {"Ecircumflex", 667}, + {"Edieresis", 667}, + {"Edotaccent", 667}, + {"Egrave", 667}, + {"Emacron", 667}, + {"Eogonek", 667}, + {"Eth", 722}, + {"Euro", 556}, + {"F", 611}, + {"G", 778}, + {"Gbreve", 778}, + {"Gcommaaccent", 778}, + {"H", 722}, + {"I", 278}, + {"Iacute", 278}, + {"Icircumflex", 278}, + {"Idieresis", 278}, + {"Idotaccent", 278}, + {"Igrave", 278}, + {"Imacron", 278}, + {"Iogonek", 278}, + {"J", 556}, + {"K", 722}, + {"Kcommaaccent", 722}, + {"L", 611}, + {"Lacute", 611}, + {"Lcaron", 611}, + {"Lcommaaccent", 611}, + {"Lslash", 611}, + {"M", 833}, + {"N", 722}, + {"Nacute", 722}, + {"Ncaron", 722}, + {"Ncommaaccent", 722}, + {"Ntilde", 722}, + {"O", 778}, + {"OE", 1000}, + {"Oacute", 778}, + {"Ocircumflex", 778}, + {"Odieresis", 778}, + {"Ograve", 778}, + {"Ohungarumlaut", 778}, + {"Omacron", 778}, + {"Oslash", 778}, + {"Otilde", 778}, + {"P", 667}, + {"Q", 778}, + {"R", 722}, + {"Racute", 722}, + {"Rcaron", 722}, + {"Rcommaaccent", 722}, + {"S", 667}, + {"Sacute", 667}, + {"Scaron", 667}, + {"Scedilla", 667}, + {"Scommaaccent", 667}, + {"T", 611}, + {"Tcaron", 611}, + {"Tcommaaccent", 611}, + {"Thorn", 667}, + {"U", 722}, + {"Uacute", 722}, + {"Ucircumflex", 722}, + {"Udieresis", 722}, + {"Ugrave", 722}, + {"Uhungarumlaut", 722}, + {"Umacron", 722}, + {"Uogonek", 722}, + {"Uring", 722}, + {"V", 667}, + {"W", 944}, + {"X", 667}, + {"Y", 667}, + {"Yacute", 667}, + {"Ydieresis", 667}, + {"Z", 611}, + {"Zacute", 611}, + {"Zcaron", 611}, + {"Zdotaccent", 611}, + {"a", 556}, + {"aacute", 556}, + {"abreve", 556}, + {"acircumflex", 556}, + {"acute", 333}, + {"adieresis", 556}, + {"ae", 889}, + {"agrave", 556}, + {"amacron", 556}, + {"ampersand", 722}, + {"aogonek", 556}, + {"aring", 556}, + {"asciicircum", 584}, + {"asciitilde", 584}, + {"asterisk", 389}, + {"at", 975}, + {"atilde", 556}, + {"b", 611}, + {"backslash", 278}, + {"bar", 280}, + {"braceleft", 389}, + {"braceright", 389}, + {"bracketleft", 333}, + {"bracketright", 333}, + {"breve", 333}, + {"brokenbar", 280}, + {"bullet", 350}, + {"c", 556}, + {"cacute", 556}, + {"caron", 333}, + {"ccaron", 556}, + {"ccedilla", 556}, + {"cedilla", 333}, + {"cent", 556}, + {"circumflex", 333}, + {"colon", 333}, + {"comma", 278}, + {"commaaccent", 250}, + {"copyright", 737}, + {"currency", 556}, + {"d", 611}, + {"dagger", 556}, + {"daggerdbl", 556}, + {"dcaron", 743}, + {"dcroat", 611}, + {"degree", 400}, + {"dieresis", 333}, + {"divide", 584}, + {"dollar", 556}, + {"dotaccent", 333}, + {"dotlessi", 278}, + {"e", 556}, + {"eacute", 556}, + {"ecaron", 556}, + {"ecircumflex", 556}, + {"edieresis", 556}, + {"edotaccent", 556}, + {"egrave", 556}, + {"eight", 556}, + {"ellipsis", 1000}, + {"emacron", 556}, + {"emdash", 1000}, + {"endash", 556}, + {"eogonek", 556}, + {"equal", 584}, + {"eth", 611}, + {"exclam", 333}, + {"exclamdown", 333}, + {"f", 333}, + {"fi", 611}, + {"five", 556}, + {"fl", 611}, + {"florin", 556}, + {"four", 556}, + {"fraction", 167}, + {"g", 611}, + {"gbreve", 611}, + {"gcommaaccent", 611}, + {"germandbls", 611}, + {"grave", 333}, + {"greater", 584}, + {"greaterequal", 549}, + {"guillemotleft", 556}, + {"guillemotright", 556}, + {"guilsinglleft", 333}, + {"guilsinglright", 333}, + {"h", 611}, + {"hungarumlaut", 333}, + {"hyphen", 333}, + {"i", 278}, + {"iacute", 278}, + {"icircumflex", 278}, + {"idieresis", 278}, + {"igrave", 278}, + {"imacron", 278}, + {"iogonek", 278}, + {"j", 278}, + {"k", 556}, + {"kcommaaccent", 556}, + {"l", 278}, + {"lacute", 278}, + {"lcaron", 400}, + {"lcommaaccent", 278}, + {"less", 584}, + {"lessequal", 549}, + {"logicalnot", 584}, + {"lozenge", 494}, + {"lslash", 278}, + {"m", 889}, + {"macron", 333}, + {"minus", 584}, + {"mu", 611}, + {"multiply", 584}, + {"n", 611}, + {"nacute", 611}, + {"ncaron", 611}, + {"ncommaaccent", 611}, + {"nine", 556}, + {"notequal", 549}, + {"ntilde", 611}, + {"numbersign", 556}, + {"o", 611}, + {"oacute", 611}, + {"ocircumflex", 611}, + {"odieresis", 611}, + {"oe", 944}, + {"ogonek", 333}, + {"ograve", 611}, + {"ohungarumlaut", 611}, + {"omacron", 611}, + {"one", 556}, + {"onehalf", 834}, + {"onequarter", 834}, + {"onesuperior", 333}, + {"ordfeminine", 370}, + {"ordmasculine", 365}, + {"oslash", 611}, + {"otilde", 611}, + {"p", 611}, + {"paragraph", 556}, + {"parenleft", 333}, + {"parenright", 333}, + {"partialdiff", 494}, + {"percent", 889}, + {"period", 278}, + {"periodcentered", 278}, + {"perthousand", 1000}, + {"plus", 584}, + {"plusminus", 584}, + {"q", 611}, + {"question", 611}, + {"questiondown", 611}, + {"quotedbl", 474}, + {"quotedblbase", 500}, + {"quotedblleft", 500}, + {"quotedblright", 500}, + {"quoteleft", 278}, + {"quoteright", 278}, + {"quotesinglbase", 278}, + {"quotesingle", 238}, + {"r", 389}, + {"racute", 389}, + {"radical", 549}, + {"rcaron", 389}, + {"rcommaaccent", 389}, + {"registered", 737}, + {"ring", 333}, + {"s", 556}, + {"sacute", 556}, + {"scaron", 556}, + {"scedilla", 556}, + {"scommaaccent", 556}, + {"section", 556}, + {"semicolon", 333}, + {"seven", 556}, + {"six", 556}, + {"slash", 278}, + {"space", 278}, + {"sterling", 556}, + {"summation", 600}, + {"t", 333}, + {"tcaron", 389}, + {"tcommaaccent", 333}, + {"thorn", 611}, + {"three", 556}, + {"threequarters", 834}, + {"threesuperior", 333}, + {"tilde", 333}, + {"trademark", 1000}, + {"two", 556}, + {"twosuperior", 333}, + {"u", 611}, + {"uacute", 611}, + {"ucircumflex", 611}, + {"udieresis", 611}, + {"ugrave", 611}, + {"uhungarumlaut", 611}, + {"umacron", 611}, + {"underscore", 556}, + {"uogonek", 611}, + {"uring", 611}, + {"v", 556}, + {"w", 778}, + {"x", 556}, + {"y", 556}, + {"yacute", 556}, + {"ydieresis", 556}, + {"yen", 556}, + {"z", 500}, + {"zacute", 500}, + {"zcaron", 500}, + {"zdotaccent", 500}, + {"zero", 556}, +}; + +constexpr std::int16_t code_widths_helvetica_bold[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 278, 333, 474, 556, 556, 889, 722, 278, 333, 333, 389, 584, 278, 333, 278, 278, + 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, + 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, + 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, + 278, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, + 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 333, 556, 556, 167, 556, 556, 556, 556, 238, 500, 556, 333, 333, 611, 611, + -1, 556, 556, 556, 278, -1, 556, 350, 278, 500, 500, 556, 1000, 1000, -1, 611, + -1, 333, 333, 333, 333, 333, 333, 333, 333, -1, 333, 333, -1, 333, 333, 333, + 1000, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1000, -1, 370, -1, -1, -1, -1, 611, 778, 1000, 365, -1, -1, -1, -1, + -1, 889, -1, -1, -1, 278, -1, -1, 278, 611, 944, 611, -1, -1, -1, -1, +}; + +constexpr GlyphWidth glyphs_helvetica_oblique[] = { + {"A", 667}, + {"AE", 1000}, + {"Aacute", 667}, + {"Abreve", 667}, + {"Acircumflex", 667}, + {"Adieresis", 667}, + {"Agrave", 667}, + {"Amacron", 667}, + {"Aogonek", 667}, + {"Aring", 667}, + {"Atilde", 667}, + {"B", 667}, + {"C", 722}, + {"Cacute", 722}, + {"Ccaron", 722}, + {"Ccedilla", 722}, + {"D", 722}, + {"Dcaron", 722}, + {"Dcroat", 722}, + {"Delta", 612}, + {"E", 667}, + {"Eacute", 667}, + {"Ecaron", 667}, + {"Ecircumflex", 667}, + {"Edieresis", 667}, + {"Edotaccent", 667}, + {"Egrave", 667}, + {"Emacron", 667}, + {"Eogonek", 667}, + {"Eth", 722}, + {"Euro", 556}, + {"F", 611}, + {"G", 778}, + {"Gbreve", 778}, + {"Gcommaaccent", 778}, + {"H", 722}, + {"I", 278}, + {"Iacute", 278}, + {"Icircumflex", 278}, + {"Idieresis", 278}, + {"Idotaccent", 278}, + {"Igrave", 278}, + {"Imacron", 278}, + {"Iogonek", 278}, + {"J", 500}, + {"K", 667}, + {"Kcommaaccent", 667}, + {"L", 556}, + {"Lacute", 556}, + {"Lcaron", 556}, + {"Lcommaaccent", 556}, + {"Lslash", 556}, + {"M", 833}, + {"N", 722}, + {"Nacute", 722}, + {"Ncaron", 722}, + {"Ncommaaccent", 722}, + {"Ntilde", 722}, + {"O", 778}, + {"OE", 1000}, + {"Oacute", 778}, + {"Ocircumflex", 778}, + {"Odieresis", 778}, + {"Ograve", 778}, + {"Ohungarumlaut", 778}, + {"Omacron", 778}, + {"Oslash", 778}, + {"Otilde", 778}, + {"P", 667}, + {"Q", 778}, + {"R", 722}, + {"Racute", 722}, + {"Rcaron", 722}, + {"Rcommaaccent", 722}, + {"S", 667}, + {"Sacute", 667}, + {"Scaron", 667}, + {"Scedilla", 667}, + {"Scommaaccent", 667}, + {"T", 611}, + {"Tcaron", 611}, + {"Tcommaaccent", 611}, + {"Thorn", 667}, + {"U", 722}, + {"Uacute", 722}, + {"Ucircumflex", 722}, + {"Udieresis", 722}, + {"Ugrave", 722}, + {"Uhungarumlaut", 722}, + {"Umacron", 722}, + {"Uogonek", 722}, + {"Uring", 722}, + {"V", 667}, + {"W", 944}, + {"X", 667}, + {"Y", 667}, + {"Yacute", 667}, + {"Ydieresis", 667}, + {"Z", 611}, + {"Zacute", 611}, + {"Zcaron", 611}, + {"Zdotaccent", 611}, + {"a", 556}, + {"aacute", 556}, + {"abreve", 556}, + {"acircumflex", 556}, + {"acute", 333}, + {"adieresis", 556}, + {"ae", 889}, + {"agrave", 556}, + {"amacron", 556}, + {"ampersand", 667}, + {"aogonek", 556}, + {"aring", 556}, + {"asciicircum", 469}, + {"asciitilde", 584}, + {"asterisk", 389}, + {"at", 1015}, + {"atilde", 556}, + {"b", 556}, + {"backslash", 278}, + {"bar", 260}, + {"braceleft", 334}, + {"braceright", 334}, + {"bracketleft", 278}, + {"bracketright", 278}, + {"breve", 333}, + {"brokenbar", 260}, + {"bullet", 350}, + {"c", 500}, + {"cacute", 500}, + {"caron", 333}, + {"ccaron", 500}, + {"ccedilla", 500}, + {"cedilla", 333}, + {"cent", 556}, + {"circumflex", 333}, + {"colon", 278}, + {"comma", 278}, + {"commaaccent", 250}, + {"copyright", 737}, + {"currency", 556}, + {"d", 556}, + {"dagger", 556}, + {"daggerdbl", 556}, + {"dcaron", 643}, + {"dcroat", 556}, + {"degree", 400}, + {"dieresis", 333}, + {"divide", 584}, + {"dollar", 556}, + {"dotaccent", 333}, + {"dotlessi", 278}, + {"e", 556}, + {"eacute", 556}, + {"ecaron", 556}, + {"ecircumflex", 556}, + {"edieresis", 556}, + {"edotaccent", 556}, + {"egrave", 556}, + {"eight", 556}, + {"ellipsis", 1000}, + {"emacron", 556}, + {"emdash", 1000}, + {"endash", 556}, + {"eogonek", 556}, + {"equal", 584}, + {"eth", 556}, + {"exclam", 278}, + {"exclamdown", 333}, + {"f", 278}, + {"fi", 500}, + {"five", 556}, + {"fl", 500}, + {"florin", 556}, + {"four", 556}, + {"fraction", 167}, + {"g", 556}, + {"gbreve", 556}, + {"gcommaaccent", 556}, + {"germandbls", 611}, + {"grave", 333}, + {"greater", 584}, + {"greaterequal", 549}, + {"guillemotleft", 556}, + {"guillemotright", 556}, + {"guilsinglleft", 333}, + {"guilsinglright", 333}, + {"h", 556}, + {"hungarumlaut", 333}, + {"hyphen", 333}, + {"i", 222}, + {"iacute", 278}, + {"icircumflex", 278}, + {"idieresis", 278}, + {"igrave", 278}, + {"imacron", 278}, + {"iogonek", 222}, + {"j", 222}, + {"k", 500}, + {"kcommaaccent", 500}, + {"l", 222}, + {"lacute", 222}, + {"lcaron", 299}, + {"lcommaaccent", 222}, + {"less", 584}, + {"lessequal", 549}, + {"logicalnot", 584}, + {"lozenge", 471}, + {"lslash", 222}, + {"m", 833}, + {"macron", 333}, + {"minus", 584}, + {"mu", 556}, + {"multiply", 584}, + {"n", 556}, + {"nacute", 556}, + {"ncaron", 556}, + {"ncommaaccent", 556}, + {"nine", 556}, + {"notequal", 549}, + {"ntilde", 556}, + {"numbersign", 556}, + {"o", 556}, + {"oacute", 556}, + {"ocircumflex", 556}, + {"odieresis", 556}, + {"oe", 944}, + {"ogonek", 333}, + {"ograve", 556}, + {"ohungarumlaut", 556}, + {"omacron", 556}, + {"one", 556}, + {"onehalf", 834}, + {"onequarter", 834}, + {"onesuperior", 333}, + {"ordfeminine", 370}, + {"ordmasculine", 365}, + {"oslash", 611}, + {"otilde", 556}, + {"p", 556}, + {"paragraph", 537}, + {"parenleft", 333}, + {"parenright", 333}, + {"partialdiff", 476}, + {"percent", 889}, + {"period", 278}, + {"periodcentered", 278}, + {"perthousand", 1000}, + {"plus", 584}, + {"plusminus", 584}, + {"q", 556}, + {"question", 556}, + {"questiondown", 611}, + {"quotedbl", 355}, + {"quotedblbase", 333}, + {"quotedblleft", 333}, + {"quotedblright", 333}, + {"quoteleft", 222}, + {"quoteright", 222}, + {"quotesinglbase", 222}, + {"quotesingle", 191}, + {"r", 333}, + {"racute", 333}, + {"radical", 453}, + {"rcaron", 333}, + {"rcommaaccent", 333}, + {"registered", 737}, + {"ring", 333}, + {"s", 500}, + {"sacute", 500}, + {"scaron", 500}, + {"scedilla", 500}, + {"scommaaccent", 500}, + {"section", 556}, + {"semicolon", 278}, + {"seven", 556}, + {"six", 556}, + {"slash", 278}, + {"space", 278}, + {"sterling", 556}, + {"summation", 600}, + {"t", 278}, + {"tcaron", 317}, + {"tcommaaccent", 278}, + {"thorn", 556}, + {"three", 556}, + {"threequarters", 834}, + {"threesuperior", 333}, + {"tilde", 333}, + {"trademark", 1000}, + {"two", 556}, + {"twosuperior", 333}, + {"u", 556}, + {"uacute", 556}, + {"ucircumflex", 556}, + {"udieresis", 556}, + {"ugrave", 556}, + {"uhungarumlaut", 556}, + {"umacron", 556}, + {"underscore", 556}, + {"uogonek", 556}, + {"uring", 556}, + {"v", 500}, + {"w", 722}, + {"x", 500}, + {"y", 500}, + {"yacute", 500}, + {"ydieresis", 500}, + {"yen", 556}, + {"z", 500}, + {"zacute", 500}, + {"zcaron", 500}, + {"zdotaccent", 500}, + {"zero", 556}, +}; + +constexpr std::int16_t code_widths_helvetica_oblique[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 278, 278, 355, 556, 556, 889, 667, 222, 333, 333, 389, 584, 278, 333, 278, 278, + 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, + 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, + 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, + 222, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, + 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 333, 556, 556, 167, 556, 556, 556, 556, 191, 333, 556, 333, 333, 500, 500, + -1, 556, 556, 556, 278, -1, 537, 350, 222, 333, 333, 556, 1000, 1000, -1, 611, + -1, 333, 333, 333, 333, 333, 333, 333, 333, -1, 333, 333, -1, 333, 333, 333, + 1000, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1000, -1, 370, -1, -1, -1, -1, 556, 778, 1000, 365, -1, -1, -1, -1, + -1, 889, -1, -1, -1, 278, -1, -1, 222, 611, 944, 611, -1, -1, -1, -1, +}; + +constexpr GlyphWidth glyphs_helvetica_boldoblique[] = { + {"A", 722}, + {"AE", 1000}, + {"Aacute", 722}, + {"Abreve", 722}, + {"Acircumflex", 722}, + {"Adieresis", 722}, + {"Agrave", 722}, + {"Amacron", 722}, + {"Aogonek", 722}, + {"Aring", 722}, + {"Atilde", 722}, + {"B", 722}, + {"C", 722}, + {"Cacute", 722}, + {"Ccaron", 722}, + {"Ccedilla", 722}, + {"D", 722}, + {"Dcaron", 722}, + {"Dcroat", 722}, + {"Delta", 612}, + {"E", 667}, + {"Eacute", 667}, + {"Ecaron", 667}, + {"Ecircumflex", 667}, + {"Edieresis", 667}, + {"Edotaccent", 667}, + {"Egrave", 667}, + {"Emacron", 667}, + {"Eogonek", 667}, + {"Eth", 722}, + {"Euro", 556}, + {"F", 611}, + {"G", 778}, + {"Gbreve", 778}, + {"Gcommaaccent", 778}, + {"H", 722}, + {"I", 278}, + {"Iacute", 278}, + {"Icircumflex", 278}, + {"Idieresis", 278}, + {"Idotaccent", 278}, + {"Igrave", 278}, + {"Imacron", 278}, + {"Iogonek", 278}, + {"J", 556}, + {"K", 722}, + {"Kcommaaccent", 722}, + {"L", 611}, + {"Lacute", 611}, + {"Lcaron", 611}, + {"Lcommaaccent", 611}, + {"Lslash", 611}, + {"M", 833}, + {"N", 722}, + {"Nacute", 722}, + {"Ncaron", 722}, + {"Ncommaaccent", 722}, + {"Ntilde", 722}, + {"O", 778}, + {"OE", 1000}, + {"Oacute", 778}, + {"Ocircumflex", 778}, + {"Odieresis", 778}, + {"Ograve", 778}, + {"Ohungarumlaut", 778}, + {"Omacron", 778}, + {"Oslash", 778}, + {"Otilde", 778}, + {"P", 667}, + {"Q", 778}, + {"R", 722}, + {"Racute", 722}, + {"Rcaron", 722}, + {"Rcommaaccent", 722}, + {"S", 667}, + {"Sacute", 667}, + {"Scaron", 667}, + {"Scedilla", 667}, + {"Scommaaccent", 667}, + {"T", 611}, + {"Tcaron", 611}, + {"Tcommaaccent", 611}, + {"Thorn", 667}, + {"U", 722}, + {"Uacute", 722}, + {"Ucircumflex", 722}, + {"Udieresis", 722}, + {"Ugrave", 722}, + {"Uhungarumlaut", 722}, + {"Umacron", 722}, + {"Uogonek", 722}, + {"Uring", 722}, + {"V", 667}, + {"W", 944}, + {"X", 667}, + {"Y", 667}, + {"Yacute", 667}, + {"Ydieresis", 667}, + {"Z", 611}, + {"Zacute", 611}, + {"Zcaron", 611}, + {"Zdotaccent", 611}, + {"a", 556}, + {"aacute", 556}, + {"abreve", 556}, + {"acircumflex", 556}, + {"acute", 333}, + {"adieresis", 556}, + {"ae", 889}, + {"agrave", 556}, + {"amacron", 556}, + {"ampersand", 722}, + {"aogonek", 556}, + {"aring", 556}, + {"asciicircum", 584}, + {"asciitilde", 584}, + {"asterisk", 389}, + {"at", 975}, + {"atilde", 556}, + {"b", 611}, + {"backslash", 278}, + {"bar", 280}, + {"braceleft", 389}, + {"braceright", 389}, + {"bracketleft", 333}, + {"bracketright", 333}, + {"breve", 333}, + {"brokenbar", 280}, + {"bullet", 350}, + {"c", 556}, + {"cacute", 556}, + {"caron", 333}, + {"ccaron", 556}, + {"ccedilla", 556}, + {"cedilla", 333}, + {"cent", 556}, + {"circumflex", 333}, + {"colon", 333}, + {"comma", 278}, + {"commaaccent", 250}, + {"copyright", 737}, + {"currency", 556}, + {"d", 611}, + {"dagger", 556}, + {"daggerdbl", 556}, + {"dcaron", 743}, + {"dcroat", 611}, + {"degree", 400}, + {"dieresis", 333}, + {"divide", 584}, + {"dollar", 556}, + {"dotaccent", 333}, + {"dotlessi", 278}, + {"e", 556}, + {"eacute", 556}, + {"ecaron", 556}, + {"ecircumflex", 556}, + {"edieresis", 556}, + {"edotaccent", 556}, + {"egrave", 556}, + {"eight", 556}, + {"ellipsis", 1000}, + {"emacron", 556}, + {"emdash", 1000}, + {"endash", 556}, + {"eogonek", 556}, + {"equal", 584}, + {"eth", 611}, + {"exclam", 333}, + {"exclamdown", 333}, + {"f", 333}, + {"fi", 611}, + {"five", 556}, + {"fl", 611}, + {"florin", 556}, + {"four", 556}, + {"fraction", 167}, + {"g", 611}, + {"gbreve", 611}, + {"gcommaaccent", 611}, + {"germandbls", 611}, + {"grave", 333}, + {"greater", 584}, + {"greaterequal", 549}, + {"guillemotleft", 556}, + {"guillemotright", 556}, + {"guilsinglleft", 333}, + {"guilsinglright", 333}, + {"h", 611}, + {"hungarumlaut", 333}, + {"hyphen", 333}, + {"i", 278}, + {"iacute", 278}, + {"icircumflex", 278}, + {"idieresis", 278}, + {"igrave", 278}, + {"imacron", 278}, + {"iogonek", 278}, + {"j", 278}, + {"k", 556}, + {"kcommaaccent", 556}, + {"l", 278}, + {"lacute", 278}, + {"lcaron", 400}, + {"lcommaaccent", 278}, + {"less", 584}, + {"lessequal", 549}, + {"logicalnot", 584}, + {"lozenge", 494}, + {"lslash", 278}, + {"m", 889}, + {"macron", 333}, + {"minus", 584}, + {"mu", 611}, + {"multiply", 584}, + {"n", 611}, + {"nacute", 611}, + {"ncaron", 611}, + {"ncommaaccent", 611}, + {"nine", 556}, + {"notequal", 549}, + {"ntilde", 611}, + {"numbersign", 556}, + {"o", 611}, + {"oacute", 611}, + {"ocircumflex", 611}, + {"odieresis", 611}, + {"oe", 944}, + {"ogonek", 333}, + {"ograve", 611}, + {"ohungarumlaut", 611}, + {"omacron", 611}, + {"one", 556}, + {"onehalf", 834}, + {"onequarter", 834}, + {"onesuperior", 333}, + {"ordfeminine", 370}, + {"ordmasculine", 365}, + {"oslash", 611}, + {"otilde", 611}, + {"p", 611}, + {"paragraph", 556}, + {"parenleft", 333}, + {"parenright", 333}, + {"partialdiff", 494}, + {"percent", 889}, + {"period", 278}, + {"periodcentered", 278}, + {"perthousand", 1000}, + {"plus", 584}, + {"plusminus", 584}, + {"q", 611}, + {"question", 611}, + {"questiondown", 611}, + {"quotedbl", 474}, + {"quotedblbase", 500}, + {"quotedblleft", 500}, + {"quotedblright", 500}, + {"quoteleft", 278}, + {"quoteright", 278}, + {"quotesinglbase", 278}, + {"quotesingle", 238}, + {"r", 389}, + {"racute", 389}, + {"radical", 549}, + {"rcaron", 389}, + {"rcommaaccent", 389}, + {"registered", 737}, + {"ring", 333}, + {"s", 556}, + {"sacute", 556}, + {"scaron", 556}, + {"scedilla", 556}, + {"scommaaccent", 556}, + {"section", 556}, + {"semicolon", 333}, + {"seven", 556}, + {"six", 556}, + {"slash", 278}, + {"space", 278}, + {"sterling", 556}, + {"summation", 600}, + {"t", 333}, + {"tcaron", 389}, + {"tcommaaccent", 333}, + {"thorn", 611}, + {"three", 556}, + {"threequarters", 834}, + {"threesuperior", 333}, + {"tilde", 333}, + {"trademark", 1000}, + {"two", 556}, + {"twosuperior", 333}, + {"u", 611}, + {"uacute", 611}, + {"ucircumflex", 611}, + {"udieresis", 611}, + {"ugrave", 611}, + {"uhungarumlaut", 611}, + {"umacron", 611}, + {"underscore", 556}, + {"uogonek", 611}, + {"uring", 611}, + {"v", 556}, + {"w", 778}, + {"x", 556}, + {"y", 556}, + {"yacute", 556}, + {"ydieresis", 556}, + {"yen", 556}, + {"z", 500}, + {"zacute", 500}, + {"zcaron", 500}, + {"zdotaccent", 500}, + {"zero", 556}, +}; + +constexpr std::int16_t code_widths_helvetica_boldoblique[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 278, 333, 474, 556, 556, 889, 722, 278, 333, 333, 389, 584, 278, 333, 278, 278, + 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, + 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, + 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, + 278, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, + 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 333, 556, 556, 167, 556, 556, 556, 556, 238, 500, 556, 333, 333, 611, 611, + -1, 556, 556, 556, 278, -1, 556, 350, 278, 500, 500, 556, 1000, 1000, -1, 611, + -1, 333, 333, 333, 333, 333, 333, 333, 333, -1, 333, 333, -1, 333, 333, 333, + 1000, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1000, -1, 370, -1, -1, -1, -1, 611, 778, 1000, 365, -1, -1, -1, -1, + -1, 889, -1, -1, -1, 278, -1, -1, 278, 611, 944, 611, -1, -1, -1, -1, +}; + +constexpr GlyphWidth glyphs_times_roman[] = { + {"A", 722}, + {"AE", 889}, + {"Aacute", 722}, + {"Abreve", 722}, + {"Acircumflex", 722}, + {"Adieresis", 722}, + {"Agrave", 722}, + {"Amacron", 722}, + {"Aogonek", 722}, + {"Aring", 722}, + {"Atilde", 722}, + {"B", 667}, + {"C", 667}, + {"Cacute", 667}, + {"Ccaron", 667}, + {"Ccedilla", 667}, + {"D", 722}, + {"Dcaron", 722}, + {"Dcroat", 722}, + {"Delta", 612}, + {"E", 611}, + {"Eacute", 611}, + {"Ecaron", 611}, + {"Ecircumflex", 611}, + {"Edieresis", 611}, + {"Edotaccent", 611}, + {"Egrave", 611}, + {"Emacron", 611}, + {"Eogonek", 611}, + {"Eth", 722}, + {"Euro", 500}, + {"F", 556}, + {"G", 722}, + {"Gbreve", 722}, + {"Gcommaaccent", 722}, + {"H", 722}, + {"I", 333}, + {"Iacute", 333}, + {"Icircumflex", 333}, + {"Idieresis", 333}, + {"Idotaccent", 333}, + {"Igrave", 333}, + {"Imacron", 333}, + {"Iogonek", 333}, + {"J", 389}, + {"K", 722}, + {"Kcommaaccent", 722}, + {"L", 611}, + {"Lacute", 611}, + {"Lcaron", 611}, + {"Lcommaaccent", 611}, + {"Lslash", 611}, + {"M", 889}, + {"N", 722}, + {"Nacute", 722}, + {"Ncaron", 722}, + {"Ncommaaccent", 722}, + {"Ntilde", 722}, + {"O", 722}, + {"OE", 889}, + {"Oacute", 722}, + {"Ocircumflex", 722}, + {"Odieresis", 722}, + {"Ograve", 722}, + {"Ohungarumlaut", 722}, + {"Omacron", 722}, + {"Oslash", 722}, + {"Otilde", 722}, + {"P", 556}, + {"Q", 722}, + {"R", 667}, + {"Racute", 667}, + {"Rcaron", 667}, + {"Rcommaaccent", 667}, + {"S", 556}, + {"Sacute", 556}, + {"Scaron", 556}, + {"Scedilla", 556}, + {"Scommaaccent", 556}, + {"T", 611}, + {"Tcaron", 611}, + {"Tcommaaccent", 611}, + {"Thorn", 556}, + {"U", 722}, + {"Uacute", 722}, + {"Ucircumflex", 722}, + {"Udieresis", 722}, + {"Ugrave", 722}, + {"Uhungarumlaut", 722}, + {"Umacron", 722}, + {"Uogonek", 722}, + {"Uring", 722}, + {"V", 722}, + {"W", 944}, + {"X", 722}, + {"Y", 722}, + {"Yacute", 722}, + {"Ydieresis", 722}, + {"Z", 611}, + {"Zacute", 611}, + {"Zcaron", 611}, + {"Zdotaccent", 611}, + {"a", 444}, + {"aacute", 444}, + {"abreve", 444}, + {"acircumflex", 444}, + {"acute", 333}, + {"adieresis", 444}, + {"ae", 667}, + {"agrave", 444}, + {"amacron", 444}, + {"ampersand", 778}, + {"aogonek", 444}, + {"aring", 444}, + {"asciicircum", 469}, + {"asciitilde", 541}, + {"asterisk", 500}, + {"at", 921}, + {"atilde", 444}, + {"b", 500}, + {"backslash", 278}, + {"bar", 200}, + {"braceleft", 480}, + {"braceright", 480}, + {"bracketleft", 333}, + {"bracketright", 333}, + {"breve", 333}, + {"brokenbar", 200}, + {"bullet", 350}, + {"c", 444}, + {"cacute", 444}, + {"caron", 333}, + {"ccaron", 444}, + {"ccedilla", 444}, + {"cedilla", 333}, + {"cent", 500}, + {"circumflex", 333}, + {"colon", 278}, + {"comma", 250}, + {"commaaccent", 250}, + {"copyright", 760}, + {"currency", 500}, + {"d", 500}, + {"dagger", 500}, + {"daggerdbl", 500}, + {"dcaron", 588}, + {"dcroat", 500}, + {"degree", 400}, + {"dieresis", 333}, + {"divide", 564}, + {"dollar", 500}, + {"dotaccent", 333}, + {"dotlessi", 278}, + {"e", 444}, + {"eacute", 444}, + {"ecaron", 444}, + {"ecircumflex", 444}, + {"edieresis", 444}, + {"edotaccent", 444}, + {"egrave", 444}, + {"eight", 500}, + {"ellipsis", 1000}, + {"emacron", 444}, + {"emdash", 1000}, + {"endash", 500}, + {"eogonek", 444}, + {"equal", 564}, + {"eth", 500}, + {"exclam", 333}, + {"exclamdown", 333}, + {"f", 333}, + {"fi", 556}, + {"five", 500}, + {"fl", 556}, + {"florin", 500}, + {"four", 500}, + {"fraction", 167}, + {"g", 500}, + {"gbreve", 500}, + {"gcommaaccent", 500}, + {"germandbls", 500}, + {"grave", 333}, + {"greater", 564}, + {"greaterequal", 549}, + {"guillemotleft", 500}, + {"guillemotright", 500}, + {"guilsinglleft", 333}, + {"guilsinglright", 333}, + {"h", 500}, + {"hungarumlaut", 333}, + {"hyphen", 333}, + {"i", 278}, + {"iacute", 278}, + {"icircumflex", 278}, + {"idieresis", 278}, + {"igrave", 278}, + {"imacron", 278}, + {"iogonek", 278}, + {"j", 278}, + {"k", 500}, + {"kcommaaccent", 500}, + {"l", 278}, + {"lacute", 278}, + {"lcaron", 344}, + {"lcommaaccent", 278}, + {"less", 564}, + {"lessequal", 549}, + {"logicalnot", 564}, + {"lozenge", 471}, + {"lslash", 278}, + {"m", 778}, + {"macron", 333}, + {"minus", 564}, + {"mu", 500}, + {"multiply", 564}, + {"n", 500}, + {"nacute", 500}, + {"ncaron", 500}, + {"ncommaaccent", 500}, + {"nine", 500}, + {"notequal", 549}, + {"ntilde", 500}, + {"numbersign", 500}, + {"o", 500}, + {"oacute", 500}, + {"ocircumflex", 500}, + {"odieresis", 500}, + {"oe", 722}, + {"ogonek", 333}, + {"ograve", 500}, + {"ohungarumlaut", 500}, + {"omacron", 500}, + {"one", 500}, + {"onehalf", 750}, + {"onequarter", 750}, + {"onesuperior", 300}, + {"ordfeminine", 276}, + {"ordmasculine", 310}, + {"oslash", 500}, + {"otilde", 500}, + {"p", 500}, + {"paragraph", 453}, + {"parenleft", 333}, + {"parenright", 333}, + {"partialdiff", 476}, + {"percent", 833}, + {"period", 250}, + {"periodcentered", 250}, + {"perthousand", 1000}, + {"plus", 564}, + {"plusminus", 564}, + {"q", 500}, + {"question", 444}, + {"questiondown", 444}, + {"quotedbl", 408}, + {"quotedblbase", 444}, + {"quotedblleft", 444}, + {"quotedblright", 444}, + {"quoteleft", 333}, + {"quoteright", 333}, + {"quotesinglbase", 333}, + {"quotesingle", 180}, + {"r", 333}, + {"racute", 333}, + {"radical", 453}, + {"rcaron", 333}, + {"rcommaaccent", 333}, + {"registered", 760}, + {"ring", 333}, + {"s", 389}, + {"sacute", 389}, + {"scaron", 389}, + {"scedilla", 389}, + {"scommaaccent", 389}, + {"section", 500}, + {"semicolon", 278}, + {"seven", 500}, + {"six", 500}, + {"slash", 278}, + {"space", 250}, + {"sterling", 500}, + {"summation", 600}, + {"t", 278}, + {"tcaron", 326}, + {"tcommaaccent", 278}, + {"thorn", 500}, + {"three", 500}, + {"threequarters", 750}, + {"threesuperior", 300}, + {"tilde", 333}, + {"trademark", 980}, + {"two", 500}, + {"twosuperior", 300}, + {"u", 500}, + {"uacute", 500}, + {"ucircumflex", 500}, + {"udieresis", 500}, + {"ugrave", 500}, + {"uhungarumlaut", 500}, + {"umacron", 500}, + {"underscore", 500}, + {"uogonek", 500}, + {"uring", 500}, + {"v", 500}, + {"w", 722}, + {"x", 500}, + {"y", 500}, + {"yacute", 500}, + {"ydieresis", 500}, + {"yen", 500}, + {"z", 444}, + {"zacute", 444}, + {"zcaron", 444}, + {"zdotaccent", 444}, + {"zero", 500}, +}; + +constexpr std::int16_t code_widths_times_roman[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 250, 333, 408, 500, 500, 833, 778, 333, 333, 333, 500, 564, 250, 333, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 564, 564, 564, 444, + 921, 722, 667, 667, 722, 611, 556, 722, 722, 333, 389, 722, 611, 889, 722, 722, + 556, 722, 667, 556, 611, 722, 722, 944, 722, 722, 611, 333, 278, 333, 469, 500, + 333, 444, 500, 444, 500, 444, 333, 500, 500, 278, 278, 500, 278, 778, 500, 500, + 500, 500, 333, 389, 278, 500, 500, 722, 500, 500, 444, 480, 200, 480, 541, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 333, 500, 500, 167, 500, 500, 500, 500, 180, 444, 500, 333, 333, 556, 556, + -1, 500, 500, 500, 250, -1, 453, 350, 333, 444, 444, 500, 1000, 1000, -1, 444, + -1, 333, 333, 333, 333, 333, 333, 333, 333, -1, 333, 333, -1, 333, 333, 333, + 1000, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 889, -1, 276, -1, -1, -1, -1, 611, 722, 889, 310, -1, -1, -1, -1, + -1, 667, -1, -1, -1, 278, -1, -1, 278, 500, 722, 500, -1, -1, -1, -1, +}; + +constexpr GlyphWidth glyphs_times_bold[] = { + {"A", 722}, + {"AE", 1000}, + {"Aacute", 722}, + {"Abreve", 722}, + {"Acircumflex", 722}, + {"Adieresis", 722}, + {"Agrave", 722}, + {"Amacron", 722}, + {"Aogonek", 722}, + {"Aring", 722}, + {"Atilde", 722}, + {"B", 667}, + {"C", 722}, + {"Cacute", 722}, + {"Ccaron", 722}, + {"Ccedilla", 722}, + {"D", 722}, + {"Dcaron", 722}, + {"Dcroat", 722}, + {"Delta", 612}, + {"E", 667}, + {"Eacute", 667}, + {"Ecaron", 667}, + {"Ecircumflex", 667}, + {"Edieresis", 667}, + {"Edotaccent", 667}, + {"Egrave", 667}, + {"Emacron", 667}, + {"Eogonek", 667}, + {"Eth", 722}, + {"Euro", 500}, + {"F", 611}, + {"G", 778}, + {"Gbreve", 778}, + {"Gcommaaccent", 778}, + {"H", 778}, + {"I", 389}, + {"Iacute", 389}, + {"Icircumflex", 389}, + {"Idieresis", 389}, + {"Idotaccent", 389}, + {"Igrave", 389}, + {"Imacron", 389}, + {"Iogonek", 389}, + {"J", 500}, + {"K", 778}, + {"Kcommaaccent", 778}, + {"L", 667}, + {"Lacute", 667}, + {"Lcaron", 667}, + {"Lcommaaccent", 667}, + {"Lslash", 667}, + {"M", 944}, + {"N", 722}, + {"Nacute", 722}, + {"Ncaron", 722}, + {"Ncommaaccent", 722}, + {"Ntilde", 722}, + {"O", 778}, + {"OE", 1000}, + {"Oacute", 778}, + {"Ocircumflex", 778}, + {"Odieresis", 778}, + {"Ograve", 778}, + {"Ohungarumlaut", 778}, + {"Omacron", 778}, + {"Oslash", 778}, + {"Otilde", 778}, + {"P", 611}, + {"Q", 778}, + {"R", 722}, + {"Racute", 722}, + {"Rcaron", 722}, + {"Rcommaaccent", 722}, + {"S", 556}, + {"Sacute", 556}, + {"Scaron", 556}, + {"Scedilla", 556}, + {"Scommaaccent", 556}, + {"T", 667}, + {"Tcaron", 667}, + {"Tcommaaccent", 667}, + {"Thorn", 611}, + {"U", 722}, + {"Uacute", 722}, + {"Ucircumflex", 722}, + {"Udieresis", 722}, + {"Ugrave", 722}, + {"Uhungarumlaut", 722}, + {"Umacron", 722}, + {"Uogonek", 722}, + {"Uring", 722}, + {"V", 722}, + {"W", 1000}, + {"X", 722}, + {"Y", 722}, + {"Yacute", 722}, + {"Ydieresis", 722}, + {"Z", 667}, + {"Zacute", 667}, + {"Zcaron", 667}, + {"Zdotaccent", 667}, + {"a", 500}, + {"aacute", 500}, + {"abreve", 500}, + {"acircumflex", 500}, + {"acute", 333}, + {"adieresis", 500}, + {"ae", 722}, + {"agrave", 500}, + {"amacron", 500}, + {"ampersand", 833}, + {"aogonek", 500}, + {"aring", 500}, + {"asciicircum", 581}, + {"asciitilde", 520}, + {"asterisk", 500}, + {"at", 930}, + {"atilde", 500}, + {"b", 556}, + {"backslash", 278}, + {"bar", 220}, + {"braceleft", 394}, + {"braceright", 394}, + {"bracketleft", 333}, + {"bracketright", 333}, + {"breve", 333}, + {"brokenbar", 220}, + {"bullet", 350}, + {"c", 444}, + {"cacute", 444}, + {"caron", 333}, + {"ccaron", 444}, + {"ccedilla", 444}, + {"cedilla", 333}, + {"cent", 500}, + {"circumflex", 333}, + {"colon", 333}, + {"comma", 250}, + {"commaaccent", 250}, + {"copyright", 747}, + {"currency", 500}, + {"d", 556}, + {"dagger", 500}, + {"daggerdbl", 500}, + {"dcaron", 672}, + {"dcroat", 556}, + {"degree", 400}, + {"dieresis", 333}, + {"divide", 570}, + {"dollar", 500}, + {"dotaccent", 333}, + {"dotlessi", 278}, + {"e", 444}, + {"eacute", 444}, + {"ecaron", 444}, + {"ecircumflex", 444}, + {"edieresis", 444}, + {"edotaccent", 444}, + {"egrave", 444}, + {"eight", 500}, + {"ellipsis", 1000}, + {"emacron", 444}, + {"emdash", 1000}, + {"endash", 500}, + {"eogonek", 444}, + {"equal", 570}, + {"eth", 500}, + {"exclam", 333}, + {"exclamdown", 333}, + {"f", 333}, + {"fi", 556}, + {"five", 500}, + {"fl", 556}, + {"florin", 500}, + {"four", 500}, + {"fraction", 167}, + {"g", 500}, + {"gbreve", 500}, + {"gcommaaccent", 500}, + {"germandbls", 556}, + {"grave", 333}, + {"greater", 570}, + {"greaterequal", 549}, + {"guillemotleft", 500}, + {"guillemotright", 500}, + {"guilsinglleft", 333}, + {"guilsinglright", 333}, + {"h", 556}, + {"hungarumlaut", 333}, + {"hyphen", 333}, + {"i", 278}, + {"iacute", 278}, + {"icircumflex", 278}, + {"idieresis", 278}, + {"igrave", 278}, + {"imacron", 278}, + {"iogonek", 278}, + {"j", 333}, + {"k", 556}, + {"kcommaaccent", 556}, + {"l", 278}, + {"lacute", 278}, + {"lcaron", 394}, + {"lcommaaccent", 278}, + {"less", 570}, + {"lessequal", 549}, + {"logicalnot", 570}, + {"lozenge", 494}, + {"lslash", 278}, + {"m", 833}, + {"macron", 333}, + {"minus", 570}, + {"mu", 556}, + {"multiply", 570}, + {"n", 556}, + {"nacute", 556}, + {"ncaron", 556}, + {"ncommaaccent", 556}, + {"nine", 500}, + {"notequal", 549}, + {"ntilde", 556}, + {"numbersign", 500}, + {"o", 500}, + {"oacute", 500}, + {"ocircumflex", 500}, + {"odieresis", 500}, + {"oe", 722}, + {"ogonek", 333}, + {"ograve", 500}, + {"ohungarumlaut", 500}, + {"omacron", 500}, + {"one", 500}, + {"onehalf", 750}, + {"onequarter", 750}, + {"onesuperior", 300}, + {"ordfeminine", 300}, + {"ordmasculine", 330}, + {"oslash", 500}, + {"otilde", 500}, + {"p", 556}, + {"paragraph", 540}, + {"parenleft", 333}, + {"parenright", 333}, + {"partialdiff", 494}, + {"percent", 1000}, + {"period", 250}, + {"periodcentered", 250}, + {"perthousand", 1000}, + {"plus", 570}, + {"plusminus", 570}, + {"q", 556}, + {"question", 500}, + {"questiondown", 500}, + {"quotedbl", 555}, + {"quotedblbase", 500}, + {"quotedblleft", 500}, + {"quotedblright", 500}, + {"quoteleft", 333}, + {"quoteright", 333}, + {"quotesinglbase", 333}, + {"quotesingle", 278}, + {"r", 444}, + {"racute", 444}, + {"radical", 549}, + {"rcaron", 444}, + {"rcommaaccent", 444}, + {"registered", 747}, + {"ring", 333}, + {"s", 389}, + {"sacute", 389}, + {"scaron", 389}, + {"scedilla", 389}, + {"scommaaccent", 389}, + {"section", 500}, + {"semicolon", 333}, + {"seven", 500}, + {"six", 500}, + {"slash", 278}, + {"space", 250}, + {"sterling", 500}, + {"summation", 600}, + {"t", 333}, + {"tcaron", 416}, + {"tcommaaccent", 333}, + {"thorn", 556}, + {"three", 500}, + {"threequarters", 750}, + {"threesuperior", 300}, + {"tilde", 333}, + {"trademark", 1000}, + {"two", 500}, + {"twosuperior", 300}, + {"u", 556}, + {"uacute", 556}, + {"ucircumflex", 556}, + {"udieresis", 556}, + {"ugrave", 556}, + {"uhungarumlaut", 556}, + {"umacron", 556}, + {"underscore", 500}, + {"uogonek", 556}, + {"uring", 556}, + {"v", 500}, + {"w", 722}, + {"x", 500}, + {"y", 500}, + {"yacute", 500}, + {"ydieresis", 500}, + {"yen", 500}, + {"z", 444}, + {"zacute", 444}, + {"zcaron", 444}, + {"zdotaccent", 444}, + {"zero", 500}, +}; + +constexpr std::int16_t code_widths_times_bold[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 250, 333, 555, 500, 500, 1000, 833, 333, 333, 333, 500, 570, 250, 333, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, + 930, 722, 667, 722, 722, 667, 611, 778, 778, 389, 500, 778, 667, 944, 722, 778, + 611, 778, 722, 556, 667, 722, 722, 1000, 722, 722, 667, 333, 278, 333, 581, 500, + 333, 500, 556, 444, 556, 444, 333, 500, 556, 278, 333, 556, 278, 833, 556, 500, + 556, 556, 444, 389, 333, 556, 500, 722, 500, 500, 444, 394, 220, 394, 520, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 333, 500, 500, 167, 500, 500, 500, 500, 278, 500, 500, 333, 333, 556, 556, + -1, 500, 500, 500, 250, -1, 540, 350, 333, 500, 500, 500, 1000, 1000, -1, 500, + -1, 333, 333, 333, 333, 333, 333, 333, 333, -1, 333, 333, -1, 333, 333, 333, + 1000, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1000, -1, 300, -1, -1, -1, -1, 667, 778, 1000, 330, -1, -1, -1, -1, + -1, 722, -1, -1, -1, 278, -1, -1, 278, 500, 722, 556, -1, -1, -1, -1, +}; + +constexpr GlyphWidth glyphs_times_italic[] = { + {"A", 611}, + {"AE", 889}, + {"Aacute", 611}, + {"Abreve", 611}, + {"Acircumflex", 611}, + {"Adieresis", 611}, + {"Agrave", 611}, + {"Amacron", 611}, + {"Aogonek", 611}, + {"Aring", 611}, + {"Atilde", 611}, + {"B", 611}, + {"C", 667}, + {"Cacute", 667}, + {"Ccaron", 667}, + {"Ccedilla", 667}, + {"D", 722}, + {"Dcaron", 722}, + {"Dcroat", 722}, + {"Delta", 612}, + {"E", 611}, + {"Eacute", 611}, + {"Ecaron", 611}, + {"Ecircumflex", 611}, + {"Edieresis", 611}, + {"Edotaccent", 611}, + {"Egrave", 611}, + {"Emacron", 611}, + {"Eogonek", 611}, + {"Eth", 722}, + {"Euro", 500}, + {"F", 611}, + {"G", 722}, + {"Gbreve", 722}, + {"Gcommaaccent", 722}, + {"H", 722}, + {"I", 333}, + {"Iacute", 333}, + {"Icircumflex", 333}, + {"Idieresis", 333}, + {"Idotaccent", 333}, + {"Igrave", 333}, + {"Imacron", 333}, + {"Iogonek", 333}, + {"J", 444}, + {"K", 667}, + {"Kcommaaccent", 667}, + {"L", 556}, + {"Lacute", 556}, + {"Lcaron", 611}, + {"Lcommaaccent", 556}, + {"Lslash", 556}, + {"M", 833}, + {"N", 667}, + {"Nacute", 667}, + {"Ncaron", 667}, + {"Ncommaaccent", 667}, + {"Ntilde", 667}, + {"O", 722}, + {"OE", 944}, + {"Oacute", 722}, + {"Ocircumflex", 722}, + {"Odieresis", 722}, + {"Ograve", 722}, + {"Ohungarumlaut", 722}, + {"Omacron", 722}, + {"Oslash", 722}, + {"Otilde", 722}, + {"P", 611}, + {"Q", 722}, + {"R", 611}, + {"Racute", 611}, + {"Rcaron", 611}, + {"Rcommaaccent", 611}, + {"S", 500}, + {"Sacute", 500}, + {"Scaron", 500}, + {"Scedilla", 500}, + {"Scommaaccent", 500}, + {"T", 556}, + {"Tcaron", 556}, + {"Tcommaaccent", 556}, + {"Thorn", 611}, + {"U", 722}, + {"Uacute", 722}, + {"Ucircumflex", 722}, + {"Udieresis", 722}, + {"Ugrave", 722}, + {"Uhungarumlaut", 722}, + {"Umacron", 722}, + {"Uogonek", 722}, + {"Uring", 722}, + {"V", 611}, + {"W", 833}, + {"X", 611}, + {"Y", 556}, + {"Yacute", 556}, + {"Ydieresis", 556}, + {"Z", 556}, + {"Zacute", 556}, + {"Zcaron", 556}, + {"Zdotaccent", 556}, + {"a", 500}, + {"aacute", 500}, + {"abreve", 500}, + {"acircumflex", 500}, + {"acute", 333}, + {"adieresis", 500}, + {"ae", 667}, + {"agrave", 500}, + {"amacron", 500}, + {"ampersand", 778}, + {"aogonek", 500}, + {"aring", 500}, + {"asciicircum", 422}, + {"asciitilde", 541}, + {"asterisk", 500}, + {"at", 920}, + {"atilde", 500}, + {"b", 500}, + {"backslash", 278}, + {"bar", 275}, + {"braceleft", 400}, + {"braceright", 400}, + {"bracketleft", 389}, + {"bracketright", 389}, + {"breve", 333}, + {"brokenbar", 275}, + {"bullet", 350}, + {"c", 444}, + {"cacute", 444}, + {"caron", 333}, + {"ccaron", 444}, + {"ccedilla", 444}, + {"cedilla", 333}, + {"cent", 500}, + {"circumflex", 333}, + {"colon", 333}, + {"comma", 250}, + {"commaaccent", 250}, + {"copyright", 760}, + {"currency", 500}, + {"d", 500}, + {"dagger", 500}, + {"daggerdbl", 500}, + {"dcaron", 544}, + {"dcroat", 500}, + {"degree", 400}, + {"dieresis", 333}, + {"divide", 675}, + {"dollar", 500}, + {"dotaccent", 333}, + {"dotlessi", 278}, + {"e", 444}, + {"eacute", 444}, + {"ecaron", 444}, + {"ecircumflex", 444}, + {"edieresis", 444}, + {"edotaccent", 444}, + {"egrave", 444}, + {"eight", 500}, + {"ellipsis", 889}, + {"emacron", 444}, + {"emdash", 889}, + {"endash", 500}, + {"eogonek", 444}, + {"equal", 675}, + {"eth", 500}, + {"exclam", 333}, + {"exclamdown", 389}, + {"f", 278}, + {"fi", 500}, + {"five", 500}, + {"fl", 500}, + {"florin", 500}, + {"four", 500}, + {"fraction", 167}, + {"g", 500}, + {"gbreve", 500}, + {"gcommaaccent", 500}, + {"germandbls", 500}, + {"grave", 333}, + {"greater", 675}, + {"greaterequal", 549}, + {"guillemotleft", 500}, + {"guillemotright", 500}, + {"guilsinglleft", 333}, + {"guilsinglright", 333}, + {"h", 500}, + {"hungarumlaut", 333}, + {"hyphen", 333}, + {"i", 278}, + {"iacute", 278}, + {"icircumflex", 278}, + {"idieresis", 278}, + {"igrave", 278}, + {"imacron", 278}, + {"iogonek", 278}, + {"j", 278}, + {"k", 444}, + {"kcommaaccent", 444}, + {"l", 278}, + {"lacute", 278}, + {"lcaron", 300}, + {"lcommaaccent", 278}, + {"less", 675}, + {"lessequal", 549}, + {"logicalnot", 675}, + {"lozenge", 471}, + {"lslash", 278}, + {"m", 722}, + {"macron", 333}, + {"minus", 675}, + {"mu", 500}, + {"multiply", 675}, + {"n", 500}, + {"nacute", 500}, + {"ncaron", 500}, + {"ncommaaccent", 500}, + {"nine", 500}, + {"notequal", 549}, + {"ntilde", 500}, + {"numbersign", 500}, + {"o", 500}, + {"oacute", 500}, + {"ocircumflex", 500}, + {"odieresis", 500}, + {"oe", 667}, + {"ogonek", 333}, + {"ograve", 500}, + {"ohungarumlaut", 500}, + {"omacron", 500}, + {"one", 500}, + {"onehalf", 750}, + {"onequarter", 750}, + {"onesuperior", 300}, + {"ordfeminine", 276}, + {"ordmasculine", 310}, + {"oslash", 500}, + {"otilde", 500}, + {"p", 500}, + {"paragraph", 523}, + {"parenleft", 333}, + {"parenright", 333}, + {"partialdiff", 476}, + {"percent", 833}, + {"period", 250}, + {"periodcentered", 250}, + {"perthousand", 1000}, + {"plus", 675}, + {"plusminus", 675}, + {"q", 500}, + {"question", 500}, + {"questiondown", 500}, + {"quotedbl", 420}, + {"quotedblbase", 556}, + {"quotedblleft", 556}, + {"quotedblright", 556}, + {"quoteleft", 333}, + {"quoteright", 333}, + {"quotesinglbase", 333}, + {"quotesingle", 214}, + {"r", 389}, + {"racute", 389}, + {"radical", 453}, + {"rcaron", 389}, + {"rcommaaccent", 389}, + {"registered", 760}, + {"ring", 333}, + {"s", 389}, + {"sacute", 389}, + {"scaron", 389}, + {"scedilla", 389}, + {"scommaaccent", 389}, + {"section", 500}, + {"semicolon", 333}, + {"seven", 500}, + {"six", 500}, + {"slash", 278}, + {"space", 250}, + {"sterling", 500}, + {"summation", 600}, + {"t", 278}, + {"tcaron", 300}, + {"tcommaaccent", 278}, + {"thorn", 500}, + {"three", 500}, + {"threequarters", 750}, + {"threesuperior", 300}, + {"tilde", 333}, + {"trademark", 980}, + {"two", 500}, + {"twosuperior", 300}, + {"u", 500}, + {"uacute", 500}, + {"ucircumflex", 500}, + {"udieresis", 500}, + {"ugrave", 500}, + {"uhungarumlaut", 500}, + {"umacron", 500}, + {"underscore", 500}, + {"uogonek", 500}, + {"uring", 500}, + {"v", 444}, + {"w", 667}, + {"x", 444}, + {"y", 444}, + {"yacute", 444}, + {"ydieresis", 444}, + {"yen", 500}, + {"z", 389}, + {"zacute", 389}, + {"zcaron", 389}, + {"zdotaccent", 389}, + {"zero", 500}, +}; + +constexpr std::int16_t code_widths_times_italic[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 250, 333, 420, 500, 500, 833, 778, 333, 333, 333, 500, 675, 250, 333, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 675, 675, 675, 500, + 920, 611, 611, 667, 722, 611, 611, 722, 722, 333, 444, 667, 556, 833, 667, 722, + 611, 722, 611, 500, 556, 722, 611, 833, 611, 556, 556, 389, 278, 389, 422, 500, + 333, 500, 500, 444, 500, 444, 278, 500, 500, 278, 278, 444, 278, 722, 500, 500, + 500, 500, 389, 389, 278, 500, 444, 667, 444, 444, 389, 400, 275, 400, 541, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 389, 500, 500, 167, 500, 500, 500, 500, 214, 556, 500, 333, 333, 500, 500, + -1, 500, 500, 500, 250, -1, 523, 350, 333, 556, 556, 500, 889, 1000, -1, 500, + -1, 333, 333, 333, 333, 333, 333, 333, 333, -1, 333, 333, -1, 333, 333, 333, + 889, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 889, -1, 276, -1, -1, -1, -1, 556, 722, 944, 310, -1, -1, -1, -1, + -1, 667, -1, -1, -1, 278, -1, -1, 278, 500, 667, 500, -1, -1, -1, -1, +}; + +constexpr GlyphWidth glyphs_times_bolditalic[] = { + {"A", 667}, + {"AE", 944}, + {"Aacute", 667}, + {"Abreve", 667}, + {"Acircumflex", 667}, + {"Adieresis", 667}, + {"Agrave", 667}, + {"Amacron", 667}, + {"Aogonek", 667}, + {"Aring", 667}, + {"Atilde", 667}, + {"B", 667}, + {"C", 667}, + {"Cacute", 667}, + {"Ccaron", 667}, + {"Ccedilla", 667}, + {"D", 722}, + {"Dcaron", 722}, + {"Dcroat", 722}, + {"Delta", 612}, + {"E", 667}, + {"Eacute", 667}, + {"Ecaron", 667}, + {"Ecircumflex", 667}, + {"Edieresis", 667}, + {"Edotaccent", 667}, + {"Egrave", 667}, + {"Emacron", 667}, + {"Eogonek", 667}, + {"Eth", 722}, + {"Euro", 500}, + {"F", 667}, + {"G", 722}, + {"Gbreve", 722}, + {"Gcommaaccent", 722}, + {"H", 778}, + {"I", 389}, + {"Iacute", 389}, + {"Icircumflex", 389}, + {"Idieresis", 389}, + {"Idotaccent", 389}, + {"Igrave", 389}, + {"Imacron", 389}, + {"Iogonek", 389}, + {"J", 500}, + {"K", 667}, + {"Kcommaaccent", 667}, + {"L", 611}, + {"Lacute", 611}, + {"Lcaron", 611}, + {"Lcommaaccent", 611}, + {"Lslash", 611}, + {"M", 889}, + {"N", 722}, + {"Nacute", 722}, + {"Ncaron", 722}, + {"Ncommaaccent", 722}, + {"Ntilde", 722}, + {"O", 722}, + {"OE", 944}, + {"Oacute", 722}, + {"Ocircumflex", 722}, + {"Odieresis", 722}, + {"Ograve", 722}, + {"Ohungarumlaut", 722}, + {"Omacron", 722}, + {"Oslash", 722}, + {"Otilde", 722}, + {"P", 611}, + {"Q", 722}, + {"R", 667}, + {"Racute", 667}, + {"Rcaron", 667}, + {"Rcommaaccent", 667}, + {"S", 556}, + {"Sacute", 556}, + {"Scaron", 556}, + {"Scedilla", 556}, + {"Scommaaccent", 556}, + {"T", 611}, + {"Tcaron", 611}, + {"Tcommaaccent", 611}, + {"Thorn", 611}, + {"U", 722}, + {"Uacute", 722}, + {"Ucircumflex", 722}, + {"Udieresis", 722}, + {"Ugrave", 722}, + {"Uhungarumlaut", 722}, + {"Umacron", 722}, + {"Uogonek", 722}, + {"Uring", 722}, + {"V", 667}, + {"W", 889}, + {"X", 667}, + {"Y", 611}, + {"Yacute", 611}, + {"Ydieresis", 611}, + {"Z", 611}, + {"Zacute", 611}, + {"Zcaron", 611}, + {"Zdotaccent", 611}, + {"a", 500}, + {"aacute", 500}, + {"abreve", 500}, + {"acircumflex", 500}, + {"acute", 333}, + {"adieresis", 500}, + {"ae", 722}, + {"agrave", 500}, + {"amacron", 500}, + {"ampersand", 778}, + {"aogonek", 500}, + {"aring", 500}, + {"asciicircum", 570}, + {"asciitilde", 570}, + {"asterisk", 500}, + {"at", 832}, + {"atilde", 500}, + {"b", 500}, + {"backslash", 278}, + {"bar", 220}, + {"braceleft", 348}, + {"braceright", 348}, + {"bracketleft", 333}, + {"bracketright", 333}, + {"breve", 333}, + {"brokenbar", 220}, + {"bullet", 350}, + {"c", 444}, + {"cacute", 444}, + {"caron", 333}, + {"ccaron", 444}, + {"ccedilla", 444}, + {"cedilla", 333}, + {"cent", 500}, + {"circumflex", 333}, + {"colon", 333}, + {"comma", 250}, + {"commaaccent", 250}, + {"copyright", 747}, + {"currency", 500}, + {"d", 500}, + {"dagger", 500}, + {"daggerdbl", 500}, + {"dcaron", 608}, + {"dcroat", 500}, + {"degree", 400}, + {"dieresis", 333}, + {"divide", 570}, + {"dollar", 500}, + {"dotaccent", 333}, + {"dotlessi", 278}, + {"e", 444}, + {"eacute", 444}, + {"ecaron", 444}, + {"ecircumflex", 444}, + {"edieresis", 444}, + {"edotaccent", 444}, + {"egrave", 444}, + {"eight", 500}, + {"ellipsis", 1000}, + {"emacron", 444}, + {"emdash", 1000}, + {"endash", 500}, + {"eogonek", 444}, + {"equal", 570}, + {"eth", 500}, + {"exclam", 389}, + {"exclamdown", 389}, + {"f", 333}, + {"fi", 556}, + {"five", 500}, + {"fl", 556}, + {"florin", 500}, + {"four", 500}, + {"fraction", 167}, + {"g", 500}, + {"gbreve", 500}, + {"gcommaaccent", 500}, + {"germandbls", 500}, + {"grave", 333}, + {"greater", 570}, + {"greaterequal", 549}, + {"guillemotleft", 500}, + {"guillemotright", 500}, + {"guilsinglleft", 333}, + {"guilsinglright", 333}, + {"h", 556}, + {"hungarumlaut", 333}, + {"hyphen", 333}, + {"i", 278}, + {"iacute", 278}, + {"icircumflex", 278}, + {"idieresis", 278}, + {"igrave", 278}, + {"imacron", 278}, + {"iogonek", 278}, + {"j", 278}, + {"k", 500}, + {"kcommaaccent", 500}, + {"l", 278}, + {"lacute", 278}, + {"lcaron", 382}, + {"lcommaaccent", 278}, + {"less", 570}, + {"lessequal", 549}, + {"logicalnot", 606}, + {"lozenge", 494}, + {"lslash", 278}, + {"m", 778}, + {"macron", 333}, + {"minus", 606}, + {"mu", 576}, + {"multiply", 570}, + {"n", 556}, + {"nacute", 556}, + {"ncaron", 556}, + {"ncommaaccent", 556}, + {"nine", 500}, + {"notequal", 549}, + {"ntilde", 556}, + {"numbersign", 500}, + {"o", 500}, + {"oacute", 500}, + {"ocircumflex", 500}, + {"odieresis", 500}, + {"oe", 722}, + {"ogonek", 333}, + {"ograve", 500}, + {"ohungarumlaut", 500}, + {"omacron", 500}, + {"one", 500}, + {"onehalf", 750}, + {"onequarter", 750}, + {"onesuperior", 300}, + {"ordfeminine", 266}, + {"ordmasculine", 300}, + {"oslash", 500}, + {"otilde", 500}, + {"p", 500}, + {"paragraph", 500}, + {"parenleft", 333}, + {"parenright", 333}, + {"partialdiff", 494}, + {"percent", 833}, + {"period", 250}, + {"periodcentered", 250}, + {"perthousand", 1000}, + {"plus", 570}, + {"plusminus", 570}, + {"q", 500}, + {"question", 500}, + {"questiondown", 500}, + {"quotedbl", 555}, + {"quotedblbase", 500}, + {"quotedblleft", 500}, + {"quotedblright", 500}, + {"quoteleft", 333}, + {"quoteright", 333}, + {"quotesinglbase", 333}, + {"quotesingle", 278}, + {"r", 389}, + {"racute", 389}, + {"radical", 549}, + {"rcaron", 389}, + {"rcommaaccent", 389}, + {"registered", 747}, + {"ring", 333}, + {"s", 389}, + {"sacute", 389}, + {"scaron", 389}, + {"scedilla", 389}, + {"scommaaccent", 389}, + {"section", 500}, + {"semicolon", 333}, + {"seven", 500}, + {"six", 500}, + {"slash", 278}, + {"space", 250}, + {"sterling", 500}, + {"summation", 600}, + {"t", 278}, + {"tcaron", 366}, + {"tcommaaccent", 278}, + {"thorn", 500}, + {"three", 500}, + {"threequarters", 750}, + {"threesuperior", 300}, + {"tilde", 333}, + {"trademark", 1000}, + {"two", 500}, + {"twosuperior", 300}, + {"u", 556}, + {"uacute", 556}, + {"ucircumflex", 556}, + {"udieresis", 556}, + {"ugrave", 556}, + {"uhungarumlaut", 556}, + {"umacron", 556}, + {"underscore", 500}, + {"uogonek", 556}, + {"uring", 556}, + {"v", 444}, + {"w", 667}, + {"x", 500}, + {"y", 444}, + {"yacute", 444}, + {"ydieresis", 444}, + {"yen", 500}, + {"z", 389}, + {"zacute", 389}, + {"zcaron", 389}, + {"zdotaccent", 389}, + {"zero", 500}, +}; + +constexpr std::int16_t code_widths_times_bolditalic[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 250, 389, 555, 500, 500, 833, 778, 333, 333, 333, 500, 570, 250, 333, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, + 832, 667, 667, 667, 722, 667, 667, 722, 778, 389, 500, 667, 611, 889, 722, 722, + 611, 722, 667, 556, 611, 722, 667, 889, 667, 611, 611, 333, 278, 333, 570, 500, + 333, 500, 500, 444, 500, 444, 333, 500, 556, 278, 278, 500, 278, 778, 556, 500, + 500, 500, 389, 389, 278, 556, 444, 667, 500, 444, 389, 348, 220, 348, 570, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 389, 500, 500, 167, 500, 500, 500, 500, 278, 500, 500, 333, 333, 556, 556, + -1, 500, 500, 500, 250, -1, 500, 350, 333, 500, 500, 500, 1000, 1000, -1, 500, + -1, 333, 333, 333, 333, 333, 333, 333, 333, -1, 333, 333, -1, 333, 333, 333, + 1000, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 944, -1, 266, -1, -1, -1, -1, 611, 722, 944, 300, -1, -1, -1, -1, + -1, 722, -1, -1, -1, 278, -1, -1, 278, 500, 722, 500, -1, -1, -1, -1, +}; + +constexpr GlyphWidth glyphs_courier[] = { + {"A", 600}, + {"AE", 600}, + {"Aacute", 600}, + {"Abreve", 600}, + {"Acircumflex", 600}, + {"Adieresis", 600}, + {"Agrave", 600}, + {"Amacron", 600}, + {"Aogonek", 600}, + {"Aring", 600}, + {"Atilde", 600}, + {"B", 600}, + {"C", 600}, + {"Cacute", 600}, + {"Ccaron", 600}, + {"Ccedilla", 600}, + {"D", 600}, + {"Dcaron", 600}, + {"Dcroat", 600}, + {"Delta", 600}, + {"E", 600}, + {"Eacute", 600}, + {"Ecaron", 600}, + {"Ecircumflex", 600}, + {"Edieresis", 600}, + {"Edotaccent", 600}, + {"Egrave", 600}, + {"Emacron", 600}, + {"Eogonek", 600}, + {"Eth", 600}, + {"Euro", 600}, + {"F", 600}, + {"G", 600}, + {"Gbreve", 600}, + {"Gcommaaccent", 600}, + {"H", 600}, + {"I", 600}, + {"Iacute", 600}, + {"Icircumflex", 600}, + {"Idieresis", 600}, + {"Idotaccent", 600}, + {"Igrave", 600}, + {"Imacron", 600}, + {"Iogonek", 600}, + {"J", 600}, + {"K", 600}, + {"Kcommaaccent", 600}, + {"L", 600}, + {"Lacute", 600}, + {"Lcaron", 600}, + {"Lcommaaccent", 600}, + {"Lslash", 600}, + {"M", 600}, + {"N", 600}, + {"Nacute", 600}, + {"Ncaron", 600}, + {"Ncommaaccent", 600}, + {"Ntilde", 600}, + {"O", 600}, + {"OE", 600}, + {"Oacute", 600}, + {"Ocircumflex", 600}, + {"Odieresis", 600}, + {"Ograve", 600}, + {"Ohungarumlaut", 600}, + {"Omacron", 600}, + {"Oslash", 600}, + {"Otilde", 600}, + {"P", 600}, + {"Q", 600}, + {"R", 600}, + {"Racute", 600}, + {"Rcaron", 600}, + {"Rcommaaccent", 600}, + {"S", 600}, + {"Sacute", 600}, + {"Scaron", 600}, + {"Scedilla", 600}, + {"Scommaaccent", 600}, + {"T", 600}, + {"Tcaron", 600}, + {"Tcommaaccent", 600}, + {"Thorn", 600}, + {"U", 600}, + {"Uacute", 600}, + {"Ucircumflex", 600}, + {"Udieresis", 600}, + {"Ugrave", 600}, + {"Uhungarumlaut", 600}, + {"Umacron", 600}, + {"Uogonek", 600}, + {"Uring", 600}, + {"V", 600}, + {"W", 600}, + {"X", 600}, + {"Y", 600}, + {"Yacute", 600}, + {"Ydieresis", 600}, + {"Z", 600}, + {"Zacute", 600}, + {"Zcaron", 600}, + {"Zdotaccent", 600}, + {"a", 600}, + {"aacute", 600}, + {"abreve", 600}, + {"acircumflex", 600}, + {"acute", 600}, + {"adieresis", 600}, + {"ae", 600}, + {"agrave", 600}, + {"amacron", 600}, + {"ampersand", 600}, + {"aogonek", 600}, + {"aring", 600}, + {"asciicircum", 600}, + {"asciitilde", 600}, + {"asterisk", 600}, + {"at", 600}, + {"atilde", 600}, + {"b", 600}, + {"backslash", 600}, + {"bar", 600}, + {"braceleft", 600}, + {"braceright", 600}, + {"bracketleft", 600}, + {"bracketright", 600}, + {"breve", 600}, + {"brokenbar", 600}, + {"bullet", 600}, + {"c", 600}, + {"cacute", 600}, + {"caron", 600}, + {"ccaron", 600}, + {"ccedilla", 600}, + {"cedilla", 600}, + {"cent", 600}, + {"circumflex", 600}, + {"colon", 600}, + {"comma", 600}, + {"commaaccent", 600}, + {"copyright", 600}, + {"currency", 600}, + {"d", 600}, + {"dagger", 600}, + {"daggerdbl", 600}, + {"dcaron", 600}, + {"dcroat", 600}, + {"degree", 600}, + {"dieresis", 600}, + {"divide", 600}, + {"dollar", 600}, + {"dotaccent", 600}, + {"dotlessi", 600}, + {"e", 600}, + {"eacute", 600}, + {"ecaron", 600}, + {"ecircumflex", 600}, + {"edieresis", 600}, + {"edotaccent", 600}, + {"egrave", 600}, + {"eight", 600}, + {"ellipsis", 600}, + {"emacron", 600}, + {"emdash", 600}, + {"endash", 600}, + {"eogonek", 600}, + {"equal", 600}, + {"eth", 600}, + {"exclam", 600}, + {"exclamdown", 600}, + {"f", 600}, + {"fi", 600}, + {"five", 600}, + {"fl", 600}, + {"florin", 600}, + {"four", 600}, + {"fraction", 600}, + {"g", 600}, + {"gbreve", 600}, + {"gcommaaccent", 600}, + {"germandbls", 600}, + {"grave", 600}, + {"greater", 600}, + {"greaterequal", 600}, + {"guillemotleft", 600}, + {"guillemotright", 600}, + {"guilsinglleft", 600}, + {"guilsinglright", 600}, + {"h", 600}, + {"hungarumlaut", 600}, + {"hyphen", 600}, + {"i", 600}, + {"iacute", 600}, + {"icircumflex", 600}, + {"idieresis", 600}, + {"igrave", 600}, + {"imacron", 600}, + {"iogonek", 600}, + {"j", 600}, + {"k", 600}, + {"kcommaaccent", 600}, + {"l", 600}, + {"lacute", 600}, + {"lcaron", 600}, + {"lcommaaccent", 600}, + {"less", 600}, + {"lessequal", 600}, + {"logicalnot", 600}, + {"lozenge", 600}, + {"lslash", 600}, + {"m", 600}, + {"macron", 600}, + {"minus", 600}, + {"mu", 600}, + {"multiply", 600}, + {"n", 600}, + {"nacute", 600}, + {"ncaron", 600}, + {"ncommaaccent", 600}, + {"nine", 600}, + {"notequal", 600}, + {"ntilde", 600}, + {"numbersign", 600}, + {"o", 600}, + {"oacute", 600}, + {"ocircumflex", 600}, + {"odieresis", 600}, + {"oe", 600}, + {"ogonek", 600}, + {"ograve", 600}, + {"ohungarumlaut", 600}, + {"omacron", 600}, + {"one", 600}, + {"onehalf", 600}, + {"onequarter", 600}, + {"onesuperior", 600}, + {"ordfeminine", 600}, + {"ordmasculine", 600}, + {"oslash", 600}, + {"otilde", 600}, + {"p", 600}, + {"paragraph", 600}, + {"parenleft", 600}, + {"parenright", 600}, + {"partialdiff", 600}, + {"percent", 600}, + {"period", 600}, + {"periodcentered", 600}, + {"perthousand", 600}, + {"plus", 600}, + {"plusminus", 600}, + {"q", 600}, + {"question", 600}, + {"questiondown", 600}, + {"quotedbl", 600}, + {"quotedblbase", 600}, + {"quotedblleft", 600}, + {"quotedblright", 600}, + {"quoteleft", 600}, + {"quoteright", 600}, + {"quotesinglbase", 600}, + {"quotesingle", 600}, + {"r", 600}, + {"racute", 600}, + {"radical", 600}, + {"rcaron", 600}, + {"rcommaaccent", 600}, + {"registered", 600}, + {"ring", 600}, + {"s", 600}, + {"sacute", 600}, + {"scaron", 600}, + {"scedilla", 600}, + {"scommaaccent", 600}, + {"section", 600}, + {"semicolon", 600}, + {"seven", 600}, + {"six", 600}, + {"slash", 600}, + {"space", 600}, + {"sterling", 600}, + {"summation", 600}, + {"t", 600}, + {"tcaron", 600}, + {"tcommaaccent", 600}, + {"thorn", 600}, + {"three", 600}, + {"threequarters", 600}, + {"threesuperior", 600}, + {"tilde", 600}, + {"trademark", 600}, + {"two", 600}, + {"twosuperior", 600}, + {"u", 600}, + {"uacute", 600}, + {"ucircumflex", 600}, + {"udieresis", 600}, + {"ugrave", 600}, + {"uhungarumlaut", 600}, + {"umacron", 600}, + {"underscore", 600}, + {"uogonek", 600}, + {"uring", 600}, + {"v", 600}, + {"w", 600}, + {"x", 600}, + {"y", 600}, + {"yacute", 600}, + {"ydieresis", 600}, + {"yen", 600}, + {"z", 600}, + {"zacute", 600}, + {"zcaron", 600}, + {"zdotaccent", 600}, + {"zero", 600}, +}; + +constexpr std::int16_t code_widths_courier[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + -1, 600, 600, 600, 600, -1, 600, 600, 600, 600, 600, 600, 600, 600, -1, 600, + -1, 600, 600, 600, 600, 600, 600, 600, 600, -1, 600, 600, -1, 600, 600, 600, + 600, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 600, -1, 600, -1, -1, -1, -1, 600, 600, 600, 600, -1, -1, -1, -1, + -1, 600, -1, -1, -1, 600, -1, -1, 600, 600, 600, 600, -1, -1, -1, -1, +}; + +constexpr GlyphWidth glyphs_courier_bold[] = { + {"A", 600}, + {"AE", 600}, + {"Aacute", 600}, + {"Abreve", 600}, + {"Acircumflex", 600}, + {"Adieresis", 600}, + {"Agrave", 600}, + {"Amacron", 600}, + {"Aogonek", 600}, + {"Aring", 600}, + {"Atilde", 600}, + {"B", 600}, + {"C", 600}, + {"Cacute", 600}, + {"Ccaron", 600}, + {"Ccedilla", 600}, + {"D", 600}, + {"Dcaron", 600}, + {"Dcroat", 600}, + {"Delta", 600}, + {"E", 600}, + {"Eacute", 600}, + {"Ecaron", 600}, + {"Ecircumflex", 600}, + {"Edieresis", 600}, + {"Edotaccent", 600}, + {"Egrave", 600}, + {"Emacron", 600}, + {"Eogonek", 600}, + {"Eth", 600}, + {"Euro", 600}, + {"F", 600}, + {"G", 600}, + {"Gbreve", 600}, + {"Gcommaaccent", 600}, + {"H", 600}, + {"I", 600}, + {"Iacute", 600}, + {"Icircumflex", 600}, + {"Idieresis", 600}, + {"Idotaccent", 600}, + {"Igrave", 600}, + {"Imacron", 600}, + {"Iogonek", 600}, + {"J", 600}, + {"K", 600}, + {"Kcommaaccent", 600}, + {"L", 600}, + {"Lacute", 600}, + {"Lcaron", 600}, + {"Lcommaaccent", 600}, + {"Lslash", 600}, + {"M", 600}, + {"N", 600}, + {"Nacute", 600}, + {"Ncaron", 600}, + {"Ncommaaccent", 600}, + {"Ntilde", 600}, + {"O", 600}, + {"OE", 600}, + {"Oacute", 600}, + {"Ocircumflex", 600}, + {"Odieresis", 600}, + {"Ograve", 600}, + {"Ohungarumlaut", 600}, + {"Omacron", 600}, + {"Oslash", 600}, + {"Otilde", 600}, + {"P", 600}, + {"Q", 600}, + {"R", 600}, + {"Racute", 600}, + {"Rcaron", 600}, + {"Rcommaaccent", 600}, + {"S", 600}, + {"Sacute", 600}, + {"Scaron", 600}, + {"Scedilla", 600}, + {"Scommaaccent", 600}, + {"T", 600}, + {"Tcaron", 600}, + {"Tcommaaccent", 600}, + {"Thorn", 600}, + {"U", 600}, + {"Uacute", 600}, + {"Ucircumflex", 600}, + {"Udieresis", 600}, + {"Ugrave", 600}, + {"Uhungarumlaut", 600}, + {"Umacron", 600}, + {"Uogonek", 600}, + {"Uring", 600}, + {"V", 600}, + {"W", 600}, + {"X", 600}, + {"Y", 600}, + {"Yacute", 600}, + {"Ydieresis", 600}, + {"Z", 600}, + {"Zacute", 600}, + {"Zcaron", 600}, + {"Zdotaccent", 600}, + {"a", 600}, + {"aacute", 600}, + {"abreve", 600}, + {"acircumflex", 600}, + {"acute", 600}, + {"adieresis", 600}, + {"ae", 600}, + {"agrave", 600}, + {"amacron", 600}, + {"ampersand", 600}, + {"aogonek", 600}, + {"aring", 600}, + {"asciicircum", 600}, + {"asciitilde", 600}, + {"asterisk", 600}, + {"at", 600}, + {"atilde", 600}, + {"b", 600}, + {"backslash", 600}, + {"bar", 600}, + {"braceleft", 600}, + {"braceright", 600}, + {"bracketleft", 600}, + {"bracketright", 600}, + {"breve", 600}, + {"brokenbar", 600}, + {"bullet", 600}, + {"c", 600}, + {"cacute", 600}, + {"caron", 600}, + {"ccaron", 600}, + {"ccedilla", 600}, + {"cedilla", 600}, + {"cent", 600}, + {"circumflex", 600}, + {"colon", 600}, + {"comma", 600}, + {"commaaccent", 600}, + {"copyright", 600}, + {"currency", 600}, + {"d", 600}, + {"dagger", 600}, + {"daggerdbl", 600}, + {"dcaron", 600}, + {"dcroat", 600}, + {"degree", 600}, + {"dieresis", 600}, + {"divide", 600}, + {"dollar", 600}, + {"dotaccent", 600}, + {"dotlessi", 600}, + {"e", 600}, + {"eacute", 600}, + {"ecaron", 600}, + {"ecircumflex", 600}, + {"edieresis", 600}, + {"edotaccent", 600}, + {"egrave", 600}, + {"eight", 600}, + {"ellipsis", 600}, + {"emacron", 600}, + {"emdash", 600}, + {"endash", 600}, + {"eogonek", 600}, + {"equal", 600}, + {"eth", 600}, + {"exclam", 600}, + {"exclamdown", 600}, + {"f", 600}, + {"fi", 600}, + {"five", 600}, + {"fl", 600}, + {"florin", 600}, + {"four", 600}, + {"fraction", 600}, + {"g", 600}, + {"gbreve", 600}, + {"gcommaaccent", 600}, + {"germandbls", 600}, + {"grave", 600}, + {"greater", 600}, + {"greaterequal", 600}, + {"guillemotleft", 600}, + {"guillemotright", 600}, + {"guilsinglleft", 600}, + {"guilsinglright", 600}, + {"h", 600}, + {"hungarumlaut", 600}, + {"hyphen", 600}, + {"i", 600}, + {"iacute", 600}, + {"icircumflex", 600}, + {"idieresis", 600}, + {"igrave", 600}, + {"imacron", 600}, + {"iogonek", 600}, + {"j", 600}, + {"k", 600}, + {"kcommaaccent", 600}, + {"l", 600}, + {"lacute", 600}, + {"lcaron", 600}, + {"lcommaaccent", 600}, + {"less", 600}, + {"lessequal", 600}, + {"logicalnot", 600}, + {"lozenge", 600}, + {"lslash", 600}, + {"m", 600}, + {"macron", 600}, + {"minus", 600}, + {"mu", 600}, + {"multiply", 600}, + {"n", 600}, + {"nacute", 600}, + {"ncaron", 600}, + {"ncommaaccent", 600}, + {"nine", 600}, + {"notequal", 600}, + {"ntilde", 600}, + {"numbersign", 600}, + {"o", 600}, + {"oacute", 600}, + {"ocircumflex", 600}, + {"odieresis", 600}, + {"oe", 600}, + {"ogonek", 600}, + {"ograve", 600}, + {"ohungarumlaut", 600}, + {"omacron", 600}, + {"one", 600}, + {"onehalf", 600}, + {"onequarter", 600}, + {"onesuperior", 600}, + {"ordfeminine", 600}, + {"ordmasculine", 600}, + {"oslash", 600}, + {"otilde", 600}, + {"p", 600}, + {"paragraph", 600}, + {"parenleft", 600}, + {"parenright", 600}, + {"partialdiff", 600}, + {"percent", 600}, + {"period", 600}, + {"periodcentered", 600}, + {"perthousand", 600}, + {"plus", 600}, + {"plusminus", 600}, + {"q", 600}, + {"question", 600}, + {"questiondown", 600}, + {"quotedbl", 600}, + {"quotedblbase", 600}, + {"quotedblleft", 600}, + {"quotedblright", 600}, + {"quoteleft", 600}, + {"quoteright", 600}, + {"quotesinglbase", 600}, + {"quotesingle", 600}, + {"r", 600}, + {"racute", 600}, + {"radical", 600}, + {"rcaron", 600}, + {"rcommaaccent", 600}, + {"registered", 600}, + {"ring", 600}, + {"s", 600}, + {"sacute", 600}, + {"scaron", 600}, + {"scedilla", 600}, + {"scommaaccent", 600}, + {"section", 600}, + {"semicolon", 600}, + {"seven", 600}, + {"six", 600}, + {"slash", 600}, + {"space", 600}, + {"sterling", 600}, + {"summation", 600}, + {"t", 600}, + {"tcaron", 600}, + {"tcommaaccent", 600}, + {"thorn", 600}, + {"three", 600}, + {"threequarters", 600}, + {"threesuperior", 600}, + {"tilde", 600}, + {"trademark", 600}, + {"two", 600}, + {"twosuperior", 600}, + {"u", 600}, + {"uacute", 600}, + {"ucircumflex", 600}, + {"udieresis", 600}, + {"ugrave", 600}, + {"uhungarumlaut", 600}, + {"umacron", 600}, + {"underscore", 600}, + {"uogonek", 600}, + {"uring", 600}, + {"v", 600}, + {"w", 600}, + {"x", 600}, + {"y", 600}, + {"yacute", 600}, + {"ydieresis", 600}, + {"yen", 600}, + {"z", 600}, + {"zacute", 600}, + {"zcaron", 600}, + {"zdotaccent", 600}, + {"zero", 600}, +}; + +constexpr std::int16_t code_widths_courier_bold[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + -1, 600, 600, 600, 600, -1, 600, 600, 600, 600, 600, 600, 600, 600, -1, 600, + -1, 600, 600, 600, 600, 600, 600, 600, 600, -1, 600, 600, -1, 600, 600, 600, + 600, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 600, -1, 600, -1, -1, -1, -1, 600, 600, 600, 600, -1, -1, -1, -1, + -1, 600, -1, -1, -1, 600, -1, -1, 600, 600, 600, 600, -1, -1, -1, -1, +}; + +constexpr GlyphWidth glyphs_courier_oblique[] = { + {"A", 600}, + {"AE", 600}, + {"Aacute", 600}, + {"Abreve", 600}, + {"Acircumflex", 600}, + {"Adieresis", 600}, + {"Agrave", 600}, + {"Amacron", 600}, + {"Aogonek", 600}, + {"Aring", 600}, + {"Atilde", 600}, + {"B", 600}, + {"C", 600}, + {"Cacute", 600}, + {"Ccaron", 600}, + {"Ccedilla", 600}, + {"D", 600}, + {"Dcaron", 600}, + {"Dcroat", 600}, + {"Delta", 600}, + {"E", 600}, + {"Eacute", 600}, + {"Ecaron", 600}, + {"Ecircumflex", 600}, + {"Edieresis", 600}, + {"Edotaccent", 600}, + {"Egrave", 600}, + {"Emacron", 600}, + {"Eogonek", 600}, + {"Eth", 600}, + {"Euro", 600}, + {"F", 600}, + {"G", 600}, + {"Gbreve", 600}, + {"Gcommaaccent", 600}, + {"H", 600}, + {"I", 600}, + {"Iacute", 600}, + {"Icircumflex", 600}, + {"Idieresis", 600}, + {"Idotaccent", 600}, + {"Igrave", 600}, + {"Imacron", 600}, + {"Iogonek", 600}, + {"J", 600}, + {"K", 600}, + {"Kcommaaccent", 600}, + {"L", 600}, + {"Lacute", 600}, + {"Lcaron", 600}, + {"Lcommaaccent", 600}, + {"Lslash", 600}, + {"M", 600}, + {"N", 600}, + {"Nacute", 600}, + {"Ncaron", 600}, + {"Ncommaaccent", 600}, + {"Ntilde", 600}, + {"O", 600}, + {"OE", 600}, + {"Oacute", 600}, + {"Ocircumflex", 600}, + {"Odieresis", 600}, + {"Ograve", 600}, + {"Ohungarumlaut", 600}, + {"Omacron", 600}, + {"Oslash", 600}, + {"Otilde", 600}, + {"P", 600}, + {"Q", 600}, + {"R", 600}, + {"Racute", 600}, + {"Rcaron", 600}, + {"Rcommaaccent", 600}, + {"S", 600}, + {"Sacute", 600}, + {"Scaron", 600}, + {"Scedilla", 600}, + {"Scommaaccent", 600}, + {"T", 600}, + {"Tcaron", 600}, + {"Tcommaaccent", 600}, + {"Thorn", 600}, + {"U", 600}, + {"Uacute", 600}, + {"Ucircumflex", 600}, + {"Udieresis", 600}, + {"Ugrave", 600}, + {"Uhungarumlaut", 600}, + {"Umacron", 600}, + {"Uogonek", 600}, + {"Uring", 600}, + {"V", 600}, + {"W", 600}, + {"X", 600}, + {"Y", 600}, + {"Yacute", 600}, + {"Ydieresis", 600}, + {"Z", 600}, + {"Zacute", 600}, + {"Zcaron", 600}, + {"Zdotaccent", 600}, + {"a", 600}, + {"aacute", 600}, + {"abreve", 600}, + {"acircumflex", 600}, + {"acute", 600}, + {"adieresis", 600}, + {"ae", 600}, + {"agrave", 600}, + {"amacron", 600}, + {"ampersand", 600}, + {"aogonek", 600}, + {"aring", 600}, + {"asciicircum", 600}, + {"asciitilde", 600}, + {"asterisk", 600}, + {"at", 600}, + {"atilde", 600}, + {"b", 600}, + {"backslash", 600}, + {"bar", 600}, + {"braceleft", 600}, + {"braceright", 600}, + {"bracketleft", 600}, + {"bracketright", 600}, + {"breve", 600}, + {"brokenbar", 600}, + {"bullet", 600}, + {"c", 600}, + {"cacute", 600}, + {"caron", 600}, + {"ccaron", 600}, + {"ccedilla", 600}, + {"cedilla", 600}, + {"cent", 600}, + {"circumflex", 600}, + {"colon", 600}, + {"comma", 600}, + {"commaaccent", 600}, + {"copyright", 600}, + {"currency", 600}, + {"d", 600}, + {"dagger", 600}, + {"daggerdbl", 600}, + {"dcaron", 600}, + {"dcroat", 600}, + {"degree", 600}, + {"dieresis", 600}, + {"divide", 600}, + {"dollar", 600}, + {"dotaccent", 600}, + {"dotlessi", 600}, + {"e", 600}, + {"eacute", 600}, + {"ecaron", 600}, + {"ecircumflex", 600}, + {"edieresis", 600}, + {"edotaccent", 600}, + {"egrave", 600}, + {"eight", 600}, + {"ellipsis", 600}, + {"emacron", 600}, + {"emdash", 600}, + {"endash", 600}, + {"eogonek", 600}, + {"equal", 600}, + {"eth", 600}, + {"exclam", 600}, + {"exclamdown", 600}, + {"f", 600}, + {"fi", 600}, + {"five", 600}, + {"fl", 600}, + {"florin", 600}, + {"four", 600}, + {"fraction", 600}, + {"g", 600}, + {"gbreve", 600}, + {"gcommaaccent", 600}, + {"germandbls", 600}, + {"grave", 600}, + {"greater", 600}, + {"greaterequal", 600}, + {"guillemotleft", 600}, + {"guillemotright", 600}, + {"guilsinglleft", 600}, + {"guilsinglright", 600}, + {"h", 600}, + {"hungarumlaut", 600}, + {"hyphen", 600}, + {"i", 600}, + {"iacute", 600}, + {"icircumflex", 600}, + {"idieresis", 600}, + {"igrave", 600}, + {"imacron", 600}, + {"iogonek", 600}, + {"j", 600}, + {"k", 600}, + {"kcommaaccent", 600}, + {"l", 600}, + {"lacute", 600}, + {"lcaron", 600}, + {"lcommaaccent", 600}, + {"less", 600}, + {"lessequal", 600}, + {"logicalnot", 600}, + {"lozenge", 600}, + {"lslash", 600}, + {"m", 600}, + {"macron", 600}, + {"minus", 600}, + {"mu", 600}, + {"multiply", 600}, + {"n", 600}, + {"nacute", 600}, + {"ncaron", 600}, + {"ncommaaccent", 600}, + {"nine", 600}, + {"notequal", 600}, + {"ntilde", 600}, + {"numbersign", 600}, + {"o", 600}, + {"oacute", 600}, + {"ocircumflex", 600}, + {"odieresis", 600}, + {"oe", 600}, + {"ogonek", 600}, + {"ograve", 600}, + {"ohungarumlaut", 600}, + {"omacron", 600}, + {"one", 600}, + {"onehalf", 600}, + {"onequarter", 600}, + {"onesuperior", 600}, + {"ordfeminine", 600}, + {"ordmasculine", 600}, + {"oslash", 600}, + {"otilde", 600}, + {"p", 600}, + {"paragraph", 600}, + {"parenleft", 600}, + {"parenright", 600}, + {"partialdiff", 600}, + {"percent", 600}, + {"period", 600}, + {"periodcentered", 600}, + {"perthousand", 600}, + {"plus", 600}, + {"plusminus", 600}, + {"q", 600}, + {"question", 600}, + {"questiondown", 600}, + {"quotedbl", 600}, + {"quotedblbase", 600}, + {"quotedblleft", 600}, + {"quotedblright", 600}, + {"quoteleft", 600}, + {"quoteright", 600}, + {"quotesinglbase", 600}, + {"quotesingle", 600}, + {"r", 600}, + {"racute", 600}, + {"radical", 600}, + {"rcaron", 600}, + {"rcommaaccent", 600}, + {"registered", 600}, + {"ring", 600}, + {"s", 600}, + {"sacute", 600}, + {"scaron", 600}, + {"scedilla", 600}, + {"scommaaccent", 600}, + {"section", 600}, + {"semicolon", 600}, + {"seven", 600}, + {"six", 600}, + {"slash", 600}, + {"space", 600}, + {"sterling", 600}, + {"summation", 600}, + {"t", 600}, + {"tcaron", 600}, + {"tcommaaccent", 600}, + {"thorn", 600}, + {"three", 600}, + {"threequarters", 600}, + {"threesuperior", 600}, + {"tilde", 600}, + {"trademark", 600}, + {"two", 600}, + {"twosuperior", 600}, + {"u", 600}, + {"uacute", 600}, + {"ucircumflex", 600}, + {"udieresis", 600}, + {"ugrave", 600}, + {"uhungarumlaut", 600}, + {"umacron", 600}, + {"underscore", 600}, + {"uogonek", 600}, + {"uring", 600}, + {"v", 600}, + {"w", 600}, + {"x", 600}, + {"y", 600}, + {"yacute", 600}, + {"ydieresis", 600}, + {"yen", 600}, + {"z", 600}, + {"zacute", 600}, + {"zcaron", 600}, + {"zdotaccent", 600}, + {"zero", 600}, +}; + +constexpr std::int16_t code_widths_courier_oblique[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + -1, 600, 600, 600, 600, -1, 600, 600, 600, 600, 600, 600, 600, 600, -1, 600, + -1, 600, 600, 600, 600, 600, 600, 600, 600, -1, 600, 600, -1, 600, 600, 600, + 600, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 600, -1, 600, -1, -1, -1, -1, 600, 600, 600, 600, -1, -1, -1, -1, + -1, 600, -1, -1, -1, 600, -1, -1, 600, 600, 600, 600, -1, -1, -1, -1, +}; + +constexpr GlyphWidth glyphs_courier_boldoblique[] = { + {"A", 600}, + {"AE", 600}, + {"Aacute", 600}, + {"Abreve", 600}, + {"Acircumflex", 600}, + {"Adieresis", 600}, + {"Agrave", 600}, + {"Amacron", 600}, + {"Aogonek", 600}, + {"Aring", 600}, + {"Atilde", 600}, + {"B", 600}, + {"C", 600}, + {"Cacute", 600}, + {"Ccaron", 600}, + {"Ccedilla", 600}, + {"D", 600}, + {"Dcaron", 600}, + {"Dcroat", 600}, + {"Delta", 600}, + {"E", 600}, + {"Eacute", 600}, + {"Ecaron", 600}, + {"Ecircumflex", 600}, + {"Edieresis", 600}, + {"Edotaccent", 600}, + {"Egrave", 600}, + {"Emacron", 600}, + {"Eogonek", 600}, + {"Eth", 600}, + {"Euro", 600}, + {"F", 600}, + {"G", 600}, + {"Gbreve", 600}, + {"Gcommaaccent", 600}, + {"H", 600}, + {"I", 600}, + {"Iacute", 600}, + {"Icircumflex", 600}, + {"Idieresis", 600}, + {"Idotaccent", 600}, + {"Igrave", 600}, + {"Imacron", 600}, + {"Iogonek", 600}, + {"J", 600}, + {"K", 600}, + {"Kcommaaccent", 600}, + {"L", 600}, + {"Lacute", 600}, + {"Lcaron", 600}, + {"Lcommaaccent", 600}, + {"Lslash", 600}, + {"M", 600}, + {"N", 600}, + {"Nacute", 600}, + {"Ncaron", 600}, + {"Ncommaaccent", 600}, + {"Ntilde", 600}, + {"O", 600}, + {"OE", 600}, + {"Oacute", 600}, + {"Ocircumflex", 600}, + {"Odieresis", 600}, + {"Ograve", 600}, + {"Ohungarumlaut", 600}, + {"Omacron", 600}, + {"Oslash", 600}, + {"Otilde", 600}, + {"P", 600}, + {"Q", 600}, + {"R", 600}, + {"Racute", 600}, + {"Rcaron", 600}, + {"Rcommaaccent", 600}, + {"S", 600}, + {"Sacute", 600}, + {"Scaron", 600}, + {"Scedilla", 600}, + {"Scommaaccent", 600}, + {"T", 600}, + {"Tcaron", 600}, + {"Tcommaaccent", 600}, + {"Thorn", 600}, + {"U", 600}, + {"Uacute", 600}, + {"Ucircumflex", 600}, + {"Udieresis", 600}, + {"Ugrave", 600}, + {"Uhungarumlaut", 600}, + {"Umacron", 600}, + {"Uogonek", 600}, + {"Uring", 600}, + {"V", 600}, + {"W", 600}, + {"X", 600}, + {"Y", 600}, + {"Yacute", 600}, + {"Ydieresis", 600}, + {"Z", 600}, + {"Zacute", 600}, + {"Zcaron", 600}, + {"Zdotaccent", 600}, + {"a", 600}, + {"aacute", 600}, + {"abreve", 600}, + {"acircumflex", 600}, + {"acute", 600}, + {"adieresis", 600}, + {"ae", 600}, + {"agrave", 600}, + {"amacron", 600}, + {"ampersand", 600}, + {"aogonek", 600}, + {"aring", 600}, + {"asciicircum", 600}, + {"asciitilde", 600}, + {"asterisk", 600}, + {"at", 600}, + {"atilde", 600}, + {"b", 600}, + {"backslash", 600}, + {"bar", 600}, + {"braceleft", 600}, + {"braceright", 600}, + {"bracketleft", 600}, + {"bracketright", 600}, + {"breve", 600}, + {"brokenbar", 600}, + {"bullet", 600}, + {"c", 600}, + {"cacute", 600}, + {"caron", 600}, + {"ccaron", 600}, + {"ccedilla", 600}, + {"cedilla", 600}, + {"cent", 600}, + {"circumflex", 600}, + {"colon", 600}, + {"comma", 600}, + {"commaaccent", 600}, + {"copyright", 600}, + {"currency", 600}, + {"d", 600}, + {"dagger", 600}, + {"daggerdbl", 600}, + {"dcaron", 600}, + {"dcroat", 600}, + {"degree", 600}, + {"dieresis", 600}, + {"divide", 600}, + {"dollar", 600}, + {"dotaccent", 600}, + {"dotlessi", 600}, + {"e", 600}, + {"eacute", 600}, + {"ecaron", 600}, + {"ecircumflex", 600}, + {"edieresis", 600}, + {"edotaccent", 600}, + {"egrave", 600}, + {"eight", 600}, + {"ellipsis", 600}, + {"emacron", 600}, + {"emdash", 600}, + {"endash", 600}, + {"eogonek", 600}, + {"equal", 600}, + {"eth", 600}, + {"exclam", 600}, + {"exclamdown", 600}, + {"f", 600}, + {"fi", 600}, + {"five", 600}, + {"fl", 600}, + {"florin", 600}, + {"four", 600}, + {"fraction", 600}, + {"g", 600}, + {"gbreve", 600}, + {"gcommaaccent", 600}, + {"germandbls", 600}, + {"grave", 600}, + {"greater", 600}, + {"greaterequal", 600}, + {"guillemotleft", 600}, + {"guillemotright", 600}, + {"guilsinglleft", 600}, + {"guilsinglright", 600}, + {"h", 600}, + {"hungarumlaut", 600}, + {"hyphen", 600}, + {"i", 600}, + {"iacute", 600}, + {"icircumflex", 600}, + {"idieresis", 600}, + {"igrave", 600}, + {"imacron", 600}, + {"iogonek", 600}, + {"j", 600}, + {"k", 600}, + {"kcommaaccent", 600}, + {"l", 600}, + {"lacute", 600}, + {"lcaron", 600}, + {"lcommaaccent", 600}, + {"less", 600}, + {"lessequal", 600}, + {"logicalnot", 600}, + {"lozenge", 600}, + {"lslash", 600}, + {"m", 600}, + {"macron", 600}, + {"minus", 600}, + {"mu", 600}, + {"multiply", 600}, + {"n", 600}, + {"nacute", 600}, + {"ncaron", 600}, + {"ncommaaccent", 600}, + {"nine", 600}, + {"notequal", 600}, + {"ntilde", 600}, + {"numbersign", 600}, + {"o", 600}, + {"oacute", 600}, + {"ocircumflex", 600}, + {"odieresis", 600}, + {"oe", 600}, + {"ogonek", 600}, + {"ograve", 600}, + {"ohungarumlaut", 600}, + {"omacron", 600}, + {"one", 600}, + {"onehalf", 600}, + {"onequarter", 600}, + {"onesuperior", 600}, + {"ordfeminine", 600}, + {"ordmasculine", 600}, + {"oslash", 600}, + {"otilde", 600}, + {"p", 600}, + {"paragraph", 600}, + {"parenleft", 600}, + {"parenright", 600}, + {"partialdiff", 600}, + {"percent", 600}, + {"period", 600}, + {"periodcentered", 600}, + {"perthousand", 600}, + {"plus", 600}, + {"plusminus", 600}, + {"q", 600}, + {"question", 600}, + {"questiondown", 600}, + {"quotedbl", 600}, + {"quotedblbase", 600}, + {"quotedblleft", 600}, + {"quotedblright", 600}, + {"quoteleft", 600}, + {"quoteright", 600}, + {"quotesinglbase", 600}, + {"quotesingle", 600}, + {"r", 600}, + {"racute", 600}, + {"radical", 600}, + {"rcaron", 600}, + {"rcommaaccent", 600}, + {"registered", 600}, + {"ring", 600}, + {"s", 600}, + {"sacute", 600}, + {"scaron", 600}, + {"scedilla", 600}, + {"scommaaccent", 600}, + {"section", 600}, + {"semicolon", 600}, + {"seven", 600}, + {"six", 600}, + {"slash", 600}, + {"space", 600}, + {"sterling", 600}, + {"summation", 600}, + {"t", 600}, + {"tcaron", 600}, + {"tcommaaccent", 600}, + {"thorn", 600}, + {"three", 600}, + {"threequarters", 600}, + {"threesuperior", 600}, + {"tilde", 600}, + {"trademark", 600}, + {"two", 600}, + {"twosuperior", 600}, + {"u", 600}, + {"uacute", 600}, + {"ucircumflex", 600}, + {"udieresis", 600}, + {"ugrave", 600}, + {"uhungarumlaut", 600}, + {"umacron", 600}, + {"underscore", 600}, + {"uogonek", 600}, + {"uring", 600}, + {"v", 600}, + {"w", 600}, + {"x", 600}, + {"y", 600}, + {"yacute", 600}, + {"ydieresis", 600}, + {"yen", 600}, + {"z", 600}, + {"zacute", 600}, + {"zcaron", 600}, + {"zdotaccent", 600}, + {"zero", 600}, +}; + +constexpr std::int16_t code_widths_courier_boldoblique[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + -1, 600, 600, 600, 600, -1, 600, 600, 600, 600, 600, 600, 600, 600, -1, 600, + -1, 600, 600, 600, 600, 600, 600, 600, 600, -1, 600, 600, -1, 600, 600, 600, + 600, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 600, -1, 600, -1, -1, -1, -1, 600, 600, 600, 600, -1, -1, -1, -1, + -1, 600, -1, -1, -1, 600, -1, -1, 600, 600, 600, 600, -1, -1, -1, -1, +}; + +constexpr GlyphWidth glyphs_symbol[] = { + {"Alpha", 722}, + {"Beta", 667}, + {"Chi", 722}, + {"Delta", 612}, + {"Epsilon", 611}, + {"Eta", 722}, + {"Euro", 750}, + {"Gamma", 603}, + {"Ifraktur", 686}, + {"Iota", 333}, + {"Kappa", 722}, + {"Lambda", 686}, + {"Mu", 889}, + {"Nu", 722}, + {"Omega", 768}, + {"Omicron", 722}, + {"Phi", 763}, + {"Pi", 768}, + {"Psi", 795}, + {"Rfraktur", 795}, + {"Rho", 556}, + {"Sigma", 592}, + {"Tau", 611}, + {"Theta", 741}, + {"Upsilon", 690}, + {"Upsilon1", 620}, + {"Xi", 645}, + {"Zeta", 611}, + {"aleph", 823}, + {"alpha", 631}, + {"ampersand", 778}, + {"angle", 768}, + {"angleleft", 329}, + {"angleright", 329}, + {"apple", 790}, + {"approxequal", 549}, + {"arrowboth", 1042}, + {"arrowdblboth", 1042}, + {"arrowdbldown", 603}, + {"arrowdblleft", 987}, + {"arrowdblright", 987}, + {"arrowdblup", 603}, + {"arrowdown", 603}, + {"arrowhorizex", 1000}, + {"arrowleft", 987}, + {"arrowright", 987}, + {"arrowup", 603}, + {"arrowvertex", 603}, + {"asteriskmath", 500}, + {"bar", 200}, + {"beta", 549}, + {"braceex", 494}, + {"braceleft", 480}, + {"braceleftbt", 494}, + {"braceleftmid", 494}, + {"bracelefttp", 494}, + {"braceright", 480}, + {"bracerightbt", 494}, + {"bracerightmid", 494}, + {"bracerighttp", 494}, + {"bracketleft", 333}, + {"bracketleftbt", 384}, + {"bracketleftex", 384}, + {"bracketlefttp", 384}, + {"bracketright", 333}, + {"bracketrightbt", 384}, + {"bracketrightex", 384}, + {"bracketrighttp", 384}, + {"bullet", 460}, + {"carriagereturn", 658}, + {"chi", 549}, + {"circlemultiply", 768}, + {"circleplus", 768}, + {"club", 753}, + {"colon", 278}, + {"comma", 250}, + {"congruent", 549}, + {"copyrightsans", 790}, + {"copyrightserif", 790}, + {"degree", 400}, + {"delta", 494}, + {"diamond", 753}, + {"divide", 549}, + {"dotmath", 250}, + {"eight", 500}, + {"element", 713}, + {"ellipsis", 1000}, + {"emptyset", 823}, + {"epsilon", 439}, + {"equal", 549}, + {"equivalence", 549}, + {"eta", 603}, + {"exclam", 333}, + {"existential", 549}, + {"five", 500}, + {"florin", 500}, + {"four", 500}, + {"fraction", 167}, + {"gamma", 411}, + {"gradient", 713}, + {"greater", 549}, + {"greaterequal", 549}, + {"heart", 753}, + {"infinity", 713}, + {"integral", 274}, + {"integralbt", 686}, + {"integralex", 686}, + {"integraltp", 686}, + {"intersection", 768}, + {"iota", 329}, + {"kappa", 549}, + {"lambda", 549}, + {"less", 549}, + {"lessequal", 549}, + {"logicaland", 603}, + {"logicalnot", 713}, + {"logicalor", 603}, + {"lozenge", 494}, + {"minus", 549}, + {"minute", 247}, + {"mu", 576}, + {"multiply", 549}, + {"nine", 500}, + {"notelement", 713}, + {"notequal", 549}, + {"notsubset", 713}, + {"nu", 521}, + {"numbersign", 500}, + {"omega", 686}, + {"omega1", 713}, + {"omicron", 549}, + {"one", 500}, + {"parenleft", 333}, + {"parenleftbt", 384}, + {"parenleftex", 384}, + {"parenlefttp", 384}, + {"parenright", 333}, + {"parenrightbt", 384}, + {"parenrightex", 384}, + {"parenrighttp", 384}, + {"partialdiff", 494}, + {"percent", 833}, + {"period", 250}, + {"perpendicular", 658}, + {"phi", 521}, + {"phi1", 603}, + {"pi", 549}, + {"plus", 549}, + {"plusminus", 549}, + {"product", 823}, + {"propersubset", 713}, + {"propersuperset", 713}, + {"proportional", 713}, + {"psi", 686}, + {"question", 444}, + {"radical", 549}, + {"radicalex", 500}, + {"reflexsubset", 713}, + {"reflexsuperset", 713}, + {"registersans", 790}, + {"registerserif", 790}, + {"rho", 549}, + {"second", 411}, + {"semicolon", 278}, + {"seven", 500}, + {"sigma", 603}, + {"sigma1", 439}, + {"similar", 549}, + {"six", 500}, + {"slash", 278}, + {"space", 250}, + {"spade", 753}, + {"suchthat", 439}, + {"summation", 713}, + {"tau", 439}, + {"therefore", 863}, + {"theta", 521}, + {"theta1", 631}, + {"three", 500}, + {"trademarksans", 786}, + {"trademarkserif", 890}, + {"two", 500}, + {"underscore", 500}, + {"union", 768}, + {"universal", 713}, + {"upsilon", 576}, + {"weierstrass", 987}, + {"xi", 493}, + {"zero", 500}, + {"zeta", 494}, +}; + +constexpr std::int16_t code_widths_symbol[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 250, 333, 713, 500, 549, 833, 778, 439, 333, 333, 500, 549, 250, 549, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 549, 549, 549, 444, + 549, 722, 667, 722, 612, 611, 763, 603, 722, 333, 631, 722, 686, 889, 722, 722, + 768, 741, 556, 592, 611, 690, 439, 768, 645, 795, 611, 333, 863, 333, 658, 500, + 500, 631, 549, 549, 494, 439, 521, 411, 603, 329, 603, 549, 549, 576, 521, 549, + 549, 521, 549, 603, 439, 576, 713, 686, 493, 686, 494, 480, 200, 480, 549, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 750, 620, 247, 549, 167, 713, 500, 753, 753, 753, 753, 1042, 987, 603, 987, 603, + 400, 549, 411, 549, 549, 713, 494, 460, 549, 549, 549, 549, 1000, 603, 1000, 658, + 823, 686, 795, 987, 768, 768, 823, 768, 768, 713, 713, 713, 713, 713, 713, 713, + 768, 713, 790, 790, 890, 823, 549, 250, 713, 603, 603, 1042, 987, 603, 987, 603, + 494, 329, 790, 790, 786, 713, 384, 384, 384, 384, 384, 384, 494, 494, 494, 494, + -1, 329, 274, 686, 686, 686, 384, 384, 384, 384, 384, 384, 494, 494, 494, -1, +}; + +constexpr GlyphWidth glyphs_zapfdingbats[] = { + {"a1", 974}, + {"a10", 692}, + {"a100", 668}, + {"a101", 732}, + {"a102", 544}, + {"a103", 544}, + {"a104", 910}, + {"a105", 911}, + {"a106", 667}, + {"a107", 760}, + {"a108", 760}, + {"a109", 626}, + {"a11", 960}, + {"a110", 694}, + {"a111", 595}, + {"a112", 776}, + {"a117", 690}, + {"a118", 791}, + {"a119", 790}, + {"a12", 939}, + {"a120", 788}, + {"a121", 788}, + {"a122", 788}, + {"a123", 788}, + {"a124", 788}, + {"a125", 788}, + {"a126", 788}, + {"a127", 788}, + {"a128", 788}, + {"a129", 788}, + {"a13", 549}, + {"a130", 788}, + {"a131", 788}, + {"a132", 788}, + {"a133", 788}, + {"a134", 788}, + {"a135", 788}, + {"a136", 788}, + {"a137", 788}, + {"a138", 788}, + {"a139", 788}, + {"a14", 855}, + {"a140", 788}, + {"a141", 788}, + {"a142", 788}, + {"a143", 788}, + {"a144", 788}, + {"a145", 788}, + {"a146", 788}, + {"a147", 788}, + {"a148", 788}, + {"a149", 788}, + {"a15", 911}, + {"a150", 788}, + {"a151", 788}, + {"a152", 788}, + {"a153", 788}, + {"a154", 788}, + {"a155", 788}, + {"a156", 788}, + {"a157", 788}, + {"a158", 788}, + {"a159", 788}, + {"a16", 933}, + {"a160", 894}, + {"a161", 838}, + {"a162", 924}, + {"a163", 1016}, + {"a164", 458}, + {"a165", 924}, + {"a166", 918}, + {"a167", 927}, + {"a168", 928}, + {"a169", 928}, + {"a17", 945}, + {"a170", 834}, + {"a171", 873}, + {"a172", 828}, + {"a173", 924}, + {"a174", 917}, + {"a175", 930}, + {"a176", 931}, + {"a177", 463}, + {"a178", 883}, + {"a179", 836}, + {"a18", 974}, + {"a180", 867}, + {"a181", 696}, + {"a182", 874}, + {"a183", 760}, + {"a184", 946}, + {"a185", 865}, + {"a186", 967}, + {"a187", 831}, + {"a188", 873}, + {"a189", 927}, + {"a19", 755}, + {"a190", 970}, + {"a191", 918}, + {"a192", 748}, + {"a193", 836}, + {"a194", 771}, + {"a195", 888}, + {"a196", 748}, + {"a197", 771}, + {"a198", 888}, + {"a199", 867}, + {"a2", 961}, + {"a20", 846}, + {"a200", 696}, + {"a201", 874}, + {"a202", 974}, + {"a203", 762}, + {"a204", 759}, + {"a205", 509}, + {"a206", 410}, + {"a21", 762}, + {"a22", 761}, + {"a23", 571}, + {"a24", 677}, + {"a25", 763}, + {"a26", 760}, + {"a27", 759}, + {"a28", 754}, + {"a29", 786}, + {"a3", 980}, + {"a30", 788}, + {"a31", 788}, + {"a32", 790}, + {"a33", 793}, + {"a34", 794}, + {"a35", 816}, + {"a36", 823}, + {"a37", 789}, + {"a38", 841}, + {"a39", 823}, + {"a4", 719}, + {"a40", 833}, + {"a41", 816}, + {"a42", 831}, + {"a43", 923}, + {"a44", 744}, + {"a45", 723}, + {"a46", 749}, + {"a47", 790}, + {"a48", 792}, + {"a49", 695}, + {"a5", 789}, + {"a50", 776}, + {"a51", 768}, + {"a52", 792}, + {"a53", 759}, + {"a54", 707}, + {"a55", 708}, + {"a56", 682}, + {"a57", 701}, + {"a58", 826}, + {"a59", 815}, + {"a6", 494}, + {"a60", 789}, + {"a61", 789}, + {"a62", 707}, + {"a63", 687}, + {"a64", 696}, + {"a65", 689}, + {"a66", 786}, + {"a67", 787}, + {"a68", 713}, + {"a69", 791}, + {"a7", 552}, + {"a70", 785}, + {"a71", 791}, + {"a72", 873}, + {"a73", 761}, + {"a74", 762}, + {"a75", 759}, + {"a76", 892}, + {"a77", 892}, + {"a78", 788}, + {"a79", 784}, + {"a8", 537}, + {"a81", 438}, + {"a82", 138}, + {"a83", 277}, + {"a84", 415}, + {"a85", 509}, + {"a86", 410}, + {"a87", 234}, + {"a88", 234}, + {"a89", 390}, + {"a9", 577}, + {"a90", 390}, + {"a91", 276}, + {"a92", 276}, + {"a93", 317}, + {"a94", 317}, + {"a95", 334}, + {"a96", 334}, + {"a97", 392}, + {"a98", 392}, + {"a99", 668}, + {"space", 278}, +}; + +constexpr std::int16_t code_widths_zapfdingbats[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 278, 974, 961, 974, 980, 719, 789, 790, 791, 690, 960, 939, 549, 855, 911, 933, + 911, 945, 974, 755, 846, 762, 761, 571, 677, 763, 760, 759, 754, 494, 552, 537, + 577, 692, 786, 788, 788, 790, 793, 794, 816, 823, 789, 841, 823, 833, 816, 831, + 923, 744, 723, 749, 790, 792, 695, 776, 768, 792, 759, 707, 708, 682, 701, 826, + 815, 789, 789, 707, 687, 696, 689, 786, 787, 713, 791, 785, 791, 873, 761, 762, + 762, 759, 759, 892, 892, 788, 784, 438, 138, 277, 415, 392, 392, 668, 668, -1, + 390, 390, 317, 317, 276, 276, 509, 509, 410, 410, 234, 234, 334, 334, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 732, 544, 544, 910, 667, 760, 760, 776, 595, 694, 626, 788, 788, 788, 788, + 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, + 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, + 788, 788, 788, 788, 894, 838, 1016, 458, 748, 924, 748, 918, 927, 928, 928, 834, + 873, 828, 924, 924, 917, 930, 931, 463, 883, 836, 836, 867, 867, 696, 696, 874, + -1, 874, 760, 946, 771, 865, 771, 888, 967, 888, 831, 873, 927, 970, 918, -1, +}; + +} // namespace + +const std::array fonts = {{ + {"Helvetica", 718, -207, 718, glyphs_helvetica, std::size(glyphs_helvetica), code_widths_helvetica}, + {"Helvetica-Bold", 718, -207, 718, glyphs_helvetica_bold, std::size(glyphs_helvetica_bold), code_widths_helvetica_bold}, + {"Helvetica-Oblique", 718, -207, 718, glyphs_helvetica_oblique, std::size(glyphs_helvetica_oblique), code_widths_helvetica_oblique}, + {"Helvetica-BoldOblique", 718, -207, 718, glyphs_helvetica_boldoblique, std::size(glyphs_helvetica_boldoblique), code_widths_helvetica_boldoblique}, + {"Times-Roman", 683, -217, 662, glyphs_times_roman, std::size(glyphs_times_roman), code_widths_times_roman}, + {"Times-Bold", 683, -217, 676, glyphs_times_bold, std::size(glyphs_times_bold), code_widths_times_bold}, + {"Times-Italic", 683, -217, 653, glyphs_times_italic, std::size(glyphs_times_italic), code_widths_times_italic}, + {"Times-BoldItalic", 683, -217, 669, glyphs_times_bolditalic, std::size(glyphs_times_bolditalic), code_widths_times_bolditalic}, + {"Courier", 629, -157, 562, glyphs_courier, std::size(glyphs_courier), code_widths_courier}, + {"Courier-Bold", 629, -157, 562, glyphs_courier_bold, std::size(glyphs_courier_bold), code_widths_courier_bold}, + {"Courier-Oblique", 629, -157, 562, glyphs_courier_oblique, std::size(glyphs_courier_oblique), code_widths_courier_oblique}, + {"Courier-BoldOblique", 629, -157, 562, glyphs_courier_boldoblique, std::size(glyphs_courier_boldoblique), code_widths_courier_boldoblique}, + {"Symbol", 1010, 0, 0, glyphs_symbol, std::size(glyphs_symbol), code_widths_symbol}, + {"ZapfDingbats", 820, 0, 0, glyphs_zapfdingbats, std::size(glyphs_zapfdingbats), code_widths_zapfdingbats}, +}}; + +} // namespace odr::internal::pdf::afm_data diff --git a/src/odr/internal/pdf/pdf_afm_data.hpp b/src/odr/internal/pdf/pdf_afm_data.hpp new file mode 100644 index 00000000..9bd5a3fb --- /dev/null +++ b/src/odr/internal/pdf/pdf_afm_data.hpp @@ -0,0 +1,40 @@ +// Auto-generated by tools/pdf/generate_afm_data.py -- DO NOT EDIT. +// Regenerate by rerunning the script; see its header for the source data. +// Adobe Core-14 AFM metrics, redistributed by Apache PDFBox (Apache-2.0); +// see tools/pdf/THIRD_PARTY_LICENSES.md. + +// clang-format off + +#pragma once + +#include +#include +#include +#include + +namespace odr::internal::pdf::afm_data { + +/// One glyph's advance width (glyph space, 1/1000 em), keyed by name. +struct GlyphWidth { + std::string_view name; + std::int16_t width; +}; + +/// One standard-14 font: its name->width table (sorted by name for a +/// binary search), the built-in encoding's code->width table (-1 where +/// the slot is empty), and header metrics (glyph space, 1/1000 em). +struct FontMetrics { + std::string_view font_name; + std::int16_t ascender; + std::int16_t descender; + std::int16_t cap_height; + const GlyphWidth *glyphs; + std::size_t glyph_count; + const std::int16_t *code_widths; // 256 entries; -1 == absent +}; + +inline constexpr std::size_t font_count = 14; + +extern const std::array fonts; + +} // namespace odr::internal::pdf::afm_data diff --git a/src/odr/internal/pdf/pdf_document.cpp b/src/odr/internal/pdf/pdf_document.cpp index 6995005c..ea77900c 100644 --- a/src/odr/internal/pdf/pdf_document.cpp +++ b/src/odr/internal/pdf/pdf_document.cpp @@ -44,6 +44,27 @@ double Font::advance_width(const std::uint32_t code) const { if (index >= 0 && index < static_cast(widths.size())) { return widths[static_cast(index)] / 1000.0; } + // Non-embedded standard-14 fonts usually ship no `/Widths`: fall back to the + // substitute's AFM metrics (ISO 32000-1 9.6.2.2) so placement stays correct. + // The `/Encoding` (a `/Differences` override or a base encoding) names the + // glyph; without one, the font's built-in encoding (the AFM's own codes) is + // the fallback — the Symbol/ZapfDingbats case. + if (substitute && substitute->metrics && code <= 0xFF) { + const StandardFont metrics = *substitute->metrics; + if (encoding) { + if (const std::string_view name = + encoding->glyph_name(static_cast(code)); + !name.empty()) { + if (const std::optional width = afm_width(metrics, name)) { + return *width / 1000.0; + } + } + } + if (const std::optional width = + afm_code_width(metrics, static_cast(code))) { + return *width / 1000.0; + } + } return missing_width / 1000.0; } diff --git a/src/odr/internal/pdf/pdf_document_element.hpp b/src/odr/internal/pdf/pdf_document_element.hpp index 2fee654f..d1f8c09b 100644 --- a/src/odr/internal/pdf/pdf_document_element.hpp +++ b/src/odr/internal/pdf/pdf_document_element.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -326,6 +327,13 @@ struct Font final : Element { /// embedded reverse map. std::shared_ptr embedded_font; + /// Substitution for a non-embedded font (`embedded_font == nullptr`): the CSS + /// `font-family` the HTML layer renders it in, plus the standard-14 AFM font + /// whose advance widths back `advance_width` when the font carries no + /// `/Widths`. Resolved once at parse time; `nullopt` for embedded fonts (they + /// render their real glyphs) and composite fonts. + std::optional substitute; + /// Composite-font `/CIDToGIDMap` (ISO 32000-1 9.7.4.3) when given as an /// explicit stream: `GID = cid_to_gid[CID]`. Empty means `Identity` /// (`GID = CID`, the common case). diff --git a/src/odr/internal/pdf/pdf_document_parser.cpp b/src/odr/internal/pdf/pdf_document_parser.cpp index f00b5a26..f192080f 100644 --- a/src/odr/internal/pdf/pdf_document_parser.cpp +++ b/src/odr/internal/pdf/pdf_document_parser.cpp @@ -380,6 +380,53 @@ void parse_simple_font_widths(DocumentParser &parser, } } +/// Resolve a substitute for a non-embedded simple font (`/FontFile*` absent or +/// unreadable) from its `/BaseFont` name and `/FontDescriptor` hints. Leaves +/// `font.substitute` unset when a font program is embedded (it renders its own +/// glyphs) — so a font whose descriptor failed to load still gets a substitute. +void resolve_font_substitute(DocumentParser &parser, + const Dictionary &dictionary, Font &font) { + if (font.embedded_font != nullptr) { + return; + } + + std::string base_font; + if (dictionary.get("BaseFont").is_name()) { + base_font = dictionary["BaseFont"].as_name(); + } + + std::uint32_t flags = 0; + int font_weight = 0; + double italic_angle = 0; + if (dictionary.has_key("FontDescriptor")) { + const Object descriptor = + parser.resolve_object_copy(dictionary["FontDescriptor"]); + if (descriptor.is_dictionary()) { + const Dictionary &d = descriptor.as_dictionary(); + if (const auto v = + parser.resolve_object_copy(d.get("Flags")).as_integer_opt()) { + flags = static_cast(*v); + } + if (const auto v = parser.resolve_object_copy(d.get("FontWeight")) + .as_integer_opt()) { + font_weight = static_cast(*v); + } + const Object angle = parser.resolve_object_copy(d.get("ItalicAngle")); + if (angle.is_real()) { + italic_angle = angle.as_real(); + } + } + } + + font.substitute = + pdf::resolve_font_substitute(base_font, flags, font_weight, italic_angle); + // A substitute with standard-14 metrics can supply the baseline shift the + // HTML layer needs when the descriptor declared no `/Ascent`. + if (!font.descriptor_ascent && font.substitute->metrics) { + font.descriptor_ascent = afm_ascender(*font.substitute->metrics); + } +} + /// Parse a composite CIDFont's `/CIDToGIDMap` (ISO 32000-1 9.7.4.3): a stream /// of big-endian `uint16` GIDs indexed by CID, or the name `Identity`. Leaves /// `font.cid_to_gid` empty for `Identity` (so `glyph_for_code` uses `GID = @@ -525,6 +572,8 @@ Font *parse_font(State &state, const ObjectReference &reference) { // fonts without a `ToUnicode` CMap. font->encoding = parse_encoding(parser, dictionary["Encoding"]); } + // Non-embedded simple fonts render in a substitute family with AFM widths. + resolve_font_substitute(parser, dictionary, *font); } return font; diff --git a/test/src/internal/pdf/pdf_font.cpp b/test/src/internal/pdf/pdf_font.cpp index 2cb89be6..ea270dad 100644 --- a/test/src/internal/pdf/pdf_font.cpp +++ b/test/src/internal/pdf/pdf_font.cpp @@ -1,6 +1,8 @@ #include #include +#include #include +#include #include #include @@ -194,3 +196,104 @@ TEST(PdfFont, no_font_yields_no_glyph) { font.composite = true; EXPECT_EQ(font.glyph_for_code(1), 0); } + +TEST(PdfAfm, resolve_substitute_by_name) { + using pdf::resolve_font_substitute; + using pdf::StandardFont; + + const pdf::FontSubstitute helv = + resolve_font_substitute("Helvetica", 0, 0, 0); + EXPECT_EQ(helv.metrics, StandardFont::helvetica); + EXPECT_FALSE(helv.bold); + EXPECT_FALSE(helv.italic); + EXPECT_NE(helv.css_family.find("sans-serif"), std::string::npos); + + const pdf::FontSubstitute tbi = + resolve_font_substitute("Times-BoldItalic", 0, 0, 0); + EXPECT_EQ(tbi.metrics, StandardFont::times_bold_italic); + EXPECT_TRUE(tbi.bold); + EXPECT_TRUE(tbi.italic); + EXPECT_NE(tbi.css_family.find("serif"), std::string::npos); + + // A subset prefix (`ABCDEF+`) is stripped before matching. + const pdf::FontSubstitute sub = + resolve_font_substitute("ABCDEF+Courier-Bold", 0, 0, 0); + EXPECT_EQ(sub.metrics, StandardFont::courier_bold); + EXPECT_TRUE(sub.bold); + EXPECT_NE(sub.css_family.find("monospace"), std::string::npos); +} + +TEST(PdfAfm, resolve_substitute_by_flags) { + using pdf::resolve_font_substitute; + using pdf::StandardFont; + + // No recognizable name: the descriptor flags pick the family (serif bit 2, + // fixed-pitch bit 1). + EXPECT_EQ(resolve_font_substitute("CustomFont", 1U << 1, 0, 0).metrics, + StandardFont::times_roman); + EXPECT_EQ(resolve_font_substitute("CustomFont", 1U << 0, 0, 0).metrics, + StandardFont::courier); + + // Italic flag (bit 7) + force-bold flag (bit 19). + const pdf::FontSubstitute flagged = + resolve_font_substitute("CustomFont", (1U << 6) | (1U << 18), 0, 0); + EXPECT_TRUE(flagged.bold); + EXPECT_TRUE(flagged.italic); + EXPECT_EQ(flagged.metrics, StandardFont::helvetica_bold_oblique); + + // FontWeight >= 600 and a non-zero ItalicAngle also imply bold/italic. + const pdf::FontSubstitute weighted = + resolve_font_substitute("CustomFont", 0, 700, -12.0); + EXPECT_TRUE(weighted.bold); + EXPECT_TRUE(weighted.italic); +} + +TEST(PdfAfm, glyph_and_code_widths) { + using pdf::afm_code_width; + using pdf::afm_width; + using pdf::StandardFont; + + EXPECT_EQ(afm_width(StandardFont::helvetica, "A"), 667.0); + EXPECT_EQ(afm_width(StandardFont::helvetica, "space"), 278.0); + EXPECT_EQ(afm_width(StandardFont::times_roman, "A"), 722.0); + EXPECT_EQ(afm_width(StandardFont::courier, "A"), 600.0); + EXPECT_FALSE(afm_width(StandardFont::helvetica, "nonexistent")); + + // Built-in-encoding fallback: Symbol code 32 is space = 250; an empty slot + // (code 0) has no width. + EXPECT_EQ(afm_code_width(StandardFont::symbol, 32), 250.0); + EXPECT_FALSE(afm_code_width(StandardFont::symbol, 0)); +} + +TEST(PdfFont, advance_width_afm_fallback_via_encoding) { + // A non-embedded Helvetica with no /Widths: the advance comes from the AFM + // table via the /Encoding glyph name. + Font font; + font.substitute = pdf::resolve_font_substitute("Helvetica", 0, 0, 0); + font.encoding.emplace(pdf::BaseEncoding::standard); + + EXPECT_NEAR(font.advance_width('A'), 0.667, 1e-9); + EXPECT_NEAR(font.advance_width(' '), 0.278, 1e-9); +} + +TEST(PdfFont, advance_width_afm_fallback_builtin_encoding) { + // No /Encoding: fall back to the substitute font's built-in code->width + // table (the Symbol / ZapfDingbats case). + Font font; + font.substitute = pdf::resolve_font_substitute("Symbol", 1U << 2, 0, 0); + + EXPECT_NEAR(font.advance_width(32), 0.25, 1e-9); +} + +TEST(PdfFont, advance_width_explicit_widths_win_over_afm) { + // An explicit /Widths entry takes precedence; a code outside its range still + // falls back to the AFM table. + Font font; + font.substitute = pdf::resolve_font_substitute("Helvetica", 0, 0, 0); + font.encoding.emplace(pdf::BaseEncoding::standard); + font.first_char = 'A'; + font.widths = {1000.0}; + + EXPECT_NEAR(font.advance_width('A'), 1.0, 1e-9); // from /Widths + EXPECT_NEAR(font.advance_width('B'), 0.667, 1e-9); // out of range -> AFM +} diff --git a/tools/pdf/THIRD_PARTY_LICENSES.md b/tools/pdf/THIRD_PARTY_LICENSES.md index ff3a1a77..e1c7ebda 100644 --- a/tools/pdf/THIRD_PARTY_LICENSES.md +++ b/tools/pdf/THIRD_PARTY_LICENSES.md @@ -24,6 +24,22 @@ The 256-entry StandardEncoding, WinAnsiEncoding and MacRomanEncoding tables from ISO 32000-1 (PDF 1.7), Annex D. These are factual data from the PDF specification, transcribed here in the same on-disk format as `glyphlist.txt`. +## Adobe Core-14 AFM metrics — fetched by `generate_afm_data.py` + +- Source: the 14 Adobe Core AFM files (`Helvetica`, `Times-*`, `Courier-*`, + `Symbol`, `ZapfDingbats`), redistributed by Apache PDFBox + (https://github.com/apache/pdfbox, pinned by tag in `_PDFBOX_TAG` in + `generate_afm_data.py`). +- The AFM metric files are Adobe's; Apache PDFBox redistributes them under the + Apache License 2.0. +- License: Apache-2.0 (redistribution), the underlying metric data being + factual glyph-advance figures from the PDF standard's base-14 fonts. + +Like the AGL and CMap resources these files are **not vendored**: the script +downloads them into `tools/pdf/afm/` (git-ignored) on first run. Apache-2.0 is +GPL-compatible; the committed C++ generated from them carries the attribution in +its banner. + ## Adobe CMap resources — fetched by `generate_cid_data.py` - Source: https://github.com/adobe-type-tools/cmap-resources (pinned by commit diff --git a/tools/pdf/generate_afm_data.py b/tools/pdf/generate_afm_data.py new file mode 100644 index 00000000..65345d59 --- /dev/null +++ b/tools/pdf/generate_afm_data.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python3 +"""Generate the standard-14 AFM glyph-metric tables for the PDF module. + +A non-embedded font (no ``/FontFile*``) is substituted, not rendered: the glyph +shapes come from the browser's fallback font, but placement still needs the +*intended* advance widths. The base-14 fonts (Helvetica/Times/Courier families + +Symbol/ZapfDingbats) usually ship no ``/Widths`` array, so their widths come from +Adobe's Core-14 AFM metric files, baked here into committed C++ +(``pdf_afm_data.{hpp,cpp}``). The build only compiles the output; there is no +build-time dependency on this script. Re-run it whenever the source data or the +font list changes: + + python3 tools/pdf/generate_afm_data.py + +Source data -- the 14 Adobe Core AFM files -- are fetched from a pinned Apache +PDFBox tag (Apache-2.0; the files themselves are Adobe's, redistributed by +PDFBox) into the git-ignored ``afm/`` cache next to this script and reused on +later runs, the same way ``generate_encoding_data.py`` fetches the AGL. See +``tools/pdf/THIRD_PARTY_LICENSES.md``. + +Each AFM lists per-glyph metrics as ``C ; WX ; N ; ...`` +lines (ISO 32000-1 references the Adobe AFM spec). ``code`` is the glyph's slot +in the font's built-in encoding, ``-1`` for glyphs outside it (still carrying a +name and width -- reachable through a PDF ``/Differences`` array). We key widths +by glyph *name* (the encoding-independent path, used with a PDF ``/Encoding``) +and additionally keep the built-in ``code -> width`` table (the fallback when a +font carries no ``/Encoding`` at all -- notably Symbol/ZapfDingbats). +""" + +from __future__ import annotations + +import argparse +import os +import sys +import urllib.request + +_DATA_DIR = os.path.dirname(os.path.abspath(__file__)) +_AFM_CACHE = os.path.join(_DATA_DIR, "afm") + +# Pinned PDFBox tag; its resources bundle Adobe's Core-14 AFM files verbatim. +_PDFBOX_TAG = "3.0.3" +_AFM_URL = ( + "https://raw.githubusercontent.com/apache/pdfbox/" + f"{_PDFBOX_TAG}/pdfbox/src/main/resources/org/apache/pdfbox/resources/afm" +) + +# The 14 fonts, in the order the C++ `StandardFont` enum expects (see pdf_afm.hpp). +_FONTS = ( + "Helvetica", + "Helvetica-Bold", + "Helvetica-Oblique", + "Helvetica-BoldOblique", + "Times-Roman", + "Times-Bold", + "Times-Italic", + "Times-BoldItalic", + "Courier", + "Courier-Bold", + "Courier-Oblique", + "Courier-BoldOblique", + "Symbol", + "ZapfDingbats", +) + + +# --- Fetching --------------------------------------------------------------- + + +def ensure_afm(font: str) -> str: + """Download the pinned AFM for `font` if absent; return its path.""" + os.makedirs(_AFM_CACHE, exist_ok=True) + path = os.path.join(_AFM_CACHE, f"{font}.afm") + if os.path.isfile(path): + return path + url = f"{_AFM_URL}/{font}.afm" + print(f"downloading {url}", file=sys.stderr) + with urllib.request.urlopen(url) as response: # noqa: S310 (pinned) + payload = response.read() + with open(path, "wb") as out: + out.write(payload) + return path + + +# --- Parsing ---------------------------------------------------------------- + + +class Afm: + """One parsed AFM: name->width, the 256-entry built-in code->width table, + and the header ascent/descent/cap-height metrics (glyph space, /1000).""" + + def __init__(self) -> None: + self.widths: dict[str, int] = {} + self.code_widths: list[int] = [-1] * 256 + self.ascender = 0 + self.descender = 0 + self.cap_height = 0 + self.bbox_ymax = 0 + + +def parse_afm(path: str) -> Afm: + afm = Afm() + with open(path, encoding="latin-1") as handle: + for line in handle: + line = line.strip() + if line.startswith("C "): + # `C ; WX ; N ; B ...` + fields = [f.strip() for f in line.split(";")] + code = width = None + name = None + for field in fields: + parts = field.split() + if not parts: + continue + if parts[0] == "C": + code = int(parts[1]) + elif parts[0] == "WX": + width = int(round(float(parts[1]))) + elif parts[0] == "N": + name = parts[1] + if name is not None and width is not None: + afm.widths[name] = width + if code is not None and 0 <= code <= 255: + afm.code_widths[code] = width + elif line.startswith("Ascender "): + afm.ascender = int(round(float(line.split()[1]))) + elif line.startswith("Descender "): + afm.descender = int(round(float(line.split()[1]))) + elif line.startswith("CapHeight "): + afm.cap_height = int(round(float(line.split()[1]))) + elif line.startswith("FontBBox "): + afm.bbox_ymax = int(round(float(line.split()[4]))) + # Symbol/ZapfDingbats carry no Ascender/Descender: fall back to the FontBBox + # so the substitute still gets a plausible baseline shift. + if afm.ascender == 0: + afm.ascender = afm.bbox_ymax + return afm + + +# --- Emit ------------------------------------------------------------------- + +_AUTOGEN = ( + "// Auto-generated by tools/pdf/generate_afm_data.py -- DO NOT EDIT.\n" + "// Regenerate by rerunning the script; see its header for the source data.\n" + "// Adobe Core-14 AFM metrics, redistributed by Apache PDFBox (Apache-2.0);\n" + "// see tools/pdf/THIRD_PARTY_LICENSES.md.\n" + "\n" + "// clang-format off" +) + + +def _ident(font: str) -> str: + return font.lower().replace("-", "_") + + +def emit_hpp() -> str: + out = [ + _AUTOGEN, + "", + "#pragma once", + "", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "namespace odr::internal::pdf::afm_data {", + "", + "/// One glyph's advance width (glyph space, 1/1000 em), keyed by name.", + "struct GlyphWidth {", + " std::string_view name;", + " std::int16_t width;", + "};", + "", + "/// One standard-14 font: its name->width table (sorted by name for a", + "/// binary search), the built-in encoding's code->width table (-1 where", + "/// the slot is empty), and header metrics (glyph space, 1/1000 em).", + "struct FontMetrics {", + " std::string_view font_name;", + " std::int16_t ascender;", + " std::int16_t descender;", + " std::int16_t cap_height;", + " const GlyphWidth *glyphs;", + " std::size_t glyph_count;", + " const std::int16_t *code_widths; // 256 entries; -1 == absent", + "};", + "", + f"inline constexpr std::size_t font_count = {len(_FONTS)};", + "", + "extern const std::array fonts;", + "", + "} // namespace odr::internal::pdf::afm_data", + "", + ] + return "\n".join(out) + + +def emit_cpp(afms: list[tuple[str, Afm]]) -> str: + out = [ + _AUTOGEN, + "", + "#include ", + "", + "namespace odr::internal::pdf::afm_data {", + "namespace {", + "", + ] + + for font, afm in afms: + ident = _ident(font) + out.append(f"constexpr GlyphWidth glyphs_{ident}[] = {{") + for name, width in sorted(afm.widths.items()): + assert '"' not in name and "\\" not in name, name + out.append(f' {{"{name}", {width}}},') + out += ["};", ""] + + out.append(f"constexpr std::int16_t code_widths_{ident}[256] = {{") + row: list[str] = [] + for code in range(256): + row.append(str(afm.code_widths[code])) + if len(row) == 16: + out.append(" " + ", ".join(row) + ",") + row = [] + out += ["};", ""] + + out += ["} // namespace", ""] + + out.append("const std::array fonts = {{") + for font, afm in afms: + ident = _ident(font) + out.append( + f' {{"{font}", {afm.ascender}, {afm.descender}, ' + f"{afm.cap_height}, glyphs_{ident}, " + f"std::size(glyphs_{ident}), code_widths_{ident}}}," + ) + out += ["}};", "", "} // namespace odr::internal::pdf::afm_data", ""] + return "\n".join(out) + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--out", + default=os.path.join("src", "odr", "internal", "pdf"), + help="output directory for pdf_afm_data.{hpp,cpp}", + ) + args = parser.parse_args() + + afms = [(font, parse_afm(ensure_afm(font))) for font in _FONTS] + + os.makedirs(args.out, exist_ok=True) + with open(os.path.join(args.out, "pdf_afm_data.hpp"), "w") as handle: + handle.write(emit_hpp()) + with open(os.path.join(args.out, "pdf_afm_data.cpp"), "w") as handle: + handle.write(emit_cpp(afms)) + + glyphs = sum(len(afm.widths) for _, afm in afms) + print(f"generated pdf_afm_data.{{hpp,cpp}} ({len(afms)} fonts, {glyphs} glyphs)") + + +if __name__ == "__main__": + main() From 3ad95ddc4bc55ad3b958b6c6d0586785ca174368 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Sat, 4 Jul 2026 14:13:38 +0200 Subject: [PATCH 2/5] more workers for compare output server script --- test/scripts/compare_output_server.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/scripts/compare_output_server.sh b/test/scripts/compare_output_server.sh index 29ff2674..ce4a6207 100755 --- a/test/scripts/compare_output_server.sh +++ b/test/scripts/compare_output_server.sh @@ -18,4 +18,4 @@ docker run -ti \ -p 8000:8000 \ --platform linux/amd64 \ ghcr.io/opendocument-app/odr_core_test:1.3.0 \ - compare-html-server /repo/$REF /repo/$OBS --compare --driver $DRIVER --port 8000 -vv + compare-html-server /repo/$REF /repo/$OBS --compare --max-workers 4 --driver $DRIVER --port 8000 -vv From 47895966fb0f8ce274051e0d405fcef26ccef9d9 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Sat, 4 Jul 2026 14:38:12 +0200 Subject: [PATCH 3/5] PDF: don't use built-in AFM widths after an explicit /Encoding For a non-embedded standard-14 font with an explicit /Encoding whose glyph name is absent from the AFM table, advance_width fell through to the built-in code->width table, returning the width of an unrelated glyph at the same numeric code. An explicit encoding overrides the font's own code->glyph mapping, so the built-in table no longer applies; fall back to /MissingWidth instead. The built-in table is now consulted only when there is no /Encoding (the Symbol/ZapfDingbats case). Fixes the DocumentParser.simple_font_widths failure: a base-14 /BaseFont now resolves AFM metrics, so the test's /MissingWidth fallback for the uncovered code was masked by the AFM 'C' width. The fixture now remaps that code via /Encoding to a glyph absent from the AFM, exercising both the /MissingWidth fallback and the fix above. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Q692zQuW77YFk32yShHCmL --- src/odr/internal/pdf/pdf_document.cpp | 16 ++++++++++------ test/src/internal/pdf/pdf_document_parser.cpp | 13 ++++++++++--- test/src/internal/pdf/pdf_font.cpp | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/odr/internal/pdf/pdf_document.cpp b/src/odr/internal/pdf/pdf_document.cpp index ea77900c..9c8556e7 100644 --- a/src/odr/internal/pdf/pdf_document.cpp +++ b/src/odr/internal/pdf/pdf_document.cpp @@ -46,12 +46,14 @@ double Font::advance_width(const std::uint32_t code) const { } // Non-embedded standard-14 fonts usually ship no `/Widths`: fall back to the // substitute's AFM metrics (ISO 32000-1 9.6.2.2) so placement stays correct. - // The `/Encoding` (a `/Differences` override or a base encoding) names the - // glyph; without one, the font's built-in encoding (the AFM's own codes) is - // the fallback — the Symbol/ZapfDingbats case. if (substitute && substitute->metrics && code <= 0xFF) { const StandardFont metrics = *substitute->metrics; if (encoding) { + // An explicit `/Encoding` (a `/Differences` override or a base encoding) + // names the glyph; look that name up only. The built-in code table + // assumes the font's own code->glyph mapping, which the encoding + // overrides, so consulting it on a miss would return an unrelated glyph's + // width — fall through to `/MissingWidth` instead. if (const std::string_view name = encoding->glyph_name(static_cast(code)); !name.empty()) { @@ -59,9 +61,11 @@ double Font::advance_width(const std::uint32_t code) const { return *width / 1000.0; } } - } - if (const std::optional width = - afm_code_width(metrics, static_cast(code))) { + } else if (const std::optional width = + afm_code_width(metrics, static_cast(code))) { + // No `/Encoding`: the font's built-in encoding (the AFM's own codes) maps + // code->glyph — the Symbol/ZapfDingbats case (text fonts default to + // StandardEncoding). return *width / 1000.0; } } diff --git a/test/src/internal/pdf/pdf_document_parser.cpp b/test/src/internal/pdf/pdf_document_parser.cpp index da31b557..e5fd8695 100644 --- a/test/src/internal/pdf/pdf_document_parser.cpp +++ b/test/src/internal/pdf/pdf_document_parser.cpp @@ -263,8 +263,12 @@ std::string simple_font_mini_pdf() { .object("<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] " "/Resources << /Font << /F1 5 0 R >> >> /Contents 4 0 R >>") .stream_object("", "BT ET") + // `/Encoding` remaps code 67 to a glyph absent from the AFM table, so its + // advance can only come from `/MissingWidth` — not the substitute's + // built-in code->width table, which the explicit encoding overrides. .object("<< /Type /Font /Subtype /TrueType /BaseFont /Helvetica " "/FirstChar 65 /LastChar 66 /Widths [500 600] " + "/Encoding << /Differences [67 /customglyph] >> " "/FontDescriptor 6 0 R >>") .object("<< /Type /FontDescriptor /FontName /Helvetica " "/MissingWidth 250 >>"); @@ -420,6 +424,8 @@ TEST(DocumentParser, shared_form_xobject_is_parsed_once) { } // A simple font's `/FirstChar`, `/Widths` and `/MissingWidth` drive advances. +// Code 67 is outside `/Widths` and its `/Encoding` glyph is absent from the +// substitute's AFM table, so it falls back to `/MissingWidth`. TEST(DocumentParser, simple_font_widths) { const std::string pdf = simple_font_mini_pdf(); DocumentParser parser(std::make_unique(pdf)); @@ -429,9 +435,10 @@ TEST(DocumentParser, simple_font_widths) { ASSERT_NE(font, nullptr); EXPECT_FALSE(font->composite); EXPECT_EQ(font->first_char, 65); - EXPECT_DOUBLE_EQ(font->advance_width(65), 0.5); // 'A' - EXPECT_DOUBLE_EQ(font->advance_width(66), 0.6); // 'B' - EXPECT_DOUBLE_EQ(font->advance_width(67), 0.25); // 'C' -> /MissingWidth + EXPECT_DOUBLE_EQ(font->advance_width(65), 0.5); // 'A' + EXPECT_DOUBLE_EQ(font->advance_width(66), 0.6); // 'B' + EXPECT_DOUBLE_EQ(font->advance_width(67), + 0.25); // /customglyph -> /MissingWidth } // Recovery: a valid file with garbage prepended (the real fixture diff --git a/test/src/internal/pdf/pdf_font.cpp b/test/src/internal/pdf/pdf_font.cpp index ea270dad..6d905001 100644 --- a/test/src/internal/pdf/pdf_font.cpp +++ b/test/src/internal/pdf/pdf_font.cpp @@ -297,3 +297,17 @@ TEST(PdfFont, advance_width_explicit_widths_win_over_afm) { EXPECT_NEAR(font.advance_width('A'), 1.0, 1e-9); // from /Widths EXPECT_NEAR(font.advance_width('B'), 0.667, 1e-9); // out of range -> AFM } + +TEST(PdfFont, advance_width_explicit_encoding_miss_uses_missing_width) { + // An explicit /Encoding names a glyph absent from the AFM table. The built-in + // code->width table assumes the font's own encoding, which the /Differences + // override replaces, so it must not be consulted — the advance is + // /MissingWidth, not the width of whatever glyph sits at the same code. + Font font; + font.substitute = pdf::resolve_font_substitute("Helvetica", 0, 0, 0); + font.encoding.emplace(pdf::BaseEncoding::standard); + font.encoding->set_difference('C', "customglyph"); // code 67, AFM 'C' = 722 + font.missing_width = 250.0; + + EXPECT_NEAR(font.advance_width('C'), 0.25, 1e-9); +} From 841d87284d1a48c4937ce25ff61e8b8a93f49109 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Sat, 4 Jul 2026 15:11:42 +0200 Subject: [PATCH 4/5] cleanup --- src/odr/internal/pdf/pdf_afm.cpp | 25 +++++++++++--------- src/odr/internal/pdf/pdf_afm.hpp | 2 +- src/odr/internal/pdf/pdf_document_parser.cpp | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/odr/internal/pdf/pdf_afm.cpp b/src/odr/internal/pdf/pdf_afm.cpp index b78597b2..3d6fd02b 100644 --- a/src/odr/internal/pdf/pdf_afm.cpp +++ b/src/odr/internal/pdf/pdf_afm.cpp @@ -42,7 +42,7 @@ std::string normalize_name(std::string_view base_font) { return result; } -bool contains(const std::string &haystack, std::string_view needle) { +bool contains(const std::string &haystack, const std::string_view needle) { return haystack.find(needle) != std::string::npos; } @@ -141,10 +141,13 @@ std::string_view family_stack(const Family family) { } // namespace -FontSubstitute resolve_font_substitute(const std::string_view base_font, - const std::uint32_t flags, - const int font_weight, - const double italic_angle) { +} // namespace odr::internal::pdf + +namespace odr::internal { + +pdf::FontSubstitute pdf::resolve_font_substitute( + const std::string_view base_font, const std::uint32_t flags, + const std::int32_t font_weight, const double italic_angle) { const std::string name = normalize_name(base_font); const Family family = classify_family(name, flags); @@ -164,8 +167,8 @@ FontSubstitute resolve_font_substitute(const std::string_view base_font, return substitute; } -std::optional afm_width(const StandardFont font, - const std::string_view glyph_name) { +std::optional pdf::afm_width(const StandardFont font, + const std::string_view glyph_name) { const afm_data::FontMetrics &m = metrics_of(font); const afm_data::GlyphWidth *const begin = m.glyphs; const afm_data::GlyphWidth *const end = m.glyphs + m.glyph_count; @@ -180,8 +183,8 @@ std::optional afm_width(const StandardFont font, return std::nullopt; } -std::optional afm_code_width(const StandardFont font, - const std::uint8_t code) { +std::optional pdf::afm_code_width(const StandardFont font, + const std::uint8_t code) { const std::int16_t width = metrics_of(font).code_widths[code]; if (width < 0) { return std::nullopt; @@ -189,8 +192,8 @@ std::optional afm_code_width(const StandardFont font, return width; } -double afm_ascender(const StandardFont font) { +double pdf::afm_ascender(const StandardFont font) { return metrics_of(font).ascender / 1000.0; } -} // namespace odr::internal::pdf +} // namespace odr::internal diff --git a/src/odr/internal/pdf/pdf_afm.hpp b/src/odr/internal/pdf/pdf_afm.hpp index df3c74e8..51ea401d 100644 --- a/src/odr/internal/pdf/pdf_afm.hpp +++ b/src/odr/internal/pdf/pdf_afm.hpp @@ -50,7 +50,7 @@ struct FontSubstitute { /// back to a sans-serif stack with Helvetica metrics. [[nodiscard]] FontSubstitute resolve_font_substitute(std::string_view base_font, std::uint32_t flags, - int font_weight, + std::int32_t font_weight, double italic_angle); /// The advance width of a glyph (by name) in `font`, glyph space (1/1000 em), diff --git a/src/odr/internal/pdf/pdf_document_parser.cpp b/src/odr/internal/pdf/pdf_document_parser.cpp index f192080f..f6ac7d42 100644 --- a/src/odr/internal/pdf/pdf_document_parser.cpp +++ b/src/odr/internal/pdf/pdf_document_parser.cpp @@ -396,7 +396,7 @@ void resolve_font_substitute(DocumentParser &parser, } std::uint32_t flags = 0; - int font_weight = 0; + std::int32_t font_weight = 0; double italic_angle = 0; if (dictionary.has_key("FontDescriptor")) { const Object descriptor = From fd62a35bb8606f358f16a2f78efaa5e54d7b1734 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Sat, 4 Jul 2026 15:18:33 +0200 Subject: [PATCH 5/5] update refs --- test/data/reference-output/odr-private | 2 +- test/data/reference-output/odr-public | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/data/reference-output/odr-private b/test/data/reference-output/odr-private index 2fcb3cc6..6f566027 160000 --- a/test/data/reference-output/odr-private +++ b/test/data/reference-output/odr-private @@ -1 +1 @@ -Subproject commit 2fcb3cc602a01d4f1748dff81272aca47f76e984 +Subproject commit 6f5660279089928d58cffc0c5db5150aabf142b3 diff --git a/test/data/reference-output/odr-public b/test/data/reference-output/odr-public index 11d25580..7a463924 160000 --- a/test/data/reference-output/odr-public +++ b/test/data/reference-output/odr-public @@ -1 +1 @@ -Subproject commit 11d25580d79ca25ed799d517fa0a37868178ea39 +Subproject commit 7a463924c3846bd93d07a36181dc876d6d86d700