Added progress bar to apply-effect and save file operations.

Added support to configure file format with a FileData like JpegData.
This commit is contained in:
David Capello 2008-03-29 03:43:19 +00:00
parent 0ffbf5164c
commit a951368da6
38 changed files with 630 additions and 217 deletions

View File

@ -1,3 +1,31 @@
2008-03-29 David A. Capello <dacap@users.sourceforge.net>
* src/file/jpeg_format.c (getdata_JPEG): Added from configure_jpeg.
* src/file/filedata.h (JpegData): Added.
* src/file/file.h (FileFormat): Added the `getdata' method to
configure the output format.
2008-03-28 David A. Capello <dacap@users.sourceforge.net>
* src/commands/cmd_save_file.c (save_sprite_in_background): Added
to save sprites with progress bar.
* src/commands/fx/effectbg.c (effect_apply_to_target_with_progressbar):
Added to show progress bar and background processing when the user
applies an effect.
* src/effect/effect.h (Effect): Added progress information to
customize the progress and cancellation of the effect operations.
* src/file/fli_format.c (load_FLI),
src/file/gif_format.c (load_GIF): Now these two routines
configure the only layer as `Background'.
* src/file/file.h (FileOp): Added seq.has_alpha so a PNG file with
alpha hasn't a `Background' layer.
2008-03-27 David A. Capello <dacap@users.sourceforge.net>
* Added a call to undo_set_label(...) for every undo operation in

View File

@ -8,6 +8,7 @@ Next beta
+ quick_move
+ quick_copy
+ quick_swap
- search for "TODO remove me"
- add the progress bar for effects and save-file.
- fix colors
- tooltips for color-bar.

View File

@ -204,7 +204,7 @@
<menu name="&Tools">
<item command="configure_tools" name="&Configure" />
<separator />
<item command="film_editor" name="&Film Editor" />
<item command="animation_editor" name="&Animation Editor" />
<item command="palette_editor" name="&Palette Editor" />
<separator />
<menu name="F&X" id="fx_popup">

View File

@ -62,7 +62,6 @@ COMMON_SOURCES = \
src/commands/cmd_reselect_mask.c \
src/commands/cmd_run_script.c \
src/commands/cmd_save_file.c \
src/commands/cmd_save_file_as.c \
src/commands/cmd_save_mask.c \
src/commands/cmd_screen_shot.c \
src/commands/cmd_select_file.c \
@ -77,6 +76,7 @@ COMMON_SOURCES = \
src/commands/fx/cmd_despeckle.c \
src/commands/fx/cmd_invert_color.c \
src/commands/fx/cmd_replace_color.c \
src/commands/fx/effectbg.c \
src/console/console.c \
src/core/app.c \
src/core/cfg.c \

View File

@ -177,7 +177,7 @@ static void cmd_open_file_execute(const char *argument)
}
}
}
/* else do nothing (the user canceled or something like that) */
/* else do nothing (the user cancelled or something like that) */
}
}

View File

