summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mfluadir/otfcc/lib/table/_TSI.c
diff options
context:
space:
mode:
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.c241
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;
+}