diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index 1d7c0fe3062..ff21b8ed242 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -1036,6 +1036,26 @@ static GpStatus METAFILE_PrepareBrushData(GDIPCONST GpBrush *brush, DWORD *size) case BrushTypeHatchFill: *size = FIELD_OFFSET(EmfPlusBrush, BrushData) + sizeof(EmfPlusHatchBrushData); break; + case BrushTypeLinearGradient: + { + BOOL ignore_xform; + GpLineGradient *gradient = (GpLineGradient*)brush; + + *size = FIELD_OFFSET(EmfPlusBrush, BrushData.lineargradient.OptionalData); + + GdipIsMatrixIdentity(&gradient->transform, &ignore_xform); + if (!ignore_xform) + *size += sizeof(gradient->transform); + + if (gradient->pblendcount > 1 && gradient->pblendcolor && gradient->pblendpos) + *size += sizeof(DWORD) + gradient->pblendcount * + (sizeof(*gradient->pblendcolor) + sizeof(*gradient->pblendpos)); + else if (gradient->blendcount > 1 && gradient->blendfac && gradient->blendpos) + *size += sizeof(DWORD) + gradient->blendcount * + (sizeof(*gradient->blendfac) + sizeof(*gradient->blendpos)); + + break; + } default: FIXME("unsupported brush type: %d\n", brush->bt); return NotImplemented; @@ -1065,6 +1085,67 @@ static void METAFILE_FillBrushData(GDIPCONST GpBrush *brush, EmfPlusBrush *data) data->BrushData.hatch.BackColor = hatch->backcol; break; } + case BrushTypeLinearGradient: + { + BYTE *cursor; + BOOL ignore_xform; + GpLineGradient *gradient = (GpLineGradient*)brush; + + data->BrushData.lineargradient.BrushDataFlags = 0; + data->BrushData.lineargradient.WrapMode = gradient->wrap; + data->BrushData.lineargradient.RectF.X = gradient->rect.X; + data->BrushData.lineargradient.RectF.Y = gradient->rect.Y; + data->BrushData.lineargradient.RectF.Width = gradient->rect.Width; + data->BrushData.lineargradient.RectF.Height = gradient->rect.Height; + data->BrushData.lineargradient.StartColor = gradient->startcolor; + data->BrushData.lineargradient.EndColor = gradient->endcolor; + data->BrushData.lineargradient.Reserved1 = gradient->startcolor; + data->BrushData.lineargradient.Reserved2 = gradient->endcolor; + + if (gradient->gamma) + data->BrushData.lineargradient.BrushDataFlags |= BrushDataIsGammaCorrected; + + cursor = &data->BrushData.lineargradient.OptionalData[0]; + + GdipIsMatrixIdentity(&gradient->transform, &ignore_xform); + if (!ignore_xform) + { + data->BrushData.lineargradient.BrushDataFlags |= BrushDataTransform; + memcpy(cursor, &gradient->transform, sizeof(gradient->transform)); + cursor += sizeof(gradient->transform); + } + + if (gradient->pblendcount > 1 && gradient->pblendcolor && gradient->pblendpos) + { + const DWORD count = gradient->pblendcount; + + data->BrushData.lineargradient.BrushDataFlags |= BrushDataPresetColors; + + memcpy(cursor, &count, sizeof(count)); + cursor += sizeof(count); + + memcpy(cursor, gradient->pblendpos, count * sizeof(*gradient->pblendpos)); + cursor += count * sizeof(*gradient->pblendpos); + + memcpy(cursor, gradient->pblendcolor, count * sizeof(*gradient->pblendcolor)); + } + else if (gradient->blendcount > 1 && gradient->blendfac && gradient->blendpos) + { + const DWORD count = gradient->blendcount; + + data->BrushData.lineargradient.BrushDataFlags |= BrushDataBlendFactorsH; + + memcpy(cursor, &count, sizeof(count)); + cursor += sizeof(count); + + memcpy(cursor, gradient->blendpos, count * sizeof(*gradient->blendpos)); + cursor += count * sizeof(*gradient->blendpos); + + memcpy(cursor, gradient->blendfac, count * sizeof(*gradient->blendfac)); + } + + break; + } default: FIXME("unsupported brush type: %d\n", brush->bt); } diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index bba44d15dae..29113fc3a05 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -3273,14 +3273,14 @@ static void test_fillregion(void) static const emfplus_record lineargradient_records[] = { { EMR_HEADER }, { EmfPlusRecordTypeHeader }, - { EmfPlusRecordTypeObject, ObjectTypeBrush << 8, 1 }, - { EmfPlusRecordTypeFillRects, 0x4000, 1 }, - { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 1, 1 }, - { EmfPlusRecordTypeFillRects, 0x4000, 1 }, - { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 2, 1 }, - { EmfPlusRecordTypeFillRects, 0x4000, 1 }, - { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 3, 1 }, - { EmfPlusRecordTypeFillRects, 0x4000, 1 }, + { EmfPlusRecordTypeObject, ObjectTypeBrush << 8, 0, 1 }, + { EmfPlusRecordTypeFillRects, 0x4000, 0, 1 }, + { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 1, 0, 1 }, + { EmfPlusRecordTypeFillRects, 0x4000, 0, 1 }, + { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 2 }, + { EmfPlusRecordTypeFillRects, 0x4000 }, + { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 3 }, + { EmfPlusRecordTypeFillRects, 0x4000 }, { EmfPlusRecordTypeEndOfFile }, { EMR_EOF }, { 0 } @@ -3342,16 +3342,16 @@ static void test_lineargradient(void) expect(Ok, stat); stat = GdipFillRectangles(graphics, vertbrush, &vertrect, 1); - todo_wine expect(Ok, stat); + expect(Ok, stat); stat = GdipFillRectangles(graphics, horizbrush, &horizrect, 1); - todo_wine expect(Ok, stat); + expect(Ok, stat); stat = GdipFillRectangles(graphics, blendbrush, &blendrect, 1); - todo_wine expect(Ok, stat); + expect(Ok, stat); stat = GdipFillRectangles(graphics, presetbrush, &presetrect, 1); - todo_wine expect(Ok, stat); + expect(Ok, stat); stat = GdipDeleteGraphics(graphics); graphics = NULL; @@ -3391,7 +3391,7 @@ static void test_lineargradient(void) /* Verify custom blend gradient fill. */ stat = GdipBitmapGetPixel(bitmap, 10, 50, &color); expect(Ok, stat); - todo_wine expect(0xffff0000, color); + expect(0xffff0000, color); stat = GdipBitmapGetPixel(bitmap, 18, 50, &color); expect(Ok, stat); @@ -3400,11 +3400,11 @@ static void test_lineargradient(void) /* Verify preset color gradient fill. */ stat = GdipBitmapGetPixel(bitmap, 50, 50, &color); expect(Ok, stat); - todo_wine expect(0xffff0000, color); + expect(0xffff0000, color); stat = GdipBitmapGetPixel(bitmap, 50, 60, &color); expect(Ok, stat); - todo_wine expect(0xff00ff00, color); + expect(0xff00ff00, color); GdipDeleteBrush(vertbrush); GdipDeleteBrush(horizbrush);