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);
166 winpr_aligned_calloc(1ull * nWidth * FreeRDPGetBytesPerPixel(hBitmap->format), nHeight, 16);
167 hBitmap->free = winpr_aligned_free;
176 memset(hBitmap->data, 0xff, size);
177 hBitmap->scanline = nWidth * FreeRDPGetBytesPerPixel(hBitmap->format);
181static BOOL op_not(UINT32* stack,
const UINT32* stackp)
183 if (!stack || !stackp)
189 stack[(*stackp) - 1] = ~stack[(*stackp) - 1];
193static BOOL op_and(UINT32* stack, UINT32* stackp)
195 if (!stack || !stackp)
202 stack[(*stackp) - 1] &= stack[(*stackp)];
206static BOOL op_or(UINT32* stack, UINT32* stackp)
208 if (!stack || !stackp)
215 stack[(*stackp) - 1] |= stack[(*stackp)];
219static BOOL op_xor(UINT32* stack, UINT32* stackp)
221 if (!stack || !stackp)
228 stack[(*stackp) - 1] ^= stack[(*stackp)];
232static UINT32 process_rop(UINT32 src, UINT32 dst, UINT32 pat,
const char* rop, UINT32 format)
234 UINT32 stack[10] = WINPR_C_ARRAY_INIT;
244 stack[stackp++] = FreeRDPGetColor(format, 0, 0, 0, 0xFF);
248 stack[stackp++] = FreeRDPGetColor(format, 0xFF, 0xFF, 0xFF, 0xFF);
252 stack[stackp++] = dst;
256 stack[stackp++] = src;
260 stack[stackp++] = pat;
264 op_xor(stack, &stackp);
268 op_and(stack, &stackp);
272 op_or(stack, &stackp);
276 op_not(stack, &stackp);
287static inline BOOL BitBlt_write(
HGDI_DC hdcDest,
HGDI_DC hdcSrc, INT32 nXDest, INT32 nYDest,
288 INT32 nXSrc, INT32 nYSrc, INT32 x, INT32 y, BOOL useSrc,
289 BOOL usePat, UINT32 style,
const char* rop,
290 const gdiPalette* palette)
296 const INT32 dstX = nXDest + x;
297 const INT32 dstY = nYDest + y;
298 BYTE* dstp = gdi_get_bitmap_pointer(hdcDest, dstX, dstY);
302 WLog_ERR(TAG,
"dstp=%p", (
const void*)dstp);
306 colorA = FreeRDPReadColor(dstp, hdcDest->format);
310 const BYTE* srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc + x, nYSrc + y);
314 WLog_ERR(TAG,
"srcp=%p", (
const void*)srcp);
318 colorC = FreeRDPReadColor(srcp, hdcSrc->format);
319 colorC = FreeRDPConvertColor(colorC, hdcSrc->format, hdcDest->format, palette);
327 colorB = hdcDest->brush->color;
334 gdi_get_brush_pointer(hdcDest, WINPR_ASSERTING_INT_CAST(uint32_t, nXDest + x),
335 WINPR_ASSERTING_INT_CAST(uint32_t, nYDest + y));
339 WLog_ERR(TAG,
"patp=%p", (
const void*)patp);
343 colorB = FreeRDPReadColor(patp, hdcDest->format);
352 dstColor = process_rop(colorC, colorA, colorB, rop, hdcDest->format);
353 return FreeRDPWriteColor(dstp, hdcDest->format, dstColor);
356static BOOL adjust_src_coordinates(
HGDI_DC hdcSrc, INT32 nWidth, INT32 nHeight, INT32* px,
363 if (!hdcSrc || (nWidth < 0) || (nHeight < 0) || !px || !py)
366 hSrcBmp = WINPR_PACKED_ALIGN_CAST(
HGDI_BITMAP, hdcSrc->selectedObject);
376 nHeight = nHeight + nYSrc;
382 nWidth = nWidth + nXSrc;
385 if (hSrcBmp->width < (nXSrc + nWidth))
386 nXSrc = hSrcBmp->width - nWidth;
388 if (hSrcBmp->height < (nYSrc + nHeight))
389 nYSrc = hSrcBmp->height - nHeight;
391 if ((nXSrc < 0) || (nYSrc < 0))
399static BOOL adjust_src_dst_coordinates(
HGDI_DC hdcDest, INT32* pnXSrc, INT32* pnYSrc, INT32* pnXDst,
400 INT32* pnYDst, INT32* pnWidth, INT32* pnHeight)
403 volatile INT32 diffX = 0;
404 volatile INT32 diffY = 0;
405 volatile INT32 nXSrc = 0;
406 volatile INT32 nYSrc = 0;
407 volatile INT32 nXDst = 0;
408 volatile INT32 nYDst = 0;
409 volatile INT32 nWidth = 0;
410 volatile INT32 nHeight = 0;
412 if (!hdcDest || !pnXSrc || !pnYSrc || !pnXDst || !pnYDst || !pnWidth || !pnHeight)
415 hDstBmp = WINPR_PACKED_ALIGN_CAST(
HGDI_BITMAP, hdcDest->selectedObject);
440 diffX = hDstBmp->width - nXDst - nWidth;
445 diffY = hDstBmp->height - nYDst - nHeight;
450 if ((nXDst < 0) || (nYDst < 0) || (nWidth < 0) || (nHeight < 0))
467static BOOL BitBlt_process(
HGDI_DC hdcDest, INT32 nXDest, INT32 nYDest, INT32 nWidth, INT32 nHeight,
468 HGDI_DC hdcSrc, INT32 nXSrc, INT32 nYSrc,
const char* rop,
469 const gdiPalette* palette)
474 const char* iter = rop;
476 while (*iter !=
'\0')
496 if (!adjust_src_dst_coordinates(hdcDest, &nXSrc, &nYSrc, &nXDest, &nYDest, &nWidth, &nHeight))
499 if (useSrc && !hdcSrc)
504 if (!adjust_src_coordinates(hdcSrc, nWidth, nHeight, &nXSrc, &nYSrc))
510 style = gdi_GetBrushStyle(hdcDest);
520 WLog_ERR(TAG,
"Invalid brush!!");
525 if ((nXDest > nXSrc) && (nYDest > nYSrc))
527 for (INT32 y = nHeight - 1; y >= 0; y--)
529 for (INT32 x = nWidth - 1; x >= 0; x--)
531 if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest, nXSrc, nYSrc, x, y, useSrc,
532 usePat, style, rop, palette))
537 else if (nXDest > nXSrc)
539 for (INT32 y = 0; y < nHeight; y++)
541 for (INT32 x = nWidth - 1; x >= 0; x--)
543 if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest, nXSrc, nYSrc, x, y, useSrc,
544 usePat, style, rop, palette))
549 else if (nYDest > nYSrc)
551 for (INT32 y = nHeight - 1; y >= 0; y--)
553 for (INT32 x = 0; x < nWidth; x++)
555 if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest, nXSrc, nYSrc, x, y, useSrc,
556 usePat, style, rop, palette))
563 for (INT32 y = 0; y < nHeight; y++)
565 for (INT32 x = 0; x < nWidth; x++)
567 if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest, nXSrc, nYSrc, x, y, useSrc,
568 usePat, style, rop, palette))
592BOOL gdi_BitBlt(
HGDI_DC hdcDest, INT32 nXDest, INT32 nYDest, INT32 nWidth, INT32 nHeight,
593 HGDI_DC hdcSrc, INT32 nXSrc, INT32 nYSrc, DWORD rop,
const gdiPalette* palette)
601 if (!gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, &nXSrc, &nYSrc))
616 if (!adjust_src_dst_coordinates(hdcDest, &nXSrc, &nYSrc, &nXDest, &nYDest, &nWidth,
620 if (!adjust_src_coordinates(hdcSrc, nWidth, nHeight, &nXSrc, &nYSrc))
623 hSrcBmp = WINPR_PACKED_ALIGN_CAST(
HGDI_BITMAP, hdcSrc->selectedObject);
624 hDstBmp = WINPR_PACKED_ALIGN_CAST(
HGDI_BITMAP, hdcDest->selectedObject);
626 if (!hSrcBmp || !hDstBmp)
629 if (!freerdp_image_copy(
630 hDstBmp->data, hDstBmp->format, hDstBmp->scanline,
631 WINPR_ASSERTING_INT_CAST(UINT32, nXDest),
632 WINPR_ASSERTING_INT_CAST(UINT32, nYDest),
633 WINPR_ASSERTING_INT_CAST(UINT32, nWidth),
634 WINPR_ASSERTING_INT_CAST(UINT32, nHeight), hSrcBmp->data, hSrcBmp->format,
635 hSrcBmp->scanline, WINPR_ASSERTING_INT_CAST(UINT32, nXSrc),
636 WINPR_ASSERTING_INT_CAST(UINT32, nYSrc), palette, FREERDP_FLIP_NONE))
642 hSrcBmp = WINPR_PACKED_ALIGN_CAST(
HGDI_BITMAP, hdcDest->selectedObject);
643 hDstBmp = WINPR_PACKED_ALIGN_CAST(
HGDI_BITMAP, hdcDest->selectedObject);
645 if (!adjust_src_dst_coordinates(hdcDest, &nXSrc, &nYSrc, &nXDest, &nYDest, &nWidth,
649 if (!adjust_src_coordinates(hdcDest, nWidth, nHeight, &nXSrc, &nYSrc))
652 if (!hSrcBmp || !hDstBmp)
655 if (!freerdp_image_copy(
656 hDstBmp->data, hDstBmp->format, hDstBmp->scanline,
657 WINPR_ASSERTING_INT_CAST(UINT32, nXDest),
658 WINPR_ASSERTING_INT_CAST(UINT32, nYDest),
659 WINPR_ASSERTING_INT_CAST(UINT32, nWidth),
660 WINPR_ASSERTING_INT_CAST(UINT32, nHeight), hSrcBmp->data, hSrcBmp->format,
661 hSrcBmp->scanline, WINPR_ASSERTING_INT_CAST(UINT32, nXSrc),
662 WINPR_ASSERTING_INT_CAST(UINT32, nYSrc), palette, FREERDP_FLIP_NONE))
668 if (!BitBlt_process(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc,
669 gdi_rop_to_string(rop), palette))
675 return gdi_InvalidateRegion(hdcDest, nXDest, nYDest, nWidth, nHeight);