diff --git a/include/freerdp/gdi/gdi.h b/include/freerdp/gdi/gdi.h index 804fb802e..592c8252a 100644 --- a/include/freerdp/gdi/gdi.h +++ b/include/freerdp/gdi/gdi.h @@ -225,6 +225,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 eb6c3d727..576c18fa1 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; } @@ -666,6 +677,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))) @@ -724,6 +737,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))) @@ -957,6 +972,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,