Vincent Povirk : gdiplus: Add a software implementation of line gradient brushes.

Alexandre Julliard julliard at winehq.org
Mon Jan 24 11:07:30 CST 2011


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Fri Jan 21 15:48:45 2011 -0600

gdiplus: Add a software implementation of line gradient brushes.

---

 dlls/gdiplus/graphics.c |   70 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 284847e..de1e28f 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -256,6 +256,15 @@ static ARGB blend_colors(ARGB start, ARGB end, REAL position)
 {
     ARGB result=0;
     ARGB i;
+    INT a1, a2, a3;
+
+    a1 = (start >> 24) & 0xff;
+    a2 = (end >> 24) & 0xff;
+
+    a3 = (int)(a1*(1.0f - position)+a2*(position));
+
+    result |= a3 << 24;
+
     for (i=0xff; i<=0xff0000; i = i << 8)
         result |= (int)((start&i)*(1.0f - position)+(end&i)*(position))&i;
     return result;
@@ -493,6 +502,7 @@ static INT brush_can_fill_pixels(GpBrush *brush)
     {
     case BrushTypeSolidColor:
     case BrushTypeHatchFill:
+    case BrushTypeLinearGradient:
         return 1;
     default:
         return 0;
@@ -539,6 +549,66 @@ static GpStatus brush_fill_pixels(GpGraphics *graphics, GpBrush *brush,
 
         return Ok;
     }
+    case BrushTypeLinearGradient:
+    {
+        GpLineGradient *fill = (GpLineGradient*)brush;
+        GpPointF draw_points[3], line_points[3];
+        GpStatus stat;
+        static const GpRectF box_1 = { 0.0, 0.0, 1.0, 1.0 };
+        GpMatrix *world_to_gradient; /* FIXME: Store this in the brush? */
+        int x, y;
+
+        draw_points[0].X = fill_area->X;
+        draw_points[0].Y = fill_area->Y;
+        draw_points[1].X = fill_area->X+1;
+        draw_points[1].Y = fill_area->Y;
+        draw_points[2].X = fill_area->X;
+        draw_points[2].Y = fill_area->Y+1;
+
+        /* Transform the points to a co-ordinate space where X is the point's
+         * position in the gradient, 0.0 being the start point and 1.0 the
+         * end point. */
+        stat = GdipTransformPoints(graphics, CoordinateSpaceWorld,
+            CoordinateSpaceDevice, draw_points, 3);
+
+        if (stat == Ok)
+        {
+            line_points[0] = fill->startpoint;
+            line_points[1] = fill->endpoint;
+            line_points[2].X = fill->startpoint.X + (fill->startpoint.Y - fill->endpoint.Y);
+            line_points[2].Y = fill->startpoint.Y + (fill->endpoint.X - fill->startpoint.X);
+
+            stat = GdipCreateMatrix3(&box_1, line_points, &world_to_gradient);
+        }
+
+        if (stat == Ok)
+        {
+            stat = GdipInvertMatrix(world_to_gradient);
+
+            if (stat == Ok)
+                stat = GdipTransformMatrixPoints(world_to_gradient, draw_points, 3);
+
+            GdipDeleteMatrix(world_to_gradient);
+        }
+
+        if (stat == Ok)
+        {
+            REAL x_delta = draw_points[1].X - draw_points[0].X;
+            REAL y_delta = draw_points[2].X - draw_points[0].X;
+
+            for (y=0; y<fill_area->Height; y++)
+            {
+                for (x=0; x<fill_area->Width; x++)
+                {
+                    REAL pos = draw_points[0].X + x * x_delta + y * y_delta;
+
+                    argb_pixels[x + y*cdwStride] = blend_line_gradient(fill, pos);
+                }
+            }
+        }
+
+        return stat;
+    }
     default:
         return NotImplemented;
     }




More information about the wine-cvs mailing list