diff --git a/plugins/paintops/libpaintop/KisDabCacheUtils.cpp b/plugins/paintops/libpaintop/KisDabCacheUtils.cpp index 1d185b17e2..3479056e5a 100644 --- a/plugins/paintops/libpaintop/KisDabCacheUtils.cpp +++ b/plugins/paintops/libpaintop/KisDabCacheUtils.cpp @@ -1,118 +1,118 @@ /* * Copyright (c) 2017 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KisDabCacheUtils.h" #include "kis_brush.h" #include "kis_paint_device.h" #include "kis_fixed_paint_device.h" #include "kis_color_source.h" #include #include #include namespace KisDabCacheUtils { DabRenderingResources::DabRenderingResources() { } DabRenderingResources::~DabRenderingResources() { } void DabRenderingResources::syncResourcesToSeqNo(int seqNo, const KisPaintInformation &info) { brush->prepareForSeqNo(info, seqNo); } QRect correctDabRectWhenFetchedFromCache(const QRect &dabRect, const QSize &realDabSize) { int diffX = (realDabSize.width() - dabRect.width()) / 2; int diffY = (realDabSize.height() - dabRect.height()) / 2; return QRect(dabRect.x() - diffX, dabRect.y() - diffY, realDabSize.width() , realDabSize.height()); } void generateDab(const DabGenerationInfo &di, DabRenderingResources *resources, KisFixedPaintDeviceSP *dab) { KIS_SAFE_ASSERT_RECOVER_RETURN(*dab); const KoColorSpace *cs = (*dab)->colorSpace(); if (resources->brush->brushType() == IMAGE || resources->brush->brushType() == PIPE_IMAGE) { *dab = resources->brush->paintDevice(cs, di.shape, di.info, di.subPixel.x(), di.subPixel.y()); } else if (di.solidColorFill) { resources->brush->mask(*dab, di.paintColor, di.shape, di.info, di.subPixel.x(), di.subPixel.y(), di.softnessFactor); } else { if (!resources->colorSourceDevice || *cs != *resources->colorSourceDevice->colorSpace()) { resources->colorSourceDevice = new KisPaintDevice(cs); } else { resources->colorSourceDevice->clear(); } QRect maskRect(QPoint(), di.dstDabRect.size()); resources->colorSource->colorize(resources->colorSourceDevice, maskRect, di.info.pos().toPoint()); resources->colorSourceDevice->convertTo(cs); resources->brush->mask(*dab, resources->colorSourceDevice, di.shape, di.info, di.subPixel.x(), di.subPixel.y(), di.softnessFactor); } if (!di.mirrorProperties.isEmpty()) { (*dab)->mirror(di.mirrorProperties.horizontalMirror, di.mirrorProperties.verticalMirror); } } void postProcessDab(KisFixedPaintDeviceSP dab, const QPoint &dabTopLeft, const KisPaintInformation& info, DabRenderingResources *resources) { if (resources->sharpnessOption) { - resources->sharpnessOption->applyThreshold(dab); + resources->sharpnessOption->applyThreshold(dab, info); } if (resources->textureOption) { resources->textureOption->apply(dab, dabTopLeft, info); } } } diff --git a/plugins/paintops/libpaintop/kis_pressure_sharpness_option.cpp b/plugins/paintops/libpaintop/kis_pressure_sharpness_option.cpp index 8889e11a40..3bec56d711 100644 --- a/plugins/paintops/libpaintop/kis_pressure_sharpness_option.cpp +++ b/plugins/paintops/libpaintop/kis_pressure_sharpness_option.cpp @@ -1,109 +1,119 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_pressure_sharpness_option.h" #include #include #include #include #include #include KisPressureSharpnessOption::KisPressureSharpnessOption() : KisCurveOption("Sharpness", KisPaintOpOption::GENERAL, false) + , m_softness(0) { } void KisPressureSharpnessOption::writeOptionSetting(KisPropertiesConfigurationSP setting) const { KisCurveOption::writeOptionSetting(setting); - setting->setProperty(SHARPNESS_THRESHOLD, m_threshold); + setting->setProperty(SHARPNESS_SOFTNESS, m_softness); } void KisPressureSharpnessOption::readOptionSetting(const KisPropertiesConfigurationSP setting) { KisCurveOption::readOptionSetting(setting); - m_threshold = setting->getInt(SHARPNESS_THRESHOLD, 4); + m_softness = quint32(setting->getInt(SHARPNESS_SOFTNESS)); // backward compatibility: test for a "sharpness factor" property // and use this value if it does exist - if (setting->hasProperty(SHARPNESS_FACTOR) && !setting->hasProperty("SharpnessValue")) + if (setting->hasProperty(SHARPNESS_FACTOR) && !setting->hasProperty("SharpnessValue")) { KisCurveOption::setValue(setting->getDouble(SHARPNESS_FACTOR)); + m_softness = quint32(setting->getDouble(SHARPNESS_FACTOR) * 100); + } + } void KisPressureSharpnessOption::apply(const KisPaintInformation &info, const QPointF &pt, qint32 &x, qint32 &y, qreal &xFraction, qreal &yFraction) const { if (!isChecked() || KisCurveOption::value() == 0.0) { // brush KisPaintOp::splitCoordinate(pt.x(), &x, &xFraction); KisPaintOp::splitCoordinate(pt.y(), &y, &yFraction); } else { qreal processedSharpness = computeSizeLikeValue(info); if (processedSharpness == 1.0) { // pen xFraction = 0.0; yFraction = 0.0; x = qRound(pt.x()); y = qRound(pt.y()); } else { // something in between qint32 xi = qRound(pt.x()); qint32 yi = qRound(pt.y()); qreal xf = processedSharpness * xi + (1.0 - processedSharpness) * pt.x(); qreal yf = processedSharpness * yi + (1.0 - processedSharpness) * pt.y(); KisPaintOp::splitCoordinate(xf, &x, &xFraction); KisPaintOp::splitCoordinate(yf, &y, &yFraction); } } } -void KisPressureSharpnessOption::applyThreshold(KisFixedPaintDeviceSP dab) +void KisPressureSharpnessOption::applyThreshold(KisFixedPaintDeviceSP dab, const KisPaintInformation & info) { if (!isChecked()) return; const KoColorSpace * cs = dab->colorSpace(); // Set all alpha > opaque/2 to opaque, the rest to transparent. // XXX: Using 4/10 as the 1x1 circle brush paints nothing with 0.5. quint8* dabPointer = dab->data(); QRect rc = dab->bounds(); - int pixelSize = dab->pixelSize(); + qreal threshold = computeSizeLikeValue(info); + + quint32 pixelSize = dab->pixelSize(); int pixelCount = rc.width() * rc.height(); + quint32 tolerance = quint32(OPACITY_OPAQUE_U8 - (threshold * OPACITY_OPAQUE_U8)); + for (int i = 0; i < pixelCount; i++) { - quint8 alpha = cs->opacityU8(dabPointer); + quint8 opacity = cs->opacityU8(dabPointer); - if (alpha < (m_threshold * OPACITY_OPAQUE_U8) / 100) { - cs->setOpacity(dabPointer, OPACITY_TRANSPARENT_U8, 1); - } - else { + // Check what pixel goes sharp + if (opacity > (tolerance) ) { cs->setOpacity(dabPointer, OPACITY_OPAQUE_U8, 1); + } else { + // keep original value if in soft range + if (opacity <= (100 - m_softness) * tolerance / 100) { + cs->setOpacity(dabPointer, OPACITY_TRANSPARENT_U8, 1); + } } - dabPointer += pixelSize; } } diff --git a/plugins/paintops/libpaintop/kis_pressure_sharpness_option.h b/plugins/paintops/libpaintop/kis_pressure_sharpness_option.h index 7111f8d14c..9de0cc19da 100644 --- a/plugins/paintops/libpaintop/kis_pressure_sharpness_option.h +++ b/plugins/paintops/libpaintop/kis_pressure_sharpness_option.h @@ -1,72 +1,71 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KIS_PRESSURE_SHARPNESS_OPTION_H #define KIS_PRESSURE_SHARPNESS_OPTION_H #include "kis_curve_option.h" #include #include #include - const QString SHARPNESS_FACTOR = "Sharpness/factor"; -const QString SHARPNESS_THRESHOLD = "Sharpness/threshold"; +const QString SHARPNESS_SOFTNESS = "Sharpness/softness"; /** * This option is responsible to mimic pencil effect from former Pixel Pencil brush engine.auto */ class PAINTOP_EXPORT KisPressureSharpnessOption : public KisCurveOption { public: KisPressureSharpnessOption(); /** * First part of the sharpness is the coordinates: in pen mode they are integers without fractions */ void apply(const KisPaintInformation &info, const QPointF &pt, qint32 &x, qint32 &y, qreal &xFraction, qreal &yFraction) const; /** * Apply threshold specified by user */ - void applyThreshold(KisFixedPaintDeviceSP dab); + void applyThreshold(KisFixedPaintDeviceSP dab, const KisPaintInformation &info); void writeOptionSetting(KisPropertiesConfigurationSP setting) const override; void readOptionSetting(const KisPropertiesConfigurationSP setting) override; /// threshold has 100 levels (like opacity) void setThreshold(qint32 threshold) { - m_threshold = qBound(0, threshold, 100); + m_softness = qBound(0, quint32(threshold), 100); } qint32 threshold() { - return m_threshold; + return qint32(m_softness); } void setSharpnessFactor(qreal factor) { KisCurveOption::setValue(factor); } qreal sharpnessFactor() { return KisCurveOption::value(); } private: - qint32 m_threshold {40}; + quint32 m_softness {0}; }; #endif diff --git a/plugins/paintops/libpaintop/kis_pressure_sharpness_option_widget.cpp b/plugins/paintops/libpaintop/kis_pressure_sharpness_option_widget.cpp index 440513d00f..ce6f810ddc 100644 --- a/plugins/paintops/libpaintop/kis_pressure_sharpness_option_widget.cpp +++ b/plugins/paintops/libpaintop/kis_pressure_sharpness_option_widget.cpp @@ -1,68 +1,75 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include "kis_curve_option_widget.h" #include "kis_pressure_sharpness_option.h" #include "kis_pressure_sharpness_option_widget.h" KisPressureSharpnessOptionWidget::KisPressureSharpnessOptionWidget(): KisCurveOptionWidget(new KisPressureSharpnessOption(), i18n("0.0"), i18n("1.0")) { setObjectName("KisPressureSharpnessOptionWidget"); - QLabel* thresholdLbl = new QLabel(i18n("Threshold:")); - - m_threshold = new KisSliderSpinBox(); - m_threshold->setRange(1, 100); - m_threshold->setValue(40); - m_threshold->setSingleStep(1); + QLabel* thresholdLbl = new QLabel(i18n("Soften edge:")); + m_softenedge = new KisSliderSpinBox(); + m_softenedge->setRange(0, 100); + m_softenedge->setValue(0); // Sets old behaviour + m_softenedge->setSingleStep(1); QHBoxLayout* hl = new QHBoxLayout; + hl->setMargin(9); hl->addWidget(thresholdLbl); - hl->addWidget(m_threshold, 1); + hl->addWidget(m_softenedge, 1); QVBoxLayout* vl = new QVBoxLayout; vl->setMargin(0); vl->addLayout(hl); vl->addWidget(KisCurveOptionWidget::curveWidget()); QWidget* w = new QWidget; w->setLayout(vl); - KisCurveOptionWidget::setConfigurationPage(w); + connect(m_softenedge, SIGNAL(valueChanged(int)), SLOT(setThreshold(int))); + + setConfigurationPage(w); - connect(m_threshold, SIGNAL(valueChanged(int)), this, SLOT(setThreshold(int))); - setThreshold(m_threshold->value()); + setThreshold(m_softenedge->value()); +} + +void KisPressureSharpnessOptionWidget::readOptionSetting(const KisPropertiesConfigurationSP setting) +{ + KisCurveOptionWidget::readOptionSetting(setting); + m_softenedge->setValue(static_cast(curveOption())->threshold()); } void KisPressureSharpnessOptionWidget::setThreshold(int threshold) { - static_cast(KisCurveOptionWidget::curveOption())->setThreshold(threshold); + static_cast(curveOption())->setThreshold(threshold); emitSettingChanged(); } diff --git a/plugins/paintops/libpaintop/kis_pressure_sharpness_option_widget.h b/plugins/paintops/libpaintop/kis_pressure_sharpness_option_widget.h index 9230c7e83e..f6c368896d 100644 --- a/plugins/paintops/libpaintop/kis_pressure_sharpness_option_widget.h +++ b/plugins/paintops/libpaintop/kis_pressure_sharpness_option_widget.h @@ -1,42 +1,43 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KIS_PRESSURE_SHARPNESS_OPTION_WIDGET_H #define KIS_PRESSURE_SHARPNESS_OPTION_WIDGET_H #include "kis_curve_option_widget.h" class KisSliderSpinBox; - class PAINTOP_EXPORT KisPressureSharpnessOptionWidget : public KisCurveOptionWidget { Q_OBJECT public: KisPressureSharpnessOptionWidget(); + void readOptionSetting(const KisPropertiesConfigurationSP setting) override; + private Q_SLOTS: void setThreshold(int threshold); private: - KisSliderSpinBox* m_threshold; + KisSliderSpinBox* m_softenedge; }; #endif // KIS_PRESSURE_SHARPNESS_OPTION_WIDGET_H