aboutsummaryrefslogtreecommitdiff
path: root/vendor/x11iraf/cdl/cdlmark.c
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/x11iraf/cdl/cdlmark.c')
-rw-r--r--vendor/x11iraf/cdl/cdlmark.c3861
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]);
+}
+