aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile11
-rw-r--r--common.h3
-rw-r--r--librifunktionsteckensnittsglyfrasteriseringsprogrambiblioteket.h105
-rw-r--r--rtgrpblib_create_raster.c45
-rw-r--r--rtgrpblib_reset_raster.c93
-rw-r--r--rtgrpblib_set_draftness.c2
-rw-r--r--sorting.c28
7 files changed, 271 insertions, 16 deletions
diff --git a/Makefile b/Makefile
index 370c2fe..300fb5f 100644
--- a/Makefile
+++ b/Makefile
@@ -16,19 +16,20 @@ LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR)
LIB_NAME = rifunktionsteckensnittsglyfrasteriseringsprogrambiblioteket
+# OBJ is sorted in testing order
OBJ =\
equations.o\
- lines.o\
sorting.o\
- draw_linear_bezier_reference.o\
rtgrpblib_create_raster.o\
+ rtgrpblib_reset_raster.o\
+ rtgrpblib_set_draftness.o\
+ draw_linear_bezier_reference.o\
+ lines.o\
rtgrpblib_draw_circular_arc.o\
rtgrpblib_draw_linear_bezier.o\
rtgrpblib_draw_quadratic_bezier.o\
rtgrpblib_draw_cubic_bezier.o\
- rtgrpblib_fill_shapes.o\
- rtgrpblib_reset_raster.o\
- rtgrpblib_set_draftness.o
+ rtgrpblib_fill_shapes.o
HDR =\
lib$(LIB_NAME).h\
diff --git a/common.h b/common.h
index 2436a6a..67a1c62 100644
--- a/common.h
+++ b/common.h
@@ -29,6 +29,8 @@
#define SIGNUM(X) (((X) > 0) - ((X) < 0))
+#define DEFAULT_DRAFTNESS 0.5
+
#define draw_vertical_line_opposite_only(...)
@@ -66,6 +68,7 @@ typedef struct rtgrpblib_cell {
typedef struct rtgrpblib_raster {
size_t height;
size_t width;
+ size_t size;
double draftness; /* TODO support 0 */
CELL cells[];
} RASTER;
diff --git a/librifunktionsteckensnittsglyfrasteriseringsprogrambiblioteket.h b/librifunktionsteckensnittsglyfrasteriseringsprogrambiblioteket.h
index fffeae7..97d57c3 100644
--- a/librifunktionsteckensnittsglyfrasteriseringsprogrambiblioteket.h
+++ b/librifunktionsteckensnittsglyfrasteriseringsprogrambiblioteket.h
@@ -5,36 +5,133 @@
#include <stddef.h>
+/**
+ * Object that the library draws on, is converted to
+ * an ink-level image using the `rtgrpblib_fill_shapes`
+ * function. This object also contain drawing
+ * configurations.
+ */
typedef struct rtgrpblib_raster RTGRPBLIB_RASTER;
+/**
+ * Create a buffer that the library can use for drawing
+ *
+ * @param width The width of the buffer
+ * @param height The height of the buffer
+ * @return Drawing buffer, which can be deallocated with (3),
+ * or `NULL` on failure
+ *
+ * @throws EINVAL `width` or `height` is zero
+ * @throws ENOMEM Cannot allocate enough memory
+ *
+ * @seealso rtgrpblib_reset_raster
+ */
RTGRPBLIB_RASTER *rtgrpblib_create_raster(size_t width, size_t height);
+
+/**
+ * Reshape and clear a drawing buffer
+ *
+ * @param raster The buffer to reshape and clear
+ * @param width The new width of the buffer
+ * @param height The new height of the buffer
+ * @return 0 on success, -1 on failure
+ *
+ * @throws EINVAL `width` or `height` is zero
+ * @throws EINVAL The buffers new area size exceeds its original area size
+ */
int rtgrpblib_reset_raster(RTGRPBLIB_RASTER *raster, size_t width, size_t height);
+
+/**
+ * Reconfigure a drawing buffer with a new draftness value
+ *
+ * When drawing a curve, the size of each step the library
+ * takes will be proportional to the draftness value, but
+ * will also depend on other factors. Doubling the draftness
+ * value with halve (disregarind overheads) the time it takes
+ * to draw any given curve.
+ *
+ * @param raster The drawing buffer to reconfigure
+ * @param draftness The new draftness value, must be positive
+ */
void rtgrpblib_set_draftness(RTGRPBLIB_RASTER *raster, double draftness);
+
+/**
+ * Create an image of the drawings applied to a drawing buffer
+ *
+ * All drawn shapes must be closed
+ *
+ * Shapes that are drawn in the same angular direction add to
+ * each other, shapes that are drawn in opposite angular
+ * directions subtract from each other
+ *
+ * @param image Output buffer, need not be initialised, but
+ * shall have an allocation size of `rowsize`
+ * multiplied by the height of `raster` and
+ * by `sizeof(double)`
+ * @param rowsize The number of elements in `image` per row,
+ * must be at least the width of `raster`
+ * @param raster The drawing buffer
+ *
+ * @seealso rtgrpblib_reset_raster
+ */
void rtgrpblib_fill_shapes(double *restrict image, size_t rowsize, const RTGRPBLIB_RASTER *raster);
+
+/**
+ * Draw a line between two points
+ *
+ * @param raster The drawing buffer
+ * @param x1, y1 The starting point
+ * @param x2, y2 The end point
+ */
void rtgrpblib_draw_linear_bezier(RTGRPBLIB_RASTER *restrict raster,
double x1, double y1,
double x2, double y2);
+/**
+ * Draw a quadratic bézier curve
+ *
+ * @param raster The drawing buffer
+ * @param x1, y1 The starting point
+ * @param x2, y2 The control point
+ * @param x3, y3 The end point
+ */
void rtgrpblib_draw_quadratic_bezier(RTGRPBLIB_RASTER *restrict raster,
double x1, double y1,
double x2, double y2,
double x3, double y3);
-void rtgrpblib_draw_cubic_bezier(RTGRPBLIB_RASTER *restrict raster,
+/**
+ * Draw a cubic bézier curve
+ *
+ * @param raster The drawing buffer
+ * @param x1, y1 The starting point
+ * @param x2, y2 The first control point
+ * @param x3, y3 The second control point
+ * @param x4, y4 The end point
+ */
+void rtgrpblib_draw_cubic_bezier(RTGRPBLIB_RASTER *restrict raster, /* needed for OpenType */
double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4);
-void rtgrpblib_draw_circular_arc(RTGRPBLIB_RASTER *restrict raster,
+/**
+ * Draw a cricular arc
+ *
+ * @param raster The drawing buffer
+ * @param x0, y0 The midpoint of the ellipse
+ * @param semiwidth Half the width of the ellipse
+ * @param semiheight Half the height of the ellipse
+ * @param start The angular starting point of the arc, in radians
+ * @param end The angular end point of the arc, in radians
+ */
+void rtgrpblib_draw_circular_arc(RTGRPBLIB_RASTER *restrict raster, /* needed for outline stoking */
double x0, double y0,
double semiwidth, double semiheight,
double start, double end);
-/* TODO add support for outlining */
-
#endif
diff --git a/rtgrpblib_create_raster.c b/rtgrpblib_create_raster.c
index 89ebad6..cbc69f2 100644
--- a/rtgrpblib_create_raster.c
+++ b/rtgrpblib_create_raster.c
@@ -7,6 +7,7 @@ RASTER *
rtgrpblib_create_raster(size_t width, size_t height)
{
RASTER *raster;
+ size_t size;
if (!width || !height) {
errno = EINVAL;
@@ -15,7 +16,8 @@ rtgrpblib_create_raster(size_t width, size_t height)
if (width > (SIZE_MAX - offsetof(RASTER, cells)) / sizeof(*raster->cells) / height)
goto enomem;
- raster = calloc(1, offsetof(RASTER, cells) + height * width * sizeof(*raster->cells));
+ size = width * height;
+ raster = calloc(1, offsetof(RASTER, cells) + size * sizeof(*raster->cells));
if (!raster) {
enomem:
errno = ENOMEM;
@@ -24,7 +26,8 @@ rtgrpblib_create_raster(size_t width, size_t height)
raster->width = width;
raster->height = height;
- raster->draftness = 0.5;
+ raster->size = size;
+ raster->draftness = DEFAULT_DRAFTNESS;
return raster;
}
@@ -34,7 +37,43 @@ rtgrpblib_create_raster(size_t width, size_t height)
int
main(void)
{
- return 0; /* TODO add test */
+ RASTER *raster;
+ size_t i, n;
+
+ errno = 0;
+ ASSERT(!rtgrpblib_create_raster(0, 1));
+ ASSERT(errno == EINVAL);
+
+ errno = 0;
+ ASSERT(!rtgrpblib_create_raster(1, 0));
+ ASSERT(errno == EINVAL);
+
+ errno = 0;
+ ASSERT(!rtgrpblib_create_raster(0, 0));
+ ASSERT(errno == EINVAL);
+
+ errno = 0;
+ ASSERT(!rtgrpblib_create_raster(SIZE_MAX - offsetof(RASTER, cells) + 1, 1));
+ ASSERT(errno == ENOMEM);
+
+ errno = 0;
+ ASSERT(!rtgrpblib_create_raster(1, SIZE_MAX - offsetof(RASTER, cells) + 1));
+ ASSERT(errno == ENOMEM);
+
+ raster = rtgrpblib_create_raster(10, 20);
+ ASSERT(raster);
+ ASSERT(raster->width == 10);
+ ASSERT(raster->height == 20);
+ ASSERT(raster->size == raster->width * raster->height);
+ ASSERT(raster->draftness == DEFAULT_DRAFTNESS);
+ n = raster->width * raster->height;
+ for (i = 0; i < n; i++) {
+ ASSERT(!raster->cells[i].cell_coverage);
+ ASSERT(!raster->cells[i].opposite_coverage);
+ }
+
+ free(raster);
+ return 0;
}
#endif
diff --git a/rtgrpblib_reset_raster.c b/rtgrpblib_reset_raster.c
index 2cfef42..a3b81df 100644
--- a/rtgrpblib_reset_raster.c
+++ b/rtgrpblib_reset_raster.c
@@ -6,7 +6,7 @@
int
rtgrpblib_reset_raster(RASTER *raster, size_t width, size_t height)
{
- if (!width || !height || width > raster->width * raster->height / height) {
+ if (!width || !height || width > raster->size / height) {
errno = EINVAL;
return -1;
}
@@ -23,7 +23,96 @@ rtgrpblib_reset_raster(RASTER *raster, size_t width, size_t height)
int
main(void)
{
- return 0; /* TODO add test */
+
+ RASTER *raster;
+ size_t i, n, size;
+
+ raster = rtgrpblib_create_raster(10, 20);
+ ASSERT(raster);
+ ASSERT(raster->width == 10);
+ ASSERT(raster->height == 20);
+ raster->draftness = 10;
+ size = raster->width * raster->height;
+ ASSERT(raster->size == size);
+
+ errno = 0;
+ ASSERT(rtgrpblib_reset_raster(raster, 10, 21) == -1);
+ ASSERT(errno == EINVAL);
+ ASSERT(raster->width == 10);
+ ASSERT(raster->height == 20);
+ ASSERT(raster->size == size);
+ ASSERT(raster->draftness == 10);
+
+ errno = 0;
+ ASSERT(rtgrpblib_reset_raster(raster, 11, 20) == -1);
+ ASSERT(errno == EINVAL);
+ ASSERT(raster->width == 10);
+ ASSERT(raster->height == 20);
+ ASSERT(raster->size == size);
+ ASSERT(raster->draftness == 10);
+
+ errno = 0;
+ ASSERT(rtgrpblib_reset_raster(raster, 1, 0) == -1);
+ ASSERT(errno == EINVAL);
+ ASSERT(raster->width == 10);
+ ASSERT(raster->height == 20);
+ ASSERT(raster->size == size);
+ ASSERT(raster->draftness == 10);
+
+ errno = 0;
+ ASSERT(rtgrpblib_reset_raster(raster, 0, 1) == -1);
+ ASSERT(errno == EINVAL);
+ ASSERT(raster->width == 10);
+ ASSERT(raster->height == 20);
+ ASSERT(raster->size == size);
+ ASSERT(raster->draftness == 10);
+
+ errno = 0;
+ ASSERT(rtgrpblib_reset_raster(raster, 0, 0) == -1);
+ ASSERT(errno == EINVAL);
+ ASSERT(raster->width == 10);
+ ASSERT(raster->height == 20);
+ ASSERT(raster->size == size);
+ ASSERT(raster->draftness == 10);
+
+ memset(raster->cells, 100, raster->size * sizeof(*raster->cells));
+ ASSERT(!rtgrpblib_reset_raster(raster, 5, 10));
+ ASSERT(raster->width == 5);
+ ASSERT(raster->height == 10);
+ ASSERT(raster->size == size);
+ ASSERT(raster->draftness == 10);
+ n = raster->width * raster->height;
+ for (i = 0; i < n; i++) {
+ ASSERT(!raster->cells[i].cell_coverage);
+ ASSERT(!raster->cells[i].opposite_coverage);
+ }
+
+ memset(raster->cells, 100, raster->size * sizeof(*raster->cells));
+ ASSERT(!rtgrpblib_reset_raster(raster, 5, 30));
+ ASSERT(raster->width == 5);
+ ASSERT(raster->height == 30);
+ ASSERT(raster->size == size);
+ ASSERT(raster->draftness == 10);
+ n = raster->width * raster->height;
+ for (i = 0; i < n; i++) {
+ ASSERT(!raster->cells[i].cell_coverage);
+ ASSERT(!raster->cells[i].opposite_coverage);
+ }
+
+ memset(raster->cells, 100, raster->size * sizeof(*raster->cells));
+ ASSERT(!rtgrpblib_reset_raster(raster, 15, 10));
+ ASSERT(raster->width == 15);
+ ASSERT(raster->height == 10);
+ ASSERT(raster->size == size);
+ ASSERT(raster->draftness == 10);
+ n = raster->width * raster->height;
+ for (i = 0; i < n; i++) {
+ ASSERT(!raster->cells[i].cell_coverage);
+ ASSERT(!raster->cells[i].opposite_coverage);
+ }
+
+ free(raster);
+ return 0;
}
#endif
diff --git a/rtgrpblib_set_draftness.c b/rtgrpblib_set_draftness.c
index dbdeed0..d35222f 100644
--- a/rtgrpblib_set_draftness.c
+++ b/rtgrpblib_set_draftness.c
@@ -15,7 +15,7 @@ rtgrpblib_set_draftness(RTGRPBLIB_RASTER *raster, double draftness)
int
main(void)
{
- return 0; /* TODO add test */
+ return 0; /* why test something this trivial */
}
#endif
diff --git a/sorting.c b/sorting.c
index e4bfdaf..2738081 100644
--- a/sorting.c
+++ b/sorting.c
@@ -18,7 +18,33 @@ doublepcmp(const void *avp, const void *bvp)
int
main(void)
{
- return 0; /* TODO add test */
+ double a, b;
+
+ a = 1.0, b = 1.0;
+ ASSERT(doublepcmp(&a, &b) == 0);
+ ASSERT(doublepcmp(&b, &a) == -doublepcmp(&a, &b));
+
+ a = -1.0, b = 1.0;
+ ASSERT(doublepcmp(&a, &b) == -1);
+ ASSERT(doublepcmp(&b, &a) == -doublepcmp(&a, &b));
+
+ a = 1.0, b = -1.0;
+ ASSERT(doublepcmp(&a, &b) == +1);
+ ASSERT(doublepcmp(&b, &a) == -doublepcmp(&a, &b));
+
+ a = 0.0, b = 0.0;
+ ASSERT(doublepcmp(&a, &b) == 0);
+ ASSERT(doublepcmp(&b, &a) == -doublepcmp(&a, &b));
+
+ a = -1.0, b = 2.5;
+ ASSERT(doublepcmp(&a, &b) == -1);
+ ASSERT(doublepcmp(&b, &a) == -doublepcmp(&a, &b));
+
+ a = 1.0, b = -2.5;
+ ASSERT(doublepcmp(&a, &b) == +1);
+ ASSERT(doublepcmp(&b, &a) == -doublepcmp(&a, &b));
+
+ return 0;
}