libfreerdp-gdi: added brush style BS_HATCHED
authorChristian Landvogt <c.landvogt@web.de>
Mon, 4 Feb 2013 14:58:22 +0000 (15:58 +0100)
committerChristian Landvogt <c.landvogt@web.de>
Mon, 4 Feb 2013 14:58:22 +0000 (15:58 +0100)
according to [MS-RDPEGDI] 2.2.2.2.1.1.2.3 PatBlt (PATBLT_ORDER)
16bit and 8bit colour depth are drawn with wrong background colour

include/freerdp/gdi/brush.h
libfreerdp/gdi/16bpp.c
libfreerdp/gdi/32bpp.c
libfreerdp/gdi/8bpp.c
libfreerdp/gdi/brush.c
libfreerdp/gdi/gdi.c

index 842f95a..10b81cb 100644 (file)
@@ -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);
index 77eb60f..e782655 100644 (file)
@@ -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++;
                                }
index fadefe9..5c1b647 100644 (file)
@@ -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++;
                                }
index c604a94..a5b0d51 100644 (file)
@@ -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++;
index f1990f9..5184112 100644 (file)
@@ -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}
index 96719af..ca241a0 100644 (file)
@@ -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;