From eb893bdea3df8ee40c690ca6f1744f90364ac318 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Mon, 30 Jan 2006 18:17:07 +0100 Subject: [PATCH] gdi: Add support for creating extended pens. --- dlls/gdi/enhmfdrv/objects.c | 15 ++- dlls/gdi/gdiobj.c | 5 +- dlls/gdi/mfdrv/objects.c | 15 ++- dlls/gdi/pen.c | 151 ++++++++++++++++++------ dlls/gdi/tests/gdiobj.c | 281 ++++++++++++++++++++++++++++++++++++-------- dlls/wineps/pen.c | 15 ++- dlls/x11drv/pen.c | 15 ++- include/gdi.h | 3 +- 8 files changed, 404 insertions(+), 96 deletions(-) diff --git a/dlls/gdi/enhmfdrv/objects.c b/dlls/gdi/enhmfdrv/objects.c index 8c51f63303f..9d8b14d6b5d 100644 --- a/dlls/gdi/enhmfdrv/objects.c +++ b/dlls/gdi/enhmfdrv/objects.c @@ -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); diff --git a/dlls/gdi/gdiobj.c b/dlls/gdi/gdiobj.c index 03828f7db59..a4c9a07e938 100644 --- a/dlls/gdi/gdiobj.c +++ b/dlls/gdi/gdiobj.c @@ -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; diff --git a/dlls/gdi/mfdrv/objects.c b/dlls/gdi/mfdrv/objects.c index 1cda8feb0b2..e0859ac59e0 100644 --- a/dlls/gdi/mfdrv/objects.c +++ b/dlls/gdi/mfdrv/objects.c @@ -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; diff --git a/dlls/gdi/pen.c b/dlls/gdi/pen.c index f165c8267d9..0e4d686d938 100644 --- a/dlls/gdi/pen.c +++ b/dlls/gdi/pen.c @@ -23,6 +23,7 @@ #include #include #include +#include #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; } diff --git a/dlls/gdi/tests/gdiobj.c b/dlls/gdi/tests/gdiobj.c index 7c5f505413b..463bbf45dd5 100644 --- a/dlls/gdi/tests/gdiobj.c +++ b/dlls/gdi/tests/gdiobj.c @@ -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); } } diff --git a/dlls/wineps/pen.c b/dlls/wineps/pen.c index 64ad7e5afaf..590acaf5ca9 100644 --- a/dlls/wineps/pen.c +++ b/dlls/wineps/pen.c @@ -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); diff --git a/dlls/x11drv/pen.c b/dlls/x11drv/pen.c index a23cd48f1cb..2db51360b7e 100644 --- a/dlls/x11drv/pen.c +++ b/dlls/x11drv/pen.c @@ -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; diff --git a/include/gdi.h b/include/gdi.h index af18a039571..91beab319c4 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -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 -- 2.11.4.GIT