Module: wine Branch: master Commit: ab12be686ae61873f694e494288c6e195267ff1c URL: https://gitlab.winehq.org/wine/wine/-/commit/ab12be686ae61873f694e494288c6e1...
Author: Piotr Caban piotr@codeweavers.com Date: Tue Mar 28 12:00:28 2023 +0200
wineps: Handle EMR_STRETCHBLT record in spool files.
---
dlls/wineps.drv/printproc.c | 135 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 6dc90ed99c0..39850af9311 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -137,6 +137,133 @@ static inline INT GDI_ROUND(double val) return (int)floor(val + 0.5); }
+static void translate(RECT *rect, const XFORM *xform) +{ + double x, y; + + x = rect->left; + y = rect->top; + rect->left = GDI_ROUND(x * xform->eM11 + y * xform->eM21 + xform->eDx); + rect->top = GDI_ROUND(x * xform->eM12 + y * xform->eM22 + xform->eDy); + + x = rect->right; + y = rect->bottom; + rect->right = GDI_ROUND(x * xform->eM11 + y * xform->eM21 + xform->eDx); + rect->bottom = GDI_ROUND(x * xform->eM12 + y * xform->eM22 + xform->eDy); +} + +static inline void get_bounding_rect(RECT *rect, int x, int y, int width, int height) +{ + rect->left = x; + rect->right = x + width; + rect->top = y; + rect->bottom = y + height; + if (rect->left > rect->right) + { + int tmp = rect->left; + rect->left = rect->right + 1; + rect->right = tmp + 1; + } + if (rect->top > rect->bottom) + { + int tmp = rect->top; + rect->top = rect->bottom + 1; + rect->bottom = tmp + 1; + } +} + +static void get_vis_rectangles(HDC hdc, struct bitblt_coords *dst, + const XFORM *xform, DWORD width, DWORD height, struct bitblt_coords *src) +{ + RECT rect; + + rect.left = dst->log_x; + rect.top = dst->log_y; + rect.right = dst->log_x + dst->log_width; + rect.bottom = dst->log_y + dst->log_height; + LPtoDP(hdc, (POINT *)&rect, 2); + dst->x = rect.left; + dst->y = rect.top; + dst->width = rect.right - rect.left; + dst->height = rect.bottom - rect.top; + if (dst->layout & LAYOUT_RTL && dst->layout & LAYOUT_BITMAPORIENTATIONPRESERVED) + { + dst->x += dst->width; + dst->width = -dst->width; + } + get_bounding_rect(&rect, dst->x, dst->y, dst->width, dst->height); + dst->visrect = rect; + + if (!src) return; + + rect.left = src->log_x; + rect.top = src->log_y; + rect.right = src->log_x + src->log_width; + rect.bottom = src->log_y + src->log_height; + translate(&rect, xform); + src->x = rect.left; + src->y = rect.top; + src->width = rect.right - rect.left; + src->height = rect.bottom - rect.top; + get_bounding_rect( &rect, src->x, src->y, src->width, src->height ); + src->visrect = rect; +} + +static int stretch_blt(PHYSDEV dev, const EMRSTRETCHBLT *blt, + const BITMAPINFO *bi, const BYTE *src_bits) +{ + char dst_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; + BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer; + struct bitblt_coords src, dst; + struct gdi_image_bits bits; + DWORD err; + + dst.log_x = blt->xDest; + dst.log_y = blt->yDest; + dst.log_width = blt->cxDest; + dst.log_height = blt->cyDest; + dst.layout = GetLayout(dev->hdc); + if (blt->dwRop & NOMIRRORBITMAP) + dst.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED; + + if (!blt->cbBmiSrc) + { + get_vis_rectangles(dev->hdc, &dst, NULL, 0, 0, NULL); + return PSDRV_PatBlt(dev, &dst, blt->dwRop); + } + + src.log_x = blt->xSrc; + src.log_y = blt->ySrc; + src.log_width = blt->cxSrc; + src.log_height = blt->cySrc; + src.layout = 0; + + get_vis_rectangles(dev->hdc, &dst, &blt->xformSrc, + bi->bmiHeader.biWidth, bi->bmiHeader.biHeight, &src); + + memcpy(dst_info, bi, blt->cbBmiSrc); + memset(&bits, 0, sizeof(bits)); + bits.ptr = (BYTE *)src_bits; + err = PSDRV_PutImage(dev, 0, dst_info, &bits, &src, &dst, blt->dwRop); + if (err == ERROR_BAD_FORMAT) + { + HDC hdc = CreateCompatibleDC(NULL); + HBITMAP bitmap; + + bits.is_copy = TRUE; + bitmap = CreateDIBSection(hdc, dst_info, DIB_RGB_COLORS, &bits.ptr, NULL, 0); + SetDIBits(hdc, bitmap, 0, bi->bmiHeader.biHeight, src_bits, bi, blt->iUsageSrc); + + err = PSDRV_PutImage(dev, 0, dst_info, &bits, &src, &dst, blt->dwRop); + DeleteObject(bitmap); + DeleteObject(hdc); + } + + if (err != ERROR_SUCCESS) + FIXME("PutImage returned %ld\n", err); + return !err; +} + static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, const ENHMETARECORD *rec, int n, LPARAM arg) { @@ -366,6 +493,14 @@ static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, DeleteObject(rgn); return ret; } + case EMR_STRETCHBLT: + { + const EMRSTRETCHBLT *p = (const EMRSTRETCHBLT *)rec; + const BITMAPINFO *bi = (const BITMAPINFO *)((BYTE *)p + p->offBmiSrc); + const BYTE *src_bits = (BYTE *)p + p->offBitsSrc; + + return stretch_blt(&data->pdev->dev, p, bi, src_bits); + } case EMR_POLYBEZIER16: { const EMRPOLYBEZIER16 *p = (const EMRPOLYBEZIER16 *)rec;