Fix polygon outline special case and min/max caption buttons
authorGé van Geldorp <ge@gse.nl>
Wed, 25 Jun 2003 16:55:33 +0000 (16:55 +0000)
committerGé van Geldorp <ge@gse.nl>
Wed, 25 Jun 2003 16:55:33 +0000 (16:55 +0000)
svn path=/trunk/; revision=4965

reactos/lib/user32/windows/draw.c
reactos/subsys/win32k/include/paint.h
reactos/subsys/win32k/objects/fillshap.c
reactos/subsys/win32k/objects/polyfill.c

index dd63408..e98a85a 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: draw.c,v 1.11 2003/05/12 19:30:00 jfilby Exp $
+/* $Id: draw.c,v 1.12 2003/06/25 16:55:32 gvg Exp $
  *
  * PROJECT:         ReactOS user32.dll
  * FILE:            lib/user32/windows/input.c
@@ -983,7 +983,7 @@ static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags)
         return TRUE;
 
     case DFCS_CAPTIONMIN:
-        Line1[0].x = Line1[3].x = myr.left   +  96*SmallDiam/750+2;
+        Line1[0].x = Line1[3].x = myr.left   +  96*SmallDiam/750+3; /* Wine uses +2 here?? */
         Line1[1].x = Line1[2].x = Line1[0].x + 372*SmallDiam/750;
         Line1[0].y = Line1[1].y = myr.top    + 563*SmallDiam/750+1;
         Line1[2].y = Line1[3].y = Line1[0].y +  92*SmallDiam/750;
index 7c5f6f3..3eb8a79 100644 (file)
@@ -2,7 +2,7 @@
 #define __WIN32K_PAINT_H
 
 BOOL STDCALL FillSolid (PSURFOBJ Surface, PRECTL Dimensions, ULONG iColor);
-BOOL STDCALL FillPolygon_ALTERNATE (PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect, INT OrigX, INT OrigY);
-BOOL STDCALL FillPolygon_WINDING (PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect, INT OrigX, INT OrigY);
+BOOL STDCALL FillPolygon_ALTERNATE (PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect);
+BOOL STDCALL FillPolygon_WINDING (PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect);
 
-#endif /* __WIN32K_DIB_H */
+#endif /* __WIN32K_PAINT_H */
index 8e84b60..29c047e 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: fillshap.c,v 1.19 2003/06/06 10:27:43 gvg Exp $ */
+/* $Id: fillshap.c,v 1.20 2003/06/25 16:55:33 gvg Exp $ */
 
 #undef WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <win32k/fillshap.h>
 #include <win32k/dc.h>
 #include <win32k/pen.h>
+#include <include/error.h>
 #include <include/object.h>
 #include <include/inteng.h>
 #include <include/path.h>
 #include <include/paint.h>
+#include <internal/safe.h>
 
 #define NDEBUG
 #include <win32k/debug1.h>
@@ -85,9 +87,7 @@ extern BOOL FillPolygon_ALTERNATE(SURFOBJ *SurfObj,
                                   MIX RopMode,
                                   CONST PPOINT Points,
                                   int Count,
-                                  RECTL BoundRect,
-                                  int OrigX,
-                                  int OrigY);
+                                  RECTL BoundRect);
 
 
 //WINDING Selects winding mode (fills any region with a nonzero winding value). 
