File indexing completed on 2024-05-12 15:58:45
0001 /* 0002 * SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef __KIS_TIME_RANGE_H 0008 #define __KIS_TIME_RANGE_H 0009 0010 #include "kritaimage_export.h" 0011 0012 #include <algorithm> 0013 #include <limits> 0014 #include <QMetaType> 0015 #include <boost/operators.hpp> 0016 #include "kis_types.h" 0017 #include <kis_dom_utils.h> 0018 0019 class KRITAIMAGE_EXPORT KisTimeSpan : public boost::equality_comparable<KisTimeSpan> 0020 { 0021 private: 0022 inline KisTimeSpan(int start, int end) 0023 : m_start(start), 0024 m_end(end) 0025 { 0026 } 0027 0028 public: 0029 inline KisTimeSpan() 0030 : m_start(0), 0031 m_end(-1) 0032 { 0033 } 0034 0035 inline int start() const { 0036 return m_start; 0037 } 0038 0039 inline int end() const { 0040 return m_end; 0041 } 0042 0043 inline int duration() const { 0044 return m_end >= m_start ? m_end - m_start + 1 : 0; 0045 } 0046 0047 inline bool isInfinite() const { 0048 return m_end == std::numeric_limits<int>::min(); 0049 } 0050 0051 inline bool isValid() const { 0052 return (m_end >= m_start) || (m_end == std::numeric_limits<int>::min() && m_start >= 0); 0053 } 0054 0055 inline bool contains(int time) const { 0056 if (m_end == std::numeric_limits<int>::min()) { 0057 return m_start <= time; 0058 } 0059 0060 return m_start <= time && time <= m_end; 0061 } 0062 0063 inline void include(int time) { 0064 m_start = qMin(time, m_start); 0065 m_end = qMax(time, m_end); 0066 } 0067 0068 inline bool overlaps(const KisTimeSpan& other) const { 0069 // If either are "invalid", we should probably return false. 0070 if (!isValid() || !other.isValid()) { 0071 return false; 0072 } 0073 0074 // Handle infinite cases... 0075 if (other.isInfinite()) { 0076 return (other.contains(start()) || other.contains(end())); 0077 } else if (isInfinite()) { 0078 return (contains(other.start()) || contains(other.end())); 0079 } 0080 0081 const int selfMin = qMin(start(), end()); 0082 const int selfMax = qMax(start(), end()); 0083 const int otherMin = qMin(other.start(), other.end()); 0084 const int otherMax = qMax(other.start(), other.end()); 0085 return (selfMax >= otherMin) && (selfMin <= otherMax ); 0086 } 0087 0088 static inline KisTimeSpan fromTimeToTime(int start, int end) { 0089 return KisTimeSpan(start, end); 0090 } 0091 0092 static inline KisTimeSpan fromTimeWithDuration(int start, int duration) { 0093 return KisTimeSpan( start, start + duration - 1); 0094 } 0095 0096 static inline KisTimeSpan infinite(int start) { 0097 return KisTimeSpan(start, std::numeric_limits<int>::min()); 0098 } 0099 0100 static KisTimeSpan calculateIdenticalFramesRecursive(const KisNode *node, int time); 0101 static KisTimeSpan calculateAffectedFramesRecursive(const KisNode *node, int time); 0102 0103 static KisTimeSpan calculateNodeIdenticalFrames(const KisNode *node, int time); 0104 static KisTimeSpan calculateNodeAffectedFrames(const KisNode *node, int time); 0105 0106 bool operator==(const KisTimeSpan &rhs) const { 0107 return rhs.m_start == m_start && rhs.m_end == m_end; 0108 } 0109 0110 KisTimeSpan operator|(const KisTimeSpan &rhs) const { 0111 KisTimeSpan result = *this; 0112 0113 if (!result.isValid()) { 0114 result.m_start = rhs.start(); 0115 } else if (rhs.isValid()) { 0116 result.m_start = std::min(result.m_start, rhs.start()); 0117 } 0118 0119 if (rhs.isInfinite() || result.isInfinite()) { 0120 result.m_end = std::numeric_limits<int>::min(); 0121 } else if (!isValid()) { 0122 result.m_end = rhs.m_end; 0123 } else { 0124 result.m_end = std::max(m_end, rhs.m_end); 0125 } 0126 0127 return result; 0128 } 0129 0130 const KisTimeSpan& operator|=(const KisTimeSpan &rhs) { 0131 KisTimeSpan result = (*this | rhs); 0132 this->m_start = result.m_start; 0133 this->m_end = result.m_end; 0134 return *this; 0135 } 0136 0137 KisTimeSpan operator&(const KisTimeSpan &rhs) const { 0138 KisTimeSpan result = *this; 0139 0140 if (!isValid()) { 0141 return result; 0142 } else if (!rhs.isValid()) { 0143 result.m_start = rhs.start(); 0144 result.m_end = rhs.m_end; 0145 return result; 0146 } else { 0147 result.m_start = std::max(result.m_start, rhs.start()); 0148 } 0149 0150 if (isInfinite()) { 0151 result.m_end = rhs.m_end; 0152 } else if (!rhs.isInfinite()) { 0153 result.m_end = std::min(result.m_end, rhs.m_end); 0154 } 0155 0156 return result; 0157 } 0158 0159 const KisTimeSpan& operator&=(const KisTimeSpan &rhs) { 0160 KisTimeSpan result = (*this & rhs); 0161 this->m_start = result.m_start; 0162 this->m_end = result.m_end; 0163 return *this; 0164 } 0165 0166 private: 0167 int m_start; 0168 int m_end; 0169 }; 0170 0171 namespace KisDomUtils { 0172 void KRITAIMAGE_EXPORT saveValue(QDomElement *parent, const QString &tag, const KisTimeSpan &range); 0173 bool KRITAIMAGE_EXPORT loadValue(const QDomElement &parent, const QString &tag, KisTimeSpan *range); 0174 } 0175 0176 0177 0178 Q_DECLARE_METATYPE(KisTimeSpan) 0179 0180 KRITAIMAGE_EXPORT QDebug operator<<(QDebug dbg, const KisTimeSpan &r); 0181 0182 0183 #endif /* __KIS_TIME_RANGE_H */