size_t dest_offset;
};
+#if 0 /* unused */
static void decode_uint8(void *src, void *dest) {
*(unsigned int *)dest = *(unsigned char *)src;
}
#define d_uint8 decode_uint8, 1
+#endif
+#if 0 /* unused */
static void decode_int8(void *src, void *dest) {
*(int *)dest = *(signed char *)src;
}
#define d_int8 decode_int8, 1
+#endif
static void decode_uint16(void *src, void *dest) {
unsigned char *cp = src;
#define d_int32 decode_int32, 4
static void decode_skip(void *src, void *dest) {
+ IGNORE(src);
+ IGNORE(dest);
/* do nothing */
}
#define d_skip(n) decode_skip, (n), 0
static void decode_end(void *src, void *dest) {
+ IGNORE(src);
+ IGNORE(dest);
/* never called */
}
#define d_end decode_end, 0, 0
typedef struct t_post_Tag t_post;
struct t_post_Tag {
unsigned format;
- unsigned italicAngle;
+ int italicAngle;
int underlinePosition;
int underlineThickness;
unsigned isFixedPitch;
};
sfnt_decode t_post_decode[] = {
{ d_uint32, offsetof(t_post, format) },
- { d_uint32, offsetof(t_post, italicAngle) },
+ { d_int32, offsetof(t_post, italicAngle) },
{ d_int16, offsetof(t_post, underlinePosition) },
{ d_int16, offsetof(t_post, underlineThickness) },
{ d_uint32, offsetof(t_post, isFixedPitch) },
return NULL;
}
+static unsigned short *cmp_glyphsbyindex;
+static int glyphsbyname_cmp(void const *a, void const *b) {
+ glyph ga = cmp_glyphsbyindex[*(unsigned short *)a];
+ glyph gb = cmp_glyphsbyindex[*(unsigned short *)b];
+ if (ga < gb) return -1;
+ if (ga > gb) return 1;
+ return 0;
+}
+static int glyphsbyname_cmp_search(void const *a, void const *b) {
+ glyph ga = *(glyph *)a;
+ glyph gb = cmp_glyphsbyindex[*(unsigned short *)b];
+ if (ga < gb) return -1;
+ if (ga > gb) return 1;
+ return 0;
+}
+
/*
* Extract data from the 'post' table (mostly glyph mappings)
*
* TODO: cope better with duplicated glyph names (usually .notdef)
* TODO: when presented with format 3.0, try to use 'CFF' if present.
*/
-static void sfnt_mapglyphs(sfnt *sf) {
+static void sfnt_mapglyphs(font_info *fi) {
+ sfnt *sf = fi->fontfile;
t_post post;
void *ptr, *end;
- unsigned char *sptr, tmp[256];
+ unsigned char *sptr;
+ char tmp[256];
glyph *extraglyphs;
unsigned nextras, i, g;
if (!sfnt_findtable(sf, TAG_post, &ptr, &end))
abort();
ptr = decode(t_post_decode, ptr, end, &post);
+
sf->minmem = post.minMemType42;
sf->maxmem = post.maxMemType42;
+ fi->italicangle = post.italicAngle / 65536.0;
if (ptr == NULL) abort();
switch (post.format) {
case 0x00010000:
sf->glyphsbyindex = (glyph *)tt_std_glyphs;
break;
case 0x00020000:
- if ((char *)ptr + 2 > end) return;
+ if ((char *)ptr + 2 > (char *)end) return;
decode_uint16(ptr, &sf->nglyphs);
ptr = (char *)ptr + 2;
- if ((char *)ptr + 2*sf->nglyphs > end) return;
+ if ((char *)ptr + 2*sf->nglyphs > (char *)end) return;
nextras = 0;
- for (sptr = (char *)ptr + 2*sf->nglyphs; sptr < end; sptr += *sptr+1)
+ for (sptr = (unsigned char *)ptr + 2*sf->nglyphs;
+ sptr < (unsigned char *)end;
+ sptr += *sptr+1)
nextras++;
extraglyphs = snewn(nextras, glyph);
i = 0;
- for (sptr = (char *)ptr + 2*sf->nglyphs; sptr < end; sptr += *sptr+1) {
+ for (sptr = (unsigned char *)ptr + 2*sf->nglyphs;
+ sptr < (unsigned char *)end;
+ sptr += *sptr+1) {
memcpy(tmp, sptr + 1, *sptr);
tmp[*sptr] = 0;
assert(i < nextras);
default:
abort();
}
+ /* Construct glyphsbyname */
+ sf->glyphsbyname = snewn(sf->nglyphs, unsigned short);
+ for (i = 0; i < sf->nglyphs; i++)
+ sf->glyphsbyname[i] = i;
+ cmp_glyphsbyindex = sf->glyphsbyindex;
+ qsort(sf->glyphsbyname, sf->nglyphs, sizeof(*sf->glyphsbyname),
+ glyphsbyname_cmp);
+}
+
+static glyph sfnt_indextoglyph(sfnt *sf, unsigned short idx) {
+ return sf->glyphsbyindex[idx];
+}
+
+static unsigned short sfnt_glyphtoindex(sfnt *sf, glyph g) {
+ cmp_glyphsbyindex = sf->glyphsbyindex;
+ return *(unsigned short *)bsearch(&g, sf->glyphsbyname, sf->nglyphs,
+ sizeof(*sf->glyphsbyname),
+ glyphsbyname_cmp_search);
}
/*
abort();
for (i = 0; i < sf->nglyphs; i++) {
glyph_width *w = snew(glyph_width);
- w->glyph = sf->glyphsbyindex[i];
+ w->glyph = sfnt_indextoglyph(sf, i);
j = i < hhea.numOfLongHorMetrics ? i : hhea.numOfLongHorMetrics - 1;
w->width = hmtx[j] * UNITS_PER_PT / sf->head.unitsPerEm;
add234(fi->widths, w);
/*
* Get mapping data from 'cmap' table
*
- * We look for either a (0, 0), (0, 1), (0, 2), (0, 3), or (3, 1) table,
- * all of these being versions of UCS-2. We only handle format 4 of this
- * table, since that seems to be the only one in use.
+ * We look for either a (0, 3), or (3, 1) table, both of these being
+ * versions of UCS-2. We only handle format 4 of this table, since
+ * that seems to be the only one in use.
*/
void sfnt_getmap(font_info *fi) {
sfnt *sf = fi->fontfile;
idx = (k + idDelta[j]) & 0xffff;
if (idx != 0) {
if (idx > sf->nglyphs) abort();
- fi->bmp[k] = sf->glyphsbyindex[idx];
+ fi->bmp[k] = sfnt_indextoglyph(sf, idx);
}
}
} else {
if (idx != 0) {
idx = (idx + idDelta[j]) & 0xffff;
if (idx > sf->nglyphs) abort();
- fi->bmp[k] = sf->glyphsbyindex[idx];
+ fi->bmp[k] = sfnt_indextoglyph(sf, idx);
}
}
}
size_t off = 0, got;
FILE *fp = in->currfp;
font_info *fi = snew(font_info);
- size_t i;
+/* size_t i; */
void *ptr, *end;
fi->name = NULL;
if ((sf->head.version & 0xffff0000) != 0x00010000)
abort();
fi->name = sfnt_psname(fi);
- sfnt_mapglyphs(sf);
+ sfnt_mapglyphs(fi);
sfnt_getmetrics(fi);
sfnt_getmap(fi);
fi->next = all_fonts;
}
fprintf(ofp, "/PaintType 0 def\n");
fprintf(ofp, "/CharStrings %u dict dup begin\n", sf->nglyphs);
+ fprintf(ofp, "0 1 %u{currentfile token pop exch def}bind for\n",
+ sf->nglyphs - 1);
for (i = 0; i < sf->nglyphs; i++)
- fprintf(ofp, "/%s %u def\n", glyph_extern(sf->glyphsbyindex[i]), i);
+ fprintf(ofp, "/%s\n", glyph_extern(sfnt_indextoglyph(sf, i)));
fprintf(ofp, "end readonly def\n");
fprintf(ofp, "/sfnts [<");
breaks = snewn(sf->osd.numTables + sf->nglyphs, size_t);