File indexing completed on 2024-12-22 04:15:39
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_exr_layers_sorter.h" 0008 0009 #include <QDomDocument> 0010 #include <QDomElement> 0011 0012 #include "kis_image.h" 0013 #include "exr_extra_tags.h" 0014 #include "kis_kra_savexml_visitor.h" 0015 #include "kis_paint_layer.h" 0016 0017 0018 struct KisExrLayersSorter::Private 0019 { 0020 Private(const QDomDocument &_extraData, KisImageSP _image) 0021 : extraData(_extraData), image(_image) {} 0022 0023 const QDomDocument &extraData; 0024 KisImageSP image; 0025 0026 QMap<QString, QDomElement> pathToElementMap; 0027 QMap<QString, int> pathToOrderingMap; 0028 0029 QMap<KisNodeSP, int> nodeToOrderingMap; 0030 0031 void createOrderingMap(); 0032 void processLayers(KisNodeSP root); 0033 void sortLayers(KisNodeSP root); 0034 }; 0035 0036 QString getNodePath(KisNodeSP node) { 0037 KIS_ASSERT_RECOVER(node) { return "UNDEFINED"; } 0038 0039 QString path; 0040 0041 KisNodeSP parentNode = node->parent(); 0042 while(parentNode) { 0043 if (!path.isEmpty()) { 0044 path.prepend("."); 0045 } 0046 path.prepend(node->name()); 0047 0048 node = parentNode; 0049 parentNode = node->parent(); 0050 } 0051 0052 return path; 0053 } 0054 0055 void KisExrLayersSorter::Private::createOrderingMap() 0056 { 0057 int index = 0; 0058 QDomElement el = extraData.documentElement().firstChildElement(); 0059 0060 0061 while (!el.isNull()) { 0062 QString path = el.attribute(EXR_NAME); 0063 pathToElementMap.insert(path, el); 0064 pathToOrderingMap.insert(path, index); 0065 0066 el = el.nextSiblingElement(); 0067 index++; 0068 } 0069 } 0070 0071 template <typename T> 0072 T fetchMapValueLazy(const QMap<QString, T> &map, QString path) 0073 { 0074 if (map.contains(path)) return map[path]; 0075 0076 0077 typename QMap<QString, T>::const_iterator it = map.constBegin(); 0078 typename QMap<QString, T>::const_iterator end = map.constEnd(); 0079 0080 for (; it != end; ++it) { 0081 if (it.key().startsWith(path)) { 0082 return it.value(); 0083 } 0084 } 0085 0086 return T(); 0087 } 0088 0089 void KisExrLayersSorter::Private::processLayers(KisNodeSP root) 0090 { 0091 if (root && root->parent()) { 0092 QString path = getNodePath(root); 0093 0094 nodeToOrderingMap.insert(root, fetchMapValueLazy(pathToOrderingMap, path)); 0095 0096 if (KisPaintLayer *paintLayer = dynamic_cast<KisPaintLayer*>(root.data())) { 0097 KisSaveXmlVisitor::loadPaintLayerAttributes(pathToElementMap[path], paintLayer); 0098 } 0099 } 0100 0101 KisNodeSP child = root->firstChild(); 0102 while (child) { 0103 processLayers(child); 0104 child = child->nextSibling(); 0105 } 0106 } 0107 0108 struct CompareNodesFunctor 0109 { 0110 CompareNodesFunctor(const QMap<KisNodeSP, int> &map) 0111 : m_nodeToOrderingMap(map) {} 0112 0113 bool operator() (KisNodeSP lhs, KisNodeSP rhs) { 0114 return m_nodeToOrderingMap[lhs] < m_nodeToOrderingMap[rhs]; 0115 } 0116 0117 private: 0118 const QMap<KisNodeSP, int> &m_nodeToOrderingMap; 0119 }; 0120 0121 0122 void KisExrLayersSorter::Private::sortLayers(KisNodeSP root) 0123 { 0124 QList<KisNodeSP> childNodes; 0125 0126 // first move all the children to the list 0127 KisNodeSP child = root->firstChild(); 0128 while (child) { 0129 KisNodeSP lastChild = child; 0130 child = child->nextSibling(); 0131 0132 childNodes.append(lastChild); 0133 image->removeNode(lastChild); 0134 } 0135 0136 // sort the list 0137 std::stable_sort(childNodes.begin(), childNodes.end(), CompareNodesFunctor(nodeToOrderingMap)); 0138 0139 // put the children back 0140 Q_FOREACH (KisNodeSP node, childNodes) { 0141 image->addNode(node, root, root->childCount()); 0142 } 0143 0144 // recursive calls 0145 child = root->firstChild(); 0146 while (child) { 0147 sortLayers(child); 0148 child = child->nextSibling(); 0149 } 0150 } 0151 0152 KisExrLayersSorter::KisExrLayersSorter(const QDomDocument &extraData, KisImageSP image) 0153 : m_d(new Private(extraData, image)) 0154 { 0155 KIS_ASSERT_RECOVER_RETURN(!extraData.isNull()); 0156 m_d->createOrderingMap(); 0157 0158 m_d->processLayers(image->root()); 0159 m_d->sortLayers(image->root()); 0160 } 0161 0162 KisExrLayersSorter::~KisExrLayersSorter() 0163 { 0164 }