#ifndef lint static char sccsid[] = "@(#)pr_shrop.c 9.2 88/01/19 Copyright 1985 Sun Micro"; #endif /* * Copyright (c) 1985 by Sun Microsystems, Inc. */ /*- shaperop for arbitrary pixrect types. pr_shrop.c, Sat Aug 24 14:33:54 1985 James Gosling, Sun Microsystems */ #include #ifdef REF #include #include #endif #include "shape.h" #include "trap_step.h" #include #undef prs_rop #define prs_rop(dstregion, op, srcprpos) \ (*((dstregion).pr)->pr_ops->pro_rop)(dstregion.pr, \ dstregion.pos.x, dstregion.pos.y, \ dstregion.size.x, dstregion.size.y, op, \ srcprpos.pr, srcprpos.pos.x, srcprpos.pos.y) generic_shaperop(dpr, shape, OP, spr, sx, sy) struct pixrect *dpr, *spr; register struct shape *shape; { struct pr_subregion dst; struct pr_prpos src; struct shape nextshape; extern cg2_rop(); if (shape == 0) return 0; if (spr == dpr && !shape->is_rect) if (shape->trapset->next) { trim_traps(shape); if (!shape->is_rect && shape->trapset->next && (sx || sy)) { /* * punt rops with complicated shapes that are within one * pixrect by copying to an intermediary */ register struct pixrect *temp; temp = mem_create(dpr->pr_width, dpr->pr_height, dpr->pr_depth); /* * pr_shaperop(temp, shape, PIX_SRC, spr, 0, 0); * pr_shaperop(dpr, shape, OP, temp, sx, sy); */ pr_rop(temp, shape->pos.x, shape->pos.y, shape->size.x, shape->size.y, PIX_SRC, spr, shape->pos.x - sx, shape->pos.y - sy); pr_shaperop(dpr, shape, OP, temp, 0, 0); pr_destroy(temp); return 0; } } else if (sy > 0) { /* downward scroll */ int op = OP; struct fine_trap_state trap; int ylimit; int xlimit; int dstx; int srcx; assert(shape->trapset->next == 0); dst.pos.x = shape->pos.x; dst.pos.y = shape->pos.y; dst.size.x = shape->size.x; dst.size.y = shape->size.y; dst.pr = dpr; src.pr = spr; src.pos.x = dst.pos.x - sx; src.pos.y = dst.pos.y - sy; if (op & PIX_DONTCLIP) op &= ~PIX_DONTCLIP; else pr_clip(&dst, &src); if (dst.size.x <= 0 || dst.size.y <= 0) return 0; if (shape->trapset->top > dst.pos.y) { register w; if ((dst.size.y += (w = dst.pos.y - shape->trapset->top)) <= 0) return 0; dst.pos.y -= w; src.pos.y -= w; } if ((ylimit = dst.pos.y + dst.size.y) > shape->trapset->bottom && (dst.size.y = (ylimit = shape->trapset->bottom) - dst.pos.y) <= 0) return 0; xlimit = dst.pos.x + dst.size.x; dstx = dst.pos.x; srcx = src.pos.x; init_fine_trap(&trap, shape->trapset); trap.seg = trap.limit - 1; trap.y = trap.seg[1].y; while (ylimit > dst.pos.y) { register x1 = dstx; register x2 = xlimit; register height; src.pos.x = srcx; trap.next = *trap.seg--; if (trap.next.x1 > x1) x1 = trap.next.x1; if (trap.next.x2 < x2) x2 = trap.next.x2; height = ylimit - trap.next.y; if (trap.next.y < dst.pos.y) { trap.next.y = dst.pos.y; height = ylimit - trap.next.y; } ylimit = trap.next.y; if (height <= 0) break; if (x1 < x2) pr_rop(dst.pr, x1, trap.next.y, x2 - x1, height, OP, src.pr, x1 - sx, trap.next.y - sy); } return 0; } while (1) { int op = OP; dst.pos.x = shape->pos.x; dst.pos.y = shape->pos.y; dst.size.x = shape->size.x; dst.size.y = shape->size.y; dst.pr = dpr; src.pr = spr; src.pos.x = dst.pos.x - sx; src.pos.y = dst.pos.y - sy; if (op & PIX_DONTCLIP) op &= ~PIX_DONTCLIP; else pr_clip(&dst, &src); if (dst.size.x <= 0 || dst.size.y <= 0) return 0; if (shape->is_rect) { prs_rop(dst, op, src); return 0; } else { struct fine_trap_state trap; int ylimit = dst.pos.y + dst.size.y; int xlimit = dst.pos.x + dst.size.x; int dstx = dst.pos.x; int srcx = src.pos.x; if (shape->trapset->top > dst.pos.y) { register w; if ((dst.size.y += (w = dst.pos.y - shape->trapset->top)) <= 0) goto nextrap; dst.pos.y -= w; src.pos.y -= w; } if (shape->trapset->bottom >= ylimit || (dst.size.y = (ylimit = shape->trapset->bottom) - dst.pos.y) > 0) { init_fine_trap(&trap, shape->trapset); fast_step_down_trap_to(&trap, dst.pos.y); while (dst.pos.y < ylimit) { register x1 = dstx; register x2 = xlimit; register height; src.pos.x = srcx; if (trap.x1 > x1) { src.pos.x += trap.x1 - x1; x1 = trap.x1; } if (trap.x2 < x2) x2 = trap.x2; height = trap.next.y - dst.pos.y; if (height <= 0) break; if (height + dst.pos.y > ylimit) height = ylimit - dst.pos.y; trap.x1 = trap.next.x1; trap.x2 = trap.next.x2; if (x1 < x2) { dst.pos.x = x1; dst.size.x = x2 - x1; dst.size.y = height; prs_rop(dst, OP, src); } dst.pos.y = trap.next.y; src.pos.y += height; trap.next = *trap.seg++; } } } nextrap: if (shape->trapset->next) { nextshape = *shape; nextshape.trapset = shape->trapset->next; shape = &nextshape; } else return 0; } }