wineps: Handle EMR_STRETCHBLT record in spool files.
This commit is contained in:
parent
83f0862b43
commit
ab12be686a
1 changed files with 135 additions and 0 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue