CCL Home Page
Up Directory CCL outfile.c
/* outfile.c
 * RasMol2 Molecular Graphics
 * Roger Sayle, August 1995
 * Version 2.6
 */
#define OUTFILE
#include "rasmol.h"

#ifdef IBMPC
#include 
#include 
#endif
#ifdef APPLEMAC
#include 
#include 
#ifdef __CONDITIONALMACROS__
#include 
#else
#include 
#endif
#endif
#ifndef sun386
#include 
#endif

#include 
#include 
#include 

#include "outfile.h"
#include "molecule.h"
#include "command.h"
#include "abstree.h"
#include "transfor.h"
#include "render.h"
#include "repres.h"
#include "graphics.h"
#include "pixutils.h"
#include "script.h"


#ifdef EIGHTBIT
#define RComp(x)   (RLut[LutInv[x]])
#define GComp(x)   (GLut[LutInv[x]])
#define BComp(x)   (BLut[LutInv[x]])
#else
#define RComp(x)   (((x)>>16)&0xff)
#define GComp(x)   (((x)>>8)&0xff)
#define BComp(x)   ((x)&0xff)
#endif


#ifdef INVERT
#define InvertY(y) (y)
#else
#define InvertY(y) (-(y))
#endif


/* Sun rasterfile.h macro defns */
#define RAS_MAGIC       0x59a66a95
#define RAS_RLE         0x80
#define RT_STANDARD     1
#define RT_BYTE_ENCODED 2
#define RMT_NONE        0
#define RMT_EQUAL_RGB   1

/* Standard A4 size page: 8.267x11.811 inches */
/* U.S. Normal size page: 8.500x11.000 inches */
#define PAGEHIGH  (11.811*72.0)
#define PAGEWIDE  (8.267*72.0)
#define BORDER    0.90

/* Compression Ratio   0clist;chain;chain=chain->cnext) \
		     for(group=chain->glist;group;group=group->gnext)    \
		     for(aptr=group->alist;aptr;aptr=aptr->anext)
#define ForEachBond  for(bptr=Database->blist;bptr;bptr=bptr->bnext)
#define ForEachBack  for(chain=Database->clist;chain;chain=chain->cnext) \
		     for(bptr=chain->blist;bptr;bptr=bptr->bnext)



#ifdef APPLEMAC
/* External RasMac Function Declaration! */
void SetFileInfo( char*, OSType, OSType, short );
#endif

static void FatalOutputError( ptr )
    char *ptr;
{
    if( CommandActive ) WriteChar('\n');
    WriteString("Output Error: Unable to create file `");
    WriteString( ptr );  WriteString("'!\n");
    CommandActive = False;
}


/*  Integer Output Routines  */
#ifdef FUNCPROTO
static void WriteLSBLong( Card );
static void WriteMSBLong( Card );
#endif

static void WriteByte( val )
    int val;
{
    putc( val, OutFile );
}

static void WriteLSBShort( val )
    int val;
{
    putc( val&0xff, OutFile );
    putc( (val>>8)&0xff, OutFile );
}

static void WriteMSBShort( val )
    int val;
{
    putc( (val>>8)&0xff, OutFile );
    putc( val&0xff, OutFile );
}

static void WriteLSBLong( val )
    Card val;
{
    putc((int)(val&0xff),OutFile);
    putc((int)((val>>8) &0xff),OutFile);
    putc((int)((val>>16)&0xff),OutFile);
    putc((int)((val>>24)&0xff),OutFile);
}

static void WriteMSBLong( val )
    Card val;
{
    putc((int)((val>>24)&0xff),OutFile);
    putc((int)((val>>16)&0xff),OutFile);
    putc((int)((val>>8) &0xff),OutFile);
    putc((int)(val&0xff),OutFile);
}


static void CalcInvColourMap()
{
#ifdef EIGHTBIT
    register int i;

    for( i=0; i<256; i++ )
        if( ULut[i] )
            LutInv[Lut[i]] = i;
#endif
}


#ifdef EIGHTBIT
static int CompactColourMap()
{
    register Pixel __huge *ptr;
    register Long pos, count;
    register int i, cols;

    CalcInvColourMap();
    for( i=0; i<256; i++ )
    {   Buffer[i] = 0;
	Node[i] = 5;
    }

#ifdef IBMPC
    ptr = (Pixel __huge*)GlobalLock(FBufHandle);    
#else
    ptr = FBuffer;
#endif

    cols = 0;
    count = (Long)XRange*YRange;
    for( pos=0; pos99 )
    {   putc((i/100)+'0',OutFile); i %= 100;
	putc((i/10) +'0',OutFile); i %= 10;
    } else if( i>9 )
    {   putc((i/10)+'0',OutFile);  i %= 10;
    }
    putc(i+'0',OutFile);
}


