/src/freetype/src/cff/cffgload.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 2972 lines · 2012 code · 597 blank · 363 comment · 262 complexity · a4c78591e5a1d86038c4f0b2f8c8ad39 MD5 · raw file

Large files are truncated click here to view the full file

  1. /***************************************************************************/
  2. /* */
  3. /* cffgload.c */
  4. /* */
  5. /* OpenType Glyph Loader (body). */
  6. /* */
  7. /* Copyright 1996-2012 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_DEBUG_H
  19. #include FT_INTERNAL_STREAM_H
  20. #include FT_INTERNAL_SFNT_H
  21. #include FT_OUTLINE_H
  22. #include "cffobjs.h"
  23. #include "cffload.h"
  24. #include "cffgload.h"
  25. #include "cfferrs.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_cffgload
  34. typedef enum CFF_Operator_
  35. {
  36. cff_op_unknown = 0,
  37. cff_op_rmoveto,
  38. cff_op_hmoveto,
  39. cff_op_vmoveto,
  40. cff_op_rlineto,
  41. cff_op_hlineto,
  42. cff_op_vlineto,
  43. cff_op_rrcurveto,
  44. cff_op_hhcurveto,
  45. cff_op_hvcurveto,
  46. cff_op_rcurveline,
  47. cff_op_rlinecurve,
  48. cff_op_vhcurveto,
  49. cff_op_vvcurveto,
  50. cff_op_flex,
  51. cff_op_hflex,
  52. cff_op_hflex1,
  53. cff_op_flex1,
  54. cff_op_endchar,
  55. cff_op_hstem,
  56. cff_op_vstem,
  57. cff_op_hstemhm,
  58. cff_op_vstemhm,
  59. cff_op_hintmask,
  60. cff_op_cntrmask,
  61. cff_op_dotsection, /* deprecated, acts as no-op */
  62. cff_op_abs,
  63. cff_op_add,
  64. cff_op_sub,
  65. cff_op_div,
  66. cff_op_neg,
  67. cff_op_random,
  68. cff_op_mul,
  69. cff_op_sqrt,
  70. cff_op_blend,
  71. cff_op_drop,
  72. cff_op_exch,
  73. cff_op_index,
  74. cff_op_roll,
  75. cff_op_dup,
  76. cff_op_put,
  77. cff_op_get,
  78. cff_op_store,
  79. cff_op_load,
  80. cff_op_and,
  81. cff_op_or,
  82. cff_op_not,
  83. cff_op_eq,
  84. cff_op_ifelse,
  85. cff_op_callsubr,
  86. cff_op_callgsubr,
  87. cff_op_return,
  88. /* Type 1 opcodes: invalid but seen in real life */
  89. cff_op_hsbw,
  90. cff_op_closepath,
  91. cff_op_callothersubr,
  92. cff_op_pop,
  93. cff_op_seac,
  94. cff_op_sbw,
  95. cff_op_setcurrentpoint,
  96. /* do not remove */
  97. cff_op_max
  98. } CFF_Operator;
  99. #define CFF_COUNT_CHECK_WIDTH 0x80
  100. #define CFF_COUNT_EXACT 0x40
  101. #define CFF_COUNT_CLEAR_STACK 0x20
  102. /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */
  103. /* used for checking the width and requested numbers of arguments */
  104. /* only; they are set to zero afterwards */
  105. /* the other two flags are informative only and unused currently */
  106. static const FT_Byte cff_argument_counts[] =
  107. {
  108. 0, /* unknown */
  109. 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
  110. 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
  111. 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
  112. 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
  113. 0 | CFF_COUNT_CLEAR_STACK,
  114. 0 | CFF_COUNT_CLEAR_STACK,
  115. 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
  116. 0 | CFF_COUNT_CLEAR_STACK,
  117. 0 | CFF_COUNT_CLEAR_STACK,
  118. 0 | CFF_COUNT_CLEAR_STACK,
  119. 0 | CFF_COUNT_CLEAR_STACK,
  120. 0 | CFF_COUNT_CLEAR_STACK,
  121. 0 | CFF_COUNT_CLEAR_STACK,
  122. 13, /* flex */
  123. 7,
  124. 9,
  125. 11,
  126. 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
  127. 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
  128. 2 | CFF_COUNT_CHECK_WIDTH,
  129. 2 | CFF_COUNT_CHECK_WIDTH,
  130. 2 | CFF_COUNT_CHECK_WIDTH,
  131. 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */
  132. 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */
  133. 0, /* dotsection */
  134. 1, /* abs */
  135. 2,
  136. 2,
  137. 2,
  138. 1,
  139. 0,
  140. 2,
  141. 1,
  142. 1, /* blend */
  143. 1, /* drop */
  144. 2,
  145. 1,
  146. 2,
  147. 1,
  148. 2, /* put */
  149. 1,
  150. 4,
  151. 3,
  152. 2, /* and */
  153. 2,
  154. 1,
  155. 2,
  156. 4,
  157. 1, /* callsubr */
  158. 1,
  159. 0,
  160. 2, /* hsbw */
  161. 0,
  162. 0,
  163. 0,
  164. 5, /* seac */
  165. 4, /* sbw */
  166. 2 /* setcurrentpoint */
  167. };
  168. /*************************************************************************/
  169. /*************************************************************************/
  170. /*************************************************************************/
  171. /********** *********/
  172. /********** *********/
  173. /********** GENERIC CHARSTRING PARSING *********/
  174. /********** *********/
  175. /********** *********/
  176. /*************************************************************************/
  177. /*************************************************************************/
  178. /*************************************************************************/
  179. /*************************************************************************/
  180. /* */
  181. /* <Function> */
  182. /* cff_builder_init */
  183. /* */
  184. /* <Description> */
  185. /* Initializes a given glyph builder. */
  186. /* */
  187. /* <InOut> */
  188. /* builder :: A pointer to the glyph builder to initialize. */
  189. /* */
  190. /* <Input> */
  191. /* face :: The current face object. */
  192. /* */
  193. /* size :: The current size object. */
  194. /* */
  195. /* glyph :: The current glyph object. */
  196. /* */
  197. /* hinting :: Whether hinting is active. */
  198. /* */
  199. static void
  200. cff_builder_init( CFF_Builder* builder,
  201. TT_Face face,
  202. CFF_Size size,
  203. CFF_GlyphSlot glyph,
  204. FT_Bool hinting )
  205. {
  206. builder->path_begun = 0;
  207. builder->load_points = 1;
  208. builder->face = face;
  209. builder->glyph = glyph;
  210. builder->memory = face->root.memory;
  211. if ( glyph )
  212. {
  213. FT_GlyphLoader loader = glyph->root.internal->loader;
  214. builder->loader = loader;
  215. builder->base = &loader->base.outline;
  216. builder->current = &loader->current.outline;
  217. FT_GlyphLoader_Rewind( loader );
  218. builder->hints_globals = 0;
  219. builder->hints_funcs = 0;
  220. if ( hinting && size )
  221. {
  222. CFF_Internal internal = (CFF_Internal)size->root.internal;
  223. builder->hints_globals = (void *)internal->topfont;
  224. builder->hints_funcs = glyph->root.internal->glyph_hints;
  225. }
  226. }
  227. builder->pos_x = 0;
  228. builder->pos_y = 0;
  229. builder->left_bearing.x = 0;
  230. builder->left_bearing.y = 0;
  231. builder->advance.x = 0;
  232. builder->advance.y = 0;
  233. }
  234. /*************************************************************************/
  235. /* */
  236. /* <Function> */
  237. /* cff_builder_done */
  238. /* */
  239. /* <Description> */
  240. /* Finalizes a given glyph builder. Its contents can still be used */
  241. /* after the call, but the function saves important information */
  242. /* within the corresponding glyph slot. */
  243. /* */
  244. /* <Input> */
  245. /* builder :: A pointer to the glyph builder to finalize. */
  246. /* */
  247. static void
  248. cff_builder_done( CFF_Builder* builder )
  249. {
  250. CFF_GlyphSlot glyph = builder->glyph;
  251. if ( glyph )
  252. glyph->root.outline = *builder->base;
  253. }
  254. /*************************************************************************/
  255. /* */
  256. /* <Function> */
  257. /* cff_compute_bias */
  258. /* */
  259. /* <Description> */
  260. /* Computes the bias value in dependence of the number of glyph */
  261. /* subroutines. */
  262. /* */
  263. /* <Input> */
  264. /* in_charstring_type :: The `CharstringType' value of the top DICT */
  265. /* dictionary. */
  266. /* */
  267. /* num_subrs :: The number of glyph subroutines. */
  268. /* */
  269. /* <Return> */
  270. /* The bias value. */
  271. static FT_Int
  272. cff_compute_bias( FT_Int in_charstring_type,
  273. FT_UInt num_subrs )
  274. {
  275. FT_Int result;
  276. if ( in_charstring_type == 1 )
  277. result = 0;
  278. else if ( num_subrs < 1240 )
  279. result = 107;
  280. else if ( num_subrs < 33900U )
  281. result = 1131;
  282. else
  283. result = 32768U;
  284. return result;
  285. }
  286. /*************************************************************************/
  287. /* */
  288. /* <Function> */
  289. /* cff_decoder_init */
  290. /* */
  291. /* <Description> */
  292. /* Initializes a given glyph decoder. */
  293. /* */
  294. /* <InOut> */
  295. /* decoder :: A pointer to the glyph builder to initialize. */
  296. /* */
  297. /* <Input> */
  298. /* face :: The current face object. */
  299. /* */
  300. /* size :: The current size object. */
  301. /* */
  302. /* slot :: The current glyph object. */
  303. /* */
  304. /* hinting :: Whether hinting is active. */
  305. /* */
  306. /* hint_mode :: The hinting mode. */
  307. /* */
  308. FT_LOCAL_DEF( void )
  309. cff_decoder_init( CFF_Decoder* decoder,
  310. TT_Face face,
  311. CFF_Size size,
  312. CFF_GlyphSlot slot,
  313. FT_Bool hinting,
  314. FT_Render_Mode hint_mode )
  315. {
  316. CFF_Font cff = (CFF_Font)face->extra.data;
  317. /* clear everything */
  318. FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
  319. /* initialize builder */
  320. cff_builder_init( &decoder->builder, face, size, slot, hinting );
  321. /* initialize Type2 decoder */
  322. decoder->cff = cff;
  323. decoder->num_globals = cff->global_subrs_index.count;
  324. decoder->globals = cff->global_subrs;
  325. decoder->globals_bias = cff_compute_bias(
  326. cff->top_font.font_dict.charstring_type,
  327. decoder->num_globals );
  328. decoder->hint_mode = hint_mode;
  329. }
  330. /* this function is used to select the subfont */
  331. /* and the locals subrs array */
  332. FT_LOCAL_DEF( FT_Error )
  333. cff_decoder_prepare( CFF_Decoder* decoder,
  334. CFF_Size size,
  335. FT_UInt glyph_index )
  336. {
  337. CFF_Builder *builder = &decoder->builder;
  338. CFF_Font cff = (CFF_Font)builder->face->extra.data;
  339. CFF_SubFont sub = &cff->top_font;
  340. FT_Error error = CFF_Err_Ok;
  341. /* manage CID fonts */
  342. if ( cff->num_subfonts )
  343. {
  344. FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index );
  345. if ( fd_index >= cff->num_subfonts )
  346. {
  347. FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
  348. error = CFF_Err_Invalid_File_Format;
  349. goto Exit;
  350. }
  351. FT_TRACE3(( "glyph index %d (subfont %d):\n", glyph_index, fd_index ));
  352. sub = cff->subfonts[fd_index];
  353. if ( builder->hints_funcs && size )
  354. {
  355. CFF_Internal internal = (CFF_Internal)size->root.internal;
  356. /* for CFFs without subfonts, this value has already been set */
  357. builder->hints_globals = (void *)internal->subfonts[fd_index];
  358. }
  359. }
  360. #ifdef FT_DEBUG_LEVEL_TRACE
  361. else
  362. FT_TRACE3(( "glyph index %d:\n", glyph_index ));
  363. #endif
  364. decoder->num_locals = sub->local_subrs_index.count;
  365. decoder->locals = sub->local_subrs;
  366. decoder->locals_bias = cff_compute_bias(
  367. decoder->cff->top_font.font_dict.charstring_type,
  368. decoder->num_locals );
  369. decoder->glyph_width = sub->private_dict.default_width;
  370. decoder->nominal_width = sub->private_dict.nominal_width;
  371. Exit:
  372. return error;
  373. }
  374. /* check that there is enough space for `count' more points */
  375. static FT_Error
  376. check_points( CFF_Builder* builder,
  377. FT_Int count )
  378. {
  379. return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
  380. }
  381. /* add a new point, do not check space */
  382. static void
  383. cff_builder_add_point( CFF_Builder* builder,
  384. FT_Pos x,
  385. FT_Pos y,
  386. FT_Byte flag )
  387. {
  388. FT_Outline* outline = builder->current;
  389. if ( builder->load_points )
  390. {
  391. FT_Vector* point = outline->points + outline->n_points;
  392. FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
  393. point->x = x >> 16;
  394. point->y = y >> 16;
  395. *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
  396. }
  397. outline->n_points++;
  398. }
  399. /* check space for a new on-curve point, then add it */
  400. static FT_Error
  401. cff_builder_add_point1( CFF_Builder* builder,
  402. FT_Pos x,
  403. FT_Pos y )
  404. {
  405. FT_Error error;
  406. error = check_points( builder, 1 );
  407. if ( !error )
  408. cff_builder_add_point( builder, x, y, 1 );
  409. return error;
  410. }
  411. /* check space for a new contour, then add it */
  412. static FT_Error
  413. cff_builder_add_contour( CFF_Builder* builder )
  414. {
  415. FT_Outline* outline = builder->current;
  416. FT_Error error;
  417. if ( !builder->load_points )
  418. {
  419. outline->n_contours++;
  420. return CFF_Err_Ok;
  421. }
  422. error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
  423. if ( !error )
  424. {
  425. if ( outline->n_contours > 0 )
  426. outline->contours[outline->n_contours - 1] =
  427. (short)( outline->n_points - 1 );
  428. outline->n_contours++;
  429. }
  430. return error;
  431. }
  432. /* if a path was begun, add its first on-curve point */
  433. static FT_Error
  434. cff_builder_start_point( CFF_Builder* builder,
  435. FT_Pos x,
  436. FT_Pos y )
  437. {
  438. FT_Error error = CFF_Err_Ok;
  439. /* test whether we are building a new contour */
  440. if ( !builder->path_begun )
  441. {
  442. builder->path_begun = 1;
  443. error = cff_builder_add_contour( builder );
  444. if ( !error )
  445. error = cff_builder_add_point1( builder, x, y );
  446. }
  447. return error;
  448. }
  449. /* close the current contour */
  450. static void
  451. cff_builder_close_contour( CFF_Builder* builder )
  452. {
  453. FT_Outline* outline = builder->current;
  454. FT_Int first;
  455. if ( !outline )
  456. return;
  457. first = outline->n_contours <= 1
  458. ? 0 : outline->contours[outline->n_contours - 2] + 1;
  459. /* We must not include the last point in the path if it */
  460. /* is located on the first point. */
  461. if ( outline->n_points > 1 )
  462. {
  463. FT_Vector* p1 = outline->points + first;
  464. FT_Vector* p2 = outline->points + outline->n_points - 1;
  465. FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
  466. /* `delete' last point only if it coincides with the first */
  467. /* point and if it is not a control point (which can happen). */
  468. if ( p1->x == p2->x && p1->y == p2->y )
  469. if ( *control == FT_CURVE_TAG_ON )
  470. outline->n_points--;
  471. }
  472. if ( outline->n_contours > 0 )
  473. {
  474. /* Don't add contours only consisting of one point, i.e., */
  475. /* check whether begin point and last point are the same. */
  476. if ( first == outline->n_points - 1 )
  477. {
  478. outline->n_contours--;
  479. outline->n_points--;
  480. }
  481. else
  482. outline->contours[outline->n_contours - 1] =
  483. (short)( outline->n_points - 1 );
  484. }
  485. }
  486. static FT_Int
  487. cff_lookup_glyph_by_stdcharcode( CFF_Font cff,
  488. FT_Int charcode )
  489. {
  490. FT_UInt n;
  491. FT_UShort glyph_sid;
  492. /* CID-keyed fonts don't have glyph names */
  493. if ( !cff->charset.sids )
  494. return -1;
  495. /* check range of standard char code */
  496. if ( charcode < 0 || charcode > 255 )
  497. return -1;
  498. /* Get code to SID mapping from `cff_standard_encoding'. */
  499. glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode );
  500. for ( n = 0; n < cff->num_glyphs; n++ )
  501. {
  502. if ( cff->charset.sids[n] == glyph_sid )
  503. return n;
  504. }
  505. return -1;
  506. }
  507. static FT_Error
  508. cff_get_glyph_data( TT_Face face,
  509. FT_UInt glyph_index,
  510. FT_Byte** pointer,
  511. FT_ULong* length )
  512. {
  513. #ifdef FT_CONFIG_OPTION_INCREMENTAL
  514. /* For incremental fonts get the character data using the */
  515. /* callback function. */
  516. if ( face->root.internal->incremental_interface )
  517. {
  518. FT_Data data;
  519. FT_Error error =
  520. face->root.internal->incremental_interface->funcs->get_glyph_data(
  521. face->root.internal->incremental_interface->object,
  522. glyph_index, &data );
  523. *pointer = (FT_Byte*)data.pointer;
  524. *length = data.length;
  525. return error;
  526. }
  527. else
  528. #endif /* FT_CONFIG_OPTION_INCREMENTAL */
  529. {
  530. CFF_Font cff = (CFF_Font)(face->extra.data);
  531. return cff_index_access_element( &cff->charstrings_index, glyph_index,
  532. pointer, length );
  533. }
  534. }
  535. static void
  536. cff_free_glyph_data( TT_Face face,
  537. FT_Byte** pointer,
  538. FT_ULong length )
  539. {
  540. #ifndef FT_CONFIG_OPTION_INCREMENTAL
  541. FT_UNUSED( length );
  542. #endif
  543. #ifdef FT_CONFIG_OPTION_INCREMENTAL
  544. /* For incremental fonts get the character data using the */
  545. /* callback function. */
  546. if ( face->root.internal->incremental_interface )
  547. {
  548. FT_Data data;
  549. data.pointer = *pointer;
  550. data.length = length;
  551. face->root.internal->incremental_interface->funcs->free_glyph_data(
  552. face->root.internal->incremental_interface->object, &data );
  553. }
  554. else
  555. #endif /* FT_CONFIG_OPTION_INCREMENTAL */
  556. {
  557. CFF_Font cff = (CFF_Font)(face->extra.data);
  558. cff_index_forget_element( &cff->charstrings_index, pointer );
  559. }
  560. }
  561. static FT_Error
  562. cff_operator_seac( CFF_Decoder* decoder,
  563. FT_Pos asb,
  564. FT_Pos adx,
  565. FT_Pos ady,
  566. FT_Int bchar,
  567. FT_Int achar )
  568. {
  569. FT_Error error;
  570. CFF_Builder* builder = &decoder->builder;
  571. FT_Int bchar_index, achar_index;
  572. TT_Face face = decoder->builder.face;
  573. FT_Vector left_bearing, advance;
  574. FT_Byte* charstring;
  575. FT_ULong charstring_len;
  576. FT_Pos glyph_width;
  577. if ( decoder->seac )
  578. {
  579. FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));
  580. return CFF_Err_Syntax_Error;
  581. }
  582. adx += decoder->builder.left_bearing.x;
  583. ady += decoder->builder.left_bearing.y;
  584. #ifdef FT_CONFIG_OPTION_INCREMENTAL
  585. /* Incremental fonts don't necessarily have valid charsets. */
  586. /* They use the character code, not the glyph index, in this case. */
  587. if ( face->root.internal->incremental_interface )
  588. {
  589. bchar_index = bchar;
  590. achar_index = achar;
  591. }
  592. else
  593. #endif /* FT_CONFIG_OPTION_INCREMENTAL */
  594. {
  595. CFF_Font cff = (CFF_Font)(face->extra.data);
  596. bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
  597. achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
  598. }
  599. if ( bchar_index < 0 || achar_index < 0 )
  600. {
  601. FT_ERROR(( "cff_operator_seac:"
  602. " invalid seac character code arguments\n" ));
  603. return CFF_Err_Syntax_Error;
  604. }
  605. /* If we are trying to load a composite glyph, do not load the */
  606. /* accent character and return the array of subglyphs. */
  607. if ( builder->no_recurse )
  608. {
  609. FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph;
  610. FT_GlyphLoader loader = glyph->internal->loader;
  611. FT_SubGlyph subg;
  612. /* reallocate subglyph array if necessary */
  613. error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
  614. if ( error )
  615. goto Exit;
  616. subg = loader->current.subglyphs;
  617. /* subglyph 0 = base character */
  618. subg->index = bchar_index;
  619. subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
  620. FT_SUBGLYPH_FLAG_USE_MY_METRICS;
  621. subg->arg1 = 0;
  622. subg->arg2 = 0;
  623. subg++;
  624. /* subglyph 1 = accent character */
  625. subg->index = achar_index;
  626. subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
  627. subg->arg1 = (FT_Int)( adx >> 16 );
  628. subg->arg2 = (FT_Int)( ady >> 16 );
  629. /* set up remaining glyph fields */
  630. glyph->num_subglyphs = 2;
  631. glyph->subglyphs = loader->base.subglyphs;
  632. glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
  633. loader->current.num_subglyphs = 2;
  634. }
  635. FT_GlyphLoader_Prepare( builder->loader );
  636. /* First load `bchar' in builder */
  637. error = cff_get_glyph_data( face, bchar_index,
  638. &charstring, &charstring_len );
  639. if ( !error )
  640. {
  641. /* the seac operator must not be nested */
  642. decoder->seac = TRUE;
  643. error = cff_decoder_parse_charstrings( decoder, charstring,
  644. charstring_len );
  645. decoder->seac = FALSE;
  646. cff_free_glyph_data( face, &charstring, charstring_len );
  647. if ( error )
  648. goto Exit;
  649. }
  650. /* Save the left bearing, advance and glyph width of the base */
  651. /* character as they will be erased by the next load. */
  652. left_bearing = builder->left_bearing;
  653. advance = builder->advance;
  654. glyph_width = decoder->glyph_width;
  655. builder->left_bearing.x = 0;
  656. builder->left_bearing.y = 0;
  657. builder->pos_x = adx - asb;
  658. builder->pos_y = ady;
  659. /* Now load `achar' on top of the base outline. */
  660. error = cff_get_glyph_data( face, achar_index,
  661. &charstring, &charstring_len );
  662. if ( !error )
  663. {
  664. /* the seac operator must not be nested */
  665. decoder->seac = TRUE;
  666. error = cff_decoder_parse_charstrings( decoder, charstring,
  667. charstring_len );
  668. decoder->seac = FALSE;
  669. cff_free_glyph_data( face, &charstring, charstring_len );
  670. if ( error )
  671. goto Exit;
  672. }
  673. /* Restore the left side bearing, advance and glyph width */
  674. /* of the base character. */
  675. builder->left_bearing = left_bearing;
  676. builder->advance = advance;
  677. decoder->glyph_width = glyph_width;
  678. builder->pos_x = 0;
  679. builder->pos_y = 0;
  680. Exit:
  681. return error;
  682. }
  683. /*************************************************************************/
  684. /* */
  685. /* <Function> */
  686. /* cff_decoder_parse_charstrings */
  687. /* */
  688. /* <Description> */
  689. /* Parses a given Type 2 charstrings program. */
  690. /* */
  691. /* <InOut> */
  692. /* decoder :: The current Type 1 decoder. */
  693. /* */
  694. /* <Input> */
  695. /* charstring_base :: The base of the charstring stream. */
  696. /* */
  697. /* charstring_len :: The length in bytes of the charstring stream. */
  698. /* */
  699. /* <Return> */
  700. /* FreeType error code. 0 means success. */
  701. /* */
  702. FT_LOCAL_DEF( FT_Error )
  703. cff_decoder_parse_charstrings( CFF_Decoder* decoder,
  704. FT_Byte* charstring_base,
  705. FT_ULong charstring_len )
  706. {
  707. FT_Error error;
  708. CFF_Decoder_Zone* zone;
  709. FT_Byte* ip;
  710. FT_Byte* limit;
  711. CFF_Builder* builder = &decoder->builder;
  712. FT_Pos x, y;
  713. FT_Fixed seed;
  714. FT_Fixed* stack;
  715. FT_Int charstring_type =
  716. decoder->cff->top_font.font_dict.charstring_type;
  717. T2_Hints_Funcs hinter;
  718. /* set default width */
  719. decoder->num_hints = 0;
  720. decoder->read_width = 1;
  721. /* compute random seed from stack address of parameter */
  722. seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^
  723. (FT_PtrDist)(char*)&decoder ^
  724. (FT_PtrDist)(char*)&charstring_base ) &
  725. FT_ULONG_MAX ) ;
  726. seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
  727. if ( seed == 0 )
  728. seed = 0x7384;
  729. /* initialize the decoder */
  730. decoder->top = decoder->stack;
  731. decoder->zone = decoder->zones;
  732. zone = decoder->zones;
  733. stack = decoder->top;
  734. hinter = (T2_Hints_Funcs)builder->hints_funcs;
  735. builder->path_begun = 0;
  736. zone->base = charstring_base;
  737. limit = zone->limit = charstring_base + charstring_len;
  738. ip = zone->cursor = zone->base;
  739. error = CFF_Err_Ok;
  740. x = builder->pos_x;
  741. y = builder->pos_y;
  742. /* begin hints recording session, if any */
  743. if ( hinter )
  744. hinter->open( hinter->hints );
  745. /* now execute loop */
  746. while ( ip < limit )
  747. {
  748. CFF_Operator op;
  749. FT_Byte v;
  750. /********************************************************************/
  751. /* */
  752. /* Decode operator or operand */
  753. /* */
  754. v = *ip++;
  755. if ( v >= 32 || v == 28 )
  756. {
  757. FT_Int shift = 16;
  758. FT_Int32 val;
  759. /* this is an operand, push it on the stack */
  760. if ( v == 28 )
  761. {
  762. if ( ip + 1 >= limit )
  763. goto Syntax_Error;
  764. val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
  765. ip += 2;
  766. }
  767. else if ( v < 247 )
  768. val = (FT_Int32)v - 139;
  769. else if ( v < 251 )
  770. {
  771. if ( ip >= limit )
  772. goto Syntax_Error;
  773. val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108;
  774. }
  775. else if ( v < 255 )
  776. {
  777. if ( ip >= limit )
  778. goto Syntax_Error;
  779. val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108;
  780. }
  781. else
  782. {
  783. if ( ip + 3 >= limit )
  784. goto Syntax_Error;
  785. val = ( (FT_Int32)ip[0] << 24 ) |
  786. ( (FT_Int32)ip[1] << 16 ) |
  787. ( (FT_Int32)ip[2] << 8 ) |
  788. ip[3];
  789. ip += 4;
  790. if ( charstring_type == 2 )
  791. shift = 0;
  792. }
  793. if ( decoder->top - stack >= CFF_MAX_OPERANDS )
  794. goto Stack_Overflow;
  795. val <<= shift;
  796. *decoder->top++ = val;
  797. #ifdef FT_DEBUG_LEVEL_TRACE
  798. if ( !( val & 0xFFFFL ) )
  799. FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) ));
  800. else
  801. FT_TRACE4(( " %.2f", val / 65536.0 ));
  802. #endif
  803. }
  804. else
  805. {
  806. /* The specification says that normally arguments are to be taken */
  807. /* from the bottom of the stack. However, this seems not to be */
  808. /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */
  809. /* arguments similar to a PS interpreter. */
  810. FT_Fixed* args = decoder->top;
  811. FT_Int num_args = (FT_Int)( args - decoder->stack );
  812. FT_Int req_args;
  813. /* find operator */
  814. op = cff_op_unknown;
  815. switch ( v )
  816. {
  817. case 1:
  818. op = cff_op_hstem;
  819. break;
  820. case 3:
  821. op = cff_op_vstem;
  822. break;
  823. case 4:
  824. op = cff_op_vmoveto;
  825. break;
  826. case 5:
  827. op = cff_op_rlineto;
  828. break;
  829. case 6:
  830. op = cff_op_hlineto;
  831. break;
  832. case 7:
  833. op = cff_op_vlineto;
  834. break;
  835. case 8:
  836. op = cff_op_rrcurveto;
  837. break;
  838. case 9:
  839. op = cff_op_closepath;
  840. break;
  841. case 10:
  842. op = cff_op_callsubr;
  843. break;
  844. case 11:
  845. op = cff_op_return;
  846. break;
  847. case 12:
  848. {
  849. if ( ip >= limit )
  850. goto Syntax_Error;
  851. v = *ip++;
  852. switch ( v )
  853. {
  854. case 0:
  855. op = cff_op_dotsection;
  856. break;
  857. case 1: /* this is actually the Type1 vstem3 operator */
  858. op = cff_op_vstem;
  859. break;
  860. case 2: /* this is actually the Type1 hstem3 operator */
  861. op = cff_op_hstem;
  862. break;
  863. case 3:
  864. op = cff_op_and;
  865. break;
  866. case 4:
  867. op = cff_op_or;
  868. break;
  869. case 5:
  870. op = cff_op_not;
  871. break;
  872. case 6:
  873. op = cff_op_seac;
  874. break;
  875. case 7:
  876. op = cff_op_sbw;
  877. break;
  878. case 8:
  879. op = cff_op_store;
  880. break;
  881. case 9:
  882. op = cff_op_abs;
  883. break;
  884. case 10:
  885. op = cff_op_add;
  886. break;
  887. case 11:
  888. op = cff_op_sub;
  889. break;
  890. case 12:
  891. op = cff_op_div;
  892. break;
  893. case 13:
  894. op = cff_op_load;
  895. break;
  896. case 14:
  897. op = cff_op_neg;
  898. break;
  899. case 15:
  900. op = cff_op_eq;
  901. break;
  902. case 16:
  903. op = cff_op_callothersubr;
  904. break;
  905. case 17:
  906. op = cff_op_pop;
  907. break;
  908. case 18:
  909. op = cff_op_drop;
  910. break;
  911. case 20:
  912. op = cff_op_put;
  913. break;
  914. case 21:
  915. op = cff_op_get;
  916. break;
  917. case 22:
  918. op = cff_op_ifelse;
  919. break;
  920. case 23:
  921. op = cff_op_random;
  922. break;
  923. case 24:
  924. op = cff_op_mul;
  925. break;
  926. case 26:
  927. op = cff_op_sqrt;
  928. break;
  929. case 27:
  930. op = cff_op_dup;
  931. break;
  932. case 28:
  933. op = cff_op_exch;
  934. break;
  935. case 29:
  936. op = cff_op_index;
  937. break;
  938. case 30:
  939. op = cff_op_roll;
  940. break;
  941. case 33:
  942. op = cff_op_setcurrentpoint;
  943. break;
  944. case 34:
  945. op = cff_op_hflex;
  946. break;
  947. case 35:
  948. op = cff_op_flex;
  949. break;
  950. case 36:
  951. op = cff_op_hflex1;
  952. break;
  953. case 37:
  954. op = cff_op_flex1;
  955. break;
  956. default:
  957. FT_TRACE4(( " unknown op (12, %d)\n", v ));
  958. break;
  959. }
  960. }
  961. break;
  962. case 13:
  963. op = cff_op_hsbw;
  964. break;
  965. case 14:
  966. op = cff_op_endchar;
  967. break;
  968. case 16:
  969. op = cff_op_blend;
  970. break;
  971. case 18:
  972. op = cff_op_hstemhm;
  973. break;
  974. case 19:
  975. op = cff_op_hintmask;
  976. break;
  977. case 20:
  978. op = cff_op_cntrmask;
  979. break;
  980. case 21:
  981. op = cff_op_rmoveto;
  982. break;
  983. case 22:
  984. op = cff_op_hmoveto;
  985. break;
  986. case 23:
  987. op = cff_op_vstemhm;
  988. break;
  989. case 24:
  990. op = cff_op_rcurveline;
  991. break;
  992. case 25:
  993. op = cff_op_rlinecurve;
  994. break;
  995. case 26:
  996. op = cff_op_vvcurveto;
  997. break;
  998. case 27:
  999. op = cff_op_hhcurveto;
  1000. break;
  1001. case 29:
  1002. op = cff_op_callgsubr;
  1003. break;
  1004. case 30:
  1005. op = cff_op_vhcurveto;
  1006. break;
  1007. case 31:
  1008. op = cff_op_hvcurveto;
  1009. break;
  1010. default:
  1011. FT_TRACE4(( " unknown op (%d)\n", v ));
  1012. break;
  1013. }
  1014. if ( op == cff_op_unknown )
  1015. continue;
  1016. /* check arguments */
  1017. req_args = cff_argument_counts[op];
  1018. if ( req_args & CFF_COUNT_CHECK_WIDTH )
  1019. {
  1020. if ( num_args > 0 && decoder->read_width )
  1021. {
  1022. /* If `nominal_width' is non-zero, the number is really a */
  1023. /* difference against `nominal_width'. Else, the number here */
  1024. /* is truly a width, not a difference against `nominal_width'. */
  1025. /* If the font does not set `nominal_width', then */
  1026. /* `nominal_width' defaults to zero, and so we can set */
  1027. /* `glyph_width' to `nominal_width' plus number on the stack */
  1028. /* -- for either case. */
  1029. FT_Int set_width_ok;
  1030. switch ( op )
  1031. {
  1032. case cff_op_hmoveto:
  1033. case cff_op_vmoveto:
  1034. set_width_ok = num_args & 2;
  1035. break;
  1036. case cff_op_hstem:
  1037. case cff_op_vstem:
  1038. case cff_op_hstemhm:
  1039. case cff_op_vstemhm:
  1040. case cff_op_rmoveto:
  1041. case cff_op_hintmask:
  1042. case cff_op_cntrmask:
  1043. set_width_ok = num_args & 1;
  1044. break;
  1045. case cff_op_endchar:
  1046. /* If there is a width specified for endchar, we either have */
  1047. /* 1 argument or 5 arguments. We like to argue. */
  1048. set_width_ok = ( num_args == 5 ) || ( num_args == 1 );
  1049. break;
  1050. default:
  1051. set_width_ok = 0;
  1052. break;
  1053. }
  1054. if ( set_width_ok )
  1055. {
  1056. decoder->glyph_width = decoder->nominal_width +
  1057. ( stack[0] >> 16 );
  1058. if ( decoder->width_only )
  1059. {
  1060. /* we only want the advance width; stop here */
  1061. break;
  1062. }
  1063. /* Consumed an argument. */
  1064. num_args--;
  1065. }
  1066. }
  1067. decoder->read_width = 0;
  1068. req_args = 0;
  1069. }
  1070. req_args &= 0x000F;
  1071. if ( num_args < req_args )
  1072. goto Stack_Underflow;
  1073. args -= req_args;
  1074. num_args -= req_args;
  1075. /* At this point, `args' points to the first argument of the */
  1076. /* operand in case `req_args' isn't zero. Otherwise, we have */
  1077. /* to adjust `args' manually. */
  1078. /* Note that we only pop arguments from the stack which we */
  1079. /* really need and can digest so that we can continue in case */
  1080. /* of superfluous stack elements. */
  1081. switch ( op )
  1082. {
  1083. case cff_op_hstem:
  1084. case cff_op_vstem:
  1085. case cff_op_hstemhm:
  1086. case cff_op_vstemhm:
  1087. /* the number of arguments is always even here */
  1088. FT_TRACE4((
  1089. op == cff_op_hstem ? " hstem\n" :
  1090. ( op == cff_op_vstem ? " vstem\n" :
  1091. ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) ));
  1092. if ( hinter )
  1093. hinter->stems( hinter->hints,
  1094. ( op == cff_op_hstem || op == cff_op_hstemhm ),
  1095. num_args / 2,
  1096. args - ( num_args & ~1 ) );
  1097. decoder->num_hints += num_args / 2;
  1098. args = stack;
  1099. break;
  1100. case cff_op_hintmask:
  1101. case cff_op_cntrmask:
  1102. FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
  1103. /* implement vstem when needed -- */
  1104. /* the specification doesn't say it, but this also works */
  1105. /* with the 'cntrmask' operator */
  1106. /* */
  1107. if ( num_args > 0 )
  1108. {
  1109. if ( hinter )
  1110. hinter->stems( hinter->hints,
  1111. 0,
  1112. num_args / 2,
  1113. args - ( num_args & ~1 ) );
  1114. decoder->num_hints += num_args / 2;
  1115. }
  1116. /* In a valid charstring there must be at least one byte */
  1117. /* after `hintmask' or `cntrmask' (e.g., for a `return' */
  1118. /* instruction). Additionally, there must be space for */
  1119. /* `num_hints' bits. */
  1120. if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit )
  1121. goto Syntax_Error;
  1122. if ( hinter )
  1123. {
  1124. if ( op == cff_op_hintmask )
  1125. hinter->hintmask( hinter->hints,
  1126. builder->current->n_points,
  1127. decoder->num_hints,
  1128. ip );
  1129. else
  1130. hinter->counter( hinter->hints,
  1131. decoder->num_hints,
  1132. ip );
  1133. }
  1134. #ifdef FT_DEBUG_LEVEL_TRACE
  1135. {
  1136. FT_UInt maskbyte;
  1137. FT_TRACE4(( " (maskbytes:" ));
  1138. for ( maskbyte = 0;
  1139. maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 );
  1140. maskbyte++, ip++ )
  1141. FT_TRACE4(( " 0x%02X", *ip ));
  1142. FT_TRACE4(( ")\n" ));
  1143. }
  1144. #else
  1145. ip += ( decoder->num_hints + 7 ) >> 3;
  1146. #endif
  1147. args = stack;
  1148. break;
  1149. case cff_op_rmoveto:
  1150. FT_TRACE4(( " rmoveto\n" ));
  1151. cff_builder_close_contour( builder );
  1152. builder->path_begun = 0;
  1153. x += args[-2];
  1154. y += args[-1];
  1155. args = stack;
  1156. break;
  1157. case cff_op_vmoveto:
  1158. FT_TRACE4(( " vmoveto\n" ));
  1159. cff_builder_close_contour( builder );
  1160. builder->path_begun = 0;
  1161. y += args[-1];
  1162. args = stack;
  1163. break;
  1164. case cff_op_hmoveto:
  1165. FT_TRACE4(( " hmoveto\n" ));
  1166. cff_builder_close_contour( builder );
  1167. builder->path_begun = 0;
  1168. x += args[-1];
  1169. args = stack;
  1170. break;
  1171. case cff_op_rlineto:
  1172. FT_TRACE4(( " rlineto\n" ));
  1173. if ( cff_builder_start_point ( builder, x, y ) ||
  1174. check_points( builder, num_args / 2 ) )
  1175. goto Fail;
  1176. if ( num_args < 2 )
  1177. goto Stack_Underflow;
  1178. args -= num_args & ~1;
  1179. while ( args < decoder->top )
  1180. {
  1181. x += args[0];
  1182. y += args[1];
  1183. cff_builder_add_point( builder, x, y, 1 );
  1184. args += 2;
  1185. }
  1186. args = stack;
  1187. break;
  1188. case cff_op_hlineto:
  1189. case cff_op_vlineto:
  1190. {
  1191. FT_Int phase = ( op == cff_op_hlineto );
  1192. FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n"
  1193. : " vlineto\n" ));
  1194. if ( num_args < 0 )
  1195. goto Stack_Underflow;
  1196. /* there exist subsetted fonts (found in PDFs) */
  1197. /* which call `hlineto' without arguments */
  1198. if ( num_args == 0 )
  1199. break;
  1200. if ( cff_builder_start_point ( builder, x, y ) ||
  1201. check_points( builder, num_args ) )
  1202. goto Fail;
  1203. args = stack;
  1204. while ( args < decoder->top )
  1205. {
  1206. if ( phase )
  1207. x += args[0];
  1208. else
  1209. y += args[0];
  1210. if ( cff_builder_add_point1( builder, x, y ) )
  1211. goto Fail;
  1212. args++;
  1213. phase ^= 1;
  1214. }
  1215. args = stack;
  1216. }
  1217. break;
  1218. case cff_op_rrcurveto:
  1219. {
  1220. FT_Int nargs;
  1221. FT_TRACE4(( " rrcurveto\n" ));
  1222. if ( num_args < 6 )
  1223. goto Stack_Underflow;
  1224. nargs = num_args - num_args % 6;
  1225. if ( cff_builder_start_point ( builder, x, y ) ||
  1226. check_points( builder, nargs / 2 ) )
  1227. goto Fail;
  1228. args -= nargs;
  1229. while ( args < decoder->top )
  1230. {
  1231. x += args[0];
  1232. y += args[1];
  1233. cff_builder_add_point( builder, x, y, 0 );
  1234. x += args[2];
  1235. y += args[3];
  1236. cff_builder_add_point( builder, x, y, 0 );
  1237. x += args[4];
  1238. y += args[5];
  1239. cff_builder_add_point( builder, x, y, 1 );
  1240. args += 6;
  1241. }
  1242. args = stack;
  1243. }
  1244. break;
  1245. case cff_op_vvcurveto:
  1246. {
  1247. FT_Int nargs;
  1248. FT_TRACE4(( " vvcurveto\n" ));
  1249. if ( num_args < 4 )
  1250. goto Stack_Underflow;
  1251. /* if num_args isn't of the form 4n or 4n+1, */
  1252. /* we enforce it by clearing the second bit */
  1253. nargs = num_args & ~2;
  1254. if ( cff_builder_start_point( builder, x, y ) )
  1255. goto Fail;
  1256. args -= nargs;
  1257. if ( nargs & 1 )
  1258. {
  1259. x += args[0];
  1260. args++;
  1261. nargs--;
  1262. }
  1263. if ( check_points( builder, 3 * ( nargs / 4 ) ) )
  1264. goto Fail;
  1265. while ( args < decoder->top )
  1266. {
  1267. y += args[0];
  1268. cff_builder_add_point( builder, x, y, 0 );
  1269. x += args[1];
  1270. y += args[2];
  1271. cff_builder_add_point( builder, x, y, 0 );
  1272. y += args[3];
  1273. cff_builder_add_point( builder, x, y, 1 );
  1274. args += 4;
  1275. }
  1276. args = stack;
  1277. }
  1278. break;
  1279. case cff_op_hhcurveto:
  1280. {
  1281. FT_Int nargs;
  1282. FT_TRACE4(( " hhcurveto\n" ));
  1283. if ( num_args < 4 )
  1284. goto Stack_Underflow;
  1285. /* if num_args isn't of the form 4n or 4n+1, */
  1286. /* we enforce it by clearing the second bit */
  1287. nargs = num_args & ~2;
  1288. if ( cff_builder_start_point( builder, x, y ) )
  1289. goto Fail;
  1290. args -= nargs;
  1291. if ( nargs & 1 )
  1292. {
  1293. y += args[0];
  1294. args++;
  1295. nargs--;
  1296. }
  1297. if ( check_points( builder, 3 * ( nargs / 4 ) ) )
  1298. goto Fail;
  1299. while ( args < decoder->top )
  1300. {
  1301. x += args[0];
  1302. cff_builder_add_point( builder, x, y, 0 );
  1303. x += args[1];
  1304. y += args[2];
  1305. cff_builder_add_point( builder, x, y, 0 );
  1306. x += args[3];
  1307. cff_builder_add_point( builder, x, y, 1 );
  1308. args += 4;
  1309. }
  1310. args = stack;
  1311. }
  1312. break;
  1313. case cff_op_vhcurveto:
  1314. case cff_op_hvcurveto:
  1315. {
  1316. FT_Int phase;
  1317. FT_Int nargs;
  1318. FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n"
  1319. : " hvcurveto\n" ));
  1320. if ( cff_builder_start_point( builder, x, y ) )
  1321. goto Fail;
  1322. if ( num_args < 4 )
  1323. goto Stack_Underflow;
  1324. /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */
  1325. /* we enforce it by clearing the second bit */
  1326. nargs = num_args & ~2;
  1327. args -= nargs;
  1328. if ( check_points( builder, ( nargs / 4 ) * 3 ) )
  1329. goto Stack_Underflow;
  1330. phase = ( op == cff_op_hvcurveto );
  1331. while ( nargs >= 4 )
  1332. {
  1333. nargs -= 4;
  1334. if ( phase )
  1335. {
  1336. x += args[0];
  1337. cff_builder_add_point( builder, x, y, 0 );
  1338. x += args[1];
  1339. y += args[2];
  1340. cff_builder_add_point( builder, x, y, 0 );
  1341. y += args[3];
  1342. if ( nargs == 1 )
  1343. x += args[4];
  1344. cff_builder_add_point( builder, x, y, 1 );
  1345. }
  1346. else
  1347. {
  1348. y += args[0];
  1349. cff_builder_add_point( builder, x, y, 0 );
  1350. x += args[1];
  1351. y += args[2];
  1352. cff_builder_add_point( builder, x, y, 0 );
  1353. x += args[3];
  1354. if ( nargs == 1 )
  1355. y += args[4];
  1356. cff_builder_add_point( builder, x, y, 1 );
  1357. }
  1358. args += 4;
  1359. phase ^= 1;
  1360. }
  1361. args = stack;
  1362. }
  1363. break;
  1364. case cff_op_rlinecurve:
  1365. {
  1366. FT_Int num_lines;
  1367. FT_Int nargs;
  1368. FT_TRACE4(( " rlinecurve\n" ));
  1369. if ( num_args < 8 )
  1370. goto Stack_Underflow;
  1371. nargs = num_args & ~1;
  1372. num_lines = ( nargs - 6 ) / 2;