22 #include <freerdp/config.h>
24 #include <winpr/crt.h>
26 #include <freerdp/log.h>
27 #include <freerdp/freerdp.h>
28 #include <freerdp/gdi/dc.h>
29 #include <freerdp/gdi/shape.h>
30 #include <freerdp/gdi/region.h>
31 #include <freerdp/gdi/bitmap.h>
38 #define TAG FREERDP_TAG("gdi")
41 HGDI_BITMAP gdi_create_bitmap(rdpGdi* gdi, UINT32 nWidth, UINT32 nHeight, UINT32 SrcFormat,
46 BYTE* pSrcData = NULL;
47 BYTE* pDstData = NULL;
53 nDstStep = nWidth * FreeRDPGetBytesPerPixel(gdi->dstFormat);
54 pDstData = winpr_aligned_malloc(1ull * nHeight * nDstStep, 16);
60 nSrcStep = nWidth * FreeRDPGetBytesPerPixel(SrcFormat);
62 if (!freerdp_image_copy_no_overlap(pDstData, gdi->dstFormat, nDstStep, 0, 0, nWidth, nHeight,
63 pSrcData, SrcFormat, nSrcStep, 0, 0, &gdi->palette,
66 winpr_aligned_free(pDstData);
70 bitmap = gdi_CreateBitmap(nWidth, nHeight, gdi->dstFormat, pDstData);
74 static BOOL gdi_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
77 rdpGdi* gdi = context->gdi;
79 gdi_bitmap->hdc = gdi_CreateCompatibleDC(gdi->hdc);
85 gdi_bitmap->bitmap = gdi_CreateCompatibleBitmap(gdi->hdc, bitmap->width, bitmap->height);
88 UINT32 format = bitmap->format;
90 gdi_create_bitmap(gdi, bitmap->width, bitmap->height, format, bitmap->data);
106 static void gdi_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap)
117 winpr_aligned_free(bitmap->data);
123 static BOOL gdi_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
126 UINT32 width = bitmap->right - bitmap->left + 1;
127 UINT32 height = bitmap->bottom - bitmap->top + 1;
128 return gdi_BitBlt(context->gdi->primary->hdc, WINPR_ASSERTING_INT_CAST(
int, bitmap->left),
129 WINPR_ASSERTING_INT_CAST(
int, bitmap->top),
130 WINPR_ASSERTING_INT_CAST(
int, width), WINPR_ASSERTING_INT_CAST(
int, height),
131 gdi_bitmap->hdc, 0, 0, GDI_SRCCOPY, &context->gdi->palette);
134 static BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
const BYTE* pSrcData,
135 UINT32 DstWidth, UINT32 DstHeight, UINT32 bpp, UINT32 length,
136 BOOL compressed, UINT32 codecId)
138 UINT32 SrcSize = length;
139 rdpGdi* gdi = context->gdi;
140 UINT32 size = DstWidth * DstHeight;
141 bitmap->compressed = FALSE;
142 bitmap->format = gdi->dstFormat;
144 if ((FreeRDPGetBytesPerPixel(bitmap->format) == 0) || (DstWidth == 0) || (DstHeight == 0) ||
145 (DstWidth > UINT32_MAX / DstHeight) ||
146 (size > (UINT32_MAX / FreeRDPGetBytesPerPixel(bitmap->format))))
148 WLog_ERR(TAG,
"invalid input data");
152 size *= FreeRDPGetBytesPerPixel(bitmap->format);
153 bitmap->length = size;
154 bitmap->data = (BYTE*)winpr_aligned_malloc(bitmap->length, 16);
161 if ((codecId == RDP_CODEC_ID_REMOTEFX) || (codecId == RDP_CODEC_ID_IMAGE_REMOTEFX))
164 region16_init(&invalidRegion);
166 if (!rfx_process_message(context->codecs->rfx, pSrcData, SrcSize, bitmap->left,
167 bitmap->top, bitmap->data, bitmap->format, gdi->stride,
168 WINPR_ASSERTING_INT_CAST(UINT32, gdi->height), &invalidRegion))
170 WLog_ERR(TAG,
"rfx_process_message failed");
174 else if (codecId == RDP_CODEC_ID_NSCODEC)
176 const int status = nsc_process_message(
177 context->codecs->nsc, 32, DstWidth, DstHeight, pSrcData, SrcSize, bitmap->data,
178 bitmap->format, 0, 0, 0, DstWidth, DstHeight, FREERDP_FLIP_VERTICAL);
182 WLog_ERR(TAG,
"nsc_process_message failed");
186 return freerdp_image_copy_no_overlap(bitmap->data, bitmap->format, 0, 0, 0, DstWidth,
187 DstHeight, pSrcData, PIXEL_FORMAT_XRGB32, 0, 0, 0,
188 &gdi->palette, FREERDP_FLIP_VERTICAL);
192 if (!interleaved_decompress(context->codecs->interleaved, pSrcData, SrcSize, DstWidth,
193 DstHeight, bpp, bitmap->data, bitmap->format, 0, 0, 0,
194 DstWidth, DstHeight, &gdi->palette))
196 WLog_ERR(TAG,
"interleaved_decompress failed");
202 const BOOL fidelity =
204 freerdp_planar_switch_bgr(context->codecs->planar, fidelity);
205 if (!planar_decompress(context->codecs->planar, pSrcData, SrcSize, DstWidth, DstHeight,
206 bitmap->data, bitmap->format, 0, 0, 0, DstWidth, DstHeight,
209 WLog_ERR(TAG,
"planar_decompress failed");
216 const UINT32 SrcFormat = gdi_get_pixel_format(bpp);
217 const size_t sbpp = FreeRDPGetBytesPerPixel(SrcFormat);
218 const size_t dbpp = FreeRDPGetBytesPerPixel(bitmap->format);
220 if ((sbpp == 0) || (dbpp == 0))
224 const size_t dstSize = SrcSize * dbpp / sbpp;
226 if (dstSize < bitmap->length)
228 WLog_ERR(TAG,
"dstSize %" PRIuz
" < bitmap->length %" PRIu32, dstSize,
234 if (!freerdp_image_copy_no_overlap(bitmap->data, bitmap->format, 0, 0, 0, DstWidth,
235 DstHeight, pSrcData, SrcFormat, 0, 0, 0, &gdi->palette,
236 FREERDP_FLIP_VERTICAL))
238 WLog_ERR(TAG,
"freerdp_image_copy failed");
246 static BOOL gdi_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary)
259 gdi->drawing = gdi->primary;
261 gdi->drawing = (gdiBitmap*)bitmap;
267 static BOOL gdi_Glyph_New(rdpContext* context, rdpGlyph* glyph)
272 if (!context || !glyph)
281 gdi_glyph->hdc->format = PIXEL_FORMAT_MONO;
282 data = freerdp_glyph_convert(glyph->cx, glyph->cy, glyph->aj);
290 gdi_glyph->bitmap = gdi_CreateBitmap(glyph->cx, glyph->cy, PIXEL_FORMAT_MONO, data);
295 winpr_aligned_free(data);
304 static void gdi_Glyph_Free(rdpContext* context, rdpGlyph* glyph)
319 static BOOL gdi_Glyph_Draw(rdpContext* context,
const rdpGlyph* glyph, INT32 x, INT32 y, INT32 w,
320 INT32 h, INT32 sx, INT32 sy, BOOL fOpRedundant)
327 if (!context || !glyph)
344 rect.right = x + w - 1;
347 rect.bottom = y + h - 1;
349 if ((rect.left < rect.right) && (rect.top < rect.bottom))
351 brush = gdi_CreateSolidBrush(gdi->drawing->hdc->bkColor);
356 gdi_FillRect(gdi->drawing->hdc, &rect, brush);
361 brush = gdi_CreateSolidBrush(gdi->drawing->hdc->textColor);
366 gdi_SelectObject(gdi->drawing->hdc, (
HGDIOBJECT)brush);
367 rc = gdi_BitBlt(gdi->drawing->hdc, x, y, w, h,
gdi_glyph->hdc, sx, sy, GDI_GLYPH_ORDER,
368 &context->gdi->palette);
373 static BOOL gdi_Glyph_BeginDraw(rdpContext* context, INT32 x, INT32 y, INT32 width, INT32 height,
374 UINT32 bgcolor, UINT32 fgcolor, BOOL fOpRedundant)
378 if (!context || !context->gdi)
383 if (!gdi->drawing || !gdi->drawing->hdc)
388 if (!gdi_decode_color(gdi, bgcolor, &bgcolor, NULL))
391 if (!gdi_decode_color(gdi, fgcolor, &fgcolor, NULL))
394 gdi_SetClipRgn(gdi->drawing->hdc, x, y, width, height);
395 gdi_SetTextColor(gdi->drawing->hdc, bgcolor);
396 gdi_SetBkColor(gdi->drawing->hdc, fgcolor);
401 HGDI_BRUSH brush = gdi_CreateSolidBrush(fgcolor);
412 rect.right = x + width - 1;
413 rect.bottom = y + height - 1;
415 if ((x + width > rect.left) && (y + height > rect.top))
416 gdi_FillRect(gdi->drawing->hdc, &rect, brush);
421 return gdi_SetNullClipRgn(gdi->drawing->hdc);
427 static BOOL gdi_Glyph_EndDraw(rdpContext* context, INT32 x, INT32 y, INT32 width, INT32 height,
428 UINT32 bgcolor, UINT32 fgcolor)
432 if (!context || !context->gdi)
437 if (!gdi->drawing || !gdi->drawing->hdc)
440 gdi_SetNullClipRgn(gdi->drawing->hdc);
445 BOOL gdi_register_graphics(rdpGraphics* graphics)
447 rdpBitmap bitmap = { 0 };
448 rdpGlyph glyph = { 0 };
449 bitmap.size =
sizeof(gdiBitmap);
450 bitmap.New = gdi_Bitmap_New;
451 bitmap.Free = gdi_Bitmap_Free;
452 bitmap.Paint = gdi_Bitmap_Paint;
453 bitmap.Decompress = gdi_Bitmap_Decompress;
454 bitmap.SetSurface = gdi_Bitmap_SetSurface;
455 graphics_register_bitmap(graphics, &bitmap);
456 glyph.size =
sizeof(gdiGlyph);
457 glyph.New = gdi_Glyph_New;
458 glyph.Free = gdi_Glyph_Free;
459 glyph.Draw = gdi_Glyph_Draw;
460 glyph.BeginDraw = gdi_Glyph_BeginDraw;
461 glyph.EndDraw = gdi_Glyph_EndDraw;
462 graphics_register_glyph(graphics, &glyph);
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.