aboutsummaryrefslogtreecommitdiffstats
path: root/src/cd/cd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cd/cd.c')
-rw-r--r--src/cd/cd.c2372
1 files changed, 2372 insertions, 0 deletions
diff --git a/src/cd/cd.c b/src/cd/cd.c
new file mode 100644
index 0000000..97656f9
--- /dev/null
+++ b/src/cd/cd.c
@@ -0,0 +1,2372 @@
+
+/* cd.c main file for cgmdraw module.
+
+ Written by G. Edward Johnson <mailto:lorax@nist.gov>
+ Date: April 1996
+ Copyright: cd software produced by NIST, an agency of the
+ U.S. government, is by statute not subject to copyright
+ in the United States. Recipients of this software assume all
+ responsibilities associated with its operation, modification
+ and maintenance.
+
+ Portions of this package are from the gd package written by
+ Thomas Boutell and are copyright 1994, 1995, Quest Protein
+ Database Center, Cold Spring Harbor Labs. They are marked in the
+ source code.
+
+*/
+
+
+#include <malloc.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "defines.h"
+#include "cd.h"
+
+
+cdImagePtr cdImageCreate(int sx, int sy)
+{
+ cdImagePtr im;
+ im = (cdImage *) calloc(SIZEOF(cdImage), 1);
+ if (!im) return 0; /* memory allocation failed */
+ /* elemlist is set to some number, when it is full, make it bigger */
+ im->elemlist = (unsigned char *) calloc(CDSTARTLISTSIZE, SIZEOF(unsigned char ) );
+ if (!im->elemlist) return 0; /* memory allocation failed */
+ im->sx = sx;
+ im->sy = sy;
+ im->colorsTotal = 0;
+ /* you can have multiple pictures in a file, keep track of
+ * which one you are on */
+ im->picnum = 10;
+ /* set line_width, line_height, line_color to the defaults */
+ /*gej: I should change these when I figure out what the defaults are */
+ im->ltype = CDLTYPE;
+ im->lwidth = CDLWIDTH;
+ im->lcolor = CDLCOLOR;
+ /* interior_style, fill_color, hatch_index */
+ im->shapestyle = CDSHAPESTYLE;
+ im->shapecolor = CDSHAPECOLOR;
+ im->shapehatch = CDSHAPEHATCH;
+ /* edge_type, edge_width, edge_color, edge_visibility */
+ im->edgetype = CDEDGETYPE;
+ im->edgecolor = CDEDGECOLOR;
+ im->edgewidth = CDEDGEWIDTH;
+ im->edgevis = CDEDGEVIS;
+ /* text_color, text_height, text_font */
+ im->textcolor = CDTEXTCOLOR;
+ im->textheight = CDTEXTHEIGHT;
+ im->textfont = CDTEXTFONT;
+ im->textpath = CDTEXTPATH;
+ /* the next three are used for maintaining the element list
+ * don't change these ever */
+ im->bytestoend = CDSTARTLISTSIZE;
+ im->listlen = CDSTARTLISTSIZE;
+ im->curelemlist = im->elemlist;
+
+ cdCgmHeader(im);
+ return im;
+
+}
+
+static int cdAppNull(unsigned char *es, int x) {
+/* put x nulls in the string.
+ * return value is number of octets added (1) */
+ int y;
+
+ for(y=0; y<x; y++) {
+ *es = '\0';
+ es++;
+ }
+ return x;
+
+}
+
+static int cdAppByte(unsigned char *es, short int addme) {
+/* Append an octet to the end of es
+ * Return value is number of octets added
+ * for internal cd functions only, do not call
+ */
+ *es = addme & 0377;
+ return 1;
+}
+
+static int cdAppShort(unsigned char *es, short int addme) {
+/* Append a short to the end of es
+ * return value is number of octets added
+ * For internal cd functions only, do not call!
+ */
+ short int temp;
+
+ temp = addme >> 8;
+ *es = (unsigned char) temp & 0377;
+ es++;
+ *es = (unsigned char) addme & 0377;
+ return 2;
+}
+
+/* static int cdAppWord(unsigned char *es, int addme){ */
+/* Append an word to es
+ * Return value is number of octets added
+ * For internal cd functions only, do not call!
+ */
+/*
+ int temp;
+ temp = addme >> 24;
+ *es = (unsigned char) temp & 0377;
+ es++;
+ temp = addme >> 16;
+ *es = (unsigned char) temp & 0377;
+ es++;
+ temp = addme >> 8;
+ *es = (unsigned char) temp & 0377;
+ es++;
+ *es = (unsigned char) addme & 0377;
+ es++;
+ return 4;
+}
+*/
+
+static int cdcomhead(unsigned char *es, int elemclass, int id, int len) {
+/* sets the command header in the first two bytes of string es
+ * element class is in bits 15-12
+ * element id is in bits 11-5
+ * parameter list length is in bits 4-0
+ */
+ int temp;
+
+ if (!es) return 0; /* the string must be allocated first */
+
+ /* set the element class */
+ *es = (unsigned char) elemclass << 4;
+ /* set the element id */
+ temp = 0177 & id ;
+ temp = temp >> 3;
+ *es = *es | temp;
+ es++;
+ id = id << 5;
+ *es = (unsigned char) id;
+ *es = *es | (unsigned char) ( 037 & len );
+
+ return 1;
+}
+
+static int cdcomheadlong(unsigned char *es, int elemclass, int id, int len) {
+/* sets the command header for the long form.
+ * first 16 bits:
+ * element class is in bits 15-12
+ * element id is in bits 11-5
+ * parameter list length is in bits 4-0 = 31
+ * second 16 bits:
+ * bit 15 = 0 (for last partition)
+ * bit 14-0 param list len
+ */
+
+ /* I'm lazy, call cdcomhead to set the first two bytes */
+ if (!cdcomhead(es, elemclass, id, 31)) return 0;
+ es += 2;
+
+ /* now set the second two bytes */
+ cdAppShort(es, (short int) len);
+ *es = *es & 0177; /* make bit 15 = 0 */
+ es += 2;
+
+ return 1;
+}
+static int cdcomheadlongp(unsigned char *es, int elemclass, int id) {
+/* sets the command header for the long form.
+ * first 16 bits:
+ * element class is in bits 15-12
+ * element id is in bits 11-5
+ * parameter list length is in bits 4-0 = 31
+ * second 16 bits:
+ * bit 15 = 0 (for last partition)
+ * bit 14-0 param list len
+ */
+
+ /* I'm lazy, call cdcomhead to set the first two bytes */
+ if (!cdcomhead(es, elemclass, id, 31)) return 0;
+ es += 2;
+
+ return 1;
+}
+static int cdcomheadlongc(unsigned char *es, int part, int len) {
+/* sets the command header for the long form.
+ * second 16 bits:
+ * bit 15 = 0 (for last partition)
+ * bit 14-0 param list len
+ */
+
+ cdAppShort(es, (short int) len);
+ *es = *es & 0177; /* make bit 15 = 0 */
+ if (part) *es=(*es) | 128;
+ es += 2;
+
+ return 1;
+}
+
+static int cdAddElem(cdImagePtr im, unsigned char *es, int octet_count)
+/* adds a string, which is a CGM element to the elemlist.
+ * This function is called by other functions in this library and
+ * should NOT be called by users of the library
+ * For internal cd functions only, do not call!
+ */
+{
+ unsigned char *newlist; /* in case memory allocation fails */
+ int x; /* counter */
+
+ while ((octet_count + 1) >= im->bytestoend) {
+ /* not enough space, must grow elemlist */
+ im->listlen = im->listlen + CDGROWLISTSIZE;
+ newlist = (unsigned char *) realloc(im->elemlist, SIZEOF(unsigned char ) * im->listlen);
+ if (newlist) {
+ /* successfully allocated memory */
+ im->elemlist = newlist;
+ im->bytestoend = im->bytestoend + CDGROWLISTSIZE;
+ im->curelemlist = im->elemlist + (im->listlen - im->bytestoend);
+ }
+ else {
+ /* memory allocation failed, save yurself */
+ im->listlen = im->listlen - CDGROWLISTSIZE;
+ return 0;
+ }
+ }
+
+ /* ok, if we get to here, there is enough space, so add it. */
+ for (x=0; x < octet_count; x++) {
+ *im->curelemlist = (unsigned char) *es;
+ im->curelemlist++;
+ es++;
+ }
+ im->bytestoend = im->bytestoend - octet_count;
+ return 1;
+
+}
+
+int cdCgmHeader(cdImagePtr im) {
+/* add the cgm header to the imagepointer's element list
+ * do it all in a string than call cdAddElem on it
+ * For internal cd functions only, do not call!
+ */
+ unsigned char *headerp;
+ unsigned char *head;
+ unsigned char *buf, *buf2;
+ int octet_count=0;
+ int blen; /* length of buf */
+ int curly;
+
+ headerp = (unsigned char *) calloc(1024, SIZEOF(unsigned char ));
+ if (!headerp) return 0; /* memory allocation failed */
+ head=headerp;
+
+ /*** Attribute: BegMF; Elem Class 0; Elem ID 1 */
+ buf = (unsigned char *) "cd: CgmDraw Library";
+ blen = strlen( (char *) buf);
+ cdcomhead(head, 0, 1, blen+1);
+ head += 2;
+ head += cdAppByte(head, (short int) blen);
+ buf2 = buf;
+ while (*buf2) {
+ *head++ = *buf2++;
+ }
+ octet_count += (blen + 3);
+ curly = 4 - (octet_count % 4);
+ if (curly % 4) {
+ octet_count += curly;
+ head += cdAppNull(head, curly);
+ }
+
+ /*** Attribute: MFVersion; Elem Class 1; Elem ID 1 */
+ cdcomhead(head, 1, 1, 2);
+ head += 2;
+ head += cdAppShort(head, (short int) 1);
+ octet_count += 4;
+
+ /*** Attribute: MFDesc; Elem Class 1; Elem ID 2 */
+ buf = (unsigned char *) "'ProfileId: Model-Profile''ProfileEd:1''ColourClass:colour''Source:Nist CGMDraw 1.2''Date: 1996-06-28'";
+ blen = strlen( (char *) buf);
+ cdcomheadlong(head, 1, 2, blen+1);
+ head += 4;
+ head += cdAppByte(head, (short int) blen);
+ buf2 = buf;
+ while (*buf2) {
+ *head++ = *buf2++;
+ }
+ octet_count += (blen + 5);
+ curly = 4 - (octet_count % 4);
+ if (curly % 4) {
+ octet_count += curly;
+ head += cdAppNull(head, curly);
+ }
+
+ /*** Attribute: ColrPrec; Elem Class 1; Elem ID 7 */
+ cdcomhead(head, 1, 7, 2);
+ head += 2;
+ head += cdAppShort(head, (short int) 8);
+ octet_count += 4;
+
+ /*** Attribute: ColrIndexPrec; Elem Class 1; Elem ID 8 */
+ cdcomhead(head, 1, 8, 2);
+ head += 2;
+ head += cdAppShort(head, (short int) 8);
+ octet_count += 4;
+
+ /*** Attribute: MaxColrIndex; Elem Class 1; Elem ID 9 */
+ cdcomhead(head, 1, 9, 1);
+ head += 2;
+ head += cdAppByte(head, (short int) 255);
+ octet_count += 4; head++;
+
+ /*** Attribute: MFElemList; Elem Class 1; Elem ID 11 */
+ /* shorthand here. 1 means 1 element specified, (-1,1)
+ * means drawing-plus-control set */
+ cdcomhead(head, 1, 11, 6);
+ head += 2;
+ head += cdAppShort(head, (short int) 1);
+ head += cdAppShort(head, (short int) -1);
+ head += cdAppShort(head, (short int) 1);
+ octet_count += 8;
+
+ /*** Attribute: FontList; Elem Class 1; Elem ID 13 */
+ cdcomheadlong(head, 1, 13, 112);
+ head +=4;
+ buf = (unsigned char *) "Times";
+ blen = strlen( (char *) buf);
+ head += cdAppByte(head, (short int) blen);
+ buf2 = buf;
+ while (*buf2) {
+ *head++ = *buf2++;
+ }
+ buf = (unsigned char *) "Times Bold";
+ blen = strlen( (char *) buf);
+ head += cdAppByte(head, (short int) blen);
+ buf2 = buf;
+ while (*buf2) {
+ *head++ = *buf2++;
+ }
+ buf = (unsigned char *) "Times Italic";
+ blen = strlen( (char *) buf);
+ head += cdAppByte(head, (short int) blen);
+ buf2 = buf;
+ while (*buf2) {
+ *head++ = *buf2++;
+ }
+ buf = (unsigned char *) "Times Bold Italic";
+ blen = strlen( (char *) buf);
+ head += cdAppByte(head, (short int) blen);
+ buf2 = buf;
+ while (*buf2) {
+ *head++ = *buf2++;
+ }
+ buf = (unsigned char *) "Helvetica";
+ blen = strlen( (char *) buf);
+ head += cdAppByte(head, (short int) blen);
+ buf2 = buf;
+ while (*buf2) {
+ *head++ = *buf2++;
+ }
+ buf = (unsigned char *) "Helvetica Bold";
+ blen = strlen( (char *) buf);
+ head += cdAppByte(head, (short int) blen);
+ buf2 = buf;
+ while (*buf2) {
+ *head++ = *buf2++;
+ }
+ buf = (unsigned char *) "Helvetica Italic";
+ blen = strlen( (char *) buf);
+ head += cdAppByte(head, (short int) blen);
+ buf2 = buf;
+ while (*buf2) {
+ *head++ = *buf2++;
+ }
+ buf = (unsigned char *) "Helvetica Bold Italic";
+ blen = strlen( (char *) buf);
+ head += cdAppByte(head, (short int) blen);
+ buf2 = buf;
+ while (*buf2) {
+ *head++ = *buf2++;
+ }
+ octet_count += (4 + 112);
+ curly = 4 - (octet_count % 4);
+ if (curly % 4) {
+ octet_count += curly;
+ head += cdAppNull(head, curly);
+ }
+
+
+ if (cdAddElem(im, headerp, octet_count)) {
+ free(headerp);
+ headerp = 0;
+ }
+ else {
+ free(headerp);
+ return 0;
+ }
+
+ if (cdCgmPic(im, 0)) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+int cdCgmPic(cdImagePtr im, int sticky) {
+/* Start the picture. if the sticky bit is set, set and use the defaults
+ * of the previous picture. Otherwise, reset all defaults.
+ * Gej: Right now, will only work if the sticky bit is not set (is 0)
+ */
+ unsigned char *headerp;
+ unsigned char *head;
+ unsigned char *buf, *buf2;
+ char *tb;
+ int octet_count=0;
+ int blen; /* length of buf */
+
+ /* increment the picture number */
+ im->picnum++;
+ tb = (char *) calloc(4*4, SIZEOF(char) );
+ headerp = (unsigned char *) calloc(1024, SIZEOF(unsigned char ));
+ if (!headerp) return 0; /* memory allocation failed */
+ head=headerp;
+
+
+ /*** Attribute: BegPic; Elem Class 0; Elem ID 3 */
+ sprintf(tb, "picture %d", im->picnum);
+ buf = (unsigned char*) tb;
+ /* buf = (unsigned char *) "picture 1"; */
+ blen = strlen( (char *) buf);
+ cdcomhead(head, 0, 3, blen+1);
+ head += 2;
+ head += cdAppByte(head, (short int) blen);
+ buf2 = buf;
+ while (*buf2) {
+ *head++ = *buf2++;
+ }
+ octet_count += (blen + 3);
+ if (!(blen % 2)) {
+ octet_count++;
+ head += cdAppNull(head, 1);
+ }
+ if (octet_count % 4) {
+ octet_count +=2;
+ head += cdAppNull(head, 2);
+ }
+
+ /*** Attribute: ColrMode; Elem Class 2; Elem ID 2 */
+ cdcomhead(head, 2, 2, 2);
+ head += 2;
+ head += cdAppShort(head, (short int) 0);
+ octet_count += 4;
+
+ /*** Attribute: VDCExt; Elem Class 2; Elem ID 6 */
+ cdcomhead(head, 2, 6, 8);
+ head += 2;
+ head += cdAppShort(head, (short int) 0);
+ head += cdAppShort(head, (short int) 0);
+ head += cdAppShort(head, (short int) im->sx);
+ head += cdAppShort(head, (short int) im->sy);
+ octet_count += 10;
+
+ /*** Attribute: ColrPrec; Elem Class 0; Elem ID 4 */
+ cdcomhead(head, 0, 4, 0);
+ head += 2;
+ octet_count += 2;
+
+ if (sticky) {
+ /* gej: were screwed. This isn't implemented yet */
+ free(headerp);
+ return 0;
+ }
+ else {
+ /* reset all the defaults */
+ /* set line_width, line_height, line_color to the defaults */
+ im->ltype = CDLTYPE;
+ im->lwidth = CDLWIDTH;
+ im->lcolor = CDLCOLOR;
+ /* interior_style, fill_color, hatch_index */
+ im->shapestyle = CDSHAPESTYLE;
+ im->shapecolor = CDSHAPECOLOR;
+ im->shapehatch = CDSHAPEHATCH;
+ /* edge_type, edge_width, edge_color, edge_visibility */
+ im->edgetype = CDEDGETYPE;
+ im->edgecolor = CDEDGECOLOR;
+ im->edgewidth = CDEDGEWIDTH;
+ im->edgevis = CDEDGEVIS;
+ /* text_color, text_height, text_font */
+ im->textcolor = CDTEXTCOLOR;
+ im->textheight = CDTEXTHEIGHT;
+ im->textfont = CDTEXTFONT;
+ im->textpath = CDTEXTPATH;
+ /* Nuke the color table if there is one */
+ cdImageColorClear(im);
+ }
+
+
+ if (cdAddElem(im, headerp, octet_count)) {
+ free(headerp);
+ return 1;
+ }
+ else {
+ free(headerp);
+ return 0;
+ }
+
+}
+
+int cdCgmNewPic(cdImagePtr im, int sticky)
+/* The CGM standard allows multiple images in a single file. This function
+ * will close the current picture, then open a new one.
+ * if sticky is 0 then all attributes will be reset to the defaults
+ * if sticky is 1 then all attributes will be inherited from the prevous
+ * picture. This is currently not implemented, be sure to set sticky to
+ * 0.
+ */
+{
+ unsigned char *es, *esp;
+ int octet_count=0;
+
+ esp = (unsigned char *) calloc(1024, SIZEOF(unsigned char ));
+ if (!esp) return 0; /* memory allocation failed */
+ es=esp;
+
+ /* Attribute: End Picture; Elem Class 0; Elem ID 5; Length 0 */
+ cdcomhead(es, 0, 5, 0);
+ octet_count += 2;
+
+
+ if (cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+ /* now start the new picture */
+ return(cdCgmPic(im, sticky));
+
+
+}
+
+int cdImageCgm(cdImagePtr im, FILE *out)
+/* Gej: Write the image to file *out, which must be open already
+ * does not close the file */
+{
+ int x; /* counter */
+ int used; /* number of bytes used in the list */
+ unsigned char *efile, *efilep; /* end of file information */
+ efile = (unsigned char *) calloc(4*4,SIZEOF(unsigned char ));
+ if (!efile) return 0; /* memory allocation failed */
+ efilep=efile;
+ /* Attribute: End Picture; Elem Class 0; Elem ID 5 */
+ *efilep = '\0';
+ efilep++;
+ *efilep = '\240'; /* set Elem ID */
+ efilep++;
+ /* Attribute: End Metafile; Elem Class 0; Elem ID 2 */
+ *efilep = '\0';
+ efilep++;
+ *efilep = '\100'; /* set Elem ID */
+
+
+ if (cdAddElem(im, efile, 4)) {
+ free(efile);
+ efile = 0;
+ efilep = 0;
+ }
+ else {
+ free(efile);
+ return 0;
+ }
+
+ /* now output the string, one byte at a time */
+ used = im->listlen - im->bytestoend;
+ for (x=0;x < used; x++) {
+ putc((unsigned char) im->elemlist[x], out);
+ }
+
+ return 1;
+
+}
+
+
+int cdSetLineType(cdImagePtr im, int lntype) {
+/* Attribute: Line Type; Elem Class 5; Elem ID 2
+ * Set the line type. Possible values are:
+ * 1=solid, 2=dash, 3=dot, 4=dash-dot, 5=dash-dot-dot
+ * Even though new ones can be defined, I am limiting lntype to these values
+ * If you really need more, you can make the proper changes.
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (lntype == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (lntype == im->ltype)
+ return 1;
+
+ /* Make sure that lntype is between 1 and 5 */
+ if ((lntype < 1) || (lntype > 5))
+ return 0;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ if (!cdcomhead(es, 5, 2, 2)) return 0;
+ es += 2;
+ /* set Param_List_Len to 2 (signed int at index precision) */
+
+ /* add in the value of lntype */
+ es += cdAppShort(es, (short int) lntype);
+
+ octet_count = 4; /* we just know this */
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->ltype = (short int) lntype;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+}
+
+int cdSetLineWidth(cdImagePtr im, int lnwidth) {
+/* Attribute: Line Width; Elem Class 5; Elem ID 3
+ * sets the line width. with an image of height X with line width 1
+ * the displayed width will be 1/X%. as an example, if you image is
+ * x=5, y=10, and you set line width = 1, and draw a vertical line, the
+ * resulting line will cover 20% of horizontal area.
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (lnwidth == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (lnwidth == im->lwidth)
+ return 1;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+
+ octet_count = 2;
+ if (!cdcomhead(es, 5, 3, 4)) return 0;
+ es += 2;
+ /*gej: line width is 32 bit floating point number, 16 bits before the
+ * decimal, 16 bits after. */
+
+ es += cdAppShort(es, (short int) lnwidth);
+
+ /* the next two (after decimal point) will always be zero */
+ es += cdAppNull(es, 2);
+
+ octet_count += 4;
+
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->lwidth = lnwidth;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+}
+
+int cdSetLineColor(cdImagePtr im, int lncolor) {
+/* Attribute: Line Colour; Elem Class 5; Elem ID 4
+ * Sets the line color. lncolor should be an index into the color
+ * table that you have previously allocated.
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (lncolor == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (lncolor == im->lcolor)
+ return 1;
+
+ /* Make sure the color they want to use has been allocated.
+ * also, that color must be non-negative */
+ if ((lncolor >= im->colorsTotal ) || (lncolor < 0))
+ return 0; /* you must allocate a color before you use it */
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+
+ if (!cdcomhead(es, 5, 4, 1)) return 0;
+ es += 2;
+
+ *es = 0377 & lncolor; /* mask off last 8 bits and put in es */
+ es++;
+
+ es += cdAppNull(es, 1);
+
+ octet_count = 4; /* we just know this; 2 octets of header,
+ * 1 octet of data, 1 octet of null data */
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->lcolor = (short int) lncolor;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+}
+
+int cdSetFillStyle(cdImagePtr im, int instyle) {
+/* set the style of the interior of filled area elements.
+ * Attribute: Interior Style; Elem Class 5; Elem ID 22
+ * These attributes stay in effect until changed, so you don't have to output
+ * them every time.
+ * Interior Style: (integers 0-6, corresponding to: hollow, solid,
+ * [not pattern], hatch, empty, [not geometric pattern],
+ * interpolated.)
+ * attribute is 16 bit signed int
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (instyle == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (instyle == im->shapestyle)
+ return 1;
+
+ /* Make sure that lnhatch is between 0 and 6, but not
+ * 2, 5, or 6 */
+ if ((instyle < 0) || (instyle > 4) || (instyle == 2))
+ return 0;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ /* set the header to Class 5, ID 22, Length 2 */
+ if (!cdcomhead(es, 5, 22, 2)) return 0;
+ es += 2;
+
+ /* add in the value of inhatch */
+ es += cdAppShort(es, (short int) instyle);
+
+ octet_count = 4; /* we just know this */
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->shapestyle = (short int) instyle;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+}
+
+int cdSetFillColor(cdImagePtr im, int incolor) {
+/* set the color of the interior of filled area elements
+ * Attribute: Fill Colour; Elem Class 5; Elem ID 23
+ * These attributes stay in effect until changed, so you don't have to output
+ * them every time.
+ * Fill Colour: (index into the color table)
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (incolor == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (incolor == im->shapecolor)
+ return 1;
+
+ /* Make sure the color they want to use has been allocated.
+ * also, that color must be non-negative */
+ if ((incolor >= im->colorsTotal ) || (incolor < 0))
+ return 0; /* you must allocate a color before you use it */
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ if (!cdcomhead(es, 5, 23, 1)) return 0;
+ es += 2;
+
+ *es = 0377 & incolor; /* mask off last 8 bits and put in es */
+ es++;
+ es += cdAppNull(es, 1);
+
+ octet_count = 4; /* we just know this; 2 octets of header,
+ * 1 octet of data, 1 octet of null data */
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->shapecolor = (short int) incolor;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+
+}
+
+int cdSetFillHatch(cdImagePtr im, int inhatch) {
+/* Set the hatch pattern for the interior of filled-area elements
+ * the fill style must be set to hatch for this to have an effect.
+ * Attribute: Hatch Index; Elem Class 5; Elem ID 24
+ * These attributes stay in effect until changed, so you don't have to output
+ * them every time.
+ * Hatch Index: (integers 1-6, corresponding to: horizontal lines,
+ * vertical lines, pos. slope parallel lines,
+ * neg. slope parallel lines, horizontal/vertical
+ * crosshatch, positive/negative slope crosshatch)
+ */
+
+ unsigned char *es, *esp;
+ int octet_count, temp;
+
+
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (inhatch == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (inhatch == im->shapehatch)
+ return 1;
+
+ /* Make sure that lnhatch is between 1 and 6 */
+ if ((inhatch < 1) || (inhatch > 6))
+ return 0;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ /* set the command header to class 5, id 24, length 2 */
+ if (!cdcomhead (es, 5, 24, 2)) return 0;
+ es += 2;
+
+ /* add in the value of inhatch */
+ temp = inhatch >> 8;
+ *es = *es | (temp & 0377);
+ es++;
+ *es = *es | (inhatch & 0377);
+ es++;
+
+ octet_count = 4; /* we just know this */
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->shapehatch = (short int) inhatch;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+}
+
+int cdSetEdgeType(cdImagePtr im, int edtype) {
+/* set the type of the edge of filled-area elements.
+ * Attribute: Edge Type; Elem Class 5; Elem ID 27
+ * These attributes stay in effect until changed, so you don't have to output
+ * them every time.
+ * Edge Type (integers 1-5, corresponding to: solid, dash, dot,
+ * dash-dot, dash-dot-dot. These are the same as those used
+ * for line type.)
+ * In Part 3 of the standard (Binary Encoding) on page 47 it says that
+ * edge type is integer. This is incorrect. Edge type is Index, just
+ * like line type.
+ * Even though new ones can be defined, I am limiting lntype to these values
+ * If you really need more, you can make the proper changes.
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (edtype == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (edtype == im->edgetype)
+ return 1;
+
+ /* Make sure that lntype is between 1 and 5 */
+ if ((edtype < 1) || (edtype > 5))
+ return 0;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ if(!cdcomhead(es, 5, 27, 2)) return 0;
+ es += 2;
+
+ /* add in the value of edtype */
+ es += cdAppShort(es, (short int) edtype);
+
+ octet_count = 4; /* we just know this */
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->edgetype = (short int) edtype;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+}
+
+int cdSetEdgeWidth(cdImagePtr im, int edwidth) {
+/* Set the width of the edge of filled-area elements.
+ * Attribute: Edge Width; Elem Class 5; Elem ID 28
+ * These attributes stay in effect until changed, so you don't have to output
+ * them every time.
+ * Edge Width (should be the same as line width)
+ */
+ unsigned char *es, *esp;
+ int octet_count, temp;
+
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (edwidth == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (edwidth == im->edgewidth)
+ return 1;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ octet_count = 2;
+ if (!cdcomhead(es, 5, 28, 4)) return 0;
+ es += 2;
+
+ /*gej: edge width is 32 bit floating point number, 16 bits before the
+ * decimal, 16 bits after. */
+ es++; octet_count++;
+ temp = edwidth >> 8;
+ *es = *es | (temp & 0377);
+ es++; octet_count++;
+ *es = *es | (edwidth & 0377);
+ /* the next two (after decimal point) will always be zero */
+ es += cdAppNull(es, 2);
+ octet_count+=2;
+
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->edgewidth = edwidth;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+
+}
+
+int cdSetEdgeColor(cdImagePtr im, int edcolor) {
+/* Set the color of the edge of filled-area elements.
+ * Attribute: Edge Color; Elem Class 5; Elem ID 29
+ * These attributes stay in effect until changed, so you don't have to output
+ * them every time.
+ * Edge Colour (index into the color table)
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (edcolor == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (edcolor == im->edgecolor)
+ return 1;
+
+ /* Make sure the color they want to use has been allocated.
+ * also, that color must be non-negative */
+ if ((edcolor >= im->colorsTotal ) || (edcolor < 0))
+ return 0; /* you must allocate a color before you use it */
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+ if (!cdcomhead(es, 5, 29, 1)) return 0;
+ es += 2;
+
+ *es = 0377 & edcolor; /* mask off last 8 bits and put in es */
+ es++;
+ es += cdAppNull(es, 1);
+
+ octet_count = 4; /* we just know this; 2 octets of header,
+ * 1 octet of data, 1 octet of null data */
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->edgecolor = (short int) edcolor;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+
+}
+
+int cdSetEdgeVis(cdImagePtr im, int edvis) {
+/* Set the visibility of the edge of filled-area elements.
+ * Attribute: Edge Visibility; Elem Class 5; Elem ID 30
+ * These attributes stay in effect until changed, so you don't have to output
+ * them every time.
+ * Edge Visibility (integer 0 or 1, corresponding to: Off, On)
+ * Attribute is 16 bit signed int.
+ */
+ unsigned char *es, *esp;
+ int octet_count, temp;
+
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (edvis == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (edvis == im->edgevis)
+ return 1;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ if (!cdcomhead(es, 5, 30, 2)) return 0;
+ es +=2; octet_count = 2;
+ temp = edvis >> 8;
+ *es = *es | (temp & 0377);
+ es++;
+ *es = *es | (edvis & 0377);
+ es++;
+ octet_count += 2;
+
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->edgevis = (short int) edvis;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+}
+
+int cdSetTextFont(cdImagePtr im, int font) {
+/* Attribute: Text Font Index; Elem Class 5; Elem ID 10
+ * font is an index into the font table. it can have one of the following
+ * values:
+ * 1 Times
+ * 2 Times Bold
+ * 3 Times Italic
+ * 4 Times Bold Italic
+ * 5 Helvetica
+ * 6 Helvetica Bold
+ * 7 Helvetica Italic
+ * 8 Helvetica Bold Italic
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (font == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (font == im->textfont)
+ return 1;
+
+ /* Make sure that font is between 1 and 8 */
+ if ((font < 1) || (font > 8))
+ return 0;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ if(!cdcomhead(es, 5, 10, 2)) return 0;
+ es += 2;
+
+ es += cdAppShort(es, (short int) font);
+
+ octet_count = 4; /* we just know this */
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->textfont = (short int) font;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+}
+
+int cdSetTextColor(cdImagePtr im, int color) {
+/* Attribute: Text Colour ; Elem Class 5; Elem ID 14
+ * set the forground color of text
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (color == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (color == im->textcolor)
+ return 1;
+
+ /* Make sure the color they want to use has been allocated.
+ * also, that color must be non-negative */
+ if ((color >= im->colorsTotal ) || (color < 0))
+ return 0; /* you must allocate a color before you use it */
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ if(!cdcomhead(es, 5, 14, 1)) return 0;
+ es += 2;
+
+ *es = 0377 & color; /* mask off last 8 bits and put in es */
+ es++;
+
+ octet_count = 4; /* we just know this; 2 octets of header,
+ * 1 octet of data, 1 octet of null data */
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->textcolor = (short int) color;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+}
+
+int cdSetTextHeight(cdImagePtr im, int height) {
+/* Attribute: Character Height; Elem Class 5; Elem ID 15
+ * the height is in the same units as line width
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (height == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (height == im->textheight)
+ return 1;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ if(!cdcomhead(es, 5, 15, 2)) return 0;
+ octet_count = 2; es += 2;
+
+ es += cdAppShort(es, height);
+ octet_count += 2;
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->textheight = height;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+}
+
+int cdSetTextPath(cdImagePtr im, int tpath) {
+/* Attribute: Text Path; Elem Class 5; Elem ID 17
+ * Is one of:
+ * 0 right -- Means the direction of the character base vector
+ * 1 left -- means 180 degrees from the character base vector
+ * 2 up -- means the direction of the character up vector
+ * 3 down -- means 180 degrees from the character up vector
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+
+ /* First check and see if the user doesn't want any changes,
+ * if so, just return success */
+ if (tpath == -1)
+ return 1;
+
+ /* Check and see if the value it is being set to is the current
+ * value, if so, don't make any changes, just return 1 */
+ if (tpath == im->textpath)
+ return 1;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+ octet_count = 0;
+
+ if (!cdcomhead(es, 5, 17, 2)) return 0;
+ es +=2; octet_count = 2;
+
+ es += cdAppShort(es, (short int) tpath);
+ octet_count += 2;
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ im->textpath = (short int) tpath;
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+}
+
+int cdSetTextOrient(cdImagePtr im, int xup, int yup, int xbase, int ybase) {
+/* Attribute: Character Orientation; Elem Class 5; Elem ID 16
+ * (xbase,ybase) is the run and the rise of the line that the text is
+ * written along. For regular text at an angle, set xup = -ybase
+ * and yup = xbase. Setting it to something different will result in
+ * skewed text (which may be what you want.) Text written from bottom to
+ * top at a 90 degree angle would have the following parameters
+ * xup=-1, yup=0, xbase=0, ybase=1
+ *
+ * This function adds the Orientation to the metafile every time.
+ * It does not follow the normal -1 for no change, although if you
+ * put in the same numbers it won't re-add it to the meta file.
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+ octet_count = 0;
+
+ if (!cdcomhead(es, 5, 16, 8)) return 0;
+ es +=2; octet_count += 2;
+
+ /* In the metafile it is a 16 bit signed integer */
+ /* add xup */
+ es += cdAppShort(es, (short int) xup);
+ octet_count += 2;
+ /* add the rest */
+ es += cdAppShort(es, (short int) yup);
+ octet_count += 2;
+ es += cdAppShort(es, (short int) xbase);
+ octet_count += 2;
+ es += cdAppShort(es, (short int) ybase);
+ octet_count += 2;
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+}
+
+int cdSetLineAttrib(cdImagePtr im, int lntype, int lnwidth, int lncolor) {
+/* Spits out the attributes of lines. These attributes stay in effect
+ * until changed, so you don't have to output them every time.
+ */
+
+ if (!cdSetLineType(im, lntype)) return 0;
+ if (!cdSetLineWidth(im, lnwidth)) return 0;
+ if (!cdSetLineColor(im, lncolor)) return 0;
+
+ return 1;
+
+}
+
+int cdSetShapeFillAttrib(cdImagePtr im, int instyle, int incolor, int inhatch) {
+/* Spits out the attributes for the interior of filled-area elements.
+ * These attributes stay in effect until changed, so you don't have to output
+ * them every time.
+ * Set the following attributes:
+ * Interior Style: (integers 0-6, corresponding to: hollow, solid,
+ * [not pattern], hatch, empty, [not geometric pattern],
+ * interpolated.)
+ * Fill Colour: (index into the color table)
+ * Hatch Index: (integers 1-6, corresponding to: horizontal lines,
+ * vertical lines, pos. slope parallel lines,
+ * neg. slope parallel lines, horizontal/vertical
+ * crosshatch, positive/negative slope crosshatch)
+ */
+ if (!cdSetFillStyle(im, instyle)) return 0;
+ if (!cdSetFillColor(im, incolor)) return 0;
+ if (!cdSetFillHatch(im, inhatch)) return 0;
+
+ return 1;
+}
+
+int cdSetShapeEdgeAttrib(cdImagePtr im, int edtype, int edwidth, int edcolor, int edvis) {
+/* Spits out the attributes for the edges of filled-area elements. It may
+ * seem logical that these would be the same as the corresponding line
+ * attributes, but this is not the case.
+ * These attributes stay in effect until changed, so you don't have to output
+ * them every time.
+ * Set the following attributes:
+ * Edge Type (integers 1-5, corresponding to: solid, dash, dot,
+ * dash-dot, dash-dot-dot. These are the same as those used
+ * for line type.)
+ * Edge Width (should be the same as line width)
+ * Edge Colour (index into the color table)
+ * Edge Visibility (integer 0 or 1, corresponding to: Off, On)
+ */
+ if (!cdSetEdgeType(im, edtype)) return 0;
+ if (!cdSetEdgeWidth(im, edwidth)) return 0;
+ if (!cdSetEdgeColor(im, edcolor)) return 0;
+ if (!cdSetEdgeVis(im, edvis)) return 0;
+
+ return 1;
+}
+
+int cdSetTextAttrib(cdImagePtr im, int font, int color, int height) {
+/* Set the attributes of text. the font is an integer pointer into the
+ * font list where:
+ * 1 Times
+ * 2 Times Bold
+ * 3 Times Italic
+ * 4 Times Bold Italic
+ * 5 Helvetica
+ * 6 Helvetica Bold
+ * 7 Helvetica Italic
+ * 8 Helvetica Bold Italic
+ * color is an index into the colortable which is the color of the text
+ * size is the approximate size you want the text written in.
+ */
+
+ if(!cdSetTextFont(im, font)) return 0;
+ if(!cdSetTextColor(im, color)) return 0;
+ if(!cdSetTextHeight(im, height)) return 0;
+
+ return 1;
+}
+
+
+int cdImageDestroy(cdImagePtr im)
+/* gej: should work, unless I make changes to cdImage Struct */
+{
+ if (im->elemlist) {
+ free(im->elemlist);
+ }
+ free(im);
+
+ return 1;
+}
+
+int cdImageColorClosest(cdImagePtr im, int r, int g, int b)
+/* From gd library, see README file for copyright information */
+/* gej: should work unchanged */
+/* gej: 5/96, changed the colors to use short int */
+{
+ short int i;
+ long rd, gd, bd;
+ int ct = (-1);
+ long mindist = 0;
+ for (i=0; (i<(im->colorsTotal)); i++) {
+ long dist;
+ if (im->open[i]) {
+ continue;
+ }
+ rd = (im->red[i] - r);
+ gd = (im->green[i] - g);
+ bd = (im->blue[i] - b);
+ dist = rd * rd + gd * gd + bd * bd;
+ if ((i == 0) || (dist < mindist)) {
+ mindist = dist;
+ ct = i;
+ }
+ }
+ return ct;
+}
+
+int cdImageColorClear(cdImagePtr im) {
+/* mark all entries in the color table as open */
+ short int i;
+ for (i=0; (i<(cdMaxColors)); i++) {
+ im->open[i] = 1;
+ }
+ return 1;
+}
+
+int cdImageColorExact(cdImagePtr im, int r, int g, int b)
+/* From gd library, see README file for copyright information */
+/* gej: should work unchanged */
+/* gej: 5/96, changed colors to work with short ints */
+{
+ short int i;
+ for (i=0; (i<(im->colorsTotal)); i++) {
+ if (im->open[i]) {
+ continue;
+ }
+ if ((im->red[i] == r) &&
+ (im->green[i] == g) &&
+ (im->blue[i] == b)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static int cdImageAddColor(cdImagePtr im, int ct, int r, int g, int b)
+/* adds a color to the cgm file. Does not allocate it in the
+ * cdImagePtr object. Use cdImageColorAllocate, not this one.
+ */
+{
+ unsigned char *cts, *ctsp; /* GEJ: color table attribute */
+ int octet_count; /* GEJ: octet count */
+ /*
+ * Attribute: Colour Table; Elem Class 5; Elem ID 34
+ * two parameters P1: Starting colour table index (1 octet, UI)
+ * P2: list of direct colour values 3-tuples (3 one-octet values)
+ */
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ cts = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!cts) return -1; /* memory allocation failed */
+ ctsp=cts;
+ *ctsp = *ctsp | b6 | b4; /* set elem class to 5 */
+ *ctsp = *ctsp | b2; /* set elem id to 34 */
+ ctsp++;
+ *ctsp = *ctsp | b6;
+ *ctsp = *ctsp | b2; /* set param list len to 4 */
+ ctsp++;
+ octet_count = 2; /* so far */
+ /* now fill in the index number */
+ *ctsp = (unsigned char) 0377 & ct; /* mask off last 8 bits and put in ctsp*/
+ ctsp++;octet_count++;
+ /* now fill in the RGB values */
+ *ctsp = (unsigned char) 0377 & r; /* mask off last 8 bits and put in ctsp*/
+ ctsp++;octet_count++;
+ *ctsp = (unsigned char) 0377 & g; /* mask off last 8 bits and put in ctsp*/
+ ctsp++;octet_count++;
+ *ctsp = (unsigned char) 0377 & b; /* mask off last 8 bits and put in ctsp*/
+ ctsp++;octet_count++;
+ /* add it to the buffer */
+ if (cdAddElem(im, cts, octet_count)) {
+ free(cts);
+ return 1;
+ }
+ else {
+ free(cts);
+ return -1;
+ }
+
+
+}
+
+int cdImageColorAllocate(cdImagePtr im, int r, int g, int b)
+/* From gd library, see README file for copyright information
+ * gej: modified to allocate the color in the CGM buffer as well
+ * as the color table */
+/* gej: 5/96, modified to use short ints for colors */
+{
+ short int i;
+ short int ct = (-1);
+ for (i=0; (i<(im->colorsTotal)); i++) {
+ if (im->open[i]) {
+ ct = i;
+ break;
+ }
+ }
+ if (ct == (-1)) {
+ ct = im->colorsTotal;
+ if (ct == cdMaxColors) {
+ return -1;
+ }
+ im->colorsTotal++;
+ }
+ im->red[ct] = (short int) r;
+ im->green[ct] = (short int) g;
+ im->blue[ct] = (short int) b;
+ im->open[ct] = (short int) 0;
+ /* GEJ: Now we have successfully alocated it in the color table
+ * so let's put it in the CGM as well.
+ */
+ if (!cdImageAddColor(im, ct, r, g, b) ) {
+ return -1;
+ }
+ else {
+ return ct;
+ }
+
+}
+
+int cdImageColor16(cdImagePtr im) {
+/* allocate the 16 basic colors in the windows pallete */
+ if( -1 == cdImageColorAllocate(im, 255, 255, 255)) return 0;
+ if( -1 == cdImageColorAllocate(im, 0, 0, 0)) return 0;
+ if( -1 == cdImageColorAllocate(im, 128, 0, 0)) return 0;
+ if( -1 == cdImageColorAllocate(im, 0, 128, 0)) return 0;
+ if( -1 == cdImageColorAllocate(im, 128, 128, 0)) return 0;
+ if( -1 == cdImageColorAllocate(im, 0, 0, 128)) return 0;
+ if( -1 == cdImageColorAllocate(im, 128, 0, 128)) return 0;
+ if( -1 == cdImageColorAllocate(im, 0, 128, 128)) return 0;
+ if( -1 == cdImageColorAllocate(im, 128, 128, 128)) return 0;
+ if( -1 == cdImageColorAllocate(im, 192, 192, 192)) return 0;
+ if( -1 == cdImageColorAllocate(im, 255, 0, 0)) return 0;
+ if( -1 == cdImageColorAllocate(im, 0, 255, 0)) return 0;
+ if( -1 == cdImageColorAllocate(im, 255, 255, 0)) return 0;
+ if( -1 == cdImageColorAllocate(im, 0, 0, 255)) return 0;
+ if( -1 == cdImageColorAllocate(im, 255, 0, 255)) return 0;
+ if( -1 == cdImageColorAllocate(im, 0, 255, 255)) return 0;
+
+ return 1;
+
+}
+
+int cdImageColorDeallocate(cdImagePtr im, int color)
+/* From gd library, see README file for copyright information */
+/* gej: should work unchanged */
+{
+ /* Mark it open. */
+ /*im->open[color] = 1;*/
+ /* gej: really can't work, we are not allowing redefinition
+ * of color table entries */
+ return 0;
+}
+
+int cdLine(cdImagePtr im, int x1, int y1, int x2, int y2)
+/* Graphic Primitive: Polyline; Elem Class 4; Elem ID 1
+ * Actually generate the line, if you are writing a program to use this
+ * library, use this function, not cdImageLine or cdImageDashedLine,
+ * those are just in for compatiblilty with gd
+ *
+ * This function will draw a line using the current line type, width, and color
+ */
+{
+
+ unsigned char *es, *esp;
+ int octet_count;
+ short int sweet;
+ short int sour;
+
+ /* check to make sure the line is withing the scope of the picture
+ * ie. the values you give for drawing the line are within
+ * the values you created the picture with */
+ if (!(cdImageBoundsSafe(im, x1,y1)) || !(cdImageBoundsSafe(im, x2,y2)))
+ return 0;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ if (!cdcomhead(es, 4, 1, 8)) return 0;
+ es += 2;
+ octet_count = 2;
+
+ /* now we are ready for the parameter data */
+ sweet = (short int) x1;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) y1;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) x2;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) y2;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ octet_count++;
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+
+}
+
+int cdRectangle(cdImagePtr im, int x1, int y1, int x2, int y2) {
+/* Graphic Primitive: rectangle; Elem Class 4; Elem ID 11
+ * Actually generate the rectangle, if you are writing a program to use this
+ * library, use this function, not cdImageRectangle,
+ * those are just in for compatiblilty with gd
+ *
+ * This function will draw a Rectangle using the current
+ * edge type, width, color, and visibility, and the current
+ * fill style, color, and hatch
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+ short int sweet;
+ short int sour;
+
+ /* check to make sure the line is withing the scope of the picture
+ * ie. the values you give for drawing the line are within
+ * the values you created the picture with */
+ if (!(cdImageBoundsSafe(im, x1,y1)) || !(cdImageBoundsSafe(im, x2,y2)))
+ return 0;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ /* their are four 16 bit signed integers as attributes */
+ if (!cdcomhead(es, 4, 11, 8)) return 0;
+ es +=2; octet_count = 2;
+
+ /* now we are ready for the parameter data */
+ sweet = (short int) x1;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) y1;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) x2;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) y2;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ octet_count++;
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+
+}
+
+int cdCircle(cdImagePtr im, int cx, int cy, int r) {
+/* Graphic Primitive: circle; Elem Class 4; Elem ID 12
+ * cx,cy is the center of the circle, r is the radius
+ *
+ * This function will draw a Circle using the current
+ * edge type, width, color, and visibility, and the current
+ * fill style, color, and hatch
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+ short int sweet;
+ short int sour;
+
+ /* check to make sure the circle is withing the scope of the picture
+ * ie. the values you give for drawing the circle are within
+ * the values you created the picture with */
+ if (!(cdImageBoundsSafe(im, cx,cy)))
+ return 0;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ /* their are three 16 bit signed integers as attributes */
+ if (!cdcomhead(es, 4, 12, 6)) return 0;
+ es +=2; octet_count = 2;
+
+ /* now we are ready for the parameter data */
+ sweet = (short int) cx;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) cy;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) r;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ octet_count++;
+
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+
+}
+
+int cdArc3Pt(cdImagePtr im, int sx,int sy, int ix,int iy, int ex,int ey) {
+/* Graphic Primitive: Cicular Arc 3 Point; Elem Class 4; Elem ID 13
+ *
+ * This function will draw a Circular Arc using the current
+ * Line type, width, and color,
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+ short int sweet;
+ short int sour;
+
+ /* check to make sure the line is withing the scope of the picture
+ * ie. the values you give for drawing the line are within
+ * the values you created the picture with */
+ if (!(cdImageBoundsSafe(im, sx,sy)) || !(cdImageBoundsSafe(im, ix,iy)) || !(cdImageBoundsSafe(im, ex, ey)))
+ return 0;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ /* their are six 16 bit signed integers as attributes */
+ if (!cdcomhead(es, 4, 13, 12)) return 0;
+ es +=2; octet_count = 2;
+
+ /* now we are ready for the parameter data */
+ sweet = (short int) sx;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) sy;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) ix;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) iy;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) ex;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ es++; octet_count++;
+ sweet = (short int) ey;
+ sour = sweet >> 8;
+ *es = *es | (sour & 0377);
+ es++; octet_count++;
+ *es = (unsigned char) sweet;
+ octet_count++;
+
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+}
+
+int cdArc3PtClose(cdImagePtr im, int sx,int sy, int ix,int iy, int ex,int ey, int cl) {
+/* Graphic Primitive: Cicular Arc 3 Point Close; Elem Class 4; Elem ID 14
+ *
+ * This function will draw a Circle using the current
+ * edge type, width, color, and visibility, and the current
+ * fill style, color, and hatch
+ *
+ * cd is the closure type. It can be either 0 for pie closure or
+ * 1 for chord closure.
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+
+ /* check to make sure the line is withing the scope of the picture
+ * ie. the values you give for drawing the line are within
+ * the values you created the picture with */
+ if (!(cdImageBoundsSafe(im, sx,sy)) || !(cdImageBoundsSafe(im, ix,iy)) || !(cdImageBoundsSafe(im, ex, ey)))
+ return 0;
+
+ /* make sure that they close the arc either with pie (0) or chord (1) */
+ if ((cl != 0) && (cl != 1))
+ return 0;
+
+ /* allocate sufficent space. should be 32 bits * 6 to be safe */
+ es = (unsigned char *) calloc(4*6, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ /* their are seven 16 bit signed integers as attributes */
+ if (!cdcomhead(es, 4, 14, 14)) return 0;
+ es +=2; octet_count = 2;
+
+ /* now we are ready for the parameter data */
+ octet_count += cdAppShort(es, (short int) sx);
+ es +=2;
+ octet_count += cdAppShort(es, (short int) sy);
+ es +=2;
+ octet_count += cdAppShort(es, (short int) ix);
+ es +=2;
+ octet_count += cdAppShort(es, (short int) iy);
+ es +=2;
+ octet_count += cdAppShort(es, (short int) ex);
+ es +=2;
+ octet_count += cdAppShort(es, (short int) ey);
+ es +=2;
+ octet_count += cdAppShort(es, (short int) cl);
+ es +=2;
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+}
+
+int cdEllipse(cdImagePtr im, int cx,int cy, int d1x,int d1y, int d2x,int d2y ) {
+/* Graphic Primitive: Ellipse; Elem Class 4; Elem ID 17
+ *
+ * This function will draw an Ellipse using the current
+ * edge type, width, color, and visibility, and the current
+ * fill style, color, and hatch
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+
+ /* check to make sure the line is withing the scope of the picture
+ * ie. the values you give for drawing the line are within
+ * the values you created the picture with */
+ if (!(cdImageBoundsSafe(im, cx,cy)) || !(cdImageBoundsSafe(im, d1x,d1y)) || !(cdImageBoundsSafe(im, d2x, d2y)))
+ return 0;
+
+ /* allocate sufficent space. should be 32 bits * 4 to be safe */
+ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ /* their are six 16 bit signed integers as attributes */
+ if (!cdcomhead(es, 4, 17, 12)) return 0;
+ es +=2; octet_count = 2;
+
+ /* now we are ready for the parameter data */
+ octet_count += cdAppShort(es, (short int) cx);
+ es +=2;
+ octet_count += cdAppShort(es, (short int) cy);
+ es +=2;
+ octet_count += cdAppShort(es, (short int) d1x);
+ es +=2;
+ octet_count += cdAppShort(es, (short int) d1y);
+ es +=2;
+ octet_count += cdAppShort(es, (short int) d2x);
+ es +=2;
+ octet_count += cdAppShort(es, (short int) d2y);
+ es +=2;
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+
+}
+
+int cdPolygon(cdImagePtr im, cdPointPtr p, int n) {
+/* Graphic Primitive: Polygon; Elem Class 4; Elem ID 7
+ *
+ * cdPointPtr is defined in cd.h, basically, it is two arrays of integers
+ * p[m].x and p[m].y containing the x and y values respectively. n
+ * is the number of points in this array (not the index of the last point,
+ * which is n-1). n must be at least 3 (otherwise
+ * you really don't have much of a polygon, it is closer to a line.)
+ *
+ * This function will draw a Polygon using the current
+ * edge type, width, color, and visibility, and the current
+ * fill style, color, and hatch
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+ int x; /* counter */
+
+ if (n < 3) return 0; /* it is either a point or a line */
+
+ if (n < 8) {
+ /* It fits in the short form of the command, lets us
+ * add it right now, shall we? */
+ /* allocate sufficent space. Should be 32 bits*10 to be safe */
+ es = (unsigned char *) calloc(4*10,SIZEOF(unsigned char ));
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+
+ /* their are n*2 16 bit signed integers as attributes */
+ if (!cdcomhead(es, 4, 7, (n*4))) return 0;
+ es +=2; octet_count = 2;
+
+ }
+ else if (n < 8191) {
+ /* there are more than 7 points in it, that sucks */
+ /* gej, so basically, for this one, I set the header
+ * to cdcomhead(es, 4, 7, 31) then write a function for the long
+ * form that takes the first 15 bits of n and tags a 0 in front
+ * of it and puts it in es, than I do the for loop all over again
+ * that doesn't seem too hard. But I will leave that for another
+ * day.
+
+ * keep in mind that if CDGROWLISTSIZE is smaller than n*4
+ * (at most 32769) then things could fail in a most unsavory fashion.
+ */
+ /* allocate sufficent space. 32 bits*(n+1) to be safe */
+ es = (unsigned char *) calloc(4*(n+1), SIZEOF(unsigned char ));
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ if (!cdcomheadlong(es, 4, 7, (n*4))) return 0;
+ es +=4; octet_count = 4;
+ }
+ else {
+ /* there are more than 8191 points in it, I am not going to implement
+ * that, if you want it that bad, do it yourself. */
+
+ printf("Writing %d points\n",n);
+
+
+ /* allocate sufficent space. 32 bits*(n+1) to be safe */
+ esp = (unsigned char *) calloc(4*(n+1), SIZEOF(unsigned char ));
+ if (!esp) return 0; /* memory allocation failed */
+ es=esp;
+
+ if (!cdcomheadlongp(es, 4, 7)) return 0;
+ es +=2; octet_count = 2;
+
+ if (!cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ return 0;
+ }
+
+ while(n>8191) {
+ es=esp;
+
+ if (!cdcomheadlongc(es, 1,8191*4)) return 0;
+ es +=2; octet_count = 2;
+
+
+ for (x=0; x<8191; x++) {
+ /* now we are ready for the parameter data */
+ es += cdAppShort(es, (short int) p->x);
+ es += cdAppShort(es, (short int) p->y);
+ octet_count += 4;
+ p++;
+ }
+
+ /* add it to the buffer */
+ if (!cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ return 0;
+ }
+
+ n-=8191;
+ printf("Done 8191 have left %d\n",n);
+ }
+ printf("doing last %d normally\n",n);
+
+ es=esp;
+
+ if (!cdcomheadlongc(es, 0, (n*4))) return 0;
+ es +=2; octet_count = 2;
+
+
+ }
+
+
+ for (x=0; x<n; x++) {
+ /* now we are ready for the parameter data */
+ es += cdAppShort(es, (short int) p->x);
+ es += cdAppShort(es, (short int) p->y);
+ octet_count += 4;
+ p++;
+ }
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+}
+
+int cdPolyLine(cdImagePtr im, cdPointPtr p, int n) {
+/* Graphic Primitive: Polyline; Elem Class 4; Elem ID 1
+ *
+ * cdPointPtr is defined in cd.h, basically, it is two arrays of integers
+ * p[m].x and p[m].y containing the x and y values respectively. n
+ * is the number of points in this array (not the index of the last point,
+ * which is n-1). if n is 2, it is a regular line, like cdline
+ *
+ * This function will draw a Polyline using the current
+ * line type, width, color, and visibility,
+ */
+ unsigned char *es, *esp;
+ int octet_count;
+ int x; /* counter */
+
+ if (n < 2) return 0; /* it is a point */
+
+ if (n < 8) {
+ /* It fits in the short form of the command, lets us
+ * add it right now, shall we? */
+ /* allocate sufficent space. Should be 32 bits*10 to be safe */
+ es = (unsigned char *) calloc(4*10,SIZEOF(unsigned char ));
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+
+ /* their are n*2 16 bit signed integers as attributes */
+ if (!cdcomhead(es, 4, 1, (n*4))) return 0;
+ es +=2; octet_count = 2;
+
+ }
+ else if (n < 8191) {
+ /* there are more than 7 points in it, that sucks */
+ /* gej, so basically, for this one, I set the header
+ * using the long version cdcomheadlong(es, 4, 1, n*4)
+
+ * keep in mind that if CDGROWLISTSIZE is smaller than n*4
+ * (at most 32769) then the list may have to grow several times
+ */
+ /* allocate sufficent space. 32 bits*(n+1) to be safe */
+ es = (unsigned char *) calloc(4*(n+1), SIZEOF(unsigned char ));
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ if (!cdcomheadlong(es, 4, 1, (n*4))) return 0;
+ es +=4; octet_count = 4;
+ }
+ else {
+ /* there are more than 8191 points in it, I am not going to implement
+ * that, if you want it that bad, do it yourself. */
+ return 0;
+ }
+
+
+ for (x=0; x<n; x++) {
+ /* now we are ready for the parameter data */
+ es += cdAppShort(es, (short int) p->x);
+ es += cdAppShort(es, (short int) p->y);
+ octet_count += 4;
+ p++;
+ }
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+}
+
+int cdText(cdImagePtr im, int x, int y, const char *ts) {
+/* Graphic Primitive: Text; Elem Class 4; Elem ID 4
+ * add text to the picture. Start it at the point (x,y)
+ * this should be the lower left corner of where the text is
+ * the parameters are point, enumerated(set to 1), string
+ *
+ * String encoding in CGM is a little strange. After you have the other
+ * parameter info, the first octet for the string is either 0..254 which
+ * is the number of octets of string data, or 255 which signifies a long
+ * string. if it is 255 then the next 16 bits indicate the length of the
+ * string. the first bit (bit15) is 0 if this is the last part of the
+ * string and 1 if another part follows it. the next 15 bits are in the
+ * range 0..32767 and are the number of octets of string info following.
+ * so the length stored in the command header is the whole enchelada.
+ */
+ int tslen, curly;
+ unsigned char *es, *esp;
+ int octet_count;
+
+ /* check to make sure the Text is within the scope of the picture
+ * actually, I am only checking the start of it
+ */
+ if (!(cdImageBoundsSafe(im, x, y)))
+ return 0;
+
+ /* allocate sufficent space. should be tslen+ 32 bits * 4 to be safe */
+ tslen = strlen(ts);
+
+ /* if there are more than 32700 characters fail
+ * gej: this could go as high as 32767 I think, but lets
+ * cut it off at 32700 */
+ if ((tslen > 32700) || (tslen < 0))return 0;
+
+ es = (unsigned char *) calloc( ((4*4)+tslen), SIZEOF(unsigned char ) );
+ if (!es) return 0; /* memory allocation failed */
+ esp=es;
+
+ if (!cdcomheadlong(es, 4, 4, 9+tslen)) return 0;
+ es +=4; octet_count = 4;
+
+ /* add the x position, the y position, then 1, which signifies
+ * that this is all the text, there is none appended after it */
+ es += cdAppShort(es, (short int) x);
+ es += cdAppShort(es, (short int) y);
+ es += cdAppShort(es, (short int) 1);
+ octet_count += 6;
+
+ /* now take care of the string information, for strings 254 bytes
+ * or less, I could use a short one, but why bother, use the long
+ * form for everything */
+ es += cdAppByte(es, (short int) 255);
+ es += cdAppShort(es, (short int) tslen);
+ octet_count += 3;
+ /* gej: I should set bit 15 to 0 because it is the final part of a
+ * string but I am not going to since I already checked that it was
+ * a 16 number that was non-negative */
+
+ while(*ts) {
+ *es++ = (unsigned char) *ts++;
+ }
+ octet_count +=tslen;
+ /* now if the octet_count is not divisible by 4 add null padding */
+ curly = 4 - (octet_count % 4);
+ if (curly % 4) {
+ octet_count += curly;
+ es += cdAppNull(es, curly);
+ }
+
+ /* add it to the buffer */
+ if (cdAddElem(im, esp, octet_count)) {
+ free(esp);
+ return 1;
+ }
+ else {
+ free(esp);
+ return 0;
+ }
+
+}
+
+int cdImageLine(cdImagePtr im, int x1, int y1, int x2, int y2, int color)
+/* gej: this should be so much easier to do as a cgm
+ * This is in for compatibility with gd, if you don't need that, use
+ * cdLine instead */
+{
+ int ltstate;
+
+
+ /* save the linetype state */
+ ltstate = im->ltype;
+ /* set the attributes of the line */
+ if (!cdSetLineAttrib(im, 1, -1, color)) return 0;
+ if (!cdLine(im, x1, y1, x2, y2)) return 0;/* draw the line */
+ /* restore the state If it fails, don't return an error, because
+ * the line was still drawn */
+ cdSetLineType(im, ltstate);
+
+ return 1;
+}
+
+int cdImageDashedLine(cdImagePtr im, int x1, int y1, int x2, int y2, int color)
+/* gej: this should be so much easier to do as a cgm
+ * in order to really get a dashed line you must call cdSetLineType first
+ * This is in for compatibility with gd, if you don't need that, use
+ * cdLine instead */
+{
+ /* set the attributes of the line */
+ if (!cdSetLineAttrib(im, -1, -1, color)) return 0;
+ /* generate the line */
+ if (!cdLine(im, x1, y1, x2, y2)) return 0;
+
+ /* everthing is A-OK */
+ return 1;
+}
+
+int cdImageBoundsSafe(cdImagePtr im, int x, int y)
+/* From gd library, see README file for copyright information */
+/* gej: this should work unchanged */
+{
+ return (!(((y < 0) || (y >= im->sy)) ||
+ ((x < 0) || (x >= im->sx))));
+}
+
+
+int cdImageRectangle(cdImagePtr im, int x1, int y1, int x2, int y2, int color)
+/* Graphic Primitive: rectangle; Elem Class 4; Elem ID 11
+ */
+
+/* gej: but I think I will use the cgm rectangle */
+{
+ if(!cdImageLine(im, x1, y1, x2, y1, color)) return 0;
+ if(!cdImageLine(im, x1, y2, x2, y2, color)) return 0;
+ if(!cdImageLine(im, x1, y1, x1, y2, color)) return 0;
+ if(!cdImageLine(im, x2, y1, x2, y2, color)) return 0;
+
+ return 1;
+}