iup-stack/cd/src/cd.c

826 lines
21 KiB
C
Executable File

/** \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"
/* This appears only here to avoid changing the cd.h header fo bug fixes */
#define CD_VERSION_FIX ""
#define CD_VERSION_FIX_NUMBER 0
/* #define CD_VERSION_FIX_DATE "" */
const char cd_ident[] =
"$CD: " CD_VERSION CD_VERSION_FIX " " CD_COPYRIGHT " $\n"
"$URL: www.tecgraf.puc-rio.br/cd $\n";
static char *tecver = "TECVERID.str:CD:LIB:" CD_VERSION CD_VERSION_FIX;
char* cdVersion(void)
{
(void)cd_ident;
(void)tecver;
return CD_VERSION CD_VERSION_FIX;
}
char* cdVersionDate(void)
{
#ifdef CD_VERSION_FIX_DATE
return CD_VERSION_FIX_DATE;
#else
return CD_VERSION_DATE;
#endif
}
int cdVersionNumber(void)
{
return CD_VERSION_NUMBER+CD_VERSION_FIX_NUMBER;
}
static void cd_setdefaultfunc(cdCanvas* canvas)
{
canvas->cxGetTextSize = cdgettextsizeEX;
canvas->cxGetFontDim = cdgetfontdimEX;
canvas->cxRect = cdSimRect;
}
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;
/* everything else is 0 because of the memset */
}
void cdUpdateAttributes(cdCanvas* canvas)
{
cdCtxCanvas* ctxcanvas = canvas->ctxcanvas;
if (canvas->cxBackground) canvas->cxBackground(ctxcanvas, canvas->background);
if (canvas->cxForeground) canvas->cxForeground(ctxcanvas, canvas->foreground);
if (canvas->cxBackOpacity) canvas->cxBackOpacity(ctxcanvas, canvas->back_opacity);
if (canvas->cxWriteMode) canvas->cxWriteMode(ctxcanvas, canvas->write_mode);
if (canvas->cxLineStyle) canvas->cxLineStyle(ctxcanvas, canvas->line_style);
if (canvas->cxLineWidth) canvas->cxLineWidth(ctxcanvas, canvas->line_width);
if (canvas->cxLineCap) canvas->cxLineCap(ctxcanvas, canvas->line_cap);
if (canvas->cxLineJoin) canvas->cxLineJoin(ctxcanvas, canvas->line_join);
if (canvas->cxHatch) canvas->cxHatch(ctxcanvas, canvas->hatch_style);
if (canvas->stipple && canvas->cxStipple) canvas->cxStipple(ctxcanvas, canvas->stipple_w, canvas->stipple_h, canvas->stipple);
if (canvas->pattern && canvas->cxPattern) canvas->cxPattern(ctxcanvas, canvas->pattern_w, canvas->pattern_h, canvas->pattern);
if (canvas->cxInteriorStyle) canvas->cxInteriorStyle(ctxcanvas, canvas->interior_style);
if (canvas->native_font[0] && canvas->cxNativeFont)
canvas->cxNativeFont(ctxcanvas, canvas->native_font);
else if (canvas->cxFont)
canvas->cxFont(ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
if (canvas->cxTextAlignment) canvas->cxTextAlignment(ctxcanvas, canvas->text_alignment);
if (canvas->cxTextOrientation) canvas->cxTextOrientation(ctxcanvas, canvas->text_orientation);
if (canvas->use_matrix && canvas->cxTransform) canvas->cxTransform(ctxcanvas, canvas->matrix);
if (canvas->clip_mode == CD_CLIPAREA && canvas->cxClipArea) canvas->cxClipArea(ctxcanvas, canvas->clip_rect.xmin, canvas->clip_rect.xmax, canvas->clip_rect.ymin, canvas->clip_rect.ymax);
if (canvas->clip_mode == CD_CLIPAREA && canvas->cxFClipArea) canvas->cxFClipArea(ctxcanvas, canvas->clip_frect.xmin, canvas->clip_frect.xmax, canvas->clip_frect.ymin, canvas->clip_frect.ymax);
if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_poly) canvas->cxPoly(ctxcanvas, CD_CLIP, canvas->clip_poly, canvas->clip_poly_n);
if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_fpoly) canvas->cxFPoly(ctxcanvas, CD_CLIP, canvas->clip_fpoly, canvas->clip_poly_n);
if (canvas->clip_mode != CD_CLIPOFF && canvas->cxClip) canvas->cxClip(ctxcanvas, canvas->clip_mode);
}
static void set_userdata_attrib(cdCtxCanvas* ctxcanvas, char* data)
{
cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
canvas->userdata = data;
}
static char* get_userdata_attrib(cdCtxCanvas* ctxcanvas)
{
cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
return canvas->userdata;
}
static cdAttribute userdata_attrib =
{
"USERDATA",
set_userdata_attrib,
get_userdata_attrib
};
cdCanvas* cdCreateCanvasf(cdContext *context, const char* format, ...)
{
char data[10240];
va_list arglist;
va_start(arglist, format);
vsnprintf(data, 10240, format, arglist);
va_end(arglist);
return cdCreateCanvas(context, data);
}
cdCanvas *cdCreateCanvas(cdContext* context, void *data_str)
{
cdCanvas *canvas;
/* useful 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) /* default is quiet */
{
printf("CD " CD_VERSION CD_VERSION_FIX " " CD_COPYRIGHT "\n");
first = 0;
}
}
/* allocates 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;
}
/* default simulation functions */
cd_setdefaultfunc(canvas);
/* initialize canvas table */
context->cxInitTable(canvas);
/* update the default attributes, must be after InitTable */
cdCanvasActivate(canvas);
cdUpdateAttributes(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);
cdRegisterAttribute(canvas, &userdata_attrib);
return canvas;
}
void cdKillCanvas(cdCanvas *canvas)
{
assert(canvas);
if (!_cdCheckCanvas(canvas)) return;
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);
if (canvas->path) free(canvas->path);
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 cdContextIsPlus(cdContext *context)
{
if (!context)
return CD_ERROR;
return context->type&CD_CTX_PLUS? 1: 0;
}
int cdContextType(cdContext *context)
{
if (!context)
return CD_ERROR;
return context->type&0x00FF;
}
int cdCanvasSimulate(cdCanvas* canvas, int mode)
{
int old_sim_mode;
cdContext* context;
assert(canvas);
if (!_cdCheckCanvas(canvas)) return CD_ERROR;
context = canvas->context;
old_sim_mode = canvas->sim_mode;
if (mode == CD_QUERY || cdCanvasGetContext(canvas) == CD_IMAGERGB)
return old_sim_mode;
/* default simulation functions */
cd_setdefaultfunc(canvas);
/* initialize canvas table */
context->cxInitTable(canvas);
canvas->sim_mode = mode;
if (mode == CD_SIM_NONE)
return old_sim_mode;
/* when simulation is active must not set driver transform */
canvas->cxTransform = NULL;
if (mode & CD_SIM_LINE)
{
canvas->cxLine = cdSimLine;
canvas->cxFLine = NULL;
}
if (mode & CD_SIM_RECT)
{
canvas->cxRect = cdSimRect;
canvas->cxFRect = NULL;
}
if (mode & CD_SIM_BOX)
{
canvas->cxBox = cdSimBox;
canvas->cxFBox = NULL;
}
if (mode & CD_SIM_ARC)
{
canvas->cxArc = cdSimArc;
canvas->cxFArc = NULL;
}
if (mode & CD_SIM_SECTOR)
{
canvas->cxSector = cdSimSector;
canvas->cxFSector = NULL;
}
if (mode & CD_SIM_CHORD)
{
canvas->cxChord = cdSimChord;
canvas->cxFChord = NULL;
}
if (mode & CD_SIM_TEXT)
{
canvas->cxText = cdSimulationText;
canvas->cxFText = NULL;
canvas->cxNativeFont = NULL;
canvas->cxFont = cdSimulationFont;
canvas->cxGetFontDim = cdSimulationGetFontDim;
canvas->cxGetTextSize = cdSimulationGetTextSize;
canvas->cxTextOrientation = NULL;
cdSimulationInitText(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)
{
/* can NOT replace canvas->cxPoly because it will be used by the simulation,
handle polygon simulation in cdCanvasEnd by calling cdPoly */
canvas->cxFPoly = NULL;
}
return old_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)); /* is actually a 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);
}
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[10240];
va_list arglist;
va_start(arglist, format);
vsnprintf(data, 10240, format, arglist);
va_end(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);
}
/* hidden function to simply control invert_yaxis behavior.
several features will NOT behave as expected, such as
arc direction, text position, image position and vector text */
int cdCanvasYAxisMode(cdCanvas* canvas, int invert)
{
int old_invert_yaxis;
assert(canvas);
if (!_cdCheckCanvas(canvas)) return CD_ERROR;
if (invert == CD_QUERY)
return canvas->invert_yaxis;
old_invert_yaxis = canvas->invert_yaxis;
canvas->invert_yaxis = invert;
return old_invert_yaxis;
}
int cdCanvasUpdateYAxis(cdCanvas* canvas, int* y)
{
assert(canvas);
assert(y);
if (!_cdCheckCanvas(canvas)) return CD_ERROR;
if(!(canvas->context->caps&CD_CAP_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->context->caps&CD_CAP_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[CD_CTXPLUS_COUNT] = {NULL, NULL, NULL, NULL, NULL, NULL};
int cdUseContextPlus(int use)
{
int old_use_context_plus = use_context_plus;
if (use == CD_QUERY)
return use_context_plus;
use_context_plus = use;
return old_use_context_plus;
}
void cdInitContextPlusList(cdContext* ctx_list[])
{
int ctx;
for (ctx = 0; ctx < CD_CTXPLUS_COUNT; ctx++)
if (ctx_list[ctx] != NULL)
context_plus[ctx] = ctx_list[ctx];
}
cdContext* cdGetContextPlus(int ctx)
{
if (ctx < 0 || ctx >= CD_CTXPLUS_COUNT)
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;
}