diff --git a/dlls/gdi32/brush.c b/dlls/gdi32/brush.c index 703dd1a658c..7513fcaed00 100644 --- a/dlls/gdi32/brush.c +++ b/dlls/gdi32/brush.c @@ -56,33 +56,42 @@ static const struct gdi_obj_funcs brush_funcs = /* fetch the contents of the brush bitmap and cache them in the brush pattern */ -static BOOL store_bitmap_bits( struct brush_pattern *brush, BITMAPOBJ *bmp ) +void cache_pattern_bits( PHYSDEV physdev, struct brush_pattern *pattern ) { - const struct gdi_dc_funcs *funcs = get_bitmap_funcs( bmp ); + const struct gdi_dc_funcs *funcs; struct gdi_image_bits bits; struct bitblt_coords src; BITMAPINFO *info; + BITMAPOBJ *bmp; - if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) - return FALSE; + if (pattern->info) return; /* already cached */ + if (!(bmp = GDI_GetObjPtr( pattern->bitmap, OBJ_BITMAP ))) return; + + /* we don't need to cache if we are selecting into the same type of DC */ + if (physdev && bmp->funcs == physdev->funcs) goto done; + + if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done; src.visrect.left = src.x = 0; src.visrect.top = src.y = 0; src.visrect.right = src.width = bmp->bitmap.bmWidth; src.visrect.bottom = src.height = bmp->bitmap.bmHeight; - if (funcs->pGetImage( NULL, brush->bitmap, info, &bits, &src )) + funcs = get_bitmap_funcs( bmp ); + if (funcs->pGetImage( NULL, pattern->bitmap, info, &bits, &src )) { HeapFree( GetProcessHeap(), 0, info ); - return FALSE; + goto done; } /* release the unneeded space */ HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, info, get_dib_info_size( info, DIB_RGB_COLORS )); - brush->info = info; - brush->bits = bits; - brush->usage = DIB_RGB_COLORS; - return TRUE; + pattern->info = info; + pattern->bits = bits; + pattern->usage = DIB_RGB_COLORS; + +done: + GDI_ReleaseObj( pattern->bitmap ); } static BOOL copy_bitmap( struct brush_pattern *brush, HBITMAP bitmap ) @@ -204,16 +213,8 @@ BOOL get_brush_bitmap_info( HBRUSH handle, BITMAPINFO *info, void **bits, UINT * if (!(brush = GDI_GetObjPtr( handle, OBJ_BRUSH ))) return FALSE; - if (!brush->pattern.info) - { - BITMAPOBJ *bmp = GDI_GetObjPtr( brush->pattern.bitmap, OBJ_BITMAP ); + if (!brush->pattern.info) cache_pattern_bits( NULL, &brush->pattern ); - if (bmp) - { - store_bitmap_bits( &brush->pattern, bmp ); - GDI_ReleaseObj( brush->pattern.bitmap ); - } - } if (brush->pattern.info) { memcpy( info, brush->pattern.info, get_dib_info_size( brush->pattern.info, brush->pattern.usage )); @@ -496,14 +497,11 @@ static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, HDC hdc ) PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSelectBrush ); struct brush_pattern *pattern = &brush->pattern; - if (pattern->bitmap && !pattern->info) + if (!pattern->info) { - BITMAPOBJ *bmp = GDI_GetObjPtr( pattern->bitmap, OBJ_BITMAP ); - /* fetch the bitmap bits if we are selecting into a different type of DC */ - if (bmp && bmp->funcs != physdev->funcs) store_bitmap_bits( pattern, bmp ); - GDI_ReleaseObj( pattern->bitmap ); + if (pattern->bitmap) cache_pattern_bits( physdev, pattern ); + else pattern = NULL; } - else if (!pattern->info) pattern = NULL; GDI_inc_ref_count( handle ); GDI_ReleaseObj( handle ); diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index 76b0743501c..63d4f27b52e 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -129,7 +129,7 @@ extern DWORD dibdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAP struct bitblt_coords *dst, DWORD rop ) DECLSPEC_HIDDEN; extern BOOL dibdrv_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN; extern HBRUSH dibdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; -extern HPEN dibdrv_SelectPen( PHYSDEV dev, HPEN hpen ) DECLSPEC_HIDDEN; +extern HPEN dibdrv_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern COLORREF dibdrv_SetDCBrushColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; extern COLORREF dibdrv_SetDCPenColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; extern COLORREF dibdrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color ) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c index 917992410ff..c9495f33c01 100644 --- a/dlls/gdi32/dibdrv/objects.c +++ b/dlls/gdi32/dibdrv/objects.c @@ -1531,7 +1531,7 @@ static inline int get_pen_device_width( dibdrv_physdev *pdev, int width ) /*********************************************************************** * dibdrv_SelectPen */ -HPEN dibdrv_SelectPen( PHYSDEV dev, HPEN hpen ) +HPEN dibdrv_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern ) { PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectPen ); dibdrv_physdev *pdev = get_dibdrv_pdev(dev); @@ -1631,7 +1631,7 @@ HPEN dibdrv_SelectPen( PHYSDEV dev, HPEN hpen ) pdev->pen_is_ext = (elp != NULL); HeapFree( GetProcessHeap(), 0, elp ); - return next->funcs->pSelectPen( next, hpen ); + return next->funcs->pSelectPen( next, hpen, pattern ); } /*********************************************************************** diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index 9f92c3d9220..b21fb74657f 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -541,7 +541,7 @@ static HPALETTE nulldrv_SelectPalette( PHYSDEV dev, HPALETTE palette, BOOL bkgnd return palette; } -static HPEN nulldrv_SelectPen( PHYSDEV dev, HPEN pen ) +static HPEN nulldrv_SelectPen( PHYSDEV dev, HPEN pen, const struct brush_pattern *pattern ) { return pen; } diff --git a/dlls/gdi32/enhmfdrv/enhmetafiledrv.h b/dlls/gdi32/enhmfdrv/enhmetafiledrv.h index 9b885567a22..a1cead51f8e 100644 --- a/dlls/gdi32/enhmfdrv/enhmetafiledrv.h +++ b/dlls/gdi32/enhmfdrv/enhmetafiledrv.h @@ -111,7 +111,7 @@ extern HBITMAP EMFDRV_SelectBitmap( PHYSDEV dev, HBITMAP handle ) DECLSPEC_HIDD extern HBRUSH EMFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern BOOL EMFDRV_SelectClipPath( PHYSDEV dev, INT iMode ) DECLSPEC_HIDDEN; extern HFONT EMFDRV_SelectFont( PHYSDEV dev, HFONT handle ) DECLSPEC_HIDDEN; -extern HPEN EMFDRV_SelectPen( PHYSDEV dev, HPEN handle ) DECLSPEC_HIDDEN; +extern HPEN EMFDRV_SelectPen( PHYSDEV dev, HPEN handle, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern HPALETTE EMFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPal, BOOL force ) DECLSPEC_HIDDEN; extern INT EMFDRV_SetArcDirection( PHYSDEV dev, INT arcDirection ) DECLSPEC_HIDDEN; extern COLORREF EMFDRV_SetBkColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/enhmfdrv/objects.c b/dlls/gdi32/enhmfdrv/objects.c index 5e7d7d707c7..7753216e17d 100644 --- a/dlls/gdi32/enhmfdrv/objects.c +++ b/dlls/gdi32/enhmfdrv/objects.c @@ -361,7 +361,7 @@ static DWORD EMFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen) /****************************************************************** * EMFDRV_SelectPen */ -HPEN EMFDRV_SelectPen(PHYSDEV dev, HPEN hPen ) +HPEN EMFDRV_SelectPen(PHYSDEV dev, HPEN hPen, const struct brush_pattern *pattern ) { EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*)dev; EMRSELECTOBJECT emr; diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 8fbbbe4ee9d..081ecfd21db 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -208,6 +208,7 @@ extern DWORD stretch_bits( const BITMAPINFO *src_info, struct bitblt_coords *src struct gdi_image_bits *bits, int mode ) DECLSPEC_HIDDEN; /* brush.c */ +extern void cache_pattern_bits( PHYSDEV physdev, struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern BOOL store_brush_pattern( LOGBRUSH *brush, struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern void free_brush_pattern( struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern BOOL get_brush_bitmap_info( HBRUSH handle, BITMAPINFO *info, void **bits, UINT *usage ) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/mfdrv/metafiledrv.h b/dlls/gdi32/mfdrv/metafiledrv.h index cdc1496daed..d04cc8f9770 100644 --- a/dlls/gdi32/mfdrv/metafiledrv.h +++ b/dlls/gdi32/mfdrv/metafiledrv.h @@ -106,7 +106,7 @@ extern HBITMAP MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP handle ) DECLSPEC_HIDDEN extern HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern BOOL MFDRV_SelectClipPath( PHYSDEV dev, INT iMode ) DECLSPEC_HIDDEN; extern HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT handle ) DECLSPEC_HIDDEN; -extern HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN handle ) DECLSPEC_HIDDEN; +extern HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN handle, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground) DECLSPEC_HIDDEN; extern UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL primary) DECLSPEC_HIDDEN; extern COLORREF MFDRV_SetBkColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/mfdrv/objects.c b/dlls/gdi32/mfdrv/objects.c index 590c959a11f..511b84f3411 100644 --- a/dlls/gdi32/mfdrv/objects.c +++ b/dlls/gdi32/mfdrv/objects.c @@ -323,7 +323,7 @@ static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen) /*********************************************************************** * MFDRV_SelectPen */ -HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen ) +HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern ) { LOGPEN16 logpen; INT16 index; diff --git a/dlls/gdi32/pen.c b/dlls/gdi32/pen.c index 569c2b296ca..1d04daef1d0 100644 --- a/dlls/gdi32/pen.c +++ b/dlls/gdi32/pen.c @@ -221,7 +221,7 @@ invalid: */ static HGDIOBJ PEN_SelectObject( HGDIOBJ handle, HDC hdc ) { - PHYSDEV physdev; + PENOBJ *pen; HGDIOBJ ret = 0; DC *dc = get_dc_ptr( hdc ); @@ -231,22 +231,43 @@ static HGDIOBJ PEN_SelectObject( HGDIOBJ handle, HDC hdc ) return 0; } - if (!GDI_inc_ref_count( handle )) + if ((pen = GDI_GetObjPtr( handle, 0 ))) { - release_dc_ptr( dc ); - return 0; - } + struct brush_pattern *pattern; + PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSelectPen ); - physdev = GET_DC_PHYSDEV( dc, pSelectPen ); - if (!physdev->funcs->pSelectPen( physdev, handle )) - { - GDI_dec_ref_count( handle ); - } - else - { - ret = dc->hPen; - dc->hPen = handle; - GDI_dec_ref_count( ret ); + switch (pen->header.type) + { + case OBJ_PEN: + pattern = NULL; + break; + case OBJ_EXTPEN: + pattern = &pen->pattern; + if (!pattern->info) + { + if (pattern->bitmap) cache_pattern_bits( physdev, pattern ); + else pattern = NULL; + } + break; + default: + GDI_ReleaseObj( handle ); + release_dc_ptr( dc ); + return 0; + } + + GDI_inc_ref_count( handle ); + GDI_ReleaseObj( handle ); + + if (!physdev->funcs->pSelectPen( physdev, handle, pattern )) + { + GDI_dec_ref_count( handle ); + } + else + { + ret = dc->hPen; + dc->hPen = handle; + GDI_dec_ref_count( ret ); + } } release_dc_ptr( dc ); return ret; diff --git a/dlls/wineps.drv/pen.c b/dlls/wineps.drv/pen.c index 422b04950d7..2526fa931f7 100644 --- a/dlls/wineps.drv/pen.c +++ b/dlls/wineps.drv/pen.c @@ -37,7 +37,7 @@ static const DWORD PEN_alternate[] = { 1 }; /*********************************************************************** * SelectPen (WINEPS.@) */ -HPEN PSDRV_SelectPen( PHYSDEV dev, HPEN hpen ) +HPEN PSDRV_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern ) { PSDRV_PDEVICE *physDev = get_psdrv_dev( dev ); LOGPEN logpen; diff --git a/dlls/wineps.drv/psdrv.h b/dlls/wineps.drv/psdrv.h index 4b33edc0859..3bcad2c4692 100644 --- a/dlls/wineps.drv/psdrv.h +++ b/dlls/wineps.drv/psdrv.h @@ -456,7 +456,7 @@ extern BOOL PSDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT ell_width, INT ell_height ) DECLSPEC_HIDDEN; extern HBRUSH PSDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern HFONT PSDRV_SelectFont( PHYSDEV dev, HFONT hfont ) DECLSPEC_HIDDEN; -extern HPEN PSDRV_SelectPen( PHYSDEV dev, HPEN hpen ) DECLSPEC_HIDDEN; +extern HPEN PSDRV_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern COLORREF PSDRV_SetBkColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; extern COLORREF PSDRV_SetDCBrushColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; extern COLORREF PSDRV_SetDCPenColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/pen.c b/dlls/winex11.drv/pen.c index c0eff9273b9..1fb2d42f8a4 100644 --- a/dlls/winex11.drv/pen.c +++ b/dlls/winex11.drv/pen.c @@ -57,7 +57,7 @@ static DWORD get_user_dashes( char *res, const DWORD *style, DWORD len ) /*********************************************************************** * SelectPen (X11DRV.@) */ -HPEN X11DRV_SelectPen( PHYSDEV dev, HPEN hpen ) +HPEN X11DRV_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern ) { static const char PEN_dash[] = { 16,8 }; static const char PEN_dot[] = { 4,4 }; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 36d98feccbc..c754623500f 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -224,7 +224,7 @@ extern BOOL X11DRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bot extern HBITMAP X11DRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap ) DECLSPEC_HIDDEN; extern HBRUSH X11DRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern HFONT X11DRV_SelectFont( PHYSDEV dev, HFONT hfont ) DECLSPEC_HIDDEN; -extern HPEN X11DRV_SelectPen( PHYSDEV dev, HPEN hpen ) DECLSPEC_HIDDEN; +extern HPEN X11DRV_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern COLORREF X11DRV_SetBkColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; extern COLORREF X11DRV_SetDCBrushColor( PHYSDEV dev, COLORREF crColor ) DECLSPEC_HIDDEN; extern COLORREF X11DRV_SetDCPenColor( PHYSDEV dev, COLORREF crColor ) DECLSPEC_HIDDEN; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index c4be7c14ee0..a471bf0e608 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -159,7 +159,7 @@ struct gdi_dc_funcs BOOL (*pSelectClipPath)(PHYSDEV,INT); HFONT (*pSelectFont)(PHYSDEV,HFONT); HPALETTE (*pSelectPalette)(PHYSDEV,HPALETTE,BOOL); - HPEN (*pSelectPen)(PHYSDEV,HPEN); + HPEN (*pSelectPen)(PHYSDEV,HPEN,const struct brush_pattern*); INT (*pSetArcDirection)(PHYSDEV,INT); COLORREF (*pSetBkColor)(PHYSDEV,COLORREF); INT (*pSetBkMode)(PHYSDEV,INT); @@ -213,7 +213,7 @@ struct gdi_dc_funcs }; /* increment this when you change the DC function table */ -#define WINE_GDI_DRIVER_VERSION 21 +#define WINE_GDI_DRIVER_VERSION 22 static inline PHYSDEV get_physdev_entry_point( PHYSDEV dev, size_t offset ) {