Krita Source Code Documentation
Loading...
Searching...
No Matches
KoPencilTool Class Reference

#include <KoPencilTool.h>

+ Inheritance diagram for KoPencilTool:

Public Member Functions

void activate (const QSet< KoShape * > &shapes) override
 
void deactivate () override
 
void keyPressEvent (QKeyEvent *event) override
 
 KoPencilTool (KoCanvasBase *canvas)
 
void mouseMoveEvent (KoPointerEvent *event) override
 
void mousePressEvent (KoPointerEvent *event) override
 
void mouseReleaseEvent (KoPointerEvent *event) override
 
void paint (QPainter &painter, const KoViewConverter &converter) override
 
 ~KoPencilTool () override
 
- Public Member Functions inherited from KoToolBase
QAction * action (const QString &name) const
 
KoCanvasBasecanvas () const
 Returns the canvas the tool is working on.
 
virtual void copy () const
 
QCursor cursor () const
 return the last emitted cursor
 
virtual void customMoveEvent (KoPointerEvent *event)
 
virtual void customPressEvent (KoPointerEvent *event)
 
virtual void customReleaseEvent (KoPointerEvent *event)
 
virtual void cut ()
 
virtual QRectF decorationsRect () const
 
int decorationThickness () const
 decorationThickness The minimum thickness for tool decoration lines, this is derived from the screen magnification, thus the HiDPI settings. Note: to use this effectively, also set the pen to isCosmetic(true);
 
virtual void deleteSelection ()
 
virtual void deselect ()
 deselect the tool should clear the selection if it has one.
 
virtual void dragLeaveEvent (QDragLeaveEvent *event)
 
virtual void dragMoveEvent (QDragMoveEvent *event, const QPointF &point)
 
virtual void dropEvent (QDropEvent *event, const QPointF &point)
 
virtual void explicitUserStrokeEndRequest ()
 explicitUserStrokeEndRequest is called by the input manager when the user presses the Enter key or any equivalent key. This callback comes before requestStrokeEnd(), which comes from a different source.
 
KoToolFactoryBasefactory () const
 
virtual void focusInEvent (QFocusEvent *event)
 
virtual void focusOutEvent (QFocusEvent *event)
 
virtual bool hasSelection ()
 
virtual void inputMethodEvent (QInputMethodEvent *event)
 
virtual QVariant inputMethodQuery (Qt::InputMethodQuery query) const
 
bool isInTextMode () const
 
bool isOpacityPresetMode () const
 
virtual void keyReleaseEvent (QKeyEvent *event)
 
 KoToolBase (KoCanvasBase *canvas)
 
bool maskSyntheticEvents () const
 
virtual void mouseDoubleClickEvent (KoPointerEvent *event)
 
virtual void mouseTripleClickEvent (KoPointerEvent *event)
 
QList< QPointer< QWidget > > optionWidgets ()
 
virtual bool paste ()
 
virtual QMenu * popupActionsMenu ()
 
virtual KisPopupWidgetInterfacepopupWidget ()
 
virtual bool selectAll ()
 selectAll select all data the tool can select.
 
virtual KoToolSelectionselection ()
 
Q_INVOKABLE QString toolId () const
 
virtual bool wantsAutoScroll () const
 
 ~KoToolBase () override
 

Protected Slots

virtual void slotUpdatePencilCursor ()
 

Protected Member Functions

virtual void addPathShape (KoPathShape *path, bool closePath)
 
QList< QPointer< QWidget > > createOptionWidgets () override
 
KoShapeStrokeSP createStroke ()
 
qreal getFittingError ()
 
KoPathShapepath ()
 
void setFittingError (qreal fittingError)
 
void setStrokeColor (QColor color)
 
- Protected Member Functions inherited from KoToolBase
virtual QWidget * createOptionWidget ()
 
int grabSensitivity () const
 Convenience function to get the current grab sensitivity.
 
qreal handleDocRadius () const
 
QRectF handleGrabRect (const QPointF &position) const
 
QRectF handlePaintRect (const QPointF &position) const
 
int handleRadius () const
 Convenience function to get the current handle radius.
 
bool isActivated () const
 
 KoToolBase (KoToolBasePrivate &dd)
 
KoPointerEventlastDeliveredPointerEvent () const
 
void setAbstractResource (KoAbstractCanvasResourceInterfaceSP abstractResource)
 
void setConverter (KoDerivedResourceConverterSP converter)
 
void setIsOpacityPresetMode (bool value)
 
void setMaskSyntheticEvents (bool value)
 
void setTextMode (bool value)
 
QHash< int, KoAbstractCanvasResourceInterfaceSPtoolAbstractResources ()
 
QHash< int, KoDerivedResourceConverterSPtoolConverters ()
 
void useCursor (const QCursor &cursor)
 

Private Types

enum  PencilMode { ModeRaw , ModeCurve , ModeStraight }
 

Private Slots

void selectMode (int mode)
 
void setDelta (double delta)
 
void setOptimize (int state)
 

Private Member Functions

void addPoint (const QPointF &point)
 
bool connectPaths (KoPathShape *pathShape, KoPathPoint *pointAtStart, KoPathPoint *pointAtEnd)
 Connects given path with the ones we hit when starting/finishing.
 
KoPathPointendPointAtPosition (const QPointF &position)
 returns the nearest existing path point
 
void finish (bool closePath)
 
