/* Copyright by JB Wang 1990 */
/* This program is intended for making bitmap fonts of different sizes from
   a set of bitmap fonts,  such as 24x24, with aid of  an IRIS 4D NeWS window
   and PostScript psview.

   The basic principle is to build  PostScript images of characters from an
   available font library (if bitmap fonts worked with psview or psh, we would
   not have to do this), display at different scales with psview or psh and
   snapshot the bitmap from the image-buffer into a file to obtain bitmap fonts
   of new sizes. This is important in building TeX pk files.



   J.B. Wang 4/8/1990
*/

#include <gl.h>
#include <stdio.h>
#include <fcntl.h>
#define nc 127


#define LEN16 32
#define LEN24 72
#define LEN48 288
#define CCLIB16jt "/usr/people/jbw/usr/src/chtex/ncclib.16"
#define CCLIB24jt "/usr/people/jbw/usr/src/chtex/cclib.24"
#define CCLIB48jt "/usr/people/ftp/ch-series/cclib.48"

    FILE *newps;



unsigned char GB_array[2544861]; /* CCLIB 16x16 to 48x48 bitmap raster */

extern char *getenv();

main(argc, argv)
int argc;
char **argv;
{
int i, j;
int lens=LEN24;
int k;
int fontsize = 24;
int fontpos = 1410;
float fontscale = 24.;
float imgscale;
char tmpstr[127];
int ht=24, wd=24;
int int_lens = 24; /* length in short integer */
int x2, y2;
char name[40];

if (argc>1) sscanf(argv[1], "%f", &fontscale);
if (argc>2) sscanf(argv[2], "%d", &fontsize);


if ((fontsize!=24)&&(fontsize!=48)&&(fontsize!=16)) fontsize = 24;


if (fontsize==16)
  {
    lens = 32;
    int_lens = 16;
    ht = 16;
    wd = 16;
  }
else if (fontsize==48)
  {
    lens = 288;
    int_lens = 144;
    ht = 48;
    wd = 48;
  }



read_cclib(lens); /* store cclib raster font into the raster array */

    sprintf(name, "ncclib.%.0f", fontscale);
    newps = fopen(name, "w");

    fontscale --;

    imgscale = fontscale/1.3;

 x2 = 
 y2 = fontscale;

for (fontpos =0; fontpos < (94*87); fontpos++)
{

    make_image(fontpos, lens, ht, wd, imgscale);
/* display the PS image */
/*
    psh("chimage.ps");
*/
    system("psh chimage.ps");

/* save the screen message */
    savescreen(name,0,x2,0,y2);

  }

    fclose(newps);
}


make_image(fontpos, lens, ht, wd, fontscale)
int fontpos, lens, ht, wd;
float fontscale;
{
FILE *outp;
long int i;
float newht, newwd;

/* convert from 72dpi to 300 dpi */

newwd = fontscale+0.5;
newht = fontscale;

   outp = fopen("chimage.ps", "w");

    fprintf(outp, "%%!\n0 0 translate\n%.3f %.3f scale\n", newwd, newht);
    fprintf(outp, "%d %d 1 [%d 0 0 -%d 0 %d] {<\n",
	    wd, ht, wd, ht, ht);

for(i=0; i<lens; i++)
  fprintf(outp, "%02x", GB_array[fontpos*lens+i]);

fprintf(outp, ">} image\nshowpage\n");


fclose(outp);
}

read_cclib(lens)
int lens;
{
int cclibhandle;
char *cclibfile;
int i;



if (lens == 32) /* 16 x 16 fonts */
  {
   	if (!(cclibfile = getenv("CCLIB16jt")))
		 cclibfile = CCLIB16jt;
      }
else 
if (lens == 72) /* 24 x 24 fonts */
  {
   	if (!(cclibfile = getenv("CCLIB24jt")))
		 cclibfile = CCLIB24jt;
      }
else if (lens == 288) /* 48 x 48 fonts */
  {
   	if (!(cclibfile = getenv("CCLIB48jt")))
		 cclibfile = CCLIB48jt;
      }


   if (( cclibhandle = open(cclibfile, O_RDONLY) ) <0 )
    {fputs("Missing library file", stderr); exit(-1);}

 lens *= (94*87);

	read(cclibhandle, &GB_array[0], lens);

     close(cclibhandle);
fprintf(stderr, " Font bitmap loaded\n");
	return(1);

}




/* now dump the screen into RGB format */
#include "gl.h"
#include "port.h"
#include "image.h"

char rbuf[2048];
char gbuf[2048];
char bbuf[2048];
short obuf[2048];
short rs[2048];
short gs[2048];
short bs[2048];

short all[127][127];

