Coverage Report

Created: 2025-07-01 06:46

/src/FreeRDP/libfreerdp/gdi/shape.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * GDI Shape Functions
4
 *
5
 * Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 * Copyright 2016 Armin Novak <armin.novak@thincast.com>
7
 * Copyright 2016 Thincast Technologies GmbH
8
 *
9
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 * you may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 *     http://www.apache.org/licenses/LICENSE-2.0
14
 *
15
 * Unless required by applicable law or agreed to in writing, software
16
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 * See the License for the specific language governing permissions and
19
 * limitations under the License.
20
 */
21
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
42
static void Ellipse_Bresenham(HGDI_DC hdc, int x1, int y1, int x2, int y2)
43
0
{
44
0
  INT32 e = 0;
45
0
  INT32 e2 = 0;
46
0
  INT32 dx = 0;
47
0
  INT32 dy = 0;
48
0
  INT32 a = 0;
49
0
  INT32 b = 0;
50
0
  INT32 c = 0;
51
0
  a = (x1 < x2) ? x2 - x1 : x1 - x2;
52
0
  b = (y1 < y2) ? y2 - y1 : y1 - y2;
53
0
  c = b & 1;
54
0
  dx = 4 * (1 - a) * b * b;
55
0
  dy = 4 * (c + 1) * a * a;
56
0
  e = dx + dy + c * a * a;
57
58
0
  if (x1 > x2)
59
0
  {
60
0
    x1 = x2;
61
0
    x2 += a;
62
0
  }
63
64
0
  if (y1 > y2)
65
0
    y1 = y2;
66
67
0
  y1 += (b + 1) / 2;
68
0
  y2 = y1 - c;
69
0
  a *= 8 * a;
70
0
  c = 8 * b * b;
71
72
0
  do
73
0
  {
74
0
    gdi_SetPixel(hdc, WINPR_ASSERTING_INT_CAST(UINT32, x2),
75
0
                 WINPR_ASSERTING_INT_CAST(UINT32, y1), 0);
76
0
    gdi_SetPixel(hdc, WINPR_ASSERTING_INT_CAST(UINT32, x1),
77
0
                 WINPR_ASSERTING_INT_CAST(UINT32, y1), 0);
78
0
    gdi_SetPixel(hdc, WINPR_ASSERTING_INT_CAST(UINT32, x1),
79
0
                 WINPR_ASSERTING_INT_CAST(UINT32, y2), 0);
80
0
    gdi_SetPixel(hdc, WINPR_ASSERTING_INT_CAST(UINT32, x2),
81
0
                 WINPR_ASSERTING_INT_CAST(UINT32, y2), 0);
82
0
    e2 = 2 * e;
83
84
0
    if (e2 >= dx)
85
0
    {
86
0
      x1++;
87
0
      x2--;
88
0
      e += dx += c;
89
0
    }
90
91
0
    if (e2 <= dy)
92
0
    {
93
0
      y1++;
94
0
      y2--;
95
0
      e += dy += a;
96
0
    }
97
0
  } while (x1 <= x2);
98
99
0
  while (y1 - y2 < b)
100
0
  {
101
0
    y1++;
102
0
    y2--;
103
104
0
    gdi_SetPixel(hdc, WINPR_ASSERTING_INT_CAST(uint32_t, x1 - 1),
105
0
                 WINPR_ASSERTING_INT_CAST(uint32_t, y1), 0);
106
0
    gdi_SetPixel(hdc, WINPR_ASSERTING_INT_CAST(uint32_t, x1 - 1),
107
0
                 WINPR_ASSERTING_INT_CAST(uint32_t, y2), 0);
108
0
  }
109
0
}
110
111
/**
112
 * Draw an ellipse
113
 * msdn{dd162510}
114
 *
115
 * @param hdc device context
116
 * @param nLeftRect x1
117
 * @param nTopRect y1
118
 * @param nRightRect x2
119
 * @param nBottomRect y2
120
 *
121
 * @return nonzero if successful, 0 otherwise
122
 */
