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