[ros-diffs] [jimtabor] 44775: [gdi32] - Add notes, fix CombineRgn and cleanup.

jimtabor at svn.reactos.org jimtabor at svn.reactos.org
Sun Dec 27 20:43:47 CET 2009


Author: jimtabor
Date: Sun Dec 27 20:43:46 2009
New Revision: 44775

URL: http://svn.reactos.org/svn/reactos?rev=44775&view=rev
Log:
[gdi32]
- Add notes, fix CombineRgn and cleanup.

Modified:
    trunk/reactos/dll/win32/gdi32/objects/region.c

Modified: trunk/reactos/dll/win32/gdi32/objects/region.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdi32/objects/region.c?rev=44775&r1=44774&r2=44775&view=diff
==============================================================================
--- trunk/reactos/dll/win32/gdi32/objects/region.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/gdi32/objects/region.c [iso-8859-1] Sun Dec 27 20:43:46 2009
@@ -1,4 +1,7 @@
 #include "precomp.h"
+
+#define NDEBUG
+#include <debug.h>
 
 #define INRECT(r, x, y) \
       ( ( ((r).right >  x)) && \
@@ -6,17 +9,30 @@
       ( ((r).bottom >  y)) && \
       ( ((r).top <= y)) )
 
+#define OVERLAPPING_RGN 0
+#define INVERTED_RGN 1
+#define SAME_RGN 2
+#define DIFF_RGN 3
+/*
+ From tests, there are four results based on normalized coordinates.
+ If the rects are overlapping and normalized, it's OVERLAPPING_RGN.
+ If the rects are overlapping in anyway or same in dimension and one is inverted,
+ it's INVERTED_RGN.
+ If the rects are same in dimension or NULL, it's SAME_RGN.
+ If the rects are overlapping and not normalized or displace in different areas,
+ it's DIFF_RGN.
+ */
 static
 INT
 FASTCALL
-ComplexityFromRects( PRECT prc1, PRECT prc2)
+ComplexityFromRects( PRECTL prc1, PRECTL prc2)
 {
   if ( prc2->left >= prc1->left )
   {
      if ( ( prc1->right >= prc2->right) &&
           ( prc1->top <= prc2->top ) &&
-          ( prc1->bottom <= prc2->bottom ) )      
-        return SIMPLEREGION;
+          ( prc1->bottom >= prc2->bottom ) )      
+        return SAME_RGN;
 
      if ( prc2->left > prc1->left )
      {
@@ -24,7 +40,7 @@
              ( prc1->right <= prc2->left ) ||
              ( prc1->top >= prc2->bottom ) ||
              ( prc1->bottom <= prc2->top ) )
-           return COMPLEXREGION;
+           return DIFF_RGN;
      }
   }
 
@@ -36,14 +52,13 @@
           ( prc1->right <= prc2->left ) ||
           ( prc1->top >= prc2->bottom ) ||
           ( prc1->bottom <= prc2->top ) )
-        return COMPLEXREGION;
+        return DIFF_RGN;
   }
   else
   {
-    return NULLREGION;
-  }
-
-  return ERROR;
+     return INVERTED_RGN;
+  }
+  return OVERLAPPING_RGN;
 }
 
 static
@@ -181,7 +196,7 @@
 /* FUNCTIONS *****************************************************************/
 
 /*
- * @unimplemented
+ * @implemented
  */
 INT
 WINAPI
