Vincent Povirk : gdiplus: Store preset blends in linear gradient brushes.

Alexandre Julliard julliard at winehq.org
Tue Sep 15 17:47:56 CDT 2009


Module: wine
Branch: master
Commit: 8bdabe3a1840755187ed7fad4146603fcb63ba2d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=8bdabe3a1840755187ed7fad4146603fcb63ba2d

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Mon Sep 14 16:21:50 2009 -0500

gdiplus: Store preset blends in linear gradient brushes.

---

 dlls/gdiplus/brush.c           |   80 +++++++++++++++++++++++++++++++++-------
 dlls/gdiplus/gdiplus_private.h |    3 +
 2 files changed, 69 insertions(+), 14 deletions(-)

diff --git a/dlls/gdiplus/brush.c b/dlls/gdiplus/brush.c
index 8b18684..1425ab7 100644
--- a/dlls/gdiplus/brush.c
+++ b/dlls/gdiplus/brush.c
@@ -116,7 +116,7 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
         }
         case BrushTypeLinearGradient:{
             GpLineGradient *dest, *src;
-            INT count;
+            INT count, pcount;
 
             dest = GdipAlloc(sizeof(GpLineGradient));
             if(!dest)    return OutOfMemory;
@@ -130,11 +130,20 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
             count = dest->blendcount;
             dest->blendfac = GdipAlloc(count * sizeof(REAL));
             dest->blendpos = GdipAlloc(count * sizeof(REAL));
+            pcount = dest->pblendcount;
+            if (pcount)
+            {
+                dest->pblendcolor = GdipAlloc(pcount * sizeof(ARGB));
+                dest->pblendpos = GdipAlloc(pcount * sizeof(REAL));
+            }
 
-            if (!dest->blendfac || !dest->blendpos)
+            if (!dest->blendfac || !dest->blendpos ||
+                (pcount && (!dest->pblendcolor || !dest->pblendpos)))
             {
                 GdipFree(dest->blendfac);
                 GdipFree(dest->blendpos);
+                GdipFree(dest->pblendcolor);
+                GdipFree(dest->pblendpos);
                 DeleteObject(dest->brush.gdibrush);
                 GdipFree(dest);
                 return OutOfMemory;
@@ -143,6 +152,12 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
             memcpy(dest->blendfac, src->blendfac, count * sizeof(REAL));
             memcpy(dest->blendpos, src->blendpos, count * sizeof(REAL));
 
+            if (pcount)
+            {
+                memcpy(dest->pblendcolor, src->pblendcolor, pcount * sizeof(ARGB));
+                memcpy(dest->pblendpos, src->pblendpos, pcount * sizeof(REAL));
+            }
+
             *clone = &dest->brush;
             break;
         }
@@ -289,6 +304,10 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint,
     (*line)->blendfac[0] = 1.0f;
     (*line)->blendpos[0] = 1.0f;
 
+    (*line)->pblendcolor = NULL;
+    (*line)->pblendpos = NULL;
+    (*line)->pblendcount = 0;
+
     return Ok;
 }
 
@@ -866,6 +885,8 @@ GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush *brush)
         case BrushTypeLinearGradient:
             GdipFree(((GpLineGradient*)brush)->blendfac);
             GdipFree(((GpLineGradient*)brush)->blendpos);
+            GdipFree(((GpLineGradient*)brush)->pblendcolor);
+            GdipFree(((GpLineGradient*)brush)->pblendpos);
             break;
         case BrushTypeTextureFill:
             GdipDeleteMatrix(((GpTexture*)brush)->transform);
@@ -1574,34 +1595,65 @@ GpStatus WINGDIPAPI GdipSetLineLinearBlend(GpLineGradient *brush, REAL focus,
 GpStatus WINGDIPAPI GdipSetLinePresetBlend(GpLineGradient *brush,
     GDIPCONST ARGB *blend, GDIPCONST REAL* positions, INT count)
 {
-    static int calls;
+    ARGB *new_color;
+    REAL *new_pos;
+    TRACE("(%p,%p,%p,%i)\n", brush, blend, positions, count);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if (!brush || !blend || !positions || count < 2 ||
+        positions[0] != 0.0f || positions[count-1] != 1.0f)
+    {
+        return InvalidParameter;
+    }
 
-    return NotImplemented;
+    new_color = GdipAlloc(count * sizeof(ARGB));
+    new_pos = GdipAlloc(count * sizeof(REAL));
+    if (!new_color || !new_pos)
+    {
+        GdipFree(new_color);
+        GdipFree(new_pos);
+        return OutOfMemory;
+    }
+
+    memcpy(new_color, blend, sizeof(ARGB) * count);
+    memcpy(new_pos, positions, sizeof(REAL) * count);
+
+    GdipFree(brush->pblendcolor);
+    GdipFree(brush->pblendpos);
+
+    brush->pblendcolor = new_color;
+    brush->pblendpos = new_pos;
+    brush->pblendcount = count;
+
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipGetLinePresetBlend(GpLineGradient *brush,
     ARGB *blend, REAL* positions, INT count)
 {
-    static int calls;
+    if (!brush || !blend || !positions || count < 2)
+        return InvalidParameter;
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if (brush->pblendcount == 0)
+        return GenericError;
 
-    return NotImplemented;
+    if (count < brush->pblendcount)
+        return InsufficientBuffer;
+
+    memcpy(blend, brush->pblendcolor, sizeof(ARGB) * brush->pblendcount);
+    memcpy(positions, brush->pblendpos, sizeof(REAL) * brush->pblendcount);
+
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipGetLinePresetBlendCount(GpLineGradient *brush,
     INT *count)
 {
-    static int calls;
+    if (!brush || !count)
+        return InvalidParameter;
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    *count = brush->pblendcount;
 
-    return NotImplemented;
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipResetLineTransform(GpLineGradient *brush)
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index c95f3ff..02c03dc 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -166,6 +166,9 @@ struct GpLineGradient{
     REAL* blendfac;  /* blend factors */
     REAL* blendpos;  /* blend positions */
     INT blendcount;
+    ARGB* pblendcolor; /* preset blend colors */
+    REAL* pblendpos; /* preset blend positions */
+    INT pblendcount;
 };
 
 struct GpTexture{




More information about the wine-cvs mailing list