From 83d58ccfe8b8cab54a17fcc7e3c7879a8e2479f0 Mon Sep 17 00:00:00 2001 From: "zihao.jiang" Date: Fri, 16 Oct 2015 02:52:02 +0800 Subject: [PATCH] GDI: Fix usage of gdi_get_brush_pointer. Currently we get color from brush according to the offset in the paint region. According to MSDN https://msdn.microsoft.com/en-us/library/dd183396(v=vs.85).aspx, it should get color according to dest position instead of offset in paint region. --- include/freerdp/gdi/gdi.h | 2 ++ libfreerdp/gdi/16bpp.c | 23 ++++++++++------------- libfreerdp/gdi/32bpp.c | 25 +++++++++++-------------- libfreerdp/gdi/8bpp.c | 23 ++++++++++------------- libfreerdp/gdi/brush.c | 6 +++--- libfreerdp/gdi/gdi.c | 21 +++++++++++++++++++-- 6 files changed, 55 insertions(+), 45 deletions(-) diff --git a/include/freerdp/gdi/gdi.h b/include/freerdp/gdi/gdi.h index 9736ba724..87bcbc12b 100644 --- a/include/freerdp/gdi/gdi.h +++ b/include/freerdp/gdi/gdi.h @@ -224,6 +224,8 @@ struct _GDI_BRUSH int style; HGDI_BITMAP pattern; GDI_COLOR color; + int nXOrg; + int nYOrg; }; typedef struct _GDI_BRUSH GDI_BRUSH; typedef GDI_BRUSH* HGDI_BRUSH; diff --git a/libfreerdp/gdi/16bpp.c b/libfreerdp/gdi/16bpp.c index 1ee8a0f6b..e292d7c47 100644 --- a/libfreerdp/gdi/16bpp.c +++ b/libfreerdp/gdi/16bpp.c @@ -487,7 +487,7 @@ static BOOL BitBlt_PSDPxax_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nW { for (x = 0; x < nWidth; x++) { - patp = (UINT16*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT16*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = (*srcp & *dstp) | (~(*srcp) & *patp); srcp++; dstp++; @@ -518,7 +518,7 @@ static BOOL BitBlt_SPna_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidt { for (x = 0; x < nWidth; x++) { - patp = (UINT16*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT16*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *srcp & ~(*patp); srcp++; dstp++; @@ -543,7 +543,7 @@ static BOOL BitBlt_DPa_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth { for (x = 0; x < nWidth; x++) { - patp = (UINT16*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT16*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *dstp & *patp; dstp++; @@ -568,7 +568,7 @@ static BOOL BitBlt_PDxn_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidt { for (x = 0; x < nWidth; x++) { - patp = (UINT16*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT16*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *dstp ^ ~(*patp); dstp++; } @@ -626,7 +626,7 @@ static BOOL BitBlt_MERGECOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int { for (x = 0; x < nWidth; x++) { - patp = (UINT16*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT16*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *srcp & *patp; srcp++; dstp++; @@ -692,13 +692,10 @@ static BOOL BitBlt_PATCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nW } 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 + xOffset = 0; + yOffset = 2; // +2 added after comparison to mstsc } else { @@ -713,7 +710,7 @@ static BOOL BitBlt_PATCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nW { for (x = 0; x < nWidth; x++) { - patp = (UINT16*) gdi_get_brush_pointer(hdcDest, x+xOffset, y+yOffset); + patp = (UINT16*) gdi_get_brush_pointer(hdcDest, nXDest + x + xOffset, nYDest + y + yOffset); *dstp = *patp; dstp++; } @@ -759,7 +756,7 @@ static BOOL BitBlt_PATINVERT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int { for (x = 0; x < nWidth; x++) { - patp = (UINT16*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT16*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *patp ^ *dstp; dstp++; } @@ -789,7 +786,7 @@ static BOOL BitBlt_PATPAINT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int n { for (x = 0; x < nWidth; x++) { - patp = (UINT16*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT16*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *dstp | (*patp | ~(*srcp)); srcp++; dstp++; diff --git a/libfreerdp/gdi/32bpp.c b/libfreerdp/gdi/32bpp.c index f9124bbae..74d1b8065 100644 --- a/libfreerdp/gdi/32bpp.c +++ b/libfreerdp/gdi/32bpp.c @@ -526,7 +526,7 @@ static BOOL BitBlt_PSDPxax_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nW { for (x = 0; x < nWidth; x++) { - patp = (UINT32*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT32*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = (*srcp & *dstp) | (~(*srcp) & *patp); srcp++; dstp++; @@ -583,7 +583,7 @@ static BOOL BitBlt_SPDSxax_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nW { for (x = 0; x < nWidth; x++) { - patp = (UINT32*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT32*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *srcp ^ (*patp & (*dstp ^ *srcp)); srcp++; dstp++; @@ -614,7 +614,7 @@ static BOOL BitBlt_SPna_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidt { for (x = 0; x < nWidth; x++) { - patp = (UINT32*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT32*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *srcp & ~(*patp); srcp++; @@ -668,7 +668,7 @@ static BOOL BitBlt_DPa_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth { for (x = 0; x < nWidth; x++) { - patp = (UINT32*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT32*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *dstp & *patp; dstp++; @@ -693,7 +693,7 @@ static BOOL BitBlt_PDxn_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidt { for (x = 0; x < nWidth; x++) { - patp = (UINT32*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT32*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *dstp ^ ~(*patp); dstp++; @@ -723,7 +723,7 @@ static BOOL BitBlt_MERGECOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int { for (x = 0; x < nWidth; x++) { - patp = (UINT32*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT32*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *srcp & *patp; srcp++; @@ -790,13 +790,10 @@ static BOOL BitBlt_PATCOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nW } 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 + xOffset = 0; + yOffset = 2; // +2 added after comparison to mstsc } else { @@ -811,7 +808,7 @@ static BOOL BitBlt_PATCOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nW { for (x = 0; x < nWidth; x++) { - patp = (UINT32*) gdi_get_brush_pointer(hdcDest, x+xOffset, y+yOffset); + patp = (UINT32*) gdi_get_brush_pointer(hdcDest, nXDest + x + xOffset, nYDest + y + yOffset); *dstp = *patp; dstp++; } @@ -857,7 +854,7 @@ static BOOL BitBlt_PATINVERT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int { for (x = 0; x < nWidth; x++) { - patp = (UINT32*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT32*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *patp ^ *dstp; dstp++; } @@ -887,7 +884,7 @@ static BOOL BitBlt_PATPAINT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int n { for (x = 0; x < nWidth; x++) { - patp = (UINT32*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (UINT32*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *dstp | (*patp | ~(*srcp)); srcp++; dstp++; diff --git a/libfreerdp/gdi/8bpp.c b/libfreerdp/gdi/8bpp.c index 4299d38d3..1303bbccb 100644 --- a/libfreerdp/gdi/8bpp.c +++ b/libfreerdp/gdi/8bpp.c @@ -396,7 +396,7 @@ static BOOL BitBlt_PSDPxax_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi { for (x = 0; x < nWidth; x++) { - patp = (BYTE*) gdi_get_brush_pointer(hdcDest, x, y); + patp = (BYTE*) gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = (*srcp & *dstp) | (~(*srcp) & *patp); srcp++; dstp++; @@ -427,7 +427,7 @@ static BOOL BitBlt_SPna_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth { for (x = 0; x < nWidth; x++) { - patp = gdi_get_brush_pointer(hdcDest, x, y); + patp = gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *srcp & ~(*patp); patp++; @@ -454,7 +454,7 @@ static BOOL BitBlt_DPa_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, { for (x = 0; x < nWidth; x++) { - patp = gdi_get_brush_pointer(hdcDest, x, y); + patp = gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *dstp & *patp; dstp++; @@ -479,7 +479,7 @@ static BOOL BitBlt_PDxn_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth { for (x = 0; x < nWidth; x++) { - patp = gdi_get_brush_pointer(hdcDest, x, y); + patp = gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *dstp ^ ~(*patp); patp++; @@ -538,7 +538,7 @@ static BOOL BitBlt_MERGECOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int n { for (x = 0; x < nWidth; x++) { - patp = gdi_get_brush_pointer(hdcDest, x, y); + patp = gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *srcp & *patp; patp++; @@ -604,13 +604,10 @@ static BOOL BitBlt_PATCOPY_8bpp(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 + xOffset = 0; + yOffset = 2; // +2 added after comparison to mstsc } else { @@ -625,7 +622,7 @@ static BOOL BitBlt_PATCOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi { for (x = 0; x < nWidth; x++) { - patp = gdi_get_brush_pointer(hdcDest, x+xOffset, y+yOffset); + patp = gdi_get_brush_pointer(hdcDest, nXDest + x + xOffset, nYDest + y + yOffset); *dstp = *patp; patp++; @@ -671,7 +668,7 @@ static BOOL BitBlt_PATINVERT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int n { for (x = 0; x < nWidth; x++) { - patp = gdi_get_brush_pointer(hdcDest, x, y); + patp = gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *patp ^ *dstp; patp++; @@ -703,7 +700,7 @@ static BOOL BitBlt_PATPAINT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nW { for (x = 0; x < nWidth; x++) { - patp = gdi_get_brush_pointer(hdcDest, x, y); + patp = gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y); *dstp = *dstp | (*patp | ~(*srcp)); patp++; diff --git a/libfreerdp/gdi/brush.c b/libfreerdp/gdi/brush.c index 0fadb9768..4a83e043c 100644 --- a/libfreerdp/gdi/brush.c +++ b/libfreerdp/gdi/brush.c @@ -53,7 +53,7 @@ p_PatBlt PatBlt_[5] = HGDI_BRUSH gdi_CreateSolidBrush(GDI_COLOR crColor) { - HGDI_BRUSH hBrush = (HGDI_BRUSH) malloc(sizeof(GDI_BRUSH)); + HGDI_BRUSH hBrush = (HGDI_BRUSH) calloc(1, sizeof(GDI_BRUSH)); if (!hBrush) return NULL; hBrush->objectType = GDIOBJECT_BRUSH; @@ -71,7 +71,7 @@ HGDI_BRUSH gdi_CreateSolidBrush(GDI_COLOR crColor) HGDI_BRUSH gdi_CreatePatternBrush(HGDI_BITMAP hbmp) { - HGDI_BRUSH hBrush = (HGDI_BRUSH) malloc(sizeof(GDI_BRUSH)); + HGDI_BRUSH hBrush = (HGDI_BRUSH) calloc(1, sizeof(GDI_BRUSH)); if (!hBrush) return NULL; hBrush->objectType = GDIOBJECT_BRUSH; @@ -82,7 +82,7 @@ HGDI_BRUSH gdi_CreatePatternBrush(HGDI_BITMAP hbmp) HGDI_BRUSH gdi_CreateHatchBrush(HGDI_BITMAP hbmp) { - HGDI_BRUSH hBrush = (HGDI_BRUSH) malloc(sizeof(GDI_BRUSH)); + HGDI_BRUSH hBrush = (HGDI_BRUSH) calloc(1, sizeof(GDI_BRUSH)); if (!hBrush) return NULL; hBrush->objectType = GDIOBJECT_BRUSH; diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index 271ecd7ef..3e62ad135 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -371,6 +371,13 @@ INLINE BYTE* gdi_get_bitmap_pointer(HGDI_DC hdcBmp, int x, int y) } } +/** + * Get current color in brush bitmap according to dest coordinates.\n + * @msdn{dd183396} + * @param x dest x-coordinate + * @param y dest y-coordinate + * @return color + */ INLINE BYTE* gdi_get_brush_pointer(HGDI_DC hdcBrush, int x, int y) { BYTE * p; @@ -381,10 +388,14 @@ INLINE BYTE* gdi_get_brush_pointer(HGDI_DC hdcBrush, int x, int y) { HGDI_BITMAP hBmpBrush = hdcBrush->brush->pattern; + /* According to @msdn{dd183396}, the system always positions a brush bitmap + * at the brush origin and copy across the client area. + * Calculate the offset of the mapped pixel in the brush bitmap according to + * brush origin and dest coordinates */ if (x >= 0 && y >= 0) { - x = x % hBmpBrush->width; - y = y % hBmpBrush->height; + x = (x + hBmpBrush->width - (hdcBrush->brush->nXOrg % hBmpBrush->width)) % hBmpBrush->width; + y = (y + hBmpBrush->height - (hdcBrush->brush->nYOrg % hBmpBrush->height)) % hBmpBrush->height; p = hBmpBrush->data + (y * hBmpBrush->scanline) + (x * hBmpBrush->bytesPerPixel); return p; } @@ -661,6 +672,8 @@ static BOOL gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) ret = FALSE; goto out_error; } + gdi->drawing->hdc->brush->nXOrg = brush->x; + gdi->drawing->hdc->brush->nYOrg = brush->y; if (!gdi_PatBlt(gdi->drawing->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight, gdi_rop3_code(patblt->bRop))) @@ -719,6 +732,8 @@ static BOOL gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) ret = FALSE; goto out_error; } + gdi->drawing->hdc->brush->nXOrg = brush->x; + gdi->drawing->hdc->brush->nYOrg = brush->y; if (!gdi_PatBlt(gdi->drawing->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight, gdi_rop3_code(patblt->bRop))) @@ -952,6 +967,8 @@ static BOOL gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) gdi_DeleteObject((HGDIOBJECT) hBmp); goto out_fail; } + gdi->drawing->hdc->brush->nXOrg = brush->x; + gdi->drawing->hdc->brush->nYOrg = brush->y; gdi_BitBlt(gdi->drawing->hdc, mem3blt->nLeftRect, mem3blt->nTopRect, mem3blt->nWidth, mem3blt->nHeight, bitmap->hdc,