Blame client/X11/xf_gdi.c

Packit Service fa4841
/**
Packit Service fa4841
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit Service fa4841
 * X11 GDI
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit Service fa4841
 * Copyright 2014 Thincast Technologies GmbH
Packit Service fa4841
 * Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
#ifdef HAVE_CONFIG_H
Packit Service fa4841
#include "config.h"
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#include <X11/Xlib.h>
Packit Service fa4841
#include <X11/Xutil.h>
Packit Service fa4841
Packit Service fa4841
#include <freerdp/gdi/gdi.h>
Packit Service fa4841
#include <freerdp/codec/rfx.h>
Packit Service fa4841
#include <freerdp/codec/nsc.h>
Packit Service fa4841
#include <freerdp/constants.h>
Packit Service fa4841
#include <freerdp/codec/color.h>
Packit Service fa4841
#include <freerdp/codec/bitmap.h>
Packit Service fa4841
Packit Service fa4841
#include "xf_gdi.h"
Packit Service fa4841
#include "xf_graphics.h"
Packit Service fa4841
Packit Service fa4841
#include <freerdp/log.h>
Packit Service fa4841
#define TAG CLIENT_TAG("x11")
Packit Service fa4841
Packit Service b1ea74
static const UINT8 GDI_BS_HATCHED_PATTERNS[] = {
Packit Service fa4841
	0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, /* HS_HORIZONTAL */
Packit Service fa4841
	0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, /* HS_VERTICAL */
Packit Service fa4841
	0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F, /* HS_FDIAGONAL */
Packit Service fa4841
	0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE, /* HS_BDIAGONAL */
Packit Service fa4841
	0xF7, 0xF7, 0xF7, 0x00, 0xF7, 0xF7, 0xF7, 0xF7, /* HS_CROSS */
Packit Service b1ea74
	0x7E, 0xBD, 0xDB, 0xE7, 0xE7, 0xDB, 0xBD, 0x7E  /* HS_DIACROSS */
