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 #include "kis_time_span.h" 0008 0009 #include <QDebug> 0010 #include "kis_keyframe_channel.h" 0011 #include "kis_node.h" 0012 #include "kis_layer_utils.h" 0013 0014 struct KisTimeSpanStaticRegistrar { 0015 KisTimeSpanStaticRegistrar() { 0016 qRegisterMetaType<KisTimeSpan>("KisTimeSpan"); 0017 } 0018 }; 0019 0020 static KisTimeSpanStaticRegistrar __registrar; 0021 0022 QDebug operator<<(QDebug dbg, const KisTimeSpan &r) 0023 { 0024 dbg.nospace() << "KisTimeSpan(" << r.start() << ", " << r.end() << ")"; 0025 0026 return dbg.space(); 0027 } 0028 0029 KisTimeSpan KisTimeSpan::calculateIdenticalFramesRecursive(const KisNode *node, int time) 0030 { 0031 KisTimeSpan range = KisTimeSpan::infinite(0); 0032 0033 KisLayerUtils::recursiveApplyNodes(node, 0034 [&range, time] (const KisNode *node) { 0035 if (node->visible()) { 0036 range &= calculateNodeIdenticalFrames(node, time); 0037 } 0038 }); 0039 0040 return range; 0041 } 0042 0043 KisTimeSpan KisTimeSpan::calculateAffectedFramesRecursive(const KisNode *node, int time) 0044 { 0045 KisTimeSpan range; 0046 0047 KisLayerUtils::recursiveApplyNodes(node, 0048 [&range, time] (const KisNode *node) { 0049 if (node->visible()) { 0050 range |= calculateNodeIdenticalFrames(node, time); 0051 } 0052 }); 0053 0054 return range; 0055 } 0056 0057 KisTimeSpan KisTimeSpan::calculateNodeIdenticalFrames(const KisNode *node, int time) 0058 { 0059 KisTimeSpan range = KisTimeSpan::infinite(0); 0060 0061 const QMap<QString, KisKeyframeChannel*> channels = 0062 node->keyframeChannels(); 0063 0064 Q_FOREACH (const KisKeyframeChannel *channel, channels) { 0065 // Intersection 0066 range &= channel->identicalFrames(time); 0067 } 0068 0069 return range; 0070 } 0071 0072 KisTimeSpan KisTimeSpan::calculateNodeAffectedFrames(const KisNode *node, int time) 0073 { 0074 KisTimeSpan range; 0075 0076 if (!node->visible()) return range; 0077 0078 const QMap<QString, KisKeyframeChannel*> channels = 0079 node->keyframeChannels(); 0080 0081 // TODO: channels should report to the image which channel exactly has changed 0082 // to avoid the dirty range to be stretched into infinity! 0083 0084 if (channels.isEmpty() || 0085 !channels.contains(KisKeyframeChannel::Raster.id())) { 0086 range = KisTimeSpan::infinite(0); 0087 return range; 0088 } 0089 0090 Q_FOREACH (const KisKeyframeChannel *channel, channels) { 0091 // Union 0092 range |= channel->affectedFrames(time); 0093 } 0094 0095 return range; 0096 } 0097 0098 namespace KisDomUtils { 0099 0100 void saveValue(QDomElement *parent, const QString &tag, const KisTimeSpan &range) 0101 { 0102 QDomDocument doc = parent->ownerDocument(); 0103 QDomElement e = doc.createElement(tag); 0104 parent->appendChild(e); 0105 0106 e.setAttribute("type", "timerange"); 0107 0108 if (range.isValid()) { 0109 e.setAttribute("from", toString(range.start())); 0110 0111 if (!range.isInfinite()) { 0112 e.setAttribute("to", toString(range.end())); 0113 } 0114 } 0115 } 0116 0117 0118 bool loadValue(const QDomElement &parent, const QString &tag, KisTimeSpan *range) 0119 { 0120 QDomElement e; 0121 if (!findOnlyElement(parent, tag, &e)) return false; 0122 0123 if (!Private::checkType(e, "timerange")) return false; 0124 0125 int start = toInt(e.attribute("from", "-1")); 0126 int end = toInt(e.attribute("to", "-1")); 0127 0128 if (start == -1) { 0129 *range = KisTimeSpan(); 0130 } else if (end == -1) { 0131 *range = KisTimeSpan::infinite(start); 0132 } else { 0133 *range = KisTimeSpan::fromTimeToTime(start, end); 0134 } 0135 return true; 0136 } 0137 0138 }