gdi32: Add a directional bias for the case when the Bresenham error term is zero.
This commit is contained in:
parent
a3e77bfe59
commit
a9675b3509
|
@ -106,7 +106,31 @@ static inline BOOL pt_in_rect( const RECT *rect, const POINT *pt )
|
|||
(pt->y >= rect->top) && (pt->y < rect->bottom));
|
||||
}
|
||||
|
||||
static void WINAPI solid_pen_line_callback(INT x, INT y, LPARAM lparam)
|
||||
/**********************************************************************
|
||||
* get_octant_number
|
||||
*
|
||||
* Return the octant number starting clockwise from the +ve x-axis.
|
||||
*/
|
||||
static inline int get_octant_number(int dx, int dy)
|
||||
{
|
||||
if(dy > 0)
|
||||
if(dx > 0)
|
||||
return ( dx > dy) ? 1 : 2;
|
||||
else
|
||||
return (-dx > dy) ? 4 : 3;
|
||||
else
|
||||
if(dx < 0)
|
||||
return (-dx > -dy) ? 5 : 6;
|
||||
else
|
||||
return ( dx > -dy) ? 8 : 7;
|
||||
}
|
||||
|
||||
static inline DWORD get_octant_mask(int dx, int dy)
|
||||
{
|
||||
return 1 << (get_octant_number(dx, dy) - 1);
|
||||
}
|
||||
|
||||
static void solid_pen_line_callback(INT x, INT y, LPARAM lparam)
|
||||
{
|
||||
dibdrv_physdev *pdev = (dibdrv_physdev *)lparam;
|
||||
RECT rect;
|
||||
|
@ -119,6 +143,61 @@ static void WINAPI solid_pen_line_callback(INT x, INT y, LPARAM lparam)
|
|||
return;
|
||||
}
|
||||
|
||||
static void bres_line_with_bias(INT x1, INT y1, INT x2, INT y2, void (* callback)(INT,INT,LPARAM), LPARAM lParam)
|
||||
{
|
||||
INT xadd = 1, yadd = 1;
|
||||
INT err, erradd;
|
||||
INT cnt;
|
||||
INT dx = x2 - x1;
|
||||
INT dy = y2 - y1;
|
||||
DWORD octant = get_octant_mask(dx, dy);
|
||||
INT bias = 0;
|
||||
|
||||
/* Octants 3, 5, 6 and 8 take a bias */
|
||||
if(octant & 0xb4) bias = 1;
|
||||
|
||||
if (dx < 0)
|
||||
{
|
||||
dx = -dx;
|
||||
xadd = -1;
|
||||
}
|
||||
if (dy < 0)
|
||||
{
|
||||
dy = -dy;
|
||||
yadd = -1;
|
||||
}
|
||||
if (dx > dy) /* line is "more horizontal" */
|
||||
{
|
||||
err = 2*dy - dx; erradd = 2*dy - 2*dx;
|
||||
for(cnt = 0; cnt < dx; cnt++)
|
||||
{
|
||||
callback(x1, y1, lParam);
|
||||
if (err + bias > 0)
|
||||
{
|
||||
y1 += yadd;
|
||||
err += erradd;
|
||||
}
|
||||
else err += 2*dy;
|
||||
x1 += xadd;
|
||||
}
|
||||
}
|
||||
else /* line is "more vertical" */
|
||||
{
|
||||
err = 2*dx - dy; erradd = 2*dx - 2*dy;
|
||||
for(cnt = 0; cnt < dy; cnt++)
|
||||
{
|
||||
callback(x1, y1, lParam);
|
||||
if (err + bias > 0)
|
||||
{
|
||||
x1 += xadd;
|
||||
err += erradd;
|
||||
}
|
||||
else err += 2*dx;
|
||||
y1 += yadd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL solid_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end)
|
||||
{
|
||||
const WINEREGION *clip = get_wine_region(pdev->clip);
|
||||
|
@ -188,7 +267,7 @@ static BOOL solid_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end)
|
|||
if(clip->numRects == 1 && pt_in_rect(&clip->extents, start) && pt_in_rect(&clip->extents, end))
|
||||
/* FIXME: Optimize by moving Bresenham algorithm to the primitive functions,
|
||||
or at least cache adjacent points in the callback */
|
||||
LineDDA(start->x, start->y, end->x, end->y, solid_pen_line_callback, (LPARAM)pdev);
|
||||
bres_line_with_bias(start->x, start->y, end->x, end->y, solid_pen_line_callback, (LPARAM)pdev);
|
||||
else if(clip->numRects >= 1)
|
||||
ret = FALSE;
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ static const char *sha1_graphics_a8r8g8b8[] =
|
|||
"a3cadd34d95d3d5cc23344f69aab1c2e55935fcf",
|
||||
"2426172d9e8fec27d9228088f382ef3c93717da9",
|
||||
"9e8f27ca952cdba01dbf25d07c34e86a7820c012",
|
||||
"664fac17803859a4015c6ae29e5538e314d5c827",
|
||||
"17b2c177bdce5e94433574a928bda5c94a8cdfa5",
|
||||
"fe6cc678fb13a3ead67839481bf22348adc69f52",
|
||||
"d51bd330cec510cdccf5394328bd8e5411901e9e",
|
||||
|
@ -150,6 +151,18 @@ static void compare_hash(BITMAPINFO *bmi, BYTE *bits, const char ***sha1, const
|
|||
HeapFree(GetProcessHeap(), 0, hash);
|
||||
}
|
||||
|
||||
static const RECT bias_check[] =
|
||||
{
|
||||
{100, 100, 200, 150},
|
||||
{100, 100, 150, 200},
|
||||
{100, 100, 50, 200},
|
||||
{100, 100, 0, 150},
|
||||
{100, 100, 0, 50},
|
||||
{100, 100, 50, 0},
|
||||
{100, 100, 150, 0},
|
||||
{100, 100, 200, 50}
|
||||
};
|
||||
|
||||
static const RECT hline_clips[] =
|
||||
{
|
||||
{120, 120, 140, 120}, /* unclipped */
|
||||
|
@ -251,6 +264,14 @@ static void draw_graphics(HDC hdc, BITMAPINFO *bmi, BYTE *bits, const char ***sh
|
|||
compare_hash(bmi, bits, sha1, "diagonal solid lines");
|
||||
memset(bits, 0xcc, dib_size);
|
||||
|
||||
for(i = 0; i < sizeof(bias_check) / sizeof(bias_check[0]); i++)
|
||||
{
|
||||
MoveToEx(hdc, bias_check[i].left, bias_check[i].top, NULL);
|
||||
LineTo(hdc, bias_check[i].right, bias_check[i].bottom);
|
||||
}
|
||||
compare_hash(bmi, bits, sha1, "more diagonal solid lines");
|
||||
memset(bits, 0xcc, dib_size);
|
||||
|
||||
/* solid brush PatBlt */
|
||||
solid_brush = CreateSolidBrush(RGB(0x33, 0xaa, 0xff));
|
||||
orig_brush = SelectObject(hdc, solid_brush);
|
||||
|
|
Loading…
Reference in New Issue