Blame libfreerdp/gdi/shape.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * GDI Shape 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/freerdp.h>
Packit 1fb8d4
#include <freerdp/gdi/gdi.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/gdi/bitmap.h>
Packit 1fb8d4
#include <freerdp/gdi/region.h>
Packit 1fb8d4
#include <freerdp/gdi/shape.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
Packit 1fb8d4
#include "clipping.h"
Packit 1fb8d4
#include "../gdi/gdi.h"
Packit 1fb8d4
Packit 1fb8d4
#define TAG FREERDP_TAG("gdi.shape")
Packit 1fb8d4
Packit 1fb8d4
static void Ellipse_Bresenham(HGDI_DC hdc, int x1, int y1, int x2, int y2)
Packit 1fb8d4
{
Packit 1fb8d4
	INT32 e, e2;
Packit 1fb8d4
	INT32 dx, dy;
Packit 1fb8d4
	INT32 a, b, c;
Packit 1fb8d4
	a = (x1 < x2) ? x2 - x1 : x1 - x2;
Packit 1fb8d4
	b = (y1 < y2) ? y2 - y1 : y1 - y2;
Packit 1fb8d4
	c = b & 1;
Packit 1fb8d4
	dx = 4 * (1 - a) * b * b;
Packit 1fb8d4
	dy = 4 * (c + 1) * a * a;
Packit 1fb8d4
	e = dx + dy + c * a * a;
Packit 1fb8d4
Packit 1fb8d4
	if (x1 > x2)
Packit 1fb8d4
	{
Packit 1fb8d4
		x1 = x2;
Packit 1fb8d4
		x2 += a;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (y1 > y2)
Packit 1fb8d4
		y1 = y2;
Packit 1fb8d4
Packit 1fb8d4
	y1 += (b + 1) / 2;
Packit 1fb8d4
	y2 = y1 - c;
Packit 1fb8d4
	a *= 8 * a;
Packit 1fb8d4
	c = 8 * b * b;
Packit 1fb8d4
Packit 1fb8d4
	do
Packit 1fb8d4
	{
Packit 1fb8d4
		gdi_SetPixel(hdc, x2, y1, 0);
Packit 1fb8d4
		gdi_SetPixel(hdc, x1, y1, 0);
Packit 1fb8d4
		gdi_SetPixel(hdc, x1, y2, 0);
Packit 1fb8d4
		gdi_SetPixel(hdc, x2, y2, 0);
Packit 1fb8d4
		e2 = 2 * e;
Packit 1fb8d4
Packit 1fb8d4
		if (e2 >= dx)
Packit 1fb8d4
		{
Packit 1fb8d4
			x1++;
Packit 1fb8d4
			x2--;
Packit 1fb8d4
			e += dx += c;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (e2 <= dy)
Packit 1fb8d4
		{
Packit 1fb8d4
			y1++;
Packit 1fb8d4
			y2--;
Packit 1fb8d4
			e += dy += a;
Packit 1fb8d4
		}
Packit Service 5a9772
	} while (x1 <= x2);
Packit 1fb8d4
Packit 1fb8d4
	while (y1 - y2 < b)
Packit 1fb8d4
	{
Packit 1fb8d4
		gdi_SetPixel(hdc, x1 - 1, ++y1, 0);
Packit 1fb8d4
		gdi_SetPixel(hdc, x1 - 1, --y2, 0);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Draw an ellipse
Packit 1fb8d4
 * @msdn{dd162510}
Packit 1fb8d4
 * @param hdc device context
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 Service 5a9772
BOOL gdi_Ellipse(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect)
Packit 1fb8d4
{
Packit 1fb8d4
	Ellipse_Bresenham(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Fill a rectangle with the given brush.\n
Packit 1fb8d4
 * @msdn{dd162719}
Packit 1fb8d4
 * @param hdc device context
Packit 1fb8d4
 * @param rect rectangle
Packit 1fb8d4
 * @param hbr brush
Packit 1fb8d4
 * @return nonzero if successful, 0 otherwise
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
BOOL gdi_FillRect(HGDI_DC hdc, const HGDI_RECT rect, HGDI_BRUSH hbr)
Packit 1fb8d4
{
Packit 1fb8d4
	INT32 x, y;
Packit 1fb8d4
	UINT32 color, dstColor;
Packit 1fb8d4
	BOOL monochrome = FALSE;
Packit 1fb8d4
	INT32 nXDest, nYDest;
Packit 1fb8d4
	INT32 nWidth, nHeight;
Packit 1fb8d4
	const BYTE* srcp;
Packit 1fb8d4
	DWORD formatSize;
Packit 1fb8d4
	gdi_RectToCRgn(rect, &nXDest, &nYDest, &nWidth, &nHeight);
Packit 1fb8d4
Packit 1fb8d4
	if (!hdc || !hbr)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_ClipCoords(hdc, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL))
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	switch (hbr->style)
Packit 1fb8d4
	{
Packit 1fb8d4
		case GDI_BS_SOLID:
Packit 1fb8d4
			color = hbr->color;
Packit 1fb8d4
Packit 1fb8d4
			for (x = 0; x < nWidth; x++)
Packit 1fb8d4
			{
Packit Service 5a9772
				BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, nYDest);
Packit 1fb8d4
Packit 1fb8d4
				if (dstp)
Packit 1fb8d4
					WriteColor(dstp, hdc->format, color);
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			srcp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest);
Packit 1fb8d4
			formatSize = GetBytesPerPixel(hdc->format);
Packit 1fb8d4
Packit 1fb8d4
			for (y = 1; y < nHeight; y++)
Packit 1fb8d4
			{
Packit 1fb8d4
				BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y);
Packit 1fb8d4
				memcpy(dstp, srcp, nWidth * formatSize);
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case GDI_BS_HATCHED:
Packit 1fb8d4
		case GDI_BS_PATTERN:
Packit 1fb8d4
			monochrome = (hbr->pattern->format == PIXEL_FORMAT_MONO);
Packit 1fb8d4
			formatSize = GetBytesPerPixel(hbr->pattern->format);
Packit 1fb8d4
Packit 1fb8d4
			for (y = 0; y < nHeight; y++)
Packit 1fb8d4
			{
Packit 1fb8d4
				for (x = 0; x < nWidth; x++)
Packit 1fb8d4
				{
Packit Service 5a9772
					const UINT32 yOffset =
Packit Service 5a9772
					    ((nYDest + y) * hbr->pattern->width % hbr->pattern->height) * formatSize;
Packit 1fb8d4
					const UINT32 xOffset = ((nXDest + x) % hbr->pattern->width) * formatSize;
Packit 1fb8d4
					const BYTE* patp = &hbr->pattern->data[yOffset + xOffset];
Packit Service 5a9772
					BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, nYDest + y);
Packit 1fb8d4
Packit 1fb8d4
					if (!patp)
Packit 1fb8d4
						return FALSE;
Packit 1fb8d4
Packit 1fb8d4
					if (monochrome)
Packit 1fb8d4
					{
Packit 1fb8d4
						if (*patp == 0)
Packit 1fb8d4
							dstColor = hdc->bkColor;
Packit 1fb8d4
						else
Packit 1fb8d4
							dstColor = hdc->textColor;
Packit 1fb8d4
					}
Packit 1fb8d4
					else
Packit 1fb8d4
					{
Packit 1fb8d4
						dstColor = ReadColor(patp, hbr->pattern->format);
Packit Service 5a9772
						dstColor =
Packit Service 5a9772
						    FreeRDPConvertColor(dstColor, hbr->pattern->format, hdc->format, NULL);
Packit 1fb8d4
					}
Packit 1fb8d4
Packit 1fb8d4
					if (dstp)
Packit 1fb8d4
						WriteColor(dstp, hdc->format, dstColor);
Packit 1fb8d4
				}
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_InvalidateRegion(hdc, nXDest, nYDest, nWidth, nHeight))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Draw a polygon
Packit 1fb8d4
 * @msdn{dd162814}
Packit 1fb8d4
 * @param hdc device context
Packit 1fb8d4
 * @param lpPoints array of points
Packit 1fb8d4
 * @param nCount number of points
Packit 1fb8d4
 * @return nonzero if successful, 0 otherwise
Packit 1fb8d4
 */
Packit 1fb8d4
BOOL gdi_Polygon(HGDI_DC hdc, GDI_POINT* lpPoints, int nCount)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_ERR(TAG, "Not implemented!");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Draw a series of closed polygons
Packit 1fb8d4
 * @msdn{dd162818}
Packit 1fb8d4
 * @param hdc device context
Packit 1fb8d4
 * @param lpPoints array of series of points
Packit 1fb8d4
 * @param lpPolyCounts array of number of points in each series
Packit 1fb8d4
 * @param nCount count of number of points in lpPolyCounts
Packit 1fb8d4
 * @return nonzero if successful, 0 otherwise
Packit 1fb8d4
 */
Packit Service 5a9772
BOOL gdi_PolyPolygon(HGDI_DC hdc, GDI_POINT* lpPoints, int* lpPolyCounts, int nCount)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_ERR(TAG, "Not implemented!");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
BOOL gdi_Rectangle(HGDI_DC hdc, INT32 nXDst, INT32 nYDst, INT32 nWidth, INT32 nHeight)
Packit 1fb8d4
{
Packit 1fb8d4
	INT32 x, y;
Packit 1fb8d4
	UINT32 color;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_ClipCoords(hdc, &nXDst, &nYDst, &nWidth, &nHeight, NULL, NULL))
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	color = hdc->textColor;
Packit 1fb8d4
Packit 1fb8d4
	for (y = 0; y < nHeight; y++)
Packit 1fb8d4
	{
Packit Service 5a9772
		BYTE* dstLeft = gdi_get_bitmap_pointer(hdc, nXDst, nYDst + y);
Packit Service 5a9772
		BYTE* dstRight = gdi_get_bitmap_pointer(hdc, nXDst + nWidth - 1, nYDst + y);
Packit 1fb8d4
Packit 1fb8d4
		if (dstLeft)
Packit 1fb8d4
			WriteColor(dstLeft, hdc->format, color);
Packit 1fb8d4
Packit 1fb8d4
		if (dstRight)
Packit 1fb8d4
			WriteColor(dstRight, hdc->format, color);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < nWidth; x++)
Packit 1fb8d4
	{
Packit Service 5a9772
		BYTE* dstTop = gdi_get_bitmap_pointer(hdc, nXDst + x, nYDst);
Packit Service 5a9772
		BYTE* dstBottom = gdi_get_bitmap_pointer(hdc, nXDst + x, nYDst + nHeight - 1);
Packit 1fb8d4
Packit 1fb8d4
		if (dstTop)
Packit 1fb8d4
			WriteColor(dstTop, hdc->format, color);
Packit 1fb8d4
Packit 1fb8d4
		if (dstBottom)
Packit 1fb8d4
			WriteColor(dstBottom, hdc->format, color);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}