Blame libfreerdp/gdi/graphics.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * Graphical Objects
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 * Copyright 2016 Armin Novak <armin.novak@thincast.com>
Packit 1fb8d4
 * Copyright 2016 Thincast Technologies GmbH
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 <winpr/crt.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
#include <freerdp/gdi/dc.h>
Packit 1fb8d4
#include <freerdp/gdi/shape.h>
Packit 1fb8d4
#include <freerdp/gdi/region.h>
Packit 1fb8d4
#include <freerdp/gdi/bitmap.h>
Packit 1fb8d4
Packit 1fb8d4
#include "clipping.h"
Packit 1fb8d4
#include "drawing.h"
Packit 1fb8d4
#include "brush.h"
Packit 1fb8d4
#include "graphics.h"
Packit 1fb8d4
Packit 1fb8d4
#define TAG FREERDP_TAG("gdi")
Packit 1fb8d4
/* Bitmap Class */
Packit 1fb8d4
Packit 1fb8d4
HGDI_BITMAP gdi_create_bitmap(rdpGdi* gdi, UINT32 nWidth, UINT32 nHeight,
Packit 1fb8d4
                              UINT32 SrcFormat, BYTE* data)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 nSrcStep;
Packit 1fb8d4
	UINT32 nDstStep;
Packit 1fb8d4
	BYTE* pSrcData;
Packit 1fb8d4
	BYTE* pDstData;
Packit 1fb8d4
	HGDI_BITMAP bitmap;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	nDstStep = nWidth * GetBytesPerPixel(gdi->dstFormat);
Packit 1fb8d4
	pDstData = _aligned_malloc(nHeight * nDstStep, 16);
Packit 1fb8d4
Packit 1fb8d4
	if (!pDstData)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	pSrcData = data;
Packit 1fb8d4
	nSrcStep = nWidth * GetBytesPerPixel(SrcFormat);
Packit 1fb8d4
Packit 1fb8d4
	if (!freerdp_image_copy(pDstData, gdi->dstFormat, nDstStep, 0, 0,
Packit 1fb8d4
	                        nWidth, nHeight, pSrcData, SrcFormat, nSrcStep, 0, 0,
Packit 1fb8d4
	                        &gdi->palette, FREERDP_FLIP_NONE))
Packit 1fb8d4
	{
Packit 1fb8d4
		_aligned_free(pDstData);
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	bitmap = gdi_CreateBitmap(nWidth, nHeight, gdi->dstFormat, pDstData);
Packit 1fb8d4
	return bitmap;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
Packit 1fb8d4
{
Packit 1fb8d4
	gdiBitmap* gdi_bitmap;
Packit 1fb8d4
	rdpGdi* gdi = context->gdi;
Packit 1fb8d4
	gdi_bitmap = (gdiBitmap*) bitmap;
Packit 1fb8d4
	gdi_bitmap->hdc = gdi_CreateCompatibleDC(gdi->hdc);
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_bitmap->hdc)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!bitmap->data)
Packit 1fb8d4
		gdi_bitmap->bitmap = gdi_CreateCompatibleBitmap(
Packit 1fb8d4
		                         gdi->hdc, bitmap->width,
Packit 1fb8d4
		                         bitmap->height);
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		UINT32 format = bitmap->format;
Packit 1fb8d4
		gdi_bitmap->bitmap = gdi_create_bitmap(gdi, bitmap->width,
Packit 1fb8d4
		                                       bitmap->height,
Packit 1fb8d4
		                                       format, bitmap->data);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_bitmap->bitmap)
Packit 1fb8d4
	{
Packit 1fb8d4
		gdi_DeleteDC(gdi_bitmap->hdc);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	gdi_bitmap->hdc->format = gdi_bitmap->bitmap->format;
Packit 1fb8d4
	gdi_SelectObject(gdi_bitmap->hdc, (HGDIOBJECT) gdi_bitmap->bitmap);
Packit 1fb8d4
	gdi_bitmap->org_bitmap = NULL;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void gdi_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap)
