00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <qrect.h>
00020 #include <qwmatrix.h>
00021 #include <qimage.h>
00022 #include <qdatetime.h>
00023 #include <qapplication.h>
00024 #include <qvaluelist.h>
00025 #include <qtimer.h>
00026
00027 #include <kcommand.h>
00028 #include <klocale.h>
00029 #include <kdebug.h>
00030
00031 #include <KoStore.h>
00032
00033 #include "kis_global.h"
00034 #include "kis_types.h"
00035 #include "kis_painter.h"
00036 #include "kis_fill_painter.h"
00037 #include "kis_undo_adapter.h"
00038 #include "kis_iterator.h"
00039 #include "kis_iterators_pixel.h"
00040 #include "kis_iteratorpixeltrait.h"
00041 #include "kis_random_accessor.h"
00042 #include "kis_random_sub_accessor.h"
00043 #include "kis_profile.h"
00044 #include "kis_color.h"
00045 #include "kis_integer_maths.h"
00046 #include "kis_colorspace_factory_registry.h"
00047 #include "kis_selection.h"
00048 #include "kis_layer.h"
00049 #include "kis_paint_device_iface.h"
00050 #include "kis_paint_device.h"
00051 #include "kis_datamanager.h"
00052 #include "kis_memento.h"
00053
00054 #include "kis_exif_info.h"
00055
00056 namespace {
00057
00058 class KisPaintDeviceCommand : public KNamedCommand {
00059 typedef KNamedCommand super;
00060
00061 public:
00062 KisPaintDeviceCommand(const QString& name, KisPaintDeviceSP paintDevice);
00063 virtual ~KisPaintDeviceCommand() {}
00064
00065 virtual void execute() = 0;
00066 virtual void unexecute() = 0;
00067
00068 protected:
00069 void setUndo(bool undo);
00070
00071 KisPaintDeviceSP m_paintDevice;
00072 };
00073
00074 KisPaintDeviceCommand::KisPaintDeviceCommand(const QString& name, KisPaintDeviceSP paintDevice) :
00075 super(name), m_paintDevice(paintDevice)
00076 {
00077 }
00078
00079 void KisPaintDeviceCommand::setUndo(bool undo)
00080 {
00081 if (m_paintDevice->undoAdapter()) {
00082 m_paintDevice->undoAdapter()->setUndo(undo);
00083 }
00084 }
00085
00086 class MoveCommand : public KNamedCommand {
00087 typedef KNamedCommand super;
00088
00089 public:
00090 MoveCommand(KisPaintDeviceSP device, const QPoint& oldpos, const QPoint& newpos);
00091 virtual ~MoveCommand();
00092
00093 virtual void execute();
00094 virtual void unexecute();
00095
00096 private:
00097 void moveTo(const QPoint& pos);
00098 void undoOff();
00099 void undoOn();
00100
00101 private:
00102 KisPaintDeviceSP m_device;
00103 QPoint m_oldPos;
00104 QPoint m_newPos;
00105 };
00106
00107 MoveCommand::MoveCommand(KisPaintDeviceSP device, const QPoint& oldpos, const QPoint& newpos) :
00108 super(i18n("Move Layer"))
00109 {
00110 m_device = device;
00111 m_oldPos = oldpos;
00112 m_newPos = newpos;
00113 }
00114
00115 MoveCommand::~MoveCommand()
00116 {
00117 }
00118
00119 void MoveCommand::undoOff()
00120 {
00121 if (m_device->undoAdapter()) {
00122 m_device->undoAdapter()->setUndo(false);
00123 }
00124 }
00125
00126 void MoveCommand::undoOn()
00127 {
00128 if (m_device->undoAdapter()) {
00129 m_device->undoAdapter()->setUndo(true);
00130 }
00131 }
00132
00133 void MoveCommand::execute()
00134 {
00135 undoOff();
00136 moveTo(m_newPos);
00137 undoOn();
00138 }
00139
00140 void MoveCommand::unexecute()
00141 {
00142 undoOff();
00143 moveTo(m_oldPos);
00144 undoOn();
00145 }
00146
00147 void MoveCommand::moveTo(const QPoint& pos)
00148 {
00149 m_device->move(pos.x(), pos.y());
00150 }
00151
00152 class KisConvertLayerTypeCmd : public KNamedCommand {
00153 typedef KNamedCommand super;
00154
00155 public:
00156 KisConvertLayerTypeCmd(KisUndoAdapter *adapter, KisPaintDeviceSP paintDevice,
00157 KisDataManagerSP beforeData, KisColorSpace * beforeColorSpace,
00158 KisDataManagerSP afterData, KisColorSpace * afterColorSpace
00159 ) : super(i18n("Convert Layer Type"))
00160 {
00161 m_adapter = adapter;
00162 m_paintDevice = paintDevice;
00163 m_beforeData = beforeData;
00164 m_beforeColorSpace = beforeColorSpace;
00165 m_afterData = afterData;
00166 m_afterColorSpace = afterColorSpace;
00167 }
00168
00169 virtual ~KisConvertLayerTypeCmd()
00170 {
00171 }
00172
00173 public:
00174 virtual void execute()
00175 {
00176 m_adapter->setUndo(false);
00177 m_paintDevice->setData(m_afterData, m_afterColorSpace);
00178 m_adapter->setUndo(true);
00179 }
00180
00181 virtual void unexecute()
00182 {
00183 m_adapter->setUndo(false);
00184 m_paintDevice->setData(m_beforeData, m_beforeColorSpace);
00185 m_adapter->setUndo(true);
00186 }
00187
00188 private:
00189 KisUndoAdapter *m_adapter;
00190
00191 KisPaintDeviceSP m_paintDevice;
00192
00193 KisDataManagerSP m_beforeData;
00194 KisColorSpace * m_beforeColorSpace;
00195
00196 KisDataManagerSP m_afterData;
00197 KisColorSpace * m_afterColorSpace;
00198 };
00199
00200 }
00201
00202 KisPaintDevice::KisPaintDevice(KisColorSpace * colorSpace, const char * name) :
00203 QObject(0, name), KShared(), m_exifInfo(0)
00204 {
00205 if (colorSpace == 0) {
00206 kdWarning(41001) << "Cannot create paint device without colorstrategy!\n";
00207 return;
00208 }
00209 m_longRunningFilterTimer = 0;
00210 m_dcop = 0;
00211
00212 m_x = 0;
00213 m_y = 0;
00214
00215 m_pixelSize = colorSpace->pixelSize();
00216 m_nChannels = colorSpace->nChannels();
00217
00218 Q_UINT8* defPixel = new Q_UINT8 [ m_pixelSize ];
00219 colorSpace->fromQColor(Qt::black, OPACITY_TRANSPARENT, defPixel);
00220
00221 m_datamanager = new KisDataManager(m_pixelSize, defPixel);
00222 delete [] defPixel;
00223
00224 Q_CHECK_PTR(m_datamanager);
00225 m_extentIsValid = true;
00226
00227 m_parentLayer = 0;
00228
00229 m_colorSpace = colorSpace;
00230
00231 m_hasSelection = false;
00232 m_selectionDeselected = false;
00233 m_selection = 0;
00234
00235 m_longRunningFilters = colorSpace->createBackgroundFilters();
00236 if (!m_longRunningFilters.isEmpty()) {
00237 m_longRunningFilterTimer = new QTimer(this);
00238 connect(m_longRunningFilterTimer, SIGNAL(timeout()), this, SLOT(runBackgroundFilters()));
00239 m_longRunningFilterTimer->start(800);
00240 }
00241 }
00242
00243 KisPaintDevice::KisPaintDevice(KisLayer *parent, KisColorSpace * colorSpace, const char * name) :
00244 QObject(0, name), KShared(), m_exifInfo(0)
00245 {
00246
00247 m_longRunningFilterTimer = 0;
00248 m_dcop = 0;
00249
00250 m_x = 0;
00251 m_y = 0;
00252
00253 m_hasSelection = false;
00254 m_selectionDeselected = false;
00255 m_selection = 0;
00256
00257 m_parentLayer = parent;
00258
00259 if (colorSpace == 0 && parent != 0 && parent->image() != 0) {
00260 m_colorSpace = parent->image()->colorSpace();
00261 }
00262 else {
00263 m_colorSpace = colorSpace;
00264 }
00265
00266 Q_ASSERT( m_colorSpace );
00267
00268 m_pixelSize = m_colorSpace->pixelSize();
00269 m_nChannels = m_colorSpace->nChannels();
00270
00271 Q_UINT8* defPixel = new Q_UINT8[ m_pixelSize ];
00272 m_colorSpace->fromQColor(Qt::black, OPACITY_TRANSPARENT, defPixel);
00273
00274 m_datamanager = new KisDataManager(m_pixelSize, defPixel);
00275 delete [] defPixel;
00276 Q_CHECK_PTR(m_datamanager);
00277 m_extentIsValid = true;
00278
00279
00280 m_longRunningFilters = m_colorSpace->createBackgroundFilters();
00281 if (!m_longRunningFilters.isEmpty()) {
00282 m_longRunningFilterTimer = new QTimer(this);
00283 connect(m_longRunningFilterTimer, SIGNAL(timeout()), this, SLOT(runBackgroundFilters()));
00284 m_longRunningFilterTimer->start(800);
00285 }
00286 }
00287
00288
00289 KisPaintDevice::KisPaintDevice(const KisPaintDevice& rhs) : QObject(), KShared(rhs)
00290 {
00291 if (this != &rhs) {
00292 m_longRunningFilterTimer = 0;
00293 m_parentLayer = 0;
00294 m_dcop = rhs.m_dcop;
00295 if (rhs.m_datamanager) {
00296 m_datamanager = new KisDataManager(*rhs.m_datamanager);
00297 Q_CHECK_PTR(m_datamanager);
00298 }
00299 else {
00300 kdWarning() << "rhs " << rhs.name() << " has no datamanager\n";
00301 }
00302 m_extentIsValid = rhs.m_extentIsValid;
00303 m_x = rhs.m_x;
00304 m_y = rhs.m_y;
00305 m_colorSpace = rhs.m_colorSpace;
00306 m_hasSelection = false;
00307 m_selection = 0;
00308 m_pixelSize = rhs.m_pixelSize;
00309 m_nChannels = rhs.m_nChannels;
00310 if(rhs.m_exifInfo)
00311 {
00312 m_exifInfo = new KisExifInfo(*rhs.m_exifInfo);
00313 }
00314 else {
00315 m_exifInfo = 0;
00316 }
00317 }
00318 }
00319
00320 KisPaintDevice::~KisPaintDevice()
00321 {
00322 delete m_dcop;
00323 delete m_longRunningFilterTimer;
00324 QValueList<KisFilter*>::iterator it;
00325 QValueList<KisFilter*>::iterator end = m_longRunningFilters.end();
00326 for (it = m_longRunningFilters.begin(); it != end; ++it) {
00327 KisFilter * f = (*it);
00328 delete f;
00329 }
00330 m_longRunningFilters.clear();
00331
00332 }
00333
00334 DCOPObject *KisPaintDevice::dcopObject()
00335 {
00336 if (!m_dcop) {
00337 m_dcop = new KisPaintDeviceIface(this);
00338 Q_CHECK_PTR(m_dcop);
00339 }
00340 return m_dcop;
00341 }
00342
00343 KisLayer *KisPaintDevice::parentLayer() const
00344 {
00345 return m_parentLayer;
00346 }
00347
00348 void KisPaintDevice::setParentLayer(KisLayer *parentLayer)
00349 {
00350 m_parentLayer = parentLayer;
00351 }
00352
00353 void KisPaintDevice::setDirty(const QRect & rc)
00354 {
00355 if (m_parentLayer) m_parentLayer->setDirty(rc);
00356 }
00357
00358 void KisPaintDevice::setDirty()
00359 {
00360 if (m_parentLayer) m_parentLayer->setDirty();
00361 }
00362
00363 KisImage *KisPaintDevice::image() const
00364 {
00365 if (m_parentLayer) {
00366 return m_parentLayer->image();
00367 } else {
00368 return 0;
00369 }
00370 }
00371
00372
00373 void KisPaintDevice::move(Q_INT32 x, Q_INT32 y)
00374 {
00375 QRect dirtyRect = extent();
00376
00377 m_x = x;
00378 m_y = y;
00379
00380 dirtyRect |= extent();
00381
00382 if(m_selection)
00383 {
00384 m_selection->setX(x);
00385 m_selection->setY(y);
00386 }
00387
00388 setDirty(dirtyRect);
00389
00390 emit positionChanged(this);
00391 }
00392
00393 void KisPaintDevice::move(const QPoint& pt)
00394 {
00395 move(pt.x(), pt.y());
00396 }
00397
00398 KNamedCommand * KisPaintDevice::moveCommand(Q_INT32 x, Q_INT32 y)
00399 {
00400 KNamedCommand * cmd = new MoveCommand(this, QPoint(m_x, m_y), QPoint(x, y));
00401 Q_CHECK_PTR(cmd);
00402 cmd->execute();
00403 return cmd;
00404 }
00405
00406 void KisPaintDevice::extent(Q_INT32 &x, Q_INT32 &y, Q_INT32 &w, Q_INT32 &h) const
00407 {
00408 m_datamanager->extent(x, y, w, h);
00409 x += m_x;
00410 y += m_y;
00411 }
00412
00413 QRect KisPaintDevice::extent() const
00414 {
00415 Q_INT32 x, y, w, h;
00416 extent(x, y, w, h);
00417 return QRect(x, y, w, h);
00418 }
00419
00420 bool KisPaintDevice::extentIsValid() const
00421 {
00422 return m_extentIsValid;
00423 }
00424
00425 void KisPaintDevice::setExtentIsValid(bool isValid)
00426 {
00427 m_extentIsValid = isValid;
00428 }
00429
00430 void KisPaintDevice::exactBounds(Q_INT32 &x, Q_INT32 &y, Q_INT32 &w, Q_INT32 &h) const
00431 {
00432 QRect r = exactBounds();
00433 x = r.x();
00434 y = r.y();
00435 w = r.width();
00436 h = r.height();
00437 }
00438
00439 QRect KisPaintDevice::exactBoundsOldMethod() const
00440 {
00441 Q_INT32 x, y, w, h, boundX, boundY, boundW, boundH;
00442 extent(x, y, w, h);
00443
00444 extent(boundX, boundY, boundW, boundH);
00445
00446 const Q_UINT8* defaultPixel = m_datamanager->defaultPixel();
00447
00448 bool found = false;
00449
00450 for (Q_INT32 y2 = y; y2 < y + h ; ++y2) {
00451 KisHLineIterator it = const_cast<KisPaintDevice *>(this)->createHLineIterator(x, y2, w, false);
00452 while (!it.isDone() && found == false) {
00453 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
00454 boundY = y2;
00455 found = true;
00456 break;
00457 }
00458 ++it;
00459 }
00460 if (found) break;
00461 }
00462
00463 found = false;
00464
00465 for (Q_INT32 y2 = y + h; y2 > y ; --y2) {
00466 KisHLineIterator it = const_cast<KisPaintDevice *>(this)->createHLineIterator(x, y2, w, false);
00467 while (!it.isDone() && found == false) {
00468 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
00469 boundH = y2 - boundY + 1;
00470 found = true;
00471 break;
00472 }
00473 ++it;
00474 }
00475 if (found) break;
00476 }
00477 found = false;
00478
00479 for (Q_INT32 x2 = x; x2 < x + w ; ++x2) {
00480 KisVLineIterator it = const_cast<KisPaintDevice *>(this)->createVLineIterator(x2, y, h, false);
00481 while (!it.isDone() && found == false) {
00482 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
00483 boundX = x2;
00484 found = true;
00485 break;
00486 }
00487 ++it;
00488 }
00489 if (found) break;
00490 }
00491
00492 found = false;
00493
00494
00495 for (Q_INT32 x2 = x + w; x2 > x ; --x2) {
00496 KisVLineIterator it = const_cast<KisPaintDevice *>(this)->createVLineIterator(x2, y, h, false);
00497 while (!it.isDone() && found == false) {
00498 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
00499 boundW = x2 - boundX + 1;
00500
00501
00502
00503
00504
00505
00506 found = true;
00507 break;
00508 }
00509 ++it;
00510 }
00511 if (found) break;
00512 }
00513
00514 return QRect(boundX, boundY, boundW, boundH);
00515 }
00516
00517 QRect KisPaintDevice::exactBoundsImprovedOldMethod() const
00518 {
00519
00520 Q_INT32 x, y, w, h, boundX2, boundY2, boundW2, boundH2;
00521 extent(x, y, w, h);
00522 extent(boundX2, boundY2, boundW2, boundH2);
00523
00524 const Q_UINT8* defaultPixel = m_datamanager->defaultPixel();
00525 bool found = false;
00526 {
00527 KisHLineIterator it = const_cast<KisPaintDevice *>(this)->createHLineIterator(x, y, w, false);
00528 for (Q_INT32 y2 = y; y2 < y + h ; ++y2) {
00529 while (!it.isDone() && found == false) {
00530 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
00531 boundY2 = y2;
00532 found = true;
00533 break;
00534 }
00535 ++it;
00536 }
00537 if (found) break;
00538 it.nextRow();
00539 }
00540 }
00541
00542 found = false;
00543
00544 for (Q_INT32 y2 = y + h; y2 > y ; --y2) {
00545 KisHLineIterator it = const_cast<KisPaintDevice *>(this)->createHLineIterator(x, y2, w, false);
00546 while (!it.isDone() && found == false) {
00547 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
00548 boundH2 = y2 - boundY2 + 1;
00549 found = true;
00550 break;
00551 }
00552 ++it;
00553 }
00554 if (found) break;
00555 }
00556 found = false;
00557
00558 {
00559 KisVLineIterator it = const_cast<KisPaintDevice *>(this)->createVLineIterator(x, boundY2, boundH2, false);
00560 for (Q_INT32 x2 = x; x2 < x + w ; ++x2) {
00561 while (!it.isDone() && found == false) {
00562 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
00563 boundX2 = x2;
00564 found = true;
00565 break;
00566 }
00567 ++it;
00568 }
00569 if (found) break;
00570 it.nextCol();
00571 }
00572 }
00573
00574 found = false;
00575
00576
00577 {
00578 for (Q_INT32 x2 = x + w; x2 > x ; --x2) {
00579 KisVLineIterator it = const_cast<KisPaintDevice *>(this)->createVLineIterator( x2, boundY2, boundH2, false);
00580 while (!it.isDone() && found == false) {
00581 if (memcmp(it.rawData(), defaultPixel, m_pixelSize) != 0) {
00582 boundW2 = x2 - boundX2 + 1;
00583
00584
00585
00586
00587
00588
00589 found = true;
00590 break;
00591 }
00592 ++it;
00593 }
00594 if (found) break;
00595 }
00596 }
00597 return QRect(boundX2, boundY2, boundW2, boundH2);
00598 }
00599
00600
00601 QRect KisPaintDevice::exactBounds() const
00602 {
00603
00604
00605
00606 QRect r2 = exactBoundsImprovedOldMethod();
00607
00608
00609
00610
00611 return r2;
00612 }
00613
00614 void KisPaintDevice::crop(Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h)
00615 {
00616 m_datamanager->setExtent(x - m_x, y - m_y, w, h);
00617 }
00618
00619
00620 void KisPaintDevice::crop(QRect r)
00621 {
00622 r.moveBy(-m_x, -m_y); m_datamanager->setExtent(r);
00623 }
00624
00625 void KisPaintDevice::clear()
00626 {
00627 m_datamanager->clear();
00628 }
00629
00630 void KisPaintDevice::fill(Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h, const Q_UINT8 *fillPixel)
00631 {
00632 m_datamanager->clear(x, y, w, h, fillPixel);
00633 }
00634
00635 void KisPaintDevice::mirrorX()
00636 {
00637 QRect r;
00638 if (hasSelection()) {
00639 r = selection()->selectedRect();
00640 }
00641 else {
00642 r = exactBounds();
00643 }
00644
00645 for (Q_INT32 y = r.top(); y <= r.bottom(); ++y) {
00646 KisHLineIteratorPixel srcIt = createHLineIterator(r.x(), y, r.width(), false);
00647 KisHLineIteratorPixel dstIt = createHLineIterator(r.x(), y, r.width(), true);
00648
00649 dstIt += r.width() - 1;
00650
00651 while (!srcIt.isDone()) {
00652 if (srcIt.isSelected()) {
00653 memcpy(dstIt.rawData(), srcIt.oldRawData(), m_pixelSize);
00654 }
00655 ++srcIt;
00656 --dstIt;
00657
00658 }
00659 }
00660 if (m_parentLayer) {
00661 m_parentLayer->setDirty(r);
00662 }
00663 }
00664
00665 void KisPaintDevice::mirrorY()
00666 {
00667
00668 QRect r;
00669 if (hasSelection()) {
00670 r = selection()->selectedRect();
00671 }
00672 else {
00673 r = exactBounds();
00674 }
00675
00676
00677 Q_INT32 y1, y2;
00678 for (y1 = r.top(), y2 = r.bottom(); y1 <= r.bottom(); ++y1, --y2) {
00679 KisHLineIteratorPixel itTop = createHLineIterator(r.x(), y1, r.width(), true);
00680 KisHLineIteratorPixel itBottom = createHLineIterator(r.x(), y2, r.width(), false);
00681 while (!itTop.isDone() && !itBottom.isDone()) {
00682 if (itBottom.isSelected()) {
00683 memcpy(itTop.rawData(), itBottom.oldRawData(), m_pixelSize);
00684 }
00685 ++itBottom;
00686 ++itTop;
00687 }
00688 }
00689
00690 if (m_parentLayer) {
00691 m_parentLayer->setDirty(r);
00692 }
00693 }
00694
00695 KisMementoSP KisPaintDevice::getMemento()
00696 {
00697 return m_datamanager->getMemento();
00698 }
00699
00700 void KisPaintDevice::rollback(KisMementoSP memento) { m_datamanager->rollback(memento); }
00701
00702 void KisPaintDevice::rollforward(KisMementoSP memento) { m_datamanager->rollforward(memento); }
00703
00704 bool KisPaintDevice::write(KoStore *store)
00705 {
00706 bool retval = m_datamanager->write(store);
00707 emit ioProgress(100);
00708
00709 return retval;
00710 }
00711
00712 bool KisPaintDevice::read(KoStore *store)
00713 {
00714 bool retval = m_datamanager->read(store);
00715 emit ioProgress(100);
00716
00717 return retval;
00718 }
00719
00720 void KisPaintDevice::convertTo(KisColorSpace * dstColorSpace, Q_INT32 renderingIntent)
00721 {
00722 kdDebug(41004) << "Converting " << name() << " to " << dstColorSpace->id().id() << " from "
00723 << m_colorSpace->id().id() << "\n";
00724 if ( (colorSpace()->id() == dstColorSpace->id()) )
00725 {
00726 return;
00727 }
00728
00729 KisPaintDevice dst(dstColorSpace);
00730 dst.setX(getX());
00731 dst.setY(getY());
00732
00733 Q_INT32 x, y, w, h;
00734 extent(x, y, w, h);
00735
00736 for (Q_INT32 row = y; row < y + h; ++row) {
00737
00738 Q_INT32 column = x;
00739 Q_INT32 columnsRemaining = w;
00740
00741 while (columnsRemaining > 0) {
00742
00743 Q_INT32 numContiguousDstColumns = dst.numContiguousColumns(column, row, row);
00744 Q_INT32 numContiguousSrcColumns = numContiguousColumns(column, row, row);
00745
00746 Q_INT32 columns = QMIN(numContiguousDstColumns, numContiguousSrcColumns);
00747 columns = QMIN(columns, columnsRemaining);
00748
00749
00750
00751 KisHLineIteratorPixel srcIt = createHLineIterator(column, row, columns, false);
00752 KisHLineIteratorPixel dstIt = dst.createHLineIterator(column, row, columns, true);
00753
00754 const Q_UINT8 *srcData = srcIt.rawData();
00755 Q_UINT8 *dstData = dstIt.rawData();
00756
00757
00758 m_colorSpace->convertPixelsTo(srcData, dstData, dstColorSpace, columns, renderingIntent);
00759
00760 column += columns;
00761 columnsRemaining -= columns;
00762 }
00763 }
00764
00765 KisDataManagerSP oldData = m_datamanager;
00766 KisColorSpace *oldColorSpace = m_colorSpace;
00767
00768 setData(dst.m_datamanager, dstColorSpace);
00769
00770 if (undoAdapter() && undoAdapter()->undo()) {
00771 undoAdapter()->addCommand(new KisConvertLayerTypeCmd(undoAdapter(), this, oldData, oldColorSpace, m_datamanager, m_colorSpace));
00772 }
00773 }
00774
00775 void KisPaintDevice::setProfile(KisProfile * profile)
00776 {
00777 if (profile == 0) return;
00778
00779 KisColorSpace * dstSpace =
00780 KisMetaRegistry::instance()->csRegistry()->getColorSpace( colorSpace()->id(),
00781 profile);
00782 if (dstSpace)
00783 m_colorSpace = dstSpace;
00784
00785 }
00786
00787 void KisPaintDevice::setData(KisDataManagerSP data, KisColorSpace * colorSpace)
00788 {
00789 m_datamanager = data;
00790 m_colorSpace = colorSpace;
00791 m_pixelSize = m_colorSpace->pixelSize();
00792 m_nChannels = m_colorSpace->nChannels();
00793
00794 if (m_parentLayer) {
00795 m_parentLayer->setDirty(extent());
00796 m_parentLayer->notifyPropertyChanged();
00797 }
00798 }
00799
00800 KisUndoAdapter *KisPaintDevice::undoAdapter() const
00801 {
00802 if (m_parentLayer && m_parentLayer->image()) {
00803 return m_parentLayer->image()->undoAdapter();
00804 }
00805 return 0;
00806 }
00807
00808 void KisPaintDevice::convertFromQImage(const QImage& image, const QString &srcProfileName,
00809 Q_INT32 offsetX, Q_INT32 offsetY)
00810 {
00811 QImage img = image;
00812
00813
00814 if (img.bitOrder() == QImage::LittleEndian) {
00815 img = img.convertBitOrder(QImage::BigEndian);
00816 }
00817 kdDebug() << k_funcinfo << img.bitOrder()<< endl;
00818
00819 img = img.convertDepth( 32 );
00820 #if 0
00821
00822 if (colorSpace() == KisMetaRegistry::instance()->csRegistry() ->getColorSpace(KisID("RGBA",""),"")) {
00823 writeBytes(img.bits(), 0, 0, img.width(), img.height());
00824 }
00825 else {
00826 #endif
00827 Q_UINT8 * dstData = new Q_UINT8[img.width() * img.height() * pixelSize()];
00828 KisMetaRegistry::instance()->csRegistry()
00829 ->getColorSpace(KisID("RGBA",""),srcProfileName)->
00830 convertPixelsTo(img.bits(), dstData, colorSpace(), img.width() * img.height());
00831 writeBytes(dstData, offsetX, offsetY, img.width(), img.height());
00832
00833 }
00834
00835 QImage KisPaintDevice::convertToQImage(KisProfile * dstProfile, float exposure)
00836 {
00837 Q_INT32 x1;
00838 Q_INT32 y1;
00839 Q_INT32 w;
00840 Q_INT32 h;
00841
00842 x1 = - getX();
00843 y1 = - getY();
00844
00845 if (image()) {
00846 w = image()->width();
00847 h = image()->height();
00848 }
00849 else {
00850 extent(x1, y1, w, h);
00851 }
00852
00853 return convertToQImage(dstProfile, x1, y1, w, h, exposure);
00854 }
00855
00856
00857 QImage KisPaintDevice::convertToQImage(KisProfile * dstProfile, Q_INT32 x1, Q_INT32 y1, Q_INT32 w, Q_INT32 h, float exposure)
00858 {
00859 if (w < 0)
00860 return QImage();
00861
00862 if (h < 0)
00863 return QImage();
00864
00865 Q_UINT8 * data = new Q_UINT8 [w * h * m_pixelSize];
00866 Q_CHECK_PTR(data);
00867
00868
00869
00870 readBytes(data, x1, y1, w, h);
00871 QImage image = colorSpace()->convertToQImage(data, w, h, dstProfile, INTENT_PERCEPTUAL, exposure);
00872 delete[] data;
00873
00874 return image;
00875 }
00876
00877 KisPaintDeviceSP KisPaintDevice::createThumbnailDevice(Q_INT32 w, Q_INT32 h)
00878 {
00879 KisPaintDeviceSP thumbnail = new KisPaintDevice(colorSpace(), "thumbnail");
00880
00881 thumbnail->clear();
00882
00883 int srcw, srch;
00884 if( image() )
00885 {
00886 srcw = image()->width();
00887 srch = image()->height();
00888 }
00889 else
00890 {
00891 const QRect e = exactBounds();
00892 srcw = e.width();
00893 srch = e.height();
00894 }
00895
00896 if (w > srcw)
00897 {
00898 w = srcw;
00899 h = Q_INT32(double(srcw) / w * h);
00900 }
00901 if (h > srch)
00902 {
00903 h = srch;
00904 w = Q_INT32(double(srch) / h * w);
00905 }
00906
00907 if (srcw > srch)
00908 h = Q_INT32(double(srch) / srcw * w);
00909 else if (srch > srcw)
00910 w = Q_INT32(double(srcw) / srch * h);
00911
00912 for (Q_INT32 y=0; y < h; ++y) {
00913 Q_INT32 iY = (y * srch ) / h;
00914 for (Q_INT32 x=0; x < w; ++x) {
00915 Q_INT32 iX = (x * srcw ) / w;
00916 thumbnail->setPixel(x, y, colorAt(iX, iY));
00917 }
00918 }
00919
00920 return thumbnail;
00921
00922 }
00923
00924
00925 QImage KisPaintDevice::createThumbnail(Q_INT32 w, Q_INT32 h)
00926 {
00927 int srcw, srch;
00928 if( image() )
00929 {
00930 srcw = image()->width();
00931 srch = image()->height();
00932 }
00933 else
00934 {
00935 const QRect e = extent();
00936 srcw = e.width();
00937 srch = e.height();
00938 }
00939
00940 if (w > srcw)
00941 {
00942 w = srcw;
00943 h = Q_INT32(double(srcw) / w * h);
00944 }
00945 if (h > srch)
00946 {
00947 h = srch;
00948 w = Q_INT32(double(srch) / h * w);
00949 }
00950
00951 if (srcw > srch)
00952 h = Q_INT32(double(srch) / srcw * w);
00953 else if (srch > srcw)
00954 w = Q_INT32(double(srcw) / srch * h);
00955
00956 QColor c;
00957 Q_UINT8 opacity;
00958 QImage img(w,h,32);
00959
00960 for (Q_INT32 y=0; y < h; ++y) {
00961 Q_INT32 iY = (y * srch ) / h;
00962 for (Q_INT32 x=0; x < w; ++x) {
00963 Q_INT32 iX = (x * srcw ) / w;
00964 pixel(iX, iY, &c, &opacity);
00965 const QRgb rgb = c.rgb();
00966 img.setPixel(x, y, qRgba(qRed(rgb), qGreen(rgb), qBlue(rgb), opacity));
00967 }
00968 }
00969
00970 return img;
00971 }
00972
00973 KisRectIteratorPixel KisPaintDevice::createRectIterator(Q_INT32 left, Q_INT32 top, Q_INT32 w, Q_INT32 h, bool writable)
00974 {
00975 if(hasSelection())
00976 return KisRectIteratorPixel(this, m_datamanager, m_selection->m_datamanager, left, top, w, h, m_x, m_y, writable);
00977 else
00978 return KisRectIteratorPixel(this, m_datamanager, NULL, left, top, w, h, m_x, m_y, writable);
00979 }
00980
00981 KisHLineIteratorPixel KisPaintDevice::createHLineIterator(Q_INT32 x, Q_INT32 y, Q_INT32 w, bool writable)
00982 {
00983 if(hasSelection())
00984 return KisHLineIteratorPixel(this, m_datamanager, m_selection->m_datamanager, x, y, w, m_x, m_y, writable);
00985 else
00986 return KisHLineIteratorPixel(this, m_datamanager, NULL, x, y, w, m_x, m_y, writable);
00987 }
00988
00989 KisVLineIteratorPixel KisPaintDevice::createVLineIterator(Q_INT32 x, Q_INT32 y, Q_INT32 h, bool writable)
00990 {
00991 if(hasSelection())
00992 return KisVLineIteratorPixel(this, m_datamanager, m_selection->m_datamanager, x, y, h, m_x, m_y, writable);
00993 else
00994 return KisVLineIteratorPixel(this, m_datamanager, NULL, x, y, h, m_x, m_y, writable);
00995
00996 }
00997
00998 KisRandomAccessorPixel KisPaintDevice::createRandomAccessor(Q_INT32 x, Q_INT32 y, bool writable) {
00999 if(hasSelection())
01000 return KisRandomAccessorPixel(m_datamanager, m_selection->m_datamanager, x, y, m_x, m_y, writable);
01001 else
01002 return KisRandomAccessorPixel(m_datamanager, NULL, x, y, m_x, m_y, writable);
01003 }
01004
01005 KisRandomSubAccessorPixel KisPaintDevice::createRandomSubAccessor()
01006 {
01007 return KisRandomSubAccessorPixel(this);
01008 }
01009
01010 void KisPaintDevice::emitSelectionChanged()
01011 {
01012 if (m_parentLayer && m_parentLayer->image()) {
01013 m_parentLayer->image()->slotSelectionChanged();
01014 }
01015 }
01016
01017 void KisPaintDevice::emitSelectionChanged(const QRect& r)
01018 {
01019 if (m_parentLayer && m_parentLayer->image()) {
01020 m_parentLayer->image()->slotSelectionChanged(r);
01021 }
01022 }
01023
01024 KisSelectionSP KisPaintDevice::selection()
01025 {
01026 if ( m_selectionDeselected && m_selection ) {
01027 m_selectionDeselected = false;
01028 }
01029 else if (!m_selection) {
01030 m_selection = new KisSelection(this);
01031 Q_CHECK_PTR(m_selection);
01032 m_selection->setX(m_x);
01033 m_selection->setY(m_y);
01034 }
01035 m_hasSelection = true;
01036
01037 return m_selection;
01038 }
01039
01040
01041 bool KisPaintDevice::hasSelection()
01042 {
01043 return m_hasSelection;
01044 }
01045
01046 bool KisPaintDevice::selectionDeselected()
01047 {
01048 return m_selectionDeselected;
01049 }
01050
01051
01052 void KisPaintDevice::deselect()
01053 {
01054 if (m_selection && m_hasSelection) {
01055 m_hasSelection = false;
01056 m_selectionDeselected = true;
01057 }
01058 }
01059
01060 void KisPaintDevice::reselect()
01061 {
01062 m_hasSelection = true;
01063 m_selectionDeselected = false;
01064 }
01065
01066 void KisPaintDevice::addSelection(KisSelectionSP selection) {
01067
01068 KisPainter painter(this->selection().data());
01069 QRect r = selection->selectedExactRect();
01070 painter.bitBlt(r.x(), r.y(), COMPOSITE_OVER, selection.data(), r.x(), r.y(), r.width(), r.height());
01071 painter.end();
01072 }
01073
01074 void KisPaintDevice::subtractSelection(KisSelectionSP selection) {
01075 KisPainter painter(this->selection().data());
01076 selection->invert();
01077
01078 QRect r = selection->selectedExactRect();
01079 painter.bitBlt(r.x(), r.y(), COMPOSITE_ERASE, selection.data(), r.x(), r.y(), r.width(), r.height());
01080
01081 selection->invert();
01082 painter.end();
01083 }
01084
01085 void KisPaintDevice::clearSelection()
01086 {
01087 if (!hasSelection()) return;
01088
01089 QRect r = m_selection->selectedExactRect();
01090
01091 if (r.isValid()) {
01092
01093 for (Q_INT32 y = 0; y < r.height(); y++) {
01094
01095 KisHLineIterator devIt = createHLineIterator(r.x(), r.y() + y, r.width(), true);
01096 KisHLineIterator selectionIt = m_selection->createHLineIterator(r.x(), r.y() + y, r.width(), false);
01097
01098 while (!devIt.isDone()) {
01099
01100
01101 m_colorSpace->applyInverseAlphaU8Mask( devIt.rawData(), selectionIt.rawData(), 1);
01102
01103 ++devIt;
01104 ++selectionIt;
01105 }
01106 }
01107
01108 if (m_parentLayer) {
01109 m_parentLayer->setDirty(r);
01110 }
01111 }
01112 }
01113
01114 void KisPaintDevice::applySelectionMask(KisSelectionSP mask)
01115 {
01116 QRect r = mask->selectedRect();
01117 crop(r);
01118
01119 for (Q_INT32 y = r.top(); y <= r.bottom(); ++y) {
01120
01121 KisHLineIterator pixelIt = createHLineIterator(r.x(), y, r.width(), true);
01122 KisHLineIterator maskIt = mask->createHLineIterator(r.x(), y, r.width(), false);
01123
01124 while (!pixelIt.isDone()) {
01125
01126
01127 m_colorSpace->applyAlphaU8Mask( pixelIt.rawData(), maskIt.rawData(), 1);
01128
01129 ++pixelIt;
01130 ++maskIt;
01131 }
01132 }
01133 }
01134
01135 KisSelectionSP KisPaintDevice::setSelection( KisSelectionSP selection)
01136 {
01137 if (selection) {
01138 KisSelectionSP oldSelection = m_selection;
01139 m_selection = selection;
01140 m_hasSelection = true;
01141 return oldSelection;
01142 }
01143 else return 0;
01144 }
01145
01146 bool KisPaintDevice::pixel(Q_INT32 x, Q_INT32 y, QColor *c, Q_UINT8 *opacity)
01147 {
01148 KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, false);
01149
01150 Q_UINT8 *pix = iter.rawData();
01151
01152 if (!pix) return false;
01153
01154 colorSpace()->toQColor(pix, c, opacity);
01155
01156 return true;
01157 }
01158
01159
01160 bool KisPaintDevice::pixel(Q_INT32 x, Q_INT32 y, KisColor * kc)
01161 {
01162 KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, false);
01163
01164 Q_UINT8 *pix = iter.rawData();
01165
01166 if (!pix) return false;
01167
01168 kc->setColor(pix, m_colorSpace);
01169
01170 return true;
01171 }
01172
01173 KisColor KisPaintDevice::colorAt(Q_INT32 x, Q_INT32 y)
01174 {
01175
01176 KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, true);
01177 return KisColor(iter.rawData(), m_colorSpace);
01178 }
01179
01180 bool KisPaintDevice::setPixel(Q_INT32 x, Q_INT32 y, const QColor& c, Q_UINT8 opacity)
01181 {
01182 KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, true);
01183
01184 colorSpace()->fromQColor(c, opacity, iter.rawData());
01185
01186 return true;
01187 }
01188
01189 bool KisPaintDevice::setPixel(Q_INT32 x, Q_INT32 y, const KisColor& kc)
01190 {
01191 Q_UINT8 * pix;
01192 if (kc.colorSpace() != m_colorSpace) {
01193 KisColor kc2 (kc, m_colorSpace);
01194 pix = kc2.data();
01195 }
01196 else {
01197 pix = kc.data();
01198 }
01199
01200 KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, true);
01201 memcpy(iter.rawData(), pix, m_colorSpace->pixelSize());
01202
01203 return true;
01204 }
01205
01206
01207 Q_INT32 KisPaintDevice::numContiguousColumns(Q_INT32 x, Q_INT32 minY, Q_INT32 maxY)
01208 {
01209 return m_datamanager->numContiguousColumns(x - m_x, minY - m_y, maxY - m_y);
01210 }
01211
01212 Q_INT32 KisPaintDevice::numContiguousRows(Q_INT32 y, Q_INT32 minX, Q_INT32 maxX)
01213 {
01214 return m_datamanager->numContiguousRows(y - m_y, minX - m_x, maxX - m_x);
01215 }
01216
01217 Q_INT32 KisPaintDevice::rowStride(Q_INT32 x, Q_INT32 y)
01218 {
01219 return m_datamanager->rowStride(x - m_x, y - m_y);
01220 }
01221
01222 const Q_UINT8* KisPaintDevice::pixel(Q_INT32 x, Q_INT32 y)
01223 {
01224 return m_datamanager->pixel(x - m_x, y - m_y);
01225 }
01226
01227 Q_UINT8* KisPaintDevice::writablePixel(Q_INT32 x, Q_INT32 y)
01228 {
01229 return m_datamanager->writablePixel(x - m_x, y - m_y);
01230 }
01231
01232 void KisPaintDevice::setX(Q_INT32 x)
01233 {
01234 m_x = x;
01235 if(m_selection && m_selection != this)
01236 m_selection->setX(x);
01237 }
01238
01239 void KisPaintDevice::setY(Q_INT32 y)
01240 {
01241 m_y = y;
01242 if(m_selection && m_selection != this)
01243 m_selection->setY(y);
01244 }
01245
01246
01247 void KisPaintDevice::readBytes(Q_UINT8 * data, Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h)
01248 {
01249 m_datamanager->readBytes(data, x - m_x, y - m_y, w, h);
01250 }
01251
01252 void KisPaintDevice::writeBytes(const Q_UINT8 * data, Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h)
01253 {
01254 m_datamanager->writeBytes( data, x - m_x, y - m_y, w, h);
01255 }
01256
01257
01258 KisDataManagerSP KisPaintDevice::dataManager() const
01259 {
01260 return m_datamanager;
01261 }
01262
01263 KisExifInfo* KisPaintDevice::exifInfo()
01264 {
01265 if(!m_exifInfo)
01266 m_exifInfo = new KisExifInfo();
01267 return m_exifInfo;
01268 }
01269
01270 void KisPaintDevice::runBackgroundFilters()
01271 {
01272 QRect rc = extent();
01273 if (!m_longRunningFilters.isEmpty()) {
01274 QValueList<KisFilter*>::iterator it;
01275 QValueList<KisFilter*>::iterator end = m_longRunningFilters.end();
01276 for (it = m_longRunningFilters.begin(); it != end; ++it) {
01277 (*it)->process(this, this, 0, rc);
01278 }
01279 }
01280 if (m_parentLayer) m_parentLayer->setDirty(rc);
01281 }
01282
01283 #include "kis_paint_device.moc"