14#include <klocalizedstring.h>
25#include <ksharedconfig.h>
70 , m_referencePaintDevice(nullptr)
71 , m_referenceNodeList(nullptr)
74 , m_dirtyRect(nullptr)
75 , m_fillStrokeId(nullptr)
77 setObjectName(
"tool_fill");
106 if (resourceProvider) {
121 if (resourceProvider) {
122 disconnect(resourceProvider,
139 i18n(
"You cannot use this tool with the selected layer type"),
154 (!
image()->wrapAroundModePermitted() &&
160 if (event->
modifiers() == Qt::ShiftModifier) {
166 }
else if (event->
modifiers() == Qt::AltModifier) {
191 const int dragDistanceSquared =
281 newReferenceNodeList,
282 referencePaintDevice,
283 newReferencePaintDevice,
294 referencePaintDevice = newReferencePaintDevice;
308 [referencePaintDevice, referenceColor, seedPoint]() ->
KUndo2Command*
310 *referenceColor = referencePaintDevice->
pixel(seedPoint);
322 *referenceColor = referencePaintDevice->
pixel(seedPoint);
338 m_transform.scale(normalizedScale, normalizedScale);
366 blendingOptionsAreNoOp &&
550 i18nc(
"The pattern 'scale' spinbox in fill tool options; {n} is the number value, % is the percent sign",
559 i18nc(
"{n} is the number value, % is the percent sign",
"Opacity: {n}%"));
570 m_sliderThreshold->setPrefix(i18nc(
"The 'threshold' spinbox prefix in fill tool options",
"Threshold: "));
576 i18nc(
"The 'spread' spinbox in fill tool options; {n} is the number value, % is the percent sign",
580 m_sliderCloseGap->setPrefix(i18nc(
"The 'close gap' spinbox prefix in fill tool options",
"Close Gap: "));
586 i18nc(
"The 'use selection as boundary' checkbox in fill tool to use selection borders as boundary when filling",
587 "Use selection as boundary")
591 m_checkBoxAntiAlias =
new QCheckBox(i18nc(
"The anti-alias checkbox in fill tool options",
"Anti-aliasing"));
595 m_sliderGrow->setPrefix(i18nc(
"The 'grow/shrink' spinbox prefix in fill tool options",
"Grow: "));
607 m_sliderFeather->setPrefix(i18nc(
"The 'feather' spinbox prefix in fill tool options",
"Feather: "));
637 QPushButton *buttonReset =
new QPushButton(i18nc(
"The 'reset' button in fill tool options",
"Reset"));
656 m_sliderThreshold->setToolTip(i18n(
"Set the color similarity tolerance of the fill. Increasing threshold increases the range of similar colors to be filled."));
657 m_sliderSpread->setToolTip(i18n(
"Set the extent of the opaque portion of the fill. Decreasing spread decreases opacity of fill areas depending on color similarity."));
658 m_sliderCloseGap->setToolTip(i18n(
"Close gaps in lines up to the set amount"));
659 m_checkBoxSelectionAsBoundary->setToolTip(i18n(
"Set if the contour of the active selection should be treated as a boundary when filling the region"));
662 m_sliderGrow->setToolTip(i18n(
"Grow or shrink the fill by the set amount"));
668 m_buttonReferenceLabeled->setToolTip(i18n(
"Fill regions found from the merging of layers with specific color labels"));
669 m_checkBoxUseActiveLayer->setToolTip(i18n(
"Includes the active layer in regions found from merging of layers with specific color labels"));
673 m_buttonDragFillSimilar->setToolTip(i18n(
"Dragging will fill only regions similar in color to the initial region (useful for filling line-art)"));
675 buttonReset->setToolTip(i18n(
"Reset the options to their default values"));
684 i18nc(
"The 'fill mode' section label in fill tool options",
"Fill mode")
691 i18nc(
"The 'fill source' section label in fill tool options",
"Fill source")
710 i18nc(
"The 'reference' section label in fill tool options",
"Reference")
713 sectionReference->
appendWidget(
"widgetLabels", widgetLabelsGroup);
719 i18nc(
"The 'fill extent' section label in fill tool options",
"Fill extent")
723 sectionRegionExtent->
setWidgetVisible(
"buttonContiguousFillBoundaryColor",
false);
732 i18nc(
"The 'adjustments' section label in fill tool options",
"Adjustments")
735 sectionAdjustments->
appendWidget(
"containerGrow", containerGrow);
741 i18nc(
"The 'drag-fill mode' section label in fill tool options",
"Drag-fill mode")
758 sectionRegionExtent->
setWidgetVisible(
"checkBoxSelectionAsBoundary",
false);
810 connect(optionButtonStripWhatToFill,
813 connect(optionButtonStripFillWith,
817 SIGNAL(valueChanged(
double)),
820 SIGNAL(angleChanged(
double)),
823 SIGNAL(toggled(
bool)),
826 SIGNAL(valueChanged(
int)),
829 SIGNAL(currentIndexChanged(
int)),
831 connect(optionButtonStripContiguousFillMode,
835 SIGNAL(changed(
const KoColor&)),
841 SIGNAL(toggled(
bool)),
846 SIGNAL(toggled(
bool)),
849 connect(optionButtonStripReference,
855 optionButtonStripDragFill,
866 const QString whatToFillStr =
m_configGroup.readEntry<QString>(
"whatToFill",
"");
867 if (whatToFillStr ==
"fillSelection") {
869 }
else if (whatToFillStr ==
"fillContiguousRegion") {
871 }
else if (whatToFillStr ==
"fillSimilarRegions") {
882 const QString fillTypeStr =
m_configGroup.readEntry<QString>(
"fillWith",
"");
883 if (fillTypeStr ==
"foregroundColor") {
885 }
else if (fillTypeStr ==
"backgroundColor") {
887 }
else if (fillTypeStr ==
"pattern") {
906 const QString contiguousFillModeStr =
m_configGroup.readEntry<QString>(
"contiguousFillMode",
"");
921 const QString sampleLayersModeStr =
m_configGroup.readEntry<QString>(
"sampleLayersMode",
"");
922 if (sampleLayersModeStr ==
"currentLayer") {
924 }
else if (sampleLayersModeStr ==
"allLayers") {
926 }
else if (sampleLayersModeStr ==
"colorLabeledLayers") {
937 const QStringList colorLabelsStr =
m_configGroup.readEntry<QString>(
"colorLabels",
"").split(
',', Qt::SkipEmptyParts);
939 for (
const QString &colorLabelStr : colorLabelsStr) {
941 const int colorLabel = colorLabelStr.toInt(&ok);
949 const QString continuousFillModeStr =
m_configGroup.readEntry<QString>(
"continuousFillMode",
"fillAnyRegion");
950 if (continuousFillModeStr ==
"doNotUse") {
952 }
else if (continuousFillModeStr ==
"fillSimilarRegions") {
962 const QString xmlColor =
m_configGroup.readEntry(
"contiguousFillBoundaryColor", QString());
964 if (doc.setContent(xmlColor)) {
965 QDomElement e = doc.documentElement().firstChild().toElement();
968 if (e.hasAttribute(
"space") || e.tagName().toLower() ==
"srgb") {
970 }
else if (doc.documentElement().hasAttribute(
"space") || doc.documentElement().tagName().toLower() ==
"srgb"){
998 ->setPrimaryWidgetVisible(
true);
1002 ->setWidgetVisible(
"sliderCloseGap",
true);
1004 ->setWidgetVisible(
"checkBoxSelectionAsBoundary",
true);
1006 m_configGroup.writeEntry(
"whatToFill",
"fillContiguousRegion");
1013 ->setPrimaryWidgetVisible(
false);
1015 ->setWidgetVisible(
"buttonContiguousFillBoundaryColor",
false);
1017 ->setWidgetVisible(
"sliderCloseGap",
false);
1019 ->setWidgetVisible(
"checkBoxSelectionAsBoundary",
false);
1021 m_configGroup.writeEntry(
"whatToFill",
"fillSimilarRegions");
1036 sectionFillWith->
setWidgetVisible(
"angleSelectorPatternRotation", visible);
1076 m_configGroup.writeEntry(
"useCustomBlendingOptions", checked);
1096 m_configGroup.writeEntry(
"customCompositeOp", compositeOpId);
1110 sectionRegionExtent->
setWidgetVisible(
"buttonContiguousFillBoundaryColor", visible);
1117 "contiguousFillMode",
1166 m_configGroup.writeEntry(
"useSelectionAsBoundary", checked);
1193 m_configGroup.writeEntry(
"stopGrowingAtDarkestPixel", enabled);
1236 if (labels.isEmpty()) {
1239 QString colorLabels = QString::number(labels.first());
1240 for (
int i = 1; i < labels.size(); ++i) {
1241 colorLabels +=
"," + QString::number(labels[i]);
1259 "continuousFillMode",
1264 :
"fillSimilarRegions"
float value(const T *src, size_t ch)
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
const qreal OPACITY_OPAQUE_F
const QString COMPOSITE_OVER
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void setOutDirtyRect(QSharedPointer< QRect > outDirtyRect)
void setSeedPoints(const QVector< QPoint > &seedPoints)
void setStopGrowingAtDarkestPixel(bool stopGrowingAtDarkestPixel)
void setUseFastMode(bool useFastMode)
void setUseCustomBlendingOptions(bool useCustomBlendingOptions)
void setFeather(int feather)
void setCustomCompositeOp(const QString &customCompositeOp)
void setProgressHelper(QSharedPointer< ProgressHelper > progressHelper)
void setOpacitySpread(int opacitySpread)
void setAntiAlias(bool antiAlias)
void setSelectionOnly(bool selectionOnly)
void setUseBgColor(bool useBgColor)
void setContinuousFillMask(KisSelectionSP continuousFillMask)
void setFillThreshold(int fillThreshold)
void setRegionFillingBoundaryColor(const KoColor ®ionFillingBoundaryColor)
void setSizeMod(int sizemod)
void setUsePattern(bool usePattern)
void setCustomOpacity(qreal customOpacity)
void setContinuousFillReferenceColor(const QSharedPointer< KoColor > continuousFillReferenceColor)
void setRegionFillingMode(KisFillPainter::RegionFillingMode regionFillingMode)
void setCloseGap(int gap)
void setContinuousFillMode(ContinuousFillMode continuousFillMode)
@ ContinuousFillMode_FillAnyRegion
@ ContinuousFillMode_FillSimilarRegions
void setUseSelectionAsBoundary(bool useSelectionAsBoundary)
@ IncreasingDirection_Clockwise
A widget with several options to select an angle.
@ FlipOptionsMode_ContextMenu
The flip options are shown only as a context menu when right-clicking the gauge widget.
void setFlipOptionsMode(FlipOptionsMode newMode)
Sets the mode in which the flip options should be shown.
void setIncreasingDirection(KisAngleGauge::IncreasingDirection newIncreasingDirection)
Sets the increasing direction in the angle gauge.
void setAngle(qreal newAngle)
Sets the current angle.
KisViewManager * viewManager() const
void validate(const KoColorSpace *cs)
KoID selectedCompositeOp() const
void selectCompositeOp(const KoID &op)
static QCursor load(const QString &cursorName, int hotspotX=-1, int hotspotY=-1)
This class is a spinbox in which you can click and drag to set the value. A slider like bar is displa...
void setValue(qreal newValue)
void setRange(qreal newMinimum, qreal newMaximum, int newNumberOfDecimals=0, bool computeNewFastSliderStep=true)
Set the minimum and the maximum values of the range.
void setSoftMaximum(qreal newSoftMaximum)
void setSizemod(int sizemod)
void setFillThreshold(int threshold)
void setFeather(int feather)
QVector< KisStrokeJobData * > createSimilarColorsSelectionJobs(KisPixelSelectionSP outSelection, const QSharedPointer< KoColor > referenceColor, KisPaintDeviceSP referenceDevice, const QRect &rect, KisPixelSelectionSP mask, QSharedPointer< KisProcessingVisitor::ProgressHelper > progressHelper=nullptr)
void setAntiAlias(bool antiAlias)
@ RegionFillingMode_BoundaryFill
@ RegionFillingMode_FloodFill
void setStopGrowingAtDarkestPixel(bool stopGrowingAtDarkestPixel)
void setOpacitySpread(int opacitySpread)
KisImageAnimationInterface * animationInterface() const
KisPaintDeviceSP projection() const
void addJob(KisStrokeId id, KisStrokeJobData *data) override
KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy) override
QRect bounds() const override
void endStroke(KisStrokeId id) override
static KisPaintDeviceSP createRefPaintDevice(KisImageSP originalImage, QString name="Merge Labeled Layers Reference Paint Device")
@ GroupSelectionPolicy_SelectIfColorLabeled
Groups will be taken into account only if they have set an explicit color label. This ignores groups ...
virtual const KoColorSpace * compositionSourceColorSpace() const
const KoColorSpace * colorSpace() const
bool pixel(qint32 x, qint32 y, QColor *c) const
The KisResourcesSnapshot class takes a snapshot of the various resources like colors and settings use...
QString compositeOpId() const
KisSelectionSP activeSelection() const
void setFillTransform(QTransform transform)
This class is a spinbox in which you can click and drag to set the value. A slider like bar is displa...
void setSoftRange(int newSoftMinimum, int newSoftMaximum)
Set the minimum and the maximum values of the soft range.
void setValue(int newValue)
void setRange(int newMinimum, int newMaximum, bool computeNewFastSliderStep=true)
Set the minimum and the maximum values of the range, computing a new "fast slider step" based on the ...
void setSupportsWrapAroundMode(bool value)
KisCanvasResourceProvider * canvasResourceProvider()
static KoColor fromXML(const QDomElement &elt, const QString &channelDepthId)
void toXML(QDomDocument &doc, QDomElement &colorElt) const
static const KoCompositeOpRegistry & instance()
KoID getKoID(const QString &compositeOpID) const
Qt::KeyboardModifiers modifiers() const
QPoint pos() const
return the position in widget coordinates
static bool qFuzzyCompare(half p1, half p2)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
QString button(const QWheelEvent &ev)
QSharedPointer< KUndo2Command > KUndo2CommandSP
KUndo2MagicString kundo2_i18n(const char *text)
QIcon loadIcon(const QString &name)
void setText(QSpinBox *spinBox, const QStringView textTemplate)
QVector< QPoint > rasterizePolylineDDA(const QVector< QPoint > &polylinePoints)
virtual KisPaintDeviceSP paintDevice() const =0
The LambdaCommand struct is a shorthand for creation of AggregateCommand commands using C++ lambda fe...
KisPixelSelectionSP pixelSelection