/* Don't bother to update the cbox. */ int gx_path_translate(gx_path * ppath, fixed dx, fixed dy) { segment *pseg; #define update_xy(pt)\ pt.x += dx, pt.y += dy if (ppath->box_last != 0) { update_xy(ppath->bbox.p); update_xy(ppath->bbox.q); } if (path_position_valid(ppath)) update_xy(ppath->position); for (pseg = (segment *) (ppath->first_subpath); pseg != 0; pseg = pseg->next ) switch (pseg->type) { case s_curve: #define pcseg ((curve_segment *)pseg) update_xy(pcseg->p1); update_xy(pcseg->p2); #undef pcseg default: update_xy(pseg->pt); } #undef update_xy return 0; }
/* Read the current point of a path. */ int gx_path_current_point(const gx_path * ppath, gs_fixed_point * ppt) { if (!path_position_valid(ppath)) return_error(gs_error_nocurrentpoint); /* Copying the coordinates individually */ /* is much faster on a PC, and almost as fast on other machines.... */ ppt->x = ppath->position.x, ppt->y = ppath->position.y; return 0; }
/* Add a relative point to the current path (rmoveto). */ int gx_path_add_relative_point(gx_path * ppath, fixed dx, fixed dy) { if (!path_position_in_range(ppath)) return_error((path_position_valid(ppath) ? gs_error_limitcheck : gs_error_nocurrentpoint)); { fixed nx = ppath->position.x + dx, ny = ppath->position.y + dy; /* Check for overflow in addition. */ if (((nx ^ dx) < 0 && (ppath->position.x ^ dx) >= 0) || ((ny ^ dy) < 0 && (ppath->position.y ^ dy) >= 0) ) return_error(gs_error_limitcheck); if (ppath->bbox_set) check_in_bbox(ppath, nx, ny); ppath->position.x = nx; ppath->position.y = ny; } path_update_moveto(ppath); return 0; }
/* Internal routine for adding an arc to the path. */ static int arc_add(const arc_curve_params_t * arc, bool is_quadrant) { gx_path *path = arc->ppath; gs_imager_state *pis = arc->pis; double x0 = arc->p0.x, y0 = arc->p0.y; double xt = arc->pt.x, yt = arc->pt.y; floatp fraction; gs_fixed_point p0, p2, p3, pt; int code; if ((arc->action != arc_nothing && #if !PRECISE_CURRENTPOINT (code = gs_point_transform2fixed(&pis->ctm, x0, y0, &p0)) < 0) || (code = gs_point_transform2fixed(&pis->ctm, xt, yt, &pt)) < 0 || (code = gs_point_transform2fixed(&pis->ctm, arc->p3.x, arc->p3.y, &p3)) < 0 #else (code = gs_point_transform2fixed_rounding(&pis->ctm, x0, y0, &p0)) < 0) || (code = gs_point_transform2fixed_rounding(&pis->ctm, xt, yt, &pt)) < 0 || (code = gs_point_transform2fixed_rounding(&pis->ctm, arc->p3.x, arc->p3.y, &p3)) < 0 #endif ) return code; #if PRECISE_CURRENTPOINT if (!path_position_valid(path)) gs_point_transform(arc->p0.x, arc->p0.y, &ctm_only(arc->pis), &pis->subpath_start); #endif code = (arc->action == arc_nothing ? (p0.x = path->position.x, p0.y = path->position.y, 0) : arc->action == arc_lineto && path_position_valid(path) ? gx_path_add_line(path, p0.x, p0.y) : /* action == arc_moveto, or lineto with no current point */ gx_path_add_point(path, p0.x, p0.y)); if (code < 0) return code; /* Compute the fraction coefficient for the curve. */ /* See gx_path_add_partial_arc for details. */ if (is_quadrant) { /* one of |dx| and |dy| is r, the other is zero */ fraction = quarter_arc_fraction; if (arc->fast_quadrant > 0) { /* * The CTM is well-behaved, and we have pre-calculated the delta * from the circumference points to the control points. */ fixed delta = arc->quadrant_delta; if (pt.x != p0.x) p0.x = (pt.x > p0.x ? p0.x + delta : p0.x - delta); if (pt.y != p0.y) p0.y = (pt.y > p0.y ? p0.y + delta : p0.y - delta); p2.x = (pt.x == p3.x ? p3.x : pt.x > p3.x ? p3.x + delta : p3.x - delta); p2.y = (pt.y == p3.y ? p3.y : pt.y > p3.y ? p3.y + delta : p3.y - delta); goto add; } } else { double r = arc->radius; floatp dx = xt - x0, dy = yt - y0; double dist = dx * dx + dy * dy; double r2 = r * r; if (dist >= r2 * 1.0e8) /* almost zero radius; */ /* the >= catches dist == r == 0 */ fraction = 0.0; else fraction = (4.0 / 3.0) / (1 + sqrt(1 + dist / r2)); } p0.x += (fixed)((pt.x - p0.x) * fraction); p0.y += (fixed)((pt.y - p0.y) * fraction); p2.x = p3.x + (fixed)((pt.x - p3.x) * fraction); p2.y = p3.y + (fixed)((pt.y - p3.y) * fraction); add: if_debug8('r', "[r]Arc f=%f p0=(%f,%f) pt=(%f,%f) p3=(%f,%f) action=%d\n", fraction, x0, y0, xt, yt, arc->p3.x, arc->p3.y, (int)arc->action); /* Open-code gx_path_add_partial_arc_notes */ return gx_path_add_curve_notes(path, p0.x, p0.y, p2.x, p2.y, p3.x, p3.y, arc->notes | sn_from_arc); }