diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/psread.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/psread.c | 701 |
1 files changed, 689 insertions, 12 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/psread.c b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/psread.c index c5e4958d0f5..cb3b0676699 100644 --- a/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/psread.c +++ b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/psread.c @@ -36,6 +36,10 @@ # include <ieeefp.h> /* Solaris defines isnan in ieeefp rather than math.h */ #endif +int THdo_hint_guessing = 0; +int THdo_set_reversing = 0; +int THdo_catagorize = 0; + typedef struct _io { char *macro, *start; FILE *ps, *fog; @@ -2673,7 +2677,7 @@ static void EntityDefaultStrokeFill(Entity *ent) { static SplinePointList *SplinesFromEntityChar(EntityChar *ec,int *flags,int is_stroked) { Entity *ent, *next; - SplinePointList *head=NULL, *last, *new, *nlast, *temp, *each, *transed; + SplinePointList *head=NULL, *last=NULL, *new, *nlast=NULL, *temp, *each, *transed; StrokeInfo si; real inversetrans[6]; /*SplineSet *spl;*/ @@ -4072,7 +4076,8 @@ SplineChar *PSCharStringToSplines(uint8 *type1, int len, struct pscontext *conte done: if ( pcsp!=0 ) LogError( _("end of subroutine reached with no return in %s\n"), name ); - SCCatagorizePoints(ret); + if (THdo_catagorize) + SCCatagorizePoints(ret); ret->hstem = HintsAppend(ret->hstem,activeh); activeh=NULL; ret->vstem = HintsAppend(ret->vstem,activev); activev=NULL; @@ -4097,27 +4102,699 @@ SplineChar *PSCharStringToSplines(uint8 *type1, int len, struct pscontext *conte SplineMake3(cur->last,cur->first); cur->last = cur->first; } - /* Oh, I see. PS and TT disagree on which direction to use, so Fontographer*/ /* chose the TT direction and we must reverse postscript */ - for ( cur = ret->layers[ly_fore].splines; cur!=NULL; cur = cur->next ) + if (THdo_set_reversing) { + for ( cur = ret->layers[ly_fore].splines; cur!=NULL; cur = cur->next ) SplineSetReverse(cur); + } if ( ret->hstem==NULL && ret->vstem==NULL ) ret->manualhints = false; if ( !is_type2 && context->instance_count!=0 ) { UnblendFree(ret->hstem); UnblendFree(ret->vstem); } - ret->hstem = HintCleanup(ret->hstem,true,context->instance_count); - ret->vstem = HintCleanup(ret->vstem,true,context->instance_count); - SCGuessHHintInstancesList(ret,ly_fore); - SCGuessVHintInstancesList(ret,ly_fore); - ret->hconflicts = StemListAnyConflicts(ret->hstem); - ret->vconflicts = StemListAnyConflicts(ret->vstem); - if ( context->instance_count==1 && !ret->hconflicts && !ret->vconflicts ) + if (THdo_hint_guessing) { + ret->hstem = HintCleanup(ret->hstem,true,context->instance_count); + ret->vstem = HintCleanup(ret->vstem,true,context->instance_count); + SCGuessHHintInstancesList(ret,ly_fore); + SCGuessVHintInstancesList(ret,ly_fore); + ret->hconflicts = StemListAnyConflicts(ret->hstem); + ret->vconflicts = StemListAnyConflicts(ret->vstem); + if ( context->instance_count==1 && !ret->hconflicts && !ret->vconflicts ) SCClearHintMasks(ret,ly_fore,false); - HintsRenumber(ret); + HintsRenumber(ret); + } if ( name!=NULL && strcmp(name,".notdef")!=0 ) ret->widthset = true; return( ret ); } + + +/* This finds the 'connect-the-dots' boundingbox of a Type2 charstring */ +/* It is a simplified version of PSCharStringToSplines, above */ + +SplineChar *PSCharStringToBB(uint8 *type1, int len, struct pscontext *context, + struct pschars *subrs, struct pschars *gsubrs, const char *name) { + real stack[50]; int sp=0, v; /* Type1 stack is about 25 long, Type2 stack is 48 */ + real transient[32]; + SplineChar *ret = SplineCharCreate(2); + + DBasePoint current, ll, ur; + real dx, dy, dx2, dy2, dx3, dy3, dx4, dy4, dx5, dy5, dx6=0, dy6; + + int first = 1; /* to flag extra set width */ + /* subroutines may be nested to a depth of 10 */ + struct substate { unsigned char *type1; int len; int subnum; } pcstack[11]; + int pcsp=0; + + real pops[30]; + int popsp=0; + int base, polarity; + + struct pschars *s; + int hint_cnt = 0; + + int last_was_b1=false, old_last_was_b1; + + ret->name = copy( name ); + ret->unicodeenc = -1; + ret->width = (int16) 0x8000; + if ( name==NULL ) name = "unnamed"; + ret->manualhints = true; + if ( !context->is_type2 ) { + LogError( _("Quick boundingbox mode only does CFF charstrings, not Type1 (font %s)\n"), name ); + return (ret); + } + + current.x = current.y = 0; + ll.x = ll.y = (int16) 0x7FFF; + ur.x = ur.y = (int16) -0x7FFF; + + while ( len>0 ) { + if ( sp>48 ) { + LogError( _("Stack got too big in %s\n"), name ); + sp = 48; + } + base = 0; + --len; + if ( (v = *type1++)>=32 ) { + if ( v<=246) { + stack[sp++] = v - 139; + } else if ( v<=250 ) { + stack[sp++] = (v-247)*256 + *type1++ + 108; + --len; + } else if ( v<=254 ) { + stack[sp++] = -(v-251)*256 - *type1++ - 108; + --len; + } else { + int val = (*type1<<24) | (type1[1]<<16) | (type1[2]<<8) | type1[3]; + stack[sp++] = val; + type1 += 4; + len -= 4; + stack[sp-1] /= 65536.; + } + } else if ( v==28 ) { + stack[sp++] = (short) ((type1[0]<<8) | type1[1]); + type1 += 2; + len -= 2; + /* In the Dict tables of CFF, a 5byte fixed value is prefixed by a */ + /* 29 code. In Type2 strings the prefix is 255. */ + } else if ( v==12 ) { + old_last_was_b1 = last_was_b1; last_was_b1 = false; + v = *type1++; + --len; + switch ( v ) { + case 0: /* dotsection */ + sp = 0; + break; + case 1: /* vstem3 */ /* specifies three v hints zones at once */ + if ( sp<6 ) LogError( _("Stack underflow on vstem3 in %s\n"), name ); + /* according to the standard, if there is a vstem3 there can't */ + /* be any vstems, so there can't be any confusion about hint order */ + /* so we don't need to worry about unblended stuff */ + hint_cnt+=3; + sp = 0; + break; + case 2: /* hstem3 */ /* specifies three h hints zones at once */ + if ( sp<6 ) LogError( _("Stack underflow on hstem3 in %s\n"), name ); + hint_cnt+=3; + sp = 0; + break; + case 6: /* seac */ /* build accented characters */ + seac: + if ( sp<5 ) LogError( _("Stack underflow on seac in %s\n"), name ); + /* stack[0] must be the lsidebearing of the accent. I'm not sure why */ + sp = 0; + break; + case 7: /* sbw */ /* generalized width/sidebearing command */ + if ( sp<4 ) LogError( _("Stack underflow on sbw in %s\n"), name ); + ret->lsidebearing = stack[0]; + /* stack[1] is lsidebearing y (only for vertical writing styles, CJK) */ + ret->width = stack[2]; + /* stack[3] is height (for vertical writing styles, CJK) */ + sp = 0; + break; + case 5: case 9: case 14: case 26: + if ( sp<1 ) LogError( _("Stack underflow on unary operator in %s\n"), name ); + switch ( v ) { + case 5: stack[sp-1] = (stack[sp-1]==0); break; /* not */ + case 9: if ( stack[sp-1]<0 ) stack[sp-1]= -stack[sp-1]; break; /* abs */ + case 14: stack[sp-1] = -stack[sp-1]; break; /* neg */ + case 26: stack[sp-1] = sqrt(stack[sp-1]); break; /* sqrt */ + } + break; + case 3: case 4: case 10: case 11: case 12: case 15: case 24: + if ( sp<2 ) LogError( _("Stack underflow on binary operator in %s\n"), name ); + else switch ( v ) { + case 3: /* and */ + stack[sp-2] = (stack[sp-1]!=0 && stack[sp-2]!=0); + break; + case 4: /* and */ + stack[sp-2] = (stack[sp-1]!=0 || stack[sp-2]!=0); + break; + case 10: /* add */ + stack[sp-2] += stack[sp-1]; + break; + case 11: /* sub */ + stack[sp-2] -= stack[sp-1]; + break; + case 12: /* div */ + stack[sp-2] /= stack[sp-1]; + break; + case 24: /* mul */ + stack[sp-2] *= stack[sp-1]; + break; + case 15: /* eq */ + stack[sp-2] = (stack[sp-1]==stack[sp-2]); + break; + } + --sp; + break; + case 22: /* ifelse */ + if ( sp<4 ) LogError( _("Stack underflow on ifelse in %s\n"), name ); + else { + if ( stack[sp-2]>stack[sp-1] ) + stack[sp-4] = stack[sp-3]; + sp -= 3; + } + break; + case 23: /* random */ + /* This function returns something (0,1]. It's not clear to me*/ + /* if rand includes 0 and RAND_MAX or not, but this approach */ + /* should work no matter what */ + do { + stack[sp] = (rand()/(RAND_MAX-1)); + } while ( stack[sp]==0 || stack[sp]>1 ); + ++sp; + break; + case 20: /* put */ + if ( sp<2 ) LogError( _("Too few items on stack for put in %s\n"), name ); + else if ( stack[sp-1]<0 || stack[sp-1]>=32 ) LogError( _("Reference to transient memory out of bounds in put in %s\n"), name ); + else { + transient[(int)stack[sp-1]] = stack[sp-2]; + sp -= 2; + } + break; + case 21: /* get */ + if ( sp<1 ) LogError( _("Too few items on stack for get in %s\n"), name ); + else if ( stack[sp-1]<0 || stack[sp-1]>=32 ) LogError( _("Reference to transient memory out of bounds in put in %s\n"), name ); + else + stack[sp-1] = transient[(int)stack[sp-1]]; + break; + case 17: /* pop */ + /* pops something from the postscript stack and pushes it on ours */ + /* used to get a return value from an othersubr call */ + /* Bleah. Adobe wants the pops to return the arguments if we */ + /* don't understand the call. What use is the subroutine then?*/ + if ( popsp<=0 ) + LogError( _("Pop stack underflow on pop in %s\n"), name ); + else + stack[sp++] = pops[--popsp]; + break; + case 18: /* drop */ + if ( sp>0 ) --sp; + break; + case 27: /* dup */ + if ( sp>=1 ) { + stack[sp] = stack[sp-1]; + ++sp; + } + break; + case 28: /* exch */ + if ( sp>=2 ) { + real temp = stack[sp-1]; + stack[sp-1] = stack[sp-2]; stack[sp-2] = temp; + } + break; + case 29: /* index */ + if ( sp>=1 ) { + int index = stack[--sp]; + if ( index<0 || sp<index+1 ) + LogError( _("Index out of range in %s\n"), name ); + else { + stack[sp] = stack[sp-index-1]; + ++sp; + } + } + break; + case 30: /* roll */ + if ( sp>=2 ) { + int j = stack[sp-1], N=stack[sp-2]; + if ( N>sp || j>=N || j<0 || N<0 ) + LogError( _("roll out of range in %s\n"), name ); + else if ( j==0 || N==0 ) + /* No op */; + else { + real *temp = galloc(N*sizeof(real)); + int i; + for ( i=0; i<N; ++i ) + temp[i] = stack[sp-N+i]; + for ( i=0; i<N; ++i ) + stack[sp-N+i] = temp[(i+j)%N]; + free(temp); + } + } + break; + case 33: /* setcurrentpoint */ + if ( sp<2 ) LogError( _("Stack underflow on setcurrentpoint in %s\n"), name ); + else { + current.x = stack[0]; + current.y = stack[1]; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + } + sp = 0; + break; + case 34: /* hflex */ + case 35: /* flex */ + case 36: /* hflex1 */ + case 37: /* flex1 */ + dy = dy3 = dy4 = dy5 = dy6 = 0; + dx = stack[base++]; + if ( v!=34 ) + dy = stack[base++]; + dx2 = stack[base++]; + dy2 = stack[base++]; + dx3 = stack[base++]; + if ( v!=34 && v!=36 ) + dy3 = stack[base++]; + dx4 = stack[base++]; + if ( v!=34 && v!=36 ) + dy4 = stack[base++]; + dx5 = stack[base++]; + if ( v==34 ) + dy5 = -dy2; + else + dy5 = stack[base++]; + switch ( v ) { + real xt, yt; + case 35: /* flex */ + dx6 = stack[base++]; + dy6 = stack[base++]; + break; + case 34: /* hflex */ + dx6 = stack[base++]; + break; + case 36: /* hflex1 */ + dx6 = stack[base++]; + dy6 = -dy-dy2-dy5; + break; + case 37: /* flex1 */ + xt = dx+dx2+dx3+dx4+dx5; + yt = dy+dy2+dy3+dy4+dy5; + if ( xt<0 ) xt= -xt; + if ( yt<0 ) yt= -yt; + if ( xt>yt ) { + dx6 = stack[base++]; + dy6 = -dy-dy2-dy3-dy4-dy5; + } else { + dy6 = stack[base++]; + dx6 = -dx-dx2-dx3-dx4-dx5; + } + break; + } + current.x = current.x+dx; current.y = current.y+dy; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + current.x = current.x+dx2; current.y = current.y+dy2; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + current.x = current.x+dx3; current.y = current.y+dy3; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + + current.x = current.x+dx4; current.y = current.y+dy4; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + current.x = current.x+dx5; current.y = current.y+dy5; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + current.x = current.x+dx6; current.y = current.y+dy6; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + sp = 0; + break; + default: + LogError( _("Uninterpreted opcode 12,%d in %s\n"), v, name ); + break; + } + } else { last_was_b1 = false; switch ( v ) { + case 1: /* hstem */ + case 18: /* hstemhm */ + base = 0; + if ( (sp&1) && ret->width == (int16) 0x8000 ) + ret->width = stack[0]; + if ( sp&1 ) + base=1; + if ( sp-base<2 ) + LogError( _("Stack underflow on hstem in %s\n"), name ); + /* stack[0] is absolute y for start of horizontal hint */ + /* (actually relative to the y specified as lsidebearing y in sbw*/ + /* stack[1] is relative y for height of hint zone */ + + + while ( sp-base>=2 ) { + hint_cnt++; + base+=2; + } + sp = 0; + break; + case 19: /* hintmask */ + case 20: /* cntrmask */ + /* If there's anything on the stack treat it as a vstem hint */ + case 3: /* vstem */ + case 23: /* vstemhm */ + base = 0; + if ( first || v==3 || v==23 ) { + if ( (sp&1) && ret->width == (int16) 0x8000 ) { + ret->width = stack[0]; + } + if ( sp&1 ) + base=1; + if ( sp-base<2 && v!=19 && v!=20 ) + LogError( _("Stack underflow on vstem in %s\n"), name ); + /* stack[0] is absolute x for start of vertical hint */ + /* (actually relative to the x specified as lsidebearing in h/sbw*/ + /* stack[1] is relative x for height of hint zone */ + + + while ( sp-base>=2 ) { + hint_cnt++; + base+=2; + } + sp = 0; + } + if ( v==19 || v==20 ) { /* hintmask, cntrmask */ + unsigned bytes = (hint_cnt+7)/8; + if ( bytes>sizeof(HintMask) ) bytes = sizeof(HintMask); + if ( bytes!=(unsigned)hint_cnt/8 ) { + int mask = 0xff>>(hint_cnt&7); + if ( type1[bytes-1]&mask ) + LogError( _("Hint mask (or counter mask) with too many hints in %s\n"), name ); + } + type1 += bytes; + len -= bytes; + } + break; + case 14: /* endchar */ + /* endchar is allowed to terminate processing even within a subroutine */ + if ( (sp&1) && ret->width == (int16) 0x8000 ) + ret->width = stack[0]; + pcsp = 0; + if ( sp==4 ) { + /* In Type2 strings endchar has a depreciated function of doing */ + /* a seac (which doesn't exist at all). Except enchar takes */ + /* 4 args and seac takes 5. Bleah */ + stack[4] = stack[3]; stack[3] = stack[2]; stack[2] = stack[1]; stack[1] = stack[0]; + stack[0] = 0; + sp = 5; + goto seac; + } else if ( sp==5 ) { + /* same as above except also specified a width */ + stack[0] = 0; + goto seac; + } + /* the docs say that endchar must be the last command in a char */ + goto done; + break; + case 13: /* hsbw (set left sidebearing and width) */ + if ( sp<2 ) LogError( _("Stack underflow on hsbw in %s\n"), name ); + ret->lsidebearing = stack[0]; + current.x = stack[0]; /* sets the current point too */ + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + ret->width = stack[1]; + sp = 0; + break; + case 9: /* closepath */ + sp = 0; + break; + case 21: /* rmoveto */ + case 22: /* hmoveto */ + case 4: /* vmoveto */ + if (( (v==21 && sp==3) || (v!=21 && sp==2)) && ret->width == (int16) 0x8000 ) + /* Character's width may be specified on the first moveto */ + ret->width = stack[0]; + if ( v==21 && sp>2 ) { + stack[0] = stack[sp-2]; stack[1] = stack[sp-1]; + sp = 2; + } else if ( v!=21 && sp>1 ) { + stack[0] = stack[sp-1]; + sp = 1; + } + /* fall through */ + case 5: /* rlineto */ + case 6: /* hlineto */ + case 7: /* vlineto */ + polarity = 0; + base = 0; + while ( base<sp ) { + dx = dy = 0; + if ( v==5 || v==21 ) { + if ( sp<base+2 ) { + LogError( _("Stack underflow on rlineto/rmoveto in %s\n"), name ); + break; + } + dx = stack[base++]; + dy = stack[base++]; + } else if ( (v==6 && !(polarity&1)) || (v==7 && (polarity&1)) || v==22 ) { + if ( sp<=base ) { + LogError( _("Stack underflow on hlineto/hmoveto in %s\n"), name ); + break; + } + dx = stack[base++]; + } else /*if ( (v==7 && !(parity&1)) || (v==6 && (parity&1) || v==4 )*/ { + if ( sp<=base ) { + LogError( _("Stack underflow on vlineto/vmoveto in %s\n"), name ); + break; + } + dy = stack[base++]; + } + ++polarity; + current.x = current.x+dx; current.y = current.y+dy; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + if ( v==4 || v==21 || v==22 ) { + first = 0; + break; + } else { + first = 0; + } + } + sp = 0; + break; + case 25: /* rlinecurve */ + base = 0; + while ( sp>base+6 ) { + current.x = current.x+stack[base++]; current.y = current.y+stack[base++]; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + first = 0; + } + case 24: /* rcurveline */ + case 8: /* rrcurveto */ + case 31: /* hvcurveto */ + case 30: /* vhcurveto */ + case 27: /* hhcurveto */ + case 26: /* vvcurveto */ + polarity = 0; + while ( sp>base+2 ) { + dx = dy = dx2 = dy2 = dx3 = dy3 = 0; + if ( v==8 || v==25 || v==24 ) { + if ( sp<6+base ) { + LogError( _("Stack underflow on rrcurveto in %s\n"), name ); + base = sp; + } else { + dx = stack[base++]; + dy = stack[base++]; + dx2 = stack[base++]; + dy2 = stack[base++]; + dx3 = stack[base++]; + dy3 = stack[base++]; + } + } else if ( v==27 ) { /* hhcurveto */ + if ( sp<4+base ) { + LogError( _("Stack underflow on hhcurveto in %s\n"), name ); + base = sp; + } else { + if ( (sp-base)&1 ) dy = stack[base++]; + dx = stack[base++]; + dx2 = stack[base++]; + dy2 = stack[base++]; + dx3 = stack[base++]; + } + } else if ( v==26 ) { /* vvcurveto */ + if ( sp<4+base ) { + LogError( _("Stack underflow on hhcurveto in %s\n"), name ); + base = sp; + } else { + if ( (sp-base)&1 ) dx = stack[base++]; + dy = stack[base++]; + dx2 = stack[base++]; + dy2 = stack[base++]; + dy3 = stack[base++]; + } + } else if ( (v==31 && !(polarity&1)) || (v==30 && (polarity&1)) ) { + if ( sp<4+base ) { + LogError( _("Stack underflow on hvcurveto in %s\n"), name ); + base = sp; + } else { + dx = stack[base++]; + dx2 = stack[base++]; + dy2 = stack[base++]; + dy3 = stack[base++]; + if ( sp==base+1 ) + dx3 = stack[base++]; + } + } else /*if ( (v==30 && !(polarity&1)) || (v==31 && (polarity&1)) )*/ { + if ( sp<4+base ) { + LogError( _("Stack underflow on vhcurveto in %s\n"), name ); + base = sp; + } else { + dy = stack[base++]; + dx2 = stack[base++]; + dy2 = stack[base++]; + dx3 = stack[base++]; + if ( sp==base+1 ) + dy3 = stack[base++]; + } + } + ++polarity; + current.x = current.x+dx; current.y = current.y+dy; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + current.x = current.x+dx2; current.y = current.y+dy2; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + current.x = current.x+dx3; current.y = current.y+dy3; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + } + if ( v==24 ) { + current.x = current.x+stack[base++]; current.y = current.y+stack[base++]; + if (ll.y>current.y) ll.y = current.y; + if (ur.y<current.y) ur.y = current.y; + if (ll.x>current.x) ll.x = current.x; + if (ur.x<current.x) ur.x = current.x; + } + sp = 0; + break; + case 29: /* callgsubr */ + case 10: /* callsubr */ + /* stack[sp-1] contains the number of the subroutine to call */ + if ( sp<1 ) { + LogError( _("Stack underflow on callsubr in %s\n"), name ); + break; + } else if ( pcsp>10 ) { + LogError( _("Too many subroutine calls in %s\n"), name ); + break; + } + s=subrs; if ( v==29 ) s = gsubrs; + if ( s!=NULL ) stack[sp-1] += s->bias; + /* Type2 subrs have a bias that must be added to the subr-number */ + /* Type1 subrs do not. We set the bias on them to 0 */ + if ( s==NULL || stack[sp-1]>=s->cnt || stack[sp-1]<0 || + s->values[(int) stack[sp-1]]==NULL ) + LogError( _("Subroutine number out of bounds in %s\n"), name ); + else { + pcstack[pcsp].type1 = type1; + pcstack[pcsp].len = len; + pcstack[pcsp].subnum = stack[sp-1]; + ++pcsp; + type1 = s->values[(int) stack[sp-1]]; + len = s->lens[(int) stack[sp-1]]; + } + if ( --sp<0 ) sp = 0; + break; + case 11: /* return */ + /* return from a subr outine */ + if ( pcsp<1 ) LogError( _("return when not in subroutine in %s\n"), name ); + else { + --pcsp; + type1 = pcstack[pcsp].type1; + len = pcstack[pcsp].len; + } + break; + case 16: { /* blend -- obsolete type 2 multiple master operator */ + int cnt,i,j; + if ( context->instance_count==0 ) + LogError( _("Attempt to use a multiple master subroutine in a non-mm font.\n") ); + else if ( sp<1 || sp<context->instance_count*stack[sp-1]+1 ) + LogError( _("Too few items on stack for blend in %s\n"), name ); + else { + if ( !context->blend_warn ) { + LogError( _("Use of obsolete blend operator.\n") ); + context->blend_warn = true; + } + cnt = stack[sp-1]; + sp -= context->instance_count*stack[sp-1]+1; + for ( i=0; i<cnt; ++i ) { + for ( j=1; j<context->instance_count; ++j ) + stack[sp+i] += context->blend_values[j]*stack[sp+ + cnt+ i*(context->instance_count-1)+ j-1]; + } + /* there will always be fewer pushes than there were pops */ + /* so I don't bother to check the stack */ + sp += cnt; + } + } + break; + default: + LogError( _("Uninterpreted opcode %d in %s\n"), v, name ); + break; + }} + } +done: + if ( pcsp!=0 ) + LogError( _("end of subroutine reached with no return in %s\n"), name ); + + if ( name!=NULL && strcmp(name,".notdef")!=0 ) + ret->widthset = true; + if (ur.x == -0x7FFF) ur.x = 0; + if (ur.y == -0x7FFF) ur.y = 0; + if (ll.x == 0x7FFF) ll.x = 0; + if (ll.y == 0x7FFF) ll.y = 0; + if (ll.x>ur.x) ll.x = ur.x; + if (ll.y>ur.y) ll.y = ur.y; + + + ret->xmin = rint(ll.x); + ret->ymin = rint(ll.y); + ret->xmax = rint(ur.x); + ret->ymax = rint(ur.y); + /* free the curves */ + if (ret->layers!=NULL && ret->layers[ly_fore].splines != NULL) { + SplinePointListsFree(ret->layers[ly_fore].splines); + ret->layers[ly_fore].splines=NULL; + } + if (ret->layers[ly_fore].refs!=NULL) { + RefCharsFree(ret->layers[ly_fore].refs); + ret->layers[ly_fore].refs = NULL; + } + return( ret ); +} |