2015-02-12 12:16:25 -03:00
|
|
|
// Aseprite
|
|
|
|
// Copyright (C) 2001-2015 David Capello
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License version 2 as
|
|
|
|
// published by the Free Software Foundation.
|
2007-09-18 23:57:02 +00:00
|
|
|
|
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-10-14 19:58:11 -03:00
|
|
|
#include "app/file/file.h"
|
|
|
|
|
2013-08-05 21:20:19 -03:00
|
|
|
#include "app/console.h"
|
2014-07-19 22:01:39 -03:00
|
|
|
#include "app/context.h"
|
2013-08-05 21:20:19 -03:00
|
|
|
#include "app/document.h"
|
|
|
|
#include "app/file/file_format.h"
|
|
|
|
#include "app/file/file_formats_manager.h"
|
|
|
|
#include "app/file/format_options.h"
|
2014-09-21 13:42:46 -03:00
|
|
|
#include "app/file/split_filename.h"
|
2015-01-25 22:36:32 -03:00
|
|
|
#include "app/filename_formatter.h"
|
2013-08-05 21:20:19 -03:00
|
|
|
#include "app/modules/gui.h"
|
|
|
|
#include "app/modules/palettes.h"
|
2013-10-14 19:58:11 -03:00
|
|
|
#include "app/ui/status_bar.h"
|
|
|
|
#include "base/fs.h"
|
|
|
|
#include "base/mutex.h"
|
|
|
|
#include "base/path.h"
|
|
|
|
#include "base/scoped_lock.h"
|
|
|
|
#include "base/shared_ptr.h"
|
|
|
|
#include "base/string.h"
|
2014-10-20 22:21:31 -03:00
|
|
|
#include "doc/doc.h"
|
2014-12-28 11:06:11 -03:00
|
|
|
#include "render/quantization.h"
|
|
|
|
#include "render/render.h"
|
2012-06-17 22:49:58 -03:00
|
|
|
#include "ui/alert.h"
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2013-10-14 19:58:11 -03:00
|
|
|
#include <cstring>
|
2015-02-12 10:55:58 -03:00
|
|
|
#include <cstdarg>
|
2011-03-22 21:11:25 -03:00
|
|
|
|
2013-08-05 21:20:19 -03:00
|
|
|
namespace app {
|
|
|
|
|
|
|
|
using namespace base;
|
|
|
|
|
2014-07-19 22:01:39 -03:00
|
|
|
static FileOp* fop_new(FileOpType type, Context* context);
|
2011-03-22 21:11:25 -03:00
|
|
|
static void fop_prepare_for_sequence(FileOp* fop);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2015-03-17 17:17:01 -03:00
|
|
|
std::string get_readable_extensions()
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2015-03-17 17:17:01 -03:00
|
|
|
std::string buf;
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2015-03-17 17:17:01 -03:00
|
|
|
for (const FileFormat* format : *FileFormatsManager::instance()) {
|
|
|
|
if (format->support(FILE_SUPPORT_LOAD)) {
|
|
|
|
if (!buf.empty())
|
|
|
|
buf.push_back(',');
|
|
|
|
buf += format->extensions();
|
2011-01-16 17:27:18 -03:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2015-03-17 17:17:01 -03:00
|
|
|
|
|
|
|
return buf;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2015-03-17 17:17:01 -03:00
|
|
|
std::string get_writable_extensions()
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2015-03-17 17:17:01 -03:00
|
|
|
std::string buf;
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2015-03-17 17:17:01 -03:00
|
|
|
for (const FileFormat* format : *FileFormatsManager::instance()) {
|
|
|
|
if (format->support(FILE_SUPPORT_SAVE)) {
|
|
|
|
if (!buf.empty())
|
|
|
|
buf.push_back(',');
|
|
|
|
buf += format->extensions();
|
2011-01-16 17:27:18 -03:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2015-03-17 17:17:01 -03:00
|
|
|
|
|
|
|
return buf;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2014-07-19 22:01:39 -03:00
|
|
|
Document* load_document(Context* context, 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 */
|
2014-07-19 22:01:39 -03:00
|
|
|
FileOp *fop = fop_to_load_document(context, 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()) {
|
2015-04-06 11:58:42 -03:00
|
|
|
Console console(context);
|
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);
|
|
|
|
|
2014-08-22 09:46:25 -03:00
|
|
|
if (document && context)
|
2014-07-29 00:53:24 -03:00
|
|
|
document->setContext(context);
|
|
|
|
|
2011-03-22 21:11:25 -03:00
|
|
|
return document;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
2014-07-29 00:53:24 -03:00
|
|
|
int save_document(Context* context, doc::Document* document)
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
2014-07-29 00:53:24 -03:00
|
|
|
ASSERT(dynamic_cast<app::Document*>(document));
|
|
|
|
|
2008-02-04 02:37:26 +00:00
|
|
|
int ret;
|
2015-01-25 22:36:32 -03:00
|
|
|
FileOp* fop = fop_to_save_document(context,
|
|
|
|
static_cast<app::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()) {
|
2015-04-06 11:58:42 -03:00
|
|
|
Console console(context);
|
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;
|
|
|
|
}
|
|
|
|
|
2014-07-19 22:01:39 -03:00
|
|
|
FileOp* fop_to_load_document(Context* context, const char* filename, int flags)
|
2008-02-04 02:37:26 +00:00
|
|
|
{
|
|
|
|
FileOp *fop;
|
|
|
|
|
2014-07-19 22:01:39 -03:00
|
|
|
fop = fop_new(FileOpLoad, context);
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!fop)
|
|
|
|
return NULL;
|
|
|
|
|
2013-10-14 19:58:11 -03:00
|
|
|
// Get the extension of the filename (in lower case)
|
2014-04-20 19:53:27 -03:00
|
|
|
std::string extension = base::string_to_lower(base::get_file_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
|
|
|
|
2013-10-14 19:58:11 -03:00
|
|
|
// Does file exist?
|
2014-04-17 17:12:55 -03:00
|
|
|
if (!base::is_file(filename)) {
|
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
|
|
|
}
|
|
|
|
|
2014-08-21 23:39:20 -03:00
|
|
|
// Get the format through the extension of the filename
|
|
|
|
fop->format = FileFormatsManager::instance()
|
|
|
|
->getFileFormatByExtension(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)) {
|
2014-09-21 13:42:46 -03:00
|
|
|
std::string left, right;
|
2008-02-10 19:06:03 +00:00
|
|
|
int c, width, start_from;
|
2014-09-21 13:42:46 -03:00
|
|
|
char buf[512];
|
2008-02-10 19:06:03 +00:00
|
|
|
|
|
|
|
/* 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
|
|
|
|
2014-09-21 13:42:46 -03:00
|
|
|
// Check is this could be a sequence
|
|
|
|
start_from = split_filename(filename, left, right, width);
|
2008-02-10 19:06:03 +00:00
|
|
|
if (start_from >= 0) {
|
2014-09-21 13:42:46 -03:00
|
|
|
// Try to get more file names
|
2012-01-05 19:45:03 -03:00
|
|
|
for (c=start_from+1; ; c++) {
|
2014-09-21 13:42:46 -03:00
|
|
|
// Get the next file name
|
|
|
|
sprintf(buf, "%s%0*d%s", left.c_str(), width, c, right.c_str());
|
2012-01-05 19:45:03 -03:00
|
|
|
|
2014-09-21 13:42:46 -03:00
|
|
|
// If the file doesn't exist, we doesn't need more files to load
|
|
|
|
if (!base::is_file(buf))
|
2012-01-05 19:45:03 -03:00
|
|
|
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 */
|
2014-07-29 00:53:24 -03:00
|
|
|
if ((flags & FILE_LOAD_SEQUENCE_ASK) && context && context->isUiAvailable()) {
|
2012-01-05 19:45:03 -03:00
|
|
|
/* really want load all files? */
|
|
|
|
if ((fop->seq.filename_list.size() > 1) &&
|
2012-06-17 22:02:54 -03:00
|
|
|
(ui::Alert::show("Notice"
|
2014-09-21 13:42:46 -03:00
|
|
|
"<<Possible animation with:"
|
|
|
|
"<<%s, %s..."
|
|
|
|
"<<Do you want to load the sequence of bitmaps?"
|
|
|
|
"||&Agree||&Skip",
|
|
|
|
base::get_file_name(fop->seq.filename_list[0]).c_str(),
|
|
|
|
base::get_file_name(fop->seq.filename_list[1]).c_str()) != 1)) {
|
|
|
|
|
|
|
|
// If the user replies "Skip", we need just one file name
|
|
|
|
// (the first one).
|
2012-01-05 19:45: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());
|
|
|
|
}
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2015-01-25 22:36:32 -03:00
|
|
|
FileOp* fop_to_save_document(Context* context, Document* document, const char* fn_format_arg)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2008-02-04 02:37:26 +00:00
|
|
|
FileOp *fop;
|
2007-09-18 23:57:02 +00:00
|
|
|
bool fatal;
|
|
|
|
|
2014-07-19 22:01:39 -03:00
|
|
|
fop = fop_new(FileOpSave, context);
|
2008-02-04 02:37:26 +00:00
|
|
|
if (!fop)
|
|
|
|
return NULL;
|
|
|
|
|
2013-10-14 19:58:11 -03:00
|
|
|
// Document to save
|
2011-03-22 21:11:25 -03:00
|
|
|
fop->document = document;
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2013-10-14 19:58:11 -03:00
|
|
|
// Get the extension of the filename (in lower case)
|
2014-07-29 00:53:24 -03:00
|
|
|
std::string extension = base::string_to_lower(base::get_file_extension(fop->document->filename()));
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2014-07-29 00:53:24 -03:00
|
|
|
PRINTF("Saving document \"%s\" (%s)\n", fop->document->filename().c_str(), extension.c_str());
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2014-08-21 23:39:20 -03:00
|
|
|
// Get the format through the extension of the filename
|
|
|
|
fop->format = FileFormatsManager::instance()
|
|
|
|
->getFileFormatByExtension(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_SAVE)) {
|
2014-07-29 00:53:24 -03:00
|
|
|
fop_error(fop, "ASEPRITE can't save \"%s\" files\n", extension.c_str());
|
2008-02-04 02:37:26 +00:00
|
|
|
return fop;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2013-10-14 19:58:11 -03:00
|
|
|
// Warnings
|
2014-04-20 19:53:27 -03:00
|
|
|
std::string warnings;
|
2010-01-30 16:43:13 +00:00
|
|
|
fatal = false;
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
/* check image type support */
|
2014-07-30 01:28:15 -03:00
|
|
|
switch (fop->document->sprite()->pixelFormat()) {
|
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))) {
|
2013-10-14 19:58:11 -03:00
|
|
|
warnings += "<<- RGB format";
|
2012-01-05 19:45:03 -03:00
|
|
|
fatal = true;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2013-10-14 19:58:11 -03:00
|
|
|
|
2011-01-16 17:27:18 -03:00
|
|
|
if (!(fop->format->support(FILE_SUPPORT_RGBA)) &&
|
2014-07-29 00:53:24 -03:00
|
|
|
fop->document->sprite()->needAlpha()) {
|
2013-10-14 19:58:11 -03:00
|
|
|
|
|
|
|
warnings += "<<- 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))) {
|
2013-10-14 19:58:11 -03:00
|
|
|
warnings += "<<- Grayscale format";
|
2012-01-05 19:45:03 -03:00
|
|
|
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)) &&
|
2014-07-29 00:53:24 -03:00
|
|
|
fop->document->sprite()->needAlpha()) {
|
2013-10-14 19:58:11 -03:00
|
|
|
|
|
|
|
warnings += "<<- 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))) {
|
2013-10-14 19:58:11 -03:00
|
|
|
warnings += "<<- Indexed format";
|
2012-01-05 19:45:03 -03:00
|
|
|
fatal = true;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-03-09 13:57:16 -03:00
|
|
|
// Frames support
|
2014-07-30 01:28:15 -03:00
|
|
|
if (fop->document->sprite()->totalFrames() > 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)) {
|
2013-10-14 19:58:11 -03:00
|
|
|
warnings += "<<- Frames";
|
2011-01-16 17:27:18 -03:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2015-03-09 13:57:16 -03:00
|
|
|
// Layers support
|
2014-07-30 01:28:15 -03:00
|
|
|
if (fop->document->sprite()->folder()->getLayersCount() > 1) {
|
2011-01-16 17:27:18 -03:00
|
|
|
if (!(fop->format->support(FILE_SUPPORT_LAYERS))) {
|
2013-10-14 19:58:11 -03:00
|
|
|
warnings += "<<- Layers";
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-09 13:57:16 -03:00
|
|
|
// Palettes support
|
2014-07-29 00:53:24 -03:00
|
|
|
if (fop->document->sprite()->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)) {
|
2013-10-14 19:58:11 -03:00
|
|
|
warnings += "<<- Palette changes between frames";
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-09 13:57:16 -03:00
|
|
|
// Check frames support
|
|
|
|
if (!fop->document->sprite()->frameTags().empty()) {
|
|
|
|
if (!fop->format->support(FILE_SUPPORT_FRAME_TAGS)) {
|
|
|
|
warnings += "<<- Frame tags";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-14 19:58:11 -03:00
|
|
|
// Show the confirmation alert
|
|
|
|
if (!warnings.empty()) {
|
|
|
|
// Interative
|
2014-07-29 00:53:24 -03:00
|
|
|
if (context && context->isUiAvailable()) {
|
2015-03-11 16:15:09 -03:00
|
|
|
warnings += "<<You can use \".ase\" format to keep all this information.";
|
|
|
|
|
|
|
|
std::string title, buttons;
|
|
|
|
if (fatal) {
|
|
|
|
title = "Error";
|
|
|
|
buttons = "&Close";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
title = "Warning";
|
|
|
|
buttons = "&Yes||&No";
|
|
|
|
}
|
|
|
|
|
|
|
|
int ret = ui::Alert::show("%s<<File format \".%s\" doesn't support:%s"
|
|
|
|
"<<Do you want continue with \".%s\" anyway?"
|
|
|
|
"||%s",
|
|
|
|
title.c_str(),
|
|
|
|
fop->format->name(),
|
|
|
|
warnings.c_str(),
|
|
|
|
fop->format->name(),
|
|
|
|
buttons.c_str());
|
|
|
|
|
|
|
|
// Operation can't be done (by fatal error) or the user cancel
|
|
|
|
// 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
|
|
|
}
|
|
|
|
}
|
2013-10-14 19:58:11 -03:00
|
|
|
// No interactive & fatal error?
|
2008-02-04 02:37:26 +00:00
|
|
|
else if (fatal) {
|
2013-10-14 19:58:11 -03:00
|
|
|
fop_error(fop, warnings.c_str());
|
2008-02-04 02:37:26 +00:00
|
|
|
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);
|
|
|
|
|
2015-01-25 22:36:32 -03:00
|
|
|
std::string fn = fop->document->filename();
|
|
|
|
std::string fn_format = fn_format_arg;
|
|
|
|
bool default_format = false;
|
|
|
|
|
|
|
|
if (fn_format.empty()) {
|
|
|
|
if (fop->document->sprite()->totalFrames() == 1)
|
|
|
|
fn_format = "{fullname}";
|
|
|
|
else {
|
|
|
|
fn_format = "{path}/{title}{frame}.{extension}";
|
|
|
|
default_format = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save one frame
|
2014-07-30 01:28:15 -03:00
|
|
|
if (fop->document->sprite()->totalFrames() == 1) {
|
2015-01-25 22:36:32 -03:00
|
|
|
fn = filename_formatter(fn_format, fn);
|
|
|
|
fop->seq.filename_list.push_back(fn);
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
2015-01-25 22:36:32 -03:00
|
|
|
// Save multiple frames
|
2008-02-04 02:37:26 +00:00
|
|
|
else {
|
2015-01-25 22:36:32 -03:00
|
|
|
int width = 0;
|
|
|
|
int start_from = 0;
|
|
|
|
|
|
|
|
if (default_format) {
|
2015-01-25 23:10:51 -03:00
|
|
|
std::string left, right;
|
|
|
|
start_from = split_filename(fn.c_str(), left, right, width);
|
2015-01-25 22:36:32 -03:00
|
|
|
if (start_from < 0) {
|
|
|
|
start_from = 1;
|
|
|
|
width = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fn = left;
|
|
|
|
fn += right;
|
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2015-01-25 22:36:32 -03:00
|
|
|
std::vector<char> buf(32);
|
|
|
|
std::sprintf(&buf[0], "{frame%0*d}", width, 0);
|
|
|
|
if (default_format)
|
|
|
|
fn_format = set_frame_format(fn_format, &buf[0]);
|
|
|
|
else if (fop->document->sprite()->totalFrames() > 1)
|
|
|
|
fn_format = add_frame_format(fn_format, &buf[0]);
|
|
|
|
|
2014-12-28 20:39:11 -03:00
|
|
|
for (frame_t frame(0); frame<fop->document->sprite()->totalFrames(); ++frame) {
|
2015-01-25 22:36:32 -03:00
|
|
|
std::string frame_fn =
|
|
|
|
filename_formatter(fn_format, fn, "", start_from+frame);
|
|
|
|
|
|
|
|
fop->seq.filename_list.push_back(frame_fn);
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2014-07-29 00:53:24 -03:00
|
|
|
fop->filename = fop->document->filename();
|
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)) {
|
2015-04-01 12:35:18 -03:00
|
|
|
base::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?
|
2015-04-02 20:42:43 -03:00
|
|
|
if (!format_options) {
|
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()) {
|
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 { \
|
2015-02-09 11:40:43 -03:00
|
|
|
fop->seq.last_cel->data()->setImage(fop->seq.image); \
|
2012-01-05 19:45:03 -03:00
|
|
|
fop->seq.layer->addCel(fop->seq.last_cel); \
|
|
|
|
\
|
2014-12-28 20:39:11 -03:00
|
|
|
if (fop->document->sprite()->palette(frame) \
|
2012-01-05 19:45:03 -03:00
|
|
|
->countDiff(fop->seq.palette, NULL, NULL) > 0) { \
|
|
|
|
fop->seq.palette->setFrame(frame); \
|
2014-07-29 00:53:24 -03:00
|
|
|
fop->document->sprite()->setPalette(fop->seq.palette, true); \
|
2012-01-05 19:45:03 -03:00
|
|
|
} \
|
|
|
|
\
|
2015-04-02 20:42:43 -03:00
|
|
|
old_image = fop->seq.image.get(); \
|
2015-01-04 10:58:14 -03:00
|
|
|
fop->seq.image.reset(NULL); \
|
2012-01-05 19:45:03 -03:00
|
|
|
fop->seq.last_cel = NULL; \
|
2008-02-04 02:37:26 +00:00
|
|
|
} while (0)
|
|
|
|
|
2015-01-04 10:58:14 -03:00
|
|
|
// Load the sequence
|
2014-12-28 20:39:11 -03:00
|
|
|
frame_t frames(fop->seq.filename_list.size());
|
|
|
|
frame_t frame(0);
|
2015-04-02 20:42:43 -03:00
|
|
|
old_image = nullptr;
|
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) {
|
2015-04-02 20:42:43 -03:00
|
|
|
fop->seq.image.reset();
|
2013-03-30 19:53:52 -03:00
|
|
|
delete fop->seq.last_cel;
|
|
|
|
delete fop->document;
|
2015-04-02 20:42:43 -03:00
|
|
|
fop->document = nullptr;
|
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) {
|
2015-04-02 20:42:43 -03:00
|
|
|
fop->seq.image.reset();
|
2013-03-30 19:53:52 -03:00
|
|
|
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
|
2013-11-09 19:59:05 -03:00
|
|
|
if (count_diff_between_images(old_image, fop->seq.image)) {
|
2012-01-05 19:45:03 -03:00
|
|
|
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
|
2014-07-29 00:53:24 -03:00
|
|
|
fop->document->sprite()->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)) {
|
2014-04-10 00:33:28 -03:00
|
|
|
#ifdef ENABLE_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
|
|
|
|
2014-07-29 00:53:24 -03:00
|
|
|
Sprite* sprite = fop->document->sprite();
|
2011-03-22 21:11:25 -03:00
|
|
|
|
|
|
|
// Create a temporary bitmap
|
2015-01-04 10:58:14 -03:00
|
|
|
fop->seq.image.reset(Image::create(sprite->pixelFormat(),
|
|
|
|
sprite->width(),
|
|
|
|
sprite->height()));
|
|
|
|
|
|
|
|
fop->seq.progress_offset = 0.0f;
|
|
|
|
fop->seq.progress_fraction = 1.0f / (double)sprite->totalFrames();
|
|
|
|
|
|
|
|
// For each frame in the sprite.
|
|
|
|
render::Render render;
|
|
|
|
for (frame_t frame(0); frame < sprite->totalFrames(); ++frame) {
|
|
|
|
// Draw the "frame" in "fop->seq.image"
|
2015-04-02 20:42:43 -03:00
|
|
|
render.renderSprite(fop->seq.image.get(), sprite, frame);
|
2015-01-04 10:58:14 -03:00
|
|
|
|
|
|
|
// Setup the palette.
|
|
|
|
sprite->palette(frame)->copyColorsTo(fop->seq.palette);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2015-01-04 10:58:14 -03:00
|
|
|
// Setup the filename to be used.
|
|
|
|
fop->filename = fop->seq.filename_list[frame];
|
|
|
|
|
|
|
|
// Call the "save" procedure... did it fail?
|
|
|
|
if (!fop->format->save(fop)) {
|
|
|
|
fop_error(fop, "Error saving frame %d in the file \"%s\"\n",
|
|
|
|
frame+1, fop->filename.c_str());
|
|
|
|
break;
|
2012-01-05 19:45:03 -03:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2015-01-04 10:58:14 -03:00
|
|
|
fop->seq.progress_offset += fop->seq.progress_fraction;
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
2015-01-04 10:58:14 -03:00
|
|
|
fop->filename = *fop->seq.filename_list.begin();
|
|
|
|
|
|
|
|
// Destroy the image
|
|
|
|
fop->seq.image.reset(NULL);
|
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
|
|
|
}
|
2014-04-10 00:33:28 -03:00
|
|
|
#else
|
|
|
|
fop_error(fop,
|
|
|
|
"Save operation is not supported in trial version.\n"
|
|
|
|
"Go to " WEBSITE_DOWNLOAD " and get the full-version.");
|
|
|
|
#endif
|
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
|
|
|
|
2014-07-29 00:53:24 -03:00
|
|
|
void FileOp::createDocument(Sprite* spr)
|
|
|
|
{
|
|
|
|
// spr can be NULL if the sprite is set in onPostLoad() then
|
|
|
|
|
|
|
|
ASSERT(this->document == NULL);
|
|
|
|
this->document = new Document(spr);
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-07-29 00:53:24 -03:00
|
|
|
if (fop->document->sprite() != NULL) {
|
2011-06-25 17:12:08 -03:00
|
|
|
// Creates a suitable palette for RGB images
|
2014-07-30 01:28:15 -03:00
|
|
|
if (fop->document->sprite()->pixelFormat() == IMAGE_RGB &&
|
2014-07-29 00:53:24 -03:00
|
|
|
fop->document->sprite()->getPalettes().size() <= 1 &&
|
2014-12-28 20:39:11 -03:00
|
|
|
fop->document->sprite()->palette(frame_t(0))->isBlack()) {
|
2015-04-01 12:35:18 -03:00
|
|
|
base::SharedPtr<Palette> palette
|
2014-12-28 11:06:11 -03:00
|
|
|
(render::create_palette_from_rgb(
|
2014-07-29 00:53:24 -03:00
|
|
|
fop->document->sprite(),
|
2014-12-28 20:39:11 -03:00
|
|
|
frame_t(0), NULL));
|
2011-06-25 17:12:08 -03:00
|
|
|
|
2014-07-29 00:53:24 -03:00
|
|
|
fop->document->sprite()->resetPalettes();
|
2015-04-02 20:42:43 -03:00
|
|
|
fop->document->sprite()->setPalette(palette.get(), false);
|
2011-06-25 17:12:08 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fop->document->markAsSaved();
|
|
|
|
}
|
|
|
|
|
2015-04-01 12:35:18 -03:00
|
|
|
void fop_sequence_set_format_options(FileOp* fop, const base::SharedPtr<FormatOptions>& format_options)
|
2008-03-27 14:29:33 +00:00
|
|
|
{
|
2015-04-02 20:42:43 -03:00
|
|
|
ASSERT(!fop->seq.format_options);
|
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)
|
|
|
|
{
|
2013-11-09 19:59:05 -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
|
|
|
|
2013-11-09 19:59:05 -03: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
|
2014-07-30 01:28:15 -03:00
|
|
|
sprite->folder()->addLayer(layer);
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2010-03-28 12:15:32 -03:00
|
|
|
// Done
|
2014-07-29 00:53:24 -03:00
|
|
|
fop->createDocument(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 {
|
2014-07-29 00:53:24 -03:00
|
|
|
sprite = fop->document->sprite();
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2014-07-30 01:28:15 -03:00
|
|
|
if (sprite->pixelFormat() != 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
|
2015-01-04 10:58:14 -03:00
|
|
|
fop->seq.image.reset(Image::create(pixelFormat, w, h));
|
|
|
|
fop->seq.last_cel = new Cel(fop->seq.frame++, ImageRef(NULL));
|
2008-02-04 02:37:26 +00:00
|
|
|
|
2015-01-04 10:58:14 -03:00
|
|
|
return fop->seq.image.get();
|
2008-02-04 02:37:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void fop_error(FileOp *fop, const char *format, ...)
|
|
|
|
{
|
|
|
|
char buf_error[4096];
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
2014-09-21 13:42:46 -03:00
|
|
|
vsnprintf(buf_error, sizeof(buf_error), format, ap);
|
2008-02-04 02:37:26 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-07-19 22:01:39 -03:00
|
|
|
static FileOp* fop_new(FileOpType type, Context* context)
|
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;
|
2014-07-19 22:01:39 -03:00
|
|
|
fop->context = context;
|
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;
|
2015-01-04 10:58:14 -03:00
|
|
|
fop->seq.image.reset(NULL);
|
2008-02-04 02:37:26 +00:00
|
|
|
fop->seq.progress_offset = 0.0f;
|
|
|
|
fop->seq.progress_fraction = 0.0f;
|
2014-12-28 20:39:11 -03:00
|
|
|
fop->seq.frame = frame_t(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
|
|
|
{
|
2014-12-28 20:39:11 -03:00
|
|
|
fop->seq.palette = new Palette(frame_t(0), 256);
|
2011-03-22 21:11:25 -03:00
|
|
|
fop->seq.format_options.reset();
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2013-08-05 21:20:19 -03:00
|
|
|
} // namespace app
|