zenilib: zenilib/jni/external/freetype2/src/bdf/bdflib.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
bdflib.c
Go to the documentation of this file.
1 /*
2 * Copyright 2000 Computing Research Labs, New Mexico State University
3 * Copyright 2001-2012
4 * Francesco Zappa Nardelli
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
20 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21 * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /*************************************************************************/
26 /* */
27 /* This file is based on bdf.c,v 1.22 2000/03/16 20:08:50 */
28 /* */
29 /* taken from Mark Leisher's xmbdfed package */
30 /* */
31 /*************************************************************************/
32
33
34 #include <ft2build.h>
35
36 #include FT_FREETYPE_H
37 #include FT_INTERNAL_DEBUG_H
38 #include FT_INTERNAL_STREAM_H
39 #include FT_INTERNAL_OBJECTS_H
40
41 #include "bdf.h"
42 #include "bdferror.h"
43
44
45 /*************************************************************************/
46 /* */
47 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
48 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
49 /* messages during execution. */
50 /* */
51 #undef FT_COMPONENT
52 #define FT_COMPONENT trace_bdflib
53
54
55 /*************************************************************************/
56 /* */
57 /* Default BDF font options. */
58 /* */
59 /*************************************************************************/
60
61
62 static const bdf_options_t _bdf_opts =
63 {
64 1, /* Correct metrics. */
65 1, /* Preserve unencoded glyphs. */
66 0, /* Preserve comments. */
67 BDF_PROPORTIONAL /* Default spacing. */
68 };
69
70
71 /*************************************************************************/
72 /* */
73 /* Builtin BDF font properties. */
74 /* */
75 /*************************************************************************/
76
77 /* List of most properties that might appear in a font. Doesn't include */
78 /* the RAW_* and AXIS_* properties in X11R6 polymorphic fonts. */
79
80 static const bdf_property_t _bdf_properties[] =
81 {
82 { (char *)"ADD_STYLE_NAME", BDF_ATOM, 1, { 0 } },
83 { (char *)"AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },
84 { (char *)"AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },
85 { (char *)"AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },
86 { (char *)"CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },
87 { (char *)"CHARSET_COLLECTIONS", BDF_ATOM, 1, { 0 } },
88 { (char *)"CHARSET_ENCODING", BDF_ATOM, 1, { 0 } },
89 { (char *)"CHARSET_REGISTRY", BDF_ATOM, 1, { 0 } },
90 { (char *)"COMMENT", BDF_ATOM, 1, { 0 } },
91 { (char *)"COPYRIGHT", BDF_ATOM, 1, { 0 } },
92 { (char *)"DEFAULT_CHAR", BDF_CARDINAL, 1, { 0 } },
93 { (char *)"DESTINATION", BDF_CARDINAL, 1, { 0 } },
94 { (char *)"DEVICE_FONT_NAME", BDF_ATOM, 1, { 0 } },
95 { (char *)"END_SPACE", BDF_INTEGER, 1, { 0 } },
96 { (char *)"FACE_NAME", BDF_ATOM, 1, { 0 } },
97 { (char *)"FAMILY_NAME", BDF_ATOM, 1, { 0 } },
98 { (char *)"FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },
99 { (char *)"FONT", BDF_ATOM, 1, { 0 } },
100 { (char *)"FONTNAME_REGISTRY", BDF_ATOM, 1, { 0 } },
101 { (char *)"FONT_ASCENT", BDF_INTEGER, 1, { 0 } },
102 { (char *)"FONT_DESCENT", BDF_INTEGER, 1, { 0 } },
103 { (char *)"FOUNDRY", BDF_ATOM, 1, { 0 } },
104 { (char *)"FULL_NAME", BDF_ATOM, 1, { 0 } },
105 { (char *)"ITALIC_ANGLE", BDF_INTEGER, 1, { 0 } },
106 { (char *)"MAX_SPACE", BDF_INTEGER, 1, { 0 } },
107 { (char *)"MIN_SPACE", BDF_INTEGER, 1, { 0 } },
108 { (char *)"NORM_SPACE", BDF_INTEGER, 1, { 0 } },
109 { (char *)"NOTICE", BDF_ATOM, 1, { 0 } },
110 { (char *)"PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },
111 { (char *)"POINT_SIZE", BDF_INTEGER, 1, { 0 } },
112 { (char *)"QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },
113 { (char *)"RAW_ASCENT", BDF_INTEGER, 1, { 0 } },
114 { (char *)"RAW_AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },
115 { (char *)"RAW_AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },
116 { (char *)"RAW_AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },
117 { (char *)"RAW_CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },
118 { (char *)"RAW_DESCENT", BDF_INTEGER, 1, { 0 } },
119 { (char *)"RAW_END_SPACE", BDF_INTEGER, 1, { 0 } },
120 { (char *)"RAW_FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },
121 { (char *)"RAW_MAX_SPACE", BDF_INTEGER, 1, { 0 } },
122 { (char *)"RAW_MIN_SPACE", BDF_INTEGER, 1, { 0 } },
123 { (char *)"RAW_NORM_SPACE", BDF_INTEGER, 1, { 0 } },
124 { (char *)"RAW_PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },
125 { (char *)"RAW_POINT_SIZE", BDF_INTEGER, 1, { 0 } },
126 { (char *)"RAW_PIXELSIZE", BDF_INTEGER, 1, { 0 } },
127 { (char *)"RAW_POINTSIZE", BDF_INTEGER, 1, { 0 } },
128 { (char *)"RAW_QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },
129 { (char *)"RAW_SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },
130 { (char *)"RAW_STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },
131 { (char *)"RAW_STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },
132 { (char *)"RAW_SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
133 { (char *)"RAW_SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },
134 { (char *)"RAW_SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
135 { (char *)"RAW_SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
136 { (char *)"RAW_SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },
137 { (char *)"RAW_SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
138 { (char *)"RAW_UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },
139 { (char *)"RAW_UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },
140 { (char *)"RAW_X_HEIGHT", BDF_INTEGER, 1, { 0 } },
141 { (char *)"RELATIVE_SETWIDTH", BDF_CARDINAL, 1, { 0 } },
142 { (char *)"RELATIVE_WEIGHT", BDF_CARDINAL, 1, { 0 } },
143 { (char *)"RESOLUTION", BDF_INTEGER, 1, { 0 } },
144 { (char *)"RESOLUTION_X", BDF_CARDINAL, 1, { 0 } },
145 { (char *)"RESOLUTION_Y", BDF_CARDINAL, 1, { 0 } },
146 { (char *)"SETWIDTH_NAME", BDF_ATOM, 1, { 0 } },
147 { (char *)"SLANT", BDF_ATOM, 1, { 0 } },
148 { (char *)"SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },
149 { (char *)"SPACING", BDF_ATOM, 1, { 0 } },
150 { (char *)"STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },
151 { (char *)"STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },
152 { (char *)"SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
153 { (char *)"SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },
154 { (char *)"SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
155 { (char *)"SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
156 { (char *)"SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },
157 { (char *)"SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
158 { (char *)"UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },
159 { (char *)"UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },
160 { (char *)"WEIGHT", BDF_CARDINAL, 1, { 0 } },
161 { (char *)"WEIGHT_NAME", BDF_ATOM, 1, { 0 } },
162 { (char *)"X_HEIGHT", BDF_INTEGER, 1, { 0 } },
163 { (char *)"_MULE_BASELINE_OFFSET", BDF_INTEGER, 1, { 0 } },
164 { (char *)"_MULE_RELATIVE_COMPOSE", BDF_INTEGER, 1, { 0 } },
165 };
166
167 static const unsigned long
168 _num_bdf_properties = sizeof ( _bdf_properties ) /
169 sizeof ( _bdf_properties[0] );
170
171
172 /* Auto correction messages. */
173 #define ACMSG1 "FONT_ASCENT property missing. " \
174 "Added `FONT_ASCENT %hd'.\n"
175 #define ACMSG2 "FONT_DESCENT property missing. " \
176 "Added `FONT_DESCENT %hd'.\n"
177 #define ACMSG3 "Font width != actual width. Old: %hd New: %hd.\n"
178 #define ACMSG4 "Font left bearing != actual left bearing. " \
179 "Old: %hd New: %hd.\n"
180 #define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd.\n"
181 #define ACMSG6 "Font descent != actual descent. Old: %hd New: %hd.\n"
182 #define ACMSG7 "Font height != actual height. Old: %hd New: %hd.\n"
183 #define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made.\n"
184 #define ACMSG9 "SWIDTH field missing at line %ld. Set automatically.\n"
185 #define ACMSG10 "DWIDTH field missing at line %ld. Set to glyph width.\n"
186 #define ACMSG11 "SIZE bits per pixel field adjusted to %hd.\n"
187 #define ACMSG12 "Duplicate encoding %ld (%s) changed to unencoded.\n"
188 #define ACMSG13 "Glyph %ld extra rows removed.\n"
189 #define ACMSG14 "Glyph %ld extra columns removed.\n"
190 #define ACMSG15 "Incorrect glyph count: %ld indicated but %ld found.\n"
191 #define ACMSG16 "Glyph %ld missing columns padded with zero bits.\n"
192
193 /* Error messages. */
194 #define ERRMSG1 "[line %ld] Missing `%s' line.\n"
195 #define ERRMSG2 "[line %ld] Font header corrupted or missing fields.\n"
196 #define ERRMSG3 "[line %ld] Font glyphs corrupted or missing fields.\n"
197 #define ERRMSG4 "[line %ld] BBX too big.\n"
198 #define ERRMSG5 "[line %ld] `%s' value too big.\n"
199 #define ERRMSG6 "[line %ld] Input line too long.\n"
200 #define ERRMSG7 "[line %ld] Font name too long.\n"
201 #define ERRMSG8 "[line %ld] Invalid `%s' value.\n"
202 #define ERRMSG9 "[line %ld] Invalid keyword.\n"
203
204 /* Debug messages. */
205 #define DBGMSG1 " [%6ld] %s" /* no \n */
206 #define DBGMSG2 " (0x%lX)\n"
207
208
209 /*************************************************************************/
210 /* */
211 /* Hash table utilities for the properties. */
212 /* */
213 /*************************************************************************/
214
215 /* XXX: Replace this with FreeType's hash functions */
216
217
218 #define INITIAL_HT_SIZE 241
219
220 typedef void
221 (*hash_free_func)( hashnode node );
222
223 static hashnode*
224 hash_bucket( const char* key,
225 hashtable* ht )
226 {
227 const char* kp = key;
228 unsigned long res = 0;
229 hashnode* bp = ht->table, *ndp;
230
231
232 /* Mocklisp hash function. */
233 while ( *kp )
234 res = ( res << 5 ) - res + *kp++;
235
236 ndp = bp + ( res % ht->size );
237 while ( *ndp )
238 {
239 kp = (*ndp)->key;
240 if ( kp[0] == key[0] && ft_strcmp( kp, key ) == 0 )
241 break;
242 ndp--;
243 if ( ndp < bp )
244 ndp = bp + ( ht->size - 1 );
245 }
246
247 return ndp;
248 }
249
250
251 static FT_Error
252 hash_rehash( hashtable* ht,
253 FT_Memory memory )
254 {
255 hashnode* obp = ht->table, *bp, *nbp;
256 int i, sz = ht->size;
257 FT_Error error = BDF_Err_Ok;
258
259
260 ht->size <<= 1;
261 ht->limit = ht->size / 3;
262
263 if ( FT_NEW_ARRAY( ht->table, ht->size ) )
264 goto Exit;
265
266 for ( i = 0, bp = obp; i < sz; i++, bp++ )
267 {
268 if ( *bp )
269 {
270 nbp = hash_bucket( (*bp)->key, ht );
271 *nbp = *bp;
272 }
273 }
274 FT_FREE( obp );
275
276 Exit:
277 return error;
278 }
279
280
281 static FT_Error
282 hash_init( hashtable* ht,
283 FT_Memory memory )
284 {
285 int sz = INITIAL_HT_SIZE;
286 FT_Error error = BDF_Err_Ok;
287
288
289 ht->size = sz;
290 ht->limit = sz / 3;
291 ht->used = 0;
292
293 if ( FT_NEW_ARRAY( ht->table, sz ) )
294 goto Exit;
295
296 Exit:
297 return error;
298 }
299
300
301 static void
302 hash_free( hashtable* ht,
303 FT_Memory memory )
304 {
305 if ( ht != 0 )
306 {
307 int i, sz = ht->size;
308 hashnode* bp = ht->table;
309
310
311 for ( i = 0; i < sz; i++, bp++ )
312 FT_FREE( *bp );
313
314 FT_FREE( ht->table );
315 }
316 }
317
318
319 static FT_Error
320 hash_insert( char* key,
321 size_t data,
322 hashtable* ht,
323 FT_Memory memory )
324 {
325 hashnode nn, *bp = hash_bucket( key, ht );
326 FT_Error error = BDF_Err_Ok;
327
328
329 nn = *bp;
330 if ( !nn )
331 {
332 if ( FT_NEW( nn ) )
333 goto Exit;
334 *bp = nn;
335
336 nn->key = key;
337 nn->data = data;
338
339 if ( ht->used >= ht->limit )
340 {
341 error = hash_rehash( ht, memory );
342 if ( error )
343 goto Exit;
344 }
345 ht->used++;
346 }
347 else
348 nn->data = data;
349
350 Exit:
351 return error;
352 }
353
354
355 static hashnode
356 hash_lookup( const char* key,
357 hashtable* ht )
358 {
359 hashnode *np = hash_bucket( key, ht );
360
361
362 return *np;
363 }
364
365
366 /*************************************************************************/
367 /* */
368 /* Utility types and functions. */
369 /* */
370 /*************************************************************************/
371
372
373 /* Function type for parsing lines of a BDF font. */
374
375 typedef FT_Error
376 (*_bdf_line_func_t)( char* line,
377 unsigned long linelen,
378 unsigned long lineno,
379 void* call_data,
380 void* client_data );
381
382
383 /* List structure for splitting lines into fields. */
384
385 typedef struct _bdf_list_t_
386 {
387 char** field;
388 unsigned long size;
389 unsigned long used;
390 FT_Memory memory;
391
392 } _bdf_list_t;
393
394
395 /* Structure used while loading BDF fonts. */
396
397 typedef struct _bdf_parse_t_
398 {
399 unsigned long flags;
400 unsigned long cnt;
401 unsigned long row;
402
403 short minlb;
404 short maxlb;
405 short maxrb;
406 short maxas;
407 short maxds;
408
409 short rbearing;
410
411 char* glyph_name;
412 long glyph_enc;
413
414 bdf_font_t* font;
415 bdf_options_t* opts;
416
417 unsigned long have[34816]; /* must be in sync with `nmod' and `umod' */
418 /* arrays from `bdf_font_t' structure */
419 _bdf_list_t list;
420
421 FT_Memory memory;
422
423 } _bdf_parse_t;
424
425
426 #define setsbit( m, cc ) \
427 ( m[(FT_Byte)(cc) >> 3] |= (FT_Byte)( 1 << ( (cc) & 7 ) ) )
428 #define sbitset( m, cc ) \
429 ( m[(FT_Byte)(cc) >> 3] & ( 1 << ( (cc) & 7 ) ) )
430
431
432 static void
433 _bdf_list_init( _bdf_list_t* list,
434 FT_Memory memory )
435 {
436 FT_ZERO( list );
437 list->memory = memory;
438 }
439
440
441 static void
442 _bdf_list_done( _bdf_list_t* list )
443 {
444 FT_Memory memory = list->memory;
445
446
447 if ( memory )
448 {
449 FT_FREE( list->field );
450 FT_ZERO( list );
451 }
452 }
453
454
455 static FT_Error
456 _bdf_list_ensure( _bdf_list_t* list,
457 unsigned long num_items ) /* same as _bdf_list_t.used */
458 {
459 FT_Error error = BDF_Err_Ok;
460
461
462 if ( num_items > list->size )
463 {
464 unsigned long oldsize = list->size; /* same as _bdf_list_t.size */
465 unsigned long newsize = oldsize + ( oldsize >> 1 ) + 5;
466 unsigned long bigsize = (unsigned long)( FT_INT_MAX / sizeof ( char* ) );
467 FT_Memory memory = list->memory;
468
469
470 if ( oldsize == bigsize )
471 {
472 error = BDF_Err_Out_Of_Memory;
473 goto Exit;
474 }
475 else if ( newsize < oldsize || newsize > bigsize )
476 newsize = bigsize;
477
478 if ( FT_RENEW_ARRAY( list->field, oldsize, newsize ) )
479 goto Exit;
480
481 list->size = newsize;
482 }
483
484 Exit:
485 return error;
486 }
487
488
489 static void
490 _bdf_list_shift( _bdf_list_t* list,
491 unsigned long n )
492 {
493 unsigned long i, u;
494
495
496 if ( list == 0 || list->used == 0 || n == 0 )
497 return;
498
499 if ( n >= list->used )
500 {
501 list->used = 0;
502 return;
503 }
504
505 for ( u = n, i = 0; u < list->used; i++, u++ )
506 list->field[i] = list->field[u];
507 list->used -= n;
508 }
509
510
511 /* An empty string for empty fields. */
512
513 static const char empty[1] = { 0 }; /* XXX eliminate this */
514
515
516 static char *
517 _bdf_list_join( _bdf_list_t* list,
518 int c,
519 unsigned long *alen )
520 {
521 unsigned long i, j;
522 char *fp, *dp;
523
524
525 *alen = 0;
526
527 if ( list == 0 || list->used == 0 )
528 return 0;
529
530 dp = list->field[0];
531 for ( i = j = 0; i < list->used; i++ )
532 {
533 fp = list->field[i];
534 while ( *fp )
535 dp[j++] = *fp++;
536
537 if ( i + 1 < list->used )
538 dp[j++] = (char)c;
539 }
540 if ( dp != empty )
541 dp[j] = 0;
542
543 *alen = j;
544 return dp;
545 }
546
547
548 /* The code below ensures that we have at least 4 + 1 `field' */
549 /* elements in `list' (which are possibly NULL) so that we */
550 /* don't have to check the number of fields in most cases. */
551
552 static FT_Error
553 _bdf_list_split( _bdf_list_t* list,
554 char* separators,
555 char* line,
556 unsigned long linelen )
557 {
558 int mult, final_empty;
559 char *sp, *ep, *end;
560 char seps[32];
561 FT_Error error = BDF_Err_Ok;
562
563
564 /* Initialize the list. */
565 list->used = 0;
566 if ( list->size )
567 {
568 list->field[0] = (char*)empty;
569 list->field[1] = (char*)empty;
570 list->field[2] = (char*)empty;
571 list->field[3] = (char*)empty;
572 }
573
574 /* If the line is empty, then simply return. */
575 if ( linelen == 0 || line[0] == 0 )
576 goto Exit;
577
578 /* In the original code, if the `separators' parameter is NULL or */
579 /* empty, the list is split into individual bytes. We don't need */
580 /* this, so an error is signaled. */
581 if ( separators == 0 || *separators == 0 )
582 {
583 error = BDF_Err_Invalid_Argument;
584 goto Exit;
585 }
586
587 /* Prepare the separator bitmap. */
588 FT_MEM_ZERO( seps, 32 );
589
590 /* If the very last character of the separator string is a plus, then */
591 /* set the `mult' flag to indicate that multiple separators should be */
592 /* collapsed into one. */
593 for ( mult = 0, sp = separators; sp && *sp; sp++ )
594 {
595 if ( *sp == '+' && *( sp + 1 ) == 0 )
596 mult = 1;
597 else
598 setsbit( seps, *sp );
599 }
600
601 /* Break the line up into fields. */
602 for ( final_empty = 0, sp = ep = line, end = sp + linelen;
603 sp < end && *sp; )
604 {
605 /* Collect everything that is not a separator. */
606 for ( ; *ep && !sbitset( seps, *ep ); ep++ )
607 ;
608
609 /* Resize the list if necessary. */
610 if ( list->used == list->size )
611 {
612 error = _bdf_list_ensure( list, list->used + 1 );
613 if ( error )
614 goto Exit;
615 }
616
617 /* Assign the field appropriately. */
618 list->field[list->used++] = ( ep > sp ) ? sp : (char*)empty;
619
620 sp = ep;
621
622 if ( mult )
623 {
624 /* If multiple separators should be collapsed, do it now by */
625 /* setting all the separator characters to 0. */
626 for ( ; *ep && sbitset( seps, *ep ); ep++ )
627 *ep = 0;
628 }
629 else if ( *ep != 0 )
630 /* Don't collapse multiple separators by making them 0, so just */
631 /* make the one encountered 0. */
632 *ep++ = 0;
633
634 final_empty = ( ep > sp && *ep == 0 );
635 sp = ep;
636 }
637
638 /* Finally, NULL-terminate the list. */
639 if ( list->used + final_empty >= list->size )
640 {
641 error = _bdf_list_ensure( list, list->used + final_empty + 1 );
642 if ( error )
643 goto Exit;
644 }
645
646 if ( final_empty )
647 list->field[list->used++] = (char*)empty;
648
649 list->field[list->used] = 0;
650
651 Exit:
652 return error;
653 }
654
655
656 #define NO_SKIP 256 /* this value cannot be stored in a 'char' */
657
658
659 static FT_Error
660 _bdf_readstream( FT_Stream stream,
661 _bdf_line_func_t callback,
662 void* client_data,
663 unsigned long *lno )
664 {
665 _bdf_line_func_t cb;
666 unsigned long lineno, buf_size;
667 int refill, hold, to_skip;
668 ptrdiff_t bytes, start, end, cursor, avail;
669 char* buf = 0;
670 FT_Memory memory = stream->memory;
671 FT_Error error = BDF_Err_Ok;
672
673
674 if ( callback == 0 )
675 {
676 error = BDF_Err_Invalid_Argument;
677 goto Exit;
678 }
679
680 /* initial size and allocation of the input buffer */
681 buf_size = 1024;
682
683 if ( FT_NEW_ARRAY( buf, buf_size ) )
684 goto Exit;
685
686 cb = callback;
687 lineno = 1;
688 buf[0] = 0;
689 start = 0;
690 end = 0;
691 avail = 0;
692 cursor = 0;
693 refill = 1;
694 to_skip = NO_SKIP;
695 bytes = 0; /* make compiler happy */
696
697 for (;;)
698 {
699 if ( refill )
700 {
701 bytes = (ptrdiff_t)FT_Stream_TryRead(
702 stream, (FT_Byte*)buf + cursor,
703 (FT_ULong)( buf_size - cursor ) );
704 avail = cursor + bytes;
705 cursor = 0;
706 refill = 0;
707 }
708
709 end = start;
710
711 /* should we skip an optional character like \n or \r? */
712 if ( start < avail && buf[start] == to_skip )
713 {
714 start += 1;
715 to_skip = NO_SKIP;
716 continue;
717 }
718
719 /* try to find the end of the line */
720 while ( end < avail && buf[end] != '\n' && buf[end] != '\r' )
721 end++;
722
723 /* if we hit the end of the buffer, try shifting its content */
724 /* or even resizing it */
725 if ( end >= avail )
726 {
727 if ( bytes == 0 ) /* last line in file doesn't end in \r or \n */
728 break; /* ignore it then exit */
729
730 if ( start == 0 )
731 {
732 /* this line is definitely too long; try resizing the input */
733 /* buffer a bit to handle it. */
734 FT_ULong new_size;
735
736
737 if ( buf_size >= 65536UL ) /* limit ourselves to 64KByte */
738 {
739 FT_ERROR(( "_bdf_readstream: " ERRMSG6, lineno ));
740 error = BDF_Err_Invalid_Argument;
741 goto Exit;
742 }
743
744 new_size = buf_size * 2;
745 if ( FT_RENEW_ARRAY( buf, buf_size, new_size ) )
746 goto Exit;
747
748 cursor = buf_size;
749 buf_size = new_size;
750 }
751 else
752 {
753 bytes = avail - start;
754
755 FT_MEM_COPY( buf, buf + start, bytes );
756
757 cursor = bytes;
758 avail -= bytes;
759 start = 0;
760 }
761 refill = 1;
762 continue;
763 }
764
765 /* Temporarily NUL-terminate the line. */
766 hold = buf[end];
767 buf[end] = 0;
768
769 /* XXX: Use encoding independent value for 0x1a */
770 if ( buf[start] != '#' && buf[start] != 0x1a && end > start )
771 {
772 error = (*cb)( buf + start, end - start, lineno,
773 (void*)&cb, client_data );
774 /* Redo if we have encountered CHARS without properties. */
775 if ( error == -1 )
776 error = (*cb)( buf + start, end - start, lineno,
777 (void*)&cb, client_data );
778 if ( error )
779 break;
780 }
781
782 lineno += 1;
783 buf[end] = (char)hold;
784 start = end + 1;
785
786 if ( hold == '\n' )
787 to_skip = '\r';
788 else if ( hold == '\r' )
789 to_skip = '\n';
790 else
791 to_skip = NO_SKIP;
792 }
793
794 *lno = lineno;
795
796 Exit:
797 FT_FREE( buf );
798 return error;
799 }
800
801
802 /* XXX: make this work with EBCDIC also */
803
804 static const unsigned char a2i[128] =
805 {
806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
810 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00,
811 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,
812 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
813 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
815 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
817 };
818
819 static const unsigned char odigits[32] =
820 {
821 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
822 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
823 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
824 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
825 };
826
827 static const unsigned char ddigits[32] =
828 {
829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
833 };
834
835 static const unsigned char hdigits[32] =
836 {
837 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
838 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
839 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
840 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
841 };
842
843
844 #define isdigok( m, d ) (m[(d) >> 3] & ( 1 << ( (d) & 7 ) ) )
845
846
847 /* Routine to convert an ASCII string into an unsigned long integer. */
848 static unsigned long
849 _bdf_atoul( char* s,
850 char** end,
851 int base )
852 {
853 unsigned long v;
854 const unsigned char* dmap;
855
856
857 if ( s == 0 || *s == 0 )
858 return 0;
859
860 /* Make sure the radix is something recognizable. Default to 10. */
861 switch ( base )
862 {
863 case 8:
864 dmap = odigits;
865 break;
866 case 16:
867 dmap = hdigits;
868 break;
869 default:
870 base = 10;
871 dmap = ddigits;
872 break;
873 }
874
875 /* Check for the special hex prefix. */
876 if ( *s == '0' &&
877 ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
878 {
879 base = 16;
880 dmap = hdigits;
881 s += 2;
882 }
883
884 for ( v = 0; isdigok( dmap, *s ); s++ )
885 v = v * base + a2i[(int)*s];
886
887 if ( end != 0 )
888 *end = s;
889
890 return v;
891 }
892
893
894 /* Routine to convert an ASCII string into an signed long integer. */
895 static long
896 _bdf_atol( char* s,
897 char** end,
898 int base )
899 {
900 long v, neg;
901 const unsigned char* dmap;
902
903
904 if ( s == 0 || *s == 0 )
905 return 0;
906
907 /* Make sure the radix is something recognizable. Default to 10. */
908 switch ( base )
909 {
910 case 8:
911 dmap = odigits;
912 break;
913 case 16:
914 dmap = hdigits;
915 break;
916 default:
917 base = 10;
918 dmap = ddigits;
919 break;
920 }
921
922 /* Check for a minus sign. */
923 neg = 0;
924 if ( *s == '-' )
925 {
926 s++;
927 neg = 1;
928 }
929
930 /* Check for the special hex prefix. */
931 if ( *s == '0' &&
932 ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
933 {
934 base = 16;
935 dmap = hdigits;
936 s += 2;
937 }
938
939 for ( v = 0; isdigok( dmap, *s ); s++ )
940 v = v * base + a2i[(int)*s];
941
942 if ( end != 0 )
943 *end = s;
944
945 return ( !neg ) ? v : -v;
946 }
947
948
949 /* Routine to convert an ASCII string into an signed short integer. */
950 static short
951 _bdf_atos( char* s,
952 char** end,
953 int base )
954 {
955 short v, neg;
956 const unsigned char* dmap;
957
958
959 if ( s == 0 || *s == 0 )
960 return 0;
961
962 /* Make sure the radix is something recognizable. Default to 10. */
963 switch ( base )
964 {
965 case 8:
966 dmap = odigits;
967 break;
968 case 16:
969 dmap = hdigits;
970 break;
971 default:
972 base = 10;
973 dmap = ddigits;
974 break;
975 }
976
977 /* Check for a minus. */
978 neg = 0;
979 if ( *s == '-' )
980 {
981 s++;
982 neg = 1;
983 }
984
985 /* Check for the special hex prefix. */
986 if ( *s == '0' &&
987 ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
988 {
989 base = 16;
990 dmap = hdigits;
991 s += 2;
992 }
993
994 for ( v = 0; isdigok( dmap, *s ); s++ )
995 v = (short)( v * base + a2i[(int)*s] );
996
997 if ( end != 0 )
998 *end = s;
999
1000 return (short)( ( !neg ) ? v : -v );
1001 }
1002
1003
1004 /* Routine to compare two glyphs by encoding so they can be sorted. */
1005 static int
1006 by_encoding( const void* a,
1007 const void* b )
1008 {
1009 bdf_glyph_t *c1, *c2;
1010
1011
1012 c1 = (bdf_glyph_t *)a;
1013 c2 = (bdf_glyph_t *)b;
1014
1015 if ( c1->encoding < c2->encoding )
1016 return -1;
1017
1018 if ( c1->encoding > c2->encoding )
1019 return 1;
1020
1021 return 0;
1022 }
1023
1024
1025 static FT_Error
1026 bdf_create_property( char* name,
1027 int format,
1028 bdf_font_t* font )
1029 {
1030 size_t n;
1031 bdf_property_t* p;
1032 FT_Memory memory = font->memory;
1033 FT_Error error = BDF_Err_Ok;
1034
1035
1036 /* First check whether the property has */
1037 /* already been added or not. If it has, then */
1038 /* simply ignore it. */
1039 if ( hash_lookup( name, &(font->proptbl) ) )
1040 goto Exit;
1041
1042 if ( FT_RENEW_ARRAY( font->user_props,
1043 font->nuser_props,
1044 font->nuser_props + 1 ) )
1045 goto Exit;
1046
1047 p = font->user_props + font->nuser_props;
1048 FT_ZERO( p );
1049
1050 n = ft_strlen( name ) + 1;
1051 if ( n > FT_ULONG_MAX )
1052 return BDF_Err_Invalid_Argument;
1053
1054 if ( FT_NEW_ARRAY( p->name, n ) )
1055 goto Exit;
1056
1057 FT_MEM_COPY( (char *)p->name, name, n );
1058
1059 p->format = format;
1060 p->builtin = 0;
1061
1062 n = _num_bdf_properties + font->nuser_props;
1063
1064 error = hash_insert( p->name, n, &(font->proptbl), memory );
1065 if ( error )
1066 goto Exit;
1067
1068 font->nuser_props++;
1069
1070 Exit:
1071 return error;
1072 }
1073
1074
1075 FT_LOCAL_DEF( bdf_property_t * )
1076 bdf_get_property( char* name,
1077 bdf_font_t* font )
1078 {
1079 hashnode hn;
1080 size_t propid;
1081
1082
1083 if ( name == 0 || *name == 0 )
1084 return 0;
1085
1086 if ( ( hn = hash_lookup( name, &(font->proptbl) ) ) == 0 )
1087 return 0;
1088
1089 propid = hn->data;
1090 if ( propid >= _num_bdf_properties )
1091 return font->user_props + ( propid - _num_bdf_properties );
1092
1093 return (bdf_property_t*)_bdf_properties + propid;
1094 }
1095
1096
1097 /*************************************************************************/
1098 /* */
1099 /* BDF font file parsing flags and functions. */
1100 /* */
1101 /*************************************************************************/
1102
1103
1104 /* Parse flags. */
1105
1106 #define _BDF_START 0x0001
1107 #define _BDF_FONT_NAME 0x0002
1108 #define _BDF_SIZE 0x0004
1109 #define _BDF_FONT_BBX 0x0008
1110 #define _BDF_PROPS 0x0010
1111 #define _BDF_GLYPHS 0x0020
1112 #define _BDF_GLYPH 0x0040
1113 #define _BDF_ENCODING 0x0080
1114 #define _BDF_SWIDTH 0x0100
1115 #define _BDF_DWIDTH 0x0200
1116 #define _BDF_BBX 0x0400
1117 #define _BDF_BITMAP 0x0800
1118
1119 #define _BDF_SWIDTH_ADJ 0x1000
1120
1121 #define _BDF_GLYPH_BITS ( _BDF_GLYPH | \
1122 _BDF_ENCODING | \
1123 _BDF_SWIDTH | \
1124 _BDF_DWIDTH | \
1125 _BDF_BBX | \
1126 _BDF_BITMAP )
1127
1128 #define _BDF_GLYPH_WIDTH_CHECK 0x40000000UL
1129 #define _BDF_GLYPH_HEIGHT_CHECK 0x80000000UL
1130
1131
1132 static FT_Error
1133 _bdf_add_comment( bdf_font_t* font,
1134 char* comment,
1135 unsigned long len )
1136 {
1137 char* cp;
1138 FT_Memory memory = font->memory;
1139 FT_Error error = BDF_Err_Ok;
1140
1141
1142 if ( FT_RENEW_ARRAY( font->comments,
1143 font->comments_len,
1144 font->comments_len + len + 1 ) )
1145 goto Exit;
1146
1147 cp = font->comments + font->comments_len;
1148
1149 FT_MEM_COPY( cp, comment, len );
1150 cp[len] = '\n';
1151
1152 font->comments_len += len + 1;
1153
1154 Exit:
1155 return error;
1156 }
1157
1158
1159 /* Set the spacing from the font name if it exists, or set it to the */
1160 /* default specified in the options. */
1161 static FT_Error
1162 _bdf_set_default_spacing( bdf_font_t* font,
1163 bdf_options_t* opts,
1164 unsigned long lineno )
1165 {
1166 size_t len;
1167 char name[256];
1168 _bdf_list_t list;
1169 FT_Memory memory;
1170 FT_Error error = BDF_Err_Ok;
1171
1172
1173 if ( font == 0 || font->name == 0 || font->name[0] == 0 )
1174 {
1175 error = BDF_Err_Invalid_Argument;
1176 goto Exit;
1177 }
1178
1179 memory = font->memory;
1180
1181 _bdf_list_init( &list, memory );
1182
1183 font->spacing = opts->font_spacing;
1184
1185 len = ft_strlen( font->name ) + 1;
1186 /* Limit ourselves to 256 characters in the font name. */
1187 if ( len >= 256 )
1188 {
1189 FT_ERROR(( "_bdf_set_default_spacing: " ERRMSG7, lineno ));
1190 error = BDF_Err_Invalid_Argument;
1191 goto Exit;
1192 }
1193
1194 FT_MEM_COPY( name, font->name, len );
1195
1196 error = _bdf_list_split( &list, (char *)"-", name, len );
1197 if ( error )
1198 goto Fail;
1199
1200 if ( list.used == 15 )
1201 {
1202 switch ( list.field[11][0] )
1203 {
1204 case 'C':
1205 case 'c':
1206 font->spacing = BDF_CHARCELL;
1207 break;
1208 case 'M':
1209 case 'm':
1210 font->spacing = BDF_MONOWIDTH;
1211 break;
1212 case 'P':
1213 case 'p':
1214 font->spacing = BDF_PROPORTIONAL;
1215 break;
1216 }
1217 }
1218
1219 Fail:
1220 _bdf_list_done( &list );
1221
1222 Exit:
1223 return error;
1224 }
1225
1226
1227 /* Determine whether the property is an atom or not. If it is, then */
1228 /* clean it up so the double quotes are removed if they exist. */
1229 static int
1230 _bdf_is_atom( char* line,
1231 unsigned long linelen,
1232 char** name,
1233 char** value,
1234 bdf_font_t* font )
1235 {
1236 int hold;
1237 char *sp, *ep;
1238 bdf_property_t* p;
1239
1240
1241 *name = sp = ep = line;
1242
1243 while ( *ep && *ep != ' ' && *ep != '\t' )
1244 ep++;
1245
1246 hold = -1;
1247 if ( *ep )
1248 {
1249 hold = *ep;
1250 *ep = 0;
1251 }
1252
1253 p = bdf_get_property( sp, font );
1254
1255 /* Restore the character that was saved before any return can happen. */
1256 if ( hold != -1 )
1257 *ep = (char)hold;
1258
1259 /* If the property exists and is not an atom, just return here. */
1260 if ( p && p->format != BDF_ATOM )
1261 return 0;
1262
1263 /* The property is an atom. Trim all leading and trailing whitespace */
1264 /* and double quotes for the atom value. */
1265 sp = ep;
1266 ep = line + linelen;
1267
1268 /* Trim the leading whitespace if it exists. */
1269 if ( *sp )
1270 *sp++ = 0;
1271 while ( *sp &&
1272 ( *sp == ' ' || *sp == '\t' ) )
1273 sp++;
1274
1275 /* Trim the leading double quote if it exists. */
1276 if ( *sp == '"' )
1277 sp++;
1278 *value = sp;
1279
1280 /* Trim the trailing whitespace if it exists. */
1281 while ( ep > sp &&
1282 ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) )
1283 *--ep = 0;
1284
1285 /* Trim the trailing double quote if it exists. */
1286 if ( ep > sp && *( ep - 1 ) == '"' )
1287 *--ep = 0;
1288
1289 return 1;
1290 }
1291
1292
1293 static FT_Error
1294 _bdf_add_property( bdf_font_t* font,
1295 char* name,
1296 char* value,
1297 unsigned long lineno )
1298 {
1299 size_t propid;
1300 hashnode hn;
1301 bdf_property_t *prop, *fp;
1302 FT_Memory memory = font->memory;
1303 FT_Error error = BDF_Err_Ok;
1304
1305
1306 /* First, check whether the property already exists in the font. */
1307 if ( ( hn = hash_lookup( name, (hashtable *)font->internal ) ) != 0 )
1308 {
1309 /* The property already exists in the font, so simply replace */
1310 /* the value of the property with the current value. */
1311 fp = font->props + hn->data;
1312
1313 switch ( fp->format )
1314 {
1315 case BDF_ATOM:
1316 /* Delete the current atom if it exists. */
1317 FT_FREE( fp->value.atom );
1318
1319 if ( value && value[0] != 0 )
1320 {
1321 if ( FT_STRDUP( fp->value.atom, value ) )
1322 goto Exit;
1323 }
1324 break;
1325
1326 case BDF_INTEGER:
1327 fp->value.l = _bdf_atol( value, 0, 10 );
1328 break;
1329
1330 case BDF_CARDINAL:
1331 fp->value.ul = _bdf_atoul( value, 0, 10 );
1332 break;
1333
1334 default:
1335 ;
1336 }
1337
1338 goto Exit;
1339 }
1340
1341 /* See whether this property type exists yet or not. */
1342 /* If not, create it. */
1343 hn = hash_lookup( name, &(font->proptbl) );
1344 if ( hn == 0 )
1345 {
1346 error = bdf_create_property( name, BDF_ATOM, font );
1347 if ( error )
1348 goto Exit;
1349 hn = hash_lookup( name, &(font->proptbl) );
1350 }
1351
1352 /* Allocate another property if this is overflow. */
1353 if ( font->props_used == font->props_size )
1354 {
1355 if ( font->props_size == 0 )
1356 {
1357 if ( FT_NEW_ARRAY( font->props, 1 ) )
1358 goto Exit;
1359 }
1360 else
1361 {
1362 if ( FT_RENEW_ARRAY( font->props,
1363 font->props_size,
1364 font->props_size + 1 ) )
1365 goto Exit;
1366 }
1367
1368 fp = font->props + font->props_size;
1369 FT_MEM_ZERO( fp, sizeof ( bdf_property_t ) );
1370 font->props_size++;
1371 }
1372
1373 propid = hn->data;
1374 if ( propid >= _num_bdf_properties )
1375 prop = font->user_props + ( propid - _num_bdf_properties );
1376 else
1377 prop = (bdf_property_t*)_bdf_properties + propid;
1378
1379 fp = font->props + font->props_used;
1380
1381 fp->name = prop->name;
1382 fp->format = prop->format;
1383 fp->builtin = prop->builtin;
1384
1385 switch ( prop->format )
1386 {
1387 case BDF_ATOM:
1388 fp->value.atom = 0;
1389 if ( value != 0 && value[0] )
1390 {
1391 if ( FT_STRDUP( fp->value.atom, value ) )
1392 goto Exit;
1393 }
1394 break;
1395
1396 case BDF_INTEGER:
1397 fp->value.l = _bdf_atol( value, 0, 10 );
1398 break;
1399
1400 case BDF_CARDINAL:
1401 fp->value.ul = _bdf_atoul( value, 0, 10 );
1402 break;
1403 }
1404
1405 /* If the property happens to be a comment, then it doesn't need */
1406 /* to be added to the internal hash table. */
1407 if ( ft_memcmp( name, "COMMENT", 7 ) != 0 )
1408 {
1409 /* Add the property to the font property table. */
1410 error = hash_insert( fp->name,
1411 font->props_used,
1412 (hashtable *)font->internal,
1413 memory );
1414 if ( error )
1415 goto Exit;
1416 }
1417
1418 font->props_used++;
1419
1420 /* Some special cases need to be handled here. The DEFAULT_CHAR */
1421 /* property needs to be located if it exists in the property list, the */
1422 /* FONT_ASCENT and FONT_DESCENT need to be assigned if they are */
1423 /* present, and the SPACING property should override the default */
1424 /* spacing. */
1425 if ( ft_memcmp( name, "DEFAULT_CHAR", 12 ) == 0 )
1426 font->default_char = fp->value.l;
1427 else if ( ft_memcmp( name, "FONT_ASCENT", 11 ) == 0 )
1428 font->font_ascent = fp->value.l;
1429 else if ( ft_memcmp( name, "FONT_DESCENT", 12 ) == 0 )
1430 font->font_descent = fp->value.l;
1431 else if ( ft_memcmp( name, "SPACING", 7 ) == 0 )
1432 {
1433 if ( !fp->value.atom )
1434 {
1435 FT_ERROR(( "_bdf_add_property: " ERRMSG8, lineno, "SPACING" ));
1436 error = BDF_Err_Invalid_File_Format;
1437 goto Exit;
1438 }
1439
1440 if ( fp->value.atom[0] == 'p' || fp->value.atom[0] == 'P' )
1441 font->spacing = BDF_PROPORTIONAL;
1442 else if ( fp->value.atom[0] == 'm' || fp->value.atom[0] == 'M' )
1443 font->spacing = BDF_MONOWIDTH;
1444 else if ( fp->value.atom[0] == 'c' || fp->value.atom[0] == 'C' )
1445 font->spacing = BDF_CHARCELL;
1446 }
1447
1448 Exit:
1449 return error;
1450 }
1451
1452
1453 static const unsigned char nibble_mask[8] =
1454 {
1455 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE
1456 };
1457
1458
1459 /* Actually parse the glyph info and bitmaps. */
1460 static FT_Error
1461 _bdf_parse_glyphs( char* line,
1462 unsigned long linelen,
1463 unsigned long lineno,
1464 void* call_data,
1465 void* client_data )
1466 {
1467 int c, mask_index;
1468 char* s;
1469 unsigned char* bp;
1470 unsigned long i, slen, nibbles;
1471
1472 _bdf_parse_t* p;
1473 bdf_glyph_t* glyph;
1474 bdf_font_t* font;
1475
1476 FT_Memory memory;
1477 FT_Error error = BDF_Err_Ok;
1478
1479 FT_UNUSED( call_data );
1480 FT_UNUSED( lineno ); /* only used in debug mode */
1481
1482
1483 p = (_bdf_parse_t *)client_data;
1484
1485 font = p->font;
1486 memory = font->memory;
1487
1488 /* Check for a comment. */
1489 if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
1490 {
1491 linelen -= 7;
1492
1493 s = line + 7;
1494 if ( *s != 0 )
1495 {
1496 s++;
1497 linelen--;
1498 }
1499 error = _bdf_add_comment( p->font, s, linelen );
1500 goto Exit;
1501 }
1502
1503 /* The very first thing expected is the number of glyphs. */
1504 if ( !( p->flags & _BDF_GLYPHS ) )
1505 {
1506 if ( ft_memcmp( line, "CHARS", 5 ) != 0 )
1507 {
1508 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "CHARS" ));
1509 error = BDF_Err_Missing_Chars_Field;
1510 goto Exit;
1511 }
1512
1513 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
1514 if ( error )
1515 goto Exit;
1516 p->cnt = font->glyphs_size = _bdf_atoul( p->list.field[1], 0, 10 );
1517
1518 /* Make sure the number of glyphs is non-zero. */
1519 if ( p->cnt == 0 )
1520 font->glyphs_size = 64;
1521
1522 /* Limit ourselves to 1,114,112 glyphs in the font (this is the */
1523 /* number of code points available in Unicode). */
1524 if ( p->cnt >= 0x110000UL )
1525 {
1526 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG5, lineno, "CHARS" ));
1527 error = BDF_Err_Invalid_Argument;
1528 goto Exit;
1529 }
1530
1531 if ( FT_NEW_ARRAY( font->glyphs, font->glyphs_size ) )
1532 goto Exit;
1533
1534 p->flags |= _BDF_GLYPHS;
1535
1536 goto Exit;
1537 }
1538
1539 /* Check for the ENDFONT field. */
1540 if ( ft_memcmp( line, "ENDFONT", 7 ) == 0 )
1541 {
1542 /* Sort the glyphs by encoding. */
1543 ft_qsort( (char *)font->glyphs,
1544 font->glyphs_used,
1545 sizeof ( bdf_glyph_t ),
1546 by_encoding );
1547
1548 p->flags &= ~_BDF_START;
1549
1550 goto Exit;
1551 }
1552
1553 /* Check for the ENDCHAR field. */
1554 if ( ft_memcmp( line, "ENDCHAR", 7 ) == 0 )
1555 {
1556 p->glyph_enc = 0;
1557 p->flags &= ~_BDF_GLYPH_BITS;
1558
1559 goto Exit;
1560 }
1561
1562 /* Check whether a glyph is being scanned but should be */
1563 /* ignored because it is an unencoded glyph. */
1564 if ( ( p->flags & _BDF_GLYPH ) &&
1565 p->glyph_enc == -1 &&
1566 p->opts->keep_unencoded == 0 )
1567 goto Exit;
1568
1569 /* Check for the STARTCHAR field. */
1570 if ( ft_memcmp( line, "STARTCHAR", 9 ) == 0 )
1571 {
1572 /* Set the character name in the parse info first until the */
1573 /* encoding can be checked for an unencoded character. */
1574 FT_FREE( p->glyph_name );
1575
1576 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
1577 if ( error )
1578 goto Exit;
1579
1580 _bdf_list_shift( &p->list, 1 );
1581
1582 s = _bdf_list_join( &p->list, ' ', &slen );
1583
1584 if ( !s )
1585 {
1586 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG8, lineno, "STARTCHAR" ));
1587 error = BDF_Err_Invalid_File_Format;
1588 goto Exit;
1589 }
1590
1591 if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) )
1592 goto Exit;
1593
1594 FT_MEM_COPY( p->glyph_name, s, slen + 1 );
1595
1596 p->flags |= _BDF_GLYPH;
1597
1598 FT_TRACE4(( DBGMSG1, lineno, s ));
1599
1600 goto Exit;
1601 }
1602
1603 /* Check for the ENCODING field. */
1604 if ( ft_memcmp( line, "ENCODING", 8 ) == 0 )
1605 {
1606 if ( !( p->flags & _BDF_GLYPH ) )
1607 {
1608 /* Missing STARTCHAR field. */
1609 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "STARTCHAR" ));
1610 error = BDF_Err_Missing_Startchar_Field;
1611 goto Exit;
1612 }
1613
1614 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
1615 if ( error )
1616 goto Exit;
1617
1618 p->glyph_enc = _bdf_atol( p->list.field[1], 0, 10 );
1619
1620 /* Normalize negative encoding values. The specification only */
1621 /* allows -1, but we can be more generous here. */
1622 if ( p->glyph_enc < -1 )
1623 p->glyph_enc = -1;
1624
1625 /* Check for alternative encoding format. */
1626 if ( p->glyph_enc == -1 && p->list.used > 2 )
1627 p->glyph_enc = _bdf_atol( p->list.field[2], 0, 10 );
1628
1629 FT_TRACE4(( DBGMSG2, p->glyph_enc ));
1630
1631 /* Check that the encoding is in the Unicode range because */
1632 /* otherwise p->have (a bitmap with static size) overflows. */
1633 if ( p->glyph_enc > 0 &&
1634 (size_t)p->glyph_enc >= sizeof ( p->have ) * 8 )
1635 {
1636 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG5, lineno, "ENCODING" ));
1637 error = BDF_Err_Invalid_File_Format;
1638 goto Exit;
1639 }
1640
1641 /* Check whether this encoding has already been encountered. */
1642 /* If it has then change it to unencoded so it gets added if */
1643 /* indicated. */
1644 if ( p->glyph_enc >= 0 )
1645 {
1646 if ( _bdf_glyph_modified( p->have, p->glyph_enc ) )
1647 {
1648 /* Emit a message saying a glyph has been moved to the */
1649 /* unencoded area. */
1650 FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG12,
1651 p->glyph_enc, p->glyph_name ));
1652 p->glyph_enc = -1;
1653 font->modified = 1;
1654 }
1655 else
1656 _bdf_set_glyph_modified( p->have, p->glyph_enc );
1657 }
1658
1659 if ( p->glyph_enc >= 0 )
1660 {
1661 /* Make sure there are enough glyphs allocated in case the */
1662 /* number of characters happen to be wrong. */
1663 if ( font->glyphs_used == font->glyphs_size )
1664 {
1665 if ( FT_RENEW_ARRAY( font->glyphs,
1666 font->glyphs_size,
1667 font->glyphs_size + 64 ) )
1668 goto Exit;
1669
1670 font->glyphs_size += 64;
1671 }
1672
1673 glyph = font->glyphs + font->glyphs_used++;
1674 glyph->name = p->glyph_name;
1675 glyph->encoding = p->glyph_enc;
1676
1677 /* Reset the initial glyph info. */
1678 p->glyph_name = 0;
1679 }
1680 else
1681 {
1682 /* Unencoded glyph. Check whether it should */
1683 /* be added or not. */
1684 if ( p->opts->keep_unencoded != 0 )
1685 {
1686 /* Allocate the next unencoded glyph. */
1687 if ( font->unencoded_used == font->unencoded_size )
1688 {
1689 if ( FT_RENEW_ARRAY( font->unencoded ,
1690 font->unencoded_size,
1691 font->unencoded_size + 4 ) )
1692 goto Exit;
1693
1694 font->unencoded_size += 4;
1695 }
1696
1697 glyph = font->unencoded + font->unencoded_used;
1698 glyph->name = p->glyph_name;
1699 glyph->encoding = font->unencoded_used++;
1700 }
1701 else
1702 /* Free up the glyph name if the unencoded shouldn't be */
1703 /* kept. */
1704 FT_FREE( p->glyph_name );
1705
1706 p->glyph_name = 0;
1707 }
1708
1709 /* Clear the flags that might be added when width and height are */
1710 /* checked for consistency. */
1711 p->flags &= ~( _BDF_GLYPH_WIDTH_CHECK | _BDF_GLYPH_HEIGHT_CHECK );
1712
1713 p->flags |= _BDF_ENCODING;
1714
1715 goto Exit;
1716 }
1717
1718 /* Point at the glyph being constructed. */
1719 if ( p->glyph_enc == -1 )
1720 glyph = font->unencoded + ( font->unencoded_used - 1 );
1721 else
1722 glyph = font->glyphs + ( font->glyphs_used - 1 );
1723
1724 /* Check whether a bitmap is being constructed. */
1725 if ( p->flags & _BDF_BITMAP )
1726 {
1727 /* If there are more rows than are specified in the glyph metrics, */
1728 /* ignore the remaining lines. */
1729 if ( p->row >= (unsigned long)glyph->bbx.height )
1730 {
1731 if ( !( p->flags & _BDF_GLYPH_HEIGHT_CHECK ) )
1732 {
1733 FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG13, glyph->encoding ));
1734 p->flags |= _BDF_GLYPH_HEIGHT_CHECK;
1735 font->modified = 1;
1736 }
1737
1738 goto Exit;
1739 }
1740
1741 /* Only collect the number of nibbles indicated by the glyph */
1742 /* metrics. If there are more columns, they are simply ignored. */
1743 nibbles = glyph->bpr << 1;
1744 bp = glyph->bitmap + p->row * glyph->bpr;
1745
1746 for ( i = 0; i < nibbles; i++ )
1747 {
1748 c = line[i];
1749 if ( !isdigok( hdigits, c ) )
1750 break;
1751 *bp = (FT_Byte)( ( *bp << 4 ) + a2i[c] );
1752 if ( i + 1 < nibbles && ( i & 1 ) )
1753 *++bp = 0;
1754 }
1755
1756 /* If any line has not enough columns, */
1757 /* indicate they have been padded with zero bits. */
1758 if ( i < nibbles &&
1759 !( p->flags & _BDF_GLYPH_WIDTH_CHECK ) )
1760 {
1761 FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG16, glyph->encoding ));
1762 p->flags |= _BDF_GLYPH_WIDTH_CHECK;
1763 font->modified = 1;
1764 }
1765
1766 /* Remove possible garbage at the right. */
1767 mask_index = ( glyph->bbx.width * p->font->bpp ) & 7;
1768 if ( glyph->bbx.width )
1769 *bp &= nibble_mask[mask_index];
1770
1771 /* If any line has extra columns, indicate they have been removed. */
1772 if ( i == nibbles &&
1773 isdigok( hdigits, line[nibbles] ) &&
1774 !( p->flags & _BDF_GLYPH_WIDTH_CHECK ) )
1775 {
1776 FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG14, glyph->encoding ));
1777 p->flags |= _BDF_GLYPH_WIDTH_CHECK;
1778 font->modified = 1;
1779 }
1780
1781 p->row++;
1782 goto Exit;
1783 }
1784
1785 /* Expect the SWIDTH (scalable width) field next. */
1786 if ( ft_memcmp( line, "SWIDTH", 6 ) == 0 )
1787 {
1788 if ( !( p->flags & _BDF_ENCODING ) )
1789 goto Missing_Encoding;
1790
1791 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
1792 if ( error )
1793 goto Exit;
1794
1795 glyph->swidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
1796 p->flags |= _BDF_SWIDTH;
1797
1798 goto Exit;
1799 }
1800
1801 /* Expect the DWIDTH (scalable width) field next. */
1802 if ( ft_memcmp( line, "DWIDTH", 6 ) == 0 )
1803 {
1804 if ( !( p->flags & _BDF_ENCODING ) )
1805 goto Missing_Encoding;
1806
1807 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
1808 if ( error )
1809 goto Exit;
1810
1811 glyph->dwidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
1812
1813 if ( !( p->flags & _BDF_SWIDTH ) )
1814 {
1815 /* Missing SWIDTH field. Emit an auto correction message and set */
1816 /* the scalable width from the device width. */
1817 FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG9, lineno ));
1818
1819 glyph->swidth = (unsigned short)FT_MulDiv(
1820 glyph->dwidth, 72000L,
1821 (FT_Long)( font->point_size *
1822 font->resolution_x ) );
1823 }
1824
1825 p->flags |= _BDF_DWIDTH;
1826 goto Exit;
1827 }
1828
1829 /* Expect the BBX field next. */
1830 if ( ft_memcmp( line, "BBX", 3 ) == 0 )
1831 {
1832 if ( !( p->flags & _BDF_ENCODING ) )
1833 goto Missing_Encoding;
1834
1835 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
1836 if ( error )
1837 goto Exit;
1838
1839 glyph->bbx.width = _bdf_atos( p->list.field[1], 0, 10 );
1840 glyph->bbx.height = _bdf_atos( p->list.field[2], 0, 10 );
1841 glyph->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );
1842 glyph->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );
1843
1844 /* Generate the ascent and descent of the character. */
1845 glyph->bbx.ascent = (short)( glyph->bbx.height + glyph->bbx.y_offset );
1846 glyph->bbx.descent = (short)( -glyph->bbx.y_offset );
1847
1848 /* Determine the overall font bounding box as the characters are */
1849 /* loaded so corrections can be done later if indicated. */
1850 p->maxas = (short)FT_MAX( glyph->bbx.ascent, p->maxas );
1851 p->maxds = (short)FT_MAX( glyph->bbx.descent, p->maxds );
1852
1853 p->rbearing = (short)( glyph->bbx.width + glyph->bbx.x_offset );
1854
1855 p->maxrb = (short)FT_MAX( p->rbearing, p->maxrb );
1856 p->minlb = (short)FT_MIN( glyph->bbx.x_offset, p->minlb );
1857 p->maxlb = (short)FT_MAX( glyph->bbx.x_offset, p->maxlb );
1858
1859 if ( !( p->flags & _BDF_DWIDTH ) )
1860 {
1861 /* Missing DWIDTH field. Emit an auto correction message and set */
1862 /* the device width to the glyph width. */
1863 FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG10, lineno ));
1864 glyph->dwidth = glyph->bbx.width;
1865 }
1866
1867 /* If the BDF_CORRECT_METRICS flag is set, then adjust the SWIDTH */
1868 /* value if necessary. */
1869 if ( p->opts->correct_metrics != 0 )
1870 {
1871 /* Determine the point size of the glyph. */
1872 unsigned short sw = (unsigned short)FT_MulDiv(
1873 glyph->dwidth, 72000L,
1874 (FT_Long)( font->point_size *
1875 font->resolution_x ) );
1876
1877
1878 if ( sw != glyph->swidth )
1879 {
1880 glyph->swidth = sw;
1881
1882 if ( p->glyph_enc == -1 )
1883 _bdf_set_glyph_modified( font->umod,
1884 font->unencoded_used - 1 );
1885 else
1886 _bdf_set_glyph_modified( font->nmod, glyph->encoding );
1887
1888 p->flags |= _BDF_SWIDTH_ADJ;
1889 font->modified = 1;
1890 }
1891 }
1892
1893 p->flags |= _BDF_BBX;
1894 goto Exit;
1895 }
1896
1897 /* And finally, gather up the bitmap. */
1898 if ( ft_memcmp( line, "BITMAP", 6 ) == 0 )
1899 {
1900 unsigned long bitmap_size;
1901
1902
1903 if ( !( p->flags & _BDF_BBX ) )
1904 {
1905 /* Missing BBX field. */
1906 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "BBX" ));
1907 error = BDF_Err_Missing_Bbx_Field;
1908 goto Exit;
1909 }
1910
1911 /* Allocate enough space for the bitmap. */
1912 glyph->bpr = ( glyph->bbx.width * p->font->bpp + 7 ) >> 3;
1913
1914 bitmap_size = glyph->bpr * glyph->bbx.height;
1915 if ( glyph->bpr > 0xFFFFU || bitmap_size > 0xFFFFU )
1916 {
1917 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG4, lineno ));
1918 error = BDF_Err_Bbx_Too_Big;
1919 goto Exit;
1920 }
1921 else
1922 glyph->bytes = (unsigned short)bitmap_size;
1923
1924 if ( FT_NEW_ARRAY( glyph->bitmap, glyph->bytes ) )
1925 goto Exit;
1926
1927 p->row = 0;
1928 p->flags |= _BDF_BITMAP;
1929
1930 goto Exit;
1931 }
1932
1933 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG9, lineno ));
1934 error = BDF_Err_Invalid_File_Format;
1935 goto Exit;
1936
1937 Missing_Encoding:
1938 /* Missing ENCODING field. */
1939 FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENCODING" ));
1940 error = BDF_Err_Missing_Encoding_Field;
1941
1942 Exit:
1943 if ( error && ( p->flags & _BDF_GLYPH ) )
1944 FT_FREE( p->glyph_name );
1945
1946 return error;
1947 }
1948
1949
1950 /* Load the font properties. */
1951 static FT_Error
1952 _bdf_parse_properties( char* line,
1953 unsigned long linelen,
1954 unsigned long lineno,
1955 void* call_data,
1956 void* client_data )
1957 {
1958 unsigned long vlen;
1959 _bdf_line_func_t* next;
1960 _bdf_parse_t* p;
1961 char* name;
1962 char* value;
1963 char nbuf[128];
1964 FT_Error error = BDF_Err_Ok;
1965
1966 FT_UNUSED( lineno );
1967
1968
1969 next = (_bdf_line_func_t *)call_data;
1970 p = (_bdf_parse_t *) client_data;
1971
1972 /* Check for the end of the properties. */
1973 if ( ft_memcmp( line, "ENDPROPERTIES", 13 ) == 0 )
1974 {
1975 /* If the FONT_ASCENT or FONT_DESCENT properties have not been */
1976 /* encountered yet, then make sure they are added as properties and */
1977 /* make sure they are set from the font bounding box info. */
1978 /* */
1979 /* This is *always* done regardless of the options, because X11 */
1980 /* requires these two fields to compile fonts. */
1981 if ( bdf_get_font_property( p->font, "FONT_ASCENT" ) == 0 )
1982 {
1983 p->font->font_ascent = p->font->bbx.ascent;
1984 ft_sprintf( nbuf, "%hd", p->font->bbx.ascent );
1985 error = _bdf_add_property( p->font, (char *)"FONT_ASCENT",
1986 nbuf, lineno );
1987 if ( error )
1988 goto Exit;
1989
1990 FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent ));
1991 p->font->modified = 1;
1992 }
1993
1994 if ( bdf_get_font_property( p->font, "FONT_DESCENT" ) == 0 )
1995 {
1996 p->font->font_descent = p->font->bbx.descent;
1997 ft_sprintf( nbuf, "%hd", p->font->bbx.descent );
1998 error = _bdf_add_property( p->font, (char *)"FONT_DESCENT",
1999 nbuf, lineno );
2000 if ( error )
2001 goto Exit;
2002
2003 FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent ));
2004 p->font->modified = 1;
2005 }
2006
2007 p->flags &= ~_BDF_PROPS;
2008 *next = _bdf_parse_glyphs;
2009
2010 goto Exit;
2011 }
2012
2013 /* Ignore the _XFREE86_GLYPH_RANGES properties. */
2014 if ( ft_memcmp( line, "_XFREE86_GLYPH_RANGES", 21 ) == 0 )
2015 goto Exit;
2016
2017 /* Handle COMMENT fields and properties in a special way to preserve */
2018 /* the spacing. */
2019 if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
2020 {
2021 name = value = line;
2022 value += 7;
2023 if ( *value )
2024 *value++ = 0;
2025 error = _bdf_add_property( p->font, name, value, lineno );
2026 if ( error )
2027 goto Exit;
2028 }
2029 else if ( _bdf_is_atom( line, linelen, &name, &value, p->font ) )
2030 {
2031 error = _bdf_add_property( p->font, name, value, lineno );
2032 if ( error )
2033 goto Exit;
2034 }
2035 else
2036 {
2037 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
2038 if ( error )
2039 goto Exit;
2040 name = p->list.field[0];
2041
2042 _bdf_list_shift( &p->list, 1 );
2043 value = _bdf_list_join( &p->list, ' ', &vlen );
2044
2045 error = _bdf_add_property( p->font, name, value, lineno );
2046 if ( error )
2047 goto Exit;
2048 }
2049
2050 Exit:
2051 return error;
2052 }
2053
2054
2055 /* Load the font header. */
2056 static FT_Error
2057 _bdf_parse_start( char* line,
2058 unsigned long linelen,
2059 unsigned long lineno,
2060 void* call_data,
2061 void* client_data )
2062 {
2063 unsigned long slen;
2064 _bdf_line_func_t* next;
2065 _bdf_parse_t* p;
2066 bdf_font_t* font;
2067 char *s;
2068
2069 FT_Memory memory = NULL;
2070 FT_Error error = BDF_Err_Ok;
2071
2072 FT_UNUSED( lineno ); /* only used in debug mode */
2073
2074
2075 next = (_bdf_line_func_t *)call_data;
2076 p = (_bdf_parse_t *) client_data;
2077
2078 if ( p->font )
2079 memory = p->font->memory;
2080
2081 /* Check for a comment. This is done to handle those fonts that have */
2082 /* comments before the STARTFONT line for some reason. */
2083 if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
2084 {
2085 if ( p->opts->keep_comments != 0 && p->font != 0 )
2086 {
2087 linelen -= 7;
2088
2089 s = line + 7;
2090 if ( *s != 0 )
2091 {
2092 s++;
2093 linelen--;
2094 }
2095
2096 error = _bdf_add_comment( p->font, s, linelen );
2097 if ( error )
2098 goto Exit;
2099 /* here font is not defined! */
2100 }
2101
2102 goto Exit;
2103 }
2104
2105 if ( !( p->flags & _BDF_START ) )
2106 {
2107 memory = p->memory;
2108
2109 if ( ft_memcmp( line, "STARTFONT", 9 ) != 0 )
2110 {
2111 /* we don't emit an error message since this code gets */
2112 /* explicitly caught one level higher */
2113 error = BDF_Err_Missing_Startfont_Field;
2114 goto Exit;
2115 }
2116
2117 p->flags = _BDF_START;
2118 font = p->font = 0;
2119
2120 if ( FT_NEW( font ) )
2121 goto Exit;
2122 p->font = font;
2123
2124 font->memory = p->memory;
2125 p->memory = 0;
2126
2127 { /* setup */
2128 size_t i;
2129 bdf_property_t* prop;
2130
2131
2132 error = hash_init( &(font->proptbl), memory );
2133 if ( error )
2134 goto Exit;
2135 for ( i = 0, prop = (bdf_property_t*)_bdf_properties;
2136 i < _num_bdf_properties; i++, prop++ )
2137 {
2138 error = hash_insert( prop->name, i,
2139 &(font->proptbl), memory );
2140 if ( error )
2141 goto Exit;
2142 }
2143 }
2144
2145 if ( FT_ALLOC( p->font->internal, sizeof ( hashtable ) ) )
2146 goto Exit;
2147 error = hash_init( (hashtable *)p->font->internal,memory );
2148 if ( error )
2149 goto Exit;
2150 p->font->spacing = p->opts->font_spacing;
2151 p->font->default_char = -1;
2152
2153 goto Exit;
2154 }
2155
2156 /* Check for the start of the properties. */
2157 if ( ft_memcmp( line, "STARTPROPERTIES", 15 ) == 0 )
2158 {
2159 if ( !( p->flags & _BDF_FONT_BBX ) )
2160 {
2161 /* Missing the FONTBOUNDINGBOX field. */
2162 FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONTBOUNDINGBOX" ));
2163 error = BDF_Err_Missing_Fontboundingbox_Field;
2164 goto Exit;
2165 }
2166
2167 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
2168 if ( error )
2169 goto Exit;
2170 /* at this point, `p->font' can't be NULL */
2171 p->cnt = p->font->props_size = _bdf_atoul( p->list.field[1], 0, 10 );
2172
2173 if ( FT_NEW_ARRAY( p->font->props, p->cnt ) )
2174 goto Exit;
2175
2176 p->flags |= _BDF_PROPS;
2177 *next = _bdf_parse_properties;
2178
2179 goto Exit;
2180 }
2181
2182 /* Check for the FONTBOUNDINGBOX field. */
2183 if ( ft_memcmp( line, "FONTBOUNDINGBOX", 15 ) == 0 )
2184 {
2185 if ( !( p->flags & _BDF_SIZE ) )
2186 {
2187 /* Missing the SIZE field. */
2188 FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "SIZE" ));
2189 error = BDF_Err_Missing_Size_Field;
2190 goto Exit;
2191 }
2192
2193 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
2194 if ( error )
2195 goto Exit;
2196
2197 p->font->bbx.width = _bdf_atos( p->list.field[1], 0, 10 );
2198 p->font->bbx.height = _bdf_atos( p->list.field[2], 0, 10 );
2199
2200 p->font->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );
2201 p->font->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );
2202
2203 p->font->bbx.ascent = (short)( p->font->bbx.height +
2204 p->font->bbx.y_offset );
2205
2206 p->font->bbx.descent = (short)( -p->font->bbx.y_offset );
2207
2208 p->flags |= _BDF_FONT_BBX;
2209
2210 goto Exit;
2211 }
2212
2213 /* The next thing to check for is the FONT field. */
2214 if ( ft_memcmp( line, "FONT", 4 ) == 0 )
2215 {
2216 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
2217 if ( error )
2218 goto Exit;
2219 _bdf_list_shift( &p->list, 1 );
2220
2221 s = _bdf_list_join( &p->list, ' ', &slen );
2222
2223 if ( !s )
2224 {
2225 FT_ERROR(( "_bdf_parse_start: " ERRMSG8, lineno, "FONT" ));
2226 error = BDF_Err_Invalid_File_Format;
2227 goto Exit;
2228 }
2229
2230 /* Allowing multiple `FONT' lines (which is invalid) doesn't hurt... */
2231 FT_FREE( p->font->name );
2232
2233 if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) )
2234 goto Exit;
2235 FT_MEM_COPY( p->font->name, s, slen + 1 );
2236
2237 /* If the font name is an XLFD name, set the spacing to the one in */
2238 /* the font name. If there is no spacing fall back on the default. */
2239 error = _bdf_set_default_spacing( p->font, p->opts, lineno );
2240 if ( error )
2241 goto Exit;
2242
2243 p->flags |= _BDF_FONT_NAME;
2244
2245 goto Exit;
2246 }
2247
2248 /* Check for the SIZE field. */
2249 if ( ft_memcmp( line, "SIZE", 4 ) == 0 )
2250 {
2251 if ( !( p->flags & _BDF_FONT_NAME ) )
2252 {
2253 /* Missing the FONT field. */
2254 FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONT" ));
2255 error = BDF_Err_Missing_Font_Field;
2256 goto Exit;
2257 }
2258
2259 error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
2260 if ( error )
2261 goto Exit;
2262
2263 p->font->point_size = _bdf_atoul( p->list.field[1], 0, 10 );
2264 p->font->resolution_x = _bdf_atoul( p->list.field[2], 0, 10 );
2265 p->font->resolution_y = _bdf_atoul( p->list.field[3], 0, 10 );
2266
2267 /* Check for the bits per pixel field. */
2268 if ( p->list.used == 5 )
2269 {
2270 unsigned short bitcount, i, shift;
2271
2272
2273 p->font->bpp = (unsigned short)_bdf_atos( p->list.field[4], 0, 10 );
2274
2275 /* Only values 1, 2, 4, 8 are allowed. */
2276 shift = p->font->bpp;
2277 bitcount = 0;
2278 for ( i = 0; shift > 0; i++ )
2279 {
2280 if ( shift & 1 )
2281 bitcount = i;
2282 shift >>= 1;
2283 }
2284
2285 shift = (short)( ( bitcount > 3 ) ? 8 : ( 1 << bitcount ) );
2286
2287 if ( p->font->bpp > shift || p->font->bpp != shift )
2288 {
2289 /* select next higher value */
2290 p->font->bpp = (unsigned short)( shift << 1 );
2291 FT_TRACE2(( "_bdf_parse_start: " ACMSG11, p->font->bpp ));
2292 }
2293 }
2294 else
2295 p->font->bpp = 1;
2296
2297 p->flags |= _BDF_SIZE;
2298
2299 goto Exit;
2300 }
2301
2302 /* Check for the CHARS field -- font properties are optional */
2303 if ( ft_memcmp( line, "CHARS", 5 ) == 0 )
2304 {
2305 char nbuf[128];
2306
2307
2308 if ( !( p->flags & _BDF_FONT_BBX ) )
2309 {
2310 /* Missing the FONTBOUNDINGBOX field. */
2311 FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONTBOUNDINGBOX" ));
2312 error = BDF_Err_Missing_Fontboundingbox_Field;
2313 goto Exit;
2314 }
2315
2316 /* Add the two standard X11 properties which are required */
2317 /* for compiling fonts. */
2318 p->font->font_ascent = p->font->bbx.ascent;
2319 ft_sprintf( nbuf, "%hd", p->font->bbx.ascent );
2320 error = _bdf_add_property( p->font, (char *)"FONT_ASCENT",
2321 nbuf, lineno );
2322 if ( error )
2323 goto Exit;
2324 FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent ));
2325
2326 p->font->font_descent = p->font->bbx.descent;
2327 ft_sprintf( nbuf, "%hd", p->font->bbx.descent );
2328 error = _bdf_add_property( p->font, (char *)"FONT_DESCENT",
2329 nbuf, lineno );
2330 if ( error )
2331 goto Exit;
2332 FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent ));
2333
2334 p->font->modified = 1;
2335
2336 *next = _bdf_parse_glyphs;
2337
2338 /* A special return value. */
2339 error = -1;
2340 goto Exit;
2341 }
2342
2343 FT_ERROR(( "_bdf_parse_start: " ERRMSG9, lineno ));
2344 error = BDF_Err_Invalid_File_Format;
2345
2346 Exit:
2347 return error;
2348 }
2349
2350
2351 /*************************************************************************/
2352 /* */
2353 /* API. */
2354 /* */
2355 /*************************************************************************/
2356
2357
2358 FT_LOCAL_DEF( FT_Error )
2359 bdf_load_font( FT_Stream stream,
2360 FT_Memory extmemory,
2361 bdf_options_t* opts,
2362 bdf_font_t* *font )
2363 {
2364 unsigned long lineno = 0; /* make compiler happy */
2365 _bdf_parse_t *p = NULL;
2366
2367 FT_Memory memory = extmemory;
2368 FT_Error error = BDF_Err_Ok;
2369
2370
2371 if ( FT_NEW( p ) )
2372 goto Exit;
2373
2374 memory = NULL;
2375 p->opts = (bdf_options_t*)( ( opts != 0 ) ? opts : &_bdf_opts );
2376 p->minlb = 32767;
2377 p->memory = extmemory; /* only during font creation */
2378
2379 _bdf_list_init( &p->list, extmemory );
2380
2381 error = _bdf_readstream( stream, _bdf_parse_start,
2382 (void *)p, &lineno );
2383 if ( error )
2384 goto Fail;
2385
2386 if ( p->font != 0 )
2387 {
2388 /* If the font is not proportional, set the font's monowidth */
2389 /* field to the width of the font bounding box. */
2390 memory = p->font->memory;
2391
2392 if ( p->font->spacing != BDF_PROPORTIONAL )
2393 p->font->monowidth = p->font->bbx.width;
2394
2395 /* If the number of glyphs loaded is not that of the original count, */
2396 /* indicate the difference. */
2397 if ( p->cnt != p->font->glyphs_used + p->font->unencoded_used )
2398 {
2399 FT_TRACE2(( "bdf_load_font: " ACMSG15, p->cnt,
2400 p->font->glyphs_used + p->font->unencoded_used ));
2401 p->font->modified = 1;
2402 }
2403
2404 /* Once the font has been loaded, adjust the overall font metrics if */
2405 /* necessary. */
2406 if ( p->opts->correct_metrics != 0 &&
2407 ( p->font->glyphs_used > 0 || p->font->unencoded_used > 0 ) )
2408 {
2409 if ( p->maxrb - p->minlb != p->font->bbx.width )
2410 {
2411 FT_TRACE2(( "bdf_load_font: " ACMSG3,
2412 p->font->bbx.width, p->maxrb - p->minlb ));
2413 p->font->bbx.width = (unsigned short)( p->maxrb - p->minlb );
2414 p->font->modified = 1;
2415 }
2416
2417 if ( p->font->bbx.x_offset != p->minlb )
2418 {
2419 FT_TRACE2(( "bdf_load_font: " ACMSG4,
2420 p->font->bbx.x_offset, p->minlb ));
2421 p->font->bbx.x_offset = p->minlb;
2422 p->font->modified = 1;
2423 }
2424
2425 if ( p->font->bbx.ascent != p->maxas )
2426 {
2427 FT_TRACE2(( "bdf_load_font: " ACMSG5,
2428 p->font->bbx.ascent, p->maxas ));
2429 p->font->bbx.ascent = p->maxas;
2430 p->font->modified = 1;
2431 }
2432
2433 if ( p->font->bbx.descent != p->maxds )
2434 {
2435 FT_TRACE2(( "bdf_load_font: " ACMSG6,
2436 p->font->bbx.descent, p->maxds ));
2437 p->font->bbx.descent = p->maxds;
2438 p->font->bbx.y_offset = (short)( -p->maxds );
2439 p->font->modified = 1;
2440 }
2441
2442 if ( p->maxas + p->maxds != p->font->bbx.height )
2443 {
2444 FT_TRACE2(( "bdf_load_font: " ACMSG7,
2445 p->font->bbx.height, p->maxas + p->maxds ));
2446 p->font->bbx.height = (unsigned short)( p->maxas + p->maxds );
2447 }
2448
2449 if ( p->flags & _BDF_SWIDTH_ADJ )
2450 FT_TRACE2(( "bdf_load_font: " ACMSG8 ));
2451 }
2452 }
2453
2454 if ( p->flags & _BDF_START )
2455 {
2456 /* The ENDFONT field was never reached or did not exist. */
2457 if ( !( p->flags & _BDF_GLYPHS ) )
2458 {
2459 /* Error happened while parsing header. */
2460 FT_ERROR(( "bdf_load_font: " ERRMSG2, lineno ));
2461 error = BDF_Err_Corrupted_Font_Header;
2462 goto Exit;
2463 }
2464 else
2465 {
2466 /* Error happened when parsing glyphs. */
2467 FT_ERROR(( "bdf_load_font: " ERRMSG3, lineno ));
2468 error = BDF_Err_Corrupted_Font_Glyphs;
2469 goto Exit;
2470 }
2471 }
2472
2473 if ( p->font != 0 )
2474 {
2475 /* Make sure the comments are NULL terminated if they exist. */
2476 memory = p->font->memory;
2477
2478 if ( p->font->comments_len > 0 )
2479 {
2480 if ( FT_RENEW_ARRAY( p->font->comments,
2481 p->font->comments_len,
2482 p->font->comments_len + 1 ) )
2483 goto Fail;
2484
2485 p->font->comments[p->font->comments_len] = 0;
2486 }
2487 }
2488 else if ( error == BDF_Err_Ok )
2489 error = BDF_Err_Invalid_File_Format;
2490
2491 *font = p->font;
2492
2493 Exit:
2494 if ( p )
2495 {
2496 _bdf_list_done( &p->list );
2497
2498 memory = extmemory;
2499
2500 FT_FREE( p );
2501 }
2502
2503 return error;
2504
2505 Fail:
2506 bdf_free_font( p->font );
2507
2508 memory = extmemory;
2509
2510 FT_FREE( p->font );
2511
2512 goto Exit;
2513 }
2514
2515
2516 FT_LOCAL_DEF( void )
2517 bdf_free_font( bdf_font_t* font )
2518 {
2519 bdf_property_t* prop;
2520 unsigned long i;
2521 bdf_glyph_t* glyphs;
2522 FT_Memory memory;
2523
2524
2525 if ( font == 0 )
2526 return;
2527
2528 memory = font->memory;
2529
2530 FT_FREE( font->name );
2531
2532 /* Free up the internal hash table of property names. */
2533 if ( font->internal )
2534 {
2535 hash_free( (hashtable *)font->internal, memory );
2536 FT_FREE( font->internal );
2537 }
2538
2539 /* Free up the comment info. */
2540 FT_FREE( font->comments );
2541
2542 /* Free up the properties. */
2543 for ( i = 0; i < font->props_size; i++ )
2544 {
2545 if ( font->props[i].format == BDF_ATOM )
2546 FT_FREE( font->props[i].value.atom );
2547 }
2548
2549 FT_FREE( font->props );
2550
2551 /* Free up the character info. */
2552 for ( i = 0, glyphs = font->glyphs;
2553 i < font->glyphs_used; i++, glyphs++ )
2554 {
2555 FT_FREE( glyphs->name );
2556 FT_FREE( glyphs->bitmap );
2557 }
2558
2559 for ( i = 0, glyphs = font->unencoded; i < font->unencoded_used;
2560 i++, glyphs++ )
2561 {
2562 FT_FREE( glyphs->name );
2563 FT_FREE( glyphs->bitmap );
2564 }
2565
2566 FT_FREE( font->glyphs );
2567 FT_FREE( font->unencoded );
2568
2569 /* Free up the overflow storage if it was used. */
2570 for ( i = 0, glyphs = font->overflow.glyphs;
2571 i < font->overflow.glyphs_used; i++, glyphs++ )
2572 {
2573 FT_FREE( glyphs->name );
2574 FT_FREE( glyphs->bitmap );
2575 }
2576
2577 FT_FREE( font->overflow.glyphs );
2578
2579 /* bdf_cleanup */
2580 hash_free( &(font->proptbl), memory );
2581
2582 /* Free up the user defined properties. */
2583 for ( prop = font->user_props, i = 0;
2584 i < font->nuser_props; i++, prop++ )
2585 {
2586 FT_FREE( prop->name );
2587 if ( prop->format == BDF_ATOM )
2588 FT_FREE( prop->value.atom );
2589 }
2590
2591 FT_FREE( font->user_props );
2592
2593 /* FREE( font ); */ /* XXX Fixme */
2594 }
2595
2596
2597 FT_LOCAL_DEF( bdf_property_t * )
2598 bdf_get_font_property( bdf_font_t* font,
2599 const char* name )
2600 {
2601 hashnode hn;
2602
2603
2604 if ( font == 0 || font->props_size == 0 || name == 0 || *name == 0 )
2605 return 0;
2606
2607 hn = hash_lookup( name, (hashtable *)font->internal );
2608
2609 return hn ? ( font->props + hn->data ) : 0;
2610 }
2611
2612
2613 /* END */
odigits
static const unsigned char odigits[32]
Definition: bdflib.c:819
_BDF_SWIDTH
#define _BDF_SWIDTH
Definition: bdflib.c:1114
bdf_font_t_::spacing
int spacing
Definition: bdf.h:201
FT_ALLOC
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:260
_BDF_GLYPH_BITS
#define _BDF_GLYPH_BITS
Definition: bdflib.c:1121
_bdf_readstream
static FT_Error _bdf_readstream(FT_Stream stream, _bdf_line_func_t callback, void *client_data, unsigned long *lno)
Definition: bdflib.c:660
FT_Error
int FT_Error
Definition: fttypes.h:296
_BDF_GLYPH_WIDTH_CHECK
#define _BDF_GLYPH_WIDTH_CHECK
Definition: bdflib.c:1128
bdf_font_t_::unencoded_size
unsigned long unencoded_size
Definition: bdf.h:214
ACMSG13
#define ACMSG13
Definition: bdflib.c:188
_bdf_atoul
static unsigned long _bdf_atoul(char *s, char **end, int base)
Definition: bdflib.c:849
setsbit
#define setsbit(m, cc)
Definition: bdflib.c:426
_BDF_DWIDTH
#define _BDF_DWIDTH
Definition: bdflib.c:1115
_BDF_FONT_BBX
#define _BDF_FONT_BBX
Definition: bdflib.c:1109
bdf_font_t_::point_size
long point_size
Definition: bdf.h:197
bdf_font_t_::comments
char * comments
Definition: bdf.h:222
FT_Long
signed long FT_Long
Definition: fttypes.h:238
s
GLdouble s
Definition: glew.h:1376
ACMSG5
#define ACMSG5
Definition: bdflib.c:180
bdf_font_t_::user_props
bdf_property_t * user_props
Definition: bdf.h:239
FT_ULong
unsigned long FT_ULong
Definition: fttypes.h:249
_BDF_BBX
#define _BDF_BBX
Definition: bdflib.c:1116
bdferror.h
ERRMSG1
#define ERRMSG1
Definition: bdflib.c:194
ACMSG7
#define ACMSG7
Definition: bdflib.c:182
isdigok
#define isdigok(m, d)
Definition: bdflib.c:844
bdf_property_t_::value
union bdf_property_t_::@25 value
_BDF_SWIDTH_ADJ
#define _BDF_SWIDTH_ADJ
Definition: bdflib.c:1119
void
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1824
_BDF_GLYPHS
#define _BDF_GLYPHS
Definition: bdflib.c:1111
_BDF_BITMAP
#define _BDF_BITMAP
Definition: bdflib.c:1117
_bdf_set_glyph_modified
#define _bdf_set_glyph_modified(map, e)
Definition: bdf.h:45
_bdf_glyph_modified
#define _bdf_glyph_modified(map, e)
Definition: bdf.h:43
by_encoding
static int by_encoding(const void *a, const void *b)
Definition: bdflib.c:1006
FT_MEM_ZERO
#define FT_MEM_ZERO(dest, count)
Definition: ftmemory.h:208
NULL
#define NULL
Definition: ftobjs.h:61
bdf_glyph_t_::encoding
long encoding
Definition: bdf.h:149
start
GLuint start
Definition: glew.h:1239
FT_ULONG_MAX
#define FT_ULONG_MAX
Definition: ftstdlib.h:67
FT_Stream_TryRead
FT_Stream_TryRead(FT_Stream stream, FT_Byte *buffer, FT_ULong count)
Definition: ftstream.c:164
stream
GLuint GLuint stream
Definition: glew.h:6573
n
GLclampd n
Definition: glew.h:7287
bdf_property_t_::name
char * name
Definition: bdf.h:111
bdf_font_t_
Definition: bdf.h:192
hash_free_func
void(* hash_free_func)(hashnode node)
Definition: bdflib.c:221
ddigits
static const unsigned char ddigits[32]
Definition: bdflib.c:827
bdf_property_t_::format
int format
Definition: bdf.h:112
ACMSG3
#define ACMSG3
Definition: bdflib.c:177
_bdf_atol
static long _bdf_atol(char *s, char **end, int base)
Definition: bdflib.c:896
bdf_font_t_::font_ascent
long font_ascent
Definition: bdf.h:207
FT_MIN
#define FT_MIN(a, b)
Definition: ftobjs.h:70
bdf_font_t_::unencoded
bdf_glyph_t * unencoded
Definition: bdf.h:216
hash_init
static FT_Error hash_init(hashtable *ht, FT_Memory memory)
Definition: bdflib.c:282
hash_rehash
static FT_Error hash_rehash(hashtable *ht, FT_Memory memory)
Definition: bdflib.c:252
BDF_CARDINAL
#define BDF_CARDINAL
Definition: bdf.h:104
BDF_INTEGER
#define BDF_INTEGER
Definition: bdf.h:103
NO_SKIP
#define NO_SKIP
Definition: bdflib.c:656
j
int32_t j
Definition: e_log.c:102
bdf_create_property
static FT_Error bdf_create_property(char *name, int format, bdf_font_t *font)
Definition: bdflib.c:1026
hashtable_::size
int size
Definition: bdf.h:171
bdf_free_font
bdf_free_font(bdf_font_t *font)
Definition: bdflib.c:2517
a
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
ACMSG11
#define ACMSG11
Definition: bdflib.c:186
bdf_font_t_::modified
unsigned short modified
Definition: bdf.h:234
_bdf_add_comment
static FT_Error _bdf_add_comment(bdf_font_t *font, char *comment, unsigned long len)
Definition: bdflib.c:1133
name
EGLImageKHR EGLint * name
Definition: eglext.h:284
DBGMSG1
#define DBGMSG1
Definition: bdflib.c:205
_bdf_parse_properties
static FT_Error _bdf_parse_properties(char *line, unsigned long linelen, unsigned long lineno, void *call_data, void *client_data)
Definition: bdflib.c:1952
len
GLenum GLsizei len
Definition: glew.h:7035
_bdf_opts
static const bdf_options_t _bdf_opts
Definition: bdflib.c:62
bdf_get_font_property
bdf_get_font_property(bdf_font_t *font, const char *name)
Definition: bdflib.c:2598
bdf_font_t_::resolution_x
unsigned long resolution_x
Definition: bdf.h:198
BDF_ATOM
#define BDF_ATOM
Definition: bdf.h:102
bdf_glyph_t_::bbx
bdf_bbx_t bbx
Definition: bdf.h:152
bdf_font_t_::props
bdf_property_t * props
Definition: bdf.h:220
bdf_font_t_::props_size
unsigned long props_size
Definition: bdf.h:218
ft_qsort
#define ft_qsort
Definition: ftstdlib.h:121
bdf_property_t_
Definition: bdf.h:109
ACMSG1
#define ACMSG1
Definition: bdflib.c:173
FT_ERROR
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
FT_Byte
unsigned char FT_Byte
Definition: fttypes.h:150
ACMSG16
#define ACMSG16
Definition: bdflib.c:191
bdf_property_t_::builtin
int builtin
Definition: bdf.h:113
FT_TRACE4
#define FT_TRACE4(varformat)
Definition: ftdebug.h:161
ACMSG4
#define ACMSG4
Definition: bdflib.c:178
INITIAL_HT_SIZE
#define INITIAL_HT_SIZE
Definition: bdflib.c:218
_bdf_list_done
static void _bdf_list_done(_bdf_list_t *list)
Definition: bdflib.c:442
ERRMSG2
#define ERRMSG2
Definition: bdflib.c:195
bdf_bbx_t_::descent
short descent
Definition: bdf.h:141
ACMSG2
#define ACMSG2
Definition: bdflib.c:175
_hashnode_::data
size_t data
Definition: bdf.h:163
bdf_font_t_::name
char * name
Definition: bdf.h:194
bdf_glyph_t_::dwidth
unsigned short dwidth
Definition: bdf.h:151
bdf_glyph_t_
Definition: bdf.h:146
bdf_property_t_::ul
unsigned long ul
Definition: bdf.h:118
FT_StreamRec_::memory
FT_Memory memory
Definition: ftsystem.h:332
row
GLenum GLenum GLvoid * row
Definition: glew.h:4447
FT_FREE
#define FT_FREE(ptr)
Definition: ftmemory.h:286
hash_free
static void hash_free(hashtable *ht, FT_Memory memory)
Definition: bdflib.c:302
u
ALuint u
Definition: alMain.h:58
bdf.h
FT_LOCAL_DEF
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:467
ft_sprintf
#define ft_sprintf
Definition: ftstdlib.h:109
v
const GLdouble * v
Definition: glew.h:1377
bdf_font_t_::default_char
long default_char
Definition: bdf.h:205
_bdf_list_t
struct _bdf_list_t_ _bdf_list_t
bdf_font_t_::glyphs_size
unsigned long glyphs_size
Definition: bdf.h:210
int
int
Definition: SDL_systhread.c:37
FT_MulDiv
FT_MulDiv(FT_Long a, FT_Long b, FT_Long c)
Definition: ftcalc.c:358
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
ACMSG14
#define ACMSG14
Definition: bdflib.c:189
error
FT_Error error
Definition: cffdrivr.c:407
ERRMSG7
#define ERRMSG7
Definition: bdflib.c:200
ERRMSG6
#define ERRMSG6
Definition: bdflib.c:199
FT_ZERO
#define FT_ZERO(p)
Definition: ftmemory.h:210
bdf_bbx_t_::x_offset
short x_offset
Definition: bdf.h:137
_BDF_ENCODING
#define _BDF_ENCODING
Definition: bdflib.c:1113
p
GLfloat GLfloat p
Definition: glew.h:14938
ACMSG9
#define ACMSG9
Definition: bdflib.c:184
bdf_font_t_::font_descent
long font_descent
Definition: bdf.h:208
_bdf_list_ensure
static FT_Error _bdf_list_ensure(_bdf_list_t *list, unsigned long num_items)
Definition: bdflib.c:456
bdf_property_t_::l
long l
Definition: bdf.h:117
empty
static const char empty[1]
Definition: bdflib.c:513
_bdf_add_property
static FT_Error _bdf_add_property(bdf_font_t *font, char *name, char *value, unsigned long lineno)
Definition: bdflib.c:1294
bdf_glyph_t_::bpr
unsigned long bpr
Definition: bdf.h:154
c
const GLfloat * c
Definition: glew.h:14913
_bdf_list_join
static char * _bdf_list_join(_bdf_list_t *list, int c, unsigned long *alen)
Definition: bdflib.c:517
FT_MAX
#define FT_MAX(a, b)
Definition: ftobjs.h:71
bdf_property_t_::atom
char * atom
Definition: bdf.h:116
_BDF_START
#define _BDF_START
Definition: bdflib.c:1106
FT_TRACE2
#define FT_TRACE2(varformat)
Definition: ftdebug.h:159
bdf_font_t_::nuser_props
unsigned long nuser_props
Definition: bdf.h:240
format
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl2ext.h:845
FT_RENEW_ARRAY
#define FT_RENEW_ARRAY(ptr, curcnt, newcnt)
Definition: ftmemory.h:293
_bdf_list_split
static FT_Error _bdf_list_split(_bdf_list_t *list, char *separators, char *line, unsigned long linelen)
Definition: bdflib.c:553
bdf_font_t_::unencoded_used
unsigned long unencoded_used
Definition: bdf.h:215
ERRMSG8
#define ERRMSG8
Definition: bdflib.c:201
hdigits
static const unsigned char hdigits[32]
Definition: bdflib.c:835
bdf_font_t_::comments_len
unsigned long comments_len
Definition: bdf.h:223
_num_bdf_properties
static const unsigned long _num_bdf_properties
Definition: bdflib.c:168
bp
static double bp[]
Definition: e_pow.c:72
_bdf_parse_start
static FT_Error _bdf_parse_start(char *line, unsigned long linelen, unsigned long lineno, void *call_data, void *client_data)
Definition: bdflib.c:2057
_bdf_list_shift
static void _bdf_list_shift(_bdf_list_t *list, unsigned long n)
Definition: bdflib.c:490
_bdf_list_init
static void _bdf_list_init(_bdf_list_t *list, FT_Memory memory)
Definition: bdflib.c:433
FT_Memory
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
DBGMSG2
#define DBGMSG2
Definition: bdflib.c:206
BDF_MONOWIDTH
#define BDF_MONOWIDTH
Definition: bdf.h:64
_hashnode_
Definition: bdf.h:160
sizeof
sizeof(FT_AutofitterRec)
FT_NEW_ARRAY
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:290
ACMSG10
#define ACMSG10
Definition: bdflib.c:185
sbitset
#define sbitset(m, cc)
Definition: bdflib.c:428
nibble_mask
static const unsigned char nibble_mask[8]
Definition: bdflib.c:1453
_bdf_is_atom
static int _bdf_is_atom(char *line, unsigned long linelen, char **name, char **value, bdf_font_t *font)
Definition: bdflib.c:1230
ACMSG8
#define ACMSG8
Definition: bdflib.c:183
value
EGLSurface EGLint void ** value
Definition: eglext.h:301
bdf_load_font
bdf_load_font(FT_Stream stream, FT_Memory memory, bdf_options_t *opts, bdf_font_t **font)
Definition: bdflib.c:2359
const
#define const
Definition: zconf.h:91
ft2build.h
bdf_bbx_t_::y_offset
short y_offset
Definition: bdf.h:138
BDF_PROPORTIONAL
#define BDF_PROPORTIONAL
Definition: bdf.h:63
bdf_font_t_::nmod
unsigned long nmod[34816]
Definition: bdf.h:231
BDF_CHARCELL
#define BDF_CHARCELL
Definition: bdf.h:65
bdf_glyph_t_::name
char * name
Definition: bdf.h:148
_hashnode_::key
const char * key
Definition: bdf.h:162
buf
GLenum GLuint GLsizei const GLchar * buf
Definition: glew.h:2539
flags
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
ft_memcmp
#define ft_memcmp
Definition: ftstdlib.h:80
bdf_options_t_
Definition: bdf.h:77
bdf_font_t_::memory
FT_Memory memory
Definition: bdf.h:237
_bdf_atos
static short _bdf_atos(char *s, char **end, int base)
Definition: bdflib.c:951
bdf_bbx_t_::height
unsigned short height
Definition: bdf.h:135
bdf_bbx_t_::ascent
short ascent
Definition: bdf.h:140
_BDF_PROPS
#define _BDF_PROPS
Definition: bdflib.c:1110
hashtable_::used
int used
Definition: bdf.h:172
ERRMSG4
#define ERRMSG4
Definition: bdflib.c:197
hashtable_::limit
int limit
Definition: bdf.h:170
bdf_glyph_t_::swidth
unsigned short swidth
Definition: bdf.h:150
b
GLdouble GLdouble GLdouble b
Definition: glew.h:8383
end
GLuint GLuint end
Definition: glew.h:1239
bdf_glyph_t_::bytes
unsigned short bytes
Definition: bdf.h:155
ERRMSG5
#define ERRMSG5
Definition: bdflib.c:198
ERRMSG3
#define ERRMSG3
Definition: bdflib.c:196
_BDF_GLYPH
#define _BDF_GLYPH
Definition: bdflib.c:1112
_BDF_SIZE
#define _BDF_SIZE
Definition: bdflib.c:1108
ACMSG6
#define ACMSG6
Definition: bdflib.c:181
bdf_font_t_::glyphs
bdf_glyph_t * glyphs
Definition: bdf.h:212
hashtable_
Definition: bdf.h:168
bdf_bbx_t_::width
unsigned short width
Definition: bdf.h:134
hash_insert
static FT_Error hash_insert(char *key, size_t data, hashtable *ht, FT_Memory memory)
Definition: bdflib.c:320
FT_INT_MAX
#define FT_INT_MAX
Definition: ftstdlib.h:64
hash_bucket
static hashnode * hash_bucket(const char *key, hashtable *ht)
Definition: bdflib.c:224
FT_STRDUP
#define FT_STRDUP(dst, str)
Definition: ftmemory.h:351
bdf_font_t_::proptbl
hashtable proptbl
Definition: bdf.h:241
hash_lookup
static hashnode hash_lookup(const char *key, hashtable *ht)
Definition: bdflib.c:356
FT_NEW
#define FT_NEW(ptr)
Definition: ftmemory.h:288
bdf_font_t_::glyphs_used
unsigned long glyphs_used
Definition: bdf.h:211
i
int i
Definition: pngrutil.c:1377
bdf_options_t_::font_spacing
int font_spacing
Definition: bdf.h:82
bdf_get_property
bdf_get_property(char *name, bdf_font_t *font)
Definition: bdflib.c:1076
FT_MEM_COPY
#define FT_MEM_COPY(dest, source, count)
Definition: ftmemory.h:203
_BDF_FONT_NAME
#define _BDF_FONT_NAME
Definition: bdflib.c:1107
a2i
static const unsigned char a2i[128]
Definition: bdflib.c:804
ACMSG15
#define ACMSG15
Definition: bdflib.c:190
hashtable_::table
hashnode * table
Definition: bdf.h:173
_bdf_properties
static const bdf_property_t _bdf_properties[]
Definition: bdflib.c:80
_bdf_set_default_spacing
static FT_Error _bdf_set_default_spacing(bdf_font_t *font, bdf_options_t *opts, unsigned long lineno)
Definition: bdflib.c:1162
FT_StreamRec_
Definition: ftsystem.h:321
ACMSG12
#define ACMSG12
Definition: bdflib.c:187
_bdf_parse_glyphs
static FT_Error _bdf_parse_glyphs(char *line, unsigned long linelen, unsigned long lineno, void *call_data, void *client_data)
Definition: bdflib.c:1461
bdf_font_t_::umod
unsigned long umod[34816]
Definition: bdf.h:232
FT_UNUSED
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
ERRMSG9
#define ERRMSG9
Definition: bdflib.c:202
bdf_glyph_t_::bitmap
unsigned char * bitmap
Definition: bdf.h:153
ft_strlen
#define ft_strlen
Definition: ftstdlib.h:87
cp
static double cp
Definition: e_pow.c:96
res
GLuint res
Definition: glew.h:10669
_BDF_GLYPH_HEIGHT_CHECK
#define _BDF_GLYPH_HEIGHT_CHECK
Definition: bdflib.c:1129
ft_strcmp
#define ft_strcmp
Definition: ftstdlib.h:85
_bdf_line_func_t
FT_Error(* _bdf_line_func_t)(char *line, unsigned long linelen, unsigned long lineno, void *call_data, void *client_data)
Definition: bdflib.c:376
bdf_font_t_::props_used
unsigned long props_used
Definition: bdf.h:219
bdf_font_t_::internal
void * internal
Definition: bdf.h:227
size
GLsizei size
Definition: gl2ext.h:1467
_bdf_parse_t
struct _bdf_parse_t_ _bdf_parse_t