chalk

kis_image.cpp
1/*
2 * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
3 * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19#include <stdlib.h>
20#include <math.h>
21
22#include <config.h>
23#include LCMS_HEADER
24
25#include <tqimage.h>
26#include <tqpainter.h>
27#include <tqsize.h>
28#include <tqtl.h>
29#include <tqapplication.h>
30#include <tqthread.h>
31#include <tqdatetime.h>
32
33#include <kcommand.h>
34#include <kdebug.h>
35#include <tdelocale.h>
36
37#include "kis_image_iface.h"
38
39#include "kis_annotation.h"
40#include "kis_colorspace_factory_registry.h"
41#include "kis_color.h"
42#include "kis_command.h"
43#include "kis_types.h"
44//#include "kis_guide.h"
45#include "kis_image.h"
46#include "kis_paint_device.h"
47#include "kis_paint_device_action.h"
48#include "kis_selection.h"
49#include "kis_painter.h"
50#include "kis_fill_painter.h"
51#include "kis_layer.h"
52#include "kis_group_layer.h"
53#include "kis_adjustment_layer.h"
54#include "kis_paint_layer.h"
55#include "kis_colorspace_convert_visitor.h"
56#include "kis_background.h"
57#include "kis_substrate.h"
58#include "kis_scale_visitor.h"
59#include "kis_nameserver.h"
60#include "kis_undo_adapter.h"
61#include "kis_merge_visitor.h"
62#include "kis_transaction.h"
63#include "kis_crop_visitor.h"
64#include "kis_transform_visitor.h"
65#include "kis_filter_strategy.h"
66#include "kis_profile.h"
67#include "kis_paint_layer.h"
68#include "kis_perspective_grid.h"
69#include "kis_change_profile_visitor.h"
70#include "kis_group_layer.h"
71#include "kis_iterators_pixel.h"
72#include "kis_shear_visitor.h"
73
74class KisImage::KisImagePrivate {
75public:
76 KisColor backgroundColor;
77 TQ_UINT32 lockCount;
78 bool sizeChangedWhileLocked;
79 bool selectionChangedWhileLocked;
80 KisSubstrateSP substrate;
81 KisPerspectiveGrid* perspectiveGrid;
82};
83
84
85namespace {
86
87 class KisResizeImageCmd : public KNamedCommand {
88 typedef KNamedCommand super;
89
90 public:
91 KisResizeImageCmd(KisUndoAdapter *adapter,
92 KisImageSP img,
93 TQ_INT32 width,
94 TQ_INT32 height,
95 TQ_INT32 oldWidth,
96 TQ_INT32 oldHeight) : super(i18n("Resize Image"))
97 {
98 m_adapter = adapter;
99 m_img = img;
100 m_before = TQSize(oldWidth, oldHeight);
101 m_after = TQSize(width, height);
102 }
103
104 virtual ~KisResizeImageCmd()
105 {
106 }
107
108 public:
109 virtual void execute()
110 {
111 m_adapter->setUndo(false);
112 m_img->resize(m_after.width(), m_after.height());
113 m_adapter->setUndo(true);
114 }
115
116 virtual void unexecute()
117 {
118 m_adapter->setUndo(false);
119 m_img->resize(m_before.width(), m_before.height());
120 m_adapter->setUndo(true);
121 }
122
123 private:
124 KisUndoAdapter *m_adapter;
125 KisImageSP m_img;
126 TQSize m_before;
127 TQSize m_after;
128 };
129
130 // -------------------------------------------------------
131
132 class KisChangeLayersCmd : public KNamedCommand {
133 typedef KNamedCommand super;
134
135 public:
136 KisChangeLayersCmd(KisUndoAdapter *adapter, KisImageSP img,
137 KisGroupLayerSP oldRootLayer, KisGroupLayerSP newRootLayer, const TQString& name)
138 : super(name)
139 {
140 m_adapter = adapter;
141 m_img = img;
142 m_oldRootLayer = oldRootLayer;
143 m_newRootLayer = newRootLayer;
144 }
145
146 virtual ~KisChangeLayersCmd()
147 {
148 }
149
150 public:
151 virtual void execute()
152 {
153 m_adapter->setUndo(false);
154 m_img->setRootLayer(m_newRootLayer);
155 m_adapter->setUndo(true);
156 m_img->notifyLayersChanged();
157 }
158
159 virtual void unexecute()
160 {
161 m_adapter->setUndo(false);
162 m_img->setRootLayer(m_oldRootLayer);
163 m_adapter->setUndo(true);
164 m_img->notifyLayersChanged();
165 }
166
167 private:
168 KisUndoAdapter *m_adapter;
169 KisImageSP m_img;
170 KisGroupLayerSP m_oldRootLayer;
171 KisGroupLayerSP m_newRootLayer;
172 };
173
174
175 // -------------------------------------------------------
176
177 class KisConvertImageTypeCmd : public KNamedCommand {
178 typedef KNamedCommand super;
179
180 public:
181 KisConvertImageTypeCmd(KisUndoAdapter *adapter, KisImageSP img,
182 KisColorSpace * beforeColorSpace, KisColorSpace * afterColorSpace
183 ) : super(i18n("Convert Image Type"))
184 {
185 m_adapter = adapter;
186 m_img = img;
187 m_beforeColorSpace = beforeColorSpace;
188 m_afterColorSpace = afterColorSpace;
189 }
190
191 virtual ~KisConvertImageTypeCmd()
192 {
193 }
194
195 public:
196 virtual void execute()
197 {
198 m_adapter->setUndo(false);
199
200 m_img->setColorSpace(m_afterColorSpace);
201 m_img->setProfile(m_afterColorSpace->getProfile());
202
203 m_adapter->setUndo(true);
204 }
205
206 virtual void unexecute()
207 {
208 m_adapter->setUndo(false);
209
210 m_img->setColorSpace(m_beforeColorSpace);
211 m_img->setProfile(m_beforeColorSpace->getProfile());
212
213 m_adapter->setUndo(true);
214 }
215
216 private:
217 KisUndoAdapter *m_adapter;
218 KisImageSP m_img;
219 KisColorSpace * m_beforeColorSpace;
220 KisColorSpace * m_afterColorSpace;
221 };
222
223
224 // -------------------------------------------------------
225
226 class KisImageCommand : public KNamedCommand {
227 typedef KNamedCommand super;
228
229 public:
230 KisImageCommand(const TQString& name, KisImageSP image);
231 virtual ~KisImageCommand() {}
232
233 virtual void execute() = 0;
234 virtual void unexecute() = 0;
235
236 protected:
237 void setUndo(bool undo);
238
239 KisImageSP m_image;
240 };
241
242 KisImageCommand::KisImageCommand(const TQString& name, KisImageSP image) :
243 super(name), m_image(image)
244 {
245 }
246
247 void KisImageCommand::setUndo(bool undo)
248 {
249 if (m_image->undoAdapter()) {
250 m_image->undoAdapter()->setUndo(undo);
251 }
252 }
253
254
255 // -------------------------------------------------------
256
257 class KisLayerPositionCommand : public KisImageCommand {
258 typedef KisImageCommand super;
259
260 public:
261 KisLayerPositionCommand(const TQString& name, KisImageSP image, KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis) : super(name, image)
262 {
263 m_layer = layer;
264 m_oldParent = layer->parent();
265 m_oldAboveThis = layer->nextSibling();
266 m_newParent = parent;
267 m_newAboveThis = aboveThis;
268 }
269
270 virtual void execute()
271 {
272 setUndo(false);
273 m_image->moveLayer(m_layer, m_newParent, m_newAboveThis);
274 setUndo(true);
275 }
276
277 virtual void unexecute()
278 {
279 setUndo(false);
280 m_image->moveLayer(m_layer, m_oldParent, m_oldAboveThis);
281 setUndo(true);
282 }
283
284 private:
285 KisLayerSP m_layer;
286 KisGroupLayerSP m_oldParent;
287 KisLayerSP m_oldAboveThis;
288 KisGroupLayerSP m_newParent;
289 KisLayerSP m_newAboveThis;
290 };
291
292
293 // -------------------------------------------------------
294
295 class LayerAddCmd : public KisCommand {
296 typedef KisCommand super;
297
298 public:
299 LayerAddCmd(KisUndoAdapter *adapter, KisImageSP img, KisLayerSP layer) : super(i18n("Add Layer"), adapter)
300 {
301 m_img = img;
302 m_layer = layer;
303 m_parent = layer->parent();
304 m_aboveThis = layer->nextSibling();
305 }
306
307 virtual ~LayerAddCmd()
308 {
309 }
310
311 virtual void execute()
312 {
313 adapter()->setUndo(false);
314 m_img->addLayer(m_layer, m_parent.data(), m_aboveThis);
315 adapter()->setUndo(true);
316 }
317
318 virtual void unexecute()
319 {
320 adapter()->setUndo(false);
321 m_img->removeLayer(m_layer);
322 adapter()->setUndo(true);
323 }
324
325 private:
326 KisImageSP m_img;
327 KisLayerSP m_layer;
328 KisGroupLayerSP m_parent;
329 KisLayerSP m_aboveThis;
330 };
331
332 // -------------------------------------------------------
333
334 class LayerRmCmd : public KNamedCommand {
335 typedef KNamedCommand super;
336
337 public:
338 LayerRmCmd(KisUndoAdapter *adapter, KisImageSP img,
339 KisLayerSP layer, KisGroupLayerSP wasParent, KisLayerSP wasAbove)
340 : super(i18n("Remove Layer"))
341 {
342 m_adapter = adapter;
343 m_img = img;
344 m_layer = layer;
345 m_prevParent = wasParent;
346 m_prevAbove = wasAbove;
347 }
348
349 virtual ~LayerRmCmd()
350 {
351 }
352
353 virtual void execute()
354 {
355 m_adapter->setUndo(false);
356 m_img->removeLayer(m_layer);
357 m_adapter->setUndo(true);
358 }
359
360 virtual void unexecute()
361 {
362 m_adapter->setUndo(false);
363 m_img->addLayer(m_layer, m_prevParent.data(), m_prevAbove);
364 m_adapter->setUndo(true);
365 }
366
367 private:
368 KisUndoAdapter *m_adapter;
369 KisImageSP m_img;
370 KisLayerSP m_layer;
371 KisGroupLayerSP m_prevParent;
372 KisLayerSP m_prevAbove;
373 };
374
375 class LayerMoveCmd: public KNamedCommand {
376 typedef KNamedCommand super;
377
378 public:
379 LayerMoveCmd(KisUndoAdapter *adapter, KisImageSP img,
380 KisLayerSP layer, KisGroupLayerSP wasParent, KisLayerSP wasAbove)
381 : super(i18n("Move Layer"))
382 {
383 m_adapter = adapter;
384 m_img = img;
385 m_layer = layer;
386 m_prevParent = wasParent;
387 m_prevAbove = wasAbove;
388 m_newParent = layer->parent();
389 m_newAbove = layer->nextSibling();
390 }
391
392 virtual ~LayerMoveCmd()
393 {
394 }
395
396 virtual void execute()
397 {
398 m_adapter->setUndo(false);
399 m_img->moveLayer(m_layer, m_newParent.data(), m_newAbove);
400 m_adapter->setUndo(true);
401 }
402
403 virtual void unexecute()
404 {
405 m_adapter->setUndo(false);
406 m_img->moveLayer(m_layer, m_prevParent.data(), m_prevAbove);
407 m_adapter->setUndo(true);
408 }
409
410 private:
411 KisUndoAdapter *m_adapter;
412 KisImageSP m_img;
413 KisLayerSP m_layer;
414 KisGroupLayerSP m_prevParent;
415 KisLayerSP m_prevAbove;
416 KisGroupLayerSP m_newParent;
417 KisLayerSP m_newAbove;
418 };
419
420
421 // -------------------------------------------------------
422
423 class LayerPropsCmd : public KNamedCommand {
424 typedef KNamedCommand super;
425
426 public:
427 LayerPropsCmd(KisLayerSP layer,
428 KisImageSP img,
429 KisUndoAdapter *adapter,
430 const TQString& name,
431 TQ_INT32 opacity,
432 const KisCompositeOp& compositeOp) : super(i18n("Layer Property Changes"))
433 {
434 m_layer = layer;
435 m_img = img;
436 m_adapter = adapter;
437 m_name = name;
438 m_opacity = opacity;
439 m_compositeOp = compositeOp;
440 }
441
442 virtual ~LayerPropsCmd()
443 {
444 }
445
446 public:
447 virtual void execute()
448 {
449 TQString name = m_layer->name();
450 TQ_INT32 opacity = m_layer->opacity();
451 KisCompositeOp compositeOp = m_layer->compositeOp();
452
453 m_adapter->setUndo(false);
454 m_img->setLayerProperties(m_layer,
455 m_opacity,
456 m_compositeOp,
457 m_name);
458 m_adapter->setUndo(true);
459 m_name = name;
460 m_opacity = opacity;
461 m_compositeOp = compositeOp;
462 m_layer->setDirty();
463 }
464
465 virtual void unexecute()
466 {
467 execute();
468 }
469
470 private:
471 KisUndoAdapter *m_adapter;
472 KisLayerSP m_layer;
473 KisImageSP m_img;
474 TQString m_name;
475 TQ_INT32 m_opacity;
476 KisCompositeOp m_compositeOp;
477 };
478
479 // -------------------------------------------------------
480
481 class LockImageCommand : public KNamedCommand {
482 typedef KNamedCommand super;
483
484 public:
485 LockImageCommand(KisImageSP img, bool lockImage) : super("lock image") // Not for translation, this
486 { // is only ever used inside a macro command.
487 m_img = img;
488 m_lockImage = lockImage;
489 }
490
491 virtual ~LockImageCommand()
492 {
493 }
494
495 virtual void execute()
496 {
497 if (m_lockImage) {
498 m_img->lock();
499 } else {
500 m_img->unlock();
501 }
502 }
503
504 virtual void unexecute()
505 {
506 if (m_lockImage) {
507 m_img->unlock();
508 } else {
509 m_img->lock();
510 }
511 }
512
513 private:
514 KisImageSP m_img;
515 bool m_lockImage;
516 };
517}
518
519KisImage::KisImage(KisUndoAdapter *adapter, TQ_INT32 width, TQ_INT32 height, KisColorSpace * colorSpace, const TQString& name)
520 : TQObject(0, name.latin1()), TDEShared()
521{
522 init(adapter, width, height, colorSpace, name);
523 setName(name);
524 m_dcop = 0L;
525}
526
527KisImage::KisImage(const KisImage& rhs) : TQObject(), TDEShared(rhs)
528{
529 m_dcop = 0L;
530 if (this != &rhs) {
531 m_private = new KisImagePrivate(*rhs.m_private);
532 m_private->perspectiveGrid = new KisPerspectiveGrid(*rhs.m_private->perspectiveGrid);
533 m_uri = rhs.m_uri;
534 m_name = TQString();
535 m_width = rhs.m_width;
536 m_height = rhs.m_height;
537 m_xres = rhs.m_xres;
538 m_yres = rhs.m_yres;
539 m_unit = rhs.m_unit;
540 m_colorSpace = rhs.m_colorSpace;
541 m_dirty = rhs.m_dirty;
542 m_adapter = rhs.m_adapter;
543
544 m_bkg = new KisBackground();
545 TQ_CHECK_PTR(m_bkg);
546
547 m_rootLayer = static_cast<KisGroupLayer*>(rhs.m_rootLayer->clone().data());
548 connect(m_rootLayer, TQ_SIGNAL(sigDirty(TQRect)), this, TQ_SIGNAL(sigImageUpdated(TQRect)));
549
550 m_annotations = rhs.m_annotations; // XXX the annotations would probably need to be deep-copied
551
552 m_nserver = new KisNameServer(i18n("Layer %1"), rhs.m_nserver->currentSeed() + 1);
553 TQ_CHECK_PTR(m_nserver);
554
555 //m_guides = rhs.m_guides;
556
557 // Set this as the current image for the layers
558 m_rootLayer->setImage(this);
559 // Set the active paint layer
560 if(rhs.activeLayer() != NULL) {
561 TQString layerName = rhs.activeLayer()->name();
562 // kdDebug(12345) << "KisImage::KisImage: active layer = " << layerName << "\n";
563 KisLayerSP activeLayer = rootLayer()->findLayer(layerName);
564 Q_ASSERT(activeLayer);
565 activate(activeLayer);
566 } else {
567 activate(NULL);
568 }
569 }
570}
571
572
573
574DCOPObject * KisImage::dcopObject()
575{
576 if (!m_dcop) {
577 m_dcop = new KisImageIface(this);
578 TQ_CHECK_PTR(m_dcop);
579 }
580 return m_dcop;
581}
582
583KisImage::~KisImage()
584{
585 delete m_private->perspectiveGrid;
586 delete m_private;
587 delete m_nserver;
588 delete m_dcop;
589}
590
591TQString KisImage::name() const
592{
593 return m_name;
594}
595
596void KisImage::setName(const TQString& name)
597{
598 if (!name.isEmpty())
599 m_name = name;
600}
601
602TQString KisImage::description() const
603{
604 return m_description;
605}
606
607void KisImage::setDescription(const TQString& description)
608{
609 if (!description.isEmpty())
610 m_description = description;
611}
612
613
614KisColor KisImage::backgroundColor() const
615{
616 return m_private->backgroundColor;
617}
618
619void KisImage::setBackgroundColor(const KisColor & color)
620{
621 m_private->backgroundColor = color;
622}
623
624
625TQString KisImage::nextLayerName() const
626{
627 if (m_nserver->currentSeed() == 0) {
628 m_nserver->number();
629 return i18n("background");
630 }
631
632 return m_nserver->name();
633}
634
635void KisImage::rollBackLayerName()
636{
637 m_nserver->rollback();
638}
639
640void KisImage::init(KisUndoAdapter *adapter, TQ_INT32 width, TQ_INT32 height, KisColorSpace * colorSpace, const TQString& name)
641{
642 Q_ASSERT(colorSpace);
643
644 if (colorSpace == 0) {
645 colorSpace = KisMetaRegistry::instance()->csRegistry()->getRGB8();
646 kdWarning(41010) << "No colorspace specified: using RGBA\n";
647 }
648
649 m_private = new KisImagePrivate();
650 m_private->backgroundColor = KisColor(TQt::white, colorSpace);
651 m_private->lockCount = 0;
652 m_private->sizeChangedWhileLocked = false;
653 m_private->selectionChangedWhileLocked = false;
654 m_private->substrate = 0;
655 m_private->perspectiveGrid = new KisPerspectiveGrid();
656
657 m_adapter = adapter;
658
659 m_nserver = new KisNameServer(i18n("Layer %1"), 1);
660 m_name = name;
661
662 m_colorSpace = colorSpace;
663 m_bkg = new KisBackground();
664
665 m_rootLayer = new KisGroupLayer(this,"root", OPACITY_OPAQUE);
666 connect(m_rootLayer, TQ_SIGNAL(sigDirty(TQRect)), this, TQ_SIGNAL(sigImageUpdated(TQRect)));
667
668 m_xres = 1.0;
669 m_yres = 1.0;
670 m_unit = KoUnit::U_PT;
671 m_dirty = false;
672 m_width = width;
673 m_height = height;
674}
675
676bool KisImage::locked() const
677{
678 return m_private->lockCount != 0;
679}
680
681void KisImage::lock()
682{
683 if (!locked()) {
684 if (m_rootLayer) disconnect(m_rootLayer, TQ_SIGNAL(sigDirty(TQRect)), this, TQ_SIGNAL(sigImageUpdated(TQRect)));
685 m_private->sizeChangedWhileLocked = false;
686 m_private->selectionChangedWhileLocked = false;
687 }
688 m_private->lockCount++;
689}
690
691void KisImage::unlock()
692{
693 Q_ASSERT(locked());
694
695 if (locked()) {
696 m_private->lockCount--;
697
698 if (m_private->lockCount == 0) {
699 if (m_private->sizeChangedWhileLocked) {
700 // A size change implies a full image update so only send this.
701 emit sigSizeChanged(m_width, m_height);
702 } else {
703 if (m_rootLayer->dirty()) emit sigImageUpdated( m_rootLayer->dirtyRect() );
704 }
705
706 if (m_private->selectionChangedWhileLocked) {
707 emit sigActiveSelectionChanged(this);
708 }
709
710 if (m_rootLayer) connect(m_rootLayer, TQ_SIGNAL(sigDirty(TQRect)), this, TQ_SIGNAL(sigImageUpdated(TQRect)));
711 }
712 }
713}
714
715void KisImage::emitSizeChanged()
716{
717 if (!locked()) {
718 emit sigSizeChanged(m_width, m_height);
719 } else {
720 m_private->sizeChangedWhileLocked = true;
721 }
722}
723
724void KisImage::notifyLayerUpdated(KisLayerSP layer, TQRect rc)
725{
726 emit sigLayerUpdated(layer, rc);
727}
728
729void KisImage::resize(TQ_INT32 w, TQ_INT32 h, TQ_INT32 x, TQ_INT32 y, bool cropLayers)
730{
731 if (w != width() || h != height()) {
732
733 lock();
734
735 if (undo()) {
736 if (cropLayers)
737 m_adapter->beginMacro(i18n("Crop Image"));
738 else
739 m_adapter->beginMacro(i18n("Resize Image"));
740
741 m_adapter->addCommand(new LockImageCommand(this, true));
742 m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
743 }
744
745 m_width = w;
746 m_height = h;
747
748 if (cropLayers) {
749 KisCropVisitor v(TQRect(x, y, w, h));
750 m_rootLayer->accept(v);
751 }
752
753 emitSizeChanged();
754
755 unlock();
756
757 if (undo()) {
758 m_adapter->addCommand(new LockImageCommand(this, false));
759 m_adapter->endMacro();
760 }
761 }
762}
763
764void KisImage::resize(const TQRect& rc, bool cropLayers)
765{
766 resize(rc.width(), rc.height(), rc.x(), rc.y(), cropLayers);
767}
768
769
770void KisImage::scale(double sx, double sy, KisProgressDisplayInterface *progress, KisFilterStrategy *filterStrategy)
771{
772 if (nlayers() == 0) return; // Nothing to scale
773
774 // New image size. XXX: Pass along to discourage rounding errors?
775 TQ_INT32 w, h;
776 w = (TQ_INT32)(( width() * sx) + 0.5);
777 h = (TQ_INT32)(( height() * sy) + 0.5);
778
779 if (w != width() || h != height()) {
780
781 lock();
782
783 if (undo()) {
784 m_adapter->beginMacro(i18n("Scale Image"));
785 m_adapter->addCommand(new LockImageCommand(this, true));
786 }
787#if 0
788 if ( colorSpace()->id() == KisID("RGBA") || colorSpace()->id() == KisID("CMYK") || colorSpace()->id() == KisID("GRAYA")) {
789 KisScaleVisitor v (this, sx, sy, progress, filterStrategy);
790 m_rootLayer->accept( v );
791 }
792 else {
793#endif
794 KisTransformVisitor visitor (this, sx, sy, 0.0, 0.0, 0.0, 0, 0, progress, filterStrategy);
795 m_rootLayer->accept(visitor);
796// }
797
798 if (undo()) {
799 m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
800 }
801
802 m_width = w;
803 m_height = h;
804
805 emitSizeChanged();
806
807 unlock();
808
809 if (undo()) {
810 m_adapter->addCommand(new LockImageCommand(this, false));
811 m_adapter->endMacro();
812 }
813 }
814}
815
816
817
818void KisImage::rotate(double radians, KisProgressDisplayInterface *progress)
819{
820 lock();
821
822 TQ_INT32 w = width();
823 TQ_INT32 h = height();
824 TQ_INT32 tx = TQ_INT32((w*cos(radians) - h*sin(radians) - w) / 2 + 0.5);
825 TQ_INT32 ty = TQ_INT32((h*cos(radians) + w*sin(radians) - h) / 2 + 0.5);
826 w = (TQ_INT32)(width()*TQABS(cos(radians)) + height()*TQABS(sin(radians)) + 0.5);
827 h = (TQ_INT32)(height()*TQABS(cos(radians)) + width()*TQABS(sin(radians)) + 0.5);
828
829 tx -= (w - width()) / 2;
830 ty -= (h - height()) / 2;
831
832 if (undo()) {
833 m_adapter->beginMacro(i18n("Rotate Image"));
834 m_adapter->addCommand(new LockImageCommand(this, true));
835 }
836
837 KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->get(KisID("Triangle"));
838 KisTransformVisitor visitor (this, 1.0, 1.0, 0, 0, radians, -tx, -ty, progress, filter);
839 m_rootLayer->accept(visitor);
840
841 if (undo()) m_adapter->addCommand(new KisResizeImageCmd(undoAdapter(), this, w, h, width(), height()));
842
843 m_width = w;
844 m_height = h;
845
846 emitSizeChanged();
847
848 unlock();
849
850 if (undo()) {
851 m_adapter->addCommand(new LockImageCommand(this, false));
852 m_adapter->endMacro();
853 }
854}
855
856void KisImage::shear(double angleX, double angleY, KisProgressDisplayInterface *m_progress)
857{
858 const double pi=3.1415926535897932385;
859
860 //new image size
861 TQ_INT32 w=width();
862 TQ_INT32 h=height();
863
864
865 if(angleX != 0 || angleY != 0){
866 double deltaY=height()*TQABS(tan(angleX*pi/180)*tan(angleY*pi/180));
867 w = (TQ_INT32) ( width() + TQABS(height()*tan(angleX*pi/180)) );
868 //ugly fix for the problem of having two extra pixels if only a shear along one
869 //axis is done. This has to be fixed in the cropping code in KisRotateVisitor!
870 if (angleX == 0 || angleY == 0)
871 h = (TQ_INT32) ( height() + TQABS(w*tan(angleY*pi/180)) );
872 else if (angleX > 0 && angleY > 0)
873 h = (TQ_INT32) ( height() + TQABS(w*tan(angleY*pi/180))- 2 * deltaY + 2 );
874 else if (angleX < 0 && angleY < 0)
875 h = (TQ_INT32) ( height() + TQABS(w*tan(angleY*pi/180))- 2 * deltaY + 2 );
876 else
877 h = (TQ_INT32) ( height() + TQABS(w*tan(angleY*pi/180)) );
878 }
879
880 if (w != width() || h != height()) {
881
882 lock();
883
884 if (undo()) {
885 m_adapter->beginMacro(i18n("Shear Image"));
886 m_adapter->addCommand(new LockImageCommand(this, true));
887 }
888
889 KisShearVisitor v(angleX, angleY, m_progress);
890 v.setUndoAdapter(undoAdapter());
891 rootLayer()->accept(v);
892
893 if (undo()) m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
894
895 m_width = w;
896 m_height = h;
897
898 emitSizeChanged();
899
900 unlock();
901
902 if (undo()) {
903 m_adapter->addCommand(new LockImageCommand(this, false));
904 m_adapter->endMacro();
905 }
906 }
907}
908
909void KisImage::convertTo(KisColorSpace * dstColorSpace, TQ_INT32 renderingIntent)
910{
911 if ( m_colorSpace == dstColorSpace )
912 {
913 return;
914 }
915
916 lock();
917
918 KisColorSpace * oldCs = m_colorSpace;
919
920 if (undo()) {
921 m_adapter->beginMacro(i18n("Convert Image Type"));
922 m_adapter->addCommand(new LockImageCommand(this, true));
923 }
924
925 setColorSpace(dstColorSpace);
926
927 KisColorSpaceConvertVisitor visitor(dstColorSpace, renderingIntent);
928 m_rootLayer->accept(visitor);
929
930 unlock();
931
932 emit sigLayerPropertiesChanged( m_activeLayer );
933
934 if (undo()) {
935
936 m_adapter->addCommand(new KisConvertImageTypeCmd(undoAdapter(), this,
937 oldCs, dstColorSpace));
938 m_adapter->addCommand(new LockImageCommand(this, false));
939 m_adapter->endMacro();
940 }
941}
942
943KisProfile * KisImage::getProfile() const
944{
945 return colorSpace()->getProfile();
946}
947
948void KisImage::setProfile(const KisProfile * profile)
949{
950 if (profile == 0) return;
951
952 KisColorSpace * dstCs= KisMetaRegistry::instance()->csRegistry()->getColorSpace( colorSpace()->id(),
953 profile);
954 if (dstCs) {
955
956 lock();
957
958 KisColorSpace * oldCs = colorSpace();
959 setColorSpace(dstCs);
960 emit(sigProfileChanged(const_cast<KisProfile *>(profile)));
961
962 KisChangeProfileVisitor visitor(oldCs, dstCs);
963 m_rootLayer->accept(visitor);
964
965 unlock();
966 }
967}
968
969double KisImage::xRes()
970{
971 return m_xres;
972}
973
974double KisImage::yRes()
975{
976 return m_yres;
977}
978
979void KisImage::setResolution(double xres, double yres)
980{
981 m_xres = xres;
982 m_yres = yres;
983}
984
985TQ_INT32 KisImage::width() const
986{
987 return m_width;
988}
989
990TQ_INT32 KisImage::height() const
991{
992 return m_height;
993}
994
995KisPaintDeviceSP KisImage::activeDevice()
996{
997 if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(m_activeLayer.data())) {
998 return layer->paintDeviceOrMask();
999 }
1000 else if (KisAdjustmentLayer* layer = dynamic_cast<KisAdjustmentLayer*>(m_activeLayer.data())) {
1001 if (layer->selection()) {
1002 return layer->selection().data();
1003 }
1004 }
1005 else if (KisGroupLayer * layer = dynamic_cast<KisGroupLayer*>(m_activeLayer.data())) {
1006 // Find first child
1007 KisLayerSP child = layer->lastChild();
1008 while(child)
1009 {
1010 if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(child.data())) {
1011 return layer->paintDevice();
1012 }
1013 child = child->prevSibling();
1014 }
1015 KisLayerSP sibling = layer->nextSibling();
1016 while (sibling) {
1017 if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(sibling.data())) {
1018 return layer->paintDevice();
1019 }
1020 sibling = sibling->nextSibling();
1021 }
1022 }
1023 else if (KisLayerSP layer = m_activeLayer) {
1024 // A weird layer -- let's not return it, but a sibling
1025 KisLayerSP sibling = layer->nextSibling();
1026 while (sibling) {
1027 if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(sibling.data())) {
1028 return layer->paintDevice();
1029 }
1030 sibling = sibling->nextSibling();
1031 }
1032 }
1033 // XXX: We're buggered!
1034 return 0;
1035}
1036
1037KisLayerSP KisImage::newLayer(const TQString& name, TQ_UINT8 opacity, const KisCompositeOp& compositeOp, KisColorSpace * colorstrategy)
1038{
1039 KisPaintLayer * layer;
1040 if (colorstrategy)
1041 layer = new KisPaintLayer(this, name, opacity, colorstrategy);
1042 else
1043 layer = new KisPaintLayer(this, name, opacity);
1044 TQ_CHECK_PTR(layer);
1045
1046 if (compositeOp.isValid())
1047 layer->setCompositeOp(compositeOp);
1048 layer->setVisible(true);
1049
1050 if (m_activeLayer != 0) {
1051 addLayer(layer, m_activeLayer->parent().data(), m_activeLayer->nextSibling());
1052 }
1053 else {
1054 addLayer(layer, m_rootLayer, 0);
1055 }
1056 activate(layer);
1057
1058 return layer;
1059}
1060
1061void KisImage::setLayerProperties(KisLayerSP layer, TQ_UINT8 opacity, const KisCompositeOp& compositeOp, const TQString& name)
1062{
1063 if (layer && (layer->opacity() != opacity || layer->compositeOp() != compositeOp || layer->name() != name)) {
1064 if (undo()) {
1065 TQString oldname = layer->name();
1066 TQ_INT32 oldopacity = layer->opacity();
1067 KisCompositeOp oldCompositeOp = layer->compositeOp();
1068 layer->setName(name);
1069 layer->setOpacity(opacity);
1070 layer->setCompositeOp(compositeOp);
1071 m_adapter->addCommand(new LayerPropsCmd(layer, this, m_adapter, oldname, oldopacity, oldCompositeOp));
1072 } else {
1073 layer->setName(name);
1074 layer->setOpacity(opacity);
1075 layer->setCompositeOp(compositeOp);
1076 }
1077 }
1078}
1079
1080KisGroupLayerSP KisImage::rootLayer() const
1081{
1082 return m_rootLayer;
1083}
1084
1085KisLayerSP KisImage::activeLayer() const
1086{
1087 return m_activeLayer;
1088}
1089
1090KisPaintDeviceSP KisImage::projection()
1091{
1092 return m_rootLayer->projection(TQRect(0, 0, m_width, m_height));
1093}
1094
1095KisLayerSP KisImage::activate(KisLayerSP layer)
1096{
1097 if (layer != m_activeLayer) {
1098 if (m_activeLayer) m_activeLayer->deactivate();
1099 m_activeLayer = layer;
1100 if (m_activeLayer) m_activeLayer->activate();
1101 emit sigLayerActivated(m_activeLayer);
1102 emit sigMaskInfoChanged();
1103 }
1104
1105 return layer;
1106}
1107
1108KisLayerSP KisImage::findLayer(const TQString& name) const
1109{
1110 return rootLayer()->findLayer(name);
1111}
1112
1113KisLayerSP KisImage::findLayer(int id) const
1114{
1115 return rootLayer()->findLayer(id);
1116}
1117
1118
1119bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent)
1120{
1121 return addLayer(layer, parent, parent->firstChild());
1122}
1123
1124bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis)
1125{
1126 if (!parent)
1127 return false;
1128
1129 const bool success = parent->addLayer(layer, aboveThis);
1130 if (success)
1131 {
1132 KisPaintLayerSP player = dynamic_cast<KisPaintLayer*>(layer.data());
1133 if (player != 0) {
1134
1135 // XXX: This should also be done whenever a layer grows!
1136 TQValueVector<KisPaintDeviceAction *> actions = KisMetaRegistry::instance() ->
1137 csRegistry()->paintDeviceActionsFor(player->paintDevice()->colorSpace());
1138 for (uint i = 0; i < actions.count(); i++) {
1139 actions.at(i)->act(player.data()->paintDevice(), width(), height());
1140 }
1141
1142 connect(player, TQ_SIGNAL(sigMaskInfoChanged()), this, TQ_SIGNAL(sigMaskInfoChanged()));
1143 }
1144
1145 if (layer->extent().isValid()) layer->setDirty();
1146
1147 if (!layer->temporary()) {
1148 emit sigLayerAdded(layer);
1149 activate(layer);
1150 }
1151
1152
1153 if (!layer->temporary() && undo()) {
1154 m_adapter->addCommand(new LayerAddCmd(m_adapter, this, layer));
1155 }
1156 }
1157
1158 return success;
1159}
1160
1161bool KisImage::removeLayer(KisLayerSP layer)
1162{
1163 if (!layer || layer->image() != this)
1164 return false;
1165
1166 if (KisGroupLayerSP parent = layer->parent()) {
1167 // Adjustment layers should mark the layers underneath them, whose rendering
1168 // they have cached, diryt on removal. Otherwise, the group won't be re-rendered.
1169 KisAdjustmentLayer * al = dynamic_cast<KisAdjustmentLayer*>(layer.data());
1170 if (al) {
1171 TQRect r = al->extent();
1172 lock(); // Lock the image, because we are going to dirty a lot of layers
1173 KisLayerSP l = layer->nextSibling();
1174 while (l) {
1175 KisAdjustmentLayer * al2 = dynamic_cast<KisAdjustmentLayer*>(l.data());
1176 l->setDirty(r, false);
1177 if (al2 != 0) break;
1178 l = l->nextSibling();
1179 }
1180 unlock();
1181 }
1182 KisPaintLayerSP player = dynamic_cast<KisPaintLayer*>(layer.data());
1183 if (player != 0) {
1184 disconnect(player, TQ_SIGNAL(sigMaskInfoChanged()),
1185 this, TQ_SIGNAL(sigMaskInfoChanged()));
1186 }
1187 KisLayerSP l = layer->prevSibling();
1188 TQRect r = layer->extent();
1189 while (l) {
1190 l->setDirty(r, false);
1191 l = l->prevSibling();
1192 }
1193
1194 KisLayerSP wasAbove = layer->nextSibling();
1195 KisLayerSP wasBelow = layer->prevSibling();
1196 const bool wasActive = layer == activeLayer();
1197 // sigLayerRemoved can set it to 0, we don't want that in the else of wasActive!
1198 KisLayerSP actLayer = activeLayer();
1199 const bool success = parent->removeLayer(layer);
1200 if (success) {
1201 layer->setImage(0);
1202 if (!layer->temporary() && undo()) {
1203 m_adapter->addCommand(new LayerRmCmd(m_adapter, this, layer, parent, wasAbove));
1204 }
1205 if (!layer->temporary()) {
1206 emit sigLayerRemoved(layer, parent, wasAbove);
1207 if (wasActive) {
1208 if (wasBelow)
1209 activate(wasBelow);
1210 else if (wasAbove)
1211 activate(wasAbove);
1212 else if (parent != rootLayer())
1213 activate(parent.data());
1214 else
1215 activate(rootLayer()->firstChild());
1216 } else {
1217 activate(actLayer);
1218 }
1219 }
1220 }
1221 return success;
1222 }
1223
1224 return false;
1225}
1226
1227bool KisImage::raiseLayer(KisLayerSP layer)
1228{
1229 if (!layer)
1230 return false;
1231 return moveLayer(layer, layer->parent().data(), layer->prevSibling());
1232}
1233
1234bool KisImage::lowerLayer(KisLayerSP layer)
1235{
1236 if (!layer)
1237 return false;
1238 if (KisLayerSP next = layer->nextSibling())
1239 return moveLayer(layer, layer->parent().data(), next->nextSibling());
1240 return false;
1241}
1242
1243bool KisImage::toTop(KisLayerSP layer)
1244{
1245 if (!layer)
1246 return false;
1247 return moveLayer(layer, rootLayer(), rootLayer()->firstChild());
1248}
1249
1250bool KisImage::toBottom(KisLayerSP layer)
1251{
1252 if (!layer)
1253 return false;
1254 return moveLayer(layer, rootLayer(), 0);
1255}
1256
1257bool KisImage::moveLayer(KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis)
1258{
1259 if (!parent)
1260 return false;
1261
1262 KisGroupLayerSP wasParent = layer->parent();
1263 KisLayerSP wasAbove = layer->nextSibling();
1264
1265 if (wasParent.data() == parent.data() && wasAbove.data() == aboveThis.data())
1266 return false;
1267
1268 lock();
1269
1270 if (!wasParent->removeLayer(layer)) {
1271 unlock();
1272 return false;
1273 }
1274
1275 const bool success = parent->addLayer(layer, aboveThis);
1276
1277 layer->setDirty();
1278
1279 unlock();
1280
1281 if (success)
1282 {
1283 emit sigLayerMoved(layer, wasParent, wasAbove);
1284 if (undo())
1285 m_adapter->addCommand(new LayerMoveCmd(m_adapter, this, layer, wasParent, wasAbove));
1286 }
1287 else //we already removed the layer above, but re-adding it failed, so...
1288 {
1289 emit sigLayerRemoved(layer, wasParent, wasAbove);
1290 if (undo())
1291 m_adapter->addCommand(new LayerRmCmd(m_adapter, this, layer, wasParent, wasAbove));
1292 }
1293
1294 return success;
1295}
1296
1297TQ_INT32 KisImage::nlayers() const
1298{
1299 return rootLayer()->numLayers() - 1;
1300}
1301
1302TQ_INT32 KisImage::nHiddenLayers() const
1303{
1304 return rootLayer()->numLayers(KisLayer::Hidden);
1305}
1306
1307void KisImage::flatten()
1308{
1309 KisGroupLayerSP oldRootLayer = m_rootLayer;
1310 disconnect(oldRootLayer, TQ_SIGNAL(sigDirty(TQRect)), this, TQ_SIGNAL(sigImageUpdated(TQRect)));
1311
1312 KisPaintLayer *dst = new KisPaintLayer(this, nextLayerName(), OPACITY_OPAQUE, colorSpace());
1313 TQ_CHECK_PTR(dst);
1314
1315 TQRect rc = mergedImage()->extent();
1316
1317 KisPainter gc(dst->paintDevice());
1318 gc.bitBlt(rc.x(), rc.y(), COMPOSITE_COPY, mergedImage(), OPACITY_OPAQUE, rc.left(), rc.top(), rc.width(), rc.height());
1319
1320 m_rootLayer = new KisGroupLayer(this, "", OPACITY_OPAQUE);
1321 connect(m_rootLayer, TQ_SIGNAL(sigDirty(TQRect)), this, TQ_SIGNAL(sigImageUpdated(TQRect)));
1322
1323 if (undo()) {
1324 m_adapter->beginMacro(i18n("Flatten Image"));
1325 m_adapter->addCommand(new LockImageCommand(this, true));
1326 m_adapter->addCommand(new KisChangeLayersCmd(m_adapter, this, oldRootLayer, m_rootLayer, ""));
1327 }
1328
1329 lock();
1330
1331 addLayer(dst, m_rootLayer, 0);
1332 activate(dst);
1333
1334 unlock();
1335
1336 notifyLayersChanged();
1337
1338 if (undo()) {
1339 m_adapter->addCommand(new LockImageCommand(this, false));
1340 m_adapter->endMacro();
1341 }
1342}
1343
1344
1345void KisImage::mergeLayer(KisLayerSP layer)
1346{
1347 KisPaintLayer *player = new KisPaintLayer(this, layer->name(), OPACITY_OPAQUE, colorSpace());
1348 TQ_CHECK_PTR(player);
1349
1350 TQRect rc = layer->extent() | layer->nextSibling()->extent();
1351
1352 undoAdapter()->beginMacro(i18n("Merge with Layer Below"));
1353
1354 //Abuse the merge visitor to only merge two layers (if either are groups they'll recursively merge)
1355 KisMergeVisitor visitor(player->paintDevice(), rc);
1356 layer->nextSibling()->accept(visitor);
1357 layer->accept(visitor);
1358
1359 removeLayer(layer->nextSibling());
1360 addLayer(player, layer->parent(), layer);
1361 removeLayer(layer);
1362
1363 undoAdapter()->endMacro();
1364}
1365
1366
1367void KisImage::setModified()
1368{
1369 emit sigImageModified();
1370}
1371
1372void KisImage::renderToPainter(TQ_INT32 x1,
1373 TQ_INT32 y1,
1374 TQ_INT32 x2,
1375 TQ_INT32 y2,
1376 TQPainter &painter,
1377 KisProfile * monitorProfile,
1378 PaintFlags paintFlags,
1379 float exposure)
1380{
1381
1382 TQImage img = convertToTQImage(x1, y1, x2, y2, monitorProfile, exposure);
1383
1384 TQ_INT32 w = x2 - x1 + 1;
1385 TQ_INT32 h = y2 - y1 + 1;
1386
1387
1388 if (paintFlags & PAINT_BACKGROUND) {
1389 m_bkg->paintBackground(img, x1, y1);
1390 img.setAlphaBuffer(false);
1391 }
1392
1393 if (paintFlags & PAINT_SELECTION) {
1394 if (m_activeLayer != 0) {
1395 m_activeLayer->paintSelection(img, x1, y1, w, h);
1396 }
1397 }
1398
1399 if (paintFlags & PAINT_MASKINACTIVELAYERS) {
1400 if (m_activeLayer != 0) {
1401 m_activeLayer->paintMaskInactiveLayers(img, x1, y1, w, h);
1402 }
1403 }
1404
1405 painter.drawImage(x1, y1, img, 0, 0, w, h);
1406}
1407
1408TQImage KisImage::convertToTQImage(TQ_INT32 x1,
1409 TQ_INT32 y1,
1410 TQ_INT32 x2,
1411 TQ_INT32 y2,
1412 KisProfile * profile,
1413 float exposure)
1414{
1415 TQ_INT32 w = x2 - x1 + 1;
1416 TQ_INT32 h = y2 - y1 + 1;
1417
1418 KisPaintDeviceSP dev = m_rootLayer->projection(TQRect(x1, y1, w, h));
1419 TQImage img = dev->convertToTQImage(profile, x1, y1, w, h, exposure);
1420
1421 if (!img.isNull()) {
1422
1423#ifdef __BIG_ENDIAN__
1424 uchar * data = img.bits();
1425 for (int i = 0; i < w * h; ++i) {
1426 uchar r, g, b, a;
1427 a = data[0];
1428 b = data[1];
1429 g = data[2];
1430 r = data[3];
1431 data[0] = r;
1432 data[1] = g;
1433 data[2] = b;
1434 data[3] = a;
1435 data += 4;
1436 }
1437#endif
1438
1439 return img;
1440 }
1441
1442 return TQImage();
1443}
1444
1445TQImage KisImage::convertToTQImage(const TQRect& r, const TQSize& scaledImageSize, KisProfile *profile, PaintFlags paintFlags, float exposure)
1446{
1447
1448 if (r.isEmpty() || scaledImageSize.isEmpty()) {
1449 return TQImage();
1450 }
1451
1452 TQ_INT32 imageWidth = width();
1453 TQ_INT32 imageHeight = height();
1454 TQ_UINT32 pixelSize = colorSpace()->pixelSize();
1455
1456 double xScale = static_cast<double>(imageWidth) / scaledImageSize.width();
1457 double yScale = static_cast<double>(imageHeight) / scaledImageSize.height();
1458
1459 TQRect srcRect;
1460
1461 srcRect.setLeft(static_cast<int>(r.left() * xScale));
1462 srcRect.setRight(static_cast<int>(ceil((r.right() + 1) * xScale)) - 1);
1463 srcRect.setTop(static_cast<int>(r.top() * yScale));
1464 srcRect.setBottom(static_cast<int>(ceil((r.bottom() + 1) * yScale)) - 1);
1465
1466 KisPaintDeviceSP mergedImage = m_rootLayer->projection(srcRect);
1467 TQTime t;
1468 t.start();
1469
1470 TQ_UINT8 *scaledImageData = new TQ_UINT8[r.width() * r.height() * pixelSize];
1471
1472 TQ_UINT8 *imageRow = new TQ_UINT8[srcRect.width() * pixelSize];
1473 const TQ_INT32 imageRowX = srcRect.x();
1474
1475 for (TQ_INT32 y = 0; y < r.height(); ++y) {
1476
1477 TQ_INT32 dstY = r.y() + y;
1478 TQ_INT32 dstX = r.x();
1479 TQ_INT32 srcY = (dstY * imageHeight) / scaledImageSize.height();
1480
1481 mergedImage->readBytes(imageRow, imageRowX, srcY, srcRect.width(), 1);
1482
1483 TQ_UINT8 *dstPixel = scaledImageData + (y * r.width() * pixelSize);
1484 TQ_UINT32 columnsRemaining = r.width();
1485
1486 while (columnsRemaining > 0) {
1487
1488 TQ_INT32 srcX = (dstX * imageWidth) / scaledImageSize.width();
1489
1490 memcpy(dstPixel, imageRow + ((srcX - imageRowX) * pixelSize), pixelSize);
1491
1492 ++dstX;
1493 dstPixel += pixelSize;
1494 --columnsRemaining;
1495 }
1496 }
1497 kdDebug() << "Time elapsed scaling image: " << t.elapsed() << endl;
1498
1499 delete [] imageRow;
1500
1501 TQImage image = colorSpace()->convertToTQImage(scaledImageData, r.width(), r.height(), profile, INTENT_PERCEPTUAL, exposure);
1502 delete [] scaledImageData;
1503
1504#ifdef __BIG_ENDIAN__
1505 uchar * data = image.bits();
1506 for (int i = 0; i < image.width() * image.height(); ++i) {
1507 uchar r, g, b, a;
1508 a = data[0];
1509 b = data[1];
1510 g = data[2];
1511 r = data[3];
1512 data[0] = r;
1513 data[1] = g;
1514 data[2] = b;
1515 data[3] = a;
1516 data += 4;
1517 }
1518#endif
1519
1520 if (paintFlags & PAINT_BACKGROUND) {
1521 m_bkg->paintBackground(image, r, scaledImageSize, TQSize(imageWidth, imageHeight));
1522 image.setAlphaBuffer(false);
1523 }
1524
1525 if (paintFlags & PAINT_SELECTION) {
1526 if (m_activeLayer != 0) {
1527 m_activeLayer->paintSelection(image, r, scaledImageSize, TQSize(imageWidth, imageHeight));
1528 }
1529 }
1530
1531 /*if (paintFlags & PAINT_MASKINACTIVELAYERS) {
1532 if (m_activeLayer != 0) {
1533 m_activeLayer->paintMaskInactiveLayers(img, x1, y1, w, h);
1534 }
1535 }*/
1536
1537 return image;
1538}
1539
1540KisPaintDeviceSP KisImage::mergedImage()
1541{
1542 return m_rootLayer->projection(TQRect(0, 0, m_width, m_height));
1543}
1544
1545KisColor KisImage::mergedPixel(TQ_INT32 x, TQ_INT32 y)
1546{
1547 return m_rootLayer->projection(TQRect(x, y, 1, 1))->colorAt(x, y);
1548}
1549
1550void KisImage::notifyLayersChanged()
1551{
1552 emit sigLayersChanged(rootLayer());
1553}
1554
1555void KisImage::notifyPropertyChanged(KisLayerSP layer)
1556{
1557 emit sigLayerPropertiesChanged(layer);
1558}
1559
1560void KisImage::notifyImageLoaded()
1561{
1562}
1563
1564TQRect KisImage::bounds() const
1565{
1566 return TQRect(0, 0, width(), height());
1567}
1568
1569
1570void KisImage::setUndoAdapter(KisUndoAdapter * adapter)
1571{
1572 m_adapter = adapter;
1573}
1574
1575
1576KisUndoAdapter* KisImage::undoAdapter() const
1577{
1578 return m_adapter;
1579}
1580
1581bool KisImage::undo() const
1582{
1583 return (m_adapter && m_adapter->undo());
1584}
1585
1586//KisGuideMgr *KisImage::guides() const
1587//{
1588// return const_cast<KisGuideMgr*>(&m_guides);
1589//}
1590
1591void KisImage::slotSelectionChanged()
1592{
1593 slotSelectionChanged(bounds());
1594}
1595
1596void KisImage::slotSelectionChanged(const TQRect& r)
1597{
1598 TQRect r2(r.x() - 1, r.y() - 1, r.width() + 2, r.height() + 2);
1599
1600 if (!locked()) {
1601 emit sigActiveSelectionChanged(this);
1602 emit sigSelectionChanged(this);
1603 } else {
1604 m_private->selectionChangedWhileLocked = true;
1605 }
1606}
1607
1608KisColorSpace * KisImage::colorSpace() const
1609{
1610 return m_colorSpace;
1611}
1612
1613void KisImage::setColorSpace(KisColorSpace * colorSpace)
1614{
1615 m_colorSpace = colorSpace;
1616 m_rootLayer->resetProjection();
1617 emit sigColorSpaceChanged(colorSpace);
1618}
1619
1620void KisImage::setRootLayer(KisGroupLayerSP rootLayer)
1621{
1622 disconnect(m_rootLayer, TQ_SIGNAL(sigDirty(TQRect)), this, TQ_SIGNAL(sigImageUpdated(TQRect)));
1623
1624 m_rootLayer = rootLayer;
1625
1626 if (!locked()) {
1627 connect(m_rootLayer, TQ_SIGNAL(sigDirty(TQRect)), this, TQ_SIGNAL(sigImageUpdated(TQRect)));
1628 }
1629 activate(m_rootLayer->firstChild());
1630}
1631
1632void KisImage::addAnnotation(KisAnnotationSP annotation)
1633{
1634 // Find the icc annotation, if there is one
1635 vKisAnnotationSP_it it = m_annotations.begin();
1636 while (it != m_annotations.end()) {
1637 if ((*it)->type() == annotation->type()) {
1638 *it = annotation;
1639 return;
1640 }
1641 ++it;
1642 }
1643 m_annotations.push_back(annotation);
1644}
1645
1646KisAnnotationSP KisImage::annotation(TQString type)
1647{
1648 vKisAnnotationSP_it it = m_annotations.begin();
1649 while (it != m_annotations.end()) {
1650 if ((*it)->type() == type) {
1651 return *it;
1652 }
1653 ++it;
1654 }
1655 return 0;
1656}
1657
1658void KisImage::removeAnnotation(TQString type)
1659{
1660 vKisAnnotationSP_it it = m_annotations.begin();
1661 while (it != m_annotations.end()) {
1662 if ((*it)->type() == type) {
1663 m_annotations.erase(it);
1664 return;
1665 }
1666 ++it;
1667 }
1668}
1669
1670vKisAnnotationSP_it KisImage::beginAnnotations()
1671{
1672 KisProfile * profile = colorSpace()->getProfile();
1673 KisAnnotationSP annotation;
1674
1675 if (profile)
1676 annotation = profile->annotation();
1677
1678 if (annotation)
1679 addAnnotation(annotation);
1680 else
1681 removeAnnotation("icc");
1682
1683 return m_annotations.begin();
1684}
1685
1686vKisAnnotationSP_it KisImage::endAnnotations()
1687{
1688 return m_annotations.end();
1689}
1690
1691KisBackgroundSP KisImage::background() const
1692{
1693 return m_bkg;
1694}
1695
1696KisPerspectiveGrid* KisImage::perspectiveGrid()
1697{
1698 return m_private->perspectiveGrid;
1699}
1700
1701#include "kis_image.moc"
1702
virtual TQRect extent() const
Returns an approximation of where the bounds on actual data are in this layer.
KisColorSpace * getRGB8()
Convenience method to get an RGB colorspace with the default lcms profile.
KisColorSpace * getColorSpace(const KisID &csID, const TQString &profileName)
Return the colorspace + profile as named, or NULL if impossible combination.
A colorspace is the definition of a certain color model in Chalk.
A KisColor describes a color in a certain colorspace.
Definition kis_color.h:33
_T get(const KisID &name) const
This function allow to get an object from its KisID.
A KisLayer that bundles child layers into a single layer.