gdi32: Implement recording of the GradientFill EMF record.
Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
4161f5120b
commit
ac0959cdf6
@ -75,6 +75,8 @@ extern BOOL EMFDRV_FlattenPath( PHYSDEV dev ) DECLSPEC_HIDDEN;
|
|||||||
extern BOOL EMFDRV_FrameRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush, INT width, INT height ) DECLSPEC_HIDDEN;
|
extern BOOL EMFDRV_FrameRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush, INT width, INT height ) DECLSPEC_HIDDEN;
|
||||||
extern BOOL EMFDRV_GdiComment( PHYSDEV dev, UINT bytes, const BYTE *buffer ) DECLSPEC_HIDDEN;
|
extern BOOL EMFDRV_GdiComment( PHYSDEV dev, UINT bytes, const BYTE *buffer ) DECLSPEC_HIDDEN;
|
||||||
extern INT EMFDRV_GetDeviceCaps( PHYSDEV dev, INT cap ) DECLSPEC_HIDDEN;
|
extern INT EMFDRV_GetDeviceCaps( PHYSDEV dev, INT cap ) DECLSPEC_HIDDEN;
|
||||||
|
extern BOOL EMFDRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
|
||||||
|
void *grad_array, ULONG ngrad, ULONG mode ) DECLSPEC_HIDDEN;
|
||||||
extern INT EMFDRV_IntersectClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN;
|
extern INT EMFDRV_IntersectClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN;
|
||||||
extern BOOL EMFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn ) DECLSPEC_HIDDEN;
|
extern BOOL EMFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn ) DECLSPEC_HIDDEN;
|
||||||
extern BOOL EMFDRV_LineTo( PHYSDEV dev, INT x, INT y ) DECLSPEC_HIDDEN;
|
extern BOOL EMFDRV_LineTo( PHYSDEV dev, INT x, INT y ) DECLSPEC_HIDDEN;
|
||||||
|
@ -855,3 +855,57 @@ no_bounds:
|
|||||||
HeapFree( GetProcessHeap(), 0, pemr );
|
HeapFree( GetProcessHeap(), 0, pemr );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* EMFDRV_GradientFill
|
||||||
|
*/
|
||||||
|
BOOL EMFDRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
|
||||||
|
void *grad_array, ULONG ngrad, ULONG mode )
|
||||||
|
{
|
||||||
|
EMRGRADIENTFILL *emr;
|
||||||
|
ULONG i, pt, size, num_pts = ngrad * (mode == GRADIENT_FILL_TRIANGLE ? 3 : 2);
|
||||||
|
const ULONG *pts = (const ULONG *)grad_array;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
size = FIELD_OFFSET(EMRGRADIENTFILL, Ver[nvert]) + num_pts * sizeof(pts[0]);
|
||||||
|
|
||||||
|
emr = HeapAlloc( GetProcessHeap(), 0, size );
|
||||||
|
if (!emr) return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < num_pts; i++)
|
||||||
|
{
|
||||||
|
pt = pts[i];
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
emr->rclBounds.left = emr->rclBounds.right = vert_array[pt].x;
|
||||||
|
emr->rclBounds.top = emr->rclBounds.bottom = vert_array[pt].y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (vert_array[pt].x < emr->rclBounds.left)
|
||||||
|
emr->rclBounds.left = vert_array[pt].x;
|
||||||
|
else if (vert_array[pt].x > emr->rclBounds.right)
|
||||||
|
emr->rclBounds.right = vert_array[pt].x;
|
||||||
|
if (vert_array[pt].y < emr->rclBounds.top)
|
||||||
|
emr->rclBounds.top = vert_array[pt].y;
|
||||||
|
else if (vert_array[pt].y > emr->rclBounds.bottom)
|
||||||
|
emr->rclBounds.bottom = vert_array[pt].y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emr->rclBounds.right--;
|
||||||
|
emr->rclBounds.bottom--;
|
||||||
|
|
||||||
|
emr->emr.iType = EMR_GRADIENTFILL;
|
||||||
|
emr->emr.nSize = size;
|
||||||
|
emr->nVer = nvert;
|
||||||
|
emr->nTri = ngrad;
|
||||||
|
emr->ulMode = mode;
|
||||||
|
memcpy( emr->Ver, vert_array, nvert * sizeof(vert_array[0]) );
|
||||||
|
memcpy( emr->Ver + nvert, pts, num_pts * sizeof(pts[0]) );
|
||||||
|
|
||||||
|
EMFDRV_UpdateBBox( dev, &emr->rclBounds );
|
||||||
|
ret = EMFDRV_WriteRecord( dev, &emr->emr );
|
||||||
|
HeapFree( GetProcessHeap(), 0, emr );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -92,7 +92,7 @@ static const struct gdi_dc_funcs EMFDRV_Funcs =
|
|||||||
NULL, /* pGetTextExtentExPointI */
|
NULL, /* pGetTextExtentExPointI */
|
||||||
NULL, /* pGetTextFace */
|
NULL, /* pGetTextFace */
|
||||||
NULL, /* pGetTextMetrics */
|
NULL, /* pGetTextMetrics */
|
||||||
NULL, /* pGradientFill */
|
EMFDRV_GradientFill, /* pGradientFill */
|
||||||
EMFDRV_IntersectClipRect, /* pIntersectClipRect */
|
EMFDRV_IntersectClipRect, /* pIntersectClipRect */
|
||||||
EMFDRV_InvertRgn, /* pInvertRgn */
|
EMFDRV_InvertRgn, /* pInvertRgn */
|
||||||
EMFDRV_LineTo, /* pLineTo */
|
EMFDRV_LineTo, /* pLineTo */
|
||||||
|
@ -1424,6 +1424,44 @@ static const unsigned char EMF_POLYPOLYLINE_BITS[] =
|
|||||||
0x14, 0x00, 0x00, 0x00
|
0x14, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const unsigned char EMF_GRADIENTFILL_BITS[] =
|
||||||
|
{
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||||
|
0x2b, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00,
|
||||||
|
0x31, 0x29, 0x00, 0x00, 0xa3, 0x2a, 0x00, 0x00,
|
||||||
|
0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
|
||||||
|
0x0c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x40, 0x05, 0x00, 0x00, 0x46, 0x03, 0x00, 0x00,
|
||||||
|
0xda, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x15, 0x3c, 0x07, 0x00,
|
||||||
|
0xcb, 0x82, 0x04, 0x00, 0x76, 0x00, 0x00, 0x00,
|
||||||
|
0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x0a, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00,
|
||||||
|
0x35, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xff, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80,
|
||||||
|
0xc8, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
|
||||||
|
0xb4, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00,
|
||||||
|
0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xf0, 0xde,
|
||||||
|
0x2c, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
|
||||||
|
0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
|
||||||
|
0x90, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00,
|
||||||
|
0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x00, 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
|
/* For debugging or dumping the raw metafiles produced by
|
||||||
* new test functions.
|
* new test functions.
|
||||||
*/
|
*/
|
||||||
@ -3599,6 +3637,50 @@ static void test_emf_PolyPolyline(void)
|
|||||||
DeleteEnhMetaFile(hemf);
|
DeleteEnhMetaFile(hemf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_emf_GradientFill(void)
|
||||||
|
{
|
||||||
|
HDC mf;
|
||||||
|
HENHMETAFILE hemf;
|
||||||
|
TRIVERTEX v[] =
|
||||||
|
{
|
||||||
|
{ 1, 10, 0xff00, 0x8000, 0x0000, 0x8001 },
|
||||||
|
{ 200, 210, 0x0000, 0x0000, 0xff00, 0xff00 },
|
||||||
|
{ 180, 190, 0x1234, 0x5678, 0x9abc, 0xdef0 },
|
||||||
|
{ 300, 310, 0xff00, 0xff00, 0xff00, 0x0000 },
|
||||||
|
{ 400, 410, 0xff00, 0xff00, 0xff00, 0x0000 }
|
||||||
|
};
|
||||||
|
GRADIENT_TRIANGLE tri[] = { { 0, 1, 2 }, { 3, 1, 0 } };
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
mf = CreateEnhMetaFileA( GetDC( 0 ), NULL, NULL, NULL );
|
||||||
|
ok( mf != 0, "CreateEnhMetaFileA error %d\n", GetLastError() );
|
||||||
|
|
||||||
|
/* Don't test the GRADIENT_FILL_RECT_ modes since a Windows bug
|
||||||
|
* means it allocates three mesh indicies rather than two per
|
||||||
|
* rectangle. This results in uninitialised values being written
|
||||||
|
* to the EMF which is rather difficult to test against.
|
||||||
|
*
|
||||||
|
* Note also that the final vertex here is not required, yet it is
|
||||||
|
* written to the EMF, but is not considered in the bounds
|
||||||
|
* calculation.
|
||||||
|
*/
|
||||||
|
ret = GdiGradientFill( mf, v, sizeof(v) / sizeof(v[0]), tri, sizeof(tri) / sizeof(tri[0]),
|
||||||
|
GRADIENT_FILL_TRIANGLE );
|
||||||
|
ok( ret, "GradientFill\n" );
|
||||||
|
|
||||||
|
hemf = CloseEnhMetaFile( mf );
|
||||||
|
ok( hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError() );
|
||||||
|
|
||||||
|
if (compare_emf_bits( hemf, EMF_GRADIENTFILL_BITS, sizeof(EMF_GRADIENTFILL_BITS),
|
||||||
|
"emf_GradientFill", FALSE ) != 0)
|
||||||
|
{
|
||||||
|
dump_emf_bits( hemf, "emf_GradientFill" );
|
||||||
|
dump_emf_records( hemf, "emf_GradientFill" );
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteEnhMetaFile( hemf );
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(metafile)
|
START_TEST(metafile)
|
||||||
{
|
{
|
||||||
init_function_pointers();
|
init_function_pointers();
|
||||||
@ -3614,6 +3696,7 @@ START_TEST(metafile)
|
|||||||
test_emf_polybezier();
|
test_emf_polybezier();
|
||||||
test_emf_GetPath();
|
test_emf_GetPath();
|
||||||
test_emf_PolyPolyline();
|
test_emf_PolyPolyline();
|
||||||
|
test_emf_GradientFill();
|
||||||
|
|
||||||
/* For win-format metafiles (mfdrv) */
|
/* For win-format metafiles (mfdrv) */
|
||||||
test_mf_SaveDC();
|
test_mf_SaveDC();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user