~calebccff/pbsplash

Various fixes and improvements v1 APPLIED

Here's the patchset that makes it look like in the video [1], when used
together with the logo [2]. After making the video I've tweaked the
font placement some more, the line at the bottom is now smaller and at
the very bottom; and the other description text is just above that
bottom line. I'd suggest now to also include the "Loading..." text while
displaying the animation, it looks good now IMHO. I'll write remaining
TODOs for integrating this into postmarketOS into the pmaports MR [3].

[1]: https://fosstodon.org/@ollieparanoid/108727375211035890
[2]: https://gitlab.com/postmarketOS/artwork/-/blob/master/logo/pmos-splash-screen.svg
[3]: https://gitlab.com/postmarketOS/pmaports/-/merge_requests/2878


Oliver Smith (13):
  usage: fix argument line
  getopt: fix error msg for invalid dpi
  getopt: remove unneeded check for -d
  getopt: make logo_size_max configurable with -q
  animate: fix fill_rect height
  Tweak the animation and placement
  Support multiple message lines
  include: add missing declarations
  nanosvg: build implementation in extra c file
  nsvgGetTextShapes: fix uninitialized values
  Support message line at the bottom
  Move regular message further down
  Add argument to disable animation

 include/nanosvg.h     |   6 ++-
 include/nanosvgrast.h |   8 +++-
 include/pbsplash.h    |   2 +-
 src/animate.c         |  18 ++++----
 src/meson.build       |   3 +-
 src/nanosvg.c         |   9 ++++
 src/pbsplash.c        | 101 ++++++++++++++++++++++++++++++++----------
 7 files changed, 110 insertions(+), 37 deletions(-)
 create mode 100644 src/nanosvg.c

-- 
2.34.3
Hi Ollie,

Thanks for this series, lots of goodies, just figuring my way around the nicest 
way to apply it all.

I just realised I have a local commit which adds support for newlines which I 
forgot to push, I tested it with the original messages and they all render 
properly now, I guess that's the problem you were trying to solve with this patch?

If so, I'll drop this in favour of my patch.

Kind Regards,
Caleb
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~calebccff/pbsplash/patches/34340/mbox | git am -3
Learn more about email & git

[PATCH 01/13] usage: fix argument line Export this patch

Add missing arguments, order them the same as listed below.
---
 src/pbsplash.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/pbsplash.c b/src/pbsplash.c
index d4070d3..629bdfe 100644
--- a/src/pbsplash.c
+++ b/src/pbsplash.c
@@ -47,7 +47,8 @@ int usage()
	// clang-format off
	fprintf(stderr, "pbsplash: postmarketOS bootsplash generator\n");
	fprintf(stderr, "-------------------------------------------\n");
	fprintf(stderr, "pbsplash [-h] [-d] [-f font] [-s splash image] [-m message]\n\n");
	fprintf(stderr, "pbsplash [-v] [-h] [-f font] [-s splash image] [-m message]\n");
	fprintf(stderr, "         [-p font size] [-d]\n\n");
	fprintf(stderr, "    -v           enable verbose logging\n");
	fprintf(stderr, "    -h           show this help\n");
	fprintf(stderr, "    -f           path to SVG font file (default: %s)\n", DEFAULT_FONT_PATH);
-- 
2.34.3

[PATCH 02/13] getopt: fix error msg for invalid dpi Export this patch

---
 src/pbsplash.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pbsplash.c b/src/pbsplash.c
index 629bdfe..5b16e93 100644
--- a/src/pbsplash.c
+++ b/src/pbsplash.c
@@ -231,7 +231,7 @@ int main(int argc, char **argv)
			}
			dpi = strtol(optarg, &end, 10);
			if (end == optarg) {
				fprintf(stderr, "Invalid font size: %s\n",
				fprintf(stderr, "Invalid dpi: %s\n",
					optarg);
				return usage();
			}
-- 
2.34.3

[PATCH 03/13] getopt: remove unneeded check for -d Export this patch

Remove the extra check for a value after specifying -d, as getopt() is
already taking care of it:

  pbsplash: option requires an argument: d
---
 src/pbsplash.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/pbsplash.c b/src/pbsplash.c
index 5b16e93..2cce927 100644
--- a/src/pbsplash.c
+++ b/src/pbsplash.c
@@ -225,10 +225,6 @@ int main(int argc, char **argv)
			}
			break;
		case 'd':
			if (!optarg) {
				fprintf(stderr, "--dpi requires an argument\n");
				return usage();
			}
			dpi = strtol(optarg, &end, 10);
			if (end == optarg) {
				fprintf(stderr, "Invalid dpi: %s\n",
-- 
2.34.3

[PATCH 04/13] getopt: make logo_size_max configurable with -q Export this patch

---
 src/pbsplash.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/src/pbsplash.c b/src/pbsplash.c
index 2cce927..7c80085 100644
--- a/src/pbsplash.c
+++ b/src/pbsplash.c
@@ -48,13 +48,14 @@ int usage()
	fprintf(stderr, "pbsplash: postmarketOS bootsplash generator\n");
	fprintf(stderr, "-------------------------------------------\n");
	fprintf(stderr, "pbsplash [-v] [-h] [-f font] [-s splash image] [-m message]\n");
	fprintf(stderr, "         [-p font size] [-d]\n\n");
	fprintf(stderr, "         [-p font size] [-q max logo size] [-d]\n\n");
	fprintf(stderr, "    -v           enable verbose logging\n");
	fprintf(stderr, "    -h           show this help\n");
	fprintf(stderr, "    -f           path to SVG font file (default: %s)\n", DEFAULT_FONT_PATH);
	fprintf(stderr, "    -s           path to splash image to display\n");
	fprintf(stderr, "    -m           message to show under the splash image\n");
	fprintf(stderr, "    -p           font size in pt (default: %d)\n", FONT_SIZE_PT);
	fprintf(stderr, "    -q           max logo size in mm (default: %d)\n", LOGO_SIZE_MAX_MM);
	fprintf(stderr, "    -d           custom DPI (for testing)\n");
	// clang-format on

@@ -188,6 +189,7 @@ int main(int argc, char **argv)
	NSVGimage *font = NULL;
	struct sigaction action;
	float font_size = FONT_SIZE_PT;
	float logo_size_max = LOGO_SIZE_MAX_MM;
	int optflag;
	long dpi = 0;

@@ -199,7 +201,7 @@ int main(int argc, char **argv)
	sigaction(SIGTERM, &action, NULL);
	sigaction(SIGINT, &action, NULL);

	while ((optflag = getopt(argc, argv, "hvf:s:m:p:d:")) != -1) {
	while ((optflag = getopt(argc, argv, "hvf:s:m:p:q:d:")) != -1) {
		char *end = NULL;
		switch (optflag) {
		case 'h':
@@ -224,6 +226,14 @@ int main(int argc, char **argv)
				return usage();
			}
			break;
		case 'q':
			logo_size_max = strtof(optarg, &end);
			if (end == optarg) {
				fprintf(stderr, "Invalid max logo size: %s\n",
					optarg);
				return usage();
			}
			break;
		case 'd':
			dpi = strtol(optarg, &end, 10);
			if (end == optarg) {
@@ -276,12 +286,12 @@ int main(int argc, char **argv)
	float logo_size_px = (float)(w < h ? w : h) * 0.75f;
	if (w_mm > 0 && h_mm > 0) {
		if (w_mm < h_mm) {
			if (w_mm > (float)LOGO_SIZE_MAX_MM * 1.2f)
				logo_size_px = (float)LOGO_SIZE_MAX_MM *
			if (w_mm > logo_size_max * 1.2f)
				logo_size_px = logo_size_max *
					       pixels_per_milli;
		} else {
			if (h_mm > (float)LOGO_SIZE_MAX_MM * 1.2f)
				logo_size_px = (float)LOGO_SIZE_MAX_MM *
			if (h_mm > logo_size_max * 1.2f)
				logo_size_px = logo_size_max *
					       pixels_per_milli;
		}
	}
-- 
2.34.3

[PATCH 05/13] animate: fix fill_rect height Export this patch

---
 src/animate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/animate.c b/src/animate.c
index eb70769..99e46b5 100644
--- a/src/animate.c
+++ b/src/animate.c
@@ -27,7 +27,7 @@ void circles_wave(int frame, int w, int y_off, long dpi)
		double offset = sin(f / 60.0 * PI + i);
		int y = y_off + offset * amplitude;
		tfb_fill_rect(x - rad - 1, y_off - amplitude - rad, rad * 2 + 2,
			      400 + rad * 2, tfb_black);
			      amplitude * 2 + rad * 2 + 1, tfb_black);
		tfb_fill_circle(x, y, rad, t_col);
	}
}
-- 
2.34.3

[PATCH 06/13] Tweak the animation and placement Export this patch

* Move the animation between the logo and the text
* Move text further below
* Change circles to 3 (like ...) and increase speed to 5
* Change circles radius, distance, amplitude
* Draw empty circles instead of full circles, to be used with a logo
  that also has an outline
---
 include/pbsplash.h |  2 +-
 src/animate.c      | 16 ++++++++--------
 src/pbsplash.c     |  5 +++--
 3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/pbsplash.h b/include/pbsplash.h
index b855f28..99a496f 100644
--- a/include/pbsplash.h
+++ b/include/pbsplash.h
@@ -10,6 +10,6 @@ struct col {
   };
};

void animate_frame(int frame, int w, int h, long dpi);
void animate_frame(int frame, int w, int y_off, long dpi);

#endif
diff --git a/src/animate.c b/src/animate.c
index 99e46b5..9f03a66 100644
--- a/src/animate.c
+++ b/src/animate.c
@@ -8,18 +8,18 @@ struct col color = { .r = 255, .g = 255, .b = 255, .a = 255 };

#define PI	  3.1415926535897932384626433832795

#define n_circles 5
#define n_circles 3

#define speed	  3
#define speed	  5

void circles_wave(int frame, int w, int y_off, long dpi)
{
	unsigned int t_col = tfb_make_color(color.r, color.g, color.b);
	int f = frame * speed;

	int rad = (int)(dpi * 4 / 96.0);
	int dist = rad * 4;
	int amplitude = rad * 2;
	int rad = (int)(dpi * 3 / 96.0);
	int dist = rad * 3;
	int amplitude = rad * 1;

	int left = (w / 2) - (dist * (n_circles - 1) / 2.0);
	for (unsigned int i = 0; i < n_circles; i++) {
@@ -28,11 +28,11 @@ void circles_wave(int frame, int w, int y_off, long dpi)
		int y = y_off + offset * amplitude;
		tfb_fill_rect(x - rad - 1, y_off - amplitude - rad, rad * 2 + 2,
			      amplitude * 2 + rad * 2 + 1, tfb_black);
		tfb_fill_circle(x, y, rad, t_col);
		tfb_draw_circle(x, y, rad, t_col);
	}
}

void animate_frame(int frame, int w, int h, long dpi)
void animate_frame(int frame, int w, int y_off, long dpi)
{
	circles_wave(frame, w, h * 0.75, dpi);
	circles_wave(frame, w, y_off, dpi);
}
diff --git a/src/pbsplash.c b/src/pbsplash.c
index 7c80085..8ab8667 100644
--- a/src/pbsplash.c
+++ b/src/pbsplash.c
@@ -340,7 +340,7 @@ int main(int argc, char **argv)
				  &textHeight);

		int tx = w / 2.f - textWidth / 2.f;
		int ty = y + image_h + textHeight * 0.5f + MM_TO_PX(dpi, 2);
		int ty = y + image_h + textHeight * 0.5f + MM_TO_PX(dpi, 20);

		draw_text(font, message, tx, ty, textWidth, textHeight, fontsz,
			  tfb_gray);
