diff --git a/inst/include/nara.h b/inst/include/nara.h index f22ffc4..f18411c 100644 --- a/inst/include/nara.h +++ b/inst/include/nara.h @@ -14,7 +14,7 @@ // nr_point(uint32_t *nr, int height, int width, uint32_t color, int x, int y) // @param nr pointer to the integer data of a native raster // @param height,width dimensions of nativeRaster -// @param color package integer representing RGBA colour +// @param color packed integer representing RGBA colour // @param x,y location of point //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static inline void nr_point(uint32_t *nr, int height, int width, uint32_t color, int x, int y) { @@ -22,8 +22,64 @@ static inline void nr_point(uint32_t *nr, int height, int width, uint32_t color, if (fun == NULL) { // void draw_point_c(uint32_t *nr, int height, int width, uint32_t color, int x, int y) - fun = (SEXP (*)(uint32_t *nr, int height, int width, uint32_t color, int x, int y)) R_GetCCallable("nara", "draw_point_c"); + fun = (SEXP (*)(uint32_t *nr, int height, int width, uint32_t color, int x, int y)) R_GetCCallable("nara", "nr_point"); } fun(nr, height, width, color, x, y); -} \ No newline at end of file +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// void line(uint32_t *nr, int height, int width, uint32_t color, int x0, int y0, int x1, int y1) +// @param nr pointer to the integer data of a native raster +// @param height,width dimensions of nativeRaster +// @param color packed integer representing RGBA colour +// @param x0,y0,x1,y1 locations of endpoints +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +static inline void nr_line(uint32_t *nr, int height, int width, uint32_t color, int x0, int y0, int x1, int y1) { + static SEXP (*fun)(uint32_t *nr, int height, int width, uint32_t color, int x0, int y0, int x1, int y1) = NULL; + + if (fun == NULL) { + fun = (SEXP (*)(uint32_t *nr, int height, int width, uint32_t color, int x0, int y0, int x1, int y1)) R_GetCCallable("nara", "nr_line"); + } + + fun(nr, height, width, color, x0, y0, x1, y1); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// void nr_hline(uint32_t *nr, int height, int width, uint32_t color, int x1, int x2, int y) +// @param nr pointer to the integer data of a native raster +// @param height,width dimensions of nativeRaster +// @param color packed integer representing RGBA colour +// @param x1,x2 inclusive endpoints +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +static inline void nr_hline(uint32_t *nr, int height, int width, uint32_t color, int x1, int x2, int y) { + static SEXP (*fun)(uint32_t *nr, int height, int width, uint32_t color, int x1, int x2, int y) = NULL; + + if (fun == NULL) { + fun = (SEXP (*)(uint32_t *nr, int height, int width, uint32_t color, int x1, int x2, int y)) R_GetCCallable("nara", "nr_hline"); + } + + fun(nr, height, width, color, x1, x2, y); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// void draw_circle_c(uint32_t *nr, int height, int width, int xm, int ym, int r, uint32_t fill, uint32_t color) +// @param nr pointer to the integer data of a native raster +// @param height,width dimensions of nativeRaster +// @param color packed integer representing RGBA colour +// @param fill packed integer representing RGBA fill +// @param xm,ym centre +// @param r radius +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +static inline void nr_circle(uint32_t *nr, int height, int width, int xm, int ym, int r, uint32_t fill, uint32_t color) { + static SEXP (*fun)(uint32_t *nr, int height, int width, int xm, int ym, int r, uint32_t fill, uint32_t color) = NULL; + + if (fun == NULL) { + fun = (SEXP (*)(uint32_t *nr, int height, int width, int xm, int ym, int r, uint32_t fill, uint32_t color)) R_GetCCallable("nara", "nr_circle"); + } + + fun(nr, height, width, xm, ym, r, fill, color); +} + \ No newline at end of file diff --git a/src/init.c b/src/init.c index 5eadbe2..384e98a 100644 --- a/src/init.c +++ b/src/init.c @@ -105,6 +105,9 @@ static const R_CallMethodDef CEntries[] = { // C funss for export via "LinkingTo" extern void draw_point_c(uint32_t *nr, int height, int width, uint32_t color, int x, int y); +extern void draw_line_c(uint32_t *nr, int height, int width, uint32_t color, int x0, int y0, int x1, int y1) ; +extern void draw_point_sequence_c(uint32_t *nr, int height, int width, uint32_t color, int x1, int x2, int y); +extern void draw_circle_c(uint32_t *nr, int height, int width, int xm, int ym, int r, uint32_t fill, uint32_t color); void R_init_nara(DllInfo *info) { R_registerRoutines( @@ -119,7 +122,10 @@ void R_init_nara(DllInfo *info) { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Make the C code available to other packages //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - R_RegisterCCallable("nara", "draw_point_c", (DL_FUNC) &draw_point_c); + R_RegisterCCallable("nara", "nr_point" , (DL_FUNC) &draw_point_c); + R_RegisterCCallable("nara", "nr_line" , (DL_FUNC) &draw_line_c); + R_RegisterCCallable("nara", "nr_hline" , (DL_FUNC) &draw_point_sequence_c); + R_RegisterCCallable("nara", "nr_circle", (DL_FUNC) &draw_circle_c); } diff --git a/src/nr-draw.c b/src/nr-draw.c index c2b7af6..b19355c 100644 --- a/src/nr-draw.c +++ b/src/nr-draw.c @@ -395,6 +395,47 @@ SEXP draw_rect_(SEXP nr_, SEXP x_, SEXP y_, SEXP w_, SEXP h_, } +// void draw_line_c(uint32_t *nr, int height, int width, uint32_t color, int x0, int y0, int x1, int y1) { +void draw_circle_c(uint32_t *nr, int height, int width, int xm, int ym, int r, uint32_t fill, uint32_t color) { + // Skip NAs + if (xm == NA_INTEGER || ym == NA_INTEGER || r == NA_INTEGER) { + return; + } + + int *ydone = (int *)calloc((size_t)r * 2, sizeof(int)); + if (ydone == NULL) { + error("draw_circle_c(): error allocating 'ydone'"); + } + + int x = -r, y = 0, err = 2-2*r; /* II. Quadrant */ + do { + + if (!is_transparent(fill) && !ydone[y]) { + draw_point_sequence_c(nr, height, width, fill, xm + x, xm - x, ym + y); + if (y != 0) { + draw_point_sequence_c(nr, height, width, fill, xm + x, xm - x, ym - y); + } + ydone[y] = 1; + } + + if (!is_transparent(color)) { + draw_point_c(nr, height, width, color, xm-x, ym+y); /* I. Quadrant */ + draw_point_c(nr, height, width, color, xm+x, ym+y); /* II. Quadrant */ + if (y != 0) { + draw_point_c(nr, height, width, color, xm-x, ym-y); /* III. Quadrant */ + draw_point_c(nr, height, width, color, xm+x, ym-y); /* IV. Quadrant */ + } + } + + r = err; + if (r <= y) err += ++y*2+1; /* e_xy+e_y < 0 */ + if (r > x || err > y) err += ++x*2+1; /* e_xy+e_x > 0 or no 2nd y-step */ + } while (x < 0); + + free(ydone); +} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Draw Circle. Vectorised [R interface] //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~