mirror of https://github.com/FreeRDP/FreeRDP
Fixed gdi_BitBlt coordinate clipping.
This commit is contained in:
parent
a078d8714e
commit
e94ed7d762
|
@ -273,8 +273,8 @@ static UINT32 process_rop(UINT32 src, UINT32 dst, UINT32 pat, const char* rop,
|
|||
return stack[0];
|
||||
}
|
||||
|
||||
static INLINE BOOL BitBlt_write(HGDI_DC hdcDest, HGDI_DC hdcSrc, UINT32 nXDest,
|
||||
UINT32 nYDest, UINT32 nXSrc, UINT32 nYSrc, UINT32 x, UINT32 y,
|
||||
static INLINE BOOL BitBlt_write(HGDI_DC hdcDest, HGDI_DC hdcSrc, INT32 nXDest,
|
||||
INT32 nYDest, INT32 nXSrc, INT32 nYSrc, INT32 x, INT32 y,
|
||||
BOOL useSrc, BOOL usePat, UINT32 style,
|
||||
const char* rop, const gdiPalette* palette)
|
||||
{
|
||||
|
@ -282,7 +282,9 @@ static INLINE BOOL BitBlt_write(HGDI_DC hdcDest, HGDI_DC hdcSrc, UINT32 nXDest,
|
|||
UINT32 colorA;
|
||||
UINT32 colorB = 0;
|
||||
UINT32 colorC = 0;
|
||||
BYTE* dstp = gdi_get_bitmap_pointer(hdcDest, nXDest + x, nYDest + y);
|
||||
const INT32 dstX = nXDest + x;
|
||||
const INT32 dstY = nYDest + y;
|
||||
BYTE* dstp = gdi_get_bitmap_pointer(hdcDest, dstX, dstY);
|
||||
|
||||
if (!dstp)
|
||||
{
|
||||
|
@ -338,11 +340,116 @@ static INLINE BOOL BitBlt_write(HGDI_DC hdcDest, HGDI_DC hdcSrc, UINT32 nXDest,
|
|||
return WriteColor(dstp, hdcDest->format, dstColor);
|
||||
}
|
||||
|
||||
static BOOL BitBlt_process(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
|
||||
UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
|
||||
UINT32 nXSrc, UINT32 nYSrc, const char* rop, const gdiPalette* palette)
|
||||
static BOOL adjust_src_coordinates(HGDI_DC hdcSrc, INT32 nWidth, INT32 nHeight,
|
||||
INT32* px, INT32* py)
|
||||
{
|
||||
INT64 x, y;
|
||||
HGDI_BITMAP hSrcBmp;
|
||||
INT32 nXSrc, nYSrc;
|
||||
|
||||
if (!hdcSrc || (nWidth < 0) || (nHeight < 0) || !px || !py)
|
||||
return FALSE;
|
||||
|
||||
hSrcBmp = (HGDI_BITMAP) hdcSrc->selectedObject;
|
||||
nXSrc = *px;
|
||||
nYSrc = *py;
|
||||
|
||||
if (!hSrcBmp)
|
||||
return FALSE;
|
||||
|
||||
if (nYSrc < 0)
|
||||
{
|
||||
nYSrc = 0;
|
||||
nHeight = nHeight + nYSrc;
|
||||
}
|
||||
|
||||
if ((nXSrc) < 0)
|
||||
{
|
||||
nXSrc = 0;
|
||||
nWidth = nWidth + nXSrc;
|
||||
}
|
||||
|
||||
if (hSrcBmp->width < (nXSrc + nWidth))
|
||||
nXSrc = hSrcBmp->width - nWidth;
|
||||
|
||||
if (hSrcBmp->height < (nYSrc + nHeight))
|
||||
nYSrc = hSrcBmp->height - nHeight;
|
||||
|
||||
if ((nXSrc < 0) || (nYSrc < 0))
|
||||
return FALSE;
|
||||
|
||||
*px = nXSrc;
|
||||
*py = nYSrc;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL adjust_src_dst_coordinates(HGDI_DC hdcDest, INT32* pnXSrc, INT32* pnYSrc,
|
||||
INT32* pnXDst, INT32* pnYDst, INT32* pnWidth, INT32* pnHeight)
|
||||
{
|
||||
HGDI_BITMAP hDstBmp;
|
||||
volatile INT32 diffX, diffY;
|
||||
volatile INT32 nXSrc, nYSrc;
|
||||
volatile INT32 nXDst, nYDst, nWidth, nHeight;
|
||||
|
||||
if (!hdcDest || !pnXSrc || !pnYSrc || !pnXDst || !pnYDst || !pnWidth || !pnHeight)
|
||||
return FALSE;
|
||||
|
||||
hDstBmp = (HGDI_BITMAP) hdcDest->selectedObject;
|
||||
nXSrc = *pnXSrc;
|
||||
nYSrc = *pnYSrc;
|
||||
nXDst = *pnXDst;
|
||||
nYDst = *pnYDst;
|
||||
nWidth = *pnWidth;
|
||||
nHeight = *pnHeight;
|
||||
|
||||
if (!hdcDest)
|
||||
return FALSE;
|
||||
|
||||
if (nXDst < 0)
|
||||
{
|
||||
nXSrc -= nXDst;
|
||||
nWidth += nXDst;
|
||||
nXDst = 0;
|
||||
}
|
||||
|
||||
if (nYDst < 0)
|
||||
{
|
||||
nYSrc -= nYDst;
|
||||
nHeight += nYDst;
|
||||
nYDst = 0;
|
||||
}
|
||||
|
||||
diffX = hDstBmp->width - nXDst - nWidth;
|
||||
|
||||
if (diffX < 0)
|
||||
nWidth += diffX;
|
||||
|
||||
diffY = hDstBmp->height - nYDst - nHeight;
|
||||
|
||||
if (diffY < 0)
|
||||
nHeight += diffY;
|
||||
|
||||
if ((nXDst < 0) || (nYDst < 0) || (nWidth < 0) || (nHeight < 0))
|
||||
{
|
||||
nXDst = 0;
|
||||
nYDst = 0;
|
||||
nWidth = 0;
|
||||
nHeight = 0;
|
||||
}
|
||||
|
||||
*pnXSrc = nXSrc;
|
||||
*pnYSrc = nYSrc;
|
||||
*pnXDst = nXDst;
|
||||
*pnYDst = nYDst;
|
||||
*pnWidth = nWidth;
|
||||
*pnHeight = nHeight;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL BitBlt_process(HGDI_DC hdcDest, INT32 nXDest, INT32 nYDest,
|
||||
INT32 nWidth, INT32 nHeight, HGDI_DC hdcSrc,
|
||||
INT32 nXSrc, INT32 nYSrc, const char* rop, const gdiPalette* palette)
|
||||
{
|
||||
INT32 x, y;
|
||||
UINT32 style = 0;
|
||||
BOOL useSrc = FALSE;
|
||||
BOOL usePat = FALSE;
|
||||
|
@ -368,9 +475,18 @@ static BOOL BitBlt_process(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
|
|||
if (!hdcDest)
|
||||
return FALSE;
|
||||
|
||||
if (!adjust_src_dst_coordinates(hdcDest, &nXSrc, &nYSrc, &nXDest, &nYDest, &nWidth, &nHeight))
|
||||
return FALSE;
|
||||
|
||||
if (useSrc && !hdcSrc)
|
||||
return FALSE;
|
||||
|
||||
if (useSrc)
|
||||
{
|
||||
if (!adjust_src_coordinates(hdcSrc, nWidth, nHeight, &nXSrc, &nYSrc))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (usePat)
|
||||
{
|
||||
style = gdi_GetBrushStyle(hdcDest);
|
||||
|
@ -390,9 +506,9 @@ static BOOL BitBlt_process(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
|
|||
|
||||
if ((nXDest > nXSrc) && (nYDest > nYSrc))
|
||||
{
|
||||
for (y = (INT64)nHeight - 1; y >= 0; y--)
|
||||
for (y = nHeight - 1; y >= 0; y--)
|
||||
{
|
||||
for (x = (INT64)nWidth - 1; x >= 0; x--)
|
||||
for (x = nWidth - 1; x >= 0; x--)
|
||||
{
|
||||
if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest,
|
||||
nXSrc, nYSrc, x, y, useSrc,
|
||||
|
@ -405,7 +521,7 @@ static BOOL BitBlt_process(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
|
|||
{
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
for (x = (INT64)nWidth - 1; x >= 0; x--)
|
||||
for (x = nWidth - 1; x >= 0; x--)
|
||||
{
|
||||
if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest,
|
||||
nXSrc, nYSrc, x, y, useSrc,
|
||||
|
@ -416,7 +532,7 @@ static BOOL BitBlt_process(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
|
|||
}
|
||||
else if (nYDest > nYSrc)
|
||||
{
|
||||
for (y = (INT64)nHeight - 1; y >= 0; y--)
|
||||
for (y = nHeight - 1; y >= 0; y--)
|
||||
{
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
|
@ -467,10 +583,6 @@ BOOL gdi_BitBlt(HGDI_DC hdcDest, INT32 nXDest, INT32 nYDest,
|
|||
if (!hdcDest)
|
||||
return FALSE;
|
||||
|
||||
if (!gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, &nXSrc,
|
||||
&nYSrc))
|
||||
return TRUE;
|
||||
|
||||
/* Check which ROP should be performed.
|
||||
* Some specific ROP are used heavily and are resource intensive,
|
||||
* add optimized versions for these here.
|
||||
|
@ -483,6 +595,12 @@ BOOL gdi_BitBlt(HGDI_DC hdcDest, INT32 nXDest, INT32 nYDest,
|
|||
if (!hdcSrc)
|
||||
return FALSE;
|
||||
|
||||
if (!adjust_src_dst_coordinates(hdcDest, &nXSrc, &nYSrc, &nXDest, &nYDest, &nWidth, &nHeight))
|
||||
return FALSE;
|
||||
|
||||
if (!adjust_src_coordinates(hdcSrc, nWidth, nHeight, &nXSrc, &nYSrc))
|
||||
return FALSE;
|
||||
|
||||
hSrcBmp = (HGDI_BITMAP) hdcSrc->selectedObject;
|
||||
hDstBmp = (HGDI_BITMAP) hdcDest->selectedObject;
|
||||
|
||||
|
@ -500,6 +618,12 @@ BOOL gdi_BitBlt(HGDI_DC hdcDest, INT32 nXDest, INT32 nYDest,
|
|||
hSrcBmp = (HGDI_BITMAP) hdcDest->selectedObject;
|
||||
hDstBmp = (HGDI_BITMAP) hdcDest->selectedObject;
|
||||
|
||||
if (!adjust_src_dst_coordinates(hdcDest, &nXSrc, &nYSrc, &nXDest, &nYDest, &nWidth, &nHeight))
|
||||
return FALSE;
|
||||
|
||||
if (!adjust_src_coordinates(hdcDest, nWidth, nHeight, &nXSrc, &nYSrc))
|
||||
return FALSE;
|
||||
|
||||
if (!hSrcBmp || !hDstBmp)
|
||||
return FALSE;
|
||||
|
||||
|
|
|
@ -584,8 +584,8 @@ static BOOL gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
|
|||
rdpGdi* gdi = context->gdi;
|
||||
BOOL ret = FALSE;
|
||||
const DWORD rop = gdi_rop3_code(patblt->bRop);
|
||||
UINT32 nXSrc = 0;
|
||||
UINT32 nYSrc = 0;
|
||||
INT32 nXSrc = 0;
|
||||
INT32 nYSrc = 0;
|
||||
BYTE data[8 * 8 * 4];
|
||||
HGDI_BITMAP hBmp = NULL;
|
||||
|
||||
|
|
|
@ -33,12 +33,12 @@ FREERDP_LOCAL gdiBitmap* gdi_bitmap_new_ex(rdpGdi* gdi, int width, int height,
|
|||
BYTE* data);
|
||||
FREERDP_LOCAL void gdi_bitmap_free_ex(gdiBitmap* gdi_bmp);
|
||||
|
||||
static INLINE BYTE* gdi_get_bitmap_pointer(HGDI_DC hdcBmp, UINT32 x, UINT32 y)
|
||||
static INLINE BYTE* gdi_get_bitmap_pointer(HGDI_DC hdcBmp, INT32 x, INT32 y)
|
||||
{
|
||||
BYTE* p;
|
||||
HGDI_BITMAP hBmp = (HGDI_BITMAP) hdcBmp->selectedObject;
|
||||
|
||||
if (x < hBmp->width && y < hBmp->height)
|
||||
if ((x >= 0) && (y >= 0) && (x < hBmp->width) && (y < hBmp->height))
|
||||
{
|
||||
p = hBmp->data + (y * hBmp->scanline) + (x * GetBytesPerPixel(hdcBmp->format));
|
||||
return p;
|
||||
|
|
Loading…
Reference in New Issue