1 /* 2 * Copyright (c) 2015 Dmitry Kazakov <dimula73@gmail.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19 #include "kis_layer_utils.h" 20 21 #include <algorithm> 22 23 #include <QUuid> 24 #include <KoColorSpaceConstants.h> 25 #include <KoProperties.h> 26 27 #include "kis_painter.h" 28 #include "kis_image.h" 29 #include "kis_node.h" 30 #include "kis_layer.h" 31 #include "kis_paint_layer.h" 32 #include "kis_clone_layer.h" 33 #include "kis_group_layer.h" 34 #include "kis_selection.h" 35 #include "kis_selection_mask.h" 36 #include "kis_meta_data_merge_strategy.h" 37 #include <kundo2command.h> 38 #include "commands/kis_image_layer_add_command.h" 39 #include "commands/kis_image_layer_remove_command.h" 40 #include "commands/kis_image_layer_move_command.h" 41 #include "commands/kis_image_change_layers_command.h" 42 #include "commands_new/kis_activate_selection_mask_command.h" 43 #include "commands/kis_image_change_visibility_command.h" 44 #include "kis_abstract_projection_plane.h" 45 #include "kis_processing_applicator.h" 46 #include "kis_image_animation_interface.h" 47 #include "kis_keyframe_channel.h" 48 #include "kis_command_utils.h" 49 #include "commands_new/kis_change_projection_color_command.h" 50 #include "kis_layer_properties_icons.h" 51 #include "lazybrush/kis_colorize_mask.h" 52 #include "commands/kis_node_property_list_command.h" 53 #include "commands/kis_node_compositeop_command.h" 54 #include <KisDelayedUpdateNodeInterface.h> 55 #include <KisCroppedOriginalLayerInterface.h> 56 #include "krita_utils.h" 57 #include "kis_image_signal_router.h" 58 59 60 namespace KisLayerUtils { 61 fetchSelectionMasks(KisNodeList mergedNodes,QVector<KisSelectionMaskSP> & selectionMasks)62 void fetchSelectionMasks(KisNodeList mergedNodes, QVector<KisSelectionMaskSP> &selectionMasks) 63 { 64 foreach (KisNodeSP node, mergedNodes) { 65 66 Q_FOREACH(KisNodeSP child, node->childNodes(QStringList("KisSelectionMask"), KoProperties())) { 67 68 KisSelectionMaskSP mask = qobject_cast<KisSelectionMask*>(child.data()); 69 if (mask) { 70 selectionMasks.append(mask); 71 } 72 } 73 } 74 } 75 76 struct MergeDownInfoBase { MergeDownInfoBaseKisLayerUtils::MergeDownInfoBase77 MergeDownInfoBase(KisImageSP _image) 78 : image(_image), 79 storage(new SwitchFrameCommand::SharedStorage()) 80 { 81 } ~MergeDownInfoBaseKisLayerUtils::MergeDownInfoBase82 virtual ~MergeDownInfoBase() {} 83 84 KisImageWSP image; 85 86 QVector<KisSelectionMaskSP> selectionMasks; 87 88 KisNodeSP dstNode; 89 90 SwitchFrameCommand::SharedStorageSP storage; 91 QSet<int> frames; 92 bool useInTimeline = false; 93 bool enableOnionSkins = false; 94 95 virtual KisNodeList allSrcNodes() = 0; 96 dstLayerKisLayerUtils::MergeDownInfoBase97 KisLayerSP dstLayer() { 98 return qobject_cast<KisLayer*>(dstNode.data()); 99 } 100 }; 101 102 struct MergeDownInfo : public MergeDownInfoBase { MergeDownInfoKisLayerUtils::MergeDownInfo103 MergeDownInfo(KisImageSP _image, 104 KisLayerSP _prevLayer, 105 KisLayerSP _currLayer) 106 : MergeDownInfoBase(_image), 107 prevLayer(_prevLayer), 108 currLayer(_currLayer) 109 { 110 frames = 111 fetchLayerFramesRecursive(prevLayer) | 112 fetchLayerFramesRecursive(currLayer); 113 114 useInTimeline = prevLayer->useInTimeline() || currLayer->useInTimeline(); 115 116 const KisPaintLayer *paintLayer = qobject_cast<KisPaintLayer*>(currLayer.data()); 117 if (paintLayer) enableOnionSkins |= paintLayer->onionSkinEnabled(); 118 119 paintLayer = qobject_cast<KisPaintLayer*>(prevLayer.data()); 120 if (paintLayer) enableOnionSkins |= paintLayer->onionSkinEnabled(); 121 } 122 123 KisLayerSP prevLayer; 124 KisLayerSP currLayer; 125 allSrcNodesKisLayerUtils::MergeDownInfo126 KisNodeList allSrcNodes() override { 127 KisNodeList mergedNodes; 128 mergedNodes << prevLayer; 129 mergedNodes << currLayer; 130 return mergedNodes; 131 } 132 }; 133 134 struct MergeMultipleInfo : public MergeDownInfoBase { MergeMultipleInfoKisLayerUtils::MergeMultipleInfo135 MergeMultipleInfo(KisImageSP _image, 136 KisNodeList _mergedNodes) 137 : MergeDownInfoBase(_image), 138 mergedNodes(_mergedNodes) 139 { 140 foreach (KisNodeSP node, mergedNodes) { 141 frames |= fetchLayerFramesRecursive(node); 142 useInTimeline |= node->useInTimeline(); 143 144 const KisPaintLayer *paintLayer = qobject_cast<KisPaintLayer*>(node.data()); 145 if (paintLayer) { 146 enableOnionSkins |= paintLayer->onionSkinEnabled(); 147 } 148 } 149 } 150 151 KisNodeList mergedNodes; 152 bool nodesCompositingVaries = false; 153 allSrcNodesKisLayerUtils::MergeMultipleInfo154 KisNodeList allSrcNodes() override { 155 return mergedNodes; 156 } 157 }; 158 159 typedef QSharedPointer<MergeDownInfoBase> MergeDownInfoBaseSP; 160 typedef QSharedPointer<MergeDownInfo> MergeDownInfoSP; 161 typedef QSharedPointer<MergeMultipleInfo> MergeMultipleInfoSP; 162 163 struct FillSelectionMasks : public KUndo2Command { FillSelectionMasksKisLayerUtils::FillSelectionMasks164 FillSelectionMasks(MergeDownInfoBaseSP info) : m_info(info) {} 165 redoKisLayerUtils::FillSelectionMasks166 void redo() override { 167 fetchSelectionMasks(m_info->allSrcNodes(), m_info->selectionMasks); 168 } 169 170 private: 171 MergeDownInfoBaseSP m_info; 172 }; 173 174 struct DisableColorizeKeyStrokes : public KisCommandUtils::AggregateCommand { DisableColorizeKeyStrokesKisLayerUtils::DisableColorizeKeyStrokes175 DisableColorizeKeyStrokes(MergeDownInfoBaseSP info) : m_info(info) {} 176 populateChildCommandsKisLayerUtils::DisableColorizeKeyStrokes177 void populateChildCommands() override { 178 Q_FOREACH (KisNodeSP node, m_info->allSrcNodes()) { 179 recursiveApplyNodes(node, 180 [this] (KisNodeSP node) { 181 if (dynamic_cast<KisColorizeMask*>(node.data()) && 182 KisLayerPropertiesIcons::nodeProperty(node, KisLayerPropertiesIcons::colorizeEditKeyStrokes, true).toBool()) { 183 184 KisBaseNode::PropertyList props = node->sectionModelProperties(); 185 KisLayerPropertiesIcons::setNodeProperty(&props, 186 KisLayerPropertiesIcons::colorizeEditKeyStrokes, 187 false); 188 189 addCommand(new KisNodePropertyListCommand(node, props)); 190 } 191 }); 192 } 193 } 194 195 private: 196 MergeDownInfoBaseSP m_info; 197 }; 198 199 struct DisableOnionSkins : public KisCommandUtils::AggregateCommand { DisableOnionSkinsKisLayerUtils::DisableOnionSkins200 DisableOnionSkins(MergeDownInfoBaseSP info) : m_info(info) {} 201 populateChildCommandsKisLayerUtils::DisableOnionSkins202 void populateChildCommands() override { 203 Q_FOREACH (KisNodeSP node, m_info->allSrcNodes()) { 204 recursiveApplyNodes(node, 205 [this] (KisNodeSP node) { 206 if (KisLayerPropertiesIcons::nodeProperty(node, KisLayerPropertiesIcons::onionSkins, false).toBool()) { 207 208 KisBaseNode::PropertyList props = node->sectionModelProperties(); 209 KisLayerPropertiesIcons::setNodeProperty(&props, 210 KisLayerPropertiesIcons::onionSkins, 211 false); 212 213 addCommand(new KisNodePropertyListCommand(node, props)); 214 } 215 }); 216 } 217 } 218 219 private: 220 MergeDownInfoBaseSP m_info; 221 }; 222 223 struct DisableExtraCompositing : public KisCommandUtils::AggregateCommand { DisableExtraCompositingKisLayerUtils::DisableExtraCompositing224 DisableExtraCompositing(MergeMultipleInfoSP info) : m_info(info) {} 225 populateChildCommandsKisLayerUtils::DisableExtraCompositing226 void populateChildCommands() override { 227 /** 228 * We disable extra compositing only in case all the layers have 229 * the same compositing properties, therefore, we can just sum them using 230 * Normal blend mode 231 */ 232 if (m_info->nodesCompositingVaries) return; 233 234 // we should disable dirty requests on **redo only**, otherwise 235 // the state of the layers will not be recovered on undo 236 m_info->image->disableDirtyRequests(); 237 238 Q_FOREACH (KisNodeSP node, m_info->allSrcNodes()) { 239 if (node->compositeOpId() != COMPOSITE_OVER) { 240 addCommand(new KisNodeCompositeOpCommand(node, node->compositeOpId(), COMPOSITE_OVER)); 241 } 242 243 if (KisLayerPropertiesIcons::nodeProperty(node, KisLayerPropertiesIcons::inheritAlpha, false).toBool()) { 244 245 KisBaseNode::PropertyList props = node->sectionModelProperties(); 246 KisLayerPropertiesIcons::setNodeProperty(&props, 247 KisLayerPropertiesIcons::inheritAlpha, 248 false); 249 250 addCommand(new KisNodePropertyListCommand(node, props)); 251 } 252 } 253 254 m_info->image->enableDirtyRequests(); 255 } 256 257 private: 258 MergeMultipleInfoSP m_info; 259 }; 260 261 struct DisablePassThroughForHeadsOnly : public KisCommandUtils::AggregateCommand { DisablePassThroughForHeadsOnlyKisLayerUtils::DisablePassThroughForHeadsOnly262 DisablePassThroughForHeadsOnly(MergeDownInfoBaseSP info, bool skipIfDstIsGroup = false) 263 : m_info(info), 264 m_skipIfDstIsGroup(skipIfDstIsGroup) 265 { 266 } 267 populateChildCommandsKisLayerUtils::DisablePassThroughForHeadsOnly268 void populateChildCommands() override { 269 if (m_skipIfDstIsGroup && 270 m_info->dstLayer() && 271 m_info->dstLayer()->inherits("KisGroupLayer")) { 272 273 return; 274 } 275 276 277 Q_FOREACH (KisNodeSP node, m_info->allSrcNodes()) { 278 if (KisLayerPropertiesIcons::nodeProperty(node, KisLayerPropertiesIcons::passThrough, false).toBool()) { 279 280 KisBaseNode::PropertyList props = node->sectionModelProperties(); 281 KisLayerPropertiesIcons::setNodeProperty(&props, 282 KisLayerPropertiesIcons::passThrough, 283 false); 284 285 addCommand(new KisNodePropertyListCommand(node, props)); 286 } 287 } 288 } 289 290 private: 291 MergeDownInfoBaseSP m_info; 292 bool m_skipIfDstIsGroup; 293 }; 294 295 struct RefreshHiddenAreas : public KUndo2Command { RefreshHiddenAreasKisLayerUtils::RefreshHiddenAreas296 RefreshHiddenAreas(MergeDownInfoBaseSP info) : m_info(info) {} 297 redoKisLayerUtils::RefreshHiddenAreas298 void redo() override { 299 KisImageAnimationInterface *interface = m_info->image->animationInterface(); 300 const QRect preparedRect = !interface->externalFrameActive() ? 301 m_info->image->bounds() : QRect(); 302 303 foreach (KisNodeSP node, m_info->allSrcNodes()) { 304 refreshHiddenAreaAsync(m_info->image, node, preparedRect); 305 } 306 } 307 308 private: 309 MergeDownInfoBaseSP m_info; 310 }; 311 312 struct RefreshDelayedUpdateLayers : public KUndo2Command { RefreshDelayedUpdateLayersKisLayerUtils::RefreshDelayedUpdateLayers313 RefreshDelayedUpdateLayers(MergeDownInfoBaseSP info) : m_info(info) {} 314 redoKisLayerUtils::RefreshDelayedUpdateLayers315 void redo() override { 316 foreach (KisNodeSP node, m_info->allSrcNodes()) { 317 forceAllDelayedNodesUpdate(node); 318 } 319 } 320 321 private: 322 MergeDownInfoBaseSP m_info; 323 }; 324 325 struct KeepMergedNodesSelected : public KisCommandUtils::AggregateCommand { KeepMergedNodesSelectedKisLayerUtils::KeepMergedNodesSelected326 KeepMergedNodesSelected(MergeDownInfoSP info, bool finalizing) 327 : m_singleInfo(info), 328 m_finalizing(finalizing) {} 329 KeepMergedNodesSelectedKisLayerUtils::KeepMergedNodesSelected330 KeepMergedNodesSelected(MergeMultipleInfoSP info, KisNodeSP putAfter, bool finalizing) 331 : m_multipleInfo(info), 332 m_finalizing(finalizing), 333 m_putAfter(putAfter) {} 334 populateChildCommandsKisLayerUtils::KeepMergedNodesSelected335 void populateChildCommands() override { 336 KisNodeSP prevNode; 337 KisNodeSP nextNode; 338 KisNodeList prevSelection; 339 KisNodeList nextSelection; 340 KisImageSP image; 341 342 if (m_singleInfo) { 343 prevNode = m_singleInfo->currLayer; 344 nextNode = m_singleInfo->dstNode; 345 image = m_singleInfo->image; 346 } else if (m_multipleInfo) { 347 prevNode = m_putAfter; 348 nextNode = m_multipleInfo->dstNode; 349 prevSelection = m_multipleInfo->allSrcNodes(); 350 image = m_multipleInfo->image; 351 } 352 353 if (!m_finalizing) { 354 addCommand(new KeepNodesSelectedCommand(prevSelection, KisNodeList(), 355 prevNode, KisNodeSP(), 356 image, false)); 357 } else { 358 addCommand(new KeepNodesSelectedCommand(KisNodeList(), nextSelection, 359 KisNodeSP(), nextNode, 360 image, true)); 361 } 362 } 363 364 private: 365 MergeDownInfoSP m_singleInfo; 366 MergeMultipleInfoSP m_multipleInfo; 367 bool m_finalizing; 368 KisNodeSP m_putAfter; 369 }; 370 371 struct CreateMergedLayer : public KisCommandUtils::AggregateCommand { CreateMergedLayerKisLayerUtils::CreateMergedLayer372 CreateMergedLayer(MergeDownInfoSP info) : m_info(info) {} 373 populateChildCommandsKisLayerUtils::CreateMergedLayer374 void populateChildCommands() override { 375 // actual merging done by KisLayer::createMergedLayer (or specialized descendant) 376 m_info->dstNode = m_info->currLayer->createMergedLayerTemplate(m_info->prevLayer); 377 378 if (m_info->frames.size() > 0) { 379 m_info->dstNode->enableAnimation(); 380 m_info->dstNode->getKeyframeChannel(KisKeyframeChannel::Content.id(), true); 381 } 382 383 m_info->dstNode->setUseInTimeline(m_info->useInTimeline); 384 m_info->dstNode->setColorLabelIndex(m_info->allSrcNodes().first()->colorLabelIndex()); 385 386 KisPaintLayer *dstPaintLayer = qobject_cast<KisPaintLayer*>(m_info->dstNode.data()); 387 if (dstPaintLayer) { 388 dstPaintLayer->setOnionSkinEnabled(m_info->enableOnionSkins); 389 } 390 } 391 392 private: 393 MergeDownInfoSP m_info; 394 }; 395 396 struct CreateMergedLayerMultiple : public KisCommandUtils::AggregateCommand { CreateMergedLayerMultipleKisLayerUtils::CreateMergedLayerMultiple397 CreateMergedLayerMultiple(MergeMultipleInfoSP info, const QString name = QString() ) 398 : m_info(info), 399 m_name(name) {} 400 populateChildCommandsKisLayerUtils::CreateMergedLayerMultiple401 void populateChildCommands() override { 402 QString mergedLayerName; 403 if (m_name.isEmpty()){ 404 const QString mergedLayerSuffix = i18n("Merged"); 405 mergedLayerName = m_info->mergedNodes.first()->name(); 406 407 if (!mergedLayerName.endsWith(mergedLayerSuffix)) { 408 mergedLayerName = QString("%1 %2") 409 .arg(mergedLayerName).arg(mergedLayerSuffix); 410 } 411 } else { 412 mergedLayerName = m_name; 413 } 414 415 KisPaintLayer *dstPaintLayer = new KisPaintLayer(m_info->image, mergedLayerName, OPACITY_OPAQUE_U8); 416 m_info->dstNode = dstPaintLayer; 417 418 if (m_info->frames.size() > 0) { 419 m_info->dstNode->enableAnimation(); 420 m_info->dstNode->getKeyframeChannel(KisKeyframeChannel::Content.id(), true); 421 } 422 423 424 auto channelFlagsLazy = [](KisNodeSP node) { 425 KisLayer *layer = dynamic_cast<KisLayer*>(node.data()); 426 return layer ? layer->channelFlags() : QBitArray(); 427 }; 428 429 QString compositeOpId; 430 QBitArray channelFlags; 431 bool compositionVaries = false; 432 bool isFirstCycle = true; 433 434 foreach (KisNodeSP node, m_info->allSrcNodes()) { 435 if (isFirstCycle) { 436 compositeOpId = node->compositeOpId(); 437 channelFlags = channelFlagsLazy(node); 438 isFirstCycle = false; 439 } else if (compositeOpId != node->compositeOpId() || 440 channelFlags != channelFlagsLazy(node)) { 441 compositionVaries = true; 442 break; 443 } 444 445 KisLayerSP layer = qobject_cast<KisLayer*>(node.data()); 446 if (layer && layer->layerStyle()) { 447 compositionVaries = true; 448 break; 449 } 450 } 451 452 if (!compositionVaries) { 453 if (!compositeOpId.isEmpty()) { 454 m_info->dstNode->setCompositeOpId(compositeOpId); 455 } 456 if (m_info->dstLayer() && !channelFlags.isEmpty()) { 457 m_info->dstLayer()->setChannelFlags(channelFlags); 458 } 459 } 460 461 m_info->nodesCompositingVaries = compositionVaries; 462 463 m_info->dstNode->setUseInTimeline(m_info->useInTimeline); 464 m_info->dstNode->setColorLabelIndex(m_info->allSrcNodes().first()->colorLabelIndex()); 465 466 dstPaintLayer->setOnionSkinEnabled(m_info->enableOnionSkins); 467 } 468 469 private: 470 MergeMultipleInfoSP m_info; 471 QString m_name; 472 }; 473 474 struct MergeLayers : public KisCommandUtils::AggregateCommand { MergeLayersKisLayerUtils::MergeLayers475 MergeLayers(MergeDownInfoSP info) : m_info(info) {} 476 populateChildCommandsKisLayerUtils::MergeLayers477 void populateChildCommands() override { 478 // actual merging done by KisLayer::createMergedLayer (or specialized descendant) 479 m_info->currLayer->fillMergedLayerTemplate(m_info->dstLayer(), m_info->prevLayer); 480 } 481 482 private: 483 MergeDownInfoSP m_info; 484 }; 485 486 struct MergeLayersMultiple : public KisCommandUtils::AggregateCommand { MergeLayersMultipleKisLayerUtils::MergeLayersMultiple487 MergeLayersMultiple(MergeMultipleInfoSP info) : m_info(info) {} 488 populateChildCommandsKisLayerUtils::MergeLayersMultiple489 void populateChildCommands() override { 490 KisPainter gc(m_info->dstNode->paintDevice()); 491 492 foreach (KisNodeSP node, m_info->allSrcNodes()) { 493 QRect rc = node->exactBounds() | m_info->image->bounds(); 494 node->projectionPlane()->apply(&gc, rc); 495 } 496 } 497 498 private: 499 MergeMultipleInfoSP m_info; 500 }; 501 502 struct MergeMetaData : public KUndo2Command { MergeMetaDataKisLayerUtils::MergeMetaData503 MergeMetaData(MergeDownInfoSP info, const KisMetaData::MergeStrategy* strategy) 504 : m_info(info), 505 m_strategy(strategy) {} 506 redoKisLayerUtils::MergeMetaData507 void redo() override { 508 QRect layerProjectionExtent = m_info->currLayer->projection()->extent(); 509 QRect prevLayerProjectionExtent = m_info->prevLayer->projection()->extent(); 510 int prevLayerArea = prevLayerProjectionExtent.width() * prevLayerProjectionExtent.height(); 511 int layerArea = layerProjectionExtent.width() * layerProjectionExtent.height(); 512 513 QList<double> scores; 514 double norm = qMax(prevLayerArea, layerArea); 515 scores.append(prevLayerArea / norm); 516 scores.append(layerArea / norm); 517 518 QList<const KisMetaData::Store*> srcs; 519 srcs.append(m_info->prevLayer->metaData()); 520 srcs.append(m_info->currLayer->metaData()); 521 m_strategy->merge(m_info->dstLayer()->metaData(), srcs, scores); 522 } 523 524 private: 525 MergeDownInfoSP m_info; 526 const KisMetaData::MergeStrategy *m_strategy; 527 }; 528 KeepNodesSelectedCommand(const KisNodeList & selectedBefore,const KisNodeList & selectedAfter,KisNodeSP activeBefore,KisNodeSP activeAfter,KisImageSP image,bool finalize,KUndo2Command * parent)529 KeepNodesSelectedCommand::KeepNodesSelectedCommand(const KisNodeList &selectedBefore, 530 const KisNodeList &selectedAfter, 531 KisNodeSP activeBefore, 532 KisNodeSP activeAfter, 533 KisImageSP image, 534 bool finalize, KUndo2Command *parent) 535 : FlipFlopCommand(finalize, parent), 536 m_selectedBefore(selectedBefore), 537 m_selectedAfter(selectedAfter), 538 m_activeBefore(activeBefore), 539 m_activeAfter(activeAfter), 540 m_image(image) 541 { 542 } 543 partB()544 void KeepNodesSelectedCommand::partB() { 545 KisImageSignalType type; 546 if (getState() == State::FINALIZING) { 547 type = ComplexNodeReselectionSignal(m_activeAfter, m_selectedAfter); 548 } else { 549 type = ComplexNodeReselectionSignal(m_activeBefore, m_selectedBefore); 550 } 551 m_image->signalRouter()->emitNotification(type); 552 } 553 SelectGlobalSelectionMask(KisImageSP image)554 SelectGlobalSelectionMask::SelectGlobalSelectionMask(KisImageSP image) 555 : m_image(image) 556 { 557 } 558 redo()559 void SelectGlobalSelectionMask::redo() { 560 561 KisImageSignalType type = 562 ComplexNodeReselectionSignal(m_image->rootLayer()->selectionMask(), KisNodeList()); 563 m_image->signalRouter()->emitNotification(type); 564 565 } 566 ~RemoveNodeHelper()567 RemoveNodeHelper::~RemoveNodeHelper() 568 { 569 } 570 571 /** 572 * The removal of two nodes in one go may be a bit tricky, because one 573 * of them may be the clone of another. If we remove the source of a 574 * clone layer, it will reincarnate into a paint layer. In this case 575 * the pointer to the second layer will be lost. 576 * 577 * That's why we need to care about the order of the nodes removal: 578 * the clone --- first, the source --- last. 579 */ safeRemoveMultipleNodes(KisNodeList nodes,KisImageSP image)580 void RemoveNodeHelper::safeRemoveMultipleNodes(KisNodeList nodes, KisImageSP image) { 581 const bool lastLayer = scanForLastLayer(image, nodes); 582 583 auto isNodeWeird = [] (KisNodeSP node) { 584 const bool normalCompositeMode = node->compositeOpId() == COMPOSITE_OVER; 585 586 KisLayer *layer = dynamic_cast<KisLayer*>(node.data()); 587 const bool hasInheritAlpha = layer && layer->alphaChannelDisabled(); 588 return !normalCompositeMode && !hasInheritAlpha; 589 }; 590 591 while (!nodes.isEmpty()) { 592 KisNodeList::iterator it = nodes.begin(); 593 594 while (it != nodes.end()) { 595 if (!checkIsSourceForClone(*it, nodes)) { 596 KisNodeSP node = *it; 597 598 addCommandImpl(new KisImageLayerRemoveCommand(image, node, !isNodeWeird(node), true)); 599 it = nodes.erase(it); 600 } else { 601 ++it; 602 } 603 } 604 } 605 606 if (lastLayer) { 607 KisLayerSP newLayer = new KisPaintLayer(image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8, image->colorSpace()); 608 addCommandImpl(new KisImageLayerAddCommand(image, newLayer, 609 image->root(), 610 KisNodeSP(), 611 false, false)); 612 } 613 } 614 checkIsSourceForClone(KisNodeSP src,const KisNodeList & nodes)615 bool RemoveNodeHelper::checkIsSourceForClone(KisNodeSP src, const KisNodeList &nodes) { 616 foreach (KisNodeSP node, nodes) { 617 if (node == src) continue; 618 619 KisCloneLayer *clone = dynamic_cast<KisCloneLayer*>(node.data()); 620 621 if (clone && KisNodeSP(clone->copyFrom()) == src) { 622 return true; 623 } 624 } 625 626 return false; 627 } 628 scanForLastLayer(KisImageWSP image,KisNodeList nodesToRemove)629 bool RemoveNodeHelper::scanForLastLayer(KisImageWSP image, KisNodeList nodesToRemove) { 630 bool removeLayers = false; 631 Q_FOREACH(KisNodeSP nodeToRemove, nodesToRemove) { 632 if (qobject_cast<KisLayer*>(nodeToRemove.data())) { 633 removeLayers = true; 634 break; 635 } 636 } 637 if (!removeLayers) return false; 638 639 bool lastLayer = true; 640 KisNodeSP node = image->root()->firstChild(); 641 while (node) { 642 if (!nodesToRemove.contains(node) && 643 qobject_cast<KisLayer*>(node.data()) && 644 !node->isFakeNode()) { 645 646 lastLayer = false; 647 break; 648 } 649 node = node->nextSibling(); 650 } 651 652 return lastLayer; 653 } 654 SimpleRemoveLayers(const KisNodeList & nodes,KisImageSP image)655 SimpleRemoveLayers::SimpleRemoveLayers(const KisNodeList &nodes, 656 KisImageSP image) 657 : m_nodes(nodes), 658 m_image(image) 659 { 660 } 661 populateChildCommands()662 void SimpleRemoveLayers::populateChildCommands() { 663 if (m_nodes.isEmpty()) return; 664 safeRemoveMultipleNodes(m_nodes, m_image); 665 } 666 addCommandImpl(KUndo2Command * cmd)667 void SimpleRemoveLayers::addCommandImpl(KUndo2Command *cmd) { 668 addCommand(cmd); 669 } 670 671 struct InsertNode : public KisCommandUtils::AggregateCommand { InsertNodeKisLayerUtils::InsertNode672 InsertNode(MergeDownInfoBaseSP info, KisNodeSP putAfter) 673 : m_info(info), m_putAfter(putAfter) {} 674 populateChildCommandsKisLayerUtils::InsertNode675 void populateChildCommands() override { 676 addCommand(new KisImageLayerAddCommand(m_info->image, 677 m_info->dstNode, 678 m_putAfter->parent(), 679 m_putAfter, 680 true, false)); 681 682 } 683 684 private: addCommandImplKisLayerUtils::InsertNode685 virtual void addCommandImpl(KUndo2Command *cmd) { 686 addCommand(cmd); 687 } 688 689 private: 690 MergeDownInfoBaseSP m_info; 691 KisNodeSP m_putAfter; 692 }; 693 694 splitNonRemovableNodes(KisNodeList & nodesToRemove,KisNodeList & _nodesToHide)695 void splitNonRemovableNodes(KisNodeList &nodesToRemove, KisNodeList &_nodesToHide) 696 { 697 QSet<KisNodeSP> nodesToHide; 698 QSet<KisNodeSP> extraNodesToRemove; 699 700 for (auto it = nodesToRemove.begin(); it != nodesToRemove.end(); ++it) { 701 KisNodeSP root = *it; 702 KIS_SAFE_ASSERT_RECOVER_NOOP(root->visible()); 703 704 if (!root->isEditable(false)) { 705 nodesToHide.insert(root); 706 } else { 707 bool rootNeedsCarefulRemoval = false; 708 709 recursiveApplyNodes(root, 710 [root, &nodesToHide, &rootNeedsCarefulRemoval] (KisNodeSP node) { 711 if (!node->isEditable(false)) { 712 while (node != root) { 713 nodesToHide.insert(node); 714 node = node->parent(); 715 KIS_SAFE_ASSERT_RECOVER_BREAK(node); 716 } 717 nodesToHide.insert(root); 718 rootNeedsCarefulRemoval = true; 719 } 720 }); 721 722 if (rootNeedsCarefulRemoval) { 723 recursiveApplyNodes(root, 724 [&extraNodesToRemove] (KisNodeSP node) { 725 extraNodesToRemove.insert(node); 726 }); 727 } 728 } 729 } 730 731 nodesToRemove += extraNodesToRemove.toList(); 732 733 KritaUtils::filterContainer<KisNodeList>(nodesToRemove, 734 [nodesToHide](KisNodeSP node) { 735 return !nodesToHide.contains(node); 736 }); 737 738 _nodesToHide = nodesToHide.toList(); 739 } 740 741 struct CleanUpNodes : private RemoveNodeHelper, public KisCommandUtils::AggregateCommand { CleanUpNodesKisLayerUtils::CleanUpNodes742 CleanUpNodes(MergeDownInfoBaseSP info, KisNodeSP putAfter) 743 : m_info(info), m_putAfter(putAfter) {} 744 findPerfectParentKisLayerUtils::CleanUpNodes745 static void findPerfectParent(KisNodeList nodesToDelete, KisNodeSP &putAfter, KisNodeSP &parent) { 746 if (!putAfter) { 747 putAfter = nodesToDelete.last(); 748 } 749 750 // Add the new merged node on top of the active node 751 // -- checking all parents if they are included in nodesToDelete 752 // Not every descendant is included in nodesToDelete even if in fact 753 // they are going to be deleted, so we need to check it. 754 // If we consider the path from root to the putAfter node, 755 // if there are any nodes marked for deletion, any node afterwards 756 // is going to be deleted, too. 757 // example: root . . . . . ! ! . . ! ! ! ! . . . . putAfter 758 // it should be: root . . . . . ! ! ! ! ! ! ! ! ! ! ! ! !putAfter 759 // and here: root . . . . X ! ! . . ! ! ! ! . . . . putAfter 760 // you can see which node is "the perfect ancestor" 761 // (marked X; called "parent" in the function arguments). 762 // and here: root . . . . . O ! . . ! ! ! ! . . . . putAfter 763 // you can see which node is "the topmost deleted ancestor" (marked 'O') 764 765 KisNodeSP node = putAfter->parent(); 766 bool foundDeletedAncestor = false; 767 KisNodeSP topmostAncestorToDelete = nullptr; 768 769 while (node) { 770 771 if (nodesToDelete.contains(node) 772 && !nodesToDelete.contains(node->parent())) { 773 foundDeletedAncestor = true; 774 topmostAncestorToDelete = node; 775 // Here node is to be deleted and its parent is not, 776 // so its parent is the one of the first not deleted (="perfect") ancestors. 777 // We need the one that is closest to the top (root) 778 } 779 780 node = node->parent(); 781 } 782 783 if (foundDeletedAncestor) { 784 parent = topmostAncestorToDelete->parent(); 785 putAfter = topmostAncestorToDelete; 786 } 787 else { 788 parent = putAfter->parent(); // putAfter (and none of its ancestors) is to be deleted, so its parent is the first not deleted ancestor 789 } 790 791 } 792 populateChildCommandsKisLayerUtils::CleanUpNodes793 void populateChildCommands() override { 794 KisNodeList nodesToDelete = m_info->allSrcNodes(); 795 796 KisNodeSP parent; 797 findPerfectParent(nodesToDelete, m_putAfter, parent); 798 799 if (!parent) { 800 KisNodeSP oldRoot = m_info->image->root(); 801 KisNodeSP newRoot(new KisGroupLayer(m_info->image, "root", OPACITY_OPAQUE_U8)); 802 803 // copy all fake nodes into the new image 804 KisLayerUtils::recursiveApplyNodes(oldRoot, [this, oldRoot, newRoot] (KisNodeSP node) { 805 if (node->isFakeNode() && node->parent() == oldRoot) { 806 addCommand(new KisImageLayerAddCommand(m_info->image, 807 node->clone(), 808 newRoot, 809 KisNodeSP(), 810 false, false)); 811 812 } 813 }); 814 815 addCommand(new KisImageLayerAddCommand(m_info->image, 816 m_info->dstNode, 817 newRoot, 818 KisNodeSP(), 819 true, false)); 820 addCommand(new KisImageChangeLayersCommand(m_info->image, oldRoot, newRoot)); 821 822 } 823 else { 824 addCommand(new KisImageLayerAddCommand(m_info->image, 825 m_info->dstNode, 826 parent, 827 m_putAfter, 828 true, false)); 829 830 831 /** 832 * We can merge selection masks, in this case dstLayer is not defined! 833 */ 834 if (m_info->dstLayer()) { 835 reparentSelectionMasks(m_info->image, 836 m_info->dstLayer(), 837 m_info->selectionMasks); 838 } 839 840 KisNodeList safeNodesToDelete = m_info->allSrcNodes(); 841 KisNodeList safeNodesToHide; 842 843 splitNonRemovableNodes(safeNodesToDelete, safeNodesToHide); 844 845 Q_FOREACH(KisNodeSP node, safeNodesToHide) { 846 addCommand(new KisImageChangeVisibilityCommand(false, node)); 847 } 848 849 safeRemoveMultipleNodes(safeNodesToDelete, m_info->image); 850 } 851 852 853 } 854 855 private: addCommandImplKisLayerUtils::CleanUpNodes856 void addCommandImpl(KUndo2Command *cmd) override { 857 addCommand(cmd); 858 } 859 reparentSelectionMasksKisLayerUtils::CleanUpNodes860 void reparentSelectionMasks(KisImageSP image, 861 KisLayerSP newLayer, 862 const QVector<KisSelectionMaskSP> &selectionMasks) { 863 864 KIS_SAFE_ASSERT_RECOVER_RETURN(newLayer); 865 866 foreach (KisSelectionMaskSP mask, selectionMasks) { 867 addCommand(new KisImageLayerMoveCommand(image, mask, newLayer, newLayer->lastChild())); 868 addCommand(new KisActivateSelectionMaskCommand(mask, false)); 869 } 870 } 871 private: 872 MergeDownInfoBaseSP m_info; 873 KisNodeSP m_putAfter; 874 }; 875 ~SharedStorage()876 SwitchFrameCommand::SharedStorage::~SharedStorage() { 877 } 878 SwitchFrameCommand(KisImageSP image,int time,bool finalize,SharedStorageSP storage)879 SwitchFrameCommand::SwitchFrameCommand(KisImageSP image, int time, bool finalize, SharedStorageSP storage) 880 : FlipFlopCommand(finalize), 881 m_image(image), 882 m_newTime(time), 883 m_storage(storage) {} 884 ~SwitchFrameCommand()885 SwitchFrameCommand::~SwitchFrameCommand() {} 886 partA()887 void SwitchFrameCommand::partA() { 888 KisImageAnimationInterface *interface = m_image->animationInterface(); 889 const int currentTime = interface->currentTime(); 890 if (currentTime == m_newTime) { 891 m_storage->value = m_newTime; 892 return; 893 } 894 895 interface->image()->disableUIUpdates(); 896 interface->saveAndResetCurrentTime(m_newTime, &m_storage->value); 897 } 898 partB()899 void SwitchFrameCommand::partB() { 900 KisImageAnimationInterface *interface = m_image->animationInterface(); 901 const int currentTime = interface->currentTime(); 902 if (currentTime == m_storage->value) { 903 return; 904 } 905 906 interface->restoreCurrentTime(&m_storage->value); 907 interface->image()->enableUIUpdates(); 908 } 909 910 struct AddNewFrame : public KisCommandUtils::AggregateCommand { AddNewFrameKisLayerUtils::AddNewFrame911 AddNewFrame(MergeDownInfoBaseSP info, int frame) : m_info(info), m_frame(frame) {} 912 populateChildCommandsKisLayerUtils::AddNewFrame913 void populateChildCommands() override { 914 KUndo2Command *cmd = new KisCommandUtils::SkipFirstRedoWrapper(); 915 KisKeyframeChannel *channel = m_info->dstNode->getKeyframeChannel(KisKeyframeChannel::Content.id()); 916 KisKeyframeSP keyframe = channel->addKeyframe(m_frame, cmd); 917 918 applyKeyframeColorLabel(keyframe); 919 920 addCommand(cmd); 921 } 922 applyKeyframeColorLabelKisLayerUtils::AddNewFrame923 void applyKeyframeColorLabel(KisKeyframeSP dstKeyframe) { 924 Q_FOREACH(KisNodeSP srcNode, m_info->allSrcNodes()) { 925 Q_FOREACH(KisKeyframeChannel *channel, srcNode->keyframeChannels().values()) { 926 KisKeyframeSP keyframe = channel->keyframeAt(m_frame); 927 if (!keyframe.isNull() && keyframe->colorLabel() != 0) { 928 dstKeyframe->setColorLabel(keyframe->colorLabel()); 929 return; 930 } 931 } 932 } 933 934 dstKeyframe->setColorLabel(0); 935 } 936 937 private: 938 MergeDownInfoBaseSP m_info; 939 int m_frame; 940 }; 941 fetchLayerFrames(KisNodeSP node)942 QSet<int> fetchLayerFrames(KisNodeSP node) { 943 KisKeyframeChannel *channel = node->getKeyframeChannel(KisKeyframeChannel::Content.id()); 944 if (!channel) return QSet<int>(); 945 946 return channel->allKeyframeIds(); 947 } 948 fetchLayerFramesRecursive(KisNodeSP rootNode)949 QSet<int> fetchLayerFramesRecursive(KisNodeSP rootNode) { 950 if (!rootNode->visible()) return QSet<int>(); 951 952 QSet<int> frames = fetchLayerFrames(rootNode); 953 954 KisNodeSP node = rootNode->firstChild(); 955 while(node) { 956 frames |= fetchLayerFramesRecursive(node); 957 node = node->nextSibling(); 958 } 959 960 return frames; 961 } 962 updateFrameJobs(FrameJobs * jobs,KisNodeSP node)963 void updateFrameJobs(FrameJobs *jobs, KisNodeSP node) { 964 QSet<int> frames = fetchLayerFrames(node); 965 966 if (frames.isEmpty()) { 967 (*jobs)[0].insert(node); 968 } else { 969 foreach (int frame, frames) { 970 (*jobs)[frame].insert(node); 971 } 972 } 973 } 974 updateFrameJobsRecursive(FrameJobs * jobs,KisNodeSP rootNode)975 void updateFrameJobsRecursive(FrameJobs *jobs, KisNodeSP rootNode) { 976 updateFrameJobs(jobs, rootNode); 977 978 KisNodeSP node = rootNode->firstChild(); 979 while(node) { 980 updateFrameJobsRecursive(jobs, node); 981 node = node->nextSibling(); 982 } 983 } 984 985 /** 986 * \see a comment in mergeMultipleLayersImpl() 987 */ mergeDown(KisImageSP image,KisLayerSP layer,const KisMetaData::MergeStrategy * strategy)988 void mergeDown(KisImageSP image, KisLayerSP layer, const KisMetaData::MergeStrategy* strategy) 989 { 990 if (!layer->prevSibling()) return; 991 992 // XXX: this breaks if we allow free mixing of masks and layers 993 KisLayerSP prevLayer = qobject_cast<KisLayer*>(layer->prevSibling().data()); 994 if (!prevLayer) return; 995 996 if (!layer->visible() && !prevLayer->visible()) { 997 return; 998 } 999 1000 KisImageSignalVector emitSignals; 1001 emitSignals << ModifiedSignal; 1002 1003 KisProcessingApplicator applicator(image, 0, 1004 KisProcessingApplicator::NONE, 1005 emitSignals, 1006 kundo2_i18n("Merge Down")); 1007 1008 if (layer->visible() && prevLayer->visible()) { 1009 MergeDownInfoSP info(new MergeDownInfo(image, prevLayer, layer)); 1010 1011 // disable key strokes on all colorize masks, all onion skins on 1012 // paint layers and wait until update is finished with a barrier 1013 applicator.applyCommand(new DisableColorizeKeyStrokes(info)); 1014 applicator.applyCommand(new DisableOnionSkins(info)); 1015 applicator.applyCommand(new KUndo2Command(), KisStrokeJobData::BARRIER); 1016 1017 applicator.applyCommand(new KeepMergedNodesSelected(info, false)); 1018 applicator.applyCommand(new FillSelectionMasks(info)); 1019 applicator.applyCommand(new CreateMergedLayer(info), KisStrokeJobData::BARRIER); 1020 1021 // NOTE: shape layer may have emitted spontaneous jobs during layer creation, 1022 // wait for them to complete! 1023 applicator.applyCommand(new RefreshDelayedUpdateLayers(info), KisStrokeJobData::BARRIER); 1024 applicator.applyCommand(new KUndo2Command(), KisStrokeJobData::BARRIER); 1025 1026 // in two-layer mode we disable pass through only when the destination layer 1027 // is not a group layer 1028 applicator.applyCommand(new DisablePassThroughForHeadsOnly(info, true)); 1029 applicator.applyCommand(new KUndo2Command(), KisStrokeJobData::BARRIER); 1030 1031 if (info->frames.size() > 0) { 1032 foreach (int frame, info->frames) { 1033 applicator.applyCommand(new SwitchFrameCommand(info->image, frame, false, info->storage)); 1034 1035 applicator.applyCommand(new AddNewFrame(info, frame)); 1036 applicator.applyCommand(new RefreshHiddenAreas(info)); 1037 applicator.applyCommand(new RefreshDelayedUpdateLayers(info), KisStrokeJobData::BARRIER); 1038 applicator.applyCommand(new MergeLayers(info), KisStrokeJobData::BARRIER); 1039 1040 applicator.applyCommand(new SwitchFrameCommand(info->image, frame, true, info->storage)); 1041 } 1042 } else { 1043 applicator.applyCommand(new RefreshHiddenAreas(info)); 1044 applicator.applyCommand(new RefreshDelayedUpdateLayers(info), KisStrokeJobData::BARRIER); 1045 applicator.applyCommand(new MergeLayers(info), KisStrokeJobData::BARRIER); 1046 } 1047 1048 applicator.applyCommand(new MergeMetaData(info, strategy), KisStrokeJobData::BARRIER); 1049 applicator.applyCommand(new CleanUpNodes(info, layer), 1050 KisStrokeJobData::SEQUENTIAL, 1051 KisStrokeJobData::EXCLUSIVE); 1052 applicator.applyCommand(new KeepMergedNodesSelected(info, true)); 1053 } else if (layer->visible()) { 1054 applicator.applyCommand(new KeepNodesSelectedCommand(KisNodeList(), KisNodeList(), 1055 layer, KisNodeSP(), 1056 image, false)); 1057 1058 applicator.applyCommand( 1059 new SimpleRemoveLayers(KisNodeList() << prevLayer, 1060 image), 1061 KisStrokeJobData::SEQUENTIAL, 1062 KisStrokeJobData::EXCLUSIVE); 1063 1064 applicator.applyCommand(new KeepNodesSelectedCommand(KisNodeList(), KisNodeList(), 1065 KisNodeSP(), layer, 1066 image, true)); 1067 } else if (prevLayer->visible()) { 1068 applicator.applyCommand(new KeepNodesSelectedCommand(KisNodeList(), KisNodeList(), 1069 layer, KisNodeSP(), 1070 image, false)); 1071 1072 applicator.applyCommand( 1073 new SimpleRemoveLayers(KisNodeList() << layer, 1074 image), 1075 KisStrokeJobData::SEQUENTIAL, 1076 KisStrokeJobData::EXCLUSIVE); 1077 1078 applicator.applyCommand(new KeepNodesSelectedCommand(KisNodeList(), KisNodeList(), 1079 KisNodeSP(), prevLayer, 1080 image, true)); 1081 } 1082 1083 applicator.end(); 1084 } 1085 checkIsChildOf(KisNodeSP node,const KisNodeList & parents)1086 bool checkIsChildOf(KisNodeSP node, const KisNodeList &parents) 1087 { 1088 KisNodeList nodeParents; 1089 1090 KisNodeSP parent = node->parent(); 1091 while (parent) { 1092 nodeParents << parent; 1093 parent = parent->parent(); 1094 } 1095 1096 foreach(KisNodeSP perspectiveParent, parents) { 1097 if (nodeParents.contains(perspectiveParent)) { 1098 return true; 1099 } 1100 } 1101 1102 return false; 1103 } 1104 checkIsCloneOf(KisNodeSP node,const KisNodeList & nodes)1105 bool checkIsCloneOf(KisNodeSP node, const KisNodeList &nodes) 1106 { 1107 bool result = false; 1108 1109 KisCloneLayer *clone = dynamic_cast<KisCloneLayer*>(node.data()); 1110 if (clone) { 1111 KisNodeSP cloneSource = KisNodeSP(clone->copyFrom()); 1112 1113 Q_FOREACH(KisNodeSP subtree, nodes) { 1114 result = 1115 recursiveFindNode(subtree, 1116 [cloneSource](KisNodeSP node) -> bool 1117 { 1118 return node == cloneSource; 1119 }); 1120 1121 if (!result) { 1122 result = checkIsCloneOf(cloneSource, nodes); 1123 } 1124 1125 if (result) { 1126 break; 1127 } 1128 } 1129 } 1130 1131 return result; 1132 } 1133 filterMergableNodes(KisNodeList & nodes,bool allowMasks)1134 void filterMergableNodes(KisNodeList &nodes, bool allowMasks) 1135 { 1136 KisNodeList::iterator it = nodes.begin(); 1137 1138 while (it != nodes.end()) { 1139 if ((!allowMasks && !qobject_cast<KisLayer*>(it->data())) || 1140 checkIsChildOf(*it, nodes)) { 1141 //qDebug() << "Skipping node" << ppVar((*it)->name()); 1142 it = nodes.erase(it); 1143 } else { 1144 ++it; 1145 } 1146 } 1147 } 1148 sortMergableNodes(KisNodeSP root,KisNodeList & inputNodes,KisNodeList & outputNodes)1149 void sortMergableNodes(KisNodeSP root, KisNodeList &inputNodes, KisNodeList &outputNodes) 1150 { 1151 KisNodeList::iterator it = std::find(inputNodes.begin(), inputNodes.end(), root); 1152 1153 if (it != inputNodes.end()) { 1154 outputNodes << *it; 1155 inputNodes.erase(it); 1156 } 1157 1158 if (inputNodes.isEmpty()) { 1159 return; 1160 } 1161 1162 KisNodeSP child = root->firstChild(); 1163 while (child) { 1164 sortMergableNodes(child, inputNodes, outputNodes); 1165 child = child->nextSibling(); 1166 } 1167 1168 /** 1169 * By the end of recursion \p inputNodes must be empty 1170 */ 1171 KIS_ASSERT_RECOVER_NOOP(root->parent() || inputNodes.isEmpty()); 1172 } 1173 sortMergableNodes(KisNodeSP root,KisNodeList nodes)1174 KisNodeList sortMergableNodes(KisNodeSP root, KisNodeList nodes) 1175 { 1176 KisNodeList result; 1177 sortMergableNodes(root, nodes, result); 1178 return result; 1179 } 1180 sortAndFilterMergableInternalNodes(KisNodeList nodes,bool allowMasks)1181 KisNodeList sortAndFilterMergableInternalNodes(KisNodeList nodes, bool allowMasks) 1182 { 1183 KIS_ASSERT_RECOVER(!nodes.isEmpty()) { return nodes; } 1184 1185 KisNodeSP root; 1186 Q_FOREACH(KisNodeSP node, nodes) { 1187 KisNodeSP localRoot = node; 1188 while (localRoot->parent()) { 1189 localRoot = localRoot->parent(); 1190 } 1191 1192 if (!root) { 1193 root = localRoot; 1194 } 1195 KIS_ASSERT_RECOVER(root == localRoot) { return nodes; } 1196 } 1197 1198 KisNodeList result; 1199 sortMergableNodes(root, nodes, result); 1200 filterMergableNodes(result, allowMasks); 1201 return result; 1202 } 1203 sortAndFilterAnyMergableNodesSafe(const KisNodeList & nodes,KisImageSP image)1204 KisNodeList sortAndFilterAnyMergableNodesSafe(const KisNodeList &nodes, KisImageSP image) { 1205 KisNodeList filteredNodes = nodes; 1206 KisNodeList sortedNodes; 1207 1208 KisLayerUtils::filterMergableNodes(filteredNodes, true); 1209 1210 bool haveExternalNodes = false; 1211 Q_FOREACH (KisNodeSP node, nodes) { 1212 if (node->graphListener() != image->root()->graphListener()) { 1213 haveExternalNodes = true; 1214 break; 1215 } 1216 } 1217 1218 if (!haveExternalNodes) { 1219 KisLayerUtils::sortMergableNodes(image->root(), filteredNodes, sortedNodes); 1220 } else { 1221 sortedNodes = filteredNodes; 1222 } 1223 1224 return sortedNodes; 1225 } 1226 1227 addCopyOfNameTag(KisNodeSP node)1228 void addCopyOfNameTag(KisNodeSP node) 1229 { 1230 const QString prefix = i18n("Copy of"); 1231 QString newName = node->name(); 1232 if (!newName.startsWith(prefix)) { 1233 newName = QString("%1 %2").arg(prefix).arg(newName); 1234 node->setName(newName); 1235 } 1236 } 1237 findNodesWithProps(KisNodeSP root,const KoProperties & props,bool excludeRoot)1238 KisNodeList findNodesWithProps(KisNodeSP root, const KoProperties &props, bool excludeRoot) 1239 { 1240 KisNodeList nodes; 1241 1242 if ((!excludeRoot || root->parent()) && root->check(props)) { 1243 nodes << root; 1244 } 1245 1246 KisNodeSP node = root->firstChild(); 1247 while (node) { 1248 nodes += findNodesWithProps(node, props, excludeRoot); 1249 node = node->nextSibling(); 1250 } 1251 1252 return nodes; 1253 } 1254 filterInvisibleNodes(const KisNodeList & nodes,KisNodeList * invisibleNodes,KisNodeSP * putAfter)1255 KisNodeList filterInvisibleNodes(const KisNodeList &nodes, KisNodeList *invisibleNodes, KisNodeSP *putAfter) 1256 { 1257 KIS_ASSERT_RECOVER(invisibleNodes) { return nodes; } 1258 KIS_ASSERT_RECOVER(putAfter) { return nodes; } 1259 1260 KisNodeList visibleNodes; 1261 int putAfterIndex = -1; 1262 1263 Q_FOREACH(KisNodeSP node, nodes) { 1264 if (node->visible() || node->userLocked()) { 1265 visibleNodes << node; 1266 } else { 1267 *invisibleNodes << node; 1268 1269 if (node == *putAfter) { 1270 putAfterIndex = visibleNodes.size() - 1; 1271 } 1272 } 1273 } 1274 1275 if (!visibleNodes.isEmpty() && putAfterIndex >= 0) { 1276 putAfterIndex = qBound(0, putAfterIndex, visibleNodes.size() - 1); 1277 *putAfter = visibleNodes[putAfterIndex]; 1278 } 1279 1280 return visibleNodes; 1281 } 1282 filterUnlockedNodes(KisNodeList & nodes)1283 void filterUnlockedNodes(KisNodeList &nodes) 1284 { 1285 KisNodeList::iterator it = nodes.begin(); 1286 1287 while (it != nodes.end()) { 1288 if ((*it)->userLocked()) { 1289 it = nodes.erase(it); 1290 } else { 1291 ++it; 1292 } 1293 } 1294 } 1295 changeImageDefaultProjectionColor(KisImageSP image,const KoColor & color)1296 void changeImageDefaultProjectionColor(KisImageSP image, const KoColor &color) 1297 { 1298 KisImageSignalVector emitSignals; 1299 emitSignals << ModifiedSignal; 1300 1301 KisProcessingApplicator applicator(image, 1302 image->root(), 1303 KisProcessingApplicator::RECURSIVE, 1304 emitSignals, 1305 kundo2_i18n("Change projection color"), 1306 0, 1307 142857 + 1); 1308 applicator.applyCommand(new KisChangeProjectionColorCommand(image, color), KisStrokeJobData::BARRIER, KisStrokeJobData::EXCLUSIVE); 1309 applicator.end(); 1310 } 1311 1312 /** 1313 * There might be two approaches for merging multiple layers: 1314 * 1315 * 1) Consider the selected nodes as a distinct "group" and merge them 1316 * as if they were isolated from the rest of the image. The key point 1317 * of this approach is that the look of the image will change, when 1318 * merging "weird" layers, like adjustment layers or layers with 1319 * non-normal blending mode. 1320 * 1321 * 2) Merge layers in a way to keep the look of the image as unchanged as 1322 * possible. With this approach one uses a few heuristics: 1323 * 1324 * * when merging multiple layers with non-normal (but equal) blending 1325 * mode, first merge these layers together using Normal blending mode, 1326 * then set blending mode of the result to the original blending mode 1327 * 1328 * * when merging multiple layers with different blending modes or 1329 * layer styles, they are first rasterized, and then laid over each 1330 * other with their own composite op. The blending mode of the final 1331 * layer is set to Normal, so the user could clearly see that he should 1332 * choose the correct blending mode. 1333 * 1334 * Krita uses the second approach: after merge operation, the image should look 1335 * as if nothing has happened (if it is technically possible). 1336 */ mergeMultipleLayersImpl(KisImageSP image,KisNodeList mergedNodes,KisNodeSP putAfter,bool flattenSingleLayer,const KUndo2MagicString & actionName,bool cleanupNodes=true,const QString layerName=QString ())1337 void mergeMultipleLayersImpl(KisImageSP image, KisNodeList mergedNodes, KisNodeSP putAfter, 1338 bool flattenSingleLayer, const KUndo2MagicString &actionName, 1339 bool cleanupNodes = true, const QString layerName = QString()) 1340 { 1341 if (!putAfter) { 1342 putAfter = mergedNodes.first(); 1343 } 1344 1345 filterMergableNodes(mergedNodes); 1346 { 1347 KisNodeList tempNodes; 1348 std::swap(mergedNodes, tempNodes); 1349 sortMergableNodes(image->root(), tempNodes, mergedNodes); 1350 } 1351 1352 if (mergedNodes.size() <= 1 && 1353 (!flattenSingleLayer && mergedNodes.size() == 1)) return; 1354 1355 KisImageSignalVector emitSignals; 1356 emitSignals << ModifiedSignal; 1357 emitSignals << ComplexNodeReselectionSignal(KisNodeSP(), KisNodeList(), KisNodeSP(), mergedNodes); 1358 1359 1360 1361 KisNodeList originalNodes = mergedNodes; 1362 KisNodeList invisibleNodes; 1363 mergedNodes = filterInvisibleNodes(originalNodes, &invisibleNodes, &putAfter); 1364 1365 if (mergedNodes.isEmpty()) return; 1366 1367 1368 // make sure we don't add the new layer into a locked group 1369 KIS_SAFE_ASSERT_RECOVER_RETURN(putAfter->parent()); 1370 while (putAfter->parent() && !putAfter->parent()->isEditable()) { 1371 putAfter = putAfter->parent(); 1372 } 1373 1374 /** 1375 * We have reached the root of the layer hierarchy and didn't manage 1376 * to find a node that was editable enough for putting our merged 1377 * result into it. That whouldn't happen in normal circumstances, 1378 * unless the user chose to make the root layer visible and lock 1379 * it manually. 1380 */ 1381 if (!putAfter->parent()) { 1382 return; 1383 } 1384 1385 KisProcessingApplicator applicator(image, 0, 1386 KisProcessingApplicator::NONE, 1387 emitSignals, 1388 actionName); 1389 1390 1391 if (!invisibleNodes.isEmpty() && cleanupNodes) { 1392 1393 /* If the putAfter node is invisible, 1394 * we should instead pick one of the nodes 1395 * to be merged to avoid a null putAfter 1396 * after we remove all invisible layers from 1397 * the image. 1398 * (The assumption is that putAfter is among 1399 * the layers to merge, so if it's invisible, 1400 * it's going to be removed) 1401 */ 1402 if (!putAfter->visible()){ 1403 putAfter = mergedNodes.first(); 1404 } 1405 1406 applicator.applyCommand( 1407 new SimpleRemoveLayers(invisibleNodes, 1408 image), 1409 KisStrokeJobData::SEQUENTIAL, 1410 KisStrokeJobData::EXCLUSIVE); 1411 } 1412 1413 if (mergedNodes.size() > 1 || invisibleNodes.isEmpty()) { 1414 MergeMultipleInfoSP info(new MergeMultipleInfo(image, mergedNodes)); 1415 1416 // disable key strokes on all colorize masks, all onion skins on 1417 // paint layers and wait until update is finished with a barrier 1418 applicator.applyCommand(new DisableColorizeKeyStrokes(info)); 1419 applicator.applyCommand(new DisableOnionSkins(info)); 1420 applicator.applyCommand(new DisablePassThroughForHeadsOnly(info)); 1421 applicator.applyCommand(new KUndo2Command(), KisStrokeJobData::BARRIER); 1422 1423 applicator.applyCommand(new KeepMergedNodesSelected(info, putAfter, false)); 1424 applicator.applyCommand(new FillSelectionMasks(info)); 1425 applicator.applyCommand(new CreateMergedLayerMultiple(info, layerName), KisStrokeJobData::BARRIER); 1426 applicator.applyCommand(new DisableExtraCompositing(info)); 1427 applicator.applyCommand(new KUndo2Command(), KisStrokeJobData::BARRIER); 1428 1429 if (!info->frames.isEmpty()) { 1430 foreach (int frame, info->frames) { 1431 applicator.applyCommand(new SwitchFrameCommand(info->image, frame, false, info->storage)); 1432 1433 applicator.applyCommand(new AddNewFrame(info, frame)); 1434 applicator.applyCommand(new RefreshHiddenAreas(info)); 1435 applicator.applyCommand(new RefreshDelayedUpdateLayers(info), KisStrokeJobData::BARRIER); 1436 applicator.applyCommand(new MergeLayersMultiple(info), KisStrokeJobData::BARRIER); 1437 1438 applicator.applyCommand(new SwitchFrameCommand(info->image, frame, true, info->storage)); 1439 } 1440 } else { 1441 applicator.applyCommand(new RefreshHiddenAreas(info)); 1442 applicator.applyCommand(new RefreshDelayedUpdateLayers(info), KisStrokeJobData::BARRIER); 1443 applicator.applyCommand(new MergeLayersMultiple(info), KisStrokeJobData::BARRIER); 1444 } 1445 1446 //applicator.applyCommand(new MergeMetaData(info, strategy), KisStrokeJobData::BARRIER); 1447 if (cleanupNodes){ 1448 applicator.applyCommand(new CleanUpNodes(info, putAfter), 1449 KisStrokeJobData::SEQUENTIAL, 1450 KisStrokeJobData::EXCLUSIVE); 1451 } else { 1452 applicator.applyCommand(new InsertNode(info, putAfter), 1453 KisStrokeJobData::SEQUENTIAL, 1454 KisStrokeJobData::EXCLUSIVE); 1455 } 1456 1457 applicator.applyCommand(new KeepMergedNodesSelected(info, putAfter, true)); 1458 } 1459 1460 applicator.end(); 1461 1462 } 1463 mergeMultipleLayers(KisImageSP image,KisNodeList mergedNodes,KisNodeSP putAfter)1464 void mergeMultipleLayers(KisImageSP image, KisNodeList mergedNodes, KisNodeSP putAfter) 1465 { 1466 mergeMultipleLayersImpl(image, mergedNodes, putAfter, false, kundo2_i18n("Merge Selected Nodes")); 1467 } 1468 newLayerFromVisible(KisImageSP image,KisNodeSP putAfter)1469 void newLayerFromVisible(KisImageSP image, KisNodeSP putAfter) 1470 { 1471 KisNodeList mergedNodes; 1472 mergedNodes << image->root(); 1473 1474 mergeMultipleLayersImpl(image, mergedNodes, putAfter, true, kundo2_i18n("New From Visible"), false, i18nc("New layer created from all the visible layers", "Visible")); 1475 } 1476 1477 struct MergeSelectionMasks : public KisCommandUtils::AggregateCommand { MergeSelectionMasksKisLayerUtils::MergeSelectionMasks1478 MergeSelectionMasks(MergeDownInfoBaseSP info, KisNodeSP putAfter) 1479 : m_info(info), 1480 m_putAfter(putAfter){} 1481 populateChildCommandsKisLayerUtils::MergeSelectionMasks1482 void populateChildCommands() override { 1483 KisNodeSP parent; 1484 CleanUpNodes::findPerfectParent(m_info->allSrcNodes(), m_putAfter, parent); 1485 1486 KisLayerSP parentLayer; 1487 do { 1488 parentLayer = qobject_cast<KisLayer*>(parent.data()); 1489 1490 parent = parent->parent(); 1491 } while(!parentLayer && parent); 1492 1493 KisSelectionSP selection = new KisSelection(); 1494 1495 foreach (KisNodeSP node, m_info->allSrcNodes()) { 1496 KisMaskSP mask = dynamic_cast<KisMask*>(node.data()); 1497 if (!mask) continue; 1498 1499 selection->pixelSelection()->applySelection( 1500 mask->selection()->pixelSelection(), SELECTION_ADD); 1501 } 1502 1503 KisSelectionMaskSP mergedMask = new KisSelectionMask(m_info->image, i18n("Selection Mask")); 1504 mergedMask->initSelection(parentLayer); 1505 mergedMask->setSelection(selection); 1506 1507 m_info->dstNode = mergedMask; 1508 } 1509 1510 private: 1511 MergeDownInfoBaseSP m_info; 1512 KisNodeSP m_putAfter; 1513 }; 1514 1515 struct ActivateSelectionMask : public KisCommandUtils::AggregateCommand { ActivateSelectionMaskKisLayerUtils::ActivateSelectionMask1516 ActivateSelectionMask(MergeDownInfoBaseSP info) 1517 : m_info(info) {} 1518 populateChildCommandsKisLayerUtils::ActivateSelectionMask1519 void populateChildCommands() override { 1520 KisSelectionMaskSP mergedMask = dynamic_cast<KisSelectionMask*>(m_info->dstNode.data()); 1521 addCommand(new KisActivateSelectionMaskCommand(mergedMask, true)); 1522 } 1523 1524 private: 1525 MergeDownInfoBaseSP m_info; 1526 }; 1527 tryMergeSelectionMasks(KisImageSP image,KisNodeList mergedNodes,KisNodeSP putAfter)1528 bool tryMergeSelectionMasks(KisImageSP image, KisNodeList mergedNodes, KisNodeSP putAfter) 1529 { 1530 QList<KisSelectionMaskSP> selectionMasks; 1531 1532 for (auto it = mergedNodes.begin(); it != mergedNodes.end(); /*noop*/) { 1533 KisSelectionMaskSP mask = dynamic_cast<KisSelectionMask*>(it->data()); 1534 if (!mask) { 1535 it = mergedNodes.erase(it); 1536 } else { 1537 selectionMasks.append(mask); 1538 ++it; 1539 } 1540 } 1541 1542 if (mergedNodes.isEmpty()) return false; 1543 1544 KisLayerSP parentLayer = qobject_cast<KisLayer*>(selectionMasks.first()->parent().data()); 1545 KIS_ASSERT_RECOVER(parentLayer) { return 0; } 1546 1547 KisImageSignalVector emitSignals; 1548 emitSignals << ModifiedSignal; 1549 1550 KisProcessingApplicator applicator(image, 0, 1551 KisProcessingApplicator::NONE, 1552 emitSignals, 1553 kundo2_i18n("Merge Selection Masks")); 1554 1555 MergeMultipleInfoSP info(new MergeMultipleInfo(image, mergedNodes)); 1556 1557 1558 applicator.applyCommand(new MergeSelectionMasks(info, putAfter)); 1559 applicator.applyCommand(new CleanUpNodes(info, putAfter), 1560 KisStrokeJobData::SEQUENTIAL, 1561 KisStrokeJobData::EXCLUSIVE); 1562 applicator.applyCommand(new ActivateSelectionMask(info)); 1563 applicator.end(); 1564 1565 return true; 1566 } 1567 flattenLayer(KisImageSP image,KisLayerSP layer)1568 void flattenLayer(KisImageSP image, KisLayerSP layer) 1569 { 1570 if (!layer->childCount() && !layer->layerStyle()) 1571 return; 1572 1573 KisNodeList mergedNodes; 1574 mergedNodes << layer; 1575 1576 mergeMultipleLayersImpl(image, mergedNodes, layer, true, kundo2_i18n("Flatten Layer")); 1577 } 1578 flattenImage(KisImageSP image,KisNodeSP activeNode)1579 void flattenImage(KisImageSP image, KisNodeSP activeNode) 1580 { 1581 if (!activeNode) { 1582 activeNode = image->root()->lastChild(); 1583 } 1584 1585 1586 KisNodeList mergedNodes; 1587 mergedNodes << image->root(); 1588 1589 mergeMultipleLayersImpl(image, mergedNodes, activeNode, true, kundo2_i18n("Flatten Image")); 1590 } 1591 KisSimpleUpdateCommand(KisNodeList nodes,bool finalize,KUndo2Command * parent)1592 KisSimpleUpdateCommand::KisSimpleUpdateCommand(KisNodeList nodes, bool finalize, KUndo2Command *parent) 1593 : FlipFlopCommand(finalize, parent), 1594 m_nodes(nodes) 1595 { 1596 } partB()1597 void KisSimpleUpdateCommand::partB() 1598 { 1599 updateNodes(m_nodes); 1600 } updateNodes(const KisNodeList & nodes)1601 void KisSimpleUpdateCommand::updateNodes(const KisNodeList &nodes) 1602 { 1603 Q_FOREACH(KisNodeSP node, nodes) { 1604 node->setDirty(node->extent()); 1605 } 1606 } 1607 recursiveFindNode(KisNodeSP node,std::function<bool (KisNodeSP)> func)1608 KisNodeSP recursiveFindNode(KisNodeSP node, std::function<bool(KisNodeSP)> func) 1609 { 1610 if (func(node)) { 1611 return node; 1612 } 1613 1614 node = node->firstChild(); 1615 while (node) { 1616 KisNodeSP resultNode = recursiveFindNode(node, func); 1617 if (resultNode) { 1618 return resultNode; 1619 } 1620 node = node->nextSibling(); 1621 } 1622 1623 return 0; 1624 } 1625 findNodeByUuid(KisNodeSP root,const QUuid & uuid)1626 KisNodeSP findNodeByUuid(KisNodeSP root, const QUuid &uuid) 1627 { 1628 return recursiveFindNode(root, 1629 [uuid] (KisNodeSP node) { 1630 return node->uuid() == uuid; 1631 }); 1632 } 1633 forceAllDelayedNodesUpdate(KisNodeSP root)1634 void forceAllDelayedNodesUpdate(KisNodeSP root) 1635 { 1636 KisLayerUtils::recursiveApplyNodes(root, 1637 [] (KisNodeSP node) { 1638 KisDelayedUpdateNodeInterface *delayedUpdate = 1639 dynamic_cast<KisDelayedUpdateNodeInterface*>(node.data()); 1640 if (delayedUpdate) { 1641 delayedUpdate->forceUpdateTimedNode(); 1642 } 1643 }); 1644 } 1645 hasDelayedNodeWithUpdates(KisNodeSP root)1646 bool hasDelayedNodeWithUpdates(KisNodeSP root) 1647 { 1648 return recursiveFindNode(root, 1649 [] (KisNodeSP node) { 1650 KisDelayedUpdateNodeInterface *delayedUpdate = 1651 dynamic_cast<KisDelayedUpdateNodeInterface*>(node.data()); 1652 1653 return delayedUpdate ? delayedUpdate->hasPendingTimedUpdates() : false; 1654 }); 1655 } 1656 forceAllHiddenOriginalsUpdate(KisNodeSP root)1657 void forceAllHiddenOriginalsUpdate(KisNodeSP root) 1658 { 1659 KisLayerUtils::recursiveApplyNodes(root, 1660 [] (KisNodeSP node) { 1661 KisCroppedOriginalLayerInterface *croppedUpdate = 1662 dynamic_cast<KisCroppedOriginalLayerInterface*>(node.data()); 1663 if (croppedUpdate) { 1664 croppedUpdate->forceUpdateHiddenAreaOnOriginal(); 1665 } 1666 }); 1667 } 1668 findImageByHierarchy(KisNodeSP node)1669 KisImageSP findImageByHierarchy(KisNodeSP node) 1670 { 1671 while (node) { 1672 const KisLayer *layer = dynamic_cast<const KisLayer*>(node.data()); 1673 if (layer) { 1674 return layer->image(); 1675 } 1676 1677 node = node->parent(); 1678 } 1679 1680 return 0; 1681 } 1682 1683 namespace Private { realNodeChangeRect(KisNodeSP rootNode,QRect currentRect=QRect ())1684 QRect realNodeChangeRect(KisNodeSP rootNode, QRect currentRect = QRect()) { 1685 KisNodeSP node = rootNode->firstChild(); 1686 1687 while(node) { 1688 currentRect |= realNodeChangeRect(node, currentRect); 1689 node = node->nextSibling(); 1690 } 1691 1692 if (!rootNode->isFakeNode()) { 1693 // TODO: it would be better to count up changeRect inside 1694 // node's extent() method 1695 currentRect |= rootNode->projectionPlane()->changeRect(rootNode->exactBounds()); 1696 } 1697 1698 return currentRect; 1699 } 1700 } 1701 refreshHiddenAreaAsync(KisImageSP image,KisNodeSP rootNode,const QRect & preparedArea)1702 void refreshHiddenAreaAsync(KisImageSP image, KisNodeSP rootNode, const QRect &preparedArea) { 1703 QRect realNodeRect = Private::realNodeChangeRect(rootNode); 1704 if (!preparedArea.contains(realNodeRect)) { 1705 1706 QRegion dirtyRegion = realNodeRect; 1707 dirtyRegion -= preparedArea; 1708 1709 auto rc = dirtyRegion.begin(); 1710 while (rc != dirtyRegion.end()) { 1711 image->refreshGraphAsync(rootNode, *rc, realNodeRect); 1712 rc++; 1713 } 1714 } 1715 } 1716 recursiveTightNodeVisibleBounds(KisNodeSP rootNode)1717 QRect recursiveTightNodeVisibleBounds(KisNodeSP rootNode) 1718 { 1719 QRect exactBounds; 1720 recursiveApplyNodes(rootNode, [&exactBounds] (KisNodeSP node) { 1721 exactBounds |= node->projectionPlane()->tightUserVisibleBounds(); 1722 }); 1723 return exactBounds; 1724 } 1725 findRoot(KisNodeSP node)1726 KisNodeSP findRoot(KisNodeSP node) 1727 { 1728 if (!node) return node; 1729 1730 while (node->parent()) { 1731 node = node->parent(); 1732 } 1733 return node; 1734 } 1735 canChangeImageProfileInvisibly(KisImageSP image)1736 bool canChangeImageProfileInvisibly(KisImageSP image) 1737 { 1738 int numLayers = 0; 1739 bool hasNonNormalLayers = false; 1740 bool hasTransparentLayer = false; 1741 1742 1743 recursiveApplyNodes(image->root(), 1744 [&numLayers, &hasNonNormalLayers, &hasTransparentLayer, image] (KisNodeSP node) { 1745 if (!node->inherits("KisLayer")) return; 1746 1747 numLayers++; 1748 1749 if (node->exactBounds().isEmpty()) return; 1750 1751 // this is only an approximation! it is not exact! 1752 if (!hasTransparentLayer && 1753 node->exactBounds() != image->bounds()) { 1754 1755 hasTransparentLayer = true; 1756 } 1757 1758 if (!hasNonNormalLayers && 1759 node->compositeOpId() != COMPOSITE_OVER) { 1760 1761 hasNonNormalLayers = true; 1762 } 1763 }); 1764 1765 return numLayers == 1 || (!hasNonNormalLayers && !hasTransparentLayer); 1766 } 1767 } 1768