static void xps_load_sfnt_cmap(xps_font_t *font) { byte *cmapdata; int offset, length; int nsubtables; offset = xps_find_sfnt_table(font, "cmap", &length); if (offset < 0 || length < 4) { gs_warn("cannot find cmap table"); return; } cmapdata = font->data + offset; nsubtables = u16(cmapdata + 2); if (nsubtables < 0 || length < 4 + nsubtables * 8) { gs_warn("cannot find cmap sub-tables"); return; } font->cmaptable = offset; font->cmapsubcount = nsubtables; font->cmapsubtable = 0; }
static int xps_true_callback_glyph_name(gs_font *pfont, gs_glyph glyph, gs_const_string *pstr) { /* This function is copied verbatim from plfont.c */ int table_length; int table_offset; ulong format; uint numGlyphs; uint glyph_name_index; const byte *postp; /* post table pointer */ /* guess if the font type is not truetype */ if ( pfont->FontType != ft_TrueType ) { glyph -= 29; if ( glyph >= 0 && glyph < 258 ) { pstr->data = (byte*) pl_mac_names[glyph]; pstr->size = strlen((char*)pstr->data); return 0; } else { return gs_throw1(-1, "glyph index %lu out of range", (ulong)glyph); } } table_offset = xps_find_sfnt_table((xps_font_t*)pfont->client_data, "post", &table_length); /* no post table */ if (table_offset < 0) return gs_throw(-1, "no post table"); /* this shoudn't happen but... */ if ( table_length == 0 ) return gs_throw(-1, "zero-size post table"); ((gs_font_type42 *)pfont)->data.string_proc((gs_font_type42 *)pfont, table_offset, table_length, &postp); format = u32(postp); /* Format 1.0 (mac encoding) is a simple table see the TT spec. * We don't implement this because we don't see it in practice. * Format 2.5 is deprecated. * Format 3.0 means that there is no post data in the font file. * We see this a lot but can't do much about it. * The only format we support is 2.0. */ if ( format != 0x20000 ) { /* Invent a name if we don't know the table format. */ char buf[32]; sprintf(buf, "glyph%d", (int)glyph); pstr->data = (byte*)buf; pstr->size = strlen((char*)pstr->data); return 0; } /* skip over the post header */ numGlyphs = u16(postp + 32); if ( glyph < 0 || glyph > numGlyphs - 1) { return gs_throw1(-1, "glyph index %lu out of range", (ulong)glyph); } /* glyph name index starts at post + 34 each entry is 2 bytes */ glyph_name_index = u16(postp + 34 + (glyph * 2)); /* this shouldn't happen */ if ( glyph_name_index < 0 && glyph_name_index > 0x7fff ) return gs_throw(-1, "post table format error"); /* mac easy */ if ( glyph_name_index < 258 ) { // dprintf2("glyph name (mac) %d = %s\n", glyph, pl_mac_names[glyph_name_index]); pstr->data = (byte*) pl_mac_names[glyph_name_index]; pstr->size = strlen((char*)pstr->data); return 0; } /* not mac */ else { byte *mydata; /* and here's the tricky part */ const byte *pascal_stringp = postp + 34 + (numGlyphs * 2); /* 0 - 257 lives in the mac table above */ glyph_name_index -= 258; /* The string we want is the index'th pascal string, * so we "hop" to each length byte "index" times. */ while (glyph_name_index > 0) { pascal_stringp += ((int)(*pascal_stringp)+1); glyph_name_index--; } /* length byte */ pstr->size = (int)(*pascal_stringp); /* + 1 is for the length byte */ pstr->data = pascal_stringp + 1; /* sanity check */ if ( pstr->data + pstr->size > postp + table_length || pstr->data - 1 < postp) return gs_throw(-1, "data out of range"); /* sigh - we have to allocate a copy of the data - by the * time a high level device makes use of it the font data * may be freed. This is a necessary leak. */ mydata = gs_alloc_bytes(pfont->memory, pstr->size + 1, "glyph to name"); if ( mydata == 0 ) return -1; memcpy(mydata, pascal_stringp + 1, pstr->size); pstr->data = mydata; mydata[pstr->size] = 0; return 0; } }
void xps_measure_font_glyph(xps_context_t *ctx, xps_font_t *font, int gid, xps_glyph_metrics_t *mtx) { int head, format, loca, glyf; int ofs, len; int idx, i, n; int hadv, vadv, vorg; int vtop, ymax, desc; int scale; /* some insane defaults */ scale = 1000; /* units-per-em */ hadv = 500; vadv = -1000; vorg = 1000; /* * Horizontal metrics are easy. */ ofs = xps_find_sfnt_table(font, "hhea", &len); if (ofs < 0 || len < 2 * 18) { gs_warn("hhea table is too short"); return; } vorg = s16(font->data + ofs + 4); /* ascender is default vorg */ desc = s16(font->data + ofs + 6); /* descender */ if (desc < 0) desc = -desc; n = u16(font->data + ofs + 17 * 2); ofs = xps_find_sfnt_table(font, "hmtx", &len); if (ofs < 0) { gs_warn("cannot find hmtx table"); return; } idx = gid; if (idx > n - 1) idx = n - 1; hadv = u16(font->data + ofs + idx * 4); vadv = 0; /* * Vertical metrics are hairy (with missing tables). */ head = xps_find_sfnt_table(font, "head", &len); if (head > 0) { scale = u16(font->data + head + 18); /* units per em */ } ofs = xps_find_sfnt_table(font, "OS/2", &len); if (ofs > 0 && len > 70) { vorg = s16(font->data + ofs + 68); /* sTypoAscender */ desc = s16(font->data + ofs + 70); /* sTypoDescender */ if (desc < 0) desc = -desc; } ofs = xps_find_sfnt_table(font, "vhea", &len); if (ofs > 0 && len >= 2 * 18) { n = u16(font->data + ofs + 17 * 2); ofs = xps_find_sfnt_table(font, "vmtx", &len); if (ofs < 0) { gs_warn("cannot find vmtx table"); return; } idx = gid; if (idx > n - 1) idx = n - 1; vadv = u16(font->data + ofs + idx * 4); vtop = u16(font->data + ofs + idx * 4 + 2); glyf = xps_find_sfnt_table(font, "glyf", &len); loca = xps_find_sfnt_table(font, "loca", &len); if (head > 0 && glyf > 0 && loca > 0) { format = u16(font->data + head + 50); /* indexToLocaFormat */ if (format == 0) ofs = u16(font->data + loca + gid * 2) * 2; else ofs = u32(font->data + loca + gid * 4); ymax = u16(font->data + glyf + ofs + 8); /* yMax */ vorg = ymax + vtop; } } ofs = xps_find_sfnt_table(font, "VORG", &len); if (ofs > 0) { vorg = u16(font->data + ofs + 6); n = u16(font->data + ofs + 6); for (i = 0; i < n; i++) { if (u16(font->data + ofs + 8 + 4 * i) == gid) { vorg = s16(font->data + ofs + 8 + 4 * i + 2); break; } } } if (vadv == 0) vadv = vorg + desc; mtx->hadv = hadv / (float) scale; mtx->vadv = vadv / (float) scale; mtx->vorg = vorg / (float) scale; }
/* * Get the windows truetype font file name - position 4 in the name table. */ void xps_load_sfnt_name(xps_font_t *font, char *namep) { byte *namedata; int offset, length; int format, count, stringoffset; int found; int i, k; found = 0; strcpy(namep, "Unknown"); offset = xps_find_sfnt_table(font, "name", &length); if (offset < 0 || length < 6) { gs_warn("cannot find name table"); return; } namedata = font->data + offset; format = u16(namedata + 0); count = u16(namedata + 2); stringoffset = u16(namedata + 4); if (length < 6 + (count * 12)) { gs_warn("name table too short"); return; } for (i = 0; i < count; i++) { byte *record = namedata + 6 + i * 12; int pid = u16(record + 0); int eid = u16(record + 2); int langid = u16(record + 4); int nameid = u16(record + 6); length = u16(record + 8); offset = u16(record + 10); /* Full font name or postscript name */ if (nameid == 4 || nameid == 6) { if (pid == 1 && eid == 0 && langid == 0) /* mac roman, english */ { if (found < 3) { memcpy(namep, namedata + stringoffset + offset, length); namep[length] = 0; found = 3; } } if (pid == 3 && eid == 1 && langid == 0x409) /* windows unicode ucs-2, US */ { if (found < 2) { unsigned char *s = namedata + stringoffset + offset; int n = length / 2; for (k = 0; k < n; k ++) { int c = u16(s + k * 2); namep[k] = isprint(c) ? c : '?'; } namep[k] = 0; found = 2; } } if (pid == 3 && eid == 10 && langid == 0x409) /* windows unicode ucs-4, US */ { if (found < 1) { unsigned char *s = namedata + stringoffset + offset; int n = length / 4; for (k = 0; k < n; k ++) { int c = u32(s + k * 4); namep[k] = isprint(c) ? c : '?'; } namep[k] = 0; found = 1; } } } } }