/src/freetype/src/pfr/pfrgload.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 844 lines · 571 code · 183 blank · 90 comment · 65 complexity · 4d2d5a854bbc8cd69a3413b0c1846a36 MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* pfrgload.c */
  4. /* */
  5. /* FreeType PFR glyph loader (body). */
  6. /* */
  7. /* Copyright 2002, 2003, 2005, 2007, 2010 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 "pfrgload.h"
  18. #include "pfrsbit.h"
  19. #include "pfrload.h" /* for macro definitions */
  20. #include FT_INTERNAL_DEBUG_H
  21. #include "pfrerror.h"
  22. #undef FT_COMPONENT
  23. #define FT_COMPONENT trace_pfr
  24. /*************************************************************************/
  25. /*************************************************************************/
  26. /***** *****/
  27. /***** PFR GLYPH BUILDER *****/
  28. /***** *****/
  29. /*************************************************************************/
  30. /*************************************************************************/
  31. FT_LOCAL_DEF( void )
  32. pfr_glyph_init( PFR_Glyph glyph,
  33. FT_GlyphLoader loader )
  34. {
  35. FT_ZERO( glyph );
  36. glyph->loader = loader;
  37. glyph->path_begun = 0;
  38. FT_GlyphLoader_Rewind( loader );
  39. }
  40. FT_LOCAL_DEF( void )
  41. pfr_glyph_done( PFR_Glyph glyph )
  42. {
  43. FT_Memory memory = glyph->loader->memory;
  44. FT_FREE( glyph->x_control );
  45. glyph->y_control = NULL;
  46. glyph->max_xy_control = 0;
  47. #if 0
  48. glyph->num_x_control = 0;
  49. glyph->num_y_control = 0;
  50. #endif
  51. FT_FREE( glyph->subs );
  52. glyph->max_subs = 0;
  53. glyph->num_subs = 0;
  54. glyph->loader = NULL;
  55. glyph->path_begun = 0;
  56. }
  57. /* close current contour, if any */
  58. static void
  59. pfr_glyph_close_contour( PFR_Glyph glyph )
  60. {
  61. FT_GlyphLoader loader = glyph->loader;
  62. FT_Outline* outline = &loader->current.outline;
  63. FT_Int last, first;
  64. if ( !glyph->path_begun )
  65. return;
  66. /* compute first and last point indices in current glyph outline */
  67. last = outline->n_points - 1;
  68. first = 0;
  69. if ( outline->n_contours > 0 )
  70. first = outline->contours[outline->n_contours - 1];
  71. /* if the last point falls on the same location than the first one */
  72. /* we need to delete it */
  73. if ( last > first )
  74. {
  75. FT_Vector* p1 = outline->points + first;
  76. FT_Vector* p2 = outline->points + last;
  77. if ( p1->x == p2->x && p1->y == p2->y )
  78. {
  79. outline->n_points--;
  80. last--;
  81. }
  82. }
  83. /* don't add empty contours */
  84. if ( last >= first )
  85. outline->contours[outline->n_contours++] = (short)last;
  86. glyph->path_begun = 0;
  87. }
  88. /* reset glyph to start the loading of a new glyph */
  89. static void
  90. pfr_glyph_start( PFR_Glyph glyph )
  91. {
  92. glyph->path_begun = 0;
  93. }
  94. static FT_Error
  95. pfr_glyph_line_to( PFR_Glyph glyph,
  96. FT_Vector* to )
  97. {
  98. FT_GlyphLoader loader = glyph->loader;
  99. FT_Outline* outline = &loader->current.outline;
  100. FT_Error error;
  101. /* check that we have begun a new path */
  102. if ( !glyph->path_begun )
  103. {
  104. error = PFR_Err_Invalid_Table;
  105. FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));
  106. goto Exit;
  107. }
  108. error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 0 );
  109. if ( !error )
  110. {
  111. FT_UInt n = outline->n_points;
  112. outline->points[n] = *to;
  113. outline->tags [n] = FT_CURVE_TAG_ON;
  114. outline->n_points++;
  115. }
  116. Exit:
  117. return error;
  118. }
  119. static FT_Error
  120. pfr_glyph_curve_to( PFR_Glyph glyph,
  121. FT_Vector* control1,
  122. FT_Vector* control2,
  123. FT_Vector* to )
  124. {
  125. FT_GlyphLoader loader = glyph->loader;
  126. FT_Outline* outline = &loader->current.outline;
  127. FT_Error error;
  128. /* check that we have begun a new path */
  129. if ( !glyph->path_begun )
  130. {
  131. error = PFR_Err_Invalid_Table;
  132. FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));
  133. goto Exit;
  134. }
  135. error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 );
  136. if ( !error )
  137. {
  138. FT_Vector* vec = outline->points + outline->n_points;
  139. FT_Byte* tag = (FT_Byte*)outline->tags + outline->n_points;
  140. vec[0] = *control1;
  141. vec[1] = *control2;
  142. vec[2] = *to;
  143. tag[0] = FT_CURVE_TAG_CUBIC;
  144. tag[1] = FT_CURVE_TAG_CUBIC;
  145. tag[2] = FT_CURVE_TAG_ON;
  146. outline->n_points = (FT_Short)( outline->n_points + 3 );
  147. }
  148. Exit:
  149. return error;
  150. }
  151. static FT_Error
  152. pfr_glyph_move_to( PFR_Glyph glyph,
  153. FT_Vector* to )
  154. {
  155. FT_GlyphLoader loader = glyph->loader;
  156. FT_Error error;
  157. /* close current contour if any */
  158. pfr_glyph_close_contour( glyph );
  159. /* indicate that a new contour has started */
  160. glyph->path_begun = 1;
  161. /* check that there is space for a new contour and a new point */
  162. error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 1 );
  163. if ( !error )
  164. /* add new start point */
  165. error = pfr_glyph_line_to( glyph, to );
  166. return error;
  167. }
  168. static void
  169. pfr_glyph_end( PFR_Glyph glyph )
  170. {
  171. /* close current contour if any */
  172. pfr_glyph_close_contour( glyph );
  173. /* merge the current glyph into the stack */
  174. FT_GlyphLoader_Add( glyph->loader );
  175. }
  176. /*************************************************************************/
  177. /*************************************************************************/
  178. /***** *****/
  179. /***** PFR GLYPH LOADER *****/
  180. /***** *****/
  181. /*************************************************************************/
  182. /*************************************************************************/
  183. /* load a simple glyph */
  184. static FT_Error
  185. pfr_glyph_load_simple( PFR_Glyph glyph,
  186. FT_Byte* p,
  187. FT_Byte* limit )
  188. {
  189. FT_Error error = PFR_Err_Ok;
  190. FT_Memory memory = glyph->loader->memory;
  191. FT_UInt flags, x_count, y_count, i, count, mask;
  192. FT_Int x;
  193. PFR_CHECK( 1 );
  194. flags = PFR_NEXT_BYTE( p );
  195. /* test for composite glyphs */
  196. if ( flags & PFR_GLYPH_IS_COMPOUND )
  197. goto Failure;
  198. x_count = 0;
  199. y_count = 0;
  200. if ( flags & PFR_GLYPH_1BYTE_XYCOUNT )
  201. {
  202. PFR_CHECK( 1 );
  203. count = PFR_NEXT_BYTE( p );
  204. x_count = count & 15;
  205. y_count = count >> 4;
  206. }
  207. else
  208. {
  209. if ( flags & PFR_GLYPH_XCOUNT )
  210. {
  211. PFR_CHECK( 1 );
  212. x_count = PFR_NEXT_BYTE( p );
  213. }
  214. if ( flags & PFR_GLYPH_YCOUNT )
  215. {
  216. PFR_CHECK( 1 );
  217. y_count = PFR_NEXT_BYTE( p );
  218. }
  219. }
  220. count = x_count + y_count;
  221. /* re-allocate array when necessary */
  222. if ( count > glyph->max_xy_control )
  223. {
  224. FT_UInt new_max = FT_PAD_CEIL( count, 8 );
  225. if ( FT_RENEW_ARRAY( glyph->x_control,
  226. glyph->max_xy_control,
  227. new_max ) )
  228. goto Exit;
  229. glyph->max_xy_control = new_max;
  230. }
  231. glyph->y_control = glyph->x_control + x_count;
  232. mask = 0;
  233. x = 0;
  234. for ( i = 0; i < count; i++ )
  235. {
  236. if ( ( i & 7 ) == 0 )
  237. {
  238. PFR_CHECK( 1 );
  239. mask = PFR_NEXT_BYTE( p );
  240. }
  241. if ( mask & 1 )
  242. {
  243. PFR_CHECK( 2 );
  244. x = PFR_NEXT_SHORT( p );
  245. }
  246. else
  247. {
  248. PFR_CHECK( 1 );
  249. x += PFR_NEXT_BYTE( p );
  250. }
  251. glyph->x_control[i] = x;
  252. mask >>= 1;
  253. }
  254. /* XXX: for now we ignore the secondary stroke and edge definitions */
  255. /* since we don't want to support native PFR hinting */
  256. /* */
  257. if ( flags & PFR_GLYPH_EXTRA_ITEMS )
  258. {
  259. error = pfr_extra_items_skip( &p, limit );
  260. if ( error )
  261. goto Exit;
  262. }
  263. pfr_glyph_start( glyph );
  264. /* now load a simple glyph */
  265. {
  266. FT_Vector pos[4];
  267. FT_Vector* cur;
  268. pos[0].x = pos[0].y = 0;
  269. pos[3] = pos[0];
  270. for (;;)
  271. {
  272. FT_UInt format, format_low, args_format = 0, args_count, n;
  273. /***************************************************************/
  274. /* read instruction */
  275. /* */
  276. PFR_CHECK( 1 );
  277. format = PFR_NEXT_BYTE( p );
  278. format_low = format & 15;
  279. switch ( format >> 4 )
  280. {
  281. case 0: /* end glyph */
  282. FT_TRACE6(( "- end glyph" ));
  283. args_count = 0;
  284. break;
  285. case 1: /* general line operation */
  286. FT_TRACE6(( "- general line" ));
  287. goto Line1;
  288. case 4: /* move to inside contour */
  289. FT_TRACE6(( "- move to inside" ));
  290. goto Line1;
  291. case 5: /* move to outside contour */
  292. FT_TRACE6(( "- move to outside" ));
  293. Line1:
  294. args_format = format_low;
  295. args_count = 1;
  296. break;
  297. case 2: /* horizontal line to */
  298. FT_TRACE6(( "- horizontal line to cx.%d", format_low ));
  299. if ( format_low >= x_count )
  300. goto Failure;
  301. pos[0].x = glyph->x_control[format_low];
  302. pos[0].y = pos[3].y;
  303. pos[3] = pos[0];
  304. args_count = 0;
  305. break;
  306. case 3: /* vertical line to */
  307. FT_TRACE6(( "- vertical line to cy.%d", format_low ));
  308. if ( format_low >= y_count )
  309. goto Failure;
  310. pos[0].x = pos[3].x;
  311. pos[0].y = glyph->y_control[format_low];
  312. pos[3] = pos[0];
  313. args_count = 0;
  314. break;
  315. case 6: /* horizontal to vertical curve */
  316. FT_TRACE6(( "- hv curve " ));
  317. args_format = 0xB8E;
  318. args_count = 3;
  319. break;
  320. case 7: /* vertical to horizontal curve */
  321. FT_TRACE6(( "- vh curve" ));
  322. args_format = 0xE2B;
  323. args_count = 3;
  324. break;
  325. default: /* general curve to */
  326. FT_TRACE6(( "- general curve" ));
  327. args_count = 4;
  328. args_format = format_low;
  329. }
  330. /***********************************************************/
  331. /* now read arguments */
  332. /* */
  333. cur = pos;
  334. for ( n = 0; n < args_count; n++ )
  335. {
  336. FT_UInt idx;
  337. FT_Int delta;
  338. /* read the X argument */
  339. switch ( args_format & 3 )
  340. {
  341. case 0: /* 8-bit index */
  342. PFR_CHECK( 1 );
  343. idx = PFR_NEXT_BYTE( p );
  344. if ( idx >= x_count )
  345. goto Failure;
  346. cur->x = glyph->x_control[idx];
  347. FT_TRACE7(( " cx#%d", idx ));
  348. break;
  349. case 1: /* 16-bit value */
  350. PFR_CHECK( 2 );
  351. cur->x = PFR_NEXT_SHORT( p );
  352. FT_TRACE7(( " x.%d", cur->x ));
  353. break;
  354. case 2: /* 8-bit delta */
  355. PFR_CHECK( 1 );
  356. delta = PFR_NEXT_INT8( p );
  357. cur->x = pos[3].x + delta;
  358. FT_TRACE7(( " dx.%d", delta ));
  359. break;
  360. default:
  361. FT_TRACE7(( " |" ));
  362. cur->x = pos[3].x;
  363. }
  364. /* read the Y argument */
  365. switch ( ( args_format >> 2 ) & 3 )
  366. {
  367. case 0: /* 8-bit index */
  368. PFR_CHECK( 1 );
  369. idx = PFR_NEXT_BYTE( p );
  370. if ( idx >= y_count )
  371. goto Failure;
  372. cur->y = glyph->y_control[idx];
  373. FT_TRACE7(( " cy#%d", idx ));
  374. break;
  375. case 1: /* 16-bit absolute value */
  376. PFR_CHECK( 2 );
  377. cur->y = PFR_NEXT_SHORT( p );
  378. FT_TRACE7(( " y.%d", cur->y ));
  379. break;
  380. case 2: /* 8-bit delta */
  381. PFR_CHECK( 1 );
  382. delta = PFR_NEXT_INT8( p );
  383. cur->y = pos[3].y + delta;
  384. FT_TRACE7(( " dy.%d", delta ));
  385. break;
  386. default:
  387. FT_TRACE7(( " -" ));
  388. cur->y = pos[3].y;
  389. }
  390. /* read the additional format flag for the general curve */
  391. if ( n == 0 && args_count == 4 )
  392. {
  393. PFR_CHECK( 1 );
  394. args_format = PFR_NEXT_BYTE( p );
  395. args_count--;
  396. }
  397. else
  398. args_format >>= 4;
  399. /* save the previous point */
  400. pos[3] = cur[0];
  401. cur++;
  402. }
  403. FT_TRACE7(( "\n" ));
  404. /***********************************************************/
  405. /* finally, execute instruction */
  406. /* */
  407. switch ( format >> 4 )
  408. {
  409. case 0: /* end glyph => EXIT */
  410. pfr_glyph_end( glyph );
  411. goto Exit;
  412. case 1: /* line operations */
  413. case 2:
  414. case 3:
  415. error = pfr_glyph_line_to( glyph, pos );
  416. goto Test_Error;
  417. case 4: /* move to inside contour */
  418. case 5: /* move to outside contour */
  419. error = pfr_glyph_move_to( glyph, pos );
  420. goto Test_Error;
  421. default: /* curve operations */
  422. error = pfr_glyph_curve_to( glyph, pos, pos + 1, pos + 2 );
  423. Test_Error: /* test error condition */
  424. if ( error )
  425. goto Exit;
  426. }
  427. } /* for (;;) */
  428. }
  429. Exit:
  430. return error;
  431. Failure:
  432. Too_Short:
  433. error = PFR_Err_Invalid_Table;
  434. FT_ERROR(( "pfr_glyph_load_simple: invalid glyph data\n" ));
  435. goto Exit;
  436. }
  437. /* load a composite/compound glyph */
  438. static FT_Error
  439. pfr_glyph_load_compound( PFR_Glyph glyph,
  440. FT_Byte* p,
  441. FT_Byte* limit )
  442. {
  443. FT_Error error = PFR_Err_Ok;
  444. FT_GlyphLoader loader = glyph->loader;
  445. FT_Memory memory = loader->memory;
  446. PFR_SubGlyph subglyph;
  447. FT_UInt flags, i, count, org_count;
  448. FT_Int x_pos, y_pos;
  449. PFR_CHECK( 1 );
  450. flags = PFR_NEXT_BYTE( p );
  451. /* test for composite glyphs */
  452. if ( !( flags & PFR_GLYPH_IS_COMPOUND ) )
  453. goto Failure;
  454. count = flags & 0x3F;
  455. /* ignore extra items when present */
  456. /* */
  457. if ( flags & PFR_GLYPH_EXTRA_ITEMS )
  458. {
  459. error = pfr_extra_items_skip( &p, limit );
  460. if (error) goto Exit;
  461. }
  462. /* we can't rely on the FT_GlyphLoader to load sub-glyphs, because */
  463. /* the PFR format is dumb, using direct file offsets to point to the */
  464. /* sub-glyphs (instead of glyph indices). Sigh. */
  465. /* */
  466. /* For now, we load the list of sub-glyphs into a different array */
  467. /* but this will prevent us from using the auto-hinter at its best */
  468. /* quality. */
  469. /* */
  470. org_count = glyph->num_subs;
  471. if ( org_count + count > glyph->max_subs )
  472. {
  473. FT_UInt new_max = ( org_count + count + 3 ) & (FT_UInt)-4;
  474. /* we arbitrarily limit the number of subglyphs */
  475. /* to avoid endless recursion */
  476. if ( new_max > 64 )
  477. {
  478. error = PFR_Err_Invalid_Table;
  479. FT_ERROR(( "pfr_glyph_load_compound:"
  480. " too many compound glyphs components\n" ));
  481. goto Exit;
  482. }
  483. if ( FT_RENEW_ARRAY( glyph->subs, glyph->max_subs, new_max ) )
  484. goto Exit;
  485. glyph->max_subs = new_max;
  486. }
  487. subglyph = glyph->subs + org_count;
  488. for ( i = 0; i < count; i++, subglyph++ )
  489. {
  490. FT_UInt format;
  491. x_pos = 0;
  492. y_pos = 0;
  493. PFR_CHECK( 1 );
  494. format = PFR_NEXT_BYTE( p );
  495. /* read scale when available */
  496. subglyph->x_scale = 0x10000L;
  497. if ( format & PFR_SUBGLYPH_XSCALE )
  498. {
  499. PFR_CHECK( 2 );
  500. subglyph->x_scale = PFR_NEXT_SHORT( p ) << 4;
  501. }
  502. subglyph->y_scale = 0x10000L;
  503. if ( format & PFR_SUBGLYPH_YSCALE )
  504. {
  505. PFR_CHECK( 2 );
  506. subglyph->y_scale = PFR_NEXT_SHORT( p ) << 4;
  507. }
  508. /* read offset */
  509. switch ( format & 3 )
  510. {
  511. case 1:
  512. PFR_CHECK( 2 );
  513. x_pos = PFR_NEXT_SHORT( p );
  514. break;
  515. case 2:
  516. PFR_CHECK( 1 );
  517. x_pos += PFR_NEXT_INT8( p );
  518. break;
  519. default:
  520. ;
  521. }
  522. switch ( ( format >> 2 ) & 3 )
  523. {
  524. case 1:
  525. PFR_CHECK( 2 );
  526. y_pos = PFR_NEXT_SHORT( p );
  527. break;
  528. case 2:
  529. PFR_CHECK( 1 );
  530. y_pos += PFR_NEXT_INT8( p );
  531. break;
  532. default:
  533. ;
  534. }
  535. subglyph->x_delta = x_pos;
  536. subglyph->y_delta = y_pos;
  537. /* read glyph position and size now */
  538. if ( format & PFR_SUBGLYPH_2BYTE_SIZE )
  539. {
  540. PFR_CHECK( 2 );
  541. subglyph->gps_size = PFR_NEXT_USHORT( p );
  542. }
  543. else
  544. {
  545. PFR_CHECK( 1 );
  546. subglyph->gps_size = PFR_NEXT_BYTE( p );
  547. }
  548. if ( format & PFR_SUBGLYPH_3BYTE_OFFSET )
  549. {
  550. PFR_CHECK( 3 );
  551. subglyph->gps_offset = PFR_NEXT_LONG( p );
  552. }
  553. else
  554. {
  555. PFR_CHECK( 2 );
  556. subglyph->gps_offset = PFR_NEXT_USHORT( p );
  557. }
  558. glyph->num_subs++;
  559. }
  560. Exit:
  561. return error;
  562. Failure:
  563. Too_Short:
  564. error = PFR_Err_Invalid_Table;
  565. FT_ERROR(( "pfr_glyph_load_compound: invalid glyph data\n" ));
  566. goto Exit;
  567. }
  568. static FT_Error
  569. pfr_glyph_load_rec( PFR_Glyph glyph,
  570. FT_Stream stream,
  571. FT_ULong gps_offset,
  572. FT_ULong offset,
  573. FT_ULong size )
  574. {
  575. FT_Error error;
  576. FT_Byte* p;
  577. FT_Byte* limit;
  578. if ( FT_STREAM_SEEK( gps_offset + offset ) ||
  579. FT_FRAME_ENTER( size ) )
  580. goto Exit;
  581. p = (FT_Byte*)stream->cursor;
  582. limit = p + size;
  583. if ( size > 0 && *p & PFR_GLYPH_IS_COMPOUND )
  584. {
  585. FT_Int n, old_count, count;
  586. FT_GlyphLoader loader = glyph->loader;
  587. FT_Outline* base = &loader->base.outline;
  588. old_count = glyph->num_subs;
  589. /* this is a compound glyph - load it */
  590. error = pfr_glyph_load_compound( glyph, p, limit );
  591. FT_FRAME_EXIT();
  592. if ( error )
  593. goto Exit;
  594. count = glyph->num_subs - old_count;
  595. FT_TRACE4(( "compound glyph with %d elements (offset %lu):\n",
  596. count, offset ));
  597. /* now, load each individual glyph */
  598. for ( n = 0; n < count; n++ )
  599. {
  600. FT_Int i, old_points, num_points;
  601. PFR_SubGlyph subglyph;
  602. FT_TRACE4(( "subglyph %d:\n", n ));
  603. subglyph = glyph->subs + old_count + n;
  604. old_points = base->n_points;
  605. error = pfr_glyph_load_rec( glyph, stream, gps_offset,
  606. subglyph->gps_offset,
  607. subglyph->gps_size );
  608. if ( error )
  609. break;
  610. /* note that `glyph->subs' might have been re-allocated */
  611. subglyph = glyph->subs + old_count + n;
  612. num_points = base->n_points - old_points;
  613. /* translate and eventually scale the new glyph points */
  614. if ( subglyph->x_scale != 0x10000L || subglyph->y_scale != 0x10000L )
  615. {
  616. FT_Vector* vec = base->points + old_points;
  617. for ( i = 0; i < num_points; i++, vec++ )
  618. {
  619. vec->x = FT_MulFix( vec->x, subglyph->x_scale ) +
  620. subglyph->x_delta;
  621. vec->y = FT_MulFix( vec->y, subglyph->y_scale ) +
  622. subglyph->y_delta;
  623. }
  624. }
  625. else
  626. {
  627. FT_Vector* vec = loader->base.outline.points + old_points;
  628. for ( i = 0; i < num_points; i++, vec++ )
  629. {
  630. vec->x += subglyph->x_delta;
  631. vec->y += subglyph->y_delta;
  632. }
  633. }
  634. /* proceed to next sub-glyph */
  635. }
  636. FT_TRACE4(( "end compound glyph with %d elements\n", count ));
  637. }
  638. else
  639. {
  640. FT_TRACE4(( "simple glyph (offset %lu)\n", offset ));
  641. /* load a simple glyph */
  642. error = pfr_glyph_load_simple( glyph, p, limit );
  643. FT_FRAME_EXIT();
  644. }
  645. Exit:
  646. return error;
  647. }
  648. FT_LOCAL_DEF( FT_Error )
  649. pfr_glyph_load( PFR_Glyph glyph,
  650. FT_Stream stream,
  651. FT_ULong gps_offset,
  652. FT_ULong offset,
  653. FT_ULong size )
  654. {
  655. /* initialize glyph loader */
  656. FT_GlyphLoader_Rewind( glyph->loader );
  657. glyph->num_subs = 0;
  658. /* load the glyph, recursively when needed */
  659. return pfr_glyph_load_rec( glyph, stream, gps_offset, offset, size );
  660. }
  661. /* END */