2011-07-01 00:17:55 +04:00
|
|
|
/**
|
2012-10-09 07:02:04 +04:00
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
2011-07-01 00:17:55 +04:00
|
|
|
* GDI Device Context Functions
|
|
|
|
*
|
|
|
|
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
2016-04-05 18:07:45 +03:00
|
|
|
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
|
|
|
|
* Copyright 2016 Thincast Technologies GmbH
|
2011-07-01 00:17:55 +04:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Device Context Functions: http://msdn.microsoft.com/en-us/library/dd183554 */
|
|
|
|
|
2022-02-16 13:20:38 +03:00
|
|
|
#include <freerdp/config.h>
|
2012-08-15 01:09:01 +04:00
|
|
|
|
2011-07-01 00:17:55 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2012-08-15 01:09:01 +04:00
|
|
|
|
2011-07-01 00:17:55 +04:00
|
|
|
#include <freerdp/freerdp.h>
|
2011-08-15 22:33:04 +04:00
|
|
|
#include <freerdp/gdi/gdi.h>
|
2011-07-01 00:17:55 +04:00
|
|
|
|
2011-08-22 21:08:01 +04:00
|
|
|
#include <freerdp/gdi/region.h>
|
2011-07-01 00:17:55 +04:00
|
|
|
|
2011-08-22 21:08:01 +04:00
|
|
|
#include <freerdp/gdi/dc.h>
|
2011-07-01 00:17:55 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current device context (a new one is created each time).\n
|
|
|
|
* @msdn{dd144871}
|
|
|
|
* @return current device context
|
|
|
|
*/
|
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
HGDI_DC gdi_GetDC(void)
|
2011-07-01 00:17:55 +04:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
HGDI_DC hDC = (HGDI_DC)calloc(1, sizeof(GDI_DC));
|
2016-08-02 09:43:26 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!hDC)
|
|
|
|
return NULL;
|
2015-06-16 16:42:07 +03:00
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
hDC->format = PIXEL_FORMAT_XRGB32;
|
2011-07-01 00:17:55 +04:00
|
|
|
hDC->drawMode = GDI_R2_BLACK;
|
|
|
|
hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0);
|
2016-08-02 09:43:26 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!hDC->clip)
|
|
|
|
{
|
|
|
|
free(hDC);
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-08-02 09:43:26 +03:00
|
|
|
|
2016-10-06 14:41:52 +03:00
|
|
|
hDC->clip->null = TRUE;
|
2011-07-01 00:17:55 +04:00
|
|
|
hDC->hwnd = NULL;
|
|
|
|
return hDC;
|
|
|
|
}
|
|
|
|
|
2012-02-02 03:42:20 +04:00
|
|
|
/**
|
|
|
|
* Create a device context.\n
|
|
|
|
* @msdn{dd144871}
|
|
|
|
* @return new device context
|
|
|
|
*/
|
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
HGDI_DC gdi_CreateDC(UINT32 format)
|
2012-02-02 03:42:20 +04:00
|
|
|
{
|
2015-05-08 22:39:23 +03:00
|
|
|
HGDI_DC hDC;
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (!(hDC = (HGDI_DC)calloc(1, sizeof(GDI_DC))))
|
2015-05-08 22:39:23 +03:00
|
|
|
return NULL;
|
2012-02-02 03:42:20 +04:00
|
|
|
|
|
|
|
hDC->drawMode = GDI_R2_BLACK;
|
2015-05-08 22:39:23 +03:00
|
|
|
|
|
|
|
if (!(hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0)))
|
|
|
|
goto fail;
|
|
|
|
|
2016-10-06 14:41:52 +03:00
|
|
|
hDC->clip->null = TRUE;
|
2012-02-02 03:42:20 +04:00
|
|
|
hDC->hwnd = NULL;
|
2016-04-05 18:07:45 +03:00
|
|
|
hDC->format = format;
|
2012-02-02 03:42:20 +04:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (!(hDC->hwnd = (HGDI_WND)calloc(1, sizeof(GDI_WND))))
|
2015-05-08 22:39:23 +03:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (!(hDC->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0)))
|
|
|
|
goto fail;
|
|
|
|
|
2016-10-06 14:41:52 +03:00
|
|
|
hDC->hwnd->invalid->null = TRUE;
|
2012-02-02 03:42:20 +04:00
|
|
|
hDC->hwnd->count = 32;
|
2016-08-02 09:43:26 +03:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (!(hDC->hwnd->cinvalid = (HGDI_RGN)calloc(hDC->hwnd->count, sizeof(GDI_RGN))))
|
2015-05-08 22:39:23 +03:00
|
|
|
goto fail;
|
|
|
|
|
2012-02-02 03:42:20 +04:00
|
|
|
hDC->hwnd->ninvalid = 0;
|
|
|
|
return hDC;
|
2015-05-08 22:39:23 +03:00
|
|
|
fail:
|
|
|
|
gdi_DeleteDC(hDC);
|
|
|
|
return NULL;
|
2012-02-02 03:42:20 +04:00
|
|
|
}
|
|
|
|
|
2011-07-01 00:17:55 +04:00
|
|
|
/**
|
|
|
|
* Create a new device context compatible with the given device context.\n
|
|
|
|
* @msdn{dd183489}
|
|
|
|
* @param hdc device context
|
|
|
|
* @return new compatible device context
|
|
|
|
*/
|
|
|
|
|
|
|
|
HGDI_DC gdi_CreateCompatibleDC(HGDI_DC hdc)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
HGDI_DC hDC = (HGDI_DC)calloc(1, sizeof(GDI_DC));
|
2016-08-02 09:43:26 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!hDC)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0)))
|
|
|
|
{
|
|
|
|
free(hDC);
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-08-02 09:43:26 +03:00
|
|
|
|
2016-10-06 14:41:52 +03:00
|
|
|
hDC->clip->null = TRUE;
|
2016-04-05 18:07:45 +03:00
|
|
|
hDC->format = hdc->format;
|
2011-07-01 00:17:55 +04:00
|
|
|
hDC->drawMode = hdc->drawMode;
|
|
|
|
hDC->hwnd = NULL;
|
|
|
|
return hDC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Select a GDI object in the current device context.\n
|
|
|
|
* @msdn{dd162957}
|
|
|
|
* @param hdc device context
|
|
|
|
* @param hgdiobject new selected GDI object
|
|
|
|
* @return previous selected GDI object
|
|
|
|
*/
|
|
|
|
|
|
|
|
HGDIOBJECT gdi_SelectObject(HGDI_DC hdc, HGDIOBJECT hgdiobject)
|
|
|
|
{
|
|
|
|
HGDIOBJECT previousSelectedObject = hdc->selectedObject;
|
|
|
|
|
|
|
|
if (hgdiobject == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (hgdiobject->objectType == GDIOBJECT_BITMAP)
|
|
|
|
{
|
|
|
|
hdc->selectedObject = hgdiobject;
|
|
|
|
}
|
|
|
|
else if (hgdiobject->objectType == GDIOBJECT_PEN)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
previousSelectedObject = (HGDIOBJECT)hdc->pen;
|
|
|
|
hdc->pen = (HGDI_PEN)hgdiobject;
|
2011-07-01 00:17:55 +04:00
|
|
|
}
|
|
|
|
else if (hgdiobject->objectType == GDIOBJECT_BRUSH)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
previousSelectedObject = (HGDIOBJECT)hdc->brush;
|
|
|
|
hdc->brush = (HGDI_BRUSH)hgdiobject;
|
2011-07-01 00:17:55 +04:00
|
|
|
}
|
|
|
|
else if (hgdiobject->objectType == GDIOBJECT_REGION)
|
|
|
|
{
|
|
|
|
hdc->selectedObject = hgdiobject;
|
2019-11-06 17:24:51 +03:00
|
|
|
previousSelectedObject = (HGDIOBJECT)COMPLEXREGION;
|
2011-07-01 00:17:55 +04:00
|
|
|
}
|
|
|
|
else if (hgdiobject->objectType == GDIOBJECT_RECT)
|
|
|
|
{
|
|
|
|
hdc->selectedObject = hgdiobject;
|
2019-11-06 17:24:51 +03:00
|
|
|
previousSelectedObject = (HGDIOBJECT)SIMPLEREGION;
|
2011-07-01 00:17:55 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Unknown GDI Object Type */
|
2015-04-14 11:14:23 +03:00
|
|
|
return NULL;
|
2011-07-01 00:17:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return previousSelectedObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete a GDI object.\n
|
|
|
|
* @msdn{dd183539}
|
|
|
|
* @param hgdiobject GDI object
|
2015-06-26 15:32:38 +03:00
|
|
|
* @return nonzero if successful, 0 otherwise
|
2011-07-01 00:17:55 +04:00
|
|
|
*/
|
|
|
|
|
2015-06-26 15:32:38 +03:00
|
|
|
BOOL gdi_DeleteObject(HGDIOBJECT hgdiobject)
|
2011-07-01 00:17:55 +04:00
|
|
|
{
|
2014-07-08 23:07:19 +04:00
|
|
|
if (!hgdiobject)
|
2015-06-26 15:32:38 +03:00
|
|
|
return FALSE;
|
2011-07-01 00:17:55 +04:00
|
|
|
|
|
|
|
if (hgdiobject->objectType == GDIOBJECT_BITMAP)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
HGDI_BITMAP hBitmap = (HGDI_BITMAP)hgdiobject;
|
2011-07-01 00:17:55 +04:00
|
|
|
|
2015-08-12 11:49:59 +03:00
|
|
|
if (hBitmap->data && hBitmap->free)
|
|
|
|
{
|
|
|
|
hBitmap->free(hBitmap->data);
|
|
|
|
hBitmap->data = NULL;
|
|
|
|
}
|
2011-07-01 00:17:55 +04:00
|
|
|
|
|
|
|
free(hBitmap);
|
|
|
|
}
|
|
|
|
else if (hgdiobject->objectType == GDIOBJECT_PEN)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
HGDI_PEN hPen = (HGDI_PEN)hgdiobject;
|
2011-07-01 00:17:55 +04:00
|
|
|
free(hPen);
|
|
|
|
}
|
|
|
|
else if (hgdiobject->objectType == GDIOBJECT_BRUSH)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
HGDI_BRUSH hBrush = (HGDI_BRUSH)hgdiobject;
|
2011-07-01 00:17:55 +04:00
|
|
|
free(hBrush);
|
|
|
|
}
|
|
|
|
else if (hgdiobject->objectType == GDIOBJECT_REGION)
|
|
|
|
{
|
|
|
|
free(hgdiobject);
|
|
|
|
}
|
|
|
|
else if (hgdiobject->objectType == GDIOBJECT_RECT)
|
|
|
|
{
|
|
|
|
free(hgdiobject);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Unknown GDI Object Type */
|
|
|
|
free(hgdiobject);
|
2015-06-26 15:32:38 +03:00
|
|
|
return FALSE;
|
2011-07-01 00:17:55 +04:00
|
|
|
}
|
|
|
|
|
2015-06-26 15:32:38 +03:00
|
|
|
return TRUE;
|
2011-07-01 00:17:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete device context.\n
|
|
|
|
* @msdn{dd183533}
|
|
|
|
* @param hdc device context
|
2015-06-26 15:32:38 +03:00
|
|
|
* @return nonzero if successful, 0 otherwise
|
2011-07-01 00:17:55 +04:00
|
|
|
*/
|
|
|
|
|
2015-06-26 15:32:38 +03:00
|
|
|
BOOL gdi_DeleteDC(HGDI_DC hdc)
|
2011-07-01 00:17:55 +04:00
|
|
|
{
|
2015-05-08 22:39:23 +03:00
|
|
|
if (hdc)
|
2011-07-01 00:17:55 +04:00
|
|
|
{
|
2015-05-08 22:39:23 +03:00
|
|
|
if (hdc->hwnd)
|
|
|
|
{
|
|
|
|
free(hdc->hwnd->cinvalid);
|
|
|
|
free(hdc->hwnd->invalid);
|
|
|
|
free(hdc->hwnd);
|
|
|
|
}
|
2016-08-02 09:43:26 +03:00
|
|
|
|
2015-05-08 22:39:23 +03:00
|
|
|
free(hdc->clip);
|
|
|
|
free(hdc);
|
2011-07-01 00:17:55 +04:00
|
|
|
}
|
|
|
|
|
2015-06-26 15:32:38 +03:00
|
|
|
return TRUE;
|
2011-07-01 00:17:55 +04:00
|
|
|
}
|