/src/freetype/src/bdf/bdflib.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 2613 lines · 1817 code · 526 blank · 270 comment · 454 complexity · 6e31146d0142cd3803006e5f21d225c8 MD5 · raw file

Large files are truncated click here to view the full 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. /* This file is based on bdf.c,v 1.22 2000/03/16 20:08:50 */
  27. /* */
  28. /* taken from Mark Leisher's xmbdfed package */
  29. /* */
  30. /*************************************************************************/
  31. #include <ft2build.h>
  32. #include FT_FREETYPE_H
  33. #include FT_INTERNAL_DEBUG_H
  34. #include FT_INTERNAL_STREAM_H
  35. #include FT_INTERNAL_OBJECTS_H
  36. #include "bdf.h"
  37. #include "bdferror.h"
  38. /*************************************************************************/
  39. /* */
  40. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  41. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  42. /* messages during execution. */
  43. /* */
  44. #undef FT_COMPONENT
  45. #define FT_COMPONENT trace_bdflib
  46. /*************************************************************************/
  47. /* */
  48. /* Default BDF font options. */
  49. /* */
  50. /*************************************************************************/
  51. static const bdf_options_t _bdf_opts =
  52. {
  53. 1, /* Correct metrics. */
  54. 1, /* Preserve unencoded glyphs. */
  55. 0, /* Preserve comments. */
  56. BDF_PROPORTIONAL /* Default spacing. */
  57. };
  58. /*************************************************************************/
  59. /* */
  60. /* Builtin BDF font properties. */
  61. /* */
  62. /*************************************************************************/
  63. /* List of most properties that might appear in a font. Doesn't include */
  64. /* the RAW_* and AXIS_* properties in X11R6 polymorphic fonts. */
  65. static const bdf_property_t _bdf_properties[] =
  66. {
  67. { (char *)"ADD_STYLE_NAME", BDF_ATOM, 1, { 0 } },
  68. { (char *)"AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },
  69. { (char *)"AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },
  70. { (char *)"AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },
  71. { (char *)"CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },
  72. { (char *)"CHARSET_COLLECTIONS", BDF_ATOM, 1, { 0 } },
  73. { (char *)"CHARSET_ENCODING", BDF_ATOM, 1, { 0 } },
  74. { (char *)"CHARSET_REGISTRY", BDF_ATOM, 1, { 0 } },
  75. { (char *)"COMMENT", BDF_ATOM, 1, { 0 } },
  76. { (char *)"COPYRIGHT", BDF_ATOM, 1, { 0 } },
  77. { (char *)"DEFAULT_CHAR", BDF_CARDINAL, 1, { 0 } },
  78. { (char *)"DESTINATION", BDF_CARDINAL, 1, { 0 } },
  79. { (char *)"DEVICE_FONT_NAME", BDF_ATOM, 1, { 0 } },
  80. { (char *)"END_SPACE", BDF_INTEGER, 1, { 0 } },
  81. { (char *)"FACE_NAME", BDF_ATOM, 1, { 0 } },
  82. { (char *)"FAMILY_NAME", BDF_ATOM, 1, { 0 } },
  83. { (char *)"FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },
  84. { (char *)"FONT", BDF_ATOM, 1, { 0 } },
  85. { (char *)"FONTNAME_REGISTRY", BDF_ATOM, 1, { 0 } },
  86. { (char *)"FONT_ASCENT", BDF_INTEGER, 1, { 0 } },
  87. { (char *)"FONT_DESCENT", BDF_INTEGER, 1, { 0 } },
  88. { (char *)"FOUNDRY", BDF_ATOM, 1, { 0 } },
  89. { (char *)"FULL_NAME", BDF_ATOM, 1, { 0 } },
  90. { (char *)"ITALIC_ANGLE", BDF_INTEGER, 1, { 0 } },
  91. { (char *)"MAX_SPACE", BDF_INTEGER, 1, { 0 } },
  92. { (char *)"MIN_SPACE", BDF_INTEGER, 1, { 0 } },
  93. { (char *)"NORM_SPACE", BDF_INTEGER, 1, { 0 } },
  94. { (char *)"NOTICE", BDF_ATOM, 1, { 0 } },
  95. { (char *)"PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },
  96. { (char *)"POINT_SIZE", BDF_INTEGER, 1, { 0 } },
  97. { (char *)"QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },
  98. { (char *)"RAW_ASCENT", BDF_INTEGER, 1, { 0 } },
  99. { (char *)"RAW_AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },
  100. { (char *)"RAW_AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },
  101. { (char *)"RAW_AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },
  102. { (char *)"RAW_CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },
  103. { (char *)"RAW_DESCENT", BDF_INTEGER, 1, { 0 } },
  104. { (char *)"RAW_END_SPACE", BDF_INTEGER, 1, { 0 } },
  105. { (char *)"RAW_FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },
  106. { (char *)"RAW_MAX_SPACE", BDF_INTEGER, 1, { 0 } },
  107. { (char *)"RAW_MIN_SPACE", BDF_INTEGER, 1, { 0 } },
  108. { (char *)"RAW_NORM_SPACE", BDF_INTEGER, 1, { 0 } },
  109. { (char *)"RAW_PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },
  110. { (char *)"RAW_POINT_SIZE", BDF_INTEGER, 1, { 0 } },
  111. { (char *)"RAW_PIXELSIZE", BDF_INTEGER, 1, { 0 } },
  112. { (char *)"RAW_POINTSIZE", BDF_INTEGER, 1, { 0 } },
  113. { (char *)"RAW_QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },
  114. { (char *)"RAW_SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },
  115. { (char *)"RAW_STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },
  116. { (char *)"RAW_STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },
  117. { (char *)"RAW_SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
  118. { (char *)"RAW_SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },
  119. { (char *)"RAW_SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
  120. { (char *)"RAW_SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
  121. { (char *)"RAW_SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },
  122. { (char *)"RAW_SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
  123. { (char *)"RAW_UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },
  124. { (char *)"RAW_UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },
  125. { (char *)"RAW_X_HEIGHT", BDF_INTEGER, 1, { 0 } },
  126. { (char *)"RELATIVE_SETWIDTH", BDF_CARDINAL, 1, { 0 } },
  127. { (char *)"RELATIVE_WEIGHT", BDF_CARDINAL, 1, { 0 } },
  128. { (char *)"RESOLUTION", BDF_INTEGER, 1, { 0 } },
  129. { (char *)"RESOLUTION_X", BDF_CARDINAL, 1, { 0 } },
  130. { (char *)"RESOLUTION_Y", BDF_CARDINAL, 1, { 0 } },
  131. { (char *)"SETWIDTH_NAME", BDF_ATOM, 1, { 0 } },
  132. { (char *)"SLANT", BDF_ATOM, 1, { 0 } },
  133. { (char *)"SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },
  134. { (char *)"SPACING", BDF_ATOM, 1, { 0 } },
  135. { (char *)"STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },
  136. { (char *)"STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },
  137. { (char *)"SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
  138. { (char *)"SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },
  139. { (char *)"SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
  140. { (char *)"SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
  141. { (char *)"SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },
  142. { (char *)"SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
  143. { (char *)"UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },
  144. { (char *)"UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },
  145. { (char *)"WEIGHT", BDF_CARDINAL, 1, { 0 } },
  146. { (char *)"WEIGHT_NAME", BDF_ATOM, 1, { 0 } },
  147. { (char *)"X_HEIGHT", BDF_INTEGER, 1, { 0 } },
  148. { (char *)"_MULE_BASELINE_OFFSET", BDF_INTEGER, 1, { 0 } },
  149. { (char *)"_MULE_RELATIVE_COMPOSE", BDF_INTEGER, 1, { 0 } },
  150. };
  151. static const unsigned long
  152. _num_bdf_properties = sizeof ( _bdf_properties ) /
  153. sizeof ( _bdf_properties[0] );
  154. /* Auto correction messages. */
  155. #define ACMSG1 "FONT_ASCENT property missing. " \
  156. "Added `FONT_ASCENT %hd'.\n"
  157. #define ACMSG2 "FONT_DESCENT property missing. " \
  158. "Added `FONT_DESCENT %hd'.\n"
  159. #define ACMSG3 "Font width != actual width. Old: %hd New: %hd.\n"
  160. #define ACMSG4 "Font left bearing != actual left bearing. " \
  161. "Old: %hd New: %hd.\n"
  162. #define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd.\n"
  163. #define ACMSG6 "Font descent != actual descent. Old: %hd New: %hd.\n"
  164. #define ACMSG7 "Font height != actual height. Old: %hd New: %hd.\n"
  165. #define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made.\n"
  166. #define ACMSG9 "SWIDTH field missing at line %ld. Set automatically.\n"
  167. #define ACMSG10 "DWIDTH field missing at line %ld. Set to glyph width.\n"
  168. #define ACMSG11 "SIZE bits per pixel field adjusted to %hd.\n"
  169. #define ACMSG12 "Duplicate encoding %ld (%s) changed to unencoded.\n"
  170. #define ACMSG13 "Glyph %ld extra rows removed.\n"
  171. #define ACMSG14 "Glyph %ld extra columns removed.\n"
  172. #define ACMSG15 "Incorrect glyph count: %ld indicated but %ld found.\n"
  173. #define ACMSG16 "Glyph %ld missing columns padded with zero bits.\n"
  174. /* Error messages. */
  175. #define ERRMSG1 "[line %ld] Missing `%s' line.\n"
  176. #define ERRMSG2 "[line %ld] Font header corrupted or missing fields.\n"
  177. #define ERRMSG3 "[line %ld] Font glyphs corrupted or missing fields.\n"
  178. #define ERRMSG4 "[line %ld] BBX too big.\n"
  179. #define ERRMSG5 "[line %ld] `%s' value too big.\n"
  180. #define ERRMSG6 "[line %ld] Input line too long.\n"
  181. #define ERRMSG7 "[line %ld] Font name too long.\n"
  182. #define ERRMSG8 "[line %ld] Invalid `%s' value.\n"
  183. #define ERRMSG9 "[line %ld] Invalid keyword.\n"
  184. /* Debug messages. */
  185. #define DBGMSG1 " [%6ld] %s" /* no \n */
  186. #define DBGMSG2 " (0x%lX)\n"
  187. /*************************************************************************/
  188. /* */
  189. /* Hash table utilities for the properties. */
  190. /* */
  191. /*************************************************************************/
  192. /* XXX: Replace this with FreeType's hash functions */
  193. #define INITIAL_HT_SIZE 241
  194. typedef void
  195. (*hash_free_func)( hashnode node );
  196. static hashnode*
  197. hash_bucket( const char* key,
  198. hashtable* ht )
  199. {
  200. const char* kp = key;
  201. unsigned long res = 0;
  202. hashnode* bp = ht->table, *ndp;
  203. /* Mocklisp hash function. */
  204. while ( *kp )
  205. res = ( res << 5 ) - res + *kp++;
  206. ndp = bp + ( res % ht->size );
  207. while ( *ndp )
  208. {
  209. kp = (*ndp)->key;
  210. if ( kp[0] == key[0] && ft_strcmp( kp, key ) == 0 )
  211. break;
  212. ndp--;
  213. if ( ndp < bp )
  214. ndp = bp + ( ht->size - 1 );
  215. }
  216. return ndp;
  217. }
  218. static FT_Error
  219. hash_rehash( hashtable* ht,
  220. FT_Memory memory )
  221. {
  222. hashnode* obp = ht->table, *bp, *nbp;
  223. int i, sz = ht->size;
  224. FT_Error error = BDF_Err_Ok;
  225. ht->size <<= 1;
  226. ht->limit = ht->size / 3;
  227. if ( FT_NEW_ARRAY( ht->table, ht->size ) )
  228. goto Exit;
  229. for ( i = 0, bp = obp; i < sz; i++, bp++ )
  230. {
  231. if ( *bp )
  232. {
  233. nbp = hash_bucket( (*bp)->key, ht );
  234. *nbp = *bp;
  235. }
  236. }
  237. FT_FREE( obp );
  238. Exit:
  239. return error;
  240. }
  241. static FT_Error
  242. hash_init( hashtable* ht,
  243. FT_Memory memory )
  244. {
  245. int sz = INITIAL_HT_SIZE;
  246. FT_Error error = BDF_Err_Ok;
  247. ht->size = sz;
  248. ht->limit = sz / 3;
  249. ht->used = 0;
  250. if ( FT_NEW_ARRAY( ht->table, sz ) )
  251. goto Exit;
  252. Exit:
  253. return error;
  254. }
  255. static void
  256. hash_free( hashtable* ht,
  257. FT_Memory memory )
  258. {
  259. if ( ht != 0 )
  260. {
  261. int i, sz = ht->size;
  262. hashnode* bp = ht->table;
  263. for ( i = 0; i < sz; i++, bp++ )
  264. FT_FREE( *bp );
  265. FT_FREE( ht->table );
  266. }
  267. }
  268. static FT_Error
  269. hash_insert( char* key,
  270. size_t data,
  271. hashtable* ht,
  272. FT_Memory memory )
  273. {
  274. hashnode nn, *bp = hash_bucket( key, ht );
  275. FT_Error error = BDF_Err_Ok;
  276. nn = *bp;
  277. if ( !nn )
  278. {
  279. if ( FT_NEW( nn ) )
  280. goto Exit;
  281. *bp = nn;
  282. nn->key = key;
  283. nn->data = data;
  284. if ( ht->used >= ht->limit )
  285. {
  286. error = hash_rehash( ht, memory );
  287. if ( error )
  288. goto Exit;
  289. }
  290. ht->used++;
  291. }
  292. else
  293. nn->data = data;
  294. Exit:
  295. return error;
  296. }
  297. static hashnode
  298. hash_lookup( const char* key,
  299. hashtable* ht )
  300. {
  301. hashnode *np = hash_bucket( key, ht );
  302. return *np;
  303. }
  304. /*************************************************************************/
  305. /* */
  306. /* Utility types and functions. */
  307. /* */
  308. /*************************************************************************/
  309. /* Function type for parsing lines of a BDF font. */
  310. typedef FT_Error
  311. (*_bdf_line_func_t)( char* line,
  312. unsigned long linelen,
  313. unsigned long lineno,
  314. void* call_data,
  315. void* client_data );
  316. /* List structure for splitting lines into fields. */
  317. typedef struct _bdf_list_t_
  318. {
  319. char** field;
  320. unsigned long size;
  321. unsigned long used;
  322. FT_Memory memory;
  323. } _bdf_list_t;
  324. /* Structure used while loading BDF fonts. */
  325. typedef struct _bdf_parse_t_
  326. {
  327. unsigned long flags;
  328. unsigned long cnt;
  329. unsigned long row;
  330. short minlb;
  331. short maxlb;
  332. short maxrb;
  333. short maxas;
  334. short maxds;
  335. short rbearing;
  336. char* glyph_name;
  337. long glyph_enc;
  338. bdf_font_t* font;
  339. bdf_options_t* opts;
  340. unsigned long have[34816]; /* must be in sync with `nmod' and `umod' */
  341. /* arrays from `bdf_font_t' structure */
  342. _bdf_list_t list;
  343. FT_Memory memory;
  344. } _bdf_parse_t;
  345. #define setsbit( m, cc ) \
  346. ( m[(FT_Byte)(cc) >> 3] |= (FT_Byte)( 1 << ( (cc) & 7 ) ) )
  347. #define sbitset( m, cc ) \
  348. ( m[(FT_Byte)(cc) >> 3] & ( 1 << ( (cc) & 7 ) ) )
  349. static void
  350. _bdf_list_init( _bdf_list_t* list,
  351. FT_Memory memory )
  352. {
  353. FT_ZERO( list );
  354. list->memory = memory;
  355. }
  356. static void
  357. _bdf_list_done( _bdf_list_t* list )
  358. {
  359. FT_Memory memory = list->memory;
  360. if ( memory )
  361. {
  362. FT_FREE( list->field );
  363. FT_ZERO( list );
  364. }
  365. }
  366. static FT_Error
  367. _bdf_list_ensure( _bdf_list_t* list,
  368. unsigned long num_items ) /* same as _bdf_list_t.used */
  369. {
  370. FT_Error error = BDF_Err_Ok;
  371. if ( num_items > list->size )
  372. {
  373. unsigned long oldsize = list->size; /* same as _bdf_list_t.size */
  374. unsigned long newsize = oldsize + ( oldsize >> 1 ) + 5;
  375. unsigned long bigsize = (unsigned long)( FT_INT_MAX / sizeof ( char* ) );
  376. FT_Memory memory = list->memory;
  377. if ( oldsize == bigsize )
  378. {
  379. error = BDF_Err_Out_Of_Memory;
  380. goto Exit;
  381. }
  382. else if ( newsize < oldsize || newsize > bigsize )
  383. newsize = bigsize;
  384. if ( FT_RENEW_ARRAY( list->field, oldsize, newsize ) )
  385. goto Exit;
  386. list->size = newsize;
  387. }
  388. Exit:
  389. return error;
  390. }
  391. static void
  392. _bdf_list_shift( _bdf_list_t* list,
  393. unsigned long n )
  394. {
  395. unsigned long i, u;
  396. if ( list == 0 || list->used == 0 || n == 0 )
  397. return;
  398. if ( n >= list->used )
  399. {
  400. list->used = 0;
  401. return;
  402. }
  403. for ( u = n, i = 0; u < list->used; i++, u++ )
  404. list->field[i] = list->field[u];
  405. list->used -= n;
  406. }
  407. /* An empty string for empty fields. */
  408. static const char empty[1] = { 0 }; /* XXX eliminate this */
  409. static char *
  410. _bdf_list_join( _bdf_list_t* list,
  411. int c,
  412. unsigned long *alen )
  413. {
  414. unsigned long i, j;
  415. char *fp, *dp;
  416. *alen = 0;
  417. if ( list == 0 || list->used == 0 )
  418. return 0;
  419. dp = list->field[0];
  420. for ( i = j = 0; i < list->used; i++ )
  421. {
  422. fp = list->field[i];
  423. while ( *fp )
  424. dp[j++] = *fp++;
  425. if ( i + 1 < list->used )
  426. dp[j++] = (char)c;
  427. }
  428. if ( dp != empty )
  429. dp[j] = 0;
  430. *alen = j;
  431. return dp;
  432. }
  433. /* The code below ensures that we have at least 4 + 1 `field' */
  434. /* elements in `list' (which are possibly NULL) so that we */
  435. /* don't have to check the number of fields in most cases. */
  436. static FT_Error
  437. _bdf_list_split( _bdf_list_t* list,
  438. char* separators,
  439. char* line,
  440. unsigned long linelen )
  441. {
  442. int mult, final_empty;
  443. char *sp, *ep, *end;
  444. char seps[32];
  445. FT_Error error = BDF_Err_Ok;
  446. /* Initialize the list. */
  447. list->used = 0;
  448. if ( list->size )
  449. {
  450. list->field[0] = (char*)empty;
  451. list->field[1] = (char*)empty;
  452. list->field[2] = (char*)empty;
  453. list->field[3] = (char*)empty;
  454. }
  455. /* If the line is empty, then simply return. */
  456. if ( linelen == 0 || line[0] == 0 )
  457. goto Exit;
  458. /* In the original code, if the `separators' parameter is NULL or */
  459. /* empty, the list is split into individual bytes. We don't need */
  460. /* this, so an error is signaled. */
  461. if ( separators == 0 || *separators == 0 )
  462. {
  463. error = BDF_Err_Invalid_Argument;
  464. goto Exit;
  465. }
  466. /* Prepare the separator bitmap. */
  467. FT_MEM_ZERO( seps, 32 );
  468. /* If the very last character of the separator string is a plus, then */
  469. /* set the `mult' flag to indicate that multiple separators should be */
  470. /* collapsed into one. */
  471. for ( mult = 0, sp = separators; sp && *sp; sp++ )
  472. {
  473. if ( *sp == '+' && *( sp + 1 ) == 0 )
  474. mult = 1;
  475. else
  476. setsbit( seps, *sp );
  477. }
  478. /* Break the line up into fields. */
  479. for ( final_empty = 0, sp = ep = line, end = sp + linelen;
  480. sp < end && *sp; )
  481. {
  482. /* Collect everything that is not a separator. */
  483. for ( ; *ep && !sbitset( seps, *ep ); ep++ )
  484. ;
  485. /* Resize the list if necessary. */
  486. if ( list->used == list->size )
  487. {
  488. error = _bdf_list_ensure( list, list->used + 1 );
  489. if ( error )
  490. goto Exit;
  491. }
  492. /* Assign the field appropriately. */
  493. list->field[list->used++] = ( ep > sp ) ? sp : (char*)empty;
  494. sp = ep;
  495. if ( mult )
  496. {
  497. /* If multiple separators should be collapsed, do it now by */
  498. /* setting all the separator characters to 0. */
  499. for ( ; *ep && sbitset( seps, *ep ); ep++ )
  500. *ep = 0;
  501. }
  502. else if ( *ep != 0 )
  503. /* Don't collapse multiple separators by making them 0, so just */
  504. /* make the one encountered 0. */
  505. *ep++ = 0;
  506. final_empty = ( ep > sp && *ep == 0 );
  507. sp = ep;
  508. }
  509. /* Finally, NULL-terminate the list. */
  510. if ( list->used + final_empty >= list->size )
  511. {
  512. error = _bdf_list_ensure( list, list->used + final_empty + 1 );
  513. if ( error )
  514. goto Exit;
  515. }
  516. if ( final_empty )
  517. list->field[list->used++] = (char*)empty;
  518. list->field[list->used] = 0;
  519. Exit:
  520. return error;
  521. }
  522. #define NO_SKIP 256 /* this value cannot be stored in a 'char' */
  523. static FT_Error
  524. _bdf_readstream( FT_Stream stream,
  525. _bdf_line_func_t callback,
  526. void* client_data,
  527. unsigned long *lno )
  528. {
  529. _bdf_line_func_t cb;
  530. unsigned long lineno, buf_size;
  531. int refill, hold, to_skip;
  532. ptrdiff_t bytes, start, end, cursor, avail;
  533. char* buf = 0;
  534. FT_Memory memory = stream->memory;
  535. FT_Error error = BDF_Err_Ok;
  536. if ( callback == 0 )
  537. {
  538. error = BDF_Err_Invalid_Argument;
  539. goto Exit;
  540. }
  541. /* initial size and allocation of the input buffer */
  542. buf_size = 1024;
  543. if ( FT_NEW_ARRAY( buf, buf_size ) )
  544. goto Exit;
  545. cb = callback;
  546. lineno = 1;
  547. buf[0] = 0;
  548. start = 0;
  549. end = 0;
  550. avail = 0;
  551. cursor = 0;
  552. refill = 1;
  553. to_skip = NO_SKIP;
  554. bytes = 0; /* make compiler happy */
  555. for (;;)
  556. {
  557. if ( refill )
  558. {
  559. bytes = (ptrdiff_t)FT_Stream_TryRead(
  560. stream, (FT_Byte*)buf + cursor,
  561. (FT_ULong)( buf_size - cursor ) );
  562. avail = cursor + bytes;
  563. cursor = 0;
  564. refill = 0;
  565. }
  566. end = start;
  567. /* should we skip an optional character like \n or \r? */
  568. if ( start < avail && buf[start] == to_skip )
  569. {
  570. start += 1;
  571. to_skip = NO_SKIP;
  572. continue;
  573. }
  574. /* try to find the end of the line */
  575. while ( end < avail && buf[end] != '\n' && buf[end] != '\r' )
  576. end++;
  577. /* if we hit the end of the buffer, try shifting its content */
  578. /* or even resizing it */
  579. if ( end >= avail )
  580. {
  581. if ( bytes == 0 ) /* last line in file doesn't end in \r or \n */
  582. break; /* ignore it then exit */
  583. if ( start == 0 )
  584. {
  585. /* this line is definitely too long; try resizing the input */
  586. /* buffer a bit to handle it. */
  587. FT_ULong new_size;
  588. if ( buf_size >= 65536UL ) /* limit ourselves to 64KByte */
  589. {
  590. FT_ERROR(( "_bdf_readstream: " ERRMSG6, lineno ));
  591. error = BDF_Err_Invalid_Argument;
  592. goto Exit;
  593. }
  594. new_size = buf_size * 2;
  595. if ( FT_RENEW_ARRAY( buf, buf_size, new_size ) )
  596. goto Exit;
  597. cursor = buf_size;
  598. buf_size = new_size;
  599. }
  600. else
  601. {
  602. bytes = avail - start;
  603. FT_MEM_COPY( buf, buf + start, bytes );
  604. cursor = bytes;
  605. avail -= bytes;
  606. start = 0;
  607. }
  608. refill = 1;
  609. continue;
  610. }
  611. /* Temporarily NUL-terminate the line. */
  612. hold = buf[end];
  613. buf[end] = 0;
  614. /* XXX: Use encoding independent value for 0x1a */
  615. if ( buf[start] != '#' && buf[start] != 0x1a && end > start )
  616. {
  617. error = (*cb)( buf + start, end - start, lineno,
  618. (void*)&cb, client_data );
  619. /* Redo if we have encountered CHARS without properties. */
  620. if ( error == -1 )
  621. error = (*cb)( buf + start, end - start, lineno,
  622. (void*)&cb, client_data );
  623. if ( error )
  624. break;
  625. }
  626. lineno += 1;
  627. buf[end] = (char)hold;
  628. start = end + 1;
  629. if ( hold == '\n' )
  630. to_skip = '\r';
  631. else if ( hold == '\r' )
  632. to_skip = '\n';
  633. else
  634. to_skip = NO_SKIP;
  635. }
  636. *lno = lineno;
  637. Exit:
  638. FT_FREE( buf );
  639. return error;
  640. }
  641. /* XXX: make this work with EBCDIC also */
  642. static const unsigned char a2i[128] =
  643. {
  644. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  645. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  646. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  647. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  648. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00,
  649. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,
  650. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  651. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  652. 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  653. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  654. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  655. };
  656. static const unsigned char odigits[32] =
  657. {
  658. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  659. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  660. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  661. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  662. };
  663. static const unsigned char ddigits[32] =
  664. {
  665. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
  666. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  667. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  668. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  669. };
  670. static const unsigned char hdigits[32] =
  671. {
  672. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
  673. 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
  674. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  675. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  676. };
  677. #define isdigok( m, d ) (m[(d) >> 3] & ( 1 << ( (d) & 7 ) ) )
  678. /* Routine to convert an ASCII string into an unsigned long integer. */
  679. static unsigned long
  680. _bdf_atoul( char* s,
  681. char** end,
  682. int base )
  683. {
  684. unsigned long v;
  685. const unsigned char* dmap;
  686. if ( s == 0 || *s == 0 )
  687. return 0;
  688. /* Make sure the radix is something recognizable. Default to 10. */
  689. switch ( base )
  690. {
  691. case 8:
  692. dmap = odigits;
  693. break;
  694. case 16:
  695. dmap = hdigits;
  696. break;
  697. default:
  698. base = 10;
  699. dmap = ddigits;
  700. break;
  701. }
  702. /* Check for the special hex prefix. */
  703. if ( *s == '0' &&
  704. ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
  705. {
  706. base = 16;
  707. dmap = hdigits;
  708. s += 2;
  709. }
  710. for ( v = 0; isdigok( dmap, *s ); s++ )
  711. v = v * base + a2i[(int)*s];
  712. if ( end != 0 )
  713. *end = s;
  714. return v;
  715. }
  716. /* Routine to convert an ASCII string into an signed long integer. */
  717. static long
  718. _bdf_atol( char* s,
  719. char** end,
  720. int base )
  721. {
  722. long v, neg;
  723. const unsigned char* dmap;
  724. if ( s == 0 || *s == 0 )
  725. return 0;
  726. /* Make sure the radix is something recognizable. Default to 10. */
  727. switch ( base )
  728. {
  729. case 8:
  730. dmap = odigits;
  731. break;
  732. case 16:
  733. dmap = hdigits;
  734. break;
  735. default:
  736. base = 10;
  737. dmap = ddigits;
  738. break;
  739. }
  740. /* Check for a minus sign. */
  741. neg = 0;
  742. if ( *s == '-' )
  743. {
  744. s++;
  745. neg = 1;
  746. }
  747. /* Check for the special hex prefix. */
  748. if ( *s == '0' &&
  749. ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
  750. {
  751. base = 16;
  752. dmap = hdigits;
  753. s += 2;
  754. }
  755. for ( v = 0; isdigok( dmap, *s ); s++ )
  756. v = v * base + a2i[(int)*s];
  757. if ( end != 0 )
  758. *end = s;
  759. return ( !neg ) ? v : -v;
  760. }
  761. /* Routine to convert an ASCII string into an signed short integer. */
  762. static short
  763. _bdf_atos( char* s,
  764. char** end,
  765. int base )
  766. {
  767. short v, neg;
  768. const unsigned char* dmap;
  769. if ( s == 0 || *s == 0 )
  770. return 0;
  771. /* Make sure the radix is something recognizable. Default to 10. */
  772. switch ( base )
  773. {
  774. case 8:
  775. dmap = odigits;
  776. break;
  777. case 16:
  778. dmap = hdigits;
  779. break;
  780. default:
  781. base = 10;
  782. dmap = ddigits;
  783. break;
  784. }
  785. /* Check for a minus. */
  786. neg = 0;
  787. if ( *s == '-' )
  788. {
  789. s++;
  790. neg = 1;
  791. }
  792. /* Check for the special hex prefix. */
  793. if ( *s == '0' &&
  794. ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
  795. {
  796. base = 16;
  797. dmap = hdigits;
  798. s += 2;
  799. }
  800. for ( v = 0; isdigok( dmap, *s ); s++ )
  801. v = (short)( v * base + a2i[(int)*s] );
  802. if ( end != 0 )
  803. *end = s;
  804. return (short)( ( !neg ) ? v : -v );
  805. }
  806. /* Routine to compare two glyphs by encoding so they can be sorted. */
  807. static int
  808. by_encoding( const void* a,
  809. const void* b )
  810. {
  811. bdf_glyph_t *c1, *c2;
  812. c1 = (bdf_glyph_t *)a;
  813. c2 = (bdf_glyph_t *)b;
  814. if ( c1->encoding < c2->encoding )
  815. return -1;
  816. if ( c1->encoding > c2->encoding )
  817. return 1;
  818. return 0;
  819. }
  820. static FT_Error
  821. bdf_create_property( char* name,
  822. int format,
  823. bdf_font_t* font )
  824. {
  825. size_t n;
  826. bdf_property_t* p;
  827. FT_Memory memory = font->memory;
  828. FT_Error error = BDF_Err_Ok;
  829. /* First check whether the property has */
  830. /* already been added or not. If it has, then */
  831. /* simply ignore it. */
  832. if ( hash_lookup( name, &(font->proptbl) ) )
  833. goto Exit;
  834. if ( FT_RENEW_ARRAY( font->user_props,
  835. font->nuser_props,
  836. font->nuser_props + 1 ) )
  837. goto Exit;
  838. p = font->user_props + font->nuser_props;
  839. FT_ZERO( p );
  840. n = ft_strlen( name ) + 1;
  841. if ( n > FT_ULONG_MAX )
  842. return BDF_Err_Invalid_Argument;
  843. if ( FT_NEW_ARRAY( p->name, n ) )
  844. goto Exit;
  845. FT_MEM_COPY( (char *)p->name, name, n );
  846. p->format = format;
  847. p->builtin = 0;
  848. n = _num_bdf_properties + font->nuser_props;
  849. error = hash_insert( p->name, n, &(font->proptbl), memory );
  850. if ( error )
  851. goto Exit;
  852. font->nuser_props++;
  853. Exit:
  854. return error;
  855. }
  856. FT_LOCAL_DEF( bdf_property_t * )
  857. bdf_get_property( char* name,
  858. bdf_font_t* font )
  859. {
  860. hashnode hn;
  861. size_t propid;
  862. if ( name == 0 || *name == 0 )
  863. return 0;
  864. if ( ( hn = hash_lookup( name, &(font->proptbl) ) ) == 0 )
  865. return 0;
  866. propid = hn->data;
  867. if ( propid >= _num_bdf_properties )
  868. return font->user_props + ( propid - _num_bdf_properties );
  869. return (bdf_property_t*)_bdf_properties + propid;
  870. }
  871. /*************************************************************************/
  872. /* */
  873. /* BDF font file parsing flags and functions. */
  874. /* */
  875. /*************************************************************************/
  876. /* Parse flags. */
  877. #define _BDF_START 0x0001
  878. #define _BDF_FONT_NAME 0x0002
  879. #define _BDF_SIZE 0x0004
  880. #define _BDF_FONT_BBX 0x0008
  881. #define _BDF_PROPS 0x0010
  882. #define _BDF_GLYPHS 0x0020
  883. #define _BDF_GLYPH 0x0040
  884. #define _BDF_ENCODING 0x0080
  885. #define _BDF_SWIDTH 0x0100
  886. #define _BDF_DWIDTH 0x0200
  887. #define _BDF_BBX 0x0400
  888. #define _BDF_BITMAP 0x0800
  889. #define _BDF_SWIDTH_ADJ 0x1000
  890. #define _BDF_GLYPH_BITS ( _BDF_GLYPH | \
  891. _BDF_ENCODING | \
  892. _BDF_SWIDTH | \
  893. _BDF_DWIDTH | \
  894. _BDF_BBX | \
  895. _BDF_BITMAP )
  896. #define _BDF_GLYPH_WIDTH_CHECK 0x40000000UL
  897. #define _BDF_GLYPH_HEIGHT_CHECK 0x80000000UL
  898. static FT_Error
  899. _bdf_add_comment( bdf_font_t* font,
  900. char* comment,
  901. unsigned long len )
  902. {
  903. char* cp;
  904. FT_Memory memory = font->memory;
  905. FT_Error error = BDF_Err_Ok;
  906. if ( FT_RENEW_ARRAY( font->comments,
  907. font->comments_len,
  908. font->comments_len + len + 1 ) )
  909. goto Exit;
  910. cp = font->comments + font->comments_len;
  911. FT_MEM_COPY( cp, comment, len );
  912. cp[len] = '\n';
  913. font->comments_len += len + 1;
  914. Exit:
  915. return error;
  916. }
  917. /* Set the spacing from the font name if it exists, or set it to the */
  918. /* default specified in the options. */
  919. static FT_Error
  920. _bdf_set_default_spacing( bdf_font_t* font,
  921. bdf_options_t* opts,
  922. unsigned long lineno )
  923. {
  924. size_t len;
  925. char name[256];
  926. _bdf_list_t list;
  927. FT_Memory memory;
  928. FT_Error error = BDF_Err_Ok;
  929. if ( font == 0 || font->name == 0 || font->name[0] == 0 )
  930. {
  931. error = BDF_Err_Invalid_Argument;
  932. goto Exit;
  933. }
  934. memory = font->memory;
  935. _bdf_list_init( &list, memory );
  936. font->spacing = opts->font_spacing;
  937. len = ft_strlen( font->name ) + 1;
  938. /* Limit ourselves to 256 characters in the font name. */
  939. if ( len >= 256 )
  940. {
  941. FT_ERROR(( "_bdf_set_default_spacing: " ERRMSG7, lineno ));
  942. error = BDF_Err_Invalid_Argument;
  943. goto Exit;
  944. }
  945. FT_MEM_COPY( name, font->name, len );
  946. error = _bdf_list_split( &list, (char *)"-", name, len );
  947. if ( error )
  948. goto Fail;
  949. if ( list.used == 15 )
  950. {
  951. switch ( list.field[11][0] )
  952. {
  953. case 'C':
  954. case 'c':
  955. font->spacing = BDF_CHARCELL;
  956. break;
  957. case 'M':
  958. case 'm':
  959. font->spacing = BDF_MONOWIDTH;
  960. break;
  961. case 'P':
  962. case 'p':
  963. font->spacing = BDF_PROPORTIONAL;
  964. break;
  965. }
  966. }
  967. Fail:
  968. _bdf_list_done( &list );
  969. Exit:
  970. return error;
  971. }
  972. /* Determine whether the property is an atom or not. If it is, then */
  973. /* clean it up so the double quotes are removed if they exist. */
  974. static int
  975. _bdf_is_atom( char* line,
  976. unsigned long linelen,
  977. char** name,
  978. char** value,
  979. bdf_font_t* font )
  980. {
  981. int hold;
  982. char *sp, *ep;
  983. bdf_property_t* p;
  984. *name = sp = ep = line;
  985. while ( *ep && *ep != ' ' && *ep != '\t' )
  986. ep++;
  987. hold = -1;
  988. if ( *ep )
  989. {
  990. hold = *ep;
  991. *ep = 0;
  992. }
  993. p = bdf_get_property( sp, font );
  994. /* Restore the character that was saved before any return can happen. */
  995. if ( hold != -1 )
  996. *ep = (char)hold;
  997. /* If the property exists and is not an atom, just return here. */
  998. if ( p && p->format != BDF_ATOM )
  999. return 0;
  1000. /* The property is an atom. Trim all leading and trailing whitespace */
  1001. /* and double quotes for the atom value. */
  1002. sp = ep;
  1003. ep = line + linelen;
  1004. /* Trim the leading whitespace if it exists. */
  1005. if ( *sp )
  1006. *sp++ = 0;
  1007. while ( *sp &&
  1008. ( *sp == ' ' || *sp == '\t' ) )
  1009. sp++;
  1010. /* Trim the leading double quote if it exists. */
  1011. if ( *sp == '"' )
  1012. sp++;
  1013. *value = sp;
  1014. /* Trim the trailing whitespace if it exists. */
  1015. while ( ep > sp &&
  1016. ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) )
  1017. *--ep = 0;
  1018. /* Trim the trailing double quote if it exists. */
  1019. if ( ep > sp && *( ep - 1 ) == '"' )
  1020. *--ep = 0;
  1021. return 1;
  1022. }
  1023. static FT_Error
  1024. _bdf_add_property( bdf_font_t* font,
  1025. char* name,
  1026. char* value,
  1027. unsigned long lineno )
  1028. {
  1029. size_t propid;
  1030. hashnode hn;
  1031. bdf_property_t *prop, *fp;
  1032. FT_Memory memory = font->memory;
  1033. FT_Error error = BDF_Err_Ok;
  1034. /* First, check whether the property already exists in the font. */
  1035. if ( ( hn = hash_lookup( name, (hashtable *)font->internal ) ) != 0 )
  1036. {
  1037. /* The property already exists in the font, so simply replace */
  1038. /* the value of the property with the current value. */
  1039. fp = font->props + hn->data;
  1040. switch ( fp->format )
  1041. {
  1042. case BDF_ATOM:
  1043. /* Delete the current atom if it exists. */
  1044. FT_FREE( fp->value.atom );
  1045. if ( value && value[0] != 0 )
  1046. {
  1047. if ( FT_STRDUP( fp->value.atom, value ) )
  1048. goto Exit;
  1049. }
  1050. break;
  1051. case BDF_INTEGER:
  1052. fp->value.l = _bdf_atol( value, 0, 10 );
  1053. break;
  1054. case BDF_CARDINAL:
  1055. fp->value.ul = _bdf_atoul( value, 0, 10 );
  1056. break;
  1057. default:
  1058. ;
  1059. }
  1060. goto Exit;
  1061. }
  1062. /* See whether this property type exists yet or not. */
  1063. /* If not, create it. */
  1064. hn = hash_lookup( name, &(font->proptbl) );
  1065. if ( hn == 0 )
  1066. {
  1067. error = bdf_create_property( name, BDF_ATOM, font );
  1068. if ( error )
  1069. goto Exit;
  1070. hn = hash_lookup( name, &(font->proptbl) );
  1071. }
  1072. /* Allocate another property if this is overflow. */
  1073. if ( font->props_used == font->props_size )
  1074. {
  1075. if ( font->props_size == 0 )
  1076. {
  1077. if ( FT_NEW_ARRAY( font->props, 1 ) )
  1078. goto Exit;
  1079. }
  1080. else
  1081. {
  1082. if ( FT_RENEW_ARRAY( font->props,
  1083. font->props_size,
  1084. font->props_size + 1 ) )
  1085. goto Exit;
  1086. }
  1087. fp = font->props + font->props_size;
  1088. FT_MEM_ZERO( fp, sizeof ( bdf_property_t ) );
  1089. font->props_size++;
  1090. }
  1091. propid = hn->data;
  1092. if ( propid >= _num_bdf_properties )
  1093. prop = font->user_props + ( propid - _num_bdf_properties );
  1094. else
  1095. prop = (bdf_property_t*)_bdf_properties + propid;
  1096. fp = font->props + font->props_used;
  1097. fp->name = prop->name;
  1098. fp->format = prop->format;
  1099. fp->builtin = prop->builtin;
  1100. switch ( prop->format )
  1101. {
  1102. case BDF_ATOM:
  1103. fp->value.atom = 0;
  1104. if ( value != 0 && value[0] )
  1105. {
  1106. if ( FT_STRDUP( fp->value.atom, value ) )
  1107. goto Exit;
  1108. }
  1109. break;
  1110. case BDF_INTEGER:
  1111. fp->value.l = _bdf_atol( value, 0, 10 );
  1112. break;
  1113. case BDF_CARDINAL:
  1114. fp->value.ul = _bdf_atoul( value, 0, 10 );
  1115. break;
  1116. }
  1117. /* If the property happens to be a comment, then it doesn't need */
  1118. /* to be added to the internal hash table. */
  1119. if ( ft_memcmp( name, "COMMENT", 7 ) != 0 )
  1120. {
  1121. /* Add the property to the font property table. */
  1122. error = hash_insert( fp->name,
  1123. font->props_used,
  1124. (hashtable *)font->internal,
  1125. memory );
  1126. if ( error )
  1127. goto Exit;
  1128. }
  1129. font->props_used++;
  1130. /* Some special cases need to be handled here. The DEFAULT_CHAR */
  1131. /* property needs to be located if it exists in the property list, the */
  1132. /* FONT_ASCENT and FONT_DESCENT need to be assigned if they are */
  1133. /* present, and the SPACING property should override the default */
  1134. /* spacing. */
  1135. if ( ft_memcmp( name, "DEFAULT_CHAR", 12 ) == 0 )
  1136. font->default_char = fp->value.l;
  1137. else if ( ft_memcmp( name, "FONT_ASCENT", 11 ) == 0 )
  1138. font->font_ascent = fp->value.l;
  1139. else if ( ft_memcmp( name, "FONT_DESCENT", 12 ) == 0 )
  1140. font->font_descent = fp->value.l;
  1141. else if ( ft_memcmp( name, "SPACING", 7 ) == 0 )
  1142. {
  1143. if ( !fp->value.atom )
  1144. {
  1145. FT_ERROR(( "_bdf_add_property: " ERRMSG8, lineno, "SPACING" ));
  1146. error = BDF_Err_Invalid_File_Format;
  1147. goto Exit;
  1148. }
  1149. if ( fp->value.atom[0] == 'p' || fp->value.atom[0] == 'P' )
  1150. font->spacing = BDF_PROPORTIONAL;
  1151. else if ( fp->value.atom[0] == 'm' || fp->value.atom[0] == 'M' )
  1152. font->spacing = BDF_MONOWIDTH;
  1153. else if ( fp->value.atom[0] == 'c' || fp->value.atom[0] == 'C' )
  1154. font->spacing = BDF_CHARCELL;
  1155. }
  1156. Exit:
  1157. return error;
  1158. }
  1159. static const unsigned char nibble_mask[8] =
  1160. {
  1161. 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE
  1162. };
  1163. /* Actually parse the glyph info and bitmaps. */
  1164. static FT_Error
  1165. _bdf_parse_glyphs( char* line,
  1166. unsigned long linelen,
  1167. unsigned long lineno,
  1168. void* call_data,
  1169. void* client_data )
  1170. {
  1171. int c, mask_index;
  1172. char* s;
  1173. unsigned char* bp;
  1174. unsigned long i, slen, nibbles;
  1175. _bdf_parse_t* p;
  1176. bdf_glyph_t* glyph;
  1177. bdf_font_t* font;
  1178. FT_Memory memory;
  1179. FT_Error error = BDF_Err_Ok;
  1180. FT_UNUSED( call_data );
  1181. FT_UNUSED( lineno ); /* only used in debug mode */
  1182. p = (_bdf_parse_t *)client_data;
  1183. font = p->font;
  1184. memory = font->memory;
  1185. /* Check for a comment. */
  1186. if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
  1187. {
  1188. linelen -= 7;
  1189. s = line + 7;
  1190. if ( *s != 0 )
  1191. {
  1192. s++;
  1193. linelen--;
  1194. }
  1195. error = _bdf_add_comment( p->font, s, linelen );
  1196. goto Exit;
  1197. }
  1198. /* The very first thing expected is the number of glyphs. */
  1199. if ( !( p->flags & _BDF_GLYPHS ) )
  1200. {
  1201. if ( ft_memcmp( line, "CHARS", 5 ) != 0 )
  1202. {
  1203. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "CHARS" ));
  1204. error = BDF_Err_Missing_Chars_Field;
  1205. goto Exit;
  1206. }
  1207. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1208. if ( error )
  1209. goto Exit;
  1210. p->cnt = font->glyphs_size = _bdf_atoul( p->list.field[1], 0, 10 );
  1211. /* Make sure the number of glyphs is non-zero. */
  1212. if ( p->cnt == 0 )
  1213. font->glyphs_size = 64;
  1214. /* Limit ourselves to 1,114,112 glyphs in the font (this is the */
  1215. /* number of code points available in Unicode). */
  1216. if ( p->cnt >= 0x110000UL )
  1217. {
  1218. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG5, lineno, "CHARS" ));
  1219. error = BDF_Err_Invalid_Argument;
  1220. goto Exit;
  1221. }
  1222. if ( FT_NEW_ARRAY( font->glyphs, font->glyphs_size ) )
  1223. goto Exit;
  1224. p->flags |= _BDF_GLYPHS;
  1225. goto Exit;
  1226. }
  1227. /* Check for the ENDFONT field. */
  1228. if ( ft_memcmp( line, "ENDFONT", 7 ) == 0 )
  1229. {
  1230. /* Sort the glyphs by encoding. */
  1231. ft_qsort( (char *)font->glyphs,
  1232. font->glyphs_used,
  1233. sizeof ( bdf_glyph_t ),
  1234. by_encoding );
  1235. p->flags &= ~_BDF_START;
  1236. goto Exit;
  1237. }
  1238. /* Check for the ENDCHAR field. */
  1239. if ( ft_memcmp( line, "ENDCHAR", 7 ) == 0 )
  1240. {
  1241. p->glyph_enc = 0;
  1242. p->flags &= ~_BDF_GLYPH_BITS;
  1243. goto Exit;
  1244. }
  1245. /* Check whether a glyph is being scanned but should be */
  1246. /* ignored because it is an unencoded glyph. */
  1247. if ( ( p->flags & _BDF_GLYPH ) &&
  1248. p->glyph_enc == -1 &&
  1249. p->opts->keep_unencoded == 0 )
  1250. goto Exit;
  1251. /* Check for the STARTCHAR field. */
  1252. if ( ft_memcmp( line, "STARTCHAR", 9 ) == 0 )
  1253. {
  1254. /* Set the character name in the parse info first until the */
  1255. /* encoding can be checked for an unencoded character. */
  1256. FT_FREE( p->glyph_name );
  1257. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1258. if ( error )
  1259. goto Exit;
  1260. _bdf_list_shift( &p->list, 1 );
  1261. s = _bdf_list_join( &p->list, ' ', &slen );
  1262. if ( !s )
  1263. {
  1264. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG8, lineno, "STARTCHAR" ));
  1265. error = BDF_Err_Invalid_File_Format;
  1266. goto Exit;
  1267. }
  1268. if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) )
  1269. goto Exit;
  1270. FT_MEM_COPY( p->glyph_name, s, slen + 1 );
  1271. p->flags |= _BDF_GLYPH;
  1272. FT_TRACE4(( DBGMSG1, lineno, s ));
  1273. goto Exit;
  1274. }
  1275. /* Check for the ENCODING field. */
  1276. if ( ft_memcmp( line, "ENCODING", 8 ) == 0 )
  1277. {
  1278. if ( !( p->flags & _BDF_GLYPH ) )
  1279. {
  1280. /* Missing STARTCHAR field. */
  1281. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "STARTCHAR" ));
  1282. error = BDF_Err_Missing_Startchar_Field;
  1283. goto Exit;
  1284. }
  1285. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1286. if ( error )
  1287. goto Exit;
  1288. p->glyph_enc = _bdf_atol( p->list.field[1], 0, 10 );
  1289. /* Normalize negative encoding values. The specification only */
  1290. /* allows -1, but we can be more generous here. */
  1291. if ( p->glyph_enc < -1 )
  1292. p->glyph_enc = -1;
  1293. /* Check for alternative encoding format. */
  1294. if ( p->glyph_enc == -1 && p->list.used > 2 )
  1295. p->glyph_enc = _bdf_atol( p->list.field[2], 0, 10 );
  1296. FT_TRACE4(( DBGMSG2, p->glyph_enc ));
  1297. /* Check that the encoding is in the Unicode range because */
  1298. /* otherwise p->have (a bitmap with static size) overflows. */
  1299. if ( p->glyph_enc > 0 &&
  1300. (size_t)p->glyph_enc >= sizeof ( p->have ) * 8 )
  1301. {
  1302. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG5, lineno, "ENCODING" ));
  1303. error = BDF_Err_Invalid_File_Format;
  1304. goto Exit;
  1305. }
  1306. /* Check whether this encoding has already been encountered. */
  1307. /* If it has then change it to unencoded so it gets added if */
  1308. /* indicated. */
  1309. if ( p->glyph_enc >= 0 )
  1310. {
  1311. if ( _bdf_glyph_modified( p->have, p->glyph_enc ) )
  1312. {
  1313. /* Emit a message saying a glyph has been moved to the */
  1314. /* unencoded area. */
  1315. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG12,
  1316. p->glyph_enc, p->glyph_name ));
  1317. p->glyph_enc = -1;
  1318. font->modified = 1;
  1319. }
  1320. else
  1321. _bdf_set_glyph_modified( p->have, p->glyph_enc );
  1322. }
  1323. if ( p->glyph_enc >= 0 )
  1324. {
  1325. /* Make sure there are enough glyphs allocated in case the */
  1326. /* number of characters happen to be wrong. */
  1327. if ( font->glyphs_used == font->glyphs_size )
  1328. {
  1329. if ( FT_RENEW_ARRAY( font->glyphs,
  1330. font->glyphs_size,
  1331. font->glyphs_size + 64 ) )
  1332. goto Exit;
  1333. font->glyphs_size += 64;
  1334. }
  1335. glyph = font->glyphs + font->glyphs_used++;
  1336. glyph->name = p->glyph_name;
  1337. glyph->encoding = p->glyph_enc;
  1338. /* Reset the initial glyph info. */
  1339. p->glyph_name = 0;
  1340. }
  1341. else
  1342. {
  1343. /* Unencoded glyph. Check whether it should */
  1344. /* be added or not. */
  1345. if ( p->opts->keep_unencoded != 0 )
  1346. {
  1347. /* Allocate the next unencoded glyph. */
  1348. if ( font->unencoded_used == font->unencoded_size )
  1349. {
  1350. if ( FT_RENEW_ARRAY( font->unencoded ,
  1351. font->unencoded_size,
  1352. font->unencoded_size + 4 ) )
  1353. goto Exit;
  1354. font->unencoded_size += 4;
  1355. }
  1356. glyph = font->unencoded + font->unencoded_used;
  1357. glyph->name = p->glyph_name;
  1358. glyph->encoding = font->unencoded_used++;
  1359. }
  1360. else
  1361. /* Free up the glyph name if the unencoded shouldn't be */
  1362. /* kept. */
  1363. FT_FREE( p->glyph_name );
  1364. p->glyph_name = 0;
  1365. }
  1366. /* Clear the flags that might be added when width and height are */
  1367. /* checked for consistency. */
  1368. p->flags &= ~( _BDF_GLYPH_WIDTH_CHECK | _BDF_GLYPH_HEIGHT_CHECK );
  1369. p->flags |= _BDF_ENCODING;
  1370. goto Exit;
  1371. }
  1372. /* Point at the glyph being constructed. */
  1373. if ( p->glyph_enc == -1 )
  1374. glyph = font->unencoded + ( font->unencoded_used - 1 );
  1375. else
  1376. glyph = font->glyphs + ( font->glyphs_used - 1 );
  1377. /* Check whether a bitmap is being constructed. */
  1378. if ( p->flags & _BDF_BITMAP )
  1379. {
  1380. /* If there are more rows than are specified in the glyph metrics, */
  1381. /* ignore the remaining lines. */
  1382. if ( p->row >= (unsigned long)glyph->bbx.height )
  1383. {
  1384. if ( !( p->flags & _BDF_GLYPH_HEIGHT_CHECK ) )
  1385. {
  1386. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG13,