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

Classes

struct  ColorSamplerConfig
 
class  MoveShortcutsHelper
 

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)
 
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.
 

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

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

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

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

321 {
322 QList<KisShapeLayerSP> foundNodes;
324 if ((node->isEditable(true) && editableOnly) || !editableOnly) {
325
326 KisShapeLayerSP shapeLayer = dynamic_cast<KisShapeLayer*>(node.data());
327 if (shapeLayer && shapeLayer->isEditable() && shapeLayer->shapeManager()->shapeAt(point)) {
328 foundNodes.append(shapeLayer);
329 }
330 }
331 });
332 return foundNodes;
333 }

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

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

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

377 {
378 KisCanvas2 *canvas2 = dynamic_cast<KisCanvas2*>(canvas);
379 if (!canvas2) return false;
380
381 QList<KoShape*> currentShapes = canvas->shapeManager()->selection()->selectedShapes();
382 QList<KisShapeLayerSP> candidates = findShapeLayers(canvas2->image()->root(), point, true);
383 KisShapeLayerSP shapeLayer = candidates.isEmpty()? nullptr: candidates.last();
384
385 if (shapeLayer) {
386 KoShape *shape = shapeLayer->shapeManager()->shapeAt(point);
387 if (shape
388 && !(currentShapes.contains(shape) && skipCurrentShapes)
389 && (shapeType.isEmpty() || shapeType == shape->shapeId())) {
390 canvas2->viewManager()->nodeManager()->slotNonUiActivatedNode(shapeLayer);
391 canvas2->shapeManager()->selection()->deselectAll();
392 canvas2->shapeManager()->selection()->select(shape);
393 } else {
394 return false;
395 }
396 } else {
397 return false;
398 }
399
400 return true;
401 }
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:880
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 309 of file kis_tool_utils.cpp.

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

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

336 {
337 QPainterPath p;
338 KisCanvas2 *canvas2 = dynamic_cast<KisCanvas2*>(canvas);
339 if (!canvas2) return p;
340
341 QList<KoShape*> currentShapes = canvas->shapeManager()->selection()->selectedShapes();
342 QList<KisShapeLayerSP> candidates = findShapeLayers(canvas2->image()->root(), point, true);
343 KisShapeLayerSP shapeLayer = candidates.isEmpty()? nullptr: candidates.last();
344
345 if (shapeLayer) {
346 KoShape *shape = shapeLayer->shapeManager()->shapeAt(point);
347 if (shape && !(currentShapes.contains(shape) && skipCurrentShapes)) {
348 shapeType = shape->shapeId();
349 KoSvgTextShape *t = dynamic_cast<KoSvgTextShape *>(shape);
350 if (t) {
351 p.addRect(t->boundingRect());
352 if (isHorizontal) {
353 *isHorizontal = t->writingMode() == KoSvgText::HorizontalTB;
354 }
355 if (!t->shapesInside().isEmpty()) {
356 QPainterPath paths;
357 Q_FOREACH(KoShape *s, t->shapesInside()) {
358 KoPathShape *path = dynamic_cast<KoPathShape *>(s);
359 if (path) {
360 paths.addPath(path->absoluteTransformation().map(path->outline()));
361 }
362 }
363 if (!paths.isEmpty()) {
364 p = paths;
365 }
366 }
367 } else {
368 p = shape->absoluteTransformation().map(shape->outline());
369 }
370 }
371 }
372
373 return p;
374 }
const Params2D p
The position of a path point within a path shape.
Definition KoPathShape.h:63
virtual QPainterPath outline() const
Definition KoShape.cpp:559
QTransform absoluteTransformation() const
Definition KoShape.cpp:335
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().