Huw Davies : gdi32: Simplify the Bresenham line drawing.
Alexandre Julliard
julliard at winehq.org
Mon Nov 21 11:10:08 CST 2011
Module: wine
Branch: master
Commit: f168f838f1f6deb530251a0d6115d12b6bf8df2c
URL: http://source.winehq.org/git/wine.git/?a=commit;h=f168f838f1f6deb530251a0d6115d12b6bf8df2c
Author: Huw Davies <huw at codeweavers.com>
Date: Mon Nov 21 10:12:51 2011 +0000
gdi32: Simplify the Bresenham line drawing.
---
dlls/gdi32/dibdrv/dibdrv.h | 8 +++
dlls/gdi32/dibdrv/objects.c | 147 ++++++++++++++++++++++++++-----------------
2 files changed, 97 insertions(+), 58 deletions(-)
diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h
index ee8e1a0..e38000e 100644
--- a/dlls/gdi32/dibdrv/dibdrv.h
+++ b/dlls/gdi32/dibdrv/dibdrv.h
@@ -147,6 +147,14 @@ static inline dibdrv_physdev *get_dibdrv_pdev( PHYSDEV dev )
return (dibdrv_physdev *)dev;
}
+struct line_params
+{
+ int err_start, err_add_1, err_add_2, bias;
+ unsigned int length;
+ int x_inc, y_inc;
+ BOOL x_major;
+};
+
struct stretch_params
{
int err_start, err_add_1, err_add_2;
diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c
index c0dd7d2..9fbb3c9 100644
--- a/dlls/gdi32/dibdrv/objects.c
+++ b/dlls/gdi32/dibdrv/objects.c
@@ -545,44 +545,39 @@ int clip_line(const POINT *start, const POINT *end, const RECT *clip,
}
}
-static void bres_line_with_bias(INT x1, INT y1, INT x2, INT y2, const bres_params *params, INT err,
- BOOL last_pt, void (* callback)(dibdrv_physdev*,INT,INT), dibdrv_physdev *pdev)
+static void bres_line_with_bias(const POINT *start, const struct line_params *params,
+ void (* callback)(dibdrv_physdev*,INT,INT), dibdrv_physdev *pdev)
{
- const int xadd = is_x_increasing(params->octant) ? 1 : -1;
- const int yadd = is_y_increasing(params->octant) ? 1 : -1;
- INT erradd;
+ POINT pt = *start;
+ int len = params->length, err = params->err_start;
- if (is_xmajor(params->octant)) /* line is "more horizontal" */
+ if (params->x_major)
{
- erradd = 2*params->dy - 2*params->dx;
- while(x1 != x2)
+ while(len--)
{
- callback(pdev, x1, y1);
+ callback(pdev, pt.x, pt.y);
if (err + params->bias > 0)
{
- y1 += yadd;
- err += erradd;
+ pt.y += params->y_inc;
+ err += params->err_add_1;
}
- else err += 2*params->dy;
- x1 += xadd;
+ else err += params->err_add_2;
+ pt.x += params->x_inc;
}
- if(last_pt) callback(pdev, x1, y1);
}
- else /* line is "more vertical" */
+ else
{
- erradd = 2*params->dx - 2*params->dy;
- while(y1 != y2)
+ while(len--)
{
- callback(pdev, x1, y1);
+ callback(pdev, pt.x, pt.y);
if (err + params->bias > 0)
{
- x1 += xadd;
- err += erradd;
+ pt.x += params->x_inc;
+ err += params->err_add_1;
}
- else err += 2*params->dx;
- y1 += yadd;
+ else err += params->err_add_2;
+ pt.y += params->y_inc;
}
- if(last_pt) callback(pdev, x1, y1);
}
}
@@ -651,38 +646,58 @@ static BOOL solid_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end)
}
else
{
- bres_params params;
- INT dx = end->x - start->x;
- INT dy = end->y - start->y;
+ bres_params clip_params;
+ struct line_params line_params;
+ INT dx = end->x - start->x, dy = end->y - start->y;
+ INT abs_dx = abs(dx), abs_dy = abs(dy);
INT i;
- params.dx = abs(dx);
- params.dy = abs(dy);
- params.octant = get_octant_mask(dx, dy);
- params.bias = get_bias(params.octant);
+ clip_params.dx = abs_dx;
+ clip_params.dy = abs_dy;
+ clip_params.octant = get_octant_mask(dx, dy);
+ clip_params.bias = get_bias( clip_params.octant );
+
+ line_params.bias = clip_params.bias;
+ line_params.x_major = is_xmajor( clip_params.octant );
+ line_params.x_inc = is_x_increasing( clip_params.octant ) ? 1 : -1;
+ line_params.y_inc = is_y_increasing( clip_params.octant ) ? 1 : -1;
+
+ if (line_params.x_major)
+ {
+ line_params.err_add_1 = 2 * abs_dy - 2 * abs_dx;
+ line_params.err_add_2 = 2 * abs_dy;
+ }
+ else
+ {
+ line_params.err_add_1 = 2 * abs_dx - 2 * abs_dy;
+ line_params.err_add_2 = 2 * abs_dx;
+ }
for(i = 0; i < clip->numRects; i++)
{
POINT clipped_start, clipped_end;
int clip_status;
- clip_status = clip_line(start, end, clip->rects + i, ¶ms, &clipped_start, &clipped_end);
+ clip_status = clip_line(start, end, clip->rects + i, &clip_params, &clipped_start, &clipped_end);
if(clip_status)
{
int m = abs(clipped_start.x - start->x);
int n = abs(clipped_start.y - start->y);
- int err;
- BOOL last_pt = FALSE;
- if(is_xmajor(params.octant))
- err = 2 * params.dy - params.dx + m * 2 * params.dy - n * 2 * params.dx;
+ if (line_params.x_major)
+ {
+ line_params.err_start = 2 * abs_dy - abs_dx + m * 2 * abs_dy - n * 2 * abs_dx;
+ line_params.length = abs( clipped_end.x - clipped_start.x ) + 1;
+ }
else
- err = 2 * params.dx - params.dy + n * 2 * params.dx - m * 2 * params.dy;
+ {
+ line_params.err_start = 2 * abs_dx - abs_dy + n * 2 * abs_dx - m * 2 * abs_dy;
+ line_params.length = abs( clipped_end.y - clipped_start.y ) + 1;
+ }
- if(clip_status == 1 && (end->x != clipped_end.x || end->y != clipped_end.y)) last_pt = TRUE;
+ if (clipped_end.x == end->x && clipped_end.y == end->y) line_params.length--;
- bres_line_with_bias(clipped_start.x, clipped_start.y, clipped_end.x, clipped_end.y, ¶ms,
- err, last_pt, solid_pen_line_callback, pdev);
+ bres_line_with_bias( &clipped_start, &line_params, solid_pen_line_callback, pdev );
if(clip_status == 2) break; /* completely unclipped, so we can finish */
}
@@ -923,54 +938,70 @@ static BOOL dashed_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end)
}
else
{
- bres_params params;
- INT dx = end->x - start->x;
- INT dy = end->y - start->y;
+ bres_params clip_params;
+ struct line_params line_params;
+ INT dx = end->x - start->x, dy = end->y - start->y;
+ INT abs_dx = abs(dx), abs_dy = abs(dy);
INT i;
- params.dx = abs(dx);
- params.dy = abs(dy);
- params.octant = get_octant_mask(dx, dy);
- params.bias = get_bias(params.octant);
+ clip_params.dx = abs_dx;
+ clip_params.dy = abs_dy;
+ clip_params.octant = get_octant_mask(dx, dy);
+ clip_params.bias = get_bias( clip_params.octant );
+
+ line_params.bias = clip_params.bias;
+ line_params.x_major = is_xmajor( clip_params.octant );
+ line_params.x_inc = is_x_increasing( clip_params.octant ) ? 1 : -1;
+ line_params.y_inc = is_y_increasing( clip_params.octant ) ? 1 : -1;
+
+ if (line_params.x_major)
+ {
+ line_params.err_add_1 = 2 * abs_dy - 2 * abs_dx;
+ line_params.err_add_2 = 2 * abs_dy;
+ }
+ else
+ {
+ line_params.err_add_1 = 2 * abs_dx - 2 * abs_dy;
+ line_params.err_add_2 = 2 * abs_dx;
+ }
for(i = 0; i < clip->numRects; i++)
{
POINT clipped_start, clipped_end;
int clip_status;
- clip_status = clip_line(start, end, clip->rects + i, ¶ms, &clipped_start, &clipped_end);
+ clip_status = clip_line(start, end, clip->rects + i, &clip_params, &clipped_start, &clipped_end);
if(clip_status)
{
int m = abs(clipped_start.x - start->x);
int n = abs(clipped_start.y - start->y);
- int err;
- BOOL last_pt = FALSE;
pdev->dash_pos = start_pos;
- if(is_xmajor(params.octant))
+ if (line_params.x_major)
{
- err = 2 * params.dy - params.dx + m * 2 * params.dy - n * 2 * params.dx;
+ line_params.err_start = 2 * abs_dy - abs_dx + m * 2 * abs_dy - n * 2 * abs_dx;
+ line_params.length = abs( clipped_end.x - clipped_start.x ) + 1;
skip_dash(pdev, m);
}
else
{
- err = 2 * params.dx - params.dy + n * 2 * params.dx - m * 2 * params.dy;
+ line_params.err_start = 2 * abs_dx - abs_dy + n * 2 * abs_dx - m * 2 * abs_dy;
+ line_params.length = abs( clipped_end.y - clipped_start.y ) + 1;
skip_dash(pdev, n);
}
- if(clip_status == 1 && (end->x != clipped_end.x || end->y != clipped_end.y)) last_pt = TRUE;
+ if (clipped_end.x == end->x && clipped_end.y == end->y) line_params.length--;
- bres_line_with_bias(clipped_start.x, clipped_start.y, clipped_end.x, clipped_end.y, ¶ms,
- err, last_pt, dashed_pen_line_callback, pdev);
+ bres_line_with_bias( &clipped_start, &line_params, dashed_pen_line_callback, pdev );
if(clip_status == 2) break; /* completely unclipped, so we can finish */
}
}
pdev->dash_pos = start_pos;
- if(is_xmajor(params.octant))
- skip_dash(pdev, params.dx);
+ if(line_params.x_major)
+ skip_dash(pdev, abs_dx);
else
- skip_dash(pdev, params.dy);
+ skip_dash(pdev, abs_dy);
}
release_wine_region(pdev->clip);
More information about the wine-cvs
mailing list