FreeRDP/libfreerdp/gdi/dc.c

259 lines
5.1 KiB
C

/*
* FreeRDP: A Remote Desktop Protocol Implementation
* GDI Device Context Functions
*
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
* Copyright 2016 Thincast Technologies GmbH
*
* 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 */
#include <freerdp/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <freerdp/freerdp.h>
#include <freerdp/gdi/gdi.h>
#include <freerdp/gdi/region.h>
#include <freerdp/gdi/dc.h>
/**
* @brief Get the current device context (a new one is created each time).
* msdn{dd144871}
*
* @return current device context
*/
HGDI_DC gdi_GetDC(void)
{
HGDI_DC hDC = (HGDI_DC)calloc(1, sizeof(GDI_DC));
if (!hDC)
return NULL;
hDC->format = PIXEL_FORMAT_XRGB32;
hDC->drawMode = GDI_R2_BLACK;
hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0);
if (!hDC->clip)
{
free(hDC);
return NULL;
}
hDC->clip->null = TRUE;
hDC->hwnd = NULL;
return hDC;
}
/**
* @brief Create a device context.
* msdn{dd144871}
*
* @return new device context
*/
HGDI_DC gdi_CreateDC(UINT32 format)
{
HGDI_DC hDC = NULL;
if (!(hDC = (HGDI_DC)calloc(1, sizeof(GDI_DC))))
return NULL;
hDC->drawMode = GDI_R2_BLACK;
if (!(hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0)))
goto fail;
hDC->clip->null = TRUE;
hDC->hwnd = NULL;
hDC->format = format;
if (!(hDC->hwnd = (HGDI_WND)calloc(1, sizeof(GDI_WND))))
goto fail;
if (!(hDC->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0)))
goto fail;
hDC->hwnd->invalid->null = TRUE;
hDC->hwnd->count = 32;
if (!(hDC->hwnd->cinvalid = (HGDI_RGN)calloc(hDC->hwnd->count, sizeof(GDI_RGN))))
goto fail;
hDC->hwnd->ninvalid = 0;
return hDC;
fail:
gdi_DeleteDC(hDC);
return NULL;
}
/**
* @brief Create a new device context compatible with the given device context.
* msdn{dd183489}
* @param hdc device context
* @return new compatible device context
*/
HGDI_DC gdi_CreateCompatibleDC(HGDI_DC hdc)
{
HGDI_DC hDC = (HGDI_DC)calloc(1, sizeof(GDI_DC));
if (!hDC)
return NULL;
if (!(hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0)))
{
free(hDC);
return NULL;
}
hDC->clip->null = TRUE;
hDC->format = hdc->format;
hDC->drawMode = hdc->drawMode;
hDC->hwnd = NULL;
return hDC;
}
/**
* @brief Select a GDI object in the current device context.
* 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)
{
previousSelectedObject = (HGDIOBJECT)hdc->pen;
hdc->pen = (HGDI_PEN)hgdiobject;
}
else if (hgdiobject->objectType == GDIOBJECT_BRUSH)
{
previousSelectedObject = (HGDIOBJECT)hdc->brush;
hdc->brush = (HGDI_BRUSH)hgdiobject;
}
else if (hgdiobject->objectType == GDIOBJECT_REGION)
{
hdc->selectedObject = hgdiobject;
previousSelectedObject = (HGDIOBJECT)COMPLEXREGION;
}
else if (hgdiobject->objectType == GDIOBJECT_RECT)
{
hdc->selectedObject = hgdiobject;
previousSelectedObject = (HGDIOBJECT)SIMPLEREGION;
}
else
{
/* Unknown GDI Object Type */
return NULL;
}
return previousSelectedObject;
}
/**
* @brief Delete a GDI object.
* msdn{dd183539}
* @param hgdiobject GDI object
* @return nonzero if successful, 0 otherwise
*/
BOOL gdi_DeleteObject(HGDIOBJECT hgdiobject)
{
if (!hgdiobject)
return FALSE;
if (hgdiobject->objectType == GDIOBJECT_BITMAP)
{
HGDI_BITMAP hBitmap = (HGDI_BITMAP)hgdiobject;
if (hBitmap->data && hBitmap->free)
{
hBitmap->free(hBitmap->data);
hBitmap->data = NULL;
}
free(hBitmap);
}
else if (hgdiobject->objectType == GDIOBJECT_PEN)
{
HGDI_PEN hPen = (HGDI_PEN)hgdiobject;
free(hPen);
}
else if (hgdiobject->objectType == GDIOBJECT_BRUSH)
{
HGDI_BRUSH hBrush = (HGDI_BRUSH)hgdiobject;
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);
return FALSE;
}
return TRUE;
}
/**
* @brief Delete device context.
* msdn{dd183533}
* @param hdc device context
* @return nonzero if successful, 0 otherwise
*/
BOOL gdi_DeleteDC(HGDI_DC hdc)
{
if (hdc)
{
if (hdc->hwnd)
{
free(hdc->hwnd->cinvalid);
free(hdc->hwnd->invalid);
free(hdc->hwnd);
}
free(hdc->clip);
free(hdc);
}
return TRUE;
}