Alexandre Julliard : gdi32: Add a helper function to compute the list of rectangles to paint after clipping .

Alexandre Julliard julliard at winehq.org
Tue Dec 27 11:27:55 CST 2011


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Dec 27 14:31:11 2011 +0100

gdi32: Add a helper function to compute the list of rectangles to paint after clipping.

---

 dlls/gdi32/dibdrv/bitblt.c   |   49 +++++++++++------------------------------
 dlls/gdi32/dibdrv/dc.c       |   43 ++++++++++++++++++++++++++++++++++++-
 dlls/gdi32/dibdrv/dibdrv.h   |   19 ++++++++++++++++
 dlls/gdi32/dibdrv/graphics.c |   27 +++++++---------------
 dlls/gdi32/gdi_private.h     |    6 -----
 5 files changed, 83 insertions(+), 61 deletions(-)

diff --git a/dlls/gdi32/dibdrv/bitblt.c b/dlls/gdi32/dibdrv/bitblt.c
index ad329be..b862ebb 100644
--- a/dlls/gdi32/dibdrv/bitblt.c
+++ b/dlls/gdi32/dibdrv/bitblt.c
@@ -576,28 +576,17 @@ static DWORD blend_rect( dib_info *dst, const RECT *dst_rect, const dib_info *sr
                          HRGN clip, BLENDFUNCTION blend )
 {
     POINT origin;
-    RECT clipped_rect;
-    const WINEREGION *clip_data;
+    struct clipped_rects clipped_rects;
     int i;
 
-    origin.x = src_rect->left;
-    origin.y = src_rect->top;
-
-    if (clip == NULL) dst->funcs->blend_rect( dst, dst_rect, src, &origin, blend );
-    else
+    if (!get_clipped_rects( dst, dst_rect, clip, &clipped_rects )) return ERROR_SUCCESS;
+    for (i = 0; i < clipped_rects.count; i++)
     {
-        clip_data = get_wine_region( clip );
-        for (i = 0; i < clip_data->numRects; i++)
-        {
-            if (intersect_rect( &clipped_rect, dst_rect, clip_data->rects + i ))
-            {
-                origin.x = src_rect->left + clipped_rect.left - dst_rect->left;
-                origin.y = src_rect->top  + clipped_rect.top  - dst_rect->top;
-                dst->funcs->blend_rect( dst, &clipped_rect, src, &origin, blend );
-            }
-        }
-        release_wine_region( clip );
+        origin.x = src_rect->left + clipped_rects.rects[i].left - dst_rect->left;
+        origin.y = src_rect->top  + clipped_rects.rects[i].top  - dst_rect->top;
+        dst->funcs->blend_rect( dst, &clipped_rects.rects[i], src, &origin, blend );
     }
+    free_clipped_rects( &clipped_rects );
     return ERROR_SUCCESS;
 }
 
@@ -679,7 +668,8 @@ static void get_gradient_triangle_vertices( const GRADIENT_TRIANGLE *tri, const
 static BOOL gradient_rect( dib_info *dib, TRIVERTEX *v, int mode, HRGN clip )
 {
     int i;
-    RECT rect, clipped_rect;
+    struct clipped_rects clipped_rects;
+    RECT rect;
     BOOL ret = TRUE;
 
     if (mode == GRADIENT_FILL_TRIANGLE)
@@ -696,26 +686,13 @@ static BOOL gradient_rect( dib_info *dib, TRIVERTEX *v, int mode, HRGN clip )
         rect.right  = v[1].x;
         rect.bottom = v[1].y;
     }
-    rect.left   = max( rect.left, 0 );
-    rect.top    = max( rect.top, 0 );
-    rect.right  = min( rect.right, dib->width );
-    rect.bottom = min( rect.bottom, dib->height );
 
-    if (clip)
+    if (!get_clipped_rects( dib, &rect, clip, &clipped_rects )) return TRUE;
+    for (i = 0; i < clipped_rects.count; i++)
     {
-        const WINEREGION *clip_data = get_wine_region( clip );
-
-        for (i = 0; i < clip_data->numRects; i++)
-        {
-            if (intersect_rect( &clipped_rect, &rect, clip_data->rects + i ))
-            {
-                if (!(ret = dib->funcs->gradient_rect( dib, &clipped_rect, v, mode ))) break;
-            }
-        }
-        release_wine_region( clip );
+        if (!(ret = dib->funcs->gradient_rect( dib, &clipped_rects.rects[i], v, mode ))) break;
     }
-    else if (!is_rect_empty( &rect )) ret = dib->funcs->gradient_rect( dib, &rect, v, mode );
-
+    free_clipped_rects( &clipped_rects );
     return ret;
 }
 
diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c
index cdcbd19..404ead2 100644
--- a/dlls/gdi32/dibdrv/dc.c
+++ b/dlls/gdi32/dibdrv/dc.c
@@ -257,7 +257,48 @@ DWORD convert_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bit
     return ERROR_SUCCESS;
 }
 
- /***********************************************************************
+int get_clipped_rects( const dib_info *dib, const RECT *rc, HRGN clip, struct clipped_rects *clip_rects )
+{
+    const WINEREGION *region;
+    RECT rect, *out = clip_rects->buffer;
+    int i;
+
+    init_clipped_rects( clip_rects );
+
+    rect.left   = 0;
+    rect.top    = 0;
+    rect.right  = dib->width;
+    rect.bottom = dib->height;
+    if (rc && !intersect_rect( &rect, &rect, rc )) return 0;
+
+    if (!clip)
+    {
+        *out = rect;
+        clip_rects->count = 1;
+        return 1;
+    }
+
+    if (!(region = get_wine_region( clip ))) return 0;
+
+    for (i = 0; i < region->numRects; i++)
+    {
+        if (region->rects[i].top >= rect.bottom) break;
+        if (!intersect_rect( out, &rect, &region->rects[i] )) continue;
+        out++;
+        if (out == &clip_rects->buffer[sizeof(clip_rects->buffer) / sizeof(RECT)])
+        {
+            clip_rects->rects = HeapAlloc( GetProcessHeap(), 0, region->numRects * sizeof(RECT) );
+            if (!clip_rects->rects) return 0;
+            memcpy( clip_rects->rects, clip_rects->buffer, (out - clip_rects->buffer) * sizeof(RECT) );
+            out = clip_rects->rects + (out - clip_rects->buffer);
+        }
+    }
+    release_wine_region( clip );
+    clip_rects->count = out - clip_rects->rects;
+    return clip_rects->count;
+}
+
+/***********************************************************************
  *           add_extra_clipping_region
  *
  * Temporarily add a region to the current clipping region.
diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h
index e8acfa0..c0cbc5b 100644
--- a/dlls/gdi32/dibdrv/dibdrv.h
+++ b/dlls/gdi32/dibdrv/dibdrv.h
@@ -212,6 +212,13 @@ typedef struct
     DWORD octant;
 } bres_params;
 
+struct clipped_rects
+{
+    RECT *rects;
+    int   count;
+    RECT  buffer[32];
+};
+
 extern void get_rop_codes(INT rop, struct rop_codes *codes) DECLSPEC_HIDDEN;
 extern void update_brush_rop( dibdrv_physdev *pdev, INT rop ) DECLSPEC_HIDDEN;
 extern void reset_dash_origin(dibdrv_physdev *pdev) DECLSPEC_HIDDEN;
@@ -225,11 +232,23 @@ extern COLORREF make_rgb_colorref( HDC hdc, dib_info *dib, COLORREF color, BOOL
 extern DWORD get_pixel_color(dibdrv_physdev *pdev, COLORREF color, BOOL mono_fixup) DECLSPEC_HIDDEN;
 extern BOOL brush_rects( dibdrv_physdev *pdev, int num, const RECT *rects ) DECLSPEC_HIDDEN;
 extern void solid_rects( dib_info *dib, int num, const RECT *rects, const rop_mask *color, HRGN region ) DECLSPEC_HIDDEN;
+extern int get_clipped_rects( const dib_info *dib, const RECT *rc, HRGN clip, struct clipped_rects *clip_rects ) DECLSPEC_HIDDEN;
 extern HRGN add_extra_clipping_region( dibdrv_physdev *pdev, HRGN rgn ) DECLSPEC_HIDDEN;
 extern void restore_clipping_region( dibdrv_physdev *pdev, HRGN rgn ) DECLSPEC_HIDDEN;
 extern int clip_line(const POINT *start, const POINT *end, const RECT *clip,
                      const bres_params *params, POINT *pt1, POINT *pt2) DECLSPEC_HIDDEN;
 
+static inline void init_clipped_rects( struct clipped_rects *clip_rects )
+{
+    clip_rects->count = 0;
+    clip_rects->rects = clip_rects->buffer;
+}
+
+static inline void free_clipped_rects( struct clipped_rects *clip_rects )
+{
+    if (clip_rects->rects != clip_rects->buffer) HeapFree( GetProcessHeap(), 0, clip_rects->rects );
+}
+
 /* compute the x coordinate corresponding to y on the specified edge */
 static inline int edge_coord( int y, int x1, int y1, int x2, int y2 )
 {
diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c
index ad6c4ad..d9b305d 100644
--- a/dlls/gdi32/dibdrv/graphics.c
+++ b/dlls/gdi32/dibdrv/graphics.c
@@ -606,36 +606,27 @@ BOOL dibdrv_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
 COLORREF dibdrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
 {
     dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
-    int i;
+    struct clipped_rects clipped_rects;
+    RECT rect;
     POINT pt;
     DWORD pixel;
-    const WINEREGION *clip = get_wine_region( pdev->clip );
 
     TRACE( "(%p, %d, %d, %08x)\n", dev, x, y, color );
 
     pt.x = x;
     pt.y = y;
     LPtoDP( dev->hdc, &pt, 1 );
+    rect.left = pt.x;
+    rect.top =  pt.y;
+    rect.right = rect.left + 1;
+    rect.bottom = rect.top + 1;
 
     /* SetPixel doesn't do the 1bpp massaging like other fg colors */
     pixel = get_pixel_color( pdev, color, FALSE );
     color = pdev->dib.funcs->pixel_to_colorref( &pdev->dib, pixel );
 
-    for (i = 0; i < clip->numRects; i++)
-    {
-        if (pt_in_rect( clip->rects + i, pt ))
-        {
-            RECT rect;
-            rect.left = pt.x;
-            rect.top =  pt.y;
-            rect.right = rect.left + 1;
-            rect.bottom = rect.top + 1;
-
-            pdev->dib.funcs->solid_rects( &pdev->dib, 1, &rect, 0, pixel );
-            break;
-        }
-    }
-
-    release_wine_region( pdev->clip );
+    if (!get_clipped_rects( &pdev->dib, &rect, pdev->clip, &clipped_rects )) return color;
+    pdev->dib.funcs->solid_rects( &pdev->dib, clipped_rects.count, clipped_rects.rects, 0, pixel );
+    free_clipped_rects( &clipped_rects );
     return color;
 }
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index d87dfdc..eab87d0 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -430,12 +430,6 @@ static inline void offset_rect( RECT *rect, int offset_x, int offset_y )
     rect->bottom += offset_y;
 }
 
-static inline BOOL pt_in_rect( const RECT *rect, POINT pt )
-{
-    return ((pt.x >= rect->left) && (pt.x < rect->right) &&
-            (pt.y >= rect->top) && (pt.y < rect->bottom));
-}
-
 static inline void get_bounding_rect( RECT *rect, int x, int y, int width, int height )
 {
     rect->left   = x;




More information about the wine-cvs mailing list