Blame client/X11/xf_graphics.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * X11 Graphical Objects
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 * Copyright 2016 Thincast Technologies GmbH
Packit 1fb8d4
 * Copyright 2016 Armin Novak <armin.novak@thincast.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <X11/Xlib.h>
Packit 1fb8d4
#include <X11/Xutil.h>
Packit 1fb8d4
Packit 1fb8d4
#ifdef WITH_XCURSOR
Packit 1fb8d4
#include <X11/Xcursor/Xcursor.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/codec/bitmap.h>
Packit 1fb8d4
#include <freerdp/codec/rfx.h>
Packit 1fb8d4
Packit 1fb8d4
#include "xf_graphics.h"
Packit 1fb8d4
#include "xf_gdi.h"
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
#define TAG CLIENT_TAG("x11")
Packit 1fb8d4
Packit 1fb8d4
BOOL xf_decode_color(xfContext* xfc, const UINT32 srcColor, XColor* color)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
	rdpSettings* settings;
Packit 1fb8d4
	UINT32 SrcFormat;
Packit 1fb8d4
	BYTE r, g, b, a;
Packit 1fb8d4
Packit 1fb8d4
	if (!xfc || !color)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi = xfc->context.gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	settings = xfc->context.settings;
Packit 1fb8d4
Packit 1fb8d4
	if (!settings)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	switch (settings->ColorDepth)
Packit 1fb8d4
	{
Packit 1fb8d4
		case 32:
Packit 1fb8d4
		case 24:
Packit 1fb8d4
			SrcFormat = PIXEL_FORMAT_BGR24;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case 16:
Packit 1fb8d4
			SrcFormat = PIXEL_FORMAT_RGB16;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case 15:
Packit 1fb8d4
			SrcFormat = PIXEL_FORMAT_RGB15;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case 8:
Packit 1fb8d4
			SrcFormat = PIXEL_FORMAT_RGB8;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	SplitColor(srcColor, SrcFormat, &r, &g, &b, &a, &gdi->palette);
Packit 1fb8d4
	color->blue = (unsigned short)(b << 8);
Packit 1fb8d4
	color->green = (unsigned short)(g << 8);
Packit 1fb8d4
	color->red = (unsigned short)(r << 8);
Packit 1fb8d4
	color->flags = DoRed | DoGreen | DoBlue;
Packit 1fb8d4
Packit 1fb8d4
	if (XAllocColor(xfc->display, xfc->colormap, color) == 0)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* Bitmap Class */
Packit 1fb8d4
static BOOL xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL rc = FALSE;
Packit 1fb8d4
	UINT32 depth;
Packit 1fb8d4
	BYTE* data;
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
	xfBitmap* xbitmap = (xfBitmap*)bitmap;
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !bitmap || !context->gdi)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi = context->gdi;
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
	depth = GetBitsPerPixel(bitmap->format);
Packit Service 5a9772
	xbitmap->pixmap =
Packit Service 5a9772
	    XCreatePixmap(xfc->display, xfc->drawable, bitmap->width, bitmap->height, xfc->depth);
Packit 1fb8d4
Packit 1fb8d4
	if (!xbitmap->pixmap)
Packit 1fb8d4
		goto unlock;
Packit 1fb8d4
Packit 1fb8d4
	if (bitmap->data)
