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, ®ion->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