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 + (long) 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 = (long) 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);
3114 static const unsigned char lookup[16] = {
3118 0x3, 0xB, 0x7, 0xF };
3120 static unsigned char byte_flip( const unsigned char n )
3122 return (lookup[n&0x0F] << 4) | lookup[n>>4];
3126 bdf_export_header(FILE *out, bdf_font_t *font, bdf_options_t *opts,
3127 bdf_callback_t callback, void *data)
3129 int bpr, fbpr, j, k;
3131 bdf_glyph_t *gp, cell;
3132 bdf_callback_struct_t cb;
3133 bdf_property_t *fprop;
3134 char fname[32], weightname[32];
3136 if (font == 0 || out == 0)
3139 if (font->glyphs_used == 0)
3143 * Call the callback if it was passed to start the export.
3145 if (callback != 0) {
3146 cb.reason = BDF_EXPORT_START;
3147 cb.total = font->glyphs_used;
3149 (*callback)(&cb, data);
3152 fbpr = ((font->bbx.width * font->bpp) + 7) >> 3;
3153 bpr = (((font->bbx.width >> 1) * font->bpp) + 7) >> 3;
3154 cell.bytes = fbpr * font->bbx.height;
3155 cell.bitmap = (unsigned char *) malloc(cell.bytes);
3157 fprop = bdf_get_font_property(font, "FAMILY_NAME");
3159 if (fprop != NULL && fprop->format == BDF_ATOM)
3160 fprintf(out, "fontname %s ", fprop->value.atom);
3162 if (fprop != NULL && fprop->format == BDF_ATOM)
3163 strncpy(fname, fprop->value.atom, 32);
3165 strncpy(fname, "NoName", 32);
3167 fprop = bdf_get_font_property(font, "WEIGHT_NAME");
3168 if (fprop != NULL && fprop->format == BDF_ATOM)
3169 strncpy(weightname, fprop->value.atom, 32);
3171 strncpy(weightname, "none", 32);
3173 fprintf(out, "/* %s */\n", font->name);
3174 fprintf(out, "#define FONT_WIDTH_%s%s_%dx%d\t%d\n", fname, weightname, font->bbx.width, font->bbx.height, font->bbx.width);
3175 fprintf(out, "#define FONT_HEIGHT_%s%s_%dx%d\t%d\n", fname, weightname, font->bbx.width, font->bbx.height, font->bbx.height);
3177 fprintf(out, "const uint8_t FONT_DATA_%s%s_%dx%d[%d][%d] = {\n", fname, weightname, font->bbx.width, font->bbx.height, font->glyphs_used, cell.bytes + ((font->spacing == BDF_PROPORTIONAL) ? 1 : 0));
3179 for (i = 0, ng = font->glyphs_used, gp = font->glyphs; i < ng; i++, gp++) {
3180 _bdf_pad_cell(font, gp, &cell);
3182 fprintf(out, "%dx%d ", gp->bbx.width, gp->bbx.height);
3183 fprintf(out, "%04X:", gp->encoding & 0xffff);
3185 if (font->spacing == BDF_PROPORTIONAL) {
3186 fprintf(out, "{/*w*/%d,",gp->dwidth /*gp->bbx.width*/);
3190 if (gp->bbx.width <= (font->bbx.width >> 1)) {
3191 for (j = 0; j < cell.bytes; j += fbpr) {
3192 for (k = 0; k < bpr; k++)
3193 fprintf(out, "a0x%02x,", cell.bitmap[j + k]);
3196 for (j = 0; j < cell.bytes; j++)
3197 fprintf(out, "0x%02x,", byte_flip(cell.bitmap[j]));
3200 fprintf(out, "},\n");
3203 * Call the callback if supplied.
3205 if (callback != 0) {
3206 cb.reason = BDF_EXPORTING;
3208 (*callback)(&cb, data);
3211 fprintf(out, "};\n");
3214 * Clean up the cell.
3216 free((char *) cell.bitmap);
3219 * Always call a final callback to make sure the client gets a chance to
3222 if (callback != 0) {
3223 cb.reason = BDF_EXPORTING;
3224 cb.current = cb.total;
3225 (*callback)(&cb, data);
3230 bdf_free_font(bdf_font_t *font)
3233 bdf_glyph_t *glyphs;
3238 if (font->name != 0)
3242 * Free up the internal hash table of property names.
3244 hash_free((hashtable *) font->internal);
3245 free((char *) font->internal);
3248 * Free up the comment info.
3250 if (font->comments_len > 0)
3251 free(font->comments);
3254 * Free up the auto-correction messages.
3256 if (font->acmsgs_len > 0)
3260 * Free up the properties.
3262 for (i = 0; i < font->props_size; i++) {
3263 if (font->props[i].format == BDF_ATOM && font->props[i].value.atom)
3264 free(font->props[i].value.atom);
3267 if (font->props_size > 0 && font->props != 0)
3268 free((char *) font->props);
3271 * Free up the character info.
3273 for (i = 0, glyphs = font->glyphs; i < font->glyphs_used; i++, glyphs++) {
3276 if (glyphs->bytes > 0 && glyphs->bitmap != 0)
3277 free((char *) glyphs->bitmap);
3280 for (i = 0, glyphs = font->unencoded; i < font->unencoded_used;
3284 if (glyphs->bytes > 0)
3285 free((char *) glyphs->bitmap);
3286 if (glyphs->unicode.map_size > 0)
3287 free((char *) glyphs->unicode.map);
3290 if (font->glyphs_size > 0)
3291 free((char *) font->glyphs);
3293 if (font->unencoded_size > 0)
3294 free((char *) font->unencoded);
3297 * Free up the overflow storage if it was used.
3299 for (i = 0, glyphs = font->overflow.glyphs; i < font->overflow.glyphs_used;
3301 if (glyphs->name != 0)
3303 if (glyphs->bytes > 0)
3304 free((char *) glyphs->bitmap);;
3305 if (glyphs->unicode.map_size > 0)
3306 free((char *) glyphs->unicode.map);
3308 if (font->overflow.glyphs_size > 0)
3309 free((char *) font->overflow.glyphs);
3311 free((char *) font);
3315 bdf_create_property(char *name, int format)
3321 * First check to see if the property has
3322 * already been added or not. If it has, then
3326 if (hash_lookup(name, &proptbl))
3329 if (nuser_props == 0)
3330 user_props = (bdf_property_t *) malloc(sizeof(bdf_property_t));
3332 user_props = (bdf_property_t *) realloc((char *) user_props,
3333 sizeof(bdf_property_t) *
3336 p = user_props + nuser_props;
3337 (void) memset((char *) p, 0, sizeof(bdf_property_t));
3338 n = (unsigned int) (strlen(name) + 1);
3339 p->name = (char *) malloc(n);
3340 (void) memcpy(p->name, name, n);
3344 n = _num_bdf_properties + nuser_props;
3345 hash_insert(p->name, (void *) n, &proptbl);
3351 bdf_get_property(char *name)
3354 unsigned int propid;
3356 if (name == 0 || *name == 0)
3359 if ((hn = hash_lookup(name, &proptbl)) == 0)
3362 propid = (long) hn->data;
3363 if (propid >= _num_bdf_properties)
3364 return user_props + (propid - _num_bdf_properties);
3365 return _bdf_properties + propid;
3369 * Routine to compare two property names.
3372 by_prop_name(const void *a, const void *b)
3374 bdf_property_t *p1, *p2;
3376 p1 = (bdf_property_t *) a;
3377 p2 = (bdf_property_t *) b;
3379 return strcmp(p1->name, p2->name);
3383 bdf_property_list(bdf_property_t **props)
3388 n = _num_bdf_properties + nuser_props;
3389 if (props != 0 && n != 0) {
3390 p = (bdf_property_t *) malloc(sizeof(bdf_property_t) * n);
3391 (void) memcpy((char *) p, (char *) _bdf_properties,
3392 sizeof(bdf_property_t) * _num_bdf_properties);
3393 (void) memcpy((char *) (p + _num_bdf_properties), (char *) user_props,
3394 sizeof(bdf_property_t) * nuser_props);
3395 qsort((char *) p, n, sizeof(bdf_property_t), by_prop_name);
3402 bdf_replace_comments(bdf_font_t *font, char *comments,
3403 unsigned int comments_len)
3405 if (font == 0 || comments_len == 0)
3408 if (font->comments_len > 0)
3409 free(font->comments);
3411 font->comments = (char *) malloc(comments_len + 1);
3412 (void) memcpy(font->comments, comments, comments_len);
3413 font->comments[comments_len] = 0;
3414 font->comments_len = comments_len;
3420 bdf_font_property_list(bdf_font_t *font, bdf_property_t **props)
3424 if (font == 0 || font->props_used == 0)
3428 p = (bdf_property_t *) malloc(sizeof(bdf_property_t) *
3430 (void) memcpy((char *) p, (char *) font->props,
3431 sizeof(bdf_property_t) * font->props_used);
3432 qsort((char *) p, font->props_used, sizeof(bdf_property_t),
3437 return font->props_used;
3441 bdf_add_font_property(bdf_font_t *font, bdf_property_t *property)
3444 unsigned int propid;
3446 bdf_property_t *p, *ip;
3448 if (property == 0 || property->name == 0 || property->name[0] == 0)
3452 * If the font does not have a property hash table yet, make
3453 * sure it is allocated.
3455 if (font->internal == 0) {
3456 font->internal = (void *) malloc(sizeof(hashtable));
3457 hash_init((hashtable *) font->internal);
3461 * See if the property is in the general property table yet.
3462 * If it isn't, then add it.
3464 if ((hn = hash_lookup(property->name, &proptbl)) == 0)
3465 bdf_create_property(property->name, property->format);
3468 * If the property exists and is a user defined property, make sure
3469 * its format is updated to match the property being added.
3471 propid = (long) hn->data;
3472 if (propid >= _num_bdf_properties) {
3473 p = user_props + (propid - _num_bdf_properties);
3474 if (p->format != property->format)
3475 p->format = property->format;
3480 * If the font already has this property, then change the existing one.
3482 hn = hash_lookup(property->name, (hashtable *) font->internal);
3485 * Changing an existing property value.
3487 p = font->props + ((long) hn->data);
3490 * If the format changed, then free the atom value if the original
3491 * format was an atom.
3493 if (p->format == BDF_ATOM && property->format != BDF_ATOM &&
3495 free((char *) p->value.atom);
3496 p->format = property->format;
3498 switch (p->format) {
3501 * If the property value is the same, then just return.
3503 if (property->value.atom == p->value.atom ||
3504 (property->value.atom && p->value.atom &&
3505 strcmp(property->value.atom, p->value.atom) == 0))
3507 if (property->value.atom == 0)
3510 len = strlen(property->value.atom) + 1;
3512 p->value.atom = (char *) malloc(len);
3513 (void) memcpy(p->value.atom, property->value.atom, len);
3519 * If the property value is the same, then just return.
3521 if (p->value.int32 == property->value.int32)
3523 p->value.int32 = property->value.int32;
3527 * If the property value is the same, then just return.
3529 if (p->value.card32 == property->value.card32)
3531 p->value.card32 = property->value.card32;
3536 * New property being added.
3540 * Get the internal table entry for a pointer to the
3541 * name of the property.
3543 hn = hash_lookup(property->name, &proptbl);
3544 propid = (long) hn->data;
3545 if (propid >= _num_bdf_properties)
3546 ip = user_props + (propid - _num_bdf_properties);
3548 ip = _bdf_properties + propid;
3551 * Add it to the property list first.
3553 if (font->props_used == font->props_size) {
3554 if (font->props_size == 0)
3555 font->props = (bdf_property_t *) malloc(sizeof(bdf_property_t));
3557 font->props = (bdf_property_t *)
3558 realloc((char *) font->props, sizeof(bdf_property_t) *
3559 (font->props_size + 1));
3562 p = font->props + font->props_used;
3565 p->format = ip->format;
3566 p->builtin = ip->builtin;
3568 switch (p->format) {
3570 if (property->value.atom == 0)
3573 len = strlen(property->value.atom) + 1;
3575 p->value.atom = (char *) malloc(len);
3576 (void) memcpy(p->value.atom, property->value.atom, len);
3581 p->value.int32 = property->value.int32;
3584 p->value.card32 = property->value.card32;
3589 * Now insert it into the internal hash table.
3591 hash_insert(p->name, (void *) font->props_used,
3592 (hashtable *) font->internal);
3596 if (memcmp(property->name, "DEFAULT_CHAR", 12) == 0)
3598 * If the property just added is DEFAULT_CHAR, then make sure the
3599 * default_glyph field is set.
3601 font->default_glyph = p->value.card32;
3602 else if (memcmp(property->name, "FONT_ASCENT", 11) == 0)
3604 * If the property just added is FONT_ASCENT, then adjust the
3605 * font_ascent field.
3607 font->font_ascent = p->value.int32;
3608 else if (memcmp(property->name, "FONT_DESCENT", 12) == 0)
3610 * If the property just added is FONT_DESCENT, then adjust the
3611 * font_descent field.
3613 font->font_descent = p->value.int32;
3614 else if (memcmp(property->name, "RESOLUTION_X", 12) == 0)
3616 * If the property just added is RESOLUTION_X, then adjust the
3617 * resolution_x field.
3619 font->resolution_x = p->value.card32;
3620 else if (memcmp(property->name, "RESOLUTION_Y", 12) == 0)
3622 * If the property just added is RESOLUTION_Y, then adjust the
3623 * resolution_y field.
3625 font->resolution_y = p->value.card32;
3626 else if (memcmp(property->name, "POINT_SIZE", 10) == 0)
3628 * If the property just added is POINT_SIZE, then adjust the
3631 font->point_size = p->value.int32 / 10;
3632 else if (memcmp(property->name, "SPACING", 7) == 0) {
3634 * Make sure the font spacing is kept in synch if the property
3635 * changes. If the spacing changes from proportional to one
3636 * of the others, force the monowidth to be set.
3638 switch (p->value.atom[0]) {
3640 if (font->spacing == BDF_PROPORTIONAL)
3641 font->monowidth = font->bbx.width + font->bbx.x_offset;
3642 font->spacing = BDF_CHARCELL;
3645 if (font->spacing == BDF_PROPORTIONAL)
3646 font->monowidth = font->bbx.width + font->bbx.x_offset;
3647 font->spacing = BDF_MONOWIDTH;
3649 case 'P': case 'p': font->spacing = BDF_PROPORTIONAL; break;
3654 * Make sure the font is marked as modified.
3660 bdf_delete_font_property(bdf_font_t *font, char *name)
3666 if (font == 0 || name == 0 || *name == 0 || font->props_used == 0)
3669 if ((hn = hash_lookup(name, (hashtable *) font->internal)) == 0)
3672 off = (long) hn->data;
3673 p = font->props + off;
3676 * Delete the ATOM value if appropriate.
3678 if (p->format == BDF_ATOM && p->value.atom != 0)
3679 free(p->value.atom);
3682 * The property exists. Two things needs to be done:
3683 * 1. Remove the property from the hash table.
3684 * 2. Remove the property from the font's list of properties.
3686 hash_delete(name, (hashtable *) font->internal);
3689 * Locate its offset in the font property list.
3691 if (off < font->props_used - 1)
3693 * We have to shift the property list down.
3695 _bdf_memmove((char *) p, (char *) (p + 1),
3696 sizeof(bdf_property_t) * ((font->props_used - 1) - off));
3700 * If the font property happens to be DEFAULT_CHAR, then make sure the
3701 * default_glyph field is reset.
3703 if (strncmp(name, "DEFAULT_CHAR", 12) == 0)
3704 font->default_glyph = -1;
3707 * Update the hash table with the correct indexes.
3709 for (off = 0, p = font->props; off < font->props_used; off++, p++)
3710 hash_insert(p->name, (void *) off, (hashtable *) font->internal);
3713 * Mark the font as being modified.
3719 bdf_get_font_property(bdf_font_t *font, char *name)
3723 if (font == 0 || font->props_size == 0 || name == 0 || *name == 0)
3726 hn = hash_lookup(name, (hashtable *) font->internal);
3727 return (hn) ? (font->props + ((long) hn->data)) : 0;
3731 bdf_options_t *opts;
3732 bdf_options_callback_t callback;
3735 } _bdf_opts_parse_t;
3738 _bdf_get_boolean(char *val)
3743 if (val == 0 || *val == 0)
3747 case '0': case 'F': case 'f': case 'N': case 'n': ok = 0; break;
3748 case '1': case 'T': case 't': case 'Y': case 'y': ok = 1; break;
3754 _bdf_parse_options(char *line, unsigned int linelen, unsigned int lineno,
3755 void *call_data, void *client_data)
3758 _bdf_opts_parse_t *p;
3761 p = (_bdf_opts_parse_t *) client_data;
3765 * Split the line into fields.
3767 _bdf_split(" \t+", line, linelen, lp);
3769 if (lp->field[0][0] == 'b' &&
3770 memcmp(lp->field[0], "bits_per_pixel", 14) == 0) {
3773 "bdf: warning: %d: incorrect number of fields %d.\n",
3776 "bdf: warning: %d: bits_per_pixel <1, 2, or 4>.\n",
3779 bpp = _bdf_atol(lp->field[1], 0, 10);
3780 if (!(bpp == 1 || bpp == 2 || bpp == 4)) {
3782 "bdf: warning: %d: invalid bits per pixel %d.\n",
3785 "bdf: warning: %d: bits_per_pixel <1, 2, or 4>.\n",
3788 p->opts->bits_per_pixel = bpp;
3793 if (lp->field[0][0] == 'e' && memcmp(lp->field[0], "eol", 3) == 0) {
3796 "bdf: warning: %d: incorrect number of fields %d.\n",
3799 "bdf: warning: %d: eol <eolname>.\n", lineno);
3801 switch (lp->field[1][0]) {
3802 case 'u': case 'U': p->opts->eol = BDF_UNIX_EOL; break;
3803 case 'd': case 'D': p->opts->eol = BDF_DOS_EOL; break;
3804 case 'm': case 'M': p->opts->eol = BDF_MAC_EOL; break;
3810 if (lp->field[0][0] == 'c' &&
3811 memcmp(lp->field[0], "correct_metrics", 15) == 0) {
3814 "bdf: warning: %d: incorrect number of fields %d.\n",
3817 "bdf: warning: %d: correct_metrics <boolean>.\n", lineno);
3819 p->opts->correct_metrics = _bdf_get_boolean(lp->field[1]);
3824 if (lp->field[0][0] == 'k' &&
3825 memcmp(lp->field[0], "keep_unencoded", 14) == 0) {
3828 "bdf: warning: %d: incorrect number of fields %d.\n",
3831 "bdf: warning: %d: keep_unencoded <boolean>.\n", lineno);
3833 p->opts->keep_unencoded = _bdf_get_boolean(lp->field[1]);
3838 if (lp->field[0][0] == 'k' &&
3839 memcmp(lp->field[0], "keep_comments", 13) == 0) {
3842 "bdf: warning: %d: incorrect number of fields %d.\n",
3845 "bdf: warning: %d: keep_comments <boolean>.\n", lineno);
3847 p->opts->keep_comments = _bdf_get_boolean(lp->field[1]);
3852 if (lp->field[0][0] == 'p' &&
3853 memcmp(lp->field[0], "pad_character_cells", 19) == 0) {
3856 "bdf: warning: %d: incorrect number of fields %d.\n",
3859 "bdf: warning: %d: pad_character_cells <boolean>.\n",
3862 p->opts->pad_cells = _bdf_get_boolean(lp->field[1]);
3867 if (lp->field[0][0] == 'p' &&
3868 memcmp(lp->field[0], "point_size", 10) == 0) {
3871 "bdf: warning: %d: incorrect number of fields %d.\n",
3874 "bdf: warning: %d: point_size <integer>.\n", lineno);
3876 p->opts->point_size = _bdf_atol(lp->field[1], 0, 10);
3880 if (lp->field[0][0] == 'h' &&
3881 memcmp(lp->field[0], "horizontal_resolution", 21) == 0) {
3884 "bdf: warning: %d: incorrect number of fields %d.\n",
3887 "bdf: warning: %d: horizontal_resolution <cardinal>.\n",
3890 p->opts->resolution_x = _bdf_atoul(lp->field[1], 0, 10);
3894 if (lp->field[0][0] == 'v' &&
3895 memcmp(lp->field[0], "vertical_resolution", 19) == 0) {
3898 "bdf: warning: %d: incorrect number of fields %d.\n",
3901 "bdf: warning: %d: vertical_resolution <cardinal>.\n",
3904 p->opts->resolution_y = _bdf_atoul(lp->field[1], 0, 10);
3908 if (lp->field[0][0] == 'f' &&
3909 memcmp(lp->field[0], "font_spacing", 12) == 0) {
3912 "bdf: warning: %d: incorrect number of fields %d.\n",
3915 "bdf: warning: %d: font_spacing <spacing name>.\n",
3918 switch (lp->field[1][0]) {
3920 p->opts->font_spacing = BDF_PROPORTIONAL;
3923 p->opts->font_spacing = BDF_MONOWIDTH;
3926 p->opts->font_spacing = BDF_CHARCELL;
3930 "bdf: warning: %d: unknown font spacing '%s'.\n",
3931 lineno, lp->field[1]);
3937 if (lp->field[0][0] == 'p' &&
3938 memcmp(lp->field[0], "property", 8) == 0) {
3941 "bdf: warning: %d: incorrect number of fields %d.\n",
3944 "bdf: warning: %d: property <name> <type>.\n",
3947 switch (lp->field[2][0]) {
3949 bdf_create_property(lp->field[1], BDF_ATOM);
3952 bdf_create_property(lp->field[1], BDF_CARDINAL);
3955 bdf_create_property(lp->field[1], BDF_INTEGER);
3959 "bdf: warning: %d: unknown property type '%s'.\n",
3960 lineno, lp->field[2]);
3966 if (lp->field[0][0] == 'h' &&
3967 (memcmp(lp->field[0], "hint_truetype_glyphs", 20) == 0 ||
3968 memcmp(lp->field[0], "hint_opentype_glyphs", 20) == 0)) {
3971 "bdf: warning: %d: incorrect number of fields %d.\n",
3974 "bdf: warning: %d: hint_opentype_glyphs <boolean>.\n",
3977 #ifdef HAVE_FREETYPE
3978 if (_bdf_get_boolean(lp->field[1]))
3979 p->opts->otf_flags &= ~FT_LOAD_NO_HINTING;
3981 p->opts->otf_flags |= FT_LOAD_NO_HINTING;
3983 p->opts->otf_flags = 0;
3984 #endif /* HAVE_FREETYPE */
3990 if (lp->field[0][0] == 'g' &&
3991 memcmp(lp->field[0], "generate_ranges", 15) == 0)
3993 * Simply ignore the glyph ranges entry in the config file.
3998 * If the callback returns a non-zero value, the caller has handled the
3999 * unknown option found in the file.
4001 if (p->callback != 0 &&
4002 (*p->callback)(p->opts, lp->field, lp->used, p->client_data) != 0)
4005 fprintf(stderr, "bdf: warning: %d: unknown configuration option '%s'.\n",
4006 lineno, lp->field[0]);
4011 bdf_load_options(FILE *in, bdf_options_t *opts,
4012 bdf_options_callback_t callback, void *client_data)
4014 unsigned int lineno;
4015 _bdf_opts_parse_t p;
4018 * Don't bother loading the options if the file or options structure
4021 if (in == 0 || opts == 0)
4024 (void *) memset((char *) &p, 0, sizeof(_bdf_opts_parse_t));
4026 p.callback = callback;
4027 p.client_data = client_data;
4028 (void) _bdf_readlines(fileno(in), _bdf_parse_options, (void *) &p,
4032 * Free up the list if there is any space allocated.
4034 if (p.list.size > 0)
4035 free((char *) p.list.field);
4039 bdf_save_options(FILE *out, bdf_options_t *opts)
4043 if (out == 0 || opts == 0)
4046 fprintf(out, "#\n# Metrics corrections.\n#\ncorrect_metrics ");
4047 if (opts->correct_metrics)
4048 fprintf(out, "true\n\n");
4050 fprintf(out, "false\n\n");
4052 fprintf(out, "#\n# Preserve unencoded glyphs.\n#\nkeep_unencoded ");
4053 if (opts->keep_unencoded)
4054 fprintf(out, "true\n\n");
4056 fprintf(out, "false\n\n");
4058 fprintf(out, "#\n# Preserve comments.\n#\nkeep_comments ");
4059 if (opts->keep_comments)
4060 fprintf(out, "true\n\n");
4062 fprintf(out, "false\n\n");
4064 fprintf(out, "#\n# Pad character cells.\n#\npad_character_cells ");
4065 if (opts->pad_cells)
4066 fprintf(out, "true\n\n");
4068 fprintf(out, "false\n\n");
4070 fprintf(out, "#\n# Font spacing.\n#\nfont_spacing ");
4071 switch (opts->font_spacing) {
4072 case BDF_PROPORTIONAL: fprintf(out, "proportional\n\n"); break;
4073 case BDF_MONOWIDTH: fprintf(out, "monowidth\n\n"); break;
4074 case BDF_CHARCELL: fprintf(out, "charactercell\n\n"); break;
4077 fprintf(out, "#\n# Point size.\n#\npoint_size %d\n\n", opts->point_size);
4080 "#\n# Horizontal resolution.\n#\nhorizontal_resolution %d\n\n",
4081 opts->resolution_x);
4084 "#\n# Vertical resolution.\n#\nvertical_resolution %d\n\n",
4085 opts->resolution_x);
4088 "#\n# Bits per pixel.\n#\nbits_per_pixel %d\n\n",
4089 opts->bits_per_pixel);
4091 fprintf(out, "#\n# Hint OpenType glyphs.\n#\nhint_opentype_glyphs ");
4092 #ifdef HAVE_FREETYPE
4093 if (opts->otf_flags & FT_LOAD_NO_HINTING)
4094 fprintf(out, "false\n\n");
4096 fprintf(out, "true\n\n");
4098 fprintf(out, "false\n\n");
4099 #endif /* HAVE_FREETYPE */
4101 fprintf(out, "#\n# Set the EOL used when writing BDF fonts.\n#\neol ");
4102 switch (opts->eol) {
4103 case BDF_UNIX_EOL: fprintf(out, "unix\n\n"); break;
4104 case BDF_DOS_EOL: fprintf(out, "dos\n\n"); break;
4105 case BDF_MAC_EOL: fprintf(out, "mac\n\n"); break;
4109 * Write out the user defined properties if they exist.
4111 if (nuser_props == 0)
4114 fprintf(out, "#\n# User defined properties.\n#\n");
4116 for (i = 0; i < nuser_props; i++) {
4117 fprintf(out, "property %s ", user_props[i].name);
4118 switch (user_props[i].format) {
4119 case BDF_ATOM: fprintf(out, "atom\n"); break;
4120 case BDF_CARDINAL: fprintf(out, "cardinal\n"); break;
4121 case BDF_INTEGER: fprintf(out, "integer\n"); break;
4127 bdf_default_options(bdf_options_t *opts)
4132 (void) memcpy((char *) opts, (char *) &_bdf_opts, sizeof(bdf_options_t));
4136 bdf_new_font(char *name, int point_size, int resolution_x, int resolution_y,
4137 int spacing, int bpp)
4143 bdf_property_t prop;
4145 font = (bdf_font_t *) calloc(1, sizeof(bdf_font_t));
4146 if (name != 0 && *name != 0) {
4147 font->name = (char *) malloc(strlen(name) + 1);
4148 (void) strcpy(font->name, name);
4152 font->point_size = point_size;
4153 font->resolution_x = resolution_x;
4154 font->resolution_y = resolution_y;
4157 * Determine the pixel size of the new font based on the
4158 * point size and resolution.
4160 dr = (double) resolution_y;
4161 dp = (double) (point_size * 10);
4162 psize = (int) (((dp * dr) / 722.7) + 0.5);
4165 * Make the default width about 1.5 smaller than the height.
4167 font->bbx.height = psize;
4168 font->bbx.width = ((double) psize) / 1.5;
4171 * Now determine the default ascent and descent assuming a
4172 * the descent is about 1/4 the ascent.
4174 font->bbx.descent = psize >> 2;
4175 font->bbx.ascent = psize - font->bbx.descent;
4177 font->bbx.y_offset = -font->bbx.descent;
4180 * Allocation the internal hash tables.
4182 font->internal = (void *) malloc(sizeof(hashtable));
4183 hash_init((hashtable *) font->internal);
4185 font->default_glyph = -1;
4186 font->spacing = spacing;
4189 * Add various useful properties.
4191 prop.name = "POINT_SIZE";
4192 prop.format = BDF_INTEGER;
4193 prop.value.int32 = font->point_size * 10;
4194 bdf_add_font_property(font, &prop);
4196 prop.name = "PIXEL_SIZE";
4197 prop.format = BDF_INTEGER;
4198 prop.value.int32 = psize;
4199 bdf_add_font_property(font, &prop);
4201 prop.name = "RESOLUTION_X";
4202 prop.format = BDF_CARDINAL;
4203 prop.value.card32 = (unsigned int) font->resolution_x;
4204 bdf_add_font_property(font, &prop);
4206 prop.name = "RESOLUTION_Y";
4207 prop.format = BDF_CARDINAL;
4208 prop.value.card32 = (unsigned int) font->resolution_y;
4209 bdf_add_font_property(font, &prop);
4211 prop.name = "FONT_ASCENT";
4212 prop.format = BDF_INTEGER;
4213 prop.value.int32 = (int) font->bbx.ascent;
4214 bdf_add_font_property(font, &prop);
4216 prop.name = "FONT_DESCENT";
4217 prop.format = BDF_INTEGER;
4218 prop.value.int32 = (int) font->bbx.descent;
4219 bdf_add_font_property(font, &prop);
4221 prop.name = "AVERAGE_WIDTH";
4222 prop.format = BDF_INTEGER;
4223 prop.value.int32 = font->bbx.width * 10;
4224 bdf_add_font_property(font, &prop);
4229 case BDF_PROPORTIONAL: sp[0] = 'P'; break;
4230 case BDF_MONOWIDTH: sp[0] = 'M'; break;
4231 case BDF_CHARCELL: sp[0] = 'C'; break;
4233 prop.name = "SPACING";
4234 prop.format = BDF_ATOM;
4235 prop.value.atom = sp;
4236 bdf_add_font_property(font, &prop);
4239 * Mark the font as unmodified.
4247 bdf_set_default_metrics(bdf_font_t *font)
4251 bdf_property_t prop;
4254 * Determine the pixel size of the new font based on the
4255 * point size and resolution.
4257 dr = (double) font->resolution_y;
4258 dp = (double) (font->point_size * 10);
4259 psize = (int) (((dp * dr) / 722.7) + 0.5);
4262 * Make the default width about 1.5 smaller than the height.
4264 font->bbx.height = psize;
4265 font->bbx.width = ((double) psize) / 1.5;
4268 * Now determine the default ascent and descent assuming a
4269 * the descent is about 1/4 the ascent.
4271 font->bbx.descent = psize >> 2;
4272 font->bbx.ascent = psize - font->bbx.descent;
4274 font->bbx.y_offset = -font->bbx.descent;
4276 font->default_glyph = -1;
4279 * Add various useful properties.
4281 prop.name = "FONT_ASCENT";
4282 prop.format = BDF_INTEGER;
4283 prop.value.int32 = (int) font->bbx.ascent;
4284 bdf_add_font_property(font, &prop);
4286 prop.name = "FONT_DESCENT";
4287 prop.format = BDF_INTEGER;
4288 prop.value.int32 = (int) font->bbx.descent;
4289 bdf_add_font_property(font, &prop);
4291 prop.name = "AVERAGE_WIDTH";
4292 prop.format = BDF_INTEGER;
4293 prop.value.int32 = font->bbx.width * 10;
4294 bdf_add_font_property(font, &prop);
4298 bdf_glyph_modified(bdf_font_t *font, int which, int unencoded)
4300 if (font == 0 || which < 0)
4304 return _bdf_glyph_modified(font->umod, which);
4306 return _bdf_glyph_modified(font->nmod, which);
4310 bdf_copy_glyphs(bdf_font_t *font, int start, int end,
4311 bdf_glyphlist_t *glyphs, int unencoded)
4314 bdf_glyph_t *cp, *dp;
4315 short maxas, maxds, maxrb, minlb, maxlb, rb;
4323 glyphs->bpp = font->bpp;
4324 glyphs->start = start;
4326 glyphs->glyphs_used = 0;
4328 tmp = (end - start) + 1;
4329 if (tmp > glyphs->glyphs_size) {
4330 if (glyphs->glyphs_size == 0)
4331 glyphs->glyphs = (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) * tmp);
4333 glyphs->glyphs = (bdf_glyph_t *) realloc((char *) glyphs->glyphs,
4334 sizeof(bdf_glyph_t) * tmp);
4335 cp = glyphs->glyphs + glyphs->glyphs_size;
4336 (void) memset((char *) cp, 0,
4337 sizeof(bdf_glyph_t) * (tmp - glyphs->glyphs_size));
4338 glyphs->glyphs_size = tmp;
4342 * Clear out bitmaps, names and any PSF Unicode mappings in the existing
4345 for (cp = glyphs->glyphs, i = 0; i < glyphs->glyphs_size; i++, cp++) {
4349 free((char *) cp->bitmap);
4350 if (cp->unicode.map_size > 0)
4351 free((char *) cp->unicode.map);
4355 * Zero out everything.
4357 (void) memset((char *) &glyphs->bbx, 0, sizeof(bdf_bbx_t));
4358 (void) memset((char *) glyphs->glyphs, 0,
4359 sizeof(bdf_glyph_t) * glyphs->glyphs_size);
4362 * Initialize the bounds used to generate the overall bounding box for the
4363 * set of glyphs being copied.
4365 minlb = font->bbx.width;
4366 maxlb = maxrb = maxas = maxds = 0;
4371 nc = (unencoded == 0) ? font->glyphs_used : font->unencoded_used;
4372 cp = (unencoded == 0) ? font->glyphs : font->unencoded;
4373 dp = glyphs->glyphs;
4376 i < nc && ((unencoded && i <= end) || cp->encoding <= end);
4378 if ((unencoded && i >= start) || cp->encoding >= start) {
4379 (void) memcpy((char *) dp, (char *) cp, sizeof(bdf_glyph_t));
4380 if (cp->name != 0) {
4381 dp->name = (char *) malloc(strlen(cp->name) + 1);
4382 (void) strcpy(dp->name, cp->name);
4384 if (cp->bytes > 0) {
4385 dp->bytes = cp->bytes;
4386 dp->bitmap = (unsigned char *) malloc(cp->bytes);
4387 (void) memcpy((char *) dp->bitmap, (char *) cp->bitmap,
4390 if (cp->unicode.map_used > 0) {
4391 dp->unicode.map_used = dp->unicode.map_size =
4392 cp->unicode.map_used;
4394 (unsigned char *) malloc(dp->unicode.map_used);
4395 (void) memcpy((char *) dp->unicode.map,
4396 (char *) cp->unicode.map,
4397 dp->unicode.map_used);
4401 * Determine the overall metrics for the group of characters being
4404 maxas = MAX(cp->bbx.ascent, maxas);
4405 maxds = MAX(cp->bbx.descent, maxds);
4406 rb = cp->bbx.width + cp->bbx.x_offset;
4407 maxrb = MAX(rb, maxrb);
4408 minlb = MIN(cp->bbx.x_offset, minlb);
4409 maxlb = MAX(cp->bbx.x_offset, maxlb);
4411 glyphs->glyphs_used++;
4417 * Set the overall metrics for this set of glyphs.
4419 glyphs->bbx.width = maxrb - minlb;
4420 glyphs->bbx.x_offset = minlb;
4422 glyphs->bbx.height = maxas + maxds;
4423 glyphs->bbx.ascent = maxas;
4424 glyphs->bbx.descent = maxds;
4425 glyphs->bbx.y_offset = -maxds;
4429 _bdf_locate_glyph(bdf_font_t *font, int code, int unencoded)
4434 if (code < 0 || font == 0)
4437 if ((unencoded && font->unencoded_used == 0) ||
4438 font->glyphs_used == 0)
4442 gl = font->unencoded;
4443 nc = font->unencoded_used;
4446 nc = font->glyphs_used;
4448 for (l = m = 0, r = nc - 1; l < r; ) {
4450 if (gl[m].encoding < code)
4452 else if (gl[m].encoding > code)
4459 * Go back until we hit the beginning of the glyphs or until
4460 * we find the glyph with a code less than the specified code.
4463 while (m > 0 && gl[m].encoding > code)
4467 * Look forward if necessary.
4470 while (m < nc && gl[m].encoding < code)
4473 return (m < nc) ? &gl[m] : &gl[nc - 1];
4477 bdf_delete_glyphs(bdf_font_t *font, int start, int end, int unencoded)
4479 int i, n, nc, cnt, mod;
4480 bdf_glyph_t *cp, *sp, *ep;
4493 nc = (unencoded == 0) ? font->glyphs_used : font->unencoded_used;
4494 cp = (unencoded == 0) ? font->glyphs : font->unencoded;
4497 for (i = 0; i < nc && cp->encoding <= end; i++, cp++) {
4498 if (cp->encoding >= start && sp == 0)
4507 * There are some glyphs to delete.
4508 * 1. Free the name and bitmap fields of the glyphs being deleted.
4509 * 2. Move the end range down if necessary.
4510 * 3. Clear the glyphs on the end if a move was done.
4514 * Mark the font as being modified.
4516 mod = font->modified = 1;
4520 for (cp = sp; cp < ep; cp++) {
4522 * Mark the glyphs being deleted as also being modified so the
4523 * empty cells can be shown correctly by the client programs.
4526 _bdf_set_glyph_modified(font->umod, cp->encoding);
4528 _bdf_set_glyph_modified(font->nmod, cp->encoding);
4533 free((char *) cp->bitmap);
4536 cp = (unencoded == 0) ? font->glyphs : font->unencoded;
4539 * Check to see if there are some glyphs that need to
4544 * Shift the glyphs down.
4547 _bdf_memmove((char *) sp, (char *) ep, sizeof(bdf_glyph_t) * n);
4550 * Set the starting point for the clear.
4555 * Set the starting point for the clear.
4560 * Clear the glyph space just moved.
4563 (void) memset((char *) ep, 0, sizeof(bdf_glyph_t) * n);
4566 * Adjust the number of glyphs used.
4569 font->glyphs_used -= cnt;
4571 font->unencoded_used -= cnt;
4574 * If unencoded glyphs were deleted, re-encode all
4575 * of them to cause a shift when everything is redrawn.
4577 if (unencoded != 0) {
4578 for (i = 0, cp = font->unencoded; i < font->unencoded_used;
4580 if (_bdf_glyph_modified(font->umod, cp->encoding)) {
4581 _bdf_clear_glyph_modified(font->umod, cp->encoding);
4582 _bdf_set_glyph_modified(font->umod, i);
4592 * These values are intended to give pixels mapped from 1bpp to nbpp the
4593 * darkest available index, which is 1.
4595 static unsigned char twobpp_ones[] = {0x40, 0x10, 0x04, 0x01};
4596 static unsigned char fourbpp_ones[] = {0x10, 0x01};
4597 static unsigned char eightbpp_ones[] = {0x01};
4600 * Routines for quick and dirty dithering.
4603 _bdf_one_to_n(bdf_glyphlist_t *gl, int n)
4606 unsigned short bpr, sbpr, bytes, col, sx, sy;
4607 unsigned char *nbmap, *ones = 0;
4610 if (gl == 0 || gl->glyphs_used == 0)
4614 case 1: ones = bdf_onebpp; break;
4615 case 2: ones = twobpp_ones; break;
4616 case 4: ones = fourbpp_ones; break;
4617 case 8: ones = eightbpp_ones; break;
4621 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4622 if (gp->bbx.width == 0 || gp->bbx.height == 0)
4624 sbpr = (gp->bbx.width + 7) >> 3;
4625 bpr = ((gp->bbx.width * n) + 7) >> 3;
4626 bytes = bpr * gp->bbx.height;
4627 nbmap = (unsigned char *) malloc(bytes);
4628 (void) memset((char *) nbmap, 0, bytes);
4630 for (sy = 0; sy < gp->bbx.height; sy++) {
4631 for (col = sx = 0; sx < gp->bbx.width; sx++, col += n) {
4632 if (gp->bitmap[(sy * sbpr) + (sx >> 3)] & (0x80 >> (sx & 7)))
4633 nbmap[(sy * bpr) + (col >> 3)] |= ones[(col & 7) / n];
4636 free((char *) gp->bitmap);
4643 _bdf_n_to_one(bdf_glyphlist_t *gl)
4646 unsigned short bpr, sbpr, bytes, col, sx, sy;
4647 unsigned char *nbmap, *masks;
4650 if (gl == 0 || gl->glyphs_used == 0)
4655 case 1: masks = bdf_onebpp; break;
4656 case 2: masks = bdf_twobpp; break;
4657 case 4: masks = bdf_fourbpp; break;
4658 case 8: masks = bdf_eightbpp; break;
4661 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4662 if (gp->bbx.width == 0 || gp->bbx.height == 0)
4664 sbpr = ((gp->bbx.width * gl->bpp) + 7) >> 3;
4665 bpr = (gp->bbx.width + 7) >> 3;
4666 bytes = bpr * gp->bbx.height;
4667 nbmap = (unsigned char *) malloc(bytes);
4668 (void) memset((char *) nbmap, 0, bytes);
4670 for (sy = 0; sy < gp->bbx.height; sy++) {
4671 for (col = sx = 0; sx < gp->bbx.width; sx++, col += gl->bpp) {
4672 if (gp->bitmap[(sy * sbpr) + (col >> 3)] &
4673 masks[(col & 7) / gl->bpp])
4674 nbmap[(sy * bpr) + (sx >> 3)] |= (0x80 >> (sx & 7));
4677 free((char *) gp->bitmap);
4685 _bdf_two_to_four(bdf_glyphlist_t *gl)
4688 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
4689 unsigned char *nbmap, *masks;
4692 if (gl == 0 || gl->glyphs_used == 0)
4697 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4698 if (gp->bbx.width == 0 || gp->bbx.height == 0)
4700 sbpr = ((gp->bbx.width << 1) + 7) >> 3;
4701 bpr = ((gp->bbx.width << 2) + 7) >> 3;
4702 bytes = bpr * gp->bbx.height;
4703 nbmap = (unsigned char *) malloc(bytes);
4704 (void) memset((char *) nbmap, 0, bytes);
4706 for (sy = 0; sy < gp->bbx.height; sy++) {
4707 for (col = sx = 0; sx < gp->bbx.width; sx++, col += 2) {
4708 si = (col & 7) >> 1;
4709 byte = gp->bitmap[(sy * sbpr) + (col >> 3)] & masks[si];
4712 byte >>= (3 - si) << 1;
4716 nbmap[(sy * bpr) + ((sx << 2) >> 3)] |= byte;
4720 free((char *) gp->bitmap);
4728 _bdf_four_to_two(bdf_glyphlist_t *gl)
4731 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
4732 unsigned char *nbmap, *masks;
4735 if (gl == 0 || gl->glyphs_used == 0)
4738 masks = bdf_fourbpp;
4741 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4742 sbpr = ((gp->bbx.width << 2) + 7) >> 3;
4743 bpr = ((gp->bbx.width << 1) + 7) >> 3;
4744 bytes = bpr * gp->bbx.height;
4745 nbmap = (unsigned char *) malloc(bytes);
4746 (void) memset((char *) nbmap, 0, bytes);
4748 for (sy = 0; sy < gp->bbx.height; sy++) {
4749 for (col = sx = 0; sx < gp->bbx.width; sx++, col += 4) {
4750 si = (col & 7) >> 2;
4751 byte = gp->bitmap[(sy * sbpr) + (col >> 3)] & masks[si];
4754 * Shift the byte down to make an index.
4760 * Scale the index to two bits per pixel and shift it into
4761 * place if necessary.
4765 * Any non-zero byte has to remain non-zero, because index
4766 * zero means no bits set.
4771 si = ((sx << 1) & 7) >> 1;
4773 byte <<= (3 - si) << 1;
4775 nbmap[(sy * bpr) + ((sx << 1) >> 3)] |= byte;
4779 free((char *) gp->bitmap);
4786 _bdf_two_to_eight(bdf_glyphlist_t *gl)
4789 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
4790 unsigned char *nbmap, *masks;
4793 if (gl == 0 || gl->glyphs_used == 0)
4798 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4799 if (gp->bbx.width == 0 || gp->bbx.height == 0)
4801 sbpr = ((gp->bbx.width << 1) + 7) >> 3;
4802 bpr = gp->bbx.width;
4803 bytes = bpr * gp->bbx.height;
4804 nbmap = (unsigned char *) malloc(bytes);
4805 (void) memset((char *) nbmap, 0, bytes);
4807 for (sy = 0; sy < gp->bbx.height; sy++) {
4808 for (col = sx = 0; sx < gp->bbx.width; sx++, col += 2) {
4809 si = (col & 7) >> 1;
4810 byte = gp->bitmap[(sy * sbpr) + (col >> 3)] & masks[si];
4813 * Shift the byte down to make an index.
4816 byte >>= (3 - si) * gl->bpp;
4819 * Scale the index to four bits per pixel and shift it into
4820 * place before adding it.
4823 nbmap[(sy * bpr) + sx] = byte;
4827 free((char *) gp->bitmap);
4835 _bdf_eight_to_two(bdf_glyphlist_t *gl)
4838 unsigned short bpr, sbpr, bytes, si, byte, sx, sy;
4839 unsigned char *nbmap /*, *masks*/;
4842 if (gl == 0 || gl->glyphs_used == 0)
4845 /*masks = bdf_fourbpp;*/
4848 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4849 sbpr = gp->bbx.width;
4850 bpr = ((gp->bbx.width << 1) + 7) >> 3;
4851 bytes = bpr * gp->bbx.height;
4852 nbmap = (unsigned char *) malloc(bytes);
4853 (void) memset((char *) nbmap, 0, bytes);
4855 for (sy = 0; sy < gp->bbx.height; sy++) {
4856 for (sx = 0; sx < gp->bbx.width; sx++) {
4857 byte = gp->bitmap[(sy * sbpr) + sx];
4863 si = ((sx << 1) & 7) >> 1;
4865 byte <<= (3 - si) << 1;
4867 nbmap[(sy * bpr) + ((sx << 1) >> 3)] |= byte;
4871 free((char *) gp->bitmap);
4878 _bdf_four_to_eight(bdf_glyphlist_t *gl)
4881 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
4882 unsigned char *nbmap, *masks;
4885 if (gl == 0 || gl->glyphs_used == 0)
4888 masks = bdf_fourbpp;
4890 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4891 if (gp->bbx.width == 0 || gp->bbx.height == 0)
4893 sbpr = ((gp->bbx.width << 2) + 7) >> 3;
4894 bpr = gp->bbx.width;
4895 bytes = bpr * gp->bbx.height;
4896 nbmap = (unsigned char *) malloc(bytes);
4897 (void) memset((char *) nbmap, 0, bytes);
4899 for (sy = 0; sy < gp->bbx.height; sy++) {
4900 for (col = sx = 0; sx < gp->bbx.width; sx++, col += 4) {
4901 si = (col & 7) >> 2;
4902 byte = gp->bitmap[(sy * sbpr) + (col >> 3)] & masks[si];
4908 nbmap[(sy * bpr) + sx] = byte;
4912 free((char *) gp->bitmap);
4920 _bdf_eight_to_four(bdf_glyphlist_t *gl)
4923 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
4924 unsigned char *nbmap/*, *masks*/;
4927 if (gl == 0 || gl->glyphs_used == 0)
4930 /*masks = bdf_twobpp;*/
4932 for (gp = gl->glyphs, i = 0; i < gl->glyphs_used; i++, gp++) {
4933 if (gp->bbx.width == 0 || gp->bbx.height == 0)
4935 sbpr = gp->bbx.width;
4936 bpr = ((gp->bbx.width << 2) + 7) >> 3;
4937 bytes = bpr * gp->bbx.height;
4938 nbmap = (unsigned char *) malloc(bytes);
4939 (void) memset((char *) nbmap, 0, bytes);
4941 for (sy = 0; sy < gp->bbx.height; sy++) {
4942 for (col = sx = 0; sx < gp->bbx.width; sx++, col += 2) {
4943 byte = gp->bitmap[(sy * sbpr) + sx];
4950 * Scale the index to four bits per pixel and shift it into
4951 * place before adding it.
4953 si = (col & 7) >> 2;
4956 nbmap[(sy * bpr) + ((sx << 2) >> 3)] |= byte;
4960 free((char *) gp->bitmap);
4968 * This only works on glyphs that exist.
4971 bdf_replace_mappings(bdf_font_t *font, int encoding, bdf_psf_unimap_t *map,
4976 if ((gp = _bdf_locate_glyph(font, encoding, unencoded)) == 0 ||
4977 gp->encoding != encoding)
4980 if (map->map_size > gp->unicode.map_size) {
4981 if (gp->unicode.map_size == 0)
4982 gp->unicode.map = (unsigned char *)
4983 malloc(sizeof(unsigned char) * map->map_size);
4985 gp->unicode.map =(unsigned char *)
4986 realloc((char *) gp->unicode.map,
4987 sizeof(unsigned char) * map->map_size);
4988 gp->unicode.map_size = map->map_size;
4990 gp->unicode.map_used = map->map_used;
4991 (void) memcpy((char *) gp->unicode.map, (char *) map->map,
4992 sizeof(unsigned char) * map->map_used);
4995 * Mark the glyph as modified.
4998 _bdf_set_glyph_modified(font->umod, gp->encoding);
5000 _bdf_set_glyph_modified(font->nmod, gp->encoding);
5008 bdf_replace_glyphs(bdf_font_t *font, int start, bdf_glyphlist_t *glyphs,
5011 int resize, appending;
5012 int i, n, ng, end, del, remaining, off[2];
5013 bdf_glyph_t *sgp, *gp, *dgp;
5014 short maxas, maxds, maxrb, minlb, maxlb, rb;
5024 * Dither the incoming bitmaps so they match the same bits per pixel as
5027 if (glyphs->bpp != font->bpp) {
5028 if (glyphs->bpp == 1)
5029 _bdf_one_to_n(glyphs, font->bpp);
5030 else if (font->bpp == 1)
5031 _bdf_n_to_one(glyphs);
5032 else if (glyphs->bpp == 2) {
5034 _bdf_two_to_four(glyphs);
5036 _bdf_two_to_eight(glyphs);
5037 } else if (glyphs->bpp == 4) {
5039 _bdf_four_to_two(glyphs);
5041 _bdf_four_to_eight(glyphs);
5042 } else if (glyphs->bpp == 8) {
5044 _bdf_eight_to_two(glyphs);
5046 _bdf_eight_to_four(glyphs);
5051 * Set the point size and horizontal resolution so the scalable width can
5054 ps = (double) font->point_size;
5055 rx = (double) font->resolution_x;
5058 * Determine if a resize is needed.
5062 * Determine the bounding box for the font without the characters being
5066 maxlb = maxrb = maxas = maxds = 0;
5069 * Get the font bounds.
5071 maxas = MAX(font->bbx.ascent, maxas);
5072 maxds = MAX(font->bbx.descent, maxds);
5073 rb = font->bbx.width + font->bbx.x_offset;
5074 maxrb = MAX(rb, maxrb);
5075 minlb = MIN(font->bbx.x_offset, minlb);
5076 maxlb = MAX(font->bbx.x_offset, maxlb);
5079 * Get the bounds of the incoming glyphs.
5081 maxas = MAX(glyphs->bbx.ascent, maxas);
5082 maxds = MAX(glyphs->bbx.descent, maxds);
5083 rb = glyphs->bbx.width + glyphs->bbx.x_offset;
5084 maxrb = MAX(rb, maxrb);
5085 minlb = MIN(glyphs->bbx.x_offset, minlb);
5086 maxlb = MAX(glyphs->bbx.x_offset, maxlb);
5089 * Set up the new font bounding box, minus the characters that are being
5090 * removed and with the new characters added.
5092 nbbx.width = maxrb - minlb;
5093 nbbx.x_offset = minlb;
5095 nbbx.height = maxas + maxds;
5096 nbbx.ascent = maxas;
5097 nbbx.descent = maxds;
5098 nbbx.y_offset = -maxds;
5101 * Now determine if the combination of the glyphs removed and the new
5102 * glyphs cause the font bounding box to be changed.
5104 resize = (nbbx.width > font->bbx.width ||
5105 nbbx.height > font->bbx.height) ? 1 : 0;
5108 * Set the pointers to the glyphs.
5110 ng = (unencoded == 0) ? font->glyphs_used : font->unencoded_used;
5111 sgp = gp = (unencoded == 0) ? font->glyphs : font->unencoded;
5114 * Locate the closest glyph on or following `start'.
5116 for (i = 0; i < ng && gp->encoding < start; i++, gp++) ;
5118 appending = (i == ng);
5121 * Set the starting point for copying the incoming glyphs.
5125 n = glyphs->end - glyphs->start;
5129 * Delete all the glyphs between `start' and `end'.
5131 for (del = 0, i = start; i <= end; i++) {
5133 * Mark the character as being modified.
5135 if (ng > 0 && !appending && gp->encoding == i) {
5137 _bdf_set_glyph_modified(font->nmod, i);
5139 _bdf_set_glyph_modified(font->umod, i);
5144 free((char *) gp->bitmap);
5145 if (gp->unicode.map_size > 0)
5146 free((char *) gp->unicode.map);
5153 * Determine how many glyphs remain following the last one deleted.
5155 remaining = ng - (gp - sgp);
5157 if (glyphs->glyphs_used == 0) {
5159 * If the glyph list is empty, then shift any remaining glyphs down
5160 * to the destination.
5162 _bdf_memmove((char *) dgp, (char *) gp,
5163 sizeof(bdf_glyph_t) * remaining);
5165 font->glyphs_used -= del;
5167 font->unencoded_used -= del;
5170 * Insert the glyph list after making sure there is enough space to
5171 * hold them. Also adjust the encoding and scalable width values
5172 * after copying the glyphs.
5174 if (unencoded == 0) {
5175 n = (font->glyphs_used - del) + glyphs->glyphs_used;
5176 if (n > font->glyphs_size) {
5179 if (font->glyphs_size == 0)
5180 font->glyphs = sgp =
5181 (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) * n);
5183 font->glyphs = sgp =
5184 (bdf_glyph_t *) realloc((char *) font->glyphs,
5185 sizeof(bdf_glyph_t) * n);
5188 font->glyphs_size = n;
5192 * Calculate how many will need to be shifted.
5194 if ((n = glyphs->glyphs_used - del) >= font->glyphs_used)
5197 n = (font->unencoded_used - del) + glyphs->glyphs_used;
5198 if (n > font->unencoded_size) {
5201 if (font->unencoded_size == 0)
5202 font->unencoded = sgp =
5203 (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) * n);
5205 font->unencoded = sgp =
5206 (bdf_glyph_t *) realloc((char *) font->unencoded,
5207 sizeof(bdf_glyph_t) * n);
5210 font->unencoded_size = n;
5214 * Calculate how many will need to be shifted.
5216 if ((n = glyphs->glyphs_used - del) >= font->unencoded_used)
5221 * Shift any following glyphs up or down if needed.
5224 _bdf_memmove((char *) (gp + n), (char *) gp,
5225 sizeof(bdf_glyph_t) * remaining);
5228 * Copy the incoming glyphs, copy their names and bitmaps,
5229 * set their encodings, and set their scalable widths.
5231 (void) memcpy((char *) dgp, (char *) glyphs->glyphs,
5232 sizeof(bdf_glyph_t) * glyphs->glyphs_used);
5233 for (i = 0; i < glyphs->glyphs_used; i++, dgp++) {
5235 dgp->name = (char *) _bdf_strdup((unsigned char *) dgp->name,
5236 strlen(dgp->name) + 1);
5239 dgp->bitmap = _bdf_strdup(dgp->bitmap, dgp->bytes);
5241 if (dgp->unicode.map_size > 0)
5242 dgp->unicode.map = _bdf_strdup(dgp->unicode.map,
5243 dgp->unicode.map_size);
5245 dgp->encoding = start + (dgp->encoding - glyphs->start);
5248 * Mark the glyph as being modified in case it fills a cell that
5251 _bdf_set_glyph_modified(font->nmod, dgp->encoding);
5253 dw = (double) dgp->dwidth;
5254 dgp->swidth = (unsigned short) ((dw * 72000.0) / (ps * rx));
5258 * Adjust the count of glyphs.
5260 ng = (ng - del) + glyphs->glyphs_used;
5262 font->glyphs_used = ng;
5264 font->unencoded_used = ng;
5268 * Last, if the replacement was done in the unencoded section,
5269 * reencode all the glyphs so they show up properly.
5271 if (unencoded != 0) {
5272 for (i = 0; i < ng; i++, sgp++) {
5273 if (_bdf_glyph_modified(font->umod, sgp->encoding)) {
5274 _bdf_clear_glyph_modified(font->umod, sgp->encoding);
5275 _bdf_set_glyph_modified(font->umod, i);
5282 (void) memcpy((char *) &font->bbx, (char *) &nbbx, sizeof(bdf_bbx_t));
5290 bdf_insert_glyphs(bdf_font_t *font, int start, bdf_glyphlist_t *glyphs)
5293 unsigned int i, ng, n, which;
5302 * Dither the incoming bitmaps so they match the same bits per pixel as
5305 if (glyphs->bpp != font->bpp) {
5306 if (glyphs->bpp == 1)
5307 _bdf_one_to_n(glyphs, font->bpp);
5308 else if (font->bpp == 1)
5309 _bdf_n_to_one(glyphs);
5310 else if (glyphs->bpp == 2)
5311 _bdf_two_to_four(glyphs);
5313 _bdf_four_to_two(glyphs);
5317 * Locate the starting glyph.
5320 ng = font->glyphs_used;
5321 for (i = 0; i < ng && gp->encoding < start; i++, gp++) ;
5324 * If there are no glyphs at the starting point, then simply do a replace.
5327 return bdf_replace_glyphs(font, start, glyphs, 0);
5330 * Go through the glyphs that would be shifted due to the insertion and
5331 * determine if some of them will overflow the 0xffff boundary.
5333 n = (glyphs->end - glyphs->start) + 1;
5334 for (which = i; i < ng; i++, gp++) {
5335 if (gp->encoding + n > 0xffff)
5341 * Some glyphs have to be moved to the unencoded area because they
5342 * would overflow the 0xffff boundary if they were moved up.
5344 bdf_copy_glyphs(font, gp->encoding, font->glyphs[ng - 1].encoding,
5345 &font->overflow, 0);
5346 bdf_delete_glyphs(font, gp->encoding, font->glyphs[ng - 1].encoding,
5348 resize += bdf_replace_glyphs(font, font->unencoded_used,
5349 &font->overflow, 1);
5353 * Go back to the insertion point and shift the remaining glyph encodings
5356 for (gp = font->glyphs + which; which < font->glyphs_used; which++, gp++) {
5358 * Mark the new glyph locations as being modified.
5361 _bdf_set_glyph_modified(font->nmod, gp->encoding);
5365 * Finally, mark the font as being modified and insert the new glyphs.
5369 return resize + bdf_replace_glyphs(font, start, glyphs, 0);
5373 _bdf_combine_glyphs(bdf_font_t *font, bdf_glyph_t *f, bdf_glyph_t *g)
5375 unsigned short x, sx, sy, si, dx, dy, di, byte, dbpr, fbpr, gbpr;
5376 short maxas, maxds, maxrb, minlb, maxlb, rb;
5377 unsigned char *masks;
5382 * Determine the max bounding box for the two glyphs.
5385 maxlb = maxrb = maxas = maxds = 0;
5388 * Get the font glyph bounds.
5390 maxas = MAX(f->bbx.ascent, maxas);
5391 maxds = MAX(f->bbx.descent, maxds);
5392 rb = f->bbx.width + f->bbx.x_offset;
5393 maxrb = MAX(rb, maxrb);
5394 minlb = MIN(f->bbx.x_offset, minlb);
5395 maxlb = MAX(f->bbx.x_offset, maxlb);
5398 * Get the bounds of the incoming glyph.
5400 maxas = MAX(g->bbx.ascent, maxas);
5401 maxds = MAX(g->bbx.descent, maxds);
5402 rb = g->bbx.width + g->bbx.x_offset;
5403 maxrb = MAX(rb, maxrb);
5404 minlb = MIN(g->bbx.x_offset, minlb);
5405 maxlb = MAX(g->bbx.x_offset, maxlb);
5408 * Set up the new glyph bounding box.
5410 nbbx.width = maxrb - minlb;
5411 nbbx.x_offset = minlb;
5412 nbbx.height = maxas + maxds;
5413 nbbx.ascent = maxas;
5414 nbbx.descent = maxds;
5415 nbbx.y_offset = -maxds;
5418 switch (font->bpp) {
5419 case 1: masks = bdf_onebpp; break;
5420 case 2: masks = bdf_twobpp; break;
5421 case 4: masks = bdf_fourbpp; break;
5422 case 8: masks = bdf_eightbpp; break;
5425 fbpr = ((f->bbx.width * font->bpp) + 7) >> 3;
5426 gbpr = ((g->bbx.width * font->bpp) + 7) >> 3;
5427 dbpr = ((nbbx.width * font->bpp) + 7) >> 3;
5429 if (memcmp((char *) &nbbx, (char *) &f->bbx, sizeof(bdf_bbx_t)) == 0) {
5431 * The largest is the first, so merge the second in with it.
5433 dy = f->bbx.ascent - g->bbx.ascent;
5434 for (sy = 0; sy < g->bbx.height; sy++, dy++) {
5435 for (x = sx = 0; x < g->bbx.width; x++, sx += font->bpp) {
5436 si = (sx & 7) / font->bpp;
5437 if ((byte = g->bitmap[(sy * gbpr) + (sx >> 3)] & masks[si]))
5439 * No shifting of the byte is needed because the x offset
5440 * is the same for both glyphs.
5442 f->bitmap[(dy * fbpr) + (sx >> 3)] |= byte;
5445 } else if (memcmp((char *) &nbbx, (char *) &g->bbx,
5446 sizeof(bdf_bbx_t)) == 0) {
5448 * The largest is the incoming glyph, so merge into that one and swap
5449 * it with the font glyph.
5451 dy = g->bbx.ascent - f->bbx.ascent;
5452 for (sy = 0; sy < f->bbx.height; sy++, dy++) {
5453 for (x = sx = 0; x < f->bbx.width; x++, sx += font->bpp) {
5454 si = (sx & 7) / font->bpp;
5455 if ((byte = f->bitmap[(sy * gbpr) + (sx >> 3)] & masks[si]))
5457 * No shifting of the byte is needed because the x offset
5458 * is the same for both glyphs.
5460 g->bitmap[(dy * fbpr) + (sx >> 3)] |= byte;
5465 * Now swap the two glyphs while preserving the name and encoding of
5468 tmp.swidth = g->swidth;
5469 tmp.dwidth = g->dwidth;
5470 tmp.bytes = g->bytes;
5471 tmp.bitmap = g->bitmap;
5472 (void) memcpy((char *) &tmp.bbx, (char *) &g->bbx, sizeof(bdf_bbx_t));
5474 g->swidth = f->swidth;
5475 g->dwidth = f->dwidth;
5476 g->bytes = f->bytes;
5477 g->bitmap = f->bitmap;
5478 (void) memcpy((char *) &g->bbx, (char *) &f->bbx, sizeof(bdf_bbx_t));
5480 f->swidth = tmp.swidth;
5481 f->dwidth = tmp.dwidth;
5482 f->bytes = tmp.bytes;
5483 f->bitmap = tmp.bitmap;
5484 (void) memcpy((char *) &f->bbx, (char *) &tmp.bbx, sizeof(bdf_bbx_t));
5487 * Need a new bitmap for the combination of the two.
5489 tmp.bytes = nbbx.height * dbpr;
5490 tmp.bitmap = (unsigned char *) malloc(tmp.bytes);
5491 (void) memset((char *) tmp.bitmap, 0, tmp.bytes);
5494 * Merge the first glyph.
5496 dy = nbbx.ascent - f->bbx.ascent;
5497 for (sy = 0; sy < f->bbx.height; sy++, dy++) {
5498 dx = MYABS(nbbx.x_offset - f->bbx.x_offset) * font->bpp;
5499 for (x = sx = 0; x < f->bbx.width; x++,
5500 sx += font->bpp, dx += font->bpp) {
5501 si = (sx & 7) / font->bpp;
5502 if ((byte = f->bitmap[(sy * fbpr) + (sx >> 3)] & masks[si])) {
5503 di = (dx & 7) / font->bpp;
5505 byte <<= (si - di) * font->bpp;
5507 byte >>= (di - si) * font->bpp;
5508 tmp.bitmap[(dy * dbpr) + (dx >> 3)] |= byte;
5514 * Merge the second glyph.
5516 dy = nbbx.ascent - g->bbx.ascent;
5517 for (sy = 0; sy < g->bbx.height; sy++, dy++) {
5518 dx = MYABS(nbbx.x_offset - g->bbx.x_offset) * font->bpp;
5519 for (x = sx = 0; x < g->bbx.width; x++,
5520 sx += font->bpp, dx += font->bpp) {
5521 si = (sx & 7) / font->bpp;
5522 if ((byte = g->bitmap[(sy * gbpr) + (sx >> 3)] & masks[si])) {
5523 di = (dx & 7) / font->bpp;
5525 byte <<= (si - di) * font->bpp;
5527 byte >>= (di - si) * font->bpp;
5528 tmp.bitmap[(dy * dbpr) + (dx >> 3)] |= byte;
5534 * Now clear the font glyph and copy the temp glyph to it.
5537 free((char *) f->bitmap);
5538 f->bytes = tmp.bytes;
5539 f->bitmap = tmp.bitmap;
5540 (void) memcpy((char *) &f->bbx, (char *) &nbbx, sizeof(bdf_bbx_t));
5543 * Set the device width. Pay attention to whether the font is
5544 * monowidth or character cell.
5546 if (font->spacing != BDF_PROPORTIONAL)
5547 f->dwidth = font->monowidth;
5549 f->dwidth = MAX(f->dwidth, g->dwidth);
5554 bdf_merge_glyphs(bdf_font_t *font, int start, bdf_glyphlist_t *glyphs,
5558 int i, n, ng, end, add, enc, off;
5559 bdf_glyph_t *sgp, *gp, *dgp, *base;
5560 short maxas, maxds, maxrb, minlb, maxlb, rb;
5570 * If the glyphs are being merged in the unencoded area, simply append
5571 * them. The unencoded area is simply storage.
5574 return bdf_replace_glyphs(font, font->unencoded_used, glyphs, unencoded);
5577 * Dither the incoming bitmaps so they match the same bits per pixel as
5580 if (glyphs->bpp != font->bpp) {
5581 if (glyphs->bpp == 1)
5582 _bdf_one_to_n(glyphs, font->bpp);
5583 else if (font->bpp == 1)
5584 _bdf_n_to_one(glyphs);
5585 else if (glyphs->bpp == 2)
5586 _bdf_two_to_four(glyphs);
5588 _bdf_four_to_two(glyphs);
5592 * Set the point size and horizontal resolution so the scalable width can
5595 ps = (double) font->point_size;
5596 rx = (double) font->resolution_x;
5599 * Determine if a resize is needed.
5603 * Determine the bounding box for the font without the characters being
5607 maxlb = maxrb = maxas = maxds = 0;
5610 * Get the font bounds.
5612 maxas = MAX(font->bbx.ascent, maxas);
5613 maxds = MAX(font->bbx.descent, maxds);
5614 rb = font->bbx.width + font->bbx.x_offset;
5615 maxrb = MAX(rb, maxrb);
5616 minlb = MIN(font->bbx.x_offset, minlb);
5617 maxlb = MAX(font->bbx.x_offset, maxlb);
5620 * Get the bounds of the incoming glyphs.
5622 maxas = MAX(glyphs->bbx.ascent, maxas);
5623 maxds = MAX(glyphs->bbx.descent, maxds);
5624 rb = glyphs->bbx.width + glyphs->bbx.x_offset;
5625 maxrb = MAX(rb, maxrb);
5626 minlb = MIN(glyphs->bbx.x_offset, minlb);
5627 maxlb = MAX(glyphs->bbx.x_offset, maxlb);
5630 * Set up the new font bounding box, minus the characters that are being
5631 * removed and with the new characters added.
5633 nbbx.width = maxrb - minlb;
5634 nbbx.x_offset = minlb;
5636 nbbx.height = maxas + maxds;
5637 nbbx.ascent = maxas;
5638 nbbx.descent = maxds;
5639 nbbx.y_offset = -maxds;
5642 * Now determine if the combination of the glyphs removed and the new
5643 * glyphs cause the font bounding box to be changed.
5645 resize = (nbbx.width > font->bbx.width ||
5646 nbbx.height > font->bbx.height) ? 1 : 0;
5649 * Set the pointers to the glyphs.
5651 ng = (unencoded == 0) ? font->glyphs_used : font->unencoded_used;
5652 gp = (unencoded == 0) ? font->glyphs : font->unencoded;
5655 * Locate the closest glyph on or following `start'.
5657 for (i = 0; i < ng && gp->encoding < start; i++, gp++) ;
5661 * If the gylphs are being added off the end of the list, simply insert
5662 * them so any overflows can be handled.
5664 return bdf_insert_glyphs(font, start, glyphs);
5667 * Set the starting point for copying the incoming glyphs.
5671 n = glyphs->end - glyphs->start;
5675 * Count the number of glyphs that will be added and mark all the
5676 * glyphs that will be modified.
5678 for (sgp = glyphs->glyphs, add = 0, i = start; i <= end; i++) {
5679 enc = (sgp->encoding - glyphs->start) + start;
5682 * Mark the glyph as being modified.
5685 _bdf_set_glyph_modified(font->nmod, enc);
5687 _bdf_set_glyph_modified(font->umod, enc);
5689 if (enc == gp->encoding)
5691 else if (enc < gp->encoding) {
5696 if (gp->encoding == i)
5704 * Need to make room for some glyphs that will be added.
5707 off = dgp - font->unencoded;
5708 if (font->unencoded_used == 0)
5710 (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) * ng);
5713 (bdf_glyph_t *) realloc((char *) font->unencoded,
5714 sizeof(bdf_glyph_t) * ng);
5715 dgp = font->unencoded + off;
5716 font->unencoded_used = ng;
5718 off = dgp - font->glyphs;
5719 if (font->glyphs_used == 0)
5721 (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) * ng);
5724 (bdf_glyph_t *) realloc((char *) font->glyphs,
5725 sizeof(bdf_glyph_t) * ng);
5726 dgp = font->glyphs + off;
5727 font->glyphs_used = ng;
5732 * Now go through and do two things:
5733 * 1. Insert new incoming glyphs.
5734 * 2. Combine two glyphs at the same location.
5736 base = (!unencoded) ? font->glyphs : font->unencoded;
5737 for (gp = dgp, sgp = glyphs->glyphs, i = start; i <= end; i++) {
5738 enc = (sgp->encoding - glyphs->start) + start;
5739 if (enc < gp->encoding) {
5741 * Shift the glyphs up by one and add this one.
5744 _bdf_memmove((char *) (gp + 1), (char *) gp,
5745 sizeof(bdf_glyph_t) * (ng - (gp - base)));
5746 (void) memcpy((char *) gp, (char *) sgp, sizeof(bdf_glyph_t));
5747 gp->name = (char *) _bdf_strdup((unsigned char *) gp->name,
5748 strlen(gp->name) + 1);
5750 gp->bitmap = _bdf_strdup(gp->bitmap, gp->bytes);
5751 if (gp->unicode.map_size > 0)
5752 gp->unicode.map = _bdf_strdup(gp->unicode.map,
5753 gp->unicode.map_size);
5756 dw = (double) gp->dwidth;
5757 gp->swidth = (unsigned short) ((dw * 72000.0) / (ps * rx));
5758 } else if (enc == gp->encoding) {
5759 _bdf_combine_glyphs(font, gp, sgp);
5760 dw = (double) gp->dwidth;
5761 gp->swidth = (unsigned short) ((dw * 72000.0) / (ps * rx));
5764 if (gp->encoding == i)
5769 (void) memcpy((char *) &font->bbx, (char *) &nbbx, sizeof(bdf_bbx_t));
5777 bdf_set_modified(bdf_font_t *font, int modified)
5779 if (font == 0 || font->modified == modified)
5782 if (modified == 0) {
5784 * Clear out the modified bitmaps.
5786 (void) memset((char *) font->nmod, 0, sizeof(unsigned int) * 2048);
5787 (void) memset((char *) font->umod, 0, sizeof(unsigned int) * 2048);
5789 font->modified = modified;
5792 /**************************************************************************
5794 * XLFD font name functions.
5796 **************************************************************************/
5798 static char *xlfdfields[] = {
5816 bdf_is_xlfd_property(char *name)
5820 for (i = 0; i < 14; i++) {
5821 if (strcmp(name, xlfdfields[i]) == 0)
5828 bdf_has_xlfd_name(bdf_font_t *font)
5834 if (font == 0 || font->name == 0 || font->name[0] == 0)
5837 len = (unsigned int) (strlen(font->name) + 1);
5838 (void) memcpy(name, font->name, len);
5839 list.size = list.used = 0;
5840 _bdf_split("-", name, len, &list);
5842 free((char *) list.field);
5844 return (list.used == 15);
5848 bdf_make_xlfd_name(bdf_font_t *font, char *foundry, char *family)
5852 unsigned int i, width, used;
5853 unsigned short awidth, pxsize;
5856 char spacing, *name, *val, *np, nbuf[256];
5858 if (font == 0 || bdf_has_xlfd_name(font))
5864 * Add the FOUNDRY field.
5866 if ((pp = bdf_get_font_property(font, "FOUNDRY")) != 0)
5867 foundry = pp->value.atom;
5868 sprintf(np, "-%s", foundry);
5872 * Add the FAMILY_NAME field.
5874 if ((pp = bdf_get_font_property(font, "FAMILY_NAME")) != 0)
5875 family = pp->value.atom;
5876 sprintf(np, "-%s", family);
5880 * Add the WEIGHT_NAME field.
5882 val = ((pp = bdf_get_font_property(font, "WEIGHT_NAME")) != 0) ?
5883 pp->value.atom : "Medium";
5886 sprintf(np, "-%s", val);
5890 * Add the SLANT field.
5892 val = ((pp = bdf_get_font_property(font, "SLANT")) != 0) ?
5893 pp->value.atom : "R";
5896 sprintf(np, "-%s", val);
5900 * Add the SETWIDTH_NAME field.
5902 val = ((pp = bdf_get_font_property(font, "SETWIDTH_NAME")) != 0) ?
5903 pp->value.atom : "Normal";
5906 sprintf(np, "-%s", val);
5910 * Add the ADD_STYLE_NAME field.
5912 val = ((pp = bdf_get_font_property(font, "ADD_STYLE_NAME")) != 0) ?
5913 pp->value.atom : "";
5916 sprintf(np, "-%s", val);
5920 * Add the PIXEL_SIZE field.
5922 if ((pp = bdf_get_font_property(font, "PIXEL_SIZE")) != 0)
5923 sprintf(np, "-%d", pp->value.int32);
5926 * Determine the pixel size.
5928 dp = (double) (font->point_size * 10);
5929 dr = (double) font->resolution_y;
5930 pxsize = (unsigned short) (((dp * dr) / 722.7) + 0.5);
5931 sprintf(np, "-%hd", pxsize);
5936 * Add the POINT_SIZE field.
5938 if ((pp = bdf_get_font_property(font, "POINT_SIZE")) != 0)
5939 sprintf(np, "-%d", pp->value.int32);
5941 sprintf(np, "-%d", font->point_size * 10);
5945 * Add the RESOLUTION_X field.
5947 if ((pp = bdf_get_font_property(font, "RESOLUTION_X")) != 0)
5948 sprintf(np, "-%d", pp->value.card32);
5950 sprintf(np, "-%d", font->resolution_x);
5954 * Add the RESOLUTION_Y field.
5956 if ((pp = bdf_get_font_property(font, "RESOLUTION_Y")) != 0)
5957 sprintf(np, "-%d", pp->value.card32);
5959 sprintf(np, "-%d", font->resolution_y);
5963 * Add the SPACING field.
5965 if ((pp = bdf_get_font_property(font, "SPACING")) != 0)
5966 spacing = pp->value.atom[0];
5969 switch (font->spacing) {
5970 case BDF_PROPORTIONAL: spacing = 'P'; break;
5971 case BDF_MONOWIDTH: spacing = 'M'; break;
5972 case BDF_CHARCELL: spacing = 'C'; break;
5975 sprintf(np, "-%c", spacing);
5979 * Add the AVERAGE_WIDTH field.
5981 if ((pp = bdf_get_font_property(font, "AVERAGE_WIDTH")) != 0)
5982 sprintf(np, "-%d", pp->value.int32);
5985 * Determine the average width of all the glyphs in the font.
5988 for (i = 0, gp = font->unencoded; i < font->unencoded_used; i++, gp++)
5989 width += gp->dwidth;
5990 for (i = 0, gp = font->glyphs; i < font->glyphs_used; i++, gp++)
5991 width += gp->dwidth;
5993 used = font->unencoded_used + font->glyphs_used;
5995 awidth = font->bbx.width * 10;
5997 awidth = (unsigned short) ((((float) width) /
5998 ((float) used)) * 10.0);
5999 sprintf(np, "-%hd", awidth);
6004 * Add the CHARSET_REGISTRY field.
6006 val = ((pp = bdf_get_font_property(font, "CHARSET_REGISTRY")) != 0) ?
6007 pp->value.atom : "FontSpecific";
6008 sprintf(np, "-%s", val);
6012 * Add the CHARSET_ENCODING field.
6014 val = ((pp = bdf_get_font_property(font, "CHARSET_ENCODING")) != 0) ?
6015 pp->value.atom : "0";
6016 sprintf(np, "-%s", val);
6019 len = (np - nbuf) + 1;
6020 name = (char *) malloc(len);
6021 (void) memcpy(name, nbuf, len);
6026 bdf_update_name_from_properties(bdf_font_t *font)
6031 char *np, name[128], nname[128];
6033 if (font == 0 || bdf_has_xlfd_name(font) == 0)
6036 (void) memset((char *) &list, 0, sizeof(_bdf_list_t));
6039 * Split the name into fields and shift out the first empty field.
6040 * This assumes that the font has a name.
6042 i = (unsigned int) strlen(font->name);
6043 (void) memcpy(name, font->name, i + 1);
6044 _bdf_split("-", name, i, &list);
6045 _bdf_shift(1, &list);
6048 * Initialize the pointer to the new name and add the '-' prefix.
6054 for (i = 0; i < 14; i++) {
6055 if ((p = bdf_get_font_property(font, xlfdfields[i])) != 0) {
6057 * The property exists, so add it to the new font name.
6059 switch (p->format) {
6061 if (p->value.atom != 0)
6062 sprintf(np, "%s", p->value.atom);
6065 sprintf(np, "%d", p->value.card32);
6068 sprintf(np, "%d", p->value.int32);
6073 * The property does not exist, so add the original value to the
6076 sprintf(np, "%s", list.field[i]);
6085 * Replace the existing font name with the new one.
6088 i = (unsigned int) (strlen(nname) + 1);
6089 font->name = (char *) malloc(i);
6090 (void) memcpy(font->name, nname, i);
6096 free((char *) list.field);
6102 bdf_update_properties_from_name(bdf_font_t *font)
6105 bdf_property_t *p, prop;
6109 if (font == 0 || font->name == 0 || bdf_has_xlfd_name(font) == 0)
6112 (void) memset((char *) &list, 0, sizeof(_bdf_list_t));
6115 * Split the name into fields and shift out the first empty field.
6117 i = (unsigned int) strlen(font->name);
6118 (void) memcpy(name, font->name, i + 1);
6119 _bdf_split("-", name, i, &list);
6120 _bdf_shift(1, &list);
6122 for (i = 0; i < 14; i++) {
6123 p = bdf_get_property(xlfdfields[i]);
6124 prop.name = p->name;
6125 prop.format = p->format;
6126 switch (prop.format) {
6128 prop.value.atom = list.field[i];
6131 prop.value.card32 = _bdf_atoul(list.field[i], 0, 10);
6134 prop.value.int32 = _bdf_atol(list.field[i], 0, 10);
6137 bdf_add_font_property(font, &prop);
6144 free((char *) list.field);
6152 bdf_update_average_width(bdf_font_t *font)
6156 int oaw, awidth, used;
6159 bdf_property_t *pp, prop;
6160 char *np, num[16], nbuf[128];
6164 used = font->unencoded_used + font->glyphs_used;
6166 awidth = font->bbx.width * 10;
6168 for (i = 0, awidth = 0, gp = font->unencoded; i < font->unencoded_used;
6170 awidth += gp->dwidth;
6171 for (i = 0, gp = font->glyphs; i < font->glyphs_used; i++, gp++)
6172 awidth += gp->dwidth;
6173 awidth = (int) ((((double) awidth) / ((double) used)) * 10.0);
6177 * Check to see if it is different than the average width in the font
6180 if (bdf_has_xlfd_name(font)) {
6181 (void) memset((char *) &list, 0, sizeof(_bdf_list_t));
6182 i = (unsigned int) strlen(font->name);
6183 (void) memcpy(nbuf, font->name, i + 1);
6184 _bdf_split("-", nbuf, i, &list);
6185 oaw = _bdf_atol(list.field[12], 0, 10);
6186 if (oaw != awidth) {
6188 * Construct a new font name with the new average width.
6191 sprintf(num, "%d", awidth);
6192 used = strlen(num) - strlen(list.field[12]);
6195 * Resize the string used for the font name instead of
6196 * creating a new one.
6199 font->name = (char *) realloc(font->name, used);
6203 * Copy the elements of the list back into the new font name.
6207 for (i = 1; i < list.used; i++) {
6211 strcpy(np, list.field[i]);
6213 if (i + 1 < list.used)
6219 * Clear up any space allocated for the list.
6222 free((char *) list.field);
6226 * Now check for the AVERAGE_WIDTH property.
6228 if ((pp = bdf_get_font_property(font, "AVERAGE_WIDTH")) != 0) {
6229 if (pp->value.int32 != awidth) {
6231 pp->value.int32 = awidth;
6235 * Property doesn't exist yet, so add it.
6238 prop.name = "AVERAGE_WIDTH";
6239 prop.format = BDF_INTEGER;
6240 prop.value.int32 = awidth;
6241 bdf_add_font_property(font, &prop);
6251 * Change the font bounding box and return a non-zero number if this causes
6252 * the font to get larger or smaller.
6255 bdf_set_font_bbx(bdf_font_t *font, bdf_metrics_t *metrics)
6261 if (font == 0 || metrics == 0)
6264 resize = (font->bbx.width != metrics->width ||
6265 font->bbx.height != metrics->height) ? 1 : 0;
6267 font->bbx.width = metrics->width;
6268 font->bbx.height = metrics->height;
6269 font->bbx.x_offset = metrics->x_offset;
6270 font->bbx.y_offset = metrics->y_offset;
6271 font->bbx.ascent = metrics->ascent;
6272 font->bbx.descent = metrics->descent;
6275 * If the font is not proportional, then make sure the monowidth field is
6276 * set to the font bounding box.
6278 if (font->spacing != BDF_PROPORTIONAL)
6279 font->monowidth = font->bbx.width;
6285 bdf_translate_glyphs(bdf_font_t *font, short dx, short dy, int start,
6286 int end, bdf_callback_t callback, void *data,
6290 bdf_glyph_t *gp, *sp, *ep;
6291 bdf_callback_struct_t cb;
6293 if (font == 0 || (dx == 0 && dy == 0))
6296 if ((unencoded && font->unencoded_used == 0) || font->glyphs_used == 0)
6300 * Call the progress initialization callback.
6302 if (callback != 0) {
6303 cb.reason = BDF_TRANSLATE_START;
6304 cb.total = (end - start) + 1;
6306 (*callback)(&cb, data);
6310 * Locate the first and last glyphs to be shifted.
6312 sp = _bdf_locate_glyph(font, start, unencoded);
6313 ep = _bdf_locate_glyph(font, end, unencoded);
6314 for (resize = 0, gp = sp; sp <= ep; sp++) {
6316 * Call the callback if one was provided.
6318 if (sp != gp && callback != 0) {
6319 cb.reason = BDF_TRANSLATING;
6320 cb.current = (sp->encoding - start) + 1;
6321 (*callback)(&cb, data);
6325 * Apply the X translation.
6328 sp->bbx.x_offset += dx;
6329 diff = sp->bbx.x_offset - font->bbx.x_offset;
6330 if (sp->bbx.x_offset < font->bbx.x_offset) {
6331 font->bbx.x_offset = sp->bbx.x_offset;
6332 font->bbx.width += MYABS(diff);
6334 } else if (sp->bbx.width + sp->bbx.x_offset >
6335 font->bbx.width + font->bbx.x_offset) {
6336 font->bbx.width += MYABS(diff);
6341 * Mark the glyph as modified appropriately.
6344 _bdf_set_glyph_modified(font->umod, sp->encoding);
6346 _bdf_set_glyph_modified(font->nmod, sp->encoding);
6350 * Apply the Y translation.
6353 sp->bbx.y_offset += dy;
6354 sp->bbx.descent = -sp->bbx.y_offset;
6355 sp->bbx.ascent = sp->bbx.height - sp->bbx.descent;
6356 diff = sp->bbx.y_offset - font->bbx.y_offset;
6357 if (sp->bbx.y_offset < font->bbx.y_offset) {
6358 font->bbx.y_offset = sp->bbx.y_offset;
6359 font->bbx.descent = -font->bbx.y_offset;
6360 font->bbx.height += MYABS(diff);
6362 } else if (sp->bbx.ascent > font->bbx.ascent) {
6363 font->bbx.ascent += MYABS(diff);
6364 font->bbx.height += MYABS(diff);
6369 * Mark the glyph as modified appropriately.
6372 _bdf_set_glyph_modified(font->umod, sp->encoding);
6374 _bdf_set_glyph_modified(font->nmod, sp->encoding);
6379 * Call the callback one more time to make sure the client knows
6382 if (callback != 0 && cb.current < cb.total) {
6383 cb.reason = BDF_TRANSLATING;
6384 cb.current = cb.total;
6385 (*callback)(&cb, data);
6395 _bdf_resize_rotation(bdf_font_t *font, int mul90, short degrees,
6396 bdf_glyph_t *glyph, bdf_bitmap_t *scratch,
6397 unsigned short *width, unsigned short *height)
6399 unsigned short w, h, wd, ht, bytes;
6400 short cx, cy, x1, y1, x2, y2;
6401 double dx1, dy1, dx2, dy2;
6405 cx = glyph->bbx.width >> 1;
6406 cy = glyph->bbx.height >> 1;
6409 * Rotate the lower left and upper right corners and check for a potential
6413 y1 = glyph->bbx.height;
6414 x2 = glyph->bbx.width;
6417 dx1 = (double) (x1 - cx);
6418 dy1 = (double) (y1 - cy);
6419 dx2 = (double) (x2 - cx);
6420 dy2 = (double) (y2 - cx);
6423 x1 = cx + (short) ((dx1 * _bdf_cos_tbl[degrees]) -
6424 (dy1 * _bdf_sin_tbl[degrees]));
6425 y1 = cy + (short) ((dx1 * _bdf_sin_tbl[degrees]) +
6426 (dy1 * _bdf_cos_tbl[degrees]));
6427 x2 = cx + (short) ((dx2 * _bdf_cos_tbl[degrees]) -
6428 (dy2 * _bdf_sin_tbl[degrees]));
6429 y2 = cy + (short) ((dx2 * _bdf_sin_tbl[degrees]) +
6430 (dy2 * _bdf_cos_tbl[degrees]));
6432 x1 = cx + _bdf_ceiling((dx1 * _bdf_cos_tbl[degrees]) -
6433 (dy1 * _bdf_sin_tbl[degrees]));
6434 y1 = cy + _bdf_ceiling((dx1 * _bdf_sin_tbl[degrees]) +
6435 (dy1 * _bdf_cos_tbl[degrees]));
6436 x2 = cx + _bdf_ceiling((dx2 * _bdf_cos_tbl[degrees]) -
6437 (dy2 * _bdf_sin_tbl[degrees]));
6438 y2 = cy + _bdf_ceiling((dx2 * _bdf_sin_tbl[degrees]) +
6439 (dy2 * _bdf_cos_tbl[degrees]));
6442 wd = MYABS(x2 - x1);
6443 ht = MYABS(y2 - y1);
6448 if (wd > font->bbx.width)
6449 font->bbx.width += wd - font->bbx.width;
6450 if (ht > font->bbx.height) {
6451 font->bbx.ascent += ht - font->bbx.height;
6452 font->bbx.height += ht - font->bbx.height;
6456 * Rotate the upper left and lower right corners and check for a potential
6461 x2 = glyph->bbx.width;
6462 y2 = glyph->bbx.height;
6464 dx1 = (double) (x1 - cx);
6465 dy1 = (double) (y1 - cy);
6466 dx2 = (double) (x2 - cx);
6467 dy2 = (double) (y2 - cx);
6470 x1 = cx + (short) ((dx1 * _bdf_cos_tbl[degrees]) -
6471 (dy1 * _bdf_sin_tbl[degrees]));
6472 y1 = cy + (short) ((dx1 * _bdf_sin_tbl[degrees]) +
6473 (dy1 * _bdf_cos_tbl[degrees]));
6474 x2 = cx + (short) ((dx2 * _bdf_cos_tbl[degrees]) -
6475 (dy2 * _bdf_sin_tbl[degrees]));
6476 y2 = cy + (short) ((dx2 * _bdf_sin_tbl[degrees]) +
6477 (dy2 * _bdf_cos_tbl[degrees]));
6479 x1 = cx + _bdf_ceiling((dx1 * _bdf_cos_tbl[degrees]) -
6480 (dy1 * _bdf_sin_tbl[degrees]));
6481 y1 = cy + _bdf_ceiling((dx1 * _bdf_sin_tbl[degrees]) +
6482 (dy1 * _bdf_cos_tbl[degrees]));
6483 x2 = cx + _bdf_ceiling((dx2 * _bdf_cos_tbl[degrees]) -
6484 (dy2 * _bdf_sin_tbl[degrees]));
6485 y2 = cy + _bdf_ceiling((dx2 * _bdf_sin_tbl[degrees]) +
6486 (dy2 * _bdf_cos_tbl[degrees]));
6489 wd = MYABS(x2 - x1);
6490 ht = MYABS(y2 - y1);
6495 if (wd > font->bbx.width)
6496 font->bbx.width += wd - font->bbx.width;
6497 if (ht > font->bbx.height) {
6498 font->bbx.ascent += ht - font->bbx.height;
6499 font->bbx.height += ht - font->bbx.height;
6502 if (font->bbx.width > scratch->width ||
6503 font->bbx.height > scratch->height) {
6504 scratch->width = MAX(font->bbx.width, scratch->width);
6505 scratch->height = MAX(font->bbx.height, scratch->height);
6506 bytes = (((font->bbx.width * font->bpp) + 7) >> 3) * font->bbx.height;
6507 if (scratch->bytes == 0)
6508 scratch->bitmap = (unsigned char *) malloc(bytes);
6510 scratch->bitmap = (unsigned char *)
6511 realloc((char *) scratch->bitmap, bytes);
6512 scratch->bytes = bytes;
6518 (void) memset((char *) scratch->bitmap, 0, scratch->bytes);
6521 * Return the new glyph width and height.
6528 bdf_rotate_glyphs(bdf_font_t *font, short degrees, int start,
6529 int end, bdf_callback_t callback, void *data,
6532 int mul90, bpr, sbpr;
6533 unsigned short wd, ht, si, di, byte, col;
6534 short x, y, cx, cy, nx, ny, ox, oy, shiftx, shifty;
6535 bdf_glyph_t *gp, *sp, *ep;
6536 unsigned char *masks;
6538 bdf_bitmap_t scratch;
6539 bdf_callback_struct_t cb;
6542 (unencoded && font->unencoded_used == 0) ||
6543 font->glyphs_used == 0 ||
6549 while (degrees >= 360)
6552 mul90 = ((degrees % 90) == 0) ? 1 : 0;
6555 switch (font->bpp) {
6556 case 1: masks = bdf_onebpp; break;
6557 case 2: masks = bdf_twobpp; break;
6558 case 4: masks = bdf_fourbpp; break;
6559 case 8: masks = bdf_eightbpp; break;
6563 * Initialize the scratch bitmap.
6565 (void) memset((char *) &scratch, 0, sizeof(bdf_bitmap_t));
6568 * Call the progress initialization callback.
6570 if (callback != 0) {
6571 cb.reason = BDF_ROTATE_START;
6572 cb.total = (end - start) + 1;
6574 (*callback)(&cb, data);
6577 sp = _bdf_locate_glyph(font, start, unencoded);
6578 ep = _bdf_locate_glyph(font, end, unencoded);
6579 for (gp = sp; sp <= ep; sp++) {
6581 * Call the callback if one was provided.
6583 if (sp != gp && callback != 0) {
6584 cb.reason = BDF_ROTATING;
6585 cb.current = (sp->encoding - start) + 1;
6586 (*callback)(&cb, data);
6590 * Resize the bitmap, adjust the font bounding box, and get the new
6591 * glyph width and height.
6593 _bdf_resize_rotation(font, mul90, degrees, sp, &scratch, &wd, &ht);
6595 cx = sp->bbx.width >> 1;
6596 cy = sp->bbx.height >> 1;
6598 shiftx = shifty = 0;
6599 sbpr = ((wd * font->bpp) + 7) >> 3;
6600 bpr = ((sp->bbx.width * font->bpp) + 7) >> 3;
6601 for (y = 0; y < sp->bbx.height; y++) {
6602 for (col = x = 0; x < sp->bbx.width; x++, col += font->bpp) {
6603 si = (col & 7) / font->bpp;
6604 byte = sp->bitmap[(y * bpr) + (col >> 3)] & masks[si];
6606 dx = (double) (x - cx);
6607 dy = (double) (y - cy);
6609 nx = cx + (short) ((dx * _bdf_cos_tbl[degrees]) -
6610 (dy * _bdf_sin_tbl[degrees]));
6611 ny = cy + (short) ((dx * _bdf_sin_tbl[degrees]) +
6612 (dy * _bdf_cos_tbl[degrees]));
6614 nx = cx + _bdf_ceiling((dx * _bdf_cos_tbl[degrees]) -
6615 (dy * _bdf_sin_tbl[degrees]));
6616 ny = cy + _bdf_ceiling((dx * _bdf_sin_tbl[degrees]) +
6617 (dy * _bdf_cos_tbl[degrees]));
6620 shiftx = MIN(shiftx, nx);
6622 } else if (nx >= wd) {
6624 shiftx = MAX(shiftx, ox);
6628 shifty = MIN(shifty, ny);
6630 } else if (ny >= ht) {
6632 shifty = MAX(shifty, oy);
6636 di = (nx & 7) / font->bpp;
6638 byte <<= (si - di) * font->bpp;
6640 byte >>= (di - si) * font->bpp;
6641 scratch.bitmap[(ny * sbpr) + (nx >> 3)] |= byte;
6646 * Resize the glyph bitmap if necessary.
6648 if (wd != sp->bbx.width || ht != sp->bbx.height) {
6650 sp->bbx.height = ht;
6651 sp->bbx.ascent = ht - sp->bbx.descent;
6652 sp->bytes = (((wd * font->bpp) + 7) >> 3) * ht;
6653 sp->bitmap = (unsigned char *)
6654 realloc((char *) sp->bitmap, sp->bytes);
6656 (void) memset((char *) sp->bitmap, 0, sp->bytes);
6659 * Copy the glyph from the scratch area to the glyph bitmap,
6660 * adjusting for any shift values encountered.
6662 bpr = ((sp->bbx.width * font->bpp) + 7) >> 3;
6663 for (y = 0; y < sp->bbx.height; y++) {
6664 for (col = x = 0; x < sp->bbx.width; x++, col += font->bpp) {
6665 si = (col & 7) / font->bpp;
6666 byte = scratch.bitmap[(y * bpr) + (col >> 3)] & masks[si];
6671 nx += sp->bbx.width;
6672 else if (nx >= sp->bbx.width)
6673 nx -= sp->bbx.width;
6675 ny += sp->bbx.height;
6676 else if (ny >= sp->bbx.height)
6677 ny -= sp->bbx.height;
6679 di = (nx & 7) / font->bpp;
6681 byte <<= (si - di) * font->bpp;
6683 byte >>= (di - si) * font->bpp;
6684 sp->bitmap[(ny * bpr) + (nx >> 3)] |= byte;
6689 * Mark the glyph as modified.
6692 _bdf_set_glyph_modified(font->umod, sp->encoding);
6694 _bdf_set_glyph_modified(font->nmod, sp->encoding);
6698 * Call the callback one more time to make sure the client knows
6701 if (callback != 0 && cb.current < cb.total) {
6702 cb.reason = BDF_TRANSLATING;
6703 cb.current = cb.total;
6704 (*callback)(&cb, data);
6707 if (scratch.bytes > 0)
6708 free((char *) scratch.bitmap);
6711 * Rotations always change things, so just return a value indicating this.
6718 _bdf_resize_shear(bdf_font_t *font, int neg, short degrees,
6719 bdf_glyph_t *glyph, bdf_bitmap_t *scratch,
6720 unsigned short *width, unsigned short *height)
6722 unsigned short wd, w, bytes;
6723 short x1, y1, x2, y2;
6726 *height = glyph->bbx.height;
6729 * Shear the lower left and upper right corners and check for a potential
6733 y1 = glyph->bbx.height;
6734 x2 = glyph->bbx.width;
6738 x1 += (short) ((double) y1 * _bdf_tan_tbl[degrees]);
6739 x2 += (short) ((double) y2 * _bdf_tan_tbl[degrees]);
6741 x1 += (short) ((double) (glyph->bbx.height - y1) *
6742 _bdf_tan_tbl[degrees]);
6743 x2 += (short) ((double) (glyph->bbx.height - y2) *
6744 _bdf_tan_tbl[degrees]);
6747 wd = MYABS(x2 - x1);
6750 if (wd > font->bbx.width)
6751 font->bbx.width += wd - font->bbx.width;
6754 * Shear the upper left and lower right corners and check for a potential
6759 x2 = glyph->bbx.width;
6760 y2 = glyph->bbx.height;
6763 x1 += (short) ((double) y1 * _bdf_tan_tbl[degrees]);
6764 x2 += (short) ((double) y2 * _bdf_tan_tbl[degrees]);
6766 x1 += (short) ((double) (glyph->bbx.height - y1) *
6767 _bdf_tan_tbl[degrees]);
6768 x2 += (short) ((double) (glyph->bbx.height - y2) *
6769 _bdf_tan_tbl[degrees]);
6772 wd = MYABS(x2 - x1);
6775 if (wd > font->bbx.width)
6776 font->bbx.width += wd - font->bbx.width;
6778 if (font->bbx.width > scratch->width ||
6779 font->bbx.height > scratch->height) {
6780 scratch->width = MAX(font->bbx.width, scratch->width);
6781 scratch->height = MAX(font->bbx.height, scratch->height);
6782 bytes = (((font->bbx.width * font->bpp) + 7) >> 3) * font->bbx.height;
6783 if (scratch->bytes == 0)
6784 scratch->bitmap = (unsigned char *) malloc(bytes);
6786 scratch->bitmap = (unsigned char *)
6787 realloc((char *) scratch->bitmap, bytes);
6788 scratch->bytes = bytes;
6794 (void) memset((char *) scratch->bitmap, 0, scratch->bytes);
6797 * Return the new glyph width.
6803 bdf_shear_glyphs(bdf_font_t *font, short degrees, int start,
6804 int end, bdf_callback_t callback, void *data,
6808 unsigned short wd, ht, si, di, byte, col;
6809 short x, y, nx, shiftx, ox;
6810 bdf_glyph_t *gp, *sp, *ep;
6811 unsigned char *masks;
6812 bdf_bitmap_t scratch;
6813 bdf_callback_struct_t cb;
6815 if (font == 0 || (unencoded && font->unencoded_used == 0) ||
6816 font->glyphs_used == 0)
6819 if (degrees == 0 || degrees < -45 || degrees > 45)
6822 if ((neg = (degrees < 0)))
6826 switch (font->bpp) {
6827 case 1: masks = bdf_onebpp; break;
6828 case 2: masks = bdf_twobpp; break;
6829 case 4: masks = bdf_fourbpp; break;
6830 case 8: masks = bdf_eightbpp; break;
6834 * Initialize the scratch bitmap.
6836 (void) memset((char *) &scratch, 0, sizeof(bdf_bitmap_t));
6839 * Call the progress initialization callback.
6841 if (callback != 0) {
6842 cb.reason = BDF_SHEAR_START;
6843 cb.total = (end - start) + 1;
6845 (*callback)(&cb, data);
6848 sp = _bdf_locate_glyph(font, start, unencoded);
6849 ep = _bdf_locate_glyph(font, end, unencoded);
6850 for (gp = sp; sp <= ep; sp++) {
6852 * Call the callback if one was provided.
6854 if (sp != gp && callback != 0) {
6855 cb.reason = BDF_SHEARING;
6856 cb.current = (sp->encoding - start) + 1;
6857 (*callback)(&cb, data);
6861 * Resize the bitmap, adjust the font bounding box, and get the new
6862 * glyph width and height.
6864 _bdf_resize_shear(font, neg, degrees, sp, &scratch, &wd, &ht);
6867 sbpr = ((wd * font->bpp) + 7) >> 3;
6868 bpr = ((sp->bbx.width * font->bpp) + 7) >> 3;
6869 for (y = 0; y < sp->bbx.height; y++) {
6870 for (col = x = 0; x < sp->bbx.width; x++, col += font->bpp) {
6871 si = (col & 7) / font->bpp;
6872 byte = sp->bitmap[(y * bpr) + (col >> 3)] & masks[si];
6875 nx = x + (short) ((double) y * _bdf_tan_tbl[degrees]);
6877 nx = x + (short) ((double) (sp->bbx.height - y) *
6878 _bdf_tan_tbl[degrees]);
6881 shiftx = MIN(shiftx, nx);
6883 } else if (nx >= wd) {
6885 shiftx = MAX(shiftx, ox);
6889 di = (nx & 7) / font->bpp;
6891 byte <<= (si - di) * font->bpp;
6893 byte >>= (di - si) * font->bpp;
6894 scratch.bitmap[(y * sbpr) + (nx >> 3)] |= byte;
6899 * Resize the glyph bitmap if necessary.
6901 if (wd != sp->bbx.width || ht != sp->bbx.height) {
6903 sp->bbx.height = ht;
6904 sp->bbx.ascent = ht - sp->bbx.descent;
6905 sp->bytes = (((wd * font->bpp) + 7) >> 3) * ht;
6906 sp->bitmap = (unsigned char *)
6907 realloc((char *) sp->bitmap, sp->bytes);
6909 (void) memset((char *) sp->bitmap, 0, sp->bytes);
6912 * Copy the glyph from the scratch area to the glyph bitmap,
6913 * adjusting for any shift values encountered.
6915 bpr = ((sp->bbx.width * font->bpp) + 7) >> 3;
6916 for (y = 0; y < sp->bbx.height; y++) {
6917 for (col = x = 0; x < sp->bbx.width; x++, col += font->bpp) {
6918 si = (col & 7) / font->bpp;
6919 byte = scratch.bitmap[(y * bpr) + (col >> 3)] & masks[si];
6923 nx += sp->bbx.width;
6924 else if (nx >= sp->bbx.width)
6925 nx -= sp->bbx.width;
6927 di = (nx & 7) / font->bpp;
6929 byte <<= (si - di) * font->bpp;
6931 byte >>= (di - si) * font->bpp;
6932 sp->bitmap[(y * bpr) + (nx >> 3)] |= byte;
6937 * Mark the glyph as modified.
6940 _bdf_set_glyph_modified(font->umod, sp->encoding);
6942 _bdf_set_glyph_modified(font->nmod, sp->encoding);
6946 * Call the callback one more time to make sure the client knows
6949 if (callback != 0 && cb.current < cb.total) {
6950 cb.reason = BDF_TRANSLATING;
6951 cb.current = cb.total;
6952 (*callback)(&cb, data);
6955 if (scratch.bytes > 0)
6956 free((char *) scratch.bitmap);
6959 * Rotations always change things, so just return a value indicating this.
6966 _bdf_widen_by(bdf_font_t *f, bdf_glyph_t *g, bdf_bitmap_t *s, int n)
6968 int bytes, sbpr, dbpr, col;
6970 unsigned char *bmap, *masks;
6974 case 1: masks = bdf_onebpp; break;
6975 case 2: masks = bdf_twobpp; break;
6976 case 4: masks = bdf_fourbpp; break;
6977 case 8: masks = bdf_eightbpp; break;
6980 s->height = g->bbx.height;
6981 s->width = g->bbx.width + n;
6983 bytes = (((s->width * f->bpp) + 7) >> 3) * s->height;
6986 s->bitmap = (unsigned char *) malloc(bytes);
6988 s->bitmap = (unsigned char *)
6989 realloc((char *) s->bitmap, bytes);
6992 (void) memset((char *) s->bitmap, 0, s->bytes);
6995 * Copy the glyph bitmap to the scratch area, and then swap the bitmaps.
6997 sbpr = ((g->bbx.width * f->bpp) + 7) >> 3;
6998 dbpr = ((s->width * f->bpp) + 7) >> 3;
6999 for (y = 0; y < g->bbx.height; y++) {
7000 for (col = x = 0; x < g->bbx.width; x++, col += f->bpp) {
7001 si = (col & 7) / f->bpp;
7002 bytes = g->bitmap[(y * sbpr) + (col >> 3)] & masks[si];
7004 di = ((x * f->bpp) & 7) / f->bpp;
7006 bytes <<= (si - di) * f->bpp;
7008 bytes >>= (di - si) * f->bpp;
7009 s->bitmap[(y * dbpr) + (col >> 3)] |= bytes;
7013 g->bbx.width = s->width;
7016 * Swap the bytes and bitmap fields from the scratch area and the glyph.
7019 g->bytes = s->bytes;
7023 g->bitmap = s->bitmap;
7028 bdf_embolden_glyphs(bdf_font_t *font, int start, int end,
7029 bdf_callback_t callback, void *data, int unencoded,
7034 unsigned short si, di, b1, b2, col;
7035 unsigned char *masks;
7036 bdf_glyph_t *gp, *sp, *ep;
7037 bdf_bitmap_t scratch;
7038 bdf_callback_struct_t cb;
7040 if (font == 0 || (unencoded && font->unencoded_used == 0) ||
7041 font->glyphs_used == 0)
7045 * Initialize the scratch bitmap which may be needed.
7047 (void) memset((char *) &scratch, 0, sizeof(bdf_bitmap_t));
7053 switch (font->bpp) {
7054 case 1: masks = bdf_onebpp; break;
7055 case 2: masks = bdf_twobpp; break;
7056 case 4: masks = bdf_fourbpp; break;
7057 case 8: masks = bdf_eightbpp; break;
7061 * Call the progress initialization callback.
7063 if (callback != 0) {
7064 cb.reason = BDF_EMBOLDEN_START;
7065 cb.total = (end - start) + 1;
7067 (*callback)(&cb, data);
7071 * Initialize the resize flag for the caller.
7075 sp = _bdf_locate_glyph(font, start, unencoded);
7076 ep = _bdf_locate_glyph(font, end, unencoded);
7077 for (; sp <= ep; sp++) {
7079 * Call the callback if one was provided.
7081 if (sp != gp && callback != 0) {
7082 cb.reason = BDF_EMBOLDENING;
7083 cb.current = (sp->encoding - start) + 1;
7084 (*callback)(&cb, data);
7087 if (font->spacing == BDF_PROPORTIONAL ||
7088 (font->spacing == BDF_MONOWIDTH &&
7089 sp->bbx.width < font->bbx.width)) {
7091 * Only widen the glyph if it is within reason.
7093 _bdf_widen_by(font, sp, &scratch, 1);
7095 if (sp->bbx.width > font->bbx.width) {
7097 * Bump the font width up by the difference.
7099 font->bbx.width += sp->bbx.width - font->bbx.width;
7105 bpr = ((sp->bbx.width * font->bpp) + 7) >> 3;
7106 for (y = 0; y < sp->bbx.height; y++) {
7107 col = (sp->bbx.width - 1) * font->bpp;
7108 for (x = sp->bbx.width - 1; x > 0; x--, col -= font->bpp) {
7109 si = (col & 7) / font->bpp;
7110 di = ((col - font->bpp) & 7) / font->bpp;
7111 b1 = (x == sp->bbx.width) ? 0 :
7112 sp->bitmap[(y * bpr) + (col >> 3)] & masks[si];
7113 b2 = sp->bitmap[(y * bpr) + ((col - font->bpp) >> 3)] &
7117 b2 >>= (si - di) * font->bpp;
7119 b2 <<= (di - si) * font->bpp;
7120 sp->bitmap[(y * bpr) + (col >> 3)] |= b2;
7126 * Mark the glyph as modified.
7130 _bdf_set_glyph_modified(font->umod, sp->encoding);
7132 _bdf_set_glyph_modified(font->nmod, sp->encoding);
7137 * Call the callback one more time to make sure the client knows
7140 if (callback != 0 && cb.current < cb.total) {
7141 cb.reason = BDF_EMBOLDENING;
7142 cb.current = cb.total;
7143 (*callback)(&cb, data);
7147 * Deallocate the scratch bitmap if necessary.
7149 if (scratch.bytes > 0)
7150 free((char *) scratch.bitmap);
7152 font->modified = mod;
7157 static int _endian = 1;
7158 static char *little_endian = (char *) &_endian;
7161 bdf_little_endian(void)
7163 return *little_endian;