mirror of
https://github.com/X11Libre/xserver.git
synced 2026-09-22 20:35:43 +00:00
R6.6 is the Xorg base-line
This commit is contained in:
parent
cb6ef07bf0
commit
ded6147bfb
609 changed files with 262690 additions and 0 deletions
818
mi/mibitblt.c
Normal file
818
mi/mibitblt.c
Normal file
|
|
@ -0,0 +1,818 @@
|
|||
/***********************************************************
|
||||
|
||||
Copyright 1987, 1998 The Open Group
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of The Open Group shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from The Open Group.
|
||||
|
||||
|
||||
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the name of Digital not be
|
||||
used in advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
||||
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
SOFTWARE.
|
||||
|
||||
******************************************************************/
|
||||
/* $Xorg: mibitblt.c,v 1.5 2001/02/09 02:05:20 xorgcvs Exp $ */
|
||||
/* Author: Todd Newman (aided and abetted by Mr. Drewry) */
|
||||
|
||||
#include "X.h"
|
||||
#include "Xprotostr.h"
|
||||
|
||||
#include "misc.h"
|
||||
#include "gcstruct.h"
|
||||
#include "pixmapstr.h"
|
||||
#include "windowstr.h"
|
||||
#include "scrnintstr.h"
|
||||
#include "mi.h"
|
||||
#include "regionstr.h"
|
||||
#include "Xmd.h"
|
||||
#include "servermd.h"
|
||||
|
||||
/* MICOPYAREA -- public entry for the CopyArea request
|
||||
* For each rectangle in the source region
|
||||
* get the pixels with GetSpans
|
||||
* set them in the destination with SetSpans
|
||||
* We let SetSpans worry about clipping to the destination.
|
||||
*/
|
||||
RegionPtr
|
||||
miCopyArea(pSrcDrawable, pDstDrawable,
|
||||
pGC, xIn, yIn, widthSrc, heightSrc, xOut, yOut)
|
||||
register DrawablePtr pSrcDrawable;
|
||||
register DrawablePtr pDstDrawable;
|
||||
GCPtr pGC;
|
||||
int xIn, yIn;
|
||||
int widthSrc, heightSrc;
|
||||
int xOut, yOut;
|
||||
{
|
||||
DDXPointPtr ppt, pptFirst;
|
||||
unsigned int *pwidthFirst, *pwidth, *pbits;
|
||||
BoxRec srcBox, *prect;
|
||||
/* may be a new region, or just a copy */
|
||||
RegionPtr prgnSrcClip;
|
||||
/* non-0 if we've created a src clip */
|
||||
RegionPtr prgnExposed;
|
||||
int realSrcClip = 0;
|
||||
int srcx, srcy, dstx, dsty, i, j, y, width, height,
|
||||
xMin, xMax, yMin, yMax;
|
||||
unsigned int *ordering;
|
||||
int numRects;
|
||||
BoxPtr boxes;
|
||||
|
||||
srcx = xIn + pSrcDrawable->x;
|
||||
srcy = yIn + pSrcDrawable->y;
|
||||
|
||||
/* If the destination isn't realized, this is easy */
|
||||
if (pDstDrawable->type == DRAWABLE_WINDOW &&
|
||||
!((WindowPtr)pDstDrawable)->realized)
|
||||
return (RegionPtr)NULL;
|
||||
|
||||
/* clip the source */
|
||||
if (pSrcDrawable->type == DRAWABLE_PIXMAP)
|
||||
{
|
||||
BoxRec box;
|
||||
|
||||
box.x1 = pSrcDrawable->x;
|
||||
box.y1 = pSrcDrawable->y;
|
||||
box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
|
||||
box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
|
||||
|
||||
prgnSrcClip = REGION_CREATE(pGC->pScreen, &box, 1);
|
||||
realSrcClip = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pGC->subWindowMode == IncludeInferiors) {
|
||||
prgnSrcClip = NotClippedByChildren ((WindowPtr) pSrcDrawable);
|
||||
realSrcClip = 1;
|
||||
} else
|
||||
prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
|
||||
}
|
||||
|
||||
/* If the src drawable is a window, we need to translate the srcBox so
|
||||
* that we can compare it with the window's clip region later on. */
|
||||
srcBox.x1 = srcx;
|
||||
srcBox.y1 = srcy;
|
||||
srcBox.x2 = srcx + widthSrc;
|
||||
srcBox.y2 = srcy + heightSrc;
|
||||
|
||||
dstx = xOut;
|
||||
dsty = yOut;
|
||||
if (pGC->miTranslate)
|
||||
{
|
||||
dstx += pDstDrawable->x;
|
||||
dsty += pDstDrawable->y;
|
||||
}
|
||||
|
||||
pptFirst = ppt = (DDXPointPtr)
|
||||
ALLOCATE_LOCAL(heightSrc * sizeof(DDXPointRec));
|
||||
pwidthFirst = pwidth = (unsigned int *)
|
||||
ALLOCATE_LOCAL(heightSrc * sizeof(unsigned int));
|
||||
numRects = REGION_NUM_RECTS(prgnSrcClip);
|
||||
boxes = REGION_RECTS(prgnSrcClip);
|
||||
ordering = (unsigned int *)
|
||||
ALLOCATE_LOCAL(numRects * sizeof(unsigned int));
|
||||
if(!pptFirst || !pwidthFirst || !ordering)
|
||||
{
|
||||
if (ordering)
|
||||
DEALLOCATE_LOCAL(ordering);
|
||||
if (pwidthFirst)
|
||||
DEALLOCATE_LOCAL(pwidthFirst);
|
||||
if (pptFirst)
|
||||
DEALLOCATE_LOCAL(pptFirst);
|
||||
return (RegionPtr)NULL;
|
||||
}
|
||||
|
||||
/* If not the same drawable then order of move doesn't matter.
|
||||
Following assumes that boxes are sorted from top
|
||||
to bottom and left to right.
|
||||
*/
|
||||
if ((pSrcDrawable != pDstDrawable) &&
|
||||
((pGC->subWindowMode != IncludeInferiors) ||
|
||||
(pSrcDrawable->type == DRAWABLE_PIXMAP) ||
|
||||
(pDstDrawable->type == DRAWABLE_PIXMAP)))
|
||||
for (i=0; i < numRects; i++)
|
||||
ordering[i] = i;
|
||||
else { /* within same drawable, must sequence moves carefully! */
|
||||
if (dsty <= srcBox.y1) { /* Scroll up or stationary vertical.
|
||||
Vertical order OK */
|
||||
if (dstx <= srcBox.x1) /* Scroll left or stationary horizontal.
|
||||
Horizontal order OK as well */
|
||||
for (i=0; i < numRects; i++)
|
||||
ordering[i] = i;
|
||||
else { /* scroll right. must reverse horizontal banding of rects. */
|
||||
for (i=0, j=1, xMax=0; i < numRects; j=i+1, xMax=i) {
|
||||
/* find extent of current horizontal band */
|
||||
y=boxes[i].y1; /* band has this y coordinate */
|
||||
while ((j < numRects) && (boxes[j].y1 == y))
|
||||
j++;
|
||||
/* reverse the horizontal band in the output ordering */
|
||||
for (j-- ; j >= xMax; j--, i++)
|
||||
ordering[i] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* Scroll down. Must reverse vertical banding. */
|
||||
if (dstx < srcBox.x1) { /* Scroll left. Horizontal order OK. */
|
||||
for (i=numRects-1, j=i-1, yMin=i, yMax=0;
|
||||
i >= 0;
|
||||
j=i-1, yMin=i) {
|
||||
/* find extent of current horizontal band */
|
||||
y=boxes[i].y1; /* band has this y coordinate */
|
||||
while ((j >= 0) && (boxes[j].y1 == y))
|
||||
j--;
|
||||
/* reverse the horizontal band in the output ordering */
|
||||
for (j++ ; j <= yMin; j++, i--, yMax++)
|
||||
ordering[yMax] = 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=numRects-1; i < numRects; i++, j--)
|
||||
ordering[i] = j;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < numRects; i++)
|
||||
{
|
||||
prect = &boxes[ordering[i]];
|
||||
xMin = max(prect->x1, srcBox.x1);
|
||||
xMax = min(prect->x2, srcBox.x2);
|
||||
yMin = max(prect->y1, srcBox.y1);
|
||||
yMax = min(prect->y2, srcBox.y2);
|
||||
/* is there anything visible here? */
|
||||
if(xMax <= xMin || yMax <= yMin)
|
||||
continue;
|
||||
|
||||
ppt = pptFirst;
|
||||
pwidth = pwidthFirst;
|
||||
y = yMin;
|
||||
height = yMax - yMin;
|
||||
width = xMax - xMin;
|
||||
|
||||
for(j = 0; j < height; j++)
|
||||
{
|
||||
/* We must untranslate before calling GetSpans */
|
||||
ppt->x = xMin;
|
||||
ppt++->y = y++;
|
||||
*pwidth++ = width;
|
||||
}
|
||||
pbits = (unsigned int *)xalloc(height * PixmapBytePad(width,
|
||||
pSrcDrawable->depth));
|
||||
if (pbits)
|
||||
{
|
||||
(*pSrcDrawable->pScreen->GetSpans)(pSrcDrawable, width, pptFirst,
|
||||
(int *)pwidthFirst, height, (char *)pbits);
|
||||
ppt = pptFirst;
|
||||
pwidth = pwidthFirst;
|
||||
xMin -= (srcx - dstx);
|
||||
y = yMin - (srcy - dsty);
|
||||
for(j = 0; j < height; j++)
|
||||
{
|
||||
ppt->x = xMin;
|
||||
ppt++->y = y++;
|
||||
*pwidth++ = width;
|
||||
}
|
||||
|
||||
(*pGC->ops->SetSpans)(pDstDrawable, pGC, (char *)pbits, pptFirst,
|
||||
(int *)pwidthFirst, height, TRUE);
|
||||
xfree(pbits);
|
||||
}
|
||||
}
|
||||
prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
|
||||
widthSrc, heightSrc, xOut, yOut, (unsigned long)0);
|
||||
if(realSrcClip)
|
||||
REGION_DESTROY(pGC->pScreen, prgnSrcClip);
|
||||
|
||||
DEALLOCATE_LOCAL(ordering);
|
||||
DEALLOCATE_LOCAL(pwidthFirst);
|
||||
DEALLOCATE_LOCAL(pptFirst);
|
||||
return prgnExposed;
|
||||
}
|
||||
|
||||
/* MIGETPLANE -- gets a bitmap representing one plane of pDraw
|
||||
* A helper used for CopyPlane and XY format GetImage
|
||||
* No clever strategy here, we grab a scanline at a time, pull out the
|
||||
* bits and then stuff them in a 1 bit deep map.
|
||||
*/
|
||||
static
|
||||
unsigned long *
|
||||
miGetPlane(pDraw, planeNum, sx, sy, w, h, result)
|
||||
DrawablePtr pDraw;
|
||||
int planeNum; /* number of the bitPlane */
|
||||
int sx, sy, w, h;
|
||||
unsigned long *result;
|
||||
{
|
||||
int i, j, k, width, bitsPerPixel, widthInBytes;
|
||||
DDXPointRec pt;
|
||||
unsigned long pixel;
|
||||
unsigned long bit;
|
||||
unsigned char *pCharsOut;
|
||||
|
||||
#if BITMAP_SCANLINE_UNIT == 8
|
||||
#define OUT_TYPE unsigned char
|
||||
#endif
|
||||
#if BITMAP_SCANLINE_UNIT == 16
|
||||
#define OUT_TYPE CARD16
|
||||
#endif
|
||||
#if BITMAP_SCANLINE_UNIT == 32
|
||||
#define OUT_TYPE CARD32
|
||||
#endif
|
||||
#if BITMAP_SCANLINE_UNIT == 64
|
||||
#define OUT_TYPE CARD64
|
||||
#endif
|
||||
|
||||
OUT_TYPE *pOut;
|
||||
int delta;
|
||||
|
||||
sx += pDraw->x;
|
||||
sy += pDraw->y;
|
||||
widthInBytes = BitmapBytePad(w);
|
||||
if(!result)
|
||||
result = (unsigned long *)xalloc(h * widthInBytes);
|
||||
if (!result)
|
||||
return (unsigned long *)NULL;
|
||||
bitsPerPixel = pDraw->bitsPerPixel;
|
||||
bzero((char *)result, h * widthInBytes);
|
||||
pOut = (OUT_TYPE *) result;
|
||||
if(bitsPerPixel == 1)
|
||||
{
|
||||
pCharsOut = (unsigned char *) result;
|
||||
width = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = (widthInBytes / (BITMAP_SCANLINE_UNIT / 8)) -
|
||||
(w / BITMAP_SCANLINE_UNIT);
|
||||
width = 1;
|
||||
#if IMAGE_BYTE_ORDER == MSBFirst
|
||||
planeNum += (32 - bitsPerPixel);
|
||||
#endif
|
||||
}
|
||||
pt.y = sy;
|
||||
for (i = h; --i >= 0; pt.y++)
|
||||
{
|
||||
pt.x = sx;
|
||||
if(bitsPerPixel == 1)
|
||||
{
|
||||
(*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1,
|
||||
(char *)pCharsOut);
|
||||
pCharsOut += widthInBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
k = 0;
|
||||
for(j = w; --j >= 0; pt.x++)
|
||||
{
|
||||
/* Fetch the next pixel */
|
||||
(*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1,
|
||||
(char *)&pixel);
|
||||
/*
|
||||
* Now get the bit and insert into a bitmap in XY format.
|
||||
*/
|
||||
bit = (pixel >> planeNum) & 1;
|
||||
/* XXX assuming bit order == byte order */
|
||||
#if BITMAP_BIT_ORDER == LSBFirst
|
||||
bit <<= k;
|
||||
#else
|
||||
bit <<= ((BITMAP_SCANLINE_UNIT - 1) - k);
|
||||
#endif
|
||||
*pOut |= (OUT_TYPE) bit;
|
||||
k++;
|
||||
if (k == BITMAP_SCANLINE_UNIT)
|
||||
{
|
||||
pOut++;
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
pOut += delta;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
|
||||
}
|
||||
|
||||
/* MIOPQSTIPDRAWABLE -- use pbits as an opaque stipple for pDraw.
|
||||
* Drawing through the clip mask we SetSpans() the bits into a
|
||||
* bitmap and stipple those bits onto the destination drawable by doing a
|
||||
* PolyFillRect over the whole drawable,
|
||||
* then we invert the bitmap by copying it onto itself with an alu of
|
||||
* GXinvert, invert the foreground/background colors of the gc, and draw
|
||||
* the background bits.
|
||||
* Note how the clipped out bits of the bitmap are always the background
|
||||
* color so that the stipple never causes FillRect to draw them.
|
||||
*/
|
||||
void
|
||||
miOpqStipDrawable(pDraw, pGC, prgnSrc, pbits, srcx, w, h, dstx, dsty)
|
||||
DrawablePtr pDraw;
|
||||
GCPtr pGC;
|
||||
RegionPtr prgnSrc;
|
||||
unsigned long *pbits;
|
||||
int srcx, w, h, dstx, dsty;
|
||||
{
|
||||
int oldfill, i;
|
||||
unsigned long oldfg;
|
||||
int *pwidth, *pwidthFirst;
|
||||
ChangeGCVal gcv[6];
|
||||
PixmapPtr pStipple, pPixmap;
|
||||
DDXPointRec oldOrg;
|
||||
GCPtr pGCT;
|
||||
DDXPointPtr ppt, pptFirst;
|
||||
xRectangle rect;
|
||||
RegionPtr prgnSrcClip;
|
||||
|
||||
pPixmap = (*pDraw->pScreen->CreatePixmap)
|
||||
(pDraw->pScreen, w + srcx, h, 1);
|
||||
if (!pPixmap)
|
||||
return;
|
||||
|
||||
/* Put the image into a 1 bit deep pixmap */
|
||||
pGCT = GetScratchGC(1, pDraw->pScreen);
|
||||
if (!pGCT)
|
||||
{
|
||||
(*pDraw->pScreen->DestroyPixmap)(pPixmap);
|
||||
return;
|
||||
}
|
||||
/* 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
|
||||
*/
|
||||
RegionPtr
|
||||
miCopyPlane(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, ffs(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
|
||||
*/
|
||||
void
|
||||
miGetImage(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;
|
||||
width = w;
|
||||
(*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, ffs(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
|
||||
*/
|
||||
void
|
||||
miPutImage(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;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue