diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index cb8dacab0..5ba751635 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -258,6 +258,7 @@ add_library(app-lib document_range.cpp document_range_ops.cpp document_undo.cpp + extra_cel.cpp file/ase_format.cpp file/bmp_format.cpp file/file.cpp diff --git a/src/app/cmd/set_pixel_format.cpp b/src/app/cmd/set_pixel_format.cpp index 1459e39f4..e7303ed97 100644 --- a/src/app/cmd/set_pixel_format.cpp +++ b/src/app/cmd/set_pixel_format.cpp @@ -105,7 +105,7 @@ void SetPixelFormat::setFormat(PixelFormat format) // Regenerate extras static_cast(sprite->document()) - ->destroyExtraCel(); + ->setExtraCel(ExtraCelRef(nullptr)); // Generate notification DocumentEvent ev(sprite->document()); diff --git a/src/app/commands/cmd_fullscreen_preview.cpp b/src/app/commands/cmd_fullscreen_preview.cpp index f3f1482f7..79c30263d 100644 --- a/src/app/commands/cmd_fullscreen_preview.cpp +++ b/src/app/commands/cmd_fullscreen_preview.cpp @@ -66,7 +66,7 @@ public: editor->getManager()->freeMouse(); // Clear extras (e.g. pen preview) - m_doc->destroyExtraCel(); + m_doc->setExtraCel(ExtraCelRef(nullptr)); gfx::Rect vp = view->getViewportBounds(); gfx::Point scroll = view->getViewScroll(); diff --git a/src/app/commands/cmd_undo.cpp b/src/app/commands/cmd_undo.cpp index 0b38c3106..e0d0ce1ef 100644 --- a/src/app/commands/cmd_undo.cpp +++ b/src/app/commands/cmd_undo.cpp @@ -122,7 +122,7 @@ void UndoCommand::onExecute(Context* context) } document->generateMaskBoundaries(); - document->destroyExtraCel(); // Regenerate extras + document->setExtraCel(ExtraCelRef(nullptr)); update_screen_for_document(document); set_current_palette(writer.palette(), false); diff --git a/src/app/document.cpp b/src/app/document.cpp index ed0092f67..839e415ef 100644 --- a/src/app/document.cpp +++ b/src/app/document.cpp @@ -51,12 +51,6 @@ Document::Document(Sprite* sprite) , m_read_locks(0) // Information about the file format used to load/save this document , m_format_options(NULL) - // Extra cel - , m_extraCel(nullptr) - , m_extraImage(nullptr) - , m_extraImageBuffer(nullptr) - , m_extraCelBlendMode(BlendMode::NORMAL) - , m_extraCelType(render::ExtraType::NONE) // Mask , m_mask(new Mask()) , m_maskVisible(true) @@ -75,8 +69,6 @@ Document::~Document() // which could result in serious problems for observers expecting a // fully created app::Document. ASSERT(context() == NULL); - - destroyExtraCel(); } DocumentApi Document::getApi(Transaction& transaction) @@ -232,55 +224,6 @@ void Document::generateMaskBoundaries(const Mask* mask) notifySelectionChanged(); } -////////////////////////////////////////////////////////////////////// -// Extra Cel (it is used to draw pen preview, pixels in movement, etc.) - -void Document::destroyExtraCel() -{ - delete m_extraCel; - - m_extraCel = nullptr; - m_extraImage.reset(nullptr); - m_extraCelType = render::ExtraType::NONE; -} - -void Document::prepareExtraCel(const gfx::Rect& bounds, frame_t frame, int opacity) -{ - ASSERT(sprite() != NULL); - - if (!m_extraImage || - m_extraImage->pixelFormat() != sprite()->pixelFormat() || - m_extraImage->width() != bounds.w || - m_extraImage->height() != bounds.h) { - if (!m_extraImageBuffer) - m_extraImageBuffer.reset(new ImageBuffer(1)); - Image* newImage = Image::create(sprite()->pixelFormat(), bounds.w, bounds.h, m_extraImageBuffer); - m_extraImage.reset(newImage); - } - - if (!m_extraCel) - m_extraCel = new Cel(frame_t(0), ImageRef(NULL)); // Ignored fields for this cel (frame, and image index) - - m_extraCel->setPosition(bounds.getOrigin()); - m_extraCel->setOpacity(opacity); - m_extraCel->setFrame(frame); -} - -void Document::setExtraCelType(render::ExtraType type) -{ - m_extraCelType = type; -} - -Cel* Document::getExtraCel() const -{ - return m_extraCel; -} - -Image* Document::getExtraCelImage() const -{ - return m_extraImage.get(); -} - ////////////////////////////////////////////////////////////////////// // Mask diff --git a/src/app/document.h b/src/app/document.h index 03b7bb1d8..bf776f3a5 100644 --- a/src/app/document.h +++ b/src/app/document.h @@ -9,6 +9,7 @@ #define APP_DOCUMENT_H_INCLUDED #pragma once +#include "app/extra_cel.h" #include "app/file/format_options.h" #include "base/disable_copying.h" #include "base/mutex.h" @@ -19,12 +20,9 @@ #include "doc/color.h" #include "doc/document.h" #include "doc/frame.h" -#include "doc/image_ref.h" -#include "doc/image_buffer.h" #include "doc/pixel_format.h" #include "gfx/rect.h" #include "gfx/transformation.h" -#include "render/extra_type.h" #include @@ -123,14 +121,8 @@ namespace app { ////////////////////////////////////////////////////////////////////// // Extra Cel (it is used to draw pen preview, pixels in movement, etc.) - void prepareExtraCel(const gfx::Rect& bounds, frame_t frame, int opacity); - void setExtraCelType(render::ExtraType type); - void destroyExtraCel(); - Cel* getExtraCel() const; - Image* getExtraCelImage() const; - render::ExtraType getExtraCelType() const { return m_extraCelType; } - BlendMode getExtraCelBlendMode() const { return m_extraCelBlendMode; } - void setExtraCelBlendMode(BlendMode mode) { m_extraCelBlendMode = mode; } + ExtraCelRef extraCel() const { return m_extraCel; } + void setExtraCel(const ExtraCelRef& extraCel) { m_extraCel = extraCel; } ////////////////////////////////////////////////////////////////////// // Mask @@ -210,13 +202,7 @@ namespace app { base::SharedPtr m_format_options; // Extra cel used to draw extra stuff (e.g. editor's pen preview, pixels in movement, etc.) - Cel* m_extraCel; - - // Image of the extra cel. - ImageRef m_extraImage; - ImageBufferPtr m_extraImageBuffer; - BlendMode m_extraCelBlendMode; - render::ExtraType m_extraCelType; + ExtraCelRef m_extraCel; // Current mask. base::UniquePtr m_mask; diff --git a/src/app/extra_cel.cpp b/src/app/extra_cel.cpp new file mode 100644 index 000000000..529689238 --- /dev/null +++ b/src/app/extra_cel.cpp @@ -0,0 +1,53 @@ +// Aseprite +// Copyright (C) 2001-2015 David Capello +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "app/extra_cel.h" + +#include "doc/sprite.h" + +namespace app { + +ExtraCel::ExtraCel() + : m_type(render::ExtraType::NONE) + , m_blendMode(doc::BlendMode::NORMAL) +{ +} + +void ExtraCel::create(doc::Sprite* sprite, + const gfx::Rect& bounds, + doc::frame_t frame, + int opacity) +{ + ASSERT(sprite); + + if (!m_image || + m_image->pixelFormat() != sprite->pixelFormat() || + m_image->width() != bounds.w || + m_image->height() != bounds.h) { + if (!m_imageBuffer) + m_imageBuffer.reset(new doc::ImageBuffer(1)); + doc::Image* newImage = doc::Image::create(sprite->pixelFormat(), + bounds.w, bounds.h, + m_imageBuffer); + m_image.reset(newImage); + } + + if (!m_cel) { + // Ignored fields for this cel (frame, and image index) + m_cel.reset(new doc::Cel(doc::frame_t(0), doc::ImageRef(nullptr))); + } + + m_cel->setPosition(bounds.getOrigin()); + m_cel->setOpacity(opacity); + m_cel->setFrame(frame); +} + +} // namespace app diff --git a/src/app/extra_cel.h b/src/app/extra_cel.h new file mode 100644 index 000000000..9c4f76255 --- /dev/null +++ b/src/app/extra_cel.h @@ -0,0 +1,58 @@ +// Aseprite +// Copyright (C) 2001-2015 David Capello +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. + +#ifndef APP_EXTRA_CEL_H_INCLUDED +#define APP_EXTRA_CEL_H_INCLUDED +#pragma once + +#include "base/disable_copying.h" +#include "base/unique_ptr.h" +#include "doc/blend_mode.h" +#include "doc/cel.h" +#include "doc/frame.h" +#include "doc/image_buffer.h" +#include "doc/image_ref.h" +#include "gfx/rect.h" +#include "render/extra_type.h" + +namespace doc { + class Sprite; +} + +namespace app { + + class ExtraCel { + public: + ExtraCel(); + + void create(doc::Sprite* sprite, const gfx::Rect& bounds, doc::frame_t frame, int opacity); + void destroy(); + + render::ExtraType type() const { return m_type; } + void setType(render::ExtraType type) { m_type = type; } + + doc::Cel* cel() const { return m_cel.get(); } + doc::Image* image() const { return m_image.get(); } + + doc::BlendMode blendMode() const { return m_blendMode; } + void setBlendMode(doc::BlendMode mode) { m_blendMode = mode; } + + private: + render::ExtraType m_type; + base::UniquePtr m_cel; + doc::ImageRef m_image; + doc::ImageBufferPtr m_imageBuffer; + doc::BlendMode m_blendMode; + + DISABLE_COPYING(ExtraCel); + }; + + typedef base::SharedPtr ExtraCelRef; + +} // namespace app + +#endif diff --git a/src/app/ui/editor/brush_preview.cpp b/src/app/ui/editor/brush_preview.cpp index 6f0da6362..8d190b074 100644 --- a/src/app/ui/editor/brush_preview.cpp +++ b/src/app/ui/editor/brush_preview.cpp @@ -155,13 +155,17 @@ void BrushPreview::show(const gfx::Point& screenPos) if (cel) opacity = MUL_UN8(opacity, cel->opacity(), t); if (layer) opacity = MUL_UN8(opacity, static_cast(layer)->opacity(), t); - document->prepareExtraCel(brushBounds, site.frame(), opacity); - document->setExtraCelType(render::ExtraType::NONE); - document->setExtraCelBlendMode( + if (!m_extraCel) + m_extraCel.reset(new ExtraCel); + m_extraCel->create(document->sprite(), brushBounds, site.frame(), opacity); + m_extraCel->setType(render::ExtraType::NONE); + m_extraCel->setBlendMode( (layer ? static_cast(layer)->blendMode(): BlendMode::NORMAL)); - Image* extraImage = document->getExtraCelImage(); + document->setExtraCel(m_extraCel); + + Image* extraImage = m_extraCel->image(); extraImage->setMaskColor(mask_index); clear_image(extraImage, (extraImage->pixelFormat() == IMAGE_INDEXED ? mask_index: 0)); @@ -173,7 +177,7 @@ void BrushPreview::show(const gfx::Point& screenPos) BlendMode::SRC); // This extra cel is a patch for the current layer/frame - document->setExtraCelType(render::ExtraType::PATCH); + m_extraCel->setType(render::ExtraType::PATCH); } tools::ToolLoop* loop = create_tool_loop_preview( @@ -247,7 +251,7 @@ void BrushPreview::hide() // Clean pixel/brush preview if (m_withRealPreview) { - document->destroyExtraCel(); + document->setExtraCel(ExtraCelRef(nullptr)); document->notifySpritePixelsModified( sprite, gfx::Region(m_lastBounds), m_lastFrame); diff --git a/src/app/ui/editor/brush_preview.h b/src/app/ui/editor/brush_preview.h index 3fbaac738..701be8160 100644 --- a/src/app/ui/editor/brush_preview.h +++ b/src/app/ui/editor/brush_preview.h @@ -9,6 +9,7 @@ #define APP_UI_EDITOR_BRUSH_PREVIEW_H_INCLUDED #pragma once +#include "app/extra_cel.h" #include "base/shared_ptr.h" #include "doc/color.h" #include "doc/frame.h" @@ -106,6 +107,8 @@ namespace app { // brush preview in the exact same place. gfx::Rect m_lastBounds; doc::frame_t m_lastFrame; + + ExtraCelRef m_extraCel; }; class HideBrushPreview { diff --git a/src/app/ui/editor/editor.cpp b/src/app/ui/editor/editor.cpp index 0969298b0..a6cab19e5 100644 --- a/src/app/ui/editor/editor.cpp +++ b/src/app/ui/editor/editor.cpp @@ -479,14 +479,13 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite } } - if (m_document->getExtraCelType() != render::ExtraType::NONE) { - ASSERT(m_document->getExtraCel()); - + ExtraCelRef extraCel = m_document->extraCel(); + if (extraCel && extraCel->type() != render::ExtraType::NONE) { m_renderEngine.setExtraImage( - m_document->getExtraCelType(), - m_document->getExtraCel(), - m_document->getExtraCelImage(), - m_document->getExtraCelBlendMode(), + extraCel->type(), + extraCel->cel(), + extraCel->image(), + extraCel->blendMode(), m_layer, m_frame); } @@ -794,22 +793,24 @@ void Editor::flashCurrentLayer() if (src_image) { m_renderEngine.removePreviewImage(); - m_document->prepareExtraCel(m_sprite->bounds(), m_frame, 255); - m_document->setExtraCelType(render::ExtraType::COMPOSITE); - - Image* flash_image = m_document->getExtraCelImage(); + ExtraCelRef extraCel(new ExtraCel); + extraCel->create(m_sprite, m_sprite->bounds(), m_frame, 255); + extraCel->setType(render::ExtraType::COMPOSITE); + extraCel->setBlendMode(BlendMode::NEG_BW); + Image* flash_image = extraCel->image(); clear_image(flash_image, flash_image->maskColor()); copy_image(flash_image, src_image, x, y); - m_document->setExtraCelBlendMode(BlendMode::NEG_BW); - drawSpriteClipped(gfx::Region( - gfx::Rect(0, 0, m_sprite->width(), m_sprite->height()))); + { + ExtraCelRef oldExtraCel = m_document->extraCel(); + m_document->setExtraCel(extraCel); + drawSpriteClipped(gfx::Region( + gfx::Rect(0, 0, m_sprite->width(), m_sprite->height()))); + getManager()->flipDisplay(); + m_document->setExtraCel(oldExtraCel); + } - getManager()->flipDisplay(); - - m_document->setExtraCelBlendMode(BlendMode::NORMAL); - m_document->destroyExtraCel(); invalidate(); } } diff --git a/src/app/ui/editor/pixels_movement.cpp b/src/app/ui/editor/pixels_movement.cpp index 300fa335f..9cc2ba6b4 100644 --- a/src/app/ui/editor/pixels_movement.cpp +++ b/src/app/ui/editor/pixels_movement.cpp @@ -89,7 +89,7 @@ PixelsMovement::PixelsMovement( // The extra cel must be null, because if it's not null, it means // that someone else is using it (e.g. the editor brush preview), // and its owner could destroy our new "extra cel". - ASSERT(!m_document->getExtraCel()); + ASSERT(!m_document->extraCel()); redrawExtraImage(); redrawCurrentMask(); @@ -491,8 +491,8 @@ void PixelsMovement::getDraggedImageCopy(base::UniquePtr& outputImage, void PixelsMovement::stampImage() { - const Cel* cel = m_document->getExtraCel(); - const Image* image = m_document->getExtraCelImage(); + const Cel* cel = m_extraCel->cel(); + const Image* image = m_extraCel->image(); ASSERT(cel && image); @@ -583,7 +583,7 @@ void PixelsMovement::dropImage() // Destroy the extra cel (this cel will be used by the drawing // cursor surely). ContextWriter writer(m_reader, 1000); - m_document->destroyExtraCel(); + m_document->setExtraCel(ExtraCelRef(nullptr)); } void PixelsMovement::discardImage(bool commit) @@ -599,7 +599,7 @@ void PixelsMovement::discardImage(bool commit) // Destroy the extra cel and regenerate the mask boundaries (we've // just deselect the mask). ContextWriter writer(m_reader, 1000); - m_document->destroyExtraCel(); + m_document->setExtraCel(ExtraCelRef(nullptr)); m_document->generateMaskBoundaries(); } @@ -610,8 +610,8 @@ bool PixelsMovement::isDragging() const gfx::Rect PixelsMovement::getImageBounds() { - const Cel* cel = m_document->getExtraCel(); - const Image* image = m_document->getExtraCelImage(); + const Cel* cel = m_extraCel->cel(); + const Image* image = m_extraCel->image(); ASSERT(cel != NULL); ASSERT(image != NULL); @@ -641,14 +641,16 @@ void PixelsMovement::redrawExtraImage() if (cel) opacity = MUL_UN8(opacity, cel->opacity(), t); gfx::Rect bounds = m_currentData.transformedBounds(); - m_document->prepareExtraCel(bounds, m_site.frame(), opacity); - m_document->setExtraCelType(render::ExtraType::PATCH); - m_document->setExtraCelBlendMode( - static_cast(m_layer)->blendMode()); + + m_extraCel.reset(new ExtraCel); + m_extraCel->create(m_document->sprite(), bounds, m_site.frame(), opacity); + m_extraCel->setType(render::ExtraType::PATCH); + m_extraCel->setBlendMode(static_cast(m_layer)->blendMode()); + m_document->setExtraCel(m_extraCel); // Draw the transformed pixels in the extra-cel which is the chunk // of pixels that the user is moving. - drawImage(m_document->getExtraCelImage(), bounds.getOrigin(), true); + drawImage(m_extraCel->image(), bounds.getOrigin(), true); } void PixelsMovement::redrawCurrentMask() diff --git a/src/app/ui/editor/pixels_movement.h b/src/app/ui/editor/pixels_movement.h index cc02e5821..abf6df7c0 100644 --- a/src/app/ui/editor/pixels_movement.h +++ b/src/app/ui/editor/pixels_movement.h @@ -10,6 +10,7 @@ #pragma once #include "app/context_access.h" +#include "app/extra_cel.h" #include "app/transaction.h" #include "app/ui/editor/handle_type.h" #include "base/connection.h" @@ -125,6 +126,7 @@ namespace app { ScopedConnection m_pivotVisConn; ScopedConnection m_pivotPosConn; ScopedConnection m_rotAlgoConn; + ExtraCelRef m_extraCel; }; inline PixelsMovement::MoveModifier& operator|=(PixelsMovement::MoveModifier& a,