gdi32: Fix handling of the DC brush/pen in metafiles.

This commit is contained in:
Alexandre Julliard 2011-03-10 20:22:22 +01:00
parent ed3ce3c91b
commit dfaee0a5d7
7 changed files with 233 additions and 7 deletions

View File

@ -38,6 +38,8 @@ typedef struct
UINT handles_size, cur_handles;
HGDIOBJ *handles;
HANDLE hFile; /* Handle for disk based MetaFile */
HBRUSH dc_brush;
HPEN dc_pen;
INT horzres, vertres;
INT horzsize, vertsize;
INT logpixelsx, logpixelsy;
@ -128,6 +130,8 @@ extern HPALETTE CDECL EMFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPal, BOOL for
extern INT CDECL EMFDRV_SetArcDirection( PHYSDEV dev, INT arcDirection ) DECLSPEC_HIDDEN;
extern COLORREF CDECL EMFDRV_SetBkColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN;
extern INT CDECL EMFDRV_SetBkMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN;
extern COLORREF CDECL EMFDRV_SetDCBrushColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN;
extern COLORREF CDECL EMFDRV_SetDCPenColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN;
extern INT CDECL EMFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDest, INT yDest,
DWORD cx, DWORD cy, INT xSrc,
INT ySrc, UINT startscan, UINT lines,

View File

