PageRenderTime 74ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/xixs/lua
C | 2692 lines | 1874 code | 540 blank | 278 comment | 479 complexity | 5835ac1e4aa3330cf78332caff1b4c4d MD5 | raw file
Possible License(s): Zlib, BSD-3-Clause, CC0-1.0, GPL-3.0, GPL-2.0, CPL-1.0, MPL-2.0-no-copyleft-exception, LGPL-2.0, LGPL-2.1, LGPL-3.0, 0BSD, Cube
  1. /*
  2. * Copyright 2000 Computing Research Labs, New Mexico State University
  3. * Copyright 2001-2014
  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. /* An auxiliary macro to parse properties, to be used in conditionals. */
  155. /* It behaves like `strncmp' but also tests the following character */
  156. /* whether it is a whitespace or NULL. */
  157. /* `property' is a constant string of length `n' to compare with. */
  158. #define _bdf_strncmp( name, property, n ) \
  159. ( ft_strncmp( name, property, n ) || \
  160. !( name[n] == ' ' || \
  161. name[n] == '\0' || \
  162. name[n] == '\n' || \
  163. name[n] == '\r' || \
  164. name[n] == '\t' ) )
  165. /* Auto correction messages. */
  166. #define ACMSG1 "FONT_ASCENT property missing. " \
  167. "Added `FONT_ASCENT %hd'.\n"
  168. #define ACMSG2 "FONT_DESCENT property missing. " \
  169. "Added `FONT_DESCENT %hd'.\n"
  170. #define ACMSG3 "Font width != actual width. Old: %hd New: %hd.\n"
  171. #define ACMSG4 "Font left bearing != actual left bearing. " \
  172. "Old: %hd New: %hd.\n"
  173. #define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd.\n"
  174. #define ACMSG6 "Font descent != actual descent. Old: %hd New: %hd.\n"
  175. #define ACMSG7 "Font height != actual height. Old: %hd New: %hd.\n"
  176. #define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made.\n"
  177. #define ACMSG9 "SWIDTH field missing at line %ld. Set automatically.\n"
  178. #define ACMSG10 "DWIDTH field missing at line %ld. Set to glyph width.\n"
  179. #define ACMSG11 "SIZE bits per pixel field adjusted to %hd.\n"
  180. #define ACMSG12 "Duplicate encoding %ld (%s) changed to unencoded.\n"
  181. #define ACMSG13 "Glyph %ld extra rows removed.\n"
  182. #define ACMSG14 "Glyph %ld extra columns removed.\n"
  183. #define ACMSG15 "Incorrect glyph count: %ld indicated but %ld found.\n"
  184. #define ACMSG16 "Glyph %ld missing columns padded with zero bits.\n"
  185. /* Error messages. */
  186. #define ERRMSG1 "[line %ld] Missing `%s' line.\n"
  187. #define ERRMSG2 "[line %ld] Font header corrupted or missing fields.\n"
  188. #define ERRMSG3 "[line %ld] Font glyphs corrupted or missing fields.\n"
  189. #define ERRMSG4 "[line %ld] BBX too big.\n"
  190. #define ERRMSG5 "[line %ld] `%s' value too big.\n"
  191. #define ERRMSG6 "[line %ld] Input line too long.\n"
  192. #define ERRMSG7 "[line %ld] Font name too long.\n"
  193. #define ERRMSG8 "[line %ld] Invalid `%s' value.\n"
  194. #define ERRMSG9 "[line %ld] Invalid keyword.\n"
  195. /* Debug messages. */
  196. #define DBGMSG1 " [%6ld] %s" /* no \n */
  197. #define DBGMSG2 " (0x%lX)\n"
  198. /*************************************************************************/
  199. /* */
  200. /* Hash table utilities for the properties. */
  201. /* */
  202. /*************************************************************************/
  203. /* XXX: Replace this with FreeType's hash functions */
  204. #define INITIAL_HT_SIZE 241
  205. typedef void
  206. (*hash_free_func)( hashnode node );
  207. static hashnode*
  208. hash_bucket( const char* key,
  209. hashtable* ht )
  210. {
  211. const char* kp = key;
  212. unsigned long res = 0;
  213. hashnode* bp = ht->table, *ndp;
  214. /* Mocklisp hash function. */
  215. while ( *kp )
  216. res = ( res << 5 ) - res + (unsigned long)*kp++;
  217. ndp = bp + ( res % ht->size );
  218. while ( *ndp )
  219. {
  220. kp = (*ndp)->key;
  221. if ( kp[0] == key[0] && ft_strcmp( kp, key ) == 0 )
  222. break;
  223. ndp--;
  224. if ( ndp < bp )
  225. ndp = bp + ( ht->size - 1 );
  226. }
  227. return ndp;
  228. }
  229. static FT_Error
  230. hash_rehash( hashtable* ht,
  231. FT_Memory memory )
  232. {
  233. hashnode* obp = ht->table, *bp, *nbp;
  234. unsigned int i, sz = ht->size;
  235. FT_Error error = FT_Err_Ok;
  236. ht->size <<= 1;
  237. ht->limit = ht->size / 3;
  238. if ( FT_NEW_ARRAY( ht->table, ht->size ) )
  239. goto Exit;
  240. for ( i = 0, bp = obp; i < sz; i++, bp++ )
  241. {
  242. if ( *bp )
  243. {
  244. nbp = hash_bucket( (*bp)->key, ht );
  245. *nbp = *bp;
  246. }
  247. }
  248. FT_FREE( obp );
  249. Exit:
  250. return error;
  251. }
  252. static FT_Error
  253. hash_init( hashtable* ht,
  254. FT_Memory memory )
  255. {
  256. unsigned int sz = INITIAL_HT_SIZE;
  257. FT_Error error = FT_Err_Ok;
  258. ht->size = sz;
  259. ht->limit = sz / 3;
  260. ht->used = 0;
  261. if ( FT_NEW_ARRAY( ht->table, sz ) )
  262. goto Exit;
  263. Exit:
  264. return error;
  265. }
  266. static void
  267. hash_free( hashtable* ht,
  268. FT_Memory memory )
  269. {
  270. if ( ht != 0 )
  271. {
  272. unsigned int i, sz = ht->size;
  273. hashnode* bp = ht->table;
  274. for ( i = 0; i < sz; i++, bp++ )
  275. FT_FREE( *bp );
  276. FT_FREE( ht->table );
  277. }
  278. }
  279. static FT_Error
  280. hash_insert( char* key,
  281. size_t data,
  282. hashtable* ht,
  283. FT_Memory memory )
  284. {
  285. hashnode nn;
  286. hashnode* bp = hash_bucket( key, ht );
  287. FT_Error error = FT_Err_Ok;
  288. nn = *bp;
  289. if ( !nn )
  290. {
  291. if ( FT_NEW( nn ) )
  292. goto Exit;
  293. *bp = nn;
  294. nn->key = key;
  295. nn->data = data;
  296. if ( ht->used >= ht->limit )
  297. {
  298. error = hash_rehash( ht, memory );
  299. if ( error )
  300. goto Exit;
  301. }
  302. ht->used++;
  303. }
  304. else
  305. nn->data = data;
  306. Exit:
  307. return error;
  308. }
  309. static hashnode
  310. hash_lookup( const char* key,
  311. hashtable* ht )
  312. {
  313. hashnode *np = hash_bucket( key, ht );
  314. return *np;
  315. }
  316. /*************************************************************************/
  317. /* */
  318. /* Utility types and functions. */
  319. /* */
  320. /*************************************************************************/
  321. /* Function type for parsing lines of a BDF font. */
  322. typedef FT_Error
  323. (*_bdf_line_func_t)( char* line,
  324. unsigned long linelen,
  325. unsigned long lineno,
  326. void* call_data,
  327. void* client_data );
  328. /* List structure for splitting lines into fields. */
  329. typedef struct _bdf_list_t_
  330. {
  331. char** field;
  332. unsigned long size;
  333. unsigned long used;
  334. FT_Memory memory;
  335. } _bdf_list_t;
  336. /* Structure used while loading BDF fonts. */
  337. typedef struct _bdf_parse_t_
  338. {
  339. unsigned long flags;
  340. unsigned long cnt;
  341. unsigned long row;
  342. short minlb;
  343. short maxlb;
  344. short maxrb;
  345. short maxas;
  346. short maxds;
  347. short rbearing;
  348. char* glyph_name;
  349. long glyph_enc;
  350. bdf_font_t* font;
  351. bdf_options_t* opts;
  352. unsigned long have[34816]; /* must be in sync with `nmod' and `umod' */
  353. /* arrays from `bdf_font_t' structure */
  354. _bdf_list_t list;
  355. FT_Memory memory;
  356. } _bdf_parse_t;
  357. #define setsbit( m, cc ) \
  358. ( m[(FT_Byte)(cc) >> 3] |= (FT_Byte)( 1 << ( (cc) & 7 ) ) )
  359. #define sbitset( m, cc ) \
  360. ( m[(FT_Byte)(cc) >> 3] & ( 1 << ( (cc) & 7 ) ) )
  361. static void
  362. _bdf_list_init( _bdf_list_t* list,
  363. FT_Memory memory )
  364. {
  365. FT_ZERO( list );
  366. list->memory = memory;
  367. }
  368. static void
  369. _bdf_list_done( _bdf_list_t* list )
  370. {
  371. FT_Memory memory = list->memory;
  372. if ( memory )
  373. {
  374. FT_FREE( list->field );
  375. FT_ZERO( list );
  376. }
  377. }
  378. static FT_Error
  379. _bdf_list_ensure( _bdf_list_t* list,
  380. unsigned long num_items ) /* same as _bdf_list_t.used */
  381. {
  382. FT_Error error = FT_Err_Ok;
  383. if ( num_items > list->size )
  384. {
  385. unsigned long oldsize = list->size; /* same as _bdf_list_t.size */
  386. unsigned long newsize = oldsize + ( oldsize >> 1 ) + 5;
  387. unsigned long bigsize = (unsigned long)( FT_INT_MAX / sizeof ( char* ) );
  388. FT_Memory memory = list->memory;
  389. if ( oldsize == bigsize )
  390. {
  391. error = FT_THROW( Out_Of_Memory );
  392. goto Exit;
  393. }
  394. else if ( newsize < oldsize || newsize > bigsize )
  395. newsize = bigsize;
  396. if ( FT_RENEW_ARRAY( list->field, oldsize, newsize ) )
  397. goto Exit;
  398. list->size = newsize;
  399. }
  400. Exit:
  401. return error;
  402. }
  403. static void
  404. _bdf_list_shift( _bdf_list_t* list,
  405. unsigned long n )
  406. {
  407. unsigned long i, u;
  408. if ( list == 0 || list->used == 0 || n == 0 )
  409. return;
  410. if ( n >= list->used )
  411. {
  412. list->used = 0;
  413. return;
  414. }
  415. for ( u = n, i = 0; u < list->used; i++, u++ )
  416. list->field[i] = list->field[u];
  417. list->used -= n;
  418. }
  419. /* An empty string for empty fields. */
  420. static const char empty[1] = { 0 }; /* XXX eliminate this */
  421. static char *
  422. _bdf_list_join( _bdf_list_t* list,
  423. int c,
  424. unsigned long *alen )
  425. {
  426. unsigned long i, j;
  427. char* dp;
  428. *alen = 0;
  429. if ( list == 0 || list->used == 0 )
  430. return 0;
  431. dp = list->field[0];
  432. for ( i = j = 0; i < list->used; i++ )
  433. {
  434. char* fp = list->field[i];
  435. while ( *fp )
  436. dp[j++] = *fp++;
  437. if ( i + 1 < list->used )
  438. dp[j++] = (char)c;
  439. }
  440. if ( dp != empty )
  441. dp[j] = 0;
  442. *alen = j;
  443. return dp;
  444. }
  445. /* The code below ensures that we have at least 4 + 1 `field' */
  446. /* elements in `list' (which are possibly NULL) so that we */
  447. /* don't have to check the number of fields in most cases. */
  448. static FT_Error
  449. _bdf_list_split( _bdf_list_t* list,
  450. char* separators,
  451. char* line,
  452. unsigned long linelen )
  453. {
  454. unsigned long final_empty;
  455. int mult;
  456. char *sp, *ep, *end;
  457. char seps[32];
  458. FT_Error error = FT_Err_Ok;
  459. /* Initialize the list. */
  460. list->used = 0;
  461. if ( list->size )
  462. {
  463. list->field[0] = (char*)empty;
  464. list->field[1] = (char*)empty;
  465. list->field[2] = (char*)empty;
  466. list->field[3] = (char*)empty;
  467. list->field[4] = (char*)empty;
  468. }
  469. /* If the line is empty, then simply return. */
  470. if ( linelen == 0 || line[0] == 0 )
  471. goto Exit;
  472. /* In the original code, if the `separators' parameter is NULL or */
  473. /* empty, the list is split into individual bytes. We don't need */
  474. /* this, so an error is signaled. */
  475. if ( separators == 0 || *separators == 0 )
  476. {
  477. error = FT_THROW( Invalid_Argument );
  478. goto Exit;
  479. }
  480. /* Prepare the separator bitmap. */
  481. FT_MEM_ZERO( seps, 32 );
  482. /* If the very last character of the separator string is a plus, then */
  483. /* set the `mult' flag to indicate that multiple separators should be */
  484. /* collapsed into one. */
  485. for ( mult = 0, sp = separators; sp && *sp; sp++ )
  486. {
  487. if ( *sp == '+' && *( sp + 1 ) == 0 )
  488. mult = 1;
  489. else
  490. setsbit( seps, *sp );
  491. }
  492. /* Break the line up into fields. */
  493. for ( final_empty = 0, sp = ep = line, end = sp + linelen;
  494. sp < end && *sp; )
  495. {
  496. /* Collect everything that is not a separator. */
  497. for ( ; *ep && !sbitset( seps, *ep ); ep++ )
  498. ;
  499. /* Resize the list if necessary. */
  500. if ( list->used == list->size )
  501. {
  502. error = _bdf_list_ensure( list, list->used + 1 );
  503. if ( error )
  504. goto Exit;
  505. }
  506. /* Assign the field appropriately. */
  507. list->field[list->used++] = ( ep > sp ) ? sp : (char*)empty;
  508. sp = ep;
  509. if ( mult )
  510. {
  511. /* If multiple separators should be collapsed, do it now by */
  512. /* setting all the separator characters to 0. */
  513. for ( ; *ep && sbitset( seps, *ep ); ep++ )
  514. *ep = 0;
  515. }
  516. else if ( *ep != 0 )
  517. /* Don't collapse multiple separators by making them 0, so just */
  518. /* make the one encountered 0. */
  519. *ep++ = 0;
  520. final_empty = ( ep > sp && *ep == 0 );
  521. sp = ep;
  522. }
  523. /* Finally, NULL-terminate the list. */
  524. if ( list->used + final_empty >= list->size )
  525. {
  526. error = _bdf_list_ensure( list, list->used + final_empty + 1 );
  527. if ( error )
  528. goto Exit;
  529. }
  530. if ( final_empty )
  531. list->field[list->used++] = (char*)empty;
  532. list->field[list->used] = 0;
  533. Exit:
  534. return error;
  535. }
  536. #define NO_SKIP 256 /* this value cannot be stored in a 'char' */
  537. static FT_Error
  538. _bdf_readstream( FT_Stream stream,
  539. _bdf_line_func_t callback,
  540. void* client_data,
  541. unsigned long *lno )
  542. {
  543. _bdf_line_func_t cb;
  544. unsigned long lineno, buf_size;
  545. int refill, hold, to_skip;
  546. ptrdiff_t bytes, start, end, cursor, avail;
  547. char* buf = NULL;
  548. FT_Memory memory = stream->memory;
  549. FT_Error error = FT_Err_Ok;
  550. if ( callback == 0 )
  551. {
  552. error = FT_THROW( Invalid_Argument );
  553. goto Exit;
  554. }
  555. /* initial size and allocation of the input buffer */
  556. buf_size = 1024;
  557. if ( FT_NEW_ARRAY( buf, buf_size ) )
  558. goto Exit;
  559. cb = callback;
  560. lineno = 1;
  561. buf[0] = 0;
  562. start = 0;
  563. avail = 0;
  564. cursor = 0;
  565. refill = 1;
  566. to_skip = NO_SKIP;
  567. bytes = 0; /* make compiler happy */
  568. for (;;)
  569. {
  570. if ( refill )
  571. {
  572. bytes = (ptrdiff_t)FT_Stream_TryRead(
  573. stream, (FT_Byte*)buf + cursor,
  574. buf_size - (unsigned long)cursor );
  575. avail = cursor + bytes;
  576. cursor = 0;
  577. refill = 0;
  578. }
  579. end = start;
  580. /* should we skip an optional character like \n or \r? */
  581. if ( start < avail && buf[start] == to_skip )
  582. {
  583. start += 1;
  584. to_skip = NO_SKIP;
  585. continue;
  586. }
  587. /* try to find the end of the line */
  588. while ( end < avail && buf[end] != '\n' && buf[end] != '\r' )
  589. end++;
  590. /* if we hit the end of the buffer, try shifting its content */
  591. /* or even resizing it */
  592. if ( end >= avail )
  593. {
  594. if ( bytes == 0 ) /* last line in file doesn't end in \r or \n */
  595. break; /* ignore it then exit */
  596. if ( start == 0 )
  597. {
  598. /* this line is definitely too long; try resizing the input */
  599. /* buffer a bit to handle it. */
  600. FT_ULong new_size;
  601. if ( buf_size >= 65536UL ) /* limit ourselves to 64KByte */
  602. {
  603. FT_ERROR(( "_bdf_readstream: " ERRMSG6, lineno ));
  604. error = FT_THROW( Invalid_Argument );
  605. goto Exit;
  606. }
  607. new_size = buf_size * 2;
  608. if ( FT_RENEW_ARRAY( buf, buf_size, new_size ) )
  609. goto Exit;
  610. cursor = (ptrdiff_t)buf_size;
  611. buf_size = new_size;
  612. }
  613. else
  614. {
  615. bytes = avail - start;
  616. FT_MEM_MOVE( buf, buf + start, bytes );
  617. cursor = bytes;
  618. avail -= bytes;
  619. start = 0;
  620. }
  621. refill = 1;
  622. continue;
  623. }
  624. /* Temporarily NUL-terminate the line. */
  625. hold = buf[end];
  626. buf[end] = 0;
  627. /* XXX: Use encoding independent value for 0x1A */
  628. if ( buf[start] != '#' && buf[start] != 0x1A && end > start )
  629. {
  630. error = (*cb)( buf + start, (unsigned long)( end - start ), lineno,
  631. (void*)&cb, client_data );
  632. /* Redo if we have encountered CHARS without properties. */
  633. if ( error == -1 )
  634. error = (*cb)( buf + start, (unsigned long)( end - start ), lineno,
  635. (void*)&cb, client_data );
  636. if ( error )
  637. break;
  638. }
  639. lineno += 1;
  640. buf[end] = (char)hold;
  641. start = end + 1;
  642. if ( hold == '\n' )
  643. to_skip = '\r';
  644. else if ( hold == '\r' )
  645. to_skip = '\n';
  646. else
  647. to_skip = NO_SKIP;
  648. }
  649. *lno = lineno;
  650. Exit:
  651. FT_FREE( buf );
  652. return error;
  653. }
  654. /* XXX: make this work with EBCDIC also */
  655. static const unsigned char a2i[128] =
  656. {
  657. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  658. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  659. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  660. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  661. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00,
  662. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00,
  663. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  664. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  665. 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
  666. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  667. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  668. };
  669. static const unsigned char odigits[32] =
  670. {
  671. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00,
  672. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  673. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  674. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  675. };
  676. static const unsigned char ddigits[32] =
  677. {
  678. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03,
  679. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  680. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  681. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  682. };
  683. static const unsigned char hdigits[32] =
  684. {
  685. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03,
  686. 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00,
  687. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  688. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  689. };
  690. /* Routine to convert an ASCII string into an unsigned long integer. */
  691. static unsigned long
  692. _bdf_atoul( char* s,
  693. char** end,
  694. unsigned int base )
  695. {
  696. unsigned long v;
  697. const unsigned char* dmap;
  698. if ( s == 0 || *s == 0 )
  699. return 0;
  700. /* Make sure the radix is something recognizable. Default to 10. */
  701. switch ( base )
  702. {
  703. case 8:
  704. dmap = odigits;
  705. break;
  706. case 16:
  707. dmap = hdigits;
  708. break;
  709. default:
  710. base = 10;
  711. dmap = ddigits;
  712. break;
  713. }
  714. /* Check for the special hex prefix. */
  715. if ( *s == '0' &&
  716. ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
  717. {
  718. base = 16;
  719. dmap = hdigits;
  720. s += 2;
  721. }
  722. for ( v = 0; sbitset( dmap, *s ); s++ )
  723. v = v * base + a2i[(int)*s];
  724. if ( end != 0 )
  725. *end = s;
  726. return v;
  727. }
  728. /* Routine to convert an ASCII string into a signed long integer. */
  729. static long
  730. _bdf_atol( char* s,
  731. char** end,
  732. int base )
  733. {
  734. long v, neg;
  735. const unsigned char* dmap;
  736. if ( s == 0 || *s == 0 )
  737. return 0;
  738. /* Make sure the radix is something recognizable. Default to 10. */
  739. switch ( base )
  740. {
  741. case 8:
  742. dmap = odigits;
  743. break;
  744. case 16:
  745. dmap = hdigits;
  746. break;
  747. default:
  748. base = 10;
  749. dmap = ddigits;
  750. break;
  751. }
  752. /* Check for a minus sign. */
  753. neg = 0;
  754. if ( *s == '-' )
  755. {
  756. s++;
  757. neg = 1;
  758. }
  759. /* Check for the special hex prefix. */
  760. if ( *s == '0' &&
  761. ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
  762. {
  763. base = 16;
  764. dmap = hdigits;
  765. s += 2;
  766. }
  767. for ( v = 0; sbitset( dmap, *s ); s++ )
  768. v = v * base + a2i[(int)*s];
  769. if ( end != 0 )
  770. *end = s;
  771. return ( !neg ) ? v : -v;
  772. }
  773. /* Routine to convert an ASCII string into an unsigned short integer. */
  774. static unsigned short
  775. _bdf_atous( char* s,
  776. char** end,
  777. unsigned int base )
  778. {
  779. unsigned short v;
  780. const unsigned char* dmap;
  781. if ( s == 0 || *s == 0 )
  782. return 0;
  783. /* Make sure the radix is something recognizable. Default to 10. */
  784. switch ( base )
  785. {
  786. case 8:
  787. dmap = odigits;
  788. break;
  789. case 16:
  790. dmap = hdigits;
  791. break;
  792. default:
  793. base = 10;
  794. dmap = ddigits;
  795. break;
  796. }
  797. /* Check for the special hex prefix. */
  798. if ( *s == '0' &&
  799. ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
  800. {
  801. base = 16;
  802. dmap = hdigits;
  803. s += 2;
  804. }
  805. for ( v = 0; sbitset( dmap, *s ); s++ )
  806. v = (unsigned short)( v * base + a2i[(int)*s] );
  807. if ( end != 0 )
  808. *end = s;
  809. return v;
  810. }
  811. /* Routine to convert an ASCII string into a signed short integer. */
  812. static short
  813. _bdf_atos( char* s,
  814. char** end,
  815. int base )
  816. {
  817. short v, neg;
  818. const unsigned char* dmap;
  819. if ( s == 0 || *s == 0 )
  820. return 0;
  821. /* Make sure the radix is something recognizable. Default to 10. */
  822. switch ( base )
  823. {
  824. case 8:
  825. dmap = odigits;
  826. break;
  827. case 16:
  828. dmap = hdigits;
  829. break;
  830. default:
  831. base = 10;
  832. dmap = ddigits;
  833. break;
  834. }
  835. /* Check for a minus. */
  836. neg = 0;
  837. if ( *s == '-' )
  838. {
  839. s++;
  840. neg = 1;
  841. }
  842. /* Check for the special hex prefix. */
  843. if ( *s == '0' &&
  844. ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
  845. {
  846. base = 16;
  847. dmap = hdigits;
  848. s += 2;
  849. }
  850. for ( v = 0; sbitset( dmap, *s ); s++ )
  851. v = (short)( v * base + a2i[(int)*s] );
  852. if ( end != 0 )
  853. *end = s;
  854. return (short)( ( !neg ) ? v : -v );
  855. }
  856. /* Routine to compare two glyphs by encoding so they can be sorted. */
  857. static int
  858. by_encoding( const void* a,
  859. const void* b )
  860. {
  861. bdf_glyph_t *c1, *c2;
  862. c1 = (bdf_glyph_t *)a;
  863. c2 = (bdf_glyph_t *)b;
  864. if ( c1->encoding < c2->encoding )
  865. return -1;
  866. if ( c1->encoding > c2->encoding )
  867. return 1;
  868. return 0;
  869. }
  870. static FT_Error
  871. bdf_create_property( char* name,
  872. int format,
  873. bdf_font_t* font )
  874. {
  875. size_t n;
  876. bdf_property_t* p;
  877. FT_Memory memory = font->memory;
  878. FT_Error error = FT_Err_Ok;
  879. /* First check whether the property has */
  880. /* already been added or not. If it has, then */
  881. /* simply ignore it. */
  882. if ( hash_lookup( name, &(font->proptbl) ) )
  883. goto Exit;
  884. if ( FT_RENEW_ARRAY( font->user_props,
  885. font->nuser_props,
  886. font->nuser_props + 1 ) )
  887. goto Exit;
  888. p = font->user_props + font->nuser_props;
  889. FT_ZERO( p );
  890. n = ft_strlen( name ) + 1;
  891. if ( n > FT_ULONG_MAX )
  892. return FT_THROW( Invalid_Argument );
  893. if ( FT_NEW_ARRAY( p->name, n ) )
  894. goto Exit;
  895. FT_MEM_COPY( (char *)p->name, name, n );
  896. p->format = format;
  897. p->builtin = 0;
  898. n = _num_bdf_properties + font->nuser_props;
  899. error = hash_insert( p->name, n, &(font->proptbl), memory );
  900. if ( error )
  901. goto Exit;
  902. font->nuser_props++;
  903. Exit:
  904. return error;
  905. }
  906. FT_LOCAL_DEF( bdf_property_t * )
  907. bdf_get_property( char* name,
  908. bdf_font_t* font )
  909. {
  910. hashnode hn;
  911. size_t propid;
  912. if ( name == 0 || *name == 0 )
  913. return 0;
  914. if ( ( hn = hash_lookup( name, &(font->proptbl) ) ) == 0 )
  915. return 0;
  916. propid = hn->data;
  917. if ( propid >= _num_bdf_properties )
  918. return font->user_props + ( propid - _num_bdf_properties );
  919. return (bdf_property_t*)_bdf_properties + propid;
  920. }
  921. /*************************************************************************/
  922. /* */
  923. /* BDF font file parsing flags and functions. */
  924. /* */
  925. /*************************************************************************/
  926. /* Parse flags. */
  927. #define _BDF_START 0x0001U
  928. #define _BDF_FONT_NAME 0x0002U
  929. #define _BDF_SIZE 0x0004U
  930. #define _BDF_FONT_BBX 0x0008U
  931. #define _BDF_PROPS 0x0010U
  932. #define _BDF_GLYPHS 0x0020U
  933. #define _BDF_GLYPH 0x0040U
  934. #define _BDF_ENCODING 0x0080U
  935. #define _BDF_SWIDTH 0x0100U
  936. #define _BDF_DWIDTH 0x0200U
  937. #define _BDF_BBX 0x0400U
  938. #define _BDF_BITMAP 0x0800U
  939. #define _BDF_SWIDTH_ADJ 0x1000U
  940. #define _BDF_GLYPH_BITS ( _BDF_GLYPH | \
  941. _BDF_ENCODING | \
  942. _BDF_SWIDTH | \
  943. _BDF_DWIDTH | \
  944. _BDF_BBX | \
  945. _BDF_BITMAP )
  946. #define _BDF_GLYPH_WIDTH_CHECK 0x40000000UL
  947. #define _BDF_GLYPH_HEIGHT_CHECK 0x80000000UL
  948. static FT_Error
  949. _bdf_add_comment( bdf_font_t* font,
  950. char* comment,
  951. unsigned long len )
  952. {
  953. char* cp;
  954. FT_Memory memory = font->memory;
  955. FT_Error error = FT_Err_Ok;
  956. if ( FT_RENEW_ARRAY( font->comments,
  957. font->comments_len,
  958. font->comments_len + len + 1 ) )
  959. goto Exit;
  960. cp = font->comments + font->comments_len;
  961. FT_MEM_COPY( cp, comment, len );
  962. cp[len] = '\n';
  963. font->comments_len += len + 1;
  964. Exit:
  965. return error;
  966. }
  967. /* Set the spacing from the font name if it exists, or set it to the */
  968. /* default specified in the options. */
  969. static FT_Error
  970. _bdf_set_default_spacing( bdf_font_t* font,
  971. bdf_options_t* opts,
  972. unsigned long lineno )
  973. {
  974. size_t len;
  975. char name[256];
  976. _bdf_list_t list;
  977. FT_Memory memory;
  978. FT_Error error = FT_Err_Ok;
  979. FT_UNUSED( lineno ); /* only used in debug mode */
  980. if ( font == 0 || font->name == 0 || font->name[0] == 0 )
  981. {
  982. error = FT_THROW( Invalid_Argument );
  983. goto Exit;
  984. }
  985. memory = font->memory;
  986. _bdf_list_init( &list, memory );
  987. font->spacing = opts->font_spacing;
  988. len = ft_strlen( font->name ) + 1;
  989. /* Limit ourselves to 256 characters in the font name. */
  990. if ( len >= 256 )
  991. {
  992. FT_ERROR(( "_bdf_set_default_spacing: " ERRMSG7, lineno ));
  993. error = FT_THROW( Invalid_Argument );
  994. goto Exit;
  995. }
  996. FT_MEM_COPY( name, font->name, len );
  997. error = _bdf_list_split( &list, (char *)"-", name, (unsigned long)len );
  998. if ( error )
  999. goto Fail;
  1000. if ( list.used == 15 )
  1001. {
  1002. switch ( list.field[11][0] )
  1003. {
  1004. case 'C':
  1005. case 'c':
  1006. font->spacing = BDF_CHARCELL;
  1007. break;
  1008. case 'M':
  1009. case 'm':
  1010. font->spacing = BDF_MONOWIDTH;
  1011. break;
  1012. case 'P':
  1013. case 'p':
  1014. font->spacing = BDF_PROPORTIONAL;
  1015. break;
  1016. }
  1017. }
  1018. Fail:
  1019. _bdf_list_done( &list );
  1020. Exit:
  1021. return error;
  1022. }
  1023. /* Determine whether the property is an atom or not. If it is, then */
  1024. /* clean it up so the double quotes are removed if they exist. */
  1025. static int
  1026. _bdf_is_atom( char* line,
  1027. unsigned long linelen,
  1028. char** name,
  1029. char** value,
  1030. bdf_font_t* font )
  1031. {
  1032. int hold;
  1033. char *sp, *ep;
  1034. bdf_property_t* p;
  1035. *name = sp = ep = line;
  1036. while ( *ep && *ep != ' ' && *ep != '\t' )
  1037. ep++;
  1038. hold = -1;
  1039. if ( *ep )
  1040. {
  1041. hold = *ep;
  1042. *ep = 0;
  1043. }
  1044. p = bdf_get_property( sp, font );
  1045. /* Restore the character that was saved before any return can happen. */
  1046. if ( hold != -1 )
  1047. *ep = (char)hold;
  1048. /* If the property exists and is not an atom, just return here. */
  1049. if ( p && p->format != BDF_ATOM )
  1050. return 0;
  1051. /* The property is an atom. Trim all leading and trailing whitespace */
  1052. /* and double quotes for the atom value. */
  1053. sp = ep;
  1054. ep = line + linelen;
  1055. /* Trim the leading whitespace if it exists. */
  1056. if ( *sp )
  1057. *sp++ = 0;
  1058. while ( *sp &&
  1059. ( *sp == ' ' || *sp == '\t' ) )
  1060. sp++;
  1061. /* Trim the leading double quote if it exists. */
  1062. if ( *sp == '"' )
  1063. sp++;
  1064. *value = sp;
  1065. /* Trim the trailing whitespace if it exists. */
  1066. while ( ep > sp &&
  1067. ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) )
  1068. *--ep = 0;
  1069. /* Trim the trailing double quote if it exists. */
  1070. if ( ep > sp && *( ep - 1 ) == '"' )
  1071. *--ep = 0;
  1072. return 1;
  1073. }
  1074. static FT_Error
  1075. _bdf_add_property( bdf_font_t* font,
  1076. char* name,
  1077. char* value,
  1078. unsigned long lineno )
  1079. {
  1080. size_t propid;
  1081. hashnode hn;
  1082. bdf_property_t *prop, *fp;
  1083. FT_Memory memory = font->memory;
  1084. FT_Error error = FT_Err_Ok;
  1085. FT_UNUSED( lineno ); /* only used in debug mode */
  1086. /* First, check whether the property already exists in the font. */
  1087. if ( ( hn = hash_lookup( name, (hashtable *)font->internal ) ) != 0 )
  1088. {
  1089. /* The property already exists in the font, so simply replace */
  1090. /* the value of the property with the current value. */
  1091. fp = font->props + hn->data;
  1092. switch ( fp->format )
  1093. {
  1094. case BDF_ATOM:
  1095. /* Delete the current atom if it exists. */
  1096. FT_FREE( fp->value.atom );
  1097. if ( value && value[0] != 0 )
  1098. {
  1099. if ( FT_STRDUP( fp->value.atom, value ) )
  1100. goto Exit;
  1101. }
  1102. break;
  1103. case BDF_INTEGER:
  1104. fp->value.l = _bdf_atol( value, 0, 10 );
  1105. break;
  1106. case BDF_CARDINAL:
  1107. fp->value.ul = _bdf_atoul( value, 0, 10 );
  1108. break;
  1109. default:
  1110. ;
  1111. }
  1112. goto Exit;
  1113. }
  1114. /* See whether this property type exists yet or not. */
  1115. /* If not, create it. */
  1116. hn = hash_lookup( name, &(font->proptbl) );
  1117. if ( hn == 0 )
  1118. {
  1119. error = bdf_create_property( name, BDF_ATOM, font );
  1120. if ( error )
  1121. goto Exit;
  1122. hn = hash_lookup( name, &(font->proptbl) );
  1123. }
  1124. /* Allocate another property if this is overflow. */
  1125. if ( font->props_used == font->props_size )
  1126. {
  1127. if ( font->props_size == 0 )
  1128. {
  1129. if ( FT_NEW_ARRAY( font->props, 1 ) )
  1130. goto Exit;
  1131. }
  1132. else
  1133. {
  1134. if ( FT_RENEW_ARRAY( font->props,
  1135. font->props_size,
  1136. font->props_size + 1 ) )
  1137. goto Exit;
  1138. }
  1139. fp = font->props + font->props_size;
  1140. FT_MEM_ZERO( fp, sizeof ( bdf_property_t ) );
  1141. font->props_size++;
  1142. }
  1143. propid = hn->data;
  1144. if ( propid >= _num_bdf_properties )
  1145. prop = font->user_props + ( propid - _num_bdf_properties );
  1146. else
  1147. prop = (bdf_property_t*)_bdf_properties + propid;
  1148. fp = font->props + font->props_used;
  1149. fp->name = prop->name;
  1150. fp->format = prop->format;
  1151. fp->builtin = prop->builtin;
  1152. switch ( prop->format )
  1153. {
  1154. case BDF_ATOM:
  1155. fp->value.atom = 0;
  1156. if ( value != 0 && value[0] )
  1157. {
  1158. if ( FT_STRDUP( fp->value.atom, value ) )
  1159. goto Exit;
  1160. }
  1161. break;
  1162. case BDF_INTEGER:
  1163. fp->value.l = _bdf_atol( value, 0, 10 );
  1164. break;
  1165. case BDF_CARDINAL:
  1166. fp->value.ul = _bdf_atoul( value, 0, 10 );
  1167. break;
  1168. }
  1169. /* If the property happens to be a comment, then it doesn't need */
  1170. /* to be added to the internal hash table. */
  1171. if ( _bdf_strncmp( name, "COMMENT", 7 ) != 0 )
  1172. {
  1173. /* Add the property to the font property table. */
  1174. error = hash_insert( fp->name,
  1175. font->props_used,
  1176. (hashtable *)font->internal,
  1177. memory );
  1178. if ( error )
  1179. goto Exit;
  1180. }
  1181. font->props_used++;
  1182. /* Some special cases need to be handled here. The DEFAULT_CHAR */
  1183. /* property needs to be located if it exists in the property list, the */
  1184. /* FONT_ASCENT and FONT_DESCENT need to be assigned if they are */
  1185. /* present, and the SPACING property should override the default */
  1186. /* spacing. */
  1187. if ( _bdf_strncmp( name, "DEFAULT_CHAR", 12 ) == 0 )
  1188. font->default_char = fp->value.l;
  1189. else if ( _bdf_strncmp( name, "FONT_ASCENT", 11 ) == 0 )
  1190. font->font_ascent = fp->value.l;
  1191. else if ( _bdf_strncmp( name, "FONT_DESCENT", 12 ) == 0 )
  1192. font->font_descent = fp->value.l;
  1193. else if ( _bdf_strncmp( name, "SPACING", 7 ) == 0 )
  1194. {
  1195. if ( !fp->value.atom )
  1196. {
  1197. FT_ERROR(( "_bdf_add_property: " ERRMSG8, lineno, "SPACING" ));
  1198. error = FT_THROW( Invalid_File_Format );
  1199. goto Exit;
  1200. }
  1201. if ( fp->value.atom[0] == 'p' || fp->value.atom[0] == 'P' )
  1202. font->spacing = BDF_PROPORTIONAL;
  1203. else if ( fp->value.atom[0] == 'm' || fp->value.atom[0] == 'M' )
  1204. font->spacing = BDF_MONOWIDTH;
  1205. else if ( fp->value.atom[0] == 'c' || fp->value.atom[0] == 'C' )
  1206. font->spacing = BDF_CHARCELL;
  1207. }
  1208. Exit:
  1209. return error;
  1210. }
  1211. static const unsigned char nibble_mask[8] =
  1212. {
  1213. 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE
  1214. };
  1215. /* Actually parse the glyph info and bitmaps. */
  1216. static FT_Error
  1217. _bdf_parse_glyphs( char* line,
  1218. unsigned long linelen,
  1219. unsigned long lineno,
  1220. void* call_data,
  1221. void* client_data )
  1222. {
  1223. int c, mask_index;
  1224. char* s;
  1225. unsigned char* bp;
  1226. unsigned long i, slen, nibbles;
  1227. _bdf_parse_t* p;
  1228. bdf_glyph_t* glyph;
  1229. bdf_font_t* font;
  1230. FT_Memory memory;
  1231. FT_Error error = FT_Err_Ok;
  1232. FT_UNUSED( call_data );
  1233. FT_UNUSED( lineno ); /* only used in debug mode */
  1234. p = (_bdf_parse_t *)client_data;
  1235. font = p->font;
  1236. memory = font->memory;
  1237. /* Check for a comment. */
  1238. if ( _bdf_strncmp( line, "COMMENT", 7 ) == 0 )
  1239. {
  1240. linelen -= 7;
  1241. s = line + 7;
  1242. if ( *s != 0 )
  1243. {
  1244. s++;
  1245. linelen--;
  1246. }
  1247. error = _bdf_add_comment( p->font, s, linelen );
  1248. goto Exit;
  1249. }
  1250. /* The very first thing expected is the number of glyphs. */
  1251. if ( !( p->flags & _BDF_GLYPHS ) )
  1252. {
  1253. if ( _bdf_strncmp( line, "CHARS", 5 ) != 0 )
  1254. {
  1255. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "CHARS" ));
  1256. error = FT_THROW( Missing_Chars_Field );
  1257. goto Exit;
  1258. }
  1259. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1260. if ( error )
  1261. goto Exit;
  1262. p->cnt = font->glyphs_size = _bdf_atoul( p->list.field[1], 0, 10 );
  1263. /* Make sure the number of glyphs is non-zero. */
  1264. if ( p->cnt == 0 )
  1265. font->glyphs_size = 64;
  1266. /* Limit ourselves to 1,114,112 glyphs in the font (this is the */
  1267. /* number of code points available in Unicode). */
  1268. if ( p->cnt >= 0x110000UL )
  1269. {
  1270. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG5, lineno, "CHARS" ));
  1271. error = FT_THROW( Invalid_Argument );
  1272. goto Exit;
  1273. }
  1274. if ( FT_NEW_ARRAY( font->glyphs, font->glyphs_size ) )
  1275. goto Exit;
  1276. p->flags |= _BDF_GLYPHS;
  1277. goto Exit;
  1278. }
  1279. /* Check for the ENDFONT field. */
  1280. if ( _bdf_strncmp( line, "ENDFONT", 7 ) == 0 )
  1281. {
  1282. if ( p->flags & _BDF_GLYPH_BITS )
  1283. {
  1284. /* Missing ENDCHAR field. */
  1285. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENDCHAR" ));
  1286. error = FT_THROW( Corrupted_Font_Glyphs );
  1287. goto Exit;
  1288. }
  1289. /* Sort the glyphs by encoding. */
  1290. ft_qsort( (char *)font->glyphs,
  1291. font->glyphs_used,
  1292. sizeof ( bdf_glyph_t ),
  1293. by_encoding );
  1294. p->flags &= ~_BDF_START;
  1295. goto Exit;
  1296. }
  1297. /* Check for the ENDCHAR field. */
  1298. if ( _bdf_strncmp( line, "ENDCHAR", 7 ) == 0 )
  1299. {
  1300. p->glyph_enc = 0;
  1301. p->flags &= ~_BDF_GLYPH_BITS;
  1302. goto Exit;
  1303. }
  1304. /* Check whether a glyph is being scanned but should be */
  1305. /* ignored because it is an unencoded glyph. */
  1306. if ( ( p->flags & _BDF_GLYPH ) &&
  1307. p->glyph_enc == -1 &&
  1308. p->opts->keep_unencoded == 0 )
  1309. goto Exit;
  1310. /* Check for the STARTCHAR field. */
  1311. if ( _bdf_strncmp( line, "STARTCHAR", 9 ) == 0 )
  1312. {
  1313. /* Set the character name in the parse info first until the */
  1314. /* encoding can be checked for an unencoded character. */
  1315. FT_FREE( p->glyph_name );
  1316. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1317. if ( error )
  1318. goto Exit;
  1319. _bdf_list_shift( &p->list, 1 );
  1320. s = _bdf_list_join( &p->list, ' ', &slen );
  1321. if ( !s )
  1322. {
  1323. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG8, lineno, "STARTCHAR" ));
  1324. error = FT_THROW( Invalid_File_Format );
  1325. goto Exit;
  1326. }
  1327. if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) )
  1328. goto Exit;
  1329. FT_MEM_COPY( p->glyph_name, s, slen + 1 );
  1330. p->flags |= _BDF_GLYPH;
  1331. FT_TRACE4(( DBGMSG1, lineno, s ));
  1332. goto Exit;
  1333. }
  1334. /* Check for the ENCODING field. */
  1335. if ( _bdf_strncmp( line, "ENCODING", 8 ) == 0 )
  1336. {
  1337. if ( !( p->flags & _BDF_GLYPH ) )
  1338. {
  1339. /* Missing STARTCHAR field. */
  1340. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "STARTCHAR" ));
  1341. error = FT_THROW( Missing_Startchar_Field );
  1342. goto Exit;
  1343. }
  1344. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1345. if ( error )
  1346. goto Exit;
  1347. p->glyph_enc = _bdf_atol( p->list.field[1], 0, 10 );
  1348. /* Normalize negative encoding values. The specification only */
  1349. /* allows -1, but we can be more generous here. */
  1350. if ( p->glyph_enc < -1 )
  1351. p->glyph_enc = -1;
  1352. /* Check for alternative encoding format. */
  1353. if ( p->glyph_enc == -1 && p->list.used > 2 )
  1354. p->glyph_enc = _bdf_atol( p->list.field[2], 0, 10 );
  1355. if ( p->glyph_enc < -1 )
  1356. p->glyph_enc = -1;
  1357. FT_TRACE4(( DBGMSG2, p->glyph_enc ));
  1358. /* Check that the encoding is in the Unicode range because */
  1359. /* otherwise p->have (a bitmap with static size) overflows. */
  1360. if ( p->glyph_enc > 0 &&
  1361. (size_t)p->glyph_enc >= sizeof ( p->have ) /
  1362. sizeof ( unsigned long ) * 32 )
  1363. {
  1364. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG5, lineno, "ENCODING" ));
  1365. error = FT_THROW( Invalid_File_Format );
  1366. goto Exit;
  1367. }
  1368. /* Check whether this encoding has already been encountered. */
  1369. /* If it has then change it to unencoded so it gets added if */
  1370. /* indicated. */
  1371. if ( p->glyph_enc >= 0 )
  1372. {
  1373. if ( _bdf_glyph_modified( p->have, p->glyph_enc ) )
  1374. {
  1375. /* Emit a message saying a glyph has been moved to the */
  1376. /* unencoded area. */
  1377. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG12,
  1378. p->glyph_enc, p->glyph_name ));
  1379. p->glyph_enc = -1;
  1380. font->modified = 1;
  1381. }
  1382. else
  1383. _bdf_set_glyph_modified( p->have, p->glyph_enc );
  1384. }
  1385. if ( p->glyph_enc >= 0 )
  1386. {
  1387. /* Make sure there are enough glyphs allocated in case the */
  1388. /* number of characters happen to be wrong. */
  1389. if ( font->glyphs_used == font->glyphs_size )
  1390. {
  1391. if ( FT_RENEW_ARRAY( font->glyphs,
  1392. font->glyphs_size,
  1393. font->glyphs_size + 64 ) )
  1394. goto Exit;
  1395. font->glyphs_size += 64;
  1396. }
  1397. glyph = font->glyphs + font->glyphs_used++;
  1398. glyph->name = p->glyph_name;
  1399. glyph->encoding = p->glyph_enc;
  1400. /* Reset the initial glyph info. */
  1401. p->glyph_name = NULL;
  1402. }
  1403. else
  1404. {
  1405. /* Unencoded glyph. Check whether it should */
  1406. /* be added or not. */
  1407. if ( p->opts->keep_unencoded != 0 )
  1408. {
  1409. /* Allocate the next unencoded glyph. */
  1410. if ( font->unencoded_used == font->unencoded_size )
  1411. {
  1412. if ( FT_RENEW_ARRAY( font->unencoded ,
  1413. font->unencoded_size,
  1414. font->unencoded_size + 4 ) )
  1415. goto Exit;
  1416. font->unencoded_size += 4;
  1417. }
  1418. glyph = font->unencoded + font->unencoded_used;
  1419. glyph->name = p->glyph_name;
  1420. glyph->encoding = (long)font->unencoded_used++;
  1421. }
  1422. else
  1423. /* Free up the glyph name if the unencoded shouldn't be */
  1424. /* kept. */
  1425. FT_FREE( p->glyph_name );
  1426. p->glyph_name = NULL;
  1427. }
  1428. /* Clear the flags that might be added when width and height are */
  1429. /* checked for consistency. */
  1430. p->flags &= ~( _BDF_GLYPH_WIDTH_CHECK | _BDF_GLYPH_HEIGHT_CHECK );
  1431. p->flags |= _BDF_ENCODING;
  1432. goto Exit;
  1433. }
  1434. /* Point at the glyph being constructed. */
  1435. if ( p->glyph_enc == -1 )
  1436. glyph = font->unencoded + ( font->unencoded_used - 1 );
  1437. else
  1438. glyph = font->glyphs + ( font->glyphs_used - 1 );
  1439. /* Check whether a bitmap is being constructed. */
  1440. if ( p->flags & _BDF_BITMAP )
  1441. {
  1442. /* If there are more rows than are specified in the glyph metrics, */
  1443. /* ignore the remaining lines. */
  1444. if ( p->row >= (unsigned long)glyph->bbx.height )
  1445. {
  1446. if ( !( p->flags & _BDF_GLYPH_HEIGHT_CHECK ) )
  1447. {
  1448. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG13, glyph->encoding ));
  1449. p->flags |= _BDF_GLYPH_HEIGHT_CHECK;
  1450. font->modified = 1;
  1451. }
  1452. goto Exit;
  1453. }
  1454. /* Only collect the number of nibbles indicated by the glyph */
  1455. /* metrics. If there are more columns, they are simply ignored. */
  1456. nibbles = glyph->bpr << 1;
  1457. bp = glyph->bitmap + p->row * glyph->bpr;
  1458. for ( i = 0; i < nibbles; i++ )
  1459. {
  1460. c = line[i];
  1461. if ( !sbitset( hdigits, c ) )
  1462. break;
  1463. *bp = (FT_Byte)( ( *bp << 4 ) + a2i[c] );
  1464. if ( i + 1 < nibbles && ( i & 1 ) )
  1465. *++bp = 0;
  1466. }
  1467. /* If any line has not enough columns, */
  1468. /* indicate they have been padded with zero bits. */
  1469. if ( i < nibbles &&
  1470. !( p->flags & _BDF_GLYPH_WIDTH_CHECK ) )
  1471. {
  1472. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG16, glyph->encoding ));
  1473. p->flags |= _BDF_GLYPH_WIDTH_CHECK;
  1474. font->modified = 1;
  1475. }
  1476. /* Remove possible garbage at the right. */
  1477. mask_index = ( glyph->bbx.width * p->font->bpp ) & 7;
  1478. if ( glyph->bbx.width )
  1479. *bp &= nibble_mask[mask_index];
  1480. /* If any line has extra columns, indicate they have been removed. */
  1481. if ( i == nibbles &&
  1482. sbitset( hdigits, line[nibbles] ) &&
  1483. !( p->flags & _BDF_GLYPH_WIDTH_CHECK ) )
  1484. {
  1485. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG14, glyph->encoding ));
  1486. p->flags |= _BDF_GLYPH_WIDTH_CHECK;
  1487. font->modified = 1;
  1488. }
  1489. p->row++;
  1490. goto Exit;
  1491. }
  1492. /* Expect the SWIDTH (scalable width) field next. */
  1493. if ( _bdf_strncmp( line, "SWIDTH", 6 ) == 0 )
  1494. {
  1495. if ( !( p->flags & _BDF_ENCODING ) )
  1496. goto Missing_Encoding;
  1497. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1498. if ( error )
  1499. goto Exit;
  1500. glyph->swidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
  1501. p->flags |= _BDF_SWIDTH;
  1502. goto Exit;
  1503. }
  1504. /* Expect the DWIDTH (scalable width) field next. */
  1505. if ( _bdf_strncmp( line, "DWIDTH", 6 ) == 0 )
  1506. {
  1507. if ( !( p->flags & _BDF_ENCODING ) )
  1508. goto Missing_Encoding;
  1509. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1510. if ( error )
  1511. goto Exit;
  1512. glyph->dwidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
  1513. if ( !( p->flags & _BDF_SWIDTH ) )
  1514. {
  1515. /* Missing SWIDTH field. Emit an auto correction message and set */
  1516. /* the scalable width from the device width. */
  1517. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG9, lineno ));
  1518. glyph->swidth = (unsigned short)FT_MulDiv(
  1519. glyph->dwidth, 72000L,
  1520. (FT_Long)( font->point_size *
  1521. font->resolution_x ) );
  1522. }
  1523. p->flags |= _BDF_DWIDTH;
  1524. goto Exit;
  1525. }
  1526. /* Expect the BBX field next. */
  1527. if ( _bdf_strncmp( line, "BBX", 3 ) == 0 )
  1528. {
  1529. if ( !( p->flags & _BDF_ENCODING ) )
  1530. goto Missing_Encoding;
  1531. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1532. if ( error )
  1533. goto Exit;
  1534. glyph->bbx.width = _bdf_atous( p->list.field[1], 0, 10 );
  1535. glyph->bbx.height = _bdf_atous( p->list.field[2], 0, 10 );
  1536. glyph->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );
  1537. glyph->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );
  1538. /* Generate the ascent and descent of the character. */
  1539. glyph->bbx.ascent = (short)( glyph->bbx.height + glyph->bbx.y_offset );
  1540. glyph->bbx.descent = (short)( -glyph->bbx.y_offset );
  1541. /* Determine the overall font bounding box as the characters are */
  1542. /* loaded so corrections can be done later if indicated. */
  1543. p->maxas = (short)FT_MAX( glyph->bbx.ascent, p->maxas );
  1544. p->maxds = (short)FT_MAX( glyph->bbx.descent, p->maxds );
  1545. p->rbearing = (short)( glyph->bbx.width + glyph->bbx.x_offset );
  1546. p->maxrb = (short)FT_MAX( p->rbearing, p->maxrb );
  1547. p->minlb = (short)FT_MIN( glyph->bbx.x_offset, p->minlb );
  1548. p->maxlb = (short)FT_MAX( glyph->bbx.x_offset, p->maxlb );
  1549. if ( !( p->flags & _BDF_DWIDTH ) )
  1550. {
  1551. /* Missing DWIDTH field. Emit an auto correction message and set */
  1552. /* the device width to the glyph width. */
  1553. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG10, lineno ));
  1554. glyph->dwidth = glyph->bbx.width;
  1555. }
  1556. /* If the BDF_CORRECT_METRICS flag is set, then adjust the SWIDTH */
  1557. /* value if necessary. */
  1558. if ( p->opts->correct_metrics != 0 )
  1559. {
  1560. /* Determine the point size of the glyph. */
  1561. unsigned short sw = (unsigned short)FT_MulDiv(
  1562. glyph->dwidth, 72000L,
  1563. (FT_Long)( font->point_size *
  1564. font->resolution_x ) );
  1565. if ( sw != glyph->swidth )
  1566. {
  1567. glyph->swidth = sw;
  1568. if ( p->glyph_enc == -1 )
  1569. _bdf_set_glyph_modified( font->umod,
  1570. font->unencoded_used - 1 );
  1571. else
  1572. _bdf_set_glyph_modified( font->nmod, glyph->encoding );
  1573. p->flags |= _BDF_SWIDTH_ADJ;
  1574. font->modified = 1;
  1575. }
  1576. }
  1577. p->flags |= _BDF_BBX;
  1578. goto Exit;
  1579. }
  1580. /* And finally, gather up the bitmap. */
  1581. if ( _bdf_strncmp( line, "BITMAP", 6 ) == 0 )
  1582. {
  1583. unsigned long bitmap_size;
  1584. if ( !( p->flags & _BDF_BBX ) )
  1585. {
  1586. /* Missing BBX field. */
  1587. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "BBX" ));
  1588. error = FT_THROW( Missing_Bbx_Field );
  1589. goto Exit;
  1590. }
  1591. /* Allocate enough space for the bitmap. */
  1592. glyph->bpr = ( glyph->bbx.width * p->font->bpp + 7 ) >> 3;
  1593. bitmap_size = glyph->bpr * glyph->bbx.height;
  1594. if ( glyph->bpr > 0xFFFFU || bitmap_size > 0xFFFFU )
  1595. {
  1596. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG4, lineno ));
  1597. error = FT_THROW( Bbx_Too_Big );
  1598. goto Exit;
  1599. }
  1600. else
  1601. glyph->bytes = (unsigned short)bitmap_size;
  1602. if ( FT_NEW_ARRAY( glyph->bitmap, glyph->bytes ) )
  1603. goto Exit;
  1604. p->row = 0;
  1605. p->flags |= _BDF_BITMAP;
  1606. goto Exit;
  1607. }
  1608. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG9, lineno ));
  1609. error = FT_THROW( Invalid_File_Format );
  1610. goto Exit;
  1611. Missing_Encoding:
  1612. /* Missing ENCODING field. */
  1613. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENCODING" ));
  1614. error = FT_THROW( Missing_Encoding_Field );
  1615. Exit:
  1616. if ( error && ( p->flags & _BDF_GLYPH ) )
  1617. FT_FREE( p->glyph_name );
  1618. return error;
  1619. }
  1620. /* Load the font properties. */
  1621. static FT_Error
  1622. _bdf_parse_properties( char* line,
  1623. unsigned long linelen,
  1624. unsigned long lineno,
  1625. void* call_data,
  1626. void* client_data )
  1627. {
  1628. unsigned long vlen;
  1629. _bdf_line_func_t* next;
  1630. _bdf_parse_t* p;
  1631. char* name;
  1632. char* value;
  1633. char nbuf[128];
  1634. FT_Error error = FT_Err_Ok;
  1635. FT_UNUSED( lineno );
  1636. next = (_bdf_line_func_t *)call_data;
  1637. p = (_bdf_parse_t *) client_data;
  1638. /* Check for the end of the properties. */
  1639. if ( _bdf_strncmp( line, "ENDPROPERTIES", 13 ) == 0 )
  1640. {
  1641. /* If the FONT_ASCENT or FONT_DESCENT properties have not been */
  1642. /* encountered yet, then make sure they are added as properties and */
  1643. /* make sure they are set from the font bounding box info. */
  1644. /* */
  1645. /* This is *always* done regardless of the options, because X11 */
  1646. /* requires these two fields to compile fonts. */
  1647. if ( bdf_get_font_property( p->font, "FONT_ASCENT" ) == 0 )
  1648. {
  1649. p->font->font_ascent = p->font->bbx.ascent;
  1650. ft_sprintf( nbuf, "%hd", p->font->bbx.ascent );
  1651. error = _bdf_add_property( p->font, (char *)"FONT_ASCENT",
  1652. nbuf, lineno );
  1653. if ( error )
  1654. goto Exit;
  1655. FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent ));
  1656. p->font->modified = 1;
  1657. }
  1658. if ( bdf_get_font_property( p->font, "FONT_DESCENT" ) == 0 )
  1659. {
  1660. p->font->font_descent = p->font->bbx.descent;
  1661. ft_sprintf( nbuf, "%hd", p->font->bbx.descent );
  1662. error = _bdf_add_property( p->font, (char *)"FONT_DESCENT",
  1663. nbuf, lineno );
  1664. if ( error )
  1665. goto Exit;
  1666. FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent ));
  1667. p->font->modified = 1;
  1668. }
  1669. p->flags &= ~_BDF_PROPS;
  1670. *next = _bdf_parse_glyphs;
  1671. goto Exit;
  1672. }
  1673. /* Ignore the _XFREE86_GLYPH_RANGES properties. */
  1674. if ( _bdf_strncmp( line, "_XFREE86_GLYPH_RANGES", 21 ) == 0 )
  1675. goto Exit;
  1676. /* Handle COMMENT fields and properties in a special way to preserve */
  1677. /* the spacing. */
  1678. if ( _bdf_strncmp( line, "COMMENT", 7 ) == 0 )
  1679. {
  1680. name = value = line;
  1681. value += 7;
  1682. if ( *value )
  1683. *value++ = 0;
  1684. error = _bdf_add_property( p->font, name, value, lineno );
  1685. if ( error )
  1686. goto Exit;
  1687. }
  1688. else if ( _bdf_is_atom( line, linelen, &name, &value, p->font ) )
  1689. {
  1690. error = _bdf_add_property( p->font, name, value, lineno );
  1691. if ( error )
  1692. goto Exit;
  1693. }
  1694. else
  1695. {
  1696. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1697. if ( error )
  1698. goto Exit;
  1699. name = p->list.field[0];
  1700. _bdf_list_shift( &p->list, 1 );
  1701. value = _bdf_list_join( &p->list, ' ', &vlen );
  1702. error = _bdf_add_property( p->font, name, value, lineno );
  1703. if ( error )
  1704. goto Exit;
  1705. }
  1706. Exit:
  1707. return error;
  1708. }
  1709. /* Load the font header. */
  1710. static FT_Error
  1711. _bdf_parse_start( char* line,
  1712. unsigned long linelen,
  1713. unsigned long lineno,
  1714. void* call_data,
  1715. void* client_data )
  1716. {
  1717. unsigned long slen;
  1718. _bdf_line_func_t* next;
  1719. _bdf_parse_t* p;
  1720. bdf_font_t* font;
  1721. char *s;
  1722. FT_Memory memory = NULL;
  1723. FT_Error error = FT_Err_Ok;
  1724. FT_UNUSED( lineno ); /* only used in debug mode */
  1725. next = (_bdf_line_func_t *)call_data;
  1726. p = (_bdf_parse_t *) client_data;
  1727. if ( p->font )
  1728. memory = p->font->memory;
  1729. /* Check for a comment. This is done to handle those fonts that have */
  1730. /* comments before the STARTFONT line for some reason. */
  1731. if ( _bdf_strncmp( line, "COMMENT", 7 ) == 0 )
  1732. {
  1733. if ( p->opts->keep_comments != 0 && p->font != 0 )
  1734. {
  1735. linelen -= 7;
  1736. s = line + 7;
  1737. if ( *s != 0 )
  1738. {
  1739. s++;
  1740. linelen--;
  1741. }
  1742. error = _bdf_add_comment( p->font, s, linelen );
  1743. if ( error )
  1744. goto Exit;
  1745. /* here font is not defined! */
  1746. }
  1747. goto Exit;
  1748. }
  1749. if ( !( p->flags & _BDF_START ) )
  1750. {
  1751. memory = p->memory;
  1752. if ( _bdf_strncmp( line, "STARTFONT", 9 ) != 0 )
  1753. {
  1754. /* we don't emit an error message since this code gets */
  1755. /* explicitly caught one level higher */
  1756. error = FT_THROW( Missing_Startfont_Field );
  1757. goto Exit;
  1758. }
  1759. p->flags = _BDF_START;
  1760. font = p->font = 0;
  1761. if ( FT_NEW( font ) )
  1762. goto Exit;
  1763. p->font = font;
  1764. font->memory = p->memory;
  1765. p->memory = 0;
  1766. { /* setup */
  1767. size_t i;
  1768. bdf_property_t* prop;
  1769. error = hash_init( &(font->proptbl), memory );
  1770. if ( error )
  1771. goto Exit;
  1772. for ( i = 0, prop = (bdf_property_t*)_bdf_properties;
  1773. i < _num_bdf_properties; i++, prop++ )
  1774. {
  1775. error = hash_insert( prop->name, i,
  1776. &(font->proptbl), memory );
  1777. if ( error )
  1778. goto Exit;
  1779. }
  1780. }
  1781. if ( FT_ALLOC( p->font->internal, sizeof ( hashtable ) ) )
  1782. goto Exit;
  1783. error = hash_init( (hashtable *)p->font->internal,memory );
  1784. if ( error )
  1785. goto Exit;
  1786. p->font->spacing = p->opts->font_spacing;
  1787. p->font->default_char = -1;
  1788. goto Exit;
  1789. }
  1790. /* Check for the start of the properties. */
  1791. if ( _bdf_strncmp( line, "STARTPROPERTIES", 15 ) == 0 )
  1792. {
  1793. if ( !( p->flags & _BDF_FONT_BBX ) )
  1794. {
  1795. /* Missing the FONTBOUNDINGBOX field. */
  1796. FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONTBOUNDINGBOX" ));
  1797. error = FT_THROW( Missing_Fontboundingbox_Field );
  1798. goto Exit;
  1799. }
  1800. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1801. if ( error )
  1802. goto Exit;
  1803. /* at this point, `p->font' can't be NULL */
  1804. p->cnt = p->font->props_size = _bdf_atoul( p->list.field[1], 0, 10 );
  1805. if ( FT_NEW_ARRAY( p->font->props, p->cnt ) )
  1806. {
  1807. p->font->props_size = 0;
  1808. goto Exit;
  1809. }
  1810. p->flags |= _BDF_PROPS;
  1811. *next = _bdf_parse_properties;
  1812. goto Exit;
  1813. }
  1814. /* Check for the FONTBOUNDINGBOX field. */
  1815. if ( _bdf_strncmp( line, "FONTBOUNDINGBOX", 15 ) == 0 )
  1816. {
  1817. if ( !( p->flags & _BDF_SIZE ) )
  1818. {
  1819. /* Missing the SIZE field. */
  1820. FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "SIZE" ));
  1821. error = FT_THROW( Missing_Size_Field );
  1822. goto Exit;
  1823. }
  1824. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1825. if ( error )
  1826. goto Exit;
  1827. p->font->bbx.width = _bdf_atous( p->list.field[1], 0, 10 );
  1828. p->font->bbx.height = _bdf_atous( p->list.field[2], 0, 10 );
  1829. p->font->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );
  1830. p->font->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );
  1831. p->font->bbx.ascent = (short)( p->font->bbx.height +
  1832. p->font->bbx.y_offset );
  1833. p->font->bbx.descent = (short)( -p->font->bbx.y_offset );
  1834. p->flags |= _BDF_FONT_BBX;
  1835. goto Exit;
  1836. }
  1837. /* The next thing to check for is the FONT field. */
  1838. if ( _bdf_strncmp( line, "FONT", 4 ) == 0 )
  1839. {
  1840. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1841. if ( error )
  1842. goto Exit;
  1843. _bdf_list_shift( &p->list, 1 );
  1844. s = _bdf_list_join( &p->list, ' ', &slen );
  1845. if ( !s )
  1846. {
  1847. FT_ERROR(( "_bdf_parse_start: " ERRMSG8, lineno, "FONT" ));
  1848. error = FT_THROW( Invalid_File_Format );
  1849. goto Exit;
  1850. }
  1851. /* Allowing multiple `FONT' lines (which is invalid) doesn't hurt... */
  1852. FT_FREE( p->font->name );
  1853. if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) )
  1854. goto Exit;
  1855. FT_MEM_COPY( p->font->name, s, slen + 1 );
  1856. /* If the font name is an XLFD name, set the spacing to the one in */
  1857. /* the font name. If there is no spacing fall back on the default. */
  1858. error = _bdf_set_default_spacing( p->font, p->opts, lineno );
  1859. if ( error )
  1860. goto Exit;
  1861. p->flags |= _BDF_FONT_NAME;
  1862. goto Exit;
  1863. }
  1864. /* Check for the SIZE field. */
  1865. if ( _bdf_strncmp( line, "SIZE", 4 ) == 0 )
  1866. {
  1867. if ( !( p->flags & _BDF_FONT_NAME ) )
  1868. {
  1869. /* Missing the FONT field. */
  1870. FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONT" ));
  1871. error = FT_THROW( Missing_Font_Field );
  1872. goto Exit;
  1873. }
  1874. error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
  1875. if ( error )
  1876. goto Exit;
  1877. p->font->point_size = _bdf_atoul( p->list.field[1], 0, 10 );
  1878. p->font->resolution_x = _bdf_atoul( p->list.field[2], 0, 10 );
  1879. p->font->resolution_y = _bdf_atoul( p->list.field[3], 0, 10 );
  1880. /* Check for the bits per pixel field. */
  1881. if ( p->list.used == 5 )
  1882. {
  1883. unsigned short bitcount, i, shift;
  1884. p->font->bpp = (unsigned short)_bdf_atos( p->list.field[4], 0, 10 );
  1885. /* Only values 1, 2, 4, 8 are allowed. */
  1886. shift = p->font->bpp;
  1887. bitcount = 0;
  1888. for ( i = 0; shift > 0; i++ )
  1889. {
  1890. if ( shift & 1 )
  1891. bitcount = i;
  1892. shift >>= 1;
  1893. }
  1894. shift = (unsigned short)( ( bitcount > 3 ) ? 8
  1895. : ( 1U << bitcount ) );
  1896. if ( p->font->bpp > shift || p->font->bpp != shift )
  1897. {
  1898. /* select next higher value */
  1899. p->font->bpp = (unsigned short)( shift << 1 );
  1900. FT_TRACE2(( "_bdf_parse_start: " ACMSG11, p->font->bpp ));
  1901. }
  1902. }
  1903. else
  1904. p->font->bpp = 1;
  1905. p->flags |= _BDF_SIZE;
  1906. goto Exit;
  1907. }
  1908. /* Check for the CHARS field -- font properties are optional */
  1909. if ( _bdf_strncmp( line, "CHARS", 5 ) == 0 )
  1910. {
  1911. char nbuf[128];
  1912. if ( !( p->flags & _BDF_FONT_BBX ) )
  1913. {
  1914. /* Missing the FONTBOUNDINGBOX field. */
  1915. FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONTBOUNDINGBOX" ));
  1916. error = FT_THROW( Missing_Fontboundingbox_Field );
  1917. goto Exit;
  1918. }
  1919. /* Add the two standard X11 properties which are required */
  1920. /* for compiling fonts. */
  1921. p->font->font_ascent = p->font->bbx.ascent;
  1922. ft_sprintf( nbuf, "%hd", p->font->bbx.ascent );
  1923. error = _bdf_add_property( p->font, (char *)"FONT_ASCENT",
  1924. nbuf, lineno );
  1925. if ( error )
  1926. goto Exit;
  1927. FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent ));
  1928. p->font->font_descent = p->font->bbx.descent;
  1929. ft_sprintf( nbuf, "%hd", p->font->bbx.descent );
  1930. error = _bdf_add_property( p->font, (char *)"FONT_DESCENT",
  1931. nbuf, lineno );
  1932. if ( error )
  1933. goto Exit;
  1934. FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent ));
  1935. p->font->modified = 1;
  1936. *next = _bdf_parse_glyphs;
  1937. /* A special return value. */
  1938. error = -1;
  1939. goto Exit;
  1940. }
  1941. FT_ERROR(( "_bdf_parse_start: " ERRMSG9, lineno ));
  1942. error = FT_THROW( Invalid_File_Format );
  1943. Exit:
  1944. return error;
  1945. }
  1946. /*************************************************************************/
  1947. /* */
  1948. /* API. */
  1949. /* */
  1950. /*************************************************************************/
  1951. FT_LOCAL_DEF( FT_Error )
  1952. bdf_load_font( FT_Stream stream,
  1953. FT_Memory extmemory,
  1954. bdf_options_t* opts,
  1955. bdf_font_t* *font )
  1956. {
  1957. unsigned long lineno = 0; /* make compiler happy */
  1958. _bdf_parse_t *p = NULL;
  1959. FT_Memory memory = extmemory; /* needed for FT_NEW */
  1960. FT_Error error = FT_Err_Ok;
  1961. if ( FT_NEW( p ) )
  1962. goto Exit;
  1963. memory = NULL;
  1964. p->opts = (bdf_options_t*)( ( opts != 0 ) ? opts : &_bdf_opts );
  1965. p->minlb = 32767;
  1966. p->memory = extmemory; /* only during font creation */
  1967. _bdf_list_init( &p->list, extmemory );
  1968. error = _bdf_readstream( stream, _bdf_parse_start,
  1969. (void *)p, &lineno );
  1970. if ( error )
  1971. goto Fail;
  1972. if ( p->font != 0 )
  1973. {
  1974. /* If the font is not proportional, set the font's monowidth */
  1975. /* field to the width of the font bounding box. */
  1976. if ( p->font->spacing != BDF_PROPORTIONAL )
  1977. p->font->monowidth = p->font->bbx.width;
  1978. /* If the number of glyphs loaded is not that of the original count, */
  1979. /* indicate the difference. */
  1980. if ( p->cnt != p->font->glyphs_used + p->font->unencoded_used )
  1981. {
  1982. FT_TRACE2(( "bdf_load_font: " ACMSG15, p->cnt,
  1983. p->font->glyphs_used + p->font->unencoded_used ));
  1984. p->font->modified = 1;
  1985. }
  1986. /* Once the font has been loaded, adjust the overall font metrics if */
  1987. /* necessary. */
  1988. if ( p->opts->correct_metrics != 0 &&
  1989. ( p->font->glyphs_used > 0 || p->font->unencoded_used > 0 ) )
  1990. {
  1991. if ( p->maxrb - p->minlb != p->font->bbx.width )
  1992. {
  1993. FT_TRACE2(( "bdf_load_font: " ACMSG3,
  1994. p->font->bbx.width, p->maxrb - p->minlb ));
  1995. p->font->bbx.width = (unsigned short)( p->maxrb - p->minlb );
  1996. p->font->modified = 1;
  1997. }
  1998. if ( p->font->bbx.x_offset != p->minlb )
  1999. {
  2000. FT_TRACE2(( "bdf_load_font: " ACMSG4,
  2001. p->font->bbx.x_offset, p->minlb ));
  2002. p->font->bbx.x_offset = p->minlb;
  2003. p->font->modified = 1;
  2004. }
  2005. if ( p->font->bbx.ascent != p->maxas )
  2006. {
  2007. FT_TRACE2(( "bdf_load_font: " ACMSG5,
  2008. p->font->bbx.ascent, p->maxas ));
  2009. p->font->bbx.ascent = p->maxas;
  2010. p->font->modified = 1;
  2011. }
  2012. if ( p->font->bbx.descent != p->maxds )
  2013. {
  2014. FT_TRACE2(( "bdf_load_font: " ACMSG6,
  2015. p->font->bbx.descent, p->maxds ));
  2016. p->font->bbx.descent = p->maxds;
  2017. p->font->bbx.y_offset = (short)( -p->maxds );
  2018. p->font->modified = 1;
  2019. }
  2020. if ( p->maxas + p->maxds != p->font->bbx.height )
  2021. {
  2022. FT_TRACE2(( "bdf_load_font: " ACMSG7,
  2023. p->font->bbx.height, p->maxas + p->maxds ));
  2024. p->font->bbx.height = (unsigned short)( p->maxas + p->maxds );
  2025. }
  2026. if ( p->flags & _BDF_SWIDTH_ADJ )
  2027. FT_TRACE2(( "bdf_load_font: " ACMSG8 ));
  2028. }
  2029. }
  2030. if ( p->flags & _BDF_START )
  2031. {
  2032. /* The ENDFONT field was never reached or did not exist. */
  2033. if ( !( p->flags & _BDF_GLYPHS ) )
  2034. {
  2035. /* Error happened while parsing header. */
  2036. FT_ERROR(( "bdf_load_font: " ERRMSG2, lineno ));
  2037. error = FT_THROW( Corrupted_Font_Header );
  2038. goto Exit;
  2039. }
  2040. else
  2041. {
  2042. /* Error happened when parsing glyphs. */
  2043. FT_ERROR(( "bdf_load_font: " ERRMSG3, lineno ));
  2044. error = FT_THROW( Corrupted_Font_Glyphs );
  2045. goto Exit;
  2046. }
  2047. }
  2048. if ( p->font != 0 )
  2049. {
  2050. /* Make sure the comments are NULL terminated if they exist. */
  2051. memory = p->font->memory;
  2052. if ( p->font->comments_len > 0 )
  2053. {
  2054. if ( FT_RENEW_ARRAY( p->font->comments,
  2055. p->font->comments_len,
  2056. p->font->comments_len + 1 ) )
  2057. goto Fail;
  2058. p->font->comments[p->font->comments_len] = 0;
  2059. }
  2060. }
  2061. else if ( error == FT_Err_Ok )
  2062. error = FT_THROW( Invalid_File_Format );
  2063. *font = p->font;
  2064. Exit:
  2065. if ( p )
  2066. {
  2067. _bdf_list_done( &p->list );
  2068. memory = extmemory;
  2069. FT_FREE( p );
  2070. }
  2071. return error;
  2072. Fail:
  2073. bdf_free_font( p->font );
  2074. memory = extmemory;
  2075. FT_FREE( p->font );
  2076. goto Exit;
  2077. }
  2078. FT_LOCAL_DEF( void )
  2079. bdf_free_font( bdf_font_t* font )
  2080. {
  2081. bdf_property_t* prop;
  2082. unsigned long i;
  2083. bdf_glyph_t* glyphs;
  2084. FT_Memory memory;
  2085. if ( font == 0 )
  2086. return;
  2087. memory = font->memory;
  2088. FT_FREE( font->name );
  2089. /* Free up the internal hash table of property names. */
  2090. if ( font->internal )
  2091. {
  2092. hash_free( (hashtable *)font->internal, memory );
  2093. FT_FREE( font->internal );
  2094. }
  2095. /* Free up the comment info. */
  2096. FT_FREE( font->comments );
  2097. /* Free up the properties. */
  2098. for ( i = 0; i < font->props_size; i++ )
  2099. {
  2100. if ( font->props[i].format == BDF_ATOM )
  2101. FT_FREE( font->props[i].value.atom );
  2102. }
  2103. FT_FREE( font->props );
  2104. /* Free up the character info. */
  2105. for ( i = 0, glyphs = font->glyphs;
  2106. i < font->glyphs_used; i++, glyphs++ )
  2107. {
  2108. FT_FREE( glyphs->name );
  2109. FT_FREE( glyphs->bitmap );
  2110. }
  2111. for ( i = 0, glyphs = font->unencoded; i < font->unencoded_used;
  2112. i++, glyphs++ )
  2113. {
  2114. FT_FREE( glyphs->name );
  2115. FT_FREE( glyphs->bitmap );
  2116. }
  2117. FT_FREE( font->glyphs );
  2118. FT_FREE( font->unencoded );
  2119. /* Free up the overflow storage if it was used. */
  2120. for ( i = 0, glyphs = font->overflow.glyphs;
  2121. i < font->overflow.glyphs_used; i++, glyphs++ )
  2122. {
  2123. FT_FREE( glyphs->name );
  2124. FT_FREE( glyphs->bitmap );
  2125. }
  2126. FT_FREE( font->overflow.glyphs );
  2127. /* bdf_cleanup */
  2128. hash_free( &(font->proptbl), memory );
  2129. /* Free up the user defined properties. */
  2130. for ( prop = font->user_props, i = 0;
  2131. i < font->nuser_props; i++, prop++ )
  2132. {
  2133. FT_FREE( prop->name );
  2134. if ( prop->format == BDF_ATOM )
  2135. FT_FREE( prop->value.atom );
  2136. }
  2137. FT_FREE( font->user_props );
  2138. /* FREE( font ); */ /* XXX Fixme */
  2139. }
  2140. FT_LOCAL_DEF( bdf_property_t * )
  2141. bdf_get_font_property( bdf_font_t* font,
  2142. const char* name )
  2143. {
  2144. hashnode hn;
  2145. if ( font == 0 || font->props_size == 0 || name == 0 || *name == 0 )
  2146. return 0;
  2147. hn = hash_lookup( name, (hashtable *)font->internal );
  2148. return hn ? ( font->props + hn->data ) : 0;
  2149. }
  2150. /* END */