savescreen(name,x1,x2,y1,y2)
char *name;
int x1, x2, y1, y2;
{
  long int winptr;
    IMAGE *oimage;
    int xsize, ysize;
    int xorg, yorg;
    int temp, y, i;
    int pos, togo, n;

    foreground();
    noport();
  winptr = winopen("scrsave");
    xorg = MIN(x1,x2);
    yorg = MIN(y1,y2);
    if(xorg<0)
       xorg = 0;
    if(yorg<0)
       yorg = 0;
    xsize = ABS(x2-x1);
    ysize = ABS(y2-y1);
    if((xorg+xsize)>XMAXSCREEN)
	xsize = XMAXSCREEN-xorg;
    if((yorg+ysize)>YMAXSCREEN)
	ysize = YMAXSCREEN-yorg;
    xsize++;
    ysize++;
/*
    oimage = iopen(name,"w",RLE(1),2,xsize,ysize);
*/
    wmplanes();
    screenspace();

    for(y=0; y<ysize; y++) {
#define READSCREENBROKEN 
#ifdef READSCREENBROKEN
	togo = xsize;
	pos = 0;
	while(togo) {
	    n = togo;
	    if(n>256)
		n = 256;
	    cmov2i(xorg+pos,yorg+y);
	    gl_readscreen(n,rbuf+pos,gbuf+pos,bbuf+pos);
	    pos += n;
	    togo -= n;
	}
#else
	cmov2i(xorg,yorg+y);
	gl_readscreen(xsize,rbuf,gbuf,bbuf);
#endif
	ctos(rbuf,rs,xsize);
	ctos(gbuf,gs,xsize);
	ctos(bbuf,bs,xsize);
	compress(rs,gs,bs,obuf,xsize);
/*
	putrow(oimage,obuf,y,0);
*/
	putnewps(obuf, xsize, ysize, y);
    }

    savenewps(xsize, ysize);
  winclose(winptr);
/*
    iclose(oimage);
*/

}


compress(rbuf,gbuf,bbuf,obuf,n)
register unsigned short *rbuf, *gbuf, *bbuf, *obuf;
int n;
{
    register short i;
    int rval, gval, bval;
    int temp;

    for(i=n; i--; ) 
	    *obuf++ = (77*(*rbuf++) + 151*(*gbuf++) + 28*(*bbuf++))>>8;
}


putnewps(buf, n, ysize, y) /* save in an array */
register unsigned short int *buf;
int n, ysize, y;
{
int xsize=n;

    while (n--) {
      all[ysize-y-1][xsize-n] = *buf;
	buf++;
    }
}

savenewps(xsize, ysize) /* from bottom to bottom to bottom to top */
int xsize, ysize;
{
int i, j, k;
unsigned short int tmpchr;
int b, r, h;
int tmpi, n;

   b = xsize/8;
   r = xsize%8;
      h = 8;

  for (i=0; i<ysize; i++)
    {


    for (j=0; j<b; j++)
      {
      tmpchr = 0;
	for (k=0; k<8; k++)
	  {
	  if (all[i][k+j*h]>0)
	    {
	      n = 7-k;
	      tmpi = 1;
	      while (n--)
		tmpi *=2;
	      tmpchr += tmpi;
	   }
	}

      fprintf(newps, "%c", tmpchr);
    }
  
      tmpchr = 0;
      if (r)
	{
	for (k=0; k<8; k++)
	  if (all[i][k+b*h]>0)
	    {
	      n = 7-k;
	      tmpi = 1;
	      while (n--)
		tmpi *=2;
	    tmpchr += tmpi;
	   }

	      fprintf(newps, "%c", tmpchr);

	}

    }

}

/*
 * This file is a product of Sun Microsystems, Inc. and is provided for
 * unrestricted use provided that this legend is included on all tape
 * media and as a part of the software program in whole or part.  Users
 * may copy or modify this file without charge, but are not authorized to
 * license or distribute it to anyone else except as part of a product
 * or program developed by the user.
 * 
 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 * 
 * This file is provided with no support and without any obligation on the
 * part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 * 
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
 * OR ANY PART THEREOF.
 * 
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even
 * if Sun has been advised of the possibility of such damages.
 * 
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 */

#ifndef lint
static char sccsid[] = "@(#)psh.c 9.9 88/02/10 Copyright 1985 Sun Micro";
#endif

/*
 * Copyright (c) 1987 by Sun Microsystems, Inc.
 */

/*-
	PostScript shell
	Used for building applications written entirely
	in PostScript.  Merely takes its stdin and writes
	it to the NeWS server.

 */

#include <stdio.h>
#include "psio.h"
char       programname[20]="psh";
char       *args[10];
int         nps=0;
int         input_file;

PSFILE       *PostScript,
             *PostScriptInput;

    int         mask;
    int         mask0;
    int         max;
    int         first = 1;
    int         seen_dollar = 0;
    PSFILE *outf;

init_ps()
{


  }

