Commit eb893bde authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

gdi: Add support for creating extended pens.

parent c1c3cc2a
......@@ -398,7 +398,20 @@ static HPEN EMFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen )
EMRCREATEPEN emr;
DWORD index = 0;
if (!GetObjectA( hPen, sizeof(emr.lopn), &emr.lopn )) return 0;
if (!GetObjectW( hPen, sizeof(emr.lopn), &emr.lopn ))
{
/* must be an extended pen */
EXTLOGPEN elp;
if (!GetObjectW( hPen, sizeof(elp), &elp ))
{
FIXME("extended pen %p not supported\n", hPen);
return 0;
}
emr.lopn.lopnStyle = elp.elpPenStyle;
emr.lopn.lopnWidth.x = elp.elpWidth;
emr.lopn.lopnWidth.y = 0;
emr.lopn.lopnColor = elp.elpColor;
}
emr.emr.iType = EMR_CREATEPEN;
emr.emr.nSize = sizeof(emr);
......
......@@ -1033,6 +1033,9 @@ DWORD WINAPI GetObjectType( HGDIOBJ handle )
case PEN_MAGIC:
result = OBJ_PEN;
break;
case EXT_PEN_MAGIC:
result = OBJ_EXTPEN;
break;
case BRUSH_MAGIC:
result = OBJ_BRUSH;
break;
......@@ -1288,7 +1291,7 @@ BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle16 )
GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
if (object)
{
magic = GDIMAGIC(object->wMagic) - PEN_MAGIC + 1;
magic = GDIMAGIC(object->wMagic) - FIRST_MAGIC + 1;
GDI_ReleaseObj( handle );
}
return magic;
......
......@@ -404,7 +404,20 @@ HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
if( index < 0 )
{
if (!GetObject16( HPEN_16(hpen), sizeof(logpen), &logpen ))
return 0;
{
/* must be an extended pen */
EXTLOGPEN elp;
if (!GetObjectW( hpen, sizeof(elp), &elp ))
{
FIXME("extended pen %p not supported\n", hpen);
return 0;
}
logpen.lopnStyle = elp.elpPenStyle;
logpen.lopnWidth.x = elp.elpWidth;
logpen.lopnWidth.y = 0;
logpen.lopnColor = elp.elpColor;
}
index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
if( index < 0 )
return 0;
......
......@@ -23,6 +23,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "windef.h"
#include "winbase.h"
......@@ -37,8 +38,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdi);
/* GDI logical pen object */
typedef struct
{
GDIOBJHDR header;
LOGPEN logpen;
GDIOBJHDR header;
EXTLOGPEN logpen;
} PENOBJ;
......@@ -86,20 +87,24 @@ HPEN WINAPI CreatePenIndirect( const LOGPEN * pen )
if (!(penPtr = GDI_AllocObject( sizeof(PENOBJ), PEN_MAGIC, (HGDIOBJ *)&hpen,
&pen_funcs ))) return 0;
if (pen->lopnStyle == PS_USERSTYLE || pen->lopnStyle == PS_ALTERNATE)
penPtr->logpen.lopnStyle = PS_SOLID;
penPtr->logpen.elpPenStyle = PS_SOLID;
else
penPtr->logpen.lopnStyle = pen->lopnStyle;
penPtr->logpen.lopnWidth.y = 0;
penPtr->logpen.elpPenStyle = pen->lopnStyle;
if (pen->lopnStyle == PS_NULL)
{
penPtr->logpen.lopnWidth.x = 1;
penPtr->logpen.lopnColor = RGB(0, 0, 0);
penPtr->logpen.elpWidth = 1;
penPtr->logpen.elpColor = RGB(0, 0, 0);
}
else
{
penPtr->logpen.lopnWidth.x = abs(pen->lopnWidth.x);
penPtr->logpen.lopnColor = pen->lopnColor;
penPtr->logpen.elpWidth = abs(pen->lopnWidth.x);
penPtr->logpen.elpColor = pen->lopnColor;
}
penPtr->logpen.elpBrushStyle = BS_SOLID;
penPtr->logpen.elpHatch = 0;
penPtr->logpen.elpNumEntries = 0;
penPtr->logpen.elpStyleEntry[0] = 0;
GDI_ReleaseObj( hpen );
return hpen;
}
......@@ -118,23 +123,63 @@ HPEN WINAPI ExtCreatePen( DWORD style, DWORD width,
HPEN hpen;
if ((style & PS_STYLE_MASK) == PS_USERSTYLE)
FIXME("PS_USERSTYLE not handled\n");
{
if (!style_count || !style_bits)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
/* FIXME: PS_USERSTYLE workaround */
FIXME("PS_USERSTYLE not handled\n");
style = (style & ~PS_STYLE_MASK) | PS_SOLID;
}
else
{
if (style_count || style_bits)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
}
if ((style & PS_STYLE_MASK) == PS_NULL)
return CreatePen( PS_NULL, 0, brush->lbColor );
if ((style & PS_TYPE_MASK) == PS_GEOMETRIC)
{
/* PS_ALTERNATE is applicable only for cosmetic pens */
if ((style & PS_STYLE_MASK) == PS_ALTERNATE)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (brush->lbHatch && ((brush->lbStyle == BS_SOLID) || (brush->lbStyle == BS_HOLLOW)))
FIXME("Hatches not implemented\n");
}
else
{
/* PS_INSIDEFRAME is applicable only for gemetric pens */
if ((style & PS_STYLE_MASK) == PS_INSIDEFRAME || width != 1)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
}
if (!(penPtr = GDI_AllocObject( sizeof(PENOBJ), PEN_MAGIC, (HGDIOBJ *)&hpen,
if (!(penPtr = GDI_AllocObject( sizeof(PENOBJ) +
style_count * sizeof(DWORD) - sizeof(penPtr->logpen.elpStyleEntry),
EXT_PEN_MAGIC, (HGDIOBJ *)&hpen,
&pen_funcs ))) return 0;
penPtr->logpen.lopnStyle = style & ~PS_TYPE_MASK;
/* PS_USERSTYLE workaround */
if((penPtr->logpen.lopnStyle & PS_STYLE_MASK) == PS_USERSTYLE)
penPtr->logpen.lopnStyle =
(penPtr->logpen.lopnStyle & ~PS_STYLE_MASK) | PS_SOLID;
penPtr->logpen.lopnWidth.x = (style & PS_GEOMETRIC) ? width : 1;
penPtr->logpen.lopnWidth.y = 0;
penPtr->logpen.lopnColor = brush->lbColor;
penPtr->logpen.elpPenStyle = style;
penPtr->logpen.elpWidth = abs(width);
penPtr->logpen.elpBrushStyle = brush->lbStyle;
penPtr->logpen.elpColor = brush->lbColor;
penPtr->logpen.elpHatch = brush->lbHatch;
penPtr->logpen.elpNumEntries = style_count;
memcpy(penPtr->logpen.elpStyleEntry, style_bits, style_count * sizeof(DWORD));
GDI_ReleaseObj( hpen );
return hpen;
......@@ -165,15 +210,19 @@ static HGDIOBJ PEN_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
static INT PEN_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
{
PENOBJ *pen = obj;
LOGPEN16 logpen;
logpen.lopnStyle = pen->logpen.lopnStyle;
logpen.lopnColor = pen->logpen.lopnColor;
logpen.lopnWidth.x = pen->logpen.lopnWidth.x;
logpen.lopnWidth.y = pen->logpen.lopnWidth.y;
if (count > sizeof(logpen)) count = sizeof(logpen);
memcpy( buffer, &logpen, count );
return count;
LOGPEN16 *logpen;
if (!buffer) return sizeof(LOGPEN16);
if (count < sizeof(LOGPEN16)) return 0;
logpen = buffer;
logpen->lopnStyle = pen->logpen.elpPenStyle;
logpen->lopnColor = pen->logpen.elpColor;
logpen->lopnWidth.x = pen->logpen.elpWidth;
logpen->lopnWidth.y = 0;
return sizeof(LOGPEN16);
}
......@@ -184,21 +233,47 @@ static INT PEN_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
{
PENOBJ *pen = obj;
if( !buffer )
return sizeof(pen->logpen);
switch (GDIMAGIC(pen->header.wMagic))
{
case PEN_MAGIC:
{
LOGPEN *lp;
if (!buffer) return sizeof(LOGPEN);
if (count < sizeof(LOGPEN)) return 0;
if ((pen->logpen.elpPenStyle & PS_STYLE_MASK) == PS_NULL &&
count == sizeof(EXTLOGPEN))
{
EXTLOGPEN *elp = buffer;
memcpy(elp, &pen->logpen, sizeof(EXTLOGPEN));
elp->elpWidth = 0;
return sizeof(EXTLOGPEN);
}
lp = buffer;
lp->lopnStyle = pen->logpen.elpPenStyle;
lp->lopnColor = pen->logpen.elpColor;
lp->lopnWidth.x = pen->logpen.elpWidth;
lp->lopnWidth.y = 0;
return sizeof(LOGPEN);
}
switch (count)
case EXT_PEN_MAGIC:
{
case sizeof(EXTLOGPEN):
FIXME("extended pens not supported\n");
return 0;
INT size = sizeof(EXTLOGPEN) + pen->logpen.elpNumEntries * sizeof(DWORD) - sizeof(pen->logpen.elpStyleEntry);
case sizeof(LOGPEN):
memcpy( buffer, &pen->logpen, sizeof(LOGPEN) );
return sizeof(LOGPEN);
if (!buffer) return size;
if (count < size) return 0;
memcpy(buffer, &pen->logpen, size);
return size;
}
default:
break;
}
assert(0);
return 0;
}
......@@ -523,7 +523,7 @@ static void test_logpen(void)
LOGPEN lp;
EXTLOGPEN elp;
LOGBRUSH lb;
DWORD user_style[2] = { 1, 2 };
DWORD obj_type, user_style[2] = { 0xabc, 0xdef };
struct
{
EXTLOGPEN elp;
......@@ -535,10 +535,38 @@ static void test_logpen(void)
trace("testing style %u\n", pen[i].style);
/********************** cosmetic pens **********************/
/* CreatePenIndirect behaviour */
lp.lopnStyle = pen[i].style,
lp.lopnWidth.x = pen[i].width;
lp.lopnWidth.y = 11; /* just in case */
lp.lopnColor = pen[i].color;
SetLastError(0xdeadbeef);
hpen = CreatePenIndirect(&lp);
ok(hpen != 0, "CreatePen error %ld\n", GetLastError());
obj_type = GetObjectType(hpen);
ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
memset(&lp, 0xb0, sizeof(lp));
SetLastError(0xdeadbeef);
size = GetObject(hpen, sizeof(lp), &lp);
ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
DeleteObject(hpen);
/* CreatePen behaviour */
SetLastError(0xdeadbeef);
hpen = CreatePen(pen[i].style, pen[i].width, pen[i].color);
ok(hpen != 0, "CreatePen error %ld\n", GetLastError());
obj_type = GetObjectType(hpen);
ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
/* check what's the real size of the object */
size = GetObject(hpen, 0, NULL);
ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
......@@ -549,6 +577,18 @@ static void test_logpen(void)
size = GetObject(hpen, sizeof(lp.lopnStyle), &lp);
ok(!size, "GetObject should fail: size %d, error %ld\n", size, GetLastError());
/* see how larger buffer sizes are handled */
memset(&lp, 0xb0, sizeof(lp));
SetLastError(0xdeadbeef);
size = GetObject(hpen, sizeof(lp) * 2, &lp);
ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
/* see how larger buffer sizes are handled */
memset(&elp, 0xb0, sizeof(elp));
SetLastError(0xdeadbeef);
size = GetObject(hpen, sizeof(elp) * 2, &elp);
ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
memset(&lp, 0xb0, sizeof(lp));
SetLastError(0xdeadbeef);
size = GetObject(hpen, sizeof(lp), &lp);
......@@ -562,39 +602,159 @@ static void test_logpen(void)
memset(&elp, 0xb0, sizeof(elp));
SetLastError(0xdeadbeef);
size = GetObject(hpen, sizeof(elp), &elp);
/* todo_wine: Wine doesn't support extended pens at all, skip all other tests */
if (!size) continue;
/* for some reason XP differentiates PS_NULL here */
if (pen[i].style == PS_NULL)
{
ok(size == sizeof(EXTLOGPEN), "GetObject returned %d, error %ld\n", size, GetLastError());
ok(elp.elpPenStyle == pen[i].ret_style, "expected %u, got %lu\n", pen[i].ret_style, elp.elpPenStyle);
ok(elp.elpWidth == 0, "expected 0, got %lu\n", elp.elpWidth);
ok(elp.elpColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, elp.elpColor);
ok(elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %u\n", elp.elpBrushStyle);
ok(elp.elpHatch == 0, "expected 0, got %p\n", (void *)elp.elpHatch);
ok(elp.elpNumEntries == 0, "expected 0, got %lx\n", elp.elpNumEntries);
}
else
{
ok(size == sizeof(LOGPEN), "GetObject returned %d, error %ld\n", size, GetLastError());
memcpy(&lp, &elp, sizeof(lp));
ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
}
ok(elp.elpPenStyle == pen[i].ret_style, "expected %u, got %lu\n", pen[i].ret_style, elp.elpPenStyle);
if (pen[i].style == PS_NULL)
ok(elp.elpWidth == 0, "expected %u, got %lu\n", pen[i].ret_width, elp.elpWidth);
DeleteObject(hpen);
/********** cosmetic pens created by ExtCreatePen ***********/
lb.lbStyle = BS_SOLID;
lb.lbColor = pen[i].color;
lb.lbHatch = HS_CROSS; /* just in case */
SetLastError(0xdeadbeef);
hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 2, user_style);
if (pen[i].style != PS_USERSTYLE)
{
ok(hpen == 0, "ExtCreatePen should fail\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"wrong last error value %ld\n", GetLastError());
SetLastError(0xdeadbeef);
hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 0, NULL);
if (pen[i].style != PS_NULL)
{
ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"wrong last error value %ld\n", GetLastError());
SetLastError(0xdeadbeef);
hpen = ExtCreatePen(pen[i].style, 1, &lb, 0, NULL);
}
}
else
ok(elp.elpWidth == pen[i].ret_width, "expected %u, got %lu\n", pen[i].ret_width, elp.elpWidth);
ok(elp.elpColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, elp.elpColor);
ok(elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %u\n", elp.elpBrushStyle);
{
ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"wrong last error value %ld\n", GetLastError());
SetLastError(0xdeadbeef);
hpen = ExtCreatePen(pen[i].style, 1, &lb, 2, user_style);
}
if (pen[i].style == PS_INSIDEFRAME)
{
/* This style is applicable only for gemetric pens */
ok(hpen == 0, "ExtCreatePen should fail\n");
goto test_geometric_pens;
}
ok(hpen != 0, "ExtCreatePen error %ld\n", GetLastError());
/* for some reason XP differenciates PS_NULL here */
obj_type = GetObjectType(hpen);
/* for some reason XP differentiates PS_NULL here */
if (pen[i].style == PS_NULL)
ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
else
ok(obj_type == OBJ_EXTPEN, "wrong object type %lu\n", obj_type);
/* check what's the real size of the object */
SetLastError(0xdeadbeef);
size = GetObject(hpen, 0, NULL);
switch (pen[i].style)
{
ok(elp.elpHatch == 0, "expected 0, got %p\n", (void *)elp.elpHatch);
ok(elp.elpNumEntries == 0, "expected 0, got %lx\n", elp.elpNumEntries);
case PS_NULL:
ok(size == sizeof(LOGPEN),
"GetObject returned %d, error %ld\n", size, GetLastError());
break;
case PS_USERSTYLE:
ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
"GetObject returned %d, error %ld\n", size, GetLastError());
break;
default:
ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry),
"GetObject returned %d, error %ld\n", size, GetLastError());
break;
}
else
/* ask for truncated data */
memset(&elp, 0xb0, sizeof(elp));
SetLastError(0xdeadbeef);
size = GetObject(hpen, sizeof(elp.elpPenStyle), &elp);
ok(!size, "GetObject should fail: size %d, error %ld\n", size, GetLastError());
/* see how larger buffer sizes are handled */
memset(&ext_pen, 0xb0, sizeof(ext_pen));
SetLastError(0xdeadbeef);
size = GetObject(hpen, sizeof(ext_pen), &ext_pen.elp);
switch (pen[i].style)
{
ok(elp.elpHatch == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %p\n", (void *)elp.elpHatch);
ok(elp.elpNumEntries == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %lx\n", elp.elpNumEntries);
case PS_NULL:
ok(size == sizeof(LOGPEN),
"GetObject returned %d, error %ld\n", size, GetLastError());
memcpy(&lp, &ext_pen.elp, sizeof(lp));
ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
/* for PS_NULL it also works this way */
memset(&elp, 0xb0, sizeof(elp));
SetLastError(0xdeadbeef);
size = GetObject(hpen, sizeof(elp), &elp);
ok(size == sizeof(EXTLOGPEN),
"GetObject returned %d, error %ld\n", size, GetLastError());
ok(ext_pen.elp.elpHatch == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %p\n", (void *)ext_pen.elp.elpHatch);
ok(ext_pen.elp.elpNumEntries == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %lx\n", ext_pen.elp.elpNumEntries);
break;
case PS_USERSTYLE:
ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
"GetObject returned %d, error %ld\n", size, GetLastError());
ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
ok(ext_pen.elp.elpNumEntries == 2, "expected 0, got %lx\n", ext_pen.elp.elpNumEntries);
ok(ext_pen.elp.elpStyleEntry[0] == 0xabc, "expected 0xabc, got %lx\n", ext_pen.elp.elpStyleEntry[0]);
ok(ext_pen.elp.elpStyleEntry[1] == 0xdef, "expected 0xabc, got %lx\n", ext_pen.elp.elpStyleEntry[1]);
break;
default:
ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry),
"GetObject returned %d, error %ld\n", size, GetLastError());
ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
ok(ext_pen.elp.elpNumEntries == 0, "expected 0, got %lx\n", ext_pen.elp.elpNumEntries);
break;
}
#if 0 /* XP returns garbage here */
ok(elp.elpStyleEntry[0] == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %lx\n", elp.elpStyleEntry[0]);
#endif
if (pen[i].style == PS_USERSTYLE)
{
todo_wine
ok(ext_pen.elp.elpPenStyle == pen[i].style, "expected %x, got %lx\n", pen[i].style, ext_pen.elp.elpPenStyle);
}
else
ok(ext_pen.elp.elpPenStyle == pen[i].style, "expected %x, got %lx\n", pen[i].style, ext_pen.elp.elpPenStyle);
ok(ext_pen.elp.elpWidth == 1, "expected 1, got %lx\n", ext_pen.elp.elpWidth);
ok(ext_pen.elp.elpColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, ext_pen.elp.elpColor);
ok(ext_pen.elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen.elp.elpBrushStyle);
DeleteObject(hpen);
test_geometric_pens:
/********************** geometric pens **********************/
lb.lbStyle = BS_SOLID;
lb.lbColor = pen[i].color;
......@@ -604,10 +764,23 @@ if (!size) continue;
if (pen[i].style != PS_USERSTYLE)
{
ok(hpen == 0, "ExtCreatePen should fail\n");
SetLastError(0xdeadbeef);
hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 0, NULL);
}
if (pen[i].style == PS_ALTERNATE)
{
/* This style is applicable only for cosmetic pens */
ok(hpen == 0, "ExtCreatePen should fail\n");
continue;
}
ok(hpen != 0, "ExtCreatePen error %ld\n", GetLastError());
obj_type = GetObjectType(hpen);
/* for some reason XP differentiates PS_NULL here */
if (pen[i].style == PS_NULL)
ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
else
ok(hpen != 0, "ExtCreatePen error %ld\n", GetLastError());
ok(obj_type == OBJ_EXTPEN, "wrong object type %lu\n", obj_type);
/* check what's the real size of the object */
size = GetObject(hpen, 0, NULL);
......@@ -618,11 +791,6 @@ if (!size) continue;
"GetObject returned %d, error %ld\n", size, GetLastError());
break;
case PS_ALTERNATE:
ok(size == 0 /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
"GetObject should fail: size %d, error %ld\n", size, GetLastError());
break;
case PS_USERSTYLE:
ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
"GetObject returned %d, error %ld\n", size, GetLastError());
......@@ -654,12 +822,13 @@ if (!size) continue;
}
else
/* XP doesn't set last error here */
ok(size == 0 /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
"GetObject should fail: size %d, error %ld\n", size, GetLastError());
memset(&elp, 0xb0, sizeof(elp));
memset(&ext_pen, 0xb0, sizeof(ext_pen));
SetLastError(0xdeadbeef);
size = GetObject(hpen, sizeof(elp), &ext_pen);
/* buffer is too small for user styles */
size = GetObject(hpen, sizeof(elp), &ext_pen.elp);
switch (pen[i].style)
{
case PS_NULL:
......@@ -667,23 +836,28 @@ if (!size) continue;
"GetObject returned %d, error %ld\n", size, GetLastError());
ok(ext_pen.elp.elpHatch == 0, "expected 0, got %p\n", (void *)ext_pen.elp.elpHatch);
ok(ext_pen.elp.elpNumEntries == 0, "expected 0, got %lx\n", ext_pen.elp.elpNumEntries);
break;
case PS_ALTERNATE:
ok(size == 0 /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
"GetObject should fail: size %d, error %ld\n", size, GetLastError());
size = GetObject(hpen, sizeof(ext_pen), &ext_pen);
/* for PS_ALTERNATE it still fails under XP SP2 */
ok(size == 0,
"GetObject should fail: size %d, error %ld\n", size, GetLastError());
/* for PS_NULL it also works this way */
SetLastError(0xdeadbeef);
size = GetObject(hpen, sizeof(ext_pen), &lp);
ok(size == sizeof(LOGPEN),
"GetObject returned %d, error %ld\n", size, GetLastError());
ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
break;
case PS_USERSTYLE:
ok(size == 0 /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
"GetObject should fail: size %d, error %ld\n", size, GetLastError());
size = GetObject(hpen, sizeof(ext_pen), &ext_pen);
size = GetObject(hpen, sizeof(ext_pen), &ext_pen.elp);
ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
"GetObject returned %d, error %ld\n", size, GetLastError());
ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
ok(ext_pen.elp.elpNumEntries == 2, "expected 0, got %lx\n", ext_pen.elp.elpNumEntries);
ok(ext_pen.elp.elpStyleEntry[0] == 0xabc, "expected 0xabc, got %lx\n", ext_pen.elp.elpStyleEntry[0]);
ok(ext_pen.elp.elpStyleEntry[1] == 0xdef, "expected 0xabc, got %lx\n", ext_pen.elp.elpStyleEntry[1]);
break;
default:
......@@ -694,24 +868,27 @@ if (!size) continue;
break;
}
if (size != 0)
/* for some reason XP differenciates PS_NULL here */
if (pen[i].style == PS_NULL)
ok(ext_pen.elp.elpPenStyle == pen[i].ret_style, "expected %x, got %lx\n", pen[i].ret_style, ext_pen.elp.elpPenStyle);
else
{
/* for some reason XP differenciates PS_NULL here */
if (pen[i].style == PS_NULL)
ok(ext_pen.elp.elpPenStyle == pen[i].ret_style, "expected %x, got %lx\n", pen[i].ret_style, ext_pen.elp.elpPenStyle);
else if (pen[i].style == PS_USERSTYLE) /* this time it's really PS_USERSTYLE */
ok(ext_pen.elp.elpPenStyle == (PS_GEOMETRIC | PS_USERSTYLE), "expected %x, got %lx\n", PS_GEOMETRIC | PS_USERSTYLE, ext_pen.elp.elpPenStyle);
else
ok(ext_pen.elp.elpPenStyle == (PS_GEOMETRIC | pen[i].ret_style), "expected %x, got %lx\n", PS_GEOMETRIC | pen[i].ret_style, ext_pen.elp.elpPenStyle);
if (pen[i].style == PS_NULL)
ok(ext_pen.elp.elpWidth == 0, "expected %u, got %lx\n", pen[i].ret_width, ext_pen.elp.elpWidth);
else
ok(ext_pen.elp.elpWidth == pen[i].ret_width, "expected %u, got %lx\n", pen[i].ret_width, ext_pen.elp.elpWidth);
ok(ext_pen.elp.elpColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, ext_pen.elp.elpColor);
ok(ext_pen.elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen.elp.elpBrushStyle);
if (pen[i].style == PS_USERSTYLE)
{
todo_wine
ok(ext_pen.elp.elpPenStyle == (PS_GEOMETRIC | pen[i].style), "expected %x, got %lx\n", PS_GEOMETRIC | pen[i].style, ext_pen.elp.elpPenStyle);
}
else
ok(ext_pen.elp.elpPenStyle == (PS_GEOMETRIC | pen[i].style), "expected %x, got %lx\n", PS_GEOMETRIC | pen[i].style, ext_pen.elp.elpPenStyle);
}
if (pen[i].style == PS_NULL)
ok(ext_pen.elp.elpWidth == 0, "expected 0, got %lx\n", ext_pen.elp.elpWidth);
else
ok(ext_pen.elp.elpWidth == pen[i].ret_width, "expected %u, got %lx\n", pen[i].ret_width, ext_pen.elp.elpWidth);
ok(ext_pen.elp.elpColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, ext_pen.elp.elpColor);
ok(ext_pen.elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen.elp.elpBrushStyle);
DeleteObject(hpen);
}
}
......
......@@ -41,7 +41,20 @@ HPEN PSDRV_SelectPen( PSDRV_PDEVICE *physDev, HPEN hpen )
{
LOGPEN logpen;
if (!GetObjectA( hpen, sizeof(logpen), &logpen )) return 0;
if (!GetObjectW( hpen, sizeof(logpen), &logpen ))
{
/* must be an extended pen */
EXTLOGPEN elp;
if (!GetObjectW( hpen, sizeof(elp), &elp ))
{
FIXME("extended pen %p not supported\n", hpen);
return 0;
}
logpen.lopnStyle = elp.elpPenStyle;
logpen.lopnWidth.x = elp.elpWidth;
logpen.lopnWidth.y = 0;
logpen.lopnColor = elp.elpColor;
}
TRACE("hpen = %p colour = %08lx\n", hpen, logpen.lopnColor);
......
......@@ -38,7 +38,20 @@ HPEN X11DRV_SelectPen( X11DRV_PDEVICE *physDev, HPEN hpen )
{
LOGPEN logpen;
if (!GetObjectA( hpen, sizeof(logpen), &logpen )) return 0;
if (!GetObjectW( hpen, sizeof(logpen), &logpen ))
{
/* must be an extended pen */
EXTLOGPEN elp;
if (!GetObjectW( hpen, sizeof(elp), &elp ))
{
FIXME("extended pen %p not supported\n", hpen);
return 0;
}
logpen.lopnStyle = elp.elpPenStyle;
logpen.lopnWidth.x = elp.elpWidth;
logpen.lopnWidth.y = 0;
logpen.lopnColor = elp.elpColor;
}
physDev->pen.style = logpen.lopnStyle & PS_STYLE_MASK;
physDev->pen.type = logpen.lopnStyle & PS_TYPE_MASK;
......
......@@ -44,7 +44,8 @@
#define ENHMETAFILE_MAGIC 0x4f52
#define ENHMETAFILE_DC_MAGIC 0x4f53
#define MEMORY_DC_MAGIC 0x4f54
#define LAST_MAGIC 0x4f54
#define EXT_PEN_MAGIC 0x4f55
#define LAST_MAGIC 0x4f55
#define MAGIC_DONTCARE 0xffff
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment