chiark / gitweb /
Output glyphs in an order that FontForge won't change
authorBen Harris <bjh21@bjh21.me.uk>
Sat, 1 Jun 2024 22:18:25 +0000 (23:18 +0100)
committerBen Harris <bjh21@bjh21.me.uk>
Sun, 18 Aug 2024 12:29:07 +0000 (13:29 +0100)
FontForge has opinions about what order glyphs in an OpenType font
should appear in, at least some of them being mandated by the OpenType
spec (for instance that .notdef must by glyph 0).  When outputting an
OpenType font, FontForge re-orders it in accordance with these opinions.

I expect that this will be a problem if I want to emit a table that
FontForge doesn't understand, since it won't be able to correct the
glyph indexes in that table.  Thus I've added code to re-order the
glyphs in Bedstead such that FontForge won't re-order them.  This should
mean that bedstead.c can safely use the glyph indexes that it generates
without worrying that FontForge might change them.

I don't think FontForge minds what order unencoded glyphs appear in, but
I've defined them to be in strcmp() order of glyph name so that they're
at least somewhat stable.  Before this, they were in the same order as
in the source file.

bedstead.c

index ab4291d9ea42315389845c54428eacce5b0b5a9c..1031a3277a8f6213ae8292903c605bfd945610b0 100644 (file)
@@ -207,7 +207,7 @@ static struct glyph {
 #define SEP6 (SEP | MOS6)
 #define SEP4 (SEP | MOS4)
        char const *alias_of;
-} const glyphs[] = {
+} glyphs[] = {
  /*
   * The first batch of glyphs comes from the code tables at the end of
   * the Mullard SAA5050 series datasheet, dated July 1982.
@@ -2646,6 +2646,27 @@ get_glyph_by_name(char const *name)
        return *gp;
 }
 
+/*
+ * Compare glyphs in a way that will put them in an order that
+ * FontForge won't change.  This should mean that our glyph IDs match
+ * FontForge's, so that we can use them in tables that FontForge
+ * doesn't understand.
+ */
+static int
+compare_glyphs_by_ffid(const void *va, const void *vb)
+{
+       struct glyph const *a = va, *b = vb;
+
+       /* .notdef comes first. */
+       if (strcmp(a->name, ".notdef") == 0) return -1;
+       if (strcmp(b->name, ".notdef") == 0) return +1;
+       /* Then characters with Unicode code-points in order. */
+       if ((unsigned)a->unicode < (unsigned)b->unicode) return -1;
+       if ((unsigned)a->unicode > (unsigned)b->unicode) return +1;
+       /* Finally sort by glyph name for an arbitrary stable order. */
+       return strcmp(a->name, b->name);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -2711,6 +2732,8 @@ main(int argc, char **argv)
                return 0;
        }
 
+       /* Put glyphs into FontForge-compatible order. */
+       qsort(glyphs, nglyphs, sizeof(glyphs[0]), &compare_glyphs_by_ffid);
        for (i = 0; i < nglyphs; i++)
                if (glyphs[i].unicode == -1)
                        extraglyphs++;