[4/4] winex11.drv: draw custom dashes [try2]
Evan Stade
estade at gmail.com
Mon Jul 30 21:09:25 CDT 2007
Hi,
[try2]
* matched braces style of rest of file
* spread code out to make it more readable
* simplified use of gdi_to_x11_dashes
dlls/winex11.drv/graphics.c | 3 +
dlls/winex11.drv/pen.c | 123 +++++++++++++++++++++++++++++++++++++++++--
dlls/winex11.drv/x11drv.h | 1
3 files changed, 120 insertions(+), 7 deletions(-)
--
Evan Stade
-------------- next part --------------
diff --git a/dlls/winex11.drv/graphics.c b/dlls/winex11.drv/graphics.c
index b2e105f..73b7cef 100644
--- a/dlls/winex11.drv/graphics.c
+++ b/dlls/winex11.drv/graphics.c
@@ -245,7 +245,8 @@ BOOL X11DRV_SetupGCForPen( X11DRV_PDEVIC
wine_tsx11_lock();
if (physDev->pen.dash_len)
{
- XSetDashes( gdi_display, physDev->gc, 0, physDev->pen.dashes, physDev->pen.dash_len );
+ XSetDashes( gdi_display, physDev->gc, physDev->pen.dash_offset,
+ physDev->pen.dashes, physDev->pen.dash_len );
val.line_style = ((GetBkMode(physDev->hdc) == OPAQUE) && (!physDev->pen.ext))
? LineDoubleDash : LineOnOffDash;
}
diff --git a/dlls/winex11.drv/pen.c b/dlls/winex11.drv/pen.c
index 96d9043..a1eba17 100644
--- a/dlls/winex11.drv/pen.c
+++ b/dlls/winex11.drv/pen.c
@@ -17,14 +17,105 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#include "config.h"
+#include <limits.h>
#include "x11drv.h"
#include "wine/debug.h"
+#define MIN(x, y) ((x) > (y) ? (y) : (x))
+
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
+/* X doesn't allow any zero entries. This function removes zero-entries
+ * and combines newly-adjacent entries that originally had the same
+ * parity. Also X represents the dash lengths as characters, so we
+ * can easily overflow. If we overflow, make the dash length
+ * UCHAR_MAX. Also note that X must start on a dash rather than a space,
+ * which is what the offset business is needed for.
+ *
+ * returns 0 for error, or the pen style for success
+ */
+static DWORD gdi_to_x11_dashes(DWORD* gdi_dashes, int count, char* out,
+ int* outcount, int* outoffset)
+{
+ DWORD dashes[16];
+ int i, j = 0, offset = 0, trailing_zero = 0;
+
+ /* First: find first non-zero entry. */
+ for(i = 0; i < count; i++)
+ if(gdi_dashes[i] != 0)
+ break;
+
+ if(i % 2)
+ offset = 1;
+
+ /* Then: iterate through all entries. */
+ for(; i < count; i++, j++)
+ {
+ if(!gdi_dashes[i])
+ {
+ trailing_zero = 1;
+ break;
+ }
+
+ dashes[j] = MIN(gdi_dashes[i], UCHAR_MAX);
+
+ /* If the next entry is zero, collapse this entry with the next
+ * one (or more) of the same parity. */
+ while((i + 2 < count) && gdi_dashes[i + 1] == 0)
+ {
+ dashes[j] = MIN(UCHAR_MAX, gdi_dashes[i + 2] + dashes[j]);
+ i += 2;
+ }
+ }
+
+ /* j is the number of entries we successfully managed to extract. */
+ if(!(*outcount = j))
+ {
+ ERR("all-zero dash array\n");
+ return 0;
+ }
+
+ if(!offset && trailing_zero)
+ {
+ dashes[0] += dashes[j - 1];
+ offset = dashes[j - 1];
+ j--;
+ }
+
+ /* offset is true if we are starting on a space. We have to copy
+ * everything over shifted one to the left. Also we copy the first
+ * value into the last space-type slot. */
+ if(offset && (j > 1))
+ {
+ for(i = 0; i + 1 < j; i++)
+ out[i] = dashes[i + 1];
+ out[j - 1 - (j % 2)] = MIN(UCHAR_MAX, dashes[0] + dashes[j - 1 - (j % 2)]);
+
+ offset = -dashes[0];
+ for(i = 0; i + 1 < j; i++)
+ offset += out[i];
+ }
+ else
+ for(i = 0; i < j; i++)
+ out[i] = dashes[i];
+
+ *outcount = j;
+ *outoffset = offset;
+
+ if((j == 1) && !(count % 2))
+ {
+ if(offset)
+ return PS_NULL;
+ else
+ return PS_SOLID;
+ }
+
+ return PS_USERSTYLE;
+}
+
+
/***********************************************************************
* SelectPen (X11DRV.@)
*/
@@ -40,7 +131,10 @@ HPEN X11DRV_SelectPen( X11DRV_PDEVICE *p
static const char EXTPEN_dashdot[] = { 3,1,1,1 };
static const char EXTPEN_dashdotdot[] = { 3,1,1,1,1,1 };
LOGPEN logpen;
- int i;
+ DWORD style = 0;
+ int i, numdashes = 0, stretch_dashes = 1;
+
+ physDev->pen.dash_offset = physDev->pen.dash_len = 0;
if (!GetObjectW( hpen, sizeof(logpen), &logpen ))
{
@@ -54,8 +148,20 @@ HPEN X11DRV_SelectPen( X11DRV_PDEVICE *p
elp = HeapAlloc( GetProcessHeap(), 0, size );
GetObjectW( hpen, size, elp );
- /* FIXME: add support for user style pens */
- logpen.lopnStyle = elp->elpPenStyle;
+
+ /* handling of PS_USERSTYLE | PS_GEOMETRIC */
+ numdashes = MIN(MAX_DASHLEN, elp->elpNumEntries);
+
+ if((elp->elpPenStyle & PS_GEOMETRIC) && numdashes)
+ style = gdi_to_x11_dashes(elp->elpStyleEntry, elp->elpNumEntries,
+ physDev->pen.dashes, &physDev->pen.dash_len,
+ &physDev->pen.dash_offset);
+
+ if(style)
+ logpen.lopnStyle = (elp->elpPenStyle & ~PS_STYLE_MASK) | style;
+ else
+ logpen.lopnStyle = elp->elpPenStyle;
+
logpen.lopnWidth.x = elp->elpWidth;
logpen.lopnWidth.y = 0;
logpen.lopnColor = elp->elpColor;
@@ -106,16 +212,21 @@ HPEN X11DRV_SelectPen( X11DRV_PDEVICE *p
case PS_ALTERNATE:
physDev->pen.dash_len = sizeof(PEN_alternate)/sizeof(*PEN_alternate);
memcpy(physDev->pen.dashes, PEN_alternate, physDev->pen.dash_len);
+ stretch_dashes = 0;
break;
case PS_USERSTYLE:
+ if(physDev->pen.ext){
+ stretch_dashes = 0;
+ break;
+ }
FIXME("PS_USERSTYLE is not supported\n");
/* fall through */
default:
physDev->pen.dash_len = 0;
+ stretch_dashes = 0;
break;
}
- if(physDev->pen.ext && physDev->pen.dash_len &&
- (logpen.lopnStyle & PS_STYLE_MASK) != PS_ALTERNATE)
+ if(stretch_dashes && physDev->pen.ext && physDev->pen.dash_len)
for(i = 0; i < physDev->pen.dash_len; i++)
physDev->pen.dashes[i] *= (physDev->pen.width ? physDev->pen.width : 1);
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index a778f64..7301d41 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -80,6 +80,7 @@ typedef struct
int width;
char dashes[MAX_DASHLEN];
int dash_len;
+ int dash_offset;
int type; /* GEOMETRIC || COSMETIC */
int ext; /* extended pen - 1, otherwise - 0 */
} X_PHYSPEN;
--
1.4.1
More information about the wine-patches
mailing list