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