/* gd_src.c * * Updated: 2/2006 * 1) Upgrade to current versions of GD (and appropriate * auxillary libraries). * 2) New GD library (version 2.033) now supports GIF, * so add GIF support * 3) I've been having some compilation problems with * the new version of GD on a few platforms, so make * the GIF driver switchable with a define option. * The purpose of this library is to provide easy access from * a Fortran 77 program to the GD library. * * Specifically, I was interested in providing support for PNG and * JPEG images for generating web viewable graphics directly from * Dataplot. We previously had supported this by generating * Postscript and then using various image conversion software. * Although workable, the GD library allows us to build the support * for web viewable graphics directly into Dataplot. Dataplot * is a Fortran 77 program that uses a vector graphics model (as * oppossed to a bit-map model) to generate graphics. The GD * library provides a vector based interface to these formats * with a C library. * * Given my problem, I have not supported the full GD library. * Instead, I have supported a basic set of calls to support a * device driver for PNG or JPEG. This set of routines provides * a wrapper layer between Fortran and the C based GD libraries. * That is, these routines use only integer and real arguments with * no C specific structures. This makes the calling sequence from * Fortran easy. * * Although I wrote this wrapper with a specific application in * mind, I believe it may well be useful for other Fortran * codes. This code may be used and modified by anyone without * restriction. * * This code assumes that the following libraries are installed on * your system: * * libgd * libpng * jpeg-6b * zlib * * These libraries are all freely available and they are downloadable * from the web. A dummy version of this library is maintained for * those systems that do not support gd or that do not allow C * routines to be called from Fortran. Since the dummy library is * coded in Fortran, routine names will be limited to six characters. * * Note that calling C from Fortran is not standard. I have * provided the following compiler defintions to enhance portability. * * 1) The default is to assume that the Fortran compiler appends an * underscore to the routine name. Use -DNOUNDERSCORE if your * compiler does not append the underscore. * 2) The default is to assume that the Fortran compiler converts * routine names to lower case. Use -DUPPERCASE if your * Fortran compiler does not do this (e.g., the Cray). * 3) Many Unix compilers support a "-r8", or something similar, * to make single precision 64-bit. Use -DDOUBLE if you * compile your Fortran with this option. * 4) Character strings are the most troublesome issue for * portability. Passing character strings from Fortran to C * is very compiler dependent. I have addressed this issue * by passing character strings as arrays of ASCII Decimal * Equivalents (ADE's). That is, the Fortran converts a * character string to an array of the integer values where * the integer is the ASCII collating sequence (i.e., A = 65, * B = 66, etc.). The end of the string is denoted by setting * the value to 0. This is easily accomplished on the Fortran * side by using the ICHAR function. The C code here then * calls an internal routine to covnert the integer array to * a C string. Although a bit convoluted, this avoids a lot * of messy portability issues. * * * The following routines are included: * * gdinit - initialize gd library * gdend - close gd library * gderas - start a new graph (close currently open one as well) * gddraw - draw a polyline * gdseco - set foreground color * gdsepa - set line pattern * gdpoin - draw a point (i.e., a pixel) * gdcirc - draw a circle * gdrgfl - solid fill of a region * gdtxth - draw a horizontal character string * gdtxtv - draw a vertical character string * i_to_s_2 - utility routine to convert array of ADE's to string * array * */ /* Site dependent definitions (see comments above) */ /* Default is an underscore and lower case. The compiler specified * definitions -DNOUNDERSCORE and -DUPPERCASE can be specified to * override these defaults. */ #ifdef NOUNDERSCORE #define APPEND_UNDERSCORE 0 #else #define APPEND_UNDERSCORE 1 #endif #ifdef UPPERCASE #define SUBROUTINE_CASE 0 #else #define SUBROUTINE_CASE 1 #endif #ifdef DOUBLE #define PRECISION 1 #else #define PRECISION 0 #endif #ifdef NO_GIF #define GIF 0 #else #define GIF 1 #endif /* include files */ #include #include #include #include #include /* global definitions */ #define MAX_COLORS 89 #define MAX_GRAY 100 #define BORDER_WIDTH 3 #define DEFAULT_X_SIZE 600 #define DEFAULT_Y_SIZE 465 #define MIN_X_SIZE 100 #define MIN_Y_SIZE 100 /* GD declarations */ gdImagePtr im; /* Declare Image */ FILE *jpegout; /* File ID for Image */ char file_string[160]; /* Name of current file */ /* common parameters */ unsigned int width, height; /* last known window size */ unsigned long black, white; /* values for black and white */ int color_flag; /* 0 - monochrome, 1 - color */ int max_colors; /* maximum colors actually allocated */ int CURRENT_COLOR; /* Define current color */ int CURRENT_LINE_STYLE[12]; /* Define current line style */ int NPTS_STYLE = 0; /* Number of points in style */ int color_table[MAX_COLORS + 100]; /* color table */ int red[MAX_COLORS] = { /* 0 - 7 */ 255, 0, 255, 0, 0, 255, 255, 0, /* 8 - 15 */ 255, 154, 0, 173, 138, 208, 47, 211, /* 16 - 23 */ 127, 165, 95, 255, 100, 85, 153, 72, /* 24 - 31 */ 0, 178, 34, 255, 218, 192, 205, 240, /* 32 - 39 */ 105, 176, 50, 176, 102, 0, 107, 250, /* 40 - 47 */ 186, 60, 123, 0, 72, 199, 25, 0, /* 48 - 55 */ 255, 218, 152, 255, 221, 160, 250, 46, /* 56 - 63 */ 160, 125, 106, 0, 70, 210, 216, 64, /* 64 - 71 */ 238, 245, 173, 224, 0, 0, 0, 0, /* 72 - 79 */ 0, 0, 0, 0, 0, 238, 205, 139, /* 80 - 87 */ 238, 205, 139, 238, 205, 139, 238, 205, /* 88 - 88 */ 139 }; int green[MAX_COLORS] = { /* 0 - 7 */ 255, 0, 0, 0, 255, 0, 165, 255, /* 8 - 15 */ 255, 205, 100, 216, 43, 32, 79, 211, /* 16 - 23 */ 255, 42, 158, 127, 149, 107, 50, 61, /* 24 - 31 */ 206, 34, 139, 215, 165, 192, 92, 230, /* 32 - 39 */ 105, 196, 205, 48, 205, 0, 142, 250, /* 40 - 47 */ 85, 179, 104, 250, 209, 21, 25, 0, /* 48 - 55 */ 69, 112, 251, 192, 160, 32, 128, 139, /* 56 - 63 */ 82, 206, 90, 255, 130, 180, 191, 224, /* 64 - 71 */ 130, 222, 255, 255, 0, 0, 0, 238, /* 72 - 79 */ 205, 139, 238, 205, 139, 238, 205, 139, /* 80 - 87 */ 154, 133, 90, 0, 0, 0, 0, 0, /* 88 - 88 */ 0 }; int blue[MAX_COLORS] = { /* 0 - 7 */ 255, 0, 0, 255, 0, 255, 0, 255, /* 8 - 15 */ 0, 50, 0, 230, 226, 144, 79, 211, /* 16 - 23 */ 212, 42, 160, 80, 237, 47, 204, 139, /* 24 - 31 */ 209, 34, 34, 0, 32, 192, 92, 140, /* 32 - 39 */ 105, 222, 50, 96, 170, 205, 35, 210, /* 40 - 47 */ 85, 179, 104, 250, 209, 21, 25, 0, /* 48 - 55 */ 0, 214, 152, 203, 221, 240, 114, 87, /* 56 - 63 */ 45, 235, 205, 127, 180, 140, 216, 208, /* 64 - 71 */ 238, 179, 47, 255, 238, 205, 139, 238, /* 72 - 79 */ 205, 139, 0, 0, 0, 0, 0, 0, /* 80 - 87 */ 0, 0, 0, 0, 0, 0, 238, 205, /* 88 - 88 */ 139 }; /* flags for current attribute settings */ static int OPEN_FLAG = 0; /* 0 - GD closed, 1 - GD open */ int DEVICE_TYPE = 0; /* define device */ /* 1 - jpeg */ /* 2 - png */ /* 3 - windows bmp */ char FONT_NAME_CURRENT[80]; /* name of current font */ char FONT_NULL[80]; /* null font */ char FONT_NAME_DEFAULT[80]; /* name of default font */ int FONT_HEIGHT_CURRENT; /* pixel ascent of current font */ int FONT_DESCENT_CURRENT; /* descent of current font */ int FONT_GAP_CURRENT; /* vertical gap of current font */ #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1 void gdend_(), gddraw_(), gdpoin_(), gdcirc_(), gdrgfl_(); void gdinit_(), gderas_(), gdtxth_(), gdtxtv_(); void gdseco_(), gdsepa_(); #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0 void GDEND_(), GDINIT_(), GDDRAW_(), GDPOIN_(), GDCIRC_(), GDRGFL_(); void GDINIT_(), GDERAS_(), GDTXTH_(), GDTXTV_(); void GDSECO_(), GDSEPA_(); #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1 void gdend(), gddraw(), gdpoin(), gdcirc(), gdrgfl(); void gdinit(), gderas(), gdtxth(), gdtxtv(),gdtatt(); void gdseco(), gdsepa(); #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0 void GDEND(), GDDRAW(), GDPOIN(), GDCIRC(), GDRGFL(); void GDINIT(), GDERAS(), GDTXTH(), GDTXTV(); void GDSECO(), GDSEPA(); #endif void i_to_s_2(); /* GDINIT - routine to initialize GD. * For GD device, simply set flag saying this routine * has been called, initialize a few variables. * * DEVICE_TYPE = 1 -- jpeg * DEVICE_TYPE = 2 -- png * DEVICE_TYPE = 3 -- wbmp * DEVICE_TYPE = 4 -- gif * */ #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1 void gdinit_(itype) #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0 void GDINIT_(itype) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1 void gdinit(itype) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0 void GDINIT(itype) #endif #if PRECISION == 0 int *itype; #else int itype[2]; #endif { int itype_temp; #if PRECISION == 0 itype_temp = *itype; #else itype_temp = itype[0]; #endif DEVICE_TYPE = itype_temp; OPEN_FLAG = 0; } /* GDERAS - routine to clear the screen. Since PNG and JPEG devices * treat each plot as a separate file, initialization * functions occur here rather than GDINIT. Do the * following: * 1) Check if a plot is currently open. If yes, write * it to a file and destroy the current image. * 2) Create a new image with the specified size specified * in pixels. Note that orientation (landscape, portrait, * is implicit in the pixel dimensions). Note that * this routine does not modify the values. * 3) Set all colors to be undefined and then set * background and foreground colors. * * xpixels - width (in pixels) for graphics window * ypixels - height (in pixels) for graphics window * back_col - background color * file name - file name (in integer ascii decimal equivalents) * */ #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1 void gderas_(xpixels, ypixels, back_col, file_name) #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0 void GDERAS_(xpixels, ypixels, back_col, file_name) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1 void gderas(xpixels, ypixels, back_col, file_name) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0 void GDERAS(xpixels, ypixels, back_col, file_name) #endif #if PRECISION == 0 int *xpixels, *ypixels, *back_col; int file_name[]; #else int xpixels[2], ypixels[2], back_col[2]; int file_name[]; #endif { int back_col_temp, temp_color, temp_color_2; int xpixels_temp, ypixels_temp; int len; int itemp, quality; int i; int itemp1, itemp2; float ai, atemp2; #if PRECISION == 0 back_col_temp = *back_col; xpixels_temp = *xpixels; ypixels_temp = *ypixels; #else back_col_temp = back_col[0]; xpixels_temp = xpixels[0]; ypixels_temp = ypixels[0]; #endif /* First, check if a graph is currently open, if so write it to the current file name. */ if (OPEN_FLAG == 1) { /* interlaced images load faster on web, but leave for now */ /* gdImageInterlace(im,1); */ jpegout = fopen(file_string,"wb"); if (DEVICE_TYPE == 1) { quality = -1; gdImageJpeg(im,jpegout,quality); } else if (DEVICE_TYPE == 2) { gdImagePng(im,jpegout); } else if (DEVICE_TYPE == 3) { itemp=1; /* gdImageWBMP(im,itemp,jpegout); */ } else if (DEVICE_TYPE == 4) { #if GIF == 1 gdImageGif(im,jpegout); #endif } else { quality = -1; gdImageJpeg(im,jpegout,quality); } fclose(jpegout); gdImageDestroy(im); } /* Now, start new image */ #if PRECISION == 0 i_to_s_2(file_name, file_string, 80, &len); #else i_to_s_2(file_name, file_string, 160, &len); #endif im = gdImageCreate(xpixels_temp, ypixels_temp); /* Open Image */ /* Set colors */ back_col_temp = back_col_temp - 1; gdImageColorAllocate(im, red[back_col_temp],green[back_col_temp],blue[back_col_temp]); for (i=0; i < MAX_COLORS; i++) { color_table[i] = gdImageColorAllocate(im,red[i],green[i],blue[i]); } for (i=0; i < 100; i++) { itemp1 = i + MAX_COLORS; ai = i; atemp2 = 255.*(ai/100.); itemp2 = atemp2; color_table[itemp1] = gdImageColorAllocate(im,itemp2,itemp2,itemp2); } OPEN_FLAG = 1; } /* GDEND - routine to end GD. Close the display. * */ #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1 void gdend_(file_name) #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0 void GDEND_(file_name) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1 void gdend(file_name) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0 void GDEND(file_name) #endif int file_name[]; { int quality; int itemp; int len; #if PRECISION == 0 i_to_s_2(file_name, file_string, 80, &len); #else i_to_s_2(file_name, file_string, 160, &len); #endif if (OPEN_FLAG == 1) { /* interlaced images load faster on web, but leave for now */ /* gdImageInterlace(im,1); */ jpegout = fopen(file_string,"wb"); if (DEVICE_TYPE == 1) { quality = -1; gdImageJpeg(im,jpegout,quality); } else if (DEVICE_TYPE == 2) { gdImagePng(im,jpegout); } else if (DEVICE_TYPE == 3) { itemp=1; /* gdImageWBMP(im,itemp,jpegout); */ } else if (DEVICE_TYPE == 4) { #if GIF == 1 gdImageGif(im,jpegout); #endif } else { gdImageJpeg(im,jpegout,quality); } fclose(jpegout); gdImageDestroy(im); } OPEN_FLAG = 0; } /* GDDRAW - draw a polyline. The color and line style have * been set in GDSECO and GDSEPA (line thickness is * generated in software) * * xpts - contains the x coordinates * ypts - contains the y coordinates * npts - the number of points to plot * */ #define MAX_LINE_POINTS 500 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1 void gddraw_(ix1,iy1,ix2,iy2) #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0 void GDDRAW_(ix1,iy1,ix2,iy2) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1 void gddraw(ix1,iy1,ix2,iy2) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0 void GDDRAW(ix1,iy1,ix2,iy2) #endif #if PRECISION == 0 int *ix1, *iy1, *ix2, *iy2; #else int ix1[2], iy1[2], ix2[2], iy2[2]; #endif { int ix1_temp; int iy1_temp; int ix2_temp; int iy2_temp; #if PRECISION == 0 ix1_temp = *ix1; iy1_temp = *iy1; ix2_temp = *ix2; iy2_temp = *iy2; #else ix1_temp = ix1[0]; iy1_temp = iy1[0]; ix2_temp = ix2[0]; iy2_temp = iy2[0]; #endif if (NPTS_STYLE <= 0) { /* Solid Line */ gdImageLine(im, ix1_temp, iy1_temp, ix2_temp, iy2_temp, color_table[CURRENT_COLOR]); } else { /* Dashed or Dotted Line */ gdImageSetStyle(im, CURRENT_LINE_STYLE, NPTS_STYLE); gdImageLine(im,ix1_temp,iy1_temp,ix2_temp,iy2_temp,gdStyled); } } /* GDSECO - set the color * * jcol - index for desired color * */ #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1 void gdseco_(jcol) #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0 void GDSECO_(jcol) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1 void gdseco(jcol) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0 void GDSECO(jcol) #endif #if PRECISION == 0 int *jcol; #else int jcol[2]; #endif { int jcol_temp; #if PRECISION == 0 jcol_temp = *jcol; #else jcol_temp = jcol[0]; #endif if (jcol_temp >= 0 ) { jcol_temp = jcol_temp - 1; CURRENT_COLOR = jcol_temp; } else { jcol_temp = -jcol_temp; jcol_temp = jcol_temp + MAX_COLORS - 1; CURRENT_COLOR = jcol_temp; } } /* GDSEPA - set pattern for lines * * jpatt - the line pattern * */ #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1 void gdsepa_(jpatt) #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0 void GDSEPA_(jpatt) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1 void gdsepa(jpatt) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0 void GDSEPA(jpatt) #endif #if PRECISION == 0 int *jpatt; #else int jpatt[2]; #endif { int jpatt_temp; #if PRECISION == 0 jpatt_temp = *jpatt; #else jpatt_temp = jpatt[0]; #endif if (jpatt_temp == 1) { /* Solid Line */ CURRENT_LINE_STYLE[0] = 0; NPTS_STYLE = 0; } else if (jpatt_temp == 2) { /* Dashed Line */ CURRENT_LINE_STYLE[0] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[1] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[2] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[3] = gdTransparent; CURRENT_LINE_STYLE[4] = gdTransparent; CURRENT_LINE_STYLE[5] = gdTransparent; NPTS_STYLE = 6; } else if (jpatt_temp == 3) { /* Dotted Line */ CURRENT_LINE_STYLE[0] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[1] = gdTransparent; NPTS_STYLE = 2; } else if (jpatt_temp == 4) { /* DA2 Line */ CURRENT_LINE_STYLE[0] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[1] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[2] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[3] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[4] = gdTransparent; CURRENT_LINE_STYLE[5] = gdTransparent; NPTS_STYLE = 6; } else if (jpatt_temp == 5) { /* DA3 Line */ CURRENT_LINE_STYLE[0] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[1] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[2] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[3] = gdTransparent; CURRENT_LINE_STYLE[4] = gdTransparent; CURRENT_LINE_STYLE[5] = gdTransparent; CURRENT_LINE_STYLE[6] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[7] = gdTransparent; NPTS_STYLE = 8; } else if (jpatt_temp == 6) { /* DA4 Line */ CURRENT_LINE_STYLE[0] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[1] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[2] = gdTransparent; CURRENT_LINE_STYLE[3] = gdTransparent; NPTS_STYLE = 4; } else if (jpatt_temp == 7) { /* DA5 Line */ CURRENT_LINE_STYLE[0] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[1] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[2] = gdTransparent; CURRENT_LINE_STYLE[3] = color_table[CURRENT_COLOR]; CURRENT_LINE_STYLE[4] = gdTransparent; NPTS_STYLE = 5; } else { CURRENT_LINE_STYLE[0] = 0; NPTS_STYLE = 0; } } /* GDPOIN - draw a point. * * ix - contains the x coordinate * iy - contains the y coordinate * jcol - color to use in drawing the point * */ #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1 void gdpoin_(ix, iy, jcol) #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0 void GDPOIN_(ix, iy, jcol) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1 void gdpoin(ix, iy, jcol) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0 void GDPOIN(ix, iy, jcol) #endif #if PRECISION == 0 int *ix, *iy, *jcol; #else int ix[2], iy[2], jcol[2]; #endif { #if PRECISION == 0 gdImageSetPixel(im, *ix, *iy, color_table[*jcol]); #else gdImageSetPixel(im, ix[0], iy[0], color_table[jcol[0]]); #endif } /* GDCIRC - draw a circle. Note that the circle may be either filled or * unfilled. For a filled circle, do twice, (once for the * outline, once to fill the interior). * * ix - contains the x coordinate for the center of the circle * iy - contains the y coordinate for the center of the circle * irad - radius * ifill - 0 for unfilled circle, 1 for filled circle * */ #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1 void gdcirc_(ix, iy, irad, ifill, jcol) #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0 void GDCIRC_(ix, iy, irad, ifill, jcol) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1 void gdcirc(ix, iy, irad, ifill, jcol) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0 void GDCIRC(ix, iy, irad, ifill, jcol) #endif #if PRECISION == 0 int *ix, *iy, *irad, *ifill, *jcol; #else int ix[2], iy[2], irad[2], ifill[2], jcol[2]; #endif { int xpos, ypos, iwidth, iheight, iang1, iang2, ir, jcol_t; iang1 = 0; iang2 = 360; #if PRECISION == 0 ir = *irad; jcol_t = *jcol; xpos = *ix - *irad; ypos = *iy - *irad; #else ir = irad[0]; jcol_t = jcol[0]; xpos = ix[0] - irad[0]; ypos = iy[0] - irad[0]; #endif iwidth = 2 * ir; iheight = 2 * ir; gdImageArc(im, xpos, ypos, iwidth, iheight, iang1, iang2, color_table[jcol_t]); } /* GDRGFL - fill a region. Rectangular regions will be filled differently * non-rectangular regions. Dataplot only handles convex polygons, * so set this (for faster performance). This routine only does * solid fills. Hatch patterns must be drawn * by the calling program (i.e., send the individual lines to * the GDDRAW routine). * * xpts - contains the x coordinates * ypts - contains the y coordinates * npts - the number of points in the polygon (if 2, assume a rectangle, * otherwise, a convex polygon) * */ #define MAX_REG_POINTS 1000 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1 void gdrgfl_(xpts, ypts, npts, jcol) #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0 void GDRGFL_(xpts, ypts, npts, jcol) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1 void gdrgfl(xpts, ypts, npts, jcol) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0 void GDRGFL(xpts, ypts, npts, jcol) #endif int xpts[], ypts[]; #if PRECISION == 0 int *npts, *jcol; #else int npts[2], jcol[2]; #endif { int points[MAX_REG_POINTS]; int npts_temp, jcol_temp, indx; #if PRECISION == 0 npts_temp = *npts; jcol_temp = *jcol; #else npts_temp = npts[0]; jcol_temp = jcol[0]; #endif #if PRECISION == 0 indx = 1; #else indx = 2; #endif if (npts_temp == 2) { /* rectangle */ int x1, y1, x2, y2; if (xpts[0] <= xpts[indx]) { x1 = xpts[0]; x2 = xpts[indx]; } else { x1 = xpts[indx]; x2 = xpts[0]; } if (ypts[0] <= ypts[indx]) { y1 = ypts[0]; y2 = ypts[indx]; } else { y1 = ypts[indx]; y2 = ypts[0]; } gdImageFilledRectangle(im, x1, y1, x2, y2, color_table[jcol_temp-1]); } else if (npts_temp > 2) { /* convex polygon */ /* int i, temp; temp = npts_temp; if(npts_temp > MAX_REG_POINTS) temp = MAX_REG_POINTS; for (i = 0; i < temp; i++) { #if PRECISION == 0 points[i].x = xpts[i]; points[i].y = ypts[i]; #else points[i].x = xpts[2*i]; points[i].y = ypts[2*i]; #endif } gdImageFilledPolygon(im,points,temp,color_table[jcol_temp-1]); */ } } /* GDTXTH - draw a horizontal text string. * * NOTE: This is not implemented on our first * pass for this driver. Issue of how * to access fonts, set sizes and * justifications need to be addressed. * * * string - text string to draw * ixpos - x position * iypos - y position * ijusth - justification (horizontal) * 0 - left justified * 1 - center justified * 2 - right justified * ijustv - justiciation (vertical) * 0 - center justified * 1 - bottom justified * 2 - top justified * jcol - color * error - error flag * */ #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1 void gdtxth_(string, ixpos, iypos, ijusth, ijustv, jcol, error) #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0 void GDTXTH_(string, ixpos, iypos, ijusth, ijustv, jcol, error) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1 void gdtxth(string, ixpos, iypos, ijusth, ijustv, jcol, error) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0 void GDTXTH(string, ixpos, iypos, ijusth, ijustv, jcol, error) #endif int string[]; #if PRECISION == 0 int *ixpos, *iypos, *ijusth, *ijustv, *jcol, *error; #else int ixpos[2], iypos[2], ijusth[2], ijustv[2], jcol[2], error[2]; #endif { int itest, itempx, itempy; /* temporary variables */ int len; /* number of characters in string */ int string_width; /* width of string in pixels */ char string2[130]; /* converted string */ int i; int ixpos_temp, iypos_temp, ijusth_temp, ijustv_temp; int jcol_temp; #if PRECISION == 0 ixpos_temp = *ixpos; iypos_temp = *iypos; ijusth_temp = *ijusth; ijustv_temp = *ijustv; jcol_temp = *jcol; #else ixpos_temp = ixpos[0]; iypos_temp = iypos[0]; ijusth_temp = ijusth[0]; ijustv_temp = ijustv[0]; jcol_temp = jcol[0]; #endif #if PRECISION == 0 i_to_s_2(string, string2, 130, &len); #else i_to_s_2(string, string2, 260, &len); #endif /* string_width = XTextWidth(font_struct, string2, len); */ switch (ijusth_temp) { case 0: /* Left justified string */ itempx = ixpos_temp; break; case 1: /* Center justified string */ itempx = ixpos_temp - (string_width/2); break; case 2: /* Right justified string */ itempx = ixpos_temp - string_width; break; default: itempx = ixpos_temp; break; } switch (ijustv_temp) { case 0: /* Center justified string */ itempy = iypos_temp + (FONT_HEIGHT_CURRENT/2.0); break; case 1: /* Bottom justified string */ itempy = iypos_temp; break; case 2: /* Top justified string */ itempy = iypos_temp + FONT_HEIGHT_CURRENT; break; default: itempy = iypos_temp + (FONT_HEIGHT_CURRENT/2.0); break; } } /* GDTXTV - draw a horizontal text string. * * NOTE: This is not implemented on our first * pass for this driver. Issue of how * to access fonts, set sizes and * justifications need to be addressed. * * * string - text string to draw * ixpos - x position * iypos - y position * ijusth - justification (horizontal) * 0 - left justified * 1 - center justified * 2 - right justified * ijustv - justiciation (vertical) * 0 - center justified * 1 - bottom justified * 2 - top justified * jcol - color * error - error flag * */ #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1 void gdtxtv_(string, ixpos, iypos, ijusth, ijustv, jcol, error) #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0 void GDTXTV_(string, ixpos, iypos, ijusth, ijustv, jcol, error) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1 void gdtxtv(string, ixpos, iypos, ijusth, ijustv, jcol, error) #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0 void GDTXTV(string, ixpos, iypos, ijusth, ijustv, jcol, error) #endif int string[]; #if PRECISION == 0 int *ixpos, *iypos, *ijusth, *ijustv, *jcol, *error; #else int ixpos[2], iypos[2], ijusth[2], ijustv[2], jcol[2], error[2]; #endif { int itest, itempx, itempy; /* temporary variables */ int len; /* number of characters in string */ int y_pix_len; /* height of entire string */ int string_width; /* width of string in pixels */ char string2[130]; /* converted string */ int i, ijunk; #if PRECISION == 0 int string3[2]; /* one character at a time */ #else int string3[4]; /* one character at a time */ #endif int ixpos_temp, iypos_temp, ijusth_temp, ijustv_temp; int jcol_temp; #if PRECISION == 0 ixpos_temp = *ixpos; iypos_temp = *iypos; ijusth_temp = *ijusth; ijustv_temp = *ijustv; jcol_temp = *jcol; #else ixpos_temp = ixpos[0]; iypos_temp = iypos[0]; ijusth_temp = ijusth[0]; ijustv_temp = ijustv[0]; jcol_temp = ijustv[0]; #endif #if PRECISION == 0 i_to_s_2(string, string2, 130, &len); #else i_to_s_2(string, string2, 260, &len); #endif y_pix_len = len * (FONT_HEIGHT_CURRENT + FONT_GAP_CURRENT); switch (ijustv_temp) { case 0: /* Center justified string */ itempy = -(y_pix_len/2) + FONT_HEIGHT_CURRENT; break; case 1: /* Bottom justified string */ itempy = -y_pix_len + FONT_HEIGHT_CURRENT; break; case 2: /* Top justified string */ itempy = FONT_HEIGHT_CURRENT; break; default: itempy = -(y_pix_len/2) + FONT_HEIGHT_CURRENT; break; } itempy = iypos_temp + itempy; #if PRECISION == 0 string3[1] = 0; for (i = 0; i < len; i++) { /* plot each character one at a time */ string3[0] = string[i]; i_to_s_2(string3,string2, 2, &ijunk); /* string_width = XTextWidth(font_struct, string2, 1); */ switch (ijusth_temp) { case 0: /* Left justified string */ itempx = 0; break; case 1: /* Center justified string */ itempx = (string_width/2); break; case 2: /* Right justified string */ itempx = string_width; break; default: itempx = ixpos_temp; break; } itempx = ixpos_temp - itempx; itempy = itempy + (FONT_HEIGHT_CURRENT + FONT_GAP_CURRENT); } #else string3[1] = 0; string3[2] = 0; string3[3] = 0; for (i = 0; i < len; i++) { /* plot each character one at a time */ string3[0] = string[2*i]; i_to_s_2(string3,string2, 4, &ijunk); switch (ijusth_temp) { case 0: /* Left justified string */ itempx = 0; break; case 1: /* Center justified string */ itempx = (string_width/2); break; case 2: /* Right justified string */ itempx = string_width; break; default: itempx = ixpos_temp; break; } itempx = ixpos_temp - itempx; itempy = itempy + (FONT_HEIGHT_CURRENT + FONT_GAP_CURRENT); } #endif } /* i_to_s_2 - utitlity routine to convert an integer array containing * Ascii Decimal Equivalents to a character string array. The * Fortran routines pass character type data as an array of * ADE's, which this routine then converts to C's character * type. Note that the input array is assumed to be correct * (i.e., a value between 0 and 127) and no error checking is * done on it. * * string1 - input array containing ADE's. * string2 - output array in C character format. * maxlen - maximum length for string2 * ilen - length of character string * */ void i_to_s_2(string1, string2, maxlen, ilen) int string1[], maxlen, *ilen; char string2[]; { int i; int itemp; i = 0; #if PRECISION == 0 while (string1[i] != 0 && i < (maxlen - 1) ) { itemp = string1[i]; string2[i] = string1[i]; i++; } *ilen = i; string2[i]='\0'; } #else while (string1[2*i] != 0 && i < (maxlen - 1) ) { itemp = string1[2*i]; string2[i] = string1[2*i]; i++; } *ilen = i; string2[i]='\0'; } #endif