summaryrefslogtreecommitdiff
path: root/src/cd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cd.c')
-rw-r--r--src/cd.c748
1 files changed, 748 insertions, 0 deletions
diff --git a/src/cd.c b/src/cd.c
new file mode 100644
index 0000000..536f7ef
--- /dev/null
+++ b/src/cd.c
@@ -0,0 +1,748 @@
+/** \file
+ * \brief External API
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <memory.h>
+#include <stdarg.h>
+
+
+#include "cd.h"
+#include "wd.h"
+#include "cd_private.h"
+#include "cdirgb.h"
+
+
+const char cd_ident[] =
+ "$CD: " CD_VERSION " " CD_COPYRIGHT " $\n"
+ "$URL: www.tecgraf.puc-rio.br/cd $\n";
+
+static char *tecver = "TECVERID.str:CD:LIB:"CD_VERSION;
+
+char* cdVersion(void)
+{
+ (void)cd_ident;
+ (void)tecver;
+ return CD_VERSION;
+}
+
+char* cdVersionDate(void)
+{
+ return CD_VERSION_DATE;
+}
+
+int cdVersionNumber(void)
+{
+ return CD_VERSION_NUMBER;
+}
+
+static void cd_setdefaultfunc(cdCanvas* canvas)
+{
+ /* default simulation functions */
+ canvas->cxGetTextSize = cdgettextsizeEX;
+ canvas->cxGetFontDim = cdgetfontdimEX;
+ canvas->cxRect = cdrectSIM;
+}
+
+static void cd_setdefaultattrib(cdCanvas* canvas)
+{
+ /* clipping attributes */
+ canvas->clip_mode = CD_CLIPOFF;
+
+ /* color attributes */
+ canvas->foreground = CD_BLACK;
+ canvas->background = CD_WHITE;
+
+ canvas->back_opacity = CD_TRANSPARENT;
+ canvas->write_mode = CD_REPLACE;
+
+ /* primitive attributes */
+ canvas->mark_type = CD_STAR;
+ canvas->mark_size = 10;
+
+ canvas->line_width = 1;
+ canvas->line_style = CD_CONTINUOUS;
+ canvas->line_cap = CD_CAPFLAT;
+ canvas->line_join = CD_MITER;
+
+ canvas->hatch_style = CD_HORIZONTAL;
+ canvas->interior_style = CD_SOLID;
+ canvas->fill_mode = CD_EVENODD;
+
+ strcpy(canvas->font_type_face, "System");
+ canvas->font_style = CD_PLAIN;
+ canvas->font_size = CD_STANDARD;
+
+ canvas->text_alignment = CD_BASE_LEFT;
+
+ canvas->matrix[0] = 1; /* identity */
+ canvas->matrix[3] = 1;
+
+ /* o resto recebeu zero no memset */
+}
+
+static void cd_updatedefaultattrib(cdCanvas* canvas)
+{
+ cdCanvasActivate(canvas);
+
+ if (canvas->cxBackground) canvas->cxBackground(canvas->ctxcanvas, canvas->background);
+ if (canvas->cxForeground) canvas->cxForeground(canvas->ctxcanvas, canvas->foreground);
+ if (canvas->cxBackOpacity) canvas->cxBackOpacity(canvas->ctxcanvas, canvas->back_opacity);
+ if (canvas->cxWriteMode) canvas->cxWriteMode(canvas->ctxcanvas, canvas->write_mode);
+ if (canvas->cxLineStyle) canvas->cxLineStyle(canvas->ctxcanvas, canvas->line_style);
+ if (canvas->cxLineWidth) canvas->cxLineWidth(canvas->ctxcanvas, canvas->line_width);
+ if (canvas->cxLineCap) canvas->cxLineCap(canvas->ctxcanvas, canvas->line_cap);
+ if (canvas->cxLineJoin) canvas->cxLineJoin(canvas->ctxcanvas, canvas->line_join);
+ if (canvas->cxHatch) canvas->cxHatch(canvas->ctxcanvas, canvas->hatch_style);
+ if (canvas->cxInteriorStyle) canvas->cxInteriorStyle(canvas->ctxcanvas, canvas->interior_style);
+ if (canvas->cxFont) canvas->cxFont(canvas->ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
+ if (canvas->cxTextAlignment) canvas->cxTextAlignment(canvas->ctxcanvas, canvas->text_alignment);
+ if (canvas->cxTextOrientation) canvas->cxTextOrientation(canvas->ctxcanvas, canvas->text_orientation);
+}
+
+cdCanvas* cdCreateCanvasf(cdContext *context, const char* format, ...)
+{
+ char data[1024];
+ va_list arglist;
+ va_start(arglist, format);
+ vsprintf(data, format, arglist);
+
+ return cdCreateCanvas(context, data);
+}
+
+cdCanvas *cdCreateCanvas(cdContext* context, void *data_str)
+{
+ cdCanvas *canvas;
+
+ /* usefull for NULL drivers, that do nothing and exist only for portability */
+ if (!context)
+ return NULL;
+
+ {
+ static int first = 1;
+ char* env = getenv("CD_QUIET");
+ if (first && env && strcmp(env, "NO")==0)
+ {
+ printf("CD "CD_VERSION" "CD_COPYRIGHT"\n");
+ first = 0;
+ }
+ }
+
+ /* alocates and initialize everything with 0s */
+ canvas = (cdCanvas*)malloc(sizeof(cdCanvas));
+ memset(canvas, 0, sizeof(cdCanvas));
+
+ canvas->signature[0] = 'C';
+ canvas->signature[1] = 'D';
+
+ canvas->vector_font = cdCreateVectorFont(canvas);
+ canvas->simulation = cdCreateSimulation(canvas);
+
+ canvas->context = context;
+
+ /* initialize default attributes, must be before creating the canvas */
+ cd_setdefaultattrib(canvas);
+
+ context->cxCreateCanvas(canvas, data_str);
+ if (!canvas->ctxcanvas)
+ {
+ cdKillVectorFont(canvas->vector_font);
+ cdKillSimulation(canvas->simulation);
+ memset(canvas, 0, sizeof(cdCanvas));
+ free(canvas);
+ return NULL;
+ }
+
+ /* functions that can do nothing, must be before InitTable */
+ cd_setdefaultfunc(canvas);
+
+ /* initialize canvas table */
+ context->cxInitTable(canvas);
+
+ /* update the default atributes, must be after InitTable */
+ cd_updatedefaultattrib(canvas);
+
+ /* must be after creating the canvas, so that we know canvas width and height */
+ canvas->clip_rect.xmax = canvas->w-1;
+ canvas->clip_rect.ymax = canvas->h-1;
+
+ wdSetDefaults(canvas);
+
+ return canvas;
+}
+
+/* re-declared here to ignore CD_NO_OLD_INTERFACE definition */
+int cdActivate(cdCanvas* canvas);
+cdCanvas* cdActiveCanvas(void);
+
+void cdKillCanvas(cdCanvas *canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (canvas == cdActiveCanvas())
+ cdActivate(NULL);
+ else
+ cdCanvasDeactivate(canvas);
+
+ canvas->cxKillCanvas(canvas->ctxcanvas);
+
+ if (canvas->pattern) free(canvas->pattern);
+ if (canvas->stipple) free(canvas->stipple);
+ if (canvas->poly) free(canvas->poly);
+ if (canvas->clip_poly) free(canvas->clip_poly);
+ if (canvas->fpoly) free(canvas->fpoly);
+ if (canvas->clip_fpoly) free(canvas->clip_fpoly);
+ if (canvas->line_dashes) free(canvas->line_dashes);
+
+ cdKillVectorFont(canvas->vector_font);
+ cdKillSimulation(canvas->simulation);
+
+ memset(canvas, 0, sizeof(cdCanvas));
+ free(canvas);
+}
+
+cdContext* cdCanvasGetContext(cdCanvas *canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return NULL;
+ return canvas->context;
+}
+
+int cdCanvasActivate(cdCanvas *canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (!canvas->cxActivate) return CD_OK;
+
+ if (canvas->cxActivate(canvas->ctxcanvas) == CD_ERROR)
+ return CD_ERROR;
+
+ return CD_OK;
+}
+
+void cdCanvasDeactivate(cdCanvas *canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas) || !canvas->cxDeactivate) return;
+ canvas->cxDeactivate(canvas->ctxcanvas);
+}
+
+unsigned long cdContextCaps(cdContext *context)
+{
+ if (!context)
+ return (unsigned long)CD_ERROR;
+ return context->caps;
+}
+
+int cdCanvasSimulate(cdCanvas* canvas, int mode)
+{
+ int sim_mode;
+ cdContext* context;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ context = canvas->context;
+
+ sim_mode = canvas->sim_mode;
+ if (mode == CD_QUERY || cdCanvasGetContext(canvas) == CD_IMAGERGB)
+ return sim_mode;
+
+ cd_setdefaultfunc(canvas);
+ context->cxInitTable(canvas);
+
+ canvas->sim_mode = mode;
+ if (mode == CD_SIM_NONE)
+ return sim_mode;
+
+ /* when simulation is active must not set driver transform */
+ canvas->cxTransform = NULL;
+
+ if (mode & CD_SIM_LINE)
+ {
+ canvas->cxLine = cdlineSIM;
+ canvas->cxFLine = NULL;
+ }
+
+ if (mode & CD_SIM_RECT)
+ {
+ canvas->cxRect = cdrectSIM;
+ canvas->cxFRect = NULL;
+ }
+
+ if (mode & CD_SIM_BOX)
+ {
+ canvas->cxBox = cdboxSIM;
+ canvas->cxFBox = NULL;
+ }
+
+ if (mode & CD_SIM_ARC)
+ {
+ canvas->cxArc = cdarcSIM;
+ canvas->cxFArc = NULL;
+ }
+
+ if (mode & CD_SIM_SECTOR)
+ {
+ canvas->cxSector = cdsectorSIM;
+ canvas->cxFSector = NULL;
+ }
+
+ if (mode & CD_SIM_CHORD)
+ {
+ canvas->cxChord = cdchordSIM;
+ canvas->cxFChord = NULL;
+ }
+
+ if (mode & CD_SIM_TEXT)
+ {
+ canvas->cxText = cdtextSIM;
+ canvas->cxFText = NULL;
+ canvas->cxNativeFont = NULL;
+ canvas->cxFont = cdfontSIM;
+ canvas->cxGetFontDim = cdgetfontdimSIM;
+ canvas->cxGetTextSize = cdgettextsizeSIM;
+ canvas->cxTextOrientation = NULL;
+
+ cdSimInitText(canvas->simulation);
+ canvas->cxFont(canvas->ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
+ }
+ else
+ canvas->cxFont(canvas->ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
+
+ if (mode & CD_SIM_POLYLINE || mode & CD_SIM_POLYGON)
+ canvas->cxFPoly = NULL;
+
+ return sim_mode;
+}
+
+cdState* cdCanvasSaveState(cdCanvas* canvas)
+{
+ cdState* state;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return NULL;
+
+ state = (cdState*)malloc(sizeof(cdState));
+ memcpy(state, canvas, sizeof(cdCanvas));
+
+ if (state->pattern)
+ {
+ int size = state->pattern_w*state->pattern_h*sizeof(long);
+ state->pattern = (long*)malloc(size);
+ memcpy(state->pattern, canvas->pattern, size);
+ }
+
+ if (state->stipple)
+ {
+ int size = state->stipple_w*state->stipple_h;
+ state->stipple = (unsigned char*)malloc(size);
+ memcpy(state->stipple, canvas->stipple, size);
+ }
+
+ if (state->clip_poly)
+ {
+ int size = state->clip_poly_n*sizeof(cdPoint);
+ state->clip_poly = (cdPoint*)malloc(size);
+ memcpy(state->clip_poly, canvas->clip_poly, size);
+ }
+
+ if (state->clip_fpoly)
+ {
+ int size = state->clip_poly_n*sizeof(cdfPoint);
+ state->clip_fpoly = (cdfPoint*)malloc(size);
+ memcpy(state->clip_fpoly, canvas->clip_fpoly, size);
+ }
+
+ if (state->line_dashes)
+ {
+ int size = state->line_dashes_count*sizeof(int);
+ state->line_dashes = (int*)malloc(size);
+ memcpy(state->line_dashes, canvas->line_dashes, size);
+ }
+
+ return state;
+}
+
+void cdReleaseState(cdState* state)
+{
+ assert(state);
+ if (!state) return;
+
+ if (state->stipple)
+ free(state->stipple);
+
+ if (state->pattern)
+ free(state->pattern);
+
+ if (state->clip_poly)
+ free(state->clip_poly);
+
+ if (state->clip_fpoly)
+ free(state->clip_fpoly);
+
+ if (state->line_dashes)
+ free(state->line_dashes);
+
+ free(state);
+ free(state);
+}
+
+void cdCanvasRestoreState(cdCanvas* canvas, cdState* state)
+{
+ assert(canvas);
+ assert(state);
+ if (!state || !_cdCheckCanvas(canvas)) return;
+
+ /* clippling must be done in low level because origin and invert y axis */
+ canvas->clip_poly_n = state->clip_poly_n;
+
+ if (canvas->clip_poly)
+ {
+ free(canvas->clip_poly);
+ canvas->clip_poly = NULL;
+ }
+
+ if (canvas->clip_fpoly)
+ {
+ free(canvas->clip_fpoly);
+ canvas->clip_fpoly = NULL;
+ }
+
+ if (state->clip_poly)
+ {
+ int size = state->clip_poly_n*sizeof(cdPoint);
+ canvas->clip_poly = (cdPoint*)malloc(size);
+ memcpy(canvas->clip_poly, state->clip_poly, size);
+ }
+
+ if (state->clip_fpoly)
+ {
+ int size = state->clip_poly_n*sizeof(cdfPoint);
+ canvas->clip_fpoly = (cdfPoint*)malloc(size);
+ memcpy(canvas->clip_fpoly, state->clip_fpoly, size);
+ }
+
+ cdCanvasClip(canvas, CD_CLIPOFF);
+ if (canvas->clip_fpoly)
+ canvas->cxFPoly(canvas->ctxcanvas, CD_CLIP, state->clip_fpoly, state->clip_poly_n);
+ else if (canvas->clip_poly)
+ canvas->cxPoly(canvas->ctxcanvas, CD_CLIP, state->clip_poly, state->clip_poly_n);
+ cdCanvasClipArea(canvas, state->clip_rect.xmin, state->clip_rect.xmax, state->clip_rect.ymin, state->clip_rect.ymax);
+ if (canvas->cxFClipArea)
+ canvas->cxFClipArea(canvas->ctxcanvas, state->clip_frect.xmin, state->clip_frect.xmax, state->clip_frect.ymin, state->clip_frect.ymax);
+ else if (canvas->cxClipArea)
+ canvas->cxClipArea(canvas->ctxcanvas, state->clip_rect.xmin, state->clip_rect.xmax, state->clip_rect.ymin, state->clip_rect.ymax);
+ cdCanvasClip(canvas, state->clip_mode);
+
+ /* regular attributes */
+ cdCanvasSetBackground(canvas, state->background);
+ cdCanvasSetForeground(canvas, state->foreground);
+ cdCanvasBackOpacity(canvas, state->back_opacity);
+ cdCanvasWriteMode(canvas, state->write_mode);
+ cdCanvasLineStyle(canvas, state->line_style);
+ cdCanvasLineWidth(canvas, state->line_width);
+ cdCanvasLineCap(canvas, state->line_cap);
+ cdCanvasLineJoin(canvas, state->line_join);
+ cdCanvasFillMode(canvas, state->fill_mode);
+ cdCanvasLineStyleDashes(canvas, state->line_dashes, state->line_dashes_count);
+ cdCanvasHatch(canvas, state->hatch_style);
+ if (state->stipple) cdCanvasStipple(canvas, state->stipple_w, state->stipple_h, state->stipple);
+ if (state->pattern) cdCanvasPattern(canvas, state->pattern_w, state->pattern_h, state->pattern);
+ cdCanvasInteriorStyle(canvas, state->interior_style);
+ if (state->native_font[0])
+ cdCanvasNativeFont(canvas, state->native_font);
+ else
+ cdCanvasFont(canvas, state->font_type_face, state->font_style, state->font_size);
+ cdCanvasTextAlignment(canvas, state->text_alignment);
+ cdCanvasTextOrientation(canvas, state->text_orientation);
+ cdCanvasMarkType(canvas, state->mark_type);
+ cdCanvasMarkSize(canvas, state->mark_size);
+ cdCanvasOrigin(canvas, state->origin.x, state->origin.y);
+ if (state->use_matrix)
+ cdCanvasTransform(canvas, state->matrix);
+ wdCanvasWindow(canvas, state->window.xmin, state->window.xmax, state->window.ymin, state->window.ymax);
+ wdCanvasViewport(canvas, state->viewport.xmin, state->viewport.xmax, state->viewport.ymin, state->viewport.ymax);
+ cdCanvasSimulate(canvas, state->sim_mode);
+
+ /* complex clipping regions are not saved */
+ /* driver internal attributes are not saved */
+}
+
+static cdAttribute* cd_findattrib(cdCanvas *canvas, const char* name, int *a)
+{
+ int i;
+
+ for (i=0; i < canvas->attrib_n; i++)
+ {
+ if (strcmp(name, canvas->attrib_list[i]->name) == 0)
+ {
+ if (a) *a = i;
+ return canvas->attrib_list[i];
+ }
+ }
+
+ return NULL;
+}
+
+void cdRegisterAttribute(cdCanvas *canvas, cdAttribute* attrib)
+{
+ cdAttribute* old_attrib;
+ int a;
+
+ assert(canvas);
+ assert(attrib);
+ if (!attrib || !_cdCheckCanvas(canvas)) return;
+
+ old_attrib = cd_findattrib(canvas, attrib->name, &a);
+
+ if (old_attrib)
+ canvas->attrib_list[a] = attrib;
+ else
+ {
+ canvas->attrib_list[canvas->attrib_n] = attrib;
+ canvas->attrib_n++;
+ }
+}
+
+void cdCanvasSetAttribute(cdCanvas* canvas, const char* name, char *data)
+{
+ cdAttribute* attrib;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ attrib = cd_findattrib(canvas, name, NULL);
+ if (attrib && attrib->set)
+ attrib->set(canvas->ctxcanvas, data);
+}
+
+void cdCanvasSetfAttribute(cdCanvas* canvas, const char* name, const char* format, ...)
+{
+ char data[1024];
+ va_list arglist;
+ va_start(arglist, format);
+ vsprintf(data, format, arglist);
+
+ cdCanvasSetAttribute(canvas, name, data);
+}
+
+char* cdCanvasGetAttribute(cdCanvas* canvas, const char* name)
+{
+ cdAttribute* attrib;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return NULL;
+
+ attrib = cd_findattrib(canvas, name, NULL);
+ if (attrib && attrib->get)
+ return attrib->get(canvas->ctxcanvas);
+
+ return NULL;
+}
+
+int cdCanvasPlay(cdCanvas* canvas, cdContext* context, int xmin, int xmax, int ymin, int ymax, void *data)
+{
+ assert(context);
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas) || !context || !context->cxPlay) return CD_ERROR;
+
+ /* the all can be 0 here, do not use cdCheckBoxSize */
+ if (xmin > xmax) _cdSwapInt(xmin, xmax);
+ if (ymin > ymax) _cdSwapInt(ymin, ymax);
+
+ return context->cxPlay(canvas, xmin, xmax, ymin, ymax, data);
+}
+
+int cdContextRegisterCallback(cdContext *context, int cb, cdCallback func)
+{
+ assert(context);
+ if (!context || !context->cxRegisterCallback) return CD_ERROR;
+ return context->cxRegisterCallback(cb, func);
+}
+
+void cdCanvasFlush(cdCanvas* canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas) || !canvas->cxFlush) return;
+ canvas->cxFlush(canvas->ctxcanvas);
+}
+
+void cdCanvasClear(cdCanvas* canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas) || !canvas->cxClear) return;
+ canvas->cxClear(canvas->ctxcanvas);
+}
+
+int cdCanvasUpdateYAxis(cdCanvas* canvas, int* y)
+{
+ assert(canvas);
+ assert(y);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ if(canvas->invert_yaxis)
+ {
+ *y = _cdInvertYAxis(canvas, *y);
+
+ if (canvas->use_origin)
+ *y -= 2*canvas->origin.y;
+ }
+
+ return *y;
+}
+
+double cdfCanvasUpdateYAxis(cdCanvas* canvas, double* y)
+{
+ assert(canvas);
+ assert(y);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ if(canvas->invert_yaxis)
+ {
+ *y = _cdInvertYAxis(canvas, *y);
+
+ if (canvas->use_origin)
+ *y -= 2*canvas->origin.y;
+ }
+
+ return *y;
+}
+
+int cdCanvasInvertYAxis(cdCanvas* canvas, int y)
+{
+ int yi;
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ yi = _cdInvertYAxis(canvas, y);
+
+ if (canvas->use_origin)
+ yi -= 2*canvas->origin.y;
+
+ return yi;
+}
+
+double cdfCanvasInvertYAxis(cdCanvas* canvas, double y)
+{
+ double yi;
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ yi = _cdInvertYAxis(canvas, y);
+
+ if (canvas->use_origin)
+ yi -= 2*canvas->origin.y;
+
+ return yi;
+}
+
+void cdCanvasGetSize(cdCanvas* canvas, int *width, int *height, double *width_mm, double *height_mm)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (width) *width = canvas->w;
+ if (height) *height = canvas->h;
+ if (width_mm) *width_mm = canvas->w_mm;
+ if (height_mm) *height_mm = canvas->h_mm;
+}
+
+void cdCanvasMM2Pixel(cdCanvas* canvas, double mm_dx, double mm_dy, int *dx, int *dy)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (dx) *dx = cdRound(mm_dx*canvas->xres);
+ if (dy) *dy = cdRound(mm_dy*canvas->yres);
+}
+
+void cdCanvasPixel2MM(cdCanvas* canvas, int dx, int dy, double *mm_dx, double *mm_dy)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (mm_dx) *mm_dx = ((double)dx)/canvas->xres;
+ if (mm_dy) *mm_dy = ((double)dy)/canvas->yres;
+}
+
+void cdfCanvasMM2Pixel(cdCanvas* canvas, double mm_dx, double mm_dy, double *dx, double *dy)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (dx) *dx = mm_dx*canvas->xres;
+ if (dy) *dy = mm_dy*canvas->yres;
+}
+
+void cdfCanvasPixel2MM(cdCanvas* canvas, double dx, double dy, double *mm_dx, double *mm_dy)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (mm_dx) *mm_dx = dx/canvas->xres;
+ if (mm_dy) *mm_dy = dy/canvas->yres;
+}
+
+/***** Context Plus Functions ********/
+
+static int use_context_plus = 0;
+static cdContext* context_plus[NUM_CONTEXTPLUS] = {NULL, NULL, NULL, NULL, NULL, NULL};
+
+int cdUseContextPlus(int use)
+{
+ if (use == CD_QUERY)
+ return use_context_plus;
+
+ {
+ int old_use_context_plus = use_context_plus;
+ use_context_plus = use;
+ return old_use_context_plus;
+ }
+}
+
+void cdInitContextPlusList(cdContext* ctx_list[])
+{
+ int ctx;
+ for (ctx = 0; ctx < NUM_CONTEXTPLUS; ctx++)
+ if (ctx_list[ctx] != NULL)
+ context_plus[ctx] = ctx_list[ctx];
+}
+
+cdContext* cdGetContextPlus(int ctx)
+{
+ if (ctx < 0 || ctx >= NUM_CONTEXTPLUS)
+ return NULL;
+
+ return context_plus[ctx];
+}
+
+/***** OLD Compatibility Functions ********/
+
+int cdRegisterCallback(cdContext *context, int cb, cdCallback func)
+{
+ return cdContextRegisterCallback(context, cb, func);
+}
+
+cdContext* cdGetContext(cdCanvas* canvas)
+{
+ return cdCanvasGetContext(canvas);
+}
+
+int * cdGetClipPoly(int *n)
+{
+ if (n) *n = 0;
+ return NULL;
+}
+
+double* wdGetClipPoly(int *n)
+{
+ if (n) *n = 0;
+ return NULL;
+}