2007-11-16 18:25:45 +00:00
|
|
|
/* ASE - Allegro Sprite Editor
|
2010-02-01 21:25:40 +00:00
|
|
|
* Copyright (C) 2001-2010 David Capello
|
2007-09-18 23:57:02 +00:00
|
|
|
*
|
|
|
|
* 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"
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
#include <allegro.h>
|
2010-09-23 23:33:39 -03:00
|
|
|
#include <string.h>
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2009-12-11 14:53:05 +00:00
|
|
|
#include "app.h"
|
2010-09-23 23:33:39 -03:00
|
|
|
#include "base/mutex.h"
|
|
|
|
#include "base/scoped_lock.h"
|
|
|
|
#include "console.h"
|
2007-09-18 23:57:02 +00:00
|
|
|
#include "file/file.h"
|
2008-03-29 04:35:30 +00:00
|
|
|
#include "file/format_options.h"
|
2010-11-06 11:59:03 -03:00
|
|
|
#include "gui/jalert.h"
|
2007-09-18 23:57:02 +00:00
|
|
|
#include "modules/gui.h"
|
2008-03-22 18:43:56 +00:00
|
|
|
#include "modules/palettes.h"
|
2007-09-18 23:57:02 +00:00
|
|
|
#include "raster/raster.h"
|
2010-04-12 21:41:26 -03:00
|
|
|
#include "util/quantize.h"
|
2007-09-30 15:32:21 +00:00
|
|
|
#include "widgets/statebar.h"
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2007-12-05 01:30:50 +00:00
|
|
|
extern FileFormat format_ase;
|
|
|
|
extern FileFormat format_bmp;
|
|
|
|
extern FileFormat format_fli;
|
|
|
|
extern FileFormat format_jpeg;
|
|
|
|
extern FileFormat format_pcx;
|
|
|
|
extern FileFormat format_tga;
|
|
|
|
extern FileFormat format_gif;
|
|
|
|
extern FileFormat format_ico;
|
|
|
|
extern FileFormat format_png;
|
|
|
|
|
|
|
|
static FileFormat *formats[] =
|
|
|
|
{
|
|
|
|
&format_ase,
|
|
|
|
&format_bmp,
|
|
|
|
&format_fli,
|
|
|
|
&format_jpeg,
|
|
|
|
&format_pcx,
|
|
|
|
&format_tga,
|
|
|
|
&format_gif,
|
|
|
|
&format_ico,
|
|
|
|
&format_png,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
static FileOp *fop_new(FileOpType type);
|
|
|
|
static void fop_prepare_for_sequence(FileOp *fop);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2007-12-05 01:30:50 +00:00
|
|
|
static FileFormat *get_fileformat(const char *extension);
|
2007-09-20 00:32:35 +00:00
|
|
|
static int split_filename(const char *filename, char *left, char *right, int *width);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
void get_readable_extensions(char* buf, int size)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
/* clear the string */
|
2008-02-04 02:37:26 +00:00
|
|
|
ustrncpy(buf, empty_string, size);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2007-12-05 01:30:50 +00:00
|
|
|
/* insert file format */
|
|
|
|
for (c=0; formats[c]; c++) {
|
|
|
|
if (formats[c]->load)
|
2008-02-04 02:37:26 +00:00
|
|
|
ustrncat(buf, formats[c]->exts, size);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2007-12-05 01:30:50 +00:00
|
|
|
if (formats[c+1] && formats[c]->load)
|
2008-02-04 02:37:26 +00:00
|
|
|
ustrncat(buf, ",", size);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
void get_writable_extensions(char* buf, int size)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
/* clear the string */
|
2008-02-04 02:37:26 +00:00
|
|
|
ustrncpy(buf, empty_string, size);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2007-12-05 01:30:50 +00:00
|
|
|
/* insert file format */
|
|
|
|
for (c=0; formats[c]; c++) {
|
|
|
|
if (formats[c]->save)
|
2008-02-04 02:37:26 +00:00
|
|
|
ustrncat(buf, formats[c]->exts, size);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2007-12-05 01:30:50 +00:00
|
|
|
if (formats[c+1] && formats[c]->save)
|
2008-02-04 02:37:26 +00:00
|
|
|
ustrncat(buf, ",", size);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-20 00:32:35 +00:00
|
|
|
Sprite *sprite_load(const char *filename)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
|
|
|
Sprite *sprite;
|
2008-02-10 19:06:03 +00:00
|
|
|
/* TODO add a option to configure what to do with the sequence */
|
|
|
|
FileOp *fop = fop_to_load_sprite(filename, FILE_LOAD_SEQUENCE_NONE);
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!fop)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* operate in this same thread */
|
|
|
|
fop_operate(fop);
|
2008-02-10 19:06:03 +00:00
|
|
|
fop_done(fop);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2010-11-06 11:59:03 -03:00
|
|
|
if (fop->has_error()) {
|
2009-06-11 15:11:11 +00:00
|
|
|
Console console;
|
2010-11-06 11:59:03 -03:00
|
|
|
console.printf(fop->error.c_str());
|
2009-06-11 15:11:11 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
sprite = fop->sprite;
|
|
|
|
fop_free(fop);
|
|
|
|
|
|
|
|
return sprite;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sprite_save(Sprite *sprite)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
FileOp *fop = fop_to_save_sprite(sprite);
|
|
|
|
if (!fop)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* operate in this same thread */
|
|
|
|
fop_operate(fop);
|
2008-02-10 19:06:03 +00:00
|
|
|
fop_done(fop);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2010-11-06 11:59:03 -03:00
|
|
|
if (fop->has_error()) {
|
2009-06-11 15:11:11 +00:00
|
|
|
Console console;
|
2010-11-06 11:59:03 -03:00
|
|
|
console.printf(fop->error.c_str());
|
2009-06-11 15:11:11 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2010-11-06 11:59:03 -03:00
|
|
|
ret = (!fop->has_error() ? 0: -1);
|
2008-02-04 02:37:26 +00:00
|
|
|
fop_free(fop);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-02-10 19:06:03 +00:00
|
|
|
FileOp *fop_to_load_sprite(const char *filename, int flags)
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
|
|
|
char *extension;
|
|
|
|
FileOp *fop;
|
|
|
|
|
|
|
|
fop = fop_new(FileOpLoad);
|
|
|
|
if (!fop)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* get the extension of the filename (in lower case) */
|
|
|
|
extension = jstrdup(get_extension(filename));
|
2007-11-14 21:28:33 +00:00
|
|
|
ustrlwr(extension);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2007-11-14 21:28:33 +00:00
|
|
|
PRINTF("Loading file \"%s\" (%s)\n", filename, extension);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
/* does file exist? */
|
|
|
|
if (!file_exists(filename, FA_ALL, NULL)) {
|
2010-09-18 23:54:56 -03:00
|
|
|
fop_error(fop, "File not found: \"%s\"\n", filename);
|
2008-02-04 02:37:26 +00:00
|
|
|
goto done;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
/* get the format through the extension of the filename */
|
|
|
|
fop->format = get_fileformat(extension);
|
|
|
|
if (!fop->format ||
|
|
|
|
!fop->format->load) {
|
2010-09-18 23:54:56 -03:00
|
|
|
fop_error(fop, "ASE can't load \"%s\" files\n", extension);
|
2008-02-04 02:37:26 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
/* use the "sequence" interface */
|
2008-02-04 02:37:26 +00:00
|
|
|
if (fop->format->flags & FILE_SUPPORT_SEQUENCES) {
|
2008-02-10 19:06:03 +00:00
|
|
|
/* prepare to load a sequence */
|
2008-02-04 02:37:26 +00:00
|
|
|
fop_prepare_for_sequence(fop);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
/* per now, we want load just one file */
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->seq.filename_list.push_back(filename);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-10 19:06:03 +00:00
|
|
|
/* don't load the sequence (just the one file/one frame) */
|
|
|
|
if (!(flags & FILE_LOAD_SEQUENCE_NONE)) {
|
|
|
|
char buf[512], left[512], right[512];
|
|
|
|
int c, width, start_from;
|
|
|
|
|
|
|
|
/* first of all, we must generate the list of files to load in the
|
|
|
|
sequence... */
|
|
|
|
|
|
|
|
/* check is this could be a sequence */
|
|
|
|
start_from = split_filename(filename, left, right, &width);
|
|
|
|
if (start_from >= 0) {
|
|
|
|
/* try to get more file names */
|
|
|
|
for (c=start_from+1; ; c++) {
|
|
|
|
/* get the next file name */
|
|
|
|
usprintf(buf, "%s%0*d%s", left, width, c, right);
|
|
|
|
|
|
|
|
/* if the file doesn't exist, we doesn't need more files to load */
|
|
|
|
if (!exists(buf))
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* add this file name to the list */
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->seq.filename_list.push_back(buf);
|
2008-02-10 19:06:03 +00:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2008-02-10 19:06:03 +00:00
|
|
|
/* TODO add a better dialog to edit file-names */
|
|
|
|
if ((flags & FILE_LOAD_SEQUENCE_ASK) &&
|
2010-09-18 17:36:21 -03:00
|
|
|
App::instance()->isGui()) {
|
2008-02-10 19:06:03 +00:00
|
|
|
/* really want load all files? */
|
2010-11-06 11:59:03 -03:00
|
|
|
if ((fop->seq.filename_list.size() > 1) &&
|
2010-09-18 23:54:56 -03:00
|
|
|
(jalert("Notice"
|
|
|
|
"<<Possible animation with:"
|
|
|
|
"<<%s"
|
|
|
|
"<<Load the sequence of bitmaps?"
|
|
|
|
"||&Agree||&Skip",
|
2008-02-10 19:06:03 +00:00
|
|
|
get_filename(filename)) != 1)) {
|
2010-11-06 11:59:03 -03:00
|
|
|
|
2008-02-10 19:06:03 +00:00
|
|
|
/* if the user replies "Skip", we need just one file name (the
|
|
|
|
first one) */
|
2010-11-06 11:59:03 -03:00
|
|
|
if (fop->seq.filename_list.size() > 1) {
|
|
|
|
fop->seq.filename_list.erase(fop->seq.filename_list.begin()+1,
|
|
|
|
fop->seq.filename_list.end());
|
2008-02-10 19:06:03 +00:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
else
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->filename = filename;
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-10 19:06:03 +00:00
|
|
|
/* load just one frame */
|
|
|
|
if (flags & FILE_LOAD_ONE_FRAME)
|
2010-01-30 16:43:13 +00:00
|
|
|
fop->oneframe = true;
|
2008-02-10 19:06:03 +00:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
done:;
|
|
|
|
jfree(extension);
|
|
|
|
return fop;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
FileOp *fop_to_save_sprite(Sprite *sprite)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
|
|
|
char extension[32], buf[2048];
|
2008-02-04 02:37:26 +00:00
|
|
|
FileOp *fop;
|
2007-09-18 23:57:02 +00:00
|
|
|
bool fatal;
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
fop = fop_new(FileOpSave);
|
|
|
|
if (!fop)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* sprite to save */
|
|
|
|
fop->sprite = sprite;
|
|
|
|
|
|
|
|
/* get the extension of the filename (in lower case) */
|
2010-03-30 21:43:18 -03:00
|
|
|
ustrcpy(extension, get_extension(fop->sprite->getFilename()));
|
2007-09-18 23:57:02 +00:00
|
|
|
ustrlwr(extension);
|
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
PRINTF("Saving sprite \"%s\" (%s)\n", fop->sprite->getFilename(), extension);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
/* get the format through the extension of the filename */
|
|
|
|
fop->format = get_fileformat(extension);
|
|
|
|
if (!fop->format ||
|
|
|
|
!fop->format->save) {
|
2010-09-18 23:54:56 -03:00
|
|
|
fop_error(fop, "ASE can't save \"%s\" files\n", extension);
|
2008-02-04 02:37:26 +00:00
|
|
|
return fop;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* warnings */
|
|
|
|
ustrcpy(buf, empty_string);
|
2010-01-30 16:43:13 +00:00
|
|
|
fatal = false;
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
/* check image type support */
|
2010-03-30 21:43:18 -03:00
|
|
|
switch (fop->sprite->getImgType()) {
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
case IMAGE_RGB:
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!(fop->format->flags & FILE_SUPPORT_RGB)) {
|
2010-09-18 23:54:56 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- %s", "RGB format");
|
2010-01-30 16:43:13 +00:00
|
|
|
fatal = true;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!(fop->format->flags & FILE_SUPPORT_RGBA) &&
|
2010-03-30 21:43:18 -03:00
|
|
|
fop->sprite->needAlpha()) {
|
2010-09-18 23:54:56 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- %s", "Alpha channel");
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IMAGE_GRAYSCALE:
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!(fop->format->flags & FILE_SUPPORT_GRAY)) {
|
2010-09-18 23:54:56 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- Grayscale format");
|
2010-01-30 16:43:13 +00:00
|
|
|
fatal = true;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!(fop->format->flags & FILE_SUPPORT_GRAYA) &&
|
2010-03-30 21:43:18 -03:00
|
|
|
fop->sprite->needAlpha()) {
|
2010-09-18 23:54:56 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- Alpha channel");
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IMAGE_INDEXED:
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!(fop->format->flags & FILE_SUPPORT_INDEXED)) {
|
2010-09-18 23:54:56 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- Indexed format");
|
2010-01-30 16:43:13 +00:00
|
|
|
fatal = true;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-11-17 13:12:26 +00:00
|
|
|
// check frames support
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!(fop->format->flags & (FILE_SUPPORT_FRAMES |
|
|
|
|
FILE_SUPPORT_SEQUENCES))) {
|
2010-03-30 21:43:18 -03:00
|
|
|
if (fop->sprite->getTotalFrames() > 1)
|
2010-09-18 23:54:56 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- Frames");
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2009-11-17 13:12:26 +00:00
|
|
|
// layers support
|
2010-03-30 21:43:18 -03:00
|
|
|
if (fop->sprite->getFolder()->get_layers_count() > 1) {
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!(fop->format->flags & FILE_SUPPORT_LAYERS)) {
|
2010-09-18 23:54:56 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- Layers");
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-30 21:38:01 -03:00
|
|
|
// Palettes support.
|
|
|
|
if (fop->sprite->getPalettes().size() > 1) {
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!(fop->format->flags & (FILE_SUPPORT_PALETTES |
|
|
|
|
FILE_SUPPORT_SEQUENCES))) {
|
2010-09-18 23:54:56 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- Palette changes between frames");
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* repositories */
|
2010-09-30 21:38:01 -03:00
|
|
|
MasksList masks = fop->sprite->getMasksRepository();
|
|
|
|
if (!masks.empty()) {
|
2007-09-18 23:57:02 +00:00
|
|
|
int count = 0;
|
|
|
|
|
2010-09-30 21:38:01 -03:00
|
|
|
for (MasksList::iterator it = masks.begin(); it != masks.end(); ++it) {
|
|
|
|
Mask* mask = *it;
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
// Names starting with '*' are ignored
|
2007-09-18 23:57:02 +00:00
|
|
|
if (mask->name && *mask->name == '*')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
if ((count > 0) && !(fop->format->flags & FILE_SUPPORT_MASKS_REPOSITORY)) {
|
2010-09-18 23:54:56 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- Mask Repository");
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-30 21:38:01 -03:00
|
|
|
if (!fop->sprite->getPathsRepository().empty()) {
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!(fop->format->flags & FILE_SUPPORT_PATHS_REPOSITORY)) {
|
2010-09-18 23:54:56 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- Path Repository");
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* show the confirmation alert */
|
2007-09-30 15:32:21 +00:00
|
|
|
if (ugetc(buf)) {
|
2008-02-04 02:37:26 +00:00
|
|
|
/* interative */
|
2010-09-18 17:36:21 -03:00
|
|
|
if (App::instance()->isGui()) {
|
2008-02-04 02:37:26 +00:00
|
|
|
int ret;
|
|
|
|
|
2007-09-18 23:57:02 +00:00
|
|
|
if (fatal)
|
2010-09-18 23:54:56 -03:00
|
|
|
ret = jalert("Error<<File format \"%s\" doesn't support:%s"
|
|
|
|
"||&Close",
|
2008-02-04 02:37:26 +00:00
|
|
|
fop->format->name, buf);
|
2007-09-18 23:57:02 +00:00
|
|
|
else
|
2010-09-18 23:54:56 -03:00
|
|
|
ret = jalert("Warning<<File format \"%s\" doesn't support:%s"
|
|
|
|
"<<Do you want continue?"
|
|
|
|
"||&Yes||&No",
|
2008-02-04 02:37:26 +00:00
|
|
|
fop->format->name, buf);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
/* operation can't be done (by fatal error) or the user cancel
|
|
|
|
the operation */
|
|
|
|
if ((fatal) || (ret != 1)) {
|
|
|
|
fop_free(fop);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* no interactive & fatal error? */
|
|
|
|
else if (fatal) {
|
|
|
|
fop_error(fop, buf);
|
|
|
|
return fop;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* use the "sequence" interface */
|
2008-02-04 02:37:26 +00:00
|
|
|
if (fop->format->flags & FILE_SUPPORT_SEQUENCES) {
|
|
|
|
fop_prepare_for_sequence(fop);
|
|
|
|
|
|
|
|
/* to save one frame */
|
2010-03-30 21:43:18 -03:00
|
|
|
if (fop->sprite->getTotalFrames() == 1) {
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->seq.filename_list.push_back(fop->sprite->getFilename());
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
/* to save more frames */
|
|
|
|
else {
|
|
|
|
char buf[256], left[256], right[256];
|
|
|
|
int frame, width, start_from;
|
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
start_from = split_filename(fop->sprite->getFilename(), left, right, &width);
|
2008-02-04 02:37:26 +00:00
|
|
|
if (start_from < 0) {
|
|
|
|
start_from = 0;
|
|
|
|
width =
|
2010-03-30 21:43:18 -03:00
|
|
|
(fop->sprite->getTotalFrames() < 10)? 1:
|
|
|
|
(fop->sprite->getTotalFrames() < 100)? 2:
|
|
|
|
(fop->sprite->getTotalFrames() < 1000)? 3: 4;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
for (frame=0; frame<fop->sprite->getTotalFrames(); frame++) {
|
2008-02-04 02:37:26 +00:00
|
|
|
/* get the name for this frame */
|
|
|
|
usprintf(buf, "%s%0*d%s", left, width, start_from+frame, right);
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->seq.filename_list.push_back(buf);
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->filename = fop->sprite->getFilename();
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2008-03-29 03:43:19 +00:00
|
|
|
/* configure output format? */
|
2008-03-29 04:24:36 +00:00
|
|
|
if (fop->format->get_options != NULL) {
|
|
|
|
FormatOptions *format_options = (fop->format->get_options)(fop);
|
2008-03-29 03:43:19 +00:00
|
|
|
|
|
|
|
/* does the user cancelled the operation? */
|
2008-03-29 04:24:36 +00:00
|
|
|
if (format_options == NULL) {
|
2008-03-29 03:43:19 +00:00
|
|
|
fop_free(fop);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-03-29 04:24:36 +00:00
|
|
|
fop->seq.format_options = format_options;
|
2010-03-30 21:43:18 -03:00
|
|
|
fop->sprite->setFormatOptions(format_options);
|
2008-03-29 03:43:19 +00:00
|
|
|
}
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
return fop;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Finally does the file operation: loading or saving the sprite.
|
|
|
|
*
|
|
|
|
* It can be called from a different thread of the one used
|
|
|
|
* by @ref fop_to_load_sprite or @ref fop_to_save_sprite.
|
|
|
|
*
|
2008-02-10 19:06:03 +00:00
|
|
|
* After operate you must to mark the 'fop' as 'done' using @ref fop_done.
|
2008-02-04 02:37:26 +00:00
|
|
|
*/
|
|
|
|
void fop_operate(FileOp *fop)
|
|
|
|
{
|
2010-08-03 23:33:44 -03:00
|
|
|
ASSERT(fop != NULL);
|
|
|
|
ASSERT(!fop_is_done(fop));
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
/* load ***********************************************************/
|
|
|
|
if (fop->type == FileOpLoad &&
|
|
|
|
fop->format != NULL &&
|
|
|
|
fop->format->load != NULL) {
|
|
|
|
/* load a sequence */
|
2010-11-06 11:59:03 -03:00
|
|
|
if (fop->is_sequence()) {
|
2008-02-04 02:37:26 +00:00
|
|
|
int frame, frames, image_index = 0;
|
|
|
|
Image *old_image;
|
|
|
|
bool loadres;
|
|
|
|
|
|
|
|
/* default palette */
|
2010-03-28 12:15:32 -03:00
|
|
|
fop->seq.palette->makeBlack();
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
/* TODO set_palette for each frame??? */
|
|
|
|
#define SEQUENCE_IMAGE() \
|
|
|
|
do { \
|
2010-09-30 22:38:26 -03:00
|
|
|
image_index = fop->sprite->getStock()->addImage(fop->seq.image); \
|
2008-02-04 02:37:26 +00:00
|
|
|
\
|
|
|
|
fop->seq.last_cel->image = image_index; \
|
2010-09-19 00:26:33 -03:00
|
|
|
fop->seq.layer->addCel(fop->seq.last_cel); \
|
2008-02-04 02:37:26 +00:00
|
|
|
\
|
2010-03-30 21:43:18 -03:00
|
|
|
if (fop->sprite->getPalette(frame) \
|
2010-03-28 12:15:32 -03:00
|
|
|
->countDiff(fop->seq.palette, NULL, NULL) > 0) { \
|
|
|
|
fop->seq.palette->setFrame(frame); \
|
2010-03-30 21:43:18 -03:00
|
|
|
fop->sprite->setPalette(fop->seq.palette, true); \
|
2008-03-22 18:43:56 +00:00
|
|
|
} \
|
2008-02-04 02:37:26 +00:00
|
|
|
\
|
|
|
|
old_image = fop->seq.image; \
|
|
|
|
fop->seq.image = NULL; \
|
|
|
|
fop->seq.last_cel = NULL; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/* load the sequence */
|
2010-11-06 11:59:03 -03:00
|
|
|
frames = fop->seq.filename_list.size();
|
2008-02-04 02:37:26 +00:00
|
|
|
frame = 0;
|
|
|
|
old_image = NULL;
|
|
|
|
|
2010-01-30 16:43:13 +00:00
|
|
|
fop->seq.has_alpha = false;
|
2008-02-04 02:37:26 +00:00
|
|
|
fop->seq.progress_offset = 0.0f;
|
|
|
|
fop->seq.progress_fraction = 1.0f / (float)frames;
|
|
|
|
|
2010-11-06 11:59:03 -03:00
|
|
|
std::vector<std::string>::iterator it = fop->seq.filename_list.begin();
|
|
|
|
std::vector<std::string>::iterator end = fop->seq.filename_list.end();
|
|
|
|
for (; it != end; ++it) {
|
|
|
|
fop->filename = it->c_str();
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
/* call the "load" procedure to read the first bitmap */
|
|
|
|
loadres = (*fop->format->load)(fop);
|
|
|
|
if (!loadres) {
|
2010-09-18 23:54:56 -03:00
|
|
|
fop_error(fop, "Error loading frame %d from file \"%s\"\n",
|
2010-11-06 11:59:03 -03:00
|
|
|
frame+1, fop->filename.c_str());
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
/* for the first frame... */
|
|
|
|
if (!old_image) {
|
|
|
|
/* error reading the first frame */
|
|
|
|
if (!loadres || !fop->sprite || !fop->seq.last_cel) {
|
|
|
|
if (fop->seq.image) image_free(fop->seq.image);
|
|
|
|
if (fop->seq.last_cel) cel_free(fop->seq.last_cel);
|
|
|
|
if (fop->sprite) {
|
2009-06-01 02:59:15 +00:00
|
|
|
delete fop->sprite;
|
2008-02-04 02:37:26 +00:00
|
|
|
fop->sprite = NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* read ok */
|
|
|
|
else {
|
|
|
|
/* add the keyframe */
|
|
|
|
SEQUENCE_IMAGE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* for other frames */
|
|
|
|
else {
|
|
|
|
/* all done (or maybe not enough memory) */
|
|
|
|
if (!loadres || !fop->seq.last_cel) {
|
|
|
|
if (fop->seq.image) image_free(fop->seq.image);
|
|
|
|
if (fop->seq.last_cel) cel_free(fop->seq.last_cel);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
/* compare the old frame with the new one */
|
|
|
|
#if USE_LINK /* TODO this should be configurable through a check-box */
|
|
|
|
if (image_count_diff(old_image, fop->seq.image)) {
|
|
|
|
SEQUENCE_IMAGE();
|
|
|
|
}
|
|
|
|
/* we don't need this image */
|
|
|
|
else {
|
|
|
|
image_free(fop->seq.image);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
/* but add a link frame */
|
|
|
|
fop->seq.last_cel->image = image_index;
|
|
|
|
layer_add_frame(fop->seq.layer, fop->seq.last_cel);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
fop->seq.last_image = NULL;
|
|
|
|
fop->seq.last_cel = NULL;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
SEQUENCE_IMAGE();
|
|
|
|
#endif
|
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
frame++;
|
|
|
|
fop->seq.progress_offset += fop->seq.progress_fraction;
|
|
|
|
}
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->filename = *fop->seq.filename_list.begin();
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
// Final setup
|
2008-03-27 14:29:33 +00:00
|
|
|
if (fop->sprite != NULL) {
|
2010-03-30 21:43:18 -03:00
|
|
|
// Configure the layer as the 'Background'
|
2008-03-29 03:43:19 +00:00
|
|
|
if (!fop->seq.has_alpha)
|
2010-09-19 00:17:21 -03:00
|
|
|
fop->seq.layer->configureAsBackground();
|
2008-03-29 03:43:19 +00:00
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
// Set the frames range
|
|
|
|
fop->sprite->setTotalFrames(frame);
|
2008-03-27 14:29:33 +00:00
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
// Set the frames range
|
|
|
|
fop->sprite->setFormatOptions(fop->seq.format_options);
|
2008-03-27 14:29:33 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
2008-03-27 14:29:33 +00:00
|
|
|
/* direct load from one file */
|
2008-02-04 02:37:26 +00:00
|
|
|
else {
|
|
|
|
/* call the "load" procedure */
|
|
|
|
if (!(*fop->format->load)(fop))
|
2010-09-18 23:54:56 -03:00
|
|
|
fop_error(fop, "Error loading sprite from file \"%s\"\n",
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->filename.c_str());
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fop->sprite != NULL) {
|
|
|
|
/* select the last layer */
|
2010-03-30 21:43:18 -03:00
|
|
|
if (fop->sprite->getFolder()->get_layers_count() > 0) {
|
|
|
|
LayerIterator last_layer = --fop->sprite->getFolder()->get_layer_end();
|
|
|
|
fop->sprite->setCurrentLayer(*last_layer);
|
2009-11-17 13:12:26 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
/* set the filename */
|
2010-11-06 11:59:03 -03:00
|
|
|
if (fop->is_sequence())
|
|
|
|
fop->sprite->setFilename(fop->seq.filename_list.begin()->c_str());
|
2008-02-04 02:37:26 +00:00
|
|
|
else
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->sprite->setFilename(fop->filename.c_str());
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2010-04-12 21:41:26 -03:00
|
|
|
// Quantize a palette for RGB images
|
|
|
|
if (fop->sprite->getImgType() == IMAGE_RGB)
|
|
|
|
sprite_quantize(fop->sprite);
|
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
fop->sprite->markAsSaved();
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* save ***********************************************************/
|
|
|
|
else if (fop->type == FileOpSave &&
|
|
|
|
fop->format != NULL &&
|
|
|
|
fop->format->save != NULL) {
|
|
|
|
/* save a sequence */
|
2010-11-06 11:59:03 -03:00
|
|
|
if (fop->is_sequence()) {
|
2010-08-03 23:33:44 -03:00
|
|
|
ASSERT(fop->format->flags & FILE_SUPPORT_SEQUENCES);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
/* create a temporary bitmap */
|
2010-03-30 21:43:18 -03:00
|
|
|
fop->seq.image = image_new(fop->sprite->getImgType(),
|
|
|
|
fop->sprite->getWidth(),
|
|
|
|
fop->sprite->getHeight());
|
2008-02-04 02:37:26 +00:00
|
|
|
if (fop->seq.image != NULL) {
|
2010-03-30 21:43:18 -03:00
|
|
|
int old_frame = fop->sprite->getCurrentFrame();
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
fop->seq.progress_offset = 0.0f;
|
2010-03-30 21:43:18 -03:00
|
|
|
fop->seq.progress_fraction = 1.0f / (float)fop->sprite->getTotalFrames();
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
/* for each frame in the sprite */
|
2010-03-30 21:43:18 -03:00
|
|
|
for (int frame=0; frame < fop->sprite->getTotalFrames(); ++frame) {
|
|
|
|
fop->sprite->setCurrentFrame(frame);
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
/* draw all the sprite in this frame in the image */
|
|
|
|
image_clear(fop->seq.image, 0);
|
2010-03-30 21:43:18 -03:00
|
|
|
fop->sprite->render(fop->seq.image, 0, 0);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
/* setup the palette */
|
2010-03-30 21:43:18 -03:00
|
|
|
fop->sprite->getPalette(fop->sprite->getCurrentFrame())
|
2010-03-28 12:15:32 -03:00
|
|
|
->copyColorsTo(fop->seq.palette);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
/* setup the filename to be used */
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->filename = fop->seq.filename_list[fop->sprite->getCurrentFrame()];
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
/* call the "save" procedure... did it fail? */
|
|
|
|
if (!(*fop->format->save)(fop)) {
|
2010-09-18 23:54:56 -03:00
|
|
|
fop_error(fop, "Error saving frame %d in the file \"%s\"\n",
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->sprite->getCurrentFrame()+1, fop->filename.c_str());
|
2007-09-18 23:57:02 +00:00
|
|
|
break;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
fop->seq.progress_offset += fop->seq.progress_fraction;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->filename = *fop->seq.filename_list.begin();
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
// Destroy the image
|
2008-02-04 02:37:26 +00:00
|
|
|
image_free(fop->seq.image);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
// Restore frame
|
|
|
|
fop->sprite->setCurrentFrame(old_frame);
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-09-18 23:54:56 -03:00
|
|
|
fop_error(fop, "Not enough memory for the temporary bitmap.\n");
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
/* direct save to a file */
|
2007-09-18 23:57:02 +00:00
|
|
|
else {
|
2008-02-04 02:37:26 +00:00
|
|
|
/* call the "save" procedure */
|
|
|
|
if (!(*fop->format->save)(fop))
|
2010-09-18 23:54:56 -03:00
|
|
|
fop_error(fop, "Error saving the sprite in the file \"%s\"\n",
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->filename.c_str());
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
2008-02-10 19:06:03 +00:00
|
|
|
/* progress = 100% */
|
|
|
|
fop_progress(fop, 1.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* After mark the 'fop' as 'done' you must to free it calling @ref fop_free.
|
|
|
|
*/
|
|
|
|
void fop_done(FileOp *fop)
|
|
|
|
{
|
2008-02-04 02:37:26 +00:00
|
|
|
/* finally done */
|
2010-03-10 00:34:50 -02:00
|
|
|
ScopedLock lock(*fop->mutex);
|
|
|
|
fop->done = true;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
2008-02-10 19:06:03 +00:00
|
|
|
void fop_stop(FileOp *fop)
|
|
|
|
{
|
2010-03-10 00:34:50 -02:00
|
|
|
ScopedLock lock(*fop->mutex);
|
|
|
|
if (!fop->done)
|
|
|
|
fop->stop = true;
|
2008-02-10 19:06:03 +00:00
|
|
|
}
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
void fop_free(FileOp *fop)
|
|
|
|
{
|
2008-03-22 18:43:56 +00:00
|
|
|
if (fop->seq.palette != NULL)
|
2010-03-28 12:15:32 -03:00
|
|
|
delete fop->seq.palette;
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2009-05-31 20:15:38 +00:00
|
|
|
if (fop->mutex)
|
2010-03-10 00:34:50 -02:00
|
|
|
delete fop->mutex;
|
2009-05-31 20:15:38 +00:00
|
|
|
|
2010-10-03 13:50:01 -03:00
|
|
|
delete fop;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
2008-03-29 04:24:36 +00:00
|
|
|
void fop_sequence_set_format_options(FileOp *fop, FormatOptions *format_options)
|
2008-03-27 14:29:33 +00:00
|
|
|
{
|
2010-08-03 23:33:44 -03:00
|
|
|
ASSERT(fop->seq.format_options == NULL);
|
2008-03-29 04:24:36 +00:00
|
|
|
fop->seq.format_options = format_options;
|
2008-03-27 14:29:33 +00:00
|
|
|
}
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
void fop_sequence_set_color(FileOp *fop, int index, int r, int g, int b)
|
|
|
|
{
|
2010-03-28 12:15:32 -03:00
|
|
|
fop->seq.palette->setEntry(index, _rgba(r, g, b, 255));
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void fop_sequence_get_color(FileOp *fop, int index, int *r, int *g, int *b)
|
|
|
|
{
|
2010-03-28 12:15:32 -03:00
|
|
|
ase_uint32 c = fop->seq.palette->getEntry(index);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2008-03-22 18:43:56 +00:00
|
|
|
*r = _rgba_getr(c);
|
|
|
|
*g = _rgba_getg(c);
|
|
|
|
*b = _rgba_getb(c);
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Image *fop_sequence_image(FileOp *fop, int imgtype, int w, int h)
|
|
|
|
{
|
2009-11-17 13:12:26 +00:00
|
|
|
Sprite* sprite;
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2010-03-28 12:15:32 -03:00
|
|
|
// Create the image
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!fop->sprite) {
|
2010-03-28 12:15:32 -03:00
|
|
|
sprite = new Sprite(imgtype, w, h, 256);
|
2009-11-17 13:12:26 +00:00
|
|
|
try {
|
|
|
|
LayerImage* layer = new LayerImage(sprite);
|
|
|
|
|
2010-03-28 12:15:32 -03:00
|
|
|
// Add the layer
|
2010-03-30 21:43:18 -03:00
|
|
|
sprite->getFolder()->add_layer(layer);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2010-03-28 12:15:32 -03:00
|
|
|
// Done
|
2009-11-17 13:12:26 +00:00
|
|
|
fop->sprite = sprite;
|
|
|
|
fop->seq.layer = layer;
|
|
|
|
}
|
|
|
|
catch (...) {
|
2009-06-01 02:59:15 +00:00
|
|
|
delete sprite;
|
2009-11-17 13:12:26 +00:00
|
|
|
throw;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
else {
|
2008-02-04 02:37:26 +00:00
|
|
|
sprite = fop->sprite;
|
|
|
|
|
2010-03-30 21:43:18 -03:00
|
|
|
if (sprite->getImgType() != imgtype)
|
2008-02-04 02:37:26 +00:00
|
|
|
return NULL;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2010-03-28 12:15:32 -03:00
|
|
|
// Create a bitmap
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
if (fop->seq.last_cel) {
|
2010-09-18 23:54:56 -03:00
|
|
|
fop_error(fop, "Error: called two times \"fop_sequence_image()\".\n");
|
2008-02-04 02:37:26 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-11-17 13:12:26 +00:00
|
|
|
Image* image = image_new(imgtype, w, h);
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!image) {
|
2010-09-18 23:54:56 -03:00
|
|
|
fop_error(fop, "Not enough memory to allocate a bitmap.\n");
|
2008-02-04 02:37:26 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
fop->seq.image = image;
|
|
|
|
fop->seq.last_cel = cel_new(fop->seq.frame++, 0);
|
|
|
|
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
|
|
|
void fop_error(FileOp *fop, const char *format, ...)
|
|
|
|
{
|
|
|
|
char buf_error[4096];
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
uvszprintf(buf_error, sizeof(buf_error), format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
2010-11-06 11:59:03 -03:00
|
|
|
// Concatenate the new error
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
2010-03-10 00:34:50 -02:00
|
|
|
ScopedLock lock(*fop->mutex);
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->error += buf_error;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void fop_progress(FileOp *fop, float progress)
|
|
|
|
{
|
|
|
|
/* rest(8); */
|
|
|
|
|
2010-03-10 00:34:50 -02:00
|
|
|
ScopedLock lock(*fop->mutex);
|
|
|
|
|
2010-11-06 11:59:03 -03:00
|
|
|
if (fop->is_sequence()) {
|
2010-03-10 00:34:50 -02:00
|
|
|
fop->progress =
|
|
|
|
fop->seq.progress_offset +
|
|
|
|
fop->seq.progress_fraction*progress;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fop->progress = progress;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float fop_get_progress(FileOp *fop)
|
|
|
|
{
|
|
|
|
float progress;
|
|
|
|
{
|
2010-03-10 00:34:50 -02:00
|
|
|
ScopedLock lock(*fop->mutex);
|
2008-02-04 02:37:26 +00:00
|
|
|
progress = fop->progress;
|
|
|
|
}
|
|
|
|
return progress;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true when the file operation finished, this means, when the
|
|
|
|
* 'fop_operate()' routine ends.
|
|
|
|
*/
|
|
|
|
bool fop_is_done(FileOp *fop)
|
|
|
|
{
|
|
|
|
bool done;
|
|
|
|
{
|
2010-03-10 00:34:50 -02:00
|
|
|
ScopedLock lock(*fop->mutex);
|
2008-02-04 02:37:26 +00:00
|
|
|
done = fop->done;
|
|
|
|
}
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool fop_is_stop(FileOp *fop)
|
|
|
|
{
|
|
|
|
bool stop;
|
|
|
|
{
|
2010-03-10 00:34:50 -02:00
|
|
|
ScopedLock lock(*fop->mutex);
|
2008-02-04 02:37:26 +00:00
|
|
|
stop = fop->stop;
|
|
|
|
}
|
|
|
|
return stop;
|
|
|
|
}
|
|
|
|
|
|
|
|
static FileOp *fop_new(FileOpType type)
|
|
|
|
{
|
2010-10-03 13:50:01 -03:00
|
|
|
FileOp *fop = new FileOp;
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
fop->type = type;
|
2008-02-10 19:06:03 +00:00
|
|
|
fop->format = NULL;
|
2008-02-04 02:37:26 +00:00
|
|
|
fop->sprite = NULL;
|
|
|
|
|
2010-03-10 00:34:50 -02:00
|
|
|
fop->mutex = new Mutex();
|
2008-02-04 02:37:26 +00:00
|
|
|
fop->progress = 0.0f;
|
2010-01-30 16:43:13 +00:00
|
|
|
fop->done = false;
|
|
|
|
fop->stop = false;
|
|
|
|
fop->oneframe = false;
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
fop->seq.palette = NULL;
|
|
|
|
fop->seq.image = NULL;
|
|
|
|
fop->seq.progress_offset = 0.0f;
|
|
|
|
fop->seq.progress_fraction = 0.0f;
|
|
|
|
fop->seq.frame = 0;
|
|
|
|
fop->seq.layer = NULL;
|
|
|
|
fop->seq.last_cel = NULL;
|
|
|
|
|
|
|
|
return fop;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void fop_prepare_for_sequence(FileOp *fop)
|
|
|
|
{
|
2010-03-28 12:15:32 -03:00
|
|
|
fop->seq.palette = new Palette(0, 256);
|
2008-03-29 04:24:36 +00:00
|
|
|
fop->seq.format_options = NULL;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2007-12-05 01:30:50 +00:00
|
|
|
static FileFormat *get_fileformat(const char *extension)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
|
|
|
char buf[512], *tok;
|
|
|
|
int c;
|
|
|
|
|
2007-12-05 01:30:50 +00:00
|
|
|
for (c=0; formats[c]; c++) {
|
|
|
|
ustrcpy(buf, formats[c]->exts);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2007-12-05 01:30:50 +00:00
|
|
|
for (tok=ustrtok(buf, ","); tok;
|
|
|
|
tok=ustrtok(NULL, ",")) {
|
|
|
|
if (ustricmp(extension, tok) == 0)
|
|
|
|
return formats[c];
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* splits a file-name like "my_ani0000.pcx" to "my_ani" and ".pcx",
|
|
|
|
returning the number of the center; returns "-1" if the function
|
|
|
|
can't split anything */
|
|
|
|
static int split_filename(const char *filename, char *left, char *right, int *width)
|
|
|
|
{
|
|
|
|
char *ptr, *ext;
|
|
|
|
char buf[16];
|
|
|
|
int chr, ret;
|
|
|
|
|
|
|
|
/* get the extension */
|
2008-01-07 15:10:17 +00:00
|
|
|
ext = get_extension(filename);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
/* with extension */
|
|
|
|
if ((ext) && (*ext)) {
|
|
|
|
/* left side (the filename without the extension and without the '.') */
|
|
|
|
ext--;
|
|
|
|
*ext = 0;
|
2008-01-07 15:10:17 +00:00
|
|
|
ustrcpy(left, filename);
|
2007-09-18 23:57:02 +00:00
|
|
|
*ext = '.';
|
|
|
|
|
|
|
|
/* right side (the extension with the '.') */
|
2008-01-07 15:10:17 +00:00
|
|
|
ustrcpy(right, ext);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
/* without extension (without right side) */
|
|
|
|
else {
|
2008-01-07 15:10:17 +00:00
|
|
|
ustrcpy(left, filename);
|
|
|
|
ustrcpy(right, empty_string);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* remove all trailing numbers in the "left" side, and pass they to "buf" */
|
|
|
|
|
|
|
|
ptr = buf+9;
|
|
|
|
ptr[1] = 0;
|
|
|
|
ret = -1;
|
|
|
|
|
|
|
|
if (width)
|
|
|
|
*width = 0;
|
|
|
|
|
|
|
|
for (;;) {
|
2008-01-07 15:10:17 +00:00
|
|
|
chr = ugetat(left, -1);
|
2007-09-18 23:57:02 +00:00
|
|
|
if ((chr >= '0') && (chr <= '9')) {
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
if (ptr >= buf) {
|
|
|
|
*(ptr--) = chr;
|
|
|
|
|
|
|
|
if (width)
|
|
|
|
(*width)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
uremove(left, -1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert the "buf" to integer and return it */
|
|
|
|
if (ret == 0) {
|
|
|
|
while (ptr >= buf)
|
|
|
|
*(ptr--) = '0';
|
|
|
|
|
2007-12-05 01:30:50 +00:00
|
|
|
ret = ustrtol(buf, NULL, 10);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2008-02-10 19:06:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads a WORD (16 bits) using in little-endian byte ordering.
|
|
|
|
*/
|
|
|
|
int fgetw(FILE *file)
|
|
|
|
{
|
|
|
|
int b1, b2;
|
|
|
|
|
|
|
|
b1 = fgetc(file);
|
|
|
|
if (b1 == EOF)
|
|
|
|
return EOF;
|
|
|
|
|
|
|
|
b2 = fgetc(file);
|
|
|
|
if (b2 == EOF)
|
|
|
|
return EOF;
|
|
|
|
|
|
|
|
/* little endian */
|
|
|
|
return ((b2 << 8) | b1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads a DWORD (32 bits) using in little-endian byte ordering.
|
|
|
|
*/
|
|
|
|
long fgetl(FILE *file)
|
|
|
|
{
|
|
|
|
int b1, b2, b3, b4;
|
|
|
|
|
|
|
|
b1 = fgetc(file);
|
|
|
|
if (b1 == EOF)
|
|
|
|
return EOF;
|
|
|
|
|
|
|
|
b2 = fgetc(file);
|
|
|
|
if (b2 == EOF)
|
|
|
|
return EOF;
|
|
|
|
|
|
|
|
b3 = fgetc(file);
|
|
|
|
if (b3 == EOF)
|
|
|
|
return EOF;
|
|
|
|
|
|
|
|
b4 = fgetc(file);
|
|
|
|
if (b4 == EOF)
|
|
|
|
return EOF;
|
|
|
|
|
|
|
|
/* little endian */
|
|
|
|
return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Writes a word using in little-endian byte ordering.
|
|
|
|
*
|
|
|
|
* @return 0 in success or -1 in error
|
|
|
|
*/
|
|
|
|
int fputw(int w, FILE *file)
|
|
|
|
{
|
|
|
|
int b1, b2;
|
|
|
|
|
|
|
|
/* little endian */
|
|
|
|
b2 = (w & 0xFF00) >> 8;
|
|
|
|
b1 = w & 0x00FF;
|
|
|
|
|
|
|
|
if (fputc(b1, file) == b1)
|
|
|
|
if (fputc(b2, file) == b2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Writes DWORD a using in little-endian byte ordering.
|
|
|
|
*
|
|
|
|
* @return 0 in success or -1 in error
|
|
|
|
*/
|
|
|
|
int fputl(long l, FILE *file)
|
|
|
|
{
|
|
|
|
int b1, b2, b3, b4;
|
|
|
|
|
|
|
|
/* little endian */
|
|
|
|
b4 = (int)((l & 0xFF000000L) >> 24);
|
|
|
|
b3 = (int)((l & 0x00FF0000L) >> 16);
|
|
|
|
b2 = (int)((l & 0x0000FF00L) >> 8);
|
|
|
|
b1 = (int)l & 0x00FF;
|
|
|
|
|
|
|
|
if (fputc(b1, file) == b1)
|
|
|
|
if (fputc(b2, file) == b2)
|
|
|
|
if (fputc(b3, file) == b3)
|
|
|
|
if (fputc(b4, file) == b4)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|