diff options
Diffstat (limited to '')
| -rw-r--r-- | Makefile | 11 | ||||
| -rw-r--r-- | common.h | 3 | ||||
| -rw-r--r-- | librifunktionsteckensnittsglyfrasteriseringsprogrambiblioteket.h | 105 | ||||
| -rw-r--r-- | rtgrpblib_create_raster.c | 45 | ||||
| -rw-r--r-- | rtgrpblib_reset_raster.c | 93 | ||||
| -rw-r--r-- | rtgrpblib_set_draftness.c | 2 | ||||
| -rw-r--r-- | sorting.c | 28 | 
7 files changed, 271 insertions, 16 deletions
| @@ -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\ @@ -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 @@ -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;  } | 
