📄 mibstore.c
字号:
* Perform a PutImage, routing output to backing-store as needed. * * Results: * None. * * Side Effects: * *----------------------------------------------------------------------- */static voidmiBSPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits) DrawablePtr pDrawable; GCPtr pGC; int depth; int x; int y; int w; int h; int leftPad; int format; char *pBits;{ SETUP_BACKING (pDrawable, pGC); PROLOGUE(pGC); (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits); (*pBackingGC->ops->PutImage)(pBackingDrawable, pBackingGC, depth, x - pBackingStore->x, y - pBackingStore->y, w, h, leftPad, format, pBits); EPILOGUE (pGC);}/*- *----------------------------------------------------------------------- * miBSDoCopy -- * Perform a CopyArea or CopyPlane within a window that has backing * store enabled. * * Results: * TRUE if the copy was performed or FALSE if a regular one should * be done. * * Side Effects: * Things are copied (no s***!) * * Notes: * The idea here is to form two regions that cover the source box. * One contains the exposed rectangles while the other contains * the obscured ones. An array of <box, drawable> pairs is then * formed where the <box> indicates the area to be copied and the * <drawable> indicates from where it is to be copied (exposed regions * come from the screen while obscured ones come from the backing * pixmap). The array 'sequence' is then filled with the indices of * the pairs in the order in which they should be copied to prevent * things from getting screwed up. A call is also made through the * backingGC to take care of any copying into the backing pixmap. * *----------------------------------------------------------------------- */static BoolmiBSDoCopy(pWin, pGC, srcx, srcy, w, h, dstx, dsty, plane, copyProc, ppRgn) WindowPtr pWin; /* Window being scrolled */ GCPtr pGC; /* GC we're called through */ int srcx; /* X of source rectangle */ int srcy; /* Y of source rectangle */ int w; /* Width of source rectangle */ int h; /* Height of source rectangle */ int dstx; /* X of destination rectangle */ int dsty; /* Y of destination rectangle */ unsigned long plane; /* Plane to copy (0 for CopyArea) */ RegionPtr (*copyProc)(); /* Procedure to call to perform the copy */ RegionPtr *ppRgn; /* resultant Graphics Expose region */{ RegionPtr pRgnExp; /* Exposed region */ RegionPtr pRgnObs; /* Obscured region */ BoxRec box; /* Source box (screen coord) */ struct BoxDraw { BoxPtr pBox; /* Source box */ enum { win, pix } source; /* Place from which to copy */ } *boxes; /* Array of box/drawable pairs covering * source box. */ int *sequence; /* Sequence of boxes to move */ register int i, j, k, l, y; register BoxPtr pBox; int dx, dy, nrects; Bool graphicsExposures; RegionPtr (*pixCopyProc)(); int numRectsExp, numRectsObs; BoxPtr pBoxExp, pBoxObs; SETUP_BACKING (pWin, pGC); /* * Create a region of exposed boxes in pRgnExp. */ box.x1 = srcx + pWin->drawable.x; box.x2 = box.x1 + w; box.y1 = srcy + pWin->drawable.y; box.y2 = box.y1 + h; pRgnExp = REGION_CREATE(pGC->pScreen, &box, 1); REGION_INTERSECT(pGC->pScreen, pRgnExp, pRgnExp, &pWin->clipList); pRgnObs = REGION_CREATE(pGC->pScreen, NULL, 1); REGION_INVERSE( pGC->pScreen, pRgnObs, pRgnExp, &box); /* * Translate regions into window coordinates for proper calls * to the copyProc, then make sure none of the obscured region sticks * into invalid areas of the backing pixmap. */ REGION_TRANSLATE(pGC->pScreen, pRgnExp, -pWin->drawable.x, -pWin->drawable.y); REGION_TRANSLATE(pGC->pScreen, pRgnObs, -pWin->drawable.x, -pWin->drawable.y); REGION_INTERSECT(pGC->pScreen, pRgnObs, pRgnObs, &pBackingStore->SavedRegion); /* * If the obscured region is empty, there's no point being fancy. */ if (!REGION_NOTEMPTY(pGC->pScreen, pRgnObs)) { REGION_DESTROY(pGC->pScreen, pRgnExp); REGION_DESTROY(pGC->pScreen, pRgnObs); return (FALSE); } numRectsExp = REGION_NUM_RECTS(pRgnExp); pBoxExp = REGION_RECTS(pRgnExp); pBoxObs = REGION_RECTS(pRgnObs); numRectsObs = REGION_NUM_RECTS(pRgnObs); nrects = numRectsExp + numRectsObs; boxes = (struct BoxDraw *)ALLOCATE_LOCAL(nrects * sizeof(struct BoxDraw)); sequence = (int *) ALLOCATE_LOCAL(nrects * sizeof(int)); *ppRgn = NULL; if (!boxes || !sequence) { if (sequence) DEALLOCATE_LOCAL(sequence); if (boxes) DEALLOCATE_LOCAL(boxes); REGION_DESTROY(pGC->pScreen, pRgnExp); REGION_DESTROY(pGC->pScreen, pRgnObs); return(TRUE); } /* * Order the boxes in the two regions so we know from which drawable * to copy which box, storing the result in the boxes array */ for (i = 0, j = 0, k = 0; (i < numRectsExp) && (j < numRectsObs); k++) { if (pBoxExp[i].y1 < pBoxObs[j].y1) { boxes[k].pBox = &pBoxExp[i]; boxes[k].source = win; i++; } else if ((pBoxObs[j].y1 < pBoxExp[i].y1) || (pBoxObs[j].x1 < pBoxExp[i].x1)) { boxes[k].pBox = &pBoxObs[j]; boxes[k].source = pix; j++; } else { boxes[k].pBox = &pBoxExp[i]; boxes[k].source = win; i++; } } /* * Catch any leftover boxes from either region (note that only * one can have leftover boxes...) */ if (i != numRectsExp) { do { boxes[k].pBox = &pBoxExp[i]; boxes[k].source = win; i++; k++; } while (i < numRectsExp); } else { do { boxes[k].pBox = &pBoxObs[j]; boxes[k].source = pix; j++; k++; } while (j < numRectsObs); } if (dsty <= srcy) { /* * Scroll up or vertically stationary, so vertical order is ok. */ if (dstx <= srcx) { /* * Scroll left or horizontally stationary, so horizontal order * is ok as well. */ for (i = 0; i < nrects; i++) { sequence[i] = i; } } else { /* * Scroll right. Need to reverse the rectangles within each * band. */ for (i = 0, j = 1, k = 0; i < nrects; j = i + 1, k = i) { y = boxes[i].pBox->y1; while ((j < nrects) && (boxes[j].pBox->y1 == y)) { j++; } for (j--; j >= k; j--, i++) { sequence[i] = j; } } } } else { /* * Scroll down. Must reverse vertical banding, at least. */ if (dstx < srcx) { /* * Scroll left. Horizontal order is ok. */ for (i = nrects - 1, j = i - 1, k = i, l = 0; i >= 0; j = i - 1, k = i) { /* * Find extent of current horizontal band, then reverse * the order of the whole band. */ y = boxes[i].pBox->y1; while ((j >= 0) && (boxes[j].pBox->y1 == y)) { j--; } for (j++; j <= k; j++, i--, l++) { sequence[l] = j; } } } else { /* * Scroll right or horizontal stationary. * Reverse horizontal order as well (if stationary, horizontal * order can be swapped without penalty and this is faster * to compute). */ for (i = 0, j = nrects - 1; i < nrects; i++, j--) { sequence[i] = j; } } } /* * XXX: To avoid getting multiple NoExpose events from this operation, * we turn OFF graphicsExposures in the gc and deal with any uncopied * areas later, if there's something not in backing-store. */ graphicsExposures = pGC->graphicsExposures; pGC->graphicsExposures = FALSE; dx = dstx - srcx; dy = dsty - srcy; /* * Figure out which copy procedure to use from the backing GC. Note we * must do this because some implementations (sun's, e.g.) have * pBackingGC a fake GC with the real one below it, thus the devPriv for * pBackingGC won't be what the output library expects. */ if (plane != 0) { pixCopyProc = pBackingGC->ops->CopyPlane; } else { pixCopyProc = pBackingGC->ops->CopyArea; } for (i = 0; i < nrects; i++) { pBox = boxes[sequence[i]].pBox; /* * If we're copying from the pixmap, we need to place its contents * onto the screen before scrolling the pixmap itself. If we're copying * from the window, we need to copy its contents into the pixmap before * we scroll the window itself. */ if (boxes[sequence[i]].source == pix) { (void) (* copyProc) (pBackingDrawable, pWin, pGC, pBox->x1 - pBackingStore->x, pBox->y1 - pBackingStore->y, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, pBox->x1 + dx, pBox->y1 + dy, plane); (void) (* pixCopyProc) (pBackingDrawable, pBackingDrawable, pBackingGC, pBox->x1 - pBackingStore->x, pBox->y1 - pBackingStore->y, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, pBox->x1 + dx - pBackingStore->x, pBox->y1 + dy - pBackingStore->y, plane); } else { (void) (* pixCopyProc) (pWin, pBackingDrawable, pBackingGC, pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, pBox->x1 + dx - pBackingStore->x, pBox->y1 + dy - pBackingStore->y, plane); (void) (* copyProc) (pWin, pWin, pGC, pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, pBox->x1 + dx, pBox->y1 + dy, plane); } } DEALLOCATE_LOCAL(sequence); DEALLOCATE_LOCAL(boxes); pGC->graphicsExposures = graphicsExposures; /* * Form union of rgnExp and rgnObs and see if covers entire area * to be copied. Store the resultant region for miBSCopyArea * to return to dispatch which will send the appropriate expose * events. */ REGION_UNION(pGC->pScreen, pRgnExp, pRgnExp, pRgnObs); box.x1 = srcx; box.x2 = srcx + w; box.y1 = srcy; box.y2 = srcy + h; if (RECT_IN_REGION(pGC->pScreen, pRgnExp, &box) == rgnIN) { REGION_EMPTY(pGC->pScreen, pRgnExp); } else { REGION_INVERSE( pGC->pScreen, pRgnExp, pRgnExp, &box); REGION_TRANSLATE( pGC->pScreen, pRgnExp, dx + pWin->drawable.x, dy + pWin->drawable.y); REGION_INTERSECT( pGC->pScreen, pRgnObs, pRgnExp, &pWin->clipList); (*pWin->drawable.pScreen->PaintWindowBackground) (pWin, pRgnObs, PW_BACKGROUND); REGION_TRANSLATE( pGC->pScreen, pRgnExp, -pWin->drawable.x, -pWin->drawable.y); miBSClearBackingRegion (pWin, pRgnExp); } if (graphicsExposures) *ppRgn = pRgnExp; else REGION_DESTROY(pGC->pScreen, pRgnExp); REGION_DESTROY(pGC->pScreen, pRgnObs); return (TRUE);}/*- *----------------------------------------------------------------------- * miBSCopyArea -- * Perform a CopyArea from the source to the destination, extracting * from the source's backing-store and storing into the destination's * backing-store without messing anything up. If the source and * destination are different, there's not too much to worry about: * we can just issue several calls to the regular CopyArea function. * * Results: * None. * * Side Effects: * *----------------------------------------------------------------------- */static RegionPtrmiBSCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty) DrawablePtr pSrc; DrawablePtr pDst; GCPtr pGC; int srcx; int srcy; int w; int h; int dstx; int dsty;{ BoxPtr pExtents; long dx, dy; int bsrcx, bsrcy, bw, bh, bdstx, bdsty; RegionPtr pixExposed = 0, winExposed = 0; SETUP_BACKING(pDst, pGC); PROLOGUE(pGC); if ((pSrc != pDst) || (!miBSDoCopy((WindowPtr)pSrc, pGC, srcx, srcy, w, h, dstx, dsty, (unsigned long) 0, pGC->ops->CopyArea, &winExposed))) { /* * always copy to the backing store first, miBSDoCopy * returns FALSE if the *source* region is disjoint * from the backing store saved region. So, copying * *to* the backing store is always safe */ if (pGC->clientClipType != CT_PIXMAP) { /* * adjust srcx, srcy, w, h, dstx, dsty to be clipped to * the backing store. An unnecessary optimisation, * but a useful one when GetSpans is slow. */ pExtents = REGION_EXTENTS(pDst->pScreen, (RegionPtr)pBackingGC->clientClip); bsrcx = srcx; bsrcy = srcy; bw = w; bh = h; bdstx = dstx; bdsty = dsty; dx = pExtents->x1 - bdstx; if (dx > 0) { bsrcx += dx; bdstx += dx; bw -= dx; } dy = pExtents->y1 - bdsty; if (dy > 0) { bsrcy += dy; bdsty += dy; bh -= dy; } dx = (bdstx + bw) - pExtents->x2; if (dx > 0) bw -= dx; dy = (bdsty + bh) - pExtents->y2; if (dy > 0) bh -= dy; if (bw > 0 && bh > 0) pixExposed = (* pBackingGC->ops->CopyArea) (pSrc, pBackingDrawable, pBackingGC, bsrcx, bsrcy, bw, bh, bdstx - pBackingStore->x, bdsty - pBackingStore->y); } else pixExposed = (* pBackingGC->ops->CopyArea) (pSrc, pBackingDrawable, pBackingGC, srcx, srcy, w, h, dstx - pBackingStore->x, dsty - pBackingStore->y); winExposed = (* pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); } /* * compute the composite graphics exposure region */ if (winExposed) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -