Blame libfreerdp/gdi/region.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * GDI Region Functions
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 * Copyright 2016 Armin Novak <armin.novak@thincast.com>
Packit 1fb8d4
 * Copyright 2016 Thincast Technologies GmbH
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <stdio.h>
Packit 1fb8d4
#include <string.h>
Packit 1fb8d4
#include <stdlib.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/api.h>
Packit 1fb8d4
#include <freerdp/freerdp.h>
Packit 1fb8d4
#include <freerdp/gdi/gdi.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/gdi/region.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
Packit 1fb8d4
#define TAG FREERDP_TAG("gdi.region")
Packit 1fb8d4
Packit ea53ec
static char* gdi_rect_str(char* buffer, size_t size, const HGDI_RECT rect)
Packit ea53ec
{
Packit ea53ec
	if (!buffer || (size < 1) || !rect)
Packit ea53ec
		return NULL;
Packit ea53ec
Packit ea53ec
	_snprintf(buffer, size - 1,
Packit ea53ec
	          "[top/left=%" PRId32 "x%" PRId32 "-bottom/right%" PRId32 "x%" PRId32 "]", rect->top,
Packit ea53ec
	          rect->left, rect->bottom, rect->right);
Packit ea53ec
		buffer[size - 1] = '\0';
Packit ea53ec
Packit ea53ec
	        return buffer;
Packit ea53ec
}
Packit ea53ec
Packit 1fb8d4
/**
Packit 1fb8d4
 * Create a region from rectangular coordinates.\n
Packit 1fb8d4
 * @msdn{dd183514}
Packit 1fb8d4
 * @param nLeftRect x1
Packit 1fb8d4
 * @param nTopRect y1
Packit 1fb8d4
 * @param nRightRect x2
Packit 1fb8d4
 * @param nBottomRect y2
Packit 1fb8d4
 * @return new region
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
HGDI_RGN gdi_CreateRectRgn(INT32 nLeftRect, INT32 nTopRect,
Packit 1fb8d4
                           INT32 nRightRect, INT32 nBottomRect)
Packit 1fb8d4
{
Packit 1fb8d4
	HGDI_RGN hRgn = (HGDI_RGN) calloc(1, sizeof(GDI_RGN));
Packit 1fb8d4
Packit 1fb8d4
	if (!hRgn)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	hRgn->objectType = GDIOBJECT_REGION;
Packit 1fb8d4
	hRgn->x = nLeftRect;
Packit 1fb8d4
	hRgn->y = nTopRect;
Packit 1fb8d4
	hRgn->w = nRightRect - nLeftRect + 1;
Packit 1fb8d4
	hRgn->h = nBottomRect - nTopRect + 1;
Packit 1fb8d4
	hRgn->null = FALSE;
Packit 1fb8d4
	return hRgn;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Create a new rectangle.
Packit 1fb8d4
 * @param xLeft x1
Packit 1fb8d4
 * @param yTop y1
Packit 1fb8d4
 * @param xRight x2
Packit 1fb8d4
 * @param yBottom y2
Packit 1fb8d4
 * @return new rectangle
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
HGDI_RECT gdi_CreateRect(INT32 xLeft, INT32 yTop,
Packit 1fb8d4
                         INT32 xRight, INT32 yBottom)
Packit 1fb8d4
{
Packit 1fb8d4
	HGDI_RECT hRect = (HGDI_RECT) calloc(1, sizeof(GDI_RECT));
Packit 1fb8d4
Packit 1fb8d4
	if (!hRect)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	hRect->objectType = GDIOBJECT_RECT;
Packit 1fb8d4
	hRect->left = xLeft;
Packit 1fb8d4
	hRect->top = yTop;
Packit 1fb8d4
	hRect->right = xRight;
Packit 1fb8d4
	hRect->bottom = yBottom;
Packit 1fb8d4
	return hRect;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Convert a rectangle to a region.
Packit 1fb8d4
 * @param rect source rectangle
Packit 1fb8d4
 * @param rgn destination region
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE void gdi_RectToRgn(HGDI_RECT rect, HGDI_RGN rgn)
Packit 1fb8d4
{
Packit 1fb8d4
	rgn->x = rect->left;
Packit 1fb8d4
	rgn->y = rect->top;
Packit 1fb8d4
	rgn->w = rect->right - rect->left + 1;
Packit 1fb8d4
	rgn->h = rect->bottom - rect->top + 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Convert rectangular coordinates to a region.
Packit 1fb8d4
 * @param left x1
Packit 1fb8d4
 * @param top y1
Packit 1fb8d4
 * @param right x2
Packit 1fb8d4
 * @param bottom y2
Packit 1fb8d4
 * @param rgn destination region
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE void gdi_CRectToRgn(INT32 left, INT32 top,
Packit 1fb8d4
                           INT32 right, INT32 bottom, HGDI_RGN rgn)
Packit 1fb8d4
{
Packit 1fb8d4
	rgn->x = left;
Packit 1fb8d4
	rgn->y = top;
Packit 1fb8d4
	rgn->w = right - left + 1;
Packit 1fb8d4
	rgn->h = bottom - top + 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Convert a rectangle to region coordinates.
Packit 1fb8d4
 * @param rect source rectangle
Packit 1fb8d4
 * @param x x1
Packit 1fb8d4
 * @param y y1
Packit 1fb8d4
 * @param w width
Packit 1fb8d4
 * @param h height
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE void gdi_RectToCRgn(const HGDI_RECT rect,
Packit 1fb8d4
                           INT32* x, INT32* y,
Packit 1fb8d4
                           INT32* w, INT32* h)
Packit 1fb8d4
{
Packit ea53ec
	INT64 tmp;
Packit 1fb8d4
	*x = rect->left;
Packit 1fb8d4
	*y = rect->top;
Packit ea53ec
	tmp = rect->right - rect->left + 1;
Packit ea53ec
	if ((tmp < 0) || (tmp > INT32_MAX))
Packit ea53ec
	{
Packit ea53ec
		char buffer[256];
Packit ea53ec
		WLog_ERR(TAG, "[%s] rectangle invalid %s", __FUNCTION__,
Packit ea53ec
		         gdi_rect_str(buffer, sizeof(buffer), rect));
Packit ea53ec
		*w = 0;
Packit ea53ec
	}
Packit ea53ec
	else
Packit ea53ec
		*w = tmp;
Packit ea53ec
	tmp = rect->bottom - rect->top + 1;
Packit ea53ec
	if ((tmp < 0) || (tmp > INT32_MAX))
Packit ea53ec
	{
Packit ea53ec
		char buffer[256];
Packit ea53ec
		WLog_ERR(TAG, "[%s] rectangle invalid %s", __FUNCTION__,
Packit ea53ec
		         gdi_rect_str(buffer, sizeof(buffer), rect));
Packit ea53ec
		*h = 0;
Packit ea53ec
	}
Packit ea53ec
	else
Packit ea53ec
		*h = tmp;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Convert rectangular coordinates to region coordinates.
Packit 1fb8d4
 * @param left x1
Packit 1fb8d4
 * @param top y1
Packit 1fb8d4
 * @param right x2
Packit 1fb8d4
 * @param bottom y2
Packit 1fb8d4
 * @param x x1
Packit 1fb8d4
 * @param y y1
Packit 1fb8d4
 * @param w width
Packit 1fb8d4
 * @param h height
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE void gdi_CRectToCRgn(INT32 left, INT32 top, INT32 right,
Packit 1fb8d4
                            INT32 bottom,
Packit 1fb8d4
                            INT32* x, INT32* y, INT32* w, INT32* h)
Packit 1fb8d4
{
Packit 1fb8d4
	*x = left;
Packit 1fb8d4
	*y = top;
Packit 1fb8d4
	*w = right - left + 1;
Packit 1fb8d4
	*h = bottom - top + 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Convert a region to a rectangle.
Packit 1fb8d4
 * @param rgn source region
Packit 1fb8d4
 * @param rect destination rectangle
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE void gdi_RgnToRect(HGDI_RGN rgn, HGDI_RECT rect)
Packit 1fb8d4
{
Packit 1fb8d4
	rect->left = rgn->x;
Packit 1fb8d4
	rect->top = rgn->y;
Packit 1fb8d4
	rect->right = rgn->x + rgn->w - 1;
Packit 1fb8d4
	rect->bottom = rgn->y + rgn->h - 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Convert region coordinates to a rectangle.
Packit 1fb8d4
 * @param x x1
Packit 1fb8d4
 * @param y y1
Packit 1fb8d4
 * @param w width
Packit 1fb8d4
 * @param h height
Packit 1fb8d4
 * @param rect destination rectangle
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE void gdi_CRgnToRect(INT64 x, INT64 y, INT32 w, INT32 h,
Packit 1fb8d4
                           HGDI_RECT rect)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL invalid = FALSE;
Packit 1fb8d4
	const INT64 r = x + w - 1;
Packit 1fb8d4
	const INT64 b = y + h - 1;
Packit 1fb8d4
	rect->left = (x > 0) ? x : 0;
Packit 1fb8d4
	rect->top = (y > 0) ? y : 0;
Packit 1fb8d4
	rect->right = rect->left;
Packit 1fb8d4
	rect->bottom = rect->top;
Packit 1fb8d4
Packit 1fb8d4
	if (r > 0)
Packit 1fb8d4
		rect->right = r;
Packit 1fb8d4
	else
Packit 1fb8d4
		invalid = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (b > 0)
Packit 1fb8d4
		rect->bottom = b;
Packit 1fb8d4
	else
Packit 1fb8d4
		invalid = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (invalid)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_DBG(TAG, "Invisible rectangle %"PRId64"x%"PRId64"-%"PRId64"x%"PRId64,
Packit 1fb8d4
		         x, y, r, b);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Convert a region to rectangular coordinates.
Packit 1fb8d4
 * @param rgn source region
Packit 1fb8d4
 * @param left x1
Packit 1fb8d4
 * @param top y1
Packit 1fb8d4
 * @param right x2
Packit 1fb8d4
 * @param bottom y2
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE void gdi_RgnToCRect(HGDI_RGN rgn, INT32* left, INT32* top,
Packit 1fb8d4
                           INT32* right, INT32* bottom)
Packit 1fb8d4
{
Packit 1fb8d4
	*left = rgn->x;
Packit 1fb8d4
	*top = rgn->y;
Packit 1fb8d4
	*right = rgn->x + rgn->w - 1;
Packit 1fb8d4
	*bottom = rgn->y + rgn->h - 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Convert region coordinates to rectangular coordinates.
Packit 1fb8d4
 * @param x x1
Packit 1fb8d4
 * @param y y1
Packit 1fb8d4
 * @param w width
Packit 1fb8d4
 * @param h height
Packit 1fb8d4
 * @param left x1
Packit 1fb8d4
 * @param top y1
Packit 1fb8d4
 * @param right x2
Packit 1fb8d4
 * @param bottom y2
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE void gdi_CRgnToCRect(INT32 x, INT32 y, INT32 w, INT32 h,
Packit 1fb8d4
                            INT32* left, INT32* top, INT32* right, INT32* bottom)
Packit 1fb8d4
{
Packit 1fb8d4
	*left = x;
Packit 1fb8d4
	*top = y;
Packit 1fb8d4
	*right = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (w > 0)
Packit 1fb8d4
		*right = x + w - 1;
Packit 1fb8d4
	else
Packit 1fb8d4
		WLog_ERR(TAG, "Invalid width");
Packit 1fb8d4
Packit 1fb8d4
	*bottom = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (h > 0)
Packit 1fb8d4
		*bottom = y + h - 1;
Packit 1fb8d4
	else
Packit 1fb8d4
		WLog_ERR(TAG, "Invalid height");
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Check if copying would involve overlapping regions
Packit 1fb8d4
 * @param x x1
Packit 1fb8d4
 * @param y y1
Packit 1fb8d4
 * @param width width
Packit 1fb8d4
 * @param height height
Packit 1fb8d4
 * @param srcx source x1
Packit 1fb8d4
 * @param srcy source y1
Packit 1fb8d4
 * @return nonzero if there is an overlap, 0 otherwise
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE BOOL gdi_CopyOverlap(INT32 x, INT32 y, INT32 width, INT32 height,
Packit 1fb8d4
                            INT32 srcx, INT32 srcy)
Packit 1fb8d4
{
Packit 1fb8d4
	GDI_RECT dst;
Packit 1fb8d4
	GDI_RECT src;
Packit 1fb8d4
	gdi_CRgnToRect(x, y, width, height, &dst);
Packit 1fb8d4
	gdi_CRgnToRect(srcx, srcy, width, height, &src;;
Packit 1fb8d4
	return (dst.right >= src.left && dst.left <= src.right &&
Packit 1fb8d4
	        dst.bottom >= src.top && dst.top <= src.bottom) ? TRUE : FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Set the coordinates of a given rectangle.\n
Packit 1fb8d4
 * @msdn{dd145085}
Packit 1fb8d4
 * @param rc rectangle
Packit 1fb8d4
 * @param xLeft x1
Packit 1fb8d4
 * @param yTop y1
Packit 1fb8d4
 * @param xRight x2
Packit 1fb8d4
 * @param yBottom y2
Packit 1fb8d4
 * @return nonzero if successful, 0 otherwise
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE BOOL gdi_SetRect(HGDI_RECT rc, INT32 xLeft, INT32 yTop,
Packit 1fb8d4
                        INT32 xRight, INT32 yBottom)
Packit 1fb8d4
{
Packit 1fb8d4
	rc->left = xLeft;
Packit 1fb8d4
	rc->top = yTop;
Packit 1fb8d4
	rc->right = xRight;
Packit 1fb8d4
	rc->bottom = yBottom;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Set the coordinates of a given region.
Packit 1fb8d4
 * @param hRgn region
Packit 1fb8d4
 * @param nXLeft x1
Packit 1fb8d4
 * @param nYLeft y1
Packit 1fb8d4
 * @param nWidth width
Packit 1fb8d4
 * @param nHeight height
Packit 1fb8d4
 * @return nonzero if successful, 0 otherwise
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE BOOL gdi_SetRgn(HGDI_RGN hRgn, INT32 nXLeft, INT32 nYLeft,
Packit 1fb8d4
                       INT32 nWidth, INT32 nHeight)
Packit 1fb8d4
{
Packit 1fb8d4
	hRgn->x = nXLeft;
Packit 1fb8d4
	hRgn->y = nYLeft;
Packit 1fb8d4
	hRgn->w = nWidth;
Packit 1fb8d4
	hRgn->h = nHeight;
Packit 1fb8d4
	hRgn->null = FALSE;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Convert rectangular coordinates to a region
Packit 1fb8d4
 * @param hRgn destination region
Packit 1fb8d4
 * @param nLeftRect x1
Packit 1fb8d4
 * @param nTopRect y1
Packit 1fb8d4
 * @param nRightRect x2
Packit 1fb8d4
 * @param nBottomRect y2
Packit 1fb8d4
 * @return nonzero if successful, 0 otherwise
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE BOOL gdi_SetRectRgn(HGDI_RGN hRgn, INT32 nLeftRect, INT32 nTopRect,
Packit 1fb8d4
                           INT32 nRightRect, INT32 nBottomRect)
Packit 1fb8d4
{
Packit 1fb8d4
	gdi_CRectToRgn(nLeftRect, nTopRect, nRightRect, nBottomRect, hRgn);
Packit 1fb8d4
	hRgn->null = FALSE;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Compare two regions for equality.\n
Packit 1fb8d4
 * @msdn{dd162700}
Packit 1fb8d4
 * @param hSrcRgn1 first region
Packit 1fb8d4
 * @param hSrcRgn2 second region
Packit 1fb8d4
 * @return nonzero if both regions are equal, 0 otherwise
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE BOOL gdi_EqualRgn(HGDI_RGN hSrcRgn1, HGDI_RGN hSrcRgn2)
Packit 1fb8d4
{
Packit 1fb8d4
	if ((hSrcRgn1->x == hSrcRgn2->x) &&
Packit 1fb8d4
	    (hSrcRgn1->y == hSrcRgn2->y) &&
Packit 1fb8d4
	    (hSrcRgn1->w == hSrcRgn2->w) &&
Packit 1fb8d4
	    (hSrcRgn1->h == hSrcRgn2->h))
Packit 1fb8d4
	{
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Copy coordinates from a rectangle to another rectangle
Packit 1fb8d4
 * @msdn{dd183481}
Packit 1fb8d4
 * @param dst destination rectangle
Packit 1fb8d4
 * @param src source rectangle
Packit 1fb8d4
 * @return nonzero if successful, 0 otherwise
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE BOOL gdi_CopyRect(HGDI_RECT dst, HGDI_RECT src)
Packit 1fb8d4
{
Packit 1fb8d4
	dst->left = src->left;
Packit 1fb8d4
	dst->top = src->top;
Packit 1fb8d4
	dst->right = src->right;
Packit 1fb8d4
	dst->bottom = src->bottom;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Check if a point is inside a rectangle.\n
Packit 1fb8d4
 * @msdn{dd162882}
Packit 1fb8d4
 * @param rc rectangle
Packit 1fb8d4
 * @param x point x position
Packit 1fb8d4
 * @param y point y position
Packit 1fb8d4
 * @return nonzero if the point is inside, 0 otherwise
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE BOOL gdi_PtInRect(HGDI_RECT rc, INT32 x, INT32 y)
Packit 1fb8d4
{
Packit 1fb8d4
	/*
Packit 1fb8d4
	 * points on the left and top sides are considered in,
Packit 1fb8d4
	 * while points on the right and bottom sides are considered out
Packit 1fb8d4
	 */
