Coverage Report

Created: 2023-09-25 06:56

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