Krita Source Code Documentation
Loading...
Searching...
No Matches
KisToolUtils Namespace Reference

Classes

struct  ColorSamplerConfig
 
class  MoveShortcutsHelper
 
class  StandardBrushSizes
 

Functions

bool clearImage (KisImageSP image, KisNodeList nodes, KisSelectionSP selection)
 
KisNodeSP findNode (KisNodeSP node, const QPoint &point, bool wholeGroup, bool editableOnly)
 
KisNodeList findNodes (KisNodeSP node, const QPoint &point, bool wholeGroup, bool includeGroups, bool editableOnly)
 
QList< KisShapeLayerSPfindShapeLayers (KisNodeSP root, const QPointF &point, bool editableOnly)
 
QString nodeEditableMessage (KisNodeSP node, bool blockedNoIndirectPainting=false)
 nodeEditableMessage
 
bool sampleColor (KoColor &out_color, KisPaintDeviceSP dev, const QPoint &pos, KoColor const *const blendColor, int radius, int blend, bool pure)
 
bool selectShapeCrossLayer (KoCanvasBase *canvas, const QPointF &point, const QString &shapeType=QString(), bool skipCurrentShapes=true)
 selectShapeCrossLayer Tries to select a shape under the cursor regardless of which layer it is on, to do so, it will always select the layer first and then the shape.
 
void KRITAUI_EXPORT setCursorPos (const QPoint &point)
 
QPainterPath shapeHoverInfoCrossLayer (KoCanvasBase *canvas, const QPointF &point, QString &shapeType, bool *isHorizontal=nullptr, bool skipCurrentShapes=true)
 shapeHoverInfoCrossLayer get hover info of shapes on all layers.
 
void KRITAUI_EXPORT showBrushSizeFloatingMessage (KoCanvasBase *canvas, qreal size)
 

Function Documentation

◆ clearImage()

bool KRITAUI_EXPORT KisToolUtils::clearImage ( KisImageSP image,
KisNodeList nodes,
KisSelectionSP selection )

return true if success Clears the image. Selection is optional, use 0 to clear everything.

Definition at line 196 of file kis_tool_utils.cpp.

197 {
198 KisNodeList masks;
199
200 Q_FOREACH (KisNodeSP node, nodes) {
201 if (node->inherits("KisMask")) {
202 masks.append(node);
203 }
204 }
205
206 // To prevent deleting same layer multiple times
208 nodes.append(masks);
209
210 if (nodes.isEmpty()) {
211 return false;
212 }
213
216
217 Q_FOREACH (KisNodeSP node, nodes) {
218 KisLayerUtils::recursiveApplyNodes(node, [&applicator, selection, masks] (KisNodeSP node) {
219
220 // applied on masks if selected explicitly
221 if (node->inherits("KisMask") && !masks.contains(node)) {
222 return;
223 }
224
225 if(node->hasEditablePaintDevice()) {
226 KUndo2Command *cmd =
227 new KisCommandUtils::LambdaCommand(kundo2_i18n("Clear"),
228 [node, selection] () {
229 KisPaintDeviceSP device = node->paintDevice();
230
231 QScopedPointer<KisCommandUtils::CompositeCommand> parentCommand(
232 new KisCommandUtils::CompositeCommand());
233
234 KUndo2Command *autoKeyframeCommand = KisAutoKey::tryAutoCreateDuplicatedFrame(device);
235 if (autoKeyframeCommand) {
236 parentCommand->addCommand(autoKeyframeCommand);
237 }
238
239 KisTransaction transaction(kundo2_noi18n("internal-clear-command"), device);
240
241 QRect dirtyRect;
242 if (selection) {
243 dirtyRect = selection->selectedRect();
244 device->clearSelection(selection);
245 } else {
246 dirtyRect = device->extent();
247 device->clear();
248 }
249
250 device->setDirty(dirtyRect);
251 parentCommand->addCommand(transaction.endAndTake());
252
253 return parentCommand.take();
254 });
255 applicator.applyCommand(cmd, KisStrokeJobData::CONCURRENT);
256 }
257 });
258 }
259
260 applicator.end();
261
262 return true;
263 }
QVector< KisImageSignalType > KisImageSignalVector
KUndo2MagicString kundo2_i18n(const char *text)
void recursiveApplyNodes(NodePointer node, Functor func)
void filterMergeableNodes(KisNodeList &nodes, bool allowMasks)
bool hasEditablePaintDevice() const

References KisProcessingApplicator::applyCommand(), KisStrokeJobData::CONCURRENT, KisLayerUtils::filterMergeableNodes(), KisBaseNode::hasEditablePaintDevice(), kundo2_i18n(), KisProcessingApplicator::NONE, and KisLayerUtils::recursiveApplyNodes().

◆ findNode()

KisNodeSP KRITAUI_EXPORT KisToolUtils::findNode ( KisNodeSP node,
const QPoint & point,
bool wholeGroup,
bool editableOnly = true )

Recursively search a node with a non-transparent pixel

Definition at line 119 of file kis_tool_utils.cpp.

120 {
121 KisNodeSP foundNode = 0;
122 while (node) {
123 KisLayerSP layer = qobject_cast<KisLayer*>(node.data());
124
125 if (!layer || !layer->isEditable()) {
126 node = node->prevSibling();
127 continue;
128 }
129
130 KoColor color(layer->projection()->colorSpace());
131 layer->projection()->pixel(point.x(), point.y(), &color);
132
133 KisGroupLayerSP group = dynamic_cast<KisGroupLayer*>(layer.data());
134
135 if ((group && group->passThroughMode()) || color.opacityU8() != OPACITY_TRANSPARENT_U8) {
136 if (layer->inherits("KisGroupLayer") && (!editableOnly || layer->isEditable())) {
137 // if this is a group and the pixel is transparent, don't even enter it
138 foundNode = findNode(node->lastChild(), point, wholeGroup, editableOnly);
139 }
140 else {
141 foundNode = !wholeGroup ? node : node->parent();
142 }
143
144 }
145
146 if (foundNode) break;
147
148 node = node->prevSibling();
149 }
150
151 return foundNode;
152 }
const quint8 OPACITY_TRANSPARENT_U8
const KoColorSpace * colorSpace() const
bool pixel(qint32 x, qint32 y, QColor *c) const
bool isEditable(bool checkVisibility=true) const
KisPaintDeviceSP projection() const override
Definition kis_layer.cc:826
KisNodeSP prevSibling() const
Definition kis_node.cpp:402
KisNodeWSP parent
Definition kis_node.cpp:86
KisNodeSP lastChild() const
Definition kis_node.cpp:367

References KisPaintDevice::colorSpace(), KisSharedPtr< T >::data(), findNode(), KisBaseNode::isEditable(), KisNode::lastChild(), OPACITY_TRANSPARENT_U8, KoColor::opacityU8(), KisNode::parent, KisGroupLayer::passThroughMode, KisPaintDevice::pixel(), KisNode::prevSibling(), and KisLayer::projection().

◆ findNodes()

KisNodeList KRITAUI_EXPORT KisToolUtils::findNodes ( KisNodeSP node,
const QPoint & point,
bool wholeGroup,
bool includeGroups,
bool editableOnly )

Definition at line 154 of file kis_tool_utils.cpp.

155 {
156 KisNodeList foundNodes;
157 while (node) {
158 KisLayerSP layer = qobject_cast<KisLayer*>(node.data());
159
160 if (!layer || !layer->isEditable()) {
161 node = node->nextSibling();
162 continue;
163 }
164
165 KoColor color(layer->projection()->colorSpace());
166 layer->projection()->pixel(point.x(), point.y(), &color);
167 const bool isTransparent = color.opacityU8() == OPACITY_TRANSPARENT_U8;
168
169 KisGroupLayerSP group = dynamic_cast<KisGroupLayer*>(layer.data());
170
171 if (group) {
172 if (!isTransparent || group->passThroughMode()) {
173 foundNodes << findNodes(node->firstChild(), point, wholeGroup, includeGroups, editableOnly);
174 if (includeGroups) {
175 foundNodes << node;
176 }
177 }
178 } else {
179 if (!isTransparent) {
180 if (wholeGroup) {
181 if (!foundNodes.contains(node->parent())) {
182 foundNodes << node->parent();
183 }
184 } else {
185 foundNodes << node;
186 }
187 }
188 }
189
190 node = node->nextSibling();
191 }
192
193 return foundNodes;
194 }
KisNodeSP firstChild() const
Definition kis_node.cpp:361
KisNodeSP nextSibling() const
Definition kis_node.cpp:408

References KisPaintDevice::colorSpace(), KisSharedPtr< T >::data(), findNodes(), KisNode::firstChild(), KisBaseNode::isEditable(), KisNode::nextSibling(), OPACITY_TRANSPARENT_U8, KoColor::opacityU8(), KisNode::parent, KisGroupLayer::passThroughMode, KisPaintDevice::pixel(), and KisLayer::projection().

◆ findShapeLayers()

QList< KisShapeLayerSP > KisToolUtils::findShapeLayers ( KisNodeSP root,
const QPointF & point,
bool editableOnly )

Definition at line 333 of file kis_tool_utils.cpp.

333 {
334 QList<KisShapeLayerSP> foundNodes;
336 if ((node->isEditable(true) && editableOnly) || !editableOnly) {
337
338 KisShapeLayerSP shapeLayer = dynamic_cast<KisShapeLayer*>(node.data());
339 if (shapeLayer && shapeLayer->isEditable() && shapeLayer->shapeManager()->shapeAt(point)) {
340 foundNodes.append(shapeLayer);
341 }
342 }
343 });
344 return foundNodes;
345 }

References KisBaseNode::isEditable(), and KisLayerUtils::recursiveApplyNodes().

◆ nodeEditableMessage()

QString KRITAUI_EXPORT KisToolUtils::nodeEditableMessage ( KisNodeSP node,
bool blockedNoIndirectPainting = false )

nodeEditableMessage

Parameters
node– active node.
blockedNoIndirectPainting– whether editing is blocked due no-indirect painting being possible.
Returns
the message for why the node is not editable. Will return empty if it is editable after all.

Definition at line 451 of file kis_tool_utils.cpp.

452 {
453 QString message;
454 if (!node->isEditable(true) || blockedNoIndirectPainting) {
455 if (!node->visible() && node->userLocked()) {
456 message = i18n("Layer is locked and invisible.");
457 } else if (node->userLocked()) {
458 message = i18n("Layer is locked.");
459 } else if(!node->visible()) {
460 message = i18n("Layer is invisible.");
461 } else if (blockedNoIndirectPainting) {
462 message = i18n("Layer can be painted in Wash Mode only.");
463 } else {
464 message = i18n("Group not editable.");
465 }
466 }
467 return message;
468 }
bool userLocked() const
virtual bool visible(bool recursive=false) const

References KisBaseNode::isEditable(), KisBaseNode::userLocked(), and KisBaseNode::visible().

◆ sampleColor()

bool KRITAUI_EXPORT KisToolUtils::sampleColor ( KoColor & out_color,
KisPaintDeviceSP dev,
const QPoint & pos,
KoColor const *const blendColor = nullptr,
int radius = 1,
int blend = 100,
bool pure = false )

Sample a color based on the given position on the given paint device.

out_color - Output parameter returning newly sampled color. dev - Paint device to sample from. pos - Position to sample from. blendColor - Optional color to be blended with. radius - Sampling area radius in pixels. blend - Blend percentage. 100% all sampled, 0% all blendColor. pure - Whether to bypass radius, blending, and active layer settings for pure sampling.

RETURN - Returns TRUE whenever a valid color is sampled.

Definition at line 43 of file kis_tool_utils.cpp.

