summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfatt.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfatt.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfatt.c3737
1 files changed, 0 insertions, 3737 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfatt.c b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfatt.c
deleted file mode 100644
index 85114e1213d..00000000000
--- a/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfatt.c
+++ /dev/null
@@ -1,3737 +0,0 @@
-/* Copyright (C) 2000-2008 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 "pfaedit.h"
-#include <chardata.h>
-#include <utype.h>
-#include <ustring.h>
-#include <math.h>
-#include <locale.h>
-#include <stdlib.h>
-#include "ttf.h"
-
-static uint16 *getAppleClassTable(FILE *ttf, int classdef_offset, int cnt, int sub, int div, struct ttfinfo *info) {
- uint16 *class = gcalloc(cnt,sizeof(uint16));
- 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 *class,int glyph_cnt) {
- char **ret = galloc(class_cnt*sizeof(char *));
- int *lens = gcalloc(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] = galloc(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 *coverageglyphs,uint16 *classed,
- struct ttfinfo *info ) {
- int i, j, len;
- uint8 *glyphs = gcalloc(info->glyph_cnt,1);
- 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 = galloc(len+1);
- else
- ret[len-1] = '\0';
- }
- free(glyphs);
-return( ret );
-}
-
-static int ClassFindCnt(uint16 *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 cmpuint16(const void *u1, const void *u2) {
-return( ((int) *((const uint16 *) u1)) - ((int) *((const uint16 *) u2)) );
-}
-
-static char *GlyphsToNames(struct ttfinfo *info,uint16 *glyphs,int make_uniq) {
- int i, j, len, off;
- char *ret, *pt;
-
- if ( glyphs==NULL )
-return( copy(""));
-
- /* 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),cmpuint16);
- 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 ( info->chars[glyphs[i]]!=NULL )
- len += strlen(info->chars[glyphs[i]]->name)+1;
- ret = pt = galloc(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 scripts {
- uint32 offset;
- uint32 tag;
- int langcnt; /* the default language is included as a */
- struct language { /* normal entry with lang tag 'dflt' */
- uint32 tag;
- uint32 offset;
- uint16 req; /* required feature index. 0xffff for null */
- int fcnt;
- uint16 *features;
- } *languages;
-};
-
-struct feature {
- uint32 offset;
- uint32 tag;
- int lcnt;
- uint16 *lookups;
-};
-
-struct lookup {
- uint16 type;
- uint16 flags;
- /* uint16 lookup; */ /* ???? can't imagine what this is*/
- uint32 offset;
- int subtabcnt;
- int32 *subtab_offsets;
- OTLookup *otlookup;
-};
-
-static uint16 *getCoverageTable(FILE *ttf, int coverage_offset, struct ttfinfo *info) {
- int format, cnt, i,j, rcnt;
- uint16 *glyphs=NULL;
- int start, end, ind, max;
-
- fseek(ttf,coverage_offset,SEEK_SET);
- format = getushort(ttf);
- if ( format==1 ) {
- cnt = getushort(ttf);
- glyphs = galloc((cnt+1)*sizeof(uint16));
- 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)\n"), glyphs[i], info->glyph_cnt );
- info->bad_ot = true;
- glyphs[i] = 0;
- }
- }
- } else if ( format==2 ) {
- glyphs = gcalloc((max=256),sizeof(uint16));
- 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)\n"), 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 = grealloc(glyphs,max*sizeof(uint16));
- memset(glyphs+oldmax,0,(max-oldmax)*sizeof(uint16));
- }
- 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 xplacement, yplacement;
- int16 xadvance, yadvance;
- uint16 offXplaceDev, offYplaceDev;
- uint16 offXadvanceDev, offYadvanceDev;
-};
-
-static uint16 *getClassDefTable(FILE *ttf, int classdef_offset, struct ttfinfo *info) {
- int format, i, j;
- uint16 start, glyphcnt, rangecnt, end, class;
- uint16 *glist=NULL;
- int warned = false;
- int cnt = info->glyph_cnt;
- uint32 g_bounds = info->g_bounds;
-
- fseek(ttf, classdef_offset, SEEK_SET);
- glist = gcalloc(cnt,sizeof(uint16)); /* 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;
- if (g_bounds<ftell(ttf))
- glyphcnt = 0;
- else
- 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)\n"), 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;
- }
-
- /* 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);
-}
-
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
-static void ReadDeviceTable(FILE *ttf,DeviceTable *adjust,uint32 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 = galloc(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) ((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) ((w<<(b*4))&0xf000))>>12;
- }
- } else {
- for ( i=0; i<c; ++i )
- adjust->corrections[i] = (int8) getc(ttf);
- }
- }
- fseek(ttf,here,SEEK_SET);
-}
-
-static ValDevTab *readValDevTab(FILE *ttf,struct valuerecord *vr,uint32 base,
- struct ttfinfo *info) {
- ValDevTab *ret;
-
- if ( vr->offXplaceDev==0 && vr->offYplaceDev==0 &&
- vr->offXadvanceDev==0 && vr->offYadvanceDev==0 )
-return( NULL );
- ret = chunkalloc(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 );
-}
-#endif
-
-static void addPairPos(struct ttfinfo *info, int glyph1, int glyph2,
- struct lookup *l, struct lookup_subtable *subtable, struct valuerecord *vr1,struct valuerecord *vr2,
- uint32 base,FILE *ttf) {
- (void)ttf; /* for -Wall */
- (void)l; /* for -Wall */
- (void)base; /* for -Wall */
- if ( glyph1<info->glyph_cnt && glyph2<info->glyph_cnt ) {
- PST *pos = chunkalloc(sizeof(PST));
- pos->type = pst_pair;
- pos->subtable = subtable;
- pos->next = info->chars[glyph1]->possub;
- info->chars[glyph1]->possub = pos;
- pos->u.pair.vr = chunkalloc(sizeof(struct vr [2]));
- pos->u.pair.paired = copy(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;
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- pos->u.pair.vr[0].adjust = readValDevTab(ttf,vr1,base,info);
- pos->u.pair.vr[1].adjust = readValDevTab(ttf,vr2,base,info);
-#endif
- } else {
- LogError( _("Bad pair position: glyphs %d & %d should have been < %d\n"),
- glyph1, glyph2, info->glyph_cnt );
- info->bad_ot = true;
- }
-}
-
-static int addKernPair(struct ttfinfo *info, int glyph1, int glyph2,
- int16 offset, uint32 devtab, struct lookup *l, struct lookup_subtable *subtable,int isv,
- FILE *ttf) {
- KernPair *kp;
- (void)ttf; /* for -Wall */
- (void)l; /* for -Wall */
- (void)devtab; /* for -Wall */
- if ( glyph1<info->glyph_cnt && glyph2<info->glyph_cnt &&
- info->chars[glyph1]!=NULL && info->chars[glyph2]!=NULL ) {
- for ( kp=isv ? info->chars[glyph1]->vkerns : info->chars[glyph1]->kerns;
- kp!=NULL; kp=kp->next ) {
- if ( kp->sc == info->chars[glyph2] )
- break;
- }
- if ( kp==NULL ) {
- kp = chunkalloc(sizeof(KernPair));
- kp->sc = info->chars[glyph2];
- kp->off = offset;
- kp->subtable = subtable;
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- if ( devtab!=0 ) {
- kp->adjust = chunkalloc(sizeof(DeviceTable));
- ReadDeviceTable(ttf,kp->adjust,devtab,info);
- }
-#endif
- if ( isv ) {
- kp->next = info->chars[glyph1]->vkerns;
- info->chars[glyph1]->vkerns = kp;
- } else {
- kp->next = info->chars[glyph1]->kerns;
- info->chars[glyph1]->kerns = kp;
- }
- } else if ( kp->subtable!=subtable )
-return( true );
- } else if ( glyph1>=info->glyph_cnt || glyph2>=info->glyph_cnt ) {
- /* Might be NULL in a ttc file where we omit glyphs */
- LogError( _("Bad kern pair: glyphs %d & %d should have been < %d\n"),
- glyph1, glyph2, info->glyph_cnt );
- info->bad_ot = true;
- }
-return( false );
-}
-
-static void gposKernSubTable(FILE *ttf, int stoffset, struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable) {
- int coverage, cnt, i, j, pair_cnt, vf1, vf2, glyph2;
- int cd1, cd2, c1_cnt, c2_cnt;
- uint16 format;
- uint16 *ps_offsets;
- uint16 *glyphs, *class1, *class2;
- struct valuerecord vr1, vr2;
- long foffset;
- KernClass *kc;
- int isv, r2l;
-
- format=getushort(ttf);
- if ( format!=1 && format!=2 ) /* Unknown subtable format */
-return;
- coverage = getushort(ttf);
- vf1 = getushort(ttf);
- vf2 = getushort(ttf);
- r2l = 0;
-
- /* Accept forms both with and without device tables */
- if ( (vf1==0x0008 || vf1==0x0088) && vf2==0x0000 )
- isv = 1; /* Top to bottom */
- else if ( vf1==0x0000 && (vf2==0x0004 || vf2==0x0044) && (l->flags&pst_r2l)) {
- isv = 0; /* Right to left */
- r2l = 1;
- } else if ( (vf1==0x0004 || vf1==0x0044) && vf2==0x0000 && !(l->flags&pst_r2l) )
- isv = 0; /* Left to right */
- else
- isv = 2; /* Can't optimize, store all 8 settings */
- if ( format==1 ) {
- subtable->per_glyph_pst_or_kern = true;
- cnt = getushort(ttf);
- ps_offsets = galloc(cnt*sizeof(uint16));
- for ( i=0; i<cnt; ++i )
- ps_offsets[i]=getushort(ttf);
- glyphs = getCoverageTable(ttf,stoffset+coverage,info);
- if ( glyphs==NULL )
-return;
- for ( i=0; i<cnt; ++i ) if ( glyphs[i]<info->glyph_cnt ) {
- fseek(ttf,stoffset+ps_offsets[i],SEEK_SET);
- pair_cnt = getushort(ttf);
- for ( j=0; j<pair_cnt; ++j ) {
- glyph2 = getushort(ttf);
- readvaluerecord(&vr1,vf1,ttf);
- readvaluerecord(&vr2,vf2,ttf);
- if ( isv==2 )
- addPairPos(info, glyphs[i], glyph2,l,subtable,&vr1,&vr2, stoffset,ttf);
- else if ( isv ) {
- if ( addKernPair(info, glyphs[i], glyph2, vr1.yadvance,
- vr1.offYadvanceDev==0?0:stoffset+vr1.offYadvanceDev,
- l,subtable,isv,ttf))
- addPairPos(info, glyphs[i], glyph2,l,subtable,&vr1,&vr2, stoffset,ttf);
- /* If we've already got kern data for this pair of */
- /* glyphs, then we can't make it be a true KernPair */
- /* but we can save the info as a pst_pair */
- } else if ( r2l ) { /* R2L */
- if ( addKernPair(info, glyphs[i], glyph2, vr2.xadvance,
- vr2.offXadvanceDev==0?0:stoffset+vr2.offXadvanceDev,
- l,subtable,isv,ttf))
- addPairPos(info, glyphs[i], glyph2,l,subtable,&vr1,&vr2,stoffset,ttf);
- } else {
- if ( addKernPair(info, glyphs[i], glyph2, vr1.xadvance,
- vr1.offXadvanceDev==0?0:stoffset+vr1.offXadvanceDev,
- l,subtable,isv,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);
- fseek(ttf, foffset, SEEK_SET); /* come back */
- c1_cnt = getushort(ttf);
- c2_cnt = getushort(ttf);
- if ( isv!=2 ) {
- if ( isv ) {
- if ( info->vkhead==NULL )
- info->vkhead = kc = chunkalloc(sizeof(KernClass));
- else
- kc = info->vklast->next = chunkalloc(sizeof(KernClass));
- info->vklast = kc;
- } else {
- if ( info->khead==NULL )
- info->khead = kc = chunkalloc(sizeof(KernClass));
- else
- kc = info->klast->next = chunkalloc(sizeof(KernClass));
- info->klast = kc;
- }
- subtable->vertical_kerning = isv;
- subtable->kc = kc;
- kc->first_cnt = c1_cnt; kc->second_cnt = c2_cnt;
- kc->subtable = subtable;
- kc->offsets = galloc(c1_cnt*c2_cnt*sizeof(int16));
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- kc->adjusts = gcalloc(c1_cnt*c2_cnt,sizeof(DeviceTable));
-#endif
- kc->firsts = ClassToNames(info,c1_cnt,class1,info->glyph_cnt);
- kc->seconds = ClassToNames(info,c2_cnt,class2,info->glyph_cnt);
- /* Now if the coverage table contains entries which are not in */
- /* the list of first classes, then those glyphs are the real */
- /* values for kc->firsts[0] */
- kc->firsts[0] = CoverageMinusClasses(glyphs,class1,info);
- for ( i=0; i<c1_cnt; ++i) {
- for ( j=0; j<c2_cnt; ++j) {
- readvaluerecord(&vr1,vf1,ttf);
- readvaluerecord(&vr2,vf2,ttf);
- if ( isv )
- kc->offsets[i*c2_cnt+j] = vr1.yadvance;
- else if ( r2l )
- kc->offsets[i*c2_cnt+j] = vr2.xadvance;
- else
- kc->offsets[i*c2_cnt+j] = vr1.xadvance;
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- if ( isv ) {
- if ( vr1.offYadvanceDev!=0 )
- ReadDeviceTable(ttf,&kc->adjusts[i*c2_cnt+j],stoffset+vr1.offYadvanceDev,info);
- } else if ( r2l ) {
- if ( vr2.offXadvanceDev!=0 )
- ReadDeviceTable(ttf,&kc->adjusts[i*c2_cnt+j],stoffset+vr2.offXadvanceDev,info);
- } else {
- if ( vr1.offXadvanceDev!=0 )
- ReadDeviceTable(ttf,&kc->adjusts[i*c2_cnt+j],stoffset+vr1.offXadvanceDev,info);
- }
-#endif
- }
- }
- } else { /* This happens when we have a feature which is neither 'kern' nor 'vkrn' we don't know what to do with it so we make it into kern pairs */
- int k,m;
- subtable->per_glyph_pst_or_kern = true;
- for ( i=0; i<c1_cnt; ++i) {
- for ( 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 ( k=0; k<info->glyph_cnt; ++k )
- if ( class1[k]==i )
- for ( m=0; m<info->glyph_cnt; ++m )
- if ( class2[m]==j )
- addPairPos(info, k,m,l,subtable,&vr1,&vr2,stoffset,ttf);
- }
- }
- }
- free(class1); free(class2);
- free(glyphs);
- }
-}
-
-static AnchorPoint *readAnchorPoint(FILE *ttf,uint32 base,AnchorClass *class,
- enum anchor_type type,AnchorPoint *last, struct ttfinfo *info) {
- AnchorPoint *ap;
- int format;
- (void)info; /* for -Wall */
- fseek(ttf,base,SEEK_SET);
-
- ap = chunkalloc(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) getushort(ttf);
- ap->me.y = (int16) getushort(ttf);
- ap->type = type;
- if ( format==2 ) {
- ap->ttf_pt_index = getushort(ttf);
- ap->has_ttf_pt = true;
- }
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- 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);
- }
-#endif
- 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 *glyphs;
- AnchorClass *class;
- SplineChar *sc;
- char buf[50];
- (void)l; /* for -Wall */
- format=getushort(ttf);
- if ( format!=1 ) /* Unknown subtable format */
-return;
- coverage = getushort(ttf);
- cnt = getushort(ttf);
- if ( cnt==0 )
-return;
- offsets = galloc(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);
-
- class = chunkalloc(sizeof(AnchorClass));
- snprintf(buf,sizeof(buf),_("Cursive-%d"),
- info->anchor_class_cnt++ );
- class->name = copy(buf);
- subtable->anchor_classes = true;
- class->subtable = subtable;
- class->type = act_curs;
- 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 *markglyphs,
- int classcnt) {
- AnchorClass **classes = gcalloc(classcnt,sizeof(AnchorClass *)), *ac;
- char buf[50];
- int i, cnt;
- struct mr { uint16 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 = chunkalloc(sizeof(AnchorClass));
- ac->name = copy(buf);
- subtable->anchor_classes = true;
- ac->subtable = subtable;
- /*ac->merge_with = info->anchor_merge_cnt+1;*/
- ac->type = l->otlookup->lookup_type==gpos_mark2mark ? act_mkmk : act_mark;
- /* 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 = galloc(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 *baseglyphs,int classcnt,
- AnchorClass **classes,enum anchor_type at) {
- int basecnt,i, j, ibase;
- uint16 *offsets;
- SplineChar *sc;
- (void)subtable; /* for -Wall */
- (void)l; /* for -Wall */
- fseek(ttf,baseoffset,SEEK_SET);
- basecnt = getushort(ttf);
- if ( feof(ttf) ) {
- LogError( _("Bad base table.\n") );
- info->bad_ot = true;
-return;
- }
- offsets = galloc(basecnt*classcnt*sizeof(uint16));
- 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 *baseglyphs,int classcnt,
- AnchorClass **classes) {
- int basecnt,compcnt, i, j, k, kbase;
- uint16 *loffsets, *aoffsets;
- SplineChar *sc;
- (void)subtable; /* for -Wall */
- (void)l; /* for -Wall */
- fseek(ttf,baseoffset,SEEK_SET);
- basecnt = getushort(ttf);
- if ( feof(ttf) ) {
- LogError( _("Bad ligature base table.\n") );
- info->bad_ot = true;
-return;
- }
- loffsets = galloc(basecnt*sizeof(uint16));
- 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 = galloc(compcnt*classcnt*sizeof(uint16));
- 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 stoffset,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable) {
- int markcoverage, basecoverage, classcnt, markoffset, baseoffset;
- uint16 *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);
-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;
- default:
- 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 format;
- uint16 *glyphs;
- struct valuerecord *vr=NULL, _vr, *which;
- (void)l; /* for -Wall */
- format=getushort(ttf);
- if ( format!=1 && format!=2 ) /* Unknown subtable format */
-return;
- coverage = getushort(ttf);
- vf = getushort(ttf);
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- if ( vf==0 )
-return;
-#else
- if ( (vf&0xf)==0 ) /* Not interested in things whose data just live in device tables */
-return;
-#endif
- if ( format==1 ) {
- memset(&_vr,0,sizeof(_vr));
- readvaluerecord(&_vr,vf,ttf);
- } else {
- cnt = getushort(ttf);
- vr = gcalloc(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);
-return;
- }
- for ( i=0; glyphs[i]!=0xffff; ++i ) if ( glyphs[i]<info->glyph_cnt ) {
- PST *pos = chunkalloc(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;
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- pos->u.pos.adjust = readValDevTab(ttf,which,stoffset,info);
-#endif
- }
- 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;
- (void)ttf; /* for -Wall */
- i = (intpt) 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 coverage;
- uint16 *glyphs;
- struct subrule {
- uint32 offset;
- int gcnt;
- int scnt;
- uint16 *glyphs;
- struct seqlookup *sl;
- };
- struct rule {
- uint32 offsets;
- int scnt;
- struct subrule *subrules;
- } *rules;
- FPST *fpst;
- struct fpst_rule *rule;
- int warned = false, warned2 = false;
- (void)l; /* for -Wall */
- coverage = getushort(ttf);
- rcnt = getushort(ttf); /* glyph count in coverage table */
- rules = galloc(rcnt*sizeof(struct rule));
- for ( i=0; i<rcnt; ++i )
- rules[i].offsets = getushort(ttf)+stoffset;
- glyphs = getCoverageTable(ttf,stoffset+coverage,info);
- 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 = galloc(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 = galloc((rules[i].subrules[j].gcnt+1)*sizeof(uint16));
- 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)\n"),
- 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 = galloc(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 *) (intpt) 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 = chunkalloc(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 = gcalloc(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 coverage;
- uint16 *glyphs;
- struct subrule {
- uint32 offset;
- int gcnt, bcnt, fcnt;
- int scnt;
- uint16 *glyphs, *bglyphs, *fglyphs;
- struct seqlookup *sl;
- };
- struct rule {
- uint32 offsets;
- int scnt;
- struct subrule *subrules;
- } *rules;
- FPST *fpst;
- struct fpst_rule *rule;
- int warned = false, warned2 = false;
- (void)l; /* for -Wall */
- coverage = getushort(ttf);
- rcnt = getushort(ttf); /* glyph count in coverage table */
- rules = galloc(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);
-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 = galloc(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 = galloc((rules[i].subrules[j].bcnt+1)*sizeof(uint16));
- 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 = galloc((rules[i].subrules[j].gcnt+1)*sizeof(uint16));
- 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 = galloc((rules[i].subrules[j].fcnt+1)*sizeof(uint16));
- 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)\n"),
- (&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 = galloc(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 *) (intpt) 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 = chunkalloc(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 = gcalloc(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 coverage;
- uint16 classoff;
- struct subrule {
- uint32 offset;
- int ccnt;
- int scnt;
- uint16 *classindeces;
- struct seqlookup *sl;
- };
- struct rule {
- uint32 offsets;
- int scnt;
- struct subrule *subrules;
- } *rules;
- FPST *fpst;
- struct fpst_rule *rule;
- uint16 *glyphs, *class;
- int warned2 = false;
- (void)l; /* for -Wall */
- coverage = getushort(ttf);
- classoff = getushort(ttf);
- rcnt = getushort(ttf); /* class count in coverage table *//* == number of top level rules */
- rules = gcalloc(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!=(unsigned)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 = galloc(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 = galloc(rules[i].subrules[j].ccnt*sizeof(uint16));
- 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 = galloc(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 *) (intpt) 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 = chunkalloc(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 = gcalloc(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,info->glyph_cnt);
-
- /* Just in case they used the coverage table to redefine class 0 */
- glyphs = getCoverageTable(ttf,stoffset+coverage,info);
- fpst->nclass[0] = CoverageMinusClasses(glyphs,class,info);
- free(glyphs); free(class); class = NULL;
-
- cnt = 0;
- for ( i=0; i<rcnt; ++i ) for ( j=0; j<rules[i].scnt; ++j ) {
- rule[cnt].u.class.nclasses = rules[i].subrules[j].classindeces;
- rule[cnt].u.class.ncnt = rules[i].subrules[j].ccnt;
- rules[i].subrules[j].classindeces = NULL;
- 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].classindeces);
- free(rules[i].subrules[j].sl);
- }
- free(rules[i].subrules);
- }
- free(rules);
-}
-
-static void g___ChainingSubTable2(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 coverage, offset;
- uint16 bclassoff, classoff, fclassoff;
- struct subrule {
- uint32 offset;
- int ccnt, bccnt, fccnt;
- int scnt;
- uint16 *classindeces, *bci, *fci;
- struct seqlookup *sl;
- };
- struct rule {
- uint32 offsets;
- int scnt;
- struct subrule *subrules;
- } *rules;
- FPST *fpst;
- struct fpst_rule *rule;
- uint16 *glyphs, *class;
- int warned2 = false;
- (void)l; /* for -Wall */
- coverage = getushort(ttf);
- bclassoff = getushort(ttf);
- classoff = getushort(ttf);
- fclassoff = getushort(ttf);
- rcnt = getushort(ttf); /* class count *//* == max number of top level rules */
- rules = gcalloc(rcnt,sizeof(struct rule));
- for ( i=0; i<rcnt; ++i ) {
- offset = getushort(ttf);
- rules[i].offsets = offset==0 ? 0 : offset+stoffset;
- }
- cnt = 0;
- for ( i=0; i<rcnt; ++i ) if ( rules[i].offsets!=0 ) { /* 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 = galloc(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].bccnt = getushort(ttf);
- if ( rules[i].subrules[j].bccnt<0 ) {
- LogError( _("Bad class count in contextual chaining sub-table.\n") );
- info->bad_ot = true;
- free(rules);
-return;
- }
- rules[i].subrules[j].bci = galloc(rules[i].subrules[j].bccnt*sizeof(uint16));
- for ( k=0; k<rules[i].subrules[j].bccnt; ++k )
- rules[i].subrules[j].bci[k] = getushort(ttf);
- rules[i].subrules[j].ccnt = 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 = galloc(rules[i].subrules[j].ccnt*sizeof(uint16));
- 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);
- rules[i].subrules[j].fccnt = getushort(ttf);
- if ( rules[i].subrules[j].fccnt<0 ) {
- LogError( _("Bad class count in contextual chaining sub-table.\n") );
- info->bad_ot = true;
- free(rules);
-return;
- }
- rules[i].subrules[j].fci = galloc(rules[i].subrules[j].fccnt*sizeof(uint16));
- for ( k=0; k<rules[i].subrules[j].fccnt; ++k )
- rules[i].subrules[j].fci[k] = getushort(ttf);
- rules[i].subrules[j].scnt = 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 = galloc(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 *) (intpt) 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 = chunkalloc(sizeof(FPST));
- fpst->type = gpos ? pst_chainpos : pst_chainsub;
- fpst->format = pst_class;
- fpst->subtable = subtable;
- subtable->fpst = fpst;
- fpst->next = info->possub;
- info->possub = fpst;
-
- fpst->rules = rule = gcalloc(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,info->glyph_cnt);
-
- /* Just in case they used the coverage table to redefine class 0 */
- glyphs = getCoverageTable(ttf,stoffset+coverage,info);
- fpst->nclass[0] = CoverageMinusClasses(glyphs,class,info);
- free(glyphs); free(class); class = NULL;
-
- /* The docs don't mention this, but in mangal.ttf fclassoff==0 NULL */
- if ( bclassoff!=0 )
- class = getClassDefTable(ttf, stoffset+bclassoff, info);
- else
- class = gcalloc(info->glyph_cnt,sizeof(uint16));
- fpst->bccnt = ClassFindCnt(class,info->glyph_cnt);
- fpst->bclass = ClassToNames(info,fpst->bccnt,class,info->glyph_cnt);
- free(class);
- if ( fclassoff!=0 )
- class = getClassDefTable(ttf, stoffset+fclassoff, info);
- else
- class = gcalloc(info->glyph_cnt,sizeof(uint16));
- fpst->fccnt = ClassFindCnt(class,info->glyph_cnt);
- fpst->fclass = ClassToNames(info,fpst->fccnt,class,info->glyph_cnt);
- free(class);
-
- cnt = 0;
- for ( i=0; i<rcnt; ++i ) for ( j=0; j<rules[i].scnt; ++j ) {
- rule[cnt].u.class.nclasses = rules[i].subrules[j].classindeces;
- rule[cnt].u.class.ncnt = rules[i].subrules[j].ccnt;
- rules[i].subrules[j].classindeces = NULL;
- rule[cnt].u.class.bclasses = rules[i].subrules[j].bci;
- rule[cnt].u.class.bcnt = rules[i].subrules[j].bccnt;
- rules[i].subrules[j].bci = NULL;
- rule[cnt].u.class.fclasses = rules[i].subrules[j].fci;
- rule[cnt].u.class.fcnt = rules[i].subrules[j].fccnt;
- rules[i].subrules[j].fci = NULL;
- 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].classindeces);
- free(rules[i].subrules[j].sl);
- }
- free(rules[i].subrules);
- }
- free(rules);
-}
-
-static void g___ContextSubTable3(FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
- struct lookup *alllooks, int gpos) {
- int i, k, scnt, gcnt;
- uint16 *coverage;
- struct seqlookup *sl;
- uint16 *glyphs;
- FPST *fpst;
- struct fpst_rule *rule;
- int warned2 = false;
- (void)l; /* for -Wall */
- gcnt = getushort(ttf);
- scnt = getushort(ttf);
- if ( feof(ttf) ) {
- LogError( _("End of file in context chaining sub-table.\n") );
- info->bad_ot = true;
-return;
- }
- coverage = galloc(gcnt*sizeof(uint16));
- for ( i=0; i<gcnt; ++i )
- coverage[i] = getushort(ttf);
- sl = galloc(scnt*sizeof(struct seqlookup));
- for ( k=0; k<scnt; ++k ) {
- sl[k].seq = getushort(ttf);
- if ( sl[k].seq >= gcnt && !warned2 ) {
- LogError( _("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d, max=%d\n"),
- sl[k].seq, gcnt-1 );
- info->bad_ot = true;
- warned2 = true;
- }
- sl[k].lookup = (void *) (intpt) 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 = chunkalloc(sizeof(FPST));
- fpst->type = gpos ? pst_contextpos : pst_contextsub;
- fpst->format = pst_coverage;
- fpst->subtable = subtable;
- subtable->fpst = fpst;
- fpst->next = info->possub;
- info->possub = fpst;
-
- fpst->rules = rule = gcalloc(1,sizeof(struct fpst_rule));
- fpst->rule_cnt = 1;
- rule->u.coverage.ncnt = gcnt;
- rule->u.coverage.ncovers = galloc(gcnt*sizeof(char **));
- for ( i=0; i<gcnt; ++i ) {
- glyphs = getCoverageTable(ttf,stoffset+coverage[i],info);
- rule->u.coverage.ncovers[i] = GlyphsToNames(info,glyphs,true);
- free(glyphs);
- }
- rule->lookup_cnt = scnt;
- rule->lookups = sl;
- for ( k=0; k<scnt; ++k )
- ProcessSubLookups(ttf,info,gpos,alllooks,&sl[k]);
- }
-
- free(coverage);
-}
-
-static void g___ChainingSubTable3(FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
- struct lookup *alllooks, int gpos) {
- int i, k, scnt, gcnt, bcnt, fcnt;
- uint16 *coverage, *bcoverage, *fcoverage;
- struct seqlookup *sl;
- uint16 *glyphs;
- FPST *fpst;
- struct fpst_rule *rule;
- int warned2 = false;
- (void)l; /* for -Wall */
- bcnt = getushort(ttf);
- if ( feof(ttf)) {
- LogError( _("End of file in context chaining subtable.\n") );
- info->bad_ot = true;
-return;
- }
- bcoverage = galloc(bcnt*sizeof(uint16));
- for ( i=0; i<bcnt; ++i )
- bcoverage[i] = getushort(ttf);
- gcnt = getushort(ttf);
- if ( feof(ttf)) {
- LogError( _("End of file in context chaining subtable.\n") );
- info->bad_ot = true;
-return;
- }
- coverage = galloc(gcnt*sizeof(uint16));
- for ( i=0; i<gcnt; ++i )
- coverage[i] = getushort(ttf);
- fcnt = getushort(ttf);
- if ( feof(ttf)) {
- LogError( _("End of file in context chaining subtable.\n") );
- info->bad_ot = true;
-return;
- }
- fcoverage = galloc(fcnt*sizeof(uint16));
- for ( i=0; i<fcnt; ++i )
- fcoverage[i] = getushort(ttf);
- scnt = getushort(ttf);
- if ( feof(ttf)) {
- LogError( _("End of file in context chaining subtable.\n") );
- info->bad_ot = true;
-return;
- }
- sl = galloc(scnt*sizeof(struct seqlookup));
- for ( k=0; k<scnt; ++k ) {
- sl[k].seq = getushort(ttf);
- if ( sl[k].seq >= gcnt && !warned2 ) {
- LogError( _("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d, max=%d\n"),
- sl[k].seq, gcnt-1 );
- info->bad_ot = true;
- warned2 = true;
- }
- sl[k].lookup = (void *) (intpt) 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 = chunkalloc(sizeof(FPST));
- fpst->type = gpos ? pst_chainpos : pst_chainsub;
- fpst->format = pst_coverage;
- fpst->subtable = subtable;
- subtable->fpst = fpst;
- fpst->next = info->possub;
- info->possub = fpst;
-
- fpst->rules = rule = gcalloc(1,sizeof(struct fpst_rule));
- fpst->rule_cnt = 1;
-
- rule->u.coverage.bcnt = bcnt;
- rule->u.coverage.bcovers = galloc(bcnt*sizeof(char **));
- for ( i=0; i<bcnt; ++i ) {
- glyphs = getCoverageTable(ttf,stoffset+bcoverage[i],info);
- rule->u.coverage.bcovers[i] = GlyphsToNames(info,glyphs,true);
- free(glyphs);
- }
-
- rule->u.coverage.ncnt = gcnt;
- rule->u.coverage.ncovers = galloc(gcnt*sizeof(char **));
- for ( i=0; i<gcnt; ++i ) {
- glyphs = getCoverageTable(ttf,stoffset+coverage[i],info);
- rule->u.coverage.ncovers[i] = GlyphsToNames(info,glyphs,true);
- free(glyphs);
- }
-
- rule->u.coverage.fcnt = fcnt;
- rule->u.coverage.fcovers = galloc(fcnt*sizeof(char **));
- for ( i=0; i<fcnt; ++i ) {
- glyphs = getCoverageTable(ttf,stoffset+fcoverage[i],info);
- rule->u.coverage.fcovers[i] = GlyphsToNames(info,glyphs,true);
- free(glyphs);
- }
-
- rule->lookup_cnt = scnt;
- rule->lookups = sl;
- for ( k=0; k<scnt; ++k )
- ProcessSubLookups(ttf,info,gpos,alllooks,&sl[k]);
- }
-
- free(bcoverage);
- free(coverage);
- free(fcoverage);
-}
-
-static void gposContextSubTable(FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable,
- struct lookup *alllooks) {
- switch( getushort(ttf)) {
- case 1:
- g___ContextSubTable1(ttf,stoffset,info,l,subtable,git_normal,alllooks,true);
- break;
- case 2:
- g___ContextSubTable2(ttf,stoffset,info,l,subtable,git_normal,alllooks,true);
- break;
- case 3:
- g___ContextSubTable3(ttf,stoffset,info,l,subtable,git_normal,alllooks,true);
- break;
- }
-}
-
-static void gposChainingSubTable(FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable,
- struct lookup *alllooks) {
- switch( getushort(ttf)) {
- case 1:
- g___ChainingSubTable1(ttf,stoffset,info,l,subtable,git_normal,alllooks,true);
- break;
- case 2:
- g___ChainingSubTable2(ttf,stoffset,info,l,subtable,git_normal,alllooks,true);
- break;
- case 3:
- g___ChainingSubTable3(ttf,stoffset,info,l,subtable,git_normal,alllooks,true);
- break;
- }
-}
-
-static struct { uint32 tag; char *str; } tagstr[] = {
- { CHR('v','r','t','2'), "vert" },
- { CHR('s','m','c','p'), "sc" },
- { CHR('s','m','c','p'), "small" },
- { CHR('o','n','u','m'), "oldstyle" },
- { CHR('s','u','p','s'), "superior" },
- { CHR('s','u','b','s'), "inferior" },
- { CHR('s','w','s','h'), "swash" },
- { 0, NULL }
-};
-
-
-static void gsubSimpleSubTable(FILE *ttf, int stoffset, struct ttfinfo *info,
- struct lookup *l, struct lookup_subtable *subtable, int justinuse) {
- int coverage, cnt, i, j, which;
- uint16 format;
- uint16 *glyphs, *glyph2s=NULL;
- int delta=0;
-
- format=getushort(ttf);
- if ( format!=1 && format!=2 ) /* Unknown subtable format */
-return;
- coverage = getushort(ttf);
- if ( format==1 ) {
- delta = getushort(ttf);
- } else {
- cnt = getushort(ttf);
- glyph2s = galloc(cnt*sizeof(uint16));
- for ( i=0; i<cnt; ++i )
- glyph2s[i] = getushort(ttf);
- /* in range check comes later */
- }
- glyphs = getCoverageTable(ttf,stoffset+coverage,info);
- if ( glyphs==NULL ) {
- free(glyph2s);
-return;
- }
- if ( justinuse==git_findnames ) {
- FeatureScriptLangList *fl;
- fl = l->otlookup->features;
- /* Unnamed glyphs get a name built of the base name and the feature tag */
- /* assuming this lookup is tagged with a feature... */
- if ( fl!=NULL )
- for ( i=0; glyphs[i]!=0xffff; ++i ) if ( glyphs[i]<info->glyph_cnt ) {
- if ( info->chars[glyphs[i]]->name!=NULL ) {
- which = format==1 ? (uint16) (glyphs[i]+delta) : glyph2s[i];
- if ( which<info->glyph_cnt && which>=0 && info->chars[which]!=NULL &&
- info->chars[which]->name==NULL ) {
- char *basename = info->chars[glyphs[i]]->name;
- char *str;
- char tag[5], *pt=tag;
- for ( j=0; tagstr[j].tag!=0 && tagstr[j].tag!=fl->featuretag; ++j );
- if ( tagstr[j].tag!=0 )
- pt = tagstr[j].str;
- else {
- tag[0] = fl->featuretag>>24;
- if ( (tag[1] = (fl->featuretag>>16)&0xff)==' ' ) tag[1] = '\0';
- if ( (tag[2] = (fl->featuretag>>8)&0xff)==' ' ) tag[2] = '\0';
- if ( (tag[3] = (fl->featuretag)&0xff)==' ' ) tag[3] = '\0';
- tag[4] = '\0';
- pt = tag;
- }
- str = galloc(strlen(basename)+strlen(pt)+2);
- sprintf(str,"%s.%s", basename, pt );
- info->chars[which]->name = str;
- }
- }
- }
- } else if ( justinuse==git_justinuse ) {
- for ( i=0; glyphs[i]!=0xffff; ++i ) if ( glyphs[i]<info->glyph_cnt ) {
- info->inuse[glyphs[i]]= true;
- which = format==1 ? (uint16) (glyphs[i]+delta) : glyph2s[i];
- info->inuse[which]= true;
- }
- } else if ( justinuse==git_normal ) {
- for ( i=0; glyphs[i]!=0xffff; ++i ) if ( glyphs[i]<info->glyph_cnt && info->chars[glyphs[i]]!=NULL ) {
- which = format==1 ? (uint16) (glyphs[i]+delta) : glyph2s[i];
- if ( which>=info->glyph_cnt ) {
- LogError( _("Bad substitution glyph: GID %d not less than %d\n"),
- which, info->glyph_cnt);
- info->bad_ot = true;
- which = 0;
- }
- if ( info->chars[which]!=NULL ) { /* Might be in a ttc file */
- PST *pos = chunkalloc(sizeof(PST));
- pos->type = pst_substitution;
- pos->subtable = subtable;
- pos->next = info->chars[glyphs[i]]->possub;
- info->chars[glyphs[i]]->possub = pos;
- pos->u.subs.variant = copy(info->chars[which]->name);
- }
- }
- }
- subtable->per_glyph_pst_or_kern = true;
- free(glyph2s);
- free(glyphs);
-}
-
-/* Multiple and alternate substitution lookups have the same format */
-static void gsubMultipleSubTable(FILE *ttf, int stoffset, struct ttfinfo *info,
- struct lookup *l, struct lookup_subtable *subtable, int justinuse) {
- int coverage, cnt, i, j, len, max;
- uint16 format;
- uint16 *offsets;
- uint16 *glyphs, *glyph2s;
- char *pt;
- int bad;
- int badcnt = 0;
-
- if ( justinuse==git_findnames )
-return;
-
- format=getushort(ttf);
- if ( format!=1 ) /* Unknown subtable format */
-return;
- coverage = getushort(ttf);
- cnt = getushort(ttf);
- if ( feof(ttf)) {
- LogError( _("Unexpected end of file in GSUB sub-table.\n"));
- info->bad_ot = true;
-return;
- }
- offsets = galloc(cnt*sizeof(uint16));
- for ( i=0; i<cnt; ++i )
- offsets[i] = getushort(ttf);
- glyphs = getCoverageTable(ttf,stoffset+coverage,info);
- if ( glyphs==NULL ) {
- free(offsets);
-return;
- }
- for ( i=0; glyphs[i]!=0xffff; ++i );
- if ( i!=cnt ) {
- LogError( _("Coverage table specifies a different number of glyphs than the sub-table expects.\n" ));
- info->bad_ot = true;
- if ( cnt<i )
- glyphs[cnt] = 0xffff;
- else
- cnt = i;
- }
- max = 20;
- glyph2s = galloc(max*sizeof(uint16));
- for ( i=0; glyphs[i]!=0xffff; ++i ) {
- PST *alt;
- fseek(ttf,stoffset+offsets[i],SEEK_SET);
- cnt = getushort(ttf);
- if ( feof(ttf)) {
- LogError( _("Unexpected end of file in GSUB sub-table.\n"));
- info->bad_ot = true;
-return;
- }
- if ( cnt>max ) {
- max = cnt+30;
- glyph2s = grealloc(glyph2s,max*sizeof(uint16));
- }
- len = 0; bad = false;
- for ( j=0; j<cnt; ++j ) {
- glyph2s[j] = getushort(ttf);
- if ( feof(ttf)) {
- LogError( _("Unexpected end of file in GSUB sub-table.\n" ));
- info->bad_ot = true;
-return;
- }
- if ( glyph2s[j]>=info->glyph_cnt ) {
- if ( !justinuse )
- LogError( _("Bad Multiple/Alternate substitution glyph. GID %d not less than %d\n"),
- glyph2s[j], info->glyph_cnt );
- info->bad_ot = true;
- if ( ++badcnt>20 )
-return;
- glyph2s[j] = 0;
- }
- if ( justinuse==git_justinuse )
- /* Do Nothing */;
- else if ( info->chars[glyph2s[j]]==NULL )
- bad = true;
- else
- len += strlen( info->chars[glyph2s[j]]->name) +1;
- }
- if ( justinuse==git_justinuse ) {
- info->inuse[glyphs[i]] = 1;
- for ( j=0; j<cnt; ++j )
- info->inuse[glyph2s[j]] = 1;
- } else if ( info->chars[glyphs[i]]!=NULL && !bad ) {
- alt = chunkalloc(sizeof(PST));
- alt->type = l->otlookup->lookup_type==gsub_multiple?pst_multiple:pst_alternate;
- alt->subtable = subtable;
- alt->next = info->chars[glyphs[i]]->possub;
- info->chars[glyphs[i]]->possub = alt;
- pt = alt->u.subs.variant = galloc(len+1);
- *pt = '\0';
- for ( j=0; j<cnt; ++j ) {
- strcat(pt,info->chars[glyph2s[j]]->name);
- strcat(pt," ");
- }
- if ( *pt!='\0' && pt[strlen(pt)-1]==' ' )
- pt[strlen(pt)-1] = '\0';
- }
- }
- subtable->per_glyph_pst_or_kern = true;
- free(glyphs);
- free(glyph2s);
- free(offsets);
-}
-
-static void gsubLigatureSubTable(FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse) {
- int coverage, cnt, i, j, k, lig_cnt, cc, len;
- uint16 *ls_offsets, *lig_offsets;
- uint16 *glyphs, *lig_glyphs, lig;
- char *pt;
- PST *liga;
-
- /* Format = */ getushort(ttf);
- coverage = getushort(ttf);
- cnt = getushort(ttf);
- if ( feof(ttf)) {
- LogError( _("Unexpected end of file in GSUB ligature sub-table.\n" ));
- info->bad_ot = true;
-return;
- }
- ls_offsets = galloc(cnt*sizeof(uint16));
- for ( i=0; i<cnt; ++i )
- ls_offsets[i]=getushort(ttf);
- glyphs = getCoverageTable(ttf,stoffset+coverage,info);
- if ( glyphs==NULL )
-return;
- for ( i=0; i<cnt; ++i ) {
- fseek(ttf,stoffset+ls_offsets[i],SEEK_SET);
- lig_cnt = getushort(ttf);
- if ( feof(ttf)) {
- LogError( _("Unexpected end of file in GSUB ligature sub-table.\n" ));
- info->bad_ot = true;
-return;
- }
- lig_offsets = galloc(lig_cnt*sizeof(uint16));
- for ( j=0; j<lig_cnt; ++j )
- lig_offsets[j] = getushort(ttf);
- if ( feof(ttf)) {
- LogError( _("Unexpected end of file in GSUB ligature sub-table.\n" ));
- info->bad_ot = true;
-return;
- }
- for ( j=0; j<lig_cnt; ++j ) {
- fseek(ttf,stoffset+ls_offsets[i]+lig_offsets[j],SEEK_SET);
- lig = getushort(ttf);
- if ( lig>=info->glyph_cnt ) {
- LogError( _("Bad ligature glyph. GID %d not less than %d\n"),
- lig, info->glyph_cnt );
- info->bad_ot = true;
- lig = 0;
- }
- cc = getushort(ttf);
- if ( cc<0 || cc>100 ) {
- LogError( _("Unlikely count of ligature components (%d), I suspect this ligature sub-\n table is garbage, I'm giving up on it.\n"), cc );
- info->bad_ot = true;
- free(glyphs); free(lig_offsets);
-return;
- }
- lig_glyphs = galloc(cc*sizeof(uint16));
- lig_glyphs[0] = glyphs[i];
- for ( k=1; k<cc; ++k ) {
- lig_glyphs[k] = getushort(ttf);
- if ( lig_glyphs[k]>=info->glyph_cnt ) {
- if ( justinuse==git_normal )
- LogError( _("Bad ligature component glyph. GID %d not less than %d (in ligature %d)\n"),
- lig_glyphs[k], info->glyph_cnt, lig );
- info->bad_ot = true;
- lig_glyphs[k] = 0;
- }
- }
- if ( justinuse==git_justinuse ) {
- info->inuse[lig] = 1;
- for ( k=0; k<cc; ++k )
- info->inuse[lig_glyphs[k]] = 1;
- } else if ( justinuse==git_findnames ) {
- FeatureScriptLangList *fl = l->otlookup->features;
- /* If our ligature glyph has no name (and its components do) */
- /* give it a name by concatenating components with underscores */
- /* between them, and appending the tag */
- if ( fl!=NULL && info->chars[lig]!=NULL && info->chars[lig]->name==NULL ) {
- int len=0;
- for ( k=0; k<cc; ++k ) {
- if ( info->chars[lig_glyphs[k]]==NULL || info->chars[lig_glyphs[k]]->name==NULL )
- break;
- len += strlen(info->chars[lig_glyphs[k]]->name)+1;
- }
- if ( k==cc ) {
- char *str = galloc(len+6), *pt;
- char tag[5];
- tag[0] = fl->featuretag>>24;
- if ( (tag[1] = (fl->featuretag>>16)&0xff)==' ' ) tag[1] = '\0';
- if ( (tag[2] = (fl->featuretag>>8)&0xff)==' ' ) tag[2] = '\0';
- if ( (tag[3] = (fl->featuretag)&0xff)==' ' ) tag[3] = '\0';
- tag[4] = '\0';
- *str='\0';
- for ( k=0; k<cc; ++k ) {
- strcat(str,info->chars[lig_glyphs[k]]->name);
- strcat(str,"_");
- }
- pt = str+strlen(str);
- pt[-1] = '.';
- strcpy(pt,tag);
- info->chars[lig]->name = str;
- }
- }
- } else if ( info->chars[lig]!=NULL ) {
- for ( k=len=0; k<cc; ++k )
- if ( lig_glyphs[k]<info->glyph_cnt &&
- info->chars[lig_glyphs[k]]!=NULL )
- len += strlen(info->chars[lig_glyphs[k]]->name)+1;
- liga = chunkalloc(sizeof(PST));
- liga->type = pst_ligature;
- liga->subtable = subtable;
- liga->next = info->chars[lig]->possub;
- info->chars[lig]->possub = liga;
- liga->u.lig.lig = info->chars[lig];
- liga->u.lig.components = pt = galloc(len);
- for ( k=0; k<cc; ++k ) {
- if ( lig_glyphs[k]<info->glyph_cnt &&
- info->chars[lig_glyphs[k]]!=NULL ) {
- strcpy(pt,info->chars[lig_glyphs[k]]->name);
- pt += strlen(pt);
- *pt++ = ' ';
- }
- }
- pt[-1] = '\0';
- }
- free(lig_glyphs);
- }
- free(lig_offsets);
- }
- subtable->per_glyph_pst_or_kern = true;
- free(ls_offsets); free(glyphs);
-}
-
-static void gsubContextSubTable(FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
- struct lookup *alllooks) {
- if ( justinuse==git_findnames )
-return; /* Don't give names to these guys, they might not be unique */
- /* ie. because these are context based there is not a one to one */
- /* mapping between input glyphs and output glyphs. One input glyph */
- /* may go to several output glyphs (depending on context) and so */
- /* <input-glyph-name>"."<tag-name> would be used for several glyphs */
- switch( getushort(ttf)) {
- case 1:
- g___ContextSubTable1(ttf,stoffset,info,l,subtable,justinuse,alllooks,false);
- break;
- case 2:
- g___ContextSubTable2(ttf,stoffset,info,l,subtable,justinuse,alllooks,false);
- break;
- case 3:
- g___ContextSubTable3(ttf,stoffset,info,l,subtable,justinuse,alllooks,false);
- break;
- }
-}
-
-static void gsubChainingSubTable(FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
- struct lookup *alllooks) {
- if ( justinuse==git_findnames )
-return; /* Don't give names to these guys, the names might not be unique */
- switch( getushort(ttf)) {
- case 1:
- g___ChainingSubTable1(ttf,stoffset,info,l,subtable,justinuse,alllooks,false);
- break;
- case 2:
- g___ChainingSubTable2(ttf,stoffset,info,l,subtable,justinuse,alllooks,false);
- break;
- case 3:
- g___ChainingSubTable3(ttf,stoffset,info,l,subtable,justinuse,alllooks,false);
- break;
- }
-}
-
-static void gsubReverseChainSubTable(FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse) {
- int scnt, bcnt, fcnt, i;
- uint16 coverage, *bcoverage, *fcoverage, *sglyphs, *glyphs;
- FPST *fpst;
- struct fpst_rule *rule;
- (void)l; /* for -Wall */
- if ( justinuse==git_findnames )
-return; /* Don't give names to these guys, they might not be unique */
- if ( getushort(ttf)!=1 )
-return; /* Don't understand this format type */
-
- coverage = getushort(ttf);
- bcnt = getushort(ttf);
- bcoverage = galloc(bcnt*sizeof(uint16));
- for ( i = 0 ; i<bcnt; ++i )
- bcoverage[i] = getushort(ttf);
- fcnt = getushort(ttf);
- fcoverage = galloc(fcnt*sizeof(uint16));
- for ( i = 0 ; i<fcnt; ++i )
- fcoverage[i] = getushort(ttf);
- scnt = getushort(ttf);
- sglyphs = galloc((scnt+1)*sizeof(uint16));
- for ( i = 0 ; i<scnt; ++i )
- if (( sglyphs[i] = getushort(ttf))>=info->glyph_cnt ) {
- LogError( _("Bad reverse contextual chaining substitution glyph: %d is not less than %d\n"),
- sglyphs[i], info->glyph_cnt );
- info->bad_ot = true;
- sglyphs[i] = 0;
- }
- sglyphs[i] = 0xffff;
-
- if ( justinuse==git_justinuse ) {
- for ( i = 0 ; i<scnt; ++i )
- info->inuse[sglyphs[i]] = 1;
- } else {
- fpst = chunkalloc(sizeof(FPST));
- fpst->type = pst_reversesub;
- fpst->format = pst_reversecoverage;
- fpst->subtable = subtable;
- fpst->next = info->possub;
- info->possub = fpst;
- subtable->fpst = fpst;
-
- fpst->rules = rule = gcalloc(1,sizeof(struct fpst_rule));
- fpst->rule_cnt = 1;
-
- rule->u.rcoverage.always1 = 1;
- rule->u.rcoverage.bcnt = bcnt;
- rule->u.rcoverage.fcnt = fcnt;
- rule->u.rcoverage.ncovers = galloc(sizeof(char *));
- rule->u.rcoverage.bcovers = galloc(bcnt*sizeof(char *));
- rule->u.rcoverage.fcovers = galloc(fcnt*sizeof(char *));
- rule->u.rcoverage.replacements = GlyphsToNames(info,sglyphs,false);
- glyphs = getCoverageTable(ttf,stoffset+coverage,info);
- rule->u.rcoverage.ncovers[0] = GlyphsToNames(info,glyphs,false);
- free(glyphs);
- for ( i=0; i<bcnt; ++i ) {
- glyphs = getCoverageTable(ttf,stoffset+bcoverage[i],info);
- rule->u.rcoverage.bcovers[i] = GlyphsToNames(info,glyphs,true);
- free(glyphs);
- }
- for ( i=0; i<fcnt; ++i ) {
- glyphs = getCoverageTable(ttf,stoffset+fcoverage[i],info);
- rule->u.rcoverage.fcovers[i] = GlyphsToNames(info,glyphs,true);
- free(glyphs);
- }
- rule->lookup_cnt = 0; /* substitution lookups needed for reverse chaining */
- }
- free(sglyphs);
- free(fcoverage);
- free(bcoverage);
-}
-
-static void readttfsizeparameters(FILE *ttf,int32 broken_pos,int32 correct_pos,
- struct ttfinfo *info) {
- int32 here;
- /* Both of the two fonts I've seen that contain a 'size' feature */
- /* have multiple features all of which point to the same parameter */
- /* area. Odd. */
- /* When Adobe first released fonts containing the 'size' feature */
- /* they did not follow the spec, and the offset to the size parameters */
- /* was relative to the wrong location. They claim (Aug 2006) that */
- /* this has been fixed. Be prepared to read either style of 'size' */
- /* following the heuristics Adobe provides */
- int32 test[2];
- int i, nid;
-
- if ( info->last_size_pos==broken_pos || info->last_size_pos==correct_pos )
-return;
-
- if ( info->last_size_pos!=0 ) {
- LogError( _("This font, %s, has multiple GPOS 'size' features. I'm not sure how to interpret that. I shall pick one arbitrarily.\n"),
- info->fontname==NULL? _("<Untitled>") : info->fontname );
- info->bad_ot = true;
-return;
- }
-
- test[0] = correct_pos; test[1] = broken_pos;
- here = ftell(ttf);
- for ( i=0; i<2; ++i ) {
- fseek(ttf,test[i],SEEK_SET);
- info->last_size_pos = test[i];
- info->design_size = getushort(ttf);
- if ( info->design_size==0 )
- continue;
- info->fontstyle_id = getushort(ttf);
- nid = getushort(ttf);
- info->design_range_bottom = getushort(ttf);
- info->design_range_top = getushort(ttf);
- if ( info->fontstyle_id == 0 && nid==0 &&
- info->design_range_bottom==0 && info->design_range_top==0 ) {
- /* Reasonable spec, only design size provided */
- info->fontstyle_name = NULL;
- break;
- }
- if ( info->design_size < info->design_range_bottom ||
- info->design_size > info->design_range_top ||
- info->design_range_bottom > info->design_range_top ||
- nid<256 || nid>32767 )
- continue;
- info->fontstyle_name = FindAllLangEntries(ttf,info,nid);
- if ( info->fontstyle_name==NULL )
- continue;
- else
- break;
- }
- if ( i==2 ) {
- LogError(_("The 'size' feature does not seem to follow the standard,\nnor does it conform to Adobe's early misinterpretation of\nthe standard. I cannot parse it.\n") );
- info->bad_ot = true;
- info->design_size = info->design_range_bottom = info->design_range_top = info->fontstyle_id = 0;
- info->fontstyle_name = NULL;
- } else if ( i==1 ) {
- LogError(_("The 'size' feature of this font conforms to Adobe's early misinterpretation of the otf standard.\n") );
- }
- fseek(ttf,here,SEEK_SET);
-
-#if 0
- printf( "pos=%d size=%g, range=(%g,%g] id=%d name=%d\n", pos,
- info->design_size/10.0, info->design_range_bottom/10.0, info->design_range_top/10.0,
- info->fontstyle_id, info->fontstyle_name );
-#endif
-}
-
-static struct scripts *readttfscripts(FILE *ttf,int32 pos, struct ttfinfo *info, int isgpos) {
- int i,j,k,cnt;
- int deflang, lcnt;
- struct scripts *scripts;
-
- if ( pos>=(int32)info->g_bounds ) {
- LogError(_("Attempt to read script data beyond end of %s table"), isgpos ? "GPOS" : "GSUB" );
- info->bad_ot = true;
-return( NULL );
- }
- fseek(ttf,pos,SEEK_SET);
- cnt = getushort(ttf);
- if ( cnt<=0 )
-return( NULL );
- else if ( cnt>1000 ) {
- LogError( _("Too many scripts %d\n"), cnt );
- info->bad_ot = true;
-return( NULL );
- }
-
- scripts = gcalloc(cnt+1,sizeof(struct scripts));
- for ( i=0; i<cnt; ++i ) {
- scripts[i].tag = getlong(ttf);
- scripts[i].offset = getushort(ttf);
- }
- for ( i=0; i<cnt; ++i ) {
- fseek(ttf,pos+scripts[i].offset,SEEK_SET);
- deflang = getushort(ttf);
- lcnt = getushort(ttf);
- lcnt += (deflang!=0);
- scripts[i].langcnt = lcnt;
- scripts[i].languages = gcalloc(lcnt+1,sizeof(struct language));
- j = 0;
- if ( deflang!=0 ) {
- scripts[i].languages[0].tag = CHR('d','f','l','t');
- scripts[i].languages[0].offset = deflang+scripts[i].offset;
- ++j;
- }
- for ( ; j<lcnt; ++j ) {
- scripts[i].languages[j].tag = getlong(ttf);
- scripts[i].languages[j].offset = scripts[i].offset+getushort(ttf);
- }
- for ( j=0; j<lcnt; ++j ) {
- if ( pos+scripts[i].languages[j].offset>=info->g_bounds ) {
- LogError(_("Attempt to read script data beyond end of %s table"), isgpos ? "GPOS" : "GSUB" );
- info->bad_ot = true;
-return( NULL );
- }
- fseek(ttf,pos+scripts[i].languages[j].offset,SEEK_SET);
- (void) getushort(ttf); /* lookup ordering table undefined */
- scripts[i].languages[j].req = getushort(ttf);
- scripts[i].languages[j].fcnt = getushort(ttf);
- if ( feof(ttf)) {
- LogError(_("End of file when reading scripts in %s table"), isgpos ? "GPOS" : "GSUB" );
- info->bad_ot = true;
-return( NULL );
- }
- scripts[i].languages[j].features = galloc(scripts[i].languages[j].fcnt*sizeof(uint16));
- for ( k=0; k<scripts[i].languages[j].fcnt; ++k )
- scripts[i].languages[j].features[k] = getushort(ttf);
- }
- }
-
- if ( feof(ttf)) {
- LogError(_("End of file in %s table"), isgpos ? "GPOS" : "GSUB" );
- info->bad_ot = true;
-return( NULL );
- }
-
-return( scripts );
-}
-
-static struct feature *readttffeatures(FILE *ttf,int32 pos,int isgpos, struct ttfinfo *info) {
- /* read the features table returning an array containing all interesting */
- /* features */
- int cnt;
- int i,j;
- struct feature *features;
- int parameters;
-
- if ( pos>=(int32)info->g_bounds ) {
- LogError(_("Attempt to read feature data beyond end of %s table"), isgpos ? "GPOS" : "GSUB" );
- info->bad_ot = true;
-return( NULL );
- }
- fseek(ttf,pos,SEEK_SET);
- info->feature_cnt = cnt = getushort(ttf);
- if ( cnt<=0 )
-return( NULL );
- else if ( cnt>1000 ) {
- LogError( _("Too many features %d\n"), cnt );
- info->bad_ot = true;
-return( NULL );
- }
-
- features = gcalloc(cnt+1,sizeof(struct feature));
- for ( i=0; i<cnt; ++i ) {
- features[i].tag = getlong(ttf);
- features[i].offset = getushort(ttf);
- }
-
- for ( i=0; i<cnt; ++i ) {
- if ( pos+features[i].offset>=info->g_bounds ) {
- LogError(_("Attempt to read feature data beyond end of %s table"), isgpos ? "GPOS" : "GSUB" );
- info->bad_ot = true;
-return( NULL );
- }
- fseek(ttf,pos+features[i].offset,SEEK_SET);
- parameters = getushort(ttf);
- if ( features[i].tag==CHR('s','i','z','e') && parameters!=0 && !feof(ttf))
- readttfsizeparameters(ttf,pos+parameters,
- pos+parameters+features[i].offset,info);
- features[i].lcnt = getushort(ttf);
- if ( feof(ttf) ) {
- LogError(_("End of file when reading features in %s table"), isgpos ? "GPOS" : "GSUB" );
- info->bad_ot = true;
-return( NULL );
- }
- features[i].lookups = galloc(features[i].lcnt*sizeof(uint16));
- for ( j=0; j<features[i].lcnt; ++j )
- features[i].lookups[j] = getushort(ttf);
- }
-
-return( features );
-}
-
-static struct lookup *readttflookups(FILE *ttf,int32 pos, struct ttfinfo *info, int isgpos) {
- int cnt,i,j;
- struct lookup *lookups;
- OTLookup *otlookup, *last=NULL;
- struct lookup_subtable *st;
-
- if ( pos>=(int32)info->g_bounds ) {
- LogError(_("Attempt to read lookup data beyond end of %s table"), isgpos ? "GPOS" : "GSUB" );
- info->bad_ot = true;
-return( NULL );
- }
-
- fseek(ttf,pos,SEEK_SET);
- info->lookup_cnt = cnt = getushort(ttf);
- info->cur_lookups = NULL;
- if ( cnt<=0 )
-return( NULL );
- else if ( cnt>1000 ) {
- LogError( _("Too many lookups %d\n"), cnt );
- info->bad_ot = true;
-return( NULL );
- }
-
- lookups = gcalloc(cnt+1,sizeof(struct lookup));
- for ( i=0; i<cnt; ++i )
- lookups[i].offset = getushort(ttf);
- for ( i=0; i<cnt; ++i ) {
- if ( pos+lookups[i].offset>=info->g_bounds ) {
- LogError(_("Attempt to read lookup data beyond end of %s table"), isgpos ? "GPOS" : "GSUB" );
- info->bad_ot = true;
-return( NULL );
- }
- fseek(ttf,pos+lookups[i].offset,SEEK_SET);
- lookups[i].type = getushort(ttf);
- lookups[i].flags = getushort(ttf);
- lookups[i].subtabcnt = getushort(ttf);
- lookups[i].subtab_offsets = galloc(lookups[i].subtabcnt*sizeof(int32));
- for ( j=0; j<lookups[i].subtabcnt; ++j )
- lookups[i].subtab_offsets[j] = pos+lookups[i].offset+getushort(ttf);
-
- lookups[i].otlookup = otlookup = chunkalloc(sizeof(OTLookup));
- otlookup->lookup_index = i;
- if ( last==NULL )
- info->cur_lookups = otlookup;
- else
- last->next = otlookup;
- last = otlookup;
- otlookup->lookup_type = (isgpos<<8) | lookups[i].type;
- otlookup->lookup_flags = lookups[i].flags;
- otlookup->lookup_index = i;
- if ( feof(ttf) ) {
- LogError(_("End of file when reading lookups in %s table"), isgpos ? "GPOS" : "GSUB" );
- info->bad_ot = true;
-return( NULL );
- }
- for ( j=0; j<lookups[i].subtabcnt; ++j ) {
- st = chunkalloc(sizeof(struct lookup_subtable));
- st->next = otlookup->subtables;
- st->lookup = otlookup;
- otlookup->subtables = st;
- }
- }
- if ( isgpos )
- info->gpos_lookups = info->cur_lookups;
- else
- info->gsub_lookups = info->cur_lookups;
-return( lookups );
-}
-
-static void tagLookupsWithFeature(uint32 script_tag,uint32 lang_tag,
- int required_feature, struct feature *feature, struct lookup *lookups,
- struct ttfinfo *info) {
- uint32 feature_tag = required_feature ? REQUIRED_FEATURE : feature->tag;
- int i;
- OTLookup *otlookup;
- FeatureScriptLangList *fl;
-
- /* The otf docs are ambiguous as to the capitalization of the default */
- /* script. The capitalized version is correct (uncapitalized is used for languages) */
- if ( script_tag == DEFAULT_LANG )
- script_tag = DEFAULT_SCRIPT;
-
- for ( i=0; i < feature->lcnt; ++i ) {
- if ( feature->lookups[i]>=info->lookup_cnt ) {
- LogError( _("Lookup out of bounds in feature table.\n") );
- info->bad_ot = true;
- } else {
- otlookup = lookups[feature->lookups[i]].otlookup;
- for ( fl = otlookup->features; fl!=NULL && fl->featuretag!=feature_tag; fl=fl->next );
- if ( fl==NULL ) {
- fl = chunkalloc(sizeof(FeatureScriptLangList));
- fl->featuretag = feature_tag;
- fl->next = otlookup->features;
- otlookup->features = fl;
- }
- FListAppendScriptLang(fl,script_tag,lang_tag);
- }
- }
-}
-
-static void tagLookupsWithScript(struct scripts *scripts,
- struct feature *features, struct lookup *lookups,struct ttfinfo *info ) {
- int i,j;
- struct scripts *s;
- struct language *lang;
- struct lookup *l;
-
- if ( scripts==NULL || features==NULL )
-return; /* Legal, I'd guess, but not very interesting. Perhaps all lookups are controlled by the JSTF table or something */
-
- /* First tag every lookup with all script, lang, feature combinations that*/
- /* invoke it */
- for ( s=scripts; s->tag!=0; ++s ) {
- for ( lang=s->languages, i=0; i<s->langcnt; ++i, ++lang ) {
- if ( lang->req==0xffff )
- /* Do Nothing */;
- else if ( lang->req>= info->feature_cnt ) {
- LogError( _("Required feature out of bounds in script table.\n") );
- info->bad_ot = true;
- } else
- tagLookupsWithFeature(s->tag,lang->tag,true,&features[lang->req],
- lookups,info);
- for ( j=0; j<lang->fcnt; ++j ) {
- if ( lang->features[j]>=info->feature_cnt ) {
- LogError( _("Feature out of bounds in script table.\n") );
- info->bad_ot = true;
- } else
- tagLookupsWithFeature(s->tag,lang->tag,false,&features[lang->features[j]],
- lookups,info);
- }
- }
- }
-
- /* The scripts got added backwards so reverse to put them in */
- /* alphabetic order again */
- for ( l=lookups, i=0; l->offset!=0; ++l, ++i ) {
- OTLookup *otl = l->otlookup;
- FeatureScriptLangList *fl;
- struct scriptlanglist *sl, *next, *prev;
- for ( fl=otl->features; fl!=NULL; fl=fl->next ) {
- prev = NULL;
- for ( sl=fl->scripts; sl!=NULL; sl = next ) {
- next = sl->next;
- sl->next = prev;
- prev = sl;
- }
- fl->scripts = prev;
- }
- }
-}
-
-static void gposExtensionSubTable(FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable,
- struct lookup *alllooks) {
- uint32 base = ftell(ttf), st, offset;
- int lu_type;
- (void)stoffset; /* for -Wall */
- /* Format = */ getushort(ttf);
- lu_type = getushort(ttf);
- offset = getlong(ttf);
-
- l->otlookup->lookup_type = 0x100|lu_type;
-
- fseek(ttf,st = base+offset,SEEK_SET);
- switch ( lu_type ) {
- case 1:
- gposSimplePos(ttf,st,info,l,subtable);
- break;
- case 2:
- gposKernSubTable(ttf,st,info,l,subtable);
- break;
- case 3:
- gposCursiveSubTable(ttf,st,info,l,subtable);
- break;
- case 4: case 5: case 6:
- gposMarkSubTable(ttf,st,info,l,subtable);
- break;
- case 7:
- gposContextSubTable(ttf,st,info,l,subtable,alllooks);
- break;
- case 8:
- gposChainingSubTable(ttf,st,info,l,subtable,alllooks);
- break;
- case 9:
- LogError( _("This font is erroneous: it has a GPOS extension subtable that points to\nanother extension sub-table.\n") );
- info->bad_ot = true;
- break;
-/* Any cases added here also need to go in the gposLookupSwitch */
- default:
- LogError( _("Unknown GPOS sub-table type: %d\n"), lu_type );
- info->bad_ot = true;
- break;
- }
- if ( ftell(ttf)>info->gpos_start+info->gpos_length ) {
- LogError( _("Subtable extends beyond end of GPOS table\n") );
- info->bad_ot = true;
- }
-}
-
-static void gsubExtensionSubTable(FILE *ttf, int stoffset,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
- struct lookup *alllooks) {
- uint32 base = ftell(ttf), st, offset;
- int lu_type;
- (void)stoffset; /* for -Wall */
- /* Format = */ getushort(ttf);
- lu_type = getushort(ttf);
- offset = getlong(ttf);
-
- l->otlookup->lookup_type = lu_type;
-
- fseek(ttf,st = base+offset,SEEK_SET);
- switch ( lu_type ) {
- case 1:
- gsubSimpleSubTable(ttf,st,info,l,subtable,justinuse);
- break;
- case 2: case 3: /* Multiple and alternate have same format, different semantics */
- gsubMultipleSubTable(ttf,st,info,l,subtable,justinuse);
- break;
- case 4:
- gsubLigatureSubTable(ttf,st,info,l,subtable,justinuse);
- break;
- case 5:
- gsubContextSubTable(ttf,st,info,l,subtable,justinuse,alllooks);
- break;
- case 6:
- gsubChainingSubTable(ttf,st,info,l,subtable,justinuse,alllooks);
- break;
- case 7:
- LogError( _("This font is erroneous: it has a GSUB extension subtable that points to\nanother extension sub-table.\n") );
- info->bad_ot = true;
- break;
- case 8:
- gsubReverseChainSubTable(ttf,st,info,l,subtable,justinuse);
- break;
-/* Any cases added here also need to go in the gsubLookupSwitch */
- default:
- LogError( _("Unknown GSUB sub-table type: %d\n"), lu_type );
- info->bad_ot = true;
- break;
- }
- if ( ftell(ttf)>info->gsub_start+info->gsub_length ) {
- LogError( _("Subtable extends beyond end of GSUB table\n") );
- info->bad_ot = true;
- }
-}
-
-static void gposLookupSwitch(FILE *ttf, int st,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable,
- struct lookup *alllooks) {
-
- switch ( l->type | 0x100 ) {
- case gpos_single:
- gposSimplePos(ttf,st,info,l,subtable);
- break;
- case gpos_pair:
- gposKernSubTable(ttf,st,info,l,subtable);
- break;
- case gpos_cursive:
- gposCursiveSubTable(ttf,st,info,l,subtable);
- break;
- case gpos_mark2base: case gpos_mark2ligature: case gpos_mark2mark:
- gposMarkSubTable(ttf,st,info,l,subtable);
- break;
- case gpos_context:
- gposContextSubTable(ttf,st,info,l,subtable,alllooks);
- break;
- case gpos_contextchain:
- gposChainingSubTable(ttf,st,info,l,subtable,alllooks);
- break;
- case 0x109:
- gposExtensionSubTable(ttf,st,info,l,subtable,alllooks);
- break;
-/* Any cases added here also need to go in the gposExtensionSubTable */
- default:
- LogError( _("Unknown GPOS sub-table type: %d\n"), l->otlookup->lookup_type );
- info->bad_ot = true;
- break;
- }
- if ( ftell(ttf)>info->gpos_start+info->gpos_length ) {
- LogError( _("Subtable extends beyond end of GPOS table\n") );
- info->bad_ot = true;
- }
-}
-
-static void gsubLookupSwitch(FILE *ttf, int st,
- struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
- struct lookup *alllooks) {
-
- switch ( l->type ) {
- case gsub_single:
- gsubSimpleSubTable(ttf,st,info,l,subtable,justinuse);
- break;
- case gsub_multiple: case gsub_alternate: /* Multiple and alternate have same format, different semantics */
- gsubMultipleSubTable(ttf,st,info,l,subtable,justinuse);
- break;
- case gsub_ligature:
- gsubLigatureSubTable(ttf,st,info,l,subtable,justinuse);
- break;
- case gsub_context:
- gsubContextSubTable(ttf,st,info,l,subtable,justinuse,alllooks);
- break;
- case gsub_contextchain:
- gsubChainingSubTable(ttf,st,info,l,subtable,justinuse,alllooks);
- break;
- case 7:
- gsubExtensionSubTable(ttf,st,info,l,subtable,justinuse,alllooks);
- break;
- case gsub_reversecchain:
- gsubReverseChainSubTable(ttf,st,info,l,subtable,justinuse);
- break;
-/* Any cases added here also need to go in the gsubExtensionSubTable */
- default:
- LogError( _("Unknown GSUB sub-table type: %d\n"), l->otlookup->lookup_type );
- info->bad_ot = true;
- break;
- }
- if ( ftell(ttf)>info->g_bounds ) {
- LogError( _("Subtable extends beyond end of GSUB table\n" ));
- info->bad_ot = true;
- }
-}
-
-static void ScriptsFree(struct scripts *scripts) {
- int i,j;
-
- if ( scripts==NULL )
-return;
- for ( i=0; scripts[i].offset!=0 ; ++i ) {
- for ( j=0; j<scripts[i].langcnt; ++j )
- free( scripts[i].languages[j].features);
- free(scripts[i].languages);
- }
- free(scripts);
-}
-
-static void FeaturesFree(struct feature *features) {
- int i;
-
- if ( features==NULL )
-return;
- for ( i=0; features[i].offset!=0 ; ++i )
- free(features[i].lookups);
- free(features);
-}
-
-static void LookupsFree(struct lookup *lookups) {
- int i;
-
- for ( i=0; lookups[i].offset!=0 ; ++i ) {
- free( lookups[i].subtab_offsets );
- }
- free(lookups);
-}
-
-static void ProcessGPOSGSUB(FILE *ttf,struct ttfinfo *info,int gpos,int inusetype) {
- int k;
- int32 base, lookup_start, st;
- int32 script_off, feature_off;
- struct scripts *scripts;
- struct feature *features;
- struct lookup *lookups, *l;
- struct lookup_subtable *subtable;
-
- if ( gpos ) {
- base = info->gpos_start;
- info->g_bounds = base + info->gpos_length;
- } else {
- base = info->gsub_start;
- info->g_bounds = base + info->gsub_length;
- }
- fseek(ttf,base,SEEK_SET);
- /* version = */ getlong(ttf);
- script_off = getushort(ttf);
- feature_off = getushort(ttf);
- lookup_start = base+getushort(ttf);
-
- scripts = readttfscripts(ttf,base+script_off,info,gpos);
- features = readttffeatures(ttf,base+feature_off,gpos,info);
- /* It is legal to have lookups with no features or scripts */
- /* For example if all the lookups were controlled by the JSTF table */
- lookups = readttflookups(ttf,lookup_start,info,gpos);
- if ( lookups==NULL ) {
- ScriptsFree(scripts);
- FeaturesFree(features);
-return;
- }
- tagLookupsWithScript(scripts,features,lookups,info);
- ScriptsFree(scripts); scripts = NULL;
- FeaturesFree(features); features = NULL;
-
- for ( l = lookups; l->offset!=0; ++l ) {
- for ( k=0, subtable=l->otlookup->subtables; k<l->subtabcnt; ++k, subtable=subtable->next ) {
- st = l->subtab_offsets[k];
- fseek(ttf,st,SEEK_SET);
- if ( gpos ) {
- gposLookupSwitch(ttf,st,info,l,subtable,lookups);
- } else {
- gsubLookupSwitch(ttf,st,info,l,subtable,inusetype,lookups);
- }
- }
- }
-
- /* Then generate some user-friendly names for the all the lookups */
- if ( inusetype==git_normal )
- for ( l=lookups; l->offset!=0; ++l )
- NameOTLookup(l->otlookup,NULL);
-
- LookupsFree(lookups);
- if ( inusetype!=git_normal && !gpos ) {
- OTLookupListFree(info->gsub_lookups);
- info->gsub_lookups = info->cur_lookups = NULL;
- }
-}
-
-void readttfgsubUsed(FILE *ttf,struct ttfinfo *info) {
- ProcessGPOSGSUB(ttf,info,false,git_justinuse);
- info->g_bounds = 0;
-}
-
-void GuessNamesFromGSUB(FILE *ttf,struct ttfinfo *info) {
- ProcessGPOSGSUB(ttf,info,false,git_findnames);
- info->g_bounds = 0;
-}
-
-void readttfgpossub(FILE *ttf,struct ttfinfo *info,int gpos) {
- ProcessGPOSGSUB(ttf,info,gpos,git_normal);
- info->g_bounds = 0;
-}
-
-void readttfgdef(FILE *ttf,struct ttfinfo *info) {
- int lclo, gclass, mac;
- int coverage, cnt, i,j, format;
- uint16 *glyphs, *lc_offsets, *offsets;
- uint32 caret_base;
- uint32 version;
- PST *pst;
- SplineChar *sc;
-
- fseek(ttf,info->gdef_start,SEEK_SET);
-
- version = getlong(ttf) ;
- if (version != 0x00010000 && version != 0x00010002)
- return;
-
- info->g_bounds = info->gdef_start + info->gdef_length;
- gclass = getushort(ttf);
- /* attach list = */ getushort(ttf);
- lclo = getushort(ttf); /* ligature caret list */
- mac = getushort(ttf); /* mark attach class */
-
- if (version == 0x00010002)
- getushort(ttf); /* class defs */
-
- if ( gclass!=0 ) {
- uint16 *gclasses = getClassDefTable(ttf,info->gdef_start+gclass, info);
- for ( i=0; i<info->glyph_cnt; ++i )
- if ( info->chars[i]!=NULL && gclasses[i]!=0 )
- info->chars[i]->glyph_class = gclasses[i]+1;
- free(gclasses);
- }
-
- if ( mac!=0 ) {
- uint16 *mclasses = getClassDefTable(ttf,info->gdef_start+mac, info);
- const char *format_spec = _("MarkClass-%d");
- info->mark_class_cnt = ClassFindCnt(mclasses,info->glyph_cnt);
- info->mark_classes = ClassToNames(info,info->mark_class_cnt,mclasses,info->glyph_cnt);
- info->mark_class_names = galloc(info->mark_class_cnt*sizeof(char *));
- info->mark_class_names[0] = NULL;
- for ( i=1; i<info->mark_class_cnt; ++i ) {
- info->mark_class_names[i] = galloc((strlen(format_spec)+10));
- sprintf( info->mark_class_names[i], format_spec, i );
- }
- free(mclasses);
- }
-
- if ( lclo!=0 ) {
- lclo += info->gdef_start;
- fseek(ttf,lclo,SEEK_SET);
- coverage = getushort(ttf);
- cnt = getushort(ttf);
- if ( cnt==0 )
-return;
- lc_offsets = galloc(cnt*sizeof(uint16));
- for ( i=0; i<cnt; ++i )
- lc_offsets[i]=getushort(ttf);
- glyphs = getCoverageTable(ttf,lclo+coverage,info);
- if ( glyphs==NULL )
-return;
- for ( i=0; i<cnt; ++i ) if ( glyphs[i]<info->glyph_cnt ) {
- fseek(ttf,lclo+lc_offsets[i],SEEK_SET);
- sc = info->chars[glyphs[i]];
- for ( pst=sc->possub; pst!=NULL && pst->type!=pst_lcaret; pst=pst->next );
- if ( pst==NULL ) {
- pst = chunkalloc(sizeof(PST));
- pst->next = sc->possub;
- sc->possub = pst;
- pst->type = pst_lcaret;
- pst->subtable = NULL;
- sc->lig_caret_cnt_fixed = true;
- }
- caret_base = ftell(ttf);
- pst->u.lcaret.cnt = getushort(ttf);
- if ( pst->u.lcaret.carets!=NULL ) free(pst->u.lcaret.carets);
- offsets = galloc(pst->u.lcaret.cnt*sizeof(uint16));
- for ( j=0; j<pst->u.lcaret.cnt; ++j )
- offsets[j] = getushort(ttf);
- pst->u.lcaret.carets = galloc(pst->u.lcaret.cnt*sizeof(int16));
- for ( j=0; j<pst->u.lcaret.cnt; ++j ) {
- fseek(ttf,caret_base+offsets[j],SEEK_SET);
- format=getushort(ttf);
- if ( format==1 ) {
- pst->u.lcaret.carets[j] = getushort(ttf);
- } else if ( format==2 ) {
- pst->u.lcaret.carets[j] = 0;
- /* point = */ getushort(ttf);
- } else if ( format==3 ) {
- pst->u.lcaret.carets[j] = getushort(ttf);
- /* in device table = */ getushort(ttf);
- } else {
- LogError( _("!!!! Unknown caret format %d !!!!\n"), format );
- info->bad_ot = true;
- }
- }
- free(offsets);
- }
- free(lc_offsets);
- free(glyphs);
- }
- info->g_bounds = 0;
-}
-
-static void OTLAppend(struct ttfinfo *info,OTLookup *otl,int gpos) {
- OTLookup *prev;
- int pos=0;
-
- if ( gpos && info->gpos_lookups == NULL )
- info->gpos_lookups = otl;
- else if ( !gpos && info->gsub_lookups == NULL )
- info->gsub_lookups = otl;
- else {
- prev = gpos ? info->gpos_lookups : info->gsub_lookups;
- pos = 1;
- while ( prev->next!=NULL ) {
- prev = prev->next;
- ++pos;
- }
- prev->next = otl;
- }
- otl->lookup_index = pos;
-}
-
-static void OTLRemove(struct ttfinfo *info,OTLookup *otl,int gpos) {
- /* Remove the most recent lookup. We got bad data and can't use it */
- OTLookup *prev, **base;
-
- base = gpos ? &info->gpos_lookups : &info->gsub_lookups;
- if ( *base==otl )
- *base = NULL;
- else if ( *base!=NULL ) {
- for ( prev = *base; prev->next!=NULL && prev->next!=otl; prev = prev->next );
- prev->next = NULL;
- }
- OTLookupFree(otl);
-}
-
-static void InfoNameOTLookup(OTLookup *otl,struct ttfinfo *info) {
- SplineFont sf;
-
- memset(&sf,0,sizeof(sf));
- NameOTLookup(otl,&sf);
-}
-
-/* Apple's docs imply that kerning info is always provided left to right, even*/
-/* for right to left scripts. My guess is that their docs are wrong, as they */
-/* often are, but if that be so then we need code in here to reverse */
-/* the order of the characters for right to left since pfaedit's convention */
-/* is to follow writing order rather than to go left to right */
-void readttfkerns(FILE *ttf,struct ttfinfo *info) {
- int tabcnt, len, coverage,i,j, npairs, version, format, flags_good, tab;
- int left, right, offset, array, rowWidth;
- int header_size;
- KernPair *kp;
- KernClass *kc;
- uint32 begin_table;
- uint16 *class1, *class2;
- int isv;
- OTLookup *otl;
-
- fseek(ttf,info->kern_start,SEEK_SET);
- version = getushort(ttf);
- tabcnt = getushort(ttf);
- if ( version!=0 ) {
- LogError(_("Invalid or unsupported version (0x%x) for 'kern' table"), version );
- info->bad_gx = true;
-return;
- }
- for ( tab=0; tab<tabcnt; ++tab ) {
- begin_table = ftell(ttf);
- /* version = */ getushort(ttf);
- len = getushort(ttf);
- coverage = getushort(ttf);
- format = coverage>>8;
- flags_good = ((coverage&7)<=1);
- isv = !(coverage&1);
- header_size = 6;
- otl = NULL;
- if ( flags_good ) {
- otl = chunkalloc(sizeof(OTLookup));
- otl->lookup_type = gpos_pair;
- otl->subtables = chunkalloc(sizeof(struct lookup_subtable));
- otl->subtables->lookup = otl;
- otl->subtables->per_glyph_pst_or_kern = true;
- otl->subtables->vertical_kerning = isv;
- otl->features = chunkalloc(sizeof(FeatureScriptLangList));
- if (isv)
- otl->features->featuretag = CHR('v','k','r','n');
- else
- otl->features->featuretag = CHR('k','e','r','n');
- OTLAppend(info,otl,true);
- }
- if ( flags_good && format==0 ) {
- /* format 0, horizontal kerning data (as pairs) not perpendicular */
- SplineChar **chars = info->chars;
- npairs = getushort(ttf);
- if ( len-14 != 6*npairs || npairs>10920 ) {
- LogError( _("In the 'kern' table, a subtable's length does not match the number of kerning pairs.") );
- info->bad_gx = true;
- }
- /* searchRange = */ getushort(ttf);
- /* entrySelector = */ getushort(ttf);
- /* rangeShift = */ getushort(ttf);
- otl->subtables[0].per_glyph_pst_or_kern = true;
- for ( j=0; j<npairs; ++j ) {
- left = getushort(ttf);
- right = getushort(ttf);
- offset = (short) getushort(ttf);
- if ( left<0 || right<0 ) {
- /* We've seen such buggy fonts... */
- LogError( _("Bad kern pair: glyphs %d & %d mustn't be negative\n"),
- left, right );
- info->bad_gx = true;
- } else if ( left>=info->glyph_cnt || right>=info->glyph_cnt ) {
- /* Holes happen when reading ttc files. They are probably ok */
- LogError( _("Bad kern pair: glyphs %d & %d must be less than %d\n"),
- left, right, info->glyph_cnt );
- info->bad_gx = true;
- } else if (chars[left]==NULL || chars[right]==NULL ) {
- /* Shouldn't happen. */
- LogError( _("Bad kern pair: glyphs at %d & %d are null\n"),
- left, right);
- info->bad_gx = true;
- } else {
- kp = chunkalloc(sizeof(KernPair));
- kp->sc = chars[right];
- kp->off = offset;
- kp->subtable = otl->subtables;
- FListsAppendScriptLang(otl->features,SCScriptFromUnicode(chars[left]),
- DEFAULT_LANG);
- if ( isv ) {
- kp->next = chars[left]->vkerns;
- chars[left]->vkerns = kp;
- } else {
- kp->next = chars[left]->kerns;
- chars[left]->kerns = kp;
- }
- }
- }
- InfoNameOTLookup(otl,info);
- } else if ( flags_good && (format==2 || format==3 )) {
- /* two class based formats */
- KernClass **khead, **klast;
- if ( isv ) {
- khead = &info->vkhead;
- klast = &info->vklast;
- } else {
- khead = &info->khead;
- klast = &info->klast;
- }
- if ( *khead==NULL )
- *khead = kc = chunkalloc(sizeof(KernClass));
- else
- kc = (*klast)->next = chunkalloc(sizeof(KernClass));
- *klast = kc;
- if ( format==2 ) {
- rowWidth = getushort(ttf);
- left = getushort(ttf);
- right = getushort(ttf);
- array = getushort(ttf);
- kc->second_cnt = rowWidth/sizeof(uint16);
- class1 = getAppleClassTable(ttf, begin_table+left, info->glyph_cnt, array, rowWidth, info );
- class2 = getAppleClassTable(ttf, begin_table+right, info->glyph_cnt, 0, sizeof(uint16), info );
- for ( i=0; i<info->glyph_cnt; ++i )
- if ( class1[i]>kc->first_cnt )
- kc->first_cnt = class1[i];
- ++ kc->first_cnt;
- kc->offsets = galloc(kc->first_cnt*kc->second_cnt*sizeof(int16));
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- kc->adjusts = gcalloc(kc->first_cnt*kc->second_cnt,sizeof(DeviceTable));
-#endif
- fseek(ttf,begin_table+array,SEEK_SET);
- for ( i=0; i<kc->first_cnt*kc->second_cnt; ++i )
- kc->offsets[i] = getushort(ttf);
- } else {
- /* format 3, horizontal kerning data (as classes limited to 256 entries) */
- /* OpenType's spec doesn't document this */
- int gc, kv, flags;
- int16 *kvs;
- gc = getushort(ttf);
- kv = getc(ttf);
- kc->first_cnt = getc(ttf);
- kc->second_cnt = getc(ttf);
- flags = getc(ttf);
- if ( gc>info->glyph_cnt ) {
- LogError( _("Kerning subtable 3 says the glyph count is %d, but maxp says %d\n"),
- gc, info->glyph_cnt );
- info->bad_gx = true;
- }
- class1 = gcalloc(gc>info->glyph_cnt?gc:info->glyph_cnt,sizeof(uint16));
- class2 = gcalloc(gc>info->glyph_cnt?gc:info->glyph_cnt,sizeof(uint16));
- kvs = galloc(kv*sizeof(int16));
- kc->offsets = galloc(kc->first_cnt*kc->second_cnt*sizeof(int16));
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- kc->adjusts = gcalloc(kc->first_cnt*kc->second_cnt,sizeof(DeviceTable));
-#endif
- for ( i=0; i<kv; ++i )
- kvs[i] = (int16) getushort(ttf);
- for ( i=0; i<gc; ++i )
- class1[i] = getc(ttf);
- for ( i=0; i<gc; ++i )
- class2[i] = getc(ttf);
- for ( i=0; i<kc->first_cnt*kc->second_cnt; ++i )
- kc->offsets[i] = kvs[getc(ttf)];
- free(kvs);
- }
- kc->firsts = ClassToNames(info,kc->first_cnt,class1,info->glyph_cnt);
- kc->seconds = ClassToNames(info,kc->second_cnt,class2,info->glyph_cnt);
- for ( i=0; i<info->glyph_cnt; ++i ) {
- if ( class1[i]>=4 && info->chars[i]!=NULL )
- FListsAppendScriptLang(otl->features,
- SCScriptFromUnicode(info->chars[i]),
- DEFAULT_LANG);
- }
- free(class1); free(class2);
- fseek(ttf,begin_table+len,SEEK_SET);
- otl->subtables[0].kc = kc;
- kc->subtable = otl->subtables;
- InfoNameOTLookup(otl,info);
- } else {
- LogError(_("Invalid or unsupported format (%d) for subtable of 'kern' table"), format );
- info->bad_gx = true;
- fseek(ttf,len-header_size,SEEK_CUR);
- if ( otl!=NULL )
- OTLRemove(info,otl,true);
- }
- }
-}
-
-/******************************************************************************/
-/* ******************************* MATH Table ******************************* */
-/* ********************** (Not strictly OpenType yet) *********************** */
-/******************************************************************************/
-
-/* ******************************** Read MATH ******************************* */
-
-static void ttf_math_read_constants(FILE *ttf,struct ttfinfo *info, uint32 start) {
- struct MATH *math;
- int i;
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- uint16 off;
-#endif
-
- fseek(ttf,start,SEEK_SET);
- info->math = math = gcalloc(1,sizeof(struct MATH));
-
- for ( i=0; math_constants_descriptor[i].script_name!=NULL; ++i ) {
- int16 *pos = (int16 *) (((char *) (math)) + math_constants_descriptor[i].offset );
- if ( pos == (int16 *) &math->MinConnectorOverlap )
- continue; /* Actually lives in the Variant table, not here */
- *pos = getushort(ttf);
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- if ( math_constants_descriptor[i].devtab_offset >= 0 ) {
- DeviceTable **devtab = (DeviceTable **) (((char *) (math)) + math_constants_descriptor[i].devtab_offset );
- off = getushort(ttf);
- if ( off!=0 ) {
- *devtab = chunkalloc(sizeof(DeviceTable));
- ReadDeviceTable(ttf,*devtab,start+off,info);
- }
- }
-#else
- /* No support for device tables, skip it */
- if ( math_constants_descriptor[i].devtab_offset != -1 )
- (void) getushort(ttf);
-#endif
- }
-}
-
-static void ttf_math_read_icta(FILE *ttf,struct ttfinfo *info, uint32 start, int is_ic) {
- /* The italic correction and top accent sub-tables have the same format */
- int coverage, cnt, i, val, offset;
- uint16 *glyphs;
-
- fseek(ttf,start,SEEK_SET);
- coverage = getushort(ttf);
- cnt = getushort(ttf);
- glyphs = getCoverageTable(ttf,start+coverage,info);
- if ( glyphs==NULL )
-return;
- fseek(ttf,start+4,SEEK_SET);
- for ( i=0; i<cnt; ++i ) {
- val = (int16) getushort(ttf);
- offset = getushort(ttf);
- if ( glyphs[i]<info->glyph_cnt && info->chars[ glyphs[i]]!=NULL ) {
- if ( is_ic )
- info->chars[ glyphs[i] ]->italic_correction = val;
- else
- info->chars[ glyphs[i] ]->top_accent_horiz = val;
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- if ( offset!=0 ) {
- DeviceTable *dv = chunkalloc(sizeof(DeviceTable));
- ReadDeviceTable(ttf,dv,start+offset,info);
- if ( is_ic )
- info->chars[ glyphs[i] ]->italic_adjusts = dv;
- else
- info->chars[ glyphs[i] ]->top_accent_adjusts = dv;
- }
-#endif
- }
- }
- free(glyphs);
-}
-
-static void ttf_math_read_extended(FILE *ttf,struct ttfinfo *info, uint32 start) {
- int i;
- uint16 *glyphs;
-
- glyphs = getCoverageTable(ttf,start,info);
- if ( glyphs==NULL )
-return;
- for ( i=0; glyphs[i]!=0xffff; ++i ) if ( glyphs[i]<info->glyph_cnt && info->chars[ glyphs[i]]!=NULL )
- info->chars[ glyphs[i] ]->is_extended_shape = true;
- free(glyphs);
-}
-
-static void ttf_math_read_mathkernv(FILE *ttf, uint32 start,struct mathkernvertex *mkv,
- SplineChar *sc, int istop, struct ttfinfo *info) {
- int cnt, i;
- (void)info; /* for -Wall */
- fseek(ttf,start,SEEK_SET);
- /* There is one more width than height. I store the width count */
- /* and guess a dummy height later */
- mkv->cnt = cnt = getushort(ttf)+1;
- mkv->mkd = gcalloc(cnt,sizeof(struct mathkerndata));
-
- for ( i=0; i<cnt-1; ++i ) {
- mkv->mkd[i].height = getushort(ttf);
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- mkv->mkd[i].height_adjusts = (void *) (intpt) getushort(ttf);
-#else
- (void) getushort(ttf);
-#endif
- }
-
- for ( i=0; i<cnt; ++i ) {
- mkv->mkd[i].kern = getushort(ttf);
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- mkv->mkd[i].kern_adjusts = (void *) (intpt) getushort(ttf);
-#else
- (void) getushort(ttf);
-#endif
- }
-
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- for ( i=0; i<cnt; ++i ) {
- DeviceTable *dv;
- uint32 offset;
- if ( mkv->mkd[i].height_adjusts!=NULL ) {
- offset = start + (intpt) mkv->mkd[i].height_adjusts;
- mkv->mkd[i].height_adjusts = dv = chunkalloc(sizeof(DeviceTable));
- ReadDeviceTable(ttf,dv,offset,info);
- }
- if ( mkv->mkd[i].kern_adjusts!=NULL ) {
- offset = start + (intpt) mkv->mkd[i].kern_adjusts;
- mkv->mkd[i].kern_adjusts = dv = chunkalloc(sizeof(DeviceTable));
- ReadDeviceTable(ttf,dv,offset,info);
- }
- }
-#endif
-
- if ( cnt>=3 )
- mkv->mkd[cnt-1].height = 2*mkv->mkd[cnt-2].height - mkv->mkd[cnt-3].height;
- else if ( cnt>=2 )
- mkv->mkd[cnt-1].height = mkv->mkd[cnt-2].height + 100;
- else if ( cnt==1 ) {
- if ( istop ) {
- DBounds b;
- SplineCharQuickBounds(sc,&b);
- mkv->mkd[cnt-1].height = b.maxy;
- } else
- mkv->mkd[cnt-1].height = 0;
- }
-}
-
-static void ttf_math_read_mathkern(FILE *ttf,struct ttfinfo *info, uint32 start) {
- int coverage, cnt, i;
- uint16 *glyphs;
- struct koff { uint16 tr, tl, br, bl; } *koff;
-
- fseek(ttf,start,SEEK_SET);
- coverage = getushort(ttf);
- cnt = getushort(ttf);
- koff = galloc(cnt*sizeof(struct koff));
- for ( i=0; i<cnt; ++i ) {
- koff[i].tr = getushort(ttf);
- koff[i].tl = getushort(ttf);
- koff[i].br = getushort(ttf);
- koff[i].bl = getushort(ttf);
- }
- glyphs = getCoverageTable(ttf,start+coverage,info);
- if ( glyphs==NULL ) {
- free(koff);
-return;
- }
- for ( i=0; i<cnt; ++i ) if ( glyphs[i]<info->glyph_cnt && info->chars[ glyphs[i]]!=NULL ) {
- SplineChar *sc = info->chars[ glyphs[i]];
- sc->mathkern = chunkalloc(sizeof(struct mathkern));
- if ( koff[i].tr!=0 )
- ttf_math_read_mathkernv(ttf,start+koff[i].tr,&sc->mathkern->top_right,sc,true,info);
- if ( koff[i].tl!=0 )
- ttf_math_read_mathkernv(ttf,start+koff[i].tl,&sc->mathkern->top_left,sc,true,info);
- if ( koff[i].br!=0 )
- ttf_math_read_mathkernv(ttf,start+koff[i].br,&sc->mathkern->bottom_right,sc,false,info);
- if ( koff[i].bl!=0 )
- ttf_math_read_mathkernv(ttf,start+koff[i].bl,&sc->mathkern->bottom_left,sc,false,info);
- }
- free(koff);
- free(glyphs);
-}
-
-static void ttf_math_read_glyphinfo(FILE *ttf,struct ttfinfo *info, uint32 start) {
- int icoff,taoff,esoff,kioff;
-
- fseek(ttf,start,SEEK_SET);
- icoff = getushort(ttf);
- taoff = getushort(ttf);
- esoff = getushort(ttf);
- kioff = getushort(ttf);
-
- if ( icoff!=0 )
- ttf_math_read_icta(ttf,info,start+icoff,true);
- if ( taoff!=0 )
- ttf_math_read_icta(ttf,info,start+taoff,false);
- if ( esoff!=0 )
- ttf_math_read_extended(ttf,info,start+esoff);
- if ( kioff!=0 )
- ttf_math_read_mathkern(ttf,info,start+kioff);
-}
-
-static struct glyphvariants *ttf_math_read_gvtable(FILE *ttf,struct ttfinfo *info, uint32 start,
- enum gsub_inusetype justinuse, SplineChar *basesc, int isv ) {
- struct glyphvariants *gv = chunkalloc(sizeof(struct glyphvariants));
- int ga_offset;
- int vcnt;
- uint16 *glyphs;
- int i, j, len;
- char *pt;
- int ic_offset, pcnt;
- SplineChar *sc;
- char ebuf[20], buffer[50], *ext;
-
- fseek(ttf,start,SEEK_SET);
- ga_offset = getushort(ttf);
- vcnt = getushort(ttf);
- if ( vcnt!=0 ) {
- if ( justinuse==git_justinuse ) {
- for ( i=0; i<vcnt; ++i ) {
- int gid = getushort(ttf);
- /* sizes[i] = */ getushort(ttf);
- if ( gid>=0 && gid<info->glyph_cnt )
- info->inuse[gid] = true;
- }
- } else if ( justinuse==git_findnames ) {
- for ( i=0; i<vcnt; ++i ) {
- int gid = getushort(ttf);
- /* sizes[i] = */ getushort(ttf);
- if ( basesc!=NULL && basesc->name!=NULL &&
- gid>=0 && gid<info->glyph_cnt &&
- (sc = info->chars[gid])!=NULL && sc->name==NULL ) {
- snprintf(buffer,sizeof(buffer),"%.30s.%csize%d",
- basesc->name, isv?'v':'h', i);
- sc->name = copy(buffer);
- }
- }
- } else {
- glyphs = galloc(vcnt*sizeof(uint16));
- len = 0;
- for ( i=0; i<vcnt; ++i ) {
- glyphs[i] = getushort(ttf);
- /* sizes[i] = */ getushort(ttf);
- if ( glyphs[i]<info->glyph_cnt && (sc = info->chars[ glyphs[i]])!=NULL )
- len += strlen(sc->name)+1;
- }
- if ( len!=0 ) {
- gv->variants = pt = galloc(len);
- for ( i=len=0; i<vcnt; ++i ) {
- if ( glyphs[i]<info->glyph_cnt && (sc = info->chars[ glyphs[i]])!=NULL ) {
- strcpy(pt+len,sc->name);
- len += strlen(sc->name);
- pt[len++] = ' ';
- }
- }
- pt[len-1] = '\0';
- }
- free(glyphs);
- }
- }
- if ( ga_offset!=0 ) {
- start += ga_offset;
- fseek(ttf,start,SEEK_SET);
- gv->italic_correction = getushort(ttf);
- ic_offset = getushort(ttf);
- gv->part_cnt = pcnt = getushort(ttf);
- if ( justinuse==git_normal )
- gv->parts = gcalloc(pcnt,sizeof(struct gv_part));
- for ( i=j=0; i<pcnt; ++i ) {
- int gid, start, end, full, flags;
- gid = getushort(ttf);
- start = getushort(ttf);
- end = getushort(ttf);
- full = getushort(ttf);
- flags = getushort(ttf);
- if ( feof(ttf)) {
- LogError( _("Bad glyph variant subtable of MATH table.\n") );
- info->bad_ot = true;
- chunkfree(gv,sizeof(*gv));
-return( NULL );
- }
- if ( justinuse==git_justinuse ) {
- if ( gid<info->glyph_cnt )
- info->inuse[gid] = true;
- } else if ( justinuse==git_findnames ) {
- if ( basesc!=NULL && basesc->name!=NULL &&
- gid>=0 && gid<info->glyph_cnt &&
- (sc = info->chars[gid])!=NULL && sc->name==NULL ) {
- if ( pcnt==1 )
- ext = "repeat";
- if ( i==0 )
- ext = isv ? "bot" : "left";
- else if ( i==pcnt-1 )
- ext = isv ? "top" : "right";
- else if ( i==1 && pcnt==3 )
- ext = "mid";
- else {
- sprintf( ebuf, "%cpart%d", isv?'v':'h', i );
- ext = ebuf;
- }
- snprintf(buffer,sizeof(buffer),"%.30s.%s",
- basesc->name, ext );
- sc->name = copy(buffer);
- }
- } else {
- if ( gid<info->glyph_cnt && (sc = info->chars[gid])!=NULL ) {
- gv->parts[j].component = copy( sc->name );
- gv->parts[j].startConnectorLength = start;
- gv->parts[j].endConnectorLength = end;
- gv->parts[j].fullAdvance = full;
- gv->parts[j++].is_extender = flags&1;
- }
- }
- }
- gv->part_cnt = j;
-#ifdef FONTFORGE_CONFIG_DEVICETABLES
- if ( ic_offset!=0 && justinuse==git_normal ) {
- gv->italic_adjusts = chunkalloc(sizeof(DeviceTable));
- ReadDeviceTable(ttf,gv->italic_adjusts,start+ic_offset,info);
- }
-#endif
- }
- if ( justinuse==git_justinuse ) {
- chunkfree(gv,sizeof(*gv));
-return( NULL );
- }
-return( gv );
-}
-
-static void ttf_math_read_variants(FILE *ttf,struct ttfinfo *info, uint32 start,
- enum gsub_inusetype justinuse) {
- int vcoverage, hcoverage, vcnt, hcnt;
- int *hoffs, *voffs;
- uint16 *hglyphs, *vglyphs;
- int i;
-
- fseek(ttf,start,SEEK_SET);
- if ( info->math==NULL )
- info->math = gcalloc(1,sizeof(struct MATH));
- info->math->MinConnectorOverlap = getushort(ttf);
- vcoverage = getushort(ttf);
- hcoverage = getushort(ttf);
- vcnt = getushort(ttf);
- hcnt = getushort(ttf);
- hoffs = galloc(hcnt*sizeof(int));
- voffs = galloc(vcnt*sizeof(int));
-
- for ( i=0; i<vcnt; ++i )
- voffs[i] = getushort(ttf);
- for ( i=0; i<hcnt; ++i )
- hoffs[i] = getushort(ttf);
- vglyphs = hglyphs = NULL;
- if ( vcoverage!=0 )
- vglyphs = getCoverageTable(ttf,start+vcoverage,info);
- if ( hcoverage!=0 )
- hglyphs = getCoverageTable(ttf,start+hcoverage,info);
-
- if ( vglyphs!=NULL ) {
- for ( i=0; i<vcnt; ++i ) if ( vglyphs[i]<info->glyph_cnt && voffs[i]!=0) {
- if ( justinuse == git_normal || justinuse == git_findnames ) {
- SplineChar *sc = info->chars[ vglyphs[i]];
- if ( sc!=NULL )
- sc->vert_variants = ttf_math_read_gvtable(ttf,info,start+voffs[i],justinuse,sc,true);
- } else if ( info->inuse[ vglyphs[i]])
- ttf_math_read_gvtable(ttf,info,start+voffs[i],justinuse,NULL,true);
- }
- }
- if ( hglyphs!=NULL ) {
- for ( i=0; i<hcnt; ++i ) if ( hglyphs[i]<info->glyph_cnt && hoffs[i]!=0) {
- if ( justinuse == git_normal || justinuse == git_findnames ) {
- SplineChar *sc = info->chars[ hglyphs[i]];
- if ( sc!=NULL )
- sc->horiz_variants = ttf_math_read_gvtable(ttf,info,start+hoffs[i],justinuse,sc,false);
- } else if ( info->inuse[ hglyphs[i]])
- ttf_math_read_gvtable(ttf,info,start+hoffs[i],justinuse,NULL,false);
- }
- }
-
- free(vglyphs); free(voffs);
- free(hglyphs); free(hoffs);
-}
-
-static void _otf_read_math(FILE *ttf,struct ttfinfo *info,
- enum gsub_inusetype justinuse) {
- int constants, glyphinfo, variants;
- if ( info->math_start==0 )
-return;
- fseek(ttf,info->math_start,SEEK_SET);
-
- info->g_bounds = info->math_start+info->math_length;
-
- if ( getlong(ttf)!=0x00010000 )
-return;
- constants = getushort(ttf);
- glyphinfo = getushort(ttf);
- variants = getushort(ttf);
-
- if ( justinuse == git_normal ) {
- if ( constants!=0 )
- ttf_math_read_constants(ttf,info,info->math_start+constants);
- if ( glyphinfo!=0 )
- ttf_math_read_glyphinfo(ttf,info,info->math_start+glyphinfo);
- }
- if ( variants!=0 )
- ttf_math_read_variants(ttf,info,info->math_start+variants,justinuse);
- if ( ftell(ttf)>info->g_bounds ) {
- LogError("MATH table extends beyond table bounds");
- info->bad_ot = true;
- }
- info->g_bounds = 0;
-}
-
-void otf_read_math(FILE *ttf,struct ttfinfo *info) {
- _otf_read_math(ttf,info,git_normal);
-}
-
-void otf_read_math_used(FILE *ttf,struct ttfinfo *info) {
- _otf_read_math(ttf,info,git_justinuse);
-}
-
-void GuessNamesFromMATH(FILE *ttf,struct ttfinfo *info) {
- _otf_read_math(ttf,info,git_findnames);
-}
-
-static struct baselangextent *readttfbaseminmax(FILE *ttf,uint32 offset,struct ttfinfo *info,
- uint32 script_tag,uint32 lang_tag) {
- int j,feat_cnt;
- struct baselangextent *lang, *cur, *last;
- (void)info; /* for -Wall */
- (void)script_tag; /* for -Wall */
- fseek(ttf,offset,SEEK_SET);
- lang = chunkalloc(sizeof(struct baselangextent));
- lang->lang = lang_tag;
- lang->descent = (short) getushort(ttf);
- lang->ascent = (short) getushort(ttf);
-
- feat_cnt = getushort(ttf);
- last = NULL;
- for ( j=0; j<feat_cnt; ++j ) {
- cur = chunkalloc(sizeof(struct baselangextent));
- if ( last==NULL )
- lang->features = cur;
- else
- last->next = cur;
- last = cur;
- cur->lang = getlong(ttf); /* Actually feature tag here */
- cur->descent = (short) getushort(ttf);
- cur->ascent = (short) getushort(ttf);
- }
-return( lang );
-}
-
-void readttfbase(FILE *ttf,struct ttfinfo *info) {
- int version;
- uint32 axes[2];
- uint32 basetags, basescripts;
- int basescriptcnt;
- struct tagoff { uint32 tag; uint32 offset; } *bs;
- int axis,i,j, tot;
- struct Base *curBase;
- struct basescript *curScript, *last;
- struct baselangextent *cur, *lastLang;
-
- if ( info->base_start==0 )
-return;
- fseek(ttf,info->base_start,SEEK_SET);
-
- version = getlong(ttf);
- if ( version!=0x00010000 )
-return;
- axes[0] = getushort(ttf); /* Horizontal */
- axes[1] = getushort(ttf); /* Vertical */
-
- for ( axis=0; axis<2; ++axis ) {
- if ( axes[axis]==0 )
- continue;
- fseek(ttf,info->base_start+axes[axis],SEEK_SET);
- curBase = chunkalloc(sizeof(struct Base));
- if ( axis==0 ) info->horiz_base = curBase; else info->vert_base = curBase;
- basetags = getushort(ttf);
- basescripts = getushort(ttf);
- if ( basetags==0 ) {
- curBase->baseline_cnt = 0;
- curBase->baseline_tags = NULL;
- } else {
- fseek(ttf,info->base_start+axes[axis]+basetags,SEEK_SET);
- curBase->baseline_cnt = getushort(ttf);
- curBase->baseline_tags = gcalloc(curBase->baseline_cnt,sizeof(uint32));
- for ( i=0; i<curBase->baseline_cnt; ++i )
- curBase->baseline_tags[i] = getlong(ttf);
- }
- if ( basescripts!=0 ) {
- fseek(ttf,info->base_start+axes[axis]+basescripts,SEEK_SET);
- basescriptcnt = getushort(ttf);
- bs = gcalloc(basescriptcnt,sizeof(struct tagoff));
- for ( i=0; i<basescriptcnt; ++i ) {
- bs[i].tag = getlong(ttf);
- bs[i].offset = getushort(ttf);
- if ( bs[i].offset != 0 )
- bs[i].offset += info->base_start+axes[axis]+basescripts;
- }
- last = NULL;
- for ( i=0; i<basescriptcnt; ++i ) if ( bs[i].offset!=0 ) {
- int basevalues, defminmax;
- int langsyscnt;
- struct tagoff *ls;
- fseek(ttf,bs[i].offset,SEEK_SET);
- basevalues = getushort(ttf);
- defminmax = getushort(ttf);
- langsyscnt = getushort(ttf);
- ls = gcalloc(langsyscnt,sizeof(struct tagoff));
- for ( j=0; j<langsyscnt; ++j ) {
- ls[j].tag = getlong(ttf);
- ls[j].offset = getushort(ttf);
- }
- curScript = chunkalloc(sizeof(struct basescript));
- if ( last==NULL )
- curBase->scripts = curScript;
- else
- last->next = curScript;
- last = curScript;
- curScript->script = bs[i].tag;
- if ( basevalues!=0 ) {
- int coordcnt;
- int *coords;
-
- fseek( ttf,bs[i].offset+basevalues,SEEK_SET);
- curScript->def_baseline = getushort(ttf);
- tot = coordcnt = getushort(ttf);
- if ( coordcnt!=curBase->baseline_cnt ) {
- info->bad_ot = true;
- LogError( "!!!!! Coord count (%d) for '%c%c%c%c' script does not match base tag count (%d) in 'BASE' table\n",
- coordcnt,
- bs[i].tag>>24, bs[i].tag>>16, bs[i].tag>>8, bs[i].tag,
- curBase->baseline_cnt );
- if ( tot<curBase->baseline_cnt )
- tot = curBase->baseline_cnt;
- }
- coords = gcalloc(coordcnt,sizeof(int));
- curScript->baseline_pos = gcalloc(tot,sizeof(int16));
- for ( j=0; j<coordcnt; ++j )
- coords[j] = getushort(ttf);
- for ( j=0; j<coordcnt; ++j ) if ( coords[j]!=0 ) {
- int format;
- fseek( ttf,bs[i].offset+basevalues+coords[j],SEEK_SET);
- format = getushort(ttf);
- curScript->baseline_pos[j] = (short) getushort(ttf);
- if ( format!=1 && format!=2 && format!=3 ) {
- info->bad_ot = true;
- LogError("!!!!! Bad Base Coord format (%d) for '%c%c%c%c' in '%c%c%c%c' script in 'BASE' table\n",
- format,
- curBase->baseline_tags[j]>>24, curBase->baseline_tags[j]>>16, curBase->baseline_tags[j]>>8, curBase->baseline_tags[j],
- bs[i].tag>>24, bs[i].tag>>16, bs[i].tag>>8, bs[i].tag );
- }
- }
- free(coords);
- }
- lastLang = NULL;
- if ( defminmax!=0 )
- curScript->langs = lastLang = readttfbaseminmax(ttf,bs[i].offset+defminmax,info,bs[i].tag,DEFAULT_LANG);
- if ( langsyscnt!=0 ) {
- for ( j=0; j<langsyscnt; ++j ) if ( ls[j].offset!=0 ) {
- cur = readttfbaseminmax(ttf,bs[i].offset+ls[j].offset,info,bs[i].tag,ls[j].tag);
- if ( last==NULL )
- curScript->langs = cur;
- else
- lastLang->next = cur;
- lastLang = cur;
- }
- }
- free(ls);
- }
- free(bs);
- }
- }
-}