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

Classes

struct  ColorSamplerConfig
 
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 194 of file kis_tool_utils.cpp.

195 {
196 KisNodeList masks;
197
198 Q_FOREACH (KisNodeSP node, nodes) {
199 if (node->inherits("KisMask")) {
200 masks.append(node);
201 }
202 }
203
204 // To prevent deleting same layer multiple times
206 nodes.append(masks);
207
208 if (nodes.isEmpty()) {
209 return false;
210 }
211
214
215 Q_FOREACH (KisNodeSP node, nodes) {
216 KisLayerUtils::recursiveApplyNodes(node, [&applicator, selection, masks] (KisNodeSP node) {
217
218 // applied on masks if selected explicitly
219 if (node->inherits("KisMask") && !masks.contains(node)) {
220 return;
221 }
222
223 if(node->hasEditablePaintDevice()) {
224 KUndo2Command *cmd =
225 new KisCommandUtils::LambdaCommand(kundo2_i18n("Clear"),
226 [node, selection] () {
227 KisPaintDeviceSP device = node->paintDevice();
228
229 std::unique_ptr<KisCommandUtils::CompositeCommand> parentCommand(
230 new KisCommandUtils::CompositeCommand());
231
232 KUndo2Command *autoKeyframeCommand = KisAutoKey::tryAutoCreateDuplicatedFrame(device);
233 if (autoKeyframeCommand) {
234 parentCommand->addCommand(autoKeyframeCommand);
235 }
236
237 KisTransaction transaction(kundo2_noi18n("internal-clear-command"), device);
238
239 QRect dirtyRect;
240 if (selection) {
241 dirtyRect = selection->selectedRect();
242 device->clearSelection(selection);
243 } else {
244 dirtyRect = device->extent();
245 device->clear();
246 }
247
248 device->setDirty(dirtyRect);
249 parentCommand->addCommand(transaction.endAndTake());
250
251 return parentCommand.release();
252 });
253 applicator.applyCommand(cmd, KisStrokeJobData::CONCURRENT);
254 }
255 });
256 }
257
258 applicator.end();
259
260 return true;
261 }
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 117 of file kis_tool_utils.cpp.

118 {
119 KisNodeSP foundNode = 0;
120 while (node) {
121 KisLayerSP layer = qobject_cast<KisLayer*>(node.data());
122
123 if (!layer || !layer->isEditable()) {
124 node = node->prevSibling();
125 continue;
126 }
127
128 KoColor color(layer->projection()->colorSpace());
129 layer->projection()->pixel(point.x(), point.y(), &color);
130
131 KisGroupLayerSP group = dynamic_cast<KisGroupLayer*>(layer.data());
132
133 if ((group && group->passThroughMode()) || color.opacityU8() != OPACITY_TRANSPARENT_U8) {
134 if (layer->inherits("KisGroupLayer") && (!editableOnly || layer->isEditable())) {
135 // if this is a group and the pixel is transparent, don't even enter it
136 foundNode = findNode(node->lastChild(), point, wholeGroup, editableOnly);
137 }
138 else {
139 foundNode = !wholeGroup ? node : node->parent();
140 }
141
142 }
143
144 if (foundNode) break;
145
146 node = node->prevSibling();
147 }
148
149 return foundNode;
150 }
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 152 of file kis_tool_utils.cpp.

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

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

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 414 of file kis_tool_utils.cpp.

415 {
416 QString message;
417 if (!node->isEditable(true) || blockedNoIndirectPainting) {
418 if (!node->visible() && node->userLocked()) {
419 message = i18n("Layer is locked and invisible.");
420 } else if (node->userLocked()) {
421 message = i18n("Layer is locked.");
422 } else if(!node->visible()) {
423 message = i18n("Layer is invisible.");
424 } else if (blockedNoIndirectPainting) {
425 message = i18n("Layer can be painted in Wash Mode only.");
426 } else {
427 message = i18n("Group not editable.");
428 }
429 }
430 return message;
431 }
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 41 of file kis_tool_utils.cpp.

