From 43a13e2e02f2b92d912541ae3477b78f7ebd305c Mon Sep 17 00:00:00 2001 From: root <> Date: Sun, 8 Feb 2009 17:13:33 +0000 Subject: *** empty log message *** --- src/cd/cd.c | 2372 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2372 insertions(+) create mode 100644 src/cd/cd.c (limited to 'src/cd/cd.c') 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 + 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 +#include +#include +#include +#include +#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> 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; xx); + 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; xx); + 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; +} -- cgit v1.2.3