summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mfluadir/otfcc/lib/table/otl/subtables/gsub-single.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/mfluadir/otfcc/lib/table/otl/subtables/gsub-single.c')
-rw-r--r--Build/source/texk/web2c/mfluadir/otfcc/lib/table/otl/subtables/gsub-single.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mfluadir/otfcc/lib/table/otl/subtables/gsub-single.c b/Build/source/texk/web2c/mfluadir/otfcc/lib/table/otl/subtables/gsub-single.c
new file mode 100644
index 00000000000..fa1ac665ade
--- /dev/null
+++ b/Build/source/texk/web2c/mfluadir/otfcc/lib/table/otl/subtables/gsub-single.c
@@ -0,0 +1,139 @@
+#include "gsub-single.h"
+
+static void gss_entry_ctor(MODIFY otl_GsubSingleEntry *entry) {
+ entry->from = Handle.empty();
+ entry->to = Handle.empty();
+}
+static void gss_entry_copyctor(MODIFY otl_GsubSingleEntry *dst,
+ COPY const otl_GsubSingleEntry *src) {
+ dst->from = Handle.dup(src->from);
+ dst->to = Handle.dup(src->to);
+}
+static void gss_entry_dtor(MODIFY otl_GsubSingleEntry *entry) {
+ Handle.dispose(&entry->from);
+ Handle.dispose(&entry->to);
+}
+
+static caryll_ElementInterface(otl_GsubSingleEntry) gss_typeinfo = {
+ .init = gss_entry_ctor, .copy = gss_entry_copyctor, .dispose = gss_entry_dtor};
+
+caryll_standardVectorImpl(subtable_gsub_single, otl_GsubSingleEntry, gss_typeinfo,
+ iSubtable_gsub_single);
+
+otl_Subtable *otl_read_gsub_single(const font_file_pointer data, uint32_t tableLength,
+ uint32_t subtableOffset, const glyphid_t maxGlyphs,
+ const otfcc_Options *options) {
+ subtable_gsub_single *subtable = iSubtable_gsub_single.create();
+ otl_Coverage *from = NULL;
+ otl_Coverage *to = NULL;
+ if (tableLength < subtableOffset + 6) goto FAIL;
+
+ uint16_t subtableFormat = read_16u(data + subtableOffset);
+ from = Coverage.read(data, tableLength, subtableOffset + read_16u(data + subtableOffset + 2));
+ if (!from || from->numGlyphs == 0) goto FAIL;
+
+ if (subtableFormat == 1) {
+ NEW(to);
+ to->numGlyphs = from->numGlyphs;
+ NEW(to->glyphs, to->numGlyphs);
+
+ uint16_t delta = read_16u(data + subtableOffset + 4);
+ for (glyphid_t j = 0; j < from->numGlyphs; j++) {
+ to->glyphs[j] = Handle.fromIndex(from->glyphs[j].index + delta);
+ }
+ } else {
+ glyphid_t toglyphs = read_16u(data + subtableOffset + 4);
+ if (tableLength < subtableOffset + 6 + toglyphs * 2 || toglyphs != from->numGlyphs)
+ goto FAIL;
+ NEW(to);
+ to->numGlyphs = toglyphs;
+ NEW(to->glyphs, to->numGlyphs);
+
+ for (glyphid_t j = 0; j < to->numGlyphs; j++) {
+ to->glyphs[j] = Handle.fromIndex(read_16u(data + subtableOffset + 6 + j * 2));
+ }
+ }
+ goto OK;
+FAIL:
+ iSubtable_gsub_single.free(subtable);
+ if (from) Coverage.free(from);
+ if (to) Coverage.free(to);
+ return NULL;
+OK:
+ for (glyphid_t j = 0; j < from->numGlyphs; j++) {
+ iSubtable_gsub_single.push(subtable, ((otl_GsubSingleEntry){
+ .from = Handle.dup(from->glyphs[j]), // from
+ .to = Handle.dup(to->glyphs[j]), // to
+ }));
+ }
+ if (from) Coverage.free(from);
+ if (to) Coverage.free(to);
+ return (otl_Subtable *)subtable;
+}
+
+json_value *otl_gsub_dump_single(const otl_Subtable *_subtable) {
+ const subtable_gsub_single *subtable = &(_subtable->gsub_single);
+ json_value *st = json_object_new(subtable->length);
+ for (size_t j = 0; j < subtable->length; j++) {
+ json_object_push(st, subtable->items[j].from.name,
+ json_string_new(subtable->items[j].to.name));
+ }
+ return st;
+}
+
+otl_Subtable *otl_gsub_parse_single(const json_value *_subtable, const otfcc_Options *options) {
+ subtable_gsub_single *subtable = iSubtable_gsub_single.create();
+ for (glyphid_t j = 0; j < _subtable->u.object.length; j++) {
+ if (_subtable->u.object.values[j].value &&
+ _subtable->u.object.values[j].value->type == json_string) {
+ glyph_handle from = Handle.fromName(sdsnewlen(
+ _subtable->u.object.values[j].name, _subtable->u.object.values[j].name_length));
+ glyph_handle to =
+ Handle.fromName(sdsnewlen(_subtable->u.object.values[j].value->u.string.ptr,
+ _subtable->u.object.values[j].value->u.string.length));
+ iSubtable_gsub_single.push(subtable, ((otl_GsubSingleEntry){.from = from, .to = to}));
+ }
+ }
+ return (otl_Subtable *)subtable;
+};
+
+caryll_Buffer *otfcc_build_gsub_single_subtable(const otl_Subtable *_subtable, otl_BuildHeuristics heuristics) {
+ const subtable_gsub_single *subtable = &(_subtable->gsub_single);
+ bool isConstantDifference = subtable->length > 0;
+ if (isConstantDifference) {
+ int32_t difference = subtable->items[0].to.index - subtable->items[0].from.index;
+ isConstantDifference = isConstantDifference && difference < 0x8000 && difference > -0x8000;
+ for (glyphid_t j = 1; j < subtable->length; j++) {
+ int32_t diffJ = subtable->items[j].to.index - subtable->items[j].from.index;
+ isConstantDifference = isConstantDifference && diffJ == difference
+ && diffJ < 0x8000 && diffJ > -0x8000;
+ }
+ }
+ otl_Coverage *cov = Coverage.create();
+ for (glyphid_t j = 0; j < subtable->length; j++) {
+ Coverage.push(cov, Handle.dup(subtable->items[j].from));
+ }
+
+ caryll_Buffer *coverageBuf = Coverage.buildFormat(cov, heuristics & OTL_BH_GSUB_VERT ? 1 : 0);
+
+ if (isConstantDifference && !(heuristics & OTL_BH_GSUB_VERT)) {
+ bk_Block *b =
+ bk_new_Block(b16, 1, // Format
+ p16, bk_newBlockFromBuffer(coverageBuf), // coverage
+ b16,
+ subtable->items[0].to.index - subtable->items[0].from.index, // delta
+ bkover);
+ Coverage.free(cov);
+ return bk_build_Block(b);
+ } else {
+ bk_Block *b = bk_new_Block(b16, 2, // Format
+ p16, bk_newBlockFromBuffer(coverageBuf), // coverage
+ b16, subtable->length, // quantity
+ bkover);
+ for (glyphid_t k = 0; k < subtable->length; k++) {
+ bk_push(b, b16, subtable->items[k].to.index, bkover);
+ }
+ Coverage.free(cov);
+ return bk_build_Block(b);
+ }
+}