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