From 21d8ff7cc13565b655ef7e4587ae931ec542d9df Mon Sep 17 00:00:00 2001 From: Massimo Del Fedele Date: Sun, 18 Jul 2010 12:26:10 +0200 Subject: [PATCH] DIB Engine: Add clipping on xxxBlt and AlphaBlend --- 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 c0227a03846..05c9392e85c 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 81dec252902..ed10b920f13 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 61846778022..8212d42794c 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 c801d96f2d0..b0f128ecbcd 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 */ -- 2.11.4.GIT