1 #pragma once
2 
3 #ifndef IMAGEMANAGER_H
4 #define IMAGEMANAGER_H
5 
6 #include <memory>
7 
8 // TnzCore includes
9 #include "timage.h"
10 #include "timageinfo.h"
11 
12 // STD includes
13 #include <string>
14 
15 // Qt includes
16 #include <QReadWriteLock>
17 
18 #undef DVAPI
19 #undef DVVAR
20 #ifdef TOONZLIB_EXPORTS
21 #define DVAPI DV_EXPORT_API
22 #define DVVAR DV_EXPORT_VAR
23 #else
24 #define DVAPI DV_IMPORT_API
25 #define DVVAR DV_IMPORT_VAR
26 #endif
27 
28 //=====================================================
29 
30 //  Forward declarations
31 
32 class TFrameId;
33 class TImageInfo;
34 class TImageReader;
35 
36 class QReadWriteLock;
37 
38 class ImageBuilder;
39 
40 class TXshSimpleLevel;
41 //=====================================================
42 
43 //***************************************************************************************
44 //    Image Manager declaration
45 //***************************************************************************************
46 
47 //! ImageManager is a singleton management class that associates string
48 //! identifiers to
49 //! image-building objects, able to fetch images on request.
50 /*!
51     The ImageManager's purpose is similar to that of TImageCache - which is
52    Toonz's other
53     images storage class - with the difference that users do not supply it
54    directly with
55     the image to be stored, but rather with an object \a capable of fetching
56    that image.
57     \n\n
58     Said objects must be reimplemented from the base ImageBuilder class, and
59    return an
60     image, and its specifications, upon request.
61 
62     The role of these image-building objects is that of providing the \a default
63    image
64     for an identifier on-demand, without prior allocation of resources.
65     \n\n
66     The ImageManager automatically stores built images in the global TImageCache
67    instance
68     (unless the user explicitly requires not to) in order to minimize the images
69    building
70     process.
71     \n\n
72     As long as an image bound in the ImageManager remains unmodified, users can
73    rebuild
74     default images according to different control modifiers (for example,
75    requiring 64-bit
76     preference, or image subsampling).
77     \n\n
78     Images stored in the ImageManager can be modified by the user (using the
79    toBeModified
80     control flag) or even externally supplied using the setImage() method.
81 
82     When an image is modified, it is assumed to override any default-buildable
83    images - thus
84     it is stored in the cache for retrieval, and any control flag modifier is
85    ignored as long as
86     the image is not invalidated().
87     \n\n
88     Invalidation of an image can be requested to revert any changes to the image
89    and clear
90     the cache.
91     \n\n
92     Please, observe that ImageManager's image caching function is thread-safe -
93    and
94     ensures that image building happens only once in case multiple threads
95    simultaneously
96     require an image that was not cached before. Furthermore, there is no
97    serialization
98     overhead for already cached images or image specifications in read-only
99    access.
100 
101     \sa The TImageCache and ImageBuilder classes.
102 */
103 
104 class DVAPI ImageManager {
105 public:
106   enum {
107     none           = 0x0,
108     dontPutInCache = 0x1,  // Prevents IM from storing built images in the cache
109     forceRebuild   = 0x2,  // Forces rebuild of images (like an invalidate())
110     toBeModified =
111         0x4,          // Whether the retrieved image will be signed as modified
112     toBeSaved = 0x8,  // User will save the image, reverts toBeModified
113 
114     is64bitEnabled = 0x10,  // Whether 64-bit rasters are allowed to return
115 
116     controlFlags = 0xF,  // Flags dealing with management control
117     imageFlags =
118         ~controlFlags  // ImageManager flags supportable by custom ImageBuilders
119   };
120 
121 public:
122   static ImageManager *instance();
123 
124   /*!
125 Binds a string identifier to an ImageBuilder instance, which is necessary before
126 any image or
127 image data can be retrieved. If the specified id was already bound, it is first
128 unbound.
129 Binding an id to 0 is equivalent to unbinding it.
130 */
131   void bind(const std::string &id, ImageBuilder *builder);
132 
133   //! Unbinds the specified identifier, returning true if the operation
134   //! succeeded.
135   bool unbind(const std::string &id);
136 
137   //! Returns true if the specified id is bound to an image builder.
138   bool isBound(const std::string &id) const;
139 
140   //! Rebinds to a different builder identifier, returning true if the operation
141   //! succeeded.
142   bool rebind(const std::string &srcId, const std::string &dstId);
143 
144   bool renumber(const std::string &srcId, const TFrameId &fid);
145 
146   //! Unbinds all known identifiers, resetting the image manager to its empty
147   //! state.
148   void clear();
149 
150   // load icon (and image) data of all frames into cache
151   void loadAllTlvIconsAndPutInCache(TXshSimpleLevel *, std::vector<TFrameId>,
152                                     std::vector<std::string>, bool);
153 
154   /*!
155 Returns the image built by the object associated with the specified identifier,
156 using the
157 supplied control flags for additional options. Provided the builder type
158 associated to the
159 identifier is known, a further external reference can be supplied to the
160 request. In this case,
161 users should enforce manual invalidate() invocations whenever the supplied data
162 changes.
163 
164 \warning Users take responsibility in modifying the returned image's data \b
165 only when imFlags
166 contains the \c toBeModified bit.
167 */
168   TImageP getImage(const std::string &id, int imFlags, void *extData);
169 
170   /*!
171 Returns the image info associated to the specified identifier.
172 
173 \warning The return type is not explicitly \c const since some of TImageInfo's
174 data (namely,
175 the image's bounding box) may need to be modified by the user together with the
176 associated image.
177 Like in getImage(), users take responsibility in modifying the returned data \b
178 only when imFlags
179 contains the \c toBeModified bit.
180 */
181   TImageInfo *getInfo(const std::string &id, int imFlags, void *extData);
182 
183   //! Invalidates cached data associated to the specified id, forcing the next
184   //! getInfo() or
185   //! getImage() to rebuild it.
186   bool invalidate(const std::string &id);
187 
188   /*!
189 Overrides the image builder, and manually associates an image to the specified
190 identifier,
191 putting the image in cache and updating the stored image info. If the image
192 reference is
193 empty, the result is equivalent to invalidate().
194 */
195   bool setImage(const std::string &id, const TImageP &img);
196 
197   //! Returns the ImageBuilder instance associate to specified id, or 0 if none
198   //! was found.
199   //! \warning The ImageManger retains ownership of the returned object, which
200   //! must \b not be deleted.
201   ImageBuilder *getBuilder(const std::string &id);
202 
203   //! Returns whether the identifier has an associated image in cache.
204   bool isCached(const std::string &id);
205 
206   /*!
207 Returns whether the image associated to the specified id has been modified.
208 Observe that
209 modifying an image overrides the build-up of the associated default image - ie
210 any subsequent
211 call to getImage() will ignore control flags and return the stored modified
212 image.
213 */
214   bool isModified(const std::string &id);
215 
216 private:
217   struct Imp;
218   std::unique_ptr<Imp> m_imp;
219 
220 private:
221   ImageManager();
222   ~ImageManager();
223 
224   // Not copyable
225   ImageManager(const ImageManager &);
226   ImageManager &operator=(const ImageManager &);
227 };
228 
229 //***************************************************************************************
230 //    ImageBuilder declaration
231 //***************************************************************************************
232 
233 //! ImageBuilder is the class model for self-creating image objects bound in the
234 //! ImageManager.
235 class DVAPI ImageBuilder : public TSmartObject {
236   DECLARE_CLASS_CODE
237 
238 public:
239   ImageBuilder();
240   virtual ~ImageBuilder();
241 
imageCached()242   bool imageCached() { return m_cached; }
imageModified()243   bool imageModified() { return m_modified; }
244 
245   /*!
246 Returns whether any currently cached image is compatible with requested
247 specifications,
248 Returning true prevents ImageBuilder::build() invocations, fetching the cached
249 data instead.
250 The default implementation returns true if m_info has positive m_lx and m_ly.
251 */
252   virtual bool isImageCompatible(int imFlags, void *extData);
253 
254   /*!
255 Returns whether any currently cached image infos are compatible with requested
256 specifications.
257 Returning true prevents ImageBuilder::build() invocations, fetching the cached
258 data instead.
259 The default implementation returns m_info.m_valid.
260 */
261   virtual bool areInfosCompatible(int imFlags, void *extData);
262 
263 public:
264   // Helper functions to fill in a TImageInfo structure.
265   // Each of these sets info.m_valid at true if the associated infos could be
266   // loaded.
267 
268   static bool setImageInfo(TImageInfo &info, const TDimension &size);
269   static bool setImageInfo(TImageInfo &info, TImage *img);
270   static bool setImageInfo(TImageInfo &info, TImageReader *ir);
271 
272 protected:
273   TImageInfo m_info;  //!< Currently cached image data - size, bpp, etc
274   int m_imFlags;      //!< Currently cached image control flags
275 
276 protected:
277   //! Builds the image as specified by the supplied control flags and external
278   //! data.
279   virtual TImageP build(int imFlags, void *extData) = 0;
280 
281   //! Returns the image infos as specified by the supplied control flags and
282   //! external data.
283   virtual bool getInfo(TImageInfo &info, int imFlags, void *extData) = 0;
284 
285   // load icon (and image) data of all frames into cache. impremented in
286   // ImageLoader
buildAllIconsAndPutInCache(TXshSimpleLevel *,std::vector<TFrameId>,std::vector<std::string>,bool)287   virtual void buildAllIconsAndPutInCache(TXshSimpleLevel *,
288                                           std::vector<TFrameId>,
289                                           std::vector<std::string>, bool){};
290 
setFid(const TFrameId & fid)291   virtual void setFid(const TFrameId &fid){};
292 
293   //! Clears the builder's cached data.
invalidate()294   virtual void invalidate() {
295     m_info    = TImageInfo();
296     m_imFlags = ImageManager::none;
297   }
298 
299 private:
300   friend class ImageManager;
301 
302   QReadWriteLock
303       m_imageBuildingLock;  //!< Image building is mutexed by the ImageManager
304 
305   bool m_cached;    //!< Whether the associated image was stored in cache
306   bool m_modified;  //!< Whether the associated image was modified
307 
308 private:
309   // Not copyable
310   ImageBuilder(const ImageBuilder &);
311   const ImageBuilder &operator=(const ImageBuilder &);
312 
setImageCachedAndModified()313   void setImageCachedAndModified() {
314     m_cached   = true;
315     m_modified = true;
316   }
317 };
318 
319 //-----------------------------------------------------------------------------
320 
321 #ifdef _WIN32
322 template class DV_EXPORT_API TSmartPointerT<ImageBuilder>;
323 #endif
324 
325 typedef TSmartPointerT<ImageBuilder> ImageBuilderP;
326 
327 //-----------------------------------------------------------------------------
328 
329 #endif
330