diff --git a/libs/ui/widgets/kis_wdg_generator.cpp b/libs/ui/widgets/kis_wdg_generator.cpp index b52d8c9cd3..f37bb1b97f 100644 --- a/libs/ui/widgets/kis_wdg_generator.cpp +++ b/libs/ui/widgets/kis_wdg_generator.cpp @@ -1,164 +1,164 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * 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 "widgets/kis_wdg_generator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "ui_wdggenerators.h" class KisGeneratorItem : public QListWidgetItem { public: KisGeneratorItem(const QString & text, QListWidget * parent = 0, int type = Type) : QListWidgetItem(text, parent, type) { } KisGeneratorSP generator; }; struct KisWdgGenerator::Private { public: Private() : centralWidget(0), view(0) { } QWidget * centralWidget; // Active generator settings widget KisGeneratorSP currentGenerator; Ui_WdgGenerators uiWdgGenerators; KisPaintDeviceSP dev; QGridLayout *widgetLayout; KisViewManager *view; }; KisWdgGenerator::KisWdgGenerator(QWidget * parent) : QWidget(parent) , d(new Private()) { - KisPaintDeviceSP dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8(0)); + d->dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8()); } KisWdgGenerator::~KisWdgGenerator() { delete d; } void KisWdgGenerator::initialize(KisViewManager *view) { d->view = view; d->uiWdgGenerators.setupUi(this); d->widgetLayout = new QGridLayout(d->uiWdgGenerators.centralWidgetHolder); QList generators = KisGeneratorRegistry::instance()->values(); Q_FOREACH (const KisGeneratorSP generator, generators) { Q_ASSERT(generator); KisGeneratorItem * item = new KisGeneratorItem(generator->name(), d->uiWdgGenerators.lstGenerators, QListWidgetItem::UserType + 1); item->generator = generator; } connect(d->uiWdgGenerators.lstGenerators, SIGNAL(currentRowChanged(int)), this, SLOT(slotGeneratorActivated(int))); if (d->uiWdgGenerators.lstGenerators->count() > 0) { d->uiWdgGenerators.lstGenerators->setCurrentRow(0); } } void KisWdgGenerator::setConfiguration(const KisFilterConfigurationSP config) { for (int i = 0; i < d->uiWdgGenerators.lstGenerators->count(); ++i) { KisGeneratorItem * item = static_cast(d->uiWdgGenerators.lstGenerators->item(i)); if (item->generator->id() == config->name()) { // match! slotGeneratorActivated(i); d->uiWdgGenerators.lstGenerators->setCurrentRow(i); KisConfigWidget * wdg = dynamic_cast(d->centralWidget); if (wdg) { wdg->setConfiguration(config); } return; } } } KisFilterConfigurationSP KisWdgGenerator::configuration() { KisConfigWidget * wdg = dynamic_cast(d->centralWidget); if (wdg) { KisFilterConfigurationSP config = dynamic_cast(wdg->configuration().data()); if (config) { return config; } } else { - return d->currentGenerator->defaultConfiguration(0); + return d->currentGenerator->defaultConfiguration(d->dev); } return 0; } void KisWdgGenerator::slotGeneratorActivated(int row) { KisGeneratorItem *item = dynamic_cast(d->uiWdgGenerators.lstGenerators->item(row)); if (!item) { d->centralWidget = new QLabel(i18n("No configuration options."), d->uiWdgGenerators.centralWidgetHolder); } else { d->currentGenerator = item->generator; delete d->centralWidget; KisConfigWidget* widget = d->currentGenerator->createConfigurationWidget(d->uiWdgGenerators.centralWidgetHolder, d->dev); if (!widget) { // No widget, so display a label instead d->centralWidget = new QLabel(i18n("No configuration options."), d->uiWdgGenerators.centralWidgetHolder); } else { d->centralWidget = widget; widget->setView(d->view); widget->setConfiguration(d->currentGenerator->defaultConfiguration(d->dev)); } } d->widgetLayout->addWidget(d->centralWidget, 0 , 0); d->uiWdgGenerators.centralWidgetHolder->setMinimumSize(d->centralWidget->minimumSize()); } diff --git a/plugins/generators/CMakeLists.txt b/plugins/generators/CMakeLists.txt index 65e3b73a13..828a5438f2 100644 --- a/plugins/generators/CMakeLists.txt +++ b/plugins/generators/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(solid) add_subdirectory(pattern) +add_subdirectory(halftone) diff --git a/plugins/generators/halftone/CMakeLists.txt b/plugins/generators/halftone/CMakeLists.txt new file mode 100644 index 0000000000..5fab809ad6 --- /dev/null +++ b/plugins/generators/halftone/CMakeLists.txt @@ -0,0 +1,15 @@ +set(kritahalftonegenerator_SOURCES + kis_halftone_generator.cpp + ) + + +ki18n_wrap_ui(kritahalftonegenerator_SOURCES + wdghalftonegeneratoroptions.ui + ) + +add_library(kritahalftonegenerator MODULE ${kritahalftonegenerator_SOURCES}) + +target_link_libraries(kritahalftonegenerator kritaui) + +install(TARGETS kritahalftonegenerator DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) + diff --git a/plugins/generators/halftone/kis_halftone_generator.cpp b/plugins/generators/halftone/kis_halftone_generator.cpp new file mode 100644 index 0000000000..d610106b13 --- /dev/null +++ b/plugins/generators/halftone/kis_halftone_generator.cpp @@ -0,0 +1,276 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2016 Wolthera van Hövell tot Westerflier + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kis_halftone_generator.h" + + +K_PLUGIN_FACTORY_WITH_JSON(KritaHalftoneGeneratorFactory, "kritahalftonegenerator.json", registerPlugin();) + +KritaHalftoneGenerator::KritaHalftoneGenerator(QObject *parent, const QVariantList &) + : QObject(parent) +{ + KisGeneratorRegistry::instance()->add(new KisHalftoneGenerator()); +} + +KritaHalftoneGenerator::~KritaHalftoneGenerator() +{ +} + +KisHalftoneGenerator::KisHalftoneGenerator() : KisGenerator(id(), KoID("basic"), i18n("&Halftone...")) +{ + setColorSpaceIndependence(FULLY_INDEPENDENT); + setSupportsPainting(true); +} + +KisFilterConfigurationSP KisHalftoneGenerator::factoryConfiguration(const KisPaintDeviceSP) const +{ + KisFilterConfigurationSP config = new KisFilterConfiguration("halftonegenerator", 1); + + config->setProperty("cellSize", 8.0); + config->setProperty("intensity", 0.5); + config->setProperty("patternAngle", 45.0); + QVariant v; + KoColor black; + black.fromQColor(QColor(Qt::black)); + v.setValue(black); + config->setProperty("foreGroundColor", v); + KoColor white; + white.fromQColor(QColor(Qt::white)); + v.setValue(white); + config->setProperty("backGroundColor", v); + config->setProperty("antiAliasing", true); + config->setProperty("invert", false); + + return config; +} + +KisConfigWidget * KisHalftoneGenerator::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const +{ + return new KisHalftoneGeneratorConfigWidget(parent, dev); +} + +void KisHalftoneGenerator::generate(KisProcessingInformation dstInfo, + const QSize& size, + const KisFilterConfigurationSP config, + KoUpdater* progressUpdater) const +{ + KisPaintDeviceSP device = dstInfo.paintDevice(); + + Q_ASSERT(!device.isNull()); + Q_ASSERT(config); + + QRect applyRect(QPoint(),size); + + qreal cellSize = (qreal)config->getInt("cellSize", 8); + qreal angle = fmod((qreal)config->getInt("patternAngle", 45), 90.0); + KoColor foregroundC(Qt::black, device->colorSpace()); + foregroundC.fromKoColor(config->getColor("foreGroundColor", KoColor(Qt::black, device->colorSpace()) ) ); + KoColor backgroundC(Qt::white, device->colorSpace()); + backgroundC.fromKoColor(config->getColor("backGroundColor", KoColor(Qt::white, device->colorSpace()) ) ); + + //First calculate the full diameter, using pythagoras theorem. + qreal diameter = qSqrt((cellSize*cellSize)*2); + + qreal cellSpacingH = cellSize; + qreal cellSpacingV = cellSize; + qreal cellOffsetV = 0; + + if (angle>0.0){ + //2/3=0.6 sin=o/h + //0.6*3=2 sin*h=o + //2/0.6=3 o/sin=h + qreal angleRad = qDegreesToRadians(angle); + //Horizontal cellspacing is the hypotenuse of the Angle and the cellSize(opposite). + cellSpacingH = cellSize/qSin(angleRad); + //Vertical cellspacing is the opposite of the Angle and the cellSize(hypotenuse). + cellSpacingV = cellSize*qSin(angleRad); + //cellSpacingoffset is the oppose of the (90-angle) and the vertical cellspacing(adjectant) toa t=o/a, t*a=o. + cellOffsetV = qTan(qDegreesToRadians(90-angle))*cellSpacingV; + } + + QPolygonF gridPoints; + QRect totalRect(QPoint(0,0), applyRect.bottomRight()); + if (gridPoints.size()<1) { + int rows = (totalRect.height()/cellSpacingV)+3; + for (int r=0; rsetRange(0, (applyRect.height()/cellSpacingV+3)*(applyRect.width()/cellSpacingH+3)); + } + KisPainter painter(device); + painter.setCompositeOp(device->colorSpace()->compositeOp(COMPOSITE_OVER)); + KisPaintDeviceSP dab = device->createCompositionSourceDevice(); + KisPainter dbPainter(dab); + device->fill(applyRect, backgroundC); + dbPainter.setAntiAliasPolygonFill(config->getBool("antiAliasing", true)); + dbPainter.setPaintColor(foregroundC); + dbPainter.setFillStyle(KisPainter::FillStyleForegroundColor); + dbPainter.setCompositeOp(device->colorSpace()->compositeOp(COMPOSITE_OVER)); + quint8 eightbit = 255; + if (config->getBool("invert", false)) { + eightbit = 0; + } + quint8 intensity = 255 * config->getFloat("intensity", 0.5); + + QRect cellRect(applyRect.topLeft()-QPoint(qFloor(cellSpacingH), qFloor(qMax(cellSpacingV, diameter))), applyRect.bottomRight()+QPoint(qCeil(cellSpacingH), qCeil(qMax(cellSpacingV, diameter)))); + for (int i=0; icrop(qAbs(qMin(0, xdifference)), + qAbs(qMin(0, ydifference)), + diameter, + diameter); + //we only want to paint the bits actually in the apply rect...) + painter.bitBlt(sPoint, + dab, + dab->exactBounds()); + if (progressUpdater) { + progressUpdater->setValue(i); + } + } + } +} + +//----------config---------// +KisHalftoneGeneratorConfigWidget::KisHalftoneGeneratorConfigWidget(QWidget* parent, KisPaintDeviceSP dev) + : KisConfigWidget(parent) +{ + Q_ASSERT(dev); + m_page.setupUi(this); + + const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8(); + + if (dev->colorSpace()) { + cs = dev->colorSpace(); + } + + KoColor white(Qt::white, cs); + KoColor black(Qt::black, cs); + + m_page.bnForeColor->setColor(white); + m_page.bnBackColor->setColor(black); + m_page.bnForeColor->setDefaultColor(white); + m_page.bnBackColor->setDefaultColor(black); + + m_page.sldSize->setRange(3, 90); + m_page.sldIntensity->setRange(0, 100); + m_page.sldIntensity->setSingleStep(1); + m_page.sldIntensity->setColors(white, black); + + connect(m_page.sldSize, SIGNAL(valueChanged(int)), SLOT(slotConfigChanged())); + connect(m_page.dialAngle, SIGNAL(valueChanged(int)), m_page.spAngle, SLOT(setValue(int))); + connect(m_page.dialAngle, SIGNAL(valueChanged(int)), SLOT(slotConfigChanged())); + connect(m_page.spAngle, SIGNAL(valueChanged(int)), SLOT(slotConfigChanged())); + + //connect(m_page.bnForeColor, SIGNAL(changed(KoColor)), SLOT(slotUpdateSlider())); + //connect(m_page.bnBackColor, SIGNAL(changed(KoColor)), SLOT(slotUpdateSlider())); + + connect(m_page.bnForeColor, SIGNAL(changed(KoColor)), SLOT(slotConfigChanged())); + connect(m_page.bnBackColor, SIGNAL(changed(KoColor)), SLOT(slotConfigChanged())); + connect(m_page.chkAntiAliasing, SIGNAL(toggled(bool)), SLOT(slotConfigChanged())); + connect(m_page.chkInvert, SIGNAL(toggled(bool)), SLOT(slotConfigChanged())); +} + +KisHalftoneGeneratorConfigWidget::~KisHalftoneGeneratorConfigWidget() +{ + +} + +KisPropertiesConfigurationSP KisHalftoneGeneratorConfigWidget::configuration() const +{ + KisFilterConfiguration *config = new KisFilterConfiguration("halftonegenerator", 1); + config->setProperty("cellSize", m_page.sldSize->value()); + config->setProperty("patternAngle", m_page.spAngle->value()); + config->setProperty("intensity", (float)m_page.sldIntensity->value()/100.0); + QVariant v; + v.setValue(m_page.bnForeColor->color()); + config->setProperty("foreGroundColor", v); + v.setValue(m_page.bnBackColor->color()); + config->setProperty("backGroundColor", v); + config->setProperty("antiAliasing", m_page.chkAntiAliasing->isChecked()); + config->setProperty("invert", m_page.chkInvert->isChecked()); + + return config; +} + +void KisHalftoneGeneratorConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) +{ + QVariant value; + if (config->getProperty("cellSize", value)) { + m_page.sldSize->setValue(value.toUInt()); + } + if (config->getProperty("patternAngle", value)) { + m_page.dialAngle->setValue(value.toUInt()); + m_page.spAngle->setValue(value.toUInt()); + } + if (config->getProperty("antiAliasing", value)) { + m_page.chkAntiAliasing->setChecked(value.toBool()); + } + if (config->getProperty("invert", value)) { + m_page.chkInvert->setChecked(value.toBool()); + } + if (config->getProperty("intensity", value)) { + m_page.sldIntensity->setValue(value.toFloat()*100); + } + + + m_page.bnForeColor->setColor(config->getColor("foreGroundColor",m_page.bnForeColor->defaultColor())); + m_page.bnBackColor->setColor(config->getColor("backGroundColor",m_page.bnBackColor->defaultColor())); +} + + +#include "kis_halftone_generator.moc" diff --git a/plugins/generators/halftone/kis_halftone_generator.h b/plugins/generators/halftone/kis_halftone_generator.h new file mode 100644 index 0000000000..a0e9ca804b --- /dev/null +++ b/plugins/generators/halftone/kis_halftone_generator.h @@ -0,0 +1,71 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2016 Wolthera van Hövell tot Westerflier + * + * 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 KISHALFTONEGENERATOR_H +#define KISHALFTONEGENERATOR_H + +#include +#include +#include +#include +#include +#include "ui_wdghalftonegeneratoroptions.h" + +class KritaHalftoneGenerator : public QObject +{ + Q_OBJECT +public: + KritaHalftoneGenerator(QObject *parent, const QVariantList &); + virtual ~KritaHalftoneGenerator(); +}; + +class KisHalftoneGenerator : public KisGenerator +{ +public: + KisHalftoneGenerator(); + + using KisGenerator::generate; + + void generate(KisProcessingInformation dst, + const QSize& size, + const KisFilterConfigurationSP config, + KoUpdater* progressUpdater + ) const; + + static inline KoID id() { + return KoID("halftonegenerator", i18n("Halftone")); + } + virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; +}; + +class KisHalftoneGeneratorConfigWidget : public KisConfigWidget +{ + Q_OBJECT +public: + KisHalftoneGeneratorConfigWidget(QWidget *parent, KisPaintDeviceSP dev); + virtual ~KisHalftoneGeneratorConfigWidget(); + + virtual KisPropertiesConfigurationSP configuration() const; + void setConfiguration(const KisPropertiesConfigurationSP config); + Ui::KisWdgHalftoneGen m_page; +}; + +#endif // KISHALFTONEGENERATOR_H diff --git a/plugins/generators/halftone/kritahalftonegenerator.json b/plugins/generators/halftone/kritahalftonegenerator.json new file mode 100644 index 0000000000..3cbd964756 --- /dev/null +++ b/plugins/generators/halftone/kritahalftonegenerator.json @@ -0,0 +1,10 @@ +{ + "Id": "Halftone Pattern Generator", + "Type": "Service", + "X-KDE-Library": "kritahalftonegenerator", + "X-KDE-ServiceTypes": [ + "Krita/Generator" + ], + "X-Krita-Version": "28" +} + diff --git a/plugins/generators/halftone/wdghalftonegeneratoroptions.ui b/plugins/generators/halftone/wdghalftonegeneratoroptions.ui new file mode 100644 index 0000000000..cece1e6ae0 --- /dev/null +++ b/plugins/generators/halftone/wdghalftonegeneratoroptions.ui @@ -0,0 +1,109 @@ + + + KisWdgHalftoneGen + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + + + + + + + + + + + + + + + + + + + + + + Colors: + + + + + + + Size: + + + + + + + + + + + + + + + + + Angle: + + + + + + + Anti-Aliasing + + + + + + + + + + Invert + + + + + + + + KoColorSlider + QWidget +
KoColorSlider.h
+ 1 +
+ + KisColorButton + QPushButton +
kis_color_button.h
+
+ + KisSliderSpinBox + QWidget +
kis_slider_spin_box.h
+ 1 +
+
+ + +