zenilib  0.5.3.0
 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 
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
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
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
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
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
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
434  FT_Memory memory )
435  {
436  FT_ZERO( list );
437  list->memory = memory;
438  }
439 
440 
441  static void
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
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
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 *
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
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
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
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 
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
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
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
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. */
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 )
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
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 
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 )
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 
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 */
static const unsigned char odigits[32]
Definition: bdflib.c:819
#define _BDF_SWIDTH
Definition: bdflib.c:1114
int spacing
Definition: bdf.h:201
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:260
#define _BDF_GLYPH_BITS
Definition: bdflib.c:1121
static FT_Error _bdf_readstream(FT_Stream stream, _bdf_line_func_t callback, void *client_data, unsigned long *lno)
Definition: bdflib.c:660
int FT_Error
Definition: fttypes.h:296
#define _BDF_GLYPH_WIDTH_CHECK
Definition: bdflib.c:1128
unsigned long unencoded_size
Definition: bdf.h:214
#define ACMSG13
Definition: bdflib.c:188
static unsigned long _bdf_atoul(char *s, char **end, int base)
Definition: bdflib.c:849
#define setsbit(m, cc)
Definition: bdflib.c:426
#define _BDF_DWIDTH
Definition: bdflib.c:1115
#define _BDF_FONT_BBX
Definition: bdflib.c:1109
long point_size
Definition: bdf.h:197
char * comments
Definition: bdf.h:222
signed long FT_Long
Definition: fttypes.h:238
GLdouble s
Definition: glew.h:1376
#define ACMSG5
Definition: bdflib.c:180
bdf_property_t * user_props
Definition: bdf.h:239
unsigned long FT_ULong
Definition: fttypes.h:249
#define _BDF_BBX
Definition: bdflib.c:1116
#define ERRMSG1
Definition: bdflib.c:194
#define ACMSG7
Definition: bdflib.c:182
#define isdigok(m, d)
Definition: bdflib.c:844
union bdf_property_t_::@25 value
#define _BDF_SWIDTH_ADJ
Definition: bdflib.c:1119
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1824
#define _BDF_GLYPHS
Definition: bdflib.c:1111
#define _BDF_BITMAP
Definition: bdflib.c:1117
#define _bdf_set_glyph_modified(map, e)
Definition: bdf.h:45
#define _bdf_glyph_modified(map, e)
Definition: bdf.h:43
static int by_encoding(const void *a, const void *b)
Definition: bdflib.c:1006
#define FT_MEM_ZERO(dest, count)
Definition: ftmemory.h:208
#define NULL
Definition: ftobjs.h:61
long encoding
Definition: bdf.h:149
GLuint start
Definition: glew.h:1239
#define FT_ULONG_MAX
Definition: ftstdlib.h:67
FT_Stream_TryRead(FT_Stream stream, FT_Byte *buffer, FT_ULong count)
Definition: ftstream.c:164
GLuint GLuint stream
Definition: glew.h:6573
GLclampd n
Definition: glew.h:7287
char * name
Definition: bdf.h:111
void(* hash_free_func)(hashnode node)
Definition: bdflib.c:221
static const unsigned char ddigits[32]
Definition: bdflib.c:827
int format
Definition: bdf.h:112
#define ACMSG3
Definition: bdflib.c:177
static long _bdf_atol(char *s, char **end, int base)
Definition: bdflib.c:896
long font_ascent
Definition: bdf.h:207
#define FT_MIN(a, b)
Definition: ftobjs.h:70
bdf_glyph_t * unencoded
Definition: bdf.h:216
static FT_Error hash_init(hashtable *ht, FT_Memory memory)
Definition: bdflib.c:282
static FT_Error hash_rehash(hashtable *ht, FT_Memory memory)
Definition: bdflib.c:252
#define BDF_CARDINAL
Definition: bdf.h:104
#define BDF_INTEGER
Definition: bdf.h:103
#define NO_SKIP
Definition: bdflib.c:656
int32_t j
Definition: e_log.c:102
static FT_Error bdf_create_property(char *name, int format, bdf_font_t *font)
Definition: bdflib.c:1026
int size
Definition: bdf.h:171
bdf_free_font(bdf_font_t *font)
Definition: bdflib.c:2517
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
#define ACMSG11
Definition: bdflib.c:186
unsigned short modified
Definition: bdf.h:234
static FT_Error _bdf_add_comment(bdf_font_t *font, char *comment, unsigned long len)
Definition: bdflib.c:1133
EGLImageKHR EGLint * name
Definition: eglext.h:284
#define DBGMSG1
Definition: bdflib.c:205
static FT_Error _bdf_parse_properties(char *line, unsigned long linelen, unsigned long lineno, void *call_data, void *client_data)
Definition: bdflib.c:1952
GLenum GLsizei len
Definition: glew.h:7035
static const bdf_options_t _bdf_opts
Definition: bdflib.c:62
bdf_get_font_property(bdf_font_t *font, const char *name)
Definition: bdflib.c:2598
unsigned long resolution_x
Definition: bdf.h:198
#define BDF_ATOM
Definition: bdf.h:102
bdf_bbx_t bbx
Definition: bdf.h:152
bdf_property_t * props
Definition: bdf.h:220
unsigned long props_size
Definition: bdf.h:218
#define ft_qsort
Definition: ftstdlib.h:121
#define ACMSG1
Definition: bdflib.c:173
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
unsigned char FT_Byte
Definition: fttypes.h:150
#define ACMSG16
Definition: bdflib.c:191
int builtin
Definition: bdf.h:113
#define FT_TRACE4(varformat)
Definition: ftdebug.h:161
#define ACMSG4
Definition: bdflib.c:178
#define INITIAL_HT_SIZE
Definition: bdflib.c:218
static void _bdf_list_done(_bdf_list_t *list)
Definition: bdflib.c:442
#define ERRMSG2
Definition: bdflib.c:195
short descent
Definition: bdf.h:141
#define ACMSG2
Definition: bdflib.c:175
size_t data
Definition: bdf.h:163
char * name
Definition: bdf.h:194
unsigned short dwidth
Definition: bdf.h:151
unsigned long ul
Definition: bdf.h:118
FT_Memory memory
Definition: ftsystem.h:332
GLenum GLenum GLvoid * row
Definition: glew.h:4447
#define FT_FREE(ptr)
Definition: ftmemory.h:286
static void hash_free(hashtable *ht, FT_Memory memory)
Definition: bdflib.c:302
ALuint u
Definition: alMain.h:58
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:467
#define ft_sprintf
Definition: ftstdlib.h:109
const GLdouble * v
Definition: glew.h:1377
long default_char
Definition: bdf.h:205
struct _bdf_list_t_ _bdf_list_t
unsigned long glyphs_size
Definition: bdf.h:210
int
Definition: SDL_systhread.c:37
FT_MulDiv(FT_Long a, FT_Long b, FT_Long c)
Definition: ftcalc.c:358
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
#define ACMSG14
Definition: bdflib.c:189
FT_Error error
Definition: cffdrivr.c:407
#define ERRMSG7
Definition: bdflib.c:200
#define ERRMSG6
Definition: bdflib.c:199
#define FT_ZERO(p)
Definition: ftmemory.h:210
short x_offset
Definition: bdf.h:137
#define _BDF_ENCODING
Definition: bdflib.c:1113
GLfloat GLfloat p
Definition: glew.h:14938
#define ACMSG9
Definition: bdflib.c:184
long font_descent
Definition: bdf.h:208
static FT_Error _bdf_list_ensure(_bdf_list_t *list, unsigned long num_items)
Definition: bdflib.c:456
long l
Definition: bdf.h:117
static const char empty[1]
Definition: bdflib.c:513
static FT_Error _bdf_add_property(bdf_font_t *font, char *name, char *value, unsigned long lineno)
Definition: bdflib.c:1294
unsigned long bpr
Definition: bdf.h:154
const GLfloat * c
Definition: glew.h:14913
static char * _bdf_list_join(_bdf_list_t *list, int c, unsigned long *alen)
Definition: bdflib.c:517
#define FT_MAX(a, b)
Definition: ftobjs.h:71
char * atom
Definition: bdf.h:116
#define _BDF_START
Definition: bdflib.c:1106
#define FT_TRACE2(varformat)
Definition: ftdebug.h:159
unsigned long nuser_props
Definition: bdf.h:240
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl2ext.h:845
#define FT_RENEW_ARRAY(ptr, curcnt, newcnt)
Definition: ftmemory.h:293
static FT_Error _bdf_list_split(_bdf_list_t *list, char *separators, char *line, unsigned long linelen)
Definition: bdflib.c:553
unsigned long unencoded_used
Definition: bdf.h:215
#define ERRMSG8
Definition: bdflib.c:201
static const unsigned char hdigits[32]
Definition: bdflib.c:835
unsigned long comments_len
Definition: bdf.h:223
static const unsigned long _num_bdf_properties
Definition: bdflib.c:168
static double bp[]
Definition: e_pow.c:72
static FT_Error _bdf_parse_start(char *line, unsigned long linelen, unsigned long lineno, void *call_data, void *client_data)
Definition: bdflib.c:2057
static void _bdf_list_shift(_bdf_list_t *list, unsigned long n)
Definition: bdflib.c:490
static void _bdf_list_init(_bdf_list_t *list, FT_Memory memory)
Definition: bdflib.c:433
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
#define DBGMSG2
Definition: bdflib.c:206
#define BDF_MONOWIDTH
Definition: bdf.h:64
sizeof(FT_AutofitterRec)
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:290
#define ACMSG10
Definition: bdflib.c:185
#define sbitset(m, cc)
Definition: bdflib.c:428
static const unsigned char nibble_mask[8]
Definition: bdflib.c:1453
static int _bdf_is_atom(char *line, unsigned long linelen, char **name, char **value, bdf_font_t *font)
Definition: bdflib.c:1230
#define ACMSG8
Definition: bdflib.c:183
EGLSurface EGLint void ** value
Definition: eglext.h:301
bdf_load_font(FT_Stream stream, FT_Memory memory, bdf_options_t *opts, bdf_font_t **font)
Definition: bdflib.c:2359
#define const
Definition: zconf.h:91
short y_offset
Definition: bdf.h:138
#define BDF_PROPORTIONAL
Definition: bdf.h:63
unsigned long nmod[34816]
Definition: bdf.h:231
#define BDF_CHARCELL
Definition: bdf.h:65
char * name
Definition: bdf.h:148
const char * key
Definition: bdf.h:162
GLenum GLuint GLsizei const GLchar * buf
Definition: glew.h:2539
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
#define ft_memcmp
Definition: ftstdlib.h:80
FT_Memory memory
Definition: bdf.h:237
static short _bdf_atos(char *s, char **end, int base)
Definition: bdflib.c:951
unsigned short height
Definition: bdf.h:135
short ascent
Definition: bdf.h:140
#define _BDF_PROPS
Definition: bdflib.c:1110
int used
Definition: bdf.h:172
#define ERRMSG4
Definition: bdflib.c:197
int limit
Definition: bdf.h:170
unsigned short swidth
Definition: bdf.h:150
GLdouble GLdouble GLdouble b
Definition: glew.h:8383
GLuint GLuint end
Definition: glew.h:1239
unsigned short bytes
Definition: bdf.h:155
#define ERRMSG5
Definition: bdflib.c:198
#define ERRMSG3
Definition: bdflib.c:196
#define _BDF_GLYPH
Definition: bdflib.c:1112
#define _BDF_SIZE
Definition: bdflib.c:1108
#define ACMSG6
Definition: bdflib.c:181
bdf_glyph_t * glyphs
Definition: bdf.h:212
unsigned short width
Definition: bdf.h:134
static FT_Error hash_insert(char *key, size_t data, hashtable *ht, FT_Memory memory)
Definition: bdflib.c:320
#define FT_INT_MAX
Definition: ftstdlib.h:64
static hashnode * hash_bucket(const char *key, hashtable *ht)
Definition: bdflib.c:224
#define FT_STRDUP(dst, str)
Definition: ftmemory.h:351
hashtable proptbl
Definition: bdf.h:241
static hashnode hash_lookup(const char *key, hashtable *ht)
Definition: bdflib.c:356
#define FT_NEW(ptr)
Definition: ftmemory.h:288
unsigned long glyphs_used
Definition: bdf.h:211
int i
Definition: pngrutil.c:1377
int font_spacing
Definition: bdf.h:82
bdf_get_property(char *name, bdf_font_t *font)
Definition: bdflib.c:1076
#define FT_MEM_COPY(dest, source, count)
Definition: ftmemory.h:203
#define _BDF_FONT_NAME
Definition: bdflib.c:1107
static const unsigned char a2i[128]
Definition: bdflib.c:804
#define ACMSG15
Definition: bdflib.c:190
hashnode * table
Definition: bdf.h:173
static const bdf_property_t _bdf_properties[]
Definition: bdflib.c:80
static FT_Error _bdf_set_default_spacing(bdf_font_t *font, bdf_options_t *opts, unsigned long lineno)
Definition: bdflib.c:1162
#define ACMSG12
Definition: bdflib.c:187
static FT_Error _bdf_parse_glyphs(char *line, unsigned long linelen, unsigned long lineno, void *call_data, void *client_data)
Definition: bdflib.c:1461
unsigned long umod[34816]
Definition: bdf.h:232
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
#define ERRMSG9
Definition: bdflib.c:202
unsigned char * bitmap
Definition: bdf.h:153
#define ft_strlen
Definition: ftstdlib.h:87
static double cp
Definition: e_pow.c:96
GLuint res
Definition: glew.h:10669
#define _BDF_GLYPH_HEIGHT_CHECK
Definition: bdflib.c:1129
#define ft_strcmp
Definition: ftstdlib.h:85
FT_Error(* _bdf_line_func_t)(char *line, unsigned long linelen, unsigned long lineno, void *call_data, void *client_data)
Definition: bdflib.c:376
unsigned long props_used
Definition: bdf.h:219
void * internal
Definition: bdf.h:227
GLsizei size
Definition: gl2ext.h:1467
struct _bdf_parse_t_ _bdf_parse_t