File indexing completed on 2025-01-26 04:10:29
0001 /* 0002 * SPDX-FileCopyrightText: 2013 Dmitry Kazakov <dimula73@gmail.com> 0003 * SPDX-FileCopyrightText: 2013 Lukáš Tvrdý <lukast.dev@gmail.com> 0004 * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy@amyspark.me> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include <QRegularExpression> 0010 0011 #include <KoCompositeOpRegistry.h> 0012 #include <commands/KisNodeRenameCommand.h> 0013 #include <commands/kis_node_compositeop_command.h> 0014 #include <commands/kis_node_opacity_command.h> 0015 #include <commands_new/kis_node_move_command2.h> 0016 #include <kis_command_utils.h> 0017 #include <kis_layer_utils.h> 0018 #include <kis_node.h> 0019 #include <kis_paint_layer.h> 0020 #include <kis_painter.h> 0021 #include <kis_selection.h> 0022 #include <kis_types.h> 0023 0024 #include "gmic.h" 0025 #include "kis_qmic_import_tools.h" 0026 #include "kis_qmic_interface.h" 0027 #include "kis_qmic_simple_convertor.h" 0028 0029 namespace KisQmicImportTools 0030 { 0031 [[nodiscard]] KUndo2Command * 0032 applyLayerNameChanges(const KisQMicImage &srcGmicImage, 0033 KisNode *node, 0034 KisSelectionSP selection) 0035 { 0036 dbgPlugins << "KisQmicImportTools::applyLayerNameChanges"; 0037 0038 auto *cmd = new KisCommandUtils::CompositeCommand(); 0039 0040 dbgPlugins << "Layer name: " << srcGmicImage.m_layerName; 0041 0042 { 0043 const QRegExp modeRe(R"(mode\(\s*([^)]*)\s*\))"); 0044 if (modeRe.indexIn(srcGmicImage.m_layerName) != -1) { 0045 QString modeStr = modeRe.cap(1).trimmed(); 0046 auto translatedMode = 0047 KisQmicSimpleConvertor::stringToBlendingMode(modeStr); 0048 dbgPlugins << "Detected mode: " << modeStr << " => " 0049 << translatedMode; 0050 if (!translatedMode.isNull()) { 0051 cmd->addCommand( 0052 new KisNodeCompositeOpCommand(node, translatedMode)); 0053 } 0054 } 0055 } 0056 0057 { 0058 const QRegExp opacityRe(R"(opacity\(\s*([^)]*)\s*\))"); 0059 0060 if (opacityRe.indexIn(srcGmicImage.m_layerName) != -1) { 0061 const auto opacity = opacityRe.cap(1).toFloat(); 0062 dbgPlugins << "Detected opacity: " << opacity 0063 << std::lround(opacity / 100.f * 255.f); 0064 cmd->addCommand( 0065 new KisNodeOpacityCommand(node, 0066 static_cast<quint8>(std::lround( 0067 float(opacity * 255) / 100.f)))); 0068 } 0069 } 0070 0071 { 0072 const QRegExp nameRe(R"(name\(\s*([^)]*)\s*\))"); 0073 0074 if (nameRe.indexIn(srcGmicImage.m_layerName) != -1) { 0075 const auto name = nameRe.cap(1); 0076 dbgPlugins << "Detected layer name: " << name; 0077 cmd->addCommand(new KisNodeRenameCommand(node, node->name(), name)); 0078 // apply command 0079 } 0080 } 0081 0082 if (!selection) { 0083 // Some GMic filters encode layer position into the layer name. 0084 // E.g. from extract foreground: "name([unnamed] 0085 // [foreground]),pos(55,35)" 0086 const QRegularExpression positionPattern( 0087 R"(pos\(\s*(-?\d*)[^)](-?\d*)\s*\))"); 0088 const QRegularExpressionMatch match = 0089 positionPattern.match(srcGmicImage.m_layerName); 0090 if (match.hasMatch()) { 0091 const auto x = match.captured(1).toInt(); 0092 const auto y = match.captured(2).toInt(); 0093 const QPoint oldPos(node->x(), node->y()); 0094 const QPoint newPos(x, y); 0095 dbgPlugins << "Detected layer position: " << oldPos << newPos 0096 << node->paintDevice()->exactBounds(); 0097 cmd->addCommand(new KisNodeMoveCommand2(node, oldPos, newPos)); 0098 } 0099 } 0100 0101 return cmd; 0102 } 0103 0104 void gmicImageToPaintDevice(const KisQMicImage &srcGmicImage, 0105 KisPaintDeviceSP dst, 0106 KisSelectionSP selection, 0107 const QRect &dstRect) 0108 { 0109 dbgPlugins << "KisQmicImportTools::gmicImageToPaintDevice()" << dstRect; 0110 0111 if (selection) { 0112 KisPaintDeviceSP src = new KisPaintDevice(dst->colorSpace()); 0113 KisQmicSimpleConvertor::convertFromGmicFast(srcGmicImage, src, 255.0f); 0114 KisPainter painter(dst, selection); 0115 painter.setCompositeOpId(COMPOSITE_COPY); 0116 painter.bitBlt(dstRect.topLeft(), 0117 src, 0118 QRect(QPoint(0, 0), dstRect.size())); 0119 } else { 0120 KisQmicSimpleConvertor::convertFromGmicFast(srcGmicImage, dst, 255.0f); 0121 } 0122 } 0123 0124 KisNodeListSP 0125 inputNodes(KisImageSP image, InputLayerMode inputMode, KisNodeSP currentNode) 0126 { 0127 /* 0128 ACTIVE_LAYER, 0129 ALL_LAYERS, 0130 ACTIVE_LAYER_BELOW_LAYER, 0131 ACTIVE_LAYER_ABOVE_LAYER, 0132 ALL_VISIBLE_LAYERS, 0133 ALL_INVISIBLE_LAYERS, 0134 ALL_VISIBLE_LAYERS_DECR, 0135 ALL_INVISIBLE_DECR, 0136 ALL_DECR 0137 */ 0138 const auto isAvailable = [](KisNodeSP node) -> bool { 0139 auto *paintLayer = dynamic_cast<KisPaintLayer *>(node.data()); 0140 return paintLayer && paintLayer->visible(false); 0141 }; 0142 0143 KisNodeListSP result(new QList<KisNodeSP>()); 0144 switch (inputMode) { 0145 case InputLayerMode::NoInput: { 0146 break; 0147 } 0148 case InputLayerMode::Active: { 0149 if (isAvailable(currentNode)) { 0150 result->prepend(currentNode); 0151 } 0152 break; // drop down in case of one more layer modes 0153 } 0154 case InputLayerMode::All: { 0155 result = [&]() { 0156 KisNodeListSP r(new QList<KisNodeSP>()); 0157 KisLayerUtils::recursiveApplyNodes( 0158 image->root(), 0159 [&](KisNodeSP item) { 0160 auto *paintLayer = 0161 dynamic_cast<KisPaintLayer *>(item.data()); 0162 if (paintLayer) { 0163 r->prepend(item); 0164 } 0165 }); 0166 return r; 0167 }(); 0168 break; 0169 } 0170 case InputLayerMode::ActiveAndBelow: { 0171 if (isAvailable(currentNode)) { 0172 result->prepend(currentNode); 0173 if (isAvailable(currentNode->prevSibling())) { 0174 result->prepend(currentNode->prevSibling()); 0175 } 0176 } 0177 break; 0178 } 0179 case InputLayerMode::ActiveAndAbove: { 0180 if (isAvailable(currentNode)) { 0181 result->prepend(currentNode); 0182 if (isAvailable(currentNode->nextSibling())) { 0183 result->prepend(currentNode->nextSibling()); 0184 } 0185 } 0186 break; 0187 } 0188 case InputLayerMode::AllVisible: 0189 case InputLayerMode::AllInvisible: { 0190 const bool visibility = (inputMode == InputLayerMode::AllInvisible); 0191 0192 result = [&]() { 0193 KisNodeListSP r(new QList<KisNodeSP>()); 0194 KisLayerUtils::recursiveApplyNodes( 0195 image->root(), 0196 [&](KisNodeSP item) { 0197 auto *paintLayer = 0198 dynamic_cast<KisPaintLayer *>(item.data()); 0199 if (paintLayer 0200 && paintLayer->visible(false) == visibility) { 0201 r->prepend(item); 0202 } 0203 }); 0204 return r; 0205 }(); 0206 break; 0207 } 0208 case InputLayerMode::Unspecified: 0209 default: { 0210 qWarning() 0211 << "Inputmode" << static_cast<int>(inputMode) 0212 << "must be specified by GMic or is not implemented in Krita"; 0213 break; 0214 } 0215 } 0216 return result; 0217 } 0218 } // namespace KisQmicImportTools