Fix crash using --save-as CLI

Reported here:
https://community.aseprite.org/t/command-line-save-as-has-stopped-working/1140
This commit is contained in:
David Capello 2018-03-17 10:50:24 -03:00
parent ddc8c880c0
commit 08d6cbcf60
4 changed files with 94 additions and 67 deletions

View File

@ -32,6 +32,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/convert_to.h" #include "base/convert_to.h"
#include "base/fs.h" #include "base/fs.h"
#include "base/scoped_value.h"
#include "base/thread.h" #include "base/thread.h"
#include "base/unique_ptr.h" #include "base/unique_ptr.h"
#include "doc/frame_tag.h" #include "doc/frame_tag.h"
@ -165,10 +166,14 @@ void SaveFileBaseCommand::saveDocumentInBackground(
const bool markAsSaved) const bool markAsSaved)
{ {
if (!m_aniDir.empty()) { if (!m_aniDir.empty()) {
if (m_aniDir == "reverse") switch (convert_string_to_anidir(m_aniDir)) {
m_selFrames = m_selFrames.makeReverse(); case AniDir::REVERSE:
else if (m_aniDir == "ping-pong") m_selFrames = m_selFrames.makeReverse();
m_selFrames = m_selFrames.makePingPong(); break;
case AniDir::PING_PONG:
m_selFrames = m_selFrames.makePingPong();
break;
}
} }
FileOpROI roi(document, m_slice, m_frameTag, FileOpROI roi(document, m_slice, m_frameTag,
@ -290,49 +295,64 @@ SaveFileCopyAsCommand::SaveFileCopyAsCommand()
void SaveFileCopyAsCommand::onExecute(Context* context) void SaveFileCopyAsCommand::onExecute(Context* context)
{ {
Document* doc = context->activeDocument(); Document* doc = context->activeDocument();
ExportFileWindow win(doc); std::string outputFilename = m_filename;
bool askOverwrite = true; std::string layers = kAllLayers;
std::string frames = kAllFrames;
double xscale = 1.0;
double yscale = 1.0;
bool applyPixelRatio = false;
doc::AniDir aniDirValue = convert_string_to_anidir(m_aniDir);
bool isForTwitter = false;
win.SelectOutputFile.connect( if (context->isUIAvailable()) {
[this, &win, &askOverwrite, context, doc]() -> std::string { ExportFileWindow win(doc);
std::string result = bool askOverwrite = true;
saveAsDialog(
context, "Export",
win.outputFilenameValue(), false, false,
(doc->isAssociatedToFile() ? doc->filename():
std::string()));
if (!result.empty())
askOverwrite = false; // Already asked in the file selector dialog
return result; win.SelectOutputFile.connect(
}); [this, &win, &askOverwrite, context, doc]() -> std::string {
std::string result =
saveAsDialog(
context, "Export",
win.outputFilenameValue(), false, false,
(doc->isAssociatedToFile() ? doc->filename():
std::string()));
if (!result.empty())
askOverwrite = false; // Already asked in the file selector dialog
again:; return result;
if (!win.show()) });
return;
std::string outputFilename = win.outputFilenameValue(); again:;
if (!win.show())
return;
if (askOverwrite && outputFilename = win.outputFilenameValue();
base::is_file(outputFilename)) {
int ret = OptionalAlert::show( if (askOverwrite &&
Preferences::instance().exportFile.showOverwriteFilesAlert, base::is_file(outputFilename)) {
1, // Yes is the default option when the alert dialog is disabled int ret = OptionalAlert::show(
fmt::format(Strings::alerts_overwrite_files_on_export(), Preferences::instance().exportFile.showOverwriteFilesAlert,
outputFilename)); 1, // Yes is the default option when the alert dialog is disabled
if (ret != 1) fmt::format(Strings::alerts_overwrite_files_on_export(),
goto again; outputFilename));
if (ret != 1)
goto again;
}
// Save the preferences used to export the file, so if we open the
// window again, we will have the same options.
win.savePref();
layers = win.layersValue();
frames = win.framesValue();
xscale = yscale = win.resizeValue();
applyPixelRatio = win.applyPixelRatio();
aniDirValue = win.aniDirValue();
isForTwitter = win.isForTwitter();
} }
// Save the preferences used to export the file, so if we open the
// window again, we will have the same options.
win.savePref();
double xscale, yscale;
xscale = yscale = win.resizeValue();
// Pixel ratio // Pixel ratio
if (win.applyPixelRatio()) { if (applyPixelRatio) {
doc::PixelRatio pr = doc->sprite()->pixelRatio(); doc::PixelRatio pr = doc->sprite()->pixelRatio();
xscale *= pr.w; xscale *= pr.w;
yscale *= pr.h; yscale *= pr.h;
@ -364,35 +384,33 @@ again:;
{ {
RestoreVisibleLayers layersVisibility; RestoreVisibleLayers layersVisibility;
Site site = context->activeSite(); if (context->isUIAvailable()) {
Site site = context->activeSite();
// Selected layers to export // Selected layers to export
calculate_visible_layers(site, calculate_visible_layers(site,
win.layersValue(), layers,
layersVisibility); layersVisibility);
// Selected frames to export // Selected frames to export
SelectedFrames selFrames; SelectedFrames selFrames;
FrameTag* frameTag = calculate_selected_frames( FrameTag* frameTag = calculate_selected_frames(
site, win.framesValue(), selFrames); site, frames, selFrames);
if (frameTag) if (frameTag)
m_frameTag = frameTag->name(); m_frameTag = frameTag->name();
m_selFrames = selFrames; m_selFrames = selFrames;
m_adjustFramesByFrameTag = false; m_adjustFramesByFrameTag = false;
m_aniDir.clear();
switch (win.aniDirValue()) {
case doc::AniDir::FORWARD: m_aniDir = "forward"; break;
case doc::AniDir::REVERSE: m_aniDir = "reverse"; break;
case doc::AniDir::PING_PONG: m_aniDir = "ping-pong"; break;
} }
GifEncoderDurationFix fix(win.isForTwitter()); base::ScopedValue<std::string> restoreAniDir(
m_aniDir,
convert_anidir_to_string(aniDirValue), // New value
m_aniDir); // Restore old value
GifEncoderDurationFix fix(isForTwitter);
saveDocumentInBackground( saveDocumentInBackground(
context, doc, outputFilename, false); context, doc, outputFilename, false);
m_aniDir.clear();
} }
// Undo resize // Undo resize

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2017 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -821,7 +821,7 @@ void DocumentExporter::createDataFile(const Samples& samples, std::ostream& os,
os << "\n { \"name\": \"" << escape_for_json(tag->name()) << "\"," os << "\n { \"name\": \"" << escape_for_json(tag->name()) << "\","
<< " \"from\": " << (tag->fromFrame()+delta.first) << "," << " \"from\": " << (tag->fromFrame()+delta.first) << ","
<< " \"to\": " << (tag->toFrame()+delta.second) << "," << " \"to\": " << (tag->toFrame()+delta.second) << ","
<< " \"direction\": \"" << escape_for_json(convert_to_string(tag->aniDir())) << "\" }"; << " \"direction\": \"" << escape_for_json(convert_anidir_to_string(tag->aniDir())) << "\" }";
} }
} }
os << "\n ]"; os << "\n ]";

View File

@ -1,5 +1,5 @@
// Aseprite Document Library // Aseprite Document Library
// Copyright (c) 2001-2015 David Capello // Copyright (c) 2001-2018 David Capello
// //
// This file is released under the terms of the MIT license. // This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information. // Read LICENSE.txt for more information.
@ -12,7 +12,7 @@
namespace doc { namespace doc {
std::string convert_to_string(AniDir anidir) std::string convert_anidir_to_string(AniDir anidir)
{ {
switch (anidir) { switch (anidir) {
case AniDir::FORWARD: return "forward"; case AniDir::FORWARD: return "forward";
@ -22,4 +22,12 @@ std::string convert_to_string(AniDir anidir)
return ""; return "";
} }
doc::AniDir convert_string_to_anidir(const std::string& s)
{
if (s == "forward") return AniDir::FORWARD;
if (s == "reverse") return AniDir::REVERSE;
if (s == "pingpong") return AniDir::PING_PONG;
return AniDir::FORWARD;
}
} // namespace doc } // namespace doc

View File

@ -1,5 +1,5 @@
// Aseprite Document Library // Aseprite Document Library
// Copyright (c) 2001-2015 David Capello // Copyright (c) 2001-2018 David Capello
// //
// This file is released under the terms of the MIT license. // This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information. // Read LICENSE.txt for more information.
@ -18,7 +18,8 @@ namespace doc {
PING_PONG = 2, PING_PONG = 2,
}; };
std::string convert_to_string(AniDir anidir); std::string convert_anidir_to_string(AniDir anidir);
doc::AniDir convert_string_to_anidir(const std::string& s);
} // namespace doc } // namespace doc