@ -120,8 +120,8 @@ static const DC_FUNCTIONS EMFDRV_Funcs =
NULL, /* pSetBitmapBits */
EMFDRV_SetBkColor, /* pSetBkColor */
EMFDRV_SetBkMode, /* pSetBkMode */
NULL, /* pSetDCBrushColor */
NULL, /* pSetDCPenColor */
EMFDRV_SetDCBrushColor, /* pSetDCBrushColor*/
EMFDRV_SetDCPenColor, /* pSetDCPenColor*/
NULL, /* pSetDIBColorTable */
NULL, /* pSetDIBits */
EMFDRV_SetDIBitsToDevice, /* pSetDIBitsToDevice */
@ -341,7 +341,8 @@ HDC WINAPI CreateEnhMetaFileW(
physDev->handles_size = HANDLE_LIST_INC;
physDev->cur_handles = 1;
physDev->hFile = 0;
physDev->dc_brush = 0;
physDev->dc_pen = 0;
physDev->horzres = GetDeviceCaps(hRefDC, HORZRES);
physDev->vertres = GetDeviceCaps(hRefDC, VERTRES);
physDev->logpixelsx = GetDeviceCaps(hRefDC, LOGPIXELSX);
@ -455,6 +456,9 @@ HENHMETAFILE WINAPI CloseEnhMetaFile(HDC hdc) /* [in] metafile DC */
if(dc->saveLevel)
RestoreDC(hdc, 1);
if (physDev->dc_brush) DeleteObject( physDev->dc_brush );
if (physDev->dc_pen) DeleteObject( physDev->dc_pen );
emr.emr.iType = EMR_EOF;
emr.emr.nSize = sizeof(emr);
emr.nPalEntries = 0;

View File

@ -287,7 +287,7 @@ HBRUSH CDECL EMFDRV_SelectBrush(PHYSDEV dev, HBRUSH hBrush )
* We do however have to handle setting the higher order bit to
* designate that this is a stock object.
*/
for (i = WHITE_BRUSH; i <= NULL_BRUSH; i++)
for (i = WHITE_BRUSH; i <= DC_BRUSH; i++)
{
if (hBrush == GetStockObject(i))
{
@ -448,7 +448,7 @@ HPEN CDECL EMFDRV_SelectPen(PHYSDEV dev, HPEN hPen )
* designate that this is a stock object.
*/
for (i = WHITE_PEN; i <= NULL_PEN; i++)
for (i = WHITE_PEN; i <= DC_PEN; i++)
{
if (hPen == GetStockObject(i))
{
@ -528,6 +528,48 @@ found:
return EMFDRV_WriteRecord( dev, &emr.emr ) ? hPal : 0;
}
/******************************************************************
* EMFDRV_SetDCBrushColor
*/
COLORREF CDECL EMFDRV_SetDCBrushColor( PHYSDEV dev, COLORREF color )
{
EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*)dev;
EMRSELECTOBJECT emr;
DWORD index;
if (GetCurrentObject( physDev->hdc, OBJ_BRUSH ) != GetStockObject( DC_BRUSH )) return color;
if (physDev->dc_brush) DeleteObject( physDev->dc_brush );
if (!(physDev->dc_brush = CreateSolidBrush( color ))) return CLR_INVALID;
if (!(index = EMFDRV_CreateBrushIndirect(dev, physDev->dc_brush ))) return CLR_INVALID;
GDI_hdc_using_object( physDev->dc_brush, physDev->hdc );
emr.emr.iType = EMR_SELECTOBJECT;
emr.emr.nSize = sizeof(emr);
emr.ihObject = index;
return EMFDRV_WriteRecord( dev, &emr.emr ) ? color : CLR_INVALID;
}
/******************************************************************
* EMFDRV_SetDCPenColor
*/
COLORREF CDECL EMFDRV_SetDCPenColor( PHYSDEV dev, COLORREF color )
{
EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*)dev;
EMRSELECTOBJECT emr;
DWORD index;
LOGPEN logpen = { PS_SOLID, { 0, 0 }, color };
if (GetCurrentObject( physDev->hdc, OBJ_PEN ) != GetStockObject( DC_PEN )) return color;
if (physDev->dc_pen) DeleteObject( physDev->dc_pen );
if (!(physDev->dc_pen = CreatePenIndirect( &logpen ))) return CLR_INVALID;
if (!(index = EMFDRV_CreatePenIndirect(dev, physDev->dc_pen))) return CLR_INVALID;
GDI_hdc_using_object( physDev->dc_pen, physDev->hdc );
emr.emr.iType = EMR_SELECTOBJECT;
emr.emr.nSize = sizeof(emr);
emr.ihObject = index;
return EMFDRV_WriteRecord( dev, &emr.emr ) ? color : CLR_INVALID;
}
/******************************************************************
* EMFDRV_GdiComment

View File

@ -144,3 +144,13 @@ BOOL CDECL MFDRV_WidenPath( PHYSDEV dev )
{
return FALSE;
}
COLORREF CDECL MFDRV_SetDCBrushColor( PHYSDEV dev, COLORREF color )
{
return CLR_INVALID;
}
COLORREF CDECL MFDRV_SetDCPenColor( PHYSDEV dev, COLORREF color )
{
return CLR_INVALID;
}

View File

@ -118,8 +118,8 @@ static const DC_FUNCTIONS MFDRV_Funcs =
NULL, /* pSetBitmapBits */
MFDRV_SetBkColor, /* pSetBkColor */
MFDRV_SetBkMode, /* pSetBkMode */
NULL, /* pSetDCBrushColor*/
NULL, /* pSetDCPenColor*/
MFDRV_SetDCBrushColor, /* pSetDCBrushColor*/
MFDRV_SetDCPenColor, /* pSetDCPenColor*/
NULL, /* pSetDIBColorTable */
NULL, /* pSetDIBits */
MFDRV_SetDIBitsToDevice, /* pSetDIBitsToDevice */

View File

@ -126,6 +126,8 @@ extern HPALETTE CDECL MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL
extern UINT CDECL MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL primary) DECLSPEC_HIDDEN;
extern COLORREF CDECL MFDRV_SetBkColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN;
extern INT CDECL MFDRV_SetBkMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN;
extern COLORREF CDECL MFDRV_SetDCBrushColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN;
extern COLORREF CDECL MFDRV_SetDCPenColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN;
extern INT CDECL MFDRV_SetMapMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN;
extern DWORD CDECL MFDRV_SetMapperFlags( PHYSDEV dev, DWORD flags ) DECLSPEC_HIDDEN;
extern COLORREF CDECL MFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color ) DECLSPEC_HIDDEN;

