1 /*
2  *  Copyright (c) 2014 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_recalculate_transform_mask_job.h"
20 
21 #include "kis_transform_mask.h"
22 #include "kis_debug.h"
23 #include "kis_layer.h"
24 #include "kis_image.h"
25 #include "kis_image_animation_interface.h"
26 #include "kis_abstract_projection_plane.h"
27 #include "kis_transform_mask_params_interface.h"
28 
KisRecalculateTransformMaskJob(KisTransformMaskSP mask)29 KisRecalculateTransformMaskJob::KisRecalculateTransformMaskJob(KisTransformMaskSP mask)
30     : m_mask(mask)
31 {
32     setExclusive(true);
33 }
34 
overrides(const KisSpontaneousJob * _otherJob)35 bool KisRecalculateTransformMaskJob::overrides(const KisSpontaneousJob *_otherJob)
36 {
37     const KisRecalculateTransformMaskJob *otherJob =
38         dynamic_cast<const KisRecalculateTransformMaskJob*>(_otherJob);
39 
40     return otherJob && otherJob->m_mask == m_mask;
41 }
42 
run()43 void KisRecalculateTransformMaskJob::run()
44 {
45     /**
46      * The mask might have been deleted from the layers stack. In
47      * such a case, don't try do update it.
48      */
49     if (!m_mask->parent()) return;
50     if (!m_mask->visible()) return;
51 
52     m_mask->recaclulateStaticImage();
53 
54     KisLayerSP layer = qobject_cast<KisLayer*>(m_mask->parent().data());
55 
56     if (!layer) {
57         warnKrita << "WARNING: KisRecalculateTransformMaskJob::run() Mask has no parent layer! Skipping projection update!";
58         return;
59     }
60 
61     KisImageSP image = layer->image();
62     Q_ASSERT(image);
63 
64     /**
65      * Depending on whether the mask is hidden we should either
66      * update it entirely via the setDirty() call, or we can use a
67      * lightweight approach by directly regenerating the
68      * precalculated static image using
69      * KisRecalculateTransformMaskJob.
70      */
71     if (m_mask->transformParams()->isHidden()) {
72         QRect updateRect = m_mask->extent();
73 
74         if (layer->original()) {
75             updateRect |= layer->original()->defaultBounds()->bounds();
76         }
77 
78         if (layer->isAnimated()) {
79             m_mask->setDirty(updateRect);
80         } else {
81             m_mask->setDirtyDontResetAnimationCache(updateRect);
82         }
83     } else {
84         /**
85          * When we call requestProjectionUpdateNoFilthy() on a layer,
86          * its masks' change rect is not counted, because it is considered
87          * to be N_ABOVE_FILTHY. Therefore, we should expand the dirty
88          * rect manually to get the correct update
89          */
90 
91         QRect updateRect = layer->projectionPlane()->changeRect(layer->extent(), KisLayer::N_FILTHY);
92         image->requestProjectionUpdateNoFilthy(layer, updateRect, image->bounds(),layer->isAnimated());
93     }
94 }
95 
levelOfDetail() const96 int KisRecalculateTransformMaskJob::levelOfDetail() const
97 {
98     return 0;
99 }
100 
debugName() const101 QString KisRecalculateTransformMaskJob::debugName() const
102 {
103     QString result;
104     QDebug dbg(&result);
105     dbg << "KisRecalculateTransformMaskJob" << m_mask;
106     return result;
107 }
108