Beginning GIF export

Beginning addition of an option to export animated GIFs
from the Open -> Slideshow dialog, after choosing the images.

Non-operable at this time, but a button has been added (and will
provide a hint to select 2 or more images, when clicked).
This commit is contained in:
Bill Kendrick 2020-07-25 00:18:46 -07:00
parent 3ede0b96bf
commit 8c3a07294b
7 changed files with 408 additions and 16 deletions

View file

@ -4,7 +4,7 @@
# Various contributors (see AUTHORS.txt) # Various contributors (see AUTHORS.txt)
# http://www.tuxpaint.org/ # http://www.tuxpaint.org/
# June 14, 2002 - June 22, 2020 # June 14, 2002 - July 24, 2020
# The version number, for release: # The version number, for release:
@ -115,10 +115,10 @@ PNG:=$(if $(PNG),$(PNG),$(call linktest,-lpng12,))
FRIBIDI_LIB:=$(shell $(PKG_CONFIG) --libs fribidi) FRIBIDI_LIB:=$(shell $(PKG_CONFIG) --libs fribidi)
FRIBIDI_CFLAGS:=$(shell $(PKG_CONFIG) --cflags fribidi) FRIBIDI_CFLAGS:=$(shell $(PKG_CONFIG) --cflags fribidi)
windows_ARCH_LINKS:=-lintl $(PNG) -lzdll -lwinspool -lshlwapi $(FRIBIDI_LIB) -liconv windows_ARCH_LINKS:=-lintl $(PNG) -lzdll -lwinspool -lshlwapi $(FRIBIDI_LIB) -liconv -limagequant
osx_ARCH_LINKS:=$(FRIBIDI_LIB) osx_ARCH_LINKS:=$(FRIBIDI_LIB) -limagequant
beos_ARCH_LINKS:=-lintl $(PNG) -lz -lbe -lnetwork -liconv $(FRIBIDI_LIB) $(PAPER_LIB) $(STDC_LIB) beos_ARCH_LINKS:=-lintl $(PNG) -lz -lbe -lnetwork -liconv $(FRIBIDI_LIB) $(PAPER_LIB) $(STDC_LIB) -limagequant
linux_ARCH_LINKS:=$(PAPER_LIB) $(FRIBIDI_LIB) linux_ARCH_LINKS:=$(PAPER_LIB) $(FRIBIDI_LIB) -limagequant
ARCH_LINKS:=$($(OS)_ARCH_LINKS) ARCH_LINKS:=$($(OS)_ARCH_LINKS)
windows_ARCH_HEADERS:=src/win32_print.h windows_ARCH_HEADERS:=src/win32_print.h
@ -1035,6 +1035,7 @@ TuxPaint.dmg:
tuxpaint: obj/tuxpaint.o obj/i18n.o obj/im.o obj/cursor.o obj/pixels.o \ tuxpaint: obj/tuxpaint.o obj/i18n.o obj/im.o obj/cursor.o obj/pixels.o \
obj/rgblinear.o obj/playsound.o obj/fonts.o obj/parse.o obj/fill.o \ obj/rgblinear.o obj/playsound.o obj/fonts.o obj/parse.o obj/fill.o \
obj/progressbar.o obj/dirwalk.o obj/get_fname.o obj/onscreen_keyboard.o \ obj/progressbar.o obj/dirwalk.o obj/get_fname.o obj/onscreen_keyboard.o \
obj/gifenc.o \
$(ARCH_LIBS) $(ARCH_LIBS)
@echo @echo
@echo "...Linking Tux Paint..." @echo "...Linking Tux Paint..."
@ -1055,6 +1056,7 @@ obj/tuxpaint.o: src/tuxpaint.c \
src/tools.h src/titles.h src/colors.h src/shapes.h \ src/tools.h src/titles.h src/colors.h src/shapes.h \
src/sounds.h src/tip_tux.h src/great.h \ src/sounds.h src/tip_tux.h src/great.h \
src/tp_magic_api.h src/parse.h src/onscreen_keyboard.h \ src/tp_magic_api.h src/parse.h src/onscreen_keyboard.h \
src/gifenc.h \
src/$(MOUSEDIR)/arrow.xbm src/$(MOUSEDIR)/arrow-mask.xbm \ src/$(MOUSEDIR)/arrow.xbm src/$(MOUSEDIR)/arrow-mask.xbm \
src/$(MOUSEDIR)/hand.xbm src/$(MOUSEDIR)/hand-mask.xbm \ src/$(MOUSEDIR)/hand.xbm src/$(MOUSEDIR)/hand-mask.xbm \
src/$(MOUSEDIR)/insertion.xbm \ src/$(MOUSEDIR)/insertion.xbm \
@ -1140,6 +1142,12 @@ obj/pixels.o: src/pixels.c src/pixels.h src/compiler.h src/debug.h
@$(CC) $(CFLAGS) $(DEBUG_FLAGS) $(SDL_CFLAGS) $(DEFS) \ @$(CC) $(CFLAGS) $(DEBUG_FLAGS) $(SDL_CFLAGS) $(DEFS) \
-c src/pixels.c -o obj/pixels.o -c src/pixels.c -o obj/pixels.o
obj/gifenc.o: src/gifenc.c src/gifenc.h
@echo
@echo "...Compiling animated GIF export libary..."
@$(CC) $(CFLAGS) $(DEBUG_FLAGS) $(DEFS) \
-c src/gifenc.c -o obj/gifenc.o
obj/playsound.o: src/playsound.c src/playsound.h \ obj/playsound.o: src/playsound.c src/playsound.h \
src/compiler.h src/debug.h src/compiler.h src/debug.h
@echo @echo

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -103,6 +103,10 @@ $Id$
which was from "Gimp-gluas" plug-in for The GIMP: which was from "Gimp-gluas" plug-in for The GIMP:
http://pippin.gimp.org/plug-ins/gluas/ http://pippin.gimp.org/plug-ins/gluas/
Animated GIF export from "gifenc",
https://github.com/lecram/gifenc,
by Marcel Rodrigues <http://lecram.github.io/>
Mouse accessibility code and keyboard access Mouse accessibility code and keyboard access
Ankit Choudary <ankit.goaldecided@gmail.com>, as part of GSOC 2010, Ankit Choudary <ankit.goaldecided@gmail.com>, as part of GSOC 2010,
with integration and fixes by Pere Pujal i Carabantes <pere@fornol.no-ip.org> with integration and fixes by Pere Pujal i Carabantes <pere@fornol.no-ip.org>

View file

@ -8,7 +8,16 @@ http://www.tuxpaint.org/
$Id$ $Id$
2020.June.22 (0.9.25) 2020.July.24 (0.9.25)
* New Features
------------
* [WIP] GIF export option from Open -> Slideshow dialog.
* Utilizes "gifenc", public domain by Marcel Rodrigues:
https://github.com/lecram/gifenc
* Depends on "libimagequant", from the "pngquant2" project:
https://github.com/ImageOptim/libimagequant
(GPL v3 or later, for Free/Libre Open Source Software)
* Ports & Building * Ports & Building
---------------- ----------------
* Corrections for Haiku not opening saved files. * Corrections for Haiku not opening saved files.

287
src/gifenc.c Normal file
View file

@ -0,0 +1,287 @@
#include "gifenc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
/* helper to write a little-endian 16-bit number portably */
#define write_num(fd, n) write((fd), (uint8_t []) {(n) & 0xFF, (n) >> 8}, 2)
static uint8_t vga[0x30] = {
0x00, 0x00, 0x00,
0xAA, 0x00, 0x00,
0x00, 0xAA, 0x00,
0xAA, 0x55, 0x00,
0x00, 0x00, 0xAA,
0xAA, 0x00, 0xAA,
0x00, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA,
0x55, 0x55, 0x55,
0xFF, 0x55, 0x55,
0x55, 0xFF, 0x55,
0xFF, 0xFF, 0x55,
0x55, 0x55, 0xFF,
0xFF, 0x55, 0xFF,
0x55, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF,
};
struct Node {
uint16_t key;
struct Node *children[];
};
typedef struct Node Node;
static Node *
new_node(uint16_t key, int degree)
{
Node *node = calloc(1, sizeof(*node) + degree * sizeof(Node *));
if (node)
node->key = key;
return node;
}
static Node *
new_trie(int degree, int *nkeys)
{
Node *root = new_node(0, degree);
/* Create nodes for single pixels. */
for (*nkeys = 0; *nkeys < degree; (*nkeys)++)
root->children[*nkeys] = new_node(*nkeys, degree);
*nkeys += 2; /* skip clear code and stop code */
return root;
}
static void
del_trie(Node *root, int degree)
{
if (!root)
return;
for (int i = 0; i < degree; i++)
del_trie(root->children[i], degree);
free(root);
}
static void put_loop(ge_GIF *gif, uint16_t loop);
ge_GIF *
ge_new_gif(
const char *fname, uint16_t width, uint16_t height,
uint8_t *palette, int depth, int loop
)
{
int i, r, g, b, v;
ge_GIF *gif = calloc(1, sizeof(*gif) + 2*width*height);
if (!gif)
goto no_gif;
gif->w = width; gif->h = height;
gif->depth = depth > 1 ? depth : 2;
gif->frame = (uint8_t *) &gif[1];
gif->back = &gif->frame[width*height];
gif->fd = creat(fname, 0666);
if (gif->fd == -1)
goto no_fd;
#ifdef _WIN32
setmode(gif->fd, O_BINARY);
#endif
write(gif->fd, "GIF89a", 6);
write_num(gif->fd, width);
write_num(gif->fd, height);
write(gif->fd, (uint8_t []) {0xF0 | (depth-1), 0x00, 0x00}, 3);
if (palette) {
write(gif->fd, palette, 3 << depth);
} else if (depth <= 4) {
write(gif->fd, vga, 3 << depth);
} else {
write(gif->fd, vga, sizeof(vga));
i = 0x10;
for (r = 0; r < 6; r++) {
for (g = 0; g < 6; g++) {
for (b = 0; b < 6; b++) {
write(gif->fd, (uint8_t []) {r*51, g*51, b*51}, 3);
if (++i == 1 << depth)
goto done_gct;
}
}
}
for (i = 1; i <= 24; i++) {
v = i * 0xFF / 25;
write(gif->fd, (uint8_t []) {v, v, v}, 3);
}
}
done_gct:
if (loop >= 0 && loop <= 0xFFFF)
put_loop(gif, (uint16_t) loop);
return gif;
no_fd:
free(gif);
no_gif:
return NULL;
}
static void
put_loop(ge_GIF *gif, uint16_t loop)
{
write(gif->fd, (uint8_t []) {'!', 0xFF, 0x0B}, 3);
write(gif->fd, "NETSCAPE2.0", 11);
write(gif->fd, (uint8_t []) {0x03, 0x01}, 2);
write_num(gif->fd, loop);
write(gif->fd, "\0", 1);
}
/* Add packed key to buffer, updating offset and partial.
* gif->offset holds position to put next *bit*
* gif->partial holds bits to include in next byte */
static void
put_key(ge_GIF *gif, uint16_t key, int key_size)
{
int byte_offset, bit_offset, bits_to_write;
byte_offset = gif->offset / 8;
bit_offset = gif->offset % 8;
gif->partial |= ((uint32_t) key) << bit_offset;
bits_to_write = bit_offset + key_size;
while (bits_to_write >= 8) {
gif->buffer[byte_offset++] = gif->partial & 0xFF;
if (byte_offset == 0xFF) {
write(gif->fd, "\xFF", 1);
write(gif->fd, gif->buffer, 0xFF);
byte_offset = 0;
}
gif->partial >>= 8;
bits_to_write -= 8;
}
gif->offset = (gif->offset + key_size) % (0xFF * 8);
}
static void
end_key(ge_GIF *gif)
{
int byte_offset;
byte_offset = gif->offset / 8;
if (gif->offset % 8)
gif->buffer[byte_offset++] = gif->partial & 0xFF;
write(gif->fd, (uint8_t []) {byte_offset}, 1);
write(gif->fd, gif->buffer, byte_offset);
write(gif->fd, "\0", 1);
gif->offset = gif->partial = 0;
}
static void
put_image(ge_GIF *gif, uint16_t w, uint16_t h, uint16_t x, uint16_t y)
{
int nkeys, key_size, i, j;
Node *node, *child, *root;
int degree = 1 << gif->depth;
write(gif->fd, ",", 1);
write_num(gif->fd, x);
write_num(gif->fd, y);
write_num(gif->fd, w);
write_num(gif->fd, h);
write(gif->fd, (uint8_t []) {0x00, gif->depth}, 2);
root = node = new_trie(degree, &nkeys);
key_size = gif->depth + 1;
put_key(gif, degree, key_size); /* clear code */
for (i = y; i < y+h; i++) {
for (j = x; j < x+w; j++) {
uint8_t pixel = gif->frame[i*gif->w+j] & (degree - 1);
child = node->children[pixel];
if (child) {
node = child;
} else {
put_key(gif, node->key, key_size);
if (nkeys < 0x1000) {
if (nkeys == (1 << key_size))
key_size++;
node->children[pixel] = new_node(nkeys++, degree);
} else {
put_key(gif, degree, key_size); /* clear code */
del_trie(root, degree);
root = node = new_trie(degree, &nkeys);
key_size = gif->depth + 1;
}
node = root->children[pixel];
}
}
}
put_key(gif, node->key, key_size);
put_key(gif, degree + 1, key_size); /* stop code */
end_key(gif);
del_trie(root, degree);
}
static int
get_bbox(ge_GIF *gif, uint16_t *w, uint16_t *h, uint16_t *x, uint16_t *y)
{
int i, j, k;
int left, right, top, bottom;
left = gif->w; right = 0;
top = gif->h; bottom = 0;
k = 0;
for (i = 0; i < gif->h; i++) {
for (j = 0; j < gif->w; j++, k++) {
if (gif->frame[k] != gif->back[k]) {
if (j < left) left = j;
if (j > right) right = j;
if (i < top) top = i;
if (i > bottom) bottom = i;
}
}
}
if (left != gif->w && top != gif->h) {
*x = left; *y = top;
*w = right - left + 1;
*h = bottom - top + 1;
return 1;
} else {
return 0;
}
}
static void
set_delay(ge_GIF *gif, uint16_t d)
{
write(gif->fd, (uint8_t []) {'!', 0xF9, 0x04, 0x04}, 4);
write_num(gif->fd, d);
write(gif->fd, "\0\0", 2);
}
void
ge_add_frame(ge_GIF *gif, uint16_t delay)
{
uint16_t w, h, x, y;
uint8_t *tmp;
if (delay)
set_delay(gif, delay);
if (gif->nframes == 0) {
w = gif->w;
h = gif->h;
x = y = 0;
} else if (!get_bbox(gif, &w, &h, &x, &y)) {
/* image's not changed; save one pixel just to add delay */
w = h = 1;
x = y = 0;
}
put_image(gif, w, h, x, y);
gif->nframes++;
tmp = gif->back;
gif->back = gif->frame;
gif->frame = tmp;
}
void
ge_close_gif(ge_GIF* gif)
{
write(gif->fd, ";", 1);
close(gif->fd);
free(gif);
}

24
src/gifenc.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef GIFENC_H
#define GIFENC_H
#include <stdint.h>
typedef struct ge_GIF {
uint16_t w, h;
int depth;
int fd;
int offset;
int nframes;
uint8_t *frame, *back;
uint32_t partial;
uint8_t buffer[0xFF];
} ge_GIF;
ge_GIF *ge_new_gif(
const char *fname, uint16_t width, uint16_t height,
uint8_t *palette, int depth, int loop
);
void ge_add_frame(ge_GIF *gif, uint16_t delay);
void ge_close_gif(ge_GIF* gif);
#endif /* GIFENC_H */

View file

@ -483,6 +483,8 @@ static void mtw(wchar_t * wtok, char *tok)
#error "---------------------------------------------------" #error "---------------------------------------------------"
#endif #endif
#include "libimagequant.h"
#include "SDL_getenv.h" #include "SDL_getenv.h"
#include "i18n.h" #include "i18n.h"
@ -495,6 +497,7 @@ static void mtw(wchar_t * wtok, char *tok)
#include "dirwalk.h" #include "dirwalk.h"
#include "get_fname.h" #include "get_fname.h"
#include "onscreen_keyboard.h" #include "onscreen_keyboard.h"
#include "gifenc.h"
#include "tools.h" #include "tools.h"
#include "titles.h" #include "titles.h"
@ -1432,7 +1435,7 @@ static SDL_Surface *img_black, *img_grey;
static SDL_Surface *img_yes, *img_no; static SDL_Surface *img_yes, *img_no;
static SDL_Surface *img_sfx, *img_speak; static SDL_Surface *img_sfx, *img_speak;
static SDL_Surface *img_open, *img_erase, *img_back, *img_trash; static SDL_Surface *img_open, *img_erase, *img_back, *img_trash;
static SDL_Surface *img_slideshow, *img_play, *img_select_digits; static SDL_Surface *img_slideshow, *img_play, *img_gif_export, *img_select_digits;
static SDL_Surface *img_printer, *img_printer_wait; static SDL_Surface *img_printer, *img_printer_wait;
static SDL_Surface *img_save_over, *img_popup_arrow; static SDL_Surface *img_save_over, *img_popup_arrow;
static SDL_Surface *img_cursor_up, *img_cursor_down; static SDL_Surface *img_cursor_up, *img_cursor_down;
@ -1755,7 +1758,8 @@ static short *brushes_directional = NULL;
static SDL_Surface *img_shapes[NUM_SHAPES], *img_shape_names[NUM_SHAPES]; static SDL_Surface *img_shapes[NUM_SHAPES], *img_shape_names[NUM_SHAPES];
static SDL_Surface *img_openlabels_open, *img_openlabels_erase, static SDL_Surface *img_openlabels_open, *img_openlabels_erase,
*img_openlabels_slideshow, *img_openlabels_back, *img_openlabels_play, *img_openlabels_next; *img_openlabels_slideshow, *img_openlabels_back, *img_openlabels_play,
*img_openlabels_gif_export, *img_openlabels_next;
static SDL_Surface *img_tux[NUM_TIP_TUX]; static SDL_Surface *img_tux[NUM_TIP_TUX];
@ -7861,11 +7865,14 @@ static void create_button_labels(void)
/* Open dialog: 'Back' button, to dismiss Open dialog without opening a picture */ /* Open dialog: 'Back' button, to dismiss Open dialog without opening a picture */
img_openlabels_back = do_render_button_label(gettext_noop("Back")); img_openlabels_back = do_render_button_label(gettext_noop("Back"));
/* Slideshow: 'Next' button, to load next slide (image) */
img_openlabels_next = do_render_button_label(gettext_noop("Next"));
/* Slideshow: 'Play' button, to begin a slideshow sequence */ /* Slideshow: 'Play' button, to begin a slideshow sequence */
img_openlabels_play = do_render_button_label(gettext_noop("Play")); img_openlabels_play = do_render_button_label(gettext_noop("Play"));
/* Slideshow: 'GIF Export' button, to create an animated GIF */
img_openlabels_gif_export = do_render_button_label(gettext_noop("GIF Export"));
/* Slideshow: 'Next' button, to load next slide (image) */
img_openlabels_next = do_render_button_label(gettext_noop("Next"));
} }
@ -15029,7 +15036,7 @@ static int do_slideshow(void)
SDL_Rect dest; SDL_Rect dest;
SDL_Event event; SDL_Event event;
SDLKey key; SDLKey key;
char *freeme; char *freeme, *instructions;
int speeds; int speeds;
float x_per, y_per; float x_per, y_per;
int xx, yy; int xx, yy;
@ -15278,9 +15285,8 @@ static int do_slideshow(void)
/* Let user choose images: */ /* Let user choose images: */
/* Instructions for Slideshow file dialog (FIXME: Make a #define) */ /* Instructions for Slideshow file dialog (FIXME: Make a #define) */
freeme = textdir(gettext_noop("Choose the pictures you want, " "then click “Play”.")); instructions = textdir(gettext_noop("Choose the pictures you want, " "then click “Play”."));
draw_tux_text(TUX_BORED, freeme, 1); draw_tux_text(TUX_BORED, instructions, 1);
free(freeme);
/* NOTE: cur is now set above; if file_id'th file is found, it's /* NOTE: cur is now set above; if file_id'th file is found, it's
set to that file's index; otherwise, we default to '0' */ set to that file's index; otherwise, we default to '0' */
@ -15386,6 +15392,21 @@ static int do_slideshow(void)
SDL_BlitSurface(img_openlabels_play, NULL, screen, &dest); SDL_BlitSurface(img_openlabels_play, NULL, screen, &dest);
/* "GIF Export" button: */
dest.x = WINDOW_WIDTH - 96 - 48 * 2;
dest.y = (48 * 7 + 40 + HEIGHTOFFSET) - 48;
SDL_BlitSurface(img_btn_up, NULL, screen, &dest);
dest.x = WINDOW_WIDTH - 96 - 48 * 2 + (48 - img_gif_export->w) / 2;
dest.y = (48 * 7 + 40 + HEIGHTOFFSET) - 48;
SDL_BlitSurface(img_gif_export, NULL, screen, &dest);
dest.x = WINDOW_WIDTH - 96 - 48 * 2 + (48 - img_openlabels_gif_export->w) / 2;
dest.y = (48 * 7 + 40 + HEIGHTOFFSET) - img_openlabels_gif_export->h;
SDL_BlitSurface(img_openlabels_gif_export, NULL, screen, &dest);
/* "Back" button: */ /* "Back" button: */
dest.x = WINDOW_WIDTH - 96 - 48; dest.x = WINDOW_WIDTH - 96 - 48;
@ -15633,6 +15654,31 @@ static int do_slideshow(void)
update_list = 1; update_list = 1;
} }
} }
else if (event.button.x >= (WINDOW_WIDTH - 96 - 48 - 48) &&
event.button.x < (WINDOW_WIDTH - 96 - 48) &&
event.button.y >= (48 * 7 + 40 + HEIGHTOFFSET) - 48 &&
event.button.y < (48 * 7 + 40 + HEIGHTOFFSET))
{
/* GIF Export */
playsound(screen, 1, SND_CLICK, 1, SNDPOS_RIGHT, SNDDIST_NEAR);
if (num_selected < 2)
{
/* None selected? Too dangerous to select all.
Only 1 selected? No point in saving as GIF.
*/
freeme = textdir(gettext_noop("Select 2 or more drawings to turn into an animated GIF."));
draw_tux_text(TUX_BORED, freeme, 1);
free(freeme);
control_drawtext_timer(2000, instructions, 0); /* N.B. It will draw instructions, regardless */
}
else
{
/* FIXME: Do it */
}
}
else if (event.button.x >= (WINDOW_WIDTH - 96 - 48) && else if (event.button.x >= (WINDOW_WIDTH - 96 - 48) &&
event.button.x < (WINDOW_WIDTH - 96) && event.button.x < (WINDOW_WIDTH - 96) &&
event.button.y >= (48 * 7 + 40 + HEIGHTOFFSET) - 48 && event.button.y >= (48 * 7 + 40 + HEIGHTOFFSET) - 48 &&
@ -15696,7 +15742,7 @@ static int do_slideshow(void)
do_setcursor(cursor_down); do_setcursor(cursor_down);
} }
else if (((event.button.x >= 96 && event.button.x < 96 + 48 + 96) || else if (((event.button.x >= 96 && event.button.x < 96 + 48 + 96) ||
(event.button.x >= (WINDOW_WIDTH - 96 - 48) && (event.button.x >= (WINDOW_WIDTH - 96 - 48 * 2) &&
event.button.x < (WINDOW_WIDTH - 96))) && event.button.x < (WINDOW_WIDTH - 96))) &&
event.button.y >= (48 * 7 + 40 + HEIGHTOFFSET) - 48 && event.button.y >= (48 * 7 + 40 + HEIGHTOFFSET) - 48 &&
event.button.y < (48 * 7 + 40 + HEIGHTOFFSET)) event.button.y < (48 * 7 + 40 + HEIGHTOFFSET))
@ -15736,6 +15782,17 @@ static int do_slideshow(void)
else if (event.type == SDL_JOYBUTTONDOWN || event.type == SDL_JOYBUTTONUP) else if (event.type == SDL_JOYBUTTONDOWN || event.type == SDL_JOYBUTTONUP)
handle_joybuttonupdown(event, oldpos_x, oldpos_y); handle_joybuttonupdown(event, oldpos_x, oldpos_y);
else if (event.type == SDL_USEREVENT)
{
if (event.user.code == USEREVENT_TEXT_UPDATE)
{
if (event.user.data1 != NULL)
{
draw_tux_text(TUX_BORED, instructions, 1);
}
}
}
} }
if (motioner | hatmotioner) if (motioner | hatmotioner)
@ -15764,6 +15821,8 @@ static int do_slideshow(void)
free(d_exts); free(d_exts);
free(selected); free(selected);
control_drawtext_timer(0, "", 0);
free(instructions);
return go_back; return go_back;
} }
@ -23990,6 +24049,7 @@ static void setup(void)
img_slideshow = loadimage(DATA_PREFIX "images/ui/slideshow.png"); img_slideshow = loadimage(DATA_PREFIX "images/ui/slideshow.png");
img_play = loadimage(DATA_PREFIX "images/ui/play.png"); img_play = loadimage(DATA_PREFIX "images/ui/play.png");
img_gif_export = loadimage(DATA_PREFIX "images/ui/gif_export.png");
img_select_digits = loadimage(DATA_PREFIX "images/ui/select_digits.png"); img_select_digits = loadimage(DATA_PREFIX "images/ui/select_digits.png");
img_popup_arrow = loadimage(DATA_PREFIX "images/ui/popup_arrow.png"); img_popup_arrow = loadimage(DATA_PREFIX "images/ui/popup_arrow.png");