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")
52 UINT32 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);
60 BYTE* 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];
76 static 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);
83 UINT32 gdi_SetPixel(
HGDI_DC hdc, UINT32 X, UINT32 Y, UINT32 crColor)
86 return gdi_SetPixelBmp(hBmp, X, Y, crColor);
99 HGDI_BITMAP gdi_CreateBitmap(UINT32 nWidth, UINT32 nHeight, UINT32 format, BYTE* data)
101 return gdi_CreateBitmapEx(nWidth, nHeight, format, 0, data, winpr_aligned_free);
115 HGDI_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);
180 static BOOL op_not(UINT32* stack,
const UINT32* stackp)
182 if (!stack || !stackp)
188 stack[(*stackp) - 1] = ~stack[(*stackp) - 1];
192 static BOOL op_and(UINT32* stack, UINT32* stackp)
194 if (!stack || !stackp)
201 stack[(*stackp) - 1] &= stack[(*stackp)];
205 static BOOL op_or(UINT32* stack, UINT32* stackp)
207 if (!stack || !stackp)
214 stack[(*stackp) - 1] |= stack[(*stackp)];
218 static BOOL op_xor(UINT32* stack, UINT32* stackp)
220 if (!stack || !stackp)
227 stack[(*stackp) - 1] ^= stack[(*stackp)];
231 static 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);
286 static 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);
355 static 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))
398 static 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))
466 static 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))
591 BOOL 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))