View File

@ -37,6 +37,8 @@ static BOOL emr_processed = FALSE;
static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
static INT (WINAPI * pSetRelAbs)(HDC, INT);
static COLORREF (WINAPI *pSetDCBrushColor)(HDC,COLORREF);
static COLORREF (WINAPI *pSetDCPenColor)(HDC,COLORREF);
#define GDI_GET_PROC(func) \
p ## func = (void *)GetProcAddress(hGDI, #func); \
@ -54,6 +56,8 @@ static void init_function_pointers(void)
assert(hGDI);
GDI_GET_PROC(GetRelAbs);
GDI_GET_PROC(SetRelAbs);
GDI_GET_PROC(SetDCBrushColor);
GDI_GET_PROC(SetDCPenColor);
}
static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
@ -1031,6 +1035,21 @@ static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
0x00, 0x00
};
static const unsigned char MF_DCBRUSH_BITS[] =
{
0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00
};
static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
{
0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
@ -1257,6 +1276,50 @@ static const unsigned char EMF_BITBLT[] =
0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
};
static const unsigned char EMF_DCBRUSH_BITS[] =
{
0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00
};
/* For debugging or dumping the raw metafiles produced by
* new test functions.
@ -1674,6 +1737,58 @@ static void test_emf_BitBlt(void)
#undef BMP_DIM
}
static void test_emf_DCBrush(void)
{
HDC hdcMetafile;
HENHMETAFILE hMetafile;
HBRUSH hBrush;
HPEN hPen;
BOOL ret;
COLORREF color;
if (!pSetDCBrushColor || !pSetDCPenColor)
{
win_skip( "SetDCBrush/PenColor not supported\n" );
return;
}
hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
ok( color == 0, "SetDCPenColor returned %x\n", color );
Rectangle( hdcMetafile, 10, 10, 20, 20 );
color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
hMetafile = CloseEnhMetaFile(hdcMetafile);
ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
"emf_DC_Brush", FALSE ) != 0)
{
dump_emf_bits(hMetafile, "emf_DC_Brush");
dump_emf_records(hMetafile, "emf_DC_Brush");
}
ret = DeleteEnhMetaFile(hMetafile);
ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
ret = DeleteObject(hBrush);
ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
ret = DeleteObject(hPen);
ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
}
/* Test a blank metafile. May be used as a template for new tests. */
static void test_mf_Blank(void)
@ -1950,6 +2065,53 @@ static void test_mf_PatternBrush(void)
HeapFree (GetProcessHeap(), 0, orig_lb);
}
static void test_mf_DCBrush(void)
{
HDC hdcMetafile;
HMETAFILE hMetafile;
HBRUSH hBrush;
HPEN hPen;
BOOL ret;
COLORREF color;
if (!pSetDCBrushColor || !pSetDCPenColor)
{
win_skip( "SetDCBrush/PenColor not supported\n" );
return;
}
hdcMetafile = CreateMetaFileA(NULL);
ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
Rectangle( hdcMetafile, 10, 10, 20, 20 );
color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
hMetafile = CloseMetaFile(hdcMetafile);
ok( hMetafile != 0, "CloseMetaFile failed\n" );
if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
{
dump_mf_bits(hMetafile, "mf_DCBrush");
EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
}
ret = DeleteMetaFile(hMetafile);
ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
}
static void test_mf_ExtTextOut_on_path(void)
{
HDC hdcMetafile;
@ -2925,12 +3087,14 @@ START_TEST(metafile)
test_ExtTextOutScale();
test_SaveDC();
test_emf_BitBlt();
test_emf_DCBrush();
/* For win-format metafiles (mfdrv) */
test_mf_SaveDC();
test_mf_Blank();
test_mf_Graphics();
test_mf_PatternBrush();
test_mf_DCBrush();
test_CopyMetaFile();
test_SetMetaFileBits();
test_mf_ExtTextOut_on_path();