[PATCH] gdi32: Improve GdiGradientFill

Hirofumi Katayama katayama.hirofumi.mz at gmail.com
Sat Feb 21 23:51:58 CST 2009


See attachment.
-------------- next part --------------
From 28b65e323c6a6ff0966d738b2f0c0de0fa222d2c Mon Sep 17 00:00:00 2001
From: Hirofumi Katayama <katayama.hirofumi.mz at gmail.com>
Date: Sat, 21 Feb 2009 20:49:59 +0900
Subject: [PATCH] gdi32: Improve GdiGradientFill

---
 dlls/gdi32/painting.c |  608 ++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 496 insertions(+), 112 deletions(-)

diff --git a/dlls/gdi32/painting.c b/dlls/gdi32/painting.c
index c3d8310..3798281 100644
--- a/dlls/gdi32/painting.c
+++ b/dlls/gdi32/painting.c
@@ -1234,152 +1234,536 @@ POINT *GDI_Bezier( const POINT *Points, INT count, INT *nPtsOut )
 }
 
 /******************************************************************************
- *           GdiGradientFill   (GDI32.@)
+ *           bayer_dithering
  *
- *  FIXME: we don't support the Alpha channel properly
+ *  FIXME: improve dithering
+ */
+static inline BYTE bayer_dithering(INT x, INT y, BYTE b)
+{
+    static const BYTE bayer_x_16_plus_8[] = 
+    {
+          8, 136,  40, 168, 
+        200,  72, 232, 104, 
+         56, 184,  24, 152, 
+        248, 120, 216,  88, 
+    };
+    if (bayer_x_16_plus_8[(y & 3) * 4 + (x & 3)] <= b)
+        return 255;
+    else
+        return 0;
+}
+
+/******************************************************************************
+ *           GdiGradientFill   (GDI32.@)
  */
 BOOL WINAPI GdiGradientFill( HDC hdc, TRIVERTEX *vert_array, ULONG nvert,
                           void * grad_array, ULONG ngrad, ULONG mode )
 {
-  unsigned int i;
-
-  TRACE("vert_array:0x%08lx nvert:%d grad_array:0x%08lx ngrad:%d\n",
+    ULONG i;
+    BITMAPINFO bi;
+    HBITMAP hbm;
+    LPBYTE pbBits, pb;
+    GRADIENT_RECT *rect;
+    GRADIENT_TRIANGLE *tri;
+    TRIVERTEX *v1, *v2, *v3;
+    COLOR16 r1, g1, b1, a1, r2, g2, b2, a2;
+    COLOR16 dr, dg, db, da;
+    INT dx, dy, x1, y1, x2;
+    INT xMin, yMin, xMax, yMax;
+    INT cx, cy, widthbytes;
+    HDC hdcMem;
+    HGDIOBJ hbmOld;
+    BITMAP bm;
+    BOOL fDithering;
+
+    TRACE("vert_array:0x%08lx nvert:%d grad_array:0x%08lx ngrad:%d\n",
         (long)vert_array, nvert, (long)grad_array, ngrad);
+    
+    if (nvert == 0 || ngrad == 0)
+        return FALSE;
 
-  switch(mode) 
+    xMin = xMax = vert_array[0].x;
+    yMin = yMax = vert_array[0].y;
+    for(i = 1; i < nvert; i++)
+    {
+        if (vert_array[i].x < xMin)
+            xMin = vert_array[i].x;
+        else if (xMax < vert_array[i].x)
+            xMax = vert_array[i].x;
+        if (vert_array[i].y < yMin)
+            yMin = vert_array[i].y;
+        else if (yMax < vert_array[i].y)
+            yMax = vert_array[i].y;
+    }
+    cx = xMax - xMin;
+    cy = yMax - yMin;
+    ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
+    bi.bmiHeader.biSize     = sizeof(BITMAPINFOHEADER);
+    bi.bmiHeader.biWidth    = cx;
+    bi.bmiHeader.biHeight   = -cy;
+    bi.bmiHeader.biPlanes   = 1;
+    bi.bmiHeader.biBitCount = 32;
+    hbm = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (VOID **)&pbBits,
+                           NULL, 0);
+    if (hbm == NULL)
+        return FALSE;
+
+    hdcMem = CreateCompatibleDC(NULL);
+    if (hdcMem == NULL)
+    {
+        DeleteObject(hbm);
+        return FALSE;
+    }
+
+    if (GetObject(GetCurrentObject(hdc, OBJ_BITMAP), sizeof(BITMAP), &bm))
+        fDithering = (bm.bmBitsPixel <= 8);
+    else
+        fDithering = FALSE;
+
+    widthbytes = cx * 4;
+
+    hbmOld = SelectObject(hdcMem, hbm);
+    BitBlt(hdcMem, 0, 0, cx, cy, hdc, xMin, yMin, SRCCOPY);
+
+    switch(mode)
     {
     case GRADIENT_FILL_RECT_H:
-      for(i = 0; i < ngrad; i++) 
+        for(i = 0; i < ngrad; i++)
         {
-          GRADIENT_RECT *rect = ((GRADIENT_RECT *)grad_array) + i;
-          TRIVERTEX *v1 = vert_array + rect->UpperLeft;
-          TRIVERTEX *v2 = vert_array + rect->LowerRight;
-          int y1 = v1->y < v2->y ? v1->y : v2->y;
-          int y2 = v2->y > v1->y ? v2->y : v1->y;
-          int x, dx;
-          if (v1->x > v2->x)
+            rect = (GRADIENT_RECT *)grad_array + i;
+            v1 = vert_array + rect->UpperLeft;
+            v2 = vert_array + rect->LowerRight;
+            if (v1->x > v2->x)
+                { TRIVERTEX *t = v2; v2 = v1; v1 = t; }
+            /* v1->x <= v2->x */
+            dx = v2->x - v1->x; dy = v2->y - v1->y;
+            r1 = v1->Red;
+            g1 = v1->Green;
+            b1 = v1->Blue;
+            a1 = v1->Alpha;
+            if (dx != 0)
+            {
+                dr = (v2->Red - v1->Red) / dx;
+                dg = (v2->Green - v1->Green) / dx;
+                db = (v2->Blue - v1->Blue) / dx;
+                da = (v2->Alpha - v1->Alpha) / dx;
+            }
+            if (dy < 0)
+            {
+                pb = pbBits + (v2->y - yMin) * widthbytes + (v1->x - xMin) * 4;
+                dy = -dy;
+            }
+            else
             {
-              TRIVERTEX *t = v2;
-              v2 = v1;
-              v1 = t;
+                pb = pbBits + (v1->y - yMin) * widthbytes + (v1->x - xMin) * 4;
             }
-          dx = v2->x - v1->x;
-          for (x = 0; x < dx; x++)
+            if (fDithering)
             {
-              POINT pts[2];
-              HPEN hPen, hOldPen;
-              
-              hPen = CreatePen( PS_SOLID, 1, RGB(
-                  (v1->Red   * (dx - x) + v2->Red   * x) / dx >> 8,
-                  (v1->Green * (dx - x) + v2->Green * x) / dx >> 8,
-                  (v1->Blue  * (dx - x) + v2->Blue  * x) / dx >> 8));
-              hOldPen = SelectObject( hdc, hPen );
-              pts[0].x = v1->x + x;
-              pts[0].y = y1;
-              pts[1].x = v1->x + x;
-              pts[1].y = y2;
-              Polyline( hdc, &pts[0], 2 );
-              DeleteObject( SelectObject(hdc, hOldPen ) );
+                for(x1 = 0; x1 < dx; x1++)
+                {
+                    for(y1 = 0; y1 < dy; y1++)
+                    {
+                        *pb++ = bayer_dithering(x1, y1, b1 >> 8);
+                        *pb++ = bayer_dithering(x1, y1, g1 >> 8);
+                        *pb++ = bayer_dithering(x1, y1, r1 >> 8);
+                        pb++;
+                        pb += widthbytes - 4;
+                    }
+                    r1 += dr;
+                    g1 += dg;
+                    b1 += db;
+                    pb -= dy * widthbytes - 4;
+                }
+            }
+            else
+            {
+                for(x1 = 0; x1 < dx; x1++)
+                {
+                    for(y1 = 0; y1 < dy; y1++)
+                    {
+                        *pb++ = b1 >> 8;
+                        *pb++ = g1 >> 8;
+                        *pb++ = r1 >> 8;
+                        *pb++ = a1 >> 8;
+                        pb += widthbytes - 4;
+                    }
+                    r1 += dr;
+                    g1 += dg;
+                    b1 += db;
+                    a1 += da;
+                    pb -= dy * widthbytes - 4;
+                }
             }
         }
-      break;
+        break;
+
     case GRADIENT_FILL_RECT_V:
-      for(i = 0; i < ngrad; i++) 
+        for(i = 0; i < ngrad; i++)
         {
-          GRADIENT_RECT *rect = ((GRADIENT_RECT *)grad_array) + i;
-          TRIVERTEX *v1 = vert_array + rect->UpperLeft;
-          TRIVERTEX *v2 = vert_array + rect->LowerRight;
-          int x1 = v1->x < v2->x ? v1->x : v2->x;
-          int x2 = v2->x > v1->x ? v2->x : v1->x;
-          int y, dy;
-          if (v1->y > v2->y)
+            rect = (GRADIENT_RECT *)grad_array + i;
+            v1 = vert_array + rect->UpperLeft;
+            v2 = vert_array + rect->LowerRight;
+            if (v1->y > v2->y)
+                { TRIVERTEX *t = v2; v2 = v1; v1 = t; }
+            /* v1->y <= v2->y */
+            dx = v2->x - v1->x; dy = v2->y - v1->y;
+            r1 = v1->Red;
+            g1 = v1->Green;
+            b1 = v1->Blue;
+            a1 = v1->Alpha;
+            if (dy != 0)
+            {
+                dr = (v2->Red - v1->Red) / dy;
+                dg = (v2->Green - v1->Green) / dy;
+                db = (v2->Blue - v1->Blue) / dy;
+                da = (v2->Alpha - v1->Alpha) / dy;
+            }
+            if (dx < 0)
+            {
+                pb = pbBits + (v1->y - yMin) * widthbytes + (v2->x - xMin) * 4;
+                dx = -dx;
+            }
+            else
+            {
+                pb = pbBits + (v1->y - yMin) * widthbytes + (v1->x - xMin) * 4;
+            }
+            if (fDithering)
             {
-              TRIVERTEX *t = v2;
-              v2 = v1;
-              v1 = t;
+                for(y1 = 0; y1 < dy; y1++)
+                {
+                    for(x1 = 0; x1 < dx; x1++)
+                    {
+                        *pb++ = bayer_dithering(x1, y1, b1 >> 8);
+                        *pb++ = bayer_dithering(x1, y1, g1 >> 8);
+                        *pb++ = bayer_dithering(x1, y1, r1 >> 8);
+                        pb++;
+                    }
+                    r1 += dr;
+                    g1 += dg;
+                    b1 += db;
+                    pb -= dx * 4;
+                    pb += widthbytes;
+                }
             }
-          dy = v2->y - v1->y;
-          for (y = 0; y < dy; y++)
+            else
             {
-              POINT pts[2];
-              HPEN hPen, hOldPen;
-              
-              hPen = CreatePen( PS_SOLID, 1, RGB(
-                  (v1->Red   * (dy - y) + v2->Red   * y) / dy >> 8,
-                  (v1->Green * (dy - y) + v2->Green * y) / dy >> 8,
-                  (v1->Blue  * (dy - y) + v2->Blue  * y) / dy >> 8));
-              hOldPen = SelectObject( hdc, hPen );
-              pts[0].x = x1;
-              pts[0].y = v1->y + y;
-              pts[1].x = x2;
-              pts[1].y = v1->y + y;
-              Polyline( hdc, &pts[0], 2 );
-              DeleteObject( SelectObject(hdc, hOldPen ) );
+                for(y1 = 0; y1 < dy; y1++)
+                {
+                    for(x1 = 0; x1 < dx; x1++)
+                    {
+                        *pb++ = b1 >> 8;
+                        *pb++ = g1 >> 8;
+                        *pb++ = r1 >> 8;
+                        *pb++ = a1 >> 8;
+                    }
+                    r1 += dr;
+                    g1 += dg;
+                    b1 += db;
+                    a1 += da;
+                    pb -= dx * 4;
+                    pb += widthbytes;
+                }
             }
         }
-      break;
+        break;
+
     case GRADIENT_FILL_TRIANGLE:
-      for (i = 0; i < ngrad; i++)  
+        for(i = 0; i < ngrad; i++)
         {
-          GRADIENT_TRIANGLE *tri = ((GRADIENT_TRIANGLE *)grad_array) + i;
-          TRIVERTEX *v1 = vert_array + tri->Vertex1;
-          TRIVERTEX *v2 = vert_array + tri->Vertex2;
-          TRIVERTEX *v3 = vert_array + tri->Vertex3;
-          int y, dy;
-          
-          if (v1->y > v2->y)
-            { TRIVERTEX *t = v1; v1 = v2; v2 = t; }
-          if (v2->y > v3->y)
+            tri = (GRADIENT_TRIANGLE *)grad_array + i;
+            v1 = vert_array + tri->Vertex1;
+            v2 = vert_array + tri->Vertex2;
+            v3 = vert_array + tri->Vertex3;
+
+            if (v1->y > v2->y)
+                { TRIVERTEX *t = v1; v1 = v2; v2 = t; }
+            if (v2->y > v3->y)
             {
-              TRIVERTEX *t = v2; v2 = v3; v3 = t;
-              if (v1->y > v2->y)
-                { t = v1; v1 = v2; v2 = t; }
+                TRIVERTEX *t = v2; v2 = v3; v3 = t;
+                if (v1->y > v2->y)
+                    { t = v1; v1 = v2; v2 = t; }
             }
-          /* v1->y <= v2->y <= v3->y */
+            /* v1->y <= v2->y <= v3->y */
 
-          dy = v3->y - v1->y;
-          for (y = 0; y < dy; y++)
+            if (fDithering)
             {
-              /* v1->y <= y < v3->y */
-              TRIVERTEX *v = y < (v2->y - v1->y) ? v1 : v3;
-              /* (v->y <= y < v2->y) || (v2->y <= y < v->y) */
-              int dy2 = v2->y - v->y;
-              int y2 = y + v1->y - v->y;
-
-              int x1 = (v3->x     * y  + v1->x     * (dy  - y )) / dy;
-              int x2 = (v2->x     * y2 + v-> x     * (dy2 - y2)) / dy2;
-              int r1 = (v3->Red   * y  + v1->Red   * (dy  - y )) / dy;
-              int r2 = (v2->Red   * y2 + v-> Red   * (dy2 - y2)) / dy2;
-              int g1 = (v3->Green * y  + v1->Green * (dy  - y )) / dy;
-              int g2 = (v2->Green * y2 + v-> Green * (dy2 - y2)) / dy2;
-              int b1 = (v3->Blue  * y  + v1->Blue  * (dy  - y )) / dy;
-              int b2 = (v2->Blue  * y2 + v-> Blue  * (dy2 - y2)) / dy2;
-               
-              int x;
-	      if (x1 < x2)
+                for(y1 = v1->y; y1 < v2->y; y1++)
                 {
-                  int dx = x2 - x1;
-                  for (x = 0; x < dx; x++)
-                    SetPixel (hdc, x + x1, y + v1->y, RGB(
-                      (r1 * (dx - x) + r2 * x) / dx >> 8,
-                      (g1 * (dx - x) + g2 * x) / dx >> 8,
-                      (b1 * (dx - x) + b2 * x) / dx >> 8));
+                    if (v2->x < v3->x)
+                    {
+                        x1 = v1->x + (v2->x - v1->x) * (y1 - v1->y) / (v2->y - v1->y);
+                        r1 = v1->Red   + (v2->Red   - v1->Red)   * (y1 - v1->y) / (v2->y - v1->y);
+                        g1 = v1->Green + (v2->Green - v1->Green) * (y1 - v1->y) / (v2->y - v1->y);
+                        b1 = v1->Blue  + (v2->Blue  - v1->Blue)  * (y1 - v1->y) / (v2->y - v1->y);
+                        x2 = v1->x + (v3->x - v1->x) * (y1 - v1->y) / (v3->y - v1->y);
+                        r2 = v1->Red   + (v3->Red   - v1->Red)   * (y1 - v1->y) / (v3->y - v1->y);
+                        g2 = v1->Green + (v3->Green - v1->Green) * (y1 - v1->y) / (v3->y - v1->y);
+                        b2 = v1->Blue  + (v3->Blue  - v1->Blue)  * (y1 - v1->y) / (v3->y - v1->y);
+                        dx = x2 - x1;
+                        if (dx != 0)
+                        {
+                            db = (b2 - b1) / dx;
+                            dg = (g2 - g1) / dx;
+                            dr = (r2 - r1) / dx;
+                        }
+                        pb = pbBits + (x1 - xMin) * 4 + (y1 - yMin) * widthbytes;
+                        for( ; x1 < x2; x1++)
+                        {
+                            *pb++ = bayer_dithering(x1, y1, b1 >> 8);
+                            *pb++ = bayer_dithering(x1, y1, g1 >> 8);
+                            *pb++ = bayer_dithering(x1, y1, r1 >> 8);
+                            pb++;
+                            b1 += db;
+                            g1 += dg;
+                            r1 += dr;
+                        }
+                    }
+                    else
+                    {
+                        x1 = v1->x + (v3->x - v1->x) * (y1 - v1->y) / (v3->y - v1->y);
+                        r1 = v1->Red   + (v3->Red   - v1->Red)   * (y1 - v1->y) / (v3->y - v1->y);
+                        g1 = v1->Green + (v3->Green - v1->Green) * (y1 - v1->y) / (v3->y - v1->y);
+                        b1 = v1->Blue  + (v3->Blue  - v1->Blue)  * (y1 - v1->y) / (v3->y - v1->y);
+                        x2 = v1->x + (v2->x - v1->x) * (y1 - v1->y) / (v2->y - v1->y);
+                        r2 = v1->Red   + (v2->Red   - v1->Red)   * (y1 - v1->y) / (v2->y - v1->y);
+                        g2 = v1->Green + (v2->Green - v1->Green) * (y1 - v1->y) / (v2->y - v1->y);
+                        b2 = v1->Blue  + (v2->Blue  - v1->Blue)  * (y1 - v1->y) / (v2->y - v1->y);
+                        dx = x2 - x1;
+                        if (dx != 0)
+                        {
+                            db = (b2 - b1) / dx;
+                            dg = (g2 - g1) / dx;
+                            dr = (r2 - r1) / dx;
+                        }
+                        pb = pbBits + (x1 - xMin) * 4 + (y1 - yMin) * widthbytes;
+                        for( ; x1 < x2; x1++)
+                        {
+                            *pb++ = bayer_dithering(x1, y1, b1 >> 8);
+                            *pb++ = bayer_dithering(x1, y1, g1 >> 8);
+                            *pb++ = bayer_dithering(x1, y1, r1 >> 8);
+                            pb++;
+                            b1 += db;
+                            g1 += dg;
+                            r1 += dr;
+                        }
+                    }
                 }
-              else
+                for(y1 = v2->y; y1 < v3->y; y1++)
                 {
-                  int dx = x1 - x2;
-                  for (x = 0; x < dx; x++)
-                    SetPixel (hdc, x + x2, y + v1->y, RGB(
-                      (r2 * (dx - x) + r1 * x) / dx >> 8,
-                      (g2 * (dx - x) + g1 * x) / dx >> 8,
-                      (b2 * (dx - x) + b1 * x) / dx >> 8));
+                    if (v2->x < v3->x)
+                    {
+                        x1 = v2->x + (v3->x - v2->x) * (y1 - v2->y) / (v3->y - v2->y);
+                        r1 = v2->Red   + (v3->Red   - v2->Red)   * (y1 - v2->y) / (v3->y - v2->y);
+                        g1 = v2->Green + (v3->Green - v2->Green) * (y1 - v2->y) / (v3->y - v2->y);
+                        b1 = v2->Blue  + (v3->Blue  - v2->Blue)  * (y1 - v2->y) / (v3->y - v2->y);
+                        x2 = v1->x + (v3->x - v1->x) * (y1 - v1->y) / (v3->y - v1->y);
+                        r2 = v1->Red   + (v3->Red   - v1->Red)   * (y1 - v1->y) / (v3->y - v1->y);
+                        g2 = v1->Green + (v3->Green - v1->Green) * (y1 - v1->y) / (v3->y - v1->y);
+                        b2 = v1->Blue  + (v3->Blue  - v1->Blue)  * (y1 - v1->y) / (v3->y - v1->y);
+                        dx = x2 - x1;
+                        if (dx != 0)
+                        {
+                            db = (b2 - b1) / dx;
+                            dg = (g2 - g1) / dx;
+                            dr = (r2 - r1) / dx;
+                        }
+                        pb = pbBits + (x1 - xMin) * 4 + (y1 - yMin) * widthbytes;
+                        for( ; x1 < x2; x1++)
+                        {
+                            *pb++ = bayer_dithering(x1, y1, b1 >> 8);
+                            *pb++ = bayer_dithering(x1, y1, g1 >> 8);
+                            *pb++ = bayer_dithering(x1, y1, r1 >> 8);
+                            pb++;
+                            b1 += db;
+                            g1 += dg;
+                            r1 += dr;
+                        }
+                    }
+                    else
+                    {
+                        x1 = v1->x + (v3->x - v1->x) * (y1 - v1->y) / (v3->y - v1->y);
+                        r1 = v1->Red   + (v3->Red   - v1->Red)   * (y1 - v1->y) / (v3->y - v1->y);
+                        g1 = v1->Green + (v3->Green - v1->Green) * (y1 - v1->y) / (v3->y - v1->y);
+                        b1 = v1->Blue  + (v3->Blue  - v1->Blue)  * (y1 - v1->y) / (v3->y - v1->y);
+                        x2 = v2->x + (v3->x - v2->x) * (y1 - v2->y) / (v3->y - v2->y);
+                        r2 = v2->Red   + (v3->Red   - v2->Red)   * (y1 - v2->y) / (v3->y - v2->y);
+                        g2 = v2->Green + (v3->Green - v2->Green) * (y1 - v2->y) / (v3->y - v2->y);
+                        b2 = v2->Blue  + (v3->Blue  - v2->Blue)  * (y1 - v2->y) / (v3->y - v2->y);
+                        dx = x2 - x1;
+                        if (dx != 0)
+                        {
+                            db = (b2 - b1) / dx;
+                            dg = (g2 - g1) / dx;
+                            dr = (r2 - r1) / dx;
+                        }
+                        pb = pbBits + (x1 - xMin) * 4 + (y1 - yMin) * widthbytes;
+                        for( ; x1 < x2; x1++)
+                        {
+                            *pb++ = bayer_dithering(x1, y1, b1 >> 8);
+                            *pb++ = bayer_dithering(x1, y1, g1 >> 8);
+                            *pb++ = bayer_dithering(x1, y1, r1 >> 8);
+                            pb++;
+                            b1 += db;
+                            g1 += dg;
+                            r1 += dr;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for(y1 = v1->y; y1 < v2->y; y1++)
+                {
+                    if (v2->x < v3->x)
+                    {
+                        x1 = v1->x + (v2->x - v1->x) * (y1 - v1->y) / (v2->y - v1->y);
+                        r1 = v1->Red   + (v2->Red   - v1->Red)   * (y1 - v1->y) / (v2->y - v1->y);
+                        g1 = v1->Green + (v2->Green - v1->Green) * (y1 - v1->y) / (v2->y - v1->y);
+                        b1 = v1->Blue  + (v2->Blue  - v1->Blue)  * (y1 - v1->y) / (v2->y - v1->y);
+                        a1 = v1->Alpha + (v2->Alpha - v1->Alpha) * (y1 - v1->y) / (v2->y - v1->y);
+                        x2 = v1->x + (v3->x - v1->x) * (y1 - v1->y) / (v3->y - v1->y);
+                        r2 = v1->Red   + (v3->Red   - v1->Red)   * (y1 - v1->y) / (v3->y - v1->y);
+                        g2 = v1->Green + (v3->Green - v1->Green) * (y1 - v1->y) / (v3->y - v1->y);
+                        b2 = v1->Blue  + (v3->Blue  - v1->Blue)  * (y1 - v1->y) / (v3->y - v1->y);
+                        a2 = v1->Alpha + (v3->Alpha - v1->Alpha) * (y1 - v1->y) / (v3->y - v1->y);
+                        dx = x2 - x1;
+                        if (dx != 0)
+                        {
+                            db = (b2 - b1) / dx;
+                            dg = (g2 - g1) / dx;
+                            dr = (r2 - r1) / dx;
+                            da = (a2 - a1) / dx;
+                        }
+                        pb = pbBits + (x1 - xMin) * 4 + (y1 - yMin) * widthbytes;
+                        for( ; x1 < x2; x1++)
+                        {
+                            *pb++ = b1 >> 8;
+                            *pb++ = g1 >> 8;
+                            *pb++ = r1 >> 8;
+                            *pb++ = a1 >> 8;
+                            b1 += db;
+                            g1 += dg;
+                            r1 += dr;
+                            a1 += da;
+                        }
+                    }
+                    else
+                    {
+                        x1 = v1->x + (v3->x - v1->x) * (y1 - v1->y) / (v3->y - v1->y);
+                        r1 = v1->Red   + (v3->Red   - v1->Red)   * (y1 - v1->y) / (v3->y - v1->y);
+                        g1 = v1->Green + (v3->Green - v1->Green) * (y1 - v1->y) / (v3->y - v1->y);
+                        b1 = v1->Blue  + (v3->Blue  - v1->Blue)  * (y1 - v1->y) / (v3->y - v1->y);
+                        a1 = v1->Alpha + (v3->Alpha - v1->Alpha) * (y1 - v1->y) / (v3->y - v1->y);
+                        x2 = v1->x + (v2->x - v1->x) * (y1 - v1->y) / (v2->y - v1->y);
+                        r2 = v1->Red   + (v2->Red   - v1->Red)   * (y1 - v1->y) / (v2->y - v1->y);
+                        g2 = v1->Green + (v2->Green - v1->Green) * (y1 - v1->y) / (v2->y - v1->y);
+                        b2 = v1->Blue  + (v2->Blue  - v1->Blue)  * (y1 - v1->y) / (v2->y - v1->y);
+                        a2 = v1->Alpha + (v2->Alpha - v1->Alpha) * (y1 - v1->y) / (v2->y - v1->y);
+                        dx = x2 - x1;
+                        if (dx != 0)
+                        {
+                            db = (b2 - b1) / dx;
+                            dg = (g2 - g1) / dx;
+                            dr = (r2 - r1) / dx;
+                            da = (a2 - a1) / dx;
+                        }
+                        pb = pbBits + (x1 - xMin) * 4 + (y1 - yMin) * widthbytes;
+                        for( ; x1 < x2; x1++)
+                        {
+                            *pb++ = b1 >> 8;
+                            *pb++ = g1 >> 8;
+                            *pb++ = r1 >> 8;
+                            *pb++ = a1 >> 8;
+                            b1 += db;
+                            g1 += dg;
+                            r1 += dr;
+                            a1 += da;
+                        }
+                    }
+                }
+                for(y1 = v2->y; y1 < v3->y; y1++)
+                {
+                    if (v2->x < v3->x)
+                    {
+                        x1 = v2->x + (v3->x - v2->x) * (y1 - v2->y) / (v3->y - v2->y);
+                        r1 = v2->Red   + (v3->Red   - v2->Red)   * (y1 - v2->y) / (v3->y - v2->y);
+                        g1 = v2->Green + (v3->Green - v2->Green) * (y1 - v2->y) / (v3->y - v2->y);
+                        b1 = v2->Blue  + (v3->Blue  - v2->Blue)  * (y1 - v2->y) / (v3->y - v2->y);
+                        a1 = v2->Alpha + (v3->Alpha - v2->Alpha) * (y1 - v2->y) / (v3->y - v2->y);
+                        x2 = v1->x + (v3->x - v1->x) * (y1 - v1->y) / (v3->y - v1->y);
+                        r2 = v1->Red   + (v3->Red   - v1->Red)   * (y1 - v1->y) / (v3->y - v1->y);
+                        g2 = v1->Green + (v3->Green - v1->Green) * (y1 - v1->y) / (v3->y - v1->y);
+                        b2 = v1->Blue  + (v3->Blue  - v1->Blue)  * (y1 - v1->y) / (v3->y - v1->y);
+                        a2 = v1->Alpha + (v3->Alpha - v1->Alpha) * (y1 - v1->y) / (v3->y - v1->y);
+                        dx = x2 - x1;
+                        if (dx != 0)
+                        {
+                            db = (b2 - b1) / dx;
+                            dg = (g2 - g1) / dx;
+                            dr = (r2 - r1) / dx;
+                            da = (a2 - a1) / dx;
+                        }
+                        pb = pbBits + (x1 - xMin) * 4 + (y1 - yMin) * widthbytes;
+                        for( ; x1 < x2; x1++)
+                        {
+                            *pb++ = b1 >> 8;
+                            *pb++ = g1 >> 8;
+                            *pb++ = r1 >> 8;
+                            *pb++ = a1 >> 8;
+                            b1 += db;
+                            g1 += dg;
+                            r1 += dr;
+                            a1 += da;
+                        }
+                    }
+                    else
+                    {
+                        x1 = v1->x + (v3->x - v1->x) * (y1 - v1->y) / (v3->y - v1->y);
+                        r1 = v1->Red   + (v3->Red   - v1->Red)   * (y1 - v1->y) / (v3->y - v1->y);
+                        g1 = v1->Green + (v3->Green - v1->Green) * (y1 - v1->y) / (v3->y - v1->y);
+                        b1 = v1->Blue  + (v3->Blue  - v1->Blue)  * (y1 - v1->y) / (v3->y - v1->y);
+                        a1 = v1->Alpha + (v3->Alpha - v1->Alpha) * (y1 - v1->y) / (v3->y - v1->y);
+                        x2 = v2->x + (v3->x - v2->x) * (y1 - v2->y) / (v3->y - v2->y);
+                        r2 = v2->Red   + (v3->Red   - v2->Red)   * (y1 - v2->y) / (v3->y - v2->y);
+                        g2 = v2->Green + (v3->Green - v2->Green) * (y1 - v2->y) / (v3->y - v2->y);
+                        b2 = v2->Blue  + (v3->Blue  - v2->Blue)  * (y1 - v2->y) / (v3->y - v2->y);
+                        a2 = v2->Alpha + (v3->Alpha - v2->Alpha) * (y1 - v2->y) / (v3->y - v2->y);
+                        dx = x2 - x1;
+                        if (dx != 0)
+                        {
+                            db = (b2 - b1) / dx;
+                            dg = (g2 - g1) / dx;
+                            dr = (r2 - r1) / dx;
+                            da = (a2 - a1) / dx;
+                        }
+                        pb = pbBits + (x1 - xMin) * 4 + (y1 - yMin) * widthbytes;
+                        for( ; x1 < x2; x1++)
+                        {
+                            *pb++ = b1 >> 8;
+                            *pb++ = g1 >> 8;
+                            *pb++ = r1 >> 8;
+                            *pb++ = a1 >> 8;
+                            b1 += db;
+                            g1 += dg;
+                            r1 += dr;
+                            a1 += da;
+                        }
+                    }
                 }
             }
         }
-      break;
+        break;
+
     default:
-      return FALSE;
-  }
+        SelectObject(hdcMem, hbmOld);
+        DeleteObject(hbm);
+        DeleteDC(hdcMem);
+        return FALSE;
+    }
 
-  return TRUE;
+    BitBlt(hdc, xMin, yMin, cx, cy, hdcMem, 0, 0, SRCCOPY);
+    SelectObject(hdcMem, hbmOld);
+    DeleteObject(hbm);
+    DeleteDC(hdcMem);
+    return TRUE;
 }
-- 
1.6.1.3


More information about the wine-patches mailing list