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);