Packit Service fa4841
};
Packit Service fa4841
Packit Service b1ea74
static const BYTE xf_rop2_table[] = {
Packit Service fa4841
	0,
Packit Service fa4841
	GXclear,        /* 0 */
Packit Service fa4841
	GXnor,          /* DPon */
Packit Service fa4841
	GXandInverted,  /* DPna */
Packit Service fa4841
	GXcopyInverted, /* Pn */
Packit Service fa4841
	GXandReverse,   /* PDna */
Packit Service fa4841
	GXinvert,       /* Dn */
Packit Service fa4841
	GXxor,          /* DPx */
Packit Service fa4841
	GXnand,         /* DPan */
Packit Service fa4841
	GXand,          /* DPa */
Packit Service fa4841
	GXequiv,        /* DPxn */
Packit Service fa4841
	GXnoop,         /* D */
Packit Service fa4841
	GXorInverted,   /* DPno */
Packit Service fa4841
	GXcopy,         /* P */
Packit Service fa4841
	GXorReverse,    /* PDno */
Packit Service fa4841
	GXor,           /* DPo */
Packit Service fa4841
	GXset           /* 1 */
Packit Service fa4841
};
Packit Service fa4841
Packit Service fa4841
static BOOL xf_set_rop2(xfContext* xfc, int rop2)
Packit Service fa4841
{
Packit Service fa4841
	if ((rop2 < 0x01) || (rop2 > 0x10))
Packit Service fa4841
	{
Packit Service b1ea74
		WLog_ERR(TAG, "Unsupported ROP2: %d", rop2);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, xf_rop2_table[rop2]);
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL xf_set_rop3(xfContext* xfc, UINT32 rop3)
Packit Service fa4841
{
Packit Service fa4841
	int function = -1;
Packit Service fa4841
Packit Service fa4841
	switch (rop3)
Packit Service fa4841
	{
Packit Service fa4841
		case GDI_BLACKNESS:
Packit Service fa4841
			function = GXclear;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_DPon:
Packit Service fa4841
			function = GXnor;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_DPna:
Packit Service fa4841
			function = GXandInverted;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_Pn:
Packit Service fa4841
			function = GXcopyInverted;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_NOTSRCERASE:
Packit Service fa4841
			function = GXnor;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_DSna:
Packit Service fa4841
			function = GXandInverted;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_NOTSRCCOPY:
Packit Service fa4841
			function = GXcopyInverted;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_SRCERASE:
Packit Service fa4841
			function = GXandReverse;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_PDna:
Packit Service fa4841
			function = GXandReverse;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_DSTINVERT:
Packit Service fa4841
			function = GXinvert;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_PATINVERT:
Packit Service fa4841
			function = GXxor;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_DPan:
Packit Service fa4841
			function = GXnand;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_SRCINVERT:
Packit Service fa4841
			function = GXxor;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_DSan:
Packit Service fa4841
			function = GXnand;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_SRCAND:
Packit Service fa4841
			function = GXand;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_DSxn:
Packit Service fa4841
			function = GXequiv;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_DPa:
Packit Service fa4841
			function = GXand;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_PDxn:
Packit Service fa4841
			function = GXequiv;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_DSTCOPY:
Packit Service fa4841
			function = GXnoop;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_DPno:
Packit Service fa4841
			function = GXorInverted;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_MERGEPAINT:
Packit Service fa4841
			function = GXorInverted;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_SRCCOPY:
Packit Service fa4841
			function = GXcopy;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_SDno:
Packit Service fa4841
			function = GXorReverse;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_SRCPAINT:
Packit Service fa4841
			function = GXor;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_PATCOPY:
Packit Service fa4841
			function = GXcopy;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_PDno:
Packit Service fa4841
			function = GXorReverse;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_DPo:
Packit Service fa4841
			function = GXor;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_WHITENESS:
Packit Service fa4841
			function = GXset;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_PSDPxax:
Packit Service fa4841
			function = GXand;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		default:
Packit Service fa4841
			break;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (function < 0)
Packit Service fa4841
	{
Packit Service b1ea74
		WLog_ERR(TAG, "Unsupported ROP3: 0x%08" PRIX32 "", rop3);
Packit Service fa4841
		XSetFunction(xfc->display, xfc->gc, GXclear);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, function);
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static Pixmap xf_brush_new(xfContext* xfc, UINT32 width, UINT32 height, UINT32 bpp, BYTE* data)
Packit Service fa4841
{
Packit Service fa4841
	GC gc;
Packit Service fa4841
	Pixmap bitmap;
Packit Service fa4841
	BYTE* cdata;
Packit Service fa4841
	XImage* image;
Packit Service fa4841
	rdpGdi* gdi;
Packit Service fa4841
	UINT32 brushFormat;
Packit Service fa4841
	gdi = xfc->context.gdi;
Packit Service fa4841
	bitmap = XCreatePixmap(xfc->display, xfc->drawable, width, height, xfc->depth);
Packit Service fa4841
Packit Service fa4841
	if (data)
Packit Service fa4841
	{
Packit Service fa4841
		brushFormat = gdi_get_pixel_format(bpp);
Packit Service b1ea74
		cdata = (BYTE*)_aligned_malloc(width * height * 4, 16);
Packit Service b1ea74
		freerdp_image_copy(cdata, gdi->dstFormat, 0, 0, 0, width, height, data, brushFormat, 0, 0,
Packit Service b1ea74
		                   0, &xfc->context.gdi->palette, FREERDP_FLIP_NONE);
Packit Service b1ea74
		image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*)cdata, width,
Packit Service b1ea74
		                     height, xfc->scanline_pad, 0);
Packit Service fa4841
		image->byte_order = LSBFirst;
Packit Service fa4841
		image->bitmap_bit_order = LSBFirst;
Packit Service fa4841
		gc = XCreateGC(xfc->display, xfc->drawable, 0, NULL);
Packit Service fa4841
		XPutImage(xfc->display, bitmap, gc, image, 0, 0, 0, 0, width, height);
Packit Service fa4841
		image->data = NULL;
Packit Service fa4841
		XDestroyImage(image);
Packit Service fa4841
Packit Service fa4841
		if (cdata != data)
Packit Service fa4841
			_aligned_free(cdata);
Packit Service fa4841
Packit Service fa4841
		XFreeGC(xfc->display, gc);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return bitmap;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static Pixmap xf_mono_bitmap_new(xfContext* xfc, int width, int height, const BYTE* data)
Packit Service fa4841
{
Packit Service fa4841
	int scanline;
Packit Service fa4841
	XImage* image;
Packit Service fa4841
	Pixmap bitmap;
Packit Service fa4841
	scanline = (width + 7) / 8;
Packit Service fa4841
	bitmap = XCreatePixmap(xfc->display, xfc->drawable, width, height, 1);
Packit Service b1ea74
	image = XCreateImage(xfc->display, xfc->visual, 1, ZPixmap, 0, (char*)data, width, height, 8,
Packit Service b1ea74
	                     scanline);
Packit Service fa4841
	image->byte_order = LSBFirst;
Packit Service fa4841
	image->bitmap_bit_order = LSBFirst;
Packit Service fa4841
	XPutImage(xfc->display, bitmap, xfc->gc_mono, image, 0, 0, 0, 0, width, height);
Packit Service fa4841
	image->data = NULL;
Packit Service fa4841
	XDestroyImage(image);
Packit Service fa4841
	return bitmap;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL xf_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds)
Packit Service fa4841
{
Packit Service fa4841
	XRectangle clip;
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
Packit Service fa4841
	if (bounds)
Packit Service fa4841
	{
Packit Service fa4841
		clip.x = bounds->left;
Packit Service fa4841
		clip.y = bounds->top;
Packit Service fa4841
		clip.width = bounds->right - bounds->left + 1;
Packit Service fa4841
		clip.height = bounds->bottom - bounds->top + 1;
Packit Service fa4841
		XSetClipRectangles(xfc->display, xfc->gc, 0, 0, &clip, 1, YXBanded);
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		XSetClipMask(xfc->display, xfc->gc, None);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL xf_gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt)
Packit Service fa4841
{
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service fa4841
	BOOL ret = FALSE;
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
Packit Service fa4841
	if (!xf_set_rop3(xfc, gdi_rop3_code(dstblt->bRop)))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);
Packit Service b1ea74
	XFillRectangle(xfc->display, xfc->drawing, xfc->gc, dstblt->nLeftRect, dstblt->nTopRect,
Packit Service fa4841
	               dstblt->nWidth, dstblt->nHeight);
Packit Service fa4841
	ret = TRUE;
Packit Service fa4841
Packit Service fa4841
	if (xfc->drawing == xfc->primary)
Packit Service b1ea74
		ret = gdi_InvalidateRegion(xfc->hdc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth,
Packit Service b1ea74
		                           dstblt->nHeight);
Packit Service fa4841
Packit Service fa4841
fail:
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
Packit Service fa4841
{
Packit Service fa4841
	const rdpBrush* brush;
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service fa4841
	BOOL ret = FALSE;
Packit Service fa4841
	XColor xfg, xbg;
Packit Service fa4841
Packit Service fa4841
	if (!xf_decode_color(xfc, patblt->foreColor, &xfg))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!xf_decode_color(xfc, patblt->backColor, &xbg))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
	brush = &patblt->brush;
Packit Service fa4841
Packit Service fa4841
	if (!xf_set_rop3(xfc, gdi_rop3_code(patblt->bRop)))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	switch (brush->style)
Packit Service fa4841
	{
Packit Service fa4841
		case GDI_BS_SOLID:
Packit Service fa4841
			XSetFillStyle(xfc->display, xfc->gc, FillSolid);
Packit Service fa4841
			XSetBackground(xfc->display, xfc->gc, xbg.pixel);
Packit Service fa4841
			XSetForeground(xfc->display, xfc->gc, xfg.pixel);
Packit Service b1ea74
			XFillRectangle(xfc->display, xfc->drawing, xfc->gc, patblt->nLeftRect, patblt->nTopRect,
Packit Service b1ea74
			               patblt->nWidth, patblt->nHeight);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_BS_HATCHED:
Packit Service b1ea74
		{
Packit Service b1ea74
			Pixmap pattern =
Packit Service b1ea74
			    xf_mono_bitmap_new(xfc, 8, 8, &GDI_BS_HATCHED_PATTERNS[8 * brush->hatch]);
Packit Service b1ea74
			XSetBackground(xfc->display, xfc->gc, xbg.pixel);
Packit Service b1ea74
			XSetForeground(xfc->display, xfc->gc, xfg.pixel);
Packit Service b1ea74
			XSetFillStyle(xfc->display, xfc->gc, FillOpaqueStippled);
Packit Service b1ea74
			XSetStipple(xfc->display, xfc->gc, pattern);
Packit Service b1ea74
			XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y);
Packit Service b1ea74
			XFillRectangle(xfc->display, xfc->drawing, xfc->gc, patblt->nLeftRect, patblt->nTopRect,
Packit Service b1ea74
			               patblt->nWidth, patblt->nHeight);
Packit Service b1ea74
			XFreePixmap(xfc->display, pattern);
Packit Service b1ea74
		}
Packit Service b1ea74
		break;
Packit Service fa4841
Packit Service fa4841
		case GDI_BS_PATTERN:
Packit Service fa4841
			if (brush->bpp > 1)
Packit Service fa4841
			{
Packit Service fa4841
				UINT32 bpp = brush->bpp;
Packit Service fa4841
Packit Service fa4841
				if ((bpp == 16) && (context->settings->ColorDepth == 15))
Packit Service fa4841
					bpp = 15;
Packit Service fa4841
Packit Service fa4841
				Pixmap pattern = xf_brush_new(xfc, 8, 8, bpp, brush->data);
Packit Service fa4841
				XSetFillStyle(xfc->display, xfc->gc, FillTiled);
Packit Service fa4841
				XSetTile(xfc->display, xfc->gc, pattern);
Packit Service fa4841
				XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y);
Packit Service b1ea74
				XFillRectangle(xfc->display, xfc->drawing, xfc->gc, patblt->nLeftRect,
Packit Service b1ea74
				               patblt->nTopRect, patblt->nWidth, patblt->nHeight);
Packit Service fa4841
				XSetTile(xfc->display, xfc->gc, xfc->primary);
Packit Service fa4841
				XFreePixmap(xfc->display, pattern);
Packit Service fa4841
			}
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service fa4841
				Pixmap pattern = xf_mono_bitmap_new(xfc, 8, 8, brush->data);
Packit Service fa4841
				XSetBackground(xfc->display, xfc->gc, xfg.pixel);
Packit Service fa4841
				XSetForeground(xfc->display, xfc->gc, xbg.pixel);
Packit Service fa4841
				XSetFillStyle(xfc->display, xfc->gc, FillOpaqueStippled);
Packit Service fa4841
				XSetStipple(xfc->display, xfc->gc, pattern);
Packit Service fa4841
				XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y);
Packit Service b1ea74
				XFillRectangle(xfc->display, xfc->drawing, xfc->gc, patblt->nLeftRect,
Packit Service b1ea74
				               patblt->nTopRect, patblt->nWidth, patblt->nHeight);
Packit Service fa4841
				XFreePixmap(xfc->display, pattern);
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		default:
Packit Service b1ea74
			WLog_ERR(TAG, "unimplemented brush style:%" PRIu32 "", brush->style);
Packit Service fa4841
			goto fail;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	ret = TRUE;
Packit Service fa4841
Packit Service fa4841
	if (xfc->drawing == xfc->primary)
Packit Service b1ea74
		ret = gdi_InvalidateRegion(xfc->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth,
Packit Service b1ea74
		                           patblt->nHeight);
Packit Service fa4841
Packit Service fa4841
fail:
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL xf_gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt)
Packit Service fa4841
{
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service fa4841
	BOOL ret = FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!xfc->display || !xfc->drawing)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
Packit Service fa4841
	if (!xf_set_rop3(xfc, gdi_rop3_code(scrblt->bRop)))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service b1ea74
	XCopyArea(xfc->display, xfc->primary, xfc->drawing, xfc->gc, scrblt->nXSrc, scrblt->nYSrc,
Packit Service fa4841
	          scrblt->nWidth, scrblt->nHeight, scrblt->nLeftRect, scrblt->nTopRect);
Packit Service fa4841
	ret = TRUE;
Packit Service fa4841
Packit Service fa4841
	if (xfc->drawing == xfc->primary)
Packit Service b1ea74
		ret = gdi_InvalidateRegion(xfc->hdc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth,
Packit Service b1ea74
		                           scrblt->nHeight);
Packit Service fa4841
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service fa4841
fail:
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL xf_gdi_opaque_rect(rdpContext* context, const OPAQUE_RECT_ORDER* opaque_rect)
Packit Service fa4841
{
Packit Service fa4841
	XColor color;
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service fa4841
	BOOL ret = TRUE;
Packit Service fa4841
Packit Service fa4841
	if (!xf_decode_color(xfc, opaque_rect->color, &color))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service fa4841
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);
Packit Service fa4841
	XSetForeground(xfc->display, xfc->gc, color.pixel);
Packit Service b1ea74
	XFillRectangle(xfc->display, xfc->drawing, xfc->gc, opaque_rect->nLeftRect,
Packit Service b1ea74
	               opaque_rect->nTopRect, opaque_rect->nWidth, opaque_rect->nHeight);
Packit Service fa4841
Packit Service fa4841
	if (xfc->drawing == xfc->primary)
Packit Service b1ea74
		ret = gdi_InvalidateRegion(xfc->hdc, opaque_rect->nLeftRect, opaque_rect->nTopRect,
Packit Service fa4841
		                           opaque_rect->nWidth, opaque_rect->nHeight);
Packit Service fa4841
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL xf_gdi_multi_opaque_rect(rdpContext* context,
Packit Service fa4841
                                     const MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 i;
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service fa4841
	BOOL ret = TRUE;
Packit Service fa4841
	XColor color;
Packit Service fa4841
Packit Service fa4841
	if (!xf_decode_color(xfc, multi_opaque_rect->color, &color))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service fa4841
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);
Packit Service fa4841
	XSetForeground(xfc->display, xfc->gc, color.pixel);
Packit Service fa4841
Packit Service fa4841
	for (i = 0; i < multi_opaque_rect->numRectangles; i++)
Packit Service fa4841
	{
Packit Service fa4841
		const DELTA_RECT* rectangle = &multi_opaque_rect->rectangles[i];
Packit Service b1ea74
		XFillRectangle(xfc->display, xfc->drawing, xfc->gc, rectangle->left, rectangle->top,
Packit Service fa4841
		               rectangle->width, rectangle->height);
Packit Service fa4841
Packit Service fa4841
		if (xfc->drawing == xfc->primary)
Packit Service fa4841
		{
Packit Service fa4841
			if (!(ret = gdi_InvalidateRegion(xfc->hdc, rectangle->left, rectangle->top,
Packit Service fa4841
			                                 rectangle->width, rectangle->height)))
Packit Service fa4841
				break;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL xf_gdi_line_to(rdpContext* context, const LINE_TO_ORDER* line_to)
Packit Service fa4841
{
Packit Service fa4841
	XColor color;
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service fa4841
	BOOL ret = TRUE;
Packit Service fa4841
Packit Service fa4841
	if (!xf_decode_color(xfc, line_to->penColor, &color))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
	xf_set_rop2(xfc, line_to->bRop2);
Packit Service fa4841
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);
Packit Service fa4841
	XSetForeground(xfc->display, xfc->gc, color.pixel);
Packit Service b1ea74
	XDrawLine(xfc->display, xfc->drawing, xfc->gc, line_to->nXStart, line_to->nYStart,
Packit Service b1ea74
	          line_to->nXEnd, line_to->nYEnd);
Packit Service fa4841
Packit Service fa4841
	if (xfc->drawing == xfc->primary)
Packit Service fa4841
	{
Packit Service fa4841
		int x, y, w, h;
Packit Service fa4841
		x = MIN(line_to->nXStart, line_to->nXEnd);
Packit Service fa4841
		y = MIN(line_to->nYStart, line_to->nYEnd);
Packit Service fa4841
		w = abs(line_to->nXEnd - line_to->nXStart) + 1;
Packit Service fa4841
		h = abs(line_to->nYEnd - line_to->nYStart) + 1;
Packit Service fa4841
		ret = gdi_InvalidateRegion(xfc->hdc, x, y, w, h);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL xf_gdi_invalidate_poly_region(xfContext* xfc, XPoint* points, int npoints)
Packit Service fa4841
{
Packit Service fa4841
	int x, y, x1, y1, x2, y2;
Packit Service fa4841
Packit Service fa4841
	if (npoints < 2)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	x = x1 = x2 = points->x;
Packit Service fa4841
	y = y1 = y2 = points->y;
Packit Service fa4841
Packit Service fa4841
	while (--npoints)
Packit Service fa4841
	{
Packit Service fa4841
		points++;
Packit Service fa4841
		x += points->x;
Packit Service fa4841
		y += points->y;
Packit Service fa4841
Packit Service fa4841
		if (x > x2)
Packit Service fa4841
			x2 = x;
Packit Service fa4841
Packit Service fa4841
		if (x < x1)
Packit Service fa4841
			x1 = x;
Packit Service fa4841
Packit Service fa4841
		if (y > y2)
Packit Service fa4841
			y2 = y;
Packit Service fa4841
Packit Service fa4841
		if (y < y1)
Packit Service fa4841
			y1 = y;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	x2++;
Packit Service fa4841
	y2++;
Packit Service fa4841
	return gdi_InvalidateRegion(xfc->hdc, x1, y1, x2 - x1, y2 - y1);
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL xf_gdi_polyline(rdpContext* context, const POLYLINE_ORDER* polyline)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 i;
Packit Service fa4841
	int npoints;
Packit Service fa4841
	XColor color;
Packit Service fa4841
	XPoint* points;
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service fa4841
	BOOL ret = TRUE;
Packit Service fa4841
Packit Service fa4841
	if (!xf_decode_color(xfc, polyline->penColor, &color))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
	xf_set_rop2(xfc, polyline->bRop2);
Packit Service fa4841
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);
Packit Service fa4841
	XSetForeground(xfc->display, xfc->gc, color.pixel);
Packit Service fa4841
	npoints = polyline->numDeltaEntries + 1;
Packit Service fa4841
	points = calloc(npoints, sizeof(XPoint));
Packit Service fa4841
Packit Service fa4841
	if (!points)
Packit Service fa4841
	{
Packit Service b1ea74
		xf_unlock_x11(xfc);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	points[0].x = polyline->xStart;
Packit Service fa4841
	points[0].y = polyline->yStart;
Packit Service fa4841
Packit Service fa4841
	for (i = 0; i < polyline->numDeltaEntries; i++)
Packit Service fa4841
	{
Packit Service fa4841
		points[i + 1].x = polyline->points[i].x;
Packit Service fa4841
		points[i + 1].y = polyline->points[i].y;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service b1ea74
	XDrawLines(xfc->display, xfc->drawing, xfc->gc, points, npoints, CoordModePrevious);
Packit Service fa4841
Packit Service fa4841
	if (xfc->drawing == xfc->primary)
Packit Service fa4841
	{
Packit Service fa4841
		if (!xf_gdi_invalidate_poly_region(xfc, points, npoints))
Packit Service fa4841
			ret = FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service fa4841
	free(points);
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
Packit Service fa4841
{
Packit Service fa4841
	xfBitmap* bitmap;
Packit Service fa4841
	xfContext* xfc;
Packit Service fa4841
	BOOL ret = TRUE;
Packit Service fa4841
Packit Service fa4841
	if (!context || !memblt)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service b1ea74
	bitmap = (xfBitmap*)memblt->bitmap;
Packit Service b1ea74
	xfc = (xfContext*)context;
Packit Service fa4841
Packit Service fa4841
	if (!bitmap || !xfc || !xfc->display || !xfc->drawing)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
Packit Service fa4841
	if (xf_set_rop3(xfc, gdi_rop3_code(memblt->bRop)))
Packit Service fa4841
	{
Packit Service b1ea74
		XCopyArea(xfc->display, bitmap->pixmap, xfc->drawing, xfc->gc, memblt->nXSrc, memblt->nYSrc,
Packit Service b1ea74
		          memblt->nWidth, memblt->nHeight, memblt->nLeftRect, memblt->nTopRect);
Packit Service fa4841
Packit Service fa4841
		if (xfc->drawing == xfc->primary)
Packit Service b1ea74
			ret = gdi_InvalidateRegion(xfc->hdc, memblt->nLeftRect, memblt->nTopRect,
Packit Service b1ea74
			                           memblt->nWidth, memblt->nHeight);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
Packit Service fa4841
{
Packit Service fa4841
	const rdpBrush* brush;
Packit Service fa4841
	xfBitmap* bitmap;
Packit Service fa4841
	XColor foreColor;
Packit Service fa4841
	XColor backColor;
Packit Service fa4841
	Pixmap pattern = 0;
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service fa4841
	BOOL ret = FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!xfc->display || !xfc->drawing)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!xf_decode_color(xfc, mem3blt->foreColor, &foreColor))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!xf_decode_color(xfc, mem3blt->backColor, &backColor))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
	brush = &mem3blt->brush;
Packit Service b1ea74
	bitmap = (xfBitmap*)mem3blt->bitmap;
Packit Service fa4841
Packit Service fa4841
	if (!xf_set_rop3(xfc, gdi_rop3_code(mem3blt->bRop)))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	switch (brush->style)
Packit Service fa4841
	{
Packit Service fa4841
		case GDI_BS_PATTERN:
Packit Service fa4841
			if (brush->bpp > 1)
Packit Service fa4841
			{
Packit Service fa4841
				UINT32 bpp = brush->bpp;
Packit Service fa4841
Packit Service fa4841
				if ((bpp == 16) && (context->settings->ColorDepth == 15))
Packit Service fa4841
					bpp = 15;
Packit Service fa4841
Packit Service fa4841
				pattern = xf_brush_new(xfc, 8, 8, bpp, brush->data);
Packit Service fa4841
				XSetFillStyle(xfc->display, xfc->gc, FillTiled);
Packit Service fa4841
				XSetTile(xfc->display, xfc->gc, pattern);
Packit Service fa4841
				XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y);
Packit Service fa4841
			}
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service fa4841
				pattern = xf_mono_bitmap_new(xfc, 8, 8, brush->data);
Packit Service fa4841
				XSetBackground(xfc->display, xfc->gc, backColor.pixel);
Packit Service fa4841
				XSetForeground(xfc->display, xfc->gc, foreColor.pixel);
Packit Service fa4841
				XSetFillStyle(xfc->display, xfc->gc, FillOpaqueStippled);
Packit Service fa4841
				XSetStipple(xfc->display, xfc->gc, pattern);
Packit Service fa4841
				XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y);
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_BS_SOLID:
Packit Service fa4841
			XSetFillStyle(xfc->display, xfc->gc, FillSolid);
Packit Service fa4841
			XSetBackground(xfc->display, xfc->gc, backColor.pixel);
Packit Service fa4841
			XSetForeground(xfc->display, xfc->gc, foreColor.pixel);
Packit Service fa4841
			XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		default:
Packit Service b1ea74
			WLog_ERR(TAG, "Mem3Blt unimplemented brush style:%" PRIu32 "", brush->style);
Packit Service fa4841
			goto fail;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service b1ea74
	XCopyArea(xfc->display, bitmap->pixmap, xfc->drawing, xfc->gc, mem3blt->nXSrc, mem3blt->nYSrc,
Packit Service b1ea74
	          mem3blt->nWidth, mem3blt->nHeight, mem3blt->nLeftRect, mem3blt->nTopRect);
Packit Service fa4841
	ret = TRUE;
Packit Service fa4841
Packit Service fa4841
	if (xfc->drawing == xfc->primary)
Packit Service b1ea74
		ret = gdi_InvalidateRegion(xfc->hdc, mem3blt->nLeftRect, mem3blt->nTopRect, mem3blt->nWidth,
Packit Service b1ea74
		                           mem3blt->nHeight);
Packit Service fa4841
Packit Service fa4841
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);
Packit Service fa4841
	XSetTSOrigin(xfc->display, xfc->gc, 0, 0);
Packit Service fa4841
Packit Service fa4841
	if (pattern != 0)
Packit Service fa4841
		XFreePixmap(xfc->display, pattern);
Packit Service fa4841
Packit Service fa4841
fail:
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL xf_gdi_polygon_sc(rdpContext* context, const POLYGON_SC_ORDER* polygon_sc)
Packit Service fa4841
{
Packit Service b1ea74
	UINT32 i;
Packit Service b1ea74
	int npoints;
Packit Service fa4841
	XPoint* points;
Packit Service fa4841
	XColor brush_color;
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service fa4841
	BOOL ret = TRUE;
Packit Service fa4841
Packit Service fa4841
	if (!xf_decode_color(xfc, polygon_sc->brushColor, &brush_color))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
	xf_set_rop2(xfc, polygon_sc->bRop2);
Packit Service fa4841
	npoints = polygon_sc->numPoints + 1;
Packit Service fa4841
	points = calloc(npoints, sizeof(XPoint));
Packit Service fa4841
Packit Service fa4841
	if (!points)
Packit Service fa4841
	{
Packit Service b1ea74
		xf_unlock_x11(xfc);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	points[0].x = polygon_sc->xStart;
Packit Service fa4841
	points[0].y = polygon_sc->yStart;
Packit Service fa4841
Packit Service fa4841
	for (i = 0; i < polygon_sc->numPoints; i++)
Packit Service fa4841
	{
Packit Service fa4841
		points[i + 1].x = polygon_sc->points[i].x;
Packit Service fa4841
		points[i + 1].y = polygon_sc->points[i].y;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	switch (polygon_sc->fillMode)
Packit Service fa4841
	{
Packit Service fa4841
		case 1: /* alternate */
Packit Service fa4841
			XSetFillRule(xfc->display, xfc->gc, EvenOddRule);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 2: /* winding */
Packit Service fa4841
			XSetFillRule(xfc->display, xfc->gc, WindingRule);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		default:
Packit Service b1ea74
			WLog_ERR(TAG, "PolygonSC unknown fillMode: %" PRIu32 "", polygon_sc->fillMode);
Packit Service fa4841
			break;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);
Packit Service fa4841
	XSetForeground(xfc->display, xfc->gc, brush_color.pixel);
Packit Service b1ea74
	XFillPolygon(xfc->display, xfc->drawing, xfc->gc, points, npoints, Complex, CoordModePrevious);
Packit Service fa4841
Packit Service fa4841
	if (xfc->drawing == xfc->primary)
Packit Service fa4841
	{
Packit Service fa4841
		if (!xf_gdi_invalidate_poly_region(xfc, points, npoints))
Packit Service fa4841
			ret = FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service fa4841
	free(points);
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
Packit Service fa4841
{
Packit Service b1ea74
	UINT32 i;
Packit Service b1ea74
	int npoints;
Packit Service fa4841
	XPoint* points;
Packit Service fa4841
	Pixmap pattern;
Packit Service fa4841
	const rdpBrush* brush;
Packit Service fa4841
	XColor foreColor;
Packit Service fa4841
	XColor backColor;
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service fa4841
	BOOL ret = TRUE;
Packit Service fa4841
Packit Service fa4841
	if (!xf_decode_color(xfc, polygon_cb->foreColor, &foreColor))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!xf_decode_color(xfc, polygon_cb->backColor, &backColor))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
	brush = &(polygon_cb->brush);
Packit Service fa4841
	xf_set_rop2(xfc, polygon_cb->bRop2);
Packit Service fa4841
	npoints = polygon_cb->numPoints + 1;
Packit Service fa4841
	points = calloc(npoints, sizeof(XPoint));
Packit Service fa4841
Packit Service fa4841
	if (!points)
Packit Service fa4841
	{
Packit Service b1ea74
		xf_unlock_x11(xfc);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	points[0].x = polygon_cb->xStart;
Packit Service fa4841
	points[0].y = polygon_cb->yStart;
Packit Service fa4841
Packit Service fa4841
	for (i = 0; i < polygon_cb->numPoints; i++)
Packit Service fa4841
	{
Packit Service fa4841
		points[i + 1].x = polygon_cb->points[i].x;
Packit Service fa4841
		points[i + 1].y = polygon_cb->points[i].y;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	switch (polygon_cb->fillMode)
Packit Service fa4841
	{
Packit Service fa4841
		case GDI_FILL_ALTERNATE: /* alternate */
Packit Service fa4841
			XSetFillRule(xfc->display, xfc->gc, EvenOddRule);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GDI_FILL_WINDING: /* winding */
Packit Service fa4841
			XSetFillRule(xfc->display, xfc->gc, WindingRule);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		default:
Packit Service b1ea74
			WLog_ERR(TAG, "PolygonCB unknown fillMode: %" PRIu32 "", polygon_cb->fillMode);
Packit Service fa4841
			break;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (brush->style == GDI_BS_PATTERN)
Packit Service fa4841
	{
Packit Service fa4841
		if (brush->bpp > 1)
Packit Service fa4841
		{
Packit Service fa4841
			UINT32 bpp = brush->bpp;
Packit Service fa4841
Packit Service fa4841
			if ((bpp == 16) && (context->settings->ColorDepth == 15))
Packit Service fa4841
				bpp = 15;
Packit Service fa4841
Packit Service fa4841
			pattern = xf_brush_new(xfc, 8, 8, bpp, brush->data);
Packit Service fa4841
			XSetFillStyle(xfc->display, xfc->gc, FillTiled);
Packit Service fa4841
			XSetTile(xfc->display, xfc->gc, pattern);
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			pattern = xf_mono_bitmap_new(xfc, 8, 8, brush->data);
Packit Service fa4841
			XSetForeground(xfc->display, xfc->gc, backColor.pixel);
Packit Service fa4841
			XSetBackground(xfc->display, xfc->gc, foreColor.pixel);
Packit Service fa4841
Packit Service fa4841
			if (polygon_cb->backMode == BACKMODE_TRANSPARENT)
Packit Service fa4841
				XSetFillStyle(xfc->display, xfc->gc, FillStippled);
Packit Service fa4841
			else if (polygon_cb->backMode == BACKMODE_OPAQUE)
Packit Service fa4841
				XSetFillStyle(xfc->display, xfc->gc, FillOpaqueStippled);
Packit Service fa4841
Packit Service fa4841
			XSetStipple(xfc->display, xfc->gc, pattern);
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y);
Packit Service b1ea74
		XFillPolygon(xfc->display, xfc->drawing, xfc->gc, points, npoints, Complex,
Packit Service b1ea74
		             CoordModePrevious);
Packit Service fa4841
		XSetFillStyle(xfc->display, xfc->gc, FillSolid);
Packit Service fa4841
		XSetTSOrigin(xfc->display, xfc->gc, 0, 0);
Packit Service fa4841
		XFreePixmap(xfc->display, pattern);
Packit Service fa4841
Packit Service fa4841
		if (xfc->drawing == xfc->primary)
Packit Service fa4841
		{
Packit Service fa4841
			if (!xf_gdi_invalidate_poly_region(xfc, points, npoints))
Packit Service fa4841
				ret = FALSE;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service b1ea74
		WLog_ERR(TAG, "PolygonCB unimplemented brush style:%" PRIu32 "", brush->style);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service fa4841
	free(points);
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL xf_gdi_surface_frame_marker(rdpContext* context,
Packit Service fa4841
                                        const SURFACE_FRAME_MARKER* surface_frame_marker)
Packit Service fa4841
{
Packit Service fa4841
	rdpSettings* settings;
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service fa4841
	BOOL ret = TRUE;
Packit Service fa4841
	settings = xfc->context.settings;
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
Packit Service fa4841
	switch (surface_frame_marker->frameAction)
Packit Service fa4841
	{
Packit Service fa4841
		case SURFACECMD_FRAMEACTION_BEGIN:
Packit Service fa4841
			xfc->frame_begin = TRUE;
Packit Service fa4841
			xfc->frame_x1 = 0;
Packit Service fa4841
			xfc->frame_y1 = 0;
Packit Service fa4841
			xfc->frame_x2 = 0;
Packit Service fa4841
			xfc->frame_y2 = 0;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case SURFACECMD_FRAMEACTION_END:
Packit Service fa4841
			xfc->frame_begin = FALSE;
Packit Service fa4841
Packit Service fa4841
			if ((xfc->frame_x2 > xfc->frame_x1) && (xfc->frame_y2 > xfc->frame_y1))
Packit Service fa4841
				ret = gdi_InvalidateRegion(xfc->hdc, xfc->frame_x1, xfc->frame_y1,
Packit Service b1ea74
				                           xfc->frame_x2 - xfc->frame_x1,
Packit Service b1ea74
				                           xfc->frame_y2 - xfc->frame_y1);
Packit Service fa4841
Packit Service fa4841
			if (settings->FrameAcknowledge > 0)
Packit Service fa4841
			{
Packit Service fa4841
				IFCALL(xfc->context.update->SurfaceFrameAcknowledge, context,
Packit Service fa4841
				       surface_frame_marker->frameId);
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL xf_gdi_surface_update_frame(xfContext* xfc, UINT16 tx, UINT16 ty, UINT16 width,
Packit Service b1ea74
                                        UINT16 height)
Packit Service fa4841
{
Packit Service fa4841
	BOOL ret = TRUE;
Packit Service fa4841
Packit Service fa4841
	if (!xfc->remote_app)
Packit Service fa4841
	{
Packit Service fa4841
		if (xfc->frame_begin)
Packit Service fa4841
		{
Packit Service fa4841
			if (xfc->frame_x2 > xfc->frame_x1 && xfc->frame_y2 > xfc->frame_y1)
Packit Service fa4841
			{
Packit Service fa4841
				xfc->frame_x1 = MIN(xfc->frame_x1, tx);
Packit Service fa4841
				xfc->frame_y1 = MIN(xfc->frame_y1, ty);
Packit Service fa4841
				xfc->frame_x2 = MAX(xfc->frame_x2, tx + width);
Packit Service fa4841
				xfc->frame_y2 = MAX(xfc->frame_y2, ty + height);
Packit Service fa4841
			}
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service fa4841
				xfc->frame_x1 = tx;
Packit Service fa4841
				xfc->frame_y1 = ty;
Packit Service fa4841
				xfc->frame_x2 = tx + width;
Packit Service fa4841
				xfc->frame_y2 = ty + height;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			ret = gdi_InvalidateRegion(xfc->hdc, tx, ty, width, height);
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		ret = gdi_InvalidateRegion(xfc->hdc, tx, ty, width, height);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL xf_gdi_update_screen(xfContext* xfc, const BYTE* pSrcData, UINT32 scanline,
Packit Service b1ea74
                                 const REGION16* pRegion)
Packit Service fa4841
{
Packit Service fa4841
	BOOL ret = FALSE;
Packit Service fa4841
	XImage* image;
Packit Service fa4841
	UINT32 i, nbRects;
Packit Service fa4841
	const RECTANGLE_16* rects;
Packit Service fa4841
	UINT32 bpp;
Packit Service fa4841
Packit Service fa4841
	if (!xfc || !pSrcData)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!(rects = region16_rects(pRegion, &nbRects)))
Packit Service fa4841
		return TRUE;
Packit Service fa4841
Packit Service fa4841
	if (xfc->depth > 16)
Packit Service fa4841
		bpp = 4;
Packit Service fa4841
	else if (xfc->depth > 8)
Packit Service fa4841
		bpp = 2;
Packit Service fa4841
	else
Packit Service fa4841
		bpp = 1;
Packit Service fa4841
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service fa4841
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);
Packit Service fa4841
Packit Service fa4841
	for (i = 0; i < nbRects; i++)
Packit Service fa4841
	{
Packit Service fa4841
		UINT32 left = rects[i].left;
Packit Service fa4841
		UINT32 top = rects[i].top;
Packit Service fa4841
		UINT32 width = rects[i].right - rects[i].left;
Packit Service fa4841
		UINT32 height = rects[i].bottom - rects[i].top;
Packit Service fa4841
		const BYTE* src = pSrcData + top * scanline + bpp * left;
Packit Service b1ea74
		image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*)src, width,
Packit Service b1ea74
		                     height, xfc->scanline_pad, scanline);
Packit Service fa4841
Packit Service fa4841
		if (!image)
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		image->byte_order = LSBFirst;
Packit Service fa4841
		image->bitmap_bit_order = LSBFirst;
Packit Service fa4841
		XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, left, top, width, height);
Packit Service fa4841
		image->data = NULL;
Packit Service fa4841
		XDestroyImage(image);
Packit Service fa4841
		ret = xf_gdi_surface_update_frame(xfc, left, top, width, height);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	XSetClipMask(xfc->display, xfc->gc, None);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL xf_gdi_surface_bits(rdpContext* context, const SURFACE_BITS_COMMAND* cmd)
Packit Service fa4841
{
Packit Service fa4841
	BYTE* pSrcData;
Packit Service b1ea74
	xfContext* xfc = (xfContext*)context;
Packit Service fa4841
	BOOL ret = FALSE;
Packit Service fa4841
	DWORD format;
Packit Service fa4841
	rdpGdi* gdi;
Packit Service b1ea74
	size_t size;
Packit Service fa4841
	REGION16 region;
Packit Service fa4841
	RECTANGLE_16 cmdRect;
Packit Service fa4841
Packit Service fa4841
	if (!context || !cmd || !context->gdi)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	region16_init(&region);
Packit Service fa4841
	cmdRect.left = cmd->destLeft;
Packit Service fa4841
	cmdRect.top = cmd->destTop;
Packit Service fa4841
	cmdRect.right = cmdRect.left + cmd->bmp.width;
Packit Service fa4841
	cmdRect.bottom = cmdRect.top + cmd->bmp.height;
Packit Service fa4841
	gdi = context->gdi;
Packit Service b1ea74
	xf_lock_x11(xfc);
Packit Service fa4841
Packit Service fa4841
	switch (cmd->bmp.codecID)
Packit Service fa4841
	{
Packit Service fa4841
		case RDP_CODEC_ID_REMOTEFX:
Packit Service fa4841
			if (!rfx_process_message(context->codecs->rfx, cmd->bmp.bitmapData,
Packit Service fa4841
			                         cmd->bmp.bitmapDataLength, cmd->destLeft, cmd->destTop,
Packit Service b1ea74
			                         gdi->primary_buffer, gdi->dstFormat, gdi->stride, gdi->height,
Packit Service b1ea74
			                         &region))
Packit Service fa4841
				goto fail;
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case RDP_CODEC_ID_NSCODEC:
Packit Service fa4841
			if (!nsc_process_message(context->codecs->nsc, cmd->bmp.bpp, cmd->bmp.width,
Packit Service b1ea74
			                         cmd->bmp.height, cmd->bmp.bitmapData,
Packit Service b1ea74
			                         cmd->bmp.bitmapDataLength, gdi->primary_buffer, gdi->dstFormat,
Packit Service b1ea74
			                         gdi->stride, 0, 0, cmd->bmp.width, cmd->bmp.height,
Packit Service b1ea74
			                         FREERDP_FLIP_VERTICAL))
Packit Service fa4841
				goto fail;
Packit Service fa4841
Packit Service fa4841
			region16_union_rect(&region, &region, &cmdRect);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case RDP_CODEC_ID_NONE:
Packit Service fa4841
			pSrcData = cmd->bmp.bitmapData;
Packit Service fa4841
			format = gdi_get_pixel_format(cmd->bmp.bpp);
Packit Service b1ea74
			size = cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format);
Packit Service b1ea74
			if (size > cmd->bmp.bitmapDataLength)
Packit Service b1ea74
			{
Packit Service b1ea74
				WLog_ERR(TAG, "Short nocodec message: got %" PRIu32 " bytes, require %" PRIuz,
Packit Service b1ea74
				         cmd->bmp.bitmapDataLength, size);
Packit Service b1ea74
				goto fail;
Packit Service b1ea74
			}
Packit Service fa4841
Packit Service b1ea74
			if (!freerdp_image_copy(gdi->primary_buffer, gdi->dstFormat, gdi->stride, cmd->destLeft,
Packit Service b1ea74
			                        cmd->destTop, cmd->bmp.width, cmd->bmp.height, pSrcData, format,
Packit Service b1ea74
			                        0, 0, 0, &xfc->context.gdi->palette, FREERDP_FLIP_VERTICAL))
Packit Service fa4841
				goto fail;
Packit Service fa4841
Packit Service fa4841
			region16_union_rect(&region, &region, &cmdRect);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		default:
Packit Service b1ea74
			WLog_ERR(TAG, "Unsupported codecID %" PRIu16 "", cmd->bmp.codecID);
Packit Service fa4841
			goto fail;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	ret = xf_gdi_update_screen(xfc, gdi->primary_buffer, gdi->stride, &region);
Packit Service fa4841
fail:
Packit Service fa4841
	region16_uninit(&region);
Packit Service b1ea74
	xf_unlock_x11(xfc);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void xf_gdi_register_update_callbacks(rdpUpdate* update)
Packit Service fa4841
{
Packit Service fa4841
	rdpPrimaryUpdate* primary = update->primary;
Packit Service fa4841
	update->SetBounds = xf_gdi_set_bounds;
Packit Service fa4841
	primary->DstBlt = xf_gdi_dstblt;
Packit Service fa4841
	primary->PatBlt = xf_gdi_patblt;
Packit Service fa4841
	primary->ScrBlt = xf_gdi_scrblt;
Packit Service fa4841
	primary->OpaqueRect = xf_gdi_opaque_rect;
Packit Service fa4841
	primary->MultiOpaqueRect = xf_gdi_multi_opaque_rect;
Packit Service fa4841
	primary->LineTo = xf_gdi_line_to;
Packit Service fa4841
	primary->Polyline = xf_gdi_polyline;
Packit Service fa4841
	primary->MemBlt = xf_gdi_memblt;
Packit Service fa4841
	primary->Mem3Blt = xf_gdi_mem3blt;
Packit Service fa4841
	primary->PolygonSC = xf_gdi_polygon_sc;
Packit Service fa4841
	primary->PolygonCB = xf_gdi_polygon_cb;
Packit Service fa4841
	update->SurfaceBits = xf_gdi_surface_bits;
Packit Service fa4841
	update->SurfaceFrameMarker = xf_gdi_surface_frame_marker;
Packit Service fa4841
}