PageRenderTime 86ms CodeModel.GetById 32ms 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

Large files files are truncated, but you can click here to view the full file

  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_s

Large files files are truncated, but you can click here to view the full file