File indexing completed on 2024-05-19 04:26:32
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_recalculate_transform_mask_job.h" 0008 0009 #include "kis_transform_mask.h" 0010 #include "kis_debug.h" 0011 #include "kis_layer.h" 0012 #include "kis_image.h" 0013 #include "kis_image_animation_interface.h" 0014 #include "kis_abstract_projection_plane.h" 0015 #include "kis_transform_mask_params_interface.h" 0016 0017 KisRecalculateTransformMaskJob::KisRecalculateTransformMaskJob(KisTransformMaskSP mask, const QRect &extraUpdateRect) 0018 : m_mask(mask) 0019 , m_extraUpdateRect(extraUpdateRect) 0020 { 0021 setExclusive(true); 0022 } 0023 0024 0025 bool KisRecalculateTransformMaskJob::overrides(const KisSpontaneousJob *_otherJob) 0026 { 0027 const KisRecalculateTransformMaskJob *otherJob = 0028 dynamic_cast<const KisRecalculateTransformMaskJob*>(_otherJob); 0029 0030 return otherJob && otherJob->m_mask == m_mask; 0031 } 0032 0033 void KisRecalculateTransformMaskJob::run() 0034 { 0035 /** 0036 * The mask might have been deleted from the layers stack. In 0037 * such a case, don't try do update it. 0038 */ 0039 if (!m_mask->parent()) return; 0040 if (!m_mask->visible()) return; 0041 if (m_mask->staticImageCacheIsValid()) return; 0042 0043 const QRect oldMaskExtent = m_mask->extent(); 0044 m_mask->recalculateStaticImage(); 0045 0046 KisLayerSP layer = qobject_cast<KisLayer*>(m_mask->parent().data()); 0047 0048 if (!layer) { 0049 warnKrita << "WARNING: KisRecalculateTransformMaskJob::run() Mask has no parent layer! Skipping projection update!"; 0050 return; 0051 } 0052 0053 KisImageSP image = layer->image(); 0054 Q_ASSERT(image); 0055 0056 /** 0057 * Depending on whether the mask is hidden we should either 0058 * update it entirely via the setDirty() call, or we can use a 0059 * lightweight approach by directly regenerating the 0060 * precalculated static image using 0061 * KisRecalculateTransformMaskJob. 0062 */ 0063 if (m_mask->transformParams()->isHidden()) { 0064 QRect updateRect = m_mask->extent() | oldMaskExtent; 0065 0066 updateRect |= m_extraUpdateRect; 0067 0068 if (layer->original()) { 0069 updateRect |= layer->original()->defaultBounds()->bounds(); 0070 } 0071 0072 if (layer->isAnimated()) { 0073 m_mask->setDirty(updateRect); 0074 } else { 0075 m_mask->setDirtyDontResetAnimationCache(updateRect); 0076 } 0077 } else { 0078 /** 0079 * When we call requestProjectionUpdateNoFilthy() on a layer, 0080 * its masks' change rect is not counted, because it is considered 0081 * to be N_ABOVE_FILTHY. Therefore, we should expand the dirty 0082 * rect manually to get the correct update 0083 */ 0084 QRect updateRect = oldMaskExtent | 0085 layer->projectionPlane()->changeRect(layer->extent(), KisLayer::N_FILTHY); 0086 0087 updateRect |= m_extraUpdateRect; 0088 0089 image->requestProjectionUpdateNoFilthy(layer, updateRect, image->bounds(), false); // Should there be a case where this is flushed? 0090 } 0091 } 0092 0093 int KisRecalculateTransformMaskJob::levelOfDetail() const 0094 { 0095 return 0; 0096 } 0097 0098 QString KisRecalculateTransformMaskJob::debugName() const 0099 { 0100 QString result; 0101 QDebug dbg(&result); 0102 dbg << "KisRecalculateTransformMaskJob" << m_mask; 0103 return result; 0104 }