[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / objects / fillshap.c
index ba92470..327b628 100644 (file)
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
 
-/*
- * a couple macros to fill a single pixel or a line
- */
-#define PUTPIXEL(x,y,BrushInst)        \
-  ret = ret && IntEngLineTo(&BitmapObj->SurfObj, \
-       dc->CombinedClip,                         \
-       &BrushInst.BrushObject,                   \
-       x, y, (x)+1, y,                           \
-       &RectBounds,                              \
-       ROP2_TO_MIX(Dc_Attr->jROP2));
-
-#define PUTLINE(x1,y1,x2,y2,BrushInst) \
-  ret = ret && IntEngLineTo(&BitmapObj->SurfObj, \
-       dc->CombinedClip,                         \
-       &BrushInst.BrushObject,                   \
-       x1, y1, x2, y2,                           \
-       &RectBounds,                              \
-       ROP2_TO_MIX(Dc_Attr->jROP2));
-
 #define Rsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))
 #define Rcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
 
-BOOL FASTCALL IntFillEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height);
-BOOL FASTCALL IntDrawEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, PGDIBRUSHOBJ PenBrushObj);
-BOOL FASTCALL IntFillRoundRect( PDC dc, INT Left, INT Top, INT Right, INT Bottom, INT Wellipse, INT Hellipse);
-BOOL FASTCALL IntDrawRoundRect( PDC dc, INT Left, INT Top, INT Right, INT Bottom, INT Wellipse, INT Hellipse, PGDIBRUSHOBJ PenBrushObj);
+BOOL FASTCALL IntFillEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, PBRUSH pbrush);
+BOOL FASTCALL IntDrawEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, PBRUSH pbrush);
+BOOL FASTCALL IntFillRoundRect( PDC dc, INT Left, INT Top, INT Right, INT Bottom, INT Wellipse, INT Hellipse, PBRUSH pbrush);
+BOOL FASTCALL IntDrawRoundRect( PDC dc, INT Left, INT Top, INT Right, INT Bottom, INT Wellipse, INT Hellipse, PBRUSH pbrush);
 
 BOOL FASTCALL
 IntGdiPolygon(PDC    dc,
               PPOINT Points,
               int    Count)
 {
-    BITMAPOBJ *BitmapObj;
-    PGDIBRUSHOBJ PenBrushObj, FillBrushObj;
-    GDIBRUSHINST PenBrushInst, FillBrushInst;
+    SURFACE *psurf;
+    PBRUSH pbrLine, pbrFill;
     BOOL ret = FALSE; // default to failure
     RECTL DestRect;
     int CurrentPoint;
-    PDC_ATTR Dc_Attr;
+    PDC_ATTR pdcattr;
+    POINTL BrushOrigin;
+//    int Left;
+//    int Top;
 
     ASSERT(dc); // caller's responsibility to pass a valid dc
 
@@ -70,8 +53,17 @@ IntGdiPolygon(PDC    dc,
         return FALSE;
     }
 
-    Dc_Attr = dc->pDc_Attr;
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+/*
+    //Find start x, y
+    Left = Points[0].x;
+    Top  = Points[0].y;
+    for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) {
+      Left = min(Left, Points[CurrentPoint].x);
+      Top  = min(Top, Points[CurrentPoint].y);
+    }
+*/
+
+    pdcattr = dc->pdcattr;
 
     /* Convert to screen coordinates */
     IntLPtoDP(dc, Points, Count);
@@ -95,29 +87,39 @@ IntGdiPolygon(PDC    dc,
             DestRect.bottom   = max(DestRect.bottom, Points[CurrentPoint].y);
         }
 
+        if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+            DC_vUpdateFillBrush(dc);
+
+        if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+            DC_vUpdateLineBrush(dc);
+
         /* Special locking order to avoid lock-ups */
-        FillBrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush);
-        PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
-        BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
-        /* FIXME - BitmapObj can be NULL!!!! don't assert but handle this case gracefully! */
-        ASSERT(BitmapObj);
-
-        /* Now fill the polygon with the current brush. */
-        if (FillBrushObj && !(FillBrushObj->flAttrs & GDIBRUSH_IS_NULL))
+        pbrFill = dc->dclevel.pbrFill;
+        pbrLine = dc->dclevel.pbrLine;
+        psurf = dc->dclevel.pSurface;
+        /* FIXME - psurf can be NULL!!!! don't assert but handle this case gracefully! */
+        ASSERT(psurf);
+
+        /* Now fill the polygon with the current fill brush. */
+        if (!(pbrFill->flAttrs & GDIBRUSH_IS_NULL))
         {
-            IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush);
-            ret = FillPolygon ( dc, BitmapObj, &FillBrushInst.BrushObject, ROP2_TO_MIX(Dc_Attr->jROP2), Points, Count, DestRect );
+            BrushOrigin = *((PPOINTL)&pbrFill->ptOrigin);
+            BrushOrigin.x += dc->ptlDCOrig.x;
+            BrushOrigin.y += dc->ptlDCOrig.y;
+            ret = IntFillPolygon (dc,
+                                  psurf,
+                                  &dc->eboFill.BrushObject,
+                                  Points,
+                                  Count, 
+                                  DestRect,
+                                  &BrushOrigin);
         }
-        if (FillBrushObj)
-            BRUSHOBJ_UnlockBrush(FillBrushObj);
 
         // Draw the Polygon Edges with the current pen ( if not a NULL pen )