@@ -351,8 +351,9 @@ int main(int argc, char **argv)

	int frame = 0;
	int tty = open(active_tty, O_RDWR);
	float y_off = y + image_h + MM_TO_PX(dpi, 5);
	while (!terminate) {
		animate_frame(frame++, w, h, dpi);
		animate_frame(frame++, w, y_off, dpi);
		tfb_flush_fb();
	}

-- 
2.34.3

[PATCH 07/13] Support multiple message lines Export this patch

---
 src/pbsplash.c | 34 +++++++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/src/pbsplash.c b/src/pbsplash.c
index 8ab8667..fb8eca7 100644
--- a/src/pbsplash.c
+++ b/src/pbsplash.c
@@ -21,6 +21,7 @@
#include "pbsplash.h"

#define MSG_MAX_LEN	  4096
#define MSG_MAX_COUNT     5
#define DEFAULT_FONT_PATH "/usr/share/pbsplash/OpenSans-Regular.svg"
#define LOGO_SIZE_MAX_MM  90
#define FONT_SIZE_PT	  9
@@ -47,13 +48,14 @@ int usage()
	// clang-format off
	fprintf(stderr, "pbsplash: postmarketOS bootsplash generator\n");
	fprintf(stderr, "-------------------------------------------\n");
	fprintf(stderr, "pbsplash [-v] [-h] [-f font] [-s splash image] [-m message]\n");
	fprintf(stderr, "pbsplash [-v] [-h] [-f font] [-s splash image]\n");
	fprintf(stderr, "         [-m message1 [-m message2 ...]\n");
	fprintf(stderr, "         [-p font size] [-q max logo size] [-d]\n\n");
	fprintf(stderr, "    -v           enable verbose logging\n");
	fprintf(stderr, "    -h           show this help\n");
	fprintf(stderr, "    -f           path to SVG font file (default: %s)\n", DEFAULT_FONT_PATH);
	fprintf(stderr, "    -s           path to splash image to display\n");
	fprintf(stderr, "    -m           message to show under the splash image\n");
	fprintf(stderr, "    -m           message(s) to show under the splash image\n");
	fprintf(stderr, "    -p           font size in pt (default: %d)\n", FONT_SIZE_PT);
	fprintf(stderr, "    -q           max logo size in mm (default: %d)\n", LOGO_SIZE_MAX_MM);
	fprintf(stderr, "    -d           custom DPI (for testing)\n");
