Skip to content

Commit

Permalink
Extend twin_pixmap_t to Support gif animation
Browse files Browse the repository at this point in the history
To enable support for GIF animations, I have extended the twin_pixmap_t
structure. The twin_pixmap_t now includes a flag to determine if the
image is animated, along with a new structure, twin_animation_t, to
manage the frames and timing information. I have also integrated an API
with gifdec [1] to load, manage and display the twin_animation_t object.

In addition, I have added a new application to demonstrate the
capabilities of twin_pixmap_t, supporting both GIF animations and static
images.

[1] https://github.com/lecram/gifdec
  • Loading branch information
ndsl7109256 committed Sep 4, 2024
1 parent 1ab586c commit c8a0535
Show file tree
Hide file tree
Showing 11 changed files with 891 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ libtwin.a_cflags-y += $(shell pkg-config --cflags libpng)
TARGET_LIBS += $(shell pkg-config --libs libpng)
endif

ifeq ($(CONFIG_LOADER_GIF), y)
libtwin.a_files-y += src/image-gif.c
endif

# Applications

libapps.a_files-y := apps/dummy.c
Expand All @@ -83,6 +87,7 @@ libapps.a_files-$(CONFIG_DEMO_CLOCK) += apps/clock.c
libapps.a_files-$(CONFIG_DEMO_CALCULATOR) += apps/calc.c
libapps.a_files-$(CONFIG_DEMO_LINE) += apps/line.c
libapps.a_files-$(CONFIG_DEMO_SPLINE) += apps/spline.c
libapps.a_files-$(CONFIG_DEMO_ANIMATION) += apps/animation.c

libapps.a_includes-y := include

Expand Down
104 changes: 104 additions & 0 deletions apps/animation.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Twin - A Tiny Window System
* Copyright (c) 2024 National Cheng Kung University
* All rights reserved.
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>

#include "twin_private.h"

#include "apps_animation.h"

#define _apps_animation_pixmap(animation) ((animation)->widget.window->pixmap)


typedef struct {
twin_widget_t widget;
twin_pixmap_t *pix;
twin_timeout_t *timeout;
} apps_animation_t;

static void _apps_animation_paint(apps_animation_t *animation)
{
twin_pixmap_t *current_frame = NULL;

if (animation->pix->animated) {
twin_animation_t *gif = animation->pix->animation;
current_frame = twin_animation_get_current_frame(gif);
twin_animation_advance_frame(gif);
} else {
current_frame = animation->pix;
}

twin_operand_t srcop = {
.source_kind = TWIN_PIXMAP,
.u.pixmap = current_frame,
};
twin_composite(_apps_animation_pixmap(animation), 0, 0, &srcop, 0, 0, NULL, 0, 0,
TWIN_SOURCE, current_frame->width, current_frame->height);
}

static twin_time_t _apps_animation_timeout(twin_time_t maybe_unused now,
void *closure)
{
apps_animation_t *animation = closure;
_twin_widget_queue_paint(&animation->widget);
twin_animation_t *gif = animation->pix->animation;
twin_time_t delay = gif->frame_delays[gif->current_frame];
return delay;
}

static twin_dispatch_result_t _apps_animation_dispatch(twin_widget_t *widget,
twin_event_t *event)
{
apps_animation_t *animation = (apps_animation_t *) widget;
if (_twin_widget_dispatch(widget, event) == TwinDispatchDone)
return TwinDispatchDone;
switch (event->kind) {
case TwinEventPaint:
_apps_animation_paint(animation);
break;
default:
break;
}
return TwinDispatchContinue;
}

static void _apps_animation_init(apps_animation_t *animation,
twin_box_t *parent,
twin_dispatch_proc_t dispatch)
{
static const twin_widget_layout_t preferred = {0, 0, 1, 1};
_twin_widget_init(&animation->widget, parent, 0, preferred, dispatch);

if (animation->pix->animated) {
twin_animation_t *gif = animation->pix->animation;
twin_time_t delay = gif->frame_delays[gif->current_frame];
animation->timeout = twin_set_timeout(_apps_animation_timeout, delay, animation);
} else {
animation->timeout = NULL;
}
}

static apps_animation_t *apps_animation_create(twin_box_t *parent, twin_pixmap_t *pix)
{
apps_animation_t *animation = malloc(sizeof(apps_animation_t));
animation->pix = pix;
_apps_animation_init(animation, parent, _apps_animation_dispatch);
return animation;
}

