Files
Arquivotheca.SunOS-4.1.4/usr.lib/libpixrect/pr/pr_replrop.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

284 lines
5.4 KiB
C

#ifndef lint
static char sccsid [] = "@(#)pr_replrop.c 1.1 94/10/31 SMI";
#endif
/*
* Copyright 1986 by Sun Microsystems, Inc.
*/
#include <sys/types.h>
#include <pixrect/pixrect.h>
#include <pixrect/memvar.h>
#include <gp1var.h>
#ifndef pr_product
#define pr_product(x, y) (x * y)
#endif
#ifndef REPL_SIZE
#define REPL_SIZE 64 /* width, height of intermediate pixrect */
#endif
/* width of 1-line high buffer */
#define LINE_SIZE (REPL_SIZE * REPL_SIZE)
pr_replrop(dpr, dx, dy, dw, dh, op, spr, sx, sy)
Pixrect *dpr;
int dx, dy, dw, dh, op;
register Pixrect *spr;
int sx, sy;
{
register int sw, sh;
register int x, y;
int errors = 0;
Pixrect *mpr;
Pixrect tmp_pr;
struct mpr_data tmp_prd;
static struct mpr_data zprd = { 0 };
short tmp_image[REPL_SIZE][REPL_SIZE/16];
extern int gp1_rop(), cg6_rop();
extern struct pixrectops mem_ops;
if (spr) {
if ((sw = spr->pr_size.x) <= 0 ||
(sh = spr->pr_size.y) <= 0)
return 0;
}
else {
sw = dw;
sh = dh;
}
/*
* Make sx, sy canonical by reducing mod spr size
*/
for (x = sw; sx < 0; x += x)
sx += x;
if (sx >= sw)
sx %= sw;
for (y = sh; sy < 0; y += y)
sy += y;
if (sy >= sh)
sy %= sh;
/* clip if requested */
if (!(op & PIX_DONTCLIP)) {
struct pr_subregion dst;
struct pr_prpos src;
dst.pr = dpr;
dst.pos.x = dx;
dst.pos.y = dy;
dst.size.x = dw;
dst.size.y = dh;
src.pr = &tmp_pr;
tmp_pr.pr_size.x = dw + sx;
tmp_pr.pr_size.y = dh + sy;
src.pos.x = sx;
src.pos.y = sy;
(void) pr_clip(&dst, &src);
dx = dst.pos.x;
dy = dst.pos.y;
dw = dst.size.x;
dh = dst.size.y;
/* make sure sx, sy are still canonical */
if ((sx = src.pos.x) >= sw)
sx %= sw;
if ((sy = src.pos.y) >= sh)
sy %= sh;
op |= PIX_DONTCLIP;
}
if (dw <= 0 || dh <= 0)
return 0;
if (dpr->pr_ops->pro_rop == gp1_rop &&
gp1_d (dpr)->fbtype == FBTYPE_SUN2COLOR) {
if (!gp1_replrop(dpr, dx, dy, dw, dh, op, spr, sx, sy))
return 0;
} else
if (dpr->pr_ops->pro_rop == cg6_rop &&
!cg6_replrop(dpr, dx, dy, dw, dh, op, spr, sx, sy))
return 0;
else
if (dpr->pr_ops->pro_rop == gp1_rop &&
gp1_d (dpr)->fbtype == FBTYPE_SUNGP3) {
if (!cg12_replrop(dpr, dx, dy, dw, dh, op, spr, sx, sy))
return 0;
}
/* make sure sw, sh are no larger than needed */
if (sw > (x = dw + sx))
sw = x;
if (sh > (y = dh + sy))
sh = y;
/*
* Build temporary pixrect in case it is needed for either
* of two special cases below. (We don't want to waste time
* on a mem_point().)
*/
tmp_pr.pr_ops = &mem_ops;
tmp_pr.pr_depth = 1;
tmp_pr.pr_data = (caddr_t) &tmp_prd;
tmp_prd = zprd;
tmp_prd.md_image = tmp_image[0];
/*
* If destination is 1 line high and source is 16 bits
* wide, then special case to go fast: replicate
* the source in a 1 line high short buffer to be
* wide enough, and rop to the destination.
*
* (It's unlikely that anyone uses this.)
*/
if (sw == 16 && dh == 1 && dw <= LINE_SIZE &&
spr && !(MP_NOTMPR(spr)) && spr->pr_depth == 1) {
register u_short pat;
{
register struct mpr_data *mprd = mpr_d(spr);
x = sx + mprd->md_offset.x;
pat = * (short *) ((caddr_t) mprd->md_image +
pr_product(mprd->md_linebytes,
mprd->md_offset.y + sy) +
(x >> 4 << 1));
pat = (pat | pat << 16) >> (16 - (x & 15));
}
{
register short *image = tmp_image[0];
x = (dw + 15) >> 4;
while (--x >= 0)
*image++ = pat;
}
tmp_pr.pr_size.x = LINE_SIZE;
tmp_pr.pr_size.y = 1;
tmp_prd.md_linebytes = LINE_SIZE / 8;
return pr_rop(dpr, dx, dy, dw, dh, op, &tmp_pr, 0, 0);
}
/*
* If source is too small, blow it up.
*/
mpr = 0;
if ((dw >= REPL_SIZE || dh >= REPL_SIZE) &&
sw <= REPL_SIZE/2 && sh <= REPL_SIZE/2) {
register int tw, th;
register Pixrect *tpr;
for (tw = sw, x = REPL_SIZE - sw; tw <= x; )
tw += sw;
if (tw > (x = dw + sx))
tw = x;
for (th = sh, y = REPL_SIZE - sh; th <= y; )
th += sh;
if (th > (y = dh + sy))
th = y;
if (spr->pr_depth == 1) {
tpr = &tmp_pr;
tmp_pr.pr_size.x = REPL_SIZE;
tmp_pr.pr_size.y = REPL_SIZE;
tmp_prd.md_linebytes = REPL_SIZE / 8;
}
else
mpr = tpr = mem_create(tw, th, spr->pr_depth);
if (tpr) {
for (x = 0; tw - x > 0; x += sw) {
if (sw > tw - x)
sw = tw - x;
errors |= pr_rop(tpr, x, 0, sw, sh,
PIX_SRC | PIX_DONTCLIP,
spr, 0, 0);
}
sw = tw;
spr = tpr;
for (y = sh; th - y > 0; y += sh) {
if (sh > th - y)
sh = th - y;
errors |= pr_rop(spr, 0, y, sw, sh,
PIX_SRC | PIX_DONTCLIP,
spr, 0, 0);
}
sh = th;
}
}
/*
* Perform the replrop.
*/
dw += (x = dx);
dh += (y = dy);
sh -= sy;
/* top left corner */
errors |= pr_rop(dpr, x, y, sw - sx, sh, op, spr, sx, sy);
/* top center/right */
for (x += sw - sx; dw - x >= sw; x += sw)
errors |= pr_rop(dpr, x, y, sw, sh, op, spr, 0, sy);
/* top right */
if (dw - x > 0)
errors |= pr_rop(dpr, x, dy, dw - x, sh, op, spr, 0, sy);
/* center/bottom strips */
y += sh; sh += sy;
for ( ; y < dh; y += sh) {
/* reduce height for bottom strip */
if (sh > dh - y)
sh = dh - y;
/* left */
x = dx;
errors |= pr_rop(dpr, x, y, sw - sx, sh,
op, spr, sx, 0);
/* center */
for (x += sw - sx; dw - x >= sw; x += sw)
errors |= pr_rop(dpr, x, y, sw, sh,
op, spr, 0, 0);
/* right */
if (dw - x > 0)
errors |= pr_rop(dpr, x, y, dw - x, sh,
op, spr, 0, 0);
}
/* destroy temporary pixrect */
if (mpr)
(void) pr_destroy(mpr);
return errors;
}