123
BOOL gdi_Ellipse(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect)
124
0
{
125
0
  Ellipse_Bresenham(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
126
0
  return TRUE;
127
0
}
128
129
/**
130
 * Fill a rectangle with the given brush.
131
 * msdn{dd162719}
132
 *
133
 * @param hdc device context
134
 * @param rect rectangle
135
 * @param hbr brush
136
 *
137
 * @return nonzero if successful, 0 otherwise
138
 */
139
140
BOOL gdi_FillRect(HGDI_DC hdc, const GDI_RECT* rect, HGDI_BRUSH hbr)
141
0
{
142
0
  UINT32 color = 0;
143
0
  UINT32 dstColor = 0;
144
0
  BOOL monochrome = FALSE;
145
0
  INT32 nXDest = 0;
146
0
  INT32 nYDest = 0;
147
0
  INT32 nWidth = 0;
148
0
  INT32 nHeight = 0;
149
0
  const BYTE* srcp = NULL;
150
0
  DWORD formatSize = 0;
151
0
  gdi_RectToCRgn(rect, &nXDest, &nYDest, &nWidth, &nHeight);
152
153
0
  if (!hdc || !hbr)
154
0
    return FALSE;
155
156
0
  if (!gdi_ClipCoords(hdc, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL))
157
0
    return TRUE;
158
159
0
  switch (hbr->style)
160
0
  {
161
0
    case GDI_BS_SOLID:
162
0
      color = hbr->color;
163
164
0
      for (INT32 x = 0; x < nWidth; x++)
165
0
      {
166
0
        BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, nYDest);
167
168
0
        if (dstp)
169
0
          FreeRDPWriteColor(dstp, hdc->format, color);
170
0
      }
171
172
0
      srcp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest);
173
0
      formatSize = FreeRDPGetBytesPerPixel(hdc->format);
174
175
0
      for (INT32 y = 1; y < nHeight; y++)
176
0
      {
177
0
        BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y);
178
0
        memcpy(dstp, srcp, 1ull * WINPR_ASSERTING_INT_CAST(size_t, nWidth) * formatSize);
179
0
      }
180
181
0
      break;
182
183
0
    case GDI_BS_HATCHED:
184
0
    case GDI_BS_PATTERN:
185
0
      monochrome = (hbr->pattern->format == PIXEL_FORMAT_MONO);
186
0
      formatSize = FreeRDPGetBytesPerPixel(hbr->pattern->format);
187
188
0
      for (INT32 y = 0; y < nHeight; y++)
189
0
      {
190
0
        for (INT32 x = 0; x < nWidth; x++)
191
0
        {
192
0
          const size_t yOffset =
193
0
              ((1ULL * WINPR_ASSERTING_INT_CAST(size_t, nYDest) +
194
0
                WINPR_ASSERTING_INT_CAST(size_t, y)) *
195
0
               WINPR_ASSERTING_INT_CAST(size_t, hbr->pattern->width) %
196
0
               WINPR_ASSERTING_INT_CAST(size_t, hbr->pattern->height)) *
197
0
              formatSize;
198
0
          const size_t xOffset = ((1ULL * WINPR_ASSERTING_INT_CAST(size_t, nXDest) +
199
0
                                   WINPR_ASSERTING_INT_CAST(size_t, x)) %
200
0
                                  WINPR_ASSERTING_INT_CAST(size_t, hbr->pattern->width)) *
201
0
                                 formatSize;
202
0
          const BYTE* patp = &hbr->pattern->data[yOffset + xOffset];
203
204
0
          if (monochrome)
205
0
          {
206
0
            if (*patp == 0)
207
0
              dstColor = hdc->bkColor;
208
0
            else
209
0
              dstColor = hdc->textColor;
210
0
          }
211
0
          else
212
0
          {
213
0
            dstColor = FreeRDPReadColor(patp, hbr->pattern->format);
214
0
            dstColor =
215
0
                FreeRDPConvertColor(dstColor, hbr->pattern->format, hdc->format, NULL);
216
0
          }
217
218
0
          BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, nYDest + y);
219
0
          if (dstp)
220
0
            FreeRDPWriteColor(dstp, hdc->format, dstColor);
221
0
        }
