📄 mibitblt.c
字号:
/* First set the whole pixmap to 0 */ gcv[0].val = 0; dixChangeGC(NullClient, pGCT, GCBackground, NULL, gcv); ValidateGC((DrawablePtr)pPixmap, pGCT); miClearDrawable((DrawablePtr)pPixmap, pGCT); ppt = pptFirst = (DDXPointPtr)ALLOCATE_LOCAL(h * sizeof(DDXPointRec)); pwidth = pwidthFirst = (int *)ALLOCATE_LOCAL(h * sizeof(int)); if(!pptFirst || !pwidthFirst) { if (pwidthFirst) DEALLOCATE_LOCAL(pwidthFirst); if (pptFirst) DEALLOCATE_LOCAL(pptFirst); FreeScratchGC(pGCT); return; } /* we need a temporary region because ChangeClip must be assumed to destroy what it's sent. note that this means we don't have to free prgnSrcClip ourselves. */ prgnSrcClip = REGION_CREATE(pGCT->pScreen, NULL, 0); REGION_COPY(pGCT->pScreen, prgnSrcClip, prgnSrc); REGION_TRANSLATE(pGCT->pScreen, prgnSrcClip, srcx, 0); (*pGCT->funcs->ChangeClip)(pGCT, CT_REGION, prgnSrcClip, 0); ValidateGC((DrawablePtr)pPixmap, pGCT); /* Since we know pDraw is always a pixmap, we never need to think * about translation here */ for(i = 0; i < h; i++) { ppt->x = 0; ppt++->y = i; *pwidth++ = w + srcx; } (*pGCT->ops->SetSpans)((DrawablePtr)pPixmap, pGCT, (char *)pbits, pptFirst, pwidthFirst, h, TRUE); DEALLOCATE_LOCAL(pwidthFirst); DEALLOCATE_LOCAL(pptFirst); /* Save current values from the client GC */ oldfill = pGC->fillStyle; pStipple = pGC->stipple; if(pStipple) pStipple->refcnt++; oldOrg = pGC->patOrg; /* Set a new stipple in the drawable */ gcv[0].val = FillStippled; gcv[1].ptr = pPixmap; gcv[2].val = dstx - srcx; gcv[3].val = dsty; dixChangeGC(NullClient, pGC, GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin, NULL, gcv); ValidateGC(pDraw, pGC); /* Fill the drawable with the stipple. This will draw the * foreground color whereever 1 bits are set, leaving everything * with 0 bits untouched. Note that the part outside the clip * region is all 0s. */ rect.x = dstx; rect.y = dsty; rect.width = w; rect.height = h; (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); /* Invert the tiling pixmap. This sets 0s for 1s and 1s for 0s, only * within the clipping region, the part outside is still all 0s */ gcv[0].val = GXinvert; dixChangeGC(NullClient, pGCT, GCFunction, NULL, gcv); ValidateGC((DrawablePtr)pPixmap, pGCT); (*pGCT->ops->CopyArea)((DrawablePtr)pPixmap, (DrawablePtr)pPixmap, pGCT, 0, 0, w + srcx, h, 0, 0); /* Swap foreground and background colors on the GC for the drawable. * Now when we fill the drawable, we will fill in the "Background" * values */ oldfg = pGC->fgPixel; gcv[0].val = pGC->bgPixel; gcv[1].val = oldfg; gcv[2].ptr = pPixmap; dixChangeGC(NullClient, pGC, GCForeground | GCBackground | GCStipple, NULL, gcv); ValidateGC(pDraw, pGC); /* PolyFillRect might have bashed the rectangle */ rect.x = dstx; rect.y = dsty; rect.width = w; rect.height = h; (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); /* Now put things back */ if(pStipple) pStipple->refcnt--; gcv[0].val = oldfg; gcv[1].val = pGC->fgPixel; gcv[2].val = oldfill; gcv[3].ptr = pStipple; gcv[4].val = oldOrg.x; gcv[5].val = oldOrg.y; dixChangeGC(NullClient, pGC, GCForeground | GCBackground | GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin, NULL, gcv); ValidateGC(pDraw, pGC); /* put what we hope is a smaller clip region back in the scratch gc */ (*pGCT->funcs->ChangeClip)(pGCT, CT_NONE, NULL, 0); FreeScratchGC(pGCT); (*pDraw->pScreen->DestroyPixmap)(pPixmap);}/* MICOPYPLANE -- public entry for the CopyPlane request. * strategy: * First build up a bitmap out of the bits requested * build a source clip * Use the bitmap we've built up as a Stipple for the destination */RegionPtrmiCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane) DrawablePtr pSrcDrawable; DrawablePtr pDstDrawable; GCPtr pGC; int srcx, srcy; int width, height; int dstx, dsty; unsigned long bitPlane;{ unsigned long *ptile; BoxRec box; RegionPtr prgnSrc, prgnExposed; /* incorporate the source clip */ box.x1 = srcx + pSrcDrawable->x; box.y1 = srcy + pSrcDrawable->y; box.x2 = box.x1 + width; box.y2 = box.y1 + height; /* clip to visible drawable */ if (box.x1 < pSrcDrawable->x) box.x1 = pSrcDrawable->x; if (box.y1 < pSrcDrawable->y) box.y1 = pSrcDrawable->y; if (box.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; if (box.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; if (box.x1 > box.x2) box.x2 = box.x1; if (box.y1 > box.y2) box.y2 = box.y1; prgnSrc = REGION_CREATE(pGC->pScreen, &box, 1); if (pSrcDrawable->type != DRAWABLE_PIXMAP) { /* clip to visible drawable */ if (pGC->subWindowMode == IncludeInferiors) { RegionPtr clipList = NotClippedByChildren ((WindowPtr) pSrcDrawable); REGION_INTERSECT(pGC->pScreen, prgnSrc, prgnSrc, clipList); REGION_DESTROY(pGC->pScreen, clipList); } else REGION_INTERSECT(pGC->pScreen, prgnSrc, prgnSrc, &((WindowPtr)pSrcDrawable)->clipList); } box = *REGION_EXTENTS(pGC->pScreen, prgnSrc); REGION_TRANSLATE(pGC->pScreen, prgnSrc, -box.x1, -box.y1); if ((box.x2 > box.x1) && (box.y2 > box.y1)) { /* minimize the size of the data extracted */ /* note that we convert the plane mask bitPlane into a plane number */ box.x1 -= pSrcDrawable->x; box.x2 -= pSrcDrawable->x; box.y1 -= pSrcDrawable->y; box.y2 -= pSrcDrawable->y; ptile = miGetPlane(pSrcDrawable, ffsl(bitPlane) - 1, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1, (unsigned long *) NULL); if (ptile) { miOpqStipDrawable(pDstDrawable, pGC, prgnSrc, ptile, 0, box.x2 - box.x1, box.y2 - box.y1, dstx + box.x1 - srcx, dsty + box.y1 - srcy); xfree(ptile); } } prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); REGION_DESTROY(pGC->pScreen, prgnSrc); return prgnExposed;}/* MIGETIMAGE -- public entry for the GetImage Request * We're getting the image into a memory buffer. While we have to use GetSpans * to read a line from the device (since we don't know what that looks like), * we can just write into the destination buffer * * two different strategies are used, depending on whether we're getting the * image in Z format or XY format * Z format: * Line at a time, GetSpans a line into the destination buffer, then if the * planemask is not all ones, we do a SetSpans into a temporary buffer (to get * bits turned off) and then another GetSpans to get stuff back (because * pixmaps are opaque, and we are passed in the memory to write into). This is * pretty ugly and slow but works. Life is hard. * XY format: * get the single plane specified in planemask */voidmiGetImage(pDraw, sx, sy, w, h, format, planeMask, pDst) DrawablePtr pDraw; int sx, sy, w, h; unsigned int format; unsigned long planeMask; char * pDst;{ unsigned char depth; int i, linelength, width, srcx, srcy; DDXPointRec pt; XID gcv[2]; PixmapPtr pPixmap = (PixmapPtr)NULL; GCPtr pGC; depth = pDraw->depth; if(format == ZPixmap) { if ( (((1<<depth)-1)&planeMask) != (1<<depth)-1 ) { xPoint pt; pGC = GetScratchGC(depth, pDraw->pScreen); if (!pGC) return; pPixmap = (*pDraw->pScreen->CreatePixmap) (pDraw->pScreen, w, 1, depth); if (!pPixmap) { FreeScratchGC(pGC); return; } /* * Clear the pixmap before doing anything else */ ValidateGC((DrawablePtr)pPixmap, pGC); pt.x = pt.y = 0; (*pGC->ops->FillSpans)((DrawablePtr)pPixmap, pGC, 1, &pt, &width, TRUE); /* alu is already GXCopy */ gcv[0] = (XID)planeMask; DoChangeGC(pGC, GCPlaneMask, gcv, 0); ValidateGC((DrawablePtr)pPixmap, pGC); } linelength = PixmapBytePad(w, depth); srcx = sx + pDraw->x; srcy = sy + pDraw->y; for(i = 0; i < h; i++) { pt.x = srcx; pt.y = srcy + i; width = w; (*pDraw->pScreen->GetSpans)(pDraw, w, &pt, &width, 1, pDst); if (pPixmap) { pt.x = 0; pt.y = 0; width = w; (*pGC->ops->SetSpans)((DrawablePtr)pPixmap, pGC, pDst, &pt, &width, 1, TRUE); (*pDraw->pScreen->GetSpans)((DrawablePtr)pPixmap, w, &pt, &width, 1, pDst); } pDst += linelength; } if (pPixmap) { (*pGC->pScreen->DestroyPixmap)(pPixmap); FreeScratchGC(pGC); } } else { (void) miGetPlane(pDraw, ffsl(planeMask) - 1, sx, sy, w, h, (unsigned long *)pDst); }}/* MIPUTIMAGE -- public entry for the PutImage request * Here we benefit from knowing the format of the bits pointed to by pImage, * even if we don't know how pDraw represents them. * Three different strategies are used depending on the format * XYBitmap Format: * we just use the Opaque Stipple helper function to cover the destination * Note that this covers all the planes of the drawable with the * foreground color (masked with the GC planemask) where there are 1 bits * and the background color (masked with the GC planemask) where there are * 0 bits * XYPixmap format: * what we're called with is a series of XYBitmaps, but we only want * each XYPixmap to update 1 plane, instead of updating all of them. * we set the foreground color to be all 1s and the background to all 0s * then for each plane, we set the plane mask to only effect that one * plane and recursive call ourself with the format set to XYBitmap * (This clever idea courtesy of RGD.) * ZPixmap format: * This part is simple, just call SetSpans */voidmiPutImage(pDraw, pGC, depth, x, y, w, h, leftPad, format, pImage) DrawablePtr pDraw; GCPtr pGC; int depth, x, y, w, h, leftPad; int format; char *pImage;{ DDXPointPtr pptFirst, ppt; int *pwidthFirst, *pwidth; RegionPtr prgnSrc; BoxRec box; unsigned long oldFg, oldBg; XID gcv[3]; unsigned long oldPlanemask; unsigned long i; long bytesPer; if (!w || !h) return; switch(format) { case XYBitmap: box.x1 = 0; box.y1 = 0; box.x2 = w; box.y2 = h; prgnSrc = REGION_CREATE(pGC->pScreen, &box, 1); miOpqStipDrawable(pDraw, pGC, prgnSrc, (unsigned long *) pImage, leftPad, w, h, x, y); REGION_DESTROY(pGC->pScreen, prgnSrc); break; case XYPixmap: depth = pGC->depth; oldPlanemask = pGC->planemask; oldFg = pGC->fgPixel; oldBg = pGC->bgPixel; gcv[0] = (XID)~0; gcv[1] = (XID)0; DoChangeGC(pGC, GCForeground | GCBackground, gcv, 0); bytesPer = (long)h * BitmapBytePad(w + leftPad); for (i = 1 << (depth-1); i != 0; i >>= 1, pImage += bytesPer) { if (i & oldPlanemask) { gcv[0] = (XID)i; DoChangeGC(pGC, GCPlaneMask, gcv, 0); ValidateGC(pDraw, pGC); (*pGC->ops->PutImage)(pDraw, pGC, 1, x, y, w, h, leftPad, XYBitmap, (char *)pImage); } } gcv[0] = (XID)oldPlanemask; gcv[1] = (XID)oldFg; gcv[2] = (XID)oldBg; DoChangeGC(pGC, GCPlaneMask | GCForeground | GCBackground, gcv, 0); break; case ZPixmap: ppt = pptFirst = (DDXPointPtr)ALLOCATE_LOCAL(h * sizeof(DDXPointRec)); pwidth = pwidthFirst = (int *)ALLOCATE_LOCAL(h * sizeof(int)); if(!pptFirst || !pwidthFirst) { if (pwidthFirst) DEALLOCATE_LOCAL(pwidthFirst); if (pptFirst) DEALLOCATE_LOCAL(pptFirst); return; } if (pGC->miTranslate) { x += pDraw->x; y += pDraw->y; } for(i = 0; i < h; i++) { ppt->x = x; ppt->y = y + i; ppt++; *pwidth++ = w; } (*pGC->ops->SetSpans)(pDraw, pGC, (char *)pImage, pptFirst, pwidthFirst, h, TRUE); DEALLOCATE_LOCAL(pwidthFirst); DEALLOCATE_LOCAL(pptFirst); break; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -