2013-08-08 21:01:20 -03:00
|
|
|
/* Aseprite
|
2013-01-27 12:13:13 -03:00
|
|
|
* Copyright (C) 2001-2013 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
|
|
|
|
*/
|
|
|
|
|
2013-08-05 21:20:19 -03:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2007-09-18 23:57:02 +00:00
|
|
|
#include "config.h"
|
2013-08-05 21:20:19 -03:00
|
|
|
#endif
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2013-08-05 21:20:19 -03:00
|
|
|
#include "app/app.h"
|
|
|
|
#include "app/ui/status_bar.h"
|
2010-09-23 23:33:39 -03:00
|
|
|
#include "base/mutex.h"
|
|
|
|
#include "base/scoped_lock.h"
|
2011-01-18 20:35:44 -03:00
|
|
|
#include "base/shared_ptr.h"
|
2011-01-23 19:19:18 -03:00
|
|
|
#include "base/string.h"
|
2013-08-05 21:20:19 -03:00
|
|
|
#include "app/console.h"
|
|
|
|
#include "app/document.h"
|
|
|
|
#include "app/file/file.h"
|
|
|
|
#include "app/file/file_format.h"
|
|
|
|
#include "app/file/file_formats_manager.h"
|
|
|
|
#include "app/file/format_options.h"
|
|
|
|
#include "app/modules/gui.h"
|
|
|
|
#include "app/modules/palettes.h"
|
2010-12-26 10:57:03 -03:00
|
|
|
#include "raster/quantization.h"
|
2011-01-23 19:19:18 -03:00
|
|
|
#include "raster/raster.h"
|
2012-06-17 22:49:58 -03:00
|
|
|
#include "ui/alert.h"
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
#include <allegro.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2013-08-05 21:20:19 -03:00
|
|
|
namespace app {
|
|
|
|
|
|
|
|
using namespace base;
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
static FileOp* fop_new(FileOpType type);
|
|
|
|
static void fop_prepare_for_sequence(FileOp* fop);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
static FileFormat* get_fileformat(const char* extension);
|
|
|
|
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
|
|
|
{
|
2011-01-16 17:27:18 -03:00
|
|
|
FileFormatsList::iterator it = FileFormatsManager::instance().begin();
|
|
|
|
FileFormatsList::iterator end = FileFormatsManager::instance().end();
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
/* 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 */
|
2011-01-16 17:27:18 -03:00
|
|
|
for (; it != end; ++it) {
|
|
|
|
if ((*it)->support(FILE_SUPPORT_LOAD)) {
|
|
|
|
if (ustrcmp(buf, empty_string) != 0)
|
2012-01-05 19:45:03 -03:00
|
|
|
ustrncat(buf, ",", size);
|
2011-01-16 17:27:18 -03:00
|
|
|
ustrncat(buf, (*it)->extensions(), 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
|
|
|
{
|
2011-01-16 17:27:18 -03:00
|
|
|
FileFormatsList::iterator it = FileFormatsManager::instance().begin();
|
|
|
|
FileFormatsList::iterator end = FileFormatsManager::instance().end();
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
/* 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 */
|
2011-01-16 17:27:18 -03:00
|
|
|
for (; it != end; ++it) {
|
|
|
|
if ((*it)->support(FILE_SUPPORT_SAVE)) {
|
|
|
|
if (ustrcmp(buf, empty_string) != 0)
|
2012-01-05 19:45:03 -03:00
|
|
|
ustrncat(buf, ",", size);
|
2011-01-16 17:27:18 -03:00
|
|
|
ustrncat(buf, (*it)->extensions(), size);
|
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
Document* load_document(const char* filename)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2011-03-22 21:11:25 -03:00
|
|
|
Document* document;
|
|
|
|
|
2008-02-10 19:06:03 +00:00
|
|
|
/* TODO add a option to configure what to do with the sequence */
|
2011-03-22 21:11:25 -03:00
|
|
|
FileOp *fop = fop_to_load_document(filename, FILE_LOAD_SEQUENCE_NONE);
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!fop)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* operate in this same thread */
|
2012-07-06 01:06:00 -03:00
|
|
|
fop_operate(fop, NULL);
|
2008-02-10 19:06:03 +00:00
|
|
|
fop_done(fop);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2011-06-25 17:12:08 -03:00
|
|
|
fop_post_load(fop);
|
|
|
|
|
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
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
document = fop->document;
|
2008-02-04 02:37:26 +00:00
|
|
|
fop_free(fop);
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
return document;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
int save_document(Document* document)
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
|
|
|
int ret;
|
2011-03-22 21:11:25 -03:00
|
|
|
FileOp* fop = fop_to_save_document(document);
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!fop)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* operate in this same thread */
|
2012-07-06 01:06:00 -03:00
|
|
|
fop_operate(fop, NULL);
|
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;
|
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
FileOp* fop_to_load_document(const char* filename, int flags)
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
|
|
|
FileOp *fop;
|
|
|
|
|
|
|
|
fop = fop_new(FileOpLoad);
|
|
|
|
if (!fop)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* get the extension of the filename (in lower case) */
|
2011-01-23 19:19:18 -03:00
|
|
|
std::string extension = base::string_to_lower(get_extension(filename));
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2011-01-23 19:19:18 -03:00
|
|
|
PRINTF("Loading file \"%s\" (%s)\n", filename, extension.c_str());
|
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 */
|
2011-01-23 19:19:18 -03:00
|
|
|
fop->format = get_fileformat(extension.c_str());
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!fop->format ||
|
2011-01-16 17:27:18 -03:00
|
|
|
!fop->format->support(FILE_SUPPORT_LOAD)) {
|
2012-01-06 01:12:57 -03:00
|
|
|
fop_error(fop, "ASEPRITE can't load \"%s\" files\n", extension.c_str());
|
2008-02-04 02:37:26 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
/* use the "sequence" interface */
|
2011-01-16 17:27:18 -03:00
|
|
|
if (fop->format->support(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
|
2012-01-05 19:45:03 -03:00
|
|
|
sequence... */
|
2008-02-10 19:06:03 +00:00
|
|
|
|
|
|
|
/* check is this could be a sequence */
|
|
|
|
start_from = split_filename(filename, left, right, &width);
|
|
|
|
if (start_from >= 0) {
|
2012-01-05 19:45:03 -03:00
|
|
|
/* 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 */
|
|
|
|
fop->seq.filename_list.push_back(buf);
|
|
|
|
}
|
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) &&
|
2012-01-05 19:45:03 -03:00
|
|
|
App::instance()->isGui()) {
|
|
|
|
/* really want load all files? */
|
|
|
|
if ((fop->seq.filename_list.size() > 1) &&
|
2012-06-17 22:02:54 -03:00
|
|
|
(ui::Alert::show("Notice"
|
|
|
|
"<<Possible animation with:"
|
|
|
|
"<<%s"
|
|
|
|
"<<Load the sequence of bitmaps?"
|
|
|
|
"||&Agree||&Skip",
|
|
|
|
get_filename(filename)) != 1)) {
|
2012-01-05 19:45:03 -03:00
|
|
|
|
|
|
|
/* if the user replies "Skip", we need just one file name (the
|
|
|
|
first one) */
|
|
|
|
if (fop->seq.filename_list.size() > 1) {
|
|
|
|
fop->seq.filename_list.erase(fop->seq.filename_list.begin()+1,
|
|
|
|
fop->seq.filename_list.end());
|
|
|
|
}
|
|
|
|
}
|
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:;
|
|
|
|
return fop;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
FileOp* fop_to_save_document(Document* document)
|
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;
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
/* document to save */
|
|
|
|
fop->document = document;
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
/* get the extension of the filename (in lower case) */
|
2011-03-22 21:11:25 -03:00
|
|
|
ustrcpy(extension, get_extension(fop->document->getFilename()));
|
2007-09-18 23:57:02 +00:00
|
|
|
ustrlwr(extension);
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
PRINTF("Saving document \"%s\" (%s)\n", fop->document->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 ||
|
2011-01-16 17:27:18 -03:00
|
|
|
!fop->format->support(FILE_SUPPORT_SAVE)) {
|
2012-01-06 01:12:57 -03:00
|
|
|
fop_error(fop, "ASEPRITE 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 */
|
2012-02-12 23:21:06 -03:00
|
|
|
switch (fop->document->getSprite()->getPixelFormat()) {
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
case IMAGE_RGB:
|
2011-01-16 17:27:18 -03:00
|
|
|
if (!(fop->format->support(FILE_SUPPORT_RGB))) {
|
2012-01-05 19:45:03 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- %s", "RGB format");
|
|
|
|
fatal = true;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2011-01-16 17:27:18 -03:00
|
|
|
if (!(fop->format->support(FILE_SUPPORT_RGBA)) &&
|
2012-01-05 19:45:03 -03:00
|
|
|
fop->document->getSprite()->needAlpha()) {
|
|
|
|
usprintf(buf+ustrlen(buf), "<<- %s", "Alpha channel");
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IMAGE_GRAYSCALE:
|
2011-01-16 17:27:18 -03:00
|
|
|
if (!(fop->format->support(FILE_SUPPORT_GRAY))) {
|
2012-01-05 19:45:03 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- Grayscale format");
|
|
|
|
fatal = true;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2011-01-16 17:27:18 -03:00
|
|
|
if (!(fop->format->support(FILE_SUPPORT_GRAYA)) &&
|
2012-01-05 19:45:03 -03:00
|
|
|
fop->document->getSprite()->needAlpha()) {
|
|
|
|
usprintf(buf+ustrlen(buf), "<<- Alpha channel");
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IMAGE_INDEXED:
|
2011-01-16 17:27:18 -03:00
|
|
|
if (!(fop->format->support(FILE_SUPPORT_INDEXED))) {
|
2012-01-05 19:45:03 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- Indexed format");
|
|
|
|
fatal = true;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-11-17 13:12:26 +00:00
|
|
|
// check frames support
|
2011-03-22 21:11:25 -03:00
|
|
|
if (fop->document->getSprite()->getTotalFrames() > 1) {
|
2011-01-16 17:27:18 -03:00
|
|
|
if (!fop->format->support(FILE_SUPPORT_FRAMES) &&
|
2012-01-05 19:45:03 -03:00
|
|
|
!fop->format->support(FILE_SUPPORT_SEQUENCES)) {
|
2010-09-18 23:54:56 -03:00
|
|
|
usprintf(buf+ustrlen(buf), "<<- Frames");
|
2011-01-16 17:27:18 -03:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2009-11-17 13:12:26 +00:00
|
|
|
// layers support
|
2013-01-11 12:43:25 -03:00
|
|
|
if (fop->document->getSprite()->getFolder()->getLayersCount() > 1) {
|
2011-01-16 17:27:18 -03:00
|
|
|
if (!(fop->format->support(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.
|
2011-03-22 21:11:25 -03:00
|
|
|
if (fop->document->getSprite()->getPalettes().size() > 1) {
|
2011-01-16 17:27:18 -03:00
|
|
|
if (!fop->format->support(FILE_SUPPORT_PALETTES) &&
|
2012-01-05 19:45:03 -03:00
|
|
|
!fop->format->support(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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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)
|
2012-06-17 22:02:54 -03:00
|
|
|
ret = ui::Alert::show("Error<<File format \"%s\" doesn't support:%s"
|
|
|
|
"||&Close",
|
|
|
|
fop->format->name(), buf);
|
2007-09-18 23:57:02 +00:00
|
|
|
else
|
2012-06-17 22:02:54 -03:00
|
|
|
ret = ui::Alert::show("Warning<<File format \"%s\" doesn't support:%s"
|
|
|
|
"<<Do you want continue?"
|
|
|
|
"||&Yes||&No",
|
|
|
|
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
|
2012-01-05 19:45:03 -03:00
|
|
|
the operation */
|
2008-02-04 02:37:26 +00:00
|
|
|
if ((fatal) || (ret != 1)) {
|
2012-01-05 19:45:03 -03:00
|
|
|
fop_free(fop);
|
|
|
|
return NULL;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* no interactive & fatal error? */
|
|
|
|
else if (fatal) {
|
|
|
|
fop_error(fop, buf);
|
|
|
|
return fop;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-16 17:27:18 -03:00
|
|
|
// Use the "sequence" interface.
|
|
|
|
if (fop->format->support(FILE_SUPPORT_SEQUENCES)) {
|
2008-02-04 02:37:26 +00:00
|
|
|
fop_prepare_for_sequence(fop);
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// To save one frame
|
|
|
|
if (fop->document->getSprite()->getTotalFrames() == 1) {
|
|
|
|
fop->seq.filename_list.push_back(fop->document->getFilename());
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
2011-03-22 21:11:25 -03:00
|
|
|
// To save more frames
|
2008-02-04 02:37:26 +00:00
|
|
|
else {
|
|
|
|
char buf[256], left[256], right[256];
|
2012-07-08 21:09:09 -03:00
|
|
|
int width, start_from;
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
start_from = split_filename(fop->document->getFilename(), left, right, &width);
|
2008-02-04 02:37:26 +00:00
|
|
|
if (start_from < 0) {
|
2012-01-05 19:45:03 -03:00
|
|
|
start_from = 0;
|
|
|
|
width =
|
|
|
|
(fop->document->getSprite()->getTotalFrames() < 10)? 1:
|
|
|
|
(fop->document->getSprite()->getTotalFrames() < 100)? 2:
|
|
|
|
(fop->document->getSprite()->getTotalFrames() < 1000)? 3: 4;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2012-07-08 21:09:09 -03:00
|
|
|
for (FrameNumber frame(0); frame<fop->document->getSprite()->getTotalFrames(); ++frame) {
|
2012-01-05 19:45:03 -03:00
|
|
|
/* get the name for this frame */
|
|
|
|
usprintf(buf, "%s%0*d%s", left, width, start_from+frame, right);
|
|
|
|
fop->seq.filename_list.push_back(buf);
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2011-03-22 21:11:25 -03:00
|
|
|
fop->filename = fop->document->getFilename();
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2011-01-18 19:30:42 -03:00
|
|
|
// Configure output format?
|
2011-01-16 17:27:18 -03:00
|
|
|
if (fop->format->support(FILE_SUPPORT_GET_FORMAT_OPTIONS)) {
|
2011-03-22 21:11:25 -03:00
|
|
|
SharedPtr<FormatOptions> format_options = fop->format->getFormatOptions(fop);
|
2008-03-29 03:43:19 +00:00
|
|
|
|
2011-01-16 17:27:18 -03: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;
|
2011-03-22 21:11:25 -03:00
|
|
|
fop->document->setFormatOptions(format_options);
|
2008-03-29 03:43:19 +00:00
|
|
|
}
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
return fop;
|
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// Executes the file operation: loads or saves the sprite.
|
|
|
|
//
|
|
|
|
// It can be called from a different thread of the one used
|
|
|
|
// by fop_to_load_sprite() or fop_to_save_sprite().
|
|
|
|
//
|
|
|
|
// After this function you must to mark the "fop" as "done" calling
|
|
|
|
// fop_done() function.
|
2012-07-06 01:06:00 -03:00
|
|
|
void fop_operate(FileOp *fop, IFileOpProgress* progress)
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
2010-08-03 23:33:44 -03:00
|
|
|
ASSERT(fop != NULL);
|
|
|
|
ASSERT(!fop_is_done(fop));
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2012-07-06 01:06:00 -03:00
|
|
|
fop->progressInterface = progress;
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// Load //////////////////////////////////////////////////////////////////////
|
2008-02-04 02:37:26 +00:00
|
|
|
if (fop->type == FileOpLoad &&
|
|
|
|
fop->format != NULL &&
|
2011-01-16 17:27:18 -03:00
|
|
|
fop->format->support(FILE_SUPPORT_LOAD)) {
|
2011-03-22 21:11:25 -03:00
|
|
|
// Load a sequence
|
2010-11-06 11:59:03 -03:00
|
|
|
if (fop->is_sequence()) {
|
2012-07-08 21:09:09 -03:00
|
|
|
int image_index = 0;
|
2011-03-22 21:11:25 -03:00
|
|
|
Image* old_image;
|
2008-02-04 02:37:26 +00:00
|
|
|
bool loadres;
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// Default palette
|
2010-03-28 12:15:32 -03:00
|
|
|
fop->seq.palette->makeBlack();
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// TODO set_palette for each frame???
|
2012-01-05 19:45:03 -03:00
|
|
|
#define SEQUENCE_IMAGE() \
|
|
|
|
do { \
|
|
|
|
image_index = fop->document \
|
|
|
|
->getSprite() \
|
|
|
|
->getStock()->addImage(fop->seq.image); \
|
|
|
|
\
|
|
|
|
fop->seq.last_cel->setImage(image_index); \
|
|
|
|
fop->seq.layer->addCel(fop->seq.last_cel); \
|
|
|
|
\
|
|
|
|
if (fop->document->getSprite()->getPalette(frame) \
|
|
|
|
->countDiff(fop->seq.palette, NULL, NULL) > 0) { \
|
|
|
|
fop->seq.palette->setFrame(frame); \
|
|
|
|
fop->document->getSprite()->setPalette(fop->seq.palette, true); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
old_image = fop->seq.image; \
|
|
|
|
fop->seq.image = NULL; \
|
|
|
|
fop->seq.last_cel = NULL; \
|
2008-02-04 02:37:26 +00:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/* load the sequence */
|
2012-07-08 21:09:09 -03:00
|
|
|
FrameNumber frames(fop->seq.filename_list.size());
|
|
|
|
FrameNumber frame(0);
|
2008-02-04 02:37:26 +00:00
|
|
|
old_image = NULL;
|
2012-01-05 19:45:03 -03:00
|
|
|
|
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;
|
2012-07-06 01:06:00 -03:00
|
|
|
fop->seq.progress_fraction = 1.0f / (double)frames;
|
2008-02-04 02:37:26 +00:00
|
|
|
|
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) {
|
2012-01-05 19:45:03 -03:00
|
|
|
fop->filename = it->c_str();
|
|
|
|
|
|
|
|
// Call the "load" procedure to read the first bitmap.
|
|
|
|
loadres = fop->format->load(fop);
|
|
|
|
if (!loadres) {
|
|
|
|
fop_error(fop, "Error loading frame %d from file \"%s\"\n",
|
|
|
|
frame+1, fop->filename.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
// For the first frame...
|
|
|
|
if (!old_image) {
|
|
|
|
// Error reading the first frame
|
|
|
|
if (!loadres || !fop->document || !fop->seq.last_cel) {
|
2013-03-30 19:53:52 -03:00
|
|
|
delete fop->seq.image;
|
|
|
|
delete fop->seq.last_cel;
|
|
|
|
delete fop->document;
|
|
|
|
fop->document = NULL;
|
2012-01-05 19:45:03 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Read ok
|
|
|
|
else {
|
2013-03-30 19:53:52 -03:00
|
|
|
// Add the keyframe
|
2012-01-05 19:45:03 -03:00
|
|
|
SEQUENCE_IMAGE();
|
|
|
|
}
|
|
|
|
}
|
2013-03-30 19:53:52 -03:00
|
|
|
// For other frames
|
2012-01-05 19:45:03 -03:00
|
|
|
else {
|
2013-03-30 19:53:52 -03:00
|
|
|
// All done (or maybe not enough memory)
|
2012-01-05 19:45:03 -03:00
|
|
|
if (!loadres || !fop->seq.last_cel) {
|
2013-03-30 19:53:52 -03:00
|
|
|
delete fop->seq.image;
|
|
|
|
delete fop->seq.last_cel;
|
2012-01-05 19:45:03 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-03-30 19:53:52 -03:00
|
|
|
// Compare the old frame with the new one
|
|
|
|
#if USE_LINK // TODO this should be configurable through a check-box
|
2012-01-05 19:45:03 -03:00
|
|
|
if (image_count_diff(old_image, fop->seq.image)) {
|
|
|
|
SEQUENCE_IMAGE();
|
|
|
|
}
|
2013-03-30 19:53:52 -03:00
|
|
|
// We don't need this image
|
2012-01-05 19:45:03 -03:00
|
|
|
else {
|
2013-03-30 19:53:52 -03:00
|
|
|
delete fop->seq.image;
|
2012-01-05 19:45:03 -03:00
|
|
|
|
2013-03-30 19:53:52 -03:00
|
|
|
// But add a link frame
|
2012-01-05 19:45:03 -03:00
|
|
|
fop->seq.last_cel->image = image_index;
|
|
|
|
layer_add_frame(fop->seq.layer, fop->seq.last_cel);
|
|
|
|
|
|
|
|
fop->seq.last_image = NULL;
|
|
|
|
fop->seq.last_cel = NULL;
|
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
#else
|
2012-01-05 19:45:03 -03:00
|
|
|
SEQUENCE_IMAGE();
|
2008-02-04 02:37:26 +00:00
|
|
|
#endif
|
2012-01-05 19:45:03 -03:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2012-07-08 21:09:09 -03:00
|
|
|
++frame;
|
2012-01-05 19:45:03 -03:00
|
|
|
fop->seq.progress_offset += fop->seq.progress_fraction;
|
2008-02-04 02:37:26 +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
|
|
|
// Final setup
|
2011-03-22 21:11:25 -03:00
|
|
|
if (fop->document != NULL) {
|
2012-01-05 19:45:03 -03:00
|
|
|
// Configure the layer as the 'Background'
|
|
|
|
if (!fop->seq.has_alpha)
|
|
|
|
fop->seq.layer->configureAsBackground();
|
2008-03-29 03:43:19 +00:00
|
|
|
|
2012-01-05 19:45:03 -03:00
|
|
|
// Set the frames range
|
|
|
|
fop->document->getSprite()->setTotalFrames(frame);
|
2008-03-27 14:29:33 +00:00
|
|
|
|
2012-01-05 19:45:03 -03:00
|
|
|
// Sets special options from the specific format (e.g. BMP
|
|
|
|
// file can contain the number of bits per pixel).
|
|
|
|
fop->document->setFormatOptions(fop->seq.format_options);
|
2008-03-27 14:29:33 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
2011-03-22 21:11:25 -03:00
|
|
|
// Direct load from one file.
|
2008-02-04 02:37:26 +00:00
|
|
|
else {
|
2011-03-22 21:11:25 -03:00
|
|
|
// Call the "load" procedure.
|
2011-01-16 17:27:18 -03:00
|
|
|
if (!fop->format->load(fop))
|
2012-01-05 19:45:03 -03:00
|
|
|
fop_error(fop, "Error loading sprite from file \"%s\"\n",
|
|
|
|
fop->filename.c_str());
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
}
|
2011-03-22 21:11:25 -03:00
|
|
|
// Save //////////////////////////////////////////////////////////////////////
|
2008-02-04 02:37:26 +00:00
|
|
|
else if (fop->type == FileOpSave &&
|
2012-01-05 19:45:03 -03:00
|
|
|
fop->format != NULL &&
|
|
|
|
fop->format->support(FILE_SUPPORT_SAVE)) {
|
2011-03-22 21:11:25 -03:00
|
|
|
// Save a sequence
|
2010-11-06 11:59:03 -03:00
|
|
|
if (fop->is_sequence()) {
|
2011-01-16 17:27:18 -03:00
|
|
|
ASSERT(fop->format->support(FILE_SUPPORT_SEQUENCES));
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
Sprite* sprite = fop->document->getSprite();
|
|
|
|
|
|
|
|
// Create a temporary bitmap
|
2012-02-12 23:21:06 -03:00
|
|
|
fop->seq.image = Image::create(sprite->getPixelFormat(),
|
2012-02-11 22:57:21 -03:00
|
|
|
sprite->getWidth(),
|
|
|
|
sprite->getHeight());
|
2008-02-04 02:37:26 +00:00
|
|
|
if (fop->seq.image != NULL) {
|
2012-01-05 19:45:03 -03:00
|
|
|
fop->seq.progress_offset = 0.0f;
|
2012-07-06 01:06:00 -03:00
|
|
|
fop->seq.progress_fraction = 1.0f / (double)sprite->getTotalFrames();
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2012-01-05 19:45:03 -03:00
|
|
|
// For each frame in the sprite.
|
2012-07-08 21:09:09 -03:00
|
|
|
for (FrameNumber frame(0); frame < sprite->getTotalFrames(); ++frame) {
|
2012-01-05 19:45:03 -03:00
|
|
|
// Draw the "frame" in "fop->seq.image"
|
2013-03-11 20:29:45 -03:00
|
|
|
sprite->render(fop->seq.image, 0, 0, frame);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2012-01-05 19:45:03 -03:00
|
|
|
// Setup the palette.
|
2013-03-11 20:29:45 -03:00
|
|
|
sprite->getPalette(frame)->copyColorsTo(fop->seq.palette);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2012-01-05 19:45:03 -03:00
|
|
|
// Setup the filename to be used.
|
2013-03-11 20:29:45 -03:00
|
|
|
fop->filename = fop->seq.filename_list[frame];
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2012-01-05 19:45:03 -03:00
|
|
|
// Call the "save" procedure... did it fail?
|
|
|
|
if (!fop->format->save(fop)) {
|
|
|
|
fop_error(fop, "Error saving frame %d in the file \"%s\"\n",
|
2013-03-11 20:29:45 -03:00
|
|
|
frame+1, fop->filename.c_str());
|
2012-01-05 19:45:03 -03:00
|
|
|
break;
|
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2012-01-05 19:45:03 -03:00
|
|
|
fop->seq.progress_offset += fop->seq.progress_fraction;
|
|
|
|
}
|
|
|
|
fop->filename = *fop->seq.filename_list.begin();
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2012-01-05 19:45:03 -03:00
|
|
|
// Destroy the image
|
2013-03-30 19:53:52 -03:00
|
|
|
delete fop->seq.image;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-01-05 19:45:03 -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
|
|
|
}
|
2011-03-22 21:11:25 -03:00
|
|
|
// Direct save to a file.
|
2007-09-18 23:57:02 +00:00
|
|
|
else {
|
2011-03-22 21:11:25 -03:00
|
|
|
// Call the "save" procedure.
|
2011-01-16 17:27:18 -03:00
|
|
|
if (!fop->format->save(fop))
|
2012-01-05 19:45:03 -03:00
|
|
|
fop_error(fop, "Error saving the sprite in the file \"%s\"\n",
|
|
|
|
fop->filename.c_str());
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// Progress = 100%
|
2008-02-10 19:06:03 +00:00
|
|
|
fop_progress(fop, 1.0f);
|
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// After mark the 'fop' as 'done' you must to free it calling fop_free().
|
2008-02-10 19:06:03 +00:00
|
|
|
void fop_done(FileOp *fop)
|
|
|
|
{
|
2011-03-22 21:11:25 -03:00
|
|
|
// Finally done.
|
2013-08-05 21:20:19 -03:00
|
|
|
scoped_lock lock(*fop->mutex);
|
2010-03-10 00:34:50 -02:00
|
|
|
fop->done = true;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
2008-02-10 19:06:03 +00:00
|
|
|
void fop_stop(FileOp *fop)
|
|
|
|
{
|
2013-08-05 21:20:19 -03:00
|
|
|
scoped_lock lock(*fop->mutex);
|
2010-03-10 00:34:50 -02:00
|
|
|
if (!fop->done)
|
|
|
|
fop->stop = true;
|
2008-02-10 19:06:03 +00:00
|
|
|
}
|
|
|
|
|
2012-07-06 01:06:00 -03:00
|
|
|
FileOp::~FileOp()
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
2012-07-06 01:06:00 -03:00
|
|
|
if (this->format)
|
|
|
|
this->format->destroyData(this);
|
2011-06-25 17:12:08 -03:00
|
|
|
|
2012-07-06 01:06:00 -03:00
|
|
|
delete this->seq.palette;
|
|
|
|
delete this->mutex;
|
|
|
|
}
|
2009-05-31 20:15:38 +00:00
|
|
|
|
2012-07-06 01:06:00 -03:00
|
|
|
void fop_free(FileOp *fop)
|
|
|
|
{
|
2010-10-03 13:50:01 -03:00
|
|
|
delete fop;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
2011-06-25 17:12:08 -03:00
|
|
|
void fop_post_load(FileOp* fop)
|
|
|
|
{
|
|
|
|
if (fop->document == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Set the filename.
|
|
|
|
if (fop->is_sequence())
|
|
|
|
fop->document->setFilename(fop->seq.filename_list.begin()->c_str());
|
|
|
|
else
|
|
|
|
fop->document->setFilename(fop->filename.c_str());
|
|
|
|
|
|
|
|
bool result = fop->format->postLoad(fop);
|
|
|
|
if (!result) {
|
|
|
|
// Destroy the document
|
|
|
|
delete fop->document;
|
|
|
|
fop->document = NULL;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fop->document->getSprite() != NULL) {
|
|
|
|
// Creates a suitable palette for RGB images
|
2012-02-12 23:21:06 -03:00
|
|
|
if (fop->document->getSprite()->getPixelFormat() == IMAGE_RGB &&
|
2012-01-05 19:45:03 -03:00
|
|
|
fop->document->getSprite()->getPalettes().size() <= 1 &&
|
2012-07-08 21:09:09 -03:00
|
|
|
fop->document->getSprite()->getPalette(FrameNumber(0))->isBlack()) {
|
2013-03-11 20:29:45 -03:00
|
|
|
SharedPtr<Palette> palette
|
|
|
|
(quantization::create_palette_from_rgb(fop->document->getSprite(),
|
|
|
|
FrameNumber(0)));
|
2011-06-25 17:12:08 -03:00
|
|
|
|
|
|
|
fop->document->getSprite()->resetPalettes();
|
|
|
|
fop->document->getSprite()->setPalette(palette, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fop->document->markAsSaved();
|
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
void fop_sequence_set_format_options(FileOp* fop, const SharedPtr<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)
|
|
|
|
{
|
2011-03-24 18:36:19 -03:00
|
|
|
uint32_t 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
|
|
|
}
|
|
|
|
|
2012-02-12 23:21:06 -03:00
|
|
|
Image* fop_sequence_image(FileOp* fop, PixelFormat pixelFormat, int w, int h)
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
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
|
2011-03-22 21:11:25 -03:00
|
|
|
if (!fop->document) {
|
2012-02-12 23:21:06 -03:00
|
|
|
sprite = new Sprite(pixelFormat, 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
|
2012-08-18 22:21:42 -03:00
|
|
|
sprite->getFolder()->addLayer(layer);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2010-03-28 12:15:32 -03:00
|
|
|
// Done
|
2011-03-22 21:11:25 -03:00
|
|
|
fop->document = new Document(sprite);
|
2009-11-17 13:12:26 +00:00
|
|
|
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 {
|
2011-03-22 21:11:25 -03:00
|
|
|
sprite = fop->document->getSprite();
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2012-02-12 23:21:06 -03:00
|
|
|
if (sprite->getPixelFormat() != pixelFormat)
|
2008-02-04 02:37:26 +00:00
|
|
|
return NULL;
|
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;
|
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// Create a bitmap
|
2012-02-12 23:21:06 -03:00
|
|
|
Image* image = Image::create(pixelFormat, w, h);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
fop->seq.image = image;
|
2011-03-28 00:24:27 -03:00
|
|
|
fop->seq.last_cel = new Cel(fop->seq.frame++, 0);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
|
|
|
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
|
|
|
{
|
2013-08-05 21:20:19 -03:00
|
|
|
scoped_lock lock(*fop->mutex);
|
2010-11-06 11:59:03 -03:00
|
|
|
fop->error += buf_error;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-06 01:06:00 -03:00
|
|
|
void fop_progress(FileOp *fop, double progress)
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
2013-08-05 21:20:19 -03:00
|
|
|
scoped_lock lock(*fop->mutex);
|
2010-03-10 00:34:50 -02:00
|
|
|
|
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
|
|
|
}
|
2012-07-06 01:06:00 -03:00
|
|
|
|
|
|
|
if (fop->progressInterface)
|
|
|
|
fop->progressInterface->ackFileOpProgress(progress);
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
2012-07-06 01:06:00 -03:00
|
|
|
double fop_get_progress(FileOp *fop)
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
2012-07-06 01:06:00 -03:00
|
|
|
double progress;
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
2013-08-05 21:20:19 -03:00
|
|
|
scoped_lock lock(*fop->mutex);
|
2008-02-04 02:37:26 +00:00
|
|
|
progress = fop->progress;
|
|
|
|
}
|
|
|
|
return progress;
|
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// Returns true when the file operation finished, this means, when the
|
|
|
|
// fop_operate() routine ends.
|
2008-02-04 02:37:26 +00:00
|
|
|
bool fop_is_done(FileOp *fop)
|
|
|
|
{
|
|
|
|
bool done;
|
|
|
|
{
|
2013-08-05 21:20:19 -03:00
|
|
|
scoped_lock lock(*fop->mutex);
|
2008-02-04 02:37:26 +00:00
|
|
|
done = fop->done;
|
|
|
|
}
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool fop_is_stop(FileOp *fop)
|
|
|
|
{
|
|
|
|
bool stop;
|
|
|
|
{
|
2013-08-05 21:20:19 -03:00
|
|
|
scoped_lock lock(*fop->mutex);
|
2008-02-04 02:37:26 +00:00
|
|
|
stop = fop->stop;
|
|
|
|
}
|
|
|
|
return stop;
|
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
static FileOp* fop_new(FileOpType type)
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
2011-03-22 21:11:25 -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;
|
2011-06-25 17:12:08 -03:00
|
|
|
fop->format_data = NULL;
|
2011-03-22 21:11:25 -03:00
|
|
|
fop->document = NULL;
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2013-08-05 21:20:19 -03:00
|
|
|
fop->mutex = new base::mutex();
|
2008-02-04 02:37:26 +00:00
|
|
|
fop->progress = 0.0f;
|
2012-07-06 01:06:00 -03:00
|
|
|
fop->progressInterface = NULL;
|
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;
|
2012-07-08 21:09:09 -03:00
|
|
|
fop->seq.frame = FrameNumber(0);
|
2008-02-04 02:37:26 +00:00
|
|
|
fop->seq.layer = NULL;
|
|
|
|
fop->seq.last_cel = NULL;
|
2012-01-05 19:45:03 -03:00
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
return fop;
|
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
static void fop_prepare_for_sequence(FileOp* fop)
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
2012-07-08 21:09:09 -03:00
|
|
|
fop->seq.palette = new Palette(FrameNumber(0), 256);
|
2011-03-22 21:11:25 -03:00
|
|
|
fop->seq.format_options.reset();
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
static FileFormat* get_fileformat(const char* extension)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2011-01-16 17:27:18 -03:00
|
|
|
FileFormatsList::iterator it = FileFormatsManager::instance().begin();
|
|
|
|
FileFormatsList::iterator end = FileFormatsManager::instance().end();
|
2007-09-18 23:57:02 +00:00
|
|
|
char buf[512], *tok;
|
|
|
|
|
2011-01-16 17:27:18 -03:00
|
|
|
for (; it != end; ++it) {
|
|
|
|
ustrcpy(buf, (*it)->extensions());
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2007-12-05 01:30:50 +00:00
|
|
|
for (tok=ustrtok(buf, ","); tok;
|
2012-01-05 19:45:03 -03:00
|
|
|
tok=ustrtok(NULL, ",")) {
|
2007-12-05 01:30:50 +00:00
|
|
|
if (ustricmp(extension, tok) == 0)
|
2012-01-05 19:45:03 -03:00
|
|
|
return (*it);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// 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)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
|
|
|
char *ptr, *ext;
|
|
|
|
char buf[16];
|
|
|
|
int chr, ret;
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// Get the extension.
|
2008-01-07 15:10:17 +00:00
|
|
|
ext = get_extension(filename);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// With extension.
|
2007-09-18 23:57:02 +00:00
|
|
|
if ((ext) && (*ext)) {
|
2011-03-22 21:11:25 -03:00
|
|
|
// Left side (the filename without the extension and without the '.').
|
2007-09-18 23:57:02 +00:00
|
|
|
ext--;
|
|
|
|
*ext = 0;
|
2008-01-07 15:10:17 +00:00
|
|
|
ustrcpy(left, filename);
|
2007-09-18 23:57:02 +00:00
|
|
|
*ext = '.';
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// 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
|
|
|
}
|
2011-03-22 21:11:25 -03:00
|
|
|
// Without extension (without right side).
|
2007-09-18 23:57:02 +00:00
|
|
|
else {
|
2008-01-07 15:10:17 +00:00
|
|
|
ustrcpy(left, filename);
|
|
|
|
ustrcpy(right, empty_string);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// Remove all trailing numbers in the "left" side, and pass they to "buf".
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
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) {
|
2012-01-05 19:45:03 -03:00
|
|
|
*(ptr--) = chr;
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2012-01-05 19:45:03 -03:00
|
|
|
if (width)
|
|
|
|
(*width)++;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uremove(left, -1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
// Convert the "buf" to integer and return it.
|
2007-09-18 23:57:02 +00:00
|
|
|
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
|
|
|
|
2013-08-05 21:20:19 -03:00
|
|
|
} // namespace app
|