PageRenderTime 68ms CodeModel.GetById 33ms 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

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

  1. #include <config.h>
  2. // This file is part of the Sorts Mill Tools.
  3. //
  4. // Sorts Mill Tools is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Sorts Mill Tools is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, see <http://www.gnu.org/licenses/>.
  16. /* Copyright (C) 2000-2012 by George Williams */
  17. /*
  18. * Redistribution and use in source and binary forms, with or without
  19. * modification, are permitted provided that the following conditions are met:
  20. * Redistributions of source code must retain the above copyright notice, this
  21. * list of conditions and the following disclaimer.
  22. * Redistributions in binary form must reproduce the above copyright notice,
  23. * this list of conditions and the following disclaimer in the documentation
  24. * and/or other materials provided with the distribution.
  25. * The name of the author may not be used to endorse or promote products
  26. * derived from this software without specific prior written permission.
  27. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  28. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  29. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  30. * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  31. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  32. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  33. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  34. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  35. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  36. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  37. */
  38. #include "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 t…

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