FreeRDP
Loading...
Searching...
No Matches
shape.c
1
22#include <freerdp/config.h>
23
24#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27
28#include <freerdp/freerdp.h>
29#include <freerdp/gdi/gdi.h>
30
31#include <freerdp/gdi/bitmap.h>
32#include <freerdp/gdi/region.h>
33#include <freerdp/gdi/shape.h>
34
35#include <freerdp/log.h>
36
37#include "clipping.h"
38#include "../gdi/gdi.h"
39
40#define TAG FREERDP_TAG("gdi.shape")
41
42WINPR_ATTR_NODISCARD
43static BOOL Ellipse_Bresenham(HGDI_DC hdc, int x1, int y1, int x2, int y2)
44{
45 INT32 a = (x1 < x2) ? x2 - x1 : x1 - x2;
46 const INT32 b = (y1 < y2) ? y2 - y1 : y1 - y2;
47 INT32 c = b & 1;
48 INT32 dx = 4 * (1 - a) * b * b;
49 INT32 dy = 4 * (c + 1) * a * a;
50 INT32 e = dx + dy + c * a * a;
51
52 if (x1 > x2)
53 {
54 x1 = x2;
55 x2 += a;
56 }
57
58 if (y1 > y2)
59 y1 = y2;
60
61 y1 += (b + 1) / 2;
62 y2 = y1 - c;
63 a *= 8 * a;
64 c = 8 * b * b;
65
66 do
67 {
68 gdi_SetPixel(hdc, WINPR_ASSERTING_INT_CAST(UINT32, x2),
69 WINPR_ASSERTING_INT_CAST(UINT32, y1), 0);
70 gdi_SetPixel(hdc, WINPR_ASSERTING_INT_CAST(UINT32, x1),
71 WINPR_ASSERTING_INT_CAST(UINT32, y1), 0);
72 gdi_SetPixel(hdc, WINPR_ASSERTING_INT_CAST(UINT32, x1),
73 WINPR_ASSERTING_INT_CAST(UINT32, y2), 0);
74 gdi_SetPixel(hdc, WINPR_ASSERTING_INT_CAST(UINT32, x2),
75 WINPR_ASSERTING_INT_CAST(UINT32, y2), 0);
76
77 const INT32 e2 = 2 * e;
78
79 if (e2 >= dx)
80 {
81 x1++;
82 x2--;
83 e += dx += c;
84 }
85
86 if (e2 <= dy)
87 {
88 y1++;
89 y2--;
90 e += dy += a;
91 }
92 } while (x1 <= x2);
93
94 while (y1 - y2 < b)
95 {
96 y1++;
97 y2--;
98
99 gdi_SetPixel(hdc, WINPR_ASSERTING_INT_CAST(uint32_t, x1 - 1),
100 WINPR_ASSERTING_INT_CAST(uint32_t, y1), 0);
101 gdi_SetPixel(hdc, WINPR_ASSERTING_INT_CAST(uint32_t, x1 - 1),
102 WINPR_ASSERTING_INT_CAST(uint32_t, y2), 0);
103 }
104 return TRUE;
105}
106
119BOOL gdi_Ellipse(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect)
120{
121 return Ellipse_Bresenham(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
122}
123
135BOOL gdi_FillRect(HGDI_DC hdc, const GDI_RECT* rect, HGDI_BRUSH hbr)
136{
137 INT32 nXDest = 0;
138 INT32 nYDest = 0;
139 INT32 nWidth = 0;
140 INT32 nHeight = 0;
141
142 if (!gdi_RectToCRgn(rect, &nXDest, &nYDest, &nWidth, &nHeight))
143 return FALSE;
144
145 if (!hdc || !hbr)
146 return FALSE;
147
148 if (!gdi_ClipCoords(hdc, &nXDest, &nYDest, &nWidth, &nHeight, nullptr, nullptr))
149 return TRUE;
150
151 switch (hbr->style)
152 {
153 case GDI_BS_SOLID:
154 {
155 const UINT32 color = hbr->color;
156
157 for (INT32 x = 0; x < nWidth; x++)
158 {
159 BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, nYDest);
160
161 if (dstp)
162 FreeRDPWriteColor(dstp, hdc->format, color);
163 }
164
165 const BYTE* srcp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest);
166 const UINT32 formatSize = FreeRDPGetBytesPerPixel(hdc->format);
167 if (formatSize == 0)
168 return FALSE;
169
170 for (INT32 y = 1; y < nHeight; y++)
171 {
172 BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y);
173 if (!dstp)
174 return FALSE;
175 memcpy(dstp, srcp, 1ull * WINPR_ASSERTING_INT_CAST(size_t, nWidth) * formatSize);
176 }
177 }
178 break;
179
180 case GDI_BS_HATCHED:
181 case GDI_BS_PATTERN:
182 {
183 const BOOL monochrome = (hbr->pattern->format == PIXEL_FORMAT_MONO);
184 const UINT32 formatSize = FreeRDPGetBytesPerPixel(hbr->pattern->format);
185 if (formatSize == 0)
186 return FALSE;
187
188 for (INT32 y = 0; y < nHeight; y++)
189 {
190 for (INT32 x = 0; x < nWidth; x++)
191 {
192 const size_t yOffset =
193 ((1ULL * WINPR_ASSERTING_INT_CAST(size_t, nYDest) +
194 WINPR_ASSERTING_INT_CAST(size_t, y)) *
195 WINPR_ASSERTING_INT_CAST(size_t, hbr->pattern->width) %
196 WINPR_ASSERTING_INT_CAST(size_t, hbr->pattern->height)) *
197 formatSize;
198 const size_t xOffset = ((1ULL * WINPR_ASSERTING_INT_CAST(size_t, nXDest) +
199 WINPR_ASSERTING_INT_CAST(size_t, x)) %
200 WINPR_ASSERTING_INT_CAST(size_t, hbr->pattern->width)) *
201 formatSize;
202 const BYTE* patp = &hbr->pattern->data[yOffset + xOffset];
203
204 UINT32 dstColor = 0;
205 if (monochrome)
206 {
207 if (*patp == 0)
208 dstColor = hdc->bkColor;
209 else
210 dstColor = hdc->textColor;
211 }
212 else
213 {
214 const UINT32 tmp = FreeRDPReadColor(patp, hbr->pattern->format);
215 dstColor =
216 FreeRDPConvertColor(tmp, hbr->pattern->format, hdc->format, nullptr);
217 }
218
219 BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, nYDest + y);
220 if (dstp)
221 FreeRDPWriteColor(dstp, hdc->format, dstColor);
222 }
223 }
224 }
225 break;
226
227 default:
228 break;
229 }
230
231 return gdi_InvalidateRegion(hdc, nXDest, nYDest, nWidth, nHeight);
232}
233
242BOOL gdi_Polygon(WINPR_ATTR_UNUSED HGDI_DC hdc, WINPR_ATTR_UNUSED GDI_POINT* lpPoints,
243 WINPR_ATTR_UNUSED int nCount)
244{
245 WLog_ERR(TAG, "Not implemented!");
246 return FALSE;
247}
248
258BOOL gdi_PolyPolygon(WINPR_ATTR_UNUSED HGDI_DC hdc, WINPR_ATTR_UNUSED GDI_POINT* lpPoints,
259 WINPR_ATTR_UNUSED int* lpPolyCounts, WINPR_ATTR_UNUSED int nCount)
260{
261 WLog_ERR(TAG, "Not implemented!");
262 return FALSE;
263}
264
265BOOL gdi_Rectangle(HGDI_DC hdc, INT32 nXDst, INT32 nYDst, INT32 nWidth, INT32 nHeight)
266{
267 UINT32 color = 0;
268
269 if (!gdi_ClipCoords(hdc, &nXDst, &nYDst, &nWidth, &nHeight, nullptr, nullptr))
270 return TRUE;
271
272 color = hdc->textColor;
273
274 for (INT32 y = 0; y < nHeight; y++)
275 {
276 BYTE* dstLeft = gdi_get_bitmap_pointer(hdc, nXDst, nYDst + y);
277 BYTE* dstRight = gdi_get_bitmap_pointer(hdc, nXDst + nWidth - 1, nYDst + y);
278
279 if (dstLeft)
280 FreeRDPWriteColor(dstLeft, hdc->format, color);
281
282 if (dstRight)
283 FreeRDPWriteColor(dstRight, hdc->format, color);
284 }
285
286 for (INT32 x = 0; x < nWidth; x++)
287 {
288 BYTE* dstTop = gdi_get_bitmap_pointer(hdc, nXDst + x, nYDst);
289 BYTE* dstBottom = gdi_get_bitmap_pointer(hdc, nXDst + x, nYDst + nHeight - 1);
290
291 if (dstTop)
292 FreeRDPWriteColor(dstTop, hdc->format, color);
293
294 if (dstBottom)
295 FreeRDPWriteColor(dstBottom, hdc->format, color);
296 }
297
298 return FALSE;
299}