561 lines
21 KiB
Diff
561 lines
21 KiB
Diff
|
DIB Engine: Add clipping on xxxBlt and AlphaBlend
|
||
|
|
||
|
From: Massimo Del Fedele <max@veneto.com>
|
||
|
|
||
|
|
||
|
---
|
||
|
|
||
|
dlls/winedib.drv/bitblt.c | 332 +++++++++++++++++++++++++++++++++++++------
|
||
|
dlls/winedib.drv/clipping.c | 42 +++++
|
||
|
dlls/winedib.drv/dc.c | 14 ++
|
||
|
dlls/winedib.drv/dibdrv.h | 6 +
|
||
|
4 files changed, 341 insertions(+), 53 deletions(-)
|
||
|
|
||
|
|
||
|
diff --git a/dlls/winedib.drv/bitblt.c b/dlls/winedib.drv/bitblt.c
|
||
|
index c0227a0..05c9392 100644
|
||
|
--- a/dlls/winedib.drv/bitblt.c
|
||
|
+++ b/dlls/winedib.drv/bitblt.c
|
||
|
@@ -33,6 +33,26 @@ static inline void intSwap(int *a, int *b)
|
||
|
*b = tmp;
|
||
|
}
|
||
|
|
||
|
+static inline void setRect(RECT *r, int x1, int y1, int x2, int y2)
|
||
|
+{
|
||
|
+ r->left = x1;
|
||
|
+ r->top = y1;
|
||
|
+ r->right = x2;
|
||
|
+ r->bottom = y2;
|
||
|
+}
|
||
|
+
|
||
|
+static inline void setPoint(POINT *p, int x, int y)
|
||
|
+{
|
||
|
+ p->x = x;
|
||
|
+ p->y = y;
|
||
|
+}
|
||
|
+
|
||
|
+static inline void setSize(SIZE *sz, int cx, int cy)
|
||
|
+{
|
||
|
+ sz->cx = cx;
|
||
|
+ sz->cy = cy;
|
||
|
+}
|
||
|
+
|
||
|
/* clips a source and destination areas to their respective clip rectangles
|
||
|
returning both source and dest modified; result is TRUE if clipping
|
||
|
leads to a non null rectangle, FALSE otherwise */
|
||
|
@@ -130,13 +150,158 @@ static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT*
|
||
|
leads to a non null rectangle, FALSE otherwise */
|
||
|
static BOOL StretchBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *szSrc, SIZE *szDst, RECT*srcClip, RECT*dstClip)
|
||
|
{
|
||
|
- ONCE(FIXME("TO DO\n"));
|
||
|
+ int xs1, ys1, xs2, ys2;
|
||
|
+ int xsc1, ysc1, xsc2, ysc2;
|
||
|
+ int xd1, yd1, xd2, yd2;
|
||
|
+ int xdc1, ydc1, xdc2, ydc2;
|
||
|
+ int ws, hs, wd, hd, dx, dy;
|
||
|
+ int mulh, divh, mulv, divv;
|
||
|
+
|
||
|
+ /* extract sizes */
|
||
|
+ ws = szSrc->cx; hs = szSrc->cy;
|
||
|
+ wd = szDst->cx; hd = szDst->cy;
|
||
|
+
|
||
|
+ /* if sizes null or negative, just return false */
|
||
|
+ /* FIXME : add support for mirror stretch */
|
||
|
+ if(ws <= 0 || hs <= 0 || wd <= 0 || hd <= 0)
|
||
|
+ return FALSE;
|
||
|
+
|
||
|
+ /* stores scaling factors from source rect to dest one */
|
||
|
+ mulh = wd; divh = ws;
|
||
|
+ mulv = hd; divv = hs;
|
||
|
+
|
||
|
+ /* extract dest area data */
|
||
|
+ xd1 = pd->x;
|
||
|
+ yd1 = pd->y;
|
||
|
+ xd2 = xd1 + wd;
|
||
|
+ yd2 = yd1 + hd;
|
||
|
+
|
||
|
+ /* extract source data */
|
||
|
+ xs1 = ps->x;
|
||
|
+ ys1 = ps->y;
|
||
|
+ xs2 = xs1 + ws;
|
||
|
+ ys2 = ys1 + hs;
|
||
|
+
|
||
|
+ /* if source clip area is not null, do first clipping on it */
|
||
|
+ if(srcClip)
|
||
|
+ {
|
||
|
+ /* extract source clipping area */
|
||
|
+ xsc1 = srcClip->left;
|
||
|
+ ysc1 = srcClip->top;
|
||
|
+ xsc2 = srcClip->right;
|
||
|
+ ysc2 = srcClip->bottom;
|
||
|
+
|
||
|
+ /* order clip area rectangle points */
|
||
|
+ if(xsc1 > xsc2) intSwap(&xsc1, &xsc2);
|
||
|
+ if(ysc1 > ysc2) intSwap(&ysc1, &ysc2);
|
||
|
+
|
||
|
+ /* clip on source clipping start point */
|
||
|
+ if(xs1 < xsc1) { dx = xsc1 - xs1; ws -= dx; xd1 += MulDiv(dx, mulh, divh); xs1 = xsc1; }
|
||
|
+ if(ys1 < ysc1) { dy = ysc1 - ys1; hs -= dy; yd1 += MulDiv(dy, mulv, divv); ys1 = ysc1; }
|
||
|
+
|
||
|
+ /* clip on source clipping end point */
|
||
|
+ if(xs2 > xsc2) { dx = xs2 - xsc2; ws -= dx; xd2 -= MulDiv(dx, mulh, divh); xs2 = xsc2; }
|
||
|
+ if(ys2 > ysc2) { dy = ys2 - ysc2; hs -= dy; yd2 -= MulDiv(dy, mulv, divv); ys2 = ysc2; }
|
||
|
+
|
||
|
+ /* if already zero area, return false */
|
||
|
+ if(ws <= 0 || hs <= 0)
|
||
|
+ return FALSE;
|
||
|
+ wd = xd2 - xd1;
|
||
|
+ hd = yd2 - yd1;
|
||
|
+ }
|
||
|
+ /* now do clipping on destination area */
|
||
|
|
||
|
+ if(dstClip)
|
||
|
+ {
|
||
|
+ /* extract destination clipping area */
|
||
|
+ xdc1 = dstClip->left;
|
||
|
+ ydc1 = dstClip->top;
|
||
|
+ xdc2 = dstClip->right;
|
||
|
+ ydc2 = dstClip->bottom;
|
||
|
+
|
||
|
+ /* order clip area rectangle points */
|
||
|
+ if(xdc1 > xdc2) intSwap(&xdc1, &xdc2);
|
||
|
+ if(ydc1 > ydc2) intSwap(&ydc1, &ydc2);
|
||
|
+
|
||
|
+ /* clip on dest clipping start point */
|
||
|
+ if(xd1 < xdc1) { dx = xdc1 - xd1; wd -= dx; xs1 += MulDiv(dx, divh, mulh); xd1 = xdc1; }
|
||
|
+ if(yd1 < ydc1) { dy = ydc1 - yd1; hd -= dy; ys1 += MulDiv(dy, divv, mulv); yd1 = ydc1; }
|
||
|
+
|
||
|
+ /* clip on dest clipping end point */
|
||
|
+ if(xd2 > xdc2) { dx = xd2 - xdc2; wd -= dx; xs2 -= MulDiv(dx, divh, mulh); xd2 = xdc2; }
|
||
|
+ if(yd2 > ydc2) { dy = yd2 - ydc2; hd -= dy; ys2 -= MulDiv(dy, divv, mulv); yd2 = ydc2; }
|
||
|
+
|
||
|
+ /* if already zero area, return false */
|
||
|
+ if(wd <= 0 || hd <= 0)
|
||
|
+ return FALSE;
|
||
|
+
|
||
|
+ ws = xs2 - xs1;
|
||
|
+ hs = ys2 - ys1;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* sets clipped/translated points and sizes and returns TRUE */
|
||
|
+ ps->x = xs1; ps->y = ys1;
|
||
|
+ pd->x = xd1; pd->y = yd1;
|
||
|
+ szSrc->cx = ws; szSrc->cy = hs;
|
||
|
+ szDst->cx = wd; szDst->cy = hd;
|
||
|
+
|
||
|
return TRUE;
|
||
|
|
||
|
}
|
||
|
|
||
|
/***********************************************************************
|
||
|
+ * _DIBDRV_InternalAlphaBlend
|
||
|
+ */
|
||
|
+BOOL _DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
|
||
|
+ DIBDRVPHYSDEV *physDevSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc,
|
||
|
+ BLENDFUNCTION blendfn)
|
||
|
+{
|
||
|
+ BOOL res;
|
||
|
+ POINT pd, ps;
|
||
|
+ SIZE szSrc, szDst;
|
||
|
+ int iRec;
|
||
|
+ RECT dstClip, srcClip;
|
||
|
+
|
||
|
+ /* first clip on physical DC sizes */
|
||
|
+ setPoint(&pd, xDst, yDst);
|
||
|
+ setPoint(&ps, xSrc, ySrc);
|
||
|
+ setSize(&szDst, widthDst, heightDst);
|
||
|
+ setSize(&szSrc, widthSrc, heightSrc);
|
||
|
+ setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
|
||
|
+ if(physDevSrc)
|
||
|
+ {
|
||
|
+ setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
|
||
|
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
|
||
|
+ if(!res)
|
||
|
+ return FALSE;
|
||
|
+ xDst = pd.x; yDst = pd.y;
|
||
|
+ xSrc = ps.x; ySrc = ps.y;
|
||
|
+ widthDst = szDst.cx; heightDst = szDst.cy;
|
||
|
+ widthSrc = szSrc.cx; heightSrc = szSrc.cy;
|
||
|
+
|
||
|
+ /* then, do blitting for each dest clip area (no clipping on source) */
|
||
|
+ res = FALSE;
|
||
|
+ for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
|
||
|
+ {
|
||
|
+ RECT *r = physDevDst->regionRects + iRec;
|
||
|
+ setRect(&dstClip, r->left, r->top, r->right, r->bottom);
|
||
|
+ setPoint(&pd, xDst, yDst);
|
||
|
+ setPoint(&ps, xSrc, ySrc);
|
||
|
+ setSize(&szDst, widthDst, heightDst);
|
||
|
+ setSize(&szSrc, widthSrc, heightSrc);
|
||
|
+ if(!StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip))
|
||
|
+ continue;
|
||
|
+ if(physDevDst->physBitmap.funcs->AlphaBlend(physDevDst, pd.x, pd.y, szDst.cx, szDst.cy,
|
||
|
+ physDevSrc, ps.x, ps.y, szSrc.cx, szSrc.cy, blendfn))
|
||
|
+ res = TRUE;
|
||
|
+ }
|
||
|
+ return res;
|
||
|
+}
|
||
|
+
|
||
|
+/***********************************************************************
|
||
|
* DIBDRV_AlphaBlend
|
||
|
*/
|
||
|
BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
|
||
|
@@ -145,6 +310,11 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
|
||
|
{
|
||
|
BOOL res;
|
||
|
|
||
|
+ POINT pd = {xDst, yDst};
|
||
|
+ POINT ps = {xSrc, ySrc};
|
||
|
+ SIZE szDst = {widthDst, heightDst};
|
||
|
+ SIZE szSrc = {widthSrc, heightSrc};
|
||
|
+
|
||
|
MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d\n",
|
||
|
physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevDst->physBitmap) : "",
|
||
|
xDst, yDst, widthDst, heightDst,
|
||
|
@@ -177,16 +347,24 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
|
||
|
{
|
||
|
/* DIB section selected in dest DC, use DIB Engine */
|
||
|
MAYBE(TRACE("Blending DIB->DIB\n"));
|
||
|
- res = physDevDst->physBitmap.funcs->AlphaBlend(physDevDst, xDst, yDst, widthDst, heightDst,
|
||
|
- physDevSrc, xSrc, ySrc, widthSrc, heightSrc, blendfn);
|
||
|
+ res = _DIBDRV_InternalAlphaBlend(physDevDst, xDst, yDst, widthDst, heightDst,
|
||
|
+ physDevSrc, xSrc, ySrc, widthSrc, heightSrc, blendfn);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* DDB selected on dest DC -- must double-convert */
|
||
|
HBITMAP tmpDIB, stock;
|
||
|
HDC tmpDC;
|
||
|
+ RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
|
||
|
MAYBE(TRACE("Blending DIB->DDB\n"));
|
||
|
|
||
|
+ /* clip blit area */
|
||
|
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, 0);
|
||
|
+ if(!res)
|
||
|
+ goto fin;
|
||
|
+ xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy;
|
||
|
+ xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
|
||
|
+
|
||
|
/* converts dest DDB onto a temporary DIB -- just the needed part */
|
||
|
tmpDIB = _DIBDRV_ConvertDevDDBtoDIB(physDevDst->hdc, physDevSrc->hdc, xDst, yDst, widthDst, heightDst);
|
||
|
if(!tmpDIB)
|
||
|
@@ -232,8 +410,55 @@ fin:
|
||
|
}
|
||
|
|
||
|
/***********************************************************************
|
||
|
- * DIBDRV_BitBlt
|
||
|
+ * _DIBDRV_InternalBitBlt
|
||
|
*/
|
||
|
+BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
|
||
|
+ INT width, INT height, DIBDRVPHYSDEV *physDevSrc,
|
||
|
+ INT xSrc, INT ySrc, DWORD rop )
|
||
|
+{
|
||
|
+ BOOL res;
|
||
|
+ POINT pd, ps;
|
||
|
+ SIZE sz;
|
||
|
+ int iRec;
|
||
|
+ RECT dstClip, srcClip;
|
||
|
+
|
||
|
+ /* first clip on physical DC sizes */
|
||
|
+ setPoint(&pd, xDst, yDst);
|
||
|
+ setPoint(&ps, xSrc, ySrc);
|
||
|
+ setSize(&sz, width, height);
|
||
|
+ setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
|
||
|
+ if(physDevSrc)
|
||
|
+ {
|
||
|
+ setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
|
||
|
+ res = BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, &dstClip);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ res = BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip);
|
||
|
+ if(!res)
|
||
|
+ return FALSE;
|
||
|
+ xDst = pd.x; yDst = pd.y;
|
||
|
+ xSrc = ps.x; ySrc = ps.y;
|
||
|
+ width = sz.cx; height = sz.cy;
|
||
|
+
|
||
|
+ /* then, do blitting for each dest clip area (no clipping on source) */
|
||
|
+ res = FALSE;
|
||
|
+ for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
|
||
|
+ {
|
||
|
+ RECT *r = physDevDst->regionRects + iRec;
|
||
|
+ setRect(&dstClip, r->left, r->top, r->right, r->bottom);
|
||
|
+ setPoint(&pd, xDst, yDst);
|
||
|
+ setPoint(&ps, xSrc, ySrc);
|
||
|
+ setSize(&sz, width, height);
|
||
|
+ if(!BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip))
|
||
|
+ continue;
|
||
|
+ if(physDevDst->physBitmap.funcs->BitBlt(physDevDst, pd.x, pd.y, sz.cx, sz.cy, physDevSrc, ps.x, ps.y, rop))
|
||
|
+ res = TRUE;
|
||
|
+ }
|
||
|
+ return res;
|
||
|
+}
|
||
|
+
|
||
|
+/***********************************************************************
|
||
|
+ * DIBDRV_BitBlt */
|
||
|
BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
|
||
|
INT width, INT height, DIBDRVPHYSDEV *physDevSrc,
|
||
|
INT xSrc, INT ySrc, DWORD rop )
|
||
|
@@ -254,26 +479,13 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
|
||
|
if(physDevDst->hasDIB)
|
||
|
{
|
||
|
/* DIB section selected in dest DC, use DIB Engine */
|
||
|
-
|
||
|
/* clip blit area */
|
||
|
RECT dstClip = {0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height};
|
||
|
|
||
|
if(!physDevSrc || physDevSrc->hasDIB)
|
||
|
{
|
||
|
- /* clip blit area */
|
||
|
- if(physDevSrc)
|
||
|
- {
|
||
|
- RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
|
||
|
- res = BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, &dstClip);
|
||
|
- }
|
||
|
- else
|
||
|
- res = BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip);
|
||
|
- if(!res)
|
||
|
- goto noBlt2;
|
||
|
- xDst = pd.x; yDst = pd.y; width = sz.cx; height = sz.cy; xSrc = ps.x; ySrc = ps.y;
|
||
|
-
|
||
|
/* source is null or has a DIB, no need to convert anyting */
|
||
|
- res = physDevDst->physBitmap.funcs->BitBlt(physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, ySrc, rop);
|
||
|
+ res = _DIBDRV_InternalBitBlt(physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, ySrc, rop);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
@@ -309,8 +521,7 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
|
||
|
goto noBlt1;
|
||
|
}
|
||
|
SelectObject(physDevSrc->hdc, dib);
|
||
|
- res = physDevDst->physBitmap.funcs->BitBlt(physDevDst, xDst, yDst, width, height,
|
||
|
- physDevSrc, xSrc, 0, rop);
|
||
|
+ res = _DIBDRV_InternalBitBlt(physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, 0, rop);
|
||
|
SelectObject(physDevSrc->hdc, ddb);
|
||
|
DeleteObject(dib);
|
||
|
noBlt1:
|
||
|
@@ -410,6 +621,58 @@ noBlt3:
|
||
|
}
|
||
|
|
||
|
/***********************************************************************
|
||
|
+ * _DIBDRV_InternalStretchBlt
|
||
|
+ */
|
||
|
+BOOL _DIBDRV_InternalStretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
|
||
|
+ INT widthDst, INT heightDst, DIBDRVPHYSDEV *physDevSrc,
|
||
|
+ INT xSrc, INT ySrc, int widthSrc, int heightSrc, DWORD rop )
|
||
|
+{
|
||
|
+ BOOL res;
|
||
|
+ POINT pd, ps;
|
||
|
+ SIZE szSrc, szDst;
|
||
|
+ int iRec;
|
||
|
+ RECT dstClip, srcClip;
|
||
|
+
|
||
|
+ /* first clip on physical DC sizes */
|
||
|
+ setPoint(&pd, xDst, yDst);
|
||
|
+ setPoint(&ps, xSrc, ySrc);
|
||
|
+ setSize(&szDst, widthDst, heightDst);
|
||
|
+ setSize(&szSrc, widthSrc, heightSrc);
|
||
|
+ setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
|
||
|
+ if(physDevSrc)
|
||
|
+ {
|
||
|
+ setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
|
||
|
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
|
||
|
+ if(!res)
|
||
|
+ return FALSE;
|
||
|
+ xDst = pd.x; yDst = pd.y;
|
||
|
+ xSrc = ps.x; ySrc = ps.y;
|
||
|
+ widthDst = szDst.cx; heightDst = szDst.cy;
|
||
|
+ widthSrc = szSrc.cx; heightSrc = szSrc.cy;
|
||
|
+
|
||
|
+ /* then, do blitting for each dest clip area (no clipping on source) */
|
||
|
+ res = FALSE;
|
||
|
+ for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
|
||
|
+ {
|
||
|
+ RECT *r = physDevDst->regionRects + iRec;
|
||
|
+ setRect(&dstClip, r->left, r->top, r->right, r->bottom);
|
||
|
+ setPoint(&pd, xDst, yDst);
|
||
|
+ setPoint(&ps, xSrc, ySrc);
|
||
|
+ setSize(&szDst, widthDst, heightDst);
|
||
|
+ setSize(&szSrc, widthSrc, heightSrc);
|
||
|
+ if(!StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip))
|
||
|
+ continue;
|
||
|
+ if(physDevDst->physBitmap.funcs->StretchBlt(physDevDst, pd.x, pd.y, szDst.cx, szDst.cy,
|
||
|
+ physDevSrc, ps.x, ps.y, szSrc.cx, szSrc.cy, rop))
|
||
|
+ res = TRUE;
|
||
|
+ }
|
||
|
+ return res;
|
||
|
+}
|
||
|
+
|
||
|
+/***********************************************************************
|
||
|
* DIBDRV_StretchBlt
|
||
|
*/
|
||
|
BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
|
||
|
@@ -439,38 +702,15 @@ BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
|
||
|
{
|
||
|
/* DIB section selected in dest DC, use DIB Engine */
|
||
|
|
||
|
- /* clip blit area */
|
||
|
- RECT dstClip = {0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height};
|
||
|
-
|
||
|
if(!physDevSrc || physDevSrc->hasDIB)
|
||
|
{
|
||
|
- /* clip blit area */
|
||
|
- if(physDevSrc)
|
||
|
- {
|
||
|
- RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
|
||
|
- res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
|
||
|
- }
|
||
|
- else
|
||
|
- res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
|
||
|
- if(!res)
|
||
|
- goto noBlt2;
|
||
|
- xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy;
|
||
|
- xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
|
||
|
-
|
||
|
/* source is null or has a DIB, no need to convert anyting */
|
||
|
- res = physDevDst->physBitmap.funcs->StretchBlt(physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, widthSrc, heightSrc, rop);
|
||
|
+ res = _DIBDRV_InternalStretchBlt(physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, widthSrc, heightSrc, rop);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* source is a DDB, must convert it to DIB */
|
||
|
|
||
|
- /* don't clip on source */
|
||
|
- res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
|
||
|
- if(!res)
|
||
|
- goto noBlt2;
|
||
|
- xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy;
|
||
|
- xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
|
||
|
-
|
||
|
/* we must differentiate from 2 cases :
|
||
|
1) source DC is a memory DC
|
||
|
2) source DC is a device DC */
|
||
|
@@ -495,8 +735,8 @@ BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
|
||
|
goto noBlt1;
|
||
|
}
|
||
|
SelectObject(physDevSrc->hdc, dib);
|
||
|
- res = physDevDst->physBitmap.funcs->StretchBlt(physDevDst, xDst, yDst, widthDst, heightDst,
|
||
|
- physDevSrc, xSrc, 0, widthSrc, heightSrc, rop);
|
||
|
+ res = _DIBDRV_InternalStretchBlt(physDevDst, xDst, yDst, widthDst, heightDst,
|
||
|
+ physDevSrc, xSrc, 0, widthSrc, heightSrc, rop);
|
||
|
SelectObject(physDevSrc->hdc, ddb);
|
||
|
DeleteObject(dib);
|
||
|
noBlt1:
|
||
|
diff --git a/dlls/winedib.drv/clipping.c b/dlls/winedib.drv/clipping.c
|
||
|
index 81dec25..ed10b92 100644
|
||
|
--- a/dlls/winedib.drv/clipping.c
|
||
|
+++ b/dlls/winedib.drv/clipping.c
|
||
|
@@ -25,22 +25,50 @@
|
||
|
|
||
|
WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
|
||
|
|
||
|
-
|
||
|
/***********************************************************************
|
||
|
* DIBDRV_SetDeviceClipping
|
||
|
*/
|
||
|
void DIBDRV_SetDeviceClipping( DIBDRVPHYSDEV *physDev, HRGN vis_rgn, HRGN clip_rgn )
|
||
|
{
|
||
|
+ RGNDATA *data;
|
||
|
+ DWORD size;
|
||
|
+ int iRect;
|
||
|
+
|
||
|
MAYBE(TRACE("physDev:%p, vis_rgn:%p, clip_rgn:%p\n", physDev, vis_rgn, clip_rgn));
|
||
|
|
||
|
- if(physDev->hasDIB)
|
||
|
+ /* sets the region for X11 driver anyways... we may change bitmap later on */
|
||
|
+ _DIBDRV_GetDisplayDriver()->pSetDeviceClipping(physDev->X11PhysDev, vis_rgn, clip_rgn);
|
||
|
+
|
||
|
+ /* then we set the region for DIB engine, same reason */
|
||
|
+
|
||
|
+ CombineRgn( physDev->region, vis_rgn, clip_rgn, clip_rgn ? RGN_AND : RGN_COPY );
|
||
|
+
|
||
|
+ /* get region rectangles */
|
||
|
+ if(!(size = GetRegionData(physDev->region, 0, NULL)))
|
||
|
+ return;
|
||
|
+ data = HeapAlloc(GetProcessHeap(), 0, size);
|
||
|
+ if (!GetRegionData(physDev->region, size, data))
|
||
|
{
|
||
|
- /* DIB section selected in, use DIB Engine */
|
||
|
- ONCE(FIXME("STUB\n"));
|
||
|
+ HeapFree( GetProcessHeap(), 0, data );
|
||
|
+ return;
|
||
|
}
|
||
|
- else
|
||
|
+
|
||
|
+ /* frees any previous regions rectangles in DC */
|
||
|
+ if(physDev->regionData)
|
||
|
+ HeapFree(GetProcessHeap(), 0, physDev->regionData);
|
||
|
+
|
||
|
+ /* sets the rectangles on physDev */
|
||
|
+ physDev->regionData = data;
|
||
|
+ physDev->regionRects = (RECT *)data->Buffer;
|
||
|
+ physDev->regionRectCount = data->rdh.nCount;
|
||
|
+
|
||
|
+ if(TRACE_ON(dibdrv))
|
||
|
{
|
||
|
- /* DDB selected in, use X11 driver */
|
||
|
- _DIBDRV_GetDisplayDriver()->pSetDeviceClipping(physDev->X11PhysDev, vis_rgn, clip_rgn);
|
||
|
+ TRACE("Region dump : %d rectangles\n", physDev->regionRectCount);
|
||
|
+ for(iRect = 0; iRect < physDev->regionRectCount; iRect++)
|
||
|
+ {
|
||
|
+ RECT *r = physDev->regionRects + iRect;
|
||
|
+ TRACE("Rect #%03d, x1:%4d, y1:%4d, x2:%4d, y2:%4d\n", iRect, r->left, r->top, r->right, r->bottom);
|
||
|
+ }
|
||
|
}
|
||
|
}
|
||
|
diff --git a/dlls/winedib.drv/dc.c b/dlls/winedib.drv/dc.c
|
||
|
index 6184677..8212d42 100644
|
||
|
--- a/dlls/winedib.drv/dc.c
|
||
|
+++ b/dlls/winedib.drv/dc.c
|
||
|
@@ -165,6 +165,12 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev
|
||
|
|
||
|
/* clears pen and brush */
|
||
|
physDev->rop2 = R2_COPYPEN;
|
||
|
+
|
||
|
+ /* clipping region */
|
||
|
+ physDev->region = CreateRectRgn( 0, 0, 0, 0 );
|
||
|
+ physDev->regionData = NULL;
|
||
|
+ physDev->regionRects = NULL;
|
||
|
+ physDev->regionRectCount = 0;
|
||
|
|
||
|
physDev->backgroundColor = 0;
|
||
|
_DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->backgroundAnd, &physDev->backgroundXor);
|
||
|
@@ -228,6 +234,14 @@ BOOL DIBDRV_DeleteDC( DIBDRVPHYSDEV *physDev )
|
||
|
physDev->brushAnds = NULL;
|
||
|
physDev->brushXors = NULL;
|
||
|
|
||
|
+ /* frees clipping region */
|
||
|
+ DeleteObject(physDev->region);
|
||
|
+ if(physDev->regionData)
|
||
|
+ HeapFree(GetProcessHeap(), 0, physDev->regionData);
|
||
|
+ physDev->regionData = NULL;
|
||
|
+ physDev->regionRects = NULL;
|
||
|
+ physDev->regionRectCount = 0;
|
||
|
+
|
||
|
/* frees DIB Engine device */
|
||
|
HeapFree(GetProcessHeap(), 0, physDev);
|
||
|
|
||
|
diff --git a/dlls/winedib.drv/dibdrv.h b/dlls/winedib.drv/dibdrv.h
|
||
|
index c801d96..b0f128e 100644
|
||
|
--- a/dlls/winedib.drv/dibdrv.h
|
||
|
+++ b/dlls/winedib.drv/dibdrv.h
|
||
|
@@ -204,6 +204,12 @@ typedef struct _DIBDRVPHYSDEV
|
||
|
|
||
|
/* active ROP2 */
|
||
|
INT rop2;
|
||
|
+
|
||
|
+ /* clipping region and its rectangles */
|
||
|
+ HRGN region;
|
||
|
+ RGNDATA *regionData;
|
||
|
+ RECT *regionRects;
|
||
|
+ int regionRectCount;
|
||
|
|
||
|
/* background color and active ROP2 precalculated
|
||
|
AND and XOR values for it */
|