#ifndef lint static char sccsid[] = "@(#)cg2_shcrv.c 9.2 88/01/19 Copyright 1985 Sun Micro"; #endif /* * Copyright (c) 1985 by Sun Microsystems, Inc. */ /*- Draw a curve on a cg2 cg2_shrop.c, Feb 1987 */ #ifdef REF #include #include #endif #include "shape.h" #include #include #include #include #include #include "fract.h" static short mrc_lmasktable[] = { 0x0000, 0x8000, 0xC000, 0xE000, 0xF000, 0xF800, 0xFC00, 0xFE00, 0xFF00, 0xFF80, 0xFFC0, 0xFFE0, 0xFFF0, 0xFFF8, 0xFFFC, 0xFFFE }; static short mrc_rmasktable[] = { 0x7FFF, 0x3FFF, 0x1FFF, 0x0FFF, 0x07FF, 0x03FF, 0x01FF, 0x00FF, 0x007F, 0x003F, 0x001F, 0x000F, 0x0007, 0x0003, 0x0001, 0x0000 }; /* In a misguided attempt to take advantage of horizontal runs, I used word mode pixel access. Unfortunatly, the high setup overhead of the rop chips more than makes up for any improvements. Some day this should be converted to use pixel mode access */ cg2_shapecurve(pr, shape, chain, op, texture, phase) struct pixrect *pr; register struct shape_dcurve *chain; struct shape *shape; short *texture; fract phase; { register u_char *bx, *by; register short linebytes, w, color; struct cg2fb *fb; struct cg2pr *dbd; short top, bottom, left, right, xoff, yoff, ropmode, nodst; if (shape == 0) return 0; if (shape->is_rect == 0) return sh_subdivide_curve(pr, shape, chain, op, texture, phase, shape->trapset); top = max(0, shape->pos.y); left = max(0, shape->pos.x); bottom = min(pr->pr_size.y, shape->pos.y + shape->size.y); right = min(pr->pr_size.x, shape->pos.x + shape->size.x); if (top >= bottom || left >= right) return 0; dbd = cg2_d(pr); xoff = dbd->cgpr_offset.x; yoff = dbd->cgpr_offset.y; fb = cg2_fbfrompr(pr); color = PIX_OPCOLOR(op); op = (op >> 1) & 0xF; fb->ppmask.reg = dbd->cgpr_planes; cg2_setfunction(fb, CG2_ALLROP, op); fb->ropcontrol[CG2_ALLROP].ropregs.mrc_pattern = 0; fb->ropcontrol[CG2_ALLROP].prime.ropregs.mrc_source2 = color | (color << 8); /* load color in src */ nodst = (PIXOP_NEEDS_DST(op << 1) == 0); if (nodst) ropmode = PRRWRD; /* load dst when necessary */ else ropmode = PWRWRD; /* but never load src */ fb->status.reg.ropmode = PWRWRD; /* ld dst for mask */ linebytes = cg2_linebytes(fb, PWRWRD); for (; chain; chain = chain->next) { register xp = chain->x0; register short *p = chain->x + 1; short y = chain->y0; short *ylimit; ylimit = p + (min(bottom - 1, chain->y1) - chain->y0); { register temp; if ((temp = chain->y0 - top) < 0) { p -= temp; y = top; if (p > ylimit) continue; xp = p[-1]; } } if (xp < *p) xp--; else if (xp > *p) xp++; by = (u_char *) cg2_ropwordaddr(fb, 0, 0, y + yoff); while (p <= ylimit) { register delta; register x = *p++; if ((delta = x - xp) == 0) { w = 1; while (p < ylimit && *p == xp) w++, p++; #define X(x) (*(short *) (by+(((x)>>3)&~1))) if (left <= xp && xp < right) { xp += xoff; fb->ropcontrol[CG2_ALLROP].ropregs.mrc_mask1 = mrc_lmasktable[xp & 0xF]; fb->ropcontrol[CG2_ALLROP].ropregs.mrc_mask2 = mrc_rmasktable[xp & 0xF]; cg2_setwidth(fb, CG2_ALLROP, 0, 0); cg2_setshift(fb, CG2_ALLROP, 0, 1); while (w-- != 0) { X(xp) = color; by += linebytes; } } else by += linebytes * w; } else { if (delta < 0) { xp = x; delta = -delta; if (delta > 1 && x == *p) { /* pimple */ delta--; xp++; } } else { xp++; if (delta > 1 && x == *p) delta--; } if (xp < left) { delta += xp - left; xp = left; } if (xp + delta > right) delta = right - xp; if (delta > 0) { xp += xoff; fb->ropcontrol[CG2_ALLROP].ropregs.mrc_mask1 = mrc_lmasktable[xp & 0xF]; fb->ropcontrol[CG2_ALLROP].ropregs.mrc_mask2 = mrc_rmasktable[(xp + delta - 1) & 0xF]; w = (delta + cg2_prskew(xp) - 1) >> 4; cg2_setwidth(fb, CG2_ALLROP, w, w); cg2_setshift(fb, CG2_ALLROP, 0, 1); switch (w) { case 0: X(xp) = color; break; case 1: X(xp) = color; (&X(xp))[1] = color; break; default: bx = (u_char *) &X(xp); if (nodst) { cg2_setwidth(fb, CG2_ALLROP, 2, 2); w -= 2; *((short *) bx)++ = color; *((short *) bx)++ = color; fb->status.reg.ropmode = ropmode; rop_fastloop(w, *((short *) bx)++ = color); fb->status.reg.ropmode = PWRWRD; } else { rop_fastloop(w, *((short *) bx)++ = color); } *((short *) bx)++ = color; } } by += linebytes; } xp = x; } } return 0; }