@@ -190,8 +205,203 @@
            HRGN  hSrc2,
            INT  CombineMode)
 {
-    /* FIXME some part should be done in user mode */
-    return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
+  PRGN_ATTR pRgn_Attr_Dest = NULL;
+  PRGN_ATTR pRgn_Attr_Src1 = NULL;
+  PRGN_ATTR pRgn_Attr_Src2 = NULL;
+  INT Complexity;
+  BOOL Ret;
+
+  Ret = GdiGetHandleUserData((HGDIOBJ) hDest, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr_Dest);
+  Ret = GdiGetHandleUserData((HGDIOBJ) hSrc1, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr_Src1);
+
+  if ( !Ret ||
+       !pRgn_Attr_Dest ||
+       !pRgn_Attr_Src1 ||
+        pRgn_Attr_Src1->Flags > SIMPLEREGION )
+     return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
+
+  /* Handle COPY and use only src1. */
+  if ( CombineMode == RGN_COPY )
+  {
+     switch (pRgn_Attr_Src1->Flags)
+     {
+        case NULLREGION:
+             Ret = SetRectRgn( hDest, 0, 0, 0, 0);
+             if (Ret)
+                return NULLREGION;
+             goto ERROR_Exit;
+
+        case SIMPLEREGION:
+             Ret = SetRectRgn( hDest,
+                               pRgn_Attr_Src1->Rect.left,
+                               pRgn_Attr_Src1->Rect.top,
+                               pRgn_Attr_Src1->Rect.right,
+                               pRgn_Attr_Src1->Rect.bottom );
+             if (Ret)
+                return SIMPLEREGION;
+             goto ERROR_Exit;
+
+        case COMPLEXREGION:
+        default:
+            return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
+     }
+  }
+
+  Ret = GdiGetHandleUserData((HGDIOBJ) hSrc2, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr_Src2);
+  if ( !Ret ||
+       !pRgn_Attr_Src2 ||
+        pRgn_Attr_Src2->Flags > SIMPLEREGION )
+     return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
+
+  /* All but AND. */
+  if ( CombineMode != RGN_AND)
+  {
+     if ( CombineMode <= RGN_AND)
+     {
+        /*
+           There might be some type of junk in the call, so go K.
+           If this becomes a problem, need to setup parameter check at the top.
+         */
+        DPRINT1("Might be junk! CombineMode %d\n",CombineMode);
+        return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
+     }
+
+     if ( CombineMode > RGN_XOR) /* Handle DIFF. */
+     {
+        if ( CombineMode != RGN_DIFF)
+        {  /* Filter check! Well, must be junk?, so go K. */
+           DPRINT1("RGN_COPY was handled! CombineMode %d\n",CombineMode);
+           return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
+        }
+
+        if ( pRgn_Attr_Src1->Flags != NULLREGION &&
+             pRgn_Attr_Src2->Flags != NULLREGION )
+        {
+           Complexity = ComplexityFromRects( &pRgn_Attr_Src1->Rect, &pRgn_Attr_Src2->Rect);
+           /* If same or overlapping and norm just go K. */
+           if (Complexity == SAME_RGN || Complexity == OVERLAPPING_RGN)
+              return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
+        }
+        /* Just NULL rgn. */
+        if (SetRectRgn( hDest, 0, 0, 0, 0))
+           return NULLREGION;
+        goto ERROR_Exit;
+     }
+     else /* Handle OR or XOR. */
+     {
+        if ( pRgn_Attr_Src1->Flags == NULLREGION )
+        {
+           if ( pRgn_Attr_Src2->Flags != NULLREGION )
+           { /* Src1 null and not NULL, set from src2. */
+              Ret = SetRectRgn( hDest,
+                                pRgn_Attr_Src2->Rect.left,
+                                pRgn_Attr_Src2->Rect.top,
+                                pRgn_Attr_Src2->Rect.right,
+                                pRgn_Attr_Src2->Rect.bottom );
+              if (Ret)
+                 return SIMPLEREGION;
+              goto ERROR_Exit;
+           }
+           /* Both are NULL. */
+           if (SetRectRgn( hDest, 0, 0, 0, 0))
+              return NULLREGION;
+           goto ERROR_Exit;          
+        }
+        /* Src1 is not NULL. */
+        if ( pRgn_Attr_Src2->Flags != NULLREGION )
+        {
+           if ( CombineMode != RGN_OR ) /* Filter XOR, so go K. */
+              return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
+
+           Complexity = ComplexityFromRects( &pRgn_Attr_Src1->Rect, &pRgn_Attr_Src2->Rect);
+           /* If inverted use Src2. */
+           if ( Complexity == INVERTED_RGN)
+           {
+              Ret = SetRectRgn( hDest,
+                                pRgn_Attr_Src2->Rect.left,
+                                pRgn_Attr_Src2->Rect.top,
+                                pRgn_Attr_Src2->Rect.right,
+                                pRgn_Attr_Src2->Rect.bottom );
+              if (Ret)
+                 return SIMPLEREGION;
+              goto ERROR_Exit;
+           }
+           /* Not NULL or overlapping or differentiated, go to K. */
+           if ( Complexity != SAME_RGN)
+              return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
+           /* If same, just fall through. */
+        }
+     }
+     Ret = SetRectRgn( hDest,
+                       pRgn_Attr_Src1->Rect.left,
+                       pRgn_Attr_Src1->Rect.top,
+                       pRgn_Attr_Src1->Rect.right,
+                       pRgn_Attr_Src1->Rect.bottom );
+     if (Ret)
+        return SIMPLEREGION;
+     goto ERROR_Exit;
+  }
+
+  /* Handle AND.  */
+  if ( pRgn_Attr_Src1->Flags != NULLREGION &&
+       pRgn_Attr_Src2->Flags != NULLREGION )
+  {
+     Complexity = ComplexityFromRects( &pRgn_Attr_Src1->Rect, &pRgn_Attr_Src2->Rect);
+
+     if ( Complexity == DIFF_RGN ) /* Differentiated in anyway just NULL rgn. */
+     {
+        if (SetRectRgn( hDest, 0, 0, 0, 0))
+           return NULLREGION;
+        goto ERROR_Exit;
+     }
+
+     if ( Complexity != INVERTED_RGN) /* Not inverted and overlapping. */
+     {
+        if ( Complexity != SAME_RGN) /* Must be norm and overlapping. */
+           return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
+        /* Merge from src2.  */
+        Ret = SetRectRgn( hDest,
+                          pRgn_Attr_Src2->Rect.left,
+                          pRgn_Attr_Src2->Rect.top,
+                          pRgn_Attr_Src2->Rect.right,
+                          pRgn_Attr_Src2->Rect.bottom );
+        if (Ret)
+           return SIMPLEREGION;
+        goto ERROR_Exit;
+     }
+     /* Inverted so merge from src1. */
+     Ret = SetRectRgn( hDest,
+                       pRgn_Attr_Src1->Rect.left,
+                       pRgn_Attr_Src1->Rect.top,
+                       pRgn_Attr_Src1->Rect.right,
+                       pRgn_Attr_Src1->Rect.bottom );
+     if (Ret)
+        return SIMPLEREGION;
+     goto ERROR_Exit;
+  }
+
+  /* It's all NULL! */
+  if (SetRectRgn( hDest, 0, 0, 0, 0))
+     return NULLREGION;
+
+ERROR_Exit:
+  /* Even on error the flag is set dirty and force server side to redraw. */
+  pRgn_Attr_Dest->AttrFlags |= ATTR_RGN_DIRTY;
+  return ERROR;
+}
+
+/*
+ * @implemented
+ */
+HRGN
+WINAPI
+CreateEllipticRgnIndirect(
+   const RECT *prc
+)
+{
+    /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
+    return NtGdiCreateEllipticRgn(prc->left, prc->top, prc->right, prc->bottom);
+
 }
 
 /*
@@ -215,20 +425,6 @@
                       int fnPolyFillMode)
 {
     return (HRGN) NtGdiPolyPolyDraw(  (HDC) fnPolyFillMode, (PPOINT) lppt, (PULONG) lpPolyCounts, (ULONG) nCount, GdiPolyPolyRgn );
-}
-
-/*
- * @implemented
- */
-HRGN
-WINAPI
-CreateEllipticRgnIndirect(
-   const RECT *prc
-)
-{
-    /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
-    return NtGdiCreateEllipticRgn(prc->left, prc->top, prc->right, prc->bottom);
-
 }
 
 /*
@@ -585,14 +781,12 @@
         {
            return ERROR;
         }
-        else
-        {
-           pRgn_Attr->Rect.top    = nTopRect;
-           pRgn_Attr->Rect.left   = nLeftRect;
-           pRgn_Attr->Rect.right  = nRightRect;
-           pRgn_Attr->Rect.bottom = nBottomRect;
-           pRgn_Attr->AttrFlags |= ATTR_RGN_DIRTY;
-        }
+
+        pRgn_Attr->Rect.top    = nTopRect;
+        pRgn_Attr->Rect.left   = nLeftRect;
+        pRgn_Attr->Rect.right  = nRightRect;
+        pRgn_Attr->Rect.bottom = nBottomRect;
+        pRgn_Attr->AttrFlags |= ATTR_RGN_DIRTY;
      }
   }
   return pRgn_Attr->Flags;
@@ -630,7 +824,7 @@
              LPCRECT prcl)
 {
   PRGN_ATTR pRgn_Attr;
-  RECT rc;
+  RECTL rc;
 
   if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
      return NtGdiRectInRegion(hrgn, (LPRECT) prcl);
@@ -643,31 +837,31 @@
 
  /* swap the coordinates to make right >= left and bottom >= top */
  /* (region building rectangles are normalized the same way) */
-   if ( prcl->top > prcl->bottom)
-   {
-      rc.top = prcl->bottom;
-      rc.bottom = prcl->top;
-   }
-   else
-   {
-     rc.top = prcl->top;
-     rc.bottom = prcl->bottom;
-   }
-   if ( prcl->right < prcl->left)
-   {
-      rc.right = prcl->left;
-      rc.left = prcl->right;
-   }
-   else
-   {
-      rc.right = prcl->right;
-      rc.left = prcl->left;
-   }
-
-   if ( ComplexityFromRects( (PRECT)&pRgn_Attr->Rect, &rc) != COMPLEXREGION )
-      return TRUE;
-
-   return FALSE;
+  if ( prcl->top > prcl->bottom)
+  {
+     rc.top = prcl->bottom;
+     rc.bottom = prcl->top;
+  }
+  else
+  {
+    rc.top = prcl->top;
+    rc.bottom = prcl->bottom;
+  }
+  if ( prcl->right < prcl->left)
+  {
+     rc.right = prcl->left;
+     rc.left = prcl->right;
+  }
+  else
+  {
+     rc.right = prcl->right;
+     rc.left = prcl->left;
+  }
+
+  if ( ComplexityFromRects( &pRgn_Attr->Rect, &rc) != DIFF_RGN )
+     return TRUE;
+
+  return FALSE;
 }
 
 /*
@@ -752,4 +946,3 @@
  return ERROR;
 }
 
-




More information about the Ros-diffs mailing list