diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c index 78248ddf8ac..9c2aca4a2f8 100644 --- a/dlls/gdi32/dibdrv/dc.c +++ b/dlls/gdi32/dibdrv/dc.c @@ -137,6 +137,7 @@ static INT CDECL dibdrv_SetROP2( PHYSDEV dev, INT rop ) dibdrv_physdev *pdev = get_dibdrv_pdev(dev); calc_and_xor_masks(rop, pdev->pen_color, &pdev->pen_and, &pdev->pen_xor); + update_brush_rop(pdev, rop); return next->funcs->pSetROP2( next, rop ); } @@ -219,7 +220,7 @@ const DC_FUNCTIONS dib_driver = NULL, /* pScaleViewportExt */ NULL, /* pScaleWindowExt */ dibdrv_SelectBitmap, /* pSelectBitmap */ - NULL, /* pSelectBrush */ + dibdrv_SelectBrush, /* pSelectBrush */ NULL, /* pSelectClipPath */ NULL, /* pSelectFont */ NULL, /* pSelectPalette */ @@ -228,7 +229,7 @@ const DC_FUNCTIONS dib_driver = NULL, /* pSetBitmapBits */ NULL, /* pSetBkColor */ NULL, /* pSetBkMode */ - NULL, /* pSetDCBrushColor */ + dibdrv_SetDCBrushColor, /* pSetDCBrushColor */ dibdrv_SetDCPenColor, /* pSetDCPenColor */ NULL, /* pSetDIBColorTable */ NULL, /* pSetDIBits */ diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index b7408ac7492..e62536f0362 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -19,7 +19,9 @@ */ extern BOOL CDECL dibdrv_LineTo( PHYSDEV dev, INT x, INT y ) DECLSPEC_HIDDEN; +extern HBRUSH CDECL dibdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush ) DECLSPEC_HIDDEN; extern HPEN CDECL dibdrv_SelectPen( PHYSDEV dev, HPEN hpen ) DECLSPEC_HIDDEN; +extern COLORREF CDECL dibdrv_SetDCBrushColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; extern COLORREF CDECL dibdrv_SetDCPenColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; static inline dibdrv_physdev *get_dibdrv_pdev( PHYSDEV dev ) @@ -43,3 +45,14 @@ 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; +extern void update_brush_rop( dibdrv_physdev *pdev, INT rop ) DECLSPEC_HIDDEN; + +static inline BOOL defer_pen(dibdrv_physdev *pdev) +{ + return pdev->defer & (DEFER_FORMAT | DEFER_PEN); +} + +static inline BOOL defer_brush(dibdrv_physdev *pdev) +{ + return pdev->defer & (DEFER_FORMAT | DEFER_BRUSH); +} diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c index 1e0de2fa6a7..1b4ccb3b4b6 100644 --- a/dlls/gdi32/dibdrv/graphics.c +++ b/dlls/gdi32/dibdrv/graphics.c @@ -40,7 +40,7 @@ BOOL CDECL dibdrv_LineTo( PHYSDEV dev, INT x, INT y ) LPtoDP(dev->hdc, pts, 2); - if(pdev->defer || !pdev->pen_line(pdev, pts, pts + 1)) + if(defer_pen(pdev) || !pdev->pen_line(pdev, pts, pts + 1)) return next->funcs->pLineTo( next, x, y ); return TRUE; diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c index a26785a07ff..4ebeee160bd 100644 --- a/dlls/gdi32/dibdrv/objects.c +++ b/dlls/gdi32/dibdrv/objects.c @@ -207,3 +207,86 @@ COLORREF CDECL dibdrv_SetDCPenColor( PHYSDEV dev, COLORREF color ) return next->funcs->pSetDCPenColor( next, color ); } + +/********************************************************************** + * solid_brush + * + * Fill a number of rectangles with the solid brush + * FIXME: Should we insist l < r && t < b? Currently we assume this. + */ +static BOOL solid_brush(dibdrv_physdev *pdev, int num, RECT *rects) +{ + int i; + DC *dc = get_dibdrv_dc( &pdev->dev ); + + if(get_clip_region(dc)) return FALSE; + + for(i = 0; i < num; i++) /* simple clip to extents */ + { + if(rects[i].left < dc->vis_rect.left) rects[i].left = dc->vis_rect.left; + if(rects[i].top < dc->vis_rect.top) rects[i].top = dc->vis_rect.top; + if(rects[i].right > dc->vis_rect.right) rects[i].right = dc->vis_rect.right; + if(rects[i].bottom > dc->vis_rect.bottom) rects[i].bottom = dc->vis_rect.bottom; + } + + pdev->dib.funcs->solid_rects(&pdev->dib, num, rects, pdev->brush_and, pdev->brush_xor); + return TRUE; +} + +void update_brush_rop( dibdrv_physdev *pdev, INT rop ) +{ + if(pdev->brush_style == BS_SOLID) + calc_and_xor_masks(rop, pdev->brush_color, &pdev->brush_and, &pdev->brush_xor); +} + +/*********************************************************************** + * dibdrv_SelectBrush + */ +HBRUSH CDECL dibdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectBrush ); + dibdrv_physdev *pdev = get_dibdrv_pdev(dev); + LOGBRUSH logbrush; + + TRACE("(%p, %p)\n", dev, hbrush); + + if (!GetObjectW( hbrush, sizeof(logbrush), &logbrush )) return 0; + + if (hbrush == GetStockObject( DC_BRUSH )) + logbrush.lbColor = GetDCBrushColor( dev->hdc ); + + pdev->brush_style = logbrush.lbStyle; + + pdev->defer |= DEFER_BRUSH; + + switch(logbrush.lbStyle) + { + case BS_SOLID: + pdev->brush_color = pdev->dib.funcs->colorref_to_pixel(&pdev->dib, logbrush.lbColor); + calc_and_xor_masks(GetROP2(dev->hdc), pdev->brush_color, &pdev->brush_and, &pdev->brush_xor); + pdev->brush_rects = solid_brush; + pdev->defer &= ~DEFER_BRUSH; + break; + default: + break; + } + + return next->funcs->pSelectBrush( next, hbrush ); +} + +/*********************************************************************** + * dibdrv_SetDCBrushColor + */ +COLORREF CDECL dibdrv_SetDCBrushColor( PHYSDEV dev, COLORREF color ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSetDCBrushColor ); + dibdrv_physdev *pdev = get_dibdrv_pdev(dev); + + if (GetCurrentObject(dev->hdc, OBJ_BRUSH) == GetStockObject( DC_BRUSH )) + { + pdev->brush_color = pdev->dib.funcs->colorref_to_pixel(&pdev->dib, color); + calc_and_xor_masks(GetROP2(dev->hdc), pdev->brush_color, &pdev->brush_and, &pdev->brush_xor); + } + + return next->funcs->pSetDCBrushColor( next, color ); +} diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index fc86b322bbc..91f4acb5161 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -102,10 +102,16 @@ typedef struct dibdrv_physdev /* pen */ DWORD pen_color, pen_and, pen_xor; BOOL (* pen_line)(struct dibdrv_physdev *pdev, POINT *start, POINT *end); + + /* brush */ + UINT brush_style; + DWORD brush_color, brush_and, brush_xor; + BOOL (* brush_rects)(struct dibdrv_physdev *pdev, int num, RECT *rects); } dibdrv_physdev; #define DEFER_FORMAT 1 #define DEFER_PEN 2 +#define DEFER_BRUSH 4 typedef struct tagDC_FUNCS {