summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Harris <bjh21@bjh21.me.uk>2007-02-13 00:12:16 +0000
committerBen Harris <bjh21@bjh21.me.uk>2007-02-13 00:12:16 +0000
commit7daf0d6079b52255d280841aa2906bb90abe3878 (patch)
tree94230236a08386953bdc8252cd6329ad63add097
parentf42514d9eafc14726d17d47aff575f0a4a8e7aec (diff)
downloadhalibut-7daf0d6079b52255d280841aa2906bb90abe3878.zip
halibut-7daf0d6079b52255d280841aa2906bb90abe3878.tar.gz
halibut-7daf0d6079b52255d280841aa2906bb90abe3878.tar.bz2
halibut-7daf0d6079b52255d280841aa2906bb90abe3878.tar.xz
Cope with TrueType fonts that have duplicate glyph names by renaming glyphs
as necessary. The algorithm for ensuring that the new name is unused is partly Gareth's fault. [originally from svn r7277]
-rw-r--r--in_sfnt.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/in_sfnt.c b/in_sfnt.c
index f29590b..eb1f7f9 100644
--- a/in_sfnt.c
+++ b/in_sfnt.c
@@ -506,6 +506,9 @@ static int glyphsbyname_cmp(void const *a, void const *b) {
glyph gb = cmp_glyphsbyindex[*(unsigned short *)b];
if (ga < gb) return -1;
if (ga > gb) return 1;
+ /* For de-duping, we'd prefer to have the first glyph stay first */
+ if (*(unsigned short *)a < *(unsigned short *)b) return -1;
+ if (*(unsigned short *)a > *(unsigned short *)b) return 1;
return 0;
}
static int glyphsbyname_cmp_search(void const *a, void const *b) {
@@ -536,8 +539,8 @@ static void sfnt_mapglyphs(font_info *fi) {
void *ptr, *end;
unsigned char *sptr;
char tmp[256];
- glyph *extraglyphs;
- unsigned nextras, i, g;
+ glyph *extraglyphs, prev, this;
+ unsigned nextras, i, g, suflen;
sf->glyphsbyname = sf->glyphsbyindex = NULL;
if (sfnt_findtable(sf, TAG_post, &ptr, &end)) {
@@ -617,6 +620,42 @@ static void sfnt_mapglyphs(font_info *fi) {
cmp_glyphsbyindex = sf->glyphsbyindex;
qsort(sf->glyphsbyname, sf->nglyphs, sizeof(*sf->glyphsbyname),
glyphsbyname_cmp);
+ /*
+ * It's possible for fonts to specify the same name for multiple
+ * glyphs, which would make one of them inaccessible. Check for
+ * that, and rename all but one of each set.
+ *
+ * To ensure that we don't clash with any existing glyph names,
+ * our renaming involves appending the glyph number formatted with
+ * enough leading zeroes to make it longer than any all-digit
+ * suffix that already exists in the font.
+ */
+ suflen = 4;
+ for (i = 0; i < sf->nglyphs; i++) {
+ char const *p;
+ p = strrchr(glyph_extern(sfnt_indextoglyph(sf, i)), '.');
+ if (p && !(p+1)[strspn(p+1, "0123456789")] && strlen(p+1) > suflen)
+ suflen = strlen(p+1);
+ }
+ suflen++;
+ prev = sfnt_indextoglyph(sf, sf->glyphsbyname[0]);
+ for (i = 1; i < sf->nglyphs; i++) {
+ if (prev == (this = sfnt_indextoglyph(sf, sf->glyphsbyname[i]))) {
+ char const *basename;
+ char *buf;
+ basename = glyph_extern(this);
+ buf = snewn(strlen(basename) + 2 + suflen, char);
+ strcpy(buf, basename);
+ sprintf(buf + strlen(basename), ".%0*hu", suflen,
+ sf->glyphsbyname[i]);
+ sf->glyphsbyindex[sf->glyphsbyname[i]] = glyph_intern(buf);
+ sfree(buf);
+ }
+ prev = this;
+ }
+ /* We may have renamed some glyphs, so re-sort the array. */
+ qsort(sf->glyphsbyname, sf->nglyphs, sizeof(*sf->glyphsbyname),
+ glyphsbyname_cmp);
}
glyph sfnt_indextoglyph(sfnt *sf, unsigned idx) {