/* See LICENSE file for copyright and license details. */ #include "librifunktionsteckensnittsglyfrasteriseringsprogrambiblioteket.h" #include #include #include #include #include #include #include #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic ignored "-Wunsuffixed-float-constants" # pragma GCC diagnostic ignored "-Wempty-body" # pragma GCC diagnostic ignored "-Wfloat-equal" # define PURE_FUNCTION __attribute__((__pure__)) # define CONST_FUNCTION __attribute__((__const__)) #elif defined(__clang__) # pragma clang diagnostic ignored "-Wcomma" # pragma clang diagnostic ignored "-Wfloat-equal" # pragma clang diagnostic ignored "-Wfloat-conversion" # define PURE_FUNCTION # define CONST_FUNCTION #else # define PURE_FUNCTION # define CONST_FUNCTION #endif #define SIGNUM(X) (((X) > 0) - ((X) < 0)) #define DEFAULT_DRAFTNESS 0.5 #define draw_vertical_line_opposite_only(...) typedef struct rtgrpblib_cell { /** * The sum all contribution lines make to * the cell's ink level * * For each line, this is calculated by * the signed area of the right triangle, * whose catheti are parallel to the edges * and whose hypotenuse is the line's segment * in the cell, plus the area of the rectangle * whose left edge is the opposite cathetus * of the right triangle, and whose right edge * intersects with the right cell edge */ double cell_coverage; /* ink here */ /** * The sum all contribution lines make to * the shadow on the cell's right edge: * the ink level on the next cell * * For each line, this is calculated by the * signed size of the opposite (right-side) * cathetus of the right triangle, whose * catheti are parallel to the edges and * whose hypotenuse is the line's segment * in the cell */ double opposite_coverage; /* ink there */ } CELL; typedef struct rtgrpblib_raster { size_t height; size_t width; size_t size; double draftness; /* TODO support 0 */ CELL cells[]; } RASTER; #define TOLERANCE 0.000001 CONST_FUNCTION static inline int iszeroish(double x) { return x <= TOLERANCE && x >= -TOLERANCE; } /* draw_linear_bezier_reference.c */ #define draw_linear_bezier_reference rtgrpblib_draw_linear_bezier_reference__ void draw_linear_bezier_reference(RASTER *restrict raster, double x1, double y1, double x2, double y2); /* equations.c */ #define solve_cubic rtgrpblib_solve_cubic__ #define solve_quadratic rtgrpblib_solve_quadratic__ #define solve_linear rtgrpblib_solve_linear__ size_t solve_cubic(double *ts, double a, double b, double c, double d); size_t solve_quadratic(double *ts, double a, double b, double c); size_t solve_linear(double *ts, double a, double b); /* lines.c */ #ifndef draw_vertical_line_opposite_only # define draw_vertical_line_opposite_only rtgrpblib_draw_vertical_line_opposite_only__ void draw_vertical_line_opposite_only(RASTER *restrict raster, size_t x, double y1, double y2, int ydir); #else # define ROWWISE_RESET_INKLEVEL #endif #define draw_vertical_line rtgrpblib_draw_vertical_line__ #define draw_diagonal_line rtgrpblib_draw_diagonal_line__ #define draw_bounded_line rtgrpblib_draw_bounded_line__ void draw_vertical_line(RASTER *restrict raster, double x1, double y1, double y2, int ydir); void draw_diagonal_line(RASTER *restrict raster, double x1, double y1, double x2, double y2, double dx, double dy, int xdir, int ydir); void draw_bounded_line(RASTER *restrict raster, double x1, double y1, double x2, double y2); /* sorting.c */ #define doublepcmp rtgrpblib_doublepcmp__ PURE_FUNCTION int doublepcmp(const void *avp, const void *bvp); #ifdef TEST #include #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic ignored "-Wunsuffixed-float-constants" # pragma GCC diagnostic ignored "-Wfloat-equal" # pragma GCC diagnostic ignored "-Wsuggest-attribute=const" #elif defined(__clang__) # pragma clang diagnostic ignored "-Wfloat-equal" #endif static inline int eq(double a, double b) { return iszeroish(a - b); } static inline int tolerant_eq(double a, double b) { return iszeroish((a - b) / 100.0); } # define ASSERT(ASSERTION)\ do {\ if (!(ASSERTION)) {\ fprintf(stderr, "Failed assertion at line %i: %s\n", __LINE__, #ASSERTION);\ exit(1);\ }\ } while (0) # if 1 static inline void print_raster(const RASTER *r) { size_t y, x; fprintf(stderr, "\nOutline (area)\n"); for (y = 0; y < r->height; y++) { for (x = 0; x < r->width; x++) fprintf(stderr, r->cells[y * r->width + x].cell_coverage ? "%+.4lf " : " 0 ", r->cells[y * r->width + x].cell_coverage); printf("\n"); } fprintf(stderr, "\nOutline (shadow)\n"); for (y = 0; y < r->height; y++) { for (x = 0; x < r->width; x++) fprintf(stderr, r->cells[y * r->width + x].opposite_coverage ? "%+.4lf " : " 0 ", r->cells[y * r->width + x].opposite_coverage); printf("\n"); } } # endif #endif