gdi32: Store the pattern brush information for geometric pens.

This commit is contained in:
Alexandre Julliard 2011-12-29 16:18:07 +01:00
parent ee89ce2982
commit a1fdd5856f
2 changed files with 150 additions and 43 deletions

View File

@ -36,8 +36,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdi);
/* GDI logical pen object */ /* GDI logical pen object */
typedef struct typedef struct
{ {
GDIOBJHDR header; GDIOBJHDR header;
EXTLOGPEN logpen; struct brush_pattern pattern;
EXTLOGPEN logpen;
} PENOBJ; } PENOBJ;
@ -87,15 +88,12 @@ HPEN WINAPI CreatePenIndirect( const LOGPEN * pen )
if (hpen) return hpen; if (hpen) return hpen;
} }
if (!(penPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*penPtr) ))) return 0; if (!(penPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*penPtr) ))) return 0;
penPtr->logpen.elpPenStyle = pen->lopnStyle; penPtr->logpen.elpPenStyle = pen->lopnStyle;
penPtr->logpen.elpWidth = abs(pen->lopnWidth.x); penPtr->logpen.elpWidth = abs(pen->lopnWidth.x);
penPtr->logpen.elpColor = pen->lopnColor; penPtr->logpen.elpColor = pen->lopnColor;
penPtr->logpen.elpBrushStyle = BS_SOLID; penPtr->logpen.elpBrushStyle = BS_SOLID;
penPtr->logpen.elpHatch = 0;
penPtr->logpen.elpNumEntries = 0;
penPtr->logpen.elpStyleEntry[0] = 0;
switch (pen->lopnStyle) switch (pen->lopnStyle)
{ {
@ -128,14 +126,12 @@ HPEN WINAPI ExtCreatePen( DWORD style, DWORD width,
const LOGBRUSH * brush, DWORD style_count, const LOGBRUSH * brush, DWORD style_count,
const DWORD *style_bits ) const DWORD *style_bits )
{ {
PENOBJ * penPtr; PENOBJ *penPtr = NULL;
HPEN hpen; HPEN hpen;
LOGBRUSH logbrush;
if ((style_count || style_bits) && (style & PS_STYLE_MASK) != PS_USERSTYLE) if ((style_count || style_bits) && (style & PS_STYLE_MASK) != PS_USERSTYLE)
{ goto invalid;
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
switch (style & PS_STYLE_MASK) switch (style & PS_STYLE_MASK)
{ {
@ -152,11 +148,7 @@ HPEN WINAPI ExtCreatePen( DWORD style, DWORD width,
case PS_USERSTYLE: case PS_USERSTYLE:
if (((INT)style_count) <= 0) return 0; if (((INT)style_count) <= 0) return 0;
if ((style_count > 16) || !style_bits) if ((style_count > 16) || !style_bits) goto invalid;
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if ((style & PS_TYPE_MASK) == PS_GEOMETRIC) if ((style & PS_TYPE_MASK) == PS_GEOMETRIC)
{ {
@ -169,28 +161,16 @@ HPEN WINAPI ExtCreatePen( DWORD style, DWORD width,
all_zero = all_zero && (style_bits[i] == 0); all_zero = all_zero && (style_bits[i] == 0);
} }
if(all_zero || has_neg) if (all_zero || has_neg) goto invalid;
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
} }
break; break;
case PS_INSIDEFRAME: /* applicable only for geometric pens */ case PS_INSIDEFRAME: /* applicable only for geometric pens */
if ((style & PS_TYPE_MASK) != PS_GEOMETRIC) if ((style & PS_TYPE_MASK) != PS_GEOMETRIC) goto invalid;
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
break; break;
case PS_ALTERNATE: /* applicable only for cosmetic pens */ case PS_ALTERNATE: /* applicable only for cosmetic pens */
if ((style & PS_TYPE_MASK) == PS_GEOMETRIC) if ((style & PS_TYPE_MASK) == PS_GEOMETRIC) goto invalid;
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
break; break;
default: default:
@ -200,35 +180,40 @@ HPEN WINAPI ExtCreatePen( DWORD style, DWORD width,
if ((style & PS_TYPE_MASK) == PS_GEOMETRIC) if ((style & PS_TYPE_MASK) == PS_GEOMETRIC)
{ {
if (brush->lbHatch && ((brush->lbStyle != BS_SOLID) && (brush->lbStyle != BS_HOLLOW))) if (brush->lbStyle == BS_NULL) return CreatePen( PS_NULL, 0, 0 );
{
static int fixme_hatches_shown;
if (!fixme_hatches_shown++) FIXME("Hatches not implemented\n");
}
} }
else else
{ {
if (width != 1) if (width != 1) goto invalid;
{ if (brush->lbStyle != BS_SOLID) goto invalid;
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
} }
if (!(penPtr = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(PENOBJ,logpen.elpStyleEntry[style_count])))) if (!(penPtr = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(PENOBJ,logpen.elpStyleEntry[style_count]))))
return 0; return 0;
logbrush = *brush;
if (!store_brush_pattern( &logbrush, &penPtr->pattern )) goto invalid;
if (logbrush.lbStyle == BS_DIBPATTERN) logbrush.lbStyle = BS_DIBPATTERNPT;
penPtr->logpen.elpPenStyle = style; penPtr->logpen.elpPenStyle = style;
penPtr->logpen.elpWidth = abs(width); penPtr->logpen.elpWidth = abs(width);
penPtr->logpen.elpBrushStyle = brush->lbStyle; penPtr->logpen.elpBrushStyle = logbrush.lbStyle;
penPtr->logpen.elpColor = brush->lbColor; penPtr->logpen.elpColor = logbrush.lbColor;
penPtr->logpen.elpHatch = brush->lbHatch; penPtr->logpen.elpHatch = brush->lbHatch;
penPtr->logpen.elpNumEntries = style_count; penPtr->logpen.elpNumEntries = style_count;
memcpy(penPtr->logpen.elpStyleEntry, style_bits, style_count * sizeof(DWORD)); memcpy(penPtr->logpen.elpStyleEntry, style_bits, style_count * sizeof(DWORD));
if (!(hpen = alloc_gdi_handle( &penPtr->header, OBJ_EXTPEN, &pen_funcs ))) if (!(hpen = alloc_gdi_handle( &penPtr->header, OBJ_EXTPEN, &pen_funcs )))
{
free_brush_pattern( &penPtr->pattern );
HeapFree( GetProcessHeap(), 0, penPtr ); HeapFree( GetProcessHeap(), 0, penPtr );
}
return hpen; return hpen;
invalid:
HeapFree( GetProcessHeap(), 0, penPtr );
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
} }
/*********************************************************************** /***********************************************************************
@ -276,6 +261,7 @@ static BOOL PEN_DeleteObject( HGDIOBJ handle )
PENOBJ *pen = free_gdi_handle( handle ); PENOBJ *pen = free_gdi_handle( handle );
if (!pen) return FALSE; if (!pen) return FALSE;
free_brush_pattern( &pen->pattern );
return HeapFree( GetProcessHeap(), 0, pen ); return HeapFree( GetProcessHeap(), 0, pen );
} }

View File

@ -570,9 +570,130 @@ static void test_ps_userstyle(void)
DeleteObject(pen); DeleteObject(pen);
} }
static void test_brush_pens(void)
{
char buffer[sizeof(EXTLOGPEN) + 15 * sizeof(DWORD)];
EXTLOGPEN *elp = (EXTLOGPEN *)buffer;
LOGBRUSH lb;
HPEN pen = 0;
DWORD size;
HBITMAP bmp = CreateBitmap( 8, 8, 1, 1, NULL );
BITMAPINFO *info;
HGLOBAL hmem;
hmem = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(*info) + 16 * 16 * 4 );
info = GlobalLock( hmem );
info->bmiHeader.biSize = sizeof(info->bmiHeader);
info->bmiHeader.biWidth = 16;
info->bmiHeader.biHeight = 16;
info->bmiHeader.biPlanes = 1;
info->bmiHeader.biBitCount = 32;
info->bmiHeader.biCompression = BI_RGB;
for (lb.lbStyle = BS_SOLID; lb.lbStyle <= BS_MONOPATTERN + 1; lb.lbStyle++)
{
SetLastError( 0xdeadbeef );
memset( buffer, 0xcc, sizeof(buffer) );
trace( "testing brush style %u\n", lb.lbStyle );
switch (lb.lbStyle)
{
case BS_SOLID:
case BS_HATCHED:
lb.lbColor = RGB(12,34,56);
lb.lbHatch = HS_CROSS;
pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
size = GetObject( pen, sizeof(buffer), elp );
ok( size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %x\n", elp->elpPenStyle );
ok( elp->elpBrushStyle == lb.lbStyle, "wrong brush style %x\n", elp->elpBrushStyle );
ok( elp->elpColor == RGB(12,34,56), "wrong color %x\n", elp->elpColor );
ok( elp->elpHatch == HS_CROSS, "wrong hatch %lx\n", elp->elpHatch );
ok( elp->elpNumEntries == 0, "wrong entries %x\n", elp->elpNumEntries );
break;
case BS_NULL:
pen = ExtCreatePen( PS_SOLID | PS_GEOMETRIC, 3, &lb, 0, NULL );
ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
size = GetObject( pen, sizeof(buffer), elp );
ok( size == sizeof(LOGPEN), "wrong size %u\n", size );
ok( ((LOGPEN *)elp)->lopnStyle == PS_NULL,
"wrong pen style %x\n", ((LOGPEN *)elp)->lopnStyle );
ok( ((LOGPEN *)elp)->lopnColor == 0,
"wrong color %x\n", ((LOGPEN *)elp)->lopnColor );
break;
case BS_PATTERN:
lb.lbColor = RGB(12,34,56);
lb.lbHatch = (ULONG_PTR)bmp;
pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
size = GetObject( pen, sizeof(buffer), elp );
ok( size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %x\n", elp->elpPenStyle );
ok( elp->elpBrushStyle == BS_PATTERN, "wrong brush style %x\n", elp->elpBrushStyle );
ok( elp->elpColor == 0, "wrong color %x\n", elp->elpColor );
ok( elp->elpHatch == (ULONG_PTR)bmp, "wrong hatch %lx/%p\n", elp->elpHatch, bmp );
ok( elp->elpNumEntries == 0, "wrong entries %x\n", elp->elpNumEntries );
break;
case BS_DIBPATTERN:
case BS_DIBPATTERNPT:
lb.lbColor = DIB_PAL_COLORS;
lb.lbHatch = lb.lbStyle == BS_DIBPATTERN ? (ULONG_PTR)hmem : (ULONG_PTR)info;
pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
size = GetObject( pen, sizeof(buffer), elp );
ok( size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %x\n", elp->elpPenStyle );
ok( elp->elpBrushStyle == BS_DIBPATTERNPT, "wrong brush style %x\n", elp->elpBrushStyle );
ok( elp->elpColor == 0, "wrong color %x\n", elp->elpColor );
ok( elp->elpHatch == lb.lbHatch || broken(elp->elpHatch != lb.lbHatch), /* <= w2k */
"wrong hatch %lx/%lx\n", elp->elpHatch, lb.lbHatch );
ok( elp->elpNumEntries == 0, "wrong entries %x\n", elp->elpNumEntries );
break;
default:
pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
ok( !pen, "ExtCreatePen succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
break;
}
if (pen) DeleteObject( pen );
else continue;
/* cosmetic pens require BS_SOLID */
SetLastError( 0xdeadbeef );
pen = ExtCreatePen( PS_DOT, 1, &lb, 0, NULL );
if (lb.lbStyle == BS_SOLID)
{
ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
size = GetObject( pen, sizeof(buffer), elp );
ok( size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
ok( elp->elpPenStyle == PS_DOT, "wrong pen style %x\n", elp->elpPenStyle );
ok( elp->elpBrushStyle == BS_SOLID, "wrong brush style %x\n", elp->elpBrushStyle );
ok( elp->elpColor == RGB(12,34,56), "wrong color %x\n", elp->elpColor );
ok( elp->elpHatch == HS_CROSS, "wrong hatch %lx\n", elp->elpHatch );
DeleteObject( pen );
}
else
{
ok( !pen, "ExtCreatePen succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
}
}
GlobalUnlock( hmem );
GlobalFree( hmem );
DeleteObject( bmp );
}
START_TEST(pen) START_TEST(pen)
{ {
test_logpen(); test_logpen();
test_brush_pens();
test_ps_alternate(); test_ps_alternate();
test_ps_userstyle(); test_ps_userstyle();
} }