GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/*************************************************************************** |
||
2 |
* Copyright (c) 2024 Microsoft Corporation |
||
3 |
* |
||
4 |
* This program and the accompanying materials are made available under the |
||
5 |
* terms of the MIT License which is available at |
||
6 |
* https://opensource.org/licenses/MIT. |
||
7 |
* |
||
8 |
* SPDX-License-Identifier: MIT |
||
9 |
**************************************************************************/ |
||
10 |
|||
11 |
|||
12 |
/**************************************************************************/ |
||
13 |
/**************************************************************************/ |
||
14 |
/** */ |
||
15 |
/** GUIX Component */ |
||
16 |
/** */ |
||
17 |
/** Display Management (Display) */ |
||
18 |
/** */ |
||
19 |
/**************************************************************************/ |
||
20 |
|||
21 |
#define GX_SOURCE_CODE |
||
22 |
|||
23 |
|||
24 |
/* Include necessary system files. */ |
||
25 |
|||
26 |
#include "gx_api.h" |
||
27 |
#include "gx_display.h" |
||
28 |
#include "gx_utility.h" |
||
29 |
|||
30 |
|||
31 |
/**************************************************************************/ |
||
32 |
/* */ |
||
33 |
/* FUNCTION RELEASE */ |
||
34 |
/* */ |
||
35 |
/* _gx_display_driver_generic_aliased_fixed_point_line_draw */ |
||
36 |
/* PORTABLE C */ |
||
37 |
/* 6.1.7 */ |
||
38 |
/* AUTHOR */ |
||
39 |
/* */ |
||
40 |
/* Kenneth Maxwell, Microsoft Corporation */ |
||
41 |
/* */ |
||
42 |
/* DESCRIPTION */ |
||
43 |
/* */ |
||
44 |
/* General anti-aliasing line drawing function. */ |
||
45 |
/* */ |
||
46 |
/* INPUT */ |
||
47 |
/* */ |
||
48 |
/* context Drawing context */ |
||
49 |
/* xstart x-coord of endpoint */ |
||
50 |
/* ystart y-coord of endpoint */ |
||
51 |
/* xend x-coord of endpoint */ |
||
52 |
/* yend y-coord of endpoint */ |
||
53 |
/* */ |
||
54 |
/* OUTPUT */ |
||
55 |
/* */ |
||
56 |
/* None */ |
||
57 |
/* */ |
||
58 |
/* CALLS */ |
||
59 |
/* */ |
||
60 |
/* [gx_display_driver_pixel_blend] Display driver blend function */ |
||
61 |
/* _gx_utility_rectangle_point_detect Detect whether a pixel is */ |
||
62 |
/* inside rectangle */ |
||
63 |
/* GX_SWAP_VALS Swap two values */ |
||
64 |
/* [gx_display_driver_simple_line_draw] Basic display driver simple */ |
||
65 |
/* line draw function */ |
||
66 |
/* */ |
||
67 |
/* CALLED BY */ |
||
68 |
/* */ |
||
69 |
/* GUIX Internal Code */ |
||
70 |
/* */ |
||
71 |
/* RELEASE HISTORY */ |
||
72 |
/* */ |
||
73 |
/* DATE NAME DESCRIPTION */ |
||
74 |
/* */ |
||
75 |
/* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */ |
||
76 |
/* 09-30-2020 Kenneth Maxwell Modified comment(s), */ |
||
77 |
/* resulting in version 6.1 */ |
||
78 |
/* 06-02-2021 Ting Zhu Modified comment(s), */ |
||
79 |
/* fixed compile warnings, */ |
||
80 |
/* resulting in version 6.1.7 */ |
||
81 |
/* */ |
||
82 |
/**************************************************************************/ |
||
83 |
20839 |
VOID _gx_display_driver_generic_aliased_fixed_point_line_draw(GX_DRAW_CONTEXT *context, |
|
84 |
GX_FIXED_VAL xstart, GX_FIXED_VAL ystart, |
||
85 |
GX_FIXED_VAL xend, GX_FIXED_VAL yend) |
||
86 |
{ |
||
87 |
20839 |
GX_BRUSH *brush = &context -> gx_draw_context_brush; |
|
88 |
20839 |
GX_COLOR line_color = brush -> gx_brush_line_color; |
|
89 |
20839 |
GX_RECTANGLE *clip = context -> gx_draw_context_clip; |
|
90 |
|||
91 |
VOID (*blend_func)(GX_DRAW_CONTEXT *context, |
||
92 |
INT x, INT y, GX_COLOR color, GX_UBYTE alpha); |
||
93 |
|||
94 |
20839 |
GX_FIXED_VAL dx = GX_ABS(xend - xstart); |
|
95 |
20839 |
GX_FIXED_VAL dy = GX_ABS(yend - ystart); |
|
96 |
GX_FIXED_VAL x_fraction; |
||
97 |
GX_FIXED_VAL y_fraction; |
||
98 |
GX_POINT point; |
||
99 |
GX_POINT point2; |
||
100 |
20839 |
INT curx = 0; |
|
101 |
20839 |
INT cury = 0; |
|
102 |
INT decision; |
||
103 |
INT back_alpha; |
||
104 |
INT fore_alpha; |
||
105 |
INT x_sign; |
||
106 |
INT y_sign; |
||
107 |
|||
108 |
#if defined(GX_BRUSH_ALPHA_SUPPORT) |
||
109 |
GX_UBYTE brush_alpha; |
||
110 |
|||
111 |
20839 |
brush_alpha = context -> gx_draw_context_brush.gx_brush_alpha; |
|
112 |
|||
113 |
✓✓ | 20839 |
if (brush_alpha == 0) |
114 |
{ |
||
115 |
/* Nothing to draw here. */ |
||
116 |
4 |
return; |
|
117 |
} |
||
118 |
#endif |
||
119 |
|||
120 |
✓✓✓✓ |
20838 |
if (!dx || !dy) |
121 |
{ |
||
122 |
2 |
return; |
|
123 |
} |
||
124 |
|||
125 |
20836 |
blend_func = context -> gx_draw_context_display -> gx_display_driver_pixel_blend; |
|
126 |
|||
127 |
✓✓ | 20836 |
if (blend_func == GX_NULL) |
128 |
{ |
||
129 |
1 |
return; |
|
130 |
} |
||
131 |
|||
132 |
✓✓✓✓ ✓✓✓✓ |
20835 |
if (((dx >= dy && (xstart > xend)) || ((dy > dx) && ystart > yend))) |
133 |
{ |
||
134 |
10418 |
GX_SWAP_VALS(xend, xstart); |
|
135 |
10418 |
GX_SWAP_VALS(yend, ystart); |
|
136 |
} |
||
137 |
|||
138 |
20835 |
x_sign = (xend - xstart) / dx; |
|
139 |
20835 |
y_sign = (yend - ystart) / dy; |
|
140 |
|||
141 |
20835 |
x_fraction = (xstart & GX_FIXED_VAL_FRACTION_MASK); |
|
142 |
20835 |
y_fraction = (ystart & GX_FIXED_VAL_FRACTION_MASK); |
|
143 |
|||
144 |
✓✓ | 20835 |
if (dx >= dy) |
145 |
{ |
||
146 |
11022 |
point.gx_point_x = (GX_VALUE)GX_FIXED_VAL_TO_INT(xstart); |
|
147 |
11022 |
point2.gx_point_x = (GX_VALUE)GX_FIXED_VAL_RND_UP(xend); |
|
148 |
|||
149 |
✓✓ | 11022 |
if (y_sign < 0) |
150 |
{ |
||
151 |
5774 |
point.gx_point_y = (GX_VALUE)GX_FIXED_VAL_RND_UP(ystart); |
|
152 |
5774 |
point2.gx_point_y = (GX_VALUE)GX_FIXED_VAL_TO_INT(yend); |
|
153 |
|||
154 |
✓✓ | 5774 |
if (y_fraction) |
155 |
{ |
||
156 |
5708 |
y_fraction = GX_FIXED_VAL_ONE - y_fraction; |
|
157 |
} |
||
158 |
} |
||
159 |
else |
||
160 |
{ |
||
161 |
5248 |
point.gx_point_y = (GX_VALUE)GX_FIXED_VAL_TO_INT(ystart); |
|
162 |
5248 |
point2.gx_point_y = (GX_VALUE)GX_FIXED_VAL_RND_UP(yend); |
|
163 |
} |
||
164 |
|||
165 |
11022 |
decision = (y_fraction * dx - x_fraction * dy) / GX_FIXED_VAL_ONE; |
|
166 |
|||
167 |
11022 |
cury = point.gx_point_y; |
|
168 |
|||
169 |
✓✓ | 11022 |
if (decision < 0) |
170 |
{ |
||
171 |
2370 |
decision += dx; |
|
172 |
2370 |
cury -= y_sign; |
|
173 |
} |
||
174 |
} |
||
175 |
else |
||
176 |
{ |
||
177 |
9813 |
point.gx_point_y = (GX_VALUE)GX_FIXED_VAL_TO_INT(ystart); |
|
178 |
9813 |
point2.gx_point_y = (GX_VALUE)GX_FIXED_VAL_RND_UP(yend); |
|
179 |
|||
180 |
✓✓ | 9813 |
if (x_sign < 0) |
181 |
{ |
||
182 |
4643 |
point.gx_point_x = (GX_VALUE)GX_FIXED_VAL_RND_UP(xstart); |
|
183 |
4643 |
point2.gx_point_x = (GX_VALUE)GX_FIXED_VAL_TO_INT(xend); |
|
184 |
|||
185 |
✓✓ | 4643 |
if (x_fraction) |
186 |
{ |
||
187 |
4642 |
x_fraction = GX_FIXED_VAL_FRACTION_MASK - x_fraction; |
|
188 |
} |
||
189 |
} |
||
190 |
else |
||
191 |
{ |
||
192 |
5170 |
point.gx_point_x = (GX_VALUE)GX_FIXED_VAL_TO_INT(xstart); |
|
193 |
5170 |
point2.gx_point_x = (GX_VALUE)GX_FIXED_VAL_RND_UP(xend); |
|
194 |
} |
||
195 |
|||
196 |
9813 |
decision = (x_fraction * dy - y_fraction * dx) / GX_FIXED_VAL_ONE; |
|
197 |
|||
198 |
9813 |
curx = point.gx_point_x; |
|
199 |
|||
200 |
✓✓ | 9813 |
if (decision < 0) |
201 |
{ |
||
202 |
1938 |
decision += dy; |
|
203 |
1938 |
curx -= x_sign; |
|
204 |
} |
||
205 |
} |
||
206 |
|||
207 |
✓✓✓✓ |
39746 |
if (_gx_utility_rectangle_point_detect(clip, point) && |
208 |
18911 |
_gx_utility_rectangle_point_detect(clip, point2)) |
|
209 |
{ |
||
210 |
/* both endpoints are inside clip rectangle. We don't need to clip |
||
211 |
inside the inner loop */ |
||
212 |
✓✓ | 17603 |
if (dx >= dy) |
213 |
{ |
||
214 |
/* handle end points separately. */ |
||
215 |
|||
216 |
/* draw anti-aliased line along x axis, no clipping */ |
||
217 |
✓✓ | 433161 |
for (curx = point.gx_point_x; curx <= point2.gx_point_x; curx++, decision += dy) |
218 |
{ |
||
219 |
✓✓ | 423769 |
if (decision >= dx) |
220 |
{ |
||
221 |
219767 |
decision -= dx; |
|
222 |
219767 |
cury += y_sign; |
|
223 |
} |
||
224 |
|||
225 |
423769 |
back_alpha = ((decision << 8) / dx); |
|
226 |
|||
227 |
423769 |
fore_alpha = 255 - back_alpha; |
|
228 |
|||
229 |
✓✓✓✓ ✓✓ |
423769 |
if ((curx == point.gx_point_x || curx == point2.gx_point_x) && x_fraction) |
230 |
{ |
||
231 |
18394 |
fore_alpha = fore_alpha * (GX_FIXED_VAL_ONE - x_fraction) / GX_FIXED_VAL_ONE; |
|
232 |
18394 |
back_alpha = back_alpha * (GX_FIXED_VAL_ONE - x_fraction) / GX_FIXED_VAL_ONE; |
|
233 |
18394 |
x_fraction = GX_FIXED_VAL_ONE - (xend & GX_FIXED_VAL_FRACTION_MASK); |
|
234 |
} |
||
235 |
|||
236 |
#if defined(GX_BRUSH_ALPHA_SUPPORT) |
||
237 |
423769 |
fore_alpha = (GX_UBYTE)(brush_alpha * fore_alpha / 255); |
|
238 |
423769 |
back_alpha = (GX_UBYTE)(brush_alpha * back_alpha / 255); |
|
239 |
#endif |
||
240 |
423769 |
blend_func(context, curx, cury, line_color, (GX_UBYTE)fore_alpha); |
|
241 |
423769 |
blend_func(context, curx, cury + y_sign, line_color, (GX_UBYTE)back_alpha); |
|
242 |
} |
||
243 |
} |
||
244 |
else |
||
245 |
{ |
||
246 |
/* draw anti-aliased line along y axis, no clipping */ |
||
247 |
✓✓ | 416109 |
for (cury = point.gx_point_y; cury <= point2.gx_point_y; cury++, decision += dx) |
248 |
{ |
||
249 |
✓✓ | 407898 |
if (decision >= dy) |
250 |
{ |
||
251 |
150775 |
decision -= dy; |
|
252 |
150775 |
curx += x_sign; |
|
253 |
} |
||
254 |
|||
255 |
407898 |
back_alpha = ((decision << 8) / dy); |
|
256 |
407898 |
fore_alpha = 255 - back_alpha; |
|
257 |
|||
258 |
✓✓✓✓ ✓✓ |
407898 |
if ((cury == point.gx_point_y || cury == point2.gx_point_y) && y_fraction) |
259 |
{ |
||
260 |
15940 |
fore_alpha = fore_alpha * (GX_FIXED_VAL_ONE - y_fraction) / GX_FIXED_VAL_ONE; |
|
261 |
15940 |
back_alpha = back_alpha * (GX_FIXED_VAL_ONE - y_fraction) / GX_FIXED_VAL_ONE; |
|
262 |
15940 |
y_fraction = GX_FIXED_VAL_ONE - (yend & GX_FIXED_VAL_FRACTION_MASK); |
|
263 |
} |
||
264 |
|||
265 |
#if defined(GX_BRUSH_ALPHA_SUPPORT) |
||
266 |
407898 |
fore_alpha = (GX_UBYTE)(brush_alpha * fore_alpha / 255); |
|
267 |
407898 |
back_alpha = (GX_UBYTE)(brush_alpha * back_alpha / 255); |
|
268 |
#endif |
||
269 |
407898 |
blend_func(context, curx, cury, line_color, (GX_UBYTE)fore_alpha); |
|
270 |
407898 |
blend_func(context, curx + x_sign, cury, line_color, (GX_UBYTE)back_alpha); |
|
271 |
} |
||
272 |
} |
||
273 |
} |
||
274 |
else |
||
275 |
{ |
||
276 |
✓✓ | 3232 |
if (dx >= dy) |
277 |
{ |
||
278 |
/* draw anti-aliased line along x axis, clipping in the inner loop */ |
||
279 |
✓✓ | 106340 |
for (curx = point.gx_point_x; curx <= point2.gx_point_x; curx++, decision += dy) |
280 |
{ |
||
281 |
✓✓ | 104710 |
if (decision >= dx) |
282 |
{ |
||
283 |
56522 |
decision -= dx; |
|
284 |
56522 |
cury += y_sign; |
|
285 |
} |
||
286 |
|||
287 |
104710 |
back_alpha = ((decision << 8) / dx); |
|
288 |
104710 |
fore_alpha = 255 - back_alpha; |
|
289 |
|||
290 |
✓✓✓✓ ✓✓ |
104710 |
if ((curx == point.gx_point_x || curx == point2.gx_point_x) && x_fraction) |
291 |
{ |
||
292 |
3236 |
fore_alpha = fore_alpha * (GX_FIXED_VAL_ONE - x_fraction) / GX_FIXED_VAL_ONE; |
|
293 |
3236 |
back_alpha = back_alpha * (GX_FIXED_VAL_ONE - x_fraction) / GX_FIXED_VAL_ONE; |
|
294 |
3236 |
x_fraction = GX_FIXED_VAL_ONE - (xend & GX_FIXED_VAL_FRACTION_MASK); |
|
295 |
} |
||
296 |
|||
297 |
#if defined(GX_BRUSH_ALPHA_SUPPORT) |
||
298 |
104710 |
fore_alpha = (GX_UBYTE)(brush_alpha * fore_alpha / 255); |
|
299 |
104710 |
back_alpha = (GX_UBYTE)(brush_alpha * back_alpha / 255); |
|
300 |
#endif |
||
301 |
✓✓ | 104710 |
if (curx >= clip -> gx_rectangle_left && |
302 |
✓✓ | 78889 |
curx <= clip -> gx_rectangle_right && |
303 |
✓✓ | 44753 |
cury >= clip -> gx_rectangle_top && |
304 |
✓✓ | 44563 |
cury <= clip -> gx_rectangle_bottom) |
305 |
{ |
||
306 |
43247 |
blend_func(context, curx, cury, line_color, (GX_UBYTE)fore_alpha); |
|
307 |
} |
||
308 |
|||
309 |
✓✓ | 104710 |
if (curx >= clip -> gx_rectangle_left && |
310 |
✓✓ | 78889 |
curx <= clip -> gx_rectangle_right && |
311 |
✓✓ | 44753 |
(cury + y_sign) >= clip -> gx_rectangle_top && |
312 |
✓✓ | 44563 |
(cury + y_sign) <= clip -> gx_rectangle_bottom) |
313 |
{ |
||
314 |
43232 |
blend_func(context, curx, cury + y_sign, line_color, (GX_UBYTE)back_alpha); |
|
315 |
} |
||
316 |
} |
||
317 |
} |
||
318 |
else |
||
319 |
{ |
||
320 |
✓✓ | 137805 |
for (cury = point.gx_point_y; cury <= point2.gx_point_y; cury++, decision += dx) |
321 |
{ |
||
322 |
✓✓ | 136203 |
if (decision >= dy) |
323 |
{ |
||
324 |
84923 |
decision -= dy; |
|
325 |
84923 |
curx += x_sign; |
|
326 |
} |
||
327 |
|||
328 |
136203 |
back_alpha = ((decision << 8) / dy); |
|
329 |
136203 |
fore_alpha = 255 - back_alpha; |
|
330 |
|||
331 |
✓✓✓✓ ✓✓ |
136203 |
if ((cury == point.gx_point_y || cury == point2.gx_point_y) && y_fraction) |
332 |
{ |
||
333 |
3108 |
fore_alpha = fore_alpha * (GX_FIXED_VAL_ONE - y_fraction) / GX_FIXED_VAL_ONE; |
|
334 |
3108 |
back_alpha = back_alpha * (GX_FIXED_VAL_ONE - y_fraction) / GX_FIXED_VAL_ONE; |
|
335 |
3108 |
y_fraction = GX_FIXED_VAL_ONE - (yend & GX_FIXED_VAL_FRACTION_MASK); |
|
336 |
} |
||
337 |
|||
338 |
#if defined(GX_BRUSH_ALPHA_SUPPORT) |
||
339 |
136203 |
fore_alpha = (GX_UBYTE)(brush_alpha * fore_alpha / 255); |
|
340 |
136203 |
back_alpha = (GX_UBYTE)(brush_alpha * back_alpha / 255); |
|
341 |
#endif |
||
342 |
✓✓ | 136203 |
if (curx >= clip -> gx_rectangle_left && |
343 |
✓✓ | 125392 |
curx <= clip -> gx_rectangle_right && |
344 |
✓✓ | 111794 |
cury >= clip -> gx_rectangle_top && |
345 |
✓✓ | 110702 |
cury <= clip -> gx_rectangle_bottom) |
346 |
{ |
||
347 |
96218 |
blend_func(context, curx, cury, line_color, (GX_UBYTE)fore_alpha); |
|
348 |
} |
||
349 |
|||
350 |
✓✓ | 136203 |
if ((curx + x_sign) >= clip -> gx_rectangle_left && |
351 |
✓✓ | 126040 |
(curx + x_sign) <= clip -> gx_rectangle_right && |
352 |
✓✓ | 110934 |
cury >= clip -> gx_rectangle_top && |
353 |
✓✓ | 109842 |
cury <= clip -> gx_rectangle_bottom) |
354 |
{ |
||
355 |
95358 |
blend_func(context, curx + x_sign, cury, line_color, (GX_UBYTE)back_alpha); |
|
356 |
} |
||
357 |
} |
||
358 |
} |
||
359 |
} |
||
360 |
} |
||
361 |
Generated by: GCOVR (Version 4.1) |