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