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")
40 static char* gdi_rect_str(
char* buffer,
size_t size,
const HGDI_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';
53 static char* gdi_regn_str(
char* buffer,
size_t size,
const HGDI_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';
77 HGDI_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;
116 HGDI_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);
180 BOOL gdi_CRectToRgn(INT32 left, INT32 top, INT32 right, INT32 bottom,
HGDI_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);
218 BOOL gdi_RectToCRgn(
const HGDI_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));
258 BOOL 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;
325 BOOL gdi_CRgnToRect(INT64 x, INT64 y, INT32 w, INT32 h,
HGDI_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,
371 BOOL gdi_RgnToCRect(
const HGDI_RGN rgn, INT32* left, INT32* top, INT32* right, INT32* bottom)
374 if ((rgn->w < 0) || (rgn->h < 0))
377 WLog_ERR(TAG,
"Can not create region %s", gdi_regn_str(buffer,
sizeof(buffer), rgn));
383 *right = rgn->x + rgn->w - 1;
384 *bottom = rgn->y + rgn->h - 1;
401 INLINE BOOL gdi_CRgnToCRect(INT32 x, INT32 y, INT32 w, INT32 h, INT32* left, INT32* top,
402 INT32* right, INT32* bottom)
413 WLog_ERR(TAG,
"Invalid width");
423 WLog_ERR(TAG,
"Invalid height");
441 INLINE BOOL gdi_CopyOverlap(INT32 x, INT32 y, INT32 width, INT32 height, INT32 srcx, INT32 srcy)
445 gdi_CRgnToRect(x, y, width, height, &dst);
446 gdi_CRgnToRect(srcx, srcy, width, height, &src);
448 if (dst.right < src.left)
450 if (dst.left > src.right)
452 if (dst.bottom < src.top)
454 if (dst.top > src.bottom)
472 INLINE BOOL gdi_SetRect(
HGDI_RECT rc, INT32 xLeft, INT32 yTop, INT32 xRight, INT32 yBottom)
484 rc->bottom = yBottom;
498 INLINE BOOL gdi_SetRgn(
HGDI_RGN hRgn, INT32 nXLeft, INT32 nYLeft, INT32 nWidth, INT32 nHeight)
503 if ((nWidth < 0) || (nHeight < 0))
524 INLINE BOOL gdi_SetRectRgn(
HGDI_RGN hRgn, INT32 nLeftRect, INT32 nTopRect, INT32 nRightRect,
527 if (!gdi_CRectToRgn(nLeftRect, nTopRect, nRightRect, nBottomRect, hRgn))
544 if ((hSrcRgn1->x == hSrcRgn2->x) && (hSrcRgn1->y == hSrcRgn2->y) &&
545 (hSrcRgn1->w == hSrcRgn2->w) && (hSrcRgn1->h == hSrcRgn2->h))
567 dst->left = src->left;
569 dst->right = src->right;
570 dst->bottom = src->bottom;
583 INLINE BOOL gdi_PtInRect(
const HGDI_RECT rc, INT32 x, INT32 y)
589 if ((x >= rc->left) && (x <= rc->right))
591 if ((y >= rc->top) && (y <= rc->bottom))
611 INLINE BOOL gdi_InvalidateRegion(
HGDI_DC hdc, INT32 x, INT32 y, INT32 w, INT32 h)
621 if (!hdc->hwnd->invalid)
624 if (w == 0 || h == 0)
627 cinvalid = hdc->hwnd->cinvalid;
629 if ((hdc->hwnd->ninvalid + 1) > (INT64)hdc->hwnd->count)
632 size_t new_cnt = 2ULL * hdc->hwnd->count;
633 if (new_cnt > UINT32_MAX)
641 hdc->hwnd->count = (UINT32)new_cnt;
645 gdi_SetRgn(&cinvalid[hdc->hwnd->ninvalid++], x, y, w, h);
646 hdc->hwnd->cinvalid = cinvalid;
647 invalid = hdc->hwnd->invalid;
655 invalid->null = FALSE;
659 gdi_CRgnToRect(x, y, w, h, &rgn);
660 gdi_RgnToRect(invalid, &inv);
662 if (rgn.left < inv.left)
665 if (rgn.top < inv.top)
668 if (rgn.right > inv.right)
669 inv.right = rgn.right;
671 if (rgn.bottom > inv.bottom)
672 inv.bottom = rgn.bottom;
674 gdi_RectToRgn(&inv, invalid);