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