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 * 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 = nWidth;
132 hBitmap->height = 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;
332 const BYTE* patp = gdi_get_brush_pointer(hdcDest, nXDest + x, nYDest + y);
336 WLog_ERR(TAG,
"patp=%p", (
const void*)patp);
340 colorB = FreeRDPReadColor(patp, hdcDest->format);
349 dstColor = process_rop(colorC, colorA, colorB, rop, hdcDest->format);
350 return FreeRDPWriteColor(dstp, hdcDest->format, dstColor);
353 static BOOL adjust_src_coordinates(
HGDI_DC hdcSrc, INT32 nWidth, INT32 nHeight, INT32* px,
360 if (!hdcSrc || (nWidth < 0) || (nHeight < 0) || !px || !py)
373 nHeight = nHeight + nYSrc;
379 nWidth = nWidth + nXSrc;
382 if (hSrcBmp->width < (nXSrc + nWidth))
383 nXSrc = hSrcBmp->width - nWidth;
385 if (hSrcBmp->height < (nYSrc + nHeight))
386 nYSrc = hSrcBmp->height - nHeight;
388 if ((nXSrc < 0) || (nYSrc < 0))
396 static BOOL adjust_src_dst_coordinates(
HGDI_DC hdcDest, INT32* pnXSrc, INT32* pnYSrc, INT32* pnXDst,
397 INT32* pnYDst, INT32* pnWidth, INT32* pnHeight)
400 volatile INT32 diffX = 0;
401 volatile INT32 diffY = 0;
402 volatile INT32 nXSrc = 0;
403 volatile INT32 nYSrc = 0;
404 volatile INT32 nXDst = 0;
405 volatile INT32 nYDst = 0;
406 volatile INT32 nWidth = 0;
407 volatile INT32 nHeight = 0;
409 if (!hdcDest || !pnXSrc || !pnYSrc || !pnXDst || !pnYDst || !pnWidth || !pnHeight)
437 diffX = hDstBmp->width - nXDst - nWidth;
442 diffY = hDstBmp->height - nYDst - nHeight;
447 if ((nXDst < 0) || (nYDst < 0) || (nWidth < 0) || (nHeight < 0))
464 static BOOL BitBlt_process(
HGDI_DC hdcDest, INT32 nXDest, INT32 nYDest, INT32 nWidth, INT32 nHeight,
465 HGDI_DC hdcSrc, INT32 nXSrc, INT32 nYSrc,
const char* rop,
466 const gdiPalette* palette)
471 const char* iter = rop;
473 while (*iter !=
'\0')
493 if (!adjust_src_dst_coordinates(hdcDest, &nXSrc, &nYSrc, &nXDest, &nYDest, &nWidth, &nHeight))
496 if (useSrc && !hdcSrc)
501 if (!adjust_src_coordinates(hdcSrc, nWidth, nHeight, &nXSrc, &nYSrc))
507 style = gdi_GetBrushStyle(hdcDest);
517 WLog_ERR(TAG,
"Invalid brush!!");
522 if ((nXDest > nXSrc) && (nYDest > nYSrc))
524 for (INT32 y = nHeight - 1; y >= 0; y--)
526 for (INT32 x = nWidth - 1; x >= 0; x--)
528 if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest, nXSrc, nYSrc, x, y, useSrc,
529 usePat, style, rop, palette))
534 else if (nXDest > nXSrc)
536 for (INT32 y = 0; y < nHeight; y++)
538 for (INT32 x = nWidth - 1; x >= 0; x--)
540 if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest, nXSrc, nYSrc, x, y, useSrc,
541 usePat, style, rop, palette))
546 else if (nYDest > nYSrc)
548 for (INT32 y = nHeight - 1; y >= 0; y--)
550 for (INT32 x = 0; x < nWidth; x++)
552 if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest, nXSrc, nYSrc, x, y, useSrc,
553 usePat, style, rop, palette))
560 for (INT32 y = 0; y < nHeight; y++)
562 for (INT32 x = 0; x < nWidth; x++)
564 if (!BitBlt_write(hdcDest, hdcSrc, nXDest, nYDest, nXSrc, nYSrc, x, y, useSrc,
565 usePat, style, rop, palette))
589 BOOL gdi_BitBlt(
HGDI_DC hdcDest, INT32 nXDest, INT32 nYDest, INT32 nWidth, INT32 nHeight,
590 HGDI_DC hdcSrc, INT32 nXSrc, INT32 nYSrc, DWORD rop,
const gdiPalette* palette)
598 if (!gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, &nXSrc, &nYSrc))
613 if (!adjust_src_dst_coordinates(hdcDest, &nXSrc, &nYSrc, &nXDest, &nYDest, &nWidth,
617 if (!adjust_src_coordinates(hdcSrc, nWidth, nHeight, &nXSrc, &nYSrc))
623 if (!hSrcBmp || !hDstBmp)
626 if (!freerdp_image_copy(hDstBmp->data, hDstBmp->format, hDstBmp->scanline, nXDest,
627 nYDest, nWidth, nHeight, hSrcBmp->data, hSrcBmp->format,
628 hSrcBmp->scanline, nXSrc, nYSrc, palette, FREERDP_FLIP_NONE))
637 if (!adjust_src_dst_coordinates(hdcDest, &nXSrc, &nYSrc, &nXDest, &nYDest, &nWidth,
641 if (!adjust_src_coordinates(hdcDest, nWidth, nHeight, &nXSrc, &nYSrc))
644 if (!hSrcBmp || !hDstBmp)
647 if (!freerdp_image_copy(hDstBmp->data, hDstBmp->format, hDstBmp->scanline, nXDest,
648 nYDest, nWidth, nHeight, hSrcBmp->data, hSrcBmp->format,
649 hSrcBmp->scanline, nXSrc, nYSrc, palette, FREERDP_FLIP_NONE))
655 if (!BitBlt_process(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc,
656 gdi_rop_to_string(rop), palette))
662 if (!gdi_InvalidateRegion(hdcDest, nXDest, nYDest, nWidth, nHeight))