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;
150 INT64 w = rect->right - rect->left + 1ll;
151 INT64 h = rect->bottom - rect->top + 1ll;
153 if ((w < 0) || (h < 0) || (w > INT32_MAX) || (h > INT32_MAX))
156 "Can not create region top/left=%" PRId32
"x%" PRId32
"-bottom/right=%" PRId32
158 rect->top, rect->left, rect->bottom, rect->right);
181BOOL gdi_CRectToRgn(INT32 left, INT32 top, INT32 right, INT32 bottom,
GDI_RGN* rgn)
186 w = right - left + 1ll;
187 h = bottom - top + 1ll;
192 if ((w < 0) || (h < 0) || (w > INT32_MAX) || (h > INT32_MAX))
195 "Can not create region top/left=%" PRId32
"x%" PRId32
"-bottom/right=%" PRId32
197 top, left, bottom, right);
219BOOL gdi_RectToCRgn(
const GDI_RECT* rect, INT32* x, INT32* y, INT32* w, INT32* h)
224 INT64 tmp = rect->right - rect->left + 1;
225 if ((tmp < 0) || (tmp > INT32_MAX))
228 WLog_ERR(TAG,
"rectangle invalid %s", gdi_rect_str(buffer,
sizeof(buffer), rect));
234 tmp = rect->bottom - rect->top + 1;
235 if ((tmp < 0) || (tmp > INT32_MAX))
238 WLog_ERR(TAG,
"rectangle invalid %s", gdi_rect_str(buffer,
sizeof(buffer), rect));
259BOOL gdi_CRectToCRgn(INT32 left, INT32 top, INT32 right, INT32 bottom, INT32* x, INT32* y, INT32* w,
265 wl = right - left + 1ll;
266 hl = bottom - top + 1ll;
268 if ((left > right) || (top > bottom) || (wl <= 0) || (hl <= 0) || (wl > INT32_MAX) ||
272 "Can not create region top/left=%" PRId32
"x%" PRId32
"-bottom/right=%" PRId32
274 top, left, bottom, right);
298 r = rgn->x + rgn->w - 1ll;
299 b = rgn->y + rgn->h - 1ll;
301 if ((r < INT32_MIN) || (r > INT32_MAX) || (b < INT32_MIN) || (b > INT32_MAX))
304 WLog_ERR(TAG,
"Can not create region %s", gdi_regn_str(buffer,
sizeof(buffer), rgn));
311 rect->right = (INT32)r;
312 rect->bottom = (INT32)b;
326BOOL gdi_CRgnToRect(INT64 x, INT64 y, INT32 w, INT32 h,
GDI_RECT* rect)
328 BOOL invalid = FALSE;
329 const INT64 r = x + w - 1;
330 const INT64 b = y + h - 1;
331 WINPR_ASSERT(x <= INT32_MAX);
332 WINPR_ASSERT(y <= INT32_MAX);
333 WINPR_ASSERT(r <= INT32_MAX);
334 WINPR_ASSERT(b <= INT32_MAX);
335 rect->left = (x > 0) ? (INT32)x : 0;
336 rect->top = (y > 0) ? (INT32)y : 0;
337 rect->right = rect->left;
338 rect->bottom = rect->top;
340 if ((w <= 0) || (h <= 0))
344 rect->right = (INT32)r;
349 rect->bottom = (INT32)b;
355 WLog_DBG(TAG,
"Invisible rectangle %" PRId64
"x%" PRId64
"-%" PRId64
"x%" PRId64, x, y, r,
372BOOL gdi_RgnToCRect(
const GDI_RGN* rgn, INT32* left, INT32* top, INT32* right, INT32* bottom)
377 if ((rgn->w < 0) || (rgn->h < 0))
380 WLog_ERR(TAG,
"Can not create region %s", gdi_regn_str(buffer,
sizeof(buffer), rgn));
386 *right = rgn->x + rgn->w - 1;
387 *bottom = rgn->y + rgn->h - 1;
404BOOL gdi_CRgnToCRect(INT32 x, INT32 y, INT32 w, INT32 h, INT32* left, INT32* top, INT32* right,
416 WLog_ERR(TAG,
"Invalid width");
426 WLog_ERR(TAG,
"Invalid height");
444inline BOOL gdi_CopyOverlap(INT32 x, INT32 y, INT32 width, INT32 height, INT32 srcx, INT32 srcy)
448 gdi_CRgnToRect(x, y, width, height, &dst);
449 gdi_CRgnToRect(srcx, srcy, width, height, &src);
451 if (dst.right < src.left)
453 if (dst.left > src.right)
455 if (dst.bottom < src.top)
457 if (dst.top > src.bottom)
475inline BOOL gdi_SetRect(
GDI_RECT* rc, INT32 xLeft, INT32 yTop, INT32 xRight, INT32 yBottom)
487 rc->bottom = yBottom;
501inline BOOL gdi_SetRgn(
GDI_RGN* hRgn, INT32 nXLeft, INT32 nYLeft, INT32 nWidth, INT32 nHeight)
506 if ((nWidth < 0) || (nHeight < 0))
527inline BOOL gdi_SetRectRgn(
GDI_RGN* hRgn, INT32 nLeftRect, INT32 nTopRect, INT32 nRightRect,
530 if (!gdi_CRectToRgn(nLeftRect, nTopRect, nRightRect, nBottomRect, hRgn))
545inline BOOL gdi_EqualRgn(
const GDI_RGN* hSrcRgn1,
const GDI_RGN* hSrcRgn2)
547 WINPR_ASSERT(hSrcRgn1);
548 WINPR_ASSERT(hSrcRgn2);
549 if ((hSrcRgn1->x == hSrcRgn2->x) && (hSrcRgn1->y == hSrcRgn2->y) &&
550 (hSrcRgn1->w == hSrcRgn2->w) && (hSrcRgn1->h == hSrcRgn2->h))
572 dst->left = src->left;
574 dst->right = src->right;
575 dst->bottom = src->bottom;
588inline BOOL gdi_PtInRect(
const GDI_RECT* rc, INT32 x, INT32 y)
594 if ((x >= rc->left) && (x <= rc->right))
596 if ((y >= rc->top) && (y <= rc->bottom))
616inline BOOL gdi_InvalidateRegion(
HGDI_DC hdc, INT32 x, INT32 y, INT32 w, INT32 h)
626 if (!hdc->hwnd->invalid)
629 if (w == 0 || h == 0)
632 cinvalid = hdc->hwnd->cinvalid;
634 if ((hdc->hwnd->ninvalid + 1) > (INT64)hdc->hwnd->count)
637 size_t new_cnt = 2ULL * hdc->hwnd->count;
638 if (new_cnt > UINT32_MAX)
646 hdc->hwnd->count = (UINT32)new_cnt;
650 gdi_SetRgn(&cinvalid[hdc->hwnd->ninvalid++], x, y, w, h);
651 hdc->hwnd->cinvalid = cinvalid;
652 invalid = hdc->hwnd->invalid;
660 invalid->null = FALSE;
664 gdi_CRgnToRect(x, y, w, h, &rgn);
665 gdi_RgnToRect(invalid, &inv);
667 if (rgn.left < inv.left)
670 if (rgn.top < inv.top)
673 if (rgn.right > inv.right)
674 inv.right = rgn.right;
676 if (rgn.bottom > inv.bottom)
677 inv.bottom = rgn.bottom;
679 gdi_RectToRgn(&inv, invalid);