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 cdCanvasGetArcStartEnd(int xc, int yc, int w, int h, double a1, double a2, int *x1, int *y1, int *x2, int *y2) { /* computation is done as if the angles are counterclockwise, and yaxis is NOT inverted. */ /* leave xc and yc outside the round, so the center will be always the same */ if (x1) *x1 = xc + cdRound((w/2.0)*cos(a1*CD_DEG2RAD)); if (y1) *y1 = yc + cdRound((h/2.0)*sin(a1*CD_DEG2RAD)); if (x2) *x2 = xc + cdRound((w/2.0)*cos(a2*CD_DEG2RAD)); if (y2) *y2 = yc + cdRound((h/2.0)*sin(a2*CD_DEG2RAD)); }
void cdfSimArc(cdCtxCanvas *ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2) { cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; double c, s, sx, sy, x, y, prev_x, prev_y, da; int i, p; cdfPoint* poly = NULL; /* number of segments of equivalent poligonal for a full ellipse */ int n = simCalcEllipseNumSegments(canvas, (int)xc, (int)yc, (int)width, (int)height); poly = (cdfPoint*)malloc(sizeof(cdfPoint)*(n+1)); /* n+1 points */ if (!poly) return; /* number of segments for the arc */ n = cdRound((fabs(angle2-angle1)*n)/360); if (n < 1) n = 1; /* converts degrees into radians */ angle1 *= CD_DEG2RAD; angle2 *= CD_DEG2RAD; /* generates arc points at origin with axis x and y */ da = (angle2-angle1)/n; c = cos(da); s = sin(da); sx = -(width*s)/height; sy = (height*s)/width; x = (width/2.0f)*cos(angle1); y = (height/2.0f)*sin(angle1); prev_x = x; prev_y = y; poly[0].x = x+xc; poly[0].y = y+yc; p = 1; for (i = 1; i < n+1; i++) /* n+1 points */ { x = c*prev_x + sx*prev_y; y = sy*prev_x + c*prev_y; poly[p].x = x+xc; poly[p].y = y+yc; if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y) p++; prev_x = x; prev_y = y; } canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, p); free(poly); }
void wdCanvasStipple(cdCanvas* canvas, int w, int h, const unsigned char *fgbg, double w_mm, double h_mm) { unsigned char *stipple = NULL; int w_pxl, h_pxl, x, y, cx, cy; int wratio, hratio; int *XTab, *YTab; assert(canvas); if (!_cdCheckCanvas(canvas)) return; cdCanvasMM2Pixel(canvas, w_mm, h_mm, &w_pxl, &h_pxl); /* to preserve the pattern characteristics must be an integer number */ 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); }
void wdCanvasPattern(cdCanvas* canvas, int w, int h, const long *color, double w_mm, double h_mm) { long *pattern = NULL; int w_pxl, h_pxl, x, y, cx, cy; int wratio, hratio; int *XTab, *YTab; assert(canvas); if (!_cdCheckCanvas(canvas)) return; cdCanvasMM2Pixel(canvas, w_mm, h_mm, &w_pxl, &h_pxl); /* to preserve the pattern characteristics must be an integer number */ 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 cdCanvasSector(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2) { assert(canvas); if (!_cdCheckCanvas(canvas)) return; if (angle1 == angle2 || w == 0 || h == 0) return; sNormAngles(&angle1, &angle2); if (canvas->interior_style == CD_HOLLOW) { cdCanvasArc(canvas, xc, yc, w, h, angle1, angle2); if (fabs(angle2-angle1) < 360) { int xi,yi,xf,yf; xi = xc + cdRound(w*cos(CD_DEG2RAD*angle1)/2.0); yi = yc + cdRound(h*sin(CD_DEG2RAD*angle1)/2.0); xf = xc + cdRound(w*cos(CD_DEG2RAD*angle2)/2.0); yf = yc + cdRound(h*sin(CD_DEG2RAD*angle2)/2.0); cdCanvasLine(canvas, xi, yi, xc, yc); cdCanvasLine(canvas, xc, yc, xf, yf); } return; } if (canvas->use_origin) { xc += canvas->origin.x; yc += canvas->origin.y; } if (canvas->invert_yaxis) yc = _cdInvertYAxis(canvas, yc); canvas->cxSector(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2); }
static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) { if (ctxcanvas->canvas->use_matrix || ctxcanvas->canvas->new_region) { cdSimSector(ctxcanvas, xc, yc, w, h, a1, a2); } else { /* "filled parameter = TRUE" produces a 'pie slice' */ gdk_draw_arc(ctxcanvas->wnd, ctxcanvas->gc, TRUE, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64)); } }
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); }
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); }
static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) { if (ctxcanvas->canvas->use_matrix) { cdSimArc(ctxcanvas, xc, yc, w, h, a1, a2); return; } /* angles in 1/64ths of degrees counterclockwise, similar to CD */ cdgdkCheckSolidStyle(ctxcanvas, 1); gdk_draw_arc(ctxcanvas->wnd, ctxcanvas->gc, FALSE, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64)); cdgdkCheckSolidStyle(ctxcanvas, 0); }
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; }
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; }
double wdCanvasMarkSize(cdCanvas* canvas, double size_mm) { int size; double mark_size_mm; assert(canvas); if (!_cdCheckCanvas(canvas)) return CD_ERROR; 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; }
double wdCanvasLineWidth(cdCanvas* canvas, double width_mm) { int width; double line_width_mm; assert(canvas); if (!_cdCheckCanvas(canvas)) return CD_ERROR; 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; }
static int sCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int height, double angle1, double angle2) { int K, dx, dy, hd; int w2 = width/2; int h2 = height/2; int x1 = xc-w2, y1 = yc-h2, x2 = xc+w2, y2 = yc+h2; if (canvas->use_matrix) { cdMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1); cdMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2); } /* first calculate the number of segments of equivalent poligonal for a full ellipse */ dx = (x1-x2); dy = (y1-y2); hd = (int)(sqrt(dx*dx + dy*dy)/2); /* Estimation Heuristic: use half diagonal to estimate the number of segments for 360 degrees. Use the difference of the half diagonal and its projection to calculate the minimum angle: cos(min_angle) = hd / (hd + 1) or min_angle = acos(hd / (hd + 1)) The number of segments will be 360 / min_angle. */ K = (int)((360.0*CD_DEG2RAD) / acos((double)hd / (hd + 1.0)) + 0.5); /* round up */ /* multiple of 4 */ K = ((K + 3)/4)*4; /* minimum number is 4 */ if (K < 4) K = 4; /* finally, calculate the number of segments for the arc */ K = cdRound((fabs(angle2-angle1)*K)/(360*CD_DEG2RAD)); if (K < 1) K = 1; return K; }
static int sScaleY(int y) { return cdRound(y * factorY + offsetY); }
void cdarcSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2) { cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; double c, s, sx, sy, x, y, prev_x, prev_y; double da; int i, yc2 = 2*yc, p, last_xi_a = -65535, last_yi_a = -65535, last_xi_b = -65535, last_yi_b = -65535; cdPoint* poly = NULL; /* number of segments of equivalent poligonal for a full ellipse */ int n = simCalcEllipseNumSegments(canvas, xc, yc, width, height); /* Use special floating point anti-alias line draw when line_width==1, and NOT using cdlineSIM. */ if (canvas->line_width > 1 || canvas->cxLine != cdlineSIM) { poly = (cdPoint*)malloc(sizeof(cdPoint)*(n+1)); /* n+1 points */ if (!poly) return; } /* number of segments for the arc */ n = cdRound((fabs(angle2-angle1)*n)/360); if (n < 1) n = 1; /* converts degrees into radians */ angle1 *= CD_DEG2RAD; angle2 *= CD_DEG2RAD; /* generates arc points at origin with axis x and y */ da = (angle2-angle1)/n; c = cos(da); s = sin(da); sx = -(width*s)/height; sy = (height*s)/width; x = (width/2.0f)*cos(angle1); y = (height/2.0f)*sin(angle1); prev_x = x; prev_y = y; if (poly) { poly[0].x = _cdRound(x)+xc; poly[0].y = _cdRound(y)+yc; if (canvas->invert_yaxis) /* must invert because of the angle orientation */ poly[0].y = yc2 - poly[0].y; p = 1; } else simLineStyleNoReset = 1; for (i = 1; i < n+1; i++) /* n+1 points */ { x = c*prev_x + sx*prev_y; y = sy*prev_x + c*prev_y; if (poly) { poly[p].x = _cdRound(x)+xc; poly[p].y = _cdRound(y)+yc; if (canvas->invert_yaxis) /* must invert because of the angle orientation */ poly[p].y = yc2 - poly[p].y; if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y) p++; } else { int old_use_matrix = canvas->use_matrix; double x1 = prev_x+xc, y1 = prev_y+yc, x2 = x+xc, y2 = y+yc; if (canvas->use_matrix && !canvas->invert_yaxis) { cdfMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1); cdfMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2); } /* must disable transformation here, because line simulation use cxPixel */ canvas->use_matrix = 0; if (canvas->invert_yaxis) /* must invert because of the angle orientation */ { y1 = yc2 - y1; y2 = yc2 - y2; } simfLineThin(canvas, x1, y1, x2, y2, &last_xi_a, &last_yi_a, &last_xi_b, &last_yi_b); canvas->use_matrix = old_use_matrix; } prev_x = x; prev_y = y; } if (poly) { canvas->cxPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, p); free(poly); } else simLineStyleNoReset = 0; }
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); }
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); }
static void cdSimElipse(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2, int sector) { cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; float c, s, sx, sy, x, y, prev_x, prev_y; double da; int i, p, yc2 = 2*yc; cdPoint* poly; /* number of segments of equivalent poligonal for a full ellipse */ int n = simCalcEllipseNumSegments(canvas, xc, yc, width, height); /* number of segments for the arc */ n = cdRound(((angle2-angle1)*n)/360); if (n < 1) n = 1; poly = (cdPoint*)malloc(sizeof(cdPoint)*(n+2+1)); /* n+1 points +1 center */ /* converts degrees into radians */ angle1 *= CD_DEG2RAD; angle2 *= CD_DEG2RAD; /* generates arc points at origin with axis x and y */ da = (angle2-angle1)/n; c = (float)cos(da); s = (float)sin(da); sx = -(width*s)/height; sy = (height*s)/width; x = xc + (width/2.0f)*(float)cos(angle1); y = yc + (height/2.0f)*(float)sin(angle1); prev_x = x; prev_y = y; poly[0].x = _cdRound(x); poly[0].y = _cdRound(y); if (canvas->invert_yaxis) poly[0].y = yc2 - poly[0].y; p = 1; for (i = 1; i < n+1; i++) /* n+1 points */ { x = xc + c*(prev_x-xc) + sx*(prev_y-yc); y = yc + sy*(prev_x-xc) + c*(prev_y-yc); poly[p].x = _cdRound(x); poly[p].y = _cdRound(y); if (canvas->invert_yaxis) poly[p].y = yc2 - poly[p].y; if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y) p++; prev_x = x; prev_y = y; } if (poly[p-1].x != poly[0].x || poly[p-1].y != poly[0].y) { if (sector) /* cdSector */ { /* add center */ poly[p].x = xc; poly[p].y = yc; } else /* cdChord */ { /* add initial point */ poly[p].x = poly[0].x; poly[p].y = poly[0].y; } p++; } canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, p); free(poly); }
int wdCanvasFont(cdCanvas* canvas, const char* type_face, int style, double size_mm) { return cdCanvasFont(canvas, type_face, style, cdRound(size_mm*CD_MM2PT)); }
static int sScaleX(int x) { return cdRound(x * factorX + offsetX); }