diff --git a/plugins/generators/CMakeLists.txt b/plugins/generators/CMakeLists.txt index 1a560d4b66..8893ded464 100644 --- a/plugins/generators/CMakeLists.txt +++ b/plugins/generators/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(solid) add_subdirectory(pattern) add_subdirectory(simplexnoise) +add_subdirectory(screentone) diff --git a/plugins/generators/screentone/CMakeLists.txt b/plugins/generators/screentone/CMakeLists.txt new file mode 100644 index 0000000000..7674e3fcdd --- /dev/null +++ b/plugins/generators/screentone/CMakeLists.txt @@ -0,0 +1,13 @@ +set(kritascreentonegenerator_SOURCES + screentonegenerator.cpp + kis_wdg_screentone.cpp + screentonefunctions.cpp + brightnesscontrastfunctions.cpp + ) +ki18n_wrap_ui(kritascreentonegenerator_SOURCES + wdgscreentoneoptions.ui + ) + +add_library(kritascreentonegenerator MODULE ${kritascreentonegenerator_SOURCES}) +target_link_libraries(kritascreentonegenerator kritaui) +install(TARGETS kritascreentonegenerator DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) diff --git a/plugins/generators/screentone/brightnesscontrastfunctions.cpp b/plugins/generators/screentone/brightnesscontrastfunctions.cpp new file mode 100644 index 0000000000..65ee2d4bb0 --- /dev/null +++ b/plugins/generators/screentone/brightnesscontrastfunctions.cpp @@ -0,0 +1,42 @@ +/* + * KDE. Krita Project. + * + * Copyright (c) 2020 Deif Lou + * + * 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 "brightnesscontrastfunctions.h" + +DefaultBrightnessContrastFunction::DefaultBrightnessContrastFunction(qreal brightness, qreal contrast) +{ + if (contrast > 0.0) { + if (qFuzzyCompare(contrast, 1.0)) { + m_m = 10000.0; + } else { + m_m = 1.0 / (1.0 - contrast); + } + m_b = -m_m * (contrast / 2.0); + } else { + m_m = 1.0 + contrast; + m_b = -contrast / 2.0; + } + m_b += (1.0 - m_b) * brightness; +} + +qreal DefaultBrightnessContrastFunction::operator()(qreal x) const +{ + return m_m * x + m_b; +} diff --git a/plugins/generators/screentone/brightnesscontrastfunctions.h b/plugins/generators/screentone/brightnesscontrastfunctions.h new file mode 100644 index 0000000000..ae0eaf16b3 --- /dev/null +++ b/plugins/generators/screentone/brightnesscontrastfunctions.h @@ -0,0 +1,45 @@ +/* + * KDE. Krita Project. + * + * Copyright (c) 2020 Deif Lou + * + * 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. + */ + +#ifndef BRIGHTNESCONTRASTFUNCTIONS_H +#define BRIGHTNESCONTRASTFUNCTIONS_H + +#include + +class IdentityBrightnessContrastFunction +{ +public: + inline qreal operator()(qreal x) const + { + return x; + } +}; + +class DefaultBrightnessContrastFunction +{ +public: + // brightness and contrast expected to be in the range [-1, 1] + DefaultBrightnessContrastFunction(qreal brightness, qreal contrast); + qreal operator()(qreal x) const; +private: + qreal m_m, m_b; +}; + +#endif diff --git a/plugins/generators/screentone/kis_wdg_screentone.cpp b/plugins/generators/screentone/kis_wdg_screentone.cpp new file mode 100644 index 0000000000..3a5e87f6c7 --- /dev/null +++ b/plugins/generators/screentone/kis_wdg_screentone.cpp @@ -0,0 +1,256 @@ +/* + * KDE. Krita Project. + * + * Copyright (c) 2020 Deif Lou + * + * 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 "kis_wdg_screentone.h" +#include "screentonefunctions.h" +#include "screentoneconfigdefaults.h" + +#include +#include +#include + +KisWdgScreentone::KisWdgScreentone(QWidget* parent, const KoColorSpace *cs) + : KisConfigWidget(parent) + , m_colorSpace(cs) +{ + m_widget.setupUi(this); + + setupPatternComboBox(); + setupShapeComboBox(); + setupInterpolationComboBox(); + + m_widget.sliderForegroundOpacity->setRange(0, 100); + m_widget.sliderForegroundOpacity->setPrefix(i18n("Opacity: ")); + m_widget.sliderForegroundOpacity->setSuffix(i18n("%")); + m_widget.sliderBackgroundOpacity->setRange(0, 100); + m_widget.sliderBackgroundOpacity->setPrefix(i18n("Opacity: ")); + m_widget.sliderBackgroundOpacity->setSuffix(i18n("%")); + m_widget.sliderBrightness->setRange(0.0, 100.0, 2); + m_widget.sliderBrightness->setSingleStep(1.0); + m_widget.sliderBrightness->setSuffix(i18n("%")); + m_widget.sliderContrast->setRange(0.0, 100.0, 2); + m_widget.sliderContrast->setSingleStep(1.0); + m_widget.sliderContrast->setSuffix(i18n("%")); + + m_widget.sliderPositionX->setRange(-1000-0, 1000.0, 2); + m_widget.sliderPositionX->setPrefix(i18n("X: ")); + m_widget.sliderPositionX->setSuffix(i18n(" px")); + m_widget.sliderPositionX->setSingleStep(1.0); + m_widget.sliderPositionY->setRange(-1000.0, 1000.0, 2); + m_widget.sliderPositionY->setPrefix(i18n("Y: ")); + m_widget.sliderPositionY->setSuffix(i18n(" px")); + m_widget.sliderPositionY->setSingleStep(1.0); + m_widget.sliderSizeX->setRange(1.0, 1000.0, 2); + m_widget.sliderSizeX->setPrefix(i18n("X: ")); + m_widget.sliderSizeX->setSuffix(i18n(" px")); + m_widget.sliderSizeX->setSingleStep(1.0); + m_widget.sliderSizeX->setExponentRatio(4.32); + m_widget.sliderSizeY->setRange(1.0, 1000.0, 2); + m_widget.sliderSizeY->setPrefix(i18n("Y: ")); + m_widget.sliderSizeY->setSuffix(i18n(" px")); + m_widget.sliderSizeY->setSingleStep(1.0); + m_widget.sliderSizeY->setExponentRatio(4.32); + m_widget.sliderShearX->setRange(-10.0, 10.0, 2); + m_widget.sliderShearX->setPrefix(i18n("X: ")); + m_widget.sliderShearX->setSingleStep(0.1); + m_widget.sliderShearY->setRange(-10.0, 10.0, 2); + m_widget.sliderShearY->setPrefix(i18n("Y: ")); + m_widget.sliderShearY->setSingleStep(0.1); + m_widget.sliderRotation->setRange(0.0, 360.0, 2); + m_widget.sliderRotation->setSuffix(i18n("˚")); + m_widget.sliderRotation->setSingleStep(1.0); + + connect(m_widget.comboBoxPattern, SIGNAL(currentIndexChanged(int)), this, SLOT(slot_comboBoxPattern_currentIndexChanged(int))); + connect(m_widget.comboBoxShape, SIGNAL(currentIndexChanged(int)), this, SLOT(slot_comboBoxShape_currentIndexChanged(int))); + connect(m_widget.comboBoxInterpolation, SIGNAL(currentIndexChanged(int)), this, SIGNAL(sigConfigurationUpdated())); + connect(m_widget.buttonForegroundColor, SIGNAL(changed(const KoColor&)), this, SIGNAL(sigConfigurationUpdated())); + connect(m_widget.sliderForegroundOpacity, SIGNAL(valueChanged(int)), this, SIGNAL(sigConfigurationUpdated())); + connect(m_widget.buttonBackgroundColor, SIGNAL(changed(const KoColor&)), this, SIGNAL(sigConfigurationUpdated())); + connect(m_widget.sliderBackgroundOpacity, SIGNAL(valueChanged(int)), this, SIGNAL(sigConfigurationUpdated())); + connect(m_widget.checkBoxInvert, SIGNAL(toggled(bool)), this, SIGNAL(sigConfigurationUpdated())); + connect(m_widget.sliderBrightness, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated())); + connect(m_widget.sliderContrast, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated())); + connect(m_widget.sliderPositionX, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated())); + connect(m_widget.sliderPositionY, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated())); + connect(m_widget.sliderSizeX, SIGNAL(valueChanged(qreal)), this, SLOT(slot_sliderSizeX_valueChanged(qreal))); + connect(m_widget.sliderSizeY, SIGNAL(valueChanged(qreal)), this, SLOT(slot_sliderSizeY_valueChanged(qreal))); + connect(m_widget.buttonKeepSizeSquare, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(slot_buttonKeepSizeSquare_keepAspectRatioChanged(bool))); + connect(m_widget.sliderShearX, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated())); + connect(m_widget.sliderShearY, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated())); + connect(m_widget.sliderRotation, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated())); +} + +KisWdgScreentone::~KisWdgScreentone() +{} + +void KisWdgScreentone::setConfiguration(const KisPropertiesConfigurationSP config) +{ + // The double slider spin boxes and the color buttons emit signals + // when their value is set via code so we block signals here to + // prevent multiple sigConfigurationUpdated being called. + // After the widgets are set up, unblock and emit sigConfigurationUpdated + // just once + blockSignals(true); + + KoColor c; + m_widget.comboBoxPattern->setCurrentIndex(config->getInt("pattern", ScreentoneConfigDefaults::pattern())); + m_widget.comboBoxShape->setCurrentIndex(config->getInt("shape", ScreentoneConfigDefaults::shape())); + m_widget.comboBoxInterpolation->setCurrentIndex(config->getInt("interpolation", ScreentoneConfigDefaults::interpolation())); + c = config->getColor("foreground_color", ScreentoneConfigDefaults::foregroundColor()); + c.convertTo(m_colorSpace); + c.setOpacity(1.0); + m_widget.buttonForegroundColor->setColor(c); + m_widget.sliderForegroundOpacity->setValue(config->getInt("foreground_opacity", ScreentoneConfigDefaults::foregroundOpacity())); + c = config->getColor("background_color", ScreentoneConfigDefaults::backgroundColor()); + c.convertTo(m_colorSpace); + c.setOpacity(1.0); + m_widget.buttonBackgroundColor->setColor(c); + m_widget.sliderBackgroundOpacity->setValue(config->getInt("background_opacity", ScreentoneConfigDefaults::backgroundOpacity())); + m_widget.checkBoxInvert->setChecked(config->getBool("invert", ScreentoneConfigDefaults::invert())); + m_widget.sliderBrightness->setValue(config->getDouble("brightness", ScreentoneConfigDefaults::brightness())); + m_widget.sliderContrast->setValue(config->getDouble("contrast", ScreentoneConfigDefaults::contrast())); + m_widget.sliderPositionX->setValue(config->getDouble("position_x", ScreentoneConfigDefaults::positionX())); + m_widget.sliderPositionY->setValue(config->getDouble("position_y", ScreentoneConfigDefaults::positionY())); + m_widget.buttonKeepSizeSquare->setKeepAspectRatio(config->getBool("keep_size_square", ScreentoneConfigDefaults::keepSizeSquare())); + m_widget.sliderSizeX->setValue(config->getDouble("size_x", ScreentoneConfigDefaults::sizeX())); + // Set the size y slider to the sithe y value only if the size must not be squared + if (m_widget.buttonKeepSizeSquare->keepAspectRatio()) { + m_widget.sliderSizeY->setValue(config->getDouble("size_x", ScreentoneConfigDefaults::sizeX())); + } else { + m_widget.sliderSizeY->setValue(config->getDouble("size_y", ScreentoneConfigDefaults::sizeY())); + } + m_widget.sliderShearX->setValue(config->getDouble("shear_x", ScreentoneConfigDefaults::shearX())); + m_widget.sliderShearY->setValue(config->getDouble("shear_y", ScreentoneConfigDefaults::shearY())); + m_widget.sliderRotation->setValue(config->getDouble("rotation", ScreentoneConfigDefaults::rotation())); + + blockSignals(false); + emit sigConfigurationUpdated(); +} + +KisPropertiesConfigurationSP KisWdgScreentone::configuration() const +{ + QVariant v; + KoColor c; + KisFilterConfigurationSP config = new KisFilterConfiguration("screentone", 1, KisGlobalResourcesInterface::instance()); + config->setProperty("pattern", m_widget.comboBoxPattern->currentIndex()); + config->setProperty("shape", m_widget.comboBoxShape->currentIndex()); + config->setProperty("interpolation", m_widget.comboBoxInterpolation->currentIndex()); + c.fromKoColor(m_widget.buttonForegroundColor->color()); + v.setValue(c); + config->setProperty("foreground_color", v); + config->setProperty("foreground_opacity", m_widget.sliderForegroundOpacity->value()); + c.fromKoColor(m_widget.buttonBackgroundColor->color()); + v.setValue(c); + config->setProperty("background_color", v); + config->setProperty("background_opacity", m_widget.sliderBackgroundOpacity->value()); + config->setProperty("invert", m_widget.checkBoxInvert->isChecked()); + config->setProperty("brightness", m_widget.sliderBrightness->value()); + config->setProperty("contrast", m_widget.sliderContrast->value()); + config->setProperty("position_x", m_widget.sliderPositionX->value()); + config->setProperty("position_y", m_widget.sliderPositionY->value()); + config->setProperty("size_x", m_widget.sliderSizeX->value()); + config->setProperty("size_y", m_widget.sliderSizeY->value()); + config->setProperty("keep_size_square", m_widget.buttonKeepSizeSquare->keepAspectRatio()); + config->setProperty("shear_x", m_widget.sliderShearX->value()); + config->setProperty("shear_y", m_widget.sliderShearY->value()); + config->setProperty("rotation", m_widget.sliderRotation->value()); + return config; +} + +void KisWdgScreentone::setupPatternComboBox() +{ + m_widget.comboBoxPattern->clear(); + m_widget.comboBoxPattern->addItems(patternNames()); +} + +void KisWdgScreentone::setupShapeComboBox() +{ + m_widget.comboBoxShape->clear(); + QStringList names = shapeNames(m_widget.comboBoxPattern->currentIndex()); + if (names.isEmpty()) { + m_widget.labelShape->hide(); + m_widget.comboBoxShape->hide(); + } else { + m_widget.comboBoxShape->addItems(names); + m_widget.labelShape->show(); + m_widget.comboBoxShape->show(); + } +} + +void KisWdgScreentone::setupInterpolationComboBox() +{ + m_widget.comboBoxInterpolation->clear(); + QStringList names = interpolationNames(m_widget.comboBoxPattern->currentIndex(), + m_widget.comboBoxShape->currentIndex()); + if (names.isEmpty()) { + m_widget.labelInterpolation->hide(); + m_widget.comboBoxInterpolation->hide(); + } else { + m_widget.comboBoxInterpolation->addItems(names); + m_widget.labelInterpolation->show(); + m_widget.comboBoxInterpolation->show(); + } +} + +void KisWdgScreentone::slot_comboBoxPattern_currentIndexChanged(int) +{ + m_widget.comboBoxShape->blockSignals(true); + m_widget.comboBoxInterpolation->blockSignals(true); + setupShapeComboBox(); + setupInterpolationComboBox(); + m_widget.comboBoxShape->blockSignals(false); + m_widget.comboBoxInterpolation->blockSignals(false); + emit sigConfigurationUpdated(); +} + +void KisWdgScreentone::slot_comboBoxShape_currentIndexChanged(int) +{ + m_widget.comboBoxInterpolation->blockSignals(true); + setupInterpolationComboBox(); + m_widget.comboBoxInterpolation->blockSignals(false); + emit sigConfigurationUpdated(); +} + +void KisWdgScreentone::slot_sliderSizeX_valueChanged(qreal value) +{ + if (m_widget.buttonKeepSizeSquare->keepAspectRatio()) { + m_widget.sliderSizeY->blockSignals(true); + m_widget.sliderSizeY->setValue(value); + m_widget.sliderSizeY->blockSignals(false); + } + emit sigConfigurationUpdated(); +} + +void KisWdgScreentone::slot_sliderSizeY_valueChanged(qreal value) +{ + if (m_widget.buttonKeepSizeSquare->keepAspectRatio()) { + m_widget.sliderSizeX->blockSignals(true); + m_widget.sliderSizeX->setValue(value); + m_widget.sliderSizeX->blockSignals(false); + } + emit sigConfigurationUpdated(); +} + +void KisWdgScreentone::slot_buttonKeepSizeSquare_keepAspectRatioChanged(bool keep) +{ + if (keep) { + slot_sliderSizeX_valueChanged(m_widget.sliderSizeX->value()); + } +} diff --git a/plugins/generators/screentone/kis_wdg_screentone.h b/plugins/generators/screentone/kis_wdg_screentone.h new file mode 100644 index 0000000000..1e2109574c --- /dev/null +++ b/plugins/generators/screentone/kis_wdg_screentone.h @@ -0,0 +1,59 @@ +/* + * KDE. Krita Project. + * + * Copyright (c) 2020 Deif Lou + * + * 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. + */ + +#ifndef KIS_WDG_SCREENTONE_H +#define KIS_WDG_SCREENTONE_H + +#include +#include +#include + +#include "ui_wdgscreentoneoptions.h" + +class Ui_WdgScreentoneOptions; + +class KisWdgScreentone : public KisConfigWidget +{ + Q_OBJECT +public: + KisWdgScreentone(QWidget* parent = 0, const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8()); + ~KisWdgScreentone() override; +public: + void setConfiguration(const KisPropertiesConfigurationSP) override; + KisPropertiesConfigurationSP configuration() const override; + +private: + Ui_WdgScreentoneOptions m_widget; + const KoColorSpace *m_colorSpace; + + void setupPatternComboBox(); + void setupShapeComboBox(); + void setupInterpolationComboBox(); + +private Q_SLOTS: + void slot_comboBoxPattern_currentIndexChanged(int); + void slot_comboBoxShape_currentIndexChanged(int); + void slot_sliderSizeX_valueChanged(qreal value); + void slot_sliderSizeY_valueChanged(qreal value); + void slot_buttonKeepSizeSquare_keepAspectRatioChanged(bool keep); + +}; + +#endif diff --git a/plugins/generators/screentone/kritascreentonegenerator.json b/plugins/generators/screentone/kritascreentonegenerator.json new file mode 100644 index 0000000000..412301b244 --- /dev/null +++ b/plugins/generators/screentone/kritascreentonegenerator.json @@ -0,0 +1,9 @@ +{ + "Id": "Screentone Generator", + "Type": "Service", + "X-KDE-Library": "kritascreentonegenerator", + "X-KDE-ServiceTypes": [ + "Krita/Generator" + ], + "X-Krita-Version": "28" +} diff --git a/plugins/generators/screentone/screentoneconfigdefaults.h b/plugins/generators/screentone/screentoneconfigdefaults.h new file mode 100644 index 0000000000..6af60b0536 --- /dev/null +++ b/plugins/generators/screentone/screentoneconfigdefaults.h @@ -0,0 +1,64 @@ +/* + * KDE. Krita Project. + * + * Copyright (c) 2020 Deif Lou + * + * 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. + */ + +#ifndef SCREENTONECONFIGDEFAULTS_H +#define SCREENTONECONFIGDEFAULTS_H + +#include +#include +#include + +namespace ScreentoneConfigDefaults +{ + +constexpr int pattern() { return 0; } +constexpr int shape() { return 0; } +constexpr int interpolation() { return 0; } + +inline const KoColor& foregroundColor() +{ + static const KoColor c(Qt::black, KoColorSpaceRegistry::instance()->rgb8()); + return c; +} + +inline const KoColor& backgroundColor() +{ + static const KoColor c(Qt::white, KoColorSpaceRegistry::instance()->rgb8()); + return c; +} + +constexpr int foregroundOpacity() { return 100; } +constexpr int backgroundOpacity() { return 100; } +constexpr bool invert() { return false; } +constexpr qreal brightness() { return 50.0; } +constexpr qreal contrast() { return 50.0; } + +constexpr qreal positionX() { return 0.0; } +constexpr qreal positionY() { return 0.0; } +constexpr qreal sizeX() { return 10.0; } +constexpr qreal sizeY() { return 10.0; } +constexpr bool keepSizeSquare() { return true; } +constexpr qreal shearX() { return 0.0; } +constexpr qreal shearY() { return 0.0; } +constexpr qreal rotation() { return 0.0; } + +} + +#endif diff --git a/plugins/generators/screentone/screentonefunctions.cpp b/plugins/generators/screentone/screentonefunctions.cpp new file mode 100644 index 0000000000..628c6cb830 --- /dev/null +++ b/plugins/generators/screentone/screentonefunctions.cpp @@ -0,0 +1,183 @@ +/* + * KDE. Krita Project. + * + * Copyright (c) 2020 Deif Lou + * + * 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 "screentonefunctions.h" + +#include + +#include +#include + +QStringList patternNames() +{ + return QStringList() + << i18n("Dots") + << i18n("Lines"); +} + +QStringList shapeNames(int pattern) +{ + if (pattern == DotsPattern) { + return QStringList() + << i18n("Round") + << i18n("Ellipse") + << i18n("Diamond") + << i18n("Square"); + } else if (pattern == LinesPattern) { + return QStringList() + << i18n("Straight") + << i18n("Sine Wave") + << i18n("Triangular Wave") + << i18n("Sawtooth Wave") + << i18n("Curtains"); + } + + return QStringList(); +} + +QStringList interpolationNames(int pattern, int shape) +{ + if (pattern == DotsPattern) { + if (shape == RoundDotsShape || shape == EllipseDotsShape) { + return QStringList() + << i18n("Linear") + << i18n("Sinusoidal"); + } + } else if (pattern == LinesPattern) { + return QStringList() + << i18n("Linear") + << i18n("Sinusoidal"); + } + + return QStringList(); +} + +qreal sinFunction(qreal x) +{ + x = std::cos(x * M_PI); + return x * x; +} + +qreal triangleFunction(qreal x) +{ + return 1.0 - 2.0 * std::abs(x - std::floor(x + 0.5)); +} + +qreal sawToothFunction(qreal x) +{ + constexpr qreal peakXOffset = 0.9; + constexpr qreal peakYOffset = 0.5; + x = x - std::floor(x); + return (x < peakXOffset ? 1.0 / peakXOffset * x : -1.0 / (1.0 - peakXOffset) * (x - 1.0)) * peakYOffset; +} + +qreal DotsRoundLinearScreentoneFunction::operator()(qreal x, qreal y) const +{ + x = triangleFunction(x); + y = triangleFunction(y); + return std::sqrt(x * x + y * y) / M_SQRT2; +} + +qreal DotsRoundSinusoidalScreentoneFunction::operator()(qreal x, qreal y) const +{ + return (sinFunction(x) + sinFunction(y)) / 2.; +} + +qreal DotsEllipseLinearScreentoneFunction::operator()(qreal x, qreal y) const +{ + constexpr qreal ellipseRatioX = 0.4 / M_SQRT2; + constexpr qreal ellipseRatioY = 0.6 / M_SQRT2; + x = triangleFunction(x) * ellipseRatioX; + y = triangleFunction(y) * ellipseRatioY; + return std::sqrt(x * x + y * y) * M_SQRT2; +} + +qreal DotsEllipseSinusoidalScreentoneFunction::operator()(qreal x, qreal y) const +{ + constexpr qreal ellipseRatioX = 0.4 * 2.0; + constexpr qreal ellipseRatioY = 0.6 * 2.0; + x = sinFunction(x) * ellipseRatioX; + y = sinFunction(y) * ellipseRatioY; + return (x + y) / 2.; +} + +qreal DotsDiamondScreentoneFunction::operator()(qreal x, qreal y) const +{ + return (triangleFunction(x) + triangleFunction(y)) / 2.; +} + +qreal DotsSquareScreentoneFunction::operator()(qreal x, qreal y) const +{ + return std::max(triangleFunction(x), triangleFunction(y)); +} + +qreal LinesStraightLinearScreentoneFunction::operator()(qreal x, qreal y) const +{ + Q_UNUSED(x); + return triangleFunction(y); +} + +qreal LinesStraightSinusoidalScreentoneFunction::operator()(qreal x, qreal y) const +{ + Q_UNUSED(x); + return sinFunction(y); +} + +qreal LinesSineWaveLinearScreentoneFunction::operator()(qreal x, qreal y) const +{ + return triangleFunction(y + sinFunction(x)); +} + +qreal LinesSineWaveSinusoidalScreentoneFunction::operator()(qreal x, qreal y) const +{ + return sinFunction(y + sinFunction(x)); +} + +qreal LinesTriangularWaveLinearScreentoneFunction::operator()(qreal x, qreal y) const +{ + return triangleFunction(y + triangleFunction(x)); +} + +qreal LinesTriangularWaveSinusoidalScreentoneFunction::operator()(qreal x, qreal y) const +{ + return sinFunction(y + triangleFunction(x)); +} + +qreal LinesSawToothWaveLinearScreentoneFunction::operator()(qreal x, qreal y) const +{ + return triangleFunction(y + sawToothFunction(x)); +} + +qreal LinesSawToothWaveSinusoidalScreentoneFunction::operator()(qreal x, qreal y) const +{ + return sinFunction(y + sawToothFunction(x)); +} + +qreal LinesCurtainsLinearScreentoneFunction::operator()(qreal x, qreal y) const +{ + x = triangleFunction(x); + return triangleFunction(y + x * x); +} + +qreal LinesCurtainsSinusoidalScreentoneFunction::operator()(qreal x, qreal y) const +{ + x = triangleFunction(x); + return sinFunction(y + x * x); +} diff --git a/plugins/generators/screentone/screentonefunctions.h b/plugins/generators/screentone/screentonefunctions.h new file mode 100644 index 0000000000..42817fae0b --- /dev/null +++ b/plugins/generators/screentone/screentonefunctions.h @@ -0,0 +1,167 @@ +/* + * KDE. Krita Project. + * + * Copyright (c) 2020 Deif Lou + * + * 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. + */ + +#ifndef SCREENTONEFUNCTIONS_H +#define SCREENTONEFUNCTIONS_H + +#include + +class QStringList; + +enum ScreentonePattern +{ + DotsPattern, + LinesPattern +}; + +enum ScreentoneShape +{ + // Dots + RoundDotsShape, + EllipseDotsShape, + DiamondDotsShape, + SquareDotsShape, + CrossDotsShape, + + // Lines + StraightLinesShape = 0, + SineWaveLinesShape, + TriangularWaveLinesShape, + SawtoothWaveLinesShape, + CurtainsLinesShape +}; + +enum ScreentoneInterpolation +{ + LinearInterpolation, + SinusoidalInterpolation +}; + +QStringList patternNames(); +QStringList shapeNames(int pattern); +QStringList interpolationNames(int pattern, int shape); + +// Screentone functions must return a value between 0.0 and 1.0 +// 0 means the foreground is fully opaque +// 1 means the foreground is fully transparent so the background can be seen +// One cycle of the pattern in each direction should expand 1px. The size (scaling) +// in the transformations dictates the final scaling of the pattern (dots, lines, etc.) + +qreal sinFunction(qreal x); +qreal triangleFunction(qreal x); +qreal sawToothFunction(qreal x); + +class DotsRoundLinearScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class DotsRoundSinusoidalScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class DotsEllipseLinearScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class DotsEllipseSinusoidalScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class DotsDiamondScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class DotsSquareScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class LinesStraightLinearScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class LinesStraightSinusoidalScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class LinesSineWaveLinearScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class LinesSineWaveSinusoidalScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class LinesTriangularWaveLinearScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class LinesTriangularWaveSinusoidalScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class LinesSawToothWaveLinearScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class LinesSawToothWaveSinusoidalScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class LinesCurtainsLinearScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +class LinesCurtainsSinusoidalScreentoneFunction +{ +public: + qreal operator()(qreal x, qreal y) const; +}; + +#endif \ No newline at end of file diff --git a/plugins/generators/screentone/screentonegenerator.cpp b/plugins/generators/screentone/screentonegenerator.cpp new file mode 100644 index 0000000000..1c39cd262f --- /dev/null +++ b/plugins/generators/screentone/screentonegenerator.cpp @@ -0,0 +1,286 @@ +/* + * KDE. Krita Project. + * + * Copyright (c) 2020 Deif Lou + * + * 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 "screentonegenerator.h" +#include "ui_wdgscreentoneoptions.h" +#include "kis_wdg_screentone.h" +#include "brightnesscontrastfunctions.h" +#include "screentonefunctions.h" +#include "screentoneconfigdefaults.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +K_PLUGIN_FACTORY_WITH_JSON(KritaScreentoneGeneratorFactory, "kritascreentonegenerator.json", registerPlugin();) + +KisScreentoneGeneratorHandle::KisScreentoneGeneratorHandle(QObject *parent, const QVariantList &) + : QObject(parent) +{ + KisGeneratorRegistry::instance()->add(new KisScreentoneGenerator()); + +} + +KisScreentoneGeneratorHandle::~KisScreentoneGeneratorHandle() +{ +} + +KisScreentoneGenerator::KisScreentoneGenerator() : KisGenerator(id(), KoID("basic"), i18n("&Screentone...")) +{ + setColorSpaceIndependence(FULLY_INDEPENDENT); + setSupportsPainting(true); +} + +void KisScreentoneGenerator::generate(KisProcessingInformation dst, + const QSize &size, + const KisFilterConfigurationSP config, + KoUpdater *progressUpdater) const +{ + const ScreentonePattern pattern = static_cast(config->getInt("pattern", ScreentoneConfigDefaults::pattern())); + const ScreentoneShape shape = static_cast(config->getInt("shape", ScreentoneConfigDefaults::shape())); + const ScreentoneInterpolation interpolation = static_cast(config->getInt("interpolation", ScreentoneConfigDefaults::interpolation())); + + if (pattern == DotsPattern) { + if (shape == RoundDotsShape) { + if (interpolation == LinearInterpolation) { + DotsRoundLinearScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } else if (interpolation == SinusoidalInterpolation) { + DotsRoundSinusoidalScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } + } else if (shape == EllipseDotsShape) { + if (interpolation == LinearInterpolation) { + DotsEllipseLinearScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } else if (interpolation == SinusoidalInterpolation) { + DotsEllipseSinusoidalScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } + } else if (shape == DiamondDotsShape) { + DotsDiamondScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } else if (shape == SquareDotsShape) { + DotsSquareScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } + } else if (pattern == LinesPattern) { + if (shape == StraightLinesShape) { + if (interpolation == LinearInterpolation) { + LinesStraightLinearScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } else if (interpolation == SinusoidalInterpolation) { + LinesStraightSinusoidalScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } + } else if (shape == SineWaveLinesShape) { + if (interpolation == LinearInterpolation) { + LinesSineWaveLinearScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } else if (interpolation == SinusoidalInterpolation) { + LinesSineWaveSinusoidalScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } + } else if (shape == TriangularWaveLinesShape) { + if (interpolation == LinearInterpolation) { + LinesTriangularWaveLinearScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } else if (interpolation == SinusoidalInterpolation) { + LinesTriangularWaveSinusoidalScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } + } else if (shape == SawtoothWaveLinesShape) { + if (interpolation == LinearInterpolation) { + LinesSawToothWaveLinearScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } else if (interpolation == SinusoidalInterpolation) { + LinesSawToothWaveSinusoidalScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } + } else if (shape == CurtainsLinesShape) { + if (interpolation == LinearInterpolation) { + LinesCurtainsLinearScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } else if (interpolation == SinusoidalInterpolation) { + LinesCurtainsSinusoidalScreentoneFunction screentoneFunction; + generate(dst, size, config, progressUpdater, screentoneFunction); + } + } + } +} + +template +void KisScreentoneGenerator::generate(KisProcessingInformation dst, + const QSize &size, + const KisFilterConfigurationSP config, + KoUpdater *progressUpdater, + const ScreentoneFunction &screentoneFunction) const +{ + const qreal brightness = config->getDouble("brightness", ScreentoneConfigDefaults::brightness()) / 50. - 1.0; + const qreal contrast = config->getDouble("contrast", ScreentoneConfigDefaults::contrast()) / 50. - 1.0; + + const bool bypassBrightnessContrast = qFuzzyIsNull(brightness) && qFuzzyIsNull(contrast); + + if (bypassBrightnessContrast) { + IdentityBrightnessContrastFunction brightnessContrastFunction; + generate(dst, size, config, progressUpdater, screentoneFunction, brightnessContrastFunction); + } else { + DefaultBrightnessContrastFunction brightnessContrastFunction(brightness, contrast); + generate(dst, size, config, progressUpdater, screentoneFunction, brightnessContrastFunction); + } +} + +bool checkUpdaterInterruptedAndSetPercent(KoUpdater *progressUpdater, int percent) +{ + // The updater is null so return false to keep going + // with the computations + if (!progressUpdater) { + return false; + } + + if (progressUpdater->interrupted()) { + return true; + } + + progressUpdater->setProgress(percent); + return false; +} + +template +void KisScreentoneGenerator::generate(KisProcessingInformation dst, + const QSize &size, + const KisFilterConfigurationSP config, + KoUpdater *progressUpdater, + const ScreentoneFunction &screentoneFunction, + const BrightnessContrastFunction &brightnessContrastFunction) const +{ + KisPaintDeviceSP device = dst.paintDevice(); + Q_ASSERT(!device.isNull()); + KIS_SAFE_ASSERT_RECOVER_RETURN(config); + + checkUpdaterInterruptedAndSetPercent(progressUpdater, 0); + + const QRect bounds = QRect(dst.topLeft(), size); + const KoColorSpace * colorSpace = device->colorSpace(); + + const qreal positionX = config->getDouble("position_x", ScreentoneConfigDefaults::positionX()); + const qreal positionY = config->getDouble("position_y", ScreentoneConfigDefaults::positionY()); + const bool kepSizeSquare = config->getBool("keep_size_square", ScreentoneConfigDefaults::keepSizeSquare()); + const qreal sizeX = config->getDouble("size_x", ScreentoneConfigDefaults::sizeX()); + // Ensure that the size y component is equal to the x component if keepSizeSquare is true + const qreal sizeY = kepSizeSquare ? sizeX : config->getDouble("size_y", ScreentoneConfigDefaults::sizeY()); + const qreal shearX = config->getDouble("shear_x", ScreentoneConfigDefaults::shearX()); + const qreal shearY = config->getDouble("shear_y", ScreentoneConfigDefaults::shearY()); + const qreal rotation = config->getDouble("rotation", ScreentoneConfigDefaults::rotation()); + QTransform t; + t.shear(shearX, shearY); + t.scale(qIsNull(sizeX) ? 0.0 : 1.0 / sizeX, qIsNull(sizeY) ? 0.0 : 1.0 / sizeY); + t.rotate(rotation); + t.translate(positionX, positionY); + + KoColor foregroundColor = config->getColor("foreground_color", ScreentoneConfigDefaults::foregroundColor()); + KoColor backgroundColor = config->getColor("background_color", ScreentoneConfigDefaults::backgroundColor()); + qreal foregroundOpacity = config->getInt("foreground_opacity", ScreentoneConfigDefaults::foregroundOpacity()) / 100.0; + qreal backgroundOpacity = config->getInt("background_opacity", ScreentoneConfigDefaults::backgroundOpacity()) / 100.0; + foregroundColor.convertTo(colorSpace); + backgroundColor.convertTo(colorSpace); + foregroundColor.setOpacity(foregroundOpacity); + backgroundColor.setOpacity(backgroundOpacity); + + KisPaintDeviceSP foregroundDevice = new KisPaintDevice(colorSpace, "screentone_generator_foreground_paint_device"); + KisPaintDeviceSP backgroundDevice = device; + + foregroundDevice->fill(bounds, foregroundColor); + checkUpdaterInterruptedAndSetPercent(progressUpdater, 25); + backgroundDevice->fill(bounds, backgroundColor); + checkUpdaterInterruptedAndSetPercent(progressUpdater, 50); + + KisSelectionSP selection = new KisSelection(device->defaultBounds()); + KisSequentialIterator it(selection->pixelSelection(), bounds); + + if (!config->getBool("invert", ScreentoneConfigDefaults::invert())) { + while (it.nextPixel()) { + qreal x, y; + t.map(it.x(), it.y(), &x, &y); + + qreal v = qBound(0.0, brightnessContrastFunction(screentoneFunction(x, y)), 1.0); + *it.rawData() = 255 - static_cast(qRound(v * 255.0)); + } + } else { + while (it.nextPixel()) { + qreal x, y; + t.map(it.x(), it.y(), &x, &y); + + qreal v = qBound(0.0, brightnessContrastFunction(screentoneFunction(x, y)), 1.0); + *it.rawData() = static_cast(qRound(v * 255.0)); + } + } + checkUpdaterInterruptedAndSetPercent(progressUpdater, 25); + + KisPainter gc(backgroundDevice, selection); + gc.setCompositeOp(COMPOSITE_OVER); + gc.bitBlt(bounds.topLeft(), foregroundDevice, bounds); + checkUpdaterInterruptedAndSetPercent(progressUpdater, 100); +} + +KisFilterConfigurationSP KisScreentoneGenerator::defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const +{ + KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface); + QVariant v; + config->setProperty("pattern", ScreentoneConfigDefaults::pattern()); + config->setProperty("shape", ScreentoneConfigDefaults::shape()); + config->setProperty("interpolation", ScreentoneConfigDefaults::interpolation()); + v.setValue(ScreentoneConfigDefaults::foregroundColor()); + config->setProperty("foreground_color", v); + config->setProperty("foreground_opacity", ScreentoneConfigDefaults::foregroundOpacity()); + v.setValue(ScreentoneConfigDefaults::backgroundColor()); + config->setProperty("background_color", v); + config->setProperty("background_opacity", ScreentoneConfigDefaults::backgroundOpacity()); + config->setProperty("invert", ScreentoneConfigDefaults::invert()); + config->setProperty("brightness", ScreentoneConfigDefaults::brightness()); + config->setProperty("contrast", ScreentoneConfigDefaults::contrast()); + config->setProperty("position_x", ScreentoneConfigDefaults::positionX()); + config->setProperty("position_y", ScreentoneConfigDefaults::positionY()); + config->setProperty("size_x", ScreentoneConfigDefaults::sizeX()); + config->setProperty("size_y", ScreentoneConfigDefaults::sizeY()); + config->setProperty("keep_size_square", ScreentoneConfigDefaults::keepSizeSquare()); + config->setProperty("shear_x", ScreentoneConfigDefaults::shearX()); + config->setProperty("shear_y", ScreentoneConfigDefaults::shearY()); + config->setProperty("rotation", ScreentoneConfigDefaults::rotation()); + return config; +} + +KisConfigWidget * KisScreentoneGenerator::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev, bool) const +{ + Q_UNUSED(dev); + return new KisWdgScreentone(parent); +} + +#include "screentonegenerator.moc" + diff --git a/plugins/generators/screentone/screentonegenerator.h b/plugins/generators/screentone/screentonegenerator.h new file mode 100644 index 0000000000..b36d7ec397 --- /dev/null +++ b/plugins/generators/screentone/screentonegenerator.h @@ -0,0 +1,73 @@ +/* + * KDE. Krita Project. + * + * Copyright (c) 2020 Deif Lou + * + * 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. + */ + +#ifndef SCREENTONEGENERATOR_H +#define SCREENTONEGENERATOR_H + +#include +#include "generator/kis_generator.h" + +class KisConfigWidget; + +class KisScreentoneGeneratorHandle : public QObject +{ + Q_OBJECT +public: + KisScreentoneGeneratorHandle(QObject *parent, const QVariantList &); + ~KisScreentoneGeneratorHandle() override; +}; + +class KisScreentoneGenerator : public KisGenerator +{ +public: + KisScreentoneGenerator(); + + using KisGenerator::generate; + + virtual void generate(KisProcessingInformation dst, + const QSize& size, + const KisFilterConfigurationSP config, + KoUpdater* progressUpdater) const override; + + template + void generate(KisProcessingInformation dst, + const QSize &size, + const KisFilterConfigurationSP config, + KoUpdater *progressUpdater, + const ScreentoneFunction &screentoneFunction) const; + + template + void generate(KisProcessingInformation dst, + const QSize &size, + const KisFilterConfigurationSP config, + KoUpdater *progressUpdater, + const ScreentoneFunction &screentoneFunction, + const BrightnessContrastFunction &brightnessContrastFunction) const; + + static inline KoID id() { + return KoID("screentone", i18n("Screentone")); + } + + KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const override; + KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev, bool useForMasks) const override; + +}; + +#endif diff --git a/plugins/generators/screentone/wdgscreentoneoptions.ui b/plugins/generators/screentone/wdgscreentoneoptions.ui new file mode 100644 index 0000000000..fdb1855c5c --- /dev/null +++ b/plugins/generators/screentone/wdgscreentoneoptions.ui @@ -0,0 +1,542 @@ + + + WdgScreentoneOptions + + + + 0 + 0 + 283 + 293 + + + + + 0 + 0 + + + + + 0 + 175 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + false + + + + Screentone Type + + + + 0 + + + 10 + + + 10 + + + 10 + + + 10 + + + + + 5 + + + 5 + + + + + Pattern: + + + + + + + + 0 + 0 + + + + + + + + Shape: + + + + + + + + 0 + 0 + + + + + + + + Interpolation: + + + + + + + + 0 + 0 + + + + + + + + + + Qt::Vertical + + + + + + + + Transformation + + + + 0 + + + 10 + + + 10 + + + 10 + + + 10 + + + + + 5 + + + 5 + + + + + Position: + + + + + + + 5 + + + + + + 0 + 0 + + + + Qt::WheelFocus + + + + + + + + 0 + 0 + + + + Qt::WheelFocus + + + + + + + + + Size: + + + + + + + 5 + + + + + + 0 + 0 + + + + Qt::WheelFocus + + + + + + + + 0 + 0 + + + + Qt::WheelFocus + + + + + + + Qt::WheelFocus + + + + + + + + + Shear: + + + + + + + 5 + + + + + + 0 + 0 + + + + Qt::WheelFocus + + + + + + + + 0 + 0 + + + + Qt::WheelFocus + + + + + + + + + Rotation: + + + + + + + + 0 + 0 + + + + Qt::WheelFocus + + + + + + + + + Qt::Vertical + + + + + + + + Postprocessing + + + + 0 + + + 10 + + + 10 + + + 10 + + + 10 + + + + + 5 + + + 5 + + + + + Foreground: + + + + + + + 5 + + + + + + + + + + + + + 0 + 0 + + + + Qt::WheelFocus + + + + + + + + + Background: + + + + + + + 5 + + + + + + + + + + + + + 0 + 0 + + + + Qt::WheelFocus + + + + + + + + + Invert: + + + + + + + + + + + + + + Brightness: + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::WheelFocus + + + + + + + Contrast: + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::WheelFocus + + + + + + + + + Qt::Vertical + + + + + + + + + + + + KisDoubleSliderSpinBox + QWidget +
kis_slider_spin_box.h
+ 1 +
+ + KisSliderSpinBox + QWidget +
kis_slider_spin_box.h
+ 1 +
+ + KoAspectButton + QWidget +
KoAspectButton.h
+ 1 +
+ + KisColorButton + QPushButton +
kis_color_button.h
+
+
+ + buttonForegroundColor + sliderForegroundOpacity + buttonBackgroundColor + sliderBackgroundOpacity + sliderPositionX + sliderPositionY + sliderSizeX + sliderSizeY + buttonKeepSizeSquare + sliderShearX + sliderShearY + + + +