From 08d47079cfa889dc2405d55137f5c187bc7fe1c3 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Sat, 15 Nov 2008 13:37:26 +0000 Subject: [PATCH] - Fix dirty bit support for select brush and pen, see bug 3863. - Hack-plement part of NtGdiExtFloodFill. We need to fix our region and clip support so ReactOS drawing functions do not over write other displayed windows. Open AbiWord than type something and select another desktop, this is just one of them.... - Tested with Qemu and real hardware. svn path=/trunk/; revision=37372 --- reactos/dll/win32/gdi32/objects/dc.c | 8 +- .../subsystems/win32/win32k/objects/bitblt.c | 27 +++- reactos/subsystems/win32/win32k/objects/dc.c | 9 +- .../subsystems/win32/win32k/objects/dcutil.c | 3 +- .../win32/win32k/objects/fillshap.c | 115 +++++++++++++++++- .../subsystems/win32/win32k/objects/line.c | 13 ++ .../subsystems/win32/win32k/objects/path.c | 30 ++++- reactos/subsystems/win32/win32k/objects/pen.c | 2 + 8 files changed, 190 insertions(+), 17 deletions(-) diff --git a/reactos/dll/win32/gdi32/objects/dc.c b/reactos/dll/win32/gdi32/objects/dc.c index 4ecd2cbcd6e..5de287b376d 100644 --- a/reactos/dll/win32/gdi32/objects/dc.c +++ b/reactos/dll/win32/gdi32/objects/dc.c @@ -1561,23 +1561,19 @@ SelectObject(HDC hDC, return NtGdiSelectBitmap(hDC, hGdiObj); case GDI_OBJECT_TYPE_BRUSH: -#if 0 // enable this when support is ready in win32k hOldObj = pDc_Attr->hbrush; pDc_Attr->ulDirty_ |= DC_BRUSH_DIRTY; pDc_Attr->hbrush = hGdiObj; return hOldObj; -#endif - return NtGdiSelectBrush(hDC, hGdiObj); +// return NtGdiSelectBrush(hDC, hGdiObj); case GDI_OBJECT_TYPE_PEN: case GDI_OBJECT_TYPE_EXTPEN: -#if 0 // enable this when support is ready in win32k hOldObj = pDc_Attr->hpen; pDc_Attr->ulDirty_ |= DC_PEN_DIRTY; pDc_Attr->hpen = hGdiObj; return hOldObj; -#endif - return NtGdiSelectPen(hDC, hGdiObj); +// return NtGdiSelectPen(hDC, hGdiObj); case GDI_OBJECT_TYPE_FONT: hOldObj = pDc_Attr->hlfntNew; diff --git a/reactos/subsystems/win32/win32k/objects/bitblt.c b/reactos/subsystems/win32/win32k/objects/bitblt.c index f0598e131bc..db8e188e202 100644 --- a/reactos/subsystems/win32/win32k/objects/bitblt.c +++ b/reactos/subsystems/win32/win32k/objects/bitblt.c @@ -225,6 +225,9 @@ NtGdiBitBlt( Dc_Attr = DCDest->pDc_Attr; if (!Dc_Attr) Dc_Attr = &DCDest->Dc_Attr; + if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(DCDest,Dc_Attr->hbrush); + /* Offset the destination and source by the origin of their DCs. */ XDest += DCDest->ptlDCOrig.x; YDest += DCDest->ptlDCOrig.y; @@ -484,6 +487,7 @@ done: * * Someone thought it would be faster to do it here and then switch back * to GDI32. I dunno. Write a test and let me know. + * A. It should be in here! */ static __inline BYTE @@ -781,6 +785,12 @@ NtGdiStretchBlt( } } + Dc_Attr = DCDest->pDc_Attr; + if (!Dc_Attr) Dc_Attr = &DCDest->Dc_Attr; + + if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(DCDest,Dc_Attr->hbrush); + /* Offset the destination and source by the origin of their DCs. */ // FIXME: ptlDCOrig is in device coordinates! XOriginDest += DCDest->ptlDCOrig.x; @@ -880,8 +890,6 @@ NtGdiStretchBlt( if (UsesPattern) { - Dc_Attr = DCDest->pDc_Attr; - if (!Dc_Attr) Dc_Attr = &DCDest->Dc_Attr; BrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush); if (NULL == BrushObj) { @@ -1008,6 +1016,7 @@ IntGdiPolyPatBlt( int i; PPATRECT r; PGDIBRUSHOBJ BrushObj; + PDC_ATTR Dc_Attr; DC *dc; dc = DC_LockDc(hDC); @@ -1023,6 +1032,12 @@ IntGdiPolyPatBlt( return TRUE; } + Dc_Attr = dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + + if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(dc,Dc_Attr->hbrush); + for (r = pRects, i = 0; i < cRects; i++) { BrushObj = BRUSHOBJ_LockBrush(r->hBrush); @@ -1074,8 +1089,6 @@ NtGdiPatBlt( SetLastWin32Error(ERROR_INVALID_HANDLE); return FALSE; } - Dc_Attr = dc->pDc_Attr; - if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; if (dc->DC_Type == DC_TYPE_INFO) { DC_UnlockDc(dc); @@ -1083,6 +1096,12 @@ NtGdiPatBlt( return TRUE; } + Dc_Attr = dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + + if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(dc,Dc_Attr->hbrush); + BrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush); if (BrushObj == NULL) { diff --git a/reactos/subsystems/win32/win32k/objects/dc.c b/reactos/subsystems/win32/win32k/objects/dc.c index bffd0f1f445..245ab547745 100644 --- a/reactos/subsystems/win32/win32k/objects/dc.c +++ b/reactos/subsystems/win32/win32k/objects/dc.c @@ -130,8 +130,8 @@ NtGdiCreateCompatibleDC(HDC hDC) NewDC->DC_Type = DC_TYPE_MEMORY; // Always! NewDC->w.hBitmap = NtGdiGetStockObject(DEFAULT_BITMAP); NewDC->pPDev = OrigDC->pPDev; + NewDC->DcLevel.hpal = OrigDC->DcLevel.hpal; - NewDC->DcLevel.hpal = OrigDC->DcLevel.hpal; nDc_Attr->lTextAlign = oDc_Attr->lTextAlign; nDc_Attr->ulForegroundClr = oDc_Attr->ulForegroundClr; nDc_Attr->ulBackgroundClr = oDc_Attr->ulBackgroundClr; @@ -1138,6 +1138,13 @@ NtGdiGetDCObject(HDC hDC, INT ObjectType) } Dc_Attr = dc->pDc_Attr; if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + + if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(dc,Dc_Attr->hbrush); + + if (Dc_Attr->ulDirty_ & DC_PEN_DIRTY) + IntGdiSelectPen(dc,Dc_Attr->hpen); + switch(ObjectType) { case GDI_OBJECT_TYPE_EXTPEN: diff --git a/reactos/subsystems/win32/win32k/objects/dcutil.c b/reactos/subsystems/win32/win32k/objects/dcutil.c index 23ef0558111..a76ce42558a 100644 --- a/reactos/subsystems/win32/win32k/objects/dcutil.c +++ b/reactos/subsystems/win32/win32k/objects/dcutil.c @@ -199,7 +199,7 @@ IntGdiSetBkColor(HDC hDC, COLORREF color) oldColor = Dc_Attr->crBackgroundClr; Dc_Attr->crBackgroundClr = color; Dc_Attr->ulBackgroundClr = (ULONG)color; - Dc_Attr->ulDirty_ &= ~DIRTY_LINE; // Clear Flag if set. + Dc_Attr->ulDirty_ &= ~(DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL); // Clear Flag if set. hBrush = Dc_Attr->hbrush; DC_UnlockDc(dc); NtGdiSelectBrush(hDC, hBrush); @@ -271,6 +271,7 @@ IntGdiSetTextColor(HDC hDC, oldColor = Dc_Attr->crForegroundClr; Dc_Attr->crForegroundClr = color; hBrush = Dc_Attr->hbrush; + Dc_Attr->ulDirty_ &= ~(DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL); DC_UnlockDc( dc ); NtGdiSelectBrush(hDC, hBrush); return oldColor; diff --git a/reactos/subsystems/win32/win32k/objects/fillshap.c b/reactos/subsystems/win32/win32k/objects/fillshap.c index 6bf346339d1..fc25c99edfe 100644 --- a/reactos/subsystems/win32/win32k/objects/fillshap.c +++ b/reactos/subsystems/win32/win32k/objects/fillshap.c @@ -95,6 +95,12 @@ IntGdiPolygon(PDC dc, DestRect.bottom = max(DestRect.bottom, Points[CurrentPoint].y); } + if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(dc,Dc_Attr->hbrush); + + if (Dc_Attr->ulDirty_ & DC_PEN_DIRTY) + IntGdiSelectPen(dc,Dc_Attr->hpen); + /* Special locking order to avoid lock-ups */ FillBrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush); PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen); @@ -242,6 +248,12 @@ NtGdiEllipse( Dc_Attr = dc->pDc_Attr; if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(dc,Dc_Attr->hbrush); + + if (Dc_Attr->ulDirty_ & DC_PEN_DIRTY) + IntGdiSelectPen(dc,Dc_Attr->hpen); + PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen); if (NULL == PenBrushObj) { @@ -544,6 +556,12 @@ IntRectangle(PDC dc, DestRect.bottom--; } + if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(dc,Dc_Attr->hbrush); + + if (Dc_Attr->ulDirty_ & DC_PEN_DIRTY) + IntGdiSelectPen(dc,Dc_Attr->hpen); + /* Special locking order to avoid lock-ups! */ FillBrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush); PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen); @@ -703,6 +721,12 @@ IntRoundRect( Dc_Attr = dc->pDc_Attr; if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(dc,Dc_Attr->hbrush); + + if (Dc_Attr->ulDirty_ & DC_PEN_DIRTY) + IntGdiSelectPen(dc,Dc_Attr->hpen); + PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen); if (!PenBrushObj) { @@ -1024,10 +1048,95 @@ NtGdiExtFloodFill( COLORREF Color, UINT FillType) { - DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n"); + PDC dc; + PDC_ATTR Dc_Attr; + BITMAPOBJ *BitmapObj = NULL; + PGDIBRUSHOBJ FillBrushObj = NULL; + GDIBRUSHINST FillBrushInst; + BOOL Ret = FALSE; + RECTL DestRect; + POINTL Pt; +// MIX Mix; - /* lie and say we succeded */ - return TRUE; + DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n"); + + dc = DC_LockDc(hDC); + if (!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + if (dc->DC_Type == DC_TYPE_INFO) + { + DC_UnlockDc(dc); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + + Dc_Attr = dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + + if (Dc_Attr->ulDirty_ & DC_PEN_DIRTY) + IntGdiSelectPen(dc,Dc_Attr->hpen); + + if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(dc,Dc_Attr->hbrush); + + Pt.x = XStart; + Pt.y = YStart; + IntLPtoDP(dc, (LPPOINT)&Pt, 1); + + Ret = NtGdiPtInRegion(dc->w.hGCClipRgn, Pt.x, Pt.y); + if (Ret) + IntGdiGetRgnBox(dc->w.hGCClipRgn,(LPRECT)&DestRect); + else + goto cleanup; + + FillBrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush); + if (!FillBrushObj) + { + Ret = FALSE; + goto cleanup; + } + BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap); + if (!BitmapObj) + { + Ret = FALSE; + goto cleanup; + } + + if ( FillBrushObj && (FillType == FLOODFILLBORDER)) + { + if (!(FillBrushObj->flAttrs & GDIBRUSH_IS_NULL)) + { + FillBrushObj->BrushAttr.lbColor = Color; + IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush); + Ret = IntEngBitBlt(&BitmapObj->SurfObj, + NULL, + NULL, + dc->CombinedClip, + NULL, + &DestRect, + NULL, + NULL, + &FillBrushInst.BrushObject, + NULL, + ROP3_TO_ROP4(PATCOPY)); + } + } + else + { + } + +cleanup: + if (FillBrushObj) + BRUSHOBJ_UnlockBrush(FillBrushObj); + + if (BitmapObj) + BITMAPOBJ_UnlockBitmap(BitmapObj); + + DC_UnlockDc(dc); + return Ret; } /* EOF */ diff --git a/reactos/subsystems/win32/win32k/objects/line.c b/reactos/subsystems/win32/win32k/objects/line.c index acb098caf48..c4368a812ca 100644 --- a/reactos/subsystems/win32/win32k/objects/line.c +++ b/reactos/subsystems/win32/win32k/objects/line.c @@ -115,6 +115,12 @@ IntGdiLineTo(DC *dc, } else { + if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(dc,Dc_Attr->hbrush); + + if (Dc_Attr->ulDirty_ & DC_PEN_DIRTY) + IntGdiSelectPen(dc,Dc_Attr->hpen); + BitmapObj = BITMAPOBJ_LockBitmap ( dc->w.hBitmap ); if (NULL == BitmapObj) { @@ -257,9 +263,16 @@ IntGdiPolyline(DC *dc, PDC_ATTR Dc_Attr = dc->pDc_Attr; if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + if (PATH_IsPathOpen(dc->DcLevel)) return PATH_Polyline(dc, pt, Count); + if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(dc,Dc_Attr->hbrush); + + if (Dc_Attr->ulDirty_ & DC_PEN_DIRTY) + IntGdiSelectPen(dc,Dc_Attr->hpen); + /* Get BRUSHOBJ from current pen. */ PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen); /* FIXME - PenBrushObj can be NULL! Don't assert here! */ diff --git a/reactos/subsystems/win32/win32k/objects/path.c b/reactos/subsystems/win32/win32k/objects/path.c index 980041511f1..4365bc6eb76 100644 --- a/reactos/subsystems/win32/win32k/objects/path.c +++ b/reactos/subsystems/win32/win32k/objects/path.c @@ -1329,7 +1329,9 @@ BOOL FASTCALL PATH_StrokePath(DC *dc, PPATH pPath) if (pPath->state != PATH_Closed) return FALSE; - if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + + /* Save the mapping mode info */ mapMode = Dc_Attr->iMapMode; IntGetViewportExtEx(dc, &szViewportExt); @@ -2265,8 +2267,9 @@ BOOL STDCALL NtGdiFillPath(HDC hDC) { - BOOL ret = TRUE; + BOOL ret = FALSE; PPATH pPath; + PDC_ATTR pDc_Attr; PDC dc = DC_LockDc ( hDC ); if ( !dc ) @@ -2281,6 +2284,12 @@ NtGdiFillPath(HDC hDC) return FALSE; } + pDc_Attr = dc->pDc_Attr; + if (!pDc_Attr) pDc_Attr = &dc->Dc_Attr; + + if (pDc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(dc,pDc_Attr->hbrush); + ret = PATH_FillPath( dc, pPath ); if ( ret ) { @@ -2534,6 +2543,7 @@ STDCALL NtGdiStrokeAndFillPath(HDC hDC) { DC *pDc; + PDC_ATTR pDc_Attr; PPATH pPath; BOOL bRet = FALSE; @@ -2550,6 +2560,15 @@ NtGdiStrokeAndFillPath(HDC hDC) DC_UnlockDc ( pDc ); return FALSE; } + + pDc_Attr = pDc->pDc_Attr; + if (!pDc_Attr) pDc_Attr = &pDc->Dc_Attr; + + if (pDc_Attr->ulDirty_ & DC_BRUSH_DIRTY) + IntGdiSelectBrush(pDc,pDc_Attr->hbrush); + if (pDc_Attr->ulDirty_ & DC_PEN_DIRTY) + IntGdiSelectPen(pDc,pDc_Attr->hpen); + bRet = PATH_FillPath(pDc, pPath); if (bRet) bRet = PATH_StrokePath(pDc, pPath); if (bRet) PATH_EmptyPath(pPath); @@ -2564,6 +2583,7 @@ STDCALL NtGdiStrokePath(HDC hDC) { DC *pDc; + PDC_ATTR pDc_Attr; PPATH pPath; BOOL bRet = FALSE; @@ -2581,6 +2601,12 @@ NtGdiStrokePath(HDC hDC) return FALSE; } + pDc_Attr = pDc->pDc_Attr; + if (!pDc_Attr) pDc_Attr = &pDc->Dc_Attr; + + if (pDc_Attr->ulDirty_ & DC_PEN_DIRTY) + IntGdiSelectPen(pDc,pDc_Attr->hpen); + bRet = PATH_StrokePath(pDc, pPath); PATH_EmptyPath(pPath); diff --git a/reactos/subsystems/win32/win32k/objects/pen.c b/reactos/subsystems/win32/win32k/objects/pen.c index a8c0eb40f57..83a03ad06e0 100644 --- a/reactos/subsystems/win32/win32k/objects/pen.c +++ b/reactos/subsystems/win32/win32k/objects/pen.c @@ -260,6 +260,8 @@ IntGdiSelectPen( XLATEOBJ *XlateObj; BOOLEAN bFailed; + if (pDC == NULL || hPen == NULL) return NULL; + pDc_Attr = pDC->pDc_Attr; if(!pDc_Attr) pDc_Attr = &pDC->Dc_Attr;