43 {
44 KIS_ASSERT(dev);
45
46 // Bugfix hack forcing pure on first sample to avoid wrong
47 // format blendColor on newly initialized Krita.
48 static bool firstTime = true;
49 if (firstTime == true) {
50 pure = true;
51 firstTime = false;
52 }
53
54 const KoColorSpace *cs = dev->colorSpace();
55 KoColor sampledColor = KoColor::createTransparent(cs);
56
57 // Wrap around color sampling is supported on any paint device
58 bool oldSupportsWraparound = dev->supportsWraproundMode();
60
61 // Sampling radius.
62 if (!pure && radius > 1) {
63 QScopedPointer<KoMixColorsOp::Mixer> mixer(cs->mixColorsOp()->createMixer());
64
66 const int effectiveRadius = radius - 1;
67
68 const QRect sampleRect(pos.x() - effectiveRadius, pos.y() - effectiveRadius,
69 2 * effectiveRadius + 1, 2 * effectiveRadius + 1);
70 KisSequentialConstIterator it(dev, sampleRect);
71
72 const int radiusSq = pow2(effectiveRadius);
73
74 int nConseqPixels = it.nConseqPixels();
75 while (it.nextPixels(nConseqPixels)) {
76 const QPoint realPos(it.x(), it.y());
77 if (kisSquareDistance(realPos, pos) < radiusSq) {
78 mixer->accumulateAverage(it.oldRawData(), nConseqPixels);
79 }
80 }
81
82 mixer->computeMixedColor(sampledColor.data());
83
84 } else {
85 dev->pixel(pos.x(), pos.y(), &sampledColor);
86 }
87
88 dev->setSupportsWraparoundMode(oldSupportsWraparound);
89
90 // Color blending.
91 if (!pure && blendColor && blend < 100) {
92 //Scale from 0..100% to 0..255 range for mixOp weights.
93 quint8 blendScaled = static_cast<quint8>(blend * 2.55f);
94
95 const quint8 *colors[2];
96 colors[0] = blendColor->data();
97 colors[1] = sampledColor.data();
98 qint16 weights[2];
99 weights[0] = 255 - blendScaled;
100 weights[1] = blendScaled;
101
102 const KoMixColorsOp *mixOp = dev->colorSpace()->mixColorsOp();
103 mixOp->mixColors(colors, weights, 2, sampledColor.data());
104 }
105
106 sampledColor.convertTo(dev->compositionSourceColorSpace());
107
108 bool validColorSampled = sampledColor.opacityU8() != OPACITY_TRANSPARENT_U8;
109
110 if (validColorSampled) {
111 out_color = sampledColor;
112 }
113
114 return validColorSampled;
115 }
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 386 of file kis_tool_utils.cpp.

387 {
388 KisCanvas2 *canvas2 = dynamic_cast<KisCanvas2*>(canvas);
389 if (!canvas2) return false;
390
391 QList<KoShape*> currentShapes = canvas->shapeManager()->selection()->selectedShapes();
392 QList<KisShapeLayerSP> candidates = findShapeLayers(canvas2->image()->root(), point, true);
393 KisShapeLayerSP shapeLayer = candidates.isEmpty()? nullptr: candidates.last();
394
395 if (shapeLayer) {
396 KoShape *shape = shapeLayer->shapeManager()->shapeAt(point);
397 if (shape
398 && !(currentShapes.contains(shape) && skipCurrentShapes)
399 && (shapeType.isEmpty() || shapeType == shape->shapeId())) {
400 canvas2->viewManager()->nodeManager()->slotNonUiActivatedNode(shapeLayer);
401 canvas2->shapeManager()->selection()->deselectAll();
402 canvas2->shapeManager()->selection()->select(shape);
403 } else {
404 return false;
405 }
406 } else {
407 return false;
408 }
409
410 return true;
411 }
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 308 of file kis_tool_utils.cpp.

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

◆ 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 345 of file kis_tool_utils.cpp.

346 {
347 QPainterPath p;
348 KisCanvas2 *canvas2 = dynamic_cast<KisCanvas2*>(canvas);
349 if (!canvas2) return p;
350
351 QList<KoShape*> currentShapes = canvas->shapeManager()->selection()->selectedShapes();
352 QList<KisShapeLayerSP> candidates = findShapeLayers(canvas2->image()->root(), point, true);
353 KisShapeLayerSP shapeLayer = candidates.isEmpty()? nullptr: candidates.last();
354
355 if (shapeLayer) {
356 KoShape *shape = shapeLayer->shapeManager()->shapeAt(point);
357 if (shape && !(currentShapes.contains(shape) && skipCurrentShapes)) {
358 shapeType = shape->shapeId();
359 KoSvgTextShape *t = dynamic_cast<KoSvgTextShape *>(shape);
360 if (t) {
361 p.addRect(t->boundingRect());
362 if (isHorizontal) {
363 *isHorizontal = t->writingMode() == KoSvgText::HorizontalTB;
364 }
365 if (!t->shapesInside().isEmpty()) {
366 QPainterPath paths;
367 Q_FOREACH(KoShape *s, t->shapesInside()) {
368 KoPathShape *path = dynamic_cast<KoPathShape *>(s);
369 if (path) {
370 paths.addPath(path->absoluteTransformation().map(path->outline()));
371 }
372 }
373 if (!paths.isEmpty()) {
374 p = paths;
375 }
376 }
377 } else {
378 p = shape->absoluteTransformation().map(shape->outline());
379 }
380 }
381 }
382
383 return p;
384 }
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 318 of file kis_tool_utils.cpp.

319 {
320 KisCanvas2 *kisCanvas = dynamic_cast<KisCanvas2 *>(canvas);
322 kisCanvas->viewManager()->showFloatingMessage(i18n("Brush Size: %1 px", size),
323 QIcon(),
324 1000,
326 Qt::AlignLeft | Qt::TextWordWrap | Qt::AlignVCenter);
327 }
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().