00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <qobject.h>
00020 #include <qapplication.h>
00021 #include <qclipboard.h>
00022 #include <qcolor.h>
00023
00024 #include <kdebug.h>
00025 #include <kaction.h>
00026 #include <klocale.h>
00027 #include <kstdaction.h>
00028
00029 #include <KoDocument.h>
00030 #include <KoMainWindow.h>
00031 #include <KoQueryTrader.h>
00032
00033 #include "kis_part_layer.h"
00034 #include "kis_adjustment_layer.h"
00035 #include "kis_clipboard.h"
00036 #include "kis_types.h"
00037 #include "kis_view.h"
00038 #include "kis_doc.h"
00039 #include "kis_image.h"
00040 #include "kis_selection.h"
00041 #include "kis_selection_manager.h"
00042 #include "kis_painter.h"
00043 #include "kis_iterators_pixel.h"
00044 #include "kis_iteratorpixeltrait.h"
00045 #include "kis_layer.h"
00046 #include "kis_group_layer.h"
00047 #include "kis_paint_layer.h"
00048 #include "kis_paint_device.h"
00049 #include "kis_channelinfo.h"
00050 #include "kis_dlg_apply_profile.h"
00051 #include "kis_config.h"
00052 #include "kis_debug_areas.h"
00053 #include "kis_transaction.h"
00054 #include "kis_undo_adapter.h"
00055 #include "kis_selected_transaction.h"
00056 #include "kis_convolution_painter.h"
00057 #include "kis_integer_maths.h"
00058 #include "kis_fill_painter.h"
00059 #include "kis_canvas.h"
00060
00061 KisSelectionManager::KisSelectionManager(KisView * parent, KisDoc * doc)
00062 : m_parent(parent),
00063 m_doc(doc),
00064 m_copy(0),
00065 m_cut(0),
00066 m_paste(0),
00067 m_pasteNew(0),
00068 m_cutToNewLayer(0),
00069 m_selectAll(0),
00070 m_deselect(0),
00071 m_clear(0),
00072 m_reselect(0),
00073 m_invert(0),
00074 m_toNewLayer(0),
00075 m_feather(0),
00076 m_border(0),
00077 m_expand(0),
00078 m_smooth(0),
00079 m_contract(0),
00080 m_similar(0),
00081 m_transform(0),
00082 m_load(0),
00083 m_save(0),
00084 m_fillForegroundColor(0),
00085 m_fillBackgroundColor(0),
00086 m_fillPattern(0)
00087 {
00088 m_pluginActions.setAutoDelete(true);
00089 m_clipboard = KisClipboard::instance();
00090 }
00091
00092 KisSelectionManager::~KisSelectionManager()
00093 {
00094 m_pluginActions.clear();
00095 }
00096
00097
00098 void KisSelectionManager::setup(KActionCollection * collection)
00099 {
00100
00101
00102 m_cut = KStdAction::cut(this,
00103 SLOT(cut()),
00104 collection,
00105 "cut");
00106
00107 m_copy = KStdAction::copy(this,
00108 SLOT(copy()),
00109 collection,
00110 "copy");
00111
00112 m_paste = KStdAction::paste(this,
00113 SLOT(paste()),
00114 collection,
00115 "paste");
00116
00117 m_pasteNew = new KAction(i18n("Paste into &New Image"),
00118 0, 0,
00119 this, SLOT(pasteNew()),
00120 collection,
00121 "paste_new");
00122
00123
00124 m_selectAll = KStdAction::selectAll(this,
00125 SLOT(selectAll()),
00126 collection,
00127 "select_all");
00128
00129 m_deselect = KStdAction::deselect(this,
00130 SLOT(deselect()),
00131 collection,
00132 "deselect");
00133
00134
00135 m_clear = KStdAction::clear(this,
00136 SLOT(clear()),
00137 collection,
00138 "clear");
00139
00140 m_reselect = new KAction(i18n("&Reselect"),
00141 0, "Ctrl+Shift+D",
00142 this, SLOT(reselect()),
00143 collection, "reselect");
00144
00145 m_invert = new KAction(i18n("&Invert"),
00146 0, "Ctrl+I",
00147 this, SLOT(invert()),
00148 collection, "invert");
00149
00150
00151 m_toNewLayer = new KAction(i18n("Copy Selection to New Layer"),
00152 0, "Ctrl+J",
00153 this, SLOT(copySelectionToNewLayer()),
00154 collection, "copy_selection_to_new_layer");
00155
00156
00157 m_cutToNewLayer = new KAction(i18n("Cut Selection to New Layer"),
00158 0, "Ctrl+Shift+J",
00159 this, SLOT(cutToNewLayer()),
00160 collection, "cut_selection_to_new_layer");
00161
00162 m_feather = new KAction(i18n("Feather"),
00163 0, "Ctrl+Alt+D",
00164 this, SLOT(feather()),
00165 collection, "feather");
00166
00167 m_fillForegroundColor = new KAction(i18n("Fill with Foreground Color"),
00168 "Alt+backspace", this,
00169 SLOT(fillForegroundColor()),
00170 collection,
00171 "fill_selection_foreground_color");
00172 m_fillBackgroundColor = new KAction(i18n("Fill with Background Color"),
00173 "backspace", this,
00174 SLOT(fillBackgroundColor()),
00175 collection,
00176 "fill_selection_background_color");
00177 m_fillPattern = new KAction(i18n("Fill with Pattern"),
00178 0, this,
00179 SLOT(fillPattern()),
00180 collection,
00181 "fill_selection_pattern");
00182
00183 m_toggleDisplaySelection = new KToggleAction(i18n("Display Selection"), "Ctrl+h", this, SLOT(toggleDisplaySelection()), collection, "toggle_display_selection");
00184 m_toggleDisplaySelection->setCheckedState(KGuiItem(i18n("Hide Selection")));
00185 m_toggleDisplaySelection->setChecked(true);
00186
00187 m_border =
00188 new KAction(i18n("Border..."),
00189 0, 0,
00190 this, SLOT(border()),
00191 collection, "border");
00192 m_expand =
00193 new KAction(i18n("Expand..."),
00194 0, 0,
00195 this, SLOT(expand()),
00196 collection, "expand");
00197
00198 m_smooth =
00199 new KAction(i18n("Smooth..."),
00200 0, 0,
00201 this, SLOT(smooth()),
00202 collection, "smooth");
00203
00204
00205 m_contract =
00206 new KAction(i18n("Contract..."),
00207 0, 0,
00208 this, SLOT(contract()),
00209 collection, "contract");
00210 m_similar =
00211 new KAction(i18n("Similar"),
00212 0, 0,
00213 this, SLOT(similar()),
00214 collection, "similar");
00215
00216
00217 m_transform
00218 = new KAction(i18n("Transform..."),
00219 0, 0,
00220 this, SLOT(transform()),
00221 collection, "transform_selection");
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 QClipboard *cb = QApplication::clipboard();
00238 connect(cb, SIGNAL(dataChanged()), SLOT(clipboardDataChanged()));
00239 }
00240
00241 void KisSelectionManager::clipboardDataChanged()
00242 {
00243 updateGUI();
00244 }
00245
00246
00247 void KisSelectionManager::addSelectionAction(KAction * action)
00248 {
00249 m_pluginActions.append(action);
00250 }
00251
00252
00253 void KisSelectionManager::updateGUI()
00254 {
00255 Q_ASSERT(m_parent);
00256 Q_ASSERT(m_clipboard);
00257
00258 if (m_parent == 0) {
00259
00260 return;
00261 }
00262
00263 if (m_clipboard == 0) {
00264
00265 return;
00266 }
00267
00268 KisImageSP img = m_parent->currentImg();
00269 KisLayerSP l = 0;
00270 KisPaintDeviceSP dev = 0;
00271
00272 bool enable = false;
00273 if (img && img->activeDevice() && img->activeLayer()) {
00274 l = img->activeLayer();
00275 dev = img->activeDevice();
00276
00277
00278 KisPartLayer * partLayer = dynamic_cast<KisPartLayer*>(l.data());
00279 KisAdjustmentLayer * adjLayer = dynamic_cast<KisAdjustmentLayer*>(l.data());
00280
00281 enable = l && dev&& dev->hasSelection() && !l->locked() && l->visible() && (partLayer==0);
00282
00283 if(dev && !adjLayer)
00284 m_reselect->setEnabled( dev->selectionDeselected() );
00285 if (adjLayer)
00286 m_reselect->setEnabled(false);
00287 }
00288
00289 m_cut->setEnabled(enable);
00290 m_cutToNewLayer->setEnabled(enable);
00291 m_selectAll->setEnabled(img != 0);
00292 m_deselect->setEnabled(enable);
00293 m_clear->setEnabled(enable);
00294 m_fillForegroundColor->setEnabled(enable);
00295 m_fillBackgroundColor->setEnabled(enable);
00296 m_fillPattern->setEnabled(enable);
00297 m_invert->setEnabled(enable);
00298
00299 m_feather->setEnabled(enable);
00300
00301 m_border->setEnabled(enable);
00302 m_expand->setEnabled(enable);
00303 m_smooth->setEnabled(enable);
00304 m_contract->setEnabled(enable);
00305 m_similar->setEnabled(enable);
00306 m_transform->setEnabled(enable);
00307
00308
00309
00310
00311 KAction * a;
00312 for (a = m_pluginActions.first(); a; a = m_pluginActions.next()) {
00313 a->setEnabled(img != 0);
00314 }
00315
00316
00317
00318 enable = false;
00319 if (img && l && dev) {
00320 enable = dev->hasSelection() && l->visible();
00321 }
00322
00323 m_copy->setEnabled(enable);
00324 m_paste->setEnabled(img != 0 && m_clipboard->hasClip());
00325 m_pasteNew->setEnabled(img != 0 && m_clipboard->hasClip());
00326 m_toNewLayer->setEnabled(enable);
00327
00328 m_parent->updateStatusBarSelectionLabel();
00329
00330 }
00331
00332 void KisSelectionManager::imgSelectionChanged(KisImageSP img)
00333 {
00334 if (img == m_parent->currentImg()) {
00335 updateGUI();
00336 }
00337 }
00338
00339 void KisSelectionManager::cut()
00340 {
00341 KisImageSP img = m_parent->currentImg();
00342 if (!img) return;
00343
00344 KisPaintDeviceSP dev = img->activeDevice();
00345 if (!dev) return;
00346
00347 if (!dev->hasSelection()) return;
00348
00349 copy();
00350
00351 KisSelectedTransaction *t = 0;
00352
00353 if (img->undo()) {
00354 t = new KisSelectedTransaction(i18n("Cut"), dev);
00355 Q_CHECK_PTR(t);
00356 }
00357
00358 dev->clearSelection();
00359 dev->deselect();
00360 dev->emitSelectionChanged();
00361
00362 if (img->undo()) {
00363 img->undoAdapter()->addCommand(t);
00364 }
00365 }
00366
00367 void KisSelectionManager::copy()
00368 {
00369 KisImageSP img = m_parent->currentImg();
00370 if (!img) return;
00371
00372 KisPaintDeviceSP dev = img->activeDevice();
00373 if (!dev) return;
00374
00375 if (!dev->hasSelection()) return;
00376
00377 KisSelectionSP selection = dev->selection();
00378
00379 QRect r = selection->selectedExactRect();
00380
00381 KisPaintDeviceSP clip = new KisPaintDevice(dev->colorSpace(), "clip");
00382 Q_CHECK_PTR(clip);
00383
00384 KisColorSpace * cs = clip->colorSpace();
00385
00386
00387
00388
00389 KisPainter gc;
00390 gc.begin(clip);
00391 gc.bitBlt(0, 0, COMPOSITE_COPY, dev, r.x(), r.y(), r.width(), r.height());
00392 gc.end();
00393
00394
00395
00396 for (Q_INT32 y = 0; y < r.height(); y++) {
00397 KisHLineIteratorPixel layerIt = clip->createHLineIterator(0, y, r.width(), true);
00398 KisHLineIteratorPixel selectionIt = selection->createHLineIterator(r.x(), r.y() + y, r.width(), false);
00399
00400 while (!layerIt.isDone()) {
00401
00402 cs->applyAlphaU8Mask( layerIt.rawData(), selectionIt.rawData(), 1 );
00403
00404
00405 ++layerIt;
00406 ++selectionIt;
00407 }
00408 }
00409
00410 m_clipboard->setClip(clip);
00411 imgSelectionChanged(m_parent->currentImg());
00412 }
00413
00414
00415 KisLayerSP KisSelectionManager::paste()
00416 {
00417 KisImageSP img = m_parent->currentImg();
00418 if (!img) return 0;
00419
00420 KisPaintDeviceSP clip = m_clipboard->clip();
00421
00422 if (clip) {
00423 KisPaintLayer *layer = new KisPaintLayer(img, img->nextLayerName() + "(pasted)", OPACITY_OPAQUE);
00424 Q_CHECK_PTR(layer);
00425
00426 QRect r = clip->exactBounds();
00427 KisPainter gc;
00428 gc.begin(layer->paintDevice());
00429 gc.bitBlt(0, 0, COMPOSITE_COPY, clip, r.x(), r.y(), r.width(), r.height());
00430 gc.end();
00431
00432
00433 KisCanvasController *cc = m_parent->getCanvasController();
00434 QPoint center = cc->viewToWindow(QPoint(cc->kiscanvas()->width()/2, cc->kiscanvas()->height()/2));
00435 QPoint bottomright = cc->viewToWindow(QPoint(cc->kiscanvas()->width(), cc->kiscanvas()->height()));
00436 if(bottomright.x() > img->width())
00437 center.setX(img->width()/2);
00438 if(bottomright.y() > img->height())
00439 center.setY(img->height()/2);
00440 center -= QPoint(r.width()/2, r.height()/2);
00441 layer->setX(center.x());
00442 layer->setY(center.y());
00443
00444
00445
00446
00447
00448
00449
00450 if(img->addLayer(layer, img->activeLayer()->parent(), img->activeLayer()))
00451 {
00452 return layer;
00453 } else {
00454 return 0;
00455 }
00456 }
00457 return 0;
00458 }
00459
00460 void KisSelectionManager::pasteNew()
00461 {
00462 KisPaintDeviceSP clip = m_clipboard->clip();
00463 if (!clip) return;
00464
00465 QRect r = clip->exactBounds();
00466 if (r.width() < 1 && r.height() < 1) {
00467
00468 return;
00469 }
00470
00471 const QCString mimetype = KoDocument::readNativeFormatMimeType();
00472 KoDocumentEntry entry = KoDocumentEntry::queryByMimeType( mimetype );
00473 KisDoc * doc = (KisDoc*) entry.createDoc();
00474
00475 Q_ASSERT(doc->undoAdapter() != 0);
00476 doc->undoAdapter()->setUndo(false);
00477
00478 KisImageSP img = new KisImage(doc->undoAdapter(), r.width(), r.height(), clip->colorSpace(), "Pasted");
00479 KisPaintLayer *layer = new KisPaintLayer(img, clip->name(), OPACITY_OPAQUE, clip->colorSpace());
00480
00481 KisPainter p(layer->paintDevice());
00482 p.bitBlt(0, 0, COMPOSITE_COPY, clip, OPACITY_OPAQUE, r.x(), r.y(), r.width(), r.height());
00483 p.end();
00484
00485 img->addLayer(layer, img->rootLayer(), 0);
00486 doc->setCurrentImage(img);
00487
00488 doc->undoAdapter()->setUndo(true);
00489
00490 KoMainWindow *win = new KoMainWindow( doc->instance() );
00491 win->show();
00492 win->setRootDocument( doc );
00493 }
00494
00495 void KisSelectionManager::selectAll()
00496 {
00497 KisImageSP img = m_parent->currentImg();
00498 if (!img) return;
00499
00500 KisPaintDeviceSP dev = img->activeDevice();
00501 if (!dev) return;
00502
00503 KisSelectedTransaction * t = 0;
00504 if (img->undo()) t = new KisSelectedTransaction(i18n("Select All"), dev);
00505 Q_CHECK_PTR(t);
00506
00507 dev->selection()->clear();
00508 dev->selection()->invert();
00509 dev->setDirty();
00510 dev->emitSelectionChanged();
00511
00512 if (img->undo())
00513 img->undoAdapter()->addCommand(t);
00514 }
00515
00516 void KisSelectionManager::deselect()
00517 {
00518 KisImageSP img = m_parent->currentImg();
00519 if (!img) return;
00520
00521 KisPaintDeviceSP dev = img->activeDevice();
00522 if (!dev) return;
00523 KisSelectedTransaction * t = 0;
00524 if (img->undo()) t = new KisSelectedTransaction(i18n("Deselect"), dev);
00525 Q_CHECK_PTR(t);
00526
00527
00528 if (dynamic_cast<KisAdjustmentLayer*>(img->activeLayer().data())) {
00529 dev->clear();
00530 } else {
00531 dev->deselect();
00532 }
00533 dev->setDirty();
00534 dev->emitSelectionChanged();
00535
00536 if (img->undo())
00537 img->undoAdapter()->addCommand(t);
00538 }
00539
00540
00541 void KisSelectionManager::clear()
00542 {
00543 KisImageSP img = m_parent->currentImg();
00544 if (!img) return;
00545
00546 KisPaintDeviceSP dev = img->activeDevice();
00547 if (!dev) return;
00548
00549 if (!dev->hasSelection()) return;
00550
00551 KisTransaction * t = 0;
00552
00553 if (img->undo()) {
00554 t = new KisTransaction(i18n("Clear"), dev);
00555 }
00556
00557 dev->clearSelection();
00558 dev->setDirty();
00559 dev->emitSelectionChanged();
00560
00561 if (img->undo()) img->undoAdapter()->addCommand(t);
00562 }
00563
00564 void KisSelectionManager::fill(const KisColor& color, bool fillWithPattern, const QString& transactionText)
00565 {
00566 KisImageSP img = m_parent->currentImg();
00567 if (!img) return;
00568
00569 KisPaintDeviceSP dev = img->activeDevice();
00570 if (!dev) return;
00571
00572 if (!dev->hasSelection()) return;
00573
00574 KisSelectionSP selection = dev->selection();
00575
00576 KisPaintDeviceSP filled = new KisPaintDevice(dev->colorSpace());
00577 KisFillPainter painter(filled);
00578
00579 if (fillWithPattern) {
00580 painter.fillRect(0, 0, img->width(), img->height(),
00581 m_parent->currentPattern());
00582 } else {
00583 painter.fillRect(0, 0, img->width(), img->height(), color);
00584 }
00585
00586 painter.end();
00587
00588 KisPainter painter2(dev);
00589
00590 if (img->undo()) painter2.beginTransaction(transactionText);
00591 painter2.bltSelection(0, 0, COMPOSITE_OVER, filled, OPACITY_OPAQUE,
00592 0, 0, img->width(), img->height());
00593
00594 dev->setDirty();
00595 dev->emitSelectionChanged();
00596
00597 if (img->undo()) {
00598 img->undoAdapter()->addCommand(painter2.endTransaction());
00599 }
00600 }
00601
00602 void KisSelectionManager::fillForegroundColor()
00603 {
00604 fill(m_parent->fgColor(), false, i18n("Fill with Foreground Color"));
00605 }
00606
00607 void KisSelectionManager::fillBackgroundColor()
00608 {
00609 fill(m_parent->bgColor(), false, i18n("Fill with Background Color"));
00610 }
00611
00612 void KisSelectionManager::fillPattern()
00613 {
00614 fill(KisColor(), true, i18n("Fill with Pattern"));
00615 }
00616
00617 void KisSelectionManager::reselect()
00618 {
00619 KisImageSP img = m_parent->currentImg();
00620 if (!img) return;
00621
00622 KisPaintDeviceSP dev = img ->activeDevice();
00623 if (!dev) return;
00624
00625 KisSelectedTransaction * t = 0;
00626 if (img->undo()) t = new KisSelectedTransaction(i18n("Reselect"), dev);
00627 Q_CHECK_PTR(t);
00628
00629 dev->reselect();
00630 dev->setDirty();
00631 dev->emitSelectionChanged();
00632
00633 if (img->undo())
00634 img->undoAdapter()->addCommand(t);
00635 }
00636
00637
00638 void KisSelectionManager::invert()
00639 {
00640 KisImageSP img = m_parent->currentImg();
00641 if (!img) return;
00642
00643 KisPaintDeviceSP dev = img->activeDevice();
00644 if (!dev) return;
00645
00646 if (dev->hasSelection()) {
00647 KisSelectionSP s = dev->selection();
00648
00649 KisSelectedTransaction * t = 0;
00650 if (img->undo())
00651 {
00652 t = new KisSelectedTransaction(i18n("Invert"), dev);
00653 Q_CHECK_PTR(t);
00654 }
00655
00656 s->invert();
00657 dev->setDirty();
00658 dev->emitSelectionChanged();
00659
00660 if (t) {
00661 img->undoAdapter()->addCommand(t);
00662 }
00663 }
00664 }
00665
00666 void KisSelectionManager::copySelectionToNewLayer()
00667 {
00668 KisImageSP img = m_parent->currentImg();
00669 if (!img) return;
00670
00671 KisPaintDeviceSP dev = img->activeDevice();
00672 if (!dev) return;
00673
00674 copy();
00675 paste();
00676 }
00677
00678 void KisSelectionManager::cutToNewLayer()
00679 {
00680 KisImageSP img = m_parent->currentImg();
00681 if (!img) return;
00682
00683 KisPaintDeviceSP dev = img->activeDevice();
00684 if (!dev) return;
00685
00686 cut();
00687 paste();
00688 }
00689
00690
00691 void KisSelectionManager::feather()
00692 {
00693 KisImageSP img = m_parent->currentImg();
00694 if (!img) return;
00695 KisPaintDeviceSP dev = img->activeDevice();
00696 if (!dev) return;
00697
00698 if (!dev->hasSelection()) {
00699
00700 dev->selection();
00701 return;
00702 }
00703
00704 KisSelectionSP selection = dev->selection();
00705 KisSelectedTransaction * t = 0;
00706 if (img->undo()) t = new KisSelectedTransaction(i18n("Feather..."), dev);
00707 Q_CHECK_PTR(t);
00708
00709
00710
00711
00712
00713 KisConvolutionPainter painter(selection.data());
00714
00715 KisKernelSP k = new KisKernel();
00716 k->width = 3;
00717 k->height = 3;
00718 k->factor = 16;
00719 k->offset = 0;
00720 k->data = new Q_INT32[9];
00721 k->data[0] = 1;
00722 k->data[1] = 2;
00723 k->data[2] = 1;
00724 k->data[3] = 2;
00725 k->data[4] = 4;
00726 k->data[5] = 2;
00727 k->data[6] = 1;
00728 k->data[7] = 2;
00729 k->data[8] = 1;
00730
00731 QRect rect = selection->selectedRect();
00732
00733 rect = QRect(rect.x() - 3, rect.y() - 3, rect.width() + 6, rect.height() + 6);
00734 rect &= QRect(0, 0, img->width(), img->height());
00735
00736 painter.applyMatrix(k, rect.x(), rect.y(), rect.width(), rect.height(), BORDER_AVOID, KisChannelInfo::FLAG_ALPHA);
00737 painter.end();
00738
00739 dev->setDirty(rect);
00740 dev->emitSelectionChanged();
00741
00742 if (img->undo())
00743 img->undoAdapter()->addCommand(t);
00744
00745 }
00746
00747 void KisSelectionManager::toggleDisplaySelection()
00748 {
00749 m_parent->selectionDisplayToggled(displaySelection());
00750 }
00751
00752 bool KisSelectionManager::displaySelection()
00753 {
00754 return m_toggleDisplaySelection->isChecked();
00755 }
00756
00757 void KisSelectionManager::border() {}
00758 void KisSelectionManager::expand() {}
00759 void KisSelectionManager::contract() {}
00760 void KisSelectionManager::similar() {}
00761 void KisSelectionManager::transform() {}
00762 void KisSelectionManager::load() {}
00763 void KisSelectionManager::save() {}
00764
00765 #define MAX(a, b) ((a) > (b) ? (a) : (b))
00766 #define MIN(a, b) ((a) < (b) ? (a) : (b))
00767
00768 void KisSelectionManager::grow (Q_INT32 xradius, Q_INT32 yradius)
00769 {
00770 KisImageSP img = m_parent->currentImg();
00771 if (!img) return;
00772
00773 KisPaintDeviceSP dev = img->activeDevice();
00774 if (!dev) return;
00775
00776 if (!dev->hasSelection()) return;
00777 KisSelectionSP selection = dev->selection();
00778
00779
00780 QRect layerSize = dev->exactBounds();
00781
00782
00783
00784
00785
00786 Q_UINT8 **buf;
00787 Q_UINT8 **max;
00788
00789 if (xradius <= 0 || yradius <= 0)
00790 return;
00791
00792 KisSelectedTransaction *t = 0;
00793
00794 if (img->undo()) {
00795 t = new KisSelectedTransaction(i18n("Grow"), dev);
00796 Q_CHECK_PTR(t);
00797 }
00798
00799 max = new Q_UINT8* [layerSize.width() + 2 * xradius];
00800 buf = new Q_UINT8* [yradius + 1];
00801 for (Q_INT32 i = 0; i < yradius + 1; i++)
00802 {
00803 buf[i] = new Q_UINT8[layerSize.width()];
00804 }
00805 Q_UINT8* buffer = new Q_UINT8[ ( layerSize.width() + 2 * xradius ) * ( yradius + 1 ) ];
00806 for (Q_INT32 i = 0; i < layerSize.width() + 2 * xradius; i++)
00807 {
00808 if (i < xradius)
00809 max[i] = buffer;
00810 else if (i < layerSize.width() + xradius)
00811 max[i] = &buffer[(yradius + 1) * (i - xradius)];
00812 else
00813 max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius - 1)];
00814
00815 for (Q_INT32 j = 0; j < xradius + 1; j++)
00816 max[i][j] = 0;
00817 }
00818
00819
00820 max += xradius;
00821
00822 Q_UINT8* out = new Q_UINT8[ layerSize.width() ];
00823
00824 Q_INT32* circ = new Q_INT32[ 2 * xradius + 1 ];
00825 computeBorder (circ, xradius, yradius);
00826
00827
00828
00829 circ += xradius;
00830
00831 memset (buf[0], 0, layerSize.width());
00832 for (Q_INT32 i = 0; i < yradius && i < layerSize.height(); i++)
00833 {
00834 selection->readBytes(buf[i + 1], layerSize.x(), layerSize.y() + i, layerSize.width(), 1);
00835 }
00836
00837 for (Q_INT32 x = 0; x < layerSize.width() ; x++)
00838 {
00839 max[x][0] = 0;
00840 max[x][1] = buf[1][x];
00841 for (Q_INT32 j = 2; j < yradius + 1; j++)
00842 {
00843 max[x][j] = MAX(buf[j][x], max[x][j-1]);
00844 }
00845 }
00846
00847 for (Q_INT32 y = 0; y < layerSize.height(); y++)
00848 {
00849 rotatePointers (buf, yradius + 1);
00850 if (y < layerSize.height() - (yradius))
00851 selection->readBytes(buf[yradius], layerSize.x(), layerSize.y() + y + yradius, layerSize.width(), 1);
00852 else
00853 memset (buf[yradius], 0, layerSize.width());
00854 for (Q_INT32 x = 0; x < layerSize.width(); x++)
00855 {
00856 for (Q_INT32 i = yradius; i > 0; i--)
00857 {
00858 max[x][i] = MAX (MAX (max[x][i - 1], buf[i - 1][x]), buf[i][x]);
00859 }
00860 max[x][0] = buf[0][x];
00861 }
00862 Q_INT32 last_max = max[0][circ[-1]];
00863 Q_INT32 last_index = 1;
00864 for (Q_INT32 x = 0; x < layerSize.width(); x++)
00865 {
00866 last_index--;
00867 if (last_index >= 0)
00868 {
00869 if (last_max == 255)
00870 out[x] = 255;
00871 else
00872 {
00873 last_max = 0;
00874 for (Q_INT32 i = xradius; i >= 0; i--)
00875 if (last_max < max[x + i][circ[i]])
00876 {
00877 last_max = max[x + i][circ[i]];
00878 last_index = i;
00879 }
00880 out[x] = last_max;
00881 }
00882 }
00883 else
00884 {
00885 last_index = xradius;
00886 last_max = max[x + xradius][circ[xradius]];
00887 for (Q_INT32 i = xradius - 1; i >= -xradius; i--)
00888 if (last_max < max[x + i][circ[i]])
00889 {
00890 last_max = max[x + i][circ[i]];
00891 last_index = i;
00892 }
00893 out[x] = last_max;
00894 }
00895 }
00896 selection->writeBytes(out, layerSize.x(), layerSize.y() + y, layerSize.width(), 1);
00897 }
00898
00899 circ -= xradius;
00900 max -= xradius;
00901
00902 delete[] circ;
00903 delete[] buffer;
00904 delete[] max;
00905 for (Q_INT32 i = 0; i < yradius + 1; i++)
00906 delete[] buf[i];
00907 delete[] buf;
00908 delete[] out;
00909
00910 dev->setDirty();
00911 dev->emitSelectionChanged();
00912
00913 if (t) {
00914 img->undoAdapter()->addCommand(t);
00915 }
00916 }
00917
00918 void KisSelectionManager::shrink (Q_INT32 xradius, Q_INT32 yradius, bool edge_lock)
00919 {
00920
00921 KisImageSP img = m_parent->currentImg();
00922 if (!img) return;
00923
00924 KisPaintDeviceSP dev = img->activeDevice();
00925 if (!dev) return;
00926
00927 if (!dev->hasSelection()) return;
00928 KisSelectionSP selection = dev->selection();
00929
00930
00931 QRect layerSize = dev->exactBounds();
00932
00933
00934
00935
00936
00937
00938
00939
00940 Q_UINT8 **buf;
00941 Q_UINT8 **max;
00942 Q_INT32 last_max, last_index;
00943
00944 if (xradius <= 0 || yradius <= 0)
00945 return;
00946
00947 max = new Q_UINT8* [layerSize.width() + 2 * xradius];
00948 buf = new Q_UINT8* [yradius + 1];
00949 for (Q_INT32 i = 0; i < yradius + 1; i++)
00950 {
00951 buf[i] = new Q_UINT8[layerSize.width()];
00952 }
00953
00954 Q_INT32 buffer_size = (layerSize.width() + 2 * xradius + 1) * (yradius + 1);
00955 Q_UINT8* buffer = new Q_UINT8[buffer_size];
00956
00957 if (edge_lock)
00958 memset(buffer, 255, buffer_size);
00959 else
00960 memset(buffer, 0, buffer_size);
00961
00962 for (Q_INT32 i = 0; i < layerSize.width() + 2 * xradius; i++)
00963 {
00964 if (i < xradius)
00965 if (edge_lock)
00966 max[i] = buffer;
00967 else
00968 max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius)];
00969 else if (i < layerSize.width() + xradius)
00970 max[i] = &buffer[(yradius + 1) * (i - xradius)];
00971 else
00972 if (edge_lock)
00973 max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius - 1)];
00974 else
00975 max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius)];
00976 }
00977 if (!edge_lock)
00978 for (Q_INT32 j = 0 ; j < xradius + 1; j++) max[0][j] = 0;
00979
00980
00981 max += xradius;
00982
00983 Q_UINT8* out = new Q_UINT8[layerSize.width()];
00984
00985 Q_INT32* circ = new Q_INT32[2 * xradius + 1];
00986
00987 computeBorder (circ, xradius, yradius);
00988
00989
00990 circ += xradius;
00991
00992 for (Q_INT32 i = 0; i < yradius && i < layerSize.height(); i++)
00993 selection->readBytes(buf[i + 1], layerSize.x(), layerSize.y() + i, layerSize.width(), 1);
00994
00995 if (edge_lock)
00996 memcpy (buf[0], buf[1], layerSize.width());
00997 else
00998 memset (buf[0], 0, layerSize.width());
00999
01000
01001 for (Q_INT32 x = 0; x < layerSize.width(); x++)
01002 {
01003 max[x][0] = buf[0][x];
01004 for (Q_INT32 j = 1; j < yradius + 1; j++)
01005 max[x][j] = MIN(buf[j][x], max[x][j-1]);
01006 }
01007
01008 for (Q_INT32 y = 0; y < layerSize.height(); y++)
01009 {
01010 rotatePointers (buf, yradius + 1);
01011 if (y < layerSize.height() - yradius)
01012 selection->readBytes(buf[yradius], layerSize.x(), layerSize.y() + y + yradius, layerSize.width(), 1);
01013 else if (edge_lock)
01014 memcpy (buf[yradius], buf[yradius - 1], layerSize.width());
01015 else
01016 memset (buf[yradius], 0, layerSize.width());
01017
01018 for (Q_INT32 x = 0 ; x < layerSize.width(); x++)
01019 {
01020 for (Q_INT32 i = yradius; i > 0; i--)
01021 {
01022 max[x][i] = MIN (MIN (max[x][i - 1], buf[i - 1][x]), buf[i][x]);
01023 }
01024 max[x][0] = buf[0][x];
01025 }
01026 last_max = max[0][circ[-1]];
01027 last_index = 0;
01028
01029 for (Q_INT32 x = 0 ; x < layerSize.width(); x++)
01030 {
01031 last_index--;
01032 if (last_index >= 0)
01033 {
01034 if (last_max == 0)
01035 out[x] = 0;
01036 else
01037 {
01038 last_max = 255;
01039 for (Q_INT32 i = xradius; i >= 0; i--)
01040 if (last_max > max[x + i][circ[i]])
01041 {
01042 last_max = max[x + i][circ[i]];
01043 last_index = i;
01044 }
01045 out[x] = last_max;
01046 }
01047 }
01048 else
01049 {
01050 last_index = xradius;
01051 last_max = max[x + xradius][circ[xradius]];
01052 for (Q_INT32 i = xradius - 1; i >= -xradius; i--)
01053 if (last_max > max[x + i][circ[i]])
01054 {
01055 last_max = max[x + i][circ[i]];
01056 last_index = i;
01057 }
01058 out[x] = last_max;
01059 }
01060 }
01061 selection->writeBytes(out, layerSize.x(), layerSize.y() + y, layerSize.width(), 1);
01062 }
01063
01064
01065 circ -= xradius;
01066 max -= xradius;
01067
01068
01069 delete[] circ;
01070 delete[] buffer;
01071 delete[] max;
01072 for (Q_INT32 i = 0; i < yradius + 1; i++)
01073 delete buf[i];
01074 delete[] buf;
01075 delete[] out;
01076
01077 dev->setDirty(layerSize);
01078 dev->emitSelectionChanged();
01079 }
01080
01081
01082
01083 void KisSelectionManager::smooth()
01084 {
01085 KisImageSP img = m_parent->currentImg();
01086 if (!img) return;
01087
01088 KisPaintDeviceSP dev = img->activeDevice();
01089 if (!dev) return;
01090
01091 if (!dev->hasSelection()) return;
01092 KisSelectionSP selection = dev->selection();
01093
01094
01095 QRect layerSize = dev->exactBounds();
01096
01097 Q_UINT8 *buf[3];
01098
01099 Q_INT32 width = layerSize.width();
01100
01101 for (Q_INT32 i = 0; i < 3; i++) buf[i] = new Q_UINT8[width + 2];
01102
01103 Q_UINT8* out = new Q_UINT8[width];
01104
01105
01106 selection->readBytes(buf[0] + 1, layerSize.x(), layerSize.y(), width, 1);
01107
01108 buf[0][0] = buf[0][1];
01109 buf[0][width + 1] = buf[0][width];
01110
01111 memcpy (buf[1], buf[0], width + 2);
01112
01113 for (Q_INT32 y = 0; y < layerSize.height(); y++)
01114 {
01115 if (y + 1 < layerSize.height())
01116 {
01117 selection->readBytes(buf[2] + 1, layerSize.x(), layerSize.y() + y + 1, width, 1);
01118
01119 buf[2][0] = buf[2][1];
01120 buf[2][width + 1] = buf[2][width];
01121 }
01122 else
01123 {
01124 memcpy (buf[2], buf[1], width + 2);
01125 }
01126
01127 for (Q_INT32 x = 0 ; x < width; x++)
01128 {
01129 Q_INT32 value = (buf[0][x] + buf[0][x+1] + buf[0][x+2] +
01130 buf[1][x] + buf[2][x+1] + buf[1][x+2] +
01131 buf[2][x] + buf[1][x+1] + buf[2][x+2]);
01132
01133 out[x] = value / 9;
01134 }
01135
01136 selection->writeBytes(out, layerSize.x(), layerSize.y() + y, width, 1);
01137
01138 rotatePointers (buf, 3);
01139 }
01140
01141 for (Q_INT32 i = 0; i < 3; i++)
01142 delete[] buf[i];
01143
01144 delete[] out;
01145
01146 dev->setDirty();
01147 dev->emitSelectionChanged();
01148 }
01149
01150
01151
01152 void KisSelectionManager::erode()
01153 {
01154 KisImageSP img = m_parent->currentImg();
01155 if (!img) return;
01156
01157 KisPaintDeviceSP dev = img->activeDevice();
01158 if (!dev) return;
01159
01160 if (!dev->hasSelection()) return;
01161 KisSelectionSP selection = dev->selection();
01162
01163
01164 QRect layerSize = dev->exactBounds();
01165
01166 Q_UINT8* buf[3];
01167
01168
01169 Q_INT32 width = layerSize.width();
01170
01171 for (Q_INT32 i = 0; i < 3; i++)
01172 buf[i] = new Q_UINT8[width + 2];
01173
01174 Q_UINT8* out = new Q_UINT8[width];
01175
01176
01177 selection->readBytes(buf[0] + 1, layerSize.x(), layerSize.y(), width, 1);
01178
01179 buf[0][0] = buf[0][1];
01180 buf[0][width + 1] = buf[0][width];
01181
01182 memcpy (buf[1], buf[0], width + 2);
01183
01184 for (Q_INT32 y = 0; y < layerSize.height(); y++)
01185 {
01186 if (y + 1 < layerSize.height())
01187 {
01188 selection->readBytes(buf[2] + 1, layerSize.x(), layerSize.y() + y + 1, width, 1);
01189
01190 buf[2][0] = buf[2][1];
01191 buf[2][width + 1] = buf[2][width];
01192 }
01193 else
01194 {
01195 memcpy (buf[2], buf[1], width + 2);
01196 }
01197
01198 for (Q_INT32 x = 0 ; x < width; x++)
01199 {
01200 Q_INT32 min = 255;
01201
01202 if (buf[0][x+1] < min) min = buf[0][x+1];
01203 if (buf[1][x] < min) min = buf[1][x];
01204 if (buf[1][x+1] < min) min = buf[1][x+1];
01205 if (buf[1][x+2] < min) min = buf[1][x+2];
01206 if (buf[2][x+1] < min) min = buf[2][x+1];
01207
01208 out[x] = min;
01209 }
01210
01211 selection->writeBytes(out, layerSize.x(), layerSize.y() + y, width, 1);
01212
01213 rotatePointers (buf, 3);
01214 }
01215
01216 for (Q_INT32 i = 0; i < 3; i++)
01217 delete[] buf[i];
01218
01219 delete[] out;
01220
01221 dev->setDirty();
01222 dev->emitSelectionChanged();
01223 }
01224
01225
01226
01227 void KisSelectionManager::dilate()
01228 {
01229 KisImageSP img = m_parent->currentImg();
01230 if (!img) return;
01231
01232 KisPaintDeviceSP dev = img->activeDevice();
01233 if (!dev) return;
01234
01235 if (!dev->hasSelection()) return;
01236 KisSelectionSP selection = dev->selection();
01237
01238
01239 QRect layerSize = dev->exactBounds();
01240
01241 Q_UINT8* buf[3];
01242
01243 Q_INT32 width = layerSize.width();
01244
01245 for (Q_INT32 i = 0; i < 3; i++)
01246 buf[i] = new Q_UINT8[width + 2];
01247
01248 Q_UINT8* out = new Q_UINT8[width];
01249
01250
01251 selection->readBytes(buf[0] + 1, layerSize.x(), layerSize.y(), width, 1);
01252
01253 buf[0][0] = buf[0][1];
01254 buf[0][width + 1] = buf[0][width];
01255
01256 memcpy (buf[1], buf[0], width + 2);
01257
01258 for (Q_INT32 y = 0; y < layerSize.height(); y++)
01259 {
01260 if (y + 1 < layerSize.height())
01261 {
01262 selection->readBytes(buf[2] + 1, layerSize.x(), layerSize.y() + y + 1, width, 1);
01263
01264 buf[2][0] = buf[2][1];
01265 buf[2][width + 1] = buf[2][width];
01266 }
01267 else
01268 {
01269 memcpy (buf[2], buf[1], width + 2);
01270 }
01271
01272 for (Q_INT32 x = 0 ; x < width; x++)
01273 {
01274 Q_INT32 max = 0;
01275
01276 if (buf[0][x+1] > max) max = buf[0][x+1];
01277 if (buf[1][x] > max) max = buf[1][x];
01278 if (buf[1][x+1] > max) max = buf[1][x+1];
01279 if (buf[1][x+2] > max) max = buf[1][x+2];
01280 if (buf[2][x+1] > max) max = buf[2][x+1];
01281
01282 out[x] = max;
01283 }
01284
01285 selection->writeBytes(out, layerSize.x(), layerSize.y() + y, width, 1);
01286
01287 rotatePointers (buf, 3);
01288 }
01289
01290 for (Q_INT32 i = 0; i < 3; i++)
01291 delete[] buf[i];
01292
01293 delete[] out;
01294
01295 dev->setDirty();
01296 dev->emitSelectionChanged();
01297 }
01298
01299 void KisSelectionManager::border(Q_INT32 xradius, Q_INT32 yradius)
01300 {
01301 KisImageSP img = m_parent->currentImg();
01302 if (!img) return;
01303
01304 KisPaintDeviceSP dev = img->activeDevice();
01305 if (!dev) return;
01306
01307 if (!dev->hasSelection()) return;
01308 KisSelectionSP selection = dev->selection();
01309
01310
01311 QRect layerSize = dev->exactBounds();
01312
01313
01314
01315
01316
01317 Q_UINT8 *buf[3];
01318 Q_UINT8 **density;
01319 Q_UINT8 **transition;
01320
01321 if (xradius == 1 && yradius == 1)
01322 {
01323 Q_UINT8* source[3];
01324
01325 for (Q_INT32 i = 0; i < 3; i++)
01326 source[i] = new Q_UINT8[layerSize.width()];
01327
01328 Q_UINT8* transition = new Q_UINT8[layerSize.width()];
01329
01330 selection->readBytes(source[0], layerSize.x(), layerSize.y(), layerSize.width(), 1);
01331 memcpy (source[1], source[0], layerSize.width());
01332 if (layerSize.height() > 1)
01333 selection->readBytes(source[2], layerSize.x(), layerSize.y() + 1, layerSize.width(), 1);
01334 else
01335 memcpy (source[2], source[1], layerSize.width());
01336
01337 computeTransition (transition, source, layerSize.width());
01338 selection->writeBytes(transition, layerSize.x(), layerSize.y(), layerSize.width(), 1);
01339
01340 for (Q_INT32 y = 1; y < layerSize.height(); y++)
01341 {
01342 rotatePointers (source, 3);
01343 if (y + 1 < layerSize.height())
01344 selection->readBytes(source[2], layerSize.x(), layerSize.y() + y + 1, layerSize.width(), 1);
01345 else
01346 memcpy(source[2], source[1], layerSize.width());
01347 computeTransition (transition, source, layerSize.width());
01348 selection->writeBytes(transition, layerSize.x(), layerSize.y() + y, layerSize.width(), 1);
01349 }
01350
01351 for (Q_INT32 i = 0; i < 3; i++)
01352 delete[] source[i];
01353 delete[] transition;
01354 return;
01355 }
01356
01357 Q_INT32* max = new Q_INT32[layerSize.width() + 2 * xradius];
01358 for (Q_INT32 i = 0; i < (layerSize.width() + 2 * xradius); i++)
01359 max[i] = yradius + 2;
01360 max += xradius;
01361
01362 for (Q_INT32 i = 0; i < 3; i++)
01363 buf[i] = new Q_UINT8[layerSize.width()];
01364
01365 transition = new Q_UINT8*[yradius + 1];
01366 for (Q_INT32 i = 0; i < yradius + 1; i++)
01367 {
01368 transition[i] = new Q_UINT8[layerSize.width() + 2 * xradius];
01369 memset(transition[i], 0, layerSize.width() + 2 * xradius);
01370 transition[i] += xradius;
01371 }
01372 Q_UINT8* out = new Q_UINT8[layerSize.width()];
01373 density = new Q_UINT8*[2 * xradius + 1];
01374 density += xradius;
01375
01376 for (Q_INT32 x = 0; x < (xradius + 1); x++)
01377 {
01378 density[ x] = new Q_UINT8[2 * yradius + 1];
01379 density[ x] += yradius;
01380 density[-x] = density[x];
01381 }
01382 for (Q_INT32 x = 0; x < (xradius + 1); x++)
01383 {
01384 double tmpx, tmpy, dist;
01385 Q_UINT8 a;
01386
01387 if (x > 0)
01388 tmpx = x - 0.5;
01389 else if (x < 0)
01390 tmpx = x + 0.5;
01391 else
01392 tmpx = 0.0;
01393
01394 for (Q_INT32 y = 0; y < (yradius + 1); y++)
01395 {
01396 if (y > 0)
01397 tmpy = y - 0.5;
01398 else if (y < 0)
01399 tmpy = y + 0.5;
01400 else
01401 tmpy = 0.0;
01402 dist = ((tmpy * tmpy) / (yradius * yradius) +
01403 (tmpx * tmpx) / (xradius * xradius));
01404 if (dist < 1.0)
01405 a = 255 * (Q_UINT8)(1.0 - sqrt (dist));
01406 else
01407 a = 0;
01408 density[ x][ y] = a;
01409 density[ x][-y] = a;
01410 density[-x][ y] = a;
01411 density[-x][-y] = a;
01412 }
01413 }
01414 selection->readBytes(buf[0], layerSize.x(), layerSize.y(), layerSize.width(), 1);
01415 memcpy (buf[1], buf[0], layerSize.width());
01416 if (layerSize.height() > 1)
01417 selection->readBytes(buf[2], layerSize.x(), layerSize.y() + 1, layerSize.width(), 1);
01418 else
01419 memcpy (buf[2], buf[1], layerSize.width());
01420 computeTransition (transition[1], buf, layerSize.width());
01421
01422 for (Q_INT32 y = 1; y < yradius && y + 1 < layerSize.height(); y++)
01423 {
01424 rotatePointers (buf, 3);
01425 selection->readBytes(buf[2], layerSize.x(), layerSize.y() + y + 1, layerSize.width(), 1);
01426 computeTransition (transition[y + 1], buf, layerSize.width());
01427 }
01428 for (Q_INT32 x = 0; x < layerSize.width(); x++)
01429 {
01430 max[x] = -(yradius + 7);
01431 for (Q_INT32 j = 1; j < yradius + 1; j++)
01432 if (transition[j][x])
01433 {
01434 max[x] = j;
01435 break;
01436 }
01437 }
01438 for (Q_INT32 y = 0; y < layerSize.height(); y++)
01439 {
01440 rotatePointers (buf, 3);
01441 rotatePointers (transition, yradius + 1);
01442 if (y < layerSize.height() - (yradius + 1))
01443 {
01444 selection->readBytes(buf[2], layerSize.x(), layerSize.y() + y + yradius + 1, layerSize.width(), 1);
01445 computeTransition (transition[yradius], buf, layerSize.width());
01446 }
01447 else
01448 memcpy (transition[yradius], transition[yradius - 1], layerSize.width());
01449
01450 for (Q_INT32 x = 0; x < layerSize.width(); x++)
01451 {
01452 if (max[x] < 1)
01453 {
01454 if (max[x] <= -yradius)
01455 {
01456 if (transition[yradius][x])
01457 max[x] = yradius;
01458 else
01459 max[x]--;
01460 }
01461 else
01462 if (transition[-max[x]][x])
01463 max[x] = -max[x];
01464 else if (transition[-max[x] + 1][x])
01465 max[x] = -max[x] + 1;
01466 else
01467 max[x]--;
01468 }
01469 else
01470 max[x]--;
01471 if (max[x] < -yradius - 1)
01472 max[x] = -yradius - 1;
01473 }
01474 Q_UINT8 last_max = max[0][density[-1]];
01475 Q_INT32 last_index = 1;
01476 for (Q_INT32 x = 0 ; x < layerSize.width(); x++)
01477 {
01478 last_index--;
01479 if (last_index >= 0)
01480 {
01481 last_max = 0;
01482 for (Q_INT32 i = xradius; i >= 0; i--)
01483 if (max[x + i] <= yradius && max[x + i] >= -yradius && density[i][max[x+i]] > last_max)
01484 {
01485 last_max = density[i][max[x + i]];
01486 last_index = i;
01487 }
01488 out[x] = last_max;
01489 }
01490 else
01491 {
01492 last_max = 0;
01493 for (Q_INT32 i = xradius; i >= -xradius; i--)
01494 if (max[x + i] <= yradius && max[x + i] >= -yradius && density[i][max[x + i]] > last_max)
01495 {
01496 last_max = density[i][max[x + i]];
01497 last_index = i;
01498 }
01499 out[x] = last_max;
01500 }
01501 if (last_max == 0)
01502 {
01503 Q_INT32 i;
01504 for (i = x + 1; i < layerSize.width(); i++)
01505 {
01506 if (max[i] >= -yradius)
01507 break;
01508 }
01509 if (i - x > xradius)
01510 {
01511 for (; x < i - xradius; x++)
01512 out[x] = 0;
01513 x--;
01514 }
01515 last_index = xradius;
01516 }
01517 }
01518 selection->writeBytes(out, layerSize.x(), layerSize.y() + y, layerSize.width(), 1);
01519 }
01520 delete [] out;
01521
01522 for (Q_INT32 i = 0; i < 3; i++)
01523 delete buf[i];
01524
01525 max -= xradius;
01526 delete[] max;
01527
01528 for (Q_INT32 i = 0; i < yradius + 1; i++)
01529 {
01530 transition[i] -= xradius;
01531 delete transition[i];
01532 }
01533 delete[] transition;
01534
01535 for (Q_INT32 i = 0; i < xradius + 1 ; i++)
01536 {
01537 density[i] -= yradius;
01538 delete density[i];
01539 }
01540 density -= xradius;
01541 delete[] density;
01542
01543 dev->setDirty();
01544 dev->emitSelectionChanged();
01545 }
01546
01547 #define RINT(x) floor ((x) + 0.5)
01548
01549 void KisSelectionManager::computeBorder (Q_INT32 *circ, Q_INT32 xradius, Q_INT32 yradius)
01550 {
01551 Q_ASSERT(xradius != 0);
01552 Q_INT32 i;
01553 Q_INT32 diameter = xradius * 2 + 1;
01554 double tmp;
01555
01556 for (i = 0; i < diameter; i++)
01557 {
01558 if (i > xradius)
01559 tmp = (i - xradius) - 0.5;
01560 else if (i < xradius)
01561 tmp = (xradius - i) - 0.5;
01562 else
01563 tmp = 0.0;
01564
01565 circ[i] = (Q_INT32) RINT (yradius / (double) xradius * sqrt (xradius * xradius - tmp * tmp));
01566 }
01567 }
01568
01569 void KisSelectionManager::rotatePointers (Q_UINT8 **p, Q_UINT32 n)
01570 {
01571 Q_UINT32 i;
01572 Q_UINT8 *tmp;
01573
01574 tmp = p[0];
01575
01576 for (i = 0; i < n - 1; i++) p[i] = p[i + 1];
01577
01578 p[i] = tmp;
01579 }
01580
01581 void KisSelectionManager::computeTransition (Q_UINT8* transition, Q_UINT8** buf, Q_INT32 width)
01582 {
01583 Q_INT32 x = 0;
01584
01585 if (width == 1)
01586 {
01587 if (buf[1][x] > 127 && (buf[0][x] < 128 || buf[2][x] < 128))
01588 transition[x] = 255;
01589 else
01590 transition[x] = 0;
01591 return;
01592 }
01593 if (buf[1][x] > 127)
01594 {
01595 if ( buf[0][x] < 128 || buf[0][x + 1] < 128 ||
01596 buf[1][x + 1] < 128 ||
01597 buf[2][x] < 128 || buf[2][x + 1] < 128 )
01598 transition[x] = 255;
01599 else
01600 transition[x] = 0;
01601 }
01602 else
01603 transition[x] = 0;
01604 for (Q_INT32 x = 1; x < width - 1; x++)
01605 {
01606 if (buf[1][x] >= 128)
01607 {
01608 if (buf[0][x - 1] < 128 || buf[0][x] < 128 || buf[0][x + 1] < 128 ||
01609 buf[1][x - 1] < 128 || buf[1][x + 1] < 128 ||
01610 buf[2][x - 1] < 128 || buf[2][x] < 128 || buf[2][x + 1] < 128)
01611 transition[x] = 255;
01612 else
01613 transition[x] = 0;
01614 }
01615 else
01616 transition[x] = 0;
01617 }
01618 if (buf[1][x] >= 128)
01619 {
01620 if (buf[0][x - 1] < 128 || buf[0][x] < 128 ||
01621 buf[1][x - 1] < 128 ||
01622 buf[2][x - 1] < 128 || buf[2][x] < 128)
01623 transition[x] = 255;
01624 else
01625 transition[x] = 0;
01626 }
01627 else
01628 transition[x] = 0;
01629 }
01630
01631 #include "kis_selection_manager.moc"