@@ -98,110 +98,168 @@ extern BOOL FillPolygon_WINDING(SURFOBJ *SurfObj,
                                 PBRUSHOBJ BrushObj,MIX RopMode,
                                 CONST PPOINT Points,
                                 int Count,
-                                RECTL BoundRect,
-                                int OrigX,
-                                int OrigY);
+                                RECTL BoundRect);
 #endif
 
 //This implementation is blatantly ripped off from W32kRectangle
 BOOL
 STDCALL
 W32kPolygon(HDC  hDC,
-            CONST PPOINT  Points,
-            int  Count)
+            CONST PPOINT UnsafePoints,
+            int Count)
 {
-  DC           *dc = DC_HandleToPtr(hDC);
-  SURFOBJ      *SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface);
-  PBRUSHOBJ    OutBrushObj, FillBrushObj;
-  BOOL      ret;
-  PRECTL       RectBounds;
-  PENOBJ    *pen;
-  RECTL     DestRect;
-  int       CurrentPoint;
+  DC *dc = DC_HandleToPtr(hDC);
+  SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface);
+  PBRUSHOBJ OutBrushObj, FillBrushObj;
+  BOOL ret;
+  PRECTL RectBounds;
+  PENOBJ *pen;
+  RECTL DestRect;
+  int CurrentPoint;
+  PPOINT Points;
+  NTSTATUS Status;
 
   DPRINT("In W32kPolygon()\n");
   
-  if(0 == dc)
-   return FALSE;
+  if (NULL == dc || NULL == Points || Count < 2)
+    {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      return FALSE;
+    }
 
-  if(0 == Points)
-   return FALSE;
+  /* Copy points from userspace to kernelspace */
+  Points = ExAllocatePool(PagedPool, Count * sizeof(POINT));
+  if (NULL == Points)
+    {
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return FALSE;
+    }
+  Status = MmCopyFromCaller(Points, UnsafePoints, Count * sizeof(POINT));
+  if (! NT_SUCCESS(Status))
+    {
+      SetLastNtError(Status);
+      ExFreePool(Points);
+      return FALSE;
+    }
 
-  if (2 > Count)
-   return FALSE;
+  /* Convert to screen coordinates */
+  for (CurrentPoint = 0; CurrentPoint < Count; CurrentPoint++)
+    {
+      Points[CurrentPoint].x += dc->w.DCOrgX;
+      Points[CurrentPoint].y += dc->w.DCOrgY;
+    }
 
   RectBounds = GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC);
   //ei not yet implemented ASSERT(RectBounds);
-       
-  DestRect.bottom   = Points[0].y + dc->w.DCOrgY + 1;
-  DestRect.top      = Points[0].y + dc->w.DCOrgY;
-  DestRect.right    = Points[0].y + dc->w.DCOrgX;
-  DestRect.left     = Points[0].y + dc->w.DCOrgX + 1;
-  
-
 
-  if(PATH_IsPathOpen(dc->w.path)) 
-  {      
+  if (PATH_IsPathOpen(dc->w.path)) 
+    {    
       ret = PATH_Polygon(hDC, Points, Count);
-  } 
+    
   else 
-  {
-         //Get the current pen.
-         pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
+    {
+      /* Get the current pen. */
+      pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
       ASSERT(pen);
-      OutBrushObj = (PBRUSHOBJ)PenToBrushObj(dc, pen);
-      GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC );
+      OutBrushObj = (PBRUSHOBJ) PenToBrushObj(dc, pen);
+      GDIOBJ_UnlockObj(dc->w.hPen, GO_PEN_MAGIC);
+       
+      DestRect.left   = Points[0].x;
+      DestRect.right  = Points[0].x;
+      DestRect.top    = Points[0].y;
+      DestRect.bottom = Points[0].y;
          
-      // Draw the Polygon Edges with the current pen
-         for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint)
-      {
-                 DestRect.bottom   = MAX(DestRect.bottom, Points[CurrentPoint].y);
-                 DestRect.top      = MIN(DestRect.top, Points[CurrentPoint].y);
-                 DestRect.right    = MAX(DestRect.right, Points[CurrentPoint].y);
-                 DestRect.left     = MIN(DestRect.left, Points[CurrentPoint].y);
-         }//for
+      for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint)
+       {
+         DestRect.left     = MIN(DestRect.left, Points[CurrentPoint].x);
+         DestRect.right    = MAX(DestRect.right, Points[CurrentPoint].x);
+         DestRect.top      = MIN(DestRect.top, Points[CurrentPoint].y);
+         DestRect.bottom   = MAX(DestRect.bottom, Points[CurrentPoint].y);
+       }
        
