2 * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * DEPARTMENT OF MATHEMATICAL SCIENCES OR NEW MEXICO STATE UNIVERSITY BE
18 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #define MAX(h, i) ((h) > (i) ? (h) : (i))
32 #define MIN(l, o) ((l) < (o) ? (l) : (o))
34 /**************************************************************************
36 * Masks used for checking different bits per pixel cases.
38 **************************************************************************/
40 unsigned char bdf_onebpp[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
41 unsigned char bdf_twobpp[] = { 0xc0, 0x30, 0x0c, 0x03 };
42 unsigned char bdf_fourbpp[] = { 0xf0, 0x0f };
43 unsigned char bdf_eightbpp[] = { 0xff };
45 /**************************************************************************
47 * Default BDF font options.
49 **************************************************************************/
51 static bdf_options_t _bdf_opts = {
53 FT_LOAD_DEFAULT, /* OTF flags - hinting on. */
56 #endif /* HAVE_FREETYPE */
57 1, /* Correct metrics. */
58 1, /* Preserve unencoded glyphs. */
59 1, /* Preserve comments. */
60 1, /* Pad character-cells. */
61 BDF_PROPORTIONAL, /* Default spacing. */
62 12, /* Default point size. */
63 0, /* Default horizontal resolution. */
64 0, /* Default vertical resolution. */
65 1, /* Bits per pixel. */
66 BDF_UNIX_EOL, /* Line separator. */
67 BDF_PSF_ALL, /* PSF font export options. */
68 0, /* An X cursor font. */
71 /**************************************************************************
73 * Builtin BDF font properties.
75 **************************************************************************/
78 * List of most properties that might appear in a font. Doesn't include the
79 * AXIS_* properties in X11R6 polymorphic fonts.
81 static bdf_property_t _bdf_properties[] = {
82 {"ADD_STYLE_NAME", BDF_ATOM, 1},
83 {"AVERAGE_WIDTH", BDF_INTEGER, 1},
84 {"AVG_CAPITAL_WIDTH", BDF_INTEGER, 1},
85 {"AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1},
86 {"CAP_HEIGHT", BDF_INTEGER, 1},
87 {"CHARSET_COLLECTIONS", BDF_ATOM, 1},
88 {"CHARSET_ENCODING", BDF_ATOM, 1},
89 {"CHARSET_REGISTRY", BDF_ATOM, 1},
90 {"COMMENT", BDF_ATOM, 1},
91 {"COPYRIGHT", BDF_ATOM, 1},
92 {"DEFAULT_CHAR", BDF_CARDINAL, 1},
93 {"DESTINATION", BDF_CARDINAL, 1},
94 {"DEVICE_FONT_NAME", BDF_ATOM, 1},
95 {"END_SPACE", BDF_INTEGER, 1},
96 {"FACE_NAME", BDF_ATOM, 1},
97 {"FAMILY_NAME", BDF_ATOM, 1},
98 {"FIGURE_WIDTH", BDF_INTEGER, 1},
99 {"FONT", BDF_ATOM, 1},
100 {"FONTNAME_REGISTRY", BDF_ATOM, 1},
101 {"FONT_ASCENT", BDF_INTEGER, 1},
102 {"FONT_DESCENT", BDF_INTEGER, 1},
103 {"FOUNDRY", BDF_ATOM, 1},
104 {"FULL_NAME", BDF_ATOM, 1},
105 {"ITALIC_ANGLE", BDF_INTEGER, 1},
106 {"MAX_SPACE", BDF_INTEGER, 1},
107 {"MIN_SPACE", BDF_INTEGER, 1},
108 {"NORM_SPACE", BDF_INTEGER, 1},
109 {"NOTICE", BDF_ATOM, 1},
110 {"PIXEL_SIZE", BDF_INTEGER, 1},
111 {"POINT_SIZE", BDF_INTEGER, 1},
112 {"QUAD_WIDTH", BDF_INTEGER, 1},
113 {"RAW_ASCENT", BDF_INTEGER, 1},
114 {"RAW_AVERAGE_WIDTH", BDF_INTEGER, 1},
115 {"RAW_AVG_CAPITAL_WIDTH", BDF_INTEGER, 1},
116 {"RAW_AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1},
117 {"RAW_CAP_HEIGHT", BDF_INTEGER, 1},
118 {"RAW_DESCENT", BDF_INTEGER, 1},
119 {"RAW_END_SPACE", BDF_INTEGER, 1},
120 {"RAW_FIGURE_WIDTH", BDF_INTEGER, 1},
121 {"RAW_MAX_SPACE", BDF_INTEGER, 1},
122 {"RAW_MIN_SPACE", BDF_INTEGER, 1},
123 {"RAW_NORM_SPACE", BDF_INTEGER, 1},
124 {"RAW_PIXEL_SIZE", BDF_INTEGER, 1},
125 {"RAW_POINT_SIZE", BDF_INTEGER, 1},
126 {"RAW_PIXELSIZE", BDF_INTEGER, 1},
127 {"RAW_POINTSIZE", BDF_INTEGER, 1},
128 {"RAW_QUAD_WIDTH", BDF_INTEGER, 1},
129 {"RAW_SMALL_CAP_SIZE", BDF_INTEGER, 1},
130 {"RAW_STRIKEOUT_ASCENT", BDF_INTEGER, 1},
131 {"RAW_STRIKEOUT_DESCENT", BDF_INTEGER, 1},
132 {"RAW_SUBSCRIPT_SIZE", BDF_INTEGER, 1},
133 {"RAW_SUBSCRIPT_X", BDF_INTEGER, 1},
134 {"RAW_SUBSCRIPT_Y", BDF_INTEGER, 1},
135 {"RAW_SUPERSCRIPT_SIZE", BDF_INTEGER, 1},
136 {"RAW_SUPERSCRIPT_X", BDF_INTEGER, 1},
137 {"RAW_SUPERSCRIPT_Y", BDF_INTEGER, 1},
138 {"RAW_UNDERLINE_POSITION", BDF_INTEGER, 1},
139 {"RAW_UNDERLINE_THICKNESS", BDF_INTEGER, 1},
140 {"RAW_X_HEIGHT", BDF_INTEGER, 1},
141 {"RELATIVE_SETWIDTH", BDF_CARDINAL, 1},
142 {"RELATIVE_WEIGHT", BDF_CARDINAL, 1},
143 {"RESOLUTION", BDF_INTEGER, 1},
144 {"RESOLUTION_X", BDF_CARDINAL, 1},
145 {"RESOLUTION_Y", BDF_CARDINAL, 1},
146 {"SETWIDTH_NAME", BDF_ATOM, 1},
147 {"SLANT", BDF_ATOM, 1},
148 {"SMALL_CAP_SIZE", BDF_INTEGER, 1},
149 {"SPACING", BDF_ATOM, 1},
150 {"STRIKEOUT_ASCENT", BDF_INTEGER, 1},
151 {"STRIKEOUT_DESCENT", BDF_INTEGER, 1},
152 {"SUBSCRIPT_SIZE", BDF_INTEGER, 1},
153 {"SUBSCRIPT_X", BDF_INTEGER, 1},
154 {"SUBSCRIPT_Y", BDF_INTEGER, 1},
155 {"SUPERSCRIPT_SIZE", BDF_INTEGER, 1},
156 {"SUPERSCRIPT_X", BDF_INTEGER, 1},
157 {"SUPERSCRIPT_Y", BDF_INTEGER, 1},
158 {"UNDERLINE_POSITION", BDF_INTEGER, 1},
159 {"UNDERLINE_THICKNESS", BDF_INTEGER, 1},
160 {"WEIGHT", BDF_CARDINAL, 1},
161 {"WEIGHT_NAME", BDF_ATOM, 1},
162 {"X_HEIGHT", BDF_INTEGER, 1},
163 {"_MULE_BASELINE_OFFSET", BDF_INTEGER, 1},
164 {"_MULE_RELATIVE_COMPOSE", BDF_INTEGER, 1},
166 * Throw this in to make it clear.
168 {"_XMBDFED_INFO", BDF_ATOM, 1},
171 static unsigned int _num_bdf_properties =
172 sizeof(_bdf_properties) / sizeof(_bdf_properties[0]);
175 * User defined properties.
177 static bdf_property_t *user_props;
178 static unsigned int nuser_props = 0;
180 /**************************************************************************
182 * Hash table utilities for the properties.
184 **************************************************************************/
186 #define INITIAL_HT_SIZE 241
191 } _hashnode, *hashnode;
200 typedef void (*hash_free_func)(hashnode node);
203 hash_bucket(char *key, hashtable *ht)
206 unsigned int res = 0;
207 hashnode *bp = ht->table, *ndp;
210 * Mocklisp hash function.
213 res = (res << 5) - res + *kp++;
215 ndp = bp + (res % ht->size);
218 if (kp[0] == key[0] && strcmp(kp, key) == 0)
222 ndp = bp + (ht->size - 1);
228 hash_rehash(hashtable *ht)
230 hashnode *obp = ht->table, *bp, *nbp;
231 int i, sz = ht->size;
234 ht->limit = ht->size / 3;
235 ht->table = (hashnode *) malloc(sizeof(hashnode) * ht->size);
236 (void) memset((char *) ht->table, 0, sizeof(hashnode) * ht->size);
238 for (i = 0, bp = obp; i < sz; i++, bp++) {
240 nbp = hash_bucket((*bp)->key, ht);
248 hash_init(hashtable *ht)
250 int sz = INITIAL_HT_SIZE;
255 ht->table = (hashnode *) malloc(sizeof(hashnode) * sz);
256 (void) memset((char *) ht->table, 0, sizeof(hashnode) * sz);
260 hash_free(hashtable *ht)
262 int i, sz = ht->size;
263 hashnode *bp = ht->table;
265 for (i = 0; i < sz; i++, bp++) {
270 free((char *) ht->table);
274 hash_insert(char *key, void *data, hashtable *ht)
276 hashnode nn, *bp = hash_bucket(key, ht);
280 *bp = nn = (hashnode) malloc(sizeof(_hashnode));
284 if (ht->used >= ht->limit)
292 hash_lookup(char *key, hashtable *ht)
294 hashnode *np = hash_bucket(key, ht);
299 hash_delete(char *name, hashtable *ht)
303 hp = hash_bucket(name, ht);
311 * The builtin property table.
313 static hashtable proptbl;
315 /**************************************************************************
317 * Utility types and functions.
319 **************************************************************************/
322 * Function type for parsing lines of a BDF font.
324 typedef int (*_bdf_line_func_t)(
326 unsigned int linelen,
333 * List structure for splitting lines into fields.
345 * Structure used while loading BDF fonts.
363 bdf_callback_t callback;
364 bdf_callback_struct_t cb;
365 unsigned int have[2048];
369 #define setsbit(m, cc) (m[(cc) >> 3] |= (1 << ((cc) & 7)))
370 #define sbitset(m, cc) (m[(cc) >> 3] & (1 << ((cc) & 7)))
373 * An empty string for empty fields.
375 static char empty[1] = { 0 };
378 * Assume the line is NULL terminated and that the `list' parameter was
379 * initialized the first time it was used.
382 _bdf_split(char *separators, char *line, unsigned int linelen,
385 int mult, final_empty;
387 unsigned char seps[32];
390 * Initialize the list.
392 list->used = list->bused = 0;
395 * If the line is empty, then simply return.
397 if (linelen == 0 || line[0] == 0)
401 * If the `separators' parameter is NULL or empty, split the list into
404 if (separators == 0 || *separators == 0) {
405 if (linelen > list->bsize) {
407 list->bfield = (char *) malloc(linelen);
409 list->bfield = (char *) realloc(list->bfield, linelen);
410 list->bsize = linelen;
412 list->bused = linelen;
413 (void) memcpy(list->bfield, line, linelen);
418 * Prepare the separator bitmap.
420 (void) memset((char *) seps, 0, 32);
423 * If the very last character of the separator string is a plus, then set
424 * the `mult' flag to indicate that multiple separators should be
425 * collapsed into one.
427 for (mult = 0, sp = separators; sp && *sp; sp++) {
428 if (*sp == '+' && *(sp + 1) == 0)
435 * Break the line up into fields.
437 for (final_empty = 0, sp = ep = line, end = sp + linelen;
440 * Collect everything that is not a separator.
442 for (; *ep && !sbitset(seps, *ep); ep++) ;
445 * Resize the list if necessary.
447 if (list->used == list->size) {
449 list->field = (char **) malloc(sizeof(char *) * 5);
451 list->field = (char **)
452 realloc((char *) list->field,
453 sizeof(char *) * (list->size + 5));
459 * Assign the field appropriately.
461 list->field[list->used++] = (ep > sp) ? sp : empty;
466 * If multiple separators should be collapsed, do it now by
467 * setting all the separator characters to 0.
469 for (; *ep && sbitset(seps, *ep); ep++)
473 * Don't collapse multiple separators by making them 0, so just
474 * make the one encountered 0.
477 final_empty = (ep > sp && *ep == 0);
482 * Finally, NULL terminate the list.
484 if (list->used + final_empty + 1 >= list->size) {
485 if (list->used == list->size) {
487 list->field = (char **) malloc(sizeof(char *) * 5);
489 list->field = (char **)
490 realloc((char *) list->field,
491 sizeof(char *) * (list->size + 5));
496 list->field[list->used++] = empty;
498 if (list->used == list->size) {
500 list->field = (char **) malloc(sizeof(char *) * 5);
502 list->field = (char **)
503 realloc((char *) list->field,
504 sizeof(char *) * (list->size + 5));
507 list->field[list->used] = 0;
511 _bdf_shift(unsigned int n, _bdf_list_t *list)
515 if (list == 0 || list->used == 0 || n == 0)
518 if (n >= list->used) {
522 for (u = n, i = 0; u < list->used; i++, u++)
523 list->field[i] = list->field[u];
528 _bdf_join(int c, unsigned int *len, _bdf_list_t *list)
533 if (list == 0 || list->used == 0)
539 for (i = j = 0; i < list->used; i++) {
543 if (i + 1 < list->used)
553 * High speed file reader that passes each line to a callback.
556 _bdf_readlines(int fd, _bdf_line_func_t callback, void *client_data,
561 int n, res, done, refill, bytes, hold;
562 char *ls, *le, *pp, *pe, *hp;
574 while (!done && (n = read(fd, pp, bytes)) > 0) {
576 * Determine the new end of the buffer pages.
580 for (refill = 0; done == 0 && refill == 0; ) {
581 while (le < pe && *le != '\n' && *le != '\r')
586 * Hit the end of the last page in the buffer. Need to find
587 * out how many pages to shift and how many pages need to be
588 * read in. Adjust the line start and end pointers down to
589 * point to the right places in the pages.
591 pp = buf + (((ls - buf) >> 13) << 13);
605 * Temporarily NULL terminate the line.
611 if (callback && *ls != '#' && *ls != 0x1a && le > ls &&
612 (res = (*cb)(ls, le - ls, lineno, (void *) &cb,
618 * Handle the case of DOS crlf sequences.
620 if (le < pe && hold == '\n' && *le =='\r')
625 * Increment the line number.
630 * Restore the character at the end of the line.
641 _bdf_strdup(unsigned char *s, unsigned int len)
645 if (s == 0 || len == 0)
648 ns = (unsigned char *) malloc(len);
649 (void) memcpy((char *) ns, (char *) s, len);
654 _bdf_memmove(char *dest, char *src, unsigned int bytes)
663 * Do a memmove using Ye Olde Duff's Device for efficiency.
672 case 7: *--dest = *--src;
673 case 6: *--dest = *--src;
674 case 5: *--dest = *--src;
675 case 4: *--dest = *--src;
676 case 3: *--dest = *--src;
677 case 2: *--dest = *--src;
678 case 1: *--dest = *--src;
681 } else if (src > dest) {
685 case 7: *dest++ = *src++;
686 case 6: *dest++ = *src++;
687 case 5: *dest++ = *src++;
688 case 4: *dest++ = *src++;
689 case 3: *dest++ = *src++;
690 case 2: *dest++ = *src++;
691 case 1: *dest++ = *src++;
697 static unsigned char a2i[128] = {
698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,
704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
711 static unsigned char odigits[32] = {
712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
718 static unsigned char ddigits[32] = {
719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
721 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
725 static unsigned char hdigits[32] = {
726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
727 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 #define isdigok(m, d) (m[(d) >> 3] & (1 << ((d) & 7)))
735 * Routine to convert an ASCII string into an unsigned int integer.
738 _bdf_atoul(char *s, char **end, int base)
743 if (s == 0 || *s == 0)
747 * Make sure the radix is something recognizable. Default to 10.
750 case 8: dmap = odigits; break;
751 case 16: dmap = hdigits; break;
752 default: base = 10; dmap = ddigits; break;
756 * Check for the special hex prefixes of 0[xX] or [Uu][+-].
758 if ((*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) ||
759 ((*s == 'U' || *s == 'u') && (*(s + 1) == '+' || *(s + 1) == '-'))) {
765 for (v = 0; isdigok(dmap, *s); s++)
766 v = (v * base) + a2i[(int) *s];
775 * Routine to convert an ASCII string into an signed int integer.
778 _bdf_atol(char *s, char **end, int base)
783 if (s == 0 || *s == 0)
787 * Make sure the radix is something recognizable. Default to 10.
790 case 8: dmap = odigits; break;
791 case 16: dmap = hdigits; break;
792 default: base = 10; dmap = ddigits; break;
796 * Check for a minus sign.
805 * Check for the special hex prefix.
807 if ((*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) ||
808 ((*s == 'U' || *s == 'u') && (*(s + 1) == '+' || *(s + 1) == '-'))) {
814 for (v = 0; isdigok(dmap, *s); s++)
815 v = (v * base) + a2i[(int) *s];
820 return (!neg) ? v : -v;
824 * Routine to convert an ASCII string into an signed short integer.
827 _bdf_atos(char *s, char **end, int base)
832 if (s == 0 || *s == 0)
836 * Make sure the radix is something recognizable. Default to 10.
839 case 8: dmap = odigits; break;
840 case 16: dmap = hdigits; break;
841 default: base = 10; dmap = ddigits; break;
854 * Check for the special hex prefix.
856 if (*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) {
862 for (v = 0; isdigok(dmap, *s); s++)
863 v = (v * base) + a2i[(int) *s];
868 return (!neg) ? v : -v;
872 * Routine to compare two glyphs by encoding so they can be sorted.
875 by_encoding(const void *a, const void *b)
877 bdf_glyph_t *c1, *c2;
879 c1 = (bdf_glyph_t *) a;
880 c2 = (bdf_glyph_t *) b;
881 if (c1->encoding < c2->encoding)
883 else if (c1->encoding > c2->encoding)
888 /**************************************************************************
890 * BDF font file parsing flags and functions.
892 **************************************************************************/
897 #define _BDF_START 0x0001
898 #define _BDF_FONT_NAME 0x0002
899 #define _BDF_SIZE 0x0004
900 #define _BDF_FONT_BBX 0x0008
901 #define _BDF_PROPS 0x0010
902 #define _BDF_GLYPHS 0x0020
903 #define _BDF_GLYPH 0x0040
904 #define _BDF_ENCODING 0x0080
905 #define _BDF_SWIDTH 0x0100
906 #define _BDF_DWIDTH 0x0200
907 #define _BDF_BBX 0x0400
908 #define _BDF_BITMAP 0x0800
910 #define _BDF_SWIDTH_ADJ 0x1000
912 #define _BDF_GLYPH_BITS (_BDF_GLYPH|_BDF_ENCODING|_BDF_SWIDTH|\
913 _BDF_DWIDTH|_BDF_BBX|_BDF_BITMAP)
915 #define _BDF_GLYPH_WIDTH_CHECK 0x40000000
916 #define _BDF_GLYPH_HEIGHT_CHECK 0x80000000
919 * Auto correction messages.
921 #define ACMSG1 "FONT_ASCENT property missing. Added \"FONT_ASCENT %hd\"."
922 #define ACMSG2 "FONT_DESCENT property missing. Added \"FONT_DESCENT %hd\"."
923 #define ACMSG3 "Font width != actual width. Old: %hd New: %hd."
924 #define ACMSG4 "Font left bearing != actual left bearing. Old: %hd New: %hd."
925 #define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd."
926 #define ACMSG6 "Font descent != actual descent. Old: %hd New: %hd."
927 #define ACMSG7 "Font height != actual height. Old: %hd New: %hd."
928 #define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made."
929 #define ACMSG9 "SWIDTH field missing at line %d. Set automatically."
930 #define ACMSG10 "DWIDTH field missing at line %d. Set to glyph width."
931 #define ACMSG11 "SIZE bits per pixel field adjusted to %hd."
932 #define ACMSG12 "Duplicate encoding %d (%s) changed to unencoded."
933 #define ACMSG13 "Glyph %d extra rows removed."
934 #define ACMSG14 "Glyph %d extra columns removed."
935 #define ACMSG15 "Incorrect glyph count: %d indicated but %d found."
940 #define ERRMSG1 "[line %d] Missing \"%s\" line."
941 #define ERRMSG2 "[line %d] Font header corrupted or missing fields."
942 #define ERRMSG3 "[line %d] Font glyphs corrupted or missing fields."
945 _bdf_add_acmsg(bdf_font_t *font, char *msg, unsigned int len)
949 if (font->acmsgs_len == 0)
950 font->acmsgs = (char *) malloc(len + 2);
952 font->acmsgs = (char *) realloc(font->acmsgs,
953 font->acmsgs_len + len + 2);
955 cp = font->acmsgs + font->acmsgs_len;
956 (void) memcpy(cp, msg, len);
960 font->acmsgs_len += len + 1;
964 _bdf_add_comment(bdf_font_t *font, char *comment, unsigned int len)
968 if (font->comments_len == 0)
969 font->comments = (char *) malloc(len + 2);
971 font->comments = (char *) realloc(font->comments,
972 font->comments_len + len + 2);
974 cp = font->comments + font->comments_len;
975 (void) memcpy(cp, comment, len);
979 font->comments_len += len + 1;
983 * Set the spacing from the font name if it exists, or set it to the default
984 * specified in the options.
987 _bdf_set_default_spacing(bdf_font_t *font, bdf_options_t *opts)
993 if (font == 0 || font->name == 0 || font->name[0] == 0)
996 font->spacing = opts->font_spacing;
998 len = (unsigned int) (strlen(font->name) + 1);
999 (void) memcpy(name, font->name, len);
1000 list.size = list.used = 0;
1001 _bdf_split("-", name, len, &list);
1002 if (list.used == 15) {
1003 switch (list.field[11][0]) {
1004 case 'C': case 'c': font->spacing = BDF_CHARCELL; break;
1005 case 'M': case 'm': font->spacing = BDF_MONOWIDTH; break;
1006 case 'P': case 'p': font->spacing = BDF_PROPORTIONAL; break;
1010 free((char *) list.field);
1014 * Determine if the property is an atom or not. If it is, then clean it up so
1015 * the double quotes are removed if they exist.
1018 _bdf_is_atom(char *line, unsigned int linelen, char **name, char **value)
1024 *name = sp = ep = line;
1025 while (*ep && *ep != ' ' && *ep != '\t')
1034 p = bdf_get_property(sp);
1037 * Restore the character that was saved before any return can happen.
1043 * If the propert exists and is not an atom, just return here.
1045 if (p && p->format != BDF_ATOM)
1049 * The property is an atom. Trim all leading and trailing whitespace and
1050 * double quotes for the atom value.
1053 ep = line + linelen;
1056 * Trim the leading whitespace if it exists.
1059 while (*sp && (*sp == ' ' || *sp == '\t'))
1063 * Trim the leading double quote if it exists.
1070 * Trim the trailing whitespace if it exists.
1072 while (ep > sp && (*(ep - 1) == ' ' || *(ep - 1) == '\t'))
1076 * Trim the trailing double quote if it exists.
1078 if (ep > sp && *(ep - 1) == '"')
1085 _bdf_add_property(bdf_font_t *font, char *name, char *value)
1087 unsigned int propid;
1090 bdf_property_t *prop, *fp;
1093 * First, check to see if the property already exists in the font.
1095 if ((hn = hash_lookup(name, (hashtable *) font->internal)) != 0) {
1097 * The property already exists in the font, so simply replace
1098 * the value of the property with the current value.
1100 fp = font->props + (unsigned int) hn->data;
1102 switch (fp->format) {
1105 * Delete the current atom if it exists.
1107 if (fp->value.atom != 0)
1108 free(fp->value.atom);
1113 len = strlen(value) + 1;
1115 fp->value.atom = (char *) malloc(len);
1116 (void) memcpy(fp->value.atom, value, len);
1121 fp->value.int32 = _bdf_atol(value, 0, 10);
1124 fp->value.card32 = _bdf_atoul(value, 0, 10);
1131 * See if this property type exists yet or not. If not, create it.
1133 hn = hash_lookup(name, &proptbl);
1135 bdf_create_property(name, BDF_ATOM);
1136 hn = hash_lookup(name, &proptbl);
1140 * Allocate another property if this is overflow.
1142 if (font->props_used == font->props_size) {
1143 if (font->props_size == 0)
1144 font->props = (bdf_property_t *) malloc(sizeof(bdf_property_t));
1146 font->props = (bdf_property_t *)
1147 realloc((char *) font->props, sizeof(bdf_property_t) *
1148 (font->props_size + 1));
1149 fp = font->props + font->props_size;
1150 (void) memset((char *) fp, 0, sizeof(bdf_property_t));
1154 propid = (unsigned int) hn->data;
1155 if (propid >= _num_bdf_properties)
1156 prop = user_props + (propid - _num_bdf_properties);
1158 prop = _bdf_properties + propid;
1160 fp = font->props + font->props_used;
1162 fp->name = prop->name;
1163 fp->format = prop->format;
1164 fp->builtin = prop->builtin;
1166 switch (prop->format) {
1171 len = strlen(value) + 1;
1173 fp->value.atom = (char *) malloc(len);
1174 (void) memcpy(fp->value.atom, value, len);
1179 fp->value.int32 = _bdf_atol(value, 0, 10);
1182 fp->value.card32 = _bdf_atoul(value, 0, 10);
1187 * If the property happens to be a comment, then it doesn't need
1188 * to be added to the internal hash table.
1190 if (memcmp(name, "COMMENT", 7) != 0)
1192 * Add the property to the font property table.
1194 hash_insert(fp->name, (void *) font->props_used,
1195 (hashtable *) font->internal);
1200 * Some special cases need to be handled here. The DEFAULT_CHAR property
1201 * needs to be located if it exists in the property list, the FONT_ASCENT
1202 * and FONT_DESCENT need to be assigned if they are present, and the
1203 * SPACING property should override the default spacing.
1205 if (memcmp(name, "DEFAULT_CHAR", 12) == 0)
1206 font->default_glyph = fp->value.int32;
1207 else if (memcmp(name, "FONT_ASCENT", 11) == 0)
1208 font->font_ascent = fp->value.int32;
1209 else if (memcmp(name, "FONT_DESCENT", 12) == 0)
1210 font->font_descent = fp->value.int32;
1211 else if (memcmp(name, "SPACING", 7) == 0) {
1212 if (fp->value.atom[0] == 'p' || fp->value.atom[0] == 'P')
1213 font->spacing = BDF_PROPORTIONAL;
1214 else if (fp->value.atom[0] == 'm' || fp->value.atom[0] == 'M')
1215 font->spacing = BDF_MONOWIDTH;
1216 else if (fp->value.atom[0] == 'c' || fp->value.atom[0] == 'C')
1217 font->spacing = BDF_CHARCELL;
1222 * Actually parse the glyph info and bitmaps.
1225 _bdf_parse_glyphs(char *line, unsigned int linelen, unsigned int lineno,
1226 void *call_data, void *client_data)
1231 unsigned int i, slen = 0, nibbles;
1232 double ps, rx, dw, sw;
1233 _bdf_line_func_t *next;
1239 next = (_bdf_line_func_t *) call_data;
1240 p = (_bdf_parse_t *) client_data;
1245 * Check for a comment.
1247 if (memcmp(line, "COMMENT", 7) == 0) {
1254 _bdf_add_comment(p->font, s, linelen);
1259 * The very first thing expected is the number of glyphs.
1261 if (!(p->flags & _BDF_GLYPHS)) {
1262 if (memcmp(line, "CHARS", 5) != 0) {
1263 sprintf(nbuf, ERRMSG1, lineno, "CHARS");
1264 _bdf_add_acmsg(p->font, nbuf, strlen(nbuf));
1265 return BDF_MISSING_CHARS;
1267 _bdf_split(" +", line, linelen, &p->list);
1268 p->cnt = font->glyphs_size = _bdf_atoul(p->list.field[1], 0, 10);
1271 * Make sure the number of glyphs is non-zero.
1274 font->glyphs_size = 64;
1276 font->glyphs = (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) *
1279 * Make sure the glyph structures are initialized.
1281 (void) memset((char *) font->glyphs, 0,
1282 sizeof(bdf_glyph_t) * font->glyphs_size);
1285 * Set up the callback to indicate the glyph loading is about to
1288 if (p->callback != 0) {
1289 p->cb.reason = BDF_LOAD_START;
1290 p->cb.total = p->cnt;
1292 (*p->callback)(&p->cb, p->client_data);
1294 p->flags |= _BDF_GLYPHS;
1299 * Check for the ENDFONT field.
1301 if (memcmp(line, "ENDFONT", 7) == 0) {
1303 * Sort the glyphs by encoding.
1305 qsort((char *) font->glyphs, font->glyphs_used, sizeof(bdf_glyph_t),
1308 p->flags &= ~_BDF_START;
1313 * Check for the ENDCHAR field.
1315 if (memcmp(line, "ENDCHAR", 7) == 0) {
1317 * Set up and call the callback if it was passed.
1319 if (p->callback != 0) {
1320 p->cb.reason = BDF_LOADING;
1321 p->cb.total = font->glyphs_size;
1322 p->cb.current = font->glyphs_used;
1323 (*p->callback)(&p->cb, p->client_data);
1326 p->flags &= ~_BDF_GLYPH_BITS;
1331 * Check to see if a glyph is being scanned but should be ignored
1332 * because it is an unencoded glyph.
1334 if ((p->flags & _BDF_GLYPH) &&
1335 p->glyph_enc == -1 && p->opts->keep_unencoded == 0)
1339 * Check for the STARTCHAR field.
1341 if (memcmp(line, "STARTCHAR", 9) == 0) {
1343 * Set the character name in the parse info first until the
1344 * encoding can be checked for an unencoded character.
1346 if (p->glyph_name != 0)
1347 free(p->glyph_name);
1348 _bdf_split(" +", line, linelen, &p->list);
1349 _bdf_shift(1, &p->list);
1350 s = _bdf_join(' ', &slen, &p->list);
1351 p->glyph_name = (char *) malloc(slen + 1);
1352 (void) memcpy(p->glyph_name, s, slen + 1);
1353 p->flags |= _BDF_GLYPH;
1358 * Check for the ENCODING field.
1360 if (memcmp(line, "ENCODING", 8) == 0) {
1361 if (!(p->flags & _BDF_GLYPH)) {
1363 * Missing STARTCHAR field.
1365 sprintf(nbuf, ERRMSG1, lineno, "STARTCHAR");
1366 _bdf_add_acmsg(font, nbuf, strlen(nbuf));
1367 return BDF_MISSING_STARTCHAR;
1369 _bdf_split(" +", line, linelen, &p->list);
1370 p->glyph_enc = _bdf_atol(p->list.field[1], 0, 10);
1373 * Check to see if this encoding has already been encountered. If it
1374 * has then change it to unencoded so it gets added if indicated.
1376 if (p->glyph_enc >= 0) {
1377 if (_bdf_glyph_modified(p->have, p->glyph_enc)) {
1379 * Add a message saying a glyph has been moved to the
1382 sprintf(nbuf, ACMSG12, p->glyph_enc, p->glyph_name);
1383 _bdf_add_acmsg(font, nbuf, strlen(nbuf));
1387 _bdf_set_glyph_modified(p->have, p->glyph_enc);
1390 if (p->glyph_enc >= 0) {
1392 * Make sure there are enough glyphs allocated in case the
1393 * number of characters happen to be wrong.
1395 if (font->glyphs_used == font->glyphs_size) {
1396 font->glyphs = (bdf_glyph_t *)
1397 realloc((char *) font->glyphs,
1398 sizeof(bdf_glyph_t) * (font->glyphs_size + 64));
1399 (void) memset((char *) (font->glyphs + font->glyphs_size),
1400 0, sizeof(bdf_glyph_t) << 6);
1401 font->glyphs_size += 64;
1404 glyph = font->glyphs + font->glyphs_used++;
1405 glyph->name = p->glyph_name;
1406 glyph->encoding = p->glyph_enc;
1409 * Reset the initial glyph info.
1414 * Unencoded glyph. Check to see if it should be added or not.
1416 if (p->opts->keep_unencoded != 0) {
1418 * Allocate the next unencoded glyph.
1420 if (font->unencoded_used == font->unencoded_size) {
1421 if (font->unencoded_size == 0)
1422 font->unencoded = (bdf_glyph_t *)
1423 malloc(sizeof(bdf_glyph_t) << 2);
1425 font->unencoded = (bdf_glyph_t *)
1426 realloc((char *) font->unencoded,
1427 sizeof(bdf_glyph_t) *
1428 (font->unencoded_size + 4));
1429 font->unencoded_size += 4;
1432 glyph = font->unencoded + font->unencoded_used;
1433 glyph->name = p->glyph_name;
1434 glyph->encoding = font->unencoded_used++;
1437 * Free up the glyph name if the unencoded shouldn't be
1440 free(p->glyph_name);
1446 * Clear the flags that might be added when width and height are
1447 * checked for consistency.
1449 p->flags &= ~(_BDF_GLYPH_WIDTH_CHECK|_BDF_GLYPH_HEIGHT_CHECK);
1451 p->flags |= _BDF_ENCODING;
1456 * Point at the glyph being constructed.
1458 if (p->glyph_enc == -1)
1459 glyph = font->unencoded + (font->unencoded_used - 1);
1461 glyph = font->glyphs + (font->glyphs_used - 1);
1464 * Check to see if a bitmap is being constructed.
1466 if (p->flags & _BDF_BITMAP) {
1468 * If there are more rows than are specified in the glyph metrics,
1469 * ignore the remaining lines.
1471 if (p->row >= glyph->bbx.height) {
1472 if (!(p->flags & _BDF_GLYPH_HEIGHT_CHECK)) {
1473 sprintf(nbuf, ACMSG13, glyph->encoding);
1474 _bdf_add_acmsg(font, nbuf, strlen(nbuf));
1475 p->flags |= _BDF_GLYPH_HEIGHT_CHECK;
1482 * Only collect the number of nibbles indicated by the glyph metrics.
1483 * If there are more columns, they are simply ignored.
1485 nibbles = p->bpr << 1;
1486 bp = glyph->bitmap + (p->row * p->bpr);
1487 for (i = 0, *bp = 0; i < nibbles; i++) {
1489 *bp = (*bp << 4) + a2i[c];
1490 if (i + 1 < nibbles && (i & 1))
1495 * If any line has extra columns, indicate they have been removed.
1497 if ((line[nibbles] == '0' || a2i[(int) line[nibbles]] != 0) &&
1498 !(p->flags & _BDF_GLYPH_WIDTH_CHECK)) {
1499 sprintf(nbuf, ACMSG14, glyph->encoding);
1500 _bdf_add_acmsg(font, nbuf, strlen(nbuf));
1501 p->flags |= _BDF_GLYPH_WIDTH_CHECK;
1510 * Expect the SWIDTH (scalable width) field next.
1512 if (memcmp(line, "SWIDTH", 6) == 0) {
1513 if (!(p->flags & _BDF_ENCODING)) {
1515 * Missing ENCODING field.
1517 sprintf(nbuf, ERRMSG1, lineno, "ENCODING");
1518 _bdf_add_acmsg(font, nbuf, strlen(nbuf));
1519 return BDF_MISSING_ENCODING;
1521 _bdf_split(" +", line, linelen, &p->list);
1522 glyph->swidth = _bdf_atoul(p->list.field[1], 0, 10);
1523 p->flags |= _BDF_SWIDTH;
1528 * Expect the DWIDTH (scalable width) field next.
1530 if (memcmp(line, "DWIDTH", 6) == 0) {
1531 _bdf_split(" +", line, linelen, &p->list);
1532 glyph->dwidth = _bdf_atoul(p->list.field[1], 0, 10);
1534 if (!(p->flags & _BDF_SWIDTH)) {
1536 * Missing SWIDTH field. Add an auto correction message and set
1537 * the scalable width from the device width.
1539 sprintf(nbuf, ACMSG9, lineno);
1540 _bdf_add_acmsg(font, nbuf, strlen(nbuf));
1541 ps = (double) font->point_size;
1542 rx = (double) font->resolution_x;
1543 dw = (double) glyph->dwidth;
1544 glyph->swidth = (unsigned short) ((dw * 72000.0) / (ps * rx));
1547 p->flags |= _BDF_DWIDTH;
1552 * Expect the BBX field next.
1554 if (memcmp(line, "BBX", 3) == 0) {
1555 _bdf_split(" +", line, linelen, &p->list);
1556 glyph->bbx.width = _bdf_atos(p->list.field[1], 0, 10);
1557 glyph->bbx.height = _bdf_atos(p->list.field[2], 0, 10);
1558 glyph->bbx.x_offset = _bdf_atos(p->list.field[3], 0, 10);
1559 glyph->bbx.y_offset = _bdf_atos(p->list.field[4], 0, 10);
1562 * Generate the ascent and descent of the character.
1564 glyph->bbx.ascent = glyph->bbx.height + glyph->bbx.y_offset;
1565 glyph->bbx.descent = -glyph->bbx.y_offset;
1568 * Determine the overall font bounding box as the characters are
1569 * loaded so corrections can be done later if indicated.
1571 p->maxas = MAX(glyph->bbx.ascent, p->maxas);
1572 p->maxds = MAX(glyph->bbx.descent, p->maxds);
1573 p->rbearing = glyph->bbx.width + glyph->bbx.x_offset;
1574 p->maxrb = MAX(p->rbearing, p->maxrb);
1575 p->minlb = MIN(glyph->bbx.x_offset, p->minlb);
1576 p->maxlb = MAX(glyph->bbx.x_offset, p->maxlb);
1578 if (!(p->flags & _BDF_DWIDTH)) {
1580 * Missing DWIDTH field. Add an auto correction message and set
1581 * the device width to the glyph width.
1583 sprintf(nbuf, ACMSG10, lineno);
1584 _bdf_add_acmsg(font, nbuf, strlen(nbuf));
1585 glyph->dwidth = glyph->bbx.width;
1589 * If the BDF_CORRECT_METRICS flag is set, then adjust the SWIDTH
1590 * value if necessary.
1592 if (p->opts->correct_metrics != 0) {
1594 * Determine the point size of the glyph.
1596 ps = (double) font->point_size;
1597 rx = (double) font->resolution_x;
1598 dw = (double) glyph->dwidth;
1599 sw = (unsigned short) ((dw * 72000.0) / (ps * rx));
1601 if (sw != glyph->swidth) {
1603 if (p->glyph_enc == -1)
1604 _bdf_set_glyph_modified(font->umod,
1605 font->unencoded_used - 1);
1607 _bdf_set_glyph_modified(font->nmod, glyph->encoding);
1608 p->flags |= _BDF_SWIDTH_ADJ;
1612 p->flags |= _BDF_BBX;
1617 * And finally, gather up the bitmap.
1619 if (memcmp(line, "BITMAP", 6) == 0) {
1620 if (!(p->flags & _BDF_BBX)) {
1622 * Missing BBX field.
1624 sprintf(nbuf, ERRMSG1, lineno, "BBX");
1625 _bdf_add_acmsg(font, nbuf, strlen(nbuf));
1626 return BDF_MISSING_BBX;
1629 * Allocate enough space for the bitmap.
1631 p->bpr = ((glyph->bbx.width * p->font->bpp) + 7) >> 3;
1632 glyph->bytes = p->bpr * glyph->bbx.height;
1633 glyph->bitmap = (unsigned char *) malloc(glyph->bytes);
1635 p->flags |= _BDF_BITMAP;
1639 return BDF_INVALID_LINE;
1643 * Load the font properties.
1646 _bdf_parse_properties(char *line, unsigned int linelen, unsigned int lineno,
1647 void *call_data, void *client_data)
1650 _bdf_line_func_t *next;
1652 char *name, *value, nbuf[128];
1654 next = (_bdf_line_func_t *) call_data;
1655 p = (_bdf_parse_t *) client_data;
1658 * Check for the end of the properties.
1660 if (memcmp(line, "ENDPROPERTIES", 13) == 0) {
1662 * If the FONT_ASCENT or FONT_DESCENT properties have not been
1663 * encountered yet, then make sure they are added as properties and
1664 * make sure they are set from the font bounding box info.
1666 * This is *always* done regardless of the options, because X11
1667 * requires these two fields to compile fonts.
1669 if (bdf_get_font_property(p->font, "FONT_ASCENT") == 0) {
1670 p->font->font_ascent = p->font->bbx.ascent;
1671 sprintf(nbuf, "%hd", p->font->bbx.ascent);
1672 _bdf_add_property(p->font, "FONT_ASCENT", nbuf);
1673 sprintf(nbuf, ACMSG1, p->font->bbx.ascent);
1674 _bdf_add_acmsg(p->font, nbuf, strlen(nbuf));
1675 p->font->modified = 1;
1677 if (bdf_get_font_property(p->font, "FONT_DESCENT") == 0) {
1678 p->font->font_descent = p->font->bbx.descent;
1679 sprintf(nbuf, "%hd", p->font->bbx.descent);
1680 _bdf_add_property(p->font, "FONT_DESCENT", nbuf);
1681 sprintf(nbuf, ACMSG2, p->font->bbx.descent);
1682 _bdf_add_acmsg(p->font, nbuf, strlen(nbuf));
1683 p->font->modified = 1;
1685 p->flags &= ~_BDF_PROPS;
1686 *next = _bdf_parse_glyphs;
1691 * Ignore the _XFREE86_GLYPH_RANGES and _XMBDFED_INFO properties.
1693 if (memcmp(line, "_XFREE86_GLYPH_RANGES", 21) == 0 ||
1694 memcmp(line, "_XMBDFED_INFO", 13) == 0)
1698 * Handle COMMENT fields and properties in a special way to preserve
1701 if (memcmp(line, "COMMENT", 7) == 0) {
1702 name = value = line;
1706 _bdf_add_property(p->font, name, value);
1707 } else if (_bdf_is_atom(line, linelen, &name, &value))
1708 _bdf_add_property(p->font, name, value);
1710 _bdf_split(" +", line, linelen, &p->list);
1711 name = p->list.field[0];
1712 _bdf_shift(1, &p->list);
1713 value = _bdf_join(' ', &vlen, &p->list);
1714 _bdf_add_property(p->font, name, value);
1721 * Load the font header.
1724 _bdf_parse_start(char *line, unsigned int linelen, unsigned int lineno,
1725 void *call_data, void *client_data)
1727 unsigned int slen = 0;
1728 _bdf_line_func_t *next;
1733 next = (_bdf_line_func_t *) call_data;
1734 p = (_bdf_parse_t *) client_data;
1737 * Check for a comment. This is done to handle those fonts that have
1738 * comments before the STARTFONT line for some reason.
1740 if (memcmp(line, "COMMENT", 7) == 0) {
1741 if (p->opts->keep_comments != 0 && p->font != 0) {
1748 _bdf_add_comment(p->font, s, linelen);
1753 if (!(p->flags & _BDF_START)) {
1754 if (memcmp(line, "STARTFONT", 9) != 0)
1756 * No STARTFONT field is a good indication of a problem.
1758 return BDF_MISSING_START;
1759 p->flags = _BDF_START;
1760 p->font = font = (bdf_font_t *) calloc(1, sizeof(bdf_font_t));
1761 p->font->internal = (void *) malloc(sizeof(hashtable));
1762 hash_init((hashtable *) p->font->internal);
1763 p->font->spacing = p->opts->font_spacing;
1764 p->font->default_glyph = -1;
1769 * Check for the start of the properties.
1771 if (memcmp(line, "STARTPROPERTIES", 15) == 0) {
1772 _bdf_split(" +", line, linelen, &p->list);
1773 p->cnt = p->font->props_size = _bdf_atoul(p->list.field[1], 0, 10);
1774 p->font->props = (bdf_property_t *)
1775 malloc(sizeof(bdf_property_t) * p->cnt);
1776 p->flags |= _BDF_PROPS;
1777 *next = _bdf_parse_properties;
1782 * Check for the FONTBOUNDINGBOX field.
1784 if (memcmp(line, "FONTBOUNDINGBOX", 15) == 0) {
1785 if (!(p->flags & _BDF_SIZE)) {
1787 * Missing the SIZE field.
1789 sprintf(nbuf, ERRMSG1, lineno, "SIZE");
1790 _bdf_add_acmsg(p->font, nbuf, strlen(nbuf));
1791 return BDF_MISSING_SIZE;
1793 _bdf_split(" +", line, linelen, &p->list);
1794 p->font->bbx.width = _bdf_atos(p->list.field[1], 0, 10);
1795 p->font->bbx.height = _bdf_atos(p->list.field[2], 0, 10);
1796 p->font->bbx.x_offset = _bdf_atos(p->list.field[3], 0, 10);
1797 p->font->bbx.y_offset = _bdf_atos(p->list.field[4], 0, 10);
1798 p->font->bbx.ascent = p->font->bbx.height + p->font->bbx.y_offset;
1799 p->font->bbx.descent = -p->font->bbx.y_offset;
1800 p->flags |= _BDF_FONT_BBX;
1805 * The next thing to check for is the FONT field.
1807 if (memcmp(line, "FONT", 4) == 0) {
1808 _bdf_split(" +", line, linelen, &p->list);
1809 _bdf_shift(1, &p->list);
1810 s = _bdf_join(' ', &slen, &p->list);
1811 p->font->name = (char *) malloc(slen + 1);
1812 (void) memcpy(p->font->name, s, slen + 1);
1814 * If the font name is an XLFD name, set the spacing to the one in the
1815 * font name. If there is no spacing fall back on the default.
1817 _bdf_set_default_spacing(p->font, p->opts);
1818 p->flags |= _BDF_FONT_NAME;
1823 * Check for the SIZE field.
1825 if (memcmp(line, "SIZE", 4) == 0) {
1826 if (!(p->flags & _BDF_FONT_NAME)) {
1828 * Missing the FONT field.
1830 sprintf(nbuf, ERRMSG1, lineno, "FONT");
1831 _bdf_add_acmsg(p->font, nbuf, strlen(nbuf));
1832 return BDF_MISSING_FONTNAME;
1834 _bdf_split(" +", line, linelen, &p->list);
1835 p->font->point_size = _bdf_atoul(p->list.field[1], 0, 10);
1836 p->font->resolution_x = _bdf_atoul(p->list.field[2], 0, 10);
1837 p->font->resolution_y = _bdf_atoul(p->list.field[3], 0, 10);
1840 * Check for the bits per pixel field.
1842 if (p->list.used == 5) {
1843 p->font->bpp = _bdf_atos(p->list.field[4], 0, 10);
1844 if (p->font->bpp > 1 && (p->font->bpp & 1)) {
1846 * Move up to the next bits per pixel value if an odd number
1850 if (p->font->bpp <= 4) {
1851 sprintf(nbuf, ACMSG11, p->font->bpp);
1852 _bdf_add_acmsg(p->font, nbuf, strlen(nbuf));
1855 if (p->font->bpp > 4) {
1856 sprintf(nbuf, ACMSG11, p->font->bpp);
1857 _bdf_add_acmsg(p->font, nbuf, strlen(nbuf));
1863 p->flags |= _BDF_SIZE;
1867 return BDF_INVALID_LINE;
1870 /**************************************************************************
1874 **************************************************************************/
1880 bdf_property_t *prop;
1882 hash_init(&proptbl);
1883 for (i = 0, prop = _bdf_properties; i < _num_bdf_properties; i++, prop++)
1884 hash_insert(prop->name, (void *) i, &proptbl);
1891 bdf_property_t *prop;
1893 hash_free(&proptbl);
1896 * Free up the user defined properties.
1898 for (prop = user_props, i = 0; i < nuser_props; i++, prop++) {
1900 if (prop->format == BDF_ATOM && prop->value.atom != 0)
1901 free(prop->value.atom);
1903 if (nuser_props > 0)
1904 free((char *) user_props);
1906 _bdf_glyph_name_cleanup();
1910 bdf_load_font(FILE *in, bdf_options_t *opts, bdf_callback_t callback,
1914 unsigned int lineno;
1918 (void) memset((char *) &p, 0, sizeof(_bdf_parse_t));
1919 p.opts = (opts != 0) ? opts : &_bdf_opts;
1921 p.callback = callback;
1922 p.client_data = data;
1923 n = _bdf_readlines(fileno(in), _bdf_parse_start, (void *) &p, &lineno);
1927 * If the font is not proportional, set the fonts monowidth
1928 * field to the width of the font bounding box.
1930 if (p.font->spacing != BDF_PROPORTIONAL)
1931 p.font->monowidth = p.font->bbx.width;
1934 * If the number of glyphs loaded is not that of the original count,
1935 * indicate the difference.
1937 if (p.cnt != p.font->glyphs_used + p.font->unencoded_used) {
1938 sprintf(msgbuf, ACMSG15, p.cnt,
1939 p.font->glyphs_used + p.font->unencoded_used);
1940 _bdf_add_acmsg(p.font, msgbuf, strlen(msgbuf));
1941 p.font->modified = 1;
1945 * Once the font has been loaded, adjust the overall font metrics if
1948 if (p.opts->correct_metrics != 0 &&
1949 (p.font->glyphs_used > 0 || p.font->unencoded_used > 0)) {
1950 if (p.maxrb - p.minlb != p.font->bbx.width) {
1951 sprintf(msgbuf, ACMSG3, p.font->bbx.width, p.maxrb - p.minlb);
1952 _bdf_add_acmsg(p.font, msgbuf, strlen(msgbuf));
1953 p.font->bbx.width = p.maxrb - p.minlb;
1954 p.font->modified = 1;
1956 if (p.font->bbx.x_offset != p.minlb) {
1957 sprintf(msgbuf, ACMSG4, p.font->bbx.x_offset, p.minlb);
1958 _bdf_add_acmsg(p.font, msgbuf, strlen(msgbuf));
1959 p.font->bbx.x_offset = p.minlb;
1960 p.font->modified = 1;
1962 if (p.font->bbx.ascent != p.maxas) {
1963 sprintf(msgbuf, ACMSG5, p.font->bbx.ascent, p.maxas);
1964 _bdf_add_acmsg(p.font, msgbuf, strlen(msgbuf));
1965 p.font->bbx.ascent = p.maxas;
1966 p.font->modified = 1;
1968 if (p.font->bbx.descent != p.maxds) {
1969 sprintf(msgbuf, ACMSG6, p.font->bbx.descent, p.maxds);
1970 _bdf_add_acmsg(p.font, msgbuf, strlen(msgbuf));
1971 p.font->bbx.descent = p.maxds;
1972 p.font->bbx.y_offset = -p.maxds;
1973 p.font->modified = 1;
1975 if (p.maxas + p.maxds != p.font->bbx.height) {
1976 sprintf(msgbuf, ACMSG7, p.font->bbx.height, p.maxas + p.maxds);
1977 _bdf_add_acmsg(p.font, msgbuf, strlen(msgbuf));
1979 p.font->bbx.height = p.maxas + p.maxds;
1981 if (p.flags & _BDF_SWIDTH_ADJ)
1982 _bdf_add_acmsg(p.font, ACMSG8, strlen(ACMSG8));
1987 * Last, if an error happened during loading, handle the messages.
1989 if (n < 0 && callback != 0) {
1991 * An error was returned. Alert the client.
1993 p.cb.reason = BDF_ERROR;
1994 p.cb.errlineno = lineno;
1995 (*callback)(&p.cb, data);
1996 } else if (p.flags & _BDF_START) {
1999 * The ENDFONT field was never reached or did not exist.
2001 if (!(p.flags & _BDF_GLYPHS))
2003 * Error happened while parsing header.
2005 sprintf(msgbuf, ERRMSG2, lineno);
2008 * Error happened when parsing glyphs.
2010 sprintf(msgbuf, ERRMSG3, lineno);
2012 _bdf_add_acmsg(p.font, msgbuf, strlen(msgbuf));
2015 if (callback != 0) {
2016 p.cb.reason = BDF_ERROR;
2017 p.cb.errlineno = lineno;
2018 (*callback)(&p.cb, data);
2020 } else if (callback != 0) {
2022 * This forces the progress bar to always finish.
2024 p.cb.current = p.cb.total;
2025 (*p.callback)(&p.cb, p.client_data);
2029 * Free up the list used during the parsing.
2031 if (p.list.size > 0)
2032 free((char *) p.list.field);
2036 * Make sure the comments are NULL terminated if they exist.
2038 if (p.font->comments_len > 0) {
2039 p.font->comments = (char *) realloc(p.font->comments,
2040 p.font->comments_len + 1);
2041 p.font->comments[p.font->comments_len] = 0;
2045 * Make sure the auto-correct messages are NULL terminated if they
2048 if (p.font->acmsgs_len > 0) {
2049 p.font->acmsgs = (char *) realloc(p.font->acmsgs,
2050 p.font->acmsgs_len + 1);
2051 p.font->acmsgs[p.font->acmsgs_len] = 0;
2061 _bdf_parse_hbf_header(char *line, unsigned int linelen, unsigned int lineno,
2062 void *call_data, void *client_data)
2064 unsigned int vlen = 0;
2067 _bdf_line_func_t *next;
2070 next = (_bdf_line_func_t *) call_data;
2071 p = (_bdf_parse_t *) client_data;
2074 * Check for comments.
2076 if (memcmp(line, "COMMENT", 7) == 0) {
2077 if (p->opts->keep_comments != 0 && p->font != 0) {
2086 * If the properties are being parsed, add the comment as a
2087 * property. Otherwise, simply add the comment in the normal
2090 if (p->flags & _BDF_PROPS)
2091 _bdf_add_property(p->font, name, value);
2093 _bdf_add_comment(p->font, value, vlen);
2098 if (!(p->flags & _BDF_START)) {
2099 if (memcmp(line, "HBF_START_FONT", 14) != 0)
2101 p->flags = _BDF_START;
2102 p->font = (bdf_font_t *) calloc(1, sizeof(bdf_font_t));
2104 * HBF fonts are always assumed to be 1 bit per pixel.
2107 p->font->internal = (void *) malloc(sizeof(hashtable));
2108 hash_init((hashtable *) p->font->internal);
2110 p->font->spacing = p->opts->font_spacing;
2111 p->font->default_glyph = -1;
2116 * Check for the HBF_END_FONT field.
2118 if (memcmp(line, "HBF_END_FONT", 12) == 0)
2120 * Need to perform some checks here to see whether some fields are
2126 * Check for HBF keywords which will be added as comments. These should
2127 * never occur in the properties list. Assume they won't.
2129 if (memcmp(line, "HBF_", 4) == 0) {
2130 if (p->opts->keep_comments != 0)
2131 _bdf_add_comment(p->font, line, linelen);
2135 if (!(p->flags & _BDF_PROPS)) {
2137 * Check for the start of the properties.
2139 if (memcmp(line, "STARTPROPERTIES", 15) == 0) {
2140 _bdf_split(" +", line, linelen, &p->list);
2141 p->cnt = p->font->props_size = _bdf_atoul(p->list.field[1], 0, 10);
2142 p->font->props = (bdf_property_t *)
2143 malloc(sizeof(bdf_property_t) * p->cnt);
2144 p->flags |= _BDF_PROPS;
2149 * Check for the CHARS field.
2151 if (memcmp(line, "CHARS", 5) == 0) {
2152 _bdf_split(" +", line, linelen, &p->list);
2153 p->cnt = p->font->glyphs_size =
2154 _bdf_atoul(p->list.field[1], 0, 10);
2155 p->font->glyphs = (bdf_glyph_t *)
2156 malloc(sizeof(bdf_glyph_t) * p->cnt);
2161 * Check for the FONTBOUNDINGBOX field.
2163 if (memcmp(line, "FONTBOUNDINGBOX", 15) == 0) {
2164 if (!(p->flags & (_BDF_START|_BDF_FONT_NAME|_BDF_SIZE)))
2166 _bdf_split(" +", line, linelen, &p->list);
2167 p->font->bbx.width = _bdf_atos(p->list.field[1], 0, 10);
2168 p->font->bbx.height = _bdf_atos(p->list.field[2], 0, 10);
2169 p->font->bbx.x_offset = _bdf_atos(p->list.field[3], 0, 10);
2170 p->font->bbx.y_offset = _bdf_atos(p->list.field[4], 0, 10);
2171 p->font->bbx.ascent = p->font->bbx.height + p->font->bbx.y_offset;
2172 p->font->bbx.descent = -p->font->bbx.y_offset;
2173 p->flags |= _BDF_FONT_BBX;
2178 * The next thing to check for is the FONT field.
2180 if (memcmp(line, "FONT", 4) == 0) {
2181 if (!(p->flags & _BDF_START))
2183 _bdf_split(" +", line, linelen, &p->list);
2184 _bdf_shift(1, &p->list);
2185 value = _bdf_join(' ', &vlen, &p->list);
2186 p->font->name = (char *) malloc(vlen + 1);
2187 (void) memcpy(p->font->name, value, vlen + 1);
2189 * If the font name is an XLFD name, set the spacing to the one in
2190 * the font name. If there is no spacing fall back on the
2193 _bdf_set_default_spacing(p->font, p->opts);
2194 p->flags |= _BDF_FONT_NAME;
2199 * Check for the SIZE field.
2201 if (memcmp(line, "SIZE", 4) == 0) {
2202 if (!(p->flags & (_BDF_START|_BDF_FONT_NAME)))
2204 _bdf_split(" +", line, linelen, &p->list);
2205 p->font->point_size = _bdf_atoul(p->list.field[1], 0, 10);
2206 p->font->resolution_x = _bdf_atoul(p->list.field[2], 0, 10);
2207 p->font->resolution_y = _bdf_atoul(p->list.field[3], 0, 10);
2208 p->flags |= _BDF_SIZE;
2213 * Check for the end of the properties.
2215 if (memcmp(line, "ENDPROPERTIES", 13) == 0) {
2217 * If the FONT_ASCENT or FONT_DESCENT properties have not been
2218 * encountered yet, then make sure they are added as properties and
2219 * make sure they are set from the font bounding box info.
2221 * This is *always* done regardless of the options, because X11
2222 * requires these two fields to compile fonts.
2224 if (bdf_get_font_property(p->font, "FONT_ASCENT") == 0) {
2225 p->font->font_ascent = p->font->bbx.ascent;
2226 sprintf(nbuf, "%hd", p->font->bbx.ascent);
2227 _bdf_add_property(p->font, "FONT_ASCENT", nbuf);
2228 sprintf(nbuf, ACMSG1, p->font->bbx.ascent);
2229 _bdf_add_acmsg(p->font, nbuf, strlen(nbuf));
2230 p->font->modified = 1;
2232 if (bdf_get_font_property(p->font, "FONT_DESCENT") == 0) {
2233 p->font->font_descent = p->font->bbx.descent;
2234 sprintf(nbuf, "%hd", p->font->bbx.descent);
2235 _bdf_add_property(p->font, "FONT_DESCENT", nbuf);
2236 sprintf(nbuf, ACMSG2, p->font->bbx.descent);
2237 _bdf_add_acmsg(p->font, nbuf, strlen(nbuf));
2238 p->font->modified = 1;
2240 p->flags &= ~_BDF_PROPS;
2245 * Handle the next thing in the usual property fashion.
2247 if (_bdf_is_atom(line, linelen, &name, &value))
2248 _bdf_add_property(p->font, name, value);
2250 _bdf_split(" +", line, linelen, &p->list);
2251 name = p->list.field[0];
2252 _bdf_shift(1, &p->list);
2253 value = _bdf_join(' ', &vlen, &p->list);
2254 _bdf_add_property(p->font, name, value);
2260 * Anything else is an error.
2268 _bdf_add_hbf_glyph(HBF *hbf, unsigned int code, void *callback_data)
2270 CONST unsigned char *bmap;
2280 * Attempt to get the bitmap.
2282 if ((bmap = hbfGetBitmap(hbf, code)) == 0)
2284 * Need some sort of error handling here.
2288 p = (_bdf_parse_t *) callback_data;
2290 fbbx = hbfFontBBox(hbf);
2295 * Check to make sure there is enough space to hold this glyph. If not,
2296 * allocate 10 more just in case.
2298 if (font->glyphs_used == font->glyphs_size) {
2299 if (font->glyphs_size == 0)
2300 font->glyphs = (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) * 16);
2302 font->glyphs = (bdf_glyph_t *)
2303 realloc((char *) font->glyphs,
2304 sizeof(bdf_glyph_t) * (font->glyphs_used + 16));
2305 gp = font->glyphs + font->glyphs_size;
2306 (void) memset((char *) gp, 0, sizeof(bdf_glyph_t) * 16);
2307 font->glyphs_size += 16;
2310 gp = font->glyphs + font->glyphs_used++;
2313 * Set the glyph name.
2315 sprintf(nbuf, "char%d", code);
2316 n = (unsigned int) strlen(nbuf);
2317 gp->name = (char *) malloc(n + 1);
2318 (void) memcpy(gp->name, nbuf, n + 1);
2323 gp->encoding = (int) code;
2326 * Set the device width.
2328 gp->dwidth = (unsigned short) fbbx->hbf_width;
2331 * Set the scalable width.
2333 ps = (double) font->point_size;
2334 rx = (double) font->resolution_x;
2335 dw = (double) gp->dwidth;
2336 gp->swidth = (unsigned short) ((dw * 72000.0) / (ps * rx));
2339 * Set the glyph bounding box.
2341 gp->bbx.width = fbbx->hbf_width;
2342 gp->bbx.height = fbbx->hbf_height;
2343 gp->bbx.x_offset = fbbx->hbf_xDisplacement;
2344 gp->bbx.y_offset = fbbx->hbf_yDisplacement;
2345 gp->bbx.ascent = gp->bbx.height + gp->bbx.y_offset;
2346 gp->bbx.descent = -gp->bbx.y_offset;
2349 * Add the bitmap by making a copy. Assumes the font bbx is OK for
2350 * determining the number of bytes needed for the glyph bitmap.
2352 gp->bytes = ((gp->bbx.width + 7) >> 3) * gp->bbx.height;
2353 gp->bitmap = (unsigned char *) malloc(gp->bytes);
2354 (void) memcpy((char *) gp->bitmap, (char *) bmap, gp->bytes);
2357 * Call the callback if it was provided.
2359 if (p->callback != 0) {
2360 p->cb.reason = BDF_LOADING;
2361 p->cb.total = font->glyphs_size;
2362 p->cb.current = font->glyphs_used;
2363 (*p->callback)(&p->cb, p->client_data);
2368 bdf_load_hbf_font(char *filename, bdf_options_t *opts, bdf_callback_t callback,
2372 unsigned int lineno;
2379 if ((hbf = hbfOpen(filename)) == 0)
2382 if ((in = fopen(hbfFileName(hbf), "r")) == 0) {
2388 * Parse the HBF header for properties and other things.
2390 (void) memset((char *) &p, 0, sizeof(_bdf_parse_t));
2391 p.opts = (opts != 0) ? opts : &_bdf_opts;
2393 p.callback = callback;
2394 p.client_data = data;
2396 n = _bdf_readlines(fileno(in), _bdf_parse_hbf_header, (void *) &p,
2402 * Determine what spacing the font has so the monowidth field can be set
2405 if ((pp = bdf_get_font_property(p.font, "SPACING")) != 0) {
2406 switch (pp->value.atom[0]) {
2407 case 'p': case 'P': p.font->spacing = BDF_PROPORTIONAL; break;
2408 case 'm': case 'M': p.font->spacing = BDF_MONOWIDTH; break;
2409 case 'c': case 'C': p.font->spacing = BDF_CHARCELL; break;
2414 * Set the monowidth field if necessary.
2416 if (p.font->spacing != BDF_PROPORTIONAL)
2417 p.font->monowidth = p.font->bbx.width;
2420 * Before loading the glyphs, check to see if any glyph structures have
2421 * been added. If not, check the HBF font for the number of characters.
2422 * Dynamically increasing glyph storage causes memory fragmentation on
2423 * some machines and crashes. This takes care of the cases where the HBF
2424 * file does not provide a "CHARS n" line.
2426 if (p.font->glyphs_size < hbfChars(hbf)) {
2427 if (p.font->glyphs_size == 0)
2428 p.font->glyphs = (bdf_glyph_t *)
2429 malloc(sizeof(bdf_glyph_t) * hbfChars(hbf));
2431 p.font->glyphs = (bdf_glyph_t *)
2432 realloc((char *) p.font->glyphs,
2433 sizeof(bdf_glyph_t) * hbfChars(hbf));
2434 diff = hbfChars(hbf) - p.font->glyphs_size;
2435 (void) memset((char *) (p.font->glyphs + p.font->glyphs_size), 0,
2437 p.font->glyphs_size = hbfChars(hbf);
2441 * Call the callback initially to set things up.
2443 if (p.callback != 0) {
2444 p.cb.reason = BDF_LOAD_START;
2445 p.cb.total = p.font->glyphs_size;
2447 (*p.callback)(&p.cb, p.client_data);
2451 * Now load the glyphs.
2453 hbfForEach(hbf, _bdf_add_hbf_glyph, (void *) &p);
2456 * Close the HBF font.
2461 * Sort the glyphs by encoding.
2463 qsort((char *) p.font->glyphs, p.font->glyphs_used, sizeof(bdf_glyph_t),
2467 * After loading the HBF header, create an XLFD name. If the XLFD name
2468 * cannot be made then preserve the name found in the HBF file.
2470 if ((name = bdf_make_xlfd_name(p.font, "HBF", "Unknown")) != 0) {
2471 if (p.font->name != 0)
2473 * If a name already exists in the font, free it up.
2478 * Replace the old name with the XLFD name.
2480 p.font->name = name;
2484 * Mark the font as being modified and generate a message that says
2485 * something about the font being converted from HBF format.
2487 p.font->modified = 1;
2488 _bdf_add_acmsg(p.font, "Font converted from HBF to BDF.", 31);
2493 #endif /* HAVE_HBF */
2496 * Crop the glyph bitmap to the minimum rectangle needed to hold the bits that
2497 * are set. Adjust the metrics based on the provided bounding box.
2500 _bdf_crop_glyph(bdf_font_t *font, bdf_glyph_t *glyph)
2503 unsigned short x, y, bpr, nbpr, col, colx, si, di;
2504 unsigned short minx, maxx, miny, maxy;
2506 unsigned char *bmap, *masks;
2512 (void) memcpy((char *) &nbbx, (char *) &glyph->bbx, sizeof(bdf_bbx_t));
2514 bpr = ((glyph->bbx.width * font->bpp) + 7) >> 3;
2517 minx = miny = 32767;
2520 switch (font->bpp) {
2521 case 1: masks = bdf_onebpp; break;
2522 case 2: masks = bdf_twobpp; break;
2523 case 4: masks = bdf_fourbpp; break;
2524 case 8: masks = bdf_eightbpp; break;
2527 for (y = 0; y < glyph->bbx.height; y++) {
2528 for (col = x = 0; x < glyph->bbx.width; x++, col += font->bpp) {
2529 si = (col & 7) / font->bpp;
2530 if (glyph->bitmap[(y * bpr) + (col >> 3)] & masks[si]) {
2531 minx = MIN(minx, x);
2532 maxx = MAX(maxx, x);
2533 miny = MIN(miny, y);
2534 maxy = MAX(maxy, y);
2540 * Handle an empty bitmap as a special case.
2542 if (minx == 32767) {
2543 if (glyph->bytes > 0)
2544 free((char *) glyph->bitmap);
2546 (void) memset((char *) &glyph->bbx, 0, sizeof(bdf_bbx_t));
2551 * Increment the max points so width and height calculations won't go
2558 nbbx.x_offset += minx;
2559 if (maxx - minx != nbbx.width)
2560 nbbx.width = maxx - minx;
2563 nbbx.ascent -= miny;
2564 if (maxy - miny != nbbx.height)
2565 nbbx.height = maxy - miny;
2566 nbbx.descent = nbbx.height - nbbx.ascent;
2567 nbbx.y_offset = -nbbx.descent;
2569 nbpr = ((nbbx.width * font->bpp) + 7) >> 3;
2572 * If nothing changed, then the glyph is already contained in the
2573 * minimum rectangle.
2575 if (memcmp((char *) &nbbx, (char *) &glyph->bbx,
2576 sizeof(bdf_bbx_t)) == 0 ||
2577 (nbpr == bpr && nbbx.height == glyph->bbx.height))
2581 * The metrics changed, so a new bitmap is needed.
2583 bytes = nbpr * nbbx.height;
2584 bmap = (unsigned char *) malloc(bytes);
2585 (void) memset((char *) bmap, 0, bytes);
2587 colx = minx * font->bpp;
2588 for (y = miny; y < maxy; y++) {
2589 for (col = x = minx; x < maxx; x++, col += font->bpp) {
2590 si = (col & 7) / font->bpp;
2591 byte = glyph->bitmap[(y * bpr) + (col >> 3)] & masks[si];
2594 * Position the pixel in the byte if necessary.
2596 di = ((col - colx) & 7) / font->bpp;
2598 byte <<= (si - di) * font->bpp;
2600 byte >>= (di - si) * font->bpp;
2601 bmap[((y - miny) * nbpr) + ((col - colx) >> 3)] |= byte;
2606 if (glyph->bytes > 0)
2607 free((char *) glyph->bitmap);
2608 glyph->bytes = bytes;
2609 glyph->bitmap = bmap;
2611 (void) memcpy((char *) &glyph->bbx, (char *) &nbbx, sizeof(bdf_bbx_t));
2615 * Pad a character-cell font glyph to match the bounds specified in the
2616 * provided bounding box.
2619 _bdf_pad_cell(bdf_font_t *font, bdf_glyph_t *glyph, bdf_glyph_t *cell)
2622 unsigned short si, di, sx, byte;
2623 unsigned short x, y, dx, dy, bx, by, bpr, nbpr;
2624 unsigned char *bmap, *masks;
2627 switch (font->bpp) {
2628 case 1: masks = bdf_onebpp; break;
2629 case 2: masks = bdf_twobpp; break;
2630 case 4: masks = bdf_fourbpp; break;
2631 case 8: masks = bdf_eightbpp; break;
2636 if (glyph->bbx.width == bbx->width && glyph->bbx.height == bbx->height) {
2638 * The glyph is already positioned in the cell. Copy the bitmap
2641 (void) memcpy((char *) cell->bitmap, (char *) glyph->bitmap,
2647 * Determine the X and Y location of the baseline.
2649 bx = MYABS(bbx->x_offset - glyph->bbx.x_offset);
2650 by = (bbx->ascent + bbx->descent) + bbx->y_offset;
2652 bpr = ((glyph->bbx.width * font->bpp) + 7) >> 3;
2653 nbpr = ((bbx->width * font->bpp) + 7) >> 3;
2656 * Set various cell values and clear the cell bitmap.
2658 bmap = cell->bitmap;
2659 (void) memset((char *) bmap, 0, cell->bytes);
2661 for (dy = by - glyph->bbx.ascent, y = 0; y < glyph->bbx.height;
2663 for (dx = bx * font->bpp, sx = x = 0; x < glyph->bbx.width;
2664 x++, dx += font->bpp, sx += font->bpp) {
2665 si = (sx & 7) / font->bpp;
2666 byte = glyph->bitmap[(y * bpr) + (sx >> 3)] & masks[si];
2668 di = (dx & 7) / font->bpp;
2670 byte <<= (si - di) * font->bpp;
2672 byte >>= (di - si) * font->bpp;
2673 bmap[(dy * nbpr) + (dx >> 3)] |= byte;
2679 static char *unix_eol = "\n";
2680 static char *dos_eol = "\r\n";
2681 static char *mac_eol = "\r";
2684 bdf_save_font(FILE *out, bdf_font_t *font, bdf_options_t *opts,
2685 bdf_callback_t callback, void *data)
2688 unsigned int i, j, bpr, pcnt;
2690 char *sp, *ep, *eol;
2692 bdf_glyph_t *c, *cp, cell;
2693 bdf_callback_struct_t cb;
2699 switch (opts->eol) {
2700 case BDF_UNIX_EOL: eol = unix_eol; break;
2701 case BDF_DOS_EOL: eol = dos_eol; break;
2702 case BDF_MAC_EOL: eol = mac_eol; break;
2706 * If the font is a character cell font, allocate some space for the
2709 if (font->spacing == BDF_CHARCELL && opts->pad_cells != 0) {
2710 bpr = ((font->bbx.width * font->bpp) + 7) >> 3;
2711 cell.bytes = bpr * font->bbx.height;
2712 cell.bitmap = (unsigned char *) malloc(cell.bytes);
2713 (void) memcpy((char *) &cell.bbx, (char *) &font->bbx,
2720 fprintf(out, "STARTFONT 2.1%s", eol);
2723 * Emit the comments.
2725 if (font->comments_len > 0) {
2726 for (sp = font->comments; *sp; sp++) {
2728 while (*ep && *ep != '\n')
2730 len = (int) (ep - sp);
2731 fprintf(out, "COMMENT %.*s%s", len, sp, eol);
2737 * Emit the font name.
2739 fprintf(out, "FONT %s%s", font->name, eol);
2742 * Emit the size info.
2745 fprintf(out, "SIZE %d %d %d%s", font->point_size,
2746 font->resolution_x, font->resolution_y, eol);
2748 fprintf(out, "SIZE %d %d %d %hd%s", font->point_size,
2749 font->resolution_x, font->resolution_y, font->bpp, eol);
2752 * Emit the bounding box.
2754 fprintf(out, "FONTBOUNDINGBOX %hd %hd %hd %hd%s",
2755 font->bbx.width, font->bbx.height, font->bbx.x_offset,
2756 font->bbx.y_offset, eol);
2759 * Emit the properties after counting how many are properties and
2760 * how many are comments.
2762 for (i = pcnt = 0, p = font->props; i < font->props_used; i++, p++) {
2763 if (memcmp(p->name, "COMMENT", 7) != 0)
2767 fprintf(out, "STARTPROPERTIES %d%s", pcnt, eol);
2768 for (i = 0, p = font->props; i < font->props_used; i++, p++) {
2769 fprintf(out, "%s ", p->name);
2770 if (p->format == BDF_ATOM) {
2771 if (p->value.atom == 0)
2772 fprintf(out, "\"\"%s", eol);
2774 fprintf(out, "\"%s\"%s", p->value.atom, eol);
2776 fprintf(out, "%d%s", p->value.int32, eol);
2779 fprintf(out, "ENDPROPERTIES%s", eol);
2782 * Emit the number of bitmaps in the font.
2784 fprintf(out, "CHARS %d%s", font->unencoded_used + font->glyphs_used, eol);
2787 * Call the callback if it was passed to start the save.
2789 if (callback != 0) {
2790 cb.reason = BDF_SAVE_START;
2791 cb.total = font->unencoded_used + font->glyphs_used;
2793 (*callback)(&cb, data);
2797 * Emit the unencoded bitmaps.
2799 for (i = 0, cp = font->unencoded; i < font->unencoded_used; i++, cp++) {
2801 * If the font has character-cell spacing and the option to pad the
2802 * glyphs to the size of the font bbx is set, then pad the glyph.
2803 * Otherwise, crop the glyph to the minimum rectangle needed to hold
2806 if (font->spacing == BDF_CHARCELL && opts->pad_cells != 0) {
2808 * Point at the temporary glyph structure and copy the necessary
2809 * glyph info into it.
2813 c->encoding = cp->encoding;
2814 c->swidth = cp->swidth;
2815 c->dwidth = cp->dwidth;
2816 _bdf_pad_cell(font, cp, c);
2819 _bdf_crop_glyph(font, c);
2823 * If the font has monowidth or character-cell spacing, then assign
2824 * the font monowidth field to the device width and recalculate the
2827 if (font->spacing != BDF_PROPORTIONAL) {
2828 c->dwidth = font->monowidth;
2829 ps = (double) font->point_size;
2830 rx = (double) font->resolution_x;
2831 dw = (double) c->dwidth;
2832 c->swidth = (unsigned short) ((dw * 72000.0) / (ps * rx));
2835 fprintf(out, "STARTCHAR unencoded%d%sENCODING -1%s", i, eol, eol);
2837 fprintf(out, "STARTCHAR %s%sENCODING -1%s", c->name, eol, eol);
2838 fprintf(out, "SWIDTH %hd 0%sDWIDTH %hd 0%s",
2839 c->swidth, eol, c->dwidth, eol);
2840 fprintf(out, "BBX %hd %hd %hd %hd%s", c->bbx.width, c->bbx.height,
2841 c->bbx.x_offset, c->bbx.y_offset, eol);
2842 fprintf(out, "BITMAP%s", eol);
2843 bpr = ((c->bbx.width * font->bpp) + 7) >> 3;
2844 for (j = 0; bpr != 0 && j < c->bytes; j++) {
2845 if (j && j % bpr == 0)
2847 fprintf(out, "%02X", c->bitmap[j]);
2850 * Handle empty bitmaps like this.
2852 if (c->bbx.height > 0)
2854 fprintf(out, "ENDCHAR%s", eol);
2857 * Call the callback if supplied.
2859 if (callback != 0) {
2860 cb.reason = BDF_SAVING;
2862 (*callback)(&cb, data);
2867 * Emit the other bitmaps.
2869 for (i = 0, cp = font->glyphs; i < font->glyphs_used; i++, cp++) {
2871 * If the font has character-cell spacing and the option to pad the
2872 * glyphs to the size of the font bbx is set, then pad the glyph.
2873 * Otherwise, crop the glyph to the minimum rectangle needed to hold
2876 if (font->spacing == BDF_CHARCELL && opts->pad_cells != 0) {
2878 * Point at the temporary glyph structure and copy the necessary
2879 * glyph info into it.
2883 c->encoding = cp->encoding;
2884 c->swidth = cp->swidth;
2885 c->dwidth = cp->dwidth;
2886 _bdf_pad_cell(font, cp, c);
2889 _bdf_crop_glyph(font, c);
2893 * If the font has monowidth or character-cell spacing, then assign
2894 * the font monowidth field to the device width and recalculate the
2897 if (font->spacing != BDF_PROPORTIONAL) {
2898 c->dwidth = font->monowidth;
2899 ps = (double) font->point_size;
2900 rx = (double) font->resolution_x;
2901 dw = (double) c->dwidth;
2902 c->swidth = (unsigned short) ((dw * 72000.0) / (ps * rx));
2905 fprintf(out, "STARTCHAR char%d%sENCODING %d%s",
2906 c->encoding, eol, c->encoding, eol);
2908 fprintf(out, "STARTCHAR %s%sENCODING %d%s",
2909 c->name, eol, c->encoding, eol);
2910 fprintf(out, "SWIDTH %hd 0%sDWIDTH %hd 0%s",
2911 c->swidth, eol, c->dwidth, eol);
2912 fprintf(out, "BBX %hd %hd %hd %hd%s", c->bbx.width, c->bbx.height,
2913 c->bbx.x_offset, c->bbx.y_offset, eol);
2914 fprintf(out, "BITMAP%s", eol);
2915 bpr = ((c->bbx.width * font->bpp) + 7) >> 3;
2916 for (j = 0; bpr != 0 && j < c->bytes; j++) {
2917 if (j && j % bpr == 0)
2919 fprintf(out, "%02X", c->bitmap[j]);
2922 * Handle empty bitmaps like this.
2924 if (c->bbx.height > 0)
2926 fprintf(out, "ENDCHAR%s", eol);
2929 * Call the callback if supplied.
2931 if (callback != 0) {
2932 cb.reason = BDF_SAVING;
2934 (*callback)(&cb, data);
2941 fprintf(out, "ENDFONT%s", eol);
2944 * Always force a final call to the callback to make sure things
2947 if (callback != 0) {
2948 cb.reason = BDF_SAVING;
2949 cb.current = cb.total;
2950 (*callback)(&cb, data);
2954 * If the font is a character cell font, clean up the temporary glyph.
2956 if (font->spacing == BDF_CHARCELL && opts->pad_cells != 0)
2957 free((char *) cell.bitmap);
2961 * Routine to write a single set of SBIT metrics.
2964 bdf_save_sbit_metrics(FILE *out, bdf_font_t *font, bdf_options_t *opts,
2970 switch (opts->eol) {
2971 case BDF_UNIX_EOL: eol = unix_eol; break;
2972 case BDF_DOS_EOL: eol = dos_eol; break;
2973 case BDF_MAC_EOL: eol = mac_eol; break;
2977 * Throw a simple header in.
2980 fprintf(out, ";%s; SBIT metrics file generated by \"%s\".%s;%s%s", eol,
2981 appname, eol, eol, eol);
2986 fprintf(out, ";%s; Pixels Per Em.%s;%s", eol, eol, eol);
2987 fprintf(out, "PPEM %d%s%s", font->point_size, eol, eol);
2990 * If the font is character cell or monowidth, set this boolean.
2992 if (font->spacing != BDF_PROPORTIONAL) {
2994 ";%s; Font is not proportional, so use mono advance.%s;%s",
2996 fprintf(out, "FORCECONSTANTMETRICS TRUE%s%s", eol, eol);
2999 ";%s; Font is proportional, so do not use mono advance.%s;%s",
3001 fprintf(out, "FORCECONSTANTMETRICS FALSE%s%s", eol, eol);
3005 * Do the horizontal line metrics only.
3007 fprintf(out, ";%s; Horizontal line metrics.%s;%s", eol, eol, eol);
3009 fprintf(out, "H_ASCENDER %d%sH_DESCENDER %d%s", font->font_ascent, eol,
3010 font->font_descent, eol);
3011 fprintf(out, "H_WIDTHMAX %hd%s", font->bbx.width, eol);
3012 fprintf(out, "H_MINORIGINSB %hd%sH_MINADVANCEBL %hd%s",
3013 font->bbx.x_offset, eol,
3014 font->bbx.width + font->bbx.x_offset, eol);
3015 fprintf(out, "H_MAXBEFOREBL %hd%sH_MINAFTERBL %hd%s%s",
3016 font->bbx.ascent, eol, font->bbx.y_offset, eol, eol);
3019 * Write the default caret info.
3021 fprintf(out, ";%s; Caret slope and offset info.%s;%s", eol, eol, eol);
3022 fprintf(out, "CARETSLOPENUMERATOR 1%sCARETSLOPEDENOMINATOR 0%s", eol, eol);
3023 fprintf(out, "CARETOFFSET 0%s%s", eol, eol);
3026 * Write the bitmap options.
3028 fprintf(out, ";%s; Bitmap options.%s;%s", eol, eol, eol);
3029 fprintf(out, "DIRECTION H%sSTORAGE FAST%s%s", eol, eol, eol);
3032 * Scaled bitmaps not implemented yet.
3034 fprintf(out, ";%s; Scaled bitmap info (Not Yet Implemented).%s;%s",
3039 * Special routine to dump the font in the Roman Czyborra's hex format. It
3040 * only dumps the encoded glyphs and assumes the bitmaps have the correct
3044 bdf_export_hex(FILE *out, bdf_font_t *font, bdf_options_t *opts,
3045 bdf_callback_t callback, void *data)
3047 int bpr, fbpr, j, k;
3049 bdf_glyph_t *gp, cell;
3050 bdf_callback_struct_t cb;
3052 if (font == 0 || out == 0)
3055 if (font->glyphs_used == 0)
3059 * Call the callback if it was passed to start the export.
3061 if (callback != 0) {
3062 cb.reason = BDF_EXPORT_START;
3063 cb.total = font->glyphs_used;
3065 (*callback)(&cb, data);
3068 fbpr = ((font->bbx.width * font->bpp) + 7) >> 3;
3069 bpr = (((font->bbx.width >> 1) * font->bpp) + 7) >> 3;
3070 cell.bytes = fbpr * font->bbx.height;
3071 cell.bitmap = (unsigned char *) malloc(cell.bytes);
3073 for (i = 0, ng = font->glyphs_used, gp = font->glyphs; i < ng; i++, gp++) {
3074 _bdf_pad_cell(font, gp, &cell);
3075 fprintf(out, "%04X:", gp->encoding & 0xffff);
3076 if (gp->bbx.width <= (font->bbx.width >> 1)) {
3077 for (j = 0; j < cell.bytes; j += fbpr) {
3078 for (k = 0; k < bpr; k++)
3079 fprintf(out, "%02X", cell.bitmap[j + k]);
3082 for (j = 0; j < cell.bytes; j++)
3083 fprintf(out, "%02X", cell.bitmap[j]);
3089 * Call the callback if supplied.
3091 if (callback != 0) {
3092 cb.reason = BDF_EXPORTING;
3094 (*callback)(&cb, data);
3099 * Clean up the cell.
3101 free((char *) cell.bitmap);
3104 * Always call a final callback to make sure the client gets a chance to
3107 if (callback != 0) {
3108 cb.reason = BDF_EXPORTING;
3109 cb.current = cb.total;
3110 (*callback)(&cb, data);
3115 bdf_free_font(bdf_font_t *font)
3118 bdf_glyph_t *glyphs;
3123 if (font->name != 0)
3127 * Free up the internal hash table of property names.
3129 hash_free((hashtable *) font->internal);
3130 free((char *) font->internal);
3133 * Free up the comment info.
3135 if (font->comments_len > 0)
3136 free(font->comments);
3139 * Free up the auto-correction messages.
3141 if (font->acmsgs_len > 0)
3145 * Free up the properties.
3147 for (i = 0; i < font->props_size; i++) {
3148 if (font->props[i].format == BDF_ATOM && font->props[i].value.atom)
3149 free(font->props[i].value.atom);
3152 if (font->props_size > 0 && font->props != 0)
3153 free((char *) font->props);
3156 * Free up the character info.
3158 for (i = 0, glyphs = font->glyphs; i < font->glyphs_used; i++, glyphs++) {
3161 if (glyphs->bytes > 0 && glyphs->bitmap != 0)
3162 free((char *) glyphs->bitmap);
3165 for (i = 0, glyphs = font->unencoded; i < font->unencoded_used;
3169 if (glyphs->bytes > 0)
3170 free((char *) glyphs->bitmap);
3171 if (glyphs->unicode.map_size > 0)
3172 free((char *) glyphs->unicode.map);
3175 if (font->glyphs_size > 0)
3176 free((char *) font->glyphs);
3178 if (font->unencoded_size > 0)
3179 free((char *) font->unencoded);
3182 * Free up the overflow storage if it was used.
3184 for (i = 0, glyphs = font->overflow.glyphs; i < font->overflow.glyphs_used;
3186 if (glyphs->name != 0)
3188 if (glyphs->bytes > 0)
3189 free((char *) glyphs->bitmap);;
3190 if (glyphs->unicode.map_size > 0)
3191 free((char *) glyphs->unicode.map);
3193 if (font->overflow.glyphs_size > 0)
3194 free((char *) font->overflow.glyphs);
3196 free((char *) font);
3200 bdf_create_property(char *name, int format)
3206 * First check to see if the property has
3207 * already been added or not. If it has, then
3211 if (hash_lookup(name, &proptbl))
3214 if (nuser_props == 0)
3215 user_props = (bdf_property_t *) malloc(sizeof(bdf_property_t));
3217 user_props = (bdf_property_t *) realloc((char *) user_props,
3218 sizeof(bdf_property_t) *
3221 p = user_props + nuser_props;
3222 (void) memset((char *) p, 0, sizeof(bdf_property_t));
3223 n = (unsigned int) (strlen(name) + 1);
3224 p->name = (char *) malloc(n);
3225 (void) memcpy(p->name, name, n);
3229 n = _num_bdf_properties + nuser_props;
3230 hash_insert(p->name, (void *) n, &proptbl);
3236 bdf_get_property(char *name)
3239 unsigned int propid;
3241 if (name == 0 || *name == 0)
3244 if ((hn = hash_lookup(name, &proptbl)) == 0)
3247 propid = (unsigned int) hn->data;
3248 if (propid >= _num_bdf_properties)
3249 return user_props + (propid - _num_bdf_properties);
3250 return _bdf_properties + propid;
3254 * Routine to compare two property names.
3257 by_prop_name(const void *a, const void *b)
3259 bdf_property_t *p1, *p2;
3261 p1 = (bdf_property_t *) a;
3262 p2 = (bdf_property_t *) b;
3264 return strcmp(p1->name, p2->name);
3268 bdf_property_list(bdf_property_t **props)
3273 n = _num_bdf_properties + nuser_props;
3274 if (props != 0 && n != 0) {
3275 p = (bdf_property_t *) malloc(sizeof(bdf_property_t) * n);
3276 (void) memcpy((char *) p, (char *) _bdf_properties,
3277 sizeof(bdf_property_t) * _num_bdf_properties);
3278 (void) memcpy((char *) (p + _num_bdf_properties), (char *) user_props,
3279 sizeof(bdf_property_t) * nuser_props);
3280 qsort((char *) p, n, sizeof(bdf_property_t), by_prop_name);
3287 bdf_replace_comments(bdf_font_t *font, char *comments,
3288 unsigned int comments_len)
3290 if (font == 0 || comments_len == 0)
3293 if (font->comments_len > 0)
3294 free(font->comments);
3296 font->comments = (char *) malloc(comments_len + 1);
3297 (void) memcpy(font->comments, comments, comments_len);
3298 font->comments[comments_len] = 0;
3299 font->comments_len = comments_len;
3305 bdf_font_property_list(bdf_font_t *font, bdf_property_t **props)
3309 if (font == 0 || font->props_used == 0)
3313 p = (bdf_property_t *) malloc(sizeof(bdf_property_t) *
3315 (void) memcpy((char *) p, (char *) font->props,
3316 sizeof(bdf_property_t) * font->props_used);
3317 qsort((char *) p, font->props_used, sizeof(bdf_property_t),
3322 return font->props_used;
3326 bdf_add_font_property(bdf_font_t *font, bdf_property_t *property)
3329 unsigned int propid;
3331 bdf_property_t *p, *ip;
3333 if (property == 0 || property->name == 0 || property->name[0] == 0)
3337 * If the font does not have a property hash table yet, make
3338 * sure it is allocated.
3340 if (font->internal == 0) {
3341 font->internal = (void *) malloc(sizeof(hashtable));
3342 hash_init((hashtable *) font->internal);
3346 * See if the property is in the general property table yet.
3347 * If it isn't, then add it.
3349 if ((hn = hash_lookup(property->name, &proptbl)) == 0)
3350 bdf_create_property(property->name, property->format);
3353 * If the property exists and is a user defined property, make sure
3354 * its format is updated to match the property being added.
3356 propid = (unsigned int) hn->data;
3357 if (propid >= _num_bdf_properties) {
3358 p = user_props + (propid - _num_bdf_properties);
3359 if (p->format != property->format)
3360 p->format = property->format;
3365 * If the font already has this property, then change the existing one.
3367 hn = hash_lookup(property->name, (hashtable *) font->internal);
3370 * Changing an existing property value.
3372 p = font->props + ((unsigned int) hn->data);
3375 * If the format changed, then free the atom value if the original
3376 * format was an atom.
3378 if (p->format == BDF_ATOM && property->format != BDF_ATOM &&
3380 free((char *) p->value.atom);
3381 p->format = property->format;
3383 switch (p->format) {
3386 * If the property value is the same, then just return.
3388 if (property->value.atom == p->value.atom ||
3389 (property->value.atom && p->value.atom &&
3390 strcmp(property->value.atom, p->value.atom) == 0))
3392 if (property->value.atom == 0)
3395 len = strlen(property->value.atom) + 1;
3397 p->value.atom = (char *) malloc(len);
3398 (void) memcpy(p->value.atom, property->value.atom, len);
3404 * If the property value is the same, then just return.
3406 if (p->value.int32 == property->value.int32)
3408 p->value.int32 = property->value.int32;
3412 * If the property value is the same, then just return.
3414 if (p->value.card32 == property->value.card32)
3416 p->value.card32 = property->value.card32;
3421 * New property being added.
3425 * Get the internal table entry for a pointer to the
3426 * name of the property.
3428 hn = hash_lookup(property->name, &proptbl);
3429 propid = (unsigned int) hn->data;
3430 if (propid >= _num_bdf_properties)
3431 ip = user_props + (propid - _num_bdf_properties);
3433 ip = _bdf_properties + propid;
3436 * Add it to the property list first.
3438 if (font->props_used == font->props_size) {
3439 if (font->props_size == 0)
3440 font->props = (bdf_property_t *) malloc(sizeof(bdf_property_t));
3442 font->props = (bdf_property_t *)
3443 realloc((char *) font->props, sizeof(bdf_property_t) *
3444 (font->props_size + 1));
3447 p = font->props + font->props_used;
3450 p->format = ip->format;
3451 p->builtin = ip->builtin;
3453 switch (p->format) {
3455 if (property->value.atom == 0)
3458 len = strlen(property->value.atom) + 1;
3460 p->value.atom = (char *) malloc(len);
3461 (void) memcpy(p->value.atom, property->value.atom, len);
3466 p->value.int32 = property->value.int32;
3469 p->value.card32 = property->value.card32;
3474 * Now insert it into the internal hash table.
3476 hash_insert(p->name, (void *) font->props_used,
3477 (hashtable *) font->internal);
3481 if (memcmp(property->name, "DEFAULT_CHAR", 12) == 0)
3483 * If the property just added is DEFAULT_CHAR, then make sure the
3484 * default_glyph field is set.
3486 font->default_glyph = p->value.card32;
3487 else if (memcmp(property->name, "FONT_ASCENT", 11) == 0)
3489 * If the property just added is FONT_ASCENT, then adjust the
3490 * font_ascent field.
3492 font->font_ascent = p->value.int32;
3493 else if (memcmp(property->name, "FONT_DESCENT", 12) == 0)
3495 * If the property just added is FONT_DESCENT, then adjust the
3496 * font_descent field.
3498 font->font_descent = p->value.int32;
3499 else if (memcmp(property->name, "RESOLUTION_X", 12) == 0)
3501 * If the property just added is RESOLUTION_X, then adjust the
3502 * resolution_x field.
3504 font->resolution_x = p->value.card32;
3505 else if (memcmp(property->name, "RESOLUTION_Y", 12) == 0)
3507 * If the property just added is RESOLUTION_Y, then adjust the
3508 * resolution_y field.
3510 font->resolution_y = p->value.card32;
3511 else if (memcmp(property->name, "POINT_SIZE", 10) == 0)
3513 * If the property just added is POINT_SIZE, then adjust the
3516 font->point_size = p->value.int32 / 10;
3517 else if (memcmp(property->name, "SPACING", 7) == 0) {
3519 * Make sure the font spacing is kept in synch if the property
3520 * changes. If the spacing changes from proportional to one
3521 * of the others, force the monowidth to be set.
3523 switch (p->value.atom[0]) {
3525 if (font->spacing == BDF_PROPORTIONAL)
3526 font->monowidth = font->bbx.width + font->bbx.x_offset;
3527 font->spacing = BDF_CHARCELL;
3530 if (font->spacing == BDF_PROPORTIONAL)
3531 font->monowidth = font->bbx.width + font->bbx.x_offset;
3532 font->spacing = BDF_MONOWIDTH;
3534 case 'P': case 'p': font->spacing = BDF_PROPORTIONAL; break;
3539 * Make sure the font is marked as modified.
3545 bdf_delete_font_property(bdf_font_t *font, char *name)
3551 if (font == 0 || name == 0 || *name == 0 || font->props_used == 0)
3554 if ((hn = hash_lookup(name, (hashtable *) font->internal)) == 0)
3557 off = (unsigned int) hn->data;
3558 p = font->props + off;
3561 * Delete the ATOM value if appropriate.
3563 if (p->format == BDF_ATOM && p->value.atom != 0)
3564 free(p->value.atom);
3567 * The property exists. Two things needs to be done:
3568 * 1. Remove the property from the hash table.
3569 * 2. Remove the property from the font's list of properties.
3571 hash_delete(name, (hashtable *) font->internal);
3574 * Locate its offset in the font property list.
3576 if (off < font->props_used - 1)
3578 * We have to shift the property list down.
3580 _bdf_memmove((char *) p, (char *) (p + 1),
3581 sizeof(bdf_property_t) * ((font->props_used - 1) - off));
3585 * If the font property happens to be DEFAULT_CHAR, then make sure the
3586 * default_glyph field is reset.
3588 if (strncmp(name, "DEFAULT_CHAR", 12) == 0)
3589 font->default_glyph = -1;
3592 * Update the hash table with the correct indexes.
3594 for (off = 0, p = font->props; off < font->props_used; off++, p++)
3595 hash_insert(p->name, (void *) off, (hashtable *) font->internal);
3598 * Mark the font as being modified.
3604 bdf_get_font_property(bdf_font_t *font, char *name)
3608 if (font == 0 || font->props_size == 0 || name == 0 || *name == 0)
3611 hn = hash_lookup(name, (hashtable *) font->internal);
3612 return (hn) ? (font->props + ((unsigned int) hn->data)) : 0;
3616 bdf_options_t *opts;
3617 bdf_options_callback_t callback;
3620 } _bdf_opts_parse_t;
3623 _bdf_get_boolean(char *val)
3628 if (val == 0 || *val == 0)
3632 case '0': case 'F': case 'f': case 'N': case 'n': ok = 0; break;
3633 case '1': case 'T': case 't': case 'Y': case 'y': ok = 1; break;
3639 _bdf_parse_options(char *line, unsigned int linelen, unsigned int lineno,
3640 void *call_data, void *client_data)
3643 _bdf_opts_parse_t *p;
3646 p = (_bdf_opts_parse_t *) client_data;
3650 * Split the line into fields.
3652 _bdf_split(" \t+", line, linelen, lp);
3654 if (lp->field[0][0] == 'b' &&
3655 memcmp(lp->field[0], "bits_per_pixel", 14) == 0) {
3658 "bdf: warning: %d: incorrect number of fields %d.\n",
3661 "bdf: warning: %d: bits_per_pixel <1, 2, or 4>.\n",
3664 bpp = _bdf_atol(lp->field[1], 0, 10);
3665 if (!(bpp == 1 || bpp == 2 || bpp == 4)) {
3667 "bdf: warning: %d: invalid bits per pixel %d.\n",
3670 "bdf: warning: %d: bits_per_pixel <1, 2, or 4>.\n",
3673 p->opts->bits_per_pixel = bpp;
3678 if (lp->field[0][0] == 'e' && memcmp(lp->field[0], "eol", 3) == 0) {
3681 "bdf: warning: %d: incorrect number of fields %d.\n",
3684 "bdf: warning: %d: eol <eolname>.\n", lineno);
3686 switch (lp->field[1][0]) {
3687 case 'u': case 'U': p->opts->eol = BDF_UNIX_EOL; break;
3688 case 'd': case 'D': p->opts->eol = BDF_DOS_EOL; break;
3689 case 'm': case 'M': p->opts->eol = BDF_MAC_EOL; break;
3695 if (lp->field[0][0] == 'c' &&
3696 memcmp(lp->field[0], "correct_metrics", 15) == 0) {
3699 "bdf: warning: %d: incorrect number of fields %d.\n",
3702 "bdf: warning: %d: correct_metrics <boolean>.\n", lineno);
3704 p->opts->correct_metrics = _bdf_get_boolean(lp->field[1]);
3709 if (lp->field[0][0] == 'k' &&
3710 memcmp(lp->field[0], "keep_unencoded", 14) == 0) {
3713 "bdf: warning: %d: incorrect number of fields %d.\n",
3716 "bdf: warning: %d: keep_unencoded <boolean>.\n", lineno);
3718 p->opts->keep_unencoded = _bdf_get_boolean(lp->field[1]);
3723 if (lp->field[0][0] == 'k' &&
3724 memcmp(lp->field[0], "keep_comments", 13) == 0) {
3727 "bdf: warning: %d: incorrect number of fields %d.\n",
3730 "bdf: warning: %d: keep_comments <boolean>.\n", lineno);
3732 p->opts->keep_comments = _bdf_get_boolean(lp->field[1]);
3737 if (lp->field[0][0] == 'p' &&
3738 memcmp(lp->field[0], "pad_character_cells", 19) == 0) {
3741 "bdf: warning: %d: incorrect number of fields %d.\n",
3744 "bdf: warning: %d: pad_character_cells <boolean>.\n",
3747 p->opts->pad_cells = _bdf_get_boolean(lp->field[1]);
3752 if (lp->field[0][0] == 'p' &&
3753 memcmp(lp->field[0], "point_size", 10) == 0) {
3756 "bdf: warning: %d: incorrect number of fields %d.\n",
3759 "bdf: warning: %d: point_size <integer>.\n", lineno);
3761 p->opts->point_size = _bdf_atol(lp->field[1], 0, 10);
3765 if (lp->field[0][0] == 'h' &&
3766 memcmp(lp->field[0], "horizontal_resolution", 21) == 0) {
3769 "bdf: warning: %d: incorrect number of fields %d.\n",
3772 "bdf: warning: %d: horizontal_resolution <cardinal>.\n",
3775 p->opts->resolution_x = _bdf_atoul(lp->field[1], 0, 10);
3779 if (lp->field[0][0] == 'v' &&
3780 memcmp(lp->field[0], "vertical_resolution", 19) == 0) {
3783 "bdf: warning: %d: incorrect number of fields %d.\n",
3786 "bdf: warning: %d: vertical_resolution <cardinal>.\n",
3789 p->opts->resolution_y = _bdf_atoul(lp->field[1], 0, 10);
3793 if (lp->field[0][0] == 'f' &&
3794 memcmp(lp->field[0], "font_spacing", 12) == 0) {
3797 "bdf: warning: %d: incorrect number of fields %d.\n",
3800 "bdf: warning: %d: font_spacing <spacing name>.\n",
3803 switch (lp->field[1][0]) {
3805 p->opts->font_spacing = BDF_PROPORTIONAL;
3808 p->opts->font_spacing = BDF_MONOWIDTH;
3811 p->opts->font_spacing = BDF_CHARCELL;
3815 "bdf: warning: %d: unknown font spacing '%s'.\n",
3816 lineno, lp->field[1]);
3822 if (lp->field[0][0] == 'p' &&
3823 memcmp(lp->field[0], "property", 8) == 0) {
3826 "bdf: warning: %d: incorrect number of fields %d.\n",
3829 "bdf: warning: %d: property <name> <type>.\n",
3832 switch (lp->field[2][0]) {
3834 bdf_create_property(lp->field[1], BDF_ATOM);
3837 bdf_create_property(lp->field[1], BDF_CARDINAL);
3840 bdf_create_property(lp->field[1], BDF_INTEGER);
3844 "bdf: warning: %d: unknown property type '%s'.\n",
3845 lineno, lp->field[2]);
3851 if (lp->field[0][0] == 'h' &&
3852 (memcmp(lp->field[0], "hint_truetype_glyphs", 20) == 0 ||
3853 memcmp(lp->field[0], "hint_opentype_glyphs", 20) == 0)) {
3856 "bdf: warning: %d: incorrect number of fields %d.\n",
3859 "bdf: warning: %d: hint_opentype_glyphs <boolean>.\n",
3862 #ifdef HAVE_FREETYPE
3863 if (_bdf_get_boolean(lp->field[1]))
3864 p->opts->otf_flags &= ~FT_LOAD_NO_HINTING;
3866 p->opts->otf_flags |= FT_LOAD_NO_HINTING;
3868 p->opts->otf_flags = 0;
3869 #endif /* HAVE_FREETYPE */
3875 if (lp->field[0][0] == 'g' &&
3876 memcmp(lp->field[0], "generate_ranges", 15) == 0)
3878 * Simply ignore the glyph ranges entry in the config file.
3883 * If the callback returns a non-zero value, the caller has handled the
3884 * unknown option found in the file.
3886 if (p->callback != 0 &&
3887 (*p->callback)(p->opts, lp->field, lp->used, p->client_data) != 0)
3890 fprintf(stderr, "bdf: warning: %d: unknown configuration option '%s'.\n",
3891 lineno, lp->field[0]);
3896 bdf_load_options(FILE *in, bdf_options_t *opts,
3897 bdf_options_callback_t callback, void *client_data)
3899 unsigned int lineno;
3900 _bdf_opts_parse_t p;
3903 * Don't bother loading the options if the file or options structure
3906 if (in == 0 || opts == 0)
3909 (void *) memset((char *) &p, 0, sizeof(_bdf_opts_parse_t));
3911 p.callback = callback;
3912 p.client_data = client_data;
3913 (void) _bdf_readlines(fileno(in), _bdf_parse_options, (void *) &p,
3917 * Free up the list if there is any space allocated.
3919 if (p.list.size > 0)
3920 free((char *) p.list.field);
3924 bdf_save_options(FILE *out, bdf_options_t *opts)
3928 if (out == 0 || opts == 0)
3931 fprintf(out, "#\n# Metrics corrections.\n#\ncorrect_metrics ");
3932 if (opts->correct_metrics)
3933 fprintf(out, "true\n\n");
3935 fprintf(out, "false\n\n");
3937 fprintf(out, "#\n# Preserve unencoded glyphs.\n#\nkeep_unencoded ");
3938 if (opts->keep_unencoded)
3939 fprintf(out, "true\n\n");
3941 fprintf(out, "false\n\n");
3943 fprintf(out, "#\n# Preserve comments.\n#\nkeep_comments ");
3944 if (opts->keep_comments)
3945 fprintf(out, "true\n\n");
3947 fprintf(out, "false\n\n");
3949 fprintf(out, "#\n# Pad character cells.\n#\npad_character_cells ");
3950 if (opts->pad_cells)
3951 fprintf(out, "true\n\n");
3953 fprintf(out, "false\n\n");
3955 fprintf(out, "#\n# Font spacing.\n#\nfont_spacing ");
3956 switch (opts->font_spacing) {
3957 case BDF_PROPORTIONAL: fprintf(out, "proportional\n\n"); break;
3958 case BDF_MONOWIDTH: fprintf(out, "monowidth\n\n"); break;
3959 case BDF_CHARCELL: fprintf(out, "charactercell\n\n"); break;
3962 fprintf(out, "#\n# Point size.\n#\npoint_size %d\n\n", opts->point_size);
3965 "#\n# Horizontal resolution.\n#\nhorizontal_resolution %d\n\n",
3966 opts->resolution_x);
3969 "#\n# Vertical resolution.\n#\nvertical_resolution %d\n\n",
3970 opts->resolution_x);
3973 "#\n# Bits per pixel.\n#\nbits_per_pixel %d\n\n",
3974 opts->bits_per_pixel);
3976 fprintf(out, "#\n# Hint OpenType glyphs.\n#\nhint_opentype_glyphs ");
3977 #ifdef HAVE_FREETYPE
3978 if (opts->otf_flags & FT_LOAD_NO_HINTING)
3979 fprintf(out, "false\n\n");
3981 fprintf(out, "true\n\n");
3983 fprintf(out, "false\n\n");
3984 #endif /* HAVE_FREETYPE */
3986 fprintf(out, "#\n# Set the EOL used when writing BDF fonts.\n#\neol ");
3987 switch (opts->eol) {
3988 case BDF_UNIX_EOL: fprintf(out, "unix\n\n"); break;
3989 case BDF_DOS_EOL: fprintf(out, "dos\n\n"); break;
3990 case BDF_MAC_EOL: fprintf(out, "mac\n\n"); break;
3994 * Write out the user defined properties if they exist.
3996 if (nuser_props == 0)
3999 fprintf(out, "#\n# User defined properties.\n#\n");
4001 for (i = 0; i < nuser_props; i++) {
4002 fprintf(out, "property %s ", user_props[i].name);
4003 switch (user_props[i].format) {
4004 case BDF_ATOM: fprintf(out, "atom\n"); break;
4005 case BDF_CARDINAL: fprintf(out, "cardinal\n"); break;
4006 case BDF_INTEGER: fprintf(out, "integer\n"); break;
4012 bdf_default_options(bdf_options_t *opts)
4017 (void) memcpy((char *) opts, (char *) &_bdf_opts, sizeof(bdf_options_t));
4021 bdf_new_font(char *name, int point_size, int resolution_x, int resolution_y,
4022 int spacing, int bpp)
4028 bdf_property_t prop;
4030 font = (bdf_font_t *) calloc(1, sizeof(bdf_font_t));
4031 if (name != 0 && *name != 0) {
4032 font->name = (char *) malloc(strlen(name) + 1);
4033 (void) strcpy(font->name, name);
4037 font->point_size = point_size;
4038 font->resolution_x = resolution_x;
4039 font->resolution_y = resolution_y;
4042 * Determine the pixel size of the new font based on the
4043 * point size and resolution.
4045 dr = (double) resolution_y;
4046 dp = (double) (point_size * 10);
4047 psize = (int) (((dp * dr) / 722.7) + 0.5);
4050 * Make the default width about 1.5 smaller than the height.
4052 font->bbx.height = psize;
4053 font->bbx.width = ((double) psize) / 1.5;
4056 * Now determine the default ascent and descent assuming a
4057 * the descent is about 1/4 the ascent.
4059 font->bbx.descent = psize >> 2;
4060 font->bbx.ascent = psize - font->bbx.descent;
4062 font->bbx.y_offset = -font->bbx.descent;
4065 * Allocation the internal hash tables.
4067 font->internal = (void *) malloc(sizeof(hashtable));
4068 hash_init((hashtable *) font->internal);
4070 font->default_glyph = -1;
4071 font->spacing = spacing;
4074 * Add various useful properties.
4076 prop.name = "POINT_SIZE";
4077 prop.format = BDF_INTEGER;
4078 prop.value.int32 = font->point_size * 10;
4079 bdf_add_font_property(font, &prop);
4081 prop.name = "PIXEL_SIZE";
4082 prop.format = BDF_INTEGER;
4083 prop.value.int32 = psize;
4084 bdf_add_font_property(font, &prop);
4086 prop.name = "RESOLUTION_X";
4087 prop.format = BDF_CARDINAL;
4088 prop.value.card32 = (unsigned int) font->resolution_x;
4089 bdf_add_font_property(font, &prop);
4091 prop.name = "RESOLUTION_Y";
4092 prop.format = BDF_CARDINAL;
4093 prop.value.card32 = (unsigned int) font->resolution_y;
4094 bdf_add_font_property(font, &prop);
4096 prop.name = "FONT_ASCENT";
4097 prop.format = BDF_INTEGER;
4098 prop.value.int32 = (int) font->bbx.ascent;
4099 bdf_add_font_property(font, &prop);
4101 prop.name = "FONT_DESCENT";
4102 prop.format = BDF_INTEGER;
4103 prop.value.int32 = (int) font->bbx.descent;
4104 bdf_add_font_property(font, &prop);
4106 prop.name = "AVERAGE_WIDTH";
4107 prop.format = BDF_INTEGER;
4108 prop.value.int32 = font->bbx.width * 10;
4109 bdf_add_font_property(font, &prop);
4114 case BDF_PROPORTIONAL: sp[0] = 'P'; break;
4115 case BDF_MONOWIDTH: sp[0] = 'M'; break;
4116 case BDF_CHARCELL: sp[0] = 'C'; break;
4118 prop.name = "SPACING";
4119 prop.format = BDF_ATOM;
4120 prop.value.atom = sp;
4121 bdf_add_font_property(font, &prop);
4124 * Mark the font as unmodified.
4132 bdf_set_default_metrics(bdf_font_t *font)
4136 bdf_property_t prop;
4139 * Determine the pixel size of the new font based on the
4140 * point size and resolution.
4142 dr = (double) font->resolution_y;
4143 dp = (double) (font->point_size * 10);
4144 psize = (int) (((dp * dr) / 722.7) + 0.5);
4147 * Make the default width about 1.5 smaller than the height.
4149 font->bbx.height = psize;
4150 font->bbx.width = ((double) psize) / 1.5;
4153 * Now determine the default ascent and descent assuming a
4154 * the descent is about 1/4 the ascent.
4156 font->bbx.descent = psize >> 2;
4157 font->bbx.ascent = psize - font->bbx.descent;
4159 font->bbx.y_offset = -font->bbx.descent;
4161 font->default_glyph = -1;
4164 * Add various useful properties.
4166 prop.name = "FONT_ASCENT";
4167 prop.format = BDF_INTEGER;
4168 prop.value.int32 = (int) font->bbx.ascent;
4169 bdf_add_font_property(font, &prop);
4171 prop.name = "FONT_DESCENT";
4172 prop.format = BDF_INTEGER;
4173 prop.value.int32 = (int) font->bbx.descent;
4174 bdf_add_font_property(font, &prop);
4176 prop.name = "AVERAGE_WIDTH";
4177 prop.format = BDF_INTEGER;
4178 prop.value.int32 = font->bbx.width * 10;
4179 bdf_add_font_property(font, &prop);
4183 bdf_glyph_modified(bdf_font_t *font, int which, int unencoded)
4185 if (font == 0 || which < 0)
4189 return _bdf_glyph_modified(font->umod, which);
4191 return _bdf_glyph_modified(font->nmod, which);
4195 bdf_copy_glyphs(bdf_font_t *font, int start, int end,
4196 bdf_glyphlist_t *glyphs, int unencoded)
4199 bdf_glyph_t *cp, *dp;
4200 short maxas, maxds, maxrb, minlb, maxlb, rb;
4208 glyphs->bpp = font->bpp;
4209 glyphs->start = start;
4211 glyphs->glyphs_used = 0;
4213 tmp = (end - start) + 1;
4214 if (tmp > glyphs->glyphs_size) {
4215 if (glyphs->glyphs_size == 0)
4216 glyphs->glyphs = (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) * tmp);
4218 glyphs->glyphs = (bdf_glyph_t *) realloc((char *) glyphs->glyphs,
4219 sizeof(bdf_glyph_t) * tmp);
4220 cp = glyphs->glyphs + glyphs->glyphs_size;
4221 (void) memset((char *) cp, 0,
4222 sizeof(bdf_glyph_t) * (tmp - glyphs->glyphs_size));
4223 glyphs->glyphs_size = tmp;
4227 * Clear out bitmaps, names and any PSF Unicode mappings in the existing
4230 for (cp = glyphs->glyphs, i = 0; i < glyphs->glyphs_size; i++, cp++) {
4234 free((char *) cp->bitmap);
4235 if (cp->unicode.map_size > 0)
4236 free((char *) cp->unicode.map);
4240 * Zero out everything.
4242 (void) memset((char *) &glyphs->bbx, 0, sizeof(bdf_bbx_t));
4243 (void) memset((char *) glyphs->glyphs, 0,
4244 sizeof(bdf_glyph_t) * glyphs->glyphs_size);
4247 * Initialize the bounds used to generate the overall bounding box for the
4248 * set of glyphs being copied.
4250 minlb = font->bbx.width;
4251 maxlb = maxrb = maxas = maxds = 0;
4256 nc = (unencoded == 0) ? font->glyphs_used : font->unencoded_used;
4257 cp = (unencoded == 0) ? font->glyphs : font->unencoded;
4258 dp = glyphs->glyphs;
4261 i < nc && ((unencoded && i <= end) || cp->encoding <= end);
4263 if ((unencoded && i >= start) || cp->encoding >= start) {
4264 (void) memcpy((char *) dp, (char *) cp, sizeof(bdf_glyph_t));
4265 if (cp->name != 0) {
4266 dp->name = (char *) malloc(strlen(cp->name) + 1);
4267 (void) strcpy(dp->name, cp->name);
4269 if (cp->bytes > 0) {
4270 dp->bytes = cp->bytes;
4271 dp->bitmap = (unsigned char *) malloc(cp->bytes);
4272 (void) memcpy((char *) dp->bitmap, (char *) cp->bitmap,
4275 if (cp->unicode.map_used > 0) {
4276 dp->unicode.map_used = dp->unicode.map_size =
4277 cp->unicode.map_used;
4279 (unsigned char *) malloc(dp->unicode.map_used);
4280 (void) memcpy((char *) dp->unicode.map,
4281 (char *) cp->unicode.map,
4282 dp->unicode.map_used);
4286 * Determine the overall metrics for the group of characters being
4289 maxas = MAX(cp->bbx.ascent, maxas);
4290 maxds = MAX(cp->bbx.descent, maxds);
4291 rb = cp->bbx.width + cp->bbx.x_offset;
4292 maxrb = MAX(rb, maxrb);
4293 minlb = MIN(cp->bbx.x_offset, minlb);
4294 maxlb = MAX(cp->bbx.x_offset, maxlb);
4296 glyphs->glyphs_used++;
4302 * Set the overall metrics for this set of glyphs.
4304 glyphs->bbx.width = maxrb - minlb;
4305 glyphs->bbx.x_offset = minlb;
4307 glyphs->bbx.height = maxas + maxds;
4308 glyphs->bbx.ascent = maxas;
4309 glyphs->bbx.descent = maxds;
4310 glyphs->bbx.y_offset = -maxds;
4314 _bdf_locate_glyph(bdf_font_t *font, int code, int unencoded)
4319 if (code < 0 || font == 0)
4322 if ((unencoded && font->unencoded_used == 0) ||
4323 font->glyphs_used == 0)
4327 gl = font->unencoded;
4328 nc = font->unencoded_used;
4331 nc = font->glyphs_used;
4333 for (l = m = 0, r = nc - 1; l < r; ) {
4335 if (gl[m].encoding < code)
4337 else if (gl[m].encoding > code)
4344 * Go back until we hit the beginning of the glyphs or until
4345 * we find the glyph with a code less than the specified code.
4348 while (m > 0 && gl[m].encoding > code)
4352 * Look forward if necessary.
4355 while (m < nc && gl[m].encoding < code)
4358 return (m < nc) ? &gl[m] : &gl[nc - 1];
4362 bdf_delete_glyphs(bdf_font_t *font, int start, int end, int unencoded)
4364 int i, n, nc, cnt, mod;
4365 bdf_glyph_t *cp, *sp, *ep;
4378 nc = (unencoded == 0) ? font->glyphs_used : font->unencoded_used;
4379 cp = (unencoded == 0) ? font->glyphs : font->unencoded;
4382 for (i = 0; i < nc && cp->encoding <= end; i++, cp++) {
4383 if (cp->encoding >= start && sp == 0)
4392 * There are some glyphs to delete.
4393 * 1. Free the name and bitmap fields of the glyphs being deleted.
4394 * 2. Move the end range down if necessary.
4395 * 3. Clear the glyphs on the end if a move was done.
4399 * Mark the font as being modified.
4401 mod = font->modified = 1;
4405 for (cp = sp; cp < ep; cp++) {
4407 * Mark the glyphs being deleted as also being modified so the
4408 * empty cells can be shown correctly by the client programs.
4411 _bdf_set_glyph_modified(font->umod, cp->encoding);
4413 _bdf_set_glyph_modified(font->nmod, cp->encoding);
4418 free((char *) cp->bitmap);
4421 cp = (unencoded == 0) ? font->glyphs : font->unencoded;
4424 * Check to see if there are some glyphs that need to
4429 * Shift the glyphs down.
4432 _bdf_memmove((char *) sp, (char *) ep, sizeof(bdf_glyph_t) * n);
4435 * Set the starting point for the clear.
4440 * Set the starting point for the clear.
4445 * Clear the glyph space just moved.
4448 (void) memset((char *) ep, 0, sizeof(bdf_glyph_t) * n);
4451 * Adjust the number of glyphs used.
4454 font->glyphs_used -= cnt;
4456 font->unencoded_used -= cnt;
4459 * If unencoded glyphs were deleted, re-encode all
4460 * of them to cause a shift when everything is redrawn.
4462 if (unencoded != 0) {
4463 for (i = 0, cp = font->unencoded; i < font->unencoded_used;
4465 if (_bdf_glyph_modified(font->umod, cp->encoding)) {
4466 _bdf_clear_glyph_modified(font->umod, cp->encoding);
4467 _bdf_set_glyph_modified(font->umod, i);
4477 * These values are intended to give pixels mapped from 1bpp to nbpp the
4478 * darkest available index, which is 1.
4480 static unsigned char twobpp_ones[] = {0x40, 0x10, 0x04, 0x01};
4481 static unsigned char fourbpp_ones[] = {0x10, 0x01};
4482 static unsigned char eightbpp_ones[] = {0x01};
4485 * Routines for quick and dirty dithering.
4488 _bdf_one_to_n(bdf_glyphlist_t *gl, int n)
4491 unsigned short bpr, sbpr, bytes, col, sx, sy;
4492 unsigned char *nbmap, *ones = 0;
4495 if (gl == 0 || gl->glyphs_used == 0)
4499 case 1: ones = bdf_onebpp; break;
4500 case 2: ones = twobpp_ones; break;
4501 case 4: ones = fourbpp_ones; break;
4502 case 8: ones = eightbpp_ones; break;
4506 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4507 if (gp->bbx.width == 0 || gp->bbx.height == 0)
4509 sbpr = (gp->bbx.width + 7) >> 3;
4510 bpr = ((gp->bbx.width * n) + 7) >> 3;
4511 bytes = bpr * gp->bbx.height;
4512 nbmap = (unsigned char *) malloc(bytes);
4513 (void) memset((char *) nbmap, 0, bytes);
4515 for (sy = 0; sy < gp->bbx.height; sy++) {
4516 for (col = sx = 0; sx < gp->bbx.width; sx++, col += n) {
4517 if (gp->bitmap[(sy * sbpr) + (sx >> 3)] & (0x80 >> (sx & 7)))
4518 nbmap[(sy * bpr) + (col >> 3)] |= ones[(col & 7) / n];
4521 free((char *) gp->bitmap);
4528 _bdf_n_to_one(bdf_glyphlist_t *gl)
4531 unsigned short bpr, sbpr, bytes, col, sx, sy;
4532 unsigned char *nbmap, *masks;
4535 if (gl == 0 || gl->glyphs_used == 0)
4540 case 1: masks = bdf_onebpp; break;
4541 case 2: masks = bdf_twobpp; break;
4542 case 4: masks = bdf_fourbpp; break;
4543 case 8: masks = bdf_eightbpp; break;
4546 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4547 if (gp->bbx.width == 0 || gp->bbx.height == 0)
4549 sbpr = ((gp->bbx.width * gl->bpp) + 7) >> 3;
4550 bpr = (gp->bbx.width + 7) >> 3;
4551 bytes = bpr * gp->bbx.height;
4552 nbmap = (unsigned char *) malloc(bytes);
4553 (void) memset((char *) nbmap, 0, bytes);
4555 for (sy = 0; sy < gp->bbx.height; sy++) {
4556 for (col = sx = 0; sx < gp->bbx.width; sx++, col += gl->bpp) {
4557 if (gp->bitmap[(sy * sbpr) + (col >> 3)] &
4558 masks[(col & 7) / gl->bpp])
4559 nbmap[(sy * bpr) + (sx >> 3)] |= (0x80 >> (sx & 7));
4562 free((char *) gp->bitmap);
4570 _bdf_two_to_four(bdf_glyphlist_t *gl)
4573 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
4574 unsigned char *nbmap, *masks;
4577 if (gl == 0 || gl->glyphs_used == 0)
4582 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4583 if (gp->bbx.width == 0 || gp->bbx.height == 0)
4585 sbpr = ((gp->bbx.width << 1) + 7) >> 3;
4586 bpr = ((gp->bbx.width << 2) + 7) >> 3;
4587 bytes = bpr * gp->bbx.height;
4588 nbmap = (unsigned char *) malloc(bytes);
4589 (void) memset((char *) nbmap, 0, bytes);
4591 for (sy = 0; sy < gp->bbx.height; sy++) {
4592 for (col = sx = 0; sx < gp->bbx.width; sx++, col += 2) {
4593 si = (col & 7) >> 1;
4594 byte = gp->bitmap[(sy * sbpr) + (col >> 3)] & masks[si];
4597 byte >>= (3 - si) << 1;
4601 nbmap[(sy * bpr) + ((sx << 2) >> 3)] |= byte;
4605 free((char *) gp->bitmap);
4613 _bdf_four_to_two(bdf_glyphlist_t *gl)
4616 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
4617 unsigned char *nbmap, *masks;
4620 if (gl == 0 || gl->glyphs_used == 0)
4623 masks = bdf_fourbpp;
4626 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4627 sbpr = ((gp->bbx.width << 2) + 7) >> 3;
4628 bpr = ((gp->bbx.width << 1) + 7) >> 3;
4629 bytes = bpr * gp->bbx.height;
4630 nbmap = (unsigned char *) malloc(bytes);
4631 (void) memset((char *) nbmap, 0, bytes);
4633 for (sy = 0; sy < gp->bbx.height; sy++) {
4634 for (col = sx = 0; sx < gp->bbx.width; sx++, col += 4) {
4635 si = (col & 7) >> 2;
4636 byte = gp->bitmap[(sy * sbpr) + (col >> 3)] & masks[si];
4639 * Shift the byte down to make an index.
4645 * Scale the index to two bits per pixel and shift it into
4646 * place if necessary.
4650 * Any non-zero byte has to remain non-zero, because index
4651 * zero means no bits set.
4656 si = ((sx << 1) & 7) >> 1;
4658 byte <<= (3 - si) << 1;
4660 nbmap[(sy * bpr) + ((sx << 1) >> 3)] |= byte;
4664 free((char *) gp->bitmap);
4671 _bdf_two_to_eight(bdf_glyphlist_t *gl)
4674 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
4675 unsigned char *nbmap, *masks;
4678 if (gl == 0 || gl->glyphs_used == 0)
4683 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4684 if (gp->bbx.width == 0 || gp->bbx.height == 0)
4686 sbpr = ((gp->bbx.width << 1) + 7) >> 3;
4687 bpr = gp->bbx.width;
4688 bytes = bpr * gp->bbx.height;
4689 nbmap = (unsigned char *) malloc(bytes);
4690 (void) memset((char *) nbmap, 0, bytes);
4692 for (sy = 0; sy < gp->bbx.height; sy++) {
4693 for (col = sx = 0; sx < gp->bbx.width; sx++, col += 2) {
4694 si = (col & 7) >> 1;
4695 byte = gp->bitmap[(sy * sbpr) + (col >> 3)] & masks[si];
4698 * Shift the byte down to make an index.
4701 byte >>= (3 - si) * gl->bpp;
4704 * Scale the index to four bits per pixel and shift it into
4705 * place before adding it.
4708 nbmap[(sy * bpr) + sx] = byte;
4712 free((char *) gp->bitmap);
4720 _bdf_eight_to_two(bdf_glyphlist_t *gl)
4723 unsigned short bpr, sbpr, bytes, si, byte, sx, sy;
4724 unsigned char *nbmap, *masks;
4727 if (gl == 0 || gl->glyphs_used == 0)
4730 masks = bdf_fourbpp;
4733 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4734 sbpr = gp->bbx.width;
4735 bpr = ((gp->bbx.width << 1) + 7) >> 3;
4736 bytes = bpr * gp->bbx.height;
4737 nbmap = (unsigned char *) malloc(bytes);
4738 (void) memset((char *) nbmap, 0, bytes);
4740 for (sy = 0; sy < gp->bbx.height; sy++) {
4741 for (sx = 0; sx < gp->bbx.width; sx++) {
4742 byte = gp->bitmap[(sy * sbpr) + sx];
4748 si = ((sx << 1) & 7) >> 1;
4750 byte <<= (3 - si) << 1;
4752 nbmap[(sy * bpr) + ((sx << 1) >> 3)] |= byte;
4756 free((char *) gp->bitmap);
4763 _bdf_four_to_eight(bdf_glyphlist_t *gl)
4766 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
4767 unsigned char *nbmap, *masks;
4770 if (gl == 0 || gl->glyphs_used == 0)
4773 masks = bdf_fourbpp;
4775 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4776 if (gp->bbx.width == 0 || gp->bbx.height == 0)
4778 sbpr = ((gp->bbx.width << 2) + 7) >> 3;
4779 bpr = gp->bbx.width;
4780 bytes = bpr * gp->bbx.height;
4781 nbmap = (unsigned char *) malloc(bytes);
4782 (void) memset((char *) nbmap, 0, bytes);
4784 for (sy = 0; sy < gp->bbx.height; sy++) {
4785 for (col = sx = 0; sx < gp->bbx.width; sx++, col += 4) {
4786 si = (col & 7) >> 2;
4787 byte = gp->bitmap[(sy * sbpr) + (col >> 3)] & masks[si];
4793 nbmap[(sy * bpr) + sx] = byte;
4797 free((char *) gp->bitmap);
4805 _bdf_eight_to_four(bdf_glyphlist_t *gl)
4808 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
4809 unsigned char *nbmap, *masks;
4812 if (gl == 0 || gl->glyphs_used == 0)
4817 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4818 if (gp->bbx.width == 0 || gp->bbx.height == 0)
4820 sbpr = gp->bbx.width;
4821 bpr = ((gp->bbx.width << 2) + 7) >> 3;
4822 bytes = bpr * gp->bbx.height;
4823 nbmap = (unsigned char *) malloc(bytes);
4824 (void) memset((char *) nbmap, 0, bytes);
4826 for (sy = 0; sy < gp->bbx.height; sy++) {
4827 for (col = sx = 0; sx < gp->bbx.width; sx++, col += 2) {
4828 byte = gp->bitmap[(sy * sbpr) + sx];
4835 * Scale the index to four bits per pixel and shift it into
4836 * place before adding it.
4838 si = (col & 7) >> 2;
4841 nbmap[(sy * bpr) + ((sx << 2) >> 3)] |= byte;
4845 free((char *) gp->bitmap);
4853 * This only works on glyphs that exist.
4856 bdf_replace_mappings(bdf_font_t *font, int encoding, bdf_psf_unimap_t *map,
4861 if ((gp = _bdf_locate_glyph(font, encoding, unencoded)) == 0 ||
4862 gp->encoding != encoding)
4865 if (map->map_size > gp->unicode.map_size) {
4866 if (gp->unicode.map_size == 0)
4867 gp->unicode.map = (unsigned char *)
4868 malloc(sizeof(unsigned char) * map->map_size);
4870 gp->unicode.map =(unsigned char *)
4871 realloc((char *) gp->unicode.map,
4872 sizeof(unsigned char) * map->map_size);
4873 gp->unicode.map_size = map->map_size;
4875 gp->unicode.map_used = map->map_used;
4876 (void) memcpy((char *) gp->unicode.map, (char *) map->map,
4877 sizeof(unsigned char) * map->map_used);
4880 * Mark the glyph as modified.
4883 _bdf_set_glyph_modified(font->umod, gp->encoding);
4885 _bdf_set_glyph_modified(font->nmod, gp->encoding);
4893 bdf_replace_glyphs(bdf_font_t *font, int start, bdf_glyphlist_t *glyphs,
4896 int resize, appending;
4897 int i, n, ng, end, del, remaining, off[2];
4898 bdf_glyph_t *sgp, *gp, *dgp;
4899 short maxas, maxds, maxrb, minlb, maxlb, rb;
4909 * Dither the incoming bitmaps so they match the same bits per pixel as
4912 if (glyphs->bpp != font->bpp) {
4913 if (glyphs->bpp == 1)
4914 _bdf_one_to_n(glyphs, font->bpp);
4915 else if (font->bpp == 1)
4916 _bdf_n_to_one(glyphs);
4917 else if (glyphs->bpp == 2) {
4919 _bdf_two_to_four(glyphs);
4921 _bdf_two_to_eight(glyphs);
4922 } else if (glyphs->bpp == 4) {
4924 _bdf_four_to_two(glyphs);
4926 _bdf_four_to_eight(glyphs);
4927 } else if (glyphs->bpp == 8) {
4929 _bdf_eight_to_two(glyphs);
4931 _bdf_eight_to_four(glyphs);
4936 * Set the point size and horizontal resolution so the scalable width can
4939 ps = (double) font->point_size;
4940 rx = (double) font->resolution_x;
4943 * Determine if a resize is needed.
4947 * Determine the bounding box for the font without the characters being
4951 maxlb = maxrb = maxas = maxds = 0;
4954 * Get the font bounds.
4956 maxas = MAX(font->bbx.ascent, maxas);
4957 maxds = MAX(font->bbx.descent, maxds);
4958 rb = font->bbx.width + font->bbx.x_offset;
4959 maxrb = MAX(rb, maxrb);
4960 minlb = MIN(font->bbx.x_offset, minlb);
4961 maxlb = MAX(font->bbx.x_offset, maxlb);
4964 * Get the bounds of the incoming glyphs.
4966 maxas = MAX(glyphs->bbx.ascent, maxas);
4967 maxds = MAX(glyphs->bbx.descent, maxds);
4968 rb = glyphs->bbx.width + glyphs->bbx.x_offset;
4969 maxrb = MAX(rb, maxrb);
4970 minlb = MIN(glyphs->bbx.x_offset, minlb);
4971 maxlb = MAX(glyphs->bbx.x_offset, maxlb);
4974 * Set up the new font bounding box, minus the characters that are being
4975 * removed and with the new characters added.
4977 nbbx.width = maxrb - minlb;
4978 nbbx.x_offset = minlb;
4980 nbbx.height = maxas + maxds;
4981 nbbx.ascent = maxas;
4982 nbbx.descent = maxds;
4983 nbbx.y_offset = -maxds;
4986 * Now determine if the combination of the glyphs removed and the new
4987 * glyphs cause the font bounding box to be changed.
4989 resize = (nbbx.width > font->bbx.width ||
4990 nbbx.height > font->bbx.height) ? 1 : 0;
4993 * Set the pointers to the glyphs.
4995 ng = (unencoded == 0) ? font->glyphs_used : font->unencoded_used;
4996 sgp = gp = (unencoded == 0) ? font->glyphs : font->unencoded;
4999 * Locate the closest glyph on or following `start'.
5001 for (i = 0; i < ng && gp->encoding < start; i++, gp++) ;
5003 appending = (i == ng);
5006 * Set the starting point for copying the incoming glyphs.
5010 n = glyphs->end - glyphs->start;
5014 * Delete all the glyphs between `start' and `end'.
5016 for (del = 0, i = start; i <= end; i++) {
5018 * Mark the character as being modified.
5020 if (ng > 0 && !appending && gp->encoding == i) {
5022 _bdf_set_glyph_modified(font->nmod, i);
5024 _bdf_set_glyph_modified(font->umod, i);
5029 free((char *) gp->bitmap);
5030 if (gp->unicode.map_size > 0)
5031 free((char *) gp->unicode.map);
5038 * Determine how many glyphs remain following the last one deleted.
5040 remaining = ng - (gp - sgp);
5042 if (glyphs->glyphs_used == 0) {
5044 * If the glyph list is empty, then shift any remaining glyphs down
5045 * to the destination.
5047 _bdf_memmove((char *) dgp, (char *) gp,
5048 sizeof(bdf_glyph_t) * remaining);
5050 font->glyphs_used -= del;
5052 font->unencoded_used -= del;
5055 * Insert the glyph list after making sure there is enough space to
5056 * hold them. Also adjust the encoding and scalable width values
5057 * after copying the glyphs.
5059 if (unencoded == 0) {
5060 n = (font->glyphs_used - del) + glyphs->glyphs_used;
5061 if (n > font->glyphs_size) {
5064 if (font->glyphs_size == 0)
5065 font->glyphs = sgp =
5066 (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) * n);
5068 font->glyphs = sgp =
5069 (bdf_glyph_t *) realloc((char *) font->glyphs,
5070 sizeof(bdf_glyph_t) * n);
5073 font->glyphs_size = n;
5077 * Calculate how many will need to be shifted.
5079 if ((n = glyphs->glyphs_used - del) >= font->glyphs_used)
5082 n = (font->unencoded_used - del) + glyphs->glyphs_used;
5083 if (n > font->unencoded_size) {
5086 if (font->unencoded_size == 0)
5087 font->unencoded = sgp =
5088 (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) * n);
5090 font->unencoded = sgp =
5091 (bdf_glyph_t *) realloc((char *) font->unencoded,
5092 sizeof(bdf_glyph_t) * n);
5095 font->unencoded_size = n;
5099 * Calculate how many will need to be shifted.
5101 if ((n = glyphs->glyphs_used - del) >= font->unencoded_used)
5106 * Shift any following glyphs up or down if needed.
5109 _bdf_memmove((char *) (gp + n), (char *) gp,
5110 sizeof(bdf_glyph_t) * remaining);
5113 * Copy the incoming glyphs, copy their names and bitmaps,
5114 * set their encodings, and set their scalable widths.
5116 (void) memcpy((char *) dgp, (char *) glyphs->glyphs,
5117 sizeof(bdf_glyph_t) * glyphs->glyphs_used);
5118 for (i = 0; i < glyphs->glyphs_used; i++, dgp++) {
5120 dgp->name = (char *) _bdf_strdup((unsigned char *) dgp->name,
5121 strlen(dgp->name) + 1);
5124 dgp->bitmap = _bdf_strdup(dgp->bitmap, dgp->bytes);
5126 if (dgp->unicode.map_size > 0)
5127 dgp->unicode.map = _bdf_strdup(dgp->unicode.map,
5128 dgp->unicode.map_size);
5130 dgp->encoding = start + (dgp->encoding - glyphs->start);
5133 * Mark the glyph as being modified in case it fills a cell that
5136 _bdf_set_glyph_modified(font->nmod, dgp->encoding);
5138 dw = (double) dgp->dwidth;
5139 dgp->swidth = (unsigned short) ((dw * 72000.0) / (ps * rx));
5143 * Adjust the count of glyphs.
5145 ng = (ng - del) + glyphs->glyphs_used;
5147 font->glyphs_used = ng;
5149 font->unencoded_used = ng;
5153 * Last, if the replacement was done in the unencoded section,
5154 * reencode all the glyphs so they show up properly.
5156 if (unencoded != 0) {
5157 for (i = 0; i < ng; i++, sgp++) {
5158 if (_bdf_glyph_modified(font->umod, sgp->encoding)) {
5159 _bdf_clear_glyph_modified(font->umod, sgp->encoding);
5160 _bdf_set_glyph_modified(font->umod, i);
5167 (void) memcpy((char *) &font->bbx, (char *) &nbbx, sizeof(bdf_bbx_t));
5175 bdf_insert_glyphs(bdf_font_t *font, int start, bdf_glyphlist_t *glyphs)
5178 unsigned int i, ng, n, which;
5187 * Dither the incoming bitmaps so they match the same bits per pixel as
5190 if (glyphs->bpp != font->bpp) {
5191 if (glyphs->bpp == 1)
5192 _bdf_one_to_n(glyphs, font->bpp);
5193 else if (font->bpp == 1)
5194 _bdf_n_to_one(glyphs);
5195 else if (glyphs->bpp == 2)
5196 _bdf_two_to_four(glyphs);
5198 _bdf_four_to_two(glyphs);
5202 * Locate the starting glyph.
5205 ng = font->glyphs_used;
5206 for (i = 0; i < ng && gp->encoding < start; i++, gp++) ;
5209 * If there are no glyphs at the starting point, then simply do a replace.
5212 return bdf_replace_glyphs(font, start, glyphs, 0);
5215 * Go through the glyphs that would be shifted due to the insertion and
5216 * determine if some of them will overflow the 0xffff boundary.
5218 n = (glyphs->end - glyphs->start) + 1;
5219 for (which = i; i < ng; i++, gp++) {
5220 if (gp->encoding + n > 0xffff)
5226 * Some glyphs have to be moved to the unencoded area because they
5227 * would overflow the 0xffff boundary if they were moved up.
5229 bdf_copy_glyphs(font, gp->encoding, font->glyphs[ng - 1].encoding,
5230 &font->overflow, 0);
5231 bdf_delete_glyphs(font, gp->encoding, font->glyphs[ng - 1].encoding,
5233 resize += bdf_replace_glyphs(font, font->unencoded_used,
5234 &font->overflow, 1);
5238 * Go back to the insertion point and shift the remaining glyph encodings
5241 for (gp = font->glyphs + which; which < font->glyphs_used; which++, gp++) {
5243 * Mark the new glyph locations as being modified.
5246 _bdf_set_glyph_modified(font->nmod, gp->encoding);
5250 * Finally, mark the font as being modified and insert the new glyphs.
5254 return resize + bdf_replace_glyphs(font, start, glyphs, 0);
5258 _bdf_combine_glyphs(bdf_font_t *font, bdf_glyph_t *f, bdf_glyph_t *g)
5260 unsigned short x, sx, sy, si, dx, dy, di, byte, dbpr, fbpr, gbpr;
5261 short maxas, maxds, maxrb, minlb, maxlb, rb;
5262 unsigned char *masks;
5267 * Determine the max bounding box for the two glyphs.
5270 maxlb = maxrb = maxas = maxds = 0;
5273 * Get the font glyph bounds.
5275 maxas = MAX(f->bbx.ascent, maxas);
5276 maxds = MAX(f->bbx.descent, maxds);
5277 rb = f->bbx.width + f->bbx.x_offset;
5278 maxrb = MAX(rb, maxrb);
5279 minlb = MIN(f->bbx.x_offset, minlb);
5280 maxlb = MAX(f->bbx.x_offset, maxlb);
5283 * Get the bounds of the incoming glyph.
5285 maxas = MAX(g->bbx.ascent, maxas);
5286 maxds = MAX(g->bbx.descent, maxds);
5287 rb = g->bbx.width + g->bbx.x_offset;
5288 maxrb = MAX(rb, maxrb);
5289 minlb = MIN(g->bbx.x_offset, minlb);
5290 maxlb = MAX(g->bbx.x_offset, maxlb);
5293 * Set up the new glyph bounding box.
5295 nbbx.width = maxrb - minlb;
5296 nbbx.x_offset = minlb;
5297 nbbx.height = maxas + maxds;
5298 nbbx.ascent = maxas;
5299 nbbx.descent = maxds;
5300 nbbx.y_offset = -maxds;
5303 switch (font->bpp) {
5304 case 1: masks = bdf_onebpp; break;
5305 case 2: masks = bdf_twobpp; break;
5306 case 4: masks = bdf_fourbpp; break;
5307 case 8: masks = bdf_eightbpp; break;
5310 fbpr = ((f->bbx.width * font->bpp) + 7) >> 3;
5311 gbpr = ((g->bbx.width * font->bpp) + 7) >> 3;
5312 dbpr = ((nbbx.width * font->bpp) + 7) >> 3;
5314 if (memcmp((char *) &nbbx, (char *) &f->bbx, sizeof(bdf_bbx_t)) == 0) {
5316 * The largest is the first, so merge the second in with it.
5318 dy = f->bbx.ascent - g->bbx.ascent;
5319 for (sy = 0; sy < g->bbx.height; sy++, dy++) {
5320 for (x = sx = 0; x < g->bbx.width; x++, sx += font->bpp) {
5321 si = (sx & 7) / font->bpp;
5322 if ((byte = g->bitmap[(sy * gbpr) + (sx >> 3)] & masks[si]))
5324 * No shifting of the byte is needed because the x offset
5325 * is the same for both glyphs.
5327 f->bitmap[(dy * fbpr) + (sx >> 3)] |= byte;
5330 } else if (memcmp((char *) &nbbx, (char *) &g->bbx,
5331 sizeof(bdf_bbx_t)) == 0) {
5333 * The largest is the incoming glyph, so merge into that one and swap
5334 * it with the font glyph.
5336 dy = g->bbx.ascent - f->bbx.ascent;
5337 for (sy = 0; sy < f->bbx.height; sy++, dy++) {
5338 for (x = sx = 0; x < f->bbx.width; x++, sx += font->bpp) {
5339 si = (sx & 7) / font->bpp;
5340 if ((byte = f->bitmap[(sy * gbpr) + (sx >> 3)] & masks[si]))
5342 * No shifting of the byte is needed because the x offset
5343 * is the same for both glyphs.
5345 g->bitmap[(dy * fbpr) + (sx >> 3)] |= byte;
5350 * Now swap the two glyphs while preserving the name and encoding of
5353 tmp.swidth = g->swidth;
5354 tmp.dwidth = g->dwidth;
5355 tmp.bytes = g->bytes;
5356 tmp.bitmap = g->bitmap;
5357 (void) memcpy((char *) &tmp.bbx, (char *) &g->bbx, sizeof(bdf_bbx_t));
5359 g->swidth = f->swidth;
5360 g->dwidth = f->dwidth;
5361 g->bytes = f->bytes;
5362 g->bitmap = f->bitmap;
5363 (void) memcpy((char *) &g->bbx, (char *) &f->bbx, sizeof(bdf_bbx_t));
5365 f->swidth = tmp.swidth;
5366 f->dwidth = tmp.dwidth;
5367 f->bytes = tmp.bytes;
5368 f->bitmap = tmp.bitmap;
5369 (void) memcpy((char *) &f->bbx, (char *) &tmp.bbx, sizeof(bdf_bbx_t));
5372 * Need a new bitmap for the combination of the two.
5374 tmp.bytes = nbbx.height * dbpr;
5375 tmp.bitmap = (unsigned char *) malloc(tmp.bytes);
5376 (void) memset((char *) tmp.bitmap, 0, tmp.bytes);
5379 * Merge the first glyph.
5381 dy = nbbx.ascent - f->bbx.ascent;
5382 for (sy = 0; sy < f->bbx.height; sy++, dy++) {
5383 dx = MYABS(nbbx.x_offset - f->bbx.x_offset) * font->bpp;
5384 for (x = sx = 0; x < f->bbx.width; x++,
5385 sx += font->bpp, dx += font->bpp) {
5386 si = (sx & 7) / font->bpp;
5387 if ((byte = f->bitmap[(sy * fbpr) + (sx >> 3)] & masks[si])) {
5388 di = (dx & 7) / font->bpp;
5390 byte <<= (si - di) * font->bpp;
5392 byte >>= (di - si) * font->bpp;
5393 tmp.bitmap[(dy * dbpr) + (dx >> 3)] |= byte;
5399 * Merge the second glyph.
5401 dy = nbbx.ascent - g->bbx.ascent;
5402 for (sy = 0; sy < g->bbx.height; sy++, dy++) {
5403 dx = MYABS(nbbx.x_offset - g->bbx.x_offset) * font->bpp;
5404 for (x = sx = 0; x < g->bbx.width; x++,
5405 sx += font->bpp, dx += font->bpp) {
5406 si = (sx & 7) / font->bpp;
5407 if ((byte = g->bitmap[(sy * gbpr) + (sx >> 3)] & masks[si])) {
5408 di = (dx & 7) / font->bpp;
5410 byte <<= (si - di) * font->bpp;
5412 byte >>= (di - si) * font->bpp;
5413 tmp.bitmap[(dy * dbpr) + (dx >> 3)] |= byte;
5419 * Now clear the font glyph and copy the temp glyph to it.
5422 free((char *) f->bitmap);
5423 f->bytes = tmp.bytes;
5424 f->bitmap = tmp.bitmap;
5425 (void) memcpy((char *) &f->bbx, (char *) &nbbx, sizeof(bdf_bbx_t));
5428 * Set the device width. Pay attention to whether the font is
5429 * monowidth or character cell.
5431 if (font->spacing != BDF_PROPORTIONAL)
5432 f->dwidth = font->monowidth;
5434 f->dwidth = MAX(f->dwidth, g->dwidth);
5439 bdf_merge_glyphs(bdf_font_t *font, int start, bdf_glyphlist_t *glyphs,
5443 int i, n, ng, end, add, enc, off;
5444 bdf_glyph_t *sgp, *gp, *dgp, *base;
5445 short maxas, maxds, maxrb, minlb, maxlb, rb;
5455 * If the glyphs are being merged in the unencoded area, simply append
5456 * them. The unencoded area is simply storage.
5459 return bdf_replace_glyphs(font, font->unencoded_used, glyphs, unencoded);
5462 * Dither the incoming bitmaps so they match the same bits per pixel as
5465 if (glyphs->bpp != font->bpp) {
5466 if (glyphs->bpp == 1)
5467 _bdf_one_to_n(glyphs, font->bpp);
5468 else if (font->bpp == 1)
5469 _bdf_n_to_one(glyphs);
5470 else if (glyphs->bpp == 2)
5471 _bdf_two_to_four(glyphs);
5473 _bdf_four_to_two(glyphs);
5477 * Set the point size and horizontal resolution so the scalable width can
5480 ps = (double) font->point_size;
5481 rx = (double) font->resolution_x;
5484 * Determine if a resize is needed.
5488 * Determine the bounding box for the font without the characters being
5492 maxlb = maxrb = maxas = maxds = 0;
5495 * Get the font bounds.
5497 maxas = MAX(font->bbx.ascent, maxas);
5498 maxds = MAX(font->bbx.descent, maxds);
5499 rb = font->bbx.width + font->bbx.x_offset;
5500 maxrb = MAX(rb, maxrb);
5501 minlb = MIN(font->bbx.x_offset, minlb);
5502 maxlb = MAX(font->bbx.x_offset, maxlb);
5505 * Get the bounds of the incoming glyphs.
5507 maxas = MAX(glyphs->bbx.ascent, maxas);
5508 maxds = MAX(glyphs->bbx.descent, maxds);
5509 rb = glyphs->bbx.width + glyphs->bbx.x_offset;
5510 maxrb = MAX(rb, maxrb);
5511 minlb = MIN(glyphs->bbx.x_offset, minlb);
5512 maxlb = MAX(glyphs->bbx.x_offset, maxlb);
5515 * Set up the new font bounding box, minus the characters that are being
5516 * removed and with the new characters added.
5518 nbbx.width = maxrb - minlb;
5519 nbbx.x_offset = minlb;
5521 nbbx.height = maxas + maxds;
5522 nbbx.ascent = maxas;
5523 nbbx.descent = maxds;
5524 nbbx.y_offset = -maxds;
5527 * Now determine if the combination of the glyphs removed and the new
5528 * glyphs cause the font bounding box to be changed.
5530 resize = (nbbx.width > font->bbx.width ||
5531 nbbx.height > font->bbx.height) ? 1 : 0;
5534 * Set the pointers to the glyphs.
5536 ng = (unencoded == 0) ? font->glyphs_used : font->unencoded_used;
5537 gp = (unencoded == 0) ? font->glyphs : font->unencoded;
5540 * Locate the closest glyph on or following `start'.
5542 for (i = 0; i < ng && gp->encoding < start; i++, gp++) ;
5546 * If the gylphs are being added off the end of the list, simply insert
5547 * them so any overflows can be handled.
5549 return bdf_insert_glyphs(font, start, glyphs);
5552 * Set the starting point for copying the incoming glyphs.
5556 n = glyphs->end - glyphs->start;
5560 * Count the number of glyphs that will be added and mark all the
5561 * glyphs that will be modified.
5563 for (sgp = glyphs->glyphs, add = 0, i = start; i <= end; i++) {
5564 enc = (sgp->encoding - glyphs->start) + start;
5567 * Mark the glyph as being modified.
5570 _bdf_set_glyph_modified(font->nmod, enc);
5572 _bdf_set_glyph_modified(font->umod, enc);
5574 if (enc == gp->encoding)
5576 else if (enc < gp->encoding) {
5581 if (gp->encoding == i)
5589 * Need to make room for some glyphs that will be added.
5592 off = dgp - font->unencoded;
5593 if (font->unencoded_used == 0)
5595 (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) * ng);
5598 (bdf_glyph_t *) realloc((char *) font->unencoded,
5599 sizeof(bdf_glyph_t) * ng);
5600 dgp = font->unencoded + off;
5601 font->unencoded_used = ng;
5603 off = dgp - font->glyphs;
5604 if (font->glyphs_used == 0)
5606 (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) * ng);
5609 (bdf_glyph_t *) realloc((char *) font->glyphs,
5610 sizeof(bdf_glyph_t) * ng);
5611 dgp = font->glyphs + off;
5612 font->glyphs_used = ng;
5617 * Now go through and do two things:
5618 * 1. Insert new incoming glyphs.
5619 * 2. Combine two glyphs at the same location.
5621 base = (!unencoded) ? font->glyphs : font->unencoded;
5622 for (gp = dgp, sgp = glyphs->glyphs, i = start; i <= end; i++) {
5623 enc = (sgp->encoding - glyphs->start) + start;
5624 if (enc < gp->encoding) {
5626 * Shift the glyphs up by one and add this one.
5629 _bdf_memmove((char *) (gp + 1), (char *) gp,
5630 sizeof(bdf_glyph_t) * (ng - (gp - base)));
5631 (void) memcpy((char *) gp, (char *) sgp, sizeof(bdf_glyph_t));
5632 gp->name = (char *) _bdf_strdup((unsigned char *) gp->name,
5633 strlen(gp->name) + 1);
5635 gp->bitmap = _bdf_strdup(gp->bitmap, gp->bytes);
5636 if (gp->unicode.map_size > 0)
5637 gp->unicode.map = _bdf_strdup(gp->unicode.map,
5638 gp->unicode.map_size);
5641 dw = (double) gp->dwidth;
5642 gp->swidth = (unsigned short) ((dw * 72000.0) / (ps * rx));
5643 } else if (enc == gp->encoding) {
5644 _bdf_combine_glyphs(font, gp, sgp);
5645 dw = (double) gp->dwidth;
5646 gp->swidth = (unsigned short) ((dw * 72000.0) / (ps * rx));
5649 if (gp->encoding == i)
5654 (void) memcpy((char *) &font->bbx, (char *) &nbbx, sizeof(bdf_bbx_t));
5662 bdf_set_modified(bdf_font_t *font, int modified)
5664 if (font == 0 || font->modified == modified)
5667 if (modified == 0) {
5669 * Clear out the modified bitmaps.
5671 (void) memset((char *) font->nmod, 0, sizeof(unsigned int) * 2048);
5672 (void) memset((char *) font->umod, 0, sizeof(unsigned int) * 2048);
5674 font->modified = modified;
5677 /**************************************************************************
5679 * XLFD font name functions.
5681 **************************************************************************/
5683 static char *xlfdfields[] = {
5701 bdf_is_xlfd_property(char *name)
5705 for (i = 0; i < 14; i++) {
5706 if (strcmp(name, xlfdfields[i]) == 0)
5713 bdf_has_xlfd_name(bdf_font_t *font)
5719 if (font == 0 || font->name == 0 || font->name[0] == 0)
5722 len = (unsigned int) (strlen(font->name) + 1);
5723 (void) memcpy(name, font->name, len);
5724 list.size = list.used = 0;
5725 _bdf_split("-", name, len, &list);
5727 free((char *) list.field);
5729 return (list.used == 15);
5733 bdf_make_xlfd_name(bdf_font_t *font, char *foundry, char *family)
5737 unsigned int i, width, used;
5738 unsigned short awidth, pxsize;
5741 char spacing, *name, *val, *np, nbuf[256];
5743 if (font == 0 || bdf_has_xlfd_name(font))
5749 * Add the FOUNDRY field.
5751 if ((pp = bdf_get_font_property(font, "FOUNDRY")) != 0)
5752 foundry = pp->value.atom;
5753 sprintf(np, "-%s", foundry);
5757 * Add the FAMILY_NAME field.
5759 if ((pp = bdf_get_font_property(font, "FAMILY_NAME")) != 0)
5760 family = pp->value.atom;
5761 sprintf(np, "-%s", family);
5765 * Add the WEIGHT_NAME field.
5767 val = ((pp = bdf_get_font_property(font, "WEIGHT_NAME")) != 0) ?
5768 pp->value.atom : "Medium";
5771 sprintf(np, "-%s", val);
5775 * Add the SLANT field.
5777 val = ((pp = bdf_get_font_property(font, "SLANT")) != 0) ?
5778 pp->value.atom : "R";
5781 sprintf(np, "-%s", val);
5785 * Add the SETWIDTH_NAME field.
5787 val = ((pp = bdf_get_font_property(font, "SETWIDTH_NAME")) != 0) ?
5788 pp->value.atom : "Normal";
5791 sprintf(np, "-%s", val);
5795 * Add the ADD_STYLE_NAME field.
5797 val = ((pp = bdf_get_font_property(font, "ADD_STYLE_NAME")) != 0) ?
5798 pp->value.atom : "";
5801 sprintf(np, "-%s", val);
5805 * Add the PIXEL_SIZE field.
5807 if ((pp = bdf_get_font_property(font, "PIXEL_SIZE")) != 0)
5808 sprintf(np, "-%d", pp->value.int32);
5811 * Determine the pixel size.
5813 dp = (double) (font->point_size * 10);
5814 dr = (double) font->resolution_y;
5815 pxsize = (unsigned short) (((dp * dr) / 722.7) + 0.5);
5816 sprintf(np, "-%hd", pxsize);
5821 * Add the POINT_SIZE field.
5823 if ((pp = bdf_get_font_property(font, "POINT_SIZE")) != 0)
5824 sprintf(np, "-%d", pp->value.int32);
5826 sprintf(np, "-%d", font->point_size * 10);
5830 * Add the RESOLUTION_X field.
5832 if ((pp = bdf_get_font_property(font, "RESOLUTION_X")) != 0)
5833 sprintf(np, "-%d", pp->value.card32);
5835 sprintf(np, "-%d", font->resolution_x);
5839 * Add the RESOLUTION_Y field.
5841 if ((pp = bdf_get_font_property(font, "RESOLUTION_Y")) != 0)
5842 sprintf(np, "-%d", pp->value.card32);
5844 sprintf(np, "-%d", font->resolution_y);
5848 * Add the SPACING field.
5850 if ((pp = bdf_get_font_property(font, "SPACING")) != 0)
5851 spacing = pp->value.atom[0];
5854 switch (font->spacing) {
5855 case BDF_PROPORTIONAL: spacing = 'P'; break;
5856 case BDF_MONOWIDTH: spacing = 'M'; break;
5857 case BDF_CHARCELL: spacing = 'C'; break;
5860 sprintf(np, "-%c", spacing);
5864 * Add the AVERAGE_WIDTH field.
5866 if ((pp = bdf_get_font_property(font, "AVERAGE_WIDTH")) != 0)
5867 sprintf(np, "-%d", pp->value.int32);
5870 * Determine the average width of all the glyphs in the font.
5873 for (i = 0, gp = font->unencoded; i < font->unencoded_used; i++, gp++)
5874 width += gp->dwidth;
5875 for (i = 0, gp = font->glyphs; i < font->glyphs_used; i++, gp++)
5876 width += gp->dwidth;
5878 used = font->unencoded_used + font->glyphs_used;
5880 awidth = font->bbx.width * 10;
5882 awidth = (unsigned short) ((((float) width) /
5883 ((float) used)) * 10.0);
5884 sprintf(np, "-%hd", awidth);
5889 * Add the CHARSET_REGISTRY field.
5891 val = ((pp = bdf_get_font_property(font, "CHARSET_REGISTRY")) != 0) ?
5892 pp->value.atom : "FontSpecific";
5893 sprintf(np, "-%s", val);
5897 * Add the CHARSET_ENCODING field.
5899 val = ((pp = bdf_get_font_property(font, "CHARSET_ENCODING")) != 0) ?
5900 pp->value.atom : "0";
5901 sprintf(np, "-%s", val);
5904 len = (np - nbuf) + 1;
5905 name = (char *) malloc(len);
5906 (void) memcpy(name, nbuf, len);
5911 bdf_update_name_from_properties(bdf_font_t *font)
5916 char *np, name[128], nname[128];
5918 if (font == 0 || bdf_has_xlfd_name(font) == 0)
5921 (void) memset((char *) &list, 0, sizeof(_bdf_list_t));
5924 * Split the name into fields and shift out the first empty field.
5925 * This assumes that the font has a name.
5927 i = (unsigned int) strlen(font->name);
5928 (void) memcpy(name, font->name, i + 1);
5929 _bdf_split("-", name, i, &list);
5930 _bdf_shift(1, &list);
5933 * Initialize the pointer to the new name and add the '-' prefix.
5939 for (i = 0; i < 14; i++) {
5940 if ((p = bdf_get_font_property(font, xlfdfields[i])) != 0) {
5942 * The property exists, so add it to the new font name.
5944 switch (p->format) {
5946 if (p->value.atom != 0)
5947 sprintf(np, "%s", p->value.atom);
5950 sprintf(np, "%d", p->value.card32);
5953 sprintf(np, "%d", p->value.int32);
5958 * The property does not exist, so add the original value to the
5961 sprintf(np, "%s", list.field[i]);
5970 * Replace the existing font name with the new one.
5973 i = (unsigned int) (strlen(nname) + 1);
5974 font->name = (char *) malloc(i);
5975 (void) memcpy(font->name, nname, i);
5981 free((char *) list.field);
5987 bdf_update_properties_from_name(bdf_font_t *font)
5990 bdf_property_t *p, prop;
5994 if (font == 0 || font->name == 0 || bdf_has_xlfd_name(font) == 0)
5997 (void) memset((char *) &list, 0, sizeof(_bdf_list_t));
6000 * Split the name into fields and shift out the first empty field.
6002 i = (unsigned int) strlen(font->name);
6003 (void) memcpy(name, font->name, i + 1);
6004 _bdf_split("-", name, i, &list);
6005 _bdf_shift(1, &list);
6007 for (i = 0; i < 14; i++) {
6008 p = bdf_get_property(xlfdfields[i]);
6009 prop.name = p->name;
6010 prop.format = p->format;
6011 switch (prop.format) {
6013 prop.value.atom = list.field[i];
6016 prop.value.card32 = _bdf_atoul(list.field[i], 0, 10);
6019 prop.value.int32 = _bdf_atol(list.field[i], 0, 10);
6022 bdf_add_font_property(font, &prop);
6029 free((char *) list.field);
6037 bdf_update_average_width(bdf_font_t *font)
6041 int oaw, awidth, used;
6044 bdf_property_t *pp, prop;
6045 char *np, num[16], nbuf[128];
6049 used = font->unencoded_used + font->glyphs_used;
6051 awidth = font->bbx.width * 10;
6053 for (i = 0, awidth = 0, gp = font->unencoded; i < font->unencoded_used;
6055 awidth += gp->dwidth;
6056 for (i = 0, gp = font->glyphs; i < font->glyphs_used; i++, gp++)
6057 awidth += gp->dwidth;
6058 awidth = (int) ((((double) awidth) / ((double) used)) * 10.0);
6062 * Check to see if it is different than the average width in the font
6065 if (bdf_has_xlfd_name(font)) {
6066 (void) memset((char *) &list, 0, sizeof(_bdf_list_t));
6067 i = (unsigned int) strlen(font->name);
6068 (void) memcpy(nbuf, font->name, i + 1);
6069 _bdf_split("-", nbuf, i, &list);
6070 oaw = _bdf_atol(list.field[12], 0, 10);
6071 if (oaw != awidth) {
6073 * Construct a new font name with the new average width.
6076 sprintf(num, "%d", awidth);
6077 used = strlen(num) - strlen(list.field[12]);
6080 * Resize the string used for the font name instead of
6081 * creating a new one.
6084 font->name = (char *) realloc(font->name, used);
6088 * Copy the elements of the list back into the new font name.
6092 for (i = 1; i < list.used; i++) {
6096 strcpy(np, list.field[i]);
6098 if (i + 1 < list.used)
6104 * Clear up any space allocated for the list.
6107 free((char *) list.field);
6111 * Now check for the AVERAGE_WIDTH property.
6113 if ((pp = bdf_get_font_property(font, "AVERAGE_WIDTH")) != 0) {
6114 if (pp->value.int32 != awidth) {
6116 pp->value.int32 = awidth;
6120 * Property doesn't exist yet, so add it.
6123 prop.name = "AVERAGE_WIDTH";
6124 prop.format = BDF_INTEGER;
6125 prop.value.int32 = awidth;
6126 bdf_add_font_property(font, &prop);
6136 * Change the font bounding box and return a non-zero number if this causes
6137 * the font to get larger or smaller.
6140 bdf_set_font_bbx(bdf_font_t *font, bdf_metrics_t *metrics)
6146 if (font == 0 || metrics == 0)
6149 resize = (font->bbx.width != metrics->width ||
6150 font->bbx.height != metrics->height) ? 1 : 0;
6152 font->bbx.width = metrics->width;
6153 font->bbx.height = metrics->height;
6154 font->bbx.x_offset = metrics->x_offset;
6155 font->bbx.y_offset = metrics->y_offset;
6156 font->bbx.ascent = metrics->ascent;
6157 font->bbx.descent = metrics->descent;
6160 * If the font is not proportional, then make sure the monowidth field is
6161 * set to the font bounding box.
6163 if (font->spacing != BDF_PROPORTIONAL)
6164 font->monowidth = font->bbx.width;
6170 bdf_translate_glyphs(bdf_font_t *font, short dx, short dy, int start,
6171 int end, bdf_callback_t callback, void *data,
6175 bdf_glyph_t *gp, *sp, *ep;
6176 bdf_callback_struct_t cb;
6178 if (font == 0 || (dx == 0 && dy == 0))
6181 if ((unencoded && font->unencoded_used == 0) || font->glyphs_used == 0)
6185 * Call the progress initialization callback.
6187 if (callback != 0) {
6188 cb.reason = BDF_TRANSLATE_START;
6189 cb.total = (end - start) + 1;
6191 (*callback)(&cb, data);
6195 * Locate the first and last glyphs to be shifted.
6197 sp = _bdf_locate_glyph(font, start, unencoded);
6198 ep = _bdf_locate_glyph(font, end, unencoded);
6199 for (resize = 0, gp = sp; sp <= ep; sp++) {
6201 * Call the callback if one was provided.
6203 if (sp != gp && callback != 0) {
6204 cb.reason = BDF_TRANSLATING;
6205 cb.current = (sp->encoding - start) + 1;
6206 (*callback)(&cb, data);
6210 * Apply the X translation.
6213 sp->bbx.x_offset += dx;
6214 diff = sp->bbx.x_offset - font->bbx.x_offset;
6215 if (sp->bbx.x_offset < font->bbx.x_offset) {
6216 font->bbx.x_offset = sp->bbx.x_offset;
6217 font->bbx.width += MYABS(diff);
6219 } else if (sp->bbx.width + sp->bbx.x_offset >
6220 font->bbx.width + font->bbx.x_offset) {
6221 font->bbx.width += MYABS(diff);
6226 * Mark the glyph as modified appropriately.
6229 _bdf_set_glyph_modified(font->umod, sp->encoding);
6231 _bdf_set_glyph_modified(font->nmod, sp->encoding);
6235 * Apply the Y translation.
6238 sp->bbx.y_offset += dy;
6239 sp->bbx.descent = -sp->bbx.y_offset;
6240 sp->bbx.ascent = sp->bbx.height - sp->bbx.descent;
6241 diff = sp->bbx.y_offset - font->bbx.y_offset;
6242 if (sp->bbx.y_offset < font->bbx.y_offset) {
6243 font->bbx.y_offset = sp->bbx.y_offset;
6244 font->bbx.descent = -font->bbx.y_offset;
6245 font->bbx.height += MYABS(diff);
6247 } else if (sp->bbx.ascent > font->bbx.ascent) {
6248 font->bbx.ascent += MYABS(diff);
6249 font->bbx.height += MYABS(diff);
6254 * Mark the glyph as modified appropriately.
6257 _bdf_set_glyph_modified(font->umod, sp->encoding);
6259 _bdf_set_glyph_modified(font->nmod, sp->encoding);
6264 * Call the callback one more time to make sure the client knows
6267 if (callback != 0 && cb.current < cb.total) {
6268 cb.reason = BDF_TRANSLATING;
6269 cb.current = cb.total;
6270 (*callback)(&cb, data);
6280 _bdf_resize_rotation(bdf_font_t *font, int mul90, short degrees,
6281 bdf_glyph_t *glyph, bdf_bitmap_t *scratch,
6282 unsigned short *width, unsigned short *height)
6284 unsigned short w, h, wd, ht, bytes;
6285 short cx, cy, x1, y1, x2, y2;
6286 double dx1, dy1, dx2, dy2;
6290 cx = glyph->bbx.width >> 1;
6291 cy = glyph->bbx.height >> 1;
6294 * Rotate the lower left and upper right corners and check for a potential
6298 y1 = glyph->bbx.height;
6299 x2 = glyph->bbx.width;
6302 dx1 = (double) (x1 - cx);
6303 dy1 = (double) (y1 - cy);
6304 dx2 = (double) (x2 - cx);
6305 dy2 = (double) (y2 - cx);
6308 x1 = cx + (short) ((dx1 * _bdf_cos_tbl[degrees]) -
6309 (dy1 * _bdf_sin_tbl[degrees]));
6310 y1 = cy + (short) ((dx1 * _bdf_sin_tbl[degrees]) +
6311 (dy1 * _bdf_cos_tbl[degrees]));
6312 x2 = cx + (short) ((dx2 * _bdf_cos_tbl[degrees]) -
6313 (dy2 * _bdf_sin_tbl[degrees]));
6314 y2 = cy + (short) ((dx2 * _bdf_sin_tbl[degrees]) +
6315 (dy2 * _bdf_cos_tbl[degrees]));
6317 x1 = cx + _bdf_ceiling((dx1 * _bdf_cos_tbl[degrees]) -
6318 (dy1 * _bdf_sin_tbl[degrees]));
6319 y1 = cy + _bdf_ceiling((dx1 * _bdf_sin_tbl[degrees]) +
6320 (dy1 * _bdf_cos_tbl[degrees]));
6321 x2 = cx + _bdf_ceiling((dx2 * _bdf_cos_tbl[degrees]) -
6322 (dy2 * _bdf_sin_tbl[degrees]));
6323 y2 = cy + _bdf_ceiling((dx2 * _bdf_sin_tbl[degrees]) +
6324 (dy2 * _bdf_cos_tbl[degrees]));
6327 wd = MYABS(x2 - x1);
6328 ht = MYABS(y2 - y1);
6333 if (wd > font->bbx.width)
6334 font->bbx.width += wd - font->bbx.width;
6335 if (ht > font->bbx.height) {
6336 font->bbx.ascent += ht - font->bbx.height;
6337 font->bbx.height += ht - font->bbx.height;
6341 * Rotate the upper left and lower right corners and check for a potential
6346 x2 = glyph->bbx.width;
6347 y2 = glyph->bbx.height;
6349 dx1 = (double) (x1 - cx);
6350 dy1 = (double) (y1 - cy);
6351 dx2 = (double) (x2 - cx);
6352 dy2 = (double) (y2 - cx);
6355 x1 = cx + (short) ((dx1 * _bdf_cos_tbl[degrees]) -
6356 (dy1 * _bdf_sin_tbl[degrees]));
6357 y1 = cy + (short) ((dx1 * _bdf_sin_tbl[degrees]) +
6358 (dy1 * _bdf_cos_tbl[degrees]));
6359 x2 = cx + (short) ((dx2 * _bdf_cos_tbl[degrees]) -
6360 (dy2 * _bdf_sin_tbl[degrees]));
6361 y2 = cy + (short) ((dx2 * _bdf_sin_tbl[degrees]) +
6362 (dy2 * _bdf_cos_tbl[degrees]));
6364 x1 = cx + _bdf_ceiling((dx1 * _bdf_cos_tbl[degrees]) -
6365 (dy1 * _bdf_sin_tbl[degrees]));
6366 y1 = cy + _bdf_ceiling((dx1 * _bdf_sin_tbl[degrees]) +
6367 (dy1 * _bdf_cos_tbl[degrees]));
6368 x2 = cx + _bdf_ceiling((dx2 * _bdf_cos_tbl[degrees]) -
6369 (dy2 * _bdf_sin_tbl[degrees]));
6370 y2 = cy + _bdf_ceiling((dx2 * _bdf_sin_tbl[degrees]) +
6371 (dy2 * _bdf_cos_tbl[degrees]));
6374 wd = MYABS(x2 - x1);
6375 ht = MYABS(y2 - y1);
6380 if (wd > font->bbx.width)
6381 font->bbx.width += wd - font->bbx.width;
6382 if (ht > font->bbx.height) {
6383 font->bbx.ascent += ht - font->bbx.height;
6384 font->bbx.height += ht - font->bbx.height;
6387 if (font->bbx.width > scratch->width ||
6388 font->bbx.height > scratch->height) {
6389 scratch->width = MAX(font->bbx.width, scratch->width);
6390 scratch->height = MAX(font->bbx.height, scratch->height);
6391 bytes = (((font->bbx.width * font->bpp) + 7) >> 3) * font->bbx.height;
6392 if (scratch->bytes == 0)
6393 scratch->bitmap = (unsigned char *) malloc(bytes);
6395 scratch->bitmap = (unsigned char *)
6396 realloc((char *) scratch->bitmap, bytes);
6397 scratch->bytes = bytes;
6403 (void) memset((char *) scratch->bitmap, 0, scratch->bytes);
6406 * Return the new glyph width and height.
6413 bdf_rotate_glyphs(bdf_font_t *font, short degrees, int start,
6414 int end, bdf_callback_t callback, void *data,
6417 int mul90, bpr, sbpr;
6418 unsigned short wd, ht, si, di, byte, col;
6419 short x, y, cx, cy, nx, ny, ox, oy, shiftx, shifty;
6420 bdf_glyph_t *gp, *sp, *ep;
6421 unsigned char *masks;
6423 bdf_bitmap_t scratch;
6424 bdf_callback_struct_t cb;
6427 (unencoded && font->unencoded_used == 0) ||
6428 font->glyphs_used == 0 ||
6434 while (degrees >= 360)
6437 mul90 = ((degrees % 90) == 0) ? 1 : 0;
6440 switch (font->bpp) {
6441 case 1: masks = bdf_onebpp; break;
6442 case 2: masks = bdf_twobpp; break;
6443 case 4: masks = bdf_fourbpp; break;
6444 case 8: masks = bdf_eightbpp; break;
6448 * Initialize the scratch bitmap.
6450 (void) memset((char *) &scratch, 0, sizeof(bdf_bitmap_t));
6453 * Call the progress initialization callback.
6455 if (callback != 0) {
6456 cb.reason = BDF_ROTATE_START;
6457 cb.total = (end - start) + 1;
6459 (*callback)(&cb, data);
6462 sp = _bdf_locate_glyph(font, start, unencoded);
6463 ep = _bdf_locate_glyph(font, end, unencoded);
6464 for (gp = sp; sp <= ep; sp++) {
6466 * Call the callback if one was provided.
6468 if (sp != gp && callback != 0) {
6469 cb.reason = BDF_ROTATING;
6470 cb.current = (sp->encoding - start) + 1;
6471 (*callback)(&cb, data);
6475 * Resize the bitmap, adjust the font bounding box, and get the new
6476 * glyph width and height.
6478 _bdf_resize_rotation(font, mul90, degrees, sp, &scratch, &wd, &ht);
6480 cx = sp->bbx.width >> 1;
6481 cy = sp->bbx.height >> 1;
6483 shiftx = shifty = 0;
6484 sbpr = ((wd * font->bpp) + 7) >> 3;
6485 bpr = ((sp->bbx.width * font->bpp) + 7) >> 3;
6486 for (y = 0; y < sp->bbx.height; y++) {
6487 for (col = x = 0; x < sp->bbx.width; x++, col += font->bpp) {
6488 si = (col & 7) / font->bpp;
6489 byte = sp->bitmap[(y * bpr) + (col >> 3)] & masks[si];
6491 dx = (double) (x - cx);
6492 dy = (double) (y - cy);
6494 nx = cx + (short) ((dx * _bdf_cos_tbl[degrees]) -
6495 (dy * _bdf_sin_tbl[degrees]));
6496 ny = cy + (short) ((dx * _bdf_sin_tbl[degrees]) +
6497 (dy * _bdf_cos_tbl[degrees]));
6499 nx = cx + _bdf_ceiling((dx * _bdf_cos_tbl[degrees]) -
6500 (dy * _bdf_sin_tbl[degrees]));
6501 ny = cy + _bdf_ceiling((dx * _bdf_sin_tbl[degrees]) +
6502 (dy * _bdf_cos_tbl[degrees]));
6505 shiftx = MIN(shiftx, nx);
6507 } else if (nx >= wd) {
6509 shiftx = MAX(shiftx, ox);
6513 shifty = MIN(shifty, ny);
6515 } else if (ny >= ht) {
6517 shifty = MAX(shifty, oy);
6521 di = (nx & 7) / font->bpp;
6523 byte <<= (si - di) * font->bpp;
6525 byte >>= (di - si) * font->bpp;
6526 scratch.bitmap[(ny * sbpr) + (nx >> 3)] |= byte;
6531 * Resize the glyph bitmap if necessary.
6533 if (wd != sp->bbx.width || ht != sp->bbx.height) {
6535 sp->bbx.height = ht;
6536 sp->bbx.ascent = ht - sp->bbx.descent;
6537 sp->bytes = (((wd * font->bpp) + 7) >> 3) * ht;
6538 sp->bitmap = (unsigned char *)
6539 realloc((char *) sp->bitmap, sp->bytes);
6541 (void) memset((char *) sp->bitmap, 0, sp->bytes);
6544 * Copy the glyph from the scratch area to the glyph bitmap,
6545 * adjusting for any shift values encountered.
6547 bpr = ((sp->bbx.width * font->bpp) + 7) >> 3;
6548 for (y = 0; y < sp->bbx.height; y++) {
6549 for (col = x = 0; x < sp->bbx.width; x++, col += font->bpp) {
6550 si = (col & 7) / font->bpp;
6551 byte = scratch.bitmap[(y * bpr) + (col >> 3)] & masks[si];
6556 nx += sp->bbx.width;
6557 else if (nx >= sp->bbx.width)
6558 nx -= sp->bbx.width;
6560 ny += sp->bbx.height;
6561 else if (ny >= sp->bbx.height)
6562 ny -= sp->bbx.height;
6564 di = (nx & 7) / font->bpp;
6566 byte <<= (si - di) * font->bpp;
6568 byte >>= (di - si) * font->bpp;
6569 sp->bitmap[(ny * bpr) + (nx >> 3)] |= byte;
6574 * Mark the glyph as modified.
6577 _bdf_set_glyph_modified(font->umod, sp->encoding);
6579 _bdf_set_glyph_modified(font->nmod, sp->encoding);
6583 * Call the callback one more time to make sure the client knows
6586 if (callback != 0 && cb.current < cb.total) {
6587 cb.reason = BDF_TRANSLATING;
6588 cb.current = cb.total;
6589 (*callback)(&cb, data);
6592 if (scratch.bytes > 0)
6593 free((char *) scratch.bitmap);
6596 * Rotations always change things, so just return a value indicating this.
6603 _bdf_resize_shear(bdf_font_t *font, int neg, short degrees,
6604 bdf_glyph_t *glyph, bdf_bitmap_t *scratch,
6605 unsigned short *width, unsigned short *height)
6607 unsigned short wd, w, bytes;
6608 short x1, y1, x2, y2;
6611 *height = glyph->bbx.height;
6614 * Shear the lower left and upper right corners and check for a potential
6618 y1 = glyph->bbx.height;
6619 x2 = glyph->bbx.width;
6623 x1 += (short) ((double) y1 * _bdf_tan_tbl[degrees]);
6624 x2 += (short) ((double) y2 * _bdf_tan_tbl[degrees]);
6626 x1 += (short) ((double) (glyph->bbx.height - y1) *
6627 _bdf_tan_tbl[degrees]);
6628 x2 += (short) ((double) (glyph->bbx.height - y2) *
6629 _bdf_tan_tbl[degrees]);
6632 wd = MYABS(x2 - x1);
6635 if (wd > font->bbx.width)
6636 font->bbx.width += wd - font->bbx.width;
6639 * Shear the upper left and lower right corners and check for a potential
6644 x2 = glyph->bbx.width;
6645 y2 = glyph->bbx.height;
6648 x1 += (short) ((double) y1 * _bdf_tan_tbl[degrees]);
6649 x2 += (short) ((double) y2 * _bdf_tan_tbl[degrees]);
6651 x1 += (short) ((double) (glyph->bbx.height - y1) *
6652 _bdf_tan_tbl[degrees]);
6653 x2 += (short) ((double) (glyph->bbx.height - y2) *
6654 _bdf_tan_tbl[degrees]);
6657 wd = MYABS(x2 - x1);
6660 if (wd > font->bbx.width)
6661 font->bbx.width += wd - font->bbx.width;
6663 if (font->bbx.width > scratch->width ||
6664 font->bbx.height > scratch->height) {
6665 scratch->width = MAX(font->bbx.width, scratch->width);
6666 scratch->height = MAX(font->bbx.height, scratch->height);
6667 bytes = (((font->bbx.width * font->bpp) + 7) >> 3) * font->bbx.height;
6668 if (scratch->bytes == 0)
6669 scratch->bitmap = (unsigned char *) malloc(bytes);
6671 scratch->bitmap = (unsigned char *)
6672 realloc((char *) scratch->bitmap, bytes);
6673 scratch->bytes = bytes;
6679 (void) memset((char *) scratch->bitmap, 0, scratch->bytes);
6682 * Return the new glyph width.
6688 bdf_shear_glyphs(bdf_font_t *font, short degrees, int start,
6689 int end, bdf_callback_t callback, void *data,
6693 unsigned short wd, ht, si, di, byte, col;
6694 short x, y, nx, shiftx, ox;
6695 bdf_glyph_t *gp, *sp, *ep;
6696 unsigned char *masks;
6697 bdf_bitmap_t scratch;
6698 bdf_callback_struct_t cb;
6700 if (font == 0 || (unencoded && font->unencoded_used == 0) ||
6701 font->glyphs_used == 0)
6704 if (degrees == 0 || degrees < -45 || degrees > 45)
6707 if ((neg = (degrees < 0)))
6711 switch (font->bpp) {
6712 case 1: masks = bdf_onebpp; break;
6713 case 2: masks = bdf_twobpp; break;
6714 case 4: masks = bdf_fourbpp; break;
6715 case 8: masks = bdf_eightbpp; break;
6719 * Initialize the scratch bitmap.
6721 (void) memset((char *) &scratch, 0, sizeof(bdf_bitmap_t));
6724 * Call the progress initialization callback.
6726 if (callback != 0) {
6727 cb.reason = BDF_SHEAR_START;
6728 cb.total = (end - start) + 1;
6730 (*callback)(&cb, data);
6733 sp = _bdf_locate_glyph(font, start, unencoded);
6734 ep = _bdf_locate_glyph(font, end, unencoded);
6735 for (gp = sp; sp <= ep; sp++) {
6737 * Call the callback if one was provided.
6739 if (sp != gp && callback != 0) {
6740 cb.reason = BDF_SHEARING;
6741 cb.current = (sp->encoding - start) + 1;
6742 (*callback)(&cb, data);
6746 * Resize the bitmap, adjust the font bounding box, and get the new
6747 * glyph width and height.
6749 _bdf_resize_shear(font, neg, degrees, sp, &scratch, &wd, &ht);
6752 sbpr = ((wd * font->bpp) + 7) >> 3;
6753 bpr = ((sp->bbx.width * font->bpp) + 7) >> 3;
6754 for (y = 0; y < sp->bbx.height; y++) {
6755 for (col = x = 0; x < sp->bbx.width; x++, col += font->bpp) {
6756 si = (col & 7) / font->bpp;
6757 byte = sp->bitmap[(y * bpr) + (col >> 3)] & masks[si];
6760 nx = x + (short) ((double) y * _bdf_tan_tbl[degrees]);
6762 nx = x + (short) ((double) (sp->bbx.height - y) *
6763 _bdf_tan_tbl[degrees]);
6766 shiftx = MIN(shiftx, nx);
6768 } else if (nx >= wd) {
6770 shiftx = MAX(shiftx, ox);
6774 di = (nx & 7) / font->bpp;
6776 byte <<= (si - di) * font->bpp;
6778 byte >>= (di - si) * font->bpp;
6779 scratch.bitmap[(y * sbpr) + (nx >> 3)] |= byte;
6784 * Resize the glyph bitmap if necessary.
6786 if (wd != sp->bbx.width || ht != sp->bbx.height) {
6788 sp->bbx.height = ht;
6789 sp->bbx.ascent = ht - sp->bbx.descent;
6790 sp->bytes = (((wd * font->bpp) + 7) >> 3) * ht;
6791 sp->bitmap = (unsigned char *)
6792 realloc((char *) sp->bitmap, sp->bytes);
6794 (void) memset((char *) sp->bitmap, 0, sp->bytes);
6797 * Copy the glyph from the scratch area to the glyph bitmap,
6798 * adjusting for any shift values encountered.
6800 bpr = ((sp->bbx.width * font->bpp) + 7) >> 3;
6801 for (y = 0; y < sp->bbx.height; y++) {
6802 for (col = x = 0; x < sp->bbx.width; x++, col += font->bpp) {
6803 si = (col & 7) / font->bpp;
6804 byte = scratch.bitmap[(y * bpr) + (col >> 3)] & masks[si];
6808 nx += sp->bbx.width;
6809 else if (nx >= sp->bbx.width)
6810 nx -= sp->bbx.width;
6812 di = (nx & 7) / font->bpp;
6814 byte <<= (si - di) * font->bpp;
6816 byte >>= (di - si) * font->bpp;
6817 sp->bitmap[(y * bpr) + (nx >> 3)] |= byte;
6822 * Mark the glyph as modified.
6825 _bdf_set_glyph_modified(font->umod, sp->encoding);
6827 _bdf_set_glyph_modified(font->nmod, sp->encoding);
6831 * Call the callback one more time to make sure the client knows
6834 if (callback != 0 && cb.current < cb.total) {
6835 cb.reason = BDF_TRANSLATING;
6836 cb.current = cb.total;
6837 (*callback)(&cb, data);
6840 if (scratch.bytes > 0)
6841 free((char *) scratch.bitmap);
6844 * Rotations always change things, so just return a value indicating this.
6851 _bdf_widen_by(bdf_font_t *f, bdf_glyph_t *g, bdf_bitmap_t *s, int n)
6853 int bytes, sbpr, dbpr, col;
6855 unsigned char *bmap, *masks;
6859 case 1: masks = bdf_onebpp; break;
6860 case 2: masks = bdf_twobpp; break;
6861 case 4: masks = bdf_fourbpp; break;
6862 case 8: masks = bdf_eightbpp; break;
6865 s->height = g->bbx.height;
6866 s->width = g->bbx.width + n;
6868 bytes = (((s->width * f->bpp) + 7) >> 3) * s->height;
6871 s->bitmap = (unsigned char *) malloc(bytes);
6873 s->bitmap = (unsigned char *)
6874 realloc((char *) s->bitmap, bytes);
6877 (void) memset((char *) s->bitmap, 0, s->bytes);
6880 * Copy the glyph bitmap to the scratch area, and then swap the bitmaps.
6882 sbpr = ((g->bbx.width * f->bpp) + 7) >> 3;
6883 dbpr = ((s->width * f->bpp) + 7) >> 3;
6884 for (y = 0; y < g->bbx.height; y++) {
6885 for (col = x = 0; x < g->bbx.width; x++, col += f->bpp) {
6886 si = (col & 7) / f->bpp;
6887 bytes = g->bitmap[(y * sbpr) + (col >> 3)] & masks[si];
6889 di = ((x * f->bpp) & 7) / f->bpp;
6891 bytes <<= (si - di) * f->bpp;
6893 bytes >>= (di - si) * f->bpp;
6894 s->bitmap[(y * dbpr) + (col >> 3)] |= bytes;
6898 g->bbx.width = s->width;
6901 * Swap the bytes and bitmap fields from the scratch area and the glyph.
6904 g->bytes = s->bytes;
6908 g->bitmap = s->bitmap;
6913 bdf_embolden_glyphs(bdf_font_t *font, int start, int end,
6914 bdf_callback_t callback, void *data, int unencoded,
6919 unsigned short si, di, b1, b2, col;
6920 unsigned char *masks;
6921 bdf_glyph_t *gp, *sp, *ep;
6922 bdf_bitmap_t scratch;
6923 bdf_callback_struct_t cb;
6925 if (font == 0 || (unencoded && font->unencoded_used == 0) ||
6926 font->glyphs_used == 0)
6930 * Initialize the scratch bitmap which may be needed.
6932 (void) memset((char *) &scratch, 0, sizeof(bdf_bitmap_t));
6938 switch (font->bpp) {
6939 case 1: masks = bdf_onebpp; break;
6940 case 2: masks = bdf_twobpp; break;
6941 case 4: masks = bdf_fourbpp; break;
6942 case 8: masks = bdf_eightbpp; break;
6946 * Call the progress initialization callback.
6948 if (callback != 0) {
6949 cb.reason = BDF_EMBOLDEN_START;
6950 cb.total = (end - start) + 1;
6952 (*callback)(&cb, data);
6956 * Initialize the resize flag for the caller.
6960 sp = _bdf_locate_glyph(font, start, unencoded);
6961 ep = _bdf_locate_glyph(font, end, unencoded);
6962 for (; sp <= ep; sp++) {
6964 * Call the callback if one was provided.
6966 if (sp != gp && callback != 0) {
6967 cb.reason = BDF_EMBOLDENING;
6968 cb.current = (sp->encoding - start) + 1;
6969 (*callback)(&cb, data);
6972 if (font->spacing == BDF_PROPORTIONAL ||
6973 (font->spacing == BDF_MONOWIDTH &&
6974 sp->bbx.width < font->bbx.width)) {
6976 * Only widen the glyph if it is within reason.
6978 _bdf_widen_by(font, sp, &scratch, 1);
6980 if (sp->bbx.width > font->bbx.width) {
6982 * Bump the font width up by the difference.
6984 font->bbx.width += sp->bbx.width - font->bbx.width;
6990 bpr = ((sp->bbx.width * font->bpp) + 7) >> 3;
6991 for (y = 0; y < sp->bbx.height; y++) {
6992 col = (sp->bbx.width - 1) * font->bpp;
6993 for (x = sp->bbx.width - 1; x > 0; x--, col -= font->bpp) {
6994 si = (col & 7) / font->bpp;
6995 di = ((col - font->bpp) & 7) / font->bpp;
6996 b1 = (x == sp->bbx.width) ? 0 :
6997 sp->bitmap[(y * bpr) + (col >> 3)] & masks[si];
6998 b2 = sp->bitmap[(y * bpr) + ((col - font->bpp) >> 3)] &
7002 b2 >>= (si - di) * font->bpp;
7004 b2 <<= (di - si) * font->bpp;
7005 sp->bitmap[(y * bpr) + (col >> 3)] |= b2;
7011 * Mark the glyph as modified.
7015 _bdf_set_glyph_modified(font->umod, sp->encoding);
7017 _bdf_set_glyph_modified(font->nmod, sp->encoding);
7022 * Call the callback one more time to make sure the client knows
7025 if (callback != 0 && cb.current < cb.total) {
7026 cb.reason = BDF_EMBOLDENING;
7027 cb.current = cb.total;
7028 (*callback)(&cb, data);
7032 * Deallocate the scratch bitmap if necessary.
7034 if (scratch.bytes > 0)
7035 free((char *) scratch.bitmap);
7037 font->modified = mod;
7042 static int _endian = 1;
7043 static char *little_endian = (char *) &_endian;
7046 bdf_little_endian(void)
7048 return *little_endian;