Alexandre Julliard : winex11: Implement rectangular gradients using straight X11 calls.

Alexandre Julliard julliard at winehq.org
Wed Nov 30 14:19:20 CST 2011


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Nov 30 13:09:08 2011 +0100

winex11: Implement rectangular gradients using straight X11 calls.

---

 dlls/winex11.drv/graphics.c |  118 +++++++++++++++++++++++++++++++++++++++++++
 dlls/winex11.drv/init.c     |    2 +-
 dlls/winex11.drv/x11drv.h   |    2 +
 3 files changed, 121 insertions(+), 1 deletions(-)

diff --git a/dlls/winex11.drv/graphics.c b/dlls/winex11.drv/graphics.c
index 0abd593..88e9b0c 100644
--- a/dlls/winex11.drv/graphics.c
+++ b/dlls/winex11.drv/graphics.c
@@ -1494,6 +1494,124 @@ BOOL X11DRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillTy
 }
 
 /**********************************************************************
+ *          X11DRV_GradientFill
+ */
+BOOL X11DRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
+                          void *grad_array, ULONG ngrad, ULONG mode )
+{
+    X11DRV_PDEVICE *physdev = get_x11drv_dev( dev );
+    const GRADIENT_RECT *rect = grad_array;
+    TRIVERTEX v[2];
+    POINT pt[2];
+    unsigned int i;
+    XGCValues val;
+
+    /* 4, 8, and 16-bpp use dithering */
+    if (physdev->depth >= 4 && physdev->depth <= 16) goto fallback;
+
+    switch (mode)
+    {
+    case GRADIENT_FILL_RECT_H:
+        val.function   = GXcopy;
+        val.fill_style = FillSolid;
+        val.line_width = 1;
+        val.cap_style  = CapNotLast;
+        val.line_style = LineSolid;
+        wine_tsx11_lock();
+        XChangeGC( gdi_display, physdev->gc,
+                   GCFunction | GCLineWidth | GCLineStyle | GCCapStyle | GCFillStyle, &val );
+        wine_tsx11_unlock();
+
+	X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
+        for (i = 0; i < ngrad; i++, rect++)
+        {
+            int pos, x, dx;
+
+            v[0] = vert_array[rect->UpperLeft];
+            v[1] = vert_array[rect->LowerRight];
+            pt[0].x = v[0].x;
+            pt[0].y = v[0].y;
+            pt[1].x = v[1].x;
+            pt[1].y = v[1].y;
+            LPtoDP( dev->hdc, pt, 2 );
+            dx = pt[1].x - pt[0].x;
+            if (!dx) continue;
+            if (dx < 0)  /* swap the colors */
+            {
+                v[0] = vert_array[rect->LowerRight];
+                v[1] = vert_array[rect->UpperLeft];
+                dx = -dx;
+            }
+            for (x = 0, pos = min( pt[0].x, pt[1].x ); x < dx; x++, pos++)
+            {
+                COLORREF color = RGB( (v[0].Red   * (dx - x) + v[1].Red   * x) / dx / 256,
+                                      (v[0].Green * (dx - x) + v[1].Green * x) / dx / 256,
+                                      (v[0].Blue  * (dx - x) + v[1].Blue  * x) / dx / 256);
+                wine_tsx11_lock();
+                XSetForeground( gdi_display, physdev->gc, X11DRV_PALETTE_ToPhysical( physdev, color ));
+                XDrawLine( gdi_display, physdev->drawable, physdev->gc,
+                           physdev->dc_rect.left + pos, physdev->dc_rect.top + pt[0].y,
+                           physdev->dc_rect.left + pos, physdev->dc_rect.top + pt[1].y );
+                wine_tsx11_unlock();
+            }
+        }
+        X11DRV_UnlockDIBSection( physdev, TRUE );
+        return TRUE;
+
+    case GRADIENT_FILL_RECT_V:
+        val.function   = GXcopy;
+        val.fill_style = FillSolid;
+        val.line_width = 1;
+        val.cap_style  = CapNotLast;
+        val.line_style = LineSolid;
+        wine_tsx11_lock();
+        XChangeGC( gdi_display, physdev->gc,
+                   GCFunction | GCLineWidth | GCLineStyle | GCCapStyle | GCFillStyle, &val );
+        wine_tsx11_unlock();
+
+	X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
+        for (i = 0; i < ngrad; i++, rect++)
+        {
+            int pos, y, dy;
+
+            v[0] = vert_array[rect->UpperLeft];
+            v[1] = vert_array[rect->LowerRight];
+            pt[0].x = v[0].x;
+            pt[0].y = v[0].y;
+            pt[1].x = v[1].x;
+            pt[1].y = v[1].y;
+            LPtoDP( dev->hdc, pt, 2 );
+            dy = pt[1].y - pt[0].y;
+            if (!dy) continue;
+            if (dy < 0)  /* swap the colors */
+            {
+                v[0] = vert_array[rect->LowerRight];
+                v[1] = vert_array[rect->UpperLeft];
+                dy = -dy;
+            }
+            for (y = 0, pos = min( pt[0].y, pt[1].y ); y < dy; y++, pos++)
+            {
+                COLORREF color = RGB( (v[0].Red   * (dy - y) + v[1].Red   * y) / dy / 256,
+                                      (v[0].Green * (dy - y) + v[1].Green * y) / dy / 256,
+                                      (v[0].Blue  * (dy - y) + v[1].Blue  * y) / dy / 256);
+                wine_tsx11_lock();
+                XSetForeground( gdi_display, physdev->gc, X11DRV_PALETTE_ToPhysical( physdev, color ));
+                XDrawLine( gdi_display, physdev->drawable, physdev->gc,
+                           physdev->dc_rect.left + pt[0].x, physdev->dc_rect.top + pos,
+                           physdev->dc_rect.left + pt[1].x, physdev->dc_rect.top + pos );
+                wine_tsx11_unlock();
+            }
+        }
+        X11DRV_UnlockDIBSection( physdev, TRUE );
+        return TRUE;
+    }
+
+fallback:
+    dev = GET_NEXT_PHYSDEV( dev, pGradientFill );
+    return dev->funcs->pGradientFill( dev, vert_array, nvert, grad_array, ngrad, mode );
+}
+
+/**********************************************************************
  *          X11DRV_SetBkColor
  */
 COLORREF X11DRV_SetBkColor( PHYSDEV dev, COLORREF color )
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c
index 8d61b5b..8b3b951 100644
--- a/dlls/winex11.drv/init.c
+++ b/dlls/winex11.drv/init.c
@@ -527,7 +527,7 @@ static const struct gdi_dc_funcs x11drv_funcs =
     NULL,                               /* pGetTextExtentExPointI */
     NULL,                               /* pGetTextFace */
     X11DRV_GetTextMetrics,              /* pGetTextMetrics */
-    NULL,                               /* pGradientFill */
+    X11DRV_GradientFill,                /* pGradientFill */
     NULL,                               /* pIntersectClipRect */
     NULL,                               /* pInvertRgn */
     X11DRV_LineTo,                      /* pLineTo */
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index dbc0629..d90968d 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -203,6 +203,8 @@ extern UINT X11DRV_GetSystemPaletteEntries( PHYSDEV dev, UINT start, UINT count,
 extern BOOL X11DRV_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR str, INT count, INT maxExt,
                                          LPINT lpnFit, LPINT alpDx, LPSIZE size ) DECLSPEC_HIDDEN;
 extern BOOL X11DRV_GetTextMetrics(PHYSDEV dev, TEXTMETRICW *metrics) DECLSPEC_HIDDEN;
+extern BOOL X11DRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
+                                 void *grad_array, ULONG ngrad, ULONG mode ) DECLSPEC_HIDDEN;
 extern BOOL X11DRV_LineTo( PHYSDEV dev, INT x, INT y) DECLSPEC_HIDDEN;
 extern BOOL X11DRV_PaintRgn( PHYSDEV dev, HRGN hrgn ) DECLSPEC_HIDDEN;
 extern BOOL X11DRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop ) DECLSPEC_HIDDEN;




More information about the wine-cvs mailing list