summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mfluadir/otfcc/lib/table/name.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/mfluadir/otfcc/lib/table/name.c')
-rw-r--r--Build/source/texk/web2c/mfluadir/otfcc/lib/table/name.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mfluadir/otfcc/lib/table/name.c b/Build/source/texk/web2c/mfluadir/otfcc/lib/table/name.c
new file mode 100644
index 00000000000..9f579932564
--- /dev/null
+++ b/Build/source/texk/web2c/mfluadir/otfcc/lib/table/name.c
@@ -0,0 +1,198 @@
+#include "name.h"
+
+#include "support/util.h"
+#include "support/unicodeconv/unicodeconv.h"
+
+#ifndef MAIN_VER
+#define MAIN_VER 0
+#endif
+#ifndef SECONDARY_VER
+#define SECONDARY_VER 0
+#endif
+#ifndef PATCH_VER
+#define PATCH_VER 0
+#endif
+
+#define COPYRIGHT_LEN 32
+
+static void nameRecordDtor(otfcc_NameRecord *entry) {
+ DELETE(sdsfree, entry->nameString);
+}
+caryll_standardType(otfcc_NameRecord, otfcc_iNameRecord, nameRecordDtor);
+caryll_standardVectorImpl(table_name, otfcc_NameRecord, otfcc_iNameRecord, table_iName);
+
+static bool shouldDecodeAsUTF16(const otfcc_NameRecord *record) {
+ return (record->platformID == 0) // Unicode, all
+ || (record->platformID == 2 && record->encodingID == 1) // ISO, 1
+ || (record->platformID == 3 && // Microsoft, 0, 1, 10
+ (record->encodingID == 0 || record->encodingID == 1 || record->encodingID == 10));
+}
+static bool shouldDecodeAsBytes(const otfcc_NameRecord *record) {
+ return record->platformID == 1 && record->encodingID == 0 &&
+ record->languageID == 0; // Mac Roman English - I hope
+}
+
+table_name *otfcc_readName(const otfcc_Packet packet, const otfcc_Options *options) {
+ FOR_TABLE(OTFCC_CHR('n','a','m','e'), table) {
+ table_name *name = NULL;
+ font_file_pointer data = table.data;
+
+ uint32_t length = table.length;
+ if (length < 6) goto TABLE_NAME_CORRUPTED;
+ uint32_t count = read_16u(data + 2);
+ uint32_t stringOffset = read_16u(data + 4);
+ if (length < 6 + 12 * count) goto TABLE_NAME_CORRUPTED;
+
+ name = table_iName.create();
+
+ for (uint16_t j = 0; j < count; j++) {
+ otfcc_NameRecord record;
+ record.platformID = read_16u(data + 6 + j * 12);
+ record.encodingID = read_16u(data + 6 + j * 12 + 2);
+ record.languageID = read_16u(data + 6 + j * 12 + 4);
+ record.nameID = read_16u(data + 6 + j * 12 + 6);
+ record.nameString = NULL;
+ uint16_t length = read_16u(data + 6 + j * 12 + 8);
+ uint16_t offset = read_16u(data + 6 + j * 12 + 10);
+
+ if (shouldDecodeAsBytes(&record)) {
+ // Mac Roman. Note that this is not very correct, but works for most fonts
+ sds nameString = sdsnewlen(data + stringOffset + offset, length);
+ record.nameString = nameString;
+ } else if (shouldDecodeAsUTF16(&record)) {
+ sds nameString = utf16be_to_utf8(data + stringOffset + offset, length);
+ record.nameString = nameString;
+ } else {
+ size_t len = 0;
+ uint8_t *buf = base64_encode(data + stringOffset + offset, length, &len);
+ record.nameString = sdsnewlen(buf, len);
+ FREE(buf);
+ }
+ table_iName.push(name, record);
+ }
+ return name;
+ TABLE_NAME_CORRUPTED:
+ logWarning("table 'name' corrupted.\n");
+ if (name) { DELETE(table_iName.free, name); }
+ }
+ return NULL;
+}
+
+void otfcc_dumpName(const table_name *name, json_value *root, const otfcc_Options *options) {
+ if (!name) return;
+ loggedStep("name") {
+ json_value *_name = json_array_new(name->length);
+ for (uint16_t j = 0; j < name->length; j++) {
+ otfcc_NameRecord *r = &(name->items[j]);
+ json_value *record = json_object_new(5);
+ json_object_push(record, "platformID", json_integer_new(r->platformID));
+ json_object_push(record, "encodingID", json_integer_new(r->encodingID));
+ json_object_push(record, "languageID", json_integer_new(r->languageID));
+ json_object_push(record, "nameID", json_integer_new(r->nameID));
+ json_object_push(
+ record, "nameString",
+ json_string_new_length((uint32_t)sdslen(r->nameString), r->nameString));
+ json_array_push(_name, record);
+ }
+ json_object_push(root, "name", _name);
+ }
+}
+static int name_record_sort(const otfcc_NameRecord *a, const otfcc_NameRecord *b) {
+ if (a->platformID != b->platformID) return a->platformID - b->platformID;
+ if (a->encodingID != b->encodingID) return a->encodingID - b->encodingID;
+ if (a->languageID != b->languageID) return a->languageID - b->languageID;
+ return a->nameID - b->nameID;
+}
+table_name *otfcc_parseName(const json_value *root, const otfcc_Options *options) {
+ table_name *name = table_iName.create();
+ json_value *table = NULL;
+ if ((table = json_obj_get_type(root, "name", json_array))) {
+ loggedStep("name") {
+
+ for (uint32_t j = 0; j < table->u.array.length; j++) {
+ if (!(table->u.array.values[j] && table->u.array.values[j]->type == json_object))
+ continue;
+ json_value *_record = table->u.array.values[j];
+ if (!json_obj_get_type(_record, "platformID", json_integer)) {
+ logWarning("Missing or invalid platformID for name entry %d\n", j);
+ continue;
+ }
+ if (!json_obj_get_type(_record, "encodingID", json_integer)) {
+ logWarning("Missing or invalid encodingID for name entry %d\n", j);
+ continue;
+ }
+ if (!json_obj_get_type(_record, "languageID", json_integer)) {
+ logWarning("Missing or invalid languageID for name entry %d\n", j);
+ continue;
+ }
+ if (!json_obj_get_type(_record, "nameID", json_integer)) {
+ logWarning("Missing or invalid nameID for name entry %d\n", j);
+ continue;
+ }
+ if (!json_obj_get_type(_record, "nameString", json_string)) {
+ logWarning("Missing or invalid name string for name entry %d\n", j);
+ continue;
+ }
+ otfcc_NameRecord record;
+ record.platformID = json_obj_getint(_record, "platformID");
+ record.encodingID = json_obj_getint(_record, "encodingID");
+ record.languageID = json_obj_getint(_record, "languageID");
+ record.nameID = json_obj_getint(_record, "nameID");
+
+ json_value *str = json_obj_get_type(_record, "nameString", json_string);
+ record.nameString = sdsnewlen(str->u.string.ptr, str->u.string.length);
+ table_iName.push(name, record);
+ }
+
+ table_iName.sort(name, name_record_sort);
+ }
+ }
+ return name;
+}
+caryll_Buffer *otfcc_buildName(const table_name *name, const otfcc_Options *options) {
+ if (!name) return NULL;
+ caryll_Buffer *buf = bufnew();
+ bufwrite16b(buf, 0);
+ bufwrite16b(buf, name->length);
+ bufwrite16b(buf, 0); // fill later
+ caryll_Buffer *strings = bufnew();
+ for (uint16_t j = 0; j < name->length; j++) {
+ otfcc_NameRecord *record = &(name->items[j]);
+ bufwrite16b(buf, record->platformID);
+ bufwrite16b(buf, record->encodingID);
+ bufwrite16b(buf, record->languageID);
+ bufwrite16b(buf, record->nameID);
+ size_t cbefore = strings->cursor;
+ if (shouldDecodeAsUTF16(record)) {
+ size_t words;
+ uint8_t *u16 = utf8toutf16be(record->nameString, &words);
+ bufwrite_bytes(strings, words, u16);
+ FREE(u16);
+ } else if (shouldDecodeAsBytes(record)) {
+ bufwrite_bytes(strings, sdslen(record->nameString), (uint8_t *)record->nameString);
+ } else {
+ size_t length;
+ uint8_t *decoded =
+ base64_decode((uint8_t *)record->nameString, sdslen(record->nameString), &length);
+ bufwrite_bytes(strings, length, decoded);
+ FREE(decoded);
+ }
+ size_t cafter = strings->cursor;
+ bufwrite16b(buf, cafter - cbefore);
+ bufwrite16b(buf, cbefore);
+ }
+
+ // write copyright info
+ sds copyright =
+ sdscatprintf(sdsempty(), "-- By OTFCC %d.%d.%d --", MAIN_VER, SECONDARY_VER, PATCH_VER);
+ sdsgrowzero(copyright, COPYRIGHT_LEN);
+ bufwrite_bytes(strings, COPYRIGHT_LEN, (uint8_t *)copyright);
+ sdsfree(copyright);
+
+ size_t stringsOffset = buf->cursor;
+ bufwrite_buf(buf, strings);
+ bufseek(buf, 4);
+ bufwrite16b(buf, stringsOffset);
+ buffree(strings);
+ return buf;
+}