Fix possibilities of random crashes using filters w/Undo History window visible

Same problem as in 86a6462d7b82608cc14a8417bbdb42e2a4e3c467
This commit is contained in:
David Capello 2017-10-27 09:25:50 -03:00
parent 7becbc09b8
commit 4585b5e7e5
4 changed files with 29 additions and 14 deletions

View File

@ -183,7 +183,7 @@ bool FilterManagerImpl::applyStep()
return true; return true;
} }
void FilterManagerImpl::apply(Transaction& transaction) void FilterManagerImpl::apply()
{ {
bool cancelled = false; bool cancelled = false;
@ -203,7 +203,7 @@ void FilterManagerImpl::apply(Transaction& transaction)
if (algorithm::shrink_bounds2(m_src.get(), m_dst.get(), if (algorithm::shrink_bounds2(m_src.get(), m_dst.get(),
m_bounds, output)) { m_bounds, output)) {
if (m_cel->layer()->isBackground()) { if (m_cel->layer()->isBackground()) {
transaction.execute( m_transaction->execute(
new cmd::CopyRegion( new cmd::CopyRegion(
m_cel->image(), m_cel->image(),
m_dst.get(), m_dst.get(),
@ -212,7 +212,7 @@ void FilterManagerImpl::apply(Transaction& transaction)
} }
else { else {
// Patch "m_cel" // Patch "m_cel"
transaction.execute( m_transaction->execute(
new cmd::PatchCel( new cmd::PatchCel(
m_cel, m_dst.get(), m_cel, m_dst.get(),
gfx::Region(output), gfx::Region(output),
@ -239,7 +239,7 @@ void FilterManagerImpl::applyToTarget()
// Initialize writting operation // Initialize writting operation
ContextReader reader(m_context); ContextReader reader(m_context);
ContextWriter writer(reader); ContextWriter writer(reader);
Transaction transaction(writer.context(), m_filter->getName(), ModifyDocument); m_transaction.reset(new Transaction(writer.context(), m_filter->getName(), ModifyDocument));
m_progressBase = 0.0f; m_progressBase = 0.0f;
m_progressWidth = 1.0f / images.size(); m_progressWidth = 1.0f / images.size();
@ -250,7 +250,7 @@ void FilterManagerImpl::applyToTarget()
if (paletteChange) { if (paletteChange) {
Palette newPalette = *getNewPalette(); Palette newPalette = *getNewPalette();
restoreSpritePalette(); restoreSpritePalette();
transaction.execute( m_transaction->execute(
new cmd::SetPalette(m_site.sprite(), new cmd::SetPalette(m_site.sprite(),
m_site.frame(), &newPalette)); m_site.frame(), &newPalette));
} }
@ -264,7 +264,7 @@ void FilterManagerImpl::applyToTarget()
// Avoid applying the filter two times to the same image // Avoid applying the filter two times to the same image
if (visited.find(image->id()) == visited.end()) { if (visited.find(image->id()) == visited.end()) {
visited.insert(image->id()); visited.insert(image->id());
applyToCel(transaction, it->cel()); applyToCel(it->cel());
} }
// Is there a delegate to know if the process was cancelled by the user? // Is there a delegate to know if the process was cancelled by the user?
@ -275,12 +275,17 @@ void FilterManagerImpl::applyToTarget()
m_progressBase += m_progressWidth; m_progressBase += m_progressWidth;
} }
transaction.commit();
// Reset m_oldPalette to avoid restoring the color palette // Reset m_oldPalette to avoid restoring the color palette
m_oldPalette.reset(nullptr); m_oldPalette.reset(nullptr);
} }
void FilterManagerImpl::commitTransaction()
{
// This must be executed in the main UI thread.
// Check Transaction::commit() comments.
m_transaction->commit();
}
void FilterManagerImpl::flush() void FilterManagerImpl::flush()
{ {
int h = m_row - m_nextRowToFlush; int h = m_row - m_nextRowToFlush;
@ -395,10 +400,10 @@ void FilterManagerImpl::init(Cel* cel)
m_target &= ~TARGET_ALPHA_CHANNEL; m_target &= ~TARGET_ALPHA_CHANNEL;
} }
void FilterManagerImpl::applyToCel(Transaction& transaction, Cel* cel) void FilterManagerImpl::applyToCel(Cel* cel)
{ {
init(cel); init(cel);
apply(transaction); apply();
} }
bool FilterManagerImpl::updateBounds(doc::Mask* mask) bool FilterManagerImpl::updateBounds(doc::Mask* mask)

View File

@ -19,6 +19,7 @@
#include "gfx/rect.h" #include "gfx/rect.h"
#include <cstring> #include <cstring>
#include <memory>
namespace doc { namespace doc {
class Cel; class Cel;
@ -82,6 +83,7 @@ namespace app {
void end(); void end();
bool applyStep(); bool applyStep();
void applyToTarget(); void applyToTarget();
void commitTransaction();
app::Document* document(); app::Document* document();
doc::Sprite* sprite() { return m_site.sprite(); } doc::Sprite* sprite() { return m_site.sprite(); }
@ -114,8 +116,8 @@ namespace app {
private: private:
void init(doc::Cel* cel); void init(doc::Cel* cel);
void apply(Transaction& transaction); void apply();
void applyToCel(Transaction& transaction, doc::Cel* cel); void applyToCel(doc::Cel* cel);
bool updateBounds(doc::Mask* mask); bool updateBounds(doc::Mask* mask);
bool paletteHasChanged(); bool paletteHasChanged();
void restoreSpritePalette(); void restoreSpritePalette();
@ -136,6 +138,7 @@ namespace app {
Target m_targetOrig; // Original targets Target m_targetOrig; // Original targets
Target m_target; // Filtered targets Target m_target; // Filtered targets
base::UniquePtr<doc::Palette> m_oldPalette; base::UniquePtr<doc::Palette> m_oldPalette;
std::unique_ptr<Transaction> m_transaction;
// Hooks // Hooks
float m_progressBase; float m_progressBase;

View File

@ -104,7 +104,9 @@ void FilterWorker::run()
{ {
scoped_lock lock(m_mutex); scoped_lock lock(m_mutex);
if (!m_done) if (m_done)
m_filterMgr->commitTransaction();
else
m_cancelled = true; m_cancelled = true;
} }

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2017 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.
@ -51,6 +51,11 @@ namespace app {
// If you don't use this routine, all the changes will be discarded // If you don't use this routine, all the changes will be discarded
// (if the sprite's undo was enabled when the Transaction was // (if the sprite's undo was enabled when the Transaction was
// created). // created).
//
// WARNING: This must be called from the main UI thread, because
// it will generate a DocumentUndo::add() which triggers a
// DocumentUndoObserver::onAddUndoState() notification, which
// updates the Undo History window UI.
void commit(); void commit();
void execute(Cmd* cmd); void execute(Cmd* cmd);