#ifndef SYSVREF
processfile(fd)
    register    fd;
{

    if (PostScript == 0 && ps_open_PostScript() == 0) {
	fprintf(stderr, "%s: Cannot connect to window server\n",
		programname);
	return(0);
    }
    outf = PostScript;
    mask0 = 1 << psio_fileno(PostScriptInput);

    max = psio_fileno(PostScriptInput);
    if (fd > max)
	max = fd;
    max++;

    while (1) {
	char        buf[8 * 1024];
	register    n;

	mask = mask0;
	if (fd >= 0) {
	    mask |= 1 << fd;
	}
	
	psio_flush(outf); 
	if (select(max, &mask, 0, 0, 0) < 0)
	{
	    perror(programname);
	    exit(1);
	}
	if (mask & mask0)
	{
	    n = read(psio_fileno(PostScriptInput), buf, sizeof buf);
	    if (n == 0) {
		if (fd >= 0)
		    fprintf(stderr, "%s: NeWS server disconnected\n",
			    programname);

		close(fd);
		fd = -1;
		return(0);
	    }
	    if (n < 0) {
		perror(programname);
		exit(1);
	    }
	    write(1, buf, n);
	}
	else if (fd >= 0 && (mask & (1 << fd)) != 0)
	{
	    register char *in;
	    n = read(fd, buf, sizeof buf);
	    if (n == 0) {
		psio_fprintf(outf, " quit ");
		close(fd);
		fd = -1;
		continue;
	    }
	    if (n < 0) {
		perror(programname);
		exit(1);
	    }
	    if (buf[0] == '#' && first)
		buf[0] = '%';
	    for (in = buf; --n >= 0; in++) {
		if (seen_dollar) {
		    seen_dollar = 0;
		    if (*in <= '9' && '1' <= *in) {
			register char *in2 = args[*in - '1'];
			if (in2)
			    while (*in2)
				psio_putc(*in2++, outf);
			continue;
		    }
		    if (*in != '$')
			psio_putc('$', outf);
		}
		else if (*in == '$') {
		    seen_dollar++;
		    continue;
		}
		psio_putc(*in, outf);
	    }
	    first = 0;
	}
	else {
	    fprintf(stderr, "%s: bogus read mask %x\n", programname, mask);
	    exit(1);
	}
    }
}
#else
#include <signal.h>
#include <errno.h>

extern int errno;

int showmsg = 1;

terminate()
{
    showmsg = 0;
}

processfile(fd)
    register    fd;
{
    char buf[8 * 1024];
    register    n;
    register PSFILE *outf;
    int pid;

    if (PostScript == 0 && ps_open_PostScript() == 0) {
	fprintf(stderr, "%s: Cannot connect to window server\n",
		programname);
	exit(0);
    }
    outf = PostScript;

    if ((pid = fork()) > 0) {	/* parent */
	signal(SIGCLD, terminate);
	while (n = read(psio_fileno(PostScriptInput), buf, sizeof buf)) {
	    if (n < 0) {
		if (errno == EINTR)
		    continue;
		else {
	            perror(programname);
		    break;
		}
	    }
	    write(1, buf, n);
	}
	if (showmsg) {
	    fprintf(stderr, "%s: NeWS server disconnected\n", programname);
	    signal(SIGCLD, SIG_DFL);
	    kill(pid, SIGKILL);
	}
    } else if (pid == 0) {	/* child */
	int first = 1;
	int seen_dollar = 0;
	register char *in;

	while (n = read(fd, buf, sizeof buf)) {
	    if (n < 0) {
	        perror(programname);
		break;
	    }
	    if (buf[0] == '#' && first)
	        buf[0] = '%';
	    for (in = buf; --n >= 0; in++) {
	        if (seen_dollar) {
		    seen_dollar = 0;
	    	    if (*in <= '9' && '1' <= *in) {
	    	    	register char *in2 = args[*in - '1'];
	    	    	if (in2)
	    		    while (*in2)
	    		    	psio_putc(*in2++, outf);
	    	    	continue;
	    	    }
	    	    if (*in != '$')
			psio_putc('$', outf);
	        }
	        else if (*in == '$') {
		    seen_dollar++;
		    continue;
	        }
	        psio_putc(*in, outf);
	    }
	    first = 0;
	    psio_flush(outf);
	}
	psio_fprintf(outf, " quit ");
	psio_flush(outf);
    } else {
	fprintf(stderr, "%s: fork failure\n", programname);
	exit(1);
    }
}
#endif

psh(filename)
    char          *filename;
{
         input_file = 0;
	    input_file = open(filename, 0);


	    if (input_file <= 0) {
		fprintf(stderr, "cannot open %s\n", programname);
		exit(1);
	      }

    processfile(input_file);
		fprintf(stderr, "Returned\n");	 
	 return(1);
}
