PageRenderTime 64ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/libs/pango/src/pango/opentype/harfbuzz-gsub.c

http://jslibs.googlecode.com/
C | 3158 lines | 2060 code | 984 blank | 114 comment | 458 complexity | 4eb75e5f6b901456600e769bde467f36 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0, GPL-3.0, GPL-2.0, AGPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, LGPL-2.0
  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_Font font,
  41. HB_GSUBHeader** retptr,
  42. HB_GDEFHeader* gdef )
  43. {
  44. HB_Stream stream = font->stream;
  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, stream,
  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. HB_Bool* d;
  959. if ( ACCESS_Frame( 4L ) )
  960. return error;
  961. scr->GlyphCount = GET_UShort();
  962. scr->SubstCount = GET_UShort();
  963. if ( scr->GlyphCount > csf2->MaxContextLength )
  964. csf2->MaxContextLength = scr->GlyphCount;
  965. FORGET_Frame();
  966. scr->Class = NULL;
  967. count = scr->GlyphCount - 1; /* only GlyphCount - 1 elements */
  968. if ( ALLOC_ARRAY( scr->Class, count, HB_UShort ) )
  969. return error;
  970. c = scr->Class;
  971. d = csf2->ClassDef.Defined;
  972. if ( ACCESS_Frame( count * 2L ) )
  973. goto Fail2;
  974. for ( n = 0; n < count; n++ )
  975. {
  976. c[n] = GET_UShort();
  977. /* We check whether the specific class is used at all. If not,
  978. class 0 is used instead. */
  979. if ( !d[c[n]] )
  980. c[n] = 0;
  981. }
  982. FORGET_Frame();
  983. scr->SubstLookupRecord = NULL;
  984. count = scr->SubstCount;
  985. if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
  986. goto Fail2;
  987. slr = scr->SubstLookupRecord;
  988. if ( ACCESS_Frame( count * 4L ) )
  989. goto Fail1;
  990. for ( n = 0; n < count; n++ )
  991. {
  992. slr[n].SequenceIndex = GET_UShort();
  993. slr[n].LookupListIndex = GET_UShort();
  994. }
  995. FORGET_Frame();
  996. return HB_Err_Ok;
  997. Fail1:
  998. FREE( slr );
  999. Fail2:
  1000. FREE( c );
  1001. return error;
  1002. }
  1003. static void Free_SubClassRule( HB_SubClassRule* scr )
  1004. {
  1005. FREE( scr->SubstLookupRecord );
  1006. FREE( scr->Class );
  1007. }
  1008. /* SubClassSet */
  1009. static HB_Error Load_SubClassSet( HB_ContextSubstFormat2* csf2,
  1010. HB_SubClassSet* scs,
  1011. HB_Stream stream )
  1012. {
  1013. HB_Error error;
  1014. HB_UShort n = 0, m, count;
  1015. HB_UInt cur_offset, new_offset, base_offset;
  1016. HB_SubClassRule* scr;
  1017. base_offset = FILE_Pos();
  1018. if ( ACCESS_Frame( 2L ) )
  1019. return error;
  1020. count = scs->SubClassRuleCount = GET_UShort();
  1021. FORGET_Frame();
  1022. scs->SubClassRule = NULL;
  1023. if ( ALLOC_ARRAY( scs->SubClassRule, count, HB_SubClassRule ) )
  1024. return error;
  1025. scr = scs->SubClassRule;
  1026. for ( n = 0; n < count; n++ )
  1027. {
  1028. if ( ACCESS_Frame( 2L ) )
  1029. goto Fail;
  1030. new_offset = GET_UShort() + base_offset;
  1031. FORGET_Frame();
  1032. cur_offset = FILE_Pos();
  1033. if ( FILE_Seek( new_offset ) ||
  1034. ( error = Load_SubClassRule( csf2, &scr[n],
  1035. stream ) ) != HB_Err_Ok )
  1036. goto Fail;
  1037. (void)FILE_Seek( cur_offset );
  1038. }
  1039. return HB_Err_Ok;
  1040. Fail:
  1041. for ( m = 0; m < n; m++ )
  1042. Free_SubClassRule( &scr[m] );
  1043. FREE( scr );
  1044. return error;
  1045. }
  1046. static void Free_SubClassSet( HB_SubClassSet* scs )
  1047. {
  1048. HB_UShort n, count;
  1049. HB_SubClassRule* scr;
  1050. if ( scs->SubClassRule )
  1051. {
  1052. count = scs->SubClassRuleCount;
  1053. scr = scs->SubClassRule;
  1054. for ( n = 0; n < count; n++ )
  1055. Free_SubClassRule( &scr[n] );
  1056. FREE( scr );
  1057. }
  1058. }
  1059. /* ContextSubstFormat2 */
  1060. static HB_Error Load_ContextSubst2( HB_ContextSubstFormat2* csf2,
  1061. HB_Stream stream )
  1062. {
  1063. HB_Error error;
  1064. HB_UShort n = 0, m, count;
  1065. HB_UInt cur_offset, new_offset, base_offset;
  1066. HB_SubClassSet* scs;
  1067. base_offset = FILE_Pos() - 2;
  1068. if ( ACCESS_Frame( 2L ) )
  1069. return error;
  1070. new_offset = GET_UShort() + base_offset;
  1071. FORGET_Frame();
  1072. cur_offset = FILE_Pos();
  1073. if ( FILE_Seek( new_offset ) ||
  1074. ( error = _HB_OPEN_Load_Coverage( &csf2->Coverage, stream ) ) != HB_Err_Ok )
  1075. return error;
  1076. (void)FILE_Seek( cur_offset );
  1077. if ( ACCESS_Frame( 4L ) )
  1078. goto Fail3;
  1079. new_offset = GET_UShort() + base_offset;
  1080. /* `SubClassSetCount' is the upper limit for class values, thus we
  1081. read it now to make an additional safety check. */
  1082. count = csf2->SubClassSetCount = GET_UShort();
  1083. FORGET_Frame();
  1084. cur_offset = FILE_Pos();
  1085. if ( FILE_Seek( new_offset ) ||
  1086. ( error = _HB_OPEN_Load_ClassDefinition( &csf2->ClassDef, count,
  1087. stream ) ) != HB_Err_Ok )
  1088. goto Fail3;
  1089. (void)FILE_Seek( cur_offset );
  1090. csf2->SubClassSet = NULL;
  1091. csf2->MaxContextLength = 0;
  1092. if ( ALLOC_ARRAY( csf2->SubClassSet, count, HB_SubClassSet ) )
  1093. goto Fail2;
  1094. scs = csf2->SubClassSet;
  1095. for ( n = 0; n < count; n++ )
  1096. {
  1097. if ( ACCESS_Frame( 2L ) )
  1098. goto Fail1;
  1099. new_offset = GET_UShort() + base_offset;
  1100. FORGET_Frame();
  1101. if ( new_offset != base_offset ) /* not a NULL offset */
  1102. {
  1103. cur_offset = FILE_Pos();
  1104. if ( FILE_Seek( new_offset ) ||
  1105. ( error = Load_SubClassSet( csf2, &scs[n],
  1106. stream ) ) != HB_Err_Ok )
  1107. goto Fail1;
  1108. (void)FILE_Seek( cur_offset );
  1109. }
  1110. else
  1111. {
  1112. /* we create a SubClassSet table with no entries */
  1113. csf2->SubClassSet[n].SubClassRuleCount = 0;
  1114. csf2->SubClassSet[n].SubClassRule = NULL;
  1115. }
  1116. }
  1117. return HB_Err_Ok;
  1118. Fail1:
  1119. for ( m = 0; m < n; m++ )
  1120. Free_SubClassSet( &scs[m] );
  1121. FREE( scs );
  1122. Fail2:
  1123. _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef );
  1124. Fail3:
  1125. _HB_OPEN_Free_Coverage( &csf2->Coverage );
  1126. return error;
  1127. }
  1128. static void Free_ContextSubst2( HB_ContextSubstFormat2* csf2 )
  1129. {
  1130. HB_UShort n, count;
  1131. HB_SubClassSet* scs;
  1132. if ( csf2->SubClassSet )
  1133. {
  1134. count = csf2->SubClassSetCount;
  1135. scs = csf2->SubClassSet;
  1136. for ( n = 0; n < count; n++ )
  1137. Free_SubClassSet( &scs[n] );
  1138. FREE( scs );
  1139. }
  1140. _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef );
  1141. _HB_OPEN_Free_Coverage( &csf2->Coverage );
  1142. }
  1143. /* ContextSubstFormat3 */
  1144. static HB_Error Load_ContextSubst3( HB_ContextSubstFormat3* csf3,
  1145. HB_Stream stream )
  1146. {
  1147. HB_Error error;
  1148. HB_UShort n = 0, m, count;
  1149. HB_UInt cur_offset, new_offset, base_offset;
  1150. HB_Coverage* c;
  1151. HB_SubstLookupRecord* slr;
  1152. base_offset = FILE_Pos() - 2L;
  1153. if ( ACCESS_Frame( 4L ) )
  1154. return error;
  1155. csf3->GlyphCount = GET_UShort();
  1156. csf3->SubstCount = GET_UShort();
  1157. FORGET_Frame();
  1158. csf3->Coverage = NULL;
  1159. count = csf3->GlyphCount;
  1160. if ( ALLOC_ARRAY( csf3->Coverage, count, HB_Coverage ) )
  1161. return error;
  1162. c = csf3->Coverage;
  1163. for ( n = 0; n < count; n++ )
  1164. {
  1165. if ( ACCESS_Frame( 2L ) )
  1166. goto Fail2;
  1167. new_offset = GET_UShort() + base_offset;
  1168. FORGET_Frame();
  1169. cur_offset = FILE_Pos();
  1170. if ( FILE_Seek( new_offset ) ||
  1171. ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != HB_Err_Ok )
  1172. goto Fail2;
  1173. (void)FILE_Seek( cur_offset );
  1174. }
  1175. csf3->SubstLookupRecord = NULL;
  1176. count = csf3->SubstCount;
  1177. if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count,
  1178. HB_SubstLookupRecord ) )
  1179. goto Fail2;
  1180. slr = csf3->SubstLookupRecord;
  1181. if ( ACCESS_Frame( count * 4L ) )
  1182. goto Fail1;
  1183. for ( n = 0; n < count; n++ )
  1184. {
  1185. slr[n].SequenceIndex = GET_UShort();
  1186. slr[n].LookupListIndex = GET_UShort();
  1187. }
  1188. FORGET_Frame();
  1189. return HB_Err_Ok;
  1190. Fail1:
  1191. FREE( slr );
  1192. Fail2:
  1193. for ( m = 0; m < n; m++ )
  1194. _HB_OPEN_Free_Coverage( &c[m] );
  1195. FREE( c );
  1196. return error;
  1197. }
  1198. static void Free_ContextSubst3( HB_ContextSubstFormat3* csf3 )
  1199. {
  1200. HB_UShort n, count;
  1201. HB_Coverage* c;
  1202. FREE( csf3->SubstLookupRecord );
  1203. if ( csf3->Coverage )
  1204. {
  1205. count = csf3->GlyphCount;
  1206. c = csf3->Coverage;
  1207. for ( n = 0; n < count; n++ )
  1208. _HB_OPEN_Free_Coverage( &c[n] );
  1209. FREE( c );
  1210. }
  1211. }
  1212. /* ContextSubst */
  1213. static HB_Error Load_ContextSubst( HB_GSUB_SubTable* st,
  1214. HB_Stream stream )
  1215. {
  1216. HB_Error error;
  1217. HB_ContextSubst* cs = &st->context;
  1218. if ( ACCESS_Frame( 2L ) )
  1219. return error;
  1220. cs->SubstFormat = GET_UShort();
  1221. FORGET_Frame();
  1222. switch ( cs->SubstFormat )
  1223. {
  1224. case 1: return Load_ContextSubst1( &cs->csf.csf1, stream );
  1225. case 2: return Load_ContextSubst2( &cs->csf.csf2, stream );
  1226. case 3: return Load_ContextSubst3( &cs->csf.csf3, stream );
  1227. default: return ERR(HB_Err_Invalid_SubTable_Format);
  1228. }
  1229. return HB_Err_Ok; /* never reached */
  1230. }
  1231. static void Free_ContextSubst( HB_GSUB_SubTable* st )
  1232. {
  1233. HB_ContextSubst* cs = &st->context;
  1234. switch ( cs->SubstFormat )
  1235. {
  1236. case 1: Free_ContextSubst1( &cs->csf.csf1 ); break;
  1237. case 2: Free_ContextSubst2( &cs->csf.csf2 ); break;
  1238. case 3: Free_ContextSubst3( &cs->csf.csf3 ); break;
  1239. default: break;
  1240. }
  1241. }
  1242. static HB_Error Lookup_ContextSubst1( HB_GSUBHeader* gsub,
  1243. HB_ContextSubstFormat1* csf1,
  1244. HB_Buffer buffer,
  1245. HB_UShort flags,
  1246. HB_UShort context_length,
  1247. int nesting_level )
  1248. {
  1249. HB_UShort index, property;
  1250. HB_UShort i, j, k, numsr;
  1251. HB_Error error;
  1252. HB_SubRule* sr;
  1253. HB_GDEFHeader* gdef;
  1254. gdef = gsub->gdef;
  1255. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  1256. return error;
  1257. error = _HB_OPEN_Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index );
  1258. if ( error )
  1259. return error;
  1260. sr = csf1->SubRuleSet[index].SubRule;
  1261. numsr = csf1->SubRuleSet[index].SubRuleCount;
  1262. for ( k = 0; k < numsr; k++ )
  1263. {
  1264. if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )
  1265. goto next_subrule;
  1266. if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length )
  1267. goto next_subrule; /* context is too long */
  1268. for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ )
  1269. {
  1270. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  1271. {
  1272. if ( error && error != HB_Err_Not_Covered )
  1273. return error;
  1274. if ( j + sr[k].GlyphCount - i == (HB_Int)buffer->in_length )
  1275. goto next_subrule;
  1276. j++;
  1277. }
  1278. if ( IN_GLYPH( j ) != sr[k].Input[i - 1] )
  1279. goto next_subrule;
  1280. }
  1281. return Do_ContextSubst( gsub, sr[k].GlyphCount,
  1282. sr[k].SubstCount, sr[k].SubstLookupRecord,
  1283. buffer,
  1284. nesting_level );
  1285. next_subrule:
  1286. ;
  1287. }
  1288. return HB_Err_Not_Covered;
  1289. }
  1290. static HB_Error Lookup_ContextSubst2( HB_GSUBHeader* gsub,
  1291. HB_ContextSubstFormat2* csf2,
  1292. HB_Buffer buffer,
  1293. HB_UShort flags,
  1294. HB_UShort context_length,
  1295. int nesting_level )
  1296. {
  1297. HB_UShort index, property;
  1298. HB_Error error;
  1299. HB_UShort i, j, k, known_classes;
  1300. HB_UShort* classes;
  1301. HB_UShort* cl;
  1302. HB_SubClassSet* scs;
  1303. HB_SubClassRule* sr;
  1304. HB_GDEFHeader* gdef;
  1305. gdef = gsub->gdef;
  1306. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  1307. return error;
  1308. /* Note: The coverage table in format 2 doesn't give an index into
  1309. anything. It just lets us know whether or not we need to
  1310. do any lookup at all. */
  1311. error = _HB_OPEN_Coverage_Index( &csf2->Coverage, IN_CURGLYPH(), &index );
  1312. if ( error )
  1313. return error;
  1314. if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, HB_UShort ) )
  1315. return error;
  1316. error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_CURGLYPH(),
  1317. &classes[0], NULL );
  1318. if ( error && error != HB_Err_Not_Covered )
  1319. goto End;
  1320. known_classes = 0;
  1321. scs = &csf2->SubClassSet[classes[0]];
  1322. if ( !scs )
  1323. {
  1324. error = ERR(HB_Err_Invalid_SubTable);
  1325. goto End;
  1326. }
  1327. for ( k = 0; k < scs->SubClassRuleCount; k++ )
  1328. {
  1329. sr = &scs->SubClassRule[k];
  1330. if ( context_length != 0xFFFF && context_length < sr->GlyphCount )
  1331. goto next_subclassrule;
  1332. if ( buffer->in_pos + sr->GlyphCount > buffer->in_length )
  1333. goto next_subclassrule; /* context is too long */
  1334. cl = sr->Class;
  1335. /* Start at 1 because [0] is implied */
  1336. for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ )
  1337. {
  1338. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  1339. {
  1340. if ( error && error != HB_Err_Not_Covered )
  1341. goto End;
  1342. if ( j + sr->GlyphCount - i < (HB_Int)buffer->in_length )
  1343. goto next_subclassrule;
  1344. j++;
  1345. }
  1346. if ( i > known_classes )
  1347. {
  1348. /* Keeps us from having to do this for each rule */
  1349. error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
  1350. if ( error && error != HB_Err_Not_Covered )
  1351. goto End;
  1352. known_classes = i;
  1353. }
  1354. if ( cl[i - 1] != classes[i] )
  1355. goto next_subclassrule;
  1356. }
  1357. error = Do_ContextSubst( gsub, sr->GlyphCount,
  1358. sr->SubstCount, sr->SubstLookupRecord,
  1359. buffer,
  1360. nesting_level );
  1361. goto End;
  1362. next_subclassrule:
  1363. ;
  1364. }
  1365. error = HB_Err_Not_Covered;
  1366. End:
  1367. FREE( classes );
  1368. return error;
  1369. }
  1370. static HB_Error Lookup_ContextSubst3( HB_GSUBHeader* gsub,
  1371. HB_ContextSubstFormat3* csf3,
  1372. HB_Buffer buffer,
  1373. HB_UShort flags,
  1374. HB_UShort context_length,
  1375. int nesting_level )
  1376. {
  1377. HB_Error error;
  1378. HB_UShort index, i, j, property;
  1379. HB_Coverage* c;
  1380. HB_GDEFHeader* gdef;
  1381. gdef = gsub->gdef;
  1382. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  1383. return error;
  1384. if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )
  1385. return HB_Err_Not_Covered;
  1386. if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length )
  1387. return HB_Err_Not_Covered; /* context is too long */
  1388. c = csf3->Coverage;
  1389. for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ )
  1390. {
  1391. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  1392. {
  1393. if ( error && error != HB_Err_Not_Covered )
  1394. return error;
  1395. if ( j + csf3->GlyphCount - i == (HB_Int)buffer->in_length )
  1396. return HB_Err_Not_Covered;
  1397. j++;
  1398. }
  1399. error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );
  1400. if ( error )
  1401. return error;
  1402. }
  1403. return Do_ContextSubst( gsub, csf3->GlyphCount,
  1404. csf3->SubstCount, csf3->SubstLookupRecord,
  1405. buffer,
  1406. nesting_level );
  1407. }
  1408. static HB_Error Lookup_ContextSubst( HB_GSUBHeader* gsub,
  1409. HB_GSUB_SubTable* st,
  1410. HB_Buffer buffer,
  1411. HB_UShort flags,
  1412. HB_UShort context_length,
  1413. int nesting_level )
  1414. {
  1415. HB_ContextSubst* cs = &st->context;
  1416. switch ( cs->SubstFormat )
  1417. {
  1418. case 1: return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer, flags, context_length, nesting_level );
  1419. case 2: return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer, flags, context_length, nesting_level );
  1420. case 3: return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer, flags, context_length, nesting_level );
  1421. default: return ERR(HB_Err_Invalid_SubTable_Format);
  1422. }
  1423. return HB_Err_Ok; /* never reached */
  1424. }
  1425. /* LookupType 6 */
  1426. /* ChainSubRule */
  1427. static HB_Error Load_ChainSubRule( HB_ChainSubRule* csr,
  1428. HB_Stream stream )
  1429. {
  1430. HB_Error error;
  1431. HB_UShort n, count;
  1432. HB_UShort* b;
  1433. HB_UShort* i;
  1434. HB_UShort* l;
  1435. HB_SubstLookupRecord* slr;
  1436. if ( ACCESS_Frame( 2L ) )
  1437. return error;
  1438. csr->BacktrackGlyphCount = GET_UShort();
  1439. FORGET_Frame();
  1440. csr->Backtrack = NULL;
  1441. count = csr->BacktrackGlyphCount;
  1442. if ( ALLOC_ARRAY( csr->Backtrack, count, HB_UShort ) )
  1443. return error;
  1444. b = csr->Backtrack;
  1445. if ( ACCESS_Frame( count * 2L ) )
  1446. goto Fail4;
  1447. for ( n = 0; n < count; n++ )
  1448. b[n] = GET_UShort();
  1449. FORGET_Frame();
  1450. if ( ACCESS_Frame( 2L ) )
  1451. goto Fail4;
  1452. csr->InputGlyphCount = GET_UShort();
  1453. FORGET_Frame();
  1454. csr->Input = NULL;
  1455. count = csr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
  1456. if ( ALLOC_ARRAY( csr->Input, count, HB_UShort ) )
  1457. goto Fail4;
  1458. i = csr->Input;
  1459. if ( ACCESS_Frame( count * 2L ) )
  1460. goto Fail3;
  1461. for ( n = 0; n < count; n++ )
  1462. i[n] = GET_UShort();
  1463. FORGET_Frame();
  1464. if ( ACCESS_Frame( 2L ) )
  1465. goto Fail3;
  1466. csr->LookaheadGlyphCount = GET_UShort();
  1467. FORGET_Frame();
  1468. csr->Lookahead = NULL;
  1469. count = csr->LookaheadGlyphCount;
  1470. if ( ALLOC_ARRAY( csr->Lookahead, count, HB_UShort ) )
  1471. goto Fail3;
  1472. l = csr->Lookahead;
  1473. if ( ACCESS_Frame( count * 2L ) )
  1474. goto Fail2;
  1475. for ( n = 0; n < count; n++ )
  1476. l[n] = GET_UShort();
  1477. FORGET_Frame();
  1478. if ( ACCESS_Frame( 2L ) )
  1479. goto Fail2;
  1480. csr->SubstCount = GET_UShort();
  1481. FORGET_Frame();
  1482. csr->SubstLookupRecord = NULL;
  1483. count = csr->SubstCount;
  1484. if ( ALLOC_ARRAY( csr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
  1485. goto Fail2;
  1486. slr = csr->SubstLookupRecord;
  1487. if ( ACCESS_Frame( count * 4L ) )
  1488. goto Fail1;
  1489. for ( n = 0; n < count; n++ )
  1490. {
  1491. slr[n].SequenceIndex = GET_UShort();
  1492. slr[n].LookupListIndex = GET_UShort();
  1493. }
  1494. FORGET_Frame();
  1495. return HB_Err_Ok;
  1496. Fail1:
  1497. FREE( slr );
  1498. Fail2:
  1499. FREE( l );
  1500. Fail3:
  1501. FREE( i );
  1502. Fail4:
  1503. FREE( b );
  1504. return error;
  1505. }
  1506. static void Free_ChainSubRule( HB_ChainSubRule* csr )
  1507. {
  1508. FREE( csr->SubstLookupRecord );
  1509. FREE( csr->Lookahead );
  1510. FREE( csr->Input );
  1511. FREE( csr->Backtrack );
  1512. }
  1513. /* ChainSubRuleSet */
  1514. static HB_Error Load_ChainSubRuleSet( HB_ChainSubRuleSet* csrs,
  1515. HB_Stream stream )
  1516. {
  1517. HB_Error error;
  1518. HB_UShort n = 0, m, count;
  1519. HB_UInt cur_offset, new_offset, base_offset;
  1520. HB_ChainSubRule* csr;
  1521. base_offset = FILE_Pos();
  1522. if ( ACCESS_Frame( 2L ) )
  1523. return error;
  1524. count = csrs->ChainSubRuleCount = GET_UShort();
  1525. FORGET_Frame();
  1526. csrs->ChainSubRule = NULL;
  1527. if ( ALLOC_ARRAY( csrs->ChainSubRule, count, HB_ChainSubRule ) )
  1528. return error;
  1529. csr = csrs->ChainSubRule;
  1530. for ( n = 0; n < count; n++ )
  1531. {
  1532. if ( ACCESS_Frame( 2L ) )
  1533. goto Fail;
  1534. new_offset = GET_UShort() + base_offset;
  1535. FORGET_Frame();
  1536. cur_offset = FILE_Pos();
  1537. if ( FILE_Seek( new_offset ) ||
  1538. ( error = Load_ChainSubRule( &csr[n], stream ) ) != HB_Err_Ok )
  1539. goto Fail;
  1540. (void)FILE_Seek( cur_offset );
  1541. }
  1542. return HB_Err_Ok;
  1543. Fail:
  1544. for ( m = 0; m < n; m++ )
  1545. Free_ChainSubRule( &csr[m] );
  1546. FREE( csr );
  1547. return error;
  1548. }
  1549. static void Free_ChainSubRuleSet( HB_ChainSubRuleSet* csrs )
  1550. {
  1551. HB_UShort n, count;
  1552. HB_ChainSubRule* csr;
  1553. if ( csrs->ChainSubRule )
  1554. {
  1555. count = csrs->ChainSubRuleCount;
  1556. csr = csrs->ChainSubRule;
  1557. for ( n = 0; n < count; n++ )
  1558. Free_ChainSubRule( &csr[n] );
  1559. FREE( csr );
  1560. }
  1561. }
  1562. /* ChainContextSubstFormat1 */
  1563. static HB_Error Load_ChainContextSubst1(
  1564. HB_ChainContextSubstFormat1* ccsf1,
  1565. HB_Stream stream )
  1566. {
  1567. HB_Error error;
  1568. HB_UShort n = 0, m, count;
  1569. HB_UInt cur_offset, new_offset, base_offset;
  1570. HB_ChainSubRuleSet* csrs;
  1571. base_offset = FILE_Pos() - 2L;
  1572. if ( ACCESS_Frame( 2L ) )
  1573. return error;
  1574. new_offset = GET_UShort() + base_offset;
  1575. FORGET_Frame();
  1576. cur_offset = FILE_Pos();
  1577. if ( FILE_Seek( new_offset ) ||
  1578. ( error = _HB_OPEN_Load_Coverage( &ccsf1->Coverage, stream ) ) != HB_Err_Ok )
  1579. return error;
  1580. (void)FILE_Seek( cur_offset );
  1581. if ( ACCESS_Frame( 2L ) )
  1582. goto Fail2;
  1583. count = ccsf1->ChainSubRuleSetCount = GET_UShort();
  1584. FORGET_Frame();
  1585. ccsf1->ChainSubRuleSet = NULL;
  1586. if ( ALLOC_ARRAY( ccsf1->ChainSubRuleSet, count, HB_ChainSubRuleSet ) )
  1587. goto Fail2;
  1588. csrs = ccsf1->ChainSubRuleSet;
  1589. for ( n = 0; n < count; n++ )
  1590. {
  1591. if ( ACCESS_Frame( 2L ) )
  1592. goto Fail1;
  1593. new_offset = GET_UShort() + base_offset;
  1594. FORGET_Frame();
  1595. cur_offset = FILE_Pos();
  1596. if ( FILE_Seek( new_offset ) ||
  1597. ( error = Load_ChainSubRuleSet( &csrs[n], stream ) ) != HB_Err_Ok )
  1598. goto Fail1;
  1599. (void)FILE_Seek( cur_offset );
  1600. }
  1601. return HB_Err_Ok;
  1602. Fail1:
  1603. for ( m = 0; m < n; m++ )
  1604. Free_ChainSubRuleSet( &csrs[m] );
  1605. FREE( csrs );
  1606. Fail2:
  1607. _HB_OPEN_Free_Coverage( &ccsf1->Coverage );
  1608. return error;
  1609. }
  1610. static void Free_ChainContextSubst1( HB_ChainContextSubstFormat1* ccsf1 )
  1611. {
  1612. HB_UShort n, count;
  1613. HB_ChainSubRuleSet* csrs;
  1614. if ( ccsf1->ChainSubRuleSet )
  1615. {
  1616. count = ccsf1->ChainSubRuleSetCount;
  1617. csrs = ccsf1->ChainSubRuleSet;
  1618. for ( n = 0; n < count; n++ )
  1619. Free_ChainSubRuleSet( &csrs[n] );
  1620. FREE( csrs );
  1621. }
  1622. _HB_OPEN_Free_Coverage( &ccsf1->Coverage );
  1623. }
  1624. /* ChainSubClassRule */
  1625. static HB_Error Load_ChainSubClassRule(
  1626. HB_ChainContextSubstFormat2* ccsf2,
  1627. HB_ChainSubClassRule* cscr,
  1628. HB_Stream stream )
  1629. {
  1630. HB_Error error;
  1631. HB_UShort n, count;
  1632. HB_UShort* b;
  1633. HB_UShort* i;
  1634. HB_UShort* l;
  1635. HB_SubstLookupRecord* slr;
  1636. HB_Bool* d;
  1637. if ( ACCESS_Frame( 2L ) )
  1638. return error;
  1639. cscr->BacktrackGlyphCount = GET_UShort();
  1640. FORGET_Frame();
  1641. if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength )
  1642. ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount;
  1643. cscr->Backtrack = NULL;
  1644. count = cscr->BacktrackGlyphCount;
  1645. if ( ALLOC_ARRAY( cscr->Backtrack, count, HB_UShort ) )
  1646. return error;
  1647. b = cscr->Backtrack;
  1648. d = ccsf2->BacktrackClassDef.Defined;
  1649. if ( ACCESS_Frame( count * 2L ) )
  1650. goto Fail4;
  1651. for ( n = 0; n < count; n++ )
  1652. {
  1653. b[n] = GET_UShort();
  1654. /* We check whether the specific class is used at all. If not,
  1655. class 0 is used instead. */
  1656. if ( !d[b[n]] )
  1657. b[n] = 0;
  1658. }
  1659. FORGET_Frame();
  1660. if ( ACCESS_Frame( 2L ) )
  1661. goto Fail4;
  1662. cscr->InputGlyphCount = GET_UShort();
  1663. FORGET_Frame();
  1664. if ( cscr->InputGlyphCount > ccsf2->MaxInputLength )
  1665. ccsf2->MaxInputLength = cscr->InputGlyphCount;
  1666. cscr->Input = NULL;
  1667. count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
  1668. if ( ALLOC_ARRAY( cscr->Input, count, HB_UShort ) )
  1669. goto Fail4;
  1670. i = cscr->Input;
  1671. d = ccsf2->InputClassDef.Defined;
  1672. if ( ACCESS_Frame( count * 2L ) )
  1673. goto Fail3;
  1674. for ( n = 0; n < count; n++ )
  1675. {
  1676. i[n] = GET_UShort();
  1677. if ( !d[i[n]] )
  1678. i[n] = 0;
  1679. }
  1680. FORGET_Frame();
  1681. if ( ACCESS_Frame( 2L ) )
  1682. goto Fail3;
  1683. cscr->LookaheadGlyphCount = GET_UShort();
  1684. FORGET_Frame();
  1685. if ( cscr->LookaheadGlyphCount > ccsf2->MaxLookaheadLength )
  1686. ccsf2->MaxLookaheadLength = cscr->LookaheadGlyphCount;
  1687. cscr->Lookahead = NULL;
  1688. count = cscr->LookaheadGlyphCount;
  1689. if ( ALLOC_ARRAY( cscr->Lookahead, count, HB_UShort ) )
  1690. goto Fail3;
  1691. l = cscr->Lookahead;
  1692. d = ccsf2->LookaheadClassDef.Defined;
  1693. if ( ACCESS_Frame( count * 2L ) )
  1694. goto Fail2;
  1695. for ( n = 0; n < count; n++ )
  1696. {
  1697. l[n] = GET_UShort();
  1698. if ( !d[l[n]] )
  1699. l[n] = 0;
  1700. }
  1701. FORGET_Frame();
  1702. if ( ACCESS_Frame( 2L ) )
  1703. goto Fail2;
  1704. cscr->SubstCount = GET_UShort();
  1705. FORGET_Frame();
  1706. cscr->SubstLookupRecord = NULL;
  1707. count = cscr->SubstCount;
  1708. if ( ALLOC_ARRAY( cscr->SubstLookupRecord, count,
  1709. HB_SubstLookupRecord ) )
  1710. goto Fail2;
  1711. slr = cscr->SubstLookupRecord;
  1712. if ( ACCESS_Frame( count * 4L ) )
  1713. goto Fail1;
  1714. for ( n = 0; n < count; n++ )
  1715. {
  1716. slr[n].SequenceIndex = GET_UShort();
  1717. slr[n].LookupListIndex = GET_UShort();
  1718. }
  1719. FORGET_Frame();
  1720. return HB_Err_Ok;
  1721. Fail1:
  1722. FREE( slr );
  1723. Fail2:
  1724. FREE( l );
  1725. Fail3:
  1726. FREE( i );
  1727. Fail4:
  1728. FREE( b );
  1729. return error;
  1730. }
  1731. static void Free_ChainSubClassRule( HB_ChainSubClassRule* cscr )
  1732. {
  1733. FREE( cscr->SubstLookupRecord );
  1734. FREE( cscr->Lookahead );
  1735. FREE( cscr->Input );
  1736. FREE( cscr->Backtrack );
  1737. }
  1738. /* SubClassSet */
  1739. static HB_Error Load_ChainSubClassSet(
  1740. HB_ChainContextSubstFormat2* ccsf2,
  1741. HB_ChainSubClassSet* cscs,
  1742. HB_Stream stream )
  1743. {
  1744. HB_Error error;
  1745. HB_UShort n = 0, m, count;
  1746. HB_UInt cur_offset, new_offset, base_offset;
  1747. HB_ChainSubClassRule* cscr;
  1748. base_offset = FILE_Pos();
  1749. if ( ACCESS_Frame( 2L ) )
  1750. return error;
  1751. count = cscs->ChainSubClassRuleCount = GET_UShort();
  1752. FORGET_Frame();
  1753. cscs->ChainSubClassRule = NULL;
  1754. if ( ALLOC_ARRAY( cscs->ChainSubClassRule, count,
  1755. HB_ChainSubClassRule ) )
  1756. return error;
  1757. cscr = cscs->ChainSubClassRule;
  1758. for ( n = 0; n < count; n++ )
  1759. {
  1760. if ( ACCESS_Frame( 2L ) )
  1761. goto Fail;
  1762. new_offset = GET_UShort() + base_offset;
  1763. FORGET_Frame();
  1764. cur_offset = FILE_Pos();
  1765. if ( FILE_Seek( new_offset ) ||
  1766. ( error = Load_ChainSubClassRule( ccsf2, &cscr[n],
  1767. stream ) ) != HB_Err_Ok )
  1768. goto Fail;
  1769. (void)FILE_Seek( cur_offset );
  1770. }
  1771. return HB_Err_Ok;
  1772. Fail:
  1773. for ( m = 0; m < n; m++ )
  1774. Free_ChainSubClassRule( &cscr[m] );
  1775. FREE( cscr );
  1776. return error;
  1777. }
  1778. static void Free_ChainSubClassSet( HB_ChainSubClassSet* cscs )
  1779. {
  1780. HB_UShort n, count;
  1781. HB_ChainSubClassRule* cscr;
  1782. if ( cscs->ChainSubClassRule )
  1783. {
  1784. count = cscs->ChainSubClassRuleCount;
  1785. cscr = cscs->ChainSubClassRule;
  1786. for ( n = 0; n < count; n++ )
  1787. Free_ChainSubClassRule( &cscr[n] );
  1788. FREE( cscr );
  1789. }
  1790. }
  1791. /* ChainContextSubstFormat2 */
  1792. static HB_Error Load_ChainContextSubst2(
  1793. HB_ChainContextSubstFormat2* ccsf2,
  1794. HB_Stream stream )
  1795. {
  1796. HB_Error error;
  1797. HB_UShort n = 0, m, count;
  1798. HB_UInt cur_offset, new_offset, base_offset;
  1799. HB_UInt backtrack_offset, input_offset, lookahead_offset;
  1800. HB_ChainSubClassSet* cscs;
  1801. base_offset = FILE_Pos() - 2;
  1802. if ( ACCESS_Frame( 2L ) )
  1803. return error;
  1804. new_offset = GET_UShort() + base_offset;
  1805. FORGET_Frame();
  1806. cur_offset = FILE_Pos();
  1807. if ( FILE_Seek( new_offset ) ||
  1808. ( error = _HB_OPEN_Load_Coverage( &ccsf2->Coverage, stream ) ) != HB_Err_Ok )
  1809. return error;
  1810. (void)FILE_Seek( cur_offset );
  1811. if ( ACCESS_Frame( 8L ) )
  1812. goto Fail5;
  1813. backtrack_offset = GET_UShort();
  1814. input_offset = GET_UShort();
  1815. lookahead_offset = GET_UShort();
  1816. /* `ChainSubClassSetCount' is the upper limit for input class values,
  1817. thus we read it now to make an additional safety check. No limit
  1818. is known or needed for the other two class definitions */
  1819. count = ccsf2->ChainSubClassSetCount = GET_UShort();
  1820. FORGET_Frame();
  1821. if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535,
  1822. backtrack_offset, base_offset,
  1823. stream ) ) != HB_Err_Ok )
  1824. goto Fail5;
  1825. if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count,
  1826. input_offset, base_offset,
  1827. stream ) ) != HB_Err_Ok )
  1828. goto Fail4;
  1829. if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535,
  1830. lookahead_offset, base_offset,
  1831. stream ) ) != HB_Err_Ok )
  1832. goto Fail3;
  1833. ccsf2->ChainSubClassSet = NULL;
  1834. ccsf2->MaxBacktrackLength = 0;
  1835. ccsf2->MaxInputLength = 0;
  1836. ccsf2->MaxLookaheadLength = 0;
  1837. if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, HB_ChainSubClassSet ) )
  1838. goto Fail2;
  1839. cscs = ccsf2->ChainSubClassSet;
  1840. for ( n = 0; n < count; n++ )
  1841. {
  1842. if ( ACCESS_Frame( 2L ) )
  1843. goto Fail1;
  1844. new_offset = GET_UShort() + base_offset;
  1845. FORGET_Frame();
  1846. if ( new_offset != base_offset ) /* not a NULL offset */
  1847. {
  1848. cur_offset = FILE_Pos();
  1849. if ( FILE_Seek( new_offset ) ||
  1850. ( error = Load_ChainSubClassSet( ccsf2, &cscs[n],
  1851. stream ) ) != HB_Err_Ok )
  1852. goto Fail1;
  1853. (void)FILE_Seek( cur_offset );
  1854. }
  1855. else
  1856. {
  1857. /* we create a ChainSubClassSet table with no entries */
  1858. ccsf2->ChainSubClassSet[n].ChainSubClassRuleCount = 0;
  1859. ccsf2->ChainSubClassSet[n].ChainSubClassRule = NULL;
  1860. }
  1861. }
  1862. return HB_Err_Ok;
  1863. Fail1:
  1864. for ( m = 0; m < n; m++ )
  1865. Free_ChainSubClassSet( &cscs[m] );
  1866. FREE( cscs );
  1867. Fail2:
  1868. _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef );
  1869. Fail3:
  1870. _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef );
  1871. Fail4:
  1872. _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef );
  1873. Fail5:
  1874. _HB_OPEN_Free_Coverage( &ccsf2->Coverage );
  1875. return error;
  1876. }
  1877. static void Free_ChainContextSubst2( HB_ChainContextSubstFormat2* ccsf2 )
  1878. {
  1879. HB_UShort n, count;
  1880. HB_ChainSubClassSet* cscs;
  1881. if ( ccsf2->ChainSubClassSet )
  1882. {
  1883. count = ccsf2->ChainSubClassSetCount;
  1884. cscs = ccsf2->ChainSubClassSet;
  1885. for ( n = 0; n < count; n++ )
  1886. Free_ChainSubClassSet( &cscs[n] );
  1887. FREE( cscs );
  1888. }
  1889. _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef );
  1890. _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef );
  1891. _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef );
  1892. _HB_OPEN_Free_Coverage( &ccsf2->Coverage );
  1893. }
  1894. /* ChainContextSubstFormat3 */
  1895. static HB_Error Load_ChainContextSubst3(
  1896. HB_ChainContextSubstFormat3* ccsf3,
  1897. HB_Stream stream )
  1898. {
  1899. HB_Error error;
  1900. HB_UShort n, nb = 0, ni =0, nl = 0, m, count;
  1901. HB_UShort backtrack_count, input_count, lookahead_count;
  1902. HB_UInt cur_offset, new_offset, base_offset;
  1903. HB_Coverage* b;
  1904. HB_Coverage* i;
  1905. HB_Coverage* l;
  1906. HB_SubstLookupRecord* slr;
  1907. base_offset = FILE_Pos() - 2L;
  1908. if ( ACCESS_Frame( 2L ) )
  1909. return error;
  1910. ccsf3->BacktrackGlyphCount = GET_UShort();
  1911. FORGET_Frame();
  1912. ccsf3->BacktrackCoverage = NULL;
  1913. backtrack_count = ccsf3->BacktrackGlyphCount;
  1914. if ( ALLOC_ARRAY( ccsf3->BacktrackCoverage, backtrack_count,
  1915. HB_Coverage ) )
  1916. return error;
  1917. b = ccsf3->BacktrackCoverage;
  1918. for ( nb = 0; nb < backtrack_count; nb++ )
  1919. {
  1920. if ( ACCESS_Frame( 2L ) )
  1921. goto Fail4;
  1922. new_offset = GET_UShort() + base_offset;
  1923. FORGET_Frame();
  1924. cur_offset = FILE_Pos();
  1925. if ( FILE_Seek( new_offset ) ||
  1926. ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok )
  1927. goto Fail4;
  1928. (void)FILE_Seek( cur_offset );
  1929. }
  1930. if ( ACCESS_Frame( 2L ) )
  1931. goto Fail4;
  1932. ccsf3->InputGlyphCount = GET_UShort();
  1933. FORGET_Frame();
  1934. ccsf3->InputCoverage = NULL;
  1935. input_count = ccsf3->InputGlyphCount;
  1936. if ( ALLOC_ARRAY( ccsf3->InputCoverage, input_count, HB_Coverage ) )
  1937. goto Fail4;
  1938. i = ccsf3->InputCoverage;
  1939. for ( ni = 0; ni < input_count; ni++ )
  1940. {
  1941. if ( ACCESS_Frame( 2L ) )
  1942. goto Fail3;
  1943. new_offset = GET_UShort() + base_offset;
  1944. FORGET_Frame();
  1945. cur_offset = FILE_Pos();
  1946. if ( FILE_Seek( new_offset ) ||
  1947. ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_Err_Ok )
  1948. goto Fail3;
  1949. (void)FILE_Seek( cur_offset );
  1950. }
  1951. if ( ACCESS_Frame( 2L ) )
  1952. goto Fail3;
  1953. ccsf3->LookaheadGlyphCount = GET_UShort();
  1954. FORGET_Frame();
  1955. ccsf3->LookaheadCoverage = NULL;
  1956. lookahead_count = ccsf3->LookaheadGlyphCount;
  1957. if ( ALLOC_ARRAY( ccsf3->LookaheadCoverage, lookahead_count,
  1958. HB_Coverage ) )
  1959. goto Fail3;
  1960. l = ccsf3->LookaheadCoverage;
  1961. for ( nl = 0; nl < lookahead_count; nl++ )
  1962. {
  1963. if ( ACCESS_Frame( 2L ) )
  1964. goto Fail2;
  1965. new_offset = GET_UShort() + base_offset;
  1966. FORGET_Frame();
  1967. cur_offset = FILE_Pos();
  1968. if ( FILE_Seek( new_offset ) ||
  1969. ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok )
  1970. goto Fail2;
  1971. (void)FILE_Seek( cur_offset );
  1972. }
  1973. if ( ACCESS_Frame( 2L ) )
  1974. goto Fail2;
  1975. ccsf3->SubstCount = GET_UShort();
  1976. FORGET_Frame();
  1977. ccsf3->SubstLookupRecord = NULL;
  1978. count = ccsf3->SubstCount;
  1979. if ( ALLOC_ARRAY( ccsf3->SubstLookupRecord, count,
  1980. HB_SubstLookupRecord ) )
  1981. goto Fail2;
  1982. slr = ccsf3->SubstLookupRecord;
  1983. if ( ACCESS_Frame( count * 4L ) )
  1984. goto Fail1;
  1985. for ( n = 0; n < count; n++ )
  1986. {
  1987. slr[n].SequenceIndex = GET_UShort();
  1988. slr[n].LookupListIndex = GET_UShort();
  1989. }
  1990. FORGET_Frame();
  1991. return HB_Err_Ok;
  1992. Fail1:
  1993. FREE( slr );
  1994. Fail2:
  1995. for ( m = 0; m < nl; m++ )
  1996. _HB_OPEN_Free_Coverage( &l[m] );
  1997. FREE( l );
  1998. Fail3:
  1999. for ( m = 0; m < ni; m++ )
  2000. _HB_OPEN_Free_Coverage( &i[m] );
  2001. FREE( i );
  2002. Fail4:
  2003. for ( m = 0; m < nb; m++ )
  2004. _HB_OPEN_Free_Coverage( &b[m] );
  2005. FREE( b );
  2006. return error;
  2007. }
  2008. static void Free_ChainContextSubst3( HB_ChainContextSubstFormat3* ccsf3 )
  2009. {
  2010. HB_UShort n, count;
  2011. HB_Coverage* c;
  2012. FREE( ccsf3->SubstLookupRecord );
  2013. if ( ccsf3->LookaheadCoverage )
  2014. {
  2015. count = ccsf3->LookaheadGlyphCount;
  2016. c = ccsf3->LookaheadCoverage;
  2017. for ( n = 0; n < count; n++ )
  2018. _HB_OPEN_Free_Coverage( &c[n] );
  2019. FREE( c );
  2020. }
  2021. if ( ccsf3->InputCoverage )
  2022. {
  2023. count = ccsf3->InputGlyphCount;
  2024. c = ccsf3->InputCoverage;
  2025. for ( n = 0; n < count; n++ )
  2026. _HB_OPEN_Free_Coverage( &c[n] );
  2027. FREE( c );
  2028. }
  2029. if ( ccsf3->BacktrackCoverage )
  2030. {
  2031. count = ccsf3->BacktrackGlyphCount;
  2032. c = ccsf3->BacktrackCoverage;
  2033. for ( n = 0; n < count; n++ )
  2034. _HB_OPEN_Free_Coverage( &c[n] );
  2035. FREE( c );
  2036. }
  2037. }
  2038. /* ChainContextSubst */
  2039. static HB_Error Load_ChainContextSubst( HB_GSUB_SubTable* st,
  2040. HB_Stream stream )
  2041. {
  2042. HB_Error error;
  2043. HB_ChainContextSubst* ccs = &st->chain;
  2044. if ( ACCESS_Frame( 2L ) )
  2045. return error;
  2046. ccs->SubstFormat = GET_UShort();
  2047. FORGET_Frame();
  2048. switch ( ccs->SubstFormat ) {
  2049. case 1: return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream );
  2050. case 2: return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream );
  2051. case 3: return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream );
  2052. default: return ERR(HB_Err_Invalid_SubTable_Format);
  2053. }
  2054. return HB_Err_Ok; /* never reached */
  2055. }
  2056. static void Free_ChainContextSubst( HB_GSUB_SubTable* st )
  2057. {
  2058. HB_ChainContextSubst* ccs = &st->chain;
  2059. switch ( ccs->SubstFormat ) {
  2060. case 1: Free_ChainContextSubst1( &ccs->ccsf.ccsf1 ); break;
  2061. case 2: Free_ChainContextSubst2( &ccs->ccsf.ccsf2 ); break;
  2062. case 3: Free_ChainContextSubst3( &ccs->ccsf.ccsf3 ); break;
  2063. default: break;
  2064. }
  2065. }
  2066. static HB_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub,
  2067. HB_ChainContextSubstFormat1* ccsf1,
  2068. HB_Buffer buffer,
  2069. HB_UShort flags,
  2070. HB_UShort context_length,
  2071. int nesting_level )
  2072. {
  2073. HB_UShort index, property;
  2074. HB_UShort i, j, k, num_csr;
  2075. HB_UShort bgc, igc, lgc;
  2076. HB_Error error;
  2077. HB_ChainSubRule* csr;
  2078. HB_ChainSubRule curr_csr;
  2079. HB_GDEFHeader* gdef;
  2080. gdef = gsub->gdef;
  2081. if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
  2082. return error;
  2083. error = _HB_OPEN_Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index );
  2084. if ( error )
  2085. return error;
  2086. csr = ccsf1->ChainSubRuleSet[index].ChainSubRule;
  2087. num_csr = ccsf1->ChainSubRuleSet[index].ChainSubRuleCount;
  2088. for ( k = 0; k < num_csr; k++ )
  2089. {
  2090. curr_csr = csr[k];
  2091. bgc = curr_csr.BacktrackGlyphCount;
  2092. igc = curr_csr.InputGlyphCount;
  2093. lgc = curr_csr.LookaheadGlyphCount;
  2094. if ( context_length != 0xFFFF && context_length < igc )
  2095. goto next_chainsubrule;
  2096. /* check whether context is too long; it is a first guess only */
  2097. if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
  2098. goto next_chainsubrule;
  2099. if ( bgc )
  2100. {
  2101. /* since we don't know in advance the number of glyphs to inspect,
  2102. we search backwards for matches in the backtrack glyph array */
  2103. for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
  2104. {
  2105. while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
  2106. {
  2107. if ( error && error != HB_Err_Not_Covered )
  2108. return error;
  2109. if ( j + 1 == bgc - i )
  2110. goto next_chainsubrule;
  2111. j--;
  2112. }
  2113. /* In OpenType 1.3, it is undefined whether the offsets of
  2114. backtrack glyphs is in logical order or not. Version 1.4
  2115. will clarify this:
  2116. Logical order - a b c d e f g h i j
  2117. i
  2118. Input offsets - 0 1
  2119. Backtrack offsets - 3 2 1 0
  2120. Lookahead offsets - 0 1 2 3 */
  2121. if ( OUT_GLYPH( j ) != curr_csr.Backtrack[i] )
  2122. goto next_chainsubrule;
  2123. }
  2124. }
  2125. /* Start at 1 because [0] is implied */
  2126. for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
  2127. {
  2128. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  2129. {
  2130. if ( error && error != HB_Err_Not_Covered )
  2131. return error;
  2132. if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
  2133. goto next_chainsubrule;
  2134. j++;
  2135. }
  2136. if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] )
  2137. goto next_chainsubrule;
  2138. }
  2139. /* we are starting to check for lookahead glyphs right after the
  2140. last context glyph */
  2141. for ( i = 0; i < lgc; i++, j++ )
  2142. {
  2143. while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
  2144. {
  2145. if ( error && error != HB_Err_Not_Covered )
  2146. return error;
  2147. if ( j + lgc - i == (HB_Int)buffer->in_length )
  2148. goto next_chainsubrule;
  2149. j++;
  2150. }
  2151. if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] )
  2152. goto next_chainsubrule;
  2153. }
  2154. return Do_ContextSubst( gsub, igc,
  2155. curr_csr.SubstCount,
  2156. curr_csr.SubstLookupRecord,
  2157. buffer,
  2158. nesting_level );
  2159. next_chainsubrule:
  2160. ;
  2161. }
  2162. return HB_Err_Not_Covered;
  2163. }
  2164. static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub,
  2165. HB_ChainContextSubstFormat2* ccsf2,
  2166. HB_Buffer buffer,
  2167. HB_UShort flags,
  2168. HB_UShort context_length,
  2169. int nesting_level )
  2170. {
  2171. HB_UShort index, property;
  2172. HB_Error error;
  2173. HB_UShort i, j, k;