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_DOC_H_INCLUDED
8 #define APP_DOC_H_INCLUDED
9 #pragma once
10 
11 #include "app/doc_observer.h"
12 #include "app/extra_cel.h"
13 #include "app/file/format_options.h"
14 #include "app/transformation.h"
15 #include "base/disable_copying.h"
16 #include "base/mutex.h"
17 #include "base/rw_lock.h"
18 #include "base/shared_ptr.h"
19 #include "base/unique_ptr.h"
20 #include "doc/blend_mode.h"
21 #include "doc/color.h"
22 #include "doc/document.h"
23 #include "doc/frame.h"
24 #include "doc/pixel_format.h"
25 #include "gfx/rect.h"
26 #include "obs/observable.h"
27 
28 #include <string>
29 
30 namespace doc {
31   class Cel;
32   class Layer;
33   class Mask;
34   class MaskBoundaries;
35   class Sprite;
36 }
37 
38 namespace gfx {
39   class Region;
40 }
41 
42 namespace app {
43 
44   class Context;
45   class DocApi;
46   class DocUndo;
47   class Transaction;
48 
49   using namespace doc;
50 
51   enum DuplicateType {
52     DuplicateExactCopy,
53     DuplicateWithFlattenLayers,
54   };
55 
56   // An application document. It is the class used to contain one file
57   // opened and being edited by the user (a sprite).
58   class Doc : public doc::Document,
59               public base::RWLock,
60               public obs::observable<DocObserver> {
61     enum Flags {
62       kAssociatedToFile = 1, // This sprite is associated to a file in the file-system
63       kMaskVisible      = 2, // The mask wasn't hidden by the user
64       kInhibitBackup    = 4, // Inhibit the backup process
65     };
66   public:
67     Doc(Sprite* sprite);
68     ~Doc();
69 
context()70     Context* context() const { return m_ctx; }
71     void setContext(Context* ctx);
72 
73     // Returns a high-level API: observable and undoable methods.
74     DocApi getApi(Transaction& transaction);
75 
76     //////////////////////////////////////////////////////////////////////
77     // Main properties
78 
undoHistory()79     const DocUndo* undoHistory() const { return m_undo; }
undoHistory()80     DocUndo* undoHistory() { return m_undo; }
81 
82     color_t bgColor() const;
83     color_t bgColor(Layer* layer) const;
84 
85     //////////////////////////////////////////////////////////////////////
86     // Notifications
87 
88     void notifyGeneralUpdate();
89     void notifySpritePixelsModified(Sprite* sprite, const gfx::Region& region, frame_t frame);
90     void notifyExposeSpritePixels(Sprite* sprite, const gfx::Region& region);
91     void notifyLayerMergedDown(Layer* srcLayer, Layer* targetLayer);
92     void notifyCelMoved(Layer* fromLayer, frame_t fromFrame, Layer* toLayer, frame_t toFrame);
93     void notifyCelCopied(Layer* fromLayer, frame_t fromFrame, Layer* toLayer, frame_t toFrame);
94     void notifySelectionChanged();
95 
96     //////////////////////////////////////////////////////////////////////
97     // File related properties
98 
99     bool isModified() const;
100     bool isAssociatedToFile() const;
101     void markAsSaved();
102 
103     // You can use this to indicate that we've destroyed (or we cannot
104     // trust) the file associated with the document (e.g. when we
105     // cancel a Save operation in the middle). So it's impossible to
106     // back to the saved state using the UndoHistory.
107     void impossibleToBackToSavedState();
108 
109     // Returns true if it does make sense to create a backup in this
110     // document. For example, it doesn't make sense to create a backup
111     // for an unmodified document.
112     bool needsBackup() const;
113 
114     // Can be used to avoid creating a backup when the file is in a
115     // unusual temporary state (e.g. when the file is resized to be
116     // exported with other size)
117     bool inhibitBackup() const;
118     void setInhibitBackup(const bool inhibitBackup);
119 
120     //////////////////////////////////////////////////////////////////////
121     // Loaded options from file
122 
123     void setFormatOptions(const base::SharedPtr<FormatOptions>& format_options);
getFormatOptions()124     base::SharedPtr<FormatOptions> getFormatOptions() { return m_format_options; }
125 
126     //////////////////////////////////////////////////////////////////////
127     // Boundaries
128 
129     void generateMaskBoundaries(const Mask* mask = nullptr);
130 
getMaskBoundaries()131     const MaskBoundaries* getMaskBoundaries() const {
132      return m_maskBoundaries.get();
133     }
134 
135     //////////////////////////////////////////////////////////////////////
136     // Extra Cel (it is used to draw pen preview, pixels in movement, etc.)
137 
extraCel()138     ExtraCelRef extraCel() const { return m_extraCel; }
setExtraCel(const ExtraCelRef & extraCel)139     void setExtraCel(const ExtraCelRef& extraCel) { m_extraCel = extraCel; }
140 
141     //////////////////////////////////////////////////////////////////////
142     // Mask
143 
144     // Returns the current mask, it can be empty. The mask could be not
145     // empty but hidden to the user if the setMaskVisible(false) was
146     // used called before.
mask()147     Mask* mask() const { return m_mask; }
148 
149     // Sets the current mask. The new mask will be visible by default,
150     // so you don't need to call setMaskVisible(true).
151     void setMask(const Mask* mask);
152 
153     // Returns true only when the mask is not empty, and was not yet
154     // hidden using setMaskVisible (e.g. when the user "deselect the
155     // mask").
156     bool isMaskVisible() const;
157 
158     // Changes the visibility state of the mask (it is useful only if
159     // the getMask() is not empty and the user can see that the mask is
160     // being hidden and shown to him).
161     void setMaskVisible(bool visible);
162 
163     //////////////////////////////////////////////////////////////////////
164     // Transformation
165 
166     Transformation getTransformation() const;
167     void setTransformation(const Transformation& transform);
168     void resetTransformation();
169 
170     //////////////////////////////////////////////////////////////////////
171     // Last point used to draw straight lines using freehand tools + Shift key
172     // (EditorCustomizationDelegate::isStraightLineFromLastPoint() modifier)
173 
174     static gfx::Point NoLastDrawingPoint();
lastDrawingPoint()175     gfx::Point lastDrawingPoint() const { return m_lastDrawingPoint; }
setLastDrawingPoint(const gfx::Point & pos)176     void setLastDrawingPoint(const gfx::Point& pos) { m_lastDrawingPoint = pos; }
177 
178     //////////////////////////////////////////////////////////////////////
179     // Copying
180 
181     void copyLayerContent(const Layer* sourceLayer, Doc* destDoc, Layer* destLayer) const;
182     Doc* duplicate(DuplicateType type) const;
183 
184     void close();
185 
186   protected:
187     void onFileNameChange() override;
188     virtual void onContextChanged();
189 
190   private:
191     void removeFromContext();
192 
193     Context* m_ctx;
194     int m_flags;
195 
196     // Undo and redo information about the document.
197     base::UniquePtr<DocUndo> m_undo;
198 
199     // Selected mask region boundaries
200     base::UniquePtr<doc::MaskBoundaries> m_maskBoundaries;
201 
202     // Data to save the file in the same format that it was loaded
203     base::SharedPtr<FormatOptions> m_format_options;
204 
205     // Extra cel used to draw extra stuff (e.g. editor's pen preview, pixels in movement, etc.)
206     ExtraCelRef m_extraCel;
207 
208     // Current mask.
209     base::UniquePtr<Mask> m_mask;
210 
211     // Current transformation.
212     Transformation m_transformation;
213 
214     gfx::Point m_lastDrawingPoint;
215 
216     DISABLE_COPYING(Doc);
217   };
218 
219 } // namespace app
220 
221 #endif
222