int WritePPMFile( name, raw )
    char *name;  int raw;
{
    register Pixel __huge *ptr;
    register int i,col;
    register int x,y;

#if defined(IBMPC) || defined(APPLEMAC)
    OutFile = fopen(name, (raw?"wb":"w") );
#else
    OutFile = fopen(name,"w");
#endif

    if( !OutFile ) 
    {   FatalOutputError(name);
	return( False );
    }

    CalcInvColourMap();
    fprintf(OutFile,"P%c %d %d 255\n",(raw?'6':'3'),XRange,YRange);

#ifdef IBMPC
    FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
#endif

#ifndef INVERT
    ptr = FBuffer;
#endif

    if( !raw )
    {   col = 0;
	for( y=YRange-1; y>=0; y-- )
	{
#ifdef INVERT
	    ptr = FBuffer + (Long)y*XRange;
#endif
	    for( x=0; x=0; y-- )
	{
#ifdef INVERT
	    ptr = FBuffer + (Long)y*XRange;
#endif
	    for( x=0; x max )
    {    
#ifdef IBMPC
	 Buffer[PacketLen++]=(Byte)(BitBuffer&0xff);
#else
	 Buffer[PacketLen++]=BitBuffer;
#endif
	 BitBuffer >>= 8;
	 BitBufLen -= 8;

	if( PacketLen==255 )
	{   WriteByte(0xff);
	    fwrite((char*)Buffer,1,255,OutFile);
	    PacketLen = 0;
	}
    }
}

int WriteGIFFile( name )
    char *name;
{
    register int i,j,cols;
    register int pref,next,last;
    register int isize, ilast;
    register Pixel __huge *ptr;
    register short __far *prev;
    register int x,y,init;

#ifdef EIGHTBIT
    cols = CompactColourMap();
    if( cols<2 ) return( False );

    for( isize=2; isize<8; isize++ )
	if( (1<= cols ) break;
    cols = 1<=0; y-- )
    {   
#ifdef INVERT
	ptr = FBuffer + (Long)y*XRange;
#endif
	for( x=0; x1)? 3 : 2;
    } else
	if( RLEOutput )
	{   if( RLELength>2 )
	    {   WriteByte(RAS_RLE);
		WriteByte(RLELength-1);
	    } else if( RLELength==2 )
		WriteByte(RLEChar);
	    WriteByte(RLEChar);
	} else RLEFileSize += MinFun(RLELength,3);
}


static void WriteRastRLECode( val )
    int val;
{
    if( RLEEncode )
    {   if( !RLELength )
	{   RLELength = 1;
	    RLEChar = val;
	} else if( (RLEChar!=val) || (RLELength==256) )
	{   FlushRastRLE();
            RLELength = 1;
            RLEChar = val;
        } else RLELength++;
    } else WriteByte(val);
}

static void WriteRastRLEPad()
{
    if( RLEEncode )
    {   if( !RLELength || (RLELength==256) )
	{   WriteRastRLECode(0x00);
	} else RLELength++;
    } else WriteByte(0x00);
}


static void WriteRastData( output )
    int output;
{
    register Pixel __huge *ptr;
    register int x,y,pad;
#ifndef EIGHTBIT
    register int i;
#endif

#ifdef IBMPC
    FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
#endif

#ifndef INVERT
    ptr = FBuffer;
#endif

    pad = XRange%2;

    RLEOutput = output;
    RLEFileSize = 0;
    RLELength = 0;

    for( y=YRange-1; y>=0; y-- )
    {   
#ifdef INVERT
	ptr = FBuffer + (Long)y*XRange;
#endif
	for( x=0; x>4] );
    WriteByte( hex[val&0x0f] );
    if( (LineLength+=2) > 72 )
    {   WriteByte('\n');
	LineLength = 0;
    }
}

static void EncodeEPSFPixel( val, col )
    int val, col;
{
    register int r, g, b;
    register int i;

    r = RComp(val);
    g = GComp(val);
    b = BComp(val);

    if( col )
    {   OutputEPSFByte( r );
	OutputEPSFByte( g );
	OutputEPSFByte( b );
    } else
    {   i = (20*r + 32*g + 12*b)>>6;
	OutputEPSFByte( i );
    }
}

int WriteEPSFFile( name, col, compr )
    char *name;  int col, compr;
{
    register int x, y, i, j;
    register int xsize, ysize;
    register int xpos, ypos;
    register int rotpage;

    register Pixel __huge *ptr;
    int RLEBuffer[128];

    OutFile = fopen(name,"w");
    if( !OutFile )
    {   FatalOutputError(name);
	return(False);
    }

    CalcInvColourMap();
    if( XRange <= YRange )
    {   rotpage = False; 
	xsize = XRange; 
	ysize = YRange;
    } else
    {   rotpage = True;  
	xsize = YRange; 
	ysize = XRange;
    }

    if( xsize > (int)(BORDER*PAGEWIDE) )
    {   ysize = (int)(ysize*(BORDER*PAGEWIDE)/xsize);
	xsize = (int)(BORDER*PAGEWIDE);
    }
    if( ysize > (int)(BORDER*PAGEHIGH) )
    {   xsize = (int)(xsize*(BORDER*PAGEHIGH)/ysize);
	ysize = (int)(BORDER*PAGEHIGH);
    }

    xpos = (int)(PAGEWIDE-xsize)/2;
    ypos = (int)(PAGEHIGH-ysize)/2;

    fputs("%!PS-Adobe-2.0 EPSF-2.0\n",OutFile);
    fputs("%%Creator: RasMol Version 2.6\n",OutFile);
    fprintf(OutFile,"%%%%Title: %s\n",name);
    fprintf(OutFile,"%%%%BoundingBox: %d %d ",xpos,ypos);
    fprintf(OutFile,"%d %d\n",xpos+xsize,ypos+ysize);

    fputs("%%Pages: 1\n",OutFile);
    fputs("%%EndComments\n",OutFile);
    fputs("%%EndProlog\n",OutFile);
    fputs("%%Page: 1 1\n",OutFile);

    fputs("gsave\n",OutFile);
    fputs("10 dict begin\n",OutFile);
    fprintf(OutFile,"%d %d translate\n",xpos,ypos);
    fprintf(OutFile,"%d %d scale\n",xsize,ysize);
    if( rotpage )
    {   fputs("0.5 0.5 translate\n",OutFile);
	fputs("90 rotate\n",OutFile);
	fputs("-0.5 -0.5 translate\n",OutFile);
    }
    fputc('\n',OutFile);

    if( compr )
    {   fputs("/rlecount 0 def\n",OutFile);
	fputs("/rlebyte 1 string def\n",OutFile);
	fprintf(OutFile,"/pixbuf %d string def\n", col?3:1 );
	fputs("/reppixel { pixbuf } def\n",OutFile);
	fputs("/getpixel { \n",OutFile);
	fputs("  currentfile pixbuf readhexstring pop\n",OutFile);
	fputs("} def\n\n",OutFile);

	if( col )
	{   fputs("/colorimage where {\n",OutFile);
	    fputs("  pop\n",OutFile);
	    fputs("} {\n",OutFile);
	    fputs("  /bytebuf 1 string def\n",OutFile);
	    fputs("  /colorimage { pop pop image } def\n",OutFile);
	    fputs("  /reppixel { bytebuf } def\n",OutFile);
	    fputs("  /getpixel {\n",OutFile);
	    fputs("    currentfile pixbuf readhexstring pop pop\n",OutFile);
	    fputs("    bytebuf 0\n",OutFile);
	    fputs("    pixbuf 0 get 20 mul\n",OutFile);
	    fputs("    pixbuf 1 get 32 mul\n",OutFile);
	    fputs("    pixbuf 2 get 12 mul\n",OutFile);
	    fputs("    add add -6 bitshift put bytebuf\n",OutFile);
	    fputs("  } def\n",OutFile);
	    fputs("} ifelse\n\n",OutFile);
	}

	fputs("/rledecode {\n",OutFile);
	fputs("  rlecount 0 eq {\n",OutFile);
	fputs("    currentfile rlebyte readhexstring pop\n",OutFile);
	fprintf(OutFile,"    0 get dup %d gt {\n",EPSFCompRatio);
	fprintf(OutFile,"      /rlecount exch %d sub def\n",EPSFCompRatio);
	fputs("      /rleflag true def\n",OutFile);
	fputs("    } {\n",OutFile);
	fputs("      /rlecount exch def\n",OutFile);
	fputs("      /rleflag false def\n",OutFile);
	fputs("    } ifelse getpixel\n",OutFile);
	fputs("  } {\n",OutFile);
	fputs("    /rlecount rlecount 1 sub def\n",OutFile);
	fputs("    rleflag { reppixel } { getpixel } ifelse\n",OutFile);
	fputs("  } ifelse\n",OutFile);
	fputs("} def\n",OutFile);
    } else if( col )
    {   fprintf(OutFile,"/scanbuf %d string def\n",XRange*3);
	fputs("/colorimage where {\n",OutFile);
	fputs("  pop\n",OutFile);
	fputs("} {\n",OutFile);
	fputs("  /pixbuf 3 string def\n",OutFile);
	fputs("  /bytebuf 1 string def\n",OutFile);
	fputs("  /colorimage {\n",OutFile);
	fputs("    pop pop pop {\n",OutFile);
	fputs("      currentfile pixbuf readhexstring pop pop\n",OutFile);
	fputs("      bytebuf 0\n",OutFile);
	fputs("      pixbuf 0 get 20 mul\n",OutFile);
	fputs("      pixbuf 1 get 32 mul\n",OutFile);
	fputs("      pixbuf 2 get 12 mul\n",OutFile);
	fputs("      add add -6 bitshift put bytebuf\n",OutFile);
	fputs("    } image\n",OutFile);
	fputs("  } def\n",OutFile);
	fputs("} ifelse\n\n",OutFile);
    } else fprintf(OutFile,"/scanbuf %d string def\n\n",XRange);

    fprintf(OutFile,"%d %d %d\n",XRange,YRange,8);
    fprintf(OutFile,"[%d 0 0 -%d 0 %d]\n",XRange,YRange,YRange);

    if( !compr )
    {   fputs("{ currentfile scanbuf readhexstring pop }\n",OutFile);
    } else fputs("{ rledecode }\n",OutFile);
    if( col ) fputs("false 3 color",OutFile);
    fputs("image\n",OutFile);

#ifdef IBMPC
    FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
#endif

#ifndef INVERT
    ptr = FBuffer; 
#endif

    RLELength = 0;
    LineLength = 0;
    for( y=YRange-1; y>=0; y-- )
    {
#ifdef INVERT
	ptr = FBuffer + (Long)y*XRange;
#endif
	for( x=0; x1 )
			{   OutputEPSFByte(RLELength-2);
			    for( j=0; j BMPCount+5 )
    {   FlushBMPPackets();
	return;
    }
    
    /* Flush AbsMode buffer */
    if( PacketLen+BMPTotal>255 )
	FlushBMPBuffer();
    

    /* Cannot leave RLEMode */
    if( PacketLen+BMPTotal<3 )
	return;
	
    /* Determine AbsMode cost */
    if( PacketLen )
    {   cost = BMPTotal - (PacketLen%2);
	cost += (cost%2);
    } else cost = (BMPTotal%2)+BMPTotal+2;    

    /* Put RLE Packets into AbsMode buffer */
    if( cost <= (int)(BMPCount<<1) )
    {   for( i=0; i=0; y-- )
    {
#ifndef INVERT
	ptr = FBuffer + (Long)y*XRange;
#endif
	for( x=0; x=0; y-- )
	{
#ifndef INVERT
	    ptr = FBuffer + (Long)y*XRange;
#endif
	    for( x=0; xz );

        case(PSBond):    bond = (Bond __far*)item;
	                 result = bond->srcatom->z;
	                 if( result < bond->dstatom->z )
	                     result = bond->dstatom->z;
                         return( result );

        case(PSSSBond):  
        case(PSHBond):   hbond = (HBond __far*)item;
                         if( (type==PSHBond)? HBondMode : SSBondMode )
                         {   result = hbond->srcCA->z;
                             if( result < hbond->dstCA->z )
                                 result = hbond->dstCA->z;
                         } else
                         {   result = hbond->src->z;
                             if( result < hbond->dst->z )
                                 result = hbond->dst->z;
                         }
                         return( result );

        case(PSMonit):   monit = (Monitor*)item;
                         result = monit->src->z;
                         if( result < monit->dst->z )
                             result = monit->dst->z;
                         return( result );
    }
    return( 0 );
}


static void DepthSort( data, type, count )
    PSItemPtr __far *data;
    char __far *type;
    int count;
{
    register char ttmp;
    register void __far *dtmp;
    register int i, j, k;
    register int depth;
    register int temp;

    for( i=1; ij; k-- )
	    {    data[k] = data[k-1];
		 type[k] = type[k-1];
	    }
	    data[j] = dtmp;
	    type[j] = ttmp;
	}
    }
}

#ifdef FUNCPROTO
static int ClipVectSphere( Atom __far* );
static int ClipVectBond( Atom __far*, Atom __far* );

static void WriteVectSphere( PSItemPtr __far*, char __far*, int );
static void WriteVectStick( Atom __far*, Atom __far*, int, int );
static void WriteVectWire( Atom __far*, Atom __far*, int, int );

static Long CountPSItems();
static void FetchPSItems( PSItemPtr __far*, char __far* );
static void WritePSItems( PSItemPtr __far*, char __far*, int );
#endif


static int ClipVectSphere( ptr )
    Atom __far *ptr;
{
    register int rad;

    rad = ptr->irad;

    if( ptr->x + rad < 0 )  return( True );
    if( ptr->y + rad < 0 )  return( True );
    if( ptr->x - rad >= XRange )  return( True );
    if( ptr->y - rad >= YRange )  return( True );
    return( False );
}


static int ClipVectBond( src, dst )
    Atom __far *src;
    Atom __far *dst;
{
    if( !src || !dst )  return( True );
    if( (src->x<0) && (dst->x<0) )  return( True );
    if( (src->y<0) && (dst->y<0) )  return( True );
    if( (src->x>=XRange) && (dst->x>=XRange) )  return( True );
    if( (src->y>=YRange) && (dst->y>=YRange) )  return( True );
    return( False );
}



static void WriteVectColour( col )
    int col;
{
    if( col != VectCol )
    {   fprintf(OutFile,"%g ",(Real)RLut[col]/255.0);
	fprintf(OutFile,"%g ",(Real)GLut[col]/255.0);
	fprintf(OutFile,"%g ",(Real)BLut[col]/255.0);
	fputs("setrgbcolor\n",OutFile);
	VectCol = col;
    }
}


#define MAXSECT 5
typedef struct {
	/* Ellipse */
	Real ephi,epsi;
	Real etheta;
	Real ex,ey;
	Real erad;

	/* Sphere */
	Real sphi,spsi;
	int sx,sy;
	Real srad;
    } SphereSect;


static int VectClipContain( x, y )
    SphereSect *x; SphereSect *y;
{
    if( x->erad != 0.0 )
    {   if( y->erad != 0.0 )
	    /* Simple segment containment test! */
	    return( ((x->sphi+x->spsi)>=(y->sphi+y->spsi)) &&
		    ((x->sphi-x->spsi)<=(y->sphi-y->spsi)) );
    } else if( y->erad == 0.0 )
	return( x->srad >= y->srad );
    return( False );
}


static void WriteVectSphere( data, type, index )
    PSItemPtr __far*data; 
    char __far *type;
    int index;
{
    register int ecount, count;
    register Atom __far *atm;
    register Atom __far *ptr;
    register Long dist2,dist3;
    register int dx, dy, dz;
    register int i,j,k;

    register Real b,d,f,g,x;
    register Real radf,radb;
    register Real phi1,phi2;
    register Real temp,psi;
    register Real theta;

    register SphereSect *sptr;
    SphereSect sect[MAXSECT];

    ptr = (Atom __far*)data[index];
    radf = ptr->radius*Scale;

    count = 0;
    ecount = 0;
    sptr = sect;
    for( i=index-1; i>=0; i-- )
    {   if( type[i] != PSAtom )
	    continue;

	atm = (Atom __far*)data[i];
	/* Atom can't intersect visibly! */
	if( atm->z + atm->irad < ptr->z )
	    continue;

	dx = atm->x - ptr->x; 
	dy = atm->y - ptr->y; 
	dz = atm->z - ptr->z;

	dist2 = (Long)dx*dx + (Long)dy*dy;
	dist3 = dist2 + dz*dz;

	radb = atm->radius*Scale;  
	temp = radf + radb;

	/* Atoms don't intersect! */
	if( dist3 > temp*temp ) continue;


	d = sqrt( (double)dist3 );
	f = (temp*(radf-radb)+dist3)/(2.0*d);
	theta = -dz/d;

	if( f>0 )
	{   temp = radf*radf;
	    /* Intersection not visible! */
	    if( theta*temp > temp-f*f )
		continue;
	} else if( f < -radf )
	    return;

	x = sqrt( (radf-f)*(radf+f) );

	if( dx || dy )
	{   g = sqrt( (double)dist2 );
	    psi = Rad2Deg*atan2(dy,dx);
	    b = (f*(dz*dz))/(d*g);

	    if( AbsFun(b)>x )
		continue;

	    phi1 = b + (f*g)/d;
	    phi1 = Rad2Deg*acos(phi1/radf);
	    if( phi1!=phi1 ) continue;

	    phi2 = (d*b)/g;
	    if( AbsFun(phi2) < x )
	    {   phi2 = Rad2Deg*acos(phi2/x);
		if( phi2!=phi2 ) continue;
		if( phi2 > 90.0 ) 
		    phi2 = 180.0-phi1;
	    } else phi2 = 90.0;

	    sptr->erad = x;
	    sptr->etheta = -theta;
	    sptr->ephi = psi;
	    sptr->epsi = phi2;

	    temp = f/d;
	    sptr->ex = ptr->x+temp*dx;
	    sptr->ey = ptr->y+temp*dy;

	    sptr->srad = radf;
	    sptr->sphi = psi;
	    sptr->spsi = phi1;
	    sptr->sx = ptr->x;
	    sptr->sy = ptr->y;

	} else
	{   x = sqrt( (radf-g)*(radf+g) );

	    sptr->srad = x;
	    sptr->erad = 0.0;
	    sptr->sx = ptr->x;
	    sptr->sy = ptr->y;
	    sptr->sphi = 180;
	    sptr->spsi = -180;
	}

	/* Optimize Segments */
	j = 0;
	while( jerad != 0.0 )
		ecount++;
	    if( count==MAXSECT )
		break;
	}
    }

    if( UseOutLine )
    {   temp = (ptr->z-ZOffset)/ImageSize + 1.0;
	if( temp != LineWidth )
	{   fprintf(OutFile,"%g setlinewidth\n",temp);
	    LineWidth = temp;
	}
    }

    if( !VectSolid )
    {   fputs("[] 0 setdash\n",OutFile);
        VectSolid = True;
    }

    if( count )
    {   fputs("gsave\n",OutFile);
	fprintf(OutFile,"%%%% %d %d\n",count,ecount);

	sptr = sect;
	for( i=0; ierad != 0.0 )
	    {   fprintf(OutFile,"%g %g %g %g %g %g ClipEllips\n",
			    sptr->erad,sptr->epsi,sptr->etheta,
			    sptr->ephi,sptr->ex,sptr->ey);
	    }

	    if( (i==count-1) || (sptr->erad==0.0) )
	    {   fprintf(OutFile,"%g %g %g %d %d ClipSphere\n",sptr->srad,
				sptr->sphi+sptr->spsi,sptr->sphi-sptr->spsi,
				sptr->sx, sptr->sy );
	    } else fprintf(OutFile,"%g %g %g %d %d ClipBox\n",
				    sptr->srad+sptr->srad+2,
				    sptr->srad+1, sptr->ephi,
				    sptr->sx, sptr->sy );
	    sptr++;
	}

	i = ptr->col + ColourMask;
	fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
	fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
	fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
	fprintf(OutFile,"%g Shade\n",radf);
	fputs("grestore\n\n",OutFile);
    } else
    {   i = ptr->col + ColourMask;
	fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
	fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
	fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
	fprintf(OutFile,"%g %d %d ",radf,ptr->x,ptr->y);
	fputs("Sphere\n\n",OutFile);
    }
}


static void WriteVectWire( src, dst, col, dash )
    Atom __far *src;
    Atom __far *dst;
    int col, dash;
{
    register Atom __far *tmp;
    register Real radius;
    register Real temp;
    register Real dist;

    register Real midx, midy;
    register Real endx, endy;
    register int col1, col2;
    register int dx, dy, dz;
    register Long dist2;
    register int inten;


    if( src->z > dst->z )
    {   tmp = src;
        src = dst;
	dst = tmp;
    }

    if( !col )
    {   col1 = src->col;
	col2 = dst->col;
    } else col1 = col2 = col;

    if( UseBackFade )
    {   dz = (src->z+dst->z)>>1;
        inten = (ColourDepth*(dz+ImageRadius-ZOffset))/ImageSize;
    } else inten = ColourMask;

    dx = dst->x - src->x;  
    dy = dst->y - src->y;
    dist2 = dx*dx + dy*dy;
    dist = sqrt( (double)dist2 );

    if( dst->flag & SphereFlag )
    {   radius = dst->radius*Scale;
	if( dist <= radius ) return;

	/* Test for second half obscured! */
	if( (col1!=col2) && (0.5*dist < radius) )
	    col2 = col1;
    }

    if( src->flag & SphereFlag )
    {   radius = src->radius*Scale;
	if( dist <= radius ) return;

	/* Test for first half obscured! */
	if( (col1!=col2) && (0.5*dist < radius) )
	    col1 = col2;
    }


    WriteVectColour( col1+inten );

    dz = (src->z+dst->z)>>1;
    temp = (double)(dz-ZOffset)/ImageSize + 1.0;
    if( temp != LineWidth )
    {   fprintf(OutFile,"%g setlinewidth\n",temp);
	LineWidth = temp;
    }

    if( dash )
    {   if( VectSolid )
        {   fputs("[3 3] 0 setdash\n",OutFile);
            VectSolid = False;
        }
    } else
        if( !VectSolid )
        {   fputs("[] 0 setdash\n",OutFile);
            VectSolid = True;
        }


    if( src->flag & SphereFlag )
    {   dz = dst->z - src->z;
	dist = sqrt( (double)(dist2 + dz*dz) );
	endx = src->x + (radius*dx)/dist;
	endy = src->y + (radius*dy)/dist;
	fprintf(OutFile,"%g %g ",endx,endy);
    } else
	fprintf(OutFile,"%d %d ",src->x,src->y);

    if( col1 != col2 )
    {   midx = 0.5*(src->x + dst->x);
	midy = 0.5*(src->y + dst->y);
	fprintf(OutFile,"%g %g Wire\n",midx,midy);

	WriteVectColour( col2+inten );
	fprintf(OutFile,"%g %g ",midx,midy);
    } 
    fprintf(OutFile,"%d %d Wire\n",dst->x,dst->y);
}


static void WriteVectStick( src, dst, col, rad )
    Atom __far *src;  
    Atom __far *dst;
    int col, rad;
{
    register Atom __far *tmp;
    register Real midx, midy;
    register Real relx, rely;
    register Real endx, endy;
    register Real radius, angle;
    register Real dist, dist3;
    register Real temp, ratio;

    register Long dist2;
    register int dx, dy, dz;
    register int col1, col2;
    register int i, inten;

    if( !rad )
    {   WriteVectWire(src,dst,col,False);
	return;
    }

    if( src->z > dst->z )
    {   tmp = src;
        src = dst;
	dst = tmp;
    }

    if( !col )
    {   col1 = src->col;
	col2 = dst->col;
    } else col1 = col2 = col;

    dx = dst->x - src->x;  
    dy = dst->y - src->y;
    dz = dst->z - src->z;
    dist2 = dx*dx + dy*dy;
    dist3 = sqrt( (double)(dist2 + dz*dz) );
    dist = sqrt( (double)dist2 );

    if( dst->flag & SphereFlag )
    {   radius = dst->radius*Scale;
	if( dist <= radius ) return;

	/* Test for nearest half obscured! */
	if( (col1!=col2) && (0.5*dist < radius) )
	    col2 = col1;
    }

    if( src->flag & SphereFlag )
    {   radius = src->radius*Scale;
	if( dist <= radius ) return;

	/* Test for furthest half obscured! */
	if( (col1!=col2) && (0.5*dist < radius) )
	    col1 = col2;
    }

    if( !VectSolid )
    {   fputs("[] 0 setdash\n",OutFile);
        VectSolid = True;
    }

    temp = ((src->z-ZOffset)+(dst->z-ZOffset))/ImageSize + 1.0;
    if( temp != LineWidth )
    {   fprintf(OutFile,"%g setlinewidth\n",temp);
	LineWidth = temp;
    }

    radius = rad*Scale;
    angle = Rad2Deg*atan2((double)dy,(double)dx);
    inten = (int)((dist/dist3)*ColourMask);

    if( col1 != col2 )
    {   midx = 0.5*(src->x + dst->x);
	midy = 0.5*(src->y + dst->y);
	relx = (radius*dx)/dist;
	rely = (radius*dy)/dist;

	fprintf(OutFile,"%g %g moveto\n",midx+rely,midy-relx);
	fprintf(OutFile,"%g %g lineto\n",midx-rely,midy+relx);

	ratio = dz/dist3;

	if( (src->flag&SphereFlag) && (src->radius>rad) )
	{   temp = (Scale*src->radius)/dist3;
	    endx = src->x + temp*dx;
	    endy = src->y + temp*dy;

	    fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
	    fprintf(OutFile,"%g %g StickEnd\n",endx,endy);
	} else
	{   fprintf(OutFile,"%d %d %g ",src->x,src->y,radius);
	    fprintf(OutFile,"%g %g arc\n",angle+90,angle-90);
	}
	fputs("closepath ",OutFile);

	i = col1 + inten;
	fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
	fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
	fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
	fputs("setrgbcolor fill\n",OutFile);

	fprintf(OutFile,"%d %d %g ",dst->x,dst->y,radius);
	fprintf(OutFile,"%g %g arc\n",angle-90,angle+90);
	fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
	fprintf(OutFile,"%g %g StickEnd\n",midx,midy);
	fputs("closepath ",OutFile);

	i = col2 + inten;
	fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
	fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
	fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
	fputs("setrgbcolor fill\n",OutFile);

	if( UseOutLine )
	{   fprintf(OutFile,"%d %d %g ",dst->x,dst->y,radius);
	    fprintf(OutFile,"%g %g arc\n",angle-90,angle+90);
	    if( (src->flag&SphereFlag) && (src->radius>rad) )
	    {   fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
		fprintf(OutFile,"%g %g StickEnd\n",endx,endy);
	    } else
	    {   fprintf(OutFile,"%d %d %g ",src->x,src->y,radius);
		fprintf(OutFile,"%g %g arc\n",angle+90,angle-90);
	    }
	    fputs("closepath 0 setgray stroke\n",OutFile);
	}
    } else /* col1 == col2! */
    {   fprintf(OutFile,"%d %d %g ",dst->x,dst->y,radius);
	fprintf(OutFile,"%g %g arc\n",angle-90,angle+90);

	if( (src->flag&SphereFlag) && (src->radius>rad) )
	{   temp = (Scale*src->radius)/dist3;
	    endx = src->x + temp*dx;
	    endy = src->y + temp*dy;
	    ratio = dz/dist3;

	    fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
	    fprintf(OutFile,"%g %g StickEnd\n",endx,endy);
	} else
	{   fprintf(OutFile,"%d %d %g ",src->x,src->y,radius);
	    fprintf(OutFile,"%g %g arc\n",angle+90,angle-90);
	}

	i = col1 + inten;
	fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
	fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
	fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
	fputs("Stick\n",OutFile);
    }
    VectCol = 0;
}


static void WriteVectDots()
{
    register DotStruct __far *ptr;
    register Real x,y,z;
    register Real xi,yi;
    register int inten;
    register int temp;
    register int zi;
    register int i;


    if( LineWidth != 1.0 )
    {   fputs("1 setlinewidth\n",OutFile);
	LineWidth = 1.0;
    }

    temp = SlabValue - ZOffset;
    for( ptr=DotPtr; ptr; ptr=ptr->next )
	for( i=0; icount; i++ )
	{   x = ptr->xpos[i];  
	    y = ptr->ypos[i];  
	    z = ptr->zpos[i];


	    xi = (x*MatX[0]+y*MatX[1]+z*MatX[2]) + XOffset;
	    if( (xi<0.0) || (xi>=XRange) ) continue;
	    yi = (x*MatY[0]+y*MatY[1]+z*MatY[2]) + YOffset;
	    if( (yi<0.0) || (yi>=YRange) ) continue;

	    zi = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2]);
	    if( UseSlabPlane && (zi>=temp) ) continue;

	    inten = (ColourDepth*(zi+ImageRadius))/ImageSize;
	    WriteVectColour( ptr->col[i]+inten );
	    fprintf(OutFile,"%g %g Dot\n",xi,yi);
	}
}


static void WriteVectLabels()
{
    register Chain __far *chain;
    register Group __far *group;
    register Atom __far *aptr;
    register Label *label;
    auto char buffer[80];

    fputs("/Times-Roman",OutFile); /* Courier or Courier-Bold? */
    fprintf(OutFile," findfont %d scalefont setfont\n",FontSize<<1);

    if( UseLabelCol )
    {   if( BackR || BackG || BackB )
	{   fprintf(OutFile,"%g %g %g setrgbcolor\n",
		    LabR/250.0, LabG/250.0, LabB/250.0);
	} else fputs("0 setgray\n",OutFile);
    } else VectCol = 0;

    ForEachAtom
	if( aptr->label )
	{   if( !UseLabelCol && (aptr->col!=VectCol) )
		 WriteVectColour( aptr->col );

	    label = (Label*)aptr->label;
	    FormatLabel(chain,group,aptr,label->label,buffer);
	    fprintf(OutFile,"(%s) %d %d Label\n",buffer,aptr->x,aptr->y);
	}
}


static void WriteVectMonitors()
{
    register Atom __far *s;
    register Atom __far *d;
    register Monitor *ptr;
    register int x,y,col;

    register char *cptr;
    register int dist;
    char buffer[10];
 
    buffer[9] = '\0';
    buffer[6] = '.';

    fputs("/Times-Roman",OutFile); /* Courier or Courier-Bold? */
    fprintf(OutFile," findfont %d scalefont setfont\n",FontSize<<1);

    for( ptr=MonitList; ptr; ptr=ptr->next )
    {   s = ptr->src;
        d = ptr->dst;

        if( ZValid( (s->z+d->z)/2 ) )
        {   x = (s->x+d->x)/2;
            y = (s->y+d->y)/2;
 
            if( !UseLabelCol )
            {   /* Use Source atom colour! */
                if( ptr->col )
                {   col = ptr->col + (ColourMask>>1);
                } else col = s->col + (ColourMask>>1);
            } else col = LabelCol;
            WriteVectColour(col);
 
            dist = ptr->dist;
            buffer[8] = (dist%10)+'0';  dist /= 10;
            buffer[7] = (dist%10)+'0';
            cptr = &buffer[5];
 
            if( dist > 9 )
            {   do {
                    dist /= 10;
                    *cptr-- = (dist%10)+'0';
                } while( dist > 9 );
                cptr++;
            } else *cptr = '0';
 
	    fprintf(OutFile,"(%s) %d %d Label\n",cptr,x+4,y);
        }
    }
}


static Long CountPSItems()
{
    register Chain __far *chain;
    register Group __far *group;
    register HBond __far *hptr;
    register Bond __far *bptr;
    register Atom __far *aptr;
    register Monitor *mptr;
    register Long result;

    result = 0;
    if( DrawAtoms )
        ForEachAtom 
	    if( aptr->flag&SphereFlag ) 
	        if( !UseClipping || !ClipVectSphere(aptr) )
		    result++;

    if( DrawBonds )
        ForEachBond 
            if( bptr->flag&DrawBondFlag && (!UseClipping ||
	        !ClipVectBond(bptr->srcatom,bptr->dstatom)) )
		    result++;

    ForEachBack 
        if( bptr->flag&DrawBondFlag && (!UseClipping ||
	    !ClipVectBond(bptr->srcatom,bptr->dstatom)) )
		result++;

    for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
        if( hptr->flag&DrawBondFlag )
        {   if( HBondMode )
            {   if( !ClipVectBond(hptr->srcCA,hptr->dstCA) )
                    result++;
            } else if( !ClipVectBond(hptr->src,hptr->dst) )
                result++;
        }

    for( hptr=Database->slist; hptr; hptr=hptr->hnext )
        if( hptr->flag&DrawBondFlag )
        {   if( SSBondMode )
            {   if( !ClipVectBond(hptr->srcCA,hptr->dstCA) )
                    result++;
            } else if( !ClipVectBond(hptr->src,hptr->dst) )
                result++;
        }

    for( mptr=MonitList; mptr; mptr=mptr->next )
        if( !UseClipping || !ClipVectBond(mptr->src,mptr->dst) )
            result++;

    return( result );
}


static void FetchPSItems( data, type )
    PSItemPtr __far *data;
    char __far *type;
{
    register Chain __far *chain;
    register Group __far *group;
    register HBond __far *hptr;
    register Bond __far *bptr;
    register Atom __far *aptr;
    register Monitor *mptr;
    register int i,flag;

    i = 0;
    if( DrawAtoms )
        ForEachAtom
	    if( aptr->flag&SphereFlag )
	        if( !UseClipping || !ClipVectSphere(aptr) )
	        {   type[i] = PSAtom; 
		    data[i++] = aptr;
	        }

    if( DrawBonds )
        ForEachBond
            if( bptr->flag&DrawBondFlag && (!UseClipping ||
	        !ClipVectBond(bptr->srcatom,bptr->dstatom)) )
	    {   type[i] = PSBond;
	        data[i++] = bptr;
	    } 

    ForEachBack
       if( bptr->flag&DrawBondFlag && (!UseClipping ||
           !ClipVectBond(bptr->srcatom,bptr->dstatom)) )
       {   type[i] = PSBond;
           data[i++] = bptr; 
       } 

    for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
        if( hptr->flag&DrawBondFlag )
        {   if( HBondMode )
            {   flag = !ClipVectBond(hptr->srcCA,hptr->dstCA);
            } else flag = !ClipVectBond(hptr->src,hptr->dst);

            if( flag )
            {   type[i] = PSHBond;
                data[i++] = hptr;
            }
        }

    for( hptr=Database->slist; hptr; hptr=hptr->hnext )
        if( hptr->flag&DrawBondFlag )
        {   if( SSBondMode )
            {   flag = !ClipVectBond(hptr->srcCA,hptr->dstCA);
            } else flag = !ClipVectBond(hptr->src,hptr->dst);

            if( flag )
            {   type[i] = PSSSBond;
                data[i++] = hptr;
            }
        }

    for( mptr=MonitList; mptr; mptr=mptr->next )
        if( !UseClipping || !ClipVectBond(mptr->src,mptr->dst) )
        {   type[i] = PSMonit;
            data[i++] = mptr;
        } 
}


static void WritePSItems( data, type, count )
    PSItemPtr __far *data;
    char __far *type;
    int count;
{
    register HBond __far *hbond;
    register Bond __far *bond;
    register Atom __far *src;
    register Atom __far *dst;
    register Monitor *monit;
    register int i;

    for( i=0; isrcatom;
                            dst = bond->dstatom;

                            if( bond->flag & WireFlag )
                            {   WriteVectWire(src,dst,bond->col,False);
                            } else if( bond->flag & CylinderFlag )
                            {   WriteVectStick(src,dst,bond->col,bond->radius);
                            } else /* bond->flag & DashFlag */
                                WriteVectWire(src,dst,bond->col,True);
                            break;

            case(PSSSBond): 
            case(PSHBond):  hbond = (HBond __far*)data[i];
                            if( (type[i]==PSHBond)? HBondMode : SSBondMode )
                            {   src = hbond->srcCA;
                                dst = hbond->dstCA;
                            } else
                            {   src = hbond->src;
                                dst = hbond->dst;
                            }

                            if( hbond->flag & WireFlag )
                            {   WriteVectWire(src,dst,hbond->col,True);
                            } else /* bond->flag & CylinderFlag */
                                WriteVectStick(src,dst,hbond->col,
                                                       hbond->radius);
                            break;

            case(PSMonit):  monit = (Monitor*)data[i];
                            WriteVectWire(monit->src,monit->dst,
                                          monit->col,True);
                            break;
        }
}



int WriteVectPSFile( name )
    char *name;
{
    register Real ambi;
    register Real temp, inten;
    register int xsize, ysize;
    register int xpos, ypos;
    register Long count;
    register int i;

    PSItemPtr __far *data;
    char __far *type;

    count = CountPSItems();
    if( !count ) return( True );

#ifdef IBMPC
    if( count > 16383 )
    {   if( CommandActive ) WriteChar('\n');
        WriteString("Output Error: Too many PostScript objects!\n");
        CommandActive = False;
	return( False );
    }
#endif

    /* Allocate arrays for objects! */
    data = (PSItemPtr __far*)_fmalloc((size_t)count*sizeof(PSItemPtr));
    type = (char __far*)_fmalloc((size_t)count*sizeof(char));
    if( !data || !type )
    {   if( CommandActive ) WriteChar('\n');
	WriteString("Output Error: Not enough memory to create PostScript!\n");
	CommandActive = False;

	if( data ) _ffree( data );
	if( type ) _ffree( type );
	return( False );
    }

    OutFile = fopen(name,"w");
    if( !OutFile )
    {   FatalOutputError(name);
	return(False);
    }

    /* Determine the size of the image */
    ysize = (int)(YRange*(BORDER*PAGEWIDE)/XRange);
    if( ysize > (int)(BORDER*PAGEHIGH) )
    {   xsize = (int)(XRange*(BORDER*PAGEHIGH)/YRange);
	ysize = (int)(BORDER*PAGEHIGH);
    } else xsize = (int)(BORDER*PAGEWIDE);

    xpos = (int)(PAGEWIDE-xsize)/2;
    ypos = (int)(PAGEHIGH-ysize)/2;

    fputs("%!PS-Adobe-2.0 EPSF-2.0\n",OutFile);
    fputs("%%Creator: RasMol Version 2.6\n",OutFile);
    fprintf(OutFile,"%%%%Title: %s\n",name);
    fprintf(OutFile,"%%%%BoundingBox: %d %d ",xpos,ypos);
    fprintf(OutFile,"%d %d\n",xpos+xsize,ypos+ysize);

    fputs("%%Pages: 1\n",OutFile);
    fputs("%%EndComments\n",OutFile);
    fputs("%%EndProlog\n",OutFile);
    fputs("%%BeginSetup\n",OutFile);

    fputs("1 setlinecap 1 setlinejoin [] 0 setdash\n",OutFile);
    fputs("1 setlinewidth 0 setgray\n",OutFile);
    fputs("%%EndSetup\n",OutFile);
    fputs("%%Page: 1 1\n",OutFile);

    fputs("gsave\n",OutFile);
    fputs("14 dict begin\n\n",OutFile);
    fputs("/handleerror { showpage } def\n\n",OutFile);
    fputs("/Inten {\n  dup 4 index mul exch\n",OutFile);
    fputs("  dup 4 index mul exch\n",OutFile);
    fputs("  3 index mul setrgbcolor\n} def\n\n",OutFile);

    fputs("/Dot {\n  moveto 0 0 rlineto stroke\n} def\n\n",OutFile);
    fputs("/Wire {\n  moveto lineto stroke\n} def\n\n",OutFile);
#ifdef INVERT
    fputs("/Label {\n  moveto show\n} def\n\n",OutFile);
#else
    fputs("/Label {\n  moveto 1 -1 scale\n",OutFile);
    fputs("  show mtrx setmatrix\n} def\n\n",OutFile);
#endif

    if( UseOutLine )
    {   fputs("/Stick {\n  closepath gsave setrgbcolor fill\n",OutFile);
	fputs("  grestore 0 setgray stroke\n} def\n\n",OutFile);
    } else
	fputs("/Stick {\n  closepath setrgbcolor fill\n} def\n\n",OutFile);

    fputs("/StickEnd {\n  matrix currentmatrix 6 1 roll\n",OutFile);
    fputs("  translate rotate 1 scale\n",OutFile);
    fputs("  0 0 3 2 roll 90 -90 arc\n  setmatrix\n} def\n\n",OutFile);

    if( UseOutLine )
    {   fputs("/Shade {\n  closepath gsave clip\n",OutFile);
    } else fputs("/Shade {\n  closepath clip\n",OutFile);

    if( Ambient < 0.99 )
    {   ambi = 0.5*Ambient;
        fputs("  45 rotate dup -0.81649658092 mul scale\n",OutFile);
        fprintf(OutFile,"  %g Inten fill\n",ambi);
        inten = (1.0-ambi)/31;
        for( i=0; i<31; i++ )
        {   temp = (Real)(i+1)/32;
	    fprintf(OutFile,"  0 %g ",(Real)i/32);
	    fprintf(OutFile,"%g 0 360 arc ",sqrt(1.0-temp*temp));
	    fprintf(OutFile,"%g Inten fill\n",i*inten+ambi);
        }
        if( UseOutLine )
        {   fputs("  grestore 0 setgray stroke",OutFile);
        } else fputc(' ',OutFile);
        fputs(" pop pop pop\n} def\n\n",OutFile);

    } else /* Saturated Colours! */
    {   fputs("  pop setrgbcolor fill\n",OutFile);
        if( UseOutLine )
            fputs("  grestore 0 setgray stroke\n",OutFile);
        fputs("} def\n\n",OutFile);
    }


    fputs("/ClipSphere {\n  translate 0 0 5 2 roll arc\n} def\n\n",OutFile);
    fputs("/ClipBox {\n  translate rotate\n  dup lineto dup neg ",OutFile);
    fputs("dup\n  0 rlineto 0 exch rlineto 0 rlineto closepath\n",OutFile);
    fputs("  clip newpath mtrx setmatrix\n} def\n\n",OutFile);
    fputs("/ClipEllips {\n  translate rotate 1 scale\n",OutFile);
    fputs("  0 0 4 2 roll dup neg arc\n",OutFile);
    fputs("  reversepath mtrx setmatrix\n} def\n\n",OutFile);

    fputs("/Sphere {\n  gsave\n",OutFile);
    fputs("  translate 0 0 2 index 0 360 arc\n",OutFile);
    if( UseOutLine )
    {   fputs("  gsave Shade grestore\n",OutFile);
	fputs("  0 setgray stroke\n",OutFile);
	fputs("  grestore\n} def\n\n",OutFile);
    } else
	fputs("  Shade grestore\n} def\n\n",OutFile);

#ifdef INVERT
    fprintf(OutFile,"%d %d translate\n",xpos,ypos);
    fprintf(OutFile,"%g ",(Real)xsize/XRange);
    fprintf(OutFile,"%g ",(Real)ysize/YRange);
#else
    fprintf(OutFile,"%d %d translate\n",xpos,ypos+ysize);
    fprintf(OutFile,"%g ",(Real)xsize/XRange);
    fprintf(OutFile,"%g ",(Real)-ysize/YRange);
#endif
    fputs("scale\n/mtrx matrix currentmatrix def\n\n",OutFile);

    fputs("newpath 0 0 moveto 0 ",OutFile);
    fprintf(OutFile,"%d rlineto %d 0 rlineto 0 %d",YRange,XRange,-YRange);
    fputs(" rlineto\nclosepath clip ",OutFile);
    if( BackR || BackG || BackB )
    {   fprintf(OutFile,"%g %g %g",BackR/255.0,BackG/255.0,BackB/255.0);
	fputs(" setrgbcolor fill\n\n",OutFile);
    } else fputs("newpath\n\n",OutFile);

    LineWidth = 1.0;
    VectSolid = True;
    VectCol = 0;

    FetchPSItems(data,type);
    if( count>1 )
	DepthSort(data,type,(int)count);

    WritePSItems(data,type,(int)count);
 
    if( !VectSolid )
    {   fputs("[] 0 setdash\n",OutFile);
        VectSolid = True;
    }

    if( DrawDots )
	WriteVectDots();
    if( DrawMonitDistance && MonitList )
        WriteVectMonitors();
    if( DrawLabels )
	WriteVectLabels();

    fputs("newpath 0 0 moveto 0 ",OutFile);
    fprintf(OutFile,"%d rlineto %d 0 rlineto 0 %d",YRange,XRange,-YRange);
    fputs(" rlineto\nclosepath 0 setgray 1 setlinewidth stroke\n",OutFile);
    fputs("end grestore\nshowpage\n",OutFile);
    fputs("%%Trailer\n",OutFile);
    fputs("%%EOF\n",OutFile);

    fclose( OutFile );
#ifdef APPLEMAC
    /* Avoid ANSI trigraph problems! */
    SetFileInfo(name,'vgrd','TEXT',134);
#endif
    _ffree( data );
    _ffree( type );
    return(True);
}



static void FlushPICTBuffer()
{
    if( PacketLen )
    {   if( RLEOutput )
        {   WriteByte(PacketLen-1);
            fwrite((char*)Buffer,1,PacketLen,OutFile);
        } else RLELineSize += PacketLen+1;
        PacketLen = 0;
    }
}


static void FlushPICTPacket()
{
    register int i;

    if( RLELength>2 )
    {   FlushPICTBuffer();

	if( RLEOutput )
	{   WriteByte(257-RLELength);
	    WriteByte(RLEChar);
	} else RLELineSize += 2;
    } else 
	for( i=0; i=0; y-- )
    {
#ifdef INVERT
	ptr = FBuffer + (Long)y*XRange;
#endif

	RLELineSize = 0;
	RLEOutput = False;
	PacketLen = 0;
	RLELength = 0;

#ifdef EIGHTBIT
	tmp = ptr;
	for( x=0; x 250 )
	{   WriteMSBShort(RLELineSize);
	    RLEFileSize += (RLELineSize+2);
	} else
	{   WriteByte(RLELineSize);
	    RLEFileSize += (RLELineSize+1);
	}
#else
	WriteMSBShort(RLELineSize);
	RLEFileSize += (RLELineSize+2);
#endif

	RLEOutput = True;
	PacketLen = 0;
	RLELength = 0;

#ifdef EIGHTBIT
	for( x=0; x2 )
    {   FlushIRISBuffer();

        if( RLEOutput )
        {   WriteByte(RLELength);
            WriteByte(RLEChar);
        } else RLELineSize += 2;
    } else
        for( i=0; imax ) max=i;
            WriteIRISCode(i);
        }
        FlushIRISPacket();
        FlushIRISBuffer();

        rowsize[y] = RLELineSize;
        rowstart[y] = RLEFileSize;
        RLEFileSize += RLELineSize;

        ptr = tmp;
        RLELineSize = 0;
        /* Green Component */
        for( x=0; xmax ) max=i;
            WriteIRISCode(i);
        }
        FlushIRISPacket();
        FlushIRISBuffer();

        i = y+YRange;
        rowsize[i] = RLELineSize;
        rowstart[i] = RLEFileSize;
        RLEFileSize += RLELineSize;

        ptr = tmp;
        RLELineSize = 0;
        /* Blue Component */
        for( x=0; xmax ) max=i;
            WriteIRISCode(i);
        }
        FlushIRISPacket();
        FlushIRISBuffer();

        i = y+(YRange<<1);
        rowsize[i] = RLELineSize;
        rowstart[i] = RLEFileSize;
        RLEFileSize += RLELineSize;
    }


    WriteMSBShort(474);     /* imagic     */
    WriteMSBShort(257);     /* type       */
    WriteMSBShort(3);       /* dim        */
    WriteMSBShort(XRange);  /* xsize      */
    WriteMSBShort(YRange);  /* ysize      */
    WriteMSBShort(3);       /* zsize      */
    WriteMSBLong(min);      /* min        */
    WriteMSBLong(max);      /* max        */
    WriteMSBLong(0);        /* wastebytes */

                            /* name       */
    fputs("RasMol IRIS RGB format output",OutFile);
    for( i=0; i<51; i++ ) WriteByte(0x00);
    WriteMSBLong(0);        /* colormap   */

    for( i=0; i<404; i++ )  WriteByte(0x00);
    for( i=0; i
  
Modified: Mon Jan 29 17:00:00 1996 GMT
Page accessed 940 times since Sat Apr 17 22:33:12 1999 GMT