| 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 |