You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4483 lines
112 KiB
4483 lines
112 KiB
/*=========================================================================
|
|
|
|
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; i<VTK_HASH_INDEX; i++)
|
|
{
|
|
this->Table[i] = NULL;
|
|
}
|
|
}
|
|
|
|
vtkColorHash::~vtkColorHash()
|
|
{
|
|
int i;
|
|
for (i=0; i<VTK_HASH_INDEX; i++)
|
|
{
|
|
if ( this->Table[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; i<numIds; i++)
|
|
{
|
|
cgmIndex = this->Table[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; i<numIds; i++)
|
|
{
|
|
cgmIndex = this->Table[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; i<numPts; i++)
|
|
{
|
|
pts->GetPoint(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<vtkUnsignedCharArray *>(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; i<npts; i++)
|
|
{
|
|
scaledPts->GetPoint(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; i<npts; i++)
|
|
{
|
|
scaledPts->GetPoint(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; i<npts; i++)
|
|
{
|
|
scaledPts->GetPoint(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<x; y++)
|
|
{
|
|
*es = '\0';
|
|
es++;
|
|
}
|
|
return x;
|
|
}
|
|
|
|
static int cgmAppByte(unsigned char *es, short int addme)
|
|
{
|
|
/* Append an octet to the end of es
|
|
* Return value is number of octets added
|
|
* for internal cgm functions only, do not call
|
|
*/
|
|
*es = (unsigned char) addme & 0377;
|
|
return 1;
|
|
}
|
|
|
|
static int cgmAppShort(unsigned char *es, short int addme)
|
|
{
|
|
/* Append a short to the end of es
|
|
* return value is number of octets added
|
|
* For internal cgm functions only, do not call!
|
|
*/
|
|
short int temp;
|
|
|
|
temp = addme >> 8;
|
|
*es = (unsigned char) temp & 0377;
|
|
es++;
|
|
*es = (unsigned char) addme & 0377;
|
|
return 2;
|
|
}
|
|
|
|
static int 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; x<n; x++)
|
|
{
|
|
/* now we are ready for the parameter data */
|
|
es += cgmAppShort(es, (short int) p->x);
|
|
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; x<n; x++)
|
|
{
|
|
/* now we are ready for the parameter data */
|
|
es += cgmAppShort(es, (short int) p->x);
|
|
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; x<n; x++)
|
|
{
|
|
/* now we are ready for the parameter data */
|
|
es += cgmAppShort(es, (short int) p->x);
|
|
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; x<n; x++)
|
|
{
|
|
/* now we are ready for the parameter data */
|
|
es += cgmAppShort(es, (short int) p->x);
|
|
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;
|
|
}
|
|
|