22#include <freerdp/config.h> 
   28#include <freerdp/api.h> 
   29#include <freerdp/freerdp.h> 
   30#include <freerdp/gdi/gdi.h> 
   31#include <freerdp/codec/color.h> 
   33#include <freerdp/gdi/region.h> 
   34#include <freerdp/gdi/bitmap.h> 
   35#include <freerdp/log.h> 
   36#include <freerdp/gdi/shape.h> 
   40#include "../gdi/gdi.h" 
   42#define TAG FREERDP_TAG("gdi.bitmap") 
   52UINT32 gdi_GetPixel(
HGDI_DC hdc, UINT32 nXPos, UINT32 nYPos)
 
   56      &(hBmp->data[(nYPos * hBmp->scanline) + nXPos * FreeRDPGetBytesPerPixel(hBmp->format)]);
 
   57  return FreeRDPReadColor(data, hBmp->format);
 
   60BYTE* gdi_GetPointer(
HGDI_BITMAP hBmp, UINT32 X, UINT32 Y)
 
   62  UINT32 bpp = FreeRDPGetBytesPerPixel(hBmp->format);
 
   63  return &hBmp->data[(Y * WINPR_ASSERTING_INT_CAST(uint32_t, hBmp->width) * bpp) + X * bpp];
 
   76static inline UINT32 gdi_SetPixelBmp(
HGDI_BITMAP hBmp, UINT32 X, UINT32 Y, UINT32 crColor)
 
   78  BYTE* p = &hBmp->data[(Y * hBmp->scanline) + X * FreeRDPGetBytesPerPixel(hBmp->format)];
 
   79  FreeRDPWriteColor(p, hBmp->format, crColor);
 
   83UINT32 gdi_SetPixel(
HGDI_DC hdc, UINT32 X, UINT32 Y, UINT32 crColor)
 
   86  return gdi_SetPixelBmp(hBmp, X, Y, crColor);
 
   99HGDI_BITMAP gdi_CreateBitmap(UINT32 nWidth, UINT32 nHeight, UINT32 format, BYTE* data)
 
  101  return gdi_CreateBitmapEx(nWidth, nHeight, format, 0, data, winpr_aligned_free);
 
  115HGDI_BITMAP gdi_CreateBitmapEx(UINT32 nWidth, UINT32 nHeight, UINT32 format, UINT32 stride,
 
  116                               BYTE* data, 
void (*fkt_free)(
void*))
 
  123  hBitmap->objectType = GDIOBJECT_BITMAP;
 
  124  hBitmap->format = format;
 
  127    hBitmap->scanline = stride;
 
  129    hBitmap->scanline = nWidth * FreeRDPGetBytesPerPixel(hBitmap->format);
 
  131  hBitmap->width = WINPR_ASSERTING_INT_CAST(
int, nWidth);
 
  132  hBitmap->height = WINPR_ASSERTING_INT_CAST(
int, nHeight);
 
  133  hBitmap->data = data;
 
  134  hBitmap->free = fkt_free;
 
  156  hBitmap->objectType = GDIOBJECT_BITMAP;
 
  157  hBitmap->format = hdc->format;
 
  158  WINPR_ASSERT(nWidth <= INT32_MAX);
 
  159  hBitmap->width = (INT32)nWidth;
 
  161  WINPR_ASSERT(nHeight <= INT32_MAX);
 
  162  hBitmap->height = (INT32)nHeight;
 
  164  size_t size = 1ull * nWidth * nHeight * FreeRDPGetBytesPerPixel(hBitmap->format);
 
  165  hBitmap->data = winpr_aligned_malloc(size, 16);
 
  166  hBitmap->free = winpr_aligned_free;
 
  175  memset(hBitmap->data, 0xff, size);
 
  176  hBitmap->scanline = nWidth * FreeRDPGetBytesPerPixel(hBitmap->format);
 
  180static BOOL op_not(UINT32* stack, 
const UINT32* stackp)
 
  182  if (!stack || !stackp)
 
  188  stack[(*stackp) - 1] = ~stack[(*stackp) - 1];
 
  192static BOOL op_and(UINT32* stack, UINT32* stackp)
 
  194  if (!stack || !stackp)
 
  201  stack[(*stackp) - 1] &= stack[(*stackp)];
 
  205static BOOL op_or(UINT32* stack, UINT32* stackp)
 
  207  if (!stack || !stackp)
 
  214  stack[(*stackp) - 1] |= stack[(*stackp)];
 
  218static BOOL op_xor(UINT32* stack, UINT32* stackp)
 
  220  if (!stack || !stackp)
 
  227  stack[(*stackp) - 1] ^= stack[(*stackp)];
 
  231static UINT32 process_rop(UINT32 src, UINT32 dst, UINT32 pat, 
const char* rop, UINT32 format)
 
  233  UINT32 stack[10] = { 0 };
 
  243        stack[stackp++] = FreeRDPGetColor(format, 0, 0, 0, 0xFF);
 
  247        stack[stackp++] = FreeRDPGetColor(format, 0xFF, 0xFF, 0xFF, 0xFF);
 
  251        stack[stackp++] = dst;
 
  255        stack[stackp++] = src;
 
  259        stack[stackp++] = pat;
 
  263        op_xor(stack, &stackp);
 
  267        op_and(stack, &stackp);
 
  271        op_or(stack, &stackp);
 
  275        op_not(stack, &stackp);
 
  286static inline BOOL BitBlt_write(
HGDI_DC hdcDest, 
HGDI_DC hdcSrc, INT32 nXDest, INT32 nYDest,
 
  287                                INT32 nXSrc, INT32 nYSrc, INT32 x, INT32 y, BOOL useSrc,
 
  288                                BOOL usePat, UINT32 style, 
const char* rop,
 
  289                                const gdiPalette* palette)
 
  295  const INT32 dstX = nXDest + x;
 
  296  const INT32 dstY = nYDest + y;
 
  297  BYTE* dstp = gdi_get_bitmap_pointer(hdcDest, dstX, dstY);
 
  301    WLog_ERR(TAG, 
"dstp=%p", (
const void*)dstp);
 
  305  colorA = FreeRDPReadColor(dstp, hdcDest->format);
 
  309    const BYTE* srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc + x, nYSrc + y);
 
  313      WLog_ERR(TAG, 
"srcp=%p", (
const void*)srcp);
 
  317    colorC = FreeRDPReadColor(srcp, hdcSrc->format);
 
  318    colorC = FreeRDPConvertColor(colorC, hdcSrc->format, hdcDest->format, palette);
 
  326        colorB = hdcDest->brush->color;
 
  333            gdi_get_brush_pointer(hdcDest, WINPR_ASSERTING_INT_CAST(uint32_t, nXDest + x),
 
  334                                  WINPR_ASSERTING_INT_CAST(uint32_t, nYDest + y));
 
  338          WLog_ERR(TAG, 
"patp=%p", (
const void*)patp);
 
  342        colorB = FreeRDPReadColor(patp, hdcDest->format);
 
  351  dstColor = process_rop(colorC, colorA, colorB, rop, hdcDest->format);
 
  352  return FreeRDPWriteColor(dstp, hdcDest->format, dstColor);
 
  355static BOOL adjust_src_coordinates(
HGDI_DC hdcSrc, INT32 nWidth, INT32 nHeight, INT32* px,
 
  362  if (!hdcSrc || (nWidth < 0) || (nHeight < 0) || !px || !py)
 
  375    nHeight = nHeight + nYSrc;
 
  381    nWidth = nWidth + nXSrc;
 
  384  if (hSrcBmp->width < (nXSrc + nWidth))
 
  385    nXSrc = hSrcBmp->width - nWidth;
 
  387  if (hSrcBmp->height < (nYSrc + nHeight))
 
  388    nYSrc = hSrcBmp->height - nHeight;
 
  390  if ((nXSrc < 0) || (nYSrc < 0))
 
  398static BOOL adjust_src_dst_coordinates(
HGDI_DC hdcDest, INT32* pnXSrc, INT32* pnYSrc, INT32* pnXDst,
 
  399                                       INT32* pnYDst, INT32* pnWidth, INT32* pnHeight)
 
  402  volatile INT32 diffX = 0;
 
  403  volatile INT32 diffY = 0;
 
  404  volatile INT32 nXSrc = 0;
 
  405  volatile INT32 nYSrc = 0;
 
  406  volatile INT32 nXDst = 0;
 
  407  volatile INT32 nYDst = 0;
 
  408  volatile INT32 nWidth = 0;
 
  409  volatile INT32 nHeight = 0;
 
  411  if (!hdcDest || !pnXSrc || !pnYSrc || !pnXDst || !pnYDst || !pnWidth || !pnHeight)
 
  439  diffX = hDstBmp->width - nXDst - nWidth;
 
  444  diffY = hDstBmp->height - nYDst - nHeight;
 
  449  if ((nXDst < 0) || (nYDst < 0) || (nWidth < 0) || (nHeight < 0))
 
  466static BOOL BitBlt_process(
HGDI_DC hdcDest, INT32 nXDest, INT32 nYDest, INT32 nWidth, INT32 nHeight,
 
  467                           HGDI_DC hdcSrc, INT32 nXSrc, INT32 nYSrc, 
const char* rop,
 
  468                           const gdiPalette* palette)
 
  473  const char* iter = rop;
 
  475  while (*iter != 
'\0')
 
  495  if (!adjust_src_dst_coordinates(hdcDest, &nXSrc, &nYSrc, &nXDest, &nYDest, &nWidth, &nHeight))
 
  498  if (useSrc && !hdcSrc)
 
  503    if (!adjust_src_coordinates(hdcSrc, nWidth, nHeight, &nXSrc, &nYSrc))
 
  509    style = gdi_GetBrushStyle(hdcDest);
 
  519        WLog_ERR(TAG, 
"Invalid brush!!");
 
  524  if ((nXDest > nXSrc) && (nYDest > nYSrc))
 
  526    for (INT32 y = nHeight - 1; y >= 0; y--)
 
  528      for (INT32 x = nWidth - 1; x >= 0; x--)
 
  530        if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest, nXSrc, nYSrc, x, y, useSrc,
 
  531                          usePat, style, rop, palette))
 
  536  else if (nXDest > nXSrc)
 
  538    for (INT32 y = 0; y < nHeight; y++)
 
  540      for (INT32 x = nWidth - 1; x >= 0; x--)
 
  542        if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest, nXSrc, nYSrc, x, y, useSrc,
 
  543                          usePat, style, rop, palette))
 
  548  else if (nYDest > nYSrc)
 
  550    for (INT32 y = nHeight - 1; y >= 0; y--)
 
  552      for (INT32 x = 0; x < nWidth; x++)
 
  554        if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest, nXSrc, nYSrc, x, y, useSrc,
 
  555                          usePat, style, rop, palette))
 
  562    for (INT32 y = 0; y < nHeight; y++)
 
  564      for (INT32 x = 0; x < nWidth; x++)
 
  566        if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest, nXSrc, nYSrc, x, y, useSrc,
 
  567                          usePat, style, rop, palette))
 
  591BOOL gdi_BitBlt(
HGDI_DC hdcDest, INT32 nXDest, INT32 nYDest, INT32 nWidth, INT32 nHeight,
 
  592                HGDI_DC hdcSrc, INT32 nXSrc, INT32 nYSrc, DWORD rop, 
const gdiPalette* palette)
 
  600  if (!gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, &nXSrc, &nYSrc))
 
  615      if (!adjust_src_dst_coordinates(hdcDest, &nXSrc, &nYSrc, &nXDest, &nYDest, &nWidth,
 
  619      if (!adjust_src_coordinates(hdcSrc, nWidth, nHeight, &nXSrc, &nYSrc))
 
  625      if (!hSrcBmp || !hDstBmp)
 
  628      if (!freerdp_image_copy(
 
  629              hDstBmp->data, hDstBmp->format, hDstBmp->scanline,
 
  630              WINPR_ASSERTING_INT_CAST(UINT32, nXDest),
 
  631              WINPR_ASSERTING_INT_CAST(UINT32, nYDest),
 
  632              WINPR_ASSERTING_INT_CAST(UINT32, nWidth),
 
  633              WINPR_ASSERTING_INT_CAST(UINT32, nHeight), hSrcBmp->data, hSrcBmp->format,
 
  634              hSrcBmp->scanline, WINPR_ASSERTING_INT_CAST(UINT32, nXSrc),
 
  635              WINPR_ASSERTING_INT_CAST(UINT32, nYSrc), palette, FREERDP_FLIP_NONE))
 
  644      if (!adjust_src_dst_coordinates(hdcDest, &nXSrc, &nYSrc, &nXDest, &nYDest, &nWidth,
 
  648      if (!adjust_src_coordinates(hdcDest, nWidth, nHeight, &nXSrc, &nYSrc))
 
  651      if (!hSrcBmp || !hDstBmp)
 
  654      if (!freerdp_image_copy(
 
  655              hDstBmp->data, hDstBmp->format, hDstBmp->scanline,
 
  656              WINPR_ASSERTING_INT_CAST(UINT32, nXDest),
 
  657              WINPR_ASSERTING_INT_CAST(UINT32, nYDest),
 
  658              WINPR_ASSERTING_INT_CAST(UINT32, nWidth),
 
  659              WINPR_ASSERTING_INT_CAST(UINT32, nHeight), hSrcBmp->data, hSrcBmp->format,
 
  660              hSrcBmp->scanline, WINPR_ASSERTING_INT_CAST(UINT32, nXSrc),
 
  661              WINPR_ASSERTING_INT_CAST(UINT32, nYSrc), palette, FREERDP_FLIP_NONE))
 
  667      if (!BitBlt_process(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc,
 
  668                          gdi_rop_to_string(rop), palette))
 
  674  if (!gdi_InvalidateRegion(hdcDest, nXDest, nYDest, nWidth, nHeight))