summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mfluadir/otfcc/lib/table/COLR.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/mfluadir/otfcc/lib/table/COLR.c')
-rw-r--r--Build/source/texk/web2c/mfluadir/otfcc/lib/table/COLR.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mfluadir/otfcc/lib/table/COLR.c b/Build/source/texk/web2c/mfluadir/otfcc/lib/table/COLR.c
new file mode 100644
index 00000000000..6f82b5296b3
--- /dev/null
+++ b/Build/source/texk/web2c/mfluadir/otfcc/lib/table/COLR.c
@@ -0,0 +1,184 @@
+#include "COLR.h"
+
+#include "support/util.h"
+#include "bk/bkgraph.h"
+
+
+static INLINE void initLayer(colr_Layer *layer) {
+ Handle.init(&layer->glyph);
+}
+static INLINE void copyLayer(colr_Layer *dst, const colr_Layer *src) {
+ Handle.copy(&dst->glyph, &src->glyph);
+ dst->paletteIndex = src->paletteIndex;
+}
+static INLINE void disposeLayer(colr_Layer *layer) {
+ Handle.dispose(&layer->glyph);
+}
+caryll_standardType(colr_Layer, colr_iLayer, initLayer, copyLayer, disposeLayer);
+caryll_standardVectorImpl(colr_LayerList, colr_Layer, colr_iLayer, colr_iLayerList);
+
+static INLINE void initMapping(colr_Mapping *mapping) {
+ Handle.init(&mapping->glyph);
+ colr_iLayerList.init(&mapping->layers);
+}
+static INLINE void copyMapping(colr_Mapping *dst, const colr_Mapping *src) {
+ Handle.copy(&dst->glyph, &src->glyph);
+ colr_iLayerList.copy(&dst->layers, &src->layers);
+}
+static INLINE void disposeMapping(colr_Mapping *mapping) {
+ Handle.dispose(&mapping->glyph);
+ colr_iLayerList.dispose(&mapping->layers);
+}
+caryll_standardType(colr_Mapping, colr_iMapping, initMapping, copyMapping, disposeMapping);
+caryll_standardVectorImpl(table_COLR, colr_Mapping, colr_iMapping, table_iCOLR);
+
+static const size_t baseGlyphRecLength = 6;
+static const size_t layerRecLength = 4;
+
+table_COLR *otfcc_readCOLR(const otfcc_Packet packet, const otfcc_Options *options) {
+ table_COLR *colr = NULL;
+ FOR_TABLE(OTFCC_CHR('C','O','L','R'), table) {
+ if (table.length < 14) goto FAIL;
+ uint16_t numBaseGlyphRecords = read_16u(table.data + 2);
+ uint16_t numLayerRecords = read_16u(table.data + 12);
+ uint32_t offsetBaseGlyphRecord = read_32u(table.data + 4);
+ uint32_t offsetLayerRecord = read_32u(table.data + 8);
+ if (table.length < offsetBaseGlyphRecord + baseGlyphRecLength * numBaseGlyphRecords)
+ goto FAIL;
+ if (table.length < offsetLayerRecord + layerRecLength * numLayerRecords) goto FAIL;
+
+ // parse layer data
+ glyphid_t *gids;
+ colorid_t *colors;
+ NEW(gids, numLayerRecords);
+ NEW(colors, numLayerRecords);
+ for (glyphid_t j = 0; j < numLayerRecords; j++) {
+ gids[j] = read_16u(table.data + offsetLayerRecord + layerRecLength * j);
+ colors[j] = read_16u(table.data + offsetLayerRecord + layerRecLength * j + 2);
+ }
+ // parse decomposition data
+ colr = table_iCOLR.create();
+ for (glyphid_t j = 0; j < numBaseGlyphRecords; j++) {
+ colr_Mapping mapping;
+ colr_iMapping.init(&mapping);
+ uint16_t gid = read_16u(table.data + offsetBaseGlyphRecord + baseGlyphRecLength * j);
+ uint16_t firstLayerIndex =
+ read_16u(table.data + offsetBaseGlyphRecord + baseGlyphRecLength * j + 2);
+ uint16_t numLayers =
+ read_16u(table.data + offsetBaseGlyphRecord + baseGlyphRecLength * j + 4);
+
+ glyph_handle baseGlyph = Handle.fromIndex(gid);
+ Handle.move(&mapping.glyph, &baseGlyph);
+ for (glyphid_t k = 0; k < numLayers; k++) {
+ if (k + firstLayerIndex < numLayerRecords) {
+ colr_iLayerList.push(&mapping.layers,
+ (colr_Layer){
+ .glyph = Handle.fromIndex(gids[k + firstLayerIndex]),
+ .paletteIndex = colors[k + firstLayerIndex],
+ });
+ }
+ }
+ table_iCOLR.push(colr, mapping);
+ }
+ return colr;
+ FAIL:
+ logWarning("Table 'COLR' corrupted.\n");
+ table_iCOLR.free(colr);
+ colr = NULL;
+ }
+ return colr;
+}
+
+void otfcc_dumpCOLR(const table_COLR *colr, json_value *root, const otfcc_Options *options) {
+ if (!colr) return;
+ loggedStep("COLR") {
+ json_value *_colr = json_array_new(colr->length);
+ foreach (colr_Mapping *mapping, *colr) {
+ json_value *_map = json_object_new(2);
+ json_object_push(_map, "from", json_string_new(mapping->glyph.name));
+ json_value *_layers = json_array_new(mapping->layers.length);
+ foreach (colr_Layer *layer, mapping->layers) {
+ json_value *_layer = json_object_new(2);
+ json_object_push(_layer, "layer", json_string_new(layer->glyph.name));
+ json_object_push(_layer, "paletteIndex", json_integer_new(layer->paletteIndex));
+ json_array_push(_layers, _layer);
+ }
+ json_object_push(_map, "to", preserialize(_layers));
+ json_array_push(_colr, _map);
+ }
+ json_object_push(root, "COLR", _colr);
+ }
+}
+
+table_COLR *otfcc_parseCOLR(const json_value *root, const otfcc_Options *options) {
+ json_value *_colr = NULL;
+ if (!(_colr = json_obj_get_type(root, "COLR", json_array))) return NULL;
+ table_COLR *colr = table_iCOLR.create();
+ loggedStep("COLR") {
+ for (glyphid_t j = 0; j < _colr->u.array.length; j++) {
+ json_value *_mapping = _colr->u.array.values[j];
+ if (!_mapping || _mapping->type != json_object) continue;
+ json_value *_baseglyph = json_obj_get_type(_mapping, "from", json_string);
+ json_value *_layers = json_obj_get_type(_mapping, "to", json_array);
+ if (!_baseglyph || !_layers) continue;
+
+ colr_Mapping m;
+ colr_iMapping.init(&m);
+ m.glyph =
+ Handle.fromName(sdsnewlen(_baseglyph->u.string.ptr, _baseglyph->u.string.length));
+ for (glyphid_t k = 0; k < _layers->u.array.length; k++) {
+ json_value *_layer = _layers->u.array.values[k];
+ if (!_layer || _layer->type != json_object) continue;
+ json_value *_layerglyph = json_obj_get_type(_layer, "layer", json_string);
+ if (!_layerglyph) continue;
+ colr_iLayerList.push(
+ &m.layers,
+ (colr_Layer){
+ .glyph = Handle.fromName(
+ sdsnewlen(_layerglyph->u.string.ptr, _layerglyph->u.string.length)),
+ .paletteIndex = json_obj_getint_fallback(_layer, "paletteIndex", 0xFFFF),
+ });
+ }
+ table_iCOLR.push(colr, m);
+ }
+ }
+ return colr;
+}
+
+static int byGID(const colr_Mapping *a, const colr_Mapping *b) {
+ return a->glyph.index - b->glyph.index;
+}
+
+caryll_Buffer *otfcc_buildCOLR(const table_COLR *_colr, const otfcc_Options *options) {
+ if (!_colr || !_colr->length) return NULL;
+
+ // sort base defs
+ table_COLR colr;
+ table_iCOLR.copy(&colr, _colr);
+ table_iCOLR.sort(&colr, byGID);
+
+ glyphid_t currentLayerIndex = 0;
+ bk_Block *layerRecords = bk_new_Block(bkover);
+ bk_Block *baseRecords = bk_new_Block(bkover);
+ foreach (colr_Mapping *mapping, colr) {
+ bk_push(baseRecords, b16, mapping->glyph.index, // GID
+ b16, currentLayerIndex, // firstLayerIndex
+ b16, mapping->layers.length, // numLayers
+ bkover);
+ foreach (colr_Layer *layer, mapping->layers) {
+ bk_push(layerRecords, b16, layer->glyph.index, // GID
+ b16, layer->paletteIndex, // paletteIndex
+ bkover);
+ currentLayerIndex += 1;
+ }
+ }
+
+ bk_Block *root = bk_new_Block(b16, 0, // Version
+ b16, colr.length, // numBaseGlyphRecords
+ p32, baseRecords, // offsetBaseGlyphRecord
+ p32, layerRecords, // offsetLayerRecord
+ b16, currentLayerIndex, // numLayerRecords
+ bkover);
+ table_iCOLR.dispose(&colr);
+ return bk_build_Block(root);
+}