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 }