#ifndef lint static char sccsid[] = "@(#)gensh_crv.c 9.3 88/01/19 Copyright 1985 Sun Micro"; #endif /* * Copyright (c) 1985 by Sun Microsystems, Inc. */ /*- Draw a curve given the discrete representation */ #ifdef REF #include #include #endif #include "shape.h" #include #include #include #include "fract.h" extern mem_rop(); /* * Comment this table out for now. It's not used anymore. * static int arclength_table[] = { (int) (1.0000000000 * (1 << 16)), (int) (1.4142135623 * (1 << 16)), (int) (2.2360679774 * (1 << 16)), (int) (3.1622776601 * (1 << 16)), (int) (4.1231056256 * (1 << 16)), (int) (5.0990195135 * (1 << 16)), (int) (6.0827625302 * (1 << 16)), (int) (7.0710678118 * (1 << 16)), (int) (8.0622577482 * (1 << 16)), (int) (9.0553851381 * (1 << 16)), (int) (10.0498756211 * (1 << 16)), (int) (11.0453610171 * (1 << 16)), (int) (12.0415945787 * (1 << 16)), (int) (13.0384048104 * (1 << 16)), (int) (14.0356688476 * (1 << 16)), (int) (15.0332963783 * (1 << 16)), (int) (16.0312195418 * (1 << 16)), (int) (17.0293863659 * (1 << 16)), (int) (18.0277563773 * (1 << 16)), (int) (19.0262975904 * (1 << 16)), (int) (20.0249843945 * (1 << 16)), (int) (21.0237960416 * (1 << 16)), (int) (22.0227155455 * (1 << 16)), (int) (23.0217288664 * (1 << 16)), (int) (24.0208242989 * (1 << 16)), (int) (25.0199920063 * (1 << 16)), (int) (26.0192236625 * (1 << 16)), (int) (27.0185121722 * (1 << 16)), (int) (28.0178514522 * (1 << 16)), (int) (29.0172362570 * (1 << 16)), (int) (30.0166620396 * (1 << 16)), (int) (31.0161248385 * (1 << 16)), * }; */ #define setbits(l,p,n) *(int *) (((char *) l) + ((p>>3)&~1)) |= (((unsigned)((1<<31)>>(n-1)))>>(p&0xF)) #define setbit(l,p) l[p>>3] |= (1<<7)>>(p&7) generic_shapecurve(fb, shape, chain, op, texture, phase) register struct pixrect *fb; register struct shape_dcurve *chain; struct shape *shape; short *texture; fract phase; { short top, bottom, left, right; if (shape == 0) return 0; if (shape->is_rect == 0) return sh_subdivide_curve(fb, shape, chain, op, texture, phase, shape->trapset); top = max(0, shape->pos.y); left = max(0, shape->pos.x); bottom = min(fb->pr_size.y, shape->pos.y + shape->size.y); right = min(fb->pr_size.x, shape->pos.x + shape->size.x); if (top >= bottom || left >= right) return 0; if (texture && *texture) { #ifdef undef /* relates to commenting out arclength_table above */ short *txtp = texture; int visible = 1; int deltay = 1; fract arclength = 0; fract left = fracti(*txtp++) - phase; while (left <= 0) { if (*txtp == 0) txtp = texture; cfloorfr(left) += *txtp++; visible = 1 - visible; } while (chain) { register xp; register short *p; register y; int ylimit; if (chain->direction < 0) deltay = -1; else if (chain->direction > 0) deltay = 1; if (deltay > 0) { xp = chain->x0; p = chain->x + 1; y = chain->y0; ylimit = chain->y1 + 1; if (xp < *p) xp--; else if (xp > *p) xp++; } else { xp = chain->x1; p = chain->x + (chain->y1 - chain->y0); xp = *p; y = chain->y1; ylimit = chain->y0 - 1; if (xp < p[1]) xp--; else if (xp > p[1]) xp++; } { int dumpedsome = 0; if (deltay > 0) while (y != ylimit) { register delta = *p - xp; register direction; if ((direction = delta) < 0) { delta = -delta; xp = *p; } else if (delta) xp++; if (delta > sizeof arclength_table / sizeof arclength_table[0]) arclength = fracti(delta); else arclength = arclength_table[delta]; if (delta > 1 && p[0] == p[1]) { /* Pimple */ delta--; if (direction < 0) xp++; } while (arclength > left) { if (visible) pr_rop(fb, direction > 0 ? xp : xp + delta - cfloorfr(left), y, cfloorfr(left) || dumpedsome ? cfloorfr(left) : 1, 1, op, 0, 0, 0); cfloorfr(arclength) -= cfloorfr(left); dumpedsome++; delta -= cfloorfr(left); if (direction > 0) xp += cfloorfr(left); visible = 1 - visible; if (*txtp == 0) txtp = texture, dumpedsome = 0; cfloorfr(left) = *txtp++; } if (visible && arclength >= fracti(1)) { dumpedsome = 1; if (delta <= 1) pr_put(fb, xp, y, PIX_OPCOLOR(op)); else pr_rop(fb, xp, y, delta, 1, op, 0, 0, 0); } if (arclength >= left) { visible = 1 - visible; if (*txtp == 0) txtp = texture, dumpedsome = 0; cfloorfr(left) += *txtp++; } left -= arclength; y += 1; xp = *p; p += 1; } else /* deltay == -1 */ while (y != ylimit) { register delta; register direction; delta = p[1] - xp; if ((direction = delta) < 0) { delta = -delta; xp = p[1]; } else if (delta) xp++; if (delta > sizeof arclength_table / sizeof arclength_table[0]) arclength = fracti(delta); else arclength = arclength_table[delta]; if (delta > 1 && p[1] == p[2]) { /* pimple */ delta--; if (direction < 0) xp++; } while (arclength > left) { if (visible) pr_rop(fb, direction < 0 ? xp : xp + delta - cfloorfr(left), y, cfloorfr(left) || dumpedsome ? cfloorfr(left) : 1, 1, op, 0, 0, 0); cfloorfr(arclength) -= cfloorfr(left); dumpedsome++; delta -= cfloorfr(left); if (direction < 0) xp += cfloorfr(left); visible = 1 - visible; if (*txtp == 0) txtp = texture, dumpedsome = 0; cfloorfr(left) = *txtp++; } if (visible && arclength >= fracti(1)) { dumpedsome = 1; if (delta <= 1) pr_put(fb, xp, y, PIX_OPCOLOR(op)); else pr_rop(fb, xp, y, delta, 1, op, 0, 0, 0); } if (arclength >= left) { visible = 1 - visible; if (*txtp == 0) txtp = texture, dumpedsome = 0; cfloorfr(left) += *txtp++; } left -= arclength; y -= 1; xp = *--p; } } deltay = -deltay; chain = chain->next; } while (txtp > texture) cfloorfr(left) -= *--txtp; return left < 0 ? -left : 0; #endif } else for (; chain; chain = chain->next) { register xp = chain->x0; register short *p = chain->x + 1; register 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++; while (p <= ylimit) { register delta; register x = *p++; if ((delta = x - xp) == 0) { register y0 = y; while (p < ylimit && *p == xp) y++, p++; if (left <= xp && xp < right) pr_rop(fb, xp, y0, 1, y - y0 + 1, op, 0, 0, 0); } 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) pr_rop(fb, xp, y, delta, 1, op, 0, 0, 0); xp = x; } y++; } } return 0; }