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 if (!srcp)
167 return FALSE;
168 const UINT32 formatSize = FreeRDPGetBytesPerPixel(hdc->format);
169 if (formatSize == 0)
170 return FALSE;
171
172 for (INT32 y = 1; y < nHeight; y++)
173 {
174 BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y);
175 if (!dstp)
176 return FALSE;
177 memcpy(dstp, srcp, 1ull * WINPR_ASSERTING_INT_CAST(size_t, nWidth) * formatSize);
178 }
179 }
180 break;
181
182 case GDI_BS_HATCHED:
183 case GDI_BS_PATTERN:
184 {
185 const BOOL monochrome = (hbr->pattern->format == PIXEL_FORMAT_MONO);
186 const UINT32 formatSize = FreeRDPGetBytesPerPixel(hbr->pattern->format);
187 if (formatSize == 0)
188 return FALSE;
189 if (hbr->pattern->width <= 0)
190 return FALSE;
191 if (hbr->pattern->height <= 0)
192 return FALSE;
193
194 for (INT32 y = 0; y < nHeight; y++)
195 {
196 for (INT32 x = 0; x < nWidth; x++)
197 {
198 const size_t yOffset =
199 ((1ULL * WINPR_ASSERTING_INT_CAST(size_t, nYDest) +
200 WINPR_ASSERTING_INT_CAST(size_t, y)) *
201 WINPR_ASSERTING_INT_CAST(size_t, hbr->pattern->width) %
202 WINPR_ASSERTING_INT_CAST(size_t, hbr->pattern->height)) *
203 formatSize;
204 const size_t xOffset = ((1ULL * WINPR_ASSERTING_INT_CAST(size_t, nXDest) +
205 WINPR_ASSERTING_INT_CAST(size_t, x)) %
206 WINPR_ASSERTING_INT_CAST(size_t, hbr->pattern->width)) *
207 formatSize;
208 const BYTE* patp = &hbr->pattern->data[yOffset + xOffset];
209
210 UINT32 dstColor = 0;
211 if (monochrome)
212 {
213 if (*patp == 0)
214 dstColor = hdc->bkColor;
215 else
216 dstColor = hdc->textColor;
217 }
218 else
219 {
220 const UINT32 tmp = FreeRDPReadColor(patp, hbr->pattern->format);
221 dstColor =
222 FreeRDPConvertColor(tmp, hbr->pattern->format, hdc->format, nullptr);
223 }
224
225 BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, nYDest + y);
226 if (dstp)
227 FreeRDPWriteColor(dstp, hdc->format, dstColor);
228 }
229 }
230 }
231 break;
232
233 default:
234 break;
235 }
236
237 return gdi_InvalidateRegion(hdc, nXDest, nYDest, nWidth, nHeight);
238}
239
248BOOL gdi_Polygon(WINPR_ATTR_UNUSED HGDI_DC hdc, WINPR_ATTR_UNUSED GDI_POINT* lpPoints,
249 WINPR_ATTR_UNUSED int nCount)
250{
251 WLog_ERR(TAG, "Not implemented!");
252 return FALSE;
253}
254
264BOOL gdi_PolyPolygon(WINPR_ATTR_UNUSED HGDI_DC hdc, WINPR_ATTR_UNUSED GDI_POINT* lpPoints,
265 WINPR_ATTR_UNUSED int* lpPolyCounts, WINPR_ATTR_UNUSED int nCount)
266{
267 WLog_ERR(TAG, "Not implemented!");
268 return FALSE;
269}
270
271BOOL gdi_Rectangle(HGDI_DC hdc, INT32 nXDst, INT32 nYDst, INT32 nWidth, INT32 nHeight)
272{
273 UINT32 color = 0;
274
275 if (!gdi_ClipCoords(hdc, &nXDst, &nYDst, &nWidth, &nHeight, nullptr, nullptr))
276 return TRUE;
277
278 color = hdc->textColor;
279
280 for (INT32 y = 0; y < nHeight; y++)
281 {
282 BYTE* dstLeft = gdi_get_bitmap_pointer(hdc, nXDst, nYDst + y);
283 BYTE* dstRight = gdi_get_bitmap_pointer(hdc, nXDst + nWidth - 1, nYDst + y);
284
285 if (dstLeft)
286 FreeRDPWriteColor(dstLeft, hdc->format, color);
287
288 if (dstRight)
289 FreeRDPWriteColor(dstRight, hdc->format, color);
290 }
291
292 for (INT32 x = 0; x < nWidth; x++)
293 {
294 BYTE* dstTop = gdi_get_bitmap_pointer(hdc, nXDst + x, nYDst);
295 BYTE* dstBottom = gdi_get_bitmap_pointer(hdc, nXDst + x, nYDst + nHeight - 1);
296
297 if (dstTop)
298 FreeRDPWriteColor(dstTop, hdc->format, color);
299
300 if (dstBottom)
301 FreeRDPWriteColor(dstBottom, hdc->format, color);
302 }
303
304 return FALSE;
305}