From 97fcb49bfbe74fa17a52e63b2196d8a5c3b27d93 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Fri, 21 Nov 2014 16:06:34 +0200
Subject: [PATCH 08/16] fbsplash: support image and bar alignment and
 positioning

---
 miscutils/fbsplash.c | 91 +++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 76 insertions(+), 15 deletions(-)

diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c
index bc80f728c..9089131b8 100644
--- a/miscutils/fbsplash.c
+++ b/miscutils/fbsplash.c
@@ -53,6 +53,7 @@
 //usage:     "\n	-c	Hide cursor"
 //usage:     "\n	-d	Framebuffer device (default /dev/fb0)"
 //usage:     "\n	-i	Config file (var=value):"
+//usage:     "\n			IMAGE_ALIGN"
 //usage:     "\n			BAR_LEFT,BAR_TOP,BAR_WIDTH,BAR_HEIGHT"
 //usage:     "\n			BAR_R,BAR_G,BAR_B"
 //usage:     "\n	-f	Control pipe (else exit after drawing image)"
@@ -73,13 +74,38 @@
 
 #define ESC "\033"
 
+enum {
+	image_align,
+
+	image_posx,
+	image_posy,
+	bar_width,
+	bar_height,
+	bar_posx,
+	bar_posy,
+	bar_colr,
+	bar_colg,
+	bar_colb,
+
+	debug
+};
+
+#define nimage_align	ns[image_align]
+#define nbar_width	ns[bar_width]
+#define nbar_height	ns[bar_height]
+#define nbar_posx	ns[bar_posx]
+#define nbar_posy	ns[bar_posy]
+#define nbar_colr	ns[bar_colr]
+#define nbar_colg	ns[bar_colg]
+#define nbar_colb	ns[bar_colb]
+
 struct globals {
 #if DEBUG
 	bool bdebug_messages;	// enable/disable logging
 	FILE *logfile_fd;	// log file
 #endif
 	unsigned char *addr;	// pointer to framebuffer memory
-	unsigned ns[7];		// n-parameters
+	unsigned ns[debug+1];		// n-parameters
 	const char *image_filename;
 	int silent_tty, fd_tty_s;
 	bool do_not_draw;
@@ -96,14 +122,6 @@ struct globals {
 	SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
 } while (0)
 
-#define nbar_width	ns[0]	// progress bar width
-#define nbar_height	ns[1]	// progress bar height
-#define nbar_posx	ns[2]	// progress bar horizontal position
-#define nbar_posy	ns[3]	// progress bar vertical position
-#define nbar_colr	ns[4]	// progress bar color red component
-#define nbar_colg	ns[5]	// progress bar color green component
-#define nbar_colb	ns[6]	// progress bar color blue component
-
 #if DEBUG
 #define DEBUG_MESSAGE(strMessage, args...) \
 	if (G.bdebug_messages) { \
@@ -384,7 +402,7 @@ static void fb_drawimage(void)
 	FILE *theme_file;
 	char *read_ptr;
 	unsigned char *pixline;
-	unsigned i, j, width, height, line_size;
+	int i, j, width, height, line_size, xoffs, yoffs, xstart;
 
 	if (LONE_DASH(G.image_filename)) {
 		theme_file = stdin;
@@ -434,18 +452,46 @@ static void fb_drawimage(void)
 	line_size = width*3;
 	pixline = xmalloc(line_size);
 
+#if 0
 	if (width > G.scr_var.xres)
 		width = G.scr_var.xres;
 	if (height > G.scr_var.yres)
 		height = G.scr_var.yres;
-	for (j = 0; j < height; j++) {
+#endif
+
+	xoffs = yoffs = 0;
+	switch (G.nimage_align % 3) {
+	case 1: xoffs = (G.scr_var.xres - width) / 2; break;
+	case 2: xoffs = G.scr_var.xres - width; break;
+	}
+	xstart = 0;
+	if (xoffs < 0) {
+		xstart = -xoffs;
+		width -= xstart;
+		xoffs = 0;
+	}
+	xoffs *= G.bytes_per_pixel;
+	if (width > G.scr_var.xres)
+		width = G.scr_var.xres;
+
+	switch (G.nimage_align / 3) {
+	case 1: yoffs = (G.scr_var.yres - height) / 2; break;
+	case 2: yoffs = G.scr_var.yres - height; break;
+	}
+
+	for (j = 0; j < height && yoffs < G.scr_var.yres; j++, yoffs++) {
 		unsigned char *pixel;
 		unsigned char *src;
 
 		if (fread(pixline, 1, line_size, theme_file) != line_size)
 			bb_error_msg_and_die("bad PPM file '%s'", G.image_filename);
+
+		if (yoffs < 0)
+			continue;
+
 		pixel = pixline;
-		src = G.addr + j * G.scr_fix.line_length;
+		src = G.addr + yoffs * G.scr_fix.line_length + xoffs;
+
 		for (i = 0; i < width; i++) {
 			unsigned thispix = fb_pixel_value(pixel[0], pixel[1], pixel[2]);
 			fb_write_pixel(src, thispix);
@@ -464,9 +510,17 @@ static void fb_drawimage(void)
  */
 static void init(const char *cfg_filename)
 {
+	static const char align_names[] ALIGN1 =
+		"LT\0" "CT\0" "RT\0"
+		"LM\0" "CM\0" "RM\0"
+		"LB\0" "CB\0" "RB\0";
 	static const char param_names[] ALIGN1 =
+		"IMAGE_ALIGN\0"
+
+		"IMAGE_X\0" "IMAGE_Y\0"
 		"BAR_WIDTH\0" "BAR_HEIGHT\0"
 		"BAR_LEFT\0" "BAR_TOP\0"
+
 		"BAR_R\0" "BAR_G\0" "BAR_B\0"
 #if DEBUG
 		"DEBUG\0"
@@ -476,14 +530,21 @@ static void init(const char *cfg_filename)
 	parser_t *parser = config_open2(cfg_filename, xfopen_stdin);
 	while (config_read(parser, token, 2, 2, "#=",
 				(PARSE_NORMAL | PARSE_MIN_DIE) & ~(PARSE_TRIM | PARSE_COLLAPSE))) {
-		unsigned val = xatoi_positive(token[1]);
+		unsigned val;
 		int i = index_in_strings(param_names, token[0]);
+
 		if (i < 0)
 			bb_error_msg_and_die("syntax error: %s", token[0]);
-		if (i >= 0 && i < 7)
+
+		if (i <= image_align)
+			val = index_in_strings(align_names, token[1]);
+		else
+			val = xatoi_positive(token[1]);
+
+		if (i < debug)
 			G.ns[i] = val;
 #if DEBUG
-		if (i == 7) {
+		if (i == debug) {
 			G.bdebug_messages = val;
 			if (G.bdebug_messages)
 				G.logfile_fd = xfopen_for_write("/tmp/fbsplash.log");
-- 
2.16.2