Coverage Report

Created: 2024-05-20 06:11

/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, x2, y1, 0);
75
0
    gdi_SetPixel(hdc, x1, y1, 0);
76
0
    gdi_SetPixel(hdc, x1, y2, 0);
77
0
    gdi_SetPixel(hdc, x2, y2, 0);
78
0
    e2 = 2 * e;
79
80
0
    if (e2 >= dx)
81
0
    {
82
0
      x1++;
83
0
      x2--;
84
0
      e += dx += c;
85
0
    }
86
87
0
    if (e2 <= dy)
88
0
    {
89
0
      y1++;
90
0
      y2--;
91
0
      e += dy += a;
92
0
    }
93
0
  } while (x1 <= x2);
94
95
0
  while (y1 - y2 < b)
96
0
  {
97
0
    gdi_SetPixel(hdc, x1 - 1, ++y1, 0);
98
0
    gdi_SetPixel(hdc, x1 - 1, --y2, 0);
99
0
  }
100
0
}
101
102
/**
103
 * Draw an ellipse
104
 * msdn{dd162510}
105
 *
106
 * @param hdc device context
107
 * @param nLeftRect x1
108
 * @param nTopRect y1
109
 * @param nRightRect x2
110
 * @param nBottomRect y2
111
 *
112
 * @return nonzero if successful, 0 otherwise
113
 */
114
BOOL gdi_Ellipse(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect)
115
0
{
116
0
  Ellipse_Bresenham(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
117
0
  return TRUE;
118
0
}
119
120
/**
121
 * Fill a rectangle with the given brush.
122
 * msdn{dd162719}
123
 *
124
 * @param hdc device context
125
 * @param rect rectangle
126
 * @param hbr brush
127
 *
128
 * @return nonzero if successful, 0 otherwise
129
 */
130
131
BOOL gdi_FillRect(HGDI_DC hdc, const HGDI_RECT rect, HGDI_BRUSH hbr)
132
0
{
133
0
  UINT32 color = 0;
134
0
  UINT32 dstColor = 0;
135
0
  BOOL monochrome = FALSE;
136
0
  INT32 nXDest = 0;
137
0
  INT32 nYDest = 0;
138
0
  INT32 nWidth = 0;
139
0
  INT32 nHeight = 0;
140
0
  const BYTE* srcp = NULL;
141
0
  DWORD formatSize = 0;
142
0
  gdi_RectToCRgn(rect, &nXDest, &nYDest, &nWidth, &nHeight);
143
144
0
  if (!hdc || !hbr)
145
0
    return FALSE;
146
147
0
  if (!gdi_ClipCoords(hdc, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL))
148
0
    return TRUE;
149
150
0
  switch (hbr->style)
151
0
  {
152
0
    case GDI_BS_SOLID:
153
0
      color = hbr->color;
154
155
0
      for (INT32 x = 0; x < nWidth; x++)
156
0
      {
157
0
        BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, nYDest);
158
159
0
        if (dstp)
160
0
          FreeRDPWriteColor(dstp, hdc->format, color);
161
0
      }
162
163
0
      srcp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest);
164
0
      formatSize = FreeRDPGetBytesPerPixel(hdc->format);
165
166
0
      for (INT32 y = 1; y < nHeight; y++)
167
0
      {
168
0
        BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y);
169
0
        memcpy(dstp, srcp, 1ull * nWidth * formatSize);
170
0
      }
171
172
0
      break;
173
174
0
    case GDI_BS_HATCHED:
175
0
    case GDI_BS_PATTERN:
176
0
      monochrome = (hbr->pattern->format == PIXEL_FORMAT_MONO);
177
0
      formatSize = FreeRDPGetBytesPerPixel(hbr->pattern->format);
178
179
0
      for (INT32 y = 0; y < nHeight; y++)
