22#include <freerdp/config.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") 
   41HGDI_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);
 
   74static 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);
 
  106static void gdi_Bitmap_Free(WINPR_ATTR_UNUSED rdpContext* context, rdpBitmap* bitmap)
 
  117    winpr_aligned_free(bitmap->data);
 
  123static 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);
 
  134static 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);
 
  167          rfx_process_message(context->codecs->rfx, pSrcData, SrcSize, bitmap->left,
 
  168                              bitmap->top, bitmap->data, bitmap->format, gdi->stride,
 
  169                              WINPR_ASSERTING_INT_CAST(UINT32, gdi->height), &invalidRegion);
 
  170      region16_uninit(&invalidRegion);
 
  174        WLog_ERR(TAG, 
"rfx_process_message failed");
 
  178    else if (codecId == RDP_CODEC_ID_NSCODEC)
 
  180      const int status = nsc_process_message(
 
  181          context->codecs->nsc, 32, DstWidth, DstHeight, pSrcData, SrcSize, bitmap->data,
 
  182          bitmap->format, 0, 0, 0, DstWidth, DstHeight, FREERDP_FLIP_VERTICAL);
 
  186        WLog_ERR(TAG, 
"nsc_process_message failed");
 
  190      return freerdp_image_copy_no_overlap(bitmap->data, bitmap->format, 0, 0, 0, DstWidth,
 
  191                                           DstHeight, pSrcData, PIXEL_FORMAT_XRGB32, 0, 0, 0,
 
  192                                           &gdi->palette, FREERDP_FLIP_VERTICAL);
 
  196      if (!interleaved_decompress(context->codecs->interleaved, pSrcData, SrcSize, DstWidth,
 
  197                                  DstHeight, bpp, bitmap->data, bitmap->format, 0, 0, 0,
 
  198                                  DstWidth, DstHeight, &gdi->palette))
 
  200        WLog_ERR(TAG, 
"interleaved_decompress failed");
 
  206      const BOOL fidelity =
 
  208      freerdp_planar_switch_bgr(context->codecs->planar, fidelity);
 
  209      if (!freerdp_bitmap_decompress_planar(context->codecs->planar, pSrcData, SrcSize,
 
  210                                            DstWidth, DstHeight, bitmap->data, bitmap->format,
 
  211                                            0, 0, 0, DstWidth, DstHeight, TRUE))
 
  213        WLog_ERR(TAG, 
"freerdp_bitmap_decompress_planar failed");
 
  220    const UINT32 SrcFormat = gdi_get_pixel_format(bpp);
 
  221    const size_t sbpp = FreeRDPGetBytesPerPixel(SrcFormat);
 
  222    const size_t dbpp = FreeRDPGetBytesPerPixel(bitmap->format);
 
  224    if ((sbpp == 0) || (dbpp == 0))
 
  228      const size_t dstSize = SrcSize * dbpp / sbpp;
 
  230      if (dstSize < bitmap->length)
 
  232        WLog_ERR(TAG, 
"dstSize %" PRIuz 
" < bitmap->length %" PRIu32, dstSize,
 
  238    if (!freerdp_image_copy_no_overlap(bitmap->data, bitmap->format, 0, 0, 0, DstWidth,
 
  239                                       DstHeight, pSrcData, SrcFormat, 0, 0, 0, &gdi->palette,
 
  240                                       FREERDP_FLIP_VERTICAL))
 
  242      WLog_ERR(TAG, 
"freerdp_image_copy failed");
 
  250static BOOL gdi_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary)
 
  263    gdi->drawing = gdi->primary;
 
  265    gdi->drawing = (gdiBitmap*)bitmap;
 
  271static BOOL gdi_Glyph_New(rdpContext* context, rdpGlyph* glyph)
 
  276  if (!context || !glyph)
 
  285  gdi_glyph->hdc->format = PIXEL_FORMAT_MONO;
 
  286  data = freerdp_glyph_convert(glyph->cx, glyph->cy, glyph->aj);
 
  294  gdi_glyph->bitmap = gdi_CreateBitmap(glyph->cx, glyph->cy, PIXEL_FORMAT_MONO, data);
 
  299    winpr_aligned_free(data);
 
  308static void gdi_Glyph_Free(WINPR_ATTR_UNUSED rdpContext* context, rdpGlyph* glyph)
 
  323static BOOL gdi_Glyph_Draw(rdpContext* context, 
const rdpGlyph* glyph, INT32 x, INT32 y, INT32 w,
 
  324                           INT32 h, INT32 sx, INT32 sy, BOOL fOpRedundant)
 
  331  if (!context || !glyph)
 
  348      rect.right = x + w - 1;
 
  351      rect.bottom = y + h - 1;
 
  353    if ((rect.left < rect.right) && (rect.top < rect.bottom))
 
  355      brush = gdi_CreateSolidBrush(gdi->drawing->hdc->bkColor);
 
  360      gdi_FillRect(gdi->drawing->hdc, &rect, brush);
 
  365  brush = gdi_CreateSolidBrush(gdi->drawing->hdc->textColor);
 
  370  gdi_SelectObject(gdi->drawing->hdc, (
HGDIOBJECT)brush);
 
  371  rc = gdi_BitBlt(gdi->drawing->hdc, x, y, w, h, 
gdi_glyph->hdc, sx, sy, GDI_GLYPH_ORDER,
 
  372                  &context->gdi->palette);
 
  377static BOOL gdi_Glyph_BeginDraw(rdpContext* context, INT32 x, INT32 y, INT32 width, INT32 height,
 
  378                                UINT32 bgcolor, UINT32 fgcolor, BOOL fOpRedundant)
 
  382  if (!context || !context->gdi)
 
  387  if (!gdi->drawing || !gdi->drawing->hdc)
 
  392    if (!gdi_decode_color(gdi, bgcolor, &bgcolor, NULL))
 
  395    if (!gdi_decode_color(gdi, fgcolor, &fgcolor, NULL))
 
  398    gdi_SetClipRgn(gdi->drawing->hdc, x, y, width, height);
 
  399    gdi_SetTextColor(gdi->drawing->hdc, bgcolor);
 
  400    gdi_SetBkColor(gdi->drawing->hdc, fgcolor);
 
  405      HGDI_BRUSH brush = gdi_CreateSolidBrush(fgcolor);
 
  416      rect.right = x + width - 1;
 
  417      rect.bottom = y + height - 1;
 
  419      if ((x + width > rect.left) && (y + height > rect.top))
 
  420        gdi_FillRect(gdi->drawing->hdc, &rect, brush);
 
  425    return gdi_SetNullClipRgn(gdi->drawing->hdc);
 
  431static BOOL gdi_Glyph_EndDraw(rdpContext* context, WINPR_ATTR_UNUSED INT32 x,
 
  432                              WINPR_ATTR_UNUSED INT32 y, WINPR_ATTR_UNUSED INT32 width,
 
  433                              WINPR_ATTR_UNUSED INT32 height, WINPR_ATTR_UNUSED UINT32 bgcolor,
 
  434                              WINPR_ATTR_UNUSED UINT32 fgcolor)
 
  438  if (!context || !context->gdi)
 
  443  if (!gdi->drawing || !gdi->drawing->hdc)
 
  446  gdi_SetNullClipRgn(gdi->drawing->hdc);
 
  451BOOL gdi_register_graphics(rdpGraphics* graphics)
 
  453  rdpBitmap bitmap = { 0 };
 
  454  rdpGlyph glyph = { 0 };
 
  455  bitmap.size = 
sizeof(gdiBitmap);
 
  456  bitmap.New = gdi_Bitmap_New;
 
  457  bitmap.Free = gdi_Bitmap_Free;
 
  458  bitmap.Paint = gdi_Bitmap_Paint;
 
  459  bitmap.Decompress = gdi_Bitmap_Decompress;
 
  460  bitmap.SetSurface = gdi_Bitmap_SetSurface;
 
  461  graphics_register_bitmap(graphics, &bitmap);
 
  462  glyph.size = 
sizeof(gdiGlyph);
 
  463  glyph.New = gdi_Glyph_New;
 
  464  glyph.Free = gdi_Glyph_Free;
 
  465  glyph.Draw = gdi_Glyph_Draw;
 
  466  glyph.BeginDraw = gdi_Glyph_BeginDraw;
 
  467  glyph.EndDraw = gdi_Glyph_EndDraw;
 
  468  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.