PageRenderTime 54ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/src/harfbuzz-gsub.c

https://bitbucket.org/cyanogenmod/android_external_harfbuzz
C | 4329 lines | 2874 code | 1293 blank | 162 comment | 679 complexity | 8d60ea2bb45c537963541ff3497eb05c MD5 | raw file
  1. /*
  2. * Copyright (C) 1998-2004 David Turner and Werner Lemberg
  3. * Copyright (C) 2006 Behdad Esfahbod
  4. * Copyright (C) 2007 Red Hat, Inc.
  5. *
  6. * This is part of HarfBuzz, an OpenType Layout engine library.
  7. *
  8. * Permission is hereby granted, without written agreement and without
  9. * license or royalty fees, to use, copy, modify, and distribute this
  10. * software and its documentation for any purpose, provided that the
  11. * above copyright notice and the following two paragraphs appear in
  12. * all copies of this software.
  13. *
  14. * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
  15. * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  16. * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
  17. * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  18. * DAMAGE.
  19. *
  20. * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  21. * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  22. * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
  23. * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  24. * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  25. *
  26. * Red Hat Author(s): Behdad Esfahbod
  27. */
  28. #include "harfbuzz-impl.h"
  29. #include "harfbuzz-gsub-private.h"
  30. #include "harfbuzz-open-private.h"
  31. #include "harfbuzz-gdef-private.h"
  32. static HB_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
  33. HB_UShort lookup_index,
  34. HB_Buffer buffer,
  35. HB_UShort context_length,
  36. int nesting_level );
  37. /**********************
  38. * Auxiliary functions
  39. **********************/
  40. HB_Error HB_Load_GSUB_Table( HB_Stream stream,
  41. HB_GSUBHeader** retptr,
  42. HB_GDEFHeader* gdef,
  43. HB_Stream gdefStream )
  44. {
  45. HB_Error error;
  46. HB_UInt cur_offset, new_offset, base_offset;
  47. HB_GSUBHeader* gsub;
  48. if ( !retptr )
  49. return ERR(HB_Err_Invalid_Argument);
  50. if ( GOTO_Table( TTAG_GSUB ) )
  51. return error;
  52. base_offset = FILE_Pos();
  53. if ( ALLOC ( gsub, sizeof( *gsub ) ) )
  54. return error;
  55. /* skip version */
  56. if ( FILE_Seek( base_offset + 4L ) ||
  57. ACCESS_Frame( 2L ) )
  58. goto Fail4;
  59. new_offset = GET_UShort() + base_offset;
  60. FORGET_Frame();
  61. cur_offset = FILE_Pos();
  62. if ( FILE_Seek( new_offset ) ||
  63. ( error = _HB_OPEN_Load_ScriptList( &gsub->ScriptList,
  64. stream ) ) != HB_Err_Ok )
  65. goto Fail4;
  66. (void)FILE_Seek( cur_offset );
  67. if ( ACCESS_Frame( 2L ) )
  68. goto Fail3;
  69. new_offset = GET_UShort() + base_offset;
  70. FORGET_Frame();
  71. cur_offset = FILE_Pos();
  72. if ( FILE_Seek( new_offset ) ||
  73. ( error = _HB_OPEN_Load_FeatureList( &gsub->FeatureList,
  74. stream ) ) != HB_Err_Ok )
  75. goto Fail3;
  76. (void)FILE_Seek( cur_offset );
  77. if ( ACCESS_Frame( 2L ) )
  78. goto Fail2;
  79. new_offset = GET_UShort() + base_offset;
  80. FORGET_Frame();
  81. cur_offset = FILE_Pos();
  82. if ( FILE_Seek( new_offset ) ||
  83. ( error = _HB_OPEN_Load_LookupList( &gsub->LookupList,
  84. stream, HB_Type_GSUB ) ) != HB_Err_Ok )
  85. goto Fail2;
  86. gsub->gdef = gdef; /* can be NULL */
  87. if ( ( error = _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, gdefStream,
  88. gsub->LookupList.Lookup,
  89. gsub->LookupList.LookupCount ) ) )
  90. goto Fail1;
  91. *retptr = gsub;
  92. return HB_Err_Ok;
  93. Fail1:
  94. _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB );
  95. Fail2:
  96. _HB_OPEN_Free_FeatureList( &gsub->FeatureList );
  97. Fail3:
  98. _HB_OPEN_Free_ScriptList( &gsub->ScriptList );
  99. Fail4:
  100. FREE ( gsub );
  101. return error;
  102. }
  103. HB_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub )
  104. {
  105. _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB );
  106. _HB_OPEN_Free_FeatureList( &gsub->FeatureList );
  107. _HB_OPEN_Free_ScriptList( &gsub->ScriptList );
  108. FREE( gsub );
  109. return HB_Err_Ok;
  110. }
  111. /*****************************
  112. * SubTable related functions
  113. *****************************/
  114. /* LookupType 1 */
  115. /* SingleSubstFormat1 */
  116. /* SingleSubstFormat2 */
  117. static HB_Error Load_SingleSubst( HB_GSUB_SubTable* st,
  118. HB_Stream stream )
  119. {
  120. HB_Error error;
  121. HB_SingleSubst* ss = &st->single;
  122. HB_UShort n, count;
  123. HB_UInt cur_offset, new_offset, base_offset;
  124. HB_UShort* s;
  125. base_offset = FILE_Pos();
  126. if ( ACCESS_Frame( 4L ) )
  127. return error;
  128. ss->SubstFormat = GET_UShort();
  129. new_offset = GET_UShort() + base_offset;
  130. FORGET_Frame();
  131. cur_offset = FILE_Pos();
  132. if ( FILE_Seek( new_offset ) ||
  133. ( error = _HB_OPEN_Load_Coverage( &ss->Coverage, stream ) ) != HB_Err_Ok )
  134. return error;
  135. (void)FILE_Seek( cur_offset );
  136. switch ( ss->SubstFormat )
  137. {
  138. case 1:
  139. if ( ACCESS_Frame( 2L ) )
  140. goto Fail2;
  141. ss->ssf.ssf1.DeltaGlyphID = GET_UShort();
  142. FORGET_Frame();
  143. break;
  144. case 2:
  145. if ( ACCESS_Frame( 2L ) )
  146. goto Fail2;
  147. count = ss->ssf.ssf2.GlyphCount = GET_UShort();
  148. FORGET_Frame();
  149. ss->ssf.ssf2.Substitute = NULL;
  150. if ( ALLOC_ARRAY( ss->ssf.ssf2.Substitute, count, HB_UShort ) )
  151. goto Fail2;
  152. s = ss->ssf.ssf2.Substitute;
  153. if ( ACCESS_Frame( count * 2L ) )
  154. goto Fail1;
  155. for ( n = 0; n < count; n++ )
  156. s[n] = GET_UShort();
  157. FORGET_Frame();
  158. break;
  159. default:
  160. return ERR(HB_Err_Invalid_SubTable_Format);
  161. }
  162. return HB_Err_Ok;
  163. Fail1:
  164. FREE( s );
  165. Fail2:
  166. _HB_OPEN_Free_Coverage( &ss->Coverage );
  167. return error;
  168. }
  169. static void Free_SingleSubst( HB_GSUB_SubTable* st )
  170. {
  171. HB_SingleSubst* ss = &st->single;
  172. switch ( ss->SubstFormat )
  173. {
  174. case 1:
  175. break;
  176. case 2:
  177. FREE( ss->ssf.ssf2.Substitute );
  178. break;
  179. default:
  180. break;
  181. }
  182. _HB_OPEN_Free_Coverage( &ss->Coverage );
  183. }
  184. static HB_Error Lookup_SingleSubst( HB_GSUBHeader* gsub,
  185. HB_GSUB_SubTable* st,
  186. HB_Buffer buffer,
  187. HB_UShort flags,
  188. HB_UShort context_length,
  189. int nesting_level )
  190. {
  191. HB_UShort index, value, property;
  192. HB_Error error;
  193. HB_SingleSubst* ss = &st->single;
  194. HB_GDEFHeader* gdef = gsub->gdef;
  195. HB_UNUSED(nesting_level);
  196. if ( context_length != 0xFFFF && context_length < 1 )
  197. return HB_Err_Not_Covered;
  198. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  199. return error;
  200. error = _HB_OPEN_Coverage_Index( &ss->Coverage, IN_CURGLYPH(), &index );
  201. if ( error )
  202. return error;
  203. switch ( ss->SubstFormat )
  204. {
  205. case 1:
  206. value = ( IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
  207. if ( REPLACE_Glyph( buffer, value, nesting_level ) )
  208. return error;
  209. break;
  210. case 2:
  211. if ( index >= ss->ssf.ssf2.GlyphCount )
  212. return ERR(HB_Err_Invalid_SubTable);
  213. value = ss->ssf.ssf2.Substitute[index];
  214. if ( REPLACE_Glyph( buffer, value, nesting_level ) )
  215. return error;
  216. break;
  217. default:
  218. return ERR(HB_Err_Invalid_SubTable);
  219. }
  220. if ( gdef && gdef->NewGlyphClasses )
  221. {
  222. /* we inherit the old glyph class to the substituted glyph */
  223. error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
  224. if ( error && error != HB_Err_Not_Covered )
  225. return error;
  226. }
  227. return HB_Err_Ok;
  228. }
  229. /* LookupType 2 */
  230. /* Sequence */
  231. static HB_Error Load_Sequence( HB_Sequence* s,
  232. HB_Stream stream )
  233. {
  234. HB_Error error;
  235. HB_UShort n, count;
  236. HB_UShort* sub;
  237. if ( ACCESS_Frame( 2L ) )
  238. return error;
  239. count = s->GlyphCount = GET_UShort();
  240. FORGET_Frame();
  241. s->Substitute = NULL;
  242. if ( count )
  243. {
  244. if ( ALLOC_ARRAY( s->Substitute, count, HB_UShort ) )
  245. return error;
  246. sub = s->Substitute;
  247. if ( ACCESS_Frame( count * 2L ) )
  248. {
  249. FREE( sub );
  250. return error;
  251. }
  252. for ( n = 0; n < count; n++ )
  253. sub[n] = GET_UShort();
  254. FORGET_Frame();
  255. }
  256. return HB_Err_Ok;
  257. }
  258. static void Free_Sequence( HB_Sequence* s )
  259. {
  260. FREE( s->Substitute );
  261. }
  262. /* MultipleSubstFormat1 */
  263. static HB_Error Load_MultipleSubst( HB_GSUB_SubTable* st,
  264. HB_Stream stream )
  265. {
  266. HB_Error error;
  267. HB_MultipleSubst* ms = &st->multiple;
  268. HB_UShort n = 0, m, count;
  269. HB_UInt cur_offset, new_offset, base_offset;
  270. HB_Sequence* s;
  271. base_offset = FILE_Pos();
  272. if ( ACCESS_Frame( 4L ) )
  273. return error;
  274. ms->SubstFormat = GET_UShort(); /* should be 1 */
  275. new_offset = GET_UShort() + base_offset;
  276. FORGET_Frame();
  277. cur_offset = FILE_Pos();
  278. if ( FILE_Seek( new_offset ) ||
  279. ( error = _HB_OPEN_Load_Coverage( &ms->Coverage, stream ) ) != HB_Err_Ok )
  280. return error;
  281. (void)FILE_Seek( cur_offset );
  282. if ( ACCESS_Frame( 2L ) )
  283. goto Fail2;
  284. count = ms->SequenceCount = GET_UShort();
  285. FORGET_Frame();
  286. ms->Sequence = NULL;
  287. if ( ALLOC_ARRAY( ms->Sequence, count, HB_Sequence ) )
  288. goto Fail2;
  289. s = ms->Sequence;
  290. for ( n = 0; n < count; n++ )
  291. {
  292. if ( ACCESS_Frame( 2L ) )
  293. goto Fail1;
  294. new_offset = GET_UShort() + base_offset;
  295. FORGET_Frame();
  296. cur_offset = FILE_Pos();
  297. if ( FILE_Seek( new_offset ) ||
  298. ( error = Load_Sequence( &s[n], stream ) ) != HB_Err_Ok )
  299. goto Fail1;
  300. (void)FILE_Seek( cur_offset );
  301. }
  302. return HB_Err_Ok;
  303. Fail1:
  304. for ( m = 0; m < n; m++ )
  305. Free_Sequence( &s[m] );
  306. FREE( s );
  307. Fail2:
  308. _HB_OPEN_Free_Coverage( &ms->Coverage );
  309. return error;
  310. }
  311. static void Free_MultipleSubst( HB_GSUB_SubTable* st )
  312. {
  313. HB_UShort n, count;
  314. HB_MultipleSubst* ms = &st->multiple;
  315. HB_Sequence* s;
  316. if ( ms->Sequence )
  317. {
  318. count = ms->SequenceCount;
  319. s = ms->Sequence;
  320. for ( n = 0; n < count; n++ )
  321. Free_Sequence( &s[n] );
  322. FREE( s );
  323. }
  324. _HB_OPEN_Free_Coverage( &ms->Coverage );
  325. }
  326. static HB_Error Lookup_MultipleSubst( HB_GSUBHeader* gsub,
  327. HB_GSUB_SubTable* st,
  328. HB_Buffer buffer,
  329. HB_UShort flags,
  330. HB_UShort context_length,
  331. int nesting_level )
  332. {
  333. HB_Error error;
  334. HB_UShort index, property, n, count;
  335. HB_UShort*s;
  336. HB_MultipleSubst* ms = &st->multiple;
  337. HB_GDEFHeader* gdef = gsub->gdef;
  338. HB_UNUSED(nesting_level);
  339. if ( context_length != 0xFFFF && context_length < 1 )
  340. return HB_Err_Not_Covered;
  341. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  342. return error;
  343. error = _HB_OPEN_Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index );
  344. if ( error )
  345. return error;
  346. if ( index >= ms->SequenceCount )
  347. return ERR(HB_Err_Invalid_SubTable);
  348. count = ms->Sequence[index].GlyphCount;
  349. s = ms->Sequence[index].Substitute;
  350. if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) )
  351. return error;
  352. if ( gdef && gdef->NewGlyphClasses )
  353. {
  354. /* this is a guess only ... */
  355. if ( property == HB_GDEF_LIGATURE )
  356. property = HB_GDEF_BASE_GLYPH;
  357. for ( n = 0; n < count; n++ )
  358. {
  359. error = _HB_GDEF_Add_Glyph_Property( gdef, s[n], property );
  360. if ( error && error != HB_Err_Not_Covered )
  361. return error;
  362. }
  363. }
  364. return HB_Err_Ok;
  365. }
  366. /* LookupType 3 */
  367. /* AlternateSet */
  368. static HB_Error Load_AlternateSet( HB_AlternateSet* as,
  369. HB_Stream stream )
  370. {
  371. HB_Error error;
  372. HB_UShort n, count;
  373. HB_UShort* a;
  374. if ( ACCESS_Frame( 2L ) )
  375. return error;
  376. count = as->GlyphCount = GET_UShort();
  377. FORGET_Frame();
  378. as->Alternate = NULL;
  379. if ( ALLOC_ARRAY( as->Alternate, count, HB_UShort ) )
  380. return error;
  381. a = as->Alternate;
  382. if ( ACCESS_Frame( count * 2L ) )
  383. {
  384. FREE( a );
  385. return error;
  386. }
  387. for ( n = 0; n < count; n++ )
  388. a[n] = GET_UShort();
  389. FORGET_Frame();
  390. return HB_Err_Ok;
  391. }
  392. static void Free_AlternateSet( HB_AlternateSet* as )
  393. {
  394. FREE( as->Alternate );
  395. }
  396. /* AlternateSubstFormat1 */
  397. static HB_Error Load_AlternateSubst( HB_GSUB_SubTable* st,
  398. HB_Stream stream )
  399. {
  400. HB_Error error;
  401. HB_AlternateSubst* as = &st->alternate;
  402. HB_UShort n = 0, m, count;
  403. HB_UInt cur_offset, new_offset, base_offset;
  404. HB_AlternateSet* aset;
  405. base_offset = FILE_Pos();
  406. if ( ACCESS_Frame( 4L ) )
  407. return error;
  408. as->SubstFormat = GET_UShort(); /* should be 1 */
  409. new_offset = GET_UShort() + base_offset;
  410. FORGET_Frame();
  411. cur_offset = FILE_Pos();
  412. if ( FILE_Seek( new_offset ) ||
  413. ( error = _HB_OPEN_Load_Coverage( &as->Coverage, stream ) ) != HB_Err_Ok )
  414. return error;
  415. (void)FILE_Seek( cur_offset );
  416. if ( ACCESS_Frame( 2L ) )
  417. goto Fail2;
  418. count = as->AlternateSetCount = GET_UShort();
  419. FORGET_Frame();
  420. as->AlternateSet = NULL;
  421. if ( ALLOC_ARRAY( as->AlternateSet, count, HB_AlternateSet ) )
  422. goto Fail2;
  423. aset = as->AlternateSet;
  424. for ( n = 0; n < count; n++ )
  425. {
  426. if ( ACCESS_Frame( 2L ) )
  427. goto Fail1;
  428. new_offset = GET_UShort() + base_offset;
  429. FORGET_Frame();
  430. cur_offset = FILE_Pos();
  431. if ( FILE_Seek( new_offset ) ||
  432. ( error = Load_AlternateSet( &aset[n], stream ) ) != HB_Err_Ok )
  433. goto Fail1;
  434. (void)FILE_Seek( cur_offset );
  435. }
  436. return HB_Err_Ok;
  437. Fail1:
  438. for ( m = 0; m < n; m++ )
  439. Free_AlternateSet( &aset[m] );
  440. FREE( aset );
  441. Fail2:
  442. _HB_OPEN_Free_Coverage( &as->Coverage );
  443. return error;
  444. }
  445. static void Free_AlternateSubst( HB_GSUB_SubTable* st )
  446. {
  447. HB_UShort n, count;
  448. HB_AlternateSubst* as = &st->alternate;
  449. HB_AlternateSet* aset;
  450. if ( as->AlternateSet )
  451. {
  452. count = as->AlternateSetCount;
  453. aset = as->AlternateSet;
  454. for ( n = 0; n < count; n++ )
  455. Free_AlternateSet( &aset[n] );
  456. FREE( aset );
  457. }
  458. _HB_OPEN_Free_Coverage( &as->Coverage );
  459. }
  460. static HB_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub,
  461. HB_GSUB_SubTable* st,
  462. HB_Buffer buffer,
  463. HB_UShort flags,
  464. HB_UShort context_length,
  465. int nesting_level )
  466. {
  467. HB_Error error;
  468. HB_UShort index, value, alt_index, property;
  469. HB_AlternateSubst* as = &st->alternate;
  470. HB_GDEFHeader* gdef = gsub->gdef;
  471. HB_AlternateSet aset;
  472. HB_UNUSED(nesting_level);
  473. if ( context_length != 0xFFFF && context_length < 1 )
  474. return HB_Err_Not_Covered;
  475. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  476. return error;
  477. error = _HB_OPEN_Coverage_Index( &as->Coverage, IN_CURGLYPH(), &index );
  478. if ( error )
  479. return error;
  480. aset = as->AlternateSet[index];
  481. /* we use a user-defined callback function to get the alternate index */
  482. if ( gsub->altfunc )
  483. alt_index = (gsub->altfunc)( buffer->out_pos, IN_CURGLYPH(),
  484. aset.GlyphCount, aset.Alternate,
  485. gsub->data );
  486. else
  487. alt_index = 0;
  488. value = aset.Alternate[alt_index];
  489. if ( REPLACE_Glyph( buffer, value, nesting_level ) )
  490. return error;
  491. if ( gdef && gdef->NewGlyphClasses )
  492. {
  493. /* we inherit the old glyph class to the substituted glyph */
  494. error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
  495. if ( error && error != HB_Err_Not_Covered )
  496. return error;
  497. }
  498. return HB_Err_Ok;
  499. }
  500. /* LookupType 4 */
  501. /* Ligature */
  502. static HB_Error Load_Ligature( HB_Ligature* l,
  503. HB_Stream stream )
  504. {
  505. HB_Error error;
  506. HB_UShort n, count;
  507. HB_UShort* c;
  508. if ( ACCESS_Frame( 4L ) )
  509. return error;
  510. l->LigGlyph = GET_UShort();
  511. l->ComponentCount = GET_UShort();
  512. FORGET_Frame();
  513. l->Component = NULL;
  514. count = l->ComponentCount - 1; /* only ComponentCount - 1 elements */
  515. if ( ALLOC_ARRAY( l->Component, count, HB_UShort ) )
  516. return error;
  517. c = l->Component;
  518. if ( ACCESS_Frame( count * 2L ) )
  519. {
  520. FREE( c );
  521. return error;
  522. }
  523. for ( n = 0; n < count; n++ )
  524. c[n] = GET_UShort();
  525. FORGET_Frame();
  526. return HB_Err_Ok;
  527. }
  528. static void Free_Ligature( HB_Ligature* l )
  529. {
  530. FREE( l->Component );
  531. }
  532. /* LigatureSet */
  533. static HB_Error Load_LigatureSet( HB_LigatureSet* ls,
  534. HB_Stream stream )
  535. {
  536. HB_Error error;
  537. HB_UShort n = 0, m, count;
  538. HB_UInt cur_offset, new_offset, base_offset;
  539. HB_Ligature* l;
  540. base_offset = FILE_Pos();
  541. if ( ACCESS_Frame( 2L ) )
  542. return error;
  543. count = ls->LigatureCount = GET_UShort();
  544. FORGET_Frame();
  545. ls->Ligature = NULL;
  546. if ( ALLOC_ARRAY( ls->Ligature, count, HB_Ligature ) )
  547. return error;
  548. l = ls->Ligature;
  549. for ( n = 0; n < count; n++ )
  550. {
  551. if ( ACCESS_Frame( 2L ) )
  552. goto Fail;
  553. new_offset = GET_UShort() + base_offset;
  554. FORGET_Frame();
  555. cur_offset = FILE_Pos();
  556. if ( FILE_Seek( new_offset ) ||
  557. ( error = Load_Ligature( &l[n], stream ) ) != HB_Err_Ok )
  558. goto Fail;
  559. (void)FILE_Seek( cur_offset );
  560. }
  561. return HB_Err_Ok;
  562. Fail:
  563. for ( m = 0; m < n; m++ )
  564. Free_Ligature( &l[m] );
  565. FREE( l );
  566. return error;
  567. }
  568. static void Free_LigatureSet( HB_LigatureSet* ls )
  569. {
  570. HB_UShort n, count;
  571. HB_Ligature* l;
  572. if ( ls->Ligature )
  573. {
  574. count = ls->LigatureCount;
  575. l = ls->Ligature;
  576. for ( n = 0; n < count; n++ )
  577. Free_Ligature( &l[n] );
  578. FREE( l );
  579. }
  580. }
  581. /* LigatureSubstFormat1 */
  582. static HB_Error Load_LigatureSubst( HB_GSUB_SubTable* st,
  583. HB_Stream stream )
  584. {
  585. HB_Error error;
  586. HB_LigatureSubst* ls = &st->ligature;
  587. HB_UShort n = 0, m, count;
  588. HB_UInt cur_offset, new_offset, base_offset;
  589. HB_LigatureSet* lset;
  590. base_offset = FILE_Pos();
  591. if ( ACCESS_Frame( 4L ) )
  592. return error;
  593. ls->SubstFormat = GET_UShort(); /* should be 1 */
  594. new_offset = GET_UShort() + base_offset;
  595. FORGET_Frame();
  596. cur_offset = FILE_Pos();
  597. if ( FILE_Seek( new_offset ) ||
  598. ( error = _HB_OPEN_Load_Coverage( &ls->Coverage, stream ) ) != HB_Err_Ok )
  599. return error;
  600. (void)FILE_Seek( cur_offset );
  601. if ( ACCESS_Frame( 2L ) )
  602. goto Fail2;
  603. count = ls->LigatureSetCount = GET_UShort();
  604. FORGET_Frame();
  605. ls->LigatureSet = NULL;
  606. if ( ALLOC_ARRAY( ls->LigatureSet, count, HB_LigatureSet ) )
  607. goto Fail2;
  608. lset = ls->LigatureSet;
  609. for ( n = 0; n < count; n++ )
  610. {
  611. if ( ACCESS_Frame( 2L ) )
  612. goto Fail1;
  613. new_offset = GET_UShort() + base_offset;
  614. FORGET_Frame();
  615. cur_offset = FILE_Pos();
  616. if ( FILE_Seek( new_offset ) ||
  617. ( error = Load_LigatureSet( &lset[n], stream ) ) != HB_Err_Ok )
  618. goto Fail1;
  619. (void)FILE_Seek( cur_offset );
  620. }
  621. return HB_Err_Ok;
  622. Fail1:
  623. for ( m = 0; m < n; m++ )
  624. Free_LigatureSet( &lset[m] );
  625. FREE( lset );
  626. Fail2:
  627. _HB_OPEN_Free_Coverage( &ls->Coverage );
  628. return error;
  629. }
  630. static void Free_LigatureSubst( HB_GSUB_SubTable* st )
  631. {
  632. HB_UShort n, count;
  633. HB_LigatureSubst* ls = &st->ligature;
  634. HB_LigatureSet* lset;
  635. if ( ls->LigatureSet )
  636. {
  637. count = ls->LigatureSetCount;
  638. lset = ls->LigatureSet;
  639. for ( n = 0; n < count; n++ )
  640. Free_LigatureSet( &lset[n] );
  641. FREE( lset );
  642. }
  643. _HB_OPEN_Free_Coverage( &ls->Coverage );
  644. }
  645. static HB_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub,
  646. HB_GSUB_SubTable* st,
  647. HB_Buffer buffer,
  648. HB_UShort flags,
  649. HB_UShort context_length,
  650. int nesting_level )
  651. {
  652. HB_UShort index, property;
  653. HB_Error error;
  654. HB_UShort numlig, i, j, is_mark, first_is_mark = FALSE;
  655. HB_UShort* c;
  656. HB_LigatureSubst* ls = &st->ligature;
  657. HB_GDEFHeader* gdef = gsub->gdef;
  658. HB_Ligature* lig;
  659. HB_UNUSED(nesting_level);
  660. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  661. return error;
  662. if ( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
  663. first_is_mark = TRUE;
  664. error = _HB_OPEN_Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index );
  665. if ( error )
  666. return error;
  667. if ( index >= ls->LigatureSetCount )
  668. return ERR(HB_Err_Invalid_SubTable);
  669. lig = ls->LigatureSet[index].Ligature;
  670. for ( numlig = ls->LigatureSet[index].LigatureCount;
  671. numlig;
  672. numlig--, lig++ )
  673. {
  674. if ( buffer->in_pos + lig->ComponentCount > buffer->in_length )
  675. goto next_ligature; /* Not enough glyphs in input */
  676. c = lig->Component;
  677. is_mark = first_is_mark;
  678. if ( context_length != 0xFFFF && context_length < lig->ComponentCount )
  679. break;
  680. for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ )
  681. {
  682. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  683. {
  684. if ( error && error != HB_Err_Not_Covered )
  685. return error;
  686. if ( j + lig->ComponentCount - i == (HB_Int)buffer->in_length )
  687. goto next_ligature;
  688. j++;
  689. }
  690. if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
  691. is_mark = FALSE;
  692. if ( IN_GLYPH( j ) != c[i - 1] )
  693. goto next_ligature;
  694. }
  695. if ( gdef && gdef->NewGlyphClasses )
  696. {
  697. /* this is just a guess ... */
  698. error = _HB_GDEF_Add_Glyph_Property( gdef, lig->LigGlyph,
  699. is_mark ? HB_GDEF_MARK : HB_GDEF_LIGATURE );
  700. if ( error && error != HB_Err_Not_Covered )
  701. return error;
  702. }
  703. if ( j == buffer->in_pos + i ) /* No input glyphs skipped */
  704. {
  705. /* We don't use a new ligature ID if there are no skipped
  706. glyphs and the ligature already has an ID. */
  707. if ( IN_LIGID( buffer->in_pos ) )
  708. {
  709. if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
  710. 0xFFFF, 0xFFFF ) )
  711. return error;
  712. }
  713. else
  714. {
  715. HB_UShort ligID = _hb_buffer_allocate_ligid( buffer );
  716. if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
  717. 0xFFFF, ligID ) )
  718. return error;
  719. }
  720. }
  721. else
  722. {
  723. HB_UShort ligID = _hb_buffer_allocate_ligid( buffer );
  724. if ( ADD_Glyph( buffer, lig->LigGlyph, 0xFFFF, ligID ) )
  725. return error;
  726. /* Now we must do a second loop to copy the skipped glyphs to
  727. `out' and assign component values to it. We start with the
  728. glyph after the first component. Glyphs between component
  729. i and i+1 belong to component i. Together with the ligID
  730. value it is later possible to check whether a specific
  731. component value really belongs to a given ligature. */
  732. for ( i = 0; i < lig->ComponentCount - 1; i++ )
  733. {
  734. while ( CHECK_Property( gdef, IN_CURITEM(),
  735. flags, &property ) )
  736. if ( ADD_Glyph( buffer, IN_CURGLYPH(), i, ligID ) )
  737. return error;
  738. (buffer->in_pos)++;
  739. }
  740. }
  741. return HB_Err_Ok;
  742. next_ligature:
  743. ;
  744. }
  745. return HB_Err_Not_Covered;
  746. }
  747. /* Do the actual substitution for a context substitution (either format
  748. 5 or 6). This is only called after we've determined that the input
  749. matches the subrule. */
  750. static HB_Error Do_ContextSubst( HB_GSUBHeader* gsub,
  751. HB_UShort GlyphCount,
  752. HB_UShort SubstCount,
  753. HB_SubstLookupRecord* subst,
  754. HB_Buffer buffer,
  755. int nesting_level )
  756. {
  757. HB_Error error;
  758. HB_UInt i, old_pos;
  759. i = 0;
  760. while ( i < GlyphCount )
  761. {
  762. if ( SubstCount && i == subst->SequenceIndex )
  763. {
  764. old_pos = buffer->in_pos;
  765. /* Do a substitution */
  766. error = GSUB_Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer,
  767. GlyphCount, nesting_level );
  768. subst++;
  769. SubstCount--;
  770. i += buffer->in_pos - old_pos;
  771. if ( error == HB_Err_Not_Covered )
  772. {
  773. if ( COPY_Glyph( buffer ) )
  774. return error;
  775. i++;
  776. }
  777. else if ( error )
  778. return error;
  779. }
  780. else
  781. {
  782. /* No substitution for this index */
  783. if ( COPY_Glyph( buffer ) )
  784. return error;
  785. i++;
  786. }
  787. }
  788. return HB_Err_Ok;
  789. }
  790. /* LookupType 5 */
  791. /* SubRule */
  792. static HB_Error Load_SubRule( HB_SubRule* sr,
  793. HB_Stream stream )
  794. {
  795. HB_Error error;
  796. HB_UShort n, count;
  797. HB_UShort* i;
  798. HB_SubstLookupRecord* slr;
  799. if ( ACCESS_Frame( 4L ) )
  800. return error;
  801. sr->GlyphCount = GET_UShort();
  802. sr->SubstCount = GET_UShort();
  803. FORGET_Frame();
  804. sr->Input = NULL;
  805. count = sr->GlyphCount - 1; /* only GlyphCount - 1 elements */
  806. if ( ALLOC_ARRAY( sr->Input, count, HB_UShort ) )
  807. return error;
  808. i = sr->Input;
  809. if ( ACCESS_Frame( count * 2L ) )
  810. goto Fail2;
  811. for ( n = 0; n < count; n++ )
  812. i[n] = GET_UShort();
  813. FORGET_Frame();
  814. sr->SubstLookupRecord = NULL;
  815. count = sr->SubstCount;
  816. if ( ALLOC_ARRAY( sr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
  817. goto Fail2;
  818. slr = sr->SubstLookupRecord;
  819. if ( ACCESS_Frame( count * 4L ) )
  820. goto Fail1;
  821. for ( n = 0; n < count; n++ )
  822. {
  823. slr[n].SequenceIndex = GET_UShort();
  824. slr[n].LookupListIndex = GET_UShort();
  825. }
  826. FORGET_Frame();
  827. return HB_Err_Ok;
  828. Fail1:
  829. FREE( slr );
  830. Fail2:
  831. FREE( i );
  832. return error;
  833. }
  834. static void Free_SubRule( HB_SubRule* sr )
  835. {
  836. FREE( sr->SubstLookupRecord );
  837. FREE( sr->Input );
  838. }
  839. /* SubRuleSet */
  840. static HB_Error Load_SubRuleSet( HB_SubRuleSet* srs,
  841. HB_Stream stream )
  842. {
  843. HB_Error error;
  844. HB_UShort n = 0, m, count;
  845. HB_UInt cur_offset, new_offset, base_offset;
  846. HB_SubRule* sr;
  847. base_offset = FILE_Pos();
  848. if ( ACCESS_Frame( 2L ) )
  849. return error;
  850. count = srs->SubRuleCount = GET_UShort();
  851. FORGET_Frame();
  852. srs->SubRule = NULL;
  853. if ( ALLOC_ARRAY( srs->SubRule, count, HB_SubRule ) )
  854. return error;
  855. sr = srs->SubRule;
  856. for ( n = 0; n < count; n++ )
  857. {
  858. if ( ACCESS_Frame( 2L ) )
  859. goto Fail;
  860. new_offset = GET_UShort() + base_offset;
  861. FORGET_Frame();
  862. cur_offset = FILE_Pos();
  863. if ( FILE_Seek( new_offset ) ||
  864. ( error = Load_SubRule( &sr[n], stream ) ) != HB_Err_Ok )
  865. goto Fail;
  866. (void)FILE_Seek( cur_offset );
  867. }
  868. return HB_Err_Ok;
  869. Fail:
  870. for ( m = 0; m < n; m++ )
  871. Free_SubRule( &sr[m] );
  872. FREE( sr );
  873. return error;
  874. }
  875. static void Free_SubRuleSet( HB_SubRuleSet* srs )
  876. {
  877. HB_UShort n, count;
  878. HB_SubRule* sr;
  879. if ( srs->SubRule )
  880. {
  881. count = srs->SubRuleCount;
  882. sr = srs->SubRule;
  883. for ( n = 0; n < count; n++ )
  884. Free_SubRule( &sr[n] );
  885. FREE( sr );
  886. }
  887. }
  888. /* ContextSubstFormat1 */
  889. static HB_Error Load_ContextSubst1( HB_ContextSubstFormat1* csf1,
  890. HB_Stream stream )
  891. {
  892. HB_Error error;
  893. HB_UShort n = 0, m, count;
  894. HB_UInt cur_offset, new_offset, base_offset;
  895. HB_SubRuleSet* srs;
  896. base_offset = FILE_Pos() - 2L;
  897. if ( ACCESS_Frame( 2L ) )
  898. return error;
  899. new_offset = GET_UShort() + base_offset;
  900. FORGET_Frame();
  901. cur_offset = FILE_Pos();
  902. if ( FILE_Seek( new_offset ) ||
  903. ( error = _HB_OPEN_Load_Coverage( &csf1->Coverage, stream ) ) != HB_Err_Ok )
  904. return error;
  905. (void)FILE_Seek( cur_offset );
  906. if ( ACCESS_Frame( 2L ) )
  907. goto Fail2;
  908. count = csf1->SubRuleSetCount = GET_UShort();
  909. FORGET_Frame();
  910. csf1->SubRuleSet = NULL;
  911. if ( ALLOC_ARRAY( csf1->SubRuleSet, count, HB_SubRuleSet ) )
  912. goto Fail2;
  913. srs = csf1->SubRuleSet;
  914. for ( n = 0; n < count; n++ )
  915. {
  916. if ( ACCESS_Frame( 2L ) )
  917. goto Fail1;
  918. new_offset = GET_UShort() + base_offset;
  919. FORGET_Frame();
  920. cur_offset = FILE_Pos();
  921. if ( FILE_Seek( new_offset ) ||
  922. ( error = Load_SubRuleSet( &srs[n], stream ) ) != HB_Err_Ok )
  923. goto Fail1;
  924. (void)FILE_Seek( cur_offset );
  925. }
  926. return HB_Err_Ok;
  927. Fail1:
  928. for ( m = 0; m < n; m++ )
  929. Free_SubRuleSet( &srs[m] );
  930. FREE( srs );
  931. Fail2:
  932. _HB_OPEN_Free_Coverage( &csf1->Coverage );
  933. return error;
  934. }
  935. static void Free_ContextSubst1( HB_ContextSubstFormat1* csf1 )
  936. {
  937. HB_UShort n, count;
  938. HB_SubRuleSet* srs;
  939. if ( csf1->SubRuleSet )
  940. {
  941. count = csf1->SubRuleSetCount;
  942. srs = csf1->SubRuleSet;
  943. for ( n = 0; n < count; n++ )
  944. Free_SubRuleSet( &srs[n] );
  945. FREE( srs );
  946. }
  947. _HB_OPEN_Free_Coverage( &csf1->Coverage );
  948. }
  949. /* SubClassRule */
  950. static HB_Error Load_SubClassRule( HB_ContextSubstFormat2* csf2,
  951. HB_SubClassRule* scr,
  952. HB_Stream stream )
  953. {
  954. HB_Error error;
  955. HB_UShort n, count;
  956. HB_UShort* c;
  957. HB_SubstLookupRecord* slr;
  958. if ( ACCESS_Frame( 4L ) )
  959. return error;
  960. scr->GlyphCount = GET_UShort();
  961. scr->SubstCount = GET_UShort();
  962. if ( scr->GlyphCount > csf2->MaxContextLength )
  963. csf2->MaxContextLength = scr->GlyphCount;
  964. FORGET_Frame();
  965. scr->Class = NULL;
  966. count = scr->GlyphCount - 1; /* only GlyphCount - 1 elements */
  967. if ( ALLOC_ARRAY( scr->Class, count, HB_UShort ) )
  968. return error;
  969. c = scr->Class;
  970. if ( ACCESS_Frame( count * 2L ) )
  971. goto Fail2;
  972. for ( n = 0; n < count; n++ )
  973. c[n] = GET_UShort();
  974. FORGET_Frame();
  975. scr->SubstLookupRecord = NULL;
  976. count = scr->SubstCount;
  977. if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
  978. goto Fail2;
  979. slr = scr->SubstLookupRecord;
  980. if ( ACCESS_Frame( count * 4L ) )
  981. goto Fail1;
  982. for ( n = 0; n < count; n++ )
  983. {
  984. slr[n].SequenceIndex = GET_UShort();
  985. slr[n].LookupListIndex = GET_UShort();
  986. }
  987. FORGET_Frame();
  988. return HB_Err_Ok;
  989. Fail1:
  990. FREE( slr );
  991. Fail2:
  992. FREE( c );
  993. return error;
  994. }
  995. static void Free_SubClassRule( HB_SubClassRule* scr )
  996. {
  997. FREE( scr->SubstLookupRecord );
  998. FREE( scr->Class );
  999. }
  1000. /* SubClassSet */
  1001. static HB_Error Load_SubClassSet( HB_ContextSubstFormat2* csf2,
  1002. HB_SubClassSet* scs,
  1003. HB_Stream stream )
  1004. {
  1005. HB_Error error;
  1006. HB_UShort n = 0, m, count;
  1007. HB_UInt cur_offset, new_offset, base_offset;
  1008. HB_SubClassRule* scr;
  1009. base_offset = FILE_Pos();
  1010. if ( ACCESS_Frame( 2L ) )
  1011. return error;
  1012. count = scs->SubClassRuleCount = GET_UShort();
  1013. FORGET_Frame();
  1014. scs->SubClassRule = NULL;
  1015. if ( ALLOC_ARRAY( scs->SubClassRule, count, HB_SubClassRule ) )
  1016. return error;
  1017. scr = scs->SubClassRule;
  1018. for ( n = 0; n < count; n++ )
  1019. {
  1020. if ( ACCESS_Frame( 2L ) )
  1021. goto Fail;
  1022. new_offset = GET_UShort() + base_offset;
  1023. FORGET_Frame();
  1024. cur_offset = FILE_Pos();
  1025. if ( FILE_Seek( new_offset ) ||
  1026. ( error = Load_SubClassRule( csf2, &scr[n],
  1027. stream ) ) != HB_Err_Ok )
  1028. goto Fail;
  1029. (void)FILE_Seek( cur_offset );
  1030. }
  1031. return HB_Err_Ok;
  1032. Fail:
  1033. for ( m = 0; m < n; m++ )
  1034. Free_SubClassRule( &scr[m] );
  1035. FREE( scr );
  1036. return error;
  1037. }
  1038. static void Free_SubClassSet( HB_SubClassSet* scs )
  1039. {
  1040. HB_UShort n, count;
  1041. HB_SubClassRule* scr;
  1042. if ( scs->SubClassRule )
  1043. {
  1044. count = scs->SubClassRuleCount;
  1045. scr = scs->SubClassRule;
  1046. for ( n = 0; n < count; n++ )
  1047. Free_SubClassRule( &scr[n] );
  1048. FREE( scr );
  1049. }
  1050. }
  1051. /* ContextSubstFormat2 */
  1052. static HB_Error Load_ContextSubst2( HB_ContextSubstFormat2* csf2,
  1053. HB_Stream stream )
  1054. {
  1055. HB_Error error;
  1056. HB_UShort n = 0, m, count;
  1057. HB_UInt cur_offset, new_offset, base_offset;
  1058. HB_SubClassSet* scs;
  1059. base_offset = FILE_Pos() - 2;
  1060. if ( ACCESS_Frame( 2L ) )
  1061. return error;
  1062. new_offset = GET_UShort() + base_offset;
  1063. FORGET_Frame();
  1064. cur_offset = FILE_Pos();
  1065. if ( FILE_Seek( new_offset ) ||
  1066. ( error = _HB_OPEN_Load_Coverage( &csf2->Coverage, stream ) ) != HB_Err_Ok )
  1067. return error;
  1068. (void)FILE_Seek( cur_offset );
  1069. if ( ACCESS_Frame( 4L ) )
  1070. goto Fail3;
  1071. new_offset = GET_UShort() + base_offset;
  1072. /* `SubClassSetCount' is the upper limit for class values, thus we
  1073. read it now to make an additional safety check. */
  1074. count = csf2->SubClassSetCount = GET_UShort();
  1075. FORGET_Frame();
  1076. cur_offset = FILE_Pos();
  1077. if ( FILE_Seek( new_offset ) ||
  1078. ( error = _HB_OPEN_Load_ClassDefinition( &csf2->ClassDef, count,
  1079. stream ) ) != HB_Err_Ok )
  1080. goto Fail3;
  1081. (void)FILE_Seek( cur_offset );
  1082. csf2->SubClassSet = NULL;
  1083. csf2->MaxContextLength = 0;
  1084. if ( ALLOC_ARRAY( csf2->SubClassSet, count, HB_SubClassSet ) )
  1085. goto Fail2;
  1086. scs = csf2->SubClassSet;
  1087. for ( n = 0; n < count; n++ )
  1088. {
  1089. if ( ACCESS_Frame( 2L ) )
  1090. goto Fail1;
  1091. new_offset = GET_UShort() + base_offset;
  1092. FORGET_Frame();
  1093. if ( new_offset != base_offset ) /* not a NULL offset */
  1094. {
  1095. cur_offset = FILE_Pos();
  1096. if ( FILE_Seek( new_offset ) ||
  1097. ( error = Load_SubClassSet( csf2, &scs[n],
  1098. stream ) ) != HB_Err_Ok )
  1099. goto Fail1;
  1100. (void)FILE_Seek( cur_offset );
  1101. }
  1102. else
  1103. {
  1104. /* we create a SubClassSet table with no entries */
  1105. csf2->SubClassSet[n].SubClassRuleCount = 0;
  1106. csf2->SubClassSet[n].SubClassRule = NULL;
  1107. }
  1108. }
  1109. return HB_Err_Ok;
  1110. Fail1:
  1111. for ( m = 0; m < n; m++ )
  1112. Free_SubClassSet( &scs[m] );
  1113. FREE( scs );
  1114. Fail2:
  1115. _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef );
  1116. Fail3:
  1117. _HB_OPEN_Free_Coverage( &csf2->Coverage );
  1118. return error;
  1119. }
  1120. static void Free_ContextSubst2( HB_ContextSubstFormat2* csf2 )
  1121. {
  1122. HB_UShort n, count;
  1123. HB_SubClassSet* scs;
  1124. if ( csf2->SubClassSet )
  1125. {
  1126. count = csf2->SubClassSetCount;
  1127. scs = csf2->SubClassSet;
  1128. for ( n = 0; n < count; n++ )
  1129. Free_SubClassSet( &scs[n] );
  1130. FREE( scs );
  1131. }
  1132. _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef );
  1133. _HB_OPEN_Free_Coverage( &csf2->Coverage );
  1134. }
  1135. /* ContextSubstFormat3 */
  1136. static HB_Error Load_ContextSubst3( HB_ContextSubstFormat3* csf3,
  1137. HB_Stream stream )
  1138. {
  1139. HB_Error error;
  1140. HB_UShort n = 0, m, count;
  1141. HB_UInt cur_offset, new_offset, base_offset;
  1142. HB_Coverage* c;
  1143. HB_SubstLookupRecord* slr;
  1144. base_offset = FILE_Pos() - 2L;
  1145. if ( ACCESS_Frame( 4L ) )
  1146. return error;
  1147. csf3->GlyphCount = GET_UShort();
  1148. csf3->SubstCount = GET_UShort();
  1149. FORGET_Frame();
  1150. csf3->Coverage = NULL;
  1151. count = csf3->GlyphCount;
  1152. if ( ALLOC_ARRAY( csf3->Coverage, count, HB_Coverage ) )
  1153. return error;
  1154. c = csf3->Coverage;
  1155. for ( n = 0; n < count; n++ )
  1156. {
  1157. if ( ACCESS_Frame( 2L ) )
  1158. goto Fail2;
  1159. new_offset = GET_UShort() + base_offset;
  1160. FORGET_Frame();
  1161. cur_offset = FILE_Pos();
  1162. if ( FILE_Seek( new_offset ) ||
  1163. ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != HB_Err_Ok )
  1164. goto Fail2;
  1165. (void)FILE_Seek( cur_offset );
  1166. }
  1167. csf3->SubstLookupRecord = NULL;
  1168. count = csf3->SubstCount;
  1169. if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count,
  1170. HB_SubstLookupRecord ) )
  1171. goto Fail2;
  1172. slr = csf3->SubstLookupRecord;
  1173. if ( ACCESS_Frame( count * 4L ) )
  1174. goto Fail1;
  1175. for ( n = 0; n < count; n++ )
  1176. {
  1177. slr[n].SequenceIndex = GET_UShort();
  1178. slr[n].LookupListIndex = GET_UShort();
  1179. }
  1180. FORGET_Frame();
  1181. return HB_Err_Ok;
  1182. Fail1:
  1183. FREE( slr );
  1184. Fail2:
  1185. for ( m = 0; m < n; m++ )
  1186. _HB_OPEN_Free_Coverage( &c[m] );
  1187. FREE( c );
  1188. return error;
  1189. }
  1190. static void Free_ContextSubst3( HB_ContextSubstFormat3* csf3 )
  1191. {
  1192. HB_UShort n, count;
  1193. HB_Coverage* c;
  1194. FREE( csf3->SubstLookupRecord );
  1195. if ( csf3->Coverage )
  1196. {
  1197. count = csf3->GlyphCount;
  1198. c = csf3->Coverage;
  1199. for ( n = 0; n < count; n++ )
  1200. _HB_OPEN_Free_Coverage( &c[n] );
  1201. FREE( c );
  1202. }
  1203. }
  1204. /* ContextSubst */
  1205. static HB_Error Load_ContextSubst( HB_GSUB_SubTable* st,
  1206. HB_Stream stream )
  1207. {
  1208. HB_Error error;
  1209. HB_ContextSubst* cs = &st->context;
  1210. if ( ACCESS_Frame( 2L ) )
  1211. return error;
  1212. cs->SubstFormat = GET_UShort();
  1213. FORGET_Frame();
  1214. switch ( cs->SubstFormat )
  1215. {
  1216. case 1: return Load_ContextSubst1( &cs->csf.csf1, stream );
  1217. case 2: return Load_ContextSubst2( &cs->csf.csf2, stream );
  1218. case 3: return Load_ContextSubst3( &cs->csf.csf3, stream );
  1219. default: return ERR(HB_Err_Invalid_SubTable_Format);
  1220. }
  1221. return HB_Err_Ok; /* never reached */
  1222. }
  1223. static void Free_ContextSubst( HB_GSUB_SubTable* st )
  1224. {
  1225. HB_ContextSubst* cs = &st->context;
  1226. switch ( cs->SubstFormat )
  1227. {
  1228. case 1: Free_ContextSubst1( &cs->csf.csf1 ); break;
  1229. case 2: Free_ContextSubst2( &cs->csf.csf2 ); break;
  1230. case 3: Free_ContextSubst3( &cs->csf.csf3 ); break;
  1231. default: break;
  1232. }
  1233. }
  1234. static HB_Error Lookup_ContextSubst1( HB_GSUBHeader* gsub,
  1235. HB_ContextSubstFormat1* csf1,
  1236. HB_Buffer buffer,
  1237. HB_UShort flags,
  1238. HB_UShort context_length,
  1239. int nesting_level )
  1240. {
  1241. HB_UShort index, property;
  1242. HB_UShort i, j, k, numsr;
  1243. HB_Error error;
  1244. HB_SubRule* sr;
  1245. HB_GDEFHeader* gdef;
  1246. gdef = gsub->gdef;
  1247. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  1248. return error;
  1249. error = _HB_OPEN_Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index );
  1250. if ( error )
  1251. return error;
  1252. sr = csf1->SubRuleSet[index].SubRule;
  1253. numsr = csf1->SubRuleSet[index].SubRuleCount;
  1254. for ( k = 0; k < numsr; k++ )
  1255. {
  1256. if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )
  1257. goto next_subrule;
  1258. if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length )
  1259. goto next_subrule; /* context is too long */
  1260. for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ )
  1261. {
  1262. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  1263. {
  1264. if ( error && error != HB_Err_Not_Covered )
  1265. return error;
  1266. if ( j + sr[k].GlyphCount - i == (HB_Int)buffer->in_length )
  1267. goto next_subrule;
  1268. j++;
  1269. }
  1270. if ( IN_GLYPH( j ) != sr[k].Input[i - 1] )
  1271. goto next_subrule;
  1272. }
  1273. return Do_ContextSubst( gsub, sr[k].GlyphCount,
  1274. sr[k].SubstCount, sr[k].SubstLookupRecord,
  1275. buffer,
  1276. nesting_level );
  1277. next_subrule:
  1278. ;
  1279. }
  1280. return HB_Err_Not_Covered;
  1281. }
  1282. static HB_Error Lookup_ContextSubst2( HB_GSUBHeader* gsub,
  1283. HB_ContextSubstFormat2* csf2,
  1284. HB_Buffer buffer,
  1285. HB_UShort flags,
  1286. HB_UShort context_length,
  1287. int nesting_level )
  1288. {
  1289. HB_UShort index, property;
  1290. HB_Error error;
  1291. HB_UShort i, j, k, known_classes;
  1292. HB_UShort* classes;
  1293. HB_UShort* cl;
  1294. HB_SubClassSet* scs;
  1295. HB_SubClassRule* sr;
  1296. HB_GDEFHeader* gdef;
  1297. gdef = gsub->gdef;
  1298. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  1299. return error;
  1300. /* Note: The coverage table in format 2 doesn't give an index into
  1301. anything. It just lets us know whether or not we need to
  1302. do any lookup at all. */
  1303. error = _HB_OPEN_Coverage_Index( &csf2->Coverage, IN_CURGLYPH(), &index );
  1304. if ( error )
  1305. return error;
  1306. if (csf2->MaxContextLength < 1)
  1307. return HB_Err_Not_Covered;
  1308. if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, HB_UShort ) )
  1309. return error;
  1310. error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_CURGLYPH(),
  1311. &classes[0], NULL );
  1312. if ( error && error != HB_Err_Not_Covered )
  1313. goto End;
  1314. known_classes = 0;
  1315. scs = &csf2->SubClassSet[classes[0]];
  1316. if ( !scs )
  1317. {
  1318. error = ERR(HB_Err_Invalid_SubTable);
  1319. goto End;
  1320. }
  1321. for ( k = 0; k < scs->SubClassRuleCount; k++ )
  1322. {
  1323. sr = &scs->SubClassRule[k];
  1324. if ( context_length != 0xFFFF && context_length < sr->GlyphCount )
  1325. goto next_subclassrule;
  1326. if ( buffer->in_pos + sr->GlyphCount > buffer->in_length )
  1327. goto next_subclassrule; /* context is too long */
  1328. cl = sr->Class;
  1329. /* Start at 1 because [0] is implied */
  1330. for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ )
  1331. {
  1332. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  1333. {
  1334. if ( error && error != HB_Err_Not_Covered )
  1335. goto End;
  1336. if ( j + sr->GlyphCount - i < (HB_Int)buffer->in_length )
  1337. goto next_subclassrule;
  1338. j++;
  1339. }
  1340. if ( i > known_classes )
  1341. {
  1342. /* Keeps us from having to do this for each rule */
  1343. error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
  1344. if ( error && error != HB_Err_Not_Covered )
  1345. goto End;
  1346. known_classes = i;
  1347. }
  1348. if ( cl[i - 1] != classes[i] )
  1349. goto next_subclassrule;
  1350. }
  1351. error = Do_ContextSubst( gsub, sr->GlyphCount,
  1352. sr->SubstCount, sr->SubstLookupRecord,
  1353. buffer,
  1354. nesting_level );
  1355. goto End;
  1356. next_subclassrule:
  1357. ;
  1358. }
  1359. error = HB_Err_Not_Covered;
  1360. End:
  1361. FREE( classes );
  1362. return error;
  1363. }
  1364. static HB_Error Lookup_ContextSubst3( HB_GSUBHeader* gsub,
  1365. HB_ContextSubstFormat3* csf3,
  1366. HB_Buffer buffer,
  1367. HB_UShort flags,
  1368. HB_UShort context_length,
  1369. int nesting_level )
  1370. {
  1371. HB_Error error;
  1372. HB_UShort index, i, j, property;
  1373. HB_Coverage* c;
  1374. HB_GDEFHeader* gdef;
  1375. gdef = gsub->gdef;
  1376. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  1377. return error;
  1378. if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )
  1379. return HB_Err_Not_Covered;
  1380. if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length )
  1381. return HB_Err_Not_Covered; /* context is too long */
  1382. c = csf3->Coverage;
  1383. for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ )
  1384. {
  1385. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  1386. {
  1387. if ( error && error != HB_Err_Not_Covered )
  1388. return error;
  1389. if ( j + csf3->GlyphCount - i == (HB_Int)buffer->in_length )
  1390. return HB_Err_Not_Covered;
  1391. j++;
  1392. }
  1393. error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );
  1394. if ( error )
  1395. return error;
  1396. }
  1397. return Do_ContextSubst( gsub, csf3->GlyphCount,
  1398. csf3->SubstCount, csf3->SubstLookupRecord,
  1399. buffer,
  1400. nesting_level );
  1401. }
  1402. static HB_Error Lookup_ContextSubst( HB_GSUBHeader* gsub,
  1403. HB_GSUB_SubTable* st,
  1404. HB_Buffer buffer,
  1405. HB_UShort flags,
  1406. HB_UShort context_length,
  1407. int nesting_level )
  1408. {
  1409. HB_ContextSubst* cs = &st->context;
  1410. switch ( cs->SubstFormat )
  1411. {
  1412. case 1: return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer, flags, context_length, nesting_level );
  1413. case 2: return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer, flags, context_length, nesting_level );
  1414. case 3: return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer, flags, context_length, nesting_level );
  1415. default: return ERR(HB_Err_Invalid_SubTable_Format);
  1416. }
  1417. return HB_Err_Ok; /* never reached */
  1418. }
  1419. /* LookupType 6 */
  1420. /* ChainSubRule */
  1421. static HB_Error Load_ChainSubRule( HB_ChainSubRule* csr,
  1422. HB_Stream stream )
  1423. {
  1424. HB_Error error;
  1425. HB_UShort n, count;
  1426. HB_UShort* b;
  1427. HB_UShort* i;
  1428. HB_UShort* l;
  1429. HB_SubstLookupRecord* slr;
  1430. if ( ACCESS_Frame( 2L ) )
  1431. return error;
  1432. csr->BacktrackGlyphCount = GET_UShort();
  1433. FORGET_Frame();
  1434. csr->Backtrack = NULL;
  1435. count = csr->BacktrackGlyphCount;
  1436. if ( ALLOC_ARRAY( csr->Backtrack, count, HB_UShort ) )
  1437. return error;
  1438. b = csr->Backtrack;
  1439. if ( ACCESS_Frame( count * 2L ) )
  1440. goto Fail4;
  1441. for ( n = 0; n < count; n++ )
  1442. b[n] = GET_UShort();
  1443. FORGET_Frame();
  1444. if ( ACCESS_Frame( 2L ) )
  1445. goto Fail4;
  1446. csr->InputGlyphCount = GET_UShort();
  1447. FORGET_Frame();
  1448. csr->Input = NULL;
  1449. count = csr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
  1450. if ( ALLOC_ARRAY( csr->Input, count, HB_UShort ) )
  1451. goto Fail4;
  1452. i = csr->Input;
  1453. if ( ACCESS_Frame( count * 2L ) )
  1454. goto Fail3;
  1455. for ( n = 0; n < count; n++ )
  1456. i[n] = GET_UShort();
  1457. FORGET_Frame();
  1458. if ( ACCESS_Frame( 2L ) )
  1459. goto Fail3;
  1460. csr->LookaheadGlyphCount = GET_UShort();
  1461. FORGET_Frame();
  1462. csr->Lookahead = NULL;
  1463. count = csr->LookaheadGlyphCount;
  1464. if ( ALLOC_ARRAY( csr->Lookahead, count, HB_UShort ) )
  1465. goto Fail3;
  1466. l = csr->Lookahead;
  1467. if ( ACCESS_Frame( count * 2L ) )
  1468. goto Fail2;
  1469. for ( n = 0; n < count; n++ )
  1470. l[n] = GET_UShort();
  1471. FORGET_Frame();
  1472. if ( ACCESS_Frame( 2L ) )
  1473. goto Fail2;
  1474. csr->SubstCount = GET_UShort();
  1475. FORGET_Frame();
  1476. csr->SubstLookupRecord = NULL;
  1477. count = csr->SubstCount;
  1478. if ( ALLOC_ARRAY( csr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
  1479. goto Fail2;
  1480. slr = csr->SubstLookupRecord;
  1481. if ( ACCESS_Frame( count * 4L ) )
  1482. goto Fail1;
  1483. for ( n = 0; n < count; n++ )
  1484. {
  1485. slr[n].SequenceIndex = GET_UShort();
  1486. slr[n].LookupListIndex = GET_UShort();
  1487. }
  1488. FORGET_Frame();
  1489. return HB_Err_Ok;
  1490. Fail1:
  1491. FREE( slr );
  1492. Fail2:
  1493. FREE( l );
  1494. Fail3:
  1495. FREE( i );
  1496. Fail4:
  1497. FREE( b );
  1498. return error;
  1499. }
  1500. static void Free_ChainSubRule( HB_ChainSubRule* csr )
  1501. {
  1502. FREE( csr->SubstLookupRecord );
  1503. FREE( csr->Lookahead );
  1504. FREE( csr->Input );
  1505. FREE( csr->Backtrack );
  1506. }
  1507. /* ChainSubRuleSet */
  1508. static HB_Error Load_ChainSubRuleSet( HB_ChainSubRuleSet* csrs,
  1509. HB_Stream stream )
  1510. {
  1511. HB_Error error;
  1512. HB_UShort n = 0, m, count;
  1513. HB_UInt cur_offset, new_offset, base_offset;
  1514. HB_ChainSubRule* csr;
  1515. base_offset = FILE_Pos();
  1516. if ( ACCESS_Frame( 2L ) )
  1517. return error;
  1518. count = csrs->ChainSubRuleCount = GET_UShort();
  1519. FORGET_Frame();
  1520. csrs->ChainSubRule = NULL;
  1521. if ( ALLOC_ARRAY( csrs->ChainSubRule, count, HB_ChainSubRule ) )
  1522. return error;
  1523. csr = csrs->ChainSubRule;
  1524. for ( n = 0; n < count; n++ )
  1525. {
  1526. if ( ACCESS_Frame( 2L ) )
  1527. goto Fail;
  1528. new_offset = GET_UShort() + base_offset;
  1529. FORGET_Frame();
  1530. cur_offset = FILE_Pos();
  1531. if ( FILE_Seek( new_offset ) ||
  1532. ( error = Load_ChainSubRule( &csr[n], stream ) ) != HB_Err_Ok )
  1533. goto Fail;
  1534. (void)FILE_Seek( cur_offset );
  1535. }
  1536. return HB_Err_Ok;
  1537. Fail:
  1538. for ( m = 0; m < n; m++ )
  1539. Free_ChainSubRule( &csr[m] );
  1540. FREE( csr );
  1541. return error;
  1542. }
  1543. static void Free_ChainSubRuleSet( HB_ChainSubRuleSet* csrs )
  1544. {
  1545. HB_UShort n, count;
  1546. HB_ChainSubRule* csr;
  1547. if ( csrs->ChainSubRule )
  1548. {
  1549. count = csrs->ChainSubRuleCount;
  1550. csr = csrs->ChainSubRule;
  1551. for ( n = 0; n < count; n++ )
  1552. Free_ChainSubRule( &csr[n] );
  1553. FREE( csr );
  1554. }
  1555. }
  1556. /* ChainContextSubstFormat1 */
  1557. static HB_Error Load_ChainContextSubst1(
  1558. HB_ChainContextSubstFormat1* ccsf1,
  1559. HB_Stream stream )
  1560. {
  1561. HB_Error error;
  1562. HB_UShort n = 0, m, count;
  1563. HB_UInt cur_offset, new_offset, base_offset;
  1564. HB_ChainSubRuleSet* csrs;
  1565. base_offset = FILE_Pos() - 2L;
  1566. if ( ACCESS_Frame( 2L ) )
  1567. return error;
  1568. new_offset = GET_UShort() + base_offset;
  1569. FORGET_Frame();
  1570. cur_offset = FILE_Pos();
  1571. if ( FILE_Seek( new_offset ) ||
  1572. ( error = _HB_OPEN_Load_Coverage( &ccsf1->Coverage, stream ) ) != HB_Err_Ok )
  1573. return error;
  1574. (void)FILE_Seek( cur_offset );
  1575. if ( ACCESS_Frame( 2L ) )
  1576. goto Fail2;
  1577. count = ccsf1->ChainSubRuleSetCount = GET_UShort();
  1578. FORGET_Frame();
  1579. ccsf1->ChainSubRuleSet = NULL;
  1580. if ( ALLOC_ARRAY( ccsf1->ChainSubRuleSet, count, HB_ChainSubRuleSet ) )
  1581. goto Fail2;
  1582. csrs = ccsf1->ChainSubRuleSet;
  1583. for ( n = 0; n < count; n++ )
  1584. {
  1585. if ( ACCESS_Frame( 2L ) )
  1586. goto Fail1;
  1587. new_offset = GET_UShort() + base_offset;
  1588. FORGET_Frame();
  1589. cur_offset = FILE_Pos();
  1590. if ( FILE_Seek( new_offset ) ||
  1591. ( error = Load_ChainSubRuleSet( &csrs[n], stream ) ) != HB_Err_Ok )
  1592. goto Fail1;
  1593. (void)FILE_Seek( cur_offset );
  1594. }
  1595. return HB_Err_Ok;
  1596. Fail1:
  1597. for ( m = 0; m < n; m++ )
  1598. Free_ChainSubRuleSet( &csrs[m] );
  1599. FREE( csrs );
  1600. Fail2:
  1601. _HB_OPEN_Free_Coverage( &ccsf1->Coverage );
  1602. return error;
  1603. }
  1604. static void Free_ChainContextSubst1( HB_ChainContextSubstFormat1* ccsf1 )
  1605. {
  1606. HB_UShort n, count;
  1607. HB_ChainSubRuleSet* csrs;
  1608. if ( ccsf1->ChainSubRuleSet )
  1609. {
  1610. count = ccsf1->ChainSubRuleSetCount;
  1611. csrs = ccsf1->ChainSubRuleSet;
  1612. for ( n = 0; n < count; n++ )
  1613. Free_ChainSubRuleSet( &csrs[n] );
  1614. FREE( csrs );
  1615. }
  1616. _HB_OPEN_Free_Coverage( &ccsf1->Coverage );
  1617. }
  1618. /* ChainSubClassRule */
  1619. static HB_Error Load_ChainSubClassRule(
  1620. HB_ChainContextSubstFormat2* ccsf2,
  1621. HB_ChainSubClassRule* cscr,
  1622. HB_Stream stream )
  1623. {
  1624. HB_Error error;
  1625. HB_UShort n, count;
  1626. HB_UShort* b;
  1627. HB_UShort* i;
  1628. HB_UShort* l;
  1629. HB_SubstLookupRecord* slr;
  1630. if ( ACCESS_Frame( 2L ) )
  1631. return error;
  1632. cscr->BacktrackGlyphCount = GET_UShort();
  1633. FORGET_Frame();
  1634. if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength )
  1635. ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount;
  1636. cscr->Backtrack = NULL;
  1637. count = cscr->BacktrackGlyphCount;
  1638. if ( ALLOC_ARRAY( cscr->Backtrack, count, HB_UShort ) )
  1639. return error;
  1640. b = cscr->Backtrack;
  1641. if ( ACCESS_Frame( count * 2L ) )
  1642. goto Fail4;
  1643. for ( n = 0; n < count; n++ )
  1644. b[n] = GET_UShort();
  1645. FORGET_Frame();
  1646. if ( ACCESS_Frame( 2L ) )
  1647. goto Fail4;
  1648. cscr->InputGlyphCount = GET_UShort();
  1649. FORGET_Frame();
  1650. if ( cscr->InputGlyphCount > ccsf2->MaxInputLength )
  1651. ccsf2->MaxInputLength = cscr->InputGlyphCount;
  1652. cscr->Input = NULL;
  1653. count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
  1654. if ( ALLOC_ARRAY( cscr->Input, count, HB_UShort ) )
  1655. goto Fail4;
  1656. i = cscr->Input;
  1657. if ( ACCESS_Frame( count * 2L ) )
  1658. goto Fail3;
  1659. for ( n = 0; n < count; n++ )
  1660. i[n] = GET_UShort();
  1661. FORGET_Frame();
  1662. if ( ACCESS_Frame( 2L ) )
  1663. goto Fail3;
  1664. cscr->LookaheadGlyphCount = GET_UShort();
  1665. FORGET_Frame();
  1666. if ( cscr->LookaheadGlyphCount > ccsf2->MaxLookaheadLength )
  1667. ccsf2->MaxLookaheadLength = cscr->LookaheadGlyphCount;
  1668. cscr->Lookahead = NULL;
  1669. count = cscr->LookaheadGlyphCount;
  1670. if ( ALLOC_ARRAY( cscr->Lookahead, count, HB_UShort ) )
  1671. goto Fail3;
  1672. l = cscr->Lookahead;
  1673. if ( ACCESS_Frame( count * 2L ) )
  1674. goto Fail2;
  1675. for ( n = 0; n < count; n++ )
  1676. l[n] = GET_UShort();
  1677. FORGET_Frame();
  1678. if ( ACCESS_Frame( 2L ) )
  1679. goto Fail2;
  1680. cscr->SubstCount = GET_UShort();
  1681. FORGET_Frame();
  1682. cscr->SubstLookupRecord = NULL;
  1683. count = cscr->SubstCount;
  1684. if ( ALLOC_ARRAY( cscr->SubstLookupRecord, count,
  1685. HB_SubstLookupRecord ) )
  1686. goto Fail2;
  1687. slr = cscr->SubstLookupRecord;
  1688. if ( ACCESS_Frame( count * 4L ) )
  1689. goto Fail1;
  1690. for ( n = 0; n < count; n++ )
  1691. {
  1692. slr[n].SequenceIndex = GET_UShort();
  1693. slr[n].LookupListIndex = GET_UShort();
  1694. }
  1695. FORGET_Frame();
  1696. return HB_Err_Ok;
  1697. Fail1:
  1698. FREE( slr );
  1699. Fail2:
  1700. FREE( l );
  1701. Fail3:
  1702. FREE( i );
  1703. Fail4:
  1704. FREE( b );
  1705. return error;
  1706. }
  1707. static void Free_ChainSubClassRule( HB_ChainSubClassRule* cscr )
  1708. {
  1709. FREE( cscr->SubstLookupRecord );
  1710. FREE( cscr->Lookahead );
  1711. FREE( cscr->Input );
  1712. FREE( cscr->Backtrack );
  1713. }
  1714. /* SubClassSet */
  1715. static HB_Error Load_ChainSubClassSet(
  1716. HB_ChainContextSubstFormat2* ccsf2,
  1717. HB_ChainSubClassSet* cscs,
  1718. HB_Stream stream )
  1719. {
  1720. HB_Error error;
  1721. HB_UShort n = 0, m, count;
  1722. HB_UInt cur_offset, new_offset, base_offset;
  1723. HB_ChainSubClassRule* cscr;
  1724. base_offset = FILE_Pos();
  1725. if ( ACCESS_Frame( 2L ) )
  1726. return error;
  1727. count = cscs->ChainSubClassRuleCount = GET_UShort();
  1728. FORGET_Frame();
  1729. cscs->ChainSubClassRule = NULL;
  1730. if ( ALLOC_ARRAY( cscs->ChainSubClassRule, count,
  1731. HB_ChainSubClassRule ) )
  1732. return error;
  1733. cscr = cscs->ChainSubClassRule;
  1734. for ( n = 0; n < count; n++ )
  1735. {
  1736. if ( ACCESS_Frame( 2L ) )
  1737. goto Fail;
  1738. new_offset = GET_UShort() + base_offset;
  1739. FORGET_Frame();
  1740. cur_offset = FILE_Pos();
  1741. if ( FILE_Seek( new_offset ) ||
  1742. ( error = Load_ChainSubClassRule( ccsf2, &cscr[n],
  1743. stream ) ) != HB_Err_Ok )
  1744. goto Fail;
  1745. (void)FILE_Seek( cur_offset );
  1746. }
  1747. return HB_Err_Ok;
  1748. Fail:
  1749. for ( m = 0; m < n; m++ )
  1750. Free_ChainSubClassRule( &cscr[m] );
  1751. FREE( cscr );
  1752. return error;
  1753. }
  1754. static void Free_ChainSubClassSet( HB_ChainSubClassSet* cscs )
  1755. {
  1756. HB_UShort n, count;
  1757. HB_ChainSubClassRule* cscr;
  1758. if ( cscs->ChainSubClassRule )
  1759. {
  1760. count = cscs->ChainSubClassRuleCount;
  1761. cscr = cscs->ChainSubClassRule;
  1762. for ( n = 0; n < count; n++ )
  1763. Free_ChainSubClassRule( &cscr[n] );
  1764. FREE( cscr );
  1765. }
  1766. }
  1767. /* ChainContextSubstFormat2 */
  1768. static HB_Error Load_ChainContextSubst2(
  1769. HB_ChainContextSubstFormat2* ccsf2,
  1770. HB_Stream stream )
  1771. {
  1772. HB_Error error;
  1773. HB_UShort n = 0, m, count;
  1774. HB_UInt cur_offset, new_offset, base_offset;
  1775. HB_UInt backtrack_offset, input_offset, lookahead_offset;
  1776. HB_ChainSubClassSet* cscs;
  1777. base_offset = FILE_Pos() - 2;
  1778. if ( ACCESS_Frame( 2L ) )
  1779. return error;
  1780. new_offset = GET_UShort() + base_offset;
  1781. FORGET_Frame();
  1782. cur_offset = FILE_Pos();
  1783. if ( FILE_Seek( new_offset ) ||
  1784. ( error = _HB_OPEN_Load_Coverage( &ccsf2->Coverage, stream ) ) != HB_Err_Ok )
  1785. return error;
  1786. (void)FILE_Seek( cur_offset );
  1787. if ( ACCESS_Frame( 8L ) )
  1788. goto Fail5;
  1789. backtrack_offset = GET_UShort();
  1790. input_offset = GET_UShort();
  1791. lookahead_offset = GET_UShort();
  1792. /* `ChainSubClassSetCount' is the upper limit for input class values,
  1793. thus we read it now to make an additional safety check. No limit
  1794. is known or needed for the other two class definitions */
  1795. count = ccsf2->ChainSubClassSetCount = GET_UShort();
  1796. FORGET_Frame();
  1797. if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535,
  1798. backtrack_offset, base_offset,
  1799. stream ) ) != HB_Err_Ok )
  1800. goto Fail5;
  1801. if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count,
  1802. input_offset, base_offset,
  1803. stream ) ) != HB_Err_Ok )
  1804. goto Fail4;
  1805. if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535,
  1806. lookahead_offset, base_offset,
  1807. stream ) ) != HB_Err_Ok )
  1808. goto Fail3;
  1809. ccsf2->ChainSubClassSet = NULL;
  1810. ccsf2->MaxBacktrackLength = 0;
  1811. ccsf2->MaxInputLength = 0;
  1812. ccsf2->MaxLookaheadLength = 0;
  1813. if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, HB_ChainSubClassSet ) )
  1814. goto Fail2;
  1815. cscs = ccsf2->ChainSubClassSet;
  1816. for ( n = 0; n < count; n++ )
  1817. {
  1818. if ( ACCESS_Frame( 2L ) )
  1819. goto Fail1;
  1820. new_offset = GET_UShort() + base_offset;
  1821. FORGET_Frame();
  1822. if ( new_offset != base_offset ) /* not a NULL offset */
  1823. {
  1824. cur_offset = FILE_Pos();
  1825. if ( FILE_Seek( new_offset ) ||
  1826. ( error = Load_ChainSubClassSet( ccsf2, &cscs[n],
  1827. stream ) ) != HB_Err_Ok )
  1828. goto Fail1;
  1829. (void)FILE_Seek( cur_offset );
  1830. }
  1831. else
  1832. {
  1833. /* we create a ChainSubClassSet table with no entries */
  1834. ccsf2->ChainSubClassSet[n].ChainSubClassRuleCount = 0;
  1835. ccsf2->ChainSubClassSet[n].ChainSubClassRule = NULL;
  1836. }
  1837. }
  1838. return HB_Err_Ok;
  1839. Fail1:
  1840. for ( m = 0; m < n; m++ )
  1841. Free_ChainSubClassSet( &cscs[m] );
  1842. FREE( cscs );
  1843. Fail2:
  1844. _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef );
  1845. Fail3:
  1846. _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef );
  1847. Fail4:
  1848. _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef );
  1849. Fail5:
  1850. _HB_OPEN_Free_Coverage( &ccsf2->Coverage );
  1851. return error;
  1852. }
  1853. static void Free_ChainContextSubst2( HB_ChainContextSubstFormat2* ccsf2 )
  1854. {
  1855. HB_UShort n, count;
  1856. HB_ChainSubClassSet* cscs;
  1857. if ( ccsf2->ChainSubClassSet )
  1858. {
  1859. count = ccsf2->ChainSubClassSetCount;
  1860. cscs = ccsf2->ChainSubClassSet;
  1861. for ( n = 0; n < count; n++ )
  1862. Free_ChainSubClassSet( &cscs[n] );
  1863. FREE( cscs );
  1864. }
  1865. _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef );
  1866. _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef );
  1867. _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef );
  1868. _HB_OPEN_Free_Coverage( &ccsf2->Coverage );
  1869. }
  1870. /* ChainContextSubstFormat3 */
  1871. static HB_Error Load_ChainContextSubst3(
  1872. HB_ChainContextSubstFormat3* ccsf3,
  1873. HB_Stream stream )
  1874. {
  1875. HB_Error error;
  1876. HB_UShort n, nb = 0, ni =0, nl = 0, m, count;
  1877. HB_UShort backtrack_count, input_count, lookahead_count;
  1878. HB_UInt cur_offset, new_offset, base_offset;
  1879. HB_Coverage* b;
  1880. HB_Coverage* i;
  1881. HB_Coverage* l;
  1882. HB_SubstLookupRecord* slr;
  1883. base_offset = FILE_Pos() - 2L;
  1884. if ( ACCESS_Frame( 2L ) )
  1885. return error;
  1886. ccsf3->BacktrackGlyphCount = GET_UShort();
  1887. FORGET_Frame();
  1888. ccsf3->BacktrackCoverage = NULL;
  1889. backtrack_count = ccsf3->BacktrackGlyphCount;
  1890. if ( ALLOC_ARRAY( ccsf3->BacktrackCoverage, backtrack_count,
  1891. HB_Coverage ) )
  1892. return error;
  1893. b = ccsf3->BacktrackCoverage;
  1894. for ( nb = 0; nb < backtrack_count; nb++ )
  1895. {
  1896. if ( ACCESS_Frame( 2L ) )
  1897. goto Fail4;
  1898. new_offset = GET_UShort() + base_offset;
  1899. FORGET_Frame();
  1900. cur_offset = FILE_Pos();
  1901. if ( FILE_Seek( new_offset ) ||
  1902. ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok )
  1903. goto Fail4;
  1904. (void)FILE_Seek( cur_offset );
  1905. }
  1906. if ( ACCESS_Frame( 2L ) )
  1907. goto Fail4;
  1908. ccsf3->InputGlyphCount = GET_UShort();
  1909. FORGET_Frame();
  1910. ccsf3->InputCoverage = NULL;
  1911. input_count = ccsf3->InputGlyphCount;
  1912. if ( ALLOC_ARRAY( ccsf3->InputCoverage, input_count, HB_Coverage ) )
  1913. goto Fail4;
  1914. i = ccsf3->InputCoverage;
  1915. for ( ni = 0; ni < input_count; ni++ )
  1916. {
  1917. if ( ACCESS_Frame( 2L ) )
  1918. goto Fail3;
  1919. new_offset = GET_UShort() + base_offset;
  1920. FORGET_Frame();
  1921. cur_offset = FILE_Pos();
  1922. if ( FILE_Seek( new_offset ) ||
  1923. ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_Err_Ok )
  1924. goto Fail3;
  1925. (void)FILE_Seek( cur_offset );
  1926. }
  1927. if ( ACCESS_Frame( 2L ) )
  1928. goto Fail3;
  1929. ccsf3->LookaheadGlyphCount = GET_UShort();
  1930. FORGET_Frame();
  1931. ccsf3->LookaheadCoverage = NULL;
  1932. lookahead_count = ccsf3->LookaheadGlyphCount;
  1933. if ( ALLOC_ARRAY( ccsf3->LookaheadCoverage, lookahead_count,
  1934. HB_Coverage ) )
  1935. goto Fail3;
  1936. l = ccsf3->LookaheadCoverage;
  1937. for ( nl = 0; nl < lookahead_count; nl++ )
  1938. {
  1939. if ( ACCESS_Frame( 2L ) )
  1940. goto Fail2;
  1941. new_offset = GET_UShort() + base_offset;
  1942. FORGET_Frame();
  1943. cur_offset = FILE_Pos();
  1944. if ( FILE_Seek( new_offset ) ||
  1945. ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok )
  1946. goto Fail2;
  1947. (void)FILE_Seek( cur_offset );
  1948. }
  1949. if ( ACCESS_Frame( 2L ) )
  1950. goto Fail2;
  1951. ccsf3->SubstCount = GET_UShort();
  1952. FORGET_Frame();
  1953. ccsf3->SubstLookupRecord = NULL;
  1954. count = ccsf3->SubstCount;
  1955. if ( ALLOC_ARRAY( ccsf3->SubstLookupRecord, count,
  1956. HB_SubstLookupRecord ) )
  1957. goto Fail2;
  1958. slr = ccsf3->SubstLookupRecord;
  1959. if ( ACCESS_Frame( count * 4L ) )
  1960. goto Fail1;
  1961. for ( n = 0; n < count; n++ )
  1962. {
  1963. slr[n].SequenceIndex = GET_UShort();
  1964. slr[n].LookupListIndex = GET_UShort();
  1965. }
  1966. FORGET_Frame();
  1967. return HB_Err_Ok;
  1968. Fail1:
  1969. FREE( slr );
  1970. Fail2:
  1971. for ( m = 0; m < nl; m++ )
  1972. _HB_OPEN_Free_Coverage( &l[m] );
  1973. FREE( l );
  1974. Fail3:
  1975. for ( m = 0; m < ni; m++ )
  1976. _HB_OPEN_Free_Coverage( &i[m] );
  1977. FREE( i );
  1978. Fail4:
  1979. for ( m = 0; m < nb; m++ )
  1980. _HB_OPEN_Free_Coverage( &b[m] );
  1981. FREE( b );
  1982. return error;
  1983. }
  1984. static void Free_ChainContextSubst3( HB_ChainContextSubstFormat3* ccsf3 )
  1985. {
  1986. HB_UShort n, count;
  1987. HB_Coverage* c;
  1988. FREE( ccsf3->SubstLookupRecord );
  1989. if ( ccsf3->LookaheadCoverage )
  1990. {
  1991. count = ccsf3->LookaheadGlyphCount;
  1992. c = ccsf3->LookaheadCoverage;
  1993. for ( n = 0; n < count; n++ )
  1994. _HB_OPEN_Free_Coverage( &c[n] );
  1995. FREE( c );
  1996. }
  1997. if ( ccsf3->InputCoverage )
  1998. {
  1999. count = ccsf3->InputGlyphCount;
  2000. c = ccsf3->InputCoverage;
  2001. for ( n = 0; n < count; n++ )
  2002. _HB_OPEN_Free_Coverage( &c[n] );
  2003. FREE( c );
  2004. }
  2005. if ( ccsf3->BacktrackCoverage )
  2006. {
  2007. count = ccsf3->BacktrackGlyphCount;
  2008. c = ccsf3->BacktrackCoverage;
  2009. for ( n = 0; n < count; n++ )
  2010. _HB_OPEN_Free_Coverage( &c[n] );
  2011. FREE( c );
  2012. }
  2013. }
  2014. /* ChainContextSubst */
  2015. static HB_Error Load_ChainContextSubst( HB_GSUB_SubTable* st,
  2016. HB_Stream stream )
  2017. {
  2018. HB_Error error;
  2019. HB_ChainContextSubst* ccs = &st->chain;
  2020. if ( ACCESS_Frame( 2L ) )
  2021. return error;
  2022. ccs->SubstFormat = GET_UShort();
  2023. FORGET_Frame();
  2024. switch ( ccs->SubstFormat ) {
  2025. case 1: return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream );
  2026. case 2: return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream );
  2027. case 3: return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream );
  2028. default: return ERR(HB_Err_Invalid_SubTable_Format);
  2029. }
  2030. return HB_Err_Ok; /* never reached */
  2031. }
  2032. static void Free_ChainContextSubst( HB_GSUB_SubTable* st )
  2033. {
  2034. HB_ChainContextSubst* ccs = &st->chain;
  2035. switch ( ccs->SubstFormat ) {
  2036. case 1: Free_ChainContextSubst1( &ccs->ccsf.ccsf1 ); break;
  2037. case 2: Free_ChainContextSubst2( &ccs->ccsf.ccsf2 ); break;
  2038. case 3: Free_ChainContextSubst3( &ccs->ccsf.ccsf3 ); break;
  2039. default: break;
  2040. }
  2041. }
  2042. static HB_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub,
  2043. HB_ChainContextSubstFormat1* ccsf1,
  2044. HB_Buffer buffer,
  2045. HB_UShort flags,
  2046. HB_UShort context_length,
  2047. int nesting_level )
  2048. {
  2049. HB_UShort index, property;
  2050. HB_UShort i, j, k, num_csr;
  2051. HB_UShort bgc, igc, lgc;
  2052. HB_Error error;
  2053. HB_ChainSubRule* csr;
  2054. HB_ChainSubRule curr_csr;
  2055. HB_GDEFHeader* gdef;
  2056. gdef = gsub->gdef;
  2057. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  2058. return error;
  2059. error = _HB_OPEN_Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index );
  2060. if ( error )
  2061. return error;
  2062. csr = ccsf1->ChainSubRuleSet[index].ChainSubRule;
  2063. num_csr = ccsf1->ChainSubRuleSet[index].ChainSubRuleCount;
  2064. for ( k = 0; k < num_csr; k++ )
  2065. {
  2066. curr_csr = csr[k];
  2067. bgc = curr_csr.BacktrackGlyphCount;
  2068. igc = curr_csr.InputGlyphCount;
  2069. lgc = curr_csr.LookaheadGlyphCount;
  2070. if ( context_length != 0xFFFF && context_length < igc )
  2071. goto next_chainsubrule;
  2072. /* check whether context is too long; it is a first guess only */
  2073. if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
  2074. goto next_chainsubrule;
  2075. if ( bgc )
  2076. {
  2077. /* since we don't know in advance the number of glyphs to inspect,
  2078. we search backwards for matches in the backtrack glyph array */
  2079. for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
  2080. {
  2081. while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
  2082. {
  2083. if ( error && error != HB_Err_Not_Covered )
  2084. return error;
  2085. if ( j + 1 == bgc - i )
  2086. goto next_chainsubrule;
  2087. j--;
  2088. }
  2089. /* In OpenType 1.3, it is undefined whether the offsets of
  2090. backtrack glyphs is in logical order or not. Version 1.4
  2091. will clarify this:
  2092. Logical order - a b c d e f g h i j
  2093. i
  2094. Input offsets - 0 1
  2095. Backtrack offsets - 3 2 1 0
  2096. Lookahead offsets - 0 1 2 3 */
  2097. if ( OUT_GLYPH( j ) != curr_csr.Backtrack[i] )
  2098. goto next_chainsubrule;
  2099. }
  2100. }
  2101. /* Start at 1 because [0] is implied */
  2102. for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
  2103. {
  2104. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  2105. {
  2106. if ( error && error != HB_Err_Not_Covered )
  2107. return error;
  2108. if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
  2109. goto next_chainsubrule;
  2110. j++;
  2111. }
  2112. if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] )
  2113. goto next_chainsubrule;
  2114. }
  2115. /* we are starting to check for lookahead glyphs right after the
  2116. last context glyph */
  2117. for ( i = 0; i < lgc; i++, j++ )
  2118. {
  2119. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  2120. {
  2121. if ( error && error != HB_Err_Not_Covered )
  2122. return error;
  2123. if ( j + lgc - i == (HB_Int)buffer->in_length )
  2124. goto next_chainsubrule;
  2125. j++;
  2126. }
  2127. if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] )
  2128. goto next_chainsubrule;
  2129. }
  2130. return Do_ContextSubst( gsub, igc,
  2131. curr_csr.SubstCount,
  2132. curr_csr.SubstLookupRecord,
  2133. buffer,
  2134. nesting_level );
  2135. next_chainsubrule:
  2136. ;
  2137. }
  2138. return HB_Err_Not_Covered;
  2139. }
  2140. static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub,
  2141. HB_ChainContextSubstFormat2* ccsf2,
  2142. HB_Buffer buffer,
  2143. HB_UShort flags,
  2144. HB_UShort context_length,
  2145. int nesting_level )
  2146. {
  2147. HB_UShort index, property;
  2148. HB_Error error;
  2149. HB_UShort i, j, k;
  2150. HB_UShort bgc, igc, lgc;
  2151. HB_UShort known_backtrack_classes,
  2152. known_input_classes,
  2153. known_lookahead_classes;
  2154. HB_UShort* backtrack_classes;
  2155. HB_UShort* input_classes;
  2156. HB_UShort* lookahead_classes;
  2157. HB_UShort* bc;
  2158. HB_UShort* ic;
  2159. HB_UShort* lc;
  2160. HB_ChainSubClassSet* cscs;
  2161. HB_ChainSubClassRule ccsr;
  2162. HB_GDEFHeader* gdef;
  2163. gdef = gsub->gdef;
  2164. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  2165. return error;
  2166. /* Note: The coverage table in format 2 doesn't give an index into
  2167. anything. It just lets us know whether or not we need to
  2168. do any lookup at all. */
  2169. error = _HB_OPEN_Coverage_Index( &ccsf2->Coverage, IN_CURGLYPH(), &index );
  2170. if ( error )
  2171. return error;
  2172. if ( ALLOC_ARRAY( backtrack_classes, ccsf2->MaxBacktrackLength, HB_UShort ) )
  2173. return error;
  2174. known_backtrack_classes = 0;
  2175. if (ccsf2->MaxInputLength < 1)
  2176. return HB_Err_Not_Covered;
  2177. if ( ALLOC_ARRAY( input_classes, ccsf2->MaxInputLength, HB_UShort ) )
  2178. goto End3;
  2179. known_input_classes = 1;
  2180. if ( ALLOC_ARRAY( lookahead_classes, ccsf2->MaxLookaheadLength, HB_UShort ) )
  2181. goto End2;
  2182. known_lookahead_classes = 0;
  2183. error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_CURGLYPH(),
  2184. &input_classes[0], NULL );
  2185. if ( error && error != HB_Err_Not_Covered )
  2186. goto End1;
  2187. cscs = &ccsf2->ChainSubClassSet[input_classes[0]];
  2188. if ( !cscs )
  2189. {
  2190. error = ERR(HB_Err_Invalid_SubTable);
  2191. goto End1;
  2192. }
  2193. for ( k = 0; k < cscs->ChainSubClassRuleCount; k++ )
  2194. {
  2195. ccsr = cscs->ChainSubClassRule[k];
  2196. bgc = ccsr.BacktrackGlyphCount;
  2197. igc = ccsr.InputGlyphCount;
  2198. lgc = ccsr.LookaheadGlyphCount;
  2199. if ( context_length != 0xFFFF && context_length < igc )
  2200. goto next_chainsubclassrule;
  2201. /* check whether context is too long; it is a first guess only */
  2202. if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
  2203. goto next_chainsubclassrule;
  2204. if ( bgc )
  2205. {
  2206. /* Since we don't know in advance the number of glyphs to inspect,
  2207. we search backwards for matches in the backtrack glyph array.
  2208. Note that `known_backtrack_classes' starts at index 0. */
  2209. bc = ccsr.Backtrack;
  2210. for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
  2211. {
  2212. while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
  2213. {
  2214. if ( error && error != HB_Err_Not_Covered )
  2215. goto End1;
  2216. if ( j + 1 == bgc - i )
  2217. goto next_chainsubclassrule;
  2218. j--;
  2219. }
  2220. if ( i >= known_backtrack_classes )
  2221. {
  2222. /* Keeps us from having to do this for each rule */
  2223. error = _HB_OPEN_Get_Class( &ccsf2->BacktrackClassDef, OUT_GLYPH( j ),
  2224. &backtrack_classes[i], NULL );
  2225. if ( error && error != HB_Err_Not_Covered )
  2226. goto End1;
  2227. known_backtrack_classes = i;
  2228. }
  2229. if ( bc[i] != backtrack_classes[i] )
  2230. goto next_chainsubclassrule;
  2231. }
  2232. }
  2233. ic = ccsr.Input;
  2234. /* Start at 1 because [0] is implied */
  2235. for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
  2236. {
  2237. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  2238. {
  2239. if ( error && error != HB_Err_Not_Covered )
  2240. goto End1;
  2241. if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
  2242. goto next_chainsubclassrule;
  2243. j++;
  2244. }
  2245. if ( i >= known_input_classes )
  2246. {
  2247. error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_GLYPH( j ),
  2248. &input_classes[i], NULL );
  2249. if ( error && error != HB_Err_Not_Covered )
  2250. goto End1;
  2251. known_input_classes = i;
  2252. }
  2253. if ( ic[i - 1] != input_classes[i] )
  2254. goto next_chainsubclassrule;
  2255. }
  2256. /* we are starting to check for lookahead glyphs right after the
  2257. last context glyph */
  2258. lc = ccsr.Lookahead;
  2259. for ( i = 0; i < lgc; i++, j++ )
  2260. {
  2261. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  2262. {
  2263. if ( error && error != HB_Err_Not_Covered )
  2264. goto End1;
  2265. if ( j + lgc - i == (HB_Int)buffer->in_length )
  2266. goto next_chainsubclassrule;
  2267. j++;
  2268. }
  2269. if ( i >= known_lookahead_classes )
  2270. {
  2271. error = _HB_OPEN_Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( j ),
  2272. &lookahead_classes[i], NULL );
  2273. if ( error && error != HB_Err_Not_Covered )
  2274. goto End1;
  2275. known_lookahead_classes = i;
  2276. }
  2277. if ( lc[i] != lookahead_classes[i] )
  2278. goto next_chainsubclassrule;
  2279. }
  2280. error = Do_ContextSubst( gsub, igc,
  2281. ccsr.SubstCount,
  2282. ccsr.SubstLookupRecord,
  2283. buffer,
  2284. nesting_level );
  2285. goto End1;
  2286. next_chainsubclassrule:
  2287. ;
  2288. }
  2289. error = HB_Err_Not_Covered;
  2290. End1:
  2291. FREE( lookahead_classes );
  2292. End2:
  2293. FREE( input_classes );
  2294. End3:
  2295. FREE( backtrack_classes );
  2296. return error;
  2297. }
  2298. static HB_Error Lookup_ChainContextSubst3( HB_GSUBHeader* gsub,
  2299. HB_ChainContextSubstFormat3* ccsf3,
  2300. HB_Buffer buffer,
  2301. HB_UShort flags,
  2302. HB_UShort context_length,
  2303. int nesting_level )
  2304. {
  2305. HB_UShort index, i, j, property;
  2306. HB_UShort bgc, igc, lgc;
  2307. HB_Error error;
  2308. HB_Coverage* bc;
  2309. HB_Coverage* ic;
  2310. HB_Coverage* lc;
  2311. HB_GDEFHeader* gdef;
  2312. gdef = gsub->gdef;
  2313. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  2314. return error;
  2315. bgc = ccsf3->BacktrackGlyphCount;
  2316. igc = ccsf3->InputGlyphCount;
  2317. lgc = ccsf3->LookaheadGlyphCount;
  2318. if ( context_length != 0xFFFF && context_length < igc )
  2319. return HB_Err_Not_Covered;
  2320. /* check whether context is too long; it is a first guess only */
  2321. if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
  2322. return HB_Err_Not_Covered;
  2323. if ( bgc )
  2324. {
  2325. /* Since we don't know in advance the number of glyphs to inspect,
  2326. we search backwards for matches in the backtrack glyph array */
  2327. bc = ccsf3->BacktrackCoverage;
  2328. for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
  2329. {
  2330. while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
  2331. {
  2332. if ( error && error != HB_Err_Not_Covered )
  2333. return error;
  2334. if ( j + 1 == bgc - i )
  2335. return HB_Err_Not_Covered;
  2336. j--;
  2337. }
  2338. error = _HB_OPEN_Coverage_Index( &bc[i], OUT_GLYPH( j ), &index );
  2339. if ( error )
  2340. return error;
  2341. }
  2342. }
  2343. ic = ccsf3->InputCoverage;
  2344. for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
  2345. {
  2346. /* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */
  2347. while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  2348. {
  2349. if ( error && error != HB_Err_Not_Covered )
  2350. return error;
  2351. if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
  2352. return HB_Err_Not_Covered;
  2353. j++;
  2354. }
  2355. error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
  2356. if ( error )
  2357. return error;
  2358. }
  2359. /* we are starting for lookahead glyphs right after the last context
  2360. glyph */
  2361. lc = ccsf3->LookaheadCoverage;
  2362. for ( i = 0; i < lgc; i++, j++ )
  2363. {
  2364. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  2365. {
  2366. if ( error && error != HB_Err_Not_Covered )
  2367. return error;
  2368. if ( j + lgc - i == (HB_Int)buffer->in_length )
  2369. return HB_Err_Not_Covered;
  2370. j++;
  2371. }
  2372. error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
  2373. if ( error )
  2374. return error;
  2375. }
  2376. return Do_ContextSubst( gsub, igc,
  2377. ccsf3->SubstCount,
  2378. ccsf3->SubstLookupRecord,
  2379. buffer,
  2380. nesting_level );
  2381. }
  2382. static HB_Error Lookup_ChainContextSubst( HB_GSUBHeader* gsub,
  2383. HB_GSUB_SubTable* st,
  2384. HB_Buffer buffer,
  2385. HB_UShort flags,
  2386. HB_UShort context_length,
  2387. int nesting_level )
  2388. {
  2389. HB_ChainContextSubst* ccs = &st->chain;
  2390. switch ( ccs->SubstFormat ) {
  2391. case 1: return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer, flags, context_length, nesting_level );
  2392. case 2: return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer, flags, context_length, nesting_level );
  2393. case 3: return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer, flags, context_length, nesting_level );
  2394. default: return ERR(HB_Err_Invalid_SubTable_Format);
  2395. }
  2396. }
  2397. static HB_Error Load_ReverseChainContextSubst( HB_GSUB_SubTable* st,
  2398. HB_Stream stream )
  2399. {
  2400. HB_Error error;
  2401. HB_ReverseChainContextSubst* rccs = &st->reverse;
  2402. HB_UShort m, count;
  2403. HB_UShort nb = 0, nl = 0, n;
  2404. HB_UShort backtrack_count, lookahead_count;
  2405. HB_UInt cur_offset, new_offset, base_offset;
  2406. HB_Coverage* b;
  2407. HB_Coverage* l;
  2408. HB_UShort* sub;
  2409. base_offset = FILE_Pos();
  2410. if ( ACCESS_Frame( 2L ) )
  2411. return error;
  2412. rccs->SubstFormat = GET_UShort();
  2413. if ( rccs->SubstFormat != 1 )
  2414. return ERR(HB_Err_Invalid_SubTable_Format);
  2415. FORGET_Frame();
  2416. if ( ACCESS_Frame( 2L ) )
  2417. return error;
  2418. new_offset = GET_UShort() + base_offset;
  2419. FORGET_Frame();
  2420. cur_offset = FILE_Pos();
  2421. if ( FILE_Seek( new_offset ) ||
  2422. ( error = _HB_OPEN_Load_Coverage( &rccs->Coverage, stream ) ) != HB_Err_Ok )
  2423. return error;
  2424. (void)FILE_Seek( cur_offset );
  2425. if ( ACCESS_Frame( 2L ) )
  2426. goto Fail4;
  2427. rccs->BacktrackGlyphCount = GET_UShort();
  2428. FORGET_Frame();
  2429. rccs->BacktrackCoverage = NULL;
  2430. backtrack_count = rccs->BacktrackGlyphCount;
  2431. if ( ALLOC_ARRAY( rccs->BacktrackCoverage, backtrack_count,
  2432. HB_Coverage ) )
  2433. goto Fail4;
  2434. b = rccs->BacktrackCoverage;
  2435. for ( nb = 0; nb < backtrack_count; nb++ )
  2436. {
  2437. if ( ACCESS_Frame( 2L ) )
  2438. goto Fail3;
  2439. new_offset = GET_UShort() + base_offset;
  2440. FORGET_Frame();
  2441. cur_offset = FILE_Pos();
  2442. if ( FILE_Seek( new_offset ) ||
  2443. ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok )
  2444. goto Fail3;
  2445. (void)FILE_Seek( cur_offset );
  2446. }
  2447. if ( ACCESS_Frame( 2L ) )
  2448. goto Fail3;
  2449. rccs->LookaheadGlyphCount = GET_UShort();
  2450. FORGET_Frame();
  2451. rccs->LookaheadCoverage = NULL;
  2452. lookahead_count = rccs->LookaheadGlyphCount;
  2453. if ( ALLOC_ARRAY( rccs->LookaheadCoverage, lookahead_count,
  2454. HB_Coverage ) )
  2455. goto Fail3;
  2456. l = rccs->LookaheadCoverage;
  2457. for ( nl = 0; nl < lookahead_count; nl++ )
  2458. {
  2459. if ( ACCESS_Frame( 2L ) )
  2460. goto Fail2;
  2461. new_offset = GET_UShort() + base_offset;
  2462. FORGET_Frame();
  2463. cur_offset = FILE_Pos();
  2464. if ( FILE_Seek( new_offset ) ||
  2465. ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok )
  2466. goto Fail2;
  2467. (void)FILE_Seek( cur_offset );
  2468. }
  2469. if ( ACCESS_Frame( 2L ) )
  2470. goto Fail2;
  2471. rccs->GlyphCount = GET_UShort();
  2472. FORGET_Frame();
  2473. rccs->Substitute = NULL;
  2474. count = rccs->GlyphCount;
  2475. if ( ALLOC_ARRAY( rccs->Substitute, count,
  2476. HB_UShort ) )
  2477. goto Fail2;
  2478. sub = rccs->Substitute;
  2479. if ( ACCESS_Frame( count * 2L ) )
  2480. goto Fail1;
  2481. for ( n = 0; n < count; n++ )
  2482. sub[n] = GET_UShort();
  2483. FORGET_Frame();
  2484. return HB_Err_Ok;
  2485. Fail1:
  2486. FREE( sub );
  2487. Fail2:
  2488. for ( m = 0; m < nl; m++ )
  2489. _HB_OPEN_Free_Coverage( &l[m] );
  2490. FREE( l );
  2491. Fail3:
  2492. for ( m = 0; m < nb; m++ )
  2493. _HB_OPEN_Free_Coverage( &b[m] );
  2494. FREE( b );
  2495. Fail4:
  2496. _HB_OPEN_Free_Coverage( &rccs->Coverage );
  2497. return error;
  2498. }
  2499. static void Free_ReverseChainContextSubst( HB_GSUB_SubTable* st )
  2500. {
  2501. HB_UShort n, count;
  2502. HB_ReverseChainContextSubst* rccs = &st->reverse;
  2503. HB_Coverage* c;
  2504. _HB_OPEN_Free_Coverage( &rccs->Coverage );
  2505. if ( rccs->LookaheadCoverage )
  2506. {
  2507. count = rccs->LookaheadGlyphCount;
  2508. c = rccs->LookaheadCoverage;
  2509. for ( n = 0; n < count; n++ )
  2510. _HB_OPEN_Free_Coverage( &c[n] );
  2511. FREE( c );
  2512. }
  2513. if ( rccs->BacktrackCoverage )
  2514. {
  2515. count = rccs->BacktrackGlyphCount;
  2516. c = rccs->BacktrackCoverage;
  2517. for ( n = 0; n < count; n++ )
  2518. _HB_OPEN_Free_Coverage( &c[n] );
  2519. FREE( c );
  2520. }
  2521. FREE ( rccs->Substitute );
  2522. }
  2523. static HB_Error Lookup_ReverseChainContextSubst( HB_GSUBHeader* gsub,
  2524. HB_GSUB_SubTable* st,
  2525. HB_Buffer buffer,
  2526. HB_UShort flags,
  2527. HB_UShort context_length,
  2528. int nesting_level )
  2529. {
  2530. HB_UShort index, input_index, i, j, property;
  2531. HB_UShort bgc, lgc;
  2532. HB_Error error;
  2533. HB_ReverseChainContextSubst* rccs = &st->reverse;
  2534. HB_Coverage* bc;
  2535. HB_Coverage* lc;
  2536. HB_GDEFHeader* gdef;
  2537. if ( nesting_level != 1 || context_length != 0xFFFF )
  2538. return HB_Err_Not_Covered;
  2539. gdef = gsub->gdef;
  2540. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  2541. return error;
  2542. bgc = rccs->BacktrackGlyphCount;
  2543. lgc = rccs->LookaheadGlyphCount;
  2544. /* check whether context is too long; it is a first guess only */
  2545. if ( bgc > buffer->in_pos || buffer->in_pos + 1 + lgc > buffer->in_length )
  2546. return HB_Err_Not_Covered;
  2547. if ( bgc )
  2548. {
  2549. /* Since we don't know in advance the number of glyphs to inspect,
  2550. we search backwards for matches in the backtrack glyph array */
  2551. bc = rccs->BacktrackCoverage;
  2552. for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
  2553. {
  2554. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  2555. {
  2556. if ( error && error != HB_Err_Not_Covered )
  2557. return error;
  2558. if ( j + 1 == bgc - i )
  2559. return HB_Err_Not_Covered;
  2560. j--;
  2561. }
  2562. error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
  2563. if ( error )
  2564. return error;
  2565. }
  2566. }
  2567. j = buffer->in_pos;
  2568. error = _HB_OPEN_Coverage_Index( &rccs->Coverage, IN_GLYPH( j ), &input_index );
  2569. if ( error )
  2570. return error;
  2571. lc = rccs->LookaheadCoverage;
  2572. for ( i = 0, j = buffer->in_pos + 1; i < lgc; i++, j++ )
  2573. {
  2574. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  2575. {
  2576. if ( error && error != HB_Err_Not_Covered )
  2577. return error;
  2578. if ( j + lgc - i == (HB_Int)buffer->in_length )
  2579. return HB_Err_Not_Covered;
  2580. j++;
  2581. }
  2582. error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
  2583. if ( error )
  2584. return error;
  2585. }
  2586. IN_CURGLYPH() = rccs->Substitute[input_index];
  2587. buffer->in_pos--; /* Reverse! */
  2588. return error;
  2589. }
  2590. /***********
  2591. * GSUB API
  2592. ***********/
  2593. HB_Error HB_GSUB_Select_Script( HB_GSUBHeader* gsub,
  2594. HB_UInt script_tag,
  2595. HB_UShort* script_index )
  2596. {
  2597. HB_UShort n;
  2598. HB_ScriptList* sl;
  2599. HB_ScriptRecord* sr;
  2600. if ( !gsub || !script_index )
  2601. return ERR(HB_Err_Invalid_Argument);
  2602. sl = &gsub->ScriptList;
  2603. sr = sl->ScriptRecord;
  2604. for ( n = 0; n < sl->ScriptCount; n++ )
  2605. if ( script_tag == sr[n].ScriptTag )
  2606. {
  2607. *script_index = n;
  2608. return HB_Err_Ok;
  2609. }
  2610. return HB_Err_Not_Covered;
  2611. }
  2612. HB_Error HB_GSUB_Select_Language( HB_GSUBHeader* gsub,
  2613. HB_UInt language_tag,
  2614. HB_UShort script_index,
  2615. HB_UShort* language_index,
  2616. HB_UShort* req_feature_index )
  2617. {
  2618. HB_UShort n;
  2619. HB_ScriptList* sl;
  2620. HB_ScriptRecord* sr;
  2621. HB_ScriptTable* s;
  2622. HB_LangSysRecord* lsr;
  2623. if ( !gsub || !language_index || !req_feature_index )
  2624. return ERR(HB_Err_Invalid_Argument);
  2625. sl = &gsub->ScriptList;
  2626. sr = sl->ScriptRecord;
  2627. if ( script_index >= sl->ScriptCount )
  2628. return ERR(HB_Err_Invalid_Argument);
  2629. s = &sr[script_index].Script;
  2630. lsr = s->LangSysRecord;
  2631. for ( n = 0; n < s->LangSysCount; n++ )
  2632. if ( language_tag == lsr[n].LangSysTag )
  2633. {
  2634. *language_index = n;
  2635. *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;
  2636. return HB_Err_Ok;
  2637. }
  2638. return HB_Err_Not_Covered;
  2639. }
  2640. /* selecting 0xFFFF for language_index asks for the values of the
  2641. default language (DefaultLangSys) */
  2642. HB_Error HB_GSUB_Select_Feature( HB_GSUBHeader* gsub,
  2643. HB_UInt feature_tag,
  2644. HB_UShort script_index,
  2645. HB_UShort language_index,
  2646. HB_UShort* feature_index )
  2647. {
  2648. HB_UShort n;
  2649. HB_ScriptList* sl;
  2650. HB_ScriptRecord* sr;
  2651. HB_ScriptTable* s;
  2652. HB_LangSysRecord* lsr;
  2653. HB_LangSys* ls;
  2654. HB_UShort* fi;
  2655. HB_FeatureList* fl;
  2656. HB_FeatureRecord* fr;
  2657. if ( !gsub || !feature_index )
  2658. return ERR(HB_Err_Invalid_Argument);
  2659. sl = &gsub->ScriptList;
  2660. sr = sl->ScriptRecord;
  2661. fl = &gsub->FeatureList;
  2662. fr = fl->FeatureRecord;
  2663. if ( script_index >= sl->ScriptCount )
  2664. return ERR(HB_Err_Invalid_Argument);
  2665. s = &sr[script_index].Script;
  2666. lsr = s->LangSysRecord;
  2667. if ( language_index == 0xFFFF )
  2668. ls = &s->DefaultLangSys;
  2669. else
  2670. {
  2671. if ( language_index >= s->LangSysCount )
  2672. return ERR(HB_Err_Invalid_Argument);
  2673. ls = &lsr[language_index].LangSys;
  2674. }
  2675. fi = ls->FeatureIndex;
  2676. for ( n = 0; n < ls->FeatureCount; n++ )
  2677. {
  2678. if ( fi[n] >= fl->FeatureCount )
  2679. return ERR(HB_Err_Invalid_SubTable_Format);
  2680. if ( feature_tag == fr[fi[n]].FeatureTag )
  2681. {
  2682. *feature_index = fi[n];
  2683. return HB_Err_Ok;
  2684. }
  2685. }
  2686. return HB_Err_Not_Covered;
  2687. }
  2688. /* The next three functions return a null-terminated list */
  2689. HB_Error HB_GSUB_Query_Scripts( HB_GSUBHeader* gsub,
  2690. HB_UInt** script_tag_list )
  2691. {
  2692. HB_UShort n;
  2693. HB_Error error;
  2694. HB_UInt* stl;
  2695. HB_ScriptList* sl;
  2696. HB_ScriptRecord* sr;
  2697. if ( !gsub || !script_tag_list )
  2698. return ERR(HB_Err_Invalid_Argument);
  2699. sl = &gsub->ScriptList;
  2700. sr = sl->ScriptRecord;
  2701. if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, HB_UInt ) )
  2702. return error;
  2703. for ( n = 0; n < sl->ScriptCount; n++ )
  2704. stl[n] = sr[n].ScriptTag;
  2705. stl[n] = 0;
  2706. *script_tag_list = stl;
  2707. return HB_Err_Ok;
  2708. }
  2709. HB_Error HB_GSUB_Query_Languages( HB_GSUBHeader* gsub,
  2710. HB_UShort script_index,
  2711. HB_UInt** language_tag_list )
  2712. {
  2713. HB_UShort n;
  2714. HB_Error error;
  2715. HB_UInt* ltl;
  2716. HB_ScriptList* sl;
  2717. HB_ScriptRecord* sr;
  2718. HB_ScriptTable* s;
  2719. HB_LangSysRecord* lsr;
  2720. if ( !gsub || !language_tag_list )
  2721. return ERR(HB_Err_Invalid_Argument);
  2722. sl = &gsub->ScriptList;
  2723. sr = sl->ScriptRecord;
  2724. if ( script_index >= sl->ScriptCount )
  2725. return ERR(HB_Err_Invalid_Argument);
  2726. s = &sr[script_index].Script;
  2727. lsr = s->LangSysRecord;
  2728. if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, HB_UInt ) )
  2729. return error;
  2730. for ( n = 0; n < s->LangSysCount; n++ )
  2731. ltl[n] = lsr[n].LangSysTag;
  2732. ltl[n] = 0;
  2733. *language_tag_list = ltl;
  2734. return HB_Err_Ok;
  2735. }
  2736. /* selecting 0xFFFF for language_index asks for the values of the
  2737. default language (DefaultLangSys) */
  2738. HB_Error HB_GSUB_Query_Features( HB_GSUBHeader* gsub,
  2739. HB_UShort script_index,
  2740. HB_UShort language_index,
  2741. HB_UInt** feature_tag_list )
  2742. {
  2743. HB_UShort n;
  2744. HB_Error error;
  2745. HB_UInt* ftl;
  2746. HB_ScriptList* sl;
  2747. HB_ScriptRecord* sr;
  2748. HB_ScriptTable* s;
  2749. HB_LangSysRecord* lsr;
  2750. HB_LangSys* ls;
  2751. HB_UShort* fi;
  2752. HB_FeatureList* fl;
  2753. HB_FeatureRecord* fr;
  2754. if ( !gsub || !feature_tag_list )
  2755. return ERR(HB_Err_Invalid_Argument);
  2756. sl = &gsub->ScriptList;
  2757. sr = sl->ScriptRecord;
  2758. fl = &gsub->FeatureList;
  2759. fr = fl->FeatureRecord;
  2760. if ( script_index >= sl->ScriptCount )
  2761. return ERR(HB_Err_Invalid_Argument);
  2762. s = &sr[script_index].Script;
  2763. lsr = s->LangSysRecord;
  2764. if ( language_index == 0xFFFF )
  2765. ls = &s->DefaultLangSys;
  2766. else
  2767. {
  2768. if ( language_index >= s->LangSysCount )
  2769. return ERR(HB_Err_Invalid_Argument);
  2770. ls = &lsr[language_index].LangSys;
  2771. }
  2772. fi = ls->FeatureIndex;
  2773. if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, HB_UInt ) )
  2774. return error;
  2775. for ( n = 0; n < ls->FeatureCount; n++ )
  2776. {
  2777. if ( fi[n] >= fl->FeatureCount )
  2778. {
  2779. FREE( ftl );
  2780. return ERR(HB_Err_Invalid_SubTable_Format);
  2781. }
  2782. ftl[n] = fr[fi[n]].FeatureTag;
  2783. }
  2784. ftl[n] = 0;
  2785. *feature_tag_list = ftl;
  2786. return HB_Err_Ok;
  2787. }
  2788. /* Do an individual subtable lookup. Returns HB_Err_Ok if substitution
  2789. has been done, or HB_Err_Not_Covered if not. */
  2790. static HB_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
  2791. HB_UShort lookup_index,
  2792. HB_Buffer buffer,
  2793. HB_UShort context_length,
  2794. int nesting_level )
  2795. {
  2796. HB_Error error = HB_Err_Not_Covered;
  2797. HB_UShort i, flags, lookup_count;
  2798. HB_Lookup* lo;
  2799. int lookup_type;
  2800. nesting_level++;
  2801. if ( nesting_level > HB_MAX_NESTING_LEVEL )
  2802. return ERR(HB_Err_Not_Covered); /* ERR() call intended */
  2803. lookup_count = gsub->LookupList.LookupCount;
  2804. if (lookup_index >= lookup_count)
  2805. return error;
  2806. lo = &gsub->LookupList.Lookup[lookup_index];
  2807. flags = lo->LookupFlag;
  2808. lookup_type = lo->LookupType;
  2809. for ( i = 0; i < lo->SubTableCount; i++ )
  2810. {
  2811. HB_GSUB_SubTable *st = &lo->SubTable[i].st.gsub;
  2812. switch (lookup_type) {
  2813. case HB_GSUB_LOOKUP_SINGLE:
  2814. error = Lookup_SingleSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;
  2815. case HB_GSUB_LOOKUP_MULTIPLE:
  2816. error = Lookup_MultipleSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;
  2817. case HB_GSUB_LOOKUP_ALTERNATE:
  2818. error = Lookup_AlternateSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;
  2819. case HB_GSUB_LOOKUP_LIGATURE:
  2820. error = Lookup_LigatureSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;
  2821. case HB_GSUB_LOOKUP_CONTEXT:
  2822. error = Lookup_ContextSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;
  2823. case HB_GSUB_LOOKUP_CHAIN:
  2824. error = Lookup_ChainContextSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;
  2825. /*case HB_GSUB_LOOKUP_EXTENSION:
  2826. error = Lookup_ExtensionSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;*/
  2827. case HB_GSUB_LOOKUP_REVERSE_CHAIN:
  2828. error = Lookup_ReverseChainContextSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;
  2829. default:
  2830. error = HB_Err_Not_Covered;
  2831. };
  2832. /* Check whether we have a successful substitution or an error other
  2833. than HB_Err_Not_Covered */
  2834. if ( error != HB_Err_Not_Covered )
  2835. return error;
  2836. }
  2837. return HB_Err_Not_Covered;
  2838. }
  2839. HB_INTERNAL HB_Error
  2840. _HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st,
  2841. HB_Stream stream,
  2842. HB_UShort lookup_type )
  2843. {
  2844. switch (lookup_type) {
  2845. case HB_GSUB_LOOKUP_SINGLE: return Load_SingleSubst ( st, stream );
  2846. case HB_GSUB_LOOKUP_MULTIPLE: return Load_MultipleSubst ( st, stream );
  2847. case HB_GSUB_LOOKUP_ALTERNATE: return Load_AlternateSubst ( st, stream );
  2848. case HB_GSUB_LOOKUP_LIGATURE: return Load_LigatureSubst ( st, stream );
  2849. case HB_GSUB_LOOKUP_CONTEXT: return Load_ContextSubst ( st, stream );
  2850. case HB_GSUB_LOOKUP_CHAIN: return Load_ChainContextSubst ( st, stream );
  2851. /*case HB_GSUB_LOOKUP_EXTENSION: return Load_ExtensionSubst ( st, stream );*/
  2852. case HB_GSUB_LOOKUP_REVERSE_CHAIN: return Load_ReverseChainContextSubst ( st, stream );
  2853. default: return ERR(HB_Err_Invalid_SubTable_Format);
  2854. };
  2855. }
  2856. HB_INTERNAL void
  2857. _HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,
  2858. HB_UShort lookup_type )
  2859. {
  2860. switch ( lookup_type ) {
  2861. case HB_GSUB_LOOKUP_SINGLE: Free_SingleSubst ( st ); return;
  2862. case HB_GSUB_LOOKUP_MULTIPLE: Free_MultipleSubst ( st ); return;
  2863. case HB_GSUB_LOOKUP_ALTERNATE: Free_AlternateSubst ( st ); return;
  2864. case HB_GSUB_LOOKUP_LIGATURE: Free_LigatureSubst ( st ); return;
  2865. case HB_GSUB_LOOKUP_CONTEXT: Free_ContextSubst ( st ); return;
  2866. case HB_GSUB_LOOKUP_CHAIN: Free_ChainContextSubst ( st ); return;
  2867. /*case HB_GSUB_LOOKUP_EXTENSION: Free_ExtensionSubst ( st ); return;*/
  2868. case HB_GSUB_LOOKUP_REVERSE_CHAIN: Free_ReverseChainContextSubst ( st ); return;
  2869. default: return;
  2870. };
  2871. }
  2872. /* apply one lookup to the input string object */
  2873. static HB_Error GSUB_Do_String_Lookup( HB_GSUBHeader* gsub,
  2874. HB_UShort lookup_index,
  2875. HB_Buffer buffer )
  2876. {
  2877. HB_Error error, retError = HB_Err_Not_Covered;
  2878. HB_UInt* properties = gsub->LookupList.Properties;
  2879. int lookup_type = gsub->LookupList.Lookup[lookup_index].LookupType;
  2880. const int nesting_level = 0;
  2881. /* 0xFFFF indicates that we don't have a context length yet */
  2882. const HB_UShort context_length = 0xFFFF;
  2883. switch (lookup_type) {
  2884. case HB_GSUB_LOOKUP_SINGLE:
  2885. case HB_GSUB_LOOKUP_MULTIPLE:
  2886. case HB_GSUB_LOOKUP_ALTERNATE:
  2887. case HB_GSUB_LOOKUP_LIGATURE:
  2888. case HB_GSUB_LOOKUP_CONTEXT:
  2889. case HB_GSUB_LOOKUP_CHAIN:
  2890. /* in/out forward substitution (implemented lazy) */
  2891. _hb_buffer_clear_output ( buffer );
  2892. buffer->in_pos = 0;
  2893. while ( buffer->in_pos < buffer->in_length )
  2894. {
  2895. if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
  2896. {
  2897. error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level );
  2898. if ( error )
  2899. {
  2900. if ( error != HB_Err_Not_Covered )
  2901. return error;
  2902. }
  2903. else
  2904. retError = error;
  2905. }
  2906. else
  2907. error = HB_Err_Not_Covered;
  2908. if ( error == HB_Err_Not_Covered )
  2909. if ( COPY_Glyph ( buffer ) )
  2910. return error;
  2911. }
  2912. /* we shouldn't swap if error occurred.
  2913. *
  2914. * also don't swap if nothing changed (ie HB_Err_Not_Covered).
  2915. * shouldn't matter in that case though.
  2916. */
  2917. if ( retError == HB_Err_Ok )
  2918. _hb_buffer_swap( buffer );
  2919. return retError;
  2920. case HB_GSUB_LOOKUP_REVERSE_CHAIN:
  2921. /* in-place backward substitution */
  2922. buffer->in_pos = buffer->in_length - 1;
  2923. do
  2924. {
  2925. if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
  2926. {
  2927. error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level );
  2928. if ( error )
  2929. {
  2930. if ( error != HB_Err_Not_Covered )
  2931. return error;
  2932. }
  2933. else
  2934. retError = error;
  2935. }
  2936. else
  2937. error = HB_Err_Not_Covered;
  2938. if ( error == HB_Err_Not_Covered )
  2939. buffer->in_pos--;
  2940. }
  2941. while ((HB_Int) buffer->in_pos >= 0);
  2942. return retError;
  2943. /*case HB_GSUB_LOOKUP_EXTENSION:*/
  2944. default:
  2945. return retError;
  2946. };
  2947. }
  2948. HB_Error HB_GSUB_Add_Feature( HB_GSUBHeader* gsub,
  2949. HB_UShort feature_index,
  2950. HB_UInt property )
  2951. {
  2952. HB_UShort i;
  2953. HB_Feature feature;
  2954. HB_UInt* properties;
  2955. HB_UShort* index;
  2956. HB_UShort lookup_count;
  2957. /* Each feature can only be added once */
  2958. if ( !gsub ||
  2959. feature_index >= gsub->FeatureList.FeatureCount ||
  2960. gsub->FeatureList.ApplyCount == gsub->FeatureList.FeatureCount )
  2961. return ERR(HB_Err_Invalid_Argument);
  2962. gsub->FeatureList.ApplyOrder[gsub->FeatureList.ApplyCount++] = feature_index;
  2963. properties = gsub->LookupList.Properties;
  2964. feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
  2965. index = feature.LookupListIndex;
  2966. lookup_count = gsub->LookupList.LookupCount;
  2967. for ( i = 0; i < feature.LookupListCount; i++ )
  2968. {
  2969. HB_UShort lookup_index = index[i];
  2970. if (lookup_index < lookup_count)
  2971. properties[lookup_index] |= property;
  2972. }
  2973. return HB_Err_Ok;
  2974. }
  2975. HB_Error HB_GSUB_Clear_Features( HB_GSUBHeader* gsub )
  2976. {
  2977. HB_UShort i;
  2978. HB_UInt* properties;
  2979. if ( !gsub )
  2980. return ERR(HB_Err_Invalid_Argument);
  2981. gsub->FeatureList.ApplyCount = 0;
  2982. properties = gsub->LookupList.Properties;
  2983. for ( i = 0; i < gsub->LookupList.LookupCount; i++ )
  2984. properties[i] = 0;
  2985. return HB_Err_Ok;
  2986. }
  2987. HB_Error HB_GSUB_Register_Alternate_Function( HB_GSUBHeader* gsub,
  2988. HB_AltFunction altfunc,
  2989. void* data )
  2990. {
  2991. if ( !gsub )
  2992. return ERR(HB_Err_Invalid_Argument);
  2993. gsub->altfunc = altfunc;
  2994. gsub->data = data;
  2995. return HB_Err_Ok;
  2996. }
  2997. /* returns error if one happened, otherwise returns HB_Err_Not_Covered if no
  2998. * feature were applied, or HB_Err_Ok otherwise.
  2999. */
  3000. HB_Error HB_GSUB_Apply_String( HB_GSUBHeader* gsub,
  3001. HB_Buffer buffer )
  3002. {
  3003. HB_Error error, retError = HB_Err_Not_Covered;
  3004. int i, j, lookup_count, num_features;
  3005. if ( !gsub ||
  3006. !buffer)
  3007. return ERR(HB_Err_Invalid_Argument);
  3008. if ( buffer->in_length == 0 )
  3009. return retError;
  3010. lookup_count = gsub->LookupList.LookupCount;
  3011. num_features = gsub->FeatureList.ApplyCount;
  3012. for ( i = 0; i < num_features; i++)
  3013. {
  3014. HB_UShort feature_index = gsub->FeatureList.ApplyOrder[i];
  3015. HB_Feature feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
  3016. for ( j = 0; j < feature.LookupListCount; j++ )
  3017. {
  3018. HB_UShort lookup_index = feature.LookupListIndex[j];
  3019. /* Skip nonexistant lookups */
  3020. if (lookup_index >= lookup_count)
  3021. continue;
  3022. error = GSUB_Do_String_Lookup( gsub, lookup_index, buffer );
  3023. if ( error )
  3024. {
  3025. if ( error != HB_Err_Not_Covered )
  3026. return error;
  3027. }
  3028. else
  3029. retError = error;
  3030. }
  3031. }
  3032. error = retError;
  3033. return error;
  3034. }
  3035. /* END */