1 /*
2  *  Copyright (c) 2005 C. Boemann <cbo@boemann.dk>
3  *  Copyright (c) 2007 Boudewijn Rempt <boud@valdyas.org>
4  *  Copyright (c) 2009 Dmitry Kazakov <dimula73@gmail.com>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 #include "kis_group_layer.h"
22 
23 #include <KoIcon.h>
24 #include <kis_icon.h>
25 #include <KoCompositeOpRegistry.h>
26 #include <KoColorSpace.h>
27 #include <KoColor.h>
28 
29 
30 #include "kis_node_visitor.h"
31 #include "kis_processing_visitor.h"
32 #include "kis_debug.h"
33 #include "kis_image.h"
34 #include "kis_paint_device.h"
35 #include "kis_default_bounds.h"
36 #include "kis_clone_layer.h"
37 #include "kis_selection_mask.h"
38 #include "kis_psd_layer_style.h"
39 #include "kis_layer_properties_icons.h"
40 
41 
42 struct Q_DECL_HIDDEN KisGroupLayer::Private
43 {
44 public:
PrivateKisGroupLayer::Private45     Private()
46         : paintDevice(0)
47         , x(0)
48         , y(0)
49         , passThroughMode(false)
50     {
51     }
52 
53     KisPaintDeviceSP paintDevice;
54     qint32 x;
55     qint32 y;
56     bool passThroughMode;
57 };
58 
KisGroupLayer(KisImageWSP image,const QString & name,quint8 opacity)59 KisGroupLayer::KisGroupLayer(KisImageWSP image, const QString &name, quint8 opacity) :
60     KisLayer(image, name, opacity),
61     m_d(new Private())
62 {
63     resetCache();
64 }
65 
KisGroupLayer(const KisGroupLayer & rhs)66 KisGroupLayer::KisGroupLayer(const KisGroupLayer &rhs) :
67     KisLayer(rhs),
68     m_d(new Private())
69 {
70     m_d->paintDevice = new KisPaintDevice(*rhs.m_d->paintDevice.data());
71     m_d->x = rhs.m_d->x;
72     m_d->y = rhs.m_d->y;
73     m_d->paintDevice->setDefaultPixel(const_cast<KisGroupLayer*>(&rhs)->m_d->paintDevice->defaultPixel());
74     m_d->paintDevice->setProjectionDevice(true);
75     m_d->passThroughMode = rhs.passThroughMode();
76 }
77 
~KisGroupLayer()78 KisGroupLayer::~KisGroupLayer()
79 {
80     delete m_d;
81 }
82 
checkCloneLayer(KisCloneLayerSP clone) const83 bool KisGroupLayer::checkCloneLayer(KisCloneLayerSP clone) const
84 {
85     KisNodeSP source = clone->copyFrom();
86     if (source) {
87         if(!allowAsChild(source)) return false;
88 
89         if (source->inherits("KisGroupLayer")) {
90             KisNodeSP newParent = const_cast<KisGroupLayer*>(this);
91             while (newParent) {
92                 if (newParent == source) {
93                     return false;
94                 }
95                 newParent = newParent->parent();
96             }
97         }
98     }
99 
100     return true;
101 }
102 
checkNodeRecursively(KisNodeSP node) const103 bool KisGroupLayer::checkNodeRecursively(KisNodeSP node) const
104 {
105     KisCloneLayerSP cloneLayer = dynamic_cast<KisCloneLayer*>(node.data());
106     if(cloneLayer) {
107         return checkCloneLayer(cloneLayer);
108     }
109     else if (node->inherits("KisGroupLayer")) {
110         KisNodeSP child = node->firstChild();
111         while (child) {
112             if (!checkNodeRecursively(child)) {
113                 return false;
114             }
115             child = child->nextSibling();
116         }
117     }
118 
119     return true;
120 }
121 
allowAsChild(KisNodeSP node) const122 bool KisGroupLayer::allowAsChild(KisNodeSP node) const
123 {
124     if (!checkNodeRecursively(node)) return false;
125 
126     if (!parent()) {
127         // We are the root layer, so we need to check
128         // whether the node that's going to be added is
129         // a selection mask; that is only allowed if
130         // there isn't a global selection. See
131         // BUG:294905
132 
133         if (node->inherits("KisSelectionMask")) {
134             return !selectionMask();
135         }
136 
137         KisImageSP image = this->image();
138 
139         if (!image || !image->allowMasksOnRootNode()) {
140             if (node->inherits("KisMask")) {
141                 return false;
142             }
143         }
144     }
145 
146     return checkNodeRecursively(node);
147 
148 }
149 
colorSpace() const150 const KoColorSpace * KisGroupLayer::colorSpace() const
151 {
152     return m_d->paintDevice->colorSpace();
153 }
154 
icon() const155 QIcon KisGroupLayer::icon() const
156 {
157     return KisIconUtils::loadIcon("groupLayer");
158 }
159 
setImage(KisImageWSP image)160 void KisGroupLayer::setImage(KisImageWSP image)
161 {
162     m_d->paintDevice->setDefaultBounds(new KisDefaultBounds(image));
163     KisLayer::setImage(image);
164 }
165 
createMergedLayerTemplate(KisLayerSP prevLayer)166 KisLayerSP KisGroupLayer::createMergedLayerTemplate(KisLayerSP prevLayer)
167 {
168     KisGroupLayer *prevGroup = dynamic_cast<KisGroupLayer*>(prevLayer.data());
169 
170     if (prevGroup && canMergeAndKeepBlendOptions(prevLayer)) {
171         KisSharedPtr<KisGroupLayer> merged(new KisGroupLayer(*prevGroup));
172 
173         KisNodeSP child, cloned;
174 
175         for (child = firstChild(); child; child = child->nextSibling()) {
176             cloned = child->clone();
177             image()->addNode(cloned, merged);
178         }
179 
180         if (!merged->passThroughMode()) {
181             image()->refreshGraphAsync(merged);
182         }
183 
184         return merged;
185     } else
186         return KisLayer::createMergedLayerTemplate(prevLayer);
187 }
188 
fillMergedLayerTemplate(KisLayerSP dstLayer,KisLayerSP prevLayer)189 void KisGroupLayer::fillMergedLayerTemplate(KisLayerSP dstLayer, KisLayerSP prevLayer)
190 {
191     if (!dynamic_cast<KisGroupLayer*>(dstLayer.data())) {
192         KisLayer::fillMergedLayerTemplate(dstLayer, prevLayer);
193     }
194 }
195 
resetCache(const KoColorSpace * colorSpace)196 void KisGroupLayer::resetCache(const KoColorSpace *colorSpace)
197 {
198     if (!colorSpace)
199         colorSpace = image()->colorSpace();
200 
201     Q_ASSERT(colorSpace);
202 
203     if (!m_d->paintDevice) {
204 
205         KisPaintDeviceSP dev = new KisPaintDevice(this, colorSpace, new KisDefaultBounds(image()));
206         dev->setX(this->x());
207         dev->setY(this->y());
208         m_d->paintDevice = dev;
209         m_d->paintDevice->setProjectionDevice(true);
210     }
211     else if(*m_d->paintDevice->colorSpace() != *colorSpace) {
212 
213         m_d->paintDevice->clear();
214         m_d->paintDevice->convertTo(colorSpace);
215 
216     } else {
217 
218         m_d->paintDevice->clear();
219     }
220 }
221 
onlyMeaningfulChild() const222 KisLayer* KisGroupLayer::onlyMeaningfulChild() const
223 {
224     KisNode *child = firstChild().data();
225     KisLayer *onlyLayer = 0;
226 
227     while (child) {
228         KisLayer *layer = qobject_cast<KisLayer*>(child);
229         if (layer && !layer->isFakeNode()) {
230             if (onlyLayer) return 0;
231             onlyLayer = layer;
232         }
233         child = child->nextSibling().data();
234     }
235 
236     return onlyLayer;
237 }
238 
tryObligeChild() const239 KisPaintDeviceSP KisGroupLayer::tryObligeChild() const
240 {
241     const KisLayer *child = onlyMeaningfulChild();
242 
243     if (child &&
244         child->channelFlags().isEmpty() &&
245         child->projection() &&
246         child->visible() &&
247         (child->compositeOpId() == COMPOSITE_OVER ||
248          child->compositeOpId() == COMPOSITE_ALPHA_DARKEN ||
249          child->compositeOpId() == COMPOSITE_COPY) &&
250         child->opacity() == OPACITY_OPAQUE_U8 &&
251         *child->projection()->colorSpace() == *colorSpace() &&
252         !child->layerStyle()) {
253 
254         quint8 defaultOpacity =
255             m_d->paintDevice->defaultPixel().opacityU8();
256 
257         if(defaultOpacity == OPACITY_TRANSPARENT_U8) {
258             return child->projection();
259         }
260     }
261 
262     return 0;
263 }
264 
original() const265 KisPaintDeviceSP KisGroupLayer::original() const
266 {
267     /**
268      * We are too lazy! Let's our children work for us.
269      * Try to use children's paintDevice if it's the only
270      * one in stack and meets some conditions
271      */
272     KisPaintDeviceSP realOriginal = tryObligeChild();
273 
274     if (!realOriginal) {
275         if (!childCount() && !m_d->paintDevice->extent().isEmpty()) {
276             m_d->paintDevice->clear();
277         }
278         realOriginal = m_d->paintDevice;
279     }
280 
281     return realOriginal;
282 }
283 
paintDevice() const284 KisPaintDeviceSP KisGroupLayer::paintDevice() const
285 {
286     return 0;
287 }
288 
projectionIsValid() const289 bool KisGroupLayer::projectionIsValid() const
290 {
291     return !tryObligeChild();
292 }
293 
setDefaultProjectionColor(KoColor color)294 void KisGroupLayer::setDefaultProjectionColor(KoColor color)
295 {
296     m_d->paintDevice->setDefaultPixel(color);
297 }
298 
defaultProjectionColor() const299 KoColor KisGroupLayer::defaultProjectionColor() const
300 {
301     KoColor color(m_d->paintDevice->defaultPixel(), m_d->paintDevice->colorSpace());
302     return color;
303 }
304 
passThroughMode() const305 bool KisGroupLayer::passThroughMode() const
306 {
307     return m_d->passThroughMode;
308 }
309 
setPassThroughMode(bool value)310 void KisGroupLayer::setPassThroughMode(bool value)
311 {
312     if (m_d->passThroughMode == value) return;
313 
314     m_d->passThroughMode = value;
315 
316     baseNodeChangedCallback();
317     baseNodeInvalidateAllFramesCallback();
318 }
319 
sectionModelProperties() const320 KisBaseNode::PropertyList KisGroupLayer::sectionModelProperties() const
321 {
322     KisBaseNode::PropertyList l = KisLayer::sectionModelProperties();
323 
324     l << KisLayerPropertiesIcons::getProperty(KisLayerPropertiesIcons::passThrough, passThroughMode());
325 
326     return l;
327 }
328 
setSectionModelProperties(const KisBaseNode::PropertyList & properties)329 void KisGroupLayer::setSectionModelProperties(const KisBaseNode::PropertyList &properties)
330 {
331     Q_FOREACH (const KisBaseNode::Property &property, properties) {
332         if (property.name == i18n("Pass Through")) {
333             setPassThroughMode(property.state.toBool());
334         }
335     }
336 
337     KisLayer::setSectionModelProperties(properties);
338 }
339 
accept(KisNodeVisitor & v)340 bool KisGroupLayer::accept(KisNodeVisitor &v)
341 {
342     return v.visit(this);
343 }
344 
accept(KisProcessingVisitor & visitor,KisUndoAdapter * undoAdapter)345 void KisGroupLayer::accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter)
346 {
347     return visitor.visit(this, undoAdapter);
348 }
349 
x() const350 qint32 KisGroupLayer::x() const
351 {
352     return m_d->paintDevice ? m_d->paintDevice->x() : m_d->x;
353 }
354 
y() const355 qint32 KisGroupLayer::y() const
356 {
357     return m_d->paintDevice ? m_d->paintDevice->y() : m_d->y;
358 }
359 
setX(qint32 x)360 void KisGroupLayer::setX(qint32 x)
361 {
362     m_d->x = x;
363     if(m_d->paintDevice) {
364         m_d->paintDevice->setX(x);
365     }
366 }
367 
setY(qint32 y)368 void KisGroupLayer::setY(qint32 y)
369 {
370     m_d->y = y;
371     if(m_d->paintDevice) {
372         m_d->paintDevice->setY(y);
373     }
374 }
375 
376 struct ExtentPolicy
377 {
operator ()ExtentPolicy378     inline QRect operator() (const KisNode *node) {
379         return node->extent();
380     }
381 };
382 
383 struct ExactBoundsPolicy
384 {
operator ()ExactBoundsPolicy385     inline QRect operator() (const KisNode *node) {
386         return node->exactBounds();
387     }
388 };
389 
390 template <class MetricPolicy>
collectRects(const KisNode * node,MetricPolicy policy)391 QRect collectRects(const KisNode *node, MetricPolicy policy)
392 {
393     QRect accumulator;
394 
395     const KisNode *child = node->firstChild();
396     while (child) {
397         if (!qobject_cast<const KisMask*>(child)) {
398             accumulator |= policy(child);
399         }
400         child = child->nextSibling();
401     }
402 
403     return accumulator;
404 }
405 
extent() const406 QRect KisGroupLayer::extent() const
407 {
408     return m_d->passThroughMode ?
409         collectRects(this, ExtentPolicy()) :
410         KisLayer::extent();
411 }
412 
exactBounds() const413 QRect KisGroupLayer::exactBounds() const
414 {
415     return m_d->passThroughMode ?
416         collectRects(this, ExactBoundsPolicy()) :
417         KisLayer::exactBounds();
418 }
419