File indexing completed on 2024-05-19 04:29:09
0001 /* 0002 * SPDX-FileCopyrightText: 2017 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef KISASYNCANIMATIONRENDERERBASE_H 0008 #define KISASYNCANIMATIONRENDERERBASE_H 0009 0010 #include <QObject> 0011 #include "kis_types.h" 0012 0013 #include "kritaui_export.h" 0014 0015 class KisRegion; 0016 class KisLockFrameGenerationLock; 0017 0018 /** 0019 * KisAsyncAnimationRendererBase is a special class representing a 0020 * single worker thread inside KisAsyncAnimationRenderDialogBase. It connects 0021 * the specified image using correct Qt::DirectConnection connections and 0022 * reacts on them. On sigFrameReady() signal it calls frameCompletedCallback(), 0023 * so the derived class can fetch a frame from the image and process it. On 0024 * sigFrameCancelled() it calls frameCancelledCallback(). The derived class 0025 * should override these two methods to do the actual work. 0026 */ 0027 0028 class KRITAUI_EXPORT KisAsyncAnimationRendererBase : public QObject 0029 { 0030 Q_OBJECT 0031 0032 public: 0033 enum Flag 0034 { 0035 None = 0x0, 0036 Cancellable = 0x1 0037 }; 0038 Q_DECLARE_FLAGS(Flags, Flag) 0039 0040 enum CancelReason { 0041 UserCancelled = 0, 0042 RenderingFailed, 0043 RenderingTimedOut 0044 }; 0045 Q_ENUM(CancelReason) 0046 0047 public: 0048 explicit KisAsyncAnimationRendererBase(QObject *parent = 0); 0049 virtual ~KisAsyncAnimationRendererBase(); 0050 0051 /** 0052 * Initiates the rendering of the frame \p frame on an image \p image. 0053 * Only \p regionOfInterest is regenerated. If \p regionOfInterest is 0054 * empty, then entire bounds of the image is regenerated. 0055 */ 0056 void startFrameRegeneration(KisImageSP image, int frame, const KisRegion ®ionOfInterest, Flags flags, KisLockFrameGenerationLock &&frameGenerationLock); 0057 0058 /** 0059 * Convenience overload that regenerates the full image 0060 */ 0061 void startFrameRegeneration(KisImageSP image, int frame, Flags flags, KisLockFrameGenerationLock &&frameGenerationLock); 0062 0063 /** 0064 * @return true if the regeneration process is in progress 0065 */ 0066 bool isActive() const; 0067 0068 public Q_SLOTS: 0069 /** 0070 * @brief cancels current rendering operation 0071 * 0072 * After calling this slot requestedImage() becomes invalid. 0073 * @see requestedImage() 0074 */ 0075 void cancelCurrentFrameRendering(CancelReason cancelReason); 0076 0077 Q_SIGNALS: 0078 void sigFrameCompleted(int frame); 0079 void sigFrameCancelled(int frame, KisAsyncAnimationRendererBase::CancelReason cancelReason); 0080 0081 private Q_SLOTS: 0082 void slotFrameRegenerationCancelled(); 0083 void slotFrameRegenerationTimedOut(); 0084 void slotFrameRegenerationFinished(int frame); 0085 0086 protected Q_SLOTS: 0087 /** 0088 * Called by a derived class to continue processing of the frames 0089 */ 0090 void notifyFrameCompleted(int frame); 0091 0092 /** 0093 * Called by a derived class to cancel processing of the frames. After calling 0094 * this method, the dialog will stop processing the frames and close. 0095 */ 0096 void notifyFrameCancelled(int frame, KisAsyncAnimationRendererBase::CancelReason cancelReason); 0097 0098 protected: 0099 /** 0100 * @brief frameCompletedCallback is called by the renderer when 0101 * a new frame becomes ready 0102 * 0103 * NOTE1: the callback is called from the context of a image 0104 * worker thread! So it is asynchronous from the GUI thread. 0105 * NOTE2: in case of successful processing of the frame, the callback 0106 * must issue some signal, connected to notifyFrameCompleted() 0107 * via auto connection, to continue processing. Please do not 0108 * call the method directly, because notifyFame*() slots should 0109 * be called from the context of the GUI thread. 0110 * NOTE3: In case of failure, notifyFrameCancelled(). The same threading 0111 * rules apply. 0112 */ 0113 virtual void frameCompletedCallback(int frame, const KisRegion &requestedRegion) = 0; 0114 0115 /** 0116 * @brief frameCancelledCallback is called when the rendering of 0117 * the frame was cancelled. 0118 * 0119 * The rendering of the frame can be either cancelled by the image itself or 0120 * by receiving a timeout signal (10 seconds). 0121 * 0122 * NOTE: the slot is called in the GUI thread. Don't forget to call 0123 * notifyFrameCancelled() in he end of your call. 0124 */ 0125 virtual void frameCancelledCallback(int frame, CancelReason cancelReason) = 0; 0126 0127 0128 /** 0129 * Called by KisAsyncAnimationRendererBase when the processing has been completed 0130 * and the internal state of the populator should be cleared 0131 * 0132 * @param isCancelled tells if frame regeneration has failed to be regenerated 0133 */ 0134 virtual void clearFrameRegenerationState(bool isCancelled); 0135 0136 protected: 0137 /** 0138 * @return the image that for which the rendering was requested using 0139 * startFrameRegeneration(). Should be used by the derived classes only. 0140 * 0141 * Please note that requestedImage() will become null as soon as the user 0142 * cancels the processing. That happens in the GUI thread so 0143 * frameCompletedCallback() should be extremely careful when requesting the 0144 * value (check the shared pointer after fetching). 0145 */ 0146 KisImageSP requestedImage() const; 0147 0148 private: 0149 struct Private; 0150 const QScopedPointer<Private> m_d; 0151 }; 0152 0153 Q_DECLARE_OPERATORS_FOR_FLAGS(KisAsyncAnimationRendererBase::Flags) 0154 0155 #endif // KISASYNCANIMATIONRENDERERBASE_H