summaryrefslogtreecommitdiffstats
path: root/libfreerdp/gdi/shape.c
diff options
context:
space:
mode:
Diffstat (limited to 'libfreerdp/gdi/shape.c')
-rw-r--r--libfreerdp/gdi/shape.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/libfreerdp/gdi/shape.c b/libfreerdp/gdi/shape.c
new file mode 100644
index 0000000..fdc05f1
--- /dev/null
+++ b/libfreerdp/gdi/shape.c
@@ -0,0 +1,286 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * GDI Shape Functions
+ *
+ * Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2016 Armin Novak <armin.novak@thincast.com>
+ * Copyright 2016 Thincast Technologies GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <freerdp/config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <freerdp/freerdp.h>
+#include <freerdp/gdi/gdi.h>
+
+#include <freerdp/gdi/bitmap.h>
+#include <freerdp/gdi/region.h>
+#include <freerdp/gdi/shape.h>
+
+#include <freerdp/log.h>
+
+#include "clipping.h"
+#include "../gdi/gdi.h"
+
+#define TAG FREERDP_TAG("gdi.shape")
+
+static void Ellipse_Bresenham(HGDI_DC hdc, int x1, int y1, int x2, int y2)
+{
+ INT32 e = 0;
+ INT32 e2 = 0;
+ INT32 dx = 0;
+ INT32 dy = 0;
+ INT32 a = 0;
+ INT32 b = 0;
+ INT32 c = 0;
+ a = (x1 < x2) ? x2 - x1 : x1 - x2;
+ b = (y1 < y2) ? y2 - y1 : y1 - y2;
+ c = b & 1;
+ dx = 4 * (1 - a) * b * b;
+ dy = 4 * (c + 1) * a * a;
+ e = dx + dy + c * a * a;
+
+ if (x1 > x2)
+ {
+ x1 = x2;
+ x2 += a;
+ }
+
+ if (y1 > y2)
+ y1 = y2;
+
+ y1 += (b + 1) / 2;
+ y2 = y1 - c;
+ a *= 8 * a;
+ c = 8 * b * b;
+
+ do
+ {
+ gdi_SetPixel(hdc, x2, y1, 0);
+ gdi_SetPixel(hdc, x1, y1, 0);
+ gdi_SetPixel(hdc, x1, y2, 0);
+ gdi_SetPixel(hdc, x2, y2, 0);
+ e2 = 2 * e;
+
+ if (e2 >= dx)
+ {
+ x1++;
+ x2--;
+ e += dx += c;
+ }
+
+ if (e2 <= dy)
+ {
+ y1++;
+ y2--;
+ e += dy += a;
+ }
+ } while (x1 <= x2);
+
+ while (y1 - y2 < b)
+ {
+ gdi_SetPixel(hdc, x1 - 1, ++y1, 0);
+ gdi_SetPixel(hdc, x1 - 1, --y2, 0);
+ }
+}
+
+/**
+ * Draw an ellipse
+ * msdn{dd162510}
+ *
+ * @param hdc device context
+ * @param nLeftRect x1
+ * @param nTopRect y1
+ * @param nRightRect x2
+ * @param nBottomRect y2
+ *
+ * @return nonzero if successful, 0 otherwise
+ */
+BOOL gdi_Ellipse(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect)
+{
+ Ellipse_Bresenham(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
+ return TRUE;
+}
+
+/**
+ * Fill a rectangle with the given brush.
+ * msdn{dd162719}
+ *
+ * @param hdc device context
+ * @param rect rectangle
+ * @param hbr brush
+ *
+ * @return nonzero if successful, 0 otherwise
+ */
+
+BOOL gdi_FillRect(HGDI_DC hdc, const HGDI_RECT rect, HGDI_BRUSH hbr)
+{
+ UINT32 color = 0;
+ UINT32 dstColor = 0;
+ BOOL monochrome = FALSE;
+ INT32 nXDest = 0;
+ INT32 nYDest = 0;
+ INT32 nWidth = 0;
+ INT32 nHeight = 0;
+ const BYTE* srcp = NULL;
+ DWORD formatSize = 0;
+ gdi_RectToCRgn(rect, &nXDest, &nYDest, &nWidth, &nHeight);
+
+ if (!hdc || !hbr)
+ return FALSE;
+
+ if (!gdi_ClipCoords(hdc, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL))
+ return TRUE;
+
+ switch (hbr->style)
+ {
+ case GDI_BS_SOLID:
+ color = hbr->color;
+
+ for (INT32 x = 0; x < nWidth; x++)
+ {
+ BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, nYDest);
+
+ if (dstp)
+ FreeRDPWriteColor(dstp, hdc->format, color);
+ }
+
+ srcp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest);
+ formatSize = FreeRDPGetBytesPerPixel(hdc->format);
+
+ for (INT32 y = 1; y < nHeight; y++)
+ {
+ BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y);
+ memcpy(dstp, srcp, 1ull * nWidth * formatSize);
+ }
+
+ break;
+
+ case GDI_BS_HATCHED:
+ case GDI_BS_PATTERN:
+ monochrome = (hbr->pattern->format == PIXEL_FORMAT_MONO);
+ formatSize = FreeRDPGetBytesPerPixel(hbr->pattern->format);
+
+ for (INT32 y = 0; y < nHeight; y++)
+ {
+ for (INT32 x = 0; x < nWidth; x++)
+ {
+ const UINT32 yOffset =
+ ((nYDest + y) * hbr->pattern->width % hbr->pattern->height) * formatSize;
+ const UINT32 xOffset = ((nXDest + x) % hbr->pattern->width) * formatSize;
+ const BYTE* patp = &hbr->pattern->data[yOffset + xOffset];
+ BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, nYDest + y);
+
+ if (!patp)
+ return FALSE;
+
+ if (monochrome)
+ {
+ if (*patp == 0)
+ dstColor = hdc->bkColor;
+ else
+ dstColor = hdc->textColor;
+ }
+ else
+ {
+ dstColor = FreeRDPReadColor(patp, hbr->pattern->format);
+ dstColor =
+ FreeRDPConvertColor(dstColor, hbr->pattern->format, hdc->format, NULL);
+ }
+
+ if (dstp)
+ FreeRDPWriteColor(dstp, hdc->format, dstColor);
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ if (!gdi_InvalidateRegion(hdc, nXDest, nYDest, nWidth, nHeight))
+ return FALSE;
+
+ return TRUE;
+}
+
+/**
+ * Draw a polygon
+ * msdn{dd162814}
+ * @param hdc device context
+ * @param lpPoints array of points
+ * @param nCount number of points
+ * @return nonzero if successful, 0 otherwise
+ */
+BOOL gdi_Polygon(HGDI_DC hdc, GDI_POINT* lpPoints, int nCount)
+{
+ WLog_ERR(TAG, "Not implemented!");
+ return FALSE;
+}
+
+/**
+ * Draw a series of closed polygons
+ * msdn{dd162818}
+ * @param hdc device context
+ * @param lpPoints array of series of points
+ * @param lpPolyCounts array of number of points in each series
+ * @param nCount count of number of points in lpPolyCounts
+ * @return nonzero if successful, 0 otherwise
+ */
+BOOL gdi_PolyPolygon(HGDI_DC hdc, GDI_POINT* lpPoints, int* lpPolyCounts, int nCount)
+{
+ WLog_ERR(TAG, "Not implemented!");
+ return FALSE;
+}
+
+BOOL gdi_Rectangle(HGDI_DC hdc, INT32 nXDst, INT32 nYDst, INT32 nWidth, INT32 nHeight)
+{
+ UINT32 color = 0;
+
+ if (!gdi_ClipCoords(hdc, &nXDst, &nYDst, &nWidth, &nHeight, NULL, NULL))
+ return TRUE;
+
+ color = hdc->textColor;
+
+ for (INT32 y = 0; y < nHeight; y++)
+ {
+ BYTE* dstLeft = gdi_get_bitmap_pointer(hdc, nXDst, nYDst + y);
+ BYTE* dstRight = gdi_get_bitmap_pointer(hdc, nXDst + nWidth - 1, nYDst + y);
+
+ if (dstLeft)
+ FreeRDPWriteColor(dstLeft, hdc->format, color);
+
+ if (dstRight)
+ FreeRDPWriteColor(dstRight, hdc->format, color);
+ }
+
+ for (INT32 x = 0; x < nWidth; x++)
+ {
+ BYTE* dstTop = gdi_get_bitmap_pointer(hdc, nXDst + x, nYDst);
+ BYTE* dstBottom = gdi_get_bitmap_pointer(hdc, nXDst + x, nYDst + nHeight - 1);
+
+ if (dstTop)
+ FreeRDPWriteColor(dstTop, hdc->format, color);
+
+ if (dstBottom)
+ FreeRDPWriteColor(dstBottom, hdc->format, color);
+ }
+
+ return FALSE;
+}