• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

cd.c

Go to the documentation of this file.
00001 
00002 // cd.c main file for cgmdraw module.
00003 //
00004 //      Written by G. Edward Johnson <mailto:lorax@nist.gov>
00005 //      Date: April 1996
00006 //      Copyright: cd software produced by NIST, an agency of the
00007 //      U.S. government, is by statute not subject to copyright
00008 //      in the United States. Recipients of this software assume all
00009 //      responsibilities associated with its operation, modification
00010 //      and maintenance.
00011 //
00012 //      Portions of this package are from the gd package written by
00013 //      Thomas Boutell and are copyright 1994, 1995, Quest Protein
00014 //      Database Center, Cold Spring Harbor Labs.  They are marked in the
00015 //      source code.
00016 //
00017 
00018 #ifndef NOMALLOCH
00019 #include <malloc.h>
00020 #endif
00021 #include <stdio.h>
00022 #include <math.h>
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include "defines.h"
00026 #include "cd.h"
00027 
00028 
00029 static int cdImageAddColor( cdImagePtr im, int si, int ei );
00030 
00031 cdImagePtr cdImageCreate( int sx, int sy )
00032 // Creates a new image of size (sx,sy).  Most people should always
00033 // start by calling this function
00034 {
00035     cdImagePtr im;
00036 
00037     im = cdImageStartCgm();
00038     if ( !im )
00039         return 0;          // memory allocation failed
00040     if ( !cdImageSetSize( im, sx, sy ) )
00041     {
00042         free( im ); return 0;
00043     }
00044 
00045     if ( !cdCgmHeader( im ) )
00046     {
00047         free( im ); return 0;
00048     }
00049 
00050     if ( cdCgmPic( im, 0 ) )
00051     {
00052         return im;
00053     }
00054     else
00055     {
00056         free( im );
00057         return 0;
00058     }
00059 }
00060 
00061 static int cdAppNull( unsigned char *es, int x )
00062 {
00063 // put x  nulls in the string.
00064 // return value is number of octets added (1)
00065     int y;
00066 
00067     for ( y = 0; y < x; y++ )
00068     {
00069         *es = '\0';
00070         es++;
00071     }
00072     return x;
00073 }
00074 
00075 static int cdAppByte( unsigned char *es, short int addme )
00076 {
00077 // Append an octet to the end of es
00078 // Return value is number of octets added
00079 // for internal cd functions only, do not call
00080 //
00081     *es = (unsigned char) addme & 0377;
00082     return 1;
00083 }
00084 
00085 static int cdAppShort( unsigned char *es, short int addme )
00086 {
00087 // Append a short to the end of es
00088 // return value is number of octets added
00089 // For internal cd functions only, do not call!
00090 //
00091     short int temp;
00092 
00093     temp = addme >> 8;
00094     *es  = (unsigned char) temp & 0377;
00095     es++;
00096     *es = (unsigned char) addme & 0377;
00097     return 2;
00098 }
00099 
00100 // static int cdAppWord(unsigned char *es, int addme){
00101 // Append an word to es
00102 // Return value is number of octets added
00103 // For internal cd functions only, do not call!
00104 //
00105 //
00106 //      int temp;
00107 //      temp = addme >> 24;
00108 //es = (unsigned char) temp & 0377;
00109 //      es++;
00110 //      temp = addme >> 16;
00111 //es = (unsigned char) temp & 0377;
00112 //      es++;
00113 //      temp = addme >> 8;
00114 //es = (unsigned char) temp & 0377;
00115 //      es++;
00116 //es = (unsigned char) addme & 0377;
00117 //      es++;
00118 //      return 4;
00119 // }
00120 //
00121 
00122 static int cdcomhead( unsigned char *es, int elemclass, int id, int len )
00123 {
00124 // sets the command header in the first two bytes of string es
00125 // element class is in bits 15-12
00126 // element id is in bits 11-5
00127 // parameter list length is in bits 4-0
00128 //
00129     int temp;
00130 
00131     if ( !es )
00132         return 0;          // the string must be allocated first
00133 
00134     // set the element class
00135     *es = (unsigned char) elemclass << 4;
00136     // set the element id
00137     temp = 0177 & id;
00138     temp = temp >> 3;
00139     *es  = *es | temp;
00140     es++;
00141     id  = id << 5;
00142     *es = (unsigned char) id;
00143     *es = *es | (unsigned char) ( 037 & len );
00144 
00145     return 1;
00146 }
00147 
00148 static int cdcomheadlong( unsigned char *es, int elemclass, int id, int len )
00149 {
00150 // sets the command header for the long form.
00151 // first 16 bits:
00152 //  element class is in bits 15-12
00153 //  element id is in bits 11-5
00154 //  parameter list length is in bits 4-0 = 31
00155 // second 16 bits:
00156 //  bit 15 = 0  (for last partition)
00157 //  bit 14-0 param list len
00158 //
00159 
00160     // I'm lazy, call cdcomhead to set the first two bytes
00161     if ( !cdcomhead( es, elemclass, id, 31 ) )
00162         return 0;
00163     es += 2;
00164 
00165     // now set the second two bytes
00166     cdAppShort( es, (short int) len );
00167     *es = *es & 0177;     // make bit 15 = 0
00168     es += 2;
00169 
00170     return 1;
00171 }
00172 
00173 static int cdAddElem( cdImagePtr im, unsigned char *es, int octet_count )
00174 // adds a string, which is a CGM element to the elemlist.
00175 // This function is called by other functions in this library and
00176 // should NOT be called by users of the library
00177 // For internal cd functions only, do not call!
00178 //
00179 {
00180     unsigned char *newlist;     // in case memory allocation fails
00181     int           x;            // counter
00182 
00183     while ( ( octet_count + 1 ) >= im->bytestoend )
00184     {
00185         // not enough space, must grow elemlist
00186         im->listlen = im->listlen + CDGROWLISTSIZE;
00187         newlist     = (unsigned char *) realloc( im->elemlist, SIZEOF( unsigned char ) * im->listlen );
00188         if ( newlist )
00189         {
00190             // successfully allocated memory
00191             im->elemlist    = newlist;
00192             im->bytestoend  = im->bytestoend + CDGROWLISTSIZE;
00193             im->curelemlist = im->elemlist + ( im->listlen - im->bytestoend );
00194         }
00195         else
00196         {
00197             // memory allocation failed, save yurself
00198             im->listlen = im->listlen - CDGROWLISTSIZE;
00199             return 0;
00200         }
00201     }
00202 
00203     // ok, if we get to here, there is enough space, so add it.
00204     for ( x = 0; x < octet_count; x++ )
00205     {
00206         *im->curelemlist = (unsigned char) *es;
00207         im->curelemlist++;
00208         es++;
00209     }
00210     im->bytestoend = im->bytestoend - octet_count;
00211     return 1;
00212 }
00213 
00214 int cdCgmHeader( cdImagePtr im )
00215 {
00216 // add the cgm header to the imagepointer's  element list
00217 // do it all in a string than call cdAddElem on it
00218 // For internal cd functions only, do not call!
00219 //
00220     unsigned char       *headerp;
00221     unsigned char       *head;
00222     const unsigned char *buf, *buf2;
00223     int octet_count = 0;
00224     int blen;                 // length of buf
00225     int curly;
00226     int fontlistlen;          // each font in the font list is stored as a string,
00227     // with a single octet in front of the string
00228     // giving its length, fontlistlen is the sum of
00229     // the lengths of all the font strings + the
00230     // length octets.
00231 
00232     if ( im->state != 0 )
00233         return 0;
00234     headerp = (unsigned char *) calloc( 1024, SIZEOF( unsigned char ) );
00235     if ( !headerp )
00236         return 0;               // memory allocation failed
00237     head = headerp;
00238 
00239     //** Attribute: BegMF; Elem Class 0; Elem ID 1
00240     buf  = (const unsigned char *) "cd: CgmDraw Library";
00241     blen = strlen( (const char *) buf );
00242     cdcomhead( head, 0, 1, blen + 1 );
00243     head += 2;
00244     head += cdAppByte( head, (short int) blen );
00245     buf2  = buf;
00246     while ( *buf2 )
00247     {
00248         *head++ = *buf2++;
00249     }
00250     octet_count += ( blen + 3 );
00251     curly        = 4 - ( octet_count % 4 );
00252     if ( curly % 4 )
00253     {
00254         octet_count += curly;
00255         head        += cdAppNull( head, curly );
00256     }
00257 
00258     //** Attribute: MFVersion; Elem Class 1; Elem ID 1
00259     cdcomhead( head, 1, 1, 2 );
00260     head        += 2;
00261     head        += cdAppShort( head, (short int) 1 );
00262     octet_count += 4;
00263 
00264     //** Attribute: MFDesc; Elem Class 1; Elem ID 2
00265     blen = strlen( (char *) im->desc );
00266     cdcomheadlong( head, 1, 2, blen + 1 );
00267     head += 4;
00268     head += cdAppByte( head, (short int) blen );
00269     buf2  = im->desc;
00270     while ( *buf2 )
00271     {
00272         *head++ = *buf2++;
00273     }
00274     octet_count += ( blen + 5 );
00275     curly        = 4 - ( octet_count % 4 );
00276     if ( curly % 4 )
00277     {
00278         octet_count += curly;
00279         head        += cdAppNull( head, curly );
00280     }
00281 
00282     //** Attribute: ColrPrec; Elem Class 1; Elem ID 7
00283     cdcomhead( head, 1, 7, 2 );
00284     head        += 2;
00285     head        += cdAppShort( head, (short int) 8 );
00286     octet_count += 4;
00287 
00288     //** Attribute: ColrIndexPrec; Elem Class 1; Elem ID 8
00289     cdcomhead( head, 1, 8, 2 );
00290     head        += 2;
00291     head        += cdAppShort( head, (short int) 8 );
00292     octet_count += 4;
00293 
00294     //** Attribute: MaxColrIndex; Elem Class 1; Elem ID 9
00295     cdcomhead( head, 1, 9, 1 );
00296     head        += 2;
00297     head        += cdAppByte( head, (short int) 255 );
00298     octet_count += 4; head++;
00299 
00300     //** Attribute: MFElemList; Elem Class 1; Elem ID 11
00301     // shorthand here.  1 means 1 element specified, (-1,1)
00302     // means drawing-plus-control set
00303     cdcomhead( head, 1, 11, 6 );
00304     head        += 2;
00305     head        += cdAppShort( head, (short int) 1 );
00306     head        += cdAppShort( head, (short int) -1 );
00307     head        += cdAppShort( head, (short int) 1 );
00308     octet_count += 8;
00309 
00310     //** Attribute: FontList; Elem Class 1; Elem ID 13
00311     // im->fontlist contains a comma separated list of font names
00312     // since we don't need the commas, and every font except one has
00313     // a comma, and we do need a length octet, that means that
00314     // taking the string length will give us one less than the
00315     // correct length.
00316     buf = im->fontlist;
00317     if ( buf )     // don't do this if there aren't any fonts
00318     {
00319         fontlistlen = strlen( (const char *) buf ) + 1;
00320         cdcomheadlong( head, 1, 13, fontlistlen );
00321         head += 4;
00322 
00323         while ( *buf )
00324         {
00325             blen = 0;
00326             buf2 = buf;
00327             while ( ( *buf ) && ( *buf != ',' ) )
00328             {
00329                 buf++;
00330                 blen++;
00331             }
00332             head += cdAppByte( head, (short int) blen );
00333             while ( buf2 < buf )
00334             {
00335                 *head++ = *buf2++;
00336             }
00337             if ( *buf )
00338             {
00339                 buf++;
00340             }
00341         }
00342         octet_count += ( 4 + fontlistlen );
00343         curly        = 4 - ( octet_count % 4 );
00344         if ( curly % 4 )
00345         {
00346             octet_count += curly;
00347             head        += cdAppNull( head, curly );
00348         }
00349     }     // end of check to see if any fonts
00350 
00351     if ( cdAddElem( im, headerp, octet_count ) )
00352     {
00353         free( headerp );
00354         headerp = 0;
00355         return 1;
00356     }
00357     else
00358     {
00359         free( headerp );
00360         return 0;
00361     }
00362 }
00363 
00364 
00365 int cdCgmPic( cdImagePtr im, int sticky )
00366 {
00367 // Start the picture.  if the sticky bit is set, set and use the defaults
00368 // of the previous picture.  Otherwise, reset all defaults.
00369 // Gej: sticky = 0 reset defaults, 1 dont reset anything, 2 only
00370 // reset the color table
00371 //
00372     unsigned char *headerp;
00373     unsigned char *head;
00374     unsigned char *buf, *buf2;
00375     char          *tb;
00376     int           octet_count = 0;
00377     int           blen;           // length of buf
00378     int           x1, x2, x3, x4; // needed for setting defaults
00379 
00380     if ( ( im->state != 0 ) && ( im->state != 2 ) )
00381         return 0;
00382     if ( ( sticky > 2 ) || ( sticky < 0 ) )
00383         return 0;                                     // invalid sticky bit
00384     // increment the picture number
00385     im->picnum++;
00386     tb = (char *) calloc( 4 * 4, SIZEOF( char ) );
00387     if ( !tb )
00388         return 0;         // memory allocation failed
00389     headerp = (unsigned char *) calloc( 1024, SIZEOF( unsigned char ) );
00390     if ( !headerp )
00391     {   // memory allocation failed
00392         free( tb );
00393         return 0;
00394     }
00395     head = headerp;
00396 
00397     //** Attribute: BegPic; Elem Class 0; Elem ID 3
00398     sprintf( tb, "picture %d", im->picnum );
00399     buf = (unsigned char *) tb;
00400     // buf = (unsigned char *) "picture 1";
00401     blen = strlen( (char *) buf );
00402     cdcomhead( head, 0, 3, blen + 1 );
00403     head += 2;
00404     head += cdAppByte( head, (short int) blen );
00405     buf2  = buf;
00406     while ( *buf2 )
00407     {
00408         *head++ = *buf2++;
00409     }
00410     free( tb );
00411     octet_count += ( blen + 3 );
00412     if ( !( blen % 2 ) )
00413     {
00414         octet_count++;
00415         head += cdAppNull( head, 1 );
00416     }
00417     if ( octet_count % 4 )
00418     {
00419         octet_count += 2;
00420         head        += cdAppNull( head, 2 );
00421     }
00422 
00423     //** Attribute: ColrMode; Elem Class 2; Elem ID 2
00424     cdcomhead( head, 2, 2, 2 );
00425     head        += 2;
00426     head        += cdAppShort( head, (short int) 0 );
00427     octet_count += 4;
00428     // Picture Descriptor: Line Width Specification Mode;
00429     // Elem Class 2; Elem ID 3
00430     if ( sticky && ( im->linespec != CDLINESPEC ) )
00431     {
00432         cdcomhead( head, 2, 3, 2 );
00433         head        += 2;
00434         head        += cdAppShort( head, (short int) im->linespec );
00435         octet_count += 4;
00436     }
00437     // Picture Descriptor: Marker Size Specification Mode;
00438     // Elem Class 2; Elem ID 4
00439     if ( sticky && ( im->markerspec != CDMARKERSPEC ) )
00440     {
00441         cdcomhead( head, 2, 4, 2 );
00442         head        += 2;
00443         head        += cdAppShort( head, (short int) im->markerspec );
00444         octet_count += 4;
00445     }
00446     // Picture Descriptor: Edge Width Specification Mode;
00447     // Elem Class 2; Elem ID 5
00448     if ( sticky && ( im->edgespec != CDEDGESPEC ) )
00449     {
00450         cdcomhead( head, 2, 5, 2 );
00451         head        += 2;
00452         head        += cdAppShort( head, (short int) im->edgespec );
00453         octet_count += 4;
00454     }
00455 
00456     //** Attribute: VDCExt; Elem Class 2; Elem ID 6
00457     cdcomhead( head, 2, 6, 8 );
00458     head        += 2;
00459     head        += cdAppShort( head, (short int) 0 );
00460     head        += cdAppShort( head, (short int) 0 );
00461     head        += cdAppShort( head, (short int) im->sx );
00462     head        += cdAppShort( head, (short int) im->sy );
00463     octet_count += 10;
00464 
00465     //** Attribute: Begin Picture Body; Elem Class 0; Elem ID 4
00466     cdcomhead( head, 0, 4, 0 );
00467     head        += 2;
00468     octet_count += 2;
00469 
00470     if ( cdAddElem( im, headerp, octet_count ) )
00471     {
00472         free( headerp );
00473     }
00474     else
00475     {
00476         free( headerp );
00477         return 0;
00478     }
00479 
00480     if ( sticky )
00481     {
00482         // keep defaults the way they are
00483         if ( sticky == 1 )
00484         {
00485             // keep the color table
00486             if ( cdImageAddColor( im, 0, im->colorsTotal - 1 ) == -1 )
00487             {
00488                 // no colortable
00489                 return 1;
00490             }
00491         }
00492         else
00493         {
00494             // Nuke the color table if there is one
00495             cdImageColorClear( im );
00496         }
00497         im->state = 1;
00498         x1        = im->ltype; x2 = im->lwidth; x3 = im->lcolor;
00499         im->ltype = CDLTYPE; im->lwidth = CDLWIDTH; im->lcolor = CDLCOLOR;
00500         if ( !cdSetLineAttrib( im, x1, x2, x3 ) )
00501             return 0;
00502 
00503         x1             = im->shapestyle; x2 = im->shapecolor; x3 = im->shapehatch;
00504         im->shapestyle = CDSHAPESTYLE; im->shapecolor = CDSHAPECOLOR;
00505         im->shapehatch = CDSHAPEHATCH;
00506         if ( !cdSetShapeFillAttrib( im, x1, x2, x3 ) )
00507             return 0;
00508 
00509         x1            = im->edgetype; x2 = im->edgewidth;
00510         x3            = im->edgecolor; x4 = im->edgevis;
00511         im->edgetype  = CDEDGETYPE; im->edgewidth = CDEDGEWIDTH;
00512         im->edgecolor = CDEDGECOLOR; im->edgevis = CDEDGEVIS;
00513         if ( !cdSetShapeEdgeAttrib( im, x1, x2, x3, x4 ) )
00514             return 0;
00515 
00516         x1             = im->textfont; x2 = im->textcolor; x3 = im->textheight;
00517         im->textfont   = CDTEXTFONT; im->textcolor = CDTEXTCOLOR;
00518         im->textheight = CDTEXTHEIGHT;
00519         if ( !cdSetTextAttrib( im, x1, x2, x3 ) )
00520             return 0;
00521 
00522         x1 = im->textpath; im->textpath = CDTEXTPATH;
00523         if ( !cdSetTextPath( im, x1 ) )
00524             return 0;
00525 
00526         x1        = im->mtype; x2 = im->msize; x3 = im->mcolor;
00527         im->ltype = CDMTYPE; im->lwidth = CDMSIZE; im->lcolor = CDMCOLOR;
00528         if ( !cdSetMarkerAttrib( im, x1, x2, x3 ) )
00529             return 0;
00530     }
00531     else
00532     {
00533         // reset all the defaults
00534         cdImageSetDefaults( im );
00535         // Nuke the color table if there is one
00536         cdImageColorClear( im );
00537         im->state = 1;         // now we are officially in the picture
00538     }
00539     return 1;
00540 }
00541 
00542 int cdCgmNewPic( cdImagePtr im, int sticky )
00543 // The CGM standard allows multiple images in a single file.  This function
00544 // will close the current picture, then open a new one.
00545 // if sticky is 0 then all attributes will be reset to the defaults
00546 // if sticky is 1 then all attributes will be inherited from the prevous
00547 // picture.
00548 // if sticky is 2 all attributes except the color table will be inherited
00549 // from the previous picture
00550 //
00551 {
00552     // close the current picture
00553     if ( !cdImageEndPic( im ) )
00554         return 0;
00555 
00556     // now start the new picture
00557     return ( cdCgmPic( im, sticky ) );
00558 }
00559 
00560 int cdImageCgm( cdImagePtr im, FILE *out )
00561 // Gej: Write the image to  file *out, which must be open already
00562 // does not close the file
00563 {
00564 //
00565 //      if (out) {
00566 //              im->outfile = out;
00567 //      }
00568 //
00569     cdImageSetOutput( im, out );
00570     return cdImageEndCgm( im );
00571 }
00572 
00573 
00574 int cdSetLineType( cdImagePtr im, int lntype )
00575 {
00576 // Attribute: Line Type; Elem Class 5; Elem ID 2
00577 // Set the line type.  Possible values are:
00578 // 1=solid, 2=dash, 3=dot, 4=dash-dot, 5=dash-dot-dot
00579 // Even though new ones can be defined, I am limiting lntype to these values
00580 // If you really need more, you can make the proper changes.
00581 //
00582     unsigned char *es, *esp;
00583     int           octet_count;
00584 
00585     // First check and see if the user doesn't want any changes,
00586     // if so, just return success
00587     if ( lntype == -1 )
00588         return 1;
00589 
00590     // Check and see if the value it is being set to is the current
00591     // value, if so, don't make any changes, just return 1
00592     if ( lntype == im->ltype )
00593         return 1;
00594 
00595     // Make sure that lntype is between 1 and 5
00596     if ( ( lntype < 1 ) || ( lntype > 5 ) )
00597         return 0;
00598 
00599     // allocate sufficent space.  should be 32 bits * 4 to be safe
00600     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
00601     if ( !es )
00602         return 0;          // memory allocation failed
00603     esp = es;
00604 
00605     if ( !cdcomhead( es, 5, 2, 2 ) )
00606     {
00607         free( esp ); return 0;
00608     }
00609     es += 2;
00610     // set Param_List_Len to 2 (signed int at index precision)
00611 
00612     // add in the value of lntype
00613     es += cdAppShort( es, (short int) lntype );
00614 
00615     octet_count = 4;     // we just know this
00616 
00617     // add it to the buffer
00618     if ( cdAddElem( im, esp, octet_count ) )
00619     {
00620         im->ltype = (short int) lntype;
00621         free( esp );
00622         return 1;
00623     }
00624     else
00625     {
00626         free( esp );
00627         return 0;
00628     }
00629 }
00630 
00631 int cdSetLineWidth( cdImagePtr im, int lnwidth )
00632 {
00633 // Attribute: Line Width; Elem Class 5; Elem ID 3
00634 // sets the line width.  with an image of height X with line width 1
00635 // the displayed width will be 1/X%.  as an example, if you image is
00636 // x=5, y=10, and you set line width = 1, and draw a vertical line, the
00637 // resulting line will  cover 20% of horizontal area.
00638 //
00639     unsigned char *es, *esp;
00640     int           octet_count;
00641 
00642     // First check and see if the user doesn't want any changes,
00643     // if so, just return success
00644     if ( lnwidth == -1 )
00645         return 1;
00646 
00647     // Check and see if the value it is being set to is the current
00648     // value, if so, don't make any changes, just return 1
00649     if ( lnwidth == im->lwidth )
00650         return 1;
00651 
00652     // allocate sufficent space.  should be 32 bits * 4 to be safe
00653     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
00654     if ( !es )
00655         return 0;          // memory allocation failed
00656     esp = es;
00657 
00658 
00659     //gej: line width is 32 bit floating point number, 16 bits before the
00660     // decimal, 16 bits after if Line Spec is default (1, scaled)
00661     // if Line Spec is 0 (0, absolute) then it is 16 bit SI
00662     if ( im->linespec )
00663     {
00664         if ( !cdcomhead( es, 5, 3, 4 ) )
00665         {
00666             free( esp ); return 0;
00667         }
00668         es          += 2;
00669         octet_count  = 2;
00670         es          += cdAppShort( es, (short int) lnwidth );
00671         octet_count += 2;
00672         // the next two (after decimal point) will always be zero
00673         es          += cdAppNull( es, 2 );
00674         octet_count += 2;
00675     }
00676     else
00677     {
00678         if ( !cdcomhead( es, 5, 3, 2 ) )
00679         {
00680             free( esp ); return 0;
00681         }
00682         octet_count  = 2;
00683         es          += 2;
00684         es          += cdAppShort( es, (short int) lnwidth );
00685         octet_count += 2;
00686     }
00687 
00688 
00689     // add it to the buffer
00690     if ( cdAddElem( im, esp, octet_count ) )
00691     {
00692         im->lwidth = lnwidth;
00693         free( esp );
00694         return 1;
00695     }
00696     else
00697     {
00698         free( esp );
00699         return 0;
00700     }
00701 }
00702 
00703 int cdSetLineColor( cdImagePtr im, int lncolor )
00704 {
00705 // Attribute: Line Colour; Elem Class 5; Elem ID 4
00706 // Sets the line color.  lncolor should be an index into the color
00707 // table that you have previously allocated.
00708 //
00709     unsigned char *es, *esp;
00710     int           octet_count;
00711     // First check and see if the user doesn't want any changes,
00712     // if so, just return success
00713     if ( lncolor == -1 )
00714         return 1;
00715 
00716     // Check and see if the value it is being set to is the current
00717     // value, if so, don't make any changes, just return 1
00718     if ( lncolor == im->lcolor )
00719         return 1;
00720 
00721     // Make sure the color they want to use has been allocated.
00722     // also, that color must be non-negative
00723     if ( ( lncolor >= im->colorsTotal ) || ( lncolor < 0 ) )
00724         return 0;          // you must allocate a color before you use it
00725 
00726     // allocate sufficent space.  should be 32 bits * 4 to be safe
00727     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
00728     if ( !es )
00729         return 0;          // memory allocation failed
00730     esp = es;
00731 
00732 
00733     if ( !cdcomhead( es, 5, 4, 1 ) )
00734     {
00735         free( esp ); return 0;
00736     }
00737     es += 2;
00738 
00739     *es = 0377 & lncolor;      // mask off last 8 bits and put in es
00740     es++;
00741 
00742     es += cdAppNull( es, 1 );
00743 
00744     octet_count = 4;     // we just know this; 2 octets of header,
00745                          // 1 octet of data, 1 octet of null data
00746 
00747     // add it to the buffer
00748     if ( cdAddElem( im, esp, octet_count ) )
00749     {
00750         im->lcolor = (short int) lncolor;
00751         free( esp );
00752         return 1;
00753     }
00754     else
00755     {
00756         free( esp );
00757         return 0;
00758     }
00759 }
00760 
00761 int cdSetFillStyle( cdImagePtr im, int instyle )
00762 {
00763 // set the style of the interior of filled area elements.
00764 // Attribute: Interior Style; Elem Class 5; Elem ID 22
00765 // These attributes stay in effect until changed, so you don't have to output
00766 // them every time.
00767 //     Interior Style: (integers 0-6, corresponding to: hollow, solid,
00768 //                      [not pattern], hatch, empty, [not geometric pattern],
00769 //                      interpolated.)
00770 // attribute is 16 bit signed int
00771 //
00772     unsigned char *es, *esp;
00773     int           octet_count;
00774 
00775     // First check and see if the user doesn't want any changes,
00776     // if so, just return success
00777     if ( instyle == -1 )
00778         return 1;
00779 
00780     // Check and see if the value it is being set to is the current
00781     // value, if so, don't make any changes, just return 1
00782     if ( instyle == im->shapestyle )
00783         return 1;
00784 
00785     // Make sure that lnhatch is between 0 and 6, but not
00786     // 2, 5, or 6
00787     if ( ( instyle < 0 ) || ( instyle > 4 ) || ( instyle == 2 ) )
00788         return 0;
00789 
00790     // allocate sufficent space.  should be 32 bits * 4 to be safe
00791     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
00792     if ( !es )
00793         return 0;          // memory allocation failed
00794     esp = es;
00795 
00796     // set the header to Class 5, ID 22, Length 2
00797     if ( !cdcomhead( es, 5, 22, 2 ) )
00798     {
00799         free( esp ); return 0;
00800     }
00801     es += 2;
00802 
00803     // add in the value of inhatch
00804     es += cdAppShort( es, (short int) instyle );
00805 
00806     octet_count = 4;     // we just know this
00807 
00808     // add it to the buffer
00809     if ( cdAddElem( im, esp, octet_count ) )
00810     {
00811         im->shapestyle = (short int) instyle;
00812         free( esp );
00813         return 1;
00814     }
00815     else
00816     {
00817         free( esp );
00818         return 0;
00819     }
00820 }
00821 
00822 int cdSetFillColor( cdImagePtr im, int incolor )
00823 {
00824 // set the color of the interior of filled area elements
00825 // Attribute: Fill Colour; Elem Class 5; Elem ID 23
00826 // These attributes stay in effect until changed, so you don't have to output
00827 // them every time.
00828 //     Fill Colour: (index into the color table)
00829 //
00830     unsigned char *es, *esp;
00831     int           octet_count;
00832     // First check and see if the user doesn't want any changes,
00833     // if so, just return success
00834     if ( incolor == -1 )
00835         return 1;
00836 
00837     // Check and see if the value it is being set to is the current
00838     // value, if so, don't make any changes, just return 1
00839     if ( incolor == im->shapecolor )
00840         return 1;
00841 
00842     // Make sure the color they want to use has been allocated.
00843     // also, that color must be non-negative
00844     if ( ( incolor >= im->colorsTotal ) || ( incolor < 0 ) )
00845         return 0;          // you must allocate a color before you use it
00846 
00847     // allocate sufficent space.  should be 32 bits * 4 to be safe
00848     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
00849     if ( !es )
00850         return 0;          // memory allocation failed
00851     esp = es;
00852 
00853     if ( !cdcomhead( es, 5, 23, 1 ) )
00854     {
00855         free( esp ); return 0;
00856     }
00857     es += 2;
00858 
00859     *es = 0377 & incolor;      // mask off last 8 bits and put in es
00860     es++;
00861     es += cdAppNull( es, 1 );
00862 
00863     octet_count = 4;     // we just know this; 2 octets of header,
00864                          // 1 octet of data, 1 octet of null data
00865 
00866     // add it to the buffer
00867     if ( cdAddElem( im, esp, octet_count ) )
00868     {
00869         im->shapecolor = (short int) incolor;
00870         free( esp );
00871         return 1;
00872     }
00873     else
00874     {
00875         free( esp );
00876         return 0;
00877     }
00878 }
00879 
00880 int cdSetFillHatch( cdImagePtr im, int inhatch )
00881 {
00882 // Set the hatch pattern for the interior of filled-area elements
00883 // the fill style must be set to hatch for this to have an effect.
00884 // Attribute: Hatch Index; Elem Class 5; Elem ID 24
00885 // These attributes stay in effect until changed, so you don't have to output
00886 // them every time.
00887 //     Hatch Index: (integers 1-6, corresponding to: horizontal lines,
00888 //                   vertical lines, pos. slope parallel lines,
00889 //                   neg. slope parallel lines, horizontal/vertical
00890 //                   crosshatch, positive/negative slope crosshatch)
00891 //
00892 
00893     unsigned char *es, *esp;
00894     int           octet_count, temp;
00895 
00896 
00897     // First check and see if the user doesn't want any changes,
00898     // if so, just return success
00899     if ( inhatch == -1 )
00900         return 1;
00901 
00902     // Check and see if the value it is being set to is the current
00903     // value, if so, don't make any changes, just return 1
00904     if ( inhatch == im->shapehatch )
00905         return 1;
00906 
00907     // Make sure that lnhatch is between 1 and 6
00908     if ( ( inhatch < 1 ) || ( inhatch > 6 ) )
00909         return 0;
00910 
00911     // allocate sufficent space.  should be 32 bits * 4 to be safe
00912     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
00913     if ( !es )
00914         return 0;          // memory allocation failed
00915     esp = es;
00916 
00917     // set the command header to class 5, id 24, length 2
00918     if ( !cdcomhead( es, 5, 24, 2 ) )
00919     {
00920         free( esp ); return 0;
00921     }
00922     es += 2;
00923 
00924     // add in the value of inhatch
00925     temp = inhatch >> 8;
00926     *es  = *es | ( temp & 0377 );
00927     es++;
00928     *es = *es | ( inhatch & 0377 );
00929     es++;
00930 
00931     octet_count = 4;     // we just know this
00932 
00933     // add it to the buffer
00934     if ( cdAddElem( im, esp, octet_count ) )
00935     {
00936         im->shapehatch = (short int) inhatch;
00937         free( esp );
00938         return 1;
00939     }
00940     else
00941     {
00942         free( esp );
00943         return 0;
00944     }
00945 }
00946 
00947 int cdSetEdgeType( cdImagePtr im, int edtype )
00948 {
00949 // set the type of the edge of filled-area elements.
00950 // Attribute: Edge Type; Elem Class 5; Elem ID 27
00951 // These attributes stay in effect until changed, so you don't have to output
00952 // them every time.
00953 //     Edge Type (integers 1-5, corresponding to: solid, dash, dot,
00954 //                dash-dot, dash-dot-dot. These are the same as those used
00955 //                for line type.)
00956 // In Part 3 of the standard (Binary Encoding) on page 47 it says that
00957 // edge type is integer.  This is incorrect.  Edge type is Index, just
00958 // like line type.
00959 // Even though new ones can be defined, I am limiting lntype to these values
00960 // If you really need more, you can make the proper changes.
00961 //
00962     unsigned char *es, *esp;
00963     int           octet_count;
00964 
00965     // First check and see if the user doesn't want any changes,
00966     // if so, just return success
00967     if ( edtype == -1 )
00968         return 1;
00969 
00970     // Check and see if the value it is being set to is the current
00971     // value, if so, don't make any changes, just return 1
00972     if ( edtype == im->edgetype )
00973         return 1;
00974 
00975     // Make sure that lntype is between 1 and 5
00976     if ( ( edtype < 1 ) || ( edtype > 5 ) )
00977         return 0;
00978 
00979     // allocate sufficent space.  should be 32 bits * 4 to be safe
00980     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
00981     if ( !es )
00982         return 0;          // memory allocation failed
00983     esp = es;
00984 
00985     if ( !cdcomhead( es, 5, 27, 2 ) )
00986     {
00987         free( esp ); return 0;
00988     }
00989     es += 2;
00990 
00991     // add in the value of edtype
00992     es += cdAppShort( es, (short int) edtype );
00993 
00994     octet_count = 4;     // we just know this
00995 
00996     // add it to the buffer
00997     if ( cdAddElem( im, esp, octet_count ) )
00998     {
00999         im->edgetype = (short int) edtype;
01000         free( esp );
01001         return 1;
01002     }
01003     else
01004     {
01005         free( esp );
01006         return 0;
01007     }
01008 }
01009 
01010 int cdSetEdgeWidth( cdImagePtr im, int edwidth )
01011 {
01012 // Set the width of the edge of filled-area elements.
01013 // Attribute: Edge Width; Elem Class 5; Elem ID 28
01014 // These attributes stay in effect until changed, so you don't have to output
01015 // them every time.
01016 //     Edge Width (should be the same as line width)
01017 //
01018     unsigned char *es, *esp;
01019     int           octet_count;
01020 
01021     // First check and see if the user doesn't want any changes,
01022     // if so, just return success
01023     if ( edwidth == -1 )
01024         return 1;
01025 
01026     // Check and see if the value it is being set to is the current
01027     // value, if so, don't make any changes, just return 1
01028     if ( edwidth == im->edgewidth )
01029         return 1;
01030 
01031     // allocate sufficent space.  should be 32 bits * 4 to be safe
01032     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
01033     if ( !es )
01034         return 0;          // memory allocation failed
01035     esp = es;
01036 
01037     //gej: edge width is 32 bit floating point number, 16 bits before the
01038     // decimal, 16 bits after for default edge spec (1, scaled) if
01039     // edge spec is absolute (0) then just 16 bit SI
01040     if ( im->edgespec )
01041     {
01042         if ( !cdcomhead( es, 5, 28, 4 ) )
01043         {
01044             free( esp ); return 0;
01045         }
01046         es          += 2;
01047         octet_count  = 2;
01048         es          += cdAppShort( es, edwidth );
01049         octet_count += 2;
01050         // the next two (after decimal point) will always be zero
01051         es          += cdAppNull( es, 2 );
01052         octet_count += 2;
01053     }
01054     else
01055     {
01056         if ( !cdcomhead( es, 5, 28, 2 ) )
01057         {
01058             free( esp ); return 0;
01059         }
01060         es          += 2;
01061         octet_count  = 2;
01062         es          += cdAppShort( es, edwidth );
01063         octet_count += 2;
01064     }
01065 
01066     // add it to the buffer
01067     if ( cdAddElem( im, esp, octet_count ) )
01068     {
01069         im->edgewidth = edwidth;
01070         free( esp );
01071         return 1;
01072     }
01073     else
01074     {
01075         free( esp );
01076         return 0;
01077     }
01078 }
01079 
01080 int cdSetEdgeColor( cdImagePtr im, int edcolor )
01081 {
01082 // Set the color of the edge of filled-area elements.
01083 // Attribute: Edge Color; Elem Class 5; Elem ID 29
01084 // These attributes stay in effect until changed, so you don't have to output
01085 // them every time.
01086 //     Edge Colour (index into the color table)
01087 //
01088     unsigned char *es, *esp;
01089     int           octet_count;
01090     // First check and see if the user doesn't want any changes,
01091     // if so, just return success
01092     if ( edcolor == -1 )
01093         return 1;
01094 
01095     // Check and see if the value it is being set to is the current
01096     // value, if so, don't make any changes, just return 1
01097     if ( edcolor == im->edgecolor )
01098         return 1;
01099 
01100     // Make sure the color they want to use has been allocated.
01101     // also, that color must be non-negative
01102     if ( ( edcolor >= im->colorsTotal ) || ( edcolor < 0 ) )
01103         return 0;          // you must allocate a color before you use it
01104 
01105     // allocate sufficent space.  should be 32 bits * 4 to be safe
01106     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
01107     if ( !es )
01108         return 0;          // memory allocation failed
01109     esp = es;
01110     if ( !cdcomhead( es, 5, 29, 1 ) )
01111     {
01112         free( esp ); return 0;
01113     }
01114     es += 2;
01115 
01116     *es = 0377 & edcolor;      // mask off last 8 bits and put in es
01117     es++;
01118     es += cdAppNull( es, 1 );
01119 
01120     octet_count = 4;     // we just know this; 2 octets of header,
01121                          // 1 octet of data, 1 octet of null data
01122 
01123     // add it to the buffer
01124     if ( cdAddElem( im, esp, octet_count ) )
01125     {
01126         im->edgecolor = (short int) edcolor;
01127         free( esp );
01128         return 1;
01129     }
01130     else
01131     {
01132         free( esp );
01133         return 0;
01134     }
01135 }
01136 
01137 int cdSetEdgeVis( cdImagePtr im, int edvis )
01138 {
01139 // Set the visibility of the edge of filled-area elements.
01140 // Attribute: Edge Visibility; Elem Class 5; Elem ID 30
01141 // These attributes stay in effect until changed, so you don't have to output
01142 // them every time.
01143 //     Edge Visibility (integer 0 or 1, corresponding to: Off, On)
01144 // Attribute is 16 bit signed int.
01145 //
01146     unsigned char *es, *esp;
01147     int           octet_count, temp;
01148 
01149     // First check and see if the user doesn't want any changes,
01150     // if so, just return success
01151     if ( edvis == -1 )
01152         return 1;
01153 
01154     // Check and see if the value it is being set to is the current
01155     // value, if so, don't make any changes, just return 1
01156     if ( edvis == im->edgevis )
01157         return 1;
01158 
01159     // allocate sufficent space.  should be 32 bits * 4 to be safe
01160     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
01161     if ( !es )
01162         return 0;          // memory allocation failed
01163     esp = es;
01164 
01165     if ( !cdcomhead( es, 5, 30, 2 ) )
01166     {
01167         free( esp ); return 0;
01168     }
01169     es  += 2; octet_count = 2;
01170     temp = edvis >> 8;
01171     *es  = *es | ( temp & 0377 );
01172     es++;
01173     *es = *es | ( edvis & 0377 );
01174     es++;
01175     octet_count += 2;
01176 
01177 
01178     // add it to the buffer
01179     if ( cdAddElem( im, esp, octet_count ) )
01180     {
01181         im->edgevis = (short int) edvis;
01182         free( esp );
01183         return 1;
01184     }
01185     else
01186     {
01187         free( esp );
01188         return 0;
01189     }
01190 }
01191 
01192 int cdSetTextFont( cdImagePtr im, int font )
01193 {
01194 // Attribute: Text Font Index; Elem Class 5; Elem ID 10
01195 // font is an index into the font table.  it can have one of the following
01196 // values:
01197 // 1 Times Roman
01198 // 2 Times Bold
01199 // 3 Times Italic
01200 // 4 Times Bold Italic
01201 // 5 Helvetica
01202 // 6 Helvetica Bold
01203 // 7 Helvetica Italic
01204 // 8 Helvetica Bold Italic
01205 // 9 Courier
01206 // 10 Courier Bold
01207 // 11 Courier Italic
01208 // 12 Courier Bold Italic
01209 //
01210     unsigned char *es, *esp;
01211     int           octet_count;
01212 
01213     // First check and see if the user doesn't want any changes,
01214     // if so, just return success
01215     if ( font == -1 )
01216         return 1;
01217 
01218     // Check and see if the value it is being set to is the current
01219     // value, if so, don't make any changes, just return 1
01220     if ( font == im->textfont )
01221         return 1;
01222 
01223     // Make sure that font is between 1 and the number of fonts
01224     if ( ( font < 1 ) || ( font > im->numfonts ) )
01225         return 0;
01226 
01227     // allocate sufficent space.  should be 32 bits * 4 to be safe
01228     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
01229     if ( !es )
01230         return 0;          // memory allocation failed
01231     esp = es;
01232 
01233     if ( !cdcomhead( es, 5, 10, 2 ) )
01234     {
01235         free( esp ); return 0;
01236     }
01237     es += 2;
01238 
01239     es += cdAppShort( es, (short int) font );
01240 
01241     octet_count = 4;     // we just know this
01242 
01243     // add it to the buffer
01244     if ( cdAddElem( im, esp, octet_count ) )
01245     {
01246         im->textfont = (short int) font;
01247         free( esp );
01248         return 1;
01249     }
01250     else
01251     {
01252         free( esp );
01253         return 0;
01254     }
01255 }
01256 
01257 int cdSetTextColor( cdImagePtr im, int color )
01258 {
01259 // Attribute: Text Colour ; Elem Class 5; Elem ID 14
01260 // set the forground color of text
01261 //
01262     unsigned char *es, *esp;
01263     int           octet_count;
01264     // First check and see if the user doesn't want any changes,
01265     // if so, just return success
01266     if ( color == -1 )
01267         return 1;
01268 
01269     // Check and see if the value it is being set to is the current
01270     // value, if so, don't make any changes, just return 1
01271     if ( color == im->textcolor )
01272         return 1;
01273 
01274     // Make sure the color they want to use has been allocated.
01275     // also, that color must be non-negative
01276     if ( ( color >= im->colorsTotal ) || ( color < 0 ) )
01277         return 0;          // you must allocate a color before you use it
01278 
01279     // allocate sufficent space.  should be 32 bits * 4 to be safe
01280     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
01281     if ( !es )
01282         return 0;          // memory allocation failed
01283     esp = es;
01284 
01285     if ( !cdcomhead( es, 5, 14, 1 ) )
01286     {
01287         free( esp ); return 0;
01288     }
01289     es += 2;
01290 
01291     *es = 0377 & color;      // mask off last 8 bits and put in es
01292     es++;
01293 
01294     octet_count = 4;     // we just know this; 2 octets of header,
01295                          // 1 octet of data, 1 octet of null data
01296 
01297     // add it to the buffer
01298     if ( cdAddElem( im, esp, octet_count ) )
01299     {
01300         im->textcolor = (short int) color;
01301         free( esp );
01302         return 1;
01303     }
01304     else
01305     {
01306         free( esp );
01307         return 0;
01308     }
01309 }
01310 
01311 int cdSetTextHeight( cdImagePtr im, int height )
01312 {
01313 // Attribute: Character Height; Elem Class 5; Elem ID 15
01314 // the height is in the same units as line width
01315 //
01316     unsigned char *es, *esp;
01317     int           octet_count;
01318     // First check and see if the user doesn't want any changes,
01319     // if so, just return success
01320     if ( height == -1 )
01321         return 1;
01322 
01323     // Check and see if the value it is being set to is the current
01324     // value, if so, don't make any changes, just return 1
01325     if ( height == im->textheight )
01326         return 1;
01327 
01328     // allocate sufficent space.  should be 32 bits * 4 to be safe
01329     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
01330     if ( !es )
01331         return 0;          // memory allocation failed
01332     esp = es;
01333 
01334     if ( !cdcomhead( es, 5, 15, 2 ) )
01335     {
01336         free( esp ); return 0;
01337     }
01338     octet_count = 2; es += 2;
01339 
01340     es          += cdAppShort( es, height );
01341     octet_count += 2;
01342 
01343     // add it to the buffer
01344     if ( cdAddElem( im, esp, octet_count ) )
01345     {
01346         im->textheight = height;
01347         free( esp );
01348         return 1;
01349     }
01350     else
01351     {
01352         free( esp );
01353         return 0;
01354     }
01355 }
01356 
01357 int cdSetTextPath( cdImagePtr im, int tpath )
01358 {
01359 // Attribute: Text Path; Elem Class 5; Elem ID 17
01360 // Is one of:
01361 //   0 right -- Means the direction of the character base vector
01362 //   1 left  -- means 180 degrees from the character base vector
01363 //   2 up    -- means the direction of the character up vector
01364 //   3 down  -- means 180 degrees from the character up vector
01365 //
01366     unsigned char *es, *esp;
01367     int           octet_count;
01368 
01369     // First check and see if the user doesn't want any changes,
01370     // if so, just return success
01371     if ( tpath == -1 )
01372         return 1;
01373 
01374     // Check and see if the value it is being set to is the current
01375     // value, if so, don't make any changes, just return 1
01376     if ( tpath == im->textpath )
01377         return 1;
01378 
01379     // allocate sufficent space.  should be 32 bits * 4 to be safe
01380     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
01381     if ( !es )
01382         return 0;          // memory allocation failed
01383     esp         = es;
01384     octet_count = 0;
01385 
01386     if ( !cdcomhead( es, 5, 17, 2 ) )
01387     {
01388         free( esp ); return 0;
01389     }
01390     es += 2; octet_count = 2;
01391 
01392     es          += cdAppShort( es, (short int) tpath );
01393     octet_count += 2;
01394 
01395     // add it to the buffer
01396     if ( cdAddElem( im, esp, octet_count ) )
01397     {
01398         im->textpath = (short int) tpath;
01399         free( esp );
01400         return 1;
01401     }
01402     else
01403     {
01404         free( esp );
01405         return 0;
01406     }
01407 }
01408 
01409 int cdSetTextOrient( cdImagePtr im, int xup, int yup, int xbase, int ybase )
01410 {
01411 // Attribute: Character Orientation; Elem Class 5; Elem ID 16
01412 // (xbase,ybase) is the run and the rise of the line that the text is
01413 // written along.  For regular text at an angle, set xup = -ybase
01414 // and yup = xbase.  Setting it to something different will result in
01415 // skewed text (which may be what you want.) Text written from bottom to
01416 // top at a 90 degree angle would have the following parameters
01417 // xup=-1, yup=0, xbase=0, ybase=1
01418 //
01419 // This function adds the Orientation to the metafile every time.
01420 // It does not follow the normal -1 for no change, although if you
01421 // put in the same numbers it won't re-add it to the meta file.
01422 //
01423     unsigned char *es, *esp;
01424     int           octet_count;
01425 
01426 
01427     // allocate sufficent space.  should be 32 bits * 4 to be safe
01428     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
01429     if ( !es )
01430         return 0;          // memory allocation failed
01431     esp         = es;
01432     octet_count = 0;
01433 
01434     if ( !cdcomhead( es, 5, 16, 8 ) )
01435     {
01436         free( esp ); return 0;
01437     }
01438     es += 2; octet_count += 2;
01439 
01440     // In the metafile it is a 16 bit signed integer
01441     // add xup
01442     es          += cdAppShort( es, (short int) xup );
01443     octet_count += 2;
01444     // add the rest
01445     es          += cdAppShort( es, (short int) yup );
01446     octet_count += 2;
01447     es          += cdAppShort( es, (short int) xbase );
01448     octet_count += 2;
01449     es          += cdAppShort( es, (short int) ybase );
01450     octet_count += 2;
01451 
01452     // add it to the buffer
01453     if ( cdAddElem( im, esp, octet_count ) )
01454     {
01455         free( esp );
01456         return 1;
01457     }
01458     else
01459     {
01460         free( esp );
01461         return 0;
01462     }
01463 }
01464 
01465 int cdSetMarkerType( cdImagePtr im, int mtype )
01466 {
01467 // Attribute: Marker Type; Elem Class 5; Elem ID 6
01468 // Set the Marker type.  Possible values are:
01469 // 1=dot, 2=plus, 3=asterisk, 4=circle, 5=cross
01470 // Even though new ones can be defined, I am limiting lntype to these values
01471 // If you really need more, you can make the proper changes.
01472 //
01473     unsigned char *es, *esp;
01474     int           octet_count;
01475 
01476     // First check and see if the user doesn't want any changes,
01477     // if so, just return success
01478     if ( mtype == -1 )
01479         return 1;
01480 
01481     // Check and see if the value it is being set to is the current
01482     // value, if so, don't make any changes, just return 1
01483     if ( mtype == im->mtype )
01484         return 1;
01485 
01486     // Make sure that mtype is between 1 and 5
01487     if ( ( mtype < 1 ) || ( mtype > 5 ) )
01488         return 0;
01489 
01490     // allocate sufficent space.  should be 32 bits * 4 to be safe
01491     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
01492     if ( !es )
01493         return 0;          // memory allocation failed
01494     esp = es;
01495 
01496     if ( !cdcomhead( es, 5, 6, 2 ) )
01497     {
01498         free( esp ); return 0;
01499     }
01500     es += 2;
01501     // set Param_List_Len to 2 (signed int at index precision)
01502 
01503     // add in the value of mtype
01504     es += cdAppShort( es, (short int) mtype );
01505 
01506     octet_count = 4;     // we just know this
01507 
01508     // add it to the buffer
01509     if ( cdAddElem( im, esp, octet_count ) )
01510     {
01511         im->mtype = (short int) mtype;
01512         free( esp );
01513         return 1;
01514     }
01515     else
01516     {
01517         free( esp );
01518         return 0;
01519     }
01520 }
01521 
01522 int cdSetMarkerSize( cdImagePtr im, int msize )
01523 {
01524 // Attribute: Marker Size; Elem Class 5; Elem ID 7
01525 // sets the marker size.  with an image of height X with marker size 1
01526 // the displayed size will be 1/X%.  as an example, if you image is
01527 // x=5, y=10, and you set marker size = 1, and draw a marker, the
01528 // resulting marker will  cover 20% of horizontal area.
01529 //
01530     unsigned char *es, *esp;
01531     int           octet_count;
01532 
01533     // First check and see if the user doesn't want any changes,
01534     // if so, just return success
01535     if ( msize == -1 )
01536         return 1;
01537 
01538     // Check and see if the value it is being set to is the current
01539     // value, if so, don't make any changes, just return 1
01540     if ( msize == im->msize )
01541         return 1;
01542 
01543     // allocate sufficent space.  should be 32 bits * 4 to be safe
01544     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
01545     if ( !es )
01546         return 0;          // memory allocation failed
01547     esp = es;
01548 
01549 
01550     //gej: marker size is 32 bit floating point number, 16 bits before the
01551     // decimal, 16 bits after if marker spec is default (1, scaled)
01552     // for absolute mode (0, absolute) it is 16 bit SI
01553     if ( im->markerspec )
01554     {
01555         if ( !cdcomhead( es, 5, 7, 4 ) )
01556         {
01557             free( esp ); return 0;
01558         }
01559         octet_count  = 2;
01560         es          += 2;
01561         es          += cdAppShort( es, (short int) msize );
01562         octet_count += 2;
01563         // the next two (after decimal point) will always be zero
01564         es          += cdAppNull( es, 2 );
01565         octet_count += 2;
01566     }
01567     else
01568     {
01569         if ( !cdcomhead( es, 5, 7, 4 ) )
01570         {
01571             free( esp ); return 0;
01572         }
01573         octet_count  = 2;
01574         es          += 2;
01575         es          += cdAppShort( es, (short int) msize );
01576         octet_count += 2;
01577     }
01578 
01579 
01580     // add it to the buffer
01581     if ( cdAddElem( im, esp, octet_count ) )
01582     {
01583         im->msize = msize;
01584         free( esp );
01585         return 1;
01586     }
01587     else
01588     {
01589         free( esp );
01590         return 0;
01591     }
01592 }
01593 
01594 int cdSetMarkerColor( cdImagePtr im, int mcolor )
01595 {
01596 // Attribute: Marker Colour; Elem Class 5; Elem ID 8
01597 // Sets the marker color.  mcolor should be an index into the color
01598 // table that you have previously allocated.
01599 //
01600     unsigned char *es, *esp;
01601     int           octet_count;
01602     // First check and see if the user doesn't want any changes,
01603     // if so, just return success
01604     if ( mcolor == -1 )
01605         return 1;
01606 
01607     // Check and see if the value it is being set to is the current
01608     // value, if so, don't make any changes, just return 1
01609     if ( mcolor == im->mcolor )
01610         return 1;
01611 
01612     // Make sure the color they want to use has been allocated.
01613     // also, that color must be non-negative
01614     if ( ( mcolor >= im->colorsTotal ) || ( mcolor < 0 ) )
01615         return 0;          // you must allocate a color before you use it
01616 
01617     // allocate sufficent space.  should be 32 bits * 4 to be safe
01618     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
01619     if ( !es )
01620         return 0;          // memory allocation failed
01621     esp = es;
01622 
01623 
01624     if ( !cdcomhead( es, 5, 8, 1 ) )
01625     {
01626         free( esp ); return 0;
01627     }
01628     es += 2;
01629 
01630     *es = 0377 & mcolor;      // mask off last 8 bits and put in es
01631     es++;
01632 
01633     es += cdAppNull( es, 1 );
01634 
01635     octet_count = 4;     // we just know this; 2 octets of header,
01636                          // 1 octet of data, 1 octet of null data
01637 
01638     // add it to the buffer
01639     if ( cdAddElem( im, esp, octet_count ) )
01640     {
01641         im->mcolor = (short int) mcolor;
01642         free( esp );
01643         return 1;
01644     }
01645     else
01646     {
01647         free( esp );
01648         return 0;
01649     }
01650 }
01651 
01652 int cdSetLineAttrib( cdImagePtr im, int lntype, int lnwidth, int lncolor )
01653 {
01654 // Spits out the attributes of lines.  These attributes stay in effect
01655 // until changed, so you don't have to output them every time.
01656 //
01657 
01658     if ( !cdSetLineType( im, lntype ) )
01659         return 0;
01660     if ( !cdSetLineWidth( im, lnwidth ) )
01661         return 0;
01662     if ( !cdSetLineColor( im, lncolor ) )
01663         return 0;
01664 
01665     return 1;
01666 }
01667 
01668 int cdSetShapeFillAttrib( cdImagePtr im, int instyle, int incolor, int inhatch )
01669 {
01670 // Spits out the attributes for the interior of filled-area elements.
01671 // These attributes stay in effect until changed, so you don't have to output
01672 // them every time.
01673 // Set the following attributes:
01674 //     Interior Style: (integers 0-6, corresponding to: hollow, solid,
01675 //                      [not pattern], hatch, empty, [not geometric pattern],
01676 //                      interpolated.)
01677 //     Fill Colour: (index into the color table)
01678 //     Hatch Index: (integers 1-6, corresponding to: horizontal lines,
01679 //                   vertical lines, pos. slope parallel lines,
01680 //                   neg. slope parallel lines, horizontal/vertical
01681 //                   crosshatch, positive/negative slope crosshatch)
01682 //
01683     if ( !cdSetFillStyle( im, instyle ) )
01684         return 0;
01685     if ( !cdSetFillColor( im, incolor ) )
01686         return 0;
01687     if ( !cdSetFillHatch( im, inhatch ) )
01688         return 0;
01689 
01690     return 1;
01691 }
01692 
01693 int cdSetShapeEdgeAttrib( cdImagePtr im, int edtype, int edwidth, int edcolor, int edvis )
01694 {
01695 // Spits out the attributes for the edges of filled-area elements.  It may
01696 // seem logical that these would be the same as the corresponding line
01697 // attributes, but this is not the case.
01698 // These attributes stay in effect until changed, so you don't have to output
01699 // them every time.
01700 // Set the following attributes:
01701 //     Edge Type (integers 1-5, corresponding to: solid, dash, dot,
01702 //                dash-dot, dash-dot-dot. These are the same as those used
01703 //                for line type.)
01704 //     Edge Width (should be the same as line width)
01705 //     Edge Colour (index into the color table)
01706 //     Edge Visibility (integer 0 or 1, corresponding to: Off, On)
01707 //
01708     if ( !cdSetEdgeType( im, edtype ) )
01709         return 0;
01710     if ( !cdSetEdgeWidth( im, edwidth ) )
01711         return 0;
01712     if ( !cdSetEdgeColor( im, edcolor ) )
01713         return 0;
01714     if ( !cdSetEdgeVis( im, edvis ) )
01715         return 0;
01716 
01717     return 1;
01718 }
01719 
01720 int cdSetTextAttrib( cdImagePtr im, int font, int color, int height )
01721 {
01722 // Set the attributes of text.  the font is an integer pointer into the
01723 // font list where:
01724 // 1 Times
01725 // 2 Times Bold
01726 // 3 Times Italic
01727 // 4 Times Bold Italic
01728 // 5 Helvetica
01729 // 6 Helvetica Bold
01730 // 7 Helvetica Italic
01731 // 8 Helvetica Bold Italic
01732 // 9 Courier
01733 // 10 Courier Bold
01734 // 11 Courier Italic
01735 // 12 Courier Bold Italic
01736 // color is an index into the colortable which is the color of the text
01737 // size is the approximate size you want the text written in.
01738 //
01739 
01740     if ( !cdSetTextFont( im, font ) )
01741         return 0;
01742     if ( !cdSetTextColor( im, color ) )
01743         return 0;
01744     if ( !cdSetTextHeight( im, height ) )
01745         return 0;
01746 
01747     return 1;
01748 }
01749 
01750 int cdSetMarkerAttrib( cdImagePtr im, int mtype, int msize, int mcolor )
01751 {
01752 // Spits out the attributes of Markers.  These attributes stay in effect
01753 // until changed, so you don't have to output them every time.
01754 //
01755 
01756     if ( !cdSetMarkerType( im, mtype ) )
01757         return 0;
01758     if ( !cdSetMarkerSize( im, msize ) )
01759         return 0;
01760     if ( !cdSetMarkerColor( im, mcolor ) )
01761         return 0;
01762 
01763     return 1;
01764 }
01765 
01766 int cdImageDestroy( cdImagePtr im )
01767 // gej: should work, unless I make changes to cdImage Struct
01768 {
01769     if ( im->elemlist )
01770     {
01771         free( im->elemlist );
01772     }
01773     if ( im->desc )
01774     {
01775         free( im->desc );
01776     }
01777     if ( im->fontlist )
01778     {
01779         free( im->fontlist );
01780     }
01781     free( im );
01782 
01783     return 1;
01784 }
01785 
01786 int cdImageColorClosest( cdImagePtr im, int r, int g, int b )
01787 // From gd library, see README file for copyright information
01788 // gej: should work unchanged
01789 // gej: 5/96, changed the colors to use short int
01790 {
01791     short int i;
01792     long      rd, gd, bd;
01793     int       ct      = ( -1 );
01794     long      mindist = 0;
01795     for ( i = 0; ( i < ( im->colorsTotal ) ); i++ )
01796     {
01797         long dist;
01798         if ( im->open[i] )
01799         {
01800             continue;
01801         }
01802         rd   = ( im->red[i] - r );
01803         gd   = ( im->green[i] - g );
01804         bd   = ( im->blue[i] - b );
01805         dist = rd * rd + gd * gd + bd * bd;
01806         if ( ( i == 0 ) || ( dist < mindist ) )
01807         {
01808             mindist = dist;
01809             ct      = i;
01810         }
01811     }
01812     return ct;
01813 }
01814 
01815 int cdImageColorClear( cdImagePtr im )
01816 {
01817 // mark all entries in the color table as open
01818     short int i;
01819     for ( i = 0; ( i < ( cdMaxColors ) ); i++ )
01820     {
01821         im->open[i] = 1;
01822     }
01823     return 1;
01824 }
01825 
01826 int cdImageColorExact( cdImagePtr im, int r, int g, int b )
01827 // From gd library, see README file for copyright information
01828 // gej: should work unchanged
01829 // gej: 5/96, changed colors to work with short ints
01830 {
01831     short int i;
01832     for ( i = 0; ( i < ( im->colorsTotal ) ); i++ )
01833     {
01834         if ( im->open[i] )
01835         {
01836             continue;
01837         }
01838         if ( ( im->red[i] == r ) &&
01839              ( im->green[i] == g ) &&
01840              ( im->blue[i] == b ) )
01841         {
01842             return i;
01843         }
01844     }
01845     return -1;
01846 }
01847 
01848 static int cdImageAddColorIndex( cdImagePtr im, int r, int g, int b )
01849 // adds the specified color to the colortable in the cdImagePtr.
01850 // does not add it to the cgm file, cdImageAddColor does.
01851 // do not use either of these two functions, use cdImageColorAllocate.
01852 //
01853 {
01854     short int i;
01855     short int ct = ( -1 );
01856     for ( i = 0; ( i < ( im->colorsTotal ) ); i++ )
01857     {
01858         if ( im->open[i] )
01859         {
01860             ct = i;
01861             break;
01862         }
01863     }
01864     if ( ct == ( -1 ) )
01865     {
01866         ct = im->colorsTotal;
01867         if ( ct == cdMaxColors )
01868         {
01869             return -1;
01870         }
01871         im->colorsTotal++;
01872     }
01873     im->red[ct]   = (short int) r;
01874     im->green[ct] = (short int) g;
01875     im->blue[ct]  = (short int) b;
01876     im->open[ct]  = (short int) 0;
01877 
01878     return ct;
01879 }
01880 
01881 static int cdImageAddColor( cdImagePtr im, int si, int ei )
01882 // adds colors to the cgm file, gets values from the color table.
01883 // adds all colors from si to ei inclusive.
01884 // Use cdImageColorAllocate, not this one.
01885 //
01886 {
01887     unsigned char *cts, *ctsp;     // GEJ: color table attribute
01888     int           octet_count;     // GEJ: octet count
01889     int           numco, curly;
01890     octet_count = 0;
01891     //
01892     // Attribute: Colour Table; Elem Class 5; Elem ID 34
01893     // two parameters P1: Starting colour table index (1 octet, UI)
01894     // P2: list of direct colour values 3-tuples (3 one-octet values)
01895     //
01896     // G E J: find out how many values are being added
01897     if ( ei < 0 )
01898         return -1;             // no colors being added
01899     numco = ei - si + 1;
01900 
01901     if ( ( numco > 0 ) && ( numco < 10 ) )
01902     {
01903         // we can use the short form of the command
01904         // allocate sufficent space. Should be 32 bits * 10 to be safe
01905         cts = (unsigned char *) calloc( 4 * 10, SIZEOF( unsigned char ) );
01906         if ( !cts )
01907             return -1;               // memory allocation failed
01908         ctsp = cts;
01909         if ( !cdcomhead( ctsp, 5, 34, ( numco * 3 ) + 1 ) )
01910         {
01911             free( cts ); return -1;
01912         }
01913         ctsp += 2; octet_count += 2;
01914     }
01915     else if ( ( numco > 9 ) && ( numco < 256 ) )
01916     {
01917         // we must use the long form of the command
01918         // allocate sufficent space. Should be 32 bits*256 to be safe
01919         cts = (unsigned char *) calloc( 256 * 4, SIZEOF( unsigned char ) );
01920         if ( !cts )
01921             return -1;               // memory allocation failed
01922         ctsp = cts;
01923         if ( !cdcomheadlong( ctsp, 5, 34, ( numco * 3 ) + 1 ) )
01924         {
01925             free( cts ); return -1;
01926         }
01927         ctsp += 4; octet_count += 4;
01928     }
01929     else
01930     {
01931         return -1;
01932     }
01933 
01934     //ctsp += cdAppByte(ctsp, (short int) si);
01935     cdAppByte( ctsp, (short int) si );
01936     ctsp++;
01937     octet_count++;
01938     for ( numco = si; numco <= ei; numco++ )
01939     {
01940         ctsp        += cdAppByte( ctsp, im->red[numco] );
01941         ctsp        += cdAppByte( ctsp, im->green[numco] );
01942         ctsp        += cdAppByte( ctsp, im->blue[numco] );
01943         octet_count += 3;
01944     }
01945 
01946 
01947     curly = 4 - ( octet_count % 4 );
01948     if ( curly % 4 )
01949     {
01950         octet_count += curly;
01951         ctsp        += cdAppNull( ctsp, curly );
01952     }
01953     // add it to the buffer
01954     if ( cdAddElem( im, cts, octet_count ) )
01955     {
01956         free( cts );
01957         return 1;
01958     }
01959     else
01960     {
01961         free( cts );
01962         return -1;
01963     }
01964 }
01965 
01966 int cdImageColorAllocate( cdImagePtr im, int r, int g, int b )
01967 // From gd library, see README file for copyright information
01968 // gej: modified to allocate the color in the CGM buffer as well
01969 // as the color table
01970 // gej: 5/96, modified to use short ints for colors
01971 {
01972     short int ct;
01973     ct = cdImageAddColorIndex( im, r, g, b );
01974     if ( ct == -1 )
01975         return -1;
01976     // GEJ: w we have successfully alocated it in the color table
01977     // so let's put it in the CGM as well.
01978     //
01979     if ( cdImageAddColor( im, ct, ct ) == -1 )
01980     {
01981         return -1;
01982     }
01983     else
01984     {
01985         return ct;
01986     }
01987 }
01988 
01989 int cdImageColor16( cdImagePtr im )
01990 {
01991 // allocate the 16 basic colors in the windows pallete
01992 //
01993 //      cdImageColorAllocate(im, 0, 0, 0);
01994 //      cdImageColorAllocate(im, 0, 0, 0);
01995 //      cdImageColorAllocate(im, 0, 0, 0);
01996 //      cdImageColorAllocate(im, 0, 0, 0);
01997 //      cdImageColorAllocate(im, 0, 0, 0);
01998 //      cdImageColorAllocate(im, 0, 0, 0);
01999 //      cdImageColorAllocate(im, 0, 0, 0);
02000 //      cdImageColorAllocate(im, 0, 0, 0);
02001 //      cdImageColorAllocate(im, 0, 0, 0);
02002 //      cdImageColorAllocate(im, 0, 0, 0);
02003 //      cdImageColorAllocate(im, 0, 0, 0);
02004 //      cdImageColorAllocate(im, 0, 0, 0);
02005 //      cdImageColorAllocate(im, 0, 0, 0);
02006 //      cdImageColorAllocate(im, 0, 0, 0);
02007 //      cdImageColorAllocate(im, 0, 0, 0);
02008 //      cdImageColorAllocate(im, 0, 0, 0);
02009 //
02010     int si, ei, li;
02011     si = cdImageAddColorIndex( im, 255, 255, 255 );
02012     if ( si == -1 )
02013         return 0;
02014     li = -1; ei = si;
02015     ei = cdImageAddColorIndex( im, 0, 0, 0 );
02016     if ( ei != -1 )
02017     {
02018         li = ei;
02019     }
02020     ei = cdImageAddColorIndex( im, 128, 0, 0 );
02021     if ( ei != -1 )
02022     {
02023         li = ei;
02024     }
02025     ei = cdImageAddColorIndex( im, 0, 128, 0 );
02026     if ( ei != -1 )
02027     {
02028         li = ei;
02029     }
02030     ei = cdImageAddColorIndex( im, 128, 128, 0 );
02031     if ( ei != -1 )
02032     {
02033         li = ei;
02034     }
02035     ei = cdImageAddColorIndex( im, 0, 0, 128 );
02036     if ( ei != -1 )
02037     {
02038         li = ei;
02039     }
02040     ei = cdImageAddColorIndex( im, 128, 0, 128 );
02041     if ( ei != -1 )
02042     {
02043         li = ei;
02044     }
02045     ei = cdImageAddColorIndex( im, 0, 128, 128 );
02046     if ( ei != -1 )
02047     {
02048         li = ei;
02049     }
02050     ei = cdImageAddColorIndex( im, 128, 128, 128 );
02051     if ( ei != -1 )
02052     {
02053         li = ei;
02054     }
02055     ei = cdImageAddColorIndex( im, 192, 192, 192 );
02056     if ( ei != -1 )
02057     {
02058         li = ei;
02059     }
02060     ei = cdImageAddColorIndex( im, 255, 0, 0 );
02061     if ( ei != -1 )
02062     {
02063         li = ei;
02064     }
02065     ei = cdImageAddColorIndex( im, 0, 255, 0 );
02066     if ( ei != -1 )
02067     {
02068         li = ei;
02069     }
02070     ei = cdImageAddColorIndex( im, 255, 255, 0 );
02071     if ( ei != -1 )
02072     {
02073         li = ei;
02074     }
02075     ei = cdImageAddColorIndex( im, 0, 0, 255 );
02076     if ( ei != -1 )
02077     {
02078         li = ei;
02079     }
02080     ei = cdImageAddColorIndex( im, 255, 0, 255 );
02081     if ( ei != -1 )
02082     {
02083         li = ei;
02084     }
02085     ei = cdImageAddColorIndex( im, 0, 255, 255 );
02086     if ( ei != -1 )
02087     {
02088         li = ei;
02089     }
02090 
02091     if ( ei == -1 )
02092     {
02093         ei = li;
02094     }
02095     if ( cdImageAddColor( im, si, ei ) == -1 )
02096     {
02097         return -1;
02098     }
02099     else
02100     {
02101         return ei;
02102     }
02103 }
02104 int cdImageColorDeallocate( cdImagePtr im, int color )
02105 // wogl: the parameter names are commented to avoid compiler warnings
02106 // From gd library, see README file for copyright information
02107 // gej: should work unchanged
02108 {
02109     // Mark it open.
02110     //im->open[color] = 1;
02111     // gej: really can't work, we are not allowing redefinition
02112     // of color table entries
02113     return 0;
02114 }
02115 
02116 int cdLine( cdImagePtr im, int x1, int y1, int x2, int y2 )
02117 // Graphic Primitive: Polyline; Elem Class 4; Elem ID 1
02118 // Actually generate the line, if you are writing a program to use this
02119 // library, use this function, not cdImageLine or cdImageDashedLine,
02120 // those are just in for compatiblilty with gd
02121 //
02122 // This function will draw a line using the current line type, width, and color
02123 //
02124 {
02125     unsigned char *es, *esp;
02126     int           octet_count;
02127     short int     sweet;
02128     short int     sour;
02129 
02130     // check to make sure the line is withing the scope of the picture
02131     // ie. the values you give for drawing the line are within
02132     // the values you created the picture with
02133     if ( !( cdImageBoundsSafe( im, x1, y1 ) ) || !( cdImageBoundsSafe( im, x2, y2 ) ) )
02134         return 0;
02135 
02136     // allocate sufficent space.  should be 32 bits * 4 to be safe
02137     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
02138     if ( !es )
02139         return 0;          // memory allocation failed
02140     esp = es;
02141 
02142     if ( !cdcomhead( es, 4, 1, 8 ) )
02143     {
02144         free( esp ); return 0;
02145     }
02146     es         += 2;
02147     octet_count = 2;
02148 
02149     // now we are ready for the parameter data
02150     sweet = (short int) x1;
02151     sour  = sweet >> 8;
02152     *es   = *es | ( sour & 0377 );
02153     es++; octet_count++;
02154     *es = (unsigned char) sweet;
02155     es++; octet_count++;
02156     sweet = (short int) y1;
02157     sour  = sweet >> 8;
02158     *es   = *es | ( sour & 0377 );
02159     es++; octet_count++;
02160     *es = (unsigned char) sweet;
02161     es++; octet_count++;
02162     sweet = (short int) x2;
02163     sour  = sweet >> 8;
02164     *es   = *es | ( sour & 0377 );
02165     es++; octet_count++;
02166     *es = (unsigned char) sweet;
02167     es++; octet_count++;
02168     sweet = (short int) y2;
02169     sour  = sweet >> 8;
02170     *es   = *es | ( sour & 0377 );
02171     es++; octet_count++;
02172     *es = (unsigned char) sweet;
02173     octet_count++;
02174 
02175     // add it to the buffer
02176     if ( cdAddElem( im, esp, octet_count ) )
02177     {
02178         free( esp );
02179         return 1;
02180     }
02181     else
02182     {
02183         free( esp );
02184         return 0;
02185     }
02186 }
02187 
02188 int cdMarker( cdImagePtr im, int x, int y )
02189 // Graphic Primitive: PolyMarker; Elem Class 4; Elem ID 3
02190 // puts a marker in the file, it will have characteristics set by
02191 // cdSetMarkerAttrib
02192 //
02193 {
02194     unsigned char *es, *esp;
02195     int           octet_count;
02196 
02197     // check to make sure the line is withing the scope of the picture
02198     // ie. the values you give for drawing the line are within
02199     // the values you created the picture with
02200     if ( !cdImageBoundsSafe( im, x, y ) )
02201         return 0;
02202 
02203     // allocate sufficent space.  should be 32 bits * 4 to be safe
02204     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
02205     if ( !es )
02206         return 0;          // memory allocation failed
02207     esp = es;
02208 
02209     if ( !cdcomhead( es, 4, 3, 4 ) )
02210     {
02211         free( esp ); return 0;
02212     }
02213     es         += 2;
02214     octet_count = 2;
02215 
02216     octet_count += cdAppShort( es, (short int) x );
02217     es          += 2;
02218     octet_count += cdAppShort( es, (short int) y );
02219     es          += 2;
02220 
02221     // add it to the buffer
02222     if ( cdAddElem( im, esp, octet_count ) )
02223     {
02224         free( esp );
02225         return 1;
02226     }
02227     else
02228     {
02229         free( esp );
02230         return 0;
02231     }
02232 }
02233 
02234 
02235 int cdRectangle( cdImagePtr im, int x1, int y1, int x2, int y2 )
02236 {
02237 // Graphic Primitive: rectangle; Elem Class 4; Elem ID 11
02238 // Actually generate the rectangle, if you are writing a program to use this
02239 // library, use this function, not cdImageRectangle,
02240 // those are just in for compatiblilty with gd
02241 //
02242 // This function will draw a Rectangle using the current
02243 // edge type, width, color, and visibility, and the current
02244 // fill style, color, and hatch
02245 //
02246     unsigned char *es, *esp;
02247     int           octet_count;
02248     short int     sweet;
02249     short int     sour;
02250 
02251     // check to make sure the line is withing the scope of the picture
02252     // ie. the values you give for drawing the line are within
02253     // the values you created the picture with
02254     if ( !( cdImageBoundsSafe( im, x1, y1 ) ) || !( cdImageBoundsSafe( im, x2, y2 ) ) )
02255         return 0;
02256 
02257     // allocate sufficent space.  should be 32 bits * 4 to be safe
02258     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
02259     if ( !es )
02260         return 0;          // memory allocation failed
02261     esp = es;
02262 
02263     // their are four 16 bit signed integers as attributes
02264     if ( !cdcomhead( es, 4, 11, 8 ) )
02265     {
02266         free( esp ); return 0;
02267     }
02268     es += 2; octet_count = 2;
02269 
02270     // now we are ready for the parameter data
02271     sweet = (short int) x1;
02272     sour  = sweet >> 8;
02273     *es   = *es | ( sour & 0377 );
02274     es++; octet_count++;
02275     *es = (unsigned char) sweet;
02276     es++; octet_count++;
02277     sweet = (short int) y1;
02278     sour  = sweet >> 8;
02279     *es   = *es | ( sour & 0377 );
02280     es++; octet_count++;
02281     *es = (unsigned char) sweet;
02282     es++; octet_count++;
02283     sweet = (short int) x2;
02284     sour  = sweet >> 8;
02285     *es   = *es | ( sour & 0377 );
02286     es++; octet_count++;
02287     *es = (unsigned char) sweet;
02288     es++; octet_count++;
02289     sweet = (short int) y2;
02290     sour  = sweet >> 8;
02291     *es   = *es | ( sour & 0377 );
02292     es++; octet_count++;
02293     *es = (unsigned char) sweet;
02294     octet_count++;
02295 
02296     // add it to the buffer
02297     if ( cdAddElem( im, esp, octet_count ) )
02298     {
02299         free( esp );
02300         return 1;
02301     }
02302     else
02303     {
02304         free( esp );
02305         return 0;
02306     }
02307 }
02308 
02309 int cdCircle( cdImagePtr im, int cx, int cy, int r )
02310 {
02311 // Graphic Primitive: circle; Elem Class 4; Elem ID 12
02312 // cx,cy is the center of the circle, r is the radius
02313 //
02314 // This function will draw a Circle using the current
02315 // edge type, width, color, and visibility, and the current
02316 // fill style, color, and hatch
02317 //
02318     unsigned char *es, *esp;
02319     int           octet_count;
02320     short int     sweet;
02321     short int     sour;
02322 
02323     // check to make sure the circle is withing the scope of the picture
02324     // ie. the values you give for drawing the circle are within
02325     // the values you created the picture with
02326     if ( !( cdImageBoundsSafe( im, cx, cy ) ) )
02327         return 0;
02328 
02329     // allocate sufficent space.  should be 32 bits * 4 to be safe
02330     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
02331     if ( !es )
02332         return 0;          // memory allocation failed
02333     esp = es;
02334 
02335     // their are three 16 bit signed integers as attributes
02336     if ( !cdcomhead( es, 4, 12, 6 ) )
02337     {
02338         free( esp ); return 0;
02339     }
02340     es += 2; octet_count = 2;
02341 
02342     // now we are ready for the parameter data
02343     sweet = (short int) cx;
02344     sour  = sweet >> 8;
02345     *es   = *es | ( sour & 0377 );
02346     es++; octet_count++;
02347     *es = (unsigned char) sweet;
02348     es++; octet_count++;
02349     sweet = (short int) cy;
02350     sour  = sweet >> 8;
02351     *es   = *es | ( sour & 0377 );
02352     es++; octet_count++;
02353     *es = (unsigned char) sweet;
02354     es++; octet_count++;
02355     sweet = (short int) r;
02356     sour  = sweet >> 8;
02357     *es   = *es | ( sour & 0377 );
02358     es++; octet_count++;
02359     *es = (unsigned char) sweet;
02360     octet_count++;
02361 
02362 
02363     // add it to the buffer
02364     if ( cdAddElem( im, esp, octet_count ) )
02365     {
02366         free( esp );
02367         return 1;
02368     }
02369     else
02370     {
02371         free( esp );
02372         return 0;
02373     }
02374 }
02375 
02376 int cdArc3Pt( cdImagePtr im, int sx, int sy, int ix, int iy, int ex, int ey )
02377 {
02378 // Graphic Primitive: Cicular Arc 3 Point; Elem Class 4; Elem ID 13
02379 //
02380 // This function will draw a Circular Arc using the current
02381 // Line type, width, and color,
02382 //
02383     unsigned char *es, *esp;
02384     int           octet_count;
02385     short int     sweet;
02386     short int     sour;
02387 
02388     // check to make sure the line is withing the scope of the picture
02389     // ie. the values you give for drawing the line are within
02390     // the values you created the picture with
02391     if ( !( cdImageBoundsSafe( im, sx, sy ) ) || !( cdImageBoundsSafe( im, ix, iy ) ) || !( cdImageBoundsSafe( im, ex, ey ) ) )
02392         return 0;
02393 
02394     // allocate sufficent space.  should be 32 bits * 4 to be safe
02395     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
02396     if ( !es )
02397         return 0;          // memory allocation failed
02398     esp = es;
02399 
02400     // their are six 16 bit signed integers as attributes
02401     if ( !cdcomhead( es, 4, 13, 12 ) )
02402     {
02403         free( esp ); return 0;
02404     }
02405     es += 2; octet_count = 2;
02406 
02407     // now we are ready for the parameter data
02408     sweet = (short int) sx;
02409     sour  = sweet >> 8;
02410     *es   = *es | ( sour & 0377 );
02411     es++; octet_count++;
02412     *es = (unsigned char) sweet;
02413     es++; octet_count++;
02414     sweet = (short int) sy;
02415     sour  = sweet >> 8;
02416     *es   = *es | ( sour & 0377 );
02417     es++; octet_count++;
02418     *es = (unsigned char) sweet;
02419     es++; octet_count++;
02420     sweet = (short int) ix;
02421     sour  = sweet >> 8;
02422     *es   = *es | ( sour & 0377 );
02423     es++; octet_count++;
02424     *es = (unsigned char) sweet;
02425     es++; octet_count++;
02426     sweet = (short int) iy;
02427     sour  = sweet >> 8;
02428     *es   = *es | ( sour & 0377 );
02429     es++; octet_count++;
02430     *es = (unsigned char) sweet;
02431     es++; octet_count++;
02432     sweet = (short int) ex;
02433     sour  = sweet >> 8;
02434     *es   = *es | ( sour & 0377 );
02435     es++; octet_count++;
02436     *es = (unsigned char) sweet;
02437     es++; octet_count++;
02438     sweet = (short int) ey;
02439     sour  = sweet >> 8;
02440     *es   = *es | ( sour & 0377 );
02441     es++; octet_count++;
02442     *es = (unsigned char) sweet;
02443     octet_count++;
02444 
02445     // add it to the buffer
02446     if ( cdAddElem( im, esp, octet_count ) )
02447     {
02448         free( esp );
02449         return 1;
02450     }
02451     else
02452     {
02453         free( esp );
02454         return 0;
02455     }
02456 }
02457 
02458 int cdArc3PtClose( cdImagePtr im, int sx, int sy, int ix, int iy, int ex, int ey, int cl )
02459 {
02460 // Graphic Primitive: Cicular Arc 3 Point Close; Elem Class 4; Elem ID 14
02461 //
02462 // This function will draw a Circle using the current
02463 // edge type, width, color, and visibility, and the current
02464 // fill style, color, and hatch
02465 //
02466 // cd is the closure type.  It can be either 0 for pie closure or
02467 // 1 for chord closure.
02468 //
02469     unsigned char *es, *esp;
02470     int           octet_count;
02471 
02472     // check to make sure the line is withing the scope of the picture
02473     // ie. the values you give for drawing the line are within
02474     // the values you created the picture with
02475     if ( !( cdImageBoundsSafe( im, sx, sy ) ) || !( cdImageBoundsSafe( im, ix, iy ) ) || !( cdImageBoundsSafe( im, ex, ey ) ) )
02476         return 0;
02477 
02478     // make sure that they close the arc either with pie (0) or chord (1)
02479     if ( ( cl != 0 ) && ( cl != 1 ) )
02480         return 0;
02481 
02482     // allocate sufficent space.  should be 32 bits * 6 to be safe
02483     es = (unsigned char *) calloc( 4 * 6, SIZEOF( unsigned char ) );
02484     if ( !es )
02485         return 0;          // memory allocation failed
02486     esp = es;
02487 
02488     // their are seven 16 bit signed integers as attributes
02489     if ( !cdcomhead( es, 4, 14, 14 ) )
02490     {
02491         free( esp ); return 0;
02492     }
02493     es += 2; octet_count = 2;
02494 
02495     // now we are ready for the parameter data
02496     octet_count += cdAppShort( es, (short int) sx );
02497     es          += 2;
02498     octet_count += cdAppShort( es, (short int) sy );
02499     es          += 2;
02500     octet_count += cdAppShort( es, (short int) ix );
02501     es          += 2;
02502     octet_count += cdAppShort( es, (short int) iy );
02503     es          += 2;
02504     octet_count += cdAppShort( es, (short int) ex );
02505     es          += 2;
02506     octet_count += cdAppShort( es, (short int) ey );
02507     es          += 2;
02508     octet_count += cdAppShort( es, (short int) cl );
02509     es          += 2;
02510 
02511     // add it to the buffer
02512     if ( cdAddElem( im, esp, octet_count ) )
02513     {
02514         free( esp );
02515         return 1;
02516     }
02517     else
02518     {
02519         free( esp );
02520         return 0;
02521     }
02522 }
02523 
02524 int cdEllipse( cdImagePtr im, int cx, int cy, int d1x, int d1y, int d2x, int d2y )
02525 {
02526 // Graphic Primitive: Ellipse; Elem Class 4; Elem ID 17
02527 //
02528 // This function will draw an Ellipse using the current
02529 // edge type, width, color, and visibility, and the current
02530 // fill style, color, and hatch
02531 //
02532     unsigned char *es, *esp;
02533     int           octet_count;
02534 
02535     // check to make sure the line is withing the scope of the picture
02536     // ie. the values you give for drawing the line are within
02537     // the values you created the picture with
02538     if ( !( cdImageBoundsSafe( im, cx, cy ) ) || !( cdImageBoundsSafe( im, d1x, d1y ) ) || !( cdImageBoundsSafe( im, d2x, d2y ) ) )
02539         return 0;
02540 
02541     // allocate sufficent space.  should be 32 bits * 4 to be safe
02542     es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
02543     if ( !es )
02544         return 0;          // memory allocation failed
02545     esp = es;
02546 
02547     // their are six 16 bit signed integers as attributes
02548     if ( !cdcomhead( es, 4, 17, 12 ) )
02549     {
02550         free( esp ); return 0;
02551     }
02552     es += 2; octet_count = 2;
02553 
02554     // now we are ready for the parameter data
02555     octet_count += cdAppShort( es, (short int) cx );
02556     es          += 2;
02557     octet_count += cdAppShort( es, (short int) cy );
02558     es          += 2;
02559     octet_count += cdAppShort( es, (short int) d1x );
02560     es          += 2;
02561     octet_count += cdAppShort( es, (short int) d1y );
02562     es          += 2;
02563     octet_count += cdAppShort( es, (short int) d2x );
02564     es          += 2;
02565     octet_count += cdAppShort( es, (short int) d2y );
02566     es          += 2;
02567 
02568     // add it to the buffer
02569     if ( cdAddElem( im, esp, octet_count ) )
02570     {
02571         free( esp );
02572         return 1;
02573     }
02574     else
02575     {
02576         free( esp );
02577         return 0;
02578     }
02579 }
02580 
02581 int cdPolygon( cdImagePtr im, cdPointPtr p, int n )
02582 {
02583 // Graphic Primitive: Polygon; Elem Class 4; Elem ID 7
02584 //
02585 // cdPointPtr is defined in cd.h, basically, it is two arrays of integers
02586 // p[m].x and p[m].y  containing the x and y values respectively.  n
02587 // is the number of points in this array (not the index of the last point,
02588 // which is n-1).  n must be at least 3 (otherwise
02589 // you really don't have much of a polygon, it is closer to a line.)
02590 //
02591 // This function will draw a Polygon using the current
02592 // edge type, width, color, and visibility, and the current
02593 // fill style, color, and hatch
02594 //
02595     unsigned char *es, *esp;
02596     int           octet_count;
02597     int           x;         // counter
02598 
02599     if ( n < 3 )
02600         return 0;            // it is either a point or a line
02601 
02602     if ( n < 8 )
02603     {
02604         // It fits in the short form of the command, lets us
02605         // add it right now, shall we?
02606         // allocate sufficent space. Should be 32 bits*10 to be safe
02607         es = (unsigned char *) calloc( 4 * 10, SIZEOF( unsigned char ) );
02608         if ( !es )
02609             return 0;              // memory allocation failed
02610         esp = es;
02611 
02612 
02613         // their are n*2 16 bit signed integers as attributes
02614         if ( !cdcomhead( es, 4, 7, ( n * 4 ) ) )
02615         {
02616             free( esp ); return 0;
02617         }
02618         es += 2; octet_count = 2;
02619     }
02620     else if ( n < 8191 )
02621     {
02622         // there are more than 7 points in it, that sucks
02623         // gej, so basically, for this one, I set the header
02624         // to cdcomhead(es, 4, 7, 31) then write a function for the long
02625         // form that takes the first 15 bits of n and tags a 0 in front
02626         // of it and puts it in es, than I do the for loop all over again
02627         // that doesn't seem too hard.  But I will leave that for another
02628         // day.
02629         //
02630         // keep in mind that if CDGROWLISTSIZE is smaller than n*4
02631         // (at most 32769) then things could fail in a most unsavory fashion.
02632         //
02633         // allocate sufficent space.  32 bits*(n+1) to be safe
02634         es = (unsigned char *) calloc( 4 * ( n + 1 ), SIZEOF( unsigned char ) );
02635         if ( !es )
02636             return 0;              // memory allocation failed
02637         esp = es;
02638 
02639         if ( !cdcomheadlong( es, 4, 7, ( n * 4 ) ) )
02640         {
02641             free( esp ); return 0;
02642         }
02643         es += 4; octet_count = 4;
02644     }
02645     else
02646     {
02647         // there are more than 8191 points in it, I am not going to implement
02648         // that, if you want it that bad, do it yourself.
02649         return 0;
02650     }
02651 
02652 
02653     for ( x = 0; x < n; x++ )
02654     {
02655         // now we are ready for the parameter data
02656         es          += cdAppShort( es, (short int) p->x );
02657         es          += cdAppShort( es, (short int) p->y );
02658         octet_count += 4;
02659         p++;
02660     }
02661 
02662     // add it to the buffer
02663     if ( cdAddElem( im, esp, octet_count ) )
02664     {
02665         free( esp );
02666         return 1;
02667     }
02668     else
02669     {
02670         free( esp );
02671         return 0;
02672     }
02673 }
02674 
02675 int cdPolygonSet( cdImagePtr im, cdPointPtr p, int n )
02676 {
02677 // Graphic Primitive: Polygon; Elem Class 4; Elem ID 8
02678 //
02679 // cdPointPtr is defined in cd.h, basically, it is three arrays of integers
02680 // p[m].x and p[m].y  containing the x and y values respectively and p[m].e
02681 // the characteristics of the line leaving point n (0=invisible,1=visible,
02682 // 2=close,invisible, 3=close,visible).  n is the number of points in this
02683 // array (not the index of the last point, which is n-1).
02684 // n must be at least 3 (otherwise you really don't have much of a polygon,
02685 // it is closer to a line.)
02686 //
02687 // This function will draw a set of Polygons using the current
02688 // edge type, width, color, and the current
02689 // fill style, color, and hatch
02690 //
02691     unsigned char *es, *esp;
02692     int           octet_count;
02693     int           x;         // counter
02694 
02695     if ( n < 3 )
02696         return 0;            // it is either a point or a line
02697 
02698     if ( n < 6 )
02699     {
02700         // It fits in the short form of the command, lets us
02701         // add it right now, shall we?
02702         // allocate sufficent space. Should be 48 bits*10 to be safe
02703         es = (unsigned char *) calloc( 6 * 10, SIZEOF( unsigned char ) );
02704         if ( !es )
02705             return 0;              // memory allocation failed
02706         esp = es;
02707 
02708 
02709         // their are n*2 16 bit signed integers as attributes
02710         if ( !cdcomhead( es, 4, 8, ( n * 6 ) ) )
02711         {
02712             free( esp ); return 0;
02713         }
02714         es += 2; octet_count = 2;
02715     }
02716     else if ( n < 5462 )
02717     {
02718         // there are more than 5 points in it, that sucks
02719         // gej, so basically, for this one, I set the header
02720         // to cdcomhead(es, 4, 7, 31) then write a function for the long
02721         // form that takes the first 15 bits of n and tags a 0 in front
02722         // of it and puts it in es, than I do the for loop all over again
02723         // that doesn't seem too hard.  But I will leave that for another
02724         // day.
02725         //
02726         // keep in mind that if CDGROWLISTSIZE is smaller than n*6
02727         // (at most 32769) then things could fail in a most unsavory fashion.
02728         //
02729         // allocate sufficent space.  48 bits*(n+1) to be safe
02730         es = (unsigned char *) calloc( 6 * ( n + 1 ), SIZEOF( unsigned char ) );
02731         if ( !es )
02732             return 0;              // memory allocation failed
02733         esp = es;
02734 
02735         if ( !cdcomheadlong( es, 4, 8, ( n * 6 ) ) )
02736         {
02737             free( esp ); return 0;
02738         }
02739         es += 4; octet_count = 4;
02740     }
02741     else
02742     {
02743         // there are more than 5462 points in it, I am not going to implement
02744         // that, if you want it that bad, do it yourself.
02745         return 0;
02746     }
02747 
02748 
02749     for ( x = 0; x < n; x++ )
02750     {
02751         // now we are ready for the parameter data
02752         es          += cdAppShort( es, (short int) p->x );
02753         es          += cdAppShort( es, (short int) p->y );
02754         es          += cdAppShort( es, (short int) p->e );
02755         octet_count += 6;
02756         p++;
02757     }
02758 
02759     // add it to the buffer
02760     if ( cdAddElem( im, esp, octet_count ) )
02761     {
02762         free( esp );
02763         return 1;
02764     }
02765     else
02766     {
02767         free( esp );
02768         return 0;
02769     }
02770 }
02771 
02772 int cdPolyLine( cdImagePtr im, cdPointPtr p, int n )
02773 {
02774 // Graphic Primitive: Polyline; Elem Class 4; Elem ID 1
02775 //
02776 // cdPointPtr is defined in cd.h, basically, it is two arrays of integers
02777 // p[m].x and p[m].y  containing the x and y values respectively.  n
02778 // is the number of points in this array (not the index of the last point,
02779 // which is n-1).  if n is 2, it is a regular line, like cdline
02780 //
02781 // This function will draw a Polyline using the current
02782 // line type, width, color, and visibility,
02783 //
02784     unsigned char *es, *esp;
02785     int           octet_count;
02786     int           x;         // counter
02787 
02788     if ( n < 2 )
02789         return 0;            // it is a point
02790 
02791     if ( n < 8 )
02792     {
02793         // It fits in the short form of the command, lets us
02794         // add it right now, shall we?
02795         // allocate sufficent space. Should be 32 bits*10 to be safe
02796         es = (unsigned char *) calloc( 4 * 10, SIZEOF( unsigned char ) );
02797         if ( !es )
02798             return 0;              // memory allocation failed
02799         esp = es;
02800 
02801 
02802         // their are n*2 16 bit signed integers as attributes
02803         if ( !cdcomhead( es, 4, 1, ( n * 4 ) ) )
02804         {
02805             free( esp ); return 0;
02806         }
02807         es += 2; octet_count = 2;
02808     }
02809     else if ( n < 8191 )
02810     {
02811         // there are more than 7 points in it, that sucks
02812         // gej, so basically, for this one, I set the header
02813         // using the long version cdcomheadlong(es, 4, 1, n*4)
02814         //
02815         // keep in mind that if CDGROWLISTSIZE is smaller than n*4
02816         // (at most 32769) then the list may have to grow several times
02817         //
02818         // allocate sufficent space.  32 bits*(n+1) to be safe
02819         es = (unsigned char *) calloc( 4 * ( n + 1 ), SIZEOF( unsigned char ) );
02820         if ( !es )
02821             return 0;              // memory allocation failed
02822         esp = es;
02823 
02824         if ( !cdcomheadlong( es, 4, 1, ( n * 4 ) ) )
02825         {
02826             free( esp ); return 0;
02827         }
02828         es += 4; octet_count = 4;
02829     }
02830     else
02831     {
02832         // there are more than 8191 points in it, I am not going to implement
02833         // that, if you want it that bad, do it yourself.
02834         return 0;
02835     }
02836 
02837     for ( x = 0; x < n; x++ )
02838     {
02839         // now we are ready for the parameter data
02840         es          += cdAppShort( es, (short int) p->x );
02841         es          += cdAppShort( es, (short int) p->y );
02842         octet_count += 4;
02843         p++;
02844     }
02845 
02846     // add it to the buffer
02847     if ( cdAddElem( im, esp, octet_count ) )
02848     {
02849         free( esp );
02850         return 1;
02851     }
02852     else
02853     {
02854         free( esp );
02855         return 0;
02856     }
02857 }
02858 
02859 int cdPolyMarker( cdImagePtr im, cdPointPtr p, int n )
02860 {
02861 // Graphic Primitive: PolyMarker; Elem Class 4; Elem ID 3
02862 //
02863 // cdPointPtr is defined in cd.h, basically, it is two arrays of integers
02864 // p[m].x and p[m].y  containing the x and y values respectively.  n
02865 // is the number of points in this array (not the index of the last point,
02866 // which is n-1).  if n is 2, it is a regular line, like cdline
02867 //
02868 // This function will insert n markers using the current
02869 // Marker type, width, color, and visibility,
02870 //
02871     unsigned char *es, *esp;
02872     int           octet_count;
02873     int           x;         // counter
02874 
02875     if ( n < 1 )
02876         return 0;            // it is nothing
02877     if ( n < 8 )
02878     {
02879         // It fits in the short form of the command, lets us
02880         // add it right now, shall we?
02881         // allocate sufficent space. Should be 32 bits*10 to be safe
02882         es = (unsigned char *) calloc( 4 * 10, SIZEOF( unsigned char ) );
02883         if ( !es )
02884             return 0;              // memory allocation failed
02885         esp = es;
02886 
02887 
02888         // their are n*2 16 bit signed integers as attributes
02889         if ( !cdcomhead( es, 4, 3, ( n * 4 ) ) )
02890         {
02891             free( esp ); return 0;
02892         }
02893         es += 2; octet_count = 2;
02894     }
02895     else if ( n < 8191 )
02896     {
02897         // there are more than 7 points in it, that sucks
02898         // gej, so basically, for this one, I set the header
02899         // using the long version cdcomheadlong(es, 4, 1, n*4)
02900         //
02901         // keep in mind that if CDGROWLISTSIZE is smaller than n*4
02902         // (at most 32769) then the list may have to grow several times
02903         //
02904         // allocate sufficent space.  32 bits*(n+1) to be safe
02905         es = (unsigned char *) calloc( 4 * ( n + 1 ), SIZEOF( unsigned char ) );
02906         if ( !es )
02907             return 0;              // memory allocation failed
02908         esp = es;
02909 
02910         if ( !cdcomheadlong( es, 4, 3, ( n * 4 ) ) )
02911         {
02912             free( esp ); return 0;
02913         }
02914         es += 4; octet_count = 4;
02915     }
02916     else
02917     {
02918         // there are more than 8191 points in it, I am not going to implement
02919         // that, if you want it that bad, do it yourself.
02920         return 0;
02921     }
02922 
02923     for ( x = 0; x < n; x++ )
02924     {
02925         // now we are ready for the parameter data
02926         es          += cdAppShort( es, (short int) p->x );
02927         es          += cdAppShort( es, (short int) p->y );
02928         octet_count += 4;
02929         p++;
02930     }
02931 
02932     // add it to the buffer
02933     if ( cdAddElem( im, esp, octet_count ) )
02934     {
02935         free( esp );
02936         return 1;
02937     }
02938     else
02939     {
02940         free( esp );
02941         return 0;
02942     }
02943 }
02944 
02945 int cdText( cdImagePtr im, int x, int y, const char *ts )
02946 {
02947 // Graphic Primitive: Text; Elem Class 4; Elem ID 4
02948 // add text to the picture.  Start it at the point (x,y)
02949 // this should be the lower left corner of where the text is
02950 // the parameters are point, enumerated(set to 1), string
02951 //
02952 // String encoding in CGM is a little strange.  After you have the other
02953 // parameter info, the first octet for the string is either 0..254 which
02954 // is the number of octets of string data, or 255 which signifies a long
02955 // string.  if it is 255 then the next 16 bits indicate the length of the
02956 // string.  the first bit (bit15) is 0 if this is the last part of the
02957 // string and 1 if another part follows it.  the next 15 bits  are in the
02958 // range 0..32767 and are the number of octets of string info following.
02959 // so the length stored in the command header is the whole enchelada.
02960 //
02961     int           tslen, curly;
02962     unsigned char *es, *esp;
02963     int           octet_count;
02964 
02965     // check to make sure the Text is within the scope of the picture
02966     // actually, I am only checking the start of it
02967     //
02968     if ( !( cdImageBoundsSafe( im, x, y ) ) )
02969         return 0;
02970 
02971     // allocate sufficent space.  should be tslen+ 32 bits * 4 to be safe
02972     tslen = strlen( ts );
02973 
02974     // if there are more than 32700 characters fail
02975     // gej: this could go as high as 32767 I think, but lets
02976     // cut it off at 32700
02977     if ( ( tslen > 32700 ) || ( tslen < 0 ) )
02978         return 0;
02979 
02980     es = (unsigned char *) calloc( ( ( 4 * 4 ) + tslen ), SIZEOF( unsigned char ) );
02981     if ( !es )
02982         return 0;          // memory allocation failed
02983     esp = es;
02984 
02985     if ( !cdcomheadlong( es, 4, 4, 9 + tslen ) )
02986     {
02987         free( esp ); return 0;
02988     }
02989     es += 4; octet_count = 4;
02990 
02991     // add the x position, the y position, then 1, which signifies
02992     // that this is all the text, there is none appended after it
02993     es          += cdAppShort( es, (short int) x );
02994     es          += cdAppShort( es, (short int) y );
02995     es          += cdAppShort( es, (short int) 1 );
02996     octet_count += 6;
02997 
02998     // now take care of the string information, for strings 254 bytes
02999     // or less, I could use a short one, but why bother, use the long
03000     // form for everything
03001     es          += cdAppByte( es, (short int) 255 );
03002     es          += cdAppShort( es, (short int) tslen );
03003     octet_count += 3;
03004     // gej: I should set bit 15 to 0 because it is the final part of a
03005     // string but I am not going to since I already checked that it was
03006     // a 16 number that was non-negative
03007 
03008     while ( *ts )
03009     {
03010         *es++ = (unsigned char) *ts++;
03011     }
03012     octet_count += tslen;
03013     // now if the octet_count is not divisible by 4 add null padding
03014     curly = 4 - ( octet_count % 4 );
03015     if ( curly % 4 )
03016     {
03017         octet_count += curly;
03018         es          += cdAppNull( es, curly );
03019     }
03020 
03021     // add it to the buffer
03022     if ( cdAddElem( im, esp, octet_count ) )
03023     {
03024         free( esp );
03025         return 1;
03026     }
03027     else
03028     {
03029         free( esp );
03030         return 0;
03031     }
03032 }
03033 
03034 int cdImageLine( cdImagePtr im, int x1, int y1, int x2, int y2, int color )
03035 // gej: this should be so much easier to do as a cgm
03036 // This is in for compatibility with gd, if you don't need that, use
03037 // cdLine instead
03038 {
03039     int ltstate;
03040 
03041 
03042     // save the linetype state
03043     ltstate = im->ltype;
03044     // set the attributes of the line
03045     if ( !cdSetLineAttrib( im, 1, -1, color ) )
03046         return 0;
03047     if ( !cdLine( im, x1, y1, x2, y2 ) )
03048         return 0;                                  // draw the line
03049     // restore the state If it fails, don't return an error, because
03050     // the line was still drawn
03051     cdSetLineType( im, ltstate );
03052 
03053     return 1;
03054 }
03055 
03056 int cdImageDashedLine( cdImagePtr im, int x1, int y1, int x2, int y2, int color )
03057 // gej: this should be so much easier to do as a cgm
03058 // in order to really get a dashed line you must call cdSetLineType first
03059 // This is in for compatibility with gd, if you don't need that, use
03060 // cdLine instead
03061 {
03062     // set the attributes of the line
03063     if ( !cdSetLineAttrib( im, -1, -1, color ) )
03064         return 0;
03065     // generate the line
03066     if ( !cdLine( im, x1, y1, x2, y2 ) )
03067         return 0;
03068 
03069     // everthing is A-OK
03070     return 1;
03071 }
03072 
03073 int cdImageBoundsSafe( cdImagePtr im, int x, int y )
03074 // From gd library, see README file for copyright information
03075 // gej: this should work unchanged
03076 {
03077     return ( !( ( ( y < 0 ) || ( y >= im->sy ) ) ||
03078                 ( ( x < 0 ) || ( x >= im->sx ) ) ) );
03079 }
03080 
03081 
03082 int cdImageRectangle( cdImagePtr im, int x1, int y1, int x2, int y2, int color )
03083 // Graphic Primitive: rectangle; Elem Class 4; Elem ID 11
03084 //
03085 
03086 // gej: but I think I will use the cgm rectangle
03087 {
03088     if ( !cdImageLine( im, x1, y1, x2, y1, color ) )
03089         return 0;
03090     if ( !cdImageLine( im, x1, y2, x2, y2, color ) )
03091         return 0;
03092     if ( !cdImageLine( im, x1, y1, x1, y2, color ) )
03093         return 0;
03094     if ( !cdImageLine( im, x2, y1, x2, y2, color ) )
03095         return 0;
03096 
03097     return 1;
03098 }
03099 
03100 
03101 // Expert functions.  If you need more control, you can use these
03102 // functions, but you probably won't need to.
03103 
03104 int cdImageSetSize( cdImagePtr im, int x, int y )
03105 // sets the width and height of subsequent pictures.
03106 {
03107     im->sx = x;
03108     im->sy = y;
03109     return 1;
03110 }
03111 
03112 int cdImageSetLineSpec( cdImagePtr im, int specmode )
03113 // Picture Descriptor: Line Width Specification Mode; Elem Class 2; Elem ID 3
03114 // sets the Line Width Specification mode of subsequent pictures.
03115 // 1 is scaled (default), 2 is absolute
03116 {
03117     if ( ( specmode < 0 ) || ( specmode > 2 ) )
03118         return 0;
03119     im->linespec = specmode;
03120     return 1;
03121 }
03122 
03123 int cdImageSetMarkerSpec( cdImagePtr im, int specmode )
03124 // Picture Descriptor: Marker Size Specification Mode; Elem Class 2; Elem ID 4
03125 // sets the Marker Width Specification mode of subsequent pictures.
03126 // 1 is scaled (default), 2 is absolute
03127 {
03128     if ( ( specmode < 0 ) || ( specmode > 2 ) )
03129         return 0;
03130     im->linespec = specmode;
03131     return 1;
03132 }
03133 
03134 int cdImageSetEdgeSpec( cdImagePtr im, int specmode )
03135 // Picture Descriptor: Edge Width Specification Mode; Elem Class 2; Elem ID 5
03136 // sets the Edge Width Specification mode of subsequent pictures.
03137 // 1 is scaled (default), 2 is absolute
03138 {
03139     if ( ( specmode < 0 ) || ( specmode > 2 ) )
03140         return 0;
03141     im->edgespec = specmode;
03142     return 1;
03143 }
03144 
03145 int cdImageSetOutput( cdImagePtr im, FILE *output )
03146 // sets the output file to *output.  which must already be open.
03147 // does not close the file
03148 // Useful if you want to write the file as you go along, or if you
03149 // want to write it to a stream
03150 //
03151 {
03152     if ( output )
03153     {
03154         im->outfile = output;
03155         return 1;
03156     }
03157     else
03158     {
03159         return 0;
03160     }
03161 }
03162 
03163 int cdImageAddFont( cdImagePtr im, const char *fontname )
03164 // adds a font to the list of fonts.  This only has an effect
03165 // if you are using the expert functions for starting pictures, and
03166 // have not yet opened the first picture.  Returns 0 for failure,
03167 // and the font index on success
03168 {
03169     unsigned char *oldfonts;
03170     int           listsize;
03171     oldfonts = im->fontlist;
03172     if ( oldfonts )
03173     {
03174         listsize = strlen( (char *) oldfonts ) + 1 + strlen( fontname ) + 1;
03175     }
03176     else
03177     {
03178         listsize = strlen( fontname ) + 1;
03179     }
03180     im->fontlist = (unsigned char *) calloc( listsize, SIZEOF( unsigned char ) );
03181     if ( !im->fontlist )
03182         return 0;                    // memory allocation failed
03183     if ( oldfonts )
03184     {
03185         sprintf( (char *) im->fontlist, "%s%s%s", (char *) oldfonts, ",", fontname );
03186     }
03187     else
03188     {
03189         sprintf( (char *) im->fontlist, "%s", fontname );
03190     }
03191     im->numfonts++;
03192     if ( oldfonts )
03193         free( oldfonts );
03194     oldfonts = NULL;
03195     return im->numfonts;
03196 }
03197 
03198 int cdImageClearFonts( cdImagePtr im )
03199 // clears out ALL fonts from the font list, including the ones the
03200 // package has be default.  Useful if you want totally different fonts.
03201 //
03202 {
03203     free( im->fontlist );
03204     im->fontlist = NULL;
03205     im->numfonts = 0;
03206     return 1;
03207 }
03208 
03209 int cdImageSetDefaults( cdImagePtr im )
03210 // resets the defaults to what is in defines.h
03211 {
03212     // you must be either before any picture has been created,
03213     // or after a picture has closed to call this
03214     if ( ( im->state != 0 ) && ( im->state != 2 ) )
03215         return 0;
03216     // set line_width, line_height, line_color to the defaults
03217     im->ltype  = CDLTYPE;
03218     im->lwidth = CDLWIDTH;
03219     im->lcolor = CDLCOLOR;
03220     // interior_style, fill_color, hatch_index
03221     im->shapestyle = CDSHAPESTYLE;
03222     im->shapecolor = CDSHAPECOLOR;
03223     im->shapehatch = CDSHAPEHATCH;
03224     // edge_type, edge_width, edge_color, edge_visibility
03225     im->edgetype  = CDEDGETYPE;
03226     im->edgecolor = CDEDGECOLOR;
03227     im->edgewidth = CDEDGEWIDTH;
03228     im->edgevis   = CDEDGEVIS;
03229     // text_color, text_height, text_font
03230     im->textcolor  = CDTEXTCOLOR;
03231     im->textheight = CDTEXTHEIGHT;
03232     im->textfont   = CDTEXTFONT;
03233     im->textpath   = CDTEXTPATH;
03234     // set marker_width, marker_size, marker_color to the defaults
03235     im->ltype  = CDMTYPE;
03236     im->lwidth = CDMSIZE;
03237     im->lcolor = CDMCOLOR;
03238     // this is set by the expert functions.  the defaults should be ok
03239     im->linespec   = CDLINESPEC;
03240     im->edgespec   = CDEDGESPEC;
03241     im->markerspec = CDMARKERSPEC;
03242 
03243     return 1;
03244 }
03245 
03246 cdImagePtr cdImageStartCgm()
03247 // initializes the CGM and sets up the defaults.  If you are using
03248 // the "expert" functions, you should call this first. _ge
03249 {
03250     const char *tmps;
03251     int        tmpsl;
03252     cdImagePtr im;
03253     im = (cdImage *) calloc( SIZEOF( cdImage ), 1 );
03254     if ( !im )
03255         return 0;          // memory allocation failed
03256     // elemlist is set to some number, when it is full, make it bigger
03257     im->elemlist = (unsigned char *) calloc( CDSTARTLISTSIZE, SIZEOF( unsigned char ) );
03258     if ( !im->elemlist )
03259     {
03260         free( im ); return 0;
03261     }                                           // memory allocation failed
03262     im->colorsTotal = 0;
03263     // you can have multiple pictures in a file,  keep track of
03264     // which one you are on
03265     im->picnum  = 0;
03266     im->outfile = NULL;
03267     // the next three are used for maintaining the element list
03268     // don't change these ever
03269     im->bytestoend  = CDSTARTLISTSIZE;
03270     im->listlen     = CDSTARTLISTSIZE;
03271     im->curelemlist = im->elemlist;
03272 
03273     // don't make this longer than 250 characters
03274     tmps  = "'ProfileId: Model-Profile''ProfileEd:1''ColourClass:colour''Source:NIST CGMDraw 1.3''Date: 1996-12-16'";
03275     tmpsl = strlen( tmps );
03276     if ( tmpsl > 250 )
03277         tmpsl = 250;
03278     im->desc = (unsigned char *) calloc( tmpsl + 1, SIZEOF( unsigned char ) );
03279     strncpy( (char *) im->desc, tmps, tmpsl );
03280     // The font list can be quite long, but individual font names can
03281     // can only be 250 chars
03282     tmps         = "TIMES_ROMAN,TIMES_BOLD,TIMES_ITALIC,TIMES_BOLD_ITALIC,HELVETICA,HELVETICA_BOLD,HELVETICA_ITALIC,HELVETICA_BOLD_ITALIC,COURIER,COURIER_BOLD,COURIER_ITALIC,COURIER_BOLD_ITALIC";
03283     im->numfonts = 12;
03284     tmpsl        = strlen( tmps );
03285     im->fontlist = (unsigned char *) calloc( tmpsl + 1, SIZEOF( unsigned char ) );
03286     strcpy( (char *) im->fontlist, tmps );
03287     im->outfile = NULL;
03288 
03289     if ( !cdImageSetDefaults( im ) )
03290     {
03291         cdImageDestroy( im );
03292     }
03293     // set the state
03294     im->state = 0;     // 0 no pictures started, 1 in a picture,
03295                        // 2 after a picture
03296 
03297     return im;
03298 }
03299 
03300 int cdImageEndPic( cdImagePtr im )
03301 // close the current picture
03302 {
03303     unsigned char *es, *esp;
03304     int           octet_count = 0;
03305 
03306     // make sure we are really in a picture before ending it
03307     if ( im->state != 1 )
03308     {
03309         return 0;
03310     }
03311 
03312     esp = (unsigned char *) calloc( 1024, SIZEOF( unsigned char ) );
03313     if ( !esp )
03314         return 0;           // memory allocation failed
03315     es = esp;
03316 
03317     // Attribute: End Picture; Elem Class 0; Elem ID 5; Length 0
03318     if ( !cdcomhead( es, 0, 5, 0 ) )
03319     {
03320         free( esp ); return 0;
03321     }
03322     octet_count += 2;
03323 
03324     if ( cdAddElem( im, esp, octet_count ) )
03325     {
03326         free( esp );
03327         im->state = 2;
03328         return 1;
03329     }
03330     else
03331     {
03332         free( esp );
03333         return 0;
03334     }
03335 }
03336 
03337 int cdImageEndCgm( cdImagePtr im )
03338 // close the current CGM file.  If an output stream is
03339 // defined, write the CGM to it
03340 {
03341     int           x;                   // counter
03342     int           used;                // number of bytes used in the list
03343     unsigned char *efile, *efilep;     // end of file information
03344 
03345     cdImageEndPic( im );
03346     if ( im->state == 2 )     // We have closed the pic, but not the CGM
03347     {
03348         efile = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
03349         if ( !efile )
03350             return 0;                 // memory allocation failed
03351         efilep = efile;
03352         // Attribute: End Metafile; Elem Class 0; Elem ID 2
03353         cdcomhead( efilep, 0, 2, 0 );
03354 
03355 
03356         if ( cdAddElem( im, efile, 2 ) )
03357         {
03358             free( efile );
03359             efile  = 0;
03360             efilep = 0;
03361         }
03362         else
03363         {
03364             free( efile );
03365             return 0;
03366         }
03367     }
03368 
03369     if ( im->outfile )
03370     {
03371         // now output the CGM, one byte at a time
03372         used = im->listlen - im->bytestoend;
03373         for ( x = 0; x < used; x++ )
03374         {
03375             putc( (unsigned char) im->elemlist[x], im->outfile );
03376         }
03377     }     // else do nothing
03378 
03379     return 1;
03380 }

Generated on Wed Oct 12 2011 20:42:21 for PLplot by  doxygen 1.7.1