#ifndef lint static char sccsid[] = "@(#)gen_rplrop.c 9.2 88/01/19 Copyr 1985 Sun Micro"; #endif /* * Copyright (c) 1983 by Sun Microsystems, Inc. */ #include #include #ifdef REF #include #endif #include #include #include #include #include "shape.h" extern mem_rop(); #define REPLSIZ 64 /* dimension of intermediate replpr */ static struct mpr_data repldata; static short lineimage[1280 / 16]; #define LONGONES ((unsigned long) 0xFFFFFFFF) static struct mpr_data linepr_data = {mpr_linebytes(1280,1), (short *)(lineimage), {0, 0}, 0, 0}; extern struct pixrectops mem_ops; static struct pixrect linepr = {&mem_ops, 1280, 1, 1, (caddr_t)&linepr_data}; /* Leif generic_replrop(dst, op, src) struct pr_subregion dst; int op; struct pr_prpos src; */ generic_replrop(dstpr, dstx, dsty, dstw, dsth, op, srcpr, srcx, srcy) struct pixrect *dstpr, *srcpr; int dstx,dsty,dstw,dsth,op,srcx,srcy; { struct pr_subregion dst; struct pr_prpos src; short replprimage[REPLSIZ*(REPLSIZ / 16)]; struct pixrect replpr; struct pixrect *rp = srcpr; struct pixrect *rptemp = 0; struct pr_pos p; int errors = 0; dst.pr = dstpr; dst.pos.x = dstx; dst.pos.y = dsty; dst.size.x = dstw; dst.size.y = dsth; src.pr = srcpr; src.pos.x = srcx; src.pos.y = srcy; assert(rp->pr_ops->pro_rop == mem_rop); if (rp->pr_size.x <= 0 || rp->pr_size.y <= 0) return (-1); /* cant replicate! */ { register T = rp->pr_size.y; if ((T & -T) == T) /* Test for being a power of two */ src.pos.y &= T - 1; else { src.pos.y = ((short) src.pos.y) % ((short) T); if (src.pos.y < 0) src.pos.y += T; } T = rp->pr_size.x; if ((T & -T) == T) src.pos.x &= T - 1; else { src.pos.x = ((short) src.pos.x) % ((short) T); if (src.pos.x < 0) src.pos.x += T; } } if (dst.pr->pr_ops->pro_rop == mem_rop && dst.pr->pr_depth == 1 && op == PIX_SRC) if (rp->pr_size.x == 16 || rp->pr_size.x == 32) { #ifdef sparc unsigned short *dstp; unsigned short mask1, mask2; #else register unsigned long *dstp; register unsigned long mask1, mask2; #endif register struct mpr_data *dstm = mpr_d(dst.pr); register struct mpr_data *srcm = mpr_d(src.pr); register widecols, deltadst; register short rows; int color; short skew; dst.pos.x += dstm->md_offset.x; dst.pos.y += dstm->md_offset.y; skew = (dst.pos.x & (rp->pr_size.x-1)) - src.pos.x; if (skew<0) skew += rp->pr_size.x; assert(sizeof(int) == 4 && sizeof(long) == 4); #ifdef sparc mask1 = ((unsigned short) 0xFFFF) >> (dst.pos.x & 0xF); mask2 = 0xFFFF << (15 - ((dst.size.x - 1 + (dst.pos.x & 0xF)) & 0xF)); widecols = (((dst.pos.x & 0xF) + dst.size.x - 1) >> 4) - 1; #else #ifdef NONSUNFB mask1 = LONGONES << (dst.pos.x & 0xF); mask2 = LONGONES >> (0x1F - ((dst.size.x - 1 + (dst.pos.x & 0xF)) & 0x1F)); #else mask1 = LONGONES >> (dst.pos.x & 0xF); mask2 = LONGONES << (0x1F - ((dst.size.x - 1 + (dst.pos.x & 0xF)) & 0x1F)); #endif widecols = (((dst.pos.x & 0xF) + dst.size.x - 1) >> 5) - 1; #endif if (widecols < 0) mask1 &= mask2; #ifdef sparc deltadst = dstm->md_linebytes - (widecols + 2) * 2; dstp = (unsigned short *) ((char *) dstm->md_image + pr_product(dst.pos.y, dstm->md_linebytes) + ((dst.pos.x >> 3) & ~1)); #else deltadst = dstm->md_linebytes - (widecols + 2) * 4; dstp = (unsigned long *) ((char *) dstm->md_image + pr_product(dst.pos.y, dstm->md_linebytes) + ((dst.pos.x >> 3) & ~1)); #endif for (rows = dst.size.y; --rows >= 0;) { register short cnt; if (rp->pr_size.x == 16) { color = ((unsigned short *)srcm->md_image)[src.pos.y]; color = (unsigned short) ((color|(color<<16))>>skew); color = color | (color<<16); } else { color = ((int *)srcm->md_image)[src.pos.y]; color = (color<<(32-skew)) | (((unsigned)color)>>skew); } /* * Need to check REVERSEVIDEO flag here since this path * doesn't end up in mem_rop code. */ #ifndef lint if (dstm->md_flags & MP_REVERSEVIDEO) color = ~((unsigned int) color); #endif *dstp = *dstp & ~mask1 | color & mask1; dstp++; if ((cnt = widecols) >= 0) { while (--cnt != -1) *dstp++ = color; *dstp = *dstp & ~mask2 | color & mask2; dstp++; } #ifdef sparc dstp = (unsigned short *) ((int) dstp + deltadst); #else dstp = (unsigned long *) ((int) dstp + deltadst); #endif src.pos.y++; if (src.pos.y>=rp->pr_size.y) src.pos.y = 0; } return 0; } if (dst.size.y <= 2 && dst.size.x < 1280 && rp->pr_depth == 1) { struct mpr_data *mprd = mpr_d(rp); register short i; int ylimit = dst.size.y + dst.pos.y; int dy; while (dst.size.y > 0) { register short *pat = lineimage; dy = dst.pos.y; if (rp->pr_size.x == 16) { register w; i = (dst.size.x + src.pos.x + 15) >> 4; w = *((short *) mprd->md_image + (mprd->md_offset.y + src.pos.y)); while (--i >= 0) *pat++ = w; } else if (rp->pr_size.x == 32) { register w; i = (dst.size.x + src.pos.x + 31) >> 5; w = *((int *) mprd->md_image + (mprd->md_offset.y + src.pos.y)); while (--i != -1) { *((int *) pat) = w; pat += (sizeof(int))/(sizeof(short)); } } else if (rp->pr_size.x == 64) { register *w; i = (dst.size.x + src.pos.x + 63) >> 6; w = ((int *) mprd->md_image + 2 * (mprd->md_offset.y + src.pos.y)); while (--i != -1) { *((int *) pat) = w[0]; pat += (sizeof(int))/(sizeof(short)); *((int *) pat) = w[1]; pat += (sizeof(int))/(sizeof(short)); } } else goto slowversion; while (dy < ylimit && --dst.size.y >= 0) { errors |= pr_rop(dst.pr, dst.pos.x, dy, dst.size.x, 1, op, &linepr, src.pos.x, 0); dy += rp->pr_size.y; }; dst.pos.y++; if (++src.pos.y >= rp->pr_size.y) src.pos.y = 0; } return (errors); } /* * If source is too small, blow it up. */ slowversion: if ((dst.size.x < REPLSIZ && dst.size.y < REPLSIZ) || (rp->pr_size.x > REPLSIZ/2 || rp->pr_size.y > REPLSIZ/2)) goto dontblowup; if (rp->pr_depth == 8) { rptemp = mem_create(REPLSIZ, REPLSIZ, rp->pr_depth); } else { rptemp = &replpr; rptemp->pr_ops = &mem_ops; repldata.md_image = replprimage; rptemp->pr_data = (caddr_t) &repldata; rptemp->pr_depth = 1; } rptemp->pr_size.x = pr_product((REPLSIZ / rp->pr_size.x), rp->pr_size.x); /*- if (rptemp->pr_size.x > dst.size.x + src.pos.x) rptemp->pr_size.x = dst.size.x + src.pos.x; */ rptemp->pr_size.y = pr_product((REPLSIZ / rp->pr_size.y), rp->pr_size.y); /*- if (rptemp->pr_size.y > dst.size.y + src.pos.y) rptemp->pr_size.y = dst.size.y + src.pos.y; */ mpr_mdlinebytes(rptemp) = mpr_prlinebytes(rptemp); for (p.x = 0; p.x < rptemp->pr_size.x; p.x += rp->pr_size.x) for (p.y = 0; p.y < rptemp->pr_size.y; p.y += rp->pr_size.y) errors |= pr_rop(rptemp, p.x, p.y, rp->pr_size.x, rp->pr_size.y, PIX_SRC | PIX_DONTCLIP, rp, 0, 0); rp = rptemp; dontblowup: dst.pr = pr_region(dst.pr, dst.pos.x, dst.pos.y, dst.size.x, dst.size.y); if (op & PIX_DONTCLIP) { /* region clips to pixrect boundary */ dst.pr->pr_width = dst.size.x; dst.pr->pr_height = dst.size.y; } /* * Make src.pos canonical by reducing mod src.pr_size. */ for (p.y = -src.pos.y; p.y < dst.size.y; p.y += rp->pr_size.y) for (p.x = -src.pos.x; p.x < dst.size.x; p.x += rp->pr_size.x) errors |= pr_rop(dst.pr, p.x, p.y, rp->pr_size.x, rp->pr_size.y, op & (~PIX_DONTCLIP), rp, 0, 0); /* * Clipping turned on cause counting on it to handle last pattern rop * in x and y directions. */ pr_destroy(dst.pr); if (rptemp && src.pr->pr_depth == 8) pr_destroy(rptemp); return (errors); }