@@ -181,7 +183,8 @@ static void getTextDimensions(NSVGimage *font, char *text, float scale,
int main(int argc, char **argv)
{
	int rc = 0;
	char *message = NULL;
	char *message[MSG_MAX_COUNT] = {};
	unsigned int message_count = 0;
	char *splash_image = NULL;
	char *font_path = DEFAULT_FONT_PATH;
	char active_tty[TTY_PATH_LEN + 1];
@@ -216,7 +219,13 @@ int main(int argc, char **argv)
			splash_image = optarg;
			break;
		case 'm':
			message = optarg;
			if (message_count >= MSG_MAX_COUNT) {
				fprintf(stderr, "MSG_MAX_COUNT is: %i\n",
					MSG_MAX_COUNT);
				return usage();
			}
			message[message_count] = optarg;
			message_count++;
			break;
		case 'p':
			font_size = strtof(optarg, &end);
@@ -322,7 +331,7 @@ int main(int argc, char **argv)

	draw_svg(image, x, y, image_w, image_h);

	if (message) {
	if (message_count) {
		int textWidth, textHeight;

		font = nsvgParseFromFile(font_path, "px", 512);
@@ -335,15 +344,18 @@ int main(int argc, char **argv)
		float fontsz = ((float)font_size * PT_TO_MM) /
			       (font->fontAscent - font->fontDescent) *
			       pixels_per_milli;
		int ty = y + image_h + MM_TO_PX(dpi, 20);

		getTextDimensions(font, message, fontsz, &textWidth,
				  &textHeight);
		for (unsigned int i=0; i < message_count; i++) {
			getTextDimensions(font, message[i], fontsz, &textWidth,
					  &textHeight);

		int tx = w / 2.f - textWidth / 2.f;
		int ty = y + image_h + textHeight * 0.5f + MM_TO_PX(dpi, 20);
			int tx = w / 2.f - textWidth / 2.f;
			ty += textHeight * 0.5f + MM_TO_PX(dpi, 2);

		draw_text(font, message, tx, ty, textWidth, textHeight, fontsz,
			  tfb_gray);
			draw_text(font, message[i], tx, ty, textWidth,
				  textHeight, fontsz, tfb_gray);
		}
	}

	tfb_flush_window();
-- 
2.34.3
Hi Ollie,

Thanks for this series, lots of goodies, just figuring my way around the nicest 
way to apply it all.

I just realised I have a local commit which adds support for newlines which I 
forgot to push, I tested it with the original messages and they all render 
properly now, I guess that's the problem you were trying to solve with this patch?

If so, I'll drop this in favour of my patch.

Kind Regards,
Caleb

[PATCH 08/13] include: add missing declarations Export this patch

Add nsvgGetTextShapes() and nsvgRasterizeText() declarations outside of
the _IMPLEMENTATION areas, so the headerfiles can be used without
having _IMPLEMENTATION set.
---
 include/nanosvg.h     | 4 +++-
 include/nanosvgrast.h | 8 +++++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/nanosvg.h b/include/nanosvg.h
index 1aceae1..2534a78 100644
--- a/include/nanosvg.h
+++ b/include/nanosvg.h
@@ -182,6 +182,8 @@ NSVGpath* nsvgDuplicatePath(NSVGpath* p);
// Deletes an image.
void nsvgDelete(NSVGimage* image);

NSVGshape** nsvgGetTextShapes(NSVGimage* image, char* text, int textLen);

#ifndef NANOSVG_CPLUSPLUS
#ifdef __cplusplus
}
@@ -3084,4 +3086,4 @@ void nsvgDelete(NSVGimage* image)
	free(image);
}

#endif
\ No newline at end of file
#endif
diff --git a/include/nanosvgrast.h b/include/nanosvgrast.h
index c080ea2..c91edcc 100644
--- a/include/nanosvgrast.h
+++ b/include/nanosvgrast.h
@@ -66,6 +66,12 @@ void nsvgRasterize(NSVGrasterizer* r,
void nsvgDeleteRasterizer(NSVGrasterizer*);


void nsvgRasterizeText(NSVGrasterizer* r,
				   NSVGimage* font, float tx, float ty, float scale,
				   unsigned char* dst, int w, int h, int stride,
				   char* text);


#ifndef NANOSVGRAST_CPLUSPLUS
#ifdef __cplusplus
}
@@ -1554,4 +1560,4 @@ void nsvgRasterize(NSVGrasterizer* r,
	r->stride = 0;
}

#endif
\ No newline at end of file
#endif
-- 
2.34.3

[PATCH 09/13] nanosvg: build implementation in extra c file Export this patch

Speed up development iterations by building the nanosvg implementation
only once. Especially on the PinePhone it takes a bit.
---
 src/meson.build | 3 ++-
 src/nanosvg.c   | 9 +++++++++
 src/pbsplash.c  | 2 --
 3 files changed, 11 insertions(+), 3 deletions(-)
 create mode 100644 src/nanosvg.c

diff --git a/src/meson.build b/src/meson.build
index 77f2b51..52b2bf3 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,6 +1,7 @@
src = [
        'pbsplash.c',
        'animate.c',
        'nanosvg.c',
        'pbsplash.c',
]

executable('pbsplash', src,
diff --git a/src/nanosvg.c b/src/nanosvg.c
new file mode 100644
index 0000000..ecf037a
--- /dev/null
+++ b/src/nanosvg.c
@@ -0,0 +1,9 @@
/* Build the nanosvg implementation here, to build it only once and have other
 * C files build fast during development. */
#include <stdio.h>

#define NANOSVG_IMPLEMENTATION
#include "nanosvg.h"

#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvgrast.h"
diff --git a/src/pbsplash.c b/src/pbsplash.c
index fb8eca7..def186e 100644
--- a/src/pbsplash.c
+++ b/src/pbsplash.c
@@ -13,9 +13,7 @@
#include <string.h>
#include <math.h>
#define NANOSVG_ALL_COLOR_KEYWORDS // Include full list of color keywords.
#define NANOSVG_IMPLEMENTATION	   // Expands implementation
#include "nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvgrast.h"

#include "pbsplash.h"
-- 
2.34.3

[PATCH 10/13] nsvgGetTextShapes: fix uninitialized values Export this patch

Use calloc to zero ret, because ret[i] does not get written if
NSVG_FLAGS_VISIBLE is unset. Found with valgrind.
---
 include/nanosvg.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/nanosvg.h b/include/nanosvg.h
index 2534a78..35d492f 100644
--- a/include/nanosvg.h
+++ b/include/nanosvg.h
@@ -2966,7 +2966,7 @@ static void nsvg__scaleToViewbox(NSVGparser* p, const char* units)
NSVGshape** nsvgGetTextShapes(NSVGimage* image, char* text, int textLen)
{
	NSVGshape *shape = NULL;
	NSVGshape **ret = malloc(sizeof(NSVGshape*)*textLen); // array of paths, text to render
	NSVGshape **ret = calloc(textLen, sizeof(shape)); // array of paths, text to render
	int i;

	// make list of paths representing glyphs to render
-- 
2.34.3

[PATCH 11/13] Support message line at the bottom Export this patch

---
 src/pbsplash.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/src/pbsplash.c b/src/pbsplash.c
index def186e..6cbbcd0 100644
--- a/src/pbsplash.c
+++ b/src/pbsplash.c
@@ -23,6 +23,7 @@
#define DEFAULT_FONT_PATH "/usr/share/pbsplash/OpenSans-Regular.svg"
#define LOGO_SIZE_MAX_MM  90
#define FONT_SIZE_PT	  9
#define FONT_SIZE_B_PT    5
#define PT_TO_MM	  0.38f
#define TTY_PATH_LEN	  11

@@ -48,12 +49,15 @@ int usage()
	fprintf(stderr, "-------------------------------------------\n");
	fprintf(stderr, "pbsplash [-v] [-h] [-f font] [-s splash image]\n");
	fprintf(stderr, "         [-m message1 [-m message2 ...]\n");
	fprintf(stderr, "         [-b message bottom] [-o font size bottom]\n");
	fprintf(stderr, "         [-p font size] [-q max logo size] [-d]\n\n");
	fprintf(stderr, "    -v           enable verbose logging\n");
	fprintf(stderr, "    -h           show this help\n");
	fprintf(stderr, "    -f           path to SVG font file (default: %s)\n", DEFAULT_FONT_PATH);
	fprintf(stderr, "    -s           path to splash image to display\n");
	fprintf(stderr, "    -m           message(s) to show under the splash image\n");
	fprintf(stderr, "    -b           message to show at the bottom\n");
	fprintf(stderr, "    -o           font size bottom in pt (default: %d)\n", FONT_SIZE_B_PT);
	fprintf(stderr, "    -p           font size in pt (default: %d)\n", FONT_SIZE_PT);
	fprintf(stderr, "    -q           max logo size in mm (default: %d)\n", LOGO_SIZE_MAX_MM);
	fprintf(stderr, "    -d           custom DPI (for testing)\n");
@@ -183,6 +187,7 @@ int main(int argc, char **argv)
	int rc = 0;
	char *message[MSG_MAX_COUNT] = {};
	unsigned int message_count = 0;
	char *message_bottom = NULL;
	char *splash_image = NULL;
	char *font_path = DEFAULT_FONT_PATH;
	char active_tty[TTY_PATH_LEN + 1];
@@ -190,6 +195,7 @@ int main(int argc, char **argv)
	NSVGimage *font = NULL;
	struct sigaction action;
	float font_size = FONT_SIZE_PT;
	float font_size_b = FONT_SIZE_B_PT;
	float logo_size_max = LOGO_SIZE_MAX_MM;
	int optflag;
	long dpi = 0;
@@ -202,7 +208,7 @@ int main(int argc, char **argv)
	sigaction(SIGTERM, &action, NULL);
	sigaction(SIGINT, &action, NULL);

	while ((optflag = getopt(argc, argv, "hvf:s:m:p:q:d:")) != -1) {
	while ((optflag = getopt(argc, argv, "hvf:s:m:b:o:p:q:d:")) != -1) {
		char *end = NULL;
		switch (optflag) {
		case 'h':
@@ -225,6 +231,17 @@ int main(int argc, char **argv)
			message[message_count] = optarg;
			message_count++;
			break;
		case 'b':
			message_bottom = optarg;
			break;
		case 'o':
			font_size_b = strtof(optarg, &end);
			if (end == optarg) {
				fprintf(stderr, "Invalid font size: %s\n",
					optarg);
				return usage();
			}
			break;
		case 'p':
			font_size = strtof(optarg, &end);
			if (end == optarg) {
@@ -329,7 +346,7 @@ int main(int argc, char **argv)

	draw_svg(image, x, y, image_w, image_h);

	if (message_count) {
	if (message_count || message_bottom) {
		int textWidth, textHeight;

		font = nsvgParseFromFile(font_path, "px", 512);
@@ -354,6 +371,19 @@ int main(int argc, char **argv)
			draw_text(font, message[i], tx, ty, textWidth,
				  textHeight, fontsz, tfb_gray);
		}

		if (message_bottom) {
			fontsz = ((float)font_size_b * PT_TO_MM) /
				 (font->fontAscent - font->fontDescent) *
				 pixels_per_milli;

			getTextDimensions(font, message_bottom, fontsz,
					  &textWidth, &textHeight);
			int tx = w / 2.f - textWidth / 2.f;
			ty = h - MM_TO_PX(dpi, 2);
			draw_text(font, message_bottom, tx, ty, textWidth,
				  textHeight, fontsz, tfb_gray);
		}
	}

	tfb_flush_window();
-- 
2.34.3

[PATCH 12/13] Move regular message further down Export this patch

Give the splash image + animation more splace by moving the message
further down. Now they are right above the very bottom message (which
has a different font size).

Write the messages from bottom up, so the space towards the bottom is
always the same while avoiding more complicated logic to calculate the
position.
---
 src/pbsplash.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/pbsplash.c b/src/pbsplash.c
index 6cbbcd0..6ce6754 100644
--- a/src/pbsplash.c
+++ b/src/pbsplash.c
@@ -359,14 +359,15 @@ int main(int argc, char **argv)
		float fontsz = ((float)font_size * PT_TO_MM) /
			       (font->fontAscent - font->fontDescent) *
			       pixels_per_milli;
		int ty = y + image_h + MM_TO_PX(dpi, 20);

		for (unsigned int i=0; i < message_count; i++) {
		int ty = h - MM_TO_PX(dpi, 5);

		for (int i = message_count - 1; i >= 0; i--) {
			getTextDimensions(font, message[i], fontsz, &textWidth,
					  &textHeight);

			int tx = w / 2.f - textWidth / 2.f;
			ty += textHeight * 0.5f + MM_TO_PX(dpi, 2);
			ty -= textHeight * 0.5f + MM_TO_PX(dpi, 2);

			draw_text(font, message[i], tx, ty, textWidth,
				  textHeight, fontsz, tfb_gray);
-- 
2.34.3

[PATCH 13/13] Add argument to disable animation Export this patch

For displaying error messages, let's not show the loading animation.
---
 src/pbsplash.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/pbsplash.c b/src/pbsplash.c
index 6ce6754..d4f3126 100644
--- a/src/pbsplash.c
+++ b/src/pbsplash.c
@@ -50,7 +50,7 @@ int usage()
	fprintf(stderr, "pbsplash [-v] [-h] [-f font] [-s splash image]\n");
	fprintf(stderr, "         [-m message1 [-m message2 ...]\n");
	fprintf(stderr, "         [-b message bottom] [-o font size bottom]\n");
	fprintf(stderr, "         [-p font size] [-q max logo size] [-d]\n\n");
	fprintf(stderr, "         [-p font size] [-q max logo size] [-d] [-e]\n\n");
	fprintf(stderr, "    -v           enable verbose logging\n");
	fprintf(stderr, "    -h           show this help\n");
	fprintf(stderr, "    -f           path to SVG font file (default: %s)\n", DEFAULT_FONT_PATH);
@@ -61,6 +61,7 @@ int usage()
	fprintf(stderr, "    -p           font size in pt (default: %d)\n", FONT_SIZE_PT);
	fprintf(stderr, "    -q           max logo size in mm (default: %d)\n", LOGO_SIZE_MAX_MM);
	fprintf(stderr, "    -d           custom DPI (for testing)\n");
	fprintf(stderr, "    -e           error (no loading animation)\n");
	// clang-format on

	return 1;
@@ -199,6 +200,7 @@ int main(int argc, char **argv)
	float logo_size_max = LOGO_SIZE_MAX_MM;
	int optflag;
	long dpi = 0;
	bool animation = true;

	memset(active_tty, '\0', TTY_PATH_LEN);
	strcat(active_tty, "/dev/");
@@ -208,7 +210,7 @@ int main(int argc, char **argv)
	sigaction(SIGTERM, &action, NULL);
	sigaction(SIGINT, &action, NULL);

	while ((optflag = getopt(argc, argv, "hvf:s:m:b:o:p:q:d:")) != -1) {
	while ((optflag = getopt(argc, argv, "hvf:s:m:b:o:p:q:d:e")) != -1) {
		char *end = NULL;
		switch (optflag) {
		case 'h':
@@ -266,6 +268,9 @@ int main(int argc, char **argv)
				return usage();
			}
			break;
		case 'e':
			animation = false;
			break;
		default:
			return usage();
		}
@@ -394,7 +399,8 @@ int main(int argc, char **argv)
	int tty = open(active_tty, O_RDWR);
	float y_off = y + image_h + MM_TO_PX(dpi, 5);
	while (!terminate) {
		animate_frame(frame++, w, y_off, dpi);
		if (animation)
			animate_frame(frame++, w, y_off, dpi);
		tfb_flush_fb();
	}

-- 
2.34.3