Esempio n. 1
0
static cdPoint* sPolyAddArc(cdCanvas* canvas, cdPoint* poly, int *n, int xc, int yc, int width, int height, double angle1, double angle2, cdPoint* current)
{
  double c, s, sx, sy, x, y, prev_x, prev_y;
  double da;
  int i, K, k, p, new_n;
  cdPoint* old_poly = poly;

  sFixAngles(canvas, &angle1, &angle2);

  /* number of segments for the arc */
  K = sCalcEllipseNumSegments(canvas, xc, yc, width, height, angle1, angle2);

  new_n = *n + K+1;  /* add room for K+1 samples */
  poly = (cdPoint*)realloc(poly, sizeof(cdPoint)*(new_n+2));  /* add room also for points at start and end */
  if (!poly) {free(old_poly); return NULL;}
  i = *n;

  /* generates arc points at origin with axis x and y */

  da = (angle2-angle1)/K;
  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 (current)
  {
    poly[i] = *current;
    i++;
    new_n++;  /* no need to reallocate */
  }

  poly[i].x = _cdRound(x)+xc;
  poly[i].y = _cdRound(y)+yc;

  p = i+1;
  for (k = 1; k < K+1; k++)
  {
    x =  c*prev_x + sx*prev_y;
    y = sy*prev_x +  c*prev_y;

    poly[p].x = _cdRound(x)+xc;
    poly[p].y = _cdRound(y)+yc;

    if (poly[p-1].x != poly[p].x || 
        poly[p-1].y != poly[p].y)
      p++;

    prev_x = x;
    prev_y = y;
  }

  *n = new_n;
  return poly;
}
Esempio n. 2
0
static cdPoint* sPolyAddBezier(cdCanvas* canvas, cdPoint* poly, int *n, cdPoint start, const cdPoint* points)
{
  int k, K, new_n, i;
  cdfPoint pt;
  cdfPoint bezier_control[4];
  cdPoint* old_poly = poly;

  sBezierForm(start, points, bezier_control);
  K = sBezierNumSegments(canvas, start, points);

  new_n = *n + K+1;  /* add room for K+1 samples */
  poly = realloc(poly, sizeof(cdPoint)*new_n);
  if (!poly) {free(old_poly); return NULL;}
  i = *n;

  /* first segment */
  sBezierCurve(bezier_control, &pt, 0);

  poly[i].x = _cdRound(pt.x);
  poly[i].y = _cdRound(pt.y);

  for(k = 1; k < K+1; k++) 
  {
    sBezierCurve(bezier_control, &pt, (double)k/(double)K);

    poly[i+k].x = _cdRound(pt.x);
    poly[i+k].y = _cdRound(pt.y);
  }

  *n = new_n;
  return poly;
}
Esempio n. 3
0
void cdfCanvasArc(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2)
{
  assert(canvas);
  if (!_cdCheckCanvas(canvas)) return;

  if (angle1 == angle2 || w == 0 || h == 0)
    return;

  sNormAngles(&angle1, &angle2);

  if (canvas->use_origin)
  {
    xc += canvas->forigin.x;
    yc += canvas->forigin.y;
  }

  if (canvas->invert_yaxis)
    yc = _cdInvertYAxis(canvas, yc);


  if (canvas->cxFArc)
    canvas->cxFArc(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2);
  else
    canvas->cxArc(canvas->ctxcanvas, _cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), angle1, angle2);
}
Esempio n. 4
0
static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
{
  int i;
  tPrimNode *prim;
  if (mode == CD_CLIP || mode == CD_REGION) return;
  if (mode == CD_PATH)
  {
    cdfpath(ctxcanvas, poly, n);
    return;
  }
  prim = primCreate(CDPIC_FPOLY);
  if (mode == CD_FILL)
    primAddAttrib_Fill(prim, ctxcanvas->canvas);
  else
    primAddAttrib_Line(prim, ctxcanvas->canvas);
  prim->param.polyf.mode = mode;
  prim->param.polyf.n = n;
  prim->param.polyf.points = malloc(n * sizeof(cdfPoint));
  memcpy(prim->param.polyf.points, poly, n * sizeof(cdfPoint));
  prim->param_buffer = prim->param.polyf.points;
  picAddPrim(ctxcanvas, prim);

  for (i = 0; i < n; i++)
  {
    if (mode == CD_FILL)
      picUpdateBBox(ctxcanvas, _cdRound(poly[i].x), _cdRound(poly[i].y), 0);
    else
      picUpdateBBox(ctxcanvas, _cdRound(poly[i].x), _cdRound(poly[i].y), ctxcanvas->canvas->line_width);
  }
}
Esempio n. 5
0
void cdfCanvasBox(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax)
{
  assert(canvas);
  if (!_cdCheckCanvas(canvas)) return;

  if (canvas->interior_style == CD_HOLLOW)
  {
    cdfCanvasRect(canvas, xmin, xmax, ymin, ymax);
    return;
  }

  if (!cdfCheckBoxSize(&xmin, &xmax, &ymin, &ymax))
    return;

  if (canvas->use_origin)
  {
    xmin += canvas->forigin.x;
    xmax += canvas->forigin.x;
    ymin += canvas->forigin.y;
    ymax += canvas->forigin.y;
  }

  if (canvas->invert_yaxis)
  {
    ymin = _cdInvertYAxis(canvas, ymin);
    ymax = _cdInvertYAxis(canvas, ymax);
    _cdSwapDouble(ymin, ymax);
  }

  if (canvas->cxFBox)
    canvas->cxFBox(canvas->ctxcanvas, xmin, xmax, ymin, ymax);
  else
    canvas->cxBox(canvas->ctxcanvas, _cdRound(xmin), _cdRound(xmax), _cdRound(ymin), _cdRound(ymax));
}
Esempio n. 6
0
static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *text, int len)
{
  int xmin, xmax, ymin, ymax;
  tPrimNode *prim = primCreate(CDPIC_FTEXT);
  primAddAttrib_Text(prim, ctxcanvas->canvas);
  prim->param.textf.x = x;
  prim->param.textf.y = y;
  prim->param.textf.s = cdStrDupN(text, len);
  prim->param_buffer = prim->param.textf.s;
  picAddPrim(ctxcanvas, prim);
  cdCanvasGetTextBox(ctxcanvas->canvas, _cdRound(x), _cdRound(y), prim->param.text.s, &xmin, &xmax, &ymin, &ymax);
  picUpdateBBox(ctxcanvas, xmin, ymin, 0);
  picUpdateBBox(ctxcanvas, xmax, ymax, 0);
}
Esempio n. 7
0
static void cdfpath(cdCtxCanvas *ctxcanvas, cdfPoint* poly, int n)
{
  int i, p, fill = -1;
  tPrimNode *prim;

  for (p=0; p<ctxcanvas->canvas->path_n; p++)
  {
    if (ctxcanvas->canvas->path[p] == CD_PATH_CLIP)
      return;
    else if (ctxcanvas->canvas->path[p] == CD_PATH_FILL ||
             ctxcanvas->canvas->path[p] == CD_PATH_FILLSTROKE)  /* no support for both in cdPicture */
    {
      fill = 1;
      break;
    }
    else if (ctxcanvas->canvas->path[p] == CD_PATH_STROKE)
    {
      fill = -1;
      break;
    }
  }

  if (fill == -1)
    return;

  prim = primCreate(CDPIC_FPATH);
  prim->param.pathf.fill = fill;

  if (fill)
    primAddAttrib_Fill(prim, ctxcanvas->canvas);
  else
    primAddAttrib_Line(prim, ctxcanvas->canvas);

  prim->param_buffer = malloc(n * sizeof(cdfPoint) + ctxcanvas->canvas->path_n * sizeof(int));

  prim->param.pathf.n = n;
  prim->param.pathf.points = (cdfPoint*)prim->param_buffer;
  memcpy(prim->param.pathf.points, poly, n * sizeof(cdfPoint));
  prim->param.pathf.path = (int*)((unsigned char*)prim->param_buffer + n * sizeof(cdfPoint));
  memcpy(prim->param.pathf.path, ctxcanvas->canvas->path, ctxcanvas->canvas->path_n * sizeof(int));
  prim->param.pathf.path_n = ctxcanvas->canvas->path_n;
  
  picAddPrim(ctxcanvas, prim);

  for (i = 0; i < n; i++)
  {
    picUpdateBBox(ctxcanvas, _cdRound(poly[i].x), _cdRound(poly[i].y), 0);
  }
}
Esempio n. 8
0
static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
  int xmin, xmax, ymin, ymax;
  tPrimNode *prim = primCreate(CDPIC_FCHORD);
  primAddAttrib_Fill(prim, ctxcanvas->canvas);
  prim->param.arcsectorchordf.xc = xc;
  prim->param.arcsectorchordf.yc = yc;
  prim->param.arcsectorchordf.w = w;
  prim->param.arcsectorchordf.h = h;
  prim->param.arcsectorchordf.angle1 = a1;
  prim->param.arcsectorchordf.angle2 = a2;
  picAddPrim(ctxcanvas, prim);
  cdCanvasGetArcBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
  picUpdateBBox(ctxcanvas, xmin, ymin, 0);
  picUpdateBBox(ctxcanvas, xmax, ymax, 0);
}
Esempio n. 9
0
void cdfCanvasSector(cdCanvas* canvas, double xc, double yc, double w, double 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)
  {
    cdfCanvasArc(canvas, xc, yc, w, h, angle1, angle2);

    if (fabs(angle2-angle1) < 360)
    {
      double xi,yi,xf,yf;
      
      xi = xc + w*cos(CD_DEG2RAD*angle1)/2.0;
      yi = yc + h*sin(CD_DEG2RAD*angle1)/2.0;
      
      xf = xc + w*cos(CD_DEG2RAD*angle2)/2.0;
      yf = yc + h*sin(CD_DEG2RAD*angle2)/2.0;

      cdfCanvasLine(canvas, xi, yi, xc, yc);
      cdfCanvasLine(canvas, xc, yc, xf, yf);
    }

    return;
  }

  if (canvas->use_origin)
  {
    xc += canvas->forigin.x;
    yc += canvas->forigin.y;
  }

  if (canvas->invert_yaxis)
    yc = _cdInvertYAxis(canvas, yc);

  if (canvas->cxFSector)
    canvas->cxFSector(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2);
  else
    canvas->cxSector(canvas->ctxcanvas, _cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), angle1, angle2);
}
Esempio n. 10
0
void cdfCanvasVertex(cdCanvas* canvas, double x, double y)
{
  assert(canvas);
  if (!_cdCheckCanvas(canvas)) return;

  if (!canvas->cxFPoly)
  {
    cdCanvasVertex(canvas, _cdRound(x), _cdRound(y));
    return;
  }

  if (canvas->use_fpoly == 0) return; /* real vertex inside a integer polygon */

  if (!canvas->fpoly)
  {
    canvas->fpoly = (cdfPoint*)malloc(sizeof(cdfPoint)*(_CD_POLY_BLOCK+1));
    canvas->fpoly_size = _CD_POLY_BLOCK;
  }

  canvas->use_fpoly = 1;

  if (!sCheckPathArc(canvas))
  {
    if (canvas->use_origin)
    {
      x += canvas->forigin.x;
      y += canvas->forigin.y;
    }

    if (canvas->invert_yaxis)
      y = _cdInvertYAxis(canvas, y);
  }

  if (canvas->poly_n == canvas->fpoly_size)
  {
    canvas->fpoly_size += _CD_POLY_BLOCK;
    canvas->fpoly = (cdfPoint*)realloc(canvas->fpoly, sizeof(cdfPoint) * (canvas->fpoly_size+1));
  }

  canvas->fpoly[canvas->poly_n].x = x;
  canvas->fpoly[canvas->poly_n].y = y;
  canvas->poly_n++;
}
Esempio n. 11
0
void cdfSimPutImageRectRGBA(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 size, i, j, dst, src, *fx, *fy, rw, rh;
  unsigned char *ar, *ag, *ab, al;
  int zw = _cdRound(w);
  int zh = _cdRound(h);
  (void)ih;

  size = zw * zh;
  ar = (unsigned char*)malloc(size * 3);
  if (!ar) return;
  ag = ar + size;
  ab = ag + size;

  canvas->cxGetImageRGB(canvas->ctxcanvas, ar, ag, ab, _cdRound(x), _cdRound(y), zw, zh);

  rw = xmax - xmin + 1;
  rh = ymax - ymin + 1;

  fx = cdGetZoomTable(zw, rw, xmin);
  fy = cdGetZoomTable(zh, rh, ymin);

  for (j = 0; j < zh; j++)
  {
    for (i = 0; i < zw; i++)
    {
      dst = j * zw + i;
      src = fy[j] * iw + fx[i];
      al = a[src];
      ar[dst] = CD_ALPHA_BLEND(r[src], ar[dst], al);
      ag[dst] = CD_ALPHA_BLEND(g[src], ag[dst], al);
      ab[dst] = CD_ALPHA_BLEND(b[src], ab[dst], al);
    }
  }

  canvas->cxFPutImageRectRGB(canvas->ctxcanvas, zw, zh, ar, ag, ab, x, y, w, h, 0, 0, 0, 0);

  free(ar);

  free(fx);
  free(fy);
}
Esempio n. 12
0
void cdfCanvasLine(cdCanvas* canvas, double x1, double y1, double x2, double y2)
{
  assert(canvas);
  if (!_cdCheckCanvas(canvas)) return;

  if (x1 == x2 && y1 == y2)
  {
    cdCanvasPixel(canvas, _cdRound(x1), _cdRound(y1), canvas->foreground);
    return;
  }
    
  if (canvas->use_origin)
  {
    x1 += canvas->forigin.x;
    y1 += canvas->forigin.y;
    x2 += canvas->forigin.x;
    y2 += canvas->forigin.y;
  }

  if (canvas->invert_yaxis)
  {
    y1 = _cdInvertYAxis(canvas, y1);
    y2 = _cdInvertYAxis(canvas, y2);
  }

  if (canvas->cxFLine)
    canvas->cxFLine(canvas->ctxcanvas, x1, y1, x2, y2);
  else
    canvas->cxLine(canvas->ctxcanvas, _cdRound(x1), _cdRound(y1), _cdRound(x2), _cdRound(y2));
}
Esempio n. 13
0
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);
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
void cdfSimMark(cdCanvas* canvas, double x, double y)
{
  int oldinteriorstyle = canvas->interior_style;
  int oldlinestyle = canvas->line_style;
  int oldlinewidth = canvas->line_width;
  double size, half_size, bottom, top, left, right;

  if (canvas->mark_type == CD_DIAMOND ||
      canvas->mark_type == CD_HOLLOW_DIAMOND)
  {
    if (canvas->use_origin)
    {
      x += canvas->forigin.x;
      y += canvas->forigin.y;
    }

    if (canvas->invert_yaxis)
      y = _cdInvertYAxis(canvas, y);
  }

  size = (double)canvas->mark_size;
  half_size = size / 2;
  bottom = y - half_size;
  top = y + half_size;
  left = x - half_size;
  right = x + half_size;

  if (canvas->interior_style != CD_SOLID &&
      (canvas->mark_type == CD_CIRCLE ||
      canvas->mark_type == CD_BOX ||
      canvas->mark_type == CD_DIAMOND))
      cdCanvasInteriorStyle(canvas, CD_SOLID);

  if (canvas->line_style != CD_CONTINUOUS &&
      (canvas->mark_type == CD_STAR ||
      canvas->mark_type == CD_PLUS ||
      canvas->mark_type == CD_X ||
      canvas->mark_type == CD_HOLLOW_BOX ||
      canvas->mark_type == CD_HOLLOW_CIRCLE ||
      canvas->mark_type == CD_HOLLOW_DIAMOND))
      cdCanvasLineStyle(canvas, CD_CONTINUOUS);

  if (canvas->line_width != 1 &&
      (canvas->mark_type == CD_STAR ||
      canvas->mark_type == CD_PLUS ||
      canvas->mark_type == CD_X ||
      canvas->mark_type == CD_HOLLOW_BOX ||
      canvas->mark_type == CD_HOLLOW_CIRCLE ||
      canvas->mark_type == CD_HOLLOW_DIAMOND))
      cdCanvasLineWidth(canvas, 1);

  switch (canvas->mark_type)
  {
  case CD_STAR:
    cdfCanvasLine(canvas, left, bottom, right, top);
    cdfCanvasLine(canvas, left, top, right, bottom);
    /* continue */
  case CD_PLUS:
    cdfCanvasLine(canvas, left, y, right, y);
    cdfCanvasLine(canvas, x, bottom, x, top);
    break;
  case CD_X:
    cdfCanvasLine(canvas, left, bottom, right, top);
    cdfCanvasLine(canvas, left, top, right, bottom);
    break;
  case CD_HOLLOW_CIRCLE:
    cdfCanvasArc(canvas, x, y, size, size, 0, 360);
    break;
  case CD_HOLLOW_BOX:
    cdfCanvasRect(canvas, left, right, bottom, top);
    break;
  case CD_CIRCLE:
    cdfCanvasSector(canvas, x, y, size, size, 0, 360);
    break;
  case CD_BOX:
    cdfCanvasBox(canvas, left, right, bottom, top);
    break;
  case CD_HOLLOW_DIAMOND:
  case CD_DIAMOND:
      /* Do not use Begin/End here so Mark can be used inside a regular BeginEnd loop */
      if (!canvas->cxFPoly)
      {
        cdPoint poly[5];  /* leave room for one more point */
        poly[0].x = _cdRound(left);
        poly[0].y = _cdRound(y);
        poly[1].x = _cdRound(x);
        poly[1].y = _cdRound(top);
        poly[2].x = _cdRound(right);
        poly[2].y = _cdRound(y);
        poly[3].x = _cdRound(x);
        poly[3].y = _cdRound(bottom);

        if (canvas->mark_type == CD_DIAMOND)
          cdPoly(canvas, CD_FILL, poly, 4);
        else
          cdPoly(canvas, CD_CLOSED_LINES, poly, 4);
      }
      else
      {
        cdfPoint poly[5];  /* leave room for one more point */
        poly[0].x = left;
        poly[0].y = y;
        poly[1].x = x;
        poly[1].y = top;
        poly[2].x = right;
        poly[2].y = y;
        poly[3].x = x;
        poly[3].y = bottom;

        if (canvas->mark_type == CD_DIAMOND)
          canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, poly, 4);
        else
          canvas->cxFPoly(canvas->ctxcanvas, CD_CLOSED_LINES, poly, 4);
      }
    break;
  }

  if (canvas->interior_style != oldinteriorstyle &&
      (canvas->mark_type == CD_CIRCLE ||
      canvas->mark_type == CD_BOX ||
      canvas->mark_type == CD_DIAMOND))
      cdCanvasInteriorStyle(canvas, oldinteriorstyle);

  if (canvas->line_style != oldlinestyle &&
      (canvas->mark_type == CD_STAR ||
      canvas->mark_type == CD_PLUS ||
      canvas->mark_type == CD_X ||
      canvas->mark_type == CD_HOLLOW_BOX ||
      canvas->mark_type == CD_HOLLOW_CIRCLE ||
      canvas->mark_type == CD_HOLLOW_DIAMOND))
      cdCanvasLineStyle(canvas, oldlinestyle);

  if (canvas->line_width != oldlinewidth &&
      (canvas->mark_type == CD_STAR ||
      canvas->mark_type == CD_PLUS ||
      canvas->mark_type == CD_X ||
      canvas->mark_type == CD_HOLLOW_BOX ||
      canvas->mark_type == CD_HOLLOW_CIRCLE ||
      canvas->mark_type == CD_HOLLOW_DIAMOND))
      cdCanvasLineWidth(canvas, oldlinewidth);
}