PageRenderTime 65ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/fontforge/parsettfatt.c

https://bitbucket.org/sortsmill/sortsmill-tools
C | 5088 lines | 4680 code | 265 blank | 143 comment | 1181 complexity | bcd8c971aa241c24bd2daa76023c09a3 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0

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

  1. #include <config.h>
  2. // This file is part of the Sorts Mill Tools.
  3. //
  4. // Sorts Mill Tools is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Sorts Mill Tools is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, see <http://www.gnu.org/licenses/>.
  16. /* Copyright (C) 2000-2012 by George Williams */
  17. /*
  18. * Redistribution and use in source and binary forms, with or without
  19. * modification, are permitted provided that the following conditions are met:
  20. * Redistributions of source code must retain the above copyright notice, this
  21. * list of conditions and the following disclaimer.
  22. * Redistributions in binary form must reproduce the above copyright notice,
  23. * this list of conditions and the following disclaimer in the documentation
  24. * and/or other materials provided with the distribution.
  25. * The name of the author may not be used to endorse or promote products
  26. * derived from this software without specific prior written permission.
  27. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  28. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  29. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  30. * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  31. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  32. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  33. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  34. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  35. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  36. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  37. */
  38. #include "fontforge.h"
  39. #include <chardata.h>
  40. #include <utype.h>
  41. #include <ustring.h>
  42. #include <math.h>
  43. #include <locale.h>
  44. #include <stdlib.h>
  45. #include "ttf.h"
  46. static uint16_t *
  47. getAppleClassTable (FILE *ttf, int classdef_offset, int cnt, int sub, int div,
  48. struct ttfinfo *info)
  49. {
  50. uint16_t *class = xcalloc (cnt, sizeof (uint16_t));
  51. int first, i, n;
  52. /* Apple stores its class tables as containing offsets. I find it hard to */
  53. /* think that way and convert them to indeces (by subtracting off a base */
  54. /* offset and dividing by the item's size) before doing anything else */
  55. fseek (ttf, classdef_offset, SEEK_SET);
  56. first = getushort (ttf);
  57. n = getushort (ttf);
  58. if (first + n - 1 >= cnt)
  59. {
  60. LogError (_("Bad Apple Kern Class\n"));
  61. info->bad_gx = true;
  62. }
  63. for (i = 0; i < n && i + first < cnt; ++i)
  64. class[first + i] = (getushort (ttf) - sub) / div;
  65. return class;
  66. }
  67. static char **
  68. ClassToNames (struct ttfinfo *info, int class_cnt, uint16_t *class,
  69. int glyph_cnt)
  70. {
  71. char **ret = xmalloc (class_cnt * sizeof (char *));
  72. int *lens = xcalloc (class_cnt, sizeof (int));
  73. int i;
  74. ret[0] = NULL;
  75. for (i = 0; i < glyph_cnt; ++i)
  76. if (class[i] != 0 && info->chars[i] != NULL && class[i] < class_cnt)
  77. lens[class[i]] += strlen (info->chars[i]->name) + 1;
  78. for (i = 1; i < class_cnt; ++i)
  79. ret[i] = xmalloc (lens[i] + 1);
  80. memset (lens, 0, class_cnt * sizeof (int));
  81. for (i = 0; i < glyph_cnt; ++i)
  82. if (class[i] != 0 && info->chars[i] != NULL)
  83. {
  84. if (class[i] < class_cnt)
  85. {
  86. strcpy (ret[class[i]] + lens[class[i]], info->chars[i]->name);
  87. lens[class[i]] += strlen (info->chars[i]->name) + 1;
  88. ret[class[i]][lens[class[i]] - 1] = ' ';
  89. }
  90. else
  91. {
  92. LogError (_("Class index out of range %d (must be <%d)\n"),
  93. class[i], class_cnt);
  94. info->bad_ot = true;
  95. }
  96. }
  97. for (i = 1; i < class_cnt; ++i)
  98. if (lens[i] == 0)
  99. ret[i][0] = '\0';
  100. else
  101. ret[i][lens[i] - 1] = '\0';
  102. free (lens);
  103. return ret;
  104. }
  105. static char *
  106. CoverageMinusClasses (uint16_t *coverageglyphs, uint16_t *classed,
  107. struct ttfinfo *info)
  108. {
  109. int i, j, len;
  110. uint8_t *glyphs = xcalloc (info->glyph_cnt, sizeof (uint8_t));
  111. char *ret;
  112. for (i = 0; coverageglyphs[i] != 0xffff; ++i)
  113. glyphs[coverageglyphs[i]] = 1;
  114. for (i = 0; i < info->glyph_cnt; ++i)
  115. if (classed[i] != 0)
  116. glyphs[i] = 0;
  117. for (i = 0; i < info->glyph_cnt; ++i)
  118. if (glyphs[i] != 0)
  119. break;
  120. /* coverage table matches glyphs in classes. No need for special treatment */
  121. if (i == info->glyph_cnt)
  122. {
  123. free (glyphs);
  124. return NULL;
  125. }
  126. /* Otherwise we need to generate a class string of glyph names in the coverage */
  127. /* table but not in any class. These become the glyphs in class 0 */
  128. ret = NULL;
  129. for (j = 0; j < 2; ++j)
  130. {
  131. len = 0;
  132. for (i = 0; i < info->glyph_cnt; ++i)
  133. {
  134. if (glyphs[i] != 0)
  135. {
  136. if (j)
  137. {
  138. strcpy (ret + len, info->chars[i]->name);
  139. strcat (ret + len, " ");
  140. }
  141. len += strlen (info->chars[i]->name) + 1;
  142. }
  143. }
  144. if (j == 0)
  145. ret = xmalloc (len + 1);
  146. else
  147. ret[len - 1] = '\0';
  148. }
  149. free (glyphs);
  150. return ret;
  151. }
  152. static int
  153. ClassFindCnt (uint16_t *class, int tot)
  154. {
  155. int i, max = 0;
  156. for (i = 0; i < tot; ++i)
  157. if (class[i] > max)
  158. max = class[i];
  159. return max + 1;
  160. }
  161. static int
  162. uint16_t_cmp (const void *u1, const void *u2)
  163. {
  164. return ((int) *((const uint16_t *) u1)) - ((int) *((const uint16_t *) u2));
  165. }
  166. static char *
  167. GlyphsToNames (struct ttfinfo *info, uint16_t *glyphs, int make_uniq)
  168. {
  169. int i, j, len, off;
  170. char *ret, *pt;
  171. if (glyphs == NULL)
  172. return xstrdup ("");
  173. /* Adobe produces coverage tables containing duplicate glyphs in */
  174. /* GaramondPremrPro.otf. We want unique glyphs, so enforce that */
  175. if (make_uniq)
  176. {
  177. for (i = 0; glyphs[i] != 0xffff; ++i);
  178. qsort (glyphs, i, sizeof (uint16_t), uint16_t_cmp);
  179. for (i = 0; glyphs[i] != 0xffff; ++i)
  180. {
  181. if (glyphs[i + 1] == glyphs[i])
  182. {
  183. for (j = i + 1; glyphs[j] == glyphs[i]; ++j);
  184. off = j - i - 1;
  185. for (j = i + 1;; ++j)
  186. {
  187. glyphs[j] = glyphs[j + off];
  188. if (glyphs[j] == 0xffff)
  189. break;
  190. }
  191. }
  192. }
  193. }
  194. for (i = len = 0; glyphs[i] != 0xffff; ++i)
  195. {
  196. if (glyphs[i] >= info->glyph_cnt)
  197. {
  198. if (!info->bad_ot)
  199. {
  200. LogError (_("Glyph %d out of range [0, %d)"),
  201. glyphs[i], info->glyph_cnt);
  202. info->bad_ot = true;
  203. }
  204. return xstrdup ("");
  205. }
  206. if (info->chars[glyphs[i]] != NULL)
  207. len += strlen (info->chars[glyphs[i]]->name) + 1;
  208. }
  209. ret = pt = xmalloc (len + 1);
  210. *pt = '\0';
  211. for (i = 0; glyphs[i] != 0xffff; ++i)
  212. if (info->chars[glyphs[i]] != NULL)
  213. {
  214. strcpy (pt, info->chars[glyphs[i]]->name);
  215. pt += strlen (pt);
  216. *pt++ = ' ';
  217. }
  218. if (pt > ret)
  219. pt[-1] = '\0';
  220. return ret;
  221. }
  222. struct language
  223. { /* normal entry with lang tag 'dflt' */
  224. uint32_t tag;
  225. uint32_t offset;
  226. uint16_t req; /* required feature index. 0xffff for null */
  227. int fcnt;
  228. uint16_t *features;
  229. };
  230. struct scripts
  231. {
  232. uint32_t offset;
  233. uint32_t tag;
  234. int langcnt; /* the default language is included as a */
  235. struct language *languages;
  236. };
  237. struct feature
  238. {
  239. uint32_t offset;
  240. uint32_t tag;
  241. int lcnt;
  242. uint16_t *lookups;
  243. };
  244. struct lookup
  245. {
  246. uint16_t type;
  247. uint32_t flags; /* low order 16 bits: traditional flags, high order: mark filtering set index if pst_usemarkfilteringset */
  248. uint32_t offset;
  249. int subtabcnt;
  250. int32_t *subtab_offsets;
  251. OTLookup *otlookup;
  252. };
  253. static uint16_t *
  254. getCoverageTable (FILE *ttf, int coverage_offset, struct ttfinfo *info)
  255. {
  256. int format, cnt, i, j, rcnt;
  257. uint16_t *glyphs = NULL;
  258. int start, end, ind, max;
  259. fseek (ttf, coverage_offset, SEEK_SET);
  260. format = getushort (ttf);
  261. if (format == 1)
  262. {
  263. cnt = getushort (ttf);
  264. glyphs = xmalloc ((cnt + 1) * sizeof (uint16_t));
  265. if (ftell (ttf) + 2 * cnt > info->g_bounds)
  266. {
  267. LogError (_("coverage table extends beyond end of table\n"));
  268. info->bad_ot = true;
  269. if (ftell (ttf) > info->g_bounds)
  270. return NULL;
  271. cnt = (info->g_bounds - ftell (ttf)) / 2;
  272. }
  273. for (i = 0; i < cnt; ++i)
  274. {
  275. if (cnt & 0xffff0000)
  276. {
  277. LogError (_("Bad count.\n"));
  278. info->bad_ot = true;
  279. }
  280. glyphs[i] = getushort (ttf);
  281. if (feof (ttf))
  282. {
  283. LogError (_("End of file found in coverage table.\n"));
  284. info->bad_ot = true;
  285. free (glyphs);
  286. return NULL;
  287. }
  288. if (glyphs[i] >= info->glyph_cnt)
  289. {
  290. LogError (_("Bad coverage table. Glyph %d out of range [0, %d)"),
  291. glyphs[i], info->glyph_cnt);
  292. info->bad_ot = true;
  293. glyphs[i] = 0;
  294. }
  295. }
  296. }
  297. else if (format == 2)
  298. {
  299. max = 256;
  300. glyphs = xcalloc (max, sizeof (uint16_t));
  301. rcnt = getushort (ttf);
  302. cnt = 0;
  303. if (ftell (ttf) + 6 * rcnt > info->g_bounds)
  304. {
  305. LogError (_("coverage table extends beyond end of table\n"));
  306. info->bad_ot = true;
  307. rcnt = (info->g_bounds - ftell (ttf)) / 6;
  308. }
  309. for (i = 0; i < rcnt; ++i)
  310. {
  311. start = getushort (ttf);
  312. end = getushort (ttf);
  313. ind = getushort (ttf);
  314. if (feof (ttf))
  315. {
  316. LogError (_("End of file found in coverage table.\n"));
  317. info->bad_ot = true;
  318. free (glyphs);
  319. return NULL;
  320. }
  321. if (start > end || end >= info->glyph_cnt)
  322. {
  323. LogError (_("Bad coverage table. "
  324. "Glyph range %d-%d out of range [0, %d)"),
  325. start, end, info->glyph_cnt);
  326. info->bad_ot = true;
  327. start = end = 0;
  328. }
  329. if (ind + end - start + 2 >= max)
  330. {
  331. int oldmax = max;
  332. max = ind + end - start + 2;
  333. glyphs = xrealloc (glyphs, max * sizeof (uint16_t));
  334. memset (glyphs + oldmax, 0, (max - oldmax) * sizeof (uint16_t));
  335. }
  336. for (j = start; j <= end; ++j)
  337. {
  338. glyphs[j - start + ind] = j;
  339. if (j >= info->glyph_cnt)
  340. glyphs[j - start + ind] = 0;
  341. }
  342. if (ind + end - start + 1 > cnt)
  343. cnt = ind + end - start + 1;
  344. }
  345. }
  346. else
  347. {
  348. LogError (_("Bad format for coverage table %d\n"), format);
  349. info->bad_ot = true;
  350. return NULL;
  351. }
  352. glyphs[cnt] = 0xffff;
  353. return glyphs;
  354. }
  355. struct valuerecord
  356. {
  357. int16_t xplacement, yplacement;
  358. int16_t xadvance, yadvance;
  359. uint16_t offXplaceDev, offYplaceDev;
  360. uint16_t offXadvanceDev, offYadvanceDev;
  361. };
  362. static uint16_t *
  363. getClassDefTable (FILE *ttf, int classdef_offset, struct ttfinfo *info)
  364. {
  365. int format, i, j;
  366. uint16_t start, glyphcnt, rangecnt, end, class;
  367. uint16_t *glist = NULL;
  368. int warned = false;
  369. int cnt = info->glyph_cnt;
  370. uint32_t g_bounds = info->g_bounds;
  371. fseek (ttf, classdef_offset, SEEK_SET);
  372. glist = xcalloc (cnt, sizeof (uint16_t)); /* Class 0 is default */
  373. format = getushort (ttf);
  374. if (format == 1)
  375. {
  376. start = getushort (ttf);
  377. glyphcnt = getushort (ttf);
  378. if (start + (int) glyphcnt > cnt)
  379. {
  380. LogError (_("Bad class def table. start=%d cnt=%d, max glyph=%d\n"),
  381. start, glyphcnt, cnt);
  382. info->bad_ot = true;
  383. glyphcnt = cnt - start;
  384. }
  385. else if (ftell (ttf) + 2 * glyphcnt > g_bounds)
  386. {
  387. LogError (_
  388. ("Class definition sub-table extends beyond end of table\n"));
  389. info->bad_ot = true;
  390. glyphcnt = (g_bounds - ftell (ttf)) / 2;
  391. }
  392. for (i = 0; i < glyphcnt; ++i)
  393. glist[start + i] = getushort (ttf);
  394. }
  395. else if (format == 2)
  396. {
  397. rangecnt = getushort (ttf);
  398. if (ftell (ttf) + 6 * rangecnt > g_bounds)
  399. {
  400. LogError (_
  401. ("Class definition sub-table extends beyond end of table\n"));
  402. info->bad_ot = true;
  403. rangecnt = (g_bounds - ftell (ttf)) / 6;
  404. }
  405. for (i = 0; i < rangecnt; ++i)
  406. {
  407. start = getushort (ttf);
  408. end = getushort (ttf);
  409. if (start > end || end >= cnt)
  410. {
  411. LogError (_("Bad class def table. "
  412. "Glyph range %d-%d out of range [0, %d)"),
  413. start, end, cnt);
  414. info->bad_ot = true;
  415. }
  416. class = getushort (ttf);
  417. for (j = start; j <= end; ++j)
  418. if (j < cnt)
  419. glist[j] = class;
  420. }
  421. }
  422. else
  423. {
  424. LogError (_("Unknown class table format: %d\n"), format);
  425. info->bad_ot = true;
  426. /* Put everything in class 0 and return that */
  427. }
  428. /* Do another validity test */
  429. for (i = 0; i < cnt; ++i)
  430. {
  431. if (glist[i] >= cnt + 1)
  432. {
  433. if (!warned)
  434. {
  435. LogError (_
  436. ("Nonsensical class assigned to a glyph-- class=%d is too big. Glyph=%d\n"),
  437. glist[i], i);
  438. info->bad_ot = true;
  439. warned = true;
  440. }
  441. glist[i] = 0;
  442. }
  443. }
  444. return glist;
  445. }
  446. static void
  447. readvaluerecord (struct valuerecord *vr, int vf, FILE *ttf)
  448. {
  449. memset (vr, '\0', sizeof (struct valuerecord));
  450. if (vf & 1)
  451. vr->xplacement = getushort (ttf);
  452. if (vf & 2)
  453. vr->yplacement = getushort (ttf);
  454. if (vf & 4)
  455. vr->xadvance = getushort (ttf);
  456. if (vf & 8)
  457. vr->yadvance = getushort (ttf);
  458. if (vf & 0x10)
  459. vr->offXplaceDev = getushort (ttf);
  460. if (vf & 0x20)
  461. vr->offYplaceDev = getushort (ttf);
  462. if (vf & 0x40)
  463. vr->offXadvanceDev = getushort (ttf);
  464. if (vf & 0x80)
  465. vr->offYadvanceDev = getushort (ttf);
  466. }
  467. static void
  468. ReadDeviceTable (FILE *ttf, DeviceTable *adjust, uint32_t devtab,
  469. struct ttfinfo *info)
  470. {
  471. long here;
  472. int pack;
  473. int w, b, i, c;
  474. if (devtab == 0)
  475. return;
  476. here = ftell (ttf);
  477. fseek (ttf, devtab, SEEK_SET);
  478. adjust->first_pixel_size = getushort (ttf);
  479. adjust->last_pixel_size = getushort (ttf);
  480. pack = getushort (ttf);
  481. if (adjust->first_pixel_size > adjust->last_pixel_size || pack == 0
  482. || pack > 3)
  483. {
  484. LogError (_("Bad device table\n"));
  485. info->bad_ot = true;
  486. adjust->first_pixel_size = adjust->last_pixel_size = 0;
  487. }
  488. else
  489. {
  490. c = adjust->last_pixel_size - adjust->first_pixel_size + 1;
  491. adjust->corrections = xmalloc (c);
  492. if (pack == 1)
  493. {
  494. for (i = 0; i < c; i += 8)
  495. {
  496. w = getushort (ttf);
  497. for (b = 0; b < 8 && i + b < c; ++b)
  498. adjust->corrections[i + b] =
  499. ((int16_t) ((w << (b * 2)) & 0xc000)) >> 14;
  500. }
  501. }
  502. else if (pack == 2)
  503. {
  504. for (i = 0; i < c; i += 4)
  505. {
  506. w = getushort (ttf);
  507. for (b = 0; b < 4 && i + b < c; ++b)
  508. adjust->corrections[i + b] =
  509. ((int16_t) ((w << (b * 4)) & 0xf000)) >> 12;
  510. }
  511. }
  512. else
  513. {
  514. for (i = 0; i < c; ++i)
  515. adjust->corrections[i] = (int8_t) getc (ttf);
  516. }
  517. }
  518. fseek (ttf, here, SEEK_SET);
  519. }
  520. static ValDevTab *
  521. readValDevTab (FILE *ttf, struct valuerecord *vr, uint32_t base,
  522. struct ttfinfo *info)
  523. {
  524. ValDevTab *ret;
  525. if (vr->offXplaceDev == 0 && vr->offYplaceDev == 0 &&
  526. vr->offXadvanceDev == 0 && vr->offYadvanceDev == 0)
  527. return NULL;
  528. ret = xzalloc (sizeof (ValDevTab));
  529. if (vr->offXplaceDev != 0)
  530. ReadDeviceTable (ttf, &ret->xadjust, base + vr->offXplaceDev, info);
  531. if (vr->offYplaceDev != 0)
  532. ReadDeviceTable (ttf, &ret->yadjust, base + vr->offYplaceDev, info);
  533. if (vr->offXadvanceDev != 0)
  534. ReadDeviceTable (ttf, &ret->xadv, base + vr->offXadvanceDev, info);
  535. if (vr->offYadvanceDev != 0)
  536. ReadDeviceTable (ttf, &ret->yadv, base + vr->offYadvanceDev, info);
  537. return ret;
  538. }
  539. static void
  540. addPairPos (struct ttfinfo *info, int glyph1, int glyph2,
  541. struct lookup *l, struct lookup_subtable *subtable,
  542. struct valuerecord *vr1, struct valuerecord *vr2, uint32_t base,
  543. FILE *ttf)
  544. {
  545. if (glyph1 < info->glyph_cnt && glyph2 < info->glyph_cnt &&
  546. info->chars[glyph1] != NULL && info->chars[glyph2] != NULL)
  547. {
  548. PST *pos = xzalloc (sizeof (PST));
  549. pos->type = pst_pair;
  550. pos->subtable = subtable;
  551. pos->next = info->chars[glyph1]->possub;
  552. info->chars[glyph1]->possub = pos;
  553. pos->u.pair.vr = xzalloc (sizeof (ValueRecord[2]));
  554. pos->u.pair.paired = xstrdup_or_null (info->chars[glyph2]->name);
  555. pos->u.pair.vr[0].xoff = vr1->xplacement;
  556. pos->u.pair.vr[0].yoff = vr1->yplacement;
  557. pos->u.pair.vr[0].h_adv_off = vr1->xadvance;
  558. pos->u.pair.vr[0].v_adv_off = vr1->yadvance;
  559. pos->u.pair.vr[1].xoff = vr2->xplacement;
  560. pos->u.pair.vr[1].yoff = vr2->yplacement;
  561. pos->u.pair.vr[1].h_adv_off = vr2->xadvance;
  562. pos->u.pair.vr[1].v_adv_off = vr2->yadvance;
  563. pos->u.pair.vr[0].adjust = readValDevTab (ttf, vr1, base, info);
  564. pos->u.pair.vr[1].adjust = readValDevTab (ttf, vr2, base, info);
  565. }
  566. else
  567. {
  568. LogError (_("Bad pair position: glyphs %d & %d should have been < %d\n"),
  569. glyph1, glyph2, info->glyph_cnt);
  570. info->bad_ot = true;
  571. }
  572. }
  573. static void
  574. gposKernSubTable (FILE *ttf, int stoffset, struct ttfinfo *info,
  575. struct lookup *l, struct lookup_subtable *subtable)
  576. {
  577. int coverage, cnt, pair_cnt, vf1, vf2, glyph2;
  578. int cd1, cd2, c1_cnt, c2_cnt;
  579. uint16_t format;
  580. uint16_t *ps_offsets;
  581. uint16_t *glyphs, *class1, *class2;
  582. struct valuerecord vr1, vr2;
  583. long foffset;
  584. format = getushort (ttf);
  585. if (format != 1 && format != 2) /* Unknown subtable format */
  586. return;
  587. coverage = getushort (ttf);
  588. vf1 = getushort (ttf);
  589. vf2 = getushort (ttf);
  590. if (format == 1)
  591. {
  592. subtable->per_glyph_pst_or_kern = true;
  593. cnt = getushort (ttf);
  594. ps_offsets = xmalloc (cnt * sizeof (uint16_t));
  595. for (int i = 0; i < cnt; ++i)
  596. ps_offsets[i] = getushort (ttf);
  597. glyphs = getCoverageTable (ttf, stoffset + coverage, info);
  598. if (glyphs == NULL)
  599. {
  600. /* TRANSLATORS: This continues a multi-line error message, hence the leading space */
  601. LogError (_(" Bad pairwise kerning table, ignored\n"));
  602. return;
  603. }
  604. for (int i = 0; i < cnt; ++i)
  605. if (glyphs[i] < info->glyph_cnt)
  606. {
  607. fseek (ttf, stoffset + ps_offsets[i], SEEK_SET);
  608. pair_cnt = getushort (ttf);
  609. for (int j = 0; j < pair_cnt; ++j)
  610. {
  611. glyph2 = getushort (ttf);
  612. readvaluerecord (&vr1, vf1, ttf);
  613. readvaluerecord (&vr2, vf2, ttf);
  614. addPairPos (info, glyphs[i], glyph2, l, subtable, &vr1, &vr2,
  615. stoffset, ttf);
  616. }
  617. }
  618. free (ps_offsets);
  619. free (glyphs);
  620. }
  621. else if (format == 2)
  622. { /* Class-based kerning */
  623. cd1 = getushort (ttf);
  624. cd2 = getushort (ttf);
  625. foffset = ftell (ttf);
  626. class1 = getClassDefTable (ttf, stoffset + cd1, info);
  627. class2 = getClassDefTable (ttf, stoffset + cd2, info);
  628. glyphs = getCoverageTable (ttf, stoffset + coverage, info);
  629. if (glyphs == NULL)
  630. {
  631. /* TRANSLATORS: This continues a multi-line error message, hence the leading space */
  632. LogError (_(" Bad kerning class table, ignored\n"));
  633. return;
  634. }
  635. fseek (ttf, foffset, SEEK_SET); /* come back */
  636. c1_cnt = getushort (ttf);
  637. c2_cnt = getushort (ttf);
  638. subtable->per_glyph_pst_or_kern = true;
  639. // TODO: read this as class kerning instead of expanding it as we do now.
  640. for (int i = 0; i < c1_cnt; ++i)
  641. {
  642. for (int j = 0; j < c2_cnt; ++j)
  643. {
  644. readvaluerecord (&vr1, vf1, ttf);
  645. readvaluerecord (&vr2, vf2, ttf);
  646. if (vr1.xadvance != 0 || vr1.xplacement != 0
  647. || vr1.yadvance != 0 || vr1.yplacement != 0
  648. || vr2.xadvance != 0 || vr2.xplacement != 0
  649. || vr2.yadvance != 0 || vr2.yplacement != 0)
  650. for (int k = 0; glyphs[k] != 0xffff; ++k)
  651. if (class1[glyphs[k]] == i)
  652. for (int m = 0; m < info->glyph_cnt; ++m)
  653. if (class2[m] == j)
  654. addPairPos (info, glyphs[k], m, l, subtable, &vr1, &vr2,
  655. stoffset, ttf);
  656. }
  657. }
  658. free (class1);
  659. free (class2);
  660. free (glyphs);
  661. }
  662. }
  663. static AnchorPoint *
  664. readAnchorPoint (FILE *ttf, uint32_t base, AnchorClass * class,
  665. enum anchor_type type, AnchorPoint *last, struct ttfinfo *info)
  666. {
  667. AnchorPoint *ap;
  668. int format;
  669. fseek (ttf, base, SEEK_SET);
  670. ap = xzalloc (sizeof (AnchorPoint));
  671. ap->anchor = class;
  672. /* All anchor types have the same initial 3 entries, format */
  673. /* x,y pos. format 2 contains a truetype positioning point, and */
  674. /* format==3 may also have device tables */
  675. format = getushort (ttf);
  676. ap->me.x = (int16_t) getushort (ttf);
  677. ap->me.y = (int16_t) getushort (ttf);
  678. ap->type = type;
  679. if (format == 2)
  680. {
  681. ap->ttf_pt_index = getushort (ttf);
  682. ap->has_ttf_pt = true;
  683. }
  684. else if (format == 3)
  685. {
  686. int devoff;
  687. devoff = getushort (ttf);
  688. if (devoff != 0)
  689. ReadDeviceTable (ttf, &ap->xadjust, base + devoff, info);
  690. devoff = getushort (ttf);
  691. if (devoff != 0)
  692. ReadDeviceTable (ttf, &ap->yadjust, base + devoff, info);
  693. }
  694. ap->next = last;
  695. return ap;
  696. }
  697. static void
  698. gposCursiveSubTable (FILE *ttf, int stoffset, struct ttfinfo *info,
  699. struct lookup *l, struct lookup_subtable *subtable)
  700. {
  701. int coverage, cnt, format, i;
  702. struct ee_offsets
  703. {
  704. int entry, exit;
  705. } *offsets;
  706. uint16_t *glyphs;
  707. AnchorClass *class;
  708. SplineChar *sc;
  709. char buf[50];
  710. format = getushort (ttf);
  711. if (format != 1) /* Unknown subtable format */
  712. return;
  713. coverage = getushort (ttf);
  714. cnt = getushort (ttf);
  715. if (cnt == 0)
  716. return;
  717. offsets = xmalloc (cnt * sizeof (struct ee_offsets));
  718. for (i = 0; i < cnt; ++i)
  719. {
  720. offsets[i].entry = getushort (ttf);
  721. offsets[i].exit = getushort (ttf);
  722. }
  723. glyphs = getCoverageTable (ttf, stoffset + coverage, info);
  724. if (glyphs == NULL)
  725. {
  726. /* TRANSLATORS: This continues a multi-line error message, hence the leading space */
  727. LogError (_(" Bad cursive alignment table, ignored\n"));
  728. free (offsets);
  729. return;
  730. }
  731. class = xzalloc (sizeof (AnchorClass));
  732. snprintf (buf, sizeof (buf), _("Cursive-%d"), info->anchor_class_cnt++);
  733. class->name = xstrdup_or_null (buf);
  734. subtable->anchor_classes = true;
  735. class->subtable = subtable;
  736. if (info->ahead == NULL)
  737. info->ahead = class;
  738. else
  739. info->alast->next = class;
  740. info->alast = class;
  741. for (i = 0; i < cnt; ++i)
  742. {
  743. sc = info->chars[glyphs[i]];
  744. if (offsets[i].entry != 0)
  745. {
  746. sc->anchor = readAnchorPoint (ttf, stoffset + offsets[i].entry, class,
  747. at_centry, sc->anchor, info);
  748. }
  749. if (offsets[i].exit != 0)
  750. {
  751. sc->anchor = readAnchorPoint (ttf, stoffset + offsets[i].exit, class,
  752. at_cexit, sc->anchor, info);
  753. }
  754. }
  755. free (offsets);
  756. free (glyphs);
  757. }
  758. static AnchorClass **
  759. MarkGlyphsProcessMarks (FILE *ttf, int markoffset,
  760. struct ttfinfo *info, struct lookup *l,
  761. struct lookup_subtable *subtable, uint16_t *markglyphs,
  762. int classcnt)
  763. {
  764. AnchorClass **classes = xcalloc (classcnt, sizeof (AnchorClass *)), *ac;
  765. char buf[50];
  766. int i, cnt;
  767. struct mr
  768. {
  769. uint16_t class, offset;
  770. } *at_offsets;
  771. SplineChar *sc;
  772. for (i = 0; i < classcnt; ++i)
  773. {
  774. snprintf (buf, sizeof (buf), _("Anchor-%d"), info->anchor_class_cnt + i);
  775. classes[i] = ac = xzalloc (sizeof (AnchorClass));
  776. ac->name = xstrdup_or_null (buf);
  777. subtable->anchor_classes = true;
  778. ac->subtable = subtable;
  779. /*ac->merge_with = info->anchor_merge_cnt+1; */
  780. /* I don't distinguish between mark to base and mark to lig */
  781. if (info->ahead == NULL)
  782. info->ahead = ac;
  783. else
  784. info->alast->next = ac;
  785. info->alast = ac;
  786. }
  787. fseek (ttf, markoffset, SEEK_SET);
  788. cnt = getushort (ttf);
  789. if (feof (ttf))
  790. {
  791. LogError (_("Bad mark table.\n"));
  792. info->bad_ot = true;
  793. return NULL;
  794. }
  795. at_offsets = xmalloc (cnt * sizeof (struct mr));
  796. for (i = 0; i < cnt; ++i)
  797. {
  798. at_offsets[i].class = getushort (ttf);
  799. at_offsets[i].offset = getushort (ttf);
  800. if (at_offsets[i].class >= classcnt)
  801. {
  802. at_offsets[i].class = 0;
  803. if (markglyphs[i] >= info->glyph_cnt)
  804. LogError (_("Class out of bounds in GPOS mark sub-table\n"));
  805. else
  806. LogError (_
  807. ("Class out of bounds in GPOS mark sub-table for mark %.30s\n"),
  808. info->chars[markglyphs[i]]->name);
  809. info->bad_ot = true;
  810. }
  811. }
  812. for (i = 0; i < cnt; ++i)
  813. {
  814. if (markglyphs[i] >= info->glyph_cnt)
  815. continue;
  816. sc = info->chars[markglyphs[i]];
  817. if (sc == NULL || at_offsets[i].offset == 0)
  818. continue;
  819. sc->anchor = readAnchorPoint (ttf, markoffset + at_offsets[i].offset,
  820. classes[at_offsets[i].class], at_mark,
  821. sc->anchor, info);
  822. }
  823. free (at_offsets);
  824. return classes;
  825. }
  826. static void
  827. MarkGlyphsProcessBases (FILE *ttf, int baseoffset,
  828. struct ttfinfo *info, struct lookup *l,
  829. struct lookup_subtable *subtable, uint16_t *baseglyphs,
  830. int classcnt, AnchorClass ** classes,
  831. enum anchor_type at)
  832. {
  833. int basecnt, i, j, ibase;
  834. uint16_t *offsets;
  835. SplineChar *sc;
  836. fseek (ttf, baseoffset, SEEK_SET);
  837. basecnt = getushort (ttf);
  838. if (feof (ttf))
  839. {
  840. LogError (_("Bad base table.\n"));
  841. info->bad_ot = true;
  842. return;
  843. }
  844. offsets = xmalloc (basecnt * classcnt * sizeof (uint16_t));
  845. for (i = 0; i < basecnt * classcnt; ++i)
  846. offsets[i] = getushort (ttf);
  847. for (i = ibase = 0; i < basecnt; ++i, ibase += classcnt)
  848. {
  849. if (baseglyphs[i] >= info->glyph_cnt)
  850. continue;
  851. sc = info->chars[baseglyphs[i]];
  852. if (sc == NULL)
  853. continue;
  854. for (j = 0; j < classcnt; ++j)
  855. if (offsets[ibase + j] != 0)
  856. {
  857. sc->anchor = readAnchorPoint (ttf, baseoffset + offsets[ibase + j],
  858. classes[j], at, sc->anchor, info);
  859. }
  860. }
  861. free (offsets);
  862. }
  863. static void
  864. MarkGlyphsProcessLigs (FILE *ttf, int baseoffset,
  865. struct ttfinfo *info, struct lookup *l,
  866. struct lookup_subtable *subtable, uint16_t *baseglyphs,
  867. int classcnt, AnchorClass ** classes)
  868. {
  869. int basecnt, compcnt, i, j, k, kbase;
  870. uint16_t *loffsets, *aoffsets;
  871. SplineChar *sc;
  872. fseek (ttf, baseoffset, SEEK_SET);
  873. basecnt = getushort (ttf);
  874. if (feof (ttf))
  875. {
  876. LogError (_("Bad ligature base table.\n"));
  877. info->bad_ot = true;
  878. return;
  879. }
  880. loffsets = xmalloc (basecnt * sizeof (uint16_t));
  881. for (i = 0; i < basecnt; ++i)
  882. loffsets[i] = getushort (ttf);
  883. for (i = 0; i < basecnt; ++i)
  884. {
  885. sc = info->chars[baseglyphs[i]];
  886. if (baseglyphs[i] >= info->glyph_cnt || sc == NULL)
  887. continue;
  888. fseek (ttf, baseoffset + loffsets[i], SEEK_SET);
  889. compcnt = getushort (ttf);
  890. if (feof (ttf))
  891. {
  892. LogError (_("Bad ligature anchor count.\n"));
  893. info->bad_ot = true;
  894. continue;
  895. }
  896. aoffsets = xmalloc (compcnt * classcnt * sizeof (uint16_t));
  897. for (k = 0; k < compcnt * classcnt; ++k)
  898. aoffsets[k] = getushort (ttf);
  899. for (k = kbase = 0; k < compcnt; ++k, kbase += classcnt)
  900. {
  901. for (j = 0; j < classcnt; ++j)
  902. if (aoffsets[kbase + j] != 0)
  903. {
  904. sc->anchor =
  905. readAnchorPoint (ttf,
  906. baseoffset + loffsets[i] + aoffsets[kbase +
  907. j],
  908. classes[j], at_baselig, sc->anchor, info);
  909. sc->anchor->lig_index = k;
  910. }
  911. }
  912. free (aoffsets);
  913. }
  914. free (loffsets);
  915. }
  916. static void
  917. gposMarkSubTable (FILE *ttf, uint32_t stoffset,
  918. struct ttfinfo *info, struct lookup *l,
  919. struct lookup_subtable *subtable)
  920. {
  921. int markcoverage, basecoverage, classcnt, markoffset, baseoffset;
  922. uint16_t *markglyphs, *baseglyphs;
  923. AnchorClass **classes;
  924. /* The header for the three different mark tables is the same */
  925. /* Type = */ getushort (ttf);
  926. markcoverage = getushort (ttf);
  927. basecoverage = getushort (ttf);
  928. classcnt = getushort (ttf);
  929. markoffset = getushort (ttf);
  930. baseoffset = getushort (ttf);
  931. markglyphs = getCoverageTable (ttf, stoffset + markcoverage, info);
  932. baseglyphs = getCoverageTable (ttf, stoffset + basecoverage, info);
  933. if (baseglyphs == NULL || markglyphs == NULL)
  934. {
  935. free (baseglyphs);
  936. free (markglyphs);
  937. LogError (_(" Bad mark attachment table, ignored\n"));
  938. return;
  939. }
  940. /* as is the (first) mark table */
  941. classes = MarkGlyphsProcessMarks (ttf, stoffset + markoffset,
  942. info, l, subtable, markglyphs, classcnt);
  943. if (classes == NULL)
  944. return;
  945. switch (l->otlookup->lookup_type)
  946. {
  947. case gpos_mark2base:
  948. case gpos_mark2mark:
  949. MarkGlyphsProcessBases (ttf, stoffset + baseoffset,
  950. info, l, subtable, baseglyphs, classcnt, classes,
  951. l->otlookup->lookup_type ==
  952. gpos_mark2base ? at_basechar : at_basemark);
  953. break;
  954. case gpos_mark2ligature:
  955. MarkGlyphsProcessLigs (ttf, stoffset + baseoffset,
  956. info, l, subtable, baseglyphs, classcnt, classes);
  957. break;
  958. }
  959. info->anchor_class_cnt += classcnt;
  960. ++info->anchor_merge_cnt;
  961. free (markglyphs);
  962. free (baseglyphs);
  963. free (classes);
  964. }
  965. static void
  966. gposSimplePos (FILE *ttf, int stoffset, struct ttfinfo *info,
  967. struct lookup *l, struct lookup_subtable *subtable)
  968. {
  969. int coverage, cnt, i, vf;
  970. uint16_t format;
  971. uint16_t *glyphs;
  972. struct valuerecord *vr = NULL, _vr, *which;
  973. format = getushort (ttf);
  974. if (format != 1 && format != 2) /* Unknown subtable format */
  975. return;
  976. coverage = getushort (ttf);
  977. vf = getushort (ttf);
  978. if (vf == 0)
  979. return;
  980. if (format == 1)
  981. {
  982. memset (&_vr, 0, sizeof (_vr));
  983. readvaluerecord (&_vr, vf, ttf);
  984. }
  985. else
  986. {
  987. cnt = getushort (ttf);
  988. vr = xcalloc (cnt, sizeof (struct valuerecord));
  989. for (i = 0; i < cnt; ++i)
  990. readvaluerecord (&vr[i], vf, ttf);
  991. }
  992. glyphs = getCoverageTable (ttf, stoffset + coverage, info);
  993. if (glyphs == NULL)
  994. {
  995. free (vr);
  996. LogError (_(" Bad simple positioning table, ignored\n"));
  997. return;
  998. }
  999. for (i = 0; glyphs[i] != 0xffff; ++i)
  1000. if (glyphs[i] < info->glyph_cnt && info->chars[glyphs[i]] != NULL)
  1001. {
  1002. PST *pos = xzalloc (sizeof (PST));
  1003. pos->type = pst_position;
  1004. pos->subtable = subtable;
  1005. pos->next = info->chars[glyphs[i]]->possub;
  1006. info->chars[glyphs[i]]->possub = pos;
  1007. which = format == 1 ? &_vr : &vr[i];
  1008. pos->u.pos.xoff = which->xplacement;
  1009. pos->u.pos.yoff = which->yplacement;
  1010. pos->u.pos.h_adv_off = which->xadvance;
  1011. pos->u.pos.v_adv_off = which->yadvance;
  1012. pos->u.pos.adjust = readValDevTab (ttf, which, stoffset, info);
  1013. }
  1014. subtable->per_glyph_pst_or_kern = true;
  1015. free (vr);
  1016. free (glyphs);
  1017. }
  1018. static void
  1019. ProcessSubLookups (FILE *ttf, struct ttfinfo *info, int gpos,
  1020. struct lookup *alllooks, struct seqlookup *sl)
  1021. {
  1022. int i;
  1023. i = (intptr_t) sl->lookup;
  1024. if (i < 0 || i >= info->lookup_cnt)
  1025. {
  1026. LogError (_
  1027. ("Attempt to reference lookup %d (within a contextual lookup), but there are\n only %d lookups in %s\n"),
  1028. i, info->lookup_cnt, gpos ? "'GPOS'" : "'GSUB'");
  1029. info->bad_ot = true;
  1030. sl->lookup = NULL;
  1031. return;
  1032. }
  1033. sl->lookup = alllooks[i].otlookup;
  1034. }
  1035. static void
  1036. g___ContextSubTable1 (FILE *ttf, int stoffset,
  1037. struct ttfinfo *info, struct lookup *l,
  1038. struct lookup_subtable *subtable, int justinuse,
  1039. struct lookup *alllooks, int gpos)
  1040. {
  1041. int i, j, k, rcnt, cnt;
  1042. uint16_t coverage;
  1043. uint16_t *glyphs;
  1044. struct subrule
  1045. {
  1046. uint32_t offset;
  1047. int gcnt;
  1048. int scnt;
  1049. uint16_t *glyphs;
  1050. struct seqlookup *sl;
  1051. };
  1052. struct rule
  1053. {
  1054. uint32_t offsets;
  1055. int scnt;
  1056. struct subrule *subrules;
  1057. } *rules;
  1058. FPST *fpst;
  1059. struct fpst_rule *rule;
  1060. int warned = false, warned2 = false;
  1061. coverage = getushort (ttf);
  1062. rcnt = getushort (ttf); /* glyph count in coverage table */
  1063. rules = xmalloc (rcnt * sizeof (struct rule));
  1064. for (i = 0; i < rcnt; ++i)
  1065. rules[i].offsets = getushort (ttf) + stoffset;
  1066. glyphs = getCoverageTable (ttf, stoffset + coverage, info);
  1067. if (glyphs == NULL)
  1068. {
  1069. /* TRANSLATORS: This continues a multi-line error message, hence the leading space */
  1070. LogError (_(" Bad contextual table, ignored\n"));
  1071. return;
  1072. }
  1073. cnt = 0;
  1074. for (i = 0; i < rcnt; ++i)
  1075. {
  1076. fseek (ttf, rules[i].offsets, SEEK_SET);
  1077. rules[i].scnt = getushort (ttf);
  1078. cnt += rules[i].scnt;
  1079. rules[i].subrules = xmalloc (rules[i].scnt * sizeof (struct subrule));
  1080. for (j = 0; j < rules[i].scnt; ++j)
  1081. rules[i].subrules[j].offset = getushort (ttf) + rules[i].offsets;
  1082. for (j = 0; j < rules[i].scnt; ++j)
  1083. {
  1084. fseek (ttf, rules[i].subrules[j].offset, SEEK_SET);
  1085. rules[i].subrules[j].gcnt = getushort (ttf);
  1086. rules[i].subrules[j].scnt = getushort (ttf);
  1087. rules[i].subrules[j].glyphs =
  1088. xmalloc ((rules[i].subrules[j].gcnt + 1) * sizeof (uint16_t));
  1089. rules[i].subrules[j].glyphs[0] = glyphs[i];
  1090. for (k = 1; k < rules[i].subrules[j].gcnt; ++k)
  1091. {
  1092. rules[i].subrules[j].glyphs[k] = getushort (ttf);
  1093. if (rules[i].subrules[j].glyphs[k] >= info->glyph_cnt)
  1094. {
  1095. if (!warned)
  1096. LogError (_("Bad contextual or chaining sub table. "
  1097. "Glyph %d out of range [0, %d)"),
  1098. rules[i].subrules[j].glyphs[k], info->glyph_cnt);
  1099. info->bad_ot = true;
  1100. warned = true;
  1101. rules[i].subrules[j].glyphs[k] = 0;
  1102. }
  1103. }
  1104. rules[i].subrules[j].glyphs[k] = 0xffff;
  1105. rules[i].subrules[j].sl =
  1106. xmalloc (rules[i].subrules[j].scnt * sizeof (struct seqlookup));
  1107. for (k = 0; k < rules[i].subrules[j].scnt; ++k)
  1108. {
  1109. rules[i].subrules[j].sl[k].seq = getushort (ttf);
  1110. if (rules[i].subrules[j].sl[k].seq >=
  1111. rules[i].subrules[j].gcnt + 1)
  1112. if (!warned2)
  1113. {
  1114. LogError (_
  1115. ("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d max=%d\n"),
  1116. rules[i].subrules[j].sl[k].seq,
  1117. rules[i].subrules[j].gcnt);
  1118. info->bad_ot = true;
  1119. warned2 = true;
  1120. }
  1121. rules[i].subrules[j].sl[k].lookup =
  1122. (void *) (intptr_t) getushort (ttf);
  1123. }
  1124. }
  1125. }
  1126. if (justinuse == git_justinuse)
  1127. {
  1128. /* Nothing to do. This lookup doesn't really reference any glyphs */
  1129. /* any lookups it invokes will be processed on their own */
  1130. }
  1131. else
  1132. {
  1133. fpst = xzalloc (sizeof (FPST));
  1134. fpst->type = gpos ? pst_contextpos : pst_contextsub;
  1135. fpst->format = pst_glyphs;
  1136. fpst->subtable = subtable;
  1137. fpst->next = info->possub;
  1138. info->possub = fpst;
  1139. subtable->fpst = fpst;
  1140. fpst->rules = rule = xcalloc (cnt, sizeof (struct fpst_rule));
  1141. fpst->rule_cnt = cnt;
  1142. cnt = 0;
  1143. for (i = 0; i < rcnt; ++i)
  1144. for (j = 0; j < rules[i].scnt; ++j)
  1145. {
  1146. rule[cnt].u.glyph.names =
  1147. GlyphsToNames (info, rules[i].subrules[j].glyphs, false);
  1148. rule[cnt].lookup_cnt = rules[i].subrules[j].scnt;
  1149. rule[cnt].lookups = rules[i].subrules[j].sl;
  1150. rules[i].subrules[j].sl = NULL;
  1151. for (k = 0; k < rule[cnt].lookup_cnt; ++k)
  1152. ProcessSubLookups (ttf, info, gpos, alllooks,
  1153. &rule[cnt].lookups[k]);
  1154. ++cnt;
  1155. }
  1156. }
  1157. for (i = 0; i < rcnt; ++i)
  1158. {
  1159. for (j = 0; j < rules[i].scnt; ++j)
  1160. {
  1161. free (rules[i].subrules[j].glyphs);
  1162. free (rules[i].subrules[j].sl);
  1163. }
  1164. free (rules[i].subrules);
  1165. }
  1166. free (rules);
  1167. free (glyphs);
  1168. }
  1169. static void
  1170. g___ChainingSubTable1 (FILE *ttf, int stoffset,
  1171. struct ttfinfo *info, struct lookup *l,
  1172. struct lookup_subtable *subtable, int justinuse,
  1173. struct lookup *alllooks, int gpos)
  1174. {
  1175. int i, j, k, rcnt, cnt, which;
  1176. uint16_t coverage;
  1177. uint16_t *glyphs;
  1178. struct subrule
  1179. {
  1180. uint32_t offset;
  1181. int gcnt, bcnt, fcnt;
  1182. int scnt;
  1183. uint16_t *glyphs, *bglyphs, *fglyphs;
  1184. struct seqlookup *sl;
  1185. };
  1186. struct rule
  1187. {
  1188. uint32_t offsets;
  1189. int scnt;
  1190. struct subrule *subrules;
  1191. } *rules;
  1192. FPST *fpst;
  1193. struct fpst_rule *rule;
  1194. int warned = false, warned2 = false;
  1195. coverage = getushort (ttf);
  1196. rcnt = getushort (ttf); /* glyph count in coverage table */
  1197. rules = xmalloc (rcnt * sizeof (struct rule));
  1198. for (i = 0; i < rcnt; ++i)
  1199. rules[i].offsets = getushort (ttf) + stoffset;
  1200. glyphs = getCoverageTable (ttf, stoffset + coverage, info);
  1201. if (glyphs == NULL)
  1202. {
  1203. free (rules);
  1204. LogError (_(" Bad contextual chaining table, ignored\n"));
  1205. return;
  1206. }
  1207. cnt = 0;
  1208. for (i = 0; i < rcnt; ++i)
  1209. {
  1210. fseek (ttf, rules[i].offsets, SEEK_SET);
  1211. rules[i].scnt = getushort (ttf);
  1212. cnt += rules[i].scnt;
  1213. rules[i].subrules = xmalloc (rules[i].scnt * sizeof (struct subrule));
  1214. for (j = 0; j < rules[i].scnt; ++j)
  1215. rules[i].subrules[j].offset = getushort (ttf) + rules[i].offsets;
  1216. for (j = 0; j < rules[i].scnt; ++j)
  1217. {
  1218. fseek (ttf, rules[i].subrules[j].offset, SEEK_SET);
  1219. rules[i].subrules[j].bcnt = getushort (ttf);
  1220. if (feof (ttf))
  1221. {
  1222. LogError (_
  1223. ("Unexpected end of file in contextual chaining subtable.\n"));
  1224. info->bad_ot = true;
  1225. return;
  1226. }
  1227. rules[i].subrules[j].bglyphs =
  1228. xmalloc ((rules[i].subrules[j].bcnt + 1) * sizeof (uint16_t));
  1229. for (k = 0; k < rules[i].subrules[j].bcnt; ++k)
  1230. rules[i].subrules[j].bglyphs[k] = getushort (ttf);
  1231. rules[i].subrules[j].bglyphs[k] = 0xffff;
  1232. rules[i].subrules[j].gcnt = getushort (ttf);
  1233. if (feof (ttf))
  1234. {
  1235. LogError (_
  1236. ("Unexpected end of file in contextual chaining subtable.\n"));
  1237. info->bad_ot = true;
  1238. return;
  1239. }
  1240. rules[i].subrules[j].glyphs =
  1241. xmalloc ((rules[i].subrules[j].gcnt + 1) * sizeof (uint16_t));
  1242. rules[i].subrules[j].glyphs[0] = glyphs[i];
  1243. for (k = 1; k < rules[i].subrules[j].gcnt; ++k)
  1244. rules[i].subrules[j].glyphs[k] = getushort (ttf);
  1245. rules[i].subrules[j].glyphs[k] = 0xffff;
  1246. rules[i].subrules[j].fcnt = getushort (ttf);
  1247. if (feof (ttf))
  1248. {
  1249. LogError (_
  1250. ("Unexpected end of file in contextual chaining subtable.\n"));
  1251. info->bad_ot = true;
  1252. return;
  1253. }
  1254. rules[i].subrules[j].fglyphs =
  1255. xmalloc ((rules[i].subrules[j].fcnt + 1) * sizeof (uint16_t));
  1256. for (k = 0; k < rules[i].subrules[j].fcnt; ++k)
  1257. rules[i].subrules[j].fglyphs[k] = getushort (ttf);
  1258. rules[i].subrules[j].fglyphs[k] = 0xffff;
  1259. for (which = 0; which < 3; ++which)
  1260. {
  1261. for (k = 0; k < (&rules[i].subrules[j].gcnt)[which]; ++k)
  1262. {
  1263. if ((&rules[i].subrules[j].glyphs)[which][k] >=
  1264. info->glyph_cnt)
  1265. {
  1266. if (!warned)
  1267. LogError (_("Bad contextual or chaining sub table. "
  1268. "Glyph %d out of range [0, %d)"),
  1269. (&rules[i].subrules[j].glyphs)[which][k],
  1270. info->glyph_cnt);
  1271. info->bad_ot = true;
  1272. warned = true;
  1273. (&rules[i].subrules[j].glyphs)[which][k] = 0;
  1274. }
  1275. }
  1276. }
  1277. rules[i].subrules[j].scnt = getushort (ttf);
  1278. if (feof (ttf))
  1279. {
  1280. LogError (_
  1281. ("Unexpected end of file in contextual chaining subtable.\n"));
  1282. info->bad_ot = true;
  1283. return;
  1284. }
  1285. rules[i].subrules[j].sl =
  1286. xmalloc (rules[i].subrules[j].scnt * sizeof (struct seqlookup));
  1287. for (k = 0; k < rules[i].subrules[j].scnt; ++k)
  1288. {
  1289. rules[i].subrules[j].sl[k].seq = getushort (ttf);
  1290. if (rules[i].subrules[j].sl[k].seq >=
  1291. rules[i].subrules[j].gcnt + 1)
  1292. if (!warned2)
  1293. {
  1294. LogError (_
  1295. ("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d max=%d\n"),
  1296. rules[i].subrules[j].sl[k].seq,
  1297. rules[i].subrules[j].gcnt);
  1298. info->bad_ot = true;
  1299. warned2 = true;
  1300. }
  1301. rules[i].subrules[j].sl[k].lookup =
  1302. (void *) (intptr_t) getushort (ttf);
  1303. }
  1304. }
  1305. }
  1306. if (justinuse == git_justinuse)
  1307. {
  1308. /* Nothing to do. This lookup doesn't really reference any glyphs */
  1309. /* any lookups it invokes will be processed on their own */
  1310. }
  1311. else
  1312. {
  1313. fpst = xzalloc (sizeof (FPST));
  1314. fpst->type = gpos ? pst_chainpos : pst_chainsub;
  1315. fpst->format = pst_glyphs;
  1316. fpst->subtable = subtable;
  1317. fpst->next = info->possub;
  1318. info->possub = fpst;
  1319. subtable->fpst = fpst;
  1320. fpst->rules = rule = xcalloc (cnt, sizeof (struct fpst_rule));
  1321. fpst->rule_cnt = cnt;
  1322. cnt = 0;
  1323. for (i = 0; i < rcnt; ++i)
  1324. for (j = 0; j < rules[i].scnt; ++j)
  1325. {
  1326. rule[cnt].u.glyph.back =
  1327. GlyphsToNames (info, rules[i].subrules[j].bglyphs, false);
  1328. rule[cnt].u.glyph.names =
  1329. GlyphsToNames (info, rules[i].subrules[j].glyphs, false);
  1330. rule[cnt].u.glyph.fore =
  1331. GlyphsToNames (info, rules[i].subrules[j].fglyphs, false);
  1332. rule[cnt].lookup_cnt = rules[i].subrules[j].scnt;
  1333. rule[cnt].lookups = rules[i].subrules[j].sl;
  1334. rules[i].subrules[j].sl = NULL;
  1335. for (k = 0; k < rule[cnt].lookup_cnt; ++k)
  1336. ProcessSubLookups (ttf, info, gpos, alllooks,
  1337. &rule[cnt].lookups[k]);
  1338. ++cnt;
  1339. }
  1340. }
  1341. for (i = 0; i < rcnt; ++i)
  1342. {
  1343. for (j = 0; j < rules[i].scnt; ++j)
  1344. {
  1345. free (rules[i].subrules[j].bglyphs);
  1346. free (rules[i].subrules[j].glyphs);
  1347. free (rules[i].subrules[j].fglyphs);
  1348. free (rules[i].subrules[j].sl);
  1349. }
  1350. free (rules[i].subrules);
  1351. }
  1352. free (rules);
  1353. free (glyphs);
  1354. }
  1355. static void
  1356. g___ContextSubTable2 (FILE *ttf, int stoffset,
  1357. struct ttfinfo *info, struct lookup *l,
  1358. struct lookup_subtable *subtable, int justinuse,
  1359. struct lookup *alllooks, int gpos)
  1360. {
  1361. int i, j, k, rcnt, cnt;
  1362. uint16_t coverage;
  1363. uint16_t classoff;
  1364. struct subrule
  1365. {
  1366. uint32_t offset;
  1367. int ccnt;
  1368. int scnt;
  1369. uint16_t *classindeces;
  1370. struct seqlookup *sl;
  1371. };
  1372. struct rule
  1373. {
  1374. uint32_t offsets;
  1375. int scnt;
  1376. struct subrule *subrules;
  1377. } *rules;
  1378. FPST *fpst;
  1379. struct fpst_rule *rule;
  1380. uint16_t *glyphs, *class;
  1381. int warned2 = false;
  1382. coverage = getushort (ttf);
  1383. classoff = getushort (ttf);
  1384. rcnt = getushort (ttf); /* class count in coverage table *//* == number of top level rules */
  1385. rules = xcalloc (rcnt, sizeof (struct rule));
  1386. for (i = 0; i < rcnt; ++i)
  1387. rules[i].offsets = getushort (ttf) + stoffset;
  1388. cnt = 0;
  1389. for (i = 0; i < rcnt; ++i)
  1390. if (rules[i].offsets != stoffset)
  1391. { /* some classes might be unused */
  1392. fseek (ttf, rules[i].offsets, SEEK_SET);
  1393. rules[i].scnt = getushort (ttf);
  1394. if (rules[i].scnt < 0)
  1395. {
  1396. LogError (_("Bad count in context chaining sub-table.\n"));
  1397. info->bad_ot = true;
  1398. return;
  1399. }
  1400. cnt += rules[i].scnt;
  1401. rules[i].subrules = xmalloc (rules[i].scnt * sizeof (struct subrule));
  1402. for (j = 0; j < rules[i].scnt; ++j)
  1403. rules[i].subrules[j].offset = getushort (ttf) + rules[i].offsets;
  1404. for (j = 0; j < rules[i].scnt; ++j)
  1405. {
  1406. fseek (ttf, rules[i].subrules[j].offset, SEEK_SET);
  1407. rules[i].subrules[j].ccnt = getushort (ttf);
  1408. rules[i].subrules[j].scnt = getushort (ttf);
  1409. if (rules[i].subrules[j].ccnt < 0)
  1410. {
  1411. LogError (_
  1412. ("Bad class count in contextual chaining sub-table.\n"));
  1413. info->bad_ot = true;
  1414. free (rules);
  1415. return;
  1416. }
  1417. rules[i].subrules[j].classindeces =
  1418. xmalloc (rules[i].subrules[j].ccnt * sizeof (uint16_t));
  1419. rules[i].subrules[j].classindeces[0] = i;
  1420. for (k = 1; k < rules[i].subrules[j].ccnt; ++k)
  1421. rules[i].subrules[j].classindeces[k] = getushort (ttf);
  1422. if (rules[i].subrules[j].scnt < 0)
  1423. {
  1424. LogError (_("Bad count in contextual chaining sub-table.\n"));
  1425. info->bad_ot = true;
  1426. free (rules);
  1427. return;
  1428. }
  1429. rules[i].subrules[j].sl =
  1430. xmalloc (rules[i].subrules[j].scnt * sizeof (struct seqlookup));
  1431. for (k = 0; k < rules[i].subrules[j].scnt; ++k)
  1432. {
  1433. rules[i].subrules[j].sl[k].seq = getushort (ttf);
  1434. if (rules[i].subrules[j].sl[k].seq >= rules[i].subrules[j].ccnt)
  1435. if (!warned2)
  1436. {
  1437. LogError (_
  1438. ("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d max=%d\n"),
  1439. rules[i].subrules[j].sl[k].seq,
  1440. rules[i].subrules[j].ccnt - 1);
  1441. info->bad_ot = true;
  1442. warned2 = true;
  1443. }
  1444. rules[i].subrules[j].sl[k].lookup =
  1445. (void *) (intptr_t) getushort (ttf);
  1446. }
  1447. }
  1448. }
  1449. if (justinuse == git_justinuse)
  1450. {
  1451. /* Nothing to do. This lookup doesn't really reference any glyphs */
  1452. /* any lookups it invokes will be processed on their own */
  1453. }
  1454. else
  1455. {
  1456. fpst = xzalloc (sizeof (FPST));
  1457. fpst->type = gpos ? pst_contextpos : pst_contextsub;
  1458. fpst->format = pst_class;
  1459. fpst->subtable = subtable;
  1460. subtable->fpst = fpst;
  1461. fpst->next = info->possub;
  1462. info->possub = fpst;
  1463. fpst->rules = rule = xcalloc (cnt, sizeof (struct fpst_rule));
  1464. fpst->rule_cnt = cnt;
  1465. class = getClassDefTable (ttf, stoffset + classoff, info);
  1466. fpst->nccnt = ClassFindCnt (class, info->glyph_cnt);
  1467. fpst->nclass = ClassToNames (info, fpst->nccnt, class, inf

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