diff options
Diffstat (limited to 'vendor/x11iraf/cdl/cdlmark.c')
-rw-r--r-- | vendor/x11iraf/cdl/cdlmark.c | 3861 |
1 files changed, 3861 insertions, 0 deletions
diff --git a/vendor/x11iraf/cdl/cdlmark.c b/vendor/x11iraf/cdl/cdlmark.c new file mode 100644 index 00000000..16a06965 --- /dev/null +++ b/vendor/x11iraf/cdl/cdlmark.c @@ -0,0 +1,3861 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <math.h> +#define CDL_NEED_LINESTYLES +#define CDL_LIBRARY_SOURCE +#include "cdl.h" +#include "cdlfont.h" + +/* + * CDL Marker Procedures -- Procedures for doing overlay graphics. + * + * cdl_mapFrame (cdl, frame) + * cdl_markCoordsFile (cdl, fname, type, size, color, label) + * cdl_markPoint (cdl, x, y, number, size, type, color) + * cdl_markPointLabel (cdl, x, y, label, size, type, color) + * cdl_markLine (cdl, xs, ys, xe, ye, color) + * cdl_markBox (cdl, lx, ly, ux, uy, fill, color) + * cdl_markPolyline (cdl, xpts, ypts, npts, color) + * cdl_markPolygon (cdl, xpts, ypts, npts, fill, color) + * cdl_markCircle (cdl, x, y, radius, fill, color) + * cdl_markCircAnnuli (cdl, x, y, radius, nannuli, sep, color) + * cdl_markEllipse (cdl, x, y, xrad, yrad, ang, fill, color) + * cdl_markEllipAnnuli (cdl, x, y, xrad, yrad, ang, nannuli, sep, color) + * cdl_markText (cdl, x, y, str, size, angle, color) + * + * cdl_setFont (cdl, font) + * cdl_setTextWidth (cdl, width) + * cdl_setLineWidth (cdl, width) + * cdl_setLineStyle (cdl, style) + * + * cdl_deleteMark (cdl, x, y) + * cdl_clearOverlay (cdl) + * cdl_redrawOverlay (cdl) + * + * cdl_beginDList (frame) Not Yet Implemented + * cdl_clearDList (frame) Not Yet Implemented + * cdl_drawDList (frame) Not Yet Implemented + * cdl_endDList (frame, flush) Not Yet Implemented + */ + +/* Function prototypes */ +#ifdef __STDC__ +#include <stddef.h> +#endif + +#ifdef ANSI_FUNC + +static int cdl_getPixRegion(CDLPtr cdl, int lx, int ly, int nx, int ny, uchar *ras); +static void cdl_doPointMark(int color, int type, uchar *pix, int sz); +static void cdl_doLineMark(int color, int width, int style, uchar *pix, int xs, int ys, int xe, int ye); +static void cdl_doBoxMark(int color, int width, int style, int fill, uchar *pix, int lx, int ly, int nx, int ny); +static void cdl_doPolygonMark(int color, int width, int style, int fill, int *x, int *y, int npts, uchar *pix, int lx, int ly, int nx, int ny, int close); +static void cdl_doCircleMark(int x, int y, int radius, int color, int width, int style, int fill, uchar *pix, int lx, int ly, int nx, int ny); +static void cdl_doCircAnnuliMark(int x, int y, int radius, int nannuli, int sep, int color, int width, int style, uchar *pix, int lx, int ly, int nx, int ny); +static void cdl_doEllipseMark(int color, int width, int style, int fill, int xc, int yc, int xrad, int yrad, float ang, uchar *pix, int lx, int ly, int nx, int ny); +static void cdl_doEllipAnnuliMark(int x, int y, int xrad, int yrad, float ang, int nannuli, int sep, int color, int width, int style, uchar *pix, int lx, int ly, int nx, int ny); +int cdl_doTextMarker(int x, int y, char *string, float size, float angle, int color, int width, int font, uchar *pix, int lx, int ly, int nx, int ny); +int cdl_freeDisplayList(CDLPtr cdl, MarkerPtr head); +static void cdl_insertMarker(CDLPtr cdl, MarkerPtr back, MarkerPtr new); +static void cdl_removeMarker(CDLPtr cdl, MarkerPtr mk); +static MarkerPtr cdl_findNearest(MarkerPtr head, int x, int y); +static void cdl_printDisplayList(FILE *fd, MarkerPtr head); +static MarkerPtr cdl_initPointMarker(int x, int y, int number, int size, int type, int color); +static MarkerPtr cdl_initPointLabelMarker(int x, int y, char *label, int size, int type, int color, int font); +static MarkerPtr cdl_initLineMarker(int x1, int y1, int x2, int y2, int color, int width, int style); +static MarkerPtr cdl_initBoxMarker(int lx, int ly, int ux, int uy, int fill, int color, int width, int style); +static MarkerPtr cdl_initPolylineMarker(int *x, int *y, int npts, int color, int width, int style); +static MarkerPtr cdl_initPolygonMarker(int *x, int *y, int npts, int fill, int color, int width, int style); +static MarkerPtr cdl_initCircleMarker(int x, int y, int radius, int fill, int color, int width, int style); +static MarkerPtr cdl_initCircAnnMarker(int x, int y, int radius, int nannuli, int sep, int color, int width, int style); +static MarkerPtr cdl_initEllipseMarker(int x, int y, int xrad, int yrad, float ang, int fill, int color, int width, int style); +static MarkerPtr cdl_initEllAnnMarker(int x, int y, int xrad, int yrad, float ang, int nannuli, int sep, int color, int width, int style); +static MarkerPtr cdl_initTextMarker(int x, int y, char *string, float size, int color, int font, int width); +static void cdl_initMarkPos(MarkerPtr mk, int nx, int ny, int lx, int ly); +static void cdl_doLineInSubRas(uchar *pix, int color, int width, int style, int x1, int x2, int y1, int y2, int lx, int ly, int nx, int ny); +static void cdl_doDashedLine(uchar *pix, int color, int width, int style, int *x, int *y, int np, int lx, int ly, int nx, int ny); +static void cdl_drawThickVector (uchar *pix, int color, int width, int style, int x1, int x2, int y1, int y2, int lx, int ly, int nx, int ny); +static void cdl_drawVector(uchar *pix, int color, int x1, int x2, int y1, int y2, int lx, int ly, int nx, int ny); +static void cdl_drawThickDashVec (uchar *pix, int color, int width, int style, int x1, int x2, int y1, int y2, int lx, int ly, int nx, int ny); +static void cdl_drawDashVec(uchar *pix, int color, int style, int x1, int x2, int y1, int y2, int lx, int ly, int nx, int ny); +static uchar cdl_setpixel(uchar pix, int style, int color); +static void cdl_fillArea(uchar *pix, int nx, int ny, int color); +static void cdl_getCircleCoords(int xcen, int ycen, int radius, int *x, int *y, int npts); +static void cdl_getEllipseCoords(int xcen, int ycen, int xradius, int yradius, float rotang, int *x, int *y); +static void cdl_minmax(int *array, int npts, int *amin, int *amax); +static int cdl_strlen(char *str, float size, int font); +static int bitupk(unsigned int wordp, int offset, int nbits); + +#else + +int cdl_freeDisplayList(); +void cdl_setFont(), cdl_setLineWidth(), cdl_setLineStyle(); +void cdl_beginDList(), cdl_drawDList(); +void cdl_clearDList(), cdl_endDList(), cdl_setTextWidth(); + +static int cdl_getPixRegion(); +static uchar cdl_setpixel(); +static void cdl_insertMarker(), cdl_removeMarker(); +static void cdl_doLineInSubRas(), cdl_drawThickVector(), cdl_drawVector(); +static void cdl_doPointMark(), cdl_doLineMark(), cdl_doBoxMark(); +static void cdl_doPolygonMark(), cdl_doCircleMark(), cdl_doCircAnnuliMark(); +static void cdl_doEllipseMark(), cdl_doEllipAnnuliMark(); +static void cdl_getCircleCoords(), cdl_getEllipseCoords(); +static void cdl_printDisplayList(), cdl_initMarkPos(); +static void cdl_fillArea(), cdl_minmax(), cdl_doDashedLine(); +static void cdl_drawThickDashVec(), cdl_drawDashVec(); + +static int cdl_strlen(), bitupk(); + +static MarkerPtr cdl_initPointMarker(), cdl_initLineMarker(); +static MarkerPtr cdl_initBoxMarker(), cdl_initPolylineMarker(); +static MarkerPtr cdl_initPolygonMarker(), cdl_initCircleMarker(); +static MarkerPtr cdl_initCircAnnMarker(), cdl_initEllipseMarker(); +static MarkerPtr cdl_initEllAnnMarker(), cdl_findNearest(); +static MarkerPtr cdl_initTextMarker(), cdl_initPointLabelMarker(); + +#endif + + +/* Display list declarations. We keep a separate list for each frame that + * is freed whenever a new image is displayed. The list is maintained as + * a doubly-linked list of Marker structs. + */ +MarkerPtr DLHead[MAX_FRAMES]; /* diplay list head */ +MarkerPtr DLTail[MAX_FRAMES]; /* diplay list tail */ +int DLFlag[] = { /* display list flags. */ + 0, 0, 0, 0, /* If set we're doing */ + 0, 0, 0, 0 /* markers in memory */ + }; +uchar *DLFBPix[MAX_FRAMES]; /* frame buffer pixels */ + + +/* absolute value of a */ +#define ABS(a) (((a)<0) ? -(a) : (a)) + +/* take binary sign of a, either -1, or 1 if >= 0 */ +#define SGN(a) (((a)<0) ? -1 : 1) + +#define N_CIRCLE_PTS 48 /* no. of points defining unit circle */ +#define N_ELLIPSE_PTS 64 /* no. of points defining unit ellipse */ +#define FONT_SCALE 0.36 /* default text font scale */ +#define FONT_SPACE 4 /* default text font spacing */ + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +extern int cdl_debug; + + + +/* CDL_MAPFRAME -- Map the current frame buffer as an image for overlay. + * This routine is a bit of a hack since we're trying to make some guesses + * about what the server has displayed, there's no way to actually query it. + * We assume the fbconfig has already been reset if it's not the default, + * and we assume the WCS defined is for a single image centered in the frame. + */ + +#ifdef ANSI_FUNC + +int +cdl_mapFrame ( + CDLPtr cdl, /* package ptr */ +int frame /* fb frame to map */ +) +#else + +int +cdl_mapFrame (cdl, frame) +CDLPtr cdl; /* package ptr */ +int frame; /* fb frame to map */ +#endif +{ + int xo, yo; + float a, b, c, d, tx, ty, z1, z2; + int zt; + char *name = NULL, *title = NULL; + + name = (char *) malloc (SZ_NAME); + title = (char *) malloc (SZ_NAME); + + /* Select the requested frame. */ + cdl_setFrame (cdl, frame); + + /* Get/Set the current WCS. */ + (void) cdl_getWCS (cdl, name, title, &a, &b, &c, &d, &tx, &ty, + &z1, &z2, &zt); + + /* If no WCS is defined for the frame make up a default. */ + if ((a+b+c+d+tx+ty+z1+z2+zt) == 0.0) { + a = 1.0; + b = 0.0; + c = 0.0; + d = -1.0; + tx = 1.0; + ty = (float) cdl->fbheight; + z1 = 0.0; + z2 = 255.0; + zt = CDL_LINEAR; + } + (void) cdl_setWCS (cdl, name, title, a, b, c, d, tx, ty, z1, z2, zt); + + /* Reset the image corners, assume image is centered in the frame. */ + xo = - cdl->tx + 1; + yo = cdl->fbheight - cdl->ty; + cdl->imd->xs = xo; + cdl->imd->ys = yo; + cdl->imd->xe = cdl->fbwidth - xo + 1; + cdl->imd->ye = cdl->fbheight - yo + 1; + + free (name); + free (title); + return (OK); +} + + +/* CDL_MARKPOINT -- Draw a mark on the display at the given point. Marks + * be specified as either a '+', 'x', or '*'. If the number argument is + * positive that value will be drawn next to the mark as a label string. + */ + +#ifdef ANSI_FUNC + +int +cdl_markPoint ( + CDLPtr cdl, /* package ptr */ + int x, + int y, /* marker position */ + int number, /* if > 0, label value */ + int size, /* marker size (pixels) */ + int type, /* type to draw */ + int color /* marker color */ +) +#else + +int +cdl_markPoint (cdl, x, y, number, size, type, color) +CDLPtr cdl; /* package ptr */ +int x, y; /* marker position */ +int number; /* if > 0, label value */ +int size; /* marker size (pixels) */ +int type; /* type to draw */ +int color; /* marker color */ +#endif +{ + register int lx, ly, sz; + uchar *pix = NULL; + MarkerPtr mk = cdl_initPointMarker (x, y, number, size, type, color); + + if (cdl_debug) + printf ("[cdl_markPoint] (%dx%d) num=%d size=%d type=%d color=%d\n", + x, y, number, size, type, color); + + sz = (size % 2 ? size : size + 1); + sz = max (sz, 3); + lx = x - (sz / 2); + ly = y - (sz / 2); + cdl_initMarkPos (mk, sz, sz, lx, ly); + + /* Get the pixel region we'll be marking. */ + pix = (uchar *) malloc (sz * sz); + if (cdl_getPixRegion (cdl, lx, ly, sz, sz, pix)) + return (ERR); + + /* Save the image pixels in the display list for erasure later. */ + mk->refpix = (uchar *) malloc (sz * sz); + mk->markpix = (uchar *) malloc (sz * sz); + bcopy (pix, mk->refpix, sz * sz); + cdl_insertMarker (cdl, DLTail[cdl->frame-1], mk); + + /* Edit the pixels with the requested color and save the raster. */ + cdl_doPointMark (color, type, pix, sz); + bcopy (pix, mk->markpix, sz * sz); + + /* Number the point if requested. */ + if (number > 0) { + char lab[64]; + int cx, cy, llen; + + sprintf (lab, "%d", number); + llen = strlen(lab) * (CHARACTER_WIDTH * FONT_SCALE) + strlen(lab); + + /* Position the label so it isn't clipped. + */ + cx = x + (sz / 2) - 1; + cy = y + (sz / 2) - 1; + if ((cx + llen) > cdl->im_nx) cx = x - llen + 1; + if ((cy + llen) > cdl->im_ny) cy = y - llen + 1; + cdl_markText (cdl, cx, cy, lab, 1., 0.0, color); + } + + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, lx, ly, sz, sz, pix)) { + free ((char *)pix); + return (ERR); + } + + free ((char *)pix); + return (OK); +} + + +/* CDL_MARKPOINTLABEL -- Draw a mark on the display at the given point. + * Marks be specified as either a '+', 'x', or '*'. If the number argument + * is positive that value will be drawn next to the mark as a label string. + */ + +#ifdef ANSI_FUNC + +int +cdl_markPointLabel ( + CDLPtr cdl, /* package ptr */ + int x, + int y, /* marker position */ + char *label, /* point label str */ + int size, /* marker size (pixels) */ + int type, /* type to draw */ + int color /* marker color */ +) +#else + +int +cdl_markPointLabel (cdl, x, y, label, size, type, color) +CDLPtr cdl; /* package ptr */ +int x, y; /* marker position */ +char *label; /* point label str */ +int size; /* marker size (pixels) */ +int type; /* type to draw */ +int color; /* marker color */ +#endif +{ + register int lx, ly, sz; + uchar *pix = NULL; + MarkerPtr mk = cdl_initPointLabelMarker(x,y, label, size, type, + color, cdl->font); + + if (cdl_debug) + printf("[cdl_pointLabel] (%dx%d) lab=%s size=%d type=%d color=%d\n", + x, y, label, size, type, color); + + sz = (size % 2 ? size : size + 1); + sz = max (sz, 3); + lx = x - (sz / 2); + ly = y - (sz / 2); + cdl_initMarkPos (mk, sz, sz, lx, ly); + + /* Get the pixel region we'll be marking. */ + pix = (uchar *) malloc (sz * sz); + if (cdl_getPixRegion (cdl, lx, ly, sz, sz, pix)) + return (ERR); + + /* Save the image pixels in the display list for erasure later. */ + mk->refpix = (uchar *) malloc (sz * sz); + mk->markpix = (uchar *) malloc (sz * sz); + bcopy (pix, mk->refpix, sz * sz); + cdl_insertMarker (cdl, DLTail[cdl->frame-1], mk); + + /* Edit the pixels with the requested color and save the raster. */ + cdl_doPointMark (color, type, pix, sz); + bcopy (pix, mk->markpix, sz * sz); + + /* Number the point if requested. */ + if (label) { + int cx, cy, llen; + + llen = cdl_strlen (label, mk->txsize, mk->font); + + /* Position the label so it isn't clipped. */ + cx = x + (sz / 2) - 1; + cy = y + (sz / 2) - 1; + if ((cx + llen) > cdl->im_nx) cx = x - llen + 1; + if ((cy + llen) > cdl->im_ny) cy = y - llen + 1; + cdl_markText (cdl, cx, cy, label, 1., 0.0, color); + } + + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, lx, ly, sz, sz, pix)) { + free ((char *)pix); + return (ERR); + } + + free ((char *)pix); + return (OK); +} + + +/* CDL_MARKLIST -- Given a filename of (x,y) and possibly label strings + * mark all points on the display with a point marker of the given type, + * size and color. + */ + +#ifdef ANSI_FUNC + +int +cdl_markCoordsFile ( + CDLPtr cdl, /* package ptr */ + char *fname, /* file name */ + int type, /* marker type */ + int size, /* marker size */ + int color, /* marker color */ + int label /* label? */ +) +#else + +int +cdl_markCoordsFile (cdl, fname, type, size, color, label) +CDLPtr cdl; /* package ptr */ +char *fname; /* file name */ +int type; /* marker type */ +int size; /* marker size */ +int color; /* marker color */ +int label; /* label? */ +#endif +{ + if (fname == (char *)NULL) + return (ERR); + + /* If a coordinate file was specified read the file and mark those + * coords with points of the specified size, type and color. + */ + if (access (fname, F_OK) == 0) { + FILE *fp; + float rx, ry; + int i, x, y; + + if ((fp = fopen (fname, "r"))) { + /* The coord file is assumed to be simply a file containing + * (x,y) pairs, one per line. Scan the file and mark each + * point. We do no bounds checking to see if the coords + * are correct for the frame. + */ + i = 1; + while (fscanf (fp, "%g %g", &rx, &ry) != EOF) { + x = (int) (rx + 0.5); + y = (int) (ry + 0.5); + if (label) + cdl_markPoint (cdl, x, y, i++, size, type, color); + else + cdl_markPoint (cdl, x, y, 0, size, type, color); + } + + } else { + fprintf (stderr, "cannot open coord file '%s'.\n", fname); + return (ERR); + } + } else { + fprintf (stderr, "'%s': coord file doesn't exist, ignoring.\n", + fname); + return (ERR); + } + return (OK); +} + + +/* CDL_MARKLINE -- Draw a line of given color between the two points + * specified. + */ + +#ifdef ANSI_FUNC + +int +cdl_markLine ( + CDLPtr cdl, /* package ptr */ + int xs, + int ys, /* line start points */ + int xe, + int ye, /* line end points */ + int color /* marker color */ +) +#else + +int +cdl_markLine (cdl, xs, ys, xe, ye, color) +CDLPtr cdl; /* package ptr */ +int xs, ys; /* line start points */ +int xe, ye; /* line end points */ +int color; /* marker color */ +#endif +{ + register int nx, ny, lx, ly; + register int width = cdl->linewidth, style = cdl->linestyle; + uchar *pix = NULL; + MarkerPtr mk = cdl_initLineMarker (xs, ys, xe, ye, color, width, style); + + if (cdl_debug) + printf ("[cdl_markLine] (%d,%d) -> (%d,%d) color=%d\n", + xs, ys, xe, ye, color); + + if (style >= L_HOLLOW) width = HOLLOW_LINE_WIDTH; + nx = ABS(xe-xs) + width + 1; + ny = ABS(ye-ys) + width + 1; + lx = min(xs,xe) - width/2 - 1; + ly = min(ys,ye) - width/2 - 1; + cdl_initMarkPos (mk, nx, ny, lx, ly); + + /* Get the pixel region we'll be marking. */ + pix = (uchar *) malloc (nx * ny); + if (cdl_getPixRegion (cdl, lx, ly, nx, ny, pix)) + return (ERR); + + /* Save the image pixels in the display list for erasure later. */ + mk->refpix = (uchar *) malloc (nx * ny); + mk->markpix = (uchar *) malloc (nx * ny); + bcopy (pix, mk->refpix, nx * ny); + cdl_insertMarker (cdl, DLTail[cdl->frame-1], mk); + + /* Edit the pixels with the requested color and save the raster. */ + cdl_doLineMark (color, width, style, pix, xs, ys, xe, ye); + bcopy (pix, mk->markpix, nx * ny); + + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, lx, ly, nx, ny, pix)) { + free ((char *)pix); + return (ERR); + } + + free ((char *)pix); + return (OK); +} + + +/* CDL_MARKBOX -- Draw a rectangular box given two corner endpoints. The + * box may be optionally filled with the specified color. + */ + +#ifdef ANSI_FUNC + +int +cdl_markBox ( + CDLPtr cdl, /* package ptr */ + int lx, + int ly, /* LL corner points */ + int ux, + int uy, /* UR corner points */ + int fill, /* fill rectangle? */ + int color /* marker color */ +) +#else + +int +cdl_markBox (cdl, lx, ly, ux, uy, fill, color) +CDLPtr cdl; /* package ptr */ +int lx, ly; /* LL corner points */ +int ux, uy; /* UR corner points */ +int fill; /* fill rectangle? */ +int color; /* marker color */ +#endif +{ + register int tmp, nx, ny; + register int width = cdl->linewidth, style = cdl->linestyle; + uchar *pix = NULL; + MarkerPtr mk = cdl_initBoxMarker (lx, ly, ux, uy, fill, color, + width, style); + + if (cdl_debug) + printf ("[cdl_markBox] (%d,%d) -> (%d,%d) fill=%d color=%d\n", + lx, ly, ux, uy, fill, color); + + /* Take care of a corner specified the wrong way. */ + if (lx > ux) { tmp = ux; ux = lx; lx = tmp; } + if (ly > uy) { tmp = uy; uy = ly; ly = tmp; } + nx = ux - lx + width + 1; + ny = uy - ly + width + 1; + lx = lx - width/2 - 1; + ly = ly - width/2 - 1; + cdl_initMarkPos (mk, nx, ny, lx, ly); + + /* Get the pixel region we'll be marking. */ + pix = (uchar *) malloc (nx * ny); + if (cdl_getPixRegion (cdl, lx, ly, nx, ny, pix)) + return (ERR); + + /* Save the image pixels in the display list for erasure later. */ + mk->refpix = (uchar *) malloc (nx * ny); + mk->markpix = (uchar *) malloc (nx * ny); + bcopy (pix, mk->refpix, nx * ny); + cdl_insertMarker (cdl, DLTail[cdl->frame-1], mk); + + /* Edit the pixels with the requested color and save the raster. */ + cdl_doBoxMark (color, width, style, fill, pix, lx, ly, nx, ny); + bcopy (pix, mk->markpix, nx * ny); + + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, lx, ly, nx, ny, pix)) { + free ((char *)pix); + return (ERR); + } + + free ((char *)pix); + return (OK); +} + + +/* CDL_MARKPOLYGON -- Draw a polygon on the display, optionally filling with + * the specified color. + */ + +#ifdef ANSI_FUNC + +int +cdl_markPolygon ( + CDLPtr cdl, /* package ptr */ + int xarray[], + int yarray[], /* vertex points */ + int npts, /* number of corners */ + int fill, /* fill polygon? */ + int color /* marker color */ +) +#else + +int +cdl_markPolygon (cdl, xarray, yarray, npts, fill, color) +CDLPtr cdl; /* package ptr */ +int xarray[], yarray[]; /* vertex points */ +int npts; /* number of corners */ +int fill; /* fill polygon? */ +int color; /* marker color */ +#endif +{ + register int nx, ny, lx, ly; + register int width = cdl->linewidth, style = cdl->linestyle; + int xmin, xmax, ymin, ymax; + uchar *pix; + MarkerPtr mk = cdl_initPolygonMarker (xarray, yarray, npts, + fill, color, width, style); + + /* Find the boundaries of the polygon. */ + cdl_minmax (xarray, npts, &xmin, &xmax); + cdl_minmax (yarray, npts, &ymin, &ymax); + nx = ABS(xmax-xmin) + width + 1; + ny = ABS(ymax-ymin) + width + 1; + lx = min(xmin,xmax) - width/2 - 1; + ly = min(ymin,ymax) - width/2 - 1; + cdl_initMarkPos (mk, nx, ny, lx, ly); + + if (cdl_debug) + printf ("[cdl_markPolygon] npts=%d fill=%d color=%d nx=%d ny=%d\n", + npts, fill, color, nx, ny); + + /* Get the pixel region we'll be marking. */ + pix = (uchar *) malloc (nx * ny); + if (cdl_getPixRegion (cdl, lx, ly, nx, ny, pix)) + return (ERR); + + /* Save the image pixels in the display list for erasure later. */ + mk->refpix = (uchar *) malloc (nx * ny); + mk->markpix = (uchar *) malloc (nx * ny); + bcopy (pix, mk->refpix, nx * ny); + cdl_insertMarker (cdl, DLTail[cdl->frame-1], mk); + + /* Edit the pixels with the requested color and save the raster. */ + cdl_doPolygonMark (color, width, style, fill, xarray, yarray, npts, + pix, lx, ly, nx, ny, True); + bcopy (pix, mk->markpix, nx * ny); + + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, lx, ly, nx, ny, pix)) { + free ((char *)pix); + return (ERR); + } + + free ((char *)pix); + return (OK); +} + + +/* CDL_MARKPOLYLINE -- Draw a polyline on the display, optionally filling with + * the specified color. + */ + +#ifdef ANSI_FUNC + +int +cdl_markPolyline ( + CDLPtr cdl, /* package ptr */ + int *xarray, + int *yarray, /* vertex points */ + int npts, /* number of points */ + int color /* marker color */ +) +#else + +int +cdl_markPolyline (cdl, xarray, yarray, npts, color) +CDLPtr cdl; /* package ptr */ +int *xarray, *yarray; /* vertex points */ +int npts; /* number of points */ +int color; /* marker color */ +#endif +{ + register int nx, ny, lx, ly; + register int width = cdl->linewidth, style = cdl->linestyle; + int xmin, xmax, ymin, ymax; + uchar *pix; + MarkerPtr mk = cdl_initPolylineMarker (xarray, yarray, npts, color, + width, style); + + /* Find the boundaries of the polyline. */ + cdl_minmax (xarray, npts, &xmin, &xmax); + cdl_minmax (yarray, npts, &ymin, &ymax); + nx = ABS(xmax-xmin) + width + 1; + ny = ABS(ymax-ymin) + width + 1; + lx = min(xmin,xmax) - width/2 - 1; + ly = min(ymin,ymax) - width/2 - 1; + cdl_initMarkPos (mk, nx, ny, lx, ly); + + if (cdl_debug) + printf ("[cdl_markPolyline] npts=%d color=%d nx=%d ny=%d\n", + npts, color, nx, ny); + + /* Get the pixel region we'll be marking. */ + pix = (uchar *) malloc (nx * ny); + if (cdl_getPixRegion (cdl, lx, ly, nx, ny, pix)) + return (ERR); + + /* Save the image pixels in the display list for erasure later. */ + mk->refpix = (uchar *) malloc (nx * ny); + mk->markpix = (uchar *) malloc (nx * ny); + bcopy (pix, mk->refpix, nx * ny); + cdl_insertMarker (cdl, DLTail[cdl->frame-1], mk); + + /* Edit the pixels with the requested color and save the raster. */ + cdl_doPolygonMark (color, width, style, False, xarray, yarray, npts, + pix, lx, ly, nx, ny, False); + bcopy (pix, mk->markpix, nx * ny); + + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, lx, ly, nx, ny, pix)) { + free ((char *)pix); + return (ERR); + } + + free ((char *)pix); + return (OK); +} + + +/* CDL_MARKCIRCLE -- Draw of circle on the display, optionally filling with + * the specified color. + */ + +#ifdef ANSI_FUNC + +int +cdl_markCircle ( + CDLPtr cdl, /* package ptr */ + int x, + int y, /* center position */ + int radius, /* radius of circle */ + int fill, /* fill circle? */ + int color /* marker color */ +) +#else + +int +cdl_markCircle (cdl, x, y, radius, fill, color) +CDLPtr cdl; /* package ptr */ +int x, y; /* center position */ +int radius; /* radius of circle */ +int fill; /* fill circle? */ +int color; /* marker color */ +#endif +{ + register int nx, ny, lx, ly; + register int width = cdl->linewidth, style = cdl->linestyle; + uchar *pix; + MarkerPtr mk = cdl_initCircleMarker (x, y, radius, fill, color, + width, style); + + nx = ny = 2 * radius + width + 3; + lx = x - radius - width/2 - 1; + ly = y - radius - width/2 - 1; + cdl_initMarkPos (mk, nx, ny, lx, ly); + + if (cdl_debug) + printf ("[cdl_markCircle] (%d,%d) radius=%d fill=%d color=%d\n", + x, y, radius, fill, color); + + /* Get the pixel region we'll be marking. */ + pix = (uchar *) malloc (nx * ny); + if (cdl_getPixRegion (cdl, lx, ly, nx, ny, pix)) + return (ERR); + + /* Save the image pixels in the display list for erasure later. */ + mk->refpix = (uchar *) malloc (nx * ny); + mk->markpix = (uchar *) malloc (nx * ny); + bcopy (pix, mk->refpix, nx * ny); + cdl_insertMarker (cdl, DLTail[cdl->frame-1], mk); + + /* Edit the pixels with the requested color and save the raster. */ + cdl_doCircleMark (x, y, radius, color, width, style, fill, pix, + lx, ly, nx, ny); + bcopy (pix, mk->markpix, nx * ny); + + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, lx, ly, nx, ny, pix)) { + free ((char *)pix); + return (ERR); + } + + free ((char *)pix); + return (OK); +} + + +/* CDL_MARKCIRCANNULI -- Draw circular annuli on the display. + */ + +#ifdef ANSI_FUNC + +int +cdl_markCircAnnuli ( + CDLPtr cdl, /* package ptr */ + int x, + int y, /* center position */ + int radius, /* radius of 1st annulus*/ + int nannuli, /* no. of annuli */ + int sep, /* annuli sep (pixels) */ + int color /* marker color */ +) +#else + +int +cdl_markCircAnnuli (cdl, x, y, radius, nannuli, sep, color) +CDLPtr cdl; /* package ptr */ +int x, y; /* center position */ +int radius; /* radius of 1st annulus*/ +int nannuli; /* no. of annuli */ +int sep; /* annuli sep (pixels) */ +int color; /* marker color */ +#endif +{ + register int nx, ny, lx, ly; + register int width = cdl->linewidth, style = cdl->linestyle; + uchar *pix; + MarkerPtr mk = cdl_initCircAnnMarker(x, y, radius, nannuli, sep, + color, width, style); + + nx = ny = 2 * (radius + nannuli * sep) + width + 3; + lx = x - (nx / 2) - width/2; + ly = y - (ny / 2) - width/2; + cdl_initMarkPos (mk, nx, ny, lx, ly); + + if (cdl_debug) + printf("[cdl_markAnnuli] (%d,%d) radius=%d N=%d sep=%d color=%d\n", + x, y, radius, nannuli, sep, color); + + /* Get the pixel region we'll be marking. */ + pix = (uchar *) malloc (nx * ny); + if (cdl_getPixRegion (cdl, lx, ly, nx, ny, pix)) + return (ERR); + + /* Save the image pixels in the display list for erasure later. */ + mk->refpix = (uchar *) malloc (nx * ny); + mk->markpix = (uchar *) malloc (nx * ny); + bcopy (pix, mk->refpix, nx * ny); + cdl_insertMarker (cdl, DLTail[cdl->frame-1], mk); + + /* Edit the pixels with the requested color and save the raster. */ + cdl_doCircAnnuliMark (x, y, radius, nannuli, sep, color, width, style, + pix, lx, ly, nx, ny); + bcopy (pix, mk->markpix, nx * ny); + + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, lx, ly, nx, ny, pix)) { + free ((char *)pix); + return (ERR); + } + + free ((char *)pix); + return (OK); +} + + +/* CDL_MARKELLIPSE -- Draw an ellipse with a given center, eccentricity + * and position on the display, optionally filling with the specified color. + */ + +#ifdef ANSI_FUNC + +int +cdl_markEllipse ( + CDLPtr cdl, /* package ptr */ + int x, + int y, /* center position */ + int xrad, + int yrad, /* x and y radii */ + float rotang, /* position angle (deg) */ + int fill, /* fill ellipse? */ + int color /* marker color */ +) +#else + +int +cdl_markEllipse (cdl, x, y, xrad, yrad, rotang, fill, color) +CDLPtr cdl; /* package ptr */ +int x, y; /* center position */ +int xrad, yrad; /* x and y radii */ +float rotang; /* position angle (deg) */ +int fill; /* fill ellipse? */ +int color; /* marker color */ +#endif +{ + register int nx, ny, lx, ly; + register int width = cdl->linewidth, style = cdl->linestyle; + uchar *pix; + MarkerPtr mk = cdl_initEllipseMarker (x, y, xrad, yrad, rotang, + fill, color, width, style); + + nx = 2 * max(xrad,yrad) + width + 3; + ny = 2 * max(xrad,yrad) + width + 3; + lx = x - (nx / 2) - width/2; + ly = y - (ny / 2) - width/2; + cdl_initMarkPos (mk, nx, ny, lx, ly); + + if (cdl_debug) + printf("[cdl_markEllipse] (%d,%d) R=(%d,%d) pa=%g fill=%d col=%d\n", + x, y, xrad, yrad, rotang, fill, color); + + /* Get the pixel region we'll be marking. */ + pix = (uchar *) malloc (nx * ny); + if (cdl_getPixRegion (cdl, lx, ly, nx, ny, pix)) + return (ERR); + + /* Save the image pixels in the display list for erasure later. */ + mk->refpix = (uchar *) malloc (nx * ny); + mk->markpix = (uchar *) malloc (nx * ny); + bcopy (pix, mk->refpix, nx * ny); + cdl_insertMarker (cdl, DLTail[cdl->frame-1], mk); + + /* Edit the pixels with the requested color and save the raster. */ + cdl_doEllipseMark (color, width, style, fill, x, y, xrad, yrad, rotang, + pix, lx, ly, nx, ny); + bcopy (pix, mk->markpix, nx * ny); + + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, lx, ly, nx, ny, pix)) { + free ((char *)pix); + return (ERR); + } + + free ((char *)pix); + return (OK); +} + + +/* CDL_MARKELLIPANNULI -- Draw elliptical annuli on the display. + */ + +#ifdef ANSI_FUNC + +int +cdl_markEllipAnnuli ( + CDLPtr cdl, /* package ptr */ + int x, + int y, /* center position */ + int xrad, + int yrad, /* radius of 1st annulus*/ + float ang, /* rotation angle */ + int nannuli, /* no. of annuli */ + int sep, /* annuli sep (pixels) */ + int color /* marker color */ +) +#else + +int +cdl_markEllipAnnuli (cdl, x, y, xrad, yrad, ang, nannuli, sep, color) +CDLPtr cdl; /* package ptr */ +int x, y; /* center position */ +int xrad, yrad; /* radius of 1st annulus*/ +float ang; /* rotation angle */ +int nannuli; /* no. of annuli */ +int sep; /* annuli sep (pixels) */ +int color; /* marker color */ +#endif +{ + register int nx, ny, lx, ly; + register int width = cdl->linewidth, style = cdl->linestyle; + uchar *pix; + MarkerPtr mk = cdl_initEllAnnMarker (x, y, xrad, yrad, ang, nannuli, + sep, color, width, style); + + nx = 2 * max(xrad + nannuli * sep, yrad + nannuli * sep) + width + 3; + ny = 2 * max(xrad + nannuli * sep, yrad + nannuli * sep) + width + 3; + lx = x - (nx / 2) - width/2; + ly = y - (ny / 2) - width/2; + cdl_initMarkPos (mk, nx, ny, lx, ly); + + if (cdl_debug) + printf("[cdl_markElAnn] (%d,%d) R=(%d,%d) pa=%g N=%d S=%d col=%d\n", + x, y, xrad, yrad, ang, nannuli, sep, color); + + /* Get the pixel region we'll be marking. */ + pix = (uchar *) malloc (nx * ny); + if (cdl_getPixRegion (cdl, lx, ly, nx, ny, pix)) + return (ERR); + + /* Save the image pixels in the display list for erasure later. */ + mk->refpix = (uchar *) malloc (nx * ny); + mk->markpix = (uchar *) malloc (nx * ny); + bcopy (pix, mk->refpix, nx * ny); + cdl_insertMarker (cdl, DLTail[cdl->frame-1], mk); + + /* Edit the pixels with the requested color and save the raster. */ + cdl_doEllipAnnuliMark (x, y, xrad, yrad, ang, nannuli, + sep, color, width, style, pix, lx, ly, nx, ny); + bcopy (pix, mk->markpix, nx * ny); + + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, lx, ly, nx, ny, pix)) { + free ((char *)pix); + return (ERR); + } + + free ((char *)pix); + return (OK); +} + + + +/* CDL_MARKTEXT -- Draw a text string on the display at the given location. + */ + +#ifdef ANSI_FUNC + +int +cdl_markText ( + CDLPtr cdl, /* package ptr */ + int x, + int y, /* marker position */ + char *str, /* text string */ + float size, /* size scale factor */ + float angle, /* text rotation angle */ + int color /* marker color */ +) +#else + +int +cdl_markText (cdl, x, y, str, size, angle, color) +CDLPtr cdl; /* package ptr */ +int x, y; /* marker position */ +char *str; /* text string */ +float size; /* size scale factor */ +float angle; /* text rotation angle */ +int color; /* marker color */ +#endif +{ + register int lx, ly, nx, ny, w = cdl->textwidth; + register int len, font = cdl->font; + uchar *pix = NULL; + float cw, ch; + MarkerPtr mk = cdl_initTextMarker (x, y, str, size, color, font, w); + extern int cdl_getPixRegion(); + extern void cdl_insertMarker(), cdl_doLineInSubRas(); + + if (cdl_debug) + printf ("[cdl_markText] (%d,%d) str='%s' size=%g color=%d ang=%g\n", + x, y, str, size, color, angle); + + len = cdl_strlen (str, size, mk->font); + cw = CHARACTER_WIDTH * (size * FONT_SCALE) + FONT_SPACE; + ch = CHARACTER_HEIGHT * (size * FONT_SCALE); + if (angle == 0.0) { + /* Optimize a bit for horizontal text. */ + lx = x; + ly = y - (2 * size); + nx = cdl_strlen (str, size, mk->font); + ny = FONT_HEIGHT * (size * FONT_SCALE) + (6 * size); + if (strstr(str, "\\fU")) { + ny += ch - (ch * 0.666) / 2; + } + if (strstr(str, "\\fD")) { + ly -= ch - (ch * 0.666) / 2 ; + ny += ch - (ch * 0.666) / 2; + } + } else { + /* Compute the four corners of the rotated and scaled text. Then + * define the raster needed to get all of the text in the box. + */ + int xc[4], yc[4]; + int i, tx, ty, xmin, xmax, ymin, ymax; + double coso, sino; + + coso = cos ((double)(angle * (double)(M_PI/180.0))); + sino = sin ((double)(angle * (double)(M_PI/180.0))); + + xc[0] = -cw / 2; /* LL corner */ + yc[0] = -ch / 2; + xc[1] = -cw / 2; /* UL corner */ + yc[1] = ch + ch / 2; + xc[2] = len + cw / 2; /* UR corner */ + yc[2] = ch + ch / 2; + xc[3] = len + cw / 2; /* LR corner */ + yc[3] = -ch / 2; + + if (strstr(str, "\fU")) + yc[1] = yc[2] = yc[1] + (ch + ch / 2); + if (strstr(str, "\fD")) + yc[0] = yc[3] = yc[1] - (ch + ch / 2); + + /* Rotate the bounding box. */ + for (i=0; i < 4; i++) { + tx = xc[i], ty = yc[i]; + xc[i] = tx * coso - ty * sino + x + 0.5; + yc[i] = tx * sino + ty * coso + y + 0.5; + } + + cdl_minmax (xc, 4, &xmin, &xmax); + cdl_minmax (yc, 4, &ymin, &ymax); + + lx = xmin - cw / 2, ly = ymin - ch / 2; + nx = xmax - xmin + cw / 2; + ny = ymax - ymin + ch / 2; +/*cdl_markBox (cdl, lx, ly, lx+nx, ly+ny, 0, 205);*/ + } + cdl_initMarkPos (mk, nx, ny, lx, ly); + + /* Get the pixel region we'll be marking. */ + pix = (uchar *) malloc (nx * ny); + if (cdl_getPixRegion (cdl, lx, ly, nx, ny, pix)) + return (ERR); + + /* Save the image pixels in the display list for erasure later. */ + mk->refpix = (uchar *) malloc (nx * ny); + mk->markpix = (uchar *) malloc (nx * ny); + bcopy (pix, mk->refpix, nx * ny); + cdl_insertMarker (cdl, DLTail[cdl->frame-1], mk); + + /* Edit the pixels with the requested color and save the raster. */ + cdl_doTextMarker (x, y, str, size, angle, color, w, mk->font, + pix, lx, ly, nx, ny); + bcopy (pix, mk->markpix, nx * ny); + + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, lx, ly, nx, ny, pix)) { + free ((char *)pix); + return (ERR); + } + + free ((char *)pix); + return (OK); +} + + +/* CDL_SETFONT -- Set the default font type. + */ + +#ifdef ANSI_FUNC + +void +cdl_setFont ( + CDLPtr cdl, + int font +) +#else + +void +cdl_setFont (cdl, font) +CDLPtr cdl; +int font; +#endif +{ + if (font == F_ROMAN) cdl->font = F_ROMAN; + else if (font == F_GREEK) cdl->font = F_GREEK; + else if (font == F_TIMES) cdl->font = F_TIMES; + else if (font == F_FUTURA) cdl->font = F_FUTURA; + else if (font == F_BOLD) + cdl_setTextWidth (cdl, cdl->textwidth+1); + else + fprintf (stderr, "Invalid font specification.\n"); +} + + +/* CDL_SETTEXTWIDTH -- Set the default text width. + */ + +#ifdef ANSI_FUNC + +void +cdl_setTextWidth ( + CDLPtr cdl, + int width +) +#else + +void +cdl_setTextWidth (cdl, width) +CDLPtr cdl; +int width; +#endif +{ + cdl->textwidth = (width > 0 ? width : 1); +} + + + +/* CDL_SETLINEWIDTH -- Set the default line width. + */ + +#ifdef ANSI_FUNC + +void +cdl_setLineWidth ( + CDLPtr cdl, + int width +) +#else + +void +cdl_setLineWidth (cdl, width) +CDLPtr cdl; +int width; +#endif +{ + cdl->linewidth = (width > 0 ? width : 1); +} + + +/* CDL_SETLINESTYLE -- Set the default line style. + */ + +#ifdef ANSI_FUNC + +void +cdl_setLineStyle ( + CDLPtr cdl, + int style +) +#else + +void +cdl_setLineStyle (cdl, style) +CDLPtr cdl; +int style; +#endif +{ + cdl->linestyle = (style >= 0 ? style : 0); +} + + +/* CDL_DELETEMARK -- Delete the overlay mark whose center is closest to + * the given position. + */ + +#ifdef ANSI_FUNC + +int +cdl_deleteMark ( + CDLPtr cdl, /* package ptr */ + int x, + int y /* marker position */ +) +#else + +int +cdl_deleteMark (cdl, x, y) +CDLPtr cdl; /* package ptr */ +int x, y; /* marker position */ +#endif +{ + MarkerPtr mk, next, back; + + if (cdl_debug) + printf ("[cdl_deleteMark] (%d,%d)\n", x, y); + + if (DLHead[cdl->frame-1] == (MarkerPtr) NULL) + return (OK); + + /* Get the marker closest to the given point. */ + mk = cdl_findNearest (DLHead[cdl->frame-1], x, y); + + /* Write the region back to the display. */ + if (cdl_writeSubRaster(cdl, mk->lx, mk->ly, mk->nx, mk->ny, mk->refpix)) + return (ERR); + + /* For point markers we may need to also delete an associated label. */ + if (mk->type == MK_POINT && mk->number > 0 && mk->next != NULL) { + next = mk->next; + if (cdl_writeSubRaster(cdl, next->lx, next->ly, + next->nx, next->ny, next->refpix)) + return (ERR); + cdl_removeMarker (cdl, next); + } else if (mk->type == MK_TEXT && mk->back != NULL) { + /* If it's a text marker, see if the previous on was a point + * with a label. + */ + back = mk->back; + if (back->type == MK_POINT && back->number > 0) { + if (cdl_writeSubRaster(cdl, back->lx, back->ly, + back->nx, back->ny, back->refpix)) + return (ERR); + cdl_removeMarker (cdl, back); + } + } + + /* Delete the marker from the display list. */ + cdl_removeMarker (cdl, mk); + + return (OK); +} + + +/* CDL_CLEAROVERLAY -- Erase all marks in the current display list. Work + * from the tail of the list so we handle overlapping marks correctly. + */ + +#ifdef ANSI_FUNC + +int +cdl_clearOverlay ( + CDLPtr cdl /* package ptr */ +) +#else + +int +cdl_clearOverlay (cdl) +CDLPtr cdl; /* package ptr */ +#endif +{ + MarkerPtr mk, back; + + if (cdl_debug) + printf ("[cdl_clearOverlay]\n"); + + /* To clear the overlay we simply walk the display list and delete + * each point. + */ + for (mk = DLTail[cdl->frame-1]; mk != (MarkerPtr) NULL; mk = back) { + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, mk->lx, mk->ly, mk->nx, mk->ny, + mk->refpix)) + return (ERR); + + /* Delete the marker from the display list. */ + back = mk->back; + cdl_removeMarker (cdl, mk); + } + DLHead[cdl->frame-1] = DLTail[cdl->frame-1] = (MarkerPtr) NULL; + + return (OK); +} + + +/* CDL_REDRAWOVERLAY -- Redraw all marks in the current display list. + */ + +#ifdef ANSI_FUNC + +int +cdl_redrawOverlay ( + CDLPtr cdl /* package ptr */ +) +#else + +int +cdl_redrawOverlay (cdl) +CDLPtr cdl; /* package ptr */ +#endif +{ + MarkerPtr mk; + + if (cdl_debug) + printf ("[cdl_redrawOverlay]\n"); + + /* Just walk the list redisplaying the markers. */ + for (mk = DLHead[cdl->frame-1]; mk != (MarkerPtr) NULL; mk = mk->next) + /* Write the region back to the display. */ + if (cdl_writeSubRaster (cdl, mk->lx, mk->ly, mk->nx, mk->ny, + mk->markpix)) + return (ERR); + + return (OK); +} + + +/* CDL_BEGINDLIST -- + */ + +#ifdef ANSI_FUNC + +void +cdl_beginDList ( + int frame /* frame number */ +) +#else + +void +cdl_beginDList (frame) +int frame; /* frame number */ +#endif +{ +/* + if (DLFlag[frame]) + error "Display list already open for frame %d"; +*/ +} + + +/* CDL_ENDDLIST -- + */ + +#ifdef ANSI_FUNC + +void +cdl_endDList ( + int frame, /* frame number */ + int flush /* flush on close */ +) +#else + +void +cdl_endDList (frame, flush) +int frame; /* frame number */ +int flush; /* flush on close */ +#endif +{ +} + + +/* CDL_CLEARDLIST -- + */ + +#ifdef ANSI_FUNC + +void +cdl_clearDList ( + int frame /* frame number */ +) +#else + +void +cdl_clearDList (frame) +int frame; /* frame number */ +#endif +{ +} + + +/* CDL_DRAWDLIST -- + */ + +#ifdef ANSI_FUNC + +void +cdl_drawDList ( + int frame /* frame number */ +) +#else + +void +cdl_drawDList (frame) +int frame; /* frame number */ +#endif +{ +} + + + +/* ------------------- + * PRIVATE PROCEDUURES + * ------------------- */ + + +/* CDL_GETPIXREGION -- Given a corner position and size, return a subraster + * of the image pixels in that region. + */ + +#ifdef ANSI_FUNC + +static int +cdl_getPixRegion ( + CDLPtr cdl, /* package ptr */ + int lx, + int ly, /* corner position */ + int nx, + int ny, /* corner position */ + uchar *ras /* subraster pixels */ +) +#else + +static int +cdl_getPixRegion (cdl, lx, ly, nx, ny, ras) +CDLPtr cdl; /* package ptr */ +int lx, ly; /* corner position */ +int nx, ny; /* corner position */ +uchar *ras; /* subraster pixels */ +#endif +{ + if (ras == NULL) + ras = (uchar *) malloc (nx * ny); + + /* Do a server query to get the pixels. */ + return (cdl_readSubRaster (cdl, lx, ly, nx, ny, &ras)); +} + + +/* CDL_DOPOINTMARK -- Edit a given raster with the requested mark. + */ + +#ifdef ANSI_FUNC + +static void +cdl_doPointMark ( + int color, /* overlay color */ + int type, /* type of mark to draw */ + uchar *pix, /* edit region raster */ + int sz /* mark size */ +) +#else + +static void +cdl_doPointMark (color, type, pix, sz) +int color; /* overlay color */ +int type; /* type of mark to draw */ +uchar *pix; /* edit region raster */ +int sz; /* mark size */ +#endif +{ + register int i, j, k, npts, center, cpix, fill = 0; + int x, y, width, xp[4], yp[4]; + + /* Save the central pixel value, we don't overwrite that. */ + x = y = (sz / 2); + center = ((sz / 2) * sz) + (sz / 2); + cpix = pix[center]; + + /* Check flags */ + if (type & M_POINT) { + cpix = color; + pix[center] = cpix; + } + if (type & M_FILL) + fill++; + + /* Draw the types requested. */ + if (type & M_BOX) + cdl_doBoxMark (color, 1, L_SOLID, fill, pix, 0, 0, sz, sz); + + if (type & M_PLUS || type & M_STAR) { + j = (y * sz); + for (i=0; i < sz; i++) + pix[j+i] = color; + j = ((sz - 1) * sz) + x; + for (i=0; i < sz; i++, j -= sz) + pix[j] = color; + } + + if (type & M_HLINE || type & M_HBLINE) { + npts = (sz - (sz / 3)) / 2; + if (type & M_HBLINE) { + j = ((y - 1) * sz); + width = 3; + } else { + j = (y * sz); + width = 1; + } + for (k=0; k < width; k++, j += sz) { + for (i=0; i < npts; i++) { + pix[j+i] = color; + pix[j+sz-i-1] = color; + } + } + } + + if (type & M_VLINE || type & M_VBLINE) { + npts = (sz - (sz / 3)) / 2; + if (type & M_VBLINE) { + for (k=-1; k < 2; k++) { + j = ((sz - 1) * sz) + x; + for (i=0; i < npts; i++, j -= sz) { + pix[j+k] = color; + pix[(i*sz)+x+k] = color; + } + } + } else { + j = ((sz - 1) * sz) + x; + for (i=0; i < npts; i++, j -= sz) { + pix[j] = color; + pix[(i*sz)+x] = color; + } + } + } + + if (type & M_CROSS || type & M_STAR) { + for (i=0, j=((sz-1)*sz); i < sz; i++, j-=sz) { + pix[(i*sz)+i] = color; /* main diagonal */ + pix[j+i] = color; /* off diagonal */ + } + } + + if (type & M_DIAMOND) { + xp[0] = x - (sz/2); yp[0] = y; + xp[1] = x; yp[1] = y + (sz/2); + xp[2] = x + (sz/2); yp[2] = y; + xp[3] = x; yp[3] = y - (sz/2); + cdl_doPolygonMark (color, 1, L_SOLID, fill, xp, yp, 4, pix, + 0, 0, sz, sz, True); + pix[x] = color; + } + + if (type & M_CIRCLE) + cdl_doCircleMark(x, y, (sz/2)+1, color, 1, L_SOLID, fill, pix, + 0, 0, sz, sz); + + /* Restore the central pixel value, we don't usually overwrite that. + */ + if (!fill && !(type & M_POINT)) + pix[center] = cpix; +} + + +/* CDL_DOLINEMARK -- Edit a given raster with the requested mark. + */ + +#ifdef ANSI_FUNC + +static void +cdl_doLineMark ( + int color, /* overlay color */ + int width, /* line width */ + int style, /* line style */ + uchar *pix, /* edit region raster */ + int xs, + int ys, + int xe, + int ye /* line endpoints */ +) +#else + +static void +cdl_doLineMark (color, width, style, pix, xs, ys, xe, ye) +int color; /* overlay color */ +int width; /* line width */ +int style; /* line style */ +uchar *pix; /* edit region raster */ +int xs, ys, xe, ye; /* line endpoints */ +#endif +{ + register int nx, ny, lx, ly; + + nx = ABS(xe-xs) + width + 1; + ny = ABS(ye-ys) + width + 1; + lx = min(xs,xe) - width/2 - 1; + ly = min(ys,ye) - width/2 - 1; + + /* Handle a line between arbitrary endpoints of any style. */ + if (style == L_SOLID || style >= L_HOLLOW) { + cdl_doLineInSubRas (pix, color, width, style, xs, xe, ys, ye, + lx, ly, nx ,ny); + } else { + int x[2], y[2]; + + switch (style) { + case L_DASHED: CLEAR_DASH_COUNT; break; + case L_DOTTED: CLEAR_DOT_COUNT; break; + case L_DOTDASH: CLEAR_DOTDASH_COUNT; break; + } + + x[0] = xs, x[1] = xe; + y[0] = ys, y[1] = ye; + cdl_doDashedLine (pix, color, width, style, x, y, 2, + lx, ly, nx ,ny); + } +} + + +/* CDL_DOBOXMARK -- Edit a given raster with the requested mark. + */ + +#ifdef ANSI_FUNC + +static void +cdl_doBoxMark ( + int color, /* overlay color */ + int width, /* line width */ + int style, /* line style */ + int fill, /* fill the box? */ + uchar *pix, /* edit region raster */ + int lx, + int ly, /* subraster corner */ + int nx, + int ny /* box size */ +) +#else + +static void +cdl_doBoxMark (color, width, style, fill, pix, lx, ly, nx, ny) +int color; /* overlay color */ +int width; /* line width */ +int style; /* line style */ +int fill; /* fill the box? */ +uchar *pix; /* edit region raster */ +int lx, ly; /* box corner */ +int nx, ny; /* box size */ +#endif +{ + register int i=0, j=0, k=0, np = (nx * ny); + + /* Edit the pixels with the requested color. */ + if (fill) { + /* Fill the entire rectangle with the color. */ + for (i=0; i < np ; i++) + pix[i] = color; + } else { + if (style == L_SOLID) { + /* Change just the borders of the box to requested color. */ + for (k=0; k < width; k++) + for (i=0, j = (ny-k-1) * nx; i < nx; i++, j++) + pix[(k*nx)+i] = pix[j] = color; + for (k=0; k < width; k++) + for (i=0+k, j = (nx-k-1); i < np; i+=nx, j+=nx) + pix[i] = pix[j] = color; + + } else if (style == L_HOLLOW) { + /* Change just the borders of the box to requested style. */ + for (k=0; k < HOLLOW_LINE_WIDTH; k++) + for (i=0, j = (ny-k-1) * nx; i < nx; i++, j++) + pix[(k*nx)+i] = pix[j] = (k == 2 ? 0 : color); + for (k=0; k < HOLLOW_LINE_WIDTH; k++) + for (i=0+k, j = (nx-k-1); i < np; i+=nx, j+=nx) + pix[i] = pix[j] = color; + + /* Redraw the center of the box to create the hollow. */ + for (i=3, j = (ny-3) * nx + 2; i < nx - 2; i++, j++) + pix[2*nx+i] = pix[j] = 0; + for (i=(2*nx) + 2, j = (nx-3); i < np - (2 * nx); i+=nx, j+=nx) + pix[i] = pix[2*nx+j] = 0; + + } else if (style == L_SHADOW) { + /* Change just the borders of the box to requested style. */ + for (k=0; k < SHADOW_LINE_WIDTH; k++) + for (i=0, j = (ny-k-1) * nx; i < nx; i++, j++) + pix[(k*nx)+i] = pix[j] = (k > 1 ? 0 : color); + for (k=0; k < SHADOW_LINE_WIDTH; k++) + for (i=(2*nx)+k, j = (3*nx-k-1); i < np-(2*nx); i+=nx,j+=nx) + pix[i] = pix[j] = (k > 1 ? 0 : color); + + } else { + int x[2], y[2], w = width, s = style; + + dash = 0, dot = 0, dotdash = 0; + +/* bottom */ x[0] = lx+width, y[0] = ly+w/2; + x[1] = lx+nx-width, y[1] = ly+w/2; + cdl_doDashedLine (pix, color, w, s, x, y, 2, lx, ly, nx, ny); + dash = 0, dot = 0, dotdash = 0; + +/* right */ x[0] = lx+nx-w/2-1, y[0] = ly+width; + x[1] = lx+nx-w/2-1, y[1] = ly+ny-width; + cdl_doDashedLine (pix, color, w, s, x, y, 2, lx, ly, nx, ny); + dash = 0, dot = 0, dotdash = 0; + +/* top */ x[0] = lx+nx-width, y[0] = ly+ny-w/2-1; + x[1] = lx+width, y[1] = ly+ny-w/2-1; + cdl_doDashedLine (pix, color, w, s, x, y, 2, lx, ly, nx, ny); + dash = 0, dot = 0, dotdash = 0; + +/* left */ x[0] = lx+w/2, y[0] = ly+ny-width; + x[1] = lx+w/2, y[1] = ly+width; + cdl_doDashedLine (pix, color, w, s, x, y, 2, lx, ly, nx, ny); + dash = 0, dot = 0, dotdash = 0; + } + } +} + + +/* CDL_DOPOLYGONMARK -- Edit a given raster with the requested mark. + */ + +#ifdef ANSI_FUNC + +static void +cdl_doPolygonMark ( + int color, /* overlay color */ + int width, /* line width */ + int style, /* line style */ + int fill, /* fill polygon */ + int *x, + int *y, /* coordinate arrays */ + int npts, /* npts to plot */ + uchar *pix, /* edit region raster */ + int lx, + int ly, /* subraster corner */ + int nx, + int ny, /* subraster size */ + int close /* close the polygon */ +) +#else + +static void +cdl_doPolygonMark (color, width, style, fill, x, y, npts, pix, lx, ly, nx, ny, close) +int color; /* overlay color */ +int width; /* line width */ +int style; /* line style */ +int fill; /* fill polygon */ +int *x, *y; /* coordinate arrays */ +int npts; /* npts to plot */ +uchar *pix; /* edit region raster */ +int lx, ly; /* subraster corner */ +int nx, ny; /* subraster size */ +int close; /* close the polygon */ +#endif +{ + register int i, nseg = (npts - 1); + + if (cdl_debug) + printf ("[cdl_doPolygonMark] npts=%d lx=%d ly=%d nseg=%d\n", + npts, lx, ly, nseg); + + /* For solid lines just draw the segments */ + if (style == L_SOLID || style >= L_HOLLOW) { + + /* Connect all the vertices. */ + if (style == L_HOLLOW) { + for (i=0; i < nseg; i++) + cdl_doLineInSubRas (pix, color, HOLLOW_LINE_WIDTH, L_SOLID, + x[i], x[i+1], y[i], y[i+1], lx, ly, nx, ny); + for (i=0; i < nseg; i++) + cdl_doLineInSubRas (pix, 0, 1, L_SOLID, + x[i], x[i+1], y[i], y[i+1], lx, ly, nx, ny); + } else { + for (i=0; i < nseg; i++) + cdl_doLineInSubRas (pix, color, width, style, x[i], x[i+1], + y[i], y[i+1], lx, ly, nx, ny); + } + + /* Now connect the last point to the first to close the polygon. */ + if (close) { + if (x[0] != x[npts] && y[0] != y[npts]) + if (style == L_HOLLOW) { + cdl_doLineInSubRas (pix, color, HOLLOW_LINE_WIDTH, + L_SOLID, x[0], x[nseg], y[0], y[nseg], + lx, ly, nx, ny); + cdl_doLineInSubRas (pix, 0, 1, L_SOLID, + x[0], x[nseg], y[0], y[nseg], lx, ly, nx, ny); + } else { + cdl_doLineInSubRas (pix, color, width, style, + x[0], x[nseg], y[0], y[nseg], lx, ly, nx, ny); + } + + /* Flood fill the polygon if requested. */ + if (fill) + cdl_fillArea (pix, nx, ny, color); + } + + } else { + switch (style) { + case L_DASHED: CLEAR_DASH_COUNT; break; + case L_DOTTED: CLEAR_DOT_COUNT; break; + case L_DOTDASH: CLEAR_DOTDASH_COUNT; break; + } + + if (close) { + register int i, *xp, *yp; + + xp = (int *) malloc ((npts+1) * sizeof(int)); + yp = (int *) malloc ((npts+1) * sizeof(int)); + for (i=0; i < npts; i++) { + xp[i] = x[i]; + yp[i] = y[i]; + } + xp[i] = x[0]; + yp[i] = y[0]; + cdl_doDashedLine (pix, color, width, style, xp, yp, npts+1, + lx, ly, nx ,ny); + + free ((char *) xp); + free ((char *) yp); + } else + cdl_doDashedLine (pix, color, width, style, x, y, npts, + lx, ly, nx ,ny); + } +} + + +/* CDL_DOCIRCLEMARK -- Edit a given raster with the requested mark. + */ + +#ifdef ANSI_FUNC + +static void +cdl_doCircleMark ( + int x, + int y, /* center point */ + int radius, /* circle radius */ + int color, /* overlay color */ + int width, /* line width */ + int style, /* line style */ + int fill, /* fill the box? */ + uchar *pix, /* edit region raster */ + int lx, + int ly, /* subraster corner */ + int nx, + int ny /* box size */ +) +#else + +static void +cdl_doCircleMark (x, y, radius, color, width, style, fill, pix, lx, ly, nx, ny) +int x, y; /* center point */ +int radius; /* circle radius */ +int color; /* overlay color */ +int width; /* line width */ +int style; /* line style */ +int fill; /* fill the box? */ +uchar *pix; /* edit region raster */ +int lx, ly; /* subraster corner */ +int nx, ny; /* box size */ +#endif +{ + int xp[N_CIRCLE_PTS+1], yp[N_CIRCLE_PTS+1]; + + /* Get the coordinates for drawing the circle. */ + cdl_getCircleCoords (x, y, radius, xp, yp, N_CIRCLE_PTS); + + /* Connect the dots to draw the circle. */ + cdl_doPolygonMark (color, width, style, fill, xp, yp, N_CIRCLE_PTS, + pix, lx, ly, nx, ny, True); +} + + +/* CDL_DOCIRCANNULIMARK -- Edit a given raster with the requested mark. + */ + +#ifdef ANSI_FUNC + +static void +cdl_doCircAnnuliMark ( + int x, + int y, /* center point */ + int radius, /* circle radius */ + int nannuli, /* No. of annuli */ + int sep, /* annulus separation */ + int color, /* overlay color */ + int width, /* line width */ + int style, /* line style */ + uchar *pix, /* edit region raster */ + int lx, + int ly, /* subraster corner */ + int nx, + int ny /* box size */ +) +#else + +static void +cdl_doCircAnnuliMark(x, y, radius, nannuli, sep, color, width, style, pix, lx, ly, nx, ny) +int x, y; /* center point */ +int radius; /* circle radius */ +int nannuli; /* No. of annuli */ +int sep; /* annulus separation */ +int color; /* overlay color */ +int width; /* line width */ +int style; /* line style */ +uchar *pix; /* edit region raster */ +int lx, ly; /* subraster corner */ +int nx, ny; /* box size */ +#endif +{ + register int i; + + /* For each annulus radius draw the circle. */ + for (i=0; i <= nannuli; i++) + cdl_doCircleMark (x, y, radius + (i* sep), color, width, style, + False, pix, lx, ly, nx, ny); +} + + +/* CDL_DOELLIPSEMARK -- Edit a given raster with the requested mark. + */ + +#ifdef ANSI_FUNC + +static void +cdl_doEllipseMark ( + int color, /* overlay color */ + int width, /* line width */ + int style, /* line style */ + int fill, /* fill the box? */ + int xc, + int yc, /* ellipse center */ + int xrad, + int yrad, /* semimajor axes */ + float ang, /* rotation angle */ + uchar *pix, /* edit region raster */ + int lx, + int ly, /* subraster corner */ + int nx, + int ny /* box size */ +) +#else + +static void +cdl_doEllipseMark (color, width, style, fill, xc, yc, xrad, yrad, ang, pix,lx,ly,nx,ny) +int color; /* overlay color */ +int width; /* line width */ +int style; /* line style */ +int fill; /* fill the box? */ +int xc, yc; /* ellipse center */ +int xrad, yrad; /* semimajor axes */ +float ang; /* rotation angle */ +uchar *pix; /* edit region raster */ +int lx, ly; /* subraster corner */ +int nx, ny; /* box size */ +#endif +{ + int xp[N_ELLIPSE_PTS+1], yp[N_ELLIPSE_PTS+1]; + + /* Get the coordinates for drawing the ellipse. */ + cdl_getEllipseCoords (xc, yc, xrad, yrad, ang, xp, yp); + + /* Connect the dots to draw the ellipse. */ + cdl_doPolygonMark (color, width, style, fill, xp, yp, N_ELLIPSE_PTS, + pix, lx, ly, nx, ny, True); +} + + +/* CDL_DOELLIPANNULIMARK -- Edit a given raster with the requested mark. + */ + +#ifdef ANSI_FUNC + +static void +cdl_doEllipAnnuliMark ( + int x, + int y, /* ellipse center */ + int xrad, + int yrad, /* semimajor axes */ + float ang, /* rotation angle */ + int nannuli, /* No. of annuli */ + int sep, /* annulus separation */ + int color, /* overlay color */ + int width, /* line width */ + int style, /* line style */ + uchar *pix, /* edit region raster */ + int lx, + int ly, /* subraster corner */ + int nx, + int ny /* box size */ +) +#else + +static void +cdl_doEllipAnnuliMark(x, y, xrad, yrad, ang, nannuli, sep, color, width, + style, pix, lx, ly, nx, ny) +int x, y; /* ellipse center */ +int xrad, yrad; /* semimajor axes */ +float ang; /* rotation angle */ +int nannuli; /* No. of annuli */ +int sep; /* annulus separation */ +int color; /* overlay color */ +int width; /* line width */ +int style; /* line style */ +uchar *pix; /* edit region raster */ +int lx, ly; /* subraster corner */ +int nx, ny; /* box size */ +#endif +{ + register int i, xr, yr; + + /* For each annulus compute the ellipse and draw it... */ + for (i=0; i <= nannuli; i++) { + xr = xrad + (i * sep); + yr = yrad + (i * sep); + cdl_doEllipseMark (color, width, style, False, x, y, xr, yr, ang, + pix, lx, ly, nx, ny); + } +} + + +/* CDL_DOTEXTMARKER -- Draw a text string to the display. + */ + +#ifdef ANSI_FUNC + +int +cdl_doTextMarker ( + int x, + int y, /* LL text position */ + char *string, /* string to draw */ + float txtsize, /* relative scale size */ + float angle, /* text rotation angle */ + int color, /* overlay color */ + int width, /* line width */ + int txtfont, /* text font */ + uchar *pix, /* edit region raster */ + int lx, + int ly, /* subraster corner */ + int nx, + int ny /* box size */ +) +#else + +int +cdl_doTextMarker (x,y,string,txtsize,angle,color,width,txtfont,pix,lx,ly,nx,ny) +int x, y; /* LL text position */ +char *string; /* string to draw */ +float txtsize; /* relative scale size */ +float angle; /* text rotation angle */ +int color; /* overlay color */ +int width; /* line width */ +int txtfont; /* text font */ +uchar *pix; /* edit region raster */ +int lx, ly; /* subraster corner */ +int nx, ny; /* box size */ +#endif +{ + char chr, *sp = string; + int mx, my, stroke, tab1, tab2, i, j, pen, len; + int x1, x2, y1, y2; + int oldfont, font, offset = 0; + register int w, cw, ch, cx, cy, ip; + float px, py, size = txtsize; + double coso, sino; + int bitupk(); + + font = oldfont = txtfont; + coso = cos ((double) (-angle * (double)(M_PI / 180.0))); + sino = sin ((double) (-angle * (double)(M_PI / 180.0))); + + /* Loop over each character in the string. */ + len = strlen (string); + x1 = cx = x; + y1 = cy = y; + + cw = CHARACTER_WIDTH * (size * FONT_SCALE) + FONT_SPACE; + ch = CHARACTER_HEIGHT * (size * FONT_SCALE); + for (j = 0; j < len && *sp; j++, sp++) { + +escape: + /* Check for an inline font escape. */ + if (*sp == '\\' && *(sp+1) == 'f') { + sp++; sp++; + if (*sp != 'P') + oldfont = font; + + switch (*sp) { + case 'B': + width = width + 1; + break; + case 'R': + font = F_ROMAN; + break; + case 'F': + font = F_FUTURA; + break; + case 'T': + font = F_TIMES; + break; + case 'G': + font = F_GREEK; + break; + case 'P': + if (width > 1) + width = width - 1; + font = oldfont; + break; + + /* Check for a super/subscript escape. */ + case 'U': + offset += ch - (ch * 0.666) / 2; + break; + case 'D': + offset -= ch - (ch * 0.666) / 2; + break; + } + sp++; + if (*sp == '\\') + goto escape; + } + + /* Adjust the size if we're doing sub/superscript. */ + if (offset != 0) + size = txtsize * 0.666; + else + size = txtsize; + + if (*sp < CHARACTER_START || *sp > CHARACTER_END) + chr = i = '?' - CHARACTER_START; + else + chr = i = *sp - CHARACTER_START; + + switch (font) { + case F_ROMAN: + tab1 = chridx[i] - 1; + tab2 = chridx[i+1] - 1; + break; + case F_GREEK: + tab1 = gchidx[i] - 1; + tab2 = gchidx[i+1] - 1; + break; + case F_TIMES: + tab1 = timidx[i] - 1; + tab2 = timidx[i+1] - 1; + break; + case F_FUTURA: + tab1 = futidx[i] - 1; + tab2 = futidx[i+1] - 1; + break; + } + + for (i=tab1; i <= tab2; i++) { + switch (font) { + case F_ROMAN: + stroke = chrtab[i]; break; + case F_GREEK: + stroke = gchtab[i]; break; + case F_TIMES: + stroke = timtab[i]; break; + case F_FUTURA: + stroke = futtab[i]; break; + } + px = (float) bitupk (stroke, COORD_X_START, COORD_X_LEN); + py = (float) bitupk (stroke, COORD_Y_START, COORD_Y_LEN); + pen = bitupk (stroke, COORD_PEN_START, COORD_PEN_LEN); + + /* Scale size of character. */ + px = px * (size * FONT_SCALE); + py = py * (size * FONT_SCALE) + offset; + + /* Shift and rotate. + */ + mx = cx + px * coso + py * sino; + my = cy - px * sino + py * coso; + + if (pen == 0) { + /* Move start point. */ + x1 = mx; + y1 = my; + } else { + /* Draw to this point and update. */ + x2 = mx; + y2 = my; + cdl_doLineInSubRas (pix, color, width, L_SOLID, + x1, x2, y1, y2, lx, ly, nx, ny); + x1 = x2; + y1 = y2; + } + } + + /* Update the character position. */ + ip = (int) chr; + switch (font) { + case F_ROMAN: + cx += cw * coso; + cy -= cw * sino; + + /* Now correct a bit to kludge a nice spacing. */ + if (index("il1:;.,!|'`", *sp)) { + cx -= FONT_SPACE * coso; + cy += FONT_SPACE * sino; + } else if (*sp == 'r') { + cx -= (FONT_SPACE - 2) * coso; + cy += (FONT_SPACE - 2) * sino; + } + break; + case F_GREEK: + w = (gchwid[ip] / 2) * (size * FONT_SCALE) + FONT_SPACE + 2; + cx += w * coso; + cy -= w * sino; + break; + case F_TIMES: + w = (timwid[ip] - 12) * (size * FONT_SCALE) + FONT_SPACE + 2; + cx += w * coso; + cy -= w * sino; + break; + case F_FUTURA: + w = (futwid[ip] / 2) * (size * FONT_SCALE) + FONT_SPACE + 2; + cx += w * coso; + cy -= w * sino; + break; + } + } + + return (OK); +} + + + + +/* ------------------------ + * Display List Procedures + * ------------------------*/ + + + +/* CDL_FREEDISPLAYLIST -- Free up the named display list. + */ + +#ifdef ANSI_FUNC + +int +cdl_freeDisplayList ( + CDLPtr cdl, /* package ptr */ + MarkerPtr head +) +#else + +int +cdl_freeDisplayList (cdl, head) +CDLPtr cdl; /* package ptr */ +MarkerPtr head; +#endif +{ + MarkerPtr mk; + + if (cdl_debug) + printf ("[cdl_freeDisplayList]\n"); + + /* Just walk the list freeing the markers. */ + for (mk = head; mk != (MarkerPtr) NULL; mk = mk->next) + cdl_removeMarker (cdl, mk); + + return (OK); +} + + +/* CDL_INSERTMARKER -- Insert a marker in the display list after the given + * entry. The display list is maintained as a doubly linked list of markers. + */ + +#ifdef ANSI_FUNC + +static void +cdl_insertMarker ( + CDLPtr cdl, /* package ptr */ + MarkerPtr back, /* insert point */ + MarkerPtr new /* marker to insert */ +) +#else + +static void +cdl_insertMarker (cdl, back, new) +CDLPtr cdl; /* package ptr */ +MarkerPtr back; /* insert point */ +MarkerPtr new; /* marker to insert */ +#endif +{ + MarkerPtr tmp; + + /* If the back pointer is null it means we're creating the head. */ + if (back == (MarkerPtr) NULL) { + DLHead[cdl->frame-1] = DLTail[cdl->frame-1] = new; + new->back = new->next = (MarkerPtr) NULL; + + } else { + /* Otherwise reset the pointers to insert the marker. */ + tmp = back->next; + back->next = new; + new->back = back; + + /* If the beck marker pointed at something, take care of that. */ + if (tmp) { + new->next = tmp; + tmp->back = new; + } else { + new->next = (MarkerPtr) NULL; + DLTail[cdl->frame-1] = new; + } + } +} + + +/* CDL_REMOVEMARKER -- Remove a marker from the display list. + */ + +#ifdef ANSI_FUNC + +static void +cdl_removeMarker ( + CDLPtr cdl, /* package ptr */ + MarkerPtr mk /* marker to delete */ +) +#else + +static void +cdl_removeMarker (cdl, mk) +CDLPtr cdl; /* package ptr */ +MarkerPtr mk; /* marker to delete */ +#endif +{ + if (mk->back) /* handle the back ptr */ + mk->back->next = mk->next; + else + DLHead[cdl->frame-1] = mk->next; + if (mk->next) /* handle the next ptr */ + mk->next->back = mk->back; + else + DLTail[cdl->frame-1] = mk->back; + + /* Now free up the marker and internal pointers. */ + if (mk->str) free ((uchar *) mk->str); + if (mk->refpix) free ((uchar *) mk->refpix); + if (mk->markpix) free ((uchar *) mk->markpix); + if (mk->xp) free ((uchar *) mk->xp); + if (mk->yp) free ((uchar *) mk->yp); + free ((MarkerPtr) mk); +} + + +/* CDL_FINDNEAREST -- Find the marker in the display list that is closest + * to the indicated point. For markers with a defined center we check the + * distance to the central point. For polylines and polygons we check for + * a vertex ir knot point that is closest. The marker is then returned. + */ + +#ifdef ANSI_FUNC + +static MarkerPtr +cdl_findNearest ( + MarkerPtr head, /* display list head */ + int x, + int y /* pixel coords */ +) +#else + +static MarkerPtr +cdl_findNearest (head, x, y) +MarkerPtr head; /* display list head */ +int x, y; /* pixel coords */ +#endif +{ + MarkerPtr mk, nearest; + register float dmin = 10.0e9, mk_dist, dist = 10.0e9, A, C, cx, cy; + register int i; + + if (head == (MarkerPtr) NULL) + return ((MarkerPtr) NULL); + + nearest = head; + for (mk = head; mk ; mk = mk->next) { + switch (mk->type) { + case MK_POLYLINE: + case MK_POLYGON: + /* Find the nearest point in the poly. */ + for (i=0; i < mk->npts; i++) { + mk_dist = sqrt ((double)(ABS(x - mk->x) * ABS(x - mk->x) + + ABS(y - mk->y) * ABS(y - mk->y)) ); + if (mk_dist < dmin) + dmin = mk_dist; + } + mk_dist = dmin; + break; + + case MK_BOX: + /* Select the box center closest to the point. */ + cx = (mk->xp[1] + mk->xp[0]) / 2; + cy = (mk->yp[1] + mk->yp[0]) / 2; + mk_dist = sqrt ((double)(ABS(x - cx) * ABS(x - cx) + + ABS(y - cy) * ABS(y - cy)) ); + break; + + case MK_LINE: + A = (float) ((mk->yp[1] - mk->yp[0]) / (mk->xp[1] - mk->xp[0])); + C = mk->yp[0] - A * x; + mk_dist = ABS( (A * x - y + C) / sqrt (A * A + 1)); + break; + + case MK_POINT: + case MK_CIRCLE: + case MK_CIRCANN: + case MK_ELLIPSE: + case MK_ELLIPANN: + case MK_TEXT: + /* Get the distance from the point to the center. */ + mk_dist = sqrt ((double)(ABS(x - mk->x) * ABS(x - mk->x) + + ABS(y - mk->y) * ABS(y - mk->y)) ); + } + if (mk_dist < dist) { + dist = mk_dist; + nearest = mk; + } + + if (cdl_debug) + printf ("Nearest: Marker type=%2d dist=%g mk_dist=%g N=%d\n", + mk->type, dist, mk_dist, nearest->type); + } + return (nearest); +} + + +/* CDL_PRINTDISPLAYLIST -- Print the display list to a file. + */ + +#ifdef ANSI_FUNC + +static void +cdl_printDisplayList ( + FILE *fd, /* file descriptor */ + MarkerPtr head /* display list head */ +) +#else + +static void +cdl_printDisplayList (fd, head) +FILE *fd; /* file descriptor */ +MarkerPtr head; /* display list head */ +#endif +{ + MarkerPtr mk; + + for (mk = head; mk ; mk = mk->next) { + switch (mk->type) { + case MK_POINT: printf ("point\t\t"); break; + case MK_LINE: printf ("line\t\t"); break; + case MK_BOX: printf ("box\t\t"); break; + case MK_POLYLINE: printf ("polyline\t\t"); break; + case MK_POLYGON: printf ("polygon\t\t"); break; + case MK_CIRCLE: printf ("circle\t\t"); break; + case MK_CIRCANN: printf ("circann\t\t"); break; + case MK_ELLIPSE: printf ("ellipse\t\t"); break; + case MK_ELLIPANN: printf ("ellipann\t\t"); break; + case MK_TEXT: printf ("text\t\t"); break; + } + printf ("mk=%d back=%10d next=%10d\n", + (int)mk, (int)mk->back, (int)mk->next); + } +} + + +/* CDL_INITPOINTMARKER -- Allocate and initialize the space for a point marker. + */ + +#ifdef ANSI_FUNC + +static MarkerPtr +cdl_initPointMarker ( + int x, + int y, /* marker position */ + int number, /* if > 0, label value */ + int size, /* marker size (pixels) */ + int type, /* type to draw */ + int color /* marker color */ +) +#else + +static MarkerPtr +cdl_initPointMarker (x, y, number, size, type, color) +int x, y; /* marker position */ +int number; /* if > 0, label value */ +int size; /* marker size (pixels) */ +int type; /* type to draw */ +int color; /* marker color */ +#endif +{ + MarkerPtr mk = (MarkerPtr) calloc (1, sizeof(struct Marker)); + + mk->type = MK_POINT; + mk->x = x; + mk->y = y; + mk->number = number; + mk->size = size; + mk->pt_type = type; + mk->color = color; + return mk; +} + + + +/* CDL_INITPOINTLABELMARKER -- Allocate and initialize the space for a point + * with a text label marker. + */ + +#ifdef ANSI_FUNC + +static MarkerPtr +cdl_initPointLabelMarker ( + int x, + int y, /* marker position */ + char *label, /* point label str */ + int size, /* marker size (pixels) */ + int type, /* type to draw */ + int color, /* marker color */ + int font /* label font */ +) +#else + +static MarkerPtr +cdl_initPointLabelMarker (x, y, label, size, type, color, font) +int x, y; /* marker position */ +char *label; /* point label str */ +int size; /* marker size (pixels) */ +int type; /* type to draw */ +int color; /* marker color */ +int font; /* label font */ +#endif +{ + MarkerPtr mk = (MarkerPtr) calloc (1, sizeof(struct Marker)); + + mk->type = MK_POINT; + mk->x = x; + mk->y = y; + mk->size = size; + mk->pt_type = type; + mk->color = color; + mk->font = font; + mk->str = (char *) malloc (strlen(label) + 1); + strcpy (mk->str, label); + return mk; +} + + +/* CDL_INITLINEMARKER -- Allocate and initialize the space for a line marker. + */ + +#ifdef ANSI_FUNC + +static MarkerPtr +cdl_initLineMarker ( + int x1, + int y1, /* line start points */ + int x2, + int y2, /* line end points */ + int color, /* marker color */ + int width, /* line width */ + int style /* line style */ +) +#else + +static MarkerPtr +cdl_initLineMarker (x1, y1, x2, y2, color, width, style) +int x1, y1; /* line start points */ +int x2, y2; /* line end points */ +int color; /* marker color */ +int width; /* line width */ +int style; /* line width */ +#endif +{ + MarkerPtr mk = (MarkerPtr) calloc (1, sizeof(struct Marker)); + + mk->type = MK_LINE; + mk->x = x1; + mk->y = y1; + mk->xp = (int *) malloc (2 * sizeof(int)); + mk->xp[0] = x1; + mk->xp[1] = x2; + mk->yp = (int *) malloc (2 * sizeof(int)); + mk->yp[0] = y1; + mk->yp[1] = y2; + mk->color = color; + mk->linewidth = width; + mk->linestyle = style; + return mk; +} + + +/* CDL_INITBOXMARKER -- Allocate and initialize the space for a box marker. + */ + +#ifdef ANSI_FUNC + +static MarkerPtr +cdl_initBoxMarker ( + int lx, + int ly, /* LL corner points */ + int ux, + int uy, /* UR corner points */ + int fill, /* fill rectangle? */ + int color, /* marker color */ + int width, /* line width */ + int style /* line style */ +) +#else + +static MarkerPtr +cdl_initBoxMarker (lx, ly, ux, uy, fill, color, width, style) +int lx, ly; /* LL corner points */ +int ux, uy; /* UR corner points */ +int fill; /* fill rectangle? */ +int color; /* marker color */ +int width; /* line width */ +int style; /* line style */ +#endif +{ + MarkerPtr mk = (MarkerPtr) calloc (1, sizeof(struct Marker)); + + mk->type = MK_BOX; + mk->x = lx; + mk->y = ly; + mk->xp = (int *) malloc (2 * sizeof(int)); + mk->xp[0] = lx; + mk->xp[1] = ux; + mk->yp = (int *) malloc (2 * sizeof(int)); + mk->yp[0] = ly; + mk->yp[1] = uy; + mk->fill = fill; + mk->color = color; + mk->linewidth = width; + mk->linestyle = style; + return mk; +} + + +/* CDL_INITPOLYLINEMARKER -- Allocate and initialize the space for a + * polyine marker. + */ + +#ifdef ANSI_FUNC + +static MarkerPtr +cdl_initPolylineMarker ( + int *x, + int *y, /* vertex points */ + int npts, /* number of points */ + int color, /* marker color */ + int width, /* line width */ + int style /* line style */ +) +#else + +static MarkerPtr +cdl_initPolylineMarker (x, y, npts, color, width, style) +int *x, *y; /* vertex points */ +int npts; /* number of points */ +int color; /* marker color */ +int width; /* line width */ +int style; /* line style */ +#endif +{ + MarkerPtr mk = (MarkerPtr) calloc (1, sizeof(struct Marker)); + + mk->type = MK_POLYLINE; + mk->xp = (int *) malloc (npts * sizeof(int)); + mk->yp = (int *) malloc (npts * sizeof(int)); + bcopy (x, mk->xp, npts * sizeof(int)); + bcopy (y, mk->yp, npts * sizeof(int)); + mk->x = mk->xp[0]; + mk->y = mk->yp[0]; + mk->npts = npts; + mk->color = color; + mk->linewidth = width; + mk->linestyle = style; + return mk; +} + + +/* CDL_INITPOLYGONMARKER -- Allocate and initialize the space for a + * polygon marker. + */ + +#ifdef ANSI_FUNC + +static MarkerPtr +cdl_initPolygonMarker ( + int *x, + int *y, /* vertex points */ + int npts, /* number of corners */ + int fill, /* fill polygon? */ + int color, /* marker color */ + int width, /* line width */ + int style /* line style */ +) +#else + +static MarkerPtr +cdl_initPolygonMarker (x, y, npts, fill, color, width, style) +int *x, *y; /* vertex points */ +int npts; /* number of corners */ +int fill; /* fill polygon? */ +int color; /* marker color */ +int width; /* line width */ +int style; /* line style */ +#endif +{ + MarkerPtr mk = (MarkerPtr) calloc (1, sizeof(struct Marker)); + + mk->type = MK_POLYGON; + mk->xp = (int *) malloc (npts * sizeof(int)); + mk->yp = (int *) malloc (npts * sizeof(int)); + bcopy (x, mk->xp, npts * sizeof(int)); + bcopy (y, mk->yp, npts * sizeof(int)); + mk->x = mk->xp[0]; + mk->y = mk->yp[0]; + mk->npts = npts; + mk->fill = fill; + mk->color = color; + mk->linewidth = width; + mk->linestyle = style; + return mk; +} + + +/* CDL_INITCIRCLEMARKER -- Allocate and initialize the space for a + * circle marker. + */ + +#ifdef ANSI_FUNC + +static MarkerPtr +cdl_initCircleMarker ( + int x, + int y, /* center position */ + int radius, /* radius of circle */ + int fill, /* fill circle? */ + int color, /* marker color */ + int width, /* line width */ + int style /* line style */ +) +#else + +static MarkerPtr +cdl_initCircleMarker (x, y, radius, fill, color, width, style) +int x, y; /* center position */ +int radius; /* radius of circle */ +int fill; /* fill circle? */ +int color; /* marker color */ +int width; /* line width */ +int style; /* line style */ +#endif +{ + MarkerPtr mk = (MarkerPtr) calloc (1, sizeof(struct Marker)); + + mk->type = MK_CIRCLE; + mk->x = x; + mk->y = y; + mk->radius = radius; + mk->fill = fill; + mk->color = color; + mk->linewidth = width; + mk->linestyle = style; + return mk; +} + + +/* CDL_INITCIRCANNMARKER -- Allocate and initialize the space for a + * circular annuli marker. + */ + +#ifdef ANSI_FUNC + +static MarkerPtr +cdl_initCircAnnMarker ( + int x, + int y, /* center position */ + int radius, /* radius of 1st annulus*/ + int nannuli, /* no. of annuli */ + int sep, /* annuli sep (pixels) */ + int color, /* marker color */ + int width, /* line width */ + int style /* line style */ +) +#else + +static MarkerPtr +cdl_initCircAnnMarker (x, y, radius, nannuli, sep, color, width, style) +int x, y; /* center position */ +int radius; /* radius of 1st annulus*/ +int nannuli; /* no. of annuli */ +int sep; /* annuli sep (pixels) */ +int color; /* marker color */ +int width; /* line width */ +int style; /* line style */ +#endif +{ + MarkerPtr mk = (MarkerPtr) calloc (1, sizeof(struct Marker)); + + mk->type = MK_CIRCANN; + mk->x = x; + mk->y = y; + mk->radius = radius; + mk->nannuli = nannuli; + mk->sep = sep; + mk->color = color; + mk->linewidth = width; + mk->linestyle = style; + return mk; +} + + +/* CDL_INITELLIPSEMARKER -- Allocate and initialize the space for a + * ellipse marker. + */ + +#ifdef ANSI_FUNC + +static MarkerPtr +cdl_initEllipseMarker ( + int x, + int y, /* center position */ + int xrad, + int yrad, /* x and y radii */ + float ang, /* position angle (deg) */ + int fill, /* fill ellipse? */ + int color, /* marker color */ + int width, /* line width */ + int style /* line style */ +) +#else + +static MarkerPtr +cdl_initEllipseMarker (x, y, xrad, yrad, ang, fill, color, width, style) +int x, y; /* center position */ +int xrad, yrad; /* x and y radii */ +float ang; /* position angle (deg) */ +int fill; /* fill ellipse? */ +int color; /* marker color */ +int width; /* line width */ +int style; /* line style */ +#endif +{ + MarkerPtr mk = (MarkerPtr) calloc (1, sizeof(struct Marker)); + + mk->type = MK_ELLIPSE; + mk->x = x; + mk->y = y; + mk->xrad = xrad; + mk->yrad = yrad; + mk->ang = ang; + mk->fill = fill; + mk->color = color; + mk->linewidth = width; + mk->linestyle = style; + return mk; +} + + +/* CDL_INITELLANNMARKER -- Allocate and initialize the space for a + * elliptical annuli marker. + */ + +#ifdef ANSI_FUNC + +static MarkerPtr +cdl_initEllAnnMarker ( + int x, + int y, /* center position */ + int xrad, + int yrad, /* radius of 1st annulus*/ + float ang, /* rotation angle */ + int nannuli, /* no. of annuli */ + int sep, /* annuli sep (pixels) */ + int color, /* marker color */ + int width, /* line width */ + int style /* line style */ +) +#else + +static MarkerPtr +cdl_initEllAnnMarker (x, y, xrad, yrad, ang, nannuli, sep, color, width, style) +int x, y; /* center position */ +int xrad, yrad; /* radius of 1st annulus*/ +float ang; /* rotation angle */ +int nannuli; /* no. of annuli */ +int sep; /* annuli sep (pixels) */ +int color; /* marker color */ +int width; /* line width */ +int style; /* line style */ +#endif +{ + MarkerPtr mk = (MarkerPtr) calloc (1, sizeof(struct Marker)); + + mk->type = MK_ELLIPANN; + mk->x = x; + mk->y = y; + mk->xrad = xrad; + mk->yrad = yrad; + mk->ang = ang; + mk->nannuli = nannuli; + mk->sep = sep; + mk->color = color; + mk->linewidth = width; + mk->linestyle = style; + return mk; +} + + +/* CDL_INITTEXTMARKER -- Allocate and initialize the space for a text marker. + */ + +#ifdef ANSI_FUNC + +static MarkerPtr +cdl_initTextMarker ( + int x, + int y, /* marker position */ + char *string, /* string to draw */ + float size, /* marker size (pixels) */ + int color, /* marker color */ + int font, /* text font */ + int width /* line width */ +) +#else + +static MarkerPtr +cdl_initTextMarker (x, y, string, size, color, font, width) +int x, y; /* marker position */ +char *string; /* string to draw */ +float size; /* marker size (pixels) */ +int color; /* marker color */ +int font; /* text font */ +int width; /* line width */ +#endif +{ + MarkerPtr mk = (MarkerPtr) calloc (1, sizeof(struct Marker)); + + mk->type = MK_TEXT; + mk->x = x; + mk->y = y; + mk->txsize = size; + mk->color = color; + mk->font = font; + mk->textwidth = width; + mk->str = (char *) malloc (strlen(string) + 1); + strcpy (mk->str, string); + return mk; +} + + + +#ifdef ANSI_FUNC + +static void +cdl_initMarkPos (MarkerPtr mk, int nx, int ny, int lx, int ly) +#else + +static void +cdl_initMarkPos (mk, nx, ny, lx, ly) +MarkerPtr mk; +int nx, ny; +int lx, ly; +#endif +{ + mk->nx = nx; + mk->ny = ny; + mk->lx = lx; + mk->ly = ly; +} + + + +/* ------------------------ + * Misc. Utility Procedures + * ------------------------*/ + +/* CDL_DOLINEINSUBRAS -- Draw a line between two arbitrary endpoints in a + * subraster. Line widths and styles are passed through to specialized + # routines. + */ + +#ifdef ANSI_FUNC + +static void +cdl_doLineInSubRas ( + uchar *pix, /* edit region raster */ + int color, /* overlay color */ + int width, /* line width */ + int style, /* line style */ + int x1, + int x2, + int y1, + int y2, /* line endpoints */ + int lx, + int ly, /* subraster LL corner */ + int nx, + int ny /* subraster size */ +) +#else + +static void +cdl_doLineInSubRas (pix, color, width, style, x1, x2, y1, y2, lx, ly, nx, ny) +uchar *pix; /* edit region raster */ +int color; /* overlay color */ +int width; /* line width */ +int style; /* line style */ +int x1, y1, x2, y2; /* line endpoints */ +int lx, ly; /* subraster LL corner */ +int nx, ny; /* subraster size */ +#endif +{ + if (style == L_SOLID || style >= L_HOLLOW) { + if (width == 1 && style == L_SOLID) + cdl_drawVector (pix, color, x1, x2, y1, y2, lx, ly, nx, ny); + else { + cdl_drawThickVector (pix, color, width, style, x1, x2, y1, y2, + lx, ly, nx, ny); + } + } else { + ; + } +} + + +/* CDL_DOLINEINSUBRAS -- Draw a line between two arbitrary endpoints in a + * subraster. Line widths and styles are passed through to specialized + # routines. + */ + +#ifdef ANSI_FUNC + +static void +cdl_doDashedLine ( + uchar *pix, /* edit region raster */ + int color, /* overlay color */ + int width, /* line width */ + int style, /* line style */ + int *x, + int *y, /* line vertices */ + int npts, /* number of vertices */ + int lx, + int ly, /* subraster LL corner */ + int nx, + int ny /* subraster size */ +) +#else + +static void +cdl_doDashedLine (pix, color, width, style, x, y, npts, lx, ly, nx, ny) +uchar *pix; /* edit region raster */ +int color; /* overlay color */ +int width; /* line width */ +int style; /* line style */ +int *x, *y; /* line vertices */ +int npts; /* number of vertices */ +int lx, ly; /* subraster LL corner */ +int nx, ny; /* subraster size */ +#endif +{ + register int i, nseg = (npts - 1); + + if (cdl_debug) + printf ("[cdl_doDashedLine] npts=%d lx=%d ly=%d nseg=%d style=%d\n", + npts, lx, ly, nseg, style); + + /* Connect all the vertices. */ + if (width == 1) { + for (i=0; i < nseg; i++) + cdl_drawDashVec (pix, color, style, x[i], x[i+1], + y[i], y[i+1], lx, ly, nx, ny); + } else { + for (i=0; i < nseg; i++) { + cdl_drawThickDashVec (pix, color, width, style, x[i], x[i+1], + y[i], y[i+1], lx, ly, nx, ny); + + /* Restore the dashed line counters so we get a smooth line */ + dash = p_dash, dot = p_dot, dotdash = p_dotdash; + } + } +} + + +/* CDL_DRAWTHICKVECTOR -- Draw a line between two arbitrary endpoints in a + * subraster. We draw multiple vectors to achieve the line thickness. + */ + +#ifdef ANSI_FUNC + +static void +cdl_drawThickVector ( + uchar *pix, /* edit region raster */ + int color, /* overlay color */ + int width, /* line width */ + int style, /* line style */ + int x1, + int x2, + int y1, + int y2, /* line endpoints */ + int lx, + int ly, /* subraster LL corner */ + int nx, + int ny /* subraster size */ +) +#else + +static void +cdl_drawThickVector (pix, color, width, style, x1, x2, y1, y2, lx, ly, nx, ny) +uchar *pix; /* edit region raster */ +int color; /* overlay color */ +int width; /* line width */ +int style; /* line style */ +int x1, y1, x2, y2; /* line endpoints */ +int lx, ly; /* subraster LL corner */ +int nx, ny; /* subraster size */ +#endif +{ + register int i, new_x = x2, new_y = y2, dx = 0, dy = 0; + register int xshift = 0, yshift = 0, w = width, col = color; + register int xx1, xx2, yy1, yy2, n = 0, sign = 1; + + if (abs (new_x - x1) > abs (new_y - y1)) + dx = 0, dy = 1; + else + dx = 1, dy = 0; + + if (style == L_HOLLOW) + w = HOLLOW_LINE_WIDTH; + else if (style == L_SHADOW) + w = SHADOW_LINE_WIDTH; + + for (i=1; i <= w; i++) { + xx1 = x1 + xshift; + yy1 = y1 + yshift; + xx2 = new_x + xshift; + yy2 = new_y + yshift; + + if (style == L_HOLLOW && i == 1) + col = 0; + else if ((style == L_SHADOW && i % 2 && dx) || + (style == L_SHADOW && !(i % 2) && dy)) + col = 0; + else + col = color; + + cdl_drawVector (pix, col, xx1, xx2, yy1, yy2, lx, ly, nx, ny); + + n = (i + 1 + 0.5) / 2; + sign = ((i % 2 == 0) ? 1 : -1); + if (x1 == x2) + xshift = sign * dx * n; + else if (y1 == y2) + yshift = sign * dy * n; + else { + xshift = sign * dx * n; + yshift = sign * dy * n; + } + } +} + + +/* CDL_DRAWVECTOR -- Draw a line between two arbitrary endpoints in a + * subraster. Endpoints are given in image coordinates along with the + * subraster boundary, we translate to subraster coords before marking the + * pixel. This allows us to get a subraster for a larger object such as + * polygon and use the line primitive to draw each vertex before writing + * back a single subraster rather than use the less efficient sequence of + * server I/O calls for each line segment. Uses Bresenham's algorithm to + * get a smoother line. + */ + +#ifdef ANSI_FUNC + +static void +cdl_drawVector ( + uchar *pix, /* edit region raster */ + int color, /* overlay color */ + int x1, + int x2, + int y1, + int y2, /* line endpoints */ + int lx, + int ly, /* subraster LL corner */ + int nx, + int ny /* subraster size */ +) +#else + +static void +cdl_drawVector (pix, color, x1, x2, y1, y2, lx, ly, nx, ny) +uchar *pix; /* edit region raster */ +int color; /* overlay color */ +int x1, y1, x2, y2; /* line endpoints */ +int lx, ly; /* subraster LL corner */ +int nx, ny; /* subraster size */ +#endif +{ + register int i, d, x, y; + register int ax, ay, sx, sy, dx, dy; + + /* Use a Bresenham algorith do draw the line. */ + dx = x2 - x1; ax = ABS(dx) << 1; sx = SGN(dx); + dy = y2 - y1; ay = ABS(dy) << 1; sy = SGN(dy); + x = x1; + y = y1; + if (ax > ay) { /* X span is dominant */ + for (d = ay - (ax >> 1); x != x2; x += sx, d += ay) { + i = max (((y-ly) * nx) + min(nx-1,(x-lx)), 0); + pix[i] = color; + if (d >= 0) { + y += sy; + d -= ax; + } + } + } else { /* Y span is dominant */ + for (d = ax - (ay >> 1); y != y2; y += sy, d += ax) { + i = max (((y-ly) * nx) + min(nx-1,(x-lx)), 0); + pix[i] = color; + if (d >= 0) { + x += sx; + d -= ay; + } + } + } + i = max (((y-ly) * nx) + min(nx-1,(x-lx)), 0); + pix[i] = color; +} + + +/* CDL_DRAWTHICKDASHVEC -- Draw a line between two arbitrary endpoints in + * a subraster. We draw multiple vectors to achieve the line thickness. + */ + +#ifdef ANSI_FUNC + +static void +cdl_drawThickDashVec ( + uchar *pix, /* edit region raster */ + int color, /* overlay color */ + int width, /* line width */ + int style, /* line style */ + int x1, + int x2, + int y1, + int y2, /* line endpoints */ + int lx, + int ly, /* subraster LL corner */ + int nx, + int ny /* subraster size */ +) +#else + +static void +cdl_drawThickDashVec (pix, color, width, style, x1, x2, y1, y2, lx, ly, nx, ny) +uchar *pix; /* edit region raster */ +int color; /* overlay color */ +int width; /* line width */ +int style; /* line style */ +int x1, y1, x2, y2; /* line endpoints */ +int lx, ly; /* subraster LL corner */ +int nx, ny; /* subraster size */ +#endif +{ + register int i, new_x = x2, new_y = y2, dx = 0, dy = 0; + register int xshift = 0, yshift = 0; + register int xx1, xx2, yy1, yy2, n = 0, sign = 1; + + if (abs (new_x - x1) > abs (new_y - y1)) + dx = 0, dy = 1; + else + dx = 1, dy = 0; + + switch (style) { + case L_DASHED: SAVE_DASH_COUNT; break; + case L_DOTTED: SAVE_DOT_COUNT; break; + case L_DOTDASH: SAVE_DOTDASH_COUNT; break; + } + + for (i=1; i <= width; i++) { + xx1 = x1 + xshift; + yy1 = y1 + yshift; + xx2 = new_x + xshift; + yy2 = new_y + yshift; + + cdl_drawDashVec (pix, color, style, xx1, xx2, yy1, yy2, + lx, ly, nx, ny); + + if (i == 1) { + /* Save the dashed line counters so we get a smooth line */ + p_dash = dash, p_dot = dot, p_dotdash = dotdash; + } + + switch (style) { + case L_DASHED: RESTORE_DASH_COUNT; break; + case L_DOTTED: RESTORE_DOT_COUNT; break; + case L_DOTDASH: RESTORE_DOTDASH_COUNT; break; + } + + n = (i + 1 + 0.5) / 2; + sign = ((i % 2 == 0) ? 1 : -1); + if (x1 == x2) + xshift = sign * dx * n; + else if (y1 == y2) + yshift = sign * dy * n; + else { + xshift = sign * dx * n; + yshift = sign * dy * n; + } + } +} + + +/* CDL_DRAWDASHVEC -- Draw a line between two arbitrary endpoints in a + * subraster. Endpoints are given in image coordinates along with the + * subraster boundary, we translate to subraster coords before marking the + * pixel. This allows us to get a subraster for a larger object such as + * polygon and use the line primitive to draw each vertex before writing + * back a single subraster rather than use the less efficient sequence of + * server I/O calls for each line segment. Uses Bresenham's algorithm to + * get a smoother line. + */ + +#ifdef ANSI_FUNC + +static void +cdl_drawDashVec ( + uchar *pix, /* edit region raster */ + int color, /* overlay color */ + int style, /* line style */ + int x1, + int x2, + int y1, + int y2, /* line endpoints */ + int lx, + int ly, /* subraster LL corner */ + int nx, + int ny /* subraster size */ +) +#else + +static void +cdl_drawDashVec (pix, color, style, x1, x2, y1, y2, lx, ly, nx, ny) +uchar *pix; /* edit region raster */ +int color; /* overlay color */ +int style; /* line style */ +int x1, y1, x2, y2; /* line endpoints */ +int lx, ly; /* subraster LL corner */ +int nx, ny; /* subraster size */ +#endif +{ + register int i, d, x, y; + register int ax, ay, sx, sy, dx, dy; + + /* Use a Bresenham algorith do draw the line. */ + dx = x2 - x1; ax = ABS(dx) << 1; sx = SGN(dx); + dy = y2 - y1; ay = ABS(dy) << 1; sy = SGN(dy); + x = x1; + y = y1; + if (ax > ay) { /* X span is dominant */ + for (d = ay - (ax >> 1); x != x2; x += sx, d += ay) { + i = ((y-ly) * nx) + min(nx-1,(x-lx)); + i = max (i, 0); + pix[i] = cdl_setpixel (pix[i], style, color); + if (d >= 0) { + y += sy; + d -= ax; + } + } + } else { /* Y span is dominant */ + for (d = ax - (ay >> 1); y != y2; y += sy, d += ax) { + i = ((y-ly) * nx) + min(nx-1,(x-lx)); + i = max (i, 0); + pix[i] = cdl_setpixel (pix[i], style, color); + if (d >= 0) { + x += sx; + d -= ay; + } + } + } +} + + +/* CDL_SETPIXEL -- Set the pixel to the desired color and keep track of + * which pixels have been changed so we get a dashed line effect. + */ + +#ifdef ANSI_FUNC + +static uchar +cdl_setpixel ( + uchar pix, /* input pixel */ + int style, /* line style */ + int color /* line color */ +) +#else + +static uchar +cdl_setpixel (pix, style, color) +uchar pix; /* input pixel */ +int style; /* line style */ +int color; /* line color */ +#endif +{ + /* If the current pixel is already set just ignore it. We need + * to do this so that when drawing many small segments in a poly- + * line (e.g. a circle) we don't increment the dash counters un- + * necessarily so we can maintain the spacing. + */ + if (pix == color) + return (pix); + + switch (style) { + case L_DASHED: + return ((DASH_PIXEL ? color : pix)); + case L_DOTTED: + return ((DOT_PIXEL ? color : pix)); + case L_DOTDASH: + return ((DOTDASH_PIXEL ? color : pix)); + } + + return (color); +} + +/* CDL_FILLAREA -- Scan the pixel array and fill the area enclosed by the + * given color, or replace with those pixels from the reference raster. + * We assume the area to be filled is a simple closed convex polygon. + */ + +#ifdef ANSI_FUNC + +static void +cdl_fillArea ( + uchar *pix, /* edit region raster */ + int nx, + int ny, /* subraster size */ + int color /* overlay color */ +) +#else + +static void +cdl_fillArea (pix, nx, ny, color) +uchar *pix; /* edit region raster */ +int nx, ny; /* subraster size */ +int color; /* overlay color */ +#endif +{ + register int i, j, l, r; + + for (i=0; i < ny; i++) { + l = r = 0; + + /* Find the left endpoint. */ + while (l < nx && pix[(i * nx) + l] != color) + l++; + if (l != nx) { + + /* Find the right endpoint. */ + r = nx - 1; + while (r > l && pix[(i * nx) + r] != color) + r--; + + if (r > l) { + /* Fill the area in between. */ + for (j=l; j <= r; j++) + pix[(i*nx)+j] = color; + } + } + } +} + + +/* CDL_GETCIRCLECOORDS -- Compute the coords for points needed to draw a + * circle of a given radius at the given center. + */ + +#ifdef ANSI_FUNC + +static void +cdl_getCircleCoords ( + int xcen, + int ycen, /* circle center */ + int radius, /* circle radius */ + int *x, + int *y, /* output coords */ + int npts /* number of coords */ +) +#else + +static void +cdl_getCircleCoords (xcen, ycen, radius, x, y, npts) +int xcen, ycen; /* circle center */ +int radius; /* circle radius */ +int *x, *y; /* output coords */ +int npts; /* number of coords */ +#endif +{ + register int i, count, xoff, yoff; + register int a1, a2, a3, b1, b2, b3, b4; + static double UnitCircleX[12] = { + -0.06540312923014, -0.19509032201613, + -0.32143946530316, -0.44228869021900, + -0.55557023301960, -0.65934581510007, + -0.75183980747898, -0.83146961230255, + -0.89687274153269, -0.94693012949511, + -0.98078528040323, -0.99785892323860 + }; + static double UnitCircleY[12] = { + -0.99785892323860, -0.98078528040323, + -0.94693012949511, -0.89687274153269, + -0.83146961230255, -0.75183980747898, + -0.65934581510007, -0.55557023301960, + -0.44228869021900, -0.32143946530316, + -0.19509032201613, -0.06540312923014 + }; + + + /* Set up array indexes for 8 fold symetry */ + /* 8 indexes radiating both ways from each of the four axes */ + a1 = npts / 4; /* (1 * cnt) / 4 */ + a2 = a1 + a1; /* (2 * cnt) / 4 */ + a3 = a2 + a1; /* (3 * cnt) / 4 */ + b1 = a1 - 1; + b2 = a2 - 1; + b3 = a3 - 1; + b4 = a3 + a1 - 1; /* (4 * cnt) / 4 - 1 */ + + /* Calculate points on circumference for 1/8th of circle */ + /* Apply to each of 8 pairs */ + count = npts / 8; + xcen -= 1; /* fix for mysterious off-by-one bug */ + for( i=0; i <= count; i++ ) { + xoff = UnitCircleX[i] * radius + 0.5; + yoff = UnitCircleY[i] * radius + 0.5; + x[i] = xcen + xoff; + y[i] = ycen + yoff; + x[a1+i] = xcen + yoff; + y[a1+i] = ycen - xoff; + x[a2+i] = xcen - xoff; + y[a2+i] = ycen - yoff; + x[a3+i] = xcen - yoff; + y[a3+i] = ycen + xoff; + x[b1-i] = xcen + yoff; + y[b1-i] = ycen + xoff; + x[b2-i] = xcen + xoff; + y[b2-i] = ycen - yoff; + x[b3-i] = xcen - yoff; + y[b3-i] = ycen - xoff; + x[b4-i] = xcen - xoff; + y[b4-i] = ycen + yoff; + } + /* Close the circle (end point same as starting point) */ + x[npts-1] = x[0]; + y[npts-1] = y[0]; +} + + +/* CDL_GETELLIPSECOORDS -- Compute the coords for points needed to draw a + * ellipse w/ given axes and angle at the desired center. + */ + +#ifdef ANSI_FUNC + +static void +cdl_getEllipseCoords ( + int xcen, + int ycen, /* ellipse center */ + int xradius, + int yradius, /* ellipse axes */ + float rotang, /* angle from X axis */ + int *x, + int *y /* output coords */ +) +#else + +static void +cdl_getEllipseCoords (xcen, ycen, xradius, yradius, rotang, x, y) +int xcen, ycen; /* ellipse center */ +int xradius, yradius; /* ellipse axes */ +float rotang; /* angle from X axis */ +int *x, *y; /* output coords */ +#endif +{ + int loop; + float xoff, yoff; + double rotsin, rotcos; + register int i; + register int x1, x2, y1, y2; + register int a2, b1, b3; + static double UnitEllipseX[16] = { + -0.04906767432742, -0.14673047445536, + -0.24298017990326, -0.33688985339222, + -0.42755509343028, -0.51410274419322, + -0.59569930449243, -0.67155895484702, + -0.74095112535496, -0.80320753148064, + -0.85772861000027, -0.90398929312344, + -0.94154406518302, -0.97003125319454, + -0.98917650996478, -0.99879545620517 + }; + static double UnitEllipseY[16] = { + -0.99879545620517, -0.98917650996478, + -0.97003125319454, -0.94154406518302, + -0.90398929312344, -0.85772861000027, + -0.80320753148064, -0.74095112535496, + -0.67155895484702, -0.59569930449243, + -0.51410274419322, -0.42755509343028, + -0.33688985339222, -0.24298017990326, + -0.14673047445536, -0.04906767432742 + }; + + /* Set up array indexes for 8 fold symetry */ + /* 4 indexes radiating both ways from each of the two axis rays */ + a2 = N_ELLIPSE_PTS / 2; + b1 = a2 - 1; + b3 = N_ELLIPSE_PTS - 1; + + rotsin = sin ((double) ((double)rotang * 0.017453293)); + rotcos = cos ((double) ((double)rotang * 0.017453293)); + + /* Recalculate points on circumference */ + /* Apply to each of 4 pairs */ + loop = N_ELLIPSE_PTS / 4; + for( i=0; i < loop; i++ ) { + /* Calculate ray lengths for orthogonal case */ + xoff = UnitEllipseX[i] * xradius; + yoff = UnitEllipseY[i] * yradius; + + /* Calculate offset of two points on the right (rotate) */ + x2 = (xoff * rotcos) + (yoff * rotsin) + 0.5; + y2 = (xoff * rotsin) - (yoff * rotcos) - 0.5; + x1 = (xoff * rotcos) - (yoff * rotsin) - 0.5; + y1 = (xoff * rotsin) + (yoff * rotcos) + 0.5; + x[i] = xcen + x1; + y[i] = ycen + y1; + x[a2+i] = xcen - x1; + y[a2+i] = ycen - y1; + x[b1-i] = xcen + x2; + y[b1-i] = ycen + y2; + x[b3-i] = xcen - x2; + y[b3-i] = ycen - y2; + } + /* Close the circle (end point same as starting point) */ + x[N_ELLIPSE_PTS-1] = x[0]; + y[N_ELLIPSE_PTS-1] = y[0]; +} + + +/* CDL_MINMAX -- Find the array extrema. */ + +#ifdef ANSI_FUNC + +static void +cdl_minmax ( + int *array, /* array to check */ + int npts, /* no of points */ + int *amin, + int *amax /* extremes */ +) +#else + +static void +cdl_minmax (array, npts, amin, amax) +int *array; /* array to check */ +int npts; /* no of points */ +int *amin, *amax; /* extremes */ +#endif +{ + register int i; + + *amin = *amax = array[0]; + for (i=1; i < npts; i++) { + if (*amin > array[i]) *amin = array[i]; + if (*amax < array[i]) *amax = array[i]; + } +} + + +/* CDL_STRLEN -- Find the length of a string to be drawn. */ + +#ifdef ANSI_FUNC + +static int +cdl_strlen ( +char *str, /* string to draw */ +float txtsize, /* string size */ +int txtfont /* font */ +) +#else + +static int +cdl_strlen (str, txtsize, txtfont) +char *str; /* string to draw */ +float txtsize; /* string size */ +int txtfont; /* font */ +#endif +{ + char chr, *sp = str; + int ip, oldfont, font = txtfont, offset = 0; + register int i, cw, ch, len; + float size = txtsize; + + /* Loop over each character in the string. */ + len = 0; + cw = CHARACTER_WIDTH * (size * FONT_SCALE) + FONT_SPACE; + ch = CHARACTER_HEIGHT * (size * FONT_SCALE); + for (; *sp; sp++) { + + /* Check for an inline font escape. */ + if (*sp == '\\' && *(sp+1) == 'f') { + sp++; sp++; + if (*sp != 'P') + oldfont = font; + + switch (*sp) { + case 'R': + font = F_ROMAN; break; + case 'F': + font = F_FUTURA; break; + case 'T': + font = F_TIMES; break; + case 'G': + font = F_GREEK; break; + case 'P': + font = oldfont; break; + + /* Check for a super/subscript escape. */ + case 'U': + offset += ch / 2; + break; + case 'D': + offset -= ch / 2; + break; + } + sp++; + } + + /* Adjust the size if we're doing sub/superscript. */ + if (offset != 0) + size = txtsize * 0.666; + else + size = txtsize; + + if (*sp < CHARACTER_START || *sp > CHARACTER_END) + chr = i = '?' - CHARACTER_START; + else + chr = i = *sp - CHARACTER_START; + + /* Update the character position. */ + ip = (int) chr; + switch (font) { + case F_ROMAN: + len += cw; + break; + case F_GREEK: + len += (gchwid[ip] / 2) * (size * FONT_SCALE) + FONT_SPACE + 2; + break; + case F_TIMES: + len += (timwid[ip] -12) * (size * FONT_SCALE) + FONT_SPACE + 2; + break; + case F_FUTURA: + len += (futwid[ip] / 2) * (size * FONT_SCALE) + FONT_SPACE + 2; + break; + } + } + return (len); +} + + +/* BITUPK -- Unpack an unsigned integer bit field from a longword. + */ + +unsigned bitmask[] = { 0, /* MACHDEP */ + 01, 03, 07, + 017, 037, 077, + 0177, 0377, 0777, + 01777, 03777, 07777, + 017777, 037777, 077777, + 0177777, 0377777, 0777777, + 01777777, 03777777, 07777777, + 017777777, 037777777, 077777777, + 0177777777, 0377777777, 0777777777, + 01777777777, 03777777777, 07777777777, + 017777777777, 037777777777 +}; + +#ifdef ANSI_FUNC + +static int +bitupk ( + unsigned int wordp, /* longword to be examined */ + int offset, /* one-indexed offset of first bit */ + int nbits /* number of bits to be set */ +) +#else + +static int +bitupk (wordp, offset, nbits) +unsigned int wordp; /* longword to be examined */ +int offset; /* one-indexed offset of first bit */ +int nbits; /* number of bits to be set */ +#endif +{ + return ((wordp >> (offset-1)) & bitmask[nbits]); +} + |