diff options
Diffstat (limited to 'Build/source/texk/web2c/mfluadir/otfcc/lib/table/_TSI.c')
-rw-r--r-- | Build/source/texk/web2c/mfluadir/otfcc/lib/table/_TSI.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mfluadir/otfcc/lib/table/_TSI.c b/Build/source/texk/web2c/mfluadir/otfcc/lib/table/_TSI.c new file mode 100644 index 00000000000..24279cf03e7 --- /dev/null +++ b/Build/source/texk/web2c/mfluadir/otfcc/lib/table/_TSI.c @@ -0,0 +1,241 @@ +#include "_TSI.h" +#include "support/util.h" + +static INLINE void initTSIEntry(tsi_Entry *entry) { + Handle.init(&entry->glyph); + entry->type = TSI_GLYPH; + entry->content = NULL; +} +static INLINE void copyTSIEntry(tsi_Entry *dst, const tsi_Entry *src) { + Handle.copy(&dst->glyph, &src->glyph); + dst->type = src->type; + dst->content = sdsdup(src->content); +} +static INLINE void disposeTSIEntry(tsi_Entry *entry) { + Handle.dispose(&entry->glyph); + sdsfree(entry->content); +} +caryll_standardType(tsi_Entry, tsi_iEntry, initTSIEntry, copyTSIEntry, disposeTSIEntry); +caryll_standardVectorImpl(table_TSI, tsi_Entry, tsi_iEntry, table_iTSI); + +static INLINE bool isValidGID(uint16_t gid, uint32_t tagIndex) { + if (tagIndex == OTFCC_CHR('T','S','I','0')) { + return gid != 0xFFFE && gid != 0xFFFC; + } else { + return gid < 0xFFFA; + } +} + +table_TSI *otfcc_readTSI(const otfcc_Packet packet, const otfcc_Options *options, uint32_t tagIndex, + uint32_t tagText) { + otfcc_PacketPiece textPart; + textPart.tag = 0; + otfcc_PacketPiece indexPart; + indexPart.tag = 0; + FOR_TABLE(tagIndex, tableIx) { + indexPart = tableIx; + } + FOR_TABLE(tagText, tableTx) { + textPart = tableTx; + } + if (!textPart.tag || !indexPart.tag) return NULL; + + table_TSI *tsi = table_iTSI.create(); + for (uint32_t j = 0; j * 8 < indexPart.length; j++) { + uint16_t gid = read_16u(indexPart.data + j * 8); + uint32_t textLength = read_16u(indexPart.data + j * 8 + 2); + uint32_t textOffset = read_32u(indexPart.data + j * 8 + 4); + if (!isValidGID(gid, tagIndex) || textOffset >= textPart.length || !textLength) continue; + // acquire next valid entry to retreve length of text of this entry + uint32_t predictedTextLength = textPart.length - textOffset; + for (glyphid_t k = j + 1; k * 8 < indexPart.length; k++) { + uint16_t gidK = read_16u(indexPart.data + k * 8); + uint32_t textOffsetK = read_32u(indexPart.data + k * 8 + 4); + if (gidK != 0xFFFE && textOffsetK < textPart.length && textOffsetK > textOffset) { + predictedTextLength = textOffsetK - textOffset; + break; + } + } + if (textLength >= 0x8000) { textLength = predictedTextLength; } + // push entry + tsi_Entry entry; + switch (gid) { + case 0xFFFA: + entry.type = TSI_PREP; + Handle.init(&entry.glyph); + break; + case 0xFFFB: + entry.type = TSI_CVT; + Handle.init(&entry.glyph); + break; + case 0xFFFD: + entry.type = TSI_FPGM; + Handle.init(&entry.glyph); + break; + default: + entry.type = TSI_GLYPH; + entry.glyph = Handle.fromIndex(gid); + break; + } + entry.content = sdsnewlen(textPart.data + textOffset, textLength); + table_iTSI.push(tsi, entry); + } + return tsi; +} + +void otfcc_dumpTSI(const table_TSI *tsi, json_value *root, const otfcc_Options *options, + const char *tag) { + if (!tsi) return; + loggedStep("%s", tag) { + json_value *_tsi = json_object_new(2); + json_value *_glyphs = json_object_new(tsi->length); + foreach (tsi_Entry *entry, *tsi) { + if (entry->type != TSI_GLYPH) continue; + json_object_push( + _glyphs, entry->glyph.name, + json_string_new_length((uint32_t)sdslen(entry->content), entry->content)); + } + + json_value *_extra = json_object_new(tsi->length); + foreach (tsi_Entry *entry, *tsi) { + if (entry->type == TSI_GLYPH) continue; + const char *extraKey; + switch (entry->type) { + case TSI_CVT: + extraKey = "cvt"; + break; + case TSI_FPGM: + extraKey = "fpgm"; + break; + break; + case TSI_PREP: + extraKey = "prep"; + break; + default: + extraKey = "reserved"; + break; + } + json_object_push( + _extra, extraKey, + json_string_new_length((uint32_t)sdslen(entry->content), entry->content)); + } + json_object_push(_tsi, "glyphs", _glyphs); + json_object_push(_tsi, "extra", _extra); + json_object_push(root, tag, _tsi); + } +} + +table_TSI *otfcc_parseTSI(const json_value *root, const otfcc_Options *options, const char *tag) { + json_value *_tsi = NULL; + if (!(_tsi = json_obj_get_type(root, tag, json_object))) return NULL; + table_TSI *tsi = table_iTSI.create(); + loggedStep("%s", tag) { + json_value *_glyphs = json_obj_get_type(_tsi, "glyphs", json_object); + if (_glyphs) { + for (uint32_t j = 0; j < _glyphs->u.object.length; j++) { + char *_gid = _glyphs->u.object.values[j].name; + size_t _gidlen = _glyphs->u.object.values[j].name_length; + json_value *_content = _glyphs->u.object.values[j].value; + if (!_content || _content->type != json_string) continue; + table_iTSI.push(tsi, (tsi_Entry){.type = TSI_GLYPH, + .glyph = Handle.fromName(sdsnewlen(_gid, _gidlen)), + .content = sdsnewlen(_content->u.string.ptr, + _content->u.string.length)}); + } + } + json_value *_extra = json_obj_get_type(_tsi, "extra", json_object); + if (_extra) { + for (uint32_t j = 0; j < _extra->u.object.length; j++) { + char *_key = _extra->u.object.values[j].name; + json_value *_content = _extra->u.object.values[j].value; + if (!_content || _content->type != json_string) continue; + if (strcmp(_key, "cvt") == 0) { + table_iTSI.push(tsi, + (tsi_Entry){.type = TSI_CVT, + .glyph = Handle.empty(), + .content = sdsnewlen(_content->u.string.ptr, + _content->u.string.length)}); + } else if (strcmp(_key, "fpgm") == 0) { + table_iTSI.push(tsi, + (tsi_Entry){.type = TSI_FPGM, + .glyph = Handle.empty(), + .content = sdsnewlen(_content->u.string.ptr, + _content->u.string.length)}); + } else if (strcmp(_key, "prep") == 0) { + table_iTSI.push(tsi, + (tsi_Entry){.type = TSI_PREP, + .glyph = Handle.empty(), + .content = sdsnewlen(_content->u.string.ptr, + _content->u.string.length)}); + } + } + } + } + return tsi; +} + +static glyphid_t propergid(tsi_Entry *entry, const tsi_EntryType type) { + switch (type) { + case TSI_CVT: + return 0xFFFB; + case TSI_FPGM: + return 0xFFFD; + case TSI_PREP: + return 0xFFFA; + case TSI_RESERVED_FFFC: + return 0xFFFC; + case TSI_GLYPH: + return entry->glyph.index; + default: + fprintf(stderr,"! warning: propergid: unknown EntryType %u. Return 0x0.\n",type); + return 0x0; + } +} + +static void pushTSIEntries(tsi_BuildTarget *target, const table_TSI *tsi, const tsi_EntryType type, + const glyphid_t minN) { + glyphid_t itemsPushed = 0; + foreach (tsi_Entry *entry, *tsi) { + if (entry->type != type) continue; + size_t lengthSofar = target->textPart->cursor; + bufwrite_sds(target->textPart, entry->content); + size_t lengthAfter = target->textPart->cursor; + bufwrite16b(target->indexPart, propergid(entry, type)); + if (lengthAfter - lengthSofar < 0x8000) { + bufwrite16b(target->indexPart, lengthAfter - lengthSofar); + } else { + bufwrite16b(target->indexPart, 0x8000); + } + bufwrite32b(target->indexPart, (uint32_t)lengthSofar); + itemsPushed += 1; + } + while (itemsPushed < minN) { + bufwrite16b(target->indexPart, propergid(NULL, type)); + bufwrite16b(target->indexPart, 0x0000); + bufwrite32b(target->indexPart, (uint32_t)target->textPart->cursor); + itemsPushed += 1; + } +} + +tsi_BuildTarget otfcc_buildTSI(const table_TSI *tsi, const otfcc_Options *options) { + + tsi_BuildTarget target; + if (!tsi) { + target.textPart = NULL; + target.indexPart = NULL; + } else { + target.textPart = bufnew(); + target.indexPart = bufnew(); + + pushTSIEntries(&target, tsi, TSI_GLYPH, 0); + // magic + bufwrite16b(target.indexPart, 0xFFFE); + bufwrite16b(target.indexPart, 0x0000); + bufwrite32b(target.indexPart, 0xABFC1F34); + pushTSIEntries(&target, tsi, TSI_PREP, 1); + pushTSIEntries(&target, tsi, TSI_CVT, 1); + pushTSIEntries(&target, tsi, TSI_RESERVED_FFFC, 1); + pushTSIEntries(&target, tsi, TSI_FPGM, 1); + } + return target; +} |