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

Classes

struct  ColorSamplerConfig
 

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

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

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

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

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

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

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

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

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

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

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