diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-06-26 00:41:16 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-06-26 00:41:16 +0000 |
commit | 698569f8428ca088f764d704034a1330517b98c0 (patch) | |
tree | bf45be6946ebbbee9cce5a5bcf838f4c952d87e6 /chalk/ui/kis_selection_manager.cc | |
parent | 2785103a6bd4de55bd26d79e34d0fdd4b329a73a (diff) | |
download | koffice-698569f8428ca088f764d704034a1330517b98c0.tar.gz koffice-698569f8428ca088f764d704034a1330517b98c0.zip |
Finish rebranding of Krita as Chalk
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1238363 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'chalk/ui/kis_selection_manager.cc')
-rw-r--r-- | chalk/ui/kis_selection_manager.cc | 1643 |
1 files changed, 1643 insertions, 0 deletions
diff --git a/chalk/ui/kis_selection_manager.cc b/chalk/ui/kis_selection_manager.cc new file mode 100644 index 00000000..3caba5e7 --- /dev/null +++ b/chalk/ui/kis_selection_manager.cc @@ -0,0 +1,1643 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <tqobject.h> +#include <tqapplication.h> +#include <tqclipboard.h> +#include <tqcolor.h> +#include <tqcursor.h> + +#include <kdebug.h> +#include <kaction.h> +#include <klocale.h> +#include <kstdaction.h> + +#include <KoDocument.h> +#include <KoMainWindow.h> +#include <KoQueryTrader.h> + +#include "kis_cursor.h" +#include "kis_part_layer.h" +#include "kis_adjustment_layer.h" +#include "kis_clipboard.h" +#include "kis_types.h" +#include "kis_view.h" +#include "kis_doc.h" +#include "kis_image.h" +#include "kis_selection.h" +#include "kis_selection_manager.h" +#include "kis_painter.h" +#include "kis_iterators_pixel.h" +#include "kis_iteratorpixeltrait.h" +#include "kis_layer.h" +#include "kis_group_layer.h" +#include "kis_paint_layer.h" +#include "kis_paint_device.h" +#include "kis_channelinfo.h" +#include "kis_dlg_apply_profile.h" +#include "kis_config.h" +#include "kis_debug_areas.h" +#include "kis_transaction.h" +#include "kis_undo_adapter.h" +#include "kis_selected_transaction.h" +#include "kis_convolution_painter.h" +#include "kis_integer_maths.h" +#include "kis_fill_painter.h" +#include "kis_canvas.h" + +KisSelectionManager::KisSelectionManager(KisView * tqparent, KisDoc * doc) + : m_parent(tqparent), + m_doc(doc), + m_copy(0), + m_cut(0), + m_paste(0), + m_pasteNew(0), + m_cutToNewLayer(0), + m_selectAll(0), + m_deselect(0), + m_clear(0), + m_reselect(0), + m_invert(0), + m_toNewLayer(0), + m_feather(0), + m_border(0), + m_expand(0), + m_smooth(0), + m_contract(0), + m_similar(0), + m_transform(0), + m_load(0), + m_save(0), + m_fillForegroundColor(0), + m_fillBackgroundColor(0), + m_fillPattern(0) +{ + m_pluginActions.setAutoDelete(true); + m_clipboard = KisClipboard::instance(); +} + +KisSelectionManager::~KisSelectionManager() +{ + m_pluginActions.clear(); +} + + +void KisSelectionManager::setup(KActionCollection * collection) +{ + // XXX: setup shortcuts! + + m_cut = KStdAction::cut(this, + TQT_SLOT(cut()), + collection, + "cut"); + + m_copy = KStdAction::copy(this, + TQT_SLOT(copy()), + collection, + "copy"); + + m_paste = KStdAction::paste(this, + TQT_SLOT(paste()), + collection, + "paste"); + + m_pasteNew = new KAction(i18n("Paste into &New Image"), + 0, 0, + this, TQT_SLOT(pasteNew()), + collection, + "paste_new"); + + + m_selectAll = KStdAction::selectAll(this, + TQT_SLOT(selectAll()), + collection, + "select_all"); + + m_deselect = KStdAction::deselect(this, + TQT_SLOT(deselect()), + collection, + "deselect"); + + + m_clear = KStdAction::clear(this, + TQT_SLOT(clear()), + collection, + "clear"); + + m_reselect = new KAction(i18n("&Reselect"), + 0, "Ctrl+Shift+D", + this, TQT_SLOT(reselect()), + collection, "reselect"); + + m_invert = new KAction(i18n("&Invert"), + 0, "Ctrl+I", + this, TQT_SLOT(invert()), + collection, "invert"); + + + m_toNewLayer = new KAction(i18n("Copy Selection to New Layer"), + 0, "Ctrl+J", + this, TQT_SLOT(copySelectionToNewLayer()), + collection, "copy_selection_to_new_layer"); + + + m_cutToNewLayer = new KAction(i18n("Cut Selection to New Layer"), + 0, "Ctrl+Shift+J", + this, TQT_SLOT(cutToNewLayer()), + collection, "cut_selection_to_new_layer"); + + m_feather = new KAction(i18n("Feather"), + 0, "Ctrl+Alt+D", + this, TQT_SLOT(feather()), + collection, "feather"); + + m_fillForegroundColor = new KAction(i18n("Fill with Foreground Color"), + "Alt+backspace", this, + TQT_SLOT(fillForegroundColor()), + collection, + "fill_selection_foreground_color"); + m_fillBackgroundColor = new KAction(i18n("Fill with Background Color"), + "backspace", this, + TQT_SLOT(fillBackgroundColor()), + collection, + "fill_selection_background_color"); + m_fillPattern = new KAction(i18n("Fill with Pattern"), + 0, this, + TQT_SLOT(fillPattern()), + collection, + "fill_selection_pattern"); + + m_toggleDisplaySelection = new KToggleAction(i18n("Display Selection"), "Ctrl+h", this, TQT_SLOT(toggleDisplaySelection()), collection, "toggle_display_selection"); + m_toggleDisplaySelection->setCheckedState(KGuiItem(i18n("Hide Selection"))); + m_toggleDisplaySelection->setChecked(true); + + m_border = + new KAction(i18n("Border..."), + 0, 0, + this, TQT_SLOT(border()), + collection, "border"); + m_expand = + new KAction(i18n("Expand..."), + 0, 0, + this, TQT_SLOT(expand()), + collection, "expand"); + + m_smooth = + new KAction(i18n("Smooth..."), + 0, 0, + this, TQT_SLOT(smooth()), + collection, "smooth"); + + + m_contract = + new KAction(i18n("Contract..."), + 0, 0, + this, TQT_SLOT(contract()), + collection, "contract"); + m_similar = + new KAction(i18n("Similar"), + 0, 0, + this, TQT_SLOT(similar()), + collection, "similar"); + + + m_transform + = new KAction(i18n("Transform..."), + 0, 0, + this, TQT_SLOT(transform()), + collection, "transform_selection"); + + +// m_load +// = new KAction(i18n("Load..."), +// 0, 0, +// this, TQT_SLOT(load()), +// collection, "load_selection"); +// +// +// m_save +// = new KAction(i18n("Save As..."), +// 0, 0, +// this, TQT_SLOT(save()), +// collection, "save_selection"); + + TQClipboard *cb = TQApplication::tqclipboard(); + connect(cb, TQT_SIGNAL(dataChanged()), TQT_SLOT(clipboardDataChanged())); +} + +void KisSelectionManager::clipboardDataChanged() +{ + updateGUI(); +} + + +void KisSelectionManager::addSelectionAction(KAction * action) +{ + m_pluginActions.append(action); +} + + +void KisSelectionManager::updateGUI() +{ + Q_ASSERT(m_parent); + Q_ASSERT(m_clipboard); + + if (m_parent == 0) { + // "Eek, no tqparent! + return; + } + + if (m_clipboard == 0) { + // Eek, no clipboard! + return; + } + + KisImageSP img = m_parent->currentImg(); + KisLayerSP l = 0; + KisPaintDeviceSP dev = 0; + + bool enable = false; + if (img && img->activeDevice() && img->activeLayer()) { + l = img->activeLayer(); + dev = img->activeDevice(); + + + KisPartLayer * partLayer = dynamic_cast<KisPartLayer*>(l.data()); + KisAdjustmentLayer * adjLayer = dynamic_cast<KisAdjustmentLayer*>(l.data()); + + enable = l && dev&& dev->hasSelection() && !l->locked() && l->visible() && (partLayer==0); + + if(dev && !adjLayer) + m_reselect->setEnabled( dev->selectionDeselected() ); + if (adjLayer) // There's no reselect for adjustment layers + m_reselect->setEnabled(false); + } + + m_cut->setEnabled(enable); + m_cutToNewLayer->setEnabled(enable); + m_selectAll->setEnabled(img != 0); + m_deselect->setEnabled(enable); + m_clear->setEnabled(enable); + m_fillForegroundColor->setEnabled(enable); + m_fillBackgroundColor->setEnabled(enable); + m_fillPattern->setEnabled(enable); + m_invert->setEnabled(enable); + + m_feather->setEnabled(enable); + + m_border->setEnabled(enable); + m_expand->setEnabled(enable); + m_smooth->setEnabled(enable); + m_contract->setEnabled(enable); + m_similar->setEnabled(enable); + m_transform->setEnabled(enable); +// m_load->setEnabled(enable); +// m_save->setEnabled(enable); + + + KAction * a; + for (a = m_pluginActions.first(); a; a = m_pluginActions.next()) { + a->setEnabled(img != 0); + } + + // You can copy from locked layers and paste the clip into a new layer, even when + // the current layer is locked. + enable = false; + if (img && l && dev) { + enable = dev->hasSelection() && l->visible(); + } + + m_copy->setEnabled(enable); + m_paste->setEnabled(img != 0 && m_clipboard->hasClip()); + m_pasteNew->setEnabled(img != 0 && m_clipboard->hasClip()); + m_toNewLayer->setEnabled(enable); + + m_parent->updateStatusBarSelectionLabel(); + +} + +void KisSelectionManager::imgSelectionChanged(KisImageSP img) +{ + if (img == m_parent->currentImg()) { + updateGUI(); + } +} + +void KisSelectionManager::cut() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + + copy(); + + KisSelectedTransaction *t = 0; + + if (img->undo()) { + t = new KisSelectedTransaction(i18n("Cut"), dev); + Q_CHECK_PTR(t); + } + + dev->clearSelection(); + dev->deselect(); + dev->emitSelectionChanged(); + + if (img->undo()) { + img->undoAdapter()->addCommand(t); + } +} + +void KisSelectionManager::copy() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + + KisSelectionSP selection = dev->selection(); + + TQRect r = selection->selectedExactRect(); + + KisPaintDeviceSP clip = new KisPaintDevice(dev->colorSpace(), "clip"); + Q_CHECK_PTR(clip); + + KisColorSpace * cs = clip->colorSpace(); + + // TODO if the source is linked... copy from all linked layers?!? + + // Copy image data + KisPainter gc; + gc.begin(clip); + gc.bitBlt(0, 0, COMPOSITE_COPY, dev, r.x(), r.y(), r.width(), r.height()); + gc.end(); + + // Apply selection tqmask. + + for (TQ_INT32 y = 0; y < r.height(); y++) { + KisHLineIteratorPixel layerIt = clip->createHLineIterator(0, y, r.width(), true); + KisHLineIteratorPixel selectionIt = selection->createHLineIterator(r.x(), r.y() + y, r.width(), false); + + while (!layerIt.isDone()) { + + cs->applyAlphaU8Mask( layerIt.rawData(), selectionIt.rawData(), 1 ); + + + ++layerIt; + ++selectionIt; + } + } + + m_clipboard->setClip(clip); + imgSelectionChanged(m_parent->currentImg()); +} + + +KisLayerSP KisSelectionManager::paste() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return 0; + + KisPaintDeviceSP clip = m_clipboard->clip(); + + if (clip) { + TQApplication::setOverrideCursor(KisCursor::waitCursor()); + KisPaintLayer *layer = new KisPaintLayer(img, img->nextLayerName() + i18n("(pasted)"), OPACITY_OPAQUE); + Q_CHECK_PTR(layer); + + TQRect r = clip->exactBounds(); + KisPainter gc; + gc.begin(layer->paintDevice()); + gc.bitBlt(0, 0, COMPOSITE_COPY, clip, r.x(), r.y(), r.width(), r.height()); + gc.end(); + + //figure out where to position the clip + KisCanvasController *cc = m_parent->getCanvasController(); + TQPoint center = cc->viewToWindow(TQPoint(cc->kiscanvas()->width()/2, cc->kiscanvas()->height()/2)); + TQPoint bottomright = cc->viewToWindow(TQPoint(cc->kiscanvas()->width(), cc->kiscanvas()->height())); + if(bottomright.x() > img->width()) + center.setX(img->width()/2); + if(bottomright.y() > img->height()) + center.setY(img->height()/2); + center -= TQPoint(r.width()/2, r.height()/2); + layer->setX(center.x()); + layer->setY(center.y()); + +/*XXX CBR have an idea of asking the user if he is about to paste a clip ion another cs than that of + the image if that is what he want rather than silently converting + if (clip->colorSpace != img ->colorSpace()) + if (dlg->exec() == TQDialog::Accepted) + layer->convertTo(img->colorSpace()); +*/ + TQApplication::restoreOverrideCursor(); + if(img->addLayer(layer, img->activeLayer()->tqparent(), img->activeLayer())) + { + return layer; + } else { + return 0; + } + } + return 0; +} + +void KisSelectionManager::pasteNew() +{ + KisPaintDeviceSP clip = m_clipboard->clip(); + if (!clip) return; + + TQRect r = clip->exactBounds(); + if (r.width() < 1 && r.height() < 1) { + // Don't paste empty clips + return; + } + + const TQCString mimetype = KoDocument::readNativeFormatMimeType(); + KoDocumentEntry entry = KoDocumentEntry::queryByMimeType( mimetype ); + KisDoc * doc = (KisDoc*) entry.createDoc(); + + Q_ASSERT(doc->undoAdapter() != 0); + doc->undoAdapter()->setUndo(false); + + KisImageSP img = new KisImage(doc->undoAdapter(), r.width(), r.height(), clip->colorSpace(), "Pasted"); + KisPaintLayer *layer = new KisPaintLayer(img, clip->name(), OPACITY_OPAQUE, clip->colorSpace()); + + KisPainter p(layer->paintDevice()); + p.bitBlt(0, 0, COMPOSITE_COPY, clip, OPACITY_OPAQUE, r.x(), r.y(), r.width(), r.height()); + p.end(); + + img->addLayer(layer, img->rootLayer(), 0); + doc->setCurrentImage(img); + + doc->undoAdapter()->setUndo(true); + + KoMainWindow *win = new KoMainWindow( doc->instance() ); + win->show(); + win->setRootDocument( doc ); +} + +void KisSelectionManager::selectAll() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + KisSelectedTransaction * t = 0; + if (img->undo()) t = new KisSelectedTransaction(i18n("Select All"), dev); + Q_CHECK_PTR(t); + + // Make adjustment layers behave better + KisAdjustmentLayer* adj = dynamic_cast<KisAdjustmentLayer*>(img->activeLayer().data()); + if (adj) { + adj->clearSelection(); + adj->selection()->invert(); + } else { + dev->selection()->clear(); + dev->selection()->invert(); + } + dev->setDirty(); + dev->emitSelectionChanged(); + + if (img->undo()) + img->undoAdapter()->addCommand(t); +} + +void KisSelectionManager::deselect() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + KisSelectedTransaction * t = 0; + if (img->undo()) t = new KisSelectedTransaction(i18n("Deselect"), dev); + Q_CHECK_PTR(t); + + // Make adjustment layers behave almost the same (except no reselect) + KisAdjustmentLayer* adj = dynamic_cast<KisAdjustmentLayer*>(img->activeLayer().data()); + if (adj) { + adj->clearSelection(); + } else { + dev->deselect(); + } + dev->setDirty(); + dev->emitSelectionChanged(); + + if (img->undo()) + img->undoAdapter()->addCommand(t); +} + + +void KisSelectionManager::clear() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + + KisTransaction * t = 0; + + if (img->undo()) { + t = new KisTransaction(i18n("Clear"), dev); + } + + dev->clearSelection(); + dev->setDirty(); + dev->emitSelectionChanged(); + + if (img->undo()) img->undoAdapter()->addCommand(t); +} + +void KisSelectionManager::fill(const KisColor& color, bool fillWithPattern, const TQString& transactionText) +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + + KisSelectionSP selection = dev->selection(); + + KisPaintDeviceSP filled = new KisPaintDevice(dev->colorSpace()); + KisFillPainter painter(filled); + + if (fillWithPattern) { + painter.fillRect(0, 0, img->width(), img->height(), + m_parent->currentPattern()); + } else { + painter.fillRect(0, 0, img->width(), img->height(), color); + } + + painter.end(); + + KisPainter painter2(dev); + + if (img->undo()) painter2.beginTransaction(transactionText); + painter2.bltSelection(0, 0, COMPOSITE_OVER, filled, OPACITY_OPAQUE, + 0, 0, img->width(), img->height()); + + dev->setDirty(); + dev->emitSelectionChanged(); + + if (img->undo()) { + img->undoAdapter()->addCommand(painter2.endTransaction()); + } +} + +void KisSelectionManager::fillForegroundColor() +{ + fill(m_parent->fgColor(), false, i18n("Fill with Foreground Color")); +} + +void KisSelectionManager::fillBackgroundColor() +{ + fill(m_parent->bgColor(), false, i18n("Fill with Background Color")); +} + +void KisSelectionManager::fillPattern() +{ + fill(KisColor(), true, i18n("Fill with Pattern")); +} + +void KisSelectionManager::reselect() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img ->activeDevice(); + if (!dev) return; + + KisSelectedTransaction * t = 0; + if (img->undo()) t = new KisSelectedTransaction(i18n("Reselect"), dev); + Q_CHECK_PTR(t); + + dev->reselect(); // sets hasSelection=true + dev->setDirty(); + dev->emitSelectionChanged(); + + if (img->undo()) + img->undoAdapter()->addCommand(t); +} + + +void KisSelectionManager::invert() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (dev->hasSelection()) { + KisSelectionSP s = dev->selection(); + + KisSelectedTransaction * t = 0; + if (img->undo()) + { + t = new KisSelectedTransaction(i18n("Invert"), dev); + Q_CHECK_PTR(t); + } + + s->invert(); + dev->setDirty(); + dev->emitSelectionChanged(); + + if (t) { + img->undoAdapter()->addCommand(t); + } + } +} + +void KisSelectionManager::copySelectionToNewLayer() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + copy(); + paste(); +} + +void KisSelectionManager::cutToNewLayer() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + cut(); + paste(); +} + + +void KisSelectionManager::feather() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) { + // activate it, but don't do anything with it + dev->selection(); + return; + } + + KisSelectionSP selection = dev->selection(); + KisSelectedTransaction * t = 0; + if (img->undo()) t = new KisSelectedTransaction(i18n("Feather..."), dev); + Q_CHECK_PTR(t); + + + // XXX: we should let gaussian blur & others influence alpha channels as well + // (on demand of the caller) + + KisConvolutionPainter painter(selection.data()); + + KisKernelSP k = new KisKernel(); + k->width = 3; + k->height = 3; + k->factor = 16; + k->offset = 0; + k->data = new TQ_INT32[9]; + k->data[0] = 1; + k->data[1] = 2; + k->data[2] = 1; + k->data[3] = 2; + k->data[4] = 4; + k->data[5] = 2; + k->data[6] = 1; + k->data[7] = 2; + k->data[8] = 1; + + TQRect rect = selection->selectedRect(); + // Make sure we've got enough space around the edges. + rect = TQRect(rect.x() - 3, rect.y() - 3, rect.width() + 6, rect.height() + 6); + rect &= TQRect(0, 0, img->width(), img->height()); + + painter.applyMatrix(k, rect.x(), rect.y(), rect.width(), rect.height(), BORDER_AVOID, KisChannelInfo::FLAG_ALPHA); + painter.end(); + + dev->setDirty(rect); + dev->emitSelectionChanged(); + + if (img->undo()) + img->undoAdapter()->addCommand(t); + +} + +void KisSelectionManager::toggleDisplaySelection() +{ + m_parent->selectionDisplayToggled(displaySelection()); +} + +bool KisSelectionManager::displaySelection() +{ + return m_toggleDisplaySelection->isChecked(); +} +// XXX: Maybe move these esoteric functions to plugins? +void KisSelectionManager::border() {} +void KisSelectionManager::expand() {} +void KisSelectionManager::contract() {} +void KisSelectionManager::similar() {} +void KisSelectionManager::transform() {} +void KisSelectionManager::load() {} +void KisSelectionManager::save() {} + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +void KisSelectionManager::grow (TQ_INT32 xradius, TQ_INT32 yradius) +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + KisSelectionSP selection = dev->selection(); + + //determine the layerSize + TQRect layerSize = dev->exactBounds(); + /* + Any bugs in this fuction are probably also in thin_region + Blame all bugs in this function on jaycox@gimp.org + */ + + TQ_UINT8 **buf; // caches the region's pixel data + TQ_UINT8 **max; // caches the largest values for each column + + if (xradius <= 0 || yradius <= 0) + return; + + KisSelectedTransaction *t = 0; + + if (img->undo()) { + t = new KisSelectedTransaction(i18n("Grow"), dev); + Q_CHECK_PTR(t); + } + + max = new TQ_UINT8* [layerSize.width() + 2 * xradius]; + buf = new TQ_UINT8* [yradius + 1]; + for (TQ_INT32 i = 0; i < yradius + 1; i++) + { + buf[i] = new TQ_UINT8[layerSize.width()]; + } + TQ_UINT8* buffer = new TQ_UINT8[ ( layerSize.width() + 2 * xradius ) * ( yradius + 1 ) ]; + for (TQ_INT32 i = 0; i < layerSize.width() + 2 * xradius; i++) + { + if (i < xradius) + max[i] = buffer; + else if (i < layerSize.width() + xradius) + max[i] = &buffer[(yradius + 1) * (i - xradius)]; + else + max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius - 1)]; + + for (TQ_INT32 j = 0; j < xradius + 1; j++) + max[i][j] = 0; + } + /* offset the max pointer by xradius so the range of the array + is [-xradius] to [region->w + xradius] */ + max += xradius; + + TQ_UINT8* out = new TQ_UINT8[ layerSize.width() ]; // holds the new scan line we are computing + + TQ_INT32* circ = new TQ_INT32[ 2 * xradius + 1 ]; // holds the y coords of the filter's tqmask + computeBorder (circ, xradius, yradius); + + /* offset the circ pointer by xradius so the range of the array + is [-xradius] to [xradius] */ + circ += xradius; + + memset (buf[0], 0, layerSize.width()); + for (TQ_INT32 i = 0; i < yradius && i < layerSize.height(); i++) // load top of image + { + selection->readBytes(buf[i + 1], layerSize.x(), layerSize.y() + i, layerSize.width(), 1); + } + + for (TQ_INT32 x = 0; x < layerSize.width() ; x++) // set up max for top of image + { + max[x][0] = 0; // buf[0][x] is always 0 + max[x][1] = buf[1][x]; // MAX (buf[1][x], max[x][0]) always = buf[1][x] + for (TQ_INT32 j = 2; j < yradius + 1; j++) + { + max[x][j] = MAX(buf[j][x], max[x][j-1]); + } + } + + for (TQ_INT32 y = 0; y < layerSize.height(); y++) + { + rotatePointers (buf, yradius + 1); + if (y < layerSize.height() - (yradius)) + selection->readBytes(buf[yradius], layerSize.x(), layerSize.y() + y + yradius, layerSize.width(), 1); + else + memset (buf[yradius], 0, layerSize.width()); + for (TQ_INT32 x = 0; x < layerSize.width(); x++) /* update max array */ + { + for (TQ_INT32 i = yradius; i > 0; i--) + { + max[x][i] = MAX (MAX (max[x][i - 1], buf[i - 1][x]), buf[i][x]); + } + max[x][0] = buf[0][x]; + } + TQ_INT32 last_max = max[0][circ[-1]]; + TQ_INT32 last_index = 1; + for (TQ_INT32 x = 0; x < layerSize.width(); x++) /* render scan line */ + { + last_index--; + if (last_index >= 0) + { + if (last_max == 255) + out[x] = 255; + else + { + last_max = 0; + for (TQ_INT32 i = xradius; i >= 0; i--) + if (last_max < max[x + i][circ[i]]) + { + last_max = max[x + i][circ[i]]; + last_index = i; + } + out[x] = last_max; + } + } + else + { + last_index = xradius; + last_max = max[x + xradius][circ[xradius]]; + for (TQ_INT32 i = xradius - 1; i >= -xradius; i--) + if (last_max < max[x + i][circ[i]]) + { + last_max = max[x + i][circ[i]]; + last_index = i; + } + out[x] = last_max; + } + } + selection->writeBytes(out, layerSize.x(), layerSize.y() + y, layerSize.width(), 1); + } + /* undo the offsets to the pointers so we can free the malloced memmory */ + circ -= xradius; + max -= xradius; + //XXXX: replace delete by delete[] where it is necessary to avoid memory leaks! + delete[] circ; + delete[] buffer; + delete[] max; + for (TQ_INT32 i = 0; i < yradius + 1; i++) + delete[] buf[i]; + delete[] buf; + delete[] out; + + dev->setDirty(); + dev->emitSelectionChanged(); + + if (t) { + img->undoAdapter()->addCommand(t); + } +} + +void KisSelectionManager::shrink (TQ_INT32 xradius, TQ_INT32 yradius, bool edge_lock) +{ + + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + KisSelectionSP selection = dev->selection(); + + //determine the layerSize + TQRect layerSize = dev->exactBounds(); + /* + pretty much the same as fatten_region only different + blame all bugs in this function on jaycox@gimp.org + */ + /* If edge_lock is true we assume that pixels outside the region + we are passed are identical to the edge pixels. + If edge_lock is false, we assume that pixels outside the region are 0 + */ + TQ_UINT8 **buf; // caches the the region's pixels + TQ_UINT8 **max; // caches the smallest values for each column + TQ_INT32 last_max, last_index; + + if (xradius <= 0 || yradius <= 0) + return; + + max = new TQ_UINT8* [layerSize.width() + 2 * xradius]; + buf = new TQ_UINT8* [yradius + 1]; + for (TQ_INT32 i = 0; i < yradius + 1; i++) + { + buf[i] = new TQ_UINT8[layerSize.width()]; + } + + TQ_INT32 buffer_size = (layerSize.width() + 2 * xradius + 1) * (yradius + 1); + TQ_UINT8* buffer = new TQ_UINT8[buffer_size]; + + if (edge_lock) + memset(buffer, 255, buffer_size); + else + memset(buffer, 0, buffer_size); + + for (TQ_INT32 i = 0; i < layerSize.width() + 2 * xradius; i++) + { + if (i < xradius) + if (edge_lock) + max[i] = buffer; + else + max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius)]; + else if (i < layerSize.width() + xradius) + max[i] = &buffer[(yradius + 1) * (i - xradius)]; + else + if (edge_lock) + max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius - 1)]; + else + max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius)]; + } + if (!edge_lock) + for (TQ_INT32 j = 0 ; j < xradius + 1; j++) max[0][j] = 0; + + // offset the max pointer by xradius so the range of the array is [-xradius] to [region->w + xradius] + max += xradius; + + TQ_UINT8* out = new TQ_UINT8[layerSize.width()]; // holds the new scan line we are computing + + TQ_INT32* circ = new TQ_INT32[2 * xradius + 1]; // holds the y coords of the filter's tqmask + + computeBorder (circ, xradius, yradius); + + // offset the circ pointer by xradius so the range of the array is [-xradius] to [xradius] + circ += xradius; + + for (TQ_INT32 i = 0; i < yradius && i < layerSize.height(); i++) // load top of image + selection->readBytes(buf[i + 1], layerSize.x(), layerSize.y() + i, layerSize.width(), 1); + + if (edge_lock) + memcpy (buf[0], buf[1], layerSize.width()); + else + memset (buf[0], 0, layerSize.width()); + + + for (TQ_INT32 x = 0; x < layerSize.width(); x++) // set up max for top of image + { + max[x][0] = buf[0][x]; + for (TQ_INT32 j = 1; j < yradius + 1; j++) + max[x][j] = MIN(buf[j][x], max[x][j-1]); + } + + for (TQ_INT32 y = 0; y < layerSize.height(); y++) + { + rotatePointers (buf, yradius + 1); + if (y < layerSize.height() - yradius) + selection->readBytes(buf[yradius], layerSize.x(), layerSize.y() + y + yradius, layerSize.width(), 1); + else if (edge_lock) + memcpy (buf[yradius], buf[yradius - 1], layerSize.width()); + else + memset (buf[yradius], 0, layerSize.width()); + + for (TQ_INT32 x = 0 ; x < layerSize.width(); x++) // update max array + { + for (TQ_INT32 i = yradius; i > 0; i--) + { + max[x][i] = MIN (MIN (max[x][i - 1], buf[i - 1][x]), buf[i][x]); + } + max[x][0] = buf[0][x]; + } + last_max = max[0][circ[-1]]; + last_index = 0; + + for (TQ_INT32 x = 0 ; x < layerSize.width(); x++) // render scan line + { + last_index--; + if (last_index >= 0) + { + if (last_max == 0) + out[x] = 0; + else + { + last_max = 255; + for (TQ_INT32 i = xradius; i >= 0; i--) + if (last_max > max[x + i][circ[i]]) + { + last_max = max[x + i][circ[i]]; + last_index = i; + } + out[x] = last_max; + } + } + else + { + last_index = xradius; + last_max = max[x + xradius][circ[xradius]]; + for (TQ_INT32 i = xradius - 1; i >= -xradius; i--) + if (last_max > max[x + i][circ[i]]) + { + last_max = max[x + i][circ[i]]; + last_index = i; + } + out[x] = last_max; + } + } + selection->writeBytes(out, layerSize.x(), layerSize.y() + y, layerSize.width(), 1); + } + + // undo the offsets to the pointers so we can free the malloced memmory + circ -= xradius; + max -= xradius; + //free the memmory + //XXXX: replace delete by delete[] where it is necessary to avoid memory leaks! + delete[] circ; + delete[] buffer; + delete[] max; + for (TQ_INT32 i = 0; i < yradius + 1; i++) + delete buf[i]; + delete[] buf; + delete[] out; + + dev->setDirty(layerSize); + dev->emitSelectionChanged(); +} + +//Simple convolution filter to smooth a tqmask (1bpp) + +void KisSelectionManager::smooth() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + KisSelectionSP selection = dev->selection(); + + //determine the layerSize + TQRect layerSize = dev->exactBounds(); + + TQ_UINT8 *buf[3]; + + TQ_INT32 width = layerSize.width(); + + for (TQ_INT32 i = 0; i < 3; i++) buf[i] = new TQ_UINT8[width + 2]; + + TQ_UINT8* out = new TQ_UINT8[width]; + + // load top of image + selection->readBytes(buf[0] + 1, layerSize.x(), layerSize.y(), width, 1); + + buf[0][0] = buf[0][1]; + buf[0][width + 1] = buf[0][width]; + + memcpy (buf[1], buf[0], width + 2); + + for (TQ_INT32 y = 0; y < layerSize.height(); y++) + { + if (y + 1 < layerSize.height()) + { + selection->readBytes(buf[2] + 1, layerSize.x(), layerSize.y() + y + 1, width, 1); + + buf[2][0] = buf[2][1]; + buf[2][width + 1] = buf[2][width]; + } + else + { + memcpy (buf[2], buf[1], width + 2); + } + + for (TQ_INT32 x = 0 ; x < width; x++) + { + TQ_INT32 value = (buf[0][x] + buf[0][x+1] + buf[0][x+2] + + buf[1][x] + buf[2][x+1] + buf[1][x+2] + + buf[2][x] + buf[1][x+1] + buf[2][x+2]); + + out[x] = value / 9; + } + + selection->writeBytes(out, layerSize.x(), layerSize.y() + y, width, 1); + + rotatePointers (buf, 3); + } + + for (TQ_INT32 i = 0; i < 3; i++) + delete[] buf[i]; + + delete[] out; + + dev->setDirty(); + dev->emitSelectionChanged(); +} + +// Erode (radius 1 pixel) a tqmask (1bpp) + +void KisSelectionManager::erode() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + KisSelectionSP selection = dev->selection(); + + //determine the layerSize + TQRect layerSize = dev->exactBounds(); + + TQ_UINT8* buf[3]; + + + TQ_INT32 width = layerSize.width(); + + for (TQ_INT32 i = 0; i < 3; i++) + buf[i] = new TQ_UINT8[width + 2]; + + TQ_UINT8* out = new TQ_UINT8[width]; + + // load top of image + selection->readBytes(buf[0] + 1, layerSize.x(), layerSize.y(), width, 1); + + buf[0][0] = buf[0][1]; + buf[0][width + 1] = buf[0][width]; + + memcpy (buf[1], buf[0], width + 2); + + for (TQ_INT32 y = 0; y < layerSize.height(); y++) + { + if (y + 1 < layerSize.height()) + { + selection->readBytes(buf[2] + 1, layerSize.x(), layerSize.y() + y + 1, width, 1); + + buf[2][0] = buf[2][1]; + buf[2][width + 1] = buf[2][width]; + } + else + { + memcpy (buf[2], buf[1], width + 2); + } + + for (TQ_INT32 x = 0 ; x < width; x++) + { + TQ_INT32 min = 255; + + if (buf[0][x+1] < min) min = buf[0][x+1]; + if (buf[1][x] < min) min = buf[1][x]; + if (buf[1][x+1] < min) min = buf[1][x+1]; + if (buf[1][x+2] < min) min = buf[1][x+2]; + if (buf[2][x+1] < min) min = buf[2][x+1]; + + out[x] = min; + } + + selection->writeBytes(out, layerSize.x(), layerSize.y() + y, width, 1); + + rotatePointers (buf, 3); + } + + for (TQ_INT32 i = 0; i < 3; i++) + delete[] buf[i]; + + delete[] out; + + dev->setDirty(); + dev->emitSelectionChanged(); +} + +// dilate (radius 1 pixel) a tqmask (1bpp) + +void KisSelectionManager::dilate() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + KisSelectionSP selection = dev->selection(); + + //determine the layerSize + TQRect layerSize = dev->exactBounds(); + + TQ_UINT8* buf[3]; + + TQ_INT32 width = layerSize.width(); + + for (TQ_INT32 i = 0; i < 3; i++) + buf[i] = new TQ_UINT8[width + 2]; + + TQ_UINT8* out = new TQ_UINT8[width]; + + // load top of image + selection->readBytes(buf[0] + 1, layerSize.x(), layerSize.y(), width, 1); + + buf[0][0] = buf[0][1]; + buf[0][width + 1] = buf[0][width]; + + memcpy (buf[1], buf[0], width + 2); + + for (TQ_INT32 y = 0; y < layerSize.height(); y++) + { + if (y + 1 < layerSize.height()) + { + selection->readBytes(buf[2] + 1, layerSize.x(), layerSize.y() + y + 1, width, 1); + + buf[2][0] = buf[2][1]; + buf[2][width + 1] = buf[2][width]; + } + else + { + memcpy (buf[2], buf[1], width + 2); + } + + for (TQ_INT32 x = 0 ; x < width; x++) + { + TQ_INT32 max = 0; + + if (buf[0][x+1] > max) max = buf[0][x+1]; + if (buf[1][x] > max) max = buf[1][x]; + if (buf[1][x+1] > max) max = buf[1][x+1]; + if (buf[1][x+2] > max) max = buf[1][x+2]; + if (buf[2][x+1] > max) max = buf[2][x+1]; + + out[x] = max; + } + + selection->writeBytes(out, layerSize.x(), layerSize.y() + y, width, 1); + + rotatePointers (buf, 3); + } + + for (TQ_INT32 i = 0; i < 3; i++) + delete[] buf[i]; + + delete[] out; + + dev->setDirty(); + dev->emitSelectionChanged(); +} + +void KisSelectionManager::border(TQ_INT32 xradius, TQ_INT32 yradius) +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + KisSelectionSP selection = dev->selection(); + + //determine the layerSize + TQRect layerSize = dev->exactBounds(); + + /* + This function has no bugs, but if you imagine some you can + blame them on jaycox@gimp.org + */ + TQ_UINT8 *buf[3]; + TQ_UINT8 **density; + TQ_UINT8 **transition; + + if (xradius == 1 && yradius == 1) // optimize this case specifically + { + TQ_UINT8* source[3]; + + for (TQ_INT32 i = 0; i < 3; i++) + source[i] = new TQ_UINT8[layerSize.width()]; + + TQ_UINT8* transition = new TQ_UINT8[layerSize.width()]; + + selection->readBytes(source[0], layerSize.x(), layerSize.y(), layerSize.width(), 1); + memcpy (source[1], source[0], layerSize.width()); + if (layerSize.height() > 1) + selection->readBytes(source[2], layerSize.x(), layerSize.y() + 1, layerSize.width(), 1); + else + memcpy (source[2], source[1], layerSize.width()); + + computeTransition (transition, source, layerSize.width()); + selection->writeBytes(transition, layerSize.x(), layerSize.y(), layerSize.width(), 1); + + for (TQ_INT32 y = 1; y < layerSize.height(); y++) + { + rotatePointers (source, 3); + if (y + 1 < layerSize.height()) + selection->readBytes(source[2], layerSize.x(), layerSize.y() + y + 1, layerSize.width(), 1); + else + memcpy(source[2], source[1], layerSize.width()); + computeTransition (transition, source, layerSize.width()); + selection->writeBytes(transition, layerSize.x(), layerSize.y() + y, layerSize.width(), 1); + } + + for (TQ_INT32 i = 0; i < 3; i++) + delete[] source[i]; + delete[] transition; + return; + } + + TQ_INT32* max = new TQ_INT32[layerSize.width() + 2 * xradius]; + for (TQ_INT32 i = 0; i < (layerSize.width() + 2 * xradius); i++) + max[i] = yradius + 2; + max += xradius; + + for (TQ_INT32 i = 0; i < 3; i++) + buf[i] = new TQ_UINT8[layerSize.width()]; + + transition = new TQ_UINT8*[yradius + 1]; + for (TQ_INT32 i = 0; i < yradius + 1; i++) + { + transition[i] = new TQ_UINT8[layerSize.width() + 2 * xradius]; + memset(transition[i], 0, layerSize.width() + 2 * xradius); + transition[i] += xradius; + } + TQ_UINT8* out = new TQ_UINT8[layerSize.width()]; + density = new TQ_UINT8*[2 * xradius + 1]; + density += xradius; + + for (TQ_INT32 x = 0; x < (xradius + 1); x++) // allocate density[][] + { + density[ x] = new TQ_UINT8[2 * yradius + 1]; + density[ x] += yradius; + density[-x] = density[x]; + } + for (TQ_INT32 x = 0; x < (xradius + 1); x++) // compute density[][] + { + double tmpx, tmpy, dist; + TQ_UINT8 a; + + if (x > 0) + tmpx = x - 0.5; + else if (x < 0) + tmpx = x + 0.5; + else + tmpx = 0.0; + + for (TQ_INT32 y = 0; y < (yradius + 1); y++) + { + if (y > 0) + tmpy = y - 0.5; + else if (y < 0) + tmpy = y + 0.5; + else + tmpy = 0.0; + dist = ((tmpy * tmpy) / (yradius * yradius) + + (tmpx * tmpx) / (xradius * xradius)); + if (dist < 1.0) + a = 255 * (TQ_UINT8)(1.0 - sqrt (dist)); + else + a = 0; + density[ x][ y] = a; + density[ x][-y] = a; + density[-x][ y] = a; + density[-x][-y] = a; + } + } + selection->readBytes(buf[0], layerSize.x(), layerSize.y(), layerSize.width(), 1); + memcpy (buf[1], buf[0], layerSize.width()); + if (layerSize.height() > 1) + selection->readBytes(buf[2], layerSize.x(), layerSize.y() + 1, layerSize.width(), 1); + else + memcpy (buf[2], buf[1], layerSize.width()); + computeTransition (transition[1], buf, layerSize.width()); + + for (TQ_INT32 y = 1; y < yradius && y + 1 < layerSize.height(); y++) // set up top of image + { + rotatePointers (buf, 3); + selection->readBytes(buf[2], layerSize.x(), layerSize.y() + y + 1, layerSize.width(), 1); + computeTransition (transition[y + 1], buf, layerSize.width()); + } + for (TQ_INT32 x = 0; x < layerSize.width(); x++) // set up max[] for top of image + { + max[x] = -(yradius + 7); + for (TQ_INT32 j = 1; j < yradius + 1; j++) + if (transition[j][x]) + { + max[x] = j; + break; + } + } + for (TQ_INT32 y = 0; y < layerSize.height(); y++) // main calculation loop + { + rotatePointers (buf, 3); + rotatePointers (transition, yradius + 1); + if (y < layerSize.height() - (yradius + 1)) + { + selection->readBytes(buf[2], layerSize.x(), layerSize.y() + y + yradius + 1, layerSize.width(), 1); + computeTransition (transition[yradius], buf, layerSize.width()); + } + else + memcpy (transition[yradius], transition[yradius - 1], layerSize.width()); + + for (TQ_INT32 x = 0; x < layerSize.width(); x++) // update max array + { + if (max[x] < 1) + { + if (max[x] <= -yradius) + { + if (transition[yradius][x]) + max[x] = yradius; + else + max[x]--; + } + else + if (transition[-max[x]][x]) + max[x] = -max[x]; + else if (transition[-max[x] + 1][x]) + max[x] = -max[x] + 1; + else + max[x]--; + } + else + max[x]--; + if (max[x] < -yradius - 1) + max[x] = -yradius - 1; + } + TQ_UINT8 last_max = max[0][density[-1]]; + TQ_INT32 last_index = 1; + for (TQ_INT32 x = 0 ; x < layerSize.width(); x++) // render scan line + { + last_index--; + if (last_index >= 0) + { + last_max = 0; + for (TQ_INT32 i = xradius; i >= 0; i--) + if (max[x + i] <= yradius && max[x + i] >= -yradius && density[i][max[x+i]] > last_max) + { + last_max = density[i][max[x + i]]; + last_index = i; + } + out[x] = last_max; + } + else + { + last_max = 0; + for (TQ_INT32 i = xradius; i >= -xradius; i--) + if (max[x + i] <= yradius && max[x + i] >= -yradius && density[i][max[x + i]] > last_max) + { + last_max = density[i][max[x + i]]; + last_index = i; + } + out[x] = last_max; + } + if (last_max == 0) + { + TQ_INT32 i; + for (i = x + 1; i < layerSize.width(); i++) + { + if (max[i] >= -yradius) + break; + } + if (i - x > xradius) + { + for (; x < i - xradius; x++) + out[x] = 0; + x--; + } + last_index = xradius; + } + } + selection->writeBytes(out, layerSize.x(), layerSize.y() + y, layerSize.width(), 1); + } + delete [] out; + + for (TQ_INT32 i = 0; i < 3; i++) + delete buf[i]; + + max -= xradius; + delete[] max; + + for (TQ_INT32 i = 0; i < yradius + 1; i++) + { + transition[i] -= xradius; + delete transition[i]; + } + delete[] transition; + + for (TQ_INT32 i = 0; i < xradius + 1 ; i++) + { + density[i] -= yradius; + delete density[i]; + } + density -= xradius; + delete[] density; + + dev->setDirty(); + dev->emitSelectionChanged(); +} + +#define RINT(x) floor ((x) + 0.5) + +void KisSelectionManager::computeBorder (TQ_INT32 *circ, TQ_INT32 xradius, TQ_INT32 yradius) +{ + Q_ASSERT(xradius != 0); + TQ_INT32 i; + TQ_INT32 diameter = xradius * 2 + 1; + double tmp; + + for (i = 0; i < diameter; i++) + { + if (i > xradius) + tmp = (i - xradius) - 0.5; + else if (i < xradius) + tmp = (xradius - i) - 0.5; + else + tmp = 0.0; + + circ[i] = (TQ_INT32) RINT (yradius / (double) xradius * sqrt (xradius * xradius - tmp * tmp)); + } +} + +void KisSelectionManager::rotatePointers (TQ_UINT8 **p, TQ_UINT32 n) +{ + TQ_UINT32 i; + TQ_UINT8 *tmp; + + tmp = p[0]; + + for (i = 0; i < n - 1; i++) p[i] = p[i + 1]; + + p[i] = tmp; +} + +void KisSelectionManager::computeTransition (TQ_UINT8* transition, TQ_UINT8** buf, TQ_INT32 width) +{ + TQ_INT32 x = 0; + + if (width == 1) + { + if (buf[1][x] > 127 && (buf[0][x] < 128 || buf[2][x] < 128)) + transition[x] = 255; + else + transition[x] = 0; + return; + } + if (buf[1][x] > 127) + { + if ( buf[0][x] < 128 || buf[0][x + 1] < 128 || + buf[1][x + 1] < 128 || + buf[2][x] < 128 || buf[2][x + 1] < 128 ) + transition[x] = 255; + else + transition[x] = 0; + } + else + transition[x] = 0; + for (TQ_INT32 x = 1; x < width - 1; x++) + { + if (buf[1][x] >= 128) + { + if (buf[0][x - 1] < 128 || buf[0][x] < 128 || buf[0][x + 1] < 128 || + buf[1][x - 1] < 128 || buf[1][x + 1] < 128 || + buf[2][x - 1] < 128 || buf[2][x] < 128 || buf[2][x + 1] < 128) + transition[x] = 255; + else + transition[x] = 0; + } + else + transition[x] = 0; + } + if (buf[1][x] >= 128) + { + if (buf[0][x - 1] < 128 || buf[0][x] < 128 || + buf[1][x - 1] < 128 || + buf[2][x - 1] < 128 || buf[2][x] < 128) + transition[x] = 255; + else + transition[x] = 0; + } + else + transition[x] = 0; +} + +#include "kis_selection_manager.moc" |