#ifndef lint static char sccsid[] = "@(#)arcs.c 9.2 88/01/19 Copyright 1985 Sun Micro"; #endif /* * Copyright (c) 1985 by Sun Microsystems, Inc. */ /*- Routines to add arc segments to a path arcs.c, Thu Sep 19 18:09:49 1985 Craig Taylor & James Gosling Sun Microsystems */ #ifdef REF #include #include #endif #include "cscript.h" /* * Generate a circular arc: Pass in environment, operand stack and * counterclockwise flag. */ shape_arc(gc, x, y, r, a1, a2, ccw) register struct graphics_context *gc; fract x, y, r, a1, a2; { struct fpoint pa, pb, pc; register fract ae, v, p; register scale = 0; /* * watch out for things like a1 = -180, a2 = 180 */ if (r <= 0) if (r == 0) return; else { r = -r; ae = a2; a2 = a1; a1 = ae; } if (a1 == a2) return; /* Normalize the angles */ if (floorfr(a1) > 360) a1 = a1 % fracti(360); if (floorfr(a2) > 360) a2 = a2 % fracti(360); while (r > fracti(127)) { scale++; r >>= 1; } while (a1 < 0) a1 += fracti(360); while (a2 < 0) a2 += fracti(360); /* * Prime the pump with the A point so that the remaining elements share * common endpoints at AC. */ frsincosd(a1, &pc.y, &pc.x); pc.x = frmul(pc.x, r); pc.y = frmul(pc.y, r); if (cs_hascurrentpoint(gc)) cs_frlineto(gc, (pc.x << scale) + x, (pc.y << scale) + y); else cs_frmoveto(gc, (pc.x << scale) + x, (pc.y << scale) + y); /* Generate ABC triangles in 90deg intervals */ ae = a1; do { pa = pc; /* Copy the common endpoint */ if (fracti(90) <= (ccw ? (a1 < a2 ? a2 - a1 : fracti(360) + a2 - a1) : (a2 < a1 ? a1 - a2 : fracti(360) + a1 - a2))) { ae = a1 / fracti(90) * fracti(90) + fracti(ccw ? 90 : -90); if (ae > fracti(360)) ae = ae % fracti(360); if (ae < 0) ae = fracti(360) + ae; } else ae = a2; frsincosd(ae, &pc.y, &pc.x); pc.x = frmul(pc.x, r); pc.y = frmul(pc.y, r); p = ae - a1; if (abs(p) == fracti(90)) { pb.x = pa.x + pc.x; pb.y = pa.y + pc.y; v = frrsh(FRSQRT2, 1); } else { register fract denom; denom = frmul(pa.x, pa.x + pc.x) + frmul(pa.y, pa.y + pc.y); if (denom == 0) p = 0; else p = frdiv(frmul(pa.x, pa.x) + frmul(pa.y, pa.y), denom); pb.x = frmul(p, pa.x + pc.x); pb.y = frmul(p, pa.y + pc.y); denom = frlsh(frsqrt(frsq(pa.x - pb.x) + frsq(pa.y - pb.y)), 1); if (denom == 0) v = 0; else v = frdiv(frsqrt(frsq(pa.x - pc.x) + frsq(pa.y - pc.y)), denom); } cs_frlineby(gc, (pb.x << scale) + x, (pb.y << scale) + y, v); cs_frlineto(gc, (pc.x << scale) + x, (pc.y << scale) + y); a1 = ae; } while (ae != a2); } cs_frarcto(gc, x2, y2, x3, y3, r, pxt1, pyt1, pxt2, pyt2) register struct graphics_context *gc; fract x2, y2, x3, y3, r; fract *pxt1, *pyt1, *pxt2, *pyt2; { fract xt1, yt1, xt2, yt2; /* if (!has_current_pos(&ee->path)) goto nocurrentpoint_error; */ sh_fritransform(&gc->transform, gc->currentpoint.x, gc->currentpoint.y); shape_point.x -= x2; shape_point.y -= y2; x3 -= x2; y3 -= y2; /* INRANGE(f) == -128.0