void apps_animation_start(twin_screen_t *screen, const char *path, int x, int y)
{
twin_pixmap_t *pix = twin_pixmap_from_file(path, TWIN_ARGB32);
twin_toplevel_t *toplevel =
twin_toplevel_create(screen, TWIN_ARGB32, TwinWindowApplication, x, y,
pix->width, pix->height, path);
apps_animation_t *animation = apps_animation_create(&toplevel->box, pix);
(void) animation;
twin_toplevel_show(toplevel);
}
14 changes: 14 additions & 0 deletions apps/apps_animation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Twin - A Tiny Window System
* Copyright (c) 2024 National Cheng Kung University
* All rights reserved.
*/

#ifndef _APPS_ANIMATION_H_
#define _APPS_ANIMATION_H_

#include <twin.h>

void apps_animation_start(twin_screen_t *screen, const char *name, int x, int y);

#endif /* _APPS_ANIMATION_H_ */
4 changes: 4 additions & 0 deletions apps/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <time.h>
#include <unistd.h>

#include "apps_animation.h"
#include "apps_calc.h"
#include "apps_clock.h"
#include "apps_hello.h"
Expand Down Expand Up @@ -122,6 +123,9 @@ int main(void)
#if defined(CONFIG_DEMO_SPLINE)
apps_spline_start(tx->screen, "Spline", 20, 20, 400, 400);
#endif
#if defined(CONFIG_DEMO_ANIMATION)
apps_animation_start(tx->screen, ASSET_PATH "nyancat.gif", 20, 20);
#endif

twin_dispatch();

Expand Down
Binary file added assets/nyancat.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions configs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ config LOADER_JPEG
bool "Enable JPEG loader"
default y

config LOADER_GIF
bool "Enable GIF loader"
default y

endmenu

menu "Demo Applications"
Expand Down Expand Up @@ -72,4 +76,8 @@ config DEMO_SPLINE
default y
depends on DEMO_APPLICATIONS

config DEMO_ANIMATION
bool "Build animation demo"
default y
depends on DEMO_APPLICATIONS
endmenu
2 changes: 2 additions & 0 deletions configs/defconfig
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
CONFIG_BACKEND_SDL=y
CONFIG_LOADER_PNG=y
CONFIG_LOADER_JPEG=y
CONFIG_LOADER_GIF=y
CONFIG_DEMO_APPLICATIONS=y
CONFIG_DEMO_MULTI=y
CONFIG_DEMO_HELLO=y
CONFIG_DEMO_CLOCK=y
CONFIG_DEMO_CALCULATOR=y
CONFIG_DEMO_LINE=y
CONFIG_DEMO_SPLINE=y
CONFIG_DEMO_ANIMATION=y
30 changes: 30 additions & 0 deletions include/twin.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ typedef union _twin_pointer {

typedef struct _twin_window twin_window_t;
typedef struct _twin_screen twin_screen_t;
typedef struct _twin_pixmap twin_pixmap_t;

/*
* Events
Expand Down Expand Up @@ -133,6 +134,21 @@ typedef struct _twin_event_queue {
twin_event_t event;
} twin_event_queue_t;

typedef struct _twin_animation {
/* Array of pixmaps representing each frame of the animation */
twin_pixmap_t **frames;
/* Number of frames in the animation */
twin_count_t n_frames;
/* Delay between frames in milliseconds */
twin_count_t *frame_delays;
/* Whether the animation should loop */
bool loop;
/* Current frame index */
twin_count_t current_frame;
twin_coord_t width; /* pixels */
twin_coord_t height; /* pixels */
} twin_animation_t;

/*
* A rectangular array of pixels
*/
Expand Down Expand Up @@ -171,6 +187,8 @@ typedef struct _twin_pixmap {
/*
* Pixels
*/
bool animated;
twin_animation_t *animation;
twin_pointer_t p;
/*
* When representing a window, this point
Expand Down Expand Up @@ -692,6 +710,18 @@ void twin_icon_draw(twin_pixmap_t *pixmap,

twin_pixmap_t *twin_pixmap_from_file(const char *path, twin_format_t fmt);

/*
* gif.c
*/

twin_animation_t *twin_animation_from_file(const char *path);

twin_pixmap_t *twin_animation_get_current_frame(twin_animation_t *animation);

void twin_animation_advance_frame(twin_animation_t *animation);

void twin_animation_destroy(twin_animation_t *animation);

/*
* label.c
*/
Expand Down
Loading

0 comments on commit c8a0535

Please sign in to comment.