Packit 1fb8d4
	{
Packit 1fb8d4
		XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit 1fb8d4
Packit Service 5a9772
		if ((INT64)depth != xfc->depth)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (!(data = _aligned_malloc(bitmap->width * bitmap->height * 4, 16)))
Packit 1fb8d4
				goto unlock;
Packit 1fb8d4
Packit Service 5a9772
			if (!freerdp_image_copy(data, gdi->dstFormat, 0, 0, 0, bitmap->width, bitmap->height,
Packit Service 5a9772
			                        bitmap->data, bitmap->format, 0, 0, 0, &context->gdi->palette,
Packit Service 5a9772
			                        FREERDP_FLIP_NONE))
Packit 1fb8d4
			{
Packit 1fb8d4
				_aligned_free(data);
Packit 1fb8d4
				goto unlock;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			_aligned_free(bitmap->data);
Packit 1fb8d4
			bitmap->data = data;
Packit 1fb8d4
			bitmap->format = gdi->dstFormat;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit Service 5a9772
		xbitmap->image =
Packit Service 5a9772
		    XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*)bitmap->data,
Packit Service 5a9772
		                 bitmap->width, bitmap->height, xfc->scanline_pad, 0);
Packit 1fb8d4
Packit 1fb8d4
		if (!xbitmap->image)
Packit 1fb8d4
			goto unlock;
Packit 1fb8d4
Packit 1fb8d4
		xbitmap->image->byte_order = LSBFirst;
Packit 1fb8d4
		xbitmap->image->bitmap_bit_order = LSBFirst;
Packit 1fb8d4
		XPutImage(xfc->display, xbitmap->pixmap, xfc->gc, xbitmap->image, 0, 0, 0, 0, bitmap->width,
Packit 1fb8d4
		          bitmap->height);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	rc = TRUE;
Packit 1fb8d4
unlock:
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void xf_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap)
Packit 1fb8d4
{
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit 1fb8d4
	xfBitmap* xbitmap = (xfBitmap*)bitmap;
Packit 1fb8d4
Packit 1fb8d4
	if (!xfc || !xbitmap)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
Packit 1fb8d4
	if (xbitmap->pixmap != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		XFreePixmap(xfc->display, xbitmap->pixmap);
Packit 1fb8d4
		xbitmap->pixmap = 0;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (xbitmap->image)
Packit 1fb8d4
	{
Packit 1fb8d4
		xbitmap->image->data = NULL;
Packit 1fb8d4
		XDestroyImage(xbitmap->image);
Packit 1fb8d4
		xbitmap->image = NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
	_aligned_free(bitmap->data);
Packit 1fb8d4
	free(xbitmap);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
Packit 1fb8d4
{
Packit 1fb8d4
	int width, height;
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit 1fb8d4
	xfBitmap* xbitmap = (xfBitmap*)bitmap;
Packit 1fb8d4
	BOOL ret;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !xbitmap)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	width = bitmap->right - bitmap->left + 1;
Packit 1fb8d4
	height = bitmap->bottom - bitmap->top + 1;
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service 5a9772
	XPutImage(xfc->display, xfc->primary, xfc->gc, xbitmap->image, 0, 0, bitmap->left, bitmap->top,
Packit Service 5a9772
	          width, height);
Packit 1fb8d4
	ret = gdi_InvalidateRegion(xfc->hdc, bitmap->left, bitmap->top, width, height);
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL xf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary)
Packit 1fb8d4
{
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || (!bitmap && !primary))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
Packit 1fb8d4
	if (primary)
Packit 1fb8d4
		xfc->drawing = xfc->primary;
Packit 1fb8d4
	else
Packit Service 5a9772
		xfc->drawing = ((xfBitmap*)bitmap)->pixmap;
Packit 1fb8d4
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* Pointer Class */
Packit 1fb8d4
static BOOL xf_Pointer_New(rdpContext* context, rdpPointer* pointer)
Packit 1fb8d4
{
Packit 1fb8d4
#ifdef WITH_XCURSOR
Packit 1fb8d4
	UINT32 CursorFormat;
Packit 1fb8d4
	size_t size;
Packit 1fb8d4
	XcursorImage ci;
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit 1fb8d4
	xfPointer* xpointer = (xfPointer*)pointer;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !pointer || !context->gdi)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!xfc->invert)
Packit 1fb8d4
		CursorFormat = (!xfc->big_endian) ? PIXEL_FORMAT_RGBA32 : PIXEL_FORMAT_ABGR32;
Packit 1fb8d4
	else
Packit 1fb8d4
		CursorFormat = (!xfc->big_endian) ? PIXEL_FORMAT_BGRA32 : PIXEL_FORMAT_ARGB32;
Packit 1fb8d4
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
	ZeroMemory(&ci, sizeof(ci));
Packit 1fb8d4
	ci.version = XCURSOR_IMAGE_VERSION;
Packit 1fb8d4
	ci.size = sizeof(ci);
Packit 1fb8d4
	ci.width = pointer->width;
Packit 1fb8d4
	ci.height = pointer->height;
Packit 1fb8d4
	ci.xhot = pointer->xPos;
Packit 1fb8d4
	ci.yhot = pointer->yPos;
Packit 1fb8d4
	size = ci.height * ci.width * GetBytesPerPixel(CursorFormat);
Packit 1fb8d4
Packit Service 5a9772
	if (!(ci.pixels = (XcursorPixel*)_aligned_malloc(size, 16)))
Packit 1fb8d4
	{
Packit Service 5a9772
		xf_unlock_x11(xfc);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!freerdp_image_copy_from_pointer_data(
Packit Service 5a9772
	        (BYTE*)ci.pixels, CursorFormat, 0, 0, 0, pointer->width, pointer->height,
Packit Service 5a9772
	        pointer->xorMaskData, pointer->lengthXorMask, pointer->andMaskData,
Packit Service 5a9772
	        pointer->lengthAndMask, pointer->xorBpp, &context->gdi->palette))
Packit 1fb8d4
	{
Packit 1fb8d4
		_aligned_free(ci.pixels);
Packit Service 5a9772
		xf_unlock_x11(xfc);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	xpointer->cursor = XcursorImageLoadCursor(xfc->display, &ci);
Packit 1fb8d4
	_aligned_free(ci.pixels);
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
#endif
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void xf_Pointer_Free(rdpContext* context, rdpPointer* pointer)
Packit 1fb8d4
{
Packit 1fb8d4
#ifdef WITH_XCURSOR
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
Packit Service 5a9772
	if (((xfPointer*)pointer)->cursor)
Packit Service 5a9772
		XFreeCursor(xfc->display, ((xfPointer*)pointer)->cursor);
Packit 1fb8d4
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
#endif
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL xf_Pointer_Set(rdpContext* context, const rdpPointer* pointer)
Packit 1fb8d4
{
Packit 1fb8d4
#ifdef WITH_XCURSOR
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit Service 5a9772
	xfc->pointer = (xfPointer*)pointer;
Packit 1fb8d4
Packit 1fb8d4
	/* in RemoteApp mode, window can be null if none has had focus */
Packit 1fb8d4
Packit 1fb8d4
	if (xfc->window)
Packit 1fb8d4
		XDefineCursor(xfc->display, xfc->window->handle, xfc->pointer->cursor);
Packit 1fb8d4
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
#endif
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL xf_Pointer_SetNull(rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
#ifdef WITH_XCURSOR
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit 1fb8d4
	static Cursor nullcursor = None;
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
Packit 1fb8d4
	if (nullcursor == None)
Packit 1fb8d4
	{
Packit 1fb8d4
		XcursorImage ci;
Packit 1fb8d4
		XcursorPixel xp = 0;
Packit 1fb8d4
		ZeroMemory(&ci, sizeof(ci));
Packit 1fb8d4
		ci.version = XCURSOR_IMAGE_VERSION;
Packit 1fb8d4
		ci.size = sizeof(ci);
Packit 1fb8d4
		ci.width = ci.height = 1;
Packit 1fb8d4
		ci.xhot = ci.yhot = 0;
Packit 1fb8d4
		ci.pixels = &xp;
Packit 1fb8d4
		nullcursor = XcursorImageLoadCursor(xfc->display, &ci);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	xfc->pointer = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if ((xfc->window) && (nullcursor != None))
Packit 1fb8d4
		XDefineCursor(xfc->display, xfc->window->handle, nullcursor);
Packit 1fb8d4
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
#endif
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL xf_Pointer_SetDefault(rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
#ifdef WITH_XCURSOR
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
	xfc->pointer = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (xfc->window)
Packit 1fb8d4
		XUndefineCursor(xfc->display, xfc->window->handle);
Packit 1fb8d4
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
#endif
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL xf_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
Packit 1fb8d4
{
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit 1fb8d4
	XWindowAttributes current;
Packit 1fb8d4
	XSetWindowAttributes tmp;
Packit 1fb8d4
	BOOL ret = FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!xfc->focused || !xfc->window)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
Packit 1fb8d4
	if (XGetWindowAttributes(xfc->display, xfc->window->handle, &current) == 0)
Packit 1fb8d4
		goto out;
Packit 1fb8d4
Packit 1fb8d4
	tmp.event_mask = (current.your_event_mask & ~(PointerMotionMask));
Packit 1fb8d4
Packit Service 5a9772
	if (XChangeWindowAttributes(xfc->display, xfc->window->handle, CWEventMask, &tmp) == 0)
Packit 1fb8d4
		goto out;
Packit 1fb8d4
Packit 1fb8d4
	XWarpPointer(xfc->display, None, xfc->window->handle, 0, 0, 0, 0, x, y);
Packit 1fb8d4
	tmp.event_mask = current.your_event_mask;
Packit 1fb8d4
	XChangeWindowAttributes(xfc->display, xfc->window->handle, CWEventMask, &tmp);
Packit 1fb8d4
	ret = TRUE;
Packit 1fb8d4
out:
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* Glyph Class */
Packit 1fb8d4
static BOOL xf_Glyph_New(rdpContext* context, const rdpGlyph* glyph)
Packit 1fb8d4
{
Packit 1fb8d4
	int scanline;
Packit 1fb8d4
	XImage* image;
Packit 1fb8d4
	xfGlyph* xf_glyph;
Packit Service 5a9772
	xf_glyph = (xfGlyph*)glyph;
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
	scanline = (glyph->cx + 7) / 8;
Packit Service 5a9772
	xf_glyph->pixmap = XCreatePixmap(xfc->display, xfc->drawing, glyph->cx, glyph->cy, 1);
Packit Service 5a9772
	image = XCreateImage(xfc->display, xfc->visual, 1, ZPixmap, 0, (char*)glyph->aj, glyph->cx,
Packit Service 5a9772
	                     glyph->cy, 8, scanline);
Packit 1fb8d4
	image->byte_order = MSBFirst;
Packit 1fb8d4
	image->bitmap_bit_order = MSBFirst;
Packit 1fb8d4
	XInitImage(image);
Packit Service 5a9772
	XPutImage(xfc->display, xf_glyph->pixmap, xfc->gc_mono, image, 0, 0, 0, 0, glyph->cx,
Packit Service 5a9772
	          glyph->cy);
Packit 1fb8d4
	image->data = NULL;
Packit 1fb8d4
	XDestroyImage(image);
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void xf_Glyph_Free(rdpContext* context, rdpGlyph* glyph)
Packit 1fb8d4
{
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
Packit Service 5a9772
	if (((xfGlyph*)glyph)->pixmap != 0)
Packit Service 5a9772
		XFreePixmap(xfc->display, ((xfGlyph*)glyph)->pixmap);
Packit 1fb8d4
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
	free(glyph->aj);
Packit 1fb8d4
	free(glyph);
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL xf_Glyph_Draw(rdpContext* context, const rdpGlyph* glyph, INT32 x, INT32 y, INT32 w,
Packit Service 5a9772
                          INT32 h, INT32 sx, INT32 sy, BOOL fOpRedundant)
Packit 1fb8d4
{
Packit 1fb8d4
	xfGlyph* xf_glyph;
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit Service 5a9772
	xf_glyph = (xfGlyph*)glyph;
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
Packit 1fb8d4
	if (!fOpRedundant)
Packit 1fb8d4
	{
Packit 1fb8d4
		XSetFillStyle(xfc->display, xfc->gc, FillOpaqueStippled);
Packit 1fb8d4
		XFillRectangle(xfc->display, xfc->drawable, xfc->gc, x, y, w, h);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	XSetFillStyle(xfc->display, xfc->gc, FillStippled);
Packit 1fb8d4
	XSetStipple(xfc->display, xfc->gc, xf_glyph->pixmap);
Packit 1fb8d4
Packit 1fb8d4
	if (sx || sy)
Packit 1fb8d4
		WLog_ERR(TAG, "");
Packit 1fb8d4
Packit Service 5a9772
	// XSetClipOrigin(xfc->display, xfc->gc, sx, sy);
Packit 1fb8d4
	XSetTSOrigin(xfc->display, xfc->gc, x, y);
Packit 1fb8d4
	XFillRectangle(xfc->display, xfc->drawing, xfc->gc, x, y, w, h);
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL xf_Glyph_BeginDraw(rdpContext* context, INT32 x, INT32 y, INT32 width, INT32 height,
Packit Service 5a9772
                               UINT32 bgcolor, UINT32 fgcolor, BOOL fOpRedundant)
Packit 1fb8d4
{
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit 1fb8d4
	XRectangle rect;
Packit 1fb8d4
	XColor xbgcolor, xfgcolor;
Packit 1fb8d4
Packit 1fb8d4
	if (!xf_decode_color(xfc, bgcolor, &xbgcolor))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!xf_decode_color(xfc, fgcolor, &xfgcolor))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	rect.x = x;
Packit 1fb8d4
	rect.y = y;
Packit 1fb8d4
	rect.width = width;
Packit 1fb8d4
	rect.height = height;
Packit Service 5a9772
	xf_lock_x11(xfc);
Packit 1fb8d4
Packit 1fb8d4
	if (!fOpRedundant)
Packit 1fb8d4
	{
Packit 1fb8d4
		XSetForeground(xfc->display, xfc->gc, xfgcolor.pixel);
Packit 1fb8d4
		XSetBackground(xfc->display, xfc->gc, xfgcolor.pixel);
Packit 1fb8d4
		XSetFillStyle(xfc->display, xfc->gc, FillOpaqueStippled);
Packit 1fb8d4
		XFillRectangle(xfc->display, xfc->drawable, xfc->gc, x, y, width, height);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	XSetForeground(xfc->display, xfc->gc, xbgcolor.pixel);
Packit 1fb8d4
	XSetBackground(xfc->display, xfc->gc, xfgcolor.pixel);
Packit Service 5a9772
	xf_unlock_x11(xfc);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL xf_Glyph_EndDraw(rdpContext* context, INT32 x, INT32 y, INT32 width, INT32 height,
Packit 1fb8d4
                             UINT32 bgcolor, UINT32 fgcolor)
Packit 1fb8d4
{
Packit Service 5a9772
	xfContext* xfc = (xfContext*)context;
Packit 1fb8d4
	BOOL ret = TRUE;
Packit 1fb8d4
	XColor xfgcolor, xbgcolor;
Packit 1fb8d4
Packit 1fb8d4
	if (!xf_decode_color(xfc, bgcolor, &xbgcolor))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!xf_decode_color(xfc, fgcolor, &xfgcolor))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (xfc->drawing == xfc->primary)
Packit 1fb8d4
		ret = gdi_InvalidateRegion(xfc->hdc, x, y, width, height);
Packit 1fb8d4
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* Graphics Module */
Packit 1fb8d4
BOOL xf_register_pointer(rdpGraphics* graphics)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpPointer* pointer = NULL;
Packit 1fb8d4
Packit Service 5a9772
	if (!(pointer = (rdpPointer*)calloc(1, sizeof(rdpPointer))))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	pointer->size = sizeof(xfPointer);
Packit 1fb8d4
	pointer->New = xf_Pointer_New;
Packit 1fb8d4
	pointer->Free = xf_Pointer_Free;
Packit 1fb8d4
	pointer->Set = xf_Pointer_Set;
Packit 1fb8d4
	pointer->SetNull = xf_Pointer_SetNull;
Packit 1fb8d4
	pointer->SetDefault = xf_Pointer_SetDefault;
Packit 1fb8d4
	pointer->SetPosition = xf_Pointer_SetPosition;
Packit 1fb8d4
	graphics_register_pointer(graphics, pointer);
Packit 1fb8d4
	free(pointer);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL xf_register_graphics(rdpGraphics* graphics)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpBitmap bitmap;
Packit 1fb8d4
	rdpGlyph glyph;
Packit 1fb8d4
Packit 1fb8d4
	if (!graphics || !graphics->Bitmap_Prototype || !graphics->Glyph_Prototype)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	bitmap = *graphics->Bitmap_Prototype;
Packit 1fb8d4
	glyph = *graphics->Glyph_Prototype;
Packit 1fb8d4
	bitmap.size = sizeof(xfBitmap);
Packit 1fb8d4
	bitmap.New = xf_Bitmap_New;
Packit 1fb8d4
	bitmap.Free = xf_Bitmap_Free;
Packit 1fb8d4
	bitmap.Paint = xf_Bitmap_Paint;
Packit 1fb8d4
	bitmap.SetSurface = xf_Bitmap_SetSurface;
Packit 1fb8d4
	graphics_register_bitmap(graphics, &bitmap);
Packit 1fb8d4
	glyph.size = sizeof(xfGlyph);
Packit 1fb8d4
	glyph.New = xf_Glyph_New;
Packit 1fb8d4
	glyph.Free = xf_Glyph_Free;
Packit 1fb8d4
	glyph.Draw = xf_Glyph_Draw;
Packit 1fb8d4
	glyph.BeginDraw = xf_Glyph_BeginDraw;
Packit 1fb8d4
	glyph.EndDraw = xf_Glyph_EndDraw;
Packit 1fb8d4
	graphics_register_glyph(graphics, &glyph);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
UINT32 xf_get_local_color_format(xfContext* xfc, BOOL aligned)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 DstFormat;
Packit 1fb8d4
	BOOL invert = FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!xfc)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	invert = xfc->invert;
Packit 1fb8d4
Packit 1fb8d4
	if (xfc->depth == 32)
Packit 1fb8d4
		DstFormat = (!invert) ? PIXEL_FORMAT_RGBA32 : PIXEL_FORMAT_BGRA32;
Packit 1fb8d4
	else if (xfc->depth == 24)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (aligned)
Packit 1fb8d4
			DstFormat = (!invert) ? PIXEL_FORMAT_RGBX32 : PIXEL_FORMAT_BGRX32;
Packit 1fb8d4
		else
Packit 1fb8d4
			DstFormat = (!invert) ? PIXEL_FORMAT_RGB24 : PIXEL_FORMAT_BGR24;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (xfc->depth == 16)
Packit 1fb8d4
		DstFormat = PIXEL_FORMAT_RGB16;
Packit 1fb8d4
	else if (xfc->depth == 15)
Packit 1fb8d4
		DstFormat = PIXEL_FORMAT_RGB15;
Packit 1fb8d4
	else
Packit 1fb8d4
		DstFormat = (!invert) ? PIXEL_FORMAT_RGBX32 : PIXEL_FORMAT_BGRX32;
Packit 1fb8d4
Packit 1fb8d4
	return DstFormat;
Packit 1fb8d4
}