Line | Branch | Exec | Source |
---|---|---|---|
1 | /* GATE PROJECT LICENSE: | ||
2 | +----------------------------------------------------------------------------+ | ||
3 | | Copyright(c) 2018-2025, Stefan Meislinger | | ||
4 | | All rights reserved. | | ||
5 | | | | ||
6 | | Redistribution and use in source and binary forms, with or without | | ||
7 | | modification, are permitted provided that the following conditions are met:| | ||
8 | | | | ||
9 | | 1. Redistributions of source code must retain the above copyright notice, | | ||
10 | | this list of conditions and the following disclaimer. | | ||
11 | | 2. Redistributions in binary form must reproduce the above copyright | | ||
12 | | notice, this list of conditions and the following disclaimer in the | | ||
13 | | documentation and/or other materials provided with the distribution. | | ||
14 | | | | ||
15 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| | ||
16 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | ||
17 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | ||
18 | | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | ||
19 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | ||
20 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | ||
21 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | ||
22 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | ||
23 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | ||
24 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | ||
25 | | THE POSSIBILITY OF SUCH DAMAGE. | | ||
26 | +----------------------------------------------------------------------------+ | ||
27 | */ | ||
28 | |||
29 | #include "gate/graphics/drawing.h" | ||
30 | #include "gate/mathematics.h" | ||
31 | #include "gate/results.h" | ||
32 | |||
33 | |||
34 | 707 | static void gate_rasterimage_plot(gate_rasterimage_t* image, int x, int y, gate_color_painter_t painter, gate_color_t const* color) | |
35 | { | ||
36 | gate_uint8_t* ptr_data; | ||
37 | gate_color_t pixel; | ||
38 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
|
727 | if (x < 0) return; |
39 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 697 times.
|
707 | if (x >= (int)image->width) return; |
40 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 697 times.
|
697 | if (y < 0) return; |
41 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 687 times.
|
697 | if (y >= (int)image->height) return; |
42 | 687 | ptr_data = image->get_ptr(image->data, image->width, image->height, image->line_padding, x, y); | |
43 | 687 | image->read_pixel(ptr_data, &pixel); | |
44 | 687 | painter(&pixel, color); | |
45 | 687 | image->write_pixel(ptr_data, &pixel); | |
46 | } | ||
47 | |||
48 | 17 | static void gate_rasterimage_line(gate_rasterimage_t* image, int x1, int y1, int x2, int y2, gate_color_t color) | |
49 | { | ||
50 | 17 | int delta_x = (x2 - x1); | |
51 | 17 | int ix = ((delta_x > 0) - (delta_x < 0)); | |
52 | |||
53 | 17 | int delta_y = (y2 - y1); | |
54 | 17 | int iy = ((delta_y > 0) - (delta_y < 0)); | |
55 | |||
56 | 17 | gate_color_painter_t painter = &gate_color_set_transparent; | |
57 | |||
58 | int error; | ||
59 | |||
60 | 17 | delta_x = gate_math_abs_i32(delta_x) << 1; | |
61 | 17 | delta_y = gate_math_abs_i32(delta_y) << 1; | |
62 | |||
63 | 17 | gate_rasterimage_plot(image, x1, y1, painter, &color); | |
64 | |||
65 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 6 times.
|
17 | if (delta_x >= delta_y) |
66 | { | ||
67 | // error may go below zero | ||
68 | 11 | error = (delta_y - (delta_x >> 1)); | |
69 | |||
70 |
2/2✓ Branch 0 taken 672 times.
✓ Branch 1 taken 11 times.
|
683 | while (x1 != x2) |
71 | { | ||
72 |
4/6✓ Branch 0 taken 672 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 336 times.
✓ Branch 3 taken 336 times.
✓ Branch 4 taken 336 times.
✗ Branch 5 not taken.
|
672 | if ((error > 0) || (!error && (ix > 0))) |
73 | { | ||
74 | 336 | error -= delta_x; | |
75 | 336 | y1 += iy; | |
76 | } | ||
77 | 672 | error += delta_y; | |
78 | 672 | x1 += ix; | |
79 | 672 | gate_rasterimage_plot(image, x1, y1, painter, &color); | |
80 | } | ||
81 | } | ||
82 | else | ||
83 | { | ||
84 | // error may go below zero | ||
85 | 6 | error = (delta_x - (delta_y >> 1)); | |
86 | |||
87 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
|
24 | while (y1 != y2) |
88 | { | ||
89 | // reduce error, while taking into account the corner case of error == 0 | ||
90 |
2/6✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
18 | if ((error > 0) || (!error && (iy > 0))) |
91 | { | ||
92 | ✗ | error -= delta_y; | |
93 | ✗ | x1 += ix; | |
94 | } | ||
95 | 18 | error += delta_x; | |
96 | 18 | y1 += iy; | |
97 | |||
98 | 18 | gate_rasterimage_plot(image, x1, y1, painter, &color); | |
99 | } | ||
100 | } | ||
101 | 17 | } | |
102 | |||
103 | 17 | gate_result_t gate_draw_line(gate_rasterimage_t* image, int x1, int y1, int x2, int y2, gate_color_t color) | |
104 | { | ||
105 | 17 | gate_rasterimage_line(image, x1, y1, x2, y2, color); | |
106 | 17 | return GATE_RESULT_OK; | |
107 | } | ||
108 | |||
109 | 19 | static void gate_draw_hline_quick(gate_rasterimage_t* image, int x, int y, int len, gate_color_t color) | |
110 | { | ||
111 | 19 | gate_uint8_t* ptr_data = image->get_ptr(image->data, image->width, image->height, image->line_padding, x, y); | |
112 | 19 | unsigned const pixel_length = image->pixel_length; | |
113 | |||
114 |
2/2✓ Branch 0 taken 185 times.
✓ Branch 1 taken 19 times.
|
204 | while (len-- > 0) |
115 | { | ||
116 | 185 | image->write_pixel(ptr_data, &color); | |
117 | 185 | ptr_data += pixel_length; | |
118 | } | ||
119 | 19 | } | |
120 | 2 | static void gate_draw_hline(gate_rasterimage_t* image, int x, int y, int len, gate_color_t color) | |
121 | { | ||
122 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
2 | if ((y < 0) || (y >= (int)image->height) || (len == 0)) |
123 | { | ||
124 | ✗ | return; | |
125 | } | ||
126 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (len < 0) |
127 | { | ||
128 | ✗ | x += len; | |
129 | ✗ | len = -len; | |
130 | } | ||
131 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (((x + len) < 0) || (x >= (int)image->width)) |
132 | { | ||
133 | ✗ | return; | |
134 | } | ||
135 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (x < 0) |
136 | { | ||
137 | ✗ | len += x; | |
138 | ✗ | x = 0; | |
139 | } | ||
140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if ((x + len) >= (int)image->width) |
141 | { | ||
142 | ✗ | len = (int)image->width - x; | |
143 | } | ||
144 | 2 | gate_draw_hline_quick(image, x, y, len, color); | |
145 | } | ||
146 | |||
147 | 2 | static void gate_draw_vline_quick(gate_rasterimage_t* image, int x, int y, int len, gate_color_t color) | |
148 | { | ||
149 | 2 | gate_uint8_t* ptr_data = image->get_ptr(image->data, image->width, image->height, image->line_padding, x, y); | |
150 | 2 | unsigned const line_length = image->width * image->pixel_length + image->line_padding; | |
151 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 2 times.
|
36 | while (len-- > 0) |
152 | { | ||
153 | 34 | image->write_pixel(ptr_data, &color); | |
154 | 34 | ptr_data += line_length; | |
155 | } | ||
156 | 2 | } | |
157 | 2 | static void gate_draw_vline(gate_rasterimage_t* image, int x, int y, int len, gate_color_t color) | |
158 | { | ||
159 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
2 | if ((x < 0) || (x >= (int)image->width) || (len == 0)) |
160 | { | ||
161 | ✗ | return; | |
162 | } | ||
163 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (len < 0) |
164 | { | ||
165 | ✗ | y += len; | |
166 | ✗ | len = -len; | |
167 | } | ||
168 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (((y + len) < 0) || (y >= (int)image->height)) |
169 | { | ||
170 | ✗ | return; | |
171 | } | ||
172 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (y < 0) |
173 | { | ||
174 | ✗ | len += y; | |
175 | ✗ | y = 0; | |
176 | } | ||
177 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if ((y + len) >= (int)image->height) |
178 | { | ||
179 | ✗ | len = (int)image->height - y; | |
180 | } | ||
181 | 2 | gate_draw_vline_quick(image, x, y, len, color); | |
182 | } | ||
183 | |||
184 | |||
185 | 1 | gate_result_t gate_draw_rectangle(gate_rasterimage_t* image, int x1, int y1, int x2, int y2, gate_color_t color) | |
186 | { | ||
187 | int tmp; | ||
188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (x1 > x2) |
189 | { | ||
190 | ✗ | tmp = x1; | |
191 | ✗ | x1 = x2; | |
192 | ✗ | x2 = tmp; | |
193 | } | ||
194 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (y1 > y2) |
195 | { | ||
196 | ✗ | tmp = y1; | |
197 | ✗ | y1 = y2; | |
198 | ✗ | y2 = tmp; | |
199 | } | ||
200 | 1 | gate_draw_hline(image, x1, y1, x2 - x1 + 1, color); | |
201 | 1 | gate_draw_hline(image, x1, y2, x2 - x1 + 1, color); | |
202 | 1 | gate_draw_vline(image, x1, y1, y2 - y1 + 1, color); | |
203 | 1 | gate_draw_vline(image, x2, y1, y2 - y1 + 1, color); | |
204 | 1 | return GATE_RESULT_OK; | |
205 | } | ||
206 | |||
207 | 1 | gate_result_t gate_draw_box(gate_rasterimage_t* image, int x1, int y1, int x2, int y2, gate_color_t color) | |
208 | { | ||
209 | int tmp; | ||
210 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (x1 > x2) |
211 | { | ||
212 | ✗ | tmp = x1; | |
213 | ✗ | x1 = x2; | |
214 | ✗ | x2 = tmp; | |
215 | } | ||
216 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (y1 > y2) |
217 | { | ||
218 | ✗ | tmp = y1; | |
219 | ✗ | y1 = y2; | |
220 | ✗ | y2 = tmp; | |
221 | } | ||
222 | |||
223 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (x1 < 0) x1 = 0; |
224 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (y1 < 0) y1 = 0; |
225 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (x2 >= (int)image->width) x2 = (int)image->width - 1; |
226 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (y2 >= (int)image->height) y2 = (int)image->height - 1; |
227 | |||
228 | 1 | tmp = x2 - x1 + 1; | |
229 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1 times.
|
18 | while (y1 <= y2) |
230 | { | ||
231 | 17 | gate_draw_hline_quick(image, x1, y1, tmp, color); | |
232 | 17 | ++y1; | |
233 | } | ||
234 | 1 | return GATE_RESULT_OK; | |
235 | } | ||
236 | |||
237 |