Alexandre Julliard : gdi32: Implement returning a region for 1-pixel wide dashed pen lines.

Alexandre Julliard julliard at winehq.org
Thu Dec 29 12:15:44 CST 2011


Module: wine
Branch: master
Commit: 9ee690c984b22b9af936bd481a445a20444d3d07
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9ee690c984b22b9af936bd481a445a20444d3d07

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Dec 28 14:28:06 2011 +0100

gdi32: Implement returning a region for 1-pixel wide dashed pen lines.

---

 dlls/gdi32/dibdrv/objects.c |  153 ++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 145 insertions(+), 8 deletions(-)

diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c
index bb68029..dd7ddb7 100644
--- a/dlls/gdi32/dibdrv/objects.c
+++ b/dlls/gdi32/dibdrv/objects.c
@@ -1047,21 +1047,158 @@ static BOOL dashed_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end)
     return TRUE;
 }
 
+static BOOL dashed_pen_line_region(dibdrv_physdev *pdev, POINT *start, POINT *end, HRGN region)
+{
+    int i, dash_len;
+    RECT rect;
+
+    rect.left   = start->x;
+    rect.top    = start->y;
+    rect.right  = start->x + 1;
+    rect.bottom = start->y + 1;
+
+    if (start->y == end->y) /* hline */
+    {
+        if (start->x <= end->x)
+        {
+            for (i = start->x; i < end->x; i += dash_len)
+            {
+                dash_len = min( pdev->dash_pos.left_in_dash, end->x - i );
+                if (pdev->dash_pos.mark)
+                {
+                    rect.left = i;
+                    rect.right = i + dash_len;
+                    add_rect_to_region( region, &rect );
+                }
+                skip_dash(pdev, dash_len);
+            }
+        }
+        else
+        {
+            for (i = start->x; i > end->x; i -= dash_len)
+            {
+                dash_len = min( pdev->dash_pos.left_in_dash, i - end->x );
+                if (pdev->dash_pos.mark)
+                {
+                    rect.left = i - dash_len + 1;
+                    rect.right = i + 1;
+                    add_rect_to_region( region, &rect );
+                }
+                skip_dash(pdev, dash_len);
+            }
+        }
+    }
+    else if (start->x == end->x) /* vline */
+    {
+        if (start->y <= end->y)
+        {
+            for (i = start->y; i < end->y; i += dash_len)
+            {
+                dash_len = min( pdev->dash_pos.left_in_dash, end->y - i );
+                if (pdev->dash_pos.mark)
+                {
+                    rect.top = i;
+                    rect.bottom = i + dash_len;
+                    add_rect_to_region( region, &rect );
+                }
+                skip_dash(pdev, dash_len);
+            }
+        }
+        else
+        {
+            for (i = start->y; i > end->y; i -= dash_len)
+            {
+                dash_len = min( pdev->dash_pos.left_in_dash, i - end->y );
+                if (pdev->dash_pos.mark)
+                {
+                    rect.top = i - dash_len + 1;
+                    rect.bottom = i + 1;
+                    add_rect_to_region( region, &rect );
+                }
+                skip_dash(pdev, dash_len);
+            }
+        }
+    }
+    else
+    {
+        INT dx = end->x - start->x, dy = end->y - start->y;
+        INT abs_dx = abs(dx), abs_dy = abs(dy);
+        DWORD octant = get_octant_mask(dx, dy);
+        INT bias = get_bias( octant );
+        int x_inc = is_x_increasing( octant ) ? 1 : -1;
+        int y_inc = is_y_increasing( octant ) ? 1 : -1;
+
+        if (is_xmajor( octant ))
+        {
+            int err_add_1 = 2 * abs_dy - 2 * abs_dx;
+            int err_add_2 = 2 * abs_dy;
+            int err = 2 * abs_dy - abs_dx;
+
+            while (abs_dx--)
+            {
+                if (pdev->dash_pos.mark) add_rect_to_region( region, &rect );
+                skip_dash(pdev, 1);
+                rect.left += x_inc;
+                rect.right += x_inc;
+                if (err + bias > 0)
+                {
+                    rect.top += y_inc;
+                    rect.bottom += y_inc;
+                    err += err_add_1;
+                }
+                else err += err_add_2;
+            }
+
+        }
+        else
+        {
+            int err_add_1 = 2 * abs_dx - 2 * abs_dy;
+            int err_add_2 = 2 * abs_dx;
+            int err = 2 * abs_dx - abs_dy;
+
+            while (abs_dy--)
+            {
+                if (pdev->dash_pos.mark) add_rect_to_region( region, &rect );
+                skip_dash(pdev, 1);
+                rect.top += y_inc;
+                rect.bottom += y_inc;
+                if (err + bias > 0)
+                {
+                    rect.left += x_inc;
+                    rect.right += x_inc;
+                    err += err_add_1;
+                }
+                else err += err_add_2;
+            }
+        }
+    }
+    return TRUE;
+}
+
 static BOOL dashed_pen_lines(dibdrv_physdev *pdev, int num, POINT *pts, BOOL close, HRGN region)
 {
     int i;
 
-    get_color_masks( pdev, GetROP2(pdev->dev.hdc), pdev->pen_colorref,
-                     pdev->pen_is_ext ? TRANSPARENT : GetBkMode(pdev->dev.hdc),
-                     &pdev->dash_masks[1], &pdev->dash_masks[0] );
-
     assert( num >= 2 );
-    for (i = 0; i < num - 1; i++)
-        if (!dashed_pen_line( pdev, pts + i, pts + i + 1 ))
-            return FALSE;
 
-    if (close) return dashed_pen_line( pdev, pts + num - 1, pts );
+    if (region)
+    {
+        for (i = 0; i < num - 1; i++)
+            if (!dashed_pen_line_region( pdev, pts + i, pts + i + 1, region ))
+                return FALSE;
+        if (close) return dashed_pen_line_region( pdev, pts + num - 1, pts, region );
+    }
+    else
+    {
+        get_color_masks( pdev, GetROP2(pdev->dev.hdc), pdev->pen_colorref,
+                         pdev->pen_is_ext ? TRANSPARENT : GetBkMode(pdev->dev.hdc),
+                         &pdev->dash_masks[1], &pdev->dash_masks[0] );
 
+        for (i = 0; i < num - 1; i++)
+            if (!dashed_pen_line( pdev, pts + i, pts + i + 1 ))
+                return FALSE;
+        if (close) return dashed_pen_line( pdev, pts + num - 1, pts );
+    }
     return TRUE;
 }
 




More information about the wine-cvs mailing list