qreal lineAngle (const QPointF &p1, const QPointF &p2)
 

Private Attributes

bool m_close {false}
 
qreal m_combineAngle {15.0}
 
KConfigGroup m_configGroup
 
KoPathPointm_existingEndPoint {0}
 an existing path point we finished a new path at
 
KoPathPointm_existingStartPoint {0}
 an existing path point we started a new path at
 
qreal m_fittingError {5.0}
 
KoPathPointm_hoveredPoint {0}
 an existing path end point the mouse is hovering on
 
PencilMode m_mode {ModeCurve}
 
bool m_optimizeCurve {false}
 
bool m_optimizeRaw {false}
 
QList< QPointF > m_points
 
KoPathShapem_shape {0}
 
QColor m_strokeColor
 
KoStrokeConfigWidgetm_strokeWidget {0}
 

Additional Inherited Members

- Public Slots inherited from KoToolBase
virtual void canvasResourceChanged (int key, const QVariant &res)
 
virtual void documentResourceChanged (int key, const QVariant &res)
 
virtual void repaintDecorations ()
 
virtual void requestRedoDuringStroke ()
 
virtual void requestStrokeCancellation ()
 
virtual void requestStrokeEnd ()
 
virtual void requestUndoDuringStroke ()
 
void setStatusText (const QString &statusText)
 
void updateOptionsWidgetIcons ()
 
- Signals inherited from KoToolBase
void activateTool (const QString &id)
 
void cursorChanged (const QCursor &cursor)
 
void selectionChanged (bool hasSelection)
 
void statusTextChanged (const QString &statusText)
 
void textModeChanged (bool inTextMode)
 
- Protected Attributes inherited from KoToolBase
KoToolBasePrivated_ptr
 

Detailed Description

Definition at line 22 of file KoPencilTool.h.

Member Enumeration Documentation

◆ PencilMode

Enumerator
ModeRaw 
ModeCurve 
ModeStraight 

Definition at line 75 of file KoPencilTool.h.

Constructor & Destructor Documentation

◆ KoPencilTool()

KoPencilTool::KoPencilTool ( KoCanvasBase * canvas)
explicit

Definition at line 44 of file KoPencilTool.cpp.

46{
47}
KoCanvasBase * canvas() const
Returns the canvas the tool is working on.

◆ ~KoPencilTool()

KoPencilTool::~KoPencilTool ( )
override

Definition at line 49 of file KoPencilTool.cpp.

50{
51}

Member Function Documentation

◆ activate()

void KoPencilTool::activate ( const QSet< KoShape * > & shapes)
overridevirtual

This method is called when this tool instance is activated. For any main window there is only one tool active at a time, which then gets all user input. Switching between tools will call deactivate on one and activate on the new tool allowing the tool to flush items (like a selection) when it is not in use.

Parameters
shapesthe set of shapes that are selected or suggested for editing by a selected shape for the tool to work on. Not all shapes will be meant for this tool.
See also
deactivate()

Reimplemented from KoToolBase.

Definition at line 157 of file KoPencilTool.cpp.

158{
159 KoToolBase::activate(shapes);
160
161 m_points.clear();
162 m_close = false;
164
165 if (m_strokeWidget) {
167 }
168 m_configGroup = KSharedConfig::openConfig()->group(toolId());
169}
QList< QPointF > m_points
virtual void slotUpdatePencilCursor()
KoStrokeConfigWidget * m_strokeWidget
KConfigGroup m_configGroup
Q_INVOKABLE QString toolId() const
virtual void activate(const QSet< KoShape * > &shapes)

References KoStrokeConfigWidget::activate(), KoToolBase::activate(), m_close, m_configGroup, m_points, m_strokeWidget, slotUpdatePencilCursor(), and KoToolBase::toolId().

◆ addPathShape()

void KoPencilTool::addPathShape ( KoPathShape * path,
bool closePath )
protectedvirtual

Add path shape to document. This method can be overridden and change the behaviour of the tool. In that case the subclass takes ownership of pathShape. It gets only called, if there are two or more points in the path.

Reimplemented in __KisToolPencilLocalTool.

Definition at line 370 of file KoPencilTool.cpp.

371{
372 KoShape * startShape = 0;
373 KoShape * endShape = 0;
374
375 if (closePath) {
376 path->close();
377 path->normalize();
378 } else {
379 path->normalize();
382 startShape = m_existingStartPoint->parent();
384 endShape = m_existingEndPoint->parent();
385 }
386 }
387
388 KUndo2Command * cmd = canvas()->shapeController()->addShape(path, 0);
389 if (cmd) {
391 selection->deselectAll();
392 selection->select(path);
393
394 if (startShape)
395 canvas()->shapeController()->removeShape(startShape, cmd);
396 if (endShape && startShape != endShape)
397 canvas()->shapeController()->removeShape(endShape, cmd);
398
399 canvas()->addCommand(cmd);
400 } else {
401 canvas()->updateCanvas(path->boundingRect());
402 delete path;
403 }
404}
QPointer< KoShapeController > shapeController
virtual KoShapeManager * shapeManager() const =0
virtual void updateCanvas(const QRectF &rc)=0
virtual void addCommand(KUndo2Command *command)=0
KoPathShape * parent() const
Get the path shape the point belongs to.
bool connectPaths(KoPathShape *pathShape, KoPathPoint *pointAtStart, KoPathPoint *pointAtEnd)
Connects given path with the ones we hit when starting/finishing.
KoPathPoint * m_existingEndPoint
an existing path point we finished a new path at
KoPathShape * path()
KoPathPoint * m_existingStartPoint
an existing path point we started a new path at
KoSelection * selection
virtual KoToolSelection * selection()

