Alexandre Julliard : gdi32: Add support for clipping source coordinates to the DC device rectangle.

Alexandre Julliard julliard at winehq.org
Tue May 1 13:12:13 CDT 2012


Module: wine
Branch: master
Commit: 41e5bc06d8928d6d9b56b8910164683cf66b4cd8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=41e5bc06d8928d6d9b56b8910164683cf66b4cd8

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Apr 30 21:17:00 2012 +0200

gdi32: Add support for clipping source coordinates to the DC device rectangle.

---

 dlls/gdi32/bitblt.c      |   14 +++--------
 dlls/gdi32/bitmap.c      |    1 +
 dlls/gdi32/clipping.c    |   55 +++++++++++++++++++++++++++------------------
 dlls/gdi32/dc.c          |    1 +
 dlls/gdi32/dib.c         |    1 +
 dlls/gdi32/gdi_private.h |    2 +
 6 files changed, 42 insertions(+), 32 deletions(-)

diff --git a/dlls/gdi32/bitblt.c b/dlls/gdi32/bitblt.c
index a97231c..6b99e43 100644
--- a/dlls/gdi32/bitblt.c
+++ b/dlls/gdi32/bitblt.c
@@ -146,13 +146,7 @@ static BOOL get_vis_rectangles( DC *dc_dst, struct bitblt_coords *dst,
     }
     get_bounding_rect( &rect, src->x, src->y, src->width, src->height );
 
-    /* source is not clipped */
-    if (dc_src->header.type == OBJ_MEMDC)
-        intersect_rect( &src->visrect, &rect, &dc_src->vis_rect );
-    else
-        src->visrect = rect;  /* FIXME: clip to device size */
-
-    if (is_rect_empty( &src->visrect )) return FALSE;
+    if (!clip_device_rect( dc_src, &src->visrect, &rect )) return FALSE;
     if (is_rect_empty( &dst->visrect )) return FALSE;
 
     return intersect_vis_rectangles( dst, src );
@@ -932,9 +926,9 @@ BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heig
 
         if (src.x < 0 || src.y < 0 || src.width < 0 || src.height < 0 ||
             src.log_width < 0 || src.log_height < 0 ||
-            (dcSrc->header.type == OBJ_MEMDC &&
-             (src.width > dcSrc->vis_rect.right - dcSrc->vis_rect.left - src.x ||
-              src.height > dcSrc->vis_rect.bottom - dcSrc->vis_rect.top - src.y)))
+            (!is_rect_empty( &dcSrc->device_rect ) &&
+             (src.width > dcSrc->device_rect.right - dcSrc->vis_rect.left - src.x ||
+              src.height > dcSrc->device_rect.bottom - dcSrc->vis_rect.top - src.y)))
         {
             WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src.x, src.y, src.width, src.height );
             SetLastError( ERROR_INVALID_PARAMETER );
diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c
index cee9204..68e9c9a 100644
--- a/dlls/gdi32/bitmap.c
+++ b/dlls/gdi32/bitmap.c
@@ -609,6 +609,7 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
         dc->vis_rect.top    = 0;
         dc->vis_rect.right  = bitmap->dib.dsBm.bmWidth;
         dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight;
+        dc->device_rect = dc->vis_rect;
         GDI_ReleaseObj( handle );
         DC_InitDC( dc );
         GDI_dec_ref_count( ret );
diff --git a/dlls/gdi32/clipping.c b/dlls/gdi32/clipping.c
index c413e1a..1cb420c 100644
--- a/dlls/gdi32/clipping.c
+++ b/dlls/gdi32/clipping.c
@@ -29,15 +29,12 @@
 WINE_DEFAULT_DEBUG_CHANNEL(clipping);
 
 
