PageRenderTime 61ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/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

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_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

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