1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * GDI Device Context Functions
4  *
5  * Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  * Copyright 2016 Armin Novak <armin.novak@thincast.com>
7  * Copyright 2016 Thincast Technologies GmbH
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *     http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 /* Device Context Functions: http://msdn.microsoft.com/en-us/library/dd183554 */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 
31 #include <freerdp/freerdp.h>
32 #include <freerdp/gdi/gdi.h>
33 
34 #include <freerdp/gdi/region.h>
35 
36 #include <freerdp/gdi/dc.h>
37 
38 /**
39  * Get the current device context (a new one is created each time).\n
40  * @msdn{dd144871}
41  * @return current device context
42  */
43 
gdi_GetDC(void)44 HGDI_DC gdi_GetDC(void)
45 {
46 	HGDI_DC hDC = (HGDI_DC)calloc(1, sizeof(GDI_DC));
47 
48 	if (!hDC)
49 		return NULL;
50 
51 	hDC->format = PIXEL_FORMAT_XRGB32;
52 	hDC->drawMode = GDI_R2_BLACK;
53 	hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0);
54 
55 	if (!hDC->clip)
56 	{
57 		free(hDC);
58 		return NULL;
59 	}
60 
61 	hDC->clip->null = TRUE;
62 	hDC->hwnd = NULL;
63 	return hDC;
64 }
65 
66 /**
67  * Create a device context.\n
68  * @msdn{dd144871}
69  * @return new device context
70  */
71 
gdi_CreateDC(UINT32 format)72 HGDI_DC gdi_CreateDC(UINT32 format)
73 {
74 	HGDI_DC hDC;
75 
76 	if (!(hDC = (HGDI_DC)calloc(1, sizeof(GDI_DC))))
77 		return NULL;
78 
79 	hDC->drawMode = GDI_R2_BLACK;
80 
81 	if (!(hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0)))
82 		goto fail;
83 
84 	hDC->clip->null = TRUE;
85 	hDC->hwnd = NULL;
86 	hDC->format = format;
87 
88 	if (!(hDC->hwnd = (HGDI_WND)calloc(1, sizeof(GDI_WND))))
89 		goto fail;
90 
91 	if (!(hDC->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0)))
92 		goto fail;
93 
94 	hDC->hwnd->invalid->null = TRUE;
95 	hDC->hwnd->count = 32;
96 
97 	if (!(hDC->hwnd->cinvalid = (HGDI_RGN)calloc(hDC->hwnd->count, sizeof(GDI_RGN))))
98 		goto fail;
99 
100 	hDC->hwnd->ninvalid = 0;
101 	return hDC;
102 fail:
103 	gdi_DeleteDC(hDC);
104 	return NULL;
105 }
106 
107 /**
108  * Create a new device context compatible with the given device context.\n
109  * @msdn{dd183489}
110  * @param hdc device context
111  * @return new compatible device context
112  */
113 
gdi_CreateCompatibleDC(HGDI_DC hdc)114 HGDI_DC gdi_CreateCompatibleDC(HGDI_DC hdc)
115 {
116 	HGDI_DC hDC = (HGDI_DC)calloc(1, sizeof(GDI_DC));
117 
118 	if (!hDC)
119 		return NULL;
120 
121 	if (!(hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0)))
122 	{
123 		free(hDC);
124 		return NULL;
125 	}
126 
127 	hDC->clip->null = TRUE;
128 	hDC->format = hdc->format;
129 	hDC->drawMode = hdc->drawMode;
130 	hDC->hwnd = NULL;
131 	return hDC;
132 }
133 
134 /**
135  * Select a GDI object in the current device context.\n
136  * @msdn{dd162957}
137  * @param hdc device context
138  * @param hgdiobject new selected GDI object
139  * @return previous selected GDI object
140  */
141 
gdi_SelectObject(HGDI_DC hdc,HGDIOBJECT hgdiobject)142 HGDIOBJECT gdi_SelectObject(HGDI_DC hdc, HGDIOBJECT hgdiobject)
143 {
144 	HGDIOBJECT previousSelectedObject = hdc->selectedObject;
145 
146 	if (hgdiobject == NULL)
147 		return NULL;
148 
149 	if (hgdiobject->objectType == GDIOBJECT_BITMAP)
150 	{
151 		hdc->selectedObject = hgdiobject;
152 	}
153 	else if (hgdiobject->objectType == GDIOBJECT_PEN)
154 	{
155 		previousSelectedObject = (HGDIOBJECT)hdc->pen;
156 		hdc->pen = (HGDI_PEN)hgdiobject;
157 	}
158 	else if (hgdiobject->objectType == GDIOBJECT_BRUSH)
159 	{
160 		previousSelectedObject = (HGDIOBJECT)hdc->brush;
161 		hdc->brush = (HGDI_BRUSH)hgdiobject;
162 	}
163 	else if (hgdiobject->objectType == GDIOBJECT_REGION)
164 	{
165 		hdc->selectedObject = hgdiobject;
166 		previousSelectedObject = (HGDIOBJECT)COMPLEXREGION;
167 	}
168 	else if (hgdiobject->objectType == GDIOBJECT_RECT)
169 	{
170 		hdc->selectedObject = hgdiobject;
171 		previousSelectedObject = (HGDIOBJECT)SIMPLEREGION;
172 	}
173 	else
174 	{
175 		/* Unknown GDI Object Type */
176 		return NULL;
177 	}
178 
179 	return previousSelectedObject;
180 }
181 
182 /**
183  * Delete a GDI object.\n
184  * @msdn{dd183539}
185  * @param hgdiobject GDI object
186  * @return nonzero if successful, 0 otherwise
187  */
188 
gdi_DeleteObject(HGDIOBJECT hgdiobject)189 BOOL gdi_DeleteObject(HGDIOBJECT hgdiobject)
190 {
191 	if (!hgdiobject)
192 		return FALSE;
193 
194 	if (hgdiobject->objectType == GDIOBJECT_BITMAP)
195 	{
196 		HGDI_BITMAP hBitmap = (HGDI_BITMAP)hgdiobject;
197 
198 		if (hBitmap->data && hBitmap->free)
199 		{
200 			hBitmap->free(hBitmap->data);
201 			hBitmap->data = NULL;
202 		}
203 
204 		free(hBitmap);
205 	}
206 	else if (hgdiobject->objectType == GDIOBJECT_PEN)
207 	{
208 		HGDI_PEN hPen = (HGDI_PEN)hgdiobject;
209 		free(hPen);
210 	}
211 	else if (hgdiobject->objectType == GDIOBJECT_BRUSH)
212 	{
213 		HGDI_BRUSH hBrush = (HGDI_BRUSH)hgdiobject;
214 		free(hBrush);
215 	}
216 	else if (hgdiobject->objectType == GDIOBJECT_REGION)
217 	{
218 		free(hgdiobject);
219 	}
220 	else if (hgdiobject->objectType == GDIOBJECT_RECT)
221 	{
222 		free(hgdiobject);
223 	}
224 	else
225 	{
226 		/* Unknown GDI Object Type */
227 		free(hgdiobject);
228 		return FALSE;
229 	}
230 
231 	return TRUE;
232 }
233 
234 /**
235  * Delete device context.\n
236  * @msdn{dd183533}
237  * @param hdc device context
238  * @return nonzero if successful, 0 otherwise
239  */
240 
gdi_DeleteDC(HGDI_DC hdc)241 BOOL gdi_DeleteDC(HGDI_DC hdc)
242 {
243 	if (hdc)
244 	{
245 		if (hdc->hwnd)
246 		{
247 			free(hdc->hwnd->cinvalid);
248 			free(hdc->hwnd->invalid);
249 			free(hdc->hwnd);
250 		}
251 
252 		free(hdc->clip);
253 		free(hdc);
254 	}
255 
256 	return TRUE;
257 }
258