Packit 1fb8d4
	if (x >= rc->left && x <= rc->right)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (y >= rc->top && y <= rc->bottom)
Packit 1fb8d4
		{
Packit 1fb8d4
			return TRUE;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Invalidate a given region, such that it is redrawn on the next region update.\n
Packit 1fb8d4
 * @msdn{dd145003}
Packit 1fb8d4
 * @param hdc device context
Packit 1fb8d4
 * @param x x1
Packit 1fb8d4
 * @param y y1
Packit 1fb8d4
 * @param w width
Packit 1fb8d4
 * @param h height
Packit 1fb8d4
 * @return nonzero on success, 0 otherwise
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
INLINE BOOL gdi_InvalidateRegion(HGDI_DC hdc, INT32 x, INT32 y, INT32 w,
Packit 1fb8d4
                                 INT32 h)
Packit 1fb8d4
{
Packit 1fb8d4
	GDI_RECT inv;
Packit 1fb8d4
	GDI_RECT rgn;
Packit 1fb8d4
	HGDI_RGN invalid;
Packit 1fb8d4
	HGDI_RGN cinvalid;
Packit 1fb8d4
Packit 1fb8d4
	if (!hdc->hwnd)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (!hdc->hwnd->invalid)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (w == 0 || h == 0)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	cinvalid = hdc->hwnd->cinvalid;
Packit 1fb8d4
Packit 1fb8d4
	if ((hdc->hwnd->ninvalid + 1) > hdc->hwnd->count)
Packit 1fb8d4
	{
Packit 1fb8d4
		int new_cnt;
Packit 1fb8d4
		HGDI_RGN new_rgn;
Packit 1fb8d4
		new_cnt = hdc->hwnd->count * 2;
Packit 1fb8d4
		new_rgn = (HGDI_RGN) realloc(cinvalid, sizeof(GDI_RGN) * new_cnt);
Packit 1fb8d4
Packit 1fb8d4
		if (!new_rgn)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		hdc->hwnd->count = new_cnt;
Packit 1fb8d4
		cinvalid = new_rgn;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	gdi_SetRgn(&cinvalid[hdc->hwnd->ninvalid++], x, y, w, h);
Packit 1fb8d4
	hdc->hwnd->cinvalid = cinvalid;
Packit 1fb8d4
	invalid = hdc->hwnd->invalid;
Packit 1fb8d4
Packit 1fb8d4
	if (invalid->null)
Packit 1fb8d4
	{
Packit 1fb8d4
		invalid->x = x;
Packit 1fb8d4
		invalid->y = y;
Packit 1fb8d4
		invalid->w = w;
Packit 1fb8d4
		invalid->h = h;
Packit 1fb8d4
		invalid->null = FALSE;
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	gdi_CRgnToRect(x, y, w, h, &rgn);
Packit 1fb8d4
	gdi_RgnToRect(invalid, &inv;;
Packit 1fb8d4
Packit 1fb8d4
	if (rgn.left < inv.left)
Packit 1fb8d4
		inv.left = rgn.left;
Packit 1fb8d4
Packit 1fb8d4
	if (rgn.top < inv.top)
Packit 1fb8d4
		inv.top = rgn.top;
Packit 1fb8d4
Packit 1fb8d4
	if (rgn.right > inv.right)
Packit 1fb8d4
		inv.right = rgn.right;
Packit 1fb8d4
Packit 1fb8d4
	if (rgn.bottom > inv.bottom)
Packit 1fb8d4
		inv.bottom = rgn.bottom;
Packit 1fb8d4
Packit 1fb8d4
	gdi_RectToRgn(&inv, invalid);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}