#ifndef lint static char sccsid[] = "@(#)stroke.c 9.2 88/01/19 Copyright 1985 Sun Micro"; #endif /* * Copyright (c) 1985 by Sun Microsystems, Inc. */ /*- Routines to deal with stroking paths. stroke.c, Fri Sep 20 14:52:56 1985 James Gosling, Sun Microsystems */ #ifdef GPROF_HOOKS asm(".globl gP_StrokeLoopTop, gP_StrokeCurvedPath, gP_StrokeDefault"); asm(".globl gP_DoClosePath, gP_DoMoveTo"); #endif #ifdef REF #include #include #endif #include "shape.h" #include "canvas.h" #include "cursor.h" /* TODO: Worry about linewidth and miterlimit for cursor removal */ extern struct shape_dcurve *shape_dcurvepath(); #define cs_checkcursorfpoints(cv, p1, p2) \ /*struct canvas *cv;*/ \ /*struct fpoint p1, p2;*/ \ { \ short left, top, width, height; \ if (cv_cursor.up) { \ if ((p1).x < (p2).x) { \ left = cfloorfr((p1).x); \ width = cfloorfr((p2).x) - left + 1; \ } else { \ left = cfloorfr((p2).x); \ width = cfloorfr((p1).x) - left + 1; \ } \ if ((p1).y < (p2).y) { \ top = cfloorfr((p1).y); \ height = cfloorfr((p2).y) - top + 1; \ } else { \ top = cfloorfr((p2).y); \ height = cfloorfr((p1).y) - top + 1; \ } \ cs_checkcursor((cv), left, top, width, height); \ } \ } cs_stroke(gc) register struct graphics_context *gc; { if (gc->clip != ((struct canvas *)gc->canvas)->lastclip && cv_is_canvas(gc->canvas)) cv_validate_clip(gc->canvas, gc->clip); if (gc->path.straight) { register n; register struct path_element *p; register struct path_element *prev = 0, *first = 0; register color = PIX_OPCOLOR(gc->func); register op = gc->func & 0x1E; p = &gc->path.element[gc->path.startpos]; n = gc->path.used - gc->path.startpos; #ifdef GPROF_HOOKS asm("gP_StrokeLoopTop:"); #endif while (--n >= 0) { switch (p->variation) { case MOVE_TO_FLAG: #ifdef GPROF_HOOKS asm("gP_DoMoveTo:"); #endif prev = p; first = p; break; case CLOSEPATH_FLAG: #ifdef GPROF_HOOKS asm("gP_DoClosePath:"); #endif if (prev && first) { cs_checkcursorfpoints(gc->canvas, prev->pos, first->pos); pr_vector(gc->canvas, cfloorfr(prev->pos.x), cfloorfr(prev->pos.y), cfloorfr(first->pos.x), cfloorfr(first->pos.y), op, color); } prev = 0; first = 0; break; default: #ifdef GPROF_HOOKS asm("gP_StrokeDefault:"); #endif if (prev) { cs_checkcursorfpoints(gc->canvas, prev->pos, p->pos); pr_vector(gc->canvas, cfloorfr(prev->pos.x), cfloorfr(prev->pos.y), cfloorfr(p->pos.x), cfloorfr(p->pos.y), op, color); } else first = p; prev = p; break; } p++; } } else { register struct shape_dcurve *c; register struct shape_dcurve *ct; register short left, right; #ifdef GPROF_HOOKS asm("gP_StrokeCurvedPath:"); #endif c = shape_dcurvepath(path_to_arc(&gc->path, 0)); if (c) { c->refcnt = 1; /* * Take advanage for the fact that we know the left & right of * of the curve to reduce the affected area of the cursor damage. * Have to cycle through curve list to determine left & right. */ left = c->left; right = c->right; for (ct = c; ct; ct = ct->next) { if (ct->right > right) right = ct->right; if (ct->left < left) left = ct->left; } cs_checkcursordims(gc->canvas, left, 0, right - left + 1, ((struct canvas *)gc->canvas)->pixrect.pr_height); pr_shapecurve(gc->canvas, &InfiniteShape, c, gc->func, gc->texture, 0); if (--c->refcnt<=0) shape_freecurve(c); } } cs_newpath(gc); } cs_frsetdash(gc,texture,offset) register struct graphics_context *gc; register fract *texture; fract offset; { /* * sometime, this will have to deal with transforms */ if (texture == 0) gc->texture[0] = 0; else { #ifdef undef /*- An old, possibly useful, fragment of code: */ if (o->type == fixed_type) cs_frdtransform(&ee->gontext,o->value.fixed,0, shape_point.x,shape_point.y); else if (o->type == real_type) cs_fldtransform(&ee->gontext,o->value.real,0, shape_point.x,shape_point.y); else goto typecheck_error; if (shape_point.y == 0) *d++ = roundfr(shape_point.x); else if (shape_point.x == 0) *d++ = roundfr(shape_point.y); else *d++ = frsqrt(frmul(shape_point.x,shape_point.x) + frmul(shape_point.y,shape_point.y)); #endif bcopy(texture, gc->texture, sizeof gc->texture); gc->texture[sizeof gc->texture / sizeof gc->texture[0] - 1] = 0; } gc->offset = roundfr(offset); gc->textrevision = -3; }