diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a92fbeded..b260892bf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,7 +43,8 @@ else() endif() # All libraries for .exe files -set(all_libs filters-lib aseprite-library gui-lib gfx-lib base-lib ${libs3rdparty} allegro ${sys_libs}) +set(all_libs aseprite-library undo-lib filters-lib gui-lib gfx-lib base-lib + ${libs3rdparty} allegro ${sys_libs}) # Directories where .h files can be found include_directories( @@ -64,6 +65,7 @@ add_subdirectory(base) add_subdirectory(gfx) add_subdirectory(gui) add_subdirectory(filters) +add_subdirectory(undo) ###################################################################### # aseprite library @@ -200,13 +202,19 @@ add_library(aseprite-library raster/algo_polygon.cpp raster/blend.cpp raster/cel.cpp + raster/cel_io.cpp raster/dirty.cpp + raster/dirty_io.cpp raster/gfxobj.cpp raster/image.cpp + raster/image_io.cpp raster/images_collector.cpp raster/layer.cpp + raster/layer_io.cpp raster/mask.cpp + raster/mask_io.cpp raster/palette.cpp + raster/palette_io.cpp raster/path.cpp raster/pen.cpp raster/quantization.cpp @@ -221,7 +229,32 @@ add_library(aseprite-library skin/skin_slider_property.cpp tools/tool.cpp tools/toolbox.cpp - undo/undo_history.cpp + undoers/add_cel.cpp + undoers/add_image.cpp + undoers/add_layer.cpp + undoers/add_palette.cpp + undoers/close_group.cpp + undoers/dirty_area.cpp + undoers/flip_image.cpp + undoers/image_area.cpp + undoers/move_layer.cpp + undoers/open_group.cpp + undoers/raw_data.cpp + undoers/remap_palette.cpp + undoers/remove_cel.cpp + undoers/remove_image.cpp + undoers/remove_layer.cpp + undoers/remove_palette.cpp + undoers/replace_image.cpp + undoers/set_current_frame.cpp + undoers/set_current_layer.cpp + undoers/set_frame_duration.cpp + undoers/set_imgtype.cpp + undoers/set_layer_name.cpp + undoers/set_mask.cpp + undoers/set_palette_colors.cpp + undoers/set_sprite_size.cpp + undoers/set_total_frames.cpp util/autocrop.cpp util/boundary.cpp util/celmove.cpp diff --git a/src/commands/cmd_cel_properties.cpp b/src/commands/cmd_cel_properties.cpp index 088a31049..3e048d962 100644 --- a/src/commands/cmd_cel_properties.cpp +++ b/src/commands/cmd_cel_properties.cpp @@ -132,7 +132,7 @@ void CelPropertiesCommand::onExecute(Context* context) Sprite* sprite_writer = document_writer->getSprite(); Layer* layer_writer = sprite_writer->getCurrentLayer(); Cel* cel_writer = static_cast(layer_writer)->getCel(sprite->getCurrentFrame()); - UndoHistory* undo = document_writer->getUndoHistory(); + undo::UndoHistory* undo = document_writer->getUndoHistory(); int new_opacity = slider_opacity->getValue(); diff --git a/src/commands/cmd_invert_mask.cpp b/src/commands/cmd_invert_mask.cpp index d89fffbf1..6ba40a47f 100644 --- a/src/commands/cmd_invert_mask.cpp +++ b/src/commands/cmd_invert_mask.cpp @@ -76,7 +76,7 @@ void InvertMaskCommand::onExecute(Context* context) else { ActiveDocumentWriter document(context); Sprite* sprite(document->getSprite()); - UndoHistory* undo = document->getUndoHistory(); + undo::UndoHistory* undo = document->getUndoHistory(); /* undo */ if (undo->isEnabled()) { diff --git a/src/commands/cmd_load_mask.cpp b/src/commands/cmd_load_mask.cpp index ffd9006f1..23d4b9228 100644 --- a/src/commands/cmd_load_mask.cpp +++ b/src/commands/cmd_load_mask.cpp @@ -68,7 +68,7 @@ void LoadMaskCommand::onExecute(Context* context) { ActiveDocumentWriter document(context); Sprite* sprite(document->getSprite()); - UndoHistory* undo(document->getUndoHistory()); + undo::UndoHistory* undo(document->getUndoHistory()); base::string filename = m_filename; diff --git a/src/commands/cmd_mask_all.cpp b/src/commands/cmd_mask_all.cpp index 3e8a21ebd..288de778d 100644 --- a/src/commands/cmd_mask_all.cpp +++ b/src/commands/cmd_mask_all.cpp @@ -57,7 +57,7 @@ void MaskAllCommand::onExecute(Context* context) { ActiveDocumentWriter document(context); Sprite* sprite(document->getSprite()); - UndoHistory* undo(document->getUndoHistory()); + undo::UndoHistory* undo(document->getUndoHistory()); // Undo if (undo->isEnabled()) { diff --git a/src/commands/cmd_merge_down_layer.cpp b/src/commands/cmd_merge_down_layer.cpp index 2768d4939..242a7ff83 100644 --- a/src/commands/cmd_merge_down_layer.cpp +++ b/src/commands/cmd_merge_down_layer.cpp @@ -73,7 +73,7 @@ void MergeDownLayerCommand::onExecute(Context* context) { ActiveDocumentWriter document(context); Sprite* sprite(document->getSprite()); - UndoHistory* undo(document->getUndoHistory()); + undo::UndoHistory* undo(document->getUndoHistory()); Layer *src_layer, *dst_layer; Cel *src_cel, *dst_cel; Image *src_image, *dst_image; diff --git a/src/commands/cmd_palette_editor.cpp b/src/commands/cmd_palette_editor.cpp index 973be9c5f..a5c100a55 100644 --- a/src/commands/cmd_palette_editor.cpp +++ b/src/commands/cmd_palette_editor.cpp @@ -654,7 +654,7 @@ void PaletteEntryEditor::updateCurrentSpritePalette(const char* operationName) try { ActiveDocumentWriter document(UIContext::instance()); Sprite* sprite(document->getSprite()); - UndoHistory* undo = document->getUndoHistory(); + undo::UndoHistory* undo = document->getUndoHistory(); Palette* newPalette = get_current_palette(); // System current pal Palette* currentSpritePalette = sprite->getPalette(sprite->getCurrentFrame()); // Sprite current pal int from, to; diff --git a/src/commands/cmd_reselect_mask.cpp b/src/commands/cmd_reselect_mask.cpp index 49b761a43..93c7f2d7c 100644 --- a/src/commands/cmd_reselect_mask.cpp +++ b/src/commands/cmd_reselect_mask.cpp @@ -59,14 +59,12 @@ bool ReselectMaskCommand::onEnabled(Context* context) void ReselectMaskCommand::onExecute(Context* context) { ActiveDocumentWriter document(context); - UndoHistory* undo = document->getUndoHistory(); - - // TODO IMPLEMENT THIS Add an undo action in the history to reverse the change of a Document's int field + undo::UndoHistory* undo = document->getUndoHistory(); // Undo if (undo->isEnabled()) { undo->setLabel("Mask Reselection"); - //undo->undo_set_mask(document); + undo->undo_set_mask(document); } // Make the mask visible again. diff --git a/src/commands/filters/filter_manager_impl.cpp b/src/commands/filters/filter_manager_impl.cpp index aedcd68e3..067e058f6 100644 --- a/src/commands/filters/filter_manager_impl.cpp +++ b/src/commands/filters/filter_manager_impl.cpp @@ -203,7 +203,7 @@ void FilterManagerImpl::apply() } if (!cancelled) { - UndoHistory* undo = m_document->getUndoHistory(); + undo::UndoHistory* undo = m_document->getUndoHistory(); // Undo stuff if (undo->isEnabled()) { @@ -230,7 +230,7 @@ void FilterManagerImpl::applyToTarget() // Initialize writting operation DocumentReader doc_reader(m_document); DocumentWriter doc_writer(doc_reader); - UndoHistory* undo = m_document->getUndoHistory(); + undo::UndoHistory* undo = m_document->getUndoHistory(); // Open group of undo operations if (images.size() > 1) { diff --git a/src/dialogs/aniedit.cpp b/src/dialogs/aniedit.cpp index 65ebf65fa..c5000e9d7 100644 --- a/src/dialogs/aniedit.cpp +++ b/src/dialogs/aniedit.cpp @@ -715,11 +715,11 @@ static bool anieditor_msg_proc(JWidget widget, JMessage msg) /* undo */ if (command && strcmp(command->short_name(), CommandId::Undo) == 0) { const DocumentReader document(const_cast(anieditor->document)); - const UndoHistory* undo = document->getUndoHistory(); + const undo::UndoHistory* undo = document->getUndoHistory(); if (undo->canUndo()) { DocumentWriter document_writer(document); - UndoHistory* undo_writer = document_writer->getUndoHistory(); + undo::UndoHistory* undo_writer = document_writer->getUndoHistory(); undo_writer->doUndo(); @@ -734,11 +734,11 @@ static bool anieditor_msg_proc(JWidget widget, JMessage msg) /* redo */ if (command && strcmp(command->short_name(), CommandId::Redo) == 0) { const DocumentReader document(const_cast(anieditor->document)); - const UndoHistory* undo = document->getUndoHistory(); + const undo::UndoHistory* undo = document->getUndoHistory(); if (undo->canRedo()) { DocumentWriter document_writer(document); - UndoHistory* undo_writer = document_writer->getUndoHistory(); + undo::UndoHistory* undo_writer = document_writer->getUndoHistory(); undo_writer->doRedo(); diff --git a/src/dialogs/maskcol.cpp b/src/dialogs/maskcol.cpp index d2c00b8f4..e6a36d475 100644 --- a/src/dialogs/maskcol.cpp +++ b/src/dialogs/maskcol.cpp @@ -128,7 +128,7 @@ void dialogs_mask_color(Document* document) if (window->get_killer() == button_ok) { DocumentWriter documentWriter(documentReader); - UndoHistory* undo = document->getUndoHistory(); + undo::UndoHistory* undo = document->getUndoHistory(); Mask* mask; /* undo */ diff --git a/src/document.cpp b/src/document.cpp index d2a25fa9f..099423ad5 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -35,6 +35,8 @@ #include "undo/undo_history.h" #include "util/boundary.h" +using namespace undo; + Document::Document(Sprite* sprite) : m_id(WithoutDocumentId) , m_sprite(sprite) diff --git a/src/document.h b/src/document.h index 449d16b86..986b8a1c5 100644 --- a/src/document.h +++ b/src/document.h @@ -31,11 +31,14 @@ class FormatOptions; class Image; class Mask; class Mutex; -class ObjectsContainer; class Sprite; -class UndoHistory; struct _BoundSeg; +namespace undo { + class ObjectsContainer; + class UndoHistory; +} + struct PreferredEditorSettings { int scroll_x; @@ -70,10 +73,10 @@ public: void setId(DocumentId id) { m_id = id; } const Sprite* getSprite() const { return m_sprite; } - const UndoHistory* getUndoHistory() const { return m_undoHistory; } + const undo::UndoHistory* getUndoHistory() const { return m_undoHistory; } Sprite* getSprite() { return m_sprite; } - UndoHistory* getUndoHistory() { return m_undoHistory; } + undo::UndoHistory* getUndoHistory() { return m_undoHistory; } ////////////////////////////////////////////////////////////////////// // File related properties @@ -160,9 +163,18 @@ private: // Unique identifier for this document (it is assigned by Documents class). DocumentId m_id; + // The main sprite. UniquePtr m_sprite; - UniquePtr m_objects; - UniquePtr m_undoHistory; + + // Collection of objects used by UndoHistory to reference deleted + // objects that are re-created by an Undoer. The container keeps an + // ID that is saved in the serialization process, and loaded in the + // deserialization process. The ID can be used by different undoers + // to keep references to deleted objects. + UniquePtr m_objects; + + // Stack of undoers to undo operations. + UniquePtr m_undoHistory; // Document's file name (from where it was loaded, where it is saved). std::string m_filename; diff --git a/src/objects_container_impl.cpp b/src/objects_container_impl.cpp index 719b1faa0..48d3f7ebc 100644 --- a/src/objects_container_impl.cpp +++ b/src/objects_container_impl.cpp @@ -20,6 +20,8 @@ #include "objects_container_impl.h" +using namespace undo; + ObjectsContainerImpl::ObjectsContainerImpl() { m_idCounter = 0; diff --git a/src/objects_container_impl.h b/src/objects_container_impl.h index 8ecf2ef2b..2dae97963 100644 --- a/src/objects_container_impl.h +++ b/src/objects_container_impl.h @@ -23,7 +23,7 @@ #include -class ObjectsContainerImpl : public ObjectsContainer +class ObjectsContainerImpl : public undo::ObjectsContainer { public: ObjectsContainerImpl(); @@ -31,15 +31,15 @@ public: // ObjectsContainer Implementation - ObjectId addObject(void* object); - void insertObject(ObjectId id, void* object); - void removeObject(ObjectId id); - void* getObject(ObjectId id); + undo::ObjectId addObject(void* object); + void insertObject(undo::ObjectId id, void* object); + void removeObject(undo::ObjectId id); + void* getObject(undo::ObjectId id); private: - ObjectId m_idCounter; - std::map m_idToPtr; - std::map m_ptrToId; + undo::ObjectId m_idCounter; + std::map m_idToPtr; + std::map m_ptrToId; }; #endif diff --git a/src/raster/cel_io.cpp b/src/raster/cel_io.cpp new file mode 100644 index 000000000..3f93df111 --- /dev/null +++ b/src/raster/cel_io.cpp @@ -0,0 +1,74 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "raster/cel_io.h" + +#include "base/serialization.h" +#include "base/unique_ptr.h" +#include "raster/cel.h" + +#include + +namespace raster { + +using namespace base::serialization; +using namespace base::serialization::little_endian; + +// Serialized Cel data: +// +// WORD Frame +// WORD Image index +// WORD[2] X, Y +// WORD Opacity + +void write_cel(std::ostream& os, Cel* cel) +{ + // ObjectId cel_id = objects->addObject(cel); + // write_raw_uint32(cel_id); + + write16(os, cel->frame); + write16(os, cel->image); + write16(os, (int16_t)cel->x); + write16(os, (int16_t)cel->y); + write16(os, cel->opacity); + + // objects->removeObject(cel_id); +} + +Cel* read_cel(std::istream& is) +{ + // ObjectId cel_id = read32(); + + int frame = read16(is); + int imageIndex = read16(is); + int x = (int16_t)read16(is); + int y = (int16_t)read16(is); + int opacity = read16(is); + + UniquePtr cel(cel_new(frame, imageIndex)); + + cel_set_position(cel, x, y); + cel_set_opacity(cel, opacity); + + // objects->insertObject(cel_id, cel); + return cel.release(); +} + +} diff --git a/src/raster/cel_io.h b/src/raster/cel_io.h new file mode 100644 index 000000000..9b9cee6a9 --- /dev/null +++ b/src/raster/cel_io.h @@ -0,0 +1,33 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef RASTER_CEL_IO_H_INCLUDED +#define RASTER_CEL_IO_H_INCLUDED + +#include + +class Cel; + +namespace raster { + +void write_cel(std::ostream& os, Cel* cel); +Cel* read_cel(std::istream& is); + +} // namespace raster + +#endif diff --git a/src/raster/dirty_io.cpp b/src/raster/dirty_io.cpp new file mode 100644 index 000000000..c4141474f --- /dev/null +++ b/src/raster/dirty_io.cpp @@ -0,0 +1,117 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "raster/dirty_io.h" + +#include "base/serialization.h" +#include "base/unique_ptr.h" +#include "raster/dirty.h" + +#include + +namespace raster { + +using namespace base::serialization; +using namespace base::serialization::little_endian; + +// Serialized Dirty data: +// +// BYTE image type +// WORD[4] x1, y1, x2, y2 +// WORD rows +// for each row +// WORD[2] y, columns +// for each column +// WORD[2] x, w +// for each pixel ("w" times) +// BYTE[4] for RGB images, or +// BYTE[2] for Grayscale images, or +// BYTE for Indexed images + +void write_dirty(std::ostream& os, Dirty* dirty) +{ + write8(os, dirty->getImgType()); + write16(os, dirty->x1()); + write16(os, dirty->y1()); + write16(os, dirty->x2()); + write16(os, dirty->y2()); + write16(os, dirty->getRowsCount()); + + for (int v=0; vgetRowsCount(); v++) { + const Dirty::Row& row = dirty->getRow(v); + + write16(os, row.y); + write16(os, row.cols.size()); + + for (size_t u=0; ux); + write16(os, row.cols[u]->w); + + size_t size = dirty->getLineSize(row.cols[u]->w); + os.write((char*)&row.cols[u]->data[0], size); + } + } +} + +Dirty* read_dirty(std::istream& is) +{ + int u, v, x, y, w; + int imgtype = read8(is); + int x1 = read16(is); + int y1 = read16(is); + int x2 = read16(is); + int y2 = read16(is); + UniquePtr dirty(new Dirty(imgtype, x1, y1, x2, y2)); + + int noRows = read16(is); + if (noRows > 0) { + dirty->m_rows.resize(noRows); + + for (v=0; vgetRowsCount(); v++) { + y = read16(is); + + UniquePtr row(new Dirty::Row(y)); + + int noCols = read16(is); + row->cols.resize(noCols); + + for (u=0; u col(new Dirty::Col(x, w)); + + int size = dirty->getLineSize(col->w); + ASSERT(size > 0); + + col->data.resize(size); + is.read((char*)&col->data[0], size); + + row->cols[u] = col.release(); + } + + dirty->m_rows[v] = row.release(); + } + } + + return dirty.release(); +} + +} diff --git a/src/raster/dirty_io.h b/src/raster/dirty_io.h new file mode 100644 index 000000000..4b983d2e1 --- /dev/null +++ b/src/raster/dirty_io.h @@ -0,0 +1,33 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef RASTER_DIRTY_IO_H_INCLUDED +#define RASTER_DIRTY_IO_H_INCLUDED + +#include + +class Dirty; + +namespace raster { + +void write_dirty(std::ostream& os, Dirty* dirty); +Dirty* read_dirty(std::istream& is); + +} // namespace raster + +#endif diff --git a/src/raster/image_io.cpp b/src/raster/image_io.cpp new file mode 100644 index 000000000..ac922a210 --- /dev/null +++ b/src/raster/image_io.cpp @@ -0,0 +1,75 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "raster/image_io.h" + +#include "base/serialization.h" +#include "base/unique_ptr.h" +#include "raster/image.h" + +#include + +namespace raster { + +using namespace base::serialization; +using namespace base::serialization::little_endian; + +// Serialized Image data: +// +// DWORD image ID +// BYTE image type +// WORD[2] w, h +// DWORD mask color +// for each line ("h" times) +// for each pixel ("w" times) +// BYTE[4] for RGB images, or +// BYTE[2] for Grayscale images, or +// BYTE for Indexed images + +void write_image(std::ostream& os, Image* image) +{ + write8(os, image->imgtype); // Imgtype + write16(os, image->w); // Width + write16(os, image->h); // Height + write32(os, image->mask_color); // Mask color + + int size = image_line_size(image, image->w); + for (int c=0; ch; c++) + os.write((char*)image->line[c], size); +} + +Image* read_image(std::istream& is) +{ + int imgtype = read8(is); // Imgtype + int width = read16(is); // Width + int height = read16(is); // Height + uint32_t maskColor = read32(is); // Mask color + + UniquePtr image(image_new(imgtype, width, height)); + int size = image_line_size(image, image->w); + + for (int c=0; ch; c++) + is.read((char*)image->line[c], size); + + image->mask_color = maskColor; + return image.release(); +} + +} diff --git a/src/raster/image_io.h b/src/raster/image_io.h new file mode 100644 index 000000000..e3e7100fa --- /dev/null +++ b/src/raster/image_io.h @@ -0,0 +1,33 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef RASTER_IMAGE_IO_H_INCLUDED +#define RASTER_IMAGE_IO_H_INCLUDED + +#include + +class Image; + +namespace raster { + +void write_image(std::ostream& os, Image* image); +Image* read_image(std::istream& is); + +} // namespace raster + +#endif diff --git a/src/raster/layer_io.cpp b/src/raster/layer_io.cpp new file mode 100644 index 000000000..25751cc55 --- /dev/null +++ b/src/raster/layer_io.cpp @@ -0,0 +1,156 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "raster/layer_io.h" + +#include "base/serialization.h" +#include "base/unique_ptr.h" +#include "raster/cel.h" +#include "raster/layer.h" +#include "raster/sprite.h" +#include "raster/stock.h" + +#include +#include + +namespace raster { + +using namespace base::serialization; +using namespace base::serialization::little_endian; + +// Serialized Layer data: + +void write_layer(std::ostream& os, LayerSubObjectsSerializer* subObjects, Layer* layer) +{ + std::string name = layer->getName(); + + write16(os, name.size()); // Name length + if (!name.empty()) + os.write(name.c_str(), name.size()); // Name + + write8(os, *layer->flags_addr()); // Flags + write16(os, layer->getType()); // Type + + switch (layer->getType()) { + + case GFXOBJ_LAYER_IMAGE: { + // Number of cels + write16(os, static_cast(layer)->getCelsCount()); + + CelIterator it = static_cast(layer)->getCelBegin(); + CelIterator end = static_cast(layer)->getCelEnd(); + + for (; it != end; ++it) { + Cel* cel = *it; + subObjects->write_cel(os, cel); + + Image* image = layer->getSprite()->getStock()->getImage(cel->image); + ASSERT(image != NULL); + + subObjects->write_image(os, image); + } + break; + } + + case GFXOBJ_LAYER_FOLDER: { + LayerIterator it = static_cast(layer)->get_layer_begin(); + LayerIterator end = static_cast(layer)->get_layer_end(); + + // Number of sub-layers + write16(os, static_cast(layer)->get_layers_count()); + + for (; it != end; ++it) + subObjects->write_layer(os, *it); + break; + } + + } +} + +Layer* read_layer(std::istream& is, LayerSubObjectsSerializer* subObjects, Sprite* sprite) +{ + int flags, layer_type; + UniquePtr layer; + + uint16_t name_length = read16(is); // Name length + std::vector name(name_length+1); + if (name_length > 0) { + is.read(&name[0], name_length); // Name + name[name_length] = 0; + } + else + name[0] = 0; + + flags = read8(is); // Flags + layer_type = read16(is); // Type + + switch (layer_type) { + + case GFXOBJ_LAYER_IMAGE: { + // Create layer + layer.reset(new LayerImage(sprite)); + + // Read cels + int cels = read16(is); // Number of cels + for (int c=0; cread_cel(is); + + // Add the cel in the layer + static_cast(layer.get())->addCel(cel); + + // Read the cel's image + Image* image = subObjects->read_image(is); + + sprite->getStock()->replaceImage(cel->image, image); + } + break; + } + + case GFXOBJ_LAYER_FOLDER: { + // Create the layer set + layer.reset(new LayerFolder(sprite)); + + // Number of sub-layers + int layers = read16(is); + for (int c=0; cread_layer(is); + if (child) + static_cast(layer.get())->add_layer(child); + else + break; + } + break; + } + + default: + throw InvalidLayerType("Invalid layer type found in stream"); + + } + + if (layer != NULL) { + layer->setName(&name[0]); + *layer->flags_addr() = flags; + } + + return layer.release(); +} + +} diff --git a/src/raster/layer_io.h b/src/raster/layer_io.h new file mode 100644 index 000000000..6044c7b89 --- /dev/null +++ b/src/raster/layer_io.h @@ -0,0 +1,62 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef RASTER_LAYER_IO_H_INCLUDED +#define RASTER_LAYER_IO_H_INCLUDED + +#include "base/exception.h" + +#include + +class Cel; +class Image; +class Layer; +class Sprite; + +namespace raster { + +// Thrown when a invalid layer type is read from the istream. +class InvalidLayerType : public base::Exception +{ +public: + InvalidLayerType(const char* msg) throw() : base::Exception(msg) { } +}; + +// Interface used to read sub-objects of a layer. +class LayerSubObjectsSerializer +{ +public: + virtual ~LayerSubObjectsSerializer() { } + + // How to write cels, images, and sub-layers + virtual void write_cel(std::ostream& os, Cel* cel) = 0; + virtual void write_image(std::ostream& os, Image* image) = 0; + virtual void write_layer(std::ostream& os, Layer* layer) = 0; + + // How to read cels, images, and sub-layers + virtual Cel* read_cel(std::istream& is) = 0; + virtual Image* read_image(std::istream& is) = 0; + virtual Layer* read_layer(std::istream& is) = 0; +}; + +void write_layer(std::ostream& os, LayerSubObjectsSerializer* subObjects, Layer* layer); +Layer* read_layer(std::istream& is, LayerSubObjectsSerializer* subObjects, Sprite* sprite); + +} // namespace raster + +#endif diff --git a/src/raster/mask_io.cpp b/src/raster/mask_io.cpp new file mode 100644 index 000000000..aa420dd51 --- /dev/null +++ b/src/raster/mask_io.cpp @@ -0,0 +1,77 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "raster/mask_io.h" + +#include "base/serialization.h" +#include "base/unique_ptr.h" +#include "raster/mask.h" + +#include + +namespace raster { + +using namespace base::serialization; +using namespace base::serialization::little_endian; + +// Serialized Mask data: +// +// WORD[4] x, y, w, h +// for each line ("h" times) +// for each packet ("((w+7)/8)" times) +// BYTE 8 pixels of the mask +// BYTE for Indexed images + +void write_mask(std::ostream& os, Mask* mask) +{ + write16(os, mask->x); // Xpos + write16(os, mask->y); // Ypos + write16(os, mask->bitmap ? mask->w: 0); // Width + write16(os, mask->bitmap ? mask->h: 0); // Height + + if (mask->bitmap) { + int size = (mask->w+7)/8; + + for (int c=0; ch; c++) + os.write((char*)mask->bitmap->line[c], size); + } +} + +Mask* read_mask(std::istream& is) +{ + int x = read16(is); // Xpos + int y = read16(is); // Ypos + int w = read16(is); // Width + int h = read16(is); // Height + + UniquePtr mask(mask_new()); + + if (w > 0 && h > 0) { + int size = (w+7)/8; + + mask->add(x, y, w, h); + for (int c=0; ch; c++) + is.read((char*)mask->bitmap->line[c], size); + } + + return mask.release(); +} + +} diff --git a/src/raster/mask_io.h b/src/raster/mask_io.h new file mode 100644 index 000000000..096042504 --- /dev/null +++ b/src/raster/mask_io.h @@ -0,0 +1,33 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef RASTER_MASK_IO_H_INCLUDED +#define RASTER_MASK_IO_H_INCLUDED + +#include + +class Mask; + +namespace raster { + +void write_mask(std::ostream& os, Mask* mask); +Mask* read_mask(std::istream& is); + +} // namespace raster + +#endif diff --git a/src/raster/palette_io.cpp b/src/raster/palette_io.cpp new file mode 100644 index 000000000..db8873d1b --- /dev/null +++ b/src/raster/palette_io.cpp @@ -0,0 +1,67 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "raster/palette_io.h" + +#include "base/serialization.h" +#include "base/unique_ptr.h" +#include "raster/palette.h" + +#include + +namespace raster { + +using namespace base::serialization; +using namespace base::serialization::little_endian; + +// Serialized Palette data: +// +// WORD Frame +// WORD Number of colors +// for each color ("ncolors" times) +// DWORD _rgba color + +void write_palette(std::ostream& os, Palette* palette) +{ + write16(os, palette->getFrame()); // Frame + write16(os, palette->size()); // Number of colors + + for (int c=0; csize(); c++) { + uint32_t color = palette->getEntry(c); + write32(os, color); + } +} + +Palette* read_palette(std::istream& is) +{ + int frame = read16(is); // Frame + int ncolors = read16(is); // Number of colors + + UniquePtr palette(new Palette(frame, ncolors)); + + for (int c=0; csetEntry(c, color); + } + + return palette.release(); +} + +} diff --git a/src/raster/palette_io.h b/src/raster/palette_io.h new file mode 100644 index 000000000..d1fd28da9 --- /dev/null +++ b/src/raster/palette_io.h @@ -0,0 +1,33 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef RASTER_PALETTE_IO_H_INCLUDED +#define RASTER_PALETTE_IO_H_INCLUDED + +#include + +class Palette; + +namespace raster { + +void write_palette(std::ostream& os, Palette* palette); +Palette* read_palette(std::istream& is); + +} // namespace raster + +#endif diff --git a/src/raster/sprite.cpp b/src/raster/sprite.cpp index 41922b133..6d8eb9d91 100644 --- a/src/raster/sprite.cpp +++ b/src/raster/sprite.cpp @@ -373,7 +373,7 @@ void Sprite::getCels(CelList& cels) getFolder()->getCels(cels); } -void Sprite::remapImages(int frame_from, int frame_to, const std::vector& mapping) +void Sprite::remapImages(int frame_from, int frame_to, const std::vector& mapping) { ASSERT(m_imgtype == IMAGE_INDEXED); ASSERT(mapping.size() == 256); diff --git a/src/raster/sprite.h b/src/raster/sprite.h index 3e3d1bdf0..7f5e95b36 100644 --- a/src/raster/sprite.h +++ b/src/raster/sprite.h @@ -125,7 +125,7 @@ public: void getCels(CelList& cels); - void remapImages(int frame_from, int frame_to, const std::vector& mapping); + void remapImages(int frame_from, int frame_to, const std::vector& mapping); //////////////////////////////////////// // Drawing diff --git a/src/undo/CMakeLists.txt b/src/undo/CMakeLists.txt new file mode 100644 index 000000000..ff4afc810 --- /dev/null +++ b/src/undo/CMakeLists.txt @@ -0,0 +1,7 @@ +# ASEPRITE Undo Library +# Copyright (C) 2001-2011 David Capello + +add_library(undo-lib + undo_history.cpp + undo_history_backward.cpp + undoers_stack.cpp) diff --git a/src/undo/LICENSE.txt b/src/undo/LICENSE.txt new file mode 100644 index 000000000..5c3b05a7c --- /dev/null +++ b/src/undo/LICENSE.txt @@ -0,0 +1,29 @@ +ASEPRITE Undo Library +Copyright (c) 2001-2011 David Capello +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of the author nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/undo/object_id.h b/src/undo/object_id.h new file mode 100644 index 000000000..056c519d2 --- /dev/null +++ b/src/undo/object_id.h @@ -0,0 +1,16 @@ +// ASEPRITE Undo Library +// Copyright (C) 2001-2011 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef UNDO_OBJECT_ID_H_INCLUDED +#define UNDO_OBJECT_ID_H_INCLUDED + +namespace undo { + +typedef uint32_t ObjectId; + +} // namespace undo + +#endif // UNDO_OBJECT_ID_H_INCLUDED diff --git a/src/undo/objects_container.h b/src/undo/objects_container.h index 2ae91e78c..3028b2395 100644 --- a/src/undo/objects_container.h +++ b/src/undo/objects_container.h @@ -1,27 +1,16 @@ -/* ASE - Allegro Sprite Editor - * Copyright (C) 2001-2011 David Capello - * - * 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 - */ +// ASEPRITE Undo Library +// Copyright (C) 2001-2011 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. #ifndef UNDO_OBJECTS_CONTAINER_H_INCLUDED #define UNDO_OBJECTS_CONTAINER_H_INCLUDED #include "base/exception.h" +#include "undo/object_id.h" -typedef uint32_t ObjectId; +namespace undo { // Thrown when you use ObjectsContainer::insertObject() with an // existent ID or pointer. @@ -90,4 +79,6 @@ public: }; -#endif +} // namespace undo + +#endif // UNDO_OBJECTS_CONTAINER_H_INCLUDED diff --git a/src/undo/undo_exception.h b/src/undo/undo_exception.h new file mode 100644 index 000000000..e7fe87105 --- /dev/null +++ b/src/undo/undo_exception.h @@ -0,0 +1,22 @@ +// ASEPRITE Undo Library +// Copyright (C) 2001-2011 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef UNDO_UNDO_EXCEPTION_H_INCLUDED +#define UNDO_UNDO_EXCEPTION_H_INCLUDED + +#include "base/exception.h" + +namespace undo { + +class UndoException : public base::Exception +{ +public: + UndoException(const char* msg) throw() : base::Exception(msg) { } +}; + +} // namespace undo + +#endif // UNDO_UNDO_EXCEPTION_H_INCLUDED diff --git a/src/undo/undo_history.cpp b/src/undo/undo_history.cpp index c5233a4ba..e08011820 100644 --- a/src/undo/undo_history.cpp +++ b/src/undo/undo_history.cpp @@ -1,286 +1,20 @@ -/* ASE - Allegro Sprite Editor - * Copyright (C) 2001-2011 David Capello - * - * 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 - */ +// ASEPRITE Undo Library +// Copyright (C) 2001-2011 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. #include "config.h" #include "undo/undo_history.h" -#include "base/memory.h" -#include "context.h" -#include "document.h" -#include "documents.h" -#include "raster/cel.h" -#include "raster/dirty.h" -#include "raster/image.h" -#include "raster/layer.h" -#include "raster/mask.h" -#include "raster/palette.h" -#include "raster/sprite.h" -#include "raster/stock.h" -#include "ui_context.h" #include "undo/objects_container.h" +#include "undo/undoer.h" +#include "undo/undoers_stack.h" -#include -#include -#include -#include -#include -#include +#include // TODO remove this when get_config_int() is removed from here -// Undo state -enum { - DO_UNDO, - DO_REDO, -}; - -// Undo types -enum { - // group - UNDO_TYPE_OPEN, - UNDO_TYPE_CLOSE, - - // data management - UNDO_TYPE_DATA, - - // image management - UNDO_TYPE_IMAGE, - UNDO_TYPE_FLIP, - UNDO_TYPE_DIRTY, - - // stock management - UNDO_TYPE_ADD_IMAGE, - UNDO_TYPE_REMOVE_IMAGE, - UNDO_TYPE_REPLACE_IMAGE, - - // cel management - UNDO_TYPE_ADD_CEL, - UNDO_TYPE_REMOVE_CEL, - - // layer management - UNDO_TYPE_SET_LAYER_NAME, - UNDO_TYPE_ADD_LAYER, - UNDO_TYPE_REMOVE_LAYER, - UNDO_TYPE_MOVE_LAYER, - UNDO_TYPE_SET_LAYER, - - // palette management - UNDO_TYPE_ADD_PALETTE, - UNDO_TYPE_REMOVE_PALETTE, - UNDO_TYPE_SET_PALETTE_COLORS, - UNDO_TYPE_REMAP_PALETTE, - - // misc - UNDO_TYPE_SET_MASK, - UNDO_TYPE_SET_IMGTYPE, - UNDO_TYPE_SET_SIZE, - UNDO_TYPE_SET_FRAME, - UNDO_TYPE_SET_FRAMES, - UNDO_TYPE_SET_FRLEN, -}; - -struct UndoChunkData; -struct UndoChunkImage; -struct UndoChunkFlip; -struct UndoChunkDirty; -struct UndoChunkAddImage; -struct UndoChunkRemoveImage; -struct UndoChunkReplaceImage; -struct UndoChunkAddCel; -struct UndoChunkRemoveCel; -struct UndoChunkSetLayerName; -struct UndoChunkAddLayer; -struct UndoChunkRemoveLayer; -struct UndoChunkMoveLayer; -struct UndoChunkSetLayer; -struct UndoChunkAddPalette; -struct UndoChunkRemovePalette; -struct UndoChunkSetPaletteColors; -struct UndoChunkRemapPalette; -struct UndoChunkSetMask; -struct UndoChunkSetImgType; -struct UndoChunkSetSize; -struct UndoChunkSetFrame; -struct UndoChunkSetFrames; -struct UndoChunkSetFrlen; - -struct UndoChunk -{ - int type; - int size; - const char *label; -}; - -static UndoChunk* undo_chunk_new(UndoStream* stream, int type, int size); -static void undo_chunk_free(UndoChunk* chunk); - -typedef std::list ChunksList; - -#include "undo_stream.h" - -struct UndoAction -{ - const char *name; - void (*invert)(UndoStream* stream, UndoChunk* chunk); -}; - -static int count_undo_groups(UndoStream* undo_stream); -static bool out_of_group(UndoStream* undo_stream); - -// Undo actions - -static void chunk_open_new(UndoStream* stream); -static void chunk_open_invert(UndoStream* stream, UndoChunk* chunk); - -static void chunk_close_new(UndoStream* stream); -static void chunk_close_invert(UndoStream* stream, UndoChunk* chunk); - -static void chunk_data_new(UndoStream* stream, void* object, void* fieldAddress, int fieldSize); -static void chunk_data_invert(UndoStream* stream, UndoChunkData *chunk); - -static void chunk_image_new(UndoStream* stream, Image* image, int x, int y, int w, int h); -static void chunk_image_invert(UndoStream* stream, UndoChunkImage* chunk); - -static void chunk_flip_new(UndoStream* stream, Image* image, int x1, int y1, int x2, int y2, bool horz); -static void chunk_flip_invert(UndoStream* stream, UndoChunkFlip *chunk); - -static void chunk_dirty_new(UndoStream* stream, Image* image, Dirty *dirty); -static void chunk_dirty_invert(UndoStream* stream, UndoChunkDirty *chunk); - -static void chunk_add_image_new(UndoStream* stream, Stock *stock, int image_index); -static void chunk_add_image_invert(UndoStream* stream, UndoChunkAddImage* chunk); - -static void chunk_remove_image_new(UndoStream* stream, Stock *stock, int image_index); -static void chunk_remove_image_invert(UndoStream* stream, UndoChunkRemoveImage* chunk); - -static void chunk_replace_image_new(UndoStream* stream, Stock *stock, int image_index); -static void chunk_replace_image_invert(UndoStream* stream, UndoChunkReplaceImage* chunk); - -static void chunk_add_cel_new(UndoStream* stream, Layer* layer, Cel* cel); -static void chunk_add_cel_invert(UndoStream* stream, UndoChunkAddCel* chunk); - -static void chunk_remove_cel_new(UndoStream* stream, Layer* layer, Cel* cel); -static void chunk_remove_cel_invert(UndoStream* stream, UndoChunkRemoveCel* chunk); - -static void chunk_set_layer_name_new(UndoStream* stream, Layer *layer); -static void chunk_set_layer_name_invert(UndoStream* stream, UndoChunkSetLayerName* chunk); - -static void chunk_add_layer_new(UndoStream* stream, Layer* set, Layer* layer); -static void chunk_add_layer_invert(UndoStream* stream, UndoChunkAddLayer* chunk); - -static void chunk_remove_layer_new(UndoStream* stream, Layer* layer); -static void chunk_remove_layer_invert(UndoStream* stream, UndoChunkRemoveLayer* chunk); - -static void chunk_move_layer_new(UndoStream* stream, Layer* layer); -static void chunk_move_layer_invert(UndoStream* stream, UndoChunkMoveLayer* chunk); - -static void chunk_set_layer_new(UndoStream* stream, Sprite *sprite); -static void chunk_set_layer_invert(UndoStream* stream, UndoChunkSetLayer* chunk); - -static void chunk_add_palette_new(UndoStream* stream, Sprite *sprite, Palette* palette); -static void chunk_add_palette_invert(UndoStream* stream, UndoChunkAddPalette *chunk); - -static void chunk_remove_palette_new(UndoStream* stream, Sprite *sprite, Palette* palette); -static void chunk_remove_palette_invert(UndoStream* stream, UndoChunkRemovePalette *chunk); - -static void chunk_set_palette_colors_new(UndoStream* stream, Sprite *sprite, Palette* palette, int from, int to); -static void chunk_set_palette_colors_invert(UndoStream* stream, UndoChunkSetPaletteColors *chunk); - -static void chunk_remap_palette_new(UndoStream* stream, Sprite* sprite, int frame_from, int frame_to, const std::vector& mapping); -static void chunk_remap_palette_invert(UndoStream* stream, UndoChunkRemapPalette *chunk); - -static void chunk_set_mask_new(UndoStream* stream, Document* document); -static void chunk_set_mask_invert(UndoStream* stream, UndoChunkSetMask* chunk); - -static void chunk_set_imgtype_new(UndoStream* stream, Sprite *sprite); -static void chunk_set_imgtype_invert(UndoStream* stream, UndoChunkSetImgType *chunk); - -static void chunk_set_size_new(UndoStream* stream, Sprite *sprite); -static void chunk_set_size_invert(UndoStream* stream, UndoChunkSetSize *chunk); - -static void chunk_set_frame_new(UndoStream* stream, Sprite *sprite); -static void chunk_set_frame_invert(UndoStream* stream, UndoChunkSetFrame *chunk); - -static void chunk_set_frames_new(UndoStream* stream, Sprite *sprite); -static void chunk_set_frames_invert(UndoStream* stream, UndoChunkSetFrames *chunk); - -static void chunk_set_frlen_new(UndoStream* stream, Sprite *sprite, int frame); -static void chunk_set_frlen_invert(UndoStream* stream, UndoChunkSetFrlen *chunk); - -#define DECL_UNDO_ACTION(name) \ - { #name, (void (*)(UndoStream* , UndoChunk*))chunk_##name##_invert } - -// WARNING: in the same order as in UNDO_TYPEs -static UndoAction undo_actions[] = { - DECL_UNDO_ACTION(open), - DECL_UNDO_ACTION(close), - DECL_UNDO_ACTION(data), - DECL_UNDO_ACTION(image), - DECL_UNDO_ACTION(flip), - DECL_UNDO_ACTION(dirty), - DECL_UNDO_ACTION(add_image), - DECL_UNDO_ACTION(remove_image), - DECL_UNDO_ACTION(replace_image), - DECL_UNDO_ACTION(add_cel), - DECL_UNDO_ACTION(remove_cel), - DECL_UNDO_ACTION(set_layer_name), - DECL_UNDO_ACTION(add_layer), - DECL_UNDO_ACTION(remove_layer), - DECL_UNDO_ACTION(move_layer), - DECL_UNDO_ACTION(set_layer), - DECL_UNDO_ACTION(add_palette), - DECL_UNDO_ACTION(remove_palette), - DECL_UNDO_ACTION(set_palette_colors), - DECL_UNDO_ACTION(remap_palette), - DECL_UNDO_ACTION(set_mask), - DECL_UNDO_ACTION(set_imgtype), - DECL_UNDO_ACTION(set_size), - DECL_UNDO_ACTION(set_frame), - DECL_UNDO_ACTION(set_frames), - DECL_UNDO_ACTION(set_frlen), -}; - -// Raw data - -static Dirty *read_raw_dirty(uint8_t* raw_data); -static uint8_t* write_raw_dirty(uint8_t* raw_data, Dirty* dirty); -static int get_raw_dirty_size(Dirty *dirty); - -static Image* read_raw_image(ObjectsContainer* objects, uint8_t* raw_data); -static uint8_t* write_raw_image(ObjectsContainer* objects, uint8_t* raw_data, Image* image); -static int get_raw_image_size(Image* image); - -static Cel* read_raw_cel(ObjectsContainer* objects, uint8_t* raw_data); -static uint8_t* write_raw_cel(ObjectsContainer* objects, uint8_t* raw_data, Cel* cel); -static int get_raw_cel_size(Cel* cel); - -static Layer* read_raw_layer(ObjectsContainer* objects, uint8_t* raw_data); -static uint8_t* write_raw_layer(ObjectsContainer* objects, uint8_t* raw_data, Layer* layer); -static int get_raw_layer_size(Layer* layer); - -static Palette* read_raw_palette(uint8_t* raw_data); -static uint8_t* write_raw_palette(uint8_t* raw_data, Palette* palette); -static int get_raw_palette_size(Palette* palette); - -static Mask* read_raw_mask(uint8_t* raw_data); -static uint8_t* write_raw_mask(uint8_t* raw_data, Mask* mask); -static int get_raw_mask_size(Mask* mask); - -////////////////////////////////////////////////////////////////////// +using namespace undo; UndoHistory::UndoHistory(ObjectsContainer* objects) : m_objects(objects) @@ -290,20 +24,20 @@ UndoHistory::UndoHistory(ObjectsContainer* objects) m_enabled = true; m_label = NULL; - m_undoStream = new UndoStream(this); + m_undoers = new UndoersStack(this); try { - m_redoStream = new UndoStream(this); + m_redoers = new UndoersStack(this); } catch (...) { - delete m_undoStream; + delete m_undoers; throw; } } UndoHistory::~UndoHistory() { - delete m_undoStream; - delete m_redoStream; + delete m_undoers; + delete m_redoers; } bool UndoHistory::isEnabled() const @@ -318,28 +52,28 @@ void UndoHistory::setEnabled(bool state) bool UndoHistory::canUndo() const { - return !m_undoStream->empty(); + return !m_undoers->empty(); } bool UndoHistory::canRedo() const { - return !m_redoStream->empty(); + return !m_redoers->empty(); } void UndoHistory::doUndo() { - runUndo(DO_UNDO); + runUndo(UndoDirection); } void UndoHistory::doRedo() { - runUndo(DO_REDO); + runUndo(RedoDirection); } void UndoHistory::clearRedo() { - if (!m_redoStream->empty()) - m_redoStream->clear(); + if (!m_redoers->empty()) + m_redoers->clear(); } const char* UndoHistory::getLabel() @@ -354,22 +88,18 @@ void UndoHistory::setLabel(const char* label) const char* UndoHistory::getNextUndoLabel() const { - UndoChunk* chunk; - ASSERT(canUndo()); - chunk = *m_undoStream->begin(); - return chunk->label; + UndoersStack::Item* item = *m_undoers->begin(); + return item->getLabel(); } const char* UndoHistory::getNextRedoLabel() const { - UndoChunk* chunk; - ASSERT(canRedo()); - chunk = *m_redoStream->begin(); - return chunk->label; + UndoersStack::Item* item = *m_redoers->begin(); + return item->getLabel(); } bool UndoHistory::isSavedState() const @@ -382,2100 +112,84 @@ void UndoHistory::markSavedState() m_diffSaved = m_diffCount; } -void UndoHistory::runUndo(int state) +void UndoHistory::runUndo(Direction direction) { - UndoStream* undo_stream = ((state == DO_UNDO)? m_undoStream: - m_redoStream); - UndoStream* redo_stream = ((state == DO_REDO)? m_undoStream: - m_redoStream); - UndoChunk* chunk; + UndoersStack* undoers = ((direction == UndoDirection)? m_undoers: m_redoers); + UndoersStack* redoers = ((direction == RedoDirection)? m_undoers: m_redoers); int level = 0; do { - chunk = undo_stream->popChunk(false); // read from head - if (!chunk) + const char* itemLabel = NULL; + if (!undoers->empty()) + itemLabel = (*undoers->begin())->getLabel(); + + Undoer* undoer = undoers->popUndoer(UndoersStack::PopFromHead); + if (!undoer) break; - setLabel(chunk->label); - (undo_actions[chunk->type].invert)(redo_stream, chunk); + setLabel(itemLabel); + undoer->revert(getObjects(), redoers); - if (chunk->type == UNDO_TYPE_OPEN) + if (undoer->isOpenGroup()) level++; - else if (chunk->type == UNDO_TYPE_CLOSE) + else if (undoer->isCloseGroup()) level--; - undo_chunk_free(chunk); + // Delete the undoer + undoer->dispose(); - if (state == DO_UNDO) + if (direction == UndoDirection) m_diffCount--; - else if (state == DO_REDO) + else if (direction == RedoDirection) m_diffCount++; } while (level); } void UndoHistory::discardTail() { - UndoStream* undo_stream = m_undoStream; - UndoChunk* chunk; int level = 0; do { - chunk = undo_stream->popChunk(true); // read from tail - if (!chunk) + Undoer* undoer = m_undoers->popUndoer(UndoersStack::PopFromTail); + if (!undoer) break; - if (chunk->type == UNDO_TYPE_OPEN) + if (undoer->isOpenGroup()) level++; - else if (chunk->type == UNDO_TYPE_CLOSE) + else if (undoer->isCloseGroup()) level--; - undo_chunk_free(chunk); + undoer->dispose(); } while (level); } -static int count_undo_groups(UndoStream* undo_stream) +void UndoHistory::pushUndoer(Undoer* undoer) { - UndoChunk* chunk; - int groups = 0; - int level; + // Add the undoer in the undoers stack + m_undoers->pushUndoer(undoer); - ChunksList::iterator it = undo_stream->begin(); - while (it != undo_stream->end()) { - level = 0; - - do { - chunk = *it; - ++it; - - if (chunk->type == UNDO_TYPE_OPEN) - level++; - else if (chunk->type == UNDO_TYPE_CLOSE) - level--; - } while (level && (it != undo_stream->end())); - - if (level == 0) - groups++; - } - - return groups; -} - -static bool out_of_group(UndoStream* undo_stream) -{ - UndoChunk* chunk; - int level = 0; - - ChunksList::iterator it = undo_stream->begin(); - while (it != undo_stream->end()) { - level = 0; - - do { - chunk = *it; - ++it; - - if (chunk->type == UNDO_TYPE_OPEN) - level++; - else if (chunk->type == UNDO_TYPE_CLOSE) - level--; - } while (level && (it != undo_stream->end())); - } - - return level == 0; -} - -// Called every time a new undo is added. -void UndoHistory::updateUndo() -{ - // TODO replace this with the following implementation: - // * Add the undo limit to Undo class as a normal member (non-static). - // * Add a new AseSprite (wrapper of a generic Sprite). - // * Add ASE delegates to listen changes in ASE configuration - // * AseSprite should implement a delegate to listen changes to the undo limit, - // * When a change is produced, AseSprite updates the wrappedSprite->getUndo()->setUndoLimit(). - int undo_size_limit = get_config_int("Options", "UndoSizeLimit", 8)*1024*1024; + // TODO Replace this with the following implementation: + // * Add the undo limit to UndoHistory class as a normal member (non-static). + // * Add App signals to listen changes in settings + // * Document should listen changes in the undo limit, + // * When a change is produced, Document calls getUndoHistory()->setUndoLimit(). + int undo_size_limit = (int)get_config_int("Options", "UndoSizeLimit", 8)*1024*1024; // More differences. m_diffCount++; - // Reset the "redo" stream. + // Reset the "redo" stack. clearRedo(); - if (out_of_group(m_undoStream)) { - int groups = count_undo_groups(m_undoStream); + // If we are outside a group, we can shrink the tail of the undo if + // it has passed the undo-limit. + if (m_undoers->isOutOfGroup()) { + int groups = m_undoers->countUndoGroups(); // "undo" is too big? - while (groups > 1 && m_undoStream->getMemSize() > undo_size_limit) { + while (groups > 1 && m_undoers->getMemSize() > undo_size_limit) { discardTail(); groups--; } } } - -/*********************************************************************** - - Raw data - -***********************************************************************/ - -#define read_raw_uint32(dst) \ - { \ - memcpy(&dword, raw_data, 4); \ - dst = dword; \ - raw_data += 4; \ - } - -#define read_raw_uint16(dst) \ - { \ - memcpy(&word, raw_data, 2); \ - dst = word; \ - raw_data += 2; \ - } - -#define read_raw_int16(dst) \ - { \ - memcpy(&word, raw_data, 2); \ - dst = (int16_t)word; \ - raw_data += 2; \ - } - -#define read_raw_uint8(dst) \ - { \ - dst = *raw_data; \ - ++raw_data; \ - } - -#define read_raw_data(dst, size) \ - { \ - memcpy(dst, raw_data, size); \ - raw_data += size; \ - } - -#define write_raw_uint32(src) \ - { \ - dword = src; \ - memcpy(raw_data, &dword, 4); \ - raw_data += 4; \ - } - -#define write_raw_uint16(src) \ - { \ - word = src; \ - memcpy(raw_data, &word, 2); \ - raw_data += 2; \ - } - -#define write_raw_int16(src) \ - { \ - word = (int16_t)src; \ - memcpy(raw_data, &word, 2); \ - raw_data += 2; \ - } - -#define write_raw_uint8(src) \ - { \ - *raw_data = src; \ - ++raw_data; \ - } - -#define write_raw_data(src, size) \ - { \ - memcpy(raw_data, src, size); \ - raw_data += size; \ - } - -/*********************************************************************** - - "open" - - no data - -***********************************************************************/ - -void UndoHistory::undo_open() -{ - chunk_open_new(m_undoStream); - updateUndo(); -} - -static void chunk_open_new(UndoStream* stream) -{ - undo_chunk_new(stream, - UNDO_TYPE_OPEN, - sizeof(UndoChunk)); -} - -static void chunk_open_invert(UndoStream* stream, UndoChunk* chunk) -{ - chunk_close_new(stream); -} - -/*********************************************************************** - - "close" - - no data - -***********************************************************************/ - -void UndoHistory::undo_close() -{ - chunk_close_new(m_undoStream); - updateUndo(); -} - -static void chunk_close_new(UndoStream* stream) -{ - undo_chunk_new(stream, - UNDO_TYPE_CLOSE, - sizeof(UndoChunk)); -} - -static void chunk_close_invert(UndoStream* stream, UndoChunk* chunk) -{ - chunk_open_new(stream); -} - -/*********************************************************************** - - "data" - - DWORD object ID - DWORD field address offset - DWORD field data size - BYTE[] field data bytes - -***********************************************************************/ - -struct UndoChunkData -{ - UndoChunk head; - ObjectId objectId; - uint32_t fieldOffset; - uint32_t fieldSize; - uint8_t fieldData[0]; -}; - -void UndoHistory::undo_data(void* object, void* fieldAddress, int fieldSize) -{ - chunk_data_new(m_undoStream, object, fieldAddress, fieldSize); - updateUndo(); -} - -static void chunk_data_new(UndoStream* stream, void* object, void* fieldAddress, int fieldSize) -{ - uint32_t fieldOffset = (uint32_t)(((uint8_t*)fieldAddress) - - ((uint8_t*)object)); - - ASSERT(fieldSize >= 1); - - UndoChunkData* chunk = (UndoChunkData *) - undo_chunk_new(stream, - UNDO_TYPE_DATA, - sizeof(UndoChunkData) + fieldSize); - - chunk->objectId = stream->getObjects()->addObject(object); - chunk->fieldOffset = fieldOffset; - chunk->fieldSize = fieldSize; - - memcpy(chunk->fieldData, fieldAddress, fieldSize); -} - -static void chunk_data_invert(UndoStream* stream, UndoChunkData *chunk) -{ - unsigned int offset = chunk->fieldOffset; - unsigned int size = chunk->fieldSize; - void* object = stream->getObjects()->getObject(chunk->objectId); - void* field = (void*)(((uint8_t*)object) + offset); - - // Save the current data - chunk_data_new(stream, object, field, size); - - // Copy back the old data - memcpy(field, chunk->fieldData, size); -} - -/*********************************************************************** - - "image" - - DWORD image ID - BYTE image type - WORD[4] x, y, w, h - for each row ("h" times) - for each pixel ("w" times) - BYTE[4] for RGB images, or - BYTE[2] for Grayscale images, or - BYTE for Indexed images - -***********************************************************************/ - -struct UndoChunkImage -{ - UndoChunk head; - ObjectId image_id; - uint8_t imgtype; - uint16_t x, y, w, h; - uint8_t data[0]; -}; - -void UndoHistory::undo_image(Image* image, int x, int y, int w, int h) -{ - chunk_image_new(m_undoStream, image, x, y, w, h); - updateUndo(); -} - -static void chunk_image_new(UndoStream* stream, Image* image, int x, int y, int w, int h) -{ - UndoChunkImage* chunk; - uint8_t* ptr; - int v, size; - - ASSERT(w >= 1 && h >= 1); - ASSERT(x >= 0 && y >= 0 && x+w <= image->w && y+h <= image->h); - - size = image_line_size(image, w); - - chunk = (UndoChunkImage*) - undo_chunk_new(stream, - UNDO_TYPE_IMAGE, - sizeof(UndoChunkImage) + size*h); - - chunk->image_id = stream->getObjects()->addObject(image); - chunk->imgtype = image->imgtype; - chunk->x = x; - chunk->y = y; - chunk->w = w; - chunk->h = h; - - ptr = chunk->data; - for (v=0; vimage_id; - int imgtype = chunk->imgtype; - Image* image = stream->getObjects()->getObjectT(id); - - if (image->imgtype != imgtype) - throw UndoException("Image type does not match"); - - int x, y, w, h; - uint8_t* ptr; - int v, size; - - x = chunk->x; - y = chunk->y; - w = chunk->w; - h = chunk->h; - - // Backup the current image portion - chunk_image_new(stream, image, x, y, w, h); - - // Restore the old image portion - size = image_line_size(image, chunk->w); - ptr = chunk->data; - - for (v=0; vimage_id = stream->getObjects()->addObject(image); - chunk->imgtype = image->imgtype; - chunk->x1 = x1; - chunk->y1 = y1; - chunk->x2 = x2; - chunk->y2 = y2; - chunk->horz = horz ? 1: 0; -} - -static void chunk_flip_invert(UndoStream* stream, UndoChunkFlip* chunk) -{ - Image* image = stream->getObjects()->getObjectT(chunk->image_id); - - if ((image) && - (image->getType() == GFXOBJ_IMAGE) && - (image->imgtype == chunk->imgtype)) { - int x1 = chunk->x1; - int y1 = chunk->y1; - int x2 = chunk->x2; - int y2 = chunk->y2; - bool horz = (chunk->horz != 0); - - chunk_flip_new(stream, image, x1, y1, x2, y2, horz); - - Image* area = image_crop(image, x1, y1, x2-x1+1, y2-y1+1, 0); - int x, y; - - for (y=0; y<(y2-y1+1); y++) - for (x=0; x<(x2-x1+1); x++) - image_putpixel(image, - horz ? x2-x: x1+x, - !horz? y2-y: y1+y, - image_getpixel(area, x, y)); - - image_free(area); - } -} - -/*********************************************************************** - - "dirty" - - DWORD image ID - DIRTY_DATA see read/write_raw_dirty - -***********************************************************************/ - -struct UndoChunkDirty -{ - UndoChunk head; - ObjectId image_id; - uint8_t data[0]; -}; - -void UndoHistory::undo_dirty(Image* image, Dirty* dirty) -{ - chunk_dirty_new(m_undoStream, image, dirty); - updateUndo(); -} - -static void chunk_dirty_new(UndoStream* stream, Image* image, Dirty *dirty) -{ - UndoChunkDirty *chunk = (UndoChunkDirty *) - undo_chunk_new(stream, - UNDO_TYPE_DIRTY, - sizeof(UndoChunkDirty)+get_raw_dirty_size(dirty)); - - chunk->image_id = stream->getObjects()->addObject(image); - write_raw_dirty(chunk->data, dirty); -} - -static void chunk_dirty_invert(UndoStream* stream, UndoChunkDirty *chunk) -{ - Image* image = stream->getObjects()->getObjectT(chunk->image_id); - - if ((image) && - (image->getType() == GFXOBJ_IMAGE)) { - Dirty* dirty = read_raw_dirty(chunk->data); - - if (dirty != NULL) { - dirty->swapImagePixels(image); - chunk_dirty_new(stream, image, dirty); - delete dirty; - } - } -} - -/*********************************************************************** - - "add_image" - - DWORD stock ID - DWORD index of the image in the stock - -***********************************************************************/ - -struct UndoChunkAddImage -{ - UndoChunk head; - ObjectId stock_id; - uint32_t image_index; -}; - -void UndoHistory::undo_add_image(Stock *stock, int image_index) -{ - chunk_add_image_new(m_undoStream, stock, image_index); - updateUndo(); -} - -static void chunk_add_image_new(UndoStream* stream, Stock *stock, int image_index) -{ - UndoChunkAddImage* chunk = (UndoChunkAddImage* ) - undo_chunk_new(stream, - UNDO_TYPE_ADD_IMAGE, - sizeof(UndoChunkAddImage)); - - chunk->stock_id = stream->getObjects()->addObject(stock); - chunk->image_index = image_index; -} - -static void chunk_add_image_invert(UndoStream* stream, UndoChunkAddImage* chunk) -{ - ObjectId stock_id = chunk->stock_id; - unsigned int image_index = chunk->image_index; - Stock *stock = stream->getObjects()->getObjectT(stock_id); - - if (stock) { - Image* image = stock->getImage(image_index); - if (image != NULL) { - chunk_remove_image_new(stream, stock, image_index); - stock->removeImage(image); - image_free(image); - } - } -} - -/*********************************************************************** - - "remove_image" - - DWORD stock ID - DWORD index of the image in the stock - IMAGE_DATA see read/write_raw_image - -***********************************************************************/ - -struct UndoChunkRemoveImage -{ - UndoChunk head; - ObjectId stock_id; - uint32_t image_index; - uint8_t data[0]; -}; - -void UndoHistory::undo_remove_image(Stock *stock, int image_index) -{ - chunk_remove_image_new(m_undoStream, stock, image_index); - updateUndo(); -} - -static void chunk_remove_image_new(UndoStream* stream, Stock *stock, int image_index) -{ - Image* image = stock->getImage(image_index); - UndoChunkRemoveImage* chunk = (UndoChunkRemoveImage*) - undo_chunk_new(stream, - UNDO_TYPE_REMOVE_IMAGE, - sizeof(UndoChunkRemoveImage)+get_raw_image_size(image)); - - chunk->stock_id = stream->getObjects()->addObject(stock); - chunk->image_index = image_index; - - write_raw_image(stream->getObjects(), chunk->data, image); -} - -static void chunk_remove_image_invert(UndoStream* stream, UndoChunkRemoveImage* chunk) -{ - ObjectId stock_id = chunk->stock_id; - unsigned int image_index = chunk->image_index; - Stock* stock = stream->getObjects()->getObjectT(stock_id); - - if (stock) { - Image* image = read_raw_image(stream->getObjects(), chunk->data); - - /* ASSERT(image != NULL); */ - - stock->replaceImage(image_index, image); - chunk_add_image_new(stream, stock, image_index); - } -} - -/*********************************************************************** - - "replace_image" - - DWORD stock ID - DWORD index of the image in the stock - IMAGE_DATA see read/write_raw_image - -***********************************************************************/ - -struct UndoChunkReplaceImage -{ - UndoChunk head; - ObjectId stock_id; - uint32_t image_index; - uint8_t data[0]; -}; - -void UndoHistory::undo_replace_image(Stock *stock, int image_index) -{ - chunk_replace_image_new(m_undoStream, stock, image_index); - updateUndo(); -} - -static void chunk_replace_image_new(UndoStream* stream, Stock *stock, int image_index) -{ - Image* image = stock->getImage(image_index); - UndoChunkReplaceImage* chunk = (UndoChunkReplaceImage* ) - undo_chunk_new(stream, - UNDO_TYPE_REPLACE_IMAGE, - sizeof(UndoChunkReplaceImage)+get_raw_image_size(image)); - - chunk->stock_id = stream->getObjects()->addObject(stock); - chunk->image_index = image_index; - - write_raw_image(stream->getObjects(), chunk->data, image); -} - -static void chunk_replace_image_invert(UndoStream* stream, UndoChunkReplaceImage* chunk) -{ - ObjectId stock_id = chunk->stock_id; - unsigned long image_index = chunk->image_index; - Stock* stock = stream->getObjects()->getObjectT(stock_id); - - if (stock) { - // read the image to be restored from the chunk - Image* image = read_raw_image(stream->getObjects(), chunk->data); - - // save the current image in the (redo) stream - chunk_replace_image_new(stream, stock, image_index); - Image* old_image = stock->getImage(image_index); - - // replace the image in the stock - stock->replaceImage(image_index, image); - - // destroy the old image - image_free(old_image); - } -} - -/*********************************************************************** - - "add_cel" - - DWORD layer ID - DWORD cel ID - -***********************************************************************/ - -struct UndoChunkAddCel -{ - UndoChunk head; - ObjectId layer_id; - ObjectId cel_id; -}; - -void UndoHistory::undo_add_cel(Layer* layer, Cel* cel) -{ - chunk_add_cel_new(m_undoStream, layer, cel); - updateUndo(); -} - -static void chunk_add_cel_new(UndoStream* stream, Layer* layer, Cel* cel) -{ - UndoChunkAddCel* chunk = (UndoChunkAddCel* ) - undo_chunk_new(stream, - UNDO_TYPE_ADD_CEL, - sizeof(UndoChunkAddCel)); - - chunk->layer_id = stream->getObjects()->addObject(layer); - chunk->cel_id = stream->getObjects()->addObject(cel); -} - -static void chunk_add_cel_invert(UndoStream* stream, UndoChunkAddCel* chunk) -{ - LayerImage* layer = stream->getObjects()->getObjectT(chunk->layer_id); - Cel* cel = stream->getObjects()->getObjectT(chunk->cel_id); - - chunk_remove_cel_new(stream, layer, cel); - - layer->removeCel(cel); - cel_free(cel); -} - -/*********************************************************************** - - "remove_cel" - - DWORD layer ID - CEL_DATA see read/write_raw_cel - -***********************************************************************/ - -struct UndoChunkRemoveCel -{ - UndoChunk head; - ObjectId layer_id; - uint8_t data[0]; -}; - -void UndoHistory::undo_remove_cel(Layer* layer, Cel* cel) -{ - chunk_remove_cel_new(m_undoStream, layer, cel); - updateUndo(); -} - -static void chunk_remove_cel_new(UndoStream* stream, Layer* layer, Cel* cel) -{ - UndoChunkRemoveCel* chunk = (UndoChunkRemoveCel*) - undo_chunk_new(stream, - UNDO_TYPE_REMOVE_CEL, - sizeof(UndoChunkRemoveCel)+get_raw_cel_size(cel)); - - chunk->layer_id = stream->getObjects()->addObject(layer); - write_raw_cel(stream->getObjects(), chunk->data, cel); -} - -static void chunk_remove_cel_invert(UndoStream* stream, UndoChunkRemoveCel* chunk) -{ - ObjectId layer_id = chunk->layer_id; - LayerImage* layer = stream->getObjects()->getObjectT(layer_id); - - // Read the cel - Cel* cel = read_raw_cel(stream->getObjects(), chunk->data); - - chunk_add_cel_new(stream, layer, cel); - layer->addCel(cel); -} - -/*********************************************************************** - - "set_layer_name" - - DWORD layer ID - DWORD name length - BYTES[length] name text - -***********************************************************************/ - -struct UndoChunkSetLayerName -{ - UndoChunk head; - ObjectId layer_id; - uint16_t name_length; - uint8_t name_text[0]; -}; - -void UndoHistory::undo_set_layer_name(Layer* layer) -{ - chunk_set_layer_name_new(m_undoStream, layer); - updateUndo(); -} - -static void chunk_set_layer_name_new(UndoStream* stream, Layer *layer) -{ - std::string layer_name = layer->getName(); - - UndoChunkSetLayerName* chunk = (UndoChunkSetLayerName*) - undo_chunk_new(stream, - UNDO_TYPE_SET_LAYER_NAME, - sizeof(UndoChunkSetLayerName) + layer_name.size()); - - chunk->layer_id = stream->getObjects()->addObject(layer); - chunk->name_length = layer_name.size(); - - for (int c=0; cname_length; c++) - chunk->name_text[c] = layer_name[c]; -} - -static void chunk_set_layer_name_invert(UndoStream* stream, UndoChunkSetLayerName* chunk) -{ - Layer* layer = stream->getObjects()->getObjectT(chunk->layer_id); - - if (layer) { - chunk_set_layer_name_new(stream, layer); - - std::string layer_name; - layer_name.reserve(chunk->name_length); - - for (int c=0; cname_length; c++) - layer_name.push_back(chunk->name_text[c]); - - layer->setName(layer_name.c_str()); - } -} - -/*********************************************************************** - - "add_layer" - - DWORD parent layer set ID - DWORD layer ID - -***********************************************************************/ - -struct UndoChunkAddLayer -{ - UndoChunk head; - ObjectId folder_id; - ObjectId layer_id; -}; - -void UndoHistory::undo_add_layer(Layer* folder, Layer* layer) -{ - chunk_add_layer_new(m_undoStream, folder, layer); - updateUndo(); -} - -static void chunk_add_layer_new(UndoStream* stream, Layer* folder, Layer* layer) -{ - UndoChunkAddLayer* chunk = (UndoChunkAddLayer* ) - undo_chunk_new(stream, - UNDO_TYPE_ADD_LAYER, - sizeof(UndoChunkAddLayer)); - - chunk->folder_id = stream->getObjects()->addObject(folder); - chunk->layer_id = stream->getObjects()->addObject(layer); -} - -static void chunk_add_layer_invert(UndoStream* stream, UndoChunkAddLayer* chunk) -{ - LayerFolder* folder = stream->getObjects()->getObjectT(chunk->folder_id); - Layer* layer = stream->getObjects()->getObjectT(chunk->layer_id); - - chunk_remove_layer_new(stream, layer); - - folder->remove_layer(layer); - delete layer; -} - -/*********************************************************************** - - "remove_layer" - - DWORD parent layer folder ID - DWORD after layer ID - LAYER_DATA see read/write_raw_layer - -***********************************************************************/ - -struct UndoChunkRemoveLayer -{ - UndoChunk head; - ObjectId folder_id; - ObjectId after_id; - uint8_t data[0]; -}; - -void UndoHistory::undo_remove_layer(Layer* layer) -{ - chunk_remove_layer_new(m_undoStream, layer); - updateUndo(); -} - -static void chunk_remove_layer_new(UndoStream* stream, Layer* layer) -{ - UndoChunkRemoveLayer* chunk = (UndoChunkRemoveLayer*) - undo_chunk_new(stream, - UNDO_TYPE_REMOVE_LAYER, - sizeof(UndoChunkRemoveLayer)+get_raw_layer_size(layer)); - LayerFolder* folder = layer->get_parent(); - Layer* after = layer->get_prev(); - - chunk->folder_id = stream->getObjects()->addObject(folder); - chunk->after_id = (after != NULL ? stream->getObjects()->addObject(after): 0); - - write_raw_layer(stream->getObjects(), chunk->data, layer); -} - -static void chunk_remove_layer_invert(UndoStream* stream, UndoChunkRemoveLayer* chunk) -{ - LayerFolder* folder = stream->getObjects()->getObjectT(chunk->folder_id); - Layer* layer = read_raw_layer(stream->getObjects(), chunk->data); - Layer* after = (chunk->after_id != 0 ? stream->getObjects()->getObjectT(chunk->after_id): NULL); - - chunk_add_layer_new(stream, folder, layer); - - folder->add_layer(layer); - folder->move_layer(layer, after); -} - -/*********************************************************************** - - "move_layer" - - DWORD parent layer folder ID - DWORD layer ID - DWORD after layer ID - -***********************************************************************/ - -struct UndoChunkMoveLayer -{ - UndoChunk head; - ObjectId folder_id; - ObjectId layer_id; - ObjectId after_id; -}; - -void UndoHistory::undo_move_layer(Layer* layer) -{ - chunk_move_layer_new(m_undoStream, layer); - updateUndo(); -} - -static void chunk_move_layer_new(UndoStream* stream, Layer* layer) -{ - UndoChunkMoveLayer* chunk = (UndoChunkMoveLayer* ) - undo_chunk_new(stream, - UNDO_TYPE_MOVE_LAYER, - sizeof(UndoChunkMoveLayer)); - LayerFolder* folder = layer->get_parent(); - Layer* after = layer->get_prev(); - - chunk->folder_id = stream->getObjects()->addObject(folder); - chunk->layer_id = stream->getObjects()->addObject(layer); - chunk->after_id = (after ? stream->getObjects()->addObject(after): 0); -} - -static void chunk_move_layer_invert(UndoStream* stream, UndoChunkMoveLayer* chunk) -{ - LayerFolder* folder = stream->getObjects()->getObjectT(chunk->folder_id); - Layer* layer = stream->getObjects()->getObjectT(chunk->layer_id); - Layer* after = (chunk->after_id != 0 ? stream->getObjects()->getObjectT(chunk->after_id): NULL); - - chunk_move_layer_new(stream, layer); - folder->move_layer(layer, after); -} - -/*********************************************************************** - - "set_layer" - - DWORD sprite ID - DWORD layer ID - -***********************************************************************/ - -struct UndoChunkSetLayer -{ - UndoChunk head; - ObjectId sprite_id; - ObjectId layer_id; -}; - -void UndoHistory::undo_set_layer(Sprite *sprite) -{ - chunk_set_layer_new(m_undoStream, sprite); - updateUndo(); -} - -static void chunk_set_layer_new(UndoStream* stream, Sprite *sprite) -{ - UndoChunkSetLayer* chunk = (UndoChunkSetLayer*) - undo_chunk_new(stream, - UNDO_TYPE_SET_LAYER, - sizeof(UndoChunkSetLayer)); - - chunk->sprite_id = stream->getObjects()->addObject(sprite); - chunk->layer_id = (sprite->getCurrentLayer() ? - stream->getObjects()->addObject(sprite->getCurrentLayer()): 0); -} - -static void chunk_set_layer_invert(UndoStream* stream, UndoChunkSetLayer* chunk) -{ - Sprite *sprite = stream->getObjects()->getObjectT(chunk->sprite_id); - Layer* layer = (chunk->layer_id != 0 ? stream->getObjects()->getObjectT(chunk->layer_id): NULL); - - chunk_set_layer_new(stream, sprite); - - sprite->setCurrentLayer(layer); -} - -/*********************************************************************** - - "add_palette" - - DWORD sprite ID - DWORD palette ID - -***********************************************************************/ - -struct UndoChunkAddPalette -{ - UndoChunk head; - ObjectId sprite_id; - ObjectId palette_id; -}; - -void UndoHistory::undo_add_palette(Sprite *sprite, Palette* palette) -{ - chunk_add_palette_new(m_undoStream, sprite, palette); - updateUndo(); -} - -static void chunk_add_palette_new(UndoStream* stream, Sprite *sprite, Palette* palette) -{ - UndoChunkAddPalette* chunk = (UndoChunkAddPalette*) - undo_chunk_new(stream, - UNDO_TYPE_ADD_PALETTE, - sizeof(UndoChunkAddPalette)); - - chunk->sprite_id = stream->getObjects()->addObject(sprite); - chunk->palette_id = stream->getObjects()->addObject(palette); -} - -static void chunk_add_palette_invert(UndoStream* stream, UndoChunkAddPalette *chunk) -{ - Sprite* sprite = stream->getObjects()->getObjectT(chunk->sprite_id); - Palette* palette = stream->getObjects()->getObjectT(chunk->palette_id); - - chunk_remove_palette_new(stream, sprite, palette); - sprite->deletePalette(palette); -} - -/*********************************************************************** - - "remove_palette" - - DWORD sprite ID - PALETTE_DATA see read/write_raw_palette - -***********************************************************************/ - -struct UndoChunkRemovePalette -{ - UndoChunk head; - ObjectId sprite_id; - uint8_t data[0]; -}; - -void UndoHistory::undo_remove_palette(Sprite *sprite, Palette* palette) -{ - chunk_remove_palette_new(m_undoStream, sprite, palette); - updateUndo(); -} - -static void chunk_remove_palette_new(UndoStream* stream, Sprite *sprite, Palette* palette) -{ - UndoChunkRemovePalette* chunk = (UndoChunkRemovePalette*) - undo_chunk_new(stream, - UNDO_TYPE_REMOVE_PALETTE, - sizeof(UndoChunkRemovePalette)+get_raw_palette_size(palette)); - - chunk->sprite_id = stream->getObjects()->addObject(sprite); - write_raw_palette(chunk->data, palette); -} - -static void chunk_remove_palette_invert(UndoStream* stream, UndoChunkRemovePalette *chunk) -{ - Sprite *sprite = stream->getObjects()->getObjectT(chunk->sprite_id); - Palette* palette = read_raw_palette(chunk->data); - - chunk_add_palette_new(stream, sprite, palette); - sprite->setPalette(palette, true); - - delete palette; -} - -/*********************************************************************** - - "set_palette_colors" - - DWORD sprite ID - DWORD frame - BYTE from - BYTE to - DWORD[to-from+1] palette entries - -***********************************************************************/ - -struct UndoChunkSetPaletteColors -{ - UndoChunk head; - ObjectId sprite_id; - uint32_t frame; - uint8_t from; - uint8_t to; - uint8_t data[0]; -}; - -void UndoHistory::undo_set_palette_colors(Sprite *sprite, Palette* palette, int from, int to) -{ - chunk_set_palette_colors_new(m_undoStream, sprite, palette, from, to); - updateUndo(); -} - -static void chunk_set_palette_colors_new(UndoStream* stream, Sprite *sprite, Palette* palette, int from, int to) -{ - UndoChunkSetPaletteColors* chunk = (UndoChunkSetPaletteColors*) - undo_chunk_new(stream, - UNDO_TYPE_SET_PALETTE_COLORS, - sizeof(UndoChunkSetPaletteColors) + sizeof(uint32_t)*(to-from+1)); - - chunk->sprite_id = stream->getObjects()->addObject(sprite); - chunk->frame = sprite->getCurrentFrame(); - chunk->from = from; - chunk->to = to; - - // Write (to-from+1) palette color entries - uint32_t dword; - uint8_t* raw_data = chunk->data; - for (int i=from; i<=to; ++i) - write_raw_uint32(palette->getEntry(i)); -} - -static void chunk_set_palette_colors_invert(UndoStream* stream, UndoChunkSetPaletteColors *chunk) -{ - Sprite* sprite = stream->getObjects()->getObjectT(chunk->sprite_id); - Palette* palette = sprite->getPalette(chunk->frame); - if (palette == NULL) - throw UndoException("chunk_set_palette_colors_invert: palette not found"); - - // Add the chunk to invert the operation - chunk_set_palette_colors_new(stream, sprite, palette, chunk->from, chunk->to); - - uint32_t dword; - uint32_t color; - uint8_t* raw_data = chunk->data; - - for (int i=(int)chunk->from; i<=(int)chunk->to; ++i) { - read_raw_uint32(color); - palette->setEntry(i, color); - } -} - -/*********************************************************************** - - "remap_palette" - - DWORD sprite ID - DWORD first frame in range - DWORD last frame in range - BYTE[256] mapping table - -***********************************************************************/ - -struct UndoChunkRemapPalette -{ - UndoChunk head; - ObjectId sprite_id; - uint32_t frame_from; - uint32_t frame_to; - uint8_t mapping[256]; -}; - -void UndoHistory::undo_remap_palette(Sprite* sprite, int frame_from, int frame_to, const std::vector& mapping) -{ - chunk_remap_palette_new(m_undoStream, sprite, frame_from, frame_to, mapping); - updateUndo(); -} - -static void chunk_remap_palette_new(UndoStream* stream, Sprite *sprite, int frame_from, int frame_to, const std::vector& mapping) -{ - UndoChunkRemapPalette* chunk = (UndoChunkRemapPalette*) - undo_chunk_new(stream, - UNDO_TYPE_REMAP_PALETTE, - sizeof(UndoChunkRemapPalette)); - - chunk->sprite_id = stream->getObjects()->addObject(sprite); - chunk->frame_from = frame_from; - chunk->frame_to = frame_to; - - ASSERT(mapping.size() == 256 && "Mapping tables must have 256 entries"); - - for (size_t c=0; c<256; c++) - chunk->mapping[c] = mapping[c]; -} - -static void chunk_remap_palette_invert(UndoStream* stream, UndoChunkRemapPalette* chunk) -{ - Sprite *sprite = stream->getObjects()->getObjectT(chunk->sprite_id); - - // Inverse mapping - std::vector inverse_mapping(256); - for (size_t c=0; c<256; ++c) - inverse_mapping[chunk->mapping[c]] = c; - - chunk_remap_palette_new(stream, sprite, chunk->frame_from, chunk->frame_to, inverse_mapping); - - // Remap in inverse order - sprite->remapImages(chunk->frame_from, chunk->frame_to, inverse_mapping); -} - -/*********************************************************************** - - "set_mask" - - DWORD document ID - MASK_DATA see read/write_raw_mask - -***********************************************************************/ - -struct UndoChunkSetMask -{ - UndoChunk head; - ObjectId doc_id; - uint8_t data[0]; -}; - -void UndoHistory::undo_set_mask(Document* document) -{ - chunk_set_mask_new(m_undoStream, document); - updateUndo(); -} - -static void chunk_set_mask_new(UndoStream* stream, Document* document) -{ - UndoChunkSetMask* chunk = (UndoChunkSetMask*) - undo_chunk_new(stream, - UNDO_TYPE_SET_MASK, - sizeof(UndoChunkSetMask)+get_raw_mask_size(document->getMask())); - - chunk->doc_id = stream->getObjects()->addObject(document); - write_raw_mask(chunk->data, document->getMask()); -} - -static void chunk_set_mask_invert(UndoStream* stream, UndoChunkSetMask* chunk) -{ - Document* document = stream->getObjects()->getObjectT(chunk->doc_id); - ASSERT(document != NULL); - - if (document != NULL) { - Mask* mask = read_raw_mask(chunk->data); - - chunk_set_mask_new(stream, document); - mask_copy(document->getMask(), mask); - mask_free(mask); - } -} - -/*********************************************************************** - - "set_imgtype" - - DWORD sprite ID - DWORD imgtype - -***********************************************************************/ - -struct UndoChunkSetImgType -{ - UndoChunk head; - ObjectId sprite_id; - uint32_t imgtype; -}; - -void UndoHistory::undo_set_imgtype(Sprite* sprite) -{ - chunk_set_imgtype_new(m_undoStream, sprite); - updateUndo(); -} - -static void chunk_set_imgtype_new(UndoStream* stream, Sprite* sprite) -{ - UndoChunkSetImgType* chunk = (UndoChunkSetImgType*) - undo_chunk_new(stream, - UNDO_TYPE_SET_IMGTYPE, - sizeof(UndoChunkSetImgType)); - - chunk->sprite_id = stream->getObjects()->addObject(sprite); - chunk->imgtype = sprite->getImgType(); -} - -static void chunk_set_imgtype_invert(UndoStream* stream, UndoChunkSetImgType* chunk) -{ - Sprite* sprite = stream->getObjects()->getObjectT(chunk->sprite_id); - - if (sprite) { - chunk_set_imgtype_new(stream, sprite); - sprite->setImgType(chunk->imgtype); - } -} - -/*********************************************************************** - - "set_size" - - DWORD sprite ID - DWORD width - DWORD height - -***********************************************************************/ - -struct UndoChunkSetSize -{ - UndoChunk head; - ObjectId sprite_id; - uint32_t width; - uint32_t height; -}; - -void UndoHistory::undo_set_size(Sprite* sprite) -{ - chunk_set_size_new(m_undoStream, sprite); - updateUndo(); -} - -static void chunk_set_size_new(UndoStream* stream, Sprite* sprite) -{ - UndoChunkSetSize* chunk = (UndoChunkSetSize*) - undo_chunk_new(stream, - UNDO_TYPE_SET_SIZE, - sizeof(UndoChunkSetSize)); - - chunk->sprite_id = stream->getObjects()->addObject(sprite); - chunk->width = sprite->getWidth(); - chunk->height = sprite->getHeight(); -} - -static void chunk_set_size_invert(UndoStream* stream, UndoChunkSetSize *chunk) -{ - Sprite *sprite = stream->getObjects()->getObjectT(chunk->sprite_id); - - if (sprite) { - chunk_set_size_new(stream, sprite); - sprite->setSize(chunk->width, chunk->height); - } -} - -/*********************************************************************** - - "set_frame" - - DWORD sprite ID - DWORD frame - -***********************************************************************/ - -struct UndoChunkSetFrame -{ - UndoChunk head; - ObjectId sprite_id; - uint32_t frame; -}; - -void UndoHistory::undo_set_frame(Sprite* sprite) -{ - chunk_set_frame_new(m_undoStream, sprite); - updateUndo(); -} - -static void chunk_set_frame_new(UndoStream* stream, Sprite* sprite) -{ - UndoChunkSetFrame* chunk = (UndoChunkSetFrame*) - undo_chunk_new(stream, - UNDO_TYPE_SET_FRAME, - sizeof(UndoChunkSetFrame)); - - chunk->sprite_id = stream->getObjects()->addObject(sprite); - chunk->frame = sprite->getCurrentFrame(); -} - -static void chunk_set_frame_invert(UndoStream* stream, UndoChunkSetFrame *chunk) -{ - Sprite* sprite = stream->getObjects()->getObjectT(chunk->sprite_id); - - if (sprite) { - chunk_set_frame_new(stream, sprite); - sprite->setCurrentFrame(chunk->frame); - } -} - -/*********************************************************************** - - "set_frames" - - DWORD sprite ID - DWORD frames - -***********************************************************************/ - -struct UndoChunkSetFrames -{ - UndoChunk head; - ObjectId sprite_id; - uint32_t frames; -}; - -void UndoHistory::undo_set_frames(Sprite *sprite) -{ - chunk_set_frames_new(m_undoStream, sprite); - updateUndo(); -} - -static void chunk_set_frames_new(UndoStream* stream, Sprite *sprite) -{ - UndoChunkSetFrames *chunk = (UndoChunkSetFrames *) - undo_chunk_new(stream, - UNDO_TYPE_SET_FRAMES, - sizeof(UndoChunkSetFrames)); - - chunk->sprite_id = stream->getObjects()->addObject(sprite); - chunk->frames = sprite->getTotalFrames(); -} - -static void chunk_set_frames_invert(UndoStream* stream, UndoChunkSetFrames *chunk) -{ - Sprite* sprite = stream->getObjects()->getObjectT(chunk->sprite_id); - - if (sprite) { - chunk_set_frames_new(stream, sprite); - sprite->setTotalFrames(chunk->frames); - } -} - -/*********************************************************************** - - "set_frlen" - - DWORD sprite ID - DWORD frame - DWORD duration - -***********************************************************************/ - -struct UndoChunkSetFrlen -{ - UndoChunk head; - ObjectId sprite_id; - uint32_t frame; - uint32_t duration; -}; - -void UndoHistory::undo_set_frlen(Sprite *sprite, int frame) -{ - chunk_set_frlen_new(m_undoStream, sprite, frame); - updateUndo(); -} - -static void chunk_set_frlen_new(UndoStream* stream, Sprite *sprite, int frame) -{ - ASSERT(frame >= 0 && frame < sprite->getTotalFrames()); - - UndoChunkSetFrlen *chunk = (UndoChunkSetFrlen *) - undo_chunk_new(stream, - UNDO_TYPE_SET_FRLEN, - sizeof(UndoChunkSetFrlen)); - - chunk->sprite_id = stream->getObjects()->addObject(sprite); - chunk->frame = frame; - chunk->duration = sprite->getFrameDuration(frame); -} - -static void chunk_set_frlen_invert(UndoStream* stream, UndoChunkSetFrlen *chunk) -{ - Sprite* sprite = stream->getObjects()->getObjectT(chunk->sprite_id); - - if (sprite != NULL) { - chunk_set_frlen_new(stream, sprite, chunk->frame); - sprite->setFrameDuration(chunk->frame, chunk->duration); - } -} - -/*********************************************************************** - - Helper routines for UndoChunk - -***********************************************************************/ - -static UndoChunk* undo_chunk_new(UndoStream* stream, int type, int size) -{ - UndoChunk* chunk; - - ASSERT(size >= (int)sizeof(UndoChunk)); - - chunk = (UndoChunk*)base_malloc0(size); - if (!chunk) - return NULL; - - chunk->type = type; - chunk->size = size; - chunk->label = stream->getUndo()->getLabel() ? - stream->getUndo()->getLabel(): - undo_actions[chunk->type].name; - - stream->pushChunk(chunk); - return chunk; -} - -static void undo_chunk_free(UndoChunk* chunk) -{ - base_free(chunk); -} - -/*********************************************************************** - - Raw dirty data - - BYTE image type - WORD[4] x1, y1, x2, y2 - WORD rows - for each row - WORD[2] y, columns - for each column - WORD[2] x, w - for each pixel ("w" times) - BYTE[4] for RGB images, or - BYTE[2] for Grayscale images, or - BYTE for Indexed images - -***********************************************************************/ - -static Dirty *read_raw_dirty(uint8_t* raw_data) -{ - uint16_t word; - int x1, y1, x2, y2, size; - int u, v, x, y, w; - int imgtype; - Dirty *dirty = NULL; - - read_raw_uint8(imgtype); - read_raw_uint16(x1); - read_raw_uint16(y1); - read_raw_uint16(x2); - read_raw_uint16(y2); - - dirty = new Dirty(imgtype, x1, y1, x2, y2); - - int noRows = 0; - read_raw_uint16(noRows); - if (noRows > 0) { - dirty->m_rows.resize(noRows); - - for (v=0; vgetRowsCount(); v++) { - y = 0; - read_raw_uint16(y); - - Dirty::Row* row = new Dirty::Row(y); - - int noCols = 0; - read_raw_uint16(noCols); - row->cols.resize(noCols); - - for (u=0; ugetLineSize(col->w); - ASSERT(size > 0); - - col->data.resize(size); - read_raw_data(&col->data[0], size); - - row->cols[u] = col; - } - - dirty->m_rows[v] = row; - } - } - - return dirty; -} - -static uint8_t* write_raw_dirty(uint8_t* raw_data, Dirty* dirty) -{ - uint16_t word; - - write_raw_uint8(dirty->getImgType()); - write_raw_uint16(dirty->x1()); - write_raw_uint16(dirty->y1()); - write_raw_uint16(dirty->x2()); - write_raw_uint16(dirty->y2()); - write_raw_uint16(dirty->getRowsCount()); - - for (int v=0; vgetRowsCount(); v++) { - const Dirty::Row& row = dirty->getRow(v); - - write_raw_uint16(row.y); - write_raw_uint16(row.cols.size()); - - for (size_t u=0; ux); - write_raw_uint16(row.cols[u]->w); - - size_t size = dirty->getLineSize(row.cols[u]->w); - write_raw_data(&row.cols[u]->data[0], size); - } - } - - return raw_data; -} - -static int get_raw_dirty_size(Dirty* dirty) -{ - int size = 1+2*4+2; // BYTE+WORD[4]+WORD - - for (int v=0; vgetRowsCount(); v++) { - const Dirty::Row& row = dirty->getRow(v); - - size += 4; // y, cols (WORD[2]) - for (size_t u=0; ugetLineSize(row.cols[u]->w); - } - } - - return size; -} - -/*********************************************************************** - - Raw image data - - DWORD image ID - BYTE image type - WORD[2] w, h - DWORD mask color - for each line ("h" times) - for each pixel ("w" times) - BYTE[4] for RGB images, or - BYTE[2] for Grayscale images, or - BYTE for Indexed images - -***********************************************************************/ - -static Image* read_raw_image(ObjectsContainer* objects, uint8_t* raw_data) -{ - uint32_t dword; - uint16_t word; - ObjectId image_id; - int imgtype; - int width; - int height; - uint32_t mask_color; - Image* image; - int c, size; - - read_raw_uint32(image_id); /* ID */ - if (!image_id) - return NULL; - - read_raw_uint8(imgtype); /* imgtype */ - read_raw_uint16(width); /* width */ - read_raw_uint16(height); /* height */ - read_raw_uint32(mask_color); /* mask color */ - - image = image_new(imgtype, width, height); - size = image_line_size(image, image->w); - - for (c=0; ch; c++) - read_raw_data(image->line[c], size); - - image->mask_color = mask_color; - - objects->insertObject(image_id, image); - return image; -} - -static uint8_t* write_raw_image(ObjectsContainer* objects, uint8_t* raw_data, Image* image) -{ - ObjectId image_id = objects->addObject(image); - uint32_t dword; - uint16_t word; - int c, size; - - write_raw_uint32(image_id); // ID - write_raw_uint8(image->imgtype); // imgtype - write_raw_uint16(image->w); // width - write_raw_uint16(image->h); // height - write_raw_uint32(image->mask_color); // mask color - - size = image_line_size(image, image->w); - for (c=0; ch; c++) - write_raw_data(image->line[c], size); - - objects->removeObject(image_id); - return raw_data; -} - -static int get_raw_image_size(Image* image) -{ - ASSERT(image != NULL); - return 4+1+2+2+4+image_line_size(image, image->w) * image->h; -} - -/*********************************************************************** - - Raw cel data - - DWORD cel ID - WORD frame - WORD image index - WORD[2] x, y - WORD opacity - -***********************************************************************/ - -static Cel* read_raw_cel(ObjectsContainer* objects, uint8_t* raw_data) -{ - uint32_t dword; - uint16_t word; - int frame, image, x, y, opacity; - ObjectId cel_id; - Cel* cel; - - read_raw_uint32(cel_id); - read_raw_uint16(frame); - read_raw_uint16(image); - read_raw_int16(x); - read_raw_int16(y); - read_raw_uint16(opacity); - - cel = cel_new(frame, image); - cel_set_position(cel, x, y); - cel_set_opacity(cel, opacity); - - objects->insertObject(cel_id, cel); - return cel; -} - -static uint8_t* write_raw_cel(ObjectsContainer* objects, uint8_t* raw_data, Cel* cel) -{ - ObjectId cel_id = objects->addObject(cel); - uint32_t dword; - uint16_t word; - - write_raw_uint32(cel_id); - write_raw_uint16(cel->frame); - write_raw_uint16(cel->image); - write_raw_int16(cel->x); - write_raw_int16(cel->y); - write_raw_uint16(cel->opacity); - - objects->removeObject(cel_id); - return raw_data; -} - -static int get_raw_cel_size(Cel* cel) -{ - return 4+2*5; -} - -/*********************************************************************** - - Raw layer data - -***********************************************************************/ - -static Layer* read_raw_layer(ObjectsContainer* objects, uint8_t* raw_data) -{ - uint32_t dword; - uint16_t word; - ObjectId layer_id, sprite_id; - std::vector name(1); - int name_length, flags, layer_type; - Layer* layer = NULL; - Sprite *sprite; - - read_raw_uint32(layer_id); // ID - - read_raw_uint16(name_length); // name length - name.resize(name_length+1); - if (name_length > 0) { - read_raw_data(&name[0], name_length); // name - name[name_length] = 0; - } - else - name[0] = 0; - - read_raw_uint8(flags); // flags - read_raw_uint16(layer_type); // type - read_raw_uint32(sprite_id); // sprite - - sprite = objects->getObjectT(sprite_id); - - switch (layer_type) { - - case GFXOBJ_LAYER_IMAGE: { - int c, cels; - - read_raw_uint16(cels); /* cels */ - - /* create layer */ - layer = new LayerImage(sprite); - - /* read cels */ - for (c=0; c(layer)->addCel(cel); - - /* read the image */ - read_raw_uint8(has_image); - if (has_image != 0) { - Image* image = read_raw_image(objects, raw_data); - raw_data += get_raw_image_size(image); - - layer->getSprite()->getStock()->replaceImage(cel->image, image); - } - } - break; - } - - case GFXOBJ_LAYER_FOLDER: { - int c, layers; - - /* create the layer set */ - layer = new LayerFolder(sprite); - - /* read how many sub-layers */ - read_raw_uint16(layers); - - for (c=0; c(layer)->add_layer(child); - raw_data += get_raw_layer_size(child); - } - else - break; - } - break; - } - - } - - if (layer != NULL) { - layer->setName(&name[0]); - *layer->flags_addr() = flags; - - objects->insertObject(layer_id, layer); - } - - return layer; -} - -static uint8_t* write_raw_layer(ObjectsContainer* objects, uint8_t* raw_data, Layer* layer) -{ - ObjectId layer_id = objects->addObject(layer); - uint32_t dword; - uint16_t word; - std::string name = layer->getName(); - - write_raw_uint32(layer_id); // ID - - write_raw_uint16(name.size()); // Name length - if (!name.empty()) - write_raw_data(name.c_str(), name.size()); // Name - - write_raw_uint8(*layer->flags_addr()); // Flags - write_raw_uint16(layer->getType()); // Type - write_raw_uint32(objects->addObject(layer->getSprite())); // Sprite - - switch (layer->getType()) { - - case GFXOBJ_LAYER_IMAGE: { - // Cels - write_raw_uint16(static_cast(layer)->getCelsCount()); - - CelIterator it = static_cast(layer)->getCelBegin(); - CelIterator end = static_cast(layer)->getCelEnd(); - - for (; it != end; ++it) { - Cel* cel = *it; - raw_data = write_raw_cel(objects, raw_data, cel); - - Image* image = layer->getSprite()->getStock()->getImage(cel->image); - ASSERT(image != NULL); - - write_raw_uint8(1); - raw_data = write_raw_image(objects, raw_data, image); - } - break; - } - - case GFXOBJ_LAYER_FOLDER: { - LayerIterator it = static_cast(layer)->get_layer_begin(); - LayerIterator end = static_cast(layer)->get_layer_end(); - - // how many sub-layers - write_raw_uint16(static_cast(layer)->get_layers_count()); - - for (; it != end; ++it) - raw_data = write_raw_layer(objects, raw_data, *it); - break; - } - - } - - objects->removeObject(layer_id); - return raw_data; -} - -static int get_raw_layer_size(Layer* layer) -{ - int size = 4+2+layer->getName().size()+1+2+4; - - switch (layer->getType()) { - - case GFXOBJ_LAYER_IMAGE: { - size += 1; // blend mode - size += 2; // num of cels - - CelIterator it = static_cast(layer)->getCelBegin(); - CelIterator end = static_cast(layer)->getCelEnd(); - - for (; it != end; ++it) { - Cel* cel = *it; - size += get_raw_cel_size(cel); - size++; // has image? - - Image* image = layer->getSprite()->getStock()->getImage(cel->image); - size += get_raw_image_size(image); - } - break; - } - - case GFXOBJ_LAYER_FOLDER: { - size += 2; // how many sub-layers - - LayerIterator it = static_cast(layer)->get_layer_begin(); - LayerIterator end = static_cast(layer)->get_layer_end(); - - for (; it != end; ++it) - size += get_raw_layer_size(*it); - break; - } - - } - - return size; -} - -/*********************************************************************** - - Raw palette data - - WORD frame - WORD ncolors - for each color ("ncolors" times) - DWORD _rgba color - -***********************************************************************/ - -static Palette* read_raw_palette(uint8_t* raw_data) -{ - uint32_t dword; - uint16_t word; - uint32_t color; - int frame, ncolors; - Palette* palette; - - read_raw_uint16(frame); /* frame */ - read_raw_uint16(ncolors); /* ncolors */ - - palette = new Palette(frame, ncolors); - if (!palette) - return NULL; - - for (int c=0; csetEntry(c, color); - } - - return palette; -} - -static uint8_t* write_raw_palette(uint8_t* raw_data, Palette* palette) -{ - uint32_t dword; - uint16_t word; - uint32_t color; - - write_raw_uint16(palette->getFrame()); // frame - write_raw_uint16(palette->size()); // number of colors - - for (int c=0; csize(); c++) { - color = palette->getEntry(c); - write_raw_uint32(color); - } - - return raw_data; -} - -static int get_raw_palette_size(Palette* palette) -{ - // 2 WORD + 4 BYTES*ncolors - return 2*2 + 4*palette->size(); -} - - -/*********************************************************************** - - Raw mask data - - WORD[4] x, y, w, h - for each line ("h" times) - for each packet ("((w+7)/8)" times) - BYTE 8 pixels of the mask - -***********************************************************************/ - -static Mask* read_raw_mask(uint8_t* raw_data) -{ - uint16_t word; - int x, y, w, h; - int c, size; - Mask* mask; - - read_raw_uint16(x); /* xpos */ - read_raw_uint16(y); /* ypos */ - read_raw_uint16(w); /* width */ - read_raw_uint16(h); /* height */ - - mask = mask_new(); - if (!mask) - return NULL; - - if (w > 0 && h > 0) { - size = (w+7)/8; - - mask->add(x, y, w, h); - for (c=0; ch; c++) - read_raw_data(mask->bitmap->line[c], size); - } - - return mask; -} - -static uint8_t* write_raw_mask(uint8_t* raw_data, Mask* mask) -{ - uint16_t word; - int c, size = (mask->w+7)/8; - - write_raw_uint16(mask->x); /* xpos */ - write_raw_uint16(mask->y); /* ypos */ - write_raw_uint16(mask->bitmap ? mask->w: 0); /* width */ - write_raw_uint16(mask->bitmap ? mask->h: 0); /* height */ - - if (mask->bitmap) - for (c=0; ch; c++) - write_raw_data(mask->bitmap->line[c], size); - - return raw_data; -} - -static int get_raw_mask_size(Mask* mask) -{ - int size = (mask->w+7)/8; - - return 2*4 + (mask->bitmap ? mask->h*size: 0); -} diff --git a/src/undo/undo_history.h b/src/undo/undo_history.h index cc6dd2e74..9433a0bcb 100644 --- a/src/undo/undo_history.h +++ b/src/undo/undo_history.h @@ -1,28 +1,17 @@ -/* ASE - Allegro Sprite Editor - * Copyright (C) 2001-2011 David Capello - * - * 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 - */ +// ASEPRITE Undo Library +// Copyright (C) 2001-2011 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. #ifndef UNDO_UNDO_HISTORY_H_INCLUDED #define UNDO_UNDO_HISTORY_H_INCLUDED -#include "base/exception.h" +#include "undo/undoers_collector.h" #include +// TODO Remove this (it is here only for backward compatibility) class Cel; class Dirty; class Document; @@ -30,19 +19,16 @@ class GfxObj; class Image; class Layer; class Mask; -class ObjectsContainer; class Palette; class Sprite; class Stock; -class UndoStream; -class UndoException : public base::Exception -{ -public: - UndoException(const char* msg) throw() : base::Exception(msg) { } -}; +namespace undo { -class UndoHistory +class ObjectsContainer; +class UndoersStack; + +class UndoHistory : public UndoersCollector { public: UndoHistory(ObjectsContainer* objects); @@ -68,6 +54,12 @@ public: bool isSavedState() const; void markSavedState(); + ObjectsContainer* getObjects() const { return m_objects; } + + // UndoersCollector interface + void pushUndoer(Undoer* undoer); + + // Backward compatibility methods void undo_open(); void undo_close(); void undo_data(void* object, void* fieldAddress, int fieldSize); @@ -87,8 +79,7 @@ public: void undo_add_palette(Sprite* sprite, Palette* palette); void undo_remove_palette(Sprite* sprite, Palette* palette); void undo_set_palette_colors(Sprite* sprite, Palette* palette, int from, int to); - void undo_remap_palette(Sprite* sprite, int frame_from, int frame_to, - const std::vector& mapping); + void undo_remap_palette(Sprite* sprite, int frame_from, int frame_to, const std::vector& mapping); void undo_set_mask(Document* document); void undo_set_imgtype(Sprite* sprite); void undo_set_size(Sprite* sprite); @@ -104,20 +95,22 @@ public: undo_data(gfxobj, (void*)(value_address), sizeof(double)); } - ObjectsContainer* getObjects() const { return m_objects; } - private: - void runUndo(int state); + enum Direction { UndoDirection, RedoDirection }; + + void runUndo(Direction direction); void discardTail(); void updateUndo(); ObjectsContainer* m_objects; // Container of objects to insert & retrieve objects by ID - UndoStream* m_undoStream; - UndoStream* m_redoStream; + UndoersStack* m_undoers; + UndoersStack* m_redoers; int m_diffCount; int m_diffSaved; bool m_enabled; // Is undo enabled? const char* m_label; // Current label to be applied to all next undo operations. }; -#endif +} // namespace undo + +#endif // UNDO_UNDO_HISTORY_H_INCLUDED diff --git a/src/undo/undo_history_backward.cpp b/src/undo/undo_history_backward.cpp new file mode 100644 index 000000000..3586193dd --- /dev/null +++ b/src/undo/undo_history_backward.cpp @@ -0,0 +1,171 @@ +// ASEPRITE Undo Library +// Copyright (C) 2001-2011 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#include "config.h" + +#include "undo/undo_history.h" + +#include "undo/undoers_stack.h" +#include "undoers/add_cel.h" +#include "undoers/add_image.h" +#include "undoers/add_layer.h" +#include "undoers/add_palette.h" +#include "undoers/close_group.h" +#include "undoers/dirty_area.h" +#include "undoers/flip_image.h" +#include "undoers/image_area.h" +#include "undoers/move_layer.h" +#include "undoers/open_group.h" +#include "undoers/raw_data.h" +#include "undoers/remap_palette.h" +#include "undoers/remove_cel.h" +#include "undoers/remove_image.h" +#include "undoers/remove_layer.h" +#include "undoers/remove_palette.h" +#include "undoers/replace_image.h" +#include "undoers/set_current_frame.h" +#include "undoers/set_current_layer.h" +#include "undoers/set_frame_duration.h" +#include "undoers/set_imgtype.h" +#include "undoers/set_layer_name.h" +#include "undoers/set_mask.h" +#include "undoers/set_palette_colors.h" +#include "undoers/set_sprite_size.h" +#include "undoers/set_total_frames.h" + +using namespace undo; + +void UndoHistory::undo_open() +{ + pushUndoer(new undoers::OpenGroup()); +} + +void UndoHistory::undo_close() +{ + pushUndoer(new undoers::CloseGroup()); +} + +void UndoHistory::undo_data(void* object, void* fieldAddress, int fieldSize) +{ + pushUndoer(new undoers::RawData(getObjects(), object, fieldAddress, fieldSize)); +} + +void UndoHistory::undo_image(Image* image, int x, int y, int w, int h) +{ + pushUndoer(new undoers::ImageArea(getObjects(), image, x, y, w, h)); +} + +void UndoHistory::undo_flip(Image* image, int x1, int y1, int x2, int y2, bool horz) +{ + pushUndoer(new undoers::FlipImage(getObjects(), image, x1, y1, x2-x1+1, y2-y1+1, + (horz ? undoers::FlipImage::FlipHorizontal: + undoers::FlipImage::FlipVertical))); +} + +void UndoHistory::undo_dirty(Image* image, Dirty* dirty) +{ + pushUndoer(new undoers::DirtyArea(getObjects(), image, dirty)); +} + +void UndoHistory::undo_add_image(Stock* stock, int imageIndex) +{ + pushUndoer(new undoers::AddImage(getObjects(), stock, imageIndex)); +} + +void UndoHistory::undo_remove_image(Stock *stock, int imageIndex) +{ + pushUndoer(new undoers::RemoveImage(getObjects(), stock, imageIndex)); +} + +void UndoHistory::undo_replace_image(Stock *stock, int imageIndex) +{ + pushUndoer(new undoers::ReplaceImage(getObjects(), stock, imageIndex)); +} + +void UndoHistory::undo_add_cel(Layer* layer, Cel* cel) +{ + pushUndoer(new undoers::AddCel(getObjects(), layer, cel)); +} + +void UndoHistory::undo_remove_cel(Layer* layer, Cel* cel) +{ + pushUndoer(new undoers::RemoveCel(getObjects(), layer, cel)); +} + +void UndoHistory::undo_set_layer_name(Layer* layer) +{ + pushUndoer(new undoers::SetLayerName(getObjects(), layer)); +} + +void UndoHistory::undo_add_layer(Layer* folder, Layer* layer) +{ + pushUndoer(new undoers::AddLayer(getObjects(), folder, layer)); +} + +void UndoHistory::undo_remove_layer(Layer* layer) +{ + pushUndoer(new undoers::RemoveLayer(getObjects(), layer)); +} + +void UndoHistory::undo_move_layer(Layer* layer) +{ + pushUndoer(new undoers::MoveLayer(getObjects(), layer)); +} + +void UndoHistory::undo_set_layer(Sprite* sprite) +{ + pushUndoer(new undoers::SetCurrentLayer(getObjects(), sprite)); +} + +void UndoHistory::undo_add_palette(Sprite* sprite, Palette* palette) +{ + pushUndoer(new undoers::AddPalette(getObjects(), sprite, palette)); +} + +void UndoHistory::undo_remove_palette(Sprite* sprite, Palette* palette) +{ + pushUndoer(new undoers::RemovePalette(getObjects(), sprite, palette)); +} + +void UndoHistory::undo_set_palette_colors(Sprite* sprite, Palette* palette, int from, int to) +{ + pushUndoer(new undoers::SetPaletteColors(getObjects(), sprite, palette, from, to)); +} + +void UndoHistory::undo_remap_palette(Sprite* sprite, int frameFrom, int frameTo, const std::vector& mapping) +{ + pushUndoer(new undoers::RemapPalette(getObjects(), sprite, frameFrom, frameTo, mapping)); +} + +void UndoHistory::undo_set_mask(Document* document) +{ + pushUndoer(new undoers::SetMask(getObjects(), document)); +} + +void UndoHistory::undo_set_imgtype(Sprite* sprite) +{ + pushUndoer(new undoers::SetImgType(getObjects(), sprite)); +} + +void UndoHistory::undo_set_size(Sprite* sprite) +{ + pushUndoer(new undoers::SetSpriteSize(getObjects(), sprite)); +} + +void UndoHistory::undo_set_frame(Sprite* sprite) +{ + pushUndoer(new undoers::SetCurrentFrame(getObjects(), sprite)); +} + +void UndoHistory::undo_set_frames(Sprite* sprite) +{ + pushUndoer(new undoers::SetTotalFrames(getObjects(), sprite)); +} + +void UndoHistory::undo_set_frlen(Sprite* sprite, int frame) +{ + pushUndoer(new undoers::SetFrameDuration(getObjects(), sprite, frame)); +} diff --git a/src/undo/undo_stream.h b/src/undo/undo_stream.h deleted file mode 100644 index b6cd2fd59..000000000 --- a/src/undo/undo_stream.h +++ /dev/null @@ -1,101 +0,0 @@ -/* ASE - Allegro Sprite Editor - * Copyright (C) 2001-2011 David Capello - * - * 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 - */ - -#ifndef UNDO_UNDO_STREAM_H_INCLUDED -#define UNDO_UNDO_STREAM_H_INCLUDED - -class UndoStream -{ -public: - typedef ChunksList::iterator iterator; - - UndoStream(UndoHistory* undo) - { - m_undo = undo; - m_size = 0; - } - - ~UndoStream() - { - clear(); - } - - UndoHistory* getUndo() const - { - return m_undo; - } - - ObjectsContainer* getObjects() const - { - return m_undo->getObjects(); - } - - iterator begin() { return m_chunks.begin(); } - iterator end() { return m_chunks.end(); } - bool empty() const { return m_chunks.empty(); } - - void clear() - { - iterator it = begin(); - iterator end = this->end(); - for (; it != end; ++it) - undo_chunk_free(*it); - - m_size = 0; - m_chunks.clear(); - } - - int getMemSize() const - { - return m_size; - } - - UndoChunk* popChunk(bool tail) - { - UndoChunk* chunk; - iterator it; - - if (!empty()) { - if (!tail) - it = begin(); - else - it = --end(); - - chunk = *it; - m_chunks.erase(it); - m_size -= chunk->size; - } - else - chunk = NULL; - - return chunk; - } - - void pushChunk(UndoChunk* chunk) - { - m_chunks.insert(begin(), chunk); - m_size += chunk->size; - } - -private: - UndoHistory* m_undo; - ChunksList m_chunks; - int m_size; -}; - -#endif diff --git a/src/undo/undoer.h b/src/undo/undoer.h new file mode 100644 index 000000000..7ed7121b0 --- /dev/null +++ b/src/undo/undoer.h @@ -0,0 +1,47 @@ +// ASEPRITE Undo Library +// Copyright (C) 2001-2011 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef UNDO_UNDOER_H_INCLUDED +#define UNDO_UNDOER_H_INCLUDED + +namespace undo { + +class ObjectsContainer; +class UndoersCollector; + +// Generic interface to undo/revert an action. +class Undoer +{ +public: + virtual ~Undoer() { } + + // Used to destroy the undoer when it is not needed anymore. A + // undoer is added in UndoersCollector, and then destroyed by + // UndoHistory using this method. + // + // This method is available because the Undo library does not know + // how this Undoer was created. So we cannot call just "delete undoer". + virtual void dispose() = 0; + + // Returns the amount of memory (in bytes) which this instance is + // using to revert the action. + virtual int getMemSize() const = 0; + + // Returns true if this undoer is the first action of a group. + virtual bool isOpenGroup() const = 0; + + // Returns true if this undoer is the last action of a group. + virtual bool isCloseGroup() const = 0; + + // Reverts the action and adds to the "redoers" stack other set of + // actions to redo the reverted action. It is the main method used + // to undo any action. + virtual void revert(ObjectsContainer* objects, UndoersCollector* redoers) = 0; +}; + +} // namespace undo + +#endif // UNDO_UNDOER_H_INCLUDED diff --git a/src/undo/undoers_collector.h b/src/undo/undoers_collector.h new file mode 100644 index 000000000..91785077c --- /dev/null +++ b/src/undo/undoers_collector.h @@ -0,0 +1,33 @@ +// ASEPRITE Undo Library +// Copyright (C) 2001-2011 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef UNDO_UNDOERS_COLLECTOR_H_INCLUDED +#define UNDO_UNDOERS_COLLECTOR_H_INCLUDED + +namespace undo { + +class Undoer; +class ObjectsContainer; + +// Simple interface to collect undoers. It's implemented by +// UndoHistory and UndoersStack. +// +// This class is passed to Undoer::revert() so the Undoer can add +// operations (other Undoers) to redo the reverted operation. +class UndoersCollector +{ +public: + virtual ~UndoersCollector() { } + + // Adds a new undoer into the collection. The undoer will be owned + // by the collector, so it will be deleted automatically (using + // Undoer::dispose() method). + virtual void pushUndoer(Undoer* undoer) = 0; +}; + +} // namespace undo + +#endif // UNDO_UNDOERS_COLLECTOR_H_INCLUDED diff --git a/src/undo/undoers_stack.cpp b/src/undo/undoers_stack.cpp new file mode 100644 index 000000000..b613f126d --- /dev/null +++ b/src/undo/undoers_stack.cpp @@ -0,0 +1,138 @@ +// ASEPRITE Undo Library +// Copyright (C) 2001-2011 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#include "config.h" + +#include "undo/undoers_stack.h" + +#include "undo/undo_history.h" +#include "undo/undoer.h" + +using namespace undo; + +UndoersStack::UndoersStack(UndoHistory* undoHistory) +{ + m_undoHistory = undoHistory; + m_size = 0; +} + +UndoersStack::~UndoersStack() +{ + clear(); +} + +void UndoersStack::clear() +{ + for (iterator it = begin(), end = this->end(); it != end; ++it) { + (*it)->getUndoer()->dispose(); // Delete the Undoer. + delete *it; // Delete the UndoersStack::Item. + } + + m_size = 0; + m_items.clear(); // Clear the list of items. +} + +int UndoersStack::getMemSize() const +{ + return m_size; +} + +ObjectsContainer* UndoersStack::getObjects() const +{ + return m_undoHistory->getObjects(); +} + +void UndoersStack::pushUndoer(Undoer* undoer) +{ + ASSERT(undoer != NULL); + + try { + Item* item = new Item(m_undoHistory->getLabel(), undoer); + try { + m_items.insert(begin(), item); + } + catch (...) { + delete item; + throw; + } + } + catch (...) { + undoer->dispose(); + throw; + } + + m_size += undoer->getMemSize(); +} + +Undoer* UndoersStack::popUndoer(PopFrom popFrom) +{ + Undoer* undoer; + iterator it; + + if (!empty()) { + if (popFrom == PopFromHead) + it = begin(); + else + it = --end(); + + undoer = (*it)->getUndoer(); // Set the undoer to return. + delete *it; // Delete the UndoersStack::Item. + m_items.erase(it); // Erase the item from the stack. + m_size -= undoer->getMemSize(); // Reduce the stack size. + } + else + undoer = NULL; + + return undoer; +} + +int UndoersStack::countUndoGroups() const +{ + int groups = 0; + int level; + + const_iterator it = begin(); + while (it != end()) { + level = 0; + + do { + const Undoer* undoer = (*it)->getUndoer(); + ++it; + + if (undoer->isOpenGroup()) + level++; + else if (undoer->isCloseGroup()) + level--; + } while (level && (it != end())); + + if (level == 0) + groups++; + } + + return groups; +} + +bool UndoersStack::isOutOfGroup() const +{ + int level = 0; + + const_iterator it = begin(); + while (it != end()) { + level = 0; + + do { + const Undoer* undoer = (*it)->getUndoer(); + ++it; + + if (undoer->isOpenGroup()) + level++; + else if (undoer->isCloseGroup()) + level--; + } while (level && (it != end())); + } + + return level == 0; +} diff --git a/src/undo/undoers_stack.h b/src/undo/undoers_stack.h new file mode 100644 index 000000000..43d7304b0 --- /dev/null +++ b/src/undo/undoers_stack.h @@ -0,0 +1,87 @@ +// ASEPRITE Undo Library +// Copyright (C) 2001-2011 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef UNDO_UNDOERS_STACK_H_INCLUDED +#define UNDO_UNDOERS_STACK_H_INCLUDED + +#include "undo/undoers_collector.h" + +#include + +namespace undo { + +class UndoHistory; +class Undoer; + +// A stack of undoable actions (Undoers). There exist two stacks (see +// the UndoHistory class): One stack to hold actions to be undone (the +// "undoers stack"), and another stack were actions are held to redo +// reverted actions (the "redoers stack"). +class UndoersStack : public UndoersCollector +{ +public: + enum PopFrom { + PopFromHead, + PopFromTail + }; + + // One item in the stack (label + Undoer) + class Item + { + public: + Item(const char* label, Undoer* undoer) + : m_label(label) + , m_undoer(undoer) { } + const char* getLabel() const { return m_label; } + Undoer* getUndoer() const { return m_undoer; } + + private: + const char* m_label; + Undoer* m_undoer; + }; + + typedef std::vector Items; + typedef Items::iterator iterator; + typedef Items::const_iterator const_iterator; + + // Ctor and dtor + UndoersStack(UndoHistory* undoHistory); + ~UndoersStack(); + + UndoHistory* getUndoHistory() const { return m_undoHistory; } + + // Returns the collection of well-known serialized objects. + ObjectsContainer* getObjects() const; + + iterator begin() { return m_items.begin(); } + iterator end() { return m_items.end(); } + const_iterator begin() const { return m_items.begin(); } + const_iterator end() const { return m_items.end(); } + bool empty() const { return m_items.empty(); } + + void clear(); + + int getMemSize() const; + + // UndoersCollector implementation + void pushUndoer(Undoer* undoer); + + // Removes a undoer from the stack, the returned undoer must be + // deleted by the caller using Undoer::dispose(). + Undoer* popUndoer(PopFrom popFrom); + + int countUndoGroups() const; + bool isOutOfGroup() const; + +private: + UndoHistory* m_undoHistory; + Items m_items; + int m_size; +}; + +} // namespace undo + +#endif // UNDO_UNDOERS_STACK_H_INCLUDED diff --git a/src/undo_transaction.cpp b/src/undo_transaction.cpp index 772d647cb..6b18382d3 100644 --- a/src/undo_transaction.cpp +++ b/src/undo_transaction.cpp @@ -1044,9 +1044,8 @@ void UndoTransaction::setMaskPosition(int x, int y) void UndoTransaction::deselectMask() { - // TODO IMPLEMENT THIS (add support to save values in UndoHistory from any object) - // if (isEnabled()) - // m_undoHistory->undo_int(m_document); + if (isEnabled()) + m_undoHistory->undo_set_mask(m_document); m_document->setMaskVisible(false); } diff --git a/src/undo_transaction.h b/src/undo_transaction.h index a28d329a5..dccbb53ae 100644 --- a/src/undo_transaction.h +++ b/src/undo_transaction.h @@ -28,7 +28,10 @@ class Layer; class LayerImage; class Mask; class Sprite; -class UndoHistory; + +namespace undo { + class UndoHistory; +} // High-level class to group a set of operations to modify the // document atomically, adding information in the undo history to @@ -127,7 +130,7 @@ public: private: Document* m_document; Sprite* m_sprite; - UndoHistory* m_undoHistory; + undo::UndoHistory* m_undoHistory; bool m_committed; bool m_enabledFlag; }; diff --git a/src/undoers/add_cel.cpp b/src/undoers/add_cel.cpp new file mode 100644 index 000000000..172764245 --- /dev/null +++ b/src/undoers/add_cel.cpp @@ -0,0 +1,52 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/add_cel.h" + +#include "raster/cel.h" +#include "raster/layer.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" +#include "undoers/remove_cel.h" + +using namespace undo; +using namespace undoers; + +AddCel::AddCel(ObjectsContainer* objects, Layer* layer, Cel* cel) + : m_layerId(objects->addObject(layer)) + , m_celId(objects->addObject(cel)) +{ +} + +void AddCel::dispose() +{ + delete this; +} + +void AddCel::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + LayerImage* layer = objects->getObjectT(m_layerId); + Cel* cel = objects->getObjectT(m_celId); + + redoers->pushUndoer(new RemoveCel(objects, layer, cel)); + + layer->removeCel(cel); + cel_free(cel); +} diff --git a/src/undoers/add_cel.h b/src/undoers/add_cel.h new file mode 100644 index 000000000..1cf873d34 --- /dev/null +++ b/src/undoers/add_cel.h @@ -0,0 +1,46 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_ADD_CEL_H_INCLUDED +#define UNDOERS_ADD_CEL_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +class Cel; +class Layer; + +namespace undoers { + +class AddCel : public UndoerBase +{ +public: + AddCel(undo::ObjectsContainer* objects, Layer* layer, Cel* cel); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_layerId; + undo::ObjectId m_celId; +}; + +} // namespace undoers + +#endif // UNDOERS_ADD_CEL_H_INCLUDED diff --git a/src/undoers/add_image.cpp b/src/undoers/add_image.cpp new file mode 100644 index 000000000..69827a876 --- /dev/null +++ b/src/undoers/add_image.cpp @@ -0,0 +1,56 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/add_image.h" + +#include "raster/image.h" +#include "raster/stock.h" +#include "undo/objects_container.h" +#include "undo/undo_exception.h" +#include "undo/undoers_collector.h" +#include "undoers/remove_image.h" + +using namespace undo; +using namespace undoers; + +AddImage::AddImage(ObjectsContainer* objects, Stock* stock, int imageIndex) + : m_stockId(objects->addObject(stock)) + , m_imageIndex(imageIndex) +{ +} + +void AddImage::dispose() +{ + delete this; +} + +void AddImage::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Stock* stock = objects->getObjectT(m_stockId); + Image* image = stock->getImage(m_imageIndex); + + if (image == NULL) + throw UndoException("One image was not found in the stock"); + + redoers->pushUndoer(new RemoveImage(objects, stock, m_imageIndex)); + + stock->removeImage(image); + delete image; +} diff --git a/src/undoers/add_image.h b/src/undoers/add_image.h new file mode 100644 index 000000000..51de8c2fa --- /dev/null +++ b/src/undoers/add_image.h @@ -0,0 +1,45 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_ADD_IMAGE_H_INCLUDED +#define UNDOERS_ADD_IMAGE_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +class Stock; + +namespace undoers { + +class AddImage : public UndoerBase +{ +public: + AddImage(undo::ObjectsContainer* objects, Stock* stock, int imageIndex); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_stockId; + uint32_t m_imageIndex; +}; + +} // namespace undoers + +#endif // UNDOERS_ADD_IMAGE_H_INCLUDED diff --git a/src/undoers/add_layer.cpp b/src/undoers/add_layer.cpp new file mode 100644 index 000000000..1088afb31 --- /dev/null +++ b/src/undoers/add_layer.cpp @@ -0,0 +1,51 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/add_layer.h" + +#include "raster/layer.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" +#include "undoers/remove_layer.h" + +using namespace undo; +using namespace undoers; + +AddLayer::AddLayer(ObjectsContainer* objects, Layer* folder, Layer* layer) + : m_folderId(objects->addObject(folder)) + , m_layerId(objects->addObject(layer)) +{ +} + +void AddLayer::dispose() +{ + delete this; +} + +void AddLayer::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + LayerFolder* folder = objects->getObjectT(m_folderId); + Layer* layer = objects->getObjectT(m_layerId); + + redoers->pushUndoer(new RemoveLayer(objects, layer)); + + folder->remove_layer(layer); + delete layer; +} diff --git a/src/undoers/add_layer.h b/src/undoers/add_layer.h new file mode 100644 index 000000000..b1e7eb83d --- /dev/null +++ b/src/undoers/add_layer.h @@ -0,0 +1,45 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_ADD_LAYER_H_INCLUDED +#define UNDOERS_ADD_LAYER_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +class Layer; + +namespace undoers { + +class AddLayer : public UndoerBase +{ +public: + AddLayer(undo::ObjectsContainer* objects, Layer* folder, Layer* layer); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_folderId; + undo::ObjectId m_layerId; +}; + +} // namespace undoers + +#endif // UNDOERS_ADD_LAYER_H_INCLUDED diff --git a/src/undoers/add_palette.cpp b/src/undoers/add_palette.cpp new file mode 100644 index 000000000..cbcc72d02 --- /dev/null +++ b/src/undoers/add_palette.cpp @@ -0,0 +1,50 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/add_palette.h" + +#include "raster/sprite.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" +#include "undoers/remove_palette.h" + +using namespace undo; +using namespace undoers; + +AddPalette::AddPalette(ObjectsContainer* objects, Sprite* sprite, Palette* palette) + : m_spriteId(objects->addObject(sprite)) + , m_paletteId(objects->addObject(palette)) +{ +} + +void AddPalette::dispose() +{ + delete this; +} + +void AddPalette::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Sprite* sprite = objects->getObjectT(m_spriteId); + Palette* palette = objects->getObjectT(m_paletteId); + + redoers->pushUndoer(new RemovePalette(objects, sprite, palette)); + + sprite->deletePalette(palette); +} diff --git a/src/undoers/add_palette.h b/src/undoers/add_palette.h new file mode 100644 index 000000000..1bcd31115 --- /dev/null +++ b/src/undoers/add_palette.h @@ -0,0 +1,46 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_ADD_PALETTE_H_INCLUDED +#define UNDOERS_ADD_PALETTE_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +class Palette; +class Sprite; + +namespace undoers { + +class AddPalette : public UndoerBase +{ +public: + AddPalette(undo::ObjectsContainer* objects, Sprite* sprite, Palette* palette); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_spriteId; + undo::ObjectId m_paletteId; +}; + +} // namespace undoers + +#endif // UNDOERS_ADD_PALETTE_H_INCLUDED diff --git a/src/undoers/close_group.cpp b/src/undoers/close_group.cpp new file mode 100644 index 000000000..1f1846c14 --- /dev/null +++ b/src/undoers/close_group.cpp @@ -0,0 +1,37 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/close_group.h" + +#include "undo/undoers_collector.h" +#include "undoers/open_group.h" + +using namespace undo; +using namespace undoers; + +void CloseGroup::dispose() +{ + delete this; +} + +void CloseGroup::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + redoers->pushUndoer(new OpenGroup()); +} diff --git a/src/undoers/close_group.h b/src/undoers/close_group.h new file mode 100644 index 000000000..ad8022435 --- /dev/null +++ b/src/undoers/close_group.h @@ -0,0 +1,39 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_CLOSE_GROUP_H_INCLUDED +#define UNDOERS_CLOSE_GROUP_H_INCLUDED + +#include "base/compiler_specific.h" +#include "undo/undoer.h" + +namespace undoers { + +class CloseGroup : public undo::Undoer +{ +public: + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + bool isOpenGroup() const OVERRIDE { return false; } + bool isCloseGroup() const OVERRIDE { return true; } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; +}; + +} // namespace undoers + +#endif // UNDOERS_CLOSE_GROUP_H_INCLUDED diff --git a/src/undoers/dirty_area.cpp b/src/undoers/dirty_area.cpp new file mode 100644 index 000000000..b1e203931 --- /dev/null +++ b/src/undoers/dirty_area.cpp @@ -0,0 +1,55 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/dirty_area.h" + +#include "base/unique_ptr.h" +#include "raster/dirty.h" +#include "raster/dirty_io.h" +#include "raster/image.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" + +using namespace undo; +using namespace undoers; + +DirtyArea::DirtyArea(ObjectsContainer* objects, Image* image, Dirty* dirty) + : m_imageId(objects->addObject(image)) +{ + raster::write_dirty(m_stream, dirty); +} + +void DirtyArea::dispose() +{ + delete this; +} + +void DirtyArea::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Image* image = objects->getObjectT(m_imageId); + UniquePtr dirty(raster::read_dirty(m_stream)); + + // Swap the saved pixels in the dirty with the pixels in the image + dirty->swapImagePixels(image); + + // Save the dirty in the "redoers" (the dirty area now contains the + // pixels before the undo) + redoers->pushUndoer(new DirtyArea(objects, image, dirty)); +} diff --git a/src/undoers/dirty_area.h b/src/undoers/dirty_area.h new file mode 100644 index 000000000..fff95c48e --- /dev/null +++ b/src/undoers/dirty_area.h @@ -0,0 +1,52 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_DIRTY_AREA_H_INCLUDED +#define UNDOERS_DIRTY_AREA_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Dirty; +class Image; + +namespace undoers { + +class DirtyArea : public UndoerBase +{ +public: + DirtyArea(undo::ObjectsContainer* objects, Image* image, Dirty* dirty); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this) + getStreamSize(); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + size_t getStreamSize() const { + return const_cast(&m_stream)->tellp(); + } + + undo::ObjectId m_imageId; + std::stringstream m_stream; +}; + +} // namespace undoers + +#endif // UNDOERS_DIRTY_AREA_H_INCLUDED diff --git a/src/undoers/flip_image.cpp b/src/undoers/flip_image.cpp new file mode 100644 index 000000000..f3405d8b1 --- /dev/null +++ b/src/undoers/flip_image.cpp @@ -0,0 +1,67 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/flip_image.h" + +#include "base/unique_ptr.h" +#include "raster/image.h" +#include "undo/objects_container.h" +#include "undo/undo_exception.h" +#include "undo/undoers_collector.h" + +using namespace undo; +using namespace undoers; + +FlipImage::FlipImage(ObjectsContainer* objects, Image* image, int x, int y, int w, int h, FlipType flipType) + : m_imageId(objects->addObject(image)) + , m_imgtype(image->imgtype) + , m_x(x), m_y(y), m_w(w), m_h(h) + , m_flipType(flipType) +{ + ASSERT(w >= 1 && h >= 1); + ASSERT(x >= 0 && y >= 0 && x+w <= image->w && y+h <= image->h); +} + +void FlipImage::dispose() +{ + delete this; +} + +void FlipImage::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Image* image = objects->getObjectT(m_imageId); + + if (image->imgtype != m_imgtype) + throw UndoException("Image type does not match"); + + redoers->pushUndoer(new FlipImage(objects, image, m_x, m_y, m_w, m_h, m_flipType)); + + UniquePtr area(image_crop(image, m_x, m_y, m_w, m_h, 0)); + int x, y; + int x2 = m_x+m_w-1; + int y2 = m_y+m_h-1; + + for (y=0; yaddObject(image)) + , m_imgtype(image->imgtype) + , m_x(x), m_y(y), m_w(w), m_h(h) + , m_lineSize(image_line_size(image, w)) + , m_data(m_lineSize * h) +{ + ASSERT(w >= 1 && h >= 1); + ASSERT(x >= 0 && y >= 0 && x+w <= image->w && y+h <= image->h); + + for (int v=0; vgetObjectT(m_imageId); + + if (image->imgtype != m_imgtype) + throw UndoException("Image type does not match"); + + // Backup the current image portion + redoers->pushUndoer(new ImageArea(objects, image, m_x, m_y, m_w, m_h)); + + // Restore the old image portion + for (int v=0; v + +class Image; + +namespace undoers { + +class ImageArea : public UndoerBase +{ +public: + ImageArea(undo::ObjectsContainer* objects, Image* image, int x, int y, int w, int h); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this) + m_data.size(); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_imageId; + uint8_t m_imgtype; + uint16_t m_x, m_y, m_w, m_h; + uint32_t m_lineSize; + std::vector m_data; +}; + +} // namespace undoers + +#endif // UNDOERS_IMAGE_AREA_H_INCLUDED diff --git a/src/undoers/move_layer.cpp b/src/undoers/move_layer.cpp new file mode 100644 index 000000000..9cf3252f2 --- /dev/null +++ b/src/undoers/move_layer.cpp @@ -0,0 +1,55 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/move_layer.h" + +#include "raster/layer.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" + +using namespace undo; +using namespace undoers; + +MoveLayer::MoveLayer(ObjectsContainer* objects, Layer* layer) + : m_folderId(objects->addObject(layer->get_parent())) + , m_layerId(objects->addObject(layer)) +{ + Layer* after = layer->get_prev(); + + m_afterId = (after ? objects->addObject(after): 0); +} + +void MoveLayer::dispose() +{ + delete this; +} + +void MoveLayer::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + LayerFolder* folder = objects->getObjectT(m_folderId); + Layer* layer = objects->getObjectT(m_layerId); + Layer* after = (m_afterId ? objects->getObjectT(m_afterId): NULL); + + // Backup the current layer position + redoers->pushUndoer(new MoveLayer(objects, layer)); + + // Move the layer + folder->move_layer(layer, after); +} diff --git a/src/undoers/move_layer.h b/src/undoers/move_layer.h new file mode 100644 index 000000000..8cb3fbd91 --- /dev/null +++ b/src/undoers/move_layer.h @@ -0,0 +1,46 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_MOVE_LAYER_H_INCLUDED +#define UNDOERS_MOVE_LAYER_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +class Layer; + +namespace undoers { + +class MoveLayer : public UndoerBase +{ +public: + MoveLayer(undo::ObjectsContainer* objects, Layer* layer); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_folderId; + undo::ObjectId m_layerId; + undo::ObjectId m_afterId; +}; + +} // namespace undoers + +#endif // UNDOERS_MOVE_LAYER_H_INCLUDED diff --git a/src/undoers/object_io.h b/src/undoers/object_io.h new file mode 100644 index 000000000..b96b83653 --- /dev/null +++ b/src/undoers/object_io.h @@ -0,0 +1,71 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_OBJECT_IO_H_INCLUDED +#define UNDOERS_OBJECT_IO_H_INCLUDED + +#include "base/serialization.h" +#include "base/unique_ptr.h" + +namespace undo { + class ObjectsContainer; +} + +namespace undoers { + +// read_object and write_object functions can be used to serialize an +// object into a stream, and restore it back into the memory with the +// same ID which were assigned in the ObjectsContainer previously. + +// Serializes the given object into the stream identifying it with an +// ID from the ObjectsContainer. When the object is deserialized with +// read_object, the object is added to the container with the same ID. +template +void write_object(undo::ObjectsContainer* objects, std::ostream& os, T* object, Writer& writer) +{ + using base::serialization::little_endian::write32; + + // Get an ID for the image. + undo::ObjectId objectId = objects->addObject(object); + + write32(os, objectId); // Write the ID + writer(os, object); // Write the object + + // Remove the object from the container (it will be + // re-added by a undoers::read_object call). + objects->removeObject(objectId); +} + +// Deserializes the given object from the stream, adding the object +// into the ObjectsContainer with the same ID saved with write_object(). +template +T* read_object(undo::ObjectsContainer* objects, std::istream& is, Reader& reader) +{ + using base::serialization::little_endian::read32; + + undo::ObjectId objectId = read32(is); // Read the ID + UniquePtr object(reader(is)); // Read the object + + // Re-insert the object in the container with the read ID. + objects->insertObject(objectId, object); + return object.release(); +} + +} // namespace undoers + +#endif // UNDOERS_OBJECT_IO_H_INCLUDED diff --git a/src/undoers/open_group.cpp b/src/undoers/open_group.cpp new file mode 100644 index 000000000..2217602a6 --- /dev/null +++ b/src/undoers/open_group.cpp @@ -0,0 +1,37 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/open_group.h" + +#include "undo/undoers_collector.h" +#include "undoers/close_group.h" + +using namespace undo; +using namespace undoers; + +void OpenGroup::dispose() +{ + delete this; +} + +void OpenGroup::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + redoers->pushUndoer(new CloseGroup()); +} diff --git a/src/undoers/open_group.h b/src/undoers/open_group.h new file mode 100644 index 000000000..c1ed8f0b7 --- /dev/null +++ b/src/undoers/open_group.h @@ -0,0 +1,39 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_OPEN_GROUP_H_INCLUDED +#define UNDOERS_OPEN_GROUP_H_INCLUDED + +#include "base/compiler_specific.h" +#include "undo/undoer.h" + +namespace undoers { + +class OpenGroup : public undo::Undoer +{ +public: + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + bool isOpenGroup() const OVERRIDE { return true; } + bool isCloseGroup() const OVERRIDE { return false; } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; +}; + +} // namespace undoers + +#endif // UNDOERS_OPEN_GROUP_H_INCLUDED diff --git a/src/undoers/raw_data.cpp b/src/undoers/raw_data.cpp new file mode 100644 index 000000000..751678b05 --- /dev/null +++ b/src/undoers/raw_data.cpp @@ -0,0 +1,52 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/raw_data.h" + +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" + +using namespace undo; +using namespace undoers; + +RawData::RawData(ObjectsContainer* objects, void* object, void* fieldAddress, int fieldSize) + : m_objectId(objects->addObject(object)) + , m_offset((uint32_t)(((uint8_t*)fieldAddress) - ((uint8_t*)object))) + , m_data(fieldSize) +{ + memcpy(&m_data[0], fieldAddress, m_data.size()); +} + +void RawData::dispose() +{ + delete this; +} + +void RawData::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + void* object = objects->getObject(m_objectId); + void* fieldAddress = (void*)(((uint8_t*)object) + m_offset); + + // Save the current data + redoers->pushUndoer(new RawData(objects, object, fieldAddress, m_data.size())); + + // Copy back the old data + memcpy(fieldAddress, &m_data[0], m_data.size()); +} diff --git a/src/undoers/raw_data.h b/src/undoers/raw_data.h new file mode 100644 index 000000000..948715eb8 --- /dev/null +++ b/src/undoers/raw_data.h @@ -0,0 +1,46 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_RAW_DATA_H_INCLUDED +#define UNDOERS_RAW_DATA_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +namespace undoers { + +class RawData : public UndoerBase +{ +public: + RawData(undo::ObjectsContainer* objects, void* object, void* fieldAddress, int fieldSize); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this) + m_data.size(); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_objectId; + uint32_t m_offset; + std::vector m_data; +}; + +} // namespace undoers + +#endif // UNDOERS_RAW_DATA_H_INCLUDED diff --git a/src/undoers/remap_palette.cpp b/src/undoers/remap_palette.cpp new file mode 100644 index 000000000..25bdc20ac --- /dev/null +++ b/src/undoers/remap_palette.cpp @@ -0,0 +1,60 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/remap_palette.h" + +#include "raster/sprite.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" +#include "undoers/add_cel.h" +#include "undoers/object_io.h" + +using namespace undo; +using namespace undoers; + +RemapPalette::RemapPalette(ObjectsContainer* objects, Sprite* sprite, int frameFrom, int frameTo, const std::vector& mapping) + : m_spriteId(objects->addObject(sprite)) + , m_frameFrom(frameFrom) + , m_frameTo(frameTo) + , m_mapping(mapping) +{ + ASSERT(mapping.size() == 256 && "Mapping tables must have 256 entries"); +} + +void RemapPalette::dispose() +{ + delete this; +} + +void RemapPalette::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Sprite* sprite = objects->getObjectT(m_spriteId); + + // Inverse mapping + std::vector inverse_mapping(m_mapping.size()); + for (size_t c=0; cpushUndoer(new RemapPalette(objects, sprite, m_frameFrom, m_frameTo, inverse_mapping)); + + // Remap in inverse order + sprite->remapImages(m_frameFrom, m_frameTo, inverse_mapping); +} diff --git a/src/undoers/remap_palette.h b/src/undoers/remap_palette.h new file mode 100644 index 000000000..a0f3fc0ed --- /dev/null +++ b/src/undoers/remap_palette.h @@ -0,0 +1,49 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_REMAP_PALETTE_H_INCLUDED +#define UNDOERS_REMAP_PALETTE_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Sprite; + +namespace undoers { + +class RemapPalette : public UndoerBase +{ +public: + RemapPalette(undo::ObjectsContainer* objects, Sprite* sprite, int frameFrom, int frameTo, const std::vector& mapping); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_spriteId; + uint32_t m_frameFrom; + uint32_t m_frameTo; + std::vector m_mapping; +}; + +} // namespace undoers + +#endif // UNDOERS_REMAP_PALETTE_H_INCLUDED diff --git a/src/undoers/remove_cel.cpp b/src/undoers/remove_cel.cpp new file mode 100644 index 000000000..a809adcc7 --- /dev/null +++ b/src/undoers/remove_cel.cpp @@ -0,0 +1,55 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/remove_cel.h" + +#include "raster/cel.h" +#include "raster/cel_io.h" +#include "raster/layer.h" +#include "raster/stock.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" +#include "undoers/add_cel.h" +#include "undoers/object_io.h" + +using namespace undo; +using namespace undoers; + +RemoveCel::RemoveCel(ObjectsContainer* objects, Layer* layer, Cel* cel) + : m_layerId(objects->addObject(layer)) +{ + write_object(objects, m_stream, cel, raster::write_cel); +} + +void RemoveCel::dispose() +{ + delete this; +} + +void RemoveCel::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + LayerImage* layer = objects->getObjectT(m_layerId); + Cel* cel = read_object(objects, m_stream, raster::read_cel); + + // Push an AddCel as redoer + redoers->pushUndoer(new AddCel(objects, layer, cel)); + + layer->addCel(cel); +} diff --git a/src/undoers/remove_cel.h b/src/undoers/remove_cel.h new file mode 100644 index 000000000..42d6294c8 --- /dev/null +++ b/src/undoers/remove_cel.h @@ -0,0 +1,52 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_REMOVE_CEL_H_INCLUDED +#define UNDOERS_REMOVE_CEL_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Cel; +class Layer; + +namespace undoers { + +class RemoveCel : public UndoerBase +{ +public: + RemoveCel(undo::ObjectsContainer* objects, Layer* layer, Cel* cel); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this) + getStreamSize(); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + size_t getStreamSize() const { + return const_cast(&m_stream)->tellp(); + } + + undo::ObjectId m_layerId; + std::stringstream m_stream; +}; + +} // namespace undoers + +#endif // UNDOERS_REMOVE_CEL_H_INCLUDED diff --git a/src/undoers/remove_image.cpp b/src/undoers/remove_image.cpp new file mode 100644 index 000000000..bad92ce4b --- /dev/null +++ b/src/undoers/remove_image.cpp @@ -0,0 +1,57 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/remove_image.h" + +#include "raster/image.h" +#include "raster/image_io.h" +#include "raster/stock.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" +#include "undoers/add_image.h" +#include "undoers/object_io.h" + +using namespace undo; +using namespace undoers; + +RemoveImage::RemoveImage(ObjectsContainer* objects, Stock* stock, int imageIndex) + : m_stockId(objects->addObject(stock)) + , m_imageIndex(imageIndex) +{ + Image* image = stock->getImage(imageIndex); + + write_object(objects, m_stream, image, raster::write_image); +} + +void RemoveImage::dispose() +{ + delete this; +} + +void RemoveImage::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Stock* stock = objects->getObjectT(m_stockId); + Image* image = read_object(objects, m_stream, raster::read_image); + + // Push an AddImage as redoer + redoers->pushUndoer(new AddImage(objects, stock, m_imageIndex)); + + stock->replaceImage(m_imageIndex, image); +} diff --git a/src/undoers/remove_image.h b/src/undoers/remove_image.h new file mode 100644 index 000000000..0563c2441 --- /dev/null +++ b/src/undoers/remove_image.h @@ -0,0 +1,52 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_REMOVE_IMAGE_H_INCLUDED +#define UNDOERS_REMOVE_IMAGE_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Stock; + +namespace undoers { + +class RemoveImage : public UndoerBase +{ +public: + RemoveImage(undo::ObjectsContainer* objects, Stock* stock, int imageIndex); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this) + getStreamSize(); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + size_t getStreamSize() const { + return const_cast(&m_stream)->tellp(); + } + + undo::ObjectId m_stockId; + uint32_t m_imageIndex; + std::stringstream m_stream; +}; + +} // namespace undoers + +#endif // UNDOERS_REMOVE_IMAGE_H_INCLUDED diff --git a/src/undoers/remove_layer.cpp b/src/undoers/remove_layer.cpp new file mode 100644 index 000000000..707559a54 --- /dev/null +++ b/src/undoers/remove_layer.cpp @@ -0,0 +1,120 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/remove_layer.h" + +#include "raster/cel.h" +#include "raster/cel_io.h" +#include "raster/image.h" +#include "raster/image_io.h" +#include "raster/layer.h" +#include "raster/layer_io.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" +#include "undoers/add_layer.h" +#include "undoers/object_io.h" + +using namespace undo; +using namespace undoers; + +class LayerSubObjectsSerializerImpl : public raster::LayerSubObjectsSerializer +{ +public: + LayerSubObjectsSerializerImpl(ObjectsContainer* objects, Sprite* sprite) + : m_objects(objects) + , m_sprite(sprite) { + } + + virtual ~LayerSubObjectsSerializerImpl() { } + + // How to write cels, images, and sub-layers + void write_cel(std::ostream& os, Cel* cel) OVERRIDE { + write_object(m_objects, os, cel, raster::write_cel); + } + + void write_image(std::ostream& os, Image* image) OVERRIDE { + write_object(m_objects, os, image, raster::write_image); + } + + void write_layer(std::ostream& os, Layer* layer) OVERRIDE { + // To write a sub-layer we use the operator() of this instance (*this) + write_object(m_objects, os, layer, *this); + } + + // How to read cels, images, and sub-layers + Cel* read_cel(std::istream& is) OVERRIDE { + return read_object(m_objects, is, raster::read_cel); + } + + Image* read_image(std::istream& is) OVERRIDE { + return read_object(m_objects, is, raster::read_image); + } + + Layer* read_layer(std::istream& is) OVERRIDE { + // To read a sub-layer we use the operator() of this instance (*this) + return read_object(m_objects, is, *this); + } + + // The following operator() calls are used in write/read_object() functions. + + void operator()(std::ostream& os, Layer* layer) { + raster::write_layer(os, this, layer); + } + + Layer* operator()(std::istream& is) { + return raster::read_layer(is, this, m_sprite); + } + +private: + ObjectsContainer* m_objects; + Sprite* m_sprite; +}; + +RemoveLayer::RemoveLayer(ObjectsContainer* objects, Layer* layer) + : m_folderId(objects->addObject(layer->get_parent())) +{ + Layer* after = layer->get_prev(); + + m_afterId = (after ? objects->addObject(after): 0); + + LayerSubObjectsSerializerImpl serializer(objects, layer->getSprite()); + write_object(objects, m_stream, layer, serializer); +} + +void RemoveLayer::dispose() +{ + delete this; +} + +void RemoveLayer::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + LayerFolder* folder = objects->getObjectT(m_folderId); + Layer* after = (m_afterId != 0 ? objects->getObjectT(m_afterId): NULL); + + // Read the layer from the stream + LayerSubObjectsSerializerImpl serializer(objects, folder->getSprite()); + Layer* layer = read_object(objects, m_stream, serializer); + + // Push an AddLayer as redoer + redoers->pushUndoer(new AddLayer(objects, folder, layer)); + + folder->add_layer(layer); + folder->move_layer(layer, after); +} diff --git a/src/undoers/remove_layer.h b/src/undoers/remove_layer.h new file mode 100644 index 000000000..3fa61fd20 --- /dev/null +++ b/src/undoers/remove_layer.h @@ -0,0 +1,52 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_REMOVE_LAYER_H_INCLUDED +#define UNDOERS_REMOVE_LAYER_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Layer; + +namespace undoers { + +class RemoveLayer : public UndoerBase +{ +public: + RemoveLayer(undo::ObjectsContainer* objects, Layer* layer); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this) + getStreamSize(); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + size_t getStreamSize() const { + return const_cast(&m_stream)->tellp(); + } + + undo::ObjectId m_folderId; + undo::ObjectId m_afterId; + std::stringstream m_stream; +}; + +} // namespace undoers + +#endif // UNDOERS_REMOVE_LAYER_H_INCLUDED diff --git a/src/undoers/remove_palette.cpp b/src/undoers/remove_palette.cpp new file mode 100644 index 000000000..abf655ac1 --- /dev/null +++ b/src/undoers/remove_palette.cpp @@ -0,0 +1,57 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/remove_palette.h" + +#include "raster/palette.h" +#include "raster/palette_io.h" +#include "raster/sprite.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" +#include "undoers/add_palette.h" +#include "undoers/object_io.h" + +using namespace undo; +using namespace undoers; + +RemovePalette::RemovePalette(ObjectsContainer* objects, Sprite* sprite, Palette* palette) + : m_spriteId(objects->addObject(sprite)) +{ + write_object(objects, m_stream, palette, raster::write_palette); +} + +void RemovePalette::dispose() +{ + delete this; +} + +void RemovePalette::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Sprite* sprite = objects->getObjectT(m_spriteId); + UniquePtr palette(read_object(objects, m_stream, raster::read_palette)); + + // Push an AddPalette as redoer + redoers->pushUndoer(new AddPalette(objects, sprite, palette)); + + sprite->setPalette(palette, true); + + // Here the palette is deleted by UniquePtr<>, it is needed becase + // Sprite::setPalette() makes a copy of the given palette. +} diff --git a/src/undoers/remove_palette.h b/src/undoers/remove_palette.h new file mode 100644 index 000000000..156f73582 --- /dev/null +++ b/src/undoers/remove_palette.h @@ -0,0 +1,52 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_REMOVE_PALETTE_H_INCLUDED +#define UNDOERS_REMOVE_PALETTE_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Palette; +class Sprite; + +namespace undoers { + +class RemovePalette : public UndoerBase +{ +public: + RemovePalette(undo::ObjectsContainer* objects, Sprite* sprite, Palette* palette); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this) + getStreamSize(); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + size_t getStreamSize() const { + return const_cast(&m_stream)->tellp(); + } + + undo::ObjectId m_spriteId; + std::stringstream m_stream; +}; + +} // namespace undoers + +#endif // UNDOERS_REMOVE_PALETTE_H_INCLUDED diff --git a/src/undoers/replace_image.cpp b/src/undoers/replace_image.cpp new file mode 100644 index 000000000..a9d8099ed --- /dev/null +++ b/src/undoers/replace_image.cpp @@ -0,0 +1,63 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/replace_image.h" + +#include "raster/image.h" +#include "raster/image_io.h" +#include "raster/stock.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" +#include "undoers/object_io.h" + +using namespace undo; +using namespace undoers; + +ReplaceImage::ReplaceImage(ObjectsContainer* objects, Stock* stock, int imageIndex) + : m_stockId(objects->addObject(stock)) + , m_imageIndex(imageIndex) +{ + Image* image = stock->getImage(imageIndex); + + write_object(objects, m_stream, image, raster::write_image); +} + +void ReplaceImage::dispose() +{ + delete this; +} + +void ReplaceImage::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Stock* stock = objects->getObjectT(m_stockId); + + // Read the image to be restored from the stream + Image* image = read_object(objects, m_stream, raster::read_image); + + // Save the current image in the redoers + redoers->pushUndoer(new ReplaceImage(objects, stock, m_imageIndex)); + Image* oldImage = stock->getImage(m_imageIndex); + + // Replace the image in the stock + stock->replaceImage(m_imageIndex, image); + + // destroy the old image + image_free(oldImage); +} diff --git a/src/undoers/replace_image.h b/src/undoers/replace_image.h new file mode 100644 index 000000000..3cfe866f8 --- /dev/null +++ b/src/undoers/replace_image.h @@ -0,0 +1,52 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_REPLACE_IMAGE_H_INCLUDED +#define UNDOERS_REPLACE_IMAGE_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Stock; + +namespace undoers { + +class ReplaceImage : public UndoerBase +{ +public: + ReplaceImage(undo::ObjectsContainer* objects, Stock* stock, int imageIndex); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this) + getStreamSize(); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + size_t getStreamSize() const { + return const_cast(&m_stream)->tellp(); + } + + undo::ObjectId m_stockId; + uint32_t m_imageIndex; + std::stringstream m_stream; +}; + +} // namespace undoers + +#endif // UNDOERS_REPLACE_IMAGE_H_INCLUDED diff --git a/src/undoers/set_current_frame.cpp b/src/undoers/set_current_frame.cpp new file mode 100644 index 000000000..8065323b2 --- /dev/null +++ b/src/undoers/set_current_frame.cpp @@ -0,0 +1,49 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/set_current_frame.h" + +#include "raster/sprite.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" + +using namespace undo; +using namespace undoers; + +SetCurrentFrame::SetCurrentFrame(ObjectsContainer* objects, Sprite* sprite) + : m_spriteId(objects->addObject(sprite)) + , m_frame(sprite->getCurrentFrame()) +{ +} + +void SetCurrentFrame::dispose() +{ + delete this; +} + +void SetCurrentFrame::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Sprite* sprite = objects->getObjectT(m_spriteId); + + // Push another SetCurrentFrame as redoer + redoers->pushUndoer(new SetCurrentFrame(objects, sprite)); + + sprite->setCurrentFrame(m_frame); +} diff --git a/src/undoers/set_current_frame.h b/src/undoers/set_current_frame.h new file mode 100644 index 000000000..803da2e3c --- /dev/null +++ b/src/undoers/set_current_frame.h @@ -0,0 +1,47 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_SET_CURRENT_FRAME_H_INCLUDED +#define UNDOERS_SET_CURRENT_FRAME_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Sprite; + +namespace undoers { + +class SetCurrentFrame : public UndoerBase +{ +public: + SetCurrentFrame(undo::ObjectsContainer* objects, Sprite* sprite); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_spriteId; + uint32_t m_frame; +}; + +} // namespace undoers + +#endif // UNDOERS_SET_CURRENT_FRAME_H_INCLUDED diff --git a/src/undoers/set_current_layer.cpp b/src/undoers/set_current_layer.cpp new file mode 100644 index 000000000..5c6f02e71 --- /dev/null +++ b/src/undoers/set_current_layer.cpp @@ -0,0 +1,50 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/set_current_layer.h" + +#include "raster/sprite.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" + +using namespace undo; +using namespace undoers; + +SetCurrentLayer::SetCurrentLayer(ObjectsContainer* objects, Sprite* sprite) + : m_spriteId(objects->addObject(sprite)) + , m_layerId(sprite->getCurrentLayer() ? objects->addObject(sprite->getCurrentLayer()): 0) +{ +} + +void SetCurrentLayer::dispose() +{ + delete this; +} + +void SetCurrentLayer::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Sprite* sprite = objects->getObjectT(m_spriteId); + Layer* layer = (m_layerId ? objects->getObjectT(m_layerId): NULL); + + // Push another SetCurrentLayer as redoer + redoers->pushUndoer(new SetCurrentLayer(objects, sprite)); + + sprite->setCurrentLayer(layer); +} diff --git a/src/undoers/set_current_layer.h b/src/undoers/set_current_layer.h new file mode 100644 index 000000000..4d29b58f6 --- /dev/null +++ b/src/undoers/set_current_layer.h @@ -0,0 +1,47 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_SET_CURRENT_LAYER_H_INCLUDED +#define UNDOERS_SET_CURRENT_LAYER_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Sprite; + +namespace undoers { + +class SetCurrentLayer : public UndoerBase +{ +public: + SetCurrentLayer(undo::ObjectsContainer* objects, Sprite* sprite); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_spriteId; + undo::ObjectId m_layerId; +}; + +} // namespace undoers + +#endif // UNDOERS_SET_CURRENT_LAYER_H_INCLUDED diff --git a/src/undoers/set_frame_duration.cpp b/src/undoers/set_frame_duration.cpp new file mode 100644 index 000000000..d56ac4ef0 --- /dev/null +++ b/src/undoers/set_frame_duration.cpp @@ -0,0 +1,52 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/set_frame_duration.h" + +#include "raster/sprite.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" + +using namespace undo; +using namespace undoers; + +SetFrameDuration::SetFrameDuration(ObjectsContainer* objects, Sprite* sprite, int frame) + : m_spriteId(objects->addObject(sprite)) + , m_frame(frame) +{ + ASSERT(frame >= 0 && frame < sprite->getTotalFrames()); + + m_duration = sprite->getFrameDuration(frame); +} + +void SetFrameDuration::dispose() +{ + delete this; +} + +void SetFrameDuration::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Sprite* sprite = objects->getObjectT(m_spriteId); + + // Push another SetFrameDuration as redoer + redoers->pushUndoer(new SetFrameDuration(objects, sprite, m_frame)); + + sprite->setFrameDuration(m_frame, m_duration); +} diff --git a/src/undoers/set_frame_duration.h b/src/undoers/set_frame_duration.h new file mode 100644 index 000000000..b1ff2409b --- /dev/null +++ b/src/undoers/set_frame_duration.h @@ -0,0 +1,46 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_SET_FRAME_DURATION_H_INCLUDED +#define UNDOERS_SET_FRAME_DURATION_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +class Sprite; + +namespace undoers { + +class SetFrameDuration : public UndoerBase +{ +public: + SetFrameDuration(undo::ObjectsContainer* objects, Sprite* sprite, int frame); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_spriteId; + uint32_t m_frame; + uint32_t m_duration; +}; + +} // namespace undoers + +#endif // UNDOERS_SET_FRAME_DURATION_H_INCLUDED diff --git a/src/undoers/set_imgtype.cpp b/src/undoers/set_imgtype.cpp new file mode 100644 index 000000000..d73efb188 --- /dev/null +++ b/src/undoers/set_imgtype.cpp @@ -0,0 +1,49 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/set_imgtype.h" + +#include "raster/sprite.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" + +using namespace undo; +using namespace undoers; + +SetImgType::SetImgType(ObjectsContainer* objects, Sprite* sprite) + : m_spriteId(objects->addObject(sprite)) + , m_imgtype(sprite->getImgType()) +{ +} + +void SetImgType::dispose() +{ + delete this; +} + +void SetImgType::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Sprite* sprite = objects->getObjectT(m_spriteId); + + // Push another SetImgType as redoer + redoers->pushUndoer(new SetImgType(objects, sprite)); + + sprite->setImgType(m_imgtype); +} diff --git a/src/undoers/set_imgtype.h b/src/undoers/set_imgtype.h new file mode 100644 index 000000000..e802e932e --- /dev/null +++ b/src/undoers/set_imgtype.h @@ -0,0 +1,45 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_SET_IMGTYPE_H_INCLUDED +#define UNDOERS_SET_IMGTYPE_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +class Sprite; + +namespace undoers { + +class SetImgType : public UndoerBase +{ +public: + SetImgType(undo::ObjectsContainer* objects, Sprite* sprite); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_spriteId; + uint32_t m_imgtype; +}; + +} // namespace undoers + +#endif // UNDOERS_SET_IMGTYPE_H_INCLUDED diff --git a/src/undoers/set_layer_name.cpp b/src/undoers/set_layer_name.cpp new file mode 100644 index 000000000..ce80ce0f3 --- /dev/null +++ b/src/undoers/set_layer_name.cpp @@ -0,0 +1,49 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/set_layer_name.h" + +#include "raster/layer.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" + +using namespace undo; +using namespace undoers; + +SetLayerName::SetLayerName(ObjectsContainer* objects, Layer* layer) + : m_layerId(objects->addObject(layer)) + , m_name(layer->getName()) +{ +} + +void SetLayerName::dispose() +{ + delete this; +} + +void SetLayerName::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Layer* layer = objects->getObjectT(m_layerId); + + // Push another SetLayerName as redoer + redoers->pushUndoer(new SetLayerName(objects, layer)); + + layer->setName(m_name.c_str()); +} diff --git a/src/undoers/set_layer_name.h b/src/undoers/set_layer_name.h new file mode 100644 index 000000000..20cb81aa5 --- /dev/null +++ b/src/undoers/set_layer_name.h @@ -0,0 +1,47 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_SET_LAYER_NAME_H_INCLUDED +#define UNDOERS_SET_LAYER_NAME_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Layer; + +namespace undoers { + +class SetLayerName : public UndoerBase +{ +public: + SetLayerName(undo::ObjectsContainer* objects, Layer* layer); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this) + m_name.size(); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_layerId; + std::string m_name; +}; + +} // namespace undoers + +#endif // UNDOERS_SET_LAYER_NAME_H_INCLUDED diff --git a/src/undoers/set_mask.cpp b/src/undoers/set_mask.cpp new file mode 100644 index 000000000..a2481f9c5 --- /dev/null +++ b/src/undoers/set_mask.cpp @@ -0,0 +1,64 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/set_mask.h" + +#include "base/unique_ptr.h" +#include "document.h" +#include "raster/mask.h" +#include "raster/mask_io.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" +#include "undoers/object_io.h" + +using namespace undo; +using namespace undoers; + +SetMask::SetMask(ObjectsContainer* objects, Document* document) + : m_documentId(objects->addObject(document)) + , m_isMaskVisible(document->isMaskVisible()) +{ + if (m_isMaskVisible) + write_object(objects, m_stream, document->getMask(), raster::write_mask); +} + +void SetMask::dispose() +{ + delete this; +} + +void SetMask::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Document* document = objects->getObjectT(m_documentId); + + // Push another SetMask as redoer + redoers->pushUndoer(new SetMask(objects, document)); + + if (m_isMaskVisible) { + UniquePtr mask(read_object(objects, m_stream, raster::read_mask)); + + document->setMask(mask); + + // Document::setMask() makes a copy of the mask, so here the mask + // is deleted with the UniquePtr. + } + else + document->setMaskVisible(false); +} diff --git a/src/undoers/set_mask.h b/src/undoers/set_mask.h new file mode 100644 index 000000000..8a65cdbf7 --- /dev/null +++ b/src/undoers/set_mask.h @@ -0,0 +1,52 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_SET_MASK_H_INCLUDED +#define UNDOERS_SET_MASK_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Document; + +namespace undoers { + +class SetMask : public UndoerBase +{ +public: + SetMask(undo::ObjectsContainer* objects, Document* document); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this) + getStreamSize(); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + size_t getStreamSize() const { + return const_cast(&m_stream)->tellp(); + } + + undo::ObjectId m_documentId; + bool m_isMaskVisible; + std::stringstream m_stream; +}; + +} // namespace undoers + +#endif // UNDOERS_SET_MASK_H_INCLUDED diff --git a/src/undoers/set_palette_colors.cpp b/src/undoers/set_palette_colors.cpp new file mode 100644 index 000000000..81034ae36 --- /dev/null +++ b/src/undoers/set_palette_colors.cpp @@ -0,0 +1,66 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/set_palette_colors.h" + +#include "base/serialization.h" +#include "raster/palette.h" +#include "raster/sprite.h" +#include "undo/objects_container.h" +#include "undo/undo_exception.h" +#include "undo/undoers_collector.h" + +using namespace undo; +using namespace undoers; +using namespace base::serialization::little_endian; + +SetPaletteColors::SetPaletteColors(ObjectsContainer* objects, Sprite* sprite, Palette* palette, int from, int to) + : m_spriteId(objects->addObject(sprite)) + , m_frame(sprite->getCurrentFrame()) + , m_from(from) + , m_to(to) +{ + // Write (to-from+1) palette color entries + for (int i=from; i<=to; ++i) + write32(m_stream, palette->getEntry(i)); +} + +void SetPaletteColors::dispose() +{ + delete this; +} + +void SetPaletteColors::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Sprite* sprite = objects->getObjectT(m_spriteId); + Palette* palette = sprite->getPalette(m_frame); + + if (palette == NULL) + throw UndoException("Palette not found when restoring colors"); + + // Push another SetPaletteColors as redoer + redoers->pushUndoer(new SetPaletteColors(objects, sprite, palette, m_from, m_to)); + + // Read palette color entries + for (int i=m_from; i<=m_to; ++i) { + uint32_t color = read32(m_stream); + palette->setEntry(i, color); + } +} diff --git a/src/undoers/set_palette_colors.h b/src/undoers/set_palette_colors.h new file mode 100644 index 000000000..846df08f8 --- /dev/null +++ b/src/undoers/set_palette_colors.h @@ -0,0 +1,55 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_SET_PALETTE_COLORS_H_INCLUDED +#define UNDOERS_SET_PALETTE_COLORS_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Palette; +class Sprite; + +namespace undoers { + +class SetPaletteColors : public UndoerBase +{ +public: + SetPaletteColors(undo::ObjectsContainer* objects, Sprite* sprite, Palette* palette, int from, int to); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this) + getStreamSize(); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + size_t getStreamSize() const { + return const_cast(&m_stream)->tellp(); + } + + undo::ObjectId m_spriteId; + uint32_t m_frame; + uint8_t m_from; + uint8_t m_to; + std::stringstream m_stream; +}; + +} // namespace undoers + +#endif // UNDOERS_SET_PALETTE_COLORS_H_INCLUDED diff --git a/src/undoers/set_sprite_size.cpp b/src/undoers/set_sprite_size.cpp new file mode 100644 index 000000000..db42ddb4d --- /dev/null +++ b/src/undoers/set_sprite_size.cpp @@ -0,0 +1,50 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/set_sprite_size.h" + +#include "raster/sprite.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" + +using namespace undo; +using namespace undoers; + +SetSpriteSize::SetSpriteSize(ObjectsContainer* objects, Sprite* sprite) + : m_spriteId(objects->addObject(sprite)) + , m_width(sprite->getWidth()) + , m_height(sprite->getHeight()) +{ +} + +void SetSpriteSize::dispose() +{ + delete this; +} + +void SetSpriteSize::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Sprite* sprite = objects->getObjectT(m_spriteId); + + // Push another SetSpriteSize as redoer + redoers->pushUndoer(new SetSpriteSize(objects, sprite)); + + sprite->setSize(m_width, m_height); +} diff --git a/src/undoers/set_sprite_size.h b/src/undoers/set_sprite_size.h new file mode 100644 index 000000000..a8e218d29 --- /dev/null +++ b/src/undoers/set_sprite_size.h @@ -0,0 +1,46 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_SET_SPRITE_SIZE_H_INCLUDED +#define UNDOERS_SET_SPRITE_SIZE_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +class Sprite; + +namespace undoers { + +class SetSpriteSize : public UndoerBase +{ +public: + SetSpriteSize(undo::ObjectsContainer* objects, Sprite* sprite); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_spriteId; + uint32_t m_width; + uint32_t m_height; +}; + +} // namespace undoers + +#endif // UNDOERS_SET_SPRITE_SIZE_H_INCLUDED diff --git a/src/undoers/set_total_frames.cpp b/src/undoers/set_total_frames.cpp new file mode 100644 index 000000000..82ce82cb2 --- /dev/null +++ b/src/undoers/set_total_frames.cpp @@ -0,0 +1,49 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "undoers/set_total_frames.h" + +#include "raster/sprite.h" +#include "undo/objects_container.h" +#include "undo/undoers_collector.h" + +using namespace undo; +using namespace undoers; + +SetTotalFrames::SetTotalFrames(ObjectsContainer* objects, Sprite* sprite) + : m_spriteId(objects->addObject(sprite)) + , m_totalFrames(sprite->getTotalFrames()) +{ +} + +void SetTotalFrames::dispose() +{ + delete this; +} + +void SetTotalFrames::revert(ObjectsContainer* objects, UndoersCollector* redoers) +{ + Sprite* sprite = objects->getObjectT(m_spriteId); + + // Push another SetTotalFrames as redoer + redoers->pushUndoer(new SetTotalFrames(objects, sprite)); + + sprite->setTotalFrames(m_totalFrames); +} diff --git a/src/undoers/set_total_frames.h b/src/undoers/set_total_frames.h new file mode 100644 index 000000000..03988b9be --- /dev/null +++ b/src/undoers/set_total_frames.h @@ -0,0 +1,47 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * 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 + */ + +#ifndef UNDOERS_SET_TOTAL_FRAMES_H_INCLUDED +#define UNDOERS_SET_TOTAL_FRAMES_H_INCLUDED + +#include "undo/object_id.h" +#include "undoers/undoer_base.h" + +#include + +class Sprite; + +namespace undoers { + +class SetTotalFrames : public UndoerBase +{ +public: + SetTotalFrames(undo::ObjectsContainer* objects, Sprite* sprite); + + void dispose() OVERRIDE; + int getMemSize() const OVERRIDE { return sizeof(*this); } + void revert(undo::ObjectsContainer* objects, undo::UndoersCollector* redoers) OVERRIDE; + +private: + undo::ObjectId m_spriteId; + uint32_t m_totalFrames; +}; + +} // namespace undoers + +#endif // UNDOERS_SET_TOTAL_FRAMES_H_INCLUDED diff --git a/src/undoers/undoer_base.h b/src/undoers/undoer_base.h new file mode 100644 index 000000000..049ec9009 --- /dev/null +++ b/src/undoers/undoer_base.h @@ -0,0 +1,26 @@ +// ASEPRITE Undo Library +// Copyright (C) 2001-2011 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef UNDOERS_UNDOER_BASE_H_INCLUDED +#define UNDOERS_UNDOER_BASE_H_INCLUDED + +#include "base/compiler_specific.h" +#include "undo/undoer.h" + +namespace undoers { + +// Helper class to make new Undoers, derive from here and implement +// revert(), getMemSize(), and dispose() methods only. +class UndoerBase : public undo::Undoer +{ +public: + bool isOpenGroup() const OVERRIDE { return false; } + bool isCloseGroup() const OVERRIDE { return false; } +}; + +} // namespace undoers + +#endif // UNDOERS_UNDOER_BASE_H_INCLUDED diff --git a/src/util/celmove.cpp b/src/util/celmove.cpp index d6dc77c3f..799fc4a8f 100644 --- a/src/util/celmove.cpp +++ b/src/util/celmove.cpp @@ -40,7 +40,7 @@ static Layer* dst_layer = NULL; static int src_frame = 0; static int dst_frame = 0; -static void remove_cel(Sprite* sprite, UndoHistory* undo, LayerImage *layer, Cel *cel); +static void remove_cel(Sprite* sprite, undo::UndoHistory* undo, LayerImage *layer, Cel *cel); void set_frame_to_handle(Layer *_src_layer, int _src_frame, Layer *_dst_layer, int _dst_frame) @@ -54,7 +54,7 @@ void set_frame_to_handle(Layer *_src_layer, int _src_frame, void move_cel(DocumentWriter& document) { Sprite* sprite = document->getSprite(); - UndoHistory* undo = document->getUndoHistory(); + undo::UndoHistory* undo = document->getUndoHistory(); Cel *src_cel, *dst_cel; ASSERT(src_layer != NULL); @@ -148,7 +148,7 @@ void move_cel(DocumentWriter& document) void copy_cel(DocumentWriter& document) { Sprite* sprite = document->getSprite(); - UndoHistory* undo = document->getUndoHistory(); + undo::UndoHistory* undo = document->getUndoHistory(); Cel *src_cel, *dst_cel; ASSERT(src_layer != NULL); @@ -231,7 +231,7 @@ void copy_cel(DocumentWriter& document) set_frame_to_handle(NULL, 0, NULL, 0); } -static void remove_cel(Sprite* sprite, UndoHistory* undo, LayerImage *layer, Cel *cel) +static void remove_cel(Sprite* sprite, undo::UndoHistory* undo, LayerImage *layer, Cel *cel) { Image *image; Cel *it; diff --git a/src/util/clipboard.cpp b/src/util/clipboard.cpp index 383282e4b..b20010b68 100644 --- a/src/util/clipboard.cpp +++ b/src/util/clipboard.cpp @@ -196,7 +196,7 @@ void clipboard::copy_image(Image* image, Palette* pal) void clipboard::paste(DocumentWriter& document) { UndoTransaction undoTransaction(document, "Paste"); - UndoHistory* undo = document->getUndoHistory(); + undo::UndoHistory* undo = document->getUndoHistory(); int xout[4], yout[4]; int dst_x, dst_y; Image *src_image; diff --git a/src/util/misc.cpp b/src/util/misc.cpp index 0ea483fa7..89a583222 100644 --- a/src/util/misc.cpp +++ b/src/util/misc.cpp @@ -87,7 +87,7 @@ int interactive_move_layer(int mode, bool use_undo, int (*callback)()) { Editor* editor = current_editor; Document* document = editor->getDocument(); - UndoHistory* undo = document->getUndoHistory(); + undo::UndoHistory* undo = document->getUndoHistory(); Sprite* sprite = document->getSprite(); ASSERT(sprite->getCurrentLayer()->is_image()); diff --git a/src/widgets/editor/editor.cpp b/src/widgets/editor/editor.cpp index a149e848b..44fcce04c 100644 --- a/src/widgets/editor/editor.cpp +++ b/src/widgets/editor/editor.cpp @@ -1907,7 +1907,7 @@ public: ~ToolLoopImpl() { if (!m_canceled) { - UndoHistory* undo = m_document->getUndoHistory(); + undo::UndoHistory* undo = m_document->getUndoHistory(); // Paint ink if (getInk()->isPaint()) {