22#include <freerdp/config.h>
28#include <winpr/wtypes.h>
30#include <freerdp/api.h>
31#include <freerdp/freerdp.h>
32#include <freerdp/gdi/gdi.h>
34#include <freerdp/gdi/region.h>
36#include <freerdp/log.h>
38#define TAG FREERDP_TAG("gdi.region")
40static char* gdi_rect_str(
char* buffer,
size_t size,
const GDI_RECT* rect)
42 if (!buffer || (size < 1) || !rect)
45 (void)_snprintf(buffer, size - 1,
46 "[top/left=%" PRId32
"x%" PRId32
"-bottom/right%" PRId32
"x%" PRId32
"]",
47 rect->top, rect->left, rect->bottom, rect->right);
48 buffer[size - 1] =
'\0';
53static char* gdi_regn_str(
char* buffer,
size_t size,
const GDI_RGN* rgn)
55 if (!buffer || (size < 1) || !rgn)
58 (void)_snprintf(buffer, size - 1,
"[%" PRId32
"x%" PRId32
"-%" PRId32
"x%" PRId32
"]", rgn->x,
59 rgn->y, rgn->w, rgn->h);
60 buffer[size - 1] =
'\0';
77GDI_RGN* gdi_CreateRectRgn(INT32 nLeftRect, INT32 nTopRect, INT32 nRightRect, INT32 nBottomRect)
83 w = nRightRect - nLeftRect + 1ll;
84 h = nBottomRect - nTopRect + 1ll;
85 if ((w < 0) || (h < 0) || (w > INT32_MAX) || (h > INT32_MAX))
88 "Can not create region top/left=%" PRId32
"x%" PRId32
"-bottom/right=%" PRId32
90 nTopRect, nLeftRect, nBottomRect, nRightRect);
98 hRgn->objectType = GDIOBJECT_REGION;
116GDI_RECT* gdi_CreateRect(INT32 xLeft, INT32 yTop, INT32 xRight, INT32 yBottom)
130 hRect->objectType = GDIOBJECT_RECT;
133 hRect->right = xRight;
134 hRect->bottom = yBottom;
149 w = rect->right - rect->left + 1ll;
150 h = rect->bottom - rect->top + 1ll;
152 if ((w < 0) || (h < 0) || (w > INT32_MAX) || (h > INT32_MAX))
155 "Can not create region top/left=%" PRId32
"x%" PRId32
"-bottom/right=%" PRId32
157 rect->top, rect->left, rect->bottom, rect->right);
180BOOL gdi_CRectToRgn(INT32 left, INT32 top, INT32 right, INT32 bottom,
GDI_RGN* rgn)
185 w = right - left + 1ll;
186 h = bottom - top + 1ll;
191 if ((w < 0) || (h < 0) || (w > INT32_MAX) || (h > INT32_MAX))
194 "Can not create region top/left=%" PRId32
"x%" PRId32
"-bottom/right=%" PRId32
196 top, left, bottom, right);
218BOOL gdi_RectToCRgn(
const GDI_RECT* rect, INT32* x, INT32* y, INT32* w, INT32* h)
223 INT64 tmp = rect->right - rect->left + 1;
224 if ((tmp < 0) || (tmp > INT32_MAX))
227 WLog_ERR(TAG,
"rectangle invalid %s", gdi_rect_str(buffer,
sizeof(buffer), rect));
233 tmp = rect->bottom - rect->top + 1;
234 if ((tmp < 0) || (tmp > INT32_MAX))
237 WLog_ERR(TAG,
"rectangle invalid %s", gdi_rect_str(buffer,
sizeof(buffer), rect));
258BOOL gdi_CRectToCRgn(INT32 left, INT32 top, INT32 right, INT32 bottom, INT32* x, INT32* y, INT32* w,
264 wl = right - left + 1ll;
265 hl = bottom - top + 1ll;
267 if ((left > right) || (top > bottom) || (wl <= 0) || (hl <= 0) || (wl > INT32_MAX) ||
271 "Can not create region top/left=%" PRId32
"x%" PRId32
"-bottom/right=%" PRId32
273 top, left, bottom, right);
297 r = rgn->x + rgn->w - 1ll;
298 b = rgn->y + rgn->h - 1ll;
300 if ((r < INT32_MIN) || (r > INT32_MAX) || (b < INT32_MIN) || (b > INT32_MAX))
303 WLog_ERR(TAG,
"Can not create region %s", gdi_regn_str(buffer,
sizeof(buffer), rgn));
310 rect->right = (INT32)r;
311 rect->bottom = (INT32)b;
325BOOL gdi_CRgnToRect(INT64 x, INT64 y, INT32 w, INT32 h,
GDI_RECT* rect)
327 BOOL invalid = FALSE;
328 const INT64 r = x + w - 1;
329 const INT64 b = y + h - 1;
330 WINPR_ASSERT(x <= INT32_MAX);
331 WINPR_ASSERT(y <= INT32_MAX);
332 WINPR_ASSERT(r <= INT32_MAX);
333 WINPR_ASSERT(b <= INT32_MAX);
334 rect->left = (x > 0) ? (INT32)x : 0;
335 rect->top = (y > 0) ? (INT32)y : 0;
336 rect->right = rect->left;
337 rect->bottom = rect->top;
339 if ((w <= 0) || (h <= 0))
343 rect->right = (INT32)r;
348 rect->bottom = (INT32)b;
354 WLog_DBG(TAG,
"Invisible rectangle %" PRId64
"x%" PRId64
"-%" PRId64
"x%" PRId64, x, y, r,
371BOOL gdi_RgnToCRect(
const GDI_RGN* rgn, INT32* left, INT32* top, INT32* right, INT32* bottom)
376 if ((rgn->w < 0) || (rgn->h < 0))
379 WLog_ERR(TAG,
"Can not create region %s", gdi_regn_str(buffer,
sizeof(buffer), rgn));
385 *right = rgn->x + rgn->w - 1;
386 *bottom = rgn->y + rgn->h - 1;
403BOOL gdi_CRgnToCRect(INT32 x, INT32 y, INT32 w, INT32 h, INT32* left, INT32* top, INT32* right,
415 WLog_ERR(TAG,
"Invalid width");
425 WLog_ERR(TAG,
"Invalid height");
443INLINE BOOL gdi_CopyOverlap(INT32 x, INT32 y, INT32 width, INT32 height, INT32 srcx, INT32 srcy)
447 gdi_CRgnToRect(x, y, width, height, &dst);
448 gdi_CRgnToRect(srcx, srcy, width, height, &src);
450 if (dst.right < src.left)
452 if (dst.left > src.right)
454 if (dst.bottom < src.top)
456 if (dst.top > src.bottom)
474INLINE BOOL gdi_SetRect(
GDI_RECT* rc, INT32 xLeft, INT32 yTop, INT32 xRight, INT32 yBottom)
486 rc->bottom = yBottom;
500INLINE BOOL gdi_SetRgn(
GDI_RGN* hRgn, INT32 nXLeft, INT32 nYLeft, INT32 nWidth, INT32 nHeight)
505 if ((nWidth < 0) || (nHeight < 0))
526INLINE BOOL gdi_SetRectRgn(
GDI_RGN* hRgn, INT32 nLeftRect, INT32 nTopRect, INT32 nRightRect,
529 if (!gdi_CRectToRgn(nLeftRect, nTopRect, nRightRect, nBottomRect, hRgn))
544INLINE BOOL gdi_EqualRgn(
const GDI_RGN* hSrcRgn1,
const GDI_RGN* hSrcRgn2)
546 WINPR_ASSERT(hSrcRgn1);
547 WINPR_ASSERT(hSrcRgn2);
548 if ((hSrcRgn1->x == hSrcRgn2->x) && (hSrcRgn1->y == hSrcRgn2->y) &&
549 (hSrcRgn1->w == hSrcRgn2->w) && (hSrcRgn1->h == hSrcRgn2->h))
571 dst->left = src->left;
573 dst->right = src->right;
574 dst->bottom = src->bottom;
587INLINE BOOL gdi_PtInRect(
const GDI_RECT* rc, INT32 x, INT32 y)
593 if ((x >= rc->left) && (x <= rc->right))
595 if ((y >= rc->top) && (y <= rc->bottom))
615INLINE BOOL gdi_InvalidateRegion(
HGDI_DC hdc, INT32 x, INT32 y, INT32 w, INT32 h)
625 if (!hdc->hwnd->invalid)
628 if (w == 0 || h == 0)
631 cinvalid = hdc->hwnd->cinvalid;
633 if ((hdc->hwnd->ninvalid + 1) > (INT64)hdc->hwnd->count)
636 size_t new_cnt = 2ULL * hdc->hwnd->count;
637 if (new_cnt > UINT32_MAX)
645 hdc->hwnd->count = (UINT32)new_cnt;
649 gdi_SetRgn(&cinvalid[hdc->hwnd->ninvalid++], x, y, w, h);
650 hdc->hwnd->cinvalid = cinvalid;
651 invalid = hdc->hwnd->invalid;
659 invalid->null = FALSE;
663 gdi_CRgnToRect(x, y, w, h, &rgn);
664 gdi_RgnToRect(invalid, &inv);
666 if (rgn.left < inv.left)
669 if (rgn.top < inv.top)
672 if (rgn.right > inv.right)
673 inv.right = rgn.right;
675 if (rgn.bottom > inv.bottom)
676 inv.bottom = rgn.bottom;
678 gdi_RectToRgn(&inv, invalid);