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, &params, &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, &params,
-                                    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, &params, &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, &params,
-                                    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