diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfvar.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfvar.c | 771 |
1 files changed, 0 insertions, 771 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfvar.c b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfvar.c deleted file mode 100644 index 1467fcbc06b..00000000000 --- a/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsettfvar.c +++ /dev/null @@ -1,771 +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 <gwidget.h> -#include "ttf.h" - -/***************************************************************************/ -/* */ -/* Apple documents these tables at */ -/* http:// developer.apple.com/fonts/TTRefMan/RM06/Chap6[fgca]var.html */ -/* The documentation for fvar is inconsistant. At one point it says that */ -/* countSizePairs should be 3, at another point 2. It should be 2. */ -/* The documentation for gvar is not intelligable, cvar refers you to gvar */ -/* and is thus also incomprehensible */ -/* The documentation for avar appears correct, but as Apple has no fonts */ -/* with an 'avar' table, so it's hard to test. */ -/* */ -/***************************************************************************/ - -/* Parse Apple's variation tables (font, glyph, cvt and axis) */ -/* To be interesting a font must have an fvar and a gvar */ -/* If it's hinted it better have a cvar */ -/* It may have an avar if it wants to be complicated */ - -void VariationFree(struct ttfinfo *info) { - int i,j; - struct variations *variation = info->variations; - - if ( variation==NULL ) -return; - if ( variation->axes!=NULL ) { - for ( i=0; i<variation->axis_count; ++i ) { - free(variation->axes[i].mapfrom); - free(variation->axes[i].mapto); - } - free(variation->axes); - } - if ( variation->instances!=NULL ) { - for ( i=0; i<variation->instance_count; ++i ) { - free(variation->instances[i].coords); - } - free(variation->instances); - } - if ( variation->tuples!=NULL ) { - for ( i=0; i<variation->tuple_count; ++i ) { - free(variation->tuples[i].coords); - if ( variation->tuples[i].chars!=NULL ) - for ( j=0; j<info->glyph_cnt; ++j ) - SplineCharFree(variation->tuples[i].chars[j]); - free(variation->tuples[i].chars); - KernClassListFree(variation->tuples[i].khead); - KernClassListFree(variation->tuples[i].vkhead); - } - free(variation->tuples); - } - free(variation); - info->variations = NULL; -} - -static void parsefvar(struct ttfinfo *info, FILE *ttf) { - int data_off, axis_count, instance_count, cnt; - int i,j; - - fseek(ttf,info->fvar_start,SEEK_SET); - if ( getlong(ttf)!=0x00010000 ) /* I only understand version 1 */ -return; - data_off = getushort(ttf); - cnt = getushort(ttf); - if ( cnt>2 ) - LogError( _("Hmm, this 'fvar' table has more count/size pairs than I expect\n") ); - else if ( cnt<2 ) { - LogError( _("Hmm, this 'fvar' table has too few count/size pairs, I shan't parse it\n") ); -return; - } - axis_count = getushort(ttf); - if ( axis_count==0 || axis_count>4 ) { - if ( axis_count==0 ) - LogError( _("Hmm, this 'fvar' table has no axes, that doesn't make sense.\n") ); - else - LogError( _("Hmm, this 'fvar' table has more axes than FontForge can handle.\n") ); -return; - } - if ( getushort(ttf)!=20 ) { - LogError( _("Hmm, this 'fvar' table has an unexpected size for an axis, I shan't parse it\n") ); -return; - } - instance_count = getushort(ttf); - if ( getushort(ttf)!=4+4*axis_count ) { - LogError( _("Hmm, this 'fvar' table has an unexpected size for an instance, I shan't parse it\n") ); -return; - } - if ( data_off+axis_count*20+instance_count*(4+4*axis_count)> (int)info->fvar_len ) { - LogError( _("Hmm, this 'fvar' table is too short\n") ); -return; - } - - info->variations = gcalloc(1,sizeof(struct variations)); - info->variations->axis_count = axis_count; - info->variations->instance_count = instance_count; - info->variations->axes = gcalloc(axis_count,sizeof(struct taxis)); - info->variations->instances = gcalloc(instance_count,sizeof(struct tinstance)); - for ( i=0; i<instance_count; ++i ) - info->variations->instances[i].coords = galloc(axis_count*sizeof(real)); - - fseek(ttf,info->fvar_start+data_off,SEEK_SET); - for ( i=0; i<axis_count; ++i ) { - struct taxis *a = &info->variations->axes[i]; - a->tag = getlong(ttf); - a->min = getlong(ttf)/65536.0; - a->def = getlong(ttf)/65536.0; - a->max = getlong(ttf)/65536.0; - /* flags = */ getushort(ttf); - a->nameid = getushort(ttf); - } - for ( i=0; i<instance_count; ++i ) { - struct tinstance *ti = &info->variations->instances[i]; - ti->nameid = getushort(ttf); - /* flags = */ getushort(ttf); - for ( j=0 ; j<axis_count; ++j ) - ti->coords[j] = getlong(ttf)/65536.0; - } -} - -static void parseavar(struct ttfinfo *info, FILE *ttf) { - int axis_count, pair_count; - int i,j; - - if ( info->variations==NULL || info->avar_start==0 || info->avar_len==0 ) -return; - - fseek(ttf,info->avar_start,SEEK_SET); - if ( getlong(ttf)!=0x00010000 ) { /* I only understand version 1 */ - VariationFree(info); -return; - } - axis_count = getlong(ttf); - if ( axis_count!=info->variations->axis_count ) { - LogError( _("Hmm, the axis count in the 'avar' table is different from that in the 'fvar' table.\n") ); - VariationFree(info); -return; - } - for ( i=0; i<axis_count; ++i ) { - pair_count = getushort(ttf); - if ( pair_count!=0 ) { - info->variations->axes[i].mapfrom = galloc(pair_count*sizeof(real)); - info->variations->axes[i].mapto= galloc(pair_count*sizeof(real)); - for ( j=0; j<pair_count; ++j ) { - info->variations->axes[i].mapfrom[j] = getushort(ttf)/16384.0; - info->variations->axes[i].mapto[j] = getushort(ttf)/16384.0; - } - } - } - if ( ftell(ttf)-info->avar_start>info->avar_len) { - LogError( _("Hmm, the the 'avar' table is too long.\n") ); - VariationFree(info); -return; - } -} - -static SplineChar **InfoCopyGlyphs(struct ttfinfo *info) { - SplineChar **chars = galloc(info->glyph_cnt*sizeof(SplineChar *)); - int i; - RefChar *r; - - for ( i=0; i<info->glyph_cnt; ++i ) { - if ( info->chars[i]==NULL ) - chars[i] = NULL; - else { - chars[i] = SplineCharCopy(info->chars[i],NULL,NULL); - free(chars[i]->ttf_instrs); chars[i]->ttf_instrs = NULL; - chars[i]->ttf_instrs_len = 0; - PSTFree(chars[i]->possub); chars[i]->possub = NULL; - for ( r=chars[i]->layers[ly_fore].refs; r!=NULL; r=r->next ) - r->sc = NULL; - chars[i]->changed = false; - chars[i]->ticked = false; - } - } - - for ( i=0; i<info->glyph_cnt; ++i ) - ttfFixupRef(chars,i); -return( chars ); -} - -#define BAD_DELTA 0x10001 -static int *readpackeddeltas(FILE *ttf,int n) { - int *deltas; - int runcnt, i, j; - - deltas = galloc(n*sizeof(int)); - - i = 0; - while ( i<n ) { - runcnt = getc(ttf); - if ( runcnt&0x80 ) { - /* runcnt zeros get added */ - for ( j=0; j<=(runcnt&0x3f) && i<n ; ++j ) - deltas[i++] = 0; - } else if ( runcnt&0x40 ) { - /* runcnt shorts from the stack */ - for ( j=0 ; j<=(runcnt&0x3f) && i<n ; ++j ) - deltas[i++] = (int16) getushort(ttf); - } else { - /* runcnt signed bytes from the stack */ - for ( j=0; j<=(runcnt&0x3f) && i<n; ++j ) - deltas[i++] = (int8) getc(ttf); - } - if ( j<=(runcnt&0x3f) ) { - if ( n>0 ) - deltas[0] = BAD_DELTA; - } - } -return( deltas ); -} - -#define ALL_POINTS 0x10001 -#define END_OF_POINTS 0x10000 - -static int *readpackedpoints(FILE *ttf) { - int *points; - int n, runcnt, i, j, first; - - n = getc(ttf); - if ( n==EOF ) - n = 0; - if ( n&0x80 ) - n = getc(ttf)|((n&0x7f)<<8); - points = galloc((n+1)*sizeof(int)); - if ( n==0 ) - points[0] = ALL_POINTS; - else { - i = 0; - while ( i<n ) { - runcnt = getc(ttf); - if ( runcnt&0x80 ) { - runcnt = (runcnt&0x7f); - points[i++] = first = getushort(ttf); - /* first point not included in runcount */ - for ( j=0; j<runcnt && i<n; ++j ) - points[i++] = (first += getushort(ttf)); - } else { - points[i++] = first = getc(ttf); - for ( j=0; j<runcnt && i<n; ++j ) - points[i++] = (first += getc(ttf)); - } - } - points[n] = END_OF_POINTS; - } -return( points ); -} - -static int TuplesMatch(struct variations *v, int vtest, int dbase) { - /* variations for [0,1] make up part of design [1,1], but not the other */ - /* way round */ - int i; - - if ( dbase>=v->tuple_count ) -return( false ); - - if ( vtest==dbase ) -return( true ); - for ( i=0; i<v->axis_count; ++i ) { - if ( v->tuples[vtest].coords[i]==0 && v->tuples[dbase].coords[i]!=0 ) -return( false ); - if ( v->tuples[dbase].coords[i]!=0 && - v->tuples[dbase].coords[i]!=v->tuples[vtest].coords[i] ) -return( false ); - } -return( true ); -} - -static int PointCount(SplineChar *sc) { - int i; - RefChar *ref; - SplineSet *ss; - SplinePoint *sp; - - if ( sc->layers[ly_fore].refs!=NULL ) - for ( i=0, ref=sc->layers[ly_fore].refs; ref!=NULL; ++i, ref=ref->next ); - else { - for ( i=0, ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) { - for ( sp=ss->first; sp!=NULL ; ) { - if ( sp->ttfindex!=0xffff && sp->ttfindex!=0xfffe ) - ++i; - if ( sp->nextcpindex!=0xffff && sp->nextcpindex!=0xfffe ) - ++i; - if ( sp->next==NULL ) - break; - sp = sp->next->to; - if ( sp==ss->first ) - break; - } - } - } -return( i ); -} - -static void SCShiftAllBy(SplineChar *sc,int xd, int yd) { - /* If they change the left/right side-bearing, I think that means everything */ - /* should be shifted over */ - SplineSet *ss; - SplinePoint *sp; - RefChar *ref; - - if ( xd==0 && yd==0 ) -return; - - for ( ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) { - for ( sp=ss->first; sp!=NULL ; ) { - if ( sp->ttfindex!=0xffff && sp->ttfindex!=0xfffe ) { - sp->me.x += xd; - sp->me.y += yd; - } - if ( sp->nextcpindex!=0xffff && sp->nextcpindex!=0xfffe ) { - sp->nextcp.x += xd; - sp->nextcp.y += yd; - if ( sp->next!=NULL ) - sp->next->to->prevcp = sp->nextcp; - } - if ( sp->next==NULL ) - break; - sp = sp->next->to; - if ( sp == ss->first ) - break; - } - } - for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) { - ref->transform[4] += xd; - ref->transform[5] += yd; - SCReinstanciateRefChar(sc,ref,ly_fore); - } -} - -static void VaryGlyph(SplineChar *sc,int *points, int *xdeltas, int *ydeltas, - int pcnt) { - /* A character contains either composites or contours */ - int i,j; - RefChar *ref; - SplineSet *ss; - SplinePoint *sp; - Spline *s, *first; - - if ( points[0]==ALL_POINTS ) { - if ( sc->layers[ly_fore].refs!=NULL ) { - for ( i=0, ref=sc->layers[ly_fore].refs; ref!=NULL; ++i, ref=ref->next ) { - if ( xdeltas[i]!=0 || ydeltas[i]!=0 ) { - ref->transform[4] += xdeltas[i]; - ref->transform[5] += ydeltas[i]; - SCReinstanciateRefChar(sc,ref,ly_fore); - } - } - } else { - for ( ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) { - for ( sp=ss->first; sp!=NULL ; ) { - if ( sp->ttfindex!=0xffff && sp->ttfindex!=0xfffe ) { - sp->me.x += xdeltas[sp->ttfindex]; - sp->me.y += ydeltas[sp->ttfindex]; - } - if ( sp->nextcpindex!=0xffff && sp->nextcpindex!=0xfffe ) { - sp->nextcp.x += xdeltas[sp->nextcpindex]; - sp->nextcp.y += ydeltas[sp->nextcpindex]; - if ( sp->next!=NULL ) - sp->next->to->prevcp = sp->nextcp; - } - if ( sp->next==NULL ) - break; - sp = sp->next->to; - if ( sp == ss->first ) - break; - } - } - } - SCShiftAllBy(sc,-xdeltas[pcnt-4],0); - SCShiftAllBy(sc,0,-ydeltas[pcnt-2]); - sc->width += xdeltas[pcnt-3]; - sc->vwidth += ydeltas[pcnt-1]; - } else { - j = 0; - if ( sc->layers[ly_fore].refs!=NULL ) { - for ( i=0, ref=sc->layers[ly_fore].refs; ref!=NULL; ++i, ref=ref->next ) { - if ( points[j]==i ) { - if ( xdeltas[j]!=0 || ydeltas[j]!=0 ) { - ref->transform[4] += xdeltas[j]; - ref->transform[5] += ydeltas[j]; - SCReinstanciateRefChar(sc,ref,ly_fore); - } - ++j; - } - } - } else { - for ( i=0, ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) { - if ( ss->first->prev!=NULL && ss->first->prev->from->nextcpindex==points[j] ) { - ss->first->prevcp.x += xdeltas[j]; - ss->first->prevcp.y += ydeltas[j]; - ss->first->prev->from->nextcp = ss->first->prevcp; - ++j; - } - for ( sp=ss->first; sp!=NULL ; ++i ) { - if ( sp->ttfindex!=0xffff && sp->ttfindex!=0xfffe ) - ++i; - if ( sp->ttfindex==points[j] ) { - sp->me.x += xdeltas[j]; - sp->me.y += ydeltas[j++]; - } - if ( sp->nextcpindex!=0xffff && sp->nextcpindex!=0xfffe ) - ++i; - if ( sp->nextcpindex==points[j] ) { - sp->nextcp.x += xdeltas[j]; - sp->nextcp.y += ydeltas[j++]; - if ( sp->next!=NULL ) - sp->next->to->prevcp = sp->nextcp; - } else if ( sp->nonextcp ) { - sp->nextcp = sp->me; - } - if ( sp->next==NULL ) - break; - sp = sp->next->to; - if ( sp == ss->first ) - break; - } - first = NULL; - } - } - if ( points[j]==i ) - SCShiftAllBy(sc,-xdeltas[j++],0); - if ( points[j]==i+1 ) - sc->width += xdeltas[j++]; - if ( points[j]==i+2 ) - SCShiftAllBy(sc,0,-ydeltas[j++]); - if ( points[j]==i+3 ) - sc->vwidth += ydeltas[j++]; - } - if ( sc->layers[ly_fore].refs==NULL ) { - for ( ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) { - for ( sp=ss->first; sp!=NULL ; ++i ) { - if ( sp->ttfindex==0xffff ) { - sp->me.x = ( sp->nextcp.x + sp->prevcp.x )/2; - sp->me.y = ( sp->nextcp.y + sp->prevcp.y )/2; - } - if ( sp->next==NULL ) - break; - sp = sp->next->to; - if ( sp == ss->first ) - break; - } - - first = NULL; - for ( s=ss->first->next; s!=NULL && s!=first; s=s->to->next ) { - SplineRefigure(s); - if ( first==NULL ) first = s; - } - } - } -} - -static void VaryGlyphs(struct ttfinfo *info,int tupleIndex,int gnum, - int *points, FILE *ttf ) { - /* one annoying thing about gvar, is that the variations do not describe */ - /* designs. well variations for [0,1] describes that design, but the */ - /* design for [1,1] includes the variations [0,1], [1,0], and [1,1] */ - int pcnt, tc; - int *xdeltas, *ydeltas; - struct variations *v = info->variations; - - if ( info->chars[gnum]==NULL ) /* Apple doesn't support ttc so this */ -return; /* can't happen */ - if ( points==NULL ) { - LogError( _("Mismatched local and shared tuple flags.\n") ); -return; - } - - if ( points[0]==ALL_POINTS ) - pcnt = PointCount(info->chars[gnum])+4; - else { - for ( pcnt=0; points[pcnt]!=END_OF_POINTS; ++pcnt ); - } - xdeltas = readpackeddeltas(ttf,pcnt); - ydeltas = readpackeddeltas(ttf,pcnt); - if ( xdeltas[0]!=BAD_DELTA && ydeltas[0]!=BAD_DELTA ) - for ( tc = 0; tc<v->tuple_count; ++tc ) { - if ( TuplesMatch(v,tc,tupleIndex)) - VaryGlyph(v->tuples[tc].chars[gnum],points,xdeltas,ydeltas,pcnt); - } else { - static int warned = false; - if ( !warned ) - LogError( _("Incorrect number of deltas in glyph %d (%s)\n"), gnum, - info->chars[gnum]->name!=NULL?info->chars[gnum]->name:"<Nameless>" ); - warned = true; - } - free(xdeltas); - free(ydeltas); -} - -static void parsegvar(struct ttfinfo *info, FILE *ttf) { - /* I'm only going to support a subset of the gvar. Only the global tuples */ - int axiscount, globaltc, gvarflags, gc, i,j,g; - uint32 tupoff, dataoff, *gvars; - struct variations *v = info->variations; - int warned=false; - - fseek(ttf,info->gvar_start,SEEK_SET); - if ( getlong(ttf)!=0x00010000 ) { /* I only understand version 1 */ - VariationFree(info); -return; - } - axiscount = getushort(ttf); - if ( axiscount!=info->variations->axis_count ) { - LogError( _("Hmm, the axis count in the 'gvar' table is different from that in the 'fvar' table.\n") ); - VariationFree(info); -return; - } - globaltc = getushort(ttf); - tupoff = getlong(ttf) + info->gvar_start; - gc = getushort(ttf); - gvarflags = getushort(ttf); - dataoff = getlong(ttf) + info->gvar_start; - if ( globaltc==0 || globaltc>AppleMmMax ) { - if ( globaltc==0 ) - LogError( _("Hmm, no global tuples specified in the 'gvar' table.\n") ); - else - LogError( _("Hmm, too many global tuples specified in the 'gvar' table.\n FontForge only supports %d\n"), AppleMmMax ); - VariationFree(info); -return; - } - if ( gc>info->glyph_cnt ) { - LogError( _("Hmm, more glyph variation data specified than there are glyphs in font.\n") ); - VariationFree(info); -return; - } - - gvars = galloc((gc+1)*sizeof(uint32)); - if ( gvarflags&1 ) { /* 32 bit data */ - for ( i=0; i<=gc; ++i ) - gvars[i] = getlong(ttf)+dataoff; - } else { - for ( i=0; i<=gc; ++i ) - gvars[i] = getushort(ttf)*2 +dataoff; /* Undocumented *2 */ - } - - v->tuple_count = globaltc; - v->tuples = gcalloc(globaltc,sizeof(struct tuples)); - fseek(ttf,tupoff,SEEK_SET); - for ( i=0; i<globaltc; ++i ) { - v->tuples[i].coords = galloc(axiscount*sizeof(float)); - for ( j=0; j<axiscount; ++j ) - v->tuples[i].coords[j] = ((short) getushort(ttf))/16384.0; - v->tuples[i].chars = InfoCopyGlyphs(info); - } - - for ( g=0; g<gc; ++g ) if ( gvars[g]!=gvars[g+1] ) { - int tc; - uint32 datoff; - int *sharedpoints=NULL; - fseek(ttf,gvars[g],SEEK_SET); - tc = getushort(ttf); - datoff = gvars[g]+getushort(ttf); - if ( tc&0x8000 ) { - uint32 here = ftell(ttf); - fseek(ttf,datoff,SEEK_SET); - sharedpoints = readpackedpoints(ttf); - datoff = ftell(ttf); - fseek(ttf,here,SEEK_SET); - } - for ( i=0; i<(tc&0xfff); ++i ) { - int tupleDataSize, tupleIndex; - tupleDataSize = getushort(ttf); - tupleIndex = getushort(ttf); - if ( tupleIndex&0xc000 ) { - if ( !warned ) - LogError( _("Warning: Glyph %d contains either private or intermediate tuple data.\n FontForge supports neither.\n"), - g); - warned = true; - if ( tupleIndex&0x8000 ) - fseek(ttf,2*axiscount,SEEK_CUR); - if ( tupleIndex&0x4000 ) - fseek(ttf,4*axiscount,SEEK_CUR); - } else { - int *localpoints=NULL; - uint32 here = ftell(ttf); - fseek(ttf,datoff,SEEK_SET); - if ( tupleIndex&0x2000 ) - localpoints = readpackedpoints(ttf); - VaryGlyphs(info,tupleIndex&0xfff,g, - (tupleIndex&0x2000)?localpoints:sharedpoints,ttf); - free(localpoints); - fseek(ttf,here,SEEK_SET); - } - datoff += tupleDataSize; - } - free(sharedpoints); - } - free(gvars); -} - -static void AlterEntry(struct ttf_table *cvt, int i, int delta ) { - int val = memushort(cvt->data,cvt->len,2*i); - memputshort(cvt->data,2*i,val+delta); -} - -static void VaryCvt(struct tuples *tuple,int *points, int *deltas, - int pcnt, struct ttf_table *orig_cvt) { - struct ttf_table *cvt; - int i; - - if ( (cvt = tuple->cvt)==NULL ) { - cvt = tuple->cvt = chunkalloc(sizeof(struct ttf_table)); - cvt->tag = orig_cvt->tag; - cvt->len = cvt->maxlen = orig_cvt->len; - cvt->data = galloc(cvt->len); - memcpy(cvt->data,orig_cvt->data,cvt->len); - } - if ( points[0]==ALL_POINTS ) { - for ( i=0; i<pcnt; ++i ) - AlterEntry(cvt,i,deltas[i]); - } else { - for ( i=0; i<pcnt; ++i ) - AlterEntry(cvt,points[i],deltas[i]); - } -} - -static void VaryCvts(struct ttfinfo *info,int tupleIndex, int *points, FILE *ttf, - struct ttf_table *origcvt ) { - /* one annoying thing about gvar, is that the variations do not describe */ - /* designs. well variations for [0,1] describes that design, but the */ - /* design for [1,1] includes the variations [0,1], [1,0], and [1,1] */ - /* And same is true of cvar */ - int pcnt, tc; - int *deltas; - struct variations *v = info->variations; - - if ( points[0]==ALL_POINTS ) - pcnt = origcvt->len/sizeof(uint16); - else { - for ( pcnt=0; points[pcnt]!=END_OF_POINTS; ++pcnt ); - } - deltas = readpackeddeltas(ttf,pcnt); - if ( deltas[0]!=BAD_DELTA ) - for ( tc = 0; tc<v->tuple_count; ++tc ) { - if ( TuplesMatch(v,tc,tupleIndex)) - VaryCvt(&v->tuples[tc],points,deltas,pcnt,origcvt); - } else { - static int warned = false; - if ( !warned ) - LogError( _("Incorrect number of deltas in cvt\n") ); - warned = true; - } - free(deltas); -} - -static void parsecvar(struct ttfinfo *info, FILE *ttf) { - struct ttf_table *cvt; - int tuplecount; - uint32 offset; - int *sharedpoints=NULL; - int i; - int warned = false; - - for ( cvt = info->tabs; cvt!=NULL && cvt->tag!=CHR('c','v','t',' '); cvt=cvt->next ); - if ( cvt==NULL ) -return; - - fseek(ttf,info->cvar_start,SEEK_SET); - if ( getlong(ttf)!=0x00010000 ) { /* I only understand version 1 */ - /* I think I can live without cvt variations... */ - /* So I shan't free the structure */ -return; - } - - tuplecount = getushort(ttf); - offset = info->cvar_start+getushort(ttf); - /* The documentation implies there are flags packed into the tuplecount */ - /* but John Jenkins tells me that shared points don't apply to cvar */ - /* Might as well parse it just in case */ - if ( tuplecount&0x8000 ) { - uint32 here = ftell(ttf); - fseek(ttf,offset,SEEK_SET); - sharedpoints = readpackedpoints(ttf); - offset = ftell(ttf); - fseek(ttf,here,SEEK_SET); - } - for ( i=0; i<(tuplecount&0xfff); ++i ) { - int tupleDataSize, tupleIndex; - tupleDataSize = getushort(ttf); - tupleIndex = getushort(ttf); - /* there is no provision here for a global tuple coordinate section */ - /* so John says there are no tuple indeces. Just embedded tuples */ - if ( tupleIndex&0x4000 ) { - if ( !warned ) - LogError( _("Warning: 'cvar' contains intermediate tuple data.\n FontForge doesn't support this.\n") ); - warned = true; - if ( tupleIndex&0x8000 ) - fseek(ttf,2*info->variations->axis_count,SEEK_CUR); - if ( tupleIndex&0x4000 ) - fseek(ttf,4*info->variations->axis_count,SEEK_CUR); - } else { - int *localpoints=NULL; - uint32 here; - int j,k,ti; - ti = tupleIndex&0xfff; - if ( tupleIndex&0x8000 ) { - real *coords = galloc(info->variations->axis_count*sizeof(real)); - for ( j=0; j<info->variations->axis_count; ++j ) - coords[j] = ((int16) getushort(ttf))/16384.0; - for ( k=0 ; k<info->variations->tuple_count; ++k ) { - for ( j=0; j<info->variations->axis_count; ++j ) - if ( coords[j]!=info->variations->tuples[k].coords[j] ) - break; - if ( j==info->variations->axis_count ) - break; - } - ti = -1; - if ( k!=info->variations->tuple_count ) - ti = k; - } - if ( ti!=-1 ) { - here = ftell(ttf); - fseek(ttf,offset,SEEK_SET); - if ( tupleIndex&0x2000 ) - localpoints = readpackedpoints(ttf); - VaryCvts(info,ti,(tupleIndex&0x2000)?localpoints:sharedpoints,ttf,cvt); - free(localpoints); - fseek(ttf,here,SEEK_SET); - } - } - offset += tupleDataSize; - } - free(sharedpoints); -} - -void readttfvariations(struct ttfinfo *info, FILE *ttf) { - if ( info->gvar_start==0 || info->gvar_len==0 || info->fvar_start==0 || info->fvar_len==0 ) -return; - - ff_progress_change_line2(_("Processing Variations")); - parsefvar(info,ttf); - if ( info->variations!=NULL && info->avar_start!=0 ) - parseavar(info,ttf); - if ( info->variations!=NULL ) - parsegvar(info,ttf); - if ( info->variations!=NULL && info->cvar_start!=0 && info->cvt_start!=0 ) - parsecvar(info,ttf); -} |