gdiplus/metafile: Support linear gradient brushes in playback.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Vincent Povirk <vincent@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d045a5ea29
commit
394e15e39c
@ -256,6 +256,26 @@ typedef struct EmfPlusTextureBrushData
|
|||||||
BYTE OptionalData[1];
|
BYTE OptionalData[1];
|
||||||
} EmfPlusTextureBrushData;
|
} EmfPlusTextureBrushData;
|
||||||
|
|
||||||
|
typedef struct EmfPlusRectF
|
||||||
|
{
|
||||||
|
float X;
|
||||||
|
float Y;
|
||||||
|
float Width;
|
||||||
|
float Height;
|
||||||
|
} EmfPlusRectF;
|
||||||
|
|
||||||
|
typedef struct EmfPlusLinearGradientBrushData
|
||||||
|
{
|
||||||
|
DWORD BrushDataFlags;
|
||||||
|
INT WrapMode;
|
||||||
|
EmfPlusRectF RectF;
|
||||||
|
EmfPlusARGB StartColor;
|
||||||
|
EmfPlusARGB EndColor;
|
||||||
|
DWORD Reserved1;
|
||||||
|
DWORD Reserved2;
|
||||||
|
BYTE OptionalData[1];
|
||||||
|
} EmfPlusLinearGradientBrushData;
|
||||||
|
|
||||||
typedef struct EmfPlusBrush
|
typedef struct EmfPlusBrush
|
||||||
{
|
{
|
||||||
DWORD Version;
|
DWORD Version;
|
||||||
@ -264,6 +284,7 @@ typedef struct EmfPlusBrush
|
|||||||
EmfPlusSolidBrushData solid;
|
EmfPlusSolidBrushData solid;
|
||||||
EmfPlusHatchBrushData hatch;
|
EmfPlusHatchBrushData hatch;
|
||||||
EmfPlusTextureBrushData texture;
|
EmfPlusTextureBrushData texture;
|
||||||
|
EmfPlusLinearGradientBrushData lineargradient;
|
||||||
} BrushData;
|
} BrushData;
|
||||||
} EmfPlusBrush;
|
} EmfPlusBrush;
|
||||||
|
|
||||||
@ -372,14 +393,6 @@ typedef struct EmfPlusObject
|
|||||||
} ObjectData;
|
} ObjectData;
|
||||||
} EmfPlusObject;
|
} EmfPlusObject;
|
||||||
|
|
||||||
typedef struct EmfPlusRectF
|
|
||||||
{
|
|
||||||
float X;
|
|
||||||
float Y;
|
|
||||||
float Width;
|
|
||||||
float Height;
|
|
||||||
} EmfPlusRectF;
|
|
||||||
|
|
||||||
typedef struct EmfPlusPointR7
|
typedef struct EmfPlusPointR7
|
||||||
{
|
{
|
||||||
BYTE X;
|
BYTE X;
|
||||||
@ -2011,7 +2024,10 @@ static GpStatus metafile_deserialize_brush(const BYTE *record_data, UINT data_si
|
|||||||
{
|
{
|
||||||
static const UINT header_size = FIELD_OFFSET(EmfPlusBrush, BrushData);
|
static const UINT header_size = FIELD_OFFSET(EmfPlusBrush, BrushData);
|
||||||
EmfPlusBrush *data = (EmfPlusBrush *)record_data;
|
EmfPlusBrush *data = (EmfPlusBrush *)record_data;
|
||||||
|
EmfPlusTransformMatrix *transform = NULL;
|
||||||
|
DWORD brushflags;
|
||||||
GpStatus status;
|
GpStatus status;
|
||||||
|
UINT offset;
|
||||||
|
|
||||||
*brush = NULL;
|
*brush = NULL;
|
||||||
|
|
||||||
@ -2035,11 +2051,9 @@ static GpStatus metafile_deserialize_brush(const BYTE *record_data, UINT data_si
|
|||||||
break;
|
break;
|
||||||
case BrushTypeTextureFill:
|
case BrushTypeTextureFill:
|
||||||
{
|
{
|
||||||
UINT offset = header_size + FIELD_OFFSET(EmfPlusTextureBrushData, OptionalData);
|
|
||||||
EmfPlusTransformMatrix *transform = NULL;
|
|
||||||
DWORD brushflags;
|
|
||||||
GpImage *image;
|
GpImage *image;
|
||||||
|
|
||||||
|
offset = header_size + FIELD_OFFSET(EmfPlusTextureBrushData, OptionalData);
|
||||||
if (data_size <= offset)
|
if (data_size <= offset)
|
||||||
return InvalidParameter;
|
return InvalidParameter;
|
||||||
|
|
||||||
@ -2063,6 +2077,80 @@ static GpStatus metafile_deserialize_brush(const BYTE *record_data, UINT data_si
|
|||||||
GdipDisposeImage(image);
|
GdipDisposeImage(image);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case BrushTypeLinearGradient:
|
||||||
|
{
|
||||||
|
GpLineGradient *gradient = NULL;
|
||||||
|
GpPointF startpoint, endpoint;
|
||||||
|
UINT position_count = 0;
|
||||||
|
|
||||||
|
offset = header_size + FIELD_OFFSET(EmfPlusLinearGradientBrushData, OptionalData);
|
||||||
|
if (data_size <= offset)
|
||||||
|
return InvalidParameter;
|
||||||
|
|
||||||
|
brushflags = data->BrushData.lineargradient.BrushDataFlags;
|
||||||
|
if ((brushflags & BrushDataPresetColors) && (brushflags & (BrushDataBlendFactorsH | BrushDataBlendFactorsV)))
|
||||||
|
return InvalidParameter;
|
||||||
|
|
||||||
|
if (brushflags & BrushDataTransform)
|
||||||
|
{
|
||||||
|
if (data_size <= offset + sizeof(EmfPlusTransformMatrix))
|
||||||
|
return InvalidParameter;
|
||||||
|
transform = (EmfPlusTransformMatrix *)(record_data + offset);
|
||||||
|
offset += sizeof(EmfPlusTransformMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (brushflags & (BrushDataPresetColors | BrushDataBlendFactorsH | BrushDataBlendFactorsV))
|
||||||
|
{
|
||||||
|
if (data_size <= offset + sizeof(DWORD)) /* Number of factors/preset colors. */
|
||||||
|
return InvalidParameter;
|
||||||
|
position_count = *(DWORD *)(record_data + offset);
|
||||||
|
offset += sizeof(DWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (brushflags & BrushDataPresetColors)
|
||||||
|
{
|
||||||
|
if (data_size != offset + position_count * (sizeof(float) + sizeof(EmfPlusARGB)))
|
||||||
|
return InvalidParameter;
|
||||||
|
}
|
||||||
|
else if (brushflags & BrushDataBlendFactorsH)
|
||||||
|
{
|
||||||
|
if (data_size != offset + position_count * 2 * sizeof(float))
|
||||||
|
return InvalidParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
startpoint.X = data->BrushData.lineargradient.RectF.X;
|
||||||
|
startpoint.Y = data->BrushData.lineargradient.RectF.Y;
|
||||||
|
endpoint.X = startpoint.X + data->BrushData.lineargradient.RectF.Width;
|
||||||
|
endpoint.Y = startpoint.Y + data->BrushData.lineargradient.RectF.Height;
|
||||||
|
|
||||||
|
status = GdipCreateLineBrush(&startpoint, &endpoint, data->BrushData.lineargradient.StartColor,
|
||||||
|
data->BrushData.lineargradient.EndColor, data->BrushData.lineargradient.WrapMode, &gradient);
|
||||||
|
if (status == Ok)
|
||||||
|
{
|
||||||
|
if (transform)
|
||||||
|
status = GdipSetLineTransform(gradient, (const GpMatrix *)transform);
|
||||||
|
|
||||||
|
if (status == Ok)
|
||||||
|
{
|
||||||
|
if (brushflags & BrushDataPresetColors)
|
||||||
|
status = GdipSetLinePresetBlend(gradient, (ARGB *)(record_data + offset +
|
||||||
|
position_count * sizeof(REAL)), (REAL *)(record_data + offset), position_count);
|
||||||
|
else if (brushflags & BrushDataBlendFactorsH)
|
||||||
|
status = GdipSetLineBlend(gradient, (REAL *)(record_data + offset + position_count * sizeof(REAL)),
|
||||||
|
(REAL *)(record_data + offset), position_count);
|
||||||
|
|
||||||
|
if (brushflags & BrushDataIsGammaCorrected)
|
||||||
|
FIXME("BrushDataIsGammaCorrected is not handled.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == Ok)
|
||||||
|
*brush = (GpBrush *)gradient;
|
||||||
|
else
|
||||||
|
GdipDeleteBrush((GpBrush *)gradient);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
FIXME("brush type %u is not supported.\n", data->Type);
|
FIXME("brush type %u is not supported.\n", data->Type);
|
||||||
return NotImplemented;
|
return NotImplemented;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user