From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 273 ++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 22713229c26..1f94e4782b9 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -264,6 +264,269 @@ static int stretch_blt(PHYSDEV dev, const EMRSTRETCHBLT *blt, return !err; }
+#define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF) +#define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF]) + +static int mask_blt(PHYSDEV dev, const EMRMASKBLT *p, const BITMAPINFO *src_bi, + const BYTE *src_bits, const BITMAPINFO *mask_bi, const BYTE *mask_bits) +{ + HBITMAP bmp1, old_bmp1, bmp2, old_bmp2, bmp_src, old_bmp_src; + char bmp2_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; + BITMAPINFO *bmp2_info = (BITMAPINFO *)bmp2_buffer; + HBRUSH brush_mask, brush_dest, old_brush; + HDC hdc_src, hdc1, hdc2; + BYTE *bits; + EMRSTRETCHBLT blt; + + static const DWORD ROP3Table[256] = + { + 0x00000042, 0x00010289, + 0x00020C89, 0x000300AA, + 0x00040C88, 0x000500A9, + 0x00060865, 0x000702C5, + 0x00080F08, 0x00090245, + 0x000A0329, 0x000B0B2A, + 0x000C0324, 0x000D0B25, + 0x000E08A5, 0x000F0001, + 0x00100C85, 0x001100A6, + 0x00120868, 0x001302C8, + 0x00140869, 0x001502C9, + 0x00165CCA, 0x00171D54, + 0x00180D59, 0x00191CC8, + 0x001A06C5, 0x001B0768, + 0x001C06CA, 0x001D0766, + 0x001E01A5, 0x001F0385, + 0x00200F09, 0x00210248, + 0x00220326, 0x00230B24, + 0x00240D55, 0x00251CC5, + 0x002606C8, 0x00271868, + 0x00280369, 0x002916CA, + 0x002A0CC9, 0x002B1D58, + 0x002C0784, 0x002D060A, + 0x002E064A, 0x002F0E2A, + 0x0030032A, 0x00310B28, + 0x00320688, 0x00330008, + 0x003406C4, 0x00351864, + 0x003601A8, 0x00370388, + 0x0038078A, 0x00390604, + 0x003A0644, 0x003B0E24, + 0x003C004A, 0x003D18A4, + 0x003E1B24, 0x003F00EA, + 0x00400F0A, 0x00410249, + 0x00420D5D, 0x00431CC4, + 0x00440328, 0x00450B29, + 0x004606C6, 0x0047076A, + 0x00480368, 0x004916C5, + 0x004A0789, 0x004B0605, + 0x004C0CC8, 0x004D1954, + 0x004E0645, 0x004F0E25, + 0x00500325, 0x00510B26, + 0x005206C9, 0x00530764, + 0x005408A9, 0x00550009, + 0x005601A9, 0x00570389, + 0x00580785, 0x00590609, + 0x005A0049, 0x005B18A9, + 0x005C0649, 0x005D0E29, + 0x005E1B29, 0x005F00E9, + 0x00600365, 0x006116C6, + 0x00620786, 0x00630608, + 0x00640788, 0x00650606, + 0x00660046, 0x006718A8, + 0x006858A6, 0x00690145, + 0x006A01E9, 0x006B178A, + 0x006C01E8, 0x006D1785, + 0x006E1E28, 0x006F0C65, + 0x00700CC5, 0x00711D5C, + 0x00720648, 0x00730E28, + 0x00740646, 0x00750E26, + 0x00761B28, 0x007700E6, + 0x007801E5, 0x00791786, + 0x007A1E29, 0x007B0C68, + 0x007C1E24, 0x007D0C69, + 0x007E0955, 0x007F03C9, + 0x008003E9, 0x00810975, + 0x00820C49, 0x00831E04, + 0x00840C48, 0x00851E05, + 0x008617A6, 0x008701C5, + 0x008800C6, 0x00891B08, + 0x008A0E06, 0x008B0666, + 0x008C0E08, 0x008D0668, + 0x008E1D7C, 0x008F0CE5, + 0x00900C45, 0x00911E08, + 0x009217A9, 0x009301C4, + 0x009417AA, 0x009501C9, + 0x00960169, 0x0097588A, + 0x00981888, 0x00990066, + 0x009A0709, 0x009B07A8, + 0x009C0704, 0x009D07A6, + 0x009E16E6, 0x009F0345, + 0x00A000C9, 0x00A11B05, + 0x00A20E09, 0x00A30669, + 0x00A41885, 0x00A50065, + 0x00A60706, 0x00A707A5, + 0x00A803A9, 0x00A90189, + 0x00AA0029, 0x00AB0889, + 0x00AC0744, 0x00AD06E9, + 0x00AE0B06, 0x00AF0229, + 0x00B00E05, 0x00B10665, + 0x00B21974, 0x00B30CE8, + 0x00B4070A, 0x00B507A9, + 0x00B616E9, 0x00B70348, + 0x00B8074A, 0x00B906E6, + 0x00BA0B09, 0x00BB0226, + 0x00BC1CE4, 0x00BD0D7D, + 0x00BE0269, 0x00BF08C9, + 0x00C000CA, 0x00C11B04, + 0x00C21884, 0x00C3006A, + 0x00C40E04, 0x00C50664, + 0x00C60708, 0x00C707AA, + 0x00C803A8, 0x00C90184, + 0x00CA0749, 0x00CB06E4, + 0x00CC0020, 0x00CD0888, + 0x00CE0B08, 0x00CF0224, + 0x00D00E0A, 0x00D1066A, + 0x00D20705, 0x00D307A4, + 0x00D41D78, 0x00D50CE9, + 0x00D616EA, 0x00D70349, + 0x00D80745, 0x00D906E8, + 0x00DA1CE9, 0x00DB0D75, + 0x00DC0B04, 0x00DD0228, + 0x00DE0268, 0x00DF08C8, + 0x00E003A5, 0x00E10185, + 0x00E20746, 0x00E306EA, + 0x00E40748, 0x00E506E5, + 0x00E61CE8, 0x00E70D79, + 0x00E81D74, 0x00E95CE6, + 0x00EA02E9, 0x00EB0849, + 0x00EC02E8, 0x00ED0848, + 0x00EE0086, 0x00EF0A08, + 0x00F00021, 0x00F10885, + 0x00F20B05, 0x00F3022A, + 0x00F40B0A, 0x00F50225, + 0x00F60265, 0x00F708C5, + 0x00F802E5, 0x00F90845, + 0x00FA0089, 0x00FB0A09, + 0x00FC008A, 0x00FD0A0A, + 0x00FE02A9, 0x00FF0062, + }; + + if (!p->cbBmiMask) + { + blt.rclBounds = p->rclBounds; + blt.xDest = p->xDest; + blt.yDest = p->yDest; + blt.cxDest = p->cxDest; + blt.cyDest = p->cyDest; + blt.dwRop = FRGND_ROP3(p->dwRop); + blt.xSrc = p->xSrc; + blt.ySrc = p->ySrc; + blt.xformSrc = p->xformSrc; + blt.crBkColorSrc = p->crBkColorSrc; + blt.iUsageSrc = p->iUsageSrc; + blt.offBmiSrc = 0; + blt.cbBmiSrc = p->cbBmiSrc; + blt.offBitsSrc = 0; + blt.cbBitsSrc = p->cbBitsSrc; + blt.cxSrc = p->cxDest; + blt.cySrc = p->cyDest; + + return stretch_blt(dev, &blt, src_bi, src_bits); + } + + hdc_src = CreateCompatibleDC(NULL); + SetGraphicsMode(hdc_src, GM_ADVANCED); + SetWorldTransform(hdc_src, &p->xformSrc); + brush_dest = CreateSolidBrush(p->crBkColorSrc); + old_brush = SelectObject(hdc_src, brush_dest); + PatBlt(hdc_src, p->rclBounds.left, p->rclBounds.top, + p->rclBounds.right - p->rclBounds.left, + p->rclBounds.bottom - p->rclBounds.top, PATCOPY); + SelectObject(hdc_src, old_brush); + DeleteObject(brush_dest); + + bmp_src = CreateDIBSection(hdc_src, src_bi, p->iUsageSrc, (void **)&bits, NULL, 0); + memcpy(bits, src_bits, p->cbBitsSrc); + old_bmp_src = SelectObject(hdc_src, bmp_src); + + bmp1 = CreateBitmap(mask_bi->bmiHeader.biWidth, mask_bi->bmiHeader.biHeight, 1, 1, NULL); + SetDIBits(dev->hdc, bmp1, 0, mask_bi->bmiHeader.biHeight, mask_bits, mask_bi, p->iUsageMask); + brush_mask = CreatePatternBrush(bmp1); + DeleteObject(bmp1); + brush_dest = SelectObject(dev->hdc, GetStockObject(NULL_BRUSH)); + + /* make bitmap */ + hdc1 = CreateCompatibleDC(NULL); + bmp1 = CreateBitmap(p->cxDest, p->cyDest, 1, 32, NULL); + old_bmp1 = SelectObject(hdc1, bmp1); + + /* draw using bkgnd rop */ + old_brush = SelectObject(hdc1, brush_dest); + BitBlt(hdc1, 0, 0, p->cxDest, p->cyDest, hdc_src, p->xSrc, p->ySrc, BKGND_ROP3(p->dwRop)); + SelectObject(hdc1, old_brush); + + /* make bitmap */ + hdc2 = CreateCompatibleDC(NULL); + bmp2_info->bmiHeader.biSize = sizeof(bmp2_info->bmiHeader); + bmp2_info->bmiHeader.biWidth = p->cxDest; + bmp2_info->bmiHeader.biHeight = p->cyDest; + bmp2_info->bmiHeader.biPlanes = 1; + bmp2_info->bmiHeader.biBitCount = 32; + bmp2_info->bmiHeader.biCompression = BI_RGB; + bmp2_info->bmiHeader.biSizeImage = p->cxDest * p->cyDest * bmp2_info->bmiHeader.biBitCount / 8; + bmp2 = CreateDIBSection(hdc2, bmp2_info, DIB_RGB_COLORS, (void **)&bits, NULL, 0); + old_bmp2 = SelectObject(hdc2, bmp2); + + /* draw using foregnd rop */ + old_brush = SelectObject(hdc2, brush_dest); + BitBlt(hdc2, 0, 0, p->cxDest, p->cyDest, hdc_src, p->xSrc, p->ySrc, FRGND_ROP3(p->dwRop)); + + /* combine both using the mask as a pattern brush */ + SelectObject(hdc2, brush_mask); + SetBrushOrgEx(hdc2, -p->xMask, -p->yMask, NULL); + /* (D & P) | (S & ~P) */ + BitBlt(hdc2, 0, 0, p->cxDest, p->cyDest, hdc1, 0, 0, 0xac0744); + SelectObject(hdc2, old_brush); + + /* blit to dst */ + blt.rclBounds = p->rclBounds; + blt.xDest = p->xDest; + blt.yDest = p->yDest; + blt.cxDest = p->cxDest; + blt.cyDest = p->cyDest; + blt.dwRop = SRCCOPY; + blt.xSrc = 0; + blt.ySrc = 0; + GetTransform(hdc2, 0x204, &blt.xformSrc); + blt.crBkColorSrc = p->crBkColorSrc; + blt.iUsageSrc = DIB_RGB_COLORS; + blt.offBmiSrc = 0; + blt.cbBmiSrc = bmp2_info->bmiHeader.biSize; + blt.offBitsSrc = 0; + blt.cbBitsSrc = bmp2_info->bmiHeader.biSizeImage; + blt.cxSrc = p->cxDest; + blt.cySrc = p->cyDest; + + stretch_blt(dev, &blt, bmp2_info, bits); + + /* restore all objects */ + SelectObject(dev->hdc, brush_dest); + SelectObject(hdc1, old_bmp1); + SelectObject(hdc2, old_bmp2); + SelectObject(hdc_src, old_bmp_src); + + /* delete all temp objects */ + DeleteObject(bmp1); + DeleteObject(bmp2); + DeleteObject(bmp_src); + DeleteObject(brush_mask); + + DeleteObject(hdc1); + DeleteObject(hdc2); + DeleteObject(hdc_src); + + return TRUE; +} + static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, const ENHMETARECORD *rec, int n, LPARAM arg) { @@ -529,6 +792,16 @@ static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable,
return stretch_blt(&data->pdev->dev, p, bi, src_bits); } + case EMR_MASKBLT: + { + const EMRMASKBLT *p = (const EMRMASKBLT *)rec; + const BITMAPINFO *mask_bi = (const BITMAPINFO *)((BYTE *)p + p->offBmiMask); + const BITMAPINFO *src_bi = (const BITMAPINFO *)((BYTE *)p + p->offBmiSrc); + const BYTE *mask_bits = (BYTE *)p + p->offBitsMask; + const BYTE *src_bits = (BYTE *)p + p->offBitsSrc; + + return mask_blt(&data->pdev->dev, p, src_bi, src_bits, mask_bi, mask_bits); + } case EMR_POLYBEZIER16: { const EMRPOLYBEZIER16 *p = (const EMRPOLYBEZIER16 *)rec;
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 103 ++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 1f94e4782b9..399e8a8c212 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -527,6 +527,103 @@ static int mask_blt(PHYSDEV dev, const EMRMASKBLT *p, const BITMAPINFO *src_bi, return TRUE; }
+static void combine_transform(XFORM *result, const XFORM *xform1, const XFORM *xform2) +{ + XFORM r; + + /* Create the result in a temporary XFORM, since result may be + * equal to xform1 or xform2 */ + r.eM11 = xform1->eM11 * xform2->eM11 + xform1->eM12 * xform2->eM21; + r.eM12 = xform1->eM11 * xform2->eM12 + xform1->eM12 * xform2->eM22; + r.eM21 = xform1->eM21 * xform2->eM11 + xform1->eM22 * xform2->eM21; + r.eM22 = xform1->eM21 * xform2->eM12 + xform1->eM22 * xform2->eM22; + r.eDx = xform1->eDx * xform2->eM11 + xform1->eDy * xform2->eM21 + xform2->eDx; + r.eDy = xform1->eDx * xform2->eM12 + xform1->eDy * xform2->eM22 + xform2->eDy; + + *result = r; +} + +static int plg_blt(PHYSDEV dev, const EMRPLGBLT *p) +{ + const BITMAPINFO *src_bi, *mask_bi; + const BYTE *src_bits, *mask_bits; + XFORM xf, xform_dest; + EMRMASKBLT maskblt; + /* rect coords */ + POINT rect[3]; + /* parallelogram coords */ + POINT plg[3]; + double det; + + memcpy(plg, p->aptlDest, sizeof(plg)); + rect[0].x = p->xSrc; + rect[0].y = p->ySrc; + rect[1].x = p->xSrc + p->cxSrc; + rect[1].y = p->ySrc; + rect[2].x = p->xSrc; + rect[2].y = p->ySrc + p->cySrc; + /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */ + /* determinant */ + det = rect[1].x*(rect[2].y - rect[0].y) - rect[2].x*(rect[1].y - rect[0].y) - rect[0].x*(rect[2].y - rect[1].y); + + if (fabs(det) < 1e-5) + return TRUE; + + TRACE("%ld,%ld,%ldx%ld -> %ld,%ld,%ld,%ld,%ld,%ld\n", p->xSrc, p->ySrc, p->cxSrc, p->cySrc, + plg[0].x, plg[0].y, plg[1].x, plg[1].y, plg[2].x, plg[2].y); + + /* X components */ + xf.eM11 = (plg[1].x*(rect[2].y - rect[0].y) - plg[2].x*(rect[1].y - rect[0].y) - plg[0].x*(rect[2].y - rect[1].y)) / det; + xf.eM21 = (rect[1].x*(plg[2].x - plg[0].x) - rect[2].x*(plg[1].x - plg[0].x) - rect[0].x*(plg[2].x - plg[1].x)) / det; + xf.eDx = (rect[0].x*(rect[1].y*plg[2].x - rect[2].y*plg[1].x) - + rect[1].x*(rect[0].y*plg[2].x - rect[2].y*plg[0].x) + + rect[2].x*(rect[0].y*plg[1].x - rect[1].y*plg[0].x) + ) / det; + + /* Y components */ + xf.eM12 = (plg[1].y*(rect[2].y - rect[0].y) - plg[2].y*(rect[1].y - rect[0].y) - plg[0].y*(rect[2].y - rect[1].y)) / det; + xf.eM22 = (rect[1].x*(plg[2].y - plg[0].y) - rect[2].x*(plg[1].y - plg[0].y) - rect[0].x*(plg[2].y - plg[1].y)) / det; + xf.eDy = (rect[0].x*(rect[1].y*plg[2].y - rect[2].y*plg[1].y) - + rect[1].x*(rect[0].y*plg[2].y - rect[2].y*plg[0].y) + + rect[2].x*(rect[0].y*plg[1].y - rect[1].y*plg[0].y) + ) / det; + + combine_transform(&xf, &xf, &p->xformSrc); + + GetTransform(dev->hdc, 0x203, &xform_dest); + SetWorldTransform(dev->hdc, &xf); + /* now destination and source DCs use same coords */ + maskblt.rclBounds = p->rclBounds; + maskblt.xDest = p->xSrc; + maskblt.yDest = p->ySrc; + maskblt.cxDest = p->cxSrc; + maskblt.cyDest = p->cySrc; + maskblt.dwRop = SRCCOPY; + maskblt.xSrc = p->xSrc; + maskblt.ySrc = p->ySrc; + maskblt.xformSrc = p->xformSrc; + maskblt.crBkColorSrc = p->crBkColorSrc; + maskblt.iUsageSrc = p->iUsageSrc; + maskblt.offBmiSrc = 0; + maskblt.cbBmiSrc = p->cbBmiSrc; + maskblt.offBitsSrc = 0; + maskblt.cbBitsSrc = p->cbBitsSrc; + maskblt.xMask = p->xMask; + maskblt.yMask = p->yMask; + maskblt.iUsageMask = p->iUsageMask; + maskblt.offBmiMask = 0; + maskblt.cbBmiMask = p->cbBmiMask; + maskblt.offBitsMask = 0; + maskblt.cbBitsMask = p->cbBitsMask; + src_bi = (const BITMAPINFO *)((BYTE *)p + p->offBmiSrc); + src_bits = (BYTE *)p + p->offBitsSrc; + mask_bi = (const BITMAPINFO *)((BYTE *)p + p->offBmiMask); + mask_bits = (BYTE *)p + p->offBitsMask; + mask_blt(dev, &maskblt, src_bi, src_bits, mask_bi, mask_bits); + SetWorldTransform(dev->hdc, &xform_dest); + return TRUE; +} + static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, const ENHMETARECORD *rec, int n, LPARAM arg) { @@ -802,6 +899,12 @@ static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable,
return mask_blt(&data->pdev->dev, p, src_bi, src_bits, mask_bi, mask_bits); } + case EMR_PLGBLT: + { + const EMRPLGBLT *p = (const EMRPLGBLT *)rec; + + return plg_blt(&data->pdev->dev, p); + } case EMR_POLYBEZIER16: { const EMRPOLYBEZIER16 *p = (const EMRPOLYBEZIER16 *)rec;
This merge request was approved by Huw Davies.