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

/src/freetype/src/psaux/t1decode.c

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