Module: wine Branch: master Commit: 77c97174149a53ba06f6826fe6f4451c48adeef8 URL: https://source.winehq.org/git/wine.git/?a=commit;h=77c97174149a53ba06f6826fe...
Author: Jacek Caban jacek@codeweavers.com Date: Thu Aug 12 11:59:53 2021 +0200
gdi32: Use GetDIBits in emfdrv_stretchblt.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/gdi32/enhmfdrv/bitblt.c | 133 +++++++++++++++++++++++++++---------------- 1 file changed, 84 insertions(+), 49 deletions(-)
diff --git a/dlls/gdi32/enhmfdrv/bitblt.c b/dlls/gdi32/enhmfdrv/bitblt.c index ca3455459e5..e1d90c281c4 100644 --- a/dlls/gdi32/enhmfdrv/bitblt.c +++ b/dlls/gdi32/enhmfdrv/bitblt.c @@ -20,51 +20,98 @@
#include <stdarg.h> #include <string.h> +#include <assert.h>
#include "windef.h" #include "winbase.h" #include "wingdi.h" #include "enhmetafiledrv.h" -#include "wine/debug.h"
/* Generate an EMRBITBLT, EMRSTRETCHBLT or EMRALPHABLEND record depending on the type parameter */ -static BOOL emfdrv_stretchblt( PHYSDEV dev_dst, struct bitblt_coords *dst, PHYSDEV dev_src, +static BOOL emfdrv_stretchblt( PHYSDEV dev_dst, struct bitblt_coords *dst, HDC hdc_src, struct bitblt_coords *src, DWORD rop, DWORD type ) { - unsigned char src_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; - BITMAPINFO *src_info = (BITMAPINFO *)src_buffer; - UINT bits_size, bmi_size, emr_size, size, bpp; - EMRSTRETCHBLT *emr_stretchblt; - struct gdi_image_bits bits; + BITMAPINFO src_info = {{ sizeof( src_info.bmiHeader ) }}; + UINT bmi_size, emr_size, size, bpp; + HBITMAP bitmap, blit_bitmap = NULL; + EMRBITBLT *emr = NULL; BITMAPINFO *bmi; - EMRBITBLT *emr; - DC *dc_src; - DWORD err; + DIBSECTION dib; + HDC blit_dc; + int info_size; BOOL ret = FALSE;
- dc_src = get_physdev_dc(dev_src); - dev_src = GET_DC_PHYSDEV(dc_src, pGetImage); - err = dev_src->funcs->pGetImage(dev_src, src_info, &bits, src); - if (err) + if (!(bitmap = GetCurrentObject( hdc_src, OBJ_BITMAP ))) return FALSE; + if (!(info_size = GetObjectW( bitmap, sizeof(dib), &dib ))) return FALSE; + + if (info_size == sizeof(DIBSECTION)) { - SetLastError(err); - return FALSE; + blit_dc = hdc_src; + blit_bitmap = bitmap; } + else + { + unsigned char dib_info_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; + BITMAPINFO *dib_info = (BITMAPINFO *)dib_info_buffer; + BITMAP bmp = dib.dsBm; + HPALETTE palette; + void *bits; + + assert( info_size == sizeof(BITMAP) ); + + dib_info->bmiHeader.biSize = sizeof(dib_info->bmiHeader); + dib_info->bmiHeader.biWidth = bmp.bmWidth; + dib_info->bmiHeader.biHeight = bmp.bmHeight; + dib_info->bmiHeader.biPlanes = 1; + dib_info->bmiHeader.biBitCount = bmp.bmBitsPixel; + dib_info->bmiHeader.biCompression = BI_RGB; + dib_info->bmiHeader.biSizeImage = 0; + dib_info->bmiHeader.biXPelsPerMeter = 0; + dib_info->bmiHeader.biYPelsPerMeter = 0; + dib_info->bmiHeader.biClrUsed = 0; + dib_info->bmiHeader.biClrImportant = 0; + switch (dib_info->bmiHeader.biBitCount) + { + case 16: + ((DWORD *)dib_info->bmiColors)[0] = 0xf800; + ((DWORD *)dib_info->bmiColors)[1] = 0x07e0; + ((DWORD *)dib_info->bmiColors)[2] = 0x001f; + break; + case 32: + ((DWORD *)dib_info->bmiColors)[0] = 0xff0000; + ((DWORD *)dib_info->bmiColors)[1] = 0x00ff00; + ((DWORD *)dib_info->bmiColors)[2] = 0x0000ff; + break; + default: + if (dib_info->bmiHeader.biBitCount > 8) break; + if (!(palette = GetCurrentObject( hdc_src, OBJ_PAL ))) return FALSE; + if (!GetPaletteEntries( palette, 0, 256, (PALETTEENTRY *)dib_info->bmiColors )) + return FALSE; + } + + if (!(blit_dc = NtGdiCreateCompatibleDC( hdc_src ))) return FALSE; + if (!(blit_bitmap = CreateDIBSection( blit_dc, dib_info, DIB_RGB_COLORS, &bits, NULL, 0 ))) + goto err; + if (!SelectObject( blit_dc, blit_bitmap )) goto err; + if (!BitBlt( blit_dc, 0, 0, bmp.bmWidth, bmp.bmHeight, hdc_src, 0, 0, SRCCOPY )) + goto err; + } + if (!GetDIBits( blit_dc, blit_bitmap, 0, INT_MAX, NULL, &src_info, DIB_RGB_COLORS )) + goto err;
- bpp = src_info->bmiHeader.biBitCount; + bpp = src_info.bmiHeader.biBitCount; if (bpp <= 8) bmi_size = sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD); else if (bpp == 16 || bpp == 32) bmi_size = sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD); else bmi_size = sizeof(BITMAPINFOHEADER); + /* EMRSTRETCHBLT and EMRALPHABLEND have the same structure */ emr_size = type == EMR_BITBLT ? sizeof(EMRBITBLT) : sizeof(EMRSTRETCHBLT); - bits_size = src_info->bmiHeader.biSizeImage; - size = emr_size + bmi_size + bits_size; + size = emr_size + bmi_size + src_info.bmiHeader.biSizeImage;
- emr = HeapAlloc(GetProcessHeap(), 0, size); - if (!emr) goto err; + if (!(emr = HeapAlloc(GetProcessHeap(), 0, size))) goto err;
emr->emr.iType = type; emr->emr.nSize = size; @@ -80,52 +127,40 @@ static BOOL emfdrv_stretchblt( PHYSDEV dev_dst, struct bitblt_coords *dst, PHYSD emr->ySrc = src->log_y; if (type == EMR_STRETCHBLT || type == EMR_ALPHABLEND) { - emr_stretchblt = (EMRSTRETCHBLT *)emr; + EMRSTRETCHBLT *emr_stretchblt = (EMRSTRETCHBLT *)emr; emr_stretchblt->cxSrc = src->log_width; emr_stretchblt->cySrc = src->log_height; } emr->dwRop = rop; - NtGdiGetTransform( dev_src->hdc, 0x204, &emr->xformSrc ); - emr->crBkColorSrc = GetBkColor(dev_src->hdc); + NtGdiGetTransform( hdc_src, 0x204, &emr->xformSrc ); + emr->crBkColorSrc = GetBkColor( hdc_src ); emr->iUsageSrc = DIB_RGB_COLORS; emr->offBmiSrc = emr_size; emr->cbBmiSrc = bmi_size; emr->offBitsSrc = emr_size + bmi_size; - emr->cbBitsSrc = bits_size; + emr->cbBitsSrc = src_info.bmiHeader.biSizeImage;
bmi = (BITMAPINFO *)((BYTE *)emr + emr->offBmiSrc); - memcpy(bmi, src_info, bmi_size); - memcpy((BYTE *)emr + emr->offBitsSrc, bits.ptr, bits_size); - - bmi->bmiHeader.biClrUsed = 0; - if (bmi->bmiHeader.biCompression == BI_RGB && bmi->bmiHeader.biBitCount == 16) - { - bmi->bmiHeader.biCompression = BI_BITFIELDS; - ((DWORD *)bmi->bmiColors)[0] = 0xf800; - ((DWORD *)bmi->bmiColors)[1] = 0x07e0; - ((DWORD *)bmi->bmiColors)[2] = 0x001f; - } - else if (bmi->bmiHeader.biCompression == BI_RGB && bmi->bmiHeader.biBitCount == 32) + bmi->bmiHeader = src_info.bmiHeader; + ret = GetDIBits( blit_dc, blit_bitmap, 0, src_info.bmiHeader.biHeight, (BYTE *)emr + emr->offBitsSrc, + bmi, DIB_RGB_COLORS ); + if (ret) { - bmi->bmiHeader.biCompression = BI_BITFIELDS; - ((DWORD *)bmi->bmiColors)[0] = 0xff0000; - ((DWORD *)bmi->bmiColors)[1] = 0x00ff00; - ((DWORD *)bmi->bmiColors)[2] = 0x0000ff; + ret = EMFDRV_WriteRecord( dev_dst, (EMR *)emr ); + if (ret) EMFDRV_UpdateBBox( dev_dst, &emr->rclBounds ); }
- ret = EMFDRV_WriteRecord(dev_dst, (EMR *)emr); - if (ret) EMFDRV_UpdateBBox(dev_dst, &emr->rclBounds); - err: - HeapFree(GetProcessHeap(), 0, emr); - if (bits.free) bits.free(&bits); + HeapFree( GetProcessHeap(), 0, emr ); + if (blit_bitmap && blit_bitmap != bitmap) DeleteObject( blit_bitmap ); + if (blit_dc && blit_dc != hdc_src) DeleteDC( blit_dc ); return ret; }
BOOL CDECL EMFDRV_AlphaBlend( PHYSDEV dev_dst, struct bitblt_coords *dst, PHYSDEV dev_src, struct bitblt_coords *src, BLENDFUNCTION func ) { - return emfdrv_stretchblt(dev_dst, dst, dev_src, src, *(DWORD *)&func, EMR_ALPHABLEND); + return emfdrv_stretchblt( dev_dst, dst, dev_src->hdc, src, *(DWORD *)&func, EMR_ALPHABLEND ); }
BOOL CDECL EMFDRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop ) @@ -176,9 +211,9 @@ BOOL CDECL EMFDRV_StretchBlt( PHYSDEV devDst, struct bitblt_coords *dst, PHYSDEV devSrc, struct bitblt_coords *src, DWORD rop ) { if (src->log_width == dst->log_width && src->log_height == dst->log_height) - return emfdrv_stretchblt(devDst, dst, devSrc, src, rop, EMR_BITBLT); + return emfdrv_stretchblt( devDst, dst, devSrc->hdc, src, rop, EMR_BITBLT ); else - return emfdrv_stretchblt(devDst, dst, devSrc, src, rop, EMR_STRETCHBLT); + return emfdrv_stretchblt( devDst, dst, devSrc->hdc, src, rop, EMR_STRETCHBLT ); }
INT CDECL EMFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,