home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
d
/
dvips549.zip
/
DVIPS
/
EMSPECIA.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-14
|
33KB
|
1,348 lines
/*
* emspecial.c
* This routine handles the emTeX special commands.
*/
#include "structures.h" /* The copyright notice in that file is included too! */
#include <ctype.h>
extern int atoi();
/*
* These are the external routines called:
*/
/**/
extern void hvpos() ;
extern void cmdout() ;
extern void numout() ;
extern void error() ;
extern void specerror() ;
extern FILE *search();
extern char errbuf[] ;
extern shalfword linepos;
extern FILE *bitfile;
extern int actualdpi ;
extern int vactualdpi ;
extern integer hh, vv;
extern char *figpath ;
extern int prettycolumn ;
extern Boolean disablecomments ;
#ifdef DEBUG
extern integer debug_flag;
#endif
#ifdef EMTEX
/* emtex specials */
#define EMMAX 1613 /* maximum number of emtex special points */
#define TRUE 1
#define FALSE 0
struct empt {
shalfword point;
integer x, y;
};
struct empt *empoints = NULL;
boolean emused = FALSE; /* true if em points used on this page */
integer emx, emy;
struct emunit {
char *unit;
float factor;
};
struct emunit emtable[] = {
{"pt",72.27},
{"pc",72.27/12},
{"in",1.0},
{"bp",72.0},
{"cm",2.54},
{"mm",25.4},
{"dd",72.27/(1238/1157)},
{"cc",72.27/12/(1238/1157)},
{"sp",72.27*65536},
{"",0.0}
};
/* clear the empoints array if necessary */
void
emclear()
{
int i;
if (emused && empoints)
for (i=0; i<EMMAX; i++)
empoints[i].point = 0;
emused = FALSE ;
}
/* put an empoint into the empoints array */
struct empt *emptput(point, x, y)
shalfword point;
integer x, y;
{
int i, start;
emused = TRUE;
start = point % EMMAX;
i = start;
while ( empoints[i].point != 0 ) {
if ( empoints[i].point == point )
break;
i++;
if (i >= EMMAX)
i = 0;
if (i == start) {
sprintf(errbuf,"!Too many em: special points");
specerror(errbuf);
}
}
empoints[i].point = point;
empoints[i].x = x;
empoints[i].y = y;
return(&empoints[i]);
}
/* get an empoint from the empoints array */
struct empt *emptget(point)
shalfword point;
{
int i, start;
start = point % EMMAX;
i = start;
if (emused == TRUE)
while ( empoints[i].point != 0 ) {
if (empoints[i].point == point)
return(&empoints[i]);
i++;
if (i >= EMMAX)
i = 0;
if (i == start)
break;
}
sprintf(errbuf,"!em: point %d not defined",point);
specerror(errbuf);
return(NULL); /* never returns due to error */
}
/* convert width into dpi units */
float emunits(width,unit)
float width;
char *unit;
{
struct emunit *p;
for (p=emtable; *(p->unit)!='\0'; p++) {
if (strcmp(p->unit,unit)==0)
return( width * actualdpi / p->factor );
}
return (-1.0); /* invalid unit */
}
/* specials for emtex, added by rjl */
/* the line cut parameter is not supported (and is ignored)
* em:graph supports PCX, MSP1, MSP2 and uncompressed BMP files
*/
void emspecial(p)
char *p ;
{
float emwidth, emheight;
shalfword empoint1, empoint2;
struct empt *empoint;
char emunit[3];
char emstr[80];
char *emp;
void emgraph();
hvpos() ;
for (emp = p+3; *emp && isspace(*emp); emp++); /* skip blanks */
if (strncmp(emp, "linewidth", 9) == 0) {
/* code for linewidth */
for (emp = emp+9; *emp && isspace(*emp); emp++); /* skip blanks */
sscanf(emp, "%f%2s", &emwidth, emunit);
emwidth = emunits(emwidth,emunit);
if (emwidth!=-1.0) {
sprintf(emstr,"%.1f setlinewidth", emwidth);
cmdout(emstr);
#ifdef DEBUG
if (dd(D_SPECIAL))
(void)fprintf(stderr, "em special: Linewidth set to %.1f dots\n",
emwidth) ;
#endif
} else {
sprintf(errbuf,"Unknown em: special width");
specerror(errbuf);
}
}
else if (strncmp(emp, "moveto", 6) == 0) {
#ifdef DEBUG
if (dd(D_SPECIAL))
#ifdef SHORTINT
(void)fprintf(stderr, "em special: moveto %ld,%ld\n", hh, vv);
#else
(void)fprintf(stderr, "em special: moveto %d,%d\n", hh, vv);
#endif
#endif
emx = hh;
emy = vv;
}
else if (strncmp(emp, "lineto", 6) == 0) {
#ifdef DEBUG
if (dd(D_SPECIAL))
#ifdef SHORTINT
(void)fprintf(stderr, "em special: lineto %ld,%ld\n", hh, vv);
#else
(void)fprintf(stderr, "em special: lineto %d,%d\n", hh, vv);
#endif
#endif
cmdout("np");
numout(emx);
numout(emy);
cmdout("a");
numout(hh);
numout(vv);
cmdout("li");
cmdout("st");
emx = hh;
emy = vv;
}
else if (strncmp(emp, "point", 5) == 0) {
if (empoints == NULL) {
empoints =
(struct empt *)mymalloc((integer)EMMAX * sizeof(struct empt)) ;
emused = TRUE;
emclear();
}
for (emp = emp+5; *emp && isspace(*emp); emp++); /* skip blanks */
empoint1 = (shalfword)atoi(emp);
empoint = emptput(empoint1,hh,vv);
#ifdef DEBUG
if (dd(D_SPECIAL))
#ifdef SHORTINT
(void)fprintf(stderr, "em special: Point %d is %ld,%ld\n",
#else
(void)fprintf(stderr, "em special: Point %d is %d,%d\n",
#endif
empoint->point, empoint->x, empoint->y) ;
#endif
}
else if (strncmp(emp, "line", 4) == 0) {
for (emp = emp+4; *emp && isspace(*emp); emp++); /* skip blanks */
empoint1 = (shalfword)atoi(emp);
for (; *emp && isdigit(*emp); emp++); /* skip point 1 */
if ( *emp && strchr("hvp",*emp)!=0 )
emp++; /* skip line cut */
for (; *emp && isspace(*emp); emp++); /* skip blanks */
if ( *emp && (*emp==',') )
emp++; /* skip comma separator */
for (; *emp && isspace(*emp); emp++); /* skip blanks */
empoint2 = (shalfword)atoi(emp);
for (; *emp && isdigit(*emp); emp++); /* skip point 2 */
if ( *emp && strchr("hvp",*emp)!=0 )
emp++; /* skip line cut */
for (; *emp && isspace(*emp); emp++); /* skip blanks */
if ( *emp && (*emp==',') )
emp++; /* skip comma separator */
emwidth = -1.0;
emunit[0]='\0';
sscanf(emp, "%f%2s", &emwidth, emunit);
emwidth = emunits(emwidth,emunit);
#ifdef DEBUG
if (dd(D_SPECIAL))
(void)fprintf(stderr, "em special: Line from point %d to point %d\n",
empoint1, empoint2) ;
#endif
cmdout("np");
if (emwidth!=-1.0) {
#ifdef DEBUG
if (dd(D_SPECIAL))
(void)fprintf(stderr,"em special: Linewidth temporarily set to %.1f dots\n",
emwidth) ;
#endif
strcpy(emstr,"currentlinewidth");
cmdout(emstr);
sprintf(emstr,"%.1f setlinewidth", emwidth);
cmdout(emstr);
}
empoint = emptget(empoint1);
numout(empoint->x);
numout(empoint->y);
cmdout("a");
empoint = emptget(empoint2);
numout(empoint->x);
numout(empoint->y);
cmdout("li");
cmdout("st");
if (emwidth!=-1.0) {
strcpy(emstr,"setlinewidth");
cmdout(emstr);
}
}
else if (strncmp(emp, "message", 7) == 0) {
(void)fprintf(stderr, "em message: %s\n", emp+7) ;
}
else if (strncmp(emp, "graph", 5) == 0) {
int i;
for (emp = emp+5; *emp && isspace(*emp); emp++); /* skip blanks */
for (i=0; *emp && !isspace(*emp) && !(*emp==',') ; emp++)
emstr[i++] = *emp; /* copy filename */
emstr[i] = '\0';
/* now get optional width and height */
emwidth = emheight = -1.0; /* no dimension is <= 0 */
for (; *emp && ( isspace(*emp) || (*emp==',') ); emp++)
; /* skip blanks and comma */
if (*emp) {
sscanf(emp, "%f%2s", &emwidth, emunit); /* read width */
emwidth = emunits(emwidth,emunit); /* convert to pixels */
for (; *emp && ( isdigit(*emp) || isalpha(*emp) ); emp++)
; /* skip width dimension */
for (; *emp && ( isspace(*emp) || (*emp==',') ); emp++)
; /* skip blanks and comma */
if (*emp) {
sscanf(emp, "%f%2s", &emheight, emunit); /* read height */
emheight = emunits(emheight,emunit)*vactualdpi/actualdpi;
}
}
if (emstr[0]) {
emgraph(emstr,emwidth,emheight);
}
else {
(void)fprintf(stderr, "em graph: no file given\n") ;
}
}
else {
sprintf(errbuf,
"Unknown em: command (%s) in \\special will be ignored", p);
specerror(errbuf) ;
}
return;
}
/* em:graph routines */
/* The graphics routines currently decode 3 types of IBM-PC based graphics */
/* files: .pcx, .bmp, .msp. The information on the formats has occasionally */
/* been sketchy, and subject to interpretation. I have attempted to implement */
/* these routines to correctly decode the graphics file types mentioned. */
/* please note that .bmp file type does not support compressed .bmp files */
/* this was caused by an inability to locate an example of a complete */
/* compressed file.
/* */
/* The method of reading in the headers of the binary files is ungainly, but */
/* portable. Failure to use a byte by byte read and convert method will */
/* result in portability problems. Specifically there is no requirement that */
/* elements of a C structure be contiguous, only that they have an ascending */
/* order of addresses. */
/* */
/* The current implementations of the graphics format to postscript */
/* conversion are not the most efficient possible. Specifically: color */
/* formats are converted to RGB ratios prior to using a simple thresholding */
/* method to determine if the postscript bit is to be set. The thresholding */
/* method is compabible with that used in emtex's drivers. The RGB */
/* intermediate value is retained to allow easy conversion to color or grey */
/* scale operation in the future, should emtex's drivers be rewritten to */
/* support these modes. */
/* */
/* Please send bug reports relating to the em:graph routines to: */
/* maurice@bruce.cs.monash.edu.au */
/* */
/* My thanks to Russell Lang for his assistance with the implementation of */
/* these routines in a manner compatible with dvips and for the optimization */
/* of some routines. */
/* */
/* Maurice Castro */
/* 8 Oct 92 */
/* Routines to read binary numbers from IBM PC file types */
integer readinteger(f)
FILE *f;
{
union {
integer i;
unsigned char ip[4];
} inv;
int r;
for (r = 0; r < 4; r++)
{
inv.ip[r] = ((unsigned char) fgetc(f)) & 0xff;
}
return(inv.i);
}
halfword readhalfword(f)
FILE *f;
{
union {
halfword i;
unsigned char ip[2];
} inv;
int r;
for (r = 0; r < 2; r++)
{
inv.ip[r] = ((unsigned char) fgetc(f)) & 0xff;
}
return(inv.i);
}
quarterword readquarterword(f)
FILE *f;
{
return(((unsigned char)fgetc(f)) & 0xff);
}
#define tobyte(x) ((x/8) + (x%8 ? 1 : 0))
/* These routines will decode PCX files produced by Microsoft
* Windows Paint. Other programs may not produce files which
* will be successfully decoded, most notably version 1.xx of
* PC Paint. */
/*
* Type declarations. integer must be a 32-bit signed; shalfword must
* be a sixteen-bit signed; halfword must be a sixteen-bit unsigned;
* quarterword must be an eight-bit unsigned.
*/
typedef struct
{
quarterword man;
quarterword ver;
quarterword enc;
quarterword bitperpix;
halfword xmin;
halfword ymin;
halfword xmax;
halfword ymax;
halfword hres;
halfword vres;
quarterword pal[48];
quarterword reserved;
quarterword colorplanes;
halfword byteperline;
halfword paltype;
quarterword fill[58];
} PCXHEAD;
int PCXreadhead(pcxf, pcxh)
FILE *pcxf;
PCXHEAD *pcxh;
{
pcxh->man = readquarterword(pcxf);
pcxh->ver = readquarterword(pcxf);
pcxh->enc = readquarterword(pcxf);
pcxh->bitperpix = readquarterword(pcxf);
pcxh->xmin = readhalfword(pcxf);
pcxh->ymin = readhalfword(pcxf);
pcxh->xmax = readhalfword(pcxf);
pcxh->ymax = readhalfword(pcxf);
pcxh->hres = readhalfword(pcxf);
pcxh->vres = readhalfword(pcxf);
fread(pcxh->pal, 1, 48, pcxf);
pcxh->reserved = readquarterword(pcxf);
pcxh->colorplanes = readquarterword(pcxf);
pcxh->byteperline = readhalfword(pcxf);
pcxh->paltype = readhalfword(pcxf);
fread(pcxh->fill, 1, 58, pcxf);
if (feof(pcxf))
return(0); /* fail */
if (pcxh->man != 0x0a)
return(0); /* fail */
if (pcxh->enc != 0x1)
return(0); /* fail */
return(1); /* success */
}
int PCXreadline(pcxf, pcxbuf, byteperline)
FILE *pcxf;
unsigned char *pcxbuf;
unsigned int byteperline;
{
int n;
int c;
int i;
n = 0;
memset(pcxbuf,0,byteperline);
do {
c = fgetc(pcxf) & 0xff;
if ((c & 0xc0) == 0xc0) {
i = c & 0x3f;
c = fgetc(pcxf);
while ((i--) && (n < byteperline)) pcxbuf[n++] = c;
}
else {
pcxbuf[n++] = c;
}
} while (n < byteperline);
if (c==EOF) n=0;
return(n);
}
void PCXgetpalette(pcxf, pcxh, r, g, b)
FILE *pcxf;
PCXHEAD *pcxh;
unsigned char r[256];
unsigned char g[256];
unsigned char b[256];
{
int i;
/* clear palette */
for (i=0; i < 256; i++) {
r[i] = 0;
g[i] = 0;
b[i] = 0;
}
switch (pcxh->ver) {
case 0:
/* version 2.5 of PC Paint Brush */
for (i=0; i < 16; i++) {
r[i] = pcxh->pal[i*3];
g[i] = pcxh->pal[i*3+1];
b[i] = pcxh->pal[i*3+2];
}
break;
case 2:
/* version 2.8 of PC Paint Brush with valid Palette */
for (i=0; i < 16; i++) {
r[i] = pcxh->pal[i*3];
g[i] = pcxh->pal[i*3+1];
b[i] = pcxh->pal[i*3+2];
}
break;
case 3:
/* version 2.8 of PC Paint Brush with no valid Palette */
/* either mono or default */
if (pcxh->colorplanes != 1) {
/* Color default palette - should be checked */
r[0] = 0x00; g[0] = 0x00; b[0] = 0x00;
r[1] = 0x80; g[1] = 0x00; b[1] = 0x00;
r[2] = 0x00; g[2] = 0x80; b[2] = 0x00;
r[3] = 0x80; g[3] = 0x80; b[3] = 0x00;
r[4] = 0x00; g[4] = 0x00; b[4] = 0x80;
r[5] = 0x80; g[5] = 0x00; b[5] = 0x80;
r[6] = 0x00; g[6] = 0x80; b[6] = 0x80;
r[7] = 0x80; g[7] = 0x80; b[7] = 0x80;
r[8] = 0xc0; g[8] = 0xc0; b[8] = 0xc0;
r[9] = 0xff; g[9] = 0x00; b[9] = 0x00;
r[10] = 0x00; g[10] = 0xff; b[10] = 0x00;
r[11] = 0xff; g[11] = 0xff; b[11] = 0x00;
r[12] = 0x00; g[12] = 0x00; b[12] = 0xff;
r[13] = 0xff; g[13] = 0x00; b[13] = 0xff;
r[14] = 0x00; g[14] = 0xff; b[14] = 0xff;
r[15] = 0xff; g[15] = 0xff; b[15] = 0xff;
}
else {
/* mono palette */
r[0] = 0x00; g[0] = 0x00; b[0] = 0x00;
r[1] = 0xff; g[1] = 0xff; b[1] = 0xff;
}
break;
case 5:
default:
/* version 3.0 of PC Paint Brush or Better */
fseek(pcxf, -769L, SEEK_END);
/* if signature byte is correct then read the palette */
/* otherwise copy the existing palette */
if (fgetc(pcxf) == 12) {
for (i=0; i < 256; i++) {
r[i] = fgetc(pcxf);
g[i] = fgetc(pcxf);
b[i] = fgetc(pcxf);
}
}
else {
for (i=0; i < 16; i++) {
r[i] = pcxh->pal[i*3];
g[i] = pcxh->pal[i*3+1];
b[i] = pcxh->pal[i*3+2];
}
}
break;
}
}
extern void mhexout() ;
void showpicture(pcxf, wide, high, bytes, cp, bp, r, g, b)
FILE *pcxf;
int wide;
int high;
int bytes;
int cp;
int bp;
unsigned char r[256];
unsigned char g[256];
unsigned char b[256];
{
int x;
int y;
int c;
unsigned char *rowa[4]; /* row array */
unsigned char *row;
int a;
int p;
int ra;
int ga;
int ba;
unsigned char *pshexa;
int cbp;
int xdiv, xmod, xbit;
int width;
width = tobyte(wide) * 8;
/* output the postscript image size preamble */
cmdout("/picstr ");
numout((integer)tobyte(wide));
cmdout("string def");
numout((integer)width);
numout((integer)high);
numout((integer)1);
cmdout("[");
numout((integer)width);
numout((integer)0);
numout((integer)0);
numout((integer)-high);
numout((integer)0);
numout((integer)0);
cmdout("]");
cmdout("{currentfile picstr readhexstring pop} ");
cmdout("image ");
/* allocate the postscript hex output array */
pshexa = (unsigned char *) malloc(tobyte(wide));
/* make sure that you start at the right point in the file */
fseek(pcxf, (long) sizeof(PCXHEAD), SEEK_SET);
/* malloc the lines */
for (c = 0; c < cp; c++)
rowa[c] = (unsigned char *) malloc(bytes);
for (y = 0; y < high; y++) {
/* clear the postscript hex array */
memset(pshexa,0xff,bytes);
/* read in all the color planes for a row of pixels */
for (c = 0; c < cp; c++)
PCXreadline(pcxf, rowa[c], bytes);
/* process each pixel */
for (x = 0; x < wide; x++) {
/* build up the pixel value from color plane entries */
p = 0;
xdiv = x>>3;
xmod = 7 - (x&7);
xbit = 1 << xmod;
switch(bp) {
case 1:
for (c = 0; c < cp; c++) {
row = rowa[c];
p |= ( (unsigned)(row[xdiv] & xbit) >> xmod ) << c;
}
ra = r[p]; /* red actual */
ga = g[p]; /* green actual */
ba = b[p]; /* blue actual */
if ((ra < 0xff) || (ga < 0xff) || (ba < 0xff))
pshexa[xdiv] &= (~xbit);
else
pshexa[xdiv] |= xbit;
break;
case 8:
for (c = 0, cbp = 0; c < cp; c++, cbp += bp) {
row = rowa[c];
a = (unsigned) (row[x]);
p |= a << (cbp);
}
ra = r[p]; /* red actual */
ga = g[p]; /* green actual */
ba = b[p]; /* blue actual */
if ((ra < 0xff) || (ga < 0xff) || (ba < 0xff))
pshexa[xdiv] &= (~xbit);
else
pshexa[xdiv] |= xbit;
break;
default:
fprintf(stderr, "em graph: Unable to Decode this PCX file\n");
return;
}
}
mhexout(pshexa,(long)tobyte(wide));
}
}
void imagehead(filename,wide,high,emwidth,emheight)
char filename[];
int wide, high;
float emwidth, emheight; /* dimension in pixels */
{
(void)fprintf(stderr,"<%s",filename);
(void)fflush(stderr);
hvpos();
cmdout("@beginspecial") ;
cmdout("@setspecial") ;
if (linepos != 0)
(void)putc('\n', bitfile) ;
linepos = 0;
if (! disablecomments)
(void)fprintf(bitfile, "%%%%BeginDocument: %s_via_em:graph\n", filename) ;
cmdout("gsave");
/* set the image size */
if (emwidth <= 0.0) emwidth = (float)wide;
if (emheight <= 0.0) emheight = (float)high;
numout(((integer)emwidth)*72/actualdpi);
numout(((integer)emheight)*72/vactualdpi);
cmdout("scale");
#ifdef DEBUG
if (dd(D_SPECIAL)) {
(void)fprintf(stderr,
"\nem graph: %s width %d pixels scaled to %.1f pixels\n",
filename, wide, emwidth);
(void)fprintf(stderr,
"em graph: %s height %d pixels scaled to %.1f pixels\n",
filename, high, emheight);
}
#endif
}
void imagetail(filename)
char filename[];
{
cmdout("grestore");
if (linepos != 0)
(void)putc('\n', bitfile) ;
linepos = 0;
if (!disablecomments) {
(void)fprintf(bitfile, "%%%%EndDocument\n") ;
linepos = 0;
}
cmdout("\n@endspecial") ;
(void)fprintf(stderr,">");
(void)fflush(stderr);
prettycolumn += 2+strlen(filename);
}
void pcxgraph(filename,emwidth,emheight)
char filename[];
float emwidth, emheight; /* dimension in pixels */
{
PCXHEAD pcxh;
FILE *pcxf;
unsigned char red[256];
unsigned char green[256];
unsigned char blue[256];
int wide;
int high;
int bytes;
int cp;
int bpp;
pcxf = search(figpath, filename, READBIN);
if (pcxf == NULL) {
fprintf(stderr, "em graph: Unable to Open File %s\n", filename);
return;
}
if (!PCXreadhead(pcxf, &pcxh)) {
fprintf(stderr, "em graph: Unable to Read Valid PCX Header\n");
return;
}
PCXgetpalette(pcxf, &pcxh, red, green, blue);
/* picture size calculation */
wide = (pcxh.xmax - pcxh.xmin) + 1;
high = (pcxh.ymax - pcxh.ymin) + 1;
bytes = pcxh.byteperline;
cp = pcxh.colorplanes;
bpp = pcxh.bitperpix;
imagehead(filename,wide,high,emwidth,emheight);
showpicture(pcxf, wide, high, bytes, cp, bpp, red, green, blue);
imagetail(filename);
}
struct wpnt_1 {
quarterword id[4];
halfword width;
halfword high;
halfword x_asp;
halfword y_asp;
halfword x_asp_prn;
halfword y_asp_prn;
halfword width_prn;
halfword high_prn;
integer chk_sum;
halfword chk_head;
};
#define WPAINT_1 1
#define WPAINT_2 2
void MSP_2_ps(f, wide, high)
FILE *f;
int wide;
int high;
{
char *line;
char *l;
int i;
int j;
char a, b, c;
int d;
int width;
halfword *linelen;
/* an undocumented format - based on a type of run length encoding */
/* the format is made up of a list of line lengths, followed by a set */
/* of lines. Each line is made up of 2 types of entries: */
/* 1) A 3 term entry (0 a b): the byte b is repeated a times */
/* 2) A variable length entry (a xxxx....xxxx): a bytes are read */
/* from the file. */
/* These entries are combined to build up a line */
width = tobyte(wide)*8;
/* output the postscript image size preamble */
cmdout("/picstr ");
numout((integer)tobyte(wide));
cmdout("string def");
numout((integer)width);
numout((integer)high);
numout((integer)1);
cmdout("[");
numout((integer)width);
numout((integer)0);
numout((integer)0);
numout((integer)-high);
numout((integer)0);
numout((integer)0);
cmdout("]");
cmdout("{currentfile picstr readhexstring pop} ");
cmdout("image ");
fseek(f, 32, SEEK_SET);
/* read in the table of line lengths */
linelen = (halfword *) malloc(sizeof(halfword) * high);
for (i = 0; i < high; i++) {
linelen[i] = readhalfword(f);
if (feof(f))
return;
}
line = (char *) malloc(tobyte(wide));
for (i = 0; i < high; i++) {
memset(line, 0xff, tobyte(wide));
l = line;
if (linelen[i] != 0) {
d = linelen[i];
while (d) {
a = fgetc(f);
d--;
if (a == 0) {
b = fgetc(f);
c = fgetc(f);
d -= 2;
for (j = 0; j < b; j++)
*l++ = c;
}
else {
for (j = 0; j < a; j++)
*l++ = fgetc(f);
d -= j;
}
}
}
mhexout(line,(long)tobyte(wide));
}
}
void MSP_1_ps(f, wide, high)
FILE *f;
int wide;
int high;
{
char *line;
int i;
int width;
width = tobyte(wide)*8;
/* an partly documented format - see The PC Sourcebook */
/* the format is made up of a simple bitmap. */
/* output the postscript image size preamble */
cmdout("/picstr ");
numout((integer)tobyte(wide));
cmdout("string def");
numout((integer)width);
numout((integer)high);
numout((integer)1);
cmdout("[");
numout((integer)width);
numout((integer)0);
numout((integer)0);
numout((integer)-high);
numout((integer)0);
numout((integer)0);
cmdout("]");
cmdout("{currentfile picstr readhexstring pop} ");
cmdout("image ");
fseek(f, 32, SEEK_SET);
line = (char *) malloc(tobyte(wide));
for (i = 0; i < high; i++) {
fread(line, 1, tobyte(wide), f);
mhexout(line,(long)tobyte(wide));
}
}
void mspgraph(filename,emwidth,emheight)
char filename[];
float emwidth, emheight; /* dimension in pixels */
{
struct wpnt_1 head;
int paint_type;
FILE *f;
paint_type = 0;
f = search(figpath, filename, READBIN);
if (f == NULL) {
fprintf(stderr, "em graph: Unable to Open File %s\n", filename);
return;
}
/* read the header of the file and figure out what it is */
fread(head.id, 1, 4, f);
head.width = readhalfword(f);
head.high = readhalfword(f);
head.x_asp = readhalfword(f);
head.y_asp = readhalfword(f);
head.x_asp_prn = readhalfword(f);
head.y_asp_prn = readhalfword(f);
head.width_prn = readhalfword(f);
head.high_prn = readhalfword(f);
head.chk_sum = readinteger(f);
head.chk_head = readhalfword(f);
if (feof(f)) {
fprintf(stderr, "em graph: Unable to Read Valid MSP Header\n");
return;
}
/* check the id bytes */
if (!memcmp(head.id, "DanM", 4))
paint_type = WPAINT_1;
if (!memcmp(head.id, "LinS", 4))
paint_type = WPAINT_2;
imagehead(filename,head.width,head.high,emwidth,emheight);
switch (paint_type) {
case WPAINT_1:
MSP_1_ps(f, head.width, head.high);
fclose(f);
break;
case WPAINT_2:
MSP_2_ps(f, head.width, head.high);
fclose(f);
break;
default:
fprintf(stderr, "em graph: Unknown File Type\n");
return;
}
imagetail(filename);
}
/* ------------------------------------------------------------------------ */
/* .BMP file structures */
struct rgbquad
{
char blue;
char green;
char red;
char res;
};
struct bitmapinfoheader
{
integer size;
integer width;
integer height;
halfword planes; /* must be set to 1 */
halfword bitcount; /* 1, 4, 8 or 24 */
integer compression;
integer sizeimage;
integer xpelspermeter;
integer ypelspermeter;
integer clrused;
integer clrimportant;
};
/* constants for the compression field */
#define RGB 0L
#define RLE8 1L
#define RLE4 2L
struct bitmapfileheader
{
char type[2];
integer size;
halfword reserved1;
halfword reserved2;
integer offbits;
};
void rgbread(f, w, b, s)
FILE *f;
int b;
int w;
char *s;
{
int i;
/* set the line to white */
memset(s, 0xff, ((w*b)/8)+1);
/* read in all the full bytes */
for (i = 0; i < (w * b) / 8; i++)
*s++ = fgetc(f);
/* read in a partly filled byte */
if ((w * b) % 8)
{
i++;
*s++ = fgetc(f);
}
/* check that we are on a 32 bit boundary; otherwise align */
while (i % 4 != 0)
{
fgetc(f);
i++;
}
}
void bmpgraph(filename,emwidth,emheight)
char filename[];
float emwidth, emheight; /* dimension in pixels */
{
FILE *f;
struct bitmapfileheader bmfh;
struct bitmapinfoheader bmih;
unsigned char r[256];
unsigned char g[256];
unsigned char b[256];
unsigned char rr;
unsigned char gg;
unsigned char bb;
unsigned char c;
char *line;
char *pshexa;
int clrtablesize;
int i;
int j;
unsigned char imask;
unsigned char omask;
int iroll;
int oroll;
f = search(figpath, filename, READBIN);
if (f == NULL) {
fprintf(stderr, "em graph: Unable to Open File %s\n", filename);
return;
}
/* read the header of the file */
fread(bmfh.type, 1, 2, f);
bmfh.size = readinteger(f);
bmfh.reserved1 = readhalfword(f);
bmfh.reserved2 = readhalfword(f);
bmfh.offbits = readinteger(f);
if (feof(f))
{
fprintf(stderr, "em graph: Unable to Read Valid BMP Header\n");
return;
}
bmih.size = readinteger(f);
bmih.width = readinteger(f);
bmih.height = readinteger(f);
bmih.planes = readhalfword(f);
bmih.bitcount = readhalfword(f);
bmih.compression = readinteger(f);
bmih.sizeimage = readinteger(f);
bmih.xpelspermeter = readinteger(f);
bmih.ypelspermeter = readinteger(f);
bmih.clrused = readinteger(f);
bmih.clrimportant = readinteger(f);
if (feof(f))
{
fprintf(stderr, "em graph: Unable to Read Valid BMP Info\n");
return;
}
if (!memcmp(bmfh.type, "bm", 2))
{
fprintf(stderr, "em graph: Unknown File Type\n");
return;
}
imagehead(filename,(int)bmih.width,(int)bmih.height,emwidth,emheight);
/* determine the size of the color table to read */
clrtablesize = 0;
if (bmih.clrused == 0)
{
switch (bmih.bitcount)
{
case 1:
clrtablesize = 2;
break;
case 4:
clrtablesize = 16;
break;
case 8:
clrtablesize = 256;
break;
case 24:
break;
}
}
else
clrtablesize = bmih.clrused;
/* read in the color table */
for (i = 0; i < clrtablesize; i++)
{
b[i] = fgetc(f);
g[i] = fgetc(f);
r[i] = fgetc(f);
(void) fgetc(f);
}
line = (char *) malloc(((bmih.width * bmih.bitcount) / 8) + 1);
pshexa = (char *) malloc(tobyte(bmih.width));
/* output the postscript image size preamble */
cmdout("/picstr ");
numout((integer)tobyte(bmih.width));
cmdout("string def");
numout((integer)bmih.width);
numout((integer)bmih.height);
numout((integer)1);
cmdout("[");
numout((integer)bmih.width);
numout((integer)0);
numout((integer)0);
numout((integer)bmih.height);
numout((integer)0);
numout((integer)bmih.height);
cmdout("]");
cmdout("{currentfile picstr readhexstring pop} ");
cmdout("image ");
switch (bmih.compression)
{
case RGB:
/* read in all the lines of the file */
for (i = 0; i < bmih.height; i++)
{
memset(pshexa,0xff,tobyte(bmih.width));
rgbread(f, (int) bmih.width, (int) bmih.bitcount, line);
switch (bmih.bitcount)
{
case 1:
imask = 0x80;
iroll = 7;
break;
case 4:
imask = 0xf0;
iroll = 4;
break;
}
omask = 0x80;
oroll = 7;
for (j = 0; j < bmih.width - 1; j++)
{
/* performance in this section of code */
/* can easily be improved through the */
/* use of techniques used in pcx */
/* Postscript generation routines */
switch (bmih.bitcount)
{
case 1:
c = line[j/8];
c &= imask;
c >>= iroll;
rr = r[c];
gg = g[c];
bb = b[c];
iroll--;
imask >>= 1;
if (iroll < 0)
{
imask = 0x80;
iroll = 7;
}
break;
case 4:
c = line[j/2];
c &= imask;
c >>= iroll;
rr = r[c];
gg = g[c];
bb = b[c];
iroll-=4;
imask >>= 4;
if (iroll < 0)
{
imask = 0xf0;
iroll = 4;
}
break;
case 8:
c = line[j];
rr = r[c];
gg = g[c];
bb = b[c];
break;
case 24:
rr = r[j*3];
gg = g[j*3+1];
bb = b[j*3+2];
break;
}
if ((rr < 0xff) || (gg < 0xff) || (bb < 0xff))
pshexa[j/8] &= ~omask;
else
pshexa[j/8] |= omask;
oroll--;
omask >>= 1;
if (oroll < 0)
{
omask = 0x80;
oroll = 7;
}
}
mhexout(pshexa,(long)tobyte(bmih.width));
}
fclose(f);
break;
case RLE8:
fprintf(stderr, "em graph: BMP Compressed Files Not Implemented\n");
return;
case RLE4:
fprintf(stderr, "em graph: BMP Compressed Files Not Implemented\n");
return;
}
imagetail(filename);
}
/* ------------------------------------------------------------------------ */
char *extarr[]=
{ ".pcx", ".msp", ".bmp", NULL };
void emgraph(filename,emwidth,emheight)
char filename[];
float emwidth, emheight; /* dimension in pixels */
{
int l;
char fname[80];
char *ext;
int idx;
int filetype;
FILE *f;
strcpy(fname, filename);
/* identify file type by extension */
l = strlen(fname);
filetype = -1;
if (l > 4) {
ext = fname+(l-4);
idx = 0;
while (extarr[idx] != NULL) {
if (!strcmp(ext, extarr[idx]))
filetype = idx;
idx++;
}
}
if (filetype == -1) {
/* try various file types */
ext = fname + l;
idx = 0;
while (extarr[idx] != NULL) {
strcpy(ext, extarr[idx]);
f = search(figpath, fname, READBIN);
if (f != NULL) {
filetype = idx;
fclose(f);
break;
}
idx++;
}
}
switch (filetype) {
case 0:
pcxgraph(fname, emwidth, emheight);
break;
case 1:
mspgraph(fname, emwidth, emheight);
break;
case 2:
bmpgraph(fname, emwidth, emheight);
break;
default:
sprintf(fname,"em graph: %s: File not found", filename);
error(fname);
}
}
#else
void emspecial(p)
char *p ;
{
sprintf(errbuf,"emTeX specials not compiled in this version");
specerror(errbuf);
}
#endif EMTEX