FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
wf_graphics.c
1
20#include <freerdp/config.h>
21
22#include <winpr/crt.h>
23
24#include <freerdp/codecs.h>
25#include <freerdp/log.h>
26
27#include "wf_gdi.h"
28#include "wf_graphics.h"
29
30#define TAG CLIENT_TAG("windows")
31
32HBITMAP wf_create_dib(wfContext* wfc, UINT32 width, UINT32 height, UINT32 srcFormat,
33 const BYTE* data, BYTE** pdata)
34{
35 HDC hdc;
36 int negHeight;
37 HBITMAP bitmap;
38 BITMAPINFO bmi;
39 BYTE* cdata = NULL;
40 UINT32 dstFormat = srcFormat;
47 negHeight = (height < 0) ? height : height * (-1);
48 hdc = GetDC(NULL);
49 bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
50 bmi.bmiHeader.biWidth = width;
51 bmi.bmiHeader.biHeight = negHeight;
52 bmi.bmiHeader.biPlanes = 1;
53 bmi.bmiHeader.biBitCount = FreeRDPGetBitsPerPixel(dstFormat);
54 bmi.bmiHeader.biCompression = BI_RGB;
55 bitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)&cdata, NULL, 0);
56
57 if (data)
58 freerdp_image_copy(cdata, dstFormat, 0, 0, 0, width, height, data, srcFormat, 0, 0, 0,
59 &wfc->common.context.gdi->palette, FREERDP_FLIP_NONE);
60
61 if (pdata)
62 *pdata = cdata;
63
64 ReleaseDC(NULL, hdc);
65 GdiFlush();
66 return bitmap;
67}
68
69wfBitmap* wf_image_new(wfContext* wfc, UINT32 width, UINT32 height, UINT32 format, const BYTE* data)
70{
71 HDC hdc;
72 wfBitmap* image;
73 hdc = GetDC(NULL);
74 image = (wfBitmap*)malloc(sizeof(wfBitmap));
75 image->hdc = CreateCompatibleDC(hdc);
76 image->bitmap = wf_create_dib(wfc, width, height, format, data, &(image->pdata));
77 image->org_bitmap = (HBITMAP)SelectObject(image->hdc, image->bitmap);
78 ReleaseDC(NULL, hdc);
79 return image;
80}
81
82void wf_image_free(wfBitmap* image)
83{
84 if (image != 0)
85 {
86 SelectObject(image->hdc, image->org_bitmap);
87 DeleteObject(image->bitmap);
88 DeleteDC(image->hdc);
89 free(image);
90 }
91}
92
93/* Bitmap Class */
94
95static BOOL wf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
96{
97 HDC hdc;
98 wfContext* wfc = (wfContext*)context;
99 wfBitmap* wf_bitmap = (wfBitmap*)bitmap;
100
101 if (!context || !bitmap)
102 return FALSE;
103
104 wf_bitmap = (wfBitmap*)bitmap;
105 hdc = GetDC(NULL);
106 wf_bitmap->hdc = CreateCompatibleDC(hdc);
107
108 if (!bitmap->data)
109 wf_bitmap->bitmap = CreateCompatibleBitmap(hdc, bitmap->width, bitmap->height);
110 else
111 wf_bitmap->bitmap =
112 wf_create_dib(wfc, bitmap->width, bitmap->height, bitmap->format, bitmap->data, NULL);
113
114 wf_bitmap->org_bitmap = (HBITMAP)SelectObject(wf_bitmap->hdc, wf_bitmap->bitmap);
115 ReleaseDC(NULL, hdc);
116 return TRUE;
117}
118
119static void wf_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap)
120{
121 wfBitmap* wf_bitmap = (wfBitmap*)bitmap;
122
123 if (wf_bitmap != 0)
124 {
125 SelectObject(wf_bitmap->hdc, wf_bitmap->org_bitmap);
126 DeleteObject(wf_bitmap->bitmap);
127 DeleteDC(wf_bitmap->hdc);
128
129 winpr_aligned_free(wf_bitmap->_bitmap.data);
130 wf_bitmap->_bitmap.data = NULL;
131 }
132}
133
134static BOOL wf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
135{
136 BOOL rc;
137 UINT32 width, height;
138 wfContext* wfc = (wfContext*)context;
139 wfBitmap* wf_bitmap = (wfBitmap*)bitmap;
140
141 if (!context || !bitmap)
142 return FALSE;
143
144 width = bitmap->right - bitmap->left + 1;
145 height = bitmap->bottom - bitmap->top + 1;
146 rc = BitBlt(wfc->primary->hdc, bitmap->left, bitmap->top, width, height, wf_bitmap->hdc, 0, 0,
147 SRCCOPY);
148 wf_invalidate_region(wfc, bitmap->left, bitmap->top, width, height);
149 return rc;
150}
151
152static BOOL wf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary)
153{
154 wfContext* wfc = (wfContext*)context;
155 wfBitmap* bmp = (wfBitmap*)bitmap;
156 rdpGdi* gdi = context->gdi;
157
158 if (!gdi || !wfc)
159 return FALSE;
160
161 if (primary)
162 wfc->drawing = wfc->primary;
163 else if (!bmp)
164 return FALSE;
165 else
166 wfc->drawing = bmp;
167
168 return TRUE;
169}
170
171/* Pointer Class */
172
173static BOOL flip_bitmap(const BYTE* src, BYTE* dst, UINT32 scanline, UINT32 nHeight)
174{
175 BYTE* bottomLine = dst + scanline * (nHeight - 1);
176
177 for (UINT32 x = 0; x < nHeight; x++)
178 {
179 memcpy(bottomLine, src, scanline);
180 src += scanline;
181 bottomLine -= scanline;
182 }
183
184 return TRUE;
185}
186
187static BOOL wf_Pointer_New(rdpContext* context, rdpPointer* pointer)
188{
189 HCURSOR hCur;
190 ICONINFO info;
191 rdpGdi* gdi;
192 BOOL rc = FALSE;
193
194 if (!context || !pointer)
195 return FALSE;
196
197 gdi = context->gdi;
198
199 if (!gdi)
200 return FALSE;
201
202 info.fIcon = FALSE;
203 info.xHotspot = pointer->xPos;
204 info.yHotspot = pointer->yPos;
205
206 if (pointer->xorBpp == 1)
207 {
208 BYTE* pdata = NULL;
209
210 if ((pointer->lengthAndMask > 0) || (pointer->lengthXorMask > 0))
211 {
212 pdata =
213 (BYTE*)winpr_aligned_malloc(pointer->lengthAndMask + pointer->lengthXorMask, 16);
214
215 if (!pdata)
216 goto fail;
217 }
218
219 CopyMemory(pdata, pointer->andMaskData, pointer->lengthAndMask);
220 CopyMemory(pdata + pointer->lengthAndMask, pointer->xorMaskData, pointer->lengthXorMask);
221 info.hbmMask = CreateBitmap(pointer->width, pointer->height * 2, 1, 1, pdata);
222 winpr_aligned_free(pdata);
223 info.hbmColor = NULL;
224 }
225 else
226 {
227 UINT32 srcFormat;
228 BYTE* pdata = NULL;
229
230 if (pointer->lengthAndMask > 0)
231 {
232 pdata = (BYTE*)winpr_aligned_malloc(pointer->lengthAndMask, 16);
233
234 if (!pdata)
235 goto fail;
236 flip_bitmap(pointer->andMaskData, pdata, (pointer->width + 7) / 8, pointer->height);
237 }
238
239 info.hbmMask = CreateBitmap(pointer->width, pointer->height, 1, 1, pdata);
240 winpr_aligned_free(pdata);
241
242 /* currently color xorBpp is only 24 per [T128] section 8.14.3 */
243 srcFormat = gdi_get_pixel_format(pointer->xorBpp);
244
245 if (!srcFormat)
246 goto fail;
247
248 info.hbmColor = wf_create_dib((wfContext*)context, pointer->width, pointer->height,
249 gdi->dstFormat, NULL, &pdata);
250
251 if (!info.hbmColor)
252 goto fail;
253
254 if (!freerdp_image_copy_from_pointer_data(
255 pdata, gdi->dstFormat, 0, 0, 0, pointer->width, pointer->height,
256 pointer->xorMaskData, pointer->lengthXorMask, pointer->andMaskData,
257 pointer->lengthAndMask, pointer->xorBpp, &gdi->palette))
258 {
259 goto fail;
260 }
261 }
262
263 hCur = CreateIconIndirect(&info);
264 ((wfPointer*)pointer)->cursor = hCur;
265 rc = TRUE;
266fail:
267
268 if (info.hbmMask)
269 DeleteObject(info.hbmMask);
270
271 if (info.hbmColor)
272 DeleteObject(info.hbmColor);
273
274 return rc;
275}
276
277static void wf_Pointer_Free(rdpContext* context, rdpPointer* pointer)
278{
279 HCURSOR hCur;
280
281 if (!context || !pointer)
282 return;
283
284 hCur = ((wfPointer*)pointer)->cursor;
285
286 if (hCur != 0)
287 DestroyIcon(hCur);
288}
289
290static BOOL wf_Pointer_Set(rdpContext* context, rdpPointer* pointer)
291{
292 HCURSOR hCur;
293 wfContext* wfc = (wfContext*)context;
294
295 if (!context || !pointer)
296 return FALSE;
297
298 hCur = ((wfPointer*)pointer)->cursor;
299
300 if (hCur != NULL)
301 {
302 SetCursor(hCur);
303 wfc->cursor = hCur;
304 }
305
306 return TRUE;
307}
308
309static BOOL wf_Pointer_SetNull(rdpContext* context)
310{
311 if (!context)
312 return FALSE;
313
314 return TRUE;
315}
316
317static BOOL wf_Pointer_SetDefault(rdpContext* context)
318{
319 if (!context)
320 return FALSE;
321
322 return TRUE;
323}
324
325static BOOL wf_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
326{
327 if (!context)
328 return FALSE;
329
330 return TRUE;
331}
332
333BOOL wf_register_pointer(rdpGraphics* graphics)
334{
335 wfContext* wfc;
336 rdpPointer pointer = { 0 };
337
338 if (!graphics)
339 return FALSE;
340
341 wfc = (wfContext*)graphics->context;
342 pointer.size = sizeof(wfPointer);
343 pointer.New = wf_Pointer_New;
344 pointer.Free = wf_Pointer_Free;
345 pointer.Set = wf_Pointer_Set;
346 pointer.SetNull = wf_Pointer_SetNull;
347 pointer.SetDefault = wf_Pointer_SetDefault;
348 pointer.SetPosition = wf_Pointer_SetPosition;
349 graphics_register_pointer(graphics, &pointer);
350 return TRUE;
351}
352
353/* Graphics Module */
354
355BOOL wf_register_graphics(rdpGraphics* graphics)
356{
357 wfContext* wfc;
358 rdpGlyph glyph;
359 rdpBitmap bitmap;
360
361 if (!graphics)
362 return FALSE;
363
364 wfc = (wfContext*)graphics->context;
365 bitmap = *graphics->Bitmap_Prototype;
366 bitmap.size = sizeof(wfBitmap);
367 bitmap.New = wf_Bitmap_New;
368 bitmap.Free = wf_Bitmap_Free;
369 bitmap.Paint = wf_Bitmap_Paint;
370 bitmap.SetSurface = wf_Bitmap_SetSurface;
371 graphics_register_bitmap(graphics, &bitmap);
372 glyph = *graphics->Glyph_Prototype;
373 graphics_register_glyph(graphics, &glyph);
374 return TRUE;
375}