180
0
      {
181
0
        for (INT32 x = 0; x < nWidth; x++)
182
0
        {
183
0
          const UINT32 yOffset =
184
0
              ((nYDest + y) * hbr->pattern->width % hbr->pattern->height) * formatSize;
185
0
          const UINT32 xOffset = ((nXDest + x) % hbr->pattern->width) * formatSize;
186
0
          const BYTE* patp = &hbr->pattern->data[yOffset + xOffset];
187
0
          BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, nYDest + y);
188
189
0
          if (!patp)
190
0
            return FALSE;
191
192
0
          if (monochrome)
193
0
          {
194
0
            if (*patp == 0)
195
0
              dstColor = hdc->bkColor;
196
0
            else
197
0
              dstColor = hdc->textColor;
198
0
          }
199
0
          else
200
0
          {
201
0
            dstColor = FreeRDPReadColor(patp, hbr->pattern->format);
202
0
            dstColor =
203
0
                FreeRDPConvertColor(dstColor, hbr->pattern->format, hdc->format, NULL);
204
0
          }
205
206
0
          if (dstp)
207
0
            FreeRDPWriteColor(dstp, hdc->format, dstColor);
208
0
        }
209
0
      }
210
211
0
      break;
212
213
0
    default:
214
0
      break;
215
0
  }
216
217
0
  if (!gdi_InvalidateRegion(hdc, nXDest, nYDest, nWidth, nHeight))
218
0
    return FALSE;
219
220
0
  return TRUE;
221
0
}
222
223
/**
224
 * Draw a polygon
225
 * msdn{dd162814}
226
 * @param hdc device context
227
 * @param lpPoints array of points
228
 * @param nCount number of points
229
 * @return nonzero if successful, 0 otherwise
230
 */
231
BOOL gdi_Polygon(HGDI_DC hdc, GDI_POINT* lpPoints, int nCount)
232
0
{
233
0
  WLog_ERR(TAG, "Not implemented!");
234
0
  return FALSE;
235
0
}
236
237
/**
238
 * Draw a series of closed polygons
239
 * msdn{dd162818}
240
 * @param hdc device context
241
 * @param lpPoints array of series of points
242
 * @param lpPolyCounts array of number of points in each series
243
 * @param nCount count of number of points in lpPolyCounts
244
 * @return nonzero if successful, 0 otherwise
245
 */
246
BOOL gdi_PolyPolygon(HGDI_DC hdc, GDI_POINT* lpPoints, int* lpPolyCounts, int nCount)
247
0
{
248
0
  WLog_ERR(TAG, "Not implemented!");
249
0
  return FALSE;
250
0
}
251
252
BOOL gdi_Rectangle(HGDI_DC hdc, INT32 nXDst, INT32 nYDst, INT32 nWidth, INT32 nHeight)
253
0
{
254
0
  UINT32 color = 0;
255
256
0
  if (!gdi_ClipCoords(hdc, &nXDst, &nYDst, &nWidth, &nHeight, NULL, NULL))
257
0
    return TRUE;
258
259
0
  color = hdc->textColor;
260
261
0
  for (INT32 y = 0; y < nHeight; y++)
262
0
  {
263
0
    BYTE* dstLeft = gdi_get_bitmap_pointer(hdc, nXDst, nYDst + y);
264
0
    BYTE* dstRight = gdi_get_bitmap_pointer(hdc, nXDst + nWidth - 1, nYDst + y);
265
266
0
    if (dstLeft)
267
0
      FreeRDPWriteColor(dstLeft, hdc->format, color);
268
269
0
    if (dstRight)
270
0
      FreeRDPWriteColor(dstRight, hdc->format, color);
271
0
  }
272
273
0
  for (INT32 x = 0; x < nWidth; x++)
274
0
  {
275
0
    BYTE* dstTop = gdi_get_bitmap_pointer(hdc, nXDst + x, nYDst);
276
0
    BYTE* dstBottom = gdi_get_bitmap_pointer(hdc, nXDst + x, nYDst + nHeight - 1);
277
278
0
    if (dstTop)
279
0
      FreeRDPWriteColor(dstTop, hdc->format, color);
280
281
0
    if (dstBottom)
282
0
      FreeRDPWriteColor(dstBottom, hdc->format, color);
283
0
  }
284
285
0
  return FALSE;
286
0
}