PageRenderTime 69ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/from_google/skia/third_party/harfbuzz/src/harfbuzz-gsub.c

https://bitbucket.org/enic/elib
C | 4329 lines | 2874 code | 1293 blank | 162 comment | 679 complexity | 8d60ea2bb45c537963541ff3497eb05c MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, CC-BY-SA-3.0

Large files files are truncated, but you can click here to view the full 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;

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