home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Science / RasMol2 / outfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-28  |  53.3 KB  |  2,355 lines  |  [TEXT/KAHL]

  1. /* outfile.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, October 1994
  4.  * Version 2.5
  5.  */
  6. #define OUTFILE
  7. #include "rasmol.h"
  8.  
  9. #ifdef IBMPC
  10. #include <windows.h>
  11. #include <malloc.h>
  12. #endif
  13. #ifdef APPLEMAC
  14. #ifdef __CONDITIONALMACROS__
  15. #include <Printing.h>
  16. #else
  17. #include <PrintTraps.h>
  18. #endif
  19. #include <Types.h>
  20. #endif
  21. #ifndef sun386
  22. #include <stdlib.h>
  23. #endif
  24.  
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include <math.h>
  28.  
  29. #include "outfile.h"
  30. #include "molecule.h"
  31. #include "command.h"
  32. #include "abstree.h"
  33. #include "transfor.h"
  34. #include "render.h"
  35. #include "graphics.h"
  36. #include "pixutils.h"
  37. #include "script.h"
  38.  
  39.  
  40. #ifdef EIGHTBIT
  41. #define RComp(x)   (RLut[LutInv[x]])
  42. #define GComp(x)   (GLut[LutInv[x]])
  43. #define BComp(x)   (BLut[LutInv[x]])
  44. #else
  45. #define RComp(x)   (((x)>>16)&0xff)
  46. #define GComp(x)   (((x)>>8)&0xff)
  47. #define BComp(x)   ((x)&0xff)
  48. #endif
  49.  
  50.  
  51. #ifdef INVERT
  52. #define InvertY(y) (y)
  53. #else
  54. #define InvertY(y) (-(y))
  55. #endif
  56.  
  57.  
  58. /* Sun rasterfile.h macro defns */
  59. #define RAS_MAGIC       0x59a66a95
  60. #define RAS_RLE         0x80
  61. #define RT_STANDARD     1
  62. #define RT_BYTE_ENCODED 2
  63. #define RMT_NONE        0
  64. #define RMT_EQUAL_RGB   1
  65.  
  66. /* Standard A4 size page: 8.267x11.811 inches */
  67. /* U.S. Normal size page: 8.500x11.000 inches */
  68. #define PAGEHIGH  (11.811*72.0)
  69. #define PAGEWIDE  (8.267*72.0)
  70. #define BORDER    0.90
  71.  
  72. /* Compression Ratio   0<x<127 */
  73. #define EPSFCompRatio  32
  74.  
  75. #define Round(x)       ((int)(x))
  76.  
  77.  
  78. #define PSLine    0x00
  79. #define PSStick   0x01
  80. #define PSSphere  0x02
  81. #define PSRibbon  0x03
  82.  
  83. typedef void __far* PSItemPtr;
  84.  
  85.  
  86. #if defined(IBMPC) || defined(APPLEMAC)
  87. static short __far *ABranch;
  88. static short __far *DBranch;
  89. static short __far *Hash;
  90. static Byte __far *Node;
  91. #else
  92. static short ABranch[4096];
  93. static short DBranch[4096];
  94. static short Hash[256];
  95. static Byte Node[4096];
  96. #endif
  97.  
  98.  
  99. /* Apple PICT macros */
  100. #define PICTcliprgn         0x0001
  101. #define PICTpicversion      0x0011
  102. #define PICTpackbitsrect    0x0098
  103. #define PICTdirectbitsrect  0x009a
  104. #define PICTendofpict       0x00ff
  105. #define PICTheaderop        0x0c00
  106.  
  107. static Byte PICTBuffer[128];
  108. static Byte PICTPixel;
  109.  
  110. typedef struct {
  111.     Byte len;
  112.     Byte ch;
  113.     } BMPPacket;
  114.     
  115.  
  116. static BMPPacket BMPBuffer[10];
  117. static int BMPCount,BMPTotal;        
  118. static int BMPPad;
  119.  
  120. static int GIFClrCode; 
  121. static int GIFEOFCode;
  122.  
  123. static Card RLEFileSize;
  124. static int RLEEncode;
  125. static int RLEOutput;
  126. static int RLELength;
  127. static int RLEPixel;
  128. static int RLEChar;
  129.  
  130.  
  131. static Byte Buffer[256];
  132. static Byte LutInv[256];
  133. static int LineLength;
  134. static FILE *OutFile;
  135. static Card BitBuffer;
  136. static int BitBufLen;
  137. static int PacketLen;
  138. static int CodeSize;
  139.  
  140. static Real LineWidth;
  141. static int VectSolid;
  142. static int VectCol;
  143.  
  144. /* Macros for commonly used loops */
  145. #define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
  146.              for(group=chain->glist;group;group=group->gnext)    \
  147.              for(aptr=group->alist;aptr;aptr=aptr->anext)
  148. #define ForEachBond  for(bptr=Database->blist;bptr;bptr=bptr->bnext)
  149. #define ForEachBack  for(chain=Database->clist;chain;chain=chain->cnext) \
  150.              for(bptr=chain->blist;bptr;bptr=bptr->bnext)
  151.  
  152.  
  153.  
  154. #ifdef APPLEMAC
  155. /* External RasMac Function Declaration! */
  156. void SetFileInfo( char*, OSType, OSType, short );
  157. #endif
  158.  
  159. static void FatalOutputError( ptr )
  160.     char *ptr;
  161. {
  162.     if( CommandActive ) WriteChar('\n');
  163.     WriteString("Output Error: Unable to create file `");
  164.     WriteString( ptr );  WriteString("'!\n");
  165.     CommandActive = False;
  166. }
  167.  
  168.  
  169. /*  Integer Output Routines  */
  170. #ifdef FUNCPROTO
  171. static void WriteLSBLong( Card );
  172. static void WriteMSBLong( Card );
  173. #endif
  174.  
  175. static void WriteLSBShort( val )
  176.     int val;
  177. {
  178.     putc( val&0xff, OutFile );
  179.     putc( (val>>8)&0xff, OutFile );
  180. }
  181.  
  182. static void WriteMSBShort( val )
  183.     int val;
  184. {
  185.     putc( (val>>8)&0xff, OutFile );
  186.     putc( val&0xff, OutFile );
  187. }
  188.  
  189. static void WriteLSBLong( val )
  190.     Card val;
  191. {
  192.     putc((int)(val&0xff),OutFile);
  193.     putc((int)((val>>8) &0xff),OutFile);
  194.     putc((int)((val>>16)&0xff),OutFile);
  195.     putc((int)((val>>24)&0xff),OutFile);
  196. }
  197.  
  198. static void WriteMSBLong( val )
  199.     Card val;
  200. {
  201.     putc((int)((val>>24)&0xff),OutFile);
  202.     putc((int)((val>>16)&0xff),OutFile);
  203.     putc((int)((val>>8) &0xff),OutFile);
  204.     putc((int)(val&0xff),OutFile);
  205. }
  206.  
  207.  
  208.  
  209.  
  210. static void WritePPMWord( i )
  211.     int i;
  212. {
  213.     if( i>99 )
  214.     {   fputc((i/100)+'0',OutFile); i %= 100;
  215.     fputc((i/10) +'0',OutFile); i %= 10;
  216.     } else if( i>9 )
  217.     {   fputc((i/10)+'0',OutFile);  i %= 10;
  218.     }
  219.     putc(i+'0',OutFile);
  220. }
  221.  
  222.  
  223. int WritePPMFile( name, raw )
  224.     char *name;  int raw;
  225. {
  226.     register Pixel __huge *ptr;
  227.     register int i, c;
  228.     register int x,y;
  229.  
  230. #if defined(IBMPC) || defined(APPLEMAC)
  231.     OutFile = fopen(name, (raw?"wb":"w") );
  232. #else
  233.     OutFile = fopen(name,"w");
  234. #endif
  235.  
  236.     if( !OutFile ) 
  237.     {   FatalOutputError(name);
  238.     return( False );
  239.     }
  240.     fputc('P',OutFile); fputc((raw?'6':'3'),OutFile);
  241.     fprintf(OutFile," %d %d 255\n",XRange,YRange);
  242.  
  243. #ifdef EIGHTBIT
  244.     for( i=0; i<256; i++ )
  245.     if( ULut[i] )
  246.         LutInv[Lut[i]] = i;
  247. #endif
  248.  
  249. #ifdef IBMPC
  250.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  251. #endif
  252.  
  253. #ifndef INVERT
  254.     ptr = FBuffer;
  255. #endif
  256.  
  257.     c = 0;
  258.  
  259.     if( !raw )
  260.     {   c = 0;
  261.     for( y=YRange-1; y>=0; y-- )
  262.     {
  263. #ifdef INVERT
  264.         ptr = FBuffer + (Long)y*XRange;
  265. #endif
  266.         for( x=0; x<XRange; x++ )
  267.         {   i = *ptr++; c++;
  268.         WritePPMWord((int)RComp(i));  fputc(' ',OutFile);
  269.         WritePPMWord((int)GComp(i));  fputc(' ',OutFile);
  270.         WritePPMWord((int)BComp(i));  
  271.         if( c==5 )
  272.         { c=0; fputc('\n',OutFile);
  273.         } else fputc(' ',OutFile);
  274.         }
  275.     }
  276.     } else
  277.     for( y=YRange-1; y>=0; y-- )
  278.     {
  279. #ifdef INVERT
  280.         ptr = FBuffer + (Long)y*XRange;
  281. #endif
  282.         for( x=0; x<XRange; x++ )
  283.         {   i = *ptr++;
  284.         fputc((int)RComp(i),OutFile);
  285.         fputc((int)GComp(i),OutFile);
  286.         fputc((int)BComp(i),OutFile);
  287.         }
  288.     }
  289.  
  290.     fclose(OutFile);
  291. #ifdef APPLEMAC
  292.     /* Avoid ANSI trigraph problems! */
  293.     SetFileInfo(name,'\?\?\?\?','\?\?\?\?',134);
  294. #endif
  295. #ifdef IBMPC
  296.     GlobalUnlock(FBufHandle); 
  297. #endif
  298.     return( True );
  299. }
  300.  
  301.  
  302.  
  303. #ifdef EIGHTBIT
  304. static int CompactColourMap()
  305. {
  306.     register Pixel __huge *ptr;
  307.     register Long pos, count;
  308.     register int i, cols;
  309.  
  310.     for( i=0; i<256; i++ )
  311.     {   if( ULut[i] )
  312.         LutInv[Lut[i]] = i;
  313.     Buffer[i] = 0;
  314.     Node[i] = 5;
  315.     }
  316.  
  317. #ifdef IBMPC
  318.     ptr = (Pixel __huge*)GlobalLock(FBufHandle);    
  319. #else
  320.     ptr = FBuffer;
  321. #endif
  322.  
  323.     cols = 0;
  324.     count = (Long)XRange*YRange;
  325.     for( pos=0; pos<count; pos++ )
  326.     {   i = LutInv[*ptr++];
  327.     if( !Buffer[i] ) 
  328.     {   Node[cols++] = i;
  329.         Buffer[i] = cols;
  330.     }
  331.     }
  332.  
  333.     for( i=0; i<256; i++ )
  334.     LutInv[i] = Buffer[LutInv[i]]-1;
  335. #ifdef IBMPC
  336.     GlobalUnlock(FBufHandle);
  337. #endif
  338.     return( cols );
  339. }
  340. #endif
  341.  
  342.  
  343.  
  344. static void WriteGIFCode( code )
  345.     int code;
  346. {
  347.     register int max;
  348.  
  349.     max = (code==GIFEOFCode)? 0 : 7;
  350.     BitBuffer |= ((Card)code<<BitBufLen);
  351.     BitBufLen += CodeSize;
  352.  
  353.     while( BitBufLen > max )
  354.     {    
  355. #ifdef IBMPC
  356.      Buffer[PacketLen++]=(Byte)(BitBuffer&0xff);
  357. #else
  358.      Buffer[PacketLen++]=BitBuffer;
  359. #endif
  360.      BitBuffer >>= 8;
  361.      BitBufLen -= 8;
  362.  
  363.     if( PacketLen==255 )
  364.     {   fputc(0xff,OutFile);
  365.         fwrite((char*)Buffer,1,255,OutFile);
  366.         PacketLen = 0;
  367.     }
  368.     }
  369. }
  370.  
  371. int WriteGIFFile( name )
  372.     char *name;
  373. {
  374.     register int i,j,cols;
  375.     register int pref,next,last;
  376.     register int isize, ilast;
  377.     register Pixel __huge *ptr;
  378.     register short __far *prev;
  379.     register int x,y,init;
  380.  
  381. #ifdef EIGHTBIT
  382.     cols = CompactColourMap();
  383.     if( cols<2 ) return( False );
  384.  
  385.     for( isize=0; isize<8; isize++ )
  386.     if( (1<<isize)>=cols ) break;
  387.     cols = 1<<isize;
  388.  
  389. #if defined(IBMPC) || defined(APPLEMAC)
  390.     OutFile = fopen(name,"wb");
  391. #else
  392.     OutFile = fopen(name,"w");
  393. #endif
  394.     if( !OutFile ) 
  395.     {    FatalOutputError(name);
  396.      return( False );
  397.     }
  398.     fwrite("GIF87a",1,6,OutFile);
  399.     WriteLSBShort(XRange);
  400.     WriteLSBShort(YRange);
  401.     fputc(0xf0|(isize-1),OutFile); 
  402.     fputc(0x00,OutFile); 
  403.     fputc(0x00,OutFile);
  404.  
  405.     for( j=0; j<cols; j++ )
  406.     {   i = Node[j];
  407.     fputc((int)RLut[i],OutFile);
  408.     fputc((int)GLut[i],OutFile);
  409.     fputc((int)BLut[i],OutFile);
  410.     }
  411.  
  412.     fputc(',',OutFile);
  413.     fputc(0x00,OutFile);  fputc(0x00,OutFile);
  414.     fputc(0x00,OutFile);  fputc(0x00,OutFile);
  415.     WriteLSBShort(XRange);
  416.     WriteLSBShort(YRange);
  417.     fputc(0x00,OutFile);  fputc(isize,OutFile);
  418.  
  419.     PacketLen=0;
  420.     BitBuffer=0;
  421.     BitBufLen=0;
  422.  
  423.     GIFClrCode = (1<<isize);
  424.     GIFEOFCode = GIFClrCode+1;
  425.     ilast = (GIFClrCode<<1)-GIFEOFCode;
  426.     isize++;
  427.  
  428.     CodeSize = isize;
  429.     last = ilast;
  430.     next = 1;  
  431.    
  432.     WriteGIFCode(GIFClrCode);
  433.     for( i=0; i<cols; i++ )
  434.     Hash[i]=0;
  435.  
  436. #ifdef IBMPC
  437.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);    
  438. #endif
  439.  
  440. #ifndef INVERT
  441.     ptr = FBuffer;
  442. #endif
  443.  
  444.     /* Avoid Warnings! */
  445.     prev = (short __far*)0; 
  446.     pref = 0;
  447.  
  448.     init = False;
  449.     for( y=YRange-1; y>=0; y-- )
  450.     {   
  451. #ifdef INVERT
  452.     ptr = FBuffer + (Long)y*XRange;
  453. #endif
  454.     for( x=0; x<XRange; x++ )
  455.     {   if( !init )
  456.         {   pref = LutInv[*ptr++];
  457.         prev = Hash+pref;
  458.         init = True;
  459.         continue;
  460.         }
  461.  
  462.         i = LutInv[*ptr++];
  463.  
  464.         while( *prev && (Node[*prev] != (Byte)i) )
  465.         prev = ABranch+*prev;
  466.  
  467.         if( *prev )
  468.         {   pref = *prev+GIFEOFCode;
  469.         prev = DBranch+*prev;
  470.         } else
  471.         {   WriteGIFCode(pref);
  472.         if( next==last )
  473.         {   if( CodeSize==12 )
  474.             {   WriteGIFCode(GIFClrCode);
  475.             pref = i;  prev = Hash+i;
  476.             for( i=0; i<cols; i++ )
  477.                 Hash[i] = 0;
  478.             CodeSize = isize;
  479.             last = ilast;
  480.             next = 1; 
  481.             continue;
  482.             }
  483.             last = (last<<1)+GIFEOFCode;
  484.             CodeSize++;
  485.         }
  486.         *prev = next;
  487.         ABranch[next] = 0;
  488.         DBranch[next] = 0;
  489.         Node[next] = i;
  490.         prev = Hash+i;
  491.         pref = i;
  492.         next++;
  493.         }
  494.     }
  495.     }
  496.  
  497.  
  498.     WriteGIFCode(pref);
  499.     WriteGIFCode(GIFEOFCode);
  500.     if( PacketLen )
  501.     {   fputc(PacketLen,OutFile);
  502.     fwrite((char*)Buffer,1,PacketLen,OutFile);
  503.     }
  504.  
  505.     fputc(0x00,OutFile);
  506.     fputc(';',OutFile);
  507.     fclose(OutFile);
  508.  
  509. #ifdef APPLEMAC
  510.     /* Avoid ANSI trigraph problems! */
  511.     SetFileInfo(name,'\?\?\?\?','GIFf',134);
  512. #endif
  513. #ifdef IBMPC
  514.     GlobalUnlock(FBufHandle);
  515. #endif
  516.     return( True );
  517. #else
  518.     if( CommandActive ) WriteChar('\n');
  519.     WriteString("Output Error: 24 bit GIF files unsupported!\n");
  520.     CommandActive = False;
  521.     return( False );
  522. #endif
  523. }
  524.  
  525.  
  526.  
  527. static void FlushRastRLE()
  528. {
  529.     if( RLEChar==RAS_RLE )
  530.     {   if( RLEOutput )
  531.     {   fputc(RAS_RLE,OutFile);
  532.         fputc(RLELength-1,OutFile);
  533.         if( RLELength!=1 )
  534.         fputc(RAS_RLE,OutFile);
  535.     } else RLEFileSize += (RLELength>1)? 3 : 2;
  536.     } else
  537.     if( RLEOutput )
  538.     {   if( RLELength>2 )
  539.         {   fputc(RAS_RLE,OutFile);
  540.         fputc(RLELength-1,OutFile);
  541.         } else if( RLELength==2 )
  542.         fputc(RLEChar,OutFile);
  543.         fputc(RLEChar,OutFile);
  544.     } else RLEFileSize += MinFun(RLELength,3);
  545. }
  546.  
  547.  
  548. static void WriteRastRLECode( val )
  549.     int val;
  550. {
  551.     if( RLEEncode )
  552.     {   if( !RLELength )
  553.     {   RLELength = 1;
  554.         RLEChar = val;
  555.     } else
  556.         if( (RLEChar!=val) || (RLELength==256) )
  557.         {   FlushRastRLE();
  558.         RLELength = 1;
  559.         RLEChar = val;
  560.         } else
  561.         RLELength++;
  562.     } else
  563.     fputc(val,OutFile);
  564. }
  565.  
  566. static void WriteRastRLEPad()
  567. {
  568.     if( RLEEncode )
  569.     {   if( !RLELength || (RLELength==256) )
  570.     {   WriteRastRLECode(0x00);
  571.     } else RLELength++;
  572.     } else fputc(0x00,OutFile);
  573. }
  574.  
  575.  
  576. static void WriteRastData( output )
  577.     int output;
  578. {
  579.     register Pixel __huge *ptr;
  580.     register int x,y,pad;
  581. #ifndef EIGHTBIT
  582.     register int i;
  583. #endif
  584.  
  585. #ifdef IBMPC
  586.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  587. #endif
  588.  
  589. #ifndef INVERT
  590.     ptr = FBuffer;
  591. #endif
  592.  
  593.     pad = XRange%2;
  594.  
  595.     RLEOutput = output;
  596.     RLEFileSize = 0;
  597.     RLELength = 0;
  598.  
  599.     for( y=YRange-1; y>=0; y-- )
  600.     {   
  601. #ifdef INVERT
  602.     ptr = FBuffer + (Long)y*XRange;
  603. #endif
  604.     for( x=0; x<XRange; x++ )
  605. #ifndef EIGHTBIT
  606.     {   i = *ptr++;
  607.         WriteRastRLECode((int)BComp(i));
  608.         WriteRastRLECode((int)GComp(i));
  609.         WriteRastRLECode((int)RComp(i));
  610.     }
  611. #else
  612.         WriteRastRLECode((int)LutInv[*ptr++]);
  613. #endif
  614.     if( pad ) WriteRastRLEPad();
  615.     }
  616.  
  617.     if( RLEEncode && RLELength )
  618.     FlushRastRLE();
  619. #ifdef IBMPC
  620.     GlobalUnlock(FBufHandle);
  621. #endif
  622. }
  623.  
  624.  
  625.  
  626. int WriteRastFile( name, encode )
  627.     char *name;
  628.     int encode;
  629. {
  630.     register int i,size,cols;
  631.  
  632. #if defined(IBMPC) || defined(APPLEMAC)
  633.     OutFile = fopen(name,"wb");
  634. #else
  635.     OutFile = fopen(name,"w");
  636. #endif
  637.  
  638.     if( !OutFile )
  639.     {   FatalOutputError(name);
  640.     return(False);
  641.     }
  642.     WriteMSBLong( RAS_MAGIC );
  643.     WriteMSBLong(XRange);  
  644.     WriteMSBLong(YRange);
  645.     RLEEncode = encode;
  646.  
  647.  
  648. #ifdef EIGHTBIT
  649.     WriteMSBLong(8);
  650.  
  651.     if( encode )
  652.     {   WriteRastData(False);
  653.     WriteMSBLong(RLEFileSize);
  654.     WriteMSBLong(RT_BYTE_ENCODED);
  655.     } else
  656.     {   size = (XRange%2)? XRange+1 : XRange;
  657.     WriteMSBLong(size*YRange);
  658.     WriteMSBLong(RT_STANDARD);
  659.     }
  660.  
  661.     cols = CompactColourMap();
  662.     WriteMSBLong(RMT_EQUAL_RGB);
  663.     WriteMSBLong(cols*3);
  664.  
  665.     for( i=0; i<cols; i++ ) fputc((int)RLut[Node[i]],OutFile);
  666.     for( i=0; i<cols; i++ ) fputc((int)GLut[Node[i]],OutFile);
  667.     for( i=0; i<cols; i++ ) fputc((int)BLut[Node[i]],OutFile);
  668. #else
  669.     WriteMSBLong(24);
  670.  
  671.     if( encode )
  672.     {   WriteRastData(False);
  673.     WriteMSBLong(RLEFileSize);
  674.     WriteMSBLong(RT_BYTE_ENCODED);
  675.     } else
  676.     {   size = XRange*3;
  677.     if( size&1 ) size++;
  678.     WriteMSBLong(size*YRange);
  679.     WriteMSBLong(RT_STANDARD);
  680.     }
  681.     WriteMSBLong(RMT_NONE);
  682.     WriteMSBLong(0);
  683. #endif
  684.  
  685.     WriteRastData(True);
  686.     fclose( OutFile );
  687. #ifdef APPLEMAC
  688.     /* Avoid ANSI trigraph problems! */
  689.     SetFileInfo(name,'\?\?\?\?','\?\?\?\?',134);
  690. #endif
  691.     return( True );
  692. }
  693.  
  694.  
  695. static void OutputEPSFByte( val )
  696.     int val;
  697. {
  698.     register int i;
  699.  
  700.     i = val/16;  fputc( (i>9)? (i-10)+'A' : i+'0', OutFile );
  701.     i = val%16;  fputc( (i>9)? (i-10)+'A' : i+'0', OutFile );
  702.     if( (LineLength+=2) > 72 )
  703.     {   fputc('\n',OutFile);
  704.     LineLength = 0;
  705.     }
  706. }
  707.  
  708. static void EncodeEPSFPixel( val, col )
  709.     int val, col;
  710. {
  711.     register int r, g, b;
  712.     register int i;
  713.  
  714.     r = RComp(val);
  715.     g = GComp(val);
  716.     b = BComp(val);
  717.  
  718.     if( col )
  719.     {   OutputEPSFByte( r );
  720.     OutputEPSFByte( g );
  721.     OutputEPSFByte( b );
  722.     } else
  723.     {   i = (20*r + 32*g + 12*b)>>6;
  724.     OutputEPSFByte( i );
  725.     }
  726. }
  727.  
  728. int WriteEPSFFile( name, col, compr )
  729.     char *name;  int col, compr;
  730. {
  731.     register int xpos, ypos;
  732.     register int xsize, ysize;
  733.     register int rotpage;
  734.     register int x, y, i, j;
  735.  
  736.     register Pixel __huge *ptr;
  737.     int RLEBuffer[128];
  738.  
  739. #ifdef EIGHTBIT
  740.     for( i=0; i<256; i++ )
  741.     if( ULut[i] )
  742.         LutInv[Lut[i]] = i;
  743. #endif
  744.  
  745.     OutFile = fopen(name,"w");
  746.     if( !OutFile )
  747.     {   FatalOutputError(name);
  748.     return(False);
  749.     }
  750.  
  751.     if( XRange <= YRange )
  752.     {   rotpage = False; 
  753.     xsize = XRange; 
  754.     ysize = YRange;
  755.     } else
  756.     {   rotpage = True;  
  757.     xsize = YRange; 
  758.     ysize = XRange;
  759.     }
  760.  
  761.     if( xsize > (int)(BORDER*PAGEWIDE) )
  762.     {   ysize = (int)(ysize*(BORDER*PAGEWIDE)/xsize);
  763.     xsize = (int)(BORDER*PAGEWIDE);
  764.     }
  765.     if( ysize > (int)(BORDER*PAGEHIGH) )
  766.     {   xsize = (int)(xsize*(BORDER*PAGEHIGH)/ysize);
  767.     ysize = (int)(BORDER*PAGEHIGH);
  768.     }
  769.  
  770.     xpos = (int)(PAGEWIDE-xsize)/2;
  771.     ypos = (int)(PAGEHIGH-ysize)/2;
  772.  
  773.     fputs("%!PS-Adobe-2.0 EPSF-2.0\n",OutFile);
  774.     fputs("%%Creator: RasMol Version 2.5\n",OutFile);
  775.     fprintf(OutFile,"%%%%Title: %s\n",name);
  776.     fprintf(OutFile,"%%%%BoundingBox: %d %d ",xpos,ypos);
  777.     fprintf(OutFile,"%d %d\n",xpos+xsize,ypos+ysize);
  778.  
  779.     fputs("%%Pages: 1\n",OutFile);
  780.     fputs("%%EndComments\n",OutFile);
  781.     fputs("%%EndProlog\n",OutFile);
  782.     fputs("%%Page: 1 1\n",OutFile);
  783.  
  784.     fputs("gsave\n",OutFile);
  785.     fputs("10 dict begin\n",OutFile);
  786.     fprintf(OutFile,"%d %d translate\n",xpos,ypos);
  787.     fprintf(OutFile,"%d %d scale\n",xsize,ysize);
  788.     if( rotpage )
  789.     {   fputs("0.5 0.5 translate\n",OutFile);
  790.     fputs("90 rotate\n",OutFile);
  791.     fputs("-0.5 -0.5 translate\n",OutFile);
  792.     }
  793.     fputc('\n',OutFile);
  794.  
  795.     if( compr )
  796.     {   fputs("/rlecount 0 def\n",OutFile);
  797.     fputs("/rlebyte 1 string def\n",OutFile);
  798.     fprintf(OutFile,"/pixbuf %d string def\n", col?3:1 );
  799.     fputs("/reppixel { pixbuf } def\n",OutFile);
  800.     fputs("/getpixel { \n",OutFile);
  801.     fputs("  currentfile pixbuf readhexstring pop\n",OutFile);
  802.     fputs("} def\n\n",OutFile);
  803.  
  804.     if( col )
  805.     {   fputs("/colorimage where {\n",OutFile);
  806.         fputs("  pop\n",OutFile);
  807.         fputs("} {\n",OutFile);
  808.         fputs("  /bytebuf 1 string def\n",OutFile);
  809.         fputs("  /colorimage { pop pop image } def\n",OutFile);
  810.         fputs("  /reppixel { bytebuf } def\n",OutFile);
  811.         fputs("  /getpixel {\n",OutFile);
  812.         fputs("    currentfile pixbuf readhexstring pop pop\n",OutFile);
  813.         fputs("    bytebuf 0\n",OutFile);
  814.         fputs("    pixbuf 0 get 20 mul\n",OutFile);
  815.         fputs("    pixbuf 1 get 32 mul\n",OutFile);
  816.         fputs("    pixbuf 2 get 12 mul\n",OutFile);
  817.         fputs("    add add -6 bitshift put bytebuf\n",OutFile);
  818.         fputs("  } def\n",OutFile);
  819.         fputs("} ifelse\n\n",OutFile);
  820.     }
  821.  
  822.     fputs("/rledecode {\n",OutFile);
  823.     fputs("  rlecount 0 eq {\n",OutFile);
  824.     fputs("    currentfile rlebyte readhexstring pop\n",OutFile);
  825.     fprintf(OutFile,"    0 get dup %d gt {\n",EPSFCompRatio);
  826.     fprintf(OutFile,"      /rlecount exch %d sub def\n",EPSFCompRatio);
  827.     fputs("      /rleflag true def\n",OutFile);
  828.     fputs("    } {\n",OutFile);
  829.     fputs("      /rlecount exch def\n",OutFile);
  830.     fputs("      /rleflag false def\n",OutFile);
  831.     fputs("    } ifelse getpixel\n",OutFile);
  832.     fputs("  } {\n",OutFile);
  833.     fputs("    /rlecount rlecount 1 sub def\n",OutFile);
  834.     fputs("    rleflag { reppixel } { getpixel } ifelse\n",OutFile);
  835.     fputs("  } ifelse\n",OutFile);
  836.     fputs("} def\n",OutFile);
  837.     } else if( col )
  838.     {   fprintf(OutFile,"/scanbuf %d string def\n",XRange*3);
  839.     fputs("/colorimage where {\n",OutFile);
  840.     fputs("  pop\n",OutFile);
  841.     fputs("} {\n",OutFile);
  842.     fputs("  /pixbuf 3 string def\n",OutFile);
  843.     fputs("  /bytebuf 1 string def\n",OutFile);
  844.     fputs("  /colorimage {\n",OutFile);
  845.     fputs("    pop pop pop {\n",OutFile);
  846.     fputs("      currentfile pixbuf readhexstring pop pop\n",OutFile);
  847.     fputs("      bytebuf 0\n",OutFile);
  848.     fputs("      pixbuf 0 get 20 mul\n",OutFile);
  849.     fputs("      pixbuf 1 get 32 mul\n",OutFile);
  850.     fputs("      pixbuf 2 get 12 mul\n",OutFile);
  851.     fputs("      add add -6 bitshift put bytebuf\n",OutFile);
  852.     fputs("    } image\n",OutFile);
  853.     fputs("  } def\n",OutFile);
  854.     fputs("} ifelse\n\n",OutFile);
  855.     } else fprintf(OutFile,"/scanbuf %d string def\n\n",XRange);
  856.  
  857.     fprintf(OutFile,"%d %d %d\n",XRange,YRange,8);
  858.     fprintf(OutFile,"[%d 0 0 -%d 0 %d]\n",XRange,YRange,YRange);
  859.  
  860.     if( !compr )
  861.     {   fputs("{ currentfile scanbuf readhexstring pop }\n",OutFile);
  862.     } else fputs("{ rledecode }\n",OutFile);
  863.     if( col ) fputs("false 3 color",OutFile);
  864.     fputs("image\n",OutFile);
  865.  
  866. #ifdef IBMPC
  867.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  868. #endif
  869.  
  870. #ifndef INVERT
  871.     ptr = FBuffer; 
  872. #endif
  873.  
  874.     RLELength = 0;
  875.     LineLength = 0;
  876.     for( y=YRange-1; y>=0; y-- )
  877.     {
  878. #ifdef INVERT
  879.     ptr = FBuffer + (Long)y*XRange;
  880. #endif
  881.     for( x=0; x<XRange; x++ )
  882.     {   i = *ptr++;
  883.         if( compr )
  884.         {   if( RLELength )
  885.         {   if( RLEEncode )
  886.             {   if( (RLEPixel!=i) || (RLELength==256-EPSFCompRatio) )
  887.             {   OutputEPSFByte(RLELength+EPSFCompRatio-1);
  888.                 EncodeEPSFPixel(RLEPixel,col);
  889.                 RLEEncode = False;
  890.                 RLEBuffer[0] = i;
  891.                 RLELength = 1;
  892.             } else RLELength++;
  893.             } else if( RLEBuffer[RLELength-1] == i )
  894.             {   if( RLELength>1 )
  895.             {   OutputEPSFByte(RLELength-2);
  896.                 for( j=0; j<RLELength-1; j++ )
  897.                 EncodeEPSFPixel(RLEBuffer[j],col);
  898.             }
  899.             RLEEncode = True;
  900.             RLELength = 2;
  901.             RLEPixel = i;
  902.             } else if( RLELength == EPSFCompRatio+1 )
  903.             {   OutputEPSFByte(EPSFCompRatio);
  904.             for( j=0; j<RLELength; j++ )
  905.                  EncodeEPSFPixel(RLEBuffer[j],col);
  906.             RLEEncode = False;
  907.             RLEBuffer[0] = i;
  908.             RLELength = 1;
  909.             } else RLEBuffer[RLELength++] = i;
  910.         } else
  911.         {   RLEEncode = False;
  912.             RLEBuffer[0] = i;
  913.             RLELength = 1;
  914.         }
  915.         } else EncodeEPSFPixel( i, col );
  916.     }
  917.     }
  918.  
  919.     if( compr && RLELength )
  920.     {   if( RLEEncode )
  921.     {   OutputEPSFByte(RLELength+EPSFCompRatio-1);
  922.         EncodeEPSFPixel(RLEPixel,col);
  923.     } else
  924.     {   OutputEPSFByte(RLELength-1);
  925.         for( j=0; j<RLELength; j++ )
  926.         EncodeEPSFPixel(RLEBuffer[j],col);
  927.     }
  928.     }
  929.  
  930.     if( LineLength ) 
  931.     fputc('\n',OutFile);
  932.     fputs("end\n",OutFile);
  933.     fputs("grestore\n",OutFile);
  934.     fputs("showpage\n",OutFile);
  935.     fputs("%%Trailer\n",OutFile);
  936.     fputs("%%EOF\n",OutFile);
  937.     fclose( OutFile );
  938. #ifdef APPLEMAC
  939.     /* Avoid ANSI trigraph problems! */
  940.     SetFileInfo(name,'\?\?\?\?','EPSF',134);
  941. #endif
  942. #ifdef IBMPC
  943.     GlobalUnlock(FBufHandle);
  944. #endif
  945.     return( True );
  946. }
  947.  
  948.  
  949.  
  950. /* Flush AbsMode buffer */
  951. static void FlushBMPBuffer()
  952. {
  953.     if( RLEOutput )
  954.     {   fputc(0x00,OutFile);
  955.     fputc(PacketLen,OutFile);
  956.     fwrite((char*)Buffer,1,PacketLen,OutFile);
  957.     if( PacketLen%2 ) fputc(0x00,OutFile);    
  958.     } else
  959.     RLEFileSize += (PacketLen%2)+PacketLen+2;
  960.      
  961.     PacketLen = 0;
  962. }
  963.  
  964. /* Flush RLEMode buffer */
  965. static void FlushBMPPackets()
  966. {
  967.     register int i;
  968.     
  969.     if( PacketLen )
  970.     FlushBMPBuffer();
  971.  
  972.     if( RLEOutput )
  973.     {   for( i=0; i<BMPCount; i++ )
  974.     {   fputc(BMPBuffer[i].len,OutFile);
  975.         fputc(BMPBuffer[i].ch,OutFile);
  976.     }
  977.     } else RLEFileSize += (BMPCount<<1);
  978.     BMPCount = BMPTotal = 0;
  979. }
  980.  
  981. static void ProcessBMPPacket()
  982. {
  983.     register int cost;
  984.     register int i,j;
  985.     
  986.     BMPBuffer[BMPCount].len = RLELength;
  987.     BMPBuffer[BMPCount].ch = RLEChar;
  988.     BMPTotal += RLELength;
  989.     RLELength = 0;
  990.     BMPCount++; 
  991.  
  992.  
  993.     /* RLEMode is more efficient */
  994.     if( BMPTotal > BMPCount+5 )
  995.     {   FlushBMPPackets();
  996.     return;
  997.     }
  998.     
  999.     /* Flush AbsMode buffer */
  1000.     if( PacketLen+BMPTotal>255 )
  1001.     FlushBMPBuffer();
  1002.     
  1003.  
  1004.     /* Cannot leave RLEMode */
  1005.     if( PacketLen+BMPTotal<3 )
  1006.     return;
  1007.     
  1008.     /* Determine AbsMode cost */
  1009.     if( PacketLen )
  1010.     {   cost = BMPTotal - (PacketLen%2);
  1011.     cost += (cost%2);
  1012.     } else cost = (BMPTotal%2)+BMPTotal+2;    
  1013.  
  1014.     /* Put RLE Packets into AbsMode buffer */
  1015.     if( cost <= (int)(BMPCount<<1) )
  1016.     {   for( i=0; i<BMPCount; i++ )
  1017.         for( j=0; j<(int)BMPBuffer[i].len; j++ )
  1018.         Buffer[PacketLen++] = BMPBuffer[i].ch;
  1019.     BMPCount = BMPTotal = 0;
  1020.     }
  1021. }
  1022.  
  1023. /* Collect pixels into RLE Packets */
  1024. static void WriteBMPCode( val )
  1025.     int val;
  1026. {
  1027.     if( !RLELength )
  1028.     {   RLELength = 1;
  1029.     RLEChar = val;
  1030.     } else
  1031.     if( (RLEChar!=val) || (RLELength==255) )
  1032.     {   ProcessBMPPacket();
  1033.         RLELength = 1;
  1034.         RLEChar = val;
  1035.     } else
  1036.         RLELength++;
  1037. }
  1038.  
  1039. static void WriteBMPData( output )
  1040.     int output;
  1041. {
  1042.     register Pixel __huge *ptr;
  1043.     register int x,y;
  1044.     
  1045.     RLEOutput = output;
  1046.     RLEFileSize = 0;   BMPCount = 0;
  1047.     RLELength = 0;     BMPTotal = 0;
  1048.     PacketLen = 0; 
  1049.  
  1050. #ifdef INVERT
  1051.     ptr = FBuffer;
  1052. #endif
  1053.  
  1054.     for( y=YRange-1; y>=0; y-- )
  1055.     {
  1056. #ifndef INVERT
  1057.     ptr = FBuffer + (Long)y*XRange;
  1058. #endif
  1059.     for( x=0; x<XRange; x++ )
  1060.         WriteBMPCode(LutInv[*ptr++]);
  1061.  
  1062.     for( x=0; x<BMPPad; x++ )
  1063.         WriteBMPCode(0x00);
  1064.  
  1065.     /* Flush RLE codes */
  1066.     ProcessBMPPacket();
  1067.     FlushBMPPackets();
  1068.     
  1069.     if( RLEOutput )
  1070.     {   /* End of line code */
  1071.         fputc(0x00,OutFile);
  1072.         fputc((y?0x00:0x01),OutFile);
  1073.     } else RLEFileSize += 2;
  1074.     }
  1075. }
  1076.  
  1077.  
  1078.     
  1079. int WriteBMPFile( name )
  1080.     char *name;
  1081. {
  1082.     register Pixel __huge *ptr;
  1083.     register int x,y,i,raw;
  1084.     register Card size;
  1085.  
  1086. #if defined(IBMPC) || defined(APPLEMAC)
  1087.     OutFile = fopen(name,"wb");
  1088. #else
  1089.     OutFile = fopen(name,"w");
  1090. #endif
  1091.     if( !OutFile )
  1092.     {    FatalOutputError(name);
  1093.      return( False );
  1094.     }
  1095.  
  1096. #ifdef EIGHTBIT
  1097.     for( i=0; i<256; i++ )
  1098.     if( ULut[i] )
  1099.         LutInv[Lut[i]] = i;
  1100.  
  1101. #ifdef IBMPC
  1102.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  1103. #endif
  1104.  
  1105.     /* zero-pad scanlines to long */
  1106.     if( (BMPPad=XRange%4) ) 
  1107.      BMPPad = 4-BMPPad; 
  1108.    
  1109.     WriteBMPData(False);
  1110.     size = (Long)(XRange+BMPPad)*YRange;
  1111.     if( RLEFileSize<size )
  1112.     {   size = RLEFileSize;
  1113.     raw = False;
  1114.     } else raw = True;
  1115.  
  1116.  
  1117.     fputc('B',OutFile); 
  1118.     fputc('M',OutFile);
  1119.     WriteLSBLong(size+1078);
  1120.     WriteLSBLong((Card)0);
  1121.     WriteLSBLong((Card)1078);
  1122.  
  1123.     WriteLSBLong((Card)40);
  1124.     WriteLSBLong((Card)XRange);
  1125.     WriteLSBLong((Card)YRange);
  1126.     fputc(0x01,OutFile);  fputc(0x00,OutFile);
  1127.     fputc(0x08,OutFile);  fputc(0x00,OutFile);
  1128.     WriteLSBLong(raw? (Card)0 : (Card)1);
  1129.     WriteLSBLong(size);
  1130.     
  1131.     WriteLSBLong((Card)0);
  1132.     WriteLSBLong((Card)0);
  1133.     WriteLSBLong((Card)256);
  1134.     WriteLSBLong((Card)256);
  1135.  
  1136.     for( i=0; i<256; i++ )
  1137.     {   fputc((int)BLut[i],OutFile);
  1138.     fputc((int)GLut[i],OutFile);
  1139.     fputc((int)RLut[i],OutFile);
  1140.     fputc(0x00,OutFile);
  1141.     }
  1142.  
  1143.     if( raw )
  1144.     {   
  1145. #ifdef INVERT
  1146.     ptr = FBuffer;
  1147. #endif
  1148.     for( y=YRange-1; y>=0; y-- )
  1149.     {
  1150. #ifndef INVERT
  1151.         ptr = FBuffer + (Long)y*XRange;
  1152. #endif
  1153.         for( x=0; x<XRange; x++ )
  1154.         fputc((int)LutInv[*ptr++],OutFile);
  1155.         for( x=0; x<BMPPad; x++ )
  1156.         fputc(0x00,OutFile);
  1157.         fputc(0x00,OutFile);
  1158.         fputc((y?0x00:0x01),OutFile);
  1159.     }
  1160.     } else
  1161.     WriteBMPData(True);
  1162.     fclose(OutFile);
  1163.  
  1164. #ifdef APPLEMAC
  1165.     /* Avoid ANSI trigraph problems! */
  1166.     SetFileInfo(name,'\?\?\?\?','\?\?\?\?',134);
  1167. #endif
  1168. #ifdef IBMPC
  1169.     GlobalUnlock(FBufHandle);
  1170. #endif
  1171.     return(True);
  1172. #else
  1173.     if( CommandActive ) WriteChar('\n');
  1174.     WriteString("Output Error: 24 bit BMP files unsupported!\n");
  1175.     CommandActive = False;
  1176.     return( False );
  1177. #endif
  1178. }
  1179.  
  1180.  
  1181.  
  1182. #ifdef FUNCPROTO
  1183. static int FindDepth( PSItemPtr, int );
  1184. static void DepthSort( PSItemPtr __far*, char __far*, int );
  1185. #endif
  1186.  
  1187. static int FindDepth( item, type )
  1188.      PSItemPtr item;  int type;
  1189. {
  1190.     register Atom __far *atom;
  1191.     register Bond __far *bond;
  1192.     register int result;
  1193.  
  1194.     if( type==PSSphere )
  1195.     {   atom = (Atom __far*)item;
  1196.     result = atom->z;
  1197.     } else /* PSLine or PSStick */
  1198.     {   bond = (Bond __far*)item;
  1199.     result = bond->srcatom->z;
  1200.     if( result < bond->dstatom->z )
  1201.         result = bond->dstatom->z;
  1202.     }
  1203.     return( result );
  1204. }
  1205.  
  1206.  
  1207. static void DepthSort( data, type, count )
  1208.     PSItemPtr __far *data;
  1209.     char __far *type;
  1210.     int count;
  1211. {
  1212.     register char ttmp;
  1213.     register void __far *dtmp;
  1214.     register int i, j, k;
  1215.     register int depth;
  1216.     register int temp;
  1217.  
  1218.     for( i=1; i<count; i++ )
  1219.     {   dtmp = data[i];  
  1220.     ttmp = type[i];
  1221.  
  1222.     j = i-1;
  1223.     depth = FindDepth(dtmp,ttmp);
  1224.     temp = FindDepth(data[j],type[j]);
  1225.     while( (depth<temp) || ((depth==temp)&&(ttmp<type[j])) )
  1226.         if( j-- ) 
  1227.         {   temp = FindDepth(data[j],type[j]);
  1228.         } else break;
  1229.     j++;
  1230.  
  1231.     if( j != i )
  1232.     {   for( k=i; k>j; k-- )
  1233.         {    data[k] = data[k-1];
  1234.          type[k] = type[k-1];
  1235.         }
  1236.         data[j] = dtmp;
  1237.         type[j] = ttmp;
  1238.     }
  1239.     }
  1240. }
  1241.  
  1242. #ifdef FUNCPROTO
  1243. static int ClipVectSphere( Atom __far* );
  1244. static int ClipVectBond( Bond __far* );
  1245.  
  1246. static void WriteVectSphere( PSItemPtr __far*, char __far*, int );
  1247. static void WriteVectStick( Bond __far* );
  1248. static void WriteVectWire( Bond __far* );
  1249. #endif
  1250.  
  1251.  
  1252. static int ClipVectSphere( ptr )
  1253.     Atom __far *ptr;
  1254. {
  1255.     register int rad;
  1256.  
  1257.     rad = ptr->irad;
  1258.  
  1259.     if( ptr->x + rad < 0 )  return( True );
  1260.     if( ptr->y + rad < 0 )  return( True );
  1261.     if( ptr->x - rad >= XRange )  return( True );
  1262.     if( ptr->y - rad >= YRange )  return( True );
  1263.     return( False );
  1264. }
  1265.  
  1266.  
  1267. static int ClipVectBond( ptr )
  1268.     Bond __far *ptr;
  1269. {
  1270.     register Atom __far *src;
  1271.     register Atom __far *dst;
  1272.  
  1273.     src = ptr->srcatom;
  1274.     dst = ptr->dstatom;
  1275.  
  1276.     if( (src->x<0) && (dst->x<0) )  return( True );
  1277.     if( (src->y<0) && (dst->y<0) )  return( True );
  1278.     if( (src->x>=XRange) && (dst->x>=XRange) )  return( True );
  1279.     if( (src->y>=YRange) && (dst->y>=YRange) )  return( True );
  1280.     return( False );
  1281. }
  1282.  
  1283.  
  1284.  
  1285. static void WriteVectColour( col )
  1286.     int col;
  1287. {
  1288.     if( col != VectCol )
  1289.     {   fprintf(OutFile,"%g ",(Real)RLut[col]/255.0);
  1290.     fprintf(OutFile,"%g ",(Real)GLut[col]/255.0);
  1291.     fprintf(OutFile,"%g ",(Real)BLut[col]/255.0);
  1292.     fputs("setrgbcolor\n",OutFile);
  1293.     VectCol = col;
  1294.     }
  1295. }
  1296.  
  1297.  
  1298. #define MAXSECT 5
  1299. typedef struct {
  1300.     /* Ellipse */
  1301.     Real ephi,epsi;
  1302.     Real etheta;
  1303.     Real ex,ey;
  1304.     Real erad;
  1305.  
  1306.     /* Sphere */
  1307.     Real sphi,spsi;
  1308.     int sx,sy;
  1309.     Real srad;
  1310.     } SphereSect;
  1311.  
  1312.  
  1313. static int VectClipContain( x, y )
  1314.     SphereSect *x; SphereSect *y;
  1315. {
  1316.     if( x->erad != 0.0 )
  1317.     {   if( y->erad != 0.0 )
  1318.         /* Simple segment containment test! */
  1319.         return( ((x->sphi+x->spsi)>=(y->sphi+y->spsi)) &&
  1320.             ((x->sphi-x->spsi)<=(y->sphi-y->spsi)) );
  1321.     } else if( y->erad == 0.0 )
  1322.     return( x->srad >= y->srad );
  1323.     return( False );
  1324. }
  1325.  
  1326.  
  1327. static void WriteVectSphere( data, type, index )
  1328.     PSItemPtr __far*data; 
  1329.     char __far *type;
  1330.     int index;
  1331. {
  1332.     register int ecount, count;
  1333.     register Atom __far *atm;
  1334.     register Atom __far *ptr;
  1335.     register Long dist2,dist3;
  1336.     register int dx, dy, dz;
  1337.     register int i,j,k;
  1338.  
  1339.     register Real b,d,f,g,x;
  1340.     register Real radf,radb;
  1341.     register Real phi1,phi2;
  1342.     register Real temp,psi;
  1343.     register Real theta;
  1344.  
  1345.     register SphereSect *sptr;
  1346.     SphereSect sect[MAXSECT];
  1347.  
  1348.     ptr = (Atom __far*)data[index];
  1349.     radf = ptr->radius*Scale;
  1350.  
  1351.     count = 0;
  1352.     ecount = 0;
  1353.     sptr = sect;
  1354.     for( i=index-1; i>=0; i-- )
  1355.     {   if( type[i] != PSSphere )
  1356.         continue;
  1357.  
  1358.     atm = (Atom __far*)data[i];
  1359.     /* Atom can't intersect visibly! */
  1360.     if( atm->z + atm->irad < ptr->z )
  1361.         continue;
  1362.  
  1363.     dx = atm->x - ptr->x; 
  1364.     dy = atm->y - ptr->y; 
  1365.     dz = atm->z - ptr->z;
  1366.  
  1367.     dist2 = (Long)dx*dx + (Long)dy*dy;
  1368.     dist3 = dist2 + dz*dz;
  1369.  
  1370.     radb = atm->radius*Scale;  
  1371.     temp = radf + radb;
  1372.  
  1373.     /* Atoms don't intersect! */
  1374.     if( dist3 > temp*temp ) continue;
  1375.  
  1376.  
  1377.     d = sqrt( (double)dist3 );
  1378.     f = (temp*(radf-radb)+dist3)/(2.0*d);
  1379.     theta = -dz/d;
  1380.  
  1381.     if( f>0 )
  1382.     {   temp = radf*radf;
  1383.         /* Intersection not visible! */
  1384.         if( theta*temp > temp-f*f )
  1385.         continue;
  1386.     } else if( f < -radf )
  1387.         return;
  1388.  
  1389.     x = sqrt( (radf-f)*(radf+f) );
  1390.  
  1391.     if( dx || dy )
  1392.     {   g = sqrt( (double)dist2 );
  1393.         psi = Rad2Deg*atan2(dy,dx);
  1394.         b = (f*(dz*dz))/(d*g);
  1395.  
  1396.         if( AbsFun(b)>x )
  1397.         continue;
  1398.  
  1399.         phi1 = b + (f*g)/d;
  1400.         phi1 = Rad2Deg*acos(phi1/radf);
  1401.         if( phi1!=phi1 ) continue;
  1402.  
  1403.         phi2 = (d*b)/g;
  1404.         if( AbsFun(phi2) < x )
  1405.         {   phi2 = Rad2Deg*acos(phi2/x);
  1406.         if( phi2!=phi2 ) continue;
  1407.         if( phi2 > 90.0 ) 
  1408.             phi2 = 180.0-phi1;
  1409.         } else phi2 = 90.0;
  1410.  
  1411.         sptr->erad = x;
  1412.         sptr->etheta = -theta;
  1413.         sptr->ephi = psi;
  1414.         sptr->epsi = phi2;
  1415.  
  1416.         temp = f/d;
  1417.         sptr->ex = ptr->x+temp*dx;
  1418.         sptr->ey = ptr->y+temp*dy;
  1419.  
  1420.         sptr->srad = radf;
  1421.         sptr->sphi = psi;
  1422.         sptr->spsi = phi1;
  1423.         sptr->sx = ptr->x;
  1424.         sptr->sy = ptr->y;
  1425.  
  1426.     } else
  1427.     {   x = sqrt( (radf-g)*(radf+g) );
  1428.  
  1429.         sptr->srad = x;
  1430.         sptr->erad = 0.0;
  1431.         sptr->sx = ptr->x;
  1432.         sptr->sy = ptr->y;
  1433.         sptr->sphi = 180;
  1434.         sptr->spsi = -180;
  1435.     }
  1436.  
  1437.     /* Optimize Segments */
  1438.     j = 0;
  1439.     while( j<count )
  1440.         if( VectClipContain(sptr,sect+j) )
  1441.         {   /* Delete Segment sect[j] */
  1442.         for( k=j; k<count; k++ )
  1443.             sect[k] = sect[k+1];
  1444.         count--;  sptr--;
  1445.         } else if( VectClipContain(sect+j,sptr) )
  1446.         {   break;  /* Exclude Segment */
  1447.         } else j++;
  1448.        
  1449.  
  1450.     if( j==count )
  1451.     {   count++;  sptr++;
  1452.         if( sptr->erad != 0.0 )
  1453.         ecount++;
  1454.         if( count==MAXSECT )
  1455.         break;
  1456.     }
  1457.     }
  1458.  
  1459.     if( UseOutLine )
  1460.     {   temp = (ptr->z-ZOffset)/ImageSize + 1.0;
  1461.     if( temp != LineWidth )
  1462.     {   fprintf(OutFile,"%g setlinewidth\n",temp);
  1463.         LineWidth = temp;
  1464.     }
  1465.     }
  1466.  
  1467.     if( count )
  1468.     {   fputs("gsave\n",OutFile);
  1469.     fprintf(OutFile,"%%%% %d %d\n",count,ecount);
  1470.  
  1471.     sptr = sect;
  1472.     for( i=0; i<count; i++ )
  1473.     {   if( sptr->erad != 0.0 )
  1474.         {   fprintf(OutFile,"%g %g %g %g %g %g ClipEllips\n",
  1475.                 sptr->erad,sptr->epsi,sptr->etheta,
  1476.                 sptr->ephi,sptr->ex,sptr->ey);
  1477.         }
  1478.  
  1479.         if( (i==count-1) || (sptr->erad==0.0) )
  1480.         {   fprintf(OutFile,"%g %g %g %d %d ClipSphere\n",sptr->srad,
  1481.                 sptr->sphi+sptr->spsi,sptr->sphi-sptr->spsi,
  1482.                 sptr->sx, sptr->sy );
  1483.         } else fprintf(OutFile,"%g %g %g %d %d ClipBox\n",
  1484.                     sptr->srad+sptr->srad+2,
  1485.                     sptr->srad+1, sptr->ephi,
  1486.                     sptr->sx, sptr->sy );
  1487.         sptr++;
  1488.     }
  1489.  
  1490.     i = ptr->col + ColourMask;
  1491.     fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
  1492.     fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
  1493.     fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
  1494.     fprintf(OutFile,"%g Shade\n",radf);
  1495.     fputs("grestore\n\n",OutFile);
  1496.     } else
  1497.     {   i = ptr->col + ColourMask;
  1498.     fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
  1499.     fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
  1500.     fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
  1501.     fprintf(OutFile,"%g %d %d ",radf,ptr->x,ptr->y);
  1502.     fputs("Sphere\n\n",OutFile);
  1503.     }
  1504. }
  1505.  
  1506.  
  1507. static void WriteVectWire( ptr )
  1508.     Bond __far *ptr;
  1509. {
  1510.     register Atom __far *src;
  1511.     register Atom __far *dst;
  1512.     register Real radius;
  1513.     register Real temp;
  1514.     register Real dist;
  1515.  
  1516.     register Real midx, midy;
  1517.     register Real endx, endy;
  1518.     register int col1, col2;
  1519.     register int dx, dy, dz;
  1520.     register Long dist2;
  1521.  
  1522.  
  1523.     src = ptr->srcatom;  
  1524.     dst = ptr->dstatom;
  1525.     if( src->z > dst->z )
  1526.     {   src = ptr->dstatom;
  1527.     dst = ptr->srcatom;
  1528.     }
  1529.  
  1530.     if( !ptr->col )
  1531.     {   col1 = src->col;
  1532.     col2 = dst->col;
  1533.     } else col1 = col2 = ptr->col;
  1534.  
  1535.     dx = dst->x - src->x;  
  1536.     dy = dst->y - src->y;
  1537.     dist2 = dx*dx + dy*dy;
  1538.     dist = sqrt( (double)dist2 );
  1539.  
  1540.     if( dst->flag & SphereFlag )
  1541.     {   radius = dst->radius*Scale;
  1542.     if( dist <= radius ) return;
  1543.  
  1544.     /* Test for second half obscured! */
  1545.     if( (col1!=col2) && (0.5*dist < radius) )
  1546.         col2 = col1;
  1547.     }
  1548.  
  1549.     if( src->flag & SphereFlag )
  1550.     {   radius = src->radius*Scale;
  1551.     if( dist <= radius ) return;
  1552.  
  1553.     /* Test for first half obscured! */
  1554.     if( (col1!=col2) && (0.5*dist < radius) )
  1555.         col1 = col2;
  1556.     }
  1557.  
  1558.  
  1559.     WriteVectColour( col1+ColourMask );
  1560.     temp = ((src->z-ZOffset)+(dst->z-ZOffset))/ImageSize + 1.0;
  1561.     if( temp != LineWidth )
  1562.     {   fprintf(OutFile,"%g setlinewidth\n",temp);
  1563.     LineWidth = temp;
  1564.     }
  1565.  
  1566.  
  1567.     if( src->flag & SphereFlag )
  1568.     {   dz = dst->z - src->z;
  1569.     dist = sqrt( (double)(dist2 + dz*dz) );
  1570.     endx = src->x + (radius*dx)/dist;
  1571.     endy = src->y + (radius*dy)/dist;
  1572.     fprintf(OutFile,"%g %g ",endx,endy);
  1573.     } else
  1574.     fprintf(OutFile,"%d %d ",src->x,src->y);
  1575.  
  1576.     if( col1 != col2 )
  1577.     {   midx = 0.5*(src->x + dst->x);
  1578.     midy = 0.5*(src->y + dst->y);
  1579.     fprintf(OutFile,"%g %g Wire\n",midx,midy);
  1580.  
  1581.     WriteVectColour( col2+ColourMask );
  1582.     fprintf(OutFile,"%g %g ",midx,midy);
  1583.     } 
  1584.     fprintf(OutFile,"%d %d Wire\n",dst->x,dst->y);
  1585. }
  1586.  
  1587.  
  1588. static void WriteVectStick( ptr )
  1589.     Bond __far *ptr;
  1590. {
  1591.     register Atom __far *src;
  1592.     register Atom __far *dst;
  1593.     register Real midx, midy;
  1594.     register Real relx, rely;
  1595.     register Real endx, endy;
  1596.     register Real radius, angle;
  1597.     register Real dist, dist3;
  1598.     register Real temp, ratio;
  1599.  
  1600.     register Long dist2;
  1601.     register int dx, dy, dz;
  1602.     register int col1, col2;
  1603.     register int i, inten;
  1604.  
  1605.     if( !ptr->radius )
  1606.     {   WriteVectWire(ptr);
  1607.     return;
  1608.     }
  1609.  
  1610.     src = ptr->srcatom;  
  1611.     dst = ptr->dstatom;
  1612.     if( src->z > dst->z )
  1613.     {   src = ptr->dstatom;
  1614.     dst = ptr->srcatom;
  1615.     }
  1616.  
  1617.     if( !ptr->col )
  1618.     {   col1 = src->col;
  1619.     col2 = dst->col;
  1620.     } else col1 = col2 = ptr->col;
  1621.  
  1622.     dx = dst->x - src->x;  
  1623.     dy = dst->y - src->y;
  1624.     dz = dst->z - src->z;
  1625.     dist2 = dx*dx + dy*dy;
  1626.     dist3 = sqrt( (double)(dist2 + dz*dz) );
  1627.     dist = sqrt( (double)dist2 );
  1628.  
  1629.     if( dst->flag & SphereFlag )
  1630.     {   radius = dst->radius*Scale;
  1631.     if( dist <= radius ) return;
  1632.  
  1633.     /* Test for nearest half obscured! */
  1634.     if( (col1!=col2) && (0.5*dist < radius) )
  1635.         col2 = col1;
  1636.     }
  1637.  
  1638.     if( src->flag & SphereFlag )
  1639.     {   radius = src->radius*Scale;
  1640.     if( dist <= radius ) return;
  1641.  
  1642.     /* Test for furthest half obscured! */
  1643.     if( (col1!=col2) && (0.5*dist < radius) )
  1644.         col1 = col2;
  1645.     }
  1646.  
  1647.     temp = ((src->z-ZOffset)+(dst->z-ZOffset))/ImageSize + 1.0;
  1648.     if( temp != LineWidth )
  1649.     {   fprintf(OutFile,"%g setlinewidth\n",temp);
  1650.     LineWidth = temp;
  1651.     }
  1652.  
  1653.     radius = ptr->radius*Scale;
  1654.     angle = Rad2Deg*atan2((double)dy,(double)dx);
  1655.     inten = (int)((dist/dist3)*ColourMask);
  1656.  
  1657.     if( col1 != col2 )
  1658.     {   midx = 0.5*(src->x + dst->x);
  1659.     midy = 0.5*(src->y + dst->y);
  1660.     relx = (radius*dx)/dist;
  1661.     rely = (radius*dy)/dist;
  1662.  
  1663.     fprintf(OutFile,"%g %g moveto\n",midx+rely,midy-relx);
  1664.     fprintf(OutFile,"%g %g lineto\n",midx-rely,midy+relx);
  1665.  
  1666.     ratio = dz/dist3;
  1667.  
  1668.     if( (src->flag&SphereFlag) && (src->radius>ptr->radius) )
  1669.     {   temp = (Scale*src->radius)/dist3;
  1670.         endx = src->x + temp*dx;
  1671.         endy = src->y + temp*dy;
  1672.  
  1673.         fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
  1674.         fprintf(OutFile,"%g %g StickEnd\n",endx,endy);
  1675.     } else
  1676.     {   fprintf(OutFile,"%d %d %g ",src->x,src->y,radius);
  1677.         fprintf(OutFile,"%g %g arc\n",angle+90,angle-90);
  1678.     }
  1679.     fputs("closepath ",OutFile);
  1680.  
  1681.     i = col1 + inten;
  1682.     fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
  1683.     fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
  1684.     fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
  1685.     fputs("setrgbcolor fill\n",OutFile);
  1686.  
  1687.     fprintf(OutFile,"%d %d %g ",dst->x,dst->y,radius);
  1688.     fprintf(OutFile,"%g %g arc\n",angle-90,angle+90);
  1689.     fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
  1690.     fprintf(OutFile,"%g %g StickEnd\n",midx,midy);
  1691.     fputs("closepath ",OutFile);
  1692.  
  1693.     i = col2 + inten;
  1694.     fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
  1695.     fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
  1696.     fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
  1697.     fputs("setrgbcolor fill\n",OutFile);
  1698.  
  1699.     if( UseOutLine )
  1700.     {   fprintf(OutFile,"%d %d %g ",dst->x,dst->y,radius);
  1701.         fprintf(OutFile,"%g %g arc\n",angle-90,angle+90);
  1702.         if( (src->flag&SphereFlag) && (src->radius>ptr->radius) )
  1703.         {   fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
  1704.         fprintf(OutFile,"%g %g StickEnd\n",endx,endy);
  1705.         } else
  1706.         {   fprintf(OutFile,"%d %d %g ",src->x,src->y,radius);
  1707.         fprintf(OutFile,"%g %g arc\n",angle+90,angle-90);
  1708.         }
  1709.         fputs("closepath 0 setgray stroke\n",OutFile);
  1710.     }
  1711.     } else /* col1 == col2! */
  1712.     {   fprintf(OutFile,"%d %d %g ",dst->x,dst->y,radius);
  1713.     fprintf(OutFile,"%g %g arc\n",angle-90,angle+90);
  1714.  
  1715.     if( (src->flag&SphereFlag) && (src->radius>ptr->radius) )
  1716.     {   temp = (Scale*src->radius)/dist3;
  1717.         endx = src->x + temp*dx;
  1718.         endy = src->y + temp*dy;
  1719.         ratio = dz/dist3;
  1720.  
  1721.         fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
  1722.         fprintf(OutFile,"%g %g StickEnd\n",endx,endy);
  1723.     } else
  1724.     {   fprintf(OutFile,"%d %d %g ",src->x,src->y,radius);
  1725.         fprintf(OutFile,"%g %g arc\n",angle+90,angle-90);
  1726.     }
  1727.  
  1728.     i = col1 + inten;
  1729.     fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
  1730.     fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
  1731.     fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
  1732.     fputs("Stick\n",OutFile);
  1733.     }
  1734.     VectCol = 0;
  1735. }
  1736.  
  1737.  
  1738. static void WriteVectDots()
  1739. {
  1740.     register DotStruct __far *ptr;
  1741.     register Real x,y,z;
  1742.     register Real xi,yi;
  1743.     register int inten;
  1744.     register int temp;
  1745.     register int zi;
  1746.     register int i;
  1747.  
  1748.  
  1749.     if( LineWidth != 1.0 )
  1750.     {   fputs("1 setlinewidth\n",OutFile);
  1751.     LineWidth = 1.0;
  1752.     }
  1753.  
  1754.     temp = SlabValue - ZOffset;
  1755.     for( ptr=DotPtr; ptr; ptr=ptr->next )
  1756.     for( i=0; i<ptr->count; i++ )
  1757.     {   x = ptr->xpos[i];  
  1758.         y = ptr->ypos[i];  
  1759.         z = ptr->zpos[i];
  1760.  
  1761.  
  1762.         xi = (x*MatX[0]+y*MatX[1]+z*MatX[2]) + XOffset;
  1763.         if( (xi<0.0) || (xi>=XRange) ) continue;
  1764.         yi = (x*MatY[0]+y*MatY[1]+z*MatY[2]) + YOffset;
  1765.         if( (yi<0.0) || (yi>=YRange) ) continue;
  1766.  
  1767.         zi = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2]);
  1768.         if( UseSlabPlane && (zi>=temp) ) continue;
  1769.  
  1770.         inten = (ColourDepth*(zi+ImageRadius))/ImageSize;
  1771.         WriteVectColour( ptr->col[i]+inten );
  1772.         fprintf(OutFile,"%g %g Dot\n",xi,yi);
  1773.     }
  1774. }
  1775.  
  1776.  
  1777. static void WriteVectLabels()
  1778. {
  1779.     register Chain __far *chain;
  1780.     register Group __far *group;
  1781.     register Atom __far *aptr;
  1782.     register Label *label;
  1783.     auto char buffer[80];
  1784.  
  1785.     fputs("/Times-Roman",OutFile); /* Courier or Courier-Bold? */
  1786.     fprintf(OutFile," findfont %d scalefont setfont\n",FontSize<<1);
  1787.  
  1788.     if( UseLabelCol )
  1789.     {   if( BackR || BackG || BackB )
  1790.     {   fprintf(OutFile,"%g %g %g setrgbcolor\n",
  1791.             LabR/250.0, LabG/250.0, LabB/250.0);
  1792.     } else fputs("0 setgray\n",OutFile);
  1793.     } else VectCol = 0;
  1794.  
  1795.     ForEachAtom
  1796.     if( aptr->label )
  1797.     {   if( !UseLabelCol && (aptr->col!=VectCol) )
  1798.          WriteVectColour( aptr->col );
  1799.  
  1800.         label = (Label*)aptr->label;
  1801.         FormatLabel(chain,group,aptr,label->label,buffer);
  1802.         fprintf(OutFile,"(%s) %d %d Label\n",buffer,aptr->x,aptr->y);
  1803.     }
  1804. }
  1805.  
  1806.  
  1807. int WriteVectPSFile( name )
  1808.     char *name;
  1809. {
  1810.     register Real ambi;
  1811.     register Real temp, inten;
  1812.     register int xsize, ysize;
  1813.     register int xpos, ypos;
  1814.     register Long count;
  1815.     register int i;
  1816.  
  1817.     PSItemPtr __far *data;
  1818.     char __far *type;
  1819.  
  1820.     register Chain __far *chain;
  1821.     register Group __far *group;
  1822.     register Bond __far *bptr;
  1823.     register Atom __far *aptr;
  1824.  
  1825.  
  1826.     /* Determine the number of objects to draw! */
  1827.     count = 0;
  1828.     ForEachAtom 
  1829.     if( aptr->flag&SphereFlag ) 
  1830.         if( !UseClipping || !ClipVectSphere(aptr) )
  1831.         count++;
  1832.     ForEachBond 
  1833.     if( bptr->flag&DrawBondFlag ) 
  1834.         if( !UseClipping || !ClipVectBond(bptr) )
  1835.         count++;
  1836.     ForEachBack 
  1837.     if( bptr->flag&DrawBondFlag )
  1838.         if( !UseClipping || !ClipVectBond(bptr) )
  1839.         count++;
  1840.  
  1841.     if( !count ) 
  1842.     return( True );
  1843.  
  1844. #ifdef IBMPC
  1845.     if( count > 16383 )
  1846.     {   if( CommandActive ) WriteChar('\n');
  1847.     WriteString("Output Error: Too many PostScript objects!\n");
  1848.     CommandActive = False;
  1849.     return( False );
  1850.     }
  1851. #endif
  1852.  
  1853.     /* Allocate arrays for objects! */
  1854.     data = (PSItemPtr __far*)_fmalloc((size_t)count*sizeof(PSItemPtr));
  1855.     type = (char __far*)_fmalloc((size_t)count*sizeof(char));
  1856.     if( !data || !type )
  1857.     {   if( CommandActive ) WriteChar('\n');
  1858.     WriteString("Output Error: Not enough memory to create PostScript!\n");
  1859.     CommandActive = False;
  1860.  
  1861.     if( data ) _ffree( data );
  1862.     if( type ) _ffree( type );
  1863.     return( False );
  1864.     }
  1865.  
  1866.     OutFile = fopen(name,"w");
  1867.     if( !OutFile )
  1868.     {   FatalOutputError(name);
  1869.     return(False);
  1870.     }
  1871.  
  1872.     /* Determine the size of the image */
  1873.     ysize = (int)(YRange*(BORDER*PAGEWIDE)/XRange);
  1874.     if( ysize > (int)(BORDER*PAGEHIGH) )
  1875.     {   xsize = (int)(XRange*(BORDER*PAGEHIGH)/YRange);
  1876.     ysize = (int)(BORDER*PAGEHIGH);
  1877.     } else xsize = (int)(BORDER*PAGEWIDE);
  1878.  
  1879.     xpos = (int)(PAGEWIDE-xsize)/2;
  1880.     ypos = (int)(PAGEHIGH-ysize)/2;
  1881.  
  1882.     fputs("%!PS-Adobe-2.0 EPSF-2.0\n",OutFile);
  1883.     fputs("%%Creator: RasMol Version 2.5\n",OutFile);
  1884.     fprintf(OutFile,"%%%%Title: %s\n",name);
  1885.     fprintf(OutFile,"%%%%BoundingBox: %d %d ",xpos,ypos);
  1886.     fprintf(OutFile,"%d %d\n",xpos+xsize,ypos+ysize);
  1887.  
  1888.     fputs("%%Pages: 1\n",OutFile);
  1889.     fputs("%%EndComments\n",OutFile);
  1890.     fputs("%%EndProlog\n",OutFile);
  1891.     fputs("%%BeginSetup\n",OutFile);
  1892.  
  1893.     fputs("1 setlinecap 1 setlinejoin [] 0 setdash\n",OutFile);
  1894.     fputs("1 setlinewidth 0 setgray\n",OutFile);
  1895.     fputs("%%EndSetup\n",OutFile);
  1896.     fputs("%%Page: 1 1\n",OutFile);
  1897.  
  1898.     fputs("gsave\n",OutFile);
  1899.     fputs("14 dict begin\n\n",OutFile);
  1900.     fputs("/handleerror { showpage } def\n\n",OutFile);
  1901.     fputs("/Inten {\n  dup 4 index mul exch\n",OutFile);
  1902.     fputs("  dup 4 index mul exch\n",OutFile);
  1903.     fputs("  3 index mul setrgbcolor\n} def\n\n",OutFile);
  1904.  
  1905.     fputs("/Dot {\n  moveto 0 0 rlineto stroke\n} def\n\n",OutFile);
  1906.     fputs("/Wire {\n  moveto lineto stroke\n} def\n\n",OutFile);
  1907. #ifdef INVERT
  1908.     fputs("/Label {\n  moveto show\n} def\n\n",OutFile);
  1909. #else
  1910.     fputs("/Label {\n  moveto 1 -1 scale\n",OutFile);
  1911.     fputs("  show mtrx setmatrix\n} def\n\n",OutFile);
  1912. #endif
  1913.  
  1914.     if( UseOutLine )
  1915.     {   fputs("/Stick {\n  closepath gsave setrgbcolor fill\n",OutFile);
  1916.     fputs("  grestore 0 setgray stroke\n} def\n\n",OutFile);
  1917.     } else
  1918.     fputs("/Stick {\n  closepath setrgbcolor fill\n} def\n\n",OutFile);
  1919.  
  1920.     fputs("/StickEnd {\n  matrix currentmatrix 6 1 roll\n",OutFile);
  1921.     fputs("  translate rotate 1 scale\n",OutFile);
  1922.     fputs("  0 0 3 2 roll 90 -90 arc\n  setmatrix\n} def\n\n",OutFile);
  1923.  
  1924.     ambi = 0.5*Ambient;
  1925.     if( UseOutLine )
  1926.     {   fputs("/Shade {\n  closepath gsave clip\n",OutFile);
  1927.     } else fputs("/Shade {\n  closepath clip\n",OutFile);
  1928.     fputs("  45 rotate dup -0.81649658092 mul scale\n",OutFile);
  1929.     fprintf(OutFile,"  %g Inten fill\n",ambi);
  1930.     inten = (1.0-ambi)/31;
  1931.     for( i=0; i<31; i++ )
  1932.     {   temp = (Real)(i+1)/32;
  1933.     fprintf(OutFile,"  0 %g ",(Real)i/32);
  1934.     fprintf(OutFile,"%g 0 360 arc ",sqrt(1.0-temp*temp));
  1935.     fprintf(OutFile,"%g Inten fill\n",i*inten+ambi);
  1936.     }
  1937.     if( UseOutLine )
  1938.     {   fputs("  grestore 0 setgray stroke pop pop pop\n} def\n\n",OutFile);
  1939.     } else fputs("  pop pop pop\n} def\n\n",OutFile);
  1940.  
  1941.     fputs("/ClipSphere {\n  translate 0 0 5 2 roll arc\n} def\n\n",OutFile);
  1942.     fputs("/ClipBox {\n  translate rotate\n  dup lineto dup neg ",OutFile);
  1943.     fputs("dup\n  0 rlineto 0 exch rlineto 0 rlineto closepath\n",OutFile);
  1944.     fputs("  clip newpath mtrx setmatrix\n} def\n\n",OutFile);
  1945.     fputs("/ClipEllips {\n  translate rotate 1 scale\n",OutFile);
  1946.     fputs("  0 0 4 2 roll dup neg arc\n",OutFile);
  1947.     fputs("  reversepath mtrx setmatrix\n} def\n\n",OutFile);
  1948.  
  1949.     fputs("/Sphere {\n  gsave\n",OutFile);
  1950.     fputs("  translate 0 0 2 index 0 360 arc\n",OutFile);
  1951.     if( UseOutLine )
  1952.     {   fputs("  gsave Shade grestore\n",OutFile);
  1953.     fputs("  0 setgray stroke\n  ",OutFile);
  1954.     fputs("  grestore\n} def\n\n",OutFile);
  1955.     } else
  1956.     fputs("  Shade grestore\n} def\n\n",OutFile);
  1957.  
  1958. #ifdef INVERT
  1959.     fprintf(OutFile,"%d %d translate\n",xpos,ypos);
  1960.     fprintf(OutFile,"%g ",(Real)xsize/XRange);
  1961.     fprintf(OutFile,"%g ",(Real)ysize/YRange);
  1962. #else
  1963.     fprintf(OutFile,"%d %d translate\n",xpos,ypos+ysize);
  1964.     fprintf(OutFile,"%g ",(Real)xsize/XRange);
  1965.     fprintf(OutFile,"%g ",(Real)-ysize/YRange);
  1966. #endif
  1967.     fputs("scale\n/mtrx matrix currentmatrix def\n\n",OutFile);
  1968.  
  1969.     fputs("newpath 0 0 moveto 0 ",OutFile);
  1970.     fprintf(OutFile,"%d rlineto %d 0 rlineto 0 %d",YRange,XRange,-YRange);
  1971.     fputs(" rlineto\nclosepath clip ",OutFile);
  1972.     if( BackR || BackG || BackB )
  1973.     {   fprintf(OutFile,"%g %g %g",BackR/255.0,BackG/255.0,BackB/255.0);
  1974.     fputs(" setrgbcolor fill\n\n",OutFile);
  1975.     } else fputs("newpath\n\n",OutFile);
  1976.  
  1977.     LineWidth = 1.0;
  1978.     VectSolid = True;
  1979.     VectCol = 0;
  1980.  
  1981.     i = 0;
  1982.     ForEachAtom
  1983.     if( aptr->flag&SphereFlag )
  1984.         if( !UseClipping || !ClipVectSphere(aptr) )
  1985.         {   type[i] = PSSphere; 
  1986.         data[i++] = aptr;
  1987.         }
  1988.  
  1989.     ForEachBond
  1990.        if( bptr->flag&DrawBondFlag )
  1991.        if( !UseClipping || !ClipVectBond(bptr) )
  1992.        {   type[i] = (bptr->flag&CylinderFlag)? PSStick:PSLine;
  1993.            data[i++] = bptr;
  1994.        } 
  1995.  
  1996.     ForEachBack
  1997.        if( bptr->flag&DrawBondFlag )
  1998.        if( !UseClipping || !ClipVectBond(bptr) )
  1999.        {   type[i] = (bptr->flag&CylinderFlag)? PSStick:PSLine;
  2000.            data[i++] = bptr; 
  2001.        } 
  2002.  
  2003.  
  2004.     if( count>1 )
  2005.     DepthSort(data,type,(int)count);
  2006.  
  2007.     for( i=0; i<count; i++ )
  2008.     if( type[i]==PSSphere )
  2009.     {   WriteVectSphere( data, type, i );
  2010.     } else if( type[i]==PSStick )
  2011.     {   WriteVectStick( data[i] );
  2012.     } else /* PSWire */
  2013.         WriteVectWire( data[i] );
  2014.  
  2015.     if( DrawDots )
  2016.     WriteVectDots();
  2017.     if( DrawLabels )
  2018.     WriteVectLabels();
  2019.  
  2020.     fputs("newpath 0 0 moveto 0 ",OutFile);
  2021.     fprintf(OutFile,"%d rlineto %d 0 rlineto 0 %d",YRange,XRange,-YRange);
  2022.     fputs(" rlineto\nclosepath 0 setgray 1 setlinewidth stroke\n",OutFile);
  2023.     fputs("end grestore\nshowpage\n",OutFile);
  2024.     fputs("%%Trailer\n",OutFile);
  2025.     fputs("%%EOF\n",OutFile);
  2026.  
  2027.     fclose( OutFile );
  2028. #ifdef APPLEMAC
  2029.     /* Avoid ANSI trigraph problems! */
  2030.     SetFileInfo(name,'\?\?\?\?','EPSF',134);
  2031. #endif
  2032.     _ffree( data );
  2033.     _ffree( type );
  2034.     return(True);
  2035. }
  2036.  
  2037.  
  2038. static void WritePICTPixel( i )
  2039.     int i;
  2040. {
  2041. #ifdef EIGHTBIT
  2042.     putc( (int)LutInv[i], OutFile );
  2043. #else
  2044.     putc( i, OutFile );
  2045. #endif
  2046. }
  2047.  
  2048.  
  2049. static int FlushPICTBuffer()
  2050. {
  2051.     register int result;
  2052.     register int i;
  2053.  
  2054.     if( RLEOutput )
  2055.     {   putc(PacketLen-1,OutFile);
  2056.     for( i=0; i<PacketLen; i++ )
  2057.         WritePICTPixel( PICTBuffer[i] );
  2058.     }
  2059.     result = PacketLen+1;
  2060.     PacketLen = 0;
  2061.     return( result );
  2062. }
  2063.  
  2064.  
  2065. static int FlushPICTPacket()
  2066. {
  2067.     register int result;
  2068.     register int i;
  2069.  
  2070.     if( RLELength>2 )
  2071.     {   if( PacketLen )
  2072.     {   result = FlushPICTBuffer();
  2073.     } else result = 0;
  2074.  
  2075.     if( RLEOutput )
  2076.     {   putc(257-RLELength,OutFile);
  2077.         WritePICTPixel(PICTPixel);
  2078.     }
  2079.     result += 2;
  2080.     } else 
  2081.     {   result = 0;
  2082.     for( i=0; i<RLELength; i++ )
  2083.     {   PICTBuffer[PacketLen++] = PICTPixel;
  2084.         if( PacketLen==128 ) 
  2085.         result  += FlushPICTBuffer();
  2086.     }
  2087.     }
  2088.     return( result );
  2089. }
  2090.  
  2091.  
  2092. static int WritePICTCode( val )
  2093.     int val;
  2094. {
  2095.     register int result;
  2096.  
  2097.     result = 0;
  2098.     if( !RLELength )
  2099.     {   PICTPixel = val;
  2100.         RLELength = 1;
  2101.     } else if( (val!=PICTPixel) || (RLELength==128) )
  2102.     {   result = FlushPICTPacket();
  2103.         PICTPixel = val;
  2104.         RLELength = 1;
  2105.     } else RLELength++;
  2106.     return( result );
  2107. }
  2108.  
  2109. static Card WritePICTData()
  2110. {
  2111. #ifndef EIGHTBIT
  2112.     register Pixel data;
  2113. #endif
  2114.     register Pixel __huge *ptr;
  2115.     register Pixel __huge *tmp;
  2116.     register int rowbytes;
  2117.     register Card result;
  2118.     register int size;
  2119.     register int x,y;
  2120.  
  2121. #ifdef IBMPC
  2122.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  2123. #endif
  2124.  
  2125. #ifdef EIGHTBIT
  2126.     rowbytes = XRange;
  2127. #else
  2128.     rowbytes = XRange*3;
  2129. #endif
  2130.  
  2131.     result = 0;
  2132. #ifndef INVERT
  2133.     ptr = FBuffer;
  2134. #endif
  2135.     for( y=YRange-1; y>=0; y-- )
  2136.     {
  2137. #ifdef INVERT
  2138.     ptr = FBuffer + (Long)y*XRange;
  2139. #endif
  2140.  
  2141.     RLEOutput = False;
  2142.     PacketLen = 0;
  2143.     RLELength = 0;
  2144.  
  2145.     size = 0;
  2146. #ifdef EIGHTBIT
  2147.     tmp = ptr;
  2148.     for( x=0; x<XRange; x++ )
  2149.         size += WritePICTCode( *tmp++ );
  2150. #else
  2151.     tmp = ptr;
  2152.     for( x=0; x<XRange; x++ )
  2153.         size += WritePICTCode( (int)RComp(*tmp++) );
  2154.     tmp = ptr;
  2155.     for( x=0; x<XRange; x++ )
  2156.         size += WritePICTCode( (int)GComp(*tmp++) );
  2157.     tmp = ptr;
  2158.     for( x=0; x<XRange; x++ )
  2159.         size += WritePICTCode( (int)BComp(*tmp++) );
  2160. #endif
  2161.     size += FlushPICTPacket();
  2162.     if( PacketLen )
  2163.         size += FlushPICTBuffer();
  2164.  
  2165. #ifdef EIGHTBIT
  2166.     if( rowbytes > 250 )
  2167.     {   WriteMSBShort(size);
  2168.         result += (size+2);
  2169.     } else
  2170.     {   putc(size,OutFile);
  2171.         result += (size+1);
  2172.     }
  2173. #else
  2174.     WriteMSBShort(size);
  2175.     result += (size+2);
  2176. #endif
  2177.  
  2178.     RLEOutput = True;
  2179.     PacketLen = 0;
  2180.     RLELength = 0;
  2181.  
  2182. #ifdef EIGHTBIT
  2183.     for( x=0; x<XRange; x++ )
  2184.         (void)WritePICTCode( *ptr++ );
  2185. #else
  2186.     tmp = ptr;
  2187.     for( x=0; x<XRange; x++ )
  2188.         (void)WritePICTCode( (int)RComp(*tmp++) );
  2189.     tmp = ptr;
  2190.     for( x=0; x<XRange; x++ )
  2191.         (void)WritePICTCode( (int)GComp(*tmp++) );
  2192.     for( x=0; x<XRange; x++ )
  2193.         (void)WritePICTCode( (int)BComp(*ptr++) );
  2194. #endif
  2195.     (void)FlushPICTPacket();
  2196.     if( PacketLen )
  2197.         (void)FlushPICTBuffer();
  2198.     }
  2199.  
  2200. #ifdef IBMPC
  2201.     GlobalUnlock(FBufHandle);
  2202. #endif
  2203.     return(result);
  2204. }
  2205.  
  2206.  
  2207. int WritePICTFile( name )
  2208.     char *name;
  2209. {
  2210. #ifdef EIGHTBIT
  2211.     register int j,r,g,b;
  2212. #endif
  2213.     register Card size;
  2214.     register int cols;
  2215.     register int i;
  2216.  
  2217. #if defined(IBMPC) || defined(APPLEMAC)
  2218.     OutFile = fopen(name,"wb");
  2219. #else
  2220.     OutFile = fopen(name,"w");
  2221. #endif
  2222.     if( !OutFile )
  2223.     {    FatalOutputError(name);
  2224.      return( False );
  2225.     }
  2226.  
  2227. #ifdef EIGHTBIT
  2228.     cols = CompactColourMap();
  2229. #endif
  2230.  
  2231.     /* Write out header */
  2232.     for( i=0; i<512; i++ )
  2233.     putc( 0, OutFile );
  2234.  
  2235.     size = 0;
  2236.     WriteMSBShort( size );  /* picSize */
  2237.     WriteMSBShort(0);       /* picFrame.top    */
  2238.     WriteMSBShort(0);       /* picFrame.left   */
  2239.     WriteMSBShort(YRange);  /* picFrame.bottom */
  2240.     WriteMSBShort(XRange);  /* picFrame.right  */
  2241.  
  2242.     WriteMSBShort(PICTpicversion);
  2243.     WriteMSBShort(0x02FF);
  2244.  
  2245.     WriteMSBShort(PICTheaderop);
  2246.     WriteMSBLong((Card)0xffffffff);
  2247.     WriteMSBShort(0);      WriteMSBShort(0);
  2248.     WriteMSBShort(0);      WriteMSBShort(0);
  2249.     WriteMSBShort(XRange); WriteMSBShort(0);
  2250.     WriteMSBShort(YRange); WriteMSBShort(0);
  2251.     WriteMSBLong(0);
  2252.  
  2253.     WriteMSBShort(PICTcliprgn);
  2254.     WriteMSBShort(10);      /* rgnSize */
  2255.     WriteMSBShort(0);       /* rgnBBox.top    */
  2256.     WriteMSBShort(0);       /* rgnBBox.left   */
  2257.     WriteMSBShort(YRange);  /* rgnBBox.bottom */
  2258.     WriteMSBShort(XRange);  /* rgnBBox.right  */
  2259.  
  2260. #ifdef EIGHTBIT
  2261.     WriteMSBShort(PICTpackbitsrect);
  2262. #else
  2263.     WriteMSBShort(PICTdirectbitsrect);
  2264.     WriteMSBShort(0x0000);  /* baseAddr      */
  2265.     WriteMSBShort(0x00ff);
  2266. #endif
  2267.     i = (XRange*sizeof(Pixel)) | 0x8000;
  2268.     WriteMSBShort( i );     /* rowBytes      */
  2269.     WriteMSBShort(0);       /* bounds.top    */
  2270.     WriteMSBShort(0);       /* bounds.left   */
  2271.     WriteMSBShort(YRange);  /* bounds.bottom */
  2272.     WriteMSBShort(XRange);  /* bounds.right  */
  2273.     WriteMSBShort(0);       /* pmVersion     */
  2274. #ifdef EIGHTBIT
  2275.     WriteMSBShort(0);       /* packType      */
  2276. #else
  2277.     WriteMSBShort(4);       /* packType      */
  2278. #endif
  2279.     WriteMSBLong(0);        /* packSize      */
  2280.     WriteMSBLong(72);       /* hRes          */
  2281.     WriteMSBLong(72);       /* vRes          */
  2282.  
  2283. #ifdef EIGHTBIT
  2284.     WriteMSBShort(0);       /* pixelType     */
  2285.     WriteMSBShort(8);       /* pixelSize     */
  2286.     WriteMSBShort(1);       /* cmpCount      */
  2287.     WriteMSBShort(8);       /* cmpSize       */
  2288. #else
  2289.     WriteMSBShort(16);      /* pixelType     */
  2290.     WriteMSBShort(32);      /* pixelSize     */
  2291.     WriteMSBShort(3);       /* cmpCount      */
  2292.     WriteMSBShort(8);       /* cmpSize       */
  2293. #endif
  2294.  
  2295.     WriteMSBLong(0);        /* planeBytes    */
  2296.     WriteMSBLong(0);        /* pmTable       */
  2297.     WriteMSBLong(0);        /* pmReserved    */
  2298.  
  2299. #ifdef EIGHTBIT
  2300.     WriteMSBLong(0);        /* ctSeed        */
  2301.     WriteMSBShort(0);       /* ctFlags       */
  2302.     WriteMSBShort(cols-1);  /* ctSize        */
  2303.  
  2304.     for( i=0; i<cols; i++ )
  2305.     {    WriteMSBShort(i);  /* value */
  2306.      j=Node[i]; r=RLut[j]; g=GLut[j]; b=BLut[j];
  2307.      WriteMSBShort( (r<<8)|r );  /* rgb.red */
  2308.      WriteMSBShort( (g<<8)|g );  /* rgb.green */
  2309.      WriteMSBShort( (b<<8)|b );  /* rgb.blue  */
  2310.     }
  2311. #endif
  2312.  
  2313.     WriteMSBShort(0);       /* srcRect.top    */
  2314.     WriteMSBShort(0);       /* srcRect.left   */
  2315.     WriteMSBShort(YRange);  /* srcRect.bottom */
  2316.     WriteMSBShort(XRange);  /* srcRect.right  */
  2317.     WriteMSBShort(0);       /* dstRect.top    */
  2318.     WriteMSBShort(0);       /* dstRect.left   */
  2319.     WriteMSBShort(YRange);  /* dstRect.bottom */
  2320.     WriteMSBShort(XRange);  /* dstRect.right  */
  2321.     WriteMSBShort(0);       /* mode (srcCopy) */
  2322.  
  2323.     size = WritePICTData();
  2324.     if( size & 0x01 ) putc(0,OutFile);
  2325.     WriteMSBShort(PICTendofpict);
  2326.     fclose(OutFile);
  2327. #ifdef APPLEMAC
  2328.     SetFileInfo(name,'ttxt','PICT',134);
  2329. #endif
  2330.     return( True );
  2331. }
  2332.  
  2333.  
  2334. int WriteIRISFile( name, encode )
  2335.     char *name;  int encode;
  2336. {
  2337.     return( True );
  2338. }
  2339.  
  2340.  
  2341. void InitialiseOutFile()
  2342. {
  2343. #if defined(IBMPC) || defined(APPLEMAC)
  2344.     /* Allocate Tables on FAR Heap */
  2345.     ABranch = (short __far*)_fmalloc(4096*sizeof(short));
  2346.     DBranch = (short __far*)_fmalloc(4096*sizeof(short));
  2347.     Hash = (short __far*)_fmalloc(256*sizeof(short));
  2348.     Node = (Byte __far*)_fmalloc(4096*sizeof(Byte));
  2349. #endif
  2350.  
  2351.     KinemageFlag = False;
  2352.     UseOutLine = False;
  2353. }
  2354.  
  2355.