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.c1926
1 files changed, 24 insertions, 1902 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
index b6c45fe956f..97974e3baf5 100644
--- a/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfatt.c
+++ b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfatt.c
@@ -31,7 +31,6 @@
#include <math.h>
#include <locale.h>
#include <stdlib.h>
-#include <ggadget.h> /* For GTextInfo */
#include "ttf.h"
static uint16 *getAppleClassTable(FILE *ttf, int classdef_offset, int cnt, int sub, int div, struct ttfinfo *info) {
@@ -1770,6 +1769,7 @@ static struct { uint32 tag; char *str; } tagstr[] = {
{ 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;
@@ -2928,113 +2928,6 @@ return;
info->g_bounds = 0;
}
-static void readttf_applelookup(FILE *ttf,struct ttfinfo *info,
- void (*apply_values)(struct ttfinfo *info, int gfirst, int glast,FILE *ttf),
- void (*apply_value)(struct ttfinfo *info, int gfirst, int glast,FILE *ttf),
- void (*apply_default)(struct ttfinfo *info, int gfirst, int glast,void *def),
- void *def, int allow_out_of_bounds) {
- int format, i, first, last, data_off, cnt, prev;
- uint32 here;
- uint32 base = ftell(ttf);
-
- format = getushort(ttf);
- switch ( format ) {
- case 0: /* Simple array */
- apply_values(info,0,info->glyph_cnt-1,ttf);
- break;
- case 2: /* Segment Single */
- /* Entry size */ getushort(ttf);
- cnt = getushort(ttf);
- /* search range */ getushort(ttf);
- /* log2(cnt) */ getushort(ttf);
- /* range shift */ getushort(ttf);
- prev = 0;
- for ( i=0; i<cnt; ++i ) {
- last = getushort(ttf);
- first = getushort(ttf);
- if ( last<first || last>=0xffff ||
- (!allow_out_of_bounds && last>=info->glyph_cnt )) {
- LogError( _("Bad lookup table: format=2 (%d/%d), first=%d last=%d total glyphs in font=%d\n"),
- i,cnt,first,last,info->glyph_cnt );
- info->bad_gx = true;
- } else {
- if ( apply_default!=NULL )
- apply_default(info,prev,first-1,def);
- apply_value(info,first,last,ttf);
- prev = last+1;
- }
- }
- break;
- case 4: /* Segment multiple */
- /* Entry size */ getushort(ttf);
- cnt = getushort(ttf);
- /* search range */ getushort(ttf);
- /* log2(cnt) */ getushort(ttf);
- /* range shift */ getushort(ttf);
- prev = 0;
- for ( i=0; i<cnt; ++i ) {
- last = getushort(ttf);
- first = getushort(ttf);
- data_off = getushort(ttf);
- if ( last<first || last>=0xffff ||
- (!allow_out_of_bounds && last>=info->glyph_cnt )) {
- LogError( _("Bad lookup table: format=4 (%d/%d), first=%d last=%d total glyphs in font=%d\n"),
- i,cnt,first,last,info->glyph_cnt );
- info->bad_gx = true;
- } else {
- here = ftell(ttf);
- if ( apply_default!=NULL )
- apply_default(info,prev,first-1,def);
- fseek(ttf,base+data_off,SEEK_SET);
- apply_values(info,first,last,ttf);
- fseek(ttf,here,SEEK_SET);
- prev = last+1;
- }
- }
- break;
- case 6: /* Single table */
- /* Entry size */ getushort(ttf);
- cnt = getushort(ttf);
- /* search range */ getushort(ttf);
- /* log2(cnt) */ getushort(ttf);
- /* range shift */ getushort(ttf);
- prev = 0;
- for ( i=0; i<cnt; ++i ) {
- first = getushort(ttf);
- if ( first>=0xffff || (!allow_out_of_bounds && first>=info->glyph_cnt )) {
- LogError( _("Bad lookup table: format=6, first=%d total glyphs in font=%d\n"),
- first,info->glyph_cnt );
- info->bad_gx = true;
- } else {
- if ( apply_default!=NULL )
- apply_default(info,prev,first-1,def);
- apply_value(info,first,first,ttf);
- prev = first+1;
- }
- }
- break;
- case 8: /* Simple array */
- first = getushort(ttf);
- cnt = getushort(ttf);
- if ( first+cnt>=0xffff || (!allow_out_of_bounds && first+cnt>=info->glyph_cnt )) {
- LogError( _("Bad lookup table: format=8, first=%d cnt=%d total glyphs in font=%d\n"),
- first,cnt,info->glyph_cnt );
- info->bad_gx = true;
- } else {
- if ( apply_default!=NULL ) {
- apply_default(info,0,first-1,def);
- apply_default(info,first+cnt,info->glyph_cnt-1,def);
- }
- apply_values(info,first,first+cnt-1,ttf);
- }
- break;
- default:
- LogError( _("Invalid lookup table format. %d\n"), format );
- info->bad_gx = true;
- break;
- }
-}
-
static void OTLAppend(struct ttfinfo *info,OTLookup *otl,int gpos) {
OTLookup *prev;
int pos=0;
@@ -3069,1544 +2962,13 @@ static void OTLRemove(struct ttfinfo *info,OTLookup *otl,int gpos) {
OTLookupFree(otl);
}
-static OTLookup *NewMacLookup(struct ttfinfo *info,int gpos) {
- OTLookup *otl;
-
- otl = chunkalloc(sizeof(OTLookup));
- otl->lookup_type = gpos ? kern_statemachine : morx_context;
- otl->subtables = chunkalloc(sizeof(struct lookup_subtable));
- otl->subtables->lookup = otl;
- otl->features = chunkalloc(sizeof(FeatureScriptLangList));
- if ( gpos )
- otl->features->featuretag = CHR('k','e','r','n');
- else {
- otl->features->featuretag = (info->mort_feat<<16) | (info->mort_setting);
- otl->features->ismac = true;
- }
- OTLAppend(info,otl,gpos);
-return( otl );
-}
-
-static OTLookup *NewMacSubsLookup(struct ttfinfo *info,OTLookup *parent,
- int nest_index, OTLookup **subs) {
- OTLookup *otl;
- char *name, *format;
-
- if ( subs[nest_index]!=NULL )
-return( subs[nest_index] );
-
- /* These are nested lookups, only to be activated by a state machine */
- /* as such they have no feature tags nor scripts of their own. */
- otl = chunkalloc(sizeof(OTLookup));
- otl->lookup_type = gsub_single;
- otl->subtables = chunkalloc(sizeof(struct lookup_subtable));
- otl->subtables->lookup = otl;
-/* GT: This is to give the name to a nested substitution lookup invoked by */
-/* GT: a statemachine. The %s is the name of the statemachine('s lookup) */
-/* GT: and the %d is n, where this lookup is the n'th defined for this state */
-/* GT: machine */
-#ifdef LUA_FF_LIB
- format = _("%s_ns_%d");
-#else
- format = _("%s nested-substitutions %d");
-#endif
- name = galloc(strlen(parent->lookup_name)+strlen(format)+10);
- sprintf( name, format, parent->lookup_name, nest_index );
- otl->lookup_name = name;
-#ifdef LUA_FF_LIB
- otl->subtables->subtable_name = strconcat(name,"_s");
-#else
- otl->subtables->subtable_name = strconcat3(name," ",_("subtable"));
-#endif
- OTLAppend(info,otl,false);
- subs[nest_index] = otl;
-return( otl );
-}
-
static void InfoNameOTLookup(OTLookup *otl,struct ttfinfo *info) {
SplineFont sf;
memset(&sf,0,sizeof(sf));
- sf.features = info->features;
NameOTLookup(otl,&sf);
}
-static void TTF_SetProp(struct ttfinfo *info,int gnum, int prop) {
- int offset;
- PST *pst;
-
- if ( gnum<0 || gnum>=info->glyph_cnt ) {
- LogError( _("Glyph out of bounds in 'prop' table %d\n"), gnum );
- info->bad_gx = true;
-return;
- }
-
- if ( prop&0x1000 ) { /* Mirror */
- offset = (prop<<20)>>28;
- if ( gnum+offset>=0 && gnum+offset<info->glyph_cnt &&
- info->chars[gnum+offset]->name!=NULL ) {
- pst = chunkalloc(sizeof(PST));
- pst->type = pst_substitution;
- pst->subtable = info->mort_subs_lookup->subtables;
- FListAppendScriptLang(info->mort_subs_lookup->features,SCScriptFromUnicode(info->chars[gnum]),
- DEFAULT_LANG);
- pst->next = info->chars[gnum]->possub;
- info->chars[gnum]->possub = pst;
- pst->u.subs.variant = copy(info->chars[gnum+offset]->name);
- }
- }
-}
-
-static void prop_apply_values(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
- int i;
-
- for ( i=gfirst; i<=glast; ++i )
- TTF_SetProp(info,i, getushort(ttf));
-}
-
-static void prop_apply_value(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
- int i;
- int prop;
-
- prop = getushort(ttf);
- for ( i=gfirst; i<=glast; ++i )
- TTF_SetProp(info,i, prop);
-}
-
-static void prop_apply_default(struct ttfinfo *info, int gfirst, int glast,void *def) {
- int def_prop, i;
-
- def_prop = (intpt) def;
- for ( i=gfirst; i<=glast; ++i )
- TTF_SetProp(info,i, def_prop);
-}
-
-void readttfprop(FILE *ttf,struct ttfinfo *info) {
- int def;
-
- fseek(ttf,info->prop_start,SEEK_SET);
- /* The one example that I've got has a wierd version, so I don't check it */
- /* the three versions that I know about are all pretty much the same, just a few extra flags */
- /* version = */ getlong(ttf);
- /* format = */ getushort(ttf);
- def = getushort(ttf);
- info->mort_subs_lookup = NewMacLookup(info,false);
- info->mort_subs_lookup->lookup_type = gsub_single;
- info->mort_subs_lookup->features->featuretag = CHR('r','t','l','a');
- info->mort_subs_lookup->features->ismac = false;
- info->mort_subs_lookup->subtables->per_glyph_pst_or_kern = true;
- readttf_applelookup(ttf,info,
- prop_apply_values,prop_apply_value,
- prop_apply_default,(void *) (intpt) def, false);
- InfoNameOTLookup(info->mort_subs_lookup,info);
-}
-
-static void TTF_SetLcaret(struct ttfinfo *info, int gnum, int offset, FILE *ttf) {
- uint32 here = ftell(ttf);
- PST *pst;
- SplineChar *sc;
- int cnt, i;
-
- if ( gnum<0 || gnum>=info->glyph_cnt ) {
- LogError( _("Glyph out of bounds in 'lcar' table %d\n"), gnum );
- info->bad_gx = true;
-return;
- } else if ( (sc=info->chars[gnum])==NULL )
-return;
-
- fseek(ttf,info->lcar_start+offset,SEEK_SET);
- cnt = getushort(ttf);
- pst = chunkalloc(sizeof(PST));
- pst->type = pst_lcaret;
- pst->subtable = NULL;
- pst->next = sc->possub;
- sc->possub = pst;
- sc->lig_caret_cnt_fixed = true;
- pst->u.lcaret.cnt = cnt;
- pst->u.lcaret.carets = galloc(cnt*sizeof(uint16));
- for ( i=0; i<cnt; ++i )
- pst->u.lcaret.carets[i] = getushort(ttf);
- fseek(ttf,here,SEEK_SET);
-}
-
-static void lcar_apply_values(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
- int i;
-
- for ( i=gfirst; i<=glast; ++i )
- TTF_SetLcaret(info,i, getushort(ttf), ttf);
-}
-
-static void lcar_apply_value(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
- int i;
- int offset;
-
- offset = getushort(ttf);
- for ( i=gfirst; i<=glast; ++i )
- TTF_SetLcaret(info,i, offset, ttf);
-}
-
-void readttflcar(FILE *ttf,struct ttfinfo *info) {
-
- fseek(ttf,info->lcar_start,SEEK_SET);
- /* version = */ getlong(ttf);
- if ( getushort(ttf)!=0 ) /* A format type of 1 has the caret locations */
-return; /* indicated by points */
- readttf_applelookup(ttf,info,
- lcar_apply_values,lcar_apply_value,NULL,NULL,false);
-}
-
-static void TTF_SetOpticalBounds(struct ttfinfo *info, int gnum, int left, int right) {
- PST *pst;
- SplineChar *sc;
-
- if ( left==0 && right==0 )
-return;
-
- if ( gnum<0 || gnum>=info->glyph_cnt ) {
- LogError( _("Glyph out of bounds in 'opbd' table %d\n"), gnum );
- info->bad_gx = true;
-return;
- } else if ( (sc=info->chars[gnum])==NULL )
-return;
-
- if ( left!=0 ) {
- pst = chunkalloc(sizeof(PST));
- pst->type = pst_position;
- pst->subtable = info->mort_subs_lookup->subtables;
- FListAppendScriptLang(info->mort_subs_lookup->features,SCScriptFromUnicode(sc),
- DEFAULT_LANG);
- pst->next = sc->possub;
- sc->possub = pst;
- pst->u.pos.xoff = left;
- pst->u.pos.h_adv_off = left;
- }
- if ( right!=0 ) {
- pst = chunkalloc(sizeof(PST));
- pst->type = pst_position;
- pst->subtable = info->mort_pos_lookup2->subtables;
- FListAppendScriptLang(info->mort_pos_lookup2->features,SCScriptFromUnicode(sc),
- DEFAULT_LANG);
- pst->next = sc->possub;
- sc->possub = pst;
- pst->u.pos.h_adv_off = -right;
- }
-}
-
-static void opbd_apply_values(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
- int i, left, right, offset;
- uint32 here;
-
- for ( i=gfirst; i<=glast; ++i ) {
- offset = getushort(ttf);
- here = ftell(ttf);
- fseek(ttf,info->opbd_start+6/*opbd header*/+offset,SEEK_SET);
- left = (int16) getushort(ttf);
- /* top = (int16) */ getushort(ttf);
- right = (int16) getushort(ttf);
- /* bottom = (int16) */ getushort(ttf);
- fseek(ttf,here,SEEK_SET);
- TTF_SetOpticalBounds(info,i, left, right);
- }
-}
-
-static void opbd_apply_value(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
- int i, left, right, offset;
- uint32 here;
-
- offset = getushort(ttf);
- here = ftell(ttf);
- fseek(ttf,info->opbd_start+offset,SEEK_SET);
- left = (int16) getushort(ttf);
- /* top = (int16) */ getushort(ttf);
- right = (int16) getushort(ttf);
- /* bottom = (int16) */ getushort(ttf);
- fseek(ttf,here,SEEK_SET);
-
- for ( i=gfirst; i<=glast; ++i )
- TTF_SetOpticalBounds(info,i, left, right);
-}
-
-void readttfopbd(FILE *ttf,struct ttfinfo *info) {
-
- fseek(ttf,info->opbd_start,SEEK_SET);
- /* version = */ getlong(ttf);
- if ( getushort(ttf)!=0 ) /* A format type of 1 has the bounds */
-return; /* indicated by points */
- info->mort_subs_lookup = NewMacLookup(info,true);
- info->mort_subs_lookup->lookup_type = gpos_single;
- info->mort_subs_lookup->features->featuretag = CHR('l','f','b','d');
- info->mort_subs_lookup->features->ismac = false;
- info->mort_subs_lookup->subtables->per_glyph_pst_or_kern = true;
-
- info->mort_pos_lookup2 = NewMacLookup(info,true);
- info->mort_pos_lookup2->lookup_type = gpos_single;
- info->mort_pos_lookup2->features->featuretag = CHR('r','t','b','d');
- info->mort_pos_lookup2->features->ismac = false;
- info->mort_pos_lookup2->subtables->per_glyph_pst_or_kern = true;
-
- readttf_applelookup(ttf,info,
- opbd_apply_values,opbd_apply_value,NULL,NULL,false);
- InfoNameOTLookup(info->mort_subs_lookup,info);
- InfoNameOTLookup(info->mort_pos_lookup2,info);
-}
-
-/* Interesting. The mac allows the creation of temporary gids beyond the */
-/* range specified by the font, as long as the user never sees them. So */
-/* it seems perfectly legal for one substitution to use a gid of 1111 */
-/* if that gid never reaches output but will be converted into a real gid */
-/* by a subsequent substitution. I saw this used in a conditional situation */
-/* to provide a temporary context for a later match. */
-static SplineChar *CreateBadGid(struct ttfinfo *info,int badgid) {
- int i;
- SplineChar *fake;
- char name[60];
-
- if ( badgid<0 || badgid>=0xffff ) /* <0 should never happen, 0xffff is the special "deleted" glyph, >0xffff should never happen */
-return( NULL );
-
- for ( i=0; i<info->badgid_cnt; ++i )
- if ( info->badgids[i]->orig_pos == badgid )
-return( info->badgids[i] );
-
- if ( info->badgid_cnt>=info->badgid_max )
- info->badgids = grealloc(info->badgids,(info->badgid_max += 20)*sizeof(SplineChar *));
- fake = SplineCharCreate(2);
- fake->orig_pos = badgid;
- sprintf( name, "Out-Of-Range-GID-%d", badgid );
- fake->name = copy(name);
- fake->widthset = true; /* So it doesn't just vanish on us */
- fake->width = fake->vwidth = info->emsize;
- info->badgids[info->badgid_cnt++] = fake;
-return( fake );
-}
-
-static void TTF_SetMortSubs(struct ttfinfo *info, int gnum, int gsubs) {
- PST *pst;
- SplineChar *sc, *ssc;
-
- if ( gsubs==0 )
-return;
-
- if ( gnum<0 || gnum>=info->glyph_cnt ) {
- if ( !info->warned_morx_out_of_bounds_glyph ) {
- LogError( _("Glyph out of bounds in 'mort'/'morx' table %d\n"), gnum );
- info->bad_gx = true;
- info->warned_morx_out_of_bounds_glyph = true;
- }
- sc = CreateBadGid(info,gnum);
- } else
- sc = info->chars[gnum];
- ssc = NULL;
- if ( gsubs<0 || (gsubs>=info->glyph_cnt && gsubs!=0xffff)) {
- if ( !info->warned_morx_out_of_bounds_glyph ) {
- LogError( _("Substitute glyph out of bounds in 'mort'/'morx' table %d\n"), gsubs );
- info->bad_gx = true;
- info->warned_morx_out_of_bounds_glyph = true;
- }
- ssc = CreateBadGid(info,gsubs);
- } else if ( gsubs!=0xffff )
- ssc=info->chars[gsubs];
- if ( sc==NULL || (gsubs!=0xffff && ssc==NULL) )
-return;
-
- pst = chunkalloc(sizeof(PST));
- pst->type = pst_substitution;
- pst->subtable = info->mort_subs_lookup->subtables;
- if ( info->mort_subs_lookup->features!=NULL )
- FListsAppendScriptLang(info->mort_subs_lookup->features,SCScriptFromUnicode(sc),
- DEFAULT_LANG);
- pst->next = sc->possub;
- sc->possub = pst;
- pst->u.subs.variant = gsubs!=0xffff ? copy(ssc->name) : copy(MAC_DELETED_GLYPH_NAME);
-}
-
-static void mort_apply_values(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
- uint16 gnum;
- int i;
-
- for ( i=gfirst; i<=glast; ++i ) {
- gnum = getushort(ttf);
- TTF_SetMortSubs(info,i, gnum);
- }
-}
-
-static void mort_apply_value(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
- uint16 gnum;
- int i;
-
- gnum = getushort(ttf);
-
- for ( i=gfirst; i<=glast; ++i )
- TTF_SetMortSubs(info,i, gnum );
-}
-
-static void mortclass_apply_values(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
- int i;
-
- for ( i=gfirst; i<=glast; ++i )
- info->morx_classes[i] = getushort(ttf);
-}
-
-static void mortclass_apply_value(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
- uint16 class;
- int i;
-
- class = getushort(ttf);
-
- for ( i=gfirst; i<=glast; ++i )
- info->morx_classes[i] = class;
-}
-
-int32 memlong(uint8 *data,int len, int offset) {
- if ( offset>=0 && offset+3<len ) {
- int ch1 = data[offset], ch2 = data[offset+1], ch3 = data[offset+2], ch4 = data[offset+3];
-return( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 );
- } else {
- LogError( _("Bad font, offset out of bounds.\n") );
-return( 0 );
- }
-}
-
-int memushort(uint8 *data,int len, int offset) {
- if ( offset>=0 && offset+1<len ) {
- int ch1 = data[offset], ch2 = data[offset+1];
-return( (ch1<<8)|ch2 );
- } else {
- LogError( _("Bad font, offset out of bounds.\n") );
-return( 0 );
- }
-}
-
-void memputshort(uint8 *data,int offset,uint16 val) {
- data[offset] = (val>>8);
- data[offset+1] = val&0xff;
-}
-
-#define MAX_LIG_COMP 16
-struct statemachine {
- uint8 *data;
- int length;
- uint32 nClasses;
- uint32 classOffset, stateOffset, entryOffset, ligActOff, compOff, ligOff;
- uint16 *classes;
- uint16 lig_comp_classes[MAX_LIG_COMP];
- uint16 lig_comp_glyphs[MAX_LIG_COMP];
- int lcp;
- uint8 *states_in_use;
- int smax;
- struct ttfinfo *info;
- int cnt;
-};
-
-static void mort_figure_ligatures(struct statemachine *sm, int lcp, int off, int32 lig_offset,
- struct ttfinfo *info) {
- uint32 lig;
- int i, j, lig_glyph;
- PST *pst;
- int len;
-
- if ( lcp<0 || off+3>sm->length )
-return;
-
- lig = memlong(sm->data,sm->length, off);
- off += sizeof(int32);
-
- for ( i=0; i<sm->info->glyph_cnt; ++i ) if ( sm->classes[i]==sm->lig_comp_classes[lcp] ) {
- sm->lig_comp_glyphs[lcp] = i;
- lig_offset += memushort(sm->data,sm->length,2*( ((((int32) lig)<<2)>>2) + i ) );
- if ( lig&0xc0000000 ) {
- if ( lig_offset+1 > sm->length ) {
- LogError( _("Invalid ligature offset\n") );
- info->bad_gx = true;
- break;
- }
- lig_glyph = memushort(sm->data,sm->length,lig_offset);
- if ( lig_glyph>=sm->info->glyph_cnt ) {
- LogError( _("Attempt to make a ligature for glyph %d out of "),
- lig_glyph );
- for ( j=lcp; j<sm->lcp; ++j )
- LogError("%d ",sm->lig_comp_glyphs[j]);
- LogError("\n");
- info->bad_gx = true;
- } else {
- char *comp;
- for ( len=0, j=lcp; j<sm->lcp; ++j )
- if ( sm->lig_comp_glyphs[j]<sm->info->glyph_cnt &&
- sm->info->chars[sm->lig_comp_glyphs[j]]!=NULL )
- len += strlen(sm->info->chars[sm->lig_comp_glyphs[j]]->name)+1;
- comp = galloc(len+1);
- *comp = '\0';
- for ( j=lcp; j<sm->lcp; ++j ) {
- if ( sm->lig_comp_glyphs[j]<sm->info->glyph_cnt &&
- sm->info->chars[sm->lig_comp_glyphs[j]]!=NULL ) {
- if ( *comp!='\0' )
- strcat(comp," ");
- strcat(comp,sm->info->chars[sm->lig_comp_glyphs[j]]->name);
- }
- }
- if ( lig_glyph<sm->info->glyph_cnt && sm->info->chars[lig_glyph]!=NULL ) {
- for ( pst=sm->info->chars[lig_glyph]->possub; pst!=NULL; pst=pst->next )
- if ( pst->type==pst_ligature && pst->subtable==sm->info->mort_subs_lookup->subtables &&
- strcmp(comp,pst->u.lig.components)==0 )
- break;
- /* There are cases where there will be multiple entries for */
- /* the same lig. ie. if we have "ff" and "ffl" then there */
- /* will be multiple entries for "ff" */
- if ( pst == NULL ) {
- pst = chunkalloc(sizeof(PST));
- pst->type = pst_ligature;
- pst->subtable = sm->info->mort_subs_lookup->subtables;
- if ( sm->info->mort_subs_lookup->features!=NULL )
- FListsAppendScriptLang(sm->info->mort_subs_lookup->features,
- SCScriptFromUnicode(sm->info->chars[lig_glyph]),
- DEFAULT_LANG);
- pst->u.lig.components = comp;
- pst->u.lig.lig = sm->info->chars[lig_glyph];
- pst->next = sm->info->chars[lig_glyph]->possub;
- sm->info->chars[lig_glyph]->possub = pst;
- } else
- free(comp);
- } else {
- LogError( _("Bad font: Ligature glyph %d is missing\n"), lig_glyph );
- info->bad_gx = true;
- }
- }
- } else
- mort_figure_ligatures(sm,lcp-1,off,lig_offset,info);
- lig_offset -= memushort(sm->data,sm->length,2*( ((((int32) lig)<<2)>>2) + i ) );
- }
-}
-
-static void follow_mort_state(struct statemachine *sm,int offset,int class,
- struct ttfinfo *info) {
- int state = (offset-sm->stateOffset)/sm->nClasses;
- int class_top, class_bottom;
-
- if ( state<0 || state>=sm->smax || sm->states_in_use[state] || sm->lcp>=MAX_LIG_COMP )
-return;
- ++ sm->cnt;
- if ( sm->cnt>=10000 ) {
- if ( sm->cnt==10000 )
-/* GT: This is a reference to "Much Ado About Nothing". The string should read */
-/* GT: "A ligature sub-table in Apple's 'mort'/'morx' table is too\ncomplex for me to understand. I shall give up on it.\nYour ligatures may not be complete." */
- LogError(_("In an attempt to process the ligatures of this font, I've concluded\nthat the state machine in Apple's mort/morx table is\n(like the learned constable) too cunning to be understood.\nI shall give up on it. Your ligatures may be incomplete.\n") );
- info->bad_gx = true;
-return;
- }
- sm->states_in_use[state] = true;
-
- if ( class==-1 ) { class_bottom = 0; class_top = sm->nClasses; }
- else { class_bottom = class; class_top = class+1; }
- for ( class=class_bottom; class<class_top; ++class ) {
- int ent = sm->data[offset+class];
- int newState = memushort(sm->data,sm->length,sm->entryOffset+4*ent);
- int flags = memushort(sm->data,sm->length,sm->entryOffset+4*ent+2);
- /* If we have the same entry as state 0, then presumably we are */
- /* ignoring the components read so far and starting over with a new */
- /* lig (similarly for state 1) */
- if (( state!=0 && sm->data[sm->stateOffset+class] == ent ) ||
- (state>1 && sm->data[sm->stateOffset+sm->nClasses+class]==ent ))
- continue;
- if ( flags&0x8000 ) /* Set component */
- sm->lig_comp_classes[sm->lcp++] = class;
- if ( flags&0x3fff ) {
- mort_figure_ligatures(sm, sm->lcp-1, flags & 0x3fff, 0,info);
- } else if ( flags&0x8000 )
- follow_mort_state(sm,newState,(flags&0x4000)?class:-1,info);
- if ( flags&0x8000 )
- --sm->lcp;
- }
- sm->states_in_use[state] = false;
-}
-
-static void morx_figure_ligatures(struct statemachine *sm, int lcp, int ligindex, int32 lig_offset,
- struct ttfinfo *info) {
- uint32 lig;
- int i, j, lig_glyph;
- PST *pst;
- int len;
-
- if ( lcp<0 || sm->ligActOff+4*ligindex+3>(unsigned)sm->length )
-return;
-
- lig = memlong(sm->data,sm->length, sm->ligActOff+4*ligindex);
- ++ligindex;
-
- for ( i=0; i<sm->info->glyph_cnt; ++i ) if ( sm->classes[i]==sm->lig_comp_classes[lcp] ) {
- sm->lig_comp_glyphs[lcp] = i;
- lig_offset += memushort(sm->data,sm->length,sm->compOff + 2*( ((((int32) lig)<<2)>>2) + i ) );
- if ( lig&0xc0000000 ) {
- if ( sm->ligOff+2*lig_offset+1 > (unsigned)sm->length ) {
- LogError( _("Invalid ligature offset\n") );
- info->bad_gx = true;
- break;
- }
- lig_glyph = memushort(sm->data,sm->length,sm->ligOff+2*lig_offset);
- if ( lig_glyph>=sm->info->glyph_cnt || sm->info->chars[lig_glyph]==NULL ) {
- LogError( _("Attempt to make a ligature for (non-existent) glyph %d out of "),
- lig_glyph );
- info->bad_gx = true;
- for ( j=lcp; j<sm->lcp; ++j )
- LogError("%d ",sm->lig_comp_glyphs[j]);
- LogError("\n");
- } else {
- char *comp;
- for ( len=0, j=lcp; j<sm->lcp; ++j )
- len += strlen(sm->info->chars[sm->lig_comp_glyphs[j]]->name)+1;
- comp = galloc(len);
- *comp = '\0';
- for ( j=lcp; j<sm->lcp; ++j ) {
- if ( *comp!='\0' )
- strcat(comp," ");
- strcat(comp,sm->info->chars[sm->lig_comp_glyphs[j]]->name);
- }
- for ( pst=sm->info->chars[lig_glyph]->possub; pst!=NULL; pst=pst->next )
- if ( pst->type==pst_ligature && pst->subtable==sm->info->mort_subs_lookup->subtables &&
- strcmp(comp,pst->u.lig.components)==0 )
- break;
- /* There are cases where there will be multiple entries for */
- /* the same lig. ie. if we have "ff" and "ffl" then there */
- /* will be multiple entries for "ff" */
- if ( pst == NULL ) {
- pst = chunkalloc(sizeof(PST));
- pst->type = pst_ligature;
- pst->subtable = sm->info->mort_subs_lookup->subtables;
- if ( sm->info->mort_subs_lookup->features!=NULL )
- FListsAppendScriptLang(sm->info->mort_subs_lookup->features,
- SCScriptFromUnicode(sm->info->chars[lig_glyph]),
- DEFAULT_LANG);
- pst->u.lig.components = comp;
- pst->u.lig.lig = sm->info->chars[lig_glyph];
- pst->next = sm->info->chars[lig_glyph]->possub;
- sm->info->chars[lig_glyph]->possub = pst;
- } else
- free(comp);
- }
- } else
- morx_figure_ligatures(sm,lcp-1,ligindex,lig_offset,info);
- lig_offset -= memushort(sm->data,sm->length,sm->compOff + 2*( ((((int32) lig)<<2)>>2) + i ) );
- }
-}
-
-static void follow_morx_state(struct statemachine *sm,int state,int class,
- struct ttfinfo *info) {
- int class_top, class_bottom;
-
- if ( state<0 || state>=sm->smax || sm->states_in_use[state] || sm->lcp>=MAX_LIG_COMP )
-return;
- ++ sm->cnt;
- if ( sm->cnt>=10000 ) {
- if ( sm->cnt==10000 )
- LogError(_("In an attempt to process the ligatures of this font, I've concluded\nthat the state machine in Apple's mort/morx table is\n(like the learned constable) too cunning to be understood.\nI shall give up on it. Your ligatures may be incomplete.\n") );
- info->bad_gx = true;
-return;
- }
- sm->states_in_use[state] = true;
-
- if ( class==-1 ) { class_bottom = 0; class_top = sm->nClasses; }
- else { class_bottom = class; class_top = class+1; }
- for ( class=class_bottom; class<class_top; ++class ) {
- int ent = memushort(sm->data, sm->length,sm->stateOffset + 2*(state*sm->nClasses+class) );
- int newState = memushort(sm->data,sm->length,sm->entryOffset+6*ent);
- int flags = memushort(sm->data,sm->length,sm->entryOffset+6*ent+2);
- int ligindex = memushort(sm->data,sm->length,sm->entryOffset+6*ent+4);
- /* If we have the same entry as state 0, then presumably we are */
- /* ignoring the components read so far and starting over with a new */
- /* lig (similarly for state 1) */
- if (( state!=0 && memushort(sm->data, sm->length,sm->stateOffset + 2*class) == ent ) ||
- (state>1 && memushort(sm->data,sm->length, sm->stateOffset + 2*(sm->nClasses+class))==ent ))
- continue;
- if ( flags&0x8000 ) /* Set component */
- sm->lig_comp_classes[sm->lcp++] = class;
- if ( flags&0x2000 ) {
- morx_figure_ligatures(sm, sm->lcp-1, ligindex, 0,info);
- } else if ( flags&0x8000 )
- follow_morx_state(sm,newState,(flags&0x4000)?class:-1,info);
- if ( flags&0x8000 )
- --sm->lcp;
- }
- sm->states_in_use[state] = false;
-}
-
-static void readttf_mortx_lig(FILE *ttf,struct ttfinfo *info,int ismorx,uint32 base,uint32 length) {
- uint32 here;
- struct statemachine sm;
- int first, cnt, i;
-
- memset(&sm,0,sizeof(sm));
- sm.info = info;
- here = ftell(ttf);
- length -= here-base;
- sm.data = galloc(length);
- sm.length = length;
- if ( fread(sm.data,1,length,ttf)!=length ) {
- free(sm.data);
- LogError( _("Bad mort ligature table. Not long enough\n"));
- info->bad_gx = true;
-return;
- }
- fseek(ttf,here,SEEK_SET);
- if ( ismorx ) {
- sm.nClasses = memlong(sm.data,sm.length, 0);
- sm.classOffset = memlong(sm.data,sm.length, sizeof(int32));
- sm.stateOffset = memlong(sm.data,sm.length, 2*sizeof(int32));
- sm.entryOffset = memlong(sm.data,sm.length, 3*sizeof(int32));
- sm.ligActOff = memlong(sm.data,sm.length, 4*sizeof(int32));
- sm.compOff = memlong(sm.data,sm.length, 5*sizeof(int32));
- sm.ligOff = memlong(sm.data,sm.length, 6*sizeof(int32));
- fseek(ttf,here+sm.classOffset,SEEK_SET);
- /* I used only to allocate space for info->glyph_cnt entries */
- /* but some fonts use out of bounds gids as flags to contextual */
- /* morx subtables, so allocate a full 65536 */
- sm.classes = info->morx_classes = galloc(65536*sizeof(uint16));
- for ( i=0; i<65536; ++i )
- sm.classes[i] = 1; /* Out of bounds */
- readttf_applelookup(ttf,info,
- mortclass_apply_values,mortclass_apply_value,NULL,NULL,true);
- sm.smax = length/(2*sm.nClasses);
- sm.states_in_use = gcalloc(sm.smax,sizeof(uint8));
- follow_morx_state(&sm,0,-1,info);
- } else {
- sm.nClasses = memushort(sm.data,sm.length, 0);
- sm.classOffset = memushort(sm.data,sm.length, sizeof(uint16));
- sm.stateOffset = memushort(sm.data,sm.length, 2*sizeof(uint16));
- sm.entryOffset = memushort(sm.data,sm.length, 3*sizeof(uint16));
- sm.ligActOff = memushort(sm.data,sm.length, 4*sizeof(uint16));
- sm.compOff = memushort(sm.data,sm.length, 5*sizeof(uint16));
- sm.ligOff = memushort(sm.data,sm.length, 6*sizeof(uint16));
- sm.classes = galloc(info->glyph_cnt*sizeof(uint16));
- for ( i=0; i<info->glyph_cnt; ++i )
- sm.classes[i] = 1; /* Out of bounds */
- first = memushort(sm.data,sm.length, sm.classOffset);
- cnt = memushort(sm.data,sm.length, sm.classOffset+sizeof(uint16));
- for ( i=0; i<cnt; ++i )
- sm.classes[first+i] = sm.data[sm.classOffset+2*sizeof(uint16)+i];
- sm.smax = length/sm.nClasses;
- sm.states_in_use = gcalloc(sm.smax,sizeof(uint8));
- follow_mort_state(&sm,sm.stateOffset,-1,info);
- }
- free(sm.data);
- free(sm.states_in_use);
- free(sm.classes);
-}
-
-struct statetable {
- uint32 state_start;
- int nclasses;
- int nstates;
- int nentries;
- int state_offset;
- int entry_size; /* size of individual entry */
- int entry_extras; /* Number of extra glyph offsets */
- int first_glyph; /* that's classifyable */
- int nglyphs;
- uint8 *classes;
- uint8 *state_table; /* state_table[nstates][nclasses], each entry is an */
- /* index into the following array */
- uint16 *state_table2; /* morx version. States are have 2 byte entries */
- uint16 *classes2;
- uint8 *transitions;
- uint32 extra_offsets[3];
-};
-
-static struct statetable *read_statetable(FILE *ttf, int ent_extras, int ismorx, struct ttfinfo *info) {
- struct statetable *st = gcalloc(1,sizeof(struct statetable));
- uint32 here = ftell(ttf);
- int nclasses, class_off, state_off, entry_off;
- int state_max, ent_max, old_state_max, old_ent_max;
- int i, j, ent, new_state, ent_size;
- int error;
-
- st->state_start = here;
-
- if ( ismorx ) {
- nclasses = getlong(ttf);
- class_off = getlong(ttf);
- state_off = getlong(ttf);
- entry_off = getlong(ttf);
- st->extra_offsets[0] = getlong(ttf);
- st->extra_offsets[1] = getlong(ttf);
- st->extra_offsets[2] = getlong(ttf);
- } else {
- nclasses = getushort(ttf); /* Number of bytes per state in state subtable, equal to number of classes */
- class_off = getushort(ttf);
- state_off = getushort(ttf);
- entry_off = getushort(ttf);
- st->extra_offsets[0] = getushort(ttf);
- st->extra_offsets[1] = getushort(ttf);
- st->extra_offsets[2] = getushort(ttf);
- }
- st->nclasses = nclasses;
- st->state_offset = state_off;
-
- /* parse class subtable */
- fseek(ttf,here+class_off,SEEK_SET);
- error = 0;
- if ( ismorx ) {
- /* I used only to allocate space for info->glyph_cnt entries */
- /* but some fonts use out of bounds gids as flags to contextual */
- /* morx subtables, so allocate a full 65536 */
- st->classes2 = info->morx_classes = galloc(65536*sizeof(uint16));
- for ( i=0; i<65536; ++i )
- st->classes2[i] = 1; /* Out of bounds */
- readttf_applelookup(ttf,info,
- mortclass_apply_values,mortclass_apply_value,NULL,NULL,true);
- for ( i=0; i<65536; ++i ) {
- if ( /*st->classes2[i]<0 ||*/ st->classes2[i]>=st->nclasses ) {
- if ( !error )
- LogError( _("Bad class in state machine.\n" ));
- info->bad_gx = true;
- error = true;
- st->classes2[i] = 1; /* Out of bounds */
- }
- }
- } else {
- st->first_glyph = getushort(ttf);
- st->nglyphs = getushort(ttf);
- if ( feof(ttf)) {
- LogError(_("Bad glyph count in mort table.\n"));
- info->bad_gx = true;
- st->nglyphs = 0;
- }
- st->classes = galloc(st->nglyphs);
- fread(st->classes,1,st->nglyphs,ttf);
- for ( i=0; i<st->nglyphs; ++i ) {
- if ( /*st->classes[i]<0 ||*/ st->classes[i]>=st->nclasses ) {
- if ( !error )
- LogError( _("Bad class in state machine.\n" ));
- info->bad_gx = true;
- error = true;
- st->classes[i] = 1; /* Out of bounds */
- }
- }
- }
-
-
- /* The size of an entry is variable. There are 2 uint16 fields at the begin-*/
- /* ning of all entries. There may be some number of shorts following these*/
- /* used for indexing special tables. */
- ent_size = 4 + 2*ent_extras;
- st->entry_size = ent_size;
- st->entry_extras = ent_extras;
-
- /* Apple does not provide a way of figuring out the size of either of the */
- /* state or entry tables, so we must parse both as we go and try to work */
- /* out the maximum values... */
- /* There are always at least 2 states defined. Parse them and find what */
- /* is the biggest entry they use, then parse those entries and find what */
- /* is the biggest state they use, and then repeat until we don't find any*/
- /* more states or entries */
- old_state_max = 0; old_ent_max = 0;
- state_max = 2; ent_max = 0;
- while ( old_state_max!=state_max ) {
- i = old_state_max*nclasses;
- fseek(ttf,here+state_off+(ismorx?(int)(i*sizeof(uint16)):i),SEEK_SET);
- old_state_max = state_max;
- for ( ; i<state_max*nclasses; ++i ) {
- ent = ismorx ? getushort(ttf) : getc(ttf);
- if ( ent+1 > ent_max )
- ent_max = ent+1;
- }
- if ( ent_max==old_ent_max ) /* Nothing more */
- break;
- if ( ent_max>1000 ) {
- LogError( _("It looks to me as though there's a morx sub-table with more than 1000\n transitions. Which makes me think there's probably an error\n" ));
- info->bad_gx = true;
- free(st);
-return( NULL );
- }
- fseek(ttf,here+entry_off+old_ent_max*ent_size,SEEK_SET);
- i = old_ent_max;
- old_ent_max = ent_max;
- for ( ; i<ent_max; ++i ) {
- new_state = getushort(ttf);
- if ( !ismorx )
- new_state = (new_state-state_off)/nclasses;
- /* flags = */ getushort(ttf);
- for ( j=0; j<ent_extras; ++j )
- /* glyphOffsets[j] = */ getushort(ttf);
- if ( new_state+1>state_max )
- state_max = new_state+1;
- }
- if ( state_max>1000 ) {
- LogError( _("It looks to me as though there's a morx sub-table with more than 1000\n states. Which makes me think there's probably an error\n" ));
- info->bad_gx = true;
- free(st);
-return( NULL );
- }
- }
-
- st->nstates = state_max;
- st->nentries = ent_max;
-
- fseek(ttf,here+state_off,SEEK_SET);
- /* an array of arrays of state transitions, each represented by one byte */
- /* which is an index into the Entry subtable, which comes next. */
- /* One dimension is the number of states, and the other the */
- /* number of classes (classes vary faster than states) */
- /* The first two states are predefined, 0 is start of text, 1 start of line*/
- if ( ismorx ) {
- st->state_table2 = galloc(st->nstates*st->nclasses*sizeof(uint16));
- for ( i=0; i<st->nstates*st->nclasses; ++i )
- st->state_table2[i] = getushort(ttf);
- } else {
- st->state_table = galloc(st->nstates*st->nclasses);
- fread(st->state_table,1,st->nstates*st->nclasses,ttf);
- }
-
- /* parse the entry subtable */
- fseek(ttf,here+entry_off,SEEK_SET);
- st->transitions = galloc(st->nentries*st->entry_size);
- fread(st->transitions,1,st->nentries*st->entry_size,ttf);
-return( st );
-}
-
-static void statetablefree(struct statetable *st) {
- free( st->classes );
- free( st->state_table );
- free( st->classes2 );
- free( st->state_table2 );
- free( st->transitions );
- free( st );
-}
-
-static void tagSMWithScriptLang(FeatureScriptLangList *fl,
- struct statetable *st,int ismorx,struct ttfinfo *info) {
- int i;
-
- if ( ismorx ) {
- for ( i=0; i<info->glyph_cnt; ++i )
- if ( st->classes2[i]>=4 && info->chars[i]!=NULL )
- FListsAppendScriptLang(fl,SCScriptFromUnicode(info->chars[i]),
- DEFAULT_LANG);
- } else {
- for ( i=st->first_glyph; i<st->first_glyph+st->nglyphs && i<info->glyph_cnt; ++i )
- if ( info->chars[i]!=NULL )
- FListsAppendScriptLang(fl,SCScriptFromUnicode(info->chars[i]),
- DEFAULT_LANG);
- }
-}
-
-static char **ClassesFromStateTable(struct statetable *st,int ismorx,struct ttfinfo *info) {
- /* On the mac the first four classes should be left blank. only class 1 */
- /* (out of bounds) is supposed to be used in the class array anyway */
- char **classes = galloc(st->nclasses*sizeof(char *));
- int *lens = gcalloc(st->nclasses,sizeof(int));
- int i;
-
-
- if ( ismorx ) {
- for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL )
- lens[st->classes2[i]] += strlen( info->chars[i]->name )+1;
- if ( info->badgids!=NULL )
- for ( i=0; i<info->badgid_cnt; ++i ) if ( info->badgids[i]!=NULL )
- lens[st->classes2[info->badgids[i]->orig_pos]] += strlen( info->badgids[i]->name )+1;
- } else {
- for ( i=st->first_glyph; i<st->first_glyph+st->nglyphs && i<info->glyph_cnt; ++i )
- if ( info->chars[i]!=NULL )
- lens[st->classes[i-st->first_glyph]] += strlen( info->chars[i]->name )+1;
- }
- classes[0] = classes[1] = classes[2] = classes[3] = NULL;
- for ( i=4; i<st->nclasses; ++i ) {
- classes[i] = galloc(lens[i]+1);
- *classes[i] = '\0';
- }
- if ( ismorx ) {
- for ( i=0; i<info->glyph_cnt; ++i ) if ( st->classes2[i]>=4 && info->chars[i]!=NULL ) {
- strcat(classes[st->classes2[i]],info->chars[i]->name );
- strcat(classes[st->classes2[i]]," ");
- }
- if ( info->badgids!=NULL )
- for ( i=0; i<info->badgid_cnt; ++i ) if ( info->badgids[i]!=NULL && st->classes2[info->badgids[i]->orig_pos]>=4) {
- strcat(classes[st->classes2[info->badgids[i]->orig_pos]],info->badgids[i]->name );
- strcat(classes[st->classes2[info->badgids[i]->orig_pos]]," ");
- }
- } else {
- for ( i=st->first_glyph; i<st->first_glyph+st->nglyphs && i<info->glyph_cnt; ++i ) if ( st->classes[i-st->first_glyph]>=4 && info->chars[i]!=NULL ) {
- strcat(classes[st->classes[i-st->first_glyph]],info->chars[i]->name );
- strcat(classes[st->classes[i-st->first_glyph]]," " );
- }
- }
- for ( i=4; i<st->nclasses; ++i ) {
- int len = strlen(classes[i]);
- if ( len!=0 )
- classes[i][len-1] = '\0'; /* Remove trailing space */
- }
- free(lens);
-return( classes );
-}
-
-static char *NamesOfList(uint32 pos,int cnt, FILE *ttf, struct ttfinfo *info) {
- int i, len, glyph;
- char *str;
-
- if ( cnt==0 )
-return(NULL);
-
- fseek(ttf,pos,SEEK_SET);
- for ( i=len=0; i<cnt; ++i ) {
- glyph = getushort(ttf);
- if ( glyph<info->glyph_cnt )
- len += strlen(info->chars[glyph]->name)+1;
- }
- if ( len==0 )
-return( NULL );
- str = galloc(len+1);
- fseek(ttf,pos,SEEK_SET);
- for ( i=len=0; i<cnt; ++i ) {
- glyph = getushort(ttf);
- if ( glyph<info->glyph_cnt ) {
- strcpy(str+len,info->chars[glyph]->name);
- len += strlen(info->chars[glyph]->name);
- str[len++] = ' ';
- }
- }
- str[len-1] = '\0';
-return( str );
-}
-
-#if 0
-static void RunStateFindKernDepth_(ASM *as,int state,int kdepth,uint8 *used) {
- int j, kd;
-
- if ( used[state] )
-return;
- used[state] = true;
-
- for ( j=0; j<as->class_cnt; ++j ) {
- kd = kdepth;
- flags = as->state[state*as->class_cnt+j];
- if ( flags&0x8000 )
- ++kd;
- if ( (flags&0x3fff)!=0 ) {
- as->state[state*as->class_cnt+j].u.kern.kcnt = kd;
- kd = 0;
- }
- RunStateFindKernDepth_(as,as->state[state*as->class_cnt+j].next_state,kd,used);
- }
-}
-
-static void RunStateFindKernDepth(ASM *as) {
- uint8 *used = gcalloc(as->class_cnt);
- int i;
-
- for ( i=0; i<as->class_cnt*as->state_cnt; ++i ) {
- as->state[i].u.kern.kerns = NULL;
- as->state[i].u.kern.kcnt = (as->state[i].flags&0x3fff)==0 ? 0 : -1;
- }
- RunStateFindKernDepth_(as,0,0,used);
- RunStateFindKernDepth_(as,1,0,used);
-}
-#endif
-
-static void KernReadKernList(FILE *ttf,uint32 pos, struct asm_state *trans) {
-/* Apple does not document how to detect the end of the list */
-/* They say "an odd value that depends on coverage" */
-/* They should say "an odd value". Any odd value terminates the list. */
-/* coverage is irrelevant */
-/* Note: List is backwards (glyphs are popped of LIFO so last glyph on */
-/* in stack gets first kern value) */
-/* There are at most 8 glyphs */
- int i,j,k;
- int16 buffer[8]; /* At most 8 kerns are supported */
-
- fseek(ttf,pos,SEEK_SET);
- for ( i=0; i<8; ++i ) {
- buffer[i]=(int16) getushort(ttf);
- if ( buffer[i]&1 ) {
- buffer[i] &= ~1;
- ++i;
- break;
- }
- }
- if ( i==0 ) {
- trans->u.kern.kerns = NULL;
- } else {
- trans->u.kern.kerns = galloc(i*sizeof(int16));
- for ( j=i-1, k=0; k<i; ++k, --j )
- trans->u.kern.kerns[k] = buffer[j];
- }
- trans->u.kern.kcnt = i;
-}
-
-static void read_perglyph_subs(FILE *ttf,struct ttfinfo *info,
- int subs_base,int subs_end,struct statetable *st,
- uint8 *classes_subbed, int evermarked, uint8 *used) {
- /* The file is positioned at the start of a per-glyph substitution table */
- /* Sadly great chunks of this table have been omitted. We are where glyph */
- /* 0 would be if it were present. We've no idea what has been omitted */
- /* Simple checks: if the file pointer is outside of the area devoted to */
- /* substitutions then we know it is ignorable. */
- /* If the current glyph is not in the list of glyphs which could ever */
- /* be substituted then we know it is ignorable. */
- /* Note: the above list is easily figured for substitutions on the current*/
- /* glyph, but if a substitution ever happens to a marked glyph then we */
- /* can't guess. We could check for all classes that get marked, but that*/
- /* doesn't work if there is a current substitution before the class is */
- /* marked, after that we don't know what class the glyph might have */
- /* Instead, for marked subs, we keep track of all locations which were */
- /* used in a current-only sub, and assume that they aren't valid for us */
- /* If the putative substitution glyph is not a valid glyph then we know */
- /* it is ignorable */
- int i, subs, was = info->mort_tag_mac;
- uint32 here;
-
- info->mort_tag_mac = false;
- for ( i=0; i<info->glyph_cnt; ++i ) {
- here = ftell(ttf);
- subs = getushort(ttf);
- if ( subs>=info->glyph_cnt && subs!=0xffff ) /* 0xffff means delete the substituted glyph */
- continue;
- if ( subs==0 ) /* A little risky, one could substitute notdef */
- continue; /* but they shouldn't */
- if ( here<(unsigned)subs_base )
- continue;
- if ( here>=(unsigned)subs_end )
- break;
- if ( evermarked ) {
- if ( used[(here-subs_base)/2] )
- continue;
- } else if ( i<st->first_glyph || i>=st->first_glyph+st->nglyphs ) {
- if ( !classes_subbed[1]) { /* Out of bounds class */
- if ( i>=st->first_glyph+st->nglyphs )
- break;
- continue;
- }
- } else {
- if ( !classes_subbed[st->classes[i-st->first_glyph]] )
- continue;
- }
-
- if ( !evermarked )
- used[(here-subs_base)/2] = true;
- TTF_SetMortSubs(info, i, subs);
- }
- info->mort_tag_mac = was;
-}
-
-static int sm_lookupfind(int32 *lookups,int *_lm,int off) {
- int lm = *_lm, i;
- for ( i=0; i<=lm; ++i )
- if ( lookups[i]==off )
-return( i );
- (*_lm)++;
- lookups[i] = off;
-return( i );
-}
-
-static ASM *readttf_mortx_asm(FILE *ttf,struct ttfinfo *info,int ismorx,
- uint32 subtab_len,enum asm_type type,int extras,
- uint32 coverage, OTLookup *otl) {
- struct statetable *st;
- ASM *as;
- int i,j;
- uint32 here = ftell(ttf);
-
- st = read_statetable(ttf,extras,ismorx,info);
- if ( st==NULL )
-return(NULL);
-
- as = chunkalloc(sizeof(ASM));
- as->type = type;
- as->flags = coverage>>16;
- as->class_cnt = st->nclasses;
- as->state_cnt = st->nstates;
- as->classes = ClassesFromStateTable(st,ismorx,info);
- as->state = galloc(st->nclasses*st->nstates*sizeof(struct asm_state));
- if ( otl==NULL )
- otl = NewMacLookup(info,false);
- otl->lookup_type = type==asm_indic ? morx_indic : type==asm_context ? morx_context : morx_insert;
- as->subtable = otl->subtables; otl->subtables->sm = as;
- tagSMWithScriptLang(otl->features,st,ismorx,info);
- InfoNameOTLookup(otl,info);
- for ( i=0; i<st->nclasses*st->nstates; ++i ) {
- int trans;
- if ( ismorx ) {
- trans = st->state_table2[i];
- as->state[i].next_state = memushort(st->transitions,st->nentries*st->entry_size,trans*st->entry_size);
- } else {
- trans = st->state_table[i];
- as->state[i].next_state = (memushort(st->transitions,st->nentries*st->entry_size,trans*st->entry_size)-st->state_offset)/st->nclasses;
- }
- as->state[i].flags = memushort(st->transitions,st->nentries*st->entry_size,trans*st->entry_size+2);
- if ( extras>0 )
- as->state[i].u.context.mark_lookup = (void *) (intpt) memushort(st->transitions,st->nentries*st->entry_size, trans*st->entry_size+2+2);
- if ( extras>1 )
- as->state[i].u.context.cur_lookup = (void *) (intpt) memushort(st->transitions,st->nentries*st->entry_size, trans*st->entry_size+2+2+2);
- }
- /* Indic tables have no attached subtables, just a verb in the flag field */
- /* so for them we are done. For the others... */
- if ( !ismorx && type==asm_insert ) {
- for ( i=0; i<st->nclasses*st->nstates; ++i ) {
- char *cur=NULL, *mark=NULL;
- if ( (as->state[i].flags&0x3e0)!=0 && as->state[i].u.context.mark_lookup!=NULL ) {
- cur = NamesOfList(here+(intpt) as->state[i].u.context.mark_lookup,
- (as->state[i].flags&0x3e0)>>5,ttf,info);
- }
- if ( (as->state[i].flags&0x01f)!=0 && as->state[i].u.context.cur_lookup!=NULL ) {
- mark = NamesOfList(here+(intpt) as->state[i].u.context.cur_lookup,
- as->state[i].flags&0x01f,ttf,info);
- }
- as->state[i].u.insert.cur_ins=cur;
- as->state[i].u.insert.mark_ins=mark;
- }
- } else if ( ismorx && type == asm_insert ) {
- for ( i=0; i<st->nclasses*st->nstates; ++i ) {
- char *cur=NULL, *mark=NULL;
- if ( (as->state[i].flags&0x3e0)!=0 && (intpt) as->state[i].u.context.mark_lookup!=0xffff ) {
- cur = NamesOfList(here+st->extra_offsets[0]+((intpt) as->state[i].u.context.mark_lookup)*2,
- (as->state[i].flags&0x3e0)>>5,ttf,info);
- }
- if ( (as->state[i].flags&0x01f)!=0 && ((intpt) as->state[i].u.context.cur_lookup)!=0xffff ) {
- mark = NamesOfList(here+st->extra_offsets[0]+((intpt) as->state[i].u.context.cur_lookup)*2,
- as->state[i].flags&0x01f,ttf,info);
- }
- as->state[i].u.insert.cur_ins=cur;
- as->state[i].u.insert.mark_ins=mark;
- }
- } else if ( !ismorx && type == asm_context ) {
- /* I don't see any good way to parse a per-glyph substitution table */
- /* the problem being that most of the per-glyph table is missing */
- /* but I don't know which bits. The offsets I'm given point to */
- /* where glyph 0 would be if it were present in the table, but */
- /* mostly only the bit used is present... */
- /* I could walk though the state machine and find all classes that */
- /* go to a specific substitution (which would tell me what glyphs */
- /* were active). That's not hard for substitutions of the current */
- /* glyph, but it is intractibable for marked glyphs. And I can't */
- /* do one without the other. So I do neither. */
- /* One thing I could test fairly easily would be to see whether */
- /* class 1 (out of bounds) is ever available for a substitution */
- /* (if it ever has a mark set on it or has a current substitution)*/
- /* if not, then I can ignore any putative substitutions for class */
- /* 1 glyphs (actually I should do this for all classes)*/
- /* Damn. That doesn't work for marks. Because a current substitution*/
- /* may be applied, and then the glyph gets marked. So we've no idea*/
- /* what class the newly marked glyph might live in */
- /* Apple's docs say the substitutions are offset from the "state */
- /* subtable", but it seems much more likely that they are offset */
- /* from the substitution table (given that Apple's docs are often */
- /* wrong */ /* Apple's docs are right. not clear why that offset */
- /* is there */
- uint8 *classes_subbed = gcalloc(st->nclasses,1);
- int lookup_max = -1, index, index_max;
- int32 *lookups = galloc(st->nclasses*st->nstates*sizeof(int32));
- uint8 *evermarked = gcalloc(st->nclasses*st->nstates,sizeof(uint8));
- uint8 *used;
- OTLookup **subs;
-
- index_max = 0;
- for ( i=0; i<st->nclasses*st->nstates; ++i ) {
- if ( as->state[i].u.context.mark_lookup!=NULL ) {
- index = sm_lookupfind(lookups,&lookup_max,(int16) (intpt) as->state[i].u.context.mark_lookup);
- if ( index>index_max ) index_max = index;
- }
- if ( as->state[i].u.context.cur_lookup!=NULL ) {
- index = sm_lookupfind(lookups,&lookup_max,(int16) (intpt) as->state[i].u.context.cur_lookup);
- if ( index>index_max ) index_max = index;
- }
- }
- subs = gcalloc(index_max+1,sizeof(OTLookup *));
-
- for ( i=0; i<st->nclasses*st->nstates; ++i ) {
- if ( as->state[i].u.context.mark_lookup!=NULL ) {
- index = sm_lookupfind(lookups,&lookup_max,(int16) (intpt) as->state[i].u.context.mark_lookup);
- evermarked[index] = true;
- as->state[i].u.context.mark_lookup = NewMacSubsLookup(info,otl,index,subs);
- }
- if ( as->state[i].u.context.cur_lookup!=NULL ) {
- index = sm_lookupfind(lookups,&lookup_max,(int16) (intpt) as->state[i].u.context.cur_lookup);
- as->state[i].u.context.cur_lookup = NewMacSubsLookup(info,otl,index,subs);
- }
- }
- used = gcalloc((subtab_len-st->extra_offsets[0]+1)/2,sizeof(uint8));
- /* first figure things that only appear in current subs */
- /* then go back and work on things that apply to things which are also in marked subs */
- for ( j=0; j<2; ++j ) for ( i=0; i<=lookup_max; ++i ) if ( evermarked[i]==j ) {
- info->mort_subs_lookup = NewMacSubsLookup(info,otl,i,subs);
- info->mort_is_nested = true;
- if ( !evermarked[i] ) { int k,l;
- memset(classes_subbed,0,st->nclasses);
- for ( k=0; k<st->nstates; ++k ) for ( l=0; l<st->nclasses; ++l ) {
- if ( as->state[k*st->nclasses+l].u.context.cur_lookup == info->mort_subs_lookup )
- classes_subbed[l] = true;
- }
- }
- fseek(ttf,here/*+st->extra_offsets[0]*/+lookups[i]*2,SEEK_SET);
- read_perglyph_subs(ttf,info,here+st->extra_offsets[0],here+subtab_len,
- st,classes_subbed,evermarked[i],used);
- }
- info->mort_is_nested = false;
- free(classes_subbed);
- free(lookups);
- free(used);
- free(evermarked);
- free(subs);
- } else if ( ismorx && type == asm_context ) {
- int lookup_max= -1;
- uint32 *lookups;
- OTLookup **subs;
-
- for ( i=0; i<st->nclasses*st->nstates; ++i ) {
- if ( (intpt) as->state[i].u.context.mark_lookup!=0xffff ) {
- if ( ((int) (intpt) as->state[i].u.context.mark_lookup)>lookup_max )
- lookup_max = (intpt) as->state[i].u.context.mark_lookup;
- }
- if ( (intpt) as->state[i].u.context.cur_lookup!=0xffff ) {
- if ( ((int) (intpt) as->state[i].u.context.cur_lookup)>lookup_max )
- lookup_max = (intpt) as->state[i].u.context.cur_lookup;
- }
- }
- ++lookup_max;
- subs = gcalloc(lookup_max,sizeof(OTLookup *));
- for ( i=0; i<st->nclasses*st->nstates; ++i ) {
- if ( (intpt) as->state[i].u.context.mark_lookup!=0xffff ) {
- as->state[i].u.context.mark_lookup = NewMacSubsLookup(info,otl,(intpt) as->state[i].u.context.mark_lookup,subs);
- } else
- as->state[i].u.context.mark_lookup = NULL;
- if ( (intpt) as->state[i].u.context.cur_lookup!=0xffff ) {
- as->state[i].u.context.cur_lookup = NewMacSubsLookup(info,otl,(intpt) as->state[i].u.context.cur_lookup,subs);
- } else
- as->state[i].u.context.cur_lookup = NULL;
- }
- lookups = galloc(lookup_max*sizeof(uint32));
- fseek(ttf,here+st->extra_offsets[0],SEEK_SET);
- for ( i=0; i<lookup_max; ++i )
- lookups[i] = getlong(ttf) + here+st->extra_offsets[0];
- for ( i=0; i<lookup_max; ++i ) {
- fseek(ttf,lookups[i],SEEK_SET);
- info->mort_subs_lookup = NewMacSubsLookup(info,otl,i,subs);
- info->mort_is_nested = true;
- readttf_applelookup(ttf,info,
- mort_apply_values,mort_apply_value,NULL,NULL,true);
- }
- info->mort_is_nested = false;
- free(subs);
- free(lookups);
- } else if ( type == asm_kern ) {
- for ( i=0; i<st->nclasses*st->nstates; ++i ) {
- if ( (as->state[i].flags&0x3fff)!=0 ) {
- KernReadKernList(ttf,here+(as->state[i].flags&0x3fff),
- &as->state[i]);
- as->state[i].flags &= ~0x3fff;
- } else {
- as->state[i].u.kern.kcnt = 0;
- as->state[i].u.kern.kerns = NULL;
- }
- }
- }
- as->next = info->sm;
- info->sm = as;
- statetablefree(st);
-return( as );
-}
-
-static int InfoHasGSUBTag(struct ttfinfo *info, uint32 tag, int apple_lookup_type) {
- OTLookup *otl;
- FeatureScriptLangList *feat;
-
- if ( apple_lookup_type==0 || /* Indic rearrangement */
- apple_lookup_type==1 || /* Contextual substitution */
- apple_lookup_type==5 ) /* Contextual insertion */
-return( false ); /* These types can either not be represented in OT */
- /* or not converted to AAT -- so we'd better read them */
- /* We can't really do contextual ligatures either, but we parse that table*/
- /* for the non-contextual ligs (which is most of them) */
-
- for ( otl = info->gsub_lookups; otl!=NULL; otl=otl->next ) {
- for ( feat = otl->features; feat!=NULL; feat=feat->next ) {
- if ( feat->featuretag == tag &&
- Macable(NULL,otl))
-return( true );
- }
- }
-return( false );
-}
-
-static void FeatMarkAsEnabled(struct ttfinfo *info,int featureType,
- int featureSetting);
-
-static uint32 readmortchain(FILE *ttf,struct ttfinfo *info, uint32 base, int ismorx) {
- uint32 chain_len, nfeatures, nsubtables, default_flags;
- uint32 enable_flags, disable_flags, flags;
- int featureType, featureSetting;
- int i,j,k;
- uint32 length, coverage;
- uint32 here;
- uint32 tag;
- struct tagmaskfeature { uint32 tag, enable_flags; uint16 ismac, feat, set; } tmf[32];
- int r2l;
- (void)base; /* for -Wall */
- default_flags = getlong(ttf);
- chain_len = getlong(ttf);
- if ( ismorx ) {
- nfeatures = getlong(ttf);
- nsubtables = getlong(ttf);
- } else {
- nfeatures = getushort(ttf);
- nsubtables = getushort(ttf);
- }
-
- k = 0;
- for ( i=0; i<(int)nfeatures; ++i ) {
- featureType = getushort(ttf);
- featureSetting = getushort(ttf);
- enable_flags = getlong(ttf);
- disable_flags = getlong(ttf);
- if ( feof(ttf))
-return( chain_len );
- if ( enable_flags & default_flags )
- FeatMarkAsEnabled(info,featureType,featureSetting);
- tag = MacFeatureToOTTag(featureType,featureSetting);
- if ( enable_flags!=0 && k<32 ) {
- if ( tag==0 ) {
- tmf[k].tag = (featureType<<16) | featureSetting;
- tmf[k].ismac = true;
- } else {
- tmf[k].tag = tag;
- tmf[k].ismac = false;
- }
- tmf[k].feat = featureType;
- tmf[k].set = featureSetting;
- tmf[k++].enable_flags = enable_flags;
- }
- }
- if ( k==0 )
-return( chain_len );
-
- for ( i=0; i<(int)nsubtables; ++i ) {
- here = ftell(ttf);
- if ( ismorx ) {
- length = getlong(ttf);
- coverage = getlong(ttf);
- } else {
- length = getushort(ttf);
- coverage = getushort(ttf);
- coverage = ((coverage&0xe000)<<16) | (coverage&7); /* convert to morx format */
- }
- r2l = (coverage & 0x40000000)? 1 : 0;
- flags = getlong(ttf);
- for ( j=k-1; j>=0 && (!(flags&tmf[j].enable_flags) || (tmf[j].enable_flags&~flags)!=0); --j );
- if ( j==-1 )
- for ( j=k-1; j>=0 && (!(flags&tmf[j].enable_flags) || tmf[j].feat==0); --j );
- if ( j>=0 ) {
- if ( !tmf[j].ismac &&
- ((coverage&0xff)==0 ||
- (coverage&0xff)==1 ||
- (coverage&0xff)==5 )) {
- /* Only do the opentype tag conversion if we've got a format */
- /* we can convert to opentype. Otherwise it is useless and */
- /* confusing */
- tmf[j].ismac = true;
- tmf[j].tag = (tmf[j].feat<<16) | tmf[j].set;
- }
- info->mort_r2l = r2l;
- info->mort_tag_mac = tmf[j].ismac;
- info->mort_feat = tmf[j].feat; info->mort_setting = tmf[j].set;
- /* If we've already read gsub. And this feature setting matches */
- /* and opentype feature tag. And we've got an OpenType lookup */
- /* attached to that feature tag. And it's a lookup type we can */
- /* convert... Then don't parse this sub-table, we shall assume */
- /* it is simply a duplicate of the OT version */
- if ( info->gsub_start!=0 &&
- (tag = MacFeatureToOTTag(tmf[j].feat,tmf[j].set))!=0 &&
- InfoHasGSUBTag(info,tag,coverage&0xff))
- /* Skip it */;
- else switch( coverage&0xff ) {
- case 0: /* Indic rearangement */
- readttf_mortx_asm(ttf,info,ismorx,length,asm_indic,0,
- coverage,NULL);
- break;
- case 1: /* contextual glyph substitution */
- readttf_mortx_asm(ttf,info,ismorx,length,asm_context,2,
- coverage,NULL);
- break;
- case 2: /* ligature substitution */
- /* Apple's ligature state machines are too weird to be */
- /* represented easily, but I can parse them into a set */
- /* of ligatures -- assuming they are unconditional */
- info->mort_subs_lookup = NewMacLookup(info,false);
- info->mort_subs_lookup->lookup_type = gsub_ligature;
- if ( !tmf[j].ismac ) {
- info->mort_subs_lookup->features->next = chunkalloc(sizeof(FeatureScriptLangList));
- info->mort_subs_lookup->features->next->featuretag = tmf[j].tag;
- info->mort_subs_lookup->features->next->ismac = false;
- }
- info->mort_subs_lookup->subtables->per_glyph_pst_or_kern = true;
- readttf_mortx_lig(ttf,info,ismorx,here,length);
- InfoNameOTLookup(info->mort_subs_lookup,info);
- /* We can give the lookup a better name after we've made a */
- /* guess at what scripts it involves => substitutions first */
- break;
- case 4: /* non-contextual glyph substitutions */
- info->mort_subs_lookup = NewMacLookup(info,false);
- info->mort_subs_lookup->lookup_type = gsub_single;
- if ( !tmf[j].ismac ) {
- info->mort_subs_lookup->features->next = chunkalloc(sizeof(FeatureScriptLangList));
- info->mort_subs_lookup->features->next->featuretag = tmf[j].tag;
- info->mort_subs_lookup->features->next->ismac = false;
- }
- info->mort_subs_lookup->subtables->per_glyph_pst_or_kern = true;
- readttf_applelookup(ttf,info,
- mort_apply_values,mort_apply_value,NULL,NULL,true);
- InfoNameOTLookup(info->mort_subs_lookup,info);
- break;
- case 5: /* contextual glyph insertion */
- readttf_mortx_asm(ttf,info,ismorx,length,asm_insert,2,
- coverage,NULL);
- break;
- }
- }
- fseek(ttf, here+length, SEEK_SET );
- }
-
-return( chain_len );
-}
-
-void readttfmort(FILE *ttf,struct ttfinfo *info) {
- uint32 base = info->morx_start!=0 ? info->morx_start : info->mort_start;
- uint32 here, len;
- int ismorx;
- int32 version;
- int i, nchains;
-
- fseek(ttf,base,SEEK_SET);
- version = getlong(ttf);
- ismorx = version == 0x00020000;
- if ( version!=0x00010000 && version != 0x00020000 )
-return;
- nchains = getlong(ttf);
- if ( feof(ttf)) {
- LogError( _("Unexpected end of file found in morx chain.\n" ));
- info->bad_gx = true;
-return;
- }
- info->mort_max = nchains*33; /* Maximum of one feature per bit ? */
- for ( i=0; i<nchains; ++i ) {
- here = ftell(ttf);
- len = readmortchain(ttf,info,base,ismorx);
- if ( feof(ttf)) {
- LogError( _("Unexpected end of file found in morx chain.\n"));
- info->bad_gx = true;
- break;
- }
- fseek(ttf,here+len,SEEK_SET);
- }
- /* Some Apple fonts use out of range gids as flags in conditional substitutions */
- /* generally to pass information from one sub-table to another which then */
- /* removes the flag */
- if ( info->badgid_cnt!=0 ) {
- /* Merge the fake glyphs in with the real ones */
- info->chars = grealloc(info->chars,(info->glyph_cnt+info->badgid_cnt)*sizeof(SplineChar *));
- for ( i=0; i<info->badgid_cnt; ++i ) {
- info->chars[info->glyph_cnt+i] = info->badgids[i];
- info->badgids[i]->orig_pos = info->glyph_cnt+i;
- }
- info->glyph_cnt += info->badgid_cnt;
- free(info->badgids);
- }
-}
-
/* 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 */
@@ -4620,63 +2982,46 @@ void readttfkerns(FILE *ttf,struct ttfinfo *info) {
KernClass *kc;
uint32 begin_table;
uint16 *class1, *class2;
- int tupleIndex;
int isv;
- SplineChar **chars;
OTLookup *otl;
fseek(ttf,info->kern_start,SEEK_SET);
version = getushort(ttf);
tabcnt = getushort(ttf);
if ( version!=0 ) {
- fseek(ttf,info->kern_start,SEEK_SET);
- version = getlong(ttf);
- tabcnt = getlong(ttf);
+ 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);
- if ( version==0 ) {
- /* version = */ getushort(ttf);
- len = getushort(ttf);
- coverage = getushort(ttf);
- format = coverage>>8;
- flags_good = ((coverage&7)<=1);
- isv = !(coverage&1);
- tupleIndex = -1;
- header_size = 6;
- } else {
- len = getlong(ttf);
- coverage = getushort(ttf);
- /* Apple has reordered the bits */
- format = (coverage&0xff);
- flags_good = ((coverage&0xdf00)==0 || (coverage&0xdf00)==0x8000);
- isv = coverage&0x8000? 1 : 0;
- tupleIndex = getushort(ttf);
- if ( coverage&0x2000 ) {
- if ( info->variations==NULL )
- flags_good = false; /* Ignore if we failed to load the tuple data */
- else if ( tupleIndex>=info->variations->tuple_count )
- flags_good = false; /* Bad tuple */
- } else
- tupleIndex = -1;
- header_size = 8;
- }
+ /* 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 = NewMacLookup(info,true);
+ otl = chunkalloc(sizeof(OTLookup));
otl->lookup_type = gpos_pair;
- if ( isv ) {
- otl->features->featuretag = CHR('v','k','r','n');
- otl->features->ismac = false;
- }
+ 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 */
- chars = tupleIndex==-1 ? info->chars : info->variations->tuples[tupleIndex].chars;
+ SplineChar **chars = info->chars;
npairs = getushort(ttf);
- if ( version==0 && (len-14 != 6*npairs || npairs>10920 )) {
+ 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;
}
@@ -4720,32 +3065,15 @@ void readttfkerns(FILE *ttf,struct ttfinfo *info) {
}
}
InfoNameOTLookup(otl,info);
- } else if ( flags_good && format==1 ) {
- /* format 1 is an apple state machine which can handle weird cases */
- /* OpenType's spec doesn't document this */
- /* Apple's docs are wrong about this table, they claim */
- /* there is a special value which marks the end of the kerning */
- /* lists. In fact there is no such value, the list is as long */
- /* as there are things on the kern stack */
- otl->lookup_type = kern_statemachine;
- readttf_mortx_asm(ttf,info,false,len-header_size,asm_kern,0,
- isv ? 0x80000000 : 0 /* coverage doesn't really apply */,otl);
- fseek(ttf,begin_table+len,SEEK_SET);
} else if ( flags_good && (format==2 || format==3 )) {
/* two class based formats */
KernClass **khead, **klast;
- if ( isv && tupleIndex==-1 ) {
+ if ( isv ) {
khead = &info->vkhead;
klast = &info->vklast;
- } else if ( tupleIndex==-1 ) {
+ } else {
khead = &info->khead;
klast = &info->klast;
- } else if ( isv ) {
- khead = &info->variations->tuples[tupleIndex].vkhead;
- klast = &info->variations->tuples[tupleIndex].vklast;
- } else {
- khead = &info->variations->tuples[tupleIndex].khead;
- klast = &info->variations->tuples[tupleIndex].klast;
}
if ( *khead==NULL )
*khead = kc = chunkalloc(sizeof(KernClass));
@@ -4826,92 +3154,6 @@ void readttfkerns(FILE *ttf,struct ttfinfo *info) {
}
}
-void readmacfeaturemap(FILE *ttf,struct ttfinfo *info) {
- MacFeat *last=NULL, *cur;
- struct macsetting *slast, *scur;
- struct fs { int n; int off; } *fs;
- int featcnt, i, j, flags;
-
- fseek(ttf,info->feat_start,SEEK_SET);
- /* version =*/ getfixed(ttf);
- featcnt = getushort(ttf);
- /* reserved */ getushort(ttf);
- /* reserved */ getlong(ttf);
- if ( feof(ttf)) {
- LogError( _("End of file in feat table.\n" ));
- info->bad_gx = true;
-return;
- }
-
- fs = galloc(featcnt*sizeof(struct fs));
- for ( i=0; i<featcnt; ++i ) {
- cur = chunkalloc(sizeof(MacFeat));
- if ( last==NULL )
- info->features = cur;
- else
- last->next = cur;
- last = cur;
-
- cur->feature = getushort(ttf);
- fs[i].n = getushort(ttf);
- fs[i].off = getlong(ttf);
- flags = getushort(ttf);
- cur->strid = getushort(ttf);
- if ( flags&0x8000 ) cur->ismutex = true;
- if ( flags&0x4000 )
- cur->default_setting = flags&0xff;
- if ( feof(ttf)) {
- free(fs);
- LogError( _("End of file in feat table.\n" ));
- info->bad_gx = true;
-return;
- }
- }
-
- for ( i=0, cur=info->features; i<featcnt; ++i, cur = cur->next ) {
- fseek(ttf,info->feat_start+fs[i].off,SEEK_SET);
- slast = NULL;
- for ( j=0; j<fs[i].n; ++j ) {
- scur = chunkalloc(sizeof(struct macsetting));
- if ( slast==NULL )
- cur->settings = scur;
- else
- slast->next = scur;
- slast = scur;
-
- scur->setting = getushort(ttf);
- scur->strid = getushort(ttf);
- if ( feof(ttf)) {
- free(fs);
- LogError( _("End of file in feat table.\n") );
- info->bad_gx = true;
-return;
- }
- }
- }
- free(fs);
-}
-
-static void FeatMarkAsEnabled(struct ttfinfo *info,int featureType,
- int featureSetting) {
- MacFeat *f;
- struct macsetting *s;
-
- for ( f = info->features; f!=NULL && f->feature!=featureType; f=f->next );
- if ( f==NULL )
-return;
- if ( f->ismutex ) {
- for ( s=f->settings ; s!=NULL; s=s->next )
- s->initially_enabled = ( s->setting==featureSetting );
- f->default_setting = featureSetting;
- } else {
- for ( s=f->settings ; s!=NULL && s->setting!=featureSetting; s=s->next );
- if ( s!=NULL )
- s->initially_enabled = true;
- }
-return;
-}
-
/******************************************************************************/
/* ******************************* MATH Table ******************************* */
/* ********************** (Not strictly OpenType yet) *********************** */
@@ -5486,123 +3728,3 @@ return;
}
}
}
-
-static void bsln_apply_values(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
- int i;
-
- for ( i=gfirst; i<=glast; ++i )
- info->bsln_values[i]= getushort(ttf);
-}
-
-static void bsln_apply_value(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
- int i;
- int bsln;
-
- bsln = getushort(ttf);
- for ( i=gfirst; i<=glast; ++i )
- info->bsln_values[i]= bsln;
-}
-
-static void bsln_apply_default(struct ttfinfo *info, int gfirst, int glast,void *def) {
- int def_bsln, i;
-
- def_bsln = (intpt) def;
- for ( i=gfirst; i<=glast; ++i )
- info->bsln_values[i]= def_bsln;
-}
-
-void readttfbsln(FILE *ttf,struct ttfinfo *info) {
- int def, ap_def, version, format;
- uint16 *values;
- int offsets[32];
- SplineChar *sc;
- BasePoint pos;
- int mapping[32];
- int i;
- struct Base *base;
- struct basescript *bs;
-
- fseek(ttf,info->bsln_start,SEEK_SET);
- version = getlong(ttf);
- if ( version!=0x00010000 )
-return;
- format = getushort(ttf);
- def = getushort(ttf);
- if ( format==0 || format==1 ) {
- for ( i=0; i<32; ++i )
- offsets[i] = (int16) getushort(ttf);
- } else if ( format==2 || format==3 ) {
- int stdGID = getushort(ttf);
- int ptnum;
- if ( stdGID>=info->glyph_cnt || (sc = info->chars[stdGID])==NULL )
-return;
- for ( i=0; i<32; ++i ) {
- ptnum = getushort(ttf);
- if ( ttfFindPointInSC(sc,ly_fore,ptnum,&pos,NULL)!=-1 )
-return;
- offsets[i] = pos.y;
- }
- }
-
- if ( format&1 ) {
- info->bsln_values = values = gcalloc(info->glyph_cnt,sizeof(uint16));
- readttf_applelookup(ttf,info,
- bsln_apply_values,bsln_apply_value,
- bsln_apply_default,(void *) (intpt) def, false);
- } else
- values = NULL;
-
- for ( i=1; i<32; ++i ) mapping[i] = 3; /* Roman */
-
- info->horiz_base = base = chunkalloc(sizeof(struct Base));
- base->baseline_cnt = 4;
- base->baseline_tags = galloc(4*sizeof(uint32));
- base->baseline_tags[0] = CHR('h','a','n','g'); /* Apple 3 */
- if ( offsets[1]!= offsets[2] ) {
- base->baseline_tags[1] = CHR('i','d','e','o'); /* Apple 2 */
- base->baseline_tags[2] = CHR('m','a','t','h'); /* Apple 4 */
- base->baseline_tags[3] = CHR('r','o','m','n'); /* Apple 0 */
-
- /* Map from Apple's baseline indeces, to OT tag positions */
- mapping[3] = 0;
- mapping[2] = 1;
- mapping[4] = 2;
- mapping[0] = 3;
- /* Apple baseline 1 does not map to an OT tag */
- /* I assume baseline 1 is the normal baseline for CJK on Macs */
- /* (because baseline 2 often (and wrongly) contains the same value */
- } else {
- /* baseline 1 (centered ideographic) and baseline 2 (low ideographic) */
- /* are documented to be different. Yet most of the fonts I have looked*/
- /* at (and I've only got about 4 test cases) have the low ideographic*/
- /* baseline set to the centered baseline. If I were to copy that to */
- /* OT it would be really bad. So even though baseline data is provided*/
- /* I shall ignore it if it looks WRONG! */
- base->baseline_cnt = 3;
- base->baseline_tags[1] = CHR('m','a','t','h'); /* Apple 4 */
- base->baseline_tags[2] = CHR('r','o','m','n'); /* Apple 0 */
- mapping[3] = 0;
- mapping[4] = 1;
- mapping[0] = 2;
- }
-
- for ( i=0; i<info->glyph_cnt; ++i ) if ( (sc=info->chars[i])!=NULL ) {
- uint32 script = SCScriptFromUnicode(sc);
- if ( script==DEFAULT_SCRIPT )
- continue;
- for ( bs=base->scripts; bs!=NULL && bs->script!=script; bs=bs->next );
- if ( bs!=NULL )
- continue;
- bs = chunkalloc(sizeof(struct basescript));
- bs->script = script;
- ap_def = def;
- if ( values!=NULL )
- ap_def = values[i];
- bs->def_baseline = mapping[ap_def];
- bs->baseline_pos = galloc(4*sizeof(int16));
- for ( i=0; i<5; ++i ) if ( i!=1 )
- bs->baseline_pos[mapping[i]] = offsets[i] - offsets[ap_def];
- bs->next = base->scripts;
- base->scripts = bs;
- }
-}