summaryrefslogtreecommitdiff
path: root/src/wd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/wd.c')
-rw-r--r--src/wd.c473
1 files changed, 473 insertions, 0 deletions
diff --git a/src/wd.c b/src/wd.c
new file mode 100644
index 0000000..85e01dd
--- /dev/null
+++ b/src/wd.c
@@ -0,0 +1,473 @@
+/** \file
+ * \brief World Coordinate Functions
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <memory.h>
+
+#include "cd.h"
+#include "wd.h"
+
+#include "cd_private.h"
+
+
+static void wdUpdateTransformation(cdCanvas* canvas)
+{
+ if (canvas->window.xmax != canvas->window.xmin)
+ canvas->sx = (canvas->viewport.xmax - canvas->viewport.xmin)/(canvas->window.xmax - canvas->window.xmin);
+ else
+ canvas->sx = 0;
+ canvas->tx = canvas->viewport.xmin - canvas->window.xmin*canvas->sx;
+
+ if (canvas->window.ymax != canvas->window.ymin)
+ canvas->sy = (canvas->viewport.ymax - canvas->viewport.ymin)/(canvas->window.ymax - canvas->window.ymin);
+ else
+ canvas->sy = 0;
+ canvas->ty = canvas->viewport.ymin - canvas->window.ymin*canvas->sy;
+
+ canvas->s = sqrt(canvas->sx * canvas->sx + canvas->sy * canvas->sy);
+}
+
+void wdSetDefaults(cdCanvas* canvas)
+{
+ canvas->window.xmin = 0;
+ canvas->window.xmax = canvas->w_mm;
+ canvas->window.ymin = 0;
+ canvas->window.ymax = canvas->h_mm;
+
+ canvas->viewport.xmin = 0;
+ canvas->viewport.xmax = canvas->w-1;
+ canvas->viewport.ymin = 0;
+ canvas->viewport.ymax = canvas->h-1;
+
+ wdUpdateTransformation(canvas);
+}
+
+void wdCanvasWindow(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax)
+{
+ canvas->window.xmin = xmin;
+ canvas->window.xmax = xmax;
+ canvas->window.ymin = ymin;
+ canvas->window.ymax = ymax;
+
+ wdUpdateTransformation(canvas);
+}
+
+void wdCanvasGetWindow (cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ if (xmin) *xmin = canvas->window.xmin;
+ if (xmax) *xmax = canvas->window.xmax;
+ if (ymin) *ymin = canvas->window.ymin;
+ if (ymax) *ymax = canvas->window.ymax;
+}
+
+void wdCanvasViewport(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax)
+{
+ canvas->viewport.xmin = xmin;
+ canvas->viewport.xmax = xmax;
+ canvas->viewport.ymin = ymin;
+ canvas->viewport.ymax = ymax;
+
+ wdUpdateTransformation(canvas);
+}
+
+void wdCanvasGetViewport(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ if (xmin) *xmin = canvas->viewport.xmin;
+ if (xmax) *xmax = canvas->viewport.xmax;
+ if (ymin) *ymin = canvas->viewport.ymin;
+ if (ymax) *ymax = canvas->viewport.ymax;
+}
+
+#define _wWorld2Canvas(_canvas, _xw, _yw, _xv, _yv) \
+{ \
+ _xv = cdRound(_canvas->sx*(_xw) + _canvas->tx); \
+ _yv = cdRound(_canvas->sy*(_yw) + _canvas->ty); \
+}
+
+#define _wfWorld2Canvas(_canvas, _xw, _yw, _xv, _yv) \
+{ \
+ _xv = (_canvas->sx*(_xw) + _canvas->tx); \
+ _yv = (_canvas->sy*(_yw) + _canvas->ty); \
+}
+
+void wdCanvasWorld2Canvas(cdCanvas* canvas, double xw, double yw, int *xv, int *yv)
+{
+ if (xv) *xv = cdRound(canvas->sx*xw + canvas->tx);
+ if (yv) *yv = cdRound(canvas->sy*yw + canvas->ty);
+}
+
+#define _wWorld2CanvasSize(_canvas, _Ww, _Hw, _Wv, _Hv) \
+{ \
+ _Wv = cdRound(_canvas->sx*(_Ww)); \
+ _Hv = cdRound(_canvas->sy*(_Hw)); \
+}
+
+#define _wfWorld2CanvasSize(_canvas, _Ww, _Hw, _Wv, _Hv) \
+{ \
+ _Wv = (_canvas->sx*(_Ww)); \
+ _Hv = (_canvas->sy*(_Hw)); \
+}
+
+void wdCanvasWorld2CanvasSize(cdCanvas* canvas, double hw, double vw, int *hv, int *vv)
+{
+ if (hv) *hv = cdRound(canvas->sx*hw);
+ if (vv) *vv = cdRound(canvas->sy*vw);
+}
+
+#define _wCanvas2World(_canvas, _xv, _yv, _xw, _yw) \
+{ \
+ _xw = ((double)(_xv) - _canvas->tx)/_canvas->sx; \
+ _yw = ((double)(_yv) - _canvas->ty)/_canvas->sy; \
+}
+
+void wdCanvasCanvas2World(cdCanvas* canvas, int xv, int yv, double *xw, double *yw)
+{
+ if (xw) *xw = ((double)xv - canvas->tx)/canvas->sx;
+ if (yw) *yw = ((double)yv - canvas->ty)/canvas->sy;
+}
+
+void wdCanvasClipArea(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax)
+{
+ int xminr, xmaxr, yminr, ymaxr;
+
+ _wWorld2Canvas(canvas, xmin, ymin, xminr, yminr);
+ _wWorld2Canvas(canvas, xmax, ymax, xmaxr, ymaxr);
+
+ cdCanvasClipArea(canvas, xminr, xmaxr, yminr, ymaxr);
+}
+
+int wdCanvasIsPointInRegion(cdCanvas* canvas, double x, double y)
+{
+ int xr, yr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ return cdCanvasIsPointInRegion(canvas, xr, yr);
+}
+
+void wdCanvasOffsetRegion(cdCanvas* canvas, double x, double y)
+{
+ int xr, yr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ cdCanvasOffsetRegion(canvas, xr, yr);
+}
+
+void wdCanvasGetRegionBox(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ int xminr, xmaxr, yminr, ymaxr;
+ cdCanvasGetRegionBox(canvas, &xminr, &xmaxr, &yminr, &ymaxr);
+ _wCanvas2World(canvas, xminr, yminr, *xmin, *ymin);
+ _wCanvas2World(canvas, xmaxr, ymaxr, *xmax, *ymax);
+}
+
+int wdCanvasGetClipArea(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ int xminr, xmaxr, yminr, ymaxr;
+ int clip = cdCanvasGetClipArea(canvas, &xminr, &xmaxr, &yminr, &ymaxr);
+ _wCanvas2World(canvas, xminr, yminr, *xmin, *ymin);
+ _wCanvas2World(canvas, xmaxr, ymaxr, *xmax, *ymax);
+ return clip;
+}
+
+void wdCanvasLine(cdCanvas* canvas, double x1, double y1, double x2, double y2)
+{
+ double xr1, xr2, yr1, yr2;
+ _wfWorld2Canvas(canvas, x1, y1, xr1, yr1);
+ _wfWorld2Canvas(canvas, x2, y2, xr2, yr2);
+ cdfCanvasLine(canvas, xr1, yr1, xr2, yr2);
+}
+
+void wdCanvasBox(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax)
+{
+ double xminr, xmaxr, yminr, ymaxr;
+ _wfWorld2Canvas(canvas, xmin, ymin, xminr, yminr);
+ _wfWorld2Canvas(canvas, xmax, ymax, xmaxr, ymaxr);
+ cdfCanvasBox(canvas, xminr, xmaxr, yminr, ymaxr);
+}
+
+void wdCanvasRect(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax)
+{
+ double xminr, xmaxr, yminr, ymaxr;
+ _wfWorld2Canvas(canvas, xmin, ymin, xminr, yminr);
+ _wfWorld2Canvas(canvas, xmax, ymax, xmaxr, ymaxr);
+ cdfCanvasRect(canvas, xminr, xmaxr, yminr, ymaxr);
+}
+
+void wdCanvasArc(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ double xcr, ycr, wr, hr;
+ _wfWorld2Canvas(canvas, xc, yc, xcr, ycr);
+ _wfWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdfCanvasArc(canvas, xcr, ycr, wr, hr, angle1, angle2);
+}
+
+void wdCanvasSector(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ double xcr, ycr, wr, hr;
+ _wfWorld2Canvas(canvas, xc, yc, xcr, ycr);
+ _wfWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdfCanvasSector(canvas, xcr, ycr, wr, hr, angle1, angle2);
+}
+
+void wdCanvasChord(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ double xcr, ycr, wr, hr;
+ _wfWorld2Canvas(canvas, xc, yc, xcr, ycr);
+ _wfWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdfCanvasChord(canvas, xcr, ycr, wr, hr, angle1, angle2);
+}
+
+void wdCanvasText(cdCanvas* canvas, double x, double y, const char *s)
+{
+ double xr, yr;
+ _wfWorld2Canvas(canvas, x, y, xr, yr);
+ cdfCanvasText(canvas, xr, yr, s);
+}
+
+void wdCanvasVertex(cdCanvas* canvas, double x, double y)
+{
+ double xr, yr;
+ _wfWorld2Canvas(canvas, x, y, xr, yr);
+ cdfCanvasVertex(canvas, xr, yr);
+}
+
+void wdCanvasMark(cdCanvas* canvas, double x, double y)
+{
+ int xr, yr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ cdCanvasMark(canvas, xr, yr);
+}
+
+void wdCanvasPixel(cdCanvas* canvas, double x, double y, long color)
+{
+ int xr, yr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ cdCanvasPixel(canvas, xr, yr, color);
+}
+
+void wdCanvasPutImageRect(cdCanvas* canvas, cdImage* image, double x, double y, int xmin, int xmax, int ymin, int ymax)
+{
+ int xr, yr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ cdCanvasPutImageRect(canvas, image, xr, yr, xmin, xmax, ymin, ymax);
+}
+
+void wdCanvasPutImageRectRGB(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax)
+{
+ int xr, yr, wr, hr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ _wWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdCanvasPutImageRectRGB(canvas, iw, ih, r, g, b, xr, yr, wr, hr, xmin, xmax, ymin, ymax);
+}
+
+void wdCanvasPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax)
+{
+ int xr, yr, wr, hr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ _wWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdCanvasPutImageRectRGBA(canvas, iw, ih, r, g, b, a, xr, yr, wr, hr, xmin, xmax, ymin, ymax);
+}
+
+void wdCanvasPutImageRectMap(cdCanvas* canvas, int iw, int ih, const unsigned char *index, const long *colors, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax)
+{
+ int xr, yr, wr, hr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ _wWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdCanvasPutImageRectMap(canvas, iw, ih, index, colors, xr, yr, wr, hr, xmin, xmax, ymin, ymax);
+}
+
+void wdCanvasPutBitmap(cdCanvas* canvas, cdBitmap* image, double x, double y, double w, double h)
+{
+ int xr, yr, wr, hr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ _wWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdCanvasPutBitmap(canvas, image, xr, yr, wr, hr);
+}
+
+double wdCanvasLineWidth(cdCanvas* canvas, double width_mm)
+{
+ int width;
+ double line_width_mm = canvas->line_width/canvas->xres;
+
+ if (width_mm == CD_QUERY)
+ return line_width_mm;
+
+ width = cdRound(width_mm*canvas->xres);
+ if (width < 1) width = 1;
+
+ cdCanvasLineWidth(canvas, width);
+
+ return line_width_mm;
+}
+
+int wdCanvasFont(cdCanvas* canvas, const char* type_face, int style, double size_mm)
+{
+ return cdCanvasFont(canvas, type_face, style, cdRound(size_mm*CD_MM2PT));
+}
+
+void wdCanvasGetFont(cdCanvas* canvas, char *type_face, int *style, double *size)
+{
+ int point_size;
+ cdCanvasGetFont(canvas, type_face, style, &point_size);
+ if (point_size<0)
+ {
+ if (size) cdCanvasPixel2MM(canvas, -point_size, 0, size, NULL);
+ }
+ else
+ {
+ if (size) *size = ((double)point_size) / CD_MM2PT;
+ }
+}
+
+double wdCanvasMarkSize(cdCanvas* canvas, double size_mm)
+{
+ int size;
+ double mark_size_mm = canvas->mark_size/canvas->xres;
+
+ if (size_mm == CD_QUERY)
+ return mark_size_mm;
+
+ size = cdRound(size_mm*canvas->xres);
+ if (size < 1) size = 1;
+
+ canvas->mark_size = size;
+
+ return mark_size_mm;
+}
+
+void wdCanvasGetFontDim(cdCanvas* canvas, double *max_width, double *height, double *ascent, double *descent)
+{
+ double origin_x, origin_y, tmp = 0;
+ double distance_x, distance_y;
+ int font_max_width, font_height, font_ascent, font_descent;
+ cdCanvasGetFontDim(canvas, &font_max_width, &font_height, &font_ascent, &font_descent);
+ _wCanvas2World(canvas, 0, 0, origin_x, origin_y);
+ _wCanvas2World(canvas, font_max_width, font_height, distance_x, distance_y);
+ if (max_width) *max_width = fabs(distance_x - origin_x);
+ if (height) *height = fabs(distance_y - origin_y);
+ _wCanvas2World(canvas, tmp, font_ascent, tmp, distance_y);
+ if (ascent) *ascent = fabs(distance_y - origin_y);
+ _wCanvas2World(canvas, tmp, font_descent, tmp, distance_y);
+ if (descent) *descent = fabs(distance_y - origin_y);
+}
+
+void wdCanvasGetTextSize(cdCanvas* canvas, const char *s, double *width, double *height)
+{
+ int text_width, text_height;
+ double origin_x, origin_y;
+ double text_x, text_y;
+ _wCanvas2World(canvas, 0, 0, origin_x, origin_y);
+ cdCanvasGetTextSize(canvas, s, &text_width, &text_height);
+ _wCanvas2World(canvas, text_width, text_height, text_x, text_y);
+ if (width) *width = fabs(text_x - origin_x);
+ if (height) *height = fabs(text_y - origin_y);
+}
+
+void wdCanvasGetTextBox(cdCanvas* canvas, double x, double y, const char *s, double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ int rx, ry, rxmin, rxmax, rymin, rymax;
+
+ _wWorld2Canvas(canvas, x, y, rx, ry);
+ cdCanvasGetTextBox(canvas, rx, ry, s, &rxmin, &rxmax, &rymin, &rymax);
+
+ _wCanvas2World(canvas, rxmin, rymin, *xmin, *ymin);
+ _wCanvas2World(canvas, rxmax, rymax, *xmax, *ymax);
+}
+
+void wdCanvasGetTextBounds(cdCanvas* canvas, double x, double y, const char *s, double *rect)
+{
+ int rx, ry, rrect[8];
+
+ _wWorld2Canvas(canvas, x, y, rx, ry);
+ cdCanvasGetTextBounds(canvas, rx, ry, s, rrect);
+
+ _wCanvas2World(canvas, rrect[0], rrect[1], rect[0], rect[1]);
+ _wCanvas2World(canvas, rrect[2], rrect[3], rect[2], rect[3]);
+ _wCanvas2World(canvas, rrect[4], rrect[5], rect[4], rect[5]);
+ _wCanvas2World(canvas, rrect[6], rrect[7], rect[6], rect[7]);
+}
+
+void wdCanvasPattern(cdCanvas* canvas, int w, int h, const long *color, double w_mm, double h_mm)
+{
+ long *pattern = 0;
+ int w_pxl, h_pxl, x, y, cx, cy;
+ int wratio, hratio;
+ int *XTab, *YTab;
+
+ cdCanvasMM2Pixel(canvas, w_mm, h_mm, &w_pxl, &h_pxl);
+
+ wratio = cdRound((double)w_pxl/(double)w);
+ hratio = cdRound((double)h_pxl/(double)h);
+
+ wratio = (wratio <= 0)? 1: wratio;
+ hratio = (hratio <= 0)? 1: hratio;
+
+ w_pxl = wratio * w;
+ h_pxl = hratio * h;
+
+ pattern = (long*)malloc(w_pxl*h_pxl*sizeof(long));
+
+ XTab = cdGetZoomTable(w_pxl, w, 0);
+ YTab = cdGetZoomTable(h_pxl, h, 0);
+
+ for (y=0; y<h_pxl; y++)
+ {
+ cy = YTab[y];
+ for (x=0; x<w_pxl; x++)
+ {
+ cx = XTab[x];
+ pattern[x + y*w_pxl] = color[cx + cy*w];
+ }
+ }
+
+ cdCanvasPattern(canvas, w_pxl, h_pxl, pattern);
+
+ free(XTab);
+ free(YTab);
+ free(pattern);
+}
+
+void wdCanvasStipple(cdCanvas* canvas, int w, int h, const unsigned char *fgbg, double w_mm, double h_mm)
+{
+ unsigned char *stipple = 0;
+ int w_pxl, h_pxl, x, y, cx, cy;
+ int wratio, hratio;
+ int *XTab, *YTab;
+
+ cdCanvasMM2Pixel(canvas, w_mm, h_mm, &w_pxl, &h_pxl);
+
+ wratio = cdRound((double)w_pxl/(double)w);
+ hratio = cdRound((double)h_pxl/(double)h);
+
+ wratio = (wratio <= 0)? 1: wratio;
+ hratio = (hratio <= 0)? 1: hratio;
+
+ w_pxl = wratio * w;
+ h_pxl = hratio * h;
+
+ stipple = (unsigned char*)malloc(w_pxl*h_pxl);
+
+ XTab = cdGetZoomTable(w_pxl, w, 0);
+ YTab = cdGetZoomTable(h_pxl, h, 0);
+
+ for (y=0; y<h_pxl; y++)
+ {
+ cy = YTab[y];
+ for (x=0; x<w_pxl; x++)
+ {
+ cx = XTab[x];
+ stipple[x + y*w_pxl] = fgbg[cx + cy*w];
+ }
+ }
+
+ cdCanvasStipple(canvas, w_pxl, h_pxl, stipple);
+
+ free(XTab);
+ free(YTab);
+ free(stipple);
+}
+