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