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)) 
   97 typedef unsigned char byte;
 
  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;
 
  266 countBufferedBytes (
const Buffer *buf)
 
  268     return buf->next - buf->begin;
 
  278 getBufferHead (
const Buffer *buf)
 
  290 getBufferTail (
const Buffer *buf)
 
  306 getBufferSlot (
Buffer *buf, 
size_t slotSize)
 
  309     void *slot = buf->next;
 
  310     buf->next += slotSize;
 
  325     buf->next = buf->begin;
 
  350 #define defineStore(name, type) \ 
  351 void name (Buffer *buf, type value) \ 
  353     type *slot = getBufferSlot (buf, sizeof value); \ 
  374 cacheU (
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,
 
  598 writeBuffer (
const Buffer *buf, FILE *file)
 
  600     writeBytes (getBufferHead (buf), countBufferedBytes (buf), file);
 
  632     uint_fast32_t glyphCount;
 
  672 static 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);
 
  895 nibbleValue (
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)
 
 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) 
 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; 
 
 2470 matchToken (
const char *operand, 
const char *key, 
char delimiter)
 
 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.
const char * matchToken(const char *operand, const char *key, char delimiter)
Match a command line option with its key for enabling.
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).
#define static_assert(a, b)
If "a" is true, return string "b".
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.
#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 data associated with one OpenType table.
Data structure for an OpenType table.