diff options
Diffstat (limited to 'Build/source/texk/web2c/mfluadir/otfcc/lib/table/otl/subtables/gpos-single.c')
-rw-r--r-- | Build/source/texk/web2c/mfluadir/otfcc/lib/table/otl/subtables/gpos-single.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mfluadir/otfcc/lib/table/otl/subtables/gpos-single.c b/Build/source/texk/web2c/mfluadir/otfcc/lib/table/otl/subtables/gpos-single.c new file mode 100644 index 00000000000..d1f42faa94c --- /dev/null +++ b/Build/source/texk/web2c/mfluadir/otfcc/lib/table/otl/subtables/gpos-single.c @@ -0,0 +1,129 @@ +#include "gpos-single.h" +#include "gpos-common.h" + +static void deleteGposSingleEntry(otl_GposSingleEntry *entry) { + Handle.dispose(&entry->target); +} + +static caryll_ElementInterface(otl_GposSingleEntry) gss_typeinfo = { + .init = NULL, .copy = NULL, .dispose = deleteGposSingleEntry}; + +caryll_standardVectorImpl(subtable_gpos_single, otl_GposSingleEntry, gss_typeinfo, + iSubtable_gpos_single); + +otl_Subtable *otl_read_gpos_single(const font_file_pointer data, uint32_t tableLength, + uint32_t offset, const glyphid_t maxGlyphs, + const otfcc_Options *options) { + subtable_gpos_single *subtable = iSubtable_gpos_single.create(); + otl_Coverage *targets = NULL; + + checkLength(offset + 6); + + uint16_t subtableFormat = read_16u(data + offset); + targets = Coverage.read(data, tableLength, offset + read_16u(data + offset + 2)); + if (!targets || targets->numGlyphs == 0) goto FAIL; + + if (subtableFormat == 1) { + otl_PositionValue v = + read_gpos_value(data, tableLength, offset + 6, read_16u(data + offset + 4)); + for (glyphid_t j = 0; j < targets->numGlyphs; j++) { + iSubtable_gpos_single.push(subtable, + ((otl_GposSingleEntry){ + .target = Handle.dup(targets->glyphs[j]), .value = v, + })); + } + } else { + uint16_t valueFormat = read_16u(data + offset + 4); + uint16_t valueCount = read_16u(data + offset + 6); + checkLength(offset + 8 + position_format_length(valueFormat) * valueCount); + if (valueCount != targets->numGlyphs) goto FAIL; + + for (glyphid_t j = 0; j < targets->numGlyphs; j++) { + iSubtable_gpos_single.push( + subtable, + ((otl_GposSingleEntry){ + .target = Handle.dup(targets->glyphs[j]), + .value = read_gpos_value(data, tableLength, + offset + 8 + j * position_format_length(valueFormat), + valueFormat), + })); + } + } + if (targets) Coverage.free(targets); + return (otl_Subtable *)subtable; + +FAIL: + if (targets) Coverage.free(targets); + iSubtable_gpos_single.free(subtable); + return NULL; +} + +json_value *otl_gpos_dump_single(const otl_Subtable *_subtable) { + const subtable_gpos_single *subtable = &(_subtable->gpos_single); + json_value *st = json_object_new(subtable->length); + for (glyphid_t j = 0; j < subtable->length; j++) { + json_object_push(st, subtable->items[j].target.name, + gpos_dump_value(subtable->items[j].value)); + } + return st; +} +otl_Subtable *otl_gpos_parse_single(const json_value *_subtable, const otfcc_Options *options) { + subtable_gpos_single *subtable = iSubtable_gpos_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_object) { + sds gname = sdsnewlen(_subtable->u.object.values[j].name, + _subtable->u.object.values[j].name_length); + iSubtable_gpos_single.push( + subtable, ((otl_GposSingleEntry){ + .target = Handle.fromName(gname), + .value = gpos_parse_value(_subtable->u.object.values[j].value), + })); + } + } + return (otl_Subtable *)subtable; +} + +caryll_Buffer *otfcc_build_gpos_single(const otl_Subtable *_subtable, otl_BuildHeuristics heuristics) { + const subtable_gpos_single *subtable = &(_subtable->gpos_single); + bool isConst = subtable->length > 0; + uint16_t format = 0; + if (subtable->length > 0) { + for (glyphid_t j = 0; j < subtable->length; j++) { + isConst = isConst && (subtable->items[j].value.dx == subtable->items[0].value.dx) && + (subtable->items[j].value.dy == subtable->items[0].value.dy) && + (subtable->items[j].value.dWidth == subtable->items[0].value.dWidth) && + (subtable->items[j].value.dHeight == subtable->items[0].value.dHeight); + format |= required_position_format(subtable->items[j].value); + } + } + otl_Coverage *cov = Coverage.create(); + for (glyphid_t j = 0; j < subtable->length; j++) { + Coverage.push(cov, Handle.dup(subtable->items[j].target)); + } + + caryll_Buffer *coverageBuf = Coverage.build(cov); + + if (isConst) { + bk_Block *b = + (bk_new_Block(b16, 1, // Format + p16, bk_newBlockFromBuffer(coverageBuf), // coverage + b16, format, // format + bkembed, bk_gpos_value(subtable->items[0].value, format), // value + 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, format, // format + b16, subtable->length, // quantity + bkover); + for (glyphid_t k = 0; k < subtable->length; k++) { + bk_push(b, bkembed, bk_gpos_value(subtable->items[k].value, format), // value + bkover); + } + Coverage.free(cov); + return bk_build_Block(b); + } +} |