-         //Now fill the polygon with the current brush.
-         FillBrushObj = (BRUSHOBJ*) GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
-         // determine the fill mode to fill the polygon.
-         if (dc->w.polyFillMode == WINDING)
-                 ret = FillPolygon_WINDING(SurfObj,  FillBrushObj, dc->w.ROPmode, Points, Count, DestRect, dc->w.DCOrgX, dc->w.DCOrgY);
-         else//default
-                 ret = FillPolygon_ALTERNATE(SurfObj,  FillBrushObj, dc->w.ROPmode, Points, Count, DestRect, dc->w.DCOrgX, dc->w.DCOrgY);
+      /* Now fill the polygon with the current brush. */
+      FillBrushObj = (BRUSHOBJ*) GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
+      /* determine the fill mode to fill the polygon. */
+      if (WINDING == dc->w.polyFillMode)
+       {
+         ret = FillPolygon_WINDING(SurfObj,  FillBrushObj, dc->w.ROPmode, Points, Count, DestRect);
+       }
+      else /* default */
+       {
+         ret = FillPolygon_ALTERNATE(SurfObj,  FillBrushObj, dc->w.ROPmode, Points, Count, DestRect);
+       }
+
       // Draw the Polygon Edges with the current pen
-         for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint)
-         { 
-        POINT To,From;
-           //Let CurrentPoint be i
-           //if i+1 > Count, Draw a line from Points[i] to Points[0]
-               //Draw a line from Points[i] to Points[i+1] 
-               if (CurrentPoint + 1 >= Count)
+      for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint)
+       { 
+          POINT To, From, Next;
+
+         /* Let CurrentPoint be i
+          * if i+1 > Count, Draw a line from Points[i] to Points[0]
+          * Draw a line from Points[i] to Points[i+1]
+          */
+         From = Points[CurrentPoint];
+         if (Count <= CurrentPoint + 1)
+           {
+             To = Points[0];
+           }
+         else
+           {
+             To = Points[CurrentPoint + 1];
+           }
+
+         /* Special handling of lower right corner of a rectangle. If we
+          * don't treat it specially, it will end up looking like this:
+          *
+          *                *
+          *                *
+          *                *
+          *       *********
+          */
+         if (3 < Count)
+           {
+             if (Count <= CurrentPoint + 2)
                {
-                 To = Points[CurrentPoint];
-                 From = Points[0];
+                 Next = Points[CurrentPoint + 2 - Count];
                }
-               else
+             else
                {
-                 From = Points[CurrentPoint];
-                 To = Points[CurrentPoint + 1];
+                 Next = Points[CurrentPoint + 2];
                }
-               DPRINT("Polygon Making line from (%d,%d) to (%d,%d)\n", From.x, From.y, To.x, To.y );
-               ret = EngLineTo(SurfObj,
-                        NULL, // ClipObj,
-                        OutBrushObj,
-                        From.x + dc->w.DCOrgX, 
-                               From.y + dc->w.DCOrgY, 
-                                           To.x + dc->w.DCOrgX, 
-                                           To.y + dc->w.DCOrgY,
-                        RectBounds, // Bounding rectangle
-                        dc->w.ROPmode); // MIX
+             if (From.x == To.x &&
+                 From.y <= To.y &&
+                 To.y == Next.y &&
+                 Next.x <= To.x)
+               {
+                 To.y++;
+               }
+             else if (From.y == To.y &&
+                      From.x <= To.x &&
+                      To.x == Next.x &&
+                      Next.y <= To.y)
+               {
+                 To.x++;
+               }
+           }
+         DPRINT("Polygon Making line from (%d,%d) to (%d,%d)\n", From.x, From.y, To.x, To.y );
+         ret = IntEngLineTo(SurfObj,
+                            NULL, /* ClipObj */
+                            OutBrushObj,
+                            From.x, 
+                            From.y, 
+                            To.x, 
+                            To.y,
+                            &DestRect,
+                            dc->w.ROPmode); /* MIX */
                  
-         }//for
-      GDIOBJ_UnlockObj( dc->w.hBrush, GO_BRUSH_MAGIC );
-  }// else
+       }
+      GDIOBJ_UnlockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
+    }
   
   GDIOBJ_UnlockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC);
