PageRenderTime 41ms CodeModel.GetById 18ms RepoModel.GetById 1ms 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
  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, info->glyph_cnt);
  1468. fpst->nclassnames = xcalloc (fpst->nccnt, sizeof (char *));
  1469. /* Just in case they used the coverage table to redefine class 0 */
  1470. glyphs = getCoverageTable (ttf, stoffset + coverage, info);
  1471. if (glyphs == NULL)
  1472. {
  1473. /* TRANSLATORS: This continues a multi-line error message, hence the leading space */
  1474. LogError (_(" Bad contextual substitution table, ignored\n"));
  1475. return;
  1476. }
  1477. fpst->nclass[0] = CoverageMinusClasses (glyphs, class, info);
  1478. free (glyphs);
  1479. free (class);
  1480. class = NULL;
  1481. cnt = 0;
  1482. for (i = 0; i < rcnt; ++i)
  1483. for (j = 0; j < rules[i].scnt; ++j)
  1484. {
  1485. rule[cnt].u.class.nclasses = rules[i].subrules[j].classindeces;
  1486. rule[cnt].u.class.ncnt = rules[i].subrules[j].ccnt;
  1487. rules[i].subrules[j].classindeces = NULL;
  1488. rule[cnt].lookup_cnt = rules[i].subrules[j].scnt;
  1489. rule[cnt].lookups = rules[i].subrules[j].sl;
  1490. rules[i].subrules[j].sl = NULL;
  1491. for (k = 0; k < rule[cnt].lookup_cnt; ++k)
  1492. ProcessSubLookups (ttf, info, gpos, alllooks,
  1493. &rule[cnt].lookups[k]);
  1494. ++cnt;
  1495. }
  1496. }
  1497. for (i = 0; i < rcnt; ++i)
  1498. {
  1499. for (j = 0; j < rules[i].scnt; ++j)
  1500. {
  1501. free (rules[i].subrules[j].classindeces);
  1502. free (rules[i].subrules[j].sl);
  1503. }
  1504. free (rules[i].subrules);
  1505. }
  1506. free (rules);
  1507. }
  1508. static void
  1509. g___ChainingSubTable2 (FILE *ttf, int stoffset,
  1510. struct ttfinfo *info, struct lookup *l,
  1511. struct lookup_subtable *subtable, int justinuse,
  1512. struct lookup *alllooks, int gpos)
  1513. {
  1514. int i, j, k, rcnt, cnt;
  1515. uint16_t coverage, offset;
  1516. uint16_t bclassoff, classoff, fclassoff;
  1517. struct subrule
  1518. {
  1519. uint32_t offset;
  1520. int ccnt, bccnt, fccnt;
  1521. int scnt;
  1522. uint16_t *classindeces, *bci, *fci;
  1523. struct seqlookup *sl;
  1524. };
  1525. struct rule
  1526. {
  1527. uint32_t offsets;
  1528. int scnt;
  1529. struct subrule *subrules;
  1530. } *rules;
  1531. FPST *fpst;
  1532. struct fpst_rule *rule;
  1533. uint16_t *glyphs, *class;
  1534. int warned2 = false;
  1535. coverage = getushort (ttf);
  1536. bclassoff = getushort (ttf);
  1537. classoff = getushort (ttf);
  1538. fclassoff = getushort (ttf);
  1539. rcnt = getushort (ttf); /* class count *//* == max number of top level rules */
  1540. rules = xcalloc (rcnt, sizeof (struct rule));
  1541. for (i = 0; i < rcnt; ++i)
  1542. {
  1543. offset = getushort (ttf);
  1544. rules[i].offsets = offset == 0 ? 0 : offset + stoffset;
  1545. }
  1546. cnt = 0;
  1547. for (i = 0; i < rcnt; ++i)
  1548. if (rules[i].offsets != 0)
  1549. { /* some classes might be unused */
  1550. fseek (ttf, rules[i].offsets, SEEK_SET);
  1551. rules[i].scnt = getushort (ttf);
  1552. if (rules[i].scnt < 0)
  1553. {
  1554. LogError (_("Bad count in context chaining sub-table.\n"));
  1555. info->bad_ot = true;
  1556. return;
  1557. }
  1558. cnt += rules[i].scnt;
  1559. rules[i].subrules = xmalloc (rules[i].scnt * sizeof (struct subrule));
  1560. for (j = 0; j < rules[i].scnt; ++j)
  1561. rules[i].subrules[j].offset = getushort (ttf) + rules[i].offsets;
  1562. for (j = 0; j < rules[i].scnt; ++j)
  1563. {
  1564. fseek (ttf, rules[i].subrules[j].offset, SEEK_SET);
  1565. rules[i].subrules[j].bccnt = getushort (ttf);
  1566. if (rules[i].subrules[j].bccnt < 0)
  1567. {
  1568. LogError (_
  1569. ("Bad class count in contextual chaining sub-table.\n"));
  1570. info->bad_ot = true;
  1571. free (rules);
  1572. return;
  1573. }
  1574. rules[i].subrules[j].bci =
  1575. xmalloc (rules[i].subrules[j].bccnt * sizeof (uint16_t));
  1576. for (k = 0; k < rules[i].subrules[j].bccnt; ++k)
  1577. rules[i].subrules[j].bci[k] = getushort (ttf);
  1578. rules[i].subrules[j].ccnt = getushort (ttf);
  1579. if (rules[i].subrules[j].ccnt < 0)
  1580. {
  1581. LogError (_
  1582. ("Bad class count in contextual chaining sub-table.\n"));
  1583. info->bad_ot = true;
  1584. free (rules);
  1585. return;
  1586. }
  1587. rules[i].subrules[j].classindeces =
  1588. xmalloc (rules[i].subrules[j].ccnt * sizeof (uint16_t));
  1589. rules[i].subrules[j].classindeces[0] = i;
  1590. for (k = 1; k < rules[i].subrules[j].ccnt; ++k)
  1591. rules[i].subrules[j].classindeces[k] = getushort (ttf);
  1592. rules[i].subrules[j].fccnt = getushort (ttf);
  1593. if (rules[i].subrules[j].fccnt < 0)
  1594. {
  1595. LogError (_
  1596. ("Bad class count in contextual chaining sub-table.\n"));
  1597. info->bad_ot = true;
  1598. free (rules);
  1599. return;
  1600. }
  1601. rules[i].subrules[j].fci =
  1602. xmalloc (rules[i].subrules[j].fccnt * sizeof (uint16_t));
  1603. for (k = 0; k < rules[i].subrules[j].fccnt; ++k)
  1604. rules[i].subrules[j].fci[k] = getushort (ttf);
  1605. rules[i].subrules[j].scnt = getushort (ttf);
  1606. if (rules[i].subrules[j].scnt < 0)
  1607. {
  1608. LogError (_("Bad count in contextual chaining sub-table.\n"));
  1609. info->bad_ot = true;
  1610. free (rules);
  1611. return;
  1612. }
  1613. rules[i].subrules[j].sl =
  1614. xmalloc (rules[i].subrules[j].scnt * sizeof (struct seqlookup));
  1615. for (k = 0; k < rules[i].subrules[j].scnt; ++k)
  1616. {
  1617. rules[i].subrules[j].sl[k].seq = getushort (ttf);
  1618. if (rules[i].subrules[j].sl[k].seq >= rules[i].subrules[j].ccnt)
  1619. if (!warned2)
  1620. {
  1621. LogError (_
  1622. ("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d max=%d\n"),
  1623. rules[i].subrules[j].sl[k].seq,
  1624. rules[i].subrules[j].ccnt - 1);
  1625. info->bad_ot = true;
  1626. warned2 = true;
  1627. }
  1628. rules[i].subrules[j].sl[k].lookup =
  1629. (void *) (intptr_t) getushort (ttf);
  1630. }
  1631. }
  1632. }
  1633. if (justinuse == git_justinuse)
  1634. {
  1635. /* Nothing to do. This lookup doesn't really reference any glyphs */
  1636. /* any lookups it invokes will be processed on their own */
  1637. }
  1638. else
  1639. {
  1640. fpst = xzalloc (sizeof (FPST));
  1641. fpst->type = gpos ? pst_chainpos : pst_chainsub;
  1642. fpst->format = pst_class;
  1643. fpst->subtable = subtable;
  1644. subtable->fpst = fpst;
  1645. fpst->next = info->possub;
  1646. info->possub = fpst;
  1647. fpst->rules = rule = xcalloc (cnt, sizeof (struct fpst_rule));
  1648. fpst->rule_cnt = cnt;
  1649. class = getClassDefTable (ttf, stoffset + classoff, info);
  1650. fpst->nccnt = ClassFindCnt (class, info->glyph_cnt);
  1651. fpst->nclass = ClassToNames (info, fpst->nccnt, class, info->glyph_cnt);
  1652. fpst->nclassnames = xcalloc (fpst->nccnt, sizeof (char *));
  1653. /* Just in case they used the coverage table to redefine class 0 */
  1654. glyphs = getCoverageTable (ttf, stoffset + coverage, info);
  1655. if (glyphs == NULL)
  1656. {
  1657. /* TRANSLATORS: This continues a multi-line error message, hence the leading space */
  1658. LogError (_
  1659. (" Bad contextual chaining substitution table, ignored\n"));
  1660. return;
  1661. }
  1662. fpst->nclass[0] = CoverageMinusClasses (glyphs, class, info);
  1663. free (glyphs);
  1664. free (class);
  1665. class = NULL;
  1666. /* The docs don't mention this, but in mangal.ttf fclassoff==0 NULL */
  1667. if (bclassoff != 0)
  1668. class = getClassDefTable (ttf, stoffset + bclassoff, info);
  1669. else
  1670. class = xcalloc (info->glyph_cnt, sizeof (uint16_t));
  1671. fpst->bccnt = ClassFindCnt (class, info->glyph_cnt);
  1672. fpst->bclass = ClassToNames (info, fpst->bccnt, class, info->glyph_cnt);
  1673. fpst->bclassnames = xcalloc (fpst->bccnt, sizeof (char *));
  1674. free (class);
  1675. if (fclassoff != 0)
  1676. class = getClassDefTable (ttf, stoffset + fclassoff, info);
  1677. else
  1678. class = xcalloc (info->glyph_cnt, sizeof (uint16_t));
  1679. fpst->fccnt = ClassFindCnt (class, info->glyph_cnt);
  1680. fpst->fclass = ClassToNames (info, fpst->fccnt, class, info->glyph_cnt);
  1681. fpst->fclassnames = xcalloc (fpst->fccnt, sizeof (char *));
  1682. free (class);
  1683. cnt = 0;
  1684. for (i = 0; i < rcnt; ++i)
  1685. for (j = 0; j < rules[i].scnt; ++j)
  1686. {
  1687. rule[cnt].u.class.nclasses = rules[i].subrules[j].classindeces;
  1688. rule[cnt].u.class.ncnt = rules[i].subrules[j].ccnt;
  1689. rules[i].subrules[j].classindeces = NULL;
  1690. rule[cnt].u.class.bclasses = rules[i].subrules[j].bci;
  1691. rule[cnt].u.class.bcnt = rules[i].subrules[j].bccnt;
  1692. rules[i].subrules[j].bci = NULL;
  1693. rule[cnt].u.class.fclasses = rules[i].subrules[j].fci;
  1694. rule[cnt].u.class.fcnt = rules[i].subrules[j].fccnt;
  1695. rules[i].subrules[j].fci = NULL;
  1696. rule[cnt].lookup_cnt = rules[i].subrules[j].scnt;
  1697. rule[cnt].lookups = rules[i].subrules[j].sl;
  1698. rules[i].subrules[j].sl = NULL;
  1699. for (k = 0; k < rule[cnt].lookup_cnt; ++k)
  1700. ProcessSubLookups (ttf, info, gpos, alllooks,
  1701. &rule[cnt].lookups[k]);
  1702. ++cnt;
  1703. }
  1704. }
  1705. for (i = 0; i < rcnt; ++i)
  1706. {
  1707. for (j = 0; j < rules[i].scnt; ++j)
  1708. {
  1709. free (rules[i].subrules[j].classindeces);
  1710. free (rules[i].subrules[j].sl);
  1711. }
  1712. free (rules[i].subrules);
  1713. }
  1714. free (rules);
  1715. }
  1716. static void
  1717. g___ContextSubTable3 (FILE *ttf, int stoffset,
  1718. struct ttfinfo *info, struct lookup *l,
  1719. struct lookup_subtable *subtable, int justinuse,
  1720. struct lookup *alllooks, int gpos)
  1721. {
  1722. int i, k, scnt, gcnt;
  1723. uint16_t *coverage;
  1724. struct seqlookup *sl;
  1725. uint16_t *glyphs;
  1726. FPST *fpst;
  1727. struct fpst_rule *rule;
  1728. int warned2 = false;
  1729. gcnt = getushort (ttf);
  1730. scnt = getushort (ttf);
  1731. if (feof (ttf))
  1732. {
  1733. LogError (_("End of file in context chaining sub-table.\n"));
  1734. info->bad_ot = true;
  1735. return;
  1736. }
  1737. coverage = xmalloc (gcnt * sizeof (uint16_t));
  1738. for (i = 0; i < gcnt; ++i)
  1739. coverage[i] = getushort (ttf);
  1740. sl = xmalloc (scnt * sizeof (struct seqlookup));
  1741. for (k = 0; k < scnt; ++k)
  1742. {
  1743. sl[k].seq = getushort (ttf);
  1744. if (sl[k].seq >= gcnt && !warned2)
  1745. {
  1746. LogError (_
  1747. ("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d, max=%d\n"),
  1748. sl[k].seq, gcnt - 1);
  1749. info->bad_ot = true;
  1750. warned2 = true;
  1751. }
  1752. sl[k].lookup = (void *) (intptr_t) getushort (ttf);
  1753. }
  1754. if (justinuse == git_justinuse)
  1755. {
  1756. /* Nothing to do. This lookup doesn't really reference any glyphs */
  1757. /* any lookups it invokes will be processed on their own */
  1758. }
  1759. else
  1760. {
  1761. fpst = xzalloc (sizeof (FPST));
  1762. fpst->type = gpos ? pst_contextpos : pst_contextsub;
  1763. fpst->format = pst_coverage;
  1764. fpst->subtable = subtable;
  1765. subtable->fpst = fpst;
  1766. fpst->next = info->possub;
  1767. info->possub = fpst;
  1768. fpst->rules = rule = xcalloc (1, sizeof (struct fpst_rule));
  1769. fpst->rule_cnt = 1;
  1770. rule->u.coverage.ncnt = gcnt;
  1771. rule->u.coverage.ncovers = xmalloc (gcnt * sizeof (char **));
  1772. for (i = 0; i < gcnt; ++i)
  1773. {
  1774. glyphs = getCoverageTable (ttf, stoffset + coverage[i], info);
  1775. rule->u.coverage.ncovers[i] = GlyphsToNames (info, glyphs, true);
  1776. free (glyphs);
  1777. }
  1778. rule->lookup_cnt = scnt;
  1779. rule->lookups = sl;
  1780. for (k = 0; k < scnt; ++k)
  1781. ProcessSubLookups (ttf, info, gpos, alllooks, &sl[k]);
  1782. }
  1783. free (coverage);
  1784. }
  1785. static void
  1786. g___ChainingSubTable3 (FILE *ttf, int stoffset,
  1787. struct ttfinfo *info, struct lookup *l,
  1788. struct lookup_subtable *subtable, int justinuse,
  1789. struct lookup *alllooks, int gpos)
  1790. {
  1791. int i, k, scnt, gcnt, bcnt, fcnt;
  1792. uint16_t *coverage, *bcoverage, *fcoverage;
  1793. struct seqlookup *sl;
  1794. uint16_t *glyphs;
  1795. FPST *fpst;
  1796. struct fpst_rule *rule;
  1797. int warned2 = false;
  1798. bcnt = getushort (ttf);
  1799. if (feof (ttf))
  1800. {
  1801. LogError (_("End of file in context chaining subtable.\n"));
  1802. info->bad_ot = true;
  1803. return;
  1804. }
  1805. bcoverage = xmalloc (bcnt * sizeof (uint16_t));
  1806. for (i = 0; i < bcnt; ++i)
  1807. bcoverage[i] = getushort (ttf);
  1808. gcnt = getushort (ttf);
  1809. if (feof (ttf))
  1810. {
  1811. LogError (_("End of file in context chaining subtable.\n"));
  1812. info->bad_ot = true;
  1813. return;
  1814. }
  1815. coverage = xmalloc (gcnt * sizeof (uint16_t));
  1816. for (i = 0; i < gcnt; ++i)
  1817. coverage[i] = getushort (ttf);
  1818. fcnt = getushort (ttf);
  1819. if (feof (ttf))
  1820. {
  1821. LogError (_("End of file in context chaining subtable.\n"));
  1822. info->bad_ot = true;
  1823. return;
  1824. }
  1825. fcoverage = xmalloc (fcnt * sizeof (uint16_t));
  1826. for (i = 0; i < fcnt; ++i)
  1827. fcoverage[i] = getushort (ttf);
  1828. scnt = getushort (ttf);
  1829. if (feof (ttf))
  1830. {
  1831. LogError (_("End of file in context chaining subtable.\n"));
  1832. info->bad_ot = true;
  1833. return;
  1834. }
  1835. sl = xmalloc (scnt * sizeof (struct seqlookup));
  1836. for (k = 0; k < scnt; ++k)
  1837. {
  1838. sl[k].seq = getushort (ttf);
  1839. if (sl[k].seq >= gcnt && !warned2)
  1840. {
  1841. LogError (_
  1842. ("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d, max=%d\n"),
  1843. sl[k].seq, gcnt - 1);
  1844. info->bad_ot = true;
  1845. warned2 = true;
  1846. }
  1847. sl[k].lookup = (void *) (intptr_t) getushort (ttf);
  1848. }
  1849. if (justinuse == git_justinuse)
  1850. {
  1851. /* Nothing to do. This lookup doesn't really reference any glyphs */
  1852. /* any lookups it invokes will be processed on their own */
  1853. }
  1854. else
  1855. {
  1856. fpst = xzalloc (sizeof (FPST));
  1857. fpst->type = gpos ? pst_chainpos : pst_chainsub;
  1858. fpst->format = pst_coverage;
  1859. fpst->subtable = subtable;
  1860. subtable->fpst = fpst;
  1861. fpst->next = info->possub;
  1862. info->possub = fpst;
  1863. fpst->rules = rule = xcalloc (1, sizeof (struct fpst_rule));
  1864. fpst->rule_cnt = 1;
  1865. rule->u.coverage.bcnt = bcnt;
  1866. rule->u.coverage.bcovers = xmalloc (bcnt * sizeof (char **));
  1867. for (i = 0; i < bcnt; ++i)
  1868. {
  1869. glyphs = getCoverageTable (ttf, stoffset + bcoverage[i], info);
  1870. rule->u.coverage.bcovers[i] = GlyphsToNames (info, glyphs, true);
  1871. free (glyphs);
  1872. }
  1873. rule->u.coverage.ncnt = gcnt;
  1874. rule->u.coverage.ncovers = xmalloc (gcnt * sizeof (char **));
  1875. for (i = 0; i < gcnt; ++i)
  1876. {
  1877. glyphs = getCoverageTable (ttf, stoffset + coverage[i], info);
  1878. rule->u.coverage.ncovers[i] = GlyphsToNames (info, glyphs, true);
  1879. free (glyphs);
  1880. }
  1881. rule->u.coverage.fcnt = fcnt;
  1882. rule->u.coverage.fcovers = xmalloc (fcnt * sizeof (char **));
  1883. for (i = 0; i < fcnt; ++i)
  1884. {
  1885. glyphs = getCoverageTable (ttf, stoffset + fcoverage[i], info);
  1886. rule->u.coverage.fcovers[i] = GlyphsToNames (info, glyphs, true);
  1887. free (glyphs);
  1888. }
  1889. rule->lookup_cnt = scnt;
  1890. rule->lookups = sl;
  1891. for (k = 0; k < scnt; ++k)
  1892. ProcessSubLookups (ttf, info, gpos, alllooks, &sl[k]);
  1893. }
  1894. free (bcoverage);
  1895. free (coverage);
  1896. free (fcoverage);
  1897. }
  1898. static void
  1899. gposContextSubTable (FILE *ttf, int stoffset,
  1900. struct ttfinfo *info, struct lookup *l,
  1901. struct lookup_subtable *subtable, struct lookup *alllooks)
  1902. {
  1903. switch (getushort (ttf))
  1904. {
  1905. case 1:
  1906. g___ContextSubTable1 (ttf, stoffset, info, l, subtable, git_normal,
  1907. alllooks, true);
  1908. break;
  1909. case 2:
  1910. g___ContextSubTable2 (ttf, stoffset, info, l, subtable, git_normal,
  1911. alllooks, true);
  1912. break;
  1913. case 3:
  1914. g___ContextSubTable3 (ttf, stoffset, info, l, subtable, git_normal,
  1915. alllooks, true);
  1916. break;
  1917. }
  1918. }
  1919. static void
  1920. gposChainingSubTable (FILE *ttf, int stoffset,
  1921. struct ttfinfo *info, struct lookup *l,
  1922. struct lookup_subtable *subtable, struct lookup *alllooks)
  1923. {
  1924. switch (getushort (ttf))
  1925. {
  1926. case 1:
  1927. g___ChainingSubTable1 (ttf, stoffset, info, l, subtable, git_normal,
  1928. alllooks, true);
  1929. break;
  1930. case 2:
  1931. g___ChainingSubTable2 (ttf, stoffset, info, l, subtable, git_normal,
  1932. alllooks, true);
  1933. break;
  1934. case 3:
  1935. g___ChainingSubTable3 (ttf, stoffset, info, l, subtable, git_normal,
  1936. alllooks, true);
  1937. break;
  1938. }
  1939. }
  1940. static struct
  1941. {
  1942. uint32_t tag;
  1943. char *str;
  1944. } tagstr[] =
  1945. {
  1946. {
  1947. CHR ('v', 'r', 't', '2'), "vert"},
  1948. {
  1949. CHR ('s', 'm', 'c', 'p'), "sc"},
  1950. {
  1951. CHR ('s', 'm', 'c', 'p'), "small"},
  1952. {
  1953. CHR ('o', 'n', 'u', 'm'), "oldstyle"},
  1954. {
  1955. CHR ('s', 'u', 'p', 's'), "superior"},
  1956. {
  1957. CHR ('s', 'u', 'b', 's'), "inferior"},
  1958. {
  1959. CHR ('s', 'w', 's', 'h'), "swash"},
  1960. {
  1961. 0, NULL}
  1962. };
  1963. static bool
  1964. glyphNameExists (struct ttfinfo *info, char *name)
  1965. {
  1966. for (int i = 0; i < info->glyph_cnt; ++i)
  1967. if (info->chars[i] != NULL && info->chars[i]->name != NULL)
  1968. if (strcmp (info->chars[i]->name, name) == 0)
  1969. return true;
  1970. return false;
  1971. }
  1972. static void
  1973. gsubSimpleSubTable (FILE *ttf, int stoffset, struct ttfinfo *info,
  1974. struct lookup *l, struct lookup_subtable *subtable,
  1975. int justinuse)
  1976. {
  1977. int coverage, cnt, i, j, which;
  1978. uint16_t format;
  1979. uint16_t *glyphs, *glyph2s = NULL;
  1980. int delta = 0;
  1981. format = getushort (ttf);
  1982. if (format != 1 && format != 2) /* Unknown subtable format */
  1983. return;
  1984. coverage = getushort (ttf);
  1985. if (format == 1)
  1986. {
  1987. delta = getushort (ttf);
  1988. }
  1989. else
  1990. {
  1991. cnt = getushort (ttf);
  1992. glyph2s = xmalloc (cnt * sizeof (uint16_t));
  1993. for (i = 0; i < cnt; ++i)
  1994. glyph2s[i] = getushort (ttf);
  1995. /* in range check comes later */
  1996. }
  1997. glyphs = getCoverageTable (ttf, stoffset + coverage, info);
  1998. if (glyphs == NULL)
  1999. {
  2000. free (glyph2s);
  2001. LogError (_("Bad simple substitution table, ignored\n"));
  2002. return;
  2003. }
  2004. if (justinuse == git_findnames)
  2005. {
  2006. FeatureScriptLangList *fl;
  2007. fl = l->otlookup->features;
  2008. /* Unnamed glyphs get a name built of the base name and the feature tag */
  2009. /* assuming this lookup is tagged with a feature... */
  2010. if (fl != NULL)
  2011. for (i = 0; glyphs[i] != 0xffff; ++i)
  2012. if (glyphs[i] < info->glyph_cnt)
  2013. {
  2014. if (info->chars[glyphs[i]]->name != NULL)
  2015. {
  2016. which =
  2017. format == 1 ? (uint16_t) (glyphs[i] + delta) : glyph2s[i];
  2018. if (which < info->glyph_cnt && which >= 0
  2019. && info->chars[which] != NULL
  2020. && info->chars[which]->name == NULL)
  2021. {
  2022. char *basename = info->chars[glyphs[i]]->name;
  2023. char *str;
  2024. char tag[5], *pt = tag;
  2025. for (j = 0;
  2026. tagstr[j].tag != 0
  2027. && tagstr[j].tag != fl->featuretag; ++j);
  2028. if (tagstr[j].tag != 0)
  2029. pt = tagstr[j].str;
  2030. else
  2031. {
  2032. tag[0] = fl->featuretag >> 24;
  2033. if ((tag[1] = (fl->featuretag >> 16) & 0xff) == ' ')
  2034. tag[1] = '\0';
  2035. if ((tag[2] = (fl->featuretag >> 8) & 0xff) == ' ')
  2036. tag[2] = '\0';
  2037. if ((tag[3] = (fl->featuretag) & 0xff) == ' ')
  2038. tag[3] = '\0';
  2039. tag[4] = '\0';
  2040. pt = tag;
  2041. }
  2042. str = xmalloc (strlen (basename) + strlen (pt) + 2);
  2043. sprintf (str, "%s.%s", basename, pt);
  2044. if (!glyphNameExists (info, str))
  2045. info->chars[which]->name = str;
  2046. }
  2047. }
  2048. }
  2049. }
  2050. else if (justinuse == git_justinuse)
  2051. {
  2052. for (i = 0; glyphs[i] != 0xffff; ++i)
  2053. if (glyphs[i] < info->glyph_cnt)
  2054. {
  2055. info->inuse[glyphs[i]] = true;
  2056. which = format == 1 ? (uint16_t) (glyphs[i] + delta) : glyph2s[i];
  2057. info->inuse[which] = true;
  2058. }
  2059. }
  2060. else if (justinuse == git_normal)
  2061. {
  2062. for (i = 0; glyphs[i] != 0xffff; ++i)
  2063. if (glyphs[i] < info->glyph_cnt && info->chars[glyphs[i]] != NULL)
  2064. {
  2065. which = format == 1 ? (uint16_t) (glyphs[i] + delta) : glyph2s[i];
  2066. if (which >= info->glyph_cnt)
  2067. {
  2068. LogError (_("Bad substitution table. "
  2069. "Glyph %d out of range [0, %d)"),
  2070. which, info->glyph_cnt);
  2071. info->bad_ot = true;
  2072. which = 0;
  2073. }
  2074. if (info->chars[which] != NULL && info->chars[glyphs[i]] != NULL)
  2075. {
  2076. /* Might be in a ttc file */
  2077. PST *pos = xzalloc (sizeof (PST));
  2078. pos->type = pst_substitution;
  2079. pos->subtable = subtable;
  2080. pos->next = info->chars[glyphs[i]]->possub;
  2081. info->chars[glyphs[i]]->possub = pos;
  2082. pos->u.subs.variant =
  2083. xstrdup_or_null (info->chars[which]->name);
  2084. }
  2085. }
  2086. }
  2087. subtable->per_glyph_pst_or_kern = true;
  2088. free (glyph2s);
  2089. free (glyphs);
  2090. }
  2091. /* Multiple and alternate substitution lookups have the same format */
  2092. static void
  2093. gsubMultipleSubTable (FILE *ttf, int stoffset, struct ttfinfo *info,
  2094. struct lookup *l, struct lookup_subtable *subtable,
  2095. int justinuse)
  2096. {
  2097. int coverage, cnt, i, j, len, max;
  2098. uint16_t format;
  2099. uint16_t *offsets;
  2100. uint16_t *glyphs, *glyph2s;
  2101. char *pt;
  2102. int bad;
  2103. int badcnt = 0;
  2104. if (justinuse == git_findnames)
  2105. return;
  2106. format = getushort (ttf);
  2107. if (format != 1) /* Unknown subtable format */
  2108. return;
  2109. coverage = getushort (ttf);
  2110. cnt = getushort (ttf);
  2111. if (feof (ttf))
  2112. {
  2113. LogError (_("Unexpected end of file in GSUB sub-table.\n"));
  2114. info->bad_ot = true;
  2115. return;
  2116. }
  2117. offsets = xmalloc (cnt * sizeof (uint16_t));
  2118. for (i = 0; i < cnt; ++i)
  2119. offsets[i] = getushort (ttf);
  2120. glyphs = getCoverageTable (ttf, stoffset + coverage, info);
  2121. if (glyphs == NULL)
  2122. {
  2123. free (offsets);
  2124. LogError (_("Bad multiple substitution table, ignored\n"));
  2125. return;
  2126. }
  2127. for (i = 0; glyphs[i] != 0xffff; ++i);
  2128. if (i != cnt)
  2129. {
  2130. LogError (_
  2131. ("Coverage table specifies a different number of glyphs than the sub-table expects.\n"));
  2132. info->bad_ot = true;
  2133. if (cnt < i)
  2134. glyphs[cnt] = 0xffff;
  2135. else
  2136. cnt = i;
  2137. }
  2138. max = 20;
  2139. glyph2s = xmalloc (max * sizeof (uint16_t));
  2140. for (i = 0; glyphs[i] != 0xffff; ++i)
  2141. {
  2142. PST *alt;
  2143. fseek (ttf, stoffset + offsets[i], SEEK_SET);
  2144. cnt = getushort (ttf);
  2145. if (feof (ttf))
  2146. {
  2147. LogError (_("Unexpected end of file in GSUB sub-table.\n"));
  2148. info->bad_ot = true;
  2149. return;
  2150. }
  2151. if (cnt > max)
  2152. {
  2153. max = cnt + 30;
  2154. glyph2s = xrealloc (glyph2s, max * sizeof (uint16_t));
  2155. }
  2156. len = 0;
  2157. bad = false;
  2158. for (j = 0; j < cnt; ++j)
  2159. {
  2160. glyph2s[j] = getushort (ttf);
  2161. if (feof (ttf))
  2162. {
  2163. LogError (_("Unexpected end of file in GSUB sub-table.\n"));
  2164. info->bad_ot = true;
  2165. return;
  2166. }
  2167. if (glyph2s[j] >= info->glyph_cnt)
  2168. {
  2169. if (!justinuse)
  2170. LogError (_("Bad Multiple/Alternate substitution glyph. "
  2171. "Glyph %d out of range [0, %d)"),
  2172. glyph2s[j], info->glyph_cnt);
  2173. info->bad_ot = true;
  2174. if (++badcnt > 20)
  2175. return;
  2176. glyph2s[j] = 0;
  2177. }
  2178. if (justinuse == git_justinuse)
  2179. /* Do Nothing */ ;
  2180. else if (info->chars[glyph2s[j]] == NULL)
  2181. bad = true;
  2182. else
  2183. len += strlen (info->chars[glyph2s[j]]->name) + 1;
  2184. }
  2185. if (justinuse == git_justinuse)
  2186. {
  2187. info->inuse[glyphs[i]] = 1;
  2188. for (j = 0; j < cnt; ++j)
  2189. info->inuse[glyph2s[j]] = 1;
  2190. }
  2191. else if (info->chars[glyphs[i]] != NULL && !bad)
  2192. {
  2193. alt = xzalloc (sizeof (PST));
  2194. alt->type =
  2195. l->otlookup->lookup_type ==
  2196. gsub_multiple ? pst_multiple : pst_alternate;
  2197. alt->subtable = subtable;
  2198. alt->next = info->chars[glyphs[i]]->possub;
  2199. info->chars[glyphs[i]]->possub = alt;
  2200. pt = alt->u.subs.variant = xmalloc (len + 1);
  2201. *pt = '\0';
  2202. for (j = 0; j < cnt; ++j)
  2203. {
  2204. strcat (pt, info->chars[glyph2s[j]]->name);
  2205. strcat (pt, " ");
  2206. }
  2207. if (*pt != '\0' && pt[strlen (pt) - 1] == ' ')
  2208. pt[strlen (pt) - 1] = '\0';
  2209. }
  2210. }
  2211. subtable->per_glyph_pst_or_kern = true;
  2212. free (glyphs);
  2213. free (glyph2s);
  2214. free (offsets);
  2215. }
  2216. static void
  2217. gsubLigatureSubTable (FILE *ttf, int stoffset,
  2218. struct ttfinfo *info, struct lookup *l,
  2219. struct lookup_subtable *subtable, int justinuse)
  2220. {
  2221. int coverage, cnt, i, j, k, lig_cnt, cc, len;
  2222. uint16_t *ls_offsets, *lig_offsets;
  2223. uint16_t *glyphs, *lig_glyphs, lig;
  2224. char *pt;
  2225. PST *liga;
  2226. /* Format = */ getushort (ttf);
  2227. coverage = getushort (ttf);
  2228. cnt = getushort (ttf);
  2229. if (feof (ttf))
  2230. {
  2231. LogError (_("Unexpected end of file in GSUB ligature sub-table.\n"));
  2232. info->bad_ot = true;
  2233. return;
  2234. }
  2235. ls_offsets = xmalloc (cnt * sizeof (uint16_t));
  2236. for (i = 0; i < cnt; ++i)
  2237. ls_offsets[i] = getushort (ttf);
  2238. glyphs = getCoverageTable (ttf, stoffset + coverage, info);
  2239. if (glyphs == NULL)
  2240. {
  2241. LogError (_("Bad ligature table, ignored\n"));
  2242. return;
  2243. }
  2244. for (i = 0; i < cnt; ++i)
  2245. {
  2246. fseek (ttf, stoffset + ls_offsets[i], SEEK_SET);
  2247. lig_cnt = getushort (ttf);
  2248. if (feof (ttf))
  2249. {
  2250. LogError (_("Unexpected end of file in GSUB ligature sub-table.\n"));
  2251. info->bad_ot = true;
  2252. return;
  2253. }
  2254. lig_offsets = xmalloc (lig_cnt * sizeof (uint16_t));
  2255. for (j = 0; j < lig_cnt; ++j)
  2256. lig_offsets[j] = getushort (ttf);
  2257. if (feof (ttf))
  2258. {
  2259. LogError (_("Unexpected end of file in GSUB ligature sub-table.\n"));
  2260. info->bad_ot = true;
  2261. return;
  2262. }
  2263. for (j = 0; j < lig_cnt; ++j)
  2264. {
  2265. fseek (ttf, stoffset + ls_offsets[i] + lig_offsets[j], SEEK_SET);
  2266. lig = getushort (ttf);
  2267. if (lig >= info->glyph_cnt)
  2268. {
  2269. LogError (_("Bad ligature glyph. Glyph %d out of range [0, %d)"),
  2270. lig, info->glyph_cnt);
  2271. info->bad_ot = true;
  2272. lig = 0;
  2273. }
  2274. cc = getushort (ttf);
  2275. if (cc < 0 || cc > 100)
  2276. {
  2277. LogError (_("Unlikely count of ligature components (%d), "
  2278. "I suspect this ligature sub-\n"
  2279. "table is garbage, I'm giving up on it."),
  2280. cc);
  2281. info->bad_ot = true;
  2282. free (glyphs);
  2283. free (lig_offsets);
  2284. return;
  2285. }
  2286. lig_glyphs = xmalloc (cc * sizeof (uint16_t));
  2287. lig_glyphs[0] = glyphs[i];
  2288. for (k = 1; k < cc; ++k)
  2289. {
  2290. lig_glyphs[k] = getushort (ttf);
  2291. if (lig_glyphs[k] >= info->glyph_cnt)
  2292. {
  2293. if (justinuse == git_normal)
  2294. LogError (_("Bad ligature component glyph. "
  2295. "Glyph %d out of range [0, %d) "
  2296. "(in ligature %d)"),
  2297. lig_glyphs[k], info->glyph_cnt, lig);
  2298. info->bad_ot = true;
  2299. lig_glyphs[k] = 0;
  2300. }
  2301. }
  2302. if (justinuse == git_justinuse)
  2303. {
  2304. info->inuse[lig] = 1;
  2305. for (k = 0; k < cc; ++k)
  2306. info->inuse[lig_glyphs[k]] = 1;
  2307. }
  2308. else if (justinuse == git_findnames)
  2309. {
  2310. FeatureScriptLangList *fl = l->otlookup->features;
  2311. /* If our ligature glyph has no name (and its components do) */
  2312. /* give it a name by concatenating components with underscores */
  2313. /* between them, and appending the tag */
  2314. if (fl != NULL && info->chars[lig] != NULL
  2315. && info->chars[lig]->name == NULL)
  2316. {
  2317. int len = 0;
  2318. for (k = 0; k < cc; ++k)
  2319. {
  2320. if (info->chars[lig_glyphs[k]] == NULL
  2321. || info->chars[lig_glyphs[k]]->name == NULL)
  2322. break;
  2323. len += strlen (info->chars[lig_glyphs[k]]->name) + 1;
  2324. }
  2325. if (k == cc)
  2326. {
  2327. char *str = xmalloc (len + 6), *pt;
  2328. char tag[5];
  2329. tag[0] = fl->featuretag >> 24;
  2330. if ((tag[1] = (fl->featuretag >> 16) & 0xff) == ' ')
  2331. tag[1] = '\0';
  2332. if ((tag[2] = (fl->featuretag >> 8) & 0xff) == ' ')
  2333. tag[2] = '\0';
  2334. if ((tag[3] = (fl->featuretag) & 0xff) == ' ')
  2335. tag[3] = '\0';
  2336. tag[4] = '\0';
  2337. *str = '\0';
  2338. for (k = 0; k < cc; ++k)
  2339. {
  2340. strcat (str, info->chars[lig_glyphs[k]]->name);
  2341. strcat (str, "_");
  2342. }
  2343. pt = str + strlen (str);
  2344. pt[-1] = '.';
  2345. strcpy (pt, tag);
  2346. if (!glyphNameExists (info, str))
  2347. info->chars[lig]->name = str;
  2348. }
  2349. }
  2350. }
  2351. else if (info->chars[lig] != NULL)
  2352. {
  2353. int err = false;
  2354. for (k = len = 0; k < cc; ++k)
  2355. if (lig_glyphs[k] < info->glyph_cnt &&
  2356. info->chars[lig_glyphs[k]] != NULL)
  2357. len += strlen (info->chars[lig_glyphs[k]]->name) + 1;
  2358. else
  2359. err = true;
  2360. if (!err)
  2361. {
  2362. liga = xzalloc (sizeof (PST));
  2363. liga->type = pst_ligature;
  2364. liga->subtable = subtable;
  2365. liga->next = info->chars[lig]->possub;
  2366. info->chars[lig]->possub = liga;
  2367. liga->u.lig.lig = info->chars[lig];
  2368. liga->u.lig.components = pt = xmalloc (len);
  2369. for (k = 0; k < cc; ++k)
  2370. {
  2371. if (lig_glyphs[k] < info->glyph_cnt &&
  2372. info->chars[lig_glyphs[k]] != NULL)
  2373. {
  2374. strcpy (pt, info->chars[lig_glyphs[k]]->name);
  2375. pt += strlen (pt);
  2376. *pt++ = ' ';
  2377. }
  2378. }
  2379. pt[-1] = '\0';
  2380. }
  2381. }
  2382. free (lig_glyphs);
  2383. }
  2384. free (lig_offsets);
  2385. }
  2386. subtable->per_glyph_pst_or_kern = true;
  2387. free (ls_offsets);
  2388. free (glyphs);
  2389. }
  2390. static void
  2391. gsubContextSubTable (FILE *ttf, int stoffset,
  2392. struct ttfinfo *info, struct lookup *l,
  2393. struct lookup_subtable *subtable, int justinuse,
  2394. struct lookup *alllooks)
  2395. {
  2396. if (justinuse == git_findnames)
  2397. return; /* Don't give names to these guys, they might not be unique */
  2398. /* ie. because these are context based there is not a one to one */
  2399. /* mapping between input glyphs and output glyphs. One input glyph */
  2400. /* may go to several output glyphs (depending on context) and so */
  2401. /* <input-glyph-name>"."<tag-name> would be used for several glyphs */
  2402. switch (getushort (ttf))
  2403. {
  2404. case 1:
  2405. g___ContextSubTable1 (ttf, stoffset, info, l, subtable, justinuse,
  2406. alllooks, false);
  2407. break;
  2408. case 2:
  2409. g___ContextSubTable2 (ttf, stoffset, info, l, subtable, justinuse,
  2410. alllooks, false);
  2411. break;
  2412. case 3:
  2413. g___ContextSubTable3 (ttf, stoffset, info, l, subtable, justinuse,
  2414. alllooks, false);
  2415. break;
  2416. }
  2417. }
  2418. static void
  2419. gsubChainingSubTable (FILE *ttf, int stoffset,
  2420. struct ttfinfo *info, struct lookup *l,
  2421. struct lookup_subtable *subtable, int justinuse,
  2422. struct lookup *alllooks)
  2423. {
  2424. if (justinuse == git_findnames)
  2425. return; /* Don't give names to these guys, the names might not be unique */
  2426. switch (getushort (ttf))
  2427. {
  2428. case 1:
  2429. g___ChainingSubTable1 (ttf, stoffset, info, l, subtable, justinuse,
  2430. alllooks, false);
  2431. break;
  2432. case 2:
  2433. g___ChainingSubTable2 (ttf, stoffset, info, l, subtable, justinuse,
  2434. alllooks, false);
  2435. break;
  2436. case 3:
  2437. g___ChainingSubTable3 (ttf, stoffset, info, l, subtable, justinuse,
  2438. alllooks, false);
  2439. break;
  2440. }
  2441. }
  2442. static void
  2443. gsubReverseChainSubTable (FILE *ttf, int stoffset,
  2444. struct ttfinfo *info, struct lookup *l,
  2445. struct lookup_subtable *subtable, int justinuse)
  2446. {
  2447. int scnt, bcnt, fcnt, i;
  2448. uint16_t coverage, *bcoverage, *fcoverage, *sglyphs, *glyphs;
  2449. FPST *fpst;
  2450. struct fpst_rule *rule;
  2451. if (justinuse == git_findnames)
  2452. return; /* Don't give names to these guys, they might not be unique */
  2453. if (getushort (ttf) != 1)
  2454. return; /* Don't understand this format type */
  2455. coverage = getushort (ttf);
  2456. bcnt = getushort (ttf);
  2457. bcoverage = xmalloc (bcnt * sizeof (uint16_t));
  2458. for (i = 0; i < bcnt; ++i)
  2459. bcoverage[i] = getushort (ttf);
  2460. fcnt = getushort (ttf);
  2461. fcoverage = xmalloc (fcnt * sizeof (uint16_t));
  2462. for (i = 0; i < fcnt; ++i)
  2463. fcoverage[i] = getushort (ttf);
  2464. scnt = getushort (ttf);
  2465. sglyphs = xmalloc ((scnt + 1) * sizeof (uint16_t));
  2466. for (i = 0; i < scnt; ++i)
  2467. if ((sglyphs[i] = getushort (ttf)) >= info->glyph_cnt)
  2468. {
  2469. LogError (_("Bad reverse contextual chaining substitution table. "
  2470. "Glyph %d out of range [0, %d)"),
  2471. sglyphs[i], info->glyph_cnt);
  2472. info->bad_ot = true;
  2473. sglyphs[i] = 0;
  2474. }
  2475. sglyphs[i] = 0xffff;
  2476. if (justinuse == git_justinuse)
  2477. {
  2478. for (i = 0; i < scnt; ++i)
  2479. info->inuse[sglyphs[i]] = 1;
  2480. }
  2481. else
  2482. {
  2483. fpst = xzalloc (sizeof (FPST));
  2484. fpst->type = pst_reversesub;
  2485. fpst->format = pst_reversecoverage;
  2486. fpst->subtable = subtable;
  2487. fpst->next = info->possub;
  2488. info->possub = fpst;
  2489. subtable->fpst = fpst;
  2490. fpst->rules = rule = xcalloc (1, sizeof (struct fpst_rule));
  2491. fpst->rule_cnt = 1;
  2492. rule->u.rcoverage.always1 = 1;
  2493. rule->u.rcoverage.bcnt = bcnt;
  2494. rule->u.rcoverage.fcnt = fcnt;
  2495. rule->u.rcoverage.ncovers = xmalloc (sizeof (char *));
  2496. rule->u.rcoverage.bcovers = xmalloc (bcnt * sizeof (char *));
  2497. rule->u.rcoverage.fcovers = xmalloc (fcnt * sizeof (char *));
  2498. rule->u.rcoverage.replacements = GlyphsToNames (info, sglyphs, false);
  2499. glyphs = getCoverageTable (ttf, stoffset + coverage, info);
  2500. rule->u.rcoverage.ncovers[0] = GlyphsToNames (info, glyphs, false);
  2501. free (glyphs);
  2502. for (i = 0; i < bcnt; ++i)
  2503. {
  2504. glyphs = getCoverageTable (ttf, stoffset + bcoverage[i], info);
  2505. rule->u.rcoverage.bcovers[i] = GlyphsToNames (info, glyphs, true);
  2506. free (glyphs);
  2507. }
  2508. for (i = 0; i < fcnt; ++i)
  2509. {
  2510. glyphs = getCoverageTable (ttf, stoffset + fcoverage[i], info);
  2511. rule->u.rcoverage.fcovers[i] = GlyphsToNames (info, glyphs, true);
  2512. free (glyphs);
  2513. }
  2514. rule->lookup_cnt = 0; /* substitution lookups needed for reverse chaining */
  2515. }
  2516. free (sglyphs);
  2517. free (fcoverage);
  2518. free (bcoverage);
  2519. }
  2520. static void
  2521. readttfsizeparameters (FILE *ttf, int32_t broken_pos, int32_t correct_pos,
  2522. struct ttfinfo *info)
  2523. {
  2524. int32_t here;
  2525. /* Both of the two fonts I've seen that contain a 'size' feature */
  2526. /* have multiple features all of which point to the same parameter */
  2527. /* area. Odd. */
  2528. /* When Adobe first released fonts containing the 'size' feature */
  2529. /* they did not follow the spec, and the offset to the size parameters */
  2530. /* was relative to the wrong location. They claim (Aug 2006) that */
  2531. /* this has been fixed. Be prepared to read either style of 'size' */
  2532. /* following the heuristics Adobe provides */
  2533. int32_t test[2];
  2534. int i, nid;
  2535. if (info->last_size_pos == broken_pos || info->last_size_pos == correct_pos)
  2536. return;
  2537. if (info->last_size_pos != 0)
  2538. {
  2539. LogError (_
  2540. ("This font, %s, has multiple GPOS 'size' features. I'm not sure how to interpret that. I shall pick one arbitrarily.\n"),
  2541. info->fontname == NULL ? _("<Untitled>") : info->fontname);
  2542. info->bad_ot = true;
  2543. return;
  2544. }
  2545. test[0] = correct_pos;
  2546. test[1] = broken_pos;
  2547. here = ftell (ttf);
  2548. for (i = 0; i < 2; ++i)
  2549. {
  2550. fseek (ttf, test[i], SEEK_SET);
  2551. info->last_size_pos = test[i];
  2552. info->design_size = getushort (ttf);
  2553. if (info->design_size == 0)
  2554. continue;
  2555. info->fontstyle_id = getushort (ttf);
  2556. nid = getushort (ttf);
  2557. info->design_range_bottom = getushort (ttf);
  2558. info->design_range_top = getushort (ttf);
  2559. if (info->fontstyle_id == 0 && nid == 0 && info->design_size != 0 &&
  2560. info->design_range_bottom == 0 && info->design_range_top == 0)
  2561. {
  2562. /* Reasonable spec, only design size provided */
  2563. info->fontstyle_name = NULL;
  2564. break;
  2565. }
  2566. if (info->design_size == 0 ||
  2567. info->design_size < info->design_range_bottom ||
  2568. info->design_size > info->design_range_top ||
  2569. info->design_range_bottom > info->design_range_top)
  2570. continue;
  2571. if (info->fontstyle_id == 0 && nid == 0)
  2572. {
  2573. /* Not really allowed, but we'll accept it anyway */
  2574. /* If a range is provided than a style name is expected */
  2575. LogError (_
  2576. ("This font contains a 'size' feature with a design size and design range but no stylename. That is technically an error, but we'll let it pass"));
  2577. info->fontstyle_name = NULL;
  2578. break;
  2579. }
  2580. if (nid < 256 || nid > 32767)
  2581. continue;
  2582. info->fontstyle_name = FindAllLangEntries (ttf, info, nid);
  2583. if (info->fontstyle_name == NULL)
  2584. continue;
  2585. else
  2586. break;
  2587. }
  2588. if (i == 2)
  2589. {
  2590. LogError (_
  2591. ("The 'size' feature does not seem to follow the standard,\nnor does it conform to Adobe's early misinterpretation of\nthe standard. I cannot parse it.\n"));
  2592. info->bad_ot = true;
  2593. info->design_size = info->design_range_bottom = info->design_range_top =
  2594. info->fontstyle_id = 0;
  2595. info->fontstyle_name = NULL;
  2596. }
  2597. else if (i == 1)
  2598. {
  2599. LogError (_
  2600. ("The 'size' feature of this font conforms to Adobe's early misinterpretation of the otf standard.\n"));
  2601. }
  2602. fseek (ttf, here, SEEK_SET);
  2603. #if 0
  2604. printf ("pos=%d size=%g, range=(%g,%g] id=%d name=%d\n", pos,
  2605. info->design_size / 10.0, info->design_range_bottom / 10.0,
  2606. info->design_range_top / 10.0, info->fontstyle_id,
  2607. info->fontstyle_name);
  2608. #endif
  2609. }
  2610. static void
  2611. readttffeatnameparameters (FILE *ttf, int32_t pos, uint32_t tag,
  2612. struct ttfinfo *info)
  2613. {
  2614. int version, nid;
  2615. struct otffeatname *fn;
  2616. uint32_t here;
  2617. here = ftell (ttf);
  2618. fseek (ttf, pos, SEEK_SET);
  2619. version = getushort (ttf); /* Minor version #, currently (2009) 0 */
  2620. nid = getushort (ttf);
  2621. fseek (ttf, here, SEEK_SET);
  2622. if (version >= 10 || nid < 256 || nid > 32767)
  2623. {
  2624. if (nid < 256 || nid > 32767)
  2625. LogError (_
  2626. ("The name parameter of the '%c%c%c%c' feature does not contain a valid name id.\n"),
  2627. tag >> 24, tag >> 16, tag >> 8, tag);
  2628. else
  2629. LogError (_
  2630. ("The name parameter of the '%c%c%c%c' feature has an unlikely version number %d.\n"),
  2631. tag >> 24, tag >> 16, tag >> 8, tag, version);
  2632. info->bad_ot = true;
  2633. return;
  2634. }
  2635. for (fn = info->feat_names; fn != NULL && fn->tag != tag; fn = fn->next);
  2636. if (fn != NULL)
  2637. {
  2638. if (fn->nid == nid)
  2639. return;
  2640. LogError (_
  2641. ("There are multiple name ids naming the '%c%c%c%c' feature\n this is technically legitimate, but fontforge can't handle it.\n"),
  2642. tag >> 24, tag >> 16, tag >> 8, tag);
  2643. return;
  2644. }
  2645. fn = xzalloc (sizeof (*fn));
  2646. fn->tag = tag;
  2647. fn->nid = nid;
  2648. fn->next = info->feat_names;
  2649. info->feat_names = fn;
  2650. fn->names = FindAllLangEntries (ttf, info, nid);
  2651. }
  2652. static struct scripts *
  2653. readttfscripts (FILE *ttf, int32_t pos, struct ttfinfo *info, int isgpos)
  2654. {
  2655. int i, j, k, cnt;
  2656. int deflang, lcnt;
  2657. struct scripts *scripts;
  2658. if (pos >= info->g_bounds)
  2659. {
  2660. LogError (_("Attempt to read script data beyond end of %s table"),
  2661. isgpos ? "GPOS" : "GSUB");
  2662. info->bad_ot = true;
  2663. return NULL;
  2664. }
  2665. fseek (ttf, pos, SEEK_SET);
  2666. cnt = getushort (ttf);
  2667. if (cnt <= 0)
  2668. return NULL;
  2669. else if (cnt > 1000)
  2670. {
  2671. LogError (_("Too many scripts %d\n"), cnt);
  2672. info->bad_ot = true;
  2673. return NULL;
  2674. }
  2675. scripts = xcalloc (cnt + 1, sizeof (struct scripts));
  2676. for (i = 0; i < cnt; ++i)
  2677. {
  2678. scripts[i].tag = getlong (ttf);
  2679. scripts[i].offset = getushort (ttf);
  2680. }
  2681. for (i = 0; i < cnt; ++i)
  2682. {
  2683. fseek (ttf, pos + scripts[i].offset, SEEK_SET);
  2684. deflang = getushort (ttf);
  2685. lcnt = getushort (ttf);
  2686. lcnt += (deflang != 0);
  2687. scripts[i].langcnt = lcnt;
  2688. scripts[i].languages = xcalloc (lcnt + 1, sizeof (struct language));
  2689. j = 0;
  2690. if (deflang != 0)
  2691. {
  2692. scripts[i].languages[0].tag = CHR ('d', 'f', 'l', 't');
  2693. scripts[i].languages[0].offset = deflang + scripts[i].offset;
  2694. ++j;
  2695. }
  2696. for (; j < lcnt; ++j)
  2697. {
  2698. scripts[i].languages[j].tag = getlong (ttf);
  2699. scripts[i].languages[j].offset = scripts[i].offset + getushort (ttf);
  2700. }
  2701. for (j = 0; j < lcnt; ++j)
  2702. {
  2703. if (pos + scripts[i].languages[j].offset >= info->g_bounds)
  2704. {
  2705. LogError (_("Attempt to read script data beyond end of %s table"),
  2706. isgpos ? "GPOS" : "GSUB");
  2707. info->bad_ot = true;
  2708. return NULL;
  2709. }
  2710. fseek (ttf, pos + scripts[i].languages[j].offset, SEEK_SET);
  2711. (void) getushort (ttf); /* lookup ordering table undefined */
  2712. scripts[i].languages[j].req = getushort (ttf);
  2713. scripts[i].languages[j].fcnt = getushort (ttf);
  2714. if (feof (ttf))
  2715. {
  2716. LogError (_("End of file when reading scripts in %s table"),
  2717. isgpos ? "GPOS" : "GSUB");
  2718. info->bad_ot = true;
  2719. return NULL;
  2720. }
  2721. scripts[i].languages[j].features =
  2722. xmalloc (scripts[i].languages[j].fcnt * sizeof (uint16_t));
  2723. for (k = 0; k < scripts[i].languages[j].fcnt; ++k)
  2724. scripts[i].languages[j].features[k] = getushort (ttf);
  2725. }
  2726. }
  2727. if (feof (ttf))
  2728. {
  2729. LogError (_("End of file in %s table"), isgpos ? "GPOS" : "GSUB");
  2730. info->bad_ot = true;
  2731. return NULL;
  2732. }
  2733. return scripts;
  2734. }
  2735. static struct feature *
  2736. readttffeatures (FILE *ttf, int32_t pos, int isgpos, struct ttfinfo *info)
  2737. {
  2738. /* read the features table returning an array containing all interesting */
  2739. /* features */
  2740. int cnt;
  2741. int i, j;
  2742. struct feature *features;
  2743. int parameters;
  2744. if (pos >= info->g_bounds)
  2745. {
  2746. LogError (_("Attempt to read feature data beyond end of %s table"),
  2747. isgpos ? "GPOS" : "GSUB");
  2748. info->bad_ot = true;
  2749. return NULL;
  2750. }
  2751. fseek (ttf, pos, SEEK_SET);
  2752. info->feature_cnt = cnt = getushort (ttf);
  2753. if (cnt <= 0)
  2754. return NULL;
  2755. else if (cnt > 1000)
  2756. {
  2757. LogError (_("Too many features %d\n"), cnt);
  2758. info->bad_ot = true;
  2759. return NULL;
  2760. }
  2761. features = xcalloc (cnt + 1, sizeof (struct feature));
  2762. for (i = 0; i < cnt; ++i)
  2763. {
  2764. features[i].tag = getlong (ttf);
  2765. features[i].offset = getushort (ttf);
  2766. }
  2767. for (i = 0; i < cnt; ++i)
  2768. {
  2769. if (pos + features[i].offset >= info->g_bounds)
  2770. {
  2771. LogError (_("Attempt to read feature data beyond end of %s table"),
  2772. isgpos ? "GPOS" : "GSUB");
  2773. info->bad_ot = true;
  2774. return NULL;
  2775. }
  2776. fseek (ttf, pos + features[i].offset, SEEK_SET);
  2777. parameters = getushort (ttf);
  2778. if (features[i].tag == CHR ('s', 'i', 'z', 'e') && parameters != 0
  2779. && !feof (ttf))
  2780. {
  2781. readttfsizeparameters (ttf, pos + parameters,
  2782. pos + parameters + features[i].offset, info);
  2783. }
  2784. else if (features[i].tag >= CHR ('s', 's', '0', '1')
  2785. && features[i].tag <= CHR ('s', 's', '2', '0') && parameters != 0
  2786. && !feof (ttf))
  2787. {
  2788. readttffeatnameparameters (ttf, pos + parameters + features[i].offset,
  2789. features[i].tag, info);
  2790. }
  2791. features[i].lcnt = getushort (ttf);
  2792. if (feof (ttf))
  2793. {
  2794. LogError (_("End of file when reading features in %s table"),
  2795. isgpos ? "GPOS" : "GSUB");
  2796. info->bad_ot = true;
  2797. return NULL;
  2798. }
  2799. features[i].lookups = xmalloc (features[i].lcnt * sizeof (uint16_t));
  2800. for (j = 0; j < features[i].lcnt; ++j)
  2801. features[i].lookups[j] = getushort (ttf);
  2802. }
  2803. return features;
  2804. }
  2805. static struct lookup *
  2806. readttflookups (FILE *ttf, int32_t pos, struct ttfinfo *info, int isgpos)
  2807. {
  2808. int cnt, i, j;
  2809. struct lookup *lookups;
  2810. OTLookup *otlookup, *last = NULL;
  2811. struct lookup_subtable *st;
  2812. if (pos >= info->g_bounds)
  2813. {
  2814. LogError (_("Attempt to read lookup data beyond end of %s table"),
  2815. isgpos == 2 ? "JSTF" : isgpos ? "GPOS" : "GSUB");
  2816. info->bad_ot = true;
  2817. return NULL;
  2818. }
  2819. fseek (ttf, pos, SEEK_SET);
  2820. info->lookup_cnt = cnt = getushort (ttf);
  2821. info->cur_lookups = NULL;
  2822. if (cnt <= 0)
  2823. return NULL;
  2824. else if (cnt > 1000)
  2825. {
  2826. LogError (_("Too many lookups %d\n"), cnt);
  2827. info->bad_ot = true;
  2828. return NULL;
  2829. }
  2830. lookups = xcalloc (cnt + 1, sizeof (struct lookup));
  2831. for (i = 0; i < cnt; ++i)
  2832. lookups[i].offset = getushort (ttf);
  2833. for (i = 0; i < cnt; ++i)
  2834. {
  2835. if (pos + lookups[i].offset >= info->g_bounds)
  2836. {
  2837. LogError (_("Attempt to read lookup data beyond end of %s table"),
  2838. isgpos == 2 ? "JSTF" : isgpos ? "GPOS" : "GSUB");
  2839. info->bad_ot = true;
  2840. return NULL;
  2841. }
  2842. fseek (ttf, pos + lookups[i].offset, SEEK_SET);
  2843. lookups[i].type = getushort (ttf);
  2844. lookups[i].flags = getushort (ttf);
  2845. lookups[i].subtabcnt = getushort (ttf);
  2846. lookups[i].subtab_offsets =
  2847. xmalloc (lookups[i].subtabcnt * sizeof (int32_t));
  2848. for (j = 0; j < lookups[i].subtabcnt; ++j)
  2849. lookups[i].subtab_offsets[j] =
  2850. pos + lookups[i].offset + getushort (ttf);
  2851. if (lookups[i].flags & pst_usemarkfilteringset)
  2852. lookups[i].flags |= (getushort (ttf) << 16);
  2853. lookups[i].otlookup = otlookup = xzalloc (sizeof (OTLookup));
  2854. otlookup->lookup_index = i;
  2855. if (last == NULL)
  2856. info->cur_lookups = otlookup;
  2857. else
  2858. last->next = otlookup;
  2859. last = otlookup;
  2860. otlookup->lookup_type = ((isgpos > 0) << 8) | lookups[i].type;
  2861. otlookup->lookup_flags = lookups[i].flags;
  2862. otlookup->lookup_index = i;
  2863. if (feof (ttf))
  2864. {
  2865. LogError (_("End of file when reading lookups in %s table"),
  2866. isgpos ? "GPOS" : "GSUB");
  2867. info->bad_ot = true;
  2868. return NULL;
  2869. }
  2870. for (j = 0; j < lookups[i].subtabcnt; ++j)
  2871. {
  2872. st =
  2873. (struct lookup_subtable *)
  2874. xzalloc (sizeof (struct lookup_subtable));
  2875. st->next = otlookup->subtables;
  2876. st->lookup = otlookup;
  2877. otlookup->subtables = st;
  2878. }
  2879. }
  2880. if (isgpos == 2)
  2881. {
  2882. OTLookup *end;
  2883. /* Add any JSTF lookups to the end of the GPOS list. they have the */
  2884. /* same format, we'll treat them as GPOS internally, and separate */
  2885. /* them out when we generate the new font */
  2886. if (info->gpos_lookups == NULL)
  2887. info->gpos_lookups = info->cur_lookups;
  2888. else
  2889. {
  2890. for (end = info->gpos_lookups; end->next != NULL; end = end->next);
  2891. end->next = info->cur_lookups;
  2892. }
  2893. }
  2894. else if (isgpos)
  2895. info->gpos_lookups = info->cur_lookups;
  2896. else
  2897. info->gsub_lookups = info->cur_lookups;
  2898. return lookups;
  2899. }
  2900. static void
  2901. tagLookupsWithFeature (uint32_t script_tag, uint32_t lang_tag,
  2902. int required_feature, struct feature *feature,
  2903. struct lookup *lookups, struct ttfinfo *info)
  2904. {
  2905. uint32_t feature_tag = required_feature ? REQUIRED_FEATURE : feature->tag;
  2906. int i;
  2907. OTLookup *otlookup;
  2908. FeatureScriptLangList *fl;
  2909. /* The otf docs are ambiguous as to the capitalization of the default */
  2910. /* script. The capitalized version is correct (uncapitalized is used for languages) */
  2911. if (script_tag == DEFAULT_LANG)
  2912. script_tag = DEFAULT_SCRIPT;
  2913. for (i = 0; i < feature->lcnt; ++i)
  2914. {
  2915. if (feature->lookups[i] >= info->lookup_cnt)
  2916. {
  2917. LogError (_("Lookup out of bounds in feature table.\n"));
  2918. info->bad_ot = true;
  2919. }
  2920. else
  2921. {
  2922. otlookup = lookups[feature->lookups[i]].otlookup;
  2923. for (fl = otlookup->features;
  2924. fl != NULL && fl->featuretag != feature_tag; fl = fl->next);
  2925. if (fl == NULL)
  2926. {
  2927. fl =
  2928. (FeatureScriptLangList *)
  2929. xzalloc (sizeof (FeatureScriptLangList));
  2930. fl->featuretag = feature_tag;
  2931. fl->next = otlookup->features;
  2932. otlookup->features = fl;
  2933. }
  2934. FListAppendScriptLang (fl, script_tag, lang_tag);
  2935. }
  2936. }
  2937. }
  2938. static void
  2939. tagLookupsWithScript (struct scripts *scripts,
  2940. struct feature *features, struct lookup *lookups,
  2941. struct ttfinfo *info)
  2942. {
  2943. int i, j;
  2944. struct scripts *s;
  2945. struct language *lang;
  2946. struct lookup *l;
  2947. if (scripts == NULL || features == NULL)
  2948. return; /* Legal, I'd guess, but not very interesting. Perhaps all lookups are controlled by the JSTF table or something */
  2949. /* First tag every lookup with all script, lang, feature combinations that */
  2950. /* invoke it */
  2951. for (s = scripts; s->tag != 0; ++s)
  2952. {
  2953. for (lang = s->languages, i = 0; i < s->langcnt; ++i, ++lang)
  2954. {
  2955. if (lang->req == 0xffff)
  2956. /* Do Nothing */ ;
  2957. else if (lang->req >= info->feature_cnt)
  2958. {
  2959. LogError (_("Required feature out of bounds in script table.\n"));
  2960. info->bad_ot = true;
  2961. }
  2962. else
  2963. tagLookupsWithFeature (s->tag, lang->tag, true,
  2964. &features[lang->req], lookups, info);
  2965. for (j = 0; j < lang->fcnt; ++j)
  2966. {
  2967. if (lang->features[j] >= info->feature_cnt)
  2968. {
  2969. LogError (_("Feature out of bounds in script table.\n"));
  2970. info->bad_ot = true;
  2971. }
  2972. else
  2973. tagLookupsWithFeature (s->tag, lang->tag, false,
  2974. &features[lang->features[j]], lookups,
  2975. info);
  2976. }
  2977. }
  2978. }
  2979. /* The scripts got added backwards so reverse to put them in */
  2980. /* alphabetic order again */
  2981. for (l = lookups, i = 0; l->offset != 0; ++l, ++i)
  2982. {
  2983. OTLookup *otl = l->otlookup;
  2984. FeatureScriptLangList *fl;
  2985. struct scriptlanglist *sl, *next, *prev;
  2986. for (fl = otl->features; fl != NULL; fl = fl->next)
  2987. {
  2988. prev = NULL;
  2989. for (sl = fl->scripts; sl != NULL; sl = next)
  2990. {
  2991. next = sl->next;
  2992. sl->next = prev;
  2993. prev = sl;
  2994. }
  2995. fl->scripts = prev;
  2996. }
  2997. }
  2998. }
  2999. static void
  3000. gposExtensionSubTable (FILE *ttf, int stoffset,
  3001. struct ttfinfo *info, struct lookup *l,
  3002. struct lookup_subtable *subtable,
  3003. struct lookup *alllooks)
  3004. {
  3005. uint32_t base = ftell (ttf), st, offset;
  3006. int lu_type;
  3007. /* Format = */ getushort (ttf);
  3008. lu_type = getushort (ttf);
  3009. offset = getlong (ttf);
  3010. l->otlookup->lookup_type = 0x100 | lu_type;
  3011. fseek (ttf, st = base + offset, SEEK_SET);
  3012. switch (lu_type)
  3013. {
  3014. case 1:
  3015. gposSimplePos (ttf, st, info, l, subtable);
  3016. break;
  3017. case 2:
  3018. gposKernSubTable (ttf, st, info, l, subtable);
  3019. break;
  3020. case 3:
  3021. gposCursiveSubTable (ttf, st, info, l, subtable);
  3022. break;
  3023. case 4:
  3024. case 5:
  3025. case 6:
  3026. gposMarkSubTable (ttf, st, info, l, subtable);
  3027. break;
  3028. case 7:
  3029. gposContextSubTable (ttf, st, info, l, subtable, alllooks);
  3030. break;
  3031. case 8:
  3032. gposChainingSubTable (ttf, st, info, l, subtable, alllooks);
  3033. break;
  3034. case 9:
  3035. LogError (_
  3036. ("This font is erroneous: it has a GPOS extension subtable that points to\nanother extension sub-table.\n"));
  3037. info->bad_ot = true;
  3038. break;
  3039. /* Any cases added here also need to go in the gposLookupSwitch */
  3040. default:
  3041. LogError (_("Unknown GPOS sub-table type: %d\n"), lu_type);
  3042. info->bad_ot = true;
  3043. break;
  3044. }
  3045. if (ftell (ttf) > info->g_bounds)
  3046. {
  3047. LogError (_("Subtable extends beyond end of GPOS table\n"));
  3048. info->bad_ot = true;
  3049. }
  3050. }
  3051. static void
  3052. gsubExtensionSubTable (FILE *ttf, int stoffset,
  3053. struct ttfinfo *info, struct lookup *l,
  3054. struct lookup_subtable *subtable, int justinuse,
  3055. struct lookup *alllooks)
  3056. {
  3057. uint32_t base = ftell (ttf), st, offset;
  3058. int lu_type;
  3059. /* Format = */ getushort (ttf);
  3060. lu_type = getushort (ttf);
  3061. offset = getlong (ttf);
  3062. l->otlookup->lookup_type = lu_type;
  3063. fseek (ttf, st = base + offset, SEEK_SET);
  3064. switch (lu_type)
  3065. {
  3066. case 1:
  3067. gsubSimpleSubTable (ttf, st, info, l, subtable, justinuse);
  3068. break;
  3069. case 2:
  3070. case 3: /* Multiple and alternate have same format, different semantics */
  3071. gsubMultipleSubTable (ttf, st, info, l, subtable, justinuse);
  3072. break;
  3073. case 4:
  3074. gsubLigatureSubTable (ttf, st, info, l, subtable, justinuse);
  3075. break;
  3076. case 5:
  3077. gsubContextSubTable (ttf, st, info, l, subtable, justinuse, alllooks);
  3078. break;
  3079. case 6:
  3080. gsubChainingSubTable (ttf, st, info, l, subtable, justinuse, alllooks);
  3081. break;
  3082. case 7:
  3083. LogError (_
  3084. ("This font is erroneous: it has a GSUB extension subtable that points to\nanother extension sub-table.\n"));
  3085. info->bad_ot = true;
  3086. break;
  3087. case 8:
  3088. gsubReverseChainSubTable (ttf, st, info, l, subtable, justinuse);
  3089. break;
  3090. /* Any cases added here also need to go in the gsubLookupSwitch */
  3091. default:
  3092. LogError (_("Unknown GSUB sub-table type: %d\n"), lu_type);
  3093. info->bad_ot = true;
  3094. break;
  3095. }
  3096. if (ftell (ttf) > info->gsub_start + info->gsub_length)
  3097. {
  3098. LogError (_("Subtable extends beyond end of GSUB table\n"));
  3099. info->bad_ot = true;
  3100. }
  3101. }
  3102. static void
  3103. gposLookupSwitch (FILE *ttf, int st,
  3104. struct ttfinfo *info, struct lookup *l,
  3105. struct lookup_subtable *subtable, struct lookup *alllooks)
  3106. {
  3107. switch (l->type | 0x100)
  3108. {
  3109. case gpos_single:
  3110. gposSimplePos (ttf, st, info, l, subtable);
  3111. break;
  3112. case gpos_pair:
  3113. gposKernSubTable (ttf, st, info, l, subtable);
  3114. break;
  3115. case gpos_cursive:
  3116. gposCursiveSubTable (ttf, st, info, l, subtable);
  3117. break;
  3118. case gpos_mark2base:
  3119. case gpos_mark2ligature:
  3120. case gpos_mark2mark:
  3121. gposMarkSubTable (ttf, st, info, l, subtable);
  3122. break;
  3123. case gpos_context:
  3124. gposContextSubTable (ttf, st, info, l, subtable, alllooks);
  3125. break;
  3126. case gpos_contextchain:
  3127. gposChainingSubTable (ttf, st, info, l, subtable, alllooks);
  3128. break;
  3129. case 0x109:
  3130. gposExtensionSubTable (ttf, st, info, l, subtable, alllooks);
  3131. break;
  3132. /* Any cases added here also need to go in the gposExtensionSubTable */
  3133. default:
  3134. LogError (_("Unknown GPOS sub-table type: %d\n"),
  3135. l->otlookup->lookup_type);
  3136. info->bad_ot = true;
  3137. break;
  3138. }
  3139. if (ftell (ttf) > info->g_bounds)
  3140. {
  3141. LogError (_("Subtable extends beyond end of GPOS table\n"));
  3142. info->bad_ot = true;
  3143. }
  3144. }
  3145. static void
  3146. gsubLookupSwitch (FILE *ttf, int st,
  3147. struct ttfinfo *info, struct lookup *l,
  3148. struct lookup_subtable *subtable, int justinuse,
  3149. struct lookup *alllooks)
  3150. {
  3151. switch (l->type)
  3152. {
  3153. case gsub_single:
  3154. gsubSimpleSubTable (ttf, st, info, l, subtable, justinuse);
  3155. break;
  3156. case gsub_multiple:
  3157. case gsub_alternate: /* Multiple and alternate have same format, different semantics */
  3158. gsubMultipleSubTable (ttf, st, info, l, subtable, justinuse);
  3159. break;
  3160. case gsub_ligature:
  3161. gsubLigatureSubTable (ttf, st, info, l, subtable, justinuse);
  3162. break;
  3163. case gsub_context:
  3164. gsubContextSubTable (ttf, st, info, l, subtable, justinuse, alllooks);
  3165. break;
  3166. case gsub_contextchain:
  3167. gsubChainingSubTable (ttf, st, info, l, subtable, justinuse, alllooks);
  3168. break;
  3169. case 7:
  3170. gsubExtensionSubTable (ttf, st, info, l, subtable, justinuse, alllooks);
  3171. break;
  3172. case gsub_reversecchain:
  3173. gsubReverseChainSubTable (ttf, st, info, l, subtable, justinuse);
  3174. break;
  3175. /* Any cases added here also need to go in the gsubExtensionSubTable */
  3176. default:
  3177. LogError (_("Unknown GSUB sub-table type: %d\n"),
  3178. l->otlookup->lookup_type);
  3179. info->bad_ot = true;
  3180. break;
  3181. }
  3182. if (ftell (ttf) > info->g_bounds)
  3183. {
  3184. LogError (_("Subtable extends beyond end of GSUB table\n"));
  3185. info->bad_ot = true;
  3186. }
  3187. }
  3188. static void
  3189. ScriptsFree (struct scripts *scripts)
  3190. {
  3191. int i, j;
  3192. if (scripts == NULL)
  3193. return;
  3194. for (i = 0; scripts[i].offset != 0; ++i)
  3195. {
  3196. for (j = 0; j < scripts[i].langcnt; ++j)
  3197. free (scripts[i].languages[j].features);
  3198. free (scripts[i].languages);
  3199. }
  3200. free (scripts);
  3201. }
  3202. static void
  3203. FeaturesFree (struct feature *features)
  3204. {
  3205. int i;
  3206. if (features == NULL)
  3207. return;
  3208. for (i = 0; features[i].offset != 0; ++i)
  3209. free (features[i].lookups);
  3210. free (features);
  3211. }
  3212. static void
  3213. LookupsFree (struct lookup *lookups)
  3214. {
  3215. int i;
  3216. for (i = 0; lookups[i].offset != 0; ++i)
  3217. {
  3218. free (lookups[i].subtab_offsets);
  3219. }
  3220. free (lookups);
  3221. }
  3222. static void
  3223. ProcessGPOSGSUB (FILE *ttf, struct ttfinfo *info, int gpos, int inusetype)
  3224. {
  3225. int k;
  3226. int32_t base, lookup_start, st;
  3227. int32_t script_off, feature_off;
  3228. struct scripts *scripts;
  3229. struct feature *features;
  3230. struct lookup *lookups, *l;
  3231. struct lookup_subtable *subtable;
  3232. if (gpos)
  3233. {
  3234. base = info->gpos_start;
  3235. info->g_bounds = base + info->gpos_length;
  3236. }
  3237. else
  3238. {
  3239. base = info->gsub_start;
  3240. info->g_bounds = base + info->gsub_length;
  3241. }
  3242. fseek (ttf, base, SEEK_SET);
  3243. /* version = */ getlong (ttf);
  3244. script_off = getushort (ttf);
  3245. feature_off = getushort (ttf);
  3246. lookup_start = base + getushort (ttf);
  3247. scripts = readttfscripts (ttf, base + script_off, info, gpos);
  3248. features = readttffeatures (ttf, base + feature_off, gpos, info);
  3249. /* It is legal to have lookups with no features or scripts */
  3250. /* For example if all the lookups were controlled by the JSTF table */
  3251. lookups = readttflookups (ttf, lookup_start, info, gpos);
  3252. if (lookups == NULL)
  3253. {
  3254. ScriptsFree (scripts);
  3255. FeaturesFree (features);
  3256. return;
  3257. }
  3258. tagLookupsWithScript (scripts, features, lookups, info);
  3259. ScriptsFree (scripts);
  3260. scripts = NULL;
  3261. FeaturesFree (features);
  3262. features = NULL;
  3263. for (l = lookups; l->offset != 0; ++l)
  3264. {
  3265. for (k = 0, subtable = l->otlookup->subtables; k < l->subtabcnt;
  3266. ++k, subtable = subtable->next)
  3267. {
  3268. st = l->subtab_offsets[k];
  3269. fseek (ttf, st, SEEK_SET);
  3270. if (gpos)
  3271. {
  3272. gposLookupSwitch (ttf, st, info, l, subtable, lookups);
  3273. }
  3274. else
  3275. {
  3276. gsubLookupSwitch (ttf, st, info, l, subtable, inusetype, lookups);
  3277. }
  3278. }
  3279. }
  3280. /* Then generate some user-friendly names for the all the lookups */
  3281. if (inusetype == git_normal)
  3282. for (l = lookups; l->offset != 0; ++l)
  3283. NameOTLookup (l->otlookup, NULL);
  3284. LookupsFree (lookups);
  3285. if (inusetype != git_normal && !gpos)
  3286. {
  3287. OTLookupListFree (info->gsub_lookups);
  3288. info->gsub_lookups = info->cur_lookups = NULL;
  3289. }
  3290. }
  3291. void
  3292. readttfgsubUsed (FILE *ttf, struct ttfinfo *info)
  3293. {
  3294. ProcessGPOSGSUB (ttf, info, false, git_justinuse);
  3295. info->g_bounds = 0;
  3296. }
  3297. void
  3298. GuessNamesFromGSUB (FILE *ttf, struct ttfinfo *info)
  3299. {
  3300. ProcessGPOSGSUB (ttf, info, false, git_findnames);
  3301. info->g_bounds = 0;
  3302. }
  3303. void
  3304. readttfgpossub (FILE *ttf, struct ttfinfo *info, int gpos)
  3305. {
  3306. ProcessGPOSGSUB (ttf, info, gpos, git_normal);
  3307. info->g_bounds = 0;
  3308. }
  3309. void
  3310. readttfgdef (FILE *ttf, struct ttfinfo *info)
  3311. {
  3312. int lclo, gclass, mac, mas = 0;
  3313. int coverage, cnt, i, j, format;
  3314. int version;
  3315. uint16_t *glyphs, *lc_offsets, *offsets;
  3316. uint32_t caret_base;
  3317. PST *pst;
  3318. SplineChar *sc;
  3319. fseek (ttf, info->gdef_start, SEEK_SET);
  3320. version = getlong (ttf);
  3321. if (version != 0x00010000 && version != 0x00010002)
  3322. return;
  3323. info->g_bounds = info->gdef_start + info->gdef_length;
  3324. gclass = getushort (ttf);
  3325. /* attach list = */ getushort (ttf);
  3326. lclo = getushort (ttf); /* ligature caret list */
  3327. mac = getushort (ttf); /* mark attach class */
  3328. if (version == 0x00010002)
  3329. mas = getushort (ttf);
  3330. if (gclass != 0)
  3331. {
  3332. uint16_t *gclasses =
  3333. getClassDefTable (ttf, info->gdef_start + gclass, info);
  3334. for (i = 0; i < info->glyph_cnt; ++i)
  3335. if (info->chars[i] != NULL && gclasses[i] != 0)
  3336. info->chars[i]->glyph_class = gclasses[i] + 1;
  3337. free (gclasses);
  3338. }
  3339. if (mac != 0)
  3340. {
  3341. uint16_t *mclasses = getClassDefTable (ttf, info->gdef_start + mac, info);
  3342. const char *format_spec = _("MarkClass-%d");
  3343. info->mark_class_cnt = ClassFindCnt (mclasses, info->glyph_cnt);
  3344. info->mark_classes =
  3345. ClassToNames (info, info->mark_class_cnt, mclasses, info->glyph_cnt);
  3346. info->mark_class_names = xmalloc (info->mark_class_cnt * sizeof (char *));
  3347. info->mark_class_names[0] = NULL;
  3348. for (i = 1; i < info->mark_class_cnt; ++i)
  3349. {
  3350. info->mark_class_names[i] = xmalloc ((strlen (format_spec) + 10));
  3351. sprintf (info->mark_class_names[i], format_spec, i);
  3352. }
  3353. free (mclasses);
  3354. }
  3355. if (mas != 0)
  3356. {
  3357. const char *format_spec = _("MarkSet-%d");
  3358. fseek (ttf, info->gdef_start + mas, SEEK_SET);
  3359. if (getushort (ttf) == 1)
  3360. { /* Version number of Mark GLyph Sets Table */
  3361. uint32_t *offsets;
  3362. uint16_t *glyphs;
  3363. info->mark_set_cnt = getushort (ttf);
  3364. offsets = xmalloc (info->mark_set_cnt * sizeof (uint32_t));
  3365. for (i = 0; i < info->mark_set_cnt; ++i)
  3366. offsets[i] = getlong (ttf);
  3367. info->mark_sets = xmalloc (info->mark_set_cnt * sizeof (char *));
  3368. info->mark_set_names = xmalloc (info->mark_set_cnt * sizeof (char *));
  3369. info->mark_set_names[0] = NULL;
  3370. for (i = 0; i < info->mark_set_cnt; ++i)
  3371. {
  3372. info->mark_set_names[i] = xmalloc ((strlen (format_spec) + 10));
  3373. sprintf (info->mark_set_names[i], format_spec, i);
  3374. if (offsets[i] != 0)
  3375. {
  3376. glyphs =
  3377. getCoverageTable (ttf, info->gdef_start + mas + offsets[i],
  3378. info);
  3379. info->mark_sets[i] = GlyphsToNames (info, glyphs, true);
  3380. free (glyphs);
  3381. }
  3382. else
  3383. info->mark_sets[i] = NULL; /* Should not happen */
  3384. }
  3385. free (offsets);
  3386. }
  3387. }
  3388. if (lclo != 0)
  3389. {
  3390. lclo += info->gdef_start;
  3391. fseek (ttf, lclo, SEEK_SET);
  3392. coverage = getushort (ttf);
  3393. cnt = getushort (ttf);
  3394. if (cnt == 0)
  3395. return;
  3396. lc_offsets = xmalloc (cnt * sizeof (uint16_t));
  3397. for (i = 0; i < cnt; ++i)
  3398. lc_offsets[i] = getushort (ttf);
  3399. glyphs = getCoverageTable (ttf, lclo + coverage, info);
  3400. if (glyphs == NULL)
  3401. return;
  3402. for (i = 0; i < cnt; ++i)
  3403. if (glyphs[i] < info->glyph_cnt
  3404. && (sc = info->chars[glyphs[i]]) != NULL)
  3405. {
  3406. fseek (ttf, lclo + lc_offsets[i], SEEK_SET);
  3407. for (pst = sc->possub; pst != NULL && pst->type != pst_lcaret;
  3408. pst = pst->next);
  3409. if (pst == NULL)
  3410. {
  3411. pst = xzalloc (sizeof (PST));
  3412. pst->next = sc->possub;
  3413. sc->possub = pst;
  3414. pst->type = pst_lcaret;
  3415. pst->subtable = NULL;
  3416. sc->lig_caret_cnt_fixed = true;
  3417. }
  3418. caret_base = ftell (ttf);
  3419. pst->u.lcaret.cnt = getushort (ttf);
  3420. if (pst->u.lcaret.carets != NULL)
  3421. free (pst->u.lcaret.carets);
  3422. offsets = xmalloc (pst->u.lcaret.cnt * sizeof (uint16_t));
  3423. for (j = 0; j < pst->u.lcaret.cnt; ++j)
  3424. offsets[j] = getushort (ttf);
  3425. pst->u.lcaret.carets =
  3426. xmalloc (pst->u.lcaret.cnt * sizeof (int16_t));
  3427. for (j = 0; j < pst->u.lcaret.cnt; ++j)
  3428. {
  3429. fseek (ttf, caret_base + offsets[j], SEEK_SET);
  3430. format = getushort (ttf);
  3431. if (format == 1)
  3432. {
  3433. pst->u.lcaret.carets[j] = getushort (ttf);
  3434. }
  3435. else if (format == 2)
  3436. {
  3437. pst->u.lcaret.carets[j] = 0;
  3438. /* point = */ getushort (ttf);
  3439. }
  3440. else if (format == 3)
  3441. {
  3442. pst->u.lcaret.carets[j] = getushort (ttf);
  3443. /* in device table = */ getushort (ttf);
  3444. }
  3445. else
  3446. {
  3447. LogError (_("!!!! Unknown caret format %d !!!!\n"), format);
  3448. info->bad_ot = true;
  3449. }
  3450. }
  3451. free (offsets);
  3452. }
  3453. free (lc_offsets);
  3454. free (glyphs);
  3455. }
  3456. info->g_bounds = 0;
  3457. }
  3458. static void
  3459. OTLAppend (struct ttfinfo *info, OTLookup *otl, int gpos)
  3460. {
  3461. OTLookup *prev;
  3462. int pos = 0;
  3463. if (gpos && info->gpos_lookups == NULL)
  3464. info->gpos_lookups = otl;
  3465. else if (!gpos && info->gsub_lookups == NULL)
  3466. info->gsub_lookups = otl;
  3467. else
  3468. {
  3469. prev = gpos ? info->gpos_lookups : info->gsub_lookups;
  3470. pos = 1;
  3471. while (prev->next != NULL)
  3472. {
  3473. prev = prev->next;
  3474. ++pos;
  3475. }
  3476. prev->next = otl;
  3477. }
  3478. otl->lookup_index = pos;
  3479. }
  3480. static void
  3481. OTLRemove (struct ttfinfo *info, OTLookup *otl, int gpos)
  3482. {
  3483. /* Remove the most recent lookup. We got bad data and can't use it */
  3484. OTLookup *prev, **base;
  3485. base = gpos ? &info->gpos_lookups : &info->gsub_lookups;
  3486. if (*base == otl)
  3487. *base = NULL;
  3488. else if (*base != NULL)
  3489. {
  3490. for (prev = *base; prev->next != NULL && prev->next != otl;
  3491. prev = prev->next);
  3492. prev->next = NULL;
  3493. }
  3494. OTLookupFree (otl);
  3495. }
  3496. static void
  3497. InfoNameOTLookup (OTLookup *otl, struct ttfinfo *info)
  3498. {
  3499. SplineFont sf;
  3500. memset (&sf, 0, sizeof (sf));
  3501. NameOTLookup (otl, &sf);
  3502. }
  3503. int32_t
  3504. memlong (uint8_t *data, int len, int offset)
  3505. {
  3506. if (offset >= 0 && offset + 3 < len)
  3507. {
  3508. int ch1 = data[offset], ch2 = data[offset + 1], ch3 =
  3509. data[offset + 2], ch4 = data[offset + 3];
  3510. return (ch1 << 24) | (ch2 << 16) | (ch3 << 8) | ch4;
  3511. }
  3512. else
  3513. {
  3514. LogError (_("Bad font, offset out of bounds.\n"));
  3515. return 0;
  3516. }
  3517. }
  3518. int
  3519. memushort (uint8_t *data, int len, int offset)
  3520. {
  3521. if (offset >= 0 && offset + 1 < len)
  3522. {
  3523. int ch1 = data[offset], ch2 = data[offset + 1];
  3524. return (ch1 << 8) | ch2;
  3525. }
  3526. else
  3527. {
  3528. LogError (_("Bad font, offset out of bounds.\n"));
  3529. return 0;
  3530. }
  3531. }
  3532. void
  3533. memputshort (uint8_t *data, int offset, uint16_t val)
  3534. {
  3535. data[offset] = (val >> 8);
  3536. data[offset + 1] = val & 0xff;
  3537. }
  3538. /* Apple's docs imply that kerning info is always provided left to right, even*/
  3539. /* for right to left scripts. My guess is that their docs are wrong, as they */
  3540. /* often are, but if that be so then we need code in here to reverse */
  3541. /* the order of the characters for right to left since pfaedit's convention */
  3542. /* is to follow writing order rather than to go left to right */
  3543. void
  3544. readttfkerns (FILE *ttf, struct ttfinfo *info)
  3545. {
  3546. int tabcnt, len, coverage, i, j, npairs, version, format, flags_good, tab;
  3547. int left, right, offset, array, rowWidth;
  3548. int header_size;
  3549. KernPair *kp;
  3550. KernClass *kc;
  3551. uint32_t begin_table;
  3552. uint16_t *class1, *class2;
  3553. int isv;
  3554. OTLookup *otl;
  3555. fseek (ttf, info->kern_start, SEEK_SET);
  3556. version = getushort (ttf);
  3557. tabcnt = getushort (ttf);
  3558. if (version != 0)
  3559. {
  3560. LogError (_("Invalid or unsupported version (0x%x) for 'kern' table"),
  3561. version);
  3562. info->bad_gx = true;
  3563. return;
  3564. }
  3565. if (tabcnt < 0 || tabcnt > 0x1000)
  3566. LogError (_("Warning: Unlikely number of subtables (%d) for 'kern' table"),
  3567. tabcnt);
  3568. for (tab = 0; tab < tabcnt; ++tab)
  3569. {
  3570. begin_table = ftell (ttf);
  3571. /* version = */ getushort (ttf);
  3572. len = getushort (ttf);
  3573. coverage = getushort (ttf);
  3574. format = coverage >> 8;
  3575. flags_good = ((coverage & 7) <= 1);
  3576. isv = !(coverage & 1);
  3577. header_size = 6;
  3578. otl = NULL;
  3579. if (flags_good)
  3580. {
  3581. otl = xzalloc (sizeof (OTLookup));
  3582. otl->lookup_type = gpos_pair;
  3583. otl->subtables =
  3584. (struct lookup_subtable *)
  3585. xzalloc (sizeof (struct lookup_subtable));
  3586. otl->subtables->lookup = otl;
  3587. otl->subtables->per_glyph_pst_or_kern = true;
  3588. otl->subtables->vertical_kerning = isv;
  3589. otl->features =
  3590. xzalloc (sizeof (FeatureScriptLangList));
  3591. if (isv)
  3592. otl->features->featuretag = CHR ('v', 'k', 'r', 'n');
  3593. else
  3594. otl->features->featuretag = CHR ('k', 'e', 'r', 'n');
  3595. OTLAppend (info, otl, true);
  3596. }
  3597. if (flags_good && format == 0)
  3598. {
  3599. /* format 0, horizontal kerning data (as pairs) not perpendicular */
  3600. npairs = getushort (ttf);
  3601. if (len - 14 != 6 * npairs || npairs > 10920)
  3602. {
  3603. LogError (_
  3604. ("In the 'kern' table, a subtable's length does not match the number of kerning pairs."));
  3605. info->bad_gx = true;
  3606. }
  3607. /* searchRange = */ getushort (ttf);
  3608. /* entrySelector = */ getushort (ttf);
  3609. /* rangeShift = */ getushort (ttf);
  3610. otl->subtables[0].per_glyph_pst_or_kern = true;
  3611. for (j = 0; j < npairs; ++j)
  3612. {
  3613. left = getushort (ttf);
  3614. right = getushort (ttf);
  3615. offset = (short) getushort (ttf);
  3616. if (left < 0 || right < 0)
  3617. {
  3618. /* We've seen such buggy fonts... */
  3619. LogError (_
  3620. ("Bad kern pair: glyphs %d & %d mustn't be negative\n"),
  3621. left, right);
  3622. info->bad_gx = true;
  3623. }
  3624. else if (left >= info->glyph_cnt || right >= info->glyph_cnt)
  3625. {
  3626. /* Holes happen when reading ttc files. They are probably ok */
  3627. LogError (_
  3628. ("Bad kern pair: glyphs %d & %d must be less than %d\n"),
  3629. left, right, info->glyph_cnt);
  3630. info->bad_gx = true;
  3631. }
  3632. else if (info->chars[left] == NULL || info->chars[right] == NULL)
  3633. {
  3634. /* Shouldn't happen. */
  3635. LogError (_("Bad kern pair: glyphs at %d & %d are null\n"),
  3636. left, right);
  3637. info->bad_gx = true;
  3638. }
  3639. else
  3640. {
  3641. kp = xzalloc (sizeof (KernPair));
  3642. kp->sc = info->chars[right];
  3643. kp->off = offset;
  3644. kp->subtable = otl->subtables;
  3645. FListsAppendScriptLang (otl->features,
  3646. SCScriptFromUnicode (info->
  3647. chars[left]),
  3648. DEFAULT_LANG);
  3649. if (isv)
  3650. {
  3651. kp->next = info->chars[left]->vkerns;
  3652. info->chars[left]->vkerns = kp;
  3653. }
  3654. else
  3655. {
  3656. kp->next = info->chars[left]->kerns;
  3657. info->chars[left]->kerns = kp;
  3658. }
  3659. }
  3660. }
  3661. InfoNameOTLookup (otl, info);
  3662. }
  3663. else if (flags_good && (format == 2 || format == 3))
  3664. {
  3665. /* two class based formats */
  3666. KernClass **khead, **klast;
  3667. if (isv)
  3668. {
  3669. khead = &info->vkhead;
  3670. klast = &info->vklast;
  3671. }
  3672. else
  3673. {
  3674. khead = &info->khead;
  3675. klast = &info->klast;
  3676. }
  3677. if (*khead == NULL)
  3678. *khead = kc = xzalloc (sizeof (KernClass));
  3679. else
  3680. kc = xzalloc (sizeof (KernClass));
  3681. *klast = kc;
  3682. if (format == 2)
  3683. {
  3684. rowWidth = getushort (ttf);
  3685. left = getushort (ttf);
  3686. right = getushort (ttf);
  3687. array = getushort (ttf);
  3688. kc->second_cnt = rowWidth / sizeof (uint16_t);
  3689. class1 =
  3690. getAppleClassTable (ttf, begin_table + left, info->glyph_cnt,
  3691. array, rowWidth, info);
  3692. class2 =
  3693. getAppleClassTable (ttf, begin_table + right, info->glyph_cnt,
  3694. 0, sizeof (uint16_t), info);
  3695. for (i = 0; i < info->glyph_cnt; ++i)
  3696. if (class1[i] > kc->first_cnt)
  3697. kc->first_cnt = class1[i];
  3698. ++kc->first_cnt;
  3699. kc->offsets =
  3700. xmalloc (kc->first_cnt * kc->second_cnt * sizeof (int16_t));
  3701. kc->adjusts =
  3702. xcalloc (kc->first_cnt * kc->second_cnt, sizeof (DeviceTable));
  3703. fseek (ttf, begin_table + array, SEEK_SET);
  3704. for (i = 0; i < kc->first_cnt * kc->second_cnt; ++i)
  3705. kc->offsets[i] = getushort (ttf);
  3706. }
  3707. else
  3708. {
  3709. /* format 3, horizontal kerning data (as classes limited to 256 entries) */
  3710. /* OpenType's spec doesn't document this */
  3711. int gc, kv, flags;
  3712. int16_t *kvs;
  3713. gc = getushort (ttf);
  3714. kv = getc (ttf);
  3715. kc->first_cnt = getc (ttf);
  3716. kc->second_cnt = getc (ttf);
  3717. flags = getc (ttf);
  3718. if (gc > info->glyph_cnt)
  3719. {
  3720. LogError (_
  3721. ("Kerning subtable 3 says the glyph count is %d, but maxp says %d\n"),
  3722. gc, info->glyph_cnt);
  3723. info->bad_gx = true;
  3724. }
  3725. class1 =
  3726. xcalloc (gc > info->glyph_cnt ? gc : info->glyph_cnt,
  3727. sizeof (uint16_t));
  3728. class2 =
  3729. xcalloc (gc > info->glyph_cnt ? gc : info->glyph_cnt,
  3730. sizeof (uint16_t));
  3731. kvs = xmalloc (kv * sizeof (int16_t));
  3732. kc->offsets =
  3733. xmalloc (kc->first_cnt * kc->second_cnt * sizeof (int16_t));
  3734. kc->adjusts =
  3735. xcalloc (kc->first_cnt * kc->second_cnt, sizeof (DeviceTable));
  3736. for (i = 0; i < kv; ++i)
  3737. kvs[i] = (int16_t) getushort (ttf);
  3738. for (i = 0; i < gc; ++i)
  3739. class1[i] = getc (ttf);
  3740. for (i = 0; i < gc; ++i)
  3741. class2[i] = getc (ttf);
  3742. for (i = 0; i < kc->first_cnt * kc->second_cnt; ++i)
  3743. kc->offsets[i] = kvs[getc (ttf)];
  3744. free (kvs);
  3745. }
  3746. kc->firsts =
  3747. ClassToNames (info, kc->first_cnt, class1, info->glyph_cnt);
  3748. kc->seconds =
  3749. ClassToNames (info, kc->second_cnt, class2, info->glyph_cnt);
  3750. for (i = 0; i < info->glyph_cnt; ++i)
  3751. {
  3752. if (class1[i] >= 4 && info->chars[i] != NULL)
  3753. FListsAppendScriptLang (otl->features,
  3754. SCScriptFromUnicode (info->chars[i]),
  3755. DEFAULT_LANG);
  3756. }
  3757. free (class1);
  3758. free (class2);
  3759. fseek (ttf, begin_table + len, SEEK_SET);
  3760. otl->subtables[0].kc = kc;
  3761. kc->subtable = otl->subtables;
  3762. InfoNameOTLookup (otl, info);
  3763. }
  3764. else
  3765. {
  3766. LogError (_
  3767. ("Invalid or unsupported format (%d) for subtable of 'kern' table"),
  3768. format);
  3769. info->bad_gx = true;
  3770. fseek (ttf, len - header_size, SEEK_CUR);
  3771. if (otl != NULL)
  3772. OTLRemove (info, otl, true);
  3773. return; /* Give up */
  3774. }
  3775. }
  3776. }
  3777. /******************************************************************************/
  3778. /* ******************************* MATH Table ******************************* */
  3779. /* ********************** (Not strictly OpenType yet) *********************** */
  3780. /******************************************************************************/
  3781. /* ******************************** Read MATH ******************************* */
  3782. static void
  3783. ttf_math_read_constants (FILE *ttf, struct ttfinfo *info, uint32_t start)
  3784. {
  3785. struct MATH *math;
  3786. int i;
  3787. uint16_t off;
  3788. fseek (ttf, start, SEEK_SET);
  3789. info->math = math = xcalloc (1, sizeof (struct MATH));
  3790. for (i = 0; math_constants_descriptor[i].script_name != NULL; ++i)
  3791. {
  3792. int16_t *pos =
  3793. (int16_t *) (((char *) (math)) + math_constants_descriptor[i].offset);
  3794. if (pos == (int16_t *) &math->MinConnectorOverlap)
  3795. continue; /* Actually lives in the Variant table, not here */
  3796. *pos = getushort (ttf);
  3797. if (math_constants_descriptor[i].devtab_offset >= 0)
  3798. {
  3799. DeviceTable **devtab =
  3800. (DeviceTable **) (((char *) (math)) +
  3801. math_constants_descriptor[i].devtab_offset);
  3802. off = getushort (ttf);
  3803. if (off != 0)
  3804. {
  3805. *devtab = xzalloc (sizeof (DeviceTable));
  3806. ReadDeviceTable (ttf, *devtab, start + off, info);
  3807. }
  3808. }
  3809. }
  3810. }
  3811. static void
  3812. ttf_math_read_icta (FILE *ttf, struct ttfinfo *info, uint32_t start, int is_ic)
  3813. {
  3814. /* The italic correction and top accent sub-tables have the same format */
  3815. int coverage, cnt, i, val, offset;
  3816. uint16_t *glyphs;
  3817. fseek (ttf, start, SEEK_SET);
  3818. coverage = getushort (ttf);
  3819. cnt = getushort (ttf);
  3820. glyphs = getCoverageTable (ttf, start + coverage, info);
  3821. if (glyphs == NULL)
  3822. return;
  3823. fseek (ttf, start + 4, SEEK_SET);
  3824. for (i = 0; i < cnt; ++i)
  3825. {
  3826. val = (int16_t) getushort (ttf);
  3827. offset = getushort (ttf);
  3828. if (glyphs[i] < info->glyph_cnt && info->chars[glyphs[i]] != NULL)
  3829. {
  3830. if (is_ic)
  3831. info->chars[glyphs[i]]->italic_correction = val;
  3832. else
  3833. info->chars[glyphs[i]]->top_accent_horiz = val;
  3834. if (offset != 0)
  3835. {
  3836. DeviceTable *dv = xzalloc (sizeof (DeviceTable));
  3837. ReadDeviceTable (ttf, dv, start + offset, info);
  3838. if (is_ic)
  3839. info->chars[glyphs[i]]->italic_adjusts = dv;
  3840. else
  3841. info->chars[glyphs[i]]->top_accent_adjusts = dv;
  3842. }
  3843. }
  3844. }
  3845. free (glyphs);
  3846. }
  3847. static void
  3848. ttf_math_read_extended (FILE *ttf, struct ttfinfo *info, uint32_t start)
  3849. {
  3850. int i;
  3851. uint16_t *glyphs;
  3852. glyphs = getCoverageTable (ttf, start, info);
  3853. if (glyphs == NULL)
  3854. return;
  3855. for (i = 0; glyphs[i] != 0xffff; ++i)
  3856. if (glyphs[i] < info->glyph_cnt && info->chars[glyphs[i]] != NULL)
  3857. info->chars[glyphs[i]]->is_extended_shape = true;
  3858. free (glyphs);
  3859. }
  3860. static void
  3861. ttf_math_read_mathkernv (FILE *ttf, uint32_t start, struct mathkernvertex *mkv,
  3862. SplineChar *sc, int istop, struct ttfinfo *info)
  3863. {
  3864. int cnt, i;
  3865. fseek (ttf, start, SEEK_SET);
  3866. /* There is one more width than height. I store the width count */
  3867. /* and guess a dummy height later */
  3868. mkv->cnt = cnt = getushort (ttf) + 1;
  3869. mkv->mkd = xcalloc (cnt, sizeof (struct mathkerndata));
  3870. for (i = 0; i < cnt - 1; ++i)
  3871. {
  3872. mkv->mkd[i].height = getushort (ttf);
  3873. mkv->mkd[i].height_adjusts = (void *) (intptr_t) getushort (ttf);
  3874. }
  3875. for (i = 0; i < cnt; ++i)
  3876. {
  3877. mkv->mkd[i].kern = getushort (ttf);
  3878. mkv->mkd[i].kern_adjusts = (void *) (intptr_t) getushort (ttf);
  3879. }
  3880. for (i = 0; i < cnt; ++i)
  3881. {
  3882. DeviceTable *dv;
  3883. uint32_t offset;
  3884. if (mkv->mkd[i].height_adjusts != NULL)
  3885. {
  3886. offset = start + (intptr_t) mkv->mkd[i].height_adjusts;
  3887. mkv->mkd[i].height_adjusts = dv =
  3888. xzalloc (sizeof (DeviceTable));
  3889. ReadDeviceTable (ttf, dv, offset, info);
  3890. }
  3891. if (mkv->mkd[i].kern_adjusts != NULL)
  3892. {
  3893. offset = start + (intptr_t) mkv->mkd[i].kern_adjusts;
  3894. mkv->mkd[i].kern_adjusts = dv =
  3895. xzalloc (sizeof (DeviceTable));
  3896. ReadDeviceTable (ttf, dv, offset, info);
  3897. }
  3898. }
  3899. if (cnt >= 3)
  3900. mkv->mkd[cnt - 1].height =
  3901. 2 * mkv->mkd[cnt - 2].height - mkv->mkd[cnt - 3].height;
  3902. else if (cnt >= 2)
  3903. mkv->mkd[cnt - 1].height = mkv->mkd[cnt - 2].height + 100;
  3904. else if (cnt == 1)
  3905. {
  3906. if (istop)
  3907. {
  3908. DBounds b;
  3909. SplineCharQuickBounds (sc, &b);
  3910. mkv->mkd[cnt - 1].height = b.maxy;
  3911. }
  3912. else
  3913. mkv->mkd[cnt - 1].height = 0;
  3914. }
  3915. }
  3916. static void
  3917. ttf_math_read_mathkern (FILE *ttf, struct ttfinfo *info, uint32_t start)
  3918. {
  3919. int coverage, cnt, i;
  3920. uint16_t *glyphs;
  3921. struct koff
  3922. {
  3923. uint16_t tr, tl, br, bl;
  3924. } *koff;
  3925. fseek (ttf, start, SEEK_SET);
  3926. coverage = getushort (ttf);
  3927. cnt = getushort (ttf);
  3928. koff = xmalloc (cnt * sizeof (struct koff));
  3929. for (i = 0; i < cnt; ++i)
  3930. {
  3931. koff[i].tr = getushort (ttf);
  3932. koff[i].tl = getushort (ttf);
  3933. koff[i].br = getushort (ttf);
  3934. koff[i].bl = getushort (ttf);
  3935. }
  3936. glyphs = getCoverageTable (ttf, start + coverage, info);
  3937. if (glyphs == NULL)
  3938. {
  3939. free (koff);
  3940. return;
  3941. }
  3942. for (i = 0; i < cnt; ++i)
  3943. if (glyphs[i] < info->glyph_cnt && info->chars[glyphs[i]] != NULL)
  3944. {
  3945. SplineChar *sc = info->chars[glyphs[i]];
  3946. sc->mathkern = xzalloc (sizeof (struct mathkern));
  3947. if (koff[i].tr != 0)
  3948. ttf_math_read_mathkernv (ttf, start + koff[i].tr,
  3949. &sc->mathkern->top_right, sc, true, info);
  3950. if (koff[i].tl != 0)
  3951. ttf_math_read_mathkernv (ttf, start + koff[i].tl,
  3952. &sc->mathkern->top_left, sc, true, info);
  3953. if (koff[i].br != 0)
  3954. ttf_math_read_mathkernv (ttf, start + koff[i].br,
  3955. &sc->mathkern->bottom_right, sc, false,
  3956. info);
  3957. if (koff[i].bl != 0)
  3958. ttf_math_read_mathkernv (ttf, start + koff[i].bl,
  3959. &sc->mathkern->bottom_left, sc, false, info);
  3960. }
  3961. free (koff);
  3962. free (glyphs);
  3963. }
  3964. static void
  3965. ttf_math_read_glyphinfo (FILE *ttf, struct ttfinfo *info, uint32_t start)
  3966. {
  3967. int icoff, taoff, esoff, kioff;
  3968. fseek (ttf, start, SEEK_SET);
  3969. icoff = getushort (ttf);
  3970. taoff = getushort (ttf);
  3971. esoff = getushort (ttf);
  3972. kioff = getushort (ttf);
  3973. if (icoff != 0)
  3974. ttf_math_read_icta (ttf, info, start + icoff, true);
  3975. if (taoff != 0)
  3976. ttf_math_read_icta (ttf, info, start + taoff, false);
  3977. if (esoff != 0)
  3978. ttf_math_read_extended (ttf, info, start + esoff);
  3979. if (kioff != 0)
  3980. ttf_math_read_mathkern (ttf, info, start + kioff);
  3981. }
  3982. static struct glyphvariants *
  3983. ttf_math_read_gvtable (FILE *ttf, struct ttfinfo *info, uint32_t start,
  3984. enum gsub_inusetype justinuse, SplineChar *basesc,
  3985. int isv)
  3986. {
  3987. struct glyphvariants *gv =
  3988. xzalloc (sizeof (struct glyphvariants));
  3989. int ga_offset;
  3990. int vcnt;
  3991. uint16_t *glyphs;
  3992. int i, j, len;
  3993. char *pt;
  3994. int ic_offset, pcnt;
  3995. SplineChar *sc;
  3996. char ebuf[10], buffer[50], *ext;
  3997. fseek (ttf, start, SEEK_SET);
  3998. ga_offset = getushort (ttf);
  3999. vcnt = getushort (ttf);
  4000. if (vcnt != 0)
  4001. {
  4002. if (justinuse == git_justinuse)
  4003. {
  4004. for (i = 0; i < vcnt; ++i)
  4005. {
  4006. int gid = getushort (ttf);
  4007. /* sizes[i] = */ getushort (ttf);
  4008. if (gid >= 0 && gid < info->glyph_cnt)
  4009. info->inuse[gid] = true;
  4010. }
  4011. }
  4012. else if (justinuse == git_findnames)
  4013. {
  4014. for (i = 0; i < vcnt; ++i)
  4015. {
  4016. int gid = getushort (ttf);
  4017. /* sizes[i] = */ getushort (ttf);
  4018. if (basesc != NULL && basesc->name != NULL &&
  4019. gid >= 0 && gid < info->glyph_cnt &&
  4020. (sc = info->chars[gid]) != NULL && sc->name == NULL)
  4021. {
  4022. snprintf (buffer, sizeof (buffer), "%.30s.%csize%d",
  4023. basesc->name, isv ? 'v' : 'h', i);
  4024. if (!glyphNameExists (info, buffer))
  4025. sc->name = xstrdup_or_null (buffer);
  4026. }
  4027. }
  4028. }
  4029. else
  4030. {
  4031. glyphs = xmalloc (vcnt * sizeof (uint16_t));
  4032. len = 0;
  4033. for (i = 0; i < vcnt; ++i)
  4034. {
  4035. glyphs[i] = getushort (ttf);
  4036. /* sizes[i] = */ getushort (ttf);
  4037. if (glyphs[i] < info->glyph_cnt
  4038. && (sc = info->chars[glyphs[i]]) != NULL)
  4039. len += strlen (sc->name) + 1;
  4040. }
  4041. if (len != 0)
  4042. {
  4043. gv->variants = pt = xmalloc (len);
  4044. for (i = len = 0; i < vcnt; ++i)
  4045. {
  4046. if (glyphs[i] < info->glyph_cnt
  4047. && (sc = info->chars[glyphs[i]]) != NULL)
  4048. {
  4049. strcpy (pt + len, sc->name);
  4050. len += strlen (sc->name);
  4051. pt[len++] = ' ';
  4052. }
  4053. }
  4054. pt[len - 1] = '\0';
  4055. }
  4056. free (glyphs);
  4057. }
  4058. }
  4059. if (ga_offset != 0)
  4060. {
  4061. start += ga_offset;
  4062. fseek (ttf, start, SEEK_SET);
  4063. gv->italic_correction = getushort (ttf);
  4064. ic_offset = getushort (ttf);
  4065. gv->part_cnt = pcnt = getushort (ttf);
  4066. if (justinuse == git_normal)
  4067. gv->parts = xcalloc (pcnt, sizeof (struct gv_part));
  4068. for (i = j = 0; i < pcnt; ++i)
  4069. {
  4070. int gid, start, end, full, flags;
  4071. gid = getushort (ttf);
  4072. start = getushort (ttf);
  4073. end = getushort (ttf);
  4074. full = getushort (ttf);
  4075. flags = getushort (ttf);
  4076. if (feof (ttf))
  4077. {
  4078. LogError (_("Bad glyph variant subtable of MATH table.\n"));
  4079. info->bad_ot = true;
  4080. free (gv);
  4081. return NULL;
  4082. }
  4083. if (justinuse == git_justinuse)
  4084. {
  4085. if (gid < info->glyph_cnt)
  4086. info->inuse[gid] = true;
  4087. }
  4088. else if (justinuse == git_findnames)
  4089. {
  4090. if (basesc != NULL && basesc->name != NULL &&
  4091. gid >= 0 && gid < info->glyph_cnt &&
  4092. (sc = info->chars[gid]) != NULL && sc->name == NULL)
  4093. {
  4094. if (pcnt == 1)
  4095. ext = "repeat";
  4096. if (i == 0)
  4097. ext = isv ? "bot" : "left";
  4098. else if (i == pcnt - 1)
  4099. ext = isv ? "top" : "right";
  4100. else if (i == 1 && pcnt == 3)
  4101. ext = "mid";
  4102. else
  4103. {
  4104. sprintf (ebuf, "%cpart%d", isv ? 'v' : 'h', i);
  4105. ext = ebuf;
  4106. }
  4107. snprintf (buffer, sizeof (buffer), "%.30s.%s",
  4108. basesc->name, ext);
  4109. if (!glyphNameExists (info, buffer))
  4110. sc->name = xstrdup_or_null (buffer);
  4111. }
  4112. }
  4113. else
  4114. {
  4115. if (gid < info->glyph_cnt && (sc = info->chars[gid]) != NULL)
  4116. {
  4117. gv->parts[j].component = xstrdup_or_null (sc->name);
  4118. gv->parts[j].startConnectorLength = start;
  4119. gv->parts[j].endConnectorLength = end;
  4120. gv->parts[j].fullAdvance = full;
  4121. gv->parts[j++].is_extender = flags & 1;
  4122. }
  4123. }
  4124. }
  4125. gv->part_cnt = j;
  4126. if (ic_offset != 0 && justinuse == git_normal)
  4127. {
  4128. gv->italic_adjusts = xzalloc (sizeof (DeviceTable));
  4129. ReadDeviceTable (ttf, gv->italic_adjusts, start + ic_offset, info);
  4130. }
  4131. }
  4132. if (justinuse == git_justinuse)
  4133. {
  4134. free (gv);
  4135. return NULL;
  4136. }
  4137. return gv;
  4138. }
  4139. static void
  4140. ttf_math_read_variants (FILE *ttf, struct ttfinfo *info, uint32_t start,
  4141. enum gsub_inusetype justinuse)
  4142. {
  4143. int vcoverage, hcoverage, vcnt, hcnt;
  4144. int *hoffs, *voffs;
  4145. uint16_t *hglyphs, *vglyphs;
  4146. int i;
  4147. fseek (ttf, start, SEEK_SET);
  4148. if (info->math == NULL)
  4149. info->math = xcalloc (1, sizeof (struct MATH));
  4150. info->math->MinConnectorOverlap = getushort (ttf);
  4151. vcoverage = getushort (ttf);
  4152. hcoverage = getushort (ttf);
  4153. vcnt = getushort (ttf);
  4154. hcnt = getushort (ttf);
  4155. hoffs = xmalloc (hcnt * sizeof (int));
  4156. voffs = xmalloc (vcnt * sizeof (int));
  4157. for (i = 0; i < vcnt; ++i)
  4158. voffs[i] = getushort (ttf);
  4159. for (i = 0; i < hcnt; ++i)
  4160. hoffs[i] = getushort (ttf);
  4161. vglyphs = hglyphs = NULL;
  4162. if (vcoverage != 0)
  4163. vglyphs = getCoverageTable (ttf, start + vcoverage, info);
  4164. if (hcoverage != 0)
  4165. hglyphs = getCoverageTable (ttf, start + hcoverage, info);
  4166. if (vglyphs != NULL)
  4167. {
  4168. for (i = 0; i < vcnt; ++i)
  4169. if (vglyphs[i] < info->glyph_cnt && voffs[i] != 0)
  4170. {
  4171. if (justinuse == git_normal || justinuse == git_findnames)
  4172. {
  4173. SplineChar *sc = info->chars[vglyphs[i]];
  4174. if (sc != NULL)
  4175. sc->vert_variants =
  4176. ttf_math_read_gvtable (ttf, info, start + voffs[i],
  4177. justinuse, sc, true);
  4178. }
  4179. else if (info->inuse[vglyphs[i]])
  4180. ttf_math_read_gvtable (ttf, info, start + voffs[i], justinuse,
  4181. NULL, true);
  4182. }
  4183. }
  4184. if (hglyphs != NULL)
  4185. {
  4186. for (i = 0; i < hcnt; ++i)
  4187. if (hglyphs[i] < info->glyph_cnt && hoffs[i] != 0)
  4188. {
  4189. if (justinuse == git_normal || justinuse == git_findnames)
  4190. {
  4191. SplineChar *sc = info->chars[hglyphs[i]];
  4192. if (sc != NULL)
  4193. sc->horiz_variants =
  4194. ttf_math_read_gvtable (ttf, info, start + hoffs[i],
  4195. justinuse, sc, false);
  4196. }
  4197. else if (info->inuse[hglyphs[i]])
  4198. ttf_math_read_gvtable (ttf, info, start + hoffs[i], justinuse,
  4199. NULL, false);
  4200. }
  4201. }
  4202. free (vglyphs);
  4203. free (voffs);
  4204. free (hglyphs);
  4205. free (hoffs);
  4206. }
  4207. static void
  4208. _otf_read_math (FILE *ttf, struct ttfinfo *info, enum gsub_inusetype justinuse)
  4209. {
  4210. int constants, glyphinfo, variants;
  4211. if (info->math_start == 0)
  4212. return;
  4213. fseek (ttf, info->math_start, SEEK_SET);
  4214. info->g_bounds = info->math_start + info->math_length;
  4215. if (getlong (ttf) != 0x00010000)
  4216. return;
  4217. constants = getushort (ttf);
  4218. glyphinfo = getushort (ttf);
  4219. variants = getushort (ttf);
  4220. if (justinuse == git_normal)
  4221. {
  4222. if (constants != 0)
  4223. ttf_math_read_constants (ttf, info, info->math_start + constants);
  4224. if (glyphinfo != 0)
  4225. ttf_math_read_glyphinfo (ttf, info, info->math_start + glyphinfo);
  4226. }
  4227. if (variants != 0)
  4228. ttf_math_read_variants (ttf, info, info->math_start + variants, justinuse);
  4229. if (ftell (ttf) > info->g_bounds)
  4230. {
  4231. LogError (_("MATH table extends beyond table bounds"));
  4232. info->bad_ot = true;
  4233. }
  4234. info->g_bounds = 0;
  4235. }
  4236. void
  4237. otf_read_math (FILE *ttf, struct ttfinfo *info)
  4238. {
  4239. _otf_read_math (ttf, info, git_normal);
  4240. }
  4241. void
  4242. otf_read_math_used (FILE *ttf, struct ttfinfo *info)
  4243. {
  4244. _otf_read_math (ttf, info, git_justinuse);
  4245. }
  4246. void
  4247. GuessNamesFromMATH (FILE *ttf, struct ttfinfo *info)
  4248. {
  4249. _otf_read_math (ttf, info, git_findnames);
  4250. }
  4251. static struct baselangextent *
  4252. readttfbaseminmax (FILE *ttf, uint32_t offset, struct ttfinfo *info,
  4253. uint32_t script_tag, uint32_t lang_tag)
  4254. {
  4255. int j, feat_cnt;
  4256. struct baselangextent *lang, *cur, *last;
  4257. fseek (ttf, offset, SEEK_SET);
  4258. lang = xzalloc (sizeof (struct baselangextent));
  4259. lang->lang = lang_tag;
  4260. lang->descent = (short) getushort (ttf);
  4261. lang->ascent = (short) getushort (ttf);
  4262. feat_cnt = getushort (ttf);
  4263. last = NULL;
  4264. for (j = 0; j < feat_cnt; ++j)
  4265. {
  4266. cur = xzalloc (sizeof (struct baselangextent));
  4267. if (last == NULL)
  4268. lang->features = cur;
  4269. else
  4270. last->next = cur;
  4271. last = cur;
  4272. cur->lang = getlong (ttf); /* Actually feature tag here */
  4273. cur->descent = (short) getushort (ttf);
  4274. cur->ascent = (short) getushort (ttf);
  4275. }
  4276. return lang;
  4277. }
  4278. void
  4279. readttfbase (FILE *ttf, struct ttfinfo *info)
  4280. {
  4281. int version;
  4282. uint32_t axes[2];
  4283. uint32_t basetags, basescripts;
  4284. int basescriptcnt;
  4285. struct tagoff
  4286. {
  4287. uint32_t tag;
  4288. uint32_t offset;
  4289. } *bs;
  4290. int axis, i, j, tot;
  4291. struct Base *curBase;
  4292. struct basescript *curScript, *last;
  4293. struct baselangextent *cur, *lastLang;
  4294. if (info->base_start == 0)
  4295. return;
  4296. fseek (ttf, info->base_start, SEEK_SET);
  4297. version = getlong (ttf);
  4298. if (version != 0x00010000)
  4299. return;
  4300. axes[0] = getushort (ttf); /* Horizontal */
  4301. axes[1] = getushort (ttf); /* Vertical */
  4302. for (axis = 0; axis < 2; ++axis)
  4303. {
  4304. if (axes[axis] == 0)
  4305. continue;
  4306. fseek (ttf, info->base_start + axes[axis], SEEK_SET);
  4307. curBase = xzalloc (sizeof (struct Base));
  4308. if (axis == 0)
  4309. info->horiz_base = curBase;
  4310. else
  4311. info->vert_base = curBase;
  4312. basetags = getushort (ttf);
  4313. basescripts = getushort (ttf);
  4314. if (basetags == 0)
  4315. {
  4316. curBase->baseline_cnt = 0;
  4317. curBase->baseline_tags = NULL;
  4318. }
  4319. else
  4320. {
  4321. fseek (ttf, info->base_start + axes[axis] + basetags, SEEK_SET);
  4322. curBase->baseline_cnt = getushort (ttf);
  4323. curBase->baseline_tags =
  4324. xcalloc (curBase->baseline_cnt, sizeof (uint32_t));
  4325. for (i = 0; i < curBase->baseline_cnt; ++i)
  4326. curBase->baseline_tags[i] = getlong (ttf);
  4327. }
  4328. if (basescripts != 0)
  4329. {
  4330. fseek (ttf, info->base_start + axes[axis] + basescripts, SEEK_SET);
  4331. basescriptcnt = getushort (ttf);
  4332. bs = xcalloc (basescriptcnt, sizeof (struct tagoff));
  4333. for (i = 0; i < basescriptcnt; ++i)
  4334. {
  4335. bs[i].tag = getlong (ttf);
  4336. bs[i].offset = getushort (ttf);
  4337. if (bs[i].offset != 0)
  4338. bs[i].offset += info->base_start + axes[axis] + basescripts;
  4339. }
  4340. last = NULL;
  4341. for (i = 0; i < basescriptcnt; ++i)
  4342. if (bs[i].offset != 0)
  4343. {
  4344. int basevalues, defminmax;
  4345. int langsyscnt;
  4346. struct tagoff *ls;
  4347. fseek (ttf, bs[i].offset, SEEK_SET);
  4348. basevalues = getushort (ttf);
  4349. defminmax = getushort (ttf);
  4350. langsyscnt = getushort (ttf);
  4351. ls = xcalloc (langsyscnt, sizeof (struct tagoff));
  4352. for (j = 0; j < langsyscnt; ++j)
  4353. {
  4354. ls[j].tag = getlong (ttf);
  4355. ls[j].offset = getushort (ttf);
  4356. }
  4357. curScript =
  4358. xzalloc (sizeof (struct basescript));
  4359. if (last == NULL)
  4360. curBase->scripts = curScript;
  4361. else
  4362. last->next = curScript;
  4363. last = curScript;
  4364. curScript->script = bs[i].tag;
  4365. if (basevalues != 0)
  4366. {
  4367. int coordcnt;
  4368. int *coords;
  4369. fseek (ttf, bs[i].offset + basevalues, SEEK_SET);
  4370. curScript->def_baseline = getushort (ttf);
  4371. tot = coordcnt = getushort (ttf);
  4372. if (coordcnt != curBase->baseline_cnt)
  4373. {
  4374. info->bad_ot = true;
  4375. LogError (_
  4376. ("!!!!! Coord count (%d) for '%c%c%c%c' script does not match base tag count (%d) in 'BASE' table\n"),
  4377. coordcnt, bs[i].tag >> 24, bs[i].tag >> 16,
  4378. bs[i].tag >> 8, bs[i].tag,
  4379. curBase->baseline_cnt);
  4380. if (tot < curBase->baseline_cnt)
  4381. tot = curBase->baseline_cnt;
  4382. }
  4383. coords = xcalloc (coordcnt, sizeof (int));
  4384. curScript->baseline_pos = xcalloc (tot, sizeof (int16_t));
  4385. for (j = 0; j < coordcnt; ++j)
  4386. coords[j] = getushort (ttf);
  4387. for (j = 0; j < coordcnt; ++j)
  4388. if (coords[j] != 0)
  4389. {
  4390. int format;
  4391. fseek (ttf, bs[i].offset + basevalues + coords[j],
  4392. SEEK_SET);
  4393. format = getushort (ttf);
  4394. curScript->baseline_pos[j] = (short) getushort (ttf);
  4395. if (format != 1 && format != 2 && format != 3)
  4396. {
  4397. info->bad_ot = true;
  4398. LogError (_
  4399. ("!!!!! Bad Base Coord format (%d) for '%c%c%c%c' in '%c%c%c%c' script in 'BASE' table\n"),
  4400. format, curBase->baseline_tags[j] >> 24,
  4401. curBase->baseline_tags[j] >> 16,
  4402. curBase->baseline_tags[j] >> 8,
  4403. curBase->baseline_tags[j],
  4404. bs[i].tag >> 24, bs[i].tag >> 16,
  4405. bs[i].tag >> 8, bs[i].tag);
  4406. }
  4407. }
  4408. free (coords);
  4409. }
  4410. else
  4411. {
  4412. curScript->baseline_pos =
  4413. xcalloc (curBase->baseline_cnt, sizeof (int16_t));
  4414. }
  4415. lastLang = NULL;
  4416. if (defminmax != 0)
  4417. curScript->langs = lastLang =
  4418. readttfbaseminmax (ttf, bs[i].offset + defminmax, info,
  4419. bs[i].tag, DEFAULT_LANG);
  4420. if (langsyscnt != 0)
  4421. {
  4422. for (j = 0; j < langsyscnt; ++j)
  4423. if (ls[j].offset != 0)
  4424. {
  4425. cur =
  4426. readttfbaseminmax (ttf, bs[i].offset + ls[j].offset,
  4427. info, bs[i].tag, ls[j].tag);
  4428. if (lastLang == NULL)
  4429. curScript->langs = cur;
  4430. else
  4431. lastLang->next = cur;
  4432. lastLang = cur;
  4433. }
  4434. }
  4435. free (ls);
  4436. }
  4437. }
  4438. free (bs);
  4439. }
  4440. }
  4441. static char *
  4442. jstf_read_extenders (FILE *ttf, uint32_t spos, int extendOff,
  4443. struct ttfinfo *info)
  4444. {
  4445. uint16_t *glyphs;
  4446. int cnt, i;
  4447. char *ret;
  4448. if (extendOff == 0)
  4449. return NULL;
  4450. if (spos + extendOff + 2 > info->g_bounds)
  4451. {
  4452. LogError (_("JSTF table is too long.\n"));
  4453. info->bad_ot = true;
  4454. return NULL;
  4455. }
  4456. fseek (ttf, spos + extendOff, SEEK_SET);
  4457. cnt = getushort (ttf);
  4458. if (spos + extendOff + 2 + 2 * cnt > info->g_bounds || cnt < 0)
  4459. {
  4460. LogError (_("JSTF table is too long.\n"));
  4461. info->bad_ot = true;
  4462. return NULL;
  4463. }
  4464. if (cnt == 0)
  4465. return NULL;
  4466. glyphs = xmalloc ((cnt + 1) * sizeof (uint16_t));
  4467. for (i = 0; i < cnt; ++i)
  4468. {
  4469. glyphs[i] = getushort (ttf);
  4470. if (glyphs[i] >= info->glyph_cnt)
  4471. {
  4472. LogError (_("Bad GID in JSTF extenser table.\n"));
  4473. glyphs[i] = 0;
  4474. info->bad_ot = true;
  4475. }
  4476. }
  4477. glyphs[i] = 0xffff;
  4478. ret = GlyphsToNames (info, glyphs, false);
  4479. free (glyphs);
  4480. return ret;
  4481. }
  4482. static OTLookup *
  4483. findLookupByIndex (OTLookup *lookups, int index)
  4484. {
  4485. while (index > 0)
  4486. {
  4487. if (lookups == NULL)
  4488. return NULL;
  4489. lookups = lookups->next;
  4490. --index;
  4491. }
  4492. return lookups;
  4493. }
  4494. static OTLookup **
  4495. jstf_subpos (FILE *ttf, uint32_t base, int Sub, int Pos, struct ttfinfo *info)
  4496. {
  4497. int scnt = 0, pcnt = 0;
  4498. OTLookup **ret;
  4499. int i;
  4500. if (Sub > 0)
  4501. {
  4502. fseek (ttf, base + Sub, SEEK_SET);
  4503. scnt = getushort (ttf);
  4504. if (base + Sub + 2 + scnt * sizeof (int16_t) > info->g_bounds || scnt < 0)
  4505. {
  4506. LogError (_("JSTF table is too long.\n"));
  4507. info->bad_ot = true;
  4508. return NULL;
  4509. }
  4510. }
  4511. if (Pos > 0)
  4512. {
  4513. fseek (ttf, base + Pos, SEEK_SET);
  4514. pcnt = getushort (ttf);
  4515. if (base + Pos + 2 + pcnt * sizeof (int16_t) > info->g_bounds || pcnt < 0)
  4516. {
  4517. LogError (_("JSTF table is too long.\n"));
  4518. info->bad_ot = true;
  4519. return NULL;
  4520. }
  4521. }
  4522. if (scnt == 0 && pcnt == 0)
  4523. return NULL;
  4524. ret = xmalloc ((scnt + pcnt + 1) * sizeof (OTLookup *));
  4525. if (Sub > 0)
  4526. {
  4527. fseek (ttf, base + Sub + 2, SEEK_SET);
  4528. for (i = 0; i < scnt; ++i)
  4529. {
  4530. int index = getushort (ttf);
  4531. if (index < 0)
  4532. {
  4533. LogError (_("JSTF table is too long.\n"));
  4534. info->bad_ot = true;
  4535. return NULL;
  4536. }
  4537. ret[i] = findLookupByIndex (info->gsub_lookups, index);
  4538. if (ret[i] == NULL)
  4539. {
  4540. LogError (_
  4541. ("Lookup index (%d) out of bounds in GSUB from JSTF table.\n"),
  4542. index);
  4543. info->bad_ot = true;
  4544. return NULL;
  4545. }
  4546. }
  4547. ret[i] = NULL;
  4548. }
  4549. if (Pos > 0)
  4550. {
  4551. fseek (ttf, base + Pos + 2, SEEK_SET);
  4552. for (i = 0; i < pcnt; ++i)
  4553. {
  4554. int index = getushort (ttf);
  4555. if (index < 0)
  4556. {
  4557. LogError (_("JSTF table is too long.\n"));
  4558. info->bad_ot = true;
  4559. return NULL;
  4560. }
  4561. ret[i + scnt] = findLookupByIndex (info->gpos_lookups, index);
  4562. if (ret[i + scnt] == NULL)
  4563. {
  4564. LogError (_
  4565. ("Lookup index (%d) out of bounds in GPOS from JSTF table.\n"),
  4566. index);
  4567. info->bad_ot = true;
  4568. return NULL;
  4569. }
  4570. }
  4571. ret[i + scnt] = NULL;
  4572. }
  4573. return ret;
  4574. }
  4575. static void
  4576. NameOTJSTFLookup (OTLookup *otl, struct ttfinfo *info)
  4577. {
  4578. char buffer[300], *format;
  4579. struct lookup_subtable *subtable;
  4580. int cnt;
  4581. if (info->jstf_isShrink)
  4582. /* TRANSLATORS: This string is used to generate a name for an OpenType lookup. */
  4583. /* the %c%c... is the language followed by the script (OT tags) */
  4584. snprintf (buffer, sizeof (buffer),
  4585. _
  4586. ("JSTF shrinkage max at priority %d #%d for %c%c%c%c in %c%c%c%c"),
  4587. info->jstf_prio, info->jstf_lcnt++, info->jstf_lang >> 24,
  4588. info->jstf_lang >> 16, info->jstf_lang >> 8, info->jstf_lang,
  4589. info->jstf_script >> 24, info->jstf_script >> 16,
  4590. info->jstf_script >> 8, info->jstf_script);
  4591. else
  4592. snprintf (buffer, sizeof (buffer),
  4593. _
  4594. ("JSTF extension max at priority %d #%d for %c%c%c%c in %c%c%c%c"),
  4595. info->jstf_prio, info->jstf_lcnt++, info->jstf_lang >> 24,
  4596. info->jstf_lang >> 16, info->jstf_lang >> 8, info->jstf_lang,
  4597. info->jstf_script >> 24, info->jstf_script >> 16,
  4598. info->jstf_script >> 8, info->jstf_script);
  4599. otl->lookup_name = xstrdup_or_null (buffer);
  4600. cnt = 0;
  4601. for (subtable = otl->subtables; subtable != NULL;
  4602. subtable = subtable->next, ++cnt)
  4603. {
  4604. if (subtable->subtable_name == NULL)
  4605. {
  4606. if (subtable == otl->subtables && subtable->next == NULL)
  4607. format = _("%s subtable");
  4608. else
  4609. format = _("%s subtable %d");
  4610. snprintf (buffer, sizeof (buffer), format, otl->lookup_name, cnt);
  4611. subtable->subtable_name = xstrdup_or_null (buffer);
  4612. }
  4613. }
  4614. }
  4615. static OTLookup **
  4616. jstf_processlookups (FILE *ttf, uint32_t base, int lookup_off,
  4617. struct ttfinfo *info)
  4618. {
  4619. OTLookup **ret;
  4620. struct lookup *lookups, *l;
  4621. struct lookup_subtable *subtable;
  4622. int cnt, k;
  4623. int32_t st;
  4624. if (lookup_off == 0)
  4625. return NULL;
  4626. lookups = readttflookups (ttf, base + lookup_off, info, 2);
  4627. if (lookups == NULL)
  4628. return NULL;
  4629. for (l = lookups, cnt = 0; l->offset != 0; ++l, ++cnt)
  4630. {
  4631. for (k = 0, subtable = l->otlookup->subtables; k < l->subtabcnt;
  4632. ++k, subtable = subtable->next)
  4633. {
  4634. st = l->subtab_offsets[k];
  4635. fseek (ttf, st, SEEK_SET);
  4636. gposLookupSwitch (ttf, st, info, l, subtable, lookups);
  4637. }
  4638. }
  4639. ret = xmalloc ((cnt + 1) * sizeof (OTLookup *));
  4640. for (l = lookups, cnt = 0; l->offset != 0; ++l, ++cnt)
  4641. {
  4642. NameOTJSTFLookup (l->otlookup, info);
  4643. ret[cnt] = l->otlookup;
  4644. }
  4645. ret[cnt] = NULL;
  4646. LookupsFree (lookups);
  4647. return ret;
  4648. }
  4649. static struct jstf_lang *
  4650. jstf_lang (FILE *ttf, uint32_t base,
  4651. int off, uint32_t tag, struct ttfinfo *info)
  4652. {
  4653. int cnt, i;
  4654. struct jstf_lang *ret;
  4655. if (off <= 0)
  4656. return NULL;
  4657. if (base + off + 2 > info->g_bounds)
  4658. {
  4659. LogError (_("JSTF table is too long.\n"));
  4660. info->bad_ot = true;
  4661. return NULL;
  4662. }
  4663. fseek (ttf, base + off, SEEK_SET);
  4664. cnt = getushort (ttf);
  4665. if (base + off + 2 + 2 * cnt > info->g_bounds || cnt < 0)
  4666. {
  4667. LogError (_("JSTF table is too long.\n"));
  4668. info->bad_ot = true;
  4669. return NULL;
  4670. }
  4671. if (cnt == 0)
  4672. return NULL;
  4673. ret = xzalloc (sizeof (struct jstf_lang));
  4674. ret->lang = info->jstf_lang = tag;
  4675. ret->cnt = cnt;
  4676. ret->prios = xcalloc (cnt, sizeof (struct jstf_prio));
  4677. for (i = 0; i < cnt; ++i)
  4678. ret->prios[i].maxExtend = (void *) (intptr_t) getushort (ttf);
  4679. for (i = 0; i < cnt; ++i)
  4680. {
  4681. int enSub, disSub, enPos, disPos, maxShrink, maxExtend;
  4682. int enSub2, disSub2, enPos2, disPos2;
  4683. uint32_t pbase = base + off + (intptr_t) ret->prios[i].maxExtend;
  4684. fseek (ttf, pbase, SEEK_SET);
  4685. info->jstf_prio = i;
  4686. enSub = getushort (ttf);
  4687. disSub = getushort (ttf);
  4688. enPos = getushort (ttf);
  4689. disPos = getushort (ttf);
  4690. maxShrink = getushort (ttf);
  4691. enSub2 = getushort (ttf);
  4692. disSub2 = getushort (ttf);
  4693. enPos2 = getushort (ttf);
  4694. disPos2 = getushort (ttf);
  4695. maxExtend = getushort (ttf);
  4696. ret->prios[i].enableShrink = jstf_subpos (ttf, pbase, enSub, enPos, info);
  4697. ret->prios[i].disableShrink =
  4698. jstf_subpos (ttf, pbase, disSub, disPos, info);
  4699. ret->prios[i].enableExtend =
  4700. jstf_subpos (ttf, pbase, enSub2, enPos2, info);
  4701. ret->prios[i].disableExtend =
  4702. jstf_subpos (ttf, pbase, disSub2, disPos2, info);
  4703. info->jstf_isShrink = true;
  4704. ret->prios[i].maxShrink =
  4705. jstf_processlookups (ttf, pbase, maxShrink, info);
  4706. info->jstf_isShrink = false;
  4707. ret->prios[i].maxExtend =
  4708. jstf_processlookups (ttf, pbase, maxExtend, info);
  4709. }
  4710. return ret;
  4711. }
  4712. void
  4713. readttfjstf (FILE *ttf, struct ttfinfo *info)
  4714. {
  4715. int version;
  4716. int scnt, lcnt, lmax;
  4717. int i, j;
  4718. struct tagoff
  4719. {
  4720. uint32_t tag;
  4721. int offset;
  4722. } *soff, *loff;
  4723. Justify *last = NULL, *cur;
  4724. struct jstf_lang *llast, *lcur;
  4725. int extendOff, defOff;
  4726. if (info->jstf_start == 0)
  4727. return;
  4728. fseek (ttf, info->jstf_start, SEEK_SET);
  4729. info->g_bounds = info->jstf_start + info->jstf_length;
  4730. version = getlong (ttf);
  4731. if (version != 0x00010000)
  4732. return;
  4733. scnt = getushort (ttf);
  4734. if (scnt < 0 || scnt > 1000)
  4735. {
  4736. LogError (_
  4737. ("Unlikely script count (%d), I suspect the JSTF-\n table is garbage, I'm giving up on it.\n"),
  4738. scnt);
  4739. info->bad_ot = true;
  4740. return;
  4741. }
  4742. soff = xmalloc (scnt * sizeof (struct tagoff));
  4743. for (i = 0; i < scnt; ++i)
  4744. {
  4745. soff[i].tag = getlong (ttf);
  4746. soff[i].offset = getushort (ttf);
  4747. if (soff[i].offset < 0)
  4748. {
  4749. LogError (_("End of file found in JSTF table.\n"));
  4750. info->bad_ot = true;
  4751. return;
  4752. }
  4753. }
  4754. if (ftell (ttf) > info->g_bounds)
  4755. {
  4756. LogError (_("JSTF table is too long.\n"));
  4757. info->bad_ot = true;
  4758. return;
  4759. }
  4760. lmax = 0;
  4761. loff = NULL;
  4762. for (i = 0; i < scnt; ++i)
  4763. {
  4764. fseek (ttf, info->jstf_start + soff[i].offset, SEEK_SET);
  4765. extendOff = getushort (ttf);
  4766. defOff = getushort (ttf);
  4767. lcnt = getushort (ttf);
  4768. if (info->jstf_start + soff[i].offset > info->g_bounds - 6 - 6 * lcnt
  4769. || lcnt < 0)
  4770. {
  4771. LogError (_("JSTF table is too long.\n"));
  4772. info->bad_ot = true;
  4773. return;
  4774. }
  4775. if (lcnt > lmax)
  4776. loff = xrealloc (loff, (lmax = lcnt) * sizeof (struct tagoff));
  4777. for (j = 0; j < lcnt; ++j)
  4778. {
  4779. loff[j].tag = getlong (ttf);
  4780. loff[j].offset = getushort (ttf);
  4781. if (loff[j].offset < 0)
  4782. {
  4783. LogError (_("End of file found in JSTF table.\n"));
  4784. info->bad_ot = true;
  4785. return;
  4786. }
  4787. }
  4788. cur = xzalloc (sizeof (Justify));
  4789. cur->script = info->jstf_script = soff[i].tag;
  4790. if (last == NULL)
  4791. info->justify = cur;
  4792. else
  4793. last->next = cur;
  4794. last = cur;
  4795. cur->extenders =
  4796. jstf_read_extenders (ttf, info->jstf_start + soff[i].offset, extendOff,
  4797. info);
  4798. llast = NULL;
  4799. if (defOff != 0)
  4800. llast = cur->langs =
  4801. jstf_lang (ttf, info->jstf_start + soff[i].offset, defOff,
  4802. DEFAULT_LANG, info);
  4803. for (j = 0; j < lcnt; ++j)
  4804. {
  4805. lcur = jstf_lang (ttf, info->jstf_start + soff[i].offset,
  4806. loff[j].offset, loff[j].tag, info);
  4807. if (lcur != NULL)
  4808. {
  4809. if (llast == NULL)
  4810. cur->langs = lcur;
  4811. else
  4812. llast->next = lcur;
  4813. llast = lcur;
  4814. }
  4815. }
  4816. }
  4817. free (loff);
  4818. free (soff);
  4819. }