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_GdiComment( PHYSDEV dev, UINT bytes, const BYTE *buffer ) 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 BOOL EMFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn ) DECLSPEC_HIDDEN;
|
||||
extern BOOL EMFDRV_LineTo( PHYSDEV dev, INT x, INT y ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -855,3 +855,57 @@ no_bounds:
|
|||
HeapFree( GetProcessHeap(), 0, pemr );
|
||||
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, /* pGetTextFace */
|
||||
NULL, /* pGetTextMetrics */
|
||||
NULL, /* pGradientFill */
|
||||
EMFDRV_GradientFill, /* pGradientFill */
|
||||
EMFDRV_IntersectClipRect, /* pIntersectClipRect */
|
||||
EMFDRV_InvertRgn, /* pInvertRgn */
|
||||
EMFDRV_LineTo, /* pLineTo */
|
||||
|
|
|
@ -1424,6 +1424,44 @@ static const unsigned char EMF_POLYPOLYLINE_BITS[] =
|
|||
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
|
||||
* new test functions.
|
||||
*/
|
||||
|
@ -3599,6 +3637,50 @@ static void test_emf_PolyPolyline(void)
|
|||
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)
|
||||
{
|
||||
init_function_pointers();
|
||||
|
@ -3614,6 +3696,7 @@ START_TEST(metafile)
|
|||
test_emf_polybezier();
|
||||
test_emf_GetPath();
|
||||
test_emf_PolyPolyline();
|
||||
test_emf_GradientFill();
|
||||
|
||||
/* For win-format metafiles (mfdrv) */
|
||||
test_mf_SaveDC();
|
||||
|
|
Loading…
Reference in New Issue