mirror of
https://git.sr.ht/~calebccff/pbsplash
synced 2026-01-12 12:38:41 -09:00
WIP: awful animation code...
This commit is contained in:
parent
080fcf60ca
commit
e08a62d580
4 changed files with 149 additions and 71 deletions
|
|
@ -3022,14 +3022,16 @@ NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)
|
|||
char* data = NULL;
|
||||
NSVGimage* image = NULL;
|
||||
|
||||
printf("open file %s\n", filename);
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (!fp) goto error;
|
||||
if (!fp) {printf("%d\n", __LINE__); goto error; }
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
data = (char*)malloc(size+1);
|
||||
if (data == NULL) goto error;
|
||||
if (fread(data, 1, size, fp) != size) goto error;
|
||||
if (data == NULL) {printf("%d\n", __LINE__); goto error; }
|
||||
if (fread(data, 1, size, fp) != size) {printf("%d\n", __LINE__); goto error; }
|
||||
data[size] = '\0'; // Must be null terminated.
|
||||
fclose(fp);
|
||||
image = nsvgParse(data, units, dpi);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,29 @@ struct col {
|
|||
};
|
||||
};
|
||||
|
||||
void animate_frame(int frame, int w, int y_off, long dpi);
|
||||
struct dpi_info {
|
||||
long dpi;
|
||||
int pixels_per_milli;
|
||||
float logo_size_px;
|
||||
int logo_size_max_mm;
|
||||
};
|
||||
|
||||
typedef struct NSVGimage NSVGimage;
|
||||
|
||||
#define MAX_FRAMES 16
|
||||
|
||||
struct image_info {
|
||||
char *path[MAX_FRAMES];
|
||||
NSVGimage *image[MAX_FRAMES];
|
||||
int num_frames;
|
||||
float width;
|
||||
float height;
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
void draw_svg(NSVGimage *image, int x, int y, int w, int h);
|
||||
|
||||
void animate_frame(int frame, int w, int y_off, long dpi, struct image_info *images);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -31,7 +31,25 @@ static void circles_wave(int frame, int w, int y_off, long dpi)
|
|||
}
|
||||
}
|
||||
|
||||
void animate_frame(int frame, int w, int y_off, long dpi)
|
||||
static void animate_logo(int frame, struct image_info *images)
|
||||
{
|
||||
circles_wave(frame, w, y_off, dpi);
|
||||
static int step = 0;
|
||||
|
||||
tfb_draw_pixel(0, 0, tfb_black);
|
||||
|
||||
if (frame > 0 && (step + 1) * 4 < frame) {
|
||||
step++;
|
||||
}
|
||||
|
||||
// tfb_fill_rect(images->x, images->y, images->width, images->height,
|
||||
// tfb_black);
|
||||
draw_svg(images->image[step % images->num_frames], images->x, images->y, images->width,
|
||||
images->height);
|
||||
}
|
||||
|
||||
void animate_frame(int frame, int w, int y_off, long dpi,
|
||||
struct image_info *images)
|
||||
{
|
||||
animate_logo(frame, images);
|
||||
// circles_wave(frame, w, y_off, dpi);
|
||||
}
|
||||
|
|
|
|||
165
src/pbsplash.c
165
src/pbsplash.c
|
|
@ -32,11 +32,13 @@
|
|||
|
||||
volatile sig_atomic_t terminate = 0;
|
||||
|
||||
bool debug = false;
|
||||
bool debug = true;
|
||||
struct col background_color = { .r = 0, .g = 0, .b = 0, .a = 255 };
|
||||
|
||||
static int screenWidth, screenHeight;
|
||||
|
||||
static struct dpi_info dpi_info = { .logo_size_max_mm = LOGO_SIZE_MAX_MM };
|
||||
|
||||
#define zalloc(size) calloc(1, size)
|
||||
|
||||
#define LOG(fmt, ...) \
|
||||
|
|
@ -80,6 +82,7 @@ static void blit_buf(unsigned char *buf, int x, int y, int w, int h, bool vflip,
|
|||
struct col prev_col = { .r = 0, .g = 0, .b = 0, .a = 0 };
|
||||
unsigned int col = tfb_make_color(
|
||||
background_color.r, background_color.g, background_color.b);
|
||||
tfb_fill_rect(x, y, w, h, col);
|
||||
|
||||
for (size_t i = 0; i < w; i++) {
|
||||
for (size_t j = 0; j < h; j++) {
|
||||
|
|
@ -123,14 +126,14 @@ static void blit_buf(unsigned char *buf, int x, int y, int w, int h, bool vflip,
|
|||
}
|
||||
}
|
||||
|
||||
static void draw_svg(NSVGimage *image, int x, int y, int w, int h)
|
||||
void draw_svg(NSVGimage *image, int x, int y, int w, int h)
|
||||
{
|
||||
float sz = (int)((float)w / (float)image->width * 100.f) / 100.f;
|
||||
LOG("draw_svg: (%d, %d), %dx%d, %f\n", x, y, w, h, sz);
|
||||
//LOG("draw_svg: (%d, %d), %dx%d, %f\n", x, y, w, h, sz);
|
||||
NSVGrasterizer *rast = nsvgCreateRasterizer();
|
||||
unsigned char *img = zalloc(w * h * 4);
|
||||
//blit_buf(img, x, y, w, h, false, false);
|
||||
nsvgRasterize(rast, image, 0, 0, sz, img, w, h, w * 4);
|
||||
|
||||
blit_buf(img, x, y, w, h, false, false);
|
||||
|
||||
free(img);
|
||||
|
|
@ -240,19 +243,15 @@ out:
|
|||
return out_text;
|
||||
}
|
||||
|
||||
struct dpi_info {
|
||||
long dpi;
|
||||
int pixels_per_milli;
|
||||
float logo_size_px;
|
||||
int logo_size_max_mm;
|
||||
};
|
||||
|
||||
static void calculate_dpi_info(struct dpi_info *dpi_info)
|
||||
struct dpi_info *calculate_dpi_info()
|
||||
{
|
||||
if (dpi_info.logo_size_px)
|
||||
return &dpi_info;
|
||||
|
||||
int w_mm = tfb_screen_width_mm();
|
||||
int h_mm = tfb_screen_height_mm();
|
||||
|
||||
if ((w_mm < 1 || h_mm < 1) && !dpi_info->dpi) {
|
||||
if ((w_mm < 1 || h_mm < 1) && !dpi_info.dpi) {
|
||||
fprintf(stderr, "ERROR!!!: Invalid screen size: %dx%d\n", w_mm, h_mm);
|
||||
|
||||
// Assume a dpi of 300
|
||||
|
|
@ -260,38 +259,40 @@ static void calculate_dpi_info(struct dpi_info *dpi_info)
|
|||
// Except ridiculous HiDPI displays
|
||||
// which honestly should expose their physical
|
||||
// dimensions....
|
||||
dpi_info->dpi = 300;
|
||||
dpi_info.dpi = 300;
|
||||
}
|
||||
|
||||
// If DPI is specified on cmdline then calculate display size from it
|
||||
// otherwise calculate the dpi based on the display size.
|
||||
if (dpi_info->dpi > 0) {
|
||||
w_mm = screenWidth / (float)dpi_info->dpi * 25.4;
|
||||
h_mm = screenHeight / (float)dpi_info->dpi * 25.4;
|
||||
if (dpi_info.dpi > 0) {
|
||||
w_mm = screenWidth / (float)dpi_info.dpi * 25.4;
|
||||
h_mm = screenHeight / (float)dpi_info.dpi * 25.4;
|
||||
} else {
|
||||
dpi_info->dpi = (float)screenWidth / (float)w_mm * 25.4;
|
||||
dpi_info.dpi = (float)screenWidth / (float)w_mm * 25.4;
|
||||
}
|
||||
dpi_info->pixels_per_milli = (float)screenWidth / (float)w_mm;
|
||||
dpi_info.pixels_per_milli = (float)screenWidth / (float)w_mm;
|
||||
|
||||
if (dpi_info->logo_size_max_mm * dpi_info->pixels_per_milli > screenWidth)
|
||||
dpi_info->logo_size_max_mm = (screenWidth * 0.75f) / dpi_info->pixels_per_milli;
|
||||
if (dpi_info.logo_size_max_mm * dpi_info.pixels_per_milli > screenWidth)
|
||||
dpi_info.logo_size_max_mm = (screenWidth * 0.75f) / dpi_info.pixels_per_milli;
|
||||
|
||||
dpi_info->logo_size_px =
|
||||
dpi_info.logo_size_px =
|
||||
(float)(screenWidth < screenHeight ? screenWidth :
|
||||
screenHeight) *
|
||||
0.75f;
|
||||
if (w_mm > 0 && h_mm > 0) {
|
||||
if (w_mm < h_mm) {
|
||||
if (w_mm > dpi_info->logo_size_max_mm * 1.2f)
|
||||
dpi_info->logo_size_px = dpi_info->logo_size_max_mm * dpi_info->pixels_per_milli;
|
||||
if (w_mm > dpi_info.logo_size_max_mm * 1.2f)
|
||||
dpi_info.logo_size_px = dpi_info.logo_size_max_mm * dpi_info.pixels_per_milli;
|
||||
} else {
|
||||
if (h_mm > dpi_info->logo_size_max_mm * 1.2f)
|
||||
dpi_info->logo_size_px = dpi_info->logo_size_max_mm * dpi_info->pixels_per_milli;
|
||||
if (h_mm > dpi_info.logo_size_max_mm * 1.2f)
|
||||
dpi_info.logo_size_px = dpi_info.logo_size_max_mm * dpi_info.pixels_per_milli;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%dx%d @ %dx%dmm, dpi=%ld, logo_size_px=%f\n", screenWidth,
|
||||
screenHeight, w_mm, h_mm, dpi_info->dpi, dpi_info->logo_size_px);
|
||||
screenHeight, w_mm, h_mm, dpi_info.dpi, dpi_info.logo_size_px);
|
||||
|
||||
return &dpi_info;
|
||||
}
|
||||
|
||||
struct msg_info {
|
||||
|
|
@ -373,35 +374,31 @@ static void show_messages(struct messages *msgs, const struct dpi_info *dpi_info
|
|||
}
|
||||
}
|
||||
|
||||
struct image_info {
|
||||
const char *path;
|
||||
NSVGimage *image;
|
||||
float width;
|
||||
float height;
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
static int load_image(const struct dpi_info *dpi_info, struct image_info *image_info)
|
||||
int load_image(const struct dpi_info *dpi_info, struct image_info *image_info, int i)
|
||||
{
|
||||
int logo_size_px = dpi_info->logo_size_px;
|
||||
int logo_size_px = dpi_info->logo_size_px;
|
||||
|
||||
image_info->image = nsvgParseFromFile(image_info->path, "", logo_size_px);
|
||||
if (!image_info->image) {
|
||||
image_info->image[i] = nsvgParseFromFile(image_info->path[i], "", logo_size_px);
|
||||
if (!image_info->image[i] && i == 0) {
|
||||
fprintf(stderr, "failed to load SVG image\n");
|
||||
fprintf(stderr, " image path: %s\n", image_info->path);
|
||||
fprintf(stderr, " image path: %s\n", image_info->path[i]);
|
||||
return 1;
|
||||
} else if (!image_info->image[i]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// For taller images make sure they don't get too wide
|
||||
if (image_info->image->width < image_info->image->height * 1.1)
|
||||
if (image_info->image[i]->width < image_info->image[i]->height * 1.1)
|
||||
logo_size_px = MM_TO_PX(dpi_info->dpi, 25);
|
||||
|
||||
if (i > 0)
|
||||
return 0;
|
||||
|
||||
float sz =
|
||||
(float)logo_size_px /
|
||||
(image_info->image->width > image_info->image->height ? image_info->image->height : image_info->image->width);
|
||||
image_info->width = image_info->image->width * sz + 0.5;
|
||||
image_info->height = image_info->image->height * sz + 0.5;
|
||||
(image_info->image[i]->width > image_info->image[i]->height ? image_info->image[i]->height : image_info->image[i]->width);
|
||||
image_info->width = image_info->image[i]->width * sz + 0.5;
|
||||
image_info->height = image_info->image[i]->height * sz + 0.5;
|
||||
if (image_info->width > (dpi_info->logo_size_max_mm * dpi_info->pixels_per_milli)) {
|
||||
float scalefactor =
|
||||
((float)(dpi_info->logo_size_max_mm * dpi_info->pixels_per_milli) / image_info->width);
|
||||
|
|
@ -415,6 +412,46 @@ static int load_image(const struct dpi_info *dpi_info, struct image_info *image_
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* strdup and increment a 2 digit number in the string at offset */
|
||||
static char *strdupinc(const char *s, int i)
|
||||
{
|
||||
char *n = NULL;
|
||||
char *base = zalloc(strlen(s));
|
||||
|
||||
LOG("%d, %s\n", i, s);
|
||||
|
||||
n = strstr(s, "01");
|
||||
|
||||
memcpy(base, s, strlen(s));
|
||||
int len = strlen(s) - strlen(n);
|
||||
base[len] = '0' + (i/10);
|
||||
base[len + 1] = '1' + (i%10);
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
int load_images(const struct dpi_info *dpi_info, struct image_info *image_info)
|
||||
{
|
||||
if (strlen(image_info->path[0]) < 6) {
|
||||
fprintf(stderr, "invalid image path\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_FRAMES; i++) {
|
||||
if (i > 0)
|
||||
image_info->path[i] = strdupinc(image_info->path[0], i);
|
||||
if (load_image(dpi_info, image_info, i)) {
|
||||
free(image_info->path[i]);
|
||||
break;
|
||||
}
|
||||
image_info->num_frames++;
|
||||
}
|
||||
|
||||
LOG("num_frames: %d\n", image_info->num_frames);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int rc = 0;
|
||||
|
|
@ -429,15 +466,9 @@ int main(int argc, char **argv)
|
|||
.msg = NULL,
|
||||
.bottom_msg = NULL,
|
||||
};
|
||||
struct dpi_info dpi_info = {
|
||||
.dpi = 0,
|
||||
.pixels_per_milli = 0,
|
||||
.logo_size_px = 0,
|
||||
.logo_size_max_mm = LOGO_SIZE_MAX_MM,
|
||||
};
|
||||
struct image_info image_info = {
|
||||
.path = NULL,
|
||||
.image = NULL,
|
||||
.path = { },
|
||||
.image = { },
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.x = 0,
|
||||
|
|
@ -466,7 +497,7 @@ int main(int argc, char **argv)
|
|||
msgs.font_path = optarg;
|
||||
break;
|
||||
case 's':
|
||||
image_info.path = optarg;
|
||||
image_info.path[0] = strdup(optarg);
|
||||
break;
|
||||
case 'm':
|
||||
message = malloc(strlen(optarg) + 1);
|
||||
|
|
@ -528,7 +559,7 @@ int main(int argc, char **argv)
|
|||
|
||||
LOG("active tty: '%s'\n", active_tty);
|
||||
|
||||
if ((rc = tfb_acquire_fb(/*TFB_FL_NO_TTY_KD_GRAPHICS */ 0, "/dev/fb0",
|
||||
if ((rc = tfb_acquire_fb(TFB_FL_USE_DOUBLE_BUFFER, "/dev/fb0",
|
||||
active_tty)) != TFB_SUCCESS) {
|
||||
fprintf(stderr, "tfb_acquire_fb() failed with error code: %d\n",
|
||||
rc);
|
||||
|
|
@ -539,18 +570,18 @@ int main(int argc, char **argv)
|
|||
screenWidth = (int)tfb_screen_width();
|
||||
screenHeight = (int)tfb_screen_height();
|
||||
|
||||
calculate_dpi_info(&dpi_info);
|
||||
struct dpi_info *dpi_info = calculate_dpi_info();
|
||||
|
||||
rc = load_image(&dpi_info, &image_info);
|
||||
rc = load_images(dpi_info, &image_info);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
float animation_y = image_info.y + image_info.height + MM_TO_PX(dpi_info.dpi, 5);
|
||||
float animation_y = image_info.y + image_info.height + MM_TO_PX(dpi_info->dpi, 5);
|
||||
|
||||
tfb_clear_screen(tfb_make_color(background_color.r, background_color.g,
|
||||
background_color.b));
|
||||
|
||||
draw_svg(image_info.image, image_info.x, image_info.y, image_info.width, image_info.height);
|
||||
draw_svg(image_info.image[0], image_info.x, image_info.y, image_info.width, image_info.height);
|
||||
|
||||
if (!message && !message_bottom)
|
||||
goto no_messages;
|
||||
|
|
@ -568,7 +599,7 @@ int main(int argc, char **argv)
|
|||
if (message)
|
||||
msgs.msg = &msg;
|
||||
|
||||
show_messages(&msgs, &dpi_info);
|
||||
show_messages(&msgs, dpi_info);
|
||||
|
||||
no_messages:
|
||||
tfb_flush_window();
|
||||
|
|
@ -592,7 +623,8 @@ no_messages:
|
|||
}
|
||||
clock_gettime(CLOCK_REALTIME, &start);
|
||||
tick = timespec_to_double(timespec_sub(start, epoch)) * tickrate;
|
||||
animate_frame(tick, screenWidth, animation_y, dpi_info.dpi);
|
||||
animate_frame(tick, screenWidth, animation_y, dpi_info->dpi, &image_info);
|
||||
tfb_flush_window();
|
||||
tfb_flush_fb();
|
||||
clock_gettime(CLOCK_REALTIME, &end);
|
||||
diff = timespec_sub(end, start);
|
||||
|
|
@ -608,15 +640,18 @@ no_messages:
|
|||
|
||||
out:
|
||||
// Before we exit print the logo so it will persist
|
||||
if (image_info.image) {
|
||||
if (image_info.image[0]) {
|
||||
ioctl(tty, KDSETMODE, KD_TEXT);
|
||||
draw_svg(image_info.image, image_info.x, image_info.y, image_info.width, image_info.height);
|
||||
draw_svg(image_info.image[0], image_info.x, image_info.y, image_info.width, image_info.height);
|
||||
}
|
||||
|
||||
// Draw the messages again so they will persist
|
||||
show_messages(&msgs, &dpi_info);
|
||||
show_messages(&msgs, dpi_info);
|
||||
|
||||
nsvgDelete(image_info.image);
|
||||
for (int i = 0; i < image_info.num_frames; i++) {
|
||||
nsvgDelete(image_info.image[i]);
|
||||
free(image_info.path[i]);
|
||||
}
|
||||
nsvgDelete(msgs.font);
|
||||
free_message(msgs.msg);
|
||||
free_message(msgs.bottom_msg);
|
||||
|
|
|
|||
Loading…
Reference in a new issue