diff --git a/include/freerdp/gdi/brush.h b/include/freerdp/gdi/brush.h index 842f95a9f..10b81cb40 100644 --- a/include/freerdp/gdi/brush.h +++ b/include/freerdp/gdi/brush.h @@ -25,6 +25,7 @@ FREERDP_API HGDI_BRUSH gdi_CreateSolidBrush(GDI_COLOR crColor); FREERDP_API HGDI_BRUSH gdi_CreatePatternBrush(HGDI_BITMAP hbmp); +FREERDP_API HGDI_BRUSH gdi_CreateHatchBrush(HGDI_BITMAP hbmp); FREERDP_API int gdi_PatBlt(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); typedef int (*p_PatBlt)(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); diff --git a/libfreerdp/gdi/16bpp.c b/libfreerdp/gdi/16bpp.c index 77eb60f98..e7826550e 100644 --- a/libfreerdp/gdi/16bpp.c +++ b/libfreerdp/gdi/16bpp.c @@ -622,7 +622,7 @@ static int BitBlt_MERGEPAINT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int static int BitBlt_PATCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { - int x, y; + int x, y, xOffset, yOffset; UINT16* dstp; UINT16* patp; UINT16 color16; @@ -647,6 +647,19 @@ static int BitBlt_PATCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi } else { + /* align pattern to 8x8 grid to make sure transition + between different pattern blocks are smooth */ + + if (hdcDest->brush->style == GDI_BS_HATCHED) + { + xOffset = nXDest % 8; + yOffset = nYDest % 8 + 2; // +2 added after comparison to mstsc + } + else + { + xOffset = 0; + yOffset = 0; + } for (y = 0; y < nHeight; y++) { dstp = (UINT16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); @@ -655,7 +668,7 @@ static int BitBlt_PATCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi { for (x = 0; x < nWidth; x++) { - patp = (UINT16*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT16*) gdi_get_brush_pointer(hdcDest, x+xOffset, y+yOffset); *dstp = *patp; dstp++; } diff --git a/libfreerdp/gdi/32bpp.c b/libfreerdp/gdi/32bpp.c index fadefe922..5c1b647e5 100644 --- a/libfreerdp/gdi/32bpp.c +++ b/libfreerdp/gdi/32bpp.c @@ -664,7 +664,7 @@ static int BitBlt_MERGEPAINT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int static int BitBlt_PATCOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { - int x, y; + int x, y, xOffset, yOffset; UINT32* dstp; UINT32* patp; UINT32 color32; @@ -689,6 +689,19 @@ static int BitBlt_PATCOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi } else { + /* align pattern to 8x8 grid to make sure transition + between different pattern blocks are smooth */ + + if (hdcDest->brush->style == GDI_BS_HATCHED) + { + xOffset = nXDest % 8; + yOffset = nYDest % 8 + 2; // +2 added after comparison to mstsc + } + else + { + xOffset = 0; + yOffset = 0; + } for (y = 0; y < nHeight; y++) { dstp = (UINT32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); @@ -697,7 +710,7 @@ static int BitBlt_PATCOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi { for (x = 0; x < nWidth; x++) { - patp = (UINT32*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT32*) gdi_get_brush_pointer(hdcDest, x+xOffset, y+yOffset); *dstp = *patp; dstp++; } diff --git a/libfreerdp/gdi/8bpp.c b/libfreerdp/gdi/8bpp.c index c604a94d6..a5b0d51d5 100644 --- a/libfreerdp/gdi/8bpp.c +++ b/libfreerdp/gdi/8bpp.c @@ -536,7 +536,7 @@ static int BitBlt_MERGEPAINT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int n static int BitBlt_PATCOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { - int x, y; + int x, y, xOffset, yOffset; BYTE* dstp; BYTE* patp; BYTE palIndex; @@ -559,6 +559,19 @@ static int BitBlt_PATCOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWid } else { + /* align pattern to 8x8 grid to make sure transition + between different pattern blocks are smooth */ + + if (hdcDest->brush->style == GDI_BS_HATCHED) + { + xOffset = nXDest % 8; + yOffset = nYDest % 8 + 2; // +2 added after comparison to mstsc + } + else + { + xOffset = 0; + yOffset = 0; + } for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); @@ -567,7 +580,7 @@ static int BitBlt_PATCOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWid { for (x = 0; x < nWidth; x++) { - patp = gdi_get_brush_pointer(hdcDest, x, y); + patp = gdi_get_brush_pointer(hdcDest, x+xOffset, y+yOffset); *dstp = *patp; patp++; diff --git a/libfreerdp/gdi/brush.c b/libfreerdp/gdi/brush.c index f1990f9ea..5184112aa 100644 --- a/libfreerdp/gdi/brush.c +++ b/libfreerdp/gdi/brush.c @@ -77,6 +77,15 @@ HGDI_BRUSH gdi_CreatePatternBrush(HGDI_BITMAP hbmp) return hBrush; } +HGDI_BRUSH gdi_CreateHatchBrush(HGDI_BITMAP hbmp) +{ + HGDI_BRUSH hBrush = (HGDI_BRUSH) malloc(sizeof(GDI_BRUSH)); + hBrush->objectType = GDIOBJECT_BRUSH; + hBrush->style = GDI_BS_HATCHED; + hBrush->pattern = hbmp; + return hBrush; +} + /** * Perform a pattern blit operation on the given pixel buffer.\n * @msdn{dd162778} diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index 96719afd9..ca241a08a 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -312,6 +312,16 @@ static const UINT32 rop3_code_table[] = 0x00FF0062 /* 1 */ }; +/* Hatch Patterns as monochrome data */ +static BYTE GDI_BS_HACHTED_PATTERNS[] = { + 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, /* HS_HORIZONTAL */ + 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, /* HS_VERTICAL */ + 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F, /* HS_FDIAGONAL */ + 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE, /* HS_BDIAGONAL */ + 0xF7, 0xF7, 0xF7, 0x00, 0xF7, 0xF7, 0xF7, 0xF7, /* HS_CROSS */ + 0x7E, 0xBD, 0xDB, 0xE7, 0xE7, 0xDB, 0xBD, 0x7E /* HS_DIACROSS */ +}; + /* GDI Helper Functions */ INLINE UINT32 gdi_rop3_code(BYTE code) @@ -342,7 +352,7 @@ INLINE BYTE* gdi_get_brush_pointer(HGDI_DC hdcBrush, int x, int y) if (hdcBrush->brush != NULL) { - if (hdcBrush->brush->style == GDI_BS_PATTERN) + if ((hdcBrush->brush->style == GDI_BS_PATTERN) || (hdcBrush->brush->style == GDI_BS_HATCHED)) { HGDI_BITMAP hBmpBrush = hdcBrush->brush->pattern; @@ -489,6 +499,24 @@ void gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) gdi_DeleteObject((HGDIOBJECT) gdi->drawing->hdc->brush); gdi->drawing->hdc->brush = originalBrush; } + else if (brush->style == GDI_BS_HATCHED) + { + HGDI_BITMAP hBmp; + + data = freerdp_mono_image_convert(GDI_BS_HACHTED_PATTERNS + 8 * brush->hatch, 8, 8, 1, + gdi->dstBpp, patblt->backColor, patblt->foreColor, gdi->clrconv); + + hBmp = gdi_CreateBitmap(8, 8, gdi->drawing->hdc->bitsPerPixel, data); + + originalBrush = gdi->drawing->hdc->brush; + gdi->drawing->hdc->brush = gdi_CreateHatchBrush(hBmp); + + gdi_PatBlt(gdi->drawing->hdc, patblt->nLeftRect, patblt->nTopRect, + patblt->nWidth, patblt->nHeight, gdi_rop3_code(patblt->bRop)); + + gdi_DeleteObject((HGDIOBJECT) gdi->drawing->hdc->brush); + gdi->drawing->hdc->brush = originalBrush; + } else if (brush->style == GDI_BS_PATTERN) { HGDI_BITMAP hBmp;