Commit 1372692f authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

gdi32: Add clipping for horizontal and vertical solid lines.

parent f33bbbfd
...@@ -100,10 +100,10 @@ static inline void order_end_points(int *s, int *e) ...@@ -100,10 +100,10 @@ static inline void order_end_points(int *s, int *e)
} }
} }
static inline BOOL pt_in_rect( const RECT *rect, POINT pt ) static inline BOOL pt_in_rect( const RECT *rect, const POINT *pt )
{ {
return ((pt.x >= rect->left) && (pt.x < rect->right) && return ((pt->x >= rect->left) && (pt->x < rect->right) &&
(pt.y >= rect->top) && (pt.y < rect->bottom)); (pt->y >= rect->top) && (pt->y < rect->bottom));
} }
static void WINAPI solid_pen_line_callback(INT x, INT y, LPARAM lparam) static void WINAPI solid_pen_line_callback(INT x, INT y, LPARAM lparam)
...@@ -121,36 +121,79 @@ static void WINAPI solid_pen_line_callback(INT x, INT y, LPARAM lparam) ...@@ -121,36 +121,79 @@ static void WINAPI solid_pen_line_callback(INT x, INT y, LPARAM lparam)
static BOOL solid_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end) static BOOL solid_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end)
{ {
RECT rc; const WINEREGION *clip = get_wine_region(pdev->clip);
DC *dc = get_dibdrv_dc( &pdev->dev ); BOOL ret = TRUE;
if(get_clip_region(dc) || !pt_in_rect(&dc->vis_rect, *start) || !pt_in_rect(&dc->vis_rect, *end))
return FALSE;
rc.left = start->x; if(start->y == end->y)
rc.top = start->y;
rc.right = end->x;
rc.bottom = end->y;
if(rc.top == rc.bottom)
{ {
order_end_points(&rc.left, &rc.right); RECT rect;
rc.bottom++; int i;
pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rc, pdev->pen_and, pdev->pen_xor);
rect.left = start->x;
rect.top = start->y;
rect.right = end->x;
rect.bottom = end->y + 1;
order_end_points(&rect.left, &rect.right);
for(i = 0; i < clip->numRects; i++)
{
if(clip->rects[i].top >= rect.bottom) break;
if(clip->rects[i].bottom <= rect.top) continue;
/* Optimize the unclipped case */
if(clip->rects[i].left <= rect.left && clip->rects[i].right >= rect.right)
{
pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, pdev->pen_and, pdev->pen_xor);
break;
}
if(clip->rects[i].right > rect.left && clip->rects[i].left < rect.right)
{
RECT tmp = rect;
tmp.left = max(rect.left, clip->rects[i].left);
tmp.right = min(rect.right, clip->rects[i].right);
pdev->dib.funcs->solid_rects(&pdev->dib, 1, &tmp, pdev->pen_and, pdev->pen_xor);
}
}
} }
else if(rc.left == rc.right) else if(start->x == end->x)
{ {
order_end_points(&rc.top, &rc.bottom); RECT rect;
rc.right++; int i;
pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rc, pdev->pen_and, pdev->pen_xor);
rect.left = start->x;
rect.top = start->y;
rect.right = end->x + 1;
rect.bottom = end->y;
order_end_points(&rect.top, &rect.bottom);
for(i = 0; i < clip->numRects; i++)
{
/* Optimize unclipped case */
if(clip->rects[i].top <= rect.top && clip->rects[i].bottom >= rect.bottom &&
clip->rects[i].left <= rect.left && clip->rects[i].right >= rect.right)
{
pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, pdev->pen_and, pdev->pen_xor);
break;
}
if(clip->rects[i].top >= rect.bottom) break;
if(clip->rects[i].bottom <= rect.top) continue;
if(clip->rects[i].right > rect.left && clip->rects[i].left < rect.right)
{
RECT tmp = rect;
tmp.top = max(rect.top, clip->rects[i].top);
tmp.bottom = min(rect.bottom, clip->rects[i].bottom);
pdev->dib.funcs->solid_rects(&pdev->dib, 1, &tmp, pdev->pen_and, pdev->pen_xor);
}
}
} }
else else
{ {
/* FIXME: Optimize by moving Bresenham algorithm to the primitive functions, if(clip->numRects == 1 && pt_in_rect(&clip->extents, start) && pt_in_rect(&clip->extents, end))
or at least cache adjacent points in the callback */ /* FIXME: Optimize by moving Bresenham algorithm to the primitive functions,
LineDDA(start->x, start->y, end->x, end->y, solid_pen_line_callback, (LPARAM)pdev); or at least cache adjacent points in the callback */
LineDDA(start->x, start->y, end->x, end->y, solid_pen_line_callback, (LPARAM)pdev);
else if(clip->numRects >= 1)
ret = FALSE;
} }
return TRUE; release_wine_region(pdev->clip);
return ret;
} }
/*********************************************************************** /***********************************************************************
......
...@@ -553,6 +553,19 @@ extern HPALETTE PALETTE_Init(void) DECLSPEC_HIDDEN; ...@@ -553,6 +553,19 @@ extern HPALETTE PALETTE_Init(void) DECLSPEC_HIDDEN;
extern INT mirror_region( HRGN dst, HRGN src, INT width ) DECLSPEC_HIDDEN; extern INT mirror_region( HRGN dst, HRGN src, INT width ) DECLSPEC_HIDDEN;
extern BOOL REGION_FrameRgn( HRGN dest, HRGN src, INT x, INT y ) DECLSPEC_HIDDEN; extern BOOL REGION_FrameRgn( HRGN dest, HRGN src, INT x, INT y ) DECLSPEC_HIDDEN;
typedef struct
{
INT size;
INT numRects;
RECT *rects;
RECT extents;
} WINEREGION;
extern const WINEREGION *get_wine_region(HRGN rgn) DECLSPEC_HIDDEN;
static inline void release_wine_region(HRGN rgn)
{
GDI_ReleaseObj(rgn);
}
/* null driver entry points */ /* null driver entry points */
extern BOOL CDECL nulldrv_AbortPath( PHYSDEV dev ) DECLSPEC_HIDDEN; extern BOOL CDECL nulldrv_AbortPath( PHYSDEV dev ) DECLSPEC_HIDDEN;
extern BOOL CDECL nulldrv_AngleArc( PHYSDEV dev, INT x, INT y, DWORD radius, FLOAT start, FLOAT sweep ) DECLSPEC_HIDDEN; extern BOOL CDECL nulldrv_AngleArc( PHYSDEV dev, INT x, INT y, DWORD radius, FLOAT start, FLOAT sweep ) DECLSPEC_HIDDEN;
......
...@@ -105,13 +105,6 @@ SOFTWARE. ...@@ -105,13 +105,6 @@ SOFTWARE.
WINE_DEFAULT_DEBUG_CHANNEL(region); WINE_DEFAULT_DEBUG_CHANNEL(region);
typedef struct {
INT size;
INT numRects;
RECT *rects;
RECT extents;
} WINEREGION;
/* GDI logical region object */ /* GDI logical region object */
typedef struct typedef struct
{ {
...@@ -924,6 +917,20 @@ HRGN WINAPI CreateEllipticRgnIndirect( const RECT *rect ) ...@@ -924,6 +917,20 @@ HRGN WINAPI CreateEllipticRgnIndirect( const RECT *rect )
rect->bottom - rect->top ); rect->bottom - rect->top );
} }
/*********************************************************************
* get_wine_region
*
* Return the region data without making a copy. The caller
* must not alter anything and must call GDI_ReleaseObj() when
* they have finished with the data.
*/
const WINEREGION *get_wine_region(HRGN rgn)
{
RGNOBJ *obj = GDI_GetObjPtr( rgn, OBJ_REGION );
if(!obj) return NULL;
return &obj->rgn;
}
/*********************************************************************** /***********************************************************************
* GetRegionData (GDI32.@) * GetRegionData (GDI32.@)
* *
......
...@@ -78,6 +78,8 @@ static const char *sha1_graphics_a8r8g8b8[] = ...@@ -78,6 +78,8 @@ static const char *sha1_graphics_a8r8g8b8[] =
"a3cadd34d95d3d5cc23344f69aab1c2e55935fcf", "a3cadd34d95d3d5cc23344f69aab1c2e55935fcf",
"2426172d9e8fec27d9228088f382ef3c93717da9", "2426172d9e8fec27d9228088f382ef3c93717da9",
"9e8f27ca952cdba01dbf25d07c34e86a7820c012", "9e8f27ca952cdba01dbf25d07c34e86a7820c012",
"76343ceb04e6295e0560019249d3c0318a23c8a6",
"6ecee6ba1c06dcb6b70ff42a8ea2df7803847860",
"17b2c177bdce5e94433574a928bda5c94a8cdfa5", "17b2c177bdce5e94433574a928bda5c94a8cdfa5",
NULL NULL
}; };
...@@ -147,12 +149,43 @@ static void compare_hash(BITMAPINFO *bmi, BYTE *bits, const char ***sha1, const ...@@ -147,12 +149,43 @@ static void compare_hash(BITMAPINFO *bmi, BYTE *bits, const char ***sha1, const
HeapFree(GetProcessHeap(), 0, hash); HeapFree(GetProcessHeap(), 0, hash);
} }
static const RECT hline_clips[] =
{
{120, 120, 140, 120}, /* unclipped */
{100, 122, 140, 122}, /* l edgecase */
{ 99, 124, 140, 124}, /* l edgecase clipped */
{120, 126, 200, 126}, /* r edgecase */
{120, 128, 201, 128}, /* r edgecase clipped */
{ 99, 130, 201, 130}, /* l and r clipped */
{120, 100, 140, 100}, /* t edgecase */
{120, 99, 140, 99}, /* t edgecase clipped */
{120, 199, 140, 199}, /* b edgecase */
{120, 200, 140, 200}, /* b edgecase clipped */
{120, 132, 310, 132} /* inside two clip rects */
};
static const RECT vline_clips[] =
{
{120, 120, 120, 140}, /* unclipped */
{100, 120, 100, 140}, /* l edgecase */
{ 99, 120, 99, 140}, /* l edgecase clipped */
{199, 120, 199, 140}, /* r edgecase */
{200, 120, 200, 140}, /* r edgecase clipped */
{122, 99, 122, 201}, /* t and b clipped */
{124, 100, 124, 140}, /* t edgecase */
{126, 99, 126, 140}, /* t edgecase clipped */
{128, 120, 128, 200}, /* b edgecase */
{130, 120, 130, 201}, /* b edgecase clipped */
{132, 12, 132, 140} /* inside two clip rects */
};
static void draw_graphics(HDC hdc, BITMAPINFO *bmi, BYTE *bits, const char ***sha1) static void draw_graphics(HDC hdc, BITMAPINFO *bmi, BYTE *bits, const char ***sha1)
{ {
DWORD dib_size = get_dib_size(bmi); DWORD dib_size = get_dib_size(bmi);
HPEN solid_pen, orig_pen; HPEN solid_pen, orig_pen;
HBRUSH solid_brush, orig_brush; HBRUSH solid_brush, orig_brush;
INT i, y; INT i, y;
HRGN hrgn, hrgn2;
memset(bits, 0xcc, dib_size); memset(bits, 0xcc, dib_size);
compare_hash(bmi, bits, sha1, "empty"); compare_hash(bmi, bits, sha1, "empty");
...@@ -188,6 +221,33 @@ static void draw_graphics(HDC hdc, BITMAPINFO *bmi, BYTE *bits, const char ***sh ...@@ -188,6 +221,33 @@ static void draw_graphics(HDC hdc, BITMAPINFO *bmi, BYTE *bits, const char ***sh
compare_hash(bmi, bits, sha1, "diagonal solid lines"); compare_hash(bmi, bits, sha1, "diagonal solid lines");
memset(bits, 0xcc, dib_size); memset(bits, 0xcc, dib_size);
hrgn = CreateRectRgn(10, 10, 200, 20);
hrgn2 = CreateRectRgn(100, 100, 200, 200);
CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
SetRectRgn(hrgn2, 290, 100, 300, 200);
CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
ExtSelectClipRgn(hdc, hrgn, RGN_COPY);
DeleteObject(hrgn2);
DeleteObject(hrgn);
for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++)
{
MoveToEx(hdc, hline_clips[i].left, hline_clips[i].top, NULL);
LineTo(hdc, hline_clips[i].right, hline_clips[i].bottom);
}
compare_hash(bmi, bits, sha1, "clipped solid hlines");
memset(bits, 0xcc, dib_size);
for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++)
{
MoveToEx(hdc, vline_clips[i].left, vline_clips[i].top, NULL);
LineTo(hdc, vline_clips[i].right, vline_clips[i].bottom);
}
compare_hash(bmi, bits, sha1, "clipped solid vlines");
memset(bits, 0xcc, dib_size);
ExtSelectClipRgn(hdc, NULL, RGN_COPY);
solid_brush = CreateSolidBrush(RGB(0x33, 0xaa, 0xff)); solid_brush = CreateSolidBrush(RGB(0x33, 0xaa, 0xff));
orig_brush = SelectObject(hdc, solid_brush); orig_brush = SelectObject(hdc, solid_brush);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment