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