45 {
46 KIS_ASSERT(dev);
47
48 // Bugfix hack forcing pure on first sample to avoid wrong
49 // format blendColor on newly initialized Krita.
50 static bool firstTime = true;
51 if (firstTime == true) {
52 pure = true;
53 firstTime = false;
54 }
55
56 const KoColorSpace *cs = dev->colorSpace();
57 KoColor sampledColor = KoColor::createTransparent(cs);
58
59 // Wrap around color sampling is supported on any paint device
60 bool oldSupportsWraparound = dev->supportsWraproundMode();
62
63 // Sampling radius.
64 if (!pure && radius > 1) {
65 QScopedPointer<KoMixColorsOp::Mixer> mixer(cs->mixColorsOp()->createMixer());
66
68 const int effectiveRadius = radius - 1;
69
70 const QRect sampleRect(pos.x() - effectiveRadius, pos.y() - effectiveRadius,
71 2 * effectiveRadius + 1, 2 * effectiveRadius + 1);
72 KisSequentialConstIterator it(dev, sampleRect);
73
74 const int radiusSq = pow2(effectiveRadius);
75
76 int nConseqPixels = it.nConseqPixels();
77 while (it.nextPixels(nConseqPixels)) {
78 const QPoint realPos(it.x(), it.y());
79 if (kisSquareDistance(realPos, pos) < radiusSq) {
80 mixer->accumulateAverage(it.oldRawData(), nConseqPixels);
81 }
82 }
83
84 mixer->computeMixedColor(sampledColor.data());
85
86 } else {
87 dev->pixel(pos.x(), pos.y(), &sampledColor);
88 }
89
90 dev->setSupportsWraparoundMode(oldSupportsWraparound);
91
92 // Color blending.
93 if (!pure && blendColor && blend < 100) {
94 //Scale from 0..100% to 0..255 range for mixOp weights.
95 quint8 blendScaled = static_cast<quint8>(blend * 2.55f);
96
97 const quint8 *colors[2];
98 colors[0] = blendColor->data();
99 colors[1] = sampledColor.data();
100 qint16 weights[2];
101 weights[0] = 255 - blendScaled;
102 weights[1] = blendScaled;
103
104 const KoMixColorsOp *mixOp = dev->colorSpace()->mixColorsOp();
105 mixOp->mixColors(colors, weights, 2, sampledColor.data());
106 }
107
108 sampledColor.convertTo(dev->compositionSourceColorSpace());
109
110 bool validColorSampled = sampledColor.opacityU8() != OPACITY_TRANSPARENT_U8;
111
112 if (validColorSampled) {
113 out_color = sampledColor;
114 }
115
116 return validColorSampled;
117 }
bool supportsWraproundMode() const
virtual const KoColorSpace * compositionSourceColorSpace() const
void setSupportsWraparoundMode(bool value)
KoMixColorsOp * mixColorsOp
void convertTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
Definition KoColor.cpp:136
static KoColor createTransparent(const KoColorSpace *cs)
Definition KoColor.cpp:682
quint8 * data()
Definition KoColor.h:144
quint8 opacityU8() const
Definition KoColor.cpp:341
virtual Mixer * createMixer() const =0
virtual void mixColors(const quint8 *const *colors, const qint16 *weights, int nColors, quint8 *dst, int weightSum=255) const =0
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
T pow2(const T &x)
Definition kis_global.h:166
qreal kisSquareDistance(const QPointF &pt1, const QPointF &pt2)
Definition kis_global.h:194
T blend(T src, T srcAlpha, T dst, T dstAlpha, T cfValue)

References KisPaintDevice::colorSpace(), KisPaintDevice::compositionSourceColorSpace(), KoColor::convertTo(), KoMixColorsOp::createMixer(), KoColor::createTransparent(), KoColor::data(), KIS_ASSERT, kisSquareDistance(), KoMixColorsOp::mixColors(), KoColorSpace::mixColorsOp, KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nConseqPixels(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixels(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::oldRawData(), OPACITY_TRANSPARENT_U8, KoColor::opacityU8(), KisPaintDevice::pixel(), pow2(), KisPaintDevice::setSupportsWraparoundMode(), KisPaintDevice::supportsWraproundMode(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::x(), and KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::y().

◆ selectShapeCrossLayer()

bool KRITAUI_EXPORT KisToolUtils::selectShapeCrossLayer ( KoCanvasBase * canvas,
const QPointF & point,
const QString & shapeType = QString(),
bool skipCurrentShapes = true )

selectShapeCrossLayer Tries to select a shape under the cursor regardless of which layer it is on, to do so, it will always select the layer first and then the shape.

Parameters
canvas– the current canvas.
point– the point in document coordinates.
shapeType– the required shapeId, if empty, selects any koshape.
Returns
whether a shape was successfully selected.

Definition at line 388 of file kis_tool_utils.cpp.

389 {
390 KisCanvas2 *canvas2 = dynamic_cast<KisCanvas2*>(canvas);
391 if (!canvas2) return false;
392
393 QList<KoShape*> currentShapes = canvas->shapeManager()->selection()->selectedShapes();
394 QList<KisShapeLayerSP> candidates = findShapeLayers(canvas2->image()->root(), point, true);
395 KisShapeLayerSP shapeLayer = candidates.isEmpty()? nullptr: candidates.last();
396
397 if (shapeLayer) {
398 KoShape *shape = shapeLayer->shapeManager()->shapeAt(point);
399 if (shape
400 && !(currentShapes.contains(shape) && skipCurrentShapes)
401 && (shapeType.isEmpty() || shapeType == shape->shapeId())) {
402 canvas2->viewManager()->nodeManager()->slotNonUiActivatedNode(shapeLayer);
403 canvas2->shapeManager()->selection()->deselectAll();
404 canvas2->shapeManager()->selection()->select(shape);
405 } else {
406 return false;
407 }
408 } else {
409 return false;
410 }
411
412 return true;
413 }
KisImageWSP image() const
KoShapeManager shapeManager
KisViewManager * viewManager() const
void slotNonUiActivatedNode(KisNodeSP node)
KoShapeManager * shapeManager() const
KisNodeManager * nodeManager() const
The node manager handles everything about nodes.
virtual KoShapeManager * shapeManager() const =0
void deselectAll()
clear the selections list
void select(KoShape *shape)
const QList< KoShape * > selectedShapes() const
KoShape * shapeAt(const QPointF &position, KoFlake::ShapeSelection selection=KoFlake::ShapeOnTop, bool omitHiddenShapes=true)
KoSelection * selection
QString shapeId() const
Definition KoShape.cpp:875
QList< KisShapeLayerSP > findShapeLayers(KisNodeSP root, const QPointF &point, bool editableOnly)

References KoSelection::deselectAll(), findShapeLayers(), KisCanvas2::image(), KisViewManager::nodeManager(), KisNodeFacade::root, KoSelection::select(), KoSelection::selectedShapes(), KoShapeManager::selection, KoShapeManager::shapeAt(), KoShape::shapeId(), KisShapeLayer::shapeManager(), KoCanvasBase::shapeManager(), KisCanvas2::shapeManager, KisNodeManager::slotNonUiActivatedNode(), and KisCanvas2::viewManager().

◆ setCursorPos()

void KRITAUI_EXPORT KisToolUtils::setCursorPos ( const QPoint & point)

Moves the cursor (hot spot) of the primary screen to the global screen position (x, y).

This function is provided as a replacement to QCursor::setPos which does not properly handle multiple monitors with different scale factors.

Definition at line 310 of file kis_tool_utils.cpp.

311 {
312 // https://bugreports.qt.io/browse/QTBUG-99009
313 QScreen *screen = qApp->screenAt(point);
314 if (!screen) {
315 screen = qApp->primaryScreen();
316 }
317 QCursor::setPos(screen, point);
318 }

◆ shapeHoverInfoCrossLayer()

QPainterPath KRITAUI_EXPORT KisToolUtils::shapeHoverInfoCrossLayer ( KoCanvasBase * canvas,
const QPointF & point,
QString & shapeType,
bool * isHorizontal = nullptr,
bool skipCurrentShapes = true )

shapeHoverInfoCrossLayer get hover info of shapes on all layers.

Parameters
canvas– current canvas.
point– the point in document coordinates.
shapeType– the shapeID of the found shape.
isHorizontal– when this is a textShape, sets whether the writing mode is horizontal.
Returns

Definition at line 347 of file kis_tool_utils.cpp.

348 {
349 QPainterPath p;
350 KisCanvas2 *canvas2 = dynamic_cast<KisCanvas2*>(canvas);
351 if (!canvas2) return p;
352
353 QList<KoShape*> currentShapes = canvas->shapeManager()->selection()->selectedShapes();
354 QList<KisShapeLayerSP> candidates = findShapeLayers(canvas2->image()->root(), point, true);
355 KisShapeLayerSP shapeLayer = candidates.isEmpty()? nullptr: candidates.last();
356
357 if (shapeLayer) {
358 KoShape *shape = shapeLayer->shapeManager()->shapeAt(point);
359 if (shape && !(currentShapes.contains(shape) && skipCurrentShapes)) {
360 shapeType = shape->shapeId();
361 KoSvgTextShape *t = dynamic_cast<KoSvgTextShape *>(shape);
362 if (t) {
363 p.addRect(t->boundingRect());
364 if (isHorizontal) {
365 *isHorizontal = t->writingMode() == KoSvgText::HorizontalTB;
366 }
367 if (!t->shapesInside().isEmpty()) {
368 QPainterPath paths;
369 Q_FOREACH(KoShape *s, t->shapesInside()) {
370 KoPathShape *path = dynamic_cast<KoPathShape *>(s);
371 if (path) {
372 paths.addPath(path->absoluteTransformation().map(path->outline()));
373 }
374 }
375 if (!paths.isEmpty()) {
376 p = paths;
377 }
378 }
379 } else {
380 p = shape->absoluteTransformation().map(shape->outline());
381 }
382 }
383 }
384
385 return p;
386 }
const Params2D p
The position of a path point within a path shape.
Definition KoPathShape.h:63
virtual QPainterPath outline() const
Definition KoShape.cpp:554
QTransform absoluteTransformation() const
Definition KoShape.cpp:330
QRectF boundingRect() const override
Get the bounding box of the shape.
QList< KoShape * > shapesInside
KoSvgText::WritingMode writingMode() const
writingMode There's a number of places we need to check the writing mode to provide proper controls.
@ HorizontalTB
Definition KoSvgText.h:38

References KoShape::absoluteTransformation(), KoSvgTextShape::boundingRect(), findShapeLayers(), KoSvgText::HorizontalTB, KisCanvas2::image(), KoShape::outline(), p, KisNodeFacade::root, KoSelection::selectedShapes(), KoShapeManager::selection, KoShapeManager::shapeAt(), KoShape::shapeId(), KisShapeLayer::shapeManager(), KoCanvasBase::shapeManager(), KoSvgTextShape::shapesInside, and KoSvgTextShape::writingMode().

◆ showBrushSizeFloatingMessage()

void KRITAUI_EXPORT KisToolUtils::showBrushSizeFloatingMessage ( KoCanvasBase * canvas,
qreal size )

Definition at line 320 of file kis_tool_utils.cpp.

321 {
322 KisCanvas2 *kisCanvas = dynamic_cast<KisCanvas2 *>(canvas);
324 kisCanvas->viewManager()->showFloatingMessage(i18n("Brush Size: %1 px", size),
325 QIcon(),
326 1000,
328 Qt::AlignLeft | Qt::TextWordWrap | Qt::AlignVCenter);
329 }
void showFloatingMessage(const QString &message, const QIcon &icon, int timeout=4500, KisFloatingMessage::Priority priority=KisFloatingMessage::Medium, int alignment=Qt::AlignCenter|Qt::TextWordWrap)
shows a floating message in the top right corner of the canvas
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References KisFloatingMessage::High, KIS_SAFE_ASSERT_RECOVER_RETURN, KisViewManager::showFloatingMessage(), and KisCanvas2::viewManager().