-  DC_ReleasePtr( hDC );
+  DC_ReleasePtr(hDC);
+  ExFreePool(Points);
+
   return ret;
 }
 
index 2874a11..4fbece0 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: polyfill.c,v 1.3 2003/05/18 17:16:18 ea Exp $
+/* $Id: polyfill.c,v 1.4 2003/06/25 16:55:33 gvg Exp $
  *
  * COPYRIGHT:         See COPYING in the top level directory
  * PROJECT:           ReactOS kernel
@@ -487,41 +487,41 @@ static void STDCALL POLYGONFILL_UpdateActiveEdges(int Scanline, PFILL_EDGE_LIST
 ** This method fills the portion of the polygon that intersects with the scanline
 ** Scanline.
 */
-static void STDCALL POLYGONFILL_FillScanLine(int ScanLine, PFILL_EDGE_LIST ActiveEdges, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, int OrigX, int OrigY)
+static void STDCALL POLYGONFILL_FillScanLine(int ScanLine, PFILL_EDGE_LIST ActiveEdges, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode)
 {
-    BOOL OnOdd = TRUE;
-    RECTL BoundRect;
-    int XInterceptOdd,XInterceptEven,ret;
-    PPFILL_EDGE pThis = ActiveEdges;
+  BOOL OnOdd = TRUE;
+  RECTL BoundRect;
+  int XInterceptOdd,XInterceptEven,ret;
+  PPFILL_EDGE pThis = ActiveEdges;
     
-    while (0 != pThis)
+  while (NULL != pThis)
     {
-        if (OnOdd)
-        {
-            XInterceptOdd = pThis->XIntercept;
-            OnOdd = FALSE;
-        }
-        else
-        {
-            BoundRect.top = ScanLine + OrigY - 1;
-            BoundRect.bottom = ScanLine + OrigY + 1;
-            BoundRect.left = XInterceptOdd + OrigX - 2;
-            BoundRect.right = XInterceptEven + OrigX;
-
-            XInterceptEven = pThis->XIntercept;
-            DPRINT("Fill Line (%d, %d) to (%d, %d)\n",XInterceptOdd - 1,ScanLine ,XInterceptEven - 1,ScanLine );
-            ret = EngLineTo(SurfObj,
-                                               NULL, // ClipObj,
-                                               BrushObj,
-                                               XInterceptOdd + OrigX - 1, 
-                                               ScanLine + OrigY
-                                               XInterceptEven + OrigX - 1, 
-                                               ScanLine + OrigY,
-                                               &BoundRect, // Bounding rectangle
-                                               RopMode); // MIX
-            OnOdd = TRUE;
-        }
-        pThis = pThis->pNext;
+      if (OnOdd)
+       {
+         XInterceptOdd = pThis->XIntercept;
+         OnOdd = FALSE;
+       }
+      else
+       {
+         BoundRect.top = ScanLine - 1;
+         BoundRect.bottom = ScanLine + 1;
+         BoundRect.left = XInterceptOdd - 2;
+         BoundRect.right = XInterceptEven;
+
+         XInterceptEven = pThis->XIntercept;
+         DPRINT("Fill Line (%d, %d) to (%d, %d)\n",XInterceptOdd - 1, ScanLine, XInterceptEven - 1, ScanLine);
+         ret = EngLineTo(SurfObj,
+                         NULL, /* ClipObj */
+                         BrushObj,
+                         XInterceptOdd - 1, 
+                         ScanLine
+                         XInterceptEven - 1, 
+                         ScanLine,
+                          &BoundRect, /* Bounding rectangle */
+                          RopMode); /* MIX */
+         OnOdd = TRUE;
+       }
+      pThis = pThis->pNext;
     }
 }
 
@@ -530,40 +530,46 @@ static void STDCALL POLYGONFILL_FillScanLine(int ScanLine, PFILL_EDGE_LIST Activ
 //When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and 
 //even-numbered polygon sides on each scan line. That is, GDI fills the area between the 
 //first and second side, between the third and fourth side, and so on. 
-BOOL STDCALL FillPolygon_ALTERNATE(SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect, int OrigX, int OrigY)
+BOOL STDCALL FillPolygon_ALTERNATE(SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect)
 {
-       PFILL_EDGE_LIST list = 0;
-    PFILL_EDGE_LIST ActiveEdges = 0;
-    int ScanLine;
-       DPRINT("FillPolygon_ALTERNATE\n");
+  PFILL_EDGE_LIST list = 0;
+  PFILL_EDGE_LIST ActiveEdges = 0;
+  int ScanLine;
+
+  DPRINT("FillPolygon_ALTERNATE\n");
        
-       //Create Edge List.
-       list = POLYGONFILL_MakeEdgeList(Points, Count);
-       //DEBUG_PRINT_EDGELIST(list);
-    if (0 == list) return FALSE;
-
-       //For each Scanline from BoundRect.bottom to BoundRect.top, 
-       //determine line segments to draw
-       for (ScanLine = BoundRect.top + 1; ScanLine < BoundRect.bottom ; ++ScanLine)
-       {
-        POLYGONFILL_UpdateActiveEdges(ScanLine, &list, &ActiveEdges);
-        //DEBUG_PRINT_EDGELIST(ActiveEdges);
-        POLYGONFILL_FillScanLine(ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode, OrigX, OrigY);
-       }
+  /* Create Edge List. */
+  list = POLYGONFILL_MakeEdgeList(Points, Count);
+  /* DEBUG_PRINT_EDGELIST(list); */
+  if (NULL == list)
+    {
+      return FALSE;
+    }
+
+  /* For each Scanline from BoundRect.bottom to BoundRect.top, 
+   * determine line segments to draw
+   */
+  for (ScanLine = BoundRect.top + 1; ScanLine < BoundRect.bottom ; ++ScanLine)
+    {
+      POLYGONFILL_UpdateActiveEdges(ScanLine, &list, &ActiveEdges);
+      /* DEBUG_PRINT_EDGELIST(ActiveEdges); */
+      POLYGONFILL_FillScanLine(ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode);
+    }
     
-       //Free Edge List. If any are left.
-       POLYGONFILL_DestroyEdgeList(list);
+  /* Free Edge List. If any are left. */
+  POLYGONFILL_DestroyEdgeList(list);
 
-       return TRUE;
+  return TRUE;
 }
 
 //WINDING Selects winding mode (fills any region with a nonzero winding value). 
 //When the fill mode is WINDING, GDI fills any region that has a nonzero winding value. 
 //This value is defined as the number of times a pen used to draw the polygon would go around the region. 
 //The direction of each edge of the polygon is important. 
-BOOL STDCALL FillPolygon_WINDING(SURFOBJ *SurfObj, PBRUSHOBJ BrushObj,MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect, int OrigX, int OrigY)
+BOOL STDCALL FillPolygon_WINDING(SURFOBJ *SurfObj, PBRUSHOBJ BrushObj,MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect)
 {
-       DPRINT("FillPolygon_WINDING\n");
-       return FALSE;
+  DPRINT("FillPolygon_WINDING\n");
+
+  return FALSE;
 }
 /* EOF */