home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / lang / postscri / 5545 < prev    next >
Encoding:
Text File  |  1992-11-16  |  36.5 KB  |  1,171 lines

  1. Newsgroups: comp.lang.postscript
  2. Path: sparky!uunet!munnari.oz.au!newsroom.utas.edu.au!probitas!dockhorn
  3. From: dockhorn@probitas.cs.utas.edu.au (Patrick Dockhorn)
  4. Subject: SOURCE: Scramble Algorithm
  5. Message-ID: <dockhorn.721922569@probitas>
  6. Keywords: SOURCE algorithm
  7. Sender: news@newsroom.utas.edu.au
  8. Organization: University of Tasmania, Australia.
  9. Date: Mon, 16 Nov 1992 14:02:49 GMT
  10. Lines: 1159
  11.  
  12. I provide an algorithm that converts two arbitrary
  13. text strings into another - sounds strange ? It is.
  14. You will have to play with the parameters to get a 
  15. good effect - and as this algorithm makes use of the
  16. charpath - pathforall - sequence, it may not run on
  17. Level 1 printers (although it should, according to
  18. the replies I got following an earlier post that
  19. dealt with that problem).
  20.  
  21. have fun!
  22.  
  23. -patsch
  24.  
  25. --
  26. /f{/Times-Roman findfont exch scalefont setfont}def/s{moveto show}def 20 f (Pa\
  27. trick Dockhorn)40 65 s 12 f(Student of Computer Science)40 50 s (University of\
  28.  Karlsruhe)54 38 s 6.1 f(We are sorry but the number you've dialed is imaginar\
  29. y.)40 28 s(Please rotate your phone 90 degrees and try again.)48 20 s showpage
  30.  
  31. --------------------------------cut here-------------------------------------
  32. %!
  33.  
  34. %%
  35. %%     THE SCRAMBLE ALGORITHM IS IN THE PUBLIC DOMAIN.
  36. %%    NEVERTHELESS THE NOTE ABOUT THE AUTHOR MAY NOT BE
  37. %% REMOVED WHEN THE PROGRAM IS USED WITHOUT MAJOR CHANGES.
  38. %%
  39. %%       COPYRIGHT (C) FOR THE SCRAMBLE ALGORITHM
  40. %%            November 1992 Patrick Dockhorn
  41. %%
  42. %% comments, suggestions : dockhorn@fzi.de
  43. %%
  44. %% -----------------------------------------------------------------------
  45. %%
  46. %% supplied procedures:
  47. %%
  48. %% align                moves to a position that is vertically given by a
  49. %%                      row (and the current font size) and horizontally
  50. %%                      determined by the mode parameter (see definition)
  51. %%
  52. %% baseclip             sets the basic clip path
  53. %%
  54. %% drawarray            draws a given array of line segments:
  55. %%                      [ lseg(1) lseg(2) ... lseg(n) ] where
  56. %%                      lseg(i) = [ startx starty endx endy ]
  57. %%
  58. %% prpoints             prints a given line segment (s.a.) to stdout
  59. %%
  60. %% prlines              prints a given array of line segments to stdout
  61. %%
  62. %% proto                writes a given simple object to stdout by
  63. %%                      converting it to a string before.
  64. %%                      if fileaccess is true, the results are also
  65. %%                      written onto the file profile (invit.pro).
  66. %%
  67. %% buildpath            takes a string and a start position from the stack
  68. %%                      and creates an array of line segments that, if it's
  69. %%                      drawn (using drawarray) represents the string given.
  70. %%                      the font to be used has to be selected before buildpath
  71. %%                      gets called. if the step parameter is not zero the 
  72. %%                      given space will be left between two consecutive chars.
  73. %%
  74. %% splitlines           takes two arrays of line segments and manipulates
  75. %%                      the smaller one so that after the procedure has
  76. %%                      finished, it includes the same number of segments
  77. %%                      the larger one does. this is done by splitting lines
  78. %%                      so building two segments out of one.
  79. %%
  80. %% merge                using a given number of intermediate steps, the
  81. %%                      first array of line segments is transformed into the
  82. %%                      second. this is the basic scramble procedure.
  83. %%                      the procedure requires the two arrays to have the
  84. %%                      same size.
  85. %%
  86. %% scramble             the main procedure for scrambling. just takes two
  87. %%                      text strings and their starting positions from the
  88. %%                      stacks and does everything to create the intermediate
  89. %%                      steps using all the fine procedures described above.
  90. %%
  91. %% ssetfont             selects the current font (fname) in the given size 
  92. %%                      and stores the size in the global variable fsize.
  93. %%
  94. %% mysetrgb             uses use_colors to either call setrgbcolor or setgray
  95. %%                      (converting color to greyscale value uses gdv formula)
  96. %%
  97.  
  98. %%
  99. %% GLOBAL VARIABLES (SHOULD NOT BE CHANGED BY THE USER)
  100. %%
  101.  
  102. /cm          { 28.346456 mul } def  %% calculates cm to points
  103. /tocm        { 28.346456 div } def  %% back to cm
  104. /A4w         21.0 cm def            %% Width of one sheet of DIN A4 paper
  105. /A4h         29.7 cm def            %% Height of one sheet of DIN A4 paper
  106. /#copies 1   def
  107.  
  108. /prostr      100 string def     %% takes data to be printed to stdout & profile
  109. /oldghost    false def           %% set true if working with GhostScript 2.1
  110. /use_colors  true def           %% if yo want it you can have it
  111. /nestlevel   0 def              %% nesting level for protocol beauty
  112. /indentamount 2 def             %% spaces for every block level
  113.  
  114. %%
  115. %% BEGIN PARAMETRIC SECTION OF SCRAMBLE     (change to your needs)
  116. %%
  117.  
  118. /perssize    48 def
  119. /persfont       /Times-Roman-German def
  120.  
  121. /color0         [ 0.0 0.0 0.0 ] def       %% between these color vectors
  122.                                           %% the program
  123. /color1         [ 0.0 0.0 0.0 ] def       %% will do linear interpolation !
  124. /finerib        0.25 def                  %% step to fill without holes
  125. /chaotic        false def                 %% exchange array elements by random ?
  126. /xoff        1.2 cm def                %% minimal horizontal offset
  127. /yoff           1.2 cm def                %% minimal vertical offset
  128. /verbose        false def                 %% if false, no protocol is generated
  129. /pro_params     true def                  %% show the parameters of all procs
  130. /pro_arrparams  false def                 %% show array params full, 
  131.                                           %% not only size
  132. /pro_procs      true def                  %% show invocation & 
  133.                                           %% exit of procedures
  134. /pro_mysetrgb   false def                 %% very space consuming, 
  135.                                           %% so extra mentioned 
  136. /tostdout       true def                  %% show output on console ?
  137. /fileaccess     false def                 %% true -> protocol also onto file
  138. /lineskip       { fsize 0.1 mul } def     %% amount of space between lines
  139. /pw A4w xoff dup add sub def              %% available width
  140. /ph A4h yoff dup add sub def              %% avaiable height
  141.  
  142. %% if fullscramble is true, the two strings are scrambled together completely,
  143. %% without any splitting. In this case there's no restriction at all to the
  144. %% length of the strings and the relation between the string lengths - they may
  145. %% be chosen arbitrary. Also the parameter 'basicstep' has no meaning at all if
  146. %% fullscramble is true.
  147.  
  148. /fullscramble   true def
  149.  
  150. %% # of characters that are regarded a unity in the shorter string
  151. %% If you change this keep in mind that the length of the longer text
  152. %% then has be a multiple of (a) the length of the shorter text and (b)
  153. %% the basicstep value (this is trivia if basicstep is 1)
  154.  
  155. /basicstep      1 def                   
  156.  
  157. /funny                     false def       %% true -> colors chosen by random
  158.  
  159. /rcolor0                   color0 def      %% limits of randomly chosen
  160. /rcolor1                   color1 def      %% colors.
  161.  
  162. %%
  163. %% BEGIN PROCEDURES
  164. %%
  165.  
  166.  
  167. %%
  168. %% string row mode align -
  169. %%
  170. %% align takes the desired row and the string to be displayed
  171. %% and calculates the start position of the string (using fsize).
  172. %% The mode parameter can take the following values:
  173. %%  0 -> center string
  174. %% -1 -> center string and place to maxtop position
  175. %%  1 -> align string to left margin
  176. %%  2 -> align string to right margin
  177. %% 
  178.  
  179. /align
  180. {
  181.     pro_procs { (align \{) nlproto } if
  182.     pro_params
  183.     {
  184.         3 -1 roll dup (string     = ) nlproto proto
  185.         3 -1 roll dup (row        = ) nlproto proto
  186.         3 -1 roll dup (mode       = ) nlproto proto
  187.     } if
  188.  
  189.    dup -1 eq
  190.     {
  191.         pop pop                                 %% pop mode and row 
  192.         dup stringwidth pop neg A4w add 2 div   %% x-position
  193.         exch
  194.         gsave newpath 0 0 moveto false charpath flattenpath 
  195.         pathbbox exch pop sub exch pop grestore
  196.         ph add
  197.     }
  198.     {
  199.         exch
  200.         lineskip mul yoff add A4h exch sub          %% y position
  201.         exch                                        %% get mode
  202.         dup 0 eq
  203.         {
  204.             pop exch stringwidth pop neg A4w add 2 div exch %% centered
  205.         }
  206.         {
  207.             dup 1 eq
  208.             {
  209.                 pop exch pop xoff exch                      %% left
  210.             }
  211.             {
  212.                 pop exch stringwidth pop neg pw add exch    %% right
  213.             } ifelse
  214.         } ifelse
  215.     } ifelse
  216.     moveto
  217.     pro_procs { (\} align) nlproto } if
  218. } def
  219.  
  220. %%
  221. %% - baseclip -
  222. %%
  223. %% baseclip restricts the drawable using xoff & yoff and DIN A4 sheets.
  224. %%
  225.  
  226. /baseclip
  227. {
  228.     pro_procs { (baseclip \{) nlproto } if
  229.     newpath xoff yoff moveto
  230.     pw 0 rlineto 0 ph rlineto pw neg 0 rlineto
  231.     closepath clip
  232.     pro_procs { (\} baseclip) nlproto } if
  233. } def
  234.  
  235. %% color0 color1 randomcolors array-of-lines drawarray -
  236. %%
  237. %% draws line segments represented in an array
  238. %% if randomcolors is true, the colors are choosen
  239. %% by randomcolors between the color vectors color0 and color1.
  240. %% if randomcolors is false, these vectors are not present on
  241. %% the stack !
  242. %%
  243.  
  244. /drawdict 7 dict def
  245.  
  246.  
  247. /drawarray
  248. {
  249.     drawdict begin          %% push new dictionary onto stack
  250.  
  251.     % pro_procs { (drawarray \{) nlproto } if
  252.  
  253.         exch /rcols exch def     %% get random parameter
  254.  
  255.         rcols
  256.         {
  257.             exch /c1 exch def
  258.             exch /c0 exch def
  259.         } if
  260.  
  261.     false % pro_params
  262.         {
  263.             rcols
  264.             {
  265.                 (color0      = ) nlproto co0 prpoints
  266.                 (color1      = ) nlproto co1 prpoints
  267.             } if
  268.  
  269.         (randomcols  = ) nlproto rcols proto
  270.             (array       = ) nlproto dup 
  271.             pro_arrparams 
  272.             { prlines } { (\[ ) proto length proto ( \]) proto } ifelse
  273.         } if
  274.  
  275.     newpath
  276.         {
  277.             /lseg exch def
  278.             lseg 0 get lseg 1 get moveto
  279.             lseg 2 get lseg 3 get lineto
  280.             rcols
  281.             {
  282.                 [
  283.                     0 1 2
  284.                     {
  285.                         /idx exch def
  286.                         rand 65536 mod 65535 div /bary exch def %% linear int.
  287.                         c0 idx get bary mul
  288.                         c1 idx get 1 bary sub mul
  289.                         add
  290.                     } for
  291.                 ] mysetrgb stroke
  292.             } if
  293.         }
  294.         forall
  295.         rcols not { stroke } if
  296.     % pro_procs { (\} drawarray) nlproto } if
  297.     end
  298. } def
  299.  
  300.  
  301. %%
  302. %% array-of-points prpoints -
  303. %%
  304. %% print points from an array using proto
  305. %%
  306.  
  307. /prpoints
  308. {
  309.     ( \[ ) proto
  310.     { (  ) proto proto } forall
  311.     ( \] ) proto
  312. } def
  313.  
  314. %%
  315. %% array-of-line-segments prlines -
  316. %%
  317. %% print lines from an array using proto
  318. %%
  319.  
  320. /prdict 1 dict def
  321.  
  322. /prlines
  323. {
  324.     prdict begin
  325.         /cnt 0 def
  326.         (\[ ) nlproto
  327.         { (\() nlproto cnt proto (\)  ) proto prpoints 
  328.             /cnt cnt 1 add def } forall
  329.         (\]\012) proto
  330.     end
  331. } def
  332.  
  333.  
  334. %%
  335. %% any proto -
  336. %%
  337. %% proto writes out a string to stdout AND a protocol file
  338. %% nlproto precedes the output with a newline and two spaces
  339. %% also scans for '{' and '}' to handle these correctly !
  340. %%
  341. %% there are also the valuable routines nlproto and indent which
  342. %% beautify the protocol output !
  343. %%
  344.  
  345. /indent
  346. {
  347.     (\012) proto                            %% output newline
  348.     0 1 nestlevel indentamount mul
  349.     {
  350.         pop ( ) proto 
  351.     } for                                   %% output indentation spaces
  352. } def
  353.  
  354. /nlproto
  355. {
  356.     dup                                     %% save for later use    
  357.     dup length 1 sub 1 getinterval          %% last char
  358.     (\{) eq 
  359.     { 
  360.         (\012) proto
  361.         indent (\{        \%\% begin procedure ) proto
  362.         dup 0 exch length 2 sub getinterval proto
  363.         /nestlevel nestlevel 1 add def   %% mark nesting
  364.     }
  365.     {
  366.         dup 0 1 getinterval                 %% first char
  367.         (\}) eq 
  368.         { 
  369.             /nestlevel nestlevel 1 sub def      %% back from block
  370.             indent (\}        \%\% end procedure ) proto
  371.             dup length 1 sub 1 exch getinterval proto (\012) proto
  372.         }
  373.         {
  374.             indent proto
  375.         } ifelse
  376.     } ifelse
  377. } def
  378.  
  379. /proflag false def               %% If true, protocol file is already open
  380. /profile (/tmp/scramble.pro) def %% Name of the protocol file
  381.  
  382. /proto
  383. {
  384.     verbose
  385.     {
  386.         prostr cvs                                  %% first convert parameter to string
  387.         dup (exit) eq          %% this parameter closes the protocol file
  388.         {
  389.             pop fileaccess { profid closefile } if %% close file
  390.         }
  391.         {       
  392.             tostdout { dup print flush } if       %% duplicate given string and
  393.             fileaccess                      %% print to stdout & file if desired 
  394.             {
  395.                 proflag not   %% Check if protocol file is already open
  396.                 {
  397.                     /profid profile (w) file def %% create new file
  398.                     /proflag true def
  399.                     profid (\012\012\%\% protocol for invit.ps\012) writestring
  400.                 } if
  401.                 profid exch writestring       %% write to protocol file
  402.                 profid flushfile              %% and flush buffers
  403.             }                             %% if fileaccess possible
  404.             { pop } ifelse
  405.         } ifelse               %% if parameter == exit then close file else print
  406.     }                          %% if verbose mode on
  407.     { pop } ifelse
  408. } def
  409.  
  410. %%
  411. %% string step xpos ypos buildpath array-of-lines
  412. %%
  413.  
  414. %% buildpath takes the given character and 
  415. %% and build a two dimensional array from it, 
  416. %% that represents the line segments needed
  417. %% to draw the character:
  418. %%
  419. %% [ 
  420. %%   [ start1-x start1-y end1-x end1-y ] 
  421. %%   [ start2-x start2-y end2-x end2-y ] 
  422. %%   ...
  423. %%   [ startN-x startN-y endN-x endN-y ] 
  424. %% ]
  425. %%
  426. %% The array elements are again arrays that describe line segments to be drawn.
  427. %%
  428.  
  429. /buildpathdict 30 dict def
  430.  
  431.  
  432. /buildpath 
  433. {
  434.     buildpathdict begin                                 %% local dictionary
  435.         newpath                                         %% start new path
  436.         /by exch def /bx exch def                       %% start position
  437.         /xskip exch def                                 %% skip amount in x direction
  438.         /str exch def
  439.  
  440.         pro_procs { (buildpath \{) nlproto } if
  441.         pro_params
  442.         {
  443.             (string  = ) nlproto str proto
  444.             (step    = ) nlproto xskip proto
  445.             (xpos    = ) nlproto bx proto
  446.             (ypos    = ) nlproto by proto
  447.             (cfsize  = ) nlproto fsize proto
  448.         } if
  449.  
  450.     % 2 setflat %% was 80 
  451.  
  452.         /str1 2 string def
  453.         [                                               %% Push initial mark on the stack
  454.             0 1 str length 1 sub
  455.             {                                           %% for all characters
  456.                 str exch 1 getinterval /str1 exch def
  457.  
  458.         (Building path for ) nlproto str1 proto
  459.  
  460.                 newpath bx by moveto
  461.                 str1 false charpath                     %% create the path
  462.         flattenpath
  463.         gsave
  464.         0 0 moveto 0 1 lineto % closepath
  465.  
  466.                 /cnt 0 def
  467.  
  468.         oldghost      %% GhostScript does not handle the path correctly -> trick
  469.                 {
  470.                     7777 8888 lineto    %% serves as 'end-of-path' marker
  471.                 } if
  472.  
  473.                 {  
  474.             /cy exch def /cx exch def 
  475.             cx cy moveto
  476.             /mx cx def /my cy def
  477.         }     %% moveto
  478.                 {  %% lineto
  479.  
  480.             oldghost %% Special handling of GhostScript 2.1
  481.                     {
  482.                         dup 8888 eq 
  483.                         { 
  484.                             pop dup 7777 eq { pop exit } { 8888 } ifelse 
  485.                         } if
  486.                     } if
  487.  
  488.             /ly exch def /lx exch def
  489.             [ cx cy lx ly ]
  490.             /cx lx def /cy ly def
  491.  
  492.             /cnt cnt 1 add def
  493.         }
  494.                 { (\012\012Illegal attempt for CURVETO !\012\012) proto exit }  
  495.                 { [ cx cy mx my ] /cx mx def /cy my def } % closepath
  496.                 pathforall
  497.         grestore
  498.  
  499.         pop /cnt cnt 1 sub def    % pop last segment (includes trick line only)
  500.  
  501.                 (path for ) nlproto str1 proto 
  502.                 ( built - ) proto cnt proto ( segments created.) proto
  503.  
  504.                 /bx bx str1 stringwidth pop add xskip add def   %% new x value
  505.  
  506.             } for                   %% for all characters in the string
  507.         ]              %% Push final mark
  508.         newpath        %% Clear Path
  509.         (\} buildpath) nlproto
  510.  
  511.     end             %% end local dictionary 
  512. } def
  513.  
  514.  
  515.  
  516. %%
  517. %% array1 array2 splitlines new-array2
  518. %%
  519.  
  520. %% splitlines takes two arrays containing line segments (as provided
  521. %% by buildpath) from the stack with the first array (array1) being 
  522. %% the larger one. The smaller (second) array is now modified so
  523. %% that it includes the same number of line segments as the big one
  524. %% afterwards.
  525.  
  526.  
  527. /splitdict 20 dict def
  528.  
  529.  
  530. /splitlines
  531. {
  532.     splitdict begin         %% push new dictionary onto stack
  533.  
  534.         pro_procs { (splitlines \{) nlproto } if
  535.         pro_params
  536.         {
  537.             exch dup
  538.             (array1      = ) nlproto
  539.             pro_arrparams 
  540.             { prlines } { (\[ ) proto length proto ( \]) proto } ifelse
  541.             exch dup
  542.             (array2      = ) nlproto
  543.             pro_arrparams
  544.             { prlines } { (\[ ) proto length proto ( \]) proto } ifelse
  545.         } if
  546.  
  547.         aload length                                %% Get destination array
  548.         dup /dstlen exch def
  549.         array /dst exch def dst astore pop
  550.  
  551.         length /srclen exch def                     %% length of source array
  552.  
  553.         srclen dstlen                               %% Get the number of segments we have to create 
  554.         div floor cvi                               %% from one single segment in the first step.
  555.         /sps exch def                               %% Segments per segment...
  556.         /rest srclen dstlen sps mul sub def
  557.  
  558.         /counter 0 def                              %% for infrequent splitting of lines
  559.         [                                           %% begin of array - marker
  560.             0 1 dstlen 1 sub                        %% OK, go through src array
  561.             {
  562.                 /indx exch def                      %% current array index
  563.                 /lseg dst indx get def              %% get current line
  564.                 sps 1 le                            %% any frequent splittings ?
  565.                 { lseg }
  566.                 {
  567.                     /x0 lseg 0 get def /y0 lseg 1 get def           %% get the points
  568.                     /x1 lseg 2 get def /y1 lseg 3 get def
  569.                     x0 x1 eq                                %% vertical line ?
  570.                     {
  571.                         0 1 sps 1 sub
  572.                         {
  573.                             /sindx exch def
  574.                             [ x0 y0 y1 y0 sub sindx       mul sps div add
  575.                                 x0 y0 y1 y0 sub sindx 1 add mul sps div add ]
  576.                         } for
  577.                     }                                       %% if vertical
  578.                     {
  579.                         0 1 sps 1 sub
  580.                         {
  581.                             /sindx exch def
  582.                             [ x0 x1 x0 sub sindx mul sps div add   %% X-START
  583.                                 y0 y1 y0 sub sindx mul sps div add   %% Y-START   
  584.                                 x0 x1 x0 sub sindx 1 add mul sps div add   %% X-END
  585.                                 y0 y1 y0 sub sindx 1 add mul sps div add   %% Y-END
  586.                             ]
  587.                         } for
  588.                         dup /lseg exch def                  %% redefine current seg for eventual infrequent split
  589.                     } ifelse                        %% if no vertical line
  590.                     
  591.                 } ifelse                           %% one segment per line -> no splitting
  592.                 
  593.                 /counter counter rest add def     %% update counter
  594.                 counter dstlen ge                 %% time for infrequent split ?
  595.                 {
  596.                     pop                                     %% pop current line
  597.                     /x0 lseg 0 get def /y0 lseg 1 get def       %% get the points
  598.                     /x1 lseg 2 get def /y1 lseg 3 get def
  599.                     
  600.                     [ x0 y0 x0 x1 add 0.5 mul y0 y1 add 0.5 mul ]       %% und aus eins mach zwei...
  601.                     [ x0 x1 add 0.5 mul y0 y1 add 0.5 mul x1 y1 ]
  602.                     /counter counter dstlen sub def
  603.                 } if                                                    %% correct counter
  604.                 
  605.             } for                              %% end for all elements of dst
  606.         ]                                      %% push mark on stack and leave
  607.  
  608.         pro_procs { (\} splitlines) nlproto } if
  609.     end %% splitdict
  610. } def
  611.  
  612. %%
  613. %% array1 killsegs reduced-array1
  614. %%
  615. %% Diese Prozedur verringert die Anzahl der Liniensegmente in einem Array
  616. %% bei jedem Aufruf um etwas die Haelfte, indem fuer je zwei aufeinander-
  617. %% folgende Elemente des Arrays geprueft wird, ob sie zusammenhaengen.
  618. %%
  619. %% Es ist anzunehmen, das zwei Arrays die vor dem Aufruf gleichgross,
  620. %% es danach nicht mehr sind.
  621. %%
  622.  
  623. /KillDict 10 dict def
  624.  
  625. /killsegs
  626. {
  627.  
  628.     pro_procs { (killsegs \{) nlproto } if
  629.  
  630.     pro_params 
  631.     {           
  632.     (array1      = ) nlproto dup
  633.     pro_arrparams { prlines } { (\[ ) proto length proto ( \]) proto } ifelse
  634.     } if
  635.  
  636.     KillDict begin
  637.     /l1 4 array def
  638.     /l2 4 array def
  639.  
  640.     aload length dup /ka1l exch def 
  641.     array /ka1 exch def ka1 astore pop
  642.  
  643.     [           %% push start of array mark
  644.         /indx 0 def
  645.         {                %% Start loop
  646.         indx ka1l 1 sub ge { exit } if    %% leave if too big
  647.         ka1 indx get /l1 exch def
  648.         ka1 indx 1 add get /l2 exch def
  649.         l1 2 get l2 0 get eq        %% are the lines connected ?
  650.         l1 3 get l2 1 get eq and
  651.         {
  652.            [        %% create new line
  653.                l1 0 get
  654.                l1 1 get
  655.                l2 2 get
  656.                l2 3 get
  657.            ]   
  658.  
  659.             % pre-increment, to check the next plus one line segment
  660.             /indx indx 1 add def    
  661.         } if
  662.         /indx indx 1 add def        %% default : check next line
  663.         } loop        %% END LOOP
  664.     ]            %% push end of array marker
  665.     end
  666.  
  667.     (After killsegs : array = ) nlproto dup 
  668.     pro_arrparams { prlines } { (\[ ) proto length proto ( \]) proto } ifelse
  669.  
  670.     pro_procs { (\} killsegs) nlproto } if
  671.  
  672. } def      % end killsegs
  673.  
  674. %%
  675. %% color0 color1                    colors to interpolate between
  676. %% randomcolors                     choose all line colors by random
  677. %% array1 array2                    line segments to interpolate between
  678. %% mergesteps                       number of intermediate drawings
  679. %% merge -
  680. %%
  681. %% merge takes the number of steps to be generated and two arrays
  682. %% from the stack. The arrays have to contain the same number of
  683. %% line segments, i.e. they have the structure like the arrays
  684. %% generated by 'buildpath'.
  685. %% Then the number of steps is generated and the result is displayed.
  686.  
  687. /mergedict 20 dict def
  688.  
  689. /merge
  690. {
  691.     mergedict begin
  692.  
  693.         pro_procs { (merge \{) nlproto } if
  694.  
  695.         /msteps exch def                %% get parameters from stack
  696.  
  697.     %(\012 MERGE ) print 
  698.     %dup length 10 string cvs print ( , ) print exch
  699.     %dup length 10 string cvs print exch 
  700.  
  701.     % LINE SEGMENT KILLER - REDUCES THE # OF LINE SEGMENTS BY A FACTOR OF
  702.         % APPROXIMATELY 2 EVERY TIME IT IS CALLED...
  703.  
  704. %    killsegs exch killsegs exch
  705. %    killsegs exch killsegs exch
  706. %    killsegs exch killsegs exch
  707.     
  708.     % Groesse anpassen
  709.  
  710.     dup length /a2l exch def exch dup length /a1l exch def exch
  711.     a2l a1l gt { exch } if
  712.  
  713.     a1l a2l eq not { exch dup 3 -1 roll splitlines } if      %% correct # of lines
  714.  
  715.         %% It's not that easy to save arrays...
  716.  
  717.         aload length array /a2 exch def a2 astore pop
  718.  
  719.     % pro_params { (array before chaos = ) nlproto dup prlines } if
  720.  
  721.         aload length dup /a1len exch def array /a1 exch def
  722.         
  723.         chaotic                         %% this gets REALLY weired...
  724.         {
  725.             1 1 a1len                   %% could also be 0 1 any-value
  726.             {
  727.                 pop
  728.                 rand a1len mod          %% now points anywhere into the array
  729.                 1 roll                  %% and roll the array...
  730.             } for
  731.         } if
  732.  
  733.         a1 astore pop
  734.         
  735.         % pro_params { (array after chaos = ) nlproto a1 prlines } if
  736.  
  737.         /randomcolors exch def
  738.  
  739.  
  740.         aload length array /co1 exch def co1 astore pop
  741.         aload length array /co0 exch def co0 astore pop
  742.  
  743.  
  744.         pro_params
  745.         {
  746.             (color0      = ) nlproto co0 prpoints
  747.             (color1      = ) nlproto co1 prpoints
  748.             (randomcols  = ) nlproto randomcolors proto
  749.             (array1      = ) nlproto a1 
  750.             pro_arrparams 
  751.             { prlines } { (\[ ) proto length proto ( \]) proto } ifelse
  752.             (array2      = ) nlproto a2 
  753.             pro_arrparams 
  754.             { prlines } { (\[ ) proto length proto ( \]) proto } ifelse
  755.             (mergesteps  = ) nlproto msteps proto 
  756.         } if
  757.  
  758.         randomcolors not
  759.         {
  760.             /adds 3 array def               %% add values
  761.  
  762.             co0 aload length array /rgbcols exch def rgbcols astore pop
  763.             
  764.            
  765.             0 1 2       %% create array with interpolation steps
  766.             {
  767.                 /indx exch def
  768.                 adds indx
  769.                 co1 indx get
  770.                 co0 indx get
  771.                 sub
  772.                 msteps 2 add div put    %% effect : divide by 2 before div !
  773.             } for
  774.             
  775.             rgbcols mysetrgb                    %% set color
  776.  
  777.         } if
  778.  
  779.         randomcolors dup                %% if random desired, supply limits
  780.         { 
  781.             co0 co1 3 -1 roll
  782.         } if
  783.  
  784.     a1 drawarray                    %% display initial array
  785.         
  786.         /len a1 length def              %% define number of array elements
  787.         len a2 length eq not
  788.         { (FATAL ! Arrays do not have the same size (merge)\012)
  789.             nlproto exit } if
  790.  
  791.         1 1 msteps 1 add                %% loop parameters
  792.         {
  793.             msteps 2 add div /bary exch def     %% Only intermediate drawings 
  794.  
  795.         /tmpsave save def       %% TEST !
  796.  
  797.         randomcolors dup
  798.             {            
  799.                 co0 co1 3 -1 roll         %% random colors desired
  800.             }
  801.             {
  802.                 0 1 2 
  803.                 {
  804.                     /idx exch def
  805.                     rgbcols idx
  806.                     rgbcols idx get
  807.                     adds idx get add put
  808.                 } for
  809.                 rgbcols mysetrgb
  810.             } ifelse                     %% if no random desired
  811.  
  812.             [                            %% push mark
  813.                 0 1 len 1 sub            %% loop over array elements
  814.                 {
  815.                     /sindx exch def
  816.                     a1 sindx get                    % barycentric combination
  817.                     { bary mul } forall  [ 5  1 roll ]
  818.                     /ls1 exch def
  819.                     a2 sindx get 
  820.                     { 1 bary sub mul } forall [ 5  1 roll ]
  821.                     /ls2 exch def
  822.                     [
  823.                         ls1 0 get ls2 0 get add
  824.                         ls1 1 get ls2 1 get add
  825.                         ls1 2 get ls2 2 get add
  826.                         ls1 3 get ls2 3 get add
  827.                     ]
  828.                 } for           %% for all array elements
  829.             ]                   %% end of intermediate array
  830.             drawarray
  831.         tmpsave restore
  832.         } for                   %% for all intermediate steps
  833.  
  834.         randomcolors dup
  835.         {
  836.             co0 co1 3 -1 roll
  837.         }
  838.         {
  839.             co1 mysetrgb
  840.         } ifelse
  841.         a2 drawarray
  842.  
  843.         pro_procs { (\} merge) nlproto } if
  844.     end
  845. } def
  846.  
  847. %%
  848. %% parameters :
  849. %%
  850. %% color0 color1                    colors to interpolate between
  851. %% randomcolors                     choose all line colors by random
  852. %% fullscramble                     regard as word or character array
  853. %% basicsteps                       #characters regarded a unity
  854. %% scramblesteps                    number of intermediate stages 
  855. %% font1 font2                      fonts to be used
  856. %% size1 size2                      sizes of the fonts
  857. %% step1 step2                      space between the characters
  858. %% s1x s1y s2x s2y                  starting positions
  859. %% string1 string2 scramble -       strings to be scrambled
  860. %%
  861.  
  862. %% melts two strings together
  863.  
  864. %% NOTE (only valid if fullscramble is false, otherwise forget about it)
  865. %% The length of the strings need to hold the following condition:
  866. %% length(s1) = n*length(s2) or length(s2) = n*length(s1), where n = 1,2,... !
  867. %% If this is a problem for you just add spaces to one of the strings...
  868.  
  869. /scrambledict 30 dict def
  870.  
  871. /scramble
  872. {
  873.     /tmpsave save def
  874.  
  875.     scrambledict begin
  876.  
  877.         pro_procs { (scramble \{) nlproto } if
  878.  
  879.         /s2 exch def                            %% Get the strings
  880.         /s1 exch def
  881.         /s2y exch def /s2x exch def             %% and the other parms
  882.         /s1y exch def /s1x exch def
  883.         /step2 exch def /step1 exch def
  884.         /fsize2 exch def /fsize1 exch def
  885.         /fname2 exch def /fname1 exch def
  886.         /scramblesteps exch def
  887.         /basicsteps exch def
  888.         /fullscramble exch def
  889.         /randomcolors exch def
  890.  
  891.         aload length array /co1 exch def co1 astore pop
  892.         aload length array /co0 exch def co0 astore pop
  893.  
  894.         fullscramble not               %% Only do that if no full scrambling desired
  895.         {
  896.             s1 length s2 length lt            %% SWAP ?
  897.             {
  898.                 /s1 s2 /s2 s1 def def
  899.                 /s1x s2x /s2x s1x def def
  900.                 /s1y s2y /s2y s1y def def
  901.                 /co0 co1 /co1 co0 def def
  902.                 /step1 step2 /step2 step1 def def
  903.                 /fsize1 fsize2 /fsize2 fsize1 def def
  904.             } if
  905.         } if    
  906.         
  907.  
  908.         pro_params
  909.         {
  910.             (color0  = ) nlproto co0 prpoints
  911.             (color1  = ) nlproto co1 prpoints
  912.             (randomc = ) nlproto randomcolors proto
  913.             (scrstep = ) nlproto scramblesteps proto
  914.             (fullscr = ) nlproto fullscramble proto
  915.             (basicst = ) nlproto basicsteps proto
  916.             (step1   = ) nlproto step1 proto
  917.             (step2   = ) nlproto step2 proto
  918.             (fsize1  = ) nlproto fsize1 proto
  919.             (fsize2  = ) nlproto fsize2 proto
  920.             (s1      = ) nlproto s1 proto
  921.             (s2      = ) nlproto s2 proto
  922.             (CHAOS   = ) nlproto chaotic proto
  923.         } if
  924.  
  925.         0 1  %% loop over the shorter string
  926.         
  927.         fullscramble                           %% this is a little easier
  928.         {    
  929.             /intlen1 s1 length def             %% Interval == full string
  930.             /intlen2 s2 length def
  931.             /basicstep 1 def                   %% basic step interval
  932.             0                                  %% END value for loop
  933.         }
  934.         {
  935.             /intlen1 s1 length                  %% raw interval length in longer string
  936.             s2 length div cvi def
  937.             /intlen2 basicstep def              %% and in shorter string
  938.             s2 length basicstep div 1 sub cvi   %% END value for loop
  939.         } ifelse
  940.         
  941.         {
  942.             /indx exch def                               %% get loop control value
  943.  
  944.             fname1 fsize1 ssetfont                       %% select 1st font
  945.             s1 indx intlen1 basicstep mul mul            %% start index
  946.             intlen1 basicstep mul                        %% length of substring
  947.             getinterval                                  %% get current segment of first string
  948.             dup step1 s1x s1y buildpath                  %% Duplicate string segment for later calc
  949.  
  950.             aload length dup /a1len exch def             %% Set a1 to
  951.             array /a1 exch def a1 astore pop             %% new value
  952.  
  953.             dup length step1 mul exch                    %% Remember the step!
  954.             stringwidth pop s1x add add /s1x exch def    %% Calculate start position for next string
  955.  
  956.             fname2 findfont fsize2 scalefont setfont     %% select 2nd font
  957.             s2 indx intlen2 mul 
  958.             intlen2 getinterval                          %% get current segment of 2nd string
  959.             dup step2 s2x s2y buildpath                  %% Build path of character(s)
  960.  
  961.             aload length dup /a2len exch def             %% Set a1 to
  962.             array /a2 exch def a2 astore pop             %% new value
  963.  
  964.             dup length step2 mul exch
  965.             stringwidth pop s2x add add /s2x exch def    %% Calculate start position for next string
  966.  
  967.             a1len a2len eq not
  968.             {
  969.                 a1len a2len gt 
  970.                 { 
  971.                     a1 a2 splitlines 
  972.                     aload length dup /a2len exch def
  973.                     array /a2 exch def a2 astore pop
  974.                 } 
  975.                 { 
  976.                     a2 a1 splitlines 
  977.                     aload length dup /a1len exch def
  978.                     array /a1 exch def a1 astore pop 
  979.                 }
  980.                 ifelse
  981.             } if
  982.  
  983.             co0 co1 randomcolors
  984.             a1 a2 scramblesteps merge       %% Merge the line segments on their ways !
  985.             
  986.         } for          %% Outer Loop, getting the substrings of the texts to be melted
  987.  
  988.     pro_procs { (\} scramble) nlproto } if
  989.     end         %% pop scrambledict dictionary
  990.     tmpsave restore
  991. } def           %% end scramble
  992.  
  993.  
  994. %%
  995. %% fname size ssetfont - 
  996. %%
  997. %% selects the current font (fname) in the given size and stores the size
  998. %% in the global variable fsize.
  999. %%
  1000.  
  1001. /ssetfont
  1002. {
  1003.     pro_procs { (ssetfont \{) nlproto } if
  1004.     pro_params 
  1005.     { 
  1006.         (fname     = ) nlproto exch dup proto
  1007.         (fsize     = ) nlproto exch dup proto 
  1008.     } if
  1009.  
  1010.  
  1011.     /fsize exch def
  1012.     findfont fsize scalefont setfont
  1013.     pro_procs { (\} ssetfont) nlproto } if
  1014. } def
  1015.  
  1016.  
  1017. %%
  1018. %% [ red green blue ] mysetrgb -
  1019. %%
  1020. %% Setzt die angegebene Farbe, falls use_color true ist.
  1021. %% Andernfalls wird ein korrespondierender Grauwert ausgerechnet.
  1022. %%
  1023.  
  1024. /myrgbdict 10 dict def
  1025.  
  1026. /mysetrgb
  1027. {
  1028.     myrgbdict begin
  1029.         pro_mysetrgb { (mysetrgb \{) nlproto } if
  1030.         pro_mysetrgb { (colorvec  = ) nlproto dup prpoints } if
  1031.         
  1032.         aload pop
  1033.         use_colors
  1034.         { setrgbcolor }
  1035.         { 0.114 mul 3 1 roll 0.587 mul 3 1 roll 0.299 mul add add setgray } 
  1036.         ifelse
  1037.         pro_mysetrgb { (\} mysetrgb) nlproto } if
  1038.     end
  1039. } def
  1040.  
  1041.  
  1042. % MYFONT!!!
  1043. /reencsmalldict 12 dict def
  1044. /ReEncodeSmall
  1045.  {
  1046.  reencsmalldict begin
  1047.  /newcodesandnames exch def
  1048.  /newfontname exch def
  1049.  /basefontname exch def
  1050.  
  1051.  /basefontdict basefontname findfont def
  1052.  /newfont basefontdict maxlength dict def
  1053.  
  1054.  basefontdict
  1055.  {
  1056.   exch dup /FID ne
  1057.   {
  1058.    dup /Encoding eq
  1059.    { exch dup length array copy
  1060.      newfont 3 1 roll put }
  1061.    { exch newfont 3 1 roll put }
  1062.    ifelse
  1063.   }
  1064.   { pop pop }
  1065.   ifelse
  1066.  } forall
  1067.  
  1068.  newfont /FontName newfontname put
  1069.  newcodesandnames aload pop
  1070.  newcodesandnames length 2 idiv
  1071.  { newfont /Encoding get 3 1 roll put } repeat
  1072.  newfontname newfont definefont pop
  1073.  end
  1074. } def
  1075.  
  1076. /germanvec [
  1077.  8#300 /adieresis
  1078.  8#311 /Adieresis
  1079.  8#321 /odieresis
  1080.  8#322 /Odieresis
  1081.  8#323 /udieresis
  1082.  8#324 /Udieresis
  1083.  8#325 /germandbls
  1084. ] def
  1085.  
  1086. %% Deutsche Umlaute kodieren
  1087.  
  1088. /Umlaute
  1089. {
  1090.  /Times-Roman /Times-Roman-German germanvec ReEncodeSmall
  1091. } def
  1092.  
  1093. % prints addresses on the border
  1094.  
  1095. /info_frame
  1096. {
  1097.     persfont 7 ssetfont
  1098.     gsave
  1099.     -6 0 translate
  1100.     newpath
  1101.     90 rotate
  1102.     0 0 moveto
  1103.     (SCRAMBLE (C) 1992 by Patsch - send \
  1104. suggestions, bugs to dockhorn@fzi.de) show
  1105.     grestore
  1106. } def
  1107.  
  1108.  
  1109.  
  1110. %%
  1111. %% - scramble_demo -
  1112. %%
  1113. %% shows usage of scramble algorithm
  1114. %%
  1115.  
  1116. /sagedict 10 dict def
  1117.  
  1118. /scramble_demo
  1119. {
  1120.     sagedict begin                   %% limit scope of variables
  1121.  
  1122.     /t1 (PostScript) def
  1123.     /t2 (is funny !) def
  1124.  
  1125.         pro_procs { (scramble_demo \{) nlproto } if
  1126.  
  1127.     persfont perssize ssetfont      %% set font name and size
  1128.  
  1129.     %% begin scramble parametrization
  1130.  
  1131.         rcolor0 rcolor1 funny           %% random colours ?
  1132.         fullscramble 1 14        %% scramble mode & # of steps
  1133.         persfont persfont        %% font names
  1134.     perssize perssize        %% font sizes
  1135.     0 0                %% step sizes
  1136.     t1 stringwidth pop
  1137.     neg A4w add 2 div             %% center strings
  1138.     ph perssize dup add sub             %% upper position
  1139.     t2 stringwidth pop
  1140.     neg A4w add 2 div 0            %% lower position
  1141.     t1 t2                  %% the names
  1142.     scramble            %% do it !
  1143.  
  1144.         pro_procs { (\} scramble_demo) nlproto } if
  1145.     end
  1146. } def
  1147.  
  1148.  
  1149. %%
  1150. %% main program
  1151. %%
  1152.  
  1153.  
  1154. (main \{) nlproto                % start main procedure
  1155.  
  1156. Umlaute                 % Activate german font
  1157.  
  1158. xoff yoff translate         % basic settings  
  1159. 0 setlinewidth
  1160.  
  1161. info_frame                       % draw comments
  1162.  
  1163. scramble_demo                 % demonstrate algorithm
  1164.  
  1165. showpage
  1166.  
  1167. (\} main) nlproto                % end main procedure
  1168.  
  1169. %% END OF FILE
  1170.  
  1171.