From 2438d7075abca8f6bfc6f580598e38555ebc5d41 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 21 Jan 2010 23:11:08 +0000 Subject: add beginnings of path plotting svn path=/trunk/libnsfb/; revision=9854 --- Makefile | 2 +- include/libnsfb_plot.h | 6 ++++ include/plot.h | 3 ++ src/plot/api.c | 5 +++ src/plot/generic.c | 62 ++++++++++++++++++++++++++++++++++ test/Makefile | 2 +- test/path.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/polygon.c | 79 +++++++++++++++++++++++++++++++++++++++++++ test/polystar.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ test/runtest.sh | 11 ++++++ 10 files changed, 349 insertions(+), 2 deletions(-) create mode 100644 test/path.c create mode 100644 test/polygon.c create mode 100644 test/polystar.c create mode 100755 test/runtest.sh diff --git a/Makefile b/Makefile index 57fa975..4468d12 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ COMPONENT_TYPE ?= lib-static include build/makefiles/Makefile.tools # Reevaluate when used, as BUILDDIR won't be defined yet -TESTRUNNER = $(BUILDDIR)/test_plottest$(EXEEXT) +TESTRUNNER = test/runtest.sh $(BUILDDIR) $(EXEEXT) # Toolchain flags WARNFLAGS := -Wall -Wextra -Wundef -Wpointer-arith -Wcast-align \ diff --git a/include/libnsfb_plot.h b/include/libnsfb_plot.h index af1768e..e0ee7de 100644 --- a/include/libnsfb_plot.h +++ b/include/libnsfb_plot.h @@ -101,6 +101,12 @@ bool nsfb_plot_line(nsfb_t *nsfb, nsfb_bbox_t *line, nsfb_plot_pen_t *pen); */ bool nsfb_plot_lines(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen); +/** Plots a number of connected lines. + * + * Draw a series of connected lines. + */ +bool nsfb_plot_polylines(nsfb_t *nsfb, int pointc, nsfb_point_t *points, nsfb_plot_pen_t *pen); + /** Plots a filled polygon. * * Plots a filled polygon with straight lines between points. The lines around diff --git a/include/plot.h b/include/plot.h index 8894c7a..929daec 100644 --- a/include/plot.h +++ b/include/plot.h @@ -90,6 +90,8 @@ typedef bool (nsfb_plotfn_quadratic_bezier_t)(nsfb_t *nsfb, nsfb_bbox_t *curve, */ typedef bool (nsfb_plotfn_cubic_bezier_t)(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_point_t *ctrlb, nsfb_colour_t c); +typedef bool (nsfb_plotfn_polylines_t)(nsfb_t *nsfb, int pointc, nsfb_point_t *points, nsfb_plot_pen_t *pen); + /** plot path */ typedef bool (nsfb_plotfn_path_t)(nsfb_t *nsfb, int pathc, nsfb_plot_pathop_t *pathop, nsfb_plot_pen_t *pen); @@ -114,6 +116,7 @@ typedef struct nsfb_plotter_fns_s { nsfb_plotfn_quadratic_bezier_t *quadratic; nsfb_plotfn_cubic_bezier_t *cubic; nsfb_plotfn_path_t *path; + nsfb_plotfn_polylines_t *polylines; } nsfb_plotter_fns_t; diff --git a/src/plot/api.c b/src/plot/api.c index 4de25c9..a3f212d 100644 --- a/src/plot/api.c +++ b/src/plot/api.c @@ -79,6 +79,11 @@ bool nsfb_plot_lines(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t return nsfb->plotter_fns->line(nsfb, linec, line, pen); } +bool nsfb_plot_polylines(nsfb_t *nsfb, int pointc, nsfb_point_t *points, nsfb_plot_pen_t *pen) +{ + return nsfb->plotter_fns->polylines(nsfb, pointc, points, pen); +} + /** Plots a filled polygon. * * Plots a filled polygon with straight lines between points. The lines around diff --git a/src/plot/generic.c b/src/plot/generic.c index d04559e..8dbc64b 100644 --- a/src/plot/generic.c +++ b/src/plot/generic.c @@ -604,6 +604,66 @@ static bool quadratic(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsf return true; } +static bool polylines(nsfb_t *nsfb, int pointc, nsfb_point_t *points, nsfb_plot_pen_t *pen) +{ + int point_loop; + + if (pen->stroke_type != NFSB_PLOT_OPTYPE_NONE) { + for (point_loop = 0; point_loop < (pointc - 1); point_loop++) { + nsfb->plotter_fns->line(nsfb, 1, (nsfb_bbox_t *)&points[point_loop], pen); + } + } + return true; +} + +static bool +path(nsfb_t *nsfb, int pathc, nsfb_plot_pathop_t *pathop, nsfb_plot_pen_t *pen) +{ + int path_loop; + nsfb_point_t *pts; + nsfb_point_t *curpt; + int ptc = 0; + + /* count the verticies in the path and add N_SEG extra for curves */ + for (path_loop = 0; path_loop < pathc; path_loop++) { + ptc++; + if ((pathop[path_loop].operation == NFSB_PLOT_PATHOP_QUAD) || + (pathop[path_loop].operation == NFSB_PLOT_PATHOP_QUAD)) + ptc += N_SEG; + } + + /* allocate storage for the vertexes */ + curpt = pts = malloc(ptc * sizeof(nsfb_point_t)); + + for (path_loop = 0; path_loop < pathc; path_loop++) { + switch (pathop[path_loop].operation) { + case NFSB_PLOT_PATHOP_QUAD: + curpt-=1; + break; + + case NFSB_PLOT_PATHOP_CUBIC: + curpt-=2; + break; + + default: + *curpt = pathop[path_loop].point; + curpt++; + } + } + + if (pen->fill_type != NFSB_PLOT_OPTYPE_NONE) { + polygon(nsfb, (int *)pts, path_loop, pen->fill_colour); + } + + if (pen->stroke_type != NFSB_PLOT_OPTYPE_NONE) { + polylines(nsfb, path_loop, pts, pen); + } + + free(pts); + + return true; +} + bool select_plotters(nsfb_t *nsfb) { const nsfb_plotter_fns_t *table = NULL; @@ -652,6 +712,8 @@ bool select_plotters(nsfb_t *nsfb) nsfb->plotter_fns->arc = arc; nsfb->plotter_fns->quadratic = quadratic; nsfb->plotter_fns->cubic = cubic; + nsfb->plotter_fns->path = path; + nsfb->plotter_fns->polylines = polylines; /* set default clip rectangle to size of framebuffer */ nsfb->clip.x0 = 0; diff --git a/test/Makefile b/test/Makefile index dcb3d8f..b408f4a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,3 +1,3 @@ -DIR_TEST_ITEMS := plottest:plottest.c;nsglobe.c frontend:frontend.c bezier:bezier.c +DIR_TEST_ITEMS := plottest:plottest.c;nsglobe.c frontend:frontend.c bezier:bezier.c path:path.c polygon:polygon.c polystar:polystar.c include build/makefiles/Makefile.subdir diff --git a/test/path.c b/test/path.c new file mode 100644 index 0000000..26c471e --- /dev/null +++ b/test/path.c @@ -0,0 +1,92 @@ +/* libnsfb plotetr test program */ + +#include +#include +#include + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "libnsfb_event.h" + +#define UNUSED(x) ((x) = (x)) + +#define PENT(op, xco, yco) path[count].operation = op; \ + path[count].point.x = (xco); \ + path[count].point.y = (yco); \ + count++ + +static int fill_shape(nsfb_plot_pathop_t *path, int xoff, int yoff) +{ + int count = 0; + + PENT(NFSB_PLOT_PATHOP_MOVE, xoff, yoff); + PENT(NFSB_PLOT_PATHOP_LINE, xoff + 100, yoff + 100); + PENT(NFSB_PLOT_PATHOP_LINE, xoff + 100, yoff ); + PENT(NFSB_PLOT_PATHOP_LINE, xoff + 200, yoff + 100); + //PENT(NFSB_PLOT_PATHOP_MOVE, xoff + 200, yoff - 200); + //PENT(NFSB_PLOT_PATHOP_MOVE, xoff + 300, yoff + 300); + //PENT(NFSB_PLOT_PATHOP_CUBIC, xoff + 300, yoff ); + PENT(NFSB_PLOT_PATHOP_LINE, xoff + 400, yoff + 100); + PENT(NFSB_PLOT_PATHOP_LINE, xoff + 400, yoff ); + //PENT(NFSB_PLOT_PATHOP_MOVE, xoff + 500, yoff + 200); + //PENT(NFSB_PLOT_PATHOP_QUAD, xoff + 500, yoff ); + PENT(NFSB_PLOT_PATHOP_LINE, xoff + 600, yoff + 150); + PENT(NFSB_PLOT_PATHOP_LINE, xoff, yoff + 150); + PENT(NFSB_PLOT_PATHOP_LINE, xoff, yoff); + + return count; +} + +int main(int argc, char **argv) +{ + nsfb_t *nsfb; + nsfb_event_t event; + nsfb_bbox_t box; + uint8_t *fbptr; + int fbstride; + nsfb_plot_pen_t pen; + nsfb_plot_pathop_t path[20]; + + UNUSED(argc); + UNUSED(argv); + + nsfb = nsfb_init(NSFB_FRONTEND_SDL); + if (nsfb == NULL) { + fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n"); + return 1; + } + + if (nsfb_init_frontend(nsfb) == -1) { + fprintf(stderr, "Unable to initialise nsfb frontend\n"); + return 2; + } + + /* get the geometry of the whole screen */ + box.x0 = box.y0 = 0; + nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL); + + nsfb_get_framebuffer(nsfb, &fbptr, &fbstride); + + /* claim the whole screen for update */ + nsfb_claim(nsfb, &box); + + nsfb_plot_clg(nsfb, 0xffffffff); + + pen.stroke_colour = 0xff0000ff; + pen.fill_colour = 0xffff0000; + pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID; + pen.fill_type = NFSB_PLOT_OPTYPE_NONE; + + nsfb_plot_path(nsfb, fill_shape(path, 100, 100), path, &pen); + + pen.fill_type = NFSB_PLOT_OPTYPE_SOLID; + + nsfb_plot_path(nsfb, fill_shape(path, 100, 300), path, &pen); + + nsfb_update(nsfb, &box); + + while (event.type != NSFB_EVENT_CONTROL) + nsfb_event(nsfb, &event, -1); + + return 0; +} diff --git a/test/polygon.c b/test/polygon.c new file mode 100644 index 0000000..cd7efd8 --- /dev/null +++ b/test/polygon.c @@ -0,0 +1,79 @@ +/* libnsfb ploygon plotter test program */ + +#include +#include +#include +#include + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "libnsfb_event.h" + +#define UNUSED(x) ((x) = (x)) + + +int main(int argc, char **argv) +{ + nsfb_t *nsfb; + nsfb_event_t event; + nsfb_bbox_t box; + uint8_t *fbptr; + int fbstride; + + int sides; + int radius; + nsfb_point_t *points; + int loop; +// nsfb_plot_pen_t pen; + + UNUSED(argc); + UNUSED(argv); + + nsfb = nsfb_init(NSFB_FRONTEND_SDL); + if (nsfb == NULL) { + fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n"); + return 1; + } + + if (nsfb_init_frontend(nsfb) == -1) { + fprintf(stderr, "Unable to initialise nsfb frontend\n"); + return 2; + } + + /* get the geometry of the whole screen */ + box.x0 = box.y0 = 0; + nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL); + + nsfb_get_framebuffer(nsfb, &fbptr, &fbstride); + + /* claim the whole screen for update */ + nsfb_claim(nsfb, &box); + + nsfb_plot_clg(nsfb, 0xffffffff); + + radius = (box.x1 / 3); + + for (sides = 13; sides >=3; sides--) { + points = malloc(sizeof(nsfb_point_t) * sides); + + for (loop = 0; loop < sides;loop++) { + points[loop].x = (box.x1 / 2) + + (radius * cos(loop * 2 * M_PI / sides)); + points[loop].y = (box.y1 / 2) + + (radius * sin(loop * 2 * M_PI / sides)); + } + + nsfb_plot_polygon(nsfb, (const int *)points, sides, + 0xff000000 | (0xffffff / (sides * 2))); + + free(points); + radius -= 25; + } + + nsfb_update(nsfb, &box); + + while (event.type != NSFB_EVENT_CONTROL) + nsfb_event(nsfb, &event, -1); + + return 0; +} diff --git a/test/polystar.c b/test/polystar.c new file mode 100644 index 0000000..9897458 --- /dev/null +++ b/test/polystar.c @@ -0,0 +1,89 @@ +/* libnsfb ploygon plotter test program */ + +#include +#include +#include +#include + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "libnsfb_event.h" + +#define UNUSED(x) ((x) = (x)) + + +int main(int argc, char **argv) +{ + nsfb_t *nsfb; + nsfb_event_t event; + nsfb_bbox_t box; + uint8_t *fbptr; + int fbstride; + + int sides; + int radius; + nsfb_point_t *points; + int loop; + nsfb_plot_pen_t pen; + + UNUSED(argc); + UNUSED(argv); + + nsfb = nsfb_init(NSFB_FRONTEND_SDL); + if (nsfb == NULL) { + fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n"); + return 1; + } + + if (nsfb_init_frontend(nsfb) == -1) { + fprintf(stderr, "Unable to initialise nsfb frontend\n"); + return 2; + } + + /* get the geometry of the whole screen */ + box.x0 = box.y0 = 0; + nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL); + + nsfb_get_framebuffer(nsfb, &fbptr, &fbstride); + + /* claim the whole screen for update */ + nsfb_claim(nsfb, &box); + + pen.stroke_colour = 0xff000000; + pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID; + + nsfb_plot_clg(nsfb, 0xffffffff); + + radius = (box.y1 / 2); + + for (sides = 14; sides >=6; sides-=2) { + points = malloc(sizeof(nsfb_point_t) * sides); + + for (loop = 0; loop < sides;loop+=2) { + points[loop].x = (box.x1 / 2) + + (radius * cos(loop * 2 * M_PI / sides)); + points[loop].y = (box.y1 / 2) + + (radius * sin(loop * 2 * M_PI / sides)); + + points[loop+1].x = (box.x1 / 2) + + ((radius / 3) * cos((loop+1) * 2 * M_PI / sides)); + points[loop+1].y = (box.y1 / 2) + + ((radius / 3) * sin((loop+1) * 2 * M_PI / sides)); + } + + nsfb_plot_polygon(nsfb, (const int *)points, sides, + 0xff000000 | (0xffffff / (sides * 2))); + + nsfb_plot_polylines(nsfb, sides, points, &pen); + + free(points); + radius -= 40; + } + + nsfb_update(nsfb, &box); + + while (event.type != NSFB_EVENT_CONTROL) + nsfb_event(nsfb, &event, -1); + + return 0; +} diff --git a/test/runtest.sh b/test/runtest.sh new file mode 100755 index 0000000..b9ab599 --- /dev/null +++ b/test/runtest.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +TEST_PATH=$1 + +${TEST_PATH}/test_frontend +${TEST_PATH}/test_plottest +${TEST_PATH}/test_bezier +${TEST_PATH}/test_path +${TEST_PATH}/test_polygon +${TEST_PATH}/test_polystar + -- cgit v1.2.3