51#define VERSION "1.0.1"   
   56#define U32MAX 0xffffffff    
   58#define PRI_CP "U+%.4"PRIXFAST32 
 
   61#define static_assert(a, b) (assert(a))  
   65#define BX(shift, x) ((uintmax_t)(!!(x)) << (shift))  
   66#define B0(shift) BX((shift), 0)     
   67#define B1(shift) BX((shift), 1)     
   69#define GLYPH_MAX_WIDTH 16   
   70#define GLYPH_HEIGHT 16      
   73#define GLYPH_MAX_BYTE_COUNT (GLYPH_HEIGHT * GLYPH_MAX_WIDTH / 8) 
   79#define ASCENDER (GLYPH_HEIGHT - DESCENDER) 
   85#define MAX_GLYPHS 65536 
   88#define MAX_NAME_IDS 256 
   91#define FU(x) ((x) * FUPEM / GLYPH_HEIGHT) 
   94#define PW(x) ((x) / (GLYPH_HEIGHT / 8)) 
  115    fputs (
"ERROR: ", stderr);
 
  117    va_start (args, reason);
 
  118    vfprintf (stderr, reason, args);
 
  136    byte *begin, *next, *end;
 
  158        fail (
"Failed to initialize buffers.");
 
  190    assert (initialCapacity > 0);
 
  206        void *extended = realloc (
allBuffers, newSize);
 
  208            fail (
"Failed to create new buffers.");
 
  215    buf->begin = malloc (initialCapacity);
 
  217        fail (
"Failed to allocate %zu bytes of memory.", initialCapacity);
 
  218    buf->capacity = initialCapacity;
 
  219    buf->next = buf->begin;
 
  220    buf->end = buf->begin + initialCapacity;
 
  241    if (buf->end - buf->next >= needed)
 
  243    ptrdiff_t occupied = buf->next - buf->begin;
 
  244    size_t required = occupied + needed;
 
  245    if (required < needed) 
 
  246        fail (
"Cannot allocate %zu + %zu bytes of memory.", occupied, needed);
 
  247    if (required > SIZE_MAX / 2)
 
  248        buf->capacity = required;
 
  249    else while (buf->capacity < required)
 
  251    void *extended = realloc (buf->begin, buf->capacity);
 
  253        fail (
"Failed to allocate %zu bytes of memory.", buf->capacity);
 
  254    buf->begin = extended;
 
  255    buf->next = buf->begin + occupied;
 
  256    buf->end = buf->begin + buf->capacity;
 
  266countBufferedBytes (
const Buffer *buf)
 
  268    return buf->next - buf->begin;
 
  278getBufferHead (
const Buffer *buf)
 
  290getBufferTail (
const Buffer *buf)
 
  306getBufferSlot (
Buffer *buf, 
size_t slotSize)
 
  309    void *slot = buf->next;
 
  310    buf->next += slotSize;
 
  325    buf->next = buf->begin;
 
  350#define defineStore(name, type) \ 
  351void name (Buffer *buf, type value) \ 
  353    type *slot = getBufferSlot (buf, sizeof value); \ 
  374cacheU (
Buffer *buf, uint_fast32_t value, 
int bytes)
 
  376    assert (1 <= bytes && bytes <= 4);
 
  380        case 4: *buf->next++ = value >> 24 & 0xff; 
 
  381        case 3: *buf->next++ = value >> 16 & 0xff; 
 
  382        case 2: *buf->next++ = value >> 8  & 0xff; 
 
  383        case 1: *buf->next++ = value       & 0xff;
 
  399    storeU8 (buf, value & 0xff);
 
  414    cacheU (buf, value, 2);
 
  429    cacheU (buf, value, 4);
 
  462    if (-107 <= value && value <= 107)
 
  464    else if (108 <= value && value <= 1131)
 
  466        cacheU8 (buf, (value - 108) / 256 + 247);
 
  467        cacheU8 (buf, (value - 108) % 256);
 
  469    else if (-32768 <= value && value <= 32767)
 
  474    else if (-2147483647 <= value && value <= 2147483647)
 
  494    memset (buf->next, 0, count);
 
  512    memcpy (buf->next, src, count);
 
  525    size_t length = countBufferedBytes (bufSrc);
 
  527    memcpy (bufDest->next, bufSrc->begin, length);
 
  528    bufDest->next += length;
 
  540    if (fwrite (bytes, count, 1, file) != 1 && count != 0)
 
  541        fail (
"Failed to write %zu bytes to output file.", count);
 
  578        (value >> 24) & 0xff,
 
  579        (value >> 16) & 0xff,
 
  598writeBuffer (
const Buffer *buf, FILE *file)
 
  600    writeBytes (getBufferHead (buf), countBufferedBytes (buf), file);
 
  632    uint_fast32_t glyphCount;
 
  672static inline uint_fast32_t tagAsU32 (
const char tag[
static 4])
 
  675    r |= (tag[0] & 0xff) << 24;
 
  676    r |= (tag[1] & 0xff) << 16;
 
  677    r |= (tag[2] & 0xff) << 8;
 
  678    r |= (tag[3] & 0xff);
 
  696    Table *table = getBufferSlot (font->tables, sizeof (
Table));
 
  697    table->tag = tagAsU32 (tag);
 
  698    table->content = content;
 
  713    const char *
const cffOrder[] = {
"head",
"hhea",
"maxp",
"OS/2",
"name",
 
  714        "cmap",
"post",
"CFF ",NULL};
 
  715    const char *
const truetypeOrder[] = {
"head",
"hhea",
"maxp",
"OS/2",
 
  716        "hmtx",
"LTSH",
"VDMX",
"hdmx",
"cmap",
"fpgm",
"prep",
"cvt ",
"loca",
 
  717        "glyf",
"kern",
"name",
"post",
"gasp",
"PCLT",
"DSIG",NULL};
 
  718    const char *
