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 }