References KoCanvasBase::addCommand(), KoToolBase::canvas(), connectPaths(), m_existingEndPoint, m_existingStartPoint, KoPathPoint::parent(), path(), KoShapeManager::selection, KoToolBase::selection(), KoCanvasBase::shapeController, KoCanvasBase::shapeManager(), and KoCanvasBase::updateCanvas().

◆ addPoint()

void KoPencilTool::addPoint ( const QPointF & point)
private

Definition at line 193 of file KoPencilTool.cpp.

194{
195 if (! m_shape)
196 return;
197
198 // do a moveTo for the first point added
199 if (m_points.empty())
200 m_shape->moveTo(point);
201 // do not allow coincident points
202 else if (point != m_points.last())
203 m_shape->lineTo(point);
204 else
205 return;
206
207 m_points.append(point);
209}
KoPathPoint * lineTo(const QPointF &p)
Adds a new line segment.
KoPathPoint * moveTo(const QPointF &p)
Starts a new Subpath.
QRectF boundingRect() const override
reimplemented
KoPathShape * m_shape

References KoPathShape::boundingRect(), KoToolBase::canvas(), KoPathShape::lineTo(), m_points, m_shape, KoPathShape::moveTo(), and KoCanvasBase::updateCanvas().

◆ connectPaths()

bool KoPencilTool::connectPaths ( KoPathShape * pathShape,
KoPathPoint * pointAtStart,
KoPathPoint * pointAtEnd )
private

Connects given path with the ones we hit when starting/finishing.

Definition at line 493 of file KoPencilTool.cpp.

494{
495 // at least one point must be valid
496 if (!pointAtStart && !pointAtEnd)
497 return false;
498 // do not allow connecting to the same point twice
499 if (pointAtStart == pointAtEnd)
500 pointAtEnd = 0;
501
502 // we have hit an existing path point on start/finish
503 // what we now do is:
504 // 1. combine the new created path with the ones we hit on start/finish
505 // 2. merge the endpoints of the corresponding subpaths
506
507 uint newPointCount = pathShape->subpathPointCount(0);
508 KoPathPointIndex newStartPointIndex(0, 0);
509 KoPathPointIndex newEndPointIndex(0, newPointCount - 1);
510 KoPathPoint * newStartPoint = pathShape->pointByIndex(newStartPointIndex);
511 KoPathPoint * newEndPoint = pathShape->pointByIndex(newEndPointIndex);
512
513 KoPathShape * startShape = pointAtStart ? pointAtStart->parent() : 0;
514 KoPathShape * endShape = pointAtEnd ? pointAtEnd->parent() : 0;
515
516 // combine with the path we hit on start
517 KoPathPointIndex startIndex(-1, -1);
518 if (pointAtStart) {
519 startIndex = startShape->pathPointIndex(pointAtStart);
520 pathShape->combine(startShape);
521 pathShape->moveSubpath(0, pathShape->subpathCount() - 1);
522 }
523 // combine with the path we hit on finish
524 KoPathPointIndex endIndex(-1, -1);
525 if (pointAtEnd) {
526 endIndex = endShape->pathPointIndex(pointAtEnd);
527 if (endShape != startShape) {
528 endIndex.first += pathShape->subpathCount();
529 pathShape->combine(endShape);
530 }
531 }
532 // do we connect twice to a single subpath ?
533 bool connectToSingleSubpath = (startShape == endShape && startIndex.first == endIndex.first);
534
535 if (startIndex.second == 0 && !connectToSingleSubpath) {
536 pathShape->reverseSubpath(startIndex.first);
537 startIndex.second = pathShape->subpathPointCount(startIndex.first) - 1;
538 }
539 if (endIndex.second > 0 && !connectToSingleSubpath) {
540 pathShape->reverseSubpath(endIndex.first);
541 endIndex.second = 0;
542 }
543
544 // after combining we have a path where with the subpaths in the following
545 // order:
546 // 1. the subpaths of the pathshape we started the new path at
547 // 2. the subpath we just created
548 // 3. the subpaths of the pathshape we finished the new path at
549
550 // get the path points we want to merge, as these are not going to
551 // change while merging
552 KoPathPoint * existingStartPoint = pathShape->pointByIndex(startIndex);
553 KoPathPoint * existingEndPoint = pathShape->pointByIndex(endIndex);
554
555 // merge first two points
556 if (existingStartPoint) {
557 KoPathPointData pd1(pathShape, pathShape->pathPointIndex(existingStartPoint));
558 KoPathPointData pd2(pathShape, pathShape->pathPointIndex(newStartPoint));
559 KoPathPointMergeCommand cmd1(pd1, pd2);
560 cmd1.redo();
561 }
562 // merge last two points
563 if (existingEndPoint) {
564 KoPathPointData pd3(pathShape, pathShape->pathPointIndex(newEndPoint));
565 KoPathPointData pd4(pathShape, pathShape->pathPointIndex(existingEndPoint));
566 KoPathPointMergeCommand cmd2(pd3, pd4);
567 cmd2.redo();
568 }
569
570 return true;
571}
unsigned int uint
QPair< int, int > KoPathPointIndex
Definition KoPathShape.h:28
Describe a KoPathPoint by a KoPathShape and its indices.
The undo / redo command for merging two subpath end points.
A KoPathPoint represents a point in a path.
The position of a path point within a path shape.
Definition KoPathShape.h:63
int subpathPointCount(int subpathIndex) const
Returns the number of points in a subpath.
bool reverseSubpath(int subpathIndex)
Reverse subpath.
bool moveSubpath(int oldSubpathIndex, int newSubpathIndex)
Moves the position of a subpath within a path.
int subpathCount() const
Returns the number of subpaths in the path.
KoPathPointIndex pathPointIndex(const KoPathPoint *point) const
Returns the path point index of a given path point.
KoPathPoint * pointByIndex(const KoPathPointIndex &pointIndex) const
Returns the path point specified by a path point index.
int combine(KoPathShape *path)
Combines two path shapes by appending the data of the specified path.

References KoPathShape::combine(), KoPathShape::moveSubpath(), KoPathPoint::parent(), KoPathShape::pathPointIndex(), KoPathShape::pointByIndex(), KoPathPointMergeCommand::redo(), KoPathShape::reverseSubpath(), KoPathShape::subpathCount(), and KoPathShape::subpathPointCount().

◆ createOptionWidgets()

QList< QPointer< QWidget > > KoPencilTool::createOptionWidgets ( )
overrideprotectedvirtual

Reimplemented from KoToolBase.

Definition at line 281 of file KoPencilTool.cpp.

282{
283 m_mode = static_cast<PencilMode>(m_configGroup.readEntry<int>("pencilMode", m_mode));
284 m_optimizeRaw = m_configGroup.readEntry<bool>("optimizeRaw", m_optimizeRaw);
285 m_optimizeCurve = m_configGroup.readEntry<bool>("optimizeCurve", m_optimizeCurve);
286 m_combineAngle = m_configGroup.readEntry<qreal>("combineAngle", m_combineAngle);
287 m_fittingError = m_configGroup.readEntry<qreal>("fittingError", m_fittingError);
288
289 QList<QPointer<QWidget> > widgets;
290 QWidget *optionWidget = new QWidget();
291 QVBoxLayout * layout = new QVBoxLayout(optionWidget);
292
293 QHBoxLayout *modeLayout = new QHBoxLayout;
294 modeLayout->setSpacing(3);
295 QLabel *modeLabel = new QLabel(i18n("Precision:"), optionWidget);
296 QComboBox * modeBox = new QComboBox(optionWidget);
297 modeBox->addItem(i18nc("The raw line data", "Raw"));
298 modeBox->addItem(i18n("Curve"));
299 modeBox->addItem(i18n("Straight"));
300 modeLayout->addWidget(modeLabel);
301 modeLayout->addWidget(modeBox, 1);
302 layout->addLayout(modeLayout);
303
304 QStackedWidget * stackedWidget = new QStackedWidget(optionWidget);
305
306 QWidget * rawBox = new QWidget(stackedWidget);
307 QVBoxLayout * rawLayout = new QVBoxLayout(rawBox);
308 QCheckBox * optimizeRaw = new QCheckBox(i18n("Optimize"), rawBox);
309 optimizeRaw->setChecked(m_optimizeRaw);
310 rawLayout->addWidget(optimizeRaw);
311 rawLayout->setContentsMargins(0, 0, 0, 0);
312
313 QWidget * curveBox = new QWidget(stackedWidget);
314 QHBoxLayout * curveLayout = new QHBoxLayout(curveBox);
315 QCheckBox * optimizeCurve = new QCheckBox(i18n("Optimize"), curveBox);
316 optimizeCurve->setChecked(m_optimizeCurve);
317 QDoubleSpinBox * fittingError = new KisDoubleParseSpinBox(curveBox);
318 fittingError->setSingleStep(0.50);
319 fittingError->setMaximum(400.0);
320 fittingError->setMinimum(0.0);
321 fittingError->setValue(m_fittingError);
322 fittingError->setToolTip(i18n("Exactness:"));
323 curveLayout->addWidget(optimizeCurve);
324 curveLayout->addWidget(fittingError);
325 curveLayout->setContentsMargins(0, 0, 0, 0);
326
327 QWidget *straightBox = new QWidget(stackedWidget);
328 QVBoxLayout *straightLayout = new QVBoxLayout(straightBox);
329 QDoubleSpinBox *combineAngle = new KisDoubleParseSpinBox(straightBox);
330 combineAngle->setSingleStep(0.50);
331 combineAngle->setMaximum(360.0);
332 combineAngle->setMinimum(0.0);
333 combineAngle->setValue(m_combineAngle);
334 combineAngle->setSuffix(" deg");
335 // QT5TODO
336 //combineAngle->setLabel(i18n("Combine angle:"), Qt::AlignLeft | Qt::AlignVCenter);
337 straightLayout->addWidget(combineAngle);
338 straightLayout->setContentsMargins(0, 0, 0, 0);
339
340 stackedWidget->addWidget(rawBox);
341 stackedWidget->addWidget(curveBox);
342 stackedWidget->addWidget(straightBox);
343 layout->addWidget(stackedWidget);
344 layout->addStretch(1);
345
346 connect(modeBox, SIGNAL(activated(int)), stackedWidget, SLOT(setCurrentIndex(int)));
347 connect(modeBox, SIGNAL(activated(int)), this, SLOT(selectMode(int)));
348 connect(optimizeRaw, SIGNAL(stateChanged(int)), this, SLOT(setOptimize(int)));
349 connect(optimizeCurve, SIGNAL(stateChanged(int)), this, SLOT(setOptimize(int)));
350 connect(fittingError, SIGNAL(valueChanged(double)), this, SLOT(setDelta(double)));
351 connect(combineAngle, SIGNAL(valueChanged(double)), this, SLOT(setDelta(double)));
352
353 modeBox->setCurrentIndex(m_mode);
354 stackedWidget->setCurrentIndex(m_mode);
355 optionWidget->setObjectName(i18n("Pencil"));
356 optionWidget->setWindowTitle(i18n("Pencil"));
357 widgets.append(optionWidget);
358
361 m_strokeWidget->setWindowTitle(i18n("Line"));
362 connect(m_strokeWidget, SIGNAL(sigStrokeChanged()), SLOT(slotUpdatePencilCursor()));
363 if (isActivated()) {
365 }
366 widgets.append(m_strokeWidget);
367 return widgets;
368}
The KisDoubleParseSpinBox class is a cleverer doubleSpinBox, able to parse arithmetic expressions.
void setDelta(double delta)
void selectMode(int mode)
qreal m_fittingError
PencilMode m_mode
bool m_optimizeCurve
void setOptimize(int state)
qreal m_combineAngle
A widget for configuring the stroke of a shape.
void setNoSelectionTrackingMode(bool value)
bool isActivated() const

References KoStrokeConfigWidget::activate(), KoToolBase::canvas(), KoToolBase::isActivated(), m_combineAngle, m_configGroup, m_fittingError, m_mode, m_optimizeCurve, m_optimizeRaw, m_strokeWidget, selectMode(), setDelta(), KoStrokeConfigWidget::setNoSelectionTrackingMode(), setOptimize(), and slotUpdatePencilCursor().

◆ createStroke()

KoShapeStrokeSP KoPencilTool::createStroke ( )
protected

Definition at line 436 of file KoPencilTool.cpp.

437{
438 KoShapeStrokeSP stroke;
439 if (m_strokeWidget) {
441 stroke->setColor(m_strokeColor);
442 }
443 return stroke;
444}
QColor m_strokeColor
KoShapeStrokeSP createShapeStroke()

References KoStrokeConfigWidget::createShapeStroke(), m_strokeColor, and m_strokeWidget.

◆ deactivate()

void KoPencilTool::deactivate ( )
overridevirtual

This method is called whenever this tool is no longer the active tool

See also
activate()

Reimplemented from KoToolBase.

Definition at line 171 of file KoPencilTool.cpp.

172{
173 m_points.clear();
174 delete m_shape;
175 m_shape = 0;
178 m_hoveredPoint = 0;
179
180 if (m_strokeWidget) {
182 }
183
185}
KoPathPoint * m_hoveredPoint
an existing path end point the mouse is hovering on
virtual void deactivate()

References KoToolBase::deactivate(), KoStrokeConfigWidget::deactivate(), m_existingEndPoint, m_existingStartPoint, m_hoveredPoint, m_points, m_shape, and m_strokeWidget.

◆ endPointAtPosition()

KoPathPoint * KoPencilTool::endPointAtPosition ( const QPointF & position)
private

returns the nearest existing path point

Definition at line 451 of file KoPencilTool.cpp.

452{
453 QRectF roi = handleGrabRect(position);
454 QList<KoShape *> shapes = canvas()->shapeManager()->shapesAt(roi);
455
457 qreal minDistance = HUGE_VAL;
458 qreal maxDistance = canvas()->viewConverter()->viewToDocumentX(grabSensitivity());
459
460 Q_FOREACH(KoShape * shape, shapes) {
461 KoPathShape * path = dynamic_cast<KoPathShape*>(shape);
462 if (!path)
463 continue;
464 KoParameterShape *paramShape = dynamic_cast<KoParameterShape*>(shape);
465 if (paramShape && paramShape->isParametricShape())
466 continue;
467
468 KoPathPoint * p = 0;
469 uint subpathCount = path->subpathCount();
470 for (uint i = 0; i < subpathCount; ++i) {
471 if (path->isClosedSubpath(i))
472 continue;
473 p = path->pointByIndex(KoPathPointIndex(i, 0));
474 // check start of subpath
475 qreal d = squareDistance(position, path->shapeToDocument(p->point()));
476 if (d < minDistance && d < maxDistance) {
477 nearestPoint = p;
478 minDistance = d;
479 }
480 // check end of subpath
481 p = path->pointByIndex(KoPathPointIndex(i, path->subpathPointCount(i) - 1));
482 d = squareDistance(position, path->shapeToDocument(p->point()));
483 if (d < minDistance && d < maxDistance) {
484 nearestPoint = p;
485 minDistance = d;
486 }
487 }
488 }
489
490 return nearestPoint;
491}
const Params2D p
qreal squareDistance(const QPointF &p1, const QPointF &p2)
virtual const KoViewConverter * viewConverter() const =0
bool isParametricShape() const
Check if object is a parametric shape.
QList< KoShape * > shapesAt(const QRectF &rect, bool omitHiddenShapes=true, bool containedMode=false)
int grabSensitivity() const
Convenience function to get the current grab sensitivity.
QRectF handleGrabRect(const QPointF &position) const
virtual qreal viewToDocumentX(qreal viewX) const
qreal nearestPoint(const QList< QPointF > controlPoints, const QPointF &point, qreal *resultDistance, QPointF *resultPoint)

References KoToolBase::canvas(), KoToolBase::grabSensitivity(), KoToolBase::handleGrabRect(), KoParameterShape::isParametricShape(), p, KoCanvasBase::shapeManager(), KoShapeManager::shapesAt(), squareDistance(), KoCanvasBase::viewConverter(), and KoViewConverter::viewToDocumentX().

◆ finish()

void KoPencilTool::finish ( bool closePath)
private

Definition at line 220 of file KoPencilTool.cpp.

221{
222 if (m_points.count() < 2)
223 return;
224
225 KoPathShape * path = 0;
226 QList<QPointF> complete;
227 QList<QPointF> *points = &m_points;
228
230 float combineAngle;
231
232 if (m_mode == ModeStraight)
233 combineAngle = m_combineAngle;
234 else
235 combineAngle = 0.50f;
236
237 //Add the first two points
238 complete.append(m_points[0]);
239 complete.append(m_points[1]);
240
241 //Now we need to get the angle of the first line
242 float lastAngle = lineAngle(complete[0], complete[1]);
243
244 uint pointCount = m_points.count();
245 for (uint i = 2; i < pointCount; ++i) {
246 float angle = lineAngle(complete.last(), m_points[i]);
247 if (qAbs(angle - lastAngle) < combineAngle)
248 complete.removeLast();
249 complete.append(m_points[i]);
250 lastAngle = angle;
251 }
252
253 m_points.clear();
254 points = &complete;
255 }
256
257 switch (m_mode) {
258 case ModeCurve: {
259 path = bezierFit(*points, m_fittingError);
260 }
261 break;
262 case ModeStraight:
263 case ModeRaw: {
264 path = new KoPathShape();
265 uint pointCount = points->count();
266 path->moveTo(points->at(0));
267 for (uint i = 1; i < pointCount; ++i)
268 path->lineTo(points->at(i));
269 }
270 break;
271 }
272
273 if (! path)
274 return;
275
276 path->setShapeId(KoPathShapeId);
277 path->setStroke(createStroke());
278 addPathShape(path, closePath);
279}
KoPathShape * bezierFit(const QList< QPointF > &points, float error)
#define KoPathShapeId
Definition KoPathShape.h:20
KoShapeStrokeSP createStroke()
virtual void addPathShape(KoPathShape *path, bool closePath)
qreal lineAngle(const QPointF &p1, const QPointF &p2)

References addPathShape(), bezierFit(), createStroke(), KoPathShapeId, lineAngle(), m_combineAngle, m_fittingError, m_mode, m_optimizeCurve, m_optimizeRaw, m_points, ModeCurve, ModeRaw, and ModeStraight.

◆ getFittingError()

qreal KoPencilTool::getFittingError ( )
protected

Definition at line 573 of file KoPencilTool.cpp.

574{
575 return this->m_fittingError;
576}

References m_fittingError.

◆ keyPressEvent()

void KoPencilTool::keyPressEvent ( QKeyEvent * event)
overridevirtual

Called when a key is pressed. Implementors should call event->ignore() if they do not actually use the event. Default implementation ignores this event.

Parameters
eventstate and reason of this key press

Reimplemented from KoToolBase.

Definition at line 148 of file KoPencilTool.cpp.

149{
150 if (m_shape) {
151 event->accept();
152 } else {
153 event->ignore();
154 }
155}

References m_shape.

◆ lineAngle()

qreal KoPencilTool::lineAngle ( const QPointF & p1,
const QPointF & p2 )
private

Definition at line 211 of file KoPencilTool.cpp.

212{
213 qreal angle = atan2(p2.y() - p1.y(), p2.x() - p1.x());
214 if (angle < 0.0)
215 angle += 2 * M_PI;
216
217 return angle * 180.0 / M_PI;
218}
QPointF p2
QPointF p1
#define M_PI
Definition kis_global.h:111
KRITAIMAGE_EXPORT qreal atan2(qreal y, qreal x)
atan2 replacement

References M_PI, p1, and p2.

◆ mouseMoveEvent()

void KoPencilTool::mouseMoveEvent ( KoPointerEvent * event)
overridevirtual

Called when the mouse or stylus moved over the canvas. Implementors should call event->ignore() if they do not actually use the event.

Parameters
eventstate and reason of this mouse or stylus move

Implements KoToolBase.

Definition at line 103 of file KoPencilTool.cpp.

104{
105 if (event->buttons() & Qt::LeftButton)
106 addPoint(event->point);
107
108 KoPathPoint * endPoint = endPointAtPosition(event->point);
109 if (m_hoveredPoint != endPoint) {
110 if (m_hoveredPoint) {
111 QPointF nodePos = m_hoveredPoint->parent()->shapeToDocument(m_hoveredPoint->point());
113 }
114 m_hoveredPoint = endPoint;
115 if (m_hoveredPoint) {
116 QPointF nodePos = m_hoveredPoint->parent()->shapeToDocument(m_hoveredPoint->point());
118 }
119 }
120}
QPointF point
void addPoint(const QPointF &point)
KoPathPoint * endPointAtPosition(const QPointF &position)
returns the nearest existing path point
Qt::MouseButtons buttons() const
return buttons pressed (see QMouseEvent::buttons());
QPointF point
The point in document coordinates.
QPointF shapeToDocument(const QPointF &point) const
Transforms point from shape coordinates to document coordinates.
Definition KoShape.cpp:1001
QRectF handlePaintRect(const QPointF &position) const

References addPoint(), KoPointerEvent::buttons(), KoToolBase::canvas(), endPointAtPosition(), KoToolBase::handlePaintRect(), m_hoveredPoint, KoPathPoint::parent(), KoPathPoint::point, KoPointerEvent::point, KoShape::shapeToDocument(), and KoCanvasBase::updateCanvas().

◆ mousePressEvent()

void KoPencilTool::mousePressEvent ( KoPointerEvent * event)
overridevirtual

Called when (one of) the mouse or stylus buttons is pressed. Implementors should call event->ignore() if they do not actually use the event.

Parameters
eventstate and reason of this mouse or stylus press

Implements KoToolBase.

Definition at line 84 of file KoPencilTool.cpp.

85{
87
88 if (!m_shape && stroke && stroke->isVisible()) {
89 m_shape = new KoPathShape();
92 m_points.clear();
93
94 QPointF point = event->point;
98
99 addPoint(point);
100 }
101}
virtual void setStroke(KoShapeStrokeModelSP stroke)
Definition KoShape.cpp:899
void setShapeId(const QString &id)
Definition KoShape.cpp:880

References addPoint(), createStroke(), endPointAtPosition(), KoPathShapeId, m_existingStartPoint, m_points, m_shape, KoPathPoint::parent(), KoPathPoint::point, KoShape::setShapeId(), KoShape::setStroke(), and KoShape::shapeToDocument().

◆ mouseReleaseEvent()

void KoPencilTool::mouseReleaseEvent ( KoPointerEvent * event)
overridevirtual

Called when (one of) the mouse or stylus buttons is released. Implementors should call event->ignore() if they do not actually use the event.

Parameters
eventstate and reason of this mouse or stylus release

Implements KoToolBase.

Definition at line 122 of file KoPencilTool.cpp.

123{
124 if (! m_shape)
125 return;
126
127 QPointF point = event->point;
131
132 addPoint(point);
133 finish(event->modifiers() & Qt::ShiftModifier);
134
137 m_hoveredPoint = 0;
138
139 // the original path may be different from the one added
140 if (canvas() && m_shape) {
142 }
143 delete m_shape;
144 m_shape = 0;
145 m_points.clear();
146}
void finish(bool closePath)
Qt::KeyboardModifiers modifiers() const

References addPoint(), KoPathShape::boundingRect(), KoToolBase::canvas(), endPointAtPosition(), finish(), m_existingEndPoint, m_existingStartPoint, m_hoveredPoint, m_points, m_shape, KoPointerEvent::modifiers(), KoPathPoint::parent(), KoPathPoint::point, KoShape::shapeToDocument(), and KoCanvasBase::updateCanvas().

◆ paint()

void KoPencilTool::paint ( QPainter & painter,
const KoViewConverter & converter )
overridevirtual

Called by the canvas to paint any decorations that the tool deems needed. The painter has the top left of the canvas as its origin.

Parameters
painterused for painting the shape
converterto convert between internal and view coordinates.

Implements KoToolBase.

Definition at line 53 of file KoPencilTool.cpp.

54{
55 if (m_shape) {
56 painter.save();
57
58 painter.setTransform(m_shape->absoluteTransformation() *
59 converter.documentToView() *
60 painter.transform());
61
62 painter.save();
63 m_shape->paint(painter);
64 painter.restore();
65
66 if (m_shape->stroke()) {
67 painter.save();
68 m_shape->stroke()->paint(m_shape, painter);
69 painter.restore();
70 }
71
72 painter.restore();
73 }
74
75 if (m_hoveredPoint) {
78
79 helper.setHandleStyle(KisHandleStyle::primarySelection(canvas()->displayRendererInterface()->handlePaletteForDisplayColorSpace()));
81 }
82}
The KisHandlePainterHelper class is a special helper for painting handles around objects....
void setHandleStyle(const KisHandleStyle &style)
static KisHandleStyle & primarySelection(KisHandlePalette palette=KisHandlePalette())
@ Node
the node point
Definition KoPathPoint.h:49
void paint(KisHandlePainterHelper &handlesHelper, PointTypes types, bool active=true)
void paint(QPainter &painter) const override
reimplemented
virtual KoShapeStrokeModelSP stroke() const
Definition KoShape.cpp:885
QTransform absoluteTransformation() const
Definition KoShape.cpp:330
static KisHandlePainterHelper createHandlePainterHelperView(QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius=0.0, int decorationThickness=1)
Definition KoShape.cpp:977
int handleRadius() const
Convenience function to get the current handle radius.
int decorationThickness() const
decorationThickness The minimum thickness for tool decoration lines, this is derived from the screen ...
virtual QPointF documentToView(const QPointF &documentPoint) const

