📄 devarc.c
字号:
else drawrow(slice->psd, slice->x0 + x0, slice->x0 + x1, slice->y0); return; } /* clip left edge / line */ ret = clip_line(slice, slice->ax, slice->ay, slice->adir, y, &x0, &x1); if (dbl) { if (!ret) { /* edges separate line to two parts */ if (gr_fillmode != MWFILL_SOLID && mode) ts_drawrow(slice->psd, slice->x0 + x0, slice->x0 + x1, slice->y0 + y); else drawrow(slice->psd, slice->x0 + x0, slice->x0 + x1, slice->y0 + y); x0 = x2; x1 = x3; } } else { if (ret > 1) { return; } } discard = ret; ret = clip_line(slice, slice->bx, slice->by, slice->bdir, y, &x0, &x1); discard += ret; if (discard > 2 && !(dbl && ret == 0 && discard == 3)) { return; } if (discard == 2) { /* line on other side than slice */ if (slice->adir < 0 || slice->bdir > 0) { return; } } if (gr_fillmode != MWFILL_SOLID && mode) ts_drawrow(slice->psd, slice->x0 + x0, slice->x0 + x1, slice->y0 + y); else drawrow(slice->psd, slice->x0 + x0, slice->x0 + x1, slice->y0 + y);}/* * draw one line segment or set of points, called from drawarc routine * * Note that this is called for all rows in one quadrant of the ellipse. * It mirrors vertically & horizontally to get the entire ellipse. * * It passes on co-ordinates for the *entire* ellipse - for pie and * arc, clipping is done later to ensure that only the requested angle * gets drawn. */static voiddrawarcsegment(SLICE *slice, MWCOORD xp, MWCOORD yp, int drawon){ unsigned long dm = 0, dc = 0; switch (slice->type) { case MWELLIPSEFILL: /* draw ellipse fill segment*/ /* First, save the dash settings, because we don't want to use them here */ if (gr_fillmode != MWFILL_SOLID) { ts_drawrow(slice->psd, slice->x0-xp, slice->x0+xp, slice->y0-yp); ts_drawrow(slice->psd, slice->x0-xp, slice->x0+xp, slice->y0+yp); } else { GdSetDash(&dm, (int *) &dc); /* Must turn off the dash settings because of drawrow() */ drawrow(slice->psd, slice->x0-xp, slice->x0+xp, slice->y0-yp); drawrow(slice->psd, slice->x0-xp, slice->x0+xp, slice->y0+yp); GdSetDash(&dm, (int *) &dc); } return; case MWELLIPSE: if (!drawon) return; /* set four points symmetrically situated around a point*/ drawpoint(slice->psd, slice->x0 + xp, slice->y0 + yp); drawpoint(slice->psd, slice->x0 - xp, slice->y0 + yp); drawpoint(slice->psd, slice->x0 + xp, slice->y0 - yp); drawpoint(slice->psd, slice->x0 - xp, slice->y0 - yp); return; case MWPIE: /* draw top and bottom halfs of pie*/ if (gr_fillmode == MWFILL_SOLID) GdSetDash(&dm, (int *) &dc); draw_line(slice, -xp, -yp, +xp, 1); draw_line(slice, -xp, +yp, +xp, 1); if (gr_fillmode == MWFILL_SOLID) GdSetDash(&dm, (int *) &dc); return; default: /* MWARC, MWARCOUTLINE*/ /* set four points symmetrically around a point and clip*/ draw_line(slice, +xp, +yp, +xp, 0); draw_line(slice, -xp, +yp, -xp, 0); draw_line(slice, +xp, -yp, +xp, 0); draw_line(slice, -xp, -yp, -xp, 0); return; }}/* General routine to plot points on an arc. Used by arc, pie and ellipse*/static voiddrawarc(SLICE *slice){ extern unsigned long gr_dashmask; extern unsigned long gr_dashcount; MWCOORD xp, yp; /* current point (based on center) */ MWCOORD rx, ry; long Asquared; /* square of x semi axis */ long TwoAsquared; long Bsquared; /* square of y semi axis */ long TwoBsquared; long d; long dx, dy; int bit = 0; int drawon = 1; rx = slice->rx; ry = slice->ry; xp = 0; yp = ry; Asquared = rx * rx; TwoAsquared = 2 * Asquared; Bsquared = ry * ry; TwoBsquared = 2 * Bsquared; d = Bsquared - Asquared * ry + (Asquared >> 2); dx = 0; dy = TwoAsquared * ry; if (gr_fillmode != MWFILL_SOLID) set_ts_origin(slice->x0 - rx, slice->y0 - ry); while (dx < dy) { /* * Only draw if one of the following conditions holds: * - We're drawing an outline - i.e. slice->type is * not MWPIE or MWELLIPSEFILL * - We're about to move on to the next Y co-ordinate * (i.e. we're drawing a filled shape and we're at * the widest point for this Y co-ordinate). * This is the case if d (the error term) is >0 * Otherwise, we draw multiple times, which messes up * with SRC_OVER or XOR modes. */ if ((d > 0) || ((slice->type != MWPIE) && (slice->type != MWELLIPSEFILL))) { if (gr_dashcount) { drawon = (gr_dashmask & (1 << bit)) ? 1 : 0; bit = (bit + 1) % gr_dashcount; } else drawon = 1; drawarcsegment(slice, xp, yp, drawon); } if (d > 0) { yp--; dy -= TwoAsquared; d -= dy; } xp++; dx += TwoBsquared; d += (Bsquared + dx); } d += ((3L * (Asquared - Bsquared) / 2L - (dx + dy)) >> 1); while (yp >= 0) { if (gr_dashcount) { drawon = (gr_dashmask & (1 << bit)) ? 1 : 0; bit = (bit + 1) % gr_dashcount; } else drawon = 1; drawarcsegment(slice, xp, yp, drawon); if (d < 0) { xp++; dx += TwoBsquared; d += dx; } yp--; dy -= TwoAsquared; d += (Asquared - dy); }}/** * Draw an arc or pie using start/end points. * Integer only routine. To specify start/end angles, * use GdArcAngle, which requires floating point. * * @param psd Destination surface. * @param x0 Center of arc (X co-ordinate). * @param y0 Center of arc (Y co-ordinate). * @param rx Radius of arc in X direction. * @param ry Radius of arc in Y direction. * @param ax Start of arc (X co-ordinate). * @param ay Start of arc (Y co-ordinate). * @param bx End of arc (X co-ordinate). * @param by End of arc (Y co-ordinate). * @param type Type of arc: * MWARC is a curved line. * MWARCOUTLINE is a curved line plus straight lines joining the ends * to the center of the arc. * MWPIE is a filled shape, like a section of a pie chart. */voidGdArc(PSD psd, MWCOORD x0, MWCOORD y0, MWCOORD rx, MWCOORD ry, MWCOORD ax, MWCOORD ay, MWCOORD bx, MWCOORD by, int type){ MWCOORD adir, bdir; SLICE slice; if (rx <= 0 || ry <= 0) return; /* * Calculate right/left side clipping, based on quadrant. * dir is positive when right side is filled and negative when * left side is to be filled. * * >= 0 is bottom half */ if (ay >= 0) adir = 1; else adir = -1; if (by >= 0) bdir = -1; else bdir = 1; /* * The clip_line routine has problems around the 0 and * 180 degree axes. * This <fix> is required to make the clip_line algorithm * work. Getting these routines to work for all angles is * a bitch. And they're still buggy. Doing this causes * half circles to be outlined with a slightly bent line * on the x axis. FIXME */ if (ay == 0) ++ay; if (by == 0) ++by; /* swap rightmost edge first */ if (bx > ax) { MWCOORD swap; swap = ax; ax = bx; bx = swap; swap = ay; ay = by; by = swap; swap = adir; adir = bdir; bdir = swap; } /* check for entire area clipped, draw with per-point clipping*/ if (GdClipArea(psd, x0-rx, y0-ry, x0+rx, y0+ry) == CLIP_INVISIBLE) return; slice.psd = psd; slice.x0 = x0; slice.y0 = y0; slice.rx = rx; slice.ry = ry; slice.ax = ax; slice.ay = ay; slice.bx = bx; slice.by = by; slice.adir = adir; slice.bdir = bdir; slice.type = type; drawarc(&slice); if (type & MWOUTLINE) { /* draw two lines from rx,ry to arc endpoints*/ GdLine(psd, x0, y0, x0+ax, y0+ay, TRUE); GdLine(psd, x0, y0, x0+bx, y0+by, TRUE); } GdFixCursor(psd);}/** * Draw an ellipse using the current clipping region and foreground color. * This draws in the outline of the ellipse, or fills it. * Integer only routine. * * @param psd Destination surface. * @param x Center of ellipse (X co-ordinate). * @param y Center of ellipse (Y co-ordinate). * @param rx Radius of ellipse in X direction. * @param ry Radius of ellipse in Y direction. * @param fill Nonzero for a filled ellipse, zero for an outline. */voidGdEllipse(PSD psd, MWCOORD x, MWCOORD y, MWCOORD rx, MWCOORD ry, MWBOOL fill){ SLICE slice; if (rx < 0 || ry < 0) return; /* Check if the ellipse bounding box is either totally visible * or totally invisible. Draw with per-point clipping. */ switch (GdClipArea(psd, x - rx, y - ry, x + rx, y + ry)) { case CLIP_VISIBLE: /* * For size considerations, there's no low-level ellipse * draw, so we've got to draw all ellipses * with per-point clipping for the time being psd->DrawEllipse(psd, x, y, rx, ry, fill, gr_foreground); GdFixCursor(psd); return; */ break; case CLIP_INVISIBLE: return; } slice.psd = psd; slice.x0 = x; slice.y0 = y; slice.rx = rx; slice.ry = ry; slice.type = fill? MWELLIPSEFILL: MWELLIPSE; /* other elements unused*/ drawarc(&slice); GdFixCursor(psd);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -