[PATCH 2/4] gdiplus: Add LinearGradient brush object serialization.

Shawn M. Chapla schapla at codeweavers.com
Wed Jul 22 22:08:10 CDT 2020


Signed-off-by: Shawn M. Chapla <schapla at codeweavers.com>
---
 dlls/gdiplus/metafile.c       | 81 +++++++++++++++++++++++++++++++++++
 dlls/gdiplus/tests/metafile.c | 30 ++++++-------
 2 files changed, 96 insertions(+), 15 deletions(-)

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);
-- 
2.28.0.rc1




More information about the wine-devel mailing list