diff options
Diffstat (limited to '')
-rw-r--r-- | rtgrpblib_draw_linear_bezier.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/rtgrpblib_draw_linear_bezier.c b/rtgrpblib_draw_linear_bezier.c new file mode 100644 index 0000000..5c83591 --- /dev/null +++ b/rtgrpblib_draw_linear_bezier.c @@ -0,0 +1,116 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +void +rtgrpblib_draw_linear_bezier(RASTER *restrict raster, double x1, double y1, double x2, double y2) +{ + double w, h, dx, dy, x, y; + int xdir, ydir; + + dx = x2 - x1; + dy = y2 - y1; + xdir = SIGNUM(dx); + ydir = SIGNUM(dy); + + if (!ydir) { + /* For horizontal lines, it is enough that we have the + * corners mapped onto the raster, which we must have + * since a glyph cannot just contain a line, but outlines: + * in `fill`, the line will not make a contribution because + * `.opposite_coverage` for each cell will be zero, and + * consequentially, `.cell_coverage` will also be zero */ + return; + } + + /* We cut of everything above and below the raster, + * as these do not contribute to the result */ + h = (double)raster->height; + if (y1 < 0 && y2 < 0) + return; + if (y1 >= h && y2 >= h) + return; + if (y1 < 0 && y2 >= 0) { + x1 = x1 + (0 - y1) * dx / dy; + y1 = 0; + } else if (y2 < 0 && y1 >= 0) { + x2 = x1 + (0 - y1) * dx / dy; + y2 = 0; + } + if (y1 < h && y2 >= h) { + x2 = x1 + (h - y1) * dx / dy; + y2 = h; + } else if (y2 < h && y1 >= h) { + x1 = x1 + (h - y1) * dx / dy; + y1 = h; + } + + /* Dealing with the left and the right section + * is not as simple as `fill` assumes that the + * sum of each line's `.opposite_coverage` is 0. + * Therefore must must identify the parts of the + * line that are left of the raster, right of + * the raster, and inside the raster. The parts + * that are outside the raster are move to the + * edge, or rather their show on the edges are + * used. */ + w = (double)raster->width; + if (x1 <= 0 && x2 <= 0) { + draw_vertical_line(raster, 0, y1, y2, ydir); + return; + } + if (x1 >= w && x2 >= w) { + draw_vertical_line_opposite_only(raster, raster->width - 1, y1, y2, ydir); + return; + } + if (x1 < 0 && x2 >= 0) { + y = y1 + (0 - x1) * dy / dx; + x = 0; + draw_vertical_line(raster, 0, y1, y, ydir); + x1 = x; + y1 = y; + } else if (x2 < 0 && x1 >= 0) { + y = y1 + (0 - x1) * dy / dx; + x = 0; + draw_vertical_line(raster, 0, y, y2, ydir); + x2 = x; + y2 = y; + } + if (x1 < w && x2 >= w) { + y = y1 + (w - x1) * dy / dx; + x = w; + draw_vertical_line_opposite_only(raster, raster->width - 1, y, y2, ydir); + x2 = x; + y2 = y; + } else if (x2 < w && x1 >= w) { + y = y1 + (w - x1) * dy / dx; + x = w; + draw_vertical_line_opposite_only(raster, raster->width - 1, y1, y, ydir); + x1 = x; + y1 = y; + } + + /* Now we can finally draw the part of the + * line that is inside the raster */ + if (!xdir) { + /* Optimisation for vertical lines. It also serves + * to illustrate how the algorithm is designed. */ + draw_vertical_line(raster, x1, y1, y2, ydir); + } else { + draw_diagonal_line(raster, x1, y1, x2, y2, dx, dy, xdir, ydir); + } +} + + +#else + + +int +main(void) +{ + return 0; /* TODO add test */ +} + + +#endif |