summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mfluadir/otfcc/lib/json-reader/json-reader.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/mfluadir/otfcc/lib/json-reader/json-reader.c')
-rw-r--r--Build/source/texk/web2c/mfluadir/otfcc/lib/json-reader/json-reader.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mfluadir/otfcc/lib/json-reader/json-reader.c b/Build/source/texk/web2c/mfluadir/otfcc/lib/json-reader/json-reader.c
new file mode 100644
index 00000000000..6561cf0d7bb
--- /dev/null
+++ b/Build/source/texk/web2c/mfluadir/otfcc/lib/json-reader/json-reader.c
@@ -0,0 +1,181 @@
+#include "support/util.h"
+#include "otfcc/font.h"
+#include "table/all.h"
+
+static otfcc_font_subtype otfcc_decideFontSubtypeFromJson(const json_value *root) {
+ if (json_obj_get_type(root, "CFF_", json_object) != NULL) {
+ return FONTTYPE_CFF;
+ } else {
+ return FONTTYPE_TTF;
+ }
+}
+
+// The default glyph_order object is completed using a two-step construction
+enum { ORD_GLYPHORDER = 1, ORD_NOTDEF = 2, ORD_CMAP = 3, ORD_GLYF = 4 };
+
+// Register a name->(orderType, orderEntry) map.
+static void setOrderByName(otfcc_GlyphOrder *go, sds name, uint8_t orderType, uint32_t orderEntry) {
+ otfcc_GlyphOrderEntry *s = NULL;
+ HASH_FIND(hhName, go->byName, name, sdslen(name), s);
+ if (!s) {
+ NEW(s);
+ s->gid = -1;
+ s->name = name;
+ s->orderType = orderType;
+ s->orderEntry = orderEntry;
+ HASH_ADD(hhName, go->byName, name[0], sdslen(s->name), s);
+ } else if (s->orderType > orderType) {
+ s->orderType = orderType;
+ s->orderEntry = orderEntry;
+ }
+}
+
+static int _byOrder(otfcc_GlyphOrderEntry *a, otfcc_GlyphOrderEntry *b) {
+ if (a->orderType < b->orderType) return (-1);
+ if (a->orderType > b->orderType) return (1);
+ if (a->orderEntry < b->orderEntry) return (-1);
+ if (a->orderEntry > b->orderEntry) return (1);
+ return 0;
+}
+
+// Complete ClyphOrder
+static void orderGlyphs(otfcc_GlyphOrder *go) {
+ HASH_SRT(hhName, go->byName, _byOrder);
+ otfcc_GlyphOrderEntry *current, *temp;
+ glyphid_t gid = 0;
+ HASH_ITER(hhName, go->byName, current, temp) {
+ current->gid = gid;
+ HASH_ADD(hhID, go->byGID, gid, sizeof(glyphid_t), current);
+ gid += 1;
+ }
+}
+
+static void escalateGlyphOrderByName(otfcc_GlyphOrder *go, sds name, uint8_t orderType,
+ uint32_t orderEntry) {
+ otfcc_GlyphOrderEntry *s = NULL;
+ HASH_FIND(hhName, go->byName, name, sdslen(name), s);
+ if (s && s->orderType > orderType) {
+ s->orderType = orderType;
+ s->orderEntry = orderEntry;
+ }
+}
+
+static void placeOrderEntriesFromGlyf(json_value *table, otfcc_GlyphOrder *go) {
+ for (uint32_t j = 0; j < table->u.object.length; j++) {
+ sds gname =
+ sdsnewlen(table->u.object.values[j].name, table->u.object.values[j].name_length);
+ if (strcmp(gname, ".notdef") == 0) {
+ setOrderByName(go, gname, ORD_NOTDEF, 0);
+ } else if (strcmp(gname, ".null") == 0) {
+ setOrderByName(go, gname, ORD_NOTDEF, 1);
+ } else {
+ setOrderByName(go, gname, ORD_GLYF, j);
+ }
+ }
+}
+static void placeOrderEntriesFromCmap(json_value *table, otfcc_GlyphOrder *go) {
+ for (uint32_t j = 0; j < table->u.object.length; j++) {
+ sds unicodeStr =
+ sdsnewlen(table->u.object.values[j].name, table->u.object.values[j].name_length);
+ json_value *item = table->u.object.values[j].value;
+ int32_t unicode;
+ if (sdslen(unicodeStr) > 2 && unicodeStr[0] == 'U' && unicodeStr[1] == '+') {
+ unicode = strtol(unicodeStr + 2, NULL, 16);
+ } else {
+ unicode = atoi(unicodeStr);
+ }
+ sdsfree(unicodeStr);
+ if (item->type == json_string && unicode > 0 &&
+ unicode <= 0x10FFFF) { // a valid unicode codepoint
+ sds gname = sdsnewlen(item->u.string.ptr, item->u.string.length);
+ escalateGlyphOrderByName(go, gname, ORD_CMAP, unicode);
+ sdsfree(gname);
+ }
+ }
+}
+static void placeOrderEntriesFromSubtable(json_value *table, otfcc_GlyphOrder *go, bool zeroOnly) {
+ uint32_t uplimit = table->u.array.length;
+ if (uplimit >= 1 && zeroOnly) { uplimit = 1; }
+ for (uint32_t j = 0; j < uplimit; j++) {
+ json_value *item = table->u.array.values[j];
+ if (item->type == json_string) {
+ sds gname = sdsnewlen(item->u.string.ptr, item->u.string.length);
+ escalateGlyphOrderByName(go, gname, ORD_GLYPHORDER, j);
+ sdsfree(gname);
+ }
+ }
+}
+
+static otfcc_GlyphOrder *parseGlyphOrder(const json_value *root, const otfcc_Options *options) {
+ otfcc_GlyphOrder *go = GlyphOrder.create();
+ if (root->type != json_object) return go;
+ json_value *table;
+
+ if ((table = json_obj_get_type(root, "glyf", json_object))) {
+ placeOrderEntriesFromGlyf(table, go);
+ if ((table = json_obj_get_type(root, "cmap", json_object))) {
+ placeOrderEntriesFromCmap(table, go);
+ }
+ if ((table = json_obj_get_type(root, "glyph_order", json_array))) {
+ bool ignoreGlyphOrder = options->ignore_glyph_order;
+ if (ignoreGlyphOrder && !!json_obj_get_type(root, "SVG_", json_array)) {
+ logNotice("OpenType SVG table detected. Glyph order is preserved.");
+ ignoreGlyphOrder = false;
+ }
+ placeOrderEntriesFromSubtable(table, go, ignoreGlyphOrder);
+ }
+ }
+ orderGlyphs(go);
+ return go;
+}
+
+static otfcc_Font *readJson(void *_root, uint32_t index, const otfcc_Options *options) {
+ const json_value *root = (json_value *)_root;
+ otfcc_Font *font = otfcc_iFont.create();
+ if (!font) return NULL;
+ font->subtype = otfcc_decideFontSubtypeFromJson(root);
+ font->glyph_order = parseGlyphOrder(root, options);
+ font->glyf = otfcc_parseGlyf(root, font->glyph_order, options);
+ font->CFF_ = otfcc_parseCFF(root, options);
+ font->head = otfcc_parseHead(root, options);
+ font->hhea = otfcc_parseHhea(root, options);
+ font->OS_2 = otfcc_parseOS_2(root, options);
+ font->maxp = otfcc_parseMaxp(root, options);
+ font->post = otfcc_parsePost(root, options);
+ font->name = otfcc_parseName(root, options);
+ font->meta = otfcc_parseMeta(root, options);
+ font->cmap = otfcc_parseCmap(root, options);
+ if (!options->ignore_hints) {
+ font->fpgm = otfcc_parseFpgmPrep(root, options, "fpgm");
+ font->prep = otfcc_parseFpgmPrep(root, options, "prep");
+ font->cvt_ = otfcc_parseCvt(root, options, "cvt_");
+ font->gasp = otfcc_parseGasp(root, options);
+ }
+ font->VDMX = otfcc_parseVDMX(root, options);
+ font->vhea = otfcc_parseVhea(root, options);
+ if (font->glyf) {
+ font->GSUB = otfcc_parseOtl(root, options, "GSUB");
+ font->GPOS = otfcc_parseOtl(root, options, "GPOS");
+ font->GDEF = otfcc_parseGDEF(root, options);
+ }
+ font->BASE = otfcc_parseBASE(root, options);
+ font->CPAL = otfcc_parseCPAL(root, options);
+ font->COLR = otfcc_parseCOLR(root, options);
+ font->SVG_ = otfcc_parseSVG(root, options);
+
+ font->TSI_01 = otfcc_parseTSI(root, options, "TSI_01");
+ font->TSI_23 = otfcc_parseTSI(root, options, "TSI_23");
+ font->TSI5 = otfcc_parseTSI5(root, options);
+
+ return font;
+}
+static INLINE void freeReader(otfcc_IFontBuilder *self) {
+ free(self);
+}
+otfcc_IFontBuilder *otfcc_newJsonReader() {
+ otfcc_IFontBuilder *reader;
+ NEW(reader);
+ reader->read = readJson;
+ reader->free = freeReader;
+ return reader;
+}