1 // Aseprite
2 // Copyright (C) 2001-2018  David Capello
3 //
4 // This program is distributed under the terms of
5 // the End-User License Agreement for Aseprite.
6 
7 #ifndef APP_COMMANDS_FILTERS_FILTER_MANAGER_IMPL_H_INCLUDED
8 #define APP_COMMANDS_FILTERS_FILTER_MANAGER_IMPL_H_INCLUDED
9 #pragma once
10 
11 #include "app/commands/filters/cels_target.h"
12 #include "app/site.h"
13 #include "base/exception.h"
14 #include "base/unique_ptr.h"
15 #include "doc/image_impl.h"
16 #include "doc/image_ref.h"
17 #include "doc/pixel_format.h"
18 #include "filters/filter_indexed_data.h"
19 #include "filters/filter_manager.h"
20 #include "gfx/rect.h"
21 
22 #include <cstring>
23 #include <memory>
24 #include <vector>
25 
26 namespace doc {
27   class Cel;
28   class Image;
29   class Layer;
30   class Mask;
31   class Sprite;
32 }
33 
34 namespace filters {
35   class Filter;
36 }
37 
38 namespace app {
39   class Context;
40   class Doc;
41   class Editor;
42   class Transaction;
43 
44   using namespace filters;
45 
46   class InvalidAreaException : public base::Exception {
47   public:
InvalidAreaException()48     InvalidAreaException() throw()
49     : base::Exception("The active selection to apply the effect is out of the canvas.") { }
50   };
51 
52   class NoImageException : public base::Exception {
53   public:
NoImageException()54     NoImageException() throw()
55     : base::Exception("There is not an active image to apply the effect.\n"
56                       "Please select a layer/cel with an image and try again.") { }
57   };
58 
59   class FilterManagerImpl : public FilterManager
60                           , public FilterIndexedData {
61   public:
62     // Interface to report progress to the user and take input from him
63     // to cancel the whole process.
64     class IProgressDelegate {
65     public:
~IProgressDelegate()66       virtual ~IProgressDelegate() { }
67 
68       // Called to report the progress of the filter (with progress from 0.0 to 1.0).
69       virtual void reportProgress(float progress) = 0;
70 
71       // Should return true if the user wants to cancel the filter.
72       virtual bool isCancelled() = 0;
73     };
74 
75     FilterManagerImpl(Context* context, Filter* filter);
76     ~FilterManagerImpl();
77 
78     void setProgressDelegate(IProgressDelegate* progressDelegate);
79 
80     doc::PixelFormat pixelFormat() const;
81 
82     void setTarget(Target target);
83     void setCelsTarget(CelsTarget celsTarget);
84 
85     void begin();
86     void beginForPreview();
87     void end();
88     bool applyStep();
89     void applyToTarget();
90     bool isTransaction() const;
91     void commitTransaction();
92 
93     Doc* document();
sprite()94     doc::Sprite* sprite() { return m_site.sprite(); }
layer()95     doc::Layer* layer() { return m_site.layer(); }
frame()96     doc::frame_t frame() { return m_site.frame(); }
destinationImage()97     doc::Image* destinationImage() const { return m_dst.get(); }
position()98     gfx::Point position() const { return gfx::Point(0, 0); }
99 
100     // Updates the current editor to show the progress of the preview.
101     void flush();
102 
103     void disablePreview();
104 
105     // FilterManager implementation
106     const void* getSourceAddress() override;
107     void* getDestinationAddress() override;
getWidth()108     int getWidth() override { return m_bounds.w; }
getTarget()109     Target getTarget() override { return m_target; }
getIndexedData()110     FilterIndexedData* getIndexedData() override { return this; }
111     bool skipPixel() override;
getSourceImage()112     const doc::Image* getSourceImage() override { return m_src.get(); }
x()113     int x() const override { return m_bounds.x; }
y()114     int y() const override { return m_bounds.y+m_row; }
isFirstRow()115     bool isFirstRow() const override { return m_row == 0; }
116     bool isMaskActive() const override;
117 
118     // FilterIndexedData implementation
119     const doc::Palette* getPalette() const override;
120     const doc::RgbMap* getRgbMap() const override;
121     doc::Palette* getNewPalette() override;
122     doc::PalettePicks getPalettePicks() override;
123 
124   private:
125     void init(doc::Cel* cel);
126     void apply();
127     void applyToCel(doc::Cel* cel);
128     bool updateBounds(doc::Mask* mask);
129 
130     // Returns true if the palette was changed (true when the filter
131     // modifies the palette).
132     bool paletteHasChanged();
133     void restoreSpritePalette();
134     void redrawColorPalette();
135 
136     Context* m_context;
137     Site m_site;
138     Filter* m_filter;
139     doc::Cel* m_cel;
140     doc::ImageRef m_src;
141     doc::ImageRef m_dst;
142     int m_row;
143     int m_nextRowToFlush;
144     gfx::Rect m_bounds;
145     doc::Mask* m_mask;
146     base::UniquePtr<doc::Mask> m_previewMask;
147     doc::ImageBits<doc::BitmapTraits> m_maskBits;
148     doc::ImageBits<doc::BitmapTraits>::iterator m_maskIterator;
149     Target m_targetOrig;          // Original targets
150     Target m_target;              // Filtered targets
151     CelsTarget m_celsTarget;
152     base::UniquePtr<doc::Palette> m_oldPalette;
153     std::unique_ptr<Transaction> m_transaction;
154 
155     // Hooks
156     float m_progressBase;
157     float m_progressWidth;
158     IProgressDelegate* m_progressDelegate;
159   };
160 
161 } // namespace app
162 
163 #endif
164