/* Copyright (C) 2005-2011 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 * dercved 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 "fontforgeui.h" #include #include #include #include extern GBox _ggadget_Default_Box; #define MAIN_FOREGROUND (_ggadget_Default_Box.main_foreground) #ifdef FREETYPE_HAS_DEBUGGER #include #include FT_FREETYPE_H #if defined(__MINGW32__) # if FREETYPE_MINOR>=2 # include # endif # include #else # if FREETYPE_MINOR>=2 # include # endif # include "ttinterp.h" #endif #if FREETYPE_MAJOR==2 && (FREETYPE_MINOR<3 || (FREETYPE_MINOR==3 && FREETYPE_PATCH<5)) # define PPEMX(exc) ((exc)->size->metrics.x_ppem) # define PPEMY(exc) ((exc)->size->metrics.y_ppem) #else # define PPEMX(exc) ((exc)->size->root.metrics.x_ppem) # define PPEMY(exc) ((exc)->size->root.metrics.y_ppem) #endif struct scr { int y, fh; int lines; GWindow pixmap; }; static int ttround(int val, TT_ExecContext exc) { if ( val<0 ) return( -ttround(-val,exc)); switch ( exc->GS.round_state ) { case TT_Round_To_Grid: val = 64*((val+32)/64); break; case TT_Round_Down_To_Grid: val = 64*(val/64); break; case TT_Round_Up_To_Grid: val = 64*((val+63)/64); break; case TT_Round_To_Half_Grid: val = 64*(val/64)+32; break; case TT_Round_Super: val = (val - exc->phase + exc->threshold) & -exc->period; val += exc->phase; break; case TT_Round_Super_45: val = ((val - exc->phase + exc->threshold) / exc->period)*exc->period; val += exc->phase; break; } return(val); } static void scrprintf(struct scr *scr, char *format, ... ) { va_list ap; char buffer[100]; va_start(ap,format); vsnprintf(buffer,sizeof(buffer),format,ap); GDrawDrawBiText8(scr->pixmap,3,scr->y,buffer,-1,NULL,MAIN_FOREGROUND); scr->y += scr->fh; ++scr->lines; } static void scrrounding(struct scr *scr, TT_ExecContext exc ) { scrprintf(scr, "RndState: %s", exc->GS.round_state==TT_Round_To_Half_Grid? "To Half Grid" : exc->GS.round_state==TT_Round_To_Grid? "To Grid" : exc->GS.round_state==TT_Round_To_Double_Grid? "To Double Grid" : exc->GS.round_state==TT_Round_Down_To_Grid? "Down To Grid" : exc->GS.round_state==TT_Round_Up_To_Grid? "Up To Grid" : exc->GS.round_state==TT_Round_Off? "Off" : exc->GS.round_state==TT_Round_Super? "Super" : exc->GS.round_state==TT_Round_Super_45? "Super45" : "Unknown" ); } static void scrfree(struct scr *scr, TT_ExecContext exc ) { scrprintf(scr, "freeVec: %g,%g", (((int)exc->GS.freeVector.x<<16)>>(16+14)) + ((exc->GS.freeVector.x&0x3fff)/16384.0), (((int)exc->GS.freeVector.y<<16)>>(16+14)) + ((exc->GS.freeVector.y&0x3fff)/16384.0) ); } static void scrproj(struct scr *scr, TT_ExecContext exc ) { scrprintf(scr,"projVec: %g,%g", (((int)exc->GS.projVector.x<<16)>>(16+14)) + ((exc->GS.projVector.x&0x3fff)/16384.0), (((int)exc->GS.projVector.y<<16)>>(16+14)) + ((exc->GS.projVector.y&0x3fff)/16384.0) ); } static int DVGlossExpose(GWindow pixmap,DebugView *dv,GEvent *event) { TT_ExecContext exc = DebuggerGetEContext(dv->dc); CharView *cv = dv->cv; long val1, val2, ret, i, cnt, off, a1, a2, b1, b2; int operator; BasePoint freedom; struct scr scr; int base; GDrawFillRect(pixmap,&event->u.expose.rect,GDrawGetDefaultBackground(screen_display)); GDrawSetFont(pixmap,dv->ii.gfont); scr.pixmap = pixmap; scr.y = 3+dv->ii.as - dv->gloss_offtop*dv->ii.fh; scr.lines = 0; scr.fh = dv->ii.fh; if ( exc==NULL ) { scrprintf(&scr,""); return(1); } if ( exc->IP>=exc->codeSize || exc->code==NULL ) { scrprintf(&scr,""); return(1); } operator = ((uint8 *) exc->code)[exc->IP]; if ( operator>=0xc0 && operator <= 0xdf ) { scrprintf(&scr," MDRP: Move Direct Relative Point"); if ( operator&0x10 ) scrprintf(&scr,(operator&0x10)?" Set rp0 to point":" don't set rp0 to point" ); scrprintf(&scr,(operator&8)?" Keep distance>=min dist":" don't keep distance>=min dist"); scrprintf(&scr,(operator&4)?" Round distance":" don't round distance"); scrprintf(&scr,(operator&3)==0?" Grey":(operator&3)==1?" Black":(operator&3)==2?" White":" Undefined Rounding"); scrprintf(&scr,"Move point so cur distance to rp0 is"); scrprintf(&scr," the same as the original distance between"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (point (%.2f,%.2f))", val1, exc->zp1.cur[val1].x/64.0,exc->zp1.cur[val1].y/64.0 ); scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); val2 = exc->GS.rp0; scrprintf(&scr,"Reference Point rp0: %d (%.2f,%.2f)", val2, exc->zp0.cur[val2].x/64.0,exc->zp0.cur[val2].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrprintf(&scr,"Sets rp1: %d (rp0)", val2); scrprintf(&scr,"Sets rp2: %d (point)", val1); scrprintf(&scr, "MinDist: %.2f", exc->GS.minimum_distance/64.0 ); scrprintf(&scr, "SingWidVal: %.2f", exc->GS.single_width_value/64.0 ); scrprintf(&scr, "SingWidCut: %.2f", exc->GS.single_width_cutin/64.0 ); scrrounding(&scr,exc); scrfree(&scr,exc); scrproj(&scr,exc); } else if ( operator>=0xe0 && operator <= 0xff ) { scrprintf(&scr," MIRP: Move Indirect Relative Point"); if ( operator&0x10 ) scrprintf(&scr,(operator&0x10)?" Set rp0 to point":" don't set rp0 to point" ); scrprintf(&scr,(operator&8)?" Keep distance>=min dist":" don't keep distance>=min dist"); scrprintf(&scr,(operator&4)?" Round distance/use cvt cutin":" don't round distance nor use cvt cutin"); scrprintf(&scr,(operator&3)==0?" Grey":(operator&3)==1?" Black":(operator&3)==2?" White":" Undefined Rounding"); scrprintf(&scr,"Move point along freedom vector so distance"); scrprintf(&scr," measured along projection to rp0 is the"); scrprintf(&scr," value in the cvt table"); val2 = exc->stack[exc->top-1]; val1 = exc->stack[exc->top-2]; scrprintf(&scr,"Pops: %d (point (%.2f,%.2f))", val1, exc->zp1.cur[val1].x/64.0,exc->zp1.cur[val1].y/64.0 ); scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); scrprintf(&scr,"Pop: %d (cvt %.2f)", val2, exc->cvt[val2]/64.0 ); val2 = exc->GS.rp0; scrprintf(&scr,"Reference Point rp0: %d (%.2f,%.2f)", val2, exc->zp0.cur[val2].x/64.0,exc->zp0.cur[val2].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrprintf(&scr,"Sets rp1: %d (rp0)", val2); scrprintf(&scr,"Sets rp2: %d (point)", val1); scrprintf(&scr, "MinDist: %.2f", exc->GS.minimum_distance/64.0 ); scrprintf(&scr, "CvtCutin: %.2f", exc->GS.control_value_cutin/64.0 ); scrprintf(&scr, "SingWidVal: %.2f", exc->GS.single_width_value/64.0 ); scrprintf(&scr, "SingWidCut: %.2f", exc->GS.single_width_cutin/64.0 ); scrprintf(&scr, "AutoFlip: %s", exc->GS.auto_flip?"True": "False" ); scrrounding(&scr,exc); scrfree(&scr,exc); scrproj(&scr,exc); } else if ( operator>=0xb0 && operator <= 0xb7 ) { scrprintf(&scr," Pushes %d byte%s", operator+1-0xb0, operator==0xb0?"":"s" ); } else if ( operator>=0xb8 && operator <= 0xbf ) { scrprintf(&scr," Pushes %d word%s", operator+1-0xb8, operator==0xb8?"":"s" ); } else switch ( operator ) { case 0x0: scrprintf(&scr," Set Freedom/Projection vector to y axis"); break; case 0x1: scrprintf(&scr," Set Freedom/Projection vector to x axis"); break; case 0x2: scrprintf(&scr," Set Projection vector to y axis"); break; case 0x3: scrprintf(&scr," Set Projection vector to x axis"); break; case 0x4: scrprintf(&scr," Set Freedom vector to y axis"); break; case 0x5: scrprintf(&scr," Set Freedom vector to x axis"); break; case 0xb: case 0xa: scrprintf(&scr," Set %s vector from stack", operator==0xb?"Freedom":"Projection"); val1 = exc->stack[exc->top-2]; val2 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %.4f (x-coord)", val1/16384.0 ); scrprintf(&scr,"Pops: %.4f (y-coord)", val2/16384.0 ); scrprintf(&scr,"Sets: %s Vector", operator==0xb?"Freedom":"Projection" ); break; case 0xe: scrprintf(&scr," Set Freedom vector to Projection vector"); scrprintf(&scr,"projVec: %g,%g", (((int)exc->GS.projVector.x<<16)>>(16+14)) + ((exc->GS.projVector.x&0x3fff)/16384.0), (((int)exc->GS.projVector.y<<16)>>(16+14)) + ((exc->GS.projVector.y&0x3fff)/16384.0) ); scrprintf(&scr,"Sets: Freedom Vector" ); break; case 0xc: case 0xd: scrprintf(&scr,operator==0xc?" Get Projection Vector":" Get Freedom Vector"); scrprintf(&scr,operator==0xc?"Pushes: Projection Vector":"Pushes: Freedom Vector"); if ( operator==0xd ) scrfree(&scr,exc); else scrproj(&scr,exc); break; case 0xf: scrprintf(&scr," Moves point to intersection of two lines"); val1 = exc->stack[exc->top-5]; a1 = exc->stack[exc->top-4]; a2 = exc->stack[exc->top-3]; b1 = exc->stack[exc->top-2]; b2 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (point (%.2f,%.2f))", val1, exc->zp2.cur[val1].x/64.0,exc->zp2.cur[val1].y/64.0 ); scrprintf(&scr," (in zone from zp2: %s)", exc->GS.gep2?"Normal":"Twilight" ); scrprintf(&scr,"Pops: %d (line1.s (%.2f,%.2f))", a1, exc->zp0.cur[a1].x/64.0,exc->zp0.cur[a1].y/64.0 ); scrprintf(&scr,"Pops: %d (line1.e (%.2f,%.2f))", a2, exc->zp0.cur[a2].x/64.0,exc->zp0.cur[a2].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrprintf(&scr,"Pops: %d (line2.s (%.2f,%.2f))", b1, exc->zp1.cur[b1].x/64.0,exc->zp1.cur[b1].y/64.0 ); scrprintf(&scr,"Pops: %d (line2.e (%.2f,%.2f))", b2, exc->zp1.cur[b2].x/64.0,exc->zp1.cur[b2].y/64.0 ); scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); scrprintf(&scr,"(ignores freedom vector)"); break; case 0x10: scrprintf(&scr," Set Reference Point 0"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (point = new rp0)", val1 ); break; case 0x11: scrprintf(&scr," Set Reference Point 1"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (point = new rp1)", val1 ); break; case 0x12: scrprintf(&scr," Set Reference Point 2"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (point = new rp2)", val1 ); break; case 0x13: scrprintf(&scr," Set Zone Pointer 0"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (new zp0 %s)", val1, val1?"Normal":"Twilight" ); break; case 0x14: scrprintf(&scr," Set Zone Pointer 1"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (new zp1 %s)", val1, val1?"Normal":"Twilight" ); break; case 0x15: scrprintf(&scr," Set Zone Pointer 2"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (new zp2 %s)", val1, val1?"Normal":"Twilight" ); break; case 0x16: scrprintf(&scr," Set Zone Pointers"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (new zp0,zp1,zp2 %s)", val1, val1?"Normal":"Twilight" ); break; case 0x17: scrprintf(&scr," Set Loop variable"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (new loop count)", val1 ); break; case 0x1A: scrprintf(&scr," Set Minimum Distance"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (new minimum distance)", val1/64.0 ); break; case 0x1B: case 0x2D: case 0x59: switch( operator ) { case 0x1B: scrprintf(&scr," Else"); break; case 0x2D: scrprintf(&scr," End Function Definition (return)"); break; case 0x59: scrprintf(&scr," End If"); break; } break; case 0x1C: scrprintf(&scr," Jump Relative (to here)"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (byte offset)", val1 ); break; case 0x1D: scrprintf(&scr," Set Control Value Table Cut-In"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %.2f (new cvt cut-in value)", val1/64.0 ); break; case 0x1E: scrprintf(&scr," Set Single Width Cut-In"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %.2f (new single width cut-in value)", val1/64.0 ); break; case 0x1F: scrprintf(&scr," Set Single Width"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %.2f (new single width value)", val1/64.0 ); break; case 0x20: scrprintf(&scr," Duplicate TOS"); scrprintf(&scr,"Pushes: %d", exc->stack[exc->top-1] ); break; case 0x21: scrprintf(&scr," Pop TOS"); scrprintf(&scr,"Pops: %d", exc->stack[exc->top-1] ); break; case 0x22: scrprintf(&scr," Clear Stack"); scrprintf(&scr,"Pops everything" ); break; case 0x23: scrprintf(&scr," Swap top of stack"); scrprintf(&scr,"Pops: top two elements" ); scrprintf(&scr,"Pushs: top two elements in opposite order" ); break; case 0x24: scrprintf(&scr," Depth of Stack"); scrprintf(&scr,"Pushes: %d", exc->top ); break; case 0x25: case 0x26: val1 = exc->stack[exc->top-1]; scrprintf(&scr,operator==0x25?" Copy Indexed element to TOS":" Move Indexed element to TOS"); scrprintf(&scr,"Pops: %d", val1 ); if ( val1top ) { val2 = exc->stack[exc->top-1-val1]; scrprintf(&scr,"Pushes: %.2f (%d)", val2/64.0, val2 ); if ( operator==0x26 ) scrprintf(&scr,"(and removes it from further down the stack)" ); } else scrprintf(&scr,"*** Stack underflow ***" ); break; case 0x27: scrprintf(&scr," Align Points"); val2 = exc->stack[exc->top-1]; val1 = exc->stack[exc->top-2]; scrprintf(&scr,"Pop1: %d (point (%.2f,%.2f))", val1, exc->zp1.cur[val1].x/64.0,exc->zp1.cur[val1].y/64.0 ); scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); scrprintf(&scr,"Pop2: %d (point (%.2f,%.2f))", val2, exc->zp0.cur[val2].x/64.0,exc->zp0.cur[val2].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrfree(&scr,exc); scrproj(&scr,exc); break; case 0x28: scrprintf(&scr," Untouch Point"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pop1: %d (point (%.2f,%.2f))", val1, exc->zp0.cur[val1].x/64.0,exc->zp0.cur[val1].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrfree(&scr,exc); break; case 0x2A: case 0x2B: case 0x2C: switch ( operator ) { case 0x2A: scrprintf(&scr," Loop Call Function"); break; case 0x2B: scrprintf(&scr," Call Function"); break; case 0x2C: scrprintf(&scr," Function Definition"); break; } val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (function number)", val1 ); if ( operator==0x2a ) { val2 = exc->stack[exc->top-2]; scrprintf(&scr,"Pops: %d (count)", val2 ); } break; case 0x2E: case 0x2F: scrprintf(&scr, operator==0x2E?" MDAP (touch point)":" MDAP (round & touch point)"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (point (%.2f,%.2f))", val1, exc->zp0.cur[val1].x/64.0,exc->zp0.cur[val1].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrprintf(&scr,"Sets: rp0,rp1 to %d", val1 ); if ( operator==0x2F ) scrrounding(&scr,exc); scrfree(&scr,exc); scrproj(&scr,exc); break; case 0x30: case 0x31: switch ( operator ) { case 0x30: scrprintf(&scr," Interpolate Untouched Points in y"); break; case 0x31: scrprintf(&scr," Interpolate Untouched Points in x"); break; } scrprintf(&scr," (in zone from zp2: %s)", exc->GS.gep2?"Normal":"Twilight" ); break; case 0x32: case 0x33: scrprintf(&scr," Shift point by amount ref point shifted"); if ( operator==0x33 ) { scrprintf(&scr, "Reference point in rp1: %d (point (%.2f,%.2f))", exc->GS.rp2, exc->zp0.cur[exc->GS.rp1].x/64.0,exc->zp0.cur[exc->GS.rp1].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); } else { scrprintf(&scr, "Reference point in rp2: %d (point (%.2f,%.2f))", exc->GS.rp2, exc->zp1.cur[exc->GS.rp2].x/64.0,exc->zp1.cur[exc->GS.rp2].y/64.0 ); scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); } scrprintf(&scr, "loop: %ld", exc->GS.loop ); for ( val1=1; val1<=exc->GS.loop && val1top; ++val1 ) { val2 = exc->stack[exc->top-val1]; scrprintf(&scr,"Pop%d: %d (point (%.2f,%.2f))", val1, val2, exc->zp2.cur[val2].x/64.0,exc->zp2.cur[val2].y/64.0 ); } scrprintf(&scr," (in zone from zp2: %s)", exc->GS.gep2?"Normal":"Twilight" ); scrfree(&scr,exc); scrproj(&scr,exc); break; case 0x34: case 0x35: scrprintf(&scr," Shift contour by amount ref point shifted"); if ( operator==0x35 ) { scrprintf(&scr, "Reference point in rp1: %d (point (%.2f,%.2f))", exc->GS.rp2, exc->zp0.cur[exc->GS.rp1].x/64.0,exc->zp0.cur[exc->GS.rp1].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); } else { scrprintf(&scr, "Reference point in rp2: %d (point (%.2f,%.2f))", exc->GS.rp2, exc->zp1.cur[exc->GS.rp2].x/64.0,exc->zp1.cur[exc->GS.rp2].y/64.0 ); scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); } scrprintf(&scr, "Pops: %d (contour index)", exc->stack[exc->top-1]); scrprintf(&scr," (in zone from zp2: %s)", exc->GS.gep2?"Normal":"Twilight" ); scrfree(&scr,exc); scrproj(&scr,exc); break; case 0x36: case 0x37: scrprintf(&scr," Shift zone by amount ref point shifted"); if ( operator==0x37 ) { scrprintf(&scr, "Reference point in rp1: %d (point (%.2f,%.2f))", exc->GS.rp2, exc->zp0.cur[exc->GS.rp1].x/64.0,exc->zp0.cur[exc->GS.rp1].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); } else { scrprintf(&scr, "Reference point in rp2: %d (point (%.2f,%.2f))", exc->GS.rp2, exc->zp1.cur[exc->GS.rp2].x/64.0,exc->zp1.cur[exc->GS.rp2].y/64.0 ); scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); } scrprintf(&scr, "Pops: %d (%s zone)", exc->stack[exc->top-1], exc->stack[exc->top-1]?"Normal":"Twilight" ); scrfree(&scr,exc); scrproj(&scr,exc); break; case 0x38: scrprintf(&scr," Shift point by pixel amount"); val1 = exc->stack[exc->top-1]; scrprintf(&scr, "Pops: %.2f (pixel amount)", val1/64.0 ); scrprintf(&scr, "loop: %ld", exc->GS.loop ); for ( val1=2; val1<=exc->GS.loop+1 && val1top; ++val1 ) { val2 = exc->stack[exc->top-val1]; scrprintf(&scr,"Pop%d: %d (point (%.2f,%.2f))", val1, val2, exc->zp2.cur[val2].x/64.0,exc->zp2.cur[val2].y/64.0 ); } scrprintf(&scr," (in zone from zp2: %s)", exc->GS.gep2?"Normal":"Twilight" ); scrfree(&scr,exc); scrproj(&scr,exc); break; case 0x39: scrprintf(&scr," Interpolated Point"); scrprintf(&scr, "Reference point in rp1: %d (point (%.2f,%.2f))", exc->GS.rp1, exc->zp0.cur[exc->GS.rp1].x/64.0,exc->zp0.cur[exc->GS.rp1].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrprintf(&scr, "Reference point in rp2: %d (point (%.2f,%.2f))", exc->GS.rp2, exc->zp1.cur[exc->GS.rp2].x/64.0,exc->zp1.cur[exc->GS.rp2].y/64.0 ); scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); scrprintf(&scr, "loop: %ld", exc->GS.loop ); for ( val1=1; val1<=exc->GS.loop && val1top; ++val1 ) { val2 = exc->stack[exc->top-val1]; scrprintf(&scr,"Pop%d: %d (point (%.2f,%.2f))", val1, val2, exc->zp2.cur[val2].x/64.0,exc->zp2.cur[val2].y/64.0 ); } scrprintf(&scr," (in zone from zp2: %s)", exc->GS.gep2?"Normal":"Twilight" ); scrfree(&scr,exc); scrproj(&scr,exc); break; case 0x3A: case 0x3B: scrprintf(&scr," MIAP Move Stack Indirect Relative Point"); scrprintf(&scr,operator&1?" set rp0 to point": " don't set rp0"); scrprintf(&scr,"moves point along freedom vector"); scrprintf(&scr," until distance from rp0 along"); scrprintf(&scr," projection vector is value from stack"); val2 = exc->stack[exc->top-1]; val1 = exc->stack[exc->top-2]; scrprintf(&scr,"Pop: %d (point (%.2f,%.2f))", val1, exc->zp1.cur[val1].x/64.0,exc->zp1.cur[val1].y/64.0 ); scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); scrprintf(&scr, "Reference point in rp0: %d (point (%.2f,%.2f))", exc->GS.rp0, exc->zp0.cur[exc->GS.rp0].x/64.0,exc->zp0.cur[exc->GS.rp0].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrprintf(&scr,"Pop: %.2f (distance)", val2/64.0 ); scrfree(&scr,exc); scrproj(&scr,exc); break; case 0x3C: scrprintf(&scr," Align to Reference Point"); scrprintf(&scr, "Reference point in rp0: %d (point (%.2f,%.2f))", exc->GS.rp0, exc->zp0.cur[exc->GS.rp0].x/64.0,exc->zp0.cur[exc->GS.rp0].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrprintf(&scr, "loop: %ld", exc->GS.loop ); for ( val1=1; val1<=exc->GS.loop && val1top; ++val1 ) { val2 = exc->stack[exc->top-val1]; scrprintf(&scr,"Pop%d: %d (point (%.2f,%.2f))", val1, val2, exc->zp1.cur[val2].x/64.0,exc->zp1.cur[val2].y/64.0 ); } scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); scrfree(&scr,exc); scrproj(&scr,exc); break; case 0x3E: case 0x3F: scrprintf(&scr," MIAP Move Indirect Absolute Point"); scrprintf(&scr,operator&1?" round distance and look at cvt cutin": " don't round distance and look at cvt cutin"); scrprintf(&scr,"moves point to cvt value along freedom vector"); val2 = exc->stack[exc->top-1]; val1 = exc->stack[exc->top-2]; scrprintf(&scr,"Pop: %d (point (%.2f,%.2f))", val1, exc->zp0.cur[val1].x/64.0,exc->zp0.cur[val1].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrprintf(&scr,"Pop: %d (cvt %.2f)", val2, exc->cvt[val2]/64.0 ); scrprintf(&scr,"Sets: rp0 and rp1 to point %d", val1 ); scrfree(&scr,exc); scrproj(&scr,exc); scrprintf(&scr, "CvtCutin: %.2f", exc->GS.control_value_cutin/64.0 ); break; case 0x40: scrprintf(&scr," Push %d Bytes", ((uint8 *) exc->code)[exc->IP+1]); break; case 0x41: scrprintf(&scr," Push %d Words", ((uint8 *) exc->code)[exc->IP+1]); break; case 0x42: scrprintf(&scr," Write Store" ); val2 = exc->stack[exc->top-1]; val1 = exc->stack[exc->top-2]; scrprintf(&scr,"Pops: %d (%.2f)", val2, val2/64.0 ); scrprintf(&scr,"Pops: %d (store index)", val1 ); break; case 0x43: scrprintf(&scr," Read Store" ); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pop: %d (store index)", val1 ); scrprintf(&scr,"Pushes: %d (%.2f)", exc->storage[val1], exc->storage[val1]/64.0 ); break; case 0x44: scrprintf(&scr," Write CVT entry in Pixels" ); val2 = exc->stack[exc->top-1]; val1 = exc->stack[exc->top-2]; scrprintf(&scr,"Pops: %.2f", val2/64.0 ); scrprintf(&scr,"Pops: %d (cvt index)", val1 ); break; case 0x45: scrprintf(&scr,"Read Control Value Table entry" ); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pop: %d (cvt index)", val1 ); scrprintf(&scr,"Pushes: %.2f (%d)", exc->cvt[val1]/64.0, exc->cvt[val1] ); break; case 0x46: case 0x47: scrprintf(&scr,"Get %s point coord projected on projection vector", operator==0x46 ? "current" : "original" ); val1 = exc->stack[exc->top-1]; if ( operator==0x46 ) { scrprintf(&scr,"Pop: %d (cur point (%.2f,%.2f))", val1, exc->zp2.cur[val1].x/64.0,exc->zp2.cur[val1].y/64.0 ); scrprintf(&scr," (in zone from zp2: %s)", exc->GS.gep2?"Normal":"Twilight" ); scrprintf(&scr, "projVec: %g,%g", (((int)exc->GS.projVector.x<<16)>>(16+14)) + ((exc->GS.projVector.x&0x3fff)/16384.0), (((int)exc->GS.projVector.y<<16)>>(16+14)) + ((exc->GS.projVector.y&0x3fff)/16384.0) ); } else { scrprintf(&scr,"Pop: %d (orig point (%.2f,%.2f))", val1, exc->zp2.org[val1].x/64.0,exc->zp2.org[val1].y/64.0 ); scrprintf(&scr," (in zone from zp2: %s)", exc->GS.gep2?"Normal":"Twilight" ); scrprintf(&scr,"dualVec: %g,%g", (((int)exc->GS.dualVector.x<<16)>>(16+14)) + ((exc->GS.dualVector.x&0x3fff)/16384.0), (((int)exc->GS.dualVector.y<<16)>>(16+14)) + ((exc->GS.dualVector.y&0x3fff)/16384.0) ); } scrprintf(&scr,"Pushes: projection" ); break; case 0x48: scrprintf(&scr," Sets coordinate from stack using proj & free vectors" ); val2 = exc->stack[exc->top-1]; val1 = exc->stack[exc->top-2]; scrprintf(&scr,"Moves point along freedom vector until its" ); scrprintf(&scr," projection on the projection vector is the" ); scrprintf(&scr," desired amount" ); scrprintf(&scr,"Pop: %d (cur point (%.2f,%.2f))", val1, exc->zp2.cur[val1].x/64.0,exc->zp2.cur[val1].y/64.0 ); scrprintf(&scr," (in zone from zp2: %s)", exc->GS.gep2?"Normal":"Twilight" ); scrfree(&scr,exc); scrproj(&scr,exc); break; case 0x49: case 0x4A: switch ( operator ) { case 0x49: scrprintf(&scr," Measure Distance (current)"); break; case 0x4A: scrprintf(&scr," Measure Distance (original)"); break; } val1 = exc->stack[exc->top-1]; val2 = exc->stack[exc->top-2]; if ( operator==0x4a ) { scrprintf(&scr,"Pop: %d (cur point (%.2f,%.2f))", val1, exc->zp0.cur[val1].x/64.0,exc->zp0.cur[val1].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrprintf(&scr,"Pop: %d (cur point (%.2f,%.2f))", val2, exc->zp1.cur[val2].x/64.0,exc->zp1.cur[val2].y/64.0 ); scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); scrprintf(&scr, "projVec: %g,%g", (((int)exc->GS.projVector.x<<16)>>(16+14)) + ((exc->GS.projVector.x&0x3fff)/16384.0), (((int)exc->GS.projVector.y<<16)>>(16+14)) + ((exc->GS.projVector.y&0x3fff)/16384.0) ); } else { scrprintf(&scr,"Pop: %d (orig point (%.2f,%.2f))", val1, exc->zp0.org[val1].x/64.0,exc->zp0.org[val1].y/64.0 ); scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrprintf(&scr,"Pop: %d (orig point (%.2f,%.2f))", val2, exc->zp1.org[val2].x/64.0,exc->zp1.org[val2].y/64.0 ); scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); scrprintf(&scr, "dualVec: %g,%g", (((int)exc->GS.dualVector.x<<16)>>(16+14)) + ((exc->GS.dualVector.x&0x3fff)/16384.0), (((int)exc->GS.dualVector.y<<16)>>(16+14)) + ((exc->GS.dualVector.y&0x3fff)/16384.0) ); } scrprintf(&scr,"Pushes: distance" ); break; case 0x4B: scrprintf(&scr," MPPEM Push Pixels Per Em"); scrprintf(&scr,"Pushes: %d", PPEMY(exc)); /* Actually this depends on the projection vector. But if xppem==yppem it will make no difference */ break; case 0x4C: scrprintf(&scr," Push Pointsize"); scrprintf(&scr,"(one might assume this returns the pointsize, %d", cv->ft_pointsizey); scrprintf(&scr," as it is documented to do, but instead it"); scrprintf(&scr," returns ppem)"); scrprintf(&scr,"Pushes: %d", PPEMY(exc) ); break; case 0x4D: case 0x4E: switch ( operator ) { case 0x4D: scrprintf(&scr," set auto Flip On"); break; case 0x4E: scrprintf(&scr," set auto Flip Off"); break; } break; case 0x4F: val1 = exc->stack[exc->top-1]; scrprintf(&scr," Debug"); scrprintf(&scr,"Pops: %d (debug hook)", val1 ); break; case 0x58: val1 = exc->stack[exc->top-1]; scrprintf(&scr," If"); scrprintf(&scr,"Pops: %d (condition)", val1 ); break; case 0x5e: scrprintf(&scr," Set Delta Base"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (new delta base)", val1 ); break; case 0x5f: scrprintf(&scr," Set Delta Shift"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (new delta shift)", val1 ); break; case 0x8B: case 0x8C: case 0x60: case 0x61: case 0x62: case 0x63: case 0x5A: case 0x5B: case 0x55: case 0x54: case 0x53: case 0x52: case 0x51: case 0x50: val2 = exc->stack[exc->top-1]; val1 = exc->stack[exc->top-2]; switch( operator ) { case 0x50: scrprintf(&scr," Less Than"); ret = val1val2; break; case 0x53: scrprintf(&scr," Greater Than or Equal"); ret = val1>=val2; break; case 0x54: scrprintf(&scr," Equal"); ret = val1==val2; break; case 0x55: scrprintf(&scr," Not Equal"); ret = val1!=val2; break; case 0x5A: scrprintf(&scr," And"); ret = val1 & val2; break; case 0x5B: scrprintf(&scr," Or"); ret = val1 | val2; break; case 0x60: scrprintf(&scr," Add"); ret = val1 + val2; break; case 0x61: scrprintf(&scr," Sub"); ret = val1 - val2; break; case 0x62: scrprintf(&scr," Divide"); if ( val2!=0 ) ret = val1*64/val2; else ret = 0x7fffffff; break; case 0x63: scrprintf(&scr," Multiply"); ret = val1*val2/64.0; break; case 0x8B: scrprintf(&scr," Max"); ret = val1>val2 ? val1 : val2; break; case 0x8C: scrprintf(&scr," Min"); ret = val1stack[exc->top-1]; switch( operator ) { case 0x64: scrprintf(&scr," Absolute Value"); if ( val2<0 ) val2 = -val2; break; case 0x65: scrprintf(&scr," Negate"); val2 = -val1; break; case 0x66: scrprintf(&scr," Floor"); val2 = 64*(val2/64); break; case 0x67: scrprintf(&scr," Ceiling"); val2 = 64*((val2+63)/64); break; case 0x5C: scrprintf(&scr," Not"); val2 = !val1; break; case 0x56: scrprintf(&scr," Odd (after rounding)"); ret = ttround(val1,exc); if ( ret&64 ) ret = 0; else ret = 1; break; case 0x57: scrprintf(&scr," Even (after rounding)"); ret = ttround(val1,exc); if ( ret&64 ) ret = 0; else ret = 1; break; } scrprintf(&scr,"Pops: %.2f (%d)", val1/64.0, val1 ); scrprintf(&scr,"Pushes: %.2f (%d)", val2/64.0, val2 ); break; case 0x68: case 0x69: case 0x6A: case 0x6B: scrprintf(&scr," Round & adjust for engine characteristics" ); scrprintf(&scr,(operator&3)==0?" Grey":(operator&3)==1?" Black":(operator&3)==2?" White":" Undefined Rounding"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %.2f", val1/64.0 ); val1 = ttround(val1,exc); scrprintf(&scr,"Pushes: %.2f", val1/64.0 ); break; case 0x6C: case 0x6D: case 0x6E: case 0x6F: scrprintf(&scr," Adjust for engine characteristics without rounding" ); scrprintf(&scr,(operator&3)==0?" Grey":(operator&3)==1?" Black":(operator&3)==2?" White":" Undefined Rounding"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %.2f", val1/64.0 ); scrprintf(&scr,"Pushes: %.2f", val1/64.0 ); break; case 0x5D: case 0x71: case 0x72: base = operator==0x5D?1:operator-0x6F; scrprintf(&scr," Delta Point%d", base ); freedom.x = (((int)exc->GS.freeVector.x<<16)>>(16+14)) + ((exc->GS.freeVector.x&0x3fff)/16384.0); freedom.y = (((int)exc->GS.freeVector.y<<16)>>(16+14)) + ((exc->GS.freeVector.y&0x3fff)/16384.0); cnt = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (count)", cnt ); for ( i=0; i exc->top ) { scrprintf(&scr,"*** Stack underflow ***"); break; } val1 = exc->stack[exc->top-2-2*i]; val2 = exc->stack[exc->top-3-2*i]; if ( (val2&0xf)<=7 ) off = -8+(val2&0xf); else off = -7+(val2&0xf); off *= 64 / (1L << exc->GS.delta_shift); scrprintf(&scr,"Pops: %d (point (%.2f,%.2f))", val1, exc->zp0.cur[val1].x/64.0,exc->zp0.cur[val1].y/64.0 ); scrprintf(&scr,"Pops: %d => at %d ppem, move (%.2f,%.2f)", val2, exc->GS.delta_base+(base-1)*16+((val2>>4)&0xf), freedom.x*off/64.0, freedom.y*off/64.0 ); } scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); scrprintf(&scr, "DeltaBase: %d", exc->GS.delta_base ); scrprintf(&scr, "DeltaShift: %d", exc->GS.delta_shift ); scrprintf(&scr, "freeVec: %g,%g", freedom.x, freedom.y); break; case 0x70: scrprintf(&scr," Write CVT entry in Funits" ); val2 = exc->stack[exc->top-1]; val1 = exc->stack[exc->top-2]; scrprintf(&scr,"Pops: %d (em-units=%.2fpixels)", val2, val2*PPEMX(exc)*64.0/ (cv->b.sc->parent->ascent+cv->b.sc->parent->descent)); scrprintf(&scr,"Pops: %d (cvt index)", val1 ); break; case 0x73: case 0x74: case 0x75: base = operator-0x72; scrprintf(&scr," Delta Point%d", base ); cnt = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (count)", cnt ); for ( i=0; i exc->top ) { scrprintf(&scr,"*** Stack underflow ***"); break; } val1 = exc->stack[exc->top-2-2*i]; val2 = exc->stack[exc->top-3-2*i]; if ( (val2&0xf)<=7 ) off = -8+(val2&0xf); else off = -7+(val2&0xf); off *= 64 / (1L << exc->GS.delta_shift); scrprintf(&scr,"Pops: %d (cvt index (%d,%.2f))", val1, exc->cvt[val1],exc->cvt[val1]/64.0 ); scrprintf(&scr,"Pops: %d => at %d ppem, change by %.2f", val2, exc->GS.delta_base+(base-1)*16+((val2>>4)&0xf), off/64.0 ); } scrprintf(&scr, "DeltaBase: %d", exc->GS.delta_base ); scrprintf(&scr, "DeltaShift: %d", exc->GS.delta_shift ); break; case 0x78: case 0x79: scrprintf(&scr,operator==0x78?" Jump Relative (to here) on True":" Jump Relative (to here) on False"); val1 = exc->stack[exc->top-1]; val2 = exc->stack[exc->top-2]; scrprintf(&scr,"Pops: %d (condition)", val1 ); scrprintf(&scr,"Pops: %d (byte offset)", val2 ); break; case 0x18: case 0x19: case 0x3D: case 0x76: case 0x77: case 0x7a: case 0x7c: case 0x7d: scrprintf(&scr, operator==0x7a?" set Rounding down to grid": operator==0x7c?" set Rounding up to grid": operator==0x77?" set Rounding to Super 45": operator==0x7d?" set Rounding Off": operator==0x18?" set Rounding to grid": operator==0x3D?" set Rounding to double grid": operator==0x19?" set Rounding to half grid": " set Rounding to Super"); scrprintf(&scr,"Sets: Rounding state"); break; case 0x7e: scrprintf(&scr," Set Angle Weight (obsolete)"); scrprintf(&scr,"Pops: an ignored value"); break; case 0x7f: scrprintf(&scr," Adjust Angle"); scrprintf(&scr,"Pops: %d (point)", exc->stack[exc->top-1]); break; case 0x80: scrprintf(&scr," Flip Points"); scrprintf(&scr, "loop: %ld", exc->GS.loop ); for ( val1=1; val1<=exc->GS.loop && val1top; ++val1 ) { val2 = exc->stack[exc->top-val1]; scrprintf(&scr,"Pop%d: %d (point (%.2f,%.2f))", val1, val2, exc->zp0.cur[val2].x/64.0,exc->zp0.cur[val2].y/64.0 ); scrprintf(&scr," was %s-curve, becomes %s-curve", exc->pts.tags[val2] & FT_CURVE_TAG_ON ? "on" : "off", exc->pts.tags[val2] & FT_CURVE_TAG_ON ? "off" : "on" ); } scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); break; case 0x81: case 0x82: val2 = exc->stack[exc->top-1]; val1 = exc->stack[exc->top-2]; scrprintf(&scr,operator==0x81?" Flip point range On":" Flip point range Off"); for ( i=val2; i<=val2; ++i ) { scrprintf(&scr," change point %d (%.2f,%.2f)", i, exc->zp0.cur[i].x/64.0,exc->zp0.cur[i].y/64.0 ); scrprintf(&scr," was %s-curve, becomes %s-curve", exc->pts.tags[val2] & FT_CURVE_TAG_ON ? "on" : "off", operator==0x82 ? "off" : "on" ); } scrprintf(&scr," (in zone from zp0: %s)", exc->GS.gep0?"Normal":"Twilight" ); break; case 0x85: scrprintf(&scr," SCANCTRL Set dropout control" ); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (flags)",val1 ); if ( val1==0 ) scrprintf(&scr,"Turn off dropout control"); else { if ( val1&0x100 ) { if ( (val1&&0xff)==0xff ) scrprintf(&scr,"set dropout control for all ppem"); else scrprintf(&scr,"set dropout control for ppem <= %d", (val1&0xff)); } if ( val1&0x800 ) { if ( (val1&&0xff)==0xff ) scrprintf(&scr,""); else scrprintf(&scr,"unset dropout control unless ppem <= %d", (val1&0xff)); } if ( val1&0x200 ) scrprintf(&scr,"set dropout control if glyph rotated"); if ( val1&0x1000 ) scrprintf(&scr,"unset dropout control unless glyph rotated"); if ( val1&0x400 ) scrprintf(&scr,"set dropout control if glyph stretched"); if ( val1&0x2000 ) scrprintf(&scr,"unset dropout control unless glyph stretched"); } break; case 0x06: case 0x07: case 0x08: case 0x09: case 0x86: case 0x87: scrprintf(&scr,operator<0x8?" Sets projection vector from line": operator<0x86?" Sets freedom vector from line": " Set dual projection vector from line"); scrprintf(&scr,(operator&1)?"orthogonal to line":"parallel to line"); val1 = exc->stack[exc->top-2]; val2 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (point (%.2f,%.2f))", val1, exc->zp1.cur[val1].x/64.0,exc->zp1.cur[val1].y/64.0 ); scrprintf(&scr," (in zone from zp1: %s)", exc->GS.gep1?"Normal":"Twilight" ); scrprintf(&scr,"Pops: %d (point (%.2f,%.2f))", val2, exc->zp2.cur[val2].x/64.0,exc->zp2.cur[val2].y/64.0 ); scrprintf(&scr," (in zone from zp2: %s)", exc->GS.gep2?"Normal":"Twilight" ); if ( operator>=0x86 ) { scrprintf(&scr,"Sets: Project vector based on current positions" ); scrprintf(&scr,"Sets: Dual proj vector based on original positions" ); } else scrprintf(&scr,"Sets: %s vector", operator<8?"Projection":"Freedom" ); break; case 0x88: val1 = exc->stack[exc->top-1]; scrprintf(&scr," Get Information"); scrprintf(&scr, "Pops: %d %s%s%s%s%s%s%s%s%s%s", val1, val1&(1<<0) ? "version (result in bits 0-7) " : "", val1&(1<<1) ? "rotated (result in bit 8)" : "", val1&(1<<2) ? "stretched (result in bit 9)" : "", val1&(1<<3) ? "Undocumented Apple ?variations? (result in bit 10)" : "", val1&(1<<4) ? "Undocumented Apple ?vertical metrics? (result in bit 11)" : "", val1&(1<<5) ? "greyscale (result in bit 12)" : "", val1&(1<<6) ? "ClearType (result in bit 13)" : "", val1&(1<<7) ? "CT widths compat (result in bit 14)" : "", val1&(1<<8) ? "CT symetrical smoothing (result in bit 15)" : "", val1&(1<<9) ? "CT processes in BGR(1) or RGB(0) (result in bit 16)" : ""); if ( val1&1 ) { scrprintf(&scr, " Versions: 1 => Mac OS 6" ); scrprintf(&scr, " 2 => Mac OS 7" ); scrprintf(&scr, " 3 => Win 3.1" ); scrprintf(&scr, " 33=> Win rasterizer 1.5" ); scrprintf(&scr, " 34=> Win rasterizer 1.6" ); scrprintf(&scr, " 35=> Win rasterizer 1.7" ); scrprintf(&scr, " 37=> Win rasterizer 1.8" ); scrprintf(&scr, " 38=> Win rasterizer 1.9" ); } scrprintf(&scr,"Pushes: result"); scrprintf(&scr,"FreeType returns: %s%s%s%s", (val1&1) ? "(Win 1.7) | ": "", (val1&2) ? exc->tt_metrics.rotated ? "(rotated) | ": "(not rotated) | " : "", (val1&4) ? exc->tt_metrics.stretched ? "(stretched) | ": "(not stretched) | " : "", #if FREETYPE_MAJOR>2 || (FREETYPE_MAJOR==2 && (FREETYPE_MINOR>1 || (FREETYPE_MINOR==1 && FREETYPE_PATCH>11 ))) (val1&32) ? exc->grayscale ? "(grey scale)": "(black/white)" : "" #else "" #endif ); break; case 0x89: scrprintf(&scr," Instruction Definition"); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (opcode)", val1 ); break; case 0x8a: scrprintf(&scr," Roll top three stack elements"); break; case 0x8D: scrprintf(&scr," SCANTYPE Set dropout control" ); val1 = exc->stack[exc->top-1]; scrprintf(&scr,"Pops: %d (mode)",val1 ); if ( val1==0 ) scrprintf(&scr,"simple dropout control scan conversion including stubs (rules 1,2,3)"); else if ( val1==1 ) scrprintf(&scr,"simple dropout control scan conversion excluding stubs (rules 1,2,4)"); else if ( val1==2 || val1==3 || val1==6 || val1==7 ) scrprintf(&scr,"fast scan conversion; dropout control turned off (rule 1,2)"); else if ( val1==4 ) scrprintf(&scr,"smart dropout control scan conversion including stubs (rule 1,2,5)"); else if ( val1==5 ) scrprintf(&scr,"smart dropout control scan conversion excluding stubs (rule 1,2,6)"); else scrprintf(&scr,"*** Unknown mode ***"); break; case 0x8E: val2 = exc->stack[exc->top-1]; val1 = exc->stack[exc->top-2]; scrprintf(&scr," Instruction Control"); scrprintf(&scr,"Pops: %d (selector)", val1 ); scrprintf(&scr,"Pops: %d (value)", val1 ); if ( val1==1 ) scrprintf(&scr, " => grid fitting %s", val2 ? "inhibited" : "normal" ); else if ( val1==2 ) scrprintf(&scr, " => cvt parameters %s", val2 ? "ignored" : "normal" ); else scrprintf(&scr, "Unknown selector"); break; } return( scr.lines ); } static void dvgloss_scroll(DebugView *dv,struct sbevent *sb) { int newpos = dv->cvt_offtop; GRect size; int min, max, page; extern int _GScrollBar_Width; GScrollBarGetBounds(dv->glosssb,&min,&max,&page); GDrawGetSize(dv->gloss,&size); switch( sb->type ) { case et_sb_top: newpos = 0; break; case et_sb_uppage: newpos -= size.height/dv->ii.fh; break; case et_sb_up: --newpos; break; case et_sb_down: ++newpos; break; case et_sb_downpage: newpos += size.height/dv->ii.fh; break; case et_sb_bottom: newpos = max-size.height/dv->ii.fh; break; case et_sb_thumb: case et_sb_thumbrelease: newpos = sb->pos; break; } if ( newpos>max-size.height/dv->ii.fh ) newpos = max-size.height/dv->ii.fh; if ( newpos<0 ) newpos =0; if ( newpos!=dv->gloss_offtop ) { int diff = newpos-dv->gloss_offtop; dv->gloss_offtop = newpos; GScrollBarSetPos(dv->glosssb,dv->gloss_offtop); size.x = size.y = 0; size.width -= GDrawPointsToPixels(dv->gloss,_GScrollBar_Width); GDrawScroll(dv->gloss,&size,0,diff*dv->ii.fh); } } static void DVGlossExposeSize(GWindow gw,DebugView *dv,GEvent *event) { int len = DVGlossExpose(gw,dv,event); GRect size; int min, max, page, offtop; GScrollBarGetBounds(dv->glosssb,&min,&max,&page); GGadgetGetSize(dv->glosssb,&size); size.height /= dv->ii.fh; if ( len!=max || page!=size.height ) { GScrollBarSetBounds(dv->glosssb,0,len,size.height); offtop = dv->gloss_offtop; if ( offtop+size.height > len ) offtop = len-size.height; if ( offtop < 0 ) offtop = 0; if ( offtop!=dv->gloss_offtop ) { dv->gloss_offtop = offtop; GScrollBarSetPos(dv->glosssb,dv->gloss_offtop); DVGlossExpose(gw,dv,event); } } } static int dvgloss_e_h(GWindow gw, GEvent *event) { DebugView *dv = (DebugView *) GDrawGetUserData(gw); GRect r,g; extern int debug_wins; if ( dv==NULL ) return( true ); switch ( event->type ) { case et_expose: DVGlossExposeSize(gw,dv,event); break; case et_char: return( DVChar(dv,event)); break; case et_controlevent: switch ( event->u.control.subtype ) { case et_scrollbarchange: dvgloss_scroll(dv,&event->u.control.u.sb); break; } break; case et_resize: GDrawGetSize(gw,&r); GGadgetGetSize(dv->glosssb,&g); GGadgetMove(dv->glosssb,r.width-g.width,0); GGadgetResize(dv->glosssb,g.width,r.height); GDrawRequestExpose(dv->gloss,NULL,false); break; case et_close: GDrawDestroyWindow(dv->gloss); debug_wins &= ~dw_gloss; break; case et_destroy: dv->gloss = NULL; break; case et_mouseup: case et_mousedown: case et_mousemove: GGadgetEndPopup(); break; } return( true ); } void DVCreateGloss(DebugView *dv) { GWindowAttrs wattrs; GRect pos; GGadgetData gd; extern int _GScrollBar_Width; memset(&wattrs,0,sizeof(wattrs)); wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle; wattrs.event_masks = -1; wattrs.cursor = ct_mypointer; wattrs.utf8_window_title = _("Instruction Gloss (TrueType)"); pos.width = GGadgetScale(GDrawPointsToPixels(NULL,230)); pos.height = 169; pos.x = CVXPos(dv,143,pos.width); pos.y = 302; dv->gloss = GDrawCreateTopWindow(NULL,&pos,dvgloss_e_h,dv,&wattrs); memset(&gd,0,sizeof(gd)); gd.pos.y = 0; gd.pos.height = pos.height; gd.pos.width = GDrawPointsToPixels(dv->gloss,_GScrollBar_Width); gd.pos.x = pos.width-gd.pos.width; gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert; dv->glosssb = GScrollBarCreate(dv->gloss,&gd,dv); GDrawSetVisible(dv->gloss,true); } /* ************************************************************************** */ /* Variant of the gloss window: Mark the points to show what the next */ /* instruction will do to them. (Change (usually move) them, or use them */ /* or ignore them */ /* ************************************************************************** */ static SplinePoint *FindPoint(SplineSet *ss,int ptnum) { SplineSet *spl; SplinePoint *sp; for ( spl=ss; spl!=NULL ; spl=spl->next ) { for ( sp = spl->first; ; ) { if ( sp->ttfindex==ptnum || sp->nextcpindex==ptnum ) return( sp ); if ( sp->next==NULL ) break; sp = sp->next->to; if ( sp==spl->first ) break; } } return( NULL ); } static void SetBasisPoint(SplineSet *ss, int ptnum) { SplinePoint *sp = FindPoint(ss,ptnum); if ( sp==NULL ) return; /* A roundx point or flexx nextcp means this is the reference */ /* point, etc. */ if ( sp->ttfindex==ptnum ) sp->roundx = true; else sp->flexx = true; } static void SetChangingPoint(SplineSet *ss, int ptnum) { SplinePoint *sp = FindPoint(ss,ptnum); if ( sp==NULL ) return; /* I reuse these flags. A "selected" point is one which will be */ /* moved by the instruction. A "flexy"ed point means its nextcp */ /* will be moved by the next instruction */ if ( sp->ttfindex==ptnum ) sp->selected = true; else sp->flexy = true; } void DVMarkPts(DebugView *dv,SplineSet *ss) { TT_ExecContext exc = DebuggerGetEContext(dv->dc); long changing_point, basis_point; int i,cnt,top; int operator; SplineSet *spl; SplinePoint *sp; for ( spl=ss; spl!=NULL ; spl=spl->next ) { for ( sp = spl->first; ; ) { sp->selected = false; sp->roundx = sp->roundy = false; sp->flexx = sp->flexy = false; /* I reuse these flags. A "selected" point is one which will be */ /* moved by the instruction. A "flexy"ed point means its nextcp */ /* will be moved by the next instruction */ /* A roundx point or flexx nextcp means this is the reference */ /* point, etc. */ if ( sp->next==NULL ) break; sp = sp->next->to; if ( sp==spl->first ) break; } } if ( exc==NULL ) return; /* Not running */ if ( exc->IP>=exc->codeSize || exc->code==NULL ) return; /* At end */ operator = ((uint8 *) exc->code)[exc->IP]; changing_point = -1; basis_point = -1; if ( operator>=0xc0 && operator <= 0xdf ) { /* MDRP */ if ( exc->GS.gep1 ) /* No good way to mark twilight points, so only mark normal ones */ changing_point = exc->stack[exc->top-1]; if ( exc->GS.gep0 ) basis_point = exc->GS.rp0; } else if ( operator>=0xe0 && operator <= 0xff ) { /* MIRP */ if ( exc->GS.gep1 ) /* No good way to mark twilight points, so only mark normal ones */ changing_point = exc->stack[exc->top-2]; if ( exc->GS.gep0 ) basis_point = exc->GS.rp0; } else if ( operator>=0xb0 && operator <= 0xbf ) { /* Push */ } else switch ( operator ) { case 0xf: /* Moves point to intersection of two lines */ if ( exc->GS.gep2 ) /* No good way to mark twilight points, so only mark normal ones */ changing_point = exc->stack[exc->top-5]; if ( exc->GS.gep0 ) { SetBasisPoint(ss,exc->stack[exc->top-4]); SetBasisPoint(ss,exc->stack[exc->top-3]); } if ( exc->GS.gep1 ) { SetBasisPoint(ss,exc->stack[exc->top-2]); SetBasisPoint(ss,exc->stack[exc->top-1]); } break; case 0x10: case 0x11: case 0x12: /* Set Reference Point ? */ basis_point = exc->stack[exc->top-1]; break; case 0x27: /* Align Points */ if ( exc->GS.gep0 ) SetChangingPoint(ss,exc->stack[exc->top-1]); if ( exc->GS.gep1 ) SetChangingPoint(ss,exc->stack[exc->top-2]); break; case 0x28: /* Untouch point */ if ( exc->GS.gep0 ) changing_point = exc->stack[exc->top-1]; break; case 0x2E: /* Touch point */ if ( exc->GS.gep0 ) changing_point = exc->stack[exc->top-1]; break; case 0x2F: /* Round and Touch point */ if ( exc->GS.gep0 ) changing_point = exc->stack[exc->top-1]; break; case 0x30: /* Interpolate Untouched Points in y */ if ( exc->GS.gep2 ) { TT_GlyphZoneRec *r = &exc->pts; for ( spl=ss; spl!=NULL ; spl=spl->next ) { for ( sp = spl->first; ; ) { if ( sp->ttfindexn_points && !(r->tags[sp->ttfindex]&FT_Curve_Tag_Touch_Y) ) sp->selected = true; if ( sp->nextcpindexn_points && !(r->tags[sp->nextcpindex]&FT_Curve_Tag_Touch_Y) ) sp->flexy = true; /* I reuse these flags. A "selected" point is one which will be */ /* moved by the instruction. A "flexy"ed point means its nextcp */ /* will be moved by the next instruction */ if ( sp->next==NULL ) break; sp = sp->next->to; if ( sp==spl->first ) break; } } } break; case 0x31: /* Interpolate Untouched Points in x */ if ( exc->GS.gep2 ) { TT_GlyphZoneRec *r = &exc->pts; for ( spl=ss; spl!=NULL ; spl=spl->next ) { for ( sp = spl->first; ; ) { if ( sp->ttfindexn_points && !(r->tags[sp->ttfindex]&FT_Curve_Tag_Touch_X) ) sp->selected = true; if ( sp->nextcpindexn_points && !(r->tags[sp->nextcpindex]&FT_Curve_Tag_Touch_X) ) sp->flexy = true; /* I reuse these flags. A "selected" point is one which will be */ /* moved by the instruction. A "flexy"ed point means its nextcp */ /* will be moved by the next instruction */ if ( sp->next==NULL ) break; sp = sp->next->to; if ( sp==spl->first ) break; } } } break; case 0x32: case 0x33: /* Shift point by amount ref point shifted */ if ( operator==0x33 ) { if ( exc->GS.gep0 ) basis_point = exc->GS.rp1; } else { if ( exc->GS.gep1 ) basis_point = exc->GS.rp2; } if ( exc->GS.gep2 ) for ( i=1; i<=exc->GS.loop && itop; ++i ) { SetChangingPoint(ss,exc->stack[exc->top-i]); } break; case 0x34: case 0x35: /* Shift contour by amount ref point shifted */ if ( operator==0x35 ) { if ( exc->GS.gep0 ) basis_point = exc->stack[exc->GS.rp1]; } else { if ( exc->GS.gep1 ) basis_point = exc->stack[exc->GS.rp2]; } if ( exc->GS.gep2 ) { for ( spl=ss, i=exc->stack[exc->top-1]; i>0 && spl!=NULL; --i, spl=spl->next ); if ( spl!=NULL ) { for ( sp = spl->first; ; ) { if ( sp->ttfindex<0xfff0 ) sp->selected = true; if ( sp->nextcpindex<0xfff0 ) sp->flexy = true; /* I reuse these flags. A "selected" point is one which will be */ /* moved by the instruction. A "flexy"ed point means its nextcp */ /* will be moved by the next instruction */ if ( sp->next==NULL ) break; sp = sp->next->to; if ( sp==spl->first ) break; } } } break; case 0x36: case 0x37: if ( operator==0x37 ) { if ( exc->GS.gep0 ) basis_point = exc->stack[exc->GS.rp1]; } else { if ( exc->GS.gep1 ) basis_point = exc->stack[exc->GS.rp2]; } if ( exc->stack[exc->top-1] ) { for ( spl=ss; spl!=NULL; spl=spl->next ) { for ( sp = spl->first; ; ) { if ( sp->ttfindex<0xfff0 ) sp->selected = true; if ( sp->nextcpindex<0xfff0 ) sp->flexy = true; /* I reuse these flags. A "selected" point is one which will be */ /* moved by the instruction. A "flexy"ed point means its nextcp */ /* will be moved by the next instruction */ if ( sp->next==NULL ) break; sp = sp->next->to; if ( sp==spl->first ) break; } } } break; case 0x38: /* Shift point by pixel amount */ if ( exc->GS.gep2 ) { for ( i=2; i<=exc->GS.loop+1 && itop; ++i ) SetChangingPoint(ss,exc->stack[exc->top-i]); } break; case 0x39: /* Interpolated Point */ if ( exc->GS.gep0 ) SetBasisPoint(ss,exc->GS.rp1); if ( exc->GS.gep1 ) SetBasisPoint(ss,exc->GS.rp2); if ( exc->GS.gep2 ) { for ( i=1; i<=exc->GS.loop+1 && itop; ++i ) SetChangingPoint(ss,exc->stack[exc->top-i]); } break; case 0x3A: case 0x3B: /* MIAP Move Stack Indirect Relative Point */ if ( exc->GS.gep1 ) changing_point = exc->stack[exc->top-2]; if ( exc->GS.gep0 ) basis_point = exc->GS.rp0; break; case 0x3C: /* Align to Reference Point */ if ( exc->GS.gep0 ) basis_point = exc->GS.rp0; if ( exc->GS.gep1 ) for ( i=1; i<=exc->GS.loop && itop; ++i ) { SetChangingPoint(ss,exc->stack[exc->top-i]); } break; case 0x3E: case 0x3F: /* MIAP Move Indirect Absolute Point */ if ( exc->GS.gep0 ) changing_point = exc->stack[exc->top-2]; break; case 0x46: case 0x47: /* Get current/original point coord projected on projection vector */ if ( exc->GS.gep2 ) basis_point = exc->stack[exc->top-1]; break; case 0x48: /* Sets coordinate from stack using proj & free vectors */ if ( exc->GS.gep2 ) changing_point = exc->stack[exc->top-2]; break; case 0x49: case 0x4A: /* Measure Distance */ if ( exc->GS.gep0 ) SetBasisPoint( ss, exc->stack[exc->top-1] ); if ( exc->GS.gep1 ) SetBasisPoint( ss, exc->stack[exc->top-2] ); break; case 0x5D: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: /* Delta Point */ cnt = exc->stack[exc->top-1]; for ( i=0; i exc->top ) break; if ( exc->GS.gep0 ) SetChangingPoint(ss, exc->stack[exc->top-2-2*i]); } break; case 0x80: /* Flip Points */ if ( exc->GS.gep0 ) for ( i=1; i<=exc->GS.loop && itop; ++i ) { SetChangingPoint(ss,exc->stack[exc->top-i]); } break; case 0x81: case 0x82: i = exc->stack[exc->top-1]; top = exc->stack[exc->top-2]; if ( exc->GS.gep0 ) for ( ; i<=top; ++i ) { SetChangingPoint(ss,exc->stack[exc->top-i]); } break; case 0x06: case 0x07: case 0x08: case 0x09: case 0x86: case 0x87: /* Sets vector from line */ if ( exc->GS.gep1 ) SetBasisPoint(ss,exc->stack[exc->top-2]); if ( exc->GS.gep2 ) SetBasisPoint(ss,exc->stack[exc->top-1]); break; default: /* Many instructions don't refer to points */ break; } if ( changing_point!=-1 ) SetChangingPoint(ss,changing_point); if ( basis_point!=-1 ) SetBasisPoint(ss,basis_point); } #else void DVCreateGloss(DebugView *dv) { } void DVMarkPts(DebugView *dv,SplineSet *ss) { } #endif /* Has Debugger */