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

Classes

struct  ColorSamplerConfig
 
class  StandardBrushSizes
 

Functions

void bakeDefaultPixel (KisPaintDeviceSP clip, const QRect &rc)
 
KisImageSP buildImageForClipboard (KisImageSP srcImage, KisNodeList nodes)
 
bool clearImage (KisImageSP image, KisNodeList nodes, KisSelectionSP selection)
 
void ensureClipVisible (const QRect &imageBounds, KisPaintDeviceSP clip)
 
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< KisShapeLayerSP > findShapeLayers (KisNodeSP root, const QPointF &point, bool editableOnly)
 
QString nodeEditableMessage (KisNodeSP node, bool blockedNoIndirectPainting=false)
 nodeEditableMessage
 
void recenterClip (KisPaintDeviceSP clip, const QPoint &newCenter)
 
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)
 
void trimDeviceForClipboard (KisImageSP image, KisPaintDeviceSP device, KisSelectionSP selection, bool makeSharpClip)
 

Function Documentation

◆ bakeDefaultPixel()

void KRITAUI_EXPORT KisToolUtils::bakeDefaultPixel ( KisPaintDeviceSP clip,
const QRect & rc )

If clip has non-transparent default pixel, it will be written into pixels explicitly in the area rc. After that, the default pixel will be reset to "transparent".

Definition at line 537 of file kis_tool_utils.cpp.

538 {
540 KisPaintDeviceSP copy = new KisPaintDevice(clip->colorSpace());
541 copy->makeCloneFromRough(clip, rc);
542 KisPainter::copyAreaOptimized(rc.topLeft(), copy, clip, rc);
544 }
545 }
const quint8 OPACITY_TRANSPARENT_U8
void setDefaultPixel(const KoColor &defPixel)
const KoColorSpace * colorSpace() const
KoColor defaultPixel() const
static void copyAreaOptimized(const QPoint &dstPt, KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &originalSrcRect)
static KoColor createTransparent(const KoColorSpace *cs)
Definition KoColor.cpp:682
quint8 opacityU8() const
Definition KoColor.cpp:341

References KisPaintDevice::colorSpace(), KisPainter::copyAreaOptimized(), KoColor::createTransparent(), KisPaintDevice::defaultPixel(), OPACITY_TRANSPARENT_U8, KoColor::opacityU8(), and KisPaintDevice::setDefaultPixel().

◆ buildImageForClipboard()

KisImageSP KRITAUI_EXPORT KisToolUtils::buildImageForClipboard ( KisImageSP srcImage,
KisNodeList nodes )

Creates an image that has the same resolution and size as srcImage, which can be used as a container image for uploading nodes into clipboard.

Definition at line 507 of file kis_tool_utils.cpp.

508 {
509 KisImageSP clipImage = new KisImage(0, srcImage->width(), srcImage->height(), srcImage->colorSpace(), "ClipImage");
510 clipImage->setResolution(srcImage->xRes(), srcImage->yRes());
511 Q_FOREACH (KisNodeSP node, nodes) {
512 clipImage->addNode(node, clipImage->root());
513 }
514
515 clipImage->refreshGraphAsync();
516 clipImage->waitForDone();
517
518 return clipImage;
519 }
void waitForDone()
void refreshGraphAsync(KisNodeSP root, const QVector< QRect > &rects, const QRect &cropRect, KisProjectionUpdateFlags flags=KisProjectionUpdateFlag::None) override
const KoColorSpace * colorSpace() const
qint32 width() const
double xRes() const
double yRes() const
qint32 height() const
void setResolution(double xres, double yres)
bool addNode(KisNodeSP node, KisNodeSP parent=KisNodeSP(), KisNodeAdditionFlags flags=KisNodeAdditionFlag::None)

References KisNodeFacade::addNode(), KisImage::colorSpace(), KisImage::height(), KisImage::refreshGraphAsync(), KisNodeFacade::root, KisImage::setResolution(), KisImage::waitForDone(), KisImage::width(), KisImage::xRes(), and KisImage::yRes().

◆ 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 std::unique_ptr<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.release();
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().

◆ ensureClipVisible()

void KRITAUI_EXPORT KisToolUtils::ensureClipVisible ( const QRect & imageBounds,
KisPaintDeviceSP clip )

Make sure non-default area of the clip device is visible within image bounds

The function uses nonDefaultPixelArea() instead of exactBounds(), because the clip may have non-transparent default pixel.

Definition at line 528 of file kis_tool_utils.cpp.

529 {
530 const QRect clipBounds = clip->nonDefaultPixelArea();
531 if (!imageBounds.intersects(clipBounds)) {
532 const QPoint diff = imageBounds.center() - clipBounds.center();
533 clip->moveTo(clip->offset() + diff);
534 }
535 }
QRect nonDefaultPixelArea() const
void moveTo(qint32 x, qint32 y)
QPoint offset() const

References KisPaintDevice::moveTo(), KisPaintDevice::nonDefaultPixelArea(), and KisPaintDevice::offset().

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

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

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

416 {
417 QString message;
418 if (!node->isEditable(true) || blockedNoIndirectPainting) {
419 if (!node->visible() && node->userLocked()) {
420 message = i18n("Layer is locked and invisible.");
421 } else if (node->userLocked()) {
422 message = i18n("Layer is locked.");
423 } else if(!node->visible()) {
424 message = i18n("Layer is invisible.");
425 } else if (blockedNoIndirectPainting) {
426 message = i18n("Layer can be painted in Wash Mode only.");
427 } else {
428 message = i18n("Group not editable.");
429 }
430 }
431 return message;
432 }
bool userLocked() const
virtual bool visible(bool recursive=false) const

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

◆ recenterClip()

void KRITAUI_EXPORT KisToolUtils::recenterClip ( KisPaintDeviceSP clip,
const QPoint & newCenter )

Moves the center of non-default area to the requested position

Definition at line 521 of file kis_tool_utils.cpp.

522 {
523 const QRect clipBounds = clip->nonDefaultPixelArea();
524 const QPoint diff = newCenter - clipBounds.center();
525 clip->moveTo(clip->offset() + diff);
526 }

References KisPaintDevice::moveTo(), KisPaintDevice::nonDefaultPixelArea(), and KisPaintDevice::offset().

◆ 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
quint8 * data()
Definition KoColor.h:144
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 387 of file kis_tool_utils.cpp.

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

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

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

◆ trimDeviceForClipboard()

void KRITAUI_EXPORT KisToolUtils::trimDeviceForClipboard ( KisImageSP image,
KisPaintDeviceSP device,
KisSelectionSP selection,
bool makeSharpClip = false )

Trims the device for uploading to the clipboard

  • if selection is present, then selection is baked into the device, the whole device is cropped by the selection and the default pixel is reset to "transparent
  • if selection is null, then device is just cropped by the image bounds

Sharp method is an exact reverse of COMPOSITE_OVER so if you cover the cut/copied piece over its source you get an exactly the same image without any seams

Definition at line 460 of file kis_tool_utils.cpp.

464 {
466
467 QRect rc = selection ? selection->selectedExactRect() : image->bounds();
468
469 const KoColorSpace *cs = device->colorSpace();
470
471 if (selection) {
472 // Apply selection mask.
473 KisPaintDeviceSP selectionProjection = selection->projection();
474 const KoColorSpace *selCs = selection->projection()->colorSpace();
475
476 KisSequentialIterator layerIt(device, rc);
477 KisSequentialConstIterator selectionIt(selectionProjection, rc);
478
479 while (layerIt.nextPixel() && selectionIt.nextPixel()) {
480
486 if (makeSharpClip) {
487 qreal dstAlpha = cs->opacityF(layerIt.rawData());
488 qreal sel = selCs->opacityF(selectionIt.oldRawData());
489 qreal newAlpha = sel * dstAlpha / (1.0 - dstAlpha + sel * dstAlpha);
490 float mask = newAlpha / dstAlpha;
491
492 cs->applyAlphaNormedFloatMask(layerIt.rawData(), &mask, 1);
493 } else {
494 cs->applyAlphaU8Mask(layerIt.rawData(), selectionIt.oldRawData(), 1);
495 }
496 }
497
498 // if we have a selection, then we should remove the rest of the image
499 // and make it fully transparent
501 device->purgeDefaultPixels();
502 }
503
504 device->crop(rc);
505 }
QRect bounds() const override
void crop(qint32 x, qint32 y, qint32 w, qint32 h)
virtual void applyAlphaU8Mask(quint8 *pixels, const quint8 *alpha, qint32 nPixels) const =0
virtual qreal opacityF(const quint8 *pixel) const =0
virtual void applyAlphaNormedFloatMask(quint8 *pixels, const float *alpha, qint32 nPixels) const =0
KisPixelSelectionSP projection() const
QRect selectedExactRect() const
Slow, but exact way of determining the rectangle that encloses the selection.

References KoColorSpace::applyAlphaNormedFloatMask(), KoColorSpace::applyAlphaU8Mask(), KisImage::bounds(), KisPaintDevice::colorSpace(), KoColor::createTransparent(), KisPaintDevice::crop(), KIS_SAFE_ASSERT_RECOVER_RETURN, KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixel(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::oldRawData(), KoColorSpace::opacityF(), KisSelection::projection(), KisPaintDevice::purgeDefaultPixels(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawData(), KisSelection::selectedExactRect(), and KisPaintDevice::setDefaultPixel().