/src/compiler/android-ndk/jni/freetype/src/psaux/t1decode.c

http://ftk.googlecode.com/ · C · 1592 lines · 1028 code · 311 blank · 253 comment · 164 complexity · cf8a939fc4e86b6b1bdea4fdb0de396c MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* t1decode.c */
  4. /* */
  5. /* PostScript Type 1 decoding routines (body). */
  6. /* */
  7. /* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 */
  8. /* 2010 by */
  9. /* David Turner, Robert Wilhelm, and Werner Lemberg. */
  10. /* */
  11. /* This file is part of the FreeType project, and may only be used, */
  12. /* modified, and distributed under the terms of the FreeType project */
  13. /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
  14. /* this file you indicate that you have read the license and */
  15. /* understand and accept it fully. */
  16. /* */
  17. /***************************************************************************/
  18. #include <ft2build.h>
  19. #include FT_INTERNAL_CALC_H
  20. #include FT_INTERNAL_DEBUG_H
  21. #include FT_INTERNAL_POSTSCRIPT_HINTS_H
  22. #include FT_OUTLINE_H
  23. #include "t1decode.h"
  24. #include "psobjs.h"
  25. #include "psauxerr.h"
  26. /*************************************************************************/
  27. /* */
  28. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  29. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  30. /* messages during execution. */
  31. /* */
  32. #undef FT_COMPONENT
  33. #define FT_COMPONENT trace_t1decode
  34. typedef enum T1_Operator_
  35. {
  36. op_none = 0,
  37. op_endchar,
  38. op_hsbw,
  39. op_seac,
  40. op_sbw,
  41. op_closepath,
  42. op_hlineto,
  43. op_hmoveto,
  44. op_hvcurveto,
  45. op_rlineto,
  46. op_rmoveto,
  47. op_rrcurveto,
  48. op_vhcurveto,
  49. op_vlineto,
  50. op_vmoveto,
  51. op_dotsection,
  52. op_hstem,
  53. op_hstem3,
  54. op_vstem,
  55. op_vstem3,
  56. op_div,
  57. op_callothersubr,
  58. op_callsubr,
  59. op_pop,
  60. op_return,
  61. op_setcurrentpoint,
  62. op_unknown15,
  63. op_max /* never remove this one */
  64. } T1_Operator;
  65. static
  66. const FT_Int t1_args_count[op_max] =
  67. {
  68. 0, /* none */
  69. 0, /* endchar */
  70. 2, /* hsbw */
  71. 5, /* seac */
  72. 4, /* sbw */
  73. 0, /* closepath */
  74. 1, /* hlineto */
  75. 1, /* hmoveto */
  76. 4, /* hvcurveto */
  77. 2, /* rlineto */
  78. 2, /* rmoveto */
  79. 6, /* rrcurveto */
  80. 4, /* vhcurveto */
  81. 1, /* vlineto */
  82. 1, /* vmoveto */
  83. 0, /* dotsection */
  84. 2, /* hstem */
  85. 6, /* hstem3 */
  86. 2, /* vstem */
  87. 6, /* vstem3 */
  88. 2, /* div */
  89. -1, /* callothersubr */
  90. 1, /* callsubr */
  91. 0, /* pop */
  92. 0, /* return */
  93. 2, /* setcurrentpoint */
  94. 2 /* opcode 15 (undocumented and obsolete) */
  95. };
  96. /*************************************************************************/
  97. /* */
  98. /* <Function> */
  99. /* t1_lookup_glyph_by_stdcharcode */
  100. /* */
  101. /* <Description> */
  102. /* Looks up a given glyph by its StandardEncoding charcode. Used to */
  103. /* implement the SEAC Type 1 operator. */
  104. /* */
  105. /* <Input> */
  106. /* face :: The current face object. */
  107. /* */
  108. /* charcode :: The character code to look for. */
  109. /* */
  110. /* <Return> */
  111. /* A glyph index in the font face. Returns -1 if the corresponding */
  112. /* glyph wasn't found. */
  113. /* */
  114. static FT_Int
  115. t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder,
  116. FT_Int charcode )
  117. {
  118. FT_UInt n;
  119. const FT_String* glyph_name;
  120. FT_Service_PsCMaps psnames = decoder->psnames;
  121. /* check range of standard char code */
  122. if ( charcode < 0 || charcode > 255 )
  123. return -1;
  124. glyph_name = psnames->adobe_std_strings(
  125. psnames->adobe_std_encoding[charcode]);
  126. for ( n = 0; n < decoder->num_glyphs; n++ )
  127. {
  128. FT_String* name = (FT_String*)decoder->glyph_names[n];
  129. if ( name &&
  130. name[0] == glyph_name[0] &&
  131. ft_strcmp( name, glyph_name ) == 0 )
  132. return n;
  133. }
  134. return -1;
  135. }
  136. /*************************************************************************/
  137. /* */
  138. /* <Function> */
  139. /* t1operator_seac */
  140. /* */
  141. /* <Description> */
  142. /* Implements the `seac' Type 1 operator for a Type 1 decoder. */
  143. /* */
  144. /* <Input> */
  145. /* decoder :: The current CID decoder. */
  146. /* */
  147. /* asb :: The accent's side bearing. */
  148. /* */
  149. /* adx :: The horizontal offset of the accent. */
  150. /* */
  151. /* ady :: The vertical offset of the accent. */
  152. /* */
  153. /* bchar :: The base character's StandardEncoding charcode. */
  154. /* */
  155. /* achar :: The accent character's StandardEncoding charcode. */
  156. /* */
  157. /* <Return> */
  158. /* FreeType error code. 0 means success. */
  159. /* */
  160. static FT_Error
  161. t1operator_seac( T1_Decoder decoder,
  162. FT_Pos asb,
  163. FT_Pos adx,
  164. FT_Pos ady,
  165. FT_Int bchar,
  166. FT_Int achar )
  167. {
  168. FT_Error error;
  169. FT_Int bchar_index, achar_index;
  170. #if 0
  171. FT_Int n_base_points;
  172. FT_Outline* base = decoder->builder.base;
  173. #endif
  174. FT_Vector left_bearing, advance;
  175. #ifdef FT_CONFIG_OPTION_INCREMENTAL
  176. T1_Face face = (T1_Face)decoder->builder.face;
  177. #endif
  178. if ( decoder->seac )
  179. {
  180. FT_ERROR(( "t1operator_seac: invalid nested seac\n" ));
  181. return PSaux_Err_Syntax_Error;
  182. }
  183. /* seac weirdness */
  184. adx += decoder->builder.left_bearing.x;
  185. /* `glyph_names' is set to 0 for CID fonts which do not */
  186. /* include an encoding. How can we deal with these? */
  187. #ifdef FT_CONFIG_OPTION_INCREMENTAL
  188. if ( decoder->glyph_names == 0 &&
  189. !face->root.internal->incremental_interface )
  190. #else
  191. if ( decoder->glyph_names == 0 )
  192. #endif /* FT_CONFIG_OPTION_INCREMENTAL */
  193. {
  194. FT_ERROR(( "t1operator_seac:"
  195. " glyph names table not available in this font\n" ));
  196. return PSaux_Err_Syntax_Error;
  197. }
  198. #ifdef FT_CONFIG_OPTION_INCREMENTAL
  199. if ( face->root.internal->incremental_interface )
  200. {
  201. /* the caller must handle the font encoding also */
  202. bchar_index = bchar;
  203. achar_index = achar;
  204. }
  205. else
  206. #endif
  207. {
  208. bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );
  209. achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );
  210. }
  211. if ( bchar_index < 0 || achar_index < 0 )
  212. {
  213. FT_ERROR(( "t1operator_seac:"
  214. " invalid seac character code arguments\n" ));
  215. return PSaux_Err_Syntax_Error;
  216. }
  217. /* if we are trying to load a composite glyph, do not load the */
  218. /* accent character and return the array of subglyphs. */
  219. if ( decoder->builder.no_recurse )
  220. {
  221. FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
  222. FT_GlyphLoader loader = glyph->internal->loader;
  223. FT_SubGlyph subg;
  224. /* reallocate subglyph array if necessary */
  225. error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
  226. if ( error )
  227. goto Exit;
  228. subg = loader->current.subglyphs;
  229. /* subglyph 0 = base character */
  230. subg->index = bchar_index;
  231. subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
  232. FT_SUBGLYPH_FLAG_USE_MY_METRICS;
  233. subg->arg1 = 0;
  234. subg->arg2 = 0;
  235. subg++;
  236. /* subglyph 1 = accent character */
  237. subg->index = achar_index;
  238. subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
  239. subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb );
  240. subg->arg2 = (FT_Int)FIXED_TO_INT( ady );
  241. /* set up remaining glyph fields */
  242. glyph->num_subglyphs = 2;
  243. glyph->subglyphs = loader->base.subglyphs;
  244. glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
  245. loader->current.num_subglyphs = 2;
  246. goto Exit;
  247. }
  248. /* First load `bchar' in builder */
  249. /* now load the unscaled outline */
  250. FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
  251. /* the seac operator must not be nested */
  252. decoder->seac = TRUE;
  253. error = t1_decoder_parse_glyph( decoder, bchar_index );
  254. decoder->seac = FALSE;
  255. if ( error )
  256. goto Exit;
  257. /* save the left bearing and width of the base character */
  258. /* as they will be erased by the next load. */
  259. left_bearing = decoder->builder.left_bearing;
  260. advance = decoder->builder.advance;
  261. decoder->builder.left_bearing.x = 0;
  262. decoder->builder.left_bearing.y = 0;
  263. decoder->builder.pos_x = adx - asb;
  264. decoder->builder.pos_y = ady;
  265. /* Now load `achar' on top of */
  266. /* the base outline */
  267. /* the seac operator must not be nested */
  268. decoder->seac = TRUE;
  269. error = t1_decoder_parse_glyph( decoder, achar_index );
  270. decoder->seac = FALSE;
  271. if ( error )
  272. goto Exit;
  273. /* restore the left side bearing and */
  274. /* advance width of the base character */
  275. decoder->builder.left_bearing = left_bearing;
  276. decoder->builder.advance = advance;
  277. decoder->builder.pos_x = 0;
  278. decoder->builder.pos_y = 0;
  279. Exit:
  280. return error;
  281. }
  282. /*************************************************************************/
  283. /* */
  284. /* <Function> */
  285. /* t1_decoder_parse_charstrings */
  286. /* */
  287. /* <Description> */
  288. /* Parses a given Type 1 charstrings program. */
  289. /* */
  290. /* <Input> */
  291. /* decoder :: The current Type 1 decoder. */
  292. /* */
  293. /* charstring_base :: The base address of the charstring stream. */
  294. /* */
  295. /* charstring_len :: The length in bytes of the charstring stream. */
  296. /* */
  297. /* <Return> */
  298. /* FreeType error code. 0 means success. */
  299. /* */
  300. FT_LOCAL_DEF( FT_Error )
  301. t1_decoder_parse_charstrings( T1_Decoder decoder,
  302. FT_Byte* charstring_base,
  303. FT_UInt charstring_len )
  304. {
  305. FT_Error error;
  306. T1_Decoder_Zone zone;
  307. FT_Byte* ip;
  308. FT_Byte* limit;
  309. T1_Builder builder = &decoder->builder;
  310. FT_Pos x, y, orig_x, orig_y;
  311. FT_Int known_othersubr_result_cnt = 0;
  312. FT_Int unknown_othersubr_result_cnt = 0;
  313. FT_Bool large_int;
  314. FT_Fixed seed;
  315. T1_Hints_Funcs hinter;
  316. #ifdef FT_DEBUG_LEVEL_TRACE
  317. FT_Bool bol = TRUE;
  318. #endif
  319. /* we don't want to touch the source code -- use macro trick */
  320. #define start_point t1_builder_start_point
  321. #define check_points t1_builder_check_points
  322. #define add_point t1_builder_add_point
  323. #define add_point1 t1_builder_add_point1
  324. #define add_contour t1_builder_add_contour
  325. #define close_contour t1_builder_close_contour
  326. /* compute random seed from stack address of parameter */
  327. seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^
  328. (FT_PtrDist)(char*)&decoder ^
  329. (FT_PtrDist)(char*)&charstring_base ) &
  330. FT_ULONG_MAX ) ;
  331. seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
  332. if ( seed == 0 )
  333. seed = 0x7384;
  334. /* First of all, initialize the decoder */
  335. decoder->top = decoder->stack;
  336. decoder->zone = decoder->zones;
  337. zone = decoder->zones;
  338. builder->parse_state = T1_Parse_Start;
  339. hinter = (T1_Hints_Funcs)builder->hints_funcs;
  340. /* a font that reads BuildCharArray without setting */
  341. /* its values first is buggy, but ... */
  342. FT_ASSERT( ( decoder->len_buildchar == 0 ) ==
  343. ( decoder->buildchar == NULL ) );
  344. if ( decoder->len_buildchar > 0 )
  345. ft_memset( &decoder->buildchar[0],
  346. 0,
  347. sizeof( decoder->buildchar[0] ) * decoder->len_buildchar );
  348. FT_TRACE4(( "\n"
  349. "Start charstring\n" ));
  350. zone->base = charstring_base;
  351. limit = zone->limit = charstring_base + charstring_len;
  352. ip = zone->cursor = zone->base;
  353. error = PSaux_Err_Ok;
  354. x = orig_x = builder->pos_x;
  355. y = orig_y = builder->pos_y;
  356. /* begin hints recording session, if any */
  357. if ( hinter )
  358. hinter->open( hinter->hints );
  359. large_int = FALSE;
  360. /* now, execute loop */
  361. while ( ip < limit )
  362. {
  363. FT_Long* top = decoder->top;
  364. T1_Operator op = op_none;
  365. FT_Int32 value = 0;
  366. FT_ASSERT( known_othersubr_result_cnt == 0 ||
  367. unknown_othersubr_result_cnt == 0 );
  368. #ifdef FT_DEBUG_LEVEL_TRACE
  369. if ( bol )
  370. {
  371. FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
  372. bol = FALSE;
  373. }
  374. #endif
  375. /*********************************************************************/
  376. /* */
  377. /* Decode operator or operand */
  378. /* */
  379. /* */
  380. /* first of all, decompress operator or value */
  381. switch ( *ip++ )
  382. {
  383. case 1:
  384. op = op_hstem;
  385. break;
  386. case 3:
  387. op = op_vstem;
  388. break;
  389. case 4:
  390. op = op_vmoveto;
  391. break;
  392. case 5:
  393. op = op_rlineto;
  394. break;
  395. case 6:
  396. op = op_hlineto;
  397. break;
  398. case 7:
  399. op = op_vlineto;
  400. break;
  401. case 8:
  402. op = op_rrcurveto;
  403. break;
  404. case 9:
  405. op = op_closepath;
  406. break;
  407. case 10:
  408. op = op_callsubr;
  409. break;
  410. case 11:
  411. op = op_return;
  412. break;
  413. case 13:
  414. op = op_hsbw;
  415. break;
  416. case 14:
  417. op = op_endchar;
  418. break;
  419. case 15: /* undocumented, obsolete operator */
  420. op = op_unknown15;
  421. break;
  422. case 21:
  423. op = op_rmoveto;
  424. break;
  425. case 22:
  426. op = op_hmoveto;
  427. break;
  428. case 30:
  429. op = op_vhcurveto;
  430. break;
  431. case 31:
  432. op = op_hvcurveto;
  433. break;
  434. case 12:
  435. if ( ip > limit )
  436. {
  437. FT_ERROR(( "t1_decoder_parse_charstrings:"
  438. " invalid escape (12+EOF)\n" ));
  439. goto Syntax_Error;
  440. }
  441. switch ( *ip++ )
  442. {
  443. case 0:
  444. op = op_dotsection;
  445. break;
  446. case 1:
  447. op = op_vstem3;
  448. break;
  449. case 2:
  450. op = op_hstem3;
  451. break;
  452. case 6:
  453. op = op_seac;
  454. break;
  455. case 7:
  456. op = op_sbw;
  457. break;
  458. case 12:
  459. op = op_div;
  460. break;
  461. case 16:
  462. op = op_callothersubr;
  463. break;
  464. case 17:
  465. op = op_pop;
  466. break;
  467. case 33:
  468. op = op_setcurrentpoint;
  469. break;
  470. default:
  471. FT_ERROR(( "t1_decoder_parse_charstrings:"
  472. " invalid escape (12+%d)\n",
  473. ip[-1] ));
  474. goto Syntax_Error;
  475. }
  476. break;
  477. case 255: /* four bytes integer */
  478. if ( ip + 4 > limit )
  479. {
  480. FT_ERROR(( "t1_decoder_parse_charstrings:"
  481. " unexpected EOF in integer\n" ));
  482. goto Syntax_Error;
  483. }
  484. value = (FT_Int32)( ( (FT_Long)ip[0] << 24 ) |
  485. ( (FT_Long)ip[1] << 16 ) |
  486. ( (FT_Long)ip[2] << 8 ) |
  487. ip[3] );
  488. ip += 4;
  489. /* According to the specification, values > 32000 or < -32000 must */
  490. /* be followed by a `div' operator to make the result be in the */
  491. /* range [-32000;32000]. We expect that the second argument of */
  492. /* `div' is not a large number. Additionally, we don't handle */
  493. /* stuff like `<large1> <large2> <num> div <num> div' or */
  494. /* <large1> <large2> <num> div div'. This is probably not allowed */
  495. /* anyway. */
  496. if ( value > 32000 || value < -32000 )
  497. {
  498. if ( large_int )
  499. {
  500. FT_ERROR(( "t1_decoder_parse_charstrings:"
  501. " no `div' after large integer\n" ));
  502. }
  503. else
  504. large_int = TRUE;
  505. }
  506. else
  507. {
  508. if ( !large_int )
  509. value <<= 16;
  510. }
  511. break;
  512. default:
  513. if ( ip[-1] >= 32 )
  514. {
  515. if ( ip[-1] < 247 )
  516. value = (FT_Int32)ip[-1] - 139;
  517. else
  518. {
  519. if ( ++ip > limit )
  520. {
  521. FT_ERROR(( "t1_decoder_parse_charstrings:"
  522. " unexpected EOF in integer\n" ));
  523. goto Syntax_Error;
  524. }
  525. if ( ip[-2] < 251 )
  526. value = ( ( (FT_Int32)ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
  527. else
  528. value = -( ( ( (FT_Int32)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
  529. }
  530. if ( !large_int )
  531. value <<= 16;
  532. }
  533. else
  534. {
  535. FT_ERROR(( "t1_decoder_parse_charstrings:"
  536. " invalid byte (%d)\n", ip[-1] ));
  537. goto Syntax_Error;
  538. }
  539. }
  540. if ( unknown_othersubr_result_cnt > 0 )
  541. {
  542. switch ( op )
  543. {
  544. case op_callsubr:
  545. case op_return:
  546. case op_none:
  547. case op_pop:
  548. break;
  549. default:
  550. /* all operands have been transferred by previous pops */
  551. unknown_othersubr_result_cnt = 0;
  552. break;
  553. }
  554. }
  555. if ( large_int && !( op == op_none || op == op_div ) )
  556. {
  557. FT_ERROR(( "t1_decoder_parse_charstrings:"
  558. " no `div' after large integer\n" ));
  559. large_int = FALSE;
  560. }
  561. /*********************************************************************/
  562. /* */
  563. /* Push value on stack, or process operator */
  564. /* */
  565. /* */
  566. if ( op == op_none )
  567. {
  568. if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
  569. {
  570. FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" ));
  571. goto Syntax_Error;
  572. }
  573. #ifdef FT_DEBUG_LEVEL_TRACE
  574. if ( large_int )
  575. FT_TRACE4(( " %ld", value ));
  576. else
  577. FT_TRACE4(( " %ld", (FT_Int32)( value >> 16 ) ));
  578. #endif
  579. *top++ = value;
  580. decoder->top = top;
  581. }
  582. else if ( op == op_callothersubr ) /* callothersubr */
  583. {
  584. FT_Int subr_no;
  585. FT_Int arg_cnt;
  586. #ifdef FT_DEBUG_LEVEL_TRACE
  587. FT_TRACE4(( " callothersubr\n" ));
  588. bol = TRUE;
  589. #endif
  590. if ( top - decoder->stack < 2 )
  591. goto Stack_Underflow;
  592. top -= 2;
  593. subr_no = (FT_Int)( top[1] >> 16 );
  594. arg_cnt = (FT_Int)( top[0] >> 16 );
  595. /***********************************************************/
  596. /* */
  597. /* remove all operands to callothersubr from the stack */
  598. /* */
  599. /* for handled othersubrs, where we know the number of */
  600. /* arguments, we increase the stack by the value of */
  601. /* known_othersubr_result_cnt */
  602. /* */
  603. /* for unhandled othersubrs the following pops adjust the */
  604. /* stack pointer as necessary */
  605. if ( arg_cnt > top - decoder->stack )
  606. goto Stack_Underflow;
  607. top -= arg_cnt;
  608. known_othersubr_result_cnt = 0;
  609. unknown_othersubr_result_cnt = 0;
  610. /* XXX TODO: The checks to `arg_count == <whatever>' */
  611. /* might not be correct; an othersubr expects a certain */
  612. /* number of operands on the PostScript stack (as opposed */
  613. /* to the T1 stack) but it doesn't have to put them there */
  614. /* by itself; previous othersubrs might have left the */
  615. /* operands there if they were not followed by an */
  616. /* appropriate number of pops */
  617. /* */
  618. /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */
  619. /* accept a font that contains charstrings like */
  620. /* */
  621. /* 100 200 2 20 callothersubr */
  622. /* 300 1 20 callothersubr pop */
  623. /* */
  624. /* Perhaps this is the reason why BuildCharArray exists. */
  625. switch ( subr_no )
  626. {
  627. case 1: /* start flex feature */
  628. if ( arg_cnt != 0 )
  629. goto Unexpected_OtherSubr;
  630. decoder->flex_state = 1;
  631. decoder->num_flex_vectors = 0;
  632. if ( start_point( builder, x, y ) ||
  633. check_points( builder, 6 ) )
  634. goto Fail;
  635. break;
  636. case 2: /* add flex vectors */
  637. {
  638. FT_Int idx;
  639. if ( arg_cnt != 0 )
  640. goto Unexpected_OtherSubr;
  641. /* note that we should not add a point for index 0; */
  642. /* this will move our current position to the flex */
  643. /* point without adding any point to the outline */
  644. idx = decoder->num_flex_vectors++;
  645. if ( idx > 0 && idx < 7 )
  646. add_point( builder,
  647. x,
  648. y,
  649. (FT_Byte)( idx == 3 || idx == 6 ) );
  650. }
  651. break;
  652. case 0: /* end flex feature */
  653. if ( arg_cnt != 3 )
  654. goto Unexpected_OtherSubr;
  655. if ( decoder->flex_state == 0 ||
  656. decoder->num_flex_vectors != 7 )
  657. {
  658. FT_ERROR(( "t1_decoder_parse_charstrings:"
  659. " unexpected flex end\n" ));
  660. goto Syntax_Error;
  661. }
  662. /* the two `results' are popped by the following setcurrentpoint */
  663. known_othersubr_result_cnt = 2;
  664. break;
  665. case 3: /* change hints */
  666. if ( arg_cnt != 1 )
  667. goto Unexpected_OtherSubr;
  668. known_othersubr_result_cnt = 1;
  669. if ( hinter )
  670. hinter->reset( hinter->hints, builder->current->n_points );
  671. break;
  672. case 12:
  673. case 13:
  674. /* counter control hints, clear stack */
  675. top = decoder->stack;
  676. break;
  677. case 14:
  678. case 15:
  679. case 16:
  680. case 17:
  681. case 18: /* multiple masters */
  682. {
  683. PS_Blend blend = decoder->blend;
  684. FT_UInt num_points, nn, mm;
  685. FT_Long* delta;
  686. FT_Long* values;
  687. if ( !blend )
  688. {
  689. FT_ERROR(( "t1_decoder_parse_charstrings:"
  690. " unexpected multiple masters operator\n" ));
  691. goto Syntax_Error;
  692. }
  693. num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 );
  694. if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) )
  695. {
  696. FT_ERROR(( "t1_decoder_parse_charstrings:"
  697. " incorrect number of multiple masters arguments\n" ));
  698. goto Syntax_Error;
  699. }
  700. /* we want to compute: */
  701. /* */
  702. /* a0*w0 + a1*w1 + ... + ak*wk */
  703. /* */
  704. /* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */
  705. /* however, given that w0 + w1 + ... + wk == 1, we can */
  706. /* rewrite it easily as: */
  707. /* */
  708. /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */
  709. /* */
  710. /* where k == num_designs-1 */
  711. /* */
  712. /* I guess that's why it's written in this `compact' */
  713. /* form. */
  714. /* */
  715. delta = top + num_points;
  716. values = top;
  717. for ( nn = 0; nn < num_points; nn++ )
  718. {
  719. FT_Long tmp = values[0];
  720. for ( mm = 1; mm < blend->num_designs; mm++ )
  721. tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );
  722. *values++ = tmp;
  723. }
  724. known_othersubr_result_cnt = num_points;
  725. break;
  726. }
  727. case 19:
  728. /* <idx> 1 19 callothersubr */
  729. /* => replace elements starting from index cvi( <idx> ) */
  730. /* of BuildCharArray with WeightVector */
  731. {
  732. FT_Int idx;
  733. PS_Blend blend = decoder->blend;
  734. if ( arg_cnt != 1 || blend == NULL )
  735. goto Unexpected_OtherSubr;
  736. idx = (FT_Int)( top[0] >> 16 );
  737. if ( idx < 0 ||
  738. idx + blend->num_designs > decoder->len_buildchar )
  739. goto Unexpected_OtherSubr;
  740. ft_memcpy( &decoder->buildchar[idx],
  741. blend->weight_vector,
  742. blend->num_designs *
  743. sizeof( blend->weight_vector[0] ) );
  744. }
  745. break;
  746. case 20:
  747. /* <arg1> <arg2> 2 20 callothersubr pop */
  748. /* ==> push <arg1> + <arg2> onto T1 stack */
  749. if ( arg_cnt != 2 )
  750. goto Unexpected_OtherSubr;
  751. top[0] += top[1]; /* XXX (over|under)flow */
  752. known_othersubr_result_cnt = 1;
  753. break;
  754. case 21:
  755. /* <arg1> <arg2> 2 21 callothersubr pop */
  756. /* ==> push <arg1> - <arg2> onto T1 stack */
  757. if ( arg_cnt != 2 )
  758. goto Unexpected_OtherSubr;
  759. top[0] -= top[1]; /* XXX (over|under)flow */
  760. known_othersubr_result_cnt = 1;
  761. break;
  762. case 22:
  763. /* <arg1> <arg2> 2 22 callothersubr pop */
  764. /* ==> push <arg1> * <arg2> onto T1 stack */
  765. if ( arg_cnt != 2 )
  766. goto Unexpected_OtherSubr;
  767. top[0] = FT_MulFix( top[0], top[1] );
  768. known_othersubr_result_cnt = 1;
  769. break;
  770. case 23:
  771. /* <arg1> <arg2> 2 23 callothersubr pop */
  772. /* ==> push <arg1> / <arg2> onto T1 stack */
  773. if ( arg_cnt != 2 || top[1] == 0 )
  774. goto Unexpected_OtherSubr;
  775. top[0] = FT_DivFix( top[0], top[1] );
  776. known_othersubr_result_cnt = 1;
  777. break;
  778. case 24:
  779. /* <val> <idx> 2 24 callothersubr */
  780. /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
  781. {
  782. FT_Int idx;
  783. PS_Blend blend = decoder->blend;
  784. if ( arg_cnt != 2 || blend == NULL )
  785. goto Unexpected_OtherSubr;
  786. idx = (FT_Int)( top[1] >> 16 );
  787. if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
  788. goto Unexpected_OtherSubr;
  789. decoder->buildchar[idx] = top[0];
  790. }
  791. break;
  792. case 25:
  793. /* <idx> 1 25 callothersubr pop */
  794. /* ==> push BuildCharArray[cvi( idx )] */
  795. /* onto T1 stack */
  796. {
  797. FT_Int idx;
  798. PS_Blend blend = decoder->blend;
  799. if ( arg_cnt != 1 || blend == NULL )
  800. goto Unexpected_OtherSubr;
  801. idx = (FT_Int)( top[0] >> 16 );
  802. if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
  803. goto Unexpected_OtherSubr;
  804. top[0] = decoder->buildchar[idx];
  805. }
  806. known_othersubr_result_cnt = 1;
  807. break;
  808. #if 0
  809. case 26:
  810. /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */
  811. /* leave mark on T1 stack */
  812. /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */
  813. XXX which routine has left its mark on the (PostScript) stack?;
  814. break;
  815. #endif
  816. case 27:
  817. /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
  818. /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
  819. /* otherwise push <res2> */
  820. if ( arg_cnt != 4 )
  821. goto Unexpected_OtherSubr;
  822. if ( top[2] > top[3] )
  823. top[0] = top[1];
  824. known_othersubr_result_cnt = 1;
  825. break;
  826. case 28:
  827. /* 0 28 callothersubr pop */
  828. /* => push random value from interval [0, 1) onto stack */
  829. if ( arg_cnt != 0 )
  830. goto Unexpected_OtherSubr;
  831. {
  832. FT_Fixed Rand;
  833. Rand = seed;
  834. if ( Rand >= 0x8000L )
  835. Rand++;
  836. top[0] = Rand;
  837. seed = FT_MulFix( seed, 0x10000L - seed );
  838. if ( seed == 0 )
  839. seed += 0x2873;
  840. }
  841. known_othersubr_result_cnt = 1;
  842. break;
  843. default:
  844. FT_ERROR(( "t1_decoder_parse_charstrings:"
  845. " unknown othersubr [%d %d], wish me luck\n",
  846. arg_cnt, subr_no ));
  847. unknown_othersubr_result_cnt = arg_cnt;
  848. break;
  849. Unexpected_OtherSubr:
  850. FT_ERROR(( "t1_decoder_parse_charstrings:"
  851. " invalid othersubr [%d %d]\n", arg_cnt, subr_no ));
  852. goto Syntax_Error;
  853. }
  854. top += known_othersubr_result_cnt;
  855. decoder->top = top;
  856. }
  857. else /* general operator */
  858. {
  859. FT_Int num_args = t1_args_count[op];
  860. FT_ASSERT( num_args >= 0 );
  861. if ( top - decoder->stack < num_args )
  862. goto Stack_Underflow;
  863. /* XXX Operators usually take their operands from the */
  864. /* bottom of the stack, i.e., the operands are */
  865. /* decoder->stack[0], ..., decoder->stack[num_args - 1]; */
  866. /* only div, callsubr, and callothersubr are different. */
  867. /* In practice it doesn't matter (?). */
  868. #ifdef FT_DEBUG_LEVEL_TRACE
  869. switch ( op )
  870. {
  871. case op_callsubr:
  872. case op_div:
  873. case op_callothersubr:
  874. case op_pop:
  875. case op_return:
  876. break;
  877. default:
  878. if ( top - decoder->stack != num_args )
  879. FT_TRACE0(( "t1_decoder_parse_charstrings:"
  880. " too much operands on the stack"
  881. " (seen %d, expected %d)\n",
  882. top - decoder->stack, num_args ));
  883. break;
  884. }
  885. #endif /* FT_DEBUG_LEVEL_TRACE */
  886. top -= num_args;
  887. switch ( op )
  888. {
  889. case op_endchar:
  890. FT_TRACE4(( " endchar\n" ));
  891. close_contour( builder );
  892. /* close hints recording session */
  893. if ( hinter )
  894. {
  895. if ( hinter->close( hinter->hints, builder->current->n_points ) )
  896. goto Syntax_Error;
  897. /* apply hints to the loaded glyph outline now */
  898. hinter->apply( hinter->hints,
  899. builder->current,
  900. (PSH_Globals)builder->hints_globals,
  901. decoder->hint_mode );
  902. }
  903. /* add current outline to the glyph slot */
  904. FT_GlyphLoader_Add( builder->loader );
  905. /* the compiler should optimize away this empty loop but ... */
  906. #ifdef FT_DEBUG_LEVEL_TRACE
  907. if ( decoder->len_buildchar > 0 )
  908. {
  909. FT_UInt i;
  910. FT_TRACE4(( "BuildCharArray = [ " ));
  911. for ( i = 0; i < decoder->len_buildchar; ++i )
  912. FT_TRACE4(( "%d ", decoder->buildchar[ i ] ));
  913. FT_TRACE4(( "]\n" ));
  914. }
  915. #endif /* FT_DEBUG_LEVEL_TRACE */
  916. FT_TRACE4(( "\n" ));
  917. /* return now! */
  918. return PSaux_Err_Ok;
  919. case op_hsbw:
  920. FT_TRACE4(( " hsbw" ));
  921. builder->parse_state = T1_Parse_Have_Width;
  922. builder->left_bearing.x += top[0];
  923. builder->advance.x = top[1];
  924. builder->advance.y = 0;
  925. orig_x = x = builder->pos_x + top[0];
  926. orig_y = y = builder->pos_y;
  927. FT_UNUSED( orig_y );
  928. /* the `metrics_only' indicates that we only want to compute */
  929. /* the glyph's metrics (lsb + advance width), not load the */
  930. /* rest of it; so exit immediately */
  931. if ( builder->metrics_only )
  932. return PSaux_Err_Ok;
  933. break;
  934. case op_seac:
  935. return t1operator_seac( decoder,
  936. top[0],
  937. top[1],
  938. top[2],
  939. (FT_Int)( top[3] >> 16 ),
  940. (FT_Int)( top[4] >> 16 ) );
  941. case op_sbw:
  942. FT_TRACE4(( " sbw" ));
  943. builder->parse_state = T1_Parse_Have_Width;
  944. builder->left_bearing.x += top[0];
  945. builder->left_bearing.y += top[1];
  946. builder->advance.x = top[2];
  947. builder->advance.y = top[3];
  948. x = builder->pos_x + top[0];
  949. y = builder->pos_y + top[1];
  950. /* the `metrics_only' indicates that we only want to compute */
  951. /* the glyph's metrics (lsb + advance width), not load the */
  952. /* rest of it; so exit immediately */
  953. if ( builder->metrics_only )
  954. return PSaux_Err_Ok;
  955. break;
  956. case op_closepath:
  957. FT_TRACE4(( " closepath" ));
  958. /* if there is no path, `closepath' is a no-op */
  959. if ( builder->parse_state == T1_Parse_Have_Path ||
  960. builder->parse_state == T1_Parse_Have_Moveto )
  961. close_contour( builder );
  962. builder->parse_state = T1_Parse_Have_Width;
  963. break;
  964. case op_hlineto:
  965. FT_TRACE4(( " hlineto" ));
  966. if ( start_point( builder, x, y ) )
  967. goto Fail;
  968. x += top[0];
  969. goto Add_Line;
  970. case op_hmoveto:
  971. FT_TRACE4(( " hmoveto" ));
  972. x += top[0];
  973. if ( !decoder->flex_state )
  974. {
  975. if ( builder->parse_state == T1_Parse_Start )
  976. goto Syntax_Error;
  977. builder->parse_state = T1_Parse_Have_Moveto;
  978. }
  979. break;
  980. case op_hvcurveto:
  981. FT_TRACE4(( " hvcurveto" ));
  982. if ( start_point( builder, x, y ) ||
  983. check_points( builder, 3 ) )
  984. goto Fail;
  985. x += top[0];
  986. add_point( builder, x, y, 0 );
  987. x += top[1];
  988. y += top[2];
  989. add_point( builder, x, y, 0 );
  990. y += top[3];
  991. add_point( builder, x, y, 1 );
  992. break;
  993. case op_rlineto:
  994. FT_TRACE4(( " rlineto" ));
  995. if ( start_point( builder, x, y ) )
  996. goto Fail;
  997. x += top[0];
  998. y += top[1];
  999. Add_Line:
  1000. if ( add_point1( builder, x, y ) )
  1001. goto Fail;
  1002. break;
  1003. case op_rmoveto:
  1004. FT_TRACE4(( " rmoveto" ));
  1005. x += top[0];
  1006. y += top[1];
  1007. if ( !decoder->flex_state )
  1008. {
  1009. if ( builder->parse_state == T1_Parse_Start )
  1010. goto Syntax_Error;
  1011. builder->parse_state = T1_Parse_Have_Moveto;
  1012. }
  1013. break;
  1014. case op_rrcurveto:
  1015. FT_TRACE4(( " rrcurveto" ));
  1016. if ( start_point( builder, x, y ) ||
  1017. check_points( builder, 3 ) )
  1018. goto Fail;
  1019. x += top[0];
  1020. y += top[1];
  1021. add_point( builder, x, y, 0 );
  1022. x += top[2];
  1023. y += top[3];
  1024. add_point( builder, x, y, 0 );
  1025. x += top[4];
  1026. y += top[5];
  1027. add_point( builder, x, y, 1 );
  1028. break;
  1029. case op_vhcurveto:
  1030. FT_TRACE4(( " vhcurveto" ));
  1031. if ( start_point( builder, x, y ) ||
  1032. check_points( builder, 3 ) )
  1033. goto Fail;
  1034. y += top[0];
  1035. add_point( builder, x, y, 0 );
  1036. x += top[1];
  1037. y += top[2];
  1038. add_point( builder, x, y, 0 );
  1039. x += top[3];
  1040. add_point( builder, x, y, 1 );
  1041. break;
  1042. case op_vlineto:
  1043. FT_TRACE4(( " vlineto" ));
  1044. if ( start_point( builder, x, y ) )
  1045. goto Fail;
  1046. y += top[0];
  1047. goto Add_Line;
  1048. case op_vmoveto:
  1049. FT_TRACE4(( " vmoveto" ));
  1050. y += top[0];
  1051. if ( !decoder->flex_state )
  1052. {
  1053. if ( builder->parse_state == T1_Parse_Start )
  1054. goto Syntax_Error;
  1055. builder->parse_state = T1_Parse_Have_Moveto;
  1056. }
  1057. break;
  1058. case op_div:
  1059. FT_TRACE4(( " div" ));
  1060. /* if `large_int' is set, we divide unscaled numbers; */
  1061. /* otherwise, we divide numbers in 16.16 format -- */
  1062. /* in both cases, it is the same operation */
  1063. *top = FT_DivFix( top[0], top[1] );
  1064. ++top;
  1065. large_int = FALSE;
  1066. break;
  1067. case op_callsubr:
  1068. {
  1069. FT_Int idx;
  1070. FT_TRACE4(( " callsubr" ));
  1071. idx = (FT_Int)( top[0] >> 16 );
  1072. if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
  1073. {
  1074. FT_ERROR(( "t1_decoder_parse_charstrings:"
  1075. " invalid subrs index\n" ));
  1076. goto Syntax_Error;
  1077. }
  1078. if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
  1079. {
  1080. FT_ERROR(( "t1_decoder_parse_charstrings:"
  1081. " too many nested subrs\n" ));
  1082. goto Syntax_Error;
  1083. }
  1084. zone->cursor = ip; /* save current instruction pointer */
  1085. zone++;
  1086. /* The Type 1 driver stores subroutines without the seed bytes. */
  1087. /* The CID driver stores subroutines with seed bytes. This */
  1088. /* case is taken care of when decoder->subrs_len == 0. */
  1089. zone->base = decoder->subrs[idx];
  1090. if ( decoder->subrs_len )
  1091. zone->limit = zone->base + decoder->subrs_len[idx];
  1092. else
  1093. {
  1094. /* We are using subroutines from a CID font. We must adjust */
  1095. /* for the seed bytes. */
  1096. zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
  1097. zone->limit = decoder->subrs[idx + 1];
  1098. }
  1099. zone->cursor = zone->base;
  1100. if ( !zone->base )
  1101. {
  1102. FT_ERROR(( "t1_decoder_parse_charstrings:"
  1103. " invoking empty subrs\n" ));
  1104. goto Syntax_Error;
  1105. }
  1106. decoder->zone = zone;
  1107. ip = zone->base;
  1108. limit = zone->limit;
  1109. break;
  1110. }
  1111. case op_pop:
  1112. FT_TRACE4(( " pop" ));
  1113. if ( known_othersubr_result_cnt > 0 )
  1114. {
  1115. known_othersubr_result_cnt--;
  1116. /* ignore, we pushed the operands ourselves */
  1117. break;
  1118. }
  1119. if ( unknown_othersubr_result_cnt == 0 )
  1120. {
  1121. FT_ERROR(( "t1_decoder_parse_charstrings:"
  1122. " no more operands for othersubr\n" ));
  1123. goto Syntax_Error;
  1124. }
  1125. unknown_othersubr_result_cnt--;
  1126. top++; /* `push' the operand to callothersubr onto the stack */
  1127. break;
  1128. case op_return:
  1129. FT_TRACE4(( " return" ));
  1130. if ( zone <= decoder->zones )
  1131. {
  1132. FT_ERROR(( "t1_decoder_parse_charstrings:"
  1133. " unexpected return\n" ));
  1134. goto Syntax_Error;
  1135. }
  1136. zone--;
  1137. ip = zone->cursor;
  1138. limit = zone->limit;
  1139. decoder->zone = zone;
  1140. break;
  1141. case op_dotsection:
  1142. FT_TRACE4(( " dotsection" ));
  1143. break;
  1144. case op_hstem:
  1145. FT_TRACE4(( " hstem" ));
  1146. /* record horizontal hint */
  1147. if ( hinter )
  1148. {
  1149. /* top[0] += builder->left_bearing.y; */
  1150. hinter->stem( hinter->hints, 1, top );
  1151. }
  1152. break;
  1153. case op_hstem3:
  1154. FT_TRACE4(( " hstem3" ));
  1155. /* record horizontal counter-controlled hints */
  1156. if ( hinter )
  1157. hinter->stem3( hinter->hints, 1, top );
  1158. break;
  1159. case op_vstem:
  1160. FT_TRACE4(( " vstem" ));
  1161. /* record vertical hint */
  1162. if ( hinter )
  1163. {
  1164. top[0] += orig_x;
  1165. hinter->stem( hinter->hints, 0, top );
  1166. }
  1167. break;
  1168. case op_vstem3:
  1169. FT_TRACE4(( " vstem3" ));
  1170. /* record vertical counter-controlled hints */
  1171. if ( hinter )
  1172. {
  1173. FT_Pos dx = orig_x;
  1174. top[0] += dx;
  1175. top[2] += dx;
  1176. top[4] += dx;
  1177. hinter->stem3( hinter->hints, 0, top );
  1178. }
  1179. break;
  1180. case op_setcurrentpoint:
  1181. FT_TRACE4(( " setcurrentpoint" ));
  1182. /* From the T1 specification, section 6.4: */
  1183. /* */
  1184. /* The setcurrentpoint command is used only in */
  1185. /* conjunction with results from OtherSubrs procedures. */
  1186. /* known_othersubr_result_cnt != 0 is already handled */
  1187. /* above. */
  1188. /* Note, however, that both Ghostscript and Adobe */
  1189. /* Distiller handle this situation by silently ignoring */
  1190. /* the inappropriate `setcurrentpoint' instruction. So */
  1191. /* we do the same. */
  1192. #if 0
  1193. if ( decoder->flex_state != 1 )
  1194. {
  1195. FT_ERROR(( "t1_decoder_parse_charstrings:"
  1196. " unexpected `setcurrentpoint'\n" ));
  1197. goto Syntax_Error;
  1198. }
  1199. else
  1200. #endif
  1201. decoder->flex_state = 0;
  1202. break;
  1203. case op_unknown15:
  1204. FT_TRACE4(( " opcode_15" ));
  1205. /* nothing to do except to pop the two arguments */
  1206. break;
  1207. default:
  1208. FT_ERROR(( "t1_decoder_parse_charstrings:"
  1209. " unhandled opcode %d\n", op ));
  1210. goto Syntax_Error;
  1211. }
  1212. /* XXX Operators usually clear the operand stack; */
  1213. /* only div, callsubr, callothersubr, pop, and */
  1214. /* return are different. */
  1215. /* In practice it doesn't matter (?). */
  1216. decoder->top = top;
  1217. #ifdef FT_DEBUG_LEVEL_TRACE
  1218. FT_TRACE4(( "\n" ));
  1219. bol = TRUE;
  1220. #endif
  1221. } /* general operator processing */
  1222. } /* while ip < limit */
  1223. FT_TRACE4(( "..end..\n\n" ));
  1224. Fail:
  1225. return error;
  1226. Syntax_Error:
  1227. return PSaux_Err_Syntax_Error;
  1228. Stack_Underflow:
  1229. return PSaux_Err_Stack_Underflow;
  1230. }
  1231. /* parse a single Type 1 glyph */
  1232. FT_LOCAL_DEF( FT_Error )
  1233. t1_decoder_parse_glyph( T1_Decoder decoder,
  1234. FT_UInt glyph )
  1235. {
  1236. return decoder->parse_callback( decoder, glyph );
  1237. }
  1238. /* initialize T1 decoder */
  1239. FT_LOCAL_DEF( FT_Error )
  1240. t1_decoder_init( T1_Decoder decoder,
  1241. FT_Face face,
  1242. FT_Size size,
  1243. FT_GlyphSlot slot,
  1244. FT_Byte** glyph_names,
  1245. PS_Blend blend,
  1246. FT_Bool hinting,
  1247. FT_Render_Mode hint_mode,
  1248. T1_Decoder_Callback parse_callback )
  1249. {
  1250. FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
  1251. /* retrieve PSNames interface from list of current modules */
  1252. {
  1253. FT_Service_PsCMaps psnames = 0;
  1254. FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
  1255. if ( !psnames )
  1256. {
  1257. FT_ERROR(( "t1_decoder_init:"
  1258. " the `psnames' module is not available\n" ));
  1259. return PSaux_Err_Unimplemented_Feature;
  1260. }
  1261. decoder->psnames = psnames;
  1262. }
  1263. t1_builder_init( &decoder->builder, face, size, slot, hinting );
  1264. /* decoder->buildchar and decoder->len_buildchar have to be */
  1265. /* initialized by the caller since we cannot know the length */
  1266. /* of the BuildCharArray */
  1267. decoder->num_glyphs = (FT_UInt)face->num_glyphs;
  1268. decoder->glyph_names = glyph_names;
  1269. decoder->hint_mode = hint_mode;
  1270. decoder->blend = blend;
  1271. decoder->parse_callback = parse_callback;
  1272. decoder->funcs = t1_decoder_funcs;
  1273. return PSaux_Err_Ok;
  1274. }
  1275. /* finalize T1 decoder */
  1276. FT_LOCAL_DEF( void )
  1277. t1_decoder_done( T1_Decoder decoder )
  1278. {
  1279. t1_builder_done( &decoder->builder );
  1280. }
  1281. /* END */