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