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