winex11.drv: draw dashed lines for extended pens

Evan Stade estade at gmail.com
Mon Jul 16 21:45:36 CDT 2007


Hi,

I'm only pretty sure this patch is correct.  Specifically, note that
there are now HeapAlloc()s in X11DRV_SelectPen that rely on
X11DRV_SelectPen being called again to free.  So what is supposed to
happen is that X11DRV_SelectPen called with some dash style will free
the last "dashes" array, and possibly allocate a new one. So this
method requires DeleteDC to call something along the lines of

SelectObject( hdc, GetStockObject(BLACK_PEN) );

This is indeed called on line 817 of gdi32/dc.c.

changelog:
* added a boolean variable in X_PHYSPEN to keep track of whether the
selected pen is an e extended pen
* added extended pen dashing (allowing pens with width > 1 to be dashed)

 dlls/winex11.drv/graphics.c |    5 +++-
 dlls/winex11.drv/pen.c      |   51 ++++++++++++++++++++++++++++++-------------
 dlls/winex11.drv/x11drv.h   |    1 +
 3 files changed, 40 insertions(+), 17 deletions(-)

-- 
Evan Stade
-------------- next part --------------
diff --git a/dlls/winex11.drv/graphics.c b/dlls/winex11.drv/graphics.c
index 638356b..381bb58 100644
--- a/dlls/winex11.drv/graphics.c
+++ b/dlls/winex11.drv/graphics.c
@@ -243,10 +243,11 @@ BOOL X11DRV_SetupGCForPen( X11DRV_PDEVIC
 	val.join_style = JoinRound;
     }
     wine_tsx11_lock();
-    if (physDev->pen.width <= 1 && physDev->pen.dash_len)
+    if ((physDev->pen.width <= 1 || physDev->pen.ext) && physDev->pen.dash_len)
     {
         XSetDashes( gdi_display, physDev->gc, 0, physDev->pen.dashes, physDev->pen.dash_len );
-        val.line_style = (GetBkMode(physDev->hdc) == OPAQUE) ? LineDoubleDash : LineOnOffDash;
+        val.line_style = ((GetBkMode(physDev->hdc) == OPAQUE) && !physDev->pen.ext)
+                         ? LineDoubleDash : LineOnOffDash;
     }
     else val.line_style = LineSolid;
 
diff --git a/dlls/winex11.drv/pen.c b/dlls/winex11.drv/pen.c
index fc6e9db..ab634e0 100644
--- a/dlls/winex11.drv/pen.c
+++ b/dlls/winex11.drv/pen.c
@@ -25,6 +25,16 @@ #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
 
+#define COPY_DASHDATA(ext, name) \
+    if(ext){ \
+        physDev->pen.dash_len = sizeof(EXTPEN_##name)/sizeof(*EXTPEN_##name); \
+        physDev->pen.dashes = HeapAlloc(GetProcessHeap(), 0, physDev->pen.dash_len); \
+        memcpy(physDev->pen.dashes, EXTPEN_##name, physDev->pen.dash_len);} \
+    else { \
+        physDev->pen.dash_len = sizeof(PEN_##name)/sizeof(*PEN_##name); \
+        physDev->pen.dashes = HeapAlloc(GetProcessHeap(), 0, physDev->pen.dash_len);\
+        memcpy(physDev->pen.dashes, PEN_##name, physDev->pen.dash_len);}
+
 /***********************************************************************
  *           SelectPen   (X11DRV.@)
  */
@@ -36,12 +46,19 @@ HPEN X11DRV_SelectPen( X11DRV_PDEVICE *p
     static char PEN_dashdot[]    = { 12,8,4,8 };
     static char PEN_dashdotdot[] = { 12,4,4,4,4,4 };
     static char PEN_alternate[]  = { 1,1 };
+    static char EXTPEN_dash[]       = { 3,1 };
+    static char EXTPEN_dot[]        = { 1,1 };
+    static char EXTPEN_dashdot[]    = { 3,1,1,1 };
+    static char EXTPEN_dashdotdot[] = { 3,1,1,1,1,1 };
+    static char EXTPEN_alternate[]  = { 1,1 };
+    int i;
 
     if (!GetObjectW( hpen, sizeof(logpen), &logpen ))
     {
         /* must be an extended pen */
         EXTLOGPEN *elp;
         INT size = GetObjectW( hpen, 0, NULL );
+        physDev->pen.ext = TRUE;
 
         if (!size) return 0;
 
@@ -56,6 +73,8 @@ HPEN X11DRV_SelectPen( X11DRV_PDEVICE *p
 
         HeapFree( GetProcessHeap(), 0, elp );
     }
+    else
+        physDev->pen.ext = FALSE;
 
     physDev->pen.style = logpen.lopnStyle & PS_STYLE_MASK;
     physDev->pen.type = logpen.lopnStyle & PS_TYPE_MASK;
@@ -73,28 +92,25 @@ HPEN X11DRV_SelectPen( X11DRV_PDEVICE *p
     if (hpen == GetStockObject( DC_PEN ))
         logpen.lopnColor = GetDCPenColor( physDev->hdc );
     physDev->pen.pixel = X11DRV_PALETTE_ToPhysical( physDev, logpen.lopnColor );
+
+    HeapFree(GetProcessHeap(), 0, physDev->pen.dashes);
     switch(logpen.lopnStyle & PS_STYLE_MASK)
     {
       case PS_DASH:
-	physDev->pen.dashes = PEN_dash;
-	physDev->pen.dash_len = sizeof(PEN_dash)/sizeof(*PEN_dash);
-	break;
+        COPY_DASHDATA(physDev->pen.ext, dash);
+        break;
       case PS_DOT:
-	physDev->pen.dashes = PEN_dot;
-	physDev->pen.dash_len = sizeof(PEN_dot)/sizeof(*PEN_dot);
-	break;
+        COPY_DASHDATA(physDev->pen.ext, dot);
+        break;
       case PS_DASHDOT:
-	physDev->pen.dashes = PEN_dashdot;
-	physDev->pen.dash_len = sizeof(PEN_dashdot)/sizeof(*PEN_dashdot);
-	break;
+        COPY_DASHDATA(physDev->pen.ext, dashdot);
+        break;
       case PS_DASHDOTDOT:
-	physDev->pen.dashes = PEN_dashdotdot;
-	physDev->pen.dash_len = sizeof(PEN_dashdotdot)/sizeof(*PEN_dashdotdot);
-	break;
+        COPY_DASHDATA(physDev->pen.ext, dashdotdot);
+        break;
       case PS_ALTERNATE:
-	physDev->pen.dashes = PEN_alternate;
-	physDev->pen.dash_len = sizeof(PEN_alternate)/sizeof(*PEN_alternate);
-	break;
+        COPY_DASHDATA(physDev->pen.ext, alternate);
+        break;
       case PS_USERSTYLE:
         FIXME("PS_USERSTYLE is not supported\n");
         /* fall through */
@@ -103,6 +119,11 @@ HPEN X11DRV_SelectPen( X11DRV_PDEVICE *p
         physDev->pen.dash_len = 0;
         break;
     }
+    /* FIXME: dash length can be greater than 256.  In this case it overflows char. */
+    if(physDev->pen.ext)
+        for(i = 0; i < physDev->pen.dash_len; i++)
+            physDev->pen.dashes[i] *= (physDev->pen.width ? physDev->pen.width : 1);
+
     return hpen;
 }
 
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index c542582..116ed7e 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -80,6 +80,7 @@ typedef struct
     char *       dashes;
     int          dash_len;
     int          type;          /* GEOMETRIC || COSMETIC */
+    int          ext;           /* 0 = CreatePen, 1 = ExtCreatePen */
 } X_PHYSPEN;
 
   /* X physical brush */
-- 
1.4.1


More information about the wine-patches mailing list