diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c index 806f089c770..1a162601f38 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 d33bf884658..2620e389e45 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 02df7cfb05d..88c9581274c 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 79fdb267353..9a81afdfd45 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