References KoShape::absoluteTransformation(), KoToolBase::canvas(), KoShape::createHandlePainterHelperView(), KoToolBase::decorationThickness(), KoViewConverter::documentToView(), KoToolBase::handleRadius(), m_hoveredPoint, m_shape, KoPathPoint::Node, KoPathPoint::paint(), KoPathShape::paint(), KoPathPoint::parent(), KisHandleStyle::primarySelection(), KisHandlePainterHelper::setHandleStyle(), and KoShape::stroke().

◆ path()

KoPathShape * KoPencilTool::path ( )
protected

Definition at line 446 of file KoPencilTool.cpp.

447{
448 return m_shape;
449}

References m_shape.

◆ selectMode

void KoPencilTool::selectMode ( int mode)
privateslot

Definition at line 406 of file KoPencilTool.cpp.

407{
408 m_mode = static_cast<PencilMode>(mode);
409 m_configGroup.writeEntry("pencilMode", mode);
410}

References m_configGroup, and m_mode.

◆ setDelta

void KoPencilTool::setDelta ( double delta)
privateslot

Definition at line 424 of file KoPencilTool.cpp.

425{
426 if (m_mode == ModeCurve) {
427 m_fittingError = delta;
428 m_configGroup.writeEntry("fittingError", m_fittingError);
429 }
430 else if (m_mode == ModeStraight) {
431 m_combineAngle = delta;
432 m_configGroup.writeEntry("combineAngle", m_combineAngle);
433 }
434}

References m_combineAngle, m_configGroup, m_fittingError, m_mode, ModeCurve, and ModeStraight.

◆ setFittingError()

void KoPencilTool::setFittingError ( qreal fittingError)
protected

Definition at line 583 of file KoPencilTool.cpp.

584{
585 this->m_fittingError = fittingError;
586}

References m_fittingError.

◆ setOptimize

void KoPencilTool::setOptimize ( int state)
privateslot

Definition at line 412 of file KoPencilTool.cpp.

413{
414 if (m_mode == ModeRaw) {
415 m_optimizeRaw = state == Qt::Checked ? true : false;
416 m_configGroup.writeEntry("optimizeRaw", m_optimizeRaw);
417 }
418 else {
419 m_optimizeCurve = state == Qt::Checked ? true : false;
420 m_configGroup.writeEntry("optimizeCurve", m_optimizeCurve);
421 }
422}

References m_configGroup, m_mode, m_optimizeCurve, m_optimizeRaw, and ModeRaw.

◆ setStrokeColor()

void KoPencilTool::setStrokeColor ( QColor color)
protected

Definition at line 578 of file KoPencilTool.cpp.

579{
580 m_strokeColor = color;
581}

References m_strokeColor.

◆ slotUpdatePencilCursor

void KoPencilTool::slotUpdatePencilCursor ( )
protectedvirtualslot

Reimplemented in __KisToolPencilLocalTool.

Definition at line 187 of file KoPencilTool.cpp.

188{
189 KoShapeStrokeSP stroke = createStroke();
190 useCursor((stroke && stroke->isVisible()) ? Qt::ArrowCursor : Qt::ForbiddenCursor);
191}
void useCursor(const QCursor &cursor)

References createStroke(), and KoToolBase::useCursor().

Member Data Documentation

◆ m_close

bool KoPencilTool::m_close {false}
private

Definition at line 82 of file KoPencilTool.h.

82{false};

◆ m_combineAngle

qreal KoPencilTool::m_combineAngle {15.0}
private

Definition at line 80 of file KoPencilTool.h.

80{15.0};

◆ m_configGroup

KConfigGroup KoPencilTool::m_configGroup
private

Definition at line 93 of file KoPencilTool.h.

◆ m_existingEndPoint

KoPathPoint* KoPencilTool::m_existingEndPoint {0}
private

an existing path point we finished a new path at

Definition at line 89 of file KoPencilTool.h.

89{0};

◆ m_existingStartPoint

KoPathPoint* KoPencilTool::m_existingStartPoint {0}
private

an existing path point we started a new path at

Definition at line 88 of file KoPencilTool.h.

88{0};

◆ m_fittingError

qreal KoPencilTool::m_fittingError {5.0}
private

Definition at line 81 of file KoPencilTool.h.

81{5.0};

◆ m_hoveredPoint

KoPathPoint* KoPencilTool::m_hoveredPoint {0}
private

an existing path end point the mouse is hovering on

Definition at line 90 of file KoPencilTool.h.

90{0};

◆ m_mode

PencilMode KoPencilTool::m_mode {ModeCurve}
private

Definition at line 77 of file KoPencilTool.h.

77{ModeCurve};

◆ m_optimizeCurve

bool KoPencilTool::m_optimizeCurve {false}
private

Definition at line 79 of file KoPencilTool.h.

79{false};

◆ m_optimizeRaw

bool KoPencilTool::m_optimizeRaw {false}
private

Definition at line 78 of file KoPencilTool.h.

78{false};

◆ m_points

QList<QPointF> KoPencilTool::m_points
private

Definition at line 85 of file KoPencilTool.h.

◆ m_shape

KoPathShape* KoPencilTool::m_shape {0}
private

Definition at line 87 of file KoPencilTool.h.

87{0};

◆ m_strokeColor

QColor KoPencilTool::m_strokeColor
private

Definition at line 83 of file KoPencilTool.h.

◆ m_strokeWidget

KoStrokeConfigWidget* KoPencilTool::m_strokeWidget {0}
private

Definition at line 91 of file KoPencilTool.h.

91{0};

The documentation for this class was generated from the following files: