20#include <tqapplication.h>
21#include <tqclipboard.h>
28#include <kstdaction.h>
30#include <KoDocument.h>
31#include <KoMainWindow.h>
32#include <KoQueryTrader.h>
34#include "kis_cursor.h"
35#include "kis_part_layer.h"
36#include "kis_adjustment_layer.h"
37#include "kis_clipboard.h"
42#include "kis_selection.h"
43#include "kis_selection_manager.h"
44#include "kis_painter.h"
45#include "kis_iterators_pixel.h"
46#include "kis_iteratorpixeltrait.h"
48#include "kis_group_layer.h"
49#include "kis_paint_layer.h"
50#include "kis_paint_device.h"
51#include "kis_channelinfo.h"
52#include "kis_dlg_apply_profile.h"
53#include "kis_config.h"
54#include "kis_debug_areas.h"
55#include "kis_transaction.h"
56#include "kis_undo_adapter.h"
57#include "kis_selected_transaction.h"
58#include "kis_convolution_painter.h"
59#include "kis_integer_maths.h"
60#include "kis_fill_painter.h"
61#include "kis_canvas.h"
63KisSelectionManager::KisSelectionManager(KisView * parent, KisDoc * doc)
86 m_fillForegroundColor(0),
87 m_fillBackgroundColor(0),
90 m_pluginActions.setAutoDelete(
true);
91 m_clipboard = KisClipboard::instance();
94KisSelectionManager::~KisSelectionManager()
96 m_pluginActions.clear();
100void KisSelectionManager::setup(TDEActionCollection * collection)
104 m_cut = KStdAction::cut(
this,
109 m_copy = KStdAction::copy(
this,
114 m_paste = KStdAction::paste(
this,
119 m_pasteNew =
new TDEAction(i18n(
"Paste into &New Image"),
121 this, TQ_SLOT(pasteNew()),
126 m_selectAll = KStdAction::selectAll(
this,
127 TQ_SLOT(selectAll()),
131 m_deselect = KStdAction::deselect(
this,
137 m_clear = KStdAction::clear(
this,
142 m_reselect =
new TDEAction(i18n(
"&Reselect"),
144 this, TQ_SLOT(reselect()),
145 collection,
"reselect");
147 m_invert =
new TDEAction(i18n(
"&Invert"),
149 this, TQ_SLOT(invert()),
150 collection,
"invert");
153 m_toNewLayer =
new TDEAction(i18n(
"Copy Selection to New Layer"),
155 this, TQ_SLOT(copySelectionToNewLayer()),
156 collection,
"copy_selection_to_new_layer");
159 m_cutToNewLayer =
new TDEAction(i18n(
"Cut Selection to New Layer"),
161 this, TQ_SLOT(cutToNewLayer()),
162 collection,
"cut_selection_to_new_layer");
164 m_feather =
new TDEAction(i18n(
"Feather"),
166 this, TQ_SLOT(feather()),
167 collection,
"feather");
169 m_fillForegroundColor =
new TDEAction(i18n(
"Fill with Foreground Color"),
170 "Alt+backspace",
this,
171 TQ_SLOT(fillForegroundColor()),
173 "fill_selection_foreground_color");
174 m_fillBackgroundColor =
new TDEAction(i18n(
"Fill with Background Color"),
176 TQ_SLOT(fillBackgroundColor()),
178 "fill_selection_background_color");
179 m_fillPattern =
new TDEAction(i18n(
"Fill with Pattern"),
181 TQ_SLOT(fillPattern()),
183 "fill_selection_pattern");
185 m_toggleDisplaySelection =
new TDEToggleAction(i18n(
"Display Selection"),
"Ctrl+h",
this, TQ_SLOT(toggleDisplaySelection()), collection,
"toggle_display_selection");
186 m_toggleDisplaySelection->setCheckedState(KGuiItem(i18n(
"Hide Selection")));
187 m_toggleDisplaySelection->setChecked(
true);
190 new TDEAction(i18n(
"Border..."),
192 this, TQ_SLOT(border()),
193 collection,
"border");
195 new TDEAction(i18n(
"Expand..."),
197 this, TQ_SLOT(expand()),
198 collection,
"expand");
201 new TDEAction(i18n(
"Smooth..."),
203 this, TQ_SLOT(smooth()),
204 collection,
"smooth");
208 new TDEAction(i18n(
"Contract..."),
210 this, TQ_SLOT(contract()),
211 collection,
"contract");
213 new TDEAction(i18n(
"Similar"),
215 this, TQ_SLOT(similar()),
216 collection,
"similar");
220 =
new TDEAction(i18n(
"Transform..."),
222 this, TQ_SLOT(transform()),
223 collection,
"transform_selection");
239 TQClipboard *cb = TQApplication::clipboard();
240 connect(cb, TQ_SIGNAL(dataChanged()), TQ_SLOT(clipboardDataChanged()));
243void KisSelectionManager::clipboardDataChanged()
249void KisSelectionManager::addSelectionAction(TDEAction * action)
251 m_pluginActions.append(action);
255void KisSelectionManager::updateGUI()
258 Q_ASSERT(m_clipboard);
265 if (m_clipboard == 0) {
270 KisImageSP img = m_parent->currentImg();
272 KisPaintDeviceSP dev = 0;
275 if (img && img->activeDevice() && img->activeLayer()) {
276 l = img->activeLayer();
277 dev = img->activeDevice();
283 enable = l && dev&& dev->hasSelection() && !l->locked() && l->visible() && (partLayer==0);
286 m_reselect->setEnabled( dev->selectionDeselected() );
288 m_reselect->setEnabled(
false);
291 m_cut->setEnabled(enable);
292 m_cutToNewLayer->setEnabled(enable);
293 m_selectAll->setEnabled(img != 0);
294 m_deselect->setEnabled(enable);
295 m_clear->setEnabled(enable);
296 m_fillForegroundColor->setEnabled(enable);
297 m_fillBackgroundColor->setEnabled(enable);
298 m_fillPattern->setEnabled(enable);
299 m_invert->setEnabled(enable);
301 m_feather->setEnabled(enable);
303 m_border->setEnabled(enable);
304 m_expand->setEnabled(enable);
305 m_smooth->setEnabled(enable);
306 m_contract->setEnabled(enable);
307 m_similar->setEnabled(enable);
308 m_transform->setEnabled(enable);
314 for (a = m_pluginActions.first(); a; a = m_pluginActions.next()) {
315 a->setEnabled(img != 0);
321 if (img && l && dev) {
322 enable = dev->hasSelection() && l->visible();
325 m_copy->setEnabled(enable);
326 m_paste->setEnabled(img != 0 && m_clipboard->hasClip());
327 m_pasteNew->setEnabled(img != 0 && m_clipboard->hasClip());
328 m_toNewLayer->setEnabled(enable);
330 m_parent->updateStatusBarSelectionLabel();
334void KisSelectionManager::imgSelectionChanged(KisImageSP img)
336 if (img == m_parent->currentImg()) {
341void KisSelectionManager::cut()
343 KisImageSP img = m_parent->currentImg();
346 KisPaintDeviceSP dev = img->activeDevice();
349 if (!dev->hasSelection())
return;
353 KisSelectedTransaction *t = 0;
356 t =
new KisSelectedTransaction(i18n(
"Cut"), dev);
360 dev->clearSelection();
362 dev->emitSelectionChanged();
365 img->undoAdapter()->addCommand(t);
369void KisSelectionManager::copy()
371 KisImageSP img = m_parent->currentImg();
374 KisPaintDeviceSP dev = img->activeDevice();
377 if (!dev->hasSelection())
return;
379 KisSelectionSP selection = dev->selection();
381 TQRect r = selection->selectedExactRect();
383 KisPaintDeviceSP clip =
new KisPaintDevice(dev->colorSpace(),
"clip");
393 gc.
bitBlt(0, 0, COMPOSITE_COPY, dev, r.x(), r.y(), r.width(), r.height());
398 for (TQ_INT32 y = 0; y < r.height(); y++) {
400 KisHLineIteratorPixel selectionIt = selection->createHLineIterator(r.x(), r.y() + y, r.width(),
false);
402 while (!layerIt.isDone()) {
413 imgSelectionChanged(m_parent->currentImg());
417KisLayerSP KisSelectionManager::paste()
419 KisImageSP img = m_parent->currentImg();
422 KisPaintDeviceSP clip = m_clipboard->
clip();
425 TQApplication::setOverrideCursor(KisCursor::waitCursor());
429 TQRect r = clip->exactBounds();
431 gc.
begin(layer->paintDevice());
432 gc.
bitBlt(0, 0, COMPOSITE_COPY, clip, r.x(), r.y(), r.width(), r.height());
439 if(bottomright.x() > img->width())
440 center.setX(img->width()/2);
441 if(bottomright.y() > img->height())
442 center.setY(img->height()/2);
443 center -= TQPoint(r.width()/2, r.height()/2);
444 layer->setX(center.x());
445 layer->setY(center.y());
453 TQApplication::restoreOverrideCursor();
454 if(img->addLayer(layer, img->activeLayer()->parent(), img->activeLayer()))
464void KisSelectionManager::pasteNew()
466 KisPaintDeviceSP clip = m_clipboard->
clip();
469 TQRect r = clip->exactBounds();
470 if (r.width() < 1 && r.height() < 1) {
475 const TQCString mimetype = KoDocument::readNativeFormatMimeType();
476 KoDocumentEntry entry = KoDocumentEntry::queryByMimeType( mimetype );
477 KisDoc * doc = (KisDoc*) entry.createDoc();
479 Q_ASSERT(doc->undoAdapter() != 0);
480 doc->undoAdapter()->setUndo(
false);
482 KisImageSP img =
new KisImage(doc->undoAdapter(), r.width(), r.height(), clip->colorSpace(),
"Pasted");
486 p.bitBlt(0, 0, COMPOSITE_COPY, clip, OPACITY_OPAQUE, r.x(), r.y(), r.width(), r.height());
489 img->addLayer(layer, img->rootLayer(), 0);
490 doc->setCurrentImage(img);
492 doc->undoAdapter()->setUndo(
true);
494 KoMainWindow *win =
new KoMainWindow( doc->instance() );
496 win->setRootDocument( doc );
499void KisSelectionManager::selectAll()
501 KisImageSP img = m_parent->currentImg();
504 KisPaintDeviceSP dev = img->activeDevice();
507 KisSelectedTransaction * t = 0;
508 if (img->undo()) t =
new KisSelectedTransaction(i18n(
"Select All"), dev);
515 adj->selection()->invert();
517 dev->selection()->clear();
518 dev->selection()->invert();
521 dev->emitSelectionChanged();
524 img->undoAdapter()->addCommand(t);
527void KisSelectionManager::deselect()
529 KisImageSP img = m_parent->currentImg();
532 KisPaintDeviceSP dev = img->activeDevice();
534 KisSelectedTransaction * t = 0;
535 if (img->undo()) t =
new KisSelectedTransaction(i18n(
"Deselect"), dev);
546 dev->emitSelectionChanged();
549 img->undoAdapter()->addCommand(t);
553void KisSelectionManager::clear()
555 KisImageSP img = m_parent->currentImg();
558 KisPaintDeviceSP dev = img->activeDevice();
561 if (!dev->hasSelection())
return;
563 KisTransaction * t = 0;
566 t =
new KisTransaction(i18n(
"Clear"), dev);
569 dev->clearSelection();
571 dev->emitSelectionChanged();
573 if (img->undo()) img->undoAdapter()->addCommand(t);
576void KisSelectionManager::fill(
const KisColor& color,
bool fillWithPattern,
const TQString& transactionText)
578 KisImageSP img = m_parent->currentImg();
581 KisPaintDeviceSP dev = img->activeDevice();
584 if (!dev->hasSelection())
return;
586 KisSelectionSP selection = dev->selection();
591 if (fillWithPattern) {
592 painter.fillRect(0, 0, img->width(), img->height(),
593 m_parent->currentPattern());
595 painter.fillRect(0, 0, img->width(), img->height(), color);
602 if (img->undo()) painter2.beginTransaction(transactionText);
603 painter2.bltSelection(0, 0, COMPOSITE_OVER, filled, OPACITY_OPAQUE,
604 0, 0, img->width(), img->height());
607 dev->emitSelectionChanged();
610 img->undoAdapter()->addCommand(painter2.endTransaction());
614void KisSelectionManager::fillForegroundColor()
616 fill(m_parent->fgColor(),
false, i18n(
"Fill with Foreground Color"));
619void KisSelectionManager::fillBackgroundColor()
621 fill(m_parent->bgColor(),
false, i18n(
"Fill with Background Color"));
624void KisSelectionManager::fillPattern()
626 fill(
KisColor(),
true, i18n(
"Fill with Pattern"));
629void KisSelectionManager::reselect()
631 KisImageSP img = m_parent->currentImg();
634 KisPaintDeviceSP dev = img ->activeDevice();
637 KisSelectedTransaction * t = 0;
638 if (img->undo()) t =
new KisSelectedTransaction(i18n(
"Reselect"), dev);
643 dev->emitSelectionChanged();
646 img->undoAdapter()->addCommand(t);
650void KisSelectionManager::invert()
652 KisImageSP img = m_parent->currentImg();
655 KisPaintDeviceSP dev = img->activeDevice();
658 if (dev->hasSelection()) {
659 KisSelectionSP s = dev->selection();
661 KisSelectedTransaction * t = 0;
664 t =
new KisSelectedTransaction(i18n(
"Invert"), dev);
670 dev->emitSelectionChanged();
673 img->undoAdapter()->addCommand(t);
678void KisSelectionManager::copySelectionToNewLayer()
680 KisImageSP img = m_parent->currentImg();
683 KisPaintDeviceSP dev = img->activeDevice();
690void KisSelectionManager::cutToNewLayer()
692 KisImageSP img = m_parent->currentImg();
695 KisPaintDeviceSP dev = img->activeDevice();
703void KisSelectionManager::feather()
705 KisImageSP img = m_parent->currentImg();
707 KisPaintDeviceSP dev = img->activeDevice();
710 if (!dev->hasSelection()) {
716 KisSelectionSP selection = dev->selection();
717 KisSelectedTransaction * t = 0;
718 if (img->undo()) t =
new KisSelectedTransaction(i18n(
"Feather..."), dev);
725 KisConvolutionPainter painter(selection.data());
727 KisKernelSP k =
new KisKernel();
732 k->data =
new TQ_INT32[9];
743 TQRect rect = selection->selectedRect();
745 rect = TQRect(rect.x() - 3, rect.y() - 3, rect.width() + 6, rect.height() + 6);
746 rect &= TQRect(0, 0, img->width(), img->height());
748 painter.applyMatrix(k, rect.x(), rect.y(), rect.width(), rect.height(), BORDER_AVOID, KisChannelInfo::FLAG_ALPHA);
752 dev->emitSelectionChanged();
755 img->undoAdapter()->addCommand(t);
759void KisSelectionManager::toggleDisplaySelection()
766 return m_toggleDisplaySelection->isChecked();
769void KisSelectionManager::border() {}
770void KisSelectionManager::expand() {}
771void KisSelectionManager::contract() {}
772void KisSelectionManager::similar() {}
773void KisSelectionManager::transform() {}
774void KisSelectionManager::load() {}
775void KisSelectionManager::save() {}
777#define MAX(a, b) ((a) > (b) ? (a) : (b))
778#define MIN(a, b) ((a) < (b) ? (a) : (b))
780void KisSelectionManager::grow (TQ_INT32 xradius, TQ_INT32 yradius)
782 KisImageSP img = m_parent->currentImg();
785 KisPaintDeviceSP dev = img->activeDevice();
788 if (!dev->hasSelection())
return;
789 KisSelectionSP selection = dev->selection();
792 TQRect layerSize = dev->exactBounds();
801 if (xradius <= 0 || yradius <= 0)
804 KisSelectedTransaction *t = 0;
807 t =
new KisSelectedTransaction(i18n(
"Grow"), dev);
811 max =
new TQ_UINT8* [layerSize.width() + 2 * xradius];
812 buf =
new TQ_UINT8* [yradius + 1];
813 for (TQ_INT32 i = 0; i < yradius + 1; i++)
815 buf[i] =
new TQ_UINT8[layerSize.width()];
817 TQ_UINT8* buffer =
new TQ_UINT8[ ( layerSize.width() + 2 * xradius ) * ( yradius + 1 ) ];
818 for (TQ_INT32 i = 0; i < layerSize.width() + 2 * xradius; i++)
822 else if (i < layerSize.width() + xradius)
823 max[i] = &buffer[(yradius + 1) * (i - xradius)];
825 max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius - 1)];
827 for (TQ_INT32 j = 0; j < xradius + 1; j++)
834 TQ_UINT8* out =
new TQ_UINT8[ layerSize.width() ];
836 TQ_INT32* circ =
new TQ_INT32[ 2 * xradius + 1 ];
837 computeBorder (circ, xradius, yradius);
843 memset (buf[0], 0, layerSize.width());
844 for (TQ_INT32 i = 0; i < yradius && i < layerSize.height(); i++)
846 selection->readBytes(buf[i + 1], layerSize.x(), layerSize.y() + i, layerSize.width(), 1);
849 for (TQ_INT32 x = 0; x < layerSize.width() ; x++)
852 max[x][1] = buf[1][x];
853 for (TQ_INT32 j = 2; j < yradius + 1; j++)
855 max[x][j] = MAX(buf[j][x], max[x][j-1]);
859 for (TQ_INT32 y = 0; y < layerSize.height(); y++)
861 rotatePointers (buf, yradius + 1);
862 if (y < layerSize.height() - (yradius))
863 selection->readBytes(buf[yradius], layerSize.x(), layerSize.y() + y + yradius, layerSize.width(), 1);
865 memset (buf[yradius], 0, layerSize.width());
866 for (TQ_INT32 x = 0; x < layerSize.width(); x++)
868 for (TQ_INT32 i = yradius; i > 0; i--)
870 max[x][i] = MAX (MAX (max[x][i - 1], buf[i - 1][x]), buf[i][x]);
872 max[x][0] = buf[0][x];
874 TQ_INT32 last_max = max[0][circ[-1]];
875 TQ_INT32 last_index = 1;
876 for (TQ_INT32 x = 0; x < layerSize.width(); x++)
886 for (TQ_INT32 i = xradius; i >= 0; i--)
887 if (last_max < max[x + i][circ[i]])
889 last_max = max[x + i][circ[i]];
897 last_index = xradius;
898 last_max = max[x + xradius][circ[xradius]];
899 for (TQ_INT32 i = xradius - 1; i >= -xradius; i--)
900 if (last_max < max[x + i][circ[i]])
902 last_max = max[x + i][circ[i]];
908 selection->writeBytes(out, layerSize.x(), layerSize.y() + y, layerSize.width(), 1);
917 for (TQ_INT32 i = 0; i < yradius + 1; i++)
923 dev->emitSelectionChanged();
926 img->undoAdapter()->addCommand(t);
930void KisSelectionManager::shrink (TQ_INT32 xradius, TQ_INT32 yradius,
bool edge_lock)
933 KisImageSP img = m_parent->currentImg();
936 KisPaintDeviceSP dev = img->activeDevice();
939 if (!dev->hasSelection())
return;
940 KisSelectionSP selection = dev->selection();
943 TQRect layerSize = dev->exactBounds();
954 TQ_INT32 last_max, last_index;
956 if (xradius <= 0 || yradius <= 0)
959 max =
new TQ_UINT8* [layerSize.width() + 2 * xradius];
960 buf =
new TQ_UINT8* [yradius + 1];
961 for (TQ_INT32 i = 0; i < yradius + 1; i++)
963 buf[i] =
new TQ_UINT8[layerSize.width()];
966 TQ_INT32 buffer_size = (layerSize.width() + 2 * xradius + 1) * (yradius + 1);
967 TQ_UINT8* buffer =
new TQ_UINT8[buffer_size];
970 memset(buffer, 255, buffer_size);
972 memset(buffer, 0, buffer_size);
974 for (TQ_INT32 i = 0; i < layerSize.width() + 2 * xradius; i++)
980 max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius)];
981 else if (i < layerSize.width() + xradius)
982 max[i] = &buffer[(yradius + 1) * (i - xradius)];
985 max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius - 1)];
987 max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius)];
990 for (TQ_INT32 j = 0 ; j < xradius + 1; j++) max[0][j] = 0;
995 TQ_UINT8* out =
new TQ_UINT8[layerSize.width()];
997 TQ_INT32* circ =
new TQ_INT32[2 * xradius + 1];
999 computeBorder (circ, xradius, yradius);
1004 for (TQ_INT32 i = 0; i < yradius && i < layerSize.height(); i++)
1005 selection->readBytes(buf[i + 1], layerSize.x(), layerSize.y() + i, layerSize.width(), 1);
1008 memcpy (buf[0], buf[1], layerSize.width());
1010 memset (buf[0], 0, layerSize.width());
1013 for (TQ_INT32 x = 0; x < layerSize.width(); x++)
1015 max[x][0] = buf[0][x];
1016 for (TQ_INT32 j = 1; j < yradius + 1; j++)
1017 max[x][j] = MIN(buf[j][x], max[x][j-1]);
1020 for (TQ_INT32 y = 0; y < layerSize.height(); y++)
1022 rotatePointers (buf, yradius + 1);
1023 if (y < layerSize.height() - yradius)
1024 selection->readBytes(buf[yradius], layerSize.x(), layerSize.y() + y + yradius, layerSize.width(), 1);
1026 memcpy (buf[yradius], buf[yradius - 1], layerSize.width());
1028 memset (buf[yradius], 0, layerSize.width());
1030 for (TQ_INT32 x = 0 ; x < layerSize.width(); x++)
1032 for (TQ_INT32 i = yradius; i > 0; i--)
1034 max[x][i] = MIN (MIN (max[x][i - 1], buf[i - 1][x]), buf[i][x]);
1036 max[x][0] = buf[0][x];
1038 last_max = max[0][circ[-1]];
1041 for (TQ_INT32 x = 0 ; x < layerSize.width(); x++)
1044 if (last_index >= 0)
1051 for (TQ_INT32 i = xradius; i >= 0; i--)
1052 if (last_max > max[x + i][circ[i]])
1054 last_max = max[x + i][circ[i]];
1062 last_index = xradius;
1063 last_max = max[x + xradius][circ[xradius]];
1064 for (TQ_INT32 i = xradius - 1; i >= -xradius; i--)
1065 if (last_max > max[x + i][circ[i]])
1067 last_max = max[x + i][circ[i]];
1073 selection->writeBytes(out, layerSize.x(), layerSize.y() + y, layerSize.width(), 1);
1084 for (TQ_INT32 i = 0; i < yradius + 1; i++)
1089 dev->setDirty(layerSize);
1090 dev->emitSelectionChanged();
1095void KisSelectionManager::smooth()
1097 KisImageSP img = m_parent->currentImg();
1100 KisPaintDeviceSP dev = img->activeDevice();
1103 if (!dev->hasSelection())
return;
1104 KisSelectionSP selection = dev->selection();
1107 TQRect layerSize = dev->exactBounds();
1111 TQ_INT32 width = layerSize.width();
1113 for (TQ_INT32 i = 0; i < 3; i++) buf[i] =
new TQ_UINT8[width + 2];
1115 TQ_UINT8* out =
new TQ_UINT8[width];
1118 selection->readBytes(buf[0] + 1, layerSize.x(), layerSize.y(), width, 1);
1120 buf[0][0] = buf[0][1];
1121 buf[0][width + 1] = buf[0][width];
1123 memcpy (buf[1], buf[0], width + 2);
1125 for (TQ_INT32 y = 0; y < layerSize.height(); y++)
1127 if (y + 1 < layerSize.height())
1129 selection->readBytes(buf[2] + 1, layerSize.x(), layerSize.y() + y + 1, width, 1);
1131 buf[2][0] = buf[2][1];
1132 buf[2][width + 1] = buf[2][width];
1136 memcpy (buf[2], buf[1], width + 2);
1139 for (TQ_INT32 x = 0 ; x < width; x++)
1141 TQ_INT32 value = (buf[0][x] + buf[0][x+1] + buf[0][x+2] +
1142 buf[1][x] + buf[2][x+1] + buf[1][x+2] +
1143 buf[2][x] + buf[1][x+1] + buf[2][x+2]);
1148 selection->writeBytes(out, layerSize.x(), layerSize.y() + y, width, 1);
1150 rotatePointers (buf, 3);
1153 for (TQ_INT32 i = 0; i < 3; i++)
1159 dev->emitSelectionChanged();
1164void KisSelectionManager::erode()
1166 KisImageSP img = m_parent->currentImg();
1169 KisPaintDeviceSP dev = img->activeDevice();
1172 if (!dev->hasSelection())
return;
1173 KisSelectionSP selection = dev->selection();
1176 TQRect layerSize = dev->exactBounds();
1181 TQ_INT32 width = layerSize.width();
1183 for (TQ_INT32 i = 0; i < 3; i++)
1184 buf[i] =
new TQ_UINT8[width + 2];
1186 TQ_UINT8* out =
new TQ_UINT8[width];
1189 selection->readBytes(buf[0] + 1, layerSize.x(), layerSize.y(), width, 1);
1191 buf[0][0] = buf[0][1];
1192 buf[0][width + 1] = buf[0][width];
1194 memcpy (buf[1], buf[0], width + 2);
1196 for (TQ_INT32 y = 0; y < layerSize.height(); y++)
1198 if (y + 1 < layerSize.height())
1200 selection->readBytes(buf[2] + 1, layerSize.x(), layerSize.y() + y + 1, width, 1);
1202 buf[2][0] = buf[2][1];
1203 buf[2][width + 1] = buf[2][width];
1207 memcpy (buf[2], buf[1], width + 2);
1210 for (TQ_INT32 x = 0 ; x < width; x++)
1214 if (buf[0][x+1] < min) min = buf[0][x+1];
1215 if (buf[1][x] < min) min = buf[1][x];
1216 if (buf[1][x+1] < min) min = buf[1][x+1];
1217 if (buf[1][x+2] < min) min = buf[1][x+2];
1218 if (buf[2][x+1] < min) min = buf[2][x+1];
1223 selection->writeBytes(out, layerSize.x(), layerSize.y() + y, width, 1);
1225 rotatePointers (buf, 3);
1228 for (TQ_INT32 i = 0; i < 3; i++)
1234 dev->emitSelectionChanged();
1239void KisSelectionManager::dilate()
1241 KisImageSP img = m_parent->currentImg();
1244 KisPaintDeviceSP dev = img->activeDevice();
1247 if (!dev->hasSelection())
return;
1248 KisSelectionSP selection = dev->selection();
1251 TQRect layerSize = dev->exactBounds();
1255 TQ_INT32 width = layerSize.width();
1257 for (TQ_INT32 i = 0; i < 3; i++)
1258 buf[i] =
new TQ_UINT8[width + 2];
1260 TQ_UINT8* out =
new TQ_UINT8[width];
1263 selection->readBytes(buf[0] + 1, layerSize.x(), layerSize.y(), width, 1);
1265 buf[0][0] = buf[0][1];
1266 buf[0][width + 1] = buf[0][width];
1268 memcpy (buf[1], buf[0], width + 2);
1270 for (TQ_INT32 y = 0; y < layerSize.height(); y++)
1272 if (y + 1 < layerSize.height())
1274 selection->readBytes(buf[2] + 1, layerSize.x(), layerSize.y() + y + 1, width, 1);
1276 buf[2][0] = buf[2][1];
1277 buf[2][width + 1] = buf[2][width];
1281 memcpy (buf[2], buf[1], width + 2);
1284 for (TQ_INT32 x = 0 ; x < width; x++)
1288 if (buf[0][x+1] > max) max = buf[0][x+1];
1289 if (buf[1][x] > max) max = buf[1][x];
1290 if (buf[1][x+1] > max) max = buf[1][x+1];
1291 if (buf[1][x+2] > max) max = buf[1][x+2];
1292 if (buf[2][x+1] > max) max = buf[2][x+1];
1297 selection->writeBytes(out, layerSize.x(), layerSize.y() + y, width, 1);
1299 rotatePointers (buf, 3);
1302 for (TQ_INT32 i = 0; i < 3; i++)
1308 dev->emitSelectionChanged();
1311void KisSelectionManager::border(TQ_INT32 xradius, TQ_INT32 yradius)
1313 KisImageSP img = m_parent->currentImg();
1316 KisPaintDeviceSP dev = img->activeDevice();
1319 if (!dev->hasSelection())
return;
1320 KisSelectionSP selection = dev->selection();
1323 TQRect layerSize = dev->exactBounds();
1331 TQ_UINT8 **transition;
1333 if (xradius == 1 && yradius == 1)
1335 TQ_UINT8* source[3];
1337 for (TQ_INT32 i = 0; i < 3; i++)
1338 source[i] =
new TQ_UINT8[layerSize.width()];
1340 TQ_UINT8* transition =
new TQ_UINT8[layerSize.width()];
1342 selection->readBytes(source[0], layerSize.x(), layerSize.y(), layerSize.width(), 1);
1343 memcpy (source[1], source[0], layerSize.width());
1344 if (layerSize.height() > 1)
1345 selection->readBytes(source[2], layerSize.x(), layerSize.y() + 1, layerSize.width(), 1);
1347 memcpy (source[2], source[1], layerSize.width());
1349 computeTransition (transition, source, layerSize.width());
1350 selection->writeBytes(transition, layerSize.x(), layerSize.y(), layerSize.width(), 1);
1352 for (TQ_INT32 y = 1; y < layerSize.height(); y++)
1354 rotatePointers (source, 3);
1355 if (y + 1 < layerSize.height())
1356 selection->readBytes(source[2], layerSize.x(), layerSize.y() + y + 1, layerSize.width(), 1);
1358 memcpy(source[2], source[1], layerSize.width());
1359 computeTransition (transition, source, layerSize.width());
1360 selection->writeBytes(transition, layerSize.x(), layerSize.y() + y, layerSize.width(), 1);
1363 for (TQ_INT32 i = 0; i < 3; i++)
1365 delete[] transition;
1369 TQ_INT32* max =
new TQ_INT32[layerSize.width() + 2 * xradius];
1370 for (TQ_INT32 i = 0; i < (layerSize.width() + 2 * xradius); i++)
1371 max[i] = yradius + 2;
1374 for (TQ_INT32 i = 0; i < 3; i++)
1375 buf[i] =
new TQ_UINT8[layerSize.width()];
1377 transition =
new TQ_UINT8*[yradius + 1];
1378 for (TQ_INT32 i = 0; i < yradius + 1; i++)
1380 transition[i] =
new TQ_UINT8[layerSize.width() + 2 * xradius];
1381 memset(transition[i], 0, layerSize.width() + 2 * xradius);
1382 transition[i] += xradius;
1384 TQ_UINT8* out =
new TQ_UINT8[layerSize.width()];
1385 density =
new TQ_UINT8*[2 * xradius + 1];
1388 for (TQ_INT32 x = 0; x < (xradius + 1); x++)
1390 density[ x] =
new TQ_UINT8[2 * yradius + 1];
1391 density[ x] += yradius;
1392 density[-x] = density[x];
1394 for (TQ_INT32 x = 0; x < (xradius + 1); x++)
1396 double tmpx, tmpy, dist;
1406 for (TQ_INT32 y = 0; y < (yradius + 1); y++)
1414 dist = ((tmpy * tmpy) / (yradius * yradius) +
1415 (tmpx * tmpx) / (xradius * xradius));
1417 a = 255 * (TQ_UINT8)(1.0 - sqrt (dist));
1420 density[ x][ y] = a;
1421 density[ x][-y] = a;
1422 density[-x][ y] = a;
1423 density[-x][-y] = a;
1426 selection->readBytes(buf[0], layerSize.x(), layerSize.y(), layerSize.width(), 1);
1427 memcpy (buf[1], buf[0], layerSize.width());
1428 if (layerSize.height() > 1)
1429 selection->readBytes(buf[2], layerSize.x(), layerSize.y() + 1, layerSize.width(), 1);
1431 memcpy (buf[2], buf[1], layerSize.width());
1432 computeTransition (transition[1], buf, layerSize.width());
1434 for (TQ_INT32 y = 1; y < yradius && y + 1 < layerSize.height(); y++)
1436 rotatePointers (buf, 3);
1437 selection->readBytes(buf[2], layerSize.x(), layerSize.y() + y + 1, layerSize.width(), 1);
1438 computeTransition (transition[y + 1], buf, layerSize.width());
1440 for (TQ_INT32 x = 0; x < layerSize.width(); x++)
1442 max[x] = -(yradius + 7);
1443 for (TQ_INT32 j = 1; j < yradius + 1; j++)
1444 if (transition[j][x])
1450 for (TQ_INT32 y = 0; y < layerSize.height(); y++)
1452 rotatePointers (buf, 3);
1453 rotatePointers (transition, yradius + 1);
1454 if (y < layerSize.height() - (yradius + 1))
1456 selection->readBytes(buf[2], layerSize.x(), layerSize.y() + y + yradius + 1, layerSize.width(), 1);
1457 computeTransition (transition[yradius], buf, layerSize.width());
1460 memcpy (transition[yradius], transition[yradius - 1], layerSize.width());
1462 for (TQ_INT32 x = 0; x < layerSize.width(); x++)
1466 if (max[x] <= -yradius)
1468 if (transition[yradius][x])
1474 if (transition[-max[x]][x])
1476 else if (transition[-max[x] + 1][x])
1477 max[x] = -max[x] + 1;
1483 if (max[x] < -yradius - 1)
1484 max[x] = -yradius - 1;
1486 TQ_UINT8 last_max = max[0][density[-1]];
1487 TQ_INT32 last_index = 1;
1488 for (TQ_INT32 x = 0 ; x < layerSize.width(); x++)
1491 if (last_index >= 0)
1494 for (TQ_INT32 i = xradius; i >= 0; i--)
1495 if (max[x + i] <= yradius && max[x + i] >= -yradius && density[i][max[x+i]] > last_max)
1497 last_max = density[i][max[x + i]];
1505 for (TQ_INT32 i = xradius; i >= -xradius; i--)
1506 if (max[x + i] <= yradius && max[x + i] >= -yradius && density[i][max[x + i]] > last_max)
1508 last_max = density[i][max[x + i]];
1516 for (i = x + 1; i < layerSize.width(); i++)
1518 if (max[i] >= -yradius)
1521 if (i - x > xradius)
1523 for (; x < i - xradius; x++)
1527 last_index = xradius;
1530 selection->writeBytes(out, layerSize.x(), layerSize.y() + y, layerSize.width(), 1);
1534 for (TQ_INT32 i = 0; i < 3; i++)
1540 for (TQ_INT32 i = 0; i < yradius + 1; i++)
1542 transition[i] -= xradius;
1543 delete transition[i];
1545 delete[] transition;
1547 for (TQ_INT32 i = 0; i < xradius + 1 ; i++)
1549 density[i] -= yradius;
1556 dev->emitSelectionChanged();
1559#define RINT(x) floor ((x) + 0.5)
1561void KisSelectionManager::computeBorder (TQ_INT32 *circ, TQ_INT32 xradius, TQ_INT32 yradius)
1563 Q_ASSERT(xradius != 0);
1565 TQ_INT32 diameter = xradius * 2 + 1;
1568 for (i = 0; i < diameter; i++)
1571 tmp = (i - xradius) - 0.5;
1572 else if (i < xradius)
1573 tmp = (xradius - i) - 0.5;
1577 circ[i] = (TQ_INT32) RINT (yradius / (
double) xradius * sqrt (xradius * xradius - tmp * tmp));
1581void KisSelectionManager::rotatePointers (TQ_UINT8 **p, TQ_UINT32 n)
1588 for (i = 0; i < n - 1; i++) p[i] = p[i + 1];
1593void KisSelectionManager::computeTransition (TQ_UINT8* transition, TQ_UINT8** buf, TQ_INT32 width)
1599 if (buf[1][x] > 127 && (buf[0][x] < 128 || buf[2][x] < 128))
1600 transition[x] = 255;
1605 if (buf[1][x] > 127)
1607 if ( buf[0][x] < 128 || buf[0][x + 1] < 128 ||
1608 buf[1][x + 1] < 128 ||
1609 buf[2][x] < 128 || buf[2][x + 1] < 128 )
1610 transition[x] = 255;
1616 for (TQ_INT32 x = 1; x < width - 1; x++)
1618 if (buf[1][x] >= 128)
1620 if (buf[0][x - 1] < 128 || buf[0][x] < 128 || buf[0][x + 1] < 128 ||
1621 buf[1][x - 1] < 128 || buf[1][x + 1] < 128 ||
1622 buf[2][x - 1] < 128 || buf[2][x] < 128 || buf[2][x + 1] < 128)
1623 transition[x] = 255;
1630 if (buf[1][x] >= 128)
1632 if (buf[0][x - 1] < 128 || buf[0][x] < 128 ||
1633 buf[1][x - 1] < 128 ||
1634 buf[2][x - 1] < 128 || buf[2][x] < 128)
1635 transition[x] = 255;
1643#include "kis_selection_manager.moc"
Class that contains a KisFilter and optionally a KisSelection.
void clearSelection()
Clears the selection (doesn't call any of the update or dirty methods)
Interface for classes that implement a canvas; i.e., a widget where KisImages are painted onto.
virtual TQPoint viewToWindow(const TQPoint &pt)=0
Conversion functions from view coordinates to image coordinates.
virtual KisCanvas * kiscanvas() const =0
void setClip(KisPaintDeviceSP layer)
Sets the clipboard to the contents of the specified paint device; also set the system clipboard to a ...
KisPaintDeviceSP clip()
Get the contents of the clipboard in the form of a paint device.
A colorspace is the definition of a certain color model in Chalk.
virtual void applyAlphaU8Mask(TQ_UINT8 *pixels, TQ_UINT8 *alpha, TQ_INT32 nPixels)=0
Applies the specified 8-bit alpha mask to the pixels.
A KisColor describes a color in a certain colorspace.
This painter can be used to fill paint devices in different ways.
The pixel iterators are high level iterarators.
A paint device contains the actual pixel data and offers methods to read and write pixels.
This layer is of a type that can be painted on.
KisPainter contains the graphics primitives necessary to draw on a KisPaintDevice.
KCommand * end()
Finish painting on the current device.
void bitBlt(TQ_INT32 dx, TQ_INT32 dy, const KisCompositeOp &op, KisPaintDeviceSP src, TQ_INT32 sx, TQ_INT32 sy, TQ_INT32 sw, TQ_INT32 sh)
Blast the specified region from src onto the current paint device.
void begin(KisPaintDeviceSP device)
Start painting on the specified device.
An interface for the Part Layer so that we can use it in core/, but can implement it in ui/.
bool displaySelection()
This function return if the selection should be displayed.