-/* return the DC visible rectangle if not empty */
-static inline BOOL get_dc_visrect( DC *dc, RECT *rect )
+/* return the DC device rectangle if not empty */
+static inline BOOL get_dc_device_rect( DC *dc, RECT *rect )
 {
-    if (dc->header.type != OBJ_MEMDC) return FALSE;
-    rect->left = 0;
-    rect->top = 0;
-    rect->right = dc->vis_rect.right - dc->vis_rect.left;
-    rect->bottom = dc->vis_rect.bottom - dc->vis_rect.top;
-    return TRUE;
+    *rect = dc->device_rect;
+    offset_rect( rect, -dc->vis_rect.left, -dc->vis_rect.top );
+    return !is_rect_empty( rect );
 }
 
 /***********************************************************************
@@ -64,6 +61,20 @@ static inline RECT get_clip_rect( DC * dc, int left, int top, int right, int bot
 }
 
 /***********************************************************************
+ *           clip_device_rect
+ *
+ * Clip a rectangle to the whole DC surface.
+ */
+BOOL clip_device_rect( DC *dc, RECT *dst, const RECT *src )
+{
+    RECT clip;
+
+    if (get_dc_device_rect( dc, &clip )) return intersect_rect( dst, src, &clip );
+    *dst = *src;
+    return TRUE;
+}
+
+/***********************************************************************
  *           clip_visrect
  *
  * Clip a rectangle to the DC visible rect.
@@ -72,11 +83,9 @@ BOOL clip_visrect( DC *dc, RECT *dst, const RECT *src )
 {
     RECT clip;
 
-    if (get_dc_visrect( dc, &clip )) intersect_rect( dst, src, &clip );
-    else *dst = *src;
-
-    if (GetRgnBox( get_dc_region(dc), &clip )) intersect_rect( dst, dst, &clip );
-    return !is_rect_empty( dst );
+    if (!clip_device_rect( dc, dst, src )) return FALSE;
+    if (GetRgnBox( get_dc_region(dc), &clip )) return intersect_rect( dst, dst, &clip );
+    return TRUE;
 }
 
 /***********************************************************************
@@ -117,7 +126,7 @@ static inline void create_default_clip_region( DC * dc )
 {
     RECT rect;
 
-    if (!get_dc_visrect( dc, &rect ))
+    if (!get_dc_device_rect( dc, &rect ))
     {
         rect.left = 0;
         rect.top = 0;
@@ -361,7 +370,7 @@ BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
     pt.y = y;
     LPtoDP( hdc, &pt, 1 );
     update_dc( dc );
-    ret = (!get_dc_visrect( dc, &visrect ) ||
+    ret = (!get_dc_device_rect( dc, &visrect ) ||
            (pt.x >= visrect.left && pt.x < visrect.right &&
             pt.y >= visrect.top && pt.y < visrect.bottom));
     if (ret && get_dc_region( dc )) ret = PtInRegion( get_dc_region( dc ), pt.x, pt.y );
@@ -385,7 +394,7 @@ BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
     LPtoDP( hdc, (POINT *)&tmpRect, 2 );
 
     update_dc( dc );
-    ret = (!get_dc_visrect( dc, &visrect ) || intersect_rect( &visrect, &visrect, &tmpRect ));
+    ret = (!get_dc_device_rect( dc, &visrect ) || intersect_rect( &visrect, &visrect, &tmpRect ));
     if (ret && get_dc_region( dc )) ret = RectInRegion( get_dc_region( dc ), &tmpRect );
     release_dc_ptr( dc );
     return ret;
@@ -406,7 +415,7 @@ INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
     if (get_dc_region( dc ))
     {
         ret = GetRgnBox( get_dc_region( dc ), rect );
-        if (get_dc_visrect( dc, &visrect ) && !intersect_rect( rect, rect, &visrect ))
+        if (get_dc_device_rect( dc, &visrect ) && !intersect_rect( rect, rect, &visrect ))
             ret = NULLREGION;
     }
     else
@@ -492,7 +501,6 @@ INT WINAPI GetMetaRgn( HDC hdc, HRGN hRgn )
 INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode)
 {
     INT ret = 1;
-    RECT visrect;
     DC *dc = get_dc_ptr( hDC );
 
     if (!dc) return -1;
@@ -516,13 +524,16 @@ INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode)
     case SYSRGN: /* == 4 */
         update_dc( dc );
         if (dc->hVisRgn)
+        {
             CombineRgn( hRgn, dc->hVisRgn, 0, RGN_COPY );
-        else if (get_dc_visrect( dc, &visrect ))
-            SetRectRgn( hRgn, visrect.left, visrect.top, visrect.right, visrect.bottom );
+            /* On Windows NT/2000, the SYSRGN returned is in screen coordinates */
+            if (!(GetVersion() & 0x80000000)) OffsetRgn( hRgn, dc->vis_rect.left, dc->vis_rect.top );
+        }
+        else if (!is_rect_empty( &dc->device_rect ))
+            SetRectRgn( hRgn, dc->device_rect.left, dc->device_rect.top,
+                        dc->device_rect.right, dc->device_rect.bottom );
         else
             ret = 0;
-        /* On Windows NT/2000, the SYSRGN returned is in screen coordinates */
-        if (ret && !(GetVersion() & 0x80000000)) OffsetRgn( hRgn, dc->vis_rect.left, dc->vis_rect.top );
         break;
     default:
         WARN("Unknown code %d\n", iCode);
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c
index 33c1033..95dd3e2 100644
--- a/dlls/gdi32/dc.c
+++ b/dlls/gdi32/dc.c
@@ -698,6 +698,7 @@ HDC WINAPI CreateCompatibleDC( HDC hdc )
     dc->vis_rect.top    = 0;
     dc->vis_rect.right  = 1;
     dc->vis_rect.bottom = 1;
+    dc->device_rect = dc->vis_rect;
 
     ret = dc->hSelf;
 
diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c
index d8d283e..f7e08a5 100644
--- a/dlls/gdi32/dib.c
+++ b/dlls/gdi32/dib.c
@@ -1624,6 +1624,7 @@ static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc )
         dc->vis_rect.top    = 0;
         dc->vis_rect.right  = bitmap->dib.dsBm.bmWidth;
         dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight;
+        dc->device_rect = dc->vis_rect;
         GDI_ReleaseObj( handle );
         DC_InitDC( dc );
         GDI_dec_ref_count( ret );
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 20b522d..2589238 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -104,6 +104,7 @@ typedef struct tagDC
     SIZE         virtual_res;      /* Initially HORZRES,VERTRES. Changed by SetVirtualResolution */
     SIZE         virtual_size;     /* Initially HORZSIZE,VERTSIZE. Changed by SetVirtualResolution */
     RECT         vis_rect;         /* visible rectangle in screen coords */
+    RECT         device_rect;      /* rectangle for the whole device */
     FLOAT        miterLimit;
 
     int           flags;
@@ -217,6 +218,7 @@ extern void free_brush_pattern( struct brush_pattern *pattern ) DECLSPEC_HIDDEN;
 extern BOOL get_brush_bitmap_info( HBRUSH handle, BITMAPINFO *info, void **bits, UINT *usage ) DECLSPEC_HIDDEN;
 
 /* clipping.c */
+extern BOOL clip_device_rect( DC *dc, RECT *dst, const RECT *src ) DECLSPEC_HIDDEN;
 extern BOOL clip_visrect( DC *dc, RECT *dst, const RECT *src ) DECLSPEC_HIDDEN;
 extern void update_dc_clipping( DC * dc ) DECLSPEC_HIDDEN;
 




More information about the wine-cvs mailing list