📄 hpcopyarea.c
字号:
/*Copyright (c) 1986, 1987, 1988 by Hewlett-Packard CompanyHEWLETT-PACKARD MAKES NO WARRANTY OF ANY KIND WITH REGARDTO THIS SOFWARE, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Hewlett-Packard shall not be liable for errors contained herein or direct, indirect, special, incidental or consequential damages in connection with the furnishing, performance, or use of this material.*//* $XConsortium: hpCopyArea.c,v 1.4 88/09/30 14:16:22 jim Exp $ *//* * hpCopyArea.c : a copy area for HP displays * Author: C Durland (aided and abetted by Mr. J. Daniels) */#include "X.h"#include "gcstruct.h"#include "pixmapstr.h"#include "windowstr.h"#include "scrnintstr.h"#include "regionstr.h"#include "mi.h"#include "servermd.h"#include "cfb.h"/* MTOS : main memory to screen MTOM : main mem to main mem, screen to main mem STOS : screen to screen DESTINATION | screen | main memory window | pixmap | pixmap SOURCE .--------|--------|------- window | STOS | STOS | MTOM screen pixmap | STOS | STOS | MTOM main memory pixmap | MTOS | MTOS | MTOM Dest clip list Source clip list window composite clip inferiors or window clip list screen pixmap maybe a client clip no main memory pixmap maybe a client clip no*/#define COPYROW(to,from,n) memcpy(to,from,n)#define PIXER(Drawable) ((hpPrivPixmapPtr)((PixmapPtr)Drawable)->devPrivate.ptr)#define SCRMER(Drawable) getPrivScreenPtr(Drawable->pScreen)#define DEVKIND(Drawable) ((PixmapPtr)Drawable)->devKind#define SWEAT_PLANES_MASK(Drawable,planesmask) \ ((SCRMER(Drawable)->planesMask & planesmask) != \ SCRMER(Drawable)->planesMask) /* Clip rectangle (x,y)-(x+w,y+h) against (a,b)-(c,d) * Returns the cliped (x,y) and w,h */void clipper(x,y,w,h, a,b,c,d, cx,cy, cw,ch) register int x,y,w,h, a,b,c,d; int *cx,*cy, *cw,*ch;{ *cw = min(x+w,c) - (*cx = max(x,a)); *ch = min(y+h,d) - (*cy = max(y,b));} /* Check to see if can copy area between two rectangles: * If the dest is above the source: can copy * else if they overlap: Can't copy * Have to check horizontal because of clip lists. boxes is the sum * of the number of clip rectangles for the source and dest. * Returns: FALSE if can copy area (ie any overlap don't matter) * true if got a overlap problem */static intlapdog(srcx,srcy, w,h, dstx,dsty, boxes) int srcx,srcy, w,h, dstx,dsty, boxes;{ return ( (srcy <= dsty) || ((boxes > 2) && (srcx < dstx)) ) && ( ((min(srcx,dstx)+w -max(srcx,dstx)) >0) && ((min(srcy,dsty)+h -max(srcy,dsty)) >0) );} /* Copy rectangles from screen to screen using the block mover * Overlapping moves: * Assumes that block mover can handle overlapping copies. * If there is a clip list, care must be taken so that copying * a block does not trash a block to be copied. * (?tx, ?ty) are translation constants to convert pixmaps * to screen coordinates. 0 if not a pixmap. */voidScreenToScreen(drawable,gc, sx,sy,width,height, dx,dy, sbox,sboxes, dbox,dboxes, stx,sty, dtx,dty) DrawablePtr drawable; GCPtr gc; int sx,sy,width,height, dx,dy, sboxes, dboxes, stx,sty, dtx,dty; BoxPtr sbox, dbox; /* the clip lists */{ register BoxPtr btr; int j, x1,y1, w1,h1, x2,y2, w2,h2, a,b,c,d, tx = sx-dx, ty = sy-dy; ScreenPtr Screen = drawable->pScreen; if (gc->alu==GXnoop) return; /* no op => don't do nothin */ for (; sboxes--; sbox++) /* for each source box */ { /* intersect source and source clip rectangle */ clipper(sx,sy,width,height, sbox->x1,sbox->y1, sbox->x2,sbox->y2, &x1,&y1, &w1,&h1); if (w1<=0 || h1<=0) continue; /* translate box to dst coordinates */ a = x1 -tx; b = y1 -ty; c = a +w1; d = b +h1; for (j = dboxes, btr = dbox; j--; btr++) /* copy to the dest box */ { /* intersect dst and dst clip rectangles */ clipper(dx,dy,width,height, btr->x1,btr->y1, btr->x2,btr->y2, &x2,&y2, &w2,&h2); if (w2<=0 || h2<=0) continue; /* intersect clipped src and clipped dst rectangles */ clipper(x2,y2,w2,h2, a,b,c,d, &x1,&y1, &w1,&h1); if (w1<=0 || h1<=0) continue; (*getPrivScreenPtr(Screen)->MoveBits) (Screen, gc->planemask, gc->alu, x1+tx+stx, y1+ty+sty, x1+dtx, y1+dty, w1, h1); } }} /* copy a rectangle of bytes: no processing */static voidCopyRec0(dst,w,h,dst_stride, alu) register char *dst; int w,h,dst_stride, alu;{ register int z; switch (alu) { case GXclear: z = 0; break; /* 0 */ case GXset: z = ~0; break; /* 1 */ } while (h--) /* copy h rows */ { memset(dst,z,w); dst += dst_stride; /* move to next row */ }} /* copy a rectangle of bytes: only process src */ /* two cases: GXcopy & GXcopyInverted */static voidCopyRec1(src,dst,w,h,src_stride,dst_stride, alu) register char *src, *dst; int w,h,src_stride,dst_stride, alu;{ register int j; if (alu==GXcopy) while (h--) /* copy h rows */ { COPYROW(dst,src,w); src += src_stride; dst += dst_stride; /* move to next row */ } else while (h--) /* copy h rows */ { j = w; while (j--) dst[j] = ~src[j]; src += src_stride; dst += dst_stride; /* move to next row */ }} /* copy a rectangle of bytes: process src & dst */static voidCopyRec2(src,dst,w,h,src_stride,dst_stride, alu,planesmask) register char *src, *dst; int w,h,src_stride,dst_stride, alu; register long int planesmask;{ register char a, b; register int j; /*!!! slime bag note: if planesmask > 8 bits this routine no workie */ while (h--) /* copy h rows */ { j = w; while (j--) /* copy a row */ { a = src[j]; b = dst[j]; switch (alu) { case GXclear: a = 0; break; /* 0 */ case GXset: a = ~0; break; /* 1 */ case GXcopyInverted: b = ~a; break; /* ~src *//* case GXcopy: a = a; break; /* src */ case GXand: a = a & b; break; /* src AND dst */ case GXandReverse: a = a & (~b); break; /* src AND NOT dst */ case GXandInverted: a = (~a) & b; break; /* NOT src AND dst */ case GXxor: a = a ^ b; break; /* src XOR dst */ case GXor: a = a | b; break; /* src OR dst */ case GXnor: a = (~a) & (~b); break; /* NOT src AND NOT dst */ case GXequiv: a = (~a) ^ b; break; /* NOT src XOR dst */ case GXinvert: a = ~b; break; /* NOT dst */ case GXorReverse: a = a | (~b); break; /* src OR NOT dst */ case GXorInverted: a = (~a) | b; break; /* NOT src OR dst */ case GXnand: a = (~a) | (~b); break; /* NOT src OR NOT dst */ } dst[j] = (a & planesmask) | (b & ~planesmask); } src += src_stride; dst += dst_stride; /* move to next row */ }} /* move bytes from main memory to main memory * or move bytes from screen to main memory * concerns: Replacement rule, overlapping copies, * Only works for depths of 1 and multiples of 8. */voidMemToMem(SrcDrawable,DstDrawable,gc, sx,sy,width,height, dx,dy, sbox,sboxes, dbox,dboxes) DrawablePtr SrcDrawable,DstDrawable; GCPtr gc; int sx,sy,width,height, dx,dy, sboxes, dboxes; BoxPtr sbox, dbox; /* the clip lists */{ unsigned char *src, *dst, *presrc; register int src_stride, dst_stride; int j, x1,y1, w1,h1, x2,y2, w2,h2, a,b,c,d, tx = sx-dx, ty = sy-dy, alu, fake_alu, DepthInBytes = SrcDrawable->depth/8; unsigned long int planesmask; register BoxPtr btr; if ((alu=gc->alu)==GXnoop) return; /* no op => don't do nothin */ fake_alu = alu; planesmask = gc->planemask; if (DepthInBytes<1) /* moving bits */ { DepthInBytes = 1; /* fake around */ if (planesmask==0) return; /* no bits will be changed */ planesmask = ~0; /* all bits can be changed */ } /* check to see if gotta sweat the planes mask */ if (SWEAT_PLANES_MASK(SrcDrawable,planesmask)) fake_alu = 666; dst_stride = PIXER(DstDrawable)->stride; if (SrcDrawable->type == DRAWABLE_WINDOW) /* from screen */ { src_stride = SCRMER(SrcDrawable)->stride; presrc = SCRMER(SrcDrawable)->bits; } else /* from main memory or offscreen pixmap */ { src_stride = PIXER(SrcDrawable)->stride; presrc = PIXER(SrcDrawable)->bits; } for (; sboxes--; sbox++) /* for each source box */ { /* intersect src and src clip rectangle */ clipper(sx,sy,width,height, sbox->x1,sbox->y1,sbox->x2,sbox->y2, &x1,&y1, &w1,&h1); if (w1<=0 || h1<=0) continue; /* translate box to dst coordinates */ a = x1 -tx; b = y1 -ty; c = a +w1; d = b +h1; for (j = dboxes, btr = dbox; j--; btr++) { /* intersect dst and dst clip rectangles */ clipper(dx,dy,width,height, btr->x1,btr->y1, btr->x2,btr->y2, &x2,&y2, &w2,&h2); if (w2<=0 || h2<=0) continue; /* intersect clipped src and clipped dst rectangles */ clipper(x2,y2,w2,h2, a,b,c,d, &x1,&y1, &w1,&h1); if (w1<=0 || h1<=0) continue; w1 *= DepthInBytes; /* convert rectangle to addresses */ src = presrc + (x1+tx)*DepthInBytes +(y1+ty)*src_stride; dst = PIXER(DstDrawable)->bits +x1*DepthInBytes +y1*dst_stride; switch (fake_alu) { case GXclear: case GXset: CopyRec0(dst,w1,h1,dst_stride, alu); break; case GXcopy: case GXcopyInverted: CopyRec1(src,dst,w1,h1,src_stride,dst_stride, alu); break; default: CopyRec2(src,dst,w1,h1,src_stride,dst_stride, alu,planesmask); } } }} /* Move bytes from main memory to screen memory. * (dtx,dty) are translation constants to convert pixmaps * to screen coordinates. 0 if not a pixmap. */voidMemToScreen(SrcDrawable,DstDrawable,gc, sx,sy,width,height, dx,dy, dboxes, dbox, dtx,dty) DrawablePtr SrcDrawable,DstDrawable; GCPtr gc; int sx,sy,width,height, dx,dy, dboxes, dtx,dty; BoxPtr dbox; /* the dst clip list */{ register unsigned char *src, *dst; register int src_stride, dst_stride; int w,h, x1,y1, DepthInBytes = SrcDrawable->depth/8; /* setup hardware */ SET_REGISTERS_FOR_WRITING(gc->pScreen,gc->planemask,gc->alu); src_stride = PIXER(SrcDrawable)->stride; dst_stride = SCRMER(DstDrawable)->stride; for (; dboxes--; dbox++) { /* intersect dst and clip rectangles */ clipper(dx,dy,width,height, dbox->x1,dbox->y1,dbox->x2,dbox->y2, &x1,&y1, &w,&h); w *= DepthInBytes; if (w<=0 || h<=0) continue; /* convert rectangle to addresses */ src = PIXER(SrcDrawable)->bits +(sx +(x1-dx))*DepthInBytes +(sy +(y1-dy))*src_stride; dst = SCRMER(DstDrawable)->bits +(x1+dtx)*DepthInBytes +(y1+dty)*dst_stride; /* copy rectangle */ while (h--) { COPYROW(dst,src,w); src += src_stride; dst += dst_stride; /* move to next row */ } }} /* reverse banding */static voidspud(list,n) BoxRec *list; int n;{ register BoxRec box; register int i, j, k; for (j = 0, i = n, k = n/2; j<k; ) { box = list[j]; list[j++] = list[--i]; list[i] = box; }} /* reverse horizontal banding */static voidspudd(list,n) register BoxRec *list; int n;{ register int i,j; for (j=0; j<n; j = i) { for (i = j+1; i<n && list[i].y1==list[j].y1; i++) ; spud(&list[j],i-j); }}extern RegionPtr NotClippedByChildren();static RegionPtr hpfbCopyArea();RegionPtr hpcCopyArea(pSrcDrawable, pDstDrawable, pGC, xIn, yIn, widthSrc, heightSrc, xOut, yOut) DrawablePtr pSrcDrawable, pDstDrawable; GCPtr pGC; int xIn, yIn, widthSrc, heightSrc, xOut, yOut;{ BoxRec *scl, *dcl, sbox; int srcx,srcy, dstx,dsty, width,height, dboxes,sboxes, stx,sty, dtx,dty, expose = 0, lowlife = 0; RegionPtr sHitList = NULL; /* the source hit list */ RegionPtr prgnExposed = NULL; extern RegionPtr mfbCopyArea ();/* ignore UNDRAWABLE_WINDOWs in the hope DIX takes care of them */ if ((pDstDrawable->type == DRAWABLE_WINDOW) && (!((WindowPtr)pDstDrawable)->realized)) return (RegionPtr)NULL; dstx = xOut; dsty = yOut; width = widthSrc; height = heightSrc; /* clip the left and top edges of the source */ if (xIn<0) { expose = 1; srcx = pSrcDrawable->x; width += xIn; } else srcx = xIn + pSrcDrawable->x; if (yIn<0) { expose = 1; srcy = pSrcDrawable->y; height += yIn; } else srcy = yIn + pSrcDrawable->y; /* lookup or create the source clip lists */ stx = sty = 0; if (pSrcDrawable->type == DRAWABLE_PIXMAP) { /* clip right and bottom edges of source */ if (width > pSrcDrawable->width) { expose = 1; width = pSrcDrawable->width; } if (height > pSrcDrawable->height) { expose = 1; height = pSrcDrawable->height; } /* if screen pixmap & going to use the block mover, translate */ if (DEVKIND(pSrcDrawable) == PIXMAP_FRAME_BUFFER) { stx = PIXER(pSrcDrawable)->pChunk->x; sty = PIXER(pSrcDrawable)->pChunk->y; } sbox.x2 = (sbox.x1 = srcx) + width; sbox.y2 = (sbox.y1 = srcy) + height; scl = &sbox; sboxes = 1; } else /* source is a window */ { expose = 1; /* hard to figure out for a window so expose always */ /* translate window to screen coordinates */ if (pGC->subWindowMode == IncludeInferiors) { /* included window can write over parent => overlap problem
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -