diff options
Diffstat (limited to 'Build/source/texk/web2c/mfluadir/otfcc/lib/table/vdmx/funcs.c')
-rw-r--r-- | Build/source/texk/web2c/mfluadir/otfcc/lib/table/vdmx/funcs.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mfluadir/otfcc/lib/table/vdmx/funcs.c b/Build/source/texk/web2c/mfluadir/otfcc/lib/table/vdmx/funcs.c new file mode 100644 index 00000000000..ec6d0691b43 --- /dev/null +++ b/Build/source/texk/web2c/mfluadir/otfcc/lib/table/vdmx/funcs.c @@ -0,0 +1,150 @@ +#include "../VDMX.h" + +#include "support/util.h" +#include "bk/bkgraph.h" + +table_VDMX *otfcc_readVDMX(const otfcc_Packet packet, const otfcc_Options *options) { + table_VDMX *vdmx = NULL; + FOR_TABLE(OTFCC_CHR('V','D','M','X'), table) { + if (table.length < 6) goto FAIL; + uint16_t version = read_16u(table.data + 0); + uint16_t numRatios = read_16u(table.data + 4); + if (table.length < 6 + 6 * numRatios) goto FAIL; + + vdmx = table_iVDMX.create(); + vdmx->version = version; + for (shapeid_t g = 0; g < numRatios; g++) { + const size_t ratioRangeOffset = 6 + 4 * g; + const size_t offsetOffset = 6 + 4 * numRatios + 2 * g; + vdmx_RatioRange r; + vdmx_iRatioRange.init(&r); + r.bCharset = read_8u(table.data + ratioRangeOffset + 0); + r.xRatio = read_8u(table.data + ratioRangeOffset + 1); + r.yStartRatio = read_8u(table.data + ratioRangeOffset + 2); + r.yEndRatio = read_8u(table.data + ratioRangeOffset + 3); + + uint16_t groupOffset = read_16u(table.data + offsetOffset); + uint16_t recs = read_16u(table.data + groupOffset + 0); + for (uint16_t j = 0; j < recs; j++) { + uint16_t yPelHeight = read_16u(table.data + groupOffset + 4 + j * 6 + 0); + int16_t yMax = read_16s(table.data + groupOffset + 4 + j * 6 + 2); + int16_t yMin = read_16s(table.data + groupOffset + 4 + j * 6 + 4); + vdmx_iGroup.push(&r.records, (vdmx_Record){ + .yPelHeight = yPelHeight, + .yMax = yMax, + .yMin = yMin, + }); + } + vdmx_iRatioRangeList.push(&vdmx->ratios, r); + } + return vdmx; + FAIL: + logWarning("Table 'VDMX' corrupted.\n"); + table_iVDMX.free(vdmx); + vdmx = NULL; + } + return vdmx; +} + +void otfcc_dumpVDMX(const table_VDMX *vdmx, json_value *root, const otfcc_Options *options) { + if (!vdmx) return; + loggedStep("VDMX") { + json_value *_vdmx = json_object_new(2); + json_object_push(_vdmx, "version", json_integer_new(vdmx->version)); + + json_value *_ratios = json_array_new(vdmx->ratios.length); + json_object_push(_vdmx, "ratios", _ratios); + foreach (vdmx_RatioRange *rr, vdmx->ratios) { + json_value *_rr = json_object_new(5); + json_array_push(_ratios, _rr); + json_object_push(_rr, "bCharset", json_integer_new(rr->bCharset)); + json_object_push(_rr, "xRatio", json_integer_new(rr->xRatio)); + json_object_push(_rr, "yStartRatio", json_integer_new(rr->yStartRatio)); + json_object_push(_rr, "yEndRatio", json_integer_new(rr->yEndRatio)); + + json_value *_records = json_array_new(rr->records.length); + json_object_push(_rr, "records", _records); + foreach (vdmx_Record *r, rr->records) { + json_value *_r = json_object_new(3); + json_array_push(_records, _r); + json_object_push(_r, "yPelHeight", json_integer_new(r->yPelHeight)); + json_object_push(_r, "yMax", json_integer_new(r->yMax)); + json_object_push(_r, "yMin", json_integer_new(r->yMin)); + } + } + json_object_push(root, "VDMX", _vdmx); + } +} + +table_VDMX *otfcc_parseVDMX(const json_value *root, const otfcc_Options *options) { + json_value *_vdmx = NULL; + if (!(_vdmx = json_obj_get_type(root, "VDMX", json_object))) return NULL; + table_VDMX *vdmx = table_iVDMX.create(); + loggedStep("VDMX") { + vdmx->version = json_obj_getnum(_vdmx, "version"); + json_value *_ratios = json_obj_get_type(_vdmx, "ratios", json_array); + for (size_t j = 0; j < _ratios->u.array.length; j++) { + json_value *_rr = _ratios->u.array.values[j]; + if (!_rr || _rr->type != json_object) continue; + vdmx_RatioRange r; + vdmx_iRatioRange.init(&r); + r.bCharset = json_obj_getnum(_rr, "bCharset"); + r.xRatio = json_obj_getnum(_rr, "xRatio"); + r.yStartRatio = json_obj_getnum(_rr, "yStartRatio"); + r.yEndRatio = json_obj_getnum(_rr, "yEndRatio"); + json_value *_records = json_obj_get_type(_rr, "records", json_array); + if (!_records) { + vdmx_iRatioRange.dispose(&r); + continue; + } + for (size_t j = 0; j < _records->u.array.length; j++) { + json_value *_r = _records->u.array.values[j]; + if (!_r || _r->type != json_object) continue; + vdmx_iGroup.push(&r.records, (vdmx_Record){ + .yPelHeight = json_obj_getnum(_r, "yPelHeight"), + .yMax = json_obj_getnum(_r, "yMax"), + .yMin = json_obj_getnum(_r, "yMin"), + }); + } + vdmx_iRatioRangeList.push(&vdmx->ratios, r); + } + } + return vdmx; +} + +caryll_Buffer *otfcc_buildVDMX(const table_VDMX *vdmx, const otfcc_Options *options) { + if (!vdmx || !vdmx->ratios.length) return NULL; + bk_Block *root = bk_new_Block(b16, vdmx->version, // Version + b16, vdmx->ratios.length, // numRecs + b16, vdmx->ratios.length, // numRatios + bkover); + foreach (vdmx_RatioRange *rr, vdmx->ratios) { + bk_push(root, // RatioRange + b8, rr->bCharset, // bCharset + b8, rr->xRatio, // bCharset + b8, rr->yStartRatio, // bCharset + b8, rr->yEndRatio, // bCharset + bkover); + } + foreach (vdmx_RatioRange *rr, vdmx->ratios) { + uint16_t startsz = 0xFFFF; + uint16_t endsz = 0; + foreach (vdmx_Record *r, rr->records) { + if (startsz > r->yPelHeight) startsz = r->yPelHeight; + if (endsz < r->yPelHeight) endsz = r->yPelHeight; + } + bk_Block *group = bk_new_Block(b16, rr->records.length, // recs + b8, startsz, // + b8, endsz, // + bkover); + foreach (vdmx_Record *r, rr->records) { + bk_push(group, // + b16, r->yPelHeight, // + b16, r->yMax, // + b16, r->yMin, // + bkover); + } + bk_push(root, p16, group, bkover); + } + return bk_build_Block_noMinimize(root); +} |