Commit 5a67081f authored by Sven Langkamp's avatar Sven Langkamp

ported selectsimelar and added a experimental marching ants

svn path=/trunk/koffice/; revision=658584
parent e4a15ad6
......@@ -23,6 +23,8 @@
#include <kdebug.h>
#include <klocale.h>
#include <QColor>
#include <QPoint>
#include <QPolygon>
#include "kis_layer.h"
#include "kis_debug_areas.h"
......@@ -564,3 +566,168 @@ void KisSelection::setDirty()
super::setDirty();
}
QVector<QPolygon> KisSelection::outline()
{
QTime t;
t.start();
QRect selectionExtent = exactBounds();
qint32 xOffset = selectionExtent.x();
qint32 yOffset = selectionExtent.y();
qint32 width = selectionExtent.width();
qint32 height = selectionExtent.height();
quint8* buffer = new quint8[width*height];
quint8* marks = new quint8[width*height];
for (int i = 0; i < width*height; i++) {
marks[i] = 0;
}
kDebug() << "Loading data: " << t.elapsed() << endl;
QVector<QPolygon> paths;
readBytes(buffer, xOffset, yOffset, width, height);
int nodes = 0;
for (qint32 y = 0; y < height; y++) {
for (qint32 x = 0; x < width; x++) {
if(buffer[y*width+x]== MIN_SELECTED)
continue;
EdgeType startEdge = TopEdge;
EdgeType edge = startEdge;
while( edge != NoEdge && (marks[y*width+x] & (1 << edge) || !isOutlineEdge(edge, x, y, buffer, width, height)))
{
edge = nextEdge(edge);
if (edge == startEdge)
edge = NoEdge;
}
if (edge != NoEdge)
{
QPolygon path;
path << QPoint(x+xOffset, y+yOffset);
bool clockwise = edge == BottomEdge;
qint32 row = y, col = x;
EdgeType currentEdge = edge;
EdgeType lastEdge = currentEdge;
do {
//While following a strait line no points nead to be added
if(lastEdge != currentEdge){
appendCoordinate(&path, col+xOffset, row+yOffset, currentEdge);
nodes++;
lastEdge = currentEdge;
}
marks[row*width+col] |= 1 << currentEdge;
nextOutlineEdge( &currentEdge, &row, &col, buffer, width, height);
}
while (row != y || col != x || currentEdge != edge);
paths.push_back(path);
}
}
}
kDebug() << "Nodes: " << nodes << endl;
kDebug() << "Generating outline: " << t.elapsed() << endl;
delete[] buffer;
delete[] marks;
return paths;
}
bool KisSelection::isOutlineEdge(EdgeType edge, qint32 x, qint32 y, quint8* buffer, qint32 bufWidth, qint32 bufHeight)
{
if(buffer[y*bufWidth+x] == MIN_SELECTED)
return false;
switch(edge){
case LeftEdge:
return x == 0 || buffer[y*bufWidth+(x - 1)] == MIN_SELECTED;
case TopEdge:
return y == 0 || buffer[(y - 1)*bufWidth+x] == MIN_SELECTED;
case RightEdge:
return x == bufWidth -1 || buffer[y*bufWidth+(x + 1)] == MIN_SELECTED;
case BottomEdge:
return y == bufHeight -1 || buffer[(y + 1)*bufWidth+x] == MIN_SELECTED;
}
return false;
}
#define TRY_PIXEL(deltaRow, deltaCol, test_edge) \
{ \
int test_row = *row + deltaRow; \
int test_col = *col + deltaCol; \
if ( (0 <= (test_row) && (test_row) < height && 0 <= (test_col) && (test_col) < width) && \
isOutlineEdge (test_edge, test_col, test_row, buffer, width, height)) \
{ \
*row = test_row; \
*col = test_col; \
*edge = test_edge; \
break; \
} \
}
void KisSelection::nextOutlineEdge(EdgeType *edge, qint32 *row, qint32 *col, quint8* buffer, qint32 width, qint32 height)
{
int original_row = *row;
int original_col = *col;
switch (*edge){
case RightEdge:
TRY_PIXEL( -1, 0, RightEdge);
TRY_PIXEL( -1, 1, BottomEdge);
break;
case TopEdge:
TRY_PIXEL( 0, -1, TopEdge);
TRY_PIXEL( -1, -1, RightEdge);
break;
case LeftEdge:
TRY_PIXEL( 1, 0, LeftEdge);
TRY_PIXEL( 1, -1, TopEdge);
break;
case BottomEdge:
TRY_PIXEL( 0, 1, BottomEdge);
TRY_PIXEL( 1, 1, LeftEdge);
break;
default:
break;
}
if (*row == original_row && *col == original_col)
*edge = nextEdge (*edge);
}
void
KisSelection::appendCoordinate(QPolygon * path, int x, int y, EdgeType edge)
{
switch (edge)
{
case TopEdge:
x++;
break;
case RightEdge:
x++;
y++;
break;
case BottomEdge:
y++;
break;
case LeftEdge:
break;
}
*path << QPoint(x, y);
}
......@@ -19,6 +19,7 @@
#define KIS_SELECTION_H_
#include <QRect>
#include <QPainterPath>
#include "kis_types.h"
#include "kis_paint_device.h"
......@@ -112,6 +113,7 @@ public:
virtual void setDirty(const QRect & rc);
virtual void setDirty();
QVector<QPolygon> outline();
private:
void paintUniformSelectionRegion(QImage img, const QRect& imageRect, const QRegion& uniformRegion);
......@@ -141,6 +143,19 @@ private:
return KisPaintDevice::region();
}
enum EdgeType
{
TopEdge = 1, LeftEdge = 2, BottomEdge = 3, RightEdge = 0, NoEdge = 4
};
bool isOutlineEdge(EdgeType edge, qint32 row, qint32 col, quint8* buffer, qint32 width, qint32 height);
EdgeType nextEdge(EdgeType edge) { return edge == NoEdge ? edge : static_cast<EdgeType>((edge + 1) % 4); }
void nextOutlineEdge(EdgeType *edge, qint32 *row, qint32 *col, quint8* buffer, qint32 bufWidth, qint32 bufHeight);
void appendCoordinate(QPolygon * path, int x, int y, EdgeType edge);
private:
KisPaintDeviceWSP m_parentPaintDevice;
bool m_dirty;
......
......@@ -5,7 +5,7 @@ add_subdirectory( tool_crop )
#add_subdirectory( tool_filter )
add_subdirectory( tool_polygon )
add_subdirectory( tool_polyline )
#add_subdirectory( tool_selectsimilar )
add_subdirectory( tool_selectsimilar )
add_subdirectory( tool_star )
#add_subdirectory( tool_transform )
#add_subdirectory( tool_perspectivegrid )
......
......@@ -27,25 +27,21 @@
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <kactioncollection.h>
#include <kaction.h>
#include <klocale.h>
#include <knuminput.h>
#include <kis_cursor.h>
#include <kis_selection_manager.h>
#include <kis_canvas_subject.h>
#include <kis_image.h>
#include <kis_layer.h>
#include <kis_paint_device.h>
#include <KoPointerEvent.h>
#include <kis_canvas_subject.h>
#include <kis_selection_options.h>
#include <kis_selection.h>
#include <kis_paint_device.h>
#include <kis_iterators_pixel.h>
#include <kis_selected_transaction.h>
#include <kis_undo_adapter.h>
#include <kis_canvas2.h>
#include "kis_tool_selectsimilar.h"
......@@ -89,14 +85,11 @@ void selectByColor(KisPaintDeviceSP dev, KisSelectionSP selection, const quint8
KisToolSelectSimilar::KisToolSelectSimilar()
: super(i18n("Select Similar Colors"))
KisToolSelectSimilar::KisToolSelectSimilar(KoCanvasBase * canvas)
: KisTool(canvas, KisCursor::load("tool_similar_selection_plus_cursor.png", 6, 6))
{
setObjectName("tool_select_similar");
m_addCursor = KisCursor::load("tool_similar_selection_plus_cursor.png", 1, 21);
m_subtractCursor = KisCursor::load("tool_similar_selection_minus_cursor.png", 1, 21);
setCursor(m_addCursor);
m_subject = 0;
m_optWidget = 0;
m_selectionOptionsWidget = 0;
m_fuzziness = 20;
......@@ -111,9 +104,9 @@ KisToolSelectSimilar::~KisToolSelectSimilar()
void KisToolSelectSimilar::activate()
{
KisToolNonPaint::activate();
m_timer->start(50);
setPickerCursor(m_currentSelectAction);
super::activate();
// m_timer->start(50);
// setPickerCursor(m_currentSelectAction);
if (m_selectionOptionsWidget) {
m_selectionOptionsWidget->slotActivated();
......@@ -125,14 +118,11 @@ void KisToolSelectSimilar::deactivate()
m_timer->stop();
}
void KisToolSelectSimilar::buttonPress(KoPointerEvent *e)
void KisToolSelectSimilar::mousePressEvent(KoPointerEvent *e)
{
if (m_subject) {
QApplication::setOverrideCursor(KisCursor::waitCursor());
KisImageSP m_currentImage;
KisPaintDeviceSP dev;
QPoint pos;
useCursor(m_subtractCursor);
if (m_canvas) {
// QApplication::setOverrideCursor(KisCursor::waitCursor());
quint8 opacity = OPACITY_OPAQUE;
if (e->button() != Qt::LeftButton && e->button() != Qt::RightButton)
......@@ -141,14 +131,13 @@ void KisToolSelectSimilar::buttonPress(KoPointerEvent *e)
if (!(m_currentImage = m_currentImage))
return;
dev = m_currentImage->activeDevice();
KisPaintDeviceSP dev = m_currentImage->activeDevice();
if (!dev || !m_currentImage->activeLayer()->visible())
return;
pos = QPoint(e->pos().floorX(), e->pos().floorY());
KisSelectedTransaction *t = 0;
if (m_currentImage->undo()) t = new KisSelectedTransaction(i18n("Similar Selection"),dev);
QPointF pos = convertToPixelCoord(e);
KisSelectedTransaction * t = new KisSelectedTransaction(i18n("Similar Selection"),dev);
KoColor c = dev->colorAt(pos.x(), pos.y());
opacity = dev->colorSpace()->alpha(c.data());
......@@ -160,11 +149,9 @@ void KisToolSelectSimilar::buttonPress(KoPointerEvent *e)
dev->setDirty();
dev->emitSelectionChanged();
if(m_currentImage->undo())
m_currentImage->undoAdapter()->addCommandOld(t);
m_subject->canvasController()->updateCanvas();
m_canvas->addCommand(t);
QApplication::restoreOverrideCursor();
// QApplication::restoreOverrideCursor();
}
}
......@@ -188,31 +175,13 @@ void KisToolSelectSimilar::slotTimer()
void KisToolSelectSimilar::setPickerCursor(enumSelectionMode action)
{
switch (action) {
case SELECTION_ADD:
m_subject->canvasController()->setCanvasCursor(m_addCursor);
break;
case SELECTION_SUBTRACT:
m_subject->canvasController()->setCanvasCursor(m_subtractCursor);
}
}
void KisToolSelectSimilar::setup(KActionCollection *collection)
{
m_action = collection->action(objectName());
if (m_action == 0) {
m_action = new KAction(KIcon("tool_similar_selection"),
i18n("&Similar Selection"),
collection,
objectName());
Q_CHECK_PTR(m_action);
m_action->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_E));
connect(m_action, SIGNAL(triggered()), this, SLOT(activate()));
m_action->setToolTip(i18n("Select similar colors"));
m_action->setActionGroup(actionGroup());
m_ownAction = true;
}
// switch (action) {
// case SELECTION_ADD:
// useCursor(m_addCursor);
// break;
// case SELECTION_SUBTRACT:
// useCursor(m_subtractCursor);
// }
}
void KisToolSelectSimilar::slotSetFuzziness(int fuzziness)
......@@ -227,7 +196,7 @@ void KisToolSelectSimilar::slotSetAction(int action)
QWidget* KisToolSelectSimilar::createOptionWidget()
{
m_optWidget = new QWidget(parent);
m_optWidget = new QWidget();
Q_CHECK_PTR(m_optWidget);
m_optWidget->setWindowTitle(i18n("Similar Selection"));
......@@ -237,7 +206,9 @@ QWidget* KisToolSelectSimilar::createOptionWidget()
l->setMargin(0);
l->setSpacing(6);
m_selectionOptionsWidget = new KisSelectionOptions(m_optWidget, m_subject);
KisCanvas2* canvas = dynamic_cast<KisCanvas2*>(m_canvas);
Q_ASSERT(canvas);
m_selectionOptionsWidget = new KisSelectionOptions(canvas);
Q_CHECK_PTR(m_selectionOptionsWidget);
l->addWidget(m_selectionOptionsWidget);
......
......@@ -18,14 +18,15 @@
#ifndef KIS_TOOL_SELECT_PICKER_H_
#define KIS_TOOL_SELECT_PICKER_H_
#include <kis_tool_non_paint.h>
#include <kis_tool.h>
#include <KoToolFactory.h>
#include <kis_selection.h>
#include "kis_layer_shape.h"
class KisCanvasSubject;
class QWidget;
class QCheckBox;
class KisIntSpinbox;
class KoCanvasBase;
/**
* Tool to select colors by pointing at a color on the image.
......@@ -36,18 +37,20 @@ class KisIntSpinbox;
class KisSelectionOptions;
class KisToolSelectSimilar : public KisToolNonPaint {
class KisToolSelectSimilar : public KisTool {
Q_OBJECT
typedef KisToolNonPaint super;
typedef KisTool super;
public:
KisToolSelectSimilar();
KisToolSelectSimilar(KoCanvasBase * canvas);
virtual ~KisToolSelectSimilar();
virtual void setup(KActionCollection *collection);
virtual quint32 priority() { return 8; }
virtual enumToolType toolType() { return TOOL_SELECT; }
// virtual quint32 priority() { return 8; }
// virtual enumToolType toolType() { return TOOL_SELECT; }
virtual void paint(QPainter& gc, KoViewConverter &converter) {}
virtual void mousePressEvent(KoPointerEvent *e);
public slots:
......@@ -61,10 +64,8 @@ private:
virtual QWidget* createOptionWidget();
virtual QWidget* optionWidget();
virtual void buttonPress(KoPointerEvent *e);
void setPickerCursor(enumSelectionMode);
QWidget *m_optWidget;
KisSelectionOptions *m_selectionOptionsWidget;
......@@ -83,12 +84,14 @@ class KisToolSelectSimilarFactory : public KoToolFactory {
public:
KisToolSelectSimilarFactory(QObject *parent, const QStringList&)
: KoToolFactory(parent, "KisToolSelectSimilar", i18n( "Select similar colors")
: KoToolFactory(parent, "KisToolSelectSimilar", i18n( "Select similar colors"))
{
setToolTip( i18n( "Select similar colors" ) );
setToolType( TOOL_TYPE_SELECTED );
// setToolType( TOOL_TYPE_SELECTED );
setToolType( dynamicToolType() );
setActivationShapeId( KIS_LAYER_SHAPE_ID );
setIcon( "tool_similar_selection" );
setShortcut( Qt::CTRL + Qt::Key_E );
setShortcut( KShortcut(Qt::CTRL + Qt::Key_E) );
setPriority( 0 );
};
......
......@@ -45,11 +45,8 @@ SelectSimilar::SelectSimilar(QObject *parent, const QStringList &)
{
setComponentData(SelectSimilarFactory::componentData());
if ( parent->inherits("KoToolRegistry") )
{
KoToolRegistry * r = dynamic_cast<KoToolRegistry*>(parent);
r->add(KoToolFactorySP(new KisToolSelectSimilarFactory()));
}
KoToolRegistry * r = KoToolRegistry::instance();
r->add(new KisToolSelectSimilarFactory(r, QStringList()));
}
SelectSimilar::~SelectSimilar()
......
......@@ -49,6 +49,7 @@
#include "scale.h"
#include "kis_doc2.h"
#include "kis_grid_drawer.h"
#include "kis_selection_manager.h"
//#define DEBUG_REPAINT
//#define USE_QT_SCALING
......@@ -160,7 +161,6 @@ void KisQPainterCanvas::paintEvent( QPaintEvent * ev )
QColor color = QColor(random()%255, random()%255, random()%255, 150);
gc.fillRect(ev->rect(), color);
#endif
// ask the current layer to paint its selection (and potentially
// other things, like wetness and active-layer outline
......@@ -171,6 +171,9 @@ void KisQPainterCanvas::paintEvent( QPaintEvent * ev )
gc.setRenderHint( QPainter::SmoothPixmapTransform );
gc.translate( QPoint( -m_d->documentOffset.x(), -m_d->documentOffset.y() ) );
//Paint marching ants
m_d->canvas->view()->selectionManager()->paint(gc, *m_d->viewConverter );
// ask the guides, grids, etc to paint themselves
t.restart();
m_d->gridDrawer->draw(&gc, m_d->viewConverter->viewToDocument(ev->rect()));
......
/*
* Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
* Copyright (c) 2007 Sven Langkamp <sven.langkamp@gmail.com>
*
* The outline algorith uses the limn algorithm of fontutils by
* Karl Berry <karl@cs.umb.edu> and Kathryn Hargreaves <letters@cs.umb.edu>
*
* 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
......@@ -37,6 +41,7 @@
#include <KoDocument.h>
#include <KoMainWindow.h>
#include <KoQueryTrader.h>
#include <KoViewConverter.h>
#include "kis_adjustment_layer.h"
#include "kis_canvas2.h"
......@@ -93,6 +98,22 @@ KisSelectionManager::KisSelectionManager(KisView2 * parent, KisDoc2 * doc)
m_fillPattern(0)
{
m_clipboard = KisClipboard::instance();
for(int i=0; i<8; i++){
QImage texture( 8, 8, QImage::Format_Mono );
for(int y=0; y<8; y++)
for(int x=0; x<8; x++)
texture.setPixel(x, y, ((x+y+i)%8 < 4)? 1 : 0);
QBrush brush;
brush.setTextureImage(texture);
brushes << brush;
}
offset = 0;
timer = new QTimer();
timer->start ( 300 );
connect(timer, SIGNAL(timeout()), this, SLOT(timerEvent()));
}
KisSelectionManager::~KisSelectionManager()
......@@ -322,6 +343,14 @@ void KisSelectionManager::imgSelectionChanged(KisImageSP img)
{
if (img == m_parent->image()) {
updateGUI();
KisPaintDeviceSP dev = img->activeDevice();
if (dev)
if (dev->hasSelection()) {
KisPaintDeviceSP dev = img->activeDevice();
KisSelectionSP selection = dev->selection();
paths = selection->outline();
}
}
}
......@@ -1620,4 +1649,49 @@ void KisSelectionManager::computeTransition (quint8* transition, quint8** buf, q
transition[x] = 0;
}
void KisSelectionManager::timerEvent()
{
offset++;
if(offset>7) offset = 0;
m_parent->canvasBase()->updateCanvas(QRectF(0.0,0.0,1000.0,1000.0));
}
void KisSelectionManager::paint(QPainter& gc, KoViewConverter &converter)
{
kDebug(41010) << "Brush count: " << brushes.count() << endl;
double sx, sy;
converter.zoom(&sx, &sy);
QMatrix matrix;
matrix.scale(sx/m_parent->image()->xRes(), sy/m_parent->image()->yRes());
QMatrix oldWorldMatrix = gc.worldMatrix();
gc.setWorldMatrix( matrix, true);
QTime t;
t.start();
gc.setRenderHints(0);
QPen pen1(Qt::black, 0);
QPen pen(brushes[offset], 0);
int i=0;
gc.setPen(pen1);
foreach(QPolygon polygon, paths)
{
gc.drawPolygon(polygon);
i++;
}
gc.setPen(pen);
foreach(QPolygon polygon, paths)
{
gc.drawPolygon(polygon);
}
kDebug(41010) << "Polygons :" << i << endl;
kDebug(41010) << "Painting marching ants :" << t.elapsed() << endl;
gc.setWorldMatrix( oldWorldMatrix);
}
#include "kis_selection_manager.moc"
......@@ -30,6 +30,7 @@
class KAction;
class KToggleAction;
class KActionCollection;
class KoViewConverter;
class KisView2;
class KisDoc;
......@@ -89,6 +90,8 @@ public slots:
void save();
void toggleDisplaySelection();
void timerEvent();
public:
void grow (qint32 xradius, qint32 yradius);
void shrink (qint32 xradius, qint32 yradius, bool edge_lock);
......@@ -98,6 +101,8 @@ public:
void erode();
void dilate();
void paint(QPainter& gc, KoViewConverter &converter);
private:
void fill(const KoColor& color, bool fillWithPattern, const QString& transactionText);
void updateStatusBar();
......@@ -138,6 +143,11 @@ private:
QList<QAction*> m_pluginActions;
QVector<QPolygon> paths;
QTimer* timer;
int offset;
QList<QBrush> brushes;
};
#endif // KIS_SELECTION_MANAGER_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment