FreeRDP
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 
32 HBITMAP 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 
69 wfBitmap* 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 
82 void 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 
95 static 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 
119 static 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 
134 static 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 
152 static 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 
173 static 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 
187 static 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;
266 fail:
267 
268  if (info.hbmMask)
269  DeleteObject(info.hbmMask);
270 
271  if (info.hbmColor)
272  DeleteObject(info.hbmColor);
273 
274  return rc;
275 }
276 
277 static 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 
290 static 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 
309 static BOOL wf_Pointer_SetNull(rdpContext* context)
310 {
311  if (!context)
312  return FALSE;
313 
314  return TRUE;
315 }
316 
317 static BOOL wf_Pointer_SetDefault(rdpContext* context)
318 {
319  if (!context)
320  return FALSE;
321 
322  return TRUE;
323 }
324 
325 static BOOL wf_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
326 {
327  if (!context)
328  return FALSE;
329 
330  return TRUE;
331 }
332 
333 BOOL 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 
355 BOOL 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 }