Blame libfreerdp/gdi/gdi.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * GDI Library
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2010-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 <stdio.h>
Packit 1fb8d4
#include <stdlib.h>
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/api.h>
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
#include <freerdp/freerdp.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/gdi/gdi.h>
Packit 1fb8d4
#include <freerdp/gdi/dc.h>
Packit 1fb8d4
#include <freerdp/gdi/pen.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 "drawing.h"
Packit 1fb8d4
#include "clipping.h"
Packit 1fb8d4
#include "brush.h"
Packit 1fb8d4
#include "line.h"
Packit 1fb8d4
#include "gdi.h"
Packit 1fb8d4
#include "../core/graphics.h"
Packit 1fb8d4
Packit 1fb8d4
#define TAG FREERDP_TAG("gdi")
Packit 1fb8d4
Packit 1fb8d4
/* Ternary Raster Operation Table */
Packit 1fb8d4
typedef struct
Packit 1fb8d4
{
Packit 1fb8d4
	DWORD code;
Packit 1fb8d4
	const char* name;
Packit 1fb8d4
} rop_table_entry;
Packit 1fb8d4
Packit 1fb8d4
static const rop_table_entry rop3_code_table[] =
Packit 1fb8d4
{
Packit 1fb8d4
	{ GDI_BLACKNESS, "0" },
Packit 1fb8d4
	{ GDI_DPSoon, "DPSoon" },
Packit 1fb8d4
	{ GDI_DPSona, "DPSona" },
Packit 1fb8d4
	{ GDI_PSon, "PSon" },
Packit 1fb8d4
	{ GDI_SDPona, "SDPona" },
Packit 1fb8d4
	{ GDI_DPon, "DPon" },
Packit 1fb8d4
	{ GDI_PDSxnon, "PDSxnon" },
Packit 1fb8d4
	{ GDI_PDSaon, "PDSaon" },
Packit 1fb8d4
	{ GDI_SDPnaa, "SDPnaa" },
Packit 1fb8d4
	{ GDI_PDSxon, "PDSxon" },
Packit 1fb8d4
	{ GDI_DPna, "DPna" },
Packit 1fb8d4
	{ GDI_PSDnaon, "PSDnaon" },
Packit 1fb8d4
	{ GDI_SPna, "SPna" },
Packit 1fb8d4
	{ GDI_PDSnaon, "PDSnaon" },
Packit 1fb8d4
	{ GDI_PDSonon, "PDSonon" },
Packit 1fb8d4
	{ GDI_Pn	, "Pn" },
Packit 1fb8d4
	{ GDI_PDSona, "PDSona" },
Packit 1fb8d4
	{ GDI_NOTSRCERASE, "DSon" },
Packit 1fb8d4
	{ GDI_SDPxnon, "SDPxnon" },
Packit 1fb8d4
	{ GDI_SDPaon, "SDPaon" },
Packit 1fb8d4
	{ GDI_DPSxnon, "DPSxnon" },
Packit 1fb8d4
	{ GDI_DPSaon, "DPSaon" },
Packit 1fb8d4
	{ GDI_PSDPSanaxx, "PSDPSanaxx" },
Packit 1fb8d4
	{ GDI_SSPxDSxaxn, "SSPxDSxaxn" },
Packit 1fb8d4
	{ GDI_SPxPDxa, "SPxPDxa" },
Packit 1fb8d4
	{ GDI_SDPSanaxn, "SDPSanaxn" },
Packit 1fb8d4
	{ GDI_PDSPaox, "PDSPaox" },
Packit 1fb8d4
	{ GDI_SDPSxaxn, "SDPSxaxn" },
Packit 1fb8d4
	{ GDI_PSDPaox, "PSDPaox" },
Packit 1fb8d4
	{ GDI_DSPDxaxn, "DSPDxaxn" },
Packit 1fb8d4
	{ GDI_PDSox, "PDSox" },
Packit 1fb8d4
	{ GDI_PDSoan, "PDSoan" },
Packit 1fb8d4
	{ GDI_DPSnaa, "DPSnaa" },
Packit 1fb8d4
	{ GDI_SDPxon, "SDPxon" },
Packit 1fb8d4
	{ GDI_DSna, "DSna" },
Packit 1fb8d4
	{ GDI_SPDnaon, "SPDnaon" },
Packit 1fb8d4
	{ GDI_SPxDSxa, "SPxDSxa" },
Packit 1fb8d4
	{ GDI_PDSPanaxn, "PDSPanaxn" },
Packit 1fb8d4
	{ GDI_SDPSaox, "SDPSaox" },
Packit 1fb8d4
	{ GDI_SDPSxnox, "SDPSxnox" },
Packit 1fb8d4
	{ GDI_DPSxa, "DPSxa" },
Packit 1fb8d4
	{ GDI_PSDPSaoxxn, "PSDPSaoxxn" },
Packit 1fb8d4
	{ GDI_DPSana, "DPSana" },
Packit 1fb8d4
	{ GDI_SSPxPDxaxn, "SSPxPDxaxn" },
Packit 1fb8d4
	{ GDI_SPDSoax, "SPDSoax" },
Packit 1fb8d4
	{ GDI_PSDnox, "PSDnox" },
Packit 1fb8d4
	{ GDI_PSDPxox, "PSDPxox" },
Packit 1fb8d4
	{ GDI_PSDnoan, "PSDnoan" },
Packit 1fb8d4
	{ GDI_PSna, "PSna" },
Packit 1fb8d4
	{ GDI_SDPnaon, "SDPnaon" },
Packit 1fb8d4
	{ GDI_SDPSoox, "SDPSoox" },
Packit 1fb8d4
	{ GDI_NOTSRCCOPY, "Sn" },
Packit 1fb8d4
	{ GDI_SPDSaox, "SPDSaox" },
Packit 1fb8d4
	{ GDI_SPDSxnox, "SPDSxnox" },
Packit 1fb8d4
	{ GDI_SDPox, "SDPox" },
Packit 1fb8d4
	{ GDI_SDPoan, "SDPoan" },
Packit 1fb8d4
	{ GDI_PSDPoax, "PSDPoax" },
Packit 1fb8d4
	{ GDI_SPDnox, "SPDnox" },
Packit 1fb8d4
	{ GDI_SPDSxox, "SPDSxox" },
Packit 1fb8d4
	{ GDI_SPDnoan, "SPDnoan" },
Packit 1fb8d4
	{ GDI_PSx	, "PSx" },
Packit 1fb8d4
	{ GDI_SPDSonox, "SPDSonox" },
Packit 1fb8d4
	{ GDI_SPDSnaox, "SPDSnaox" },
Packit 1fb8d4
	{ GDI_PSan, "PSan" },
Packit 1fb8d4
	{ GDI_PSDnaa, "PSDnaa" },
Packit 1fb8d4
	{ GDI_DPSxon, "DPSxon" },
Packit 1fb8d4
	{ GDI_SDxPDxa, "SDxPDxa" },
Packit 1fb8d4
	{ GDI_SPDSanaxn, "SPDSanaxn" },
Packit 1fb8d4
	{ GDI_SRCERASE, "SDna" },
Packit 1fb8d4
	{ GDI_DPSnaon, "DPSnaon" },
Packit 1fb8d4
	{ GDI_DSPDaox, "DSPDaox" },
Packit 1fb8d4
	{ GDI_PSDPxaxn, "PSDPxaxn" },
Packit 1fb8d4
	{ GDI_SDPxa, "SDPxa" },
Packit 1fb8d4
	{ GDI_PDSPDaoxxn, "PDSPDaoxxn" },
Packit 1fb8d4
	{ GDI_DPSDoax, "DPSDoax" },
Packit 1fb8d4
	{ GDI_PDSnox, "PDSnox" },
Packit 1fb8d4
	{ GDI_SDPana, "SDPana" },
Packit 1fb8d4
	{ GDI_SSPxDSxoxn, "SSPxDSxoxn" },
Packit 1fb8d4
	{ GDI_PDSPxox, "PDSPxox" },
Packit 1fb8d4
	{ GDI_PDSnoan, "PDSnoan" },
Packit 1fb8d4
	{ GDI_PDna, "PDna" },
Packit 1fb8d4
	{ GDI_DSPnaon, "DSPnaon" },
Packit 1fb8d4
	{ GDI_DPSDaox, "DPSDaox" },
Packit 1fb8d4
	{ GDI_SPDSxaxn, "SPDSxaxn" },
Packit 1fb8d4
	{ GDI_DPSonon, "DPSonon" },
Packit 1fb8d4
	{ GDI_DSTINVERT, "Dn" },
Packit 1fb8d4
	{ GDI_DPSox, "DPSox" },
Packit 1fb8d4
	{ GDI_DPSoan, "DPSoan" },
Packit 1fb8d4
	{ GDI_PDSPoax, "PDSPoax" },
Packit 1fb8d4
	{ GDI_DPSnox, "DPSnox" },
Packit 1fb8d4
	{ GDI_PATINVERT, "DPx" },
Packit 1fb8d4
	{ GDI_DPSDonox, "DPSDonox" },
Packit 1fb8d4
	{ GDI_DPSDxox, "DPSDxox" },
Packit 1fb8d4
	{ GDI_DPSnoan, "DPSnoan" },
Packit 1fb8d4
	{ GDI_DPSDnaox, "DPSDnaox" },
Packit 1fb8d4
	{ GDI_DPan, "DPan" },
Packit 1fb8d4
	{ GDI_PDSxa, "PDSxa" },
Packit 1fb8d4
	{ GDI_DSPDSaoxxn, "DSPDSaoxxn" },
Packit 1fb8d4
	{ GDI_DSPDoax, "DSPDoax" },
Packit 1fb8d4
	{ GDI_SDPnox, "SDPnox" },
Packit 1fb8d4
	{ GDI_SDPSoax, "SDPSoax" },
Packit 1fb8d4
	{ GDI_DSPnox, "DSPnox" },
Packit 1fb8d4
	{ GDI_SRCINVERT, "DSx" },
Packit 1fb8d4
	{ GDI_SDPSonox, "SDPSonox" },
Packit 1fb8d4
	{ GDI_DSPDSonoxxn, "DSPDSonoxxn" },
Packit 1fb8d4
	{ GDI_PDSxxn, "PDSxxn" },
Packit 1fb8d4
	{ GDI_DPSax, "DPSax" },
Packit 1fb8d4
	{ GDI_PSDPSoaxxn, "PSDPSoaxxn" },
Packit 1fb8d4
	{ GDI_SDPax, "SDPax" },
Packit 1fb8d4
	{ GDI_PDSPDoaxxn, "PDSPDoaxxn" },
Packit 1fb8d4
	{ GDI_SDPSnoax, "SDPSnoax" },
Packit 1fb8d4
	{ GDI_PDSxnan, "PDSxnan" },
Packit 1fb8d4
	{ GDI_PDSana, "PDSana" },
Packit 1fb8d4
	{ GDI_SSDxPDxaxn, "SSDxPDxaxn" },
Packit 1fb8d4
	{ GDI_SDPSxox, "SDPSxox" },
Packit 1fb8d4
	{ GDI_SDPnoan, "SDPnoan" },
Packit 1fb8d4
	{ GDI_DSPDxox, "DSPDxox" },
Packit 1fb8d4
	{ GDI_DSPnoan, "DSPnoan" },
Packit 1fb8d4
	{ GDI_SDPSnaox, "SDPSnaox" },
Packit 1fb8d4
	{ GDI_DSan, "DSan" },
Packit 1fb8d4
	{ GDI_PDSax, "PDSax" },
Packit 1fb8d4
	{ GDI_DSPDSoaxxn, "DSPDSoaxxn" },
Packit 1fb8d4
	{ GDI_DPSDnoax, "DPSDnoax" },
Packit 1fb8d4
	{ GDI_SDPxnan, "SDPxnan" },
Packit 1fb8d4
	{ GDI_SPDSnoax, "SPDSnoax" },
Packit 1fb8d4
	{ GDI_DPSxnan, "DPSxnan" },
Packit 1fb8d4
	{ GDI_SPxDSxo, "SPxDSxo" },
Packit 1fb8d4
	{ GDI_DPSaan, "DPSaan" },
Packit 1fb8d4
	{ GDI_DPSaa, "DPSaa" },
Packit 1fb8d4
	{ GDI_SPxDSxon, "SPxDSxon" },
Packit 1fb8d4
	{ GDI_DPSxna, "DPSxna" },
Packit 1fb8d4
	{ GDI_SPDSnoaxn, "SPDSnoaxn" },
Packit 1fb8d4
	{ GDI_SDPxna, "SDPxna" },
Packit 1fb8d4
	{ GDI_PDSPnoaxn, "PDSPnoaxn" },
Packit 1fb8d4
	{ GDI_DSPDSoaxx, "DSPDSoaxx" },
Packit 1fb8d4
	{ GDI_PDSaxn, "PDSaxn" },
Packit 1fb8d4
	{ GDI_SRCAND, "DSa" },
Packit 1fb8d4
	{ GDI_SDPSnaoxn, "SDPSnaoxn" },
Packit 1fb8d4
	{ GDI_DSPnoa, "DSPnoa" },
Packit 1fb8d4
	{ GDI_DSPDxoxn, "DSPDxoxn" },
Packit 1fb8d4
	{ GDI_SDPnoa, "SDPnoa" },
Packit 1fb8d4
	{ GDI_SDPSxoxn, "SDPSxoxn" },
Packit 1fb8d4
	{ GDI_SSDxPDxax, "SSDxPDxax" },
Packit 1fb8d4
	{ GDI_PDSanan, "PDSanan" },
Packit 1fb8d4
	{ GDI_PDSxna, "PDSxna" },
Packit 1fb8d4
	{ GDI_SDPSnoaxn, "SDPSnoaxn" },
Packit 1fb8d4
	{ GDI_DPSDPoaxx, "DPSDPoaxx" },
Packit 1fb8d4
	{ GDI_SPDaxn, "SPDaxn" },
Packit 1fb8d4
	{ GDI_PSDPSoaxx, "PSDPSoaxx" },
Packit 1fb8d4
	{ GDI_DPSaxn, "DPSaxn" },
Packit 1fb8d4
	{ GDI_DPSxx, "DPSxx" },
Packit 1fb8d4
	{ GDI_PSDPSonoxx, "PSDPSonoxx" },
Packit 1fb8d4
	{ GDI_SDPSonoxn, "SDPSonoxn" },
Packit 1fb8d4
	{ GDI_DSxn, "DSxn" },
Packit 1fb8d4
	{ GDI_DPSnax, "DPSnax" },
Packit 1fb8d4
	{ GDI_SDPSoaxn, "SDPSoaxn" },
Packit 1fb8d4
	{ GDI_SPDnax, "SPDnax" },
Packit 1fb8d4
	{ GDI_DSPDoaxn, "DSPDoaxn" },
Packit 1fb8d4
	{ GDI_DSPDSaoxx, "DSPDSaoxx" },
Packit 1fb8d4
	{ GDI_PDSxan, "PDSxan" },
Packit 1fb8d4
	{ GDI_DPa	, "DPa" },
Packit 1fb8d4
	{ GDI_PDSPnaoxn, "PDSPnaoxn" },
Packit 1fb8d4
	{ GDI_DPSnoa, "DPSnoa" },
Packit 1fb8d4
	{ GDI_DPSDxoxn, "DPSDxoxn" },
Packit 1fb8d4
	{ GDI_PDSPonoxn, "PDSPonoxn" },
Packit 1fb8d4
	{ GDI_PDxn, "PDxn" },
Packit 1fb8d4
	{ GDI_DSPnax, "DSPnax" },
Packit 1fb8d4
	{ GDI_PDSPoaxn, "PDSPoaxn" },
Packit 1fb8d4
	{ GDI_DPSoa, "DPSoa" },
Packit 1fb8d4
	{ GDI_DPSoxn, "DPSoxn" },
Packit 1fb8d4
	{ GDI_DSTCOPY, "D" },
Packit 1fb8d4
	{ GDI_DPSono, "DPSono" },
Packit 1fb8d4
	{ GDI_SPDSxax, "SPDSxax" },
Packit 1fb8d4
	{ GDI_DPSDaoxn, "DPSDaoxn" },
Packit 1fb8d4
	{ GDI_DSPnao, "DSPnao" },
Packit 1fb8d4
	{ GDI_DPno, "DPno" },
Packit 1fb8d4
	{ GDI_PDSnoa, "PDSnoa" },
Packit 1fb8d4
	{ GDI_PDSPxoxn, "PDSPxoxn" },
Packit 1fb8d4
	{ GDI_SSPxDSxox, "SSPxDSxox" },
Packit 1fb8d4
	{ GDI_SDPanan, "SDPanan" },
Packit 1fb8d4
	{ GDI_PSDnax, "PSDnax" },
Packit 1fb8d4
	{ GDI_DPSDoaxn, "DPSDoaxn" },
Packit 1fb8d4
	{ GDI_DPSDPaoxx, "DPSDPaoxx" },
Packit 1fb8d4
	{ GDI_SDPxan, "SDPxan" },
Packit 1fb8d4
	{ GDI_PSDPxax, "PSDPxax" },
Packit 1fb8d4
	{ GDI_DSPDaoxn, "DSPDaoxn" },
Packit 1fb8d4
	{ GDI_DPSnao, "DPSnao" },
Packit 1fb8d4
	{ GDI_MERGEPAINT, "DSno" },
Packit 1fb8d4
	{ GDI_SPDSanax, "SPDSanax" },
Packit 1fb8d4
	{ GDI_SDxPDxan, "SDxPDxan" },
Packit 1fb8d4
	{ GDI_DPSxo, "DPSxo" },
Packit 1fb8d4
	{ GDI_DPSano, "DPSano" },
Packit 1fb8d4
	{ GDI_MERGECOPY, "PSa" },
Packit 1fb8d4
	{ GDI_SPDSnaoxn, "SPDSnaoxn" },
Packit 1fb8d4
	{ GDI_SPDSonoxn, "SPDSonoxn" },
Packit 1fb8d4
	{ GDI_PSxn, "PSxn" },
Packit 1fb8d4
	{ GDI_SPDnoa, "SPDnoa" },
Packit 1fb8d4
	{ GDI_SPDSxoxn, "SPDSxoxn" },
Packit 1fb8d4
	{ GDI_SDPnax, "SDPnax" },
Packit 1fb8d4
	{ GDI_PSDPoaxn, "PSDPoaxn" },
Packit 1fb8d4
	{ GDI_SDPoa, "SDPoa" },
Packit 1fb8d4
	{ GDI_SPDoxn, "SPDoxn" },
Packit 1fb8d4
	{ GDI_DPSDxax, "DPSDxax" },
Packit 1fb8d4
	{ GDI_SPDSaoxn, "SPDSaoxn" },
Packit 1fb8d4
	{ GDI_SRCCOPY, "S" },
Packit 1fb8d4
	{ GDI_SDPono, "SDPono" },
Packit 1fb8d4
	{ GDI_SDPnao, "SDPnao" },
Packit 1fb8d4
	{ GDI_SPno, "SPno" },
Packit 1fb8d4
	{ GDI_PSDnoa, "PSDnoa" },
Packit 1fb8d4
	{ GDI_PSDPxoxn, "PSDPxoxn" },
Packit 1fb8d4
	{ GDI_PDSnax, "PDSnax" },
Packit 1fb8d4
	{ GDI_SPDSoaxn, "SPDSoaxn" },
Packit 1fb8d4
	{ GDI_SSPxPDxax, "SSPxPDxax" },
Packit 1fb8d4
	{ GDI_DPSanan, "DPSanan" },
Packit 1fb8d4
	{ GDI_PSDPSaoxx, "PSDPSaoxx" },
Packit 1fb8d4
	{ GDI_DPSxan, "DPSxan" },
Packit 1fb8d4
	{ GDI_PDSPxax, "PDSPxax" },
Packit 1fb8d4
	{ GDI_SDPSaoxn, "SDPSaoxn" },
Packit 1fb8d4
	{ GDI_DPSDanax, "DPSDanax" },
Packit 1fb8d4
	{ GDI_SPxDSxan, "SPxDSxan" },
Packit 1fb8d4
	{ GDI_SPDnao, "SPDnao" },
Packit 1fb8d4
	{ GDI_SDno, "SDno" },
Packit 1fb8d4
	{ GDI_SDPxo, "SDPxo" },
Packit 1fb8d4
	{ GDI_SDPano, "SDPano" },
Packit 1fb8d4
	{ GDI_PDSoa, "PDSoa" },
Packit 1fb8d4
	{ GDI_PDSoxn, "PDSoxn" },
Packit 1fb8d4
	{ GDI_DSPDxax, "DSPDxax" },
Packit 1fb8d4
	{ GDI_PSDPaoxn, "PSDPaoxn" },
Packit 1fb8d4
	{ GDI_SDPSxax, "SDPSxax" },
Packit 1fb8d4
	{ GDI_PDSPaoxn, "PDSPaoxn" },
Packit 1fb8d4
	{ GDI_SDPSanax, "SDPSanax" },
Packit 1fb8d4
	{ GDI_SPxPDxan, "SPxPDxan" },
Packit 1fb8d4
	{ GDI_SSPxDSxax, "SSPxDSxax" },
Packit 1fb8d4
	{ GDI_DSPDSanaxxn, "DSPDSanaxxn" },
Packit 1fb8d4
	{ GDI_DPSao, "DPSao" },
Packit 1fb8d4
	{ GDI_DPSxno, "DPSxno" },
Packit 1fb8d4
	{ GDI_SDPao, "SDPao" },
Packit 1fb8d4
	{ GDI_SDPxno, "SDPxno" },
Packit 1fb8d4
	{ GDI_SRCPAINT, "DSo" },
Packit 1fb8d4
	{ GDI_SDPnoo, "SDPnoo" },
Packit 1fb8d4
	{ GDI_PATCOPY, "P" },
Packit 1fb8d4
	{ GDI_PDSono, "PDSono" },
Packit 1fb8d4
	{ GDI_PDSnao, "PDSnao" },
Packit 1fb8d4
	{ GDI_PSno, "PSno" },
Packit 1fb8d4
	{ GDI_PSDnao, "PSDnao" },
Packit 1fb8d4
	{ GDI_PDno, "PDno" },
Packit 1fb8d4
	{ GDI_PDSxo, "PDSxo" },
Packit 1fb8d4
	{ GDI_PDSano, "PDSano" },
Packit 1fb8d4
	{ GDI_PDSao, "PDSao" },
Packit 1fb8d4
	{ GDI_PDSxno, "PDSxno" },
Packit 1fb8d4
	{ GDI_DPo	, "DPo" },
Packit 1fb8d4
	{ GDI_PATPAINT, "DPSnoo" },
Packit 1fb8d4
	{ GDI_PSo	, "PSo" },
Packit 1fb8d4
	{ GDI_PSDnoo, "PSDnoo" },
Packit 1fb8d4
	{ GDI_DPSoo, "DPSoo" },
Packit 1fb8d4
	{ GDI_WHITENESS, "1" }
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
/* Hatch Patterns as monochrome data */
Packit 1fb8d4
static const BYTE GDI_BS_HATCHED_PATTERNS[] =
Packit 1fb8d4
{
Packit 1fb8d4
	0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, /* HS_HORIZONTAL */
Packit 1fb8d4
	0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, /* HS_VERTICAL */
Packit 1fb8d4
	0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F, /* HS_FDIAGONAL */
Packit 1fb8d4
	0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE, /* HS_BDIAGONAL */
Packit 1fb8d4
	0xF7, 0xF7, 0xF7, 0x00, 0xF7, 0xF7, 0xF7, 0xF7, /* HS_CROSS */
Packit 1fb8d4
	0x7E, 0xBD, 0xDB, 0xE7, 0xE7, 0xDB, 0xBD, 0x7E /* HS_DIACROSS */
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
INLINE BOOL gdi_decode_color(rdpGdi* gdi, const UINT32 srcColor,
Packit 1fb8d4
                             UINT32* color, UINT32* format)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 SrcFormat;
Packit 1fb8d4
	UINT32 ColorDepth;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi || !color || !gdi->context || !gdi->context->settings)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	ColorDepth = gdi->context->settings->ColorDepth;
Packit 1fb8d4
Packit 1fb8d4
	switch (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
	if (format)
Packit 1fb8d4
		*format = gdi->dstFormat;
Packit 1fb8d4
Packit 1fb8d4
	*color = FreeRDPConvertColor(srcColor, SrcFormat, gdi->dstFormat, &gdi->palette);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* GDI Helper Functions */
Packit 1fb8d4
DWORD gdi_rop3_code(BYTE code)
Packit 1fb8d4
{
Packit 1fb8d4
	return rop3_code_table[code].code;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
const char* gdi_rop3_code_string(BYTE code)
Packit 1fb8d4
{
Packit 1fb8d4
	return rop3_code_table[code].name;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
const char* gdi_rop3_string(DWORD rop)
Packit 1fb8d4
{
Packit 1fb8d4
	const size_t count = sizeof(rop3_code_table) / sizeof(rop3_code_table[0]);
Packit 1fb8d4
	size_t x;
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < count; x++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (rop3_code_table[x].code == rop)
Packit 1fb8d4
			return rop3_code_table[x].name;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return "UNKNOWN";
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
UINT32 gdi_get_pixel_format(UINT32 bitsPerPixel)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 format;
Packit 1fb8d4
Packit 1fb8d4
	switch (bitsPerPixel)
Packit 1fb8d4
	{
Packit 1fb8d4
		case 32:
Packit 1fb8d4
			format = PIXEL_FORMAT_BGRA32;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case 24:
Packit 1fb8d4
			format = PIXEL_FORMAT_BGR24;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case 16:
Packit 1fb8d4
			format = PIXEL_FORMAT_RGB16;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case 15:
Packit 1fb8d4
			format = PIXEL_FORMAT_RGB15;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case 8:
Packit 1fb8d4
			format = PIXEL_FORMAT_RGB8;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit 1fb8d4
			WLog_ERR(TAG, "Unsupported color depth %"PRIu32, bitsPerPixel);
Packit 1fb8d4
			format = 0;
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return format;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
gdiBitmap* gdi_bitmap_new_ex(rdpGdi* gdi, int width, int height, int bpp,
Packit 1fb8d4
                             BYTE* data)
Packit 1fb8d4
{
Packit 1fb8d4
	gdiBitmap* bitmap;
Packit 1fb8d4
	bitmap = (gdiBitmap*) calloc(1, sizeof(gdiBitmap));
Packit 1fb8d4
Packit 1fb8d4
	if (!bitmap)
Packit 1fb8d4
		goto fail_bitmap;
Packit 1fb8d4
Packit 1fb8d4
	if (!(bitmap->hdc = gdi_CreateCompatibleDC(gdi->hdc)))
Packit 1fb8d4
		goto fail_hdc;
Packit 1fb8d4
Packit 1fb8d4
	WLog_Print(gdi->log, WLOG_DEBUG, "gdi_bitmap_new: width:%d height:%d bpp:%d",
Packit 1fb8d4
	           width, height, bpp);
Packit 1fb8d4
Packit 1fb8d4
	if (!data)
Packit 1fb8d4
		bitmap->bitmap = gdi_CreateCompatibleBitmap(gdi->hdc, width, height);
Packit 1fb8d4
	else
Packit 1fb8d4
		bitmap->bitmap = gdi_create_bitmap(gdi, width, height, bpp, data);
Packit 1fb8d4
Packit 1fb8d4
	if (!bitmap->bitmap)
Packit 1fb8d4
		goto fail_bitmap_bitmap;
Packit 1fb8d4
Packit 1fb8d4
	gdi_SelectObject(bitmap->hdc, (HGDIOBJECT) bitmap->bitmap);
Packit 1fb8d4
	bitmap->org_bitmap = NULL;
Packit 1fb8d4
	return bitmap;
Packit 1fb8d4
fail_bitmap_bitmap:
Packit 1fb8d4
	gdi_DeleteDC(bitmap->hdc);
Packit 1fb8d4
fail_hdc:
Packit 1fb8d4
	free(bitmap);
Packit 1fb8d4
fail_bitmap:
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void gdi_bitmap_free_ex(gdiBitmap* bitmap)
Packit 1fb8d4
{
Packit 1fb8d4
	if (bitmap)
Packit 1fb8d4
	{
Packit 1fb8d4
		gdi_SelectObject(bitmap->hdc, (HGDIOBJECT) bitmap->org_bitmap);
Packit 1fb8d4
		gdi_DeleteObject((HGDIOBJECT) bitmap->bitmap);
Packit 1fb8d4
		gdi_DeleteDC(bitmap->hdc);
Packit 1fb8d4
		free(bitmap);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL gdi_bitmap_update(rdpContext* context,
Packit 1fb8d4
                       const BITMAP_UPDATE* bitmapUpdate)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 index;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !bitmapUpdate || !context->gdi || !context->codecs)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	for (index = 0; index < bitmapUpdate->number; index++)
Packit 1fb8d4
	{
Packit 1fb8d4
		const BITMAP_DATA* bitmap = &(bitmapUpdate->rectangles[index]);
Packit 1fb8d4
		rdpBitmap* bmp = Bitmap_Alloc(context);
Packit 1fb8d4
Packit 1fb8d4
		if (!bmp)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		Bitmap_SetDimensions(bmp, bitmap->width, bitmap->height);
Packit 1fb8d4
		Bitmap_SetRectangle(bmp, bitmap->destLeft, bitmap->destTop, bitmap->destRight,
Packit 1fb8d4
		                    bitmap->destBottom);
Packit 1fb8d4
Packit 1fb8d4
		if (!bmp->Decompress(context, bmp, bitmap->bitmapDataStream,
Packit 1fb8d4
		                     bitmap->width, bitmap->height, bitmap->bitsPerPixel,
Packit 1fb8d4
		                     bitmap->bitmapLength, bitmap->compressed,
Packit 1fb8d4
		                     RDP_CODEC_ID_NONE))
Packit 1fb8d4
		{
Packit 1fb8d4
			Bitmap_Free(context, bmp);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!bmp->New(context, bmp))
Packit 1fb8d4
		{
Packit 1fb8d4
			Bitmap_Free(context, bmp);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!bmp->Paint(context, bmp))
Packit 1fb8d4
		{
Packit 1fb8d4
			Bitmap_Free(context, bmp);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		Bitmap_Free(context, bmp);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_palette_update(rdpContext* context,
Packit 1fb8d4
                               const PALETTE_UPDATE* palette)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 index;
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !palette)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi = context->gdi;
Packit 1fb8d4
	gdi->palette.format = gdi->dstFormat;
Packit 1fb8d4
Packit 1fb8d4
	for (index = 0; index < palette->number; index++)
Packit 1fb8d4
	{
Packit 1fb8d4
		const PALETTE_ENTRY* pe = &(palette->entries[index]);
Packit 1fb8d4
		gdi->palette.palette[index] =
Packit 1fb8d4
		    FreeRDPGetColor(gdi->dstFormat, pe->red, pe->green, pe->blue, 0xFF);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_set_bounds(rdpContext* context, const rdpBounds* bounds)
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 (bounds)
Packit 1fb8d4
	{
Packit 1fb8d4
		gdi_SetClipRgn(gdi->drawing->hdc, bounds->left, bounds->top,
Packit 1fb8d4
		               bounds->right - bounds->left + 1, bounds->bottom - bounds->top + 1);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
		gdi_SetNullClipRgn(gdi->drawing->hdc);
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !dstblt)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi = context->gdi;
Packit 1fb8d4
	return gdi_BitBlt(gdi->drawing->hdc, dstblt->nLeftRect, dstblt->nTopRect,
Packit 1fb8d4
	                  dstblt->nWidth, dstblt->nHeight, NULL, 0, 0,
Packit 1fb8d4
	                  gdi_rop3_code(dstblt->bRop), &gdi->palette);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
Packit 1fb8d4
{
Packit 1fb8d4
	const rdpBrush* brush = &patblt->brush;
Packit 1fb8d4
	UINT32 foreColor;
Packit 1fb8d4
	UINT32 backColor;
Packit 1fb8d4
	UINT32 originalColor;
Packit 1fb8d4
	HGDI_BRUSH originalBrush, hbrush = NULL;
Packit 1fb8d4
	rdpGdi* gdi = context->gdi;
Packit 1fb8d4
	BOOL ret = FALSE;
Packit 1fb8d4
	const DWORD rop = gdi_rop3_code(patblt->bRop);
Packit 1fb8d4
	INT32 nXSrc = 0;
Packit 1fb8d4
	INT32 nYSrc = 0;
Packit 1fb8d4
	BYTE data[8 * 8 * 4];
Packit 1fb8d4
	HGDI_BITMAP hBmp = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_decode_color(gdi, patblt->foreColor, &foreColor, NULL))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_decode_color(gdi, patblt->backColor, &backColor, NULL))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	originalColor = gdi_SetTextColor(gdi->drawing->hdc, foreColor);
Packit 1fb8d4
	originalBrush = gdi->drawing->hdc->brush;
Packit 1fb8d4
Packit 1fb8d4
	switch (brush->style)
Packit 1fb8d4
	{
Packit 1fb8d4
		case GDI_BS_SOLID:
Packit 1fb8d4
			hbrush = gdi_CreateSolidBrush(foreColor);
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case GDI_BS_HATCHED:
Packit 1fb8d4
			{
Packit 1fb8d4
				const BYTE* hatched;
Packit 1fb8d4
				hatched = GDI_BS_HATCHED_PATTERNS + (8 * brush->hatch);
Packit 1fb8d4
Packit 1fb8d4
				if (!freerdp_image_copy_from_monochrome(data, gdi->drawing->hdc->format, 0, 0,
Packit 1fb8d4
				                                        0, 8, 8,
Packit 1fb8d4
				                                        hatched, backColor, foreColor, &gdi->palette))
Packit 1fb8d4
					goto out_error;
Packit 1fb8d4
Packit 1fb8d4
				hBmp = gdi_CreateBitmapEx(8, 8, gdi->drawing->hdc->format, 0, data, NULL);
Packit 1fb8d4
Packit 1fb8d4
				if (!hBmp)
Packit 1fb8d4
					goto out_error;
Packit 1fb8d4
Packit 1fb8d4
				hbrush = gdi_CreateHatchBrush(hBmp);
Packit 1fb8d4
			}
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case GDI_BS_PATTERN:
Packit 1fb8d4
			{
Packit 1fb8d4
				UINT32 brushFormat;
Packit 1fb8d4
Packit 1fb8d4
				if (brush->bpp > 1)
Packit 1fb8d4
				{
Packit 1fb8d4
					UINT32 bpp = brush->bpp;
Packit 1fb8d4
Packit 1fb8d4
					if ((bpp == 16) && (context->settings->ColorDepth == 15))
Packit 1fb8d4
						bpp = 15;
Packit 1fb8d4
Packit 1fb8d4
					brushFormat = gdi_get_pixel_format(bpp);
Packit 1fb8d4
Packit 1fb8d4
					if (!freerdp_image_copy(data, gdi->drawing->hdc->format, 0, 0, 0,
Packit 1fb8d4
					                        8, 8, brush->data, brushFormat, 0, 0, 0,
Packit 1fb8d4
					                        &gdi->palette, FREERDP_FLIP_NONE))
Packit 1fb8d4
						goto out_error;
Packit 1fb8d4
				}
Packit 1fb8d4
				else
Packit 1fb8d4
				{
Packit 1fb8d4
					if (!freerdp_image_copy_from_monochrome(data, gdi->drawing->hdc->format, 0, 0,
Packit 1fb8d4
					                                        0, 8, 8,
Packit 1fb8d4
					                                        brush->data, backColor, foreColor, &gdi->palette))
Packit 1fb8d4
						goto out_error;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				hBmp = gdi_CreateBitmapEx(8, 8, gdi->drawing->hdc->format, 0, data, NULL);
Packit 1fb8d4
Packit 1fb8d4
				if (!hBmp)
Packit 1fb8d4
					goto out_error;
Packit 1fb8d4
Packit 1fb8d4
				hbrush = gdi_CreatePatternBrush(hBmp);
Packit 1fb8d4
			}
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit 1fb8d4
			WLog_ERR(TAG,  "unimplemented brush style:%"PRIu32"", brush->style);
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (hbrush)
Packit 1fb8d4
	{
Packit 1fb8d4
		hbrush->nXOrg = brush->x;
Packit 1fb8d4
		hbrush->nYOrg = brush->y;
Packit 1fb8d4
		gdi->drawing->hdc->brush = hbrush;
Packit 1fb8d4
		ret = gdi_BitBlt(gdi->drawing->hdc, patblt->nLeftRect, patblt->nTopRect,
Packit 1fb8d4
		                 patblt->nWidth, patblt->nHeight,
Packit 1fb8d4
		                 gdi->primary->hdc, nXSrc, nYSrc, rop, &gdi->palette);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
out_error:
Packit 1fb8d4
	gdi_DeleteObject((HGDIOBJECT) hBmp);
Packit 1fb8d4
	gdi_DeleteObject((HGDIOBJECT) hbrush);
Packit 1fb8d4
	gdi->drawing->hdc->brush = originalBrush;
Packit 1fb8d4
	gdi_SetTextColor(gdi->drawing->hdc, originalColor);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt)
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
	return gdi_BitBlt(gdi->drawing->hdc, scrblt->nLeftRect, scrblt->nTopRect,
Packit 1fb8d4
	                  scrblt->nWidth, scrblt->nHeight, gdi->primary->hdc,
Packit 1fb8d4
	                  scrblt->nXSrc, scrblt->nYSrc, gdi_rop3_code(scrblt->bRop),
Packit 1fb8d4
	                  &gdi->palette);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_opaque_rect(rdpContext* context,
Packit 1fb8d4
                            const OPAQUE_RECT_ORDER* opaque_rect)
Packit 1fb8d4
{
Packit 1fb8d4
	GDI_RECT rect;
Packit 1fb8d4
	HGDI_BRUSH hBrush;
Packit 1fb8d4
	UINT32 brush_color;
Packit 1fb8d4
	rdpGdi* gdi = context->gdi;
Packit 1fb8d4
	BOOL ret;
Packit 1fb8d4
	INT32 x = opaque_rect->nLeftRect;
Packit 1fb8d4
	INT32 y = opaque_rect->nTopRect;
Packit 1fb8d4
	INT32 w = opaque_rect->nWidth;
Packit 1fb8d4
	INT32 h = opaque_rect->nHeight;
Packit 1fb8d4
	gdi_ClipCoords(gdi->drawing->hdc, &x, &y, &w, &h, NULL, NULL);
Packit 1fb8d4
	gdi_CRgnToRect(x, y, w, h, &rect);
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_decode_color(gdi, opaque_rect->color, &brush_color, NULL))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!(hBrush = gdi_CreateSolidBrush(brush_color)))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	ret = gdi_FillRect(gdi->drawing->hdc, &rect, hBrush);
Packit 1fb8d4
	gdi_DeleteObject((HGDIOBJECT) hBrush);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_multi_opaque_rect(rdpContext* context,
Packit 1fb8d4
                                  const MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 i;
Packit 1fb8d4
	GDI_RECT rect;
Packit 1fb8d4
	HGDI_BRUSH hBrush;
Packit 1fb8d4
	UINT32 brush_color;
Packit 1fb8d4
	rdpGdi* gdi = context->gdi;
Packit 1fb8d4
	BOOL ret = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_decode_color(gdi, multi_opaque_rect->color, &brush_color, NULL))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	hBrush = gdi_CreateSolidBrush(brush_color);
Packit 1fb8d4
Packit 1fb8d4
	if (!hBrush)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < multi_opaque_rect->numRectangles; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		const DELTA_RECT* rectangle = &multi_opaque_rect->rectangles[i];
Packit 1fb8d4
		INT32 x = rectangle->left;
Packit 1fb8d4
		INT32 y = rectangle->top;
Packit 1fb8d4
		INT32 w = rectangle->width;
Packit 1fb8d4
		INT32 h = rectangle->height;
Packit 1fb8d4
		gdi_ClipCoords(gdi->drawing->hdc, &x, &y, &w, &h, NULL, NULL);
Packit 1fb8d4
		gdi_CRgnToRect(x, y, w, h, &rect);
Packit 1fb8d4
		ret = gdi_FillRect(gdi->drawing->hdc, &rect, hBrush);
Packit 1fb8d4
Packit 1fb8d4
		if (!ret)
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	gdi_DeleteObject((HGDIOBJECT) hBrush);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_line_to(rdpContext* context, const LINE_TO_ORDER* lineTo)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 color;
Packit 1fb8d4
	HGDI_PEN hPen;
Packit 1fb8d4
	rdpGdi* gdi = context->gdi;
Packit 1fb8d4
	INT32 xStart = lineTo->nXStart;
Packit 1fb8d4
	INT32 yStart = lineTo->nYStart;
Packit 1fb8d4
	INT32 xEnd = lineTo->nXEnd;
Packit 1fb8d4
	INT32 yEnd = lineTo->nYEnd;
Packit 1fb8d4
	INT32 w = 0;
Packit 1fb8d4
	INT32 h = 0;
Packit 1fb8d4
	gdi_ClipCoords(gdi->drawing->hdc, &xStart, &yStart, &w, &h, NULL, NULL);
Packit 1fb8d4
	gdi_ClipCoords(gdi->drawing->hdc, &xEnd, &yEnd, &w, &h, NULL, NULL);
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_decode_color(gdi, lineTo->penColor, &color, NULL))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!(hPen = gdi_CreatePen(lineTo->penStyle, lineTo->penWidth, color,
Packit 1fb8d4
	                           gdi->drawing->hdc->format, &gdi->palette)))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi_SelectObject(gdi->drawing->hdc, (HGDIOBJECT) hPen);
Packit 1fb8d4
	gdi_SetROP2(gdi->drawing->hdc, lineTo->bRop2);
Packit 1fb8d4
	gdi_MoveToEx(gdi->drawing->hdc, lineTo->nXStart, lineTo->nYStart, NULL);
Packit 1fb8d4
	gdi_LineTo(gdi->drawing->hdc, lineTo->nXEnd, lineTo->nYEnd);
Packit 1fb8d4
	gdi_DeleteObject((HGDIOBJECT) hPen);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_polyline(rdpContext* context, const POLYLINE_ORDER* polyline)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 i;
Packit 1fb8d4
	INT32 x;
Packit 1fb8d4
	INT32 y;
Packit 1fb8d4
	UINT32 color;
Packit 1fb8d4
	HGDI_PEN hPen;
Packit 1fb8d4
	DELTA_POINT* points;
Packit 1fb8d4
	rdpGdi* gdi = context->gdi;
Packit 1fb8d4
	INT32 w = 0, h = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_decode_color(gdi, polyline->penColor, &color, NULL))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!(hPen = gdi_CreatePen(GDI_PS_SOLID, 1, color, gdi->drawing->hdc->format,
Packit 1fb8d4
	                           &gdi->palette)))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi_SelectObject(gdi->drawing->hdc, (HGDIOBJECT) hPen);
Packit 1fb8d4
	gdi_SetROP2(gdi->drawing->hdc, polyline->bRop2);
Packit 1fb8d4
	x = polyline->xStart;
Packit 1fb8d4
	y = polyline->yStart;
Packit 1fb8d4
	gdi_ClipCoords(gdi->drawing->hdc, &x, &y, &w, &h, NULL, NULL);
Packit 1fb8d4
	gdi_MoveToEx(gdi->drawing->hdc, x, y, NULL);
Packit 1fb8d4
	points = polyline->points;
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < polyline->numDeltaEntries; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		x += points[i].x;
Packit 1fb8d4
		y += points[i].y;
Packit 1fb8d4
		gdi_ClipCoords(gdi->drawing->hdc, &x, &y, &w, &h, NULL, NULL);
Packit 1fb8d4
		gdi_LineTo(gdi->drawing->hdc, x, y);
Packit 1fb8d4
		gdi_MoveToEx(gdi->drawing->hdc, x, y, NULL);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	gdi_DeleteObject((HGDIOBJECT) hPen);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
Packit 1fb8d4
{
Packit 1fb8d4
	gdiBitmap* bitmap;
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !memblt || !context->gdi || !memblt->bitmap)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	bitmap = (gdiBitmap*) memblt->bitmap;
Packit 1fb8d4
	gdi = context->gdi;
Packit 1fb8d4
	return gdi_BitBlt(gdi->drawing->hdc, memblt->nLeftRect, memblt->nTopRect,
Packit 1fb8d4
	                  memblt->nWidth, memblt->nHeight, bitmap->hdc,
Packit 1fb8d4
	                  memblt->nXSrc, memblt->nYSrc, gdi_rop3_code(memblt->bRop),
Packit 1fb8d4
	                  &gdi->palette);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
Packit 1fb8d4
{
Packit 1fb8d4
	HGDI_BRUSH originalBrush;
Packit 1fb8d4
	rdpGdi* gdi = context->gdi;
Packit 1fb8d4
	BOOL ret = TRUE;
Packit 1fb8d4
	const rdpBrush* brush = &mem3blt->brush;
Packit 1fb8d4
	gdiBitmap* bitmap = (gdiBitmap*) mem3blt->bitmap;
Packit 1fb8d4
	UINT32 foreColor;
Packit 1fb8d4
	UINT32 backColor;
Packit 1fb8d4
	UINT32 originalColor;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_decode_color(gdi, mem3blt->foreColor, &foreColor, NULL))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_decode_color(gdi, mem3blt->backColor, &backColor, NULL))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	originalColor = gdi_SetTextColor(gdi->drawing->hdc, foreColor);
Packit 1fb8d4
Packit 1fb8d4
	switch (brush->style)
Packit 1fb8d4
	{
Packit 1fb8d4
		case GDI_BS_SOLID:
Packit 1fb8d4
			originalBrush = gdi->drawing->hdc->brush;
Packit 1fb8d4
			gdi->drawing->hdc->brush = gdi_CreateSolidBrush(foreColor);
Packit 1fb8d4
Packit 1fb8d4
			if (!gdi->drawing->hdc->brush)
Packit 1fb8d4
			{
Packit 1fb8d4
				ret = FALSE;
Packit 1fb8d4
				goto out_fail;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			ret = gdi_BitBlt(gdi->drawing->hdc, mem3blt->nLeftRect, mem3blt->nTopRect,
Packit 1fb8d4
			                 mem3blt->nWidth, mem3blt->nHeight, bitmap->hdc,
Packit 1fb8d4
			                 mem3blt->nXSrc, mem3blt->nYSrc, gdi_rop3_code(mem3blt->bRop),
Packit 1fb8d4
			                 &gdi->palette);
Packit 1fb8d4
			gdi_DeleteObject((HGDIOBJECT) gdi->drawing->hdc->brush);
Packit 1fb8d4
			gdi->drawing->hdc->brush = originalBrush;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case GDI_BS_PATTERN:
Packit 1fb8d4
			{
Packit 1fb8d4
				HGDI_BITMAP hBmp;
Packit 1fb8d4
				UINT32 brushFormat;
Packit 1fb8d4
				BYTE* data = (BYTE*) _aligned_malloc(8 * 8 * GetBytesPerPixel(
Packit 1fb8d4
				        gdi->drawing->hdc->format),
Packit 1fb8d4
				                                     16);
Packit 1fb8d4
Packit 1fb8d4
				if (!data)
Packit 1fb8d4
				{
Packit 1fb8d4
					ret = FALSE;
Packit 1fb8d4
					goto out_fail;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				if (brush->bpp > 1)
Packit 1fb8d4
				{
Packit 1fb8d4
					UINT32 bpp = brush->bpp;
Packit 1fb8d4
Packit 1fb8d4
					if ((bpp == 16) && (context->settings->ColorDepth == 15))
Packit 1fb8d4
						bpp = 15;
Packit 1fb8d4
Packit 1fb8d4
					brushFormat = gdi_get_pixel_format(bpp);
Packit 1fb8d4
Packit 1fb8d4
					if (!freerdp_image_copy(data, gdi->drawing->hdc->format, 0, 0, 0,
Packit 1fb8d4
					                        8, 8, brush->data, brushFormat,
Packit 1fb8d4
					                        0, 0, 0, &gdi->palette, FREERDP_FLIP_NONE))
Packit 1fb8d4
					{
Packit 1fb8d4
						ret = FALSE;
Packit 1fb8d4
						_aligned_free(data);
Packit 1fb8d4
						goto out_fail;
Packit 1fb8d4
					}
Packit 1fb8d4
				}
Packit 1fb8d4
				else
Packit 1fb8d4
				{
Packit 1fb8d4
					if (!freerdp_image_copy_from_monochrome(data, gdi->drawing->hdc->format, 0, 0,
Packit 1fb8d4
					                                        0, 8, 8,
Packit 1fb8d4
					                                        brush->data, backColor, foreColor,
Packit 1fb8d4
					                                        &gdi->palette))
Packit 1fb8d4
					{
Packit 1fb8d4
						ret = FALSE;
Packit 1fb8d4
						_aligned_free(data);
Packit 1fb8d4
						goto out_fail;
Packit 1fb8d4
					}
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				hBmp = gdi_CreateBitmap(8, 8, gdi->drawing->hdc->format, data);
Packit 1fb8d4
Packit 1fb8d4
				if (!hBmp)
Packit 1fb8d4
				{
Packit 1fb8d4
					ret = FALSE;
Packit 1fb8d4
					_aligned_free(data);
Packit 1fb8d4
					goto out_fail;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				originalBrush = gdi->drawing->hdc->brush;
Packit 1fb8d4
				gdi->drawing->hdc->brush = gdi_CreatePatternBrush(hBmp);
Packit 1fb8d4
Packit 1fb8d4
				if (!gdi->drawing->hdc->brush)
Packit 1fb8d4
				{
Packit 1fb8d4
					gdi_DeleteObject((HGDIOBJECT) hBmp);
Packit 1fb8d4
					goto out_fail;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				gdi->drawing->hdc->brush->nXOrg = brush->x;
Packit 1fb8d4
				gdi->drawing->hdc->brush->nYOrg = brush->y;
Packit 1fb8d4
				ret = gdi_BitBlt(gdi->drawing->hdc, mem3blt->nLeftRect, mem3blt->nTopRect,
Packit 1fb8d4
				                 mem3blt->nWidth, mem3blt->nHeight, bitmap->hdc,
Packit 1fb8d4
				                 mem3blt->nXSrc, mem3blt->nYSrc, gdi_rop3_code(mem3blt->bRop),
Packit 1fb8d4
				                 &gdi->palette);
Packit 1fb8d4
				gdi_DeleteObject((HGDIOBJECT) gdi->drawing->hdc->brush);
Packit 1fb8d4
				gdi_DeleteObject((HGDIOBJECT) hBmp);
Packit 1fb8d4
				gdi->drawing->hdc->brush = originalBrush;
Packit 1fb8d4
			}
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit 1fb8d4
			WLog_ERR(TAG,  "Mem3Blt unimplemented brush style:%"PRIu32"", brush->style);
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
out_fail:
Packit 1fb8d4
	gdi_SetTextColor(gdi->drawing->hdc, originalColor);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_polygon_sc(rdpContext* context,
Packit 1fb8d4
                           const POLYGON_SC_ORDER* polygon_sc)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_WARN(TAG, "%s: not implemented", __FUNCTION__);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_WARN(TAG, "%s: not implemented", __FUNCTION__);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_ellipse_sc(rdpContext* context,
Packit 1fb8d4
                           const ELLIPSE_SC_ORDER* ellipse_sc)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_WARN(TAG, "%s: not implemented", __FUNCTION__);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_ellipse_cb(rdpContext* context,
Packit 1fb8d4
                           const ELLIPSE_CB_ORDER* ellipse_cb)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_WARN(TAG, "%s: not implemented", __FUNCTION__);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_frame_marker(rdpContext* context,
Packit 1fb8d4
                             const FRAME_MARKER_ORDER* frameMarker)
Packit 1fb8d4
{
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL gdi_surface_frame_marker(rdpContext* context,
Packit 1fb8d4
                              const SURFACE_FRAME_MARKER* surfaceFrameMarker)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_Print(context->gdi->log, WLOG_DEBUG, "frameId %"PRIu32" frameAction %"PRIu32"",
Packit 1fb8d4
	           surfaceFrameMarker->frameId,
Packit 1fb8d4
	           surfaceFrameMarker->frameAction);
Packit 1fb8d4
Packit 1fb8d4
	switch (surfaceFrameMarker->frameAction)
Packit 1fb8d4
	{
Packit 1fb8d4
		case SURFACECMD_FRAMEACTION_BEGIN:
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case SURFACECMD_FRAMEACTION_END:
Packit 1fb8d4
			if (context->settings->FrameAcknowledge > 0)
Packit 1fb8d4
			{
Packit 1fb8d4
				IFCALL(context->update->SurfaceFrameAcknowledge, context,
Packit 1fb8d4
				       surfaceFrameMarker->frameId);
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_surface_bits(rdpContext* context,
Packit 1fb8d4
                             const SURFACE_BITS_COMMAND* cmd)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL result = FALSE;
Packit 1fb8d4
	DWORD format;
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
	REGION16 region;
Packit 1fb8d4
	RECTANGLE_16 cmdRect;
Packit 1fb8d4
	UINT32 i, nbRects;
Packit 1fb8d4
	const RECTANGLE_16* rects;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !cmd)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi = context->gdi;
Packit 1fb8d4
	WLog_Print(gdi->log, WLOG_DEBUG,
Packit 1fb8d4
	           "destLeft %"PRIu32" destTop %"PRIu32" destRight %"PRIu32" destBottom %"PRIu32" "
Packit 1fb8d4
	           "bpp %"PRIu8" flags %"PRIx8" codecID %"PRIu16" width %"PRIu16" height %"PRIu16" length %"PRIu32"",
Packit 1fb8d4
	           cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom,
Packit 1fb8d4
	           cmd->bmp.bpp, cmd->bmp.flags, cmd->bmp.codecID, cmd->bmp.width, cmd->bmp.height,
Packit 1fb8d4
	           cmd->bmp.bitmapDataLength);
Packit 1fb8d4
	region16_init(&region);
Packit 1fb8d4
	cmdRect.left = cmd->destLeft;
Packit 1fb8d4
	cmdRect.top = cmd->destTop;
Packit 1fb8d4
	cmdRect.right = cmdRect.left + cmd->bmp.width;
Packit 1fb8d4
	cmdRect.bottom = cmdRect.top + cmd->bmp.height;
Packit 1fb8d4
Packit 1fb8d4
	switch (cmd->bmp.codecID)
Packit 1fb8d4
	{
Packit 1fb8d4
		case RDP_CODEC_ID_REMOTEFX:
Packit 1fb8d4
			if (!rfx_process_message(context->codecs->rfx, cmd->bmp.bitmapData,
Packit 1fb8d4
			                         cmd->bmp.bitmapDataLength,
Packit 1fb8d4
			                         cmd->destLeft, cmd->destTop,
Packit 1fb8d4
			                         gdi->primary_buffer, gdi->dstFormat,
Packit 1fb8d4
			                         gdi->stride, gdi->height, &region))
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "Failed to process RemoteFX message");
Packit 1fb8d4
				goto out;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case RDP_CODEC_ID_NSCODEC:
Packit 1fb8d4
			format = gdi->dstFormat;
Packit 1fb8d4
Packit 1fb8d4
			if (!nsc_process_message(context->codecs->nsc, cmd->bmp.bpp, cmd->bmp.width,
Packit 1fb8d4
			                         cmd->bmp.height, cmd->bmp.bitmapData,
Packit 1fb8d4
			                         cmd->bmp.bitmapDataLength, gdi->primary_buffer,
Packit 1fb8d4
			                         format, gdi->stride, cmd->destLeft, cmd->destTop,
Packit 1fb8d4
			                         cmd->bmp.width, cmd->bmp.height, FREERDP_FLIP_VERTICAL))
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "Failed to process NSCodec message");
Packit 1fb8d4
				goto out;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			region16_union_rect(&region, &region, &cmdRect);
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case RDP_CODEC_ID_NONE:
Packit 1fb8d4
			format = gdi_get_pixel_format(cmd->bmp.bpp);
Packit 1fb8d4
Packit 1fb8d4
			if (!freerdp_image_copy(gdi->primary_buffer, gdi->dstFormat, gdi->stride,
Packit 1fb8d4
			                        cmd->destLeft, cmd->destTop, cmd->bmp.width, cmd->bmp.height,
Packit 1fb8d4
			                        cmd->bmp.bitmapData, format, 0, 0, 0,
Packit 1fb8d4
			                        &gdi->palette, FREERDP_FLIP_VERTICAL))
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "Failed to process nocodec message");
Packit 1fb8d4
				goto out;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			region16_union_rect(&region, &region, &cmdRect);
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit 1fb8d4
			WLog_ERR(TAG, "Unsupported codecID %"PRIu32"", cmd->bmp.codecID);
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!(rects = region16_rects(&region, &nbRects)))
Packit 1fb8d4
		goto out;
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < nbRects; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		UINT32 left = rects[i].left;
Packit 1fb8d4
		UINT32 top = rects[i].top;
Packit 1fb8d4
		UINT32 width = rects[i].right - rects[i].left;
Packit 1fb8d4
		UINT32 height = rects[i].bottom - rects[i].top;
Packit 1fb8d4
Packit 1fb8d4
		if (!gdi_InvalidateRegion(gdi->primary->hdc, left, top, width, height))
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "Failed to update invalid region");
Packit 1fb8d4
			goto out;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	result = TRUE;
Packit 1fb8d4
out:
Packit 1fb8d4
	region16_uninit(&region);
Packit 1fb8d4
	return result;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Register GDI callbacks with libfreerdp-core.
Packit 1fb8d4
 * @param inst current instance
Packit 1fb8d4
 * @return
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
static void gdi_register_update_callbacks(rdpUpdate* update)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpPrimaryUpdate* primary = update->primary;
Packit 1fb8d4
	update->Palette = gdi_palette_update;
Packit 1fb8d4
	update->SetBounds = gdi_set_bounds;
Packit 1fb8d4
	primary->DstBlt = gdi_dstblt;
Packit 1fb8d4
	primary->PatBlt = gdi_patblt;
Packit 1fb8d4
	primary->ScrBlt = gdi_scrblt;
Packit 1fb8d4
	primary->OpaqueRect = gdi_opaque_rect;
Packit 1fb8d4
	primary->DrawNineGrid = NULL;
Packit 1fb8d4
	primary->MultiDstBlt = NULL;
Packit 1fb8d4
	primary->MultiPatBlt = NULL;
Packit 1fb8d4
	primary->MultiScrBlt = NULL;
Packit 1fb8d4
	primary->MultiOpaqueRect = gdi_multi_opaque_rect;
Packit 1fb8d4
	primary->MultiDrawNineGrid = NULL;
Packit 1fb8d4
	primary->LineTo = gdi_line_to;
Packit 1fb8d4
	primary->Polyline = gdi_polyline;
Packit 1fb8d4
	primary->MemBlt = gdi_memblt;
Packit 1fb8d4
	primary->Mem3Blt = gdi_mem3blt;
Packit 1fb8d4
	primary->SaveBitmap = NULL;
Packit 1fb8d4
	primary->GlyphIndex = NULL;
Packit 1fb8d4
	primary->FastIndex = NULL;
Packit 1fb8d4
	primary->FastGlyph = NULL;
Packit 1fb8d4
	primary->PolygonSC = gdi_polygon_sc;
Packit 1fb8d4
	primary->PolygonCB = gdi_polygon_cb;
Packit 1fb8d4
	primary->EllipseSC = gdi_ellipse_sc;
Packit 1fb8d4
	primary->EllipseCB = gdi_ellipse_cb;
Packit 1fb8d4
	update->SurfaceBits = gdi_surface_bits;
Packit 1fb8d4
	update->SurfaceFrameMarker = gdi_surface_frame_marker;
Packit 1fb8d4
	update->altsec->FrameMarker = gdi_frame_marker;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL gdi_init_primary(rdpGdi* gdi, UINT32 stride, UINT32 format,
Packit 1fb8d4
                             BYTE* buffer, void (*pfree)(void*))
Packit 1fb8d4
{
Packit 1fb8d4
	gdi->primary = (gdiBitmap*) calloc(1, sizeof(gdiBitmap));
Packit 1fb8d4
Packit 1fb8d4
	if (format > 0)
Packit 1fb8d4
		gdi->dstFormat = format;
Packit 1fb8d4
Packit 1fb8d4
	if (stride > 0)
Packit 1fb8d4
		gdi->stride = stride;
Packit 1fb8d4
	else
Packit 1fb8d4
		gdi->stride = gdi->width * GetBytesPerPixel(gdi->dstFormat);
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi->primary)
Packit 1fb8d4
		goto fail_primary;
Packit 1fb8d4
Packit 1fb8d4
	if (!(gdi->primary->hdc = gdi_CreateCompatibleDC(gdi->hdc)))
Packit 1fb8d4
		goto fail_hdc;
Packit 1fb8d4
Packit 1fb8d4
	if (!buffer)
Packit 1fb8d4
	{
Packit 1fb8d4
		gdi->primary->bitmap = gdi_CreateCompatibleBitmap(
Packit 1fb8d4
		                           gdi->hdc, gdi->width, gdi->height);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		gdi->primary->bitmap = gdi_CreateBitmapEx(gdi->width, gdi->height,
Packit 1fb8d4
		                       gdi->dstFormat,
Packit 1fb8d4
		                       gdi->stride,
Packit 1fb8d4
		                       buffer, pfree);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi->primary->bitmap)
Packit 1fb8d4
		goto fail_bitmap;
Packit 1fb8d4
Packit 1fb8d4
	gdi->stride = gdi->primary->bitmap->scanline;
Packit 1fb8d4
	gdi_SelectObject(gdi->primary->hdc, (HGDIOBJECT) gdi->primary->bitmap);
Packit 1fb8d4
	gdi->primary->org_bitmap = NULL;
Packit 1fb8d4
	gdi->primary_buffer = gdi->primary->bitmap->data;
Packit 1fb8d4
Packit 1fb8d4
	if (!(gdi->primary->hdc->hwnd = (HGDI_WND) calloc(1, sizeof(GDI_WND))))
Packit 1fb8d4
		goto fail_hwnd;
Packit 1fb8d4
Packit 1fb8d4
	if (!(gdi->primary->hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0)))
Packit 1fb8d4
		goto fail_hwnd;
Packit 1fb8d4
Packit 1fb8d4
	gdi->primary->hdc->hwnd->invalid->null = TRUE;
Packit 1fb8d4
	gdi->primary->hdc->hwnd->count = 32;
Packit 1fb8d4
Packit 1fb8d4
	if (!(gdi->primary->hdc->hwnd->cinvalid = (HGDI_RGN) calloc(
Packit 1fb8d4
	            gdi->primary->hdc->hwnd->count, sizeof(GDI_RGN))))
Packit 1fb8d4
		goto fail_hwnd;
Packit 1fb8d4
Packit 1fb8d4
	gdi->primary->hdc->hwnd->ninvalid = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi->drawing)
Packit 1fb8d4
		gdi->drawing = gdi->primary;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
fail_hwnd:
Packit 1fb8d4
	gdi_DeleteObject((HGDIOBJECT) gdi->primary->bitmap);
Packit 1fb8d4
fail_bitmap:
Packit 1fb8d4
	gdi_DeleteDC(gdi->primary->hdc);
Packit 1fb8d4
fail_hdc:
Packit 1fb8d4
	free(gdi->primary);
Packit 1fb8d4
	gdi->primary = NULL;
Packit 1fb8d4
fail_primary:
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL gdi_resize(rdpGdi* gdi, UINT32 width, UINT32 height)
Packit 1fb8d4
{
Packit 1fb8d4
	return gdi_resize_ex(gdi, width, height, 0, 0, NULL, NULL);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL gdi_resize_ex(rdpGdi* gdi, UINT32 width, UINT32 height,
Packit 1fb8d4
                   UINT32 stride, UINT32 format, BYTE* buffer,
Packit 1fb8d4
                   void (*pfree)(void*))
Packit 1fb8d4
{
Packit 1fb8d4
	if (!gdi || !gdi->primary)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (gdi->width == width && gdi->height == height &&
Packit 1fb8d4
	    (!buffer || gdi->primary_buffer == buffer))
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (gdi->drawing == gdi->primary)
Packit 1fb8d4
		gdi->drawing = NULL;
Packit 1fb8d4
Packit 1fb8d4
	gdi->width = width;
Packit 1fb8d4
	gdi->height = height;
Packit 1fb8d4
	gdi_bitmap_free_ex(gdi->primary);
Packit 1fb8d4
	gdi->primary = NULL;
Packit 1fb8d4
	gdi->primary_buffer = NULL;
Packit 1fb8d4
	return gdi_init_primary(gdi, stride, format, buffer, pfree);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Initialize GDI
Packit 1fb8d4
 * @param inst current instance
Packit 1fb8d4
 * @return
Packit 1fb8d4
 */
Packit 1fb8d4
BOOL gdi_init(freerdp* instance, UINT32 format)
Packit 1fb8d4
{
Packit 1fb8d4
	return gdi_init_ex(instance, format, 0, NULL, _aligned_free);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL gdi_init_ex(freerdp* instance, UINT32 format, UINT32 stride, BYTE* buffer,
Packit 1fb8d4
                 void (*pfree)(void*))
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 SrcFormat = gdi_get_pixel_format(instance->settings->ColorDepth);
Packit 1fb8d4
	rdpGdi* gdi = (rdpGdi*) calloc(1, sizeof(rdpGdi));
Packit 1fb8d4
	rdpContext* context = instance->context;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi)
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	instance->context->gdi = gdi;
Packit 1fb8d4
	gdi->log = WLog_Get(TAG);
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi->log)
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	gdi->context = instance->context;
Packit 1fb8d4
	gdi->width = instance->settings->DesktopWidth;
Packit 1fb8d4
	gdi->height = instance->settings->DesktopHeight;
Packit 1fb8d4
	gdi->dstFormat = format;
Packit 1fb8d4
	/* default internal buffer format */
Packit 1fb8d4
	WLog_Print(gdi->log, WLOG_INFO, "Local framebuffer format  %s",
Packit 1fb8d4
	           FreeRDPGetColorFormatName(gdi->dstFormat));
Packit 1fb8d4
	WLog_Print(gdi->log, WLOG_INFO, "Remote framebuffer format %s",
Packit 1fb8d4
	           FreeRDPGetColorFormatName(SrcFormat));
Packit 1fb8d4
Packit 1fb8d4
	if (!(gdi->hdc = gdi_GetDC()))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	gdi->hdc->format = gdi->dstFormat;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_init_primary(gdi, stride, gdi->dstFormat, buffer, pfree))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!(context->cache = cache_new(instance->settings)))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	gdi_register_update_callbacks(instance->update);
Packit 1fb8d4
	brush_cache_register_callbacks(instance->update);
Packit 1fb8d4
	glyph_cache_register_callbacks(instance->update);
Packit 1fb8d4
	bitmap_cache_register_callbacks(instance->update);
Packit 1fb8d4
	offscreen_cache_register_callbacks(instance->update);
Packit 1fb8d4
	palette_cache_register_callbacks(instance->update);
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_register_graphics(instance->context->graphics))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
fail:
Packit 1fb8d4
	gdi_free(instance);
Packit 1fb8d4
	WLog_ERR(TAG,  "failed to initialize gdi");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void gdi_free(freerdp* instance)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
	rdpContext* context;
Packit 1fb8d4
Packit 1fb8d4
	if (!instance || !instance->context)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	gdi = instance->context->gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (gdi)
Packit 1fb8d4
	{
Packit 1fb8d4
		gdi_bitmap_free_ex(gdi->primary);
Packit 1fb8d4
		gdi_DeleteDC(gdi->hdc);
Packit 1fb8d4
		free(gdi);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	context = instance->context;
Packit 1fb8d4
	cache_free(context->cache);
Packit 1fb8d4
	context->cache = NULL;
Packit 1fb8d4
	instance->context->gdi = (rdpGdi*) NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL gdi_send_suppress_output(rdpGdi* gdi, BOOL suppress)
Packit 1fb8d4
{
Packit 1fb8d4
	RECTANGLE_16 rect;
Packit 1fb8d4
	rdpSettings* settings;
Packit 1fb8d4
	rdpUpdate* update;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi || !gdi->context->settings || !gdi->context->update)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (gdi->suppressOutput == suppress)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	gdi->suppressOutput = suppress;
Packit 1fb8d4
	settings = gdi->context->settings;
Packit 1fb8d4
	update = gdi->context->update;
Packit 1fb8d4
	rect.left = 0;
Packit 1fb8d4
	rect.top = 0;
Packit 1fb8d4
	rect.right = settings->DesktopWidth;
Packit 1fb8d4
	rect.bottom = settings->DesktopHeight;
Packit 1fb8d4
	return update->SuppressOutput(gdi->context, !suppress, &rect);
Packit 1fb8d4
}
Packit 1fb8d4