PageRenderTime 57ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib/freetype-1.3.1/lib/extend/ftxgsub.c

https://bitbucket.org/davaeron/uplink
C | 4307 lines | 2863 code | 1286 blank | 158 comment | 640 complexity | 8cdfdcbf31649071a2b97cfae54d35fa MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1

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

  1. /*******************************************************************
  2. *
  3. * ftxgsub.c
  4. *
  5. * TrueType Open GSUB table support.
  6. *
  7. * Copyright 1996-1999 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. /* XXX There is *a lot* of duplicated code (cf. formats 5 and 6), but
  18. I don't care currently. I believe that it would be possible to
  19. save about 50% of TTO code by carefully designing the structures,
  20. sharing as much as possible with extensive use of macros. This
  21. is something for a volunteer :-) */
  22. #include "tttypes.h"
  23. #include "tttags.h"
  24. #include "ttload.h"
  25. #include "ttextend.h"
  26. #include "ttmemory.h"
  27. #include "ttfile.h"
  28. #include "ftxopen.h"
  29. #include "ftxopenf.h"
  30. #define GSUB_ID Build_Extension_ID( 'G', 'S', 'U', 'B' )
  31. #define ADD_String( in, num_in, out, num_out, data ) \
  32. ( ( error = TT_GSUB_Add_String( (in), (num_in), \
  33. (out), (num_out), \
  34. (data) ) ) != TT_Err_Ok )
  35. #define CHECK_Property( gdef, index, flags, property ) \
  36. ( ( error = Check_Property( (gdef), (index), (flags), \
  37. (property) ) ) != TT_Err_Ok )
  38. static TT_Error Do_Glyph_Lookup( TTO_GSUBHeader* gsub,
  39. UShort lookup_index,
  40. TTO_GSUB_String* in,
  41. TTO_GSUB_String* out,
  42. UShort context_length,
  43. int nesting_level );
  44. /**********************
  45. * Auxiliary functions
  46. **********************/
  47. /* The following function copies `num_out' elements from `data' to
  48. `out', advancing the array pointer in the `in' structure by `num_in'
  49. elements and in `out' by `num_out' elements. If the string (resp.
  50. the properties) array in `out' is empty or too small, it allocates
  51. resp. reallocates the string (and properties) array. Finally, it
  52. sets the `length' field of `out' equal to `pos' of the `out'
  53. structure.
  54. The properties (if defined) for all replaced glyphs are taken from
  55. the glyph at position `in->pos'. */
  56. EXPORT_FUNC
  57. TT_Error TT_GSUB_Add_String( TTO_GSUB_String* in,
  58. UShort num_in,
  59. TTO_GSUB_String* out,
  60. UShort num_out,
  61. UShort* data )
  62. {
  63. TT_Error error;
  64. UShort i;
  65. UShort p_in;
  66. UShort* p_out;
  67. /* sanity check */
  68. if ( !in || !out ||
  69. in->length == 0 || in->pos >= in->length ||
  70. in->length < in->pos + num_in )
  71. return TT_Err_Invalid_Argument;
  72. if ( out->pos + num_out >= out->allocated )
  73. {
  74. ULong size = out->pos + num_out + 256L;
  75. /* The following works because all fields in `out' must be
  76. initialized to zero (including the `string' field) for the
  77. first use. */
  78. if ( REALLOC( out->string, size * sizeof ( UShort ) ) )
  79. return error;
  80. if ( in->properties )
  81. if ( REALLOC( out->properties, size * sizeof ( UShort ) ) )
  82. return error;
  83. out->allocated = size;
  84. }
  85. if ( num_out )
  86. {
  87. MEM_Copy( &out->string[out->pos], data, num_out * sizeof ( UShort ) );
  88. if ( in->properties )
  89. {
  90. p_in = in->properties[in->pos];
  91. p_out = out->properties;
  92. for ( i = out->pos; i < out->pos + num_out; i++ )
  93. p_out[i] = p_in;
  94. }
  95. }
  96. in->pos += num_in;
  97. out->pos += num_out;
  98. out->length = out->pos;
  99. return TT_Err_Ok;
  100. }
  101. static TT_Error Check_Property( TTO_GDEFHeader* gdef,
  102. UShort index,
  103. UShort flags,
  104. UShort* property )
  105. {
  106. TT_Error error;
  107. if ( gdef )
  108. {
  109. error = TT_GDEF_Get_Glyph_Property( gdef, index, property );
  110. if ( error )
  111. return error;
  112. /* This is OpenType 1.2 */
  113. if ( flags & IGNORE_SPECIAL_MARKS )
  114. if ( (flags & 0xFF00) != *property )
  115. return TTO_Err_Not_Covered;
  116. if ( flags & *property )
  117. return TTO_Err_Not_Covered;
  118. }
  119. return TT_Err_Ok;
  120. }
  121. /**********************
  122. * Extension Functions
  123. **********************/
  124. static TT_Error GSUB_Create( void* ext,
  125. PFace face )
  126. {
  127. DEFINE_LOAD_LOCALS( face->stream );
  128. TTO_GSUBHeader* gsub = (TTO_GSUBHeader*)ext;
  129. Long table;
  130. /* by convention */
  131. if ( !gsub )
  132. return TT_Err_Ok;
  133. /* a null offset indicates that there is no GSUB table */
  134. gsub->offset = 0;
  135. /* we store the start offset and the size of the subtable */
  136. table = TT_LookUp_Table( face, TTAG_GSUB );
  137. if ( table < 0 )
  138. return TT_Err_Ok; /* The table is optional */
  139. if ( FILE_Seek( face->dirTables[table].Offset ) ||
  140. ACCESS_Frame( 4L ) )
  141. return error;
  142. gsub->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */
  143. gsub->Version = GET_ULong();
  144. FORGET_Frame();
  145. gsub->loaded = FALSE;
  146. return TT_Err_Ok;
  147. }
  148. static TT_Error GSUB_Destroy( void* ext,
  149. PFace face )
  150. {
  151. TTO_GSUBHeader* gsub = (TTO_GSUBHeader*)ext;
  152. /* by convention */
  153. if ( !gsub )
  154. return TT_Err_Ok;
  155. if ( gsub->loaded )
  156. {
  157. Free_LookupList( &gsub->LookupList, GSUB );
  158. Free_FeatureList( &gsub->FeatureList );
  159. Free_ScriptList( &gsub->ScriptList );
  160. }
  161. return TT_Err_Ok;
  162. }
  163. EXPORT_FUNC
  164. TT_Error TT_Init_GSUB_Extension( TT_Engine engine )
  165. {
  166. PEngine_Instance _engine = HANDLE_Engine( engine );
  167. if ( !_engine )
  168. return TT_Err_Invalid_Engine;
  169. return TT_Register_Extension( _engine,
  170. GSUB_ID,
  171. sizeof ( TTO_GSUBHeader ),
  172. GSUB_Create,
  173. GSUB_Destroy );
  174. }
  175. EXPORT_FUNC
  176. TT_Error TT_Load_GSUB_Table( TT_Face face,
  177. TTO_GSUBHeader* retptr,
  178. TTO_GDEFHeader* gdef )
  179. {
  180. ULong cur_offset, new_offset, base_offset;
  181. TT_UShort i, num_lookups;
  182. TT_Error error;
  183. TT_Stream stream;
  184. TTO_GSUBHeader* gsub;
  185. TTO_Lookup* lo;
  186. PFace faze = HANDLE_Face( face );
  187. if ( !retptr )
  188. return TT_Err_Invalid_Argument;
  189. if ( !faze )
  190. return TT_Err_Invalid_Face_Handle;
  191. error = TT_Extension_Get( faze, GSUB_ID, (void**)&gsub );
  192. if ( error )
  193. return error;
  194. if ( gsub->offset == 0 )
  195. return TT_Err_Table_Missing; /* no GSUB table; nothing to do */
  196. /* now access stream */
  197. if ( USE_Stream( faze->stream, stream ) )
  198. return error;
  199. base_offset = gsub->offset;
  200. /* skip version */
  201. if ( FILE_Seek( base_offset + 4L ) ||
  202. ACCESS_Frame( 2L ) )
  203. return error;
  204. new_offset = GET_UShort() + base_offset;
  205. FORGET_Frame();
  206. cur_offset = FILE_Pos();
  207. if ( FILE_Seek( new_offset ) ||
  208. ( error = Load_ScriptList( &gsub->ScriptList,
  209. faze ) ) != TT_Err_Ok )
  210. return error;
  211. (void)FILE_Seek( cur_offset );
  212. if ( ACCESS_Frame( 2L ) )
  213. goto Fail3;
  214. new_offset = GET_UShort() + base_offset;
  215. FORGET_Frame();
  216. cur_offset = FILE_Pos();
  217. if ( FILE_Seek( new_offset ) ||
  218. ( error = Load_FeatureList( &gsub->FeatureList,
  219. faze ) ) != TT_Err_Ok )
  220. goto Fail3;
  221. (void)FILE_Seek( cur_offset );
  222. if ( ACCESS_Frame( 2L ) )
  223. goto Fail2;
  224. new_offset = GET_UShort() + base_offset;
  225. FORGET_Frame();
  226. cur_offset = FILE_Pos();
  227. if ( FILE_Seek( new_offset ) ||
  228. ( error = Load_LookupList( &gsub->LookupList,
  229. faze, GSUB ) ) != TT_Err_Ok )
  230. goto Fail2;
  231. gsub->gdef = gdef; /* can be NULL */
  232. /* We now check the LookupFlags for values larger than 0xFF to find
  233. out whether we need to load the `MarkAttachClassDef' field of the
  234. GDEF table -- this hack is necessary for OpenType 1.2 tables since
  235. the version field of the GDEF table hasn't been incremented.
  236. For constructed GDEF tables, we only load it if
  237. `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
  238. a constructed mark attach table is not supported currently). */
  239. if ( gdef &&
  240. gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded )
  241. {
  242. lo = gsub->LookupList.Lookup;
  243. num_lookups = gsub->LookupList.LookupCount;
  244. for ( i = 0; i < num_lookups; i++ )
  245. {
  246. if ( lo[i].LookupFlag & IGNORE_SPECIAL_MARKS )
  247. {
  248. if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) ||
  249. ACCESS_Frame( 2L ) )
  250. goto Fail1;
  251. new_offset = GET_UShort();
  252. FORGET_Frame();
  253. if ( !new_offset )
  254. return TTO_Err_Invalid_GDEF_SubTable;
  255. new_offset += base_offset;
  256. if ( FILE_Seek( new_offset ) ||
  257. ( error = Load_ClassDefinition( &gdef->MarkAttachClassDef,
  258. 256, faze ) ) != TT_Err_Ok )
  259. goto Fail1;
  260. break;
  261. }
  262. }
  263. }
  264. gsub->loaded = TRUE;
  265. *retptr = *gsub;
  266. DONE_Stream( stream );
  267. return TT_Err_Ok;
  268. Fail1:
  269. Free_LookupList( &gsub->LookupList, GSUB );
  270. Fail2:
  271. Free_FeatureList( &gsub->FeatureList );
  272. Fail3:
  273. Free_ScriptList( &gsub->ScriptList );
  274. /* release stream */
  275. DONE_Stream( stream );
  276. return error;
  277. }
  278. /*****************************
  279. * SubTable related functions
  280. *****************************/
  281. /* LookupType 1 */
  282. /* SingleSubstFormat1 */
  283. /* SingleSubstFormat2 */
  284. TT_Error Load_SingleSubst( TTO_SingleSubst* ss,
  285. PFace input )
  286. {
  287. DEFINE_LOAD_LOCALS( input->stream );
  288. UShort n, count;
  289. ULong cur_offset, new_offset, base_offset;
  290. UShort* s;
  291. base_offset = FILE_Pos();
  292. if ( ACCESS_Frame( 4L ) )
  293. return error;
  294. ss->SubstFormat = GET_UShort();
  295. new_offset = GET_UShort() + base_offset;
  296. FORGET_Frame();
  297. cur_offset = FILE_Pos();
  298. if ( FILE_Seek( new_offset ) ||
  299. ( error = Load_Coverage( &ss->Coverage, input ) ) != TT_Err_Ok )
  300. return error;
  301. (void)FILE_Seek( cur_offset );
  302. switch ( ss->SubstFormat )
  303. {
  304. case 1:
  305. if ( ACCESS_Frame( 2L ) )
  306. goto Fail2;
  307. ss->ssf.ssf1.DeltaGlyphID = GET_UShort();
  308. FORGET_Frame();
  309. break;
  310. case 2:
  311. if ( ACCESS_Frame( 2L ) )
  312. goto Fail2;
  313. count = ss->ssf.ssf2.GlyphCount = GET_UShort();
  314. FORGET_Frame();
  315. ss->ssf.ssf2.Substitute = NULL;
  316. if ( ALLOC_ARRAY( ss->ssf.ssf2.Substitute, count, UShort ) )
  317. goto Fail2;
  318. s = ss->ssf.ssf2.Substitute;
  319. if ( ACCESS_Frame( count * 2L ) )
  320. goto Fail1;
  321. for ( n = 0; n < count; n++ )
  322. s[n] = GET_UShort();
  323. FORGET_Frame();
  324. break;
  325. default:
  326. return TTO_Err_Invalid_GSUB_SubTable_Format;
  327. }
  328. return TT_Err_Ok;
  329. Fail1:
  330. FREE( s );
  331. Fail2:
  332. Free_Coverage( &ss->Coverage );
  333. return error;
  334. }
  335. void Free_SingleSubst( TTO_SingleSubst* ss )
  336. {
  337. switch ( ss->SubstFormat )
  338. {
  339. case 1:
  340. break;
  341. case 2:
  342. FREE( ss->ssf.ssf2.Substitute );
  343. break;
  344. }
  345. Free_Coverage( &ss->Coverage );
  346. }
  347. static TT_Error Lookup_SingleSubst( TTO_SingleSubst* ss,
  348. TTO_GSUB_String* in,
  349. TTO_GSUB_String* out,
  350. UShort flags,
  351. UShort context_length,
  352. TTO_GDEFHeader* gdef )
  353. {
  354. UShort index, value[1], property;
  355. TT_Error error;
  356. if ( context_length != 0xFFFF && context_length < 1 )
  357. return TTO_Err_Not_Covered;
  358. if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
  359. return error;
  360. error = Coverage_Index( &ss->Coverage, in->string[in->pos], &index );
  361. if ( error )
  362. return error;
  363. switch ( ss->SubstFormat )
  364. {
  365. case 1:
  366. value[0] = ( in->string[in->pos] + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
  367. if ( ADD_String( in, 1, out, 1, value ) )
  368. return error;
  369. break;
  370. case 2:
  371. if ( index >= ss->ssf.ssf2.GlyphCount )
  372. return TTO_Err_Invalid_GSUB_SubTable;
  373. value[0] = ss->ssf.ssf2.Substitute[index];
  374. if ( ADD_String( in, 1, out, 1, value ) )
  375. return error;
  376. break;
  377. default:
  378. return TTO_Err_Invalid_GSUB_SubTable;
  379. }
  380. if ( gdef && gdef->NewGlyphClasses )
  381. {
  382. /* we inherit the old glyph class to the substituted glyph */
  383. error = Add_Glyph_Property( gdef, value[0], property );
  384. if ( error && error != TTO_Err_Not_Covered )
  385. return error;
  386. }
  387. return TT_Err_Ok;
  388. }
  389. /* LookupType 2 */
  390. /* Sequence */
  391. static TT_Error Load_Sequence( TTO_Sequence* s,
  392. PFace input )
  393. {
  394. DEFINE_LOAD_LOCALS( input->stream );
  395. UShort n, count;
  396. UShort* sub;
  397. if ( ACCESS_Frame( 2L ) )
  398. return error;
  399. count = s->GlyphCount = GET_UShort();
  400. FORGET_Frame();
  401. s->Substitute = NULL;
  402. if ( count )
  403. {
  404. if ( ALLOC_ARRAY( s->Substitute, count, UShort ) )
  405. return error;
  406. sub = s->Substitute;
  407. if ( ACCESS_Frame( count * 2L ) )
  408. {
  409. FREE( sub );
  410. return error;
  411. }
  412. for ( n = 0; n < count; n++ )
  413. sub[n] = GET_UShort();
  414. FORGET_Frame();
  415. }
  416. return TT_Err_Ok;
  417. }
  418. static void Free_Sequence( TTO_Sequence* s )
  419. {
  420. FREE( s->Substitute );
  421. }
  422. /* MultipleSubstFormat1 */
  423. TT_Error Load_MultipleSubst( TTO_MultipleSubst* ms,
  424. PFace input )
  425. {
  426. DEFINE_LOAD_LOCALS( input->stream );
  427. UShort n, count;
  428. ULong cur_offset, new_offset, base_offset;
  429. TTO_Sequence* s;
  430. base_offset = FILE_Pos();
  431. if ( ACCESS_Frame( 4L ) )
  432. return error;
  433. ms->SubstFormat = GET_UShort(); /* should be 1 */
  434. new_offset = GET_UShort() + base_offset;
  435. FORGET_Frame();
  436. cur_offset = FILE_Pos();
  437. if ( FILE_Seek( new_offset ) ||
  438. ( error = Load_Coverage( &ms->Coverage, input ) ) != TT_Err_Ok )
  439. return error;
  440. (void)FILE_Seek( cur_offset );
  441. if ( ACCESS_Frame( 2L ) )
  442. goto Fail2;
  443. count = ms->SequenceCount = GET_UShort();
  444. FORGET_Frame();
  445. ms->Sequence = NULL;
  446. if ( ALLOC_ARRAY( ms->Sequence, count, TTO_Sequence ) )
  447. goto Fail2;
  448. s = ms->Sequence;
  449. for ( n = 0; n < count; n++ )
  450. {
  451. if ( ACCESS_Frame( 2L ) )
  452. goto Fail1;
  453. new_offset = GET_UShort() + base_offset;
  454. FORGET_Frame();
  455. cur_offset = FILE_Pos();
  456. if ( FILE_Seek( new_offset ) ||
  457. ( error = Load_Sequence( &s[n], input ) ) != TT_Err_Ok )
  458. goto Fail1;
  459. (void)FILE_Seek( cur_offset );
  460. }
  461. return TT_Err_Ok;
  462. Fail1:
  463. for ( n = 0; n < count; n++ )
  464. Free_Sequence( &s[n] );
  465. FREE( s );
  466. Fail2:
  467. Free_Coverage( &ms->Coverage );
  468. return error;
  469. }
  470. void Free_MultipleSubst( TTO_MultipleSubst* ms )
  471. {
  472. UShort n, count;
  473. TTO_Sequence* s;
  474. if ( ms->Sequence )
  475. {
  476. count = ms->SequenceCount;
  477. s = ms->Sequence;
  478. for ( n = 0; n < count; n++ )
  479. Free_Sequence( &s[n] );
  480. FREE( s );
  481. }
  482. Free_Coverage( &ms->Coverage );
  483. }
  484. static TT_Error Lookup_MultipleSubst( TTO_MultipleSubst* ms,
  485. TTO_GSUB_String* in,
  486. TTO_GSUB_String* out,
  487. UShort flags,
  488. UShort context_length,
  489. TTO_GDEFHeader* gdef )
  490. {
  491. TT_Error error;
  492. UShort index, property, n, count;
  493. UShort* s;
  494. if ( context_length != 0xFFFF && context_length < 1 )
  495. return TTO_Err_Not_Covered;
  496. if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
  497. return error;
  498. error = Coverage_Index( &ms->Coverage, in->string[in->pos], &index );
  499. if ( error )
  500. return error;
  501. if ( index >= ms->SequenceCount )
  502. return TTO_Err_Invalid_GSUB_SubTable;
  503. count = ms->Sequence[index].GlyphCount;
  504. s = ms->Sequence[index].Substitute;
  505. if ( ADD_String( in, 1, out, count, s ) )
  506. return error;
  507. if ( gdef && gdef->NewGlyphClasses )
  508. {
  509. /* this is a guess only ... */
  510. if ( property == TTO_LIGATURE )
  511. property = TTO_BASE_GLYPH;
  512. for ( n = 0; n < count; n++ )
  513. {
  514. error = Add_Glyph_Property( gdef, s[n], property );
  515. if ( error && error != TTO_Err_Not_Covered )
  516. return error;
  517. }
  518. }
  519. return TT_Err_Ok;
  520. }
  521. /* LookupType 3 */
  522. /* AlternateSet */
  523. static TT_Error Load_AlternateSet( TTO_AlternateSet* as,
  524. PFace input )
  525. {
  526. DEFINE_LOAD_LOCALS( input->stream );
  527. UShort n, count;
  528. UShort* a;
  529. if ( ACCESS_Frame( 2L ) )
  530. return error;
  531. count = as->GlyphCount = GET_UShort();
  532. FORGET_Frame();
  533. as->Alternate = NULL;
  534. if ( ALLOC_ARRAY( as->Alternate, count, UShort ) )
  535. return error;
  536. a = as->Alternate;
  537. if ( ACCESS_Frame( count * 2L ) )
  538. {
  539. FREE( a );
  540. return error;
  541. }
  542. for ( n = 0; n < count; n++ )
  543. a[n] = GET_UShort();
  544. FORGET_Frame();
  545. return TT_Err_Ok;
  546. }
  547. static void Free_AlternateSet( TTO_AlternateSet* as )
  548. {
  549. FREE( as->Alternate );
  550. }
  551. /* AlternateSubstFormat1 */
  552. TT_Error Load_AlternateSubst( TTO_AlternateSubst* as,
  553. PFace input )
  554. {
  555. DEFINE_LOAD_LOCALS( input->stream );
  556. UShort n, count;
  557. ULong cur_offset, new_offset, base_offset;
  558. TTO_AlternateSet* aset;
  559. base_offset = FILE_Pos();
  560. if ( ACCESS_Frame( 4L ) )
  561. return error;
  562. as->SubstFormat = GET_UShort(); /* should be 1 */
  563. new_offset = GET_UShort() + base_offset;
  564. FORGET_Frame();
  565. cur_offset = FILE_Pos();
  566. if ( FILE_Seek( new_offset ) ||
  567. ( error = Load_Coverage( &as->Coverage, input ) ) != TT_Err_Ok )
  568. return error;
  569. (void)FILE_Seek( cur_offset );
  570. if ( ACCESS_Frame( 2L ) )
  571. goto Fail2;
  572. count = as->AlternateSetCount = GET_UShort();
  573. FORGET_Frame();
  574. as->AlternateSet = NULL;
  575. if ( ALLOC_ARRAY( as->AlternateSet, count, TTO_AlternateSet ) )
  576. goto Fail2;
  577. aset = as->AlternateSet;
  578. for ( n = 0; n < count; n++ )
  579. {
  580. if ( ACCESS_Frame( 2L ) )
  581. goto Fail1;
  582. new_offset = GET_UShort() + base_offset;
  583. FORGET_Frame();
  584. cur_offset = FILE_Pos();
  585. if ( FILE_Seek( new_offset ) ||
  586. ( error = Load_AlternateSet( &aset[n], input ) ) != TT_Err_Ok )
  587. goto Fail1;
  588. (void)FILE_Seek( cur_offset );
  589. }
  590. return TT_Err_Ok;
  591. Fail1:
  592. for ( n = 0; n < count; n++ )
  593. Free_AlternateSet( &aset[n] );
  594. FREE( aset );
  595. Fail2:
  596. Free_Coverage( &as->Coverage );
  597. return error;
  598. }
  599. void Free_AlternateSubst( TTO_AlternateSubst* as )
  600. {
  601. UShort n, count;
  602. TTO_AlternateSet* aset;
  603. if ( as->AlternateSet )
  604. {
  605. count = as->AlternateSetCount;
  606. aset = as->AlternateSet;
  607. for ( n = 0; n < count; n++ )
  608. Free_AlternateSet( &aset[n] );
  609. FREE( aset );
  610. }
  611. Free_Coverage( &as->Coverage );
  612. }
  613. static TT_Error Lookup_AlternateSubst( TTO_GSUBHeader* gsub,
  614. TTO_AlternateSubst* as,
  615. TTO_GSUB_String* in,
  616. TTO_GSUB_String* out,
  617. UShort flags,
  618. UShort context_length,
  619. TTO_GDEFHeader* gdef )
  620. {
  621. TT_Error error;
  622. UShort index, alt_index, property;
  623. TTO_AlternateSet aset;
  624. if ( context_length != 0xFFFF && context_length < 1 )
  625. return TTO_Err_Not_Covered;
  626. if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
  627. return error;
  628. error = Coverage_Index( &as->Coverage, in->string[in->pos], &index );
  629. if ( error )
  630. return error;
  631. aset = as->AlternateSet[index];
  632. /* we use a user-defined callback function to get the alternate index */
  633. if ( gsub->alt )
  634. alt_index = (gsub->alt)( out->pos, in->string[in->pos],
  635. aset.GlyphCount, aset.Alternate,
  636. gsub->data );
  637. else
  638. alt_index = 0;
  639. if ( ADD_String( in, 1, out, 1, &aset.Alternate[alt_index] ) )
  640. return error;
  641. if ( gdef && gdef->NewGlyphClasses )
  642. {
  643. /* we inherit the old glyph class to the substituted glyph */
  644. error = Add_Glyph_Property( gdef, aset.Alternate[alt_index],
  645. property );
  646. if ( error && error != TTO_Err_Not_Covered )
  647. return error;
  648. }
  649. return TT_Err_Ok;
  650. }
  651. /* LookupType 4 */
  652. /* Ligature */
  653. static TT_Error Load_Ligature( TTO_Ligature* l,
  654. PFace input )
  655. {
  656. DEFINE_LOAD_LOCALS( input->stream );
  657. UShort n, count;
  658. UShort* c;
  659. if ( ACCESS_Frame( 4L ) )
  660. return error;
  661. l->LigGlyph = GET_UShort();
  662. l->ComponentCount = GET_UShort();
  663. FORGET_Frame();
  664. l->Component = NULL;
  665. count = l->ComponentCount - 1; /* only ComponentCount - 1 elements */
  666. if ( ALLOC_ARRAY( l->Component, count, UShort ) )
  667. return error;
  668. c = l->Component;
  669. if ( ACCESS_Frame( count * 2L ) )
  670. {
  671. FREE( c );
  672. return error;
  673. }
  674. for ( n = 0; n < count; n++ )
  675. c[n] = GET_UShort();
  676. FORGET_Frame();
  677. return TT_Err_Ok;
  678. }
  679. static void Free_Ligature( TTO_Ligature* l )
  680. {
  681. FREE( l->Component );
  682. }
  683. /* LigatureSet */
  684. static TT_Error Load_LigatureSet( TTO_LigatureSet* ls,
  685. PFace input )
  686. {
  687. DEFINE_LOAD_LOCALS( input->stream );
  688. UShort n, count;
  689. ULong cur_offset, new_offset, base_offset;
  690. TTO_Ligature* l;
  691. base_offset = FILE_Pos();
  692. if ( ACCESS_Frame( 2L ) )
  693. return error;
  694. count = ls->LigatureCount = GET_UShort();
  695. FORGET_Frame();
  696. ls->Ligature = NULL;
  697. if ( ALLOC_ARRAY( ls->Ligature, count, TTO_Ligature ) )
  698. return error;
  699. l = ls->Ligature;
  700. for ( n = 0; n < count; n++ )
  701. {
  702. if ( ACCESS_Frame( 2L ) )
  703. goto Fail;
  704. new_offset = GET_UShort() + base_offset;
  705. FORGET_Frame();
  706. cur_offset = FILE_Pos();
  707. if ( FILE_Seek( new_offset ) ||
  708. ( error = Load_Ligature( &l[n], input ) ) != TT_Err_Ok )
  709. goto Fail;
  710. (void)FILE_Seek( cur_offset );
  711. }
  712. return TT_Err_Ok;
  713. Fail:
  714. for ( n = 0; n < count; n++ )
  715. Free_Ligature( &l[n] );
  716. FREE( l );
  717. return error;
  718. }
  719. static void Free_LigatureSet( TTO_LigatureSet* ls )
  720. {
  721. UShort n, count;
  722. TTO_Ligature* l;
  723. if ( ls->Ligature )
  724. {
  725. count = ls->LigatureCount;
  726. l = ls->Ligature;
  727. for ( n = 0; n < count; n++ )
  728. Free_Ligature( &l[n] );
  729. FREE( l );
  730. }
  731. }
  732. /* LigatureSubstFormat1 */
  733. TT_Error Load_LigatureSubst( TTO_LigatureSubst* ls,
  734. PFace input )
  735. {
  736. DEFINE_LOAD_LOCALS( input->stream );
  737. UShort n, count;
  738. ULong cur_offset, new_offset, base_offset;
  739. TTO_LigatureSet* lset;
  740. base_offset = FILE_Pos();
  741. if ( ACCESS_Frame( 4L ) )
  742. return error;
  743. ls->SubstFormat = GET_UShort(); /* should be 1 */
  744. new_offset = GET_UShort() + base_offset;
  745. FORGET_Frame();
  746. cur_offset = FILE_Pos();
  747. if ( FILE_Seek( new_offset ) ||
  748. ( error = Load_Coverage( &ls->Coverage, input ) ) != TT_Err_Ok )
  749. return error;
  750. (void)FILE_Seek( cur_offset );
  751. if ( ACCESS_Frame( 2L ) )
  752. goto Fail2;
  753. count = ls->LigatureSetCount = GET_UShort();
  754. FORGET_Frame();
  755. ls->LigatureSet = NULL;
  756. if ( ALLOC_ARRAY( ls->LigatureSet, count, TTO_LigatureSet ) )
  757. goto Fail2;
  758. lset = ls->LigatureSet;
  759. for ( n = 0; n < count; n++ )
  760. {
  761. if ( ACCESS_Frame( 2L ) )
  762. goto Fail1;
  763. new_offset = GET_UShort() + base_offset;
  764. FORGET_Frame();
  765. cur_offset = FILE_Pos();
  766. if ( FILE_Seek( new_offset ) ||
  767. ( error = Load_LigatureSet( &lset[n], input ) ) != TT_Err_Ok )
  768. goto Fail1;
  769. (void)FILE_Seek( cur_offset );
  770. }
  771. return TT_Err_Ok;
  772. Fail1:
  773. for ( n = 0; n < count; n++ )
  774. Free_LigatureSet( &lset[n] );
  775. FREE( lset );
  776. Fail2:
  777. Free_Coverage( &ls->Coverage );
  778. return error;
  779. }
  780. void Free_LigatureSubst( TTO_LigatureSubst* ls )
  781. {
  782. UShort n, count;
  783. TTO_LigatureSet* lset;
  784. if ( ls->LigatureSet )
  785. {
  786. count = ls->LigatureSetCount;
  787. lset = ls->LigatureSet;
  788. for ( n = 0; n < count; n++ )
  789. Free_LigatureSet( &lset[n] );
  790. FREE( lset );
  791. }
  792. Free_Coverage( &ls->Coverage );
  793. }
  794. static TT_Error Lookup_LigatureSubst( TTO_LigatureSubst* ls,
  795. TTO_GSUB_String* in,
  796. TTO_GSUB_String* out,
  797. UShort flags,
  798. UShort context_length,
  799. TTO_GDEFHeader* gdef )
  800. {
  801. UShort index, property;
  802. TT_Error error;
  803. UShort numlig, i, j;
  804. UShort* s_in;
  805. UShort* c;
  806. TTO_Ligature* lig;
  807. if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
  808. return error;
  809. error = Coverage_Index( &ls->Coverage, in->string[in->pos], &index );
  810. if ( error )
  811. return error;
  812. if ( index >= ls->LigatureSetCount )
  813. return TTO_Err_Invalid_GSUB_SubTable;
  814. lig = ls->LigatureSet[index].Ligature;
  815. for ( numlig = ls->LigatureSet[index].LigatureCount;
  816. numlig;
  817. numlig--, lig++ )
  818. {
  819. if ( in->pos + lig->ComponentCount > in->length )
  820. continue; /* Not enough glyphs in input */
  821. s_in = &in->string[in->pos];
  822. c = lig->Component;
  823. if ( context_length != 0xFFFF && context_length < lig->ComponentCount )
  824. break;
  825. for ( i = 1, j = 1; i < lig->ComponentCount; i++, j++ )
  826. {
  827. while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
  828. {
  829. if ( error && error != TTO_Err_Not_Covered )
  830. return error;
  831. if ( in->pos + j < in->length )
  832. j++;
  833. else
  834. break;
  835. }
  836. if ( s_in[j] != c[i - 1] )
  837. break;
  838. }
  839. if ( i == lig->ComponentCount )
  840. {
  841. if ( ADD_String( in, lig->ComponentCount, out, 1, &lig->LigGlyph ) )
  842. return error;
  843. if ( gdef && gdef->NewGlyphClasses )
  844. {
  845. /* this is just a guess ... */
  846. error = Add_Glyph_Property( gdef, lig->LigGlyph, TTO_LIGATURE );
  847. if ( error && error != TTO_Err_Not_Covered )
  848. return error;
  849. }
  850. return TT_Err_Ok;
  851. }
  852. }
  853. return TTO_Err_Not_Covered;
  854. }
  855. /* Do the actual substitution for a context substitution (either format
  856. 5 or 6). This is only called after we've determined that the input
  857. matches the subrule. */
  858. static TT_Error Do_ContextSubst( TTO_GSUBHeader* gsub,
  859. UShort GlyphCount,
  860. UShort SubstCount,
  861. TTO_SubstLookupRecord* subst,
  862. TTO_GSUB_String* in,
  863. TTO_GSUB_String* out,
  864. int nesting_level )
  865. {
  866. TT_Error error;
  867. UShort i, old_pos;
  868. i = 0;
  869. while ( i < GlyphCount )
  870. {
  871. if ( SubstCount && i == subst->SequenceIndex )
  872. {
  873. old_pos = in->pos;
  874. /* Do a substitution */
  875. error = Do_Glyph_Lookup( gsub, subst->LookupListIndex, in, out,
  876. GlyphCount, nesting_level );
  877. subst++;
  878. SubstCount--;
  879. i += in->pos - old_pos;
  880. if ( error == TTO_Err_Not_Covered )
  881. {
  882. /* XXX "can't happen" -- but don't count on it */
  883. if ( ADD_String( in, 1, out, 1, &in->string[in->pos] ) )
  884. return error;
  885. i++;
  886. }
  887. else if ( error )
  888. return error;
  889. }
  890. else
  891. {
  892. /* No substitution for this index */
  893. if ( ADD_String( in, 1, out, 1, &in->string[in->pos] ) )
  894. return error;
  895. i++;
  896. }
  897. }
  898. return TT_Err_Ok;
  899. }
  900. /* LookupType 5 */
  901. /* SubRule */
  902. static TT_Error Load_SubRule( TTO_SubRule* sr,
  903. PFace input )
  904. {
  905. DEFINE_LOAD_LOCALS( input->stream );
  906. UShort n, count;
  907. UShort* i;
  908. TTO_SubstLookupRecord* slr;
  909. if ( ACCESS_Frame( 4L ) )
  910. return error;
  911. sr->GlyphCount = GET_UShort();
  912. sr->SubstCount = GET_UShort();
  913. FORGET_Frame();
  914. sr->Input = NULL;
  915. count = sr->GlyphCount - 1; /* only GlyphCount - 1 elements */
  916. if ( ALLOC_ARRAY( sr->Input, count, UShort ) )
  917. return error;
  918. i = sr->Input;
  919. if ( ACCESS_Frame( count * 2L ) )
  920. goto Fail2;
  921. for ( n = 0; n < count; n++ )
  922. i[n] = GET_UShort();
  923. FORGET_Frame();
  924. sr->SubstLookupRecord = NULL;
  925. count = sr->SubstCount;
  926. if ( ALLOC_ARRAY( sr->SubstLookupRecord, count, TTO_SubstLookupRecord ) )
  927. goto Fail2;
  928. slr = sr->SubstLookupRecord;
  929. if ( ACCESS_Frame( count * 4L ) )
  930. goto Fail1;
  931. for ( n = 0; n < count; n++ )
  932. {
  933. slr[n].SequenceIndex = GET_UShort();
  934. slr[n].LookupListIndex = GET_UShort();
  935. }
  936. FORGET_Frame();
  937. return TT_Err_Ok;
  938. Fail1:
  939. FREE( slr );
  940. Fail2:
  941. FREE( i );
  942. return error;
  943. }
  944. static void Free_SubRule( TTO_SubRule* sr )
  945. {
  946. FREE( sr->SubstLookupRecord );
  947. FREE( sr->Input );
  948. }
  949. /* SubRuleSet */
  950. static TT_Error Load_SubRuleSet( TTO_SubRuleSet* srs,
  951. PFace input )
  952. {
  953. DEFINE_LOAD_LOCALS( input->stream );
  954. UShort n, count;
  955. ULong cur_offset, new_offset, base_offset;
  956. TTO_SubRule* sr;
  957. base_offset = FILE_Pos();
  958. if ( ACCESS_Frame( 2L ) )
  959. return error;
  960. count = srs->SubRuleCount = GET_UShort();
  961. FORGET_Frame();
  962. srs->SubRule = NULL;
  963. if ( ALLOC_ARRAY( srs->SubRule, count, TTO_SubRule ) )
  964. return error;
  965. sr = srs->SubRule;
  966. for ( n = 0; n < count; n++ )
  967. {
  968. if ( ACCESS_Frame( 2L ) )
  969. goto Fail;
  970. new_offset = GET_UShort() + base_offset;
  971. FORGET_Frame();
  972. cur_offset = FILE_Pos();
  973. if ( FILE_Seek( new_offset ) ||
  974. ( error = Load_SubRule( &sr[n], input ) ) != TT_Err_Ok )
  975. goto Fail;
  976. (void)FILE_Seek( cur_offset );
  977. }
  978. return TT_Err_Ok;
  979. Fail:
  980. for ( n = 0; n < count; n++ )
  981. Free_SubRule( &sr[n] );
  982. FREE( sr );
  983. return error;
  984. }
  985. static void Free_SubRuleSet( TTO_SubRuleSet* srs )
  986. {
  987. UShort n, count;
  988. TTO_SubRule* sr;
  989. if ( srs->SubRule )
  990. {
  991. count = srs->SubRuleCount;
  992. sr = srs->SubRule;
  993. for ( n = 0; n < count; n++ )
  994. Free_SubRule( &sr[n] );
  995. FREE( sr );
  996. }
  997. }
  998. /* ContextSubstFormat1 */
  999. static TT_Error Load_ContextSubst1( TTO_ContextSubstFormat1* csf1,
  1000. PFace input )
  1001. {
  1002. DEFINE_LOAD_LOCALS( input->stream );
  1003. UShort n, count;
  1004. ULong cur_offset, new_offset, base_offset;
  1005. TTO_SubRuleSet* srs;
  1006. base_offset = FILE_Pos() - 2L;
  1007. if ( ACCESS_Frame( 2L ) )
  1008. return error;
  1009. new_offset = GET_UShort() + base_offset;
  1010. FORGET_Frame();
  1011. cur_offset = FILE_Pos();
  1012. if ( FILE_Seek( new_offset ) ||
  1013. ( error = Load_Coverage( &csf1->Coverage, input ) ) != TT_Err_Ok )
  1014. return error;
  1015. (void)FILE_Seek( cur_offset );
  1016. if ( ACCESS_Frame( 2L ) )
  1017. goto Fail2;
  1018. count = csf1->SubRuleSetCount = GET_UShort();
  1019. FORGET_Frame();
  1020. csf1->SubRuleSet = NULL;
  1021. if ( ALLOC_ARRAY( csf1->SubRuleSet, count, TTO_SubRuleSet ) )
  1022. goto Fail2;
  1023. srs = csf1->SubRuleSet;
  1024. for ( n = 0; n < count; n++ )
  1025. {
  1026. if ( ACCESS_Frame( 2L ) )
  1027. goto Fail1;
  1028. new_offset = GET_UShort() + base_offset;
  1029. FORGET_Frame();
  1030. cur_offset = FILE_Pos();
  1031. if ( FILE_Seek( new_offset ) ||
  1032. ( error = Load_SubRuleSet( &srs[n], input ) ) != TT_Err_Ok )
  1033. goto Fail1;
  1034. (void)FILE_Seek( cur_offset );
  1035. }
  1036. return TT_Err_Ok;
  1037. Fail1:
  1038. for ( n = 0; n < count; n++ )
  1039. Free_SubRuleSet( &srs[n] );
  1040. FREE( srs );
  1041. Fail2:
  1042. Free_Coverage( &csf1->Coverage );
  1043. return error;
  1044. }
  1045. static void Free_Context1( TTO_ContextSubstFormat1* csf1 )
  1046. {
  1047. UShort n, count;
  1048. TTO_SubRuleSet* srs;
  1049. if ( csf1->SubRuleSet )
  1050. {
  1051. count = csf1->SubRuleSetCount;
  1052. srs = csf1->SubRuleSet;
  1053. for ( n = 0; n < count; n++ )
  1054. Free_SubRuleSet( &srs[n] );
  1055. FREE( srs );
  1056. }
  1057. Free_Coverage( &csf1->Coverage );
  1058. }
  1059. /* SubClassRule */
  1060. static TT_Error Load_SubClassRule( TTO_ContextSubstFormat2* csf2,
  1061. TTO_SubClassRule* scr,
  1062. PFace input )
  1063. {
  1064. DEFINE_LOAD_LOCALS( input->stream );
  1065. UShort n, count;
  1066. UShort* c;
  1067. TTO_SubstLookupRecord* slr;
  1068. Bool* d;
  1069. if ( ACCESS_Frame( 4L ) )
  1070. return error;
  1071. scr->GlyphCount = GET_UShort();
  1072. scr->SubstCount = GET_UShort();
  1073. if ( scr->GlyphCount > csf2->MaxContextLength )
  1074. csf2->MaxContextLength = scr->GlyphCount;
  1075. FORGET_Frame();
  1076. scr->Class = NULL;
  1077. count = scr->GlyphCount - 1; /* only GlyphCount - 1 elements */
  1078. if ( ALLOC_ARRAY( scr->Class, count, UShort ) )
  1079. return error;
  1080. c = scr->Class;
  1081. d = csf2->ClassDef.Defined;
  1082. if ( ACCESS_Frame( count * 2L ) )
  1083. goto Fail2;
  1084. for ( n = 0; n < count; n++ )
  1085. {
  1086. c[n] = GET_UShort();
  1087. /* We check whether the specific class is used at all. If not,
  1088. class 0 is used instead. */
  1089. if ( !d[c[n]] )
  1090. c[n] = 0;
  1091. }
  1092. FORGET_Frame();
  1093. scr->SubstLookupRecord = NULL;
  1094. count = scr->SubstCount;
  1095. if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, TTO_SubstLookupRecord ) )
  1096. goto Fail2;
  1097. slr = scr->SubstLookupRecord;
  1098. if ( ACCESS_Frame( count * 4L ) )
  1099. goto Fail1;
  1100. for ( n = 0; n < count; n++ )
  1101. {
  1102. slr[n].SequenceIndex = GET_UShort();
  1103. slr[n].LookupListIndex = GET_UShort();
  1104. }
  1105. FORGET_Frame();
  1106. return TT_Err_Ok;
  1107. Fail1:
  1108. FREE( slr );
  1109. Fail2:
  1110. FREE( c );
  1111. return error;
  1112. }
  1113. static void Free_SubClassRule( TTO_SubClassRule* scr )
  1114. {
  1115. FREE( scr->SubstLookupRecord );
  1116. FREE( scr->Class );
  1117. }
  1118. /* SubClassSet */
  1119. static TT_Error Load_SubClassSet( TTO_ContextSubstFormat2* csf2,
  1120. TTO_SubClassSet* scs,
  1121. PFace input )
  1122. {
  1123. DEFINE_LOAD_LOCALS( input->stream );
  1124. UShort n, count;
  1125. ULong cur_offset, new_offset, base_offset;
  1126. TTO_SubClassRule* scr;
  1127. base_offset = FILE_Pos();
  1128. if ( ACCESS_Frame( 2L ) )
  1129. return error;
  1130. count = scs->SubClassRuleCount = GET_UShort();
  1131. FORGET_Frame();
  1132. scs->SubClassRule = NULL;
  1133. if ( ALLOC_ARRAY( scs->SubClassRule, count, TTO_SubClassRule ) )
  1134. return error;
  1135. scr = scs->SubClassRule;
  1136. for ( n = 0; n < count; n++ )
  1137. {
  1138. if ( ACCESS_Frame( 2L ) )
  1139. goto Fail;
  1140. new_offset = GET_UShort() + base_offset;
  1141. FORGET_Frame();
  1142. cur_offset = FILE_Pos();
  1143. if ( FILE_Seek( new_offset ) ||
  1144. ( error = Load_SubClassRule( csf2, &scr[n],
  1145. input ) ) != TT_Err_Ok )
  1146. goto Fail;
  1147. (void)FILE_Seek( cur_offset );
  1148. }
  1149. return TT_Err_Ok;
  1150. Fail:
  1151. for ( n = 0; n < count; n++ )
  1152. Free_SubClassRule( &scr[n] );
  1153. FREE( scr );
  1154. return error;
  1155. }
  1156. static void Free_SubClassSet( TTO_SubClassSet* scs )
  1157. {
  1158. UShort n, count;
  1159. TTO_SubClassRule* scr;
  1160. if ( scs->SubClassRule )
  1161. {
  1162. count = scs->SubClassRuleCount;
  1163. scr = scs->SubClassRule;
  1164. for ( n = 0; n < count; n++ )
  1165. Free_SubClassRule( &scr[n] );
  1166. FREE( scr );
  1167. }
  1168. }
  1169. /* ContextSubstFormat2 */
  1170. static TT_Error Load_ContextSubst2( TTO_ContextSubstFormat2* csf2,
  1171. PFace input )
  1172. {
  1173. DEFINE_LOAD_LOCALS( input->stream );
  1174. UShort n, count;
  1175. ULong cur_offset, new_offset, base_offset;
  1176. TTO_SubClassSet* scs;
  1177. base_offset = FILE_Pos() - 2;
  1178. if ( ACCESS_Frame( 2L ) )
  1179. return error;
  1180. new_offset = GET_UShort() + base_offset;
  1181. FORGET_Frame();
  1182. cur_offset = FILE_Pos();
  1183. if ( FILE_Seek( new_offset ) ||
  1184. ( error = Load_Coverage( &csf2->Coverage, input ) ) != TT_Err_Ok )
  1185. return error;
  1186. (void)FILE_Seek( cur_offset );
  1187. if ( ACCESS_Frame( 4L ) )
  1188. goto Fail3;
  1189. new_offset = GET_UShort() + base_offset;
  1190. /* `SubClassSetCount' is the upper limit for class values, thus we
  1191. read it now to make an additional safety check. */
  1192. count = csf2->SubClassSetCount = GET_UShort();
  1193. FORGET_Frame();
  1194. cur_offset = FILE_Pos();
  1195. if ( FILE_Seek( new_offset ) ||
  1196. ( error = Load_ClassDefinition( &csf2->ClassDef, count,
  1197. input ) ) != TT_Err_Ok )
  1198. goto Fail3;
  1199. (void)FILE_Seek( cur_offset );
  1200. csf2->SubClassSet = NULL;
  1201. csf2->MaxContextLength = 0;
  1202. if ( ALLOC_ARRAY( csf2->SubClassSet, count, TTO_SubClassSet ) )
  1203. goto Fail2;
  1204. scs = csf2->SubClassSet;
  1205. for ( n = 0; n < count; n++ )
  1206. {
  1207. if ( ACCESS_Frame( 2L ) )
  1208. goto Fail1;
  1209. new_offset = GET_UShort() + base_offset;
  1210. FORGET_Frame();
  1211. if ( new_offset != base_offset ) /* not a NULL offset */
  1212. {
  1213. cur_offset = FILE_Pos();
  1214. if ( FILE_Seek( new_offset ) ||
  1215. ( error = Load_SubClassSet( csf2, &scs[n],
  1216. input ) ) != TT_Err_Ok )
  1217. goto Fail1;
  1218. (void)FILE_Seek( cur_offset );
  1219. }
  1220. else
  1221. {
  1222. /* we create a SubClassSet table with no entries */
  1223. csf2->SubClassSet[n].SubClassRuleCount = 0;
  1224. csf2->SubClassSet[n].SubClassRule = NULL;
  1225. }
  1226. }
  1227. return TT_Err_Ok;
  1228. Fail1:
  1229. for ( n = 0; n < count; n++ )
  1230. Free_SubClassSet( &scs[n] );
  1231. FREE( scs );
  1232. Fail2:
  1233. Free_ClassDefinition( &csf2->ClassDef );
  1234. Fail3:
  1235. Free_Coverage( &csf2->Coverage );
  1236. return error;
  1237. }
  1238. static void Free_Context2( TTO_ContextSubstFormat2* csf2 )
  1239. {
  1240. UShort n, count;
  1241. TTO_SubClassSet* scs;
  1242. if ( csf2->SubClassSet )
  1243. {
  1244. count = csf2->SubClassSetCount;
  1245. scs = csf2->SubClassSet;
  1246. for ( n = 0; n < count; n++ )
  1247. Free_SubClassSet( &scs[n] );
  1248. FREE( scs );
  1249. }
  1250. Free_ClassDefinition( &csf2->ClassDef );
  1251. Free_Coverage( &csf2->Coverage );
  1252. }
  1253. /* ContextSubstFormat3 */
  1254. static TT_Error Load_ContextSubst3( TTO_ContextSubstFormat3* csf3,
  1255. PFace input )
  1256. {
  1257. DEFINE_LOAD_LOCALS( input->stream );
  1258. UShort n, count;
  1259. ULong cur_offset, new_offset, base_offset;
  1260. TTO_Coverage* c;
  1261. TTO_SubstLookupRecord* slr;
  1262. base_offset = FILE_Pos() - 2L;
  1263. if ( ACCESS_Frame( 4L ) )
  1264. return error;
  1265. csf3->GlyphCount = GET_UShort();
  1266. csf3->SubstCount = GET_UShort();
  1267. FORGET_Frame();
  1268. csf3->Coverage = NULL;
  1269. count = csf3->GlyphCount;
  1270. if ( ALLOC_ARRAY( csf3->Coverage, count, TTO_Coverage ) )
  1271. return error;
  1272. c = csf3->Coverage;
  1273. for ( n = 0; n < count; n++ )
  1274. {
  1275. if ( ACCESS_Frame( 2L ) )
  1276. goto Fail2;
  1277. new_offset = GET_UShort() + base_offset;
  1278. FORGET_Frame();
  1279. cur_offset = FILE_Pos();
  1280. if ( FILE_Seek( new_offset ) ||
  1281. ( error = Load_Coverage( &c[n], input ) ) != TT_Err_Ok )
  1282. goto Fail2;
  1283. (void)FILE_Seek( cur_offset );
  1284. }
  1285. csf3->SubstLookupRecord = NULL;
  1286. count = csf3->SubstCount;
  1287. if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count,
  1288. TTO_SubstLookupRecord ) )
  1289. goto Fail2;
  1290. slr = csf3->SubstLookupRecord;
  1291. if ( ACCESS_Frame( count * 4L ) )
  1292. goto Fail1;
  1293. for ( n = 0; n < count; n++ )
  1294. {
  1295. slr[n].SequenceIndex = GET_UShort();
  1296. slr[n].LookupListIndex = GET_UShort();
  1297. }
  1298. FORGET_Frame();
  1299. return TT_Err_Ok;
  1300. Fail1:
  1301. FREE( slr );
  1302. Fail2:
  1303. for ( n = 0; n < count; n++ )
  1304. Free_Coverage( &c[n] );
  1305. FREE( c );
  1306. return error;
  1307. }
  1308. static void Free_Context3( TTO_ContextSubstFormat3* csf3 )
  1309. {
  1310. UShort n, count;
  1311. TTO_Coverage* c;
  1312. FREE( csf3->SubstLookupRecord );
  1313. if ( csf3->Coverage )
  1314. {
  1315. count = csf3->GlyphCount;
  1316. c = csf3->Coverage;
  1317. for ( n = 0; n < count; n++ )
  1318. Free_Coverage( &c[n] );
  1319. FREE( c );
  1320. }
  1321. }
  1322. /* ContextSubst */
  1323. TT_Error Load_ContextSubst( TTO_ContextSubst* cs,
  1324. PFace input )
  1325. {
  1326. DEFINE_LOAD_LOCALS( input->stream );
  1327. if ( ACCESS_Frame( 2L ) )
  1328. return error;
  1329. cs->SubstFormat = GET_UShort();
  1330. FORGET_Frame();
  1331. switch ( cs->SubstFormat )
  1332. {
  1333. case 1:
  1334. return Load_ContextSubst1( &cs->csf.csf1, input );
  1335. case 2:
  1336. return Load_ContextSubst2( &cs->csf.csf2, input );
  1337. case 3:
  1338. return Load_ContextSubst3( &cs->csf.csf3, input );
  1339. default:
  1340. return TTO_Err_Invalid_GSUB_SubTable_Format;
  1341. }
  1342. return TT_Err_Ok; /* never reached */
  1343. }
  1344. void Free_ContextSubst( TTO_ContextSubst* cs )
  1345. {
  1346. switch ( cs->SubstFormat )
  1347. {
  1348. case 1:
  1349. Free_Context1( &cs->csf.csf1 );
  1350. break;
  1351. case 2:
  1352. Free_Context2( &cs->csf.csf2 );
  1353. break;
  1354. case 3:
  1355. Free_Context3( &cs->csf.csf3 );
  1356. break;
  1357. }
  1358. }
  1359. static TT_Error Lookup_ContextSubst1(
  1360. TTO_GSUBHeader* gsub,
  1361. TTO_ContextSubstFormat1* csf1,
  1362. TTO_GSUB_String* in,
  1363. TTO_GSUB_String* out,
  1364. UShort flags,
  1365. UShort context_length,
  1366. int nesting_level )
  1367. {
  1368. UShort index, property;
  1369. UShort i, j, k, numsr;
  1370. TT_Error error;
  1371. UShort* s_in;
  1372. TTO_SubRule* sr;
  1373. TTO_GDEFHeader* gdef;
  1374. gdef = gsub->gdef;
  1375. if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
  1376. return error;
  1377. error = Coverage_Index( &csf1->Coverage, in->string[in->pos], &index );
  1378. if ( error )
  1379. return error;
  1380. sr = csf1->SubRuleSet[index].SubRule;
  1381. numsr = csf1->SubRuleSet[index].SubRuleCount;
  1382. for ( k = 0; k < numsr; k++ )
  1383. {
  1384. if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )
  1385. continue;
  1386. if ( in->pos + sr[k].GlyphCount > in->length )
  1387. continue; /* context is too long */
  1388. s_in = &in->string[in->pos];
  1389. for ( i = 1, j = 1; i < sr[k].GlyphCount; i++, j++ )
  1390. {
  1391. while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
  1392. {
  1393. if ( error && error != TTO_Err_Not_Covered )
  1394. return error;
  1395. if ( in->pos + j < in->length )
  1396. j++;
  1397. else
  1398. break;
  1399. }
  1400. if ( s_in[j] != sr[k].Input[i - 1] )
  1401. break;
  1402. }
  1403. if ( i == sr[k].GlyphCount )
  1404. return Do_ContextSubst( gsub, sr[k].GlyphCount,
  1405. sr[k].SubstCount, sr[k].SubstLookupRecord,
  1406. in, out,
  1407. nesting_level );
  1408. }
  1409. return TTO_Err_Not_Covered;
  1410. }
  1411. static TT_Error Lookup_ContextSubst2(
  1412. TTO_GSUBHeader* gsub,
  1413. TTO_ContextSubstFormat2* csf2,
  1414. TTO_GSUB_String* in,
  1415. TTO_GSUB_String* out,
  1416. UShort flags,
  1417. UShort context_length,
  1418. int nesting_level )
  1419. {
  1420. UShort index, property;
  1421. TT_Error error;
  1422. UShort i, j, k, known_classes;
  1423. UShort* classes;
  1424. UShort* s_in;
  1425. UShort* cl;
  1426. TTO_SubClassSet* scs;
  1427. TTO_SubClassRule* sr;
  1428. TTO_GDEFHeader* gdef;
  1429. gdef = gsub->gdef;
  1430. if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, UShort ) )
  1431. return error;
  1432. if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
  1433. return error;
  1434. /* Note: The coverage table in format 2 doesn't give an index into
  1435. anything. It just lets us know whether or not we need to
  1436. do any lookup at all. */
  1437. error = Coverage_Index( &csf2->Coverage, in->string[in->pos], &index );
  1438. if ( error )
  1439. goto End;
  1440. error = Get_Class( &csf2->ClassDef, in->string[in->pos],
  1441. &classes[0], NULL );
  1442. if ( error )
  1443. goto End;
  1444. known_classes = 0;
  1445. scs = &csf2->SubClassSet[classes[0]];
  1446. if ( !scs )
  1447. {
  1448. error = TTO_Err_Invalid_GSUB_SubTable;
  1449. goto End;
  1450. }
  1451. for ( k = 0; k < scs->SubC

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