summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mfluadir/otfcc/lib/libcff/cff-dict.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/mfluadir/otfcc/lib/libcff/cff-dict.c')
-rw-r--r--Build/source/texk/web2c/mfluadir/otfcc/lib/libcff/cff-dict.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mfluadir/otfcc/lib/libcff/cff-dict.c b/Build/source/texk/web2c/mfluadir/otfcc/lib/libcff/cff-dict.c
new file mode 100644
index 00000000000..151d5d4e14d
--- /dev/null
+++ b/Build/source/texk/web2c/mfluadir/otfcc/lib/libcff/cff-dict.c
@@ -0,0 +1,122 @@
+#include "libcff.h"
+
+static INLINE void disposeDict(cff_Dict *dict) {
+ for (uint32_t j = 0; j < dict->count; j++) {
+ FREE(dict->ents[j].vals);
+ }
+ FREE(dict->ents);
+}
+
+caryll_standardRefTypeFn(cff_Dict, disposeDict);
+
+static cff_Dict *parseDict(const uint8_t *data, const uint32_t len) {
+ cff_Dict *dict;
+ NEW(dict);
+ uint32_t index = 0, advance;
+ cff_Value val, stack[48];
+ const uint8_t *temp = data;
+
+ while (temp < data + len) {
+ advance = cff_decodeCffToken(temp, &val);
+
+ switch (val.t) {
+ case cff_OPERATOR:
+ RESIZE(dict->ents, dict->count + 1);
+ dict->ents[dict->count].op = val.i;
+ dict->ents[dict->count].cnt = index;
+ NEW(dict->ents[dict->count].vals, index);
+ memcpy(dict->ents[dict->count].vals, stack, sizeof(cff_Value) * index);
+ dict->count++;
+ index = 0;
+ break;
+ case cff_INTEGER:
+ case cff_DOUBLE:
+ stack[index++] = val;
+ break;
+ }
+
+ temp += advance;
+ }
+
+ return dict;
+}
+
+static void parseToCallback(const uint8_t *data, const uint32_t len, void *context,
+ void (*callback)(uint32_t op, uint8_t top, cff_Value *stack, void *context)) {
+ uint8_t index = 0;
+ uint32_t advance;
+ cff_Value val, stack[256];
+ const uint8_t *temp = data;
+
+ while (temp < data + len) {
+ advance = cff_decodeCffToken(temp, &val);
+
+ switch (val.t) {
+ case cff_OPERATOR:
+ callback(val.i, index, stack, context);
+ index = 0;
+ break;
+
+ case cff_INTEGER:
+ case cff_DOUBLE:
+ stack[index++] = val;
+ break;
+ }
+
+ temp += advance;
+ }
+}
+
+typedef struct {
+ bool found;
+ cff_Value res;
+ uint32_t op;
+ uint32_t idx;
+} cff_get_key_context;
+
+static void callback_get_key(uint32_t op, uint8_t top, cff_Value *stack, void *_context) {
+ cff_get_key_context *context = (cff_get_key_context *)_context;
+ if (op == context->op && context->idx <= top) {
+ context->found = true;
+ context->res = stack[context->idx];
+ }
+}
+
+static cff_Value parseDictKey(const uint8_t *data, const uint32_t len, const uint32_t op, const uint32_t idx) {
+ cff_get_key_context context;
+ context.found = false;
+ context.idx = idx;
+ context.op = op;
+ context.res.t = 0;
+ context.res.i = -1;
+
+ parseToCallback(data, len, &context, callback_get_key);
+ return context.res;
+}
+
+static caryll_Buffer *buildDict(const cff_Dict *dict) {
+ caryll_Buffer *blob = bufnew();
+ for (uint32_t i = 0; i < dict->count; i++) {
+ for (uint32_t j = 0; j < dict->ents[i].cnt; j++) {
+ caryll_Buffer *blob_val;
+ if (dict->ents[i].vals[j].t == cff_INTEGER) {
+ blob_val = cff_encodeCffInteger(dict->ents[i].vals[j].i);
+ } else if (dict->ents[i].vals[j].t == cff_DOUBLE) {
+ blob_val = cff_encodeCffFloat(dict->ents[i].vals[j].d);
+ } else {
+ blob_val = cff_encodeCffInteger(0);
+ }
+ bufwrite_bufdel(blob, blob_val);
+ }
+ bufwrite_bufdel(blob, cff_encodeCffOperator(dict->ents[i].op));
+ }
+ return blob;
+}
+
+caryll_ElementInterfaceOf(cff_Dict) cff_iDict = {
+ caryll_standardRefTypeMethods(cff_Dict),
+ .parse = parseDict,
+ .parseToCallback = parseToCallback,
+ .parseDictKey = parseDictKey,
+ .build = buildDict,
+};