Packit 1fb8d4
{
Packit 1fb8d4
	gdiBitmap* gdi_bitmap = (gdiBitmap*) bitmap;
Packit 1fb8d4
Packit 1fb8d4
	if (gdi_bitmap)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (gdi_bitmap->hdc)
Packit 1fb8d4
			gdi_SelectObject(gdi_bitmap->hdc, (HGDIOBJECT) gdi_bitmap->org_bitmap);
Packit 1fb8d4
Packit 1fb8d4
		gdi_DeleteObject((HGDIOBJECT) gdi_bitmap->bitmap);
Packit 1fb8d4
		gdi_DeleteDC(gdi_bitmap->hdc);
Packit 1fb8d4
		_aligned_free(bitmap->data);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(bitmap);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
Packit 1fb8d4
{
Packit 1fb8d4
	gdiBitmap* gdi_bitmap = (gdiBitmap*) bitmap;
Packit 1fb8d4
	UINT32 width = bitmap->right - bitmap->left + 1;
Packit 1fb8d4
	UINT32 height = bitmap->bottom - bitmap->top + 1;
Packit 1fb8d4
	return gdi_BitBlt(context->gdi->primary->hdc,
Packit 1fb8d4
	                  bitmap->left, bitmap->top,
Packit 1fb8d4
	                  width, height, gdi_bitmap->hdc,
Packit 1fb8d4
	                  0, 0, GDI_SRCCOPY, &context->gdi->palette);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
Packit 1fb8d4
                                  const BYTE* pSrcData, UINT32 DstWidth, UINT32 DstHeight,
Packit 1fb8d4
                                  UINT32 bpp, UINT32 length, BOOL compressed,
Packit 1fb8d4
                                  UINT32 codecId)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 SrcSize = length;
Packit 1fb8d4
	rdpGdi* gdi = context->gdi;
Packit 1fb8d4
	UINT32 size = DstWidth * DstHeight;
Packit 1fb8d4
	bitmap->compressed = FALSE;
Packit 1fb8d4
	bitmap->format = gdi->dstFormat;
Packit 1fb8d4
Packit 1fb8d4
	if ((GetBytesPerPixel(bitmap->format) == 0) ||
Packit 1fb8d4
	    (DstWidth == 0) || (DstHeight == 0) || (DstWidth > UINT32_MAX / DstHeight) ||
Packit 1fb8d4
	    (size > (UINT32_MAX / GetBytesPerPixel(bitmap->format))))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	size *= GetBytesPerPixel(bitmap->format);
Packit 1fb8d4
	bitmap->length = size;
Packit 1fb8d4
	bitmap->data = (BYTE*) _aligned_malloc(bitmap->length, 16);
Packit 1fb8d4
Packit 1fb8d4
	if (!bitmap->data)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (compressed)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (bpp < 32)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (!interleaved_decompress(context->codecs->interleaved,
Packit 1fb8d4
			                            pSrcData, SrcSize,
Packit 1fb8d4
			                            DstWidth, DstHeight,
Packit 1fb8d4
			                            bpp,
Packit 1fb8d4
			                            bitmap->data, bitmap->format,
Packit 1fb8d4
			                            0, 0, 0, DstWidth, DstHeight,
Packit 1fb8d4
			                            &gdi->palette))
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			if (!planar_decompress(context->codecs->planar, pSrcData, SrcSize,
Packit 1fb8d4
			                       DstWidth, DstHeight,
Packit 1fb8d4
			                       bitmap->data, bitmap->format, 0, 0, 0,
Packit 1fb8d4
			                       DstWidth, DstHeight, TRUE))
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		const UINT32 SrcFormat = gdi_get_pixel_format(bpp);
Packit 1fb8d4
		const size_t sbpp = GetBytesPerPixel(SrcFormat);
Packit 1fb8d4
		const size_t dbpp = GetBytesPerPixel(bitmap->format);
Packit 1fb8d4
Packit 1fb8d4
		if ((sbpp == 0) || (dbpp == 0))
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			const size_t dstSize = SrcSize * dbpp / sbpp;
Packit 1fb8d4
Packit 1fb8d4
			if (dstSize  < bitmap->length)
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!freerdp_image_copy(bitmap->data, bitmap->format, 0, 0, 0,
Packit 1fb8d4
		                        DstWidth, DstHeight, pSrcData, SrcFormat,
Packit 1fb8d4
		                        0, 0, 0, &gdi->palette, FREERDP_FLIP_VERTICAL))
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap,
Packit 1fb8d4
                                  BOOL primary)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi = context->gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (primary)
Packit 1fb8d4
		gdi->drawing = gdi->primary;
Packit 1fb8d4
	else
Packit 1fb8d4
		gdi->drawing = (gdiBitmap*) bitmap;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* Glyph Class */
Packit 1fb8d4
static BOOL gdi_Glyph_New(rdpContext* context, const rdpGlyph* glyph)
Packit 1fb8d4
{
Packit 1fb8d4
	BYTE* data;
Packit 1fb8d4
	gdiGlyph* gdi_glyph;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !glyph)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi_glyph = (gdiGlyph*) glyph;
Packit 1fb8d4
	gdi_glyph->hdc = gdi_GetDC();
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_glyph->hdc)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi_glyph->hdc->format = PIXEL_FORMAT_MONO;
Packit 1fb8d4
	data = freerdp_glyph_convert(glyph->cx, glyph->cy, glyph->aj);
Packit 1fb8d4
Packit 1fb8d4
	if (!data)
Packit 1fb8d4
	{
Packit 1fb8d4
		gdi_DeleteDC(gdi_glyph->hdc);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	gdi_glyph->bitmap = gdi_CreateBitmap(glyph->cx, glyph->cy, PIXEL_FORMAT_MONO,
Packit 1fb8d4
	                                     data);
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_glyph->bitmap)
Packit 1fb8d4
	{
Packit 1fb8d4
		gdi_DeleteDC(gdi_glyph->hdc);
Packit 1fb8d4
		_aligned_free(data);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	gdi_SelectObject(gdi_glyph->hdc, (HGDIOBJECT) gdi_glyph->bitmap);
Packit 1fb8d4
	gdi_glyph->org_bitmap = NULL;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void gdi_Glyph_Free(rdpContext* context, rdpGlyph* glyph)
Packit 1fb8d4
{
Packit 1fb8d4
	gdiGlyph* gdi_glyph;
Packit 1fb8d4
	gdi_glyph = (gdiGlyph*) glyph;
Packit 1fb8d4
Packit 1fb8d4
	if (gdi_glyph)
Packit 1fb8d4
	{
Packit 1fb8d4
		gdi_SelectObject(gdi_glyph->hdc, (HGDIOBJECT) gdi_glyph->org_bitmap);
Packit 1fb8d4
		gdi_DeleteObject((HGDIOBJECT) gdi_glyph->bitmap);
Packit 1fb8d4
		gdi_DeleteDC(gdi_glyph->hdc);
Packit 1fb8d4
		free(glyph->aj);
Packit 1fb8d4
		free(glyph);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_Glyph_Draw(rdpContext* context, const rdpGlyph* glyph, INT32 x,
Packit 1fb8d4
                           INT32 y, INT32 w, INT32 h, INT32 sx, INT32 sy, BOOL fOpRedundant)
Packit 1fb8d4
{
Packit 1fb8d4
	gdiGlyph* gdi_glyph;
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
	HGDI_BRUSH brush;
Packit 1fb8d4
	BOOL rc = FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !glyph)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi = context->gdi;
Packit 1fb8d4
	gdi_glyph = (gdiGlyph*) glyph;
Packit 1fb8d4
Packit 1fb8d4
	if (!fOpRedundant && 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		GDI_RECT rect = { 0 };
Packit 1fb8d4
Packit 1fb8d4
		if (x > 0)
Packit 1fb8d4
			rect.left = x;
Packit 1fb8d4
Packit 1fb8d4
		if (y > 0)
Packit 1fb8d4
			rect.top = y;
Packit 1fb8d4
Packit 1fb8d4
		if (x + w > 0)
Packit 1fb8d4
			rect.right = x + w - 1;
Packit 1fb8d4
Packit 1fb8d4
		if (y + h > 0)
Packit 1fb8d4
			rect.bottom = y + h - 1;
Packit 1fb8d4
Packit 1fb8d4
		if ((rect.left < rect.right) && (rect.top < rect.bottom))
Packit 1fb8d4
		{
Packit 1fb8d4
			brush = gdi_CreateSolidBrush(gdi->drawing->hdc->bkColor);
Packit 1fb8d4
Packit 1fb8d4
			if (!brush)
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
Packit 1fb8d4
			gdi_FillRect(gdi->drawing->hdc, &rect, brush);
Packit 1fb8d4
			gdi_DeleteObject((HGDIOBJECT)brush);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	brush = gdi_CreateSolidBrush(gdi->drawing->hdc->textColor);
Packit 1fb8d4
Packit 1fb8d4
	if (!brush)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi_SelectObject(gdi->drawing->hdc, (HGDIOBJECT)brush);
Packit 1fb8d4
	rc = gdi_BitBlt(gdi->drawing->hdc, x, y, w, h, gdi_glyph->hdc, sx, sy,
Packit 1fb8d4
	                GDI_GLYPH_ORDER, &context->gdi->palette);
Packit 1fb8d4
	gdi_DeleteObject((HGDIOBJECT)brush);
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_Glyph_SetBounds(rdpContext* context, INT32 x, INT32 y, INT32 width, INT32 height)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !context->gdi)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi = context->gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi->drawing || !gdi->drawing->hdc)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return gdi_SetClipRgn(gdi->drawing->hdc, x, y, width, height);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_Glyph_BeginDraw(rdpContext* context, INT32 x, INT32 y,
Packit 1fb8d4
                                INT32 width, INT32 height, UINT32 bgcolor,
Packit 1fb8d4
                                UINT32 fgcolor, BOOL fOpRedundant)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !context->gdi)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi = context->gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi->drawing || !gdi->drawing->hdc)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!fOpRedundant)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!gdi_decode_color(gdi, bgcolor, &bgcolor, NULL))
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		if (!gdi_decode_color(gdi, fgcolor, &fgcolor, NULL))
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		gdi_SetClipRgn(gdi->drawing->hdc, x, y, width, height);
Packit 1fb8d4
		gdi_SetTextColor(gdi->drawing->hdc, bgcolor);
