/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkCGMWriter.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkCGMWriter.h" #include "vtkMath.h" #include "vtkUnsignedCharArray.h" #include "vtkViewport.h" #include "vtkIdList.h" #include "vtkPolyData.h" #include "vtkCellArray.h" #include "vtkGenericCell.h" #include "vtkCellData.h" #include "vtkObjectFactory.h" vtkCxxRevisionMacro(vtkCGMWriter, "$Revision: 1.20 $"); vtkStandardNewMacro(vtkCGMWriter); vtkCxxSetObjectMacro(vtkCGMWriter, Viewport, vtkViewport); vtkCGMWriter::vtkCGMWriter() { this->Viewport = NULL; this->ColorMode = VTK_COLOR_MODE_DEFAULT; this->SpecifiedColor[0] = 1.0; this->SpecifiedColor[1] = 1.0; this->SpecifiedColor[2] = 1.0; this->Resolution = 10000; this->Sort = 0; } vtkCGMWriter::~vtkCGMWriter() { if ( this->Viewport != NULL ) { this->Viewport->Delete(); this->Viewport = NULL; } } //--------------------------#defines and method descriptions for CGM output //---defines.h #define b0 01 #define b1 02 #define b2 04 #define b3 010 #define b4 020 #define b5 040 #define b6 0100 #define b7 0200 #define b8 0400 #define b9 01000 #define b10 02000 #define b11 04000 #define b12 010000 #define b13 020000 #define b14 040000 #define b15 0100000 // Defines the default values for different attributes. In general, // these track the CGM specificaition, so changing them is not a good idea. // however, it is generally ok to set them to -1 (undefined) if you want. // #define CGMLTYPE 1 #define CGMLWIDTH 0 #define CGMLCOLOR 1 #define CGMSHAPESTYLE 0 #define CGMSHAPECOLOR 1 #define CGMSHAPEHATCH 1 #define CGMEDGETYPE 1 #define CGMEDGECOLOR 1 #define CGMEDGEWIDTH 1 #define CGMEDGEVIS 0 #define CGMTEXTFONT 1 #define CGMTEXTCOLOR 1 #define CGMTEXTHEIGHT -1 #define CGMTEXTPATH 0 #define CGMMTYPE 1 #define CGMMSIZE 0 #define CGMMCOLOR 1 #define CGMLINESPEC 1 #define CGMEDGESPEC 1 #define CGMMARKERSPEC 1 //--the include file CGM.h // This can not be changed to a value larger than 256, though smaller // values can be used. // #define cgmMaxColors 256 // If you know you will be working with large pictures, increase the values // of the next two constants. // // The initial size of the element list. When it fills up, we will just // make it bigger. Starting with a larger number reduces the frequency of // the list growing, but increases the memory needed for small pictures // #define CGMSTARTLISTSIZE 4096 // How much the element list grows by. When the list fills up, we allocate // a new larger list. This number is how much larger. using a larger number // decreases the frequency of the list growing, but if only a small amount // more is needed, it could waste memory // #define CGMGROWLISTSIZE 2048 // Image type. See functions below; you will not need to change // the elements directly. Use the provided macros to // access sx, sy, the color table, and colorsTotal for // read-only purposes. typedef struct cgmImageStruct { // Don't mess with these unsigned char * elemlist; short int state; int red[cgmMaxColors]; int green[cgmMaxColors]; int blue[cgmMaxColors]; int open[cgmMaxColors]; int colorsTotal; // You can have multiple pictures in the file, this keeps track // of which one you are on int picnum; // these take effect only when the first picture is created. // subsequent changes have no effect unsigned char *desc; unsigned char *fontlist; short int numfonts; FILE *outfile; // these take effect when a new picture is opened. Subsequent // changes are for the next picture int linespec; int edgespec; int markerspec; int sx; int sy; // these take effect immediately // Linetype, line width, line color have a broader scope in CGM int ltype; int lwidth; int lcolor; // interior style [of filled objects] (for me) can be empty, hollow, // solid, hatch [don't do pattern, geometric pattern, interpolated int shapestyle; // fill color, color used on inside of closed objects, significant // if interior style is hollow, solid, hatch, or geometric pattern int shapecolor; // hatch index, which hatch style to use, 1=horizontal, 2=vertical, // 3=pos.slope, 4=neg.slope, 5=hor/vert.crosshatch, // 6=pos/neg.crosshatch int shapehatch; // The edges of filled shapes can have line styles too. They // correspond to the ones for lines. These next few set them. int edgetype; int edgewidth; int edgecolor; int edgevis; // is the edge visible or invisible // now for the TEXT related attributes, Text Color, Text Height, // and Text font index int textfont; int textcolor; int textheight; int textpath; // Marker type, Marker size, marker color int mtype; int msize; int mcolor; // the next three are used for maintaining the element list long int bytestoend; // number of bytes to end of the element list long int listlen; // the total length of the element list unsigned char * curelemlist; // where we curently are in the list } cgmImage; typedef cgmImage* cgmImagePtr; // Point type for use in polygon drawing. typedef struct cgmPointStruct{ int x, y, e; } cgmPoint, *cgmPointPtr; // Functions to manipulate images. static cgmImagePtr cgmImageCreate(int sx, int sy); #ifdef VTK_NOT_DEFINED static int cgmCgmNewPic(cgmImagePtr im, int sticky); #endif static int cgmImageCgm(cgmImagePtr im, FILE *); static int cgmImageDestroy(cgmImagePtr im); #ifdef VTK_NOT_DEFINED // Use cgmLine, not cgmImageLine static int cgmLine(cgmImagePtr im, int x1, int y1, int x2, int y2); // Specify corners (not width and height). Upper left first, lower right second. static int cgmRectangle(cgmImagePtr im, int x1, int y1, int x2, int y2); // center x, then center y, then radius of circle static int cgmCircle(cgmImagePtr im, int cx, int cy, int r); // start, middle and end of arc static int cgmArc3Pt(cgmImagePtr im, int sx,int sy, int ix,int iy, int ex,int ey); // cl is 0 for pie closure, 1 for cord closure static int cgmArc3PtClose(cgmImagePtr im, int sx,int sy, int ix,int iy, int ex,int ey, int cl); static int cgmEllipse(cgmImagePtr im, int cx,int cy, int d1x,int d1y, int d2x,int d2y ); static int cgmMarker(cgmImagePtr im, int x, int y); #endif // polyshapes static int cgmPolygon(cgmImagePtr im, cgmPointPtr p, int n); #ifdef VTK_NOT_DEFINED static int cgmPolygonSet(cgmImagePtr im, cgmPointPtr p, int n); #endif static int cgmPolyLine(cgmImagePtr im, cgmPointPtr p, int n); static int cgmPolyMarker(cgmImagePtr im, cgmPointPtr p, int n); // Functions for Compatibility with gd #ifdef VTK_NOT_DEFINED static int cgmImageLine(cgmImagePtr im, int x1, int y1, int x2, int y2, int color); static int cgmImageRectangle(cgmImagePtr im, int x1, int y1, int x2, int y2, int color); #endif #ifdef VTK_NOT_DEFINED static int cgmImageBoundsSafe(cgmImagePtr im, int x, int y); // These put characters in the picture. CGM can handle fonts // (x,y) is the lower left corner of where the text goes static int cgmText(cgmImagePtr im, int x, int y, const char *); #endif // Functions for allocating colors static int cgmImageColorAllocate(cgmImagePtr im, int r, int g, int b); #ifdef VTK_NOT_DEFINED static int cgmImageColorClosest(cgmImagePtr im, int r, int g, int b); static int cgmImageColorExact(cgmImagePtr im, int r, int g, int b); static int cgmImageColorDeallocate(cgmImagePtr im, int color); #endif static int cgmImageColorGet(cgmImagePtr im, int cgmIndex, int& r, int& g, int& b); #ifdef VTK_NOT_DEFINED // wogl: the parameter names are commented to avoid compiler warnings static int cgmImageColor16(cgmImagePtr im); #endif // gej: functions that set style attributes static int cgmSetLineAttrib(cgmImagePtr im, int lntype, int lnwidth, int lncolor); static int cgmSetShapeFillAttrib(cgmImagePtr im, int instyle, int incolor, int inhatch); static int cgmSetShapeEdgeAttrib(cgmImagePtr im, int edtype, int edwidth, int edcolor, int edvis); static int cgmSetTextAttrib(cgmImagePtr im, int font, int color, int height); static int cgmSetMarkerAttrib(cgmImagePtr im, int mtype, int msize, int mcolor); // gej: or if you prefer, set the attributes individually static int cgmSetLineType(cgmImagePtr im, int lntype); static int cgmSetLineWidth(cgmImagePtr im, int lnwidth); static int cgmSetLineColor(cgmImagePtr im, int lncolor); static int cgmSetFillStyle(cgmImagePtr im, int instyle); static int cgmSetFillColor(cgmImagePtr im, int incolor); static int cgmSetFillHatch(cgmImagePtr im, int inhatch); static int cgmSetEdgeType(cgmImagePtr im, int edtype); static int cgmSetEdgeWidth(cgmImagePtr im, int edwidth); static int cgmSetEdgeColor(cgmImagePtr im, int edcolor); static int cgmSetEdgeVis(cgmImagePtr im, int edvis); static int cgmSetTextFont(cgmImagePtr im, int font); static int cgmSetTextColor(cgmImagePtr im, int color); static int cgmSetTextHeight(cgmImagePtr im, int height); // geJ: these individual attributes can't be set with a group function static int cgmSetTextPath(cgmImagePtr im, int tpath); #ifdef VTK_NOT_DEFINED static int cgmSetTextOrient(cgmImagePtr im, int xup, int yup, int xbase, int ybase); #endif static int cgmSetMarkerType(cgmImagePtr im, int mtype); static int cgmSetMarkerSize(cgmImagePtr im, int msize); static int cgmSetMarkerColor(cgmImagePtr im, int mcolor); // EJ: Expert Functions, If you just need more control static int cgmImageSetSize(cgmImagePtr im, int x, int y); #ifdef VTK_NOT_DEFINED static int cgmImageSetLineSpec(cgmImagePtr im, int specmode); static int cgmImageSetMarkerSpec(cgmImagePtr im, int specmode); static int cgmImageSetEdgeSpec(cgmImagePtr im, int specmode); #endif static int cgmImageSetOutput(cgmImagePtr im, FILE *output); #ifdef VTK_NOT_DEFINED static int cgmImageAddFont(cgmImagePtr im, const char *fontname); static int cgmImageClearFonts(cgmImagePtr im); #endif static cgmImagePtr cgmImageStartCgm(); static int cgmCgmHeader(cgmImagePtr); static int cgmCgmPic(cgmImagePtr, int); static int cgmImageSetDefaults(cgmImagePtr im); static int cgmImageEndPic(cgmImagePtr im); static int cgmImageEndCgm (cgmImagePtr im); // Macros to access information about images. READ ONLY. Changing // these values will NOT have the desired result. #define cgmImageSX(im) ((im)->sx) #define cgmImageSY(im) ((im)->sy) #define cgmImageColorsTotal(im) ((im)->colorsTotal) #define cgmImageRed(im, c) ((im)->red[(c)]) #define cgmImageGreen(im, c) ((im)->green[(c)]) #define cgmImageBlue(im, c) ((im)->blue[(c)]) // Source: Independent JPEG Group // In ANSI C, and indeed any rational implementation, size_t is also the // type returned by sizeof(). However, it seems there are some irrational // implementations out there, in which sizeof() returns an int even though // size_t is defined as long or unsigned long. To ensure consistent results // we always use this SIZEOF() macro in place of using sizeof() directly. // #define SIZEOF(object) ((size_t) sizeof(object)) // GeJ: these are helper functions I use in cgm. That means DON'T call // them from your program. Yes, that means you. static int cgmImageColorClear(cgmImagePtr im); //-------------------methods vtk uses to write data--------------------------- // // Define class for looking up colors class vtkColorHash { public: vtkColorHash(); ~vtkColorHash(); int InsertUniqueColor(cgmImagePtr im, int r, int g, int b); int GetColorIndex(cgmImagePtr im, int r, int g, int b); protected: vtkIdList **Table; }; #define VTK_HASH_INDEX 737 vtkColorHash::vtkColorHash() { int i; this->Table = new vtkIdList * [VTK_HASH_INDEX]; for (i=0; iTable[i] = NULL; } } vtkColorHash::~vtkColorHash() { int i; for (i=0; iTable[i] != NULL ) { this->Table[i]->Delete(); } } delete [] this->Table; } int vtkColorHash::InsertUniqueColor(cgmImagePtr im, int r, int g, int b) { int index = (65536*r + 256*g * b) % VTK_HASH_INDEX; int cgmIndex=0; //remove warning // If no list, just insert the color if ( this->Table[index] == NULL ) { this->Table[index] = vtkIdList::New(); this->Table[index]->Allocate(3,3); cgmIndex = cgmImageColorAllocate(im, r, g, b); this->Table[index]->InsertNextId(cgmIndex); } // otherwise, check to see if color exists else { vtkIdType numIds=this->Table[index]->GetNumberOfIds(); int red, green, blue; vtkIdType i; for (i=0; iTable[index]->GetId(i); cgmImageColorGet(im, cgmIndex, red, green, blue); if ( r == red && g == green && b == blue ) { break; } } if ( i >= numIds ) //means didn't find one { cgmIndex = cgmImageColorAllocate(im, r, g, b); this->Table[index]->InsertNextId(cgmIndex); } } return cgmIndex; } int vtkColorHash::GetColorIndex(cgmImagePtr im, int r, int g, int b) { int index = (65536*r + 256*g * b) % VTK_HASH_INDEX; vtkIdType cgmIndex; vtkIdType numIds=this->Table[index]->GetNumberOfIds(); int red, green, blue; int i; for (i=0; iTable[index]->GetId(i); cgmImageColorGet(im, cgmIndex, red, green, blue); if ( r == red && g == green && b == blue ) { return cgmIndex; } } return 0; } #undef VTK_HASH_INDEX // ------------------------------end vtkColorHash stuff--------------- // Build colors consisting of 3 bits red, 3 bits green, 2 bits blue // (total of 256 colors) // static void DefineColors(cgmImagePtr im, int CGMcolors[256]) { int red, green, blue, idx=0; // use 3-3-2 bits for rgb for (blue=0; blue<256; blue+=64) { for (green=0; green<256; green+=32) { for (red=0; red<256; red+=32) { CGMcolors[idx++] = cgmImageColorAllocate(im, red, green, blue); } } } } // Define CGM colors from the lookup table provided // static vtkColorHash *DefineLUTColors(cgmImagePtr im, unsigned char *colors, int numColors, int bpp) { vtkColorHash *colorHash = new vtkColorHash; unsigned char *ptr; int r=0, g=0, b=0; //warnings int id; for (id=0; id < numColors; id++) { ptr = colors + bpp*id; switch (bpp) { case 1: case 2: r = g = b = *ptr; break; case 3: case 4: r = ptr[0]; g = ptr[1]; b = ptr[2]; break; } colorHash->InsertUniqueColor(im, r, g, b); } return colorHash; } // Get a CGM color from the RGB value specified. // static int GetColor(int red, int green, int blue, int CGMColors[256]) { // round to nearest value red = (red + 16) / 32; red = (red > 7 ? 7 : red); green =(green + 16) / 32; green = (green > 7 ? 7 : green); blue = (blue + 32) / 64; blue = (blue > 3 ? 3 : blue); return CGMColors[red + green*8 + blue*64]; } #ifdef VTK_NOT_DEFINED static int GetLUTColor(int vtkNotUsed(red), int vtkNotUsed(green), int vtkNotUsed(blue)) { return 0; } #endif typedef struct _vtkSortValues { float z; int cellId; } vtkSortValues; extern "C" { int vtkCGMqsortCompare(const void *val1, const void *val2) { if (((vtkSortValues *)val1)->z > ((vtkSortValues *)val2)->z) { return (-1); } else if (((vtkSortValues *)val1)->z < ((vtkSortValues *)val2)->z) { return (1); } else { return (0); } } } void vtkCGMWriter::WriteData() { FILE *outf; vtkPolyData *input=this->GetInput(); vtkIdType numCells=input->GetNumberOfCells(), cellId; vtkIdType numPts=input->GetNumberOfPoints(); // Check that there is something to write if ( numPts < 1 || numCells < 1 ) { vtkErrorMacro(<<"No data to write"); return; } // Try opening the file if ( (outf = fopen(this->FileName, "wb")) == NULL ) { vtkErrorMacro(<<"Cannot open CGM file"); return; } cgmImagePtr im; vtkPoints *inPts=input->GetPoints(), *pts; vtkGenericCell *cell=vtkGenericCell::New(); vtkDataArray *inScalars=input->GetCellData()->GetScalars(); int i, id, type, npts, size[2]; vtkIdType *p; double bounds[6], xRange, yRange, x[3], factor[2]; int color, bpp=1, colorMode; unsigned char *ptr, *colors=NULL; int rgbColor[3], maxCellSize; cgmPoint *points; vtkSortValues *depth=NULL; //warnings // Figure out the coordinate range of the data. // Generate the points that will be used for output. // if ( this->Viewport == NULL ) //zero-out z values { input->GetBounds(bounds); pts = inPts; } else //transform into view coordinates { vtkPoints *displayPts = vtkPoints::New(); displayPts->SetNumberOfPoints(numPts); for ( i=0; i < numPts; i++ ) { inPts->GetPoint(i, x); this->Viewport->SetWorldPoint(x[0], x[1], x[2], 1.0); this->Viewport->WorldToDisplay(); this->Viewport->GetDisplayPoint(x); displayPts->SetPoint(i, x); } displayPts->GetBounds(bounds); pts = displayPts; } // Get the bounding box of the points // xRange = bounds[1] - bounds[0]; yRange = bounds[3] - bounds[2]; if ( xRange > yRange ) { factor[0] = 1.0; factor[1] = yRange/xRange; size[0] = this->Resolution; size[1] = (int)(factor[1] * this->Resolution); } else { factor[0] = yRange/xRange; factor[1] = 1.0; size[0] = (int)(factor[0] * this->Resolution); size[1] = this->Resolution; } // Loop over the points again, transforming them into resolution specified // vtkPoints *scaledPts = vtkPoints::New(); scaledPts->SetDataTypeToInt(); scaledPts->SetNumberOfPoints(numPts); x[2] = 0.0; for (i=0; iGetPoint(i,x); x[0] = (x[0] - bounds[0]) / xRange * this->Resolution * factor[0]; x[1] = (x[1] - bounds[2]) / yRange * this->Resolution * factor[1]; scaledPts->SetPoint(i,x); } // Generate the colors according to specified method // int CGMColors[256]; im = cgmImageCreate(size[0], size[1]); vtkColorHash *colorHash=NULL; if ( this->ColorMode == VTK_COLOR_MODE_DEFAULT ) { if ( inScalars && inScalars->GetDataType() == VTK_UNSIGNED_CHAR ) { colorMode = VTK_COLOR_MODE_DEFAULT; bpp = inScalars->GetNumberOfComponents(); colors = static_cast(inScalars)->GetPointer(0); } else { colorMode = VTK_COLOR_MODE_SPECIFIED_COLOR; } } else { colorMode = this->ColorMode; } if ( colorMode == VTK_COLOR_MODE_DEFAULT ) { colorHash = DefineLUTColors(im, colors, numCells, bpp); } else //random or specified color { DefineColors(im, CGMColors); } // Setup creation of the CGM file // maxCellSize = input->GetVerts()->GetMaxCellSize(); maxCellSize = (input->GetLines()->GetMaxCellSize() > maxCellSize ? input->GetLines()->GetMaxCellSize() : maxCellSize ); maxCellSize = (input->GetPolys()->GetMaxCellSize() > maxCellSize ? input->GetPolys()->GetMaxCellSize() : maxCellSize ); maxCellSize = (input->GetStrips()->GetMaxCellSize() > maxCellSize ? input->GetStrips()->GetMaxCellSize() : maxCellSize ); points = new cgmPoint [maxCellSize]; // If sorting is turned on, then traverse the cells, generating a depth // value which is used for sorting. // if ( this->Sort ) { depth = new vtkSortValues [numCells]; for ( cellId=0; cellId < numCells; cellId++ ) { input->GetCell(cellId, cell); id = cell->PointIds->GetId(0); pts->GetPoint(id,x); depth[cellId].z = x[2]; depth[cellId].cellId = cellId; } qsort((void *)depth, numCells, sizeof(vtkSortValues), vtkCGMqsortCompare); } // Traverse the cells and spit out the appropriate primitives. cgmSetShapeEdgeAttrib(im, 1, 0, 0, 0); for ( cellId=0; cellId < numCells; cellId++ ) { if ( this->Sort ) { id = depth[cellId].cellId; } else { id = cellId; } input->GetCell(id, cell); type = cell->GetCellType(); npts = cell->GetNumberOfPoints(); p = cell->GetPointIds()->GetPointer(0); if ( colorMode == VTK_COLOR_MODE_DEFAULT ) { ptr = colors + bpp*id; switch (bpp) { case 1: case 2: rgbColor[0] = *ptr; rgbColor[1] = *ptr; rgbColor[2] = *ptr; break; case 3: case 4: rgbColor[0] = ptr[0]; rgbColor[1] = ptr[1]; rgbColor[2] = ptr[2]; break; } color = colorHash->GetColorIndex(im, rgbColor[0], rgbColor[1], rgbColor[2]); } else if ( colorMode == VTK_COLOR_MODE_SPECIFIED_COLOR ) { color = GetColor((int)(this->SpecifiedColor[0] * 255.0), (int)(this->SpecifiedColor[1] * 255.0), (int)(this->SpecifiedColor[2] * 255.0), CGMColors); } else //if ( colorMode == VTK_COLOR_MODE_RANDOM_COLORS ) { color = GetColor((int)vtkMath::Random(0,255), (int)vtkMath::Random(0,255), (int)vtkMath::Random(0,255), CGMColors); } switch (type) { case VTK_VERTEX: case VTK_POLY_VERTEX: for (i=0; iGetPoint(p[i], x); points[0].x = (int)x[0]; points[0].y = (int)x[1]; } cgmPolyMarker(im, points, 1); break; case VTK_LINE: case VTK_POLY_LINE: for (i=0; iGetPoint(p[i], x); points[i].x = (int)x[0]; points[i].y = (int)x[1]; } cgmSetLineColor(im, color); cgmPolyLine(im, points, npts); break; case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON: for (i=0; iGetPoint(p[i], x); points[i].x = (int)x[0]; points[i].y = (int)x[1]; } cgmSetShapeFillAttrib(im, 1, color, -1); cgmPolygon(im, points, npts); break; case VTK_TRIANGLE_STRIP: for (i=0; i<(npts-2); i++) { scaledPts->GetPoint(p[i], x); points[0].x = (int)x[0]; points[0].y = (int)x[1]; scaledPts->GetPoint(p[i+1], x); points[1].x = (int)x[0]; points[1].y = (int)x[1]; scaledPts->GetPoint(p[i+2], x); points[2].x = (int)x[0]; points[2].y = (int)x[1]; } cgmSetShapeFillAttrib(im, 1, color, -1); cgmPolygon(im, points, 3); break; default: vtkErrorMacro(<<"Unsupported CGM type"); } } if ( colorMode == VTK_COLOR_MODE_DEFAULT ) { delete colorHash; } cell->Delete(); scaledPts->Delete(); delete [] points; if ( this->Sort ) { delete [] depth; } // Write out the CGM file cgmImageCgm(im, outf); // Clean up and get out fclose(outf); cgmImageDestroy(im); //destroys image } void vtkCGMWriter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); if ( this->Viewport ) { os << indent << "Viewport: " << this->Viewport << "\n"; this->Viewport->PrintSelf(os, indent.GetNextIndent()); } else { os << indent << "No Viewport defined\n"; } os << indent << "Sort: " << (this->Sort ? "On\n" : "Off\n"); os << indent << "Color Mode: "; if ( this->ColorMode == VTK_COLOR_MODE_DEFAULT ) { os << "Default" << endl; } else if ( this->ColorMode == VTK_COLOR_MODE_SPECIFIED_COLOR ) { os << "Specified Color: (" << this->SpecifiedColor[0] << ", " << this->SpecifiedColor[1] << ", " << this->SpecifiedColor[2] << ")\n"; } else { os << "Random Colors"; } os << indent << "Resolution: " << this->Resolution << endl; } //------------------private helper functions--------------------- //---the CGM functions static int cgmImageAddColor(cgmImagePtr im, int si, int ei); /* Creates a new image of size (sx,sy). Most people should always * start by calling this function */ static cgmImagePtr cgmImageCreate(int sx, int sy) { cgmImagePtr im; im = cgmImageStartCgm(); if (!im) { return 0; /* memory allocation failed */ } if (!cgmImageSetSize(im, sx,sy)) { free (im); return 0; } if (!cgmCgmHeader(im)) { free (im); return 0; } if (cgmCgmPic(im, 0)) { return im; } else { free(im); return 0; } } static int cgmAppNull(unsigned char *es, int x) { /* put x nulls in the string. * return value is number of octets added (1) */ int y; for(y=0; y> 8; *es = (unsigned char) temp & 0377; es++; *es = (unsigned char) addme & 0377; return 2; } static int cgmcomhead(unsigned char *es, int elemclass, int id, int len) { /* sets the command header in the first two bytes of string es * element class is in bits 15-12 * element id is in bits 11-5 * parameter list length is in bits 4-0 */ int temp; if (!es) { return 0; /* the string must be allocated first */ } /* set the element class */ *es = (unsigned char) elemclass << 4; /* set the element id */ temp = 0177 & id ; temp = temp >> 3; *es = *es | temp; es++; id = id << 5; *es = (unsigned char) id; *es = *es | (unsigned char) ( 037 & len ); return 1; } static int cgmcomheadlong(unsigned char *es, int elemclass, int id, int len) { /* sets the command header for the long form. * first 16 bits: * element class is in bits 15-12 * element id is in bits 11-5 * parameter list length is in bits 4-0 = 31 * second 16 bits: * bit 15 = 0 (for last partition) * bit 14-0 param list len */ /* I'm lazy, call cgmcomhead to set the first two bytes */ if (!cgmcomhead(es, elemclass, id, 31)) { return 0; } es += 2; /* now set the second two bytes */ cgmAppShort(es, (short int) len); *es = *es & 0177; /* make bit 15 = 0 */ es += 2; return 1; } static int cgmAddElem(cgmImagePtr im, unsigned char *es, int octet_count) /* adds a string, which is a CGM element to the elemlist. * This function is called by other functions in this library and * should NOT be called by users of the library * For internal cgm functions only, do not call! */ { unsigned char *newlist; /* in case memory allocation fails */ int x; /* counter */ while ((octet_count + 1) >= im->bytestoend) { /* not enough space, must grow elemlist */ im->listlen = im->listlen + CGMGROWLISTSIZE; newlist = (unsigned char *) realloc(im->elemlist, SIZEOF(unsigned char ) * im->listlen); if (newlist) { /* successfully allocated memory */ im->elemlist = newlist; im->bytestoend = im->bytestoend + CGMGROWLISTSIZE; im->curelemlist = im->elemlist + (im->listlen - im->bytestoend); } else { /* memory allocation failed, save yurself */ im->listlen = im->listlen - CGMGROWLISTSIZE; return 0; } } /* ok, if we get to here, there is enough space, so add it. */ for (x=0; x < octet_count; x++) { *im->curelemlist = (unsigned char) *es; im->curelemlist++; es++; } im->bytestoend = im->bytestoend - octet_count; return 1; } static int cgmCgmHeader(cgmImagePtr im) { /* add the cgm header to the imagepointer's element list * do it all in a string than call cgmAddElem on it * For internal cgm functions only, do not call! */ unsigned char *headerp; unsigned char *head; const unsigned char *buf, *buf2; int octet_count=0; int blen; /* length of buf */ int curly; int fontlistlen; /* each font in the font list is stored as a string, with a single octet in front of the string giving its length, fontlistlen is the sum of the lengths of all the font strings + the length octets. */ if (im->state != 0) { return 0; } headerp = (unsigned char *) calloc(1024, SIZEOF(unsigned char )); if (!headerp) { return 0; /* memory allocation failed */ } head=headerp; /*** Attribute: BegMF; Elem Class 0; Elem ID 1 */ buf = (const unsigned char *) "vtk: Visualization Toolkit"; blen = (int)strlen( (const char *) buf); cgmcomhead(head, 0, 1, blen+1); head += 2; head += cgmAppByte(head, (short int) blen); buf2 = buf; while (*buf2) { *head++ = *buf2++; } octet_count += (blen + 3); curly = 4 - (octet_count % 4); if (curly % 4) { octet_count += curly; head += cgmAppNull(head, curly); } /*** Attribute: MFVersion; Elem Class 1; Elem ID 1 */ cgmcomhead(head, 1, 1, 2); head += 2; head += cgmAppShort(head, (short int) 1); octet_count += 4; /*** Attribute: MFDesc; Elem Class 1; Elem ID 2 */ blen = (int)strlen( (char *) im->desc); cgmcomheadlong(head, 1, 2, blen+1); head += 4; head += cgmAppByte(head, (short int) blen); buf2 = im->desc; while (*buf2) { *head++ = *buf2++; } octet_count += (blen + 5); curly = 4 - (octet_count % 4); if (curly % 4) { octet_count += curly; head += cgmAppNull(head, curly); } /*** Attribute: ColrPrec; Elem Class 1; Elem ID 7 */ cgmcomhead(head, 1, 7, 2); head += 2; head += cgmAppShort(head, (short int) 8); octet_count += 4; /*** Attribute: ColrIndexPrec; Elem Class 1; Elem ID 8 */ cgmcomhead(head, 1, 8, 2); head += 2; head += cgmAppShort(head, (short int) 8); octet_count += 4; /*** Attribute: MaxColrIndex; Elem Class 1; Elem ID 9 */ cgmcomhead(head, 1, 9, 1); head += 2; head += cgmAppByte(head, (short int) 255); octet_count += 4; head++; /*** Attribute: MFElemList; Elem Class 1; Elem ID 11 */ /* shorthand here. 1 means 1 element specified, (-1,1) * means drawing-plus-control set */ cgmcomhead(head, 1, 11, 6); head += 2; head += cgmAppShort(head, (short int) 1); head += cgmAppShort(head, (short int) -1); head += cgmAppShort(head, (short int) 1); octet_count += 8; /*** Attribute: FontList; Elem Class 1; Elem ID 13 */ /* im->fontlist contains a comma separated list of font names * since we don't need the commas, and every font except one has * a comma, and we do need a length octet, that means that * taking the string length will give us one less than the * correct length. */ buf = im->fontlist; if (0) { /* don't do this if there aren't any fonts */ // if (buf) /* don't do this if there aren't any fonts */ fontlistlen = (int)strlen( (const char *) buf) + 1; cgmcomheadlong(head, 1, 13, fontlistlen); head +=4; while (*buf) { blen = 0; buf2 = buf; while ((*buf) && (*buf != ',')) { buf++; blen++; } head += cgmAppByte(head, (short int) blen); while (buf2 < buf) { *head++ = *buf2++; } if (*buf) { buf++; } } octet_count += (4 + fontlistlen); curly = 4 - (octet_count % 4); if (curly % 4) { octet_count += curly; head += cgmAppNull(head, curly); } } /* end of check to see if any fonts */ if (cgmAddElem(im, headerp, octet_count)) { free(headerp); return 1; } else { free(headerp); return 0; } } static int cgmCgmPic(cgmImagePtr im, int sticky) { /* Start the picture. if the sticky bit is set, set and use the defaults * of the previous picture. Otherwise, reset all defaults. * Gej: sticky = 0 reset defaults, 1 dont reset anything, 2 only * reset the color table */ unsigned char *headerp; unsigned char *head; unsigned char *buf, *buf2; char *tb; int octet_count=0; int blen; /* length of buf */ int x1,x2,x3,x4; /* needed for setting defaults */ if ((im->state != 0) && (im->state != 2)) { return 0; } if ((sticky > 2) || (sticky < 0)) { return 0; /* invalid sticky bit */ } /* increment the picture number */ im->picnum++; tb = (char *) calloc(4*4, SIZEOF(char) ); headerp = (unsigned char *) calloc(1024, SIZEOF(unsigned char )); if (!headerp) { return 0; /* memory allocation failed */ } head=headerp; /*** Attribute: BegPic; Elem Class 0; Elem ID 3 */ sprintf(tb, "picture %d", im->picnum); buf = (unsigned char*) tb; /* buf = (unsigned char *) "picture 1"; */ blen = (int)strlen( (char *) buf); cgmcomhead(head, 0, 3, blen+1); head += 2; head += cgmAppByte(head, (short int) blen); buf2 = buf; while (*buf2) { *head++ = *buf2++; } free(tb); octet_count += (blen + 3); if (!(blen % 2)) { octet_count++; head += cgmAppNull(head, 1); } if (octet_count % 4) { octet_count +=2; head += cgmAppNull(head, 2); } /*** Attribute: ColrMode; Elem Class 2; Elem ID 2 */ cgmcomhead(head, 2, 2, 2); head += 2; head += cgmAppShort(head, (short int) 0); octet_count += 4; /* Picture Descriptor: Line Width Specification Mode; * Elem Class 2; Elem ID 3*/ if (sticky && (im->linespec != CGMLINESPEC)) { cgmcomhead(head, 2, 3, 2); head += 2; head += cgmAppShort(head, (short int) im->linespec); octet_count += 4; } /* Picture Descriptor: Marker Size Specification Mode; * Elem Class 2; Elem ID 4*/ if (sticky && (im->markerspec != CGMMARKERSPEC)) { cgmcomhead(head, 2, 4, 2); head += 2; head += cgmAppShort(head, (short int) im->markerspec); octet_count += 4; } /* Picture Descriptor: Edge Width Specification Mode; * Elem Class 2; Elem ID 5*/ if (sticky && (im->edgespec != CGMEDGESPEC)) { cgmcomhead(head, 2, 5, 2); head += 2; head += cgmAppShort(head, (short int) im->edgespec); octet_count += 4; } /*** Attribute: VDCExt; Elem Class 2; Elem ID 6 */ cgmcomhead(head, 2, 6, 8); head += 2; head += cgmAppShort(head, (short int) 0); head += cgmAppShort(head, (short int) 0); head += cgmAppShort(head, (short int) im->sx); head += cgmAppShort(head, (short int) im->sy); octet_count += 10; /*** Attribute: Begin Picture Body; Elem Class 0; Elem ID 4 */ cgmcomhead(head, 0, 4, 0); head += 2; octet_count += 2; if (cgmAddElem(im, headerp, octet_count)) { free(headerp); } else { free(headerp); return 0; } if (sticky) { /* keep defaults the way they are */ if (sticky == 1) { /* keep the color table */ if(cgmImageAddColor(im, 0, im->colorsTotal - 1) == -1) { /* no colortable */ return 1; } } else { /* Nuke the color table if there is one */ cgmImageColorClear(im); } im->state = 1; x1=im->ltype; x2=im->lwidth; x3=im->lcolor; im->ltype=CGMLTYPE; im->lwidth=CGMLWIDTH; im->lcolor=CGMLCOLOR; if(!cgmSetLineAttrib(im, x1, x2, x3)) { return 0; } x1=im->shapestyle; x2=im->shapecolor; x3=im->shapehatch; im->shapestyle=CGMSHAPESTYLE; im->shapecolor=CGMSHAPECOLOR; im->shapehatch=CGMSHAPEHATCH; if (!cgmSetShapeFillAttrib(im, x1, x2, x3)) { return 0; } x1=im->edgetype; x2=im->edgewidth; x3=im->edgecolor; x4=im->edgevis; im->edgetype=CGMEDGETYPE; im->edgewidth=CGMEDGEWIDTH; im->edgecolor=CGMEDGECOLOR; im->edgevis=CGMEDGEVIS; if (!cgmSetShapeEdgeAttrib(im, x1, x2, x3, x4)) { return 0; } x1=im->textfont; x2=im->textcolor; x3=im->textheight; im->textfont=CGMTEXTFONT; im->textcolor=CGMTEXTCOLOR; im->textheight=CGMTEXTHEIGHT; if(!cgmSetTextAttrib(im, x1, x2, x3)) { return 0; } x1=im->textpath; im->textpath = CGMTEXTPATH; if (!cgmSetTextPath(im, x1)) { return 0; } x1=im->mtype; x2=im->msize; x3=im->mcolor; im->ltype=CGMMTYPE; im->lwidth=CGMMSIZE; im->lcolor=CGMMCOLOR; if(!cgmSetMarkerAttrib(im, x1, x2, x3)) { return 0; } } else { /* reset all the defaults */ cgmImageSetDefaults(im); /* Nuke the color table if there is one */ cgmImageColorClear(im); im->state = 1; /* now we are officially in the picture */ } return 1; } #ifdef VTK_NOT_DEFINED static int cgmCgmNewPic(cgmImagePtr im, int sticky) /* The CGM standard allows multiple images in a single file. This function * will close the current picture, then open a new one. * if sticky is 0 then all attributes will be reset to the defaults * if sticky is 1 then all attributes will be inherited from the prevous * picture. * if sticky is 2 all attributes except the color table will be inherited * from the previous picture */ { /* close the current picture */ if (!cgmImageEndPic(im)) { return 0; } /* now start the new picture */ return(cgmCgmPic(im, sticky)); } #endif static int cgmImageCgm(cgmImagePtr im, FILE *out) /* Gej: Write the image to file *out, which must be open already * does not close the file */ { cgmImageSetOutput(im, out); return cgmImageEndCgm(im); } static int cgmSetLineType(cgmImagePtr im, int lntype) { /* Attribute: Line Type; Elem Class 5; Elem ID 2 * Set the line type. Possible values are: * 1=solid, 2=dash, 3=dot, 4=dash-dot, 5=dash-dot-dot * Even though new ones can be defined, I am limiting lntype to these values * If you really need more, you can make the proper changes. */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (lntype == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (lntype == im->ltype) { return 1; } /* Make sure that lntype is between 1 and 5 */ if ((lntype < 1) || (lntype > 5)) { return 0; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomhead(es, 5, 2, 2)) { free(esp); return 0; } es += 2; /* set Param_List_Len to 2 (signed int at index precision) */ /* add in the value of lntype */ es += cgmAppShort(es, (short int) lntype); octet_count = 4; /* we just know this */ /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->ltype = (short int) lntype; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetLineWidth(cgmImagePtr im, int lnwidth) { /* Attribute: Line Width; Elem Class 5; Elem ID 3 * sets the line width. with an image of height X with line width 1 * the displayed width will be 1/X%. as an example, if you image is * x=5, y=10, and you set line width = 1, and draw a vertical line, the * resulting line will cover 20% of horizontal area. */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (lnwidth == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (lnwidth == im->lwidth) { return 1; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; /*gej: line width is 32 bit floating point number, 16 bits before the * decimal, 16 bits after if Line Spec is default (1, scaled) * if Line Spec is 0 (0, absolute) then it is 16 bit SI */ if (im->linespec) { if (!cgmcomhead(es, 5, 3, 4)) { free(esp); return 0; } es += 2; octet_count = 2; es += cgmAppShort(es, (short int) lnwidth); octet_count += 2; /* the next two (after decimal point) will always be zero */ es += cgmAppNull(es, 2); octet_count += 2; } else { if (!cgmcomhead(es, 5, 3, 2)) { free(esp); return 0; } octet_count = 2; es += 2; es += cgmAppShort(es, (short int) lnwidth); octet_count += 2; } /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->lwidth = lnwidth; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetLineColor(cgmImagePtr im, int lncolor) { /* Attribute: Line Colour; Elem Class 5; Elem ID 4 * Sets the line color. lncolor should be an index into the color * table that you have previously allocated. */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (lncolor == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (lncolor == im->lcolor) { return 1; } /* Make sure the color they want to use has been allocated. * also, that color must be non-negative */ if ((lncolor >= im->colorsTotal ) || (lncolor < 0)) { return 0; /* you must allocate a color before you use it */ } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomhead(es, 5, 4, 1)) { free (esp); return 0; } es += 2; *es = 0377 & lncolor; /* mask off last 8 bits and put in es */ es++; es += cgmAppNull(es, 1); octet_count = 4; /* we just know this; 2 octets of header, * 1 octet of data, 1 octet of null data */ /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->lcolor = (short int) lncolor; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetFillStyle(cgmImagePtr im, int instyle) { /* set the style of the interior of filled area elements. * Attribute: Interior Style; Elem Class 5; Elem ID 22 * These attributes stay in effect until changed, so you don't have to output * them every time. * Interior Style: (integers 0-6, corresponding to: hollow, solid, * [not pattern], hatch, empty, [not geometric pattern], * interpolated.) * attribute is 16 bit signed int */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (instyle == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (instyle == im->shapestyle) { return 1; } /* Make sure that lnhatch is between 0 and 6, but not * 2, 5, or 6 */ if ((instyle < 0) || (instyle > 4) || (instyle == 2)) { return 0; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; /* set the header to Class 5, ID 22, Length 2 */ if (!cgmcomhead(es, 5, 22, 2)) { free (esp); return 0; } es += 2; /* add in the value of inhatch */ es += cgmAppShort(es, (short int) instyle); octet_count = 4; /* we just know this */ /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->shapestyle = (short int) instyle; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetFillColor(cgmImagePtr im, int incolor) { /* set the color of the interior of filled area elements * Attribute: Fill Colour; Elem Class 5; Elem ID 23 * These attributes stay in effect until changed, so you don't have to output * them every time. * Fill Colour: (index into the color table) */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (incolor == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (incolor == im->shapecolor) { return 1; } /* Make sure the color they want to use has been allocated. * also, that color must be non-negative */ if ((incolor >= im->colorsTotal ) || (incolor < 0)) { return 0; /* you must allocate a color before you use it */ } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomhead(es, 5, 23, 1)) { free(esp); return 0; } es += 2; *es = 0377 & incolor; /* mask off last 8 bits and put in es */ es++; es += cgmAppNull(es, 1); octet_count = 4; /* we just know this; 2 octets of header, * 1 octet of data, 1 octet of null data */ /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->shapecolor = (short int) incolor; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetFillHatch(cgmImagePtr im, int inhatch) { /* Set the hatch pattern for the interior of filled-area elements * the fill style must be set to hatch for this to have an effect. * Attribute: Hatch Index; Elem Class 5; Elem ID 24 * These attributes stay in effect until changed, so you don't have to output * them every time. * Hatch Index: (integers 1-6, corresponding to: horizontal lines, * vertical lines, pos. slope parallel lines, * neg. slope parallel lines, horizontal/vertical * crosshatch, positive/negative slope crosshatch) */ unsigned char *es, *esp; int octet_count, temp; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (inhatch == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (inhatch == im->shapehatch) { return 1; } /* Make sure that lnhatch is between 1 and 6 */ if ((inhatch < 1) || (inhatch > 6)) { return 0; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; /* set the command header to class 5, id 24, length 2 */ if (!cgmcomhead (es, 5, 24, 2)) { free(esp); return 0; } es += 2; /* add in the value of inhatch */ temp = inhatch >> 8; *es = *es | (temp & 0377); es++; *es = *es | (inhatch & 0377); es++; octet_count = 4; /* we just know this */ /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->shapehatch = (short int) inhatch; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetEdgeType(cgmImagePtr im, int edtype) { /* set the type of the edge of filled-area elements. * Attribute: Edge Type; Elem Class 5; Elem ID 27 * These attributes stay in effect until changed, so you don't have to output * them every time. * Edge Type (integers 1-5, corresponding to: solid, dash, dot, * dash-dot, dash-dot-dot. These are the same as those used * for line type.) * In Part 3 of the standard (Binary Encoding) on page 47 it says that * edge type is integer. This is incorrect. Edge type is Index, just * like line type. * Even though new ones can be defined, I am limiting lntype to these values * If you really need more, you can make the proper changes. */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (edtype == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (edtype == im->edgetype) { return 1; } /* Make sure that lntype is between 1 and 5 */ if ((edtype < 1) || (edtype > 5)) { return 0; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if(!cgmcomhead(es, 5, 27, 2)) {free(esp);return 0;} es += 2; /* add in the value of edtype */ es += cgmAppShort(es, (short int) edtype); octet_count = 4; /* we just know this */ /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->edgetype = (short int) edtype; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetEdgeWidth(cgmImagePtr im, int edwidth) { /* Set the width of the edge of filled-area elements. * Attribute: Edge Width; Elem Class 5; Elem ID 28 * These attributes stay in effect until changed, so you don't have to output * them every time. * Edge Width (should be the same as line width) */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (edwidth == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (edwidth == im->edgewidth) { return 1; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; /*gej: edge width is 32 bit floating point number, 16 bits before the * decimal, 16 bits after for default edge spec (1, scaled) if * edge spec is absolute (0) then just 16 bit SI */ if (im->edgespec) { if (!cgmcomhead(es, 5, 28, 4)) { free(esp); return 0; } es += 2; octet_count = 2; es+= cgmAppShort(es, edwidth); octet_count+=2; /* the next two (after decimal point) will always be zero */ es += cgmAppNull(es, 2); octet_count += 2; } else { if (!cgmcomhead(es, 5, 28, 2)) {free(esp);return 0;} es += 2; octet_count = 2; es+= cgmAppShort(es, edwidth); octet_count+=2; } /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->edgewidth = edwidth; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetEdgeColor(cgmImagePtr im, int edcolor) { /* Set the color of the edge of filled-area elements. * Attribute: Edge Color; Elem Class 5; Elem ID 29 * These attributes stay in effect until changed, so you don't have to output * them every time. * Edge Colour (index into the color table) */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (edcolor == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (edcolor == im->edgecolor) { return 1; } /* Make sure the color they want to use has been allocated. * also, that color must be non-negative */ if ((edcolor >= im->colorsTotal ) || (edcolor < 0)) { return 0; /* you must allocate a color before you use it */ } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomhead(es, 5, 29, 1)) { free(esp); return 0; } es += 2; *es = 0377 & edcolor; /* mask off last 8 bits and put in es */ es++; es += cgmAppNull(es, 1); octet_count = 4; /* we just know this; 2 octets of header, * 1 octet of data, 1 octet of null data */ /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->edgecolor = (short int) edcolor; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetEdgeVis(cgmImagePtr im, int edvis) { /* Set the visibility of the edge of filled-area elements. * Attribute: Edge Visibility; Elem Class 5; Elem ID 30 * These attributes stay in effect until changed, so you don't have to output * them every time. * Edge Visibility (integer 0 or 1, corresponding to: Off, On) * Attribute is 16 bit signed int. */ unsigned char *es, *esp; int octet_count, temp; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (edvis == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (edvis == im->edgevis) { return 1; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomhead(es, 5, 30, 2)) { free(esp); return 0; } es +=2; octet_count = 2; temp = edvis >> 8; *es = *es | (temp & 0377); es++; *es = *es | (edvis & 0377); es++; octet_count += 2; /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->edgevis = (short int) edvis; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetTextFont(cgmImagePtr im, int font) { /* Attribute: Text Font Index; Elem Class 5; Elem ID 10 * font is an index into the font table. it can have one of the following * values: * 1 Times Roman * 2 Times Bold * 3 Times Italic * 4 Times Bold Italic * 5 Helvetica * 6 Helvetica Bold * 7 Helvetica Italic * 8 Helvetica Bold Italic * 9 Courier * 10 Courier Bold * 11 Courier Italic * 12 Courier Bold Italic */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (font == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (font == im->textfont) { return 1; } /* Make sure that font is between 1 and the number of fonts */ if ((font < 1) || (font > im->numfonts)) { return 0; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if(!cgmcomhead(es, 5, 10, 2)) { free(esp); return 0; } es += 2; es += cgmAppShort(es, (short int) font); octet_count = 4; /* we just know this */ /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->textfont = (short int) font; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetTextColor(cgmImagePtr im, int color) { /* Attribute: Text Colour ; Elem Class 5; Elem ID 14 * set the forground color of text */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (color == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (color == im->textcolor) { return 1; } /* Make sure the color they want to use has been allocated. * also, that color must be non-negative */ if ((color >= im->colorsTotal ) || (color < 0)) { return 0; /* you must allocate a color before you use it */ } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if(!cgmcomhead(es, 5, 14, 1)) { free(esp); return 0; } es += 2; *es = 0377 & color; /* mask off last 8 bits and put in es */ es++; octet_count = 4; /* we just know this; 2 octets of header, * 1 octet of data, 1 octet of null data */ /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->textcolor = (short int) color; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetTextHeight(cgmImagePtr im, int height) { /* Attribute: Character Height; Elem Class 5; Elem ID 15 * the height is in the same units as line width */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (height == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (height == im->textheight) { return 1; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if(!cgmcomhead(es, 5, 15, 2)) { free(esp); return 0; } octet_count = 2; es += 2; es += cgmAppShort(es, height); octet_count += 2; /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->textheight = height; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetTextPath(cgmImagePtr im, int tpath) { /* Attribute: Text Path; Elem Class 5; Elem ID 17 * Is one of: * 0 right -- Means the direction of the character base vector * 1 left -- means 180 degrees from the character base vector * 2 up -- means the direction of the character up vector * 3 down -- means 180 degrees from the character up vector */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (tpath == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (tpath == im->textpath) { return 1; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomhead(es, 5, 17, 2)) { free(esp); return 0; } es +=2; octet_count = 2; es += cgmAppShort(es, (short int) tpath); octet_count += 2; /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->textpath = (short int) tpath; free(esp); return 1; } else { free(esp); return 0; } } #ifdef VTK_NOT_DEFINED static int cgmSetTextOrient(cgmImagePtr im, int xup, int yup, int xbase, int ybase) { /* Attribute: Character Orientation; Elem Class 5; Elem ID 16 * (xbase,ybase) is the run and the rise of the line that the text is * written along. For regular text at an angle, set xup = -ybase * and yup = xbase. Setting it to something different will result in * skewed text (which may be what you want.) Text written from bottom to * top at a 90 degree angle would have the following parameters * xup=-1, yup=0, xbase=0, ybase=1 * * This function adds the Orientation to the metafile every time. * It does not follow the normal -1 for no change, although if you * put in the same numbers it won't re-add it to the meta file. */ unsigned char *es, *esp; int octet_count; /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; octet_count = 0; if (!cgmcomhead(es, 5, 16, 8)) { free(esp); return 0; } es +=2; octet_count += 2; /* In the metafile it is a 16 bit signed integer */ /* add xup */ es += cgmAppShort(es, (short int) xup); octet_count += 2; /* add the rest */ es += cgmAppShort(es, (short int) yup); octet_count += 2; es += cgmAppShort(es, (short int) xbase); octet_count += 2; es += cgmAppShort(es, (short int) ybase); octet_count += 2; /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } #endif static int cgmSetMarkerType(cgmImagePtr im, int mtype) { /* Attribute: Marker Type; Elem Class 5; Elem ID 6 * Set the Marker type. Possible values are: * 1=dot, 2=plus, 3=asterisk, 4=circle, 5=cross * Even though new ones can be defined, I am limiting lntype to these values * If you really need more, you can make the proper changes. */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (mtype == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (mtype == im->mtype) { return 1; } /* Make sure that mtype is between 1 and 5 */ if ((mtype < 1) || (mtype > 5)) { return 0; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomhead(es, 5, 6, 2)) { free(esp); return 0; } es += 2; /* set Param_List_Len to 2 (signed int at index precision) */ /* add in the value of mtype */ //es += cgmAppShort(es, (short int) mtype); octet_count = 4; /* we just know this */ /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->mtype = (short int) mtype; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetMarkerSize(cgmImagePtr im, int msize) { /* Attribute: Marker Size; Elem Class 5; Elem ID 7 * sets the marker size. with an image of height X with marker size 1 * the displayed size will be 1/X%. as an example, if you image is * x=5, y=10, and you set marker size = 1, and draw a marker, the * resulting marker will cover 20% of horizontal area. */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (msize == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (msize == im->msize) { return 1; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; /*gej: marker size is 32 bit floating point number, 16 bits before the * decimal, 16 bits after if marker spec is default (1, scaled) * for absolute mode (0, absolute) it is 16 bit SI */ if (im->markerspec) { if (!cgmcomhead(es, 5, 7, 4)) {free(esp);return 0;} octet_count = 2; es += 2; es += cgmAppShort(es, (short int) msize); octet_count += 2; /* the next two (after decimal point) will always be zero */ es += cgmAppNull(es, 2); octet_count += 2; } else { if (!cgmcomhead(es, 5, 7, 4)) { free(esp); return 0; } octet_count = 2; es += 2; //es += cgmAppShort(es, (short int) msize); octet_count += 2; } /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->msize = msize; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetMarkerColor(cgmImagePtr im, int mcolor) { /* Attribute: Marker Colour; Elem Class 5; Elem ID 8 * Sets the marker color. mcolor should be an index into the color * table that you have previously allocated. */ unsigned char *es, *esp; int octet_count; /* First check and see if the user doesn't want any changes, * if so, just return success */ if (mcolor == -1) { return 1; } /* Check and see if the value it is being set to is the current * value, if so, don't make any changes, just return 1 */ if (mcolor == im->mcolor) { return 1; } /* Make sure the color they want to use has been allocated. * also, that color must be non-negative */ if ((mcolor >= im->colorsTotal ) || (mcolor < 0)) { return 0; /* you must allocate a color before you use it */ } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomhead(es, 5, 8, 1)) {free (esp);return 0;} es += 2; *es = 0377 & mcolor; /* mask off last 8 bits and put in es */ es++; //es += cgmAppNull(es, 1); octet_count = 4; /* we just know this; 2 octets of header, * 1 octet of data, 1 octet of null data */ /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { im->mcolor = (short int) mcolor; free(esp); return 1; } else { free(esp); return 0; } } static int cgmSetLineAttrib(cgmImagePtr im, int lntype, int lnwidth, int lncolor) { /* Spits out the attributes of lines. These attributes stay in effect * until changed, so you don't have to output them every time. */ if (!cgmSetLineType(im, lntype)) { return 0; } if (!cgmSetLineWidth(im, lnwidth)) { return 0; } if (!cgmSetLineColor(im, lncolor)) { return 0; } return 1; } static int cgmSetShapeFillAttrib(cgmImagePtr im, int instyle, int incolor, int inhatch) { /* Spits out the attributes for the interior of filled-area elements. * These attributes stay in effect until changed, so you don't have to output * them every time. * Set the following attributes: * Interior Style: (integers 0-6, corresponding to: hollow, solid, * [not pattern], hatch, empty, [not geometric pattern], * interpolated.) * Fill Colour: (index into the color table) * Hatch Index: (integers 1-6, corresponding to: horizontal lines, * vertical lines, pos. slope parallel lines, * neg. slope parallel lines, horizontal/vertical * crosshatch, positive/negative slope crosshatch) */ if (!cgmSetFillStyle(im, instyle)) { return 0; } if (!cgmSetFillColor(im, incolor)) { return 0; } if (!cgmSetFillHatch(im, inhatch)) { return 0; } return 1; } static int cgmSetShapeEdgeAttrib(cgmImagePtr im, int edtype, int edwidth, int edcolor, int edvis) { /* Spits out the attributes for the edges of filled-area elements. It may * seem logical that these would be the same as the corresponding line * attributes, but this is not the case. * These attributes stay in effect until changed, so you don't have to output * them every time. * Set the following attributes: * Edge Type (integers 1-5, corresponding to: solid, dash, dot, * dash-dot, dash-dot-dot. These are the same as those used * for line type.) * Edge Width (should be the same as line width) * Edge Colour (index into the color table) * Edge Visibility (integer 0 or 1, corresponding to: Off, On) */ if (!cgmSetEdgeType(im, edtype)) { return 0; } if (!cgmSetEdgeWidth(im, edwidth)) { return 0; } if (!cgmSetEdgeColor(im, edcolor)) { return 0; } if (!cgmSetEdgeVis(im, edvis)) { return 0; } return 1; } static int cgmSetTextAttrib(cgmImagePtr im, int font, int color, int height) { /* Set the attributes of text. the font is an integer pointer into the * font list where: * 1 Times * 2 Times Bold * 3 Times Italic * 4 Times Bold Italic * 5 Helvetica * 6 Helvetica Bold * 7 Helvetica Italic * 8 Helvetica Bold Italic * 9 Courier * 10 Courier Bold * 11 Courier Italic * 12 Courier Bold Italic * color is an index into the colortable which is the color of the text * size is the approximate size you want the text written in. */ if(!cgmSetTextFont(im, font)) { return 0; } if(!cgmSetTextColor(im, color)) { return 0; } if(!cgmSetTextHeight(im, height)) { return 0; } return 1; } static int cgmSetMarkerAttrib(cgmImagePtr im, int mtype, int msize, int mcolor) { /* Spits out the attributes of Markers. These attributes stay in effect * until changed, so you don't have to output them every time. */ if (!cgmSetMarkerType(im, mtype)) { return 0; } if (!cgmSetMarkerSize(im, msize)) { return 0; } if (!cgmSetMarkerColor(im, mcolor)) { return 0; } return 1; } static int cgmImageDestroy(cgmImagePtr im) /* gej: should work, unless I make changes to cgmImage Struct */ { if (im->elemlist) { free(im->elemlist); } if (im->desc) { free(im->desc); } if (im->fontlist) { free(im->fontlist); } free(im); return 1; } #ifdef VTK_NOT_DEFINED static int cgmImageColorClosest(cgmImagePtr im, int r, int g, int b) /* From gd library, see README file for copyright information */ /* gej: should work unchanged */ /* gej: 5/96, changed the colors to use short int */ { short int i; long rd, gd, bd; int ct = (-1); long mindist = 0; for (i=0; (i<(im->colorsTotal)); i++) { long dist; if (im->open[i]) { continue; } rd = (im->red[i] - r); gd = (im->green[i] - g); bd = (im->blue[i] - b); dist = rd * rd + gd * gd + bd * bd; if ((i == 0) || (dist < mindist)) { mindist = dist; ct = i; } } return ct; } #endif static int cgmImageColorClear(cgmImagePtr im) { /* mark all entries in the color table as open */ short int i; for (i=0; (i<(cgmMaxColors)); i++) { im->open[i] = 1; } return 1; } #ifdef VTK_NOT_DEFINED static int cgmImageColorExact(cgmImagePtr im, int r, int g, int b) /* From gd library, see README file for copyright information */ /* gej: should work unchanged */ /* gej: 5/96, changed colors to work with short ints */ { short int i; for (i=0; (i<(im->colorsTotal)); i++) { if (im->open[i]) { continue; } if ((im->red[i] == r) && (im->green[i] == g) && (im->blue[i] == b)) { return i; } } return -1; } #endif static int cgmImageAddColorIndex(cgmImagePtr im, int r, int g, int b) /* adds the specified color to the colortable in the cgmImagePtr. * does not add it to the cgm file, cgmImageAddColor does. * do not use either of these two functions, use cgmImageColorAllocate. */ { short int i; short int ct = (-1); for (i=0; (i<(im->colorsTotal)); i++) { if (im->open[i]) { ct = i; break; } } if (ct == (-1)) { ct = im->colorsTotal; if (ct == cgmMaxColors) { return -1; } im->colorsTotal++; } im->red[ct] = (short int) r; im->green[ct] = (short int) g; im->blue[ct] = (short int) b; im->open[ct] = (short int) 0; return ct; } static int cgmImageAddColor(cgmImagePtr im, int si, int ei) /* adds colors to the cgm file, gets values from the color table. * adds all colors from si to ei inclusive. * Use cgmImageColorAllocate, not this one. */ { unsigned char *cts, *ctsp; /* GEJ: color table attribute */ int octet_count; /* GEJ: octet count */ int numco, curly; octet_count = 0; /* * Attribute: Colour Table; Elem Class 5; Elem ID 34 * two parameters P1: Starting colour table index (1 octet, UI) * P2: list of direct colour values 3-tuples (3 one-octet values) */ /* G E J: find out how many values are being added */ if (ei < 0) { return -1; /* no colors being added */ } numco = ei - si + 1; if (( numco > 0) && (numco < 10)) { /* we can use the short form of the command */ /* allocate sufficent space. Should be 32 bits * 10 to be safe*/ cts = (unsigned char *) calloc(4*10, SIZEOF(unsigned char ) ); if (!cts) { return -1; /* memory allocation failed */ } ctsp=cts; if (!cgmcomhead(ctsp,5,34,(numco*3)+1)) { free(cts); return -1; } ctsp +=2; octet_count += 2; } else if ((numco > 9) && (numco < 256)) { /* we must use the long form of the command */ /* allocate sufficent space. Should be 32 bits*256 to be safe*/ cts = (unsigned char *) calloc(256*4, SIZEOF(unsigned char ) ); if (!cts) { return -1; /* memory allocation failed */ } ctsp=cts; if (!cgmcomheadlong(ctsp,5,34,(numco*3)+1)) { free(cts); return -1; } ctsp +=4; octet_count += 4; } else { return -1; } /*ctsp += cgmAppByte(ctsp, (short int) si);*/ cgmAppByte(ctsp, (short int) si); ctsp++; octet_count++; for (numco = si; numco <= ei; numco++) { ctsp += cgmAppByte(ctsp, im->red[numco]); ctsp += cgmAppByte(ctsp, im->green[numco]); ctsp += cgmAppByte(ctsp, im->blue[numco]); octet_count +=3; } curly = 4 - (octet_count % 4); if (curly % 4) { octet_count += curly; //ctsp += cgmAppNull(ctsp, curly); } /* add it to the buffer */ if (cgmAddElem(im, cts, octet_count)) { free(cts); return 1; } else { free(cts); return -1; } } static int cgmImageColorAllocate(cgmImagePtr im, int r, int g, int b) /* From gd library, see README file for copyright information * gej: modified to allocate the color in the CGM buffer as well * as the color table */ /* gej: 5/96, modified to use short ints for colors */ { short int ct; ct = cgmImageAddColorIndex(im, r, g, b); if (ct == -1) { return -1; } /* GEJ: w we have successfully alocated it in the color table * so let's put it in the CGM as well. */ if (cgmImageAddColor(im, ct, ct) == -1 ) { return -1; } else { return ct; } } #ifdef VTK_NOT_DEFINED static int cgmImageColor16(cgmImagePtr im) { int si, ei, li; si = cgmImageAddColorIndex(im, 255, 255, 255); if (si == -1) { return 0; } li = -1; ei=si; ei = cgmImageAddColorIndex(im, 0, 0, 0); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 128, 0, 0); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 0, 128, 0); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 128, 128, 0); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 0, 0, 128); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 128, 0, 128); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 0, 128, 128); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 128, 128, 128); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 192, 192, 192); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 255, 0, 0); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 0, 255, 0); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 255, 255, 0); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 0, 0, 255); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 255, 0, 255); if (ei != -1) { li = ei; } ei = cgmImageAddColorIndex(im, 0, 255, 255); if (ei != -1) { li = ei; } if (ei == -1) { ei = li; } if(cgmImageAddColor(im,si,ei) == -1) { return -1; } else { return ei; } } static int cgmImageColorDeallocate(cgmImagePtr vtkNotUsed(im), int vtkNotUsed(color)) /* wogl: the parameter names are commented to avoid compiler warnings */ /* From gd library, see README file for copyright information */ /* gej: should work unchanged */ { /* Mark it open. */ /*im->open[color] = 1;*/ /* gej: really can't work, we are not allowing redefinition * of color table entries */ return 0; } #endif static int cgmImageColorGet(cgmImagePtr im, int cgmIndex, int& r, int& g, int& b) { cgmIndex = (cgmIndex >= cgmMaxColors ? cgmMaxColors-1 : cgmIndex); r = im->red[cgmIndex]; g = im->green[cgmIndex]; b = im->blue[cgmIndex]; return 1; } #ifdef VTK_NOT_DEFINED static int cgmLine(cgmImagePtr im, int x1, int y1, int x2, int y2) /* Graphic Primitive: Polyline; Elem Class 4; Elem ID 1 * Actually generate the line, if you are writing a program to use this * library, use this function, not cgmImageLine or cgmImageDashedLine, * those are just in for compatiblilty with gd * * This function will draw a line using the current line type, width, and color */ { unsigned char *es, *esp; int octet_count; short int sweet; short int sour; /* check to make sure the line is withing the scope of the picture * ie. the values you give for drawing the line are within * the values you created the picture with */ if (!(cgmImageBoundsSafe(im, x1,y1)) || !(cgmImageBoundsSafe(im, x2,y2))) { return 0; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomhead(es, 4, 1, 8)) { free(esp); return 0; } es += 2; octet_count = 2; /* now we are ready for the parameter data */ sweet = (short int) x1; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) y1; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) x2; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) y2; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; octet_count++; /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } static int cgmMarker(cgmImagePtr im, int x, int y) /* Graphic Primitive: PolyMarker; Elem Class 4; Elem ID 3 * puts a marker in the file, it will have characteristics set by * cgmSetMarkerAttrib */ { unsigned char *es, *esp; int octet_count; /* check to make sure the line is withing the scope of the picture * ie. the values you give for drawing the line are within * the values you created the picture with */ if (!cgmImageBoundsSafe(im, x,y) ) { return 0; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomhead(es, 4, 3, 4)) { free(esp); return 0; } es += 2; octet_count = 2; octet_count += cgmAppShort(es, (short int) x); es += 2; octet_count += cgmAppShort(es, (short int) y); es += 2; /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } static int cgmRectangle(cgmImagePtr im, int x1, int y1, int x2, int y2) { /* Graphic Primitive: rectangle; Elem Class 4; Elem ID 11 * Actually generate the rectangle, if you are writing a program to use this * library, use this function, not cgmImageRectangle, * those are just in for compatiblilty with gd * * This function will draw a Rectangle using the current * edge type, width, color, and visibility, and the current * fill style, color, and hatch */ unsigned char *es, *esp; int octet_count; short int sweet; short int sour; /* check to make sure the line is withing the scope of the picture * ie. the values you give for drawing the line are within * the values you created the picture with */ if (!(cgmImageBoundsSafe(im, x1,y1)) || !(cgmImageBoundsSafe(im, x2,y2))) { return 0; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; /* their are four 16 bit signed integers as attributes */ if (!cgmcomhead(es, 4, 11, 8)) { free(esp); return 0; } es +=2; octet_count = 2; /* now we are ready for the parameter data */ sweet = (short int) x1; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) y1; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) x2; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) y2; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; octet_count++; /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } static int cgmCircle(cgmImagePtr im, int cx, int cy, int r) { /* Graphic Primitive: circle; Elem Class 4; Elem ID 12 * cx,cy is the center of the circle, r is the radius * * This function will draw a Circle using the current * edge type, width, color, and visibility, and the current * fill style, color, and hatch */ unsigned char *es, *esp; int octet_count; short int sweet; short int sour; /* check to make sure the circle is withing the scope of the picture * ie. the values you give for drawing the circle are within * the values you created the picture with */ if (!(cgmImageBoundsSafe(im, cx,cy))) { return 0; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; /* their are three 16 bit signed integers as attributes */ if (!cgmcomhead(es, 4, 12, 6)) { free(esp); return 0; } es +=2; octet_count = 2; /* now we are ready for the parameter data */ sweet = (short int) cx; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) cy; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) r; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; octet_count++; /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } static int cgmArc3Pt(cgmImagePtr im, int sx,int sy, int ix,int iy, int ex,int ey) { /* Graphic Primitive: Cicular Arc 3 Point; Elem Class 4; Elem ID 13 * * This function will draw a Circular Arc using the current * Line type, width, and color, */ unsigned char *es, *esp; int octet_count; short int sweet; short int sour; /* check to make sure the line is withing the scope of the picture * ie. the values you give for drawing the line are within * the values you created the picture with */ if (!(cgmImageBoundsSafe(im, sx,sy)) || !(cgmImageBoundsSafe(im, ix,iy)) || !(cgmImageBoundsSafe(im, ex, ey))) { return 0; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; /* their are six 16 bit signed integers as attributes */ if (!cgmcomhead(es, 4, 13, 12)) { free(esp); return 0; } es +=2; octet_count = 2; /* now we are ready for the parameter data */ sweet = (short int) sx; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) sy; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) ix; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) iy; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) ex; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; es++; octet_count++; sweet = (short int) ey; sour = sweet >> 8; *es = *es | (sour & 0377); es++; octet_count++; *es = (unsigned char) sweet; octet_count++; /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } static int cgmArc3PtClose(cgmImagePtr im, int sx,int sy, int ix,int iy, int ex,int ey, int cl) { /* Graphic Primitive: Cicular Arc 3 Point Close; Elem Class 4; Elem ID 14 * * This function will draw a Circle using the current * edge type, width, color, and visibility, and the current * fill style, color, and hatch * * cgm is the closure type. It can be either 0 for pie closure or * 1 for chord closure. */ unsigned char *es, *esp; int octet_count; /* check to make sure the line is withing the scope of the picture * ie. the values you give for drawing the line are within * the values you created the picture with */ if (!(cgmImageBoundsSafe(im, sx,sy)) || !(cgmImageBoundsSafe(im, ix,iy)) || !(cgmImageBoundsSafe(im, ex, ey))) { return 0; } /* make sure that they close the arc either with pie (0) or chord (1) */ if ((cl != 0) && (cl != 1)) { return 0; } /* allocate sufficent space. should be 32 bits * 6 to be safe */ es = (unsigned char *) calloc(4*6, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; /* their are seven 16 bit signed integers as attributes */ if (!cgmcomhead(es, 4, 14, 14)) { free(esp); return 0; } es +=2; octet_count = 2; /* now we are ready for the parameter data */ octet_count += cgmAppShort(es, (short int) sx); es +=2; octet_count += cgmAppShort(es, (short int) sy); es +=2; octet_count += cgmAppShort(es, (short int) ix); es +=2; octet_count += cgmAppShort(es, (short int) iy); es +=2; octet_count += cgmAppShort(es, (short int) ex); es +=2; octet_count += cgmAppShort(es, (short int) ey); es +=2; octet_count += cgmAppShort(es, (short int) cl); es +=2; /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } static int cgmEllipse(cgmImagePtr im, int cx,int cy, int d1x,int d1y, int d2x,int d2y ) { /* Graphic Primitive: Ellipse; Elem Class 4; Elem ID 17 * * This function will draw an Ellipse using the current * edge type, width, color, and visibility, and the current * fill style, color, and hatch */ unsigned char *es, *esp; int octet_count; /* check to make sure the line is withing the scope of the picture * ie. the values you give for drawing the line are within * the values you created the picture with */ if (!(cgmImageBoundsSafe(im, cx,cy)) || !(cgmImageBoundsSafe(im, d1x,d1y)) || !(cgmImageBoundsSafe(im, d2x, d2y))) { return 0; } /* allocate sufficent space. should be 32 bits * 4 to be safe */ es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; /* their are six 16 bit signed integers as attributes */ if (!cgmcomhead(es, 4, 17, 12)) { free(esp); return 0; } es +=2; octet_count = 2; /* now we are ready for the parameter data */ octet_count += cgmAppShort(es, (short int) cx); es +=2; octet_count += cgmAppShort(es, (short int) cy); es +=2; octet_count += cgmAppShort(es, (short int) d1x); es +=2; octet_count += cgmAppShort(es, (short int) d1y); es +=2; octet_count += cgmAppShort(es, (short int) d2x); es +=2; octet_count += cgmAppShort(es, (short int) d2y); es +=2; /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } #endif static int cgmPolygon(cgmImagePtr im, cgmPointPtr p, int n) { /* Graphic Primitive: Polygon; Elem Class 4; Elem ID 7 * * cgmPointPtr is defined in cgm.h, basically, it is two arrays of integers * p[m].x and p[m].y containing the x and y values respectively. n * is the number of points in this array (not the index of the last point, * which is n-1). n must be at least 3 (otherwise * you really don't have much of a polygon, it is closer to a line.) * * This function will draw a Polygon using the current * edge type, width, color, and visibility, and the current * fill style, color, and hatch */ unsigned char *es, *esp; int octet_count; int x; /* counter */ if (n < 3) { return 0; /* it is either a point or a line */ } if (n < 8) { /* It fits in the short form of the command, lets us * add it right now, shall we? */ /* allocate sufficent space. Should be 32 bits*10 to be safe */ es = (unsigned char *) calloc(4*10,SIZEOF(unsigned char )); if (!es) { return 0; /* memory allocation failed */ } esp=es; /* their are n*2 16 bit signed integers as attributes */ if (!cgmcomhead(es, 4, 7, (n*4))) { free(esp); return 0; } es +=2; octet_count = 2; } else if (n < 8191) { /* there are more than 7 points in it, that sucks */ /* gej, so basically, for this one, I set the header * to cgmcomhead(es, 4, 7, 31) then write a function for the long * form that takes the first 15 bits of n and tags a 0 in front * of it and puts it in es, than I do the for loop all over again * that doesn't seem too hard. But I will leave that for another * day. * keep in mind that if CGMGROWLISTSIZE is smaller than n*4 * (at most 32769) then things could fail in a most unsavory fashion. */ /* allocate sufficent space. 32 bits*(n+1) to be safe */ es = (unsigned char *) calloc(4*(n+1), SIZEOF(unsigned char )); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomheadlong(es, 4, 7, (n*4))) { free(esp); return 0; } es +=4; octet_count = 4; } else { /* there are more than 8191 points in it, I am not going to implement * that, if you want it that bad, do it yourself. */ return 0; } for (x=0; xx); es += cgmAppShort(es, (short int) p->y); octet_count += 4; p++; } /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } #ifdef VTK_NOT_DEFINED static int cgmPolygonSet(cgmImagePtr im, cgmPointPtr p, int n) { /* Graphic Primitive: Polygon; Elem Class 4; Elem ID 8 * * cgmPointPtr is defined in cgm.h, basically, it is three arrays of integers * p[m].x and p[m].y containing the x and y values respectively and p[m].e * the characteristics of the line leaving point n (0=invisible,1=visible, * 2=close,invisible, 3=close,visible). n is the number of points in this * array (not the index of the last point, which is n-1). * n must be at least 3 (otherwise you really don't have much of a polygon, * it is closer to a line.) * * This function will draw a set of Polygons using the current * edge type, width, color, and the current * fill style, color, and hatch */ unsigned char *es, *esp; int octet_count; int x; /* counter */ if (n < 3) { return 0; /* it is either a point or a line */ } if (n < 6) { /* It fits in the short form of the command, lets us * add it right now, shall we? */ /* allocate sufficent space. Should be 48 bits*10 to be safe */ es = (unsigned char *) calloc(6*10,SIZEOF(unsigned char )); if (!es) { return 0; /* memory allocation failed */ } esp=es; /* their are n*2 16 bit signed integers as attributes */ if (!cgmcomhead(es, 4, 8, (n*6))) { free(esp); return 0; } es +=2; octet_count = 2; } else if (n < 5462) { /* there are more than 5 points in it, that sucks */ /* gej, so basically, for this one, I set the header * to cgmcomhead(es, 4, 7, 31) then write a function for the long * form that takes the first 15 bits of n and tags a 0 in front * of it and puts it in es, than I do the for loop all over again * that doesn't seem too hard. But I will leave that for another * day. * keep in mind that if CGMGROWLISTSIZE is smaller than n*6 * (at most 32769) then things could fail in a most unsavory fashion. */ /* allocate sufficent space. 48 bits*(n+1) to be safe */ es = (unsigned char *) calloc(6*(n+1), SIZEOF(unsigned char )); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomheadlong(es, 4, 8, (n*6))) { free(esp); return 0; } es +=4; octet_count = 4; } else { /* there are more than 5462 points in it, I am not going to implement * that, if you want it that bad, do it yourself. */ return 0; } for (x=0; xx); es += cgmAppShort(es, (short int) p->y); es += cgmAppShort(es, (short int) p->e); octet_count += 6; p++; } /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } #endif static int cgmPolyLine(cgmImagePtr im, cgmPointPtr p, int n) { /* Graphic Primitive: Polyline; Elem Class 4; Elem ID 1 * * cgmPointPtr is defined in cgm.h, basically, it is two arrays of integers * p[m].x and p[m].y containing the x and y values respectively. n * is the number of points in this array (not the index of the last point, * which is n-1). if n is 2, it is a regular line, like cgmline * * This function will draw a Polyline using the current * line type, width, color, and visibility, */ unsigned char *es, *esp; int octet_count; int x; /* counter */ if (n < 2) { return 0; /* it is a point */ } if (n < 8) { /* It fits in the short form of the command, lets us * add it right now, shall we? */ /* allocate sufficent space. Should be 32 bits*10 to be safe */ es = (unsigned char *) calloc(4*10,SIZEOF(unsigned char )); if (!es) { return 0; /* memory allocation failed */ } esp=es; /* their are n*2 16 bit signed integers as attributes */ if (!cgmcomhead(es, 4, 1, (n*4))) { free(esp); return 0; } es +=2; octet_count = 2; } else if (n < 8191) { /* there are more than 7 points in it, that sucks */ /* gej, so basically, for this one, I set the header * using the long version cgmcomheadlong(es, 4, 1, n*4) * keep in mind that if CGMGROWLISTSIZE is smaller than n*4 * (at most 32769) then the list may have to grow several times */ /* allocate sufficent space. 32 bits*(n+1) to be safe */ es = (unsigned char *) calloc(4*(n+1), SIZEOF(unsigned char )); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomheadlong(es, 4, 1, (n*4))) { free(esp); return 0; } es +=4; octet_count = 4; } else { /* there are more than 8191 points in it, I am not going to implement * that, if you want it that bad, do it yourself. */ return 0; } for (x=0; xx); es += cgmAppShort(es, (short int) p->y); octet_count += 4; p++; } /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } static int cgmPolyMarker(cgmImagePtr im, cgmPointPtr p, int n) { /* Graphic Primitive: PolyMarker; Elem Class 4; Elem ID 3 * * cgmPointPtr is defined in cgm.h, basically, it is two arrays of integers * p[m].x and p[m].y containing the x and y values respectively. n * is the number of points in this array (not the index of the last point, * which is n-1). if n is 2, it is a regular line, like cgmline * * This function will insert n markers using the current * Marker type, width, color, and visibility, */ unsigned char *es, *esp; int octet_count; int x; /* counter */ if (n < 1) { return 0; /* it is nothing */ } if (n < 8) { /* It fits in the short form of the command, lets us * add it right now, shall we? */ /* allocate sufficent space. Should be 32 bits*10 to be safe */ es = (unsigned char *) calloc(4*10,SIZEOF(unsigned char )); if (!es) { return 0; /* memory allocation failed */ } esp=es; /* their are n*2 16 bit signed integers as attributes */ if (!cgmcomhead(es, 4, 3, (n*4))) { free(esp); return 0; } es +=2; octet_count = 2; } else if (n < 8191) { /* there are more than 7 points in it, that sucks */ /* gej, so basically, for this one, I set the header * using the long version cgmcomheadlong(es, 4, 1, n*4) * keep in mind that if CGMGROWLISTSIZE is smaller than n*4 * (at most 32769) then the list may have to grow several times */ /* allocate sufficent space. 32 bits*(n+1) to be safe */ es = (unsigned char *) calloc(4*(n+1), SIZEOF(unsigned char )); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomheadlong(es, 4, 3, (n*4))) { free(esp); return 0; } es +=4; octet_count = 4; } else { /* there are more than 8191 points in it, I am not going to implement * that, if you want it that bad, do it yourself. */ return 0; } for (x=0; xx); es += cgmAppShort(es, (short int) p->y); octet_count += 4; p++; } /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } #ifdef VTK_NOT_DEFINED static int cgmText(cgmImagePtr im, int x, int y, const char *ts) { /* Graphic Primitive: Text; Elem Class 4; Elem ID 4 * add text to the picture. Start it at the point (x,y) * this should be the lower left corner of where the text is * the parameters are point, enumerated(set to 1), string * * String encoding in CGM is a little strange. After you have the other * parameter info, the first octet for the string is either 0..254 which * is the number of octets of string data, or 255 which signifies a long * string. if it is 255 then the next 16 bits indicate the length of the * string. the first bit (bit15) is 0 if this is the last part of the * string and 1 if another part follows it. the next 15 bits are in the * range 0..32767 and are the number of octets of string info following. * so the length stored in the command header is the whole enchelada. */ int tslen, curly; unsigned char *es, *esp; int octet_count; /* check to make sure the Text is within the scope of the picture * actually, I am only checking the start of it */ if (!(cgmImageBoundsSafe(im, x, y))) { return 0; } /* allocate sufficent space. should be tslen+ 32 bits * 4 to be safe */ tslen = strlen(ts); /* if there are more than 32700 characters fail * gej: this could go as high as 32767 I think, but lets * cut it off at 32700 */ if ((tslen > 32700) || (tslen < 0)) { return 0; } es = (unsigned char *) calloc( ((4*4)+tslen), SIZEOF(unsigned char ) ); if (!es) { return 0; /* memory allocation failed */ } esp=es; if (!cgmcomheadlong(es, 4, 4, 9+tslen)) { free(esp); return 0; } es +=4; octet_count = 4; /* add the x position, the y position, then 1, which signifies * that this is all the text, there is none appended after it */ es += cgmAppShort(es, (short int) x); es += cgmAppShort(es, (short int) y); es += cgmAppShort(es, (short int) 1); octet_count += 6; /* now take care of the string information, for strings 254 bytes * or less, I could use a short one, but why bother, use the long * form for everything */ es += cgmAppByte(es, (short int) 255); es += cgmAppShort(es, (short int) tslen); octet_count += 3; /* gej: I should set bit 15 to 0 because it is the final part of a * string but I am not going to since I already checked that it was * a 16 number that was non-negative */ while(*ts) { *es++ = (unsigned char) *ts++; } octet_count +=tslen; /* now if the octet_count is not divisible by 4 add null padding */ curly = 4 - (octet_count % 4); if (curly % 4) { octet_count += curly; es += cgmAppNull(es, curly); } /* add it to the buffer */ if (cgmAddElem(im, esp, octet_count)) { free(esp); return 1; } else { free(esp); return 0; } } static int cgmImageLine(cgmImagePtr im, int x1, int y1, int x2, int y2, int color) /* gej: this should be so much easier to do as a cgm * This is in for compatibility with gd, if you don't need that, use * cgmLine instead */ { int ltstate; /* save the linetype state */ ltstate = im->ltype; /* set the attributes of the line */ if (!cgmSetLineAttrib(im, 1, -1, color)) { return 0; } if (!cgmLine(im, x1, y1, x2, y2)) { return 0;/* draw the line */ } /* restore the state If it fails, don't return an error, because * the line was still drawn */ cgmSetLineType(im, ltstate); return 1; } static int cgmImageDashedLine(cgmImagePtr im, int x1, int y1, int x2, int y2, int color) /* gej: this should be so much easier to do as a cgm * in order to really get a dashed line you must call cgmSetLineType first * This is in for compatibility with gd, if you don't need that, use * cgmLine instead */ { /* set the attributes of the line */ if (!cgmSetLineAttrib(im, -1, -1, color)) { return 0; } /* generate the line */ if (!cgmLine(im, x1, y1, x2, y2)) { return 0; } /* everthing is A-OK */ return 1; } static int cgmImageBoundsSafe(cgmImagePtr im, int x, int y) /* From gd library, see README file for copyright information */ /* gej: this should work unchanged */ { return (!(((y < 0) || (y >= im->sy)) || ((x < 0) || (x >= im->sx)))); } static int cgmImageRectangle(cgmImagePtr im, int x1, int y1, int x2, int y2, int color) /* Graphic Primitive: rectangle; Elem Class 4; Elem ID 11 */ /* gej: but I think I will use the cgm rectangle */ { if(!cgmImageLine(im, x1, y1, x2, y1, color)) { return 0; } if(!cgmImageLine(im, x1, y2, x2, y2, color)) { return 0; } if(!cgmImageLine(im, x1, y1, x1, y2, color)) { return 0; } if(!cgmImageLine(im, x2, y1, x2, y2, color)) { return 0; } return 1; } #endif /* Expert functions. If you need more control, you can use these * functions, but you probably won't need to. */ static int cgmImageSetSize(cgmImagePtr im, int x, int y) /* sets the width and height of subsequent pictures. */ { im->sx = x; im->sy = y; return 1; } #ifdef VTK_NOT_DEFINED static int cgmImageSetLineSpec(cgmImagePtr im, int specmode) /* Picture Descriptor: Line Width Specification Mode; Elem Class 2; Elem ID 3*/ /* sets the Line Width Specification mode of subsequent pictures. * 1 is scaled (default), 2 is absolute */ { if ((specmode < 0) || (specmode > 2)) { return 0; } im->linespec = specmode; return 1; } static int cgmImageSetMarkerSpec(cgmImagePtr im, int specmode) /* Picture Descriptor: Marker Size Specification Mode; Elem Class 2; Elem ID 4*/ /* sets the Marker Width Specification mode of subsequent pictures. * 1 is scaled (default), 2 is absolute */ { if ((specmode < 0) || (specmode > 2)) { return 0; } im->linespec = specmode; return 1; } static int cgmImageSetEdgeSpec(cgmImagePtr im, int specmode) /* Picture Descriptor: Edge Width Specification Mode; Elem Class 2; Elem ID 5*/ /* sets the Edge Width Specification mode of subsequent pictures. * 1 is scaled (default), 2 is absolute */ { if ((specmode < 0) || (specmode > 2)) { return 0; } im->edgespec = specmode; return 1; } #endif static int cgmImageSetOutput(cgmImagePtr im, FILE *output) /* sets the output file to *output. which must already be open. * does not close the file * Useful if you want to write the file as you go along, or if you * want to write it to a stream */ { if(output) { im->outfile = output; return 1; } else { return 0; } } #ifdef VTK_NOT_DEFINED static int cgmImageAddFont(cgmImagePtr im, const char *fontname) /* adds a font to the list of fonts. This only has an effect * if you are using the expert functions for starting pictures, and * have not yet opened the first picture. Returns 0 for failure, * and the font index on success */ { unsigned char *oldfonts; int listsize; oldfonts = im->fontlist; if (oldfonts) { listsize = strlen( (char *)oldfonts) + 1 + strlen(fontname) + 1; } else { listsize = strlen(fontname) +1; } im->fontlist=(unsigned char *) calloc(listsize,SIZEOF(unsigned char)); if (!im->fontlist) { return 0; /* memory allocation failed */ } if (oldfonts) { sprintf((char *)im->fontlist, "%s%s%s", (char *)oldfonts, ",", fontname); } else { sprintf((char *)im->fontlist, "%s", fontname); } im->numfonts++; if (oldfonts) { free(oldfonts); } oldfonts = NULL; return im->numfonts; } static int cgmImageClearFonts(cgmImagePtr im) /* clears out ALL fonts from the font list, including the ones the * package has be default. Useful if you want totally different fonts. */ { free(im->fontlist); im->fontlist = NULL; im->numfonts = 0; return 1; } #endif static int cgmImageSetDefaults(cgmImagePtr im) /* resets the defaults to what is in defines.h */ { /* you must be either before any picture has been created, * or after a picture has closed to call this */ if ((im->state != 0) && (im->state != 2)) { return 0; } /* set line_width, line_height, line_color to the defaults */ im->ltype = CGMLTYPE; im->lwidth = CGMLWIDTH; im->lcolor = CGMLCOLOR; /* interior_style, fill_color, hatch_index */ im->shapestyle = CGMSHAPESTYLE; im->shapecolor = CGMSHAPECOLOR; im->shapehatch = CGMSHAPEHATCH; /* edge_type, edge_width, edge_color, edge_visibility */ im->edgetype = CGMEDGETYPE; im->edgecolor = CGMEDGECOLOR; im->edgewidth = CGMEDGEWIDTH; im->edgevis = CGMEDGEVIS; /* text_color, text_height, text_font */ im->textcolor = CGMTEXTCOLOR; im->textheight = CGMTEXTHEIGHT; im->textfont = CGMTEXTFONT; im->textpath = CGMTEXTPATH; /* set marker_width, marker_size, marker_color to the defaults */ im->ltype = CGMMTYPE; im->lwidth = CGMMSIZE; im->lcolor = CGMMCOLOR; /* this is set by the expert functions. the defaults should be ok */ im->linespec = CGMLINESPEC; im->edgespec = CGMEDGESPEC; im->markerspec = CGMMARKERSPEC; return 1; } static cgmImagePtr cgmImageStartCgm() /* initializes the CGM and sets up the defaults. If you are using * the "expert" functions, you should call this first. _ge */ { const char *tmps; int tmpsl; cgmImagePtr im; im = (cgmImage *) calloc(SIZEOF(cgmImage), 1); if (!im) { return 0; /* memory allocation failed */ } /* elemlist is set to some number, when it is full, make it bigger */ im->elemlist = (unsigned char *) calloc(CGMSTARTLISTSIZE, SIZEOF(unsigned char ) ); if (!im->elemlist) { free(im); return 0; } /* memory allocation failed */ im->colorsTotal = 0; /* you can have multiple pictures in a file, keep track of * which one you are on */ im->picnum = 0; im->outfile = NULL; /* the next three are used for maintaining the element list * don't change these ever */ im->bytestoend = CGMSTARTLISTSIZE; im->listlen = CGMSTARTLISTSIZE; im->curelemlist = im->elemlist; /* don't make this longer than 250 characters */ tmps = "vtk CGM Output file"; tmpsl = (int)strlen(tmps); if (tmpsl >250) { tmpsl = 250; } im->desc = (unsigned char *) calloc(tmpsl+1, SIZEOF(unsigned char)); strncpy((char*)im->desc, tmps, tmpsl); /* The font list can be quite long, but individual font names can * can only be 250 chars */ 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"; im->numfonts=12; tmpsl = (int)strlen(tmps); im->fontlist = (unsigned char *) calloc(tmpsl+1, SIZEOF(unsigned char)); strcpy((char*)im->fontlist, tmps); im->outfile = NULL; if (!cgmImageSetDefaults(im)) { cgmImageDestroy (im); } /* set the state */ im->state = 0; /* 0 no pictures started, 1 in a picture, * 2 after a picture */ return im; } static int cgmImageEndPic(cgmImagePtr im) /* close the current picture */ { unsigned char *es, *esp; int octet_count=0; /* make sure we are really in a picture before ending it */ if (im->state != 1) { return 0; } esp = (unsigned char *) calloc(1024, SIZEOF(unsigned char )); if (!esp) { return 0; /* memory allocation failed */ } es=esp; /* Attribute: End Picture; Elem Class 0; Elem ID 5; Length 0 */ if (!cgmcomhead(es, 0, 5, 0)) { free(esp); return 0; } octet_count += 2; if (cgmAddElem(im, esp, octet_count)) { free(esp); im->state=2; return 1; } else { free(esp); return 0; } } static int cgmImageEndCgm (cgmImagePtr im) /* close the current CGM file. If an output stream is * defined, write the CGM to it */ { int x; /* counter */ int used; /* number of bytes used in the list */ unsigned char *efile, *efilep; /* end of file information */ cgmImageEndPic(im); if (im->state == 2) { /* We have closed the pic, but not the CGM */ efile = (unsigned char *) calloc(4*4,SIZEOF(unsigned char )); if (!efile) { return 0; /* memory allocation failed */ } efilep=efile; /* Attribute: End Metafile; Elem Class 0; Elem ID 2 */ cgmcomhead(efilep, 0, 2, 0); if (cgmAddElem(im, efile, 2)) { free(efile); } else { free(efile); return 0; } } if (im->outfile) { /* now output the CGM, one byte at a time */ used = im->listlen - im->bytestoend; for (x=0;x < used; x++) { putc((unsigned char) im->elemlist[x], im->outfile); } } /* else do nothing */ return 1; }