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;