Packit 1fb8d4
		gdi_SetBkColor(gdi->drawing->hdc, fgcolor);
Packit 1fb8d4
Packit 1fb8d4
		if (1)
Packit 1fb8d4
		{
Packit 1fb8d4
			GDI_RECT rect = { 0 };
Packit 1fb8d4
			HGDI_BRUSH brush = gdi_CreateSolidBrush(fgcolor);
Packit 1fb8d4
Packit 1fb8d4
			if (!brush)
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
Packit 1fb8d4
			if (x > 0)
Packit 1fb8d4
				rect.left = x;
Packit 1fb8d4
Packit 1fb8d4
			if (y > 0)
Packit 1fb8d4
				rect.top = y;
Packit 1fb8d4
Packit 1fb8d4
			rect.right = x + width - 1;
Packit 1fb8d4
			rect.bottom = y + height - 1;
Packit 1fb8d4
Packit 1fb8d4
			if ((x + width > rect.left) && (y + height > rect.top))
Packit 1fb8d4
				gdi_FillRect(gdi->drawing->hdc, &rect, brush);
Packit 1fb8d4
Packit 1fb8d4
			gdi_DeleteObject((HGDIOBJECT)brush);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		return gdi_SetNullClipRgn(gdi->drawing->hdc);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_Glyph_EndDraw(rdpContext* context, INT32 x, INT32 y,
Packit 1fb8d4
                              INT32 width, INT32 height, UINT32 bgcolor, UINT32 fgcolor)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !context->gdi)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi = context->gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi->drawing || !gdi->drawing->hdc)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi_SetNullClipRgn(gdi->drawing->hdc);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* Graphics Module */
Packit 1fb8d4
BOOL gdi_register_graphics(rdpGraphics* graphics)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpBitmap bitmap;
Packit 1fb8d4
	rdpGlyph glyph;
Packit 1fb8d4
	bitmap.size = sizeof(gdiBitmap);
Packit 1fb8d4
	bitmap.New = gdi_Bitmap_New;
Packit 1fb8d4
	bitmap.Free = gdi_Bitmap_Free;
Packit 1fb8d4
	bitmap.Paint = gdi_Bitmap_Paint;
Packit 1fb8d4
	bitmap.Decompress = gdi_Bitmap_Decompress;
Packit 1fb8d4
	bitmap.SetSurface = gdi_Bitmap_SetSurface;
Packit 1fb8d4
	graphics_register_bitmap(graphics, &bitmap);
Packit 1fb8d4
	glyph.size = sizeof(gdiGlyph);
Packit 1fb8d4
	glyph.New = gdi_Glyph_New;
Packit 1fb8d4
	glyph.Free = gdi_Glyph_Free;
Packit 1fb8d4
	glyph.Draw = gdi_Glyph_Draw;
Packit 1fb8d4
	glyph.BeginDraw = gdi_Glyph_BeginDraw;
Packit 1fb8d4
	glyph.EndDraw = gdi_Glyph_EndDraw;
Packit 1fb8d4
	glyph.SetBounds = gdi_Glyph_SetBounds;
Packit 1fb8d4
	graphics_register_glyph(graphics, &glyph);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}