@ -20,40 +20,153 @@
#include <allegro.h>
#include "jinete/jbase.h"
#include "jinete/jinete.h"
#include "commands/commands.h"
#include "core/app.h"
#include "console/console.h"
#include "dialogs/filesel.h"
#include "file/file.h"
#include "modules/gui.h"
#include "modules/recent.h"
#include "modules/sprites.h"
#include "raster/sprite.h"
#include "widgets/statebar.h"
typedef struct SaveFileData
{
Monitor *monitor;
FileOp *fop;
Progress *progress;
JThread thread;
JWidget alert_window;
} SaveFileData;
/**
* Thread to do the hard work: save the file to the disk.
*
* [saving thread]
*/
static void savefile_bg(void *fop_data)
{
FileOp *fop = (FileOp *)fop_data;
fop_operate(fop);
fop_done(fop);
}
/**
* Called by the gui-monitor (a timer in the gui module that is called
* every 100 milliseconds).
*
* [main thread]
*/
static void monitor_savefile_bg(void *_data)
{
SaveFileData *data = (SaveFileData *)_data;
FileOp *fop = (FileOp *)data->fop;
if (data->progress)
progress_update(data->progress, fop_get_progress(fop));
if (fop_is_done(fop))
remove_gui_monitor(data->monitor);
}
/**
* Called when the monitor is destroyed.
*
* [main thread]
*/
static void monitor_free(void *_data)
{
SaveFileData *data = (SaveFileData *)_data;
if (data->alert_window != NULL) {
data->monitor = NULL;
jwindow_close(data->alert_window, NULL);
}
}
static void save_sprite_in_background(Sprite *sprite)
{
FileOp *fop = fop_to_save_sprite(sprite);
if (fop) {
JThread thread = jthread_new(savefile_bg, fop);
if (thread) {
SaveFileData *data = jnew(SaveFileData, 1);
data->fop = fop;
data->progress = progress_new(app_get_statusbar());
data->thread = thread;
data->alert_window = jalert_new(PACKAGE
"<<Saving file:<<%s||&Cancel",
get_filename(sprite->filename));
data->monitor = NULL;
/* add a monitor to check the saving (FileOp) progress */
data->monitor = add_gui_monitor(monitor_savefile_bg,
monitor_free, data);
/* TODO error handling */
jwindow_open_fg(data->alert_window);
if (data->monitor != NULL)
remove_gui_monitor(data->monitor);
/* wait the `savefile_bg' thread */
jthread_join(data->thread);
/* show any error */
if (fop->error) {
console_open();
console_printf(fop->error);
console_close();
}
/* no error? */
else {
recent_file(sprite->filename);
sprite_mark_as_saved(sprite);
statusbar_set_text(app_get_statusbar(),
2000, "File %s, saved.",
get_filename(sprite->filename));
}
progress_free(data->progress);
jwidget_free(data->alert_window);
fop_free(fop);
jfree(data);
}
}
}
/*********************************************************************
Save File
*********************************************************************/
/**
* Returns true if there is a current sprite to save.
*
* [main thread]
*/
static bool cmd_save_file_enabled(const char *argument)
{
return current_sprite != NULL;
}
/**
* Saves the current sprite in a file.
*
* [main thread]
*/
static void cmd_save_file_execute(const char *argument)
{
Sprite *sprite = current_sprite;
/* if the sprite is associated to a file in the file-system, we can
save it directly without user interaction */
if (sprite_is_associated_to_file(current_sprite)) {
if (sprite_save(current_sprite) == 0) {
recent_file(current_sprite->filename);
sprite_mark_as_saved(current_sprite);
if (app_get_statusbar())
statusbar_set_text(app_get_statusbar(),
1000, "File %s, saved.",
get_filename(current_sprite->filename));
}
else {
/* TODO if the user cancel we shouldn't unrecent the file */
unrecent_file(current_sprite->filename);
}
if (sprite_is_associated_to_file(sprite)) {
save_sprite_in_background(sprite);
}
/* if the sprite isn't associated to a file, we must to show the
save-as dialog to the user to select for first time the file-name
@ -63,6 +176,64 @@ static void cmd_save_file_execute(const char *argument)
}
}
/*********************************************************************
Save File As
*********************************************************************/
static bool cmd_save_file_as_enabled(const char *argument)
{
return current_sprite != NULL;
}
static void cmd_save_file_as_execute(const char *argument)
{
Sprite *sprite = current_sprite;
char filename[4096];
char exts[4096];
char *newfilename;
int ret;
ustrcpy(filename, sprite->filename);
get_writable_extensions(exts, sizeof(exts));
for (;;) {
newfilename = ase_file_selector(_("Save Sprite"), filename, exts);
if (!newfilename)
return;
ustrcpy(filename, newfilename);
jfree(newfilename);
/* does the file exist? */
if (exists(filename)) {
/* ask if the user wants overwrite the file? */
ret = jalert("%s<<%s<<%s||%s||%s||%s",
_("Warning"),
_("File exists, overwrite it?"),
get_filename(filename),
_("&Yes"), _("&No"), _("&Cancel"));
}
else
break;
/* "yes": we must continue with the operation... */
if (ret == 1)
break;
/* "cancel" or <esc> per example: we back doing nothing */
else if (ret != 2)
return;
/* "no": we must back to select other file-name */
}
sprite_set_filename(sprite, filename);
app_realloc_sprite_list();
save_sprite_in_background(sprite);
}
/**
* Command to save the current sprite in its associated file.
*/
Command cmd_save_file = {
CMD_SAVE_FILE,
cmd_save_file_enabled,
@ -70,3 +241,14 @@ Command cmd_save_file = {
cmd_save_file_execute,
NULL
};
/**
* Command to save the current sprite in another file.
*/
Command cmd_save_file_as = {
CMD_SAVE_FILE_AS,
cmd_save_file_as_enabled,
NULL,
cmd_save_file_as_execute,
NULL
};

View File

@ -1,98 +0,0 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <allegro.h>
#include "jinete/jalert.h"
#include "commands/commands.h"
#include "console/console.h"
#include "core/app.h"
#include "dialogs/filesel.h"
#include "file/file.h"
#include "modules/recent.h"
#include "modules/gui.h"
#include "modules/sprites.h"
#include "raster/sprite.h"
static bool cmd_save_file_as_enabled(const char *argument)
{
return current_sprite != NULL;
}
static void cmd_save_file_as_execute(const char *argument)
{
char filename[4096];
char exts[4096];
char *newfilename;
int ret;
ustrcpy(filename, current_sprite->filename);
get_writable_extensions(exts, sizeof(exts));
for (;;) {
newfilename = ase_file_selector(_("Save Sprite"), filename, exts);
if (!newfilename)
return;
ustrcpy(filename, newfilename);
jfree(newfilename);
/* does the file exist? */
if (exists(filename)) {
/* ask if the user wants overwrite the file? */
ret = jalert("%s<<%s<<%s||%s||%s||%s",
_("Warning"),
_("File exists, overwrite it?"),
get_filename(filename),
_("&Yes"), _("&No"), _("&Cancel"));
}
else
break;
/* "yes": we must continue with the operation... */
if (ret == 1)
break;
/* "cancel" or <esc> per example: we back doing nothing */
else if (ret != 2)
return;
/* "no": we must back to select other file-name */
}
sprite_set_filename(current_sprite, filename);
app_realloc_sprite_list();
if (sprite_save(current_sprite) == 0) {
recent_file(filename);
sprite_mark_as_saved(current_sprite);
}
else {
/* TODO if the user cancel we shouldn't unrecent the file */
unrecent_file(filename);
}
}
Command cmd_save_file_as = {
CMD_SAVE_FILE_AS,
cmd_save_file_as_enabled,
NULL,
cmd_save_file_as_execute,
NULL
};

View File

@ -21,6 +21,7 @@
#include "jinete/jinete.h"
#include "commands/commands.h"
#include "commands/fx/effectbg.h"
#include "console/console.h"
#include "core/app.h"
#include "core/cfg.h"
@ -124,7 +125,7 @@ static void cmd_color_curve_execute(const char *argument)
jwindow_open_fg(window);
if (jwindow_get_killer(window) == button_ok) {
effect_apply_to_target(effect);
effect_apply_to_target_with_progressbar(effect);
}
effect_free(effect);

View File

@ -32,6 +32,7 @@
#include "jinete/jwindow.h"
#include "commands/commands.h"
#include "commands/fx/effectbg.h"
#include "console/console.h"
#include "core/cfg.h"
#include "core/color.h"
@ -149,7 +150,7 @@ static void cmd_convolution_matrix_execute(const char *argument)
jwindow_open_fg(window);
if (jwindow_get_killer(window) == button_ok) {
effect_apply_to_target(effect);
effect_apply_to_target_with_progressbar(effect);
}
effect_free(effect);

View File

@ -28,6 +28,7 @@
#include "jinete/jwindow.h"
#include "commands/commands.h"
#include "commands/fx/effectbg.h"
#include "console/console.h"
#include "core/cfg.h"
#include "core/core.h"
@ -130,7 +131,7 @@ static void cmd_despeckle_execute(const char *argument)
jwindow_open_fg(window);
if (jwindow_get_killer(window) == button_ok) {
effect_apply_to_target(effect);
effect_apply_to_target_with_progressbar(effect);
}
effect_free(effect);

View File

@ -27,6 +27,7 @@
#include "jinete/jwindow.h"
#include "commands/commands.h"
#include "commands/fx/effectbg.h"
#include "console/console.h"
#include "core/cfg.h"
#include "core/color.h"
@ -109,7 +110,7 @@ static void cmd_invert_color_execute(const char *argument)
jwindow_open_fg(window);
if (jwindow_get_killer(window) == button_ok) {
effect_apply_to_target(effect);
effect_apply_to_target_with_progressbar(effect);
}
effect_free(effect);

View File

@ -23,6 +23,7 @@
#include "jinete/jinete.h"
#include "commands/commands.h"
#include "commands/fx/effectbg.h"
#include "console/console.h"
#include "core/app.h"
#include "core/cfg.h"
@ -137,7 +138,7 @@ static void cmd_replace_color_execute(const char *argument)
jwindow_open_fg(window);
if (jwindow_get_killer(window) == button_ok) {
effect_apply_to_target(effect);
effect_apply_to_target_with_progressbar(effect);
}
effect_free(effect);

193
src/commands/fx/effectbg.c Normal file
View File

@ -0,0 +1,193 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include "jinete/jinete.h"
#include "core/app.h"
#include "core/cfg.h"
#include "effect/effect.h"
#include "modules/editors.h"
#include "modules/gui.h"
#include "modules/sprites.h"
#include "raster/sprite.h"
#include "widgets/editor.h"
#include "widgets/statebar.h"
/**********************************************************************
Apply effect in two threads: bg-thread to modify the sprite, and the
main thread to monitoring the progress.
**********************************************************************/
typedef struct ThreadData
{
Effect *effect; /* effect to be applied */
JMutex mutex; /* mutex to access to 'pos', 'done'
and 'cancelled' fields in different
threads */
float pos; /* current progress position */
bool done; /* was the effect completelly applied? */
bool cancelled; /* was the effect cancelled by the user? */
Monitor *monitor; /* monitor to update the progress-bar */
Progress *progress; /* the progress-bar */
JThread thread; /* thread to apply the effect in background */
JWidget alert_window; /* alert for the user to cancel the
effect-progress if he wants */
} ThreadData;
/**
* Called by @ref effect_apply to informate the progress of the
* effect.
*
* [effect thread]
*/
static void effect_progress_hook(void *_data, float progress)
{
ThreadData *data = (ThreadData *)_data;
jmutex_lock(data->mutex);
data->pos = progress;
jmutex_unlock(data->mutex);
}
/**
* Called by @ref effect_apply to know if the user cancelled the
* operation.
*
* [effect thread]
*/
static bool effect_is_cancelled_hook(void *_data)
{
ThreadData *data = (ThreadData *)_data;
bool cancelled;
jmutex_lock(data->mutex);
cancelled = data->cancelled;
jmutex_unlock(data->mutex);
return cancelled;
}
/**
* Applies the effect to the sprite in a background thread.
*
* [effect thread]
*/
static void effect_bg(void *_data)
{
ThreadData *data = (ThreadData *)_data;
/* apply the effect */
effect_apply_to_target(data->effect);
/* mark the work as 'done' */
jmutex_lock(data->mutex);
data->done = TRUE;
jmutex_unlock(data->mutex);
}
/**
* Called by the gui-monitor (a timer in the gui module that is called
* every 100 milliseconds).
*
* [main thread]
*/
static void monitor_effect_bg(void *_data)
{
ThreadData *data = (ThreadData *)_data;
float pos;
bool done;
jmutex_lock(data->mutex);
pos = data->pos;
done = data->done;
jmutex_unlock(data->mutex);
if (data->progress)
progress_update(data->progress, pos);
if (data->done)
remove_gui_monitor(data->monitor);
}
/**
* Called to destroy the data of the monitor.
*
* [main thread]
*/
static void monitor_free(void *_data)
{
ThreadData *data = (ThreadData *)_data;
if (data->alert_window != NULL)
jwindow_close(data->alert_window, NULL);
}
/**
* Applies the effect to the specified targets in the effect structure.
*
* [main thread]
*/
void effect_apply_to_target_with_progressbar(Effect *effect)
{
ThreadData *data;
data = jnew(ThreadData, 1);
if (data == NULL) {
jalert("Error<<Not enough memory||&OK");
return;
}
effect->progress_data = data;
effect->progress = effect_progress_hook;
effect->is_cancelled = effect_is_cancelled_hook;
data->mutex = jmutex_new();
data->effect = effect;
data->pos = 0.0;
data->done = FALSE;
data->cancelled = FALSE;
data->progress = progress_new(app_get_statusbar());
data->thread = jthread_new(effect_bg, data);
data->alert_window = jalert_new(PACKAGE
"<<Applying effect...||&Cancel");
data->monitor = add_gui_monitor(monitor_effect_bg,
monitor_free, data);
/* TODO error handling */
jwindow_open_fg(data->alert_window);
jmutex_lock(data->mutex);
if (!data->done) {
remove_gui_monitor(data->monitor);
data->cancelled = TRUE;
}
jmutex_unlock(data->mutex);
/* wait the `effect_bg' thread */
jthread_join(data->thread);
progress_free(data->progress);
jwidget_free(data->alert_window);
jfree(data);
}

View File

@ -0,0 +1,26 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef COMMANDS_FX_EFFECTBG_H
#define COMMANDS_FX_EFFECTBG_H
struct Effect;
void effect_apply_to_target_with_progressbar(struct Effect *effect);
#endif /* COMMANDS_FX_EFFECTBG_H */

View File

@ -465,7 +465,7 @@ void app_realloc_sprite_list(void)
*
* @warning This routine can't be used when a menu callback was
* called, because, it destroy the menus, you should use
* rebuild_recent_list() instead (src/gui/gui.c).
* schedule_rebuild_recent_list() instead (src/modules/gui.c).
*/
bool app_realloc_recent_list(void)
{

View File

@ -701,8 +701,9 @@ void color_to_formalstring(int imgtype, color_t color,
break;
case COLOR_TYPE_INDEX: {
ase_uint32 _c = palette_get_entry(get_current_palette(), data & 0xff);
ase_uint32 _c;
data = GET_COLOR_DATA_INDEX(color);
_c = palette_get_entry(get_current_palette(), data & 0xff);
uszprintf(buf, size, "%s %d (RGB %d %d %d)",
_("Index"),
data & 0xff,

View File

@ -982,7 +982,7 @@ static FileItem *get_fileitem_by_path(const char *path, bool create_if_not)
FileItem *fileitem;
int attrib;
#ifdef ALLEGRO_UNIX
#ifdef ALLEGRO_UNIX
if (*path == 0)
return rootitem;
#endif

View File

@ -50,8 +50,8 @@ void curve_get_values(Curve *curve, int x1, int x2, int *values);
void set_color_curve(Curve *curve);
void apply_color_curve4 (struct Effect *effect);
void apply_color_curve2 (struct Effect *effect);
void apply_color_curve1 (struct Effect *effect);
void apply_color_curve4(struct Effect *effect);
void apply_color_curve2(struct Effect *effect);
void apply_color_curve1(struct Effect *effect);
#endif /* EFFECT_COLCURVE_H */

View File

@ -55,8 +55,8 @@ JList get_convmatr_stock(void);
void init_convolution_matrix(void);
void exit_convolution_matrix(void);
void apply_convolution_matrix4 (struct Effect *effect);
void apply_convolution_matrix2 (struct Effect *effect);
void apply_convolution_matrix1 (struct Effect *effect);
void apply_convolution_matrix4(struct Effect *effect);
void apply_convolution_matrix2(struct Effect *effect);
void apply_convolution_matrix1(struct Effect *effect);
#endif /* EFFECT_CONVMATR_H */

View File

@ -117,6 +117,9 @@ Effect *effect_new(Sprite *sprite, const char *name)
effect->mask_address = NULL;
effect->effect_data = effect_data;
effect->apply = apply;
effect->progress_data = NULL;
effect->progress = NULL;
effect->is_cancelled = NULL;
effect_load_target(effect);
@ -266,13 +269,20 @@ bool effect_apply_step(Effect *effect)
void effect_apply(Effect *effect)
{
/* add_progress(effect->h); */
bool cancelled = FALSE;
effect_begin(effect);
while (effect_apply_step(effect))
;
/* do_progress(effect->row); */
while (!cancelled && effect_apply_step(effect)) {
if (effect->progress != NULL)
(effect->progress)(effect->progress_data,
effect->progress_base
+ effect->progress_width * (effect->row+1) / effect->h);
if (effect->is_cancelled != NULL)
cancelled = (effect->is_cancelled)(effect->progress_data);
}
if (!cancelled) {
/* undo stuff */
if (undo_is_enabled(effect->sprite->undo)) {
undo_set_label(effect->sprite->undo,
@ -283,10 +293,13 @@ void effect_apply(Effect *effect)
/* copy "dst" to "src" */
image_copy(effect->src, effect->dst, 0, 0);
/* del_progress(); */
}
}
/**
* Updates the current editor to show the progress of the preview.
*/
void effect_flush(Effect *effect)
{
if (effect->row >= 0) {
@ -329,6 +342,7 @@ void effect_apply_to_target(Effect *effect)
int n, n2, images = 0;
Stock *stock;
int *x, *y;
bool cancelled = FALSE;
stock = sprite_get_images(effect->sprite, target, TRUE, &x, &y);
if (!stock)
@ -339,24 +353,29 @@ void effect_apply_to_target(Effect *effect)
images++;
if (images > 0) {
/* open undo group of operations */
if (images > 1) {
/* open undo */
if (undo_is_enabled(effect->sprite->undo))
undo_open(effect->sprite->undo);
}
/* add_progress(images); */
for (n=n2=0; n<stock->nimage; n++) {
effect->progress_base = 0.0f;
effect->progress_width = 1.0f / images;
for (n=n2=0; n<stock->nimage && !cancelled; n++) {
if (!stock->image[n])
continue;
/* do_progress(n2++); */
effect_apply_to_image(effect, stock->image[n], x[n], y[n]);
}
/* del_progress(); */
if (effect->is_cancelled != NULL)
cancelled = (effect->is_cancelled)(effect->progress_data);
effect->progress_base += effect->progress_width;
}
/* close undo group of operations */
if (images > 1) {
/* close */
if (undo_is_enabled(effect->sprite->undo))
undo_close(effect->sprite->undo);
}

View File

@ -50,6 +50,11 @@ typedef struct Effect
int a:1;
int index:1;
} target;
/* hooks */
float progress_base, progress_width;
void *progress_data;
void (*progress)(void *data, float progress);
bool (*is_cancelled)(void *data);
} Effect;
Effect *effect_new(struct Sprite *sprite, const char *name);

View File

@ -106,6 +106,7 @@ FileFormat format_ase =
"ase,aseprite",
load_ASE,
save_ASE,
NULL,
FILE_SUPPORT_RGB |
FILE_SUPPORT_RGBA |
FILE_SUPPORT_GRAY |

View File

@ -35,6 +35,7 @@ FileFormat format_bmp =
"bmp",
load_BMP,
save_BMP,
NULL,
FILE_SUPPORT_RGB |
FILE_SUPPORT_GRAY |
FILE_SUPPORT_INDEXED |
@ -678,7 +679,7 @@ static bool load_BMP(FileOp *fop)
}
/* setup the file-data */
if (fop_sequence_get_filedata(fop) == NULL) {
if (fop->seq.filedata == NULL) {
BmpData *bmpdata = bmpdata_new();
bmpdata->format = format;

View File

@ -320,7 +320,7 @@ FileOp *fop_to_save_sprite(Sprite *sprite)
if (jlist_length(fop->sprite->palettes) > 1) {
if (!(fop->format->flags & (FILE_SUPPORT_PALETTES |
FILE_SUPPORT_SEQUENCES))) {
usprintf(buf+ustrlen(buf), "<<- %s", _("Palette changes"));
usprintf(buf+ustrlen(buf), "<<- %s", _("Palette changes between frames"));
}
}
@ -414,6 +414,20 @@ FileOp *fop_to_save_sprite(Sprite *sprite)
else
fop->filename = jstrdup(fop->sprite->filename);
/* configure output format? */
if (fop->format->getdata) {
FileData *data = (fop->format->getdata)(fop);
/* does the user cancelled the operation? */
if (data == NULL) {
fop_free(fop);
return NULL;
}
fop->seq.filedata = data;
sprite_set_filedata(fop->sprite, data);
}
return fop;
}
@ -470,6 +484,7 @@ void fop_operate(FileOp *fop)
frame = 0;
old_image = NULL;
fop->seq.has_alpha = FALSE;
fop->seq.progress_offset = 0.0f;
fop->seq.progress_fraction = 1.0f / (float)frames;
@ -539,6 +554,10 @@ void fop_operate(FileOp *fop)
/* final setup */
if (fop->sprite != NULL) {
/* configure the layer as the `Background' */
if (!fop->seq.has_alpha)
layer_configure_as_background(fop->seq.layer);
/* set the frames range */
sprite_set_frames(fop->sprite, frame);
@ -691,11 +710,6 @@ void fop_sequence_set_filedata(FileOp *fop, FileData *filedata)
fop->seq.filedata = filedata;
}
FileData *fop_sequence_get_filedata(FileOp *fop)
{
return fop->seq.filedata;
}
void fop_sequence_set_color(FileOp *fop, int index, int r, int g, int b)
{
palette_set_entry(fop->seq.palette, index, _rgba(r, g, b, 255));
@ -731,9 +745,6 @@ Image *fop_sequence_image(FileOp *fop, int imgtype, int w, int h)
/* add the layer */
layer_add_layer(sprite->set, layer);
/* configure the layer as the background */
layer_configure_as_background(layer);
/* done */
fop->sprite = sprite;
fop->seq.layer = layer;

View File

@ -50,10 +50,14 @@ struct FileFormat;
struct FileOp;
/* file operations */
typedef enum { FileOpLoad, FileOpSave } FileOpType;
typedef enum { FileOpLoad,
FileOpSave } FileOpType;
typedef bool (*FileLoad)(struct FileOp *fop);
typedef bool (*FileSave)(struct FileOp *fop);
typedef struct FileData *(*FileGetData)(struct FileOp *fop);
/* load or/and save a file format */
typedef struct FileFormat
{
@ -61,6 +65,7 @@ typedef struct FileFormat
const char *exts; /* extensions (e.g. "jpeg,jpg") */
FileLoad load; /* procedure to read a sprite in this format */
FileSave save; /* procedure to write a sprite in this format */
FileGetData getdata; /* procedure to configure the format to be saved */
int flags;
} FileFormat;
@ -92,6 +97,7 @@ typedef struct FileOp
float progress_fraction; /* progress fraction for one frame */
/* to load sequences */
int frame;
bool has_alpha;
struct Layer *layer;
struct Cel *last_cel;
struct FileData *filedata;
@ -118,8 +124,6 @@ void fop_stop(FileOp *fop);
void fop_free(FileOp *fop);
void fop_sequence_set_filedata(FileOp *fop, struct FileData *filedata);
struct FileData *fop_sequence_get_filedata(FileOp *fop);
void fop_sequence_set_color(FileOp *fop, int index, int r, int g, int b);
void fop_sequence_get_color(FileOp *fop, int index, int *r, int *g, int *b);
struct Image *fop_sequence_image(FileOp *fi, int imgtype, int w, int h);

View File

@ -56,3 +56,14 @@ BmpData *bmpdata_new(void)
return bmpdata;
}
JpegData *jpegdata_new(void)
{
JpegData *jpegdata = (JpegData *)filedata_new(FILEDATA_JPEG,
sizeof(JpegData));
if (jpegdata == NULL)
return NULL;
return jpegdata;
}

View File

@ -21,6 +21,7 @@
enum {
FILEDATA_BMP,
FILEDATA_JPEG,
FILEDATA_MAX
};
@ -60,4 +61,23 @@ typedef struct BmpData
BmpData *bmpdata_new(void);
/*********************************************************************
Data for JPEG files
*********************************************************************/
#define JPEGDATA_METHOD_SLOW 0 /* slow but accurate integer algorithm */
#define JPEGDATA_METHOD_FAST 1 /* faster, less accurate integer method */
#define JPEGDATA_METHOD_FLOAT 2 /* floating-point: accurate, fast on fast HW */
#define JPEGDATA_METHOD_DEFAULT JPEGDATA_METHOD_SLOW
typedef struct JpegData
{
FileData head;
float quality; /* 1.0 maximum quality */
float smooth; /* 1.0 maximum smooth */
int method;
} JpegData;
JpegData *jpegdata_new(void);
#endif /* FILEDATA_H */

View File

@ -37,6 +37,7 @@ FileFormat format_fli =
"flc,fli",
load_FLI,
save_FLI,
NULL,
FILE_SUPPORT_INDEXED |
FILE_SUPPORT_FRAMES |
FILE_SUPPORT_PALETTES
@ -104,8 +105,8 @@ static bool load_FLI(FileOp *fop)
/* create the image */
sprite = sprite_new(IMAGE_INDEXED, w, h);
layer = layer_new(sprite);
layer_set_name(layer, _("Background"));
layer_add_layer(sprite->set, layer);
layer_configure_as_background(layer);
/* set frames and speed */
sprite_set_frames(sprite, fli_header.frames);

View File

@ -47,12 +47,12 @@ FileFormat format_gif =
"gif",
load_GIF,
save_GIF,
NULL,
FILE_SUPPORT_INDEXED |
FILE_SUPPORT_FRAMES |
FILE_SUPPORT_PALETTES
};
static void render_gif_frame(GIF_FRAME *frame, Image *image,
int x, int y, int w, int h)
{
@ -117,7 +117,7 @@ static bool load_GIF(FileOp *fop)
}
layer_add_layer(sprite->set, layer);
layer_set_name(layer, _("Base"));
layer_configure_as_background(layer);
image_clear(current_image, gif->background_index);
image_clear(current_image_old, gif->background_index);

View File

@ -34,6 +34,7 @@ FileFormat format_ico =
"ico",
NULL, /* load_ICO, */
save_ICO,
NULL,
/* FILE_SUPPORT_RGB | */
/* FILE_SUPPORT_GRAY | */
FILE_SUPPORT_INDEXED

View File

@ -28,6 +28,7 @@
#include "core/cfg.h"
#include "core/core.h"
#include "file/file.h"
#include "file/filedata.h"
#include "raster/raster.h"
#include "script/script.h"
@ -35,8 +36,7 @@
static bool load_JPEG(FileOp *fop);
static bool save_JPEG(FileOp *fop);
static bool configure_jpeg(void); /* TODO warning: not thread safe */
static JpegData *getdata_JPEG(FileOp *fop);
FileFormat format_jpeg =
{
@ -44,6 +44,7 @@ FileFormat format_jpeg =
"jpeg,jpg",
load_JPEG,
save_JPEG,
getdata_JPEG,
FILE_SUPPORT_RGB |
FILE_SUPPORT_GRAY |
FILE_SUPPORT_SEQUENCES
@ -228,19 +229,8 @@ static bool save_JPEG(FileOp *fop)
FILE *file;
JSAMPARRAY buffer;
JDIMENSION buffer_height;
JpegData *jpegdata = (JpegData *)fop->seq.filedata;
int c;
int smooth;
int quality;
J_DCT_METHOD method;
/* Configure JPEG compression only in the first frame. */
if (fop->sprite->frame == 0 && !configure_jpeg())
return FALSE;
/* Options. */
smooth = get_config_int("JPEG", "Smooth", 0);
quality = get_config_int("JPEG", "Quality", 100);
method = get_config_int("JPEG", "Method", JDCT_DEFAULT);
/* Open the file for write in it. */
file = fopen(fop->filename, "wb");
@ -271,9 +261,9 @@ static bool save_JPEG(FileOp *fop)
}
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE);
cinfo.dct_method = method;
cinfo.smoothing_factor = smooth;
jpeg_set_quality(&cinfo, (int)MID(0, 100.0f * jpegdata->quality, 100), TRUE);
cinfo.dct_method = jpegdata->method;
cinfo.smoothing_factor = (int)MID(0, 100.0f * jpegdata->smooth, 100);
/* Start compressor. */
jpeg_start_compress(&cinfo, TRUE);
@ -358,26 +348,25 @@ static bool save_JPEG(FileOp *fop)
/**
* Shows the JPEG configuration dialog.
*/
static bool configure_jpeg(void)
static JpegData *getdata_JPEG(FileOp *fop)
{
JWidget window, box1, box2, box3, box4, box5;
JWidget label_quality, label_smooth, label_method;
JWidget slider_quality, slider_smooth, view_method;
JWidget list_method, button_ok, button_cancel;
int quality, smooth, method;
bool ret;
JpegData *jpegdata = jpegdata_new();
/* configuration parameters */
jpegdata->quality = get_config_float("JPEG", "Quality", 0.6f);
jpegdata->smooth = 0.0f;
jpegdata->method = JPEGDATA_METHOD_DEFAULT;
/* interactive mode */
if (!is_interactive())
return TRUE;
/* configuration parameters */
quality = get_config_int("JPEG", "Quality", 100);
smooth = get_config_int("JPEG", "Smooth", 0);
method = get_config_int("JPEG", "Method", 0);
return jpegdata;
/* widgets */
window = jwindow_new(_("Configure JPEG Compression"));
window = jwindow_new(_("JPEG Options"));
box1 = jbox_new(JI_VERTICAL);
box2 = jbox_new(JI_HORIZONTAL);
box3 = jbox_new(JI_VERTICAL + JI_HOMOGENEOUS);
@ -386,8 +375,8 @@ static bool configure_jpeg(void)
label_quality = jlabel_new(_("Quality:"));
label_smooth = jlabel_new(_("Smooth:"));
label_method = jlabel_new(_("Method:"));
slider_quality = jslider_new(0, 100, quality);
slider_smooth = jslider_new(0, 100, smooth);
slider_quality = jslider_new(0, 10, jpegdata->quality*10);
slider_smooth = jslider_new(0, 10, jpegdata->smooth*10);
view_method = jview_new();
list_method = jlistbox_new();
button_ok = jbutton_new(_("&OK"));
@ -396,13 +385,14 @@ static bool configure_jpeg(void)
jwidget_add_child(list_method, jlistitem_new(_("Slow")));
jwidget_add_child(list_method, jlistitem_new(_("Fast")));
jwidget_add_child(list_method, jlistitem_new(_("Float")));
jlistbox_select_index(list_method, method);
jlistbox_select_index(list_method, jpegdata->method);
jview_attach(view_method, list_method);
jview_maxsize(view_method);
jwidget_expansive(box4, TRUE);
jwidget_expansive(view_method, TRUE);
jwidget_magnetic(button_ok, TRUE);
jwidget_add_child(box3, label_quality);
jwidget_add_child(box3, label_smooth);
@ -421,19 +411,17 @@ static bool configure_jpeg(void)
jwindow_open_fg(window);
if (jwindow_get_killer(window) == button_ok) {
ret = TRUE;
jpegdata->quality = jslider_get_value(slider_quality) / 10.0f;
jpegdata->smooth = jslider_get_value(slider_smooth) / 10.0f;
jpegdata->method = jlistbox_get_selected_index(list_method);
quality = jslider_get_value(slider_quality);
smooth = jslider_get_value(slider_smooth);
method = jlistbox_get_selected_index(list_method);
set_config_int("JPEG", "Quality", quality);
set_config_int("JPEG", "Smooth", smooth);
set_config_int("JPEG", "Method", method);
set_config_float("JPEG", "Quality", jpegdata->quality);
}
else {
filedata_free((FileData *)jpegdata);
jpegdata = NULL;
}
else
ret = FALSE;
jwidget_free(window);
return ret;
return jpegdata;
}

View File

@ -34,6 +34,7 @@ FileFormat format_pcx =
"pcx",
load_PCX,
save_PCX,
NULL,
FILE_SUPPORT_RGB |
FILE_SUPPORT_GRAY |
FILE_SUPPORT_INDEXED |

View File

@ -42,6 +42,7 @@ FileFormat format_png =
"png",
load_PNG,
save_PNG,
NULL,
FILE_SUPPORT_RGB |
FILE_SUPPORT_RGBA |
FILE_SUPPORT_GRAY |
@ -155,17 +156,23 @@ static bool load_PNG(FileOp *fop)
/* create the output image */
switch (info_ptr->color_type) {
case PNG_COLOR_TYPE_RGB:
case PNG_COLOR_TYPE_RGB_ALPHA:
fop->seq.has_alpha = TRUE;
case PNG_COLOR_TYPE_RGB:
imgtype = IMAGE_RGB;
break;
case PNG_COLOR_TYPE_GRAY:
case PNG_COLOR_TYPE_GRAY_ALPHA:
fop->seq.has_alpha = TRUE;
case PNG_COLOR_TYPE_GRAY:
imgtype = IMAGE_GRAYSCALE;
break;
case PNG_COLOR_TYPE_PALETTE:
imgtype = IMAGE_INDEXED;
break;
default:
fop_error(fop, "Color type not supported\n)");
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);

View File

@ -37,6 +37,7 @@ FileFormat format_tga =
"tga",
load_TGA,
save_TGA,
NULL,
FILE_SUPPORT_RGB |
FILE_SUPPORT_RGBA |
FILE_SUPPORT_GRAY |

View File

@ -54,6 +54,8 @@
#define REBUILD_RECENT_LIST 2
#define REFRESH_FULL_SCREEN 4
#define MONITOR_TIMER_MSECS 100
/**************************************************************/
#ifdef ALLEGRO_WINDOWS
@ -573,7 +575,7 @@ JWidget load_widget(const char *filename, const char *name)
return widget;
}
void rebuild_recent_list(void)
void schedule_rebuild_recent_list(void)
{
next_idle_flags |= REBUILD_RECENT_LIST;
}
@ -740,7 +742,7 @@ Monitor *add_gui_monitor(void (*proc)(void *),
jlist_append(monitors, monitor);
if (monitor_timer < 0)
monitor_timer = jmanager_add_timer(manager, 100);
monitor_timer = jmanager_add_timer(manager, MONITOR_TIMER_MSECS);
jmanager_start_timer(monitor_timer);
@ -748,7 +750,7 @@ Monitor *add_gui_monitor(void (*proc)(void *),
}
/**
* Removes a previously added monitor.
* Removes and frees a previously added monitor.
*/
void remove_gui_monitor(Monitor *monitor)
{

View File

@ -50,7 +50,7 @@ void save_window_pos(JWidget window, const char *section);
JWidget load_widget(const char *filename, const char *name);
void rebuild_recent_list(void);
void schedule_rebuild_recent_list(void);
void hook_signal(JWidget widget,
int signal_num,

View File

@ -88,7 +88,7 @@ void recent_file(const char *filename)
if (strcmp(filename, filename_it) == 0) {
jlist_remove(recent_files, filename_it);
jlist_prepend(recent_files, filename_it);
rebuild_recent_list();
schedule_rebuild_recent_list();
return;
}
count++;
@ -103,7 +103,7 @@ void recent_file(const char *filename)
}
jlist_prepend(recent_files, jstrdup(filename));
rebuild_recent_list();
schedule_rebuild_recent_list();
}
}
@ -118,7 +118,7 @@ void unrecent_file(const char *filename)
if (strcmp(filename, filename_it) == 0) {
jfree(filename_it);
jlist_delete_link(recent_files, link);
rebuild_recent_list();
schedule_rebuild_recent_list();
break;
}
}

View File

@ -102,6 +102,8 @@ static bool preview_msg_proc(JWidget widget, JMessage msg)
case JM_CLOSE:
set_preview_image(NULL, NULL);
/* stop the preview timer */
jmanager_stop_timer(preview->timer_id);
break;
case JM_TIMER: