/* * Python interface to Bruce Verderaime's GDChart library. * * Copyright (c) 1999-2001 Mike Steed. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software, to deal in the software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the software, and to * permit persons to whom the software is furnished to do so, subject to the * following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Please direct any enquiries to pygdchart@nullcube.com */ #include #include #include #include #define MAXSHORT SHRT_MAX #define HAVE_JPEG 1 #include "Python.h" #include "cStringIO.h" #include "gdc.h" #include "gdchart.h" #include "gdcpie.h" #ifndef HAVE_JPEG #define GDC_JPEG 1 #endif // Use unique values for pie chart types, since the module exports a single // function for creating all types of charts. #define MY_GDC_2DPIE (100 + GDC_2DPIE) #define MY_GDC_3DPIE (100 + GDC_3DPIE) #define SetTypeError(f, a) \ sprintf(Msgbuf, "%s: illegal argument type for %s", f, a); \ PyErr_SetString(GDChartError, Msgbuf) #define SetValueError(f, a) \ sprintf(Msgbuf, "%s: illegal value for %s", f, a); \ PyErr_SetString(GDChartError, Msgbuf) static char ModuleDoc[] = "This module provides an interface to the GDChart library by Bruce Verderaime.\n\ (c) 1999-2001 Mike Steed. http://www.nullcube.com/software/pygdchart/index.html\n\ \n\ Dynamic objects:\n\ \n\ error -- Module-level exception.\n\ \n\ Constants:\n\ \n\ image formats --\n\ GDC_GIF GDC_JPEG GDC_PNG\n\ GDC_WBMP (black & white)\n\ \n\ chart styles --\n\ GDC_AREA GDC_3DAREA\n\ GDC_BAR GDC_3DBAR\n\ GDC_FLOATINGBAR GDC_3DFLOATINGBAR\n\ GDC_LINE GDC_3DLINE\n\ GDC_COMBO_LINE_AREA GDC_3DCOMBO_LINE_AREA\n\ GDC_COMBO_LINE_BAR GDC_3DCOMBO_LINE_BAR\n\ GDC_COMBO_LINE_LINE GDC_3DCOMBO_LINE_LINE\n\ GDC_HILOCLOSE GDC_3DHILOCLOSE\n\ GDC_COMBO_HLC_AREA GDC_3DCOMBO_HLC_AREA\n\ GDC_COMBO_HLC_BAR GDC_3DCOMBO_HLC_BAR\n\ GDC_2DPIE GDC_3DPIE\n\ \n\ fonts --\n\ GDC_TINY GDC_SMALL GDC_MEDBOLD\n\ GDC_LARGE GDC_GIANT\n\ \n\ stack options --\n\ GDC_STACK_BESIDE GDC_STACK_DEPTH GDC_STACK_LAYER\n\ GDC_STACK_SUM\n\ \n\ hi-lo-close styles (may be combined) --\n\ GDC_HLC_CLOSE_CONNECTED GDC_HLC_CONNECTING\n\ GDC_HLC_DIAMOND GDC_HLC_I_CAP\n\ \n\ scatter point styles --\n\ GDC_SCATTER_TRIANGLE_DOWN GDC_SCATTER_TRIANGLE_UP GDC_SCATTER_CIRCLE\n\ \n\ percent placement options (pie charts) --\n\ GDCPIE_PCT_NONE GDCPIE_PCT_ABOVE GDCPIE_PCT_BELOW\n\ GDCPIE_PCT_RIGHT GDCPIE_PCT_LEFT\n\ \n\ border styles --\n\ GDC_BORDER_NONE GDC_BORDER_ALL GDC_BORDER_X\n\ GDC_BORDER_Y GDC_BORDER_Y2 GDC_BORDER_TOP\n\ \n\ tick styles (for 'grid' and 'ticks' options) --\n\ GDC_TICK_LABELS GDC_TICK_POINTS GDC_TICK_NONE\n\ \n\ other --\n\ GDC_INTERP_VALUE => interpolate data value if 'interpolations' opt is true\n\ \n\ Functions:\n\ \n\ chart() -- create a chart\n\ option() -- get and set chart options\n\ "; static char ChartDoc[] = "chart(s, (w, h), f, l, data...)\n\ \n\ s -- chart style\n\ (w,h) -- dimensions of image (width, height)\n\ f -- file object or name of file where image should be written\n\ l -- sequence of x-axis labels\n\ data -- one or more sequences of data values, depending on the chart style:\n\ simple: chart(s, (w,h), f, l, d [,d...])\n\ float bar: chart(s, (w,h), f, l, (dl,dh) [,(dl,dh)...])\n\ combo: chart(s, (w,h), f, l, d [,d...], da)\n\ hi-lo-close: chart(s, (w,h), f, l, (dh,dl,dc) [,(dh,dl,dc)...])\n\ combo hlc: chart(s, (w,h), f, l, (dh,dl,dc) [,(dh,dl,dc)...], dv)\n\ pie: chart(s, (w,h), f, l, d [, p])\n\ missing values:\n\ for pie charts, p is a sequence indicating which values in d are\n\ 'present' (0 or None => corresponding value in d is missing)\n\ for other charts, None in a dataset indicates a missing value"; static char OptionDoc[] = "option() -- return a dictionary of current option settings\n\ option(keyword=value [,keyword=value...]) -- change one or more options\n\ \n\ keywords and type codes --\n\ b: boolean c: color (0xRRGGBB) e: enum (GDC_*)\n\ n: number s: string *: not implemented\n\ (x): sequence of type x\n\ \n\ annotation=(n,c,s) label_dist=n vol_color=c\n\ annotation_font=e label_font=e xaxis=b\n\ bar_width=n label_line=b xaxis_font=e\n\ bg_color=c line_color=c xlabel_color=c\n\ bg_image=s other_threshold=n xlabel_spacing=n\n\ bg_transparent=b percent_format=s xtitle=s\n\ border=e percent_labels=e xtitle_color=c\n\ edge_color=c pie_color=(c) xtitle_font=e\n\ explode=(i) plot_color=c yaxis=b\n\ ext_color=(c) requested_yinterval=n yaxis2=b\n\ ext_vol_color=(c) requested_ymax=n yaxis_font=e\n\ format=e|(e,n) requested_ymin=n ylabel_color=c\n\ generate_img=b scatter=((n,n,n,c,e),...) ylabel_density=n\n\ grid=e|n set_color=(c) ylabel_fmt=s\n\ grid_color=c stack_type=e ylabel2_color=c\n\ hard_graphheight=n threed_angle=n ylabel2_fmt=s\n\ hard_graphwidth=n threed_depth=n ytitle=s\n\ hard_size=b thumblabel=s ytitle_color=c\n\ hard_xorig=n thumbnail=b ytitle_font=e\n\ hard_yorig=n thumbval=n ytitle2=s\n\ hlc_cap_width=n ticks=e|n ytitle2_color=c\n\ hlc_style=e title=s zeroshelf=b\n\ hold_img=b title_color=c \n\ interpolations=b title_font=e \n\ \n\ 'annotation' values are (point, color, note). The GDChart library is\n\ currently limited to one annotation per chart.\n\ \n\ 'format' specifies the image format (default is GDC_PNG). With GDC_JPEG,\n\ you can optionally specify the image quality (0-95, or -1 for default).\n\ \n\ 'scatter' is a sequence of tuples: ((x, y, width(%), color, style) [,...]).\n"; static PyObject *GDChartError; static char Msgbuf[128]; // Cached values for array & string options static void *Annotation = NULL; // GDC_annotation static void *BGImage = NULL; // GDC_BGImage static void *Explode = NULL; // GDCPIE_explode static void *ExtColor = NULL; // GDC_ExtColor static void *ExtVolColor = NULL; // GDC_ExtVolColor static void *xlabel_ctl = NULL; // GDC_xlabel_ctl static void *PercentFmt = NULL; // GDCPIE_percent_fmt static void *PieColor = NULL; // GDCPIE_Color static void *Scatter = NULL; // GDC_scatter static void *SetColor = NULL; // GDC_SetColor static void *ThumbLabel = NULL; // GDC_thumblabel static void *Title = NULL; // GDC_title static void *XTitle = NULL; // GDC_xtitle static void *YLabelFmt = NULL; // GDC_ylabel_fmt static void *YLabel2Fmt = NULL; // GDC_ylabel2_fmt static void *YTitle = NULL; // GDC_ytitle static void *YTitle2 = NULL; // GDC_ytitle // Pointers to the above pointers, used to free any allocated memory at exit. static void **ArrayData[] = { &Annotation, &BGImage, &Explode, &ExtColor, &ExtVolColor, &xlabel_ctl, &PercentFmt, &PieColor, &Scatter, &SetColor, &ThumbLabel, &Title, &XTitle, &YLabelFmt, &YLabel2Fmt, &YTitle, &YTitle2, NULL }; typedef enum { opt_bool, opt_bool_a, opt_float, opt_font, opt_int, opt_int_a, opt_long, opt_long_a, opt_percent, opt_special, opt_string } option_type; static struct option { char *keyword; option_type type; void *chartvar; void *pievar; void **cache; int size; } Options[] = { { "annotation", opt_special, NULL, NULL }, { "annotation_font", opt_font, &GDC_annotation_font, NULL }, { "bar_width", opt_percent, &GDC_bar_width, NULL }, { "bg_color", opt_long, &GDC_BGColor, &GDCPIE_BGColor }, { "bg_image", opt_string, &GDC_BGImage, &GDC_BGImage, &BGImage }, { "bg_transparent", opt_bool, &GDC_transparent_bg, NULL }, { "border", opt_special, &GDC_border, NULL }, { "edge_color", opt_long, NULL, &GDCPIE_EdgeColor }, { "explode", opt_int_a, NULL, &GDCPIE_explode, &Explode }, { "ext_color", opt_long_a, &GDC_ExtColor, NULL, &ExtColor }, { "ext_vol_color", opt_long_a, &GDC_ExtVolColor, NULL, &ExtVolColor }, { "xlabel_ctl", opt_bool_a, &GDC_xlabel_ctl, NULL, &xlabel_ctl }, { "format", opt_special, NULL, NULL, }, { "generate_img", opt_bool, &GDC_generate_img, NULL }, { "grid", opt_special, &GDC_grid, NULL }, { "grid_color", opt_long, &GDC_GridColor, NULL }, { "hard_graphheight", opt_int, &GDC_hard_grapheight, NULL }, { "hard_graphwidth", opt_int, &GDC_hard_graphwidth, NULL }, { "hard_size", opt_bool, &GDC_hard_size, NULL }, { "hard_xorig", opt_int, &GDC_hard_xorig, NULL }, { "hard_yorig", opt_int, &GDC_hard_yorig, NULL }, { "hlc_cap_width", opt_percent, &GDC_HLC_cap_width, NULL }, { "hlc_style", opt_special, &GDC_HLC_style, NULL }, { "hold_img", opt_special, &GDC_hold_img, NULL }, { "interpolations", opt_bool, &GDC_interpolations, NULL }, { "label_dist", opt_int, NULL, &GDCPIE_label_dist }, { "label_font", opt_font, NULL, &GDCPIE_label_size }, { "label_line", opt_bool, NULL, &GDCPIE_label_line }, { "line_color", opt_long, &GDC_LineColor, &GDCPIE_LineColor }, { "other_threshold", opt_special, NULL, NULL }, { "percent_format", opt_string, NULL, &GDCPIE_percent_fmt, &PercentFmt }, { "percent_labels", opt_special, NULL, &GDCPIE_percent_labels }, { "pie_color", opt_long_a, NULL, &GDCPIE_Color, &PieColor }, { "plot_color", opt_long, &GDC_PlotColor, &GDCPIE_PlotColor }, { "requested_yinterval", opt_float, &GDC_requested_yinterval, NULL }, { "requested_ymax", opt_float, &GDC_requested_ymax, NULL }, { "requested_ymin", opt_float, &GDC_requested_ymin, NULL }, { "scatter", opt_special, NULL, NULL }, { "set_color", opt_long_a, &GDC_SetColor, NULL, &SetColor }, { "stack_type", opt_special, &GDC_stack_type, NULL }, { "threed_angle", opt_special, NULL, NULL }, { "threed_depth", opt_special, NULL, NULL }, // different types! { "thumblabel", opt_string, &GDC_thumblabel, NULL, &ThumbLabel }, { "thumbnail", opt_bool, &GDC_thumbnail, NULL }, { "thumbval", opt_float, &GDC_thumbval, NULL }, { "ticks", opt_special, &GDC_ticks, NULL }, { "title", opt_string, &GDC_title, &GDCPIE_title, &Title }, { "title_color", opt_long, &GDC_TitleColor, NULL }, // why no pie opt? { "title_font", opt_font, &GDC_title_size, &GDCPIE_title_size }, { "vol_color", opt_long, &GDC_VolColor, NULL }, { "xaxis", opt_bool, &GDC_xaxis, NULL }, { "xaxis_font", opt_font, &GDC_xaxisfont_size, NULL }, { "xlabel_color", opt_long, &GDC_XLabelColor, NULL }, { "xlabel_spacing", opt_special, NULL, NULL }, { "xtitle", opt_string, &GDC_xtitle, NULL, &XTitle }, { "xtitle_color", opt_long, &GDC_XTitleColor, NULL }, { "xtitle_font", opt_font, &GDC_xtitle_size, NULL }, { "yaxis", opt_bool, &GDC_yaxis, NULL }, { "yaxis2", opt_bool, &GDC_yaxis2, NULL }, { "yaxis_font", opt_font, &GDC_yaxisfont_size, NULL }, { "ylabel_color", opt_long, &GDC_YLabelColor, NULL }, { "ylabel_density", opt_percent, &GDC_ylabel_density, NULL }, { "ylabel_fmt", opt_string, &GDC_ylabel_fmt, NULL, &YLabelFmt }, { "ylabel2_color", opt_long, &GDC_YLabel2Color, NULL }, { "ylabel2_fmt", opt_string, &GDC_ylabel2_fmt, NULL, &YLabel2Fmt }, { "ytitle", opt_string, &GDC_ytitle, NULL, &YTitle }, { "ytitle_color", opt_long, &GDC_YTitleColor, NULL }, { "ytitle_font", opt_font, &GDC_ytitle_size, NULL }, { "ytitle2", opt_string, &GDC_ytitle2, NULL, &YTitle2 }, { "ytitle2_color", opt_long, &GDC_YTitle2Color, NULL }, { "zeroshelf", opt_bool, &GDC_0Shelf, NULL }, { NULL } }; static void _cleanup() { int i = 0; void **mem; for (i = 0; (mem = ArrayData[i]) != NULL; i++) { if (*mem != NULL) { PyMem_Free(*mem); *mem = NULL; } } } // Retrieve chart style, image dimensions, file, and labels from a Python // argument list. Also return the number of points expected in each data set, // if known. static int _parse_common_args( PyObject * args, char * caller, int * chartStyle, int * imgWidth, int * imgHeight, FILE ** file, PyObject ** stringIO, char *** labels, int * numPoints, int * closeFile) { PyObject *arg; PyObject *width; PyObject *height; PyObject *label; char *filename; int i; // Parse common arguments. Can't use PyArg_ParseTuple() because we need // to handle variable arg quantities & types. // Chart style: int. arg = PyTuple_GetItem(args, 0); if (!PyInt_Check(arg)) { sprintf(Msgbuf, "%s, argument 1: expected int", caller); PyErr_SetString(PyExc_TypeError, Msgbuf); return 0; } *chartStyle = (int) PyInt_AsLong(arg); // Image dimensions: (int, int). arg = PyTuple_GetItem(args, 1); if (!PySequence_Check(arg) || PyObject_Length(arg) != 2) { sprintf(Msgbuf, "%s, argument 2: expected 2-tuple", caller); PyErr_SetString(PyExc_TypeError, Msgbuf); return 0; } width = PySequence_GetItem(arg, 0); height = PySequence_GetItem(arg, 1); Py_DECREF(width); Py_DECREF(height); if (!PyInt_Check(width) || !PyInt_Check(height)) { sprintf(Msgbuf, "%s, argument 3: expected (int,int)", caller); PyErr_SetString(PyExc_TypeError, Msgbuf); return 0; } *imgWidth = (int) PyInt_AsLong(width); *imgHeight = (int) PyInt_AsLong(height); if (*imgWidth < 0 || *imgHeight < 0) { SetValueError(caller, "image dimensions"); return 0; } // File: file, cStringIO, or string (=filename) object. *stringIO = NULL; arg = PyTuple_GetItem(args, 2); if (PyFile_Check(arg)) { *file = PyFile_AsFile(arg); *closeFile = 0; } else if (PycStringIO != NULL && PycStringIO_OutputCheck(arg)) { *file = tmpfile(); *closeFile = 1; *stringIO = arg; } else if (PyString_Check(arg)) { filename = PyString_AsString(arg); *file = fopen(filename, "wb"); if (*file == NULL) { sprintf(Msgbuf, "%s: can't open %s for writing", caller, filename); PyErr_SetString(PyExc_TypeError, Msgbuf); return 0; } *closeFile = 1; } else { if (PycStringIO == NULL) { sprintf(Msgbuf, "%s, argument 3: expected file or string", caller); } else { sprintf(Msgbuf, "%s, argument 3: expected file, string, or cStringIO", caller); } PyErr_SetString(PyExc_TypeError, Msgbuf); return 0; } // Labels: (string, ...). arg = PyTuple_GetItem(args, 3); if (!PySequence_Check(arg) || PyString_Check(arg)) { sprintf(Msgbuf, "%s, argument 4: expected sequence of strings", caller); PyErr_SetString(PyExc_TypeError, Msgbuf); return 0; } // The label count must equal the number of points in each data set, so // just store this value in numPoints. *numPoints = PyObject_Length(arg); *labels = (char **) PyMem_Malloc((*numPoints + 1) * sizeof(char **)); if (*labels == NULL) { PyErr_NoMemory(); return 0; } memset(*labels, 0, (*numPoints + 1) * sizeof(char **)); for (i = 0; i < *numPoints; i++) { label = PySequence_GetItem(arg, i); // It's safe to decrement the refcount immediately, since this object is // part of a sequence object, which also owns a reference to it. Py_DECREF(label); if (PyString_Check(label)) { (*labels)[i] = PyString_AsString(label); } else { // Found an invalid label. Clean up and return failure. PyMem_Free(*labels); *labels = NULL; sprintf(Msgbuf, "%s, argument 4: expected sequence of strings", caller); PyErr_SetString(PyExc_TypeError, Msgbuf); return 0; } } // Note: caller is responsible for freeing the labels array when this // function succeeds! return 1; } // Retrieve a data set from a Python object. void _parse_data_set(PyObject *pyseq, char *caller, int numPoints, float *data) { int i; PyObject *value; if (!PySequence_Check(pyseq)) { sprintf(Msgbuf, "%s: expected sequence", caller); PyErr_SetString(PyExc_TypeError, Msgbuf); return; } if (PyObject_Length(pyseq) != numPoints) { sprintf(Msgbuf, "%s: mismatched data sets", caller); PyErr_SetString(PyExc_TypeError, Msgbuf); return; } for (i = 0; i < numPoints; i++) { value = PySequence_GetItem(pyseq, i); if (value == Py_None) { data[i] = GDC_NOVALUE; } else { data[i] = (float) PyFloat_AsDouble(value); } Py_DECREF(value); } } // Retrieve n data sets from a Python object. void _parse_data_sets(PyObject *pyseq, char *caller, int numSets, int numPoints, float *data) { int i; if (!PySequence_Check(pyseq) || PyObject_Length(pyseq) != numSets) { sprintf(Msgbuf, "%s: mismatched data sets", caller); PyErr_SetString(PyExc_TypeError, Msgbuf); return; } for (i = 0; i < numSets; i++) { PyObject *dataset = PySequence_GetItem(pyseq, i); Py_DECREF(dataset); _parse_data_set(dataset, caller, numPoints, &data[numPoints * i]); } } // Module function chart(style, (w, h), file, labels, data...) static PyObject * gdc_chart(PyObject *self, PyObject *args) { int argc; int chartStyle; int imgWidth, imgHeight; FILE *file; char **labels; int setSize; int numDataArgs, minDatasets = 1, maxDatasets = -1; int hiloclose = 0, combo = 0, floatingbar = 0; int arrayCount = 1; float *data; int argidx, setidx, i; int closeFile; PyObject *stringIO; argc = PyTuple_Size(args); if (argc < 5) { sprintf(Msgbuf, "chart requires at least 5 arguments; %d given", argc); PyErr_SetString(PyExc_TypeError, Msgbuf); return NULL; } if (!_parse_common_args(args, "chart", &chartStyle, &imgWidth, &imgHeight, &file, &stringIO, &labels, &setSize, &closeFile)) { return NULL; } // Set parameters based on chart type. numDataArgs = argc - 4; if (chartStyle == GDC_LINE || chartStyle == GDC_3DLINE || chartStyle == GDC_AREA || chartStyle == GDC_3DAREA || chartStyle == GDC_BAR || chartStyle == GDC_3DBAR) { arrayCount = numDataArgs; } else if (chartStyle == GDC_FLOATINGBAR || chartStyle == GDC_3DFLOATINGBAR) { floatingbar = 1; arrayCount = 2 * numDataArgs; } else if (chartStyle == GDC_COMBO_LINE_AREA || chartStyle == GDC_COMBO_LINE_BAR || chartStyle == GDC_COMBO_LINE_LINE || chartStyle == GDC_3DCOMBO_LINE_AREA || chartStyle == GDC_3DCOMBO_LINE_BAR || chartStyle == GDC_3DCOMBO_LINE_LINE) { minDatasets = 2; combo = 1; arrayCount = numDataArgs; } else if (chartStyle == GDC_HILOCLOSE || chartStyle == GDC_3DHILOCLOSE) { hiloclose = 1; arrayCount = 3 * numDataArgs; } else if (chartStyle == GDC_COMBO_HLC_AREA || chartStyle == GDC_COMBO_HLC_BAR || chartStyle == GDC_3DCOMBO_HLC_AREA || chartStyle == GDC_3DCOMBO_HLC_BAR) { minDatasets = 2; hiloclose = 1; combo = 1; arrayCount = 3 * (numDataArgs - 1) + 1; } else if (chartStyle == MY_GDC_2DPIE || chartStyle == MY_GDC_3DPIE) { // For pie charts, the second data set (if any) is a sequence of // values indicating missing data points (0 == missing). maxDatasets = 2; arrayCount = numDataArgs; } // Check number of data sets. if (numDataArgs < minDatasets) { PyErr_SetString(PyExc_TypeError, "chart: more data expected"); return NULL; } if (maxDatasets > 0 && numDataArgs > maxDatasets) { PyErr_SetString(PyExc_TypeError, "chart: less data expected"); return NULL; } // Allocate space for formatted data. data = PyMem_Malloc(arrayCount * setSize * sizeof(float)); if (data == NULL) { PyErr_NoMemory(); return NULL; } // Format data for calls to GDChart. setidx = 0; argidx = 4; while (!PyErr_Occurred() && argidx < argc) { PyObject *dataset = PyTuple_GetItem(args, argidx); if (floatingbar) { _parse_data_sets(dataset, "chart", 2, setSize, &data[setSize * setidx]); setidx += 2; } else if (hiloclose && (!combo || argidx < argc - 1)) { // Get a (hi, lo, close) data set. _parse_data_sets(dataset, "chart", 3, setSize, &data[setSize * setidx]); setidx += 3; } else { // Get a normal data set. _parse_data_set(dataset, "chart", setSize, &data[setSize * setidx]); setidx++; } argidx++; } // Call GDChart. if (!PyErr_Occurred()) { if (chartStyle == MY_GDC_2DPIE || chartStyle == MY_GDC_3DPIE) { // Scale data so it sums to 100. float scale, sum = 0.0; for (i = 0; i < setSize; i++) { sum += data[i]; } scale = 100.0 / sum; for (i = 0; i < setSize; i++) { data[i] *= scale; } // If a second data set was provided, it indicates what values // are missing (0 == missing). if (numDataArgs == 2) { GDCPIE_missing = PyMem_Malloc(setSize * sizeof(unsigned char)); if (GDCPIE_missing == NULL) { PyErr_NoMemory(); return NULL; } for (i = 0; i < setSize; i++) { GDCPIE_missing[i] = (unsigned char) (data[setSize + i] == 0.0 || data[setSize + i] == GDC_NOVALUE) ? TRUE : FALSE; } } chartStyle = (chartStyle == MY_GDC_2DPIE) ? GDC_2DPIE : GDC_3DPIE; GDC_out_pie(imgWidth, imgHeight, file, chartStyle, setSize, labels, data); if (numDataArgs == 2) { PyMem_Free(GDCPIE_missing); GDCPIE_missing = NULL; } } else { float *comboData = NULL; if (combo) { comboData = &data[setSize * (arrayCount - 1)]; } GDC_out_graph(imgWidth, imgHeight, file, chartStyle, setSize, labels, numDataArgs - combo, data, comboData); } } // Clean up. if (!PyErr_Occurred() && stringIO != NULL) { size_t n; void *buf = malloc(1024); fseek(file, 0, SEEK_SET); do { n = fread(buf, 1, 1024, file); PycStringIO->cwrite(stringIO, (char *)buf, n); } while (n == 1024); } if (closeFile) { fclose(file); } PyMem_Free(data); PyMem_Free(labels); if (PyErr_Occurred()) { return NULL; } else { Py_INCREF(Py_None); return Py_None; } } // Handle 'special' options. static int _handle_special_option(char *keyword, PyObject *value) { // annotation if (strcmp(keyword, "annotation") == 0) { int len; void *mem = NULL; if (value == Py_None) { len = 0; } else { if (!PySequence_Check(value) || ((len = PySequence_Length(value)) != 0 && len != 3)) { SetTypeError("option", keyword); return 0; } } if (len == 3) { GDC_ANNOTATION_T *ann; PyObject *pointObj = PySequence_GetItem(value, 0); PyObject *colorObj = PySequence_GetItem(value, 1); PyObject *noteObj = PySequence_GetItem(value, 2); if (PyNumber_Check(pointObj) && PyNumber_Check(colorObj) && PyString_Check(noteObj)) { mem = PyMem_Malloc(sizeof(GDC_ANNOTATION_T)); ann = (GDC_ANNOTATION_T *)mem; ann->point = (float)PyFloat_AsDouble(pointObj); ann->color = PyInt_AsLong(colorObj); strncpy(ann->note, PyString_AsString(noteObj), MAX_NOTE_LEN); ann->note[MAX_NOTE_LEN] = '\0'; } else { SetTypeError("option", keyword); } Py_DECREF(pointObj); Py_DECREF(colorObj); Py_DECREF(noteObj); } if (PyErr_Occurred()) { return 0; } if (GDC_annotation != NULL) { PyMem_Free(GDC_annotation); } GDC_annotation = mem; Annotation = mem; return 1; } // border else if (strcmp(keyword, "border") == 0) { int x = (int) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } if (x < 0 || x > 31) { SetValueError("option", keyword); return 0; } GDC_border = x; return 1; } // format else if (strcmp(keyword, "format") == 0) { if (PySequence_Check(value)) { PyObject *formatObj; int format; #ifdef HAVE_JPEG PyObject *qualityObj; int quality; #endif int size = PyObject_Length(value); if (size != 2) { SetValueError("option", keyword); return 0; } formatObj = PySequence_GetItem(value, 0); format = (int) PyInt_AsLong(formatObj); Py_DECREF(formatObj); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } if (format != GDC_JPEG) { SetValueError("option", keyword); return 0; } #ifdef HAVE_JPEG qualityObj = PySequence_GetItem(value, 1); quality = (int) PyInt_AsLong(qualityObj); Py_DECREF(qualityObj); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } GDC_image_type = format; GDC_jpeg_quality = quality; return 1; #else PyErr_SetString(GDChartError, "option: module was built without JPEG support"); return 0; #endif } else { int format = (int) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } #ifndef HAVE_JPEG if (format == GDC_JPEG) { PyErr_SetString(GDChartError, "option: module was built without JPEG support"); return 0; } #endif if (format != GDC_PNG && format != GDC_JPEG && format != GDC_GIF && format != GDC_WBMP) { SetValueError("option", keyword); return 0; } GDC_image_type = format; if (format == GDC_JPEG) { GDC_jpeg_quality = -1; // default } return 1; } } // grid and ticks (same constraints) else if (strcmp(keyword, "grid") == 0 || strcmp(keyword, "ticks") == 0) { int x = (int) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } if (x < GDC_TICK_LABELS) { SetValueError("option", keyword); return 0; } if (keyword[0] == 'g') { GDC_grid = x; } else { GDC_ticks = x; } return 1; } // hlc_style else if (strcmp(keyword, "hlc_style") == 0) { int x = (int) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } if (x < 1 || x > 15 || (x & 6) == 6) { SetValueError("option", keyword); return 0; } GDC_HLC_style = x; return 1; } // hold_img else if (strcmp(keyword, "hold_img") == 0) { int x = (int) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } if (x < GDC_DESTROY_IMAGE || x > GDC_REUSE_IMAGE) { SetValueError("option", keyword); return 0; } GDC_hold_img = x; return 1; } // other_threshold else if (strcmp(keyword, "other_threshold") == 0) { char x; if (value == Py_None) { GDCPIE_other_threshold = -1; return 1; } x = (char) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } if (x < 0 || x > 100) { SetValueError("option", keyword); return 0; } GDCPIE_other_threshold = x; return 1; } // percent_labels else if (strcmp(keyword, "percent_labels") == 0) { int x = (int) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } if (x < GDCPIE_PCT_NONE || x > GDCPIE_PCT_LEFT) { SetValueError("option", keyword); return 0; } GDCPIE_percent_labels = x; return 1; } // scatter else if (strcmp(keyword, "scatter") == 0) { int i; int len; void *mem; GDC_SCATTER_T *scatter; if (value == Py_None) { len = 0; mem = NULL; } else { if (!PySequence_Check(value)) { SetTypeError("option", keyword); return 0; } len = PySequence_Length(value); mem = PyMem_Malloc(len * sizeof(GDC_SCATTER_T)); } for (i = 0, scatter = (GDC_SCATTER_T *)mem; i < len; i++, scatter++) { PyObject *x, *y, *width, *color, *style; PyObject *seq = PySequence_GetItem(value, i); Py_DECREF(seq); if (!PySequence_Check(seq) || PySequence_Length(seq) != 5) { SetTypeError("option", keyword); break; } x = PySequence_GetItem(seq, 0); y = PySequence_GetItem(seq, 1); width = PySequence_GetItem(seq, 2); color = PySequence_GetItem(seq, 3); style = PySequence_GetItem(seq, 4); Py_DECREF(x); Py_DECREF(y); Py_DECREF(width); Py_DECREF(color); Py_DECREF(style); if (PyNumber_Check(x) && PyNumber_Check(y) && PyNumber_Check(width) && PyNumber_Check(color) && PyNumber_Check(style)) { scatter->point = (float) PyFloat_AsDouble(x); scatter->val = (float) PyFloat_AsDouble(y); scatter->width = (unsigned short) PyInt_AsLong(width); scatter->color = (unsigned long) PyInt_AsLong(color); scatter->ind = (GDC_SCATTER_IND_T) PyInt_AsLong(style); if (scatter->width < 1 || 100 < scatter->width || scatter->ind < GDC_SCATTER_TRIANGLE_DOWN || GDC_SCATTER_CIRCLE < scatter->ind) { SetValueError("option", keyword); break; } } else { SetTypeError("option", keyword); break; } } if (PyErr_Occurred()) { if (mem != NULL) { PyMem_Free(mem); } return 0; } if (GDC_scatter != NULL) { PyMem_Free(GDC_scatter); } GDC_scatter = mem; Scatter = mem; GDC_num_scatter_pts = len; return 1; } // stack_type else if (strcmp(keyword, "stack_type") == 0) { int x = (int) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } if (x < GDC_STACK_DEPTH || x > GDC_STACK_LAYER) { SetValueError("option", keyword); return 0; } GDC_stack_type = x; return 1; } // threed_angle else if (strcmp(keyword, "threed_angle") == 0) { unsigned short x = (unsigned short) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } if (x > 359) { SetValueError("option", keyword); return 0; } GDC_3d_angle = (unsigned char) x; GDCPIE_3d_angle = x; return 1; } // threed_depth else if (strcmp(keyword, "threed_depth") == 0) { float x = (float) PyFloat_AsDouble(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } if (x < 0.0 || x > 100.0) { SetValueError("option", keyword); return 0; } GDC_3d_depth = x; GDCPIE_3d_depth = (unsigned short) x; return 1; } // xlabel_spacing else if (strcmp(keyword, "xlabel_spacing") == 0) { short x; if (value == Py_None) { GDC_xlabel_spacing = MAXSHORT; return 1; } x = (short) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return 0; } if (x < 0) { SetValueError("option", keyword); return 0; } GDC_xlabel_spacing = x; return 1; } // Oops! else { PyErr_SetString(GDChartError, "something is horribly wrong in gdchart"); return 0; } } // Make a dictionary of current option values -- helper for module funciton // option(keyword=value, ...) static PyObject * option_dict() { // Chui Tey 05-22-2000 // Updated by MS 10-09-2000 struct option *opt = Options; PyObject *dict = PyDict_New(); if (dict == NULL) { return NULL; } while (opt->keyword != NULL) { PyObject *key; PyObject *value; switch (opt->type) { case opt_bool: case opt_percent: { char *p = (opt->chartvar != NULL) ? opt->chartvar : opt->pievar; if (p != NULL) { key = PyString_FromString(opt->keyword); value = Py_BuildValue("i", *p); PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } break; } case opt_float: { float *p = (opt->chartvar != NULL) ? opt->chartvar : opt->pievar; if (p != NULL) { key = PyString_FromString(opt->keyword); if (*p == GDC_NOVALUE) { Py_INCREF(Py_None); value = Py_None; } else { value = Py_BuildValue("f", *p); } PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } break; } case opt_font: { enum GDC_font_size *p = (opt->chartvar != NULL) ? opt->chartvar : opt->pievar; if (p != NULL) { key = PyString_FromString(opt->keyword); value = Py_BuildValue("i", *p); PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } break; } case opt_int: case opt_long: { int *p = (opt->chartvar != NULL) ? opt->chartvar : opt->pievar; if (p != NULL) { key = PyString_FromString(opt->keyword); value = Py_BuildValue("i", *p); PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } break; } case opt_int_a: case opt_long_a: { int **p = (opt->chartvar != NULL) ? opt->chartvar : opt->pievar; if (p != NULL) { int i; key = PyString_FromString(opt->keyword); value = PyTuple_New(opt->size); for (i = 0; i < opt->size; i++) { PyTuple_SetItem(value, i, Py_BuildValue("i", (*p)[i])); } PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } break; } case opt_bool_a: { char **p = (opt->chartvar != NULL) ? opt->chartvar : opt->pievar; if (p != NULL) { int i; key = PyString_FromString(opt->keyword); value = PyTuple_New(opt->size); for (i = 0; i < opt->size; i++) { PyTuple_SetItem(value, i, Py_BuildValue("i", (*p)[i])); } PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } break; } case opt_special: { if (strcmp(opt->keyword, "scatter") == 0) { key = PyString_FromString(opt->keyword); if (GDC_scatter == NULL) { Py_INCREF(Py_None); value = Py_None; } else { int i; value = PyTuple_New(GDC_num_scatter_pts); for (i = 0; i < GDC_num_scatter_pts; i++) { PyObject *s = PyTuple_New(5); PyTuple_SetItem(s, 0, Py_BuildValue("f", GDC_scatter[i].point)); PyTuple_SetItem(s, 1, Py_BuildValue("f", GDC_scatter[i].val)); PyTuple_SetItem(s, 2, Py_BuildValue("i", GDC_scatter[i].width)); PyTuple_SetItem(s, 3, Py_BuildValue("i", GDC_scatter[i].color)); PyTuple_SetItem(s, 4, Py_BuildValue("i", GDC_scatter[i].ind)); PyTuple_SetItem(value, i, s); } } PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } else if (strcmp(opt->keyword, "annotation") == 0) { key = PyString_FromString(opt->keyword); if (GDC_annotation == NULL) { Py_INCREF(Py_None); value = Py_None; } else { value = PyTuple_New(3); PyTuple_SetItem(value, 0, Py_BuildValue("f", GDC_annotation->point)); PyTuple_SetItem(value, 1, Py_BuildValue("i", GDC_annotation->color)); PyTuple_SetItem(value, 2, Py_BuildValue("s", GDC_annotation->note)); } PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } else if (strcmp(opt->keyword, "format") == 0) { key = PyString_FromString(opt->keyword); if (GDC_image_type == GDC_JPEG && GDC_jpeg_quality != -1) { value = PyTuple_New(2); PyTuple_SetItem(value, 0, Py_BuildValue("i", GDC_image_type)); PyTuple_SetItem(value, 1, Py_BuildValue("i", GDC_jpeg_quality)); } else { value = Py_BuildValue("i", GDC_image_type); } PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } else if (strcmp(opt->keyword, "border") == 0 || strcmp(opt->keyword, "grid") == 0 || strcmp(opt->keyword, "hlc_style") == 0 || strcmp(opt->keyword, "hold_img") == 0 || strcmp(opt->keyword, "percent_labels") == 0 || strcmp(opt->keyword, "stack_type") == 0 || strcmp(opt->keyword, "ticks") == 0) { int *p = (opt->chartvar != NULL) ? opt->chartvar : opt->pievar; key = PyString_FromString(opt->keyword); value = Py_BuildValue("i", *p); PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } else if (strcmp(opt->keyword, "other_threshold") == 0) { key = PyString_FromString(opt->keyword); if (GDCPIE_other_threshold == -1) { Py_INCREF(Py_None); value = Py_None; } else { value = Py_BuildValue("i", (int)GDCPIE_other_threshold); } PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } else if (strcmp(opt->keyword, "threed_angle") == 0) { key = PyString_FromString(opt->keyword); if (GDCPIE_3d_angle > 255) { value = Py_BuildValue("i", (int)GDCPIE_3d_angle); } else { value = Py_BuildValue("i", (int)GDC_3d_angle); } PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } else if (strcmp(opt->keyword, "threed_depth") == 0) { key = PyString_FromString(opt->keyword); value = Py_BuildValue("f", GDC_3d_depth); PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } else if (strcmp(opt->keyword, "xlabel_spacing") == 0) { key = PyString_FromString(opt->keyword); if (GDC_xlabel_spacing == MAXSHORT) { Py_INCREF(Py_None); value = Py_None; } else { value = Py_BuildValue("i", (int)GDC_xlabel_spacing); } PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } break; } case opt_string: { unsigned char **p = (opt->chartvar != NULL) ? opt->chartvar : opt->pievar; if (p != NULL) { key = PyString_FromString(opt->keyword); value = Py_BuildValue("s", *p); PyDict_SetItem(dict, key, value); Py_DECREF(key); Py_DECREF(value); } break; } } // switch opt++; } // while return dict; } // Module function option(keyword=value, ...) static PyObject * gdc_option(PyObject *self, PyObject *args, PyObject *keywordDict) { int pos; PyObject *key; PyObject *value; // If there are any non-keyword arguments, report an error. if (args != NULL && PyObject_Length(args) > 0) { PyObject_Print(args, stdout, 0); PyErr_SetString(GDChartError, "option: only keyword arguments allowed"); return NULL; } // Return a dict of current option values when no args are passed. if (keywordDict == NULL || PyDict_Size(keywordDict) == 0) { return option_dict(); } // Process keyword arguments. pos = 0; while (PyDict_Next(keywordDict, &pos, &key, &value)) { struct option *opt = Options; char *keyword = PyString_AsString(key); while (opt->keyword != NULL) { if (strcmp(opt->keyword, keyword) == 0) { break; } opt++; } if (opt->keyword == NULL) { sprintf(Msgbuf, "option: unexpected keyword argument: %s", keyword); PyErr_SetString(GDChartError, Msgbuf); return NULL; } switch (opt->type) { case opt_bool: case opt_percent: { char x = (char) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return NULL; } if (opt->type == opt_bool) { x = (x != 0) ? 1 : 0; } else if (opt->type == opt_percent && (x < 0 || x > 100)) { SetValueError("option", keyword); return NULL; } if (opt->chartvar != NULL) { *((char *) opt->chartvar) = x; } if (opt->pievar != NULL) { *((char *) opt->pievar) = x; } break; } case opt_float: { // Chui Tey: None resets float options to their default values. float x; if (value == Py_None) { x = GDC_NOVALUE; } else { x = (float) PyFloat_AsDouble(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return NULL; } } if (opt->chartvar != NULL) { *((float *) opt->chartvar) = x; } if (opt->pievar != NULL) { *((float *) opt->pievar) = x; } break; } case opt_font: { enum GDC_font_size x = (enum GDC_font_size) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return NULL; } if (x < GDC_pad || x >= GDC_numfonts) { SetValueError("option", keyword); return NULL; } if (opt->chartvar != NULL) { *((enum GDC_font_size *) opt->chartvar) = x; } if (opt->pievar != NULL) { *((enum GDC_font_size *) opt->pievar) = x; } break; } case opt_int: case opt_long: assert(sizeof(int) == sizeof(long)); { int x = (int) PyInt_AsLong(value); if (PyErr_Occurred()) { SetTypeError("option", keyword); return NULL; } if (opt->chartvar != NULL) { *((int *) opt->chartvar) = x; } if (opt->pievar != NULL) { *((int *) opt->pievar) = x; } break; } case opt_int_a: case opt_long_a: assert(sizeof(int) == sizeof(long)); { int size; int *vals = NULL; if (value == Py_None) { size = 0; } else { if (!PySequence_Check(value)) { SetTypeError("option", keyword); return NULL; } size = PyObject_Length(value); } if (size > 0) { int i; vals = PyMem_Malloc(size * sizeof(int)); if (vals == NULL) { PyErr_NoMemory(); return NULL; } for (i = 0; i < size; i++) { PyObject *element = PySequence_GetItem(value, i); int x = PyInt_AsLong(element); Py_DECREF(element); vals[i] = x; } if (PyErr_Occurred()) { SetTypeError("option", keyword); return NULL; } } if (opt->chartvar != NULL) { *((int **) opt->chartvar) = vals; } if (opt->pievar != NULL) { *((int **) opt->pievar) = vals; } if (*opt->cache != NULL) { PyMem_Free(*opt->cache); } *opt->cache = vals; opt->size = size; break; } case opt_bool_a: { int size; char *vals = NULL; if (value == Py_None) { size = 0; } else { if (!PySequence_Check(value)) { SetTypeError("option", keyword); return NULL; } size = PyObject_Length(value); } if (size > 0) { int i; vals = PyMem_Malloc(size * sizeof(char)); if (vals == NULL) { PyErr_NoMemory(); return NULL; } for (i = 0; i < size; i++) { PyObject *element = PySequence_GetItem(value, i); char x = (char) PyInt_AsLong(element); Py_DECREF(element); vals[i] = x; } if (PyErr_Occurred()) { SetTypeError("option", keyword); return NULL; } } if (opt->chartvar != NULL) { *((int **) opt->chartvar) = vals; } if (opt->pievar != NULL) { *((int **) opt->pievar) = vals; } if (*opt->cache != NULL) { PyMem_Free(*opt->cache); } *opt->cache = vals; opt->size = size; break; } case opt_special: if (!_handle_special_option(keyword, value)) { return NULL; } break; case opt_string: { int len; char *val = NULL; if (value == Py_None) { len = 0; } else { if (!PyString_Check(value)) { SetTypeError("option", keyword); return NULL; } len = PyString_Size(value); } if (len > 0) { val = strdup(PyString_AsString(value)); } if (opt->chartvar != NULL) { *((unsigned char **) opt->chartvar) = val; } if (opt->pievar != NULL) { *((unsigned char **) opt->pievar) = val; } if (*opt->cache != NULL) { PyMem_Free(*opt->cache); } *opt->cache = val; break; } default: PyErr_SetString(GDChartError, "something is horribly wrong in gdchart"); return NULL; //break; } } Py_INCREF(Py_None); return Py_None; } // Export an integer value. static void _export_int(PyObject *dict, char *name, int value) { PyObject *x = PyInt_FromLong((long) value); if (x == NULL || PyDict_SetItemString(dict, name, x) != 0) { PyErr_Clear(); } Py_XDECREF(x); } // Export a float value. static void _export_float(PyObject *dict, char *name, float value) { PyObject *x = PyFloat_FromDouble((double) value); if (x == NULL || PyDict_SetItemString(dict, name, x) != 0) { PyErr_Clear(); } Py_XDECREF(x); } // Initialize the module. void initgdchart() { static PyMethodDef methods[] = { { "chart", gdc_chart, METH_VARARGS, ChartDoc }, { "option", (PyCFunction) gdc_option, METH_KEYWORDS, OptionDoc }, { NULL, NULL } }; PyObject *module; PyObject *dict; module = Py_InitModule4("gdchart", methods, ModuleDoc, NULL, PYTHON_API_VERSION); dict = PyModule_GetDict(module); // Create module-level exception. GDChartError = PyErr_NewException("gdchart.error", NULL, NULL); PyDict_SetItemString(dict, "error", GDChartError); // Export GDChart constants. // Image formats: _export_int(dict, "GDC_PNG", GDC_PNG); _export_int(dict, "GDC_JPEG", GDC_JPEG); _export_int(dict, "GDC_GIF", GDC_GIF); _export_int(dict, "GDC_WBMP", GDC_WBMP); // Chart styles (including pie): _export_int(dict, "GDC_LINE", GDC_LINE); _export_int(dict, "GDC_AREA", GDC_AREA); _export_int(dict, "GDC_BAR", GDC_BAR); _export_int(dict, "GDC_FLOATINGBAR", GDC_FLOATINGBAR); _export_int(dict, "GDC_HILOCLOSE", GDC_HILOCLOSE); _export_int(dict, "GDC_COMBO_LINE_BAR", GDC_COMBO_LINE_BAR); _export_int(dict, "GDC_COMBO_HLC_BAR", GDC_COMBO_HLC_BAR); _export_int(dict, "GDC_COMBO_LINE_AREA", GDC_COMBO_LINE_AREA); _export_int(dict, "GDC_COMBO_LINE_LINE", GDC_COMBO_LINE_LINE); _export_int(dict, "GDC_COMBO_HLC_AREA", GDC_COMBO_HLC_AREA); _export_int(dict, "GDC_3DHILOCLOSE", GDC_3DHILOCLOSE); _export_int(dict, "GDC_3DCOMBO_LINE_BAR", GDC_3DCOMBO_LINE_BAR); _export_int(dict, "GDC_3DCOMBO_LINE_AREA", GDC_3DCOMBO_LINE_AREA); _export_int(dict, "GDC_3DCOMBO_LINE_LINE", GDC_3DCOMBO_LINE_LINE); _export_int(dict, "GDC_3DCOMBO_HLC_BAR", GDC_3DCOMBO_HLC_BAR); _export_int(dict, "GDC_3DCOMBO_HLC_AREA", GDC_3DCOMBO_HLC_AREA); _export_int(dict, "GDC_3DBAR", GDC_3DBAR); _export_int(dict, "GDC_3DFLOATINGBAR", GDC_3DFLOATINGBAR); _export_int(dict, "GDC_3DAREA", GDC_3DAREA); _export_int(dict, "GDC_3DLINE", GDC_3DLINE); _export_int(dict, "GDC_3DPIE", MY_GDC_3DPIE); _export_int(dict, "GDC_2DPIE", MY_GDC_2DPIE); // Fonts: _export_int(dict, "GDC_TINY", GDC_TINY); _export_int(dict, "GDC_SMALL", GDC_SMALL); _export_int(dict, "GDC_MEDBOLD", GDC_MEDBOLD); _export_int(dict, "GDC_LARGE", GDC_LARGE); _export_int(dict, "GDC_GIANT", GDC_GIANT); // Stack options: _export_int(dict, "GDC_STACK_DEPTH", GDC_STACK_DEPTH); _export_int(dict, "GDC_STACK_SUM", GDC_STACK_SUM); _export_int(dict, "GDC_STACK_BESIDE", GDC_STACK_BESIDE); _export_int(dict, "GDC_STACK_LAYER", GDC_STACK_LAYER); // Hi-lo-close styles: _export_int(dict, "GDC_HLC_DIAMOND", GDC_HLC_DIAMOND); _export_int(dict, "GDC_HLC_CLOSE_CONNECTED", GDC_HLC_CLOSE_CONNECTED); _export_int(dict, "GDC_HLC_CONNECTING", GDC_HLC_CONNECTING); _export_int(dict, "GDC_HLC_I_CAP", GDC_HLC_I_CAP); // Scatter point styles: _export_int(dict, "GDC_SCATTER_TRIANGLE_DOWN", GDC_SCATTER_TRIANGLE_DOWN); _export_int(dict, "GDC_SCATTER_TRIANGLE_UP", GDC_SCATTER_TRIANGLE_UP); _export_int(dict, "GDC_SCATTER_CIRCLE", GDC_SCATTER_CIRCLE); // Percent placement (pie charts): _export_int(dict, "GDCPIE_PCT_NONE", GDCPIE_PCT_NONE); _export_int(dict, "GDCPIE_PCT_ABOVE", GDCPIE_PCT_ABOVE); _export_int(dict, "GDCPIE_PCT_BELOW", GDCPIE_PCT_BELOW); _export_int(dict, "GDCPIE_PCT_RIGHT", GDCPIE_PCT_RIGHT); _export_int(dict, "GDCPIE_PCT_LEFT", GDCPIE_PCT_LEFT); // Border styles: _export_int(dict, "GDC_BORDER_NONE", GDC_BORDER_NONE); _export_int(dict, "GDC_BORDER_ALL", GDC_BORDER_ALL); _export_int(dict, "GDC_BORDER_X", GDC_BORDER_X); _export_int(dict, "GDC_BORDER_Y", GDC_BORDER_Y); _export_int(dict, "GDC_BORDER_Y2", GDC_BORDER_Y2); _export_int(dict, "GDC_BORDER_TOP", GDC_BORDER_TOP); // Tick styles: _export_int(dict, "GDC_TICK_LABELS", GDC_TICK_LABELS); _export_int(dict, "GDC_TICK_POINTS", GDC_TICK_POINTS); _export_int(dict, "GDC_TICK_NONE", GDC_TICK_NONE); // Other magic: _export_float(dict, "GDC_INTERP_VALUE", GDC_INTERP_VALUE); // Get cStringIO module if it is available: reference is in PycStringIO. PycString_IMPORT; Py_AtExit(_cleanup); if (PyErr_Occurred()) { Py_FatalError("can't initialize module gdchart"); } } /* vim: set sw=4 sts=4 ts=8 noet */