Commit 97da8cc7 authored by Roman Gilg's avatar Roman Gilg

Scale DoGetImage

parent f203ff0c
......@@ -379,6 +379,9 @@ compSetOwnerSize(WindowPtr pWin, CARD16 ownerWidth, CARD16 ownerHeight, ClientPt
int
compSendOwnerSizeCoreEvents(WindowPtr pWin);
void
compScalePicture(WindowPtr pWin, PicturePtr picture, double *xscale, double *yscale);
void PanoramiXCompositeInit(void);
void PanoramiXCompositeReset(void);
......
......@@ -717,6 +717,34 @@ compGetRedirectBorderClip(WindowPtr pWin)
return &cw->borderClip;
}
void
compScalePicture(WindowPtr pWin, PicturePtr picture, double *xscale, double *yscale)
{
CARD16 bw = pWin->borderWidth;
CARD16 actualWidth = pWin->drawable.width;
CARD16 actualHeight = pWin->drawable.height;
CARD16 clientWidth = wOwnerWidth(pWin);
CARD16 clientHeight = wOwnerHeight(pWin);
if (actualWidth != clientWidth || actualHeight != clientHeight) {
double trans_x, trans_y;
*xscale = (double) clientWidth / (double) actualWidth;
*yscale = (double) clientHeight / (double) actualHeight;
trans_x = (1.0 - *xscale) * bw;
trans_y = (1.0 - *yscale) * bw;
PictTransform transform = (PictTransform) {
.matrix = {
{ pixman_double_to_fixed(*xscale), 0, pixman_double_to_fixed(trans_x) },
{ 0, pixman_double_to_fixed(*yscale), pixman_double_to_fixed(trans_y) },
{ 0, 0, pixman_int_to_fixed(1) }
}
};
SetPictureTransform(picture, &transform);
SetPictureFilter(picture, FilterBilinear, -1, NULL, 0);
}
}
static void
compWindowUpdateAutomatic(WindowPtr pWin)
{
......@@ -746,31 +774,11 @@ compWindowUpdateAutomatic(WindowPtr pWin)
* Scale
*/
if (wOwnerSized(pWin)) {
CARD16 bw = pWin->borderWidth;
CARD16 actualWidth = pWin->drawable.width;
CARD16 actualHeight = pWin->drawable.height;
CARD16 clientWidth = wOwnerWidth(pWin);
CARD16 clientHeight = wOwnerHeight(pWin);
if (actualWidth != clientWidth || actualHeight != clientHeight) {
double xscale = (double) clientWidth / (double) actualWidth;
double yscale = (double) clientHeight / (double) actualHeight;
double trans_x = (1.0 - xscale) * bw;
double trans_y = (1.0 - yscale) * bw;
PictTransform transform = (PictTransform) {
.matrix = {
{ pixman_double_to_fixed(xscale), 0, pixman_double_to_fixed(trans_x) },
{ 0, pixman_double_to_fixed(yscale), pixman_double_to_fixed(trans_y) },
{ 0, 0, pixman_int_to_fixed(1) }
}
};
SetPictureTransform(pSrcPicture, &transform);
compScaleRegion(pRegion, 1.0/xscale, 1.0/yscale);
width = pWin->drawable.width + bw * 2;
height = pWin->drawable.height + bw * 2;
SetPictureFilter(pSrcPicture, FilterBilinear, -1, NULL, 0);
}
double xscale, yscale;
compScalePicture(pWin, pSrcPicture, &xscale, &yscale);
compScaleRegion(pRegion, 1.0/xscale, 1.0/yscale);
width = pWin->drawable.width + pWin->borderWidth * 2;
height = pWin->drawable.height + pWin->borderWidth * 2;
}
/*
......
......@@ -135,6 +135,10 @@ int ProcInitialConnection();
#include "probes.h"
#endif
#ifdef COMPOSITE
#include "compint.h"
#endif
#define mskcnt ((MAXCLIENTS + 31) / 32)
#define BITMASK(i) (1U << ((i) & 31))
#define MASKIDX(i) ((i) >> 5)
......@@ -2084,6 +2088,7 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
Bool internal;
double scaleX = 1.;
double scaleY = 1.;
PixmapPtr pDstPixmap = NULL;
/* coordinates relative to the bounding drawable */
int relx, rely;
......@@ -2095,11 +2100,12 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
if ((format != XYPixmap) && (format != ZPixmap)) {
client->errorValue = format;
return BadValue;
rc = BadValue;
goto out;
}
rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
if (rc != Success)
return rc;
goto out;
memset(&xgi, 0, sizeof(xGetImageReply));
......@@ -2112,16 +2118,23 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
/* "If the drawable is a window, the window must be viewable ... or a
* BadMatch error results" */
if (!pWin->viewable)
return BadMatch;
if (!pWin->viewable) {
rc = BadMatch;
goto out;
}
// TODO: this is still in owner-size
pVisibleRegion = &pWin->borderClip;
/* If the drawable is a window, the rectangle must be contained within
* its bounds (including the border). */
if (x < -wBorderWidth(pWin) ||
x + width > wBorderWidth(pWin) + (int) pDraw->width ||
y < -wBorderWidth(pWin) ||
y + height > wBorderWidth(pWin) + (int) pDraw->height)
return BadMatch;
y + height > wBorderWidth(pWin) + (int) pDraw->height) {
rc = BadMatch;
goto out;
}
relx += pDraw->x;
rely += pDraw->y;
......@@ -2134,15 +2147,46 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
#ifdef COMPOSITE
relx -= pPix->screen_x;
rely -= pPix->screen_y;
#endif
if (!internal) {
/* need to translate owner-size */
scaleX = (pBoundingDraw->width - relx) / (double) pWin->drawable.width;
scaleY = (pBoundingDraw->height -rely) / (double) pWin->drawable.height;
if (!internal && wOwnerSized(pWin)) {
PicturePtr pDstPicture, pSrcPicture;
PictFormatPtr pFormat = PictureWindowFormat(pWin);
int error;
pDstPixmap = pDraw->pScreen->CreatePixmap(pDraw->pScreen,
pDraw->width,
pDraw->height,
pDraw->depth,
CREATE_PIXMAP_USAGE_SCRATCH);
if (!pDstPixmap) {
rc = BadAlloc;
goto out;
}
pSrcPicture = CreatePicture(0, pDraw,
pFormat,
0, 0,
serverClient,
&error);
pDstPicture = CreatePicture(0, &pDstPixmap->drawable,
pFormat,
0, 0,
serverClient,
&error);
compScalePicture(pWin, pSrcPicture, &scaleX, &scaleY);
CompositePicture(PictOpSrc, pSrcPicture, 0, pDstPicture,
0, 0, /* src_x, src_y */
0, 0, /* msk_x, msk_y */
relx,
rely,
pWin->drawable.width + pWin->borderWidth * 2,
pWin->drawable.width + pWin->borderWidth * 2);
FreePicture(pSrcPicture, 0);
FreePicture(pDstPicture, 0);
}
#endif
}
else {
pBoundingDraw = (DrawablePtr) pDraw->pScreen->root;
}
......@@ -2166,8 +2210,10 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
* means that a GetImage request may succeed or fail with BadMatch depending
* on whether any of its ancestor windows are redirected. */
if (relx < 0 || relx + width * scaleX > (int) pBoundingDraw->width ||
rely < 0 || rely + height * scaleY > (int) pBoundingDraw->height)
return BadMatch;
rely < 0 || rely + height * scaleY > (int) pBoundingDraw->height) {
rc = BadMatch;
goto out;
}
xgi.type = X_Reply;
xgi.sequenceNumber = client->sequence;
......@@ -2211,17 +2257,19 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
length += widthBytesLine;
}
}
if (!(pBuf = calloc(1, length)))
return BadAlloc;
if (!(pBuf = calloc(1, length))) {
rc = BadAlloc;
goto out;
}
WriteReplyToClient(client, sizeof(xGetImageReply), &xgi);
if (pDraw->type == DRAWABLE_WINDOW)
pVisibleRegion = &((WindowPtr) pDraw)->borderClip;
if (linesPerBuf == 0) {
/* nothing to do */
}
else if (format == ZPixmap) {
if (pDstPixmap != NULL)
pDraw = &pDstPixmap->drawable;
linesDone = 0;
while (height - linesDone > 0) {
nlines = min(linesPerBuf, height - linesDone);
......@@ -2276,7 +2324,11 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
}
}
free(pBuf);
return Success;
rc = Success;
out:
if (pDstPixmap)
FreePixmap(pDstPixmap);
return rc;
}
int
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment