PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/fontforge/tottfgpos.c

https://bitbucket.org/sortsmill/sortsmill-tools
C | 5571 lines | 4941 code | 397 blank | 233 comment | 1955 complexity | fb79f565cec60f1267722303855b2deb 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 "fontforgevw.h"
  39. #include <utype.h>
  40. #include <ustring.h>
  41. VISIBLE int coverageformatsallowed = 3;
  42. VISIBLE int use_second_indic_scripts = false;
  43. #include "ttf.h"
  44. /* This file contains routines to create the otf gpos and gsub tables and their */
  45. /* attendant subtables */
  46. /* Undocumented fact: ATM (which does kerning for otf fonts in Word) can't handle features with multiple lookups */
  47. /* Undocumented fact: Only one feature with a given tag allowed per script/lang */
  48. /* So if we have multiple lookups with the same tag they must be merged into */
  49. /* one feature with many lookups */
  50. /* scripts (for opentype) that I understand */
  51. /* see also list in lookups.c mapping script tags to friendly names */
  52. static uint32_t scripts[][15] = {
  53. /* Arabic */ {CHR ('a', 'r', 'a', 'b'), 0x0600, 0x06ff, 0xfb50, 0xfdff,
  54. 0xfe70, 0xfefe},
  55. /* Aramaic */ {CHR ('a', 'r', 'a', 'm'), 0x820, 0x83f},
  56. /* Armenian */ {CHR ('a', 'r', 'm', 'n'), 0x0530, 0x058f, 0xfb13, 0xfb17},
  57. /* Balinese */ {CHR ('b', 'a', 'l', 'i'), 0x1b00, 0x1b7f},
  58. /* Bengali */ {CHR ('b', 'e', 'n', 'g'), 0x0980, 0x09ff},
  59. /* Bliss symb */ {CHR ('b', 'l', 'i', 's'), 0x12200, 0x124ff},
  60. /* Bopomofo */ {CHR ('b', 'o', 'p', 'o'), 0x3100, 0x312f, 0x31a0, 0x31bf},
  61. /* Braille */ {CHR ('b', 'r', 'a', 'i'), 0x2800, 0x28ff},
  62. /* Buginese */ {CHR ('b', 'u', 'g', 'i'), 0x1a00, 0x1a1f},
  63. /* Buhid */ {CHR ('b', 'u', 'h', 'd'), 0x1740, 0x1753},
  64. /* Byzantine M*/ {CHR ('b', 'y', 'z', 'm'), 0x1d000, 0x1d0ff},
  65. /* Canadian Syl*/ {CHR ('c', 'a', 'n', 's'), 0x1400, 0x167f},
  66. /* Carian */ {CHR ('c', 'a', 'r', 'i'), 0x0, 0x0},
  67. /* Cham */ {CHR ('c', 'h', 'a', 'm'), 0x0, 0x0},
  68. /* Cherokee */ {CHR ('c', 'h', 'e', 'r'), 0x13a0, 0x13ff},
  69. /* Cirth */ {CHR ('c', 'i', 'r', 't'), 0x12080, 0x120ff},
  70. /* CJKIdeogra */ {CHR ('h', 'a', 'n', 'i'), 0x3300, 0x9fff, 0xf900, 0xfaff,
  71. 0x020000, 0x02ffff},
  72. /* Coptic */ {CHR ('c', 'o', 'p', 't'), 0x2c80, 0x2cff},
  73. /* Cypriot */ {CHR ('c', 'p', 'm', 'n'), 0x10800, 0x1083f},
  74. /* Cyrillic */ {CHR ('c', 'y', 'r', 'l'), 0x0400, 0x052f, 0x1d2b, 0x1d2b,
  75. 0x1d78, 0x1d78,
  76. 0x2de0, 0x2dff, 0xa640, 0xa6ff},
  77. /* Deseret */ {CHR ('d', 's', 'r', 't'), 0x10400, 0x1044f},
  78. /* Devanagari */ {CHR ('d', 'e', 'v', 'a'), 0x0900, 0x097f},
  79. /* Ethiopic */ {CHR ('e', 't', 'h', 'i'), 0x1200, 0x139f},
  80. /* Georgian */ {CHR ('g', 'e', 'o', 'r'), 0x1080, 0x10ff},
  81. /* Glagolitic */ {CHR ('g', 'l', 'a', 'g'), 0x1080, 0x10ff},
  82. /* Gothic */ {CHR ('g', 'o', 't', 'h'), 0x10330, 0x1034a},
  83. /* Greek */ {CHR ('g', 'r', 'e', 'k'), 0x0370, 0x03ff, 0x1f00, 0x1fff},
  84. /* Gujarati */ {CHR ('g', 'u', 'j', 'r'), 0x0a80, 0x0aff},
  85. /* Gurmukhi */ {CHR ('g', 'u', 'r', 'u'), 0x0a00, 0x0a7f},
  86. /* Hangul */ {CHR ('h', 'a', 'n', 'g'), 0xac00, 0xd7af, 0x3130, 0x319f,
  87. 0xffa0, 0xff9f},
  88. /* Hanunoo */ {CHR ('h', 'a', 'n', 'o'), 0x1720, 0x1734},
  89. /* I'm not sure what the difference is between the 'hang' tag and the 'jamo' */
  90. /* tag. 'Jamo' is said to be the precomposed forms, but what's 'hang'? */
  91. /* Hebrew */ {CHR ('h', 'e', 'b', 'r'), 0x0590, 0x05ff, 0xfb1e, 0xfb4f},
  92. #if 0 /* Hiragana used to have its own tag, but has since been merged with katakana */
  93. /* Hiragana */ {CHR ('h', 'i', 'r', 'a'), 0x3040, 0x309f},
  94. #endif
  95. /* Hangul Jamo*/ {CHR ('j', 'a', 'm', 'o'), 0x1100, 0x11ff, 0x3130, 0x319f,
  96. 0xffa0, 0xffdf},
  97. /* Javanese */ {CHR ('j', 'a', 'v', 'a'), 0},
  98. /* MS has a tag, but there is no unicode range */
  99. /* Katakana */ {CHR ('k', 'a', 'n', 'a'), 0x3040, 0x30ff, 0xff60, 0xff9f},
  100. /* Kayah Li */ {CHR ('k', 'a', 'l', 'i'), 0},
  101. /* Kannada */ {CHR ('k', 'n', 'd', 'a'), 0x0c80, 0x0cff},
  102. /* Kharosthi */ {CHR ('k', 'h', 'a', 'r'), 0x10a00, 0x10a5f},
  103. /* Khmer */ {CHR ('k', 'h', 'm', 'r'), 0x1780, 0x17ff},
  104. /* Latin */ {CHR ('l', 'a', 't', 'n'), 0x0041, 0x005a, 0x0061, 0x007a,
  105. 0x00c0, 0x02af, 0x1d00, 0x1eff, 0xfb00, 0xfb0f, 0xff00, 0xff5f,
  106. 0xa770, 0xa7ff},
  107. /* Lao */ {CHR ('l', 'a', 'o', ' '), 0x0e80, 0x0eff},
  108. /* Lepcha */ {CHR ('l', 'e', 'p', 'c'), 0},
  109. /* Limbu */ {CHR ('l', 'i', 'm', 'b'), 0x1900, 0x194f},
  110. /* Linear A *//*{ CHR('l','i','n','a'), 0x10180, 0x102cf }, *//* What happened to linear A? */
  111. /* Linear B */ {CHR ('l', 'i', 'n', 'b'), 0x10000, 0x100fa},
  112. /* Lycian */ {CHR ('l', 'y', 'c', 'i'), 0},
  113. /* Lydian */ {CHR ('l', 'y', 'd', 'i'), 0},
  114. /* Malayalam */ {CHR ('m', 'l', 'y', 'm'), 0x0d00, 0x0d7f},
  115. /* Mathematical Alphanumeric Symbols */
  116. {CHR ('m', 'a', 't', 'h'), 0x1d400, 0x1d7ff},
  117. /* Mongolian */ {CHR ('m', 'o', 'n', 'g'), 0x1800, 0x18af},
  118. /* Musical */ {CHR ('m', 'u', 's', 'c'), 0x1d100, 0x1d1ff},
  119. /* Myanmar */ {CHR ('m', 'y', 'm', 'r'), 0x1000, 0x107f},
  120. /* New Tai Lue*/ {CHR ('t', 'a', 'l', 'u'), 0},
  121. /* N'Ko */ {CHR ('n', 'k', 'o', ' '), 0x07c0, 0x07fa},
  122. /* Ogham */ {CHR ('o', 'g', 'a', 'm'), 0x1680, 0x169f},
  123. /* Ol Chiki */ {CHR ('o', 'l', 'c', 'k'), 0},
  124. /* Old Italic */ {CHR ('i', 't', 'a', 'l'), 0x10300, 0x1031e},
  125. /* Old Permic */ {CHR ('p', 'e', 'r', 'm'), 0x10350, 0x1037f},
  126. /* Old Persian cuneiform */
  127. {CHR ('x', 'p', 'e', 'o'), 0x103a0, 0x103df},
  128. /* Oriya */ {CHR ('o', 'r', 'y', 'a'), 0x0b00, 0x0b7f},
  129. /* Osmanya */ {CHR ('o', 's', 'm', 'a'), 0x10480, 0x104a9},
  130. /* Phags-pa */ {CHR ('p', 'h', 'a', 'g'), 0xa840, 0xa87f},
  131. /* Phoenician */ {CHR ('p', 'h', 'n', 'x'), 0x10900, 0x1091f},
  132. /* Pollard */ {CHR ('p', 'l', 'r', 'd'), 0x104b0, 0x104d9},
  133. /* Rejang */ {CHR ('r', 'j', 'n', 'g'), 0},
  134. /* Rongorongo */ {CHR ('r', 'o', 'r', 'o'), 0},
  135. /* Runic */ {CHR ('r', 'u', 'n', 'r'), 0x16a0, 0x16ff},
  136. /* Saurashtra*/ {CHR ('s', 'a', 'u', 'r'), 0},
  137. /* Shavian */ {CHR ('s', 'h', 'a', 'w'), 0x10450, 0x1047f},
  138. /* Sinhala */ {CHR ('s', 'i', 'n', 'h'), 0x0d80, 0x0dff},
  139. /* Sumero-Akkadian Cuneiform */
  140. {CHR ('x', 's', 'u', 'x'), 0x12000, 0x1236e},
  141. /* Sundanese */ {CHR ('s', 'u', 'n', 'd'), 0},
  142. /* Syloti Nagri */
  143. {CHR ('s', 'y', 'l', 'o'), 0xa800, 0xa82f},
  144. /* Syriac */ {CHR ('s', 'y', 'r', 'c'), 0x0700, 0x074f},
  145. /* Tagalog */ {CHR ('t', 'a', 'g', 'l'), 0x1700, 0x1714},
  146. /* Tagbanwa */ {CHR ('t', 'a', 'g', 'b'), 0x1760, 0x1773},
  147. /* Tai Le */ {CHR ('t', 'a', 'l', 'e'), 0x1950, 0x1974},
  148. /* Tai Lu */ {CHR ('t', 'a', 'l', 'u'), 0x1980, 0x19df},
  149. /* Tamil */ {CHR ('t', 'a', 'm', 'l'), 0x0b80, 0x0bff},
  150. /* Telugu */ {CHR ('t', 'e', 'l', 'u'), 0x0c00, 0x0c7f},
  151. /* Tengwar */ {CHR ('t', 'e', 'n', 'g'), 0x12000, 0x1207f},
  152. /* Thaana */ {CHR ('t', 'h', 'a', 'a'), 0x0780, 0x07bf},
  153. /* Thai */ {CHR ('t', 'h', 'a', 'i'), 0x0e00, 0x0e7f},
  154. /* Tibetan */ {CHR ('t', 'i', 'b', 't'), 0x0f00, 0x0fff},
  155. /* Tifinagh */ {CHR ('t', 'f', 'n', 'g'), 0x2d30, 0x2d7f},
  156. /* Ugaritic */ {CHR ('u', 'g', 'a', 'r'), 0x10380, 0x1039d},
  157. /* Yi */ {CHR ('y', 'i', ' ', ' '), 0xa000, 0xa4c6},
  158. {0}
  159. };
  160. void
  161. ScriptMainRange (uint32_t script, int *start, int *end)
  162. {
  163. int i;
  164. for (i = 0; scripts[i][0] != 0; ++i)
  165. {
  166. if (scripts[i][0] == script)
  167. {
  168. *start = scripts[i][1];
  169. *end = scripts[i][2];
  170. return;
  171. }
  172. }
  173. *start = *end = -1;
  174. }
  175. int
  176. ScriptIsRightToLeft (uint32_t script)
  177. {
  178. if (script == CHR ('a', 'r', 'a', 'b') || script == CHR ('h', 'e', 'b', 'r')
  179. || script == CHR ('c', 'p', 'm', 'n')
  180. || script == CHR ('k', 'h', 'a', 'r')
  181. || script == CHR ('s', 'y', 'r', 'c')
  182. || script == CHR ('t', 'h', 'a', 'a')
  183. || script == CHR ('n', 'k', 'o', ' '))
  184. return true;
  185. return false;
  186. }
  187. uint32_t
  188. ScriptFromUnicode (int u, SplineFont *sf)
  189. {
  190. int s, k;
  191. if (u != -1)
  192. {
  193. for (s = 0; scripts[s][0] != 0; ++s)
  194. {
  195. for (k = 1; scripts[s][k + 1] != 0; k += 2)
  196. if (u >= scripts[s][k] && u <= scripts[s][k + 1])
  197. break;
  198. if (scripts[s][k + 1] != 0)
  199. break;
  200. }
  201. if (scripts[s][0] != 0)
  202. {
  203. uint32_t script = scripts[s][0];
  204. if (use_second_indic_scripts)
  205. {
  206. /* MS has a parallel set of script tags for their new */
  207. /* Indic font shaper */
  208. if (script == CHR ('b', 'e', 'n', 'g'))
  209. script = CHR ('b', 'n', 'g', '2');
  210. else if (script == CHR ('d', 'e', 'v', 'a'))
  211. script = CHR ('d', 'e', 'v', '2');
  212. else if (script == CHR ('g', 'u', 'j', 'r'))
  213. script = CHR ('g', 'j', 'r', '2');
  214. else if (script == CHR ('g', 'u', 'r', 'u'))
  215. script = CHR ('g', 'u', 'r', '2');
  216. else if (script == CHR ('k', 'n', 'd', 'a'))
  217. script = CHR ('k', 'n', 'd', '2');
  218. else if (script == CHR ('m', 'l', 'y', 'm'))
  219. script = CHR ('m', 'l', 'm', '2');
  220. else if (script == CHR ('o', 'r', 'y', 'a'))
  221. script = CHR ('o', 'r', 'y', '2');
  222. else if (script == CHR ('t', 'a', 'm', 'l'))
  223. script = CHR ('t', 'm', 'l', '2');
  224. else if (script == CHR ('t', 'e', 'l', 'u'))
  225. script = CHR ('t', 'e', 'l', '2');
  226. }
  227. return script;
  228. }
  229. }
  230. else if (sf != NULL)
  231. {
  232. if (sf->cidmaster != NULL || sf->subfontcnt != 0)
  233. {
  234. if (sf->cidmaster != NULL)
  235. sf = sf->cidmaster;
  236. if (strcasecmp (sf->ordering, "Identity") == 0)
  237. return DEFAULT_SCRIPT;
  238. else if (strcasecmp (sf->ordering, "Korean") == 0)
  239. return CHR ('h', 'a', 'n', 'g');
  240. else
  241. return CHR ('h', 'a', 'n', 'i');
  242. }
  243. }
  244. return DEFAULT_SCRIPT;
  245. }
  246. uint32_t
  247. SCScriptFromUnicode (SplineChar *sc)
  248. {
  249. char *pt;
  250. PST *pst;
  251. SplineFont *sf;
  252. int i;
  253. unsigned uni;
  254. FeatureScriptLangList *features;
  255. if (sc == NULL)
  256. return DEFAULT_SCRIPT;
  257. sf = sc->parent;
  258. if (sc->unicodeenc != -1 &&
  259. !(sc->unicodeenc >= 0xe000 && sc->unicodeenc < 0xf8ff) &&
  260. !(sc->unicodeenc >= 0xf0000 && sc->unicodeenc < 0x10ffff))
  261. return ScriptFromUnicode (sc->unicodeenc, sf);
  262. pt = sc->name;
  263. if (*pt)
  264. for (++pt; *pt != '\0' && *pt != '_' && *pt != '.'; ++pt)
  265. ;
  266. if (*pt != '\0')
  267. {
  268. char *str = xstrndup (sc->name, pt - sc->name);
  269. int uni = sf == NULL
  270. || sf->fv == NULL ? UniFromName (str, ui_none,
  271. &custom) : UniFromName (str,
  272. sf->uni_interp,
  273. sf->fv->map->
  274. enc);
  275. free (str);
  276. if (uni != -1)
  277. return ScriptFromUnicode (uni, sf);
  278. }
  279. /* Adobe ligature uniXXXXXXXX */
  280. if (strncmp (sc->name, "uni", 3) == 0
  281. && sscanf (sc->name + 3, "%4x", &uni) == 1)
  282. return ScriptFromUnicode (uni, sf);
  283. if (sf == NULL)
  284. return DEFAULT_SCRIPT;
  285. if (sf->cidmaster)
  286. sf = sf->cidmaster;
  287. else if (sf->mm != NULL)
  288. sf = sf->mm->normal;
  289. for (i = 0; i < 2; ++i)
  290. {
  291. for (pst = sc->possub; pst != NULL; pst = pst->next)
  292. {
  293. if (pst->type == pst_lcaret)
  294. continue;
  295. for (features = pst->subtable->lookup->features; features != NULL;
  296. features = features->next)
  297. {
  298. if (features->scripts != NULL)
  299. return features->scripts->script;
  300. }
  301. }
  302. }
  303. return ScriptFromUnicode (sc->unicodeenc, sf);
  304. }
  305. int
  306. SCRightToLeft (SplineChar *sc)
  307. {
  308. if (sc->unicodeenc >= 0x10800 && sc->unicodeenc <= 0x10fff)
  309. return true; /* Supplemental Multilingual Plane, RTL scripts */
  310. if (sc->unicodeenc != -1 && sc->unicodeenc < 0x10000)
  311. return isrighttoleft (sc->unicodeenc);
  312. return ScriptIsRightToLeft (SCScriptFromUnicode (sc));
  313. }
  314. static void
  315. GlyphMapFree (SplineChar ***map)
  316. {
  317. int i;
  318. if (map == NULL)
  319. return;
  320. for (i = 0; map[i] != NULL; ++i)
  321. free (map[i]);
  322. free (map);
  323. }
  324. static SplineChar **
  325. FindSubs (SplineChar *sc, struct lookup_subtable *sub)
  326. {
  327. SplineChar *spc[30], **space = spc;
  328. int max = sizeof (spc) / sizeof (spc[0]);
  329. int cnt = 0;
  330. char *pt, *start;
  331. SplineChar *subssc, **ret;
  332. PST *pst;
  333. for (pst = sc->possub; pst != NULL; pst = pst->next)
  334. {
  335. if (pst->subtable == sub)
  336. {
  337. pt = pst->u.subs.variant;
  338. while (1)
  339. {
  340. while (*pt == ' ')
  341. ++pt;
  342. start = pt;
  343. pt = strchr (start, ' ');
  344. if (pt != NULL)
  345. *pt = '\0';
  346. subssc = SFGetChar (sc->parent, -1, start);
  347. if (subssc != NULL && subssc->ttf_glyph != -1)
  348. {
  349. if (cnt >= max)
  350. {
  351. if (spc == space)
  352. {
  353. space = xmalloc ((max += 30) * sizeof (SplineChar *));
  354. memcpy (space, spc,
  355. (max - 30) * sizeof (SplineChar *));
  356. }
  357. else
  358. space =
  359. xrealloc (space, (max += 30) * sizeof (SplineChar *));
  360. }
  361. space[cnt++] = subssc;
  362. }
  363. if (pt == NULL)
  364. break;
  365. *pt = ' ';
  366. }
  367. }
  368. }
  369. if (cnt == 0) /* Might happen if the substitution names weren't in the font */
  370. return NULL;
  371. ret = xmalloc ((cnt + 1) * sizeof (SplineChar *));
  372. memcpy (ret, space, cnt * sizeof (SplineChar *));
  373. ret[cnt] = NULL;
  374. if (space != spc)
  375. free (space);
  376. return ret;
  377. }
  378. static SplineChar ***
  379. generateMapList (SplineChar **glyphs, struct lookup_subtable *sub)
  380. {
  381. int cnt;
  382. SplineChar *sc;
  383. int i;
  384. SplineChar ***maps = NULL;
  385. for (cnt = 0; glyphs[cnt] != NULL; ++cnt);
  386. maps = xmalloc ((cnt + 1) * sizeof (SplineChar **));
  387. for (i = 0; i < cnt; ++i)
  388. {
  389. sc = glyphs[i];
  390. maps[i] = FindSubs (sc, sub);
  391. }
  392. maps[cnt] = NULL;
  393. return maps;
  394. }
  395. void
  396. AnchorClassDecompose (SplineFont *sf, AnchorClass * _ac, int classcnt,
  397. int *subcnts, SplineChar ***marks, SplineChar ***base,
  398. SplineChar ***lig, SplineChar ***mkmk,
  399. struct glyphinfo *gi)
  400. {
  401. /* Run through the font finding all characters with this anchor class */
  402. /* (and the cnt-1 classes after it) */
  403. /* and distributing in the four possible anchor types */
  404. int i, j, k, gid, gmax;
  405. struct sclist
  406. {
  407. int cnt;
  408. SplineChar **glyphs;
  409. } heads[at_max];
  410. AnchorPoint *test;
  411. AnchorClass *ac;
  412. memset (heads, 0, sizeof (heads));
  413. memset (subcnts, 0, classcnt * sizeof (int));
  414. memset (marks, 0, classcnt * sizeof (SplineChar **));
  415. gmax = gi == NULL ? sf->glyphcnt : gi->gcnt;
  416. for (j = 0; j < 2; ++j)
  417. {
  418. for (i = 0; i < gmax; ++i)
  419. if ((gid = gi == NULL ? i : gi->bygid[i]) != -1
  420. && sf->glyphs[gid] != NULL)
  421. {
  422. for (ac = _ac, k = 0; k < classcnt; ac = ac->next)
  423. if (ac->matches)
  424. {
  425. for (test = sf->glyphs[gid]->anchor; test != NULL;
  426. test = test->next)
  427. {
  428. if (test->anchor == ac)
  429. {
  430. if (test->type == at_mark)
  431. {
  432. if (j)
  433. marks[k][subcnts[k]] = sf->glyphs[gid];
  434. ++subcnts[k];
  435. if (AnchorClass_lookup_type (ac) != gpos_mark2mark)
  436. break;
  437. }
  438. else if (test->type != at_centry
  439. && test->type != at_cexit)
  440. {
  441. if (heads[test->type].glyphs != NULL)
  442. {
  443. /* If we have multiple mark classes, we may use the same base glyph */
  444. /* with more than one mark class. But it should only appear once in */
  445. /* the output */
  446. if (heads[test->type].cnt == 0 ||
  447. heads[test->type].
  448. glyphs[heads[test->type].cnt - 1] !=
  449. sf->glyphs[gid])
  450. {
  451. heads[test->type].
  452. glyphs[heads[test->type].cnt] =
  453. sf->glyphs[gid];
  454. ++heads[test->type].cnt;
  455. }
  456. }
  457. else
  458. ++heads[test->type].cnt;
  459. if (AnchorClass_lookup_type (ac) != gpos_mark2mark)
  460. break;
  461. }
  462. }
  463. }
  464. ++k;
  465. }
  466. }
  467. if (j == 1)
  468. break;
  469. for (i = 0; i < 4; ++i)
  470. if (heads[i].cnt != 0)
  471. {
  472. heads[i].glyphs =
  473. xmalloc ((heads[i].cnt + 1) * sizeof (SplineChar *));
  474. /* I used to set glyphs[cnt] to NULL here. But it turns out */
  475. /* cnt may be an overestimate on the first pass. So we can */
  476. /* only set it at the end of the second pass */
  477. heads[i].cnt = 0;
  478. }
  479. for (k = 0; k < classcnt; ++k)
  480. if (subcnts[k] != 0)
  481. {
  482. marks[k] = xmalloc ((subcnts[k] + 1) * sizeof (SplineChar *));
  483. marks[k][subcnts[k]] = NULL;
  484. subcnts[k] = 0;
  485. }
  486. }
  487. for (i = 0; i < 4; ++i)
  488. if (heads[i].glyphs != NULL)
  489. heads[i].glyphs[heads[i].cnt] = NULL;
  490. *base = heads[at_basechar].glyphs;
  491. *lig = heads[at_baselig].glyphs;
  492. *mkmk = heads[at_basemark].glyphs;
  493. }
  494. SplineChar **
  495. EntryExitDecompose (SplineFont *sf, AnchorClass * ac, struct glyphinfo *gi)
  496. {
  497. /* Run through the font finding all characters with this anchor class */
  498. int i, j, cnt, gmax, gid;
  499. SplineChar **array;
  500. AnchorPoint *test;
  501. array = NULL;
  502. gmax = gi == NULL ? sf->glyphcnt : gi->gcnt;
  503. for (j = 0; j < 2; ++j)
  504. {
  505. cnt = 0;
  506. for (i = 0; i < gmax; ++i)
  507. if ((gid = gi == NULL ? i : gi->bygid[i]) != -1
  508. && sf->glyphs[gid] != NULL)
  509. {
  510. for (test = sf->glyphs[gid]->anchor;
  511. test != NULL && test->anchor != ac; test = test->next);
  512. if (test != NULL
  513. && (test->type == at_centry || test->type == at_cexit))
  514. {
  515. if (array != NULL)
  516. array[cnt] = sf->glyphs[gid];
  517. ++cnt;
  518. }
  519. }
  520. if (cnt == 0)
  521. return NULL;
  522. if (j == 1)
  523. break;
  524. array = xmalloc ((cnt + 1) * sizeof (SplineChar *));
  525. array[cnt] = NULL;
  526. }
  527. return array;
  528. }
  529. static void
  530. AnchorGuessContext (SplineFont *sf, struct alltabs *at)
  531. {
  532. int i;
  533. int maxbase = 0, maxmark = 0, basec, markc;
  534. AnchorPoint *ap;
  535. int hascursive = 0;
  536. /* the order in which we examine the glyphs does not matter here, so */
  537. /* we needn't add the complexity running though in gid order */
  538. for (i = 0; i < sf->glyphcnt; ++i)
  539. if (sf->glyphs[i])
  540. {
  541. basec = markc = 0;
  542. for (ap = sf->glyphs[i]->anchor; ap != NULL; ap = ap->next)
  543. if (ap->type == at_basemark)
  544. ++markc;
  545. else if (ap->type == at_basechar || ap->type == at_baselig)
  546. ++basec;
  547. else if (ap->type == at_centry)
  548. hascursive = true;
  549. if (basec > maxbase)
  550. maxbase = basec;
  551. if (markc > maxmark)
  552. maxmark = markc;
  553. }
  554. if (maxbase * (maxmark + 1) > at->os2.maxContext)
  555. at->os2.maxContext = maxbase * (maxmark + 1);
  556. if (hascursive && at->os2.maxContext < 2)
  557. at->os2.maxContext = 2;
  558. }
  559. static void
  560. dumpcoveragetable (FILE *gpos, SplineChar **glyphs)
  561. {
  562. int i, last = -2, range_cnt = 0, start, r;
  563. /* the glyph list should already be sorted */
  564. /* figure out whether it is better (smaller) to use an array of glyph ids */
  565. /* or a set of glyph id ranges */
  566. for (i = 0; glyphs[i] != NULL; ++i)
  567. {
  568. if (glyphs[i]->ttf_glyph <= last)
  569. IError ("Glyphs must be ordered when creating coverage table");
  570. if (glyphs[i]->ttf_glyph != last + 1)
  571. ++range_cnt;
  572. last = glyphs[i]->ttf_glyph;
  573. }
  574. /* I think Windows will only accept format 2 coverage tables? */
  575. if (!(coverageformatsallowed & 2)
  576. || ((coverageformatsallowed & 1) && i <= 3 * range_cnt))
  577. {
  578. /* We use less space with a list of glyphs than with a set of ranges */
  579. putshort (gpos, 1); /* Coverage format=1 => glyph list */
  580. putshort (gpos, i); /* count of glyphs */
  581. for (i = 0; glyphs[i] != NULL; ++i)
  582. putshort (gpos, glyphs[i]->ttf_glyph); /* array of glyph IDs */
  583. }
  584. else
  585. {
  586. putshort (gpos, 2); /* Coverage format=2 => range list */
  587. putshort (gpos, range_cnt); /* count of ranges */
  588. last = -2;
  589. start = -2; /* start is a index in our glyph array, last is ttf_glyph */
  590. r = 0;
  591. for (i = 0; glyphs[i] != NULL; ++i)
  592. {
  593. if (glyphs[i]->ttf_glyph != last + 1)
  594. {
  595. if (last != -2)
  596. {
  597. putshort (gpos, glyphs[start]->ttf_glyph); /* start glyph ID */
  598. putshort (gpos, last); /* end glyph ID */
  599. putshort (gpos, start); /* coverage index of start glyph */
  600. ++r;
  601. }
  602. start = i;
  603. }
  604. last = glyphs[i]->ttf_glyph;
  605. }
  606. if (last != -2)
  607. {
  608. putshort (gpos, glyphs[start]->ttf_glyph); /* start glyph ID */
  609. putshort (gpos, last); /* end glyph ID */
  610. putshort (gpos, start); /* coverage index of start glyph */
  611. ++r;
  612. }
  613. if (r != range_cnt)
  614. IError ("Miscounted ranges in format 2 coverage table output");
  615. }
  616. }
  617. static int
  618. sc_ttf_order (const void *_sc1, const void *_sc2)
  619. {
  620. const SplineChar *sc1 = *(const SplineChar **) _sc1, *sc2 =
  621. *(const SplineChar **) _sc2;
  622. return sc1->ttf_glyph - sc2->ttf_glyph;
  623. }
  624. static SplineChar **
  625. SFOrderedGlyphsWithPSTinSubtable (SplineFont *sf, struct lookup_subtable *sub)
  626. {
  627. SplineChar **glyphs = SFGlyphsWithPSTinSubtable (sf, sub);
  628. int cnt, i, k;
  629. if (glyphs == NULL)
  630. return NULL;
  631. for (cnt = 0; glyphs[cnt] != NULL; ++cnt);
  632. qsort (glyphs, cnt, sizeof (SplineChar *), sc_ttf_order);
  633. if (glyphs[0]->ttf_glyph == -1)
  634. {
  635. /* Not sure if this can happen, but it's easy to fix */
  636. for (k = 0; k < cnt && glyphs[k]->ttf_glyph == -1; ++k);
  637. for (i = 0; i <= cnt - k; ++i)
  638. glyphs[i] = glyphs[i + k];
  639. }
  640. return glyphs;
  641. }
  642. SplineChar **
  643. SFGlyphsFromNames (SplineFont *sf, char *names)
  644. {
  645. int cnt, ch;
  646. char *pt, *end;
  647. SplineChar *sc, **glyphs;
  648. if (names == NULL)
  649. return xcalloc (1, sizeof (SplineChar *));
  650. cnt = 0;
  651. for (pt = names; *pt; pt = end + 1)
  652. {
  653. ++cnt;
  654. end = strchr (pt, ' ');
  655. if (end == NULL)
  656. break;
  657. }
  658. glyphs = xmalloc ((cnt + 1) * sizeof (SplineChar *));
  659. cnt = 0;
  660. for (pt = names; *pt; pt = end + 1)
  661. {
  662. end = strchr (pt, ' ');
  663. if (end == NULL)
  664. end = pt + strlen (pt);
  665. ch = *end;
  666. *end = '\0';
  667. sc = SFGetChar (sf, -1, pt);
  668. if (sc != NULL && sc->ttf_glyph != -1)
  669. glyphs[cnt++] = sc;
  670. *end = ch;
  671. if (ch == '\0')
  672. break;
  673. }
  674. glyphs[cnt] = NULL;
  675. return glyphs;
  676. }
  677. static SplineChar **
  678. OrderedGlyphsFromNames (SplineFont *sf, char *names)
  679. {
  680. SplineChar **glyphs = SFGlyphsFromNames (sf, names);
  681. int i, j;
  682. if (glyphs == NULL || glyphs[0] == NULL)
  683. return glyphs;
  684. for (i = 0; glyphs[i + 1] != NULL; ++i)
  685. for (j = i + 1; glyphs[j] != NULL; ++j)
  686. {
  687. if (glyphs[i]->ttf_glyph > glyphs[j]->ttf_glyph)
  688. {
  689. SplineChar *sc = glyphs[i];
  690. glyphs[i] = glyphs[j];
  691. glyphs[j] = sc;
  692. }
  693. }
  694. if (glyphs[0] != NULL)
  695. { /* Glyphs should not appear twice in the name list, just just in case they do... */
  696. for (i = 0; glyphs[i + 1] != NULL; ++i)
  697. {
  698. if (glyphs[i] == glyphs[i + 1])
  699. {
  700. for (j = i + 1; glyphs[j] != NULL; ++j)
  701. glyphs[j] = glyphs[j + 1];
  702. }
  703. }
  704. }
  705. return glyphs;
  706. }
  707. static void
  708. gposvrmaskeddump (FILE *gpos, int vf1, int mask, int offset)
  709. {
  710. if (vf1 & 1)
  711. putshort (gpos, mask & 1 ? offset : 0);
  712. if (vf1 & 2)
  713. putshort (gpos, mask & 2 ? offset : 0);
  714. if (vf1 & 4)
  715. putshort (gpos, mask & 4 ? offset : 0);
  716. if (vf1 & 8)
  717. putshort (gpos, mask & 8 ? offset : 0);
  718. }
  719. static int
  720. devtaboffsetsize (DeviceTable *dt)
  721. {
  722. int type = 1, i;
  723. for (i = dt->last_pixel_size - dt->first_pixel_size; i >= 0; --i)
  724. {
  725. if (dt->corrections[i] >= 8 || dt->corrections[i] < -8)
  726. return 3;
  727. else if (dt->corrections[i] >= 2 || dt->corrections[i] < -2)
  728. type = 2;
  729. }
  730. return type;
  731. }
  732. static void
  733. dumpgposdevicetable (FILE *gpos, DeviceTable *dt)
  734. {
  735. int type;
  736. int i, cnt, b;
  737. if (dt == NULL || dt->corrections == NULL)
  738. return;
  739. type = devtaboffsetsize (dt);
  740. putshort (gpos, dt->first_pixel_size);
  741. putshort (gpos, dt->last_pixel_size);
  742. putshort (gpos, type);
  743. cnt = dt->last_pixel_size - dt->first_pixel_size + 1;
  744. if (type == 3)
  745. {
  746. for (i = 0; i < cnt; ++i)
  747. putc (dt->corrections[i], gpos);
  748. if (cnt & 1)
  749. putc (0, gpos);
  750. }
  751. else if (type == 2)
  752. {
  753. for (i = 0; i < cnt; i += 4)
  754. {
  755. int val = 0;
  756. for (b = 0; b < 4 && i + b < cnt; ++b)
  757. val |= (dt->corrections[i + b] & 0x000f) << (12 - b * 4);
  758. putshort (gpos, val);
  759. }
  760. }
  761. else
  762. {
  763. for (i = 0; i < cnt; i += 8)
  764. {
  765. int val = 0;
  766. for (b = 0; b < 8 && i + b < cnt; ++b)
  767. val |= (dt->corrections[i + b] & 0x0003) << (14 - b * 2);
  768. putshort (gpos, val);
  769. }
  770. }
  771. }
  772. static int
  773. DevTabLen (DeviceTable *dt)
  774. {
  775. int type;
  776. int cnt;
  777. if (dt == NULL || dt->corrections == NULL)
  778. return 0;
  779. cnt = dt->last_pixel_size - dt->first_pixel_size + 1;
  780. type = devtaboffsetsize (dt);
  781. if (type == 3)
  782. cnt = (cnt + 1) / 2;
  783. else if (type == 2)
  784. cnt = (cnt + 3) / 4;
  785. else
  786. cnt = (cnt + 7) / 8;
  787. cnt += 3; /* first, last, type */
  788. return sizeof (uint16_t) * cnt;
  789. }
  790. static int
  791. ValDevTabLen (ValDevTab * vdt)
  792. {
  793. if (vdt == NULL)
  794. return 0;
  795. return (DevTabLen (&vdt->xadjust) + DevTabLen (&vdt->yadjust) +
  796. DevTabLen (&vdt->xadv) + DevTabLen (&vdt->yadv));
  797. }
  798. static int
  799. gposdumpvaldevtab (FILE *gpos, ValDevTab * vdt, int bits, int next_dev_tab)
  800. {
  801. if (bits & 0x10)
  802. {
  803. if (vdt == NULL || vdt->xadjust.corrections == NULL)
  804. putshort (gpos, 0);
  805. else
  806. {
  807. putshort (gpos, next_dev_tab);
  808. next_dev_tab += DevTabLen (&vdt->xadjust);
  809. }
  810. }
  811. if (bits & 0x20)
  812. {
  813. if (vdt == NULL || vdt->yadjust.corrections == NULL)
  814. putshort (gpos, 0);
  815. else
  816. {
  817. putshort (gpos, next_dev_tab);
  818. next_dev_tab += DevTabLen (&vdt->yadjust);
  819. }
  820. }
  821. if (bits & 0x40)
  822. {
  823. if (vdt == NULL || vdt->xadv.corrections == NULL)
  824. putshort (gpos, 0);
  825. else
  826. {
  827. putshort (gpos, next_dev_tab);
  828. next_dev_tab += DevTabLen (&vdt->xadv);
  829. }
  830. }
  831. if (bits & 0x80)
  832. {
  833. if (vdt == NULL || vdt->yadv.corrections == NULL)
  834. putshort (gpos, 0);
  835. else
  836. {
  837. putshort (gpos, next_dev_tab);
  838. next_dev_tab += DevTabLen (&vdt->yadv);
  839. }
  840. }
  841. return next_dev_tab;
  842. }
  843. static int
  844. gposmaskeddumpdevtab (FILE *gpos, DeviceTable *dt, int bits, int mask,
  845. int next_dev_tab)
  846. {
  847. if (bits & 0x10)
  848. {
  849. if (!(mask & 0x10) || dt == NULL)
  850. putshort (gpos, 0);
  851. else
  852. {
  853. putshort (gpos, next_dev_tab);
  854. next_dev_tab += DevTabLen (dt);
  855. }
  856. }
  857. if (bits & 0x20)
  858. {
  859. if (!(mask & 0x20) || dt == NULL)
  860. putshort (gpos, 0);
  861. else
  862. {
  863. putshort (gpos, next_dev_tab);
  864. next_dev_tab += DevTabLen (dt);
  865. }
  866. }
  867. if (bits & 0x40)
  868. {
  869. if (!(mask & 0x40) || dt == NULL)
  870. putshort (gpos, 0);
  871. else
  872. {
  873. putshort (gpos, next_dev_tab);
  874. next_dev_tab += DevTabLen (dt);
  875. }
  876. }
  877. if (bits & 0x80)
  878. {
  879. if (!(mask & 0x80) || dt == NULL)
  880. putshort (gpos, 0);
  881. else
  882. {
  883. putshort (gpos, next_dev_tab);
  884. next_dev_tab += DevTabLen (dt);
  885. }
  886. }
  887. return next_dev_tab;
  888. }
  889. static int
  890. DevTabsSame (DeviceTable *dt1, DeviceTable *dt2)
  891. {
  892. DeviceTable _dt;
  893. int i;
  894. if (dt1 == NULL && dt2 == NULL)
  895. return true;
  896. if (dt1 == NULL)
  897. {
  898. memset (&_dt, 0, sizeof (_dt));
  899. dt1 = &_dt;
  900. }
  901. if (dt2 == NULL)
  902. {
  903. memset (&_dt, 0, sizeof (_dt));
  904. dt2 = &_dt;
  905. }
  906. if (dt1->corrections == NULL && dt2->corrections == NULL)
  907. return true;
  908. if (dt1->corrections == NULL || dt2->corrections == NULL)
  909. return false;
  910. if (dt1->first_pixel_size != dt2->first_pixel_size ||
  911. dt1->last_pixel_size != dt2->last_pixel_size)
  912. return false;
  913. for (i = dt2->last_pixel_size - dt1->first_pixel_size; i >= 0; --i)
  914. if (dt1->corrections[i] != dt2->corrections[i])
  915. return false;
  916. return true;
  917. }
  918. static int
  919. ValDevTabsSame (ValDevTab * vdt1, ValDevTab * vdt2)
  920. {
  921. ValDevTab _vdt;
  922. if (vdt1 == NULL && vdt2 == NULL)
  923. return true;
  924. if (vdt1 == NULL)
  925. {
  926. memset (&_vdt, 0, sizeof (_vdt));
  927. vdt1 = &_vdt;
  928. }
  929. if (vdt2 == NULL)
  930. {
  931. memset (&_vdt, 0, sizeof (_vdt));
  932. vdt2 = &_vdt;
  933. }
  934. return (DevTabsSame (&vdt1->xadjust, &vdt2->xadjust) &&
  935. DevTabsSame (&vdt1->yadjust, &vdt2->yadjust) &&
  936. DevTabsSame (&vdt1->xadv, &vdt2->xadv) &&
  937. DevTabsSame (&vdt1->yadv, &vdt2->yadv));
  938. }
  939. static void
  940. dumpGPOSsimplepos (FILE *gpos, SplineFont *sf, struct lookup_subtable *sub)
  941. {
  942. int cnt, cnt2;
  943. int32_t coverage_pos, end;
  944. PST *pst, *first = NULL;
  945. int bits = 0, same = true;
  946. SplineChar **glyphs;
  947. glyphs = SFOrderedGlyphsWithPSTinSubtable (sf, sub);
  948. for (cnt = cnt2 = 0; glyphs[cnt] != NULL; ++cnt)
  949. {
  950. for (pst = glyphs[cnt]->possub; pst != NULL; pst = pst->next)
  951. {
  952. if (pst->subtable == sub && pst->type == pst_position)
  953. {
  954. if (first == NULL)
  955. first = pst;
  956. else if (same)
  957. {
  958. if (first->u.pos.xoff != pst->u.pos.xoff ||
  959. first->u.pos.yoff != pst->u.pos.yoff ||
  960. first->u.pos.h_adv_off != pst->u.pos.h_adv_off ||
  961. first->u.pos.v_adv_off != pst->u.pos.v_adv_off)
  962. same = false;
  963. if (!ValDevTabsSame (pst->u.pos.adjust, first->u.pos.adjust))
  964. same = false;
  965. }
  966. if (pst->u.pos.xoff != 0)
  967. bits |= 1;
  968. if (pst->u.pos.yoff != 0)
  969. bits |= 2;
  970. if (pst->u.pos.h_adv_off != 0)
  971. bits |= 4;
  972. if (pst->u.pos.v_adv_off != 0)
  973. bits |= 8;
  974. if (pst->u.pos.adjust != NULL)
  975. {
  976. if (pst->u.pos.adjust->xadjust.corrections != NULL)
  977. bits |= 0x10;
  978. if (pst->u.pos.adjust->yadjust.corrections != NULL)
  979. bits |= 0x20;
  980. if (pst->u.pos.adjust->xadv.corrections != NULL)
  981. bits |= 0x40;
  982. if (pst->u.pos.adjust->yadv.corrections != NULL)
  983. bits |= 0x80;
  984. }
  985. ++cnt2;
  986. break;
  987. }
  988. }
  989. }
  990. if (bits == 0)
  991. bits = 1;
  992. if (cnt != cnt2)
  993. IError ("Count mismatch in dumpGPOSsimplepos#1 %d vs %d\n", cnt, cnt2);
  994. putshort (gpos, same ? 1 : 2); /* 1 means all value records same */
  995. coverage_pos = ftell (gpos);
  996. putshort (gpos, 0); /* offset to coverage table */
  997. putshort (gpos, bits);
  998. if (same)
  999. {
  1000. if (bits & 1)
  1001. putshort (gpos, first->u.pos.xoff);
  1002. if (bits & 2)
  1003. putshort (gpos, first->u.pos.yoff);
  1004. if (bits & 4)
  1005. putshort (gpos, first->u.pos.h_adv_off);
  1006. if (bits & 8)
  1007. putshort (gpos, first->u.pos.v_adv_off);
  1008. if (bits & 0xf0)
  1009. {
  1010. int next_dev_tab = ftell (gpos) - coverage_pos + 2 +
  1011. sizeof (int16_t) * ((bits & 0x10 ? 1 : 0) + (bits & 0x20 ? 1 : 0) +
  1012. (bits & 0x40 ? 1 : 0) + (bits & 0x80 ? 1 : 0));
  1013. if (bits & 0x10)
  1014. {
  1015. putshort (gpos, next_dev_tab);
  1016. next_dev_tab += DevTabLen (&first->u.pos.adjust->xadjust);
  1017. }
  1018. if (bits & 0x20)
  1019. {
  1020. putshort (gpos, next_dev_tab);
  1021. next_dev_tab += DevTabLen (&first->u.pos.adjust->yadjust);
  1022. }
  1023. if (bits & 0x40)
  1024. {
  1025. putshort (gpos, next_dev_tab);
  1026. next_dev_tab += DevTabLen (&first->u.pos.adjust->xadv);
  1027. }
  1028. if (bits & 0x80)
  1029. {
  1030. putshort (gpos, next_dev_tab);
  1031. next_dev_tab += DevTabLen (&first->u.pos.adjust->yadv);
  1032. }
  1033. if (bits & 0x10)
  1034. dumpgposdevicetable (gpos, &first->u.pos.adjust->xadjust);
  1035. if (bits & 0x20)
  1036. dumpgposdevicetable (gpos, &first->u.pos.adjust->yadjust);
  1037. if (bits & 0x40)
  1038. dumpgposdevicetable (gpos, &first->u.pos.adjust->xadv);
  1039. if (bits & 0x80)
  1040. dumpgposdevicetable (gpos, &first->u.pos.adjust->yadv);
  1041. if (next_dev_tab != ftell (gpos) - coverage_pos + 2)
  1042. IError ("Device Table offsets wrong in simple positioning 2");
  1043. }
  1044. }
  1045. else
  1046. {
  1047. int vr_size =
  1048. sizeof (int16_t) * ((bits & 0x1 ? 1 : 0) + (bits & 0x2 ? 1 : 0) +
  1049. (bits & 0x4 ? 1 : 0) + (bits & 0x8 ? 1 : 0) +
  1050. (bits & 0x10 ? 1 : 0) + (bits & 0x20 ? 1 : 0) +
  1051. (bits & 0x40 ? 1 : 0) + (bits & 0x80 ? 1 : 0));
  1052. int next_dev_tab = ftell (gpos) - coverage_pos + 2 + 2 + vr_size * cnt;
  1053. putshort (gpos, cnt);
  1054. for (cnt2 = 0; glyphs[cnt2] != NULL; ++cnt2)
  1055. {
  1056. for (pst = glyphs[cnt2]->possub; pst != NULL; pst = pst->next)
  1057. {
  1058. if (pst->subtable == sub && pst->type == pst_position)
  1059. {
  1060. if (bits & 1)
  1061. putshort (gpos, pst->u.pos.xoff);
  1062. if (bits & 2)
  1063. putshort (gpos, pst->u.pos.yoff);
  1064. if (bits & 4)
  1065. putshort (gpos, pst->u.pos.h_adv_off);
  1066. if (bits & 8)
  1067. putshort (gpos, pst->u.pos.v_adv_off);
  1068. next_dev_tab =
  1069. gposdumpvaldevtab (gpos, pst->u.pos.adjust, bits,
  1070. next_dev_tab);
  1071. break;
  1072. }
  1073. }
  1074. }
  1075. if (cnt != cnt2)
  1076. IError ("Count mismatch in dumpGPOSsimplepos#3 %d vs %d\n", cnt, cnt2);
  1077. if (bits & 0xf0)
  1078. {
  1079. for (cnt2 = 0; glyphs[cnt2] != NULL; ++cnt2)
  1080. {
  1081. for (pst = glyphs[cnt2]->possub; pst != NULL; pst = pst->next)
  1082. {
  1083. if (pst->subtable == sub && pst->type == pst_position)
  1084. {
  1085. if (bits & 0x10)
  1086. dumpgposdevicetable (gpos,
  1087. &first->u.pos.adjust->xadjust);
  1088. if (bits & 0x20)
  1089. dumpgposdevicetable (gpos,
  1090. &first->u.pos.adjust->yadjust);
  1091. if (bits & 0x40)
  1092. dumpgposdevicetable (gpos, &first->u.pos.adjust->xadv);
  1093. if (bits & 0x80)
  1094. dumpgposdevicetable (gpos, &first->u.pos.adjust->yadv);
  1095. }
  1096. }
  1097. }
  1098. }
  1099. if (next_dev_tab != ftell (gpos) - coverage_pos + 2)
  1100. IError ("Device Table offsets wrong in simple positioning 2");
  1101. }
  1102. end = ftell (gpos);
  1103. fseek (gpos, coverage_pos, SEEK_SET);
  1104. putshort (gpos, end - coverage_pos + 2);
  1105. fseek (gpos, end, SEEK_SET);
  1106. dumpcoveragetable (gpos, glyphs);
  1107. fseek (gpos, 0, SEEK_END);
  1108. free (glyphs);
  1109. }
  1110. struct sckppst
  1111. {
  1112. uint16_t samewas;
  1113. uint16_t devtablen;
  1114. uint16_t tot;
  1115. uint8_t isv;
  1116. uint8_t subtable_too_big;
  1117. /* The first few fields are only meaningful in the first structure in the array*/
  1118. /* and provide information about the entire rest of the array */
  1119. uint16_t other_gid;
  1120. SplineChar *sc;
  1121. KernPair *kp;
  1122. PST *pst;
  1123. };
  1124. static int
  1125. cmp_gid (const void *_s1, const void *_s2)
  1126. {
  1127. const struct sckppst *s1 = _s1, *s2 = _s2;
  1128. return ((int) s1->other_gid) - ((int) s2->other_gid);
  1129. }
  1130. static void
  1131. dumpGPOSpairpos (FILE *gpos, SplineFont *sf, struct lookup_subtable *sub)
  1132. {
  1133. int cnt;
  1134. int32_t coverage_pos, offset_pos, end, start, pos;
  1135. PST *pst;
  1136. KernPair *kp;
  1137. int vf1 = 0, vf2 = 0, i, j, k, tot, bit_cnt, v;
  1138. int start_cnt, end_cnt;
  1139. int chunk_cnt, chunk_max;
  1140. SplineChar *sc, **glyphs, *gtemp;
  1141. struct sckppst **seconds;
  1142. int devtablen;
  1143. int next_dev_tab;
  1144. /* Figure out all the data we need. First the glyphs with kerning info */
  1145. /* then the glyphs to which they kern, and by how much */
  1146. glyphs = SFOrderedGlyphsWithPSTinSubtable (sf, sub);
  1147. for (cnt = 0; glyphs[cnt] != NULL; ++cnt);
  1148. seconds = xmalloc (cnt * sizeof (struct sckppst *));
  1149. for (cnt = 0; glyphs[cnt] != NULL; ++cnt)
  1150. {
  1151. for (k = 0; k < 2; ++k)
  1152. {
  1153. devtablen = 0;
  1154. tot = 0;
  1155. for (pst = glyphs[cnt]->possub; pst != NULL; pst = pst->next)
  1156. {
  1157. if (pst->subtable == sub && pst->type == pst_pair &&
  1158. (sc = SFGetChar (sf, -1, pst->u.pair.paired)) != NULL &&
  1159. sc->ttf_glyph != -1)
  1160. {
  1161. if (k)
  1162. {
  1163. seconds[cnt][tot].sc = sc;
  1164. seconds[cnt][tot].other_gid = sc->ttf_glyph;
  1165. seconds[cnt][tot].pst = pst;
  1166. devtablen += ValDevTabLen (pst->u.pair.vr[0].adjust) +
  1167. ValDevTabLen (pst->u.pair.vr[1].adjust);
  1168. }
  1169. ++tot;
  1170. }
  1171. }
  1172. for (v = 0; v < 2; ++v)
  1173. {
  1174. for (kp = v ? glyphs[cnt]->vkerns : glyphs[cnt]->kerns;
  1175. kp != NULL; kp = kp->next)
  1176. {
  1177. if (kp->sc->ttf_glyph != -1)
  1178. {
  1179. if (k)
  1180. {
  1181. seconds[cnt][tot].other_gid = kp->sc->ttf_glyph;
  1182. seconds[cnt][tot].sc = kp->sc;
  1183. seconds[cnt][tot].kp = kp;
  1184. seconds[cnt][tot].isv = v;
  1185. devtablen += DevTabLen (kp->adjust);
  1186. }
  1187. ++tot;
  1188. }
  1189. }
  1190. }
  1191. if (k == 0)
  1192. {
  1193. seconds[cnt] = xcalloc (tot + 1, sizeof (struct sckppst));
  1194. }
  1195. else
  1196. {
  1197. qsort (seconds[cnt], tot, sizeof (struct sckppst), cmp_gid);
  1198. seconds[cnt][0].tot = tot;
  1199. /* Devtablen is 0 unless we are configured for device tables */
  1200. seconds[cnt][0].devtablen = devtablen;
  1201. seconds[cnt][0].samewas = 0xffff;
  1202. }
  1203. }
  1204. }
  1205. /* Some fonts do a primitive form of class based kerning, several glyphs */
  1206. /* can share the same list of second glyphs & offsets */
  1207. for (cnt = 0; glyphs[cnt] != NULL; ++cnt)
  1208. {
  1209. struct sckppst *test = seconds[cnt], *test2;
  1210. for (i = cnt - 1; i >= 0; --i)
  1211. {
  1212. test2 = seconds[i];
  1213. if (test[0].tot != test2[0].tot || test2[0].samewas != 0xffff)
  1214. continue;
  1215. for (j = test[0].tot - 1; j >= 0; --j)
  1216. {
  1217. if (test[j].other_gid != test2[j].other_gid)
  1218. break;
  1219. if (test[j].kp != NULL && test2[j].kp != NULL &&
  1220. test[j].kp->off == test2[j].kp->off
  1221. && DevTabsSame (test[j].kp->adjust, test2[j].kp->adjust))
  1222. /* So far, so good */ ;
  1223. else if (test[j].pst != NULL && test2[j].pst != NULL &&
  1224. test[j].pst->u.pair.vr[0].xoff ==
  1225. test2[j].pst->u.pair.vr[0].xoff
  1226. && test[j].pst->u.pair.vr[0].yoff ==
  1227. test2[j].pst->u.pair.vr[0].yoff
  1228. && test[j].pst->u.pair.vr[0].h_adv_off ==
  1229. test2[j].pst->u.pair.vr[0].h_adv_off
  1230. && test[j].pst->u.pair.vr[0].v_adv_off ==
  1231. test2[j].pst->u.pair.vr[0].v_adv_off
  1232. && test[j].pst->u.pair.vr[1].xoff ==
  1233. test2[j].pst->u.pair.vr[1].xoff
  1234. && test[j].pst->u.pair.vr[1].yoff ==
  1235. test2[j].pst->u.pair.vr[1].yoff
  1236. && test[j].pst->u.pair.vr[1].h_adv_off ==
  1237. test2[j].pst->u.pair.vr[1].h_adv_off
  1238. && test[j].pst->u.pair.vr[1].v_adv_off ==
  1239. test2[j].pst->u.pair.vr[1].v_adv_off
  1240. && ValDevTabsSame (test[j].pst->u.pair.vr[0].adjust,
  1241. test2[j].pst->u.pair.vr[0].adjust)
  1242. && ValDevTabsSame (test[j].pst->u.pair.vr[1].adjust,
  1243. test2[j].pst->u.pair.vr[1].adjust))
  1244. /* That's ok too. */ ;
  1245. else
  1246. break;
  1247. }
  1248. if (j >= 0)
  1249. continue;
  1250. test[0].samewas = i;
  1251. break;
  1252. }
  1253. }
  1254. /* Ok, how many offsets must we output? Normal kerning will just use */
  1255. /* one offset (with perhaps a device table), but the standard allows */
  1256. /* us to adjust 8 different values (with 8 different device tables) */
  1257. /* Find out which we need */
  1258. for (cnt = 0; glyphs[cnt] != NULL; ++cnt)
  1259. {
  1260. for (tot = 0; tot < seconds[cnt][0].tot; ++tot)
  1261. {
  1262. if ((pst = seconds[cnt][tot].pst) != NULL)
  1263. {
  1264. if (pst->subtable == sub && pst->type == pst_pair)
  1265. {
  1266. if (pst->u.pair.vr[0].xoff != 0)
  1267. vf1 |= 1;
  1268. if (pst->u.pair.vr[0].yoff != 0)
  1269. vf1 |= 2;
  1270. if (pst->u.pair.vr[0].h_adv_off != 0)
  1271. vf1 |= 4;
  1272. if (pst->u.pair.vr[0].v_adv_off != 0)
  1273. vf1 |= 8;
  1274. if (pst->u.pair.vr[0].adjust != NULL)
  1275. {
  1276. if (pst->u.pair.vr[0].adjust->xadjust.corrections != NULL)
  1277. vf1 |= 0x10;
  1278. if (pst->u.pair.vr[0].adjust->yadjust.corrections != NULL)
  1279. vf1 |= 0x20;
  1280. if (pst->u.pair.vr[0].adjust->xadv.corrections != NULL)
  1281. vf1 |= 0x40;
  1282. if (pst->u.pair.vr[0].adjust->yadv.corrections != NULL)
  1283. vf1 |= 0x80;
  1284. }
  1285. if (pst->u.pair.vr[1].xoff != 0)
  1286. vf2 |= 1;
  1287. if (pst->u.pair.vr[1].yoff != 0)
  1288. vf2 |= 2;
  1289. if (pst->u.pair.vr[1].h_adv_off != 0)
  1290. vf2 |= 4;
  1291. if (pst->u.pair.vr[1].v_adv_off != 0)
  1292. vf2 |= 8;
  1293. if (pst->u.pair.vr[1].adjust != NULL)
  1294. {
  1295. if (pst->u.pair.vr[1].adjust->xadjust.corrections != NULL)
  1296. vf2 |= 0x10;
  1297. if (pst->u.pair.vr[1].adjust->yadjust.corrections != NULL)
  1298. vf2 |= 0x20;
  1299. if (pst->u.pair.vr[1].adjust->xadv.corrections != NULL)
  1300. vf2 |= 0x40;
  1301. if (pst->u.pair.vr[1].adjust->yadv.corrections != NULL)
  1302. vf2 |= 0x80;
  1303. }
  1304. }
  1305. }
  1306. if ((kp = seconds[cnt][tot].kp) != NULL)
  1307. {
  1308. int mask = 0, mask2 = 0;
  1309. if (seconds[cnt][tot].isv)
  1310. mask = 0x0008;
  1311. else
  1312. mask = 0x0004;
  1313. if (kp->adjust != NULL)
  1314. {
  1315. mask |= mask << 4;
  1316. mask2 |= mask2 << 4;
  1317. }
  1318. vf1 |= mask;
  1319. vf2 |= mask2;
  1320. }
  1321. }
  1322. }
  1323. if (vf1 == 0 && vf2 == 0)
  1324. vf1 = 1;
  1325. bit_cnt = 0;
  1326. for (i = 0; i < 8; ++i)
  1327. {
  1328. if (vf1 & (1 << i))
  1329. ++bit_cnt;
  1330. if (vf2 & (1 << i))
  1331. ++bit_cnt;
  1332. }
  1333. chunk_max = chunk_cnt = 0;
  1334. for (start_cnt = 0; start_cnt < cnt; start_cnt = end_cnt)
  1335. {
  1336. int len = 5 * 2; /* Subtable header */
  1337. for (end_cnt = start_cnt; end_cnt < cnt; ++end_cnt)
  1338. {
  1339. int glyph_len = 2; /* For the glyph's offset */
  1340. if (seconds[end_cnt][0].samewas == 0xffff
  1341. || seconds[end_cnt][0].samewas < start_cnt)
  1342. glyph_len += (bit_cnt * 2 + 2) * seconds[end_cnt][0].tot + seconds[end_cnt][0].devtablen + 2; /* Number of secondary glyphs */
  1343. if (glyph_len > 65535 && end_cnt == start_cnt)
  1344. {
  1345. LogError (_
  1346. ("Lookup subtable %s contains a glyph %s whose kerning information takes up more than 64k bytes\n"),
  1347. sub->subtable_name, glyphs[start_cnt]->name);
  1348. len += glyph_len;
  1349. }
  1350. else if (len + glyph_len > 65535)
  1351. {
  1352. if (start_cnt == 0)
  1353. LogError (_
  1354. ("Lookup subtable %s had to be split into several subtables\nbecause it was too big.\n"),
  1355. sub->subtable_name);
  1356. break;
  1357. }
  1358. else
  1359. len += glyph_len;
  1360. }
  1361. if (start_cnt != 0 || end_cnt != cnt)
  1362. {
  1363. if (chunk_cnt >= chunk_max)
  1364. sub->extra_subtables =
  1365. xrealloc (sub->extra_subtables,
  1366. ((chunk_max += 10) + 1) * sizeof (uint32_t));
  1367. sub->extra_subtables[chunk_cnt++] = ftell (gpos);
  1368. sub->extra_subtables[chunk_cnt] = -1;
  1369. }
  1370. start = ftell (gpos);
  1371. putshort (gpos, 1); /* 1 means char pairs (ie. not classes) */
  1372. coverage_pos = ftell (gpos);
  1373. putshort (gpos, 0); /* offset to coverage table */
  1374. putshort (gpos, vf1);
  1375. putshort (gpos, vf2);
  1376. putshort (gpos, end_cnt - start_cnt);
  1377. offset_pos = ftell (gpos);
  1378. for (i = start_cnt; i < end_cnt; ++i)
  1379. putshort (gpos, 0); /* Fill in later */
  1380. for (i = start_cnt; i < end_cnt; ++i)
  1381. {
  1382. if (seconds[i][0].samewas >= start_cnt
  1383. && seconds[i][0].samewas != 0xffff)
  1384. {
  1385. /* It's the same as the glyph at samewas, so just copy the */
  1386. /* offset from there. We don't need to do anything else */
  1387. int offset;
  1388. fseek (gpos,
  1389. offset_pos + (seconds[i][0].samewas -
  1390. start_cnt) * sizeof (uint16_t), SEEK_SET);
  1391. offset = getushort (gpos);
  1392. fseek (gpos, offset_pos + (i - start_cnt) * sizeof (uint16_t),
  1393. SEEK_SET);
  1394. putshort (gpos, offset);
  1395. fseek (gpos, 0, SEEK_END);
  1396. continue;
  1397. }
  1398. next_dev_tab = ftell (gpos) - start;
  1399. if ((vf1 & 0xf0) || (vf2 & 0xf0))
  1400. {
  1401. for (tot = 0; tot < seconds[i][0].tot; ++tot)
  1402. {
  1403. if ((pst = seconds[i][tot].pst) != NULL)
  1404. {
  1405. if (pst->u.pair.vr[0].adjust != NULL)
  1406. {
  1407. dumpgposdevicetable (gpos,
  1408. &pst->u.pair.vr[0].adjust->
  1409. xadjust);
  1410. dumpgposdevicetable (gpos,
  1411. &pst->u.pair.vr[0].adjust->
  1412. yadjust);
  1413. dumpgposdevicetable (gpos,
  1414. &pst->u.pair.vr[0].adjust->xadv);
  1415. dumpgposdevicetable (gpos,
  1416. &pst->u.pair.vr[0].adjust->yadv);
  1417. }
  1418. if (pst->u.pair.vr[1].adjust != NULL)
  1419. {
  1420. dumpgposdevicetable (gpos,
  1421. &pst->u.pair.vr[1].adjust->
  1422. xadjust);
  1423. dumpgposdevicetable (gpos,
  1424. &pst->u.pair.vr[1].adjust->
  1425. yadjust);
  1426. dumpgposdevicetable (gpos,
  1427. &pst->u.pair.vr[1].adjust->xadv);
  1428. dumpgposdevicetable (gpos,
  1429. &pst->u.pair.vr[1].adjust->yadv);
  1430. }
  1431. }
  1432. if ((kp = seconds[i][tot].kp) != NULL && kp->adjust != NULL)
  1433. dumpgposdevicetable (gpos, kp->adjust);
  1434. }
  1435. }
  1436. pos = ftell (gpos);
  1437. fseek (gpos, offset_pos + (i - start_cnt) * sizeof (uint16_t),
  1438. SEEK_SET);
  1439. putshort (gpos, pos - start);
  1440. fseek (gpos, pos, SEEK_SET);
  1441. putshort (gpos, seconds[i][0].tot);
  1442. for (tot = 0; tot < seconds[i][0].tot; ++tot)
  1443. {
  1444. putshort (gpos, seconds[i][tot].other_gid);
  1445. if ((pst = seconds[i][tot].pst) != NULL)
  1446. {
  1447. if (vf1 & 1)
  1448. putshort (gpos, pst->u.pair.vr[0].xoff);
  1449. if (vf1 & 2)
  1450. putshort (gpos, pst->u.pair.vr[0].yoff);
  1451. if (vf1 & 4)
  1452. putshort (gpos, pst->u.pair.vr[0].h_adv_off);
  1453. if (vf1 & 8)
  1454. putshort (gpos, pst->u.pair.vr[0].v_adv_off);
  1455. next_dev_tab =
  1456. gposdumpvaldevtab (gpos, pst->u.pair.vr[0].adjust, vf1,
  1457. next_dev_tab);
  1458. if (vf2 & 1)
  1459. putshort (gpos, pst->u.pair.vr[1].xoff);
  1460. if (vf2 & 2)
  1461. putshort (gpos, pst->u.pair.vr[1].yoff);
  1462. if (vf2 & 4)
  1463. putshort (gpos, pst->u.pair.vr[1].h_adv_off);
  1464. if (vf2 & 8)
  1465. putshort (gpos, pst->u.pair.vr[1].v_adv_off);
  1466. next_dev_tab =
  1467. gposdumpvaldevtab (gpos, pst->u.pair.vr[1].adjust, vf2,
  1468. next_dev_tab);
  1469. }
  1470. else if ((kp = seconds[i][tot].kp) != NULL)
  1471. {
  1472. int mask = 0, mask2 = 0;
  1473. if (seconds[i][tot].isv)
  1474. mask = 0x8;
  1475. else
  1476. mask = 0x4;
  1477. gposvrmaskeddump (gpos, vf1, mask, kp->off);
  1478. next_dev_tab =
  1479. gposmaskeddumpdevtab (gpos, kp->adjust, vf1, mask << 4,
  1480. next_dev_tab);
  1481. gposvrmaskeddump (gpos, vf2, mask2, kp->off);
  1482. next_dev_tab =
  1483. gposmaskeddumpdevtab (gpos, kp->adjust, vf2, mask2 << 4,
  1484. next_dev_tab);
  1485. }
  1486. }
  1487. }
  1488. end = ftell (gpos);
  1489. fseek (gpos, coverage_pos, SEEK_SET);
  1490. if (end - start > 65535)
  1491. IError (_
  1492. ("I miscalculated the size of subtable %s, this means the kerning output is wrong."),
  1493. sub->subtable_name);
  1494. putshort (gpos, end - start);
  1495. fseek (gpos, end, SEEK_SET);
  1496. gtemp = glyphs[end_cnt];
  1497. glyphs[end_cnt] = NULL;
  1498. dumpcoveragetable (gpos, glyphs + start_cnt);
  1499. glyphs[end_cnt] = gtemp;
  1500. }
  1501. for (i = 0; i < cnt; ++i)
  1502. free (seconds[i]);
  1503. free (seconds);
  1504. free (glyphs);
  1505. }
  1506. uint16_t *
  1507. ClassesFromNames (SplineFont *sf, char **classnames, int class_cnt,
  1508. int numGlyphs, SplineChar ***glyphs, int apple_kc)
  1509. {
  1510. uint16_t *class;
  1511. int i;
  1512. char *pt, *end, ch;
  1513. SplineChar *sc, **gs = NULL;
  1514. int offset = (apple_kc && classnames[0] != NULL);
  1515. class = xcalloc (numGlyphs, sizeof (uint16_t));
  1516. if (glyphs)
  1517. *glyphs = gs = xcalloc (numGlyphs, sizeof (SplineChar *));
  1518. for (i = 0; i < class_cnt; ++i)
  1519. {
  1520. if (i == 0 && classnames[0] == NULL)
  1521. continue;
  1522. for (pt = classnames[i]; *pt; pt = end + 1)
  1523. {
  1524. while (*pt == ' ')
  1525. ++pt;
  1526. if (*pt == '\0')
  1527. break;
  1528. end = strchr (pt, ' ');
  1529. if (end == NULL)
  1530. end = pt + strlen (pt);
  1531. ch = *end;
  1532. *end = '\0';
  1533. sc = SFGetChar (sf, -1, pt);
  1534. if (sc != NULL && sc->ttf_glyph != -1)
  1535. {
  1536. class[sc->ttf_glyph] = i + offset;
  1537. if (gs != NULL)
  1538. gs[sc->ttf_glyph] = sc;
  1539. }
  1540. *end = ch;
  1541. if (ch == '\0')
  1542. break;
  1543. }
  1544. }
  1545. return class;
  1546. }
  1547. static SplineChar **
  1548. GlyphsFromClasses (SplineChar **gs, int numGlyphs)
  1549. {
  1550. int i, cnt;
  1551. SplineChar **glyphs;
  1552. for (i = cnt = 0; i < numGlyphs; ++i)
  1553. if (gs[i] != NULL)
  1554. ++cnt;
  1555. glyphs = xmalloc ((cnt + 1) * sizeof (SplineChar *));
  1556. for (i = cnt = 0; i < numGlyphs; ++i)
  1557. if (gs[i] != NULL)
  1558. glyphs[cnt++] = gs[i];
  1559. glyphs[cnt++] = NULL;
  1560. free (gs);
  1561. return glyphs;
  1562. }
  1563. static SplineChar **
  1564. GlyphsFromInitialClasses (SplineChar **gs, int numGlyphs, uint16_t *classes,
  1565. uint16_t *initial)
  1566. {
  1567. int i, j, cnt;
  1568. SplineChar **glyphs;
  1569. for (i = cnt = 0; i < numGlyphs; ++i)
  1570. {
  1571. for (j = 0; initial[j] != 0xffff; ++j)
  1572. if (initial[j] == classes[i])
  1573. break;
  1574. if (initial[j] != 0xffff && gs[i] != NULL)
  1575. ++cnt;
  1576. }
  1577. glyphs = xmalloc ((cnt + 1) * sizeof (SplineChar *));
  1578. for (i = cnt = 0; i < numGlyphs; ++i)
  1579. {
  1580. for (j = 0; initial[j] != 0xffff; ++j)
  1581. if (initial[j] == classes[i])
  1582. break;
  1583. if (initial[j] != 0xffff && gs[i] != NULL)
  1584. glyphs[cnt++] = gs[i];
  1585. }
  1586. glyphs[cnt++] = NULL;
  1587. return glyphs;
  1588. }
  1589. static void
  1590. DumpClass (FILE *gpos, uint16_t *class, int numGlyphs)
  1591. {
  1592. int ranges, i, cur, first = -1, last = -1, istart;
  1593. for (i = ranges = 0; i < numGlyphs;)
  1594. {
  1595. istart = i;
  1596. cur = class[i];
  1597. while (i < numGlyphs && class[i] == cur)
  1598. ++i;
  1599. if (cur != 0)
  1600. {
  1601. ++ranges;
  1602. if (first == -1)
  1603. first = istart;
  1604. last = i - 1;
  1605. }
  1606. }
  1607. if (ranges * 3 + 1 > last - first + 1 + 2 || first == -1)
  1608. {
  1609. if (first == -1)
  1610. first = last = 0;
  1611. putshort (gpos, 1); /* Format 1, list of all posibilities */
  1612. putshort (gpos, first);
  1613. putshort (gpos, last - first + 1);
  1614. for (i = first; i <= last; ++i)
  1615. putshort (gpos, class[i]);
  1616. }
  1617. else
  1618. {
  1619. putshort (gpos, 2); /* Format 2, series of ranges */
  1620. putshort (gpos, ranges);
  1621. for (i = 0; i < numGlyphs;)
  1622. {
  1623. istart = i;
  1624. cur = class[i];
  1625. while (i < numGlyphs && class[i] == cur)
  1626. ++i;
  1627. if (cur != 0)
  1628. {
  1629. putshort (gpos, istart);
  1630. putshort (gpos, i - 1);
  1631. putshort (gpos, cur);
  1632. }
  1633. }
  1634. }
  1635. }
  1636. static void
  1637. dumpgposkernclass (FILE *gpos, SplineFont *sf,
  1638. struct lookup_subtable *sub, struct alltabs *at)
  1639. {
  1640. uint32_t begin_off = ftell (gpos), pos;
  1641. uint16_t *class1, *class2;
  1642. KernClass *kc = sub->kc, *test;
  1643. SplineChar **glyphs;
  1644. int i, isv;
  1645. int anydevtab = false;
  1646. int next_devtab;
  1647. putshort (gpos, 2); /* format 2 of the pair adjustment subtable */
  1648. putshort (gpos, 0); /* offset to coverage table */
  1649. for (i = 0; i < kc->first_cnt * kc->second_cnt; ++i)
  1650. {
  1651. if (kc->adjusts[i].corrections != NULL)
  1652. {
  1653. anydevtab = true;
  1654. break;
  1655. }
  1656. }
  1657. for (test = sf->vkerns; test != NULL && test != kc; test = test->next);
  1658. isv = test == kc;
  1659. if (isv)
  1660. {
  1661. /* As far as I know there is no "bottom to top" writing direction */
  1662. /* Oh. There is. Ogham, Runic */
  1663. putshort (gpos, anydevtab ? 0x0088 : 0x0008); /* Alter YAdvance of first character */
  1664. putshort (gpos, 0x0000); /* leave second char alone */
  1665. }
  1666. else
  1667. {
  1668. putshort (gpos, anydevtab ? 0x0044 : 0x0004); /* Alter XAdvance of first character */
  1669. putshort (gpos, 0x0000); /* leave second char alone */
  1670. }
  1671. class1 =
  1672. ClassesFromNames (sf, kc->firsts, kc->first_cnt, at->maxp.numGlyphs,
  1673. &glyphs, false);
  1674. glyphs = GlyphsFromClasses (glyphs, at->maxp.numGlyphs);
  1675. class2 =
  1676. ClassesFromNames (sf, kc->seconds, kc->second_cnt, at->maxp.numGlyphs, NULL,
  1677. false);
  1678. putshort (gpos, 0); /* offset to first glyph classes */
  1679. putshort (gpos, 0); /* offset to second glyph classes */
  1680. putshort (gpos, kc->first_cnt);
  1681. putshort (gpos, kc->second_cnt);
  1682. next_devtab =
  1683. ftell (gpos) - begin_off +
  1684. kc->first_cnt * kc->second_cnt * 2 * sizeof (uint16_t);
  1685. for (i = 0; i < kc->first_cnt * kc->second_cnt; ++i)
  1686. {
  1687. putshort (gpos, kc->offsets[i]);
  1688. if (anydevtab && kc->adjusts[i].corrections != NULL)
  1689. {
  1690. putshort (gpos, next_devtab);
  1691. next_devtab += DevTabLen (&kc->adjusts[i]);
  1692. }
  1693. else if (anydevtab)
  1694. putshort (gpos, 0);
  1695. }
  1696. if (anydevtab)
  1697. {
  1698. for (i = 0; i < kc->first_cnt * kc->second_cnt; ++i)
  1699. {
  1700. if (kc->adjusts[i].corrections != NULL)
  1701. dumpgposdevicetable (gpos, &kc->adjusts[i]);
  1702. }
  1703. if (next_devtab != ftell (gpos) - begin_off)
  1704. IError ("Device table offsets screwed up in kerning class");
  1705. }
  1706. pos = ftell (gpos);
  1707. fseek (gpos, begin_off + 4 * sizeof (uint16_t), SEEK_SET);
  1708. putshort (gpos, pos - begin_off);
  1709. fseek (gpos, pos, SEEK_SET);
  1710. DumpClass (gpos, class1, at->maxp.numGlyphs);
  1711. pos = ftell (gpos);
  1712. fseek (gpos, begin_off + 5 * sizeof (uint16_t), SEEK_SET);
  1713. putshort (gpos, pos - begin_off);
  1714. fseek (gpos, pos, SEEK_SET);
  1715. DumpClass (gpos, class2, at->maxp.numGlyphs);
  1716. pos = ftell (gpos);
  1717. fseek (gpos, begin_off + sizeof (uint16_t), SEEK_SET);
  1718. putshort (gpos, pos - begin_off);
  1719. fseek (gpos, pos, SEEK_SET);
  1720. dumpcoveragetable (gpos, glyphs);
  1721. free (glyphs);
  1722. free (class1);
  1723. free (class2);
  1724. }
  1725. static void
  1726. dumpanchor (FILE *gpos, AnchorPoint *ap, int is_ttf)
  1727. {
  1728. int base = ftell (gpos);
  1729. if (ap->xadjust.corrections != NULL || ap->yadjust.corrections != NULL)
  1730. putshort (gpos, 3); /* format 3 w/ device tables */
  1731. else if (ap->has_ttf_pt && is_ttf)
  1732. putshort (gpos, 2); /* format 2 w/ a matching ttf point index */
  1733. else
  1734. putshort (gpos, 1); /* Anchor format 1 just location */
  1735. putshort (gpos, ap->me.x); /* X coord of attachment */
  1736. putshort (gpos, ap->me.y); /* Y coord of attachment */
  1737. if (ap->xadjust.corrections != NULL || ap->yadjust.corrections != NULL)
  1738. {
  1739. putshort (gpos, ap->xadjust.corrections == NULL ? 0 :
  1740. ftell (gpos) - base + 4);
  1741. putshort (gpos, ap->yadjust.corrections == NULL ? 0 :
  1742. ftell (gpos) - base + 2 + DevTabLen (&ap->xadjust));
  1743. dumpgposdevicetable (gpos, &ap->xadjust);
  1744. dumpgposdevicetable (gpos, &ap->yadjust);
  1745. }
  1746. else if (ap->has_ttf_pt && is_ttf)
  1747. putshort (gpos, ap->ttf_pt_index);
  1748. }
  1749. static void
  1750. dumpgposCursiveAttach (FILE *gpos, SplineFont *sf,
  1751. struct lookup_subtable *sub, struct glyphinfo *gi)
  1752. {
  1753. AnchorClass *ac, *testac;
  1754. SplineChar **entryexit;
  1755. int cnt, offset, j;
  1756. AnchorPoint *ap, *entry, *exit;
  1757. uint32_t coverage_offset, start;
  1758. ac = NULL;
  1759. for (testac = sf->anchor; testac != NULL; testac = testac->next)
  1760. {
  1761. if (testac->subtable == sub)
  1762. {
  1763. if (ac == NULL)
  1764. ac = testac;
  1765. else
  1766. {
  1767. ff_post_error (_("Two cursive anchor classes"),
  1768. _
  1769. ("Two cursive anchor classes in the same subtable, %s"),
  1770. sub->subtable_name);
  1771. break;
  1772. }
  1773. }
  1774. }
  1775. if (ac == NULL)
  1776. {
  1777. IError ("Missing anchor class for %s", sub->subtable_name);
  1778. return;
  1779. }
  1780. entryexit = EntryExitDecompose (sf, ac, gi);
  1781. if (entryexit == NULL)
  1782. return;
  1783. for (cnt = 0; entryexit[cnt] != NULL; ++cnt);
  1784. start = ftell (gpos);
  1785. putshort (gpos, 1); /* format 1 for this subtable */
  1786. putshort (gpos, 0); /* Fill in later, offset to coverage table */
  1787. putshort (gpos, cnt); /* number of glyphs */
  1788. offset = 6 + 2 * 2 * cnt;
  1789. for (j = 0; j < cnt; ++j)
  1790. {
  1791. entry = exit = NULL;
  1792. for (ap = entryexit[j]->anchor; ap != NULL; ap = ap->next)
  1793. {
  1794. if (ap->anchor == ac && ap->type == at_centry)
  1795. entry = ap;
  1796. if (ap->anchor == ac && ap->type == at_cexit)
  1797. exit = ap;
  1798. }
  1799. if (entry != NULL)
  1800. {
  1801. putshort (gpos, offset);
  1802. offset += 6;
  1803. if (entry->xadjust.corrections != NULL
  1804. || entry->yadjust.corrections != NULL)
  1805. offset +=
  1806. 4 + DevTabLen (&entry->xadjust) + DevTabLen (&entry->yadjust);
  1807. if (gi->is_ttf && entry->has_ttf_pt)
  1808. offset += 2;
  1809. }
  1810. else
  1811. putshort (gpos, 0);
  1812. if (exit != NULL)
  1813. {
  1814. putshort (gpos, offset);
  1815. offset += 6;
  1816. if (exit->xadjust.corrections != NULL
  1817. || exit->yadjust.corrections != NULL)
  1818. offset +=
  1819. 4 + DevTabLen (&exit->xadjust) + DevTabLen (&exit->yadjust);
  1820. else if (gi->is_ttf && exit->has_ttf_pt)
  1821. offset += 2;
  1822. }
  1823. else
  1824. putshort (gpos, 0);
  1825. }
  1826. for (j = 0; j < cnt; ++j)
  1827. {
  1828. entry = exit = NULL;
  1829. for (ap = entryexit[j]->anchor; ap != NULL; ap = ap->next)
  1830. {
  1831. if (ap->anchor == ac && ap->type == at_centry)
  1832. entry = ap;
  1833. if (ap->anchor == ac && ap->type == at_cexit)
  1834. exit = ap;
  1835. }
  1836. if (entry != NULL)
  1837. dumpanchor (gpos, entry, gi->is_ttf);
  1838. if (exit != NULL)
  1839. dumpanchor (gpos, exit, gi->is_ttf);
  1840. }
  1841. coverage_offset = ftell (gpos);
  1842. dumpcoveragetable (gpos, entryexit);
  1843. fseek (gpos, start + 2, SEEK_SET);
  1844. putshort (gpos, coverage_offset - start);
  1845. fseek (gpos, 0, SEEK_END);
  1846. free (entryexit);
  1847. }
  1848. static int
  1849. orderglyph (const void *_sc1, const void *_sc2)
  1850. {
  1851. SplineChar *const *sc1 = _sc1, *const *sc2 = _sc2;
  1852. return (*sc1)->ttf_glyph - (*sc2)->ttf_glyph;
  1853. }
  1854. static SplineChar **
  1855. allmarkglyphs (SplineChar ***glyphlist, int classcnt)
  1856. {
  1857. SplineChar **glyphs;
  1858. int i, tot, k;
  1859. if (classcnt == 1)
  1860. return glyphlist[0];
  1861. for (i = tot = 0; i < classcnt; ++i)
  1862. {
  1863. for (k = 0; glyphlist[i][k] != NULL; ++k);
  1864. tot += k;
  1865. }
  1866. glyphs = xmalloc ((tot + 1) * sizeof (SplineChar *));
  1867. for (i = tot = 0; i < classcnt; ++i)
  1868. {
  1869. for (k = 0; glyphlist[i][k] != NULL; ++k)
  1870. glyphs[tot++] = glyphlist[i][k];
  1871. }
  1872. qsort (glyphs, tot, sizeof (SplineChar *), orderglyph);
  1873. for (i = k = 0; i < tot; ++i)
  1874. {
  1875. while (i + 1 < tot && glyphs[i] == glyphs[i + 1])
  1876. ++i;
  1877. glyphs[k++] = glyphs[i];
  1878. }
  1879. glyphs[k] = NULL;
  1880. return glyphs;
  1881. }
  1882. static void
  1883. dumpgposAnchorData (FILE *gpos, AnchorClass * _ac,
  1884. enum anchor_type at,
  1885. SplineChar ***marks, SplineChar **base,
  1886. int classcnt, struct glyphinfo *gi)
  1887. {
  1888. AnchorClass *ac = NULL;
  1889. int j, cnt, k, l, pos, offset, tot, max;
  1890. uint32_t coverage_offset, markarray_offset, subtable_start;
  1891. AnchorPoint *ap, **aps;
  1892. SplineChar **markglyphs;
  1893. for (cnt = 0; base[cnt] != NULL; ++cnt);
  1894. subtable_start = ftell (gpos);
  1895. putshort (gpos, 1); /* format 1 for this subtable */
  1896. putshort (gpos, 0); /* Fill in later, offset to mark coverage table */
  1897. putshort (gpos, 0); /* Fill in later, offset to base coverage table */
  1898. putshort (gpos, classcnt);
  1899. putshort (gpos, 0); /* Fill in later, offset to mark array */
  1900. putshort (gpos, 12); /* Offset to base array */
  1901. /* Base array */
  1902. putshort (gpos, cnt); /* Number of entries in array */
  1903. if (at == at_basechar || at == at_basemark)
  1904. {
  1905. offset = 2;
  1906. for (l = 0; l < 3; ++l)
  1907. {
  1908. for (j = 0; j < cnt; ++j)
  1909. {
  1910. for (k = 0, ac = _ac; k < classcnt; ac = ac->next)
  1911. if (ac->matches)
  1912. {
  1913. if (!ac->has_mark || !ac->has_base)
  1914. continue;
  1915. for (ap = base[j]->anchor;
  1916. ap != NULL && (ap->anchor != ac || ap->type != at);
  1917. ap = ap->next);
  1918. switch (l)
  1919. {
  1920. case 0:
  1921. offset += 2;
  1922. break;
  1923. case 1:
  1924. if (ap == NULL)
  1925. putshort (gpos, 0);
  1926. else
  1927. {
  1928. putshort (gpos, offset);
  1929. offset += 6;
  1930. if (ap->xadjust.corrections != NULL
  1931. || ap->yadjust.corrections != NULL)
  1932. offset +=
  1933. 4 + DevTabLen (&ap->xadjust) +
  1934. DevTabLen (&ap->yadjust);
  1935. else if (gi->is_ttf && ap->has_ttf_pt)
  1936. offset += 2;
  1937. }
  1938. break;
  1939. case 2:
  1940. if (ap != NULL)
  1941. dumpanchor (gpos, ap, gi->is_ttf);
  1942. break;
  1943. }
  1944. ++k;
  1945. }
  1946. }
  1947. }
  1948. }
  1949. else
  1950. {
  1951. offset = 2 + 2 * cnt;
  1952. max = 0;
  1953. for (j = 0; j < cnt; ++j)
  1954. {
  1955. putshort (gpos, offset);
  1956. pos = tot = 0;
  1957. for (ap = base[j]->anchor; ap != NULL; ap = ap->next)
  1958. for (k = 0, ac = _ac; k < classcnt; ac = ac->next)
  1959. if (ac->matches)
  1960. {
  1961. if (ap->anchor == ac)
  1962. {
  1963. if (ap->lig_index > pos)
  1964. pos = ap->lig_index;
  1965. ++tot;
  1966. }
  1967. ++k;
  1968. }
  1969. if (pos > max)
  1970. max = pos;
  1971. offset += 2 + (pos + 1) * classcnt * 2 + tot * 6;
  1972. /* 2 for component count, for each component an offset to an offset to an anchor record */
  1973. }
  1974. ++max;
  1975. aps = xmalloc ((classcnt * max) * sizeof (AnchorPoint *));
  1976. for (j = 0; j < cnt; ++j)
  1977. {
  1978. memset (aps, 0, (classcnt * max) * sizeof (AnchorPoint *));
  1979. pos = 0;
  1980. for (ap = base[j]->anchor; ap != NULL; ap = ap->next)
  1981. for (k = 0, ac = _ac; k < classcnt; ac = ac->next)
  1982. if (ac->matches)
  1983. {
  1984. if (ap->anchor == ac)
  1985. {
  1986. if (ap->lig_index > pos)
  1987. pos = ap->lig_index;
  1988. aps[k * max + ap->lig_index] = ap;
  1989. }
  1990. ++k;
  1991. }
  1992. ++pos;
  1993. putshort (gpos, pos);
  1994. offset = 2 + 2 * pos * classcnt;
  1995. for (l = 0; l < pos; ++l)
  1996. {
  1997. for (k = 0; k < classcnt; ++k)
  1998. {
  1999. if (aps[k * max + l] == NULL)
  2000. putshort (gpos, 0);
  2001. else
  2002. {
  2003. putshort (gpos, offset);
  2004. offset += 6;
  2005. if (aps[k * max + l]->xadjust.corrections != NULL
  2006. || aps[k * max + l]->yadjust.corrections != NULL)
  2007. offset +=
  2008. 4 + DevTabLen (&aps[k * max + l]->xadjust) +
  2009. DevTabLen (&aps[k * max + l]->yadjust);
  2010. else if (gi->is_ttf && aps[k * max + l]->has_ttf_pt)
  2011. offset += 2;
  2012. }
  2013. }
  2014. }
  2015. for (l = 0; l < pos; ++l)
  2016. {
  2017. for (k = 0; k < classcnt; ++k)
  2018. {
  2019. if (aps[k * max + l] != NULL)
  2020. {
  2021. dumpanchor (gpos, aps[k * max + l], gi->is_ttf);
  2022. }
  2023. }
  2024. }
  2025. }
  2026. free (aps);
  2027. }
  2028. coverage_offset = ftell (gpos);
  2029. fseek (gpos, subtable_start + 4, SEEK_SET);
  2030. putshort (gpos, coverage_offset - subtable_start);
  2031. fseek (gpos, 0, SEEK_END);
  2032. dumpcoveragetable (gpos, base);
  2033. /* We tried sharing the mark table, (among all these sub-tables) but */
  2034. /* that doesn't work because we need to be able to reorder the sub-tables */
  2035. markglyphs = allmarkglyphs (marks, classcnt);
  2036. coverage_offset = ftell (gpos);
  2037. dumpcoveragetable (gpos, markglyphs);
  2038. markarray_offset = ftell (gpos);
  2039. for (cnt = 0; markglyphs[cnt] != NULL; ++cnt);
  2040. putshort (gpos, cnt);
  2041. offset = 2 + 4 * cnt;
  2042. for (j = 0; j < cnt; ++j)
  2043. {
  2044. if (classcnt == 0)
  2045. {
  2046. putshort (gpos, 0); /* Only one class */
  2047. ap = NULL;
  2048. }
  2049. else
  2050. {
  2051. for (k = 0, ac = _ac; k < classcnt; ac = ac->next)
  2052. {
  2053. if (ac->matches)
  2054. {
  2055. for (ap = markglyphs[j]->anchor;
  2056. ap != NULL && (ap->anchor != ac || ap->type != at_mark);
  2057. ap = ap->next);
  2058. if (ap != NULL)
  2059. break;
  2060. ++k;
  2061. }
  2062. }
  2063. putshort (gpos, k);
  2064. }
  2065. putshort (gpos, offset);
  2066. offset += 6;
  2067. if (ap != NULL
  2068. && (ap->xadjust.corrections != NULL
  2069. || ap->yadjust.corrections != NULL))
  2070. offset += 4 + DevTabLen (&ap->xadjust) + DevTabLen (&ap->yadjust);
  2071. else if (gi->is_ttf && ap->has_ttf_pt)
  2072. offset += 2;
  2073. }
  2074. for (j = 0; j < cnt; ++j)
  2075. {
  2076. for (k = 0, ac = _ac; k < classcnt; ac = ac->next)
  2077. {
  2078. if (ac->matches)
  2079. {
  2080. for (ap = markglyphs[j]->anchor;
  2081. ap != NULL && (ap->anchor != ac || ap->type != at_mark);
  2082. ap = ap->next);
  2083. if (ap != NULL)
  2084. break;
  2085. ++k;
  2086. }
  2087. }
  2088. dumpanchor (gpos, ap, gi->is_ttf);
  2089. }
  2090. if (markglyphs != marks[0])
  2091. free (markglyphs);
  2092. fseek (gpos, subtable_start + 2, SEEK_SET); /* mark coverage table offset */
  2093. putshort (gpos, coverage_offset - subtable_start);
  2094. fseek (gpos, 4, SEEK_CUR);
  2095. putshort (gpos, markarray_offset - subtable_start);
  2096. fseek (gpos, 0, SEEK_END);
  2097. }
  2098. static void
  2099. dumpGSUBsimplesubs (FILE *gsub, SplineFont *sf, struct lookup_subtable *sub)
  2100. {
  2101. int cnt, diff, ok = true;
  2102. int32_t coverage_pos, end;
  2103. SplineChar **glyphs, ***maps;
  2104. glyphs = SFOrderedGlyphsWithPSTinSubtable (sf, sub);
  2105. maps = generateMapList (glyphs, sub);
  2106. diff = (*maps[0])->ttf_glyph - glyphs[0]->ttf_glyph;
  2107. for (cnt = 0; glyphs[cnt] != NULL; ++cnt)
  2108. if (diff != maps[cnt][0]->ttf_glyph - glyphs[cnt]->ttf_glyph)
  2109. ok = false;
  2110. if (ok)
  2111. {
  2112. putshort (gsub, 1); /* delta format */
  2113. coverage_pos = ftell (gsub);
  2114. putshort (gsub, 0); /* offset to coverage table */
  2115. putshort (gsub, diff);
  2116. }
  2117. else
  2118. {
  2119. putshort (gsub, 2); /* glyph list format */
  2120. coverage_pos = ftell (gsub);
  2121. putshort (gsub, 0); /* offset to coverage table */
  2122. putshort (gsub, cnt);
  2123. for (cnt = 0; glyphs[cnt] != NULL; ++cnt)
  2124. putshort (gsub, (*maps[cnt])->ttf_glyph);
  2125. }
  2126. end = ftell (gsub);
  2127. fseek (gsub, coverage_pos, SEEK_SET);
  2128. putshort (gsub, end - coverage_pos + 2);
  2129. fseek (gsub, end, SEEK_SET);
  2130. dumpcoveragetable (gsub, glyphs);
  2131. free (glyphs);
  2132. GlyphMapFree (maps);
  2133. }
  2134. static void
  2135. dumpGSUBmultiplesubs (FILE *gsub, SplineFont *sf, struct lookup_subtable *sub)
  2136. {
  2137. int cnt, offset;
  2138. int32_t coverage_pos, end;
  2139. int gc;
  2140. SplineChar **glyphs, ***maps;
  2141. glyphs = SFOrderedGlyphsWithPSTinSubtable (sf, sub);
  2142. maps = generateMapList (glyphs, sub);
  2143. for (cnt = 0; glyphs[cnt] != NULL; ++cnt);
  2144. putshort (gsub, 1); /* glyph list format */
  2145. coverage_pos = ftell (gsub);
  2146. putshort (gsub, 0); /* offset to coverage table */
  2147. putshort (gsub, cnt);
  2148. offset = 6 + 2 * cnt;
  2149. for (cnt = 0; glyphs[cnt] != NULL; ++cnt)
  2150. {
  2151. putshort (gsub, offset);
  2152. for (gc = 0; maps[cnt][gc] != NULL; ++gc);
  2153. offset += 2 + 2 * gc;
  2154. }
  2155. for (cnt = 0; glyphs[cnt] != NULL; ++cnt)
  2156. {
  2157. for (gc = 0; maps[cnt][gc] != NULL; ++gc);
  2158. putshort (gsub, gc);
  2159. for (gc = 0; maps[cnt][gc] != NULL; ++gc)
  2160. putshort (gsub, maps[cnt][gc]->ttf_glyph);
  2161. }
  2162. end = ftell (gsub);
  2163. fseek (gsub, coverage_pos, SEEK_SET);
  2164. putshort (gsub, end - coverage_pos + 2);
  2165. fseek (gsub, end, SEEK_SET);
  2166. dumpcoveragetable (gsub, glyphs);
  2167. free (glyphs);
  2168. GlyphMapFree (maps);
  2169. }
  2170. static int
  2171. AllToBeOutput (LigList * lig)
  2172. {
  2173. struct splinecharlist *cmp;
  2174. if (lig->lig->u.lig.lig->ttf_glyph == -1 || lig->first->ttf_glyph == -1)
  2175. return 0;
  2176. for (cmp = lig->components; cmp != NULL; cmp = cmp->next)
  2177. if (cmp->sc->ttf_glyph == -1)
  2178. return 0;
  2179. return true;
  2180. }
  2181. static void
  2182. dumpGSUBligdata (FILE *gsub, SplineFont *sf,
  2183. struct lookup_subtable *sub, struct alltabs *at)
  2184. {
  2185. int32_t coverage_pos, next_val_pos, here, lig_list_start;
  2186. int cnt, i, pcnt, lcnt, max = 100, j;
  2187. uint16_t *offsets = NULL, *ligoffsets = xmalloc (max * sizeof (uint16_t));
  2188. SplineChar **glyphs;
  2189. LigList *ll;
  2190. struct splinecharlist *scl;
  2191. glyphs = SFOrderedGlyphsWithPSTinSubtable (sf, sub);
  2192. cnt = 0;
  2193. if (glyphs != NULL)
  2194. for (; glyphs[cnt] != NULL; ++cnt);
  2195. putshort (gsub, 1); /* only one format for ligatures */
  2196. coverage_pos = ftell (gsub);
  2197. putshort (gsub, 0); /* offset to coverage table */
  2198. putshort (gsub, cnt);
  2199. next_val_pos = ftell (gsub);
  2200. if (glyphs != NULL)
  2201. offsets = xmalloc (cnt * sizeof (int16_t));
  2202. for (i = 0; i < cnt; ++i)
  2203. putshort (gsub, 0);
  2204. for (i = 0; i < cnt; ++i)
  2205. {
  2206. offsets[i] = ftell (gsub) - coverage_pos + 2;
  2207. for (pcnt = 0, ll = glyphs[i]->ligofme; ll != NULL; ll = ll->next)
  2208. if (ll->lig->subtable == sub && AllToBeOutput (ll))
  2209. ++pcnt;
  2210. putshort (gsub, pcnt);
  2211. if (pcnt >= max)
  2212. {
  2213. max = pcnt + 100;
  2214. ligoffsets = xrealloc (ligoffsets, max * sizeof (int));
  2215. }
  2216. lig_list_start = ftell (gsub);
  2217. for (j = 0; j < pcnt; ++j)
  2218. putshort (gsub, 0); /* Place holders */
  2219. for (pcnt = 0, ll = glyphs[i]->ligofme; ll != NULL; ll = ll->next)
  2220. {
  2221. if (ll->lig->subtable == sub && AllToBeOutput (ll))
  2222. {
  2223. ligoffsets[pcnt] = ftell (gsub) - lig_list_start + 2;
  2224. putshort (gsub, ll->lig->u.lig.lig->ttf_glyph);
  2225. for (lcnt = 0, scl = ll->components; scl != NULL; scl = scl->next)
  2226. ++lcnt;
  2227. putshort (gsub, lcnt + 1);
  2228. if (lcnt + 1 > at->os2.maxContext)
  2229. at->os2.maxContext = lcnt + 1;
  2230. for (scl = ll->components; scl != NULL; scl = scl->next)
  2231. putshort (gsub, scl->sc->ttf_glyph);
  2232. ++pcnt;
  2233. }
  2234. }
  2235. fseek (gsub, lig_list_start, SEEK_SET);
  2236. for (j = 0; j < pcnt; ++j)
  2237. putshort (gsub, ligoffsets[j]);
  2238. fseek (gsub, 0, SEEK_END);
  2239. }
  2240. free (ligoffsets);
  2241. if (glyphs != NULL)
  2242. {
  2243. here = ftell (gsub);
  2244. fseek (gsub, coverage_pos, SEEK_SET);
  2245. putshort (gsub, here - coverage_pos + 2);
  2246. fseek (gsub, next_val_pos, SEEK_SET);
  2247. for (i = 0; i < cnt; ++i)
  2248. putshort (gsub, offsets[i]);
  2249. fseek (gsub, here, SEEK_SET);
  2250. dumpcoveragetable (gsub, glyphs);
  2251. free (glyphs);
  2252. free (offsets);
  2253. }
  2254. }
  2255. static int
  2256. ui16cmp (const void *_i1, const void *_i2)
  2257. {
  2258. if (*(const uint16_t *) _i1 > *(const uint16_t *) _i2)
  2259. return 1;
  2260. if (*(const uint16_t *) _i1 < *(const uint16_t *) _i2)
  2261. return -1;
  2262. return 0;
  2263. }
  2264. static uint16_t *
  2265. FigureInitialClasses (FPST *fpst)
  2266. {
  2267. uint16_t *initial = xmalloc ((fpst->nccnt + 1) * sizeof (uint16_t));
  2268. int i, cnt, j;
  2269. for (i = cnt = 0; i < fpst->rule_cnt; ++i)
  2270. {
  2271. for (j = 0; j < cnt; ++j)
  2272. if (initial[j] == fpst->rules[i].u.class.nclasses[0])
  2273. break;
  2274. if (j == cnt)
  2275. initial[cnt++] = fpst->rules[i].u.class.nclasses[0];
  2276. }
  2277. qsort (initial, cnt, sizeof (uint16_t), ui16cmp);
  2278. initial[cnt] = 0xffff;
  2279. return initial;
  2280. }
  2281. static SplineChar **
  2282. OrderedInitialGlyphs (SplineFont *sf, FPST *fpst)
  2283. {
  2284. SplineChar **glyphs, *sc;
  2285. int i, j, cnt, ch;
  2286. char *pt, *names;
  2287. glyphs = xmalloc ((fpst->rule_cnt + 1) * sizeof (SplineChar *));
  2288. for (i = cnt = 0; i < fpst->rule_cnt; ++i)
  2289. {
  2290. names = fpst->rules[i].u.glyph.names;
  2291. pt = strchr (names, ' ');
  2292. if (pt == NULL)
  2293. pt = names + strlen (names);
  2294. ch = *pt;
  2295. *pt = '\0';
  2296. sc = SFGetChar (sf, -1, names);
  2297. *pt = ch;
  2298. for (j = 0; j < cnt; ++j)
  2299. if (glyphs[j] == sc)
  2300. break;
  2301. if (j == cnt && sc != NULL)
  2302. glyphs[cnt++] = sc;
  2303. }
  2304. glyphs[cnt] = NULL;
  2305. if (cnt == 0)
  2306. return glyphs;
  2307. for (i = 0; glyphs[i + 1] != NULL; ++i)
  2308. for (j = i + 1; glyphs[j] != NULL; ++j)
  2309. {
  2310. if (glyphs[i]->ttf_glyph > glyphs[j]->ttf_glyph)
  2311. {
  2312. sc = glyphs[i];
  2313. glyphs[i] = glyphs[j];
  2314. glyphs[j] = sc;
  2315. }
  2316. }
  2317. return glyphs;
  2318. }
  2319. static int
  2320. NamesStartWith (SplineChar *sc, char *names)
  2321. {
  2322. char *pt;
  2323. pt = strchr (names, ' ');
  2324. if (pt == NULL)
  2325. pt = names + strlen (names);
  2326. if (pt - names != strlen (sc->name))
  2327. return false;
  2328. return strncmp (sc->name, names, pt - names) == 0;
  2329. }
  2330. static int
  2331. CntRulesStartingWith (FPST *fpst, SplineChar *sc)
  2332. {
  2333. int i, cnt;
  2334. for (i = cnt = 0; i < fpst->rule_cnt; ++i)
  2335. {
  2336. if (NamesStartWith (sc, fpst->rules[i].u.glyph.names))
  2337. ++cnt;
  2338. }
  2339. return cnt;
  2340. }
  2341. static int
  2342. CntRulesStartingWithClass (FPST *fpst, uint16_t cval)
  2343. {
  2344. int i, cnt;
  2345. for (i = cnt = 0; i < fpst->rule_cnt; ++i)
  2346. {
  2347. if (fpst->rules[i].u.class.nclasses[0] == cval)
  2348. ++cnt;
  2349. }
  2350. return cnt;
  2351. }
  2352. static void
  2353. dumpg___ContextChainGlyphs (FILE *lfile, SplineFont *sf,
  2354. struct lookup_subtable *sub, struct alltabs *at)
  2355. {
  2356. FPST *fpst = sub->fpst;
  2357. int iscontext = fpst->type == pst_contextpos || fpst->type == pst_contextsub;
  2358. uint32_t base = ftell (lfile);
  2359. int i, cnt, subcnt, j, k, l, maxcontext, curcontext;
  2360. SplineChar **glyphs, **subglyphs;
  2361. int lc;
  2362. glyphs = OrderedInitialGlyphs (sf, fpst);
  2363. for (cnt = 0; glyphs[cnt] != NULL; ++cnt);
  2364. putshort (lfile, 1); /* Sub format 1 => glyph lists */
  2365. putshort (lfile, (3 + cnt) * sizeof (short)); /* offset to coverage */
  2366. putshort (lfile, cnt);
  2367. for (i = 0; i < cnt; ++i)
  2368. putshort (lfile, 0); /* Offset to rule */
  2369. dumpcoveragetable (lfile, glyphs);
  2370. maxcontext = 0;
  2371. for (i = 0; i < cnt; ++i)
  2372. {
  2373. uint32_t pos = ftell (lfile);
  2374. fseek (lfile, base + (3 + i) * sizeof (short), SEEK_SET);
  2375. putshort (lfile, pos - base);
  2376. fseek (lfile, pos, SEEK_SET);
  2377. subcnt = CntRulesStartingWith (fpst, glyphs[i]);
  2378. putshort (lfile, subcnt);
  2379. for (j = 0; j < subcnt; ++j)
  2380. putshort (lfile, 0);
  2381. for (j = k = 0; k < fpst->rule_cnt; ++k)
  2382. if (NamesStartWith (glyphs[i], fpst->rules[k].u.glyph.names))
  2383. {
  2384. uint32_t subpos = ftell (lfile);
  2385. fseek (lfile, pos + (1 + j) * sizeof (short), SEEK_SET);
  2386. putshort (lfile, subpos - pos);
  2387. fseek (lfile, subpos, SEEK_SET);
  2388. for (l = lc = 0; l < fpst->rules[k].lookup_cnt; ++l)
  2389. if (fpst->rules[k].lookups[l].lookup->lookup_index != -1)
  2390. ++lc;
  2391. if (iscontext)
  2392. {
  2393. subglyphs =
  2394. SFGlyphsFromNames (sf, fpst->rules[k].u.glyph.names);
  2395. for (l = 0; subglyphs[l] != NULL; ++l);
  2396. putshort (lfile, l);
  2397. curcontext = l;
  2398. putshort (lfile, lc);
  2399. for (l = 1; subglyphs[l] != NULL; ++l)
  2400. putshort (lfile, subglyphs[l]->ttf_glyph);
  2401. free (subglyphs);
  2402. }
  2403. else
  2404. {
  2405. subglyphs = SFGlyphsFromNames (sf, fpst->rules[k].u.glyph.back);
  2406. for (l = 0; subglyphs[l] != NULL; ++l);
  2407. putshort (lfile, l);
  2408. curcontext = l;
  2409. for (l = 0; subglyphs[l] != NULL; ++l)
  2410. putshort (lfile, subglyphs[l]->ttf_glyph);
  2411. free (subglyphs);
  2412. subglyphs =
  2413. SFGlyphsFromNames (sf, fpst->rules[k].u.glyph.names);
  2414. for (l = 0; subglyphs[l] != NULL; ++l);
  2415. putshort (lfile, l);
  2416. curcontext += l;
  2417. for (l = 1; subglyphs[l] != NULL; ++l)
  2418. putshort (lfile, subglyphs[l]->ttf_glyph);
  2419. free (subglyphs);
  2420. subglyphs = SFGlyphsFromNames (sf, fpst->rules[k].u.glyph.fore);
  2421. for (l = 0; subglyphs[l] != NULL; ++l);
  2422. putshort (lfile, l);
  2423. curcontext += l;
  2424. for (l = 0; subglyphs[l] != NULL; ++l)
  2425. putshort (lfile, subglyphs[l]->ttf_glyph);
  2426. free (subglyphs);
  2427. putshort (lfile, lc);
  2428. }
  2429. for (l = 0; l < fpst->rules[k].lookup_cnt; ++l)
  2430. if (fpst->rules[k].lookups[l].lookup->lookup_index != -1)
  2431. {
  2432. putshort (lfile, fpst->rules[k].lookups[l].seq);
  2433. putshort (lfile,
  2434. fpst->rules[k].lookups[l].lookup->lookup_index);
  2435. }
  2436. ++j;
  2437. if (curcontext > maxcontext)
  2438. maxcontext = curcontext;
  2439. }
  2440. }
  2441. free (glyphs);
  2442. if (maxcontext > at->os2.maxContext)
  2443. at->os2.maxContext = maxcontext;
  2444. }
  2445. static int
  2446. ClassesMatch (int cnt1, char **classes1, int cnt2, char **classes2)
  2447. {
  2448. int i;
  2449. if (cnt1 != cnt2)
  2450. return false;
  2451. for (i = 1; i < cnt2; ++i)
  2452. if (strcmp (classes1[i], classes2[i]) != 0)
  2453. return false;
  2454. return true;
  2455. }
  2456. static void
  2457. dumpg___ContextChainClass (FILE *lfile, SplineFont *sf,
  2458. struct lookup_subtable *sub, struct alltabs *at)
  2459. {
  2460. FPST *fpst = sub->fpst;
  2461. int iscontext = fpst->type == pst_contextpos || fpst->type == pst_contextsub;
  2462. uint32_t base = ftell (lfile), rulebase, pos, subpos, npos;
  2463. uint16_t *initialclasses, *iclass, *bclass, *lclass;
  2464. SplineChar **iglyphs, **bglyphs, **lglyphs, **glyphs;
  2465. int i, ii, cnt, subcnt, j, k, l, maxcontext, curcontext;
  2466. int lc;
  2467. putshort (lfile, 2); /* Sub format 2 => class */
  2468. putshort (lfile, 0); /* offset to coverage table */
  2469. if (iscontext)
  2470. putshort (lfile, 0); /* offset to input classdef */
  2471. else
  2472. {
  2473. putshort (lfile, 0); /* offset to backtrack classdef */
  2474. putshort (lfile, 0); /* offset to input classdef */
  2475. putshort (lfile, 0); /* offset to lookahead classdef */
  2476. }
  2477. initialclasses = FigureInitialClasses (fpst);
  2478. putshort (lfile, fpst->nccnt);
  2479. rulebase = ftell (lfile);
  2480. for (cnt = 0; cnt < fpst->nccnt; ++cnt)
  2481. putshort (lfile, 0);
  2482. iclass =
  2483. ClassesFromNames (sf, fpst->nclass, fpst->nccnt, at->maxp.numGlyphs,
  2484. &iglyphs, false);
  2485. lglyphs = bglyphs = NULL;
  2486. bclass = lclass = NULL;
  2487. if (!iscontext)
  2488. {
  2489. bclass =
  2490. ClassesFromNames (sf, fpst->bclass, fpst->bccnt, at->maxp.numGlyphs,
  2491. &bglyphs, false);
  2492. lclass =
  2493. ClassesFromNames (sf, fpst->fclass, fpst->fccnt, at->maxp.numGlyphs,
  2494. &lglyphs, false);
  2495. }
  2496. pos = ftell (lfile);
  2497. fseek (lfile, base + sizeof (uint16_t), SEEK_SET);
  2498. putshort (lfile, pos - base);
  2499. fseek (lfile, pos, SEEK_SET);
  2500. glyphs =
  2501. GlyphsFromInitialClasses (iglyphs, at->maxp.numGlyphs, iclass,
  2502. initialclasses);
  2503. dumpcoveragetable (lfile, glyphs);
  2504. free (glyphs);
  2505. free (iglyphs);
  2506. free (bglyphs);
  2507. free (lglyphs);
  2508. if (iscontext)
  2509. {
  2510. pos = ftell (lfile);
  2511. fseek (lfile, base + 2 * sizeof (uint16_t), SEEK_SET);
  2512. putshort (lfile, pos - base);
  2513. fseek (lfile, pos, SEEK_SET);
  2514. DumpClass (lfile, iclass, at->maxp.numGlyphs);
  2515. free (iclass);
  2516. }
  2517. else
  2518. {
  2519. pos = ftell (lfile);
  2520. fseek (lfile, base + 2 * sizeof (uint16_t), SEEK_SET);
  2521. putshort (lfile, pos - base);
  2522. fseek (lfile, pos, SEEK_SET);
  2523. DumpClass (lfile, bclass, at->maxp.numGlyphs);
  2524. if (ClassesMatch (fpst->bccnt, fpst->bclass, fpst->nccnt, fpst->nclass))
  2525. {
  2526. npos = pos;
  2527. fseek (lfile, base + 3 * sizeof (uint16_t), SEEK_SET);
  2528. putshort (lfile, npos - base);
  2529. fseek (lfile, 0, SEEK_END);
  2530. }
  2531. else
  2532. {
  2533. npos = ftell (lfile);
  2534. fseek (lfile, base + 3 * sizeof (uint16_t), SEEK_SET);
  2535. putshort (lfile, npos - base);
  2536. fseek (lfile, npos, SEEK_SET);
  2537. DumpClass (lfile, iclass, at->maxp.numGlyphs);
  2538. }
  2539. if (ClassesMatch (fpst->fccnt, fpst->fclass, fpst->bccnt, fpst->bclass))
  2540. {
  2541. fseek (lfile, base + 4 * sizeof (uint16_t), SEEK_SET);
  2542. putshort (lfile, pos - base);
  2543. fseek (lfile, 0, SEEK_END);
  2544. }
  2545. else
  2546. if (ClassesMatch (fpst->fccnt, fpst->fclass, fpst->nccnt, fpst->nclass))
  2547. {
  2548. fseek (lfile, base + 4 * sizeof (uint16_t), SEEK_SET);
  2549. putshort (lfile, npos - base);
  2550. fseek (lfile, 0, SEEK_END);
  2551. }
  2552. else
  2553. {
  2554. pos = ftell (lfile);
  2555. fseek (lfile, base + 4 * sizeof (uint16_t), SEEK_SET);
  2556. putshort (lfile, pos - base);
  2557. fseek (lfile, pos, SEEK_SET);
  2558. DumpClass (lfile, lclass, at->maxp.numGlyphs);
  2559. }
  2560. free (iclass);
  2561. free (bclass);
  2562. free (lclass);
  2563. }
  2564. ii = 0;
  2565. for (i = 0; i < fpst->nccnt; ++i)
  2566. {
  2567. if (initialclasses[ii] != i)
  2568. {
  2569. /* This class isn't an initial one, so leave it's rule pointer NULL */
  2570. }
  2571. else
  2572. {
  2573. ++ii;
  2574. pos = ftell (lfile);
  2575. fseek (lfile, rulebase + i * sizeof (short), SEEK_SET);
  2576. putshort (lfile, pos - base);
  2577. fseek (lfile, pos, SEEK_SET);
  2578. subcnt = CntRulesStartingWithClass (fpst, i);
  2579. putshort (lfile, subcnt);
  2580. for (j = 0; j < subcnt; ++j)
  2581. putshort (lfile, 0);
  2582. for (j = k = 0; k < fpst->rule_cnt; ++k)
  2583. if (i == fpst->rules[k].u.class.nclasses[0])
  2584. {
  2585. subpos = ftell (lfile);
  2586. fseek (lfile, pos + (1 + j) * sizeof (short), SEEK_SET);
  2587. putshort (lfile, subpos - pos);
  2588. fseek (lfile, subpos, SEEK_SET);
  2589. for (l = lc = 0; l < fpst->rules[k].lookup_cnt; ++l)
  2590. if (fpst->rules[k].lookups[l].lookup->lookup_index != -1)
  2591. ++lc;
  2592. if (iscontext)
  2593. {
  2594. putshort (lfile, fpst->rules[k].u.class.ncnt);
  2595. putshort (lfile, lc);
  2596. for (l = 1; l < fpst->rules[k].u.class.ncnt; ++l)
  2597. putshort (lfile, fpst->rules[k].u.class.nclasses[l]);
  2598. }
  2599. else
  2600. {
  2601. putshort (lfile, fpst->rules[k].u.class.bcnt);
  2602. for (l = 0; l < fpst->rules[k].u.class.bcnt; ++l)
  2603. putshort (lfile, fpst->rules[k].u.class.bclasses[l]);
  2604. putshort (lfile, fpst->rules[k].u.class.ncnt);
  2605. for (l = 1; l < fpst->rules[k].u.class.ncnt; ++l)
  2606. putshort (lfile, fpst->rules[k].u.class.nclasses[l]);
  2607. putshort (lfile, fpst->rules[k].u.class.fcnt);
  2608. for (l = 0; l < fpst->rules[k].u.class.fcnt; ++l)
  2609. putshort (lfile, fpst->rules[k].u.class.fclasses[l]);
  2610. putshort (lfile, lc);
  2611. }
  2612. for (l = 0; l < fpst->rules[k].lookup_cnt; ++l)
  2613. if (fpst->rules[k].lookups[l].lookup->lookup_index != -1)
  2614. {
  2615. putshort (lfile, fpst->rules[k].lookups[l].seq);
  2616. putshort (lfile,
  2617. fpst->rules[k].lookups[l].lookup->lookup_index);
  2618. }
  2619. ++j;
  2620. }
  2621. }
  2622. }
  2623. free (initialclasses);
  2624. maxcontext = 0;
  2625. for (i = 0; i < fpst->rule_cnt; ++i)
  2626. {
  2627. curcontext =
  2628. fpst->rules[i].u.class.ncnt + fpst->rules[i].u.class.bcnt +
  2629. fpst->rules[i].u.class.fcnt;
  2630. if (curcontext > maxcontext)
  2631. maxcontext = curcontext;
  2632. }
  2633. if (maxcontext > at->os2.maxContext)
  2634. at->os2.maxContext = maxcontext;
  2635. }
  2636. static void
  2637. dumpg___ContextChainCoverage (FILE *lfile, SplineFont *sf,
  2638. struct lookup_subtable *sub, struct alltabs *at)
  2639. {
  2640. FPST *fpst = sub->fpst;
  2641. int iscontext = fpst->type == pst_contextpos || fpst->type == pst_contextsub;
  2642. uint32_t base = ftell (lfile), ibase, lbase, bbase;
  2643. int i, l;
  2644. SplineChar **glyphs;
  2645. int curcontext;
  2646. int lc;
  2647. if (fpst->rule_cnt != 1)
  2648. IError ("Bad rule cnt in coverage context lookup");
  2649. if (fpst->format == pst_reversecoverage
  2650. && fpst->rules[0].u.rcoverage.always1 != 1)
  2651. IError ("Bad input count in reverse coverage lookup");
  2652. putshort (lfile, 3); /* Sub format 3 => coverage */
  2653. for (l = lc = 0; l < fpst->rules[0].lookup_cnt; ++l)
  2654. if (fpst->rules[0].lookups[l].lookup->lookup_index != -1)
  2655. ++lc;
  2656. if (iscontext)
  2657. {
  2658. putshort (lfile, fpst->rules[0].u.coverage.ncnt);
  2659. putshort (lfile, lc);
  2660. for (i = 0; i < fpst->rules[0].u.coverage.ncnt; ++i)
  2661. putshort (lfile, 0);
  2662. for (i = 0; i < fpst->rules[0].lookup_cnt; ++i)
  2663. if (fpst->rules[0].lookups[i].lookup->lookup_index != -1)
  2664. {
  2665. putshort (lfile, fpst->rules[0].lookups[i].seq);
  2666. putshort (lfile, fpst->rules[0].lookups[i].lookup->lookup_index);
  2667. }
  2668. for (i = 0; i < fpst->rules[0].u.coverage.ncnt; ++i)
  2669. {
  2670. uint32_t pos = ftell (lfile);
  2671. fseek (lfile, base + 6 + 2 * i, SEEK_SET);
  2672. putshort (lfile, pos - base);
  2673. fseek (lfile, pos, SEEK_SET);
  2674. glyphs =
  2675. OrderedGlyphsFromNames (sf, fpst->rules[0].u.coverage.ncovers[i]);
  2676. dumpcoveragetable (lfile, glyphs);
  2677. free (glyphs);
  2678. }
  2679. }
  2680. else
  2681. {
  2682. if (fpst->format == pst_reversecoverage)
  2683. {
  2684. ibase = ftell (lfile);
  2685. putshort (lfile, 0);
  2686. }
  2687. putshort (lfile, fpst->rules[0].u.coverage.bcnt);
  2688. bbase = ftell (lfile);
  2689. for (i = 0; i < fpst->rules[0].u.coverage.bcnt; ++i)
  2690. putshort (lfile, 0);
  2691. if (fpst->format == pst_coverage)
  2692. {
  2693. putshort (lfile, fpst->rules[0].u.coverage.ncnt);
  2694. ibase = ftell (lfile);
  2695. for (i = 0; i < fpst->rules[0].u.coverage.ncnt; ++i)
  2696. putshort (lfile, 0);
  2697. }
  2698. putshort (lfile, fpst->rules[0].u.coverage.fcnt);
  2699. lbase = ftell (lfile);
  2700. for (i = 0; i < fpst->rules[0].u.coverage.fcnt; ++i)
  2701. putshort (lfile, 0);
  2702. if (fpst->format == pst_coverage)
  2703. {
  2704. putshort (lfile, lc);
  2705. for (i = 0; i < fpst->rules[0].lookup_cnt; ++i)
  2706. if (fpst->rules[0].lookups[i].lookup->lookup_index != -1)
  2707. {
  2708. putshort (lfile, fpst->rules[0].lookups[i].seq);
  2709. putshort (lfile,
  2710. fpst->rules[0].lookups[i].lookup->lookup_index);
  2711. }
  2712. }
  2713. else
  2714. { /* reverse coverage */
  2715. glyphs =
  2716. SFGlyphsFromNames (sf, fpst->rules[0].u.rcoverage.replacements);
  2717. for (i = 0; glyphs[i] != 0; ++i);
  2718. putshort (lfile, i);
  2719. for (i = 0; glyphs[i] != 0; ++i)
  2720. putshort (lfile, glyphs[i]->ttf_glyph);
  2721. }
  2722. for (i = 0; i < fpst->rules[0].u.coverage.ncnt; ++i)
  2723. {
  2724. uint32_t pos = ftell (lfile);
  2725. fseek (lfile, ibase + 2 * i, SEEK_SET);
  2726. putshort (lfile, pos - base);
  2727. fseek (lfile, pos, SEEK_SET);
  2728. glyphs =
  2729. OrderedGlyphsFromNames (sf, fpst->rules[0].u.coverage.ncovers[i]);
  2730. dumpcoveragetable (lfile, glyphs);
  2731. free (glyphs);
  2732. }
  2733. for (i = 0; i < fpst->rules[0].u.coverage.bcnt; ++i)
  2734. {
  2735. uint32_t pos = ftell (lfile);
  2736. fseek (lfile, bbase + 2 * i, SEEK_SET);
  2737. putshort (lfile, pos - base);
  2738. fseek (lfile, pos, SEEK_SET);
  2739. glyphs =
  2740. OrderedGlyphsFromNames (sf, fpst->rules[0].u.coverage.bcovers[i]);
  2741. dumpcoveragetable (lfile, glyphs);
  2742. free (glyphs);
  2743. }
  2744. for (i = 0; i < fpst->rules[0].u.coverage.fcnt; ++i)
  2745. {
  2746. uint32_t pos = ftell (lfile);
  2747. fseek (lfile, lbase + 2 * i, SEEK_SET);
  2748. putshort (lfile, pos - base);
  2749. fseek (lfile, pos, SEEK_SET);
  2750. glyphs =
  2751. OrderedGlyphsFromNames (sf, fpst->rules[0].u.coverage.fcovers[i]);
  2752. dumpcoveragetable (lfile, glyphs);
  2753. free (glyphs);
  2754. }
  2755. }
  2756. curcontext =
  2757. fpst->rules[0].u.coverage.ncnt + fpst->rules[0].u.coverage.bcnt +
  2758. fpst->rules[0].u.coverage.fcnt;
  2759. if (curcontext > at->os2.maxContext)
  2760. at->os2.maxContext = curcontext;
  2761. }
  2762. static void
  2763. dumpg___ContextChain (FILE *lfile, SplineFont *sf,
  2764. struct lookup_subtable *sub, struct alltabs *at)
  2765. {
  2766. FPST *fpst = sub->fpst;
  2767. switch (fpst->format)
  2768. {
  2769. case pst_glyphs:
  2770. dumpg___ContextChainGlyphs (lfile, sf, sub, at);
  2771. break;
  2772. case pst_class:
  2773. dumpg___ContextChainClass (lfile, sf, sub, at);
  2774. break;
  2775. case pst_coverage:
  2776. case pst_reversecoverage:
  2777. dumpg___ContextChainCoverage (lfile, sf, sub, at);
  2778. break;
  2779. }
  2780. fseek (lfile, 0, SEEK_END);
  2781. }
  2782. static void
  2783. AnchorsAway (FILE *lfile, SplineFont *sf,
  2784. struct lookup_subtable *sub, struct glyphinfo *gi)
  2785. {
  2786. SplineChar **base, **lig, **mkmk;
  2787. AnchorClass *ac, *acfirst;
  2788. SplineChar ***marks;
  2789. int *subcnts;
  2790. int cmax, classcnt;
  2791. int i;
  2792. marks = xmalloc ((cmax = 20) * sizeof (SplineChar **));
  2793. subcnts = xmalloc (cmax * sizeof (int));
  2794. classcnt = 0;
  2795. acfirst = NULL;
  2796. for (ac = sf->anchor; ac != NULL; ac = ac->next)
  2797. {
  2798. ac->matches = false;
  2799. if (ac->subtable == sub && !ac->processed)
  2800. {
  2801. if (acfirst == NULL)
  2802. acfirst = ac;
  2803. if (AnchorClass_lookup_type (ac) == gpos_cursive)
  2804. continue;
  2805. else if (ac->has_mark && ac->has_base)
  2806. {
  2807. ac->matches = ac->processed = true;
  2808. ++classcnt;
  2809. }
  2810. }
  2811. }
  2812. if (classcnt > cmax)
  2813. {
  2814. marks = xrealloc (marks, (cmax = classcnt + 10) * sizeof (SplineChar **));
  2815. subcnts = xrealloc (subcnts, cmax * sizeof (int));
  2816. }
  2817. AnchorClassDecompose (sf, acfirst, classcnt, subcnts, marks, &base, &lig,
  2818. &mkmk, gi);
  2819. switch (sub->lookup->lookup_type)
  2820. {
  2821. case gpos_mark2base:
  2822. if (marks[0] != NULL && base != NULL)
  2823. dumpgposAnchorData (lfile, acfirst, at_basechar, marks, base, classcnt,
  2824. gi);
  2825. break;
  2826. case gpos_mark2ligature:
  2827. if (marks[0] != NULL && lig != NULL)
  2828. dumpgposAnchorData (lfile, acfirst, at_baselig, marks, lig, classcnt,
  2829. gi);
  2830. break;
  2831. case gpos_mark2mark:
  2832. if (marks[0] != NULL && mkmk != NULL)
  2833. dumpgposAnchorData (lfile, acfirst, at_basemark, marks, mkmk, classcnt,
  2834. gi);
  2835. break;
  2836. }
  2837. for (i = 0; i < classcnt; ++i)
  2838. free (marks[i]);
  2839. free (base);
  2840. free (lig);
  2841. free (mkmk);
  2842. free (marks);
  2843. free (subcnts);
  2844. }
  2845. static int
  2846. lookup_size_cmp (const void *_l1, const void *_l2)
  2847. {
  2848. const OTLookup *l1 = *(OTLookup **) _l1, *l2 = *(OTLookup **) _l2;
  2849. return l1->lookup_length - l2->lookup_length;
  2850. }
  2851. static void
  2852. otf_dumpALookup (FILE *lfile, OTLookup *otl, SplineFont *sf, struct alltabs *at)
  2853. {
  2854. struct lookup_subtable *sub;
  2855. otl->lookup_offset = ftell (lfile);
  2856. for (sub = otl->subtables; sub != NULL; sub = sub->next)
  2857. {
  2858. sub->extra_subtables = NULL;
  2859. if (sub->unused)
  2860. sub->subtable_offset = -1;
  2861. else
  2862. {
  2863. sub->subtable_offset = ftell (lfile);
  2864. switch (otl->lookup_type)
  2865. {
  2866. /* GPOS lookup types */
  2867. case gpos_single:
  2868. dumpGPOSsimplepos (lfile, sf, sub);
  2869. break;
  2870. case gpos_pair:
  2871. if (at->os2.maxContext < 2)
  2872. at->os2.maxContext = 2;
  2873. if (sub->kc != NULL)
  2874. dumpgposkernclass (lfile, sf, sub, at);
  2875. else
  2876. dumpGPOSpairpos (lfile, sf, sub);
  2877. break;
  2878. case gpos_cursive:
  2879. dumpgposCursiveAttach (lfile, sf, sub, &at->gi);
  2880. break;
  2881. case gpos_mark2base:
  2882. case gpos_mark2ligature:
  2883. case gpos_mark2mark:
  2884. AnchorsAway (lfile, sf, sub, &at->gi);
  2885. break;
  2886. case gpos_contextchain:
  2887. case gpos_context:
  2888. dumpg___ContextChain (lfile, sf, sub, at);
  2889. break;
  2890. /* GSUB lookup types */
  2891. case gsub_single:
  2892. dumpGSUBsimplesubs (lfile, sf, sub);
  2893. break;
  2894. case gsub_multiple:
  2895. case gsub_alternate:
  2896. dumpGSUBmultiplesubs (lfile, sf, sub);
  2897. break;
  2898. case gsub_ligature:
  2899. dumpGSUBligdata (lfile, sf, sub, at);
  2900. break;
  2901. case gsub_contextchain:
  2902. case gsub_context:
  2903. case gsub_reversecchain:
  2904. dumpg___ContextChain (lfile, sf, sub, at);
  2905. break;
  2906. }
  2907. if (ftell (lfile) - sub->subtable_offset == 0)
  2908. {
  2909. IError ("Lookup sub table, %s in %s, contains no data.\n",
  2910. sub->subtable_name, sub->lookup->lookup_name);
  2911. sub->unused = true;
  2912. sub->subtable_offset = -1;
  2913. }
  2914. else if (sub->extra_subtables == NULL &&
  2915. ftell (lfile) - sub->subtable_offset > 65535)
  2916. IError
  2917. ("Lookup sub table, %s in %s, is too big. Will not be useable.\n",
  2918. sub->subtable_name, sub->lookup->lookup_name);
  2919. }
  2920. }
  2921. otl->lookup_length = ftell (lfile) - otl->lookup_offset;
  2922. }
  2923. static FILE *
  2924. G___figureLookups (SplineFont *sf, int is_gpos, struct alltabs *at)
  2925. {
  2926. OTLookup *otl;
  2927. struct lookup_subtable *sub;
  2928. int index, i, j;
  2929. FILE *final;
  2930. FILE *lfile = tmpfile ();
  2931. OTLookup **sizeordered;
  2932. OTLookup *all = is_gpos ? sf->gpos_lookups : sf->gsub_lookups;
  2933. char *buffer;
  2934. int len;
  2935. index = 0;
  2936. for (otl = all; otl != NULL; otl = otl->next)
  2937. {
  2938. if (otl->unused || otl->only_jstf || otl->temporary_kern)
  2939. otl->lookup_index = -1;
  2940. else
  2941. otl->lookup_index = index++;
  2942. }
  2943. for (otl = all; otl != NULL; otl = otl->next)
  2944. {
  2945. if (otl->lookup_index != -1)
  2946. {
  2947. otf_dumpALookup (lfile, otl, sf, at);
  2948. }
  2949. }
  2950. if (is_gpos)
  2951. AnchorGuessContext (sf, at);
  2952. /* We don't need to reorder short files */
  2953. if (ftell (lfile) < 65536)
  2954. return lfile;
  2955. /* Order the lookups so that the smallest ones come first */
  2956. /* thus we are less likely to need extension tables */
  2957. /* I think it's better to order the entire lookup rather than ordering the */
  2958. /* subtables -- since the extension subtable would be required for all */
  2959. /* subtables in the lookup, so might as well keep them all together */
  2960. sizeordered = xmalloc (index * sizeof (OTLookup *));
  2961. for (otl = is_gpos ? sf->gpos_lookups : sf->gsub_lookups; otl != NULL;
  2962. otl = otl->next)
  2963. if (otl->lookup_index != -1)
  2964. sizeordered[otl->lookup_index] = otl;
  2965. qsort (sizeordered, index, sizeof (OTLookup *), lookup_size_cmp);
  2966. final = tmpfile ();
  2967. buffer = xmalloc (32768);
  2968. for (i = 0; i < index; ++i)
  2969. {
  2970. uint32_t diff;
  2971. otl = sizeordered[i];
  2972. fseek (lfile, otl->lookup_offset, SEEK_SET);
  2973. diff = ftell (final) - otl->lookup_offset;
  2974. otl->lookup_offset = ftell (final);
  2975. len = otl->lookup_length;
  2976. while (len >= 32768)
  2977. {
  2978. int done = fread (buffer, 1, 32768, lfile);
  2979. if (done == 0) /* fread returns 0 on error, not EOF */
  2980. break;
  2981. fwrite (buffer, 1, done, final);
  2982. len -= done;
  2983. }
  2984. if (len > 0 && len <= 32768)
  2985. {
  2986. int done = fread (buffer, 1, len, lfile);
  2987. if (done == 0)
  2988. break;
  2989. fwrite (buffer, 1, done, final);
  2990. }
  2991. for (sub = otl->subtables; sub != NULL; sub = sub->next)
  2992. {
  2993. if (!sub->unused)
  2994. {
  2995. sub->subtable_offset += diff;
  2996. if (sub->extra_subtables != NULL)
  2997. {
  2998. for (j = 0; sub->extra_subtables[j] != -1; ++j)
  2999. sub->extra_subtables[j] += diff;
  3000. }
  3001. }
  3002. }
  3003. }
  3004. free (buffer);
  3005. free (sizeordered);
  3006. fclose (lfile);
  3007. return final;
  3008. }
  3009. struct feat_lookups
  3010. {
  3011. uint32_t tag;
  3012. int lcnt;
  3013. OTLookup **lookups;
  3014. int feature_id; /* Initially consecutive, but may be rearranged by sorting */
  3015. uint32_t name_param_ptr;
  3016. };
  3017. struct langsys
  3018. {
  3019. uint32_t lang;
  3020. int fc;
  3021. int *feature_id;
  3022. int same_as;
  3023. int32_t offset;
  3024. };
  3025. struct scriptset
  3026. {
  3027. uint32_t script;
  3028. int lc;
  3029. struct langsys *langsys;
  3030. };
  3031. struct ginfo
  3032. {
  3033. int fmax, fcnt;
  3034. struct feat_lookups *feat_lookups;
  3035. int sc;
  3036. struct scriptset *scripts;
  3037. };
  3038. static int
  3039. FindOrMakeNewFeatureLookup (struct ginfo *ginfo, OTLookup **lookups,
  3040. uint32_t tag)
  3041. {
  3042. int i, j;
  3043. for (i = 0; i < ginfo->fcnt; ++i)
  3044. {
  3045. if (ginfo->feat_lookups[i].tag != tag)
  3046. continue;
  3047. if (lookups == NULL && ginfo->feat_lookups[i].lookups == NULL) /* 'size' feature */
  3048. return i;
  3049. if (lookups == NULL || ginfo->feat_lookups[i].lookups == NULL)
  3050. continue;
  3051. for (j = 0;
  3052. lookups[j] != NULL && ginfo->feat_lookups[i].lookups[j] != NULL; ++j)
  3053. if (ginfo->feat_lookups[i].lookups[j] != lookups[j])
  3054. break;
  3055. if (ginfo->feat_lookups[i].lookups[j] == lookups[j])
  3056. {
  3057. free (lookups);
  3058. return i;
  3059. }
  3060. }
  3061. if (ginfo->fcnt >= ginfo->fmax)
  3062. ginfo->feat_lookups =
  3063. xrealloc (ginfo->feat_lookups,
  3064. (ginfo->fmax += 20) * sizeof (struct feat_lookups));
  3065. ginfo->feat_lookups[i].feature_id = i;
  3066. ginfo->feat_lookups[i].tag = tag;
  3067. ginfo->feat_lookups[i].lookups = lookups;
  3068. j = 0;
  3069. if (lookups != NULL)
  3070. for (; lookups[j] != NULL; ++j);
  3071. ginfo->feat_lookups[i].lcnt = j;
  3072. ++ginfo->fcnt;
  3073. return i;
  3074. }
  3075. static int
  3076. feat_alphabetize (const void *_fl1, const void *_fl2)
  3077. {
  3078. const struct feat_lookups *fl1 = _fl1, *fl2 = _fl2;
  3079. if (fl1->tag < fl2->tag)
  3080. return -1;
  3081. if (fl1->tag > fl2->tag)
  3082. return 1;
  3083. return 0;
  3084. }
  3085. static int
  3086. numeric_order (const void *_i1, const void *_i2)
  3087. {
  3088. int i1 = *(const int *) _i1, i2 = *(const int *) _i2;
  3089. if (i1 < i2)
  3090. return -1;
  3091. if (i1 > i2)
  3092. return 1;
  3093. return 0;
  3094. }
  3095. static int
  3096. LangSysMatch (struct scriptset *s, int ils1, int ils2)
  3097. {
  3098. struct langsys *ls1 = &s->langsys[ils1], *ls2 = &s->langsys[ils2];
  3099. int i;
  3100. if (ls1->fc != ls2->fc)
  3101. return false;
  3102. for (i = 0; i < ls1->fc; ++i)
  3103. if (ls1->feature_id[i] != ls2->feature_id[i])
  3104. return false;
  3105. return true;
  3106. }
  3107. static void
  3108. FindFeatures (SplineFont *sf, int is_gpos, struct ginfo *ginfo)
  3109. {
  3110. uint32_t *scripts, *langs, *features;
  3111. OTLookup **lookups;
  3112. int sc, lc, fc, j;
  3113. memset (ginfo, 0, sizeof (struct ginfo));
  3114. scripts = SFScriptsInLookups (sf, is_gpos);
  3115. if (scripts == NULL) /* All lookups unused */
  3116. return;
  3117. for (sc = 0; scripts[sc] != 0; ++sc);
  3118. ginfo->scripts = xmalloc (sc * sizeof (struct scriptset));
  3119. ginfo->sc = sc;
  3120. for (sc = 0; scripts[sc] != 0; ++sc)
  3121. {
  3122. langs = SFLangsInScript (sf, is_gpos, scripts[sc]);
  3123. for (lc = 0; langs[lc] != 0; ++lc);
  3124. ginfo->scripts[sc].script = scripts[sc];
  3125. ginfo->scripts[sc].lc = lc;
  3126. ginfo->scripts[sc].langsys = xmalloc (lc * sizeof (struct langsys));
  3127. for (lc = 0; langs[lc] != 0; ++lc)
  3128. {
  3129. features =
  3130. SFFeaturesInScriptLang (sf, is_gpos, scripts[sc], langs[lc]);
  3131. for (fc = 0; features[fc] != 0; ++fc);
  3132. ginfo->scripts[sc].langsys[lc].lang = langs[lc];
  3133. ginfo->scripts[sc].langsys[lc].fc = fc;
  3134. ginfo->scripts[sc].langsys[lc].feature_id =
  3135. xmalloc (fc * sizeof (int));
  3136. ginfo->scripts[sc].langsys[lc].same_as = -1;
  3137. for (fc = 0; features[fc] != 0; ++fc)
  3138. {
  3139. lookups =
  3140. SFLookupsInScriptLangFeature (sf, is_gpos, scripts[sc],
  3141. langs[lc], features[fc]);
  3142. ginfo->scripts[sc].langsys[lc].feature_id[fc] =
  3143. FindOrMakeNewFeatureLookup (ginfo, lookups, features[fc]);
  3144. /* lookups is freed or used by FindOrMakeNewFeatureLookup */
  3145. }
  3146. free (features);
  3147. }
  3148. free (langs);
  3149. }
  3150. free (scripts);
  3151. qsort (ginfo->feat_lookups, ginfo->fcnt, sizeof (struct feat_lookups),
  3152. feat_alphabetize);
  3153. /* Now we've disordered the features. Find each feature_id and turn it back */
  3154. /* into a feature number */
  3155. for (sc = 0; sc < ginfo->sc; ++sc)
  3156. {
  3157. for (lc = 0; lc < ginfo->scripts[sc].lc; ++lc)
  3158. {
  3159. int fcmax = ginfo->scripts[sc].langsys[lc].fc;
  3160. int *feature_id = ginfo->scripts[sc].langsys[lc].feature_id;
  3161. for (fc = 0; fc < fcmax; ++fc)
  3162. {
  3163. int id = feature_id[fc];
  3164. for (j = 0; j < ginfo->fcnt; ++j)
  3165. if (id == ginfo->feat_lookups[j].feature_id)
  3166. break;
  3167. feature_id[fc] = j;
  3168. }
  3169. qsort (feature_id, fcmax, sizeof (int), numeric_order);
  3170. }
  3171. /* See if there are langsys tables which use exactly the same features */
  3172. /* They can use the same entry in the file. This optimization seems */
  3173. /* to be required for Japanese vertical writing to work in Uniscribe. */
  3174. for (lc = 0; lc < ginfo->scripts[sc].lc; ++lc)
  3175. {
  3176. for (j = 0; j < lc; ++j)
  3177. if (LangSysMatch (&ginfo->scripts[sc], j, lc))
  3178. {
  3179. ginfo->scripts[sc].langsys[lc].same_as = j;
  3180. break;
  3181. }
  3182. }
  3183. }
  3184. }
  3185. static void
  3186. dump_script_table (FILE *g___, struct scriptset *ss, struct ginfo *ginfo)
  3187. {
  3188. int i, lcnt, dflt_lang = -1;
  3189. uint32_t base;
  3190. int j, req_index;
  3191. uint32_t offset;
  3192. /* Count the languages, and find default */
  3193. for (lcnt = 0; lcnt < ss->lc; ++lcnt)
  3194. if (ss->langsys[lcnt].lang == DEFAULT_LANG)
  3195. dflt_lang = lcnt;
  3196. if (dflt_lang != -1)
  3197. --lcnt;
  3198. base = ftell (g___);
  3199. putshort (g___, 0); /* fill in later, Default Lang Sys */
  3200. putshort (g___, lcnt);
  3201. for (i = 0; i < ss->lc; ++i)
  3202. if (i != dflt_lang)
  3203. {
  3204. putlong (g___, ss->langsys[i].lang); /* Language tag */
  3205. putshort (g___, 0); /* Fill in later, offset to langsys */
  3206. }
  3207. for (lcnt = 0; lcnt < ss->lc; ++lcnt)
  3208. {
  3209. if (ss->langsys[lcnt].same_as != -1)
  3210. offset = ss->langsys[ss->langsys[lcnt].same_as].offset;
  3211. else
  3212. {
  3213. offset = ftell (g___);
  3214. ss->langsys[lcnt].offset = offset;
  3215. }
  3216. fseek (g___, lcnt == dflt_lang ? base :
  3217. lcnt < dflt_lang || dflt_lang == -1 ? base + 4 + lcnt * 6 + 4 :
  3218. base + 4 + (lcnt - 1) * 6 + 4, SEEK_SET);
  3219. putshort (g___, offset - base);
  3220. fseek (g___, 0, SEEK_END);
  3221. if (ss->langsys[lcnt].same_as == -1)
  3222. {
  3223. req_index = -1;
  3224. for (j = 0; j < ss->langsys[lcnt].fc; ++j)
  3225. {
  3226. if (ginfo->feat_lookups[ss->langsys[lcnt].feature_id[j]].tag ==
  3227. REQUIRED_FEATURE)
  3228. {
  3229. req_index = ss->langsys[lcnt].feature_id[j];
  3230. break;
  3231. }
  3232. }
  3233. putshort (g___, 0); /* LookupOrder, always NULL */
  3234. putshort (g___, req_index); /* index of required feature, if any */
  3235. putshort (g___, ss->langsys[lcnt].fc - (req_index != -1));
  3236. /* count of non-required features */
  3237. for (j = 0; j < ss->langsys[lcnt].fc; ++j)
  3238. if (ss->langsys[lcnt].feature_id[j] != req_index)
  3239. putshort (g___, ss->langsys[lcnt].feature_id[j]);
  3240. }
  3241. }
  3242. }
  3243. static FILE *
  3244. g___FigureExtensionSubTables (OTLookup *all, int startoffset, int is_gpos)
  3245. {
  3246. OTLookup *otf;
  3247. struct lookup_subtable *sub;
  3248. int len, len2;
  3249. bool gotmore;
  3250. FILE *efile;
  3251. int i, offset, cnt;
  3252. if (all == NULL)
  3253. return NULL;
  3254. gotmore = true;
  3255. cnt = len = 0;
  3256. while (gotmore)
  3257. {
  3258. gotmore = false;
  3259. offset = startoffset + 8 * cnt;
  3260. for (otf = all; otf != NULL; otf = otf->next)
  3261. {
  3262. if (otf->lookup_index != -1)
  3263. {
  3264. if (otf->needs_extension)
  3265. continue;
  3266. for (sub = otf->subtables; sub != NULL; sub = sub->next)
  3267. {
  3268. if (sub->subtable_offset == -1)
  3269. continue;
  3270. if (sub->extra_subtables != NULL)
  3271. {
  3272. for (i = 0; sub->extra_subtables[i] != -1; ++i)
  3273. {
  3274. if (sub->extra_subtables[i] + offset > 65535)
  3275. break;
  3276. }
  3277. if (sub->extra_subtables[i] != -1)
  3278. break;
  3279. }
  3280. else if (sub->subtable_offset + offset > 65535)
  3281. break;
  3282. }
  3283. if (sub != NULL)
  3284. {
  3285. otf->needs_extension = true;
  3286. gotmore = true;
  3287. len += 8 * otf->subcnt;
  3288. ++cnt;
  3289. }
  3290. offset -= 6 + 2 * otf->subcnt;
  3291. }
  3292. }
  3293. }
  3294. if (cnt == 0) /* No offset overflows */
  3295. return NULL;
  3296. /* Now we've worked out which lookups need extension tables and marked them */
  3297. /* Generate the extension tables, and update the offsets to reflect the size */
  3298. /* of the extensions */
  3299. efile = tmpfile ();
  3300. len2 = 0;
  3301. for (otf = all; otf != NULL; otf = otf->next)
  3302. {
  3303. if (otf->lookup_index != -1)
  3304. {
  3305. for (sub = otf->subtables; sub != NULL; sub = sub->next)
  3306. {
  3307. if (sub->subtable_offset == -1)
  3308. continue;
  3309. if (sub->extra_subtables != NULL)
  3310. {
  3311. for (i = 0; sub->extra_subtables[i] != -1; ++i)
  3312. {
  3313. sub->extra_subtables[i] += len;
  3314. if (otf->needs_extension)
  3315. {
  3316. int off = ftell (efile);
  3317. putshort (efile, 1); /* exten subtable format (there's only one) */
  3318. putshort (efile, otf->lookup_type & 0xff);
  3319. putlong (efile, sub->extra_subtables[i] - len2);
  3320. sub->extra_subtables[i] = off;
  3321. len2 += 8;
  3322. }
  3323. }
  3324. }
  3325. else
  3326. {
  3327. sub->subtable_offset += len;
  3328. if (otf->needs_extension)
  3329. {
  3330. int off = ftell (efile);
  3331. putshort (efile, 1); /* exten subtable format (there's only one) */
  3332. putshort (efile, otf->lookup_type & 0xff);
  3333. putlong (efile, sub->subtable_offset - len2);
  3334. sub->subtable_offset = off;
  3335. len2 += 8;
  3336. }
  3337. }
  3338. }
  3339. }
  3340. }
  3341. return efile;
  3342. }
  3343. struct otffeatname *
  3344. findotffeatname (uint32_t tag, SplineFont *sf)
  3345. {
  3346. struct otffeatname *fn;
  3347. for (fn = sf->feat_names; fn != NULL && fn->tag != tag; fn = fn->next);
  3348. return fn;
  3349. }
  3350. static FILE *
  3351. dumpg___info (struct alltabs *at, SplineFont *sf, int is_gpos)
  3352. {
  3353. /* Dump out either a gpos or a gsub table. gpos handles kerns, gsub ligs */
  3354. /* we assume that SFFindUnusedLookups has been called */
  3355. FILE *lfile, *g___, *efile;
  3356. uint32_t lookup_list_table_start, feature_list_table_start, here,
  3357. scripts_start_offset;
  3358. struct ginfo ginfo;
  3359. int32_t size_params_loc, size_params_ptr;
  3360. int i, j, cnt, scnt, offset;
  3361. OTLookup *otf, *all;
  3362. struct lookup_subtable *sub;
  3363. char *buf;
  3364. struct otffeatname *fn;
  3365. for (fn = sf->feat_names; fn != NULL; fn = fn->next)
  3366. fn->nid = 0;
  3367. FindFeatures (sf, is_gpos, &ginfo);
  3368. if (ginfo.sc == 0)
  3369. return NULL;
  3370. lfile = G___figureLookups (sf, is_gpos, at);
  3371. if (ginfo.sc == 0 && ftell (lfile) == 0)
  3372. {
  3373. /* ftell(lfile)==0 => There are no lookups for this table */
  3374. /* ginfo.sc==0 => There are no scripts. */
  3375. /* If both are true then we don't need to output the table */
  3376. /* It is perfectly possible to have lookups without scripts */
  3377. /* (if some other table refered to them -- we don't currently */
  3378. /* support this, but we might some day). */
  3379. /* It is also possible to have scripts without lookups (to get */
  3380. /* around a bug in Uniscribe which only processes some scripts */
  3381. /* if both GPOS and GSUB entries are present. So we share scripts */
  3382. /* between the two tables */
  3383. fclose (lfile);
  3384. /* if ginfo.sc==0 then there will be nothing to free in the ginfo struct */
  3385. return NULL;
  3386. }
  3387. g___ = tmpfile ();
  3388. putlong (g___, 0x10000); /* version number */
  3389. putshort (g___, 10); /* offset to script table */
  3390. putshort (g___, 0); /* offset to features. Come back for this */
  3391. putshort (g___, 0); /* offset to lookups. Come back for this */
  3392. /* Now the scripts */
  3393. scripts_start_offset = ftell (g___);
  3394. putshort (g___, ginfo.sc);
  3395. for (i = 0; i < ginfo.sc; ++i)
  3396. {
  3397. putlong (g___, ginfo.scripts[i].script);
  3398. putshort (g___, 0); /* fix up later */
  3399. }
  3400. /* Ok, that was the script_list_table which gives each script an offset */
  3401. /* Now for each script we provide a Script table which contains an */
  3402. /* offset to a bunch of features for the default language, and a */
  3403. /* a more complex situation for non-default languages. */
  3404. offset = 2 + 4; /* To the script pointer at the start of table */
  3405. for (i = 0; i < ginfo.sc; ++i)
  3406. {
  3407. here = ftell (g___);
  3408. fseek (g___, scripts_start_offset + offset, SEEK_SET);
  3409. putshort (g___, here - scripts_start_offset);
  3410. offset += 6;
  3411. fseek (g___, here, SEEK_SET);
  3412. dump_script_table (g___, &ginfo.scripts[i], &ginfo);
  3413. }
  3414. /* And that should finish all the scripts/languages */
  3415. /* so free the ginfo script/lang data */
  3416. for (i = 0; i < ginfo.sc; ++i)
  3417. {
  3418. for (j = 0; j < ginfo.scripts[i].lc; ++j)
  3419. {
  3420. free (ginfo.scripts[i].langsys[j].feature_id);
  3421. }
  3422. free (ginfo.scripts[i].langsys);
  3423. }
  3424. free (ginfo.scripts);
  3425. /* Now the features */
  3426. feature_list_table_start = ftell (g___);
  3427. fseek (g___, 6, SEEK_SET);
  3428. putshort (g___, feature_list_table_start);
  3429. fseek (g___, 0, SEEK_END);
  3430. putshort (g___, ginfo.fcnt); /* Number of features */
  3431. offset = 2 + 6 * ginfo.fcnt; /* Offset to start of first feature table from beginning of feature_list */
  3432. for (i = 0; i < ginfo.fcnt; ++i)
  3433. {
  3434. putlong (g___, ginfo.feat_lookups[i].tag);
  3435. putshort (g___, offset);
  3436. offset += 4 + 2 * ginfo.feat_lookups[i].lcnt;
  3437. }
  3438. /* for each feature, one feature table */
  3439. size_params_ptr = 0;
  3440. for (i = 0; i < ginfo.fcnt; ++i)
  3441. {
  3442. ginfo.feat_lookups[i].name_param_ptr = 0;
  3443. if (ginfo.feat_lookups[i].tag == CHR ('s', 'i', 'z', 'e'))
  3444. size_params_ptr = ftell (g___);
  3445. else if (ginfo.feat_lookups[i].tag >= CHR ('s', 's', '0', '1')
  3446. && ginfo.feat_lookups[i].tag <= CHR ('s', 's', '2', '0'))
  3447. ginfo.feat_lookups[i].name_param_ptr = ftell (g___);
  3448. putshort (g___, 0); /* No feature params (we'll come back for 'size') */
  3449. putshort (g___, ginfo.feat_lookups[i].lcnt); /* this many lookups */
  3450. for (j = 0; j < ginfo.feat_lookups[i].lcnt; ++j)
  3451. putshort (g___, ginfo.feat_lookups[i].lookups[j]->lookup_index);
  3452. /* index of each lookup */
  3453. }
  3454. if (size_params_ptr != 0)
  3455. {
  3456. size_params_loc = ftell (g___);
  3457. fseek (g___, size_params_ptr, SEEK_SET);
  3458. putshort (g___, size_params_loc - size_params_ptr);
  3459. fseek (g___, size_params_loc, SEEK_SET);
  3460. putshort (g___, sf->design_size);
  3461. if (sf->fontstyle_id != 0 || sf->fontstyle_name != NULL)
  3462. {
  3463. putshort (g___, sf->fontstyle_id);
  3464. at->fontstyle_name_strid = at->next_strid++;
  3465. putshort (g___, at->fontstyle_name_strid);
  3466. }
  3467. else
  3468. {
  3469. putshort (g___, 0);
  3470. putshort (g___, 0);
  3471. }
  3472. putshort (g___, sf->design_range_bottom);
  3473. putshort (g___, sf->design_range_top);
  3474. }
  3475. for (i = 0; i < ginfo.fcnt; ++i)
  3476. {
  3477. if (ginfo.feat_lookups[i].name_param_ptr != 0 &&
  3478. (fn = findotffeatname (ginfo.feat_lookups[i].tag, sf)) != NULL)
  3479. {
  3480. if (fn->nid == 0)
  3481. fn->nid = at->next_strid++;
  3482. uint32_t name_param_loc = ftell (g___);
  3483. fseek (g___, ginfo.feat_lookups[i].name_param_ptr, SEEK_SET);
  3484. putshort (g___,
  3485. name_param_loc - ginfo.feat_lookups[i].name_param_ptr);
  3486. fseek (g___, name_param_loc, SEEK_SET);
  3487. putshort (g___, 0); /* Minor version number */
  3488. putshort (g___, fn->nid);
  3489. }
  3490. }
  3491. /* And that should finish all the features */
  3492. /* so free the ginfo feature data */
  3493. for (i = 0; i < ginfo.fcnt; ++i)
  3494. free (ginfo.feat_lookups[i].lookups);
  3495. free (ginfo.feat_lookups);
  3496. /* Now the lookups */
  3497. all = is_gpos ? sf->gpos_lookups : sf->gsub_lookups;
  3498. for (cnt = 0, otf = all; otf != NULL; otf = otf->next)
  3499. {
  3500. if (otf->lookup_index != -1)
  3501. ++cnt;
  3502. }
  3503. lookup_list_table_start = ftell (g___);
  3504. fseek (g___, 8, SEEK_SET);
  3505. putshort (g___, lookup_list_table_start);
  3506. fseek (g___, 0, SEEK_END);
  3507. putshort (g___, cnt);
  3508. offset = 2 + 2 * cnt; /* Offset to start of first lookup table from beginning of lookup list */
  3509. for (otf = all; otf != NULL; otf = otf->next)
  3510. if (otf->lookup_index != -1)
  3511. {
  3512. putshort (g___, offset);
  3513. for (scnt = 0, sub = otf->subtables; sub != NULL; sub = sub->next)
  3514. {
  3515. if (sub->subtable_offset == -1)
  3516. continue;
  3517. else if (sub->extra_subtables != NULL)
  3518. {
  3519. for (i = 0; sub->extra_subtables[i] != -1; ++i)
  3520. ++scnt;
  3521. }
  3522. else
  3523. ++scnt;
  3524. }
  3525. otf->subcnt = scnt;
  3526. offset += 6 + 2 * scnt; /* 6 bytes header +2 per lookup */
  3527. if (otf->lookup_flags & pst_usemarkfilteringset)
  3528. offset += 2; /* For mark filtering set, if used */
  3529. }
  3530. offset -= 2 + 2 * cnt;
  3531. /* now the lookup tables */
  3532. /* do we need any extension sub-tables? */
  3533. efile = g___FigureExtensionSubTables (all, offset, is_gpos);
  3534. for (otf = all; otf != NULL; otf = otf->next)
  3535. if (otf->lookup_index != -1)
  3536. {
  3537. putshort (g___, !otf->needs_extension ? (otf->lookup_type & 0xff)
  3538. : is_gpos ? 9 : 7);
  3539. putshort (g___, (otf->lookup_flags & 0xffff));
  3540. putshort (g___, otf->subcnt);
  3541. for (sub = otf->subtables; sub != NULL; sub = sub->next)
  3542. {
  3543. if (sub->subtable_offset == -1)
  3544. continue;
  3545. else if (sub->extra_subtables != NULL)
  3546. {
  3547. for (i = 0; sub->extra_subtables[i] != -1; ++i)
  3548. putshort (g___, offset + sub->extra_subtables[i]);
  3549. }
  3550. else
  3551. putshort (g___, offset + sub->subtable_offset);
  3552. /* Offset to lookup data which is in the temp file */
  3553. /* we keep adjusting offset so it reflects the distance between */
  3554. /* here and the place where the temp file will start, and then */
  3555. /* we need to skip l->offset bytes in the temp file */
  3556. /* If it's a big GPOS/SUB table we may also need some extension */
  3557. /* pointers, but FigureExtension will adjust for that */
  3558. }
  3559. offset -= 6 + 2 * otf->subcnt;
  3560. if (otf->lookup_flags & pst_usemarkfilteringset)
  3561. {
  3562. putshort (g___, otf->lookup_flags >> 16);
  3563. offset -= 2;
  3564. }
  3565. }
  3566. buf = xmalloc (8096);
  3567. if (efile != NULL)
  3568. {
  3569. rewind (efile);
  3570. while ((i = fread (buf, 1, 8096, efile)) > 0)
  3571. fwrite (buf, 1, i, g___);
  3572. fclose (efile);
  3573. }
  3574. rewind (lfile);
  3575. while ((i = fread (buf, 1, 8096, lfile)) > 0)
  3576. fwrite (buf, 1, i, g___);
  3577. fclose (lfile);
  3578. free (buf);
  3579. for (otf = all; otf != NULL; otf = otf->next)
  3580. if (otf->lookup_index != -1)
  3581. {
  3582. for (sub = otf->subtables; sub != NULL; sub = sub->next)
  3583. {
  3584. free (sub->extra_subtables);
  3585. sub->extra_subtables = NULL;
  3586. }
  3587. otf->needs_extension = false;
  3588. }
  3589. return g___;
  3590. }
  3591. void
  3592. otf_dumpgpos (struct alltabs *at, SplineFont *sf)
  3593. {
  3594. AnchorClass *ac;
  3595. for (ac = sf->anchor; ac != NULL; ac = ac->next)
  3596. ac->processed = false;
  3597. at->gpos = dumpg___info (at, sf, true);
  3598. if (at->gpos != NULL)
  3599. {
  3600. at->gposlen = ftell (at->gpos);
  3601. if (at->gposlen & 1)
  3602. putc ('\0', at->gpos);
  3603. if ((at->gposlen + 1) & 2)
  3604. putshort (at->gpos, 0);
  3605. }
  3606. }
  3607. void
  3608. otf_dumpgsub (struct alltabs *at, SplineFont *sf)
  3609. {
  3610. /* substitutions such as: Ligatures, cjk vertical rotation replacement, */
  3611. /* arabic forms, small caps, ... */
  3612. SFLigaturePrepare (sf);
  3613. at->gsub = dumpg___info (at, sf, false);
  3614. if (at->gsub != NULL)
  3615. {
  3616. at->gsublen = ftell (at->gsub);
  3617. if (at->gsublen & 1)
  3618. putc ('\0', at->gsub);
  3619. if ((at->gsublen + 1) & 2)
  3620. putshort (at->gsub, 0);
  3621. }
  3622. SFLigatureCleanup (sf);
  3623. }
  3624. int
  3625. LigCaretCnt (SplineChar *sc)
  3626. {
  3627. PST *pst;
  3628. int j, cnt;
  3629. for (pst = sc->possub; pst != NULL; pst = pst->next)
  3630. {
  3631. if (pst->type == pst_lcaret)
  3632. {
  3633. if (sc->lig_caret_cnt_fixed)
  3634. return pst->u.lcaret.cnt;
  3635. else
  3636. {
  3637. /* only output non-zero carets */
  3638. cnt = 0;
  3639. for (j = pst->u.lcaret.cnt - 1; j >= 0; --j)
  3640. if (pst->u.lcaret.carets[j] != 0)
  3641. ++cnt;
  3642. return cnt;
  3643. }
  3644. }
  3645. }
  3646. return 0;
  3647. }
  3648. static void
  3649. DumpLigCarets (FILE *gdef, SplineChar *sc)
  3650. {
  3651. PST *pst;
  3652. int i, j, offset, cnt;
  3653. for (pst = sc->possub; pst != NULL; pst = pst->next)
  3654. {
  3655. if (pst->type == pst_lcaret)
  3656. break;
  3657. }
  3658. if (pst == NULL)
  3659. return;
  3660. cnt = LigCaretCnt (sc);
  3661. if (cnt == 0)
  3662. return;
  3663. for (i = 0; i < pst->u.lcaret.cnt - 1; ++i)
  3664. for (j = i + 1; j < pst->u.lcaret.cnt; ++j)
  3665. if (pst->u.lcaret.carets[i] > pst->u.lcaret.carets[j])
  3666. {
  3667. int16_t temp = pst->u.lcaret.carets[i];
  3668. pst->u.lcaret.carets[i] = pst->u.lcaret.carets[j];
  3669. pst->u.lcaret.carets[j] = temp;
  3670. }
  3671. putshort (gdef, cnt); /* this many carets */
  3672. offset = sizeof (uint16_t) + sizeof (uint16_t) * cnt;
  3673. for (i = 0; i < cnt; ++i)
  3674. {
  3675. putshort (gdef, offset);
  3676. offset += 4;
  3677. }
  3678. for (i = 0; i < pst->u.lcaret.cnt; ++i)
  3679. {
  3680. if (sc->lig_caret_cnt_fixed || pst->u.lcaret.carets[i] != 0)
  3681. {
  3682. putshort (gdef, 1); /* Format 1 */
  3683. putshort (gdef, pst->u.lcaret.carets[i]);
  3684. }
  3685. }
  3686. }
  3687. static int
  3688. glyphnameinlist (char *haystack, char *name)
  3689. {
  3690. char *start, *pt;
  3691. int ch, match, slen = strlen (name);
  3692. for (pt = haystack;;)
  3693. {
  3694. while (*pt == ' ')
  3695. ++pt;
  3696. if (*pt == '\0')
  3697. return false;
  3698. start = pt;
  3699. while (*pt != ' ' && *pt != '\0')
  3700. ++pt;
  3701. if (pt - start == slen)
  3702. {
  3703. ch = *pt;
  3704. *pt = '\0';
  3705. match = strcmp (start, name);
  3706. *pt = ch;
  3707. if (match == 0)
  3708. return true;
  3709. }
  3710. }
  3711. }
  3712. static int
  3713. ReferencedByGSUB (SplineChar *sc)
  3714. {
  3715. PST *pst;
  3716. SplineFont *sf = sc->parent;
  3717. int gid;
  3718. SplineChar *testsc;
  3719. char *name = sc->name;
  3720. /* If it is itself a ligature it will be referenced by GSUB */
  3721. /* (because we store ligatures on the glyph generated) */
  3722. for (pst = sc->possub; pst != NULL; pst = pst->next)
  3723. if (pst->type == pst_ligature)
  3724. return true;
  3725. for (gid = 0; gid < sf->glyphcnt; ++gid)
  3726. if ((testsc = sf->glyphs[gid]) != NULL)
  3727. {
  3728. for (pst = testsc->possub; pst != NULL; pst = pst->next)
  3729. {
  3730. if (pst->type == pst_substitution || pst->type == pst_alternate ||
  3731. pst->type == pst_multiple)
  3732. {
  3733. if (glyphnameinlist (pst->u.mult.components, name))
  3734. return true;
  3735. }
  3736. }
  3737. }
  3738. return false;
  3739. }
  3740. int
  3741. gdefclass (SplineChar *sc)
  3742. {
  3743. PST *pst;
  3744. AnchorPoint *ap;
  3745. if (sc->glyph_class != 0)
  3746. return sc->glyph_class - 1;
  3747. if (strcmp (sc->name, ".notdef") == 0)
  3748. return 0;
  3749. /* It isn't clear to me what should be done if a glyph is both a ligature */
  3750. /* and a mark (There are some greek accent ligatures, it is probably more */
  3751. /* important that they be indicated as marks). Here I chose mark rather */
  3752. /* than ligature as the mark class is far more likely to be used */
  3753. ap = sc->anchor;
  3754. while (ap != NULL && (ap->type == at_centry || ap->type == at_cexit))
  3755. ap = ap->next;
  3756. if (ap != NULL && (ap->type == at_mark || ap->type == at_basemark))
  3757. return 3;
  3758. for (pst = sc->possub; pst != NULL; pst = pst->next)
  3759. {
  3760. if (pst->type == pst_ligature)
  3761. return 2; /* Ligature */
  3762. }
  3763. /* I not quite sure what a componant glyph is. Probably something */
  3764. /* that is not in the cmap table and is referenced in other glyphs */
  3765. /* (I've never seen it used by others) */
  3766. /* (Note: No glyph in a CID font can be components as all CIDs mean */
  3767. /* something) (I think) */
  3768. if (sc->unicodeenc == -1 && sc->dependents != NULL &&
  3769. sc->parent->cidmaster != NULL && !ReferencedByGSUB (sc))
  3770. return 4;
  3771. else
  3772. return 1;
  3773. }
  3774. void
  3775. otf_dumpgdef (struct alltabs *at, SplineFont *sf)
  3776. {
  3777. /* In spite of what the open type docs say, this table does appear to be */
  3778. /* required (at least the glyph class def table) if we do mark to base */
  3779. /* positioning */
  3780. /* I was wondering at the apperant contradiction: something can be both a */
  3781. /* base glyph and a ligature component, but it appears that the component */
  3782. /* class is unused and everything is a base unless it is a ligature or */
  3783. /* mark */
  3784. /* All my example fonts ignore the attachment list subtable and the mark */
  3785. /* attach class def subtable, so I shall too */
  3786. /* Ah. Some indic fonts need the mark attach class subtable for greater */
  3787. /* control of lookup flags */
  3788. /* All my example fonts contain a ligature caret list subtable, which is */
  3789. /* empty. Odd, but perhaps important */
  3790. int i, j, k, lcnt, needsclass;
  3791. int pos, offset;
  3792. int cnt, start, last, lastval;
  3793. SplineChar **glyphs, *sc;
  3794. /* Don't look in the cidmaster if we are only dumping one subfont */
  3795. if (sf->cidmaster && sf->cidmaster->glyphs != NULL)
  3796. sf = sf->cidmaster;
  3797. else if (sf->mm != NULL)
  3798. sf = sf->mm->normal;
  3799. glyphs = NULL;
  3800. for (k = 0; k < 2; ++k)
  3801. {
  3802. lcnt = 0;
  3803. needsclass = false;
  3804. for (i = 0; i < at->gi.gcnt; ++i)
  3805. if (at->gi.bygid[i] != -1)
  3806. {
  3807. SplineChar *sc = sf->glyphs[at->gi.bygid[i]];
  3808. if (sc->glyph_class != 0 || gdefclass (sc) != 1)
  3809. needsclass = true;
  3810. if (LigCaretCnt (sc) != 0)
  3811. {
  3812. if (glyphs != NULL)
  3813. glyphs[lcnt] = sc;
  3814. ++lcnt;
  3815. }
  3816. }
  3817. if (lcnt == 0)
  3818. break;
  3819. if (glyphs != NULL)
  3820. break;
  3821. glyphs = xmalloc ((lcnt + 1) * sizeof (SplineChar *));
  3822. glyphs[lcnt] = NULL;
  3823. }
  3824. if (!needsclass && lcnt == 0 && sf->mark_class_cnt == 0
  3825. && sf->mark_set_cnt == 0)
  3826. return; /* No anchor positioning, no ligature carets */
  3827. at->gdef = tmpfile ();
  3828. if (sf->mark_set_cnt == 0)
  3829. putlong (at->gdef, 0x00010000); /* Version */
  3830. else
  3831. putlong (at->gdef, 0x00010002); /* Version with mark sets */
  3832. putshort (at->gdef, needsclass ? 14 : 0); /* glyph class defn table */
  3833. putshort (at->gdef, 0); /* attachment list table */
  3834. putshort (at->gdef, 0); /* ligature caret table (come back and fix up later) */
  3835. putshort (at->gdef, 0); /* mark attachment class table */
  3836. putshort (at->gdef, 0); /* mark attachment set table only meaningful if version is 0x10002, but doesn't hurt to output always */
  3837. /* Glyph class subtable */
  3838. if (needsclass)
  3839. {
  3840. /* Mark shouldn't conflict with anything */
  3841. /* Ligature is more important than Base */
  3842. /* Component is not used */
  3843. #if 1 /* ttx can't seem to support class format type 1 so let's output type 2 */
  3844. for (j = 0; j < 2; ++j)
  3845. {
  3846. cnt = 0;
  3847. for (i = 0; i < at->gi.gcnt; ++i)
  3848. if (at->gi.bygid[i] != -1)
  3849. {
  3850. sc = sf->glyphs[at->gi.bygid[i]];
  3851. if (sc != NULL && sc->ttf_glyph != -1)
  3852. {
  3853. lastval = gdefclass (sc);
  3854. start = last = i;
  3855. for (; i < at->gi.gcnt; ++i)
  3856. if (at->gi.bygid[i] != -1)
  3857. {
  3858. sc = sf->glyphs[at->gi.bygid[i]];
  3859. if (gdefclass (sc) != lastval)
  3860. break;
  3861. last = i;
  3862. }
  3863. --i;
  3864. if (lastval != 0)
  3865. {
  3866. if (j == 1)
  3867. {
  3868. putshort (at->gdef, start);
  3869. putshort (at->gdef, last);
  3870. putshort (at->gdef, lastval);
  3871. }
  3872. ++cnt;
  3873. }
  3874. }
  3875. }
  3876. if (j == 0)
  3877. {
  3878. putshort (at->gdef, 2); /* class format 2, range list by class */
  3879. putshort (at->gdef, cnt);
  3880. }
  3881. }
  3882. #else
  3883. putshort (at->gdef, 1); /* class format 1 complete list of glyphs */
  3884. putshort (at->gdef, 0); /* First glyph */
  3885. putshort (at->gdef, at->maxp.numGlyphs);
  3886. j = 0;
  3887. for (i = 0; i < at->gi.gcnt; ++i)
  3888. if (at->gi.bygid[i] != -1)
  3889. {
  3890. for (; j < i; ++j)
  3891. putshort (at->gdef, 1); /* Any hidden characters (like notdef) default to base */
  3892. putshort (at->gdef, gdefclass (sf->glyphs[at->gi.bygid[i]]));
  3893. ++j;
  3894. }
  3895. #endif
  3896. }
  3897. /* Ligature caret subtable. Always include this if we have a GDEF */
  3898. pos = ftell (at->gdef);
  3899. fseek (at->gdef, 8, SEEK_SET); /* location of lig caret table offset */
  3900. putshort (at->gdef, pos);
  3901. fseek (at->gdef, 0, SEEK_END);
  3902. if (lcnt == 0)
  3903. {
  3904. /* It always seems to be present, even if empty */
  3905. putshort (at->gdef, 4); /* Offset to (empty) coverage table */
  3906. putshort (at->gdef, 0); /* no ligatures */
  3907. putshort (at->gdef, 2); /* coverage table format 2 */
  3908. putshort (at->gdef, 0); /* no ranges in coverage table */
  3909. }
  3910. else
  3911. {
  3912. pos = ftell (at->gdef); /* coverage location */
  3913. putshort (at->gdef, 0); /* Offset to coverage table (fix up later) */
  3914. putshort (at->gdef, lcnt);
  3915. offset = 2 * lcnt + 4;
  3916. for (i = 0; i < lcnt; ++i)
  3917. {
  3918. putshort (at->gdef, offset);
  3919. offset += 2 + 6 * LigCaretCnt (glyphs[i]);
  3920. }
  3921. for (i = 0; i < lcnt; ++i)
  3922. DumpLigCarets (at->gdef, glyphs[i]);
  3923. offset = ftell (at->gdef);
  3924. fseek (at->gdef, pos, SEEK_SET);
  3925. putshort (at->gdef, offset - pos);
  3926. fseek (at->gdef, 0, SEEK_END);
  3927. dumpcoveragetable (at->gdef, glyphs);
  3928. }
  3929. /* Mark Attachment Class Subtable */
  3930. if (sf->mark_class_cnt > 0)
  3931. {
  3932. uint16_t *mclasses =
  3933. ClassesFromNames (sf, sf->mark_classes, sf->mark_class_cnt,
  3934. at->maxp.numGlyphs, NULL, false);
  3935. pos = ftell (at->gdef);
  3936. fseek (at->gdef, 10, SEEK_SET); /* location of mark attach table offset */
  3937. putshort (at->gdef, pos);
  3938. fseek (at->gdef, 0, SEEK_END);
  3939. DumpClass (at->gdef, mclasses, at->maxp.numGlyphs);
  3940. free (mclasses);
  3941. }
  3942. /* Mark Attachment Class Subtable */
  3943. if (sf->mark_set_cnt > 0)
  3944. {
  3945. pos = ftell (at->gdef);
  3946. fseek (at->gdef, 12, SEEK_SET); /* location of mark attach table offset */
  3947. putshort (at->gdef, pos);
  3948. fseek (at->gdef, 0, SEEK_END);
  3949. putshort (at->gdef, 1); /* Version number */
  3950. putshort (at->gdef, sf->mark_set_cnt);
  3951. for (i = 0; i < sf->mark_set_cnt; ++i)
  3952. putlong (at->gdef, 0);
  3953. for (i = 0; i < sf->mark_set_cnt; ++i)
  3954. {
  3955. int here = ftell (at->gdef);
  3956. fseek (at->gdef, pos + 4 + 4 * i, SEEK_SET);
  3957. putlong (at->gdef, here - pos);
  3958. fseek (at->gdef, 0, SEEK_END);
  3959. glyphs = OrderedGlyphsFromNames (sf, sf->mark_sets[i]);
  3960. dumpcoveragetable (at->gdef, glyphs);
  3961. free (glyphs);
  3962. }
  3963. }
  3964. at->gdeflen = ftell (at->gdef);
  3965. if (at->gdeflen & 1)
  3966. putc ('\0', at->gdef);
  3967. if ((at->gdeflen + 1) & 2)
  3968. putshort (at->gdef, 0);
  3969. }
  3970. /******************************************************************************/
  3971. /* ******************************* MATH Table ******************************* */
  3972. /* ********************** (Not strictly OpenType yet) *********************** */
  3973. /******************************************************************************/
  3974. enum math_bits
  3975. { mb_constants = 0x01, mb_italic = 0x02, mb_topaccent = 0x04,
  3976. mb_extended = 0x08, mb_mathkern = 0x10, mb_vertvariant = 0x20,
  3977. mb_horizvariant = 0x40,
  3978. mb_all = 0x7f,
  3979. mb_gi = (mb_italic | mb_topaccent | mb_extended | mb_mathkern),
  3980. mb_gv = (mb_vertvariant | mb_horizvariant)
  3981. };
  3982. static int
  3983. MathBits (struct alltabs *at, SplineFont *sf)
  3984. {
  3985. int i, gid, ret;
  3986. SplineChar *sc;
  3987. ret = sf->MATH ? mb_constants : 0;
  3988. for (i = 0; i < at->gi.gcnt; ++i)
  3989. {
  3990. if ((gid = at->gi.bygid[i]) != -1 && (sc = sf->glyphs[gid]) != NULL)
  3991. {
  3992. if (sc->italic_correction != TEX_UNDEF)
  3993. ret |= mb_italic;
  3994. if (sc->top_accent_horiz != TEX_UNDEF)
  3995. ret |= mb_topaccent;
  3996. if (sc->is_extended_shape)
  3997. ret |= mb_extended;
  3998. if (sc->mathkern != NULL)
  3999. ret |= mb_mathkern;
  4000. if (sc->vert_variants != NULL)
  4001. ret |= mb_vertvariant;
  4002. if (sc->horiz_variants != NULL)
  4003. ret |= mb_horizvariant;
  4004. if (ret == mb_all)
  4005. return mb_all;
  4006. }
  4007. }
  4008. return ret;
  4009. }
  4010. static void
  4011. ttf_math_dump_italic_top (FILE *mathf, struct alltabs *at, SplineFont *sf,
  4012. int is_italic)
  4013. {
  4014. int i, gid, len;
  4015. SplineChar *sc, **glyphs;
  4016. uint32_t coverage_pos, coverage_table;
  4017. uint32_t devtab_offset;
  4018. DeviceTable *devtab;
  4019. /* Figure out our glyph list (and count) */
  4020. for (i = len = 0; i < at->gi.gcnt; ++i)
  4021. if ((gid = at->gi.bygid[i]) != -1 && (sc = sf->glyphs[gid]) != NULL)
  4022. if ((is_italic && sc->italic_correction != TEX_UNDEF)
  4023. || (!is_italic && sc->top_accent_horiz != TEX_UNDEF))
  4024. ++len;
  4025. glyphs = xmalloc ((len + 1) * sizeof (SplineChar *));
  4026. for (i = len = 0; i < at->gi.gcnt; ++i)
  4027. if ((gid = at->gi.bygid[i]) != -1 && (sc = sf->glyphs[gid]) != NULL)
  4028. if ((is_italic && sc->italic_correction != TEX_UNDEF)
  4029. || (!is_italic && sc->top_accent_horiz != TEX_UNDEF))
  4030. glyphs[len++] = sc;
  4031. glyphs[len] = NULL;
  4032. coverage_pos = ftell (mathf);
  4033. putshort (mathf, 0); /* Coverage table, return to this */
  4034. putshort (mathf, len);
  4035. devtab_offset = 4 + 4 * len;
  4036. for (i = 0; i < len; ++i)
  4037. {
  4038. putshort (mathf,
  4039. is_italic ? glyphs[i]->italic_correction : glyphs[i]->
  4040. top_accent_horiz);
  4041. devtab =
  4042. is_italic ? glyphs[i]->italic_adjusts : glyphs[i]->top_accent_adjusts;
  4043. if (devtab != NULL)
  4044. {
  4045. putshort (mathf, devtab_offset);
  4046. devtab_offset += DevTabLen (devtab);
  4047. }
  4048. else
  4049. putshort (mathf, 0);
  4050. }
  4051. for (i = 0; i < len; ++i)
  4052. {
  4053. devtab =
  4054. is_italic ? glyphs[i]->italic_adjusts : glyphs[i]->top_accent_adjusts;
  4055. if (devtab != NULL)
  4056. dumpgposdevicetable (mathf, devtab);
  4057. }
  4058. if (devtab_offset != ftell (mathf) - coverage_pos)
  4059. IError
  4060. ("Actual end did not match expected end in %s table, expected=%d, actual=%d",
  4061. is_italic ? "italic" : "top accent", devtab_offset,
  4062. ftell (mathf) - coverage_pos);
  4063. coverage_table = ftell (mathf);
  4064. fseek (mathf, coverage_pos, SEEK_SET);
  4065. putshort (mathf, coverage_table - coverage_pos);
  4066. fseek (mathf, coverage_table, SEEK_SET);
  4067. dumpcoveragetable (mathf, glyphs);
  4068. free (glyphs);
  4069. }
  4070. static void
  4071. ttf_math_dump_extended (FILE *mathf, struct alltabs *at, SplineFont *sf)
  4072. {
  4073. int i, gid, len;
  4074. SplineChar *sc, **glyphs;
  4075. for (i = len = 0; i < at->gi.gcnt; ++i)
  4076. if ((gid = at->gi.bygid[i]) != -1 && (sc = sf->glyphs[gid]) != NULL)
  4077. if (sc->is_extended_shape)
  4078. ++len;
  4079. glyphs = xmalloc ((len + 1) * sizeof (SplineChar *));
  4080. for (i = len = 0; i < at->gi.gcnt; ++i)
  4081. if ((gid = at->gi.bygid[i]) != -1 && (sc = sf->glyphs[gid]) != NULL)
  4082. if (sc->is_extended_shape)
  4083. glyphs[len++] = sc;
  4084. glyphs[len] = NULL;
  4085. dumpcoveragetable (mathf, glyphs);
  4086. free (glyphs);
  4087. }
  4088. static int
  4089. mkv_len (struct mathkernvertex *mkv)
  4090. {
  4091. return 2 + 8 * mkv->cnt - 4;
  4092. }
  4093. static int
  4094. ttf_math_dump_mathkernvertex (FILE *mathf, struct mathkernvertex *mkv,
  4095. int devtab_pos)
  4096. {
  4097. int i;
  4098. uint32_t here = ftell (mathf);
  4099. putshort (mathf, mkv->cnt - 1);
  4100. for (i = 0; i < mkv->cnt - 1; ++i)
  4101. {
  4102. putshort (mathf, mkv->mkd[i].height);
  4103. if (mkv->mkd[i].height_adjusts != NULL)
  4104. {
  4105. putshort (mathf, devtab_pos - here);
  4106. devtab_pos += DevTabLen (mkv->mkd[i].height_adjusts);
  4107. }
  4108. else
  4109. putshort (mathf, 0);
  4110. }
  4111. for (i = 0; i < mkv->cnt; ++i)
  4112. {
  4113. putshort (mathf, mkv->mkd[i].kern);
  4114. if (mkv->mkd[i].kern_adjusts != NULL)
  4115. {
  4116. putshort (mathf, devtab_pos - here);
  4117. devtab_pos += DevTabLen (mkv->mkd[i].kern_adjusts);
  4118. }
  4119. else
  4120. putshort (mathf, 0);
  4121. }
  4122. return devtab_pos;
  4123. }
  4124. static void
  4125. ttf_math_dump_mathkerndevtab (FILE *mathf, struct mathkernvertex *mkv)
  4126. {
  4127. int i;
  4128. for (i = 0; i < mkv->cnt - 1; ++i)
  4129. if (mkv->mkd[i].height_adjusts != NULL)
  4130. dumpgposdevicetable (mathf, mkv->mkd[i].height_adjusts);
  4131. for (i = 0; i < mkv->cnt; ++i)
  4132. if (mkv->mkd[i].kern_adjusts != NULL)
  4133. dumpgposdevicetable (mathf, mkv->mkd[i].kern_adjusts);
  4134. }
  4135. static void
  4136. ttf_math_dump_mathkern (FILE *mathf, struct alltabs *at, SplineFont *sf)
  4137. {
  4138. int i, gid, len;
  4139. SplineChar *sc, **glyphs;
  4140. uint32_t coverage_pos, coverage_table, kr_pos, midpos2;
  4141. /* Figure out our glyph list (and count) */
  4142. for (i = len = 0; i < at->gi.gcnt; ++i)
  4143. if ((gid = at->gi.bygid[i]) != -1 && (sc = sf->glyphs[gid]) != NULL)
  4144. if (sc->mathkern != NULL)
  4145. ++len;
  4146. glyphs = xmalloc ((len + 1) * sizeof (SplineChar *));
  4147. for (i = len = 0; i < at->gi.gcnt; ++i)
  4148. if ((gid = at->gi.bygid[i]) != -1 && (sc = sf->glyphs[gid]) != NULL)
  4149. if (sc->mathkern != NULL)
  4150. glyphs[len++] = sc;
  4151. glyphs[len] = NULL;
  4152. coverage_pos = ftell (mathf);
  4153. putshort (mathf, 0); /* Coverage table, return to this */
  4154. putshort (mathf, len);
  4155. kr_pos = coverage_pos + 4 + 8 * len;
  4156. for (i = 0; i < len; ++i)
  4157. {
  4158. struct mathkern *mk = glyphs[i]->mathkern;
  4159. if (mk->top_right.cnt == 0)
  4160. putshort (mathf, 0);
  4161. else
  4162. {
  4163. putshort (mathf, kr_pos - coverage_pos);
  4164. kr_pos += mkv_len (&mk->top_right);
  4165. }
  4166. if (mk->top_left.cnt == 0)
  4167. putshort (mathf, 0);
  4168. else
  4169. {
  4170. putshort (mathf, kr_pos - coverage_pos);
  4171. kr_pos += mkv_len (&mk->top_left);
  4172. }
  4173. if (mk->bottom_right.cnt == 0)
  4174. putshort (mathf, 0);
  4175. else
  4176. {
  4177. putshort (mathf, kr_pos - coverage_pos);
  4178. kr_pos += mkv_len (&mk->bottom_right);
  4179. }
  4180. if (mk->bottom_left.cnt == 0)
  4181. putshort (mathf, 0);
  4182. else
  4183. {
  4184. putshort (mathf, kr_pos - coverage_pos);
  4185. kr_pos += mkv_len (&mk->bottom_left);
  4186. }
  4187. }
  4188. if (ftell (mathf) != coverage_pos + 4 + 8 * len)
  4189. IError
  4190. ("Actual midpoint1 did not match expected midpoint1 in mathkern table, expected=%d, actual=%d",
  4191. coverage_pos + 4 + 8 * len, ftell (mathf));
  4192. midpos2 = kr_pos;
  4193. for (i = 0; i < len; ++i)
  4194. {
  4195. struct mathkern *mk = glyphs[i]->mathkern;
  4196. if (mk->top_right.cnt != 0)
  4197. kr_pos = ttf_math_dump_mathkernvertex (mathf, &mk->top_right, kr_pos);
  4198. if (mk->top_left.cnt != 0)
  4199. kr_pos = ttf_math_dump_mathkernvertex (mathf, &mk->top_left, kr_pos);
  4200. if (mk->bottom_right.cnt != 0)
  4201. kr_pos =
  4202. ttf_math_dump_mathkernvertex (mathf, &mk->bottom_right, kr_pos);
  4203. if (mk->bottom_left.cnt != 0)
  4204. kr_pos = ttf_math_dump_mathkernvertex (mathf, &mk->bottom_left, kr_pos);
  4205. }
  4206. if (ftell (mathf) != midpos2)
  4207. IError
  4208. ("Actual midpoint2 did not match expected midpoint2 in mathkern table, expected=%d, actual=%d",
  4209. midpos2, ftell (mathf));
  4210. for (i = 0; i < len; ++i)
  4211. {
  4212. struct mathkern *mk = glyphs[i]->mathkern;
  4213. if (mk->top_right.cnt != 0)
  4214. ttf_math_dump_mathkerndevtab (mathf, &mk->top_right);
  4215. if (mk->top_left.cnt != 0)
  4216. ttf_math_dump_mathkerndevtab (mathf, &mk->top_left);
  4217. if (mk->bottom_right.cnt != 0)
  4218. ttf_math_dump_mathkerndevtab (mathf, &mk->bottom_right);
  4219. if (mk->bottom_left.cnt != 0)
  4220. ttf_math_dump_mathkerndevtab (mathf, &mk->bottom_left);
  4221. }
  4222. if (kr_pos != ftell (mathf))
  4223. IError
  4224. ("Actual end did not match expected end in mathkern table, expected=%d, actual=%d",
  4225. kr_pos, ftell (mathf));
  4226. coverage_table = ftell (mathf);
  4227. fseek (mathf, coverage_pos, SEEK_SET);
  4228. putshort (mathf, coverage_table - coverage_pos);
  4229. fseek (mathf, coverage_table, SEEK_SET);
  4230. dumpcoveragetable (mathf, glyphs);
  4231. free (glyphs);
  4232. }
  4233. static int
  4234. gv_len (SplineFont *sf, struct glyphvariants *gv)
  4235. {
  4236. char *pt, *start;
  4237. int ch, cnt;
  4238. SplineChar *sc;
  4239. if (gv == NULL || (gv->variants == NULL && gv->part_cnt == 0))
  4240. return 0;
  4241. if (gv->variants == NULL)
  4242. return 4; /* No variants, but we've got parts to assemble */
  4243. cnt = 0;
  4244. for (start = gv->variants;;)
  4245. {
  4246. while (*start == ' ')
  4247. ++start;
  4248. if (*start == '\0')
  4249. return 4 + 4 * cnt; /* MathGlyphConstructionTable */
  4250. for (pt = start; *pt != ' ' && *pt != '\0'; ++pt);
  4251. ch = *pt;
  4252. *pt = '\0';
  4253. sc = SFGetChar (sf, -1, start);
  4254. *pt = ch;
  4255. if (sc != NULL)
  4256. ++cnt;
  4257. start = pt;
  4258. }
  4259. }
  4260. static int
  4261. gvc_len (struct glyphvariants *gv)
  4262. {
  4263. if (gv->part_cnt == 0)
  4264. return 0;
  4265. return 6 + 10 * gv->part_cnt;
  4266. }
  4267. static uint32_t
  4268. ttf_math_dump_mathglyphconstructiontable (FILE *mathf,
  4269. struct glyphvariants *gv,
  4270. SplineFont *sf, uint32_t pos,
  4271. int is_v)
  4272. {
  4273. char *pt, *start;
  4274. int ch, cnt;
  4275. SplineChar *sc;
  4276. uint32_t here = ftell (mathf);
  4277. DBounds b;
  4278. putshort (mathf, gv->part_cnt == 0 ? 0 : pos - here);
  4279. if (gv->variants == NULL)
  4280. {
  4281. putshort (mathf, 0);
  4282. }
  4283. else
  4284. {
  4285. cnt = 0;
  4286. for (start = gv->variants;;)
  4287. {
  4288. while (*start == ' ')
  4289. ++start;
  4290. if (*start == '\0')
  4291. break;
  4292. for (pt = start; *pt != ' ' && *pt != '\0'; ++pt);
  4293. ch = *pt;
  4294. *pt = '\0';
  4295. sc = SFGetChar (sf, -1, start);
  4296. *pt = ch;
  4297. if (sc != NULL)
  4298. ++cnt;
  4299. start = pt;
  4300. }
  4301. putshort (mathf, cnt);
  4302. for (start = gv->variants;;)
  4303. {
  4304. while (*start == ' ')
  4305. ++start;
  4306. if (*start == '\0')
  4307. break;
  4308. for (pt = start; *pt != ' ' && *pt != '\0'; ++pt);
  4309. ch = *pt;
  4310. *pt = '\0';
  4311. sc = SFGetChar (sf, -1, start);
  4312. *pt = ch;
  4313. if (sc != NULL)
  4314. {
  4315. putshort (mathf, sc->ttf_glyph);
  4316. SplineCharFindBounds (sc, &b);
  4317. /* Don't ask me why I have a plus one here. In the MS font */
  4318. /* CambriaMath all of these values are one more than I would */
  4319. /* expect */
  4320. if (is_v)
  4321. putshort (mathf, b.maxy - b.miny + 1);
  4322. else
  4323. putshort (mathf, b.maxx - b.minx + 1);
  4324. }
  4325. start = pt;
  4326. }
  4327. }
  4328. return pos + gvc_len (gv);
  4329. }
  4330. static uint32_t
  4331. ttf_math_dump_mathglyphassemblytable (FILE *mathf,
  4332. struct glyphvariants *gv, SplineFont *sf,
  4333. uint32_t devtab_pos)
  4334. {
  4335. SplineChar *sc;
  4336. uint32_t here = ftell (mathf);
  4337. int i;
  4338. if (gv->part_cnt == 0)
  4339. return devtab_pos;
  4340. putshort (mathf, gv->italic_correction);
  4341. if (gv->italic_adjusts != NULL)
  4342. {
  4343. putshort (mathf, devtab_pos - here);
  4344. devtab_pos += DevTabLen (gv->italic_adjusts);
  4345. }
  4346. else
  4347. putshort (mathf, 0);
  4348. putshort (mathf, gv->part_cnt);
  4349. for (i = 0; i < gv->part_cnt; ++i)
  4350. {
  4351. sc = SFGetChar (sf, -1, gv->parts[i].component);
  4352. if (sc == NULL)
  4353. putshort (mathf, 0); /* .notdef */
  4354. else
  4355. putshort (mathf, sc->ttf_glyph);
  4356. putshort (mathf, gv->parts[i].startConnectorLength);
  4357. putshort (mathf, gv->parts[i].endConnectorLength);
  4358. putshort (mathf, gv->parts[i].fullAdvance);
  4359. putshort (mathf, gv->parts[i].is_extender);
  4360. }
  4361. return devtab_pos;
  4362. }
  4363. static void
  4364. ttf_math_dump_glyphvariant (FILE *mathf, struct alltabs *at, SplineFont *sf)
  4365. {
  4366. int i, gid, vlen, hlen;
  4367. SplineChar *sc, **vglyphs, **hglyphs;
  4368. uint32_t coverage_pos, coverage_table, offset, pos, assembly_pos;
  4369. /* Figure out our glyph list (and count) */
  4370. for (i = vlen = hlen = 0; i < at->gi.gcnt; ++i)
  4371. if ((gid = at->gi.bygid[i]) != -1 && (sc = sf->glyphs[gid]) != NULL)
  4372. {
  4373. if (sc->vert_variants != NULL)
  4374. ++vlen;
  4375. if (sc->horiz_variants != NULL)
  4376. ++hlen;
  4377. }
  4378. vglyphs = xmalloc ((vlen + 1) * sizeof (SplineChar *));
  4379. hglyphs = xmalloc ((hlen + 1) * sizeof (SplineChar *));
  4380. for (i = vlen = hlen = 0; i < at->gi.gcnt; ++i)
  4381. if ((gid = at->gi.bygid[i]) != -1 && (sc = sf->glyphs[gid]) != NULL)
  4382. {
  4383. if (sc->vert_variants != NULL)
  4384. vglyphs[vlen++] = sc;
  4385. if (sc->horiz_variants != NULL)
  4386. hglyphs[hlen++] = sc;
  4387. }
  4388. vglyphs[vlen] = NULL;
  4389. hglyphs[hlen] = NULL;
  4390. putshort (mathf,
  4391. sf->MATH ==
  4392. NULL ? (sf->ascent +
  4393. sf->descent) / 50 : sf->MATH->MinConnectorOverlap);
  4394. coverage_pos = ftell (mathf);
  4395. putshort (mathf, 0); /* Vertical Coverage table, return to this */
  4396. putshort (mathf, 0); /* Horizontal Coverage table, return to this */
  4397. putshort (mathf, vlen);
  4398. putshort (mathf, hlen);
  4399. offset = 5 * 2 + vlen * 2 + hlen * 2;
  4400. for (i = 0; i < vlen; ++i)
  4401. {
  4402. putshort (mathf, offset);
  4403. offset += gv_len (sf, vglyphs[i]->vert_variants);
  4404. }
  4405. for (i = 0; i < hlen; ++i)
  4406. {
  4407. putshort (mathf, offset);
  4408. offset += gv_len (sf, hglyphs[i]->horiz_variants);
  4409. }
  4410. assembly_pos = pos = (coverage_pos - 2) + offset;
  4411. for (i = 0; i < vlen; ++i)
  4412. {
  4413. /*uint32_t start = ftell(mathf); */
  4414. pos = ttf_math_dump_mathglyphconstructiontable (mathf,
  4415. vglyphs[i]->vert_variants,
  4416. sf, pos, true);
  4417. /*if ( ftell(mathf)-start != gv_len(sf,vglyphs[i]->vert_variants)) */
  4418. /*IError("v gv_len incorrect"); */
  4419. }
  4420. for (i = 0; i < hlen; ++i)
  4421. {
  4422. /*uint32_t start = ftell(mathf); */
  4423. pos = ttf_math_dump_mathglyphconstructiontable (mathf,
  4424. hglyphs[i]->
  4425. horiz_variants, sf, pos,
  4426. false);
  4427. /*if ( ftell(mathf)-start != gv_len(sf,hglyphs[i]->horiz_variants)) */
  4428. /*IError("h gv_len incorrect: %s", hglyphs[i]->name); */
  4429. }
  4430. if (ftell (mathf) != assembly_pos)
  4431. IError ("assembly tables at wrong place");
  4432. for (i = 0; i < vlen; ++i)
  4433. pos = ttf_math_dump_mathglyphassemblytable (mathf,
  4434. vglyphs[i]->vert_variants, sf,
  4435. pos);
  4436. for (i = 0; i < hlen; ++i)
  4437. pos = ttf_math_dump_mathglyphassemblytable (mathf,
  4438. hglyphs[i]->horiz_variants, sf,
  4439. pos);
  4440. for (i = 0; i < vlen; ++i)
  4441. if (vglyphs[i]->vert_variants->part_cnt != 0 &&
  4442. vglyphs[i]->vert_variants->italic_adjusts != NULL)
  4443. dumpgposdevicetable (mathf, vglyphs[i]->vert_variants->italic_adjusts);
  4444. for (i = 0; i < hlen; ++i)
  4445. if (hglyphs[i]->horiz_variants->part_cnt != 0 &&
  4446. hglyphs[i]->horiz_variants->italic_adjusts != NULL)
  4447. dumpgposdevicetable (mathf, hglyphs[i]->horiz_variants->italic_adjusts);
  4448. if (vlen != 0)
  4449. {
  4450. coverage_table = ftell (mathf);
  4451. fseek (mathf, coverage_pos, SEEK_SET);
  4452. putshort (mathf, coverage_table - (coverage_pos - 2));
  4453. fseek (mathf, coverage_table, SEEK_SET);
  4454. dumpcoveragetable (mathf, vglyphs);
  4455. }
  4456. free (vglyphs);
  4457. if (hlen != 0)
  4458. {
  4459. coverage_table = ftell (mathf);
  4460. fseek (mathf, coverage_pos + 2, SEEK_SET);
  4461. putshort (mathf, coverage_table - (coverage_pos - 2));
  4462. fseek (mathf, coverage_table, SEEK_SET);
  4463. dumpcoveragetable (mathf, hglyphs);
  4464. }
  4465. free (hglyphs);
  4466. }
  4467. void
  4468. otf_dump_math (struct alltabs *at, SplineFont *sf)
  4469. {
  4470. FILE *mathf;
  4471. int i;
  4472. uint32_t devtab_offsets[60], const_start, gi_start, v_start;
  4473. int bits = MathBits (at, sf);
  4474. if (sf->MATH == NULL)
  4475. return;
  4476. at->math = mathf = tmpfile ();
  4477. putlong (mathf, 0x00010000); /* Version 1 */
  4478. putshort (mathf, 10); /* Offset to constants */
  4479. putshort (mathf, 0); /* GlyphInfo, fix later */
  4480. putshort (mathf, 0); /* Variants, fix later */
  4481. /* Start on constants */
  4482. memset (devtab_offsets, 0, sizeof (devtab_offsets));
  4483. const_start = ftell (mathf);
  4484. for (i = 0; math_constants_descriptor[i].script_name != NULL; ++i)
  4485. {
  4486. int16_t *pos =
  4487. (int16_t *) (((char *) (sf->MATH)) +
  4488. math_constants_descriptor[i].offset);
  4489. if (pos == (int16_t *) &sf->MATH->MinConnectorOverlap)
  4490. continue; /* Actually lives in the Variant table, not here */
  4491. putshort (mathf, *pos);
  4492. if (math_constants_descriptor[i].devtab_offset != -1)
  4493. {
  4494. devtab_offsets[i] = ftell (mathf);
  4495. putshort (mathf, 0); /* Fix up later if we support device tables */
  4496. }
  4497. }
  4498. for (i = 0; math_constants_descriptor[i].script_name != NULL; ++i)
  4499. {
  4500. int16_t *pos =
  4501. (int16_t *) (((char *) (sf->MATH)) +
  4502. math_constants_descriptor[i].offset);
  4503. DeviceTable **devtab =
  4504. (DeviceTable **) (((char *) (sf->MATH)) +
  4505. math_constants_descriptor[i].devtab_offset);
  4506. if (pos == (int16_t *) &sf->MATH->MinConnectorOverlap)
  4507. continue; /* Actually lives in the Variant table, not here */
  4508. if (math_constants_descriptor[i].devtab_offset >= 0 && *devtab != NULL)
  4509. {
  4510. uint32_t here = ftell (mathf);
  4511. fseek (mathf, devtab_offsets[i], SEEK_SET);
  4512. putshort (mathf, here - const_start);
  4513. fseek (mathf, here, SEEK_SET);
  4514. dumpgposdevicetable (mathf, *devtab);
  4515. }
  4516. }
  4517. /* The spec does not say this can be NULL */
  4518. if (1 /* bits&mb_gi */ )
  4519. {
  4520. gi_start = ftell (mathf);
  4521. fseek (mathf, 6, SEEK_SET);
  4522. putshort (mathf, gi_start);
  4523. fseek (mathf, gi_start, SEEK_SET);
  4524. putshort (mathf, 0); /* Italics correction */
  4525. putshort (mathf, 0); /* top accent */
  4526. putshort (mathf, 0); /* is extended shape */
  4527. putshort (mathf, 0); /* math kern info */
  4528. if (bits & mb_italic)
  4529. {
  4530. v_start = ftell (mathf);
  4531. fseek (mathf, gi_start, SEEK_SET);
  4532. putshort (mathf, v_start - gi_start);
  4533. fseek (mathf, v_start, SEEK_SET);
  4534. ttf_math_dump_italic_top (mathf, at, sf, true);
  4535. }
  4536. if (bits & mb_topaccent)
  4537. {
  4538. v_start = ftell (mathf);
  4539. fseek (mathf, gi_start + 2, SEEK_SET);
  4540. putshort (mathf, v_start - gi_start);
  4541. fseek (mathf, v_start, SEEK_SET);
  4542. ttf_math_dump_italic_top (mathf, at, sf, false);
  4543. }
  4544. if (bits & mb_extended)
  4545. {
  4546. v_start = ftell (mathf);
  4547. fseek (mathf, gi_start + 4, SEEK_SET);
  4548. putshort (mathf, v_start - gi_start);
  4549. fseek (mathf, v_start, SEEK_SET);
  4550. ttf_math_dump_extended (mathf, at, sf);
  4551. }
  4552. if (bits & mb_mathkern)
  4553. {
  4554. v_start = ftell (mathf);
  4555. fseek (mathf, gi_start + 6, SEEK_SET);
  4556. putshort (mathf, v_start - gi_start);
  4557. fseek (mathf, v_start, SEEK_SET);
  4558. ttf_math_dump_mathkern (mathf, at, sf);
  4559. }
  4560. }
  4561. /* The spec does not say this can be NULL */
  4562. if (1 /* bits&mb_gv */ )
  4563. {
  4564. v_start = ftell (mathf);
  4565. fseek (mathf, 8, SEEK_SET);
  4566. putshort (mathf, v_start);
  4567. fseek (mathf, v_start, SEEK_SET);
  4568. ttf_math_dump_glyphvariant (mathf, at, sf);
  4569. }
  4570. at->mathlen = ftell (mathf);
  4571. if (ftell (mathf) & 1)
  4572. putc ('\0', mathf);
  4573. if (ftell (mathf) & 2)
  4574. putshort (mathf, 0);
  4575. }
  4576. struct taglist
  4577. {
  4578. uint32_t tag;
  4579. struct taglist *next;
  4580. };
  4581. static int
  4582. taglistcompar (const void *_cv1, const void *_cv2)
  4583. {
  4584. const struct taglist *const *tl1 = _cv1, *const *tl2 = _cv2;
  4585. if ((*tl1)->tag == (*tl2)->tag)
  4586. return 0;
  4587. if ((*tl1)->tag > (*tl2)->tag)
  4588. return 1;
  4589. return -1;
  4590. }
  4591. static int
  4592. langlistcompar (const void *_cv1, const void *_cv2)
  4593. {
  4594. const struct taglist *const *tl1 = _cv1, *const *tl2 = _cv2;
  4595. if ((*tl1)->tag == (*tl2)->tag)
  4596. return 0;
  4597. if ((*tl1)->tag == DEFAULT_LANG)
  4598. return -1;
  4599. if ((*tl2)->tag == DEFAULT_LANG)
  4600. return 1;
  4601. if ((*tl1)->tag > (*tl2)->tag)
  4602. return 1;
  4603. return -1;
  4604. }
  4605. static struct taglist *
  4606. sorttaglist (struct taglist *list, int (*compar) (const void *, const void *))
  4607. {
  4608. struct taglist *t, **array;
  4609. int i, cnt;
  4610. if (list == NULL || list->next == NULL)
  4611. return list;
  4612. for (t = list, cnt = 0; t != NULL; t = t->next, ++cnt);
  4613. array = xmalloc (cnt * sizeof (struct taglist *));
  4614. for (t = list, cnt = 0; t != NULL; t = t->next, ++cnt)
  4615. array[cnt] = t;
  4616. qsort (array, cnt, sizeof (struct taglist *), compar);
  4617. for (i = 1; i < cnt; ++i)
  4618. array[i - 1]->next = array[i];
  4619. array[cnt - 1]->next = NULL;
  4620. list = array[0];
  4621. free (array);
  4622. return list;
  4623. }
  4624. static void
  4625. _base_sort (struct Base *base)
  4626. {
  4627. /* Sort the base lines. Which can reorder the def_baseline index in the */
  4628. /* script, and the baseline_pos lists */
  4629. /* Sort the script list */
  4630. /* Sort the language lists in each script */
  4631. /* Sort the feature lists in each language */
  4632. int i, j, pos, tag;
  4633. struct basescript *bs;
  4634. struct baselangextent *langs;
  4635. if (base == NULL)
  4636. return;
  4637. if (base->baseline_cnt != 0)
  4638. {
  4639. for (i = 0; i < base->baseline_cnt; ++i)
  4640. for (j = i + 1; j < base->baseline_cnt; ++j)
  4641. {
  4642. if (base->baseline_tags[i] > base->baseline_tags[j])
  4643. {
  4644. tag = base->baseline_tags[i];
  4645. base->baseline_tags[i] = base->baseline_tags[j];
  4646. base->baseline_tags[j] = tag;
  4647. for (bs = base->scripts; bs != NULL; bs = bs->next)
  4648. {
  4649. if (bs->def_baseline == i)
  4650. bs->def_baseline = j;
  4651. else if (bs->def_baseline == j)
  4652. bs->def_baseline = i;
  4653. pos = bs->baseline_pos[i];
  4654. bs->baseline_pos[i] = bs->baseline_pos[j];
  4655. bs->baseline_pos[j] = pos;
  4656. }
  4657. }
  4658. }
  4659. }
  4660. base->scripts =
  4661. (struct basescript *) sorttaglist ((struct taglist *) base->scripts,
  4662. taglistcompar);
  4663. for (bs = base->scripts; bs != NULL; bs = bs->next)
  4664. {
  4665. bs->langs =
  4666. (struct baselangextent *) sorttaglist ((struct taglist *) bs->langs,
  4667. langlistcompar);
  4668. for (langs = bs->langs; langs != NULL; langs = langs->next)
  4669. langs->features =
  4670. (struct baselangextent *) sorttaglist ((struct taglist *) langs->
  4671. features, taglistcompar);
  4672. }
  4673. }
  4674. void
  4675. SFBaseSort (SplineFont *sf)
  4676. {
  4677. _base_sort (sf->horiz_base);
  4678. _base_sort (sf->vert_base);
  4679. }
  4680. static void
  4681. dump_minmax (FILE *basef, struct baselangextent *bl)
  4682. {
  4683. struct baselangextent *fl;
  4684. int fcnt;
  4685. putshort (basef, bl->descent);
  4686. putshort (basef, bl->ascent);
  4687. for (fl = bl->features, fcnt = 0; fl != NULL; fl = fl->next, ++fcnt);
  4688. putshort (basef, fcnt);
  4689. for (fl = bl->features; fl != NULL; fl = fl->next)
  4690. {
  4691. putlong (basef, fl->lang); /* feature tag really */
  4692. putshort (basef, fl->descent);
  4693. putshort (basef, fl->ascent);
  4694. }
  4695. }
  4696. void
  4697. otf_dumpbase (struct alltabs *at, SplineFont *sf)
  4698. {
  4699. FILE *basef;
  4700. int i, j, cnt, lcnt;
  4701. uint32_t here, bsl;
  4702. struct basescript *bs;
  4703. struct baselangextent *bl, *dflt;
  4704. int offset;
  4705. if (sf->horiz_base == NULL && sf->vert_base == NULL)
  4706. return;
  4707. SFBaseSort (sf);
  4708. at->base = basef = tmpfile ();
  4709. putlong (basef, 0x00010000); /* Version 1 */
  4710. putshort (basef, 0); /* offset to horizontal baselines, fill in later */
  4711. putshort (basef, 0); /* offset to vertical baselines, fill in later */
  4712. for (i = 0; i < 2; ++i)
  4713. {
  4714. struct Base *base = i == 0 ? sf->horiz_base : sf->vert_base;
  4715. if (base == NULL)
  4716. continue;
  4717. here = ftell (basef);
  4718. fseek (basef, 4 + 2 * i, SEEK_SET);
  4719. putshort (basef, here - 0);
  4720. fseek (basef, here, SEEK_SET);
  4721. /* axis table */
  4722. putshort (basef, base->baseline_cnt == 0 ? 0 : 4);
  4723. putshort (basef, base->baseline_cnt == 0 ? 4 :
  4724. 4 + 2 + 4 * base->baseline_cnt);
  4725. if (base->baseline_cnt != 0)
  4726. {
  4727. /* BaseTagList table */
  4728. putshort (basef, base->baseline_cnt);
  4729. for (j = 0; j < base->baseline_cnt; ++j)
  4730. putlong (basef, base->baseline_tags[j]);
  4731. }
  4732. /* BaseScriptList table */
  4733. bsl = ftell (basef);
  4734. for (bs = base->scripts, cnt = 0; bs != NULL; bs = bs->next, ++cnt);
  4735. putshort (basef, cnt);
  4736. for (bs = base->scripts; bs != NULL; bs = bs->next)
  4737. {
  4738. putlong (basef, bs->script);
  4739. putshort (basef, 0);
  4740. }
  4741. /* BaseScript table */
  4742. for (bs = base->scripts, cnt = 0; bs != NULL; bs = bs->next, ++cnt)
  4743. {
  4744. uint32_t bst = ftell (basef);
  4745. fseek (basef, bsl + 2 + 6 * cnt + 4, SEEK_SET);
  4746. putshort (basef, bst - bsl);
  4747. fseek (basef, bst, SEEK_SET);
  4748. for (bl = bs->langs, dflt = NULL, lcnt = 0; bl != NULL; bl = bl->next)
  4749. {
  4750. if (bl->lang == DEFAULT_LANG)
  4751. dflt = bl;
  4752. else
  4753. ++lcnt;
  4754. }
  4755. offset = 6 + 6 * lcnt;
  4756. putshort (basef, base->baseline_cnt == 0 ? 0 : offset);
  4757. if (base->baseline_cnt != 0)
  4758. offset += 4 + 2 * base->baseline_cnt + 4 * base->baseline_cnt;
  4759. putshort (basef, dflt == NULL ? 0 : offset);
  4760. putshort (basef, lcnt);
  4761. for (bl = bs->langs; bl != NULL; bl = bl->next)
  4762. if (bl->lang != DEFAULT_LANG)
  4763. {
  4764. putlong (basef, bl->lang);
  4765. putshort (basef, 0);
  4766. }
  4767. /* Base Values table */
  4768. if (base->baseline_cnt != 0)
  4769. {
  4770. offset = 4 + 2 * base->baseline_cnt;
  4771. putshort (basef, bs->def_baseline);
  4772. putshort (basef, base->baseline_cnt);
  4773. for (j = 0; j < base->baseline_cnt; ++j)
  4774. {
  4775. putshort (basef, offset);
  4776. offset += 2 * 2;
  4777. }
  4778. for (j = 0; j < base->baseline_cnt; ++j)
  4779. {
  4780. putshort (basef, 1); /* format 1 */
  4781. putshort (basef, bs->baseline_pos[j]);
  4782. }
  4783. }
  4784. if (dflt != NULL)
  4785. dump_minmax (basef, dflt);
  4786. for (bl = bs->langs, dflt = NULL, lcnt = 0; bl != NULL; bl = bl->next)
  4787. if (bl->lang != DEFAULT_LANG)
  4788. {
  4789. uint32_t here = ftell (basef);
  4790. fseek (basef, bst + 6 + 6 * lcnt + 4, SEEK_SET);
  4791. putshort (basef, here - bst);
  4792. fseek (basef, here, SEEK_SET);
  4793. dump_minmax (basef, bl);
  4794. }
  4795. }
  4796. }
  4797. at->baselen = ftell (basef);
  4798. if (ftell (basef) & 1)
  4799. putc ('\0', basef);
  4800. if (ftell (basef) & 2)
  4801. putshort (basef, 0);
  4802. }
  4803. static int
  4804. jscriptsort (const void *_s1, const void *_s2)
  4805. {
  4806. const Justify *const *__s1 = (const Justify * const *) _s1;
  4807. const Justify *const *__s2 = (const Justify * const *) _s2;
  4808. const Justify *s1 = *__s1;
  4809. const Justify *s2 = *__s2;
  4810. if (s1->script > s2->script)
  4811. return 1;
  4812. else if (s1->script < s2->script)
  4813. return -1;
  4814. else
  4815. return 0;
  4816. }
  4817. static int
  4818. jlangsort (const void *_s1, const void *_s2)
  4819. {
  4820. const struct jstf_lang *const *__s1 = (const struct jstf_lang * const *) _s1;
  4821. const struct jstf_lang *const *__s2 = (const struct jstf_lang * const *) _s2;
  4822. const struct jstf_lang *s1 = *__s1;
  4823. const struct jstf_lang *s2 = *__s2;
  4824. if (s1->lang == s2->lang)
  4825. return 0;
  4826. if (s1->lang == DEFAULT_LANG)
  4827. return -1;
  4828. if (s2->lang == DEFAULT_LANG)
  4829. return 1;
  4830. if (s1->lang > s2->lang)
  4831. return 1;
  4832. else
  4833. return -1;
  4834. }
  4835. static int
  4836. lookup_order (const void *_s1, const void *_s2)
  4837. {
  4838. const OTLookup *const *__s1 = (const OTLookup *const *) _s1;
  4839. const OTLookup *const *__s2 = (const OTLookup *const *) _s2;
  4840. const OTLookup *s1 = *__s1;
  4841. const OTLookup *s2 = *__s2;
  4842. if (s1->lookup_index > s2->lookup_index)
  4843. return 1;
  4844. else if (s1->lookup_index < s2->lookup_index)
  4845. return -1;
  4846. else
  4847. return 0;
  4848. }
  4849. static void
  4850. SFJstfSort (SplineFont *sf)
  4851. {
  4852. /* scripts must be ordered */
  4853. /* languages must be ordered within scripts */
  4854. /* lookup lists must be ordered */
  4855. Justify *jscript, **scripts;
  4856. int i, cnt, lmax;
  4857. struct jstf_lang **langs;
  4858. for (cnt = 0, jscript = sf->justify; jscript != NULL;
  4859. ++cnt, jscript = jscript->next);
  4860. if (cnt > 1)
  4861. {
  4862. scripts = xmalloc (cnt * sizeof (Justify *));
  4863. for (i = 0, jscript = sf->justify; jscript != NULL;
  4864. ++i, jscript = jscript->next)
  4865. scripts[i] = jscript;
  4866. qsort (scripts, cnt, sizeof (Justify *), jscriptsort);
  4867. for (i = 1; i < cnt; ++i)
  4868. scripts[i - 1]->next = scripts[i];
  4869. scripts[cnt - 1]->next = NULL;
  4870. sf->justify = scripts[0];
  4871. free (scripts);
  4872. }
  4873. langs = NULL;
  4874. lmax = 0;
  4875. for (jscript = sf->justify; jscript != NULL; jscript = jscript->next)
  4876. {
  4877. struct jstf_lang *jlang;
  4878. for (cnt = 0, jlang = jscript->langs; jlang != NULL;
  4879. ++cnt, jlang = jlang->next);
  4880. if (cnt > 1)
  4881. {
  4882. if (cnt > lmax)
  4883. langs =
  4884. xrealloc (langs, (lmax = cnt + 10) * sizeof (struct jstf_lang *));
  4885. for (i = 0, jlang = jscript->langs; jlang != NULL;
  4886. ++i, jlang = jlang->next)
  4887. langs[i] = jlang;
  4888. qsort (langs, cnt, sizeof (Justify *), jlangsort);
  4889. for (i = 1; i < cnt; ++i)
  4890. langs[i - 1]->next = langs[i];
  4891. langs[cnt - 1]->next = NULL;
  4892. jscript->langs = langs[0];
  4893. }
  4894. }
  4895. free (langs);
  4896. /* don't bother to sort the lookup lists yet. We need to separate them into */
  4897. /* GPOS/GSUB first, might as well do it all at once later */
  4898. }
  4899. static void
  4900. jstf_SplitTables (OTLookup **mixed, OTLookup ***_SUB, OTLookup ***_POS)
  4901. {
  4902. /* (later is now, see comment above) */
  4903. /* mixed contains both gsub and gpos lookups. put them into their own */
  4904. /* lists, and then sort them */
  4905. int cnt, s, p;
  4906. OTLookup **SUB, **POS;
  4907. if (mixed == NULL || mixed[0] == NULL)
  4908. {
  4909. *_SUB = NULL;
  4910. *_POS = NULL;
  4911. return;
  4912. }
  4913. for (cnt = 0; mixed[cnt] != NULL; ++cnt);
  4914. SUB = xmalloc ((cnt + 1) * sizeof (OTLookup *));
  4915. POS = xmalloc ((cnt + 1) * sizeof (OTLookup *));
  4916. for (cnt = s = p = 0; mixed[cnt] != NULL; ++cnt)
  4917. {
  4918. if (mixed[cnt]->lookup_index == -1) /* Not actually used */
  4919. continue;
  4920. if (mixed[cnt]->lookup_type >= gpos_start)
  4921. POS[p++] = mixed[cnt];
  4922. else
  4923. SUB[s++] = mixed[cnt];
  4924. }
  4925. POS[p] = SUB[s] = NULL;
  4926. if (p > 1)
  4927. qsort (POS, p, sizeof (OTLookup *), lookup_order);
  4928. if (s > 1)
  4929. qsort (SUB, s, sizeof (OTLookup *), lookup_order);
  4930. if (p == 0)
  4931. {
  4932. free (POS);
  4933. POS = NULL;
  4934. }
  4935. if (s == 0)
  4936. {
  4937. free (SUB);
  4938. SUB = NULL;
  4939. }
  4940. *_SUB = SUB;
  4941. *_POS = POS;
  4942. }
  4943. static uint32_t
  4944. jstf_dumplklist (FILE *jstf, OTLookup **PS, uint32_t base)
  4945. {
  4946. uint32_t here;
  4947. int i;
  4948. if (PS == NULL)
  4949. return 0;
  4950. here = ftell (jstf);
  4951. for (i = 0; PS[i] != NULL; ++i);
  4952. putshort (jstf, i); /* Lookup cnt */
  4953. for (i = 0; PS[i] != NULL; ++i)
  4954. putshort (jstf, PS[i]->lookup_index);
  4955. free (PS);
  4956. return here - base;
  4957. }
  4958. static uint32_t
  4959. jstf_dumpmaxlookups (FILE *jstf, SplineFont *sf, struct alltabs *at,
  4960. OTLookup **maxes, uint32_t base)
  4961. {
  4962. uint32_t here, lbase;
  4963. int cnt, i;
  4964. int scnt, j;
  4965. struct lookup_subtable *sub;
  4966. if (maxes == NULL)
  4967. return 0;
  4968. for (cnt = i = 0; maxes[i] != NULL; ++i)
  4969. if (!maxes[i]->unused)
  4970. ++cnt;
  4971. if (cnt == 0)
  4972. return 0;
  4973. here = ftell (jstf);
  4974. putshort (jstf, cnt);
  4975. for (i = 0; maxes[i] != NULL; ++i)
  4976. if (!maxes[i]->unused)
  4977. putshort (jstf, 0);
  4978. for (cnt = i = 0; maxes[i] != NULL; ++i)
  4979. if (!maxes[i]->unused)
  4980. {
  4981. lbase = ftell (jstf);
  4982. fseek (jstf, here + 2 + 2 * cnt, SEEK_SET);
  4983. putshort (jstf, lbase - here);
  4984. fseek (jstf, lbase, SEEK_SET);
  4985. putshort (jstf, maxes[i]->lookup_type - gpos_start);
  4986. putshort (jstf, maxes[i]->lookup_flags);
  4987. for (scnt = 0, sub = maxes[i]->subtables; sub != NULL; sub = sub->next)
  4988. if (!sub->unused)
  4989. ++scnt;
  4990. putshort (jstf, scnt);
  4991. for (j = 0; j < scnt; ++j)
  4992. putshort (jstf, 0);
  4993. /* I don't think extension lookups get a MarkAttachmentType, I guess */
  4994. /* that inherits from the parent? */
  4995. otf_dumpALookup (jstf, maxes[i], sf, at);
  4996. fseek (jstf, lbase + 6, SEEK_SET);
  4997. for (sub = maxes[i]->subtables; sub != NULL; sub = sub->next)
  4998. if (!sub->unused)
  4999. putshort (jstf, sub->subtable_offset - lbase);
  5000. ++cnt;
  5001. }
  5002. return here - base;
  5003. }
  5004. void
  5005. otf_dumpjstf (struct alltabs *at, SplineFont *sf)
  5006. {
  5007. FILE *jstf;
  5008. int i, cnt, lcnt, offset;
  5009. uint32_t here, base;
  5010. Justify *jscript;
  5011. struct jstf_lang *jlang;
  5012. if (sf->justify == NULL)
  5013. return;
  5014. SFJstfSort (sf);
  5015. for (jscript = sf->justify, cnt = 0; jscript != NULL;
  5016. jscript = jscript->next, ++cnt);
  5017. at->jstf = jstf = tmpfile ();
  5018. putlong (jstf, 0x00010000); /* Version 1 */
  5019. putshort (jstf, cnt); /* script count */
  5020. for (jscript = sf->justify; jscript != NULL; jscript = jscript->next)
  5021. {
  5022. putlong (jstf, jscript->script);
  5023. putshort (jstf, 0); /* Come back to this later */
  5024. }
  5025. for (jscript = sf->justify, cnt = 0; jscript != NULL;
  5026. jscript = jscript->next, ++cnt)
  5027. {
  5028. base = ftell (jstf);
  5029. if (base > 0xffff)
  5030. ff_post_error (_("Failure"),
  5031. _
  5032. ("Offset in JSTF table is too big. The resultant font will not work."));
  5033. fseek (jstf, 6 + 6 * cnt + 4, SEEK_SET);
  5034. putshort (jstf, base);
  5035. fseek (jstf, base, SEEK_SET);
  5036. putshort (jstf, 0); /* extender glyphs */
  5037. putshort (jstf, 0); /* default lang */
  5038. for (jlang = jscript->langs, lcnt = 0; jlang != NULL;
  5039. jlang = jlang->next, ++lcnt);
  5040. if (lcnt > 0 && jscript->langs->lang == DEFAULT_LANG)
  5041. --lcnt;
  5042. putshort (jstf, lcnt); /* count of non-default languages */
  5043. jlang = jscript->langs;
  5044. if (jlang != NULL && jlang->lang == DEFAULT_LANG)
  5045. jlang = jlang->next;
  5046. for (; jlang != NULL; jlang = jlang->next)
  5047. {
  5048. putlong (jstf, jlang->lang);
  5049. putshort (jstf, 0); /* Come back to this later */
  5050. }
  5051. if (jscript->extenders != NULL)
  5052. {
  5053. SplineChar **glyphs;
  5054. int gcnt, g;
  5055. here = ftell (jstf);
  5056. fseek (jstf, base, SEEK_SET);
  5057. putshort (jstf, here - base);
  5058. fseek (jstf, here, SEEK_SET);
  5059. glyphs = OrderedGlyphsFromNames (sf, jscript->extenders);
  5060. if (glyphs == NULL)
  5061. gcnt = 0;
  5062. else
  5063. for (gcnt = 0; glyphs[gcnt] != NULL; ++gcnt);
  5064. putshort (jstf, gcnt);
  5065. for (g = 0; g < gcnt; ++g)
  5066. putshort (jstf, glyphs[g]->ttf_glyph);
  5067. free (glyphs);
  5068. }
  5069. offset = 0;
  5070. for (jlang = jscript->langs, lcnt = 0; jlang != NULL;
  5071. jlang = jlang->next, ++lcnt)
  5072. {
  5073. here = ftell (jstf);
  5074. if (jlang->lang == DEFAULT_LANG)
  5075. {
  5076. fseek (jstf, base + 2, SEEK_SET);
  5077. offset = -6;
  5078. }
  5079. else
  5080. fseek (jstf, base + offset + 10 + lcnt * 6, SEEK_SET);
  5081. putshort (jstf, here - base);
  5082. fseek (jstf, here, SEEK_SET);
  5083. putshort (jstf, jlang->cnt);
  5084. for (i = 0; i < jlang->cnt; ++i)
  5085. putshort (jstf, 0);
  5086. for (i = 0; i < jlang->cnt; ++i)
  5087. {
  5088. OTLookup **enSUB, **enPOS, **disSUB, **disPOS;
  5089. uint32_t enSUBoff, enPOSoff, disSUBoff, disPOSoff, maxOff;
  5090. uint32_t pbase;
  5091. pbase = ftell (jstf);
  5092. fseek (jstf, here + 2 + i * 2, SEEK_SET);
  5093. putshort (jstf, pbase - here);
  5094. fseek (jstf, pbase, SEEK_SET);
  5095. putshort (jstf, 0);
  5096. putshort (jstf, 0);
  5097. putshort (jstf, 0);
  5098. putshort (jstf, 0);
  5099. putshort (jstf, 0);
  5100. putshort (jstf, 0);
  5101. putshort (jstf, 0);
  5102. putshort (jstf, 0);
  5103. putshort (jstf, 0);
  5104. putshort (jstf, 0);
  5105. jstf_SplitTables (jlang->prios[i].enableShrink, &enSUB, &enPOS);
  5106. jstf_SplitTables (jlang->prios[i].disableShrink, &disSUB,
  5107. &disPOS);
  5108. enSUBoff = jstf_dumplklist (jstf, enSUB, pbase);
  5109. disSUBoff = jstf_dumplklist (jstf, disSUB, pbase);
  5110. enPOSoff = jstf_dumplklist (jstf, enPOS, pbase);
  5111. disPOSoff = jstf_dumplklist (jstf, disPOS, pbase);
  5112. maxOff =
  5113. jstf_dumpmaxlookups (jstf, sf, at, jlang->prios[i].maxShrink,
  5114. pbase);
  5115. fseek (jstf, pbase, SEEK_SET);
  5116. putshort (jstf, enSUBoff);
  5117. putshort (jstf, disSUBoff);
  5118. putshort (jstf, enPOSoff);
  5119. putshort (jstf, disPOSoff);
  5120. putshort (jstf, maxOff);
  5121. fseek (jstf, 0, SEEK_END);
  5122. jstf_SplitTables (jlang->prios[i].enableExtend, &enSUB, &enPOS);
  5123. jstf_SplitTables (jlang->prios[i].disableExtend, &disSUB,
  5124. &disPOS);
  5125. enSUBoff = jstf_dumplklist (jstf, enSUB, pbase);
  5126. disSUBoff = jstf_dumplklist (jstf, disSUB, pbase);
  5127. enPOSoff = jstf_dumplklist (jstf, enPOS, pbase);
  5128. disPOSoff = jstf_dumplklist (jstf, disPOS, pbase);
  5129. maxOff =
  5130. jstf_dumpmaxlookups (jstf, sf, at, jlang->prios[i].maxExtend,
  5131. pbase);
  5132. fseek (jstf, pbase + 10, SEEK_SET);
  5133. putshort (jstf, enSUBoff);
  5134. putshort (jstf, disSUBoff);
  5135. putshort (jstf, enPOSoff);
  5136. putshort (jstf, disPOSoff);
  5137. putshort (jstf, maxOff);
  5138. fseek (jstf, 0, SEEK_END);
  5139. }
  5140. }
  5141. }
  5142. fseek (jstf, 0, SEEK_END);
  5143. at->jstflen = ftell (jstf);
  5144. if (ftell (jstf) & 1)
  5145. putc ('\0', jstf);
  5146. if (ftell (jstf) & 2)
  5147. putshort (jstf, 0);
  5148. }
  5149. void
  5150. otf_dump_dummydsig (struct alltabs *at, SplineFont *sf)
  5151. {
  5152. FILE *dsigf;
  5153. /* I think the DSIG table is a big crock. At best the most it can do is */
  5154. /* tell you that the font hasn't changed since it was signed. It gives */
  5155. /* no guarantee that the data are reasonable. I think it's stupid. */
  5156. /* I think it is even more stupid that MS choses this useless table as a */
  5157. /* mark of whether a ttf font is OpenType or not. */
  5158. /* But users want their fonts to show up as OpenType under MS. And I'm */
  5159. /* told an empty DSIG table works for that. So... a truely pointless */
  5160. /* instance of a pointless table. I suppose that's a bit ironic. */
  5161. at->dsigf = dsigf = tmpfile ();
  5162. putlong (dsigf, 0x00000001); /* Standard version (and why isn't it 0x10000 like everything else?) */
  5163. putshort (dsigf, 0); /* No signatures in my signature table */
  5164. putshort (dsigf, 0); /* No flags */
  5165. at->dsiglen = ftell (dsigf);
  5166. if (ftell (dsigf) & 1)
  5167. putc ('\0', dsigf);
  5168. if (ftell (dsigf) & 2)
  5169. putshort (dsigf, 0);
  5170. }