GNU Unifont 16.0.01
Pan-Unicode font with complete Unicode Plane 0 coverage and partial coverage of higher planes
hex2otf.c
Go to the documentation of this file.
1/**
2 @file hex2otf.c
3
4 @brief hex2otf - Convert GNU Unifont .hex file to OpenType font
5
6 This program reads a Unifont .hex format file and a file containing
7 combining mark offset information, and produces an OpenType font file.
8
9 @copyright Copyright © 2022 何志翔 (He Zhixiang)
10
11 @author 何志翔 (He Zhixiang)
12*/
13
14/*
15 LICENSE:
16
17 This program is free software; you can redistribute it and/or
18 modify it under the terms of the GNU General Public License
19 as published by the Free Software Foundation; either version 2
20 of the License, or (at your option) any later version.
21
22 This program is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
26
27 You should have received a copy of the GNU General Public License
28 along with this program; if not, write to the Free Software
29 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 02110-1301, USA.
31
32 NOTE: It is a violation of the license terms of this software
33 to delete or override license and copyright information contained
34 in the hex2otf.h file if creating a font derived from Unifont glyphs.
35 Fonts derived from Unifont can add names to the copyright notice
36 for creators of new or modified glyphs.
37*/
38
39#include <assert.h>
40#include <ctype.h>
41#include <inttypes.h>
42#include <stdarg.h>
43#include <stdbool.h>
44#include <stddef.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48
49#include "hex2otf.h"
50
51#define VERSION "1.0.1" ///< Program version, for "--version" option.
52
53// This program assumes the execution character set is compatible with ASCII.
54
55#define U16MAX 0xffff ///< Maximum UTF-16 code point value.
56#define U32MAX 0xffffffff ///< Maximum UTF-32 code point value.
57
58#define PRI_CP "U+%.4"PRIXFAST32 ///< Format string to print Unicode code point.
59
60#ifndef static_assert
61#define static_assert(a, b) (assert(a)) ///< If "a" is true, return string "b".
62#endif
63
64// Set or clear a particular bit.
65#define BX(shift, x) ((uintmax_t)(!!(x)) << (shift)) ///< Truncate & shift word.
66#define B0(shift) BX((shift), 0) ///< Clear a given bit in a word.
67#define B1(shift) BX((shift), 1) ///< Set a given bit in a word.
68
69#define GLYPH_MAX_WIDTH 16 ///< Maximum glyph width, in pixels.
70#define GLYPH_HEIGHT 16 ///< Maximum glyph height, in pixels.
71
72/// Number of bytes to represent one bitmap glyph as a binary array.
73#define GLYPH_MAX_BYTE_COUNT (GLYPH_HEIGHT * GLYPH_MAX_WIDTH / 8)
74
75/// Count of pixels below baseline.
76#define DESCENDER 2
77
78/// Count of pixels above baseline.
79#define ASCENDER (GLYPH_HEIGHT - DESCENDER)
80
81/// Font units per em.
82#define FUPEM 64
83
84/// An OpenType font has at most 65536 glyphs.
85#define MAX_GLYPHS 65536
86
87/// Name IDs 0-255 are used for standard names.
88#define MAX_NAME_IDS 256
89
90/// Convert pixels to font units.
91#define FU(x) ((x) * FUPEM / GLYPH_HEIGHT)
92
93/// Convert glyph byte count to pixel width.
94#define PW(x) ((x) / (GLYPH_HEIGHT / 8))
95
96/// Definition of "byte" type as an unsigned char.
97typedef unsigned char byte;
98
99/// This type must be able to represent max(GLYPH_MAX_WIDTH, GLYPH_HEIGHT).
100typedef int_least8_t pixels_t;
101
102/**
103 @brief Print an error message on stderr, then exit.
104
105 This function prints the provided error string and optional
106 following arguments to stderr, and then exits with a status
107 of EXIT_FAILURE.
108
109 @param[in] reason The output string to describe the error.
110 @param[in] ... Optional following arguments to output.
111*/
112void
113fail (const char *reason, ...)
114{
115 fputs ("ERROR: ", stderr);
116 va_list args;
117 va_start (args, reason);
118 vfprintf (stderr, reason, args);
119 va_end (args);
120 putc ('\n', stderr);
121 exit (EXIT_FAILURE);
122}
123
124/**
125 @brief Generic data structure for a linked list of buffer elements.
126
127 A buffer can act as a vector (when filled with 'store*' functions),
128 or a temporary output area (when filled with 'cache*' functions).
129 The 'store*' functions use native endian.
130 The 'cache*' functions use big endian or other formats in OpenType.
131 Beware of memory alignment.
132*/
133typedef struct Buffer
134{
135 size_t capacity; // = 0 iff this buffer is free
136 byte *begin, *next, *end;
138
139Buffer *allBuffers; ///< Initial allocation of empty array of buffer pointers.
140size_t bufferCount; ///< Number of buffers in a Buffer * array.
141size_t nextBufferIndex; ///< Index number to tail element of Buffer * array.
142
143/**
144 @brief Initialize an array of buffer pointers to all zeroes.
145
146 This function initializes the "allBuffers" array of buffer
147 pointers to all zeroes.
148
149 @param[in] count The number of buffer array pointers to allocate.
150*/
151void
152initBuffers (size_t count)
153{
154 assert (count > 0);
155 assert (bufferCount == 0); // uninitialized
156 allBuffers = calloc (count, sizeof *allBuffers);
157 if (!allBuffers)
158 fail ("Failed to initialize buffers.");
159 bufferCount = count;
160 nextBufferIndex = 0;
161}
162
163/**
164 @brief Free all allocated buffer pointers.
165
166 This function frees all buffer pointers previously allocated
167 in the initBuffers function.
168*/
169void
171{
172 for (size_t i = 0; i < bufferCount; i++)
173 if (allBuffers[i].capacity)
174 free (allBuffers[i].begin);
175 free (allBuffers);
176 bufferCount = 0;
177}
178
179/**
180 @brief Create a new buffer.
181
182 This function creates a new buffer array of type Buffer,
183 with an initial size of initialCapacity elements.
184
185 @param[in] initialCapacity The initial number of elements in the buffer.
186*/
187Buffer *
188newBuffer (size_t initialCapacity)
189{
190 assert (initialCapacity > 0);
191 Buffer *buf = NULL;
192 size_t sentinel = nextBufferIndex;
193 do
194 {
196 nextBufferIndex = 0;
197 if (allBuffers[nextBufferIndex].capacity == 0)
198 {
199 buf = &allBuffers[nextBufferIndex++];
200 break;
201 }
202 } while (++nextBufferIndex != sentinel);
203 if (!buf) // no existing buffer available
204 {
205 size_t newSize = sizeof (Buffer) * bufferCount * 2;
206 void *extended = realloc (allBuffers, newSize);
207 if (!extended)
208 fail ("Failed to create new buffers.");
209 allBuffers = extended;
210 memset (allBuffers + bufferCount, 0, sizeof (Buffer) * bufferCount);
211 buf = &allBuffers[bufferCount];
213 bufferCount *= 2;
214 }
215 buf->begin = malloc (initialCapacity);
216 if (!buf->begin)
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;
221 return buf;
222}
223
224/**
225 @brief Ensure that the buffer has at least the specified minimum size.
226
227 This function takes a buffer array of type Buffer and the
228 necessary minimum number of elements as inputs, and attempts
229 to increase the size of the buffer if it must be larger.
230
231 If the buffer is too small and cannot be resized, the program
232 will terminate with an error message and an exit status of
233 EXIT_FAILURE.
234
235 @param[in,out] buf The buffer to check.
236 @param[in] needed The required minimum number of elements in the buffer.
237*/
238void
239ensureBuffer (Buffer *buf, size_t needed)
240{
241 if (buf->end - buf->next >= needed)
242 return;
243 ptrdiff_t occupied = buf->next - buf->begin;
244 size_t required = occupied + needed;
245 if (required < needed) // overflow
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)
250 buf->capacity *= 2;
251 void *extended = realloc (buf->begin, buf->capacity);
252 if (!extended)
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;
257}
258
259/**
260 @brief Count the number of elements in a buffer.
261
262 @param[in] buf The buffer to be examined.
263 @return The number of elements in the buffer.
264*/
265static inline size_t
266countBufferedBytes (const Buffer *buf)
267{
268 return buf->next - buf->begin;
269}
270
271/**
272 @brief Get the start of the buffer array.
273
274 @param[in] buf The buffer to be examined.
275 @return A pointer of type Buffer * to the start of the buffer.
276*/
277static inline void *
278getBufferHead (const Buffer *buf)
279{
280 return buf->begin;
281}
282
283/**
284 @brief Get the end of the buffer array.
285
286 @param[in] buf The buffer to be examined.
287 @return A pointer of type Buffer * to the end of the buffer.
288*/
289static inline void *
290getBufferTail (const Buffer *buf)
291{
292 return buf->next;
293}
294
295/**
296 @brief Add a slot to the end of a buffer.
297
298 This function ensures that the buffer can grow by one slot,
299 and then returns a pointer to the new slot within the buffer.
300
301 @param[in] buf The pointer to an array of type Buffer *.
302 @param[in] slotSize The new slot number.
303 @return A pointer to the new slot within the buffer.
304*/
305static inline void *
306getBufferSlot (Buffer *buf, size_t slotSize)
307{
308 ensureBuffer (buf, slotSize);
309 void *slot = buf->next;
310 buf->next += slotSize;
311 return slot;
312}
313
314/**
315 @brief Reset a buffer pointer to the buffer's beginning.
316
317 This function resets an array of type Buffer * to point
318 its tail to the start of the array.
319
320 @param[in] buf The pointer to an array of type Buffer *.
321*/
322static inline void
323resetBuffer (Buffer *buf)
324{
325 buf->next = buf->begin;
326}
327
328/**
329 @brief Free the memory previously allocated for a buffer.
330
331 This function frees the memory allocated to an array
332 of type Buffer *.
333
334 @param[in] buf The pointer to an array of type Buffer *.
335*/
336void
338{
339 free (buf->begin);
340 buf->capacity = 0;
341}
342
343/**
344 @brief Temporary define to look up an element in an array of given type.
345
346 This defintion is used to create lookup functions to return
347 a given element in unsigned arrays of size 8, 16, and 32 bytes,
348 and in an array of pixels.
349*/
350#define defineStore(name, type) \
351void name (Buffer *buf, type value) \
352{ \
353 type *slot = getBufferSlot (buf, sizeof value); \
354 *slot = value; \
355}
356defineStore (storeU8, uint_least8_t)
357defineStore (storeU16, uint_least16_t)
358defineStore (storeU32, uint_least32_t)
359defineStore (storePixels, pixels_t)
360#undef defineStore
361
362/**
363 @brief Cache bytes in a big-endian format.
364
365 This function adds from 1, 2, 3, or 4 bytes to the end of
366 a byte array in big-endian order. The buffer is updated
367 to account for the newly-added bytes.
368
369 @param[in,out] buf The array of bytes to which to append new bytes.
370 @param[in] value The bytes to add, passed as a 32-bit unsigned word.
371 @param[in] bytes The number of bytes to append to the buffer.
372*/
373void
374cacheU (Buffer *buf, uint_fast32_t value, int bytes)
375{
376 assert (1 <= bytes && bytes <= 4);
377 ensureBuffer (buf, bytes);
378 switch (bytes)
379 {
380 case 4: *buf->next++ = value >> 24 & 0xff; // fall through
381 case 3: *buf->next++ = value >> 16 & 0xff; // fall through
382 case 2: *buf->next++ = value >> 8 & 0xff; // fall through
383 case 1: *buf->next++ = value & 0xff;
384 }
385}
386
387/**
388 @brief Append one unsigned byte to the end of a byte array.
389
390 This function adds one byte to the end of a byte array.
391 The buffer is updated to account for the newly-added byte.
392
393 @param[in,out] buf The array of bytes to which to append a new byte.
394 @param[in] value The 8-bit unsigned value to append to the buf array.
395*/
396void
397cacheU8 (Buffer *buf, uint_fast8_t value)
398{
399 storeU8 (buf, value & 0xff);
400}
401
402/**
403 @brief Append two unsigned bytes to the end of a byte array.
404
405 This function adds two bytes to the end of a byte array.
406 The buffer is updated to account for the newly-added bytes.
407
408 @param[in,out] buf The array of bytes to which to append two new bytes.
409 @param[in] value The 16-bit unsigned value to append to the buf array.
410*/
411void
412cacheU16 (Buffer *buf, uint_fast16_t value)
413{
414 cacheU (buf, value, 2);
415}
416
417/**
418 @brief Append four unsigned bytes to the end of a byte array.
419
420 This function adds four bytes to the end of a byte array.
421 The buffer is updated to account for the newly-added bytes.
422
423 @param[in,out] buf The array of bytes to which to append four new bytes.
424 @param[in] value The 32-bit unsigned value to append to the buf array.
425*/
426void
427cacheU32 (Buffer *buf, uint_fast32_t value)
428{
429 cacheU (buf, value, 4);
430}
431
432/**
433 @brief Cache charstring number encoding in a CFF buffer.
434
435 This function caches two's complement 8-, 16-, and 32-bit
436 words as per Adobe's Type 2 Charstring encoding for operands.
437 These operands are used in Compact Font Format data structures.
438
439 Byte values can have offsets, for which this function
440 compensates, optionally followed by additional bytes:
441
442 Byte Range Offset Bytes Adjusted Range
443 ---------- ------ ----- --------------
444 0 to 11 0 1 0 to 11 (operators)
445 12 0 2 Next byte is 8-bit op code
446 13 to 18 0 1 13 to 18 (operators)
447 19 to 20 0 2+ hintmask and cntrmask operators
448 21 to 27 0 1 21 to 27 (operators)
449 28 0 3 16-bit 2's complement number
450 29 to 31 0 1 29 to 31 (operators)
451 32 to 246 -139 1 -107 to +107
452 247 to 250 +108 2 +108 to +1131
453 251 to 254 -108 2 -108 to -1131
454 255 0 5 16-bit integer and 16-bit fraction
455
456 @param[in,out] buf The buffer to which the operand value is appended.
457 @param[in] value The operand value.
458*/
459void
460cacheCFFOperand (Buffer *buf, int_fast32_t value)
461{
462 if (-107 <= value && value <= 107)
463 cacheU8 (buf, value + 139);
464 else if (108 <= value && value <= 1131)
465 {
466 cacheU8 (buf, (value - 108) / 256 + 247);
467 cacheU8 (buf, (value - 108) % 256);
468 }
469 else if (-32768 <= value && value <= 32767)
470 {
471 cacheU8 (buf, 28);
472 cacheU16 (buf, value);
473 }
474 else if (-2147483647 <= value && value <= 2147483647)
475 {
476 cacheU8 (buf, 29);
477 cacheU32 (buf, value);
478 }
479 else
480 assert (false); // other encodings are not used and omitted
481 static_assert (GLYPH_MAX_WIDTH <= 107, "More encodings are needed.");
482}
483
484/**
485 @brief Append 1 to 4 bytes of zeroes to a buffer, for padding.
486
487 @param[in,out] buf The buffer to which the operand value is appended.
488 @param[in] count The number of bytes containing zeroes to append.
489*/
490void
491cacheZeros (Buffer *buf, size_t count)
492{
493 ensureBuffer (buf, count);
494 memset (buf->next, 0, count);
495 buf->next += count;
496}
497
498/**
499 @brief Append a string of bytes to a buffer.
500
501 This function appends an array of 1 to 4 bytes to the end of
502 a buffer.
503
504 @param[in,out] buf The buffer to which the bytes are appended.
505 @param[in] src The array of bytes to append to the buffer.
506 @param[in] count The number of bytes containing zeroes to append.
507*/
508void
509cacheBytes (Buffer *restrict buf, const void *restrict src, size_t count)
510{
511 ensureBuffer (buf, count);
512 memcpy (buf->next, src, count);
513 buf->next += count;
514}
515
516/**
517 @brief Append bytes of a table to a byte buffer.
518
519 @param[in,out] bufDest The buffer to which the new bytes are appended.
520 @param[in] bufSrc The bytes to append to the buffer array.
521*/
522void
523cacheBuffer (Buffer *restrict bufDest, const Buffer *restrict bufSrc)
524{
525 size_t length = countBufferedBytes (bufSrc);
526 ensureBuffer (bufDest, length);
527 memcpy (bufDest->next, bufSrc->begin, length);
528 bufDest->next += length;
529}
530
531/**
532 @brief Write an array of bytes to an output file.
533
534 @param[in] bytes An array of unsigned bytes to write.
535 @param[in] file The file pointer for writing, of type FILE *.
536*/
537void
538writeBytes (const byte bytes[], size_t count, FILE *file)
539{
540 if (fwrite (bytes, count, 1, file) != 1 && count != 0)
541 fail ("Failed to write %zu bytes to output file.", count);
542}
543
544/**
545 @brief Write an unsigned 16-bit value to an output file.
546
547 This function writes a 16-bit unsigned value in big-endian order
548 to an output file specified with a file pointer.
549
550 @param[in] value The 16-bit value to write.
551 @param[in] file The file pointer for writing, of type FILE *.
552*/
553void
554writeU16 (uint_fast16_t value, FILE *file)
555{
556 byte bytes[] =
557 {
558 (value >> 8) & 0xff,
559 (value ) & 0xff,
560 };
561 writeBytes (bytes, sizeof bytes, file);
562}
563
564/**
565 @brief Write an unsigned 32-bit value to an output file.
566
567 This function writes a 32-bit unsigned value in big-endian order
568 to an output file specified with a file pointer.
569
570 @param[in] value The 32-bit value to write.
571 @param[in] file The file pointer for writing, of type FILE *.
572*/
573void
574writeU32 (uint_fast32_t value, FILE *file)
575{
576 byte bytes[] =
577 {
578 (value >> 24) & 0xff,
579 (value >> 16) & 0xff,
580 (value >> 8) & 0xff,
581 (value ) & 0xff,
582 };
583 writeBytes (bytes, sizeof bytes, file);
584}
585
586/**
587 @brief Write an entire buffer array of bytes to an output file.
588
589 This function determines the size of a buffer of bytes and
590 writes that number of bytes to an output file specified with
591 a file pointer. The number of bytes is determined from the
592 length information stored as part of the Buffer * data structure.
593
594 @param[in] buf An array containing unsigned bytes to write.
595 @param[in] file The file pointer for writing, of type FILE *.
596*/
597static inline void
598writeBuffer (const Buffer *buf, FILE *file)
599{
600 writeBytes (getBufferHead (buf), countBufferedBytes (buf), file);
601}
602
603/// Array of OpenType names indexed directly by Name IDs.
604typedef const char *NameStrings[MAX_NAME_IDS];
605
606/**
607 @brief Data structure to hold data for one bitmap glyph.
608
609 This data structure holds data to represent one Unifont bitmap
610 glyph: Unicode code point, number of bytes in its bitmap array,
611 whether or not it is a combining character, and an offset from
612 the glyph origin to the start of the bitmap.
613*/
614typedef struct Glyph
615{
616 uint_least32_t codePoint; ///< undefined for glyph 0
617 byte bitmap[GLYPH_MAX_BYTE_COUNT]; ///< hexadecimal bitmap character array
618 uint_least8_t byteCount; ///< length of bitmap data
619 bool combining; ///< whether this is a combining glyph
620 pixels_t pos; ///< number of pixels the glyph should be moved to the right
621 ///< (negative number means moving to the left)
622 pixels_t lsb; ///< left side bearing (x position of leftmost contour point)
624
625/**
626 @brief Data structure to hold information for one font.
627*/
628typedef struct Font
629{
630 Buffer *tables;
631 Buffer *glyphs;
632 uint_fast32_t glyphCount;
633 pixels_t maxWidth;
635
636/**
637 @brief Data structure for an OpenType table.
638
639 This data structure contains a table tag and a pointer to the
640 start of the buffer that holds data for this OpenType table.
641
642 For information on the OpenType tables and their structure, see
643 https://docs.microsoft.com/en-us/typography/opentype/spec/otff#font-tables.
644*/
645typedef struct Table
646{
647 uint_fast32_t tag;
648 Buffer *content;
650
651/**
652 @brief Index to Location ("loca") offset information.
653
654 This enumerated type encodes the type of offset to locations
655 in a table. It denotes Offset16 (16-bit) and Offset32 (32-bit)
656 offset types.
657*/
659 LOCA_OFFSET16 = 0, ///< Offset to location is a 16-bit Offset16 value
660 LOCA_OFFSET32 = 1 ///< Offset to location is a 32-bit Offset32 value
662
663/**
664 @brief Convert a 4-byte array to the machine's native 32-bit endian order.
665
666 This function takes an array of 4 bytes in big-endian order and
667 converts it to a 32-bit word in the endian order of the native machine.
668
669 @param[in] tag The array of 4 bytes in big-endian order.
670 @return The 32-bit unsigned word in a machine's native endian order.
671*/
672static inline uint_fast32_t tagAsU32 (const char tag[static 4])
673{
674 uint_fast32_t r = 0;
675 r |= (tag[0] & 0xff) << 24;
676 r |= (tag[1] & 0xff) << 16;
677 r |= (tag[2] & 0xff) << 8;
678 r |= (tag[3] & 0xff);
679 return r;
680}
681
682/**
683 @brief Add a TrueType or OpenType table to the font.
684
685 This function adds a TrueType or OpenType table to a font.
686 The 4-byte table tag is passed as an unsigned 32-bit integer
687 in big-endian format.
688
689 @param[in,out] font The font to which a font table will be added.
690 @param[in] tag The 4-byte table name.
691 @param[in] content The table bytes to add, of type Buffer *.
692*/
693void
694addTable (Font *font, const char tag[static 4], Buffer *content)
695{
696 Table *table = getBufferSlot (font->tables, sizeof (Table));
697 table->tag = tagAsU32 (tag);
698 table->content = content;
699}
700
701/**
702 @brief Sort tables according to OpenType recommendations.
703
704 The various tables in a font are sorted in an order recommended
705 for TrueType font files.
706
707 @param[in,out] font The font in which to sort tables.
708 @param[in] isCFF True iff Compact Font Format (CFF) is being used.
709*/
710void
711organizeTables (Font *font, bool isCFF)
712{
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++)
722 {
723 uint_fast32_t tag = tagAsU32 (*p);
724 for (Table *t = unordered; t < tablesEnd; t++)
725 {
726 if (t->tag != tag)
727 continue;
728 if (t != unordered)
729 {
730 Table temp = *unordered;
731 *unordered = *t;
732 *t = temp;
733 }
734 unordered++;
735 break;
736 }
737 }
738}
739
740/**
741 @brief Data structure for data associated with one OpenType table.
742
743 This data structure contains an OpenType table's tag, start within
744 an OpenType font file, length in bytes, and checksum at the end of
745 the table.
746*/
748{
749 uint_least32_t tag, offset, length, checksum;
750};
751
752/**
753 @brief Compare tables by 4-byte unsigned table tag value.
754
755 This function takes two pointers to a TableRecord data structure
756 and extracts the four-byte tag structure element for each. The
757 two 32-bit numbers are then compared. If the first tag is greater
758 than the first, then gt = 1 and lt = 0, and so 1 - 0 = 1 is
759 returned. If the first is less than the second, then gt = 0 and
760 lt = 1, and so 0 - 1 = -1 is returned.
761
762 @param[in] a Pointer to the first TableRecord structure.
763 @param[in] b Pointer to the second TableRecord structure.
764 @return 1 if the tag in "a" is greater, -1 if less, 0 if equal.
765*/
766int
767byTableTag (const void *a, const void *b)
768{
769 const struct TableRecord *const ra = a, *const rb = b;
770 int gt = ra->tag > rb->tag;
771 int lt = ra->tag < rb->tag;
772 return gt - lt;
773}
774
775/**
776 @brief Write OpenType font to output file.
777
778 This function writes the constructed OpenType font to the
779 output file named "filename".
780
781 @param[in] font Pointer to the font, of type Font *.
782 @param[in] isCFF Boolean indicating whether the font has CFF data.
783 @param[in] filename The name of the font file to create.
784*/
785void
786writeFont (Font *font, bool isCFF, const char *fileName)
787{
788 FILE *file = fopen (fileName, "wb");
789 if (!file)
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;
797 Buffer *tableRecords =
798 newBuffer (sizeof (struct TableRecord) * tableCount);
799 for (size_t i = 0; i < tableCount; i++)
800 {
801 struct TableRecord *record =
802 getBufferSlot (tableRecords, sizeof *record);
803 record->tag = tables[i].tag;
804 size_t length = countBufferedBytes (tables[i].content);
805 #if SIZE_MAX > U32MAX
806 if (offset > U32MAX)
807 fail ("Table offset exceeded 4 GiB.");
808 if (length > U32MAX)
809 fail ("Table size exceeded 4 GiB.");
810 #endif
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);
815
816 /// Add a byte shifted by 24, 16, 8, or 0 bits.
817 #define addByte(shift) \
818 if (p == end) \
819 break; \
820 record->checksum += (uint_fast32_t)*p++ << (shift);
821
822 for (;;)
823 {
824 addByte (24)
825 addByte (16)
826 addByte (8)
827 addByte (0)
828 }
829 #undef addByte
830 cacheZeros (tables[i].content, (~length + 1U) & 3U);
831 record->offset = offset;
832 offset += countBufferedBytes (tables[i].content);
833 totalChecksum += record->checksum;
834 }
835 struct TableRecord *records = getBufferHead (tableRecords);
836 qsort (records, tableCount, sizeof *records, byTableTag);
837 // Offset Table
838 uint_fast32_t sfntVersion = isCFF ? 0x4f54544f : 0x00010000;
839 writeU32 (sfntVersion, file); // sfntVersion
840 totalChecksum += sfntVersion;
841 uint_fast16_t entrySelector = 0;
842 for (size_t k = tableCount; k != 1; k >>= 1)
843 entrySelector++;
844 uint_fast16_t searchRange = 1 << (entrySelector + 4);
845 uint_fast16_t rangeShift = (tableCount - (1 << entrySelector)) << 4;
846 writeU16 (tableCount, file); // numTables
847 writeU16 (searchRange, file); // searchRange
848 writeU16 (entrySelector, file); // entrySelector
849 writeU16 (rangeShift, file); // rangeShift
850 totalChecksum += (uint_fast32_t)tableCount << 16;
851 totalChecksum += searchRange;
852 totalChecksum += (uint_fast32_t)entrySelector << 16;
853 totalChecksum += rangeShift;
854 // Table Records (always sorted by table tags)
855 for (size_t i = 0; i < tableCount; i++)
856 {
857 // Table Record
858 writeU32 (records[i].tag, file); // tableTag
859 writeU32 (records[i].checksum, file); // checkSum
860 writeU32 (records[i].offset, file); // offset
861 writeU32 (records[i].length, file); // length
862 totalChecksum += records[i].tag;
863 totalChecksum += records[i].checksum;
864 totalChecksum += records[i].offset;
865 totalChecksum += records[i].length;
866 }
867 freeBuffer (tableRecords);
868 for (const Table *table = tables; table < tablesEnd; table++)
869 {
870 if (table->tag == 0x68656164) // 'head' table
871 {
872 byte *begin = getBufferHead (table->content);
873 byte *end = getBufferTail (table->content);
874 writeBytes (begin, 8, file);
875 writeU32 (0xb1b0afbaU - totalChecksum, file); // checksumAdjustment
876 writeBytes (begin + 12, end - (begin + 12), file);
877 continue;
878 }
879 writeBuffer (table->content, file);
880 }
881 fclose (file);
882}
883
884/**
885 @brief Convert a hexadecimal digit character to a 4-bit number.
886
887 This function takes a character that contains one hexadecimal digit
888 and returns the 4-bit value (as an unsigned 8-bit value) corresponding
889 to the hexadecimal digit.
890
891 @param[in] nibble The character containing one hexadecimal digit.
892 @return The hexadecimal digit value, 0 through 15, inclusive.
893*/
894static inline byte
895nibbleValue (char nibble)
896{
897 if (isdigit (nibble))
898 return nibble - '0';
899 nibble = toupper (nibble);
900 return nibble - 'A' + 10;
901}
902
903/**
904 @brief Read up to 6 hexadecimal digits and a colon from file.
905
906 This function reads up to 6 hexadecimal digits followed by
907 a colon from a file.
908
909 If the end of the file is reached, the function returns true.
910 The file name is provided to include in an error message if
911 the end of file was reached unexpectedly.
912
913 @param[out] codePoint The Unicode code point.
914 @param[in] fileName The name of the input file.
915 @param[in] file Pointer to the input file stream.
916 @return true if at end of file, false otherwise.
917*/
918bool
919readCodePoint (uint_fast32_t *codePoint, const char *fileName, FILE *file)
920{
921 *codePoint = 0;
922 uint_fast8_t digitCount = 0;
923 for (;;)
924 {
925 int c = getc (file);
926 if (isxdigit (c) && ++digitCount <= 6)
927 {
928 *codePoint = (*codePoint << 4) | nibbleValue (c);
929 continue;
930 }
931 if (c == ':' && digitCount > 0)
932 return false;
933 if (c == EOF)
934 {
935 if (digitCount == 0)
936 return true;
937 if (feof (file))
938 fail ("%s: Unexpected end of file.", fileName);
939 else
940 fail ("%s: Read error.", fileName);
941 }
942 fail ("%s: Unexpected character: %#.2x.", fileName, (unsigned)c);
943 }
944}
945
946/**
947 @brief Read glyph definitions from a Unifont .hex format file.
948
949 This function reads in the glyph bitmaps contained in a Unifont
950 .hex format file. These input files contain one glyph bitmap
951 per line. Each line is of the form
952
953 <hexadecimal code point> ':' <hexadecimal bitmap sequence>
954
955 The code point field typically consists of 4 hexadecimal digits
956 for a code point in Unicode Plane 0, and 6 hexadecimal digits for
957 code points above Plane 0. The hexadecimal bitmap sequence is
958 32 hexadecimal digits long for a glyph that is 8 pixels wide by
959 16 pixels high, and 64 hexadecimal digits long for a glyph that
960 is 16 pixels wide by 16 pixels high.
961
962 @param[in,out] font The font data structure to update with new glyphs.
963 @param[in] fileName The name of the Unifont .hex format input file.
964*/
965void
966readGlyphs (Font *font, const char *fileName)
967{
968 FILE *file = fopen (fileName, "r");
969 if (!file)
970 fail ("Failed to open file '%s'.", fileName);
971 uint_fast32_t glyphCount = 1; // for glyph 0
972 uint_fast8_t maxByteCount = 0;
973 { // Hard code the .notdef glyph.
974 const byte bitmap[] = "\0\0\0~fZZzvv~vv~\0\0"; // same as U+FFFD
975 const size_t byteCount = sizeof bitmap - 1;
976 assert (byteCount <= GLYPH_MAX_BYTE_COUNT);
977 assert (byteCount % GLYPH_HEIGHT == 0);
978 Glyph *notdef = getBufferSlot (font->glyphs, sizeof (Glyph));
979 memcpy (notdef->bitmap, bitmap, byteCount);
980 notdef->byteCount = maxByteCount = byteCount;
981 notdef->combining = false;
982 notdef->pos = 0;
983 notdef->lsb = 0;
984 }
985 for (;;)
986 {
987 uint_fast32_t codePoint;
988 if (readCodePoint (&codePoint, fileName, file))
989 break;
990 if (++glyphCount > MAX_GLYPHS)
991 fail ("OpenType does not support more than %lu glyphs.",
992 MAX_GLYPHS);
993 Glyph *glyph = getBufferSlot (font->glyphs, sizeof (Glyph));
994 glyph->codePoint = codePoint;
995 glyph->byteCount = 0;
996 glyph->combining = false;
997 glyph->pos = 0;
998 glyph->lsb = 0;
999 for (byte *p = glyph->bitmap;; p++)
1000 {
1001 int h, l;
1002 if (isxdigit (h = getc (file)) && isxdigit (l = getc (file)))
1003 {
1004 if (++glyph->byteCount > GLYPH_MAX_BYTE_COUNT)
1005 fail ("Hex stream of "PRI_CP" is too long.", codePoint);
1006 *p = nibbleValue (h) << 4 | nibbleValue (l);
1007 }
1008 else if (h == '\n' || (h == EOF && feof (file)))
1009 break;
1010 else if (ferror (file))
1011 fail ("%s: Read error.", fileName);
1012 else
1013 fail ("Hex stream of "PRI_CP" is invalid.", codePoint);
1014 }
1015 if (glyph->byteCount % GLYPH_HEIGHT != 0)
1016 fail ("Hex length of "PRI_CP" is indivisible by glyph height %d.",
1017 codePoint, GLYPH_HEIGHT);
1018 if (glyph->byteCount > maxByteCount)
1019 maxByteCount = glyph->byteCount;
1020 }
1021 if (glyphCount == 1)
1022 fail ("No glyph is specified.");
1023 font->glyphCount = glyphCount;
1024 font->maxWidth = PW (maxByteCount);
1025 fclose (file);
1026}
1027
1028/**
1029 @brief Compare two Unicode code points to determine which is greater.
1030
1031 This function compares the Unicode code points contained within
1032 two Glyph data structures. The function returns 1 if the first
1033 code point is greater, and -1 if the second is greater.
1034
1035 @param[in] a A Glyph data structure containing the first code point.
1036 @param[in] b A Glyph data structure containing the second code point.
1037 @return 1 if the code point a is greater, -1 if less, 0 if equal.
1038*/
1039int
1040byCodePoint (const void *a, const void *b)
1041{
1042 const Glyph *const ga = a, *const gb = b;
1043 int gt = ga->codePoint > gb->codePoint;
1044 int lt = ga->codePoint < gb->codePoint;
1045 return gt - lt;
1046}
1047
1048/**
1049 @brief Position a glyph within a 16-by-16 pixel bounding box.
1050
1051 Position a glyph within the 16-by-16 pixel drawing area and
1052 note whether or not the glyph is a combining character.
1053
1054 N.B.: Glyphs must be sorted by code point before calling this function.
1055
1056 @param[in,out] font Font data structure pointer to store glyphs.
1057 @param[in] fileName Name of glyph file to read.
1058 @param[in] xMin Minimum x-axis value (for left side bearing).
1059*/
1060void
1061positionGlyphs (Font *font, const char *fileName, pixels_t *xMin)
1062{
1063 *xMin = 0;
1064 FILE *file = fopen (fileName, "r");
1065 if (!file)
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]; // predict and avoid search
1070 for (;;)
1071 {
1072 uint_fast32_t codePoint;
1073 if (readCodePoint (&codePoint, fileName, file))
1074 break;
1075 Glyph *glyph = nextGlyph;
1076 if (glyph == endGlyph || glyph->codePoint != codePoint)
1077 {
1078 // Prediction failed. Search.
1079 const Glyph key = { .codePoint = codePoint };
1080 glyph = bsearch (&key, glyphs + 1, font->glyphCount - 1,
1081 sizeof key, byCodePoint);
1082 if (!glyph)
1083 fail ("Glyph "PRI_CP" is positioned but not defined.",
1084 codePoint);
1085 }
1086 nextGlyph = glyph + 1;
1087 char s[8];
1088 if (!fgets (s, sizeof s, file))
1089 fail ("%s: Read error.", fileName);
1090 char *end;
1091 const long value = strtol (s, &end, 10);
1092 if (*end != '\n' && *end != '\0')
1093 fail ("Position of glyph "PRI_CP" is invalid.", codePoint);
1094 // Currently no glyph is moved to the right,
1095 // so positive position is considered out of range.
1096 // If this limit is to be lifted,
1097 // 'xMax' of bounding box in 'head' table shall also be updated.
1098 if (value < -GLYPH_MAX_WIDTH || value > 0)
1099 fail ("Position of glyph "PRI_CP" is out of range.", codePoint);
1100 glyph->combining = true;
1101 glyph->pos = value;
1102 glyph->lsb = value; // updated during outline generation
1103 if (value < *xMin)
1104 *xMin = value;
1105 }
1106 fclose (file);
1107}
1108
1109/**
1110 @brief Sort the glyphs in a font by Unicode code point.
1111
1112 This function reads in an array of glyphs and sorts them
1113 by Unicode code point. If a duplicate code point is encountered,
1114 that will result in a fatal error with an error message to stderr.
1115
1116 @param[in,out] font Pointer to a Font structure with glyphs to sort.
1117*/
1118void
1120{
1121 Glyph *glyphs = getBufferHead (font->glyphs);
1122 const Glyph *const glyphsEnd = getBufferTail (font->glyphs);
1123 glyphs++; // glyph 0 does not need sorting
1124 qsort (glyphs, glyphsEnd - glyphs, sizeof *glyphs, byCodePoint);
1125 for (const Glyph *glyph = glyphs; glyph < glyphsEnd - 1; glyph++)
1126 {
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);
1130 }
1131}
1132
1133/**
1134 @brief Specify the current contour drawing operation.
1135*/
1137 OP_CLOSE, ///< Close the current contour path that was being drawn.
1138 OP_POINT ///< Add one more (x,y) point to the contor being drawn.
1140
1141/**
1142 @brief Fill to the left side (CFF) or right side (TrueType) of a contour.
1143*/
1145 FILL_LEFT, ///< Draw outline counter-clockwise (CFF, PostScript).
1146 FILL_RIGHT ///< Draw outline clockwise (TrueType).
1148
1149/**
1150 @brief Build a glyph outline.
1151
1152 This function builds a glyph outline from a Unifont glyph bitmap.
1153
1154 @param[out] result The resulting glyph outline.
1155 @param[in] bitmap A bitmap array.
1156 @param[in] byteCount the number of bytes in the input bitmap array.
1157 @param[in] fillSide Enumerated indicator to fill left or right side.
1158*/
1159void
1160buildOutline (Buffer *result, const byte bitmap[], const size_t byteCount,
1161 const enum FillSide fillSide)
1162{
1163 enum Direction {RIGHT, LEFT, DOWN, UP}; // order is significant
1164
1165 // respective coordinate deltas
1166 const pixels_t dx[] = {1, -1, 0, 0}, dy[] = {0, 0, -1, 1};
1167
1168 assert (byteCount % GLYPH_HEIGHT == 0);
1169 const uint_fast8_t bytesPerRow = byteCount / GLYPH_HEIGHT;
1170 const pixels_t glyphWidth = bytesPerRow * 8;
1171 assert (glyphWidth <= GLYPH_MAX_WIDTH);
1172
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;
1177 #else
1178 #error GLYPH_MAX_WIDTH is too large.
1179 #endif
1180
1181 row_t pixels[GLYPH_HEIGHT + 2] = {0};
1182 for (pixels_t row = GLYPH_HEIGHT; row > 0; row--)
1183 for (pixels_t b = 0; b < bytesPerRow; b++)
1184 pixels[row] = pixels[row] << 8 | *bitmap++;
1185 typedef row_t graph_t[GLYPH_HEIGHT + 1];
1186 graph_t vectors[4];
1187 const row_t *lower = pixels, *upper = pixels + 1;
1188 for (pixels_t row = 0; row <= GLYPH_HEIGHT; row++)
1189 {
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 ));
1195 lower++;
1196 upper++;
1197 }
1198 graph_t selection = {0};
1199 const row_t x0 = (row_t)1 << glyphWidth;
1200
1201 /// Get the value of a given bit that is in a given row.
1202 #define getRowBit(rows, x, y) ((rows)[(y)] & x0 >> (x))
1203
1204 /// Invert the value of a given bit that is in a given row.
1205 #define flipRowBit(rows, x, y) ((rows)[(y)] ^= x0 >> (x))
1206
1207 for (pixels_t y = GLYPH_HEIGHT; y >= 0; y--)
1208 {
1209 for (pixels_t x = 0; x <= glyphWidth; x++)
1210 {
1211 assert (!getRowBit (vectors[LEFT], x, y));
1212 assert (!getRowBit (vectors[UP], x, y));
1213 enum Direction initial;
1214
1215 if (getRowBit (vectors[RIGHT], x, y))
1216 initial = RIGHT;
1217 else if (getRowBit (vectors[DOWN], x, y))
1218 initial = DOWN;
1219 else
1220 continue;
1221
1222 static_assert ((GLYPH_MAX_WIDTH + 1) * (GLYPH_HEIGHT + 1) * 2 <=
1223 U16MAX, "potential overflow");
1224
1225 uint_fast16_t lastPointCount = 0;
1226 for (bool converged = false;;)
1227 {
1228 uint_fast16_t pointCount = 0;
1229 enum Direction heading = initial;
1230 for (pixels_t tx = x, ty = y;;)
1231 {
1232 if (converged)
1233 {
1234 storePixels (result, OP_POINT);
1235 storePixels (result, tx);
1236 storePixels (result, ty);
1237 }
1238 do
1239 {
1240 if (converged)
1241 flipRowBit (vectors[heading], tx, ty);
1242 tx += dx[heading];
1243 ty += dy[heading];
1244 } while (getRowBit (vectors[heading], tx, ty));
1245 if (tx == x && ty == y)
1246 break;
1247 static_assert ((UP ^ DOWN) == 1 && (LEFT ^ RIGHT) == 1,
1248 "wrong enums");
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);
1254 pointCount++;
1255 }
1256 if (converged)
1257 break;
1258 converged = pointCount == lastPointCount;
1259 lastPointCount = pointCount;
1260 }
1261
1262 storePixels (result, OP_CLOSE);
1263 }
1264 }
1265 #undef getRowBit
1266 #undef flipRowBit
1267}
1268
1269/**
1270 @brief Prepare 32-bit glyph offsets in a font table.
1271
1272 @param[in] sizes Array of glyph sizes, for offset calculations.
1273*/
1274void
1275prepareOffsets (size_t *sizes)
1276{
1277 size_t *p = sizes;
1278 for (size_t *i = sizes + 1; *i; i++)
1279 *i += *p++;
1280 if (*p > 2147483647U) // offset not representable
1281 fail ("CFF table is too large.");
1282}
1283
1284/**
1285 @brief Prepare a font name string index.
1286
1287 @param[in] names List of name strings.
1288 @return Pointer to a Buffer struct containing the string names.
1289*/
1290Buffer *
1292{
1293 Buffer *buf = newBuffer (256);
1294 assert (names[6]);
1295 const char *strings[] = {"Adobe", "Identity", names[6]};
1296 /// Get the number of elements in array char *strings[].
1297 #define stringCount (sizeof strings / sizeof *strings)
1298 static_assert (stringCount <= U16MAX, "too many strings");
1299 size_t offset = 1;
1300 size_t lengths[stringCount];
1301 for (size_t i = 0; i < stringCount; i++)
1302 {
1303 assert (strings[i]);
1304 lengths[i] = strlen (strings[i]);
1305 offset += lengths[i];
1306 }
1307 int offsetSize = 1 + (offset > 0xff)
1308 + (offset > 0xffff)
1309 + (offset > 0xffffff);
1310 cacheU16 (buf, stringCount); // count
1311 cacheU8 (buf, offsetSize); // offSize
1312 cacheU (buf, offset = 1, offsetSize); // offset[0]
1313 for (size_t i = 0; i < stringCount; i++)
1314 cacheU (buf, offset += lengths[i], offsetSize); // offset[i + 1]
1315 for (size_t i = 0; i < stringCount; i++)
1316 cacheBytes (buf, strings[i], lengths[i]);
1317 #undef stringCount
1318 return buf;
1319}
1320
1321/**
1322 @brief Add a CFF table to a font.
1323
1324 @param[in,out] font Pointer to a Font struct to contain the CFF table.
1325 @param[in] version Version of CFF table, with value 1 or 2.
1326 @param[in] names List of NameStrings.
1327*/
1328void
1329fillCFF (Font *font, int version, const NameStrings names)
1330{
1331 // HACK: For convenience, CFF data structures are hard coded.
1332 assert (0 < version && version <= 2);
1333 Buffer *cff = newBuffer (65536);
1334 addTable (font, version == 1 ? "CFF " : "CFF2", cff);
1335
1336 /// Use fixed width integer for variables to simplify offset calculation.
1337 #define cacheCFF32(buf, x) (cacheU8 ((buf), 29), cacheU32 ((buf), (x)))
1338
1339 // In Unifont, 16px glyphs are more common. This is used by CFF1 only.
1340 const pixels_t defaultWidth = 16, nominalWidth = 8;
1341 if (version == 1)
1342 {
1343 Buffer *strings = prepareStringIndex (names);
1344 size_t stringsSize = countBufferedBytes (strings);
1345 const char *cffName = names[6];
1346 assert (cffName);
1347 size_t nameLength = strlen (cffName);
1348 size_t namesSize = nameLength + 5;
1349 // These sizes must be updated together with the data below.
1350 size_t offsets[] = {4, namesSize, 45, stringsSize, 2, 5, 8, 32, 4, 0};
1351 prepareOffsets (offsets);
1352 { // Header
1353 cacheU8 (cff, 1); // major
1354 cacheU8 (cff, 0); // minor
1355 cacheU8 (cff, 4); // hdrSize
1356 cacheU8 (cff, 1); // offSize
1357 }
1358 assert (countBufferedBytes (cff) == offsets[0]);
1359 { // Name INDEX (should not be used by OpenType readers)
1360 cacheU16 (cff, 1); // count
1361 cacheU8 (cff, 1); // offSize
1362 cacheU8 (cff, 1); // offset[0]
1363 if (nameLength + 1 > 255) // must be too long; spec limit is 63
1364 fail ("PostScript name is too long.");
1365 cacheU8 (cff, nameLength + 1); // offset[1]
1366 cacheBytes (cff, cffName, nameLength);
1367 }
1368 assert (countBufferedBytes (cff) == offsets[1]);
1369 { // Top DICT INDEX
1370 cacheU16 (cff, 1); // count
1371 cacheU8 (cff, 1); // offSize
1372 cacheU8 (cff, 1); // offset[0]
1373 cacheU8 (cff, 41); // offset[1]
1374 cacheCFFOperand (cff, 391); // "Adobe"
1375 cacheCFFOperand (cff, 392); // "Identity"
1376 cacheCFFOperand (cff, 0);
1377 cacheBytes (cff, (byte[]){12, 30}, 2); // ROS
1378 cacheCFF32 (cff, font->glyphCount);
1379 cacheBytes (cff, (byte[]){12, 34}, 2); // CIDCount
1380 cacheCFF32 (cff, offsets[6]);
1381 cacheBytes (cff, (byte[]){12, 36}, 2); // FDArray
1382 cacheCFF32 (cff, offsets[5]);
1383 cacheBytes (cff, (byte[]){12, 37}, 2); // FDSelect
1384 cacheCFF32 (cff, offsets[4]);
1385 cacheU8 (cff, 15); // charset
1386 cacheCFF32 (cff, offsets[8]);
1387 cacheU8 (cff, 17); // CharStrings
1388 }
1389 assert (countBufferedBytes (cff) == offsets[2]);
1390 { // String INDEX
1391 cacheBuffer (cff, strings);
1392 freeBuffer (strings);
1393 }
1394 assert (countBufferedBytes (cff) == offsets[3]);
1395 cacheU16 (cff, 0); // Global Subr INDEX
1396 assert (countBufferedBytes (cff) == offsets[4]);
1397 { // Charsets
1398 cacheU8 (cff, 2); // format
1399 { // Range2[0]
1400 cacheU16 (cff, 1); // first
1401 cacheU16 (cff, font->glyphCount - 2); // nLeft
1402 }
1403 }
1404 assert (countBufferedBytes (cff) == offsets[5]);
1405 { // FDSelect
1406 cacheU8 (cff, 3); // format
1407 cacheU16 (cff, 1); // nRanges
1408 cacheU16 (cff, 0); // first
1409 cacheU8 (cff, 0); // fd
1410 cacheU16 (cff, font->glyphCount); // sentinel
1411 }
1412 assert (countBufferedBytes (cff) == offsets[6]);
1413 { // FDArray
1414 cacheU16 (cff, 1); // count
1415 cacheU8 (cff, 1); // offSize
1416 cacheU8 (cff, 1); // offset[0]
1417 cacheU8 (cff, 28); // offset[1]
1418 cacheCFFOperand (cff, 393);
1419 cacheBytes (cff, (byte[]){12, 38}, 2); // FontName
1420 // Windows requires FontMatrix in Font DICT.
1421 const byte unit[] = {0x1e,0x15,0x62,0x5c,0x6f}; // 1/64 (0.015625)
1422 cacheBytes (cff, unit, sizeof unit);
1423 cacheCFFOperand (cff, 0);
1424 cacheCFFOperand (cff, 0);
1425 cacheBytes (cff, unit, sizeof unit);
1426 cacheCFFOperand (cff, 0);
1427 cacheCFFOperand (cff, 0);
1428 cacheBytes (cff, (byte[]){12, 7}, 2); // FontMatrix
1429 cacheCFFOperand (cff, offsets[8] - offsets[7]); // size
1430 cacheCFF32 (cff, offsets[7]); // offset
1431 cacheU8 (cff, 18); // Private
1432 }
1433 assert (countBufferedBytes (cff) == offsets[7]);
1434 { // Private
1435 cacheCFFOperand (cff, FU (defaultWidth));
1436 cacheU8 (cff, 20); // defaultWidthX
1437 cacheCFFOperand (cff, FU (nominalWidth));
1438 cacheU8 (cff, 21); // nominalWidthX
1439 }
1440 assert (countBufferedBytes (cff) == offsets[8]);
1441 }
1442 else
1443 {
1444 assert (version == 2);
1445 // These sizes must be updated together with the data below.
1446 size_t offsets[] = {5, 21, 4, 10, 0};
1447 prepareOffsets (offsets);
1448 { // Header
1449 cacheU8 (cff, 2); // majorVersion
1450 cacheU8 (cff, 0); // minorVersion
1451 cacheU8 (cff, 5); // headerSize
1452 cacheU16 (cff, offsets[1] - offsets[0]); // topDictLength
1453 }
1454 assert (countBufferedBytes (cff) == offsets[0]);
1455 { // Top DICT
1456 const byte unit[] = {0x1e,0x15,0x62,0x5c,0x6f}; // 1/64 (0.015625)
1457 cacheBytes (cff, unit, sizeof unit);
1458 cacheCFFOperand (cff, 0);
1459 cacheCFFOperand (cff, 0);
1460 cacheBytes (cff, unit, sizeof unit);
1461 cacheCFFOperand (cff, 0);
1462 cacheCFFOperand (cff, 0);
1463 cacheBytes (cff, (byte[]){12, 7}, 2); // FontMatrix
1464 cacheCFFOperand (cff, offsets[2]);
1465 cacheBytes (cff, (byte[]){12, 36}, 2); // FDArray
1466 cacheCFFOperand (cff, offsets[3]);
1467 cacheU8 (cff, 17); // CharStrings
1468 }
1469 assert (countBufferedBytes (cff) == offsets[1]);
1470 cacheU32 (cff, 0); // Global Subr INDEX
1471 assert (countBufferedBytes (cff) == offsets[2]);
1472 { // Font DICT INDEX
1473 cacheU32 (cff, 1); // count
1474 cacheU8 (cff, 1); // offSize
1475 cacheU8 (cff, 1); // offset[0]
1476 cacheU8 (cff, 4); // offset[1]
1477 cacheCFFOperand (cff, 0);
1478 cacheCFFOperand (cff, 0);
1479 cacheU8 (cff, 18); // Private
1480 }
1481 assert (countBufferedBytes (cff) == offsets[3]);
1482 }
1483 { // CharStrings INDEX
1484 Buffer *offsets = newBuffer (4096);
1485 Buffer *charstrings = newBuffer (4096);
1486 Buffer *outline = newBuffer (1024);
1487 const Glyph *glyph = getBufferHead (font->glyphs);
1488 const Glyph *const endGlyph = glyph + font->glyphCount;
1489 for (; glyph < endGlyph; glyph++)
1490 {
1491 // CFF offsets start at 1
1492 storeU32 (offsets, countBufferedBytes (charstrings) + 1);
1493
1494 pixels_t rx = -glyph->pos;
1495 pixels_t ry = DESCENDER;
1496 resetBuffer (outline);
1497 buildOutline (outline, glyph->bitmap, glyph->byteCount, FILL_LEFT);
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;
1502 int stackSize = 0;
1503 bool isDrawing = false;
1504 pixels_t width = glyph->combining ? 0 : PW (glyph->byteCount);
1505 if (version == 1 && width != defaultWidth)
1506 {
1507 cacheCFFOperand (charstrings, FU (width - nominalWidth));
1508 stackSize++;
1509 }
1510 for (const pixels_t *p = getBufferHead (outline),
1511 *const end = getBufferTail (outline); p < end;)
1512 {
1513 int s = 0;
1514 const enum ContourOp op = *p++;
1515 if (op == OP_POINT)
1516 {
1517 const pixels_t x = *p++, y = *p++;
1518 if (x != rx)
1519 {
1520 cacheCFFOperand (charstrings, FU (x - rx));
1521 rx = x;
1522 stackSize++;
1523 s |= 1;
1524 }
1525 if (y != ry)
1526 {
1527 cacheCFFOperand (charstrings, FU (y - ry));
1528 ry = y;
1529 stackSize++;
1530 s |= 2;
1531 }
1532 assert (!(isDrawing && s == 3));
1533 }
1534 if (s)
1535 {
1536 if (!isDrawing)
1537 {
1538 const enum CFFOp moves[] = {0, hmoveto, vmoveto,
1539 rmoveto};
1540 cacheU8 (charstrings, moves[s]);
1541 stackSize = 0;
1542 }
1543 else if (!pendingOp)
1544 pendingOp = (enum CFFOp[]){0, hlineto, vlineto}[s];
1545 }
1546 else if (!isDrawing)
1547 {
1548 // only when the first point happens to be (0, 0)
1549 cacheCFFOperand (charstrings, FU (0));
1550 cacheU8 (charstrings, hmoveto);
1551 stackSize = 0;
1552 }
1553 if (op == OP_CLOSE || stackSize >= STACK_LIMIT)
1554 {
1555 assert (stackSize <= STACK_LIMIT);
1556 cacheU8 (charstrings, pendingOp);
1557 pendingOp = 0;
1558 stackSize = 0;
1559 }
1560 isDrawing = op != OP_CLOSE;
1561 }
1562 if (version == 1)
1563 cacheU8 (charstrings, endchar);
1564 }
1565 size_t lastOffset = countBufferedBytes (charstrings) + 1;
1566 #if SIZE_MAX > U32MAX
1567 if (lastOffset > U32MAX)
1568 fail ("CFF data exceeded size limit.");
1569 #endif
1570 storeU32 (offsets, lastOffset);
1571 int offsetSize = 1 + (lastOffset > 0xff)
1572 + (lastOffset > 0xffff)
1573 + (lastOffset > 0xffffff);
1574 // count (must match 'numGlyphs' in 'maxp' table)
1575 cacheU (cff, font->glyphCount, version * 2);
1576 cacheU8 (cff, offsetSize); // offSize
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); // offsets
1581 cacheBuffer (cff, charstrings); // data
1582 freeBuffer (offsets);
1583 freeBuffer (charstrings);
1584 freeBuffer (outline);
1585 }
1586 #undef cacheCFF32
1587}
1588
1589/**
1590 @brief Add a TrueType table to a font.
1591
1592 @param[in,out] font Pointer to a Font struct to contain the TrueType table.
1593 @param[in] format The TrueType "loca" table format, Offset16 or Offset32.
1594 @param[in] names List of NameStrings.
1595*/
1596void
1597fillTrueType (Font *font, enum LocaFormat *format,
1598 uint_fast16_t *maxPoints, uint_fast16_t *maxContours)
1599{
1600 Buffer *glyf = newBuffer (65536);
1601 addTable (font, "glyf", glyf);
1602 Buffer *loca = newBuffer (4 * (font->glyphCount + 1));
1603 addTable (font, "loca", loca);
1604 *format = LOCA_OFFSET32;
1605 Buffer *endPoints = newBuffer (256);
1606 Buffer *flags = newBuffer (256);
1607 Buffer *xs = newBuffer (256);
1608 Buffer *ys = newBuffer (256);
1609 Buffer *outline = newBuffer (1024);
1610 Glyph *const glyphs = getBufferHead (font->glyphs);
1611 const Glyph *const glyphsEnd = getBufferTail (font->glyphs);
1612 for (Glyph *glyph = glyphs; glyph < glyphsEnd; glyph++)
1613 {
1614 cacheU32 (loca, countBufferedBytes (glyf));
1615 pixels_t rx = -glyph->pos;
1616 pixels_t ry = DESCENDER;
1617 pixels_t xMin = GLYPH_MAX_WIDTH, xMax = 0;
1618 pixels_t yMin = ASCENDER, yMax = -DESCENDER;
1619 resetBuffer (endPoints);
1620 resetBuffer (flags);
1621 resetBuffer (xs);
1622 resetBuffer (ys);
1623 resetBuffer (outline);
1624 buildOutline (outline, glyph->bitmap, glyph->byteCount, FILL_RIGHT);
1625 uint_fast32_t pointCount = 0, contourCount = 0;
1626 for (const pixels_t *p = getBufferHead (outline),
1627 *const end = getBufferTail (outline); p < end;)
1628 {
1629 const enum ContourOp op = *p++;
1630 if (op == OP_CLOSE)
1631 {
1632 contourCount++;
1633 assert (contourCount <= U16MAX);
1634 cacheU16 (endPoints, pointCount - 1);
1635 continue;
1636 }
1637 assert (op == OP_POINT);
1638 pointCount++;
1639 assert (pointCount <= U16MAX);
1640 const pixels_t x = *p++, y = *p++;
1641 uint_fast8_t pointFlags =
1642 + B1 (0) // point is on curve
1643 + BX (1, x != rx) // x coordinate is 1 byte instead of 2
1644 + BX (2, y != ry) // y coordinate is 1 byte instead of 2
1645 + B0 (3) // repeat
1646 + BX (4, x >= rx) // when x is 1 byte: x is positive;
1647 // when x is 2 bytes: x unchanged and omitted
1648 + BX (5, y >= ry) // when y is 1 byte: y is positive;
1649 // when y is 2 bytes: y unchanged and omitted
1650 + B1 (6) // contours may overlap
1651 + B0 (7) // reserved
1652 ;
1653 cacheU8 (flags, pointFlags);
1654 if (x != rx)
1655 cacheU8 (xs, FU (x > rx ? x - rx : rx - x));
1656 if (y != ry)
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;
1662 rx = x;
1663 ry = y;
1664 }
1665 if (contourCount == 0)
1666 continue; // blank glyph is indicated by the 'loca' table
1667 glyph->lsb = glyph->pos + xMin;
1668 cacheU16 (glyf, contourCount); // numberOfContours
1669 cacheU16 (glyf, FU (glyph->pos + xMin)); // xMin
1670 cacheU16 (glyf, FU (yMin)); // yMin
1671 cacheU16 (glyf, FU (glyph->pos + xMax)); // xMax
1672 cacheU16 (glyf, FU (yMax)); // yMax
1673 cacheBuffer (glyf, endPoints); // endPtsOfContours[]
1674 cacheU16 (glyf, 0); // instructionLength
1675 cacheBuffer (glyf, flags); // flags[]
1676 cacheBuffer (glyf, xs); // xCoordinates[]
1677 cacheBuffer (glyf, ys); // yCoordinates[]
1678 if (pointCount > *maxPoints)
1679 *maxPoints = pointCount;
1680 if (contourCount > *maxContours)
1681 *maxContours = contourCount;
1682 }
1683 cacheU32 (loca, countBufferedBytes (glyf));
1684 freeBuffer (endPoints);
1685 freeBuffer (flags);
1686 freeBuffer (xs);
1687 freeBuffer (ys);
1688 freeBuffer (outline);
1689}
1690
1691/**
1692 @brief Create a dummy blank outline in a font table.
1693
1694 @param[in,out] font Pointer to a Font struct to insert a blank outline.
1695*/
1696void
1698{
1699 Buffer *glyf = newBuffer (12);
1700 addTable (font, "glyf", glyf);
1701 // Empty table is not allowed, but an empty outline for glyph 0 suffices.
1702 cacheU16 (glyf, 0); // numberOfContours
1703 cacheU16 (glyf, FU (0)); // xMin
1704 cacheU16 (glyf, FU (0)); // yMin
1705 cacheU16 (glyf, FU (0)); // xMax
1706 cacheU16 (glyf, FU (0)); // yMax
1707 cacheU16 (glyf, 0); // instructionLength
1708 Buffer *loca = newBuffer (2 * (font->glyphCount + 1));
1709 addTable (font, "loca", loca);
1710 cacheU16 (loca, 0); // offsets[0]
1711 assert (countBufferedBytes (glyf) % 2 == 0);
1712 for (uint_fast32_t i = 1; i <= font->glyphCount; i++)
1713 cacheU16 (loca, countBufferedBytes (glyf) / 2); // offsets[i]
1714}
1715
1716/**
1717 @brief Fill OpenType bitmap data and location tables.
1718
1719 This function fills an Embedded Bitmap Data (EBDT) Table
1720 and an Embedded Bitmap Location (EBLC) Table with glyph
1721 bitmap information. These tables enable embedding bitmaps
1722 in OpenType fonts. No Embedded Bitmap Scaling (EBSC) table
1723 is used for the bitmap glyphs, only EBDT and EBLC.
1724
1725 @param[in,out] font Pointer to a Font struct in which to add bitmaps.
1726*/
1727void
1729{
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;
1735 Buffer *ebdt = newBuffer (4 + bitmapsSize);
1736 addTable (font, "EBDT", ebdt);
1737 cacheU16 (ebdt, 2); // majorVersion
1738 cacheU16 (ebdt, 0); // minorVersion
1739 uint_fast8_t byteCount = 0; // unequal to any glyph
1740 pixels_t pos = 0;
1741 bool combining = false;
1742 Buffer *rangeHeads = newBuffer (32);
1743 Buffer *offsets = newBuffer (64);
1744 for (const Glyph *glyph = glyphs; glyph < glyphsEnd; glyph++)
1745 {
1746 if (glyph->byteCount != byteCount || glyph->pos != pos ||
1747 glyph->combining != combining)
1748 {
1749 storeU16 (rangeHeads, glyph - glyphs);
1750 storeU32 (offsets, countBufferedBytes (ebdt));
1751 byteCount = glyph->byteCount;
1752 pos = glyph->pos;
1753 combining = glyph->combining;
1754 }
1755 cacheBytes (ebdt, glyph->bitmap, byteCount);
1756 }
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);
1761 Buffer *eblc = newBuffer (4096);
1762 addTable (font, "EBLC", eblc);
1763 cacheU16 (eblc, 2); // majorVersion
1764 cacheU16 (eblc, 0); // minorVersion
1765 cacheU32 (eblc, 1); // numSizes
1766 { // bitmapSizes[0]
1767 cacheU32 (eblc, 56); // indexSubTableArrayOffset
1768 cacheU32 (eblc, (8 + 20) * rangeCount); // indexTablesSize
1769 cacheU32 (eblc, rangeCount); // numberOfIndexSubTables
1770 cacheU32 (eblc, 0); // colorRef
1771 { // hori
1772 cacheU8 (eblc, ASCENDER); // ascender
1773 cacheU8 (eblc, -DESCENDER); // descender
1774 cacheU8 (eblc, font->maxWidth); // widthMax
1775 cacheU8 (eblc, 1); // caretSlopeNumerator
1776 cacheU8 (eblc, 0); // caretSlopeDenominator
1777 cacheU8 (eblc, 0); // caretOffset
1778 cacheU8 (eblc, 0); // minOriginSB
1779 cacheU8 (eblc, 0); // minAdvanceSB
1780 cacheU8 (eblc, ASCENDER); // maxBeforeBL
1781 cacheU8 (eblc, -DESCENDER); // minAfterBL
1782 cacheU8 (eblc, 0); // pad1
1783 cacheU8 (eblc, 0); // pad2
1784 }
1785 { // vert
1786 cacheU8 (eblc, ASCENDER); // ascender
1787 cacheU8 (eblc, -DESCENDER); // descender
1788 cacheU8 (eblc, font->maxWidth); // widthMax
1789 cacheU8 (eblc, 1); // caretSlopeNumerator
1790 cacheU8 (eblc, 0); // caretSlopeDenominator
1791 cacheU8 (eblc, 0); // caretOffset
1792 cacheU8 (eblc, 0); // minOriginSB
1793 cacheU8 (eblc, 0); // minAdvanceSB
1794 cacheU8 (eblc, ASCENDER); // maxBeforeBL
1795 cacheU8 (eblc, -DESCENDER); // minAfterBL
1796 cacheU8 (eblc, 0); // pad1
1797 cacheU8 (eblc, 0); // pad2
1798 }
1799 cacheU16 (eblc, 0); // startGlyphIndex
1800 cacheU16 (eblc, font->glyphCount - 1); // endGlyphIndex
1801 cacheU8 (eblc, 16); // ppemX
1802 cacheU8 (eblc, 16); // ppemY
1803 cacheU8 (eblc, 1); // bitDepth
1804 cacheU8 (eblc, 1); // flags = Horizontal
1805 }
1806 { // IndexSubTableArray
1807 uint_fast32_t offset = rangeCount * 8;
1808 for (const uint_least16_t *p = ranges; p < rangesEnd; p++)
1809 {
1810 cacheU16 (eblc, *p); // firstGlyphIndex
1811 cacheU16 (eblc, p[1] - 1); // lastGlyphIndex
1812 cacheU32 (eblc, offset); // additionalOffsetToIndexSubtable
1813 offset += 20;
1814 }
1815 }
1816 { // IndexSubTables
1817 const uint_least32_t *offset = getBufferHead (offsets);
1818 for (const uint_least16_t *p = ranges; p < rangesEnd; p++)
1819 {
1820 const Glyph *glyph = &glyphs[*p];
1821 cacheU16 (eblc, 2); // indexFormat
1822 cacheU16 (eblc, 5); // imageFormat
1823 cacheU32 (eblc, *offset++); // imageDataOffset
1824 cacheU32 (eblc, glyph->byteCount); // imageSize
1825 { // bigMetrics
1826 cacheU8 (eblc, GLYPH_HEIGHT); // height
1827 const uint_fast8_t width = PW (glyph->byteCount);
1828 cacheU8 (eblc, width); // width
1829 cacheU8 (eblc, glyph->pos); // horiBearingX
1830 cacheU8 (eblc, ASCENDER); // horiBearingY
1831 cacheU8 (eblc, glyph->combining ? 0 : width); // horiAdvance
1832 cacheU8 (eblc, 0); // vertBearingX
1833 cacheU8 (eblc, 0); // vertBearingY
1834 cacheU8 (eblc, GLYPH_HEIGHT); // vertAdvance
1835 }
1836 }
1837 }
1838 freeBuffer (rangeHeads);
1839 freeBuffer (offsets);
1840}
1841
1842/**
1843 @brief Fill a "head" font table.
1844
1845 The "head" table contains font header information common to the
1846 whole font.
1847
1848 @param[in,out] font The Font struct to which to add the table.
1849 @param[in] locaFormat The "loca" offset index location table.
1850 @param[in] xMin The minimum x-coordinate for a glyph.
1851*/
1852void
1853fillHeadTable (Font *font, enum LocaFormat locaFormat, pixels_t xMin)
1854{
1855 Buffer *head = newBuffer (56);
1856 addTable (font, "head", head);
1857 cacheU16 (head, 1); // majorVersion
1858 cacheU16 (head, 0); // minorVersion
1859 cacheZeros (head, 4); // fontRevision (unused)
1860 // The 'checksumAdjustment' field is a checksum of the entire file.
1861 // It is later calculated and written directly in the 'writeFont' function.
1862 cacheU32 (head, 0); // checksumAdjustment (placeholder)
1863 cacheU32 (head, 0x5f0f3cf5); // magicNumber
1864 const uint_fast16_t flags =
1865 + B1 ( 0) // baseline at y=0
1866 + B1 ( 1) // LSB at x=0 (doubtful; probably should be LSB=xMin)
1867 + B0 ( 2) // instructions may depend on point size
1868 + B0 ( 3) // force internal ppem to integers
1869 + B0 ( 4) // instructions may alter advance width
1870 + B0 ( 5) // not used in OpenType
1871 + B0 ( 6) // not used in OpenType
1872 + B0 ( 7) // not used in OpenType
1873 + B0 ( 8) // not used in OpenType
1874 + B0 ( 9) // not used in OpenType
1875 + B0 (10) // not used in OpenType
1876 + B0 (11) // font transformed
1877 + B0 (12) // font converted
1878 + B0 (13) // font optimized for ClearType
1879 + B0 (14) // last resort font
1880 + B0 (15) // reserved
1881 ;
1882 cacheU16 (head, flags); // flags
1883 cacheU16 (head, FUPEM); // unitsPerEm
1884 cacheZeros (head, 8); // created (unused)
1885 cacheZeros (head, 8); // modified (unused)
1886 cacheU16 (head, FU (xMin)); // xMin
1887 cacheU16 (head, FU (-DESCENDER)); // yMin
1888 cacheU16 (head, FU (font->maxWidth)); // xMax
1889 cacheU16 (head, FU (ASCENDER)); // yMax
1890 // macStyle (must agree with 'fsSelection' in 'OS/2' table)
1891 const uint_fast16_t macStyle =
1892 + B0 (0) // bold
1893 + B0 (1) // italic
1894 + B0 (2) // underline
1895 + B0 (3) // outline
1896 + B0 (4) // shadow
1897 + B0 (5) // condensed
1898 + B0 (6) // extended
1899 // 7-15 reserved
1900 ;
1901 cacheU16 (head, macStyle);
1902 cacheU16 (head, GLYPH_HEIGHT); // lowestRecPPEM
1903 cacheU16 (head, 2); // fontDirectionHint
1904 cacheU16 (head, locaFormat); // indexToLocFormat
1905 cacheU16 (head, 0); // glyphDataFormat
1906}
1907
1908/**
1909 @brief Fill a "hhea" font table.
1910
1911 The "hhea" table contains horizontal header information,
1912 for example left and right side bearings.
1913
1914 @param[in,out] font The Font struct to which to add the table.
1915 @param[in] xMin The minimum x-coordinate for a glyph.
1916*/
1917void
1919{
1920 Buffer *hhea = newBuffer (36);
1921 addTable (font, "hhea", hhea);
1922 cacheU16 (hhea, 1); // majorVersion
1923 cacheU16 (hhea, 0); // minorVersion
1924 cacheU16 (hhea, FU (ASCENDER)); // ascender
1925 cacheU16 (hhea, FU (-DESCENDER)); // descender
1926 cacheU16 (hhea, FU (0)); // lineGap
1927 cacheU16 (hhea, FU (font->maxWidth)); // advanceWidthMax
1928 cacheU16 (hhea, FU (xMin)); // minLeftSideBearing
1929 cacheU16 (hhea, FU (0)); // minRightSideBearing (unused)
1930 cacheU16 (hhea, FU (font->maxWidth)); // xMaxExtent
1931 cacheU16 (hhea, 1); // caretSlopeRise
1932 cacheU16 (hhea, 0); // caretSlopeRun
1933 cacheU16 (hhea, 0); // caretOffset
1934 cacheU16 (hhea, 0); // reserved
1935 cacheU16 (hhea, 0); // reserved
1936 cacheU16 (hhea, 0); // reserved
1937 cacheU16 (hhea, 0); // reserved
1938 cacheU16 (hhea, 0); // metricDataFormat
1939 cacheU16 (hhea, font->glyphCount); // numberOfHMetrics
1940}
1941
1942/**
1943 @brief Fill a "maxp" font table.
1944
1945 The "maxp" table contains maximum profile information,
1946 such as the memory required to contain the font.
1947
1948 @param[in,out] font The Font struct to which to add the table.
1949 @param[in] isCFF true if a CFF font is included, false otherwise.
1950 @param[in] maxPoints Maximum points in a non-composite glyph.
1951 @param[in] maxContours Maximum contours in a non-composite glyph.
1952*/
1953void
1954fillMaxpTable (Font *font, bool isCFF, uint_fast16_t maxPoints,
1955 uint_fast16_t maxContours)
1956{
1957 Buffer *maxp = newBuffer (32);
1958 addTable (font, "maxp", maxp);
1959 cacheU32 (maxp, isCFF ? 0x00005000 : 0x00010000); // version
1960 cacheU16 (maxp, font->glyphCount); // numGlyphs
1961 if (isCFF)
1962 return;
1963 cacheU16 (maxp, maxPoints); // maxPoints
1964 cacheU16 (maxp, maxContours); // maxContours
1965 cacheU16 (maxp, 0); // maxCompositePoints
1966 cacheU16 (maxp, 0); // maxCompositeContours
1967 cacheU16 (maxp, 0); // maxZones
1968 cacheU16 (maxp, 0); // maxTwilightPoints
1969 cacheU16 (maxp, 0); // maxStorage
1970 cacheU16 (maxp, 0); // maxFunctionDefs
1971 cacheU16 (maxp, 0); // maxInstructionDefs
1972 cacheU16 (maxp, 0); // maxStackElements
1973 cacheU16 (maxp, 0); // maxSizeOfInstructions
1974 cacheU16 (maxp, 0); // maxComponentElements
1975 cacheU16 (maxp, 0); // maxComponentDepth
1976}
1977
1978/**
1979 @brief Fill an "OS/2" font table.
1980
1981 The "OS/2" table contains OS/2 and Windows font metrics information.
1982
1983 @param[in,out] font The Font struct to which to add the table.
1984*/
1985void
1987{
1988 Buffer *os2 = newBuffer (100);
1989 addTable (font, "OS/2", os2);
1990 cacheU16 (os2, 5); // version
1991 // HACK: Average glyph width is not actually calculated.
1992 cacheU16 (os2, FU (font->maxWidth)); // xAvgCharWidth
1993 cacheU16 (os2, 400); // usWeightClass = Normal
1994 cacheU16 (os2, 5); // usWidthClass = Medium
1995 const uint_fast16_t typeFlags =
1996 + B0 (0) // reserved
1997 // usage permissions, one of:
1998 // Default: Installable embedding
1999 + B0 (1) // Restricted License embedding
2000 + B0 (2) // Preview & Print embedding
2001 + B0 (3) // Editable embedding
2002 // 4-7 reserved
2003 + B0 (8) // no subsetting
2004 + B0 (9) // bitmap embedding only
2005 // 10-15 reserved
2006 ;
2007 cacheU16 (os2, typeFlags); // fsType
2008 cacheU16 (os2, FU (5)); // ySubscriptXSize
2009 cacheU16 (os2, FU (7)); // ySubscriptYSize
2010 cacheU16 (os2, FU (0)); // ySubscriptXOffset
2011 cacheU16 (os2, FU (1)); // ySubscriptYOffset
2012 cacheU16 (os2, FU (5)); // ySuperscriptXSize
2013 cacheU16 (os2, FU (7)); // ySuperscriptYSize
2014 cacheU16 (os2, FU (0)); // ySuperscriptXOffset
2015 cacheU16 (os2, FU (4)); // ySuperscriptYOffset
2016 cacheU16 (os2, FU (1)); // yStrikeoutSize
2017 cacheU16 (os2, FU (5)); // yStrikeoutPosition
2018 cacheU16 (os2, 0x080a); // sFamilyClass = Sans Serif, Matrix
2019 const byte panose[] =
2020 {
2021 2, // Family Kind = Latin Text
2022 11, // Serif Style = Normal Sans
2023 4, // Weight = Thin
2024 // Windows would render all glyphs to the same width,
2025 // if 'Proportion' is set to 'Monospaced' (as Unifont should be).
2026 // 'Condensed' is the best alternative according to metrics.
2027 6, // Proportion = Condensed
2028 2, // Contrast = None
2029 2, // Stroke = No Variation
2030 2, // Arm Style = Straight Arms
2031 8, // Letterform = Normal/Square
2032 2, // Midline = Standard/Trimmed
2033 4, // X-height = Constant/Large
2034 };
2035 cacheBytes (os2, panose, sizeof panose); // panose
2036 // HACK: All defined Unicode ranges are marked functional for convenience.
2037 cacheU32 (os2, 0xffffffff); // ulUnicodeRange1
2038 cacheU32 (os2, 0xffffffff); // ulUnicodeRange2
2039 cacheU32 (os2, 0xffffffff); // ulUnicodeRange3
2040 cacheU32 (os2, 0x0effffff); // ulUnicodeRange4
2041 cacheBytes (os2, "GNU ", 4); // achVendID
2042 // fsSelection (must agree with 'macStyle' in 'head' table)
2043 const uint_fast16_t selection =
2044 + B0 (0) // italic
2045 + B0 (1) // underscored
2046 + B0 (2) // negative
2047 + B0 (3) // outlined
2048 + B0 (4) // strikeout
2049 + B0 (5) // bold
2050 + B1 (6) // regular
2051 + B1 (7) // use sTypo* metrics in this table
2052 + B1 (8) // font name conforms to WWS model
2053 + B0 (9) // oblique
2054 // 10-15 reserved
2055 ;
2056 cacheU16 (os2, 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;
2060 cacheU16 (os2, first < U16MAX ? first : U16MAX); // usFirstCharIndex
2061 cacheU16 (os2, last < U16MAX ? last : U16MAX); // usLastCharIndex
2062 cacheU16 (os2, FU (ASCENDER)); // sTypoAscender
2063 cacheU16 (os2, FU (-DESCENDER)); // sTypoDescender
2064 cacheU16 (os2, FU (0)); // sTypoLineGap
2065 cacheU16 (os2, FU (ASCENDER)); // usWinAscent
2066 cacheU16 (os2, FU (DESCENDER)); // usWinDescent
2067 // HACK: All reasonable code pages are marked functional for convenience.
2068 cacheU32 (os2, 0x603f01ff); // ulCodePageRange1
2069 cacheU32 (os2, 0xffff0000); // ulCodePageRange2
2070 cacheU16 (os2, FU (8)); // sxHeight
2071 cacheU16 (os2, FU (10)); // sCapHeight
2072 cacheU16 (os2, 0); // usDefaultChar
2073 cacheU16 (os2, 0x20); // usBreakChar
2074 cacheU16 (os2, 0); // usMaxContext
2075 cacheU16 (os2, 0); // usLowerOpticalPointSize
2076 cacheU16 (os2, 0xffff); // usUpperOpticalPointSize
2077}
2078
2079/**
2080 @brief Fill an "hmtx" font table.
2081
2082 The "hmtx" table contains horizontal metrics information.
2083
2084 @param[in,out] font The Font struct to which to add the table.
2085*/
2086void
2088{
2089 Buffer *hmtx = newBuffer (4 * font->glyphCount);
2090 addTable (font, "hmtx", hmtx);
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++)
2094 {
2095 int_fast16_t aw = glyph->combining ? 0 : PW (glyph->byteCount);
2096 cacheU16 (hmtx, FU (aw)); // advanceWidth
2097 cacheU16 (hmtx, FU (glyph->lsb)); // lsb
2098 }
2099}
2100
2101/**
2102 @brief Fill a "cmap" font table.
2103
2104 The "cmap" table contains character to glyph index mapping information.
2105
2106 @param[in,out] font The Font struct to which to add the table.
2107*/
2108void
2110{
2111 Glyph *const glyphs = getBufferHead (font->glyphs);
2112 Buffer *rangeHeads = newBuffer (16);
2113 uint_fast32_t rangeCount = 0;
2114 uint_fast32_t bmpRangeCount = 1; // 1 for the last 0xffff-0xffff range
2115 glyphs[0].codePoint = glyphs[1].codePoint; // to start a range at glyph 1
2116 for (uint_fast16_t i = 1; i < font->glyphCount; i++)
2117 {
2118 if (glyphs[i].codePoint != glyphs[i - 1].codePoint + 1)
2119 {
2120 storeU16 (rangeHeads, i);
2121 rangeCount++;
2122 bmpRangeCount += glyphs[i].codePoint < 0xffff;
2123 }
2124 }
2125 Buffer *cmap = newBuffer (256);
2126 addTable (font, "cmap", cmap);
2127 // Format 4 table is always generated for compatibility.
2128 bool hasFormat12 = glyphs[font->glyphCount - 1].codePoint > 0xffff;
2129 cacheU16 (cmap, 0); // version
2130 cacheU16 (cmap, 1 + hasFormat12); // numTables
2131 { // encodingRecords[0]
2132 cacheU16 (cmap, 3); // platformID
2133 cacheU16 (cmap, 1); // encodingID
2134 cacheU32 (cmap, 12 + 8 * hasFormat12); // subtableOffset
2135 }
2136 if (hasFormat12) // encodingRecords[1]
2137 {
2138 cacheU16 (cmap, 3); // platformID
2139 cacheU16 (cmap, 10); // encodingID
2140 cacheU32 (cmap, 36 + 8 * bmpRangeCount); // subtableOffset
2141 }
2142 const uint_least16_t *ranges = getBufferHead (rangeHeads);
2143 const uint_least16_t *const rangesEnd = getBufferTail (rangeHeads);
2144 storeU16 (rangeHeads, font->glyphCount);
2145 { // format 4 table
2146 cacheU16 (cmap, 4); // format
2147 cacheU16 (cmap, 16 + 8 * bmpRangeCount); // length
2148 cacheU16 (cmap, 0); // language
2149 if (bmpRangeCount * 2 > U16MAX)
2150 fail ("Too many ranges in 'cmap' table.");
2151 cacheU16 (cmap, bmpRangeCount * 2); // segCountX2
2152 uint_fast16_t searchRange = 1, entrySelector = -1;
2153 while (searchRange <= bmpRangeCount)
2154 {
2155 searchRange <<= 1;
2156 entrySelector++;
2157 }
2158 cacheU16 (cmap, searchRange); // searchRange
2159 cacheU16 (cmap, entrySelector); // entrySelector
2160 cacheU16 (cmap, bmpRangeCount * 2 - searchRange); // rangeShift
2161 { // endCode[]
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;
2166 if (cp > 0xfffe)
2167 cp = 0xfffe;
2168 cacheU16 (cmap, cp);
2169 cacheU16 (cmap, 0xffff);
2170 }
2171 cacheU16 (cmap, 0); // reservedPad
2172 { // startCode[]
2173 for (uint_fast32_t i = 0; i < bmpRangeCount - 1; i++)
2174 cacheU16 (cmap, glyphs[ranges[i]].codePoint);
2175 cacheU16 (cmap, 0xffff);
2176 }
2177 { // idDelta[]
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)
2183 delta = *p - glyphs[*p].codePoint;
2184 cacheU16 (cmap, delta);
2185 }
2186 { // idRangeOffsets[]
2187 for (uint_least16_t i = 0; i < bmpRangeCount; i++)
2188 cacheU16 (cmap, 0);
2189 }
2190 }
2191 if (hasFormat12) // format 12 table
2192 {
2193 cacheU16 (cmap, 12); // format
2194 cacheU16 (cmap, 0); // reserved
2195 cacheU32 (cmap, 16 + 12 * rangeCount); // length
2196 cacheU32 (cmap, 0); // language
2197 cacheU32 (cmap, rangeCount); // numGroups
2198
2199 // groups[]
2200 for (const uint_least16_t *p = ranges; p < rangesEnd; p++)
2201 {
2202 cacheU32 (cmap, glyphs[*p].codePoint); // startCharCode
2203 cacheU32 (cmap, glyphs[p[1] - 1].codePoint); // endCharCode
2204 cacheU32 (cmap, *p); // startGlyphID
2205 }
2206 }
2207 freeBuffer (rangeHeads);
2208}
2209
2210/**
2211 @brief Fill a "post" font table.
2212
2213 The "post" table contains information for PostScript printers.
2214
2215 @param[in,out] font The Font struct to which to add the table.
2216*/
2217void
2219{
2220 Buffer *post = newBuffer (32);
2221 addTable (font, "post", post);
2222 cacheU32 (post, 0x00030000); // version = 3.0
2223 cacheU32 (post, 0); // italicAngle
2224 cacheU16 (post, 0); // underlinePosition
2225 cacheU16 (post, 1); // underlineThickness
2226 cacheU32 (post, 1); // isFixedPitch
2227 cacheU32 (post, 0); // minMemType42
2228 cacheU32 (post, 0); // maxMemType42
2229 cacheU32 (post, 0); // minMemType1
2230 cacheU32 (post, 0); // maxMemType1
2231}
2232
2233/**
2234 @brief Fill a "GPOS" font table.
2235
2236 The "GPOS" table contains information for glyph positioning.
2237
2238 @param[in,out] font The Font struct to which to add the table.
2239*/
2240void
2242{
2243 Buffer *gpos = newBuffer (16);
2244 addTable (font, "GPOS", gpos);
2245 cacheU16 (gpos, 1); // majorVersion
2246 cacheU16 (gpos, 0); // minorVersion
2247 cacheU16 (gpos, 10); // scriptListOffset
2248 cacheU16 (gpos, 12); // featureListOffset
2249 cacheU16 (gpos, 14); // lookupListOffset
2250 { // ScriptList table
2251 cacheU16 (gpos, 0); // scriptCount
2252 }
2253 { // Feature List table
2254 cacheU16 (gpos, 0); // featureCount
2255 }
2256 { // Lookup List Table
2257 cacheU16 (gpos, 0); // lookupCount
2258 }
2259}
2260
2261/**
2262 @brief Fill a "GSUB" font table.
2263
2264 The "GSUB" table contains information for glyph substitution.
2265
2266 @param[in,out] font The Font struct to which to add the table.
2267*/
2268void
2270{
2271 Buffer *gsub = newBuffer (38);
2272 addTable (font, "GSUB", gsub);
2273 cacheU16 (gsub, 1); // majorVersion
2274 cacheU16 (gsub, 0); // minorVersion
2275 cacheU16 (gsub, 10); // scriptListOffset
2276 cacheU16 (gsub, 34); // featureListOffset
2277 cacheU16 (gsub, 36); // lookupListOffset
2278 { // ScriptList table
2279 cacheU16 (gsub, 2); // scriptCount
2280 { // scriptRecords[0]
2281 cacheBytes (gsub, "DFLT", 4); // scriptTag
2282 cacheU16 (gsub, 14); // scriptOffset
2283 }
2284 { // scriptRecords[1]
2285 cacheBytes (gsub, "thai", 4); // scriptTag
2286 cacheU16 (gsub, 14); // scriptOffset
2287 }
2288 { // Script table
2289 cacheU16 (gsub, 4); // defaultLangSysOffset
2290 cacheU16 (gsub, 0); // langSysCount
2291 { // Default Language System table
2292 cacheU16 (gsub, 0); // lookupOrderOffset
2293 cacheU16 (gsub, 0); // requiredFeatureIndex
2294 cacheU16 (gsub, 0); // featureIndexCount
2295 }
2296 }
2297 }
2298 { // Feature List table
2299 cacheU16 (gsub, 0); // featureCount
2300 }
2301 { // Lookup List Table
2302 cacheU16 (gsub, 0); // lookupCount
2303 }
2304}
2305
2306/**
2307 @brief Cache a string as a big-ending UTF-16 surrogate pair.
2308
2309 This function encodes a UTF-8 string as a big-endian UTF-16
2310 surrogate pair.
2311
2312 @param[in,out] buf Pointer to a Buffer struct to update.
2313 @param[in] str The character array to encode.
2314*/
2315void
2316cacheStringAsUTF16BE (Buffer *buf, const char *str)
2317{
2318 for (const char *p = str; *p; p++)
2319 {
2320 byte c = *p;
2321 if (c < 0x80)
2322 {
2323 cacheU16 (buf, c);
2324 continue;
2325 }
2326 int length = 1;
2327 byte mask = 0x40;
2328 for (; c & mask; mask >>= 1)
2329 length++;
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++)
2334 {
2335 c = *++p;
2336 if ((c & 0xc0) != 0x80) // NUL checked here
2337 fail ("Ill-formed UTF-8 sequence.");
2338 codePoint = (codePoint << 6) | (c & 0x3f);
2339 }
2340 const int lowerBits = length==2 ? 7 : length==3 ? 11 : 16;
2341 if (codePoint >> lowerBits == 0)
2342 fail ("Ill-formed UTF-8 sequence."); // sequence should be shorter
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)
2348 {
2349 cacheU16 (buf, 0xd800 | (codePoint - 0x10000) >> 10);
2350 cacheU16 (buf, 0xdc00 | (codePoint & 0x3ff));
2351 }
2352 else
2353 cacheU16 (buf, codePoint);
2354 }
2355}
2356
2357/**
2358 @brief Fill a "name" font table.
2359
2360 The "name" table contains name information, for example for Name IDs.
2361
2362 @param[in,out] font The Font struct to which to add the table.
2363 @param[in] names List of NameStrings.
2364*/
2365void
2366fillNameTable (Font *font, NameStrings nameStrings)
2367{
2368 Buffer *name = newBuffer (2048);
2369 addTable (font, "name", name);
2370 size_t nameStringCount = 0;
2371 for (size_t i = 0; i < MAX_NAME_IDS; i++)
2372 nameStringCount += !!nameStrings[i];
2373 cacheU16 (name, 0); // version
2374 cacheU16 (name, nameStringCount); // count
2375 cacheU16 (name, 2 * 3 + 12 * nameStringCount); // storageOffset
2376 Buffer *stringData = newBuffer (1024);
2377 // nameRecord[]
2378 for (size_t i = 0; i < MAX_NAME_IDS; i++)
2379 {
2380 if (!nameStrings[i])
2381 continue;
2382 size_t offset = countBufferedBytes (stringData);
2383 cacheStringAsUTF16BE (stringData, nameStrings[i]);
2384 size_t length = countBufferedBytes (stringData) - offset;
2385 if (offset > U16MAX || length > U16MAX)
2386 fail ("Name strings are too long.");
2387 // Platform ID 0 (Unicode) is not well supported.
2388 // ID 3 (Windows) seems to be the best for compatibility.
2389 cacheU16 (name, 3); // platformID = Windows
2390 cacheU16 (name, 1); // encodingID = Unicode BMP
2391 cacheU16 (name, 0x0409); // languageID = en-US
2392 cacheU16 (name, i); // nameID
2393 cacheU16 (name, length); // length
2394 cacheU16 (name, offset); // stringOffset
2395 }
2396 cacheBuffer (name, stringData);
2397 freeBuffer (stringData);
2398}
2399
2400/**
2401 @brief Print program version string on stdout.
2402
2403 Print program version if invoked with the "--version" option,
2404 and then exit successfully.
2405*/
2406void
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");
2415
2416 exit (EXIT_SUCCESS);
2417}
2418
2419/**
2420 @brief Print help message to stdout and then exit.
2421
2422 Print help message if invoked with the "--help" option,
2423 and then exit successfully.
2424*/
2425void
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");
2432 printf (" cff\n");
2433 printf (" cff2\n");
2434 printf (" truetype\n");
2435 printf (" blank\n");
2436 printf (" bitmap\n");
2437 printf (" gpos\n");
2438 printf (" gsub\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");
2442
2443 exit (EXIT_SUCCESS);
2444}
2445
2446/**
2447 @brief Data structure to hold options for OpenType font output.
2448
2449 This data structure holds the status of options that can be
2450 specified as command line arguments for creating the output
2451 OpenType font file.
2452*/
2453typedef struct Options
2454{
2455 bool truetype, blankOutline, bitmap, gpos, gsub;
2456 int cff; // 0 = no CFF outline; 1 = use 'CFF' table; 2 = use 'CFF2' table
2457 const char *hex, *pos, *out; // file names
2458 NameStrings nameStrings; // indexed directly by Name IDs
2460
2461/**
2462 @brief Match a command line option with its key for enabling.
2463
2464 @param[in] operand A pointer to the specified operand.
2465 @param[in] key Pointer to the option structure.
2466 @param[in] delimeter The delimiter to end searching.
2467 @return Pointer to the first character of the desired option.
2468*/
2469const char *
2470matchToken (const char *operand, const char *key, char delimiter)
2471{
2472 while (*key)
2473 if (*operand++ != *key++)
2474 return NULL;
2475 if (!*operand || *operand++ == delimiter)
2476 return operand;
2477 return NULL;
2478}
2479
2480/**
2481 @brief Parse command line options.
2482
2483 Option Data Type Description
2484 ------ --------- -----------
2485 truetype bool Generate TrueType outlines
2486 blankOutline bool Generate blank outlines
2487 bitmap bool Generate embedded bitmap
2488 gpos bool Generate a dummy GPOS table
2489 gsub bool Generate a dummy GSUB table
2490 cff int Generate CFF 1 or CFF 2 outlines
2491 hex const char * Name of Unifont .hex file
2492 pos const char * Name of Unifont combining data file
2493 out const char * Name of output font file
2494 nameStrings NameStrings Array of TrueType font Name IDs
2495
2496 @param[in] argv Pointer to array of command line options.
2497 @return Data structure to hold requested command line options.
2498*/
2499Options
2500parseOptions (char *const argv[const])
2501{
2502 Options opt = {0}; // all options default to 0, false and NULL
2503 const char *format = NULL;
2504 struct StringArg
2505 {
2506 const char *const key;
2507 const char **const value;
2508 } strArgs[] =
2509 {
2510 {"hex", &opt.hex},
2511 {"pos", &opt.pos},
2512 {"out", &opt.out},
2513 {"format", &format},
2514 {NULL, NULL} // sentinel
2515 };
2516 for (char *const *argp = argv + 1; *argp; argp++)
2517 {
2518 const char *const arg = *argp;
2519 struct StringArg *p;
2520 const char *value = NULL;
2521 if (strcmp (arg, "--help") == 0)
2522 printHelp ();
2523 if (strcmp (arg, "--version") == 0)
2524 printVersion ();
2525 for (p = strArgs; p->key; p++)
2526 if ((value = matchToken (arg, p->key, '=')))
2527 break;
2528 if (p->key)
2529 {
2530 if (!*value)
2531 fail ("Empty argument: '%s'.", p->key);
2532 if (*p->value)
2533 fail ("Duplicate argument: '%s'.", p->key);
2534 *p->value = value;
2535 }
2536 else // shall be a name string
2537 {
2538 char *endptr;
2539 unsigned long id = strtoul (arg, &endptr, 10);
2540 if (endptr == arg || id >= MAX_NAME_IDS || *endptr != '=')
2541 fail ("Invalid argument: '%s'.", arg);
2542 endptr++; // skip '='
2543 if (opt.nameStrings[id])
2544 fail ("Duplicate name ID: %lu.", id);
2545 opt.nameStrings[id] = endptr;
2546 }
2547 }
2548 if (!opt.hex)
2549 fail ("Hex file is not specified.");
2550 if (opt.pos && opt.pos[0] == '\0')
2551 opt.pos = NULL; // Position file is optional. Empty path means none.
2552 if (!opt.out)
2553 fail ("Output file is not specified.");
2554 if (!format)
2555 fail ("Format is not specified.");
2556 for (const NamePair *p = defaultNames; p->str; p++)
2557 if (!opt.nameStrings[p->id])
2558 opt.nameStrings[p->id] = p->str;
2559 bool cff = false, cff2 = false;
2560 struct Symbol
2561 {
2562 const char *const key;
2563 bool *const found;
2564 } symbols[] =
2565 {
2566 {"cff", &cff},
2567 {"cff2", &cff2},
2568 {"truetype", &opt.truetype},
2569 {"blank", &opt.blankOutline},
2570 {"bitmap", &opt.bitmap},
2571 {"gpos", &opt.gpos},
2572 {"gsub", &opt.gsub},
2573 {NULL, NULL} // sentinel
2574 };
2575 while (*format)
2576 {
2577 const struct Symbol *p;
2578 const char *next = NULL;
2579 for (p = symbols; p->key; p++)
2580 if ((next = matchToken (format, p->key, ',')))
2581 break;
2582 if (!p->key)
2583 fail ("Invalid format.");
2584 *p->found = true;
2585 format = next;
2586 }
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;
2592 return opt;
2593}
2594
2595/**
2596 @brief The main function.
2597
2598 @param[in] argc The number of command-line arguments.
2599 @param[in] argv The array of command-line arguments.
2600 @return EXIT_FAILURE upon fatal error, EXIT_SUCCESS otherwise.
2601*/
2602int
2603main (int argc, char *argv[])
2604{
2605 initBuffers (16);
2606 atexit (cleanBuffers);
2607 Options opt = parseOptions (argv);
2608 Font font;
2609 font.tables = newBuffer (sizeof (Table) * 16);
2610 font.glyphs = newBuffer (sizeof (Glyph) * MAX_GLYPHS);
2611 readGlyphs (&font, opt.hex);
2612 sortGlyphs (&font);
2613 enum LocaFormat loca = LOCA_OFFSET16;
2614 uint_fast16_t maxPoints = 0, maxContours = 0;
2615 pixels_t xMin = 0;
2616 if (opt.pos)
2617 positionGlyphs (&font, opt.pos, &xMin);
2618 if (opt.gpos)
2619 fillGposTable (&font);
2620 if (opt.gsub)
2621 fillGsubTable (&font);
2622 if (opt.cff)
2623 fillCFF (&font, opt.cff, opt.nameStrings);
2624 if (opt.truetype)
2625 fillTrueType (&font, &loca, &maxPoints, &maxContours);
2626 if (opt.blankOutline)
2627 fillBlankOutline (&font);
2628 if (opt.bitmap)
2629 fillBitmap (&font);
2630 fillHeadTable (&font, loca, xMin);
2631 fillHheaTable (&font, xMin);
2632 fillMaxpTable (&font, opt.cff, maxPoints, maxContours);
2633 fillOS2Table (&font);
2634 fillNameTable (&font, opt.nameStrings);
2635 fillHmtxTable (&font);
2636 fillCmapTable (&font);
2637 fillPostTable (&font);
2638 organizeTables (&font, opt.cff);
2639 writeFont (&font, opt.cff, opt.out);
2640 return EXIT_SUCCESS;
2641}
#define U16MAX
Maximum UTF-16 code point value.
Definition: hex2otf.c:55
void organizeTables(Font *font, bool isCFF)
Sort tables according to OpenType recommendations.
Definition: hex2otf.c:711
void cacheU32(Buffer *buf, uint_fast32_t value)
Append four unsigned bytes to the end of a byte array.
Definition: hex2otf.c:427
Buffer * allBuffers
Initial allocation of empty array of buffer pointers.
Definition: hex2otf.c:139
#define MAX_NAME_IDS
Name IDs 0-255 are used for standard names.
Definition: hex2otf.c:88
void fillGsubTable(Font *font)
Fill a "GSUB" font table.
Definition: hex2otf.c:2269
void writeFont(Font *font, bool isCFF, const char *fileName)
Write OpenType font to output file.
Definition: hex2otf.c:786
void cacheU16(Buffer *buf, uint_fast16_t value)
Append two unsigned bytes to the end of a byte array.
Definition: hex2otf.c:412
const char * NameStrings[MAX_NAME_IDS]
Array of OpenType names indexed directly by Name IDs.
Definition: hex2otf.c:604
unsigned char byte
Definition of "byte" type as an unsigned char.
Definition: hex2otf.c:97
int byCodePoint(const void *a, const void *b)
Compare two Unicode code points to determine which is greater.
Definition: hex2otf.c:1040
void printHelp()
Print help message to stdout and then exit.
Definition: hex2otf.c:2426
void cacheZeros(Buffer *buf, size_t count)
Append 1 to 4 bytes of zeroes to a buffer, for padding.
Definition: hex2otf.c:491
void fillPostTable(Font *font)
Fill a "post" font table.
Definition: hex2otf.c:2218
int main(int argc, char *argv[])
The main function.
Definition: hex2otf.c:2603
#define defineStore(name, type)
Temporary define to look up an element in an array of given type.
Definition: hex2otf.c:350
size_t nextBufferIndex
Index number to tail element of Buffer * array.
Definition: hex2otf.c:141
#define B0(shift)
Clear a given bit in a word.
Definition: hex2otf.c:66
void cacheStringAsUTF16BE(Buffer *buf, const char *str)
Cache a string as a big-ending UTF-16 surrogate pair.
Definition: hex2otf.c:2316
#define MAX_GLYPHS
An OpenType font has at most 65536 glyphs.
Definition: hex2otf.c:85
#define VERSION
Program version, for "--version" option.
Definition: hex2otf.c:51
void addTable(Font *font, const char tag[static 4], Buffer *content)
Add a TrueType or OpenType table to the font.
Definition: hex2otf.c:694
#define B1(shift)
Set a given bit in a word.
Definition: hex2otf.c:67
ContourOp
Specify the current contour drawing operation.
Definition: hex2otf.c:1136
@ OP_POINT
Add one more (x,y) point to the contor being drawn.
Definition: hex2otf.c:1138
@ OP_CLOSE
Close the current contour path that was being drawn.
Definition: hex2otf.c:1137
void fillHheaTable(Font *font, pixels_t xMin)
Fill a "hhea" font table.
Definition: hex2otf.c:1918
void fail(const char *reason,...)
Print an error message on stderr, then exit.
Definition: hex2otf.c:113
void fillTrueType(Font *font, enum LocaFormat *format, uint_fast16_t *maxPoints, uint_fast16_t *maxContours)
Add a TrueType table to a font.
Definition: hex2otf.c:1597
void fillCFF(Font *font, int version, const NameStrings names)
Add a CFF table to a font.
Definition: hex2otf.c:1329
void fillHeadTable(Font *font, enum LocaFormat locaFormat, pixels_t xMin)
Fill a "head" font table.
Definition: hex2otf.c:1853
void initBuffers(size_t count)
Initialize an array of buffer pointers to all zeroes.
Definition: hex2otf.c:152
void cacheCFFOperand(Buffer *buf, int_fast32_t value)
Cache charstring number encoding in a CFF buffer.
Definition: hex2otf.c:460
void cacheBuffer(Buffer *restrict bufDest, const Buffer *restrict bufSrc)
Append bytes of a table to a byte buffer.
Definition: hex2otf.c:523
void buildOutline(Buffer *result, const byte bitmap[], const size_t byteCount, const enum FillSide fillSide)
Build a glyph outline.
Definition: hex2otf.c:1160
void fillCmapTable(Font *font)
Fill a "cmap" font table.
Definition: hex2otf.c:2109
#define FUPEM
Font units per em.
Definition: hex2otf.c:82
struct Font Font
Data structure to hold information for one font.
#define GLYPH_MAX_WIDTH
Maximum glyph width, in pixels.
Definition: hex2otf.c:69
FillSide
Fill to the left side (CFF) or right side (TrueType) of a contour.
Definition: hex2otf.c:1144
@ FILL_RIGHT
Draw outline clockwise (TrueType).
Definition: hex2otf.c:1146
@ FILL_LEFT
Draw outline counter-clockwise (CFF, PostScript).
Definition: hex2otf.c:1145
void fillGposTable(Font *font)
Fill a "GPOS" font table.
Definition: hex2otf.c:2241
#define BX(shift, x)
Truncate & shift word.
Definition: hex2otf.c:65
void sortGlyphs(Font *font)
Sort the glyphs in a font by Unicode code point.
Definition: hex2otf.c:1119
void fillNameTable(Font *font, NameStrings nameStrings)
Fill a "name" font table.
Definition: hex2otf.c:2366
#define PW(x)
Convert glyph byte count to pixel width.
Definition: hex2otf.c:94
#define U32MAX
Maximum UTF-32 code point value.
Definition: hex2otf.c:56
#define GLYPH_HEIGHT
Maximum glyph height, in pixels.
Definition: hex2otf.c:70
LocaFormat
Index to Location ("loca") offset information.
Definition: hex2otf.c:658
@ LOCA_OFFSET16
Offset to location is a 16-bit Offset16 value.
Definition: hex2otf.c:659
@ LOCA_OFFSET32
Offset to location is a 32-bit Offset32 value.
Definition: hex2otf.c:660
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.
Definition: hex2otf.c:554
void cacheU8(Buffer *buf, uint_fast8_t value)
Append one unsigned byte to the end of a byte array.
Definition: hex2otf.c:397
#define FU(x)
Convert pixels to font units.
Definition: hex2otf.c:91
struct Glyph Glyph
Data structure to hold data for one bitmap glyph.
#define DESCENDER
Count of pixels below baseline.
Definition: hex2otf.c:76
size_t bufferCount
Number of buffers in a Buffer * array.
Definition: hex2otf.c:140
void cacheBytes(Buffer *restrict buf, const void *restrict src, size_t count)
Append a string of bytes to a buffer.
Definition: hex2otf.c:509
void writeU32(uint_fast32_t value, FILE *file)
Write an unsigned 32-bit value to an output file.
Definition: hex2otf.c:574
void prepareOffsets(size_t *sizes)
Prepare 32-bit glyph offsets in a font table.
Definition: hex2otf.c:1275
void fillHmtxTable(Font *font)
Fill an "hmtx" font table.
Definition: hex2otf.c:2087
struct Options Options
Data structure to hold options for OpenType font output.
void printVersion()
Print program version string on stdout.
Definition: hex2otf.c:2407
Buffer * prepareStringIndex(const NameStrings names)
Prepare a font name string index.
Definition: hex2otf.c:1291
struct Table Table
Data structure for an OpenType table.
void fillBlankOutline(Font *font)
Create a dummy blank outline in a font table.
Definition: hex2otf.c:1697
void fillOS2Table(Font *font)
Fill an "OS/2" font table.
Definition: hex2otf.c:1986
int_least8_t pixels_t
This type must be able to represent max(GLYPH_MAX_WIDTH, GLYPH_HEIGHT).
Definition: hex2otf.c:100
Options parseOptions(char *const argv[const])
Parse command line options.
Definition: hex2otf.c:2500
void freeBuffer(Buffer *buf)
Free the memory previously allocated for a buffer.
Definition: hex2otf.c:337
void cleanBuffers()
Free all allocated buffer pointers.
Definition: hex2otf.c:170
#define ASCENDER
Count of pixels above baseline.
Definition: hex2otf.c:79
#define GLYPH_MAX_BYTE_COUNT
Number of bytes to represent one bitmap glyph as a binary array.
Definition: hex2otf.c:73
void readGlyphs(Font *font, const char *fileName)
Read glyph definitions from a Unifont .hex format file.
Definition: hex2otf.c:966
bool readCodePoint(uint_fast32_t *codePoint, const char *fileName, FILE *file)
Read up to 6 hexadecimal digits and a colon from file.
Definition: hex2otf.c:919
void writeBytes(const byte bytes[], size_t count, FILE *file)
Write an array of bytes to an output file.
Definition: hex2otf.c:538
void ensureBuffer(Buffer *buf, size_t needed)
Ensure that the buffer has at least the specified minimum size.
Definition: hex2otf.c:239
Buffer * newBuffer(size_t initialCapacity)
Create a new buffer.
Definition: hex2otf.c:188
int byTableTag(const void *a, const void *b)
Compare tables by 4-byte unsigned table tag value.
Definition: hex2otf.c:767
const char * matchToken(const char *operand, const char *key, char delimiter)
Match a command line option with its key for enabling.
Definition: hex2otf.c:2470
#define PRI_CP
Format string to print Unicode code point.
Definition: hex2otf.c:58
void positionGlyphs(Font *font, const char *fileName, pixels_t *xMin)
Position a glyph within a 16-by-16 pixel bounding box.
Definition: hex2otf.c:1061
void fillBitmap(Font *font)
Fill OpenType bitmap data and location tables.
Definition: hex2otf.c:1728
void fillMaxpTable(Font *font, bool isCFF, uint_fast16_t maxPoints, uint_fast16_t maxContours)
Fill a "maxp" font table.
Definition: hex2otf.c:1954
hex2otf.h - Header file for hex2otf.c
const NamePair defaultNames[]
Allocate array of NameID codes with default values.
Definition: hex2otf.h:93
Generic data structure for a linked list of buffer elements.
Definition: hex2otf.c:134
Data structure to hold information for one font.
Definition: hex2otf.c:629
Data structure to hold data for one bitmap glyph.
Definition: hex2otf.c:615
uint_least32_t codePoint
undefined for glyph 0
Definition: hex2otf.c:616
pixels_t lsb
left side bearing (x position of leftmost contour point)
Definition: hex2otf.c:622
uint_least8_t byteCount
length of bitmap data
Definition: hex2otf.c:618
byte bitmap[GLYPH_MAX_BYTE_COUNT]
hexadecimal bitmap character array
Definition: hex2otf.c:617
pixels_t pos
Definition: hex2otf.c:620
bool combining
whether this is a combining glyph
Definition: hex2otf.c:619
Data structure for a font ID number and name character string.
Definition: hex2otf.h:78
Data structure to hold options for OpenType font output.
Definition: hex2otf.c:2454
Data structure for an OpenType table.
Definition: hex2otf.c:646
Data structure for data associated with one OpenType table.
Definition: hex2otf.c:748