+static char*readString(memreader_t*r, int len)
+{
+ char*s = malloc(len+1);
+ readBlock(r, s, len);
+ s[len] = 0;
+ return s;
+}
+void name_parse(memreader_t*r, ttf_t*ttf)
+{
+ U16 format = readU16(r);
+ U16 count = readU16(r);
+ U16 offset = readU16(r);
+
+ int t;
+ for(t=0;t<count;t++) {
+ U16 platform = readU16(r);
+ U16 encoding = readU16(r);
+ U16 language = readU16(r);
+ U16 name_id = readU16(r);
+ U16 len = readU16(r);
+ U16 offset_2 = readU16(r);
+
+ char ** read_name = 0;
+
+ INIT_READ(ss, r->mem, r->size, offset+offset_2);
+ if(!(platform==0 || (platform==1 && encoding==0)))
+ continue;
+
+ INIT_READ(s, r->mem, r->size, offset+offset_2);
+
+ switch (name_id) {
+ case 1: read_name = &ttf->family_name; break;
+ case 2: read_name = &ttf->subfamily_name; break;
+ case 3: read_name = &ttf->font_uid; break;
+ case 4: read_name = &ttf->full_name; break;
+ case 5: read_name = &ttf->version_string; break;
+ case 6: read_name = &ttf->postscript_name; break;
+ default: read_name = 0;
+ }
+
+ if (read_name) {
+ if (*read_name) free(*read_name);
+ *read_name = readString(&s, len);
+ }
+ }
+}
+void name_write(ttf_t*ttf, ttf_table_t*table)
+{
+ char*strings[6] = {ttf->family_name, ttf->subfamily_name, ttf->font_uid, ttf->full_name, ttf->version_string, ttf->postscript_name};
+ int codes[6] = {1,2,3,4,5,6};
+
+ writeU16(table, 0); //format
+ int count = 0;
+ int t;
+ int nr = sizeof(strings)/sizeof(strings[0]);
+
+ for(t=0;t<nr;t++) {
+ if(strings[t])
+ count+=2;
+ }
+ writeU16(table, count); //count
+
+ int offset_pos = table->len;
+ writeU16(table, 0); //offset (will be filled in later)
+
+ /* Windows expects the name table to be sorted by platform/encoding/language/name_id */
+ int offset = 0;
+ for(t=0;t<nr;t++) {
+ if(strings[t]) {
+ writeU16(table, 1); //platform id (mac)
+ writeU16(table, 0); //encoding id (latin-1)
+ writeU16(table, 0); //language (english)
+ writeU16(table, codes[t]);
+ int len = strlen(strings[t]);
+ writeU16(table, len);
+ writeU16(table, offset);
+ offset += len;
+ }
+ }
+ for(t=0;t<nr;t++) {
+ if(strings[t]) {
+ writeU16(table, 3); //platform id (windows)
+ writeU16(table, 1); //encoding id (ucs-2)
+ writeU16(table, 0x409); //language (US)
+ writeU16(table, codes[t]);
+ int len2 = strlen(strings[t]) * 2;
+ writeU16(table, len2);
+ writeU16(table, offset);
+ offset += len2;
+ }
+ }
+
+ table->data[offset_pos] = table->len>>8;
+ table->data[offset_pos+1] = table->len;
+
+ for(t=0;t<nr;t++) {
+ if(strings[t]) {
+ int len = strlen(strings[t]);
+ writeBlock(table, strings[t], len);
+ }
+ }
+ for(t=0;t<nr;t++) {
+ if(strings[t]) {
+ int s;
+ int len = strlen(strings[t]);
+ for(s=0;s<len;s++) {
+ writeU8(table, 0);
+ writeU8(table, strings[t][s]);
+ }
+ }
+ }
+}
+void name_delete(ttf_t*ttf)
+{
+ if(ttf->full_name) {
+ free(ttf->full_name);
+ ttf->full_name=0;
+ }
+ if(ttf->family_name) {
+ free(ttf->family_name);
+ ttf->family_name=0;
+ }
+ if(ttf->subfamily_name) {
+ free(ttf->subfamily_name);
+ ttf->subfamily_name=0;
+ }
+ if(ttf->version_string) {
+ free(ttf->version_string);
+ ttf->version_string=0;
+ }
+ if(ttf->font_uid) {
+ free(ttf->font_uid);
+ ttf->font_uid=0;
+ }
+ if(ttf->postscript_name) {
+ free(ttf->postscript_name);
+ ttf->postscript_name=0;
+ }
+}
+
+static table_post_t*post_new(ttf_t*ttf)
+{
+ table_post_t*post = rfx_calloc(sizeof(table_post_t));
+ return post;
+}
+void post_parse(memreader_t*r, ttf_t*ttf)
+{
+ table_post_t*post = ttf->post = rfx_calloc(sizeof(table_post_t));
+ U16 format = readU16(r);
+ post->italic_angle = readU16(r);
+ post->underline_position = readU16(r);
+ post->underline_thickness = readU16(r);
+ U16 is_monospaced = readU16(r);
+ readU16(r); // min mem 42
+ readU16(r);
+ readU16(r); // min mem 1
+ readU16(r);
+}
+void post_write(ttf_t*ttf, ttf_table_t*table)
+{
+ table_post_t*post = ttf->post;
+ writeU32(table, 0x00030000);
+ writeU32(table, post->italic_angle);
+ writeU16(table, post->underline_position);
+ writeU16(table, post->underline_thickness);
+ writeU32(table, 0); //is monospaced TODO
+ writeU32(table, 0); //min mem 42
+ writeU32(table, 0);
+ writeU32(table, 0); //min mem 1
+ writeU32(table, 0);
+}
+void post_delete(ttf_t*ttf)
+{
+ if(ttf->post) {
+ free(ttf->post);
+ ttf->post = 0;
+ }
+}