/* 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; if (raster->draftness <= 0) { draw_linear_bezier_reference(raster, x1, y1, x2, y2); return; } 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