/* 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; }