-        if (PenBrushObj && !(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL))
+        if (!(pbrLine->flAttrs & GDIBRUSH_IS_NULL))
         {
             int i;
 
-            IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
-
             for (i = 0; i < Count-1; i++)
             {
 
@@ -125,35 +127,32 @@ IntGdiPolygon(PDC    dc,
 //                                 Points[0].x, Points[0].y,
 //                                 Points[1].x, Points[1].y );
 
-                ret = IntEngLineTo(&BitmapObj->SurfObj,
-                                   dc->CombinedClip,
-                                   &PenBrushInst.BrushObject,
+                ret = IntEngLineTo(&psurf->SurfObj,
+                                   dc->rosdc.CombinedClip,
+                                   &dc->eboLine.BrushObject,
                                    Points[i].x,          /* From */
                                    Points[i].y,
                                    Points[i+1].x,          /* To */
                                    Points[i+1].y,
                                    &DestRect,
-                                   ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */
+                                   ROP2_TO_MIX(pdcattr->jROP2)); /* MIX */
                 if (!ret) break;
             }
             /* Close the polygon */
             if (ret)
             {
-                ret = IntEngLineTo(&BitmapObj->SurfObj,
-                                   dc->CombinedClip,
-                                   &PenBrushInst.BrushObject,
+                ret = IntEngLineTo(&psurf->SurfObj,
+                                   dc->rosdc.CombinedClip,
+                                   &dc->eboLine.BrushObject,
                                    Points[Count-1].x, /* From */
                                    Points[Count-1].y,
                                    Points[0].x,       /* To */
                                    Points[0].y,
                                    &DestRect,
-                                   ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */
+                                   ROP2_TO_MIX(pdcattr->jROP2)); /* MIX */
             }
         }
-        if (PenBrushObj)
-            PENOBJ_UnlockPen(PenBrushObj);
     }
-    BITMAPOBJ_UnlockBitmap(BitmapObj);
 
     return ret;
 }
@@ -164,7 +163,7 @@ IntGdiPolyPolygon(DC      *dc,
                   PULONG  PolyCounts,
                   int     Count)
 {
-    if (PATH_IsPathOpen(dc->DcLevel))
+    if (PATH_IsPathOpen(dc->dclevel))
         return PATH_PolyPolygon ( dc, Points, (PINT)PolyCounts, Count);
 
     while (--Count >=0)
@@ -192,7 +191,7 @@ IntGdiPolyPolygon(DC      *dc,
  *
  */
 
-BOOL STDCALL
+BOOL APIENTRY
 NtGdiEllipse(
     HDC hDC,
     int Left,
@@ -201,12 +200,14 @@ NtGdiEllipse(
     int Bottom)
 {
     PDC dc;
-    PDC_ATTR Dc_Attr;
+    PDC_ATTR pdcattr;
     RECTL RectBounds;
-    PGDIBRUSHOBJ PenBrushObj;
+    PBRUSH pbrush;
     BOOL ret = TRUE;
     LONG PenWidth, PenOrigWidth;
     LONG RadiusX, RadiusY, CenterX, CenterY;
+    PBRUSH pFillBrushObj;
+    BRUSH tmpFillBrushObj;
 
     if ((Left == Right) || (Top == Bottom)) return TRUE;
 
@@ -216,14 +217,14 @@ NtGdiEllipse(
        SetLastWin32Error(ERROR_INVALID_HANDLE);
        return FALSE;
     }
-    if (dc->DC_Type == DC_TYPE_INFO)
+    if (dc->dctype == DC_TYPE_INFO)
     {
        DC_UnlockDc(dc);
        /* Yes, Windows really returns TRUE in this case */
        return TRUE;
     }
 
-    if (PATH_IsPathOpen(dc->DcLevel))
+    if (PATH_IsPathOpen(dc->dclevel))
     {
         ret = PATH_Ellipse(dc, Left, Top, Right, Bottom);
         DC_UnlockDc(dc);
@@ -239,11 +240,16 @@ NtGdiEllipse(
        INT tmp = Bottom; Bottom = Top; Top = tmp;
     }
 
-    Dc_Attr = dc->pDc_Attr;
-    if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+    pdcattr = dc->pdcattr;
+
+    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+        DC_vUpdateFillBrush(dc);
 
-    PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
-    if (NULL == PenBrushObj)
+    if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+        DC_vUpdateLineBrush(dc);
+
+    pbrush = PEN_LockPen(pdcattr->hpen);
+    if (!pbrush)
     {
         DPRINT1("Ellipse Fail 1\n");
         DC_UnlockDc(dc);
@@ -251,10 +257,10 @@ NtGdiEllipse(
         return FALSE;
     }
 
-    PenOrigWidth = PenWidth = PenBrushObj->ptPenWidth.x;
-    if (PenBrushObj->ulPenStyle == PS_NULL) PenWidth = 0;
+    PenOrigWidth = PenWidth = pbrush->ptPenWidth.x;
+    if (pbrush->ulPenStyle == PS_NULL) PenWidth = 0;
 
-    if (PenBrushObj->ulPenStyle == PS_INSIDEFRAME)
+    if (pbrush->ulPenStyle == PS_INSIDEFRAME)
     {
        if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
        if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
@@ -265,7 +271,7 @@ NtGdiEllipse(
     }
 
     if (!PenWidth) PenWidth = 1;
-    PenBrushObj->ptPenWidth.x = PenWidth;  
+    pbrush->ptPenWidth.x = PenWidth;  
 
     RectBounds.left   = Left;
     RectBounds.right  = Right;
@@ -291,21 +297,39 @@ NtGdiEllipse(
     DPRINT("Ellipse 2: XLeft: %d, YLeft: %d, Width: %d, Height: %d\n",
                CenterX - RadiusX, CenterY + RadiusY, RadiusX*2, RadiusY*2);
 
-    ret = IntFillEllipse( dc,
-                          CenterX - RadiusX,
-                          CenterY - RadiusY,
-                          RadiusX*2, // Width
-                          RadiusY*2); // Height
+    pFillBrushObj = BRUSH_LockBrush(pdcattr->hbrush);
+    if (NULL == pFillBrushObj)   
+    {
+        DPRINT1("FillEllipse Fail\n");
+        SetLastWin32Error(ERROR_INTERNAL_ERROR);
+        ret = FALSE;
+    }
+    else
+    {
+        RtlCopyMemory(&tmpFillBrushObj, pFillBrushObj, sizeof(tmpFillBrushObj));
+//        tmpFillBrushObj.ptOrigin.x += RectBounds.left - Left;
+//        tmpFillBrushObj.ptOrigin.y += RectBounds.top - Top;
+        tmpFillBrushObj.ptOrigin.x += dc->ptlDCOrig.x;
+        tmpFillBrushObj.ptOrigin.y += dc->ptlDCOrig.y;
+        ret = IntFillEllipse( dc,
+                              CenterX - RadiusX,
+                              CenterY - RadiusY,
+                              RadiusX*2, // Width
+                              RadiusY*2, // Height
+                              &tmpFillBrushObj);
+        BRUSH_UnlockBrush(pFillBrushObj);
+    }
+
     if (ret)
        ret = IntDrawEllipse( dc,
                              CenterX - RadiusX,
                              CenterY - RadiusY,
                              RadiusX*2, // Width
                              RadiusY*2, // Height
-                             PenBrushObj);
+                             pbrush);
 
-    PenBrushObj->ptPenWidth.x = PenOrigWidth;
-    PENOBJ_UnlockPen(PenBrushObj);
+    pbrush->ptPenWidth.x = PenOrigWidth;
+    PEN_UnlockPen(pbrush);
     DC_UnlockDc(dc);
     DPRINT("Ellipse Exit.\n");
     return ret;
@@ -334,7 +358,7 @@ extern BOOL FillPolygon(PDC dc,
 
 
 ULONG_PTR
-STDCALL
+APIENTRY
 NtGdiPolyPolyDraw( IN HDC hDC,
                    IN PPOINT UnsafePoints,
                    IN PULONG UnsafeCounts,
@@ -356,7 +380,7 @@ NtGdiPolyPolyDraw( IN HDC hDC,
         return FALSE;
     }
 
-    _SEH_TRY
+    _SEH2_TRY
     {
         ProbeForRead(UnsafePoints, Count * sizeof(POINT), 1);
         ProbeForRead(UnsafeCounts, Count * sizeof(ULONG), 1);
@@ -372,11 +396,11 @@ NtGdiPolyPolyDraw( IN HDC hDC,
             nMaxPoints = max(nMaxPoints, UnsafeCounts[i]);
         }
     }
-    _SEH_HANDLE
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
-        Status = _SEH_GetExceptionCode();
+        Status = _SEH2_GetExceptionCode();
     }
-    _SEH_END;
+    _SEH2_END;
 
     if (!NT_SUCCESS(Status))
     {
@@ -411,17 +435,17 @@ NtGdiPolyPolyDraw( IN HDC hDC,
     SafeCounts = pTemp;
     SafePoints = (PVOID)(SafeCounts + Count);
 
-    _SEH_TRY
+    _SEH2_TRY
     {
         /* Pointers already probed! */
         RtlCopyMemory(SafeCounts, UnsafeCounts, Count * sizeof(ULONG));
         RtlCopyMemory(SafePoints, UnsafePoints, nPoints * sizeof(POINT));
     }
-    _SEH_HANDLE
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
-        Status = _SEH_GetExceptionCode();
+        Status = _SEH2_GetExceptionCode();
     }
-    _SEH_END;
+    _SEH2_END;
 
     if (!NT_SUCCESS(Status))
     {
@@ -446,7 +470,7 @@ NtGdiPolyPolyDraw( IN HDC hDC,
         return FALSE;
     }
 
-    if (dc->DC_Type == DC_TYPE_INFO)
+    if (dc->dctype == DC_TYPE_INFO)
     {
         DC_UnlockDc(dc);
         ExFreePool(pTemp);
@@ -493,33 +517,35 @@ IntRectangle(PDC dc,
              int RightRect,
              int BottomRect)
 {
-    BITMAPOBJ *BitmapObj = NULL;
-    PGDIBRUSHOBJ PenBrushObj = NULL, FillBrushObj = NULL;
-    GDIBRUSHINST PenBrushInst, FillBrushInst;
+    SURFACE *psurf = NULL;
+    PBRUSH pbrLine, pbrFill;
     BOOL       ret = FALSE; // default to failure
     RECTL      DestRect;
     MIX        Mix;
-    PDC_ATTR Dc_Attr;
+    PDC_ATTR pdcattr;
+    POINTL BrushOrigin;
 
     ASSERT ( dc ); // caller's responsibility to set this up
 
-    Dc_Attr = dc->pDc_Attr;
-    if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-
-    if ( PATH_IsPathOpen(dc->DcLevel) )
-    {
-        return PATH_Rectangle ( dc, LeftRect, TopRect, RightRect, BottomRect );
-    }
+    pdcattr = dc->pdcattr;
 
     /* Do we rotate or shear? */
-    if (!(dc->DcLevel.mxWorldToDevice.flAccel & MX_SCALE))
+    if (!(dc->dclevel.mxWorldToDevice.flAccel & MX_SCALE))
     {
+
         POINTL DestCoords[4];
+        ULONG  PolyCounts = 4;
         DestCoords[0].x = DestCoords[3].x = LeftRect;
         DestCoords[0].y = DestCoords[1].y = TopRect;
         DestCoords[1].x = DestCoords[2].x = RightRect;
         DestCoords[2].y = DestCoords[3].y = BottomRect;
-        return IntGdiPolygon(dc, DestCoords, 4);
+        // Use IntGdiPolyPolygon so to support PATH.
+        return IntGdiPolyPolygon(dc, DestCoords, &PolyCounts, 1);
+    }
+    // Rectangle Path only.
+    if ( PATH_IsPathOpen(dc->dclevel) )
+    {
+        return PATH_Rectangle ( dc, LeftRect, TopRect, RightRect, BottomRect );
     }
 
     DestRect.left = LeftRect;
@@ -535,94 +561,90 @@ IntRectangle(PDC dc,
     DestRect.bottom += dc->ptlDCOrig.y;
 
     /* In GM_COMPATIBLE, don't include bottom and right edges */
-    if (IntGetGraphicsMode(dc) == GM_COMPATIBLE)
+    if (pdcattr->iGraphicsMode == GM_COMPATIBLE)
     {
         DestRect.right--;
         DestRect.bottom--;
     }
 
-    /* Special locking order to avoid lock-ups! */
-    FillBrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush);
-    PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
-    if (!PenBrushObj)
+    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+        DC_vUpdateFillBrush(dc);
+
+    if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+        DC_vUpdateLineBrush(dc);
+
+    pbrFill = dc->dclevel.pbrFill;
+    pbrLine = dc->dclevel.pbrLine;
+    if (!pbrLine)
     {
         ret = FALSE;
         goto cleanup;
     }
-    BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
-    if (!BitmapObj)
+    psurf = dc->dclevel.pSurface;
+    if (!psurf)
     {
         ret = FALSE;
         goto cleanup;
     }
 
-    if ( FillBrushObj )
+    if (pbrFill)
     {
-        if (!(FillBrushObj->flAttrs & GDIBRUSH_IS_NULL))
+        if (!(pbrFill->flAttrs & GDIBRUSH_IS_NULL))
         {
-            IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush);
-            ret = IntEngBitBlt(&BitmapObj->SurfObj,
+            BrushOrigin = *((PPOINTL)&pbrFill->ptOrigin);
+            BrushOrigin.x += dc->ptlDCOrig.x;
+            BrushOrigin.y += dc->ptlDCOrig.y;
+            ret = IntEngBitBlt(&psurf->SurfObj,
                                NULL,
                                NULL,
-                               dc->CombinedClip,
+                               dc->rosdc.CombinedClip,
                                NULL,
                                &DestRect,
                                NULL,
                                NULL,
-                               &FillBrushInst.BrushObject,
-                               NULL,
+                               &dc->eboFill.BrushObject,
+                               &BrushOrigin,
                                ROP3_TO_ROP4(PATCOPY));
         }
     }
 
-    IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
-
     // Draw the rectangle with the current pen
 
     ret = TRUE; // change default to success
 
-    if (!(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL))
+    if (!(pbrLine->flAttrs & GDIBRUSH_IS_NULL))
     {
-        Mix = ROP2_TO_MIX(Dc_Attr->jROP2);
-        ret = ret && IntEngLineTo(&BitmapObj->SurfObj,
-                                  dc->CombinedClip,
-                                  &PenBrushInst.BrushObject,
+        Mix = ROP2_TO_MIX(pdcattr->jROP2);
+        ret = ret && IntEngLineTo(&psurf->SurfObj,
+                                  dc->rosdc.CombinedClip,
+                                  &dc->eboLine.BrushObject,
                                   DestRect.left, DestRect.top, DestRect.right, DestRect.top,
                                   &DestRect, // Bounding rectangle
                                   Mix);
 
-        ret = ret && IntEngLineTo(&BitmapObj->SurfObj,
-                                  dc->CombinedClip,
-                                  &PenBrushInst.BrushObject,
+        ret = ret && IntEngLineTo(&psurf->SurfObj,
+                                  dc->rosdc.CombinedClip,
+                                  &dc->eboLine.BrushObject,
                                   DestRect.right, DestRect.top, DestRect.right, DestRect.bottom,
                                   &DestRect, // Bounding rectangle
                                   Mix);
 
-        ret = ret && IntEngLineTo(&BitmapObj->SurfObj,
-                                  dc->CombinedClip,
-                                  &PenBrushInst.BrushObject,
+        ret = ret && IntEngLineTo(&psurf->SurfObj,
+                                  dc->rosdc.CombinedClip,
+                                  &dc->eboLine.BrushObject,
                                   DestRect.right, DestRect.bottom, DestRect.left, DestRect.bottom,
                                   &DestRect, // Bounding rectangle
                                   Mix);
 
-        ret = ret && IntEngLineTo(&BitmapObj->SurfObj,
-                                  dc->CombinedClip,
-                                  &PenBrushInst.BrushObject,
+        ret = ret && IntEngLineTo(&psurf->SurfObj,
+                                  dc->rosdc.CombinedClip,
+                                  &dc->eboLine.BrushObject,
                                   DestRect.left, DestRect.bottom, DestRect.left, DestRect.top,
                                   &DestRect, // Bounding rectangle
                                   Mix);
     }
 
 cleanup:
-    if (FillBrushObj)
-        BRUSHOBJ_UnlockBrush(FillBrushObj);
-
-    if (PenBrushObj)
-        PENOBJ_UnlockPen(PenBrushObj);
-
-    if (BitmapObj)
-        BITMAPOBJ_UnlockBitmap(BitmapObj);
-
     /* Move current position in DC?
        MSDN: The current position is neither used nor updated by Rectangle. */
 
@@ -630,7 +652,7 @@ cleanup:
 }
 
 BOOL
-STDCALL
+APIENTRY
 NtGdiRectangle(HDC  hDC,
                int  LeftRect,
                int  TopRect,
@@ -646,7 +668,7 @@ NtGdiRectangle(HDC  hDC,
         SetLastWin32Error(ERROR_INVALID_HANDLE);
         return FALSE;
     }
-    if (dc->DC_Type == DC_TYPE_INFO)
+    if (dc->dctype == DC_TYPE_INFO)
     {
         DC_UnlockDc(dc);
         /* Yes, Windows really returns TRUE in this case */
@@ -671,15 +693,16 @@ IntRoundRect(
     int  xCurveDiameter,
     int  yCurveDiameter)
 {
-    PDC_ATTR Dc_Attr;
-    PGDIBRUSHOBJ   PenBrushObj;
+    PDC_ATTR pdcattr;
+    PBRUSH   pbrushLine, pbrushFill;
     RECTL RectBounds;
     LONG PenWidth, PenOrigWidth;
     BOOL ret = TRUE; // default to success
+    BRUSH brushTemp;
 
     ASSERT ( dc ); // caller's responsibility to set this up
 
-    if ( PATH_IsPathOpen(dc->DcLevel) )
+    if ( PATH_IsPathOpen(dc->dclevel) )
         return PATH_RoundRect ( dc, Left, Top, Right, Bottom,
                                 xCurveDiameter, yCurveDiameter );
 
@@ -697,21 +720,26 @@ IntRoundRect(
        INT tmp = Bottom; Bottom = Top; Top = tmp;
     }
 
-    Dc_Attr = dc->pDc_Attr;
-    if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+    pdcattr = dc->pdcattr;
+
+    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+        DC_vUpdateFillBrush(dc);
+
+    if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+        DC_vUpdateLineBrush(dc);
 
-    PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
-    if (!PenBrushObj)
+    pbrushLine = PEN_LockPen(pdcattr->hpen);
+    if (!pbrushLine)
     {
         /* Nothing to do, as we don't have a bitmap */
         SetLastWin32Error(ERROR_INTERNAL_ERROR);
         return FALSE;
     }
 
-    PenOrigWidth = PenWidth = PenBrushObj->ptPenWidth.x;
-    if (PenBrushObj->ulPenStyle == PS_NULL) PenWidth = 0;
+    PenOrigWidth = PenWidth = pbrushLine->ptPenWidth.x;
+    if (pbrushLine->ulPenStyle == PS_NULL) PenWidth = 0;
 
-    if (PenBrushObj->ulPenStyle == PS_INSIDEFRAME)
+    if (pbrushLine->ulPenStyle == PS_INSIDEFRAME)
     {
        if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
        if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
@@ -722,7 +750,7 @@ IntRoundRect(
     }
 
     if (!PenWidth) PenWidth = 1;
-    PenBrushObj->ptPenWidth.x = PenWidth;  
+    pbrushLine->ptPenWidth.x = PenWidth;  
 
     RectBounds.left = Left;
     RectBounds.top = Top;
@@ -736,13 +764,29 @@ IntRoundRect(
     RectBounds.right  += dc->ptlDCOrig.x;
     RectBounds.bottom += dc->ptlDCOrig.y;
 
-    ret = IntFillRoundRect( dc,
-               RectBounds.left,
-                RectBounds.top,
-              RectBounds.right,
-             RectBounds.bottom,
-                xCurveDiameter,
-                yCurveDiameter);
+    pbrushFill = BRUSH_LockBrush(pdcattr->hbrush);
+    if (NULL == pbrushFill)   
+    {
+        DPRINT1("FillRound Fail\n");
+        SetLastWin32Error(ERROR_INTERNAL_ERROR);
+        ret = FALSE;
+    } 
+    else
+    {
+        RtlCopyMemory(&brushTemp, pbrushFill, sizeof(brushTemp));
+        brushTemp.ptOrigin.x += RectBounds.left - Left;
+        brushTemp.ptOrigin.y += RectBounds.top - Top;
+        ret = IntFillRoundRect( dc,
+                                RectBounds.left,
+                                RectBounds.top,
+                                RectBounds.right,
+                                RectBounds.bottom,
+                                xCurveDiameter,
+                                yCurveDiameter,
+                                &brushTemp);
+        BRUSH_UnlockBrush(pbrushFill);
+    }
+
     if (ret)
        ret = IntDrawRoundRect( dc,
                   RectBounds.left,
@@ -751,15 +795,15 @@ IntRoundRect(
                 RectBounds.bottom,
                    xCurveDiameter,
                    yCurveDiameter,
-                   PenBrushObj);
+                   pbrushLine);
 
-    PenBrushObj->ptPenWidth.x = PenOrigWidth;
-    PENOBJ_UnlockPen(PenBrushObj);
+    pbrushLine->ptPenWidth.x = PenOrigWidth;
+    PEN_UnlockPen(pbrushLine);
     return ret;
 }
 
 BOOL
-STDCALL
+APIENTRY
 NtGdiRoundRect(
     HDC  hDC,
     int  LeftRect,
@@ -778,7 +822,7 @@ NtGdiRoundRect(
         DPRINT1("NtGdiRoundRect() - hDC is invalid\n");
         SetLastWin32Error(ERROR_INVALID_HANDLE);
     }
-    else if (dc->DC_Type == DC_TYPE_INFO)
+    else if (dc->dctype == DC_TYPE_INFO)
     {
         DC_UnlockDc(dc);
         /* Yes, Windows really returns TRUE in this case */
@@ -793,40 +837,36 @@ NtGdiRoundRect(
     return ret;
 }
 
-BOOL FASTCALL
-IntGdiGradientFill(
-    DC *dc,
+BOOL
+NTAPI
+GreGradientFill(
+    HDC hdc,
     PTRIVERTEX pVertex,
-    ULONG uVertex,
+    ULONG nVertex,
     PVOID pMesh,
-    ULONG uMesh,
+    ULONG nMesh,
     ULONG ulMode)
 {
-    BITMAPOBJ *BitmapObj;
-    PPALGDI PalDestGDI;
-    XLATEOBJ *XlateObj;
-    RECTL Extent;
-    POINTL DitherOrg;
-    ULONG Mode, i;
-    BOOL Ret;
+    PDC pdc;
+    SURFACE *psurf;
+    PPALETTE ppal;
+    EXLATEOBJ exlo;
+    RECTL rclExtent;
+    POINTL ptlDitherOrg;
+    ULONG i;
+    BOOL bRet;
     HPALETTE hDestPalette;
 
-    ASSERT(dc);
-    ASSERT(pVertex);
-    ASSERT(uVertex);
-    ASSERT(pMesh);
-    ASSERT(uMesh);
-
-    /* check parameters */
-    if (ulMode & GRADIENT_FILL_TRIANGLE)
+    /* Check parameters */
+    if (ulMode == GRADIENT_FILL_TRIANGLE)
     {
-        PGRADIENT_TRIANGLE tr = (PGRADIENT_TRIANGLE)pMesh;
+        PGRADIENT_TRIANGLE pTriangle = (PGRADIENT_TRIANGLE)pMesh;
 
-        for (i = 0; i < uMesh; i++, tr++)
+        for (i = 0; i < nMesh; i++, pTriangle++)
         {
-            if (tr->Vertex1 >= uVertex ||
-                    tr->Vertex2 >= uVertex ||
-                    tr->Vertex3 >= uVertex)
+            if (pTriangle->Vertex1 >= nVertex ||
+                pTriangle->Vertex2 >= nVertex ||
+                pTriangle->Vertex3 >= nVertex)
             {
                 SetLastWin32Error(ERROR_INVALID_PARAMETER);
                 return FALSE;
@@ -835,10 +875,10 @@ IntGdiGradientFill(
     }
     else
     {
-        PGRADIENT_RECT rc = (PGRADIENT_RECT)pMesh;
-        for (i = 0; i < uMesh; i++, rc++)
+        PGRADIENT_RECT pRect = (PGRADIENT_RECT)pMesh;
+        for (i = 0; i < nMesh; i++, pRect++)
         {
-            if (rc->UpperLeft >= uVertex || rc->LowerRight >= uVertex)
+            if (pRect->UpperLeft >= nVertex || pRect->LowerRight >= nVertex)
             {
                 SetLastWin32Error(ERROR_INVALID_PARAMETER);
                 return FALSE;
@@ -846,92 +886,98 @@ IntGdiGradientFill(
         }
     }
 
-    /* calculate extent */
-    Extent.left = Extent.right = pVertex->x;
-    Extent.top = Extent.bottom = pVertex->y;
-    for (i = 0; i < uVertex; i++)
+    /* Lock the output DC */
+    pdc = DC_LockDc(hdc);
+    if (!pdc)
     {
-        Extent.left = min(Extent.left, (pVertex + i)->x);
-        Extent.right = max(Extent.right, (pVertex + i)->x);
-        Extent.top = min(Extent.top, (pVertex + i)->y);
-        Extent.bottom = max(Extent.bottom, (pVertex + i)->y);
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
     }
 
-    DitherOrg.x = dc->ptlDCOrig.x;
-    DitherOrg.y = dc->ptlDCOrig.y;
-    Extent.left += DitherOrg.x;
-    Extent.right += DitherOrg.x;
-    Extent.top += DitherOrg.y;
-    Extent.bottom += DitherOrg.y;
-
-    BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
-    /* FIXME - BitmapObj can be NULL!!! Don't assert but handle this case gracefully! */
-    ASSERT(BitmapObj);
+    if (pdc->dctype == DC_TYPE_INFO)
+    {
+        DC_UnlockDc(pdc);
+        /* Yes, Windows really returns TRUE in this case */
+        return TRUE;
+    }
 
-    hDestPalette = BitmapObj->hDIBPalette;
-    if (!hDestPalette) hDestPalette = pPrimarySurface->DevInfo.hpalDefault;
+    psurf = pdc->dclevel.pSurface;
+    if (!psurf)
+    {
+        /* Memory DC with no surface selected */
+        DC_UnlockDc(pdc);
+        return TRUE; // CHECKME
+    }
 
-    PalDestGDI = PALETTE_LockPalette(hDestPalette);
-    if (PalDestGDI)
+    /* calculate extent */
+    rclExtent.left = rclExtent.right = pVertex->x;
+    rclExtent.top = rclExtent.bottom = pVertex->y;
+    for (i = 0; i < nVertex; i++)
     {
-        Mode = PalDestGDI->Mode;
-        PALETTE_UnlockPalette(PalDestGDI);
+        rclExtent.left = min(rclExtent.left, (pVertex + i)->x);
+        rclExtent.right = max(rclExtent.right, (pVertex + i)->x);
+        rclExtent.top = min(rclExtent.top, (pVertex + i)->y);
+        rclExtent.bottom = max(rclExtent.bottom, (pVertex + i)->y);
     }
-    else
-        Mode = PAL_RGB;
 
-    XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, hDestPalette, NULL);
-    ASSERT(XlateObj);
+    IntLPtoDP(pdc, (LPPOINT)&rclExtent, 2);
+    rclExtent.left   += pdc->ptlDCOrig.x;
+    rclExtent.right  += pdc->ptlDCOrig.x;
+    rclExtent.top    += pdc->ptlDCOrig.y;
+    rclExtent.bottom += pdc->ptlDCOrig.y;
 
-    Ret = IntEngGradientFill(&BitmapObj->SurfObj,
-                             dc->CombinedClip,
-                             XlateObj,
-                             pVertex,
-                             uVertex,
-                             pMesh,
-                             uMesh,
-                             &Extent,
-                             &DitherOrg,
-                             ulMode);
+    ptlDitherOrg.x = ptlDitherOrg.y = 0;
+    IntLPtoDP(pdc, (LPPOINT)&ptlDitherOrg, 1);
+    ptlDitherOrg.x += pdc->ptlDCOrig.x;
+    ptlDitherOrg.y += pdc->ptlDCOrig.y;
 
-    BITMAPOBJ_UnlockBitmap(BitmapObj);
-    EngDeleteXlate(XlateObj);
+    hDestPalette = psurf->hDIBPalette;
+    if (!hDestPalette) hDestPalette = pPrimarySurface->devinfo.hpalDefault;
 
-    return Ret;
+    ppal = PALETTE_LockPalette(hDestPalette);
+    EXLATEOBJ_vInitialize(&exlo, &gpalRGB, ppal, 0, 0, 0);
+
+    ASSERT(pdc->rosdc.CombinedClip);
+
+    bRet = IntEngGradientFill(&psurf->SurfObj,
+                              pdc->rosdc.CombinedClip,
+                              &exlo.xlo,
+                              pVertex,
+                              nVertex,
+                              pMesh,
+                              nMesh,
+                              &rclExtent,
+                              &ptlDitherOrg,
+                              ulMode);
+
+    EXLATEOBJ_vCleanup(&exlo);
+
+    if (ppal)
+        PALETTE_UnlockPalette(ppal);
+
+    DC_UnlockDc(pdc);
+
+    return bRet;
 }
 
 BOOL
-STDCALL
+APIENTRY
 NtGdiGradientFill(
     HDC hdc,
     PTRIVERTEX pVertex,
-    ULONG uVertex,
+    ULONG nVertex,
     PVOID pMesh,
-    ULONG uMesh,
+    ULONG nMesh,
     ULONG ulMode)
 {
-    DC *dc;
-    BOOL Ret;
+    BOOL bRet;
     PTRIVERTEX SafeVertex;
     PVOID SafeMesh;
-    ULONG SizeMesh;
-    NTSTATUS Status = STATUS_SUCCESS;
+    ULONG cbVertex, cbMesh;
 
-    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;
-    }
-    if (!pVertex || !uVertex || !pMesh || !uMesh)
+    /* Validate parameters */
+    if (!pVertex || !nVertex || !pMesh || !nMesh)
     {
-        DC_UnlockDc(dc);
         SetLastWin32Error(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
@@ -940,80 +986,58 @@ NtGdiGradientFill(
     {
         case GRADIENT_FILL_RECT_H:
         case GRADIENT_FILL_RECT_V:
-            SizeMesh = uMesh * sizeof(GRADIENT_RECT);
+            cbMesh = nMesh * sizeof(GRADIENT_RECT);
             break;
         case GRADIENT_FILL_TRIANGLE:
-            SizeMesh = uMesh * sizeof(TRIVERTEX);
+            cbMesh = nMesh * sizeof(GRADIENT_TRIANGLE);
             break;
         default:
-            DC_UnlockDc(dc);
             SetLastWin32Error(ERROR_INVALID_PARAMETER);
             return FALSE;
     }
 
-    _SEH_TRY
-    {
-        ProbeForRead(pVertex,
-                     uVertex * sizeof(TRIVERTEX),
-                     1);
-        ProbeForRead(pMesh,
-                     SizeMesh,
-                     1);
-    }
-    _SEH_HANDLE
-    {
-        Status = _SEH_GetExceptionCode();
-    }
-    _SEH_END;
-
-    if (!NT_SUCCESS(Status))
+    cbVertex = nVertex * sizeof(TRIVERTEX);
+    if (cbVertex + cbMesh <= cbVertex)
     {
-        DC_UnlockDc(dc);
-        SetLastWin32Error(Status);
+        /* Overflow */
         return FALSE;
     }
 
-    if (!(SafeVertex = ExAllocatePoolWithTag(PagedPool, (uVertex * sizeof(TRIVERTEX)) + SizeMesh, TAG_SHAPE)))
+    /* Allocate a kernel mode buffer */
+    SafeVertex = ExAllocatePoolWithTag(PagedPool, cbVertex + cbMesh, TAG_SHAPE);
+    if (!SafeVertex)
     {
-        DC_UnlockDc(dc);
         SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
 
-    SafeMesh = (PTRIVERTEX)(SafeVertex + uVertex);
+    SafeMesh = (PVOID)((ULONG_PTR)SafeVertex + cbVertex);
 
-    _SEH_TRY
-    {
-        /* pointers were already probed! */
-        RtlCopyMemory(SafeVertex,
-                      pVertex,
-                      uVertex * sizeof(TRIVERTEX));
-        RtlCopyMemory(SafeMesh,
-                      pMesh,
-                      SizeMesh);
-    }
-    _SEH_HANDLE
+    /* Copy the parameters to kernel mode */
+    _SEH2_TRY
     {
-        Status = _SEH_GetExceptionCode();
+        ProbeForRead(pVertex, cbVertex, 1);
+        ProbeForRead(pMesh, cbMesh, 1);
+        RtlCopyMemory(SafeVertex, pVertex, cbVertex);
+        RtlCopyMemory(SafeMesh, pMesh, cbMesh);
     }
-    _SEH_END;
-
-    if (!NT_SUCCESS(Status))
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
-        DC_UnlockDc(dc);
         ExFreePoolWithTag(SafeVertex, TAG_SHAPE);
-        SetLastNtError(Status);
-        return FALSE;
+        SetLastNtError(_SEH2_GetExceptionCode());
+        _SEH2_YIELD(return FALSE;)
     }
+    _SEH2_END;
 
-    Ret = IntGdiGradientFill(dc, SafeVertex, uVertex, SafeMesh, uMesh, ulMode);
+    /* Call the internal function */
+    bRet = GreGradientFill(hdc, SafeVertex, nVertex, SafeMesh, nMesh, ulMode);
 
-    DC_UnlockDc(dc);
-    ExFreePool(SafeVertex);
-    return Ret;
+    /* Cleanup and return result */
+    ExFreePoolWithTag(SafeVertex, TAG_SHAPE);
+    return bRet;
 }
 
-BOOL STDCALL
+BOOL APIENTRY
 NtGdiExtFloodFill(
     HDC  hDC,
     INT  XStart,
@@ -1021,10 +1045,74 @@ NtGdiExtFloodFill(
     COLORREF  Color,
     UINT  FillType)
 {
-    DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
+    PDC dc;
+    PDC_ATTR   pdcattr;
+    SURFACE    *psurf = NULL;
+    HPALETTE   hpal;
+    PPALETTE   ppal;
+    EXLATEOBJ  exlo;
+    BOOL       Ret = FALSE;
+    RECTL      DestRect;
+    POINTL     Pt;
+    ULONG      ConvColor;
 
-    /* lie and say we succeded */
-    return TRUE;
+    dc = DC_LockDc(hDC);
+    if (!dc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (dc->dctype == DC_TYPE_INFO)
+    {
+        DC_UnlockDc(dc);
+        /* Yes, Windows really returns TRUE in this case */
+        return TRUE;
+    }
+
+    pdcattr = dc->pdcattr;
+
+    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+        DC_vUpdateFillBrush(dc);
+
+    if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+        DC_vUpdateLineBrush(dc);
+
+    Pt.x = XStart;
+    Pt.y = YStart;
+    IntLPtoDP(dc, (LPPOINT)&Pt, 1);
+
+    Ret = NtGdiPtInRegion(dc->rosdc.hGCClipRgn, Pt.x, Pt.y);
+    if (Ret)
+        IntGdiGetRgnBox(dc->rosdc.hGCClipRgn,(LPRECT)&DestRect);
+    else
+        goto cleanup;
+
+    psurf = dc->dclevel.pSurface;
+    if (!psurf)
+    {
+        Ret = FALSE;
+        goto cleanup;
+    }
+
+    hpal = dc->dclevel.pSurface->hDIBPalette;
+    if (!hpal) hpal = pPrimarySurface->devinfo.hpalDefault;
+    ppal = PALETTE_ShareLockPalette(hpal);
+    
+    EXLATEOBJ_vInitialize(&exlo, &gpalRGB, ppal, 0, 0xffffff, 0);
+
+    /* Only solid fills supported for now
+     * How to support pattern brushes and non standard surfaces (not offering dib functions):
+     * Version a (most likely slow): call DrvPatBlt for every pixel
+     * Version b: create a flood mask and let MaskBlt blit a masked brush */
+    ConvColor = XLATEOBJ_iXlate(&exlo.xlo, Color);
+    Ret = DIB_XXBPP_FloodFillSolid(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, ConvColor, FillType);
+
+    EXLATEOBJ_vCleanup(&exlo);
+    PALETTE_ShareUnlockPalette(ppal);
+
+cleanup:
+    DC_UnlockDc(dc);
+    return Ret;
 }
 
 /* EOF */