222
0
      }
223
224
0
      break;
225
226
0
    default:
227
0
      break;
228
0
  }
229
230
0
  if (!gdi_InvalidateRegion(hdc, nXDest, nYDest, nWidth, nHeight))
231
0
    return FALSE;
232
233
0
  return TRUE;
234
0
}
235
236
/**
237
 * Draw a polygon
238
 * msdn{dd162814}
239
 * @param hdc device context
240
 * @param lpPoints array of points
241
 * @param nCount number of points
242
 * @return nonzero if successful, 0 otherwise
243
 */
244
BOOL gdi_Polygon(WINPR_ATTR_UNUSED HGDI_DC hdc, WINPR_ATTR_UNUSED GDI_POINT* lpPoints,
245
                 WINPR_ATTR_UNUSED int nCount)
246
0
{
247
0
  WLog_ERR(TAG, "Not implemented!");
248
0
  return FALSE;
249
0
}
250
251
/**
252
 * Draw a series of closed polygons
253
 * msdn{dd162818}
254
 * @param hdc device context
255
 * @param lpPoints array of series of points
256
 * @param lpPolyCounts array of number of points in each series
257
 * @param nCount count of number of points in lpPolyCounts
258
 * @return nonzero if successful, 0 otherwise
259
 */
260
BOOL gdi_PolyPolygon(WINPR_ATTR_UNUSED HGDI_DC hdc, WINPR_ATTR_UNUSED GDI_POINT* lpPoints,
261
                     WINPR_ATTR_UNUSED int* lpPolyCounts, WINPR_ATTR_UNUSED int nCount)
262
0
{
263
0
  WLog_ERR(TAG, "Not implemented!");
264
0
  return FALSE;
265
0
}
266
267
BOOL gdi_Rectangle(HGDI_DC hdc, INT32 nXDst, INT32 nYDst, INT32 nWidth, INT32 nHeight)
268
0
{
269
0
  UINT32 color = 0;
270
271
0
  if (!gdi_ClipCoords(hdc, &nXDst, &nYDst, &nWidth, &nHeight, NULL, NULL))
272
0
    return TRUE;
273
274
0
  color = hdc->textColor;
275
276
0
  for (INT32 y = 0; y < nHeight; y++)
277
0
  {
278
0
    BYTE* dstLeft = gdi_get_bitmap_pointer(hdc, nXDst, nYDst + y);
279
0
    BYTE* dstRight = gdi_get_bitmap_pointer(hdc, nXDst + nWidth - 1, nYDst + y);
280
281
0
    if (dstLeft)
282
0
      FreeRDPWriteColor(dstLeft, hdc->format, color);
283
284
0
    if (dstRight)
285
0
      FreeRDPWriteColor(dstRight, hdc->format, color);
286
0
  }
287
288
0
  for (INT32 x = 0; x < nWidth; x++)
289
0
  {
290
0
    BYTE* dstTop = gdi_get_bitmap_pointer(hdc, nXDst + x, nYDst);
291
0
    BYTE* dstBottom = gdi_get_bitmap_pointer(hdc, nXDst + x, nYDst + nHeight - 1);
292
293
0
    if (dstTop)
294
0
      FreeRDPWriteColor(dstTop, hdc->format, color);
295
296
0
    if (dstBottom)
297
0
      FreeRDPWriteColor(dstBottom, hdc->format, color);
298
0
  }
299
300
0
  return FALSE;
301
0
}