Huw Davies : gdi32: Calculate AND and XOR masks corresponding to the current pen colour and rop2 .

Alexandre Julliard julliard at winehq.org
Thu Apr 7 11:16:42 CDT 2011


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

Author: Huw Davies <huw at codeweavers.com>
Date:   Thu Apr  7 13:48:39 2011 +0100

gdi32: Calculate AND and XOR masks corresponding to the current pen colour and rop2.

---

 dlls/gdi32/dibdrv/dc.c      |   15 +++++++++-
 dlls/gdi32/dibdrv/dibdrv.h  |    2 +
 dlls/gdi32/dibdrv/objects.c |   68 +++++++++++++++++++++++++++++++++++++++++++
 dlls/gdi32/gdi_private.h    |    2 +-
 4 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c
index 806f089..1a16260 100644
--- a/dlls/gdi32/dibdrv/dc.c
+++ b/dlls/gdi32/dibdrv/dc.c
@@ -128,6 +128,19 @@ static HBITMAP CDECL dibdrv_SelectBitmap( PHYSDEV dev, HBITMAP bitmap )
     return next->funcs->pSelectBitmap( next, bitmap );
 }
 
+/***********************************************************************
+ *           dibdrv_SetROP2
+ */
+static INT CDECL dibdrv_SetROP2( PHYSDEV dev, INT rop )
+{
+    PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSetROP2 );
+    dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
+
+    calc_and_xor_masks(rop, pdev->pen_color, &pdev->pen_and, &pdev->pen_xor);
+
+    return next->funcs->pSetROP2( next, rop );
+}
+
 const DC_FUNCTIONS dib_driver =
 {
     NULL,                               /* pAbortDoc */
@@ -228,7 +241,7 @@ const DC_FUNCTIONS dib_driver =
     NULL,                               /* pSetPixel */
     NULL,                               /* pSetPixelFormat */
     NULL,                               /* pSetPolyFillMode */
-    NULL,                               /* pSetROP2 */
+    dibdrv_SetROP2,                     /* pSetROP2 */
     NULL,                               /* pSetRelAbs */
     NULL,                               /* pSetStretchBltMode */
     NULL,                               /* pSetTextAlign */
diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h
index d33bf88..2620e38 100644
--- a/dlls/gdi32/dibdrv/dibdrv.h
+++ b/dlls/gdi32/dibdrv/dibdrv.h
@@ -35,3 +35,5 @@ typedef struct primitive_funcs
 extern const primitive_funcs funcs_8888 DECLSPEC_HIDDEN;
 extern const primitive_funcs funcs_32   DECLSPEC_HIDDEN;
 extern const primitive_funcs funcs_null DECLSPEC_HIDDEN;
+
+extern void calc_and_xor_masks(INT rop, DWORD color, DWORD *and, DWORD *xor) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c
index 02df7cf..88c9581 100644
--- a/dlls/gdi32/dibdrv/objects.c
+++ b/dlls/gdi32/dibdrv/objects.c
@@ -25,6 +25,70 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dib);
 
+/*
+ *
+ * Decompose the 16 ROP2s into an expression of the form
+ *
+ * D = (D & A) ^ X
+ *
+ * Where A and X depend only on P (and so can be precomputed).
+ *
+ *                                       A    X
+ *
+ * R2_BLACK         0                    0    0
+ * R2_NOTMERGEPEN   ~(D | P)            ~P   ~P
+ * R2_MASKNOTPEN    ~P & D              ~P    0
+ * R2_NOTCOPYPEN    ~P                   0   ~P
+ * R2_MASKPENNOT    P & ~D               P    P
+ * R2_NOT           ~D                   1    1
+ * R2_XORPEN        P ^ D                1    P
+ * R2_NOTMASKPEN    ~(P & D)             P    1
+ * R2_MASKPEN       P & D                P    0
+ * R2_NOTXORPEN     ~(P ^ D)             1   ~P
+ * R2_NOP           D                    1    0
+ * R2_MERGENOTPEN   ~P | D               P   ~P
+ * R2_COPYPEN       P                    0    P
+ * R2_MERGEPENNOT   P | ~D              ~P    1
+ * R2_MERGEPEN      P | D               ~P    P
+ * R2_WHITE         1                    0    1
+ *
+ */
+
+/* A = (P & A1) | (~P & A2) */
+#define ZERO {0, 0}
+#define ONE {0xffffffff, 0xffffffff}
+#define P {0xffffffff, 0}
+#define NOT_P {0, 0xffffffff}
+
+static const DWORD rop2_and_array[16][2] =
+{
+    ZERO, NOT_P, NOT_P, ZERO,
+    P,    ONE,   ONE,   P,
+    P,    ONE,   ONE,   P,
+    ZERO, NOT_P, NOT_P, ZERO
+};
+
+/* X = (P & X1) | (~P & X2) */
+static const DWORD rop2_xor_array[16][2] =
+{
+    ZERO, NOT_P, ZERO, NOT_P,
+    P,    ONE,   P,    ONE,
+    ZERO, NOT_P, ZERO, NOT_P,
+    P,    ONE,   P,    ONE
+};
+
+#undef NOT_P
+#undef P
+#undef ONE
+#undef ZERO
+
+void calc_and_xor_masks(INT rop, DWORD color, DWORD *and, DWORD *xor)
+{
+    /* NB The ROP2 codes start at one and the arrays are zero-based */
+    *and = (color & rop2_and_array[rop-1][0]) | ((~color) & rop2_and_array[rop-1][1]);
+    *xor = (color & rop2_xor_array[rop-1][0]) | ((~color) & rop2_xor_array[rop-1][1]);
+}
+
 /***********************************************************************
  *           dibdrv_SelectPen
  */
@@ -60,6 +124,7 @@ HPEN CDECL dibdrv_SelectPen( PHYSDEV dev, HPEN hpen )
         logpen.lopnColor = GetDCPenColor( dev->hdc );
 
     pdev->pen_color = pdev->dib.funcs->colorref_to_pixel(&pdev->dib, logpen.lopnColor);
+    calc_and_xor_masks(GetROP2(dev->hdc), pdev->pen_color, &pdev->pen_and, &pdev->pen_xor);
 
     pdev->defer |= DEFER_PEN;
 
@@ -86,7 +151,10 @@ COLORREF CDECL dibdrv_SetDCPenColor( PHYSDEV dev, COLORREF color )
     dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
 
     if (GetCurrentObject(dev->hdc, OBJ_PEN) == GetStockObject( DC_PEN ))
+    {
         pdev->pen_color = pdev->dib.funcs->colorref_to_pixel(&pdev->dib, color);
+        calc_and_xor_masks(GetROP2(dev->hdc), pdev->pen_color, &pdev->pen_and, &pdev->pen_xor);
+    }
 
     return next->funcs->pSetDCPenColor( next, color );
 }
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 79fdb26..9a81afd 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -100,7 +100,7 @@ typedef struct dibdrv_physdev
     DWORD defer;
 
     /* pen */
-    DWORD pen_color;
+    DWORD pen_color, pen_and, pen_xor;
 } dibdrv_physdev;
 
 #define DEFER_FORMAT     1




More information about the wine-cvs mailing list