aboutsummaryrefslogtreecommitdiffstats
path: root/rtgrpblib_draw_linear_bezier.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2023-02-05 01:49:25 +0100
committerMattias Andrée <maandree@kth.se>2023-02-05 01:49:25 +0100
commit32c96afc3c2c78e15c0e05560b4e08f8cdc2437e (patch)
tree3b4f9b8588cfb574ef420bc5667c3d4a177b58d3 /rtgrpblib_draw_linear_bezier.c
downloadlibrifunktionsteckensnittsglyfrasteriseringsprogrambiblioteket-32c96afc3c2c78e15c0e05560b4e08f8cdc2437e.tar.gz
librifunktionsteckensnittsglyfrasteriseringsprogrambiblioteket-32c96afc3c2c78e15c0e05560b4e08f8cdc2437e.tar.bz2
librifunktionsteckensnittsglyfrasteriseringsprogrambiblioteket-32c96afc3c2c78e15c0e05560b4e08f8cdc2437e.tar.xz
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'rtgrpblib_draw_linear_bezier.c')
-rw-r--r--rtgrpblib_draw_linear_bezier.c116
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