[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    patch to enable text overlay on framebuffer via fbsplash
From:       "Richard Moore" <rich () richud ! com>
Date:       2018-01-08 14:58:03
Message-ID: d648ef40998df909b39c8936a8ad1aed.squirrel () mail ! scaryscary ! com
[Download RAW message or body]

Hi,

Patch attached to add text overlay support to fbsplash which currently
only supports displaying images.

With the recent kernel inclusion of 'fbtft' (CONFIG_FB_TFT) many small
screen/OLED/TFT/LCD screen driver chips now have native framebuffer
support in the kernel.

These are often used on devices such as Raspberry Pi for simple
feedback/information displaying/signage etc. and it would be useful to
have a simple way to display text as well as just an image.
For example a 0.96" OLED screen attached via SPI, small thermometer
pictures as the background image and then overlaying the current
indoor/outdoor temperature as text.

This patch is the simplest way I could think of to implement, yet still be
usable.
It allows text to be displayed using some simple markup escape codes to
move it around, scale it and colour it. This allows it to be fairly
dynamic in usage not needing separate config files.
(It is based on a patch submitted several years ago my Michele Sanges.)



Regards


Richard Moore
["busybox_fbsplash.c.patch" (text/x-patch)]

--- miscutils/fbsplash.c.orig	2016-12-10 17:46:36.000000000 +0000
+++ miscutils/fbsplash.c	2018-01-08 09:18:46.183162038 +0000
@@ -11,6 +11,7 @@
  *      -c: hide cursor
  *      -d /dev/fbN: framebuffer device (if not /dev/fb0)
  *      -s path_to_image_file (can be "-" for stdin)
+ *      -t text string overlay (with simple markup langauge)
  *      -i path_to_cfg_file
  *      -f path_to_fifo (can be "-" for stdin)
  * - if you want to run it only in presence of a kernel parameter
@@ -34,6 +35,7 @@
 //config:	    -c: hide cursor
 //config:	    -d /dev/fbN: framebuffer device (if not /dev/fb0)
 //config:	    -s path_to_image_file (can be "-" for stdin)
+//config:	    -t text string overlay (with simple markup langauge)
 //config:	    -i path_to_cfg_file (can be "-" for stdin)
 //config:	    -f path_to_fifo (can be "-" for stdin)
 //config:	  - if you want to run it only in presence of kernel parameter:
@@ -47,9 +49,12 @@
 //kbuild:lib-$(CONFIG_FBSPLASH) += fbsplash.o
 
 //usage:#define fbsplash_trivial_usage
-//usage:       "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD]"
+//usage:       "-s IMGFILE [-c] [-t STRING] [-d DEV] [-i INIFILE] [-f CMD]"
 //usage:#define fbsplash_full_usage "\n\n"
 //usage:       "	-s	Image"
+//usage:     "\n	-t	Text String Overlay (with simple markup language)"
+//usage:     "\n			x% \\x[0-9] y% \\y[0-9] size \\s[1-4]"
+//usage:     "\n			nudge \\[udlr][1-9] colour \\c[000000-FFFFFF]"
 //usage:     "\n	-c	Hide cursor"
 //usage:     "\n	-d	Framebuffer device (default /dev/fb0)"
 //usage:     "\n	-i	Config file (var=value):"
@@ -105,6 +110,108 @@
 #endif
 
 /**
+ * Public domain basic 8x8 ascii / XBM style font for -t text arg.
+ */
+static char fontmap[96][8] = {
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0020 (space)
+    { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00},   // U+0021 (!)
+    { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0022 (")
+    { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00},   // U+0023 (#)
+    { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00},   // U+0024 ($)
+    { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00},   // U+0025 (%)
+    { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00},   // U+0026 (&)
+    { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0027 (')
+    { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00},   // U+0028 (()
+    { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00},   // U+0029 ())
+    { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00},   // U+002A (*)
+    { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00},   // U+002B (+)
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06},   // U+002C (,)
+    { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00},   // U+002D (-)
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00},   // U+002E (.)
+    { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00},   // U+002F (/)
+    { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00},   // U+0030 (0)
+    { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00},   // U+0031 (1)
+    { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00},   // U+0032 (2)
+    { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00},   // U+0033 (3)
+    { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00},   // U+0034 (4)
+    { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00},   // U+0035 (5)
+    { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00},   // U+0036 (6)
+    { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00},   // U+0037 (7)
+    { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00},   // U+0038 (8)
+    { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00},   // U+0039 (9)
+    { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00},   // U+003A (:)
+    { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06},   // U+003B (//)
+    { 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00},   // U+003C (<)
+    { 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00},   // U+003D (=)
+    { 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00},   // U+003E (>)
+    { 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00},   // U+003F (?)
+    { 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00},   // U+0040 (@)
+    { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00},   // U+0041 (A)
+    { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00},   // U+0042 (B)
+    { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00},   // U+0043 (C)
+    { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00},   // U+0044 (D)
+    { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00},   // U+0045 (E)
+    { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00},   // U+0046 (F)
+    { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00},   // U+0047 (G)
+    { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00},   // U+0048 (H)
+    { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+0049 (I)
+    { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00},   // U+004A (J)
+    { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00},   // U+004B (K)
+    { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00},   // U+004C (L)
+    { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00},   // U+004D (M)
+    { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00},   // U+004E (N)
+    { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00},   // U+004F (O)
+    { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00},   // U+0050 (P)
+    { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00},   // U+0051 (Q)
+    { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00},   // U+0052 (R)
+    { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00},   // U+0053 (S)
+    { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+0054 (T)
+    { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00},   // U+0055 (U)
+    { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00},   // U+0056 (V)
+    { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00},   // U+0057 (W)
+    { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00},   // U+0058 (X)
+    { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00},   // U+0059 (Y)
+    { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00},   // U+005A (Z)
+    { 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00},   // U+005B ([)
+    { 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00},   // U+005C (\)
+    { 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00},   // U+005D (])
+    { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00},   // U+005E (^)
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},   // U+005F (_)
+    { 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0060 (`)
+    { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00},   // U+0061 (a)
+    { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00},   // U+0062 (b)
+    { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00},   // U+0063 (c)
+    { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00},   // U+0064 (d)
+    { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00},   // U+0065 (e)
+    { 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00},   // U+0066 (f)
+    { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F},   // U+0067 (g)
+    { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00},   // U+0068 (h)
+    { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+0069 (i)
+    { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E},   // U+006A (j)
+    { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00},   // U+006B (k)
+    { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+006C (l)
+    { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00},   // U+006D (m)
+    { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00},   // U+006E (n)
+    { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00},   // U+006F (o)
+    { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F},   // U+0070 (p)
+    { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78},   // U+0071 (q)
+    { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00},   // U+0072 (r)
+    { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00},   // U+0073 (s)
+    { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00},   // U+0074 (t)
+    { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00},   // U+0075 (u)
+    { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00},   // U+0076 (v)
+    { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00},   // U+0077 (w)
+    { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00},   // U+0078 (x)
+    { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F},   // U+0079 (y)
+    { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00},   // U+007A (z)
+    { 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00},   // U+007B ({)
+    { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00},   // U+007C (|)
+    { 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00},   // U+007D (})
+    { 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+007E (~)
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}    // U+007F
+};
+
+/**
  * Configure palette for RGB:332
  */
 static void fb_setpal(int fd)
@@ -449,6 +556,105 @@
 
 
 /**
+ * Draws a single character on framebuffer.
+ * \param nXPos horizontal position from which draw the character.
+ * \param nYPos vertical position from which draw the character.
+ * \param nCharSize character scale factor [1..4].
+ * \param nChar character to draw.
+ */
+static void fb_drawchar(int nXPos, int nYPos, int nCharSize, int nChar, unsigned \
thispix) +{
+	unsigned *ptr;
+
+	for (int nHeight = 0; nHeight < 8 * nCharSize; nHeight++) {
+		for (int nWidth = 0; nWidth < 8 * nCharSize; nWidth++) {
+			ptr = (unsigned *)(G.addr + ((nYPos + nHeight) * G.scr_var.xres + (nXPos + \
nWidth)) * G.bytes_per_pixel); +			if ((fontmap[nChar - 32][nHeight / nCharSize] & \
(0x1 << (nWidth / nCharSize))) != 0) { +				*ptr = thispix;
+			}
+		}
+	}
+}
+
+
+/**
+ * Draws a string on framebuffer.
+ * \param text_str text string from getopt32
+ * Example -t "\x1\y5\s2\cFF00FFSome text"
+ * Would display magenta coloured text at 10% x and 50% y scale size 2.
+ */
+static void fb_drawstring(const char *txt_str)
+{
+	int x = 0;		//0-9 = 0% - 90% top left x position
+	int y = 0;
+	int siz = 2;		//scaling size 1 - 4
+	int nred = 255 >> 3; 	// 5-bit red
+	int ngreen = 255 >> 2;  // 6-bit green
+	int nblue = 255 >> 3; 	// 5-bit blue
+	char buf[3];
+	int val;
+
+	for (int nCharNum = 0; nCharNum < strlen(txt_str); nCharNum++) {
+
+		if(*(txt_str + nCharNum) == 92 ) {	//escape code
+
+			val = *(txt_str + nCharNum + 2) - '0';
+			switch(*(txt_str + nCharNum + 1)) {
+				case 110:		// newline \n
+					y += siz * 12;
+					x = 0;
+					nCharNum++;
+					continue;
+				case 115:		// text size \s
+					if (val < 1)
+						siz = 1;
+					else if (val > 4)
+						siz = 4;
+					else
+						siz = val;
+					nCharNum+=2;
+					continue;
+				case 117:		// nudge up pixels /u
+					y -= val;
+					nCharNum+=2;
+					continue;
+				case 100:		// nudge down pixels /d
+					y += val;
+					nCharNum+=2;
+					continue;
+				case 108:		// nudge left pixels /l
+					x -= val;
+					nCharNum+=2;
+					continue;
+				case 114:		// nudge right pixels /r
+					x += val;
+					nCharNum+=2;
+					continue;
+				case 120:		// x position % of screen \x
+					x = G.scr_var.xres * val/10;
+					nCharNum+=2;
+					continue;
+				case 121:		// y position % of screen \y
+					y = G.scr_var.yres * val/10;
+					nCharNum+=2;
+					continue;
+				case 99:		// colour \c ,  hex triplet format RGB 888 > RGB 565
+					sprintf(buf, "%c%c", *(txt_str + nCharNum + 2), *(txt_str + nCharNum + 3));
+					nred = strtol(buf, NULL, 16) >> 3;
+					sprintf(buf, "%c%c", *(txt_str + nCharNum + 4), *(txt_str + nCharNum + 5));
+					ngreen = strtol(buf, NULL, 16) >> 2;
+					sprintf(buf, "%c%c", *(txt_str + nCharNum + 6), *(txt_str + nCharNum + 7));
+					nblue = strtol(buf, NULL, 16) >> 3;
+					nCharNum+=7;
+					continue;
+			}
+		}
+		fb_drawchar(abs(x), abs(y), siz, *(txt_str + nCharNum), (nblue + (ngreen << 5) + \
(nred << (5+6)))); +		x += siz * 8;
+	}
+}
+
+/*
  * Parse configuration file
  * \param *cfg_filename name of the configuration file
  */
@@ -487,7 +693,7 @@
 int fbsplash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int fbsplash_main(int argc UNUSED_PARAM, char **argv)
 {
-	const char *fb_device, *cfg_filename, *fifo_filename;
+	const char *fb_device, *cfg_filename, *fifo_filename, *txt_str;
 	FILE *fp = fp; // for compiler
 	char *num_buf;
 	unsigned num;
@@ -499,8 +705,9 @@
 	fb_device = "/dev/fb0";
 	cfg_filename = NULL;
 	fifo_filename = NULL;
-	bCursorOff = 1 & getopt32(argv, "cs:d:i:f:",
-			&G.image_filename, &fb_device, &cfg_filename, &fifo_filename);
+	txt_str = NULL;
+	bCursorOff = 1 & getopt32(argv, "cs:t:d:i:f:",
+			&G.image_filename, &txt_str, &fb_device, &cfg_filename, &fifo_filename);
 
 	// parse configuration file
 	if (cfg_filename)
@@ -519,6 +726,9 @@
 
 	fb_drawimage();
 
+	if (txt_str)
+		fb_drawstring(txt_str);
+
 	if (!fifo_filename)
 		return EXIT_SUCCESS;
 



_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic