@@ 1,8 1,78 @@
#include "cmp.h"
#include <fontconfig/fontconfig.h>
#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+FcStrSet *decodeStrSet(cmp_ctx_t *bytes) {
+ if (bytes == NULL) return NULL;
+
+ uint32_t size;
+ if (!cmp_read_array(bytes, &size)) return NULL;
+
+ FcStrSet *ret = FcStrSetCreate();
+ if (ret == NULL) return NULL;
+
+ for (uint32_t i = 0; i < size; i++) {
+ char text[512]; // What's the appropriate size here?
+ uint32_t str_size = 512;
+ if (!cmp_read_str(bytes, text, &str_size)) goto fail;
+ if (!FcStrSetAdd(ret, text)) goto fail;
+ }
+ return ret;
+fail:
+ FcStrSetDestroy(ret);
+ return NULL;
+}
+
+FcStrSet *decodeFileSet(cmp_ctx_t *bytes) {
+ if (bytes == NULL) return NULL;
+
+ uint32_t size;
+ if (!cmp_read_array(bytes, &size)) return NULL;
+
+ FcStrSet *ret = FcStrSetCreate();
+ if (ret == NULL) return NULL;
+
+ for (uint32_t i = 0; i < size; i++) {
+ char text[512]; // What's the appropriate size here?
+ uint32_t str_size = 512;
+ if (!cmp_read_str(bytes, text, &str_size)) goto fail;
+ if (!FcStrSetAddFilename(ret, text)) goto fail;
+ }
+ return ret;
+fail:
+ FcStrSetDestroy(ret);
+ return NULL;
+}
+
+bool encodeStrSet(cmp_ctx_t *bytes, FcStrSet *data) {
+ if (bytes == NULL || data == NULL) return false;
+ bool ret = false;
+
+ FcStrList *iter = FcStrListCreate(data);
+ if (iter == NULL) return false;
+
+ uint32_t size = 0;
+ FcStrListFirst(iter);
+ while (FcStrListNext(iter) != NULL) size++;
+ if (!cmp_write_array(bytes, size)) goto exit;
+
+ FcStrListFirst(iter);
+ char *text = FcStrListNext(iter);
+ while (text != NULL) {
+ if (!cmp_write_str(bytes, text, strlen(text))) goto exit;
+ text = FcStrListNext(iter);
+ }
+ ret = true;
+exit:
+ FcStrListDone(iter);
+ return ret;
+}
FcCharSet *decodeCharSet(cmp_ctx_t *bytes) {
+ if (bytes == NULL) return NULL;
+
uint32_t size;
if (!cmp_read_array(bytes, &size)) return NULL;
@@ 23,6 93,8 @@ fail:
}
bool encodeCharSet(cmp_ctx_t *bytes, FcCharSet *data) {
+ if (bytes == NULL || data == NULL) return false;
+
FcChar32 size = FcCharSetCount(data);
FcChar32 count = 0; // For validation
if (!cmp_write_array(bytes, size)) return false;
@@ 40,3 112,265 @@ bool encodeCharSet(cmp_ctx_t *bytes, FcCharSet *data) {
assert(size == count);
return true;
}
+
+FcLangSet *decodeLangSet(cmp_ctx_t *bytes) {
+ if (bytes == NULL) return NULL;
+ uint32_t size;
+ if (!cmp_read_array(bytes, &size)) return NULL;
+
+ FcLangSet *ret = FcLangSetCreate();
+ if (ret == NULL) return NULL;
+ for (uint32_t i = 0; i < size; i++) {
+ char lang[10];
+ uint32_t str_size = 10;
+ if (!cmp_read_str(bytes, lang, &str_size)) goto fail;
+ char *lang2 = FcLangNormalize(lang);
+ if (lang2 == NULL) goto fail;
+ if (!FcLangSetAdd(ret, lang2)) goto fail;
+ free(lang2);
+ }
+ return ret;
+fail:
+ FcLangSetDestroy(ret);
+ return NULL;
+}
+
+bool encodeLangSet(cmp_ctx_t *bytes, FcLangSet *data) {
+ if (bytes == NULL || data == NULL) return false;
+ FcStrSet *langs = FcLangSetGetLangs(data);
+ if (langs == NULL) return false;
+ bool ret = encodeStrSet(bytes, langs);
+ FcStrSetDestroy(langs);
+ return ret;
+}
+
+FcObjectSet *decodeObjectSet(cmp_ctx_t *bytes) {
+ if (bytes == NULL) return NULL;
+
+ uint32_t size;
+ if (!cmp_read_array(bytes, &size)) return NULL;
+
+ FcObjectSet *ret = FcObjectSetCreate();
+ for (uint32_t i = 0; i < size; i++) {
+ char object[20];
+ uint32_t o_size = 20;
+ if (!cmp_read_str(bytes, lang, &str_size)) goto fail;
+ if (!FcObjectSetAdd(ret, object)) goto fail;
+ }
+ return ret;
+fail:
+ FcObjectSetDestroy(ret);
+ return NULL;
+}
+
+// No corresponding objectset encoder.
+
+FcRange *decodeRange(cmp_ctx_t *bytes) {
+ if (bytes == NULL) return NULL;
+
+ uint32_t size;
+ if (!cmp_read_map(bytes, &size)) return NULL;
+
+ double range[2];
+ for (uint32_t i = 0; i < size; i++) {
+ uint32_t j;
+ if (!cmp_read_uint(bytes, &j)) return NULL;
+ if (!cmp_read_double(bytes, &range[j])) return NULL;
+ }
+ return FcCreateDouble(range[0], range[1]);
+}
+
+bool encodeRange(cmp_ctx_t *bytes, FcRange *data) {
+ if (bytes == NULL || data == NULL) return false;
+
+ double begin, end;
+ if (!FcRangeGetDouble(data, &begin, &end)) return false;
+
+ if (!cmp_write_map(bytes, 2)) return false;
+ if (!cmp_write_uint(bytes, 0)) return false;
+ if (!cmp_write_double(bytes, begin)) return false;
+ if (!cmp_write_uint(bytes, 1)) return false;
+ if (!cmp_write_double(bytes, end)) return false;
+ return true;
+}
+
+FcMatrix *decodeMatrix(cmp_ctx_t *bytes) {
+ if (bytes == NULL) return NULL;
+
+ uint32_t size;
+ if (!cmp_read_array(bytes, &size) || size != 4) return NULL;
+
+ FcMatrix *ret = malloc(sizeof(FcMatrix));
+ if (!cmp_read_double(bytes, &ret->xx)) goto fail;
+ if (!cmp_read_double(bytes, &ret->xy)) goto fail;
+ if (!cmp_read_double(bytes, &ret->yx)) goto fail;
+ if (!cmp_read_double(bytes, &ret->yy)) goto fail;
+ return ret;
+fail:
+ free(ret);
+ return NULL;
+}
+
+bool encodeMatrix(cmp_ctx_t *bytes, FcMatrix *data) {
+ if (bytes == NULL || data == NULL) return NULL;
+
+ if (!cmp_write_array(bytes, 4)) return false;
+ if (!cmp_write_double(bytes, data->xx)) return false;
+ if (!cmp_write_double(bytes, data->xy)) return false;
+ if (!cmp_write_double(bytes, data->yx)) return false;
+ if (!cmp_write_double(bytes, data->yy)) return false;
+ return true;
+}
+
+bool decodeValue(cmp_ctx_t *bytes, FcValue *out) {
+ if (bytes == NULL || out == NULL) return false;
+
+ if (cmp_read_nil(bytes)) out->type = FcTypeVoid;
+ else if (cmp_read_int(bytes, &out->u.i)) out->type = FcTypeInteger;
+ else if (cmp_read_double(bytes, &out->u.d)) out->type = FcTypeDouble;
+ else if (cmp_read_string(bytes, &out->u.s, NULL)) out->type = FcTypeString;
+ else if (cmp_read_bool(bytes, &out->u.b)) out->type = FcTypeBool;
+ else if ((out->u.m = decodeMatrix(bytes)) != NULL) out->type = FcTypeMatrix;
+ else if ((out->u.c = decodeCharSet(bytes)) != NULL) out->type = FcTypeCharSet;
+ // Not supporting FcTypeFcFace
+ else if ((out->u.l = decodeLangSet(bytes)) != NULL) out->type = FcTypeLangSet;
+ else if ((out->u.r = decodeRange(bytes)) != NULL) out->type = FcTypeRange;
+ else return false;
+ return true;
+}
+
+bool encodeValue(cmp_ctx_t *bytes, FcValue *data) {
+ if (bytes == NULL || data == NULL) return false;
+
+ switch (data->type) {
+ case FcTypeVoid:
+ return cmp_write_nil(bytes);
+ case FcTypeInteger:
+ return cmp_write_int(bytes, data->u.i);
+ case FcTypeDouble:
+ return cmp_write_double(bytes, data->u.d);
+ case FcTypeString:
+ return cmp_write_string(bytes, data->u.s, strlen(data->u.s));
+ case FcTypeBool:
+ return cmp_write_bool(bytes, data->u.b);
+ case FcTypeMatrix:
+ return encodeMatrix(bytes, data->u.m);
+ case FcTypeCharSet:
+ return encodeCharSet(bytes, data->u.c);
+ case FcTypeFcFace:
+ return true; // Not supporting this yet...
+ case FcTypeLangSet:
+ return encodeLangSet(bytes, data->u.l);
+ case FcTypeRange:
+ return encodeRange(bytes, data->u.r);
+ default:
+ return false;
+ }
+}
+
+FcPattern *decodePattern(cmp_ctx_t *bytes) {
+ if (bytes == NULL) return NULL;
+
+ uint32_t size;
+ if (!cmp_read_map(bytes, &size)) return NULL;
+
+ FcPattern *ret = FcPatternCreate();
+ for (uint32_t i = 0; i < size; i++) {
+ char object[20];
+ uint32_t osize = 20;
+ if (!cmp_read_string(bytes, object, &osize)) goto fail;
+ uint32_t vsize;
+ if (!cmp_read_array(bytes, &vsize)) goto fail;
+ for (uint32 j = 0; j < vsize; j++) {
+ uint32_t tsize;
+ if (!cmp_read_array(bytes, &tsize) || tsize != 2) goto fail;
+ bool is_strong = false;
+ if (cmp_read_bool(bytes, &is_weak)) {}
+ else if (cmp_read_nil(bytes)) {}
+ else goto fail;
+ FcValue val;
+ if (!decodeValue(bytes, &val)) goto fail;
+ if (is_strong) {
+ if (!FcPatternAdd(bytes, object, value, true)) goto fail;
+ } else {
+ if (!FcPatternAddWeak(bytes, object, value, true)) goto fail;
+ }
+ }
+ }
+ return ret;
+fail:
+ FcPatternDestroy(ret);
+ return NULL;
+}
+
+bool encodePattern(cmp_ctx_t *bytes, FcPattern *data) {
+ if (bytes == NULL || data == NULL) return false;
+
+ int size = FcPatternObjectCount(data);
+ if (!cmp_write_map(bytes, &size)) return false;
+
+ FcPatternIter iter;
+ FcPatternIterStart(data, &iter);
+ int count = 0;
+ while (FcPatternIterNext(data, &iter)) {
+ count++;
+ char *obj = FcPatternIterGetObject(data, &iter);
+ if (!cmp_write_string(bytes, obj, strlen(obj))) return false;
+ int nvalues = FcPatternIterValueCount(data, &iter);
+ if (!cmp_write_array(bytes, nvalues)) return false;
+ for (int j = 0; j < nvalues; j++) {
+ FcValue val;
+ FcValueBinding weight;
+ if (FcPatternIterGetValue(data, &iter, j, &val, &weight) != FcResultMatch)
+ return false;
+
+ if (!cmp_write_array(bytes, 2)) return false;
+ switch (weight) {
+ case FcValueBindingWeak:
+ if (!cmp_write_bool(bytes, false)) return false;
+ break;
+ case FcValueBindingStrong:
+ if (!cmp_write_bool(bytes, true)) return false;
+ break;
+ case FcValueBindingSame:
+ if (!cmp_write_nil(bytes)) return false;
+ break;
+ default:
+ return false;
+ }
+ if (!encodeValue(bytes, &val)) return false;
+ }
+ }
+ assert(size == count);
+ return true;
+}
+
+FcFontSet *decodeFontSet(cmp_ctx_t *bytes) {
+ if (bytes == NULL) return NULL;
+
+ uint32_t size;
+ if (!cmp_read_array(bytes, &size)) return NULL;
+
+ FcFontSet *ret = FcFontSetCreate();
+ if (ret == NULL) return NULL;
+
+ for (uint32_t i = 0; i < size; i++) {
+ FcPattern *font = decodePattern(bytes);
+ if (font == NULL) goto fail;
+ if (!FcFontSetAdd(ret, font)) goto fail;
+ }
+ return ret;
+fail:
+ FcFontSetDestroy(ret);
+ return NULL;
+}
+
+bool encodeFontSet(cmp_ctx_t *bytes, FcFontSet *data) {
+ if (bytes == NULL || data == NULL) return NULL;
+
+ if (!cmp_write_array(bytes, data->nfont)) return false;
+ for (int i = 0; i < data->nfont; i++) {
+ if (!encodePattern(bytes, data->fonts[i])) return false;
+ }
+ return true;
+}