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
Class that contains a KisFilter and optionally a KisSelection.
virtual TQRect extent() const
Returns an approximation of where the bounds on actual data are in this layer.
The Change Profile visitor walks over all layers and if the current layer has the specified colorspac...
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.
virtual TQImage convertToTQImage(const TQ_UINT8 *data, TQ_INT32 width, TQ_INT32 height, KisProfile *dstProfile, TQ_INT32 renderingIntent=INTENT_PERCEPTUAL, float exposure=0.0f)=0
Convert the pixels in data to (8-bit BGRA) TQImage using the specified profiles.
virtual TQ_UINT32 pixelSize() const =0
The size in bytes of a single pixel in this color model.
virtual KisProfile * getProfile() const =0
Return the profile of this color space.
A KisColor describes a color in a certain colorspace.
Definition kis_color.h:33
A KisLayer that bundles child layers into a single layer.
Chalk has a large number of extensible resources.
Definition kis_id.h:57
virtual void setDirty(bool propagate=true)
Set the entire layer extent dirty; this percolates up to parent layers all the way to the root layer.
This layer is of a type that can be painted on.
KisPainter contains the graphics primitives necessary to draw on a KisPaintDevice.
Definition kis_painter.h:56