%! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % PostScript $99 XY TABLE FLUTTERWUMPER TOOLKIT % ======================================================== % by Don Lancaster Revised January 13, 1997 % =================================================================== % Copyright c 1997 by Don Lancaster and Synergetics, Box 809, % Thatcher AZ, 85552. (520) 428-4073 www.tinaja.com don@tinaja.com % All commercial rights and all electronic media rights are % *fully* reserved. Linking welcome. Reposting expressly forbidden. % =================================================================== % % SUMMARY: A Flutterwumper is any hackable entity that moves and % either chomps or spits. This is a very powerful set of % preliminary PostScript tools, utilities, readers, test % files, emulators, and demos as required for preliminary % homebrew PIC flutterwumper development. % % Tutorial may be read as textfile. % Acrobat Distiller or GhostScript required for use % % See FLUTWUMP.PDF and POSTFLUT.PDF. % % Copyright c 1994, 1997 by Don Lancaster. All rights reserved. % PIC sourcecode and full consulting services available. % Free help line and additional info: (520) 428-4073. % % ============================================================================ % % Name of textfile: FLUTOOLS.PS % Source: SYNERGETICS % Author: Don Lancaster % Desc: PS $99 XY table flutterwumper toolkit % Date: September 24, 1994 July 14, 1997 % Release: 3.0 % Approx length: 43K % Status: Copyright 1994,1997 by Don Lancaster and Synergetics. % 3860 West First Street, Thatcher, AZ. (520) 428-4073. % All commercial rights and all electronic media rights % fully reserved. Personal use is permitted so long as % this status message stays present and intact. % Basic flutterwumper Infopack $75 VISA/MC. Free help % line and additional info (520) 428-4073. % % Keywords: PostScript, guru, xy, x-y, table, flutterwumper, % vector, raster, driver, utility, tool, tutorial, hack % hardware, software, interface, hack, stepper, Santa, % Claus, PIC, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % This particular utility set has been optimized to work with Acrobat % Distiller or GhostScript on Windows 95. Example data files are % written and read from the A: drive. PS printer-based utilities % using print statements instead of disk writes are equally possible. % PS $99 XY TABLE FLUTTERWUMPER TOOLKIT % ===================================== % by Don Lancster % This toolkit consists of PS-to-step methods for getting from PostScript % to the individual XY steps needed in a $99 flutterwumper, or any other % automated positioning system. % A (usually) serial and extremely low level communication format called % a FLUTFILE is created. A flutfile simply itemizes each and every individual % table step or action as one ASCII character. Thus DRAMATICALLY minimizing % the smarts needed by the flutterwumper itself. % The input to these tools can be largely UNMODIFIED PostScript, generated % by hand or by many applications package. Virtually ALL of the power of % PostScript becomes available for your flutterwumper at near zero cost! % In use, ordinary PostScript code is combined with these routines and % sent to (preferably) Acrobat Distiller or (alternately) GhostScript % running on a host. A flutfile is generated. This file can be sent % out a port to immediately control the flutterwumper or can be kept % for later reuse. Any comm program can be used for an interface. % These routines are easily extended to input or output HPGL or Gerber files. % For most uses, these fancier formats are unnecessary complications. % Several example flutfiles are provided, including a simple box, a circle, % and a typographic character. Along with tolerance plots. % A flutfile reader is included. This can be used to proof or debug % flutfiles, or else to software emulate a hardware flutterwumper project % in development. % The fundamental core problems are to convert fonts into PostScript paths, % convert paths into straight line vectors and then convert those % vectors into individual flutfile steps. % Font path conversion gets done with the -charpath- operator. Curves % in the path get converted to straight line vectors using the -setflat- % and -flattenpath- operators. Paths are enumerated for vector conversion % with the -pathforall- operator. Step conversion uses the code below. % In this version, a vector flutfile system is used, sending commands for % octant moves of north, northwest, west, southwest, south, southeast, east, % and northeast. Note that a flutterwumper that INTERLEAVES x any y stepper % phases offers DRAMATICALLY smoother results, finer resolution, and shorter % file lengths. % All motions with the exception of the !H HOME command are RELATIVE with % respect to the CURRENT flutterwumper tool position. % Code at present is for 2-1/2 D applications, where the Z axis is a % simple up-down or on-off command. These routines are easily extended % for full three axis or higher uses. % While not included here, it is EXTREMELY SIMPLE to add transformations % for non-cartesian (non-XYZ) output devices. Hooks are provided. % These results have not yet been speed optimized. But they already are % much faster than most flutterwumpers, even at lower serial baud rates. % Table lookup (details on request) can offer speed improvements. % The code also provides "very good" but not "outstanding" typography. % On coarser resolution devices, slight retouching may be required, % compared to the simple and direct use of -charpath- shown here. % In any "low res" and "small letter" situation, picking a low res % friendly friendly font (Helvetica or Stone) can help bunches. It % is also possible to "retouch" the results by using the flutfile reader. % or custom hinting code. % Faster matrix transformation methods are also possible, but these % are harder to understand and debug. Plain old algebra is used instead. % //////////// (A) CREATE A POSTSCRIPT DICTIONARY ////////////////// % Since these tools intercept several fundamental PostScript commands, % they are best placed inside a closed dictionary until they are actually % required... /flutdict 100 dict def % define a dictionary flutdict begin % open dictionary for most following routines % ///////////// (B) A TIME DELAY ROUTINE ///////////////////////////// % A brief time delay might be handy for open loop flutterwumper homing, % special comm situations, and such. Here is a simple and obvious one... /stall1 {usertime add 300000 {usertime 1 index sub 0 ge {exit} if} repeat pop} def % Example: For a 600 millisecond delay, use 600 -stall1-. % ////////////// (C) OUTPUT FILE FORMATTER /////////////////////// % Flutterwumper files often consist of long strings of single characters. % This print formatter limits the width of certain printed lines... /linecount 0 def % initial character counter init /maxline 64 def % maximum linewidth /write1 { dup dup length 1 gt exch (\n) eq or {dest exch writestring /linecount 0 store} {dest exch writestring /linecount linecount 1 add store linecount maxline ge {dest (\n) writestring /linecount 0 store}if}ifelse} bind def /writecr1 {write1 (\n) dest exch writestring } def % ////////////// (D) OUTPUT COMMAND REDEFINER /////////////// % These hooks allow you to redefine your flutfile character set. % The ability to ignore everything between a "%" and a carriage % return or linefeed is assumed... % A flutterwumper that can INTERLEAVE X and Y step phases is assumed. % To convert these to degrees, MULTIPLY them by 45... /!E (0) def % step east /!NE (1) def % step northeast /!N (2) def % step north /!NW (3) def % step northwest /!W (4) def % step west /!SW (5) def % step southwest /!S (6) def % step south /!SE (7) def % step southeast /!H (H\n) def % step to XY home /!U (U\n) def % pen up command /!D (D\n) def % pen down command /!B (B\n) def % initialize job /!Q (Q\n\n\n) def % job completed /!X (X\n) def % breaking debugger /!R {(R?) dup repeatcount 32 sub 1 put} def % repeatproc /repeatcount 4 def % and default /!cr (\n) def % forced carriage return /flutbegin {/lastxmove 0 def /lastymove 0 def /curxpos 0 def /curypos 0 def !B write1 !cr} def % send begin command /fluthome {flutpenup !H write1 !cr} def % home command /penupflag true def % initialize penup /flutpenup {penupflag not {!U write1 % pen up if not up /penupflag true store}if} def /flutpendown {penupflag {!D write1 % pen down if not down /penupflag false store}if} def /flutquit {flutpenup !Q write1 !cr} def % flut quit proc /flutbreak {flutpenup !X write1 !cr} def % flut break debugger /lastxmove 0 def % defaults /lastymove 0 def % //////////// (E) VECTOR OCTANT SELECTOR //////////////////// % Final stack has -x- -y- -angle- {octantproc}. /findoctant { 2 copy exch 2 copy 0 eq exch 0 eq and {pop 0.000001} if atan dup round cvi 45 idiv [{oct0}{oct1}{oct2}{oct3}{oct4}{oct5}{oct6}{oct7}{oct0}] exch get} def % examples: 10 4.7 leaves {oct0} on stack top; -4.7 10 leaves {oct2}. % //////////// (G) OCTANT VECTOR-TO-STEP ALGORITHMS ///////////// % Assume an octant #0 from 0 to +45 degrees. There will ALWAYS be more % X increments than Y in a step approximation. For each X step, % advance X, check the Y position. If half a unit low, also advance Y. % % These can later be speed optimized through table lookups of longer % vectors. They are presented in simple form for clarity here. /curxpos 0 def % running currentpoint for output /curypos 0 def % running currentpoint for output /oct0 { cos 0.5 mul /thresh exch store % calculate threshold 2 copy exch dup 0 eq {0.00001 add} if div % don't divide by zero /slope exch store % find the slope pop abs % don't need y no more? round cvi /#incs exch store % number of x incs 0 % set y increment counter 0 1 #incs 1 sub {/posn exch def % start loop /curxpos curxpos 1 add store % move one right posn 1 add slope mul thresh sub % test vertical position 1 index ge {1 add % y increment advance !NE write1 % command x and y move /curypos curypos 1 add store} % move one up {!E write1} % command x move only ifelse % go east or northeast? } for % for all x increments pop % done with y increment count } bind def % end proc % Each of the remaining octants is slightly different, rotating mirroring or % exchanging x for y... /oct1 {sin 0.5 mul /thresh exch store exch 2 copy exch div /slope exch store pop abs round cvi /#incs exch store 0 0 1 #incs 1 sub {/posn exch def /curypos curypos 1 add store posn 1 add slope mul thresh sub 1 index ge {1 add !NE write1 /curxpos curxpos 1 add store}{!N write1} ifelse } for pop} bind def /oct2 {sin 0.5 mul /thresh exch store exch 2 copy exch div neg /slope exch store pop abs round cvi /#incs exch store 0 0 1 #incs 1 sub {/posn exch def /curypos curypos 1 add store posn 1 add slope mul thresh sub 1 index ge {1 add !NW write1 /curxpos curxpos 1 sub store} {!N write1} ifelse } for pop} bind def /oct3 {cos -0.5 mul /thresh exch store 2 copy exch div neg /slope exch store pop abs round cvi /#incs exch store 0 0 1 #incs 1 sub {/posn exch def /curxpos curxpos 1 sub store posn 1 add slope mul thresh sub 1 index ge {1 add !NW write1 /curypos curypos 1 add store} {!W write1} ifelse } for pop} bind def /oct4 {cos -0.5 mul /thresh exch store 2 copy exch div /slope exch store pop abs round cvi /#incs exch store 0 0 1 #incs 1 sub {/posn exch def /curxpos curxpos 1 sub store posn 1 add slope mul thresh sub 1 index ge {1 add !SW write1 /curypos curypos 1 sub store}{!W write1} ifelse } for pop} bind def /oct5 {sin -0.5 mul /thresh exch store 2 copy div /slope exch store abs round cvi /#incs exch store pop 0 0 1 #incs 1 sub {/posn exch def /curypos curypos 1 sub store posn 1 add slope mul thresh sub 1 index ge {1 add !SW write1 /curxpos curxpos 1 sub store}{!S write1} ifelse } for pop} bind def /oct6 {sin -0.5 mul /thresh exch store 2 copy div neg /slope exch store abs round cvi /#incs exch store pop 0 0 1 #incs 1 sub {/posn exch def /curypos curypos 1 sub store posn 1 add slope mul thresh sub 1 index ge {1 add !SE write1 /curxpos curxpos 1 add store}{!S write1} ifelse } for pop} bind def /oct7 {cos 0.5 mul /thresh exch store 2 copy exch div neg /slope exch store pop abs round cvi /#incs exch store 0 0 1 #incs 1 sub {/posn exch def /curxpos curxpos 1 add store posn 1 add slope mul thresh sub 1 index ge {1 add !SE write1 /curypos curypos 1 sub store}{!E write1} ifelse } for pop} bind def % ////////////// (H) MAIN VECTOR-TO-STEP ALGORITHM ///////////////// % To convert a vector to individual XY steps, the octant is first found, % and then a suitable octant algorithm is used... /vectortostep {findoctant exec !cr write1 } bind def % ///////////// (I) FLATTENPATH CALCULATOR ////////////////////////// % For conversion to vectors, all curves get converted by -flattenpath-. % Too high a value, and output step size suffers. Too low a value and % the computation time get excessive. % Note that -flattenpath- is DEVICE DEPENDENT. A 2X cruder value is % needed at 600 DPI to get the same results at 300 DPI! /inch {72 mul} def % inch converter /flutres 0.01 inch def % DEVICE DEPENDENT output resolution % For small or complex typography, an oversample value of at least 8 % is recommended. This causes a -flattenpath- error of less than 0.25 % flutterwumper steps. Oversamples of 0.4 or less execute faster, but % make straight line approximations that have path errors.. % In general, this is a subtle variable. It does NOT affect the output file % length, but DOES affect computation time SOMEWHAT. The effects are data % dependent, but changes usually occur in large chunks. The average % flutfile line length gives you a clue whether a change has happened. % Leave -oversample- at 8 unless you are after special situations. /oversample 8 def % flat error per output resolution error % A scheme to find resolution of old level I PS code... /findres {save /snap exch def initgraphics matrix currentmatrix dup 0 get dup mul exch 1 get dup mul add sqrt 72 mul cvi snap restore} def /findflat {findres 1 exch div flutres 72 div exch div oversample div} def % /////////////// (J) CO-ORDINATE TRANSFORM AND SCALING /////////// % This does a custom scaling and optional nonlinear co-ordinate transform % from PostScript XY space to flutterwumper axis space. /coordxf {xfxyrelative} def % pick a set of rules % xfxyrelative is the default transform, shifting from absolute PS xy % values to relative flutterwumper values of suitable scale... % microsizing, XY home offsets, and tool diameter allowances are not yet % implemented. They can be added here... /xfxyrelative { curypos flutres mul sub flutres div exch % scale y to output res curxpos flutres mul sub flutres div exch % scale x to output res } def % /////////////// (K) PS PATH TO VECTOR CONVERTER ////////////////// % We will initially assume that ONLY paths ending with the -stroke- % operator OR strings ending with the -show- operator are to be vector % converted. We will also assume the default scale of one point. % At present, clips, fills, images, awidthshows, etc.. are IGNORED. % These features can easily be added as the need arises. % Define output resolution... /inch {72 mul} def /flutres 0.01 inch def % DEVICE DEPENDENT output resolution % Routines needed by -pathforall-... /lastxmove 0 def /lastymove 0 def /curxpos 0 def /curypos 0 def /movetoproc { flutpenup % pen or drill up coordxf % translate to flutter axes vectortostep % generate flutter file curypos flutres mul /lastymove exch store % save device yposn curxpos flutres mul /lastxmove exch store % save device xposn } def /linetoproc { flutpendown % pen or drill down coordxf % translate to flutter axes vectortostep % generate flutter file } def /curvetoproc { % should NOT happen! (Error - No curveto should remain!\n) write1 flush unflattenedcurvetoerror} def /closepathproc {lastxmove lastymove % force lineto linetoproc} def % Intercept PS commands for vector conversion. These MUST be in a dictionary % opened ONLY when generating flutterwumper files! /stroke {findflat setflat flattenpath {movetoproc}{linetoproc}{curvetoproc}{closepathproc} pathforall} def /show {false charpath stroke} def % //////////////// (L) CLOSE FLUTDICT DICTIONARY ////////////// end % place all above definitions into closed dictionary % ////////// (M) GENERATE TEST FILE - SIMPLE RECTANGLE ///////////// % The full flutdict definitions above are needed in the file or run % as a prefile before this code can be run. flutdict begin % open flutterwumper dictionary % Always use "\\" when you mean "\" in a PostScript filename string! /destfilename (A:\\demo0001.txt) def /inch {72 mul} def /flutres 0.01 inch def % set DEVICE DEPENDENT output resolution destfilename (w) file % create an output file /dest exch store % A flutfile permits a comment header. Eventually standards similar to % .eps file headers can be used. For now, just say something... ( %! flut3.0 Synergetics % Simple Rectangle at 100 DPI % demo001.txt v 3.0 DEL 7-24-97 ) writecr1 flutbegin % initialize flutterwumper fluthome % home flutterwumper to x=0 y=0 % ============= YOUR POSTSCRIPT SOURCE FILE STARTS HERE =============== % ============= MUST NOT INCLUDE SHOWPAGE, QUIT, ETC... =============== newpath /inch {72 mul} def 0.4 inch 0.6 inch moveto % set rectangle lower left 0 inch 0.8 inch rlineto % go north relative 1.2 inch 0 inch rlineto % go east relative 0 inch -0.8 inch rlineto % go south relative closepath % and close stroke % ============== YOUR POSTSCRIPT SOURCE FILE ENDS HERE ================ % fluthome % send fluterwumper home % flutquit % eject job or clean up or whatever flush % MUST clear print buffer (!) dest closefile % MUST close output file end % MUST close flutproc dictionary (!) % and here is the returned flutfile (remove %% comments before use)... %% %! flut3.0 Synergetics %% % Simple Rectangle at 100 DPI %% % demo001.txt v 3.0 DEL 7-24-97 %% B %% H %% 121121121121121121121121121121121121121121121121121121121121 %% D %% 2222222222222222222222222222222222222222222222222222222222222222 %% 2222222222222222 %% 0000000000000000000000000000000000000000000000000000000000000000 %% 00000000000000000000000000000000000000000000000000000000 %% 6666666666666666666666666666666666666666666666666666666666666666 %% 6666666666666666 %% 4444444444444444444444444444444444444444444444444444444444444444 %% 44444444444444444444444444444444444444444444444444444444 %% U %% H %% Q % Here is a compressed version of the same flutile... %% BH1Rh2R4D2Rp0R\R\6Rp4R\R\UHQ % ////////// (N) GENERATE TEST FILE - ACCURATE CIRCLE ///////////// % The full flutdict definitions above are needed in the file or run % as a prefile before this code can be run. flutdict begin % open flutterwumper dictionary % Always use "\\" when you mean "\" in a PostScript filename string! /destfilename (A:\\demo0002.txt) def /inch {72 mul} def /flutres 0.01 inch def % set DEVICE DEPENDENT output resolution destfilename (w) file % create an output file /dest exch store % A flutfile permits a comment header. Eventually standards similar to % .eps file headers can be used. For now, just say something... ( %! flut3.0 Synergetics % Three inch circle at 100 DPI % demo002.txt v 3.0 DEL 7-24-97 ) writecr1 flutbegin % initialize flutterwumper fluthome % home flutterwumper to x=0 y=0 % ============= YOUR POSTSCRIPT SOURCE FILE STARTS HERE =============== % ============= MUST NOT INCLUDE SHOWPAGE, QUIT, ETC... =============== newpath /inch {72 mul} def 2 inch 2.5 inch 1.5 inch 0 360 arc % define circle closepath % and close stroke % and convert % ============== YOUR POSTSCRIPT SOURCE FILE ENDS HERE ================ fluthome % send fluterwumper home flutquit % eject job or clean up or whatever flush % MUST clear print buffer (!) dest closefile % MUST close output file end % MUST close flutproc dictionary (!) % and here is the returned flutfile (remove %% comments before use)... %! flut3.0 Synergetics % Three inch circle at 100 DPI % demo002.txt v 3.0 DEL 7-24-97 %% B %% U %% H %% 1101101110110111011011101101110110111011011101101110110111011011 %% 1011011101101110110111011011101101110110111011011101101110110111 %% 0110111011011101101110110111011011101101110110111011011101101110 %% 1101110110111011011101101110110111011011101101110110111011011101 %% 1011101101110110111011011101101110110111011011101101110110111011 %% 011101101110110111011011101101 %% D %% 22222222 %% 2222322 %% 22222322 %% 2223222 %% 2232223 %% 22322232 %% 2322322 %% 232323 %% 2323223 %% 322323 %% 3232323 %% 323323 %% 323323 %% 333323 %% 33333 %% 33333 %% 333433 %% 33433 %% 334334 %% 343334 %% 3434334 %% 343434 %% 3434434 %% 4344344 %% 43443444 %% 4344434 %% 4434444 %% 44434444 %% 4444344 %% 44444444 %% 44444444 %% 444544 %% 44444544 %% 4445444 %% 4454445 %% 44544454 %% 4544544 %% 454545 %% 4545445 %% 544545 %% 5454545 %% 545545 %% 45545 %% 55455 %% 555545 %% 55555 %% 55555 %% 555655 %% 55655 %% 556556 %% 565556 %% 5656556 %% 565656 %% 656565 %% 6566566 %% 65665666 %% 6656666 %% 66656666 %% 6666566 %% 66666666 %% 6666666 %% 6666766 %% 66666766 %% 6667666 %% 6676667 %% 66766676 %% 6766766 %% 76767 %% 6767667 %% 766767 %% 7676767 %% 767767 %% 767767 %% 77677 %% 777767 %% 77777 %% 77777 %% 777077 %% 77077 %% 770770 %% 707770 %% 7070770 %% 707070 %% 7070070 %% 070707 %% 07007000 %% 0700070 %% 0070000 %% 00070000 %% 0000700 %% 00000000 %% 00000000 %% 0000100 %% 00000100 %% 0010001 %% 00100010 %% 0100100 %% 010101 %% 0101001 %% 100101 %% 010101 %% 101101 %% 11011 %% 111101 %% 11111 %% 11111 %% 111211 %% 11211 %% 112112 %% 121112 %% 1212112 %% 121212 %% 1212212 %% 212121 %% 2122122 %% 21221222 %% 2122212 %% 22212222 %% 2222122 %% 22222222 %% %% U %% Q %% % ///////// (O) GENERATE TEST FILE - PALATINO BOLD "R" ///////////// % The full flutdict definitions above are needed in the file or run % as a prefile before this code can be run. flutdict begin % open flutterwumper dictionary % Always use "\\" when you mean "\" in a PostScript filename string! /destfilename (A:\\demo0003.txt) def /inch {72 mul} def /flutres 0.01 inch def % set DEVICE DEPENDENT output resolution destfilename (w) file % create an output file /dest exch store % A flutfile permits a comment header. Eventually standards similar to % .eps file headers can be used. For now, just say something... ( %! flut3.0 Synergetics % Palatino bold "R" at 100 DPI % demo003.txt v 3.0 DEL 7-24-97 ) writecr1 flutbegin % initialize flutterwumper fluthome % home flutterwumper to x=0 y=0 % ============= YOUR POSTSCRIPT SOURCE FILE STARTS HERE =============== % ============= MUST NOT INCLUDE SHOWPAGE, QUIT, ETC... =============== newpath % MUST use a previously installed font! % /Palatino-Bold findfont 100 scalefont setfont % pick a font% /URWPalladioL-Bold findfont 100 scalefont setfont 100 200 moveto % pick starting point (R) show % convert desired string % ============== YOUR POSTSCRIPT SOURCE FILE ENDS HERE ================ fluthome % send fluterwumper home flutquit % eject job or clean up or whatever flush % MUST clear print buffer (!) dest closefile % MUST close output file end % MUST close flutproc dictionary (!) % Here is the returned flutfile. Remove %% before use... %% %! flut3.0 Synergetics %% % Palatino bold "R" at 100 DPI %% % demo003.txt v 3.0 DEL 7-24-97 %% %% B %% H %% 1211212112121121121211211212112121121121211211212112121121121211 %% 2112121121211211212112121121121211211212112121121121211211212112 %% 1211211212112121121121211211212112121121121211211212112121121121 %% 2112121121121211211212112121121121211211212112121121121211211212 %% 1121211211212112121121121211211212112121121121211211212112121121 %% 1212112 %% D %% 01010 %% 1010 %% 111 %% 111 %% 11 %% 1 %% 21 %% 21 %% 22 %% 21 %% 22 %% 22 %% 22 %% 222 %% 32 %% 23 %% 23 %% 3 %% 32 %% 33 %% 4 %% 34 %% 343 %% 44 %% 43 %% 444444 %% 4444444444 %% 444444444444444444 %% 444444444 %% 4444444444444444 %% 66666 %% 00000 %% 00 %% 0 %% 76 %% 7 %% 666 %% 6666666 %% 666666666666666666666666666666666666666666666666666666666 %% 6666666 %% 66 %% 56 %% 5 %% 4 %% 454 %% 44444 %% 666666 %% 00000000 %% 00000000 %% 0000000000700 %% 222222 %% 43 %% 43 %% 32 %% 22 %% 2222222 %% 2222222222222222222222222222222222222222222222222222222222222222 %% 2222 %% 100 %% 00000 %% 0000 %% 0070 %% 07 %% 0 %% %% 70 %% 7 %% 77 %% 6 %% 67 %% 6 %% 6666 %% 666 %% 666 %% 56 %% 56 %% 56 %% 55 %% 55 %% 5 %% 454 %% 44 %% 4454 %% 65 %% 7677677676776776776776767767767767767677677677676 %% 0000000010000 %% 222222 %% 443 %% 4 %% 3 %% 3 %% 333 %% 32332332332332332332332332332323323323 %% U %% 7767776777677767776777677767777677767776777677767 %% H %% Q %% % /// (P) FLUTFILE ANALYZER/EMULATOR/READER/RETOUCHER/DEBUGGER ///////////// % (ALSO DISPENSES SOFT ICE CREAM) % /readflutfile reads a flutterwumper file and plots it back as PostScript. % This is useful for proof checks and to magnify closure and error details. % /readflutfile also can serve as an emulator and debugger during % flutterwumper hardware development. It may also be used to manually % "retouch" or otherwise "optimize" low resolution typography. % This version reads a disk based flutfile. Send it to the Acrobat % Distiller to generate a .PDF file. .PDF is recommended because of % its ease of magnification. % This does not yet include microsizing, tool allowances or home offset. % Repeat commands are not yet implimented 100 dict /flutreader exch def flutreader begin /xoffset 100 def % zero x position on page /yoffset 100 def % zero y position on page /upmode true def % initialize up-down mode /nocomment true def % initialize comment mode /inch {72 mul} def % inch scaling /flutres 0.01 inch def % current resolution of flutfile /penwidth 0.5 def % pen linewidth in points /showaxisflag true def % show 0-0 axis? /xaxislength 5 inch def % length of x axis /yaxislength 4.5 inch def % length of y axis /showgridflag true def % show a layout grid? /gridblock 0.1 inch def % small grid block size /gridblockx 1 inch def % large grid block size /black {0 0 0 setrgbcolor} def /green {0 1 0 setrgbcolor} def /red {1 0 0 setrgbcolor} def /blue {0 0 1 setrgbcolor} def systemdict /setstrokeadjust known {true setstrokeadjust} if % for video 256 array /flutcommandset exch def % build an array of all characters 0 1 255 {flutcommandset exch {} put} for % fill it with null procs (0) 0 get flutcommandset exch {nocomment {!E} if} put % stuff commands (1) 0 get flutcommandset exch {nocomment {!NE} if} put (2) 0 get flutcommandset exch {nocomment {!N} if} put (3) 0 get flutcommandset exch {nocomment {!NW} if} put (4) 0 get flutcommandset exch {nocomment {!W} if} put (5) 0 get flutcommandset exch {nocomment {!SW} if} put (6) 0 get flutcommandset exch {nocomment {!S} if} put (7) 0 get flutcommandset exch {nocomment {!SE} if} put (D) 0 get flutcommandset exch {nocomment {!D} if} put (U) 0 get flutcommandset exch {nocomment {!U} if} put (H) 0 get flutcommandset exch {nocomment {!H} if} put (B) 0 get flutcommandset exch {nocomment {!B} if} put (Q) 0 get flutcommandset exch {nocomment {!Q} if} put (%) 0 get flutcommandset exch {!com} put 10 flutcommandset exch {!ret} put % stuff control commands 13 flutcommandset exch {!ret} put % file insertable error trapper. Placing ! in the flutfile executes % custom code named debug. Like a trap or break... (!) 0 get flutcommandset exch {nocomment {debug}if} put % debugger % action commands... /!H {0 0 moveto} def % XY home startup /!com {/nocomment false def} def % start comment mode /!ret {/nocomment true def} def % reset comment mode /!D {/upmode false def} def % pen down /!U {/upmode true def} def % pen up /!go {upmode{rmoveto}{rlineto % action selector currentpoint stroke moveto}ifelse} def /!E {1 0 !go} def % go east one step /!NE {1 1 !go} def % go northeast one step /!N {0 1 !go} def % go north one step /!NW {-1 1 !go} def % go northwest one step /!W {-1 0 !go} def % go west one step /!SW {-1 -1 !go} def % go southwest one step /!S {0 -1 !go} def % go south one step /!SE {1 -1 !go} def % go southeast one step /!Q {} def % end of flutfile quit /!B {} def % flutterwumper setup % optional axis shower... /showaxis {showaxisflag {gsave green 1 setlinecap 2 setlinewidth gsave 0 0 moveto 0 yaxislength rlineto xaxislength 0 rlineto 0 yaxislength neg rlineto 0.92 1 0.92 setrgbcolor fill grestore 0 inch -0.1 inch moveto 0 yaxislength 0.2 inch add rlineto stroke -0.1 inch 0 moveto xaxislength 0.2 inch add 0 rlineto stroke grestore}if} def % optional fine grid shower... /showfinegrid {showgridflag{ gsave green 1 setlinewidth gsave xaxislength gridblock div 1 add cvi {0 0 moveto 0 yaxislength lineto stroke gridblock 0 translate} repeat grestore gsave yaxislength gridblock div 1 add cvi {0 0 moveto xaxislength 0 lineto stroke 0 gridblock translate} repeat grestore grestore }if}def % optional coarse grid shower... /showcoarsegrid {showgridflag{gsave green 2 setlinewidth gsave xaxislength gridblockx div 1 add cvi {0 0 moveto 0 yaxislength lineto stroke gridblockx 0 translate} repeat grestore gsave yaxislength gridblockx div 1 add cvi {0 0 moveto xaxislength 0 lineto stroke 0 gridblockx translate} repeat grestore grestore}if}def % this processes one flutfile line /procflutline {{flutcommandset exch get cvx exec} forall} def % this processes the entire flutfile /scanflutfile {black {source 128 string readstring {procflutline} {procflutline exit}ifelse} loop } def % an annotator... /graphtitle {gsave black xoffset yoffset translate /Helvetica-Bold findfont 12 scalefont setfont 0.1 inch -0.35 inch moveto show grestore} def % this does it all... /readflutfile { save /flutsnap exch store (r) file /source exch store % create read file xoffset yoffset translate % set initial page position showaxis % optionally show axis showfinegrid % optionally show layout grid showcoarsegrid penwidth setlinewidth % set pen width flutres dup scale % set flutres resolution % and magnification scanflutfile % extract flutfile commands flutsnap restore } def end % close flutreader dictionary %%%%%% Demo - remove or alter before reuse %%%%%%%%%%%%%%%%%%%%%%%%% flutreader begin /debug {currentpoint zowie} def % optional debugger % This example produces one PDF file of five pages. Each can % be individually magnified for detail, etc... newpath black 0.25 setlinewidth (A:\\demo0001.txt) readflutfile % read selected flutfile (A simple 100 DPI rectangle.) graphtitle % annotate it showpage % advance to next page black 0.25 setlinewidth (A:\\demo0002.txt) readflutfile % read selected flutfile (A medium sized 100 DPI circle.) graphtitle % annotate it showpage black 0.25 setlinewidth (A:\\demo0002.txt) readflutfile % read selected flutfile (100 DPI circle and tolerance limits. Use high magnification.) graphtitle % annotate it % plot an original overlay tolerance window for comparison. % NOTE: takes *extreme* PDF magnification to view tolerance... red 0 setlinewidth gsave xoffset yoffset translate 2 inch 2.5 inch 1.5 0.007 add inch 0 360 arc closepath stroke 2 inch 2.5 inch 1.5 0.007 sub inch 0 360 arc closepath stroke grestore showpage % advance to next page black 1 setlinewidth (A:\\demo0003.txt) readflutfile % read selected flutfile (Palatino "R" at 100 dpi.) graphtitle showpage black 0.25 setlinewidth (A:\\demo0003.txt) readflutfile % read selected flutfile (Palatino "R" accuracy comparison. Use high magnification.) graphtitle gsave red 0.001 setlinewidth xoffset yoffset translate /URWPalladioL-Bold findfont 100 scalefont setfont % NEED VALID FONT HERE 100 200 moveto (R) false charpath 0.001 setlinewidth stroke grestore showpage black 1 setlinewidth (A:\\demo0004.txt) readflutfile % read selected flutfile (Hand retouched 100 DPI "R".) graphtitle showpage end % close flutreader dictionary %%%%%%%%%%%%%%%%%%%%%%% Further Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Note also that no matter what you do, running a small character of a fancy % font at low resolution will look less than stunning. But you can take % the stock Palatino "R" above, and "retouch" your flutfile. For instance, % the left foot can be flattened by replacing 0000000100 with 0000000000 and % 0000000070 with 0000000000. The small tic at the top inside of the R bowl % may be eliminated by replacing the 00001 and 0070 with 00000 and 0000. The % "byte" at the upper right can be improved by replacing the 33 44 43 with % 33 43 44, and so on. % With some practice, a flutfile can easily be "sight read". Try it. % Note that "%" comments may be inserted anywhere in a flutflie as markers % or reminders. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % GURU's LAIR VOICE HELPLINE % ========================== % % A no charge Guru's Lair voice helpline is avilable for your use % for technical information, referral to qualified consultants, and for % off-the-wall networking in general. % % Best calling times are 8-5 weekdays MOUNTAIN STANDARD TIME year around. % Please, US calls only. % % Phone or write your flutterwumper questions to: % % Don Lancaster % SYNERGETICS % Box 809-GL % Thatcher, AZ, 85552 % % (520) 428-4073 % % Or visit the www.tinaja.com website. % % Questions may also be emailed to don@tinaja.com % % Full consulting and PIC development services available. % A free TECHNICAL INSIDER SECRETS catalog is also available. % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%% END PS FLUTTERWUMPER UTILITIES %%%%%%%%%%%%%%%%%%%%%% % Consulting services available on concepts shown. % =================================================================== % Copyright c 1997 by Don Lancaster and Synergetics, Box 809, % Thatcher AZ, 85552. (520) 428-4073 www.tinaja.com don@tinaja.com % All commercial rights and all electronic media rights are % *fully* reserved. Linking welcome. Reposting expressly forbidden. % ===================================================================