Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

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