/* @(#)pslibi.c 17.1.1.1 (ES0-DMD) 01/25/02 17:39:36 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COPYRIGHT (c) 1994 European Southern Observatory .LANGUAGE C .IDENT pslibi.c .AUTHOR Preben Grosbol, ESO/IPG .KEYWORDS hardcopy, PostScript, image, library .ENVIRON MIDAS .PURPOSE Library of C-routines to generate hardcopy of images in PostScript format. .COMMENT The following routines are available: psopen(...) : Open and initiate PS-file psmode(...) : Define and initiate page mode pscolor(...) : Define graphics color mode psclose() : Terminate and close PS-file psitf(...) : Define Intensity Transfer Functions psframe(...) : Define location and size of image frame psimage(...) : Define image parameters and do setup psline(...) : Write one line of image data pscapt(...) : Define location etc. of caption area pstext(...) : Write text in caption area pslabel(...) : Write text lable at given position pswedge(...) : Write gray/color wedge psdraw(...) : Draw different shapes: line, ... .COMMENT Routines use OSA-routines to write PostScript file to disk. .VERSION 1.0 1990-Jul-18 : Creation, PJG .VERSION 1.1 1990-Aug-09 : Correct bugs + change psopen, PJG .VERSION 1.2 1990-Aug-22 : Add pslabel/psmode + explicit fonts, PJG .VERSION 1.3 1991-Jan-30 : Use pixel resolution, PJG .VERSION 1.4 1991-Oct-04 : Correct spelling of 'gray', PJG .VERSION 1.5 1992-Mar-17 : add pswedge function, PJG .VERSION 1.55 1992-Apr-10 : use mode in psframe, KB .VERSION 2.00 1992-Jul-29 : Change call sequence, add EPS, PJG .VERSION 2.05 1993-Mar-02 : Omit 'setscreen' if resolution<=0, PJG .VERSION 2.10 1993-Mar-23 : Change psline and psbwc, PJG .VERSION 2.15 1993-Nov-11 : Correct pslabel, PJG .VERSION 2.20 1994-May-03 : Add option for only box/no labels, PJG .VERSION 2.25 1994-Sep-07 : Explicit cast for strlen, PJG .VERSION 2.30 1998-Feb-27 : Add 'pfcolor()','pfdraw()' plus improve 'boundingbox' calculation, PJG .VERSION 2.35 1998-Mar-04 : Add margin to boundingbox, PJG .VERSION 2.40 1998-Sep-16 : Correct initiation of variable, PJG .VERSION 2.45 2000-Jan-12 : Correct (atend) string, PJG ------------------------------------------------------------------------*/ #include #include /* String library definitions */ #include /* Standard math library */ #include /* Standard time definitions */ #include /* OS-parameter definitions */ #include #define MXTEXT 128 /* Max. size of text and name str */ #define MXCPL 72 /* Max. char. per PS-line */ #define PPCM 28.246 /* PS-points per cm */ #define MXITF 256 /* Max. size of ITF tables */ #define MXBUF 4096 /* Max. size of Image buffer */ static int psfid; /* File-id for PostScript file */ static int pscxo; /* Current X-origin */ static int pscyo; /* Current Y-origin */ static double pscxs; /* Current X scale factor */ static double pscys; /* Current Y scale factor */ static double psang; /* Rotation angle of paper */ static int psres; /* PS Resolution in pixel per cm */ static int psisx; /* Current Image size in X (pt) */ static int psisy; /* Current Image size in Y (pt) */ static int psbin; /* Binning factor in both X and Y */ static int psbyc; /* Binning counter in Y */ static int pstls; /* PS Text line spacing */ static int pstyl; /* PS Text Y line position */ static int pstcs; /* PS Text column spacing */ static int pstbc; /* Text buffer countacing */ static int psnx; /* No. of image pixels in X axis */ static int psny; /* No. of image pixels in Y axis */ static int psbwc; /* PSmode: 0)B/W, 1)pseudo, 2)true color*/ static int psbp8; /* Flag: True if 8bit per pixel else 4 */ static int bflag; /* Flag: true if boudingbox initiated */ static int llx; /* Lower left corner of boudingbox in X */ static int lly; /* Lower left corner of boudingbox in Y */ static int urx; /* Upper right corner of boudingbox in X*/ static int ury; /* Upper right corner of boudingbox in Y*/ static int mox; /* Margin offset in X */ static int moy; /* Margin offset in Y */ static int psitt[MXITF]; /* Intensity Transform Table */ static int psmap[3][MXITF]; /* Color Transform Table */ static char text[MXTEXT]; /* Text buffer for formating */ static char psfnt[MXTEXT]; /* Buffer for PostScript fonts used */ static short pbbuf[MXBUF]; /* Buffer for blue image pixel rebin */ static short pgbuf[MXBUF]; /* Buffer for green image pixel rebin */ static short prbuf[MXBUF]; /* Buffer for red image pixel rebin */ void bbupdate(xll,yll,xur,yur) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Internal function to update boundingbox variables .RETURN Status, none ------------------------------------------------------------------------*/ double xll; /* New lower left limit in X */ double yll; /* New lower left limit in Y */ double xur; /* New upper right limit in X */ double yur; /* New upper right limit in Y */ { if (bflag) { if (xll%-50.50s<\n",ident); (void) osawrite(psfid,text,strlen(text)); if (oshdate(psname,&tms)) psname[0] = '\0'; (void) sprintf(text,"%%%%CreationDate: %s\n",psname); (void) osawrite(psfid,text,strlen(text)); (void) sprintf(text,"%%%%Pages: 1\n"); (void) osawrite(psfid,text,strlen(text)); (void) sprintf(text,"%%%%DocumentFonts: (atend)\n"); (void) osawrite(psfid,text,strlen(text)); (void) sprintf(text,"%%%%EndComments\n"); (void) osawrite(psfid,text,strlen(text)); (void) sprintf(text,"%%%%EndProlog\n"); (void) osawrite(psfid,text,strlen(text)); /* write coordinate transformation */ (void) sprintf(text,"save\n"); (void) osawrite(psfid,text,strlen(text)); (void) sprintf(text,"%f %f translate %f rotate\n",xcen,ycen,angle); (void) osawrite(psfid,text,strlen(text)); (void) sprintf(text,"%f %f translate\n",-x,-y); (void) osawrite(psfid,text,strlen(text)); /* define pixel frequence for halftone */ if (*res > 0.0) { psres = res[0]; i = 2.54 * res[1]; } else { psres = 60; i = 0; } psfnt[0] = '\0'; if (0>= 4; *pc++ = "0123456789abcdef"[n1]; pstbc++; if (psbp8) { *pc++ = "0123456789abcdef"[n2]; pstbc++; } } if (MXCPL<=pstbc) { /* check if text line is full */ *pc++ = '\n'; *pc = '\0'; pc = text; (void) osawrite(psfid,pc,strlen(pc)); pstbc = 0; } } } else { /* true color mode */ psb = pbbuf; psg = pgbuf; psr = prbuf; pstbc = 0; n = nx + 1; while (n--) { /* convert to hex */ np[0] = psitt[*psb++]; np[1] = psitt[*psg++]; np[2] = psitt[*psr++]; nc = 3; while (nc--) { n1 = psmap[nc][np[nc]]; n2 = n1 & 0x0F; n1 >>= 4; *pc++ = "0123456789abcdef"[n1]; pstbc++; if (psbp8) { *pc++ = "0123456789abcdef"[n2]; pstbc++; } } if (MXCPL<=pstbc) { /* check if text line is full */ *pc++ = '\n'; *pc = '\0'; pc = text; (void) osawrite(psfid,pc,strlen(pc)); pstbc = 0; } } } if (pstbc) { /* write remaining bytes to file */ if (pstbc & 1) *pc++ = '0'; *pc++ = '\n'; *pc = '\0'; pc = text; (void) osawrite(psfid,pc,strlen(pc)); } psbyc = psbin; return 0; } int pscapt(xstr,ystr,font,fsize,offset) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Define area and fonts for image captions .RETURN Status, 0:OK -1:Error font-size ------------------------------------------------------------------------*/ double xstr; /* Start of Caption area in X axis */ double ystr; /* Start of Caption area in Y axis */ char *font; /* Name of font used for captions */ int fsize; /* Size of fonts used for captions */ double offset; /* Column offset in cm for text field */ { int iox, ioy; if (psfid<0) return -1; /* check if ps-file open */ /* offset to image origin and scale to size */ iox = PPCM*xstr; ioy = PPCM*ystr; (void) sprintf(text,"%f %f scale %d %d translate\n", 1.0/pscxs,1.0/pscys,iox-pscxo,ioy-pscyo); (void) osawrite(psfid,text,strlen(text)); pscxo = iox; pscyo = ioy; pscxs = 1.0; pscys = 1.0; /* define caption font and initiate offsets */ (void) strcat(psfnt,font); (void) strcat(psfnt," "); if ((size_t) MXTEXT <= strlen(psfnt)) return -1; (void) sprintf(text,"/%s findfont %d scalefont setfont\n",font,fsize); (void) osawrite(psfid,text,strlen(text)); pstcs = PPCM*offset; pstyl = 0; pstls = 1.2*fsize; if (pstls==fsize) pstls = fsize + 1; bbupdate(PPCM*xstr, PPCM*ystr, PPCM*xstr, PPCM*ystr); return 0; } int pstext(label,str) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Write a text line out in the caption area .RETURN Status, 0:OK ------------------------------------------------------------------------*/ char *label; /* Pointer to text in label column */ char *str; /* Pointer to text string */ { int nt; if (psfid<0) return -1; /* check if ps-file open */ (void) sprintf(text,"0 %d moveto\n",pstyl); (void) osawrite(psfid,text,strlen(text)); (void) sprintf(text,"(%s) show\n",label); (void) osawrite(psfid,text,strlen(text)); (void) sprintf(text,"%d %d moveto\n",pstcs,pstyl); (void) osawrite(psfid,text,strlen(text)); (void) sprintf(text,"(: %s) show\n",str); (void) osawrite(psfid,text,strlen(text)); nt = strlen(text) - 10; pstyl -= pstls; bbupdate((double) pstcs, (double) pstyl, (double) pstcs+pstls*nt/1.2, (double) pstyl+pstls); return 0; } int pslabel(xstr,ystr,font,fsize,label) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Write text label at given location with special font .RETURN Status, 0:OK -1:Error font-size ------------------------------------------------------------------------*/ double xstr; /* Start of text label in X axis */ double ystr; /* Start of text label in Y axis */ char *font; /* Name of label font */ int fsize; /* Size of fonts used for text label */ char *label; /* Pointer to text */ { int iox, ioy, nt; if (psfid<0) return -1; /* check if ps-file open */ /* reset offset and scale */ (void) sprintf(text,"%f %f scale %d %d translate\n", 1.0/pscxs,1.0/pscys,-pscxo,-pscyo); (void) osawrite(psfid,text,strlen(text)); pscxo = 0; pscyo = 0; pscxs = 1.0; pscys = 1.0; /* define text font and initiate offsets */ if (strstr(psfnt,font)==NULL) { if (strlen(psfnt)+strlen(font) < (size_t)(MXTEXT-2)) { (void) strcat(psfnt,font); (void) strcat(psfnt," "); } } (void) sprintf(text,"/%s findfont %d scalefont setfont\n",font,fsize); (void) osawrite(psfid,text,strlen(text)); /* write text label */ iox = PPCM*xstr; ioy = PPCM*ystr; (void) sprintf(text,"%d %d moveto\n",iox,ioy); (void) osawrite(psfid,text,strlen(text)); (void) sprintf(text,"(%s) show\n",label); (void) osawrite(psfid,text,strlen(text)); nt = strlen(text) - 8; bbupdate(PPCM*xstr, PPCM*ystr, PPCM*xstr+nt*fsize, PPCM*ystr+fsize); return 0; } int pswedge(mode,xorg,yorg,xsize,ysize,zlow,zhigh) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE write gray/color wedge at given location and size .RETURN Status, 0:OK -1:Error ------------------------------------------------------------------------*/ int mode; /* Mode for drawing the wedge */ double xorg; /* Origin of wedge in X axis */ double yorg; /* Origin of wedge in Y axis */ double xsize; /* Size of wedge in X axis */ double ysize; /* Size of wedge in Y axis */ double zlow; /* Start label value for wedge */ double zhigh; /* End label value for wedge */ { char *pc; int iox, ioy, isx, isy; int n, nx, ny, np, nv, nc, n1, n2, nn, bpp; double sxi, syi; if (psfid<0) return -1; /* check if ps-file open */ if (psbwc==2) return 0; /* no wedge in real color mode */ iox = PPCM*xorg; ioy = PPCM*yorg; isx = PPCM*xsize; isy = PPCM*ysize; sxi = isx; syi = isy; bbupdate(PPCM*xorg, PPCM*yorg, PPCM*(xorg+xsize), PPCM*(yorg+ysize)); /* offset to wedge origin and scale to size */ (void) sprintf(text,"%f %f scale %d %d translate\n", 1.0/pscxs,1.0/pscys,-pscxo,-pscyo); (void) osawrite(psfid,text,strlen(text)); pscxo = 0; pscyo = 0; pscxs = 1.0; pscys = 1.0; /* draw frame around wedge */ if (mode) { (void) sprintf(text,"%f setlinewidth\n",1.0/pscxs); (void) sprintf(text,"newpath %d %d moveto %d %d lineto\n", iox,ioy,iox,ioy+isy); (void) osawrite(psfid,text,strlen(text)); (void) sprintf(text,"%d %d lineto %d %d lineto closepath stroke\n", iox+isx,ioy+isy,iox+isx,ioy); (void) osawrite(psfid,text,strlen(text)); } /* restore origin and scale */ (void) sprintf(text,"%d %d translate %f %f scale\n", iox-pscxo,ioy-pscyo,sxi/pscxs,syi/pscys); (void) osawrite(psfid,text,strlen(text)); /* define image transformation and format */ psbp8 = 1; bpp = (psbp8) ? 8 : 4; np = (psbp8) ? MXITF : MXITF/16; nx = (ysize>= 4; *pc++ = "0123456789abcdef"[n1]; nn++; if (psbp8) { *pc++ = "0123456789abcdef"[n2]; nn++; } } if (MXCPL<=nn) { /* check if text line is full */ *pc++ = '\n'; *pc = '\0'; pc = text; (void) osawrite(psfid,pc,strlen(pc)); nn = 0; } } if (nn) { /* write remaining bytes to file */ if (nn & 1) *pc++ = '0'; *pc++ = '\n'; *pc = '\0'; pc = text; (void) osawrite(psfid,pc,strlen(pc)); } pscxo = iox; pscyo = ioy; pscxs = sxi; pscys = syi; return 0; } int psdraw(mode,xorg,yorg,width,parm1,parm2,parm3,parm4) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Draw shape depending on mode at origin xorg,yorg with line width 'width and the parameters parm1,parm2,parm3. The supported shapes are: 0) line (parm1=length, parm2=angle) 1) circle (parm1=radius, parm2=ang1, parm3=ang2) .RETURN Status, 0:OK, -1:Error font-size, -2: wrong mode ------------------------------------------------------------------------*/ int mode; double xorg; /* Origin of shape in X */ double yorg; /* Origin of shape in Y */ double width; /* Width of line */ double parm1; /* Shape parameter 1 */ double parm2; /* Shape parameter 2 */ double parm3; /* Shape parameter 3 */ double parm4; /* Shape parameter 3 */ { int iox, ioy, iex, iey; double ang, ox, oy; if (psfid<0) return -1; /* check if ps-file open */ if (mode!=0 && mode!=1) return -2; /* none supported shape */ /* reset offset and scale */ (void) sprintf(text,"%f %f scale %d %d translate\n", 1.0/pscxs,1.0/pscys,-pscxo,-pscyo); (void) osawrite(psfid,text,strlen(text)); pscxo = 0; pscyo = 0; pscxs = 1.0; pscys = 1.0; (void) sprintf(text,"%f setlinewidth\n",PPCM*width); (void) osawrite(psfid,text,strlen(text)); switch (mode) { case 0: /* line */ ang = (atan(1.0)/45.0) * parm2; iox = PPCM*xorg; ioy = PPCM*yorg; iex = iox + PPCM*parm1*cos(ang); iey = ioy + PPCM*parm1*sin(ang); (void) sprintf(text,"%d %d moveto %d %d lineto stroke\n", iox,ioy,iex,iey); (void) osawrite(psfid,text,strlen(text)); bbupdate((double) iox, (double) ioy, (double) iex, (double) iey); break; case 1: /* circle arc */ ang = (atan(1.0)/45.0) * parm2; ox = PPCM*(xorg+parm1*cos(ang)); oy = PPCM*(yorg+parm1*sin(ang)); (void) sprintf(text,"%f %f moveto %f %f %f %f %f arc stroke\n", ox,oy,PPCM*xorg,PPCM*yorg,PPCM*parm1,parm2,parm3); (void) osawrite(psfid,text,strlen(text)); bbupdate(PPCM*(xorg-parm1), PPCM*(yorg-parm1), PPCM*(xorg+parm1), PPCM*(yorg+parm1)); break; } return 0; }