[PATCH v2 2/4] GUI: Add code to draw simple graphics

Andrey Smirnov andrew.smirnov at gmail.com
Thu Jun 23 22:35:33 PDT 2016


Add code to draw simple graphics, namely lines(solid or dashed) and
circles.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 include/gui/2d-primitives.h |  15 ++++
 lib/gui/2d-primitives.c     | 199 ++++++++++++++++++++++++++++++++++++++++++++
 lib/gui/Kconfig             |   3 +
 lib/gui/Makefile            |   1 +
 4 files changed, 218 insertions(+)
 create mode 100644 include/gui/2d-primitives.h
 create mode 100644 lib/gui/2d-primitives.c

diff --git a/include/gui/2d-primitives.h b/include/gui/2d-primitives.h
new file mode 100644
index 0000000..06216bb
--- /dev/null
+++ b/include/gui/2d-primitives.h
@@ -0,0 +1,15 @@
+#ifndef __2D_PRIMITIVES__
+#define __2D_PRIMITIVES__
+
+#include <fb.h>
+
+void gu_draw_line(struct screen *sc,
+		  int x1, int y1, int x2, int y2,
+		  u8 r, u8 g, u8 b, u8 a,
+		  unsigned int dash);
+
+void gu_draw_circle(struct screen *sc,
+		    int x0, int y0, int radius,
+		    u8 r, u8 g, u8 b, u8 a);
+
+#endif
diff --git a/lib/gui/2d-primitives.c b/lib/gui/2d-primitives.c
new file mode 100644
index 0000000..f3814ee
--- /dev/null
+++ b/lib/gui/2d-primitives.c
@@ -0,0 +1,199 @@
+#include <common.h>
+#include <fb.h>
+#include <gui/graphic_utils.h>
+#include <linux/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <fs.h>
+#include <malloc.h>
+
+static void __illuminate(struct fb_info *info,
+			 int x, int y,
+			 u8 r, u8 g, u8 b, u8 a)
+{
+	void *pixel;
+
+	pixel  = fb_get_screen_base(info);
+	pixel += y * info->line_length + x * (info->bits_per_pixel >> 3);
+
+	gu_set_rgba_pixel(info, pixel, r, g, b, a);
+}
+
+static void illuminate(struct fb_info *info,
+		       bool invert,
+		       int x, int y,
+		       u8 r, u8 g, u8 b, u8 a)
+{
+	if (invert)
+		__illuminate(info, y, x,
+			     r, g, b, a);
+	else
+		__illuminate(info, x, y,
+			     r, g, b, a);
+
+}
+
+
+static void draw_simple_line(struct screen *sc,
+			     int x1, int y1,
+			     int x2, int y2,
+			     u8 r, u8 g, u8 b, u8 a,
+			     unsigned int dash)
+{
+	int x;
+	bool invert = false;
+	unsigned int pixel = 0;
+
+	BUG_ON(x1 != x2 &&
+	       y1 != y2);
+
+	if (x1 == x2) {
+		swap(x1, y1);
+		swap(x2, y2);
+		invert = true;
+	}
+
+	if (x1 > x2) {
+		swap(x1, x2);
+		swap(y1, y2);
+	}
+
+	for (x = x1; x < x2 - 1; x++) {
+		if (!dash ||
+		    (++pixel % (2 * dash)) < dash)
+			illuminate(sc->info,
+				   invert,
+				   x, y1,
+				   r, g, b, a);
+	}
+}
+
+/**
+ * gl_draw_line - draw a 2D dashed line between (x1, y1) and (x2,y2)
+ *
+ * @sc: screen to draw on
+ * @x1, @y1: first point defining the line
+ * @x2, @y2: second point defining the line
+ * @r, @g, @b, @a: line's color
+ * @dash: dash length (0 denotes solid line)
+ *
+ * gl_draw_line() implements integer version of Bresenham's algoritm
+ * as can be found here:
+ *
+ * http://www.idav.ucdavis.edu/education/GraphicsNotes/Bresenhams-Algorithm.pdf
+ */
+void gu_draw_line(struct screen *sc,
+		  int x1, int y1,
+		  int x2, int y2,
+		  u8 r, u8 g, u8 b, u8 a,
+		  unsigned int dash)
+{
+	int dx;
+	int dy;
+	int i, j, eps;
+	bool invert = false;
+	unsigned int pixel = 0;
+
+	BUG_ON(x1 < 0 || y1 < 0 ||
+	       x2 < 0 || y2 < 0);
+
+	if (x1 == x2 || y1 == y2) {
+		draw_simple_line(sc,
+				 x1, y1,
+				 x2, y2,
+				 r, g, b, a, dash);
+		return;
+	}
+
+	dx = abs(x2 - x1);
+	dy = abs(y2 - y1);
+
+	/*
+	 * First thing we need to determine "Driving Axis", as can be
+	 * seen below if Y-axis projection of the line is bigger than
+	 * X-axis projection we swap axes and pretend the X is Y and
+	 * vice versa
+	 */
+	if (dy > dx) {
+		swap(x1, y1);
+		swap(x2, y2);
+		swap(dx, dy);
+		invert = true;
+	}
+
+	/*
+	 * Second, we need to make sure that we will be traversing
+	 * driving axis in the direction of increment so we swap point
+	 * 1 with point 2 if x1 is greater than x2
+	 */
+	if (x1 > x2) {
+		swap(x1, x2);
+		swap(y1, y2);
+	}
+
+	j   = y1;
+	eps = dy - dx;
+
+	for (i = x1; i <= x2 - 1; i++) {
+		if (!dash ||
+		    (++pixel % (2 * dash)) > dash) {
+			illuminate(sc->info,
+				   invert,
+				   j, i,
+				   r, g, b, a);
+		} else {
+			printf("NOT illuminating pixel: %d\n", pixel);
+		}
+
+		if (eps >= 0) {
+			j += 1;
+			eps -= dx;
+		}
+
+		eps += dy;
+	}
+}
+
+/**
+ * gl_draw_circle - draw a 2D circle with center at (x0, y0)
+ *
+ * @sc: screen to draw on
+ * @x0, @y0: coordinates of circle's center
+ * @radius: circle's radius
+ * @r, @g, @b, @a: circle's color
+
+ *
+ * gu_draw_circle() implements midpoint circle algorithm as can be
+ * found here:
+ *
+ * https://en.wikipedia.org/wiki/Midpoint_circle_algorithm
+ */
+void gu_draw_circle(struct screen *sc,
+		    int x0, int y0, int radius,
+		    u8 r, u8 g, u8 b, u8 a)
+{
+	int x = radius;
+	int y = 0;
+	int e = 0;
+
+	BUG_ON(x0 < 0 || y0 < 0 || radius < 0);
+
+	while (x >= y) {
+		 __illuminate(sc->info, x0 + x, y0 + y, r, g, b, a);
+		 __illuminate(sc->info, x0 + y, y0 + x, r, g, b, a);
+		 __illuminate(sc->info, x0 - y, y0 + x, r, g, b, a);
+		 __illuminate(sc->info, x0 - x, y0 + y, r, g, b, a);
+		 __illuminate(sc->info, x0 - x, y0 - y, r, g, b, a);
+		 __illuminate(sc->info, x0 - y, y0 - x, r, g, b, a);
+		 __illuminate(sc->info, x0 + y, y0 - x, r, g, b, a);
+		 __illuminate(sc->info, x0 + x, y0 - y, r, g, b, a);
+
+		 y += 1;
+		 e += 1 + 2 * y;
+
+		 if (2 * (e - x) + 1 > 0) {
+			 x -= 1;
+			 e += 1 - 2 * x;
+		 }
+	}
+}
diff --git a/lib/gui/Kconfig b/lib/gui/Kconfig
index eac9597..2625d9f 100644
--- a/lib/gui/Kconfig
+++ b/lib/gui/Kconfig
@@ -6,6 +6,9 @@ config IMAGE_RENDERER
 
 if IMAGE_RENDERER
 
+config 2D_PRIMITIVES
+       bool
+
 config BMP
 	bool "bmp"
 
diff --git a/lib/gui/Makefile b/lib/gui/Makefile
index d4b26c4..31e6622 100644
--- a/lib/gui/Makefile
+++ b/lib/gui/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_IMAGE_RENDERER)	+= image_renderer.o graphic_utils.o
 obj-$(CONFIG_PNG)	+= png.o
 obj-$(CONFIG_LODEPNG)	+= png_lode.o lodepng.o
 obj-$(CONFIG_PICOPNG)	+= png_pico.o picopng.o
+obj-$(CONFIG_2D_PRIMITIVES) += 2d-primitives.o
-- 
2.5.5




More information about the barebox mailing list