summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@netsurf-browser.org>2010-01-06 22:26:55 +0000
committerVincent Sanders <vince@netsurf-browser.org>2010-01-06 22:26:55 +0000
commitfd3c7753435658a6aeebf1b68d18178a6c7cf57d (patch)
treef17b620b6f7831476cae8d4f97ca8c2f9cbaa7b5
parentdfc3faf3fdf331e806cf43971c2251e65111f065 (diff)
downloadlibnsfb-fd3c7753435658a6aeebf1b68d18178a6c7cf57d.tar.gz
libnsfb-fd3c7753435658a6aeebf1b68d18178a6c7cf57d.tar.bz2
add bezier curve plotters
svn path=/trunk/libnsfb/; revision=9794
-rw-r--r--include/libnsfb.h20
-rw-r--r--include/libnsfb_plot.h4
-rw-r--r--include/nsfb_plot.h10
-rw-r--r--src/plot.c11
-rw-r--r--src/plotters.c88
-rw-r--r--test/Makefile2
-rw-r--r--test/bezier.c112
7 files changed, 246 insertions, 1 deletions
diff --git a/include/libnsfb.h b/include/libnsfb.h
index 5975768..41490ad 100644
--- a/include/libnsfb.h
+++ b/include/libnsfb.h
@@ -15,9 +15,29 @@
typedef struct nsfb_cursor_s nsfb_cursor_t;
typedef struct nsfb_s nsfb_t;
+
+/** representation of a colour.
+ *
+ * The colour value comprises of four components arranged in the order ABGR:
+ * bits 24-31 are the alpha value and represent the opacity. 0 is
+ * transparent i.e. there would be no change in the target surface if
+ * this colour were to be used and 0xFF is opaque.
+ *
+ * bits 16-23 are the Blue component of the colour.
+ *
+ * bits 8-15 are the Green component of the colour.
+ *
+ * bits 0-7 are the Red component of the colour.
+ */
typedef uint32_t nsfb_colour_t;
typedef struct nsfb_event_s nsfb_event_t;
+/** co-ordinate for plotting operations */
+typedef struct nsfb_point_s {
+ int x;
+ int y;
+} nsfb_point_t;
+
/** bounding box for plotting operations */
typedef struct nsfb_bbox_s {
int x0;
diff --git a/include/libnsfb_plot.h b/include/libnsfb_plot.h
index 45aad28..1d420b0 100644
--- a/include/libnsfb_plot.h
+++ b/include/libnsfb_plot.h
@@ -78,6 +78,10 @@ bool nsfb_plot_arc(nsfb_t *nsfb, int x, int y, int radius, int angle1, int angle
*/
bool nsfb_plot_point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c);
+bool nsfb_plot_cubic_bezier(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_point_t *ctrlb, nsfb_colour_t c);
+
+bool nsfb_plot_quadratic_bezier(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_colour_t cl);
+
/** copy an area of screen
*
* Copy an area of the display.
diff --git a/include/nsfb_plot.h b/include/nsfb_plot.h
index 790a923..52af7cd 100644
--- a/include/nsfb_plot.h
+++ b/include/nsfb_plot.h
@@ -83,6 +83,14 @@ typedef bool (nsfb_plotfn_glyph1_t)(nsfb_t *nsfb, nsfb_bbox_t *loc, const uint8_
*/
typedef bool (nsfb_plotfn_readrect_t)(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer);
+/** Plot quadratic bezier spline
+ */
+typedef bool (nsfb_plotfn_quadratic_bezier_t)(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_colour_t c);
+
+/** Plot cubic bezier spline
+ */
+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);
+
/** plotter function table. */
typedef struct nsfb_plotter_fns_s {
nsfb_plotfn_clg_t *clg;
@@ -101,6 +109,8 @@ typedef struct nsfb_plotter_fns_s {
nsfb_plotfn_glyph8_t *glyph8;
nsfb_plotfn_glyph1_t *glyph1;
nsfb_plotfn_readrect_t *readrect;
+ nsfb_plotfn_quadratic_bezier_t *quadratic;
+ nsfb_plotfn_cubic_bezier_t *cubic;
} nsfb_plotter_fns_t;
diff --git a/src/plot.c b/src/plot.c
index 55437cf..6303127 100644
--- a/src/plot.c
+++ b/src/plot.c
@@ -140,3 +140,14 @@ bool nsfb_plot_readrect(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer)
{
return nsfb->plotter_fns->readrect(nsfb, rect, buffer);
}
+
+
+bool nsfb_plot_cubic_bezier(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_point_t *ctrlb, nsfb_colour_t c)
+{
+ return nsfb->plotter_fns->cubic(nsfb, curve, ctrla, ctrlb, c);
+}
+
+bool nsfb_plot_quadratic_bezier(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_colour_t c)
+{
+ return nsfb->plotter_fns->quadratic(nsfb, curve, ctrla, c);
+}
diff --git a/src/plotters.c b/src/plotters.c
index 82deb0f..60826d3 100644
--- a/src/plotters.c
+++ b/src/plotters.c
@@ -435,6 +435,8 @@ static bool ellipse_fill(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c)
}
}
+
+
/* copy an area of screen from one location to another.
*
* @warning This implementation is woefully incomplete!
@@ -504,6 +506,90 @@ static bool arc(nsfb_t *nsfb, int x, int y, int radius, int angle1, int angle2,
return true;
}
+#define N_SEG 30
+
+static bool cubic(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_point_t *ctrlb, nsfb_colour_t cl)
+{
+ nsfb_bbox_t line;
+
+ unsigned int seg_loop;
+ double t;
+ double one_minus_t;
+ double a;
+ double b;
+ double c;
+ double d;
+ double x;
+ double y;
+
+ x = curve->x0;
+ y = curve->y0;
+
+ for (seg_loop = 1; seg_loop <= N_SEG; ++seg_loop) {
+ t = (double)seg_loop / (double)N_SEG;
+
+ one_minus_t = 1.0 - t;
+
+ a = one_minus_t * one_minus_t * one_minus_t;
+ b = 3.0 * t * one_minus_t * one_minus_t;
+ c = 3.0 * t * t * one_minus_t;
+ d = t * t * t;
+
+ line.x0 = x;
+ line.y0 = y;
+
+ x = a * curve->x0 + b * ctrla->x + c * ctrlb->x + d * curve->x1;
+ y = a * curve->y0 + b * ctrla->y + c * ctrlb->y + d * curve->y1;
+
+ line.x1 = x;
+ line.y1 = y;
+
+ nsfb->plotter_fns->line(nsfb, &line, 1, cl, false, false);
+ }
+
+ return true;
+}
+
+static bool quadratic(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_colour_t cl)
+{
+ nsfb_bbox_t line;
+
+ unsigned int seg_loop;
+ double t;
+ double one_minus_t;
+ double a;
+ double b;
+ double c;
+ double x;
+ double y;
+
+ x = curve->x0;
+ y = curve->y0;
+
+ for (seg_loop = 1; seg_loop <= N_SEG; ++seg_loop) {
+ t = (double)seg_loop / (double)N_SEG;
+
+ one_minus_t = 1.0 - t;
+
+ a = one_minus_t * one_minus_t;
+ b = 2.0 * t * one_minus_t;
+ c = t * t;
+
+ line.x0 = x;
+ line.y0 = y;
+
+ x = a * curve->x0 + b * ctrla->x + c * curve->x1;
+ y = a * curve->y0 + b * ctrla->y + c * curve->y1;
+
+ line.x1 = x;
+ line.y1 = y;
+
+ nsfb->plotter_fns->line(nsfb, &line, 1, cl, false, false);
+ }
+
+ return true;
+}
+
bool select_plotters(nsfb_t *nsfb)
{
const nsfb_plotter_fns_t *table;
@@ -550,6 +636,8 @@ bool select_plotters(nsfb_t *nsfb)
nsfb->plotter_fns->ellipse_fill = ellipse_fill;
nsfb->plotter_fns->copy = copy;
nsfb->plotter_fns->arc = arc;
+ nsfb->plotter_fns->quadratic = quadratic;
+ nsfb->plotter_fns->cubic = cubic;
/* set default clip rectangle to size of framebuffer */
nsfb->clip.x0 = 0;
diff --git a/test/Makefile b/test/Makefile
index 6d4f4fa..dcb3d8f 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,3 +1,3 @@
-DIR_TEST_ITEMS := plottest:plottest.c;nsglobe.c frontend:frontend.c
+DIR_TEST_ITEMS := plottest:plottest.c;nsglobe.c frontend:frontend.c bezier:bezier.c
include build/makefiles/Makefile.subdir
diff --git a/test/bezier.c b/test/bezier.c
new file mode 100644
index 0000000..d44779b
--- /dev/null
+++ b/test/bezier.c
@@ -0,0 +1,112 @@
+/* libnsfb plotetr test program */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#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;
+ nsfb_bbox_t box2;
+ uint8_t *fbptr;
+ int fbstride;
+ nsfb_point_t ctrla;
+ nsfb_point_t ctrlb;
+ int loop;
+
+ 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);
+
+ box2.x0=100;
+ box2.y0=100;
+
+ box2.x1=400;
+ box2.y1=400;
+
+ for (loop=-300;loop < 600;loop+=100) {
+ ctrla.x = 100;
+ ctrla.y = loop;
+
+ ctrlb.x = 400;
+ ctrlb.y = 500 - loop;
+
+ nsfb_plot_cubic_bezier(nsfb, &box2, &ctrla, &ctrlb, 0xff000000);
+ }
+
+
+ box2.x0=400;
+ box2.y0=100;
+
+ box2.x1=600;
+ box2.y1=400;
+
+ nsfb_plot_line(nsfb, &box2, 1, 0xff000000, false, false);
+
+ box2.x0=800;
+ box2.y0=100;
+
+ box2.x1=600;
+ box2.y1=400;
+
+ nsfb_plot_line(nsfb, &box2, 1, 0xff000000, false, false);
+
+ box2.x0=400;
+ box2.y0=100;
+
+ box2.x1=800;
+ box2.y1=100;
+
+ ctrla.x = 600;
+ ctrla.y = 400;
+
+ nsfb_plot_cubic_bezier(nsfb, &box2, &ctrla, &ctrla, 0xffff0000);
+
+ box2.x0=400;
+ box2.y0=100;
+
+ box2.x1=800;
+ box2.y1=100;
+
+ ctrla.x = 600;
+ ctrla.y = 400;
+
+ nsfb_plot_quadratic_bezier(nsfb, &box2, &ctrla, 0xff0000ff);
+
+ nsfb_update(nsfb, &box);
+
+ while (event.type != NSFB_EVENT_CONTROL)
+ nsfb_event(nsfb, &event, -1);
+
+ return 0;
+}