chalk

kis_paint_device.cpp
1/*
2 * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
3 * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
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 <tqrect.h>
20#include <tqwmatrix.h>
21#include <tqimage.h>
22#include <tqdatetime.h>
23#include <tqapplication.h>
24#include <tqvaluelist.h>
25#include <tqtimer.h>
26
27#include <kcommand.h>
28#include <tdelocale.h>
29#include <kdebug.h>
30
31#include <KoStore.h>
32
33#include "kis_global.h"
34#include "kis_types.h"
35#include "kis_painter.h"
36#include "kis_fill_painter.h"
37#include "kis_undo_adapter.h"
38#include "kis_iterator.h"
39#include "kis_iterators_pixel.h"
40#include "kis_iteratorpixeltrait.h"
41#include "kis_random_accessor.h"
42#include "kis_random_sub_accessor.h"
43#include "kis_transaction.h"
44#include "kis_profile.h"
45#include "kis_color.h"
46#include "kis_integer_maths.h"
47#include "kis_colorspace_factory_registry.h"
48#include "kis_selection.h"
49#include "kis_layer.h"
50#include "kis_paint_device_iface.h"
51#include "kis_paint_device.h"
52#include "kis_datamanager.h"
53#include "kis_memento.h"
54#include "kis_selection.h"
55
56#include "kis_exif_info.h"
57
58namespace {
59
60 class KisPaintDeviceCommand : public KNamedCommand {
61 typedef KNamedCommand super;
62
63 public:
64 KisPaintDeviceCommand(const TQString& name, KisPaintDeviceSP paintDevice);
65 virtual ~KisPaintDeviceCommand() {}
66
67 virtual void execute() = 0;
68 virtual void unexecute() = 0;
69
70 protected:
71 void setUndo(bool undo);
72
73 KisPaintDeviceSP m_paintDevice;
74 };
75
76 KisPaintDeviceCommand::KisPaintDeviceCommand(const TQString& name, KisPaintDeviceSP paintDevice) :
77 super(name), m_paintDevice(paintDevice)
78 {
79 }
80
81 void KisPaintDeviceCommand::setUndo(bool undo)
82 {
83 if (m_paintDevice->undoAdapter()) {
84 m_paintDevice->undoAdapter()->setUndo(undo);
85 }
86 }
87
88 class MoveCommand : public KNamedCommand {
89 typedef KNamedCommand super;
90
91 public:
92 MoveCommand(KisPaintDeviceSP device, const TQPoint& oldpos, const TQPoint& newpos);
93 virtual ~MoveCommand();
94
95 virtual void execute();
96 virtual void unexecute();
97
98 private:
99 void moveTo(const TQPoint& pos);
100 void undoOff();
101 void undoOn();
102
103 private:
104 KisPaintDeviceSP m_device;
105 TQPoint m_oldPos;
106 TQPoint m_newPos;
107 };
108
109 MoveCommand::MoveCommand(KisPaintDeviceSP device, const TQPoint& oldpos, const TQPoint& newpos) :
110 super(i18n("Move Layer"))
111 {
112 m_device = device;
113 m_oldPos = oldpos;
114 m_newPos = newpos;
115 }
116
117 MoveCommand::~MoveCommand()
118 {
119 }
120
121 void MoveCommand::undoOff()
122 {
123 if (m_device->undoAdapter()) {
124 m_device->undoAdapter()->setUndo(false);
125 }
126 }
127
128 void MoveCommand::undoOn()
129 {
130 if (m_device->undoAdapter()) {
131 m_device->undoAdapter()->setUndo(true);
132 }
133 }
134
135 void MoveCommand::execute()
136 {
137 undoOff();
138 moveTo(m_newPos);
139 undoOn();
140 }
141
142 void MoveCommand::unexecute()
143 {
144 undoOff();
145 moveTo(m_oldPos);
146 undoOn();
147 }
148
149 void MoveCommand::moveTo(const TQPoint& pos)
150 {
151 m_device->move(pos.x(), pos.y());
152 }
153
154 class KisConvertLayerTypeCmd : public KNamedCommand {
155 typedef KNamedCommand super;
156
157 public:
158 KisConvertLayerTypeCmd(KisUndoAdapter *adapter, KisPaintDeviceSP paintDevice,
159 KisDataManagerSP beforeData, KisColorSpace * beforeColorSpace,
160 KisDataManagerSP afterData, KisColorSpace * afterColorSpace
161 ) : super(i18n("Convert Layer Type"))
162 {
163 m_adapter = adapter;
164 m_paintDevice = paintDevice;
165 m_beforeData = beforeData;
166 m_beforeColorSpace = beforeColorSpace;
167 m_afterData = afterData;
168 m_afterColorSpace = afterColorSpace;
169 }
170
171 virtual ~KisConvertLayerTypeCmd()
172 {
173 }
174
175 public:
176 virtual void execute()
177 {
178 m_adapter->setUndo(false);
179 m_paintDevice->setData(m_afterData, m_afterColorSpace);
180 m_adapter->setUndo(true);
181 }
182
183 virtual void unexecute()
184 {
185 m_adapter->setUndo(false);
186 m_paintDevice->setData(m_beforeData, m_beforeColorSpace);
187 m_adapter->setUndo(true);
188 }
189
190 private:
191 KisUndoAdapter *m_adapter;
192
193 KisPaintDeviceSP m_paintDevice;
194
195 KisDataManagerSP m_beforeData;
196 KisColorSpace * m_beforeColorSpace;
197
198 KisDataManagerSP m_afterData;
199 KisColorSpace * m_afterColorSpace;
200 };
201
202}
203
204KisPaintDevice::KisPaintDevice(KisColorSpace * colorSpace, const char * name) :
205 TQObject(0, name), TDEShared(), m_exifInfo(0), m_lock( false )
206{
207 if (colorSpace == 0) {
208 kdWarning(41001) << "Cannot create paint device without colorstrategy!\n";
209 return;
210 }
211 m_longRunningFilterTimer = 0;
212 m_dcop = 0;
213
214 m_x = 0;
215 m_y = 0;
216
217 m_pixelSize = colorSpace->pixelSize();
218 m_nChannels = colorSpace->nChannels();
219
220 TQ_UINT8* defPixel = new TQ_UINT8 [ m_pixelSize ];
221 colorSpace->fromTQColor(TQt::black, OPACITY_TRANSPARENT, defPixel);
222
223 m_datamanager = new KisDataManager(m_pixelSize, defPixel);
224 delete [] defPixel;
225
226 TQ_CHECK_PTR(m_datamanager);
227 m_extentIsValid = true;
228
229 m_parentLayer = 0;
230
231 m_colorSpace = colorSpace;
232
233 m_hasSelection = false;
234 m_selectionDeselected = false;
235 m_selection = 0;
236
237}
238
239KisPaintDevice::KisPaintDevice(KisLayer *parent, KisColorSpace * colorSpace, const char * name) :
240 TQObject(0, name), TDEShared(), m_exifInfo(0), m_lock( false )
241{
242
243 m_longRunningFilterTimer = 0;
244 m_dcop = 0;
245
246 m_x = 0;
247 m_y = 0;
248
249 m_hasSelection = false;
250 m_selectionDeselected = false;
251 m_selection = 0;
252
253 m_parentLayer = parent;
254
255 if (colorSpace == 0 && parent != 0 && parent->image() != 0) {
256 m_colorSpace = parent->image()->colorSpace();
257 }
258 else {
259 m_colorSpace = colorSpace;
260 }
261
262 Q_ASSERT( m_colorSpace );
263
264 m_pixelSize = m_colorSpace->pixelSize();
265 m_nChannels = m_colorSpace->nChannels();
266
267 TQ_UINT8* defPixel = new TQ_UINT8[ m_pixelSize ];
268 m_colorSpace->fromTQColor(TQt::black, OPACITY_TRANSPARENT, defPixel);
269
270 m_datamanager = new KisDataManager(m_pixelSize, defPixel);
271 delete [] defPixel;
272 TQ_CHECK_PTR(m_datamanager);
273 m_extentIsValid = true;
274
275 if ( TQString ( name ) == TQString( "Layer 1" ) ) {
276 m_longRunningFilters = m_colorSpace->createBackgroundFilters();
277
278 if (!m_longRunningFilters.isEmpty()) {
279 m_longRunningFilterTimer = new TQTimer(this);
280 connect(m_longRunningFilterTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(runBackgroundFilters()));
281 m_longRunningFilterTimer->start(2000);
282 }
283 }
284}
285
286
287KisPaintDevice::KisPaintDevice(const KisPaintDevice& rhs) : TQObject(), TDEShared(rhs)
288{
289 if (this != &rhs) {
290 m_longRunningFilterTimer = 0;
291 m_parentLayer = 0;
292 m_dcop = rhs.m_dcop;
293 if (rhs.m_datamanager) {
294 m_datamanager = new KisDataManager(*rhs.m_datamanager);
295 TQ_CHECK_PTR(m_datamanager);
296 }
297 else {
298 kdWarning() << "rhs " << rhs.name() << " has no datamanager\n";
299 }
300 m_extentIsValid = rhs.m_extentIsValid;
301 m_x = rhs.m_x;
302 m_y = rhs.m_y;
303 m_colorSpace = rhs.m_colorSpace;
304 m_hasSelection = rhs.m_hasSelection;
305
306 if ( m_hasSelection )
307 m_selection = new KisSelection(*rhs.m_selection);
308 else
309 m_selection = 0;
310
311 m_pixelSize = rhs.m_pixelSize;
312 m_nChannels = rhs.m_nChannels;
313 if(rhs.m_exifInfo)
314 {
315 m_exifInfo = new KisExifInfo(*rhs.m_exifInfo);
316 }
317 else {
318 m_exifInfo = 0;
319 }
320 }
321}
322
323KisPaintDevice::~KisPaintDevice()
324{
325 delete m_dcop;
326 delete m_longRunningFilterTimer;
327 TQValueList<KisFilter*>::iterator it;
328 TQValueList<KisFilter*>::iterator end = m_longRunningFilters.end();
329 for (it = m_longRunningFilters.begin(); it != end; ++it) {
330 KisFilter * f = (*it);
331 delete f;
332 }
333 m_longRunningFilters.clear();
334 //delete m_exifInfo;
335}
336
337DCOPObject *KisPaintDevice::dcopObject()
338{
339 if (!m_dcop) {
340 m_dcop = new KisPaintDeviceIface(this);
341 TQ_CHECK_PTR(m_dcop);
342 }
343 return m_dcop;
344}
345
347{
348 return m_parentLayer;
349}
350
355
356void KisPaintDevice::setDirty(const TQRect & rc)
357{
358 if (m_parentLayer) m_parentLayer->setDirty(rc);
359}
360
362{
363 if (m_parentLayer) m_parentLayer->setDirty();
364}
365
366KisImage *KisPaintDevice::image() const
367{
368 if (m_parentLayer) {
369 return m_parentLayer->image();
370 } else {
371 return 0;
372 }
373}
374
375
376void KisPaintDevice::move(TQ_INT32 x, TQ_INT32 y)
377{
378 TQRect dirtyRect = extent();
379
380 m_x = x;
381 m_y = y;
382
383 dirtyRect |= extent();
384
385 if(m_selection)
386 {
387 m_selection->setX(x);
388 m_selection->setY(y);
389 }
390
391 setDirty(dirtyRect);
392
393 emit positionChanged(this);
394}
395
396void KisPaintDevice::move(const TQPoint& pt)
397{
398 move(pt.x(), pt.y());
399}
400
401KNamedCommand * KisPaintDevice::moveCommand(TQ_INT32 x, TQ_INT32 y)
402{
403 KNamedCommand * cmd = new MoveCommand(this, TQPoint(m_x, m_y), TQPoint(x, y));
404 TQ_CHECK_PTR(cmd);
405 cmd->execute();
406 return cmd;
407}
408
409void KisPaintDevice::extent(TQ_INT32 &x, TQ_INT32 &y, TQ_INT32 &w, TQ_INT32 &h) const
410{
411 m_datamanager->extent(x, y, w, h);
412 x += m_x;
413 y += m_y;
414}
415
416TQRect KisPaintDevice::extent() const
417{
418 TQ_INT32 x, y, w, h;
419 extent(x, y, w, h);
420 return TQRect(x, y, w, h);
421}
422
424{
425 return m_extentIsValid;
426}
427
429{
430 m_extentIsValid = isValid;
431}
432
433void KisPaintDevice::exactBounds(TQ_INT32 &x, TQ_INT32 &y, TQ_INT32 &w, TQ_INT32 &h) const
434{
435 TQRect r = exactBounds();
436 x = r.x();
437 y = r.y();
438 w = r.width();
439 h = r.height();
440}
441
442TQRect KisPaintDevice::exactBoundsOldMethod() const
443{
444 TQ_INT32 x, y, w, h, boundX, boundY, boundW, boundH;
445 extent(x, y, w, h);
446
447 extent(boundX, boundY, boundW, boundH);
448
449 const TQ_UINT8* defaultPixel = m_datamanager->defaultPixel();
450
451 bool found = false;
452
453 for (TQ_INT32 y2 = y; y2 < y + h ; ++y2) {
454 KisHLineIterator it = const_cast<KisPaintDevice *>(this)->createHLineIterator(x, y2, w, false);
455 while (!it.isDone() && found == false) {
456 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
457 boundY = y2;
458 found = true;
459 break;
460 }
461 ++it;
462 }
463 if (found) break;
464 }
465
466 found = false;
467
468 for (TQ_INT32 y2 = y + h; y2 > y ; --y2) {
469 KisHLineIterator it = const_cast<KisPaintDevice *>(this)->createHLineIterator(x, y2, w, false);
470 while (!it.isDone() && found == false) {
471 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
472 boundH = y2 - boundY + 1;
473 found = true;
474 break;
475 }
476 ++it;
477 }
478 if (found) break;
479 }
480 found = false;
481
482 for (TQ_INT32 x2 = x; x2 < x + w ; ++x2) {
483 KisVLineIterator it = const_cast<KisPaintDevice *>(this)->createVLineIterator(x2, y, h, false);
484 while (!it.isDone() && found == false) {
485 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
486 boundX = x2;
487 found = true;
488 break;
489 }
490 ++it;
491 }
492 if (found) break;
493 }
494
495 found = false;
496
497 // Look for right edge )
498 for (TQ_INT32 x2 = x + w; x2 > x ; --x2) {
499 KisVLineIterator it = const_cast<KisPaintDevice *>(this)->createVLineIterator(x2, y, h, false);
500 while (!it.isDone() && found == false) {
501 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
502 boundW = x2 - boundX + 1; // XXX: I commented this
503 // +1 out, but why? It
504 // should be correct, since
505 // we've found the first
506 // pixel that should be
507 // included, and it should
508 // be added to the width.
509 found = true;
510 break;
511 }
512 ++it;
513 }
514 if (found) break;
515 }
516
517 return TQRect(boundX, boundY, boundW, boundH);
518}
519
520TQRect KisPaintDevice::exactBoundsImprovedOldMethod() const
521{
522 // Solution n°2
523 TQ_INT32 x, y, w, h, boundX2, boundY2, boundW2, boundH2;
524 extent(x, y, w, h);
525 extent(boundX2, boundY2, boundW2, boundH2);
526
527 const TQ_UINT8* defaultPixel = m_datamanager->defaultPixel();
528 bool found = false;
529 {
530 KisHLineIterator it = const_cast<KisPaintDevice *>(this)->createHLineIterator(x, y, w, false);
531 for (TQ_INT32 y2 = y; y2 < y + h ; ++y2) {
532 while (!it.isDone() && found == false) {
533 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
534 boundY2 = y2;
535 found = true;
536 break;
537 }
538 ++it;
539 }
540 if (found) break;
541 it.nextRow();
542 }
543 }
544
545 found = false;
546
547 for (TQ_INT32 y2 = y + h; y2 > y ; --y2) {
548 KisHLineIterator it = const_cast<KisPaintDevice *>(this)->createHLineIterator(x, y2, w, false);
549 while (!it.isDone() && found == false) {
550 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
551 boundH2 = y2 - boundY2 + 1;
552 found = true;
553 break;
554 }
555 ++it;
556 }
557 if (found) break;
558 }
559 found = false;
560
561 {
562 KisVLineIterator it = const_cast<KisPaintDevice *>(this)->createVLineIterator(x, boundY2, boundH2, false);
563 for (TQ_INT32 x2 = x; x2 < x + w ; ++x2) {
564 while (!it.isDone() && found == false) {
565 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
566 boundX2 = x2;
567 found = true;
568 break;
569 }
570 ++it;
571 }
572 if (found) break;
573 it.nextCol();
574 }
575 }
576
577 found = false;
578
579 // Look for right edge )
580 {
581 for (TQ_INT32 x2 = x + w; x2 > x ; --x2) {
582 KisVLineIterator it = const_cast<KisPaintDevice *>(this)->createVLineIterator(/*x + w*/ x2, boundY2, boundH2, false);
583 while (!it.isDone() && found == false) {
584 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
585 boundW2 = x2 - boundX2 + 1; // XXX: I commented this
586 // +1 out, but why? It
587 // should be correct, since
588 // we've found the first
589 // pixel that should be
590 // included, and it should
591 // be added to the width.
592 found = true;
593 break;
594 }
595 ++it;
596 }
597 if (found) break;
598 }
599 }
600 return TQRect(boundX2, boundY2, boundW2, boundH2);
601}
602
603
604TQRect KisPaintDevice::exactBounds() const
605{
606 TQRect r2 = exactBoundsImprovedOldMethod();
607 return r2;
608}
609
610void KisPaintDevice::crop(TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h)
611{
612 m_datamanager->setExtent(x - m_x, y - m_y, w, h);
613}
614
615
617{
618 r.moveBy(-m_x, -m_y); m_datamanager->setExtent(r);
619}
620
622{
623 m_datamanager->clear();
624}
625
626void KisPaintDevice::fill(TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h, const TQ_UINT8 *fillPixel)
627{
628 m_datamanager->clear(x, y, w, h, fillPixel);
629}
630
632{
633 TQRect r;
634 if (hasSelection()) {
635 r = selection()->selectedRect();
636 }
637 else {
638 r = exactBounds();
639 }
640
641 for (TQ_INT32 y = r.top(); y <= r.bottom(); ++y) {
642 KisHLineIteratorPixel srcIt = createHLineIterator(r.x(), y, r.width(), false);
643 KisHLineIteratorPixel dstIt = createHLineIterator(r.x(), y, r.width(), true);
644
645 dstIt += r.width() - 1;
646
647 while (!srcIt.isDone()) {
648 if (srcIt.isSelected()) {
649 memcpy(dstIt.rawData(), srcIt.oldRawData(), m_pixelSize);
650 }
651 ++srcIt;
652 --dstIt;
653
654 }
655 }
656 if (m_parentLayer) {
657 m_parentLayer->setDirty(r);
658 }
659}
660
662{
663 /* Read a line from bottom to top and and from top to bottom and write their values to each other */
664 TQRect r;
665 if (hasSelection()) {
666 r = selection()->selectedRect();
667 }
668 else {
669 r = exactBounds();
670 }
671
672
673 TQ_INT32 y1, y2;
674 for (y1 = r.top(), y2 = r.bottom(); y1 <= r.bottom(); ++y1, --y2) {
675 KisHLineIteratorPixel itTop = createHLineIterator(r.x(), y1, r.width(), true);
676 KisHLineIteratorPixel itBottom = createHLineIterator(r.x(), y2, r.width(), false);
677 while (!itTop.isDone() && !itBottom.isDone()) {
678 if (itBottom.isSelected()) {
679 memcpy(itTop.rawData(), itBottom.oldRawData(), m_pixelSize);
680 }
681 ++itBottom;
682 ++itTop;
683 }
684 }
685
686 if (m_parentLayer) {
687 m_parentLayer->setDirty(r);
688 }
689}
690
691KisMementoSP KisPaintDevice::getMemento()
692{
693 return m_datamanager->getMemento();
694}
695
696void KisPaintDevice::rollback(KisMementoSP memento) { m_datamanager->rollback(memento); }
697
698void KisPaintDevice::rollforward(KisMementoSP memento) { m_datamanager->rollforward(memento); }
699
700bool KisPaintDevice::write(KoStore *store)
701{
702 bool retval = m_datamanager->write(store);
703 emit ioProgress(100);
704
705 return retval;
706}
707
708bool KisPaintDevice::read(KoStore *store)
709{
710 bool retval = m_datamanager->read(store);
711 emit ioProgress(100);
712
713 return retval;
714}
715
716void KisPaintDevice::convertTo(KisColorSpace * dstColorSpace, TQ_INT32 renderingIntent)
717{
718 kdDebug(41004) << "Converting " << name() << " to " << dstColorSpace->id().id() << " from "
719 << m_colorSpace->id().id() << "\n";
720 if ( colorSpace() == dstColorSpace )
721 {
722 return;
723 }
724
725 KisPaintDevice dst(dstColorSpace);
726 dst.setX(getX());
727 dst.setY(getY());
728
729 TQ_INT32 x, y, w, h;
730 extent(x, y, w, h);
731
732 for (TQ_INT32 row = y; row < y + h; ++row) {
733
734 TQ_INT32 column = x;
735 TQ_INT32 columnsRemaining = w;
736
737 while (columnsRemaining > 0) {
738
739 TQ_INT32 numContiguousDstColumns = dst.numContiguousColumns(column, row, row);
740 TQ_INT32 numContiguousSrcColumns = numContiguousColumns(column, row, row);
741
742 TQ_INT32 columns = TQMIN(numContiguousDstColumns, numContiguousSrcColumns);
743 columns = TQMIN(columns, columnsRemaining);
744
745 //const TQ_UINT8 *srcData = pixel(column, row);
746 //TQ_UINT8 *dstData = dst.writablePixel(column, row);
747 KisHLineIteratorPixel srcIt = createHLineIterator(column, row, columns, false);
748 KisHLineIteratorPixel dstIt = dst.createHLineIterator(column, row, columns, true);
749
750 const TQ_UINT8 *srcData = srcIt.rawData();
751 TQ_UINT8 *dstData = dstIt.rawData();
752
753
754 m_colorSpace->convertPixelsTo(srcData, dstData, dstColorSpace, columns, renderingIntent);
755
756 column += columns;
757 columnsRemaining -= columns;
758 }
759 }
760
761 KisDataManagerSP oldData = m_datamanager;
762 KisColorSpace *oldColorSpace = m_colorSpace;
763
764 setData(dst.m_datamanager, dstColorSpace);
765
766 if (undoAdapter() && undoAdapter()->undo()) {
767 undoAdapter()->addCommand(new KisConvertLayerTypeCmd(undoAdapter(), this, oldData, oldColorSpace, m_datamanager, m_colorSpace));
768 }
769}
770
771void KisPaintDevice::setProfile(KisProfile * profile)
772{
773 if (profile == 0) return;
774
775 KisColorSpace * dstSpace =
776 KisMetaRegistry::instance()->csRegistry()->getColorSpace( colorSpace()->id(),
777 profile);
778 if (dstSpace)
779 m_colorSpace = dstSpace;
780
781}
782
783void KisPaintDevice::setData(KisDataManagerSP data, KisColorSpace * colorSpace)
784{
785 m_datamanager = data;
786 m_colorSpace = colorSpace;
787 m_pixelSize = m_colorSpace->pixelSize();
788 m_nChannels = m_colorSpace->nChannels();
789
790 if (m_parentLayer) {
791 m_parentLayer->setDirty(extent());
792 m_parentLayer->notifyPropertyChanged();
793 }
794}
795
796KisUndoAdapter *KisPaintDevice::undoAdapter() const
797{
798 if (m_parentLayer && m_parentLayer->image()) {
799 return m_parentLayer->image()->undoAdapter();
800 }
801 return 0;
802}
803
804void KisPaintDevice::convertFromTQImage(const TQImage& image, const TQString &srcProfileName,
805 TQ_INT32 offsetX, TQ_INT32 offsetY)
806{
807 TQImage img = image;
808
809 // Chalk is little-endian inside.
810 if (img.bitOrder() == TQImage::LittleEndian) {
811 img = img.convertBitOrder(TQImage::BigEndian);
812 }
813 kdDebug() << k_funcinfo << img.bitOrder()<< endl;
814 // Chalk likes bgra (convertDepth returns *this is the img is alread 32 bits)
815 img = img.convertDepth( 32 );
816#if 0
817 // XXX: Apply import profile
818 if (colorSpace() == KisMetaRegistry::instance()->csRegistry() ->getColorSpace(KisID("RGBA",""),"")) {
819 writeBytes(img.bits(), 0, 0, img.width(), img.height());
820 }
821 else {
822#endif
823 TQ_UINT8 * dstData = new TQ_UINT8[img.width() * img.height() * pixelSize()];
824 KisMetaRegistry::instance()->csRegistry()
825 ->getColorSpace(KisID("RGBA",""),srcProfileName)->
826 convertPixelsTo(img.bits(), dstData, colorSpace(), img.width() * img.height());
827 writeBytes(dstData, offsetX, offsetY, img.width(), img.height());
828// }
829}
830
831TQImage KisPaintDevice::convertToTQImage(KisProfile * dstProfile, float exposure)
832{
833 TQ_INT32 x1;
834 TQ_INT32 y1;
835 TQ_INT32 w;
836 TQ_INT32 h;
837
838 x1 = - getX();
839 y1 = - getY();
840
841 if (image()) {
842 w = image()->width();
843 h = image()->height();
844 }
845 else {
846 extent(x1, y1, w, h);
847 }
848
849 return convertToTQImage(dstProfile, x1, y1, w, h, exposure);
850}
851
852// XXX: is this faster than building the TQImage ourselves? It makes
853TQImage KisPaintDevice::convertToTQImage(KisProfile * dstProfile, TQ_INT32 x1, TQ_INT32 y1, TQ_INT32 w, TQ_INT32 h, float exposure)
854{
855 if (w < 0)
856 return TQImage();
857
858 if (h < 0)
859 return TQImage();
860
861 TQ_UINT8 * data = new TQ_UINT8 [w * h * m_pixelSize];
862 TQ_CHECK_PTR(data);
863
864 // XXX: Is this really faster than converting line by line and building the TQImage directly?
865 // This copies potentially a lot of data.
866 readBytes(data, x1, y1, w, h);
867 TQImage image = colorSpace()->convertToTQImage(data, w, h, dstProfile, INTENT_PERCEPTUAL, exposure);
868 delete[] data;
869
870 return image;
871}
872
873KisPaintDeviceSP KisPaintDevice::createThumbnailDevice(TQ_INT32 w, TQ_INT32 h)
874{
875 KisPaintDeviceSP thumbnail = new KisPaintDevice(colorSpace(), "thumbnail");
876
877 thumbnail->clear();
878
879 int srcw, srch;
880 if( image() )
881 {
882 srcw = image()->width();
883 srch = image()->height();
884 }
885 else
886 {
887 const TQRect e = exactBounds();
888 srcw = e.width();
889 srch = e.height();
890 }
891
892 if (w > srcw)
893 {
894 w = srcw;
895 h = TQ_INT32(double(srcw) / w * h);
896 }
897 if (h > srch)
898 {
899 h = srch;
900 w = TQ_INT32(double(srch) / h * w);
901 }
902
903 if (srcw > srch)
904 h = TQ_INT32(double(srch) / srcw * w);
905 else if (srch > srcw)
906 w = TQ_INT32(double(srcw) / srch * h);
907
908 for (TQ_INT32 y=0; y < h; ++y) {
909 TQ_INT32 iY = (y * srch ) / h;
910 for (TQ_INT32 x=0; x < w; ++x) {
911 TQ_INT32 iX = (x * srcw ) / w;
912 thumbnail->setPixel(x, y, colorAt(iX, iY));
913 }
914 }
915
916 return thumbnail;
917
918}
919
920
921TQImage KisPaintDevice::createThumbnail(TQ_INT32 w, TQ_INT32 h)
922{
923 int srcw, srch;
924 if( image() )
925 {
926 srcw = image()->width();
927 srch = image()->height();
928 }
929 else
930 {
931 const TQRect e = extent();
932 srcw = e.width();
933 srch = e.height();
934 }
935
936 if (w > srcw)
937 {
938 w = srcw;
939 h = TQ_INT32(double(srcw) / w * h);
940 }
941 if (h > srch)
942 {
943 h = srch;
944 w = TQ_INT32(double(srch) / h * w);
945 }
946
947 if (srcw > srch)
948 h = TQ_INT32(double(srch) / srcw * w);
949 else if (srch > srcw)
950 w = TQ_INT32(double(srcw) / srch * h);
951
952 TQColor c;
953 TQ_UINT8 opacity;
954 TQImage img(w,h,32);
955
956 for (TQ_INT32 y=0; y < h; ++y) {
957 TQ_INT32 iY = (y * srch ) / h;
958 for (TQ_INT32 x=0; x < w; ++x) {
959 TQ_INT32 iX = (x * srcw ) / w;
960 pixel(iX, iY, &c, &opacity);
961 const TQRgb rgb = c.rgb();
962 img.setPixel(x, y, tqRgba(tqRed(rgb), tqGreen(rgb), tqBlue(rgb), opacity));
963 }
964 }
965
966 return img;
967}
968
969KisRectIteratorPixel KisPaintDevice::createRectIterator(TQ_INT32 left, TQ_INT32 top, TQ_INT32 w, TQ_INT32 h, bool writable)
970{
971 if(hasSelection())
972 return KisRectIteratorPixel(this, m_datamanager, m_selection->m_datamanager, left, top, w, h, m_x, m_y, writable);
973 else
974 return KisRectIteratorPixel(this, m_datamanager, NULL, left, top, w, h, m_x, m_y, writable);
975}
976
977KisHLineIteratorPixel KisPaintDevice::createHLineIterator(TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, bool writable)
978{
979 if(hasSelection())
980 return KisHLineIteratorPixel(this, m_datamanager, m_selection->m_datamanager, x, y, w, m_x, m_y, writable);
981 else
982 return KisHLineIteratorPixel(this, m_datamanager, NULL, x, y, w, m_x, m_y, writable);
983}
984
985KisVLineIteratorPixel KisPaintDevice::createVLineIterator(TQ_INT32 x, TQ_INT32 y, TQ_INT32 h, bool writable)
986{
987 if(hasSelection())
988 return KisVLineIteratorPixel(this, m_datamanager, m_selection->m_datamanager, x, y, h, m_x, m_y, writable);
989 else
990 return KisVLineIteratorPixel(this, m_datamanager, NULL, x, y, h, m_x, m_y, writable);
991
992}
993
994KisRandomAccessorPixel KisPaintDevice::createRandomAccessor(TQ_INT32 x, TQ_INT32 y, bool writable) {
995 if(hasSelection())
996 return KisRandomAccessorPixel(m_datamanager, m_selection->m_datamanager, x, y, m_x, m_y, writable);
997 else
998 return KisRandomAccessorPixel(m_datamanager, NULL, x, y, m_x, m_y, writable);
999}
1000
1002{
1003 return KisRandomSubAccessorPixel(this);
1004}
1005
1007{
1008 if (m_parentLayer && m_parentLayer->image()) {
1009 m_parentLayer->image()->slotSelectionChanged();
1010 }
1011}
1012
1014{
1015 if (m_parentLayer && m_parentLayer->image()) {
1016 m_parentLayer->image()->slotSelectionChanged(r);
1017 }
1018}
1019
1021{
1022 if ( m_selectionDeselected && m_selection ) {
1023 m_selectionDeselected = false;
1024 }
1025 else if (!m_selection) {
1026 m_selection = new KisSelection(this);
1027 TQ_CHECK_PTR(m_selection);
1028 m_selection->setX(m_x);
1029 m_selection->setY(m_y);
1030 }
1031 m_hasSelection = true;
1032
1033 return m_selection;
1034}
1035
1036
1038{
1039 return m_hasSelection;
1040}
1041
1043{
1044 return m_selectionDeselected;
1045}
1046
1047
1049{
1050 if (m_selection && m_hasSelection) {
1051 m_hasSelection = false;
1052 m_selectionDeselected = true;
1053 }
1054}
1055
1057{
1058 m_hasSelection = true;
1059 m_selectionDeselected = false;
1060}
1061
1063
1064 KisPainter painter(this->selection().data());
1065 TQRect r = selection->selectedExactRect();
1066 painter.bitBlt(r.x(), r.y(), COMPOSITE_OVER, selection.data(), r.x(), r.y(), r.width(), r.height());
1067 painter.end();
1068}
1069
1071 KisPainter painter(this->selection().data());
1072 selection->invert();
1073
1074 TQRect r = selection->selectedExactRect();
1075 painter.bitBlt(r.x(), r.y(), COMPOSITE_ERASE, selection.data(), r.x(), r.y(), r.width(), r.height());
1076
1077 selection->invert();
1078 painter.end();
1079}
1080
1082{
1083 if (!hasSelection()) return;
1084
1085 TQRect r = m_selection->selectedExactRect();
1086
1087 if (r.isValid()) {
1088
1089 for (TQ_INT32 y = 0; y < r.height(); y++) {
1090
1091 KisHLineIterator devIt = createHLineIterator(r.x(), r.y() + y, r.width(), true);
1092 KisHLineIterator selectionIt = m_selection->createHLineIterator(r.x(), r.y() + y, r.width(), false);
1093
1094 while (!devIt.isDone()) {
1095 // XXX: Optimize by using stretches
1096
1097 m_colorSpace->applyInverseAlphaU8Mask( devIt.rawData(), selectionIt.rawData(), 1);
1098
1099 ++devIt;
1100 ++selectionIt;
1101 }
1102 }
1103
1104 if (m_parentLayer) {
1105 m_parentLayer->setDirty(r);
1106 }
1107 }
1108}
1109
1110void KisPaintDevice::applySelectionMask(KisSelectionSP mask)
1111{
1112 TQRect r = mask->selectedRect();
1113 crop(r);
1114
1115 for (TQ_INT32 y = r.top(); y <= r.bottom(); ++y) {
1116
1117 KisHLineIterator pixelIt = createHLineIterator(r.x(), y, r.width(), true);
1118 KisHLineIterator maskIt = mask->createHLineIterator(r.x(), y, r.width(), false);
1119
1120 while (!pixelIt.isDone()) {
1121 // XXX: Optimize by using stretches
1122
1123 m_colorSpace->applyAlphaU8Mask( pixelIt.rawData(), maskIt.rawData(), 1);
1124
1125 ++pixelIt;
1126 ++maskIt;
1127 }
1128 }
1129}
1130
1131KisSelectionSP KisPaintDevice::setSelection( KisSelectionSP selection)
1132{
1133 if (selection) {
1134 KisSelectionSP oldSelection = m_selection;
1135 m_selection = selection;
1136 m_hasSelection = true;
1137 return oldSelection;
1138 }
1139 else return 0;
1140}
1141
1142bool KisPaintDevice::pixel(TQ_INT32 x, TQ_INT32 y, TQColor *c, TQ_UINT8 *opacity)
1143{
1144 KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, false);
1145
1146 TQ_UINT8 *pix = iter.rawData();
1147
1148 if (!pix) return false;
1149
1150 colorSpace()->toTQColor(pix, c, opacity);
1151
1152 return true;
1153}
1154
1155
1156bool KisPaintDevice::pixel(TQ_INT32 x, TQ_INT32 y, KisColor * kc)
1157{
1158 KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, false);
1159
1160 TQ_UINT8 *pix = iter.rawData();
1161
1162 if (!pix) return false;
1163
1164 kc->setColor(pix, m_colorSpace);
1165
1166 return true;
1167}
1168
1169KisColor KisPaintDevice::colorAt(TQ_INT32 x, TQ_INT32 y)
1170{
1171 //return KisColor(m_datamanager->pixel(x - m_x, y - m_y), m_colorSpace);
1172 KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, true);
1173 return KisColor(iter.rawData(), m_colorSpace);
1174}
1175
1176bool KisPaintDevice::setPixel(TQ_INT32 x, TQ_INT32 y, const TQColor& c, TQ_UINT8 opacity)
1177{
1178 KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, true);
1179
1180 colorSpace()->fromTQColor(c, opacity, iter.rawData());
1181
1182 return true;
1183}
1184
1185bool KisPaintDevice::setPixel(TQ_INT32 x, TQ_INT32 y, const KisColor& kc)
1186{
1187 TQ_UINT8 * pix;
1188 if (kc.colorSpace() != m_colorSpace) {
1189 KisColor kc2 (kc, m_colorSpace);
1190 pix = kc2.data();
1191 }
1192 else {
1193 pix = kc.data();
1194 }
1195
1196 KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, true);
1197 memcpy(iter.rawData(), pix, m_colorSpace->pixelSize());
1198
1199 return true;
1200}
1201
1202
1203TQ_INT32 KisPaintDevice::numContiguousColumns(TQ_INT32 x, TQ_INT32 minY, TQ_INT32 maxY)
1204{
1205 return m_datamanager->numContiguousColumns(x - m_x, minY - m_y, maxY - m_y);
1206}
1207
1208TQ_INT32 KisPaintDevice::numContiguousRows(TQ_INT32 y, TQ_INT32 minX, TQ_INT32 maxX)
1209{
1210 return m_datamanager->numContiguousRows(y - m_y, minX - m_x, maxX - m_x);
1211}
1212
1213TQ_INT32 KisPaintDevice::rowStride(TQ_INT32 x, TQ_INT32 y)
1214{
1215 return m_datamanager->rowStride(x - m_x, y - m_y);
1216}
1217
1218const TQ_UINT8* KisPaintDevice::pixel(TQ_INT32 x, TQ_INT32 y)
1219{
1220 return m_datamanager->pixel(x - m_x, y - m_y);
1221}
1222
1223TQ_UINT8* KisPaintDevice::writablePixel(TQ_INT32 x, TQ_INT32 y)
1224{
1225 return m_datamanager->writablePixel(x - m_x, y - m_y);
1226}
1227
1228void KisPaintDevice::setX(TQ_INT32 x)
1229{
1230 m_x = x;
1231 if(m_selection && m_selection != this)
1232 m_selection->setX(x);
1233}
1234
1235void KisPaintDevice::setY(TQ_INT32 y)
1236{
1237 m_y = y;
1238 if(m_selection && m_selection != this)
1239 m_selection->setY(y);
1240}
1241
1242
1243void KisPaintDevice::readBytes(TQ_UINT8 * data, TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h)
1244{
1245 m_datamanager->readBytes(data, x - m_x, y - m_y, w, h);
1246}
1247
1248void KisPaintDevice::writeBytes(const TQ_UINT8 * data, TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h)
1249{
1250 m_datamanager->writeBytes( data, x - m_x, y - m_y, w, h);
1251}
1252
1253
1254KisDataManagerSP KisPaintDevice::dataManager() const
1255{
1256 return m_datamanager;
1257}
1258
1260{
1261 if(!m_exifInfo)
1262 m_exifInfo = new KisExifInfo();
1263 return m_exifInfo;
1264}
1265
1266void KisPaintDevice::runBackgroundFilters()
1267{
1268 if ( m_lock ) return;
1269
1270 KisTransaction * cmd = new KisTransaction("Running autofilters", this);
1271
1272 TQRect rc = extent();
1273 if (!m_longRunningFilters.isEmpty()) {
1274 TQValueList<KisFilter*>::iterator it;
1275 TQValueList<KisFilter*>::iterator end = m_longRunningFilters.end();
1276 for (it = m_longRunningFilters.begin(); it != end; ++it) {
1277 (*it)->process(this, this, 0, rc);
1278 }
1279 }
1280 if (cmd && undoAdapter()) undoAdapter()->addCommand(cmd);
1281
1282 if (m_parentLayer) m_parentLayer->setDirty(rc);
1283}
1284
1285#include "kis_paint_device.moc"
A colorspace is the definition of a certain color model in Chalk.
virtual KisID id() const =0
Chalk definition for use in .kra files and internally: unchanging name + i18n'able description.
A KisColor describes a color in a certain colorspace.
Definition kis_color.h:33
void setColor(TQ_UINT8 *data, KisColorSpace *colorSpace=0)
Replace the existing color data, and colorspace with the specified data.
TQ_UINT8 * data() const
For easy memcpy'ing etc.
Definition kis_color.h:62
KisDataManager defines the interface that modules responsible for storing and retrieving data must in...
The pixel iterators are high level iterarators.
Chalk has a large number of extensible resources.
Definition kis_id.h:57
Abstract class that represents the concept of a Layer in Chalk.
Definition kis_layer.h:42
A paint device contains the actual pixel data and offers methods to read and write pixels.
void mirrorX()
Mirror the device along the X axis.
KisImage * image() const
Return the image that contains this paint device, or 0 if it is not part of an image.
virtual TQImage convertToTQImage(KisProfile *dstProfile, TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h, float exposure=0.0f)
Create an RGBA TQImage from a rectangle in the paint device.
KisRandomSubAccessorPixel createRandomSubAccessor()
This function create a random accessor which can easily access to sub pixel values.
KisRectIteratorPixel createRectIterator(TQ_INT32 left, TQ_INT32 top, TQ_INT32 w, TQ_INT32 h, bool writable)
This function return an iterator which points to the first pixel of an rectangle.
KisPaintDevice(KisColorSpace *colorSpace, const char *name=0)
Create a new paint device with the specified colorspace.
TQ_INT32 rowStride(TQ_INT32 x, TQ_INT32 y)
Get the row stride at pixel (x, y).
virtual void writeBytes(const TQ_UINT8 *data, TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h)
Copy the bytes in data into the rect specified by x, y, w, h.
KisVLineIteratorPixel createVLineIterator(TQ_INT32 x, TQ_INT32 y, TQ_INT32 h, bool writable)
This function return an iterator which points to the first pixel of a vertical line.
virtual bool read(KoStore *store)
Fill this paint device with the pixels from the specified file store.
KisLayer * parentLayer() const
Returns the KisLayer that contains this paint device, or 0 if this is not part of a layer.
virtual void clear()
Complete erase the current paint device.
TDE_DEPRECATED const TQ_UINT8 * pixel(TQ_INT32 x, TQ_INT32 y)
Get a read-only pointer to pixel (x, y).
virtual void readBytes(TQ_UINT8 *data, TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h)
Read the bytes representing the rectangle described by x, y, w, h into data.
virtual void setProfile(KisProfile *profile)
Changes the profile of the colorspace of this paint device to the given profile.
void deselect()
Deselect the selection for this paintdevice.
KisColor colorAt(TQ_INT32 x, TQ_INT32 y)
Return the KisColor of the pixel at x,y.
KisExifInfo * exifInfo()
Return the exifInfo associated with this layer.
KisSelectionSP selection()
Get the current selection or create one if this paintdevice hasn't got a selection yet.
void setParentLayer(KisLayer *parentLayer)
Set the KisLayer that contains this paint device, or 0 if this is not part of a layer.
void clearSelection()
Clear the selected pixels from the paint device.
void addSelection(KisSelectionSP selection)
Adds the specified selection to the currently active selection for this paintdevice.
bool selectionDeselected()
Whether the previous selection was deselected.
TQ_INT32 getX() const
The X offset of the paint device.
virtual void convertTo(KisColorSpace *dstColorSpace, TQ_INT32 renderingIntent=INTENT_PERCEPTUAL)
Converts the paint device to a different colorspace.
TQ_INT32 numContiguousRows(TQ_INT32 y, TQ_INT32 minX, TQ_INT32 maxX)
Get the number of contiguous rows starting at y, valid for all values of x between minX and maxX.
TQ_INT32 getY() const
The Y offset of the paint device.
virtual KNamedCommand * moveCommand(TQ_INT32 x, TQ_INT32 y)
Move the paint device to the specified location and make it possible to undo the move.
TDE_DEPRECATED TQ_UINT8 * writablePixel(TQ_INT32 x, TQ_INT32 y)
Get a read-write pointer to pixel (x, y).
virtual void setDirty()
Set the parent layer completely dirty, if this paint device has one.
virtual void convertFromTQImage(const TQImage &img, const TQString &srcProfileName, TQ_INT32 offsetX=0, TQ_INT32 offsetY=0)
Fill this paint device with the data from img; starting at (offsetX, offsetY).
void crop(TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h)
Cut the paint device down to the specified rect.
KisPaintDeviceSP createThumbnailDevice(TQ_INT32 w, TQ_INT32 h)
Creates a paint device thumbnail of the paint device, retaining the aspect ratio.
void reselect()
Reinstates the old selection.
bool extentIsValid() const
XXX: This should be a temporay hack, awaiting a proper fix.
virtual TQ_INT32 pixelSize() const
Return the number of bytes a pixel takes.
void setX(TQ_INT32 x)
Return the X offset of the paint device.
virtual bool write(KoStore *store)
Write the pixels of this paint device into the specified file store.
virtual void move(TQ_INT32 x, TQ_INT32 y)
Moves the device to these new coordinates (so no incremental move or so).
void applySelectionMask(KisSelectionSP mask)
Apply a mask to the image data, i.e.
void mirrorY()
Mirror the device along the Y axis.
KisSelectionSP setSelection(KisSelectionSP selection)
Sets the selection of this paint device to the new selection, returns the old selection,...
void setY(TQ_INT32 y)
Return the Y offset of the paint device.
KisHLineIteratorPixel createHLineIterator(TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, bool writable)
This function return an iterator which points to the first pixel of a horizontal line.
KisRandomAccessorPixel createRandomAccessor(TQ_INT32 x, TQ_INT32 y, bool writable)
This function creates a random accessor which allow to randomly access any pixels on the paint device...
void emitSelectionChanged()
Notify the owning image that the current selection has changed.
bool setPixel(TQ_INT32 x, TQ_INT32 y, const TQColor &c, TQ_UINT8 opacity)
Set the specified pixel to the specified color.
bool hasSelection()
Whether there is a valid selection for this paintdevice.
void setExtentIsValid(bool isValid)
Convience method for the above.
virtual void extent(TQ_INT32 &x, TQ_INT32 &y, TQ_INT32 &w, TQ_INT32 &h) const
Retrieve the bounds of the paint device.
TQ_INT32 numContiguousColumns(TQ_INT32 x, TQ_INT32 minY, TQ_INT32 maxY)
Get the number of contiguous columns starting at x, valid for all values of y between minY and maxY.
virtual void exactBounds(TQ_INT32 &x, TQ_INT32 &y, TQ_INT32 &w, TQ_INT32 &h) const
Get the exact bounds of this paint device.
void subtractSelection(KisSelectionSP selection)
Subtracts the specified selection from the currently active selection for this paindevice.
void setData(KisDataManagerSP data, KisColorSpace *colorSpace)
Replace the pixel data, color strategy, and profile.
virtual TQImage createThumbnail(TQ_INT32 maxw, TQ_INT32 maxh)
Creates a thumbnail of the paint device, retaining the aspect ratio.
void fill(TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h, const TQ_UINT8 *fillPixel)
Fill the given rectangle with the given pixel.
KisPainter contains the graphics primitives necessary to draw on a KisPaintDevice.
Definition kis_painter.h:56
KCommand * end()
Finish painting on the current device.
void bitBlt(TQ_INT32 dx, TQ_INT32 dy, const KisCompositeOp &op, KisPaintDeviceSP src, TQ_INT32 sx, TQ_INT32 sy, TQ_INT32 sw, TQ_INT32 sh)
Blast the specified region from src onto the current paint device.
KisSelection contains a byte-map representation of a layer, where the value of a byte signifies wheth...