const *
const order = isCFF ? cffOrder : truetypeOrder;
 
  719    Table *unordered = getBufferHead (font->tables);
 
  720    const Table *
const tablesEnd = getBufferTail (font->tables);
 
  721    for (
const char *
const *p = order; *p; p++)
 
  723        uint_fast32_t tag = tagAsU32 (*p);
 
  724        for (
Table *t = unordered; t < tablesEnd; t++)
 
  730                Table temp = *unordered;
 
  749    uint_least32_t tag, offset, length, checksum;
 
  769    const struct TableRecord *
const ra = a, *
const rb = b;
 
  770    int gt = ra->tag > rb->tag;
 
  771    int lt = ra->tag < rb->tag;
 
  788    FILE *file = fopen (fileName, 
"wb");
 
  790        fail (
"Failed to open file '%s'.", fileName);
 
  791    const Table *
const tables = getBufferHead (font->tables);
 
  792    const Table *
const tablesEnd = getBufferTail (font->tables);
 
  793    size_t tableCount = tablesEnd - tables;
 
  794    assert (0 < tableCount && tableCount <= 
U16MAX);
 
  795    size_t offset = 12 + 16 * tableCount;
 
  796    uint_fast32_t totalChecksum = 0;
 
  799    for (
size_t i = 0; i < tableCount; i++)
 
  802            getBufferSlot (tableRecords, 
sizeof *record);
 
  803        record->tag = tables[i].tag;
 
  804        size_t length = countBufferedBytes (tables[i].content);
 
  805        #if SIZE_MAX > U32MAX 
  807                fail (
"Table offset exceeded 4 GiB.");
 
  809                fail (
"Table size exceeded 4 GiB.");
 
  811        record->length = length;
 
  812        record->checksum = 0;
 
  813        const byte *p = getBufferHead (tables[i].content);
 
  814        const byte *
const end = getBufferTail (tables[i].content);
 
  817        #define addByte(shift) \ 
  820            record->checksum += (uint_fast32_t)*p++ << (shift); 
  830        cacheZeros (tables[i].content, (~length + 1U) & 3U);
 
  831        record->offset = offset;
 
  832        offset += countBufferedBytes (tables[i].content);
 
  833        totalChecksum += record->checksum;
 
  835    struct TableRecord *records = getBufferHead (tableRecords);
 
  836    qsort (records, tableCount, 
sizeof *records, 
byTableTag);
 
  838    uint_fast32_t sfntVersion = isCFF ? 0x4f54544f : 0x00010000;
 
  840    totalChecksum += sfntVersion;
 
  841    uint_fast16_t entrySelector = 0;
 
  842    for (
size_t k = tableCount; k != 1; k >>= 1)
 
  844    uint_fast16_t searchRange = 1 << (entrySelector + 4);
 
  845    uint_fast16_t rangeShift = (tableCount - (1 << entrySelector)) << 4;
 
  850    totalChecksum += (uint_fast32_t)tableCount << 16;
 
  851    totalChecksum += searchRange;
 
  852    totalChecksum += (uint_fast32_t)entrySelector << 16;
 
  853    totalChecksum += rangeShift;
 
  855    for (
size_t i = 0; i < tableCount; i++)
 
  859        writeU32 (records[i].checksum, file); 
 
  862        totalChecksum += records[i].tag;
 
  863        totalChecksum += records[i].checksum;
 
  864        totalChecksum += records[i].offset;
 
  865        totalChecksum += records[i].length;
 
  868    for (
const Table *table = tables; table < tablesEnd; table++)
 
  870        if (table->tag == 0x68656164) 
 
  872            byte *begin = getBufferHead (table->content);
 
  873            byte *end = getBufferTail (table->content);
 
  875            writeU32 (0xb1b0afbaU - totalChecksum, file); 
 
  876            writeBytes (begin + 12, end - (begin + 12), file);
 
  879        writeBuffer (table->content, file);
 
  895nibbleValue (
char nibble)
 
  897    if (isdigit (nibble))
 
  899    nibble = toupper (nibble);
 
  900    return nibble - 
'A' + 10;
 
  922    uint_fast8_t digitCount = 0;
 
  926        if (isxdigit (c) && ++digitCount <= 6)
 
  928            *codePoint = (*codePoint << 4) | nibbleValue (c);
 
  931        if (c == 
':' && digitCount > 0)
 
  938                fail (
"%s: Unexpected end of file.", fileName);
 
  940                fail (
"%s: Read error.", fileName);
 
  942        fail (
"%s: Unexpected character: %#.2x.", fileName, (
unsigned)c);
 
  968    FILE *file = fopen (fileName, 
"r");
 
  970        fail (
"Failed to open file '%s'.", fileName);
 
  971    uint_fast32_t glyphCount = 1; 
 
  972    uint_fast8_t maxByteCount = 0;
 
  974        const byte bitmap[] = 
"\0\0\0~fZZzvv~vv~\0\0"; 
 
  975        const size_t byteCount = 
sizeof bitmap - 1;
 
  978        Glyph *notdef = getBufferSlot (font->glyphs, sizeof (
Glyph));
 
  979        memcpy (notdef->
bitmap, bitmap, byteCount);
 
  980        notdef->
byteCount = maxByteCount = byteCount;
 
  987        uint_fast32_t codePoint;
 
  991            fail (
"OpenType does not support more than %lu glyphs.",
 
  993        Glyph *glyph = getBufferSlot (font->glyphs, sizeof (
Glyph));
 
  999        for (
byte *p = glyph->
bitmap;; p++)
 
 1002            if (isxdigit (h = getc (file)) && isxdigit (l = getc (file)))
 
 1005                    fail (
"Hex stream of "PRI_CP" is too long.", codePoint);
 
 1006                *p = nibbleValue (h) << 4 | nibbleValue (l);
 
 1008            else if (h == 
'\n' || (h == EOF && feof (file)))
 
 1010            else if (ferror (file))
 
 1011                fail (
"%s: Read error.", fileName);
 
 1013                fail (
"Hex stream of "PRI_CP" is invalid.", codePoint);
 
 1016            fail (
"Hex length of "PRI_CP" is indivisible by glyph height %d.",
 
 1021    if (glyphCount == 1)
 
 1022        fail (
"No glyph is specified.");
 
 1023    font->glyphCount = glyphCount;
 
 1024    font->maxWidth = 
PW (maxByteCount);
 
 1042    const Glyph *
const ga = a, *
const gb = b;
 
 1064    FILE *file = fopen (fileName, 
"r");
 
 1066        fail (
"Failed to open file '%s'.", fileName);
 
 1067    Glyph *glyphs = getBufferHead (font->glyphs);
 
 1068    const Glyph *
const endGlyph = glyphs + font->glyphCount;
 
 1069    Glyph *nextGlyph = &glyphs[1]; 
 
 1072        uint_fast32_t codePoint;
 
 1075        Glyph *glyph = nextGlyph;
 
 1076        if (glyph == endGlyph || glyph->
codePoint != codePoint)
 
 1080            glyph = bsearch (&key, glyphs + 1, font->glyphCount - 1,
 
 1083                fail (
"Glyph "PRI_CP" is positioned but not defined.",
 
 1086        nextGlyph = glyph + 1;
 
 1088        if (!fgets (s, 
sizeof s, file))
 
 1089            fail (
"%s: Read error.", fileName);
 
 1091        const long value = strtol (s, &end, 10);
 
 1092        if (*end != 
'\n' && *end != 
'\0')
 
 1093            fail (
"Position of glyph "PRI_CP" is invalid.", codePoint);
 
 1098        if (value < -GLYPH_MAX_WIDTH || value > 0)
 
 1099            fail (
"Position of glyph "PRI_CP" is out of range.", codePoint);
 
 1121    Glyph *glyphs = getBufferHead (font->glyphs);
 
 1122    const Glyph *
const glyphsEnd = getBufferTail (font->glyphs);
 
 1124    qsort (glyphs, glyphsEnd - glyphs, 
sizeof *glyphs, 
byCodePoint);
 
 1125    for (
const Glyph *glyph = glyphs; glyph < glyphsEnd - 1; glyph++)
 
 1127        if (glyph[0].codePoint == glyph[1].codePoint)
 
 1128            fail (
"Duplicate code point: "PRI_CP".", glyph[0].codePoint);
 
 1129        assert (glyph[0].codePoint < glyph[1].codePoint);
 
 1163    enum Direction {RIGHT, LEFT, DOWN, UP}; 
 
 1166    const pixels_t dx[] = {1, -1, 0, 0}, dy[] = {0, 0, -1, 1};
 
 1169    const uint_fast8_t bytesPerRow = byteCount / 
GLYPH_HEIGHT;
 
 1170    const pixels_t glyphWidth = bytesPerRow * 8;
 
 1173    #if GLYPH_MAX_WIDTH < 32 
 1174        typedef uint_fast32_t row_t;
 
 1175    #elif GLYPH_MAX_WIDTH < 64 
 1176        typedef uint_fast64_t row_t;
 
 1178        #error GLYPH_MAX_WIDTH is too large. 
 1183        for (
pixels_t b = 0; b < bytesPerRow; b++)
 
 1184            pixels[row] = pixels[row] << 8 | *bitmap++;
 
 1187    const row_t *lower = pixels, *upper = pixels + 1;
 
 1190        const row_t m = (fillSide == 
FILL_RIGHT) - 1;
 
 1191        vectors[RIGHT][row] = (m ^ (*lower << 1)) & (~m ^ (*upper << 1));
 
 1192        vectors[LEFT ][row] = (m ^ (*upper     )) & (~m ^ (*lower     ));
 
 1193        vectors[DOWN ][row] = (m ^ (*lower     )) & (~m ^ (*lower << 1));
 
 1194        vectors[UP   ][row] = (m ^ (*upper << 1)) & (~m ^ (*upper     ));
 
 1198    graph_t selection = {0};
 
 1199    const row_t x0 = (row_t)1 << glyphWidth;
 
 1202    #define getRowBit(rows, x, y)  ((rows)[(y)] &  x0 >> (x)) 
 1205    #define flipRowBit(rows, x, y) ((rows)[(y)] ^= x0 >> (x)) 
 1209        for (
pixels_t x = 0; x <= glyphWidth; x++)
 
 1211            assert (!getRowBit (vectors[LEFT], x, y));
 
 1212            assert (!getRowBit (vectors[UP], x, y));
 
 1213            enum Direction initial;
 
 1215            if (getRowBit (vectors[RIGHT], x, y))
 
 1217            else if (getRowBit (vectors[DOWN], x, y))
 
 1223                U16MAX, 
"potential overflow");
 
 1225            uint_fast16_t lastPointCount = 0;
 
 1226            for (
bool converged = 
false;;)
 
 1228                uint_fast16_t pointCount = 0;
 
 1229                enum Direction heading = initial;
 
 1235                        storePixels (result, tx);
 
 1236                        storePixels (result, ty);
 
 1241                            flipRowBit (vectors[heading], tx, ty);
 
 1244                    } 
while (getRowBit (vectors[heading], tx, ty));
 
 1245                    if (tx == x && ty == y)
 
 1247                    static_assert ((UP ^ DOWN) == 1 && (LEFT ^ RIGHT) == 1,
 
 1249                    heading = (heading & 2) ^ 2;
 
 1250                    heading |= !!getRowBit (selection, tx, ty);
 
 1251                    heading ^= !getRowBit (vectors[heading], tx, ty);
 
 1252                    assert (getRowBit (vectors[heading], tx, ty));
 
 1253                    flipRowBit (selection, tx, ty);
 
 1258                converged = pointCount == lastPointCount;
 
 1259                lastPointCount = pointCount;
 
 1278    for (
size_t *i = sizes + 1; *i; i++)
 
 1280    if (*p > 2147483647U) 
 
 1281        fail (
"CFF table is too large.");
 
 1295    const char *strings[] = {
"Adobe", 
"Identity", names[6]};
 
 1297    #define stringCount (sizeof strings / sizeof *strings) 
 1298    static_assert (stringCount <= 
U16MAX, 
"too many strings");
 
 1300    size_t lengths[stringCount];
 
 1301    for (
size_t i = 0; i < stringCount; i++)
 
 1303        assert (strings[i]);
 
 1304        lengths[i] = strlen (strings[i]);
 
 1305        offset += lengths[i];
 
 1307    int offsetSize = 1 + (offset > 0xff)
 
 1309                       + (offset > 0xffffff);
 
 1312    cacheU (buf, offset = 1, offsetSize); 
 
 1313    for (
size_t i = 0; i < stringCount; i++)
 
 1314        cacheU (buf, offset += lengths[i], offsetSize); 
 
 1315    for (
size_t i = 0; i < stringCount; i++)
 
 1332    assert (0 < version && version <= 2);
 
 1334    addTable (font, version == 1 ? 
"CFF " : 
"CFF2", cff);
 
 1337    #define cacheCFF32(buf, x) (cacheU8 ((buf), 29), cacheU32 ((buf), (x))) 
 1340    const pixels_t defaultWidth = 16, nominalWidth = 8;
 
 1344        size_t stringsSize = countBufferedBytes (strings);
 
 1345        const char *cffName = names[6];
 
 1347        size_t nameLength = strlen (cffName);
 
 1348        size_t namesSize = nameLength + 5;
 
 1350        size_t offsets[] = {4, namesSize, 45, stringsSize, 2, 5, 8, 32, 4, 0};
 
 1358        assert (countBufferedBytes (cff) == offsets[0]);
 
 1363            if (nameLength + 1 > 255) 
 
 1364                fail (
"PostScript name is too long.");
 
 1365            cacheU8 (cff, nameLength + 1); 
 
 1368        assert (countBufferedBytes (cff) == offsets[1]);
 
 1378            cacheCFF32 (cff, font->glyphCount);
 
 1380            cacheCFF32 (cff, offsets[6]);
 
 1382            cacheCFF32 (cff, offsets[5]);
 
 1384            cacheCFF32 (cff, offsets[4]);
 
 1386            cacheCFF32 (cff, offsets[8]);
 
 1389        assert (countBufferedBytes (cff) == offsets[2]);
 
 1394        assert (countBufferedBytes (cff) == offsets[3]);
 
 1396        assert (countBufferedBytes (cff) == offsets[4]);
 
 1401                cacheU16 (cff, font->glyphCount - 2); 
 
 1404        assert (countBufferedBytes (cff) == offsets[5]);
 
 1412        assert (countBufferedBytes (cff) == offsets[6]);
 
 1421            const byte unit[] = {0x1e,0x15,0x62,0x5c,0x6f}; 
 
 1430            cacheCFF32 (cff, offsets[7]); 
 
 1433        assert (countBufferedBytes (cff) == offsets[7]);
 
 1440        assert (countBufferedBytes (cff) == offsets[8]);
 
 1444        assert (version == 2);
 
 1446        size_t offsets[] = {5, 21, 4, 10, 0};
 
 1452            cacheU16 (cff, offsets[1] - offsets[0]); 
 
 1454        assert (countBufferedBytes (cff) == offsets[0]);
 
 1456            const byte unit[] = {0x1e,0x15,0x62,0x5c,0x6f}; 
 
 1469        assert (countBufferedBytes (cff) == offsets[1]);
 
 1471        assert (countBufferedBytes (cff) == offsets[2]);
 
 1481        assert (countBufferedBytes (cff) == offsets[3]);
 
 1487        const Glyph *glyph = getBufferHead (font->glyphs);
 
 1488        const Glyph *
const endGlyph = glyph + font->glyphCount;
 
 1489        for (; glyph < endGlyph; glyph++)
 
 1492            storeU32 (offsets, countBufferedBytes (charstrings) + 1);
 
 1496            resetBuffer (outline);
 
 1498            enum CFFOp {rmoveto=21, hmoveto=22, vmoveto=4, hlineto=6,
 
 1499                vlineto=7, endchar=14};
 
 1500            enum CFFOp pendingOp = 0;
 
 1501            const int STACK_LIMIT = version == 1 ? 48 : 513;
 
 1503            bool isDrawing = 
false;
 
 1505            if (version == 1 && width != defaultWidth)
 
 1510            for (
const pixels_t *p = getBufferHead (outline),
 
 1511                 *
const end = getBufferTail (outline); p < end;)
 
 1532                    assert (!(isDrawing && s == 3));
 
 1538                        const enum CFFOp moves[] = {0, hmoveto, vmoveto,
 
 1540                        cacheU8 (charstrings, moves[s]);
 
 1543                    else if (!pendingOp)
 
 1544                        pendingOp = (
enum CFFOp[]){0, hlineto, vlineto}[s];
 
 1546                else if (!isDrawing)
 
 1550                    cacheU8 (charstrings, hmoveto);
 
 1553                if (op == 
OP_CLOSE || stackSize >= STACK_LIMIT)
 
 1555                    assert (stackSize <= STACK_LIMIT);
 
 1556                    cacheU8 (charstrings, pendingOp);
 
 1563                cacheU8 (charstrings, endchar);
 
 1565        size_t lastOffset = countBufferedBytes (charstrings) + 1;
 
 1566        #if SIZE_MAX > U32MAX 
 1568                fail (
"CFF data exceeded size limit.");
 
 1570        storeU32 (offsets, lastOffset);
 
 1571        int offsetSize = 1 + (lastOffset > 0xff)
 
 1572                           + (lastOffset > 0xffff)
 
 1573                           + (lastOffset > 0xffffff);
 
 1575        cacheU (cff, font->glyphCount, version * 2);
 
 1577        const uint_least32_t *p = getBufferHead (offsets);
 
 1578        const uint_least32_t *
const end = getBufferTail (offsets);
 
 1579        for (; p < end; p++)
 
 1580            cacheU (cff, *p, offsetSize); 
 
 1598    uint_fast16_t *maxPoints, uint_fast16_t *maxContours)
 
 1610    Glyph *
const glyphs = getBufferHead (font->glyphs);
 
 1611    const Glyph *
const glyphsEnd = getBufferTail (font->glyphs);
 
 1612    for (
Glyph *glyph = glyphs; glyph < glyphsEnd; glyph++)
 
 1614        cacheU32 (loca, countBufferedBytes (glyf));
 
 1619        resetBuffer (endPoints);
 
 1620        resetBuffer (flags);
 
 1623        resetBuffer (outline);
 
 1625        uint_fast32_t pointCount = 0, contourCount = 0;
 
 1626        for (
const pixels_t *p = getBufferHead (outline),
 
 1627             *
const end = getBufferTail (outline); p < end;)
 
 1633                assert (contourCount <= 
U16MAX);
 
 1634                cacheU16 (endPoints, pointCount - 1);
 
 1639            assert (pointCount <= 
U16MAX);
 
 1641            uint_fast8_t pointFlags =
 
 1655                cacheU8 (xs, 
FU (x > rx ? x - rx : rx - x));
 
 1657                cacheU8 (ys, 
FU (y > ry ? y - ry : ry - y));
 
 1658            if (x < xMin) xMin = x;
 
 1659            if (y < yMin) yMin = y;
 
 1660            if (x > xMax) xMax = x;
 
 1661            if (y > yMax) yMax = y;
 
 1665        if (contourCount == 0)
 
 1667        glyph->lsb = glyph->pos + xMin;
 
 1678        if (pointCount > *maxPoints)
 
 1679            *maxPoints = pointCount;
 
 1680        if (contourCount > *maxContours)
 
 1681            *maxContours = contourCount;
 
 1683    cacheU32 (loca, countBufferedBytes (glyf));
 
 1711    assert (countBufferedBytes (glyf) % 2 == 0);
 
 1712    for (uint_fast32_t i = 1; i <= font->glyphCount; i++)
 
 1713        cacheU16 (loca, countBufferedBytes (glyf) / 2); 
 
 1730    const Glyph *
const glyphs = getBufferHead (font->glyphs);
 
 1731    const Glyph *
const glyphsEnd = getBufferTail (font->glyphs);
 
 1732    size_t bitmapsSize = 0;
 
 1733    for (
const Glyph *glyph = glyphs; glyph < glyphsEnd; glyph++)
 
 1734        bitmapsSize += glyph->byteCount;
 
 1739    uint_fast8_t byteCount = 0; 
 
 1741    bool combining = 
false;
 
 1744    for (
const Glyph *glyph = glyphs; glyph < glyphsEnd; glyph++)
 
 1746        if (glyph->byteCount != byteCount || glyph->pos != pos ||
 
 1747            glyph->combining != combining)
 
 1749            storeU16 (rangeHeads, glyph - glyphs);
 
 1750            storeU32 (offsets, countBufferedBytes (ebdt));
 
 1751            byteCount = glyph->byteCount;
 
 1753            combining = glyph->combining;
 
 1757    const uint_least16_t *ranges = getBufferHead (rangeHeads);
 
 1758    const uint_least16_t *rangesEnd = getBufferTail (rangeHeads);
 
 1759    uint_fast32_t rangeCount = rangesEnd - ranges;
 
 1760    storeU16 (rangeHeads, font->glyphCount);
 
 1768        cacheU32 (eblc, (8 + 20) * rangeCount); 
 
 1774            cacheU8 (eblc, font->maxWidth); 
 
 1788            cacheU8 (eblc, font->maxWidth); 
 
 1800        cacheU16 (eblc, font->glyphCount - 1); 
 
 1807        uint_fast32_t offset = rangeCount * 8;
 
 1808        for (
const uint_least16_t *p = ranges; p < rangesEnd; p++)
 
 1817        const uint_least32_t *offset = getBufferHead (offsets);
 
 1818        for (
const uint_least16_t *p = ranges; p < rangesEnd; p++)
 
 1820            const Glyph *glyph = &glyphs[*p];
 
 1864    const uint_fast16_t flags =
 
 1891    const uint_fast16_t macStyle =
 
 1955    uint_fast16_t maxContours)
 
 1959    cacheU32 (maxp, isCFF ? 0x00005000 : 0x00010000); 
 
 1995    const uint_fast16_t typeFlags =
 
 2019    const byte panose[] =
 
 2043    const uint_fast16_t selection =
 
 2057    const Glyph *glyphs = getBufferHead (font->glyphs);
 
 2058    uint_fast32_t first = glyphs[1].
codePoint;
 
 2059    uint_fast32_t last = glyphs[font->glyphCount - 1].
codePoint;
 
 2091    const Glyph *
const glyphs = getBufferHead (font->glyphs);
 
 2092    const Glyph *
const glyphsEnd = getBufferTail (font->glyphs);
 
 2093    for (
const Glyph *glyph = glyphs; glyph < glyphsEnd; glyph++)
 
 2095        int_fast16_t aw = glyph->combining ? 0 : 
PW (glyph->byteCount);
 
 2111    Glyph *
const glyphs = getBufferHead (font->glyphs);
 
 2113    uint_fast32_t rangeCount = 0;
 
 2114    uint_fast32_t bmpRangeCount = 1; 
 
 2116    for (uint_fast16_t i = 1; i < font->glyphCount; i++)
 
 2118        if (glyphs[i].codePoint != glyphs[i - 1].codePoint + 1)
 
 2120            storeU16 (rangeHeads, i);
 
 2122            bmpRangeCount += glyphs[i].
codePoint < 0xffff;
 
 2128    bool hasFormat12 = glyphs[font->glyphCount - 1].
codePoint > 0xffff;
 
 2134        cacheU32 (cmap, 12 + 8 * hasFormat12); 
 
 2140        cacheU32 (cmap, 36 + 8 * bmpRangeCount); 
 
 2142    const uint_least16_t *ranges = getBufferHead (rangeHeads);
 
 2143    const uint_least16_t *
const rangesEnd = getBufferTail (rangeHeads);
 
 2144    storeU16 (rangeHeads, font->glyphCount);
 
 2147        cacheU16 (cmap, 16 + 8 * bmpRangeCount); 
 
 2149        if (bmpRangeCount * 2 > 
U16MAX)
 
 2150            fail (
"Too many ranges in 'cmap' table.");
 
 2151        cacheU16 (cmap, bmpRangeCount * 2); 
 
 2152        uint_fast16_t searchRange = 1, entrySelector = -1;
 
 2153        while (searchRange <= bmpRangeCount)
 
 2160        cacheU16 (cmap, bmpRangeCount * 2 - searchRange); 
 
 2162            const uint_least16_t *p = ranges;
 
 2163            for (p++; p < rangesEnd && glyphs[*p].
codePoint < 0xffff; p++)
 
 2164                cacheU16 (cmap, glyphs[*p - 1].codePoint);
 
 2165            uint_fast32_t cp = glyphs[*p - 1].
codePoint;
 
 2173            for (uint_fast32_t i = 0; i < bmpRangeCount - 1; i++)
 
 2174                cacheU16 (cmap, glyphs[ranges[i]].codePoint);
 
 2178            const uint_least16_t *p = ranges;
 
 2179            for (; p < rangesEnd && glyphs[*p].
codePoint < 0xffff; p++)
 
 2180                cacheU16 (cmap, *p - glyphs[*p].codePoint);
 
 2181            uint_fast16_t delta = 1;
 
 2182            if (p < rangesEnd && *p == 0xffff)
 
 2187            for (uint_least16_t i = 0; i < bmpRangeCount; i++)
 
 2195        cacheU32 (cmap, 16 + 12 * rangeCount); 
 
 2200        for (
const uint_least16_t *p = ranges; p < rangesEnd; p++)
 
 2202            cacheU32 (cmap, glyphs[*p].codePoint); 
 
 2203            cacheU32 (cmap, glyphs[p[1] - 1].codePoint); 
 
 2318    for (
const char *p = str; *p; p++)
 
 2328        for (; c & mask; mask >>= 1)
 
 2330        if (length == 1 || length > 4)
 
 2331            fail (
"Ill-formed UTF-8 sequence.");
 
 2332        uint_fast32_t codePoint = c & (mask - 1);
 
 2333        for (
int i = 1; i < length; i++)
 
 2336            if ((c & 0xc0) != 0x80) 
 
 2337                fail (
"Ill-formed UTF-8 sequence.");
 
 2338            codePoint = (codePoint << 6) | (c & 0x3f);
 
 2340        const int lowerBits = length==2 ? 7 : length==3 ? 11 : 16;
 
 2341        if (codePoint >> lowerBits == 0)
 
 2342            fail (
"Ill-formed UTF-8 sequence."); 
 
 2343        if (codePoint >= 0xd800 && codePoint <= 0xdfff)
 
 2344            fail (
"Ill-formed UTF-8 sequence.");
 
 2345        if (codePoint > 0x10ffff)
 
 2346            fail (
"Ill-formed UTF-8 sequence.");
 
 2347        if (codePoint > 0xffff)
 
 2349            cacheU16 (buf, 0xd800 | (codePoint - 0x10000) >> 10);
 
 2350            cacheU16 (buf, 0xdc00 | (codePoint & 0x3ff));
 
 2370    size_t nameStringCount = 0;
 
 2372        nameStringCount += !!nameStrings[i];
 
 2375    cacheU16 (name, 2 * 3 + 12 * nameStringCount); 
 
 2380        if (!nameStrings[i])
 
 2382        size_t offset = countBufferedBytes (stringData);
 
 2384        size_t length = countBufferedBytes (stringData) - offset;
 
 2386            fail (
"Name strings are too long.");
 
 2408    printf (
"hex2otf (GNU Unifont) %s\n", 
VERSION);
 
 2409    printf (
"Copyright \u00A9 2022 \u4F55\u5FD7\u7FD4 (He Zhixiang)\n");
 
 2410    printf (
"License GPLv2+: GNU GPL version 2 or later\n");
 
 2411    printf (
"<https://gnu.org/licenses/gpl.html>\n");
 
 2412    printf (
"This is free software: you are free to change and\n");
 
 2413    printf (
"redistribute it.  There is NO WARRANTY, to the extent\n");
 
 2414    printf (
"permitted by law.\n");
 
 2416    exit (EXIT_SUCCESS);
 
 2427    printf (
"Synopsis: hex2otf <options>:\n\n");
 
 2428    printf (
"    hex=<filename>        Specify Unifont .hex input file.\n");
 
 2429    printf (
"    pos=<filename>        Specify combining file. (Optional)\n");
 
 2430    printf (
"    out=<filename>        Specify output font file.\n");
 
 2431    printf (
"    format=<f1>,<f2>,...  Specify font format(s); values:\n");
 
 2434    printf (
"                             truetype\n");
 
 2435    printf (
"                             blank\n");
 
 2436    printf (
"                             bitmap\n");
 
 2439    printf (
"\nExample:\n\n");
 
 2440    printf (
"    hex2otf hex=Myfont.hex out=Myfont.otf format=cff\n\n");
 
 2441    printf (
"For more information, consult the hex2otf(1) man page.\n\n");
 
 2443    exit (EXIT_SUCCESS);
 
 2455    bool truetype, blankOutline, bitmap, gpos, gsub;
 
 2457    const char *hex, *pos, *out; 
 
 2473        if (*operand++ != *key++)
 
 2475    if (!*operand || *operand++ == delimiter)
 
 2503    const char *format = NULL;
 
 2506        const char *
const key;
 
 2507        const char **
const value;
 
 2513        {
"format", &format},
 
 2516    for (
char *
const *argp = argv + 1; *argp; argp++)
 
 2518        const char *
const arg = *argp;
 
 2519        struct StringArg *p;
 
 2520        const char *value = NULL;
 
 2521        if (strcmp (arg, 
"--help") == 0)
 
 2523        if (strcmp (arg, 
"--version") == 0)
 
 2525        for (p = strArgs; p->key; p++)
 
 2531                fail (
"Empty argument: '%s'.", p->key);
 
 2533                fail (
"Duplicate argument: '%s'.", p->key);
 
 2539            unsigned long id = strtoul (arg, &endptr, 10);
 
 2540            if (endptr == arg || 
id >= 
MAX_NAME_IDS || *endptr != 
'=')
 
 2541                fail (
"Invalid argument: '%s'.", arg);
 
 2543            if (opt.nameStrings[
id])
 
 2544                fail (
"Duplicate name ID: %lu.", 
id);
 
 2545            opt.nameStrings[id] = endptr;
 
 2549        fail (
"Hex file is not specified.");
 
 2550    if (opt.pos && opt.pos[0] == 
'\0')
 
 2553        fail (
"Output file is not specified.");
 
 2555        fail (
"Format is not specified.");
 
 2557        if (!opt.nameStrings[p->id])
 
 2558            opt.nameStrings[p->id] = p->str;
 
 2559    bool cff = 
false, cff2 = 
false;
 
 2562        const char *
const key;
 
 2568        {
"truetype", &opt.truetype},
 
 2569        {
"blank", &opt.blankOutline},
 
 2570        {
"bitmap", &opt.bitmap},
 
 2571        {
"gpos", &opt.gpos},
 
 2572        {
"gsub", &opt.gsub},
 
 2577        const struct Symbol *p;
 
 2578        const char *next = NULL;
 
 2579        for (p = symbols; p->key; p++)
 
 2580            if ((next = 
matchToken (format, p->key, 
',')))
 
 2583            fail (
"Invalid format.");
 
 2587    if (cff + cff2 + opt.truetype + opt.blankOutline > 1)
 
 2588        fail (
"At most one outline format can be accepted.");
 
 2589    if (!(cff || cff2 || opt.truetype || opt.bitmap))
 
 2590        fail (
"Invalid format.");
 
 2591    opt.cff = cff + cff2 * 2;
 
 2614    uint_fast16_t maxPoints = 0, maxContours = 0;
 
 2623        fillCFF (&font, opt.cff, opt.nameStrings);
 
 2626    if (opt.blankOutline)
 
 2640    return EXIT_SUCCESS;
 
#define U16MAX
Maximum UTF-16 code point value.
void organizeTables(Font *font, bool isCFF)
Sort tables according to OpenType recommendations.
void cacheU32(Buffer *buf, uint_fast32_t value)
Append four unsigned bytes to the end of a byte array.
Buffer * allBuffers
Initial allocation of empty array of buffer pointers.
#define MAX_NAME_IDS
Name IDs 0-255 are used for standard names.
void fillGsubTable(Font *font)
Fill a "GSUB" font table.
void writeFont(Font *font, bool isCFF, const char *fileName)
Write OpenType font to output file.
void cacheU16(Buffer *buf, uint_fast16_t value)
Append two unsigned bytes to the end of a byte array.
const char * NameStrings[MAX_NAME_IDS]
Array of OpenType names indexed directly by Name IDs.
unsigned char byte
Definition of "byte" type as an unsigned char.
int byCodePoint(const void *a, const void *b)
Compare two Unicode code points to determine which is greater.
void printHelp()
Print help message to stdout and then exit.
void cacheZeros(Buffer *buf, size_t count)
Append 1 to 4 bytes of zeroes to a buffer, for padding.
void fillPostTable(Font *font)
Fill a "post" font table.
int main(int argc, char *argv[])
The main function.
#define defineStore(name, type)
Temporary define to look up an element in an array of given type.
size_t nextBufferIndex
Index number to tail element of Buffer * array.
#define B0(shift)
Clear a given bit in a word.
void cacheStringAsUTF16BE(Buffer *buf, const char *str)
Cache a string as a big-ending UTF-16 surrogate pair.
#define MAX_GLYPHS
An OpenType font has at most 65536 glyphs.
#define VERSION
Program version, for "--version" option.
void addTable(Font *font, const char tag[static 4], Buffer *content)
Add a TrueType or OpenType table to the font.
#define B1(shift)
Set a given bit in a word.
ContourOp
Specify the current contour drawing operation.
@ OP_POINT
Add one more (x,y) point to the contor being drawn.
@ OP_CLOSE
Close the current contour path that was being drawn.
void fillHheaTable(Font *font, pixels_t xMin)
Fill a "hhea" font table.
void fail(const char *reason,...)
Print an error message on stderr, then exit.
void fillTrueType(Font *font, enum LocaFormat *format, uint_fast16_t *maxPoints, uint_fast16_t *maxContours)
Add a TrueType table to a font.
void fillCFF(Font *font, int version, const NameStrings names)
Add a CFF table to a font.
void fillHeadTable(Font *font, enum LocaFormat locaFormat, pixels_t xMin)
Fill a "head" font table.
void initBuffers(size_t count)
Initialize an array of buffer pointers to all zeroes.
void cacheCFFOperand(Buffer *buf, int_fast32_t value)
Cache charstring number encoding in a CFF buffer.
void cacheBuffer(Buffer *restrict bufDest, const Buffer *restrict bufSrc)
Append bytes of a table to a byte buffer.
void buildOutline(Buffer *result, const byte bitmap[], const size_t byteCount, const enum FillSide fillSide)
Build a glyph outline.
void fillCmapTable(Font *font)
Fill a "cmap" font table.
#define FUPEM
Font units per em.
struct Font Font
Data structure to hold information for one font.
#define GLYPH_MAX_WIDTH
Maximum glyph width, in pixels.
FillSide
Fill to the left side (CFF) or right side (TrueType) of a contour.
@ FILL_RIGHT
Draw outline clockwise (TrueType).
@ FILL_LEFT
Draw outline counter-clockwise (CFF, PostScript).
void fillGposTable(Font *font)
Fill a "GPOS" font table.
#define BX(shift, x)
Truncate & shift word.
void sortGlyphs(Font *font)
Sort the glyphs in a font by Unicode code point.
void fillNameTable(Font *font, NameStrings nameStrings)
Fill a "name" font table.
#define PW(x)
Convert glyph byte count to pixel width.
#define U32MAX
Maximum UTF-32 code point value.
#define GLYPH_HEIGHT
Maximum glyph height, in pixels.
LocaFormat
Index to Location ("loca") offset information.
@ LOCA_OFFSET16
Offset to location is a 16-bit Offset16 value.
@ LOCA_OFFSET32
Offset to location is a 32-bit Offset32 value.
struct Buffer Buffer
Generic data structure for a linked list of buffer elements.
void writeU16(uint_fast16_t value, FILE *file)
Write an unsigned 16-bit value to an output file.
void cacheU8(Buffer *buf, uint_fast8_t value)
Append one unsigned byte to the end of a byte array.
#define FU(x)
Convert pixels to font units.
struct Glyph Glyph
Data structure to hold data for one bitmap glyph.
#define DESCENDER
Count of pixels below baseline.
size_t bufferCount
Number of buffers in a Buffer * array.
void cacheBytes(Buffer *restrict buf, const void *restrict src, size_t count)
Append a string of bytes to a buffer.
void writeU32(uint_fast32_t value, FILE *file)
Write an unsigned 32-bit value to an output file.
void prepareOffsets(size_t *sizes)
Prepare 32-bit glyph offsets in a font table.
void fillHmtxTable(Font *font)
Fill an "hmtx" font table.
struct Options Options
Data structure to hold options for OpenType font output.
void printVersion()
Print program version string on stdout.
Buffer * prepareStringIndex(const NameStrings names)
Prepare a font name string index.
struct Table Table
Data structure for an OpenType table.
void fillBlankOutline(Font *font)
Create a dummy blank outline in a font table.
void fillOS2Table(Font *font)
Fill an "OS/2" font table.
int_least8_t pixels_t
This type must be able to represent max(GLYPH_MAX_WIDTH, GLYPH_HEIGHT).
Options parseOptions(char *const argv[const])
Parse command line options.
void freeBuffer(Buffer *buf)
Free the memory previously allocated for a buffer.
void cleanBuffers()
Free all allocated buffer pointers.
#define ASCENDER
Count of pixels above baseline.
#define GLYPH_MAX_BYTE_COUNT
Number of bytes to represent one bitmap glyph as a binary array.
void readGlyphs(Font *font, const char *fileName)
Read glyph definitions from a Unifont .hex format file.
bool readCodePoint(uint_fast32_t *codePoint, const char *fileName, FILE *file)
Read up to 6 hexadecimal digits and a colon from file.
void writeBytes(const byte bytes[], size_t count, FILE *file)
Write an array of bytes to an output file.
void ensureBuffer(Buffer *buf, size_t needed)
Ensure that the buffer has at least the specified minimum size.
Buffer * newBuffer(size_t initialCapacity)
Create a new buffer.
int byTableTag(const void *a, const void *b)
Compare tables by 4-byte unsigned table tag value.
const char * matchToken(const char *operand, const char *key, char delimiter)
Match a command line option with its key for enabling.
#define PRI_CP
Format string to print Unicode code point.
void positionGlyphs(Font *font, const char *fileName, pixels_t *xMin)
Position a glyph within a 16-by-16 pixel bounding box.
void fillBitmap(Font *font)
Fill OpenType bitmap data and location tables.
void fillMaxpTable(Font *font, bool isCFF, uint_fast16_t maxPoints, uint_fast16_t maxContours)
Fill a "maxp" font table.
hex2otf.h - Header file for hex2otf.c
const NamePair defaultNames[]
Allocate array of NameID codes with default values.
Generic data structure for a linked list of buffer elements.
Data structure to hold information for one font.
Data structure to hold data for one bitmap glyph.
uint_least32_t codePoint
undefined for glyph 0
pixels_t lsb
left side bearing (x position of leftmost contour point)
uint_least8_t byteCount
length of bitmap data
byte bitmap[GLYPH_MAX_BYTE_COUNT]
hexadecimal bitmap character array
bool combining
whether this is a combining glyph
Data structure for a font ID number and name character string.
Data structure to hold options for OpenType font output.
Data structure for an OpenType table.
Data structure for data associated with one OpenType table.