/fontforge/parsettfatt.c
C | 5088 lines | 4680 code | 265 blank | 143 comment | 1181 complexity | bcd8c971aa241c24bd2daa76023c09a3 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- #include <config.h>
- // This file is part of the Sorts Mill Tools.
- //
- // Sorts Mill Tools is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 3 of the License, or
- // (at your option) any later version.
- //
- // Sorts Mill Tools is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, see <http://www.gnu.org/licenses/>.
- /* Copyright (C) 2000-2012 by George Williams */
- /*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "fontforge.h"
- #include <chardata.h>
- #include <utype.h>
- #include <ustring.h>
- #include <math.h>
- #include <locale.h>
- #include <stdlib.h>
- #include "ttf.h"
- static uint16_t *
- getAppleClassTable (FILE *ttf, int classdef_offset, int cnt, int sub, int div,
- struct ttfinfo *info)
- {
- uint16_t *class = xcalloc (cnt, sizeof (uint16_t));
- int first, i, n;
- /* Apple stores its class tables as containing offsets. I find it hard to */
- /* think that way and convert them to indeces (by subtracting off a base */
- /* offset and dividing by the item's size) before doing anything else */
- fseek (ttf, classdef_offset, SEEK_SET);
- first = getushort (ttf);
- n = getushort (ttf);
- if (first + n - 1 >= cnt)
- {
- LogError (_("Bad Apple Kern Class\n"));
- info->bad_gx = true;
- }
- for (i = 0; i < n && i + first < cnt; ++i)
- class[first + i] = (getushort (ttf) - sub) / div;
- return class;
- }
- static char **
- ClassToNames (struct ttfinfo *info, int class_cnt, uint16_t *class,
- int glyph_cnt)
- {
- char **ret = xmalloc (class_cnt * sizeof (char *));
- int *lens = xcalloc (class_cnt, sizeof (int));
- int i;
- ret[0] = NULL;
- for (i = 0; i < glyph_cnt; ++i)
- if (class[i] != 0 && info->chars[i] != NULL && class[i] < class_cnt)
- lens[class[i]] += strlen (info->chars[i]->name) + 1;
- for (i = 1; i < class_cnt; ++i)
- ret[i] = xmalloc (lens[i] + 1);
- memset (lens, 0, class_cnt * sizeof (int));
- for (i = 0; i < glyph_cnt; ++i)
- if (class[i] != 0 && info->chars[i] != NULL)
- {
- if (class[i] < class_cnt)
- {
- strcpy (ret[class[i]] + lens[class[i]], info->chars[i]->name);
- lens[class[i]] += strlen (info->chars[i]->name) + 1;
- ret[class[i]][lens[class[i]] - 1] = ' ';
- }
- else
- {
- LogError (_("Class index out of range %d (must be <%d)\n"),
- class[i], class_cnt);
- info->bad_ot = true;
- }
- }
- for (i = 1; i < class_cnt; ++i)
- if (lens[i] == 0)
- ret[i][0] = '\0';
- else
- ret[i][lens[i] - 1] = '\0';
- free (lens);
- return ret;
- }
- static char *
- CoverageMinusClasses (uint16_t *coverageglyphs, uint16_t *classed,
- struct ttfinfo *info)
- {
- int i, j, len;
- uint8_t *glyphs = xcalloc (info->glyph_cnt, sizeof (uint8_t));
- char *ret;
- for (i = 0; coverageglyphs[i] != 0xffff; ++i)
- glyphs[coverageglyphs[i]] = 1;
- for (i = 0; i < info->glyph_cnt; ++i)
- if (classed[i] != 0)
- glyphs[i] = 0;
- for (i = 0; i < info->glyph_cnt; ++i)
- if (glyphs[i] != 0)
- break;
- /* coverage table matches glyphs in classes. No need for special treatment */
- if (i == info->glyph_cnt)
- {
- free (glyphs);
- return NULL;
- }
- /* Otherwise we need to generate a class string of glyph names in the coverage */
- /* table but not in any class. These become the glyphs in class 0 */
- ret = NULL;
- for (j = 0; j < 2; ++j)
- {
- len = 0;
- for (i = 0; i < info->glyph_cnt; ++i)
- {
- if (glyphs[i] != 0)
- {
- if (j)
- {
- strcpy (ret + len, info->chars[i]->name);
- strcat (ret + len, " ");
- }
- len += strlen (info->chars[i]->name) + 1;
- }
- }
- if (j == 0)
- ret = xmalloc (len + 1);
- else
- ret[len - 1] = '\0';
- }
- free (glyphs);
- return ret;
- }
- static int
- ClassFindCnt (uint16_t *class, int tot)
- {
- int i, max = 0;
- for (i = 0; i < tot; ++i)
- if (class[i] > max)
- max = class[i];
- return max + 1;
- }
- static int
- uint16_t_cmp (const void *u1, const void *u2)
- {
- return ((int) *((const uint16_t *) u1)) - ((int) *((const uint16_t *) u2));
- }
- static char *
- GlyphsToNames (struct ttfinfo *info, uint16_t *glyphs, int make_uniq)
- {
- int i, j, len, off;
- char *ret, *pt;
- if (glyphs == NULL)
- return xstrdup ("");
- /* Adobe produces coverage tables containing duplicate glyphs in */
- /* GaramondPremrPro.otf. We want unique glyphs, so enforce that */
- if (make_uniq)
- {
- for (i = 0; glyphs[i] != 0xffff; ++i);
- qsort (glyphs, i, sizeof (uint16_t), uint16_t_cmp);
- for (i = 0; glyphs[i] != 0xffff; ++i)
- {
- if (glyphs[i + 1] == glyphs[i])
- {
- for (j = i + 1; glyphs[j] == glyphs[i]; ++j);
- off = j - i - 1;
- for (j = i + 1;; ++j)
- {
- glyphs[j] = glyphs[j + off];
- if (glyphs[j] == 0xffff)
- break;
- }
- }
- }
- }
- for (i = len = 0; glyphs[i] != 0xffff; ++i)
- {
- if (glyphs[i] >= info->glyph_cnt)
- {
- if (!info->bad_ot)
- {
- LogError (_("Glyph %d out of range [0, %d)"),
- glyphs[i], info->glyph_cnt);
- info->bad_ot = true;
- }
- return xstrdup ("");
- }
- if (info->chars[glyphs[i]] != NULL)
- len += strlen (info->chars[glyphs[i]]->name) + 1;
- }
- ret = pt = xmalloc (len + 1);
- *pt = '\0';
- for (i = 0; glyphs[i] != 0xffff; ++i)
- if (info->chars[glyphs[i]] != NULL)
- {
- strcpy (pt, info->chars[glyphs[i]]->name);
- pt += strlen (pt);
- *pt++ = ' ';
- }
- if (pt > ret)
- pt[-1] = '\0';
- return ret;
- }
- struct language
- { /* normal entry with lang tag 'dflt' */
- uint32_t tag;
- uint32_t offset;
- uint16_t req; /* required feature index. 0xffff for null */
- int fcnt;
- uint16_t *features;
- };
- struct scripts
- {
- uint32_t offset;
- uint32_t tag;
- int langcnt; /* the default language is included as a */
- struct language *languages;
- };
- struct feature
- {
- uint32_t offset;
- uint32_t tag;
- int lcnt;
- uint16_t *lookups;
- };
- struct lookup
- {
- uint16_t type;
- uint32_t flags; /* low order 16 bits: traditional flags, high order: mark filtering set index if pst_usemarkfilteringset */
- uint32_t offset;
- int subtabcnt;
- int32_t *subtab_offsets;
- OTLookup *otlookup;
- };
- static uint16_t *
- getCoverageTable (FILE *ttf, int coverage_offset, struct ttfinfo *info)
- {
- int format, cnt, i, j, rcnt;
- uint16_t *glyphs = NULL;
- int start, end, ind, max;
- fseek (ttf, coverage_offset, SEEK_SET);
- format = getushort (ttf);
- if (format == 1)
- {
- cnt = getushort (ttf);
- glyphs = xmalloc ((cnt + 1) * sizeof (uint16_t));
- if (ftell (ttf) + 2 * cnt > info->g_bounds)
- {
- LogError (_("coverage table extends beyond end of table\n"));
- info->bad_ot = true;
- if (ftell (ttf) > info->g_bounds)
- return NULL;
- cnt = (info->g_bounds - ftell (ttf)) / 2;
- }
- for (i = 0; i < cnt; ++i)
- {
- if (cnt & 0xffff0000)
- {
- LogError (_("Bad count.\n"));
- info->bad_ot = true;
- }
- glyphs[i] = getushort (ttf);
- if (feof (ttf))
- {
- LogError (_("End of file found in coverage table.\n"));
- info->bad_ot = true;
- free (glyphs);
- return NULL;
- }
- if (glyphs[i] >= info->glyph_cnt)
- {
- LogError (_("Bad coverage table. Glyph %d out of range [0, %d)"),
- glyphs[i], info->glyph_cnt);
- info->bad_ot = true;
- glyphs[i] = 0;
- }
- }
- }
- else if (format == 2)
- {
- max = 256;
- glyphs = xcalloc (max, sizeof (uint16_t));
- rcnt = getushort (ttf);
- cnt = 0;
- if (ftell (ttf) + 6 * rcnt > info->g_bounds)
- {
- LogError (_("coverage table extends beyond end of table\n"));
- info->bad_ot = true;
- rcnt = (info->g_bounds - ftell (ttf)) / 6;
- }
- for (i = 0; i < rcnt; ++i)
- {
- start = getushort (ttf);
- end = getushort (ttf);
- ind = getushort (ttf);
- if (feof (ttf))
- {
- LogError (_("End of file found in coverage table.\n"));
- info->bad_ot = true;
- free (glyphs);
- return NULL;
- }
- if (start > end || end >= info->glyph_cnt)
- {
- LogError (_("Bad coverage table. "
- "Glyph range %d-%d out of range [0, %d)"),
- start, end, info->glyph_cnt);
- info->bad_ot = true;
- start = end = 0;
- }
- if (ind + end - start + 2 >= max)
- {
- int oldmax = max;
- max = ind + end - start + 2;
- glyphs = xrealloc (glyphs, max * sizeof (uint16_t));
- memset (glyphs + oldmax, 0, (max - oldmax) * sizeof (uint16_t));
- }
- for (j = start; j <= end; ++j)
- {
- glyphs[j - start + ind] = j;
- if (j >= info->glyph_cnt)
- glyphs[j - start + ind] = 0;
- }
- if (ind + end - start + 1 > cnt)
- cnt = ind + end - start + 1;
- }
- }
- else
- {
- LogError (_("Bad format for coverage table %d\n"), format);
- info->bad_ot = true;
- return NULL;
- }
- glyphs[cnt] = 0xffff;
- return glyphs;
- }
- struct valuerecord
- {
- int16_t xplacement, yplacement;
- int16_t xadvance, yadvance;
- uint16_t offXplaceDev, offYplaceDev;
- uint16_t offXadvanceDev, offYadvanceDev;
- };
- static uint16_t *
- getClassDefTable (FILE *ttf, int classdef_offset, struct ttfinfo *info)
- {
- int format, i, j;
- uint16_t start, glyphcnt, rangecnt, end, class;
- uint16_t *glist = NULL;
- int warned = false;
- int cnt = info->glyph_cnt;
- uint32_t g_bounds = info->g_bounds;
- fseek (ttf, classdef_offset, SEEK_SET);
- glist = xcalloc (cnt, sizeof (uint16_t)); /* Class 0 is default */
- format = getushort (ttf);
- if (format == 1)
- {
- start = getushort (ttf);
- glyphcnt = getushort (ttf);
- if (start + (int) glyphcnt > cnt)
- {
- LogError (_("Bad class def table. start=%d cnt=%d, max glyph=%d\n"),
- start, glyphcnt, cnt);
- info->bad_ot = true;
- glyphcnt = cnt - start;
- }
- else if (ftell (ttf) + 2 * glyphcnt > g_bounds)
- {
- LogError (_
- ("Class definition sub-table extends beyond end of table\n"));
- info->bad_ot = true;
- glyphcnt = (g_bounds - ftell (ttf)) / 2;
- }
- for (i = 0; i < glyphcnt; ++i)
- glist[start + i] = getushort (ttf);
- }
- else if (format == 2)
- {
- rangecnt = getushort (ttf);
- if (ftell (ttf) + 6 * rangecnt > g_bounds)
- {
- LogError (_
- ("Class definition sub-table extends beyond end of table\n"));
- info->bad_ot = true;
- rangecnt = (g_bounds - ftell (ttf)) / 6;
- }
- for (i = 0; i < rangecnt; ++i)
- {
- start = getushort (ttf);
- end = getushort (ttf);
- if (start > end || end >= cnt)
- {
- LogError (_("Bad class def table. "
- "Glyph range %d-%d out of range [0, %d)"),
- start, end, cnt);
- info->bad_ot = true;
- }
- class = getushort (ttf);
- for (j = start; j <= end; ++j)
- if (j < cnt)
- glist[j] = class;
- }
- }
- else
- {
- LogError (_("Unknown class table format: %d\n"), format);
- info->bad_ot = true;
- /* Put everything in class 0 and return that */
- }
- /* Do another validity test */
- for (i = 0; i < cnt; ++i)
- {
- if (glist[i] >= cnt + 1)
- {
- if (!warned)
- {
- LogError (_
- ("Nonsensical class assigned to a glyph-- class=%d is too big. Glyph=%d\n"),
- glist[i], i);
- info->bad_ot = true;
- warned = true;
- }
- glist[i] = 0;
- }
- }
- return glist;
- }
- static void
- readvaluerecord (struct valuerecord *vr, int vf, FILE *ttf)
- {
- memset (vr, '\0', sizeof (struct valuerecord));
- if (vf & 1)
- vr->xplacement = getushort (ttf);
- if (vf & 2)
- vr->yplacement = getushort (ttf);
- if (vf & 4)
- vr->xadvance = getushort (ttf);
- if (vf & 8)
- vr->yadvance = getushort (ttf);
- if (vf & 0x10)
- vr->offXplaceDev = getushort (ttf);
- if (vf & 0x20)
- vr->offYplaceDev = getushort (ttf);
- if (vf & 0x40)
- vr->offXadvanceDev = getushort (ttf);
- if (vf & 0x80)
- vr->offYadvanceDev = getushort (ttf);
- }
- static void
- ReadDeviceTable (FILE *ttf, DeviceTable *adjust, uint32_t devtab,
- struct ttfinfo *info)
- {
- long here;
- int pack;
- int w, b, i, c;
- if (devtab == 0)
- return;
- here = ftell (ttf);
- fseek (ttf, devtab, SEEK_SET);
- adjust->first_pixel_size = getushort (ttf);
- adjust->last_pixel_size = getushort (ttf);
- pack = getushort (ttf);
- if (adjust->first_pixel_size > adjust->last_pixel_size || pack == 0
- || pack > 3)
- {
- LogError (_("Bad device table\n"));
- info->bad_ot = true;
- adjust->first_pixel_size = adjust->last_pixel_size = 0;
- }
- else
- {
- c = adjust->last_pixel_size - adjust->first_pixel_size + 1;
- adjust->corrections = xmalloc (c);
- if (pack == 1)
- {
- for (i = 0; i < c; i += 8)
- {
- w = getushort (ttf);
- for (b = 0; b < 8 && i + b < c; ++b)
- adjust->corrections[i + b] =
- ((int16_t) ((w << (b * 2)) & 0xc000)) >> 14;
- }
- }
- else if (pack == 2)
- {
- for (i = 0; i < c; i += 4)
- {
- w = getushort (ttf);
- for (b = 0; b < 4 && i + b < c; ++b)
- adjust->corrections[i + b] =
- ((int16_t) ((w << (b * 4)) & 0xf000)) >> 12;
- }
- }
- else
- {
- for (i = 0; i < c; ++i)
- adjust->corrections[i] = (int8_t) getc (ttf);
- }
- }
- fseek (ttf, here, SEEK_SET);
- }
- static ValDevTab *
- readValDevTab (FILE *ttf, struct valuerecord *vr, uint32_t base,
- struct ttfinfo *info)
- {
- ValDevTab *ret;
- if (vr->offXplaceDev == 0 && vr->offYplaceDev == 0 &&
- vr->offXadvanceDev == 0 && vr->offYadvanceDev == 0)
- return NULL;
- ret = xzalloc (sizeof (ValDevTab));
- if (vr->offXplaceDev != 0)
- ReadDeviceTable (ttf, &ret->xadjust, base + vr->offXplaceDev, info);
- if (vr->offYplaceDev != 0)
- ReadDeviceTable (ttf, &ret->yadjust, base + vr->offYplaceDev, info);
- if (vr->offXadvanceDev != 0)
- ReadDeviceTable (ttf, &ret->xadv, base + vr->offXadvanceDev, info);
- if (vr->offYadvanceDev != 0)
- ReadDeviceTable (ttf, &ret->yadv, base + vr->offYadvanceDev, info);
- return ret;
- }
- static void
- addPairPos (struct ttfinfo *info, int glyph1, int glyph2,
- struct lookup *l, struct lookup_subtable *subtable,
- struct valuerecord *vr1, struct valuerecord *vr2, uint32_t base,
- FILE *ttf)
- {
- if (glyph1 < info->glyph_cnt && glyph2 < info->glyph_cnt &&
- info->chars[glyph1] != NULL && info->chars[glyph2] != NULL)
- {
- PST *pos = xzalloc (sizeof (PST));
- pos->type = pst_pair;
- pos->subtable = subtable;
- pos->next = info->chars[glyph1]->possub;
- info->chars[glyph1]->possub = pos;
- pos->u.pair.vr = xzalloc (sizeof (ValueRecord[2]));
- pos->u.pair.paired = xstrdup_or_null (info->chars[glyph2]->name);
- pos->u.pair.vr[0].xoff = vr1->xplacement;
- pos->u.pair.vr[0].yoff = vr1->yplacement;
- pos->u.pair.vr[0].h_adv_off = vr1->xadvance;
- pos->u.pair.vr[0].v_adv_off = vr1->yadvance;
- pos->u.pair.vr[1].xoff = vr2->xplacement;
- pos->u.pair.vr[1].yoff = vr2->yplacement;
- pos->u.pair.vr[1].h_adv_off = vr2->xadvance;
- pos->u.pair.vr[1].v_adv_off = vr2->yadvance;
- pos->u.pair.vr[0].adjust = readValDevTab (ttf, vr1, base, info);
- pos->u.pair.vr[1].adjust = readValDevTab (ttf, vr2, base, info);
- }
- else
- {
- LogError (_("Bad pair position: glyphs %d & %d should have been < %d\n"),
- glyph1, glyph2, info->glyph_cnt);
- info->bad_ot = true;
- }
- }
- static void
- gposKernSubTable (FILE *ttf, int stoffset, struct ttfinfo *info,
- struct lookup *l, struct lookup_subtable *subtable)
- {
- int coverage, cnt, pair_cnt, vf1, vf2, glyph2;
- int cd1, cd2, c1_cnt, c2_cnt;
- uint16_t format;
- uint16_t *ps_offsets;
- uint16_t *glyphs, *class1, *class2;
- struct valuerecord vr1, vr2;
- long foffset;
- format = getushort (ttf);
- if (format != 1 && format != 2) /* Unknown subtable format */
- return;
- coverage = getushort (ttf);
- vf1 = getushort (ttf);
- vf2 = getushort (ttf);
- if (format == 1)
- {
- subtable->per_glyph_pst_or_kern = true;
- cnt = getushort (ttf);
- ps_offsets = xmalloc (cnt * sizeof (uint16_t));
- for (int i = 0; i < cnt; ++i)
- ps_offsets[i] = getushort (ttf);
- glyphs = getCoverageTable (ttf, stoffset + coverage, info);
- if (glyphs == NULL)
- {
- /* TRANSLATORS: This continues a multi-line error message, hence the leading space */
- LogError (_(" Bad pairwise kerning table, ignored\n"));
- return;
- }
- for (int i = 0; i < cnt; ++i)
- if (glyphs[i] < info->glyph_cnt)
- {
- fseek (ttf, stoffset + ps_offsets[i], SEEK_SET);
- pair_cnt = getushort (ttf);
- for (int j = 0; j < pair_cnt; ++j)
- {
- glyph2 = getushort (ttf);
- readvaluerecord (&vr1, vf1, ttf);
- readvaluerecord (&vr2, vf2, ttf);
- addPairPos (info, glyphs[i], glyph2, l, subtable, &vr1, &vr2,
- stoffset, ttf);
- }
- }
- free (ps_offsets);
- free (glyphs);
- }
- else if (format == 2)
- { /* Class-based kerning */
- cd1 = getushort (ttf);
- cd2 = getushort (ttf);
- foffset = ftell (ttf);
- class1 = getClassDefTable (ttf, stoffset + cd1, info);
- class2 = getClassDefTable (ttf, stoffset + cd2, info);
- glyphs = getCoverageTable (ttf, stoffset + coverage, info);
- if (glyphs == NULL)
- {
- /* TRANSLATORS: This continues a multi-line error message, hence the leading space */
- LogError (_(" Bad kerning class table, ignored\n"));
- return;
- }
- fseek (ttf, foffset, SEEK_SET); /* come back */
- c1_cnt = getushort (ttf);
- c2_cnt = getushort (ttf);
- subtable->per_glyph_pst_or_kern = true;
- // TODO: read this as class kerning instead of expanding it as we do now.
- for (int i = 0; i < c1_cnt; ++i)
- {
- for (int j = 0; j < c2_cnt; ++j)
- {
- readvaluerecord (&vr1, vf1, ttf);
- readvaluerecord (&vr2, vf2, ttf);
- if (vr1.xadvance != 0 || vr1.xplacement != 0
- || vr1.yadvance != 0 || vr1.yplacement != 0
- || vr2.xadvance != 0 || vr2.xplacement != 0
- || vr2.yadvance != 0 || vr2.yplacement != 0)
- for (int k = 0; glyphs[k] != 0xffff; ++k)
- if (class1[glyphs[k]] == i)
- for (int m = 0; m < info->glyph_cnt; ++m)
- if (class2[m] == j)
- addPairPos (info, glyphs[k], m, l, subtable, &vr1, &vr2,
- stoffset, ttf);
- }
- }
- free (class1);
- free (class2);
- free (glyphs);
- }
- }
- static AnchorPoint *
- readAnchorPoint (FILE *ttf, uint32_t base, AnchorClass * class,
- enum anchor_type type, AnchorPoint *last, struct ttfinfo *info)
- {
- AnchorPoint *ap;
- int format;
- fseek (ttf, base, SEEK_SET);
- ap = xzalloc (sizeof (AnchorPoint));
- ap->anchor = class;
- /* All anchor types have the same initial 3 entries, format */
- /* x,y pos. format 2 contains a truetype positioning point, and */
- /* format==3 may also have device tables */
- format = getushort (ttf);
- ap->me.x = (int16_t) getushort (ttf);
- ap->me.y = (int16_t) getushort (ttf);
- ap->type = type;
- if (format == 2)
- {
- ap->ttf_pt_index = getushort (ttf);
- ap->has_ttf_pt = true;
- }
- else if (format == 3)
- {
- int devoff;
- devoff = getushort (ttf);
- if (devoff != 0)
- ReadDeviceTable (ttf, &ap->xadjust, base + devoff, info);
- devoff = getushort (ttf);
- if (devoff != 0)
- ReadDeviceTable (ttf, &ap->yadjust, base + devoff, info);
- }
- ap->next = last;
- return ap;
- }
- static void
- gposCursiveSubTable (FILE *ttf, int stoffset, struct ttfinfo *info,
- struct lookup *l, struct lookup_subtable *subtable)
- {
- int coverage, cnt, format, i;
- struct ee_offsets
- {
- int entry, exit;
- } *offsets;
- uint16_t *glyphs;
- AnchorClass *class;
- SplineChar *sc;
- char buf[50];
- format = getushort (ttf);
- if (format != 1) /* Unknown subtable format */
- return;
- coverage = getushort (ttf);
- cnt = getushort (ttf);
- if (cnt == 0)
- return;
- offsets = xmalloc (cnt * sizeof (struct ee_offsets));
- for (i = 0; i < cnt; ++i)
- {
- offsets[i].entry = getushort (ttf);
- offsets[i].exit = getushort (ttf);
- }
- glyphs = getCoverageTable (ttf, stoffset + coverage, info);
- if (glyphs == NULL)
- {
- /* TRANSLATORS: This continues a multi-line error message, hence the leading space */
- LogError (_(" Bad cursive alignment table, ignored\n"));
- free (offsets);
- return;
- }
- class = xzalloc (sizeof (AnchorClass));
- snprintf (buf, sizeof (buf), _("Cursive-%d"), info->anchor_class_cnt++);
- class->name = xstrdup_or_null (buf);
- subtable->anchor_classes = true;
- class->subtable = subtable;
- if (info->ahead == NULL)
- info->ahead = class;
- else
- info->alast->next = class;
- info->alast = class;
- for (i = 0; i < cnt; ++i)
- {
- sc = info->chars[glyphs[i]];
- if (offsets[i].entry != 0)
- {
- sc->anchor = readAnchorPoint (ttf, stoffset + offsets[i].entry, class,
- at_centry, sc->anchor, info);
- }
- if (offsets[i].exit != 0)
- {
- sc->anchor = readAnchorPoint (ttf, stoffset + offsets[i].exit, class,
- at_cexit, sc->anchor, info);
- }
- }
- free (offsets);
- free (glyphs);
- }
- static AnchorClass **
- MarkGlyphsProcessMarks (FILE *ttf, int markoffset,
- struct ttfinfo *info, struct lookup *l,
- struct lookup_subtable *subtable, uint16_t *markglyphs,
- int classcnt)
- {
- AnchorClass **classes = xcalloc (classcnt, sizeof (AnchorClass *)), *ac;
- char buf[50];
- int i, cnt;
- struct mr
- {
- uint16_t class, offset;
- } *at_offsets;
- SplineChar *sc;
- for (i = 0; i < classcnt; ++i)
- {
- snprintf (buf, sizeof (buf), _("Anchor-%d"), info->anchor_class_cnt + i);
- classes[i] = ac = xzalloc (sizeof (AnchorClass));
- ac->name = xstrdup_or_null (buf);
- subtable->anchor_classes = true;
- ac->subtable = subtable;
- /*ac->merge_with = info->anchor_merge_cnt+1; */
- /* I don't distinguish between mark to base and mark to lig */
- if (info->ahead == NULL)
- info->ahead = ac;
- else
- info->alast->next = ac;
- info->alast = ac;
- }
- fseek (ttf, markoffset, SEEK_SET);
- cnt = getushort (ttf);
- if (feof (ttf))
- {
- LogError (_("Bad mark table.\n"));
- info->bad_ot = true;
- return NULL;
- }
- at_offsets = xmalloc (cnt * sizeof (struct mr));
- for (i = 0; i < cnt; ++i)
- {
- at_offsets[i].class = getushort (ttf);
- at_offsets[i].offset = getushort (ttf);
- if (at_offsets[i].class >= classcnt)
- {
- at_offsets[i].class = 0;
- if (markglyphs[i] >= info->glyph_cnt)
- LogError (_("Class out of bounds in GPOS mark sub-table\n"));
- else
- LogError (_
- ("Class out of bounds in GPOS mark sub-table for mark %.30s\n"),
- info->chars[markglyphs[i]]->name);
- info->bad_ot = true;
- }
- }
- for (i = 0; i < cnt; ++i)
- {
- if (markglyphs[i] >= info->glyph_cnt)
- continue;
- sc = info->chars[markglyphs[i]];
- if (sc == NULL || at_offsets[i].offset == 0)
- continue;
- sc->anchor = readAnchorPoint (ttf, markoffset + at_offsets[i].offset,
- classes[at_offsets[i].class], at_mark,
- sc->anchor, info);
- }
- free (at_offsets);
- return classes;
- }
- static void
- MarkGlyphsProcessBases (FILE *ttf, int baseoffset,
- struct ttfinfo *info, struct lookup *l,
- struct lookup_subtable *subtable, uint16_t *baseglyphs,
- int classcnt, AnchorClass ** classes,
- enum anchor_type at)
- {
- int basecnt, i, j, ibase;
- uint16_t *offsets;
- SplineChar *sc;
- fseek (ttf, baseoffset, SEEK_SET);
- basecnt = getushort (ttf);
- if (feof (ttf))
- {
- LogError (_("Bad base table.\n"));
- info->bad_ot = true;
- return;
- }
- offsets = xmalloc (basecnt * classcnt * sizeof (uint16_t));
- for (i = 0; i < basecnt * classcnt; ++i)
- offsets[i] = getushort (ttf);
- for (i = ibase = 0; i < basecnt; ++i, ibase += classcnt)
- {
- if (baseglyphs[i] >= info->glyph_cnt)
- continue;
- sc = info->chars[baseglyphs[i]];
- if (sc == NULL)
- continue;
- for (j = 0; j < classcnt; ++j)
- if (offsets[ibase + j] != 0)
- {
- sc->anchor = readAnchorPoint (ttf, baseoffset + offsets[ibase + j],
- classes[j], at, sc->anchor, info);
- }
- }
- free (offsets);
- }
- static void
- MarkGlyphsProcessLigs (FILE *ttf, int baseoffset,
- struct ttfinfo *info, struct lookup *l,
- struct lookup_subtable *subtable, uint16_t *baseglyphs,
- int classcnt, AnchorClass ** classes)
- {
- int basecnt, compcnt, i, j, k, kbase;
- uint16_t *loffsets, *aoffsets;
- SplineChar *sc;
- fseek (ttf, baseoffset, SEEK_SET);
- basecnt = getushort (ttf);
- if (feof (ttf))
- {
- LogError (_("Bad ligature base table.\n"));
- info->bad_ot = true;
- return;
- }
- loffsets = xmalloc (basecnt * sizeof (uint16_t));
- for (i = 0; i < basecnt; ++i)
- loffsets[i] = getushort (ttf);
- for (i = 0; i < basecnt; ++i)
- {
- sc = info->chars[baseglyphs[i]];
- if (baseglyphs[i] >= info->glyph_cnt || sc == NULL)
- continue;
- fseek (ttf, baseoffset + loffsets[i], SEEK_SET);
- compcnt = getushort (ttf);
- if (feof (ttf))
- {
- LogError (_("Bad ligature anchor count.\n"));
- info->bad_ot = true;
- continue;
- }
- aoffsets = xmalloc (compcnt * classcnt * sizeof (uint16_t));
- for (k = 0; k < compcnt * classcnt; ++k)
- aoffsets[k] = getushort (ttf);
- for (k = kbase = 0; k < compcnt; ++k, kbase += classcnt)
- {
- for (j = 0; j < classcnt; ++j)
- if (aoffsets[kbase + j] != 0)
- {
- sc->anchor =
- readAnchorPoint (ttf,
- baseoffset + loffsets[i] + aoffsets[kbase +
- j],
- classes[j], at_baselig, sc->anchor, info);
- sc->anchor->lig_index = k;
- }
- }
- free (aoffsets);
- }
- free (loffsets);
- }
- static void
- gposMarkSubTable (FILE *ttf, uint32_t stoffset,
- struct ttfinfo *info, struct lookup *l,
- struct lookup_subtable *subtable)
- {
- int markcoverage, basecoverage, classcnt, markoffset, baseoffset;
- uint16_t *markglyphs, *baseglyphs;
- AnchorClass **classes;
- /* The header for the three different mark tables is the same */
- /* Type = */ getushort (ttf);
- markcoverage = getushort (ttf);
- basecoverage = getushort (ttf);
- classcnt = getushort (ttf);
- markoffset = getushort (ttf);
- baseoffset = getushort (ttf);
- markglyphs = getCoverageTable (ttf, stoffset + markcoverage, info);
- baseglyphs = getCoverageTable (ttf, stoffset + basecoverage, info);
- if (baseglyphs == NULL || markglyphs == NULL)
- {
- free (baseglyphs);
- free (markglyphs);
- LogError (_(" Bad mark attachment table, ignored\n"));
- return;
- }
- /* as is the (first) mark table */
- classes = MarkGlyphsProcessMarks (ttf, stoffset + markoffset,
- info, l, subtable, markglyphs, classcnt);
- if (classes == NULL)
- return;
- switch (l->otlookup->lookup_type)
- {
- case gpos_mark2base:
- case gpos_mark2mark:
- MarkGlyphsProcessBases (ttf, stoffset + baseoffset,
- info, l, subtable, baseglyphs, classcnt, classes,
- l->otlookup->lookup_type ==
- gpos_mark2base ? at_basechar : at_basemark);
- break;
- case gpos_mark2ligature:
- MarkGlyphsProcessLigs (ttf, stoffset + baseoffset,
- info, l, subtable, baseglyphs, classcnt, classes);
- break;
- }
- info->anchor_class_cnt += classcnt;
- ++info->anchor_merge_cnt;
- free (markglyphs);
- free (baseglyphs);
- free (classes);
- }
- static void
- gposSimplePos (FILE *ttf, int stoffset, struct ttfinfo *info,
- struct lookup *l, struct lookup_subtable *subtable)
- {
- int coverage, cnt, i, vf;
- uint16_t format;
- uint16_t *glyphs;
- struct valuerecord *vr = NULL, _vr, *which;
- format = getushort (ttf);
- if (format != 1 && format != 2) /* Unknown subtable format */
- return;
- coverage = getushort (ttf);
- vf = getushort (ttf);
- if (vf == 0)
- return;
- if (format == 1)
- {
- memset (&_vr, 0, sizeof (_vr));
- readvaluerecord (&_vr, vf, ttf);
- }
- else
- {
- cnt = getushort (ttf);
- vr = xcalloc (cnt, sizeof (struct valuerecord));
- for (i = 0; i < cnt; ++i)
- readvaluerecord (&vr[i], vf, ttf);
- }
- glyphs = getCoverageTable (ttf, stoffset + coverage, info);
- if (glyphs == NULL)
- {
- free (vr);
- LogError (_(" Bad simple positioning table, ignored\n"));
- return;
- }
- for (i = 0; glyphs[i] != 0xffff; ++i)
- if (glyphs[i] < info->glyph_cnt && info->chars[glyphs[i]] != NULL)
- {
- PST *pos = xzalloc (sizeof (PST));
- pos->type = pst_position;
- pos->subtable = subtable;
- pos->next = info->chars[glyphs[i]]->possub;
- info->chars[glyphs[i]]->possub = pos;
- which = format == 1 ? &_vr : &vr[i];
- pos->u.pos.xoff = which->xplacement;
- pos->u.pos.yoff = which->yplacement;
- pos->u.pos.h_adv_off = which->xadvance;
- pos->u.pos.v_adv_off = which->yadvance;
- pos->u.pos.adjust = readValDevTab (ttf, which, stoffset, info);
- }
- subtable->per_glyph_pst_or_kern = true;
- free (vr);
- free (glyphs);
- }
- static void
- ProcessSubLookups (FILE *ttf, struct ttfinfo *info, int gpos,
- struct lookup *alllooks, struct seqlookup *sl)
- {
- int i;
- i = (intptr_t) sl->lookup;
- if (i < 0 || i >= info->lookup_cnt)
- {
- LogError (_
- ("Attempt to reference lookup %d (within a contextual lookup), but there are\n only %d lookups in %s\n"),
- i, info->lookup_cnt, gpos ? "'GPOS'" : "'GSUB'");
- info->bad_ot = true;
- sl->lookup = NULL;
- return;
- }
- sl->lookup = alllooks[i].otlookup;
- }
- static void
- g___ContextSubTable1 (FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l,
- struct lookup_subtable *subtable, int justinuse,
- struct lookup *alllooks, int gpos)
- {
- int i, j, k, rcnt, cnt;
- uint16_t coverage;
- uint16_t *glyphs;
- struct subrule
- {
- uint32_t offset;
- int gcnt;
- int scnt;
- uint16_t *glyphs;
- struct seqlookup *sl;
- };
- struct rule
- {
- uint32_t offsets;
- int scnt;
- struct subrule *subrules;
- } *rules;
- FPST *fpst;
- struct fpst_rule *rule;
- int warned = false, warned2 = false;
- coverage = getushort (ttf);
- rcnt = getushort (ttf); /* glyph count in coverage table */
- rules = xmalloc (rcnt * sizeof (struct rule));
- for (i = 0; i < rcnt; ++i)
- rules[i].offsets = getushort (ttf) + stoffset;
- glyphs = getCoverageTable (ttf, stoffset + coverage, info);
- if (glyphs == NULL)
- {
- /* TRANSLATORS: This continues a multi-line error message, hence the leading space */
- LogError (_(" Bad contextual table, ignored\n"));
- return;
- }
- cnt = 0;
- for (i = 0; i < rcnt; ++i)
- {
- fseek (ttf, rules[i].offsets, SEEK_SET);
- rules[i].scnt = getushort (ttf);
- cnt += rules[i].scnt;
- rules[i].subrules = xmalloc (rules[i].scnt * sizeof (struct subrule));
- for (j = 0; j < rules[i].scnt; ++j)
- rules[i].subrules[j].offset = getushort (ttf) + rules[i].offsets;
- for (j = 0; j < rules[i].scnt; ++j)
- {
- fseek (ttf, rules[i].subrules[j].offset, SEEK_SET);
- rules[i].subrules[j].gcnt = getushort (ttf);
- rules[i].subrules[j].scnt = getushort (ttf);
- rules[i].subrules[j].glyphs =
- xmalloc ((rules[i].subrules[j].gcnt + 1) * sizeof (uint16_t));
- rules[i].subrules[j].glyphs[0] = glyphs[i];
- for (k = 1; k < rules[i].subrules[j].gcnt; ++k)
- {
- rules[i].subrules[j].glyphs[k] = getushort (ttf);
- if (rules[i].subrules[j].glyphs[k] >= info->glyph_cnt)
- {
- if (!warned)
- LogError (_("Bad contextual or chaining sub table. "
- "Glyph %d out of range [0, %d)"),
- rules[i].subrules[j].glyphs[k], info->glyph_cnt);
- info->bad_ot = true;
- warned = true;
- rules[i].subrules[j].glyphs[k] = 0;
- }
- }
- rules[i].subrules[j].glyphs[k] = 0xffff;
- rules[i].subrules[j].sl =
- xmalloc (rules[i].subrules[j].scnt * sizeof (struct seqlookup));
- for (k = 0; k < rules[i].subrules[j].scnt; ++k)
- {
- rules[i].subrules[j].sl[k].seq = getushort (ttf);
- if (rules[i].subrules[j].sl[k].seq >=
- rules[i].subrules[j].gcnt + 1)
- if (!warned2)
- {
- LogError (_
- ("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d max=%d\n"),
- rules[i].subrules[j].sl[k].seq,
- rules[i].subrules[j].gcnt);
- info->bad_ot = true;
- warned2 = true;
- }
- rules[i].subrules[j].sl[k].lookup =
- (void *) (intptr_t) getushort (ttf);
- }
- }
- }
- if (justinuse == git_justinuse)
- {
- /* Nothing to do. This lookup doesn't really reference any glyphs */
- /* any lookups it invokes will be processed on their own */
- }
- else
- {
- fpst = xzalloc (sizeof (FPST));
- fpst->type = gpos ? pst_contextpos : pst_contextsub;
- fpst->format = pst_glyphs;
- fpst->subtable = subtable;
- fpst->next = info->possub;
- info->possub = fpst;
- subtable->fpst = fpst;
- fpst->rules = rule = xcalloc (cnt, sizeof (struct fpst_rule));
- fpst->rule_cnt = cnt;
- cnt = 0;
- for (i = 0; i < rcnt; ++i)
- for (j = 0; j < rules[i].scnt; ++j)
- {
- rule[cnt].u.glyph.names =
- GlyphsToNames (info, rules[i].subrules[j].glyphs, false);
- rule[cnt].lookup_cnt = rules[i].subrules[j].scnt;
- rule[cnt].lookups = rules[i].subrules[j].sl;
- rules[i].subrules[j].sl = NULL;
- for (k = 0; k < rule[cnt].lookup_cnt; ++k)
- ProcessSubLookups (ttf, info, gpos, alllooks,
- &rule[cnt].lookups[k]);
- ++cnt;
- }
- }
- for (i = 0; i < rcnt; ++i)
- {
- for (j = 0; j < rules[i].scnt; ++j)
- {
- free (rules[i].subrules[j].glyphs);
- free (rules[i].subrules[j].sl);
- }
- free (rules[i].subrules);
- }
- free (rules);
- free (glyphs);
- }
- static void
- g___ChainingSubTable1 (FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l,
- struct lookup_subtable *subtable, int justinuse,
- struct lookup *alllooks, int gpos)
- {
- int i, j, k, rcnt, cnt, which;
- uint16_t coverage;
- uint16_t *glyphs;
- struct subrule
- {
- uint32_t offset;
- int gcnt, bcnt, fcnt;
- int scnt;
- uint16_t *glyphs, *bglyphs, *fglyphs;
- struct seqlookup *sl;
- };
- struct rule
- {
- uint32_t offsets;
- int scnt;
- struct subrule *subrules;
- } *rules;
- FPST *fpst;
- struct fpst_rule *rule;
- int warned = false, warned2 = false;
- coverage = getushort (ttf);
- rcnt = getushort (ttf); /* glyph count in coverage table */
- rules = xmalloc (rcnt * sizeof (struct rule));
- for (i = 0; i < rcnt; ++i)
- rules[i].offsets = getushort (ttf) + stoffset;
- glyphs = getCoverageTable (ttf, stoffset + coverage, info);
- if (glyphs == NULL)
- {
- free (rules);
- LogError (_(" Bad contextual chaining table, ignored\n"));
- return;
- }
- cnt = 0;
- for (i = 0; i < rcnt; ++i)
- {
- fseek (ttf, rules[i].offsets, SEEK_SET);
- rules[i].scnt = getushort (ttf);
- cnt += rules[i].scnt;
- rules[i].subrules = xmalloc (rules[i].scnt * sizeof (struct subrule));
- for (j = 0; j < rules[i].scnt; ++j)
- rules[i].subrules[j].offset = getushort (ttf) + rules[i].offsets;
- for (j = 0; j < rules[i].scnt; ++j)
- {
- fseek (ttf, rules[i].subrules[j].offset, SEEK_SET);
- rules[i].subrules[j].bcnt = getushort (ttf);
- if (feof (ttf))
- {
- LogError (_
- ("Unexpected end of file in contextual chaining subtable.\n"));
- info->bad_ot = true;
- return;
- }
- rules[i].subrules[j].bglyphs =
- xmalloc ((rules[i].subrules[j].bcnt + 1) * sizeof (uint16_t));
- for (k = 0; k < rules[i].subrules[j].bcnt; ++k)
- rules[i].subrules[j].bglyphs[k] = getushort (ttf);
- rules[i].subrules[j].bglyphs[k] = 0xffff;
- rules[i].subrules[j].gcnt = getushort (ttf);
- if (feof (ttf))
- {
- LogError (_
- ("Unexpected end of file in contextual chaining subtable.\n"));
- info->bad_ot = true;
- return;
- }
- rules[i].subrules[j].glyphs =
- xmalloc ((rules[i].subrules[j].gcnt + 1) * sizeof (uint16_t));
- rules[i].subrules[j].glyphs[0] = glyphs[i];
- for (k = 1; k < rules[i].subrules[j].gcnt; ++k)
- rules[i].subrules[j].glyphs[k] = getushort (ttf);
- rules[i].subrules[j].glyphs[k] = 0xffff;
- rules[i].subrules[j].fcnt = getushort (ttf);
- if (feof (ttf))
- {
- LogError (_
- ("Unexpected end of file in contextual chaining subtable.\n"));
- info->bad_ot = true;
- return;
- }
- rules[i].subrules[j].fglyphs =
- xmalloc ((rules[i].subrules[j].fcnt + 1) * sizeof (uint16_t));
- for (k = 0; k < rules[i].subrules[j].fcnt; ++k)
- rules[i].subrules[j].fglyphs[k] = getushort (ttf);
- rules[i].subrules[j].fglyphs[k] = 0xffff;
- for (which = 0; which < 3; ++which)
- {
- for (k = 0; k < (&rules[i].subrules[j].gcnt)[which]; ++k)
- {
- if ((&rules[i].subrules[j].glyphs)[which][k] >=
- info->glyph_cnt)
- {
- if (!warned)
- LogError (_("Bad contextual or chaining sub table. "
- "Glyph %d out of range [0, %d)"),
- (&rules[i].subrules[j].glyphs)[which][k],
- info->glyph_cnt);
- info->bad_ot = true;
- warned = true;
- (&rules[i].subrules[j].glyphs)[which][k] = 0;
- }
- }
- }
- rules[i].subrules[j].scnt = getushort (ttf);
- if (feof (ttf))
- {
- LogError (_
- ("Unexpected end of file in contextual chaining subtable.\n"));
- info->bad_ot = true;
- return;
- }
- rules[i].subrules[j].sl =
- xmalloc (rules[i].subrules[j].scnt * sizeof (struct seqlookup));
- for (k = 0; k < rules[i].subrules[j].scnt; ++k)
- {
- rules[i].subrules[j].sl[k].seq = getushort (ttf);
- if (rules[i].subrules[j].sl[k].seq >=
- rules[i].subrules[j].gcnt + 1)
- if (!warned2)
- {
- LogError (_
- ("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d max=%d\n"),
- rules[i].subrules[j].sl[k].seq,
- rules[i].subrules[j].gcnt);
- info->bad_ot = true;
- warned2 = true;
- }
- rules[i].subrules[j].sl[k].lookup =
- (void *) (intptr_t) getushort (ttf);
- }
- }
- }
- if (justinuse == git_justinuse)
- {
- /* Nothing to do. This lookup doesn't really reference any glyphs */
- /* any lookups it invokes will be processed on their own */
- }
- else
- {
- fpst = xzalloc (sizeof (FPST));
- fpst->type = gpos ? pst_chainpos : pst_chainsub;
- fpst->format = pst_glyphs;
- fpst->subtable = subtable;
- fpst->next = info->possub;
- info->possub = fpst;
- subtable->fpst = fpst;
- fpst->rules = rule = xcalloc (cnt, sizeof (struct fpst_rule));
- fpst->rule_cnt = cnt;
- cnt = 0;
- for (i = 0; i < rcnt; ++i)
- for (j = 0; j < rules[i].scnt; ++j)
- {
- rule[cnt].u.glyph.back =
- GlyphsToNames (info, rules[i].subrules[j].bglyphs, false);
- rule[cnt].u.glyph.names =
- GlyphsToNames (info, rules[i].subrules[j].glyphs, false);
- rule[cnt].u.glyph.fore =
- GlyphsToNames (info, rules[i].subrules[j].fglyphs, false);
- rule[cnt].lookup_cnt = rules[i].subrules[j].scnt;
- rule[cnt].lookups = rules[i].subrules[j].sl;
- rules[i].subrules[j].sl = NULL;
- for (k = 0; k < rule[cnt].lookup_cnt; ++k)
- ProcessSubLookups (ttf, info, gpos, alllooks,
- &rule[cnt].lookups[k]);
- ++cnt;
- }
- }
- for (i = 0; i < rcnt; ++i)
- {
- for (j = 0; j < rules[i].scnt; ++j)
- {
- free (rules[i].subrules[j].bglyphs);
- free (rules[i].subrules[j].glyphs);
- free (rules[i].subrules[j].fglyphs);
- free (rules[i].subrules[j].sl);
- }
- free (rules[i].subrules);
- }
- free (rules);
- free (glyphs);
- }
- static void
- g___ContextSubTable2 (FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l,
- struct lookup_subtable *subtable, int justinuse,
- struct lookup *alllooks, int gpos)
- {
- int i, j, k, rcnt, cnt;
- uint16_t coverage;
- uint16_t classoff;
- struct subrule
- {
- uint32_t offset;
- int ccnt;
- int scnt;
- uint16_t *classindeces;
- struct seqlookup *sl;
- };
- struct rule
- {
- uint32_t offsets;
- int scnt;
- struct subrule *subrules;
- } *rules;
- FPST *fpst;
- struct fpst_rule *rule;
- uint16_t *glyphs, *class;
- int warned2 = false;
- coverage = getushort (ttf);
- classoff = getushort (ttf);
- rcnt = getushort (ttf); /* class count in coverage table *//* == number of top level rules */
- rules = xcalloc (rcnt, sizeof (struct rule));
- for (i = 0; i < rcnt; ++i)
- rules[i].offsets = getushort (ttf) + stoffset;
- cnt = 0;
- for (i = 0; i < rcnt; ++i)
- if (rules[i].offsets != stoffset)
- { /* some classes might be unused */
- fseek (ttf, rules[i].offsets, SEEK_SET);
- rules[i].scnt = getushort (ttf);
- if (rules[i].scnt < 0)
- {
- LogError (_("Bad count in context chaining sub-table.\n"));
- info->bad_ot = true;
- return;
- }
- cnt += rules[i].scnt;
- rules[i].subrules = xmalloc (rules[i].scnt * sizeof (struct subrule));
- for (j = 0; j < rules[i].scnt; ++j)
- rules[i].subrules[j].offset = getushort (ttf) + rules[i].offsets;
- for (j = 0; j < rules[i].scnt; ++j)
- {
- fseek (ttf, rules[i].subrules[j].offset, SEEK_SET);
- rules[i].subrules[j].ccnt = getushort (ttf);
- rules[i].subrules[j].scnt = getushort (ttf);
- if (rules[i].subrules[j].ccnt < 0)
- {
- LogError (_
- ("Bad class count in contextual chaining sub-table.\n"));
- info->bad_ot = true;
- free (rules);
- return;
- }
- rules[i].subrules[j].classindeces =
- xmalloc (rules[i].subrules[j].ccnt * sizeof (uint16_t));
- rules[i].subrules[j].classindeces[0] = i;
- for (k = 1; k < rules[i].subrules[j].ccnt; ++k)
- rules[i].subrules[j].classindeces[k] = getushort (ttf);
- if (rules[i].subrules[j].scnt < 0)
- {
- LogError (_("Bad count in contextual chaining sub-table.\n"));
- info->bad_ot = true;
- free (rules);
- return;
- }
- rules[i].subrules[j].sl =
- xmalloc (rules[i].subrules[j].scnt * sizeof (struct seqlookup));
- for (k = 0; k < rules[i].subrules[j].scnt; ++k)
- {
- rules[i].subrules[j].sl[k].seq = getushort (ttf);
- if (rules[i].subrules[j].sl[k].seq >= rules[i].subrules[j].ccnt)
- if (!warned2)
- {
- LogError (_
- ("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d max=%d\n"),
- rules[i].subrules[j].sl[k].seq,
- rules[i].subrules[j].ccnt - 1);
- info->bad_ot = true;
- warned2 = true;
- }
- rules[i].subrules[j].sl[k].lookup =
- (void *) (intptr_t) getushort (ttf);
- }
- }
- }
- if (justinuse == git_justinuse)
- {
- /* Nothing to do. This lookup doesn't really reference any glyphs */
- /* any lookups it invokes will be processed on their own */
- }
- else
- {
- fpst = xzalloc (sizeof (FPST));
- fpst->type = gpos ? pst_contextpos : pst_contextsub;
- fpst->format = pst_class;
- fpst->subtable = subtable;
- subtable->fpst = fpst;
- fpst->next = info->possub;
- info->possub = fpst;
- fpst->rules = rule = xcalloc (cnt, sizeof (struct fpst_rule));
- fpst->rule_cnt = cnt;
- class = getClassDefTable (ttf, stoffset + classoff, info);
- fpst->nccnt = ClassFindCnt (class, info->glyph_cnt);
- fpst->nclass = ClassToNames (info, fpst->nccnt, class, inf…
Large files files are truncated, but you can click here to view the full file