1 #pragma once
2 
3 #ifndef TXSHSIMPLELEVEL_INCLUDED
4 #define TXSHSIMPLELEVEL_INCLUDED
5 
6 #include <memory>
7 
8 // TnzLib includes
9 #include "toonz/txshlevel.h"
10 #include "toonz/txshleveltypes.h"
11 #include "toonz/imagemanager.h"
12 
13 // TnzCore includes
14 #include "traster.h"
15 #include "trasterimage.h"
16 
17 // Qt includes
18 #include <QObject>
19 #include <QStringList>
20 
21 // boost includes
22 #include <boost/container/flat_set.hpp>
23 #include <boost/container/flat_map.hpp>
24 
25 // STD includes
26 #include <set>
27 
28 #undef DVAPI
29 #undef DVVAR
30 #ifdef TOONZLIB_EXPORTS
31 #define DVAPI DV_EXPORT_API
32 #define DVVAR DV_EXPORT_VAR
33 #else
34 #define DVAPI DV_IMPORT_API
35 #define DVVAR DV_IMPORT_VAR
36 #endif
37 
38 //===================================================================
39 
40 //    Forward declarations
41 
42 class ImageBuilder;
43 class LevelProperties;
44 class TPalette;
45 class TContentHistory;
46 
47 //===================================================================
48 
49 //*************************************************************************************************
50 //    TXshSimpleLevel  declaration
51 //*************************************************************************************************
52 
53 /*!
54   \brief    The \p TXshLevel specialization for image levels.
55 
56   \todo     Substitute m_frames with a sorted vector or
57             a boost flat_set.
58 */
59 
60 class DVAPI TXshSimpleLevel final : public TXshLevel {
61   Q_OBJECT
62 
63   PERSIST_DECLARATION(TXshSimpleLevel)
64   DECLARE_CLASS_CODE
65 
66 public:
67   /*! \details  Level frames may have special properties depending on
68           the level type they are part of.
69 
70 \sa       \p TXshSimpleLevel::getFrameStatus() and
71           \p setFrameStatus() for further details.                  */
72 
73   enum FrameStatusBit      //!  Describes a level's frame status.
74   { Normal         = 0x0,  //!< Frame has no special status.
75     Scanned        = 0x1,  //!< A fullcolor frame (only tlv levels).
76     Cleanupped     = 0x2,  //!< A cleanupped frame (only tlv levels).
77     CleanupPreview = 0x4   //!< A cleanup preview (only fullcolor levels).
78   };
79 
80 public:
81   static bool
82       m_rasterizePli;  //!< \internal  Not the proper place for this data.
83   static bool m_fillFullColorRaster;  //!< \internal  Not the proper place for
84                                       //! this data.
85 
86 public:
87   TXshSimpleLevel(
88       const std::wstring &name =
89           std::wstring());  //!< Constructs a TXshSimpleLevel with a name
90   ~TXshSimpleLevel();
91 
getSimpleLevel()92   TXshSimpleLevel *getSimpleLevel() override {
93     return this;
94   }  //!< Reimplemented for TXshLevel.
95 
isSubsequence()96   bool isSubsequence() const { return m_isSubsequence; }
97 
is16BitChannelLevel()98   bool is16BitChannelLevel() const {
99     return getType() == OVL_XSHLEVEL && m_16BitChannelLevel;
100   }
set16BitChannelLevel(bool value)101   void set16BitChannelLevel(bool value) {
102     m_16BitChannelLevel = (value && getType() == OVL_XSHLEVEL);
103   }
104 
isReadOnly()105   bool isReadOnly() const { return m_isReadOnly; }
setIsReadOnly(bool value)106   void setIsReadOnly(bool value) { m_isReadOnly = value; }
107   void updateReadOnly();
108 
getProperties()109   LevelProperties *getProperties()
110       const  //!< Returns a pointer to the \a owned level properties.
111   {
112     return m_properties.get();
113   }
114   void clonePropertiesFrom(const TXshSimpleLevel *oldSl);
115 
116   TPalette *getPalette()
117       const;  //!< Returns a pointer to the \a shared level palette.
118   void setPalette(TPalette *palette);  //!< Assigns a palette to the level.
119 
getPath()120   TFilePath getPath() const override { return m_path; }
121   void setPath(const TFilePath &path, bool retainCachedImages = false);
122 
getScannedPath()123   TFilePath getScannedPath() const { return m_scannedPath; }
124   void setScannedPath(const TFilePath &path);
125 
126   /*! \details      Each level frame have a corresponding image retrievable
127               with the getFrame() method and similar.
128 
129 \remark       Consider using functions getFrameCount() and getFrameId()
130               to avoid a container copy.                                      */
131 
132   std::vector<TFrameId> getFids()
133       const;  //!< Returns a copy of the level's frame ids.
134   void getFids(
135       std::vector<TFrameId> &fids) const override;  //!< Copies fids() into
136                                                     //! fids.  \deprecated  Use
137   //! the return valued
138   //! variation instead.
139 
140   TFrameId getFirstFid()
141       const;  //!< Returns the first level frame's id; roughly equivalent to
142               //!  <TT>index2fid(0)</TT>.
143   TFrameId getLastFid()
144       const;  //!< Returns the last level frame's id; roughly equivalent to
145               //!  <TT>index2fid(getFrameCount()-1)</TT>.
146 
isEmpty()147   bool isEmpty() const override {
148     return m_frames.empty();
149   }  //!< Returns whether the level is empty.
150   bool isFid(const TFrameId &fid)
151       const;  //!< Returns whether a given frameId is in the level.
152 
153   /*! \details  Unlike function index2fid(), getFrameId() \a asserts
154           beyond current frames count.                              */
155 
156   const TFrameId &getFrameId(
157       int index) const;  //!< Returns the frame id at specified index.
getFrameCount()158   int getFrameCount() const override {
159     return m_frames.size();
160   }  //!< Returns the level's frames count.
161 
162   /*! \details  Function index2fid() attempts guessing frame ids for
163           frame indexes beyond current frames count. See function
164           guessStep() for further details.                          */
165 
166   TFrameId index2fid(int index) const;  //!< Returns a frame id corresponding to
167                                         //! the specified frame index, or
168   //!  an invalid frame otherwise.
169   int fid2index(const TFrameId &fid) const;  //!< Returns the frame \a index
170                                              //! corresponding to the specified
171   //! frame id,
172   //!  or \p -1 if not found.
173 
174   /*
175 if the table contains 'fid' it returns fid2index(fid).
176 if fid is greater than the last fid in the table, it returns a "guessed" index.
177 e.g. if fids = [1,3,5,7] then fid2index(11) == 5
178 if fid is smaller than the last fid in the table (and is not contained in the
179 table) it returns the proper insertion index
180 */
181   int guessIndex(const TFrameId &fid) const;
182 
183   //! Analyzes the level's frames table and returns the alleged entries \a step
184   //! - ie the distance
185   //! from each entry to the next.
186   int guessStep() const;
187 
188   void setFrame(const TFrameId &fid, const TImageP &img);
189 
190   TImageP getFrame(const TFrameId &fid, UCHAR imgManagerParamsMask,
191                    int subsampling) const;
getFrame(const TFrameId & fid,bool toBeModified)192   TImageP getFrame(const TFrameId &fid, bool toBeModified) const {
193     return getFrame(
194         fid, toBeModified ? ImageManager::toBeModified : ImageManager::none, 0);
195   }
196   TImageP getFullsampledFrame(const TFrameId &fid,
197                               UCHAR imgManagerParamsMask) const;
198 
199   TImageInfo *getFrameInfo(const TFrameId &fid, bool toBeModified);
200   TImageP getFrameIcon(const TFrameId &fid) const;
201 
202   // load icon (and image) data of all frames into cache
203   void loadAllIconsAndPutInCache(bool cacheImagesAsWell);
204 
205   TRasterImageP getFrameToCleanup(const TFrameId &fid) const;
206 
207   std::string getImageId(const TFrameId &fid, int frameStatus = -1) const;
208   std::string getIconId(const TFrameId &fid, int frameStatus = -1) const;
209   std::string getIconId(const TFrameId &fid, const TDimension &size) const;
210 
211   void eraseFrame(const TFrameId &fid);
212   void clearFrames();
213   void invalidateFrames();
214 
215   void invalidateFrame(const TFrameId &fid);
216 
217   /*!
218 Set the range of frame that can be edited and saved.
219 Editable range is contained in \b m_editableRange.
220 */
221   void setEditableRange(unsigned int from, unsigned int to,
222                         const std::wstring &userName);
223   void mergeTemporaryHookFile(unsigned int from, unsigned int to,
224                               const TFilePath &hookFile);
225   void clearEditableRange();
226   std::wstring getEditableFileName();
227 
228   std::set<TFrameId>
229   getEditableRange();  //!< Returns the set of editable frames.
230 
231   int getFrameStatus(const TFrameId &fid) const;
232   void setFrameStatus(const TFrameId &fid, int status);
233 
234   /*! \details      This function will implicitly convert the input path
235               extension to a correctly formatted \a tlv. Behavior
236               is undefined in case the level is not of fullcolor type.
237 
238 \deprecated   Function is obviously an implementation detail of the
239               cleanup process. Should be moved there.                         */
240 
241   void makeTlv(const TFilePath &tlvPath);  //!< Transforms the level from \a
242                                            //! fullcolor to tlv (colormap),
243   //!  and assigns the specified level path.
244   TImageP createEmptyFrame();
245 
246   void initializePalette();
247   void initializeResolutionAndDpi(const TDimension &dim = TDimension(),
248                                   double dpi            = 0);
249 
250   TDimension getResolution();
251 
252   TPointD getImageDpi(const TFrameId &fid = TFrameId::NO_FRAME,
253                       int frameStatus     = -1);
254   int getImageSubsampling(const TFrameId &fid) const;
255   TPointD getDpi(const TFrameId &fid = TFrameId::NO_FRAME,
256                  int frameStatus     = -1);
257 
258   /*! \brief    Returns the bbox for the level's fid, specified in standard
259           \a inch coordinates (which are \a different from Toonz's
260           standard world coordinates, by a \p Stage::inch factor).            */
261 
262   TRectD getBBox(const TFrameId &fid) const;
263 
264   void setDirtyFlag(bool on) override;
265   bool getDirtyFlag() const;
266 
267   //! Updates content history (invokes setDirtyFlag(true))
268   //! \warning Not what users may expect!
269   void touchFrame(const TFrameId &fid);
270 
271   void loadData(TIStream &is) override;
272   void saveData(TOStream &os) override;
273 
274   //! Loads the level from disk, translating encoded level paths relative
275   //! to the level's scene path.
276   void load() override;
277   void load(const std::vector<TFrameId> &fIds);
278 
279   //! Saves the level to disk, with the same path deduction from load()
280   void save() override;
281 
282   /*!
283 Save the level in the specified fp.
284 The oldFp is used when the current scene path change...
285 */
286   void save(const TFilePath &fp, const TFilePath &oldFp = TFilePath(),
287             bool overwritePalette = true);
288 
289   //! note gets the contentHistory. can be 0
getContentHistory()290   const TContentHistory *getContentHistory() const {
291     return m_contentHistory.get();
292   }
getContentHistory()293   TContentHistory *getContentHistory() { return m_contentHistory.get(); }
294 
295   //! destroys the old contentHistory and replaces it with the new one. Gets
296   //! ownership
297   void setContentHistory(TContentHistory *contentHistory);
298 
299   //! Set elements of m_renumberTable with m_frames.
300   void setRenumberTable();
renumberTable()301   const std::map<TFrameId, TFrameId> &renumberTable() const {
302     return m_renumberTable;
303   }
304 
305   //! Renumbers the level frames to the specified fids (fids and this->fids()
306   //! must have the same size).
307   void renumber(const std::vector<TFrameId> &fids);
308 
309   bool isFrameReadOnly(TFrameId fid);
310 
311 public:
312   // Auxiliary files management: hooks, tpl, etc.
313   // May throw; copy and rename perform touchparentdir
314 
315   static void copyFiles(const TFilePath &dst,
316                         const TFilePath &src);  //!< Copy files from src to dst.
317   static void renameFiles(
318       const TFilePath &dst,
319       const TFilePath &src);  //!< Rename files from src to dst.
320   static void removeFiles(const TFilePath &fp);  //!< Remove files at fp.
321 
322   //! Get the auxiliary files list: hooks, tpl, etc.
323   static void getFiles(const TFilePath &fp, TFilePathSet &fpset);
324 
325   /*!
326 Translates a level path into the corresponding hook path (no check for
327 the existence of said hook file).
328 */
329   static TFilePath getHookPath(const TFilePath &levelPath);
330 
331   /*!
332 \brief    Returns the list of \a existing hook files associated to the
333         specified level, sorted by modification date (last modified at front).
334         The list stores <I>local paths<\I> relative to
335         decodedLevelPath.getParentDir().
336 
337 \note     A level may have multiple hook files if the hook set was edited
338         with older Toonz versions. Use this function if you need to access all
339         of them. Only the latest file format is considered when loading a level.
340 */
341   static QStringList getHookFiles(const TFilePath &decodedLevelPath);
342 
343   /*!
344 \brief    Returns the path of the newest \a existing hook file associated to the
345         specified \b decoded level path - or an empty path if none was found.
346 
347 \note     In case there are more than one hook file (ie files from older
348         Toonz version), the latest file version is used.
349 */
350   static TFilePath getExistingHookFile(const TFilePath &decodedLevelPath);
351 
352   static void setCompatibilityMasks(int writeMask, int neededMask,
353                                     int forbiddenMask);
354 
355 public Q_SLOTS:
356 
357   void onPaletteChanged();  //!< Invoked when some colorstyle has been changed
358 
359 private:
360   typedef boost::container::flat_set<TFrameId> FramesSet;
361 
362 private:
363   std::unique_ptr<LevelProperties> m_properties;
364   std::unique_ptr<TContentHistory> m_contentHistory;
365 
366   TPalette *m_palette;
367 
368   FramesSet m_frames;
369 
370   std::map<TFrameId, TFrameId>
371       m_renumberTable;  //!< Maps disk-frames to level-frames.
372   //!  Typically, the 2 match - however, the situation changes
373   //!  after an explicit frame renumbering process. In case
374   //!  a level-frame is deleted, the table entry is removed;
375   //!  it will be physically removed only when the level is saved.
376   //!  A similar thing happens with newly inserted frames.
377   std::map<TFrameId, int> m_framesStatus;
378 
379   std::set<TFrameId> m_editableRange;
380 
381   TFilePath m_path, m_scannedPath;
382 
383   std::string m_idBase;
384   std::wstring m_editableRangeUserInfo;
385 
386   bool m_isSubsequence, m_16BitChannelLevel, m_isReadOnly,
387       m_temporaryHookMerged;  //!< Used only during hook merge (and hence during
388                               //! saving)
389 
390 private:
391   //! Save simple level in scene-decoded path \p decodedFp.
392   void saveSimpleLevel(
393       const TFilePath &decodedFp,
394       bool overwritePalette = true);  // Difference from save(..)?
395 
396 private:
397   // Not copyable
398   TXshSimpleLevel(const TXshSimpleLevel &);
399   TXshSimpleLevel &operator=(const TXshSimpleLevel &);
400 };
401 
402 //=====================================================================================
403 
404 #ifdef _WIN32
405 template class DV_EXPORT_API TSmartPointerT<TXshSimpleLevel>;
406 #endif
407 typedef TSmartPointerT<TXshSimpleLevel> TXshSimpleLevelP;
408 
409 //=====================================================================================
410 
411 void DVAPI setLoadingLevelRange(const TFrameId &fromFid, const TFrameId &toFid);
412 void DVAPI getLoadingLevelRange(TFrameId &fromFid, TFrameId &toFid);
413 
414 #endif  // TXSHSIMPLELEVEL_INCLUDED
415