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;