From 8362bf63dea22bbf6736609b0f49c152f975eb63 Mon Sep 17 00:00:00 2001 From: tpearson Date: Wed, 20 Jan 2010 01:29:50 +0000 Subject: Added old abandoned KDE3 version of koffice git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- krita/plugins/paintops/Makefile.am | 2 + krita/plugins/paintops/defaultpaintops/Makefile.am | 38 ++ krita/plugins/paintops/defaultpaintops/README | 3 + .../plugins/paintops/defaultpaintops/airbrush.png | Bin 0 -> 1037 bytes .../defaultpaintops/defaultpaintops_plugin.cc | 70 +++ .../defaultpaintops/defaultpaintops_plugin.h | 35 ++ krita/plugins/paintops/defaultpaintops/eraser.png | Bin 0 -> 734 bytes .../paintops/defaultpaintops/kis_airbrushop.cc | 150 +++++ .../paintops/defaultpaintops/kis_airbrushop.h | 60 ++ .../paintops/defaultpaintops/kis_brushop.cc | 284 +++++++++ .../plugins/paintops/defaultpaintops/kis_brushop.h | 112 ++++ .../paintops/defaultpaintops/kis_convolveop.cc | 58 ++ .../paintops/defaultpaintops/kis_convolveop.h | 56 ++ .../defaultpaintops/kis_dlgbrushcurvecontrol.ui | 271 +++++++++ .../paintops/defaultpaintops/kis_duplicateop.cc | 341 +++++++++++ .../paintops/defaultpaintops/kis_duplicateop.h | 62 ++ .../paintops/defaultpaintops/kis_eraseop.cc | 140 +++++ .../plugins/paintops/defaultpaintops/kis_eraseop.h | 56 ++ .../plugins/paintops/defaultpaintops/kis_penop.cc | 132 +++++ krita/plugins/paintops/defaultpaintops/kis_penop.h | 58 ++ .../paintops/defaultpaintops/kis_smudgeop.cc | 328 +++++++++++ .../paintops/defaultpaintops/kis_smudgeop.h | 117 ++++ .../defaultpaintops/kritadefaultpaintops.desktop | 93 +++ .../paintops/defaultpaintops/paintbrush.png | Bin 0 -> 769 bytes krita/plugins/paintops/defaultpaintops/pencil.png | Bin 0 -> 793 bytes krita/plugins/paintops/defaultpaintops/src/README | 2 + .../paintops/defaultpaintops/src/pencil_01.svg | 637 +++++++++++++++++++++ .../src/pencil_jonathan_dietrich_01.svg | 434 ++++++++++++++ .../src/pennello_mauro_olivo_01.svg | 616 ++++++++++++++++++++ 29 files changed, 4155 insertions(+) create mode 100644 krita/plugins/paintops/Makefile.am create mode 100644 krita/plugins/paintops/defaultpaintops/Makefile.am create mode 100644 krita/plugins/paintops/defaultpaintops/README create mode 100644 krita/plugins/paintops/defaultpaintops/airbrush.png create mode 100644 krita/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cc create mode 100644 krita/plugins/paintops/defaultpaintops/defaultpaintops_plugin.h create mode 100644 krita/plugins/paintops/defaultpaintops/eraser.png create mode 100644 krita/plugins/paintops/defaultpaintops/kis_airbrushop.cc create mode 100644 krita/plugins/paintops/defaultpaintops/kis_airbrushop.h create mode 100644 krita/plugins/paintops/defaultpaintops/kis_brushop.cc create mode 100644 krita/plugins/paintops/defaultpaintops/kis_brushop.h create mode 100644 krita/plugins/paintops/defaultpaintops/kis_convolveop.cc create mode 100644 krita/plugins/paintops/defaultpaintops/kis_convolveop.h create mode 100644 krita/plugins/paintops/defaultpaintops/kis_dlgbrushcurvecontrol.ui create mode 100644 krita/plugins/paintops/defaultpaintops/kis_duplicateop.cc create mode 100644 krita/plugins/paintops/defaultpaintops/kis_duplicateop.h create mode 100644 krita/plugins/paintops/defaultpaintops/kis_eraseop.cc create mode 100644 krita/plugins/paintops/defaultpaintops/kis_eraseop.h create mode 100644 krita/plugins/paintops/defaultpaintops/kis_penop.cc create mode 100644 krita/plugins/paintops/defaultpaintops/kis_penop.h create mode 100644 krita/plugins/paintops/defaultpaintops/kis_smudgeop.cc create mode 100644 krita/plugins/paintops/defaultpaintops/kis_smudgeop.h create mode 100644 krita/plugins/paintops/defaultpaintops/kritadefaultpaintops.desktop create mode 100644 krita/plugins/paintops/defaultpaintops/paintbrush.png create mode 100644 krita/plugins/paintops/defaultpaintops/pencil.png create mode 100644 krita/plugins/paintops/defaultpaintops/src/README create mode 100644 krita/plugins/paintops/defaultpaintops/src/pencil_01.svg create mode 100644 krita/plugins/paintops/defaultpaintops/src/pencil_jonathan_dietrich_01.svg create mode 100644 krita/plugins/paintops/defaultpaintops/src/pennello_mauro_olivo_01.svg (limited to 'krita/plugins/paintops') diff --git a/krita/plugins/paintops/Makefile.am b/krita/plugins/paintops/Makefile.am new file mode 100644 index 00000000..328f0162 --- /dev/null +++ b/krita/plugins/paintops/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = \ + defaultpaintops diff --git a/krita/plugins/paintops/defaultpaintops/Makefile.am b/krita/plugins/paintops/defaultpaintops/Makefile.am new file mode 100644 index 00000000..5a52d651 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/Makefile.am @@ -0,0 +1,38 @@ +kritaimagesdir = $(prefix)/share/apps/krita/images + +kritaimages_DATA = \ + airbrush.png \ + paintbrush.png \ + eraser.png \ + pencil.png + + +kde_services_DATA = kritadefaultpaintops.desktop + +# all_includes must remain last! +INCLUDES = -I$(srcdir)/../../../sdk \ + -I$(srcdir)/../../../core \ + -I$(srcdir)/../../../kritacolor/ \ + -I$(srcdir)/../../../ui \ + $(KOFFICE_INCLUDES) $(KOPAINTER_INCLUDES) $(all_includes) + + +kritadefaultpaintops_la_SOURCES = \ + defaultpaintops_plugin.cc \ + kis_airbrushop.cc \ + kis_brushop.cc \ + kis_duplicateop.cc \ + kis_eraseop.cc \ + kis_penop.cc \ + kis_dlgbrushcurvecontrol.ui \ + kis_smudgeop.cc + +noinst_HEADERS = defaultpaintops_plugin.h kis_airbrushop.h kis_brushop.h \ + kis_duplicateop.h kis_eraseop.h kis_penop.h kis_smudgeop.h + +kde_module_LTLIBRARIES = kritadefaultpaintops.la + +kritadefaultpaintops_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritadefaultpaintops_la_LIBADD = ../../../libkritacommon.la $(LIB_KOPAINTER) $(LIB_KOFFICECORE) + +kritadefaultpaintops_la_METASOURCES = AUTO diff --git a/krita/plugins/paintops/defaultpaintops/README b/krita/plugins/paintops/defaultpaintops/README new file mode 100644 index 00000000..47b07ce7 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/README @@ -0,0 +1,3 @@ +Default implementations of the paintop interface. These may +some day become plugins. New paintops should be created as +plugins. diff --git a/krita/plugins/paintops/defaultpaintops/airbrush.png b/krita/plugins/paintops/defaultpaintops/airbrush.png new file mode 100644 index 00000000..075fa49d Binary files /dev/null and b/krita/plugins/paintops/defaultpaintops/airbrush.png differ diff --git a/krita/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cc b/krita/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cc new file mode 100644 index 00000000..e23fd3cf --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cc @@ -0,0 +1,70 @@ +/* + * defaultpaintops_plugin.cc -- Part of Krita + * + * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) + * + * 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 "kis_airbrushop.h" +#include "kis_brushop.h" +#include "kis_duplicateop.h" +#include "kis_eraseop.h" +#include "kis_smudgeop.h" +#include "kis_penop.h" +#include "kis_global.h" +#include "kis_paintop_registry.h" + +#include "defaultpaintops_plugin.h" + +typedef KGenericFactory DefaultPaintOpsPluginFactory; +K_EXPORT_COMPONENT_FACTORY( kritadefaultpaintops, DefaultPaintOpsPluginFactory( "kritacore" ) ) + + +DefaultPaintOpsPlugin::DefaultPaintOpsPlugin(QObject *parent, const char *name, const QStringList &) + : KParts::Plugin(parent, name) +{ + setInstance(DefaultPaintOpsPluginFactory::instance()); + + // This is not a gui plugin; only load it when the doc is created. + if ( parent->inherits("KisPaintOpRegistry") ) + { + KisPaintOpRegistry * r = dynamic_cast(parent); + // Add hard-coded paint ops. Plugin paintops will add + // themselves in the plugin initialization code. + r->add ( new KisAirbrushOpFactory ); + r->add ( new KisBrushOpFactory ); + r->add ( new KisDuplicateOpFactory ); + r->add ( new KisEraseOpFactory ); + r->add ( new KisPenOpFactory ); + r->add ( new KisSmudgeOpFactory ); + } + +} + +DefaultPaintOpsPlugin::~DefaultPaintOpsPlugin() +{ +} + +#include "defaultpaintops_plugin.moc" diff --git a/krita/plugins/paintops/defaultpaintops/defaultpaintops_plugin.h b/krita/plugins/paintops/defaultpaintops/defaultpaintops_plugin.h new file mode 100644 index 00000000..402ae4a2 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/defaultpaintops_plugin.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt (boud@valdyas.org) + * + * 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 DEFAULT_PAINTOPS_PLUGIN_H_ +#define DEFAULT_PAINTOPS_PLUGIN_H_ + +#include + +/** + * A plugin wrapper that adds the paintop factories to the paintop registry. + */ +class DefaultPaintOpsPlugin : public KParts::Plugin +{ + Q_OBJECT +public: + DefaultPaintOpsPlugin(QObject *parent, const char *name, const QStringList &); + virtual ~DefaultPaintOpsPlugin(); +}; + +#endif // DEFAULT_PAINTOPSGRAY_PLUGIN_H_ diff --git a/krita/plugins/paintops/defaultpaintops/eraser.png b/krita/plugins/paintops/defaultpaintops/eraser.png new file mode 100644 index 00000000..99eefc78 Binary files /dev/null and b/krita/plugins/paintops/defaultpaintops/eraser.png differ diff --git a/krita/plugins/paintops/defaultpaintops/kis_airbrushop.cc b/krita/plugins/paintops/defaultpaintops/kis_airbrushop.cc new file mode 100644 index 00000000..6f2e5cb1 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_airbrushop.cc @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2002 Patrick Julien + * Copyright (c) 2004 Boudewijn Rempt + * Copyright (c) 2004 Clarence Dang + * Copyright (c) 2004 Adrian Page + * Copyright (c) 2004 Cyrille Berger + * + * 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 "kis_vec.h" +#include "kis_brush.h" +#include "kis_global.h" +#include "kis_paint_device.h" +#include "kis_painter.h" +#include "kis_types.h" +#include "kis_paintop.h" +#include "kis_layer.h" +#include "kis_selection.h" +#include "kis_airbrushop.h" + +KisPaintOp * KisAirbrushOpFactory::createOp(const KisPaintOpSettings */*settings*/, KisPainter * painter) +{ + KisPaintOp * op = new KisAirbrushOp(painter); + Q_CHECK_PTR(op); + return op; +} + + +KisAirbrushOp::KisAirbrushOp(KisPainter * painter) + : super(painter) +{ +} + +KisAirbrushOp::~KisAirbrushOp() +{ +} + +void KisAirbrushOp::paintAt(const KisPoint &pos, const KisPaintInformation& info) +{ +// See: http://www.sysf.physto.se/~klere/airbrush/ for information +// about _real_ airbrushes. +// +// Most graphics apps -- especially the simple ones like Kolourpaint +// and the previous version of this routine in Krita took a brush +// shape -- often a simple ellipse -- and filled that shape with a +// random 'spray' of single pixels. +// +// Other, more advanced graphics apps, like the Gimp or Photoshop, +// take the brush shape and paint just as with the brush paint op, +// only making the initial dab more transparent, and perhaps adding +// extra transparence near the edges. Then, using a timer, when the +// cursor stays in place, dab upon dab is positioned in the same +// place, which makes the result less and less transparent. +// +// What I want to do here is create an airbrush that approaches a real +// one. It won't use brush shapes, instead going for the old-fashioned +// circle. Depending upon pressure, both the size of the dab and the +// rate of paint deposition is determined. The edges of the dab are +// more transparent than the center, with perhaps even some fully +// transparent pixels between the near-transparent pixels. +// +// By pressing some to-be-determined key at the same time as pressing +// mouse-down, one edge of the dab is made straight, to simulate +// working with a shield. +// +// Tilt may be used to make the gradients more realistic, but I don't +// have a tablet that supports tilt. +// +// Anyway, it's exactly twenty years ago that I have held a real +// airbrush, for the first and up to now the last time... +// + + if (!m_painter) return; + + KisPaintDeviceSP device = m_painter->device(); + + // For now: use the current brush shape -- it beats calculating + // ellipes and cones, and it shows the working of the timer. + if (!device) return; + + KisBrush * brush = m_painter->brush(); + if (! brush->canPaintFor(info) ) + return; + KisPaintDeviceSP dab = m_painter->dab(); + + KisPoint hotSpot = brush->hotSpot(info); + KisPoint pt = pos - hotSpot; + + Q_INT32 x; + double xFraction; + Q_INT32 y; + double yFraction; + + splitCoordinate(pt.x(), &x, &xFraction); + splitCoordinate(pt.y(), &y, &yFraction); + + if (brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) { + dab = brush->image(device->colorSpace(), info, xFraction, yFraction); + } + else { + KisAlphaMaskSP mask = brush->mask(info, xFraction, yFraction); + dab = computeDab(mask); + } + + m_painter->setDab(dab); // Cache dab for future paints in the painter. + m_painter->setPressure(info.pressure); // Cache pressure in the current painter. + + QRect dabRect = QRect(0, 0, brush->maskWidth(info), brush->maskHeight(info)); + QRect dstRect = QRect(x, y, dabRect.width(), dabRect.height()); + + KisImage * image = device->image(); + + if (image != 0) { + dstRect &= image->bounds(); + } + + if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; + + Q_INT32 sx = dstRect.x() - x; + Q_INT32 sy = dstRect.y() - y; + Q_INT32 sw = dstRect.width(); + Q_INT32 sh = dstRect.height(); + + if (m_source->hasSelection()) { + m_painter->bltSelection(dstRect.x(), dstRect.y(), m_painter->compositeOp(), dab.data(), + m_source->selection(), m_painter->opacity(), sx, sy, sw, sh); + } + else { + m_painter->bitBlt(dstRect.x(), dstRect.y(), m_painter->compositeOp(), dab.data(), m_painter->opacity(), sx, sy, sw, sh); + } + + m_painter->addDirtyRect(dstRect); +} diff --git a/krita/plugins/paintops/defaultpaintops/kis_airbrushop.h b/krita/plugins/paintops/defaultpaintops/kis_airbrushop.h new file mode 100644 index 00000000..7e751d3e --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_airbrushop.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002 Patrick Julien + * Copyright (c) 2004 Boudewijn Rempt + * Copyright (c) 2004 Clarence Dang + * Copyright (c) 2004 Adrian Page + * Copyright (c) 2004 Cyrille Berger + * + * 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_AIRBRUSHOP_H_ +#define KIS_AIRBRUSHOP_H_ + +#include "kis_paintop.h" + +class KisPoint; +class KisPainter; + +class KisAirbrushOpFactory : public KisPaintOpFactory { + +public: + KisAirbrushOpFactory() {} + virtual ~KisAirbrushOpFactory() {} + + virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter); + virtual KisID id() { return KisID("airbrush", i18n("Pixel Airbrush")); } + virtual QString pixmap() { return "airbrush.png"; } +}; + + + +class KisAirbrushOp : public KisPaintOp { + + typedef KisPaintOp super; + +public: + + KisAirbrushOp(KisPainter * painter); + virtual ~KisAirbrushOp(); + + // We want to spray even when the pointer doesn't move. + virtual bool incremental() { return true; } + + void paintAt(const KisPoint &pos, const KisPaintInformation& info); + +}; + +#endif // KIS_AIRBRUSHOP_H_ diff --git a/krita/plugins/paintops/defaultpaintops/kis_brushop.cc b/krita/plugins/paintops/defaultpaintops/kis_brushop.cc new file mode 100644 index 00000000..4a7485e5 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_brushop.cc @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2002 Patrick Julien + * Copyright (c) 2004 Boudewijn Rempt + * Copyright (c) 2004 Clarence Dang + * Copyright (c) 2004 Adrian Page + * Copyright (c) 2004 Cyrille Berger + * + * 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 "kcurve.h" +#include "kis_brush.h" +#include "kis_global.h" +#include "kis_paint_device.h" +#include "kis_layer.h" +#include "kis_painter.h" +#include "kis_types.h" +#include "kis_paintop.h" +#include "kis_input_device.h" +#include "kis_selection.h" +#include "kis_brushop.h" + +#include "kis_dlgbrushcurvecontrol.h" + +KisPaintOp * KisBrushOpFactory::createOp(const KisPaintOpSettings *settings, KisPainter * painter) +{ + const KisBrushOpSettings *brushopSettings = dynamic_cast(settings); + Q_ASSERT(settings == 0 || brushopSettings != 0); + + KisPaintOp * op = new KisBrushOp(brushopSettings, painter); + Q_CHECK_PTR(op); + return op; +} + +KisBrushOpSettings::KisBrushOpSettings(QWidget *parent) + : super(parent) +{ + m_optionsWidget = new QWidget(parent, "brush option widget"); + QHBoxLayout * l = new QHBoxLayout(m_optionsWidget); + l->setAutoAdd(true); + m_pressureVariation = new QLabel(i18n("Pressure variation: "), m_optionsWidget); + m_size = new QCheckBox(i18n("Size"), m_optionsWidget); + m_size->setChecked(true); + m_opacity = new QCheckBox(i18n("Opacity"), m_optionsWidget); + m_darken = new QCheckBox(i18n("Darken"), m_optionsWidget); + m_curveControl = new WdgBrushCurveControl(m_optionsWidget); + QToolButton* moreButton = new QToolButton(Qt::UpArrow, m_optionsWidget); + moreButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + moreButton->setMinimumSize(QSize(24,24)); // Bah, I had hoped the above line would make this unneeded + connect(moreButton, SIGNAL(clicked()), this, SLOT(slotCustomCurves())); + + m_customSize = false; + m_customOpacity = false; + m_customDarken = false; + // the curves will get filled in when the slot gets accepted +} + +void KisBrushOpSettings::slotCustomCurves() { + if (m_curveControl->exec() == QDialog::Accepted) { + m_customSize = m_curveControl->sizeCheckbox->isChecked(); + m_customOpacity = m_curveControl->opacityCheckbox->isChecked(); + m_customDarken = m_curveControl->darkenCheckbox->isChecked(); + + if (m_customSize) { + transferCurve(m_curveControl->sizeCurve, m_sizeCurve); + } + if (m_customOpacity) { + transferCurve(m_curveControl->opacityCurve, m_opacityCurve); + } + if (m_customDarken) { + transferCurve(m_curveControl->darkenCurve, m_darkenCurve); + } + } +} + +void KisBrushOpSettings::transferCurve(KCurve* curve, double* target) { + double value; + for (int i = 0; i < 256; i++) { + value = curve->getCurveValue( i / 255.0); + if (value < PRESSURE_MIN) + target[i] = PRESSURE_MIN; + else if (value > PRESSURE_MAX) + target[i] = PRESSURE_MAX; + else + target[i] = value; + } +} + + +bool KisBrushOpSettings::varySize() const +{ + return m_size->isChecked(); +} + +bool KisBrushOpSettings::varyOpacity() const +{ + return m_opacity->isChecked(); +} + +bool KisBrushOpSettings::varyDarken() const +{ + return m_darken->isChecked(); +} + +KisPaintOpSettings* KisBrushOpFactory::settings(QWidget * parent, const KisInputDevice& inputDevice) +{ + if (inputDevice == KisInputDevice::mouse()) { + // No options for mouse, only tablet devices + return 0; + } else { + return new KisBrushOpSettings(parent); + } +} + +KisBrushOp::KisBrushOp(const KisBrushOpSettings *settings, KisPainter *painter) + : super(painter) + , m_pressureSize(true) + , m_pressureOpacity(false) + , m_pressureDarken(false) + , m_customSize(false) + , m_customOpacity(false) + , m_customDarken(false) +{ + if (settings != 0) { + m_pressureSize = settings->varySize(); + painter->setVaryBrushSpacingWithPressureWhenDrawingALine( m_pressureSize ); + + m_pressureOpacity = settings->varyOpacity(); + m_pressureDarken = settings->varyDarken(); + m_customSize = settings->customSize(); + m_customOpacity = settings->customOpacity(); + m_customDarken = settings->customDarken(); + if (m_customSize) { + memcpy(m_sizeCurve, settings->sizeCurve(), 256 * sizeof(double)); + } + if (m_customOpacity) { + memcpy(m_opacityCurve, settings->opacityCurve(), 256 * sizeof(double)); + } + if (m_customDarken) { + memcpy(m_darkenCurve, settings->darkenCurve(), 256 * sizeof(double)); + } + } +} + +KisBrushOp::~KisBrushOp() +{ + m_painter->setVaryBrushSpacingWithPressureWhenDrawingALine( true ); +} + +void KisBrushOp::paintAt(const KisPoint &pos, const KisPaintInformation& info) +{ + KisPaintInformation adjustedInfo(info); + if (!m_pressureSize) + adjustedInfo.pressure = PRESSURE_DEFAULT; + else if (m_customSize) + adjustedInfo.pressure = scaleToCurve(adjustedInfo.pressure, m_sizeCurve); + + // Painting should be implemented according to the following algorithm: + // retrieve brush + // if brush == mask + // retrieve mask + // else if brush == image + // retrieve image + // subsample (mask | image) for position -- pos should be double! + // apply filters to mask (colour | gradient | pattern | etc. + // composite filtered mask into temporary layer + // composite temporary layer into target layer + // @see: doc/brush.txt + + if (!m_painter->device()) return; + + KisBrush *brush = m_painter->brush(); + + Q_ASSERT(brush); + if (!brush) return; + if (! brush->canPaintFor(adjustedInfo) ) + return; + + KisPaintDeviceSP device = m_painter->device(); + + KisPoint hotSpot = brush->hotSpot(adjustedInfo); + KisPoint pt = pos - hotSpot; + + // Split the coordinates into integer plus fractional parts. The integer + // is where the dab will be positioned and the fractional part determines + // the sub-pixel positioning. + Q_INT32 x; + double xFraction; + Q_INT32 y; + double yFraction; + + splitCoordinate(pt.x(), &x, &xFraction); + splitCoordinate(pt.y(), &y, &yFraction); + + KisPaintDeviceSP dab = 0; + + Q_UINT8 origOpacity = m_painter->opacity(); + KisColor origColor = m_painter->paintColor(); + + if (m_pressureOpacity) { + if (!m_customOpacity) + m_painter->setOpacity((Q_INT8)(origOpacity * info.pressure)); + else + m_painter->setOpacity((Q_INT8)(origOpacity * scaleToCurve(info.pressure, m_opacityCurve))); + } + + if (m_pressureDarken) { + KisColor darkened = origColor; + // Darken docs aren't really clear about what exactly the amount param can have as value... + Q_UINT32 darkenAmount; + if (!m_customDarken) + darkenAmount = (Q_INT32)(255 - 75 * info.pressure); + else + darkenAmount = (Q_INT32)(255 - 75 * scaleToCurve(info.pressure, m_darkenCurve)); + + darkened.colorSpace()->darken(origColor.data(), darkened.data(), + darkenAmount, false, 0.0, 1); + m_painter->setPaintColor(darkened); + } + + if (brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) { + dab = brush->image(device->colorSpace(), adjustedInfo, xFraction, yFraction); + } + else { + KisAlphaMaskSP mask = brush->mask(adjustedInfo, xFraction, yFraction); + dab = computeDab(mask); + } + + m_painter->setPressure(adjustedInfo.pressure); + + QRect dabRect = QRect(0, 0, brush->maskWidth(adjustedInfo), + brush->maskHeight(adjustedInfo)); + QRect dstRect = QRect(x, y, dabRect.width(), dabRect.height()); + + KisImage * image = device->image(); + + if (image != 0) { + dstRect &= image->bounds(); + } + + if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; + + Q_INT32 sx = dstRect.x() - x; + Q_INT32 sy = dstRect.y() - y; + Q_INT32 sw = dstRect.width(); + Q_INT32 sh = dstRect.height(); + + if (m_source->hasSelection()) { + m_painter->bltSelection(dstRect.x(), dstRect.y(), m_painter->compositeOp(), dab.data(), + m_source->selection(), m_painter->opacity(), sx, sy, sw, sh); + } + else { + m_painter->bitBlt(dstRect.x(), dstRect.y(), m_painter->compositeOp(), dab.data(), m_painter->opacity(), sx, sy, sw, sh); + } + m_painter->addDirtyRect(dstRect); + + m_painter->setOpacity(origOpacity); + m_painter->setPaintColor(origColor); +} + +#include "kis_brushop.moc" diff --git a/krita/plugins/paintops/defaultpaintops/kis_brushop.h b/krita/plugins/paintops/defaultpaintops/kis_brushop.h new file mode 100644 index 00000000..ecaf3ad2 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_brushop.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2002 Patrick Julien + * Copyright (c) 2004 Boudewijn Rempt + * Copyright (c) 2004 Clarence Dang + * Copyright (c) 2004 Adrian Page + * Copyright (c) 2004 Cyrille Berger + * + * 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_BRUSHOP_H_ +#define KIS_BRUSHOP_H_ + +#include "kis_paintop.h" + +class QWidget; +class QCheckBox; +class QLabel; +class KisPoint; +class KisPainter; +class KCurve; +class WdgBrushCurveControl; + +class KisBrushOpFactory : public KisPaintOpFactory { + +public: + KisBrushOpFactory() {} + virtual ~KisBrushOpFactory() {} + + virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter); + virtual KisID id() { return KisID("paintbrush", i18n("Pixel Brush")); } + virtual QString pixmap() { return "paintbrush.png"; } + virtual KisPaintOpSettings *settings(QWidget * parent, const KisInputDevice& inputDevice); +}; + +class KisBrushOpSettings : public QObject, public KisPaintOpSettings { + Q_OBJECT + typedef KisPaintOpSettings super; +public: + KisBrushOpSettings(QWidget *parent); + + bool varySize() const; + bool varyOpacity() const; + bool varyDarken() const; + + bool customSize() const { return m_customSize; } + bool customOpacity() const { return m_customOpacity; } + bool customDarken() const { return m_customDarken; } + const double* sizeCurve() const { return m_sizeCurve; } + const double* opacityCurve() const { return m_opacityCurve; } + const double* darkenCurve() const { return m_darkenCurve; } + + virtual QWidget *widget() const { return m_optionsWidget; } +private slots: + void slotCustomCurves(); +private: + void transferCurve(KCurve* curve, double* target); + QWidget *m_optionsWidget; + QLabel * m_pressureVariation; + QCheckBox * m_size; + QCheckBox * m_opacity; + QCheckBox * m_darken; + WdgBrushCurveControl* m_curveControl; + + bool m_customSize; + bool m_customOpacity; + bool m_customDarken; + double m_sizeCurve[256]; + double m_opacityCurve[256]; + double m_darkenCurve[256]; +}; + +class KisBrushOp : public KisPaintOp { + + typedef KisPaintOp super; + +public: + + KisBrushOp(const KisBrushOpSettings *settings, KisPainter * painter); + virtual ~KisBrushOp(); + + void paintAt(const KisPoint &pos, const KisPaintInformation& info); + +private: + inline double scaleToCurve(double pressure, double* curve) const { + int offset = CLAMP(int(255.0 * pressure), 0, 255); + return curve[offset]; + } + bool m_pressureSize; + bool m_pressureOpacity; + bool m_pressureDarken; + bool m_customSize; + bool m_customOpacity; + bool m_customDarken; + double m_sizeCurve[256]; + double m_opacityCurve[256]; + double m_darkenCurve[256]; +}; + +#endif // KIS_BRUSHOP_H_ diff --git a/krita/plugins/paintops/defaultpaintops/kis_convolveop.cc b/krita/plugins/paintops/defaultpaintops/kis_convolveop.cc new file mode 100644 index 00000000..ae55f54f --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_convolveop.cc @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2002 Patrick Julien + * Copyright (c) 2004 Boudewijn Rempt + * Copyright (c) 2004 Clarence Dang + * Copyright (c) 2004 Adrian Page + * Copyright (c) 2004 Cyrille Berger + * + * 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 "kis_brush.h" +#include "kis_global.h" +#include "kis_paint_device.h" +#include "kis_painter.h" +#include "kis_layer.h" +#include "kis_types.h" +#include "kis_paintop.h" +#include "kis_selection.h" +#include "kis_convolveop.h" + + +KisPaintOp * KisConvolveOpFactory::createOp(const KisPaintOpSettings */*settings*/, KisPainter * painter) +{ + KisPaintOp * op = new KisConvolveOp(painter); + Q_CHECK_PTR(op); + return op; +} + + +KisConvolveOp::KisConvolveOp(KisPainter * painter) + : super(painter) +{ +} + +KisConvolveOp::~KisConvolveOp() +{ +} + +void KisConvolveOp::paintAt(const KisPoint &/*pos*/, const KisPaintInformation& /*info*/) +{ + // XXX: use convolve painter here. + +} diff --git a/krita/plugins/paintops/defaultpaintops/kis_convolveop.h b/krita/plugins/paintops/defaultpaintops/kis_convolveop.h new file mode 100644 index 00000000..d5dc3764 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_convolveop.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002 Patrick Julien + * Copyright (c) 2004 Boudewijn Rempt + * Copyright (c) 2004 Clarence Dang + * Copyright (c) 2004 Adrian Page + * Copyright (c) 2004 Cyrille Berger + * + * 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_CONVOLVEOP_H_ +#define KIS_CONVOLVEOP_H_ + +#include "kis_paintop.h" + +class KisPoint; +class KisPainter; + + +class KisConvolveOpFactory : public KisPaintOpFactory { + +public: + KisConvolveOpFactory() {} + virtual ~KisConvolveOpFactory() {} + + virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter); + virtual KisID id() { return KisID("convolve", i18n("Convolve")); } +}; + + +class KisConvolveOp : public KisPaintOp { + + typedef KisPaintOp super; + +public: + + KisConvolveOp(KisPainter * painter); + virtual ~KisConvolveOp(); + + void paintAt(const KisPoint &pos, const KisPaintInformation& info); + +}; + +#endif // KIS_CONVOLVEOP_H_ diff --git a/krita/plugins/paintops/defaultpaintops/kis_dlgbrushcurvecontrol.ui b/krita/plugins/paintops/defaultpaintops/kis_dlgbrushcurvecontrol.ui new file mode 100644 index 00000000..7682c12f --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_dlgbrushcurvecontrol.ui @@ -0,0 +1,271 @@ + +WdgBrushCurveControl + + + WdgBrushCurveControl + + + + 0 + 0 + 477 + 430 + + + + Custom Curves + + + true + + + + unnamed + + + + tabWidget + + + + Widget8 + + + Size Curve + + + + unnamed + + + + layout4 + + + + unnamed + + + + sizeCheckbox + + + Use custom curve + + + + + sizeCurve + + + + 7 + 7 + 0 + 0 + + + + + + + + + + Widget9 + + + Opacity Curve + + + + unnamed + + + + layout3 + + + + unnamed + + + + opacityCheckbox + + + Use custom curve + + + + + opacityCurve + + + + 7 + 7 + 0 + 0 + + + + + + + + + + TabPage + + + Darken Curve + + + + unnamed + + + + layout5 + + + + unnamed + + + + darkenCheckbox + + + Use custom curve + + + + + darkenCurve + + + + 7 + 7 + 0 + 0 + + + + + + + + + + + Layout1 + + + + unnamed + + + 0 + + + 6 + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + buttonOk + + + &OK + + + + + + true + + + true + + + + + buttonCancel + + + &Cancel + + + + + + true + + + + + + + + + KCurve +
kcurve.h
+ + -1 + -1 + + 0 + + 5 + 5 + 0 + 0 + + image0 +
+
+ + + 89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082 + + + + + buttonOk + clicked() + WdgBrushCurveControl + accept() + + + buttonCancel + clicked() + WdgBrushCurveControl + reject() + + + + + kcurve.h + kcurve.h + kcurve.h + +
diff --git a/krita/plugins/paintops/defaultpaintops/kis_duplicateop.cc b/krita/plugins/paintops/defaultpaintops/kis_duplicateop.cc new file mode 100644 index 00000000..79d00b96 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_duplicateop.cc @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2002 Patrick Julien + * Copyright (c) 2004 Boudewijn Rempt + * Copyright (c) 2004 Clarence Dang + * Copyright (c) 2004 Adrian Page + * Copyright (c) 2004-2006 Cyrille Berger + * + * 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_duplicateop.h" + +#include + +#include + +#include "kis_brush.h" +#include "kis_global.h" +#include "kis_paint_device.h" +#include "kis_layer.h" +#include "kis_painter.h" +#include "kis_types.h" +#include "kis_meta_registry.h" +#include "kis_colorspace_factory_registry.h" +#include "kis_paintop.h" +#include "kis_iterators_pixel.h" +#include "kis_selection.h" +#include "kis_perspective_grid.h" +#include "kis_random_sub_accessor.h" + +KisPaintOp * KisDuplicateOpFactory::createOp(const KisPaintOpSettings */*settings*/, KisPainter * painter) +{ + KisPaintOp * op = new KisDuplicateOp(painter); + Q_CHECK_PTR(op); + return op; +} + + +KisDuplicateOp::KisDuplicateOp(KisPainter * painter) + : super(painter) + , m_target(0) + , m_srcdev(0) +{ +} + +KisDuplicateOp::~KisDuplicateOp() +{ +} + +double KisDuplicateOp::minimizeEnergy(const double* m, double* sol, int w, int h) +{ + int rowstride = 3*w; + double err = 0; + memcpy(sol, m, 3* sizeof(double) * w); + m+=rowstride; + sol+=rowstride; + for ( int i = 1; i < h - 1; i++) + { + memcpy(sol, m, 3* sizeof(double)); + m+=3; sol+=3; + for ( int j = 3; j < rowstride-3; j++) + { + double tmp = *sol; + *sol = ( ( *(m - 3 ) + *(m + 3) + *(m - rowstride ) + *(m + rowstride )) + 2 * *m ) /6; + double diff = *sol - tmp; + err += diff*diff; + m ++; sol ++; + } + memcpy(sol, m, 3* sizeof(double)); + m+=3; sol+=3; +} + memcpy(sol, m, 3* sizeof(double) * w); + return err; +} + + +void KisDuplicateOp::paintAt(const KisPoint &pos, const KisPaintInformation& info) +{ + if (!m_painter) return; + + bool heal = m_painter->duplicateHealing(); +// int healradius = m_painter->duplicateHealingRadius(); + + KisPaintDeviceSP device = m_painter->device(); + if (m_source) device = m_source; + if (!device) return; + + KisBrush * brush = m_painter->brush(); + if (!brush) return; + if (! brush->canPaintFor(info) ) + return; + + KisPoint hotSpot = brush->hotSpot(info); + KisPoint pt = pos - hotSpot; + + // Split the coordinates into integer plus fractional parts. The integer + // is where the dab will be positioned and the fractional part determines + // the sub-pixel positioning. + Q_INT32 x; + double xFraction; + Q_INT32 y; + double yFraction; + + splitCoordinate(pt.x(), &x, &xFraction); + splitCoordinate(pt.y(), &y, &yFraction); + xFraction = yFraction = 0.0; + + KisPaintDeviceSP dab = 0; + + if (brush->brushType() == IMAGE || + brush->brushType() == PIPE_IMAGE) { + dab = brush->image(device->colorSpace(), info, xFraction, yFraction); + dab->convertTo(KisMetaRegistry::instance()->csRegistry()->getAlpha8()); + } + else { + KisAlphaMaskSP mask = brush->mask(info, xFraction, yFraction); + dab = computeDab(mask, KisMetaRegistry::instance()->csRegistry()->getAlpha8()); + } + + m_painter->setPressure(info.pressure); + + KisPoint srcPointF = pt - m_painter->duplicateOffset(); + QPoint srcPoint = QPoint(x - static_cast(m_painter->duplicateOffset().x()), + y - static_cast(m_painter->duplicateOffset().y())); + + + Q_INT32 sw = dab->extent().width(); + Q_INT32 sh = dab->extent().height(); + + if (srcPoint.x() < 0 ) + srcPoint.setX(0); + + if( srcPoint.y() < 0) + srcPoint.setY(0); + if( !(m_srcdev && m_srcdev->colorSpace() != device->colorSpace()) ) + { + m_srcdev = new KisPaintDevice(device->colorSpace(), "duplicate source dev"); + m_target = new KisPaintDevice(device->colorSpace(), "duplicate target dev"); + } + Q_CHECK_PTR(m_srcdev); + + // Perspective correction ? + KisPainter copyPainter(m_srcdev); + if(m_painter->duplicatePerspectiveCorrection()) + { + double startM[3][3]; + double endM[3][3]; + for(int i = 0; i < 3; i++) + { + for(int j = 0; j < 3; j++) + { + startM[i][j] = 0.; + endM[i][j] = 0.; + } + startM[i][i] = 1.; + endM[i][i] = 1.; + } + // First look for the grid corresponding to the start point + KisSubPerspectiveGrid* subGridStart = *device->image()->perspectiveGrid()->begin();//device->image()->perspectiveGrid()->gridAt(KisPoint(srcPoint.x() +hotSpot.x(),srcPoint.y() +hotSpot.y())); + QRect r = QRect(0,0, device->image()->width(), device->image()->height()); + +#if 1 + if(subGridStart) + { +// kdDebug() << "fgrid" << endl; +// kdDebug() << *subGridStart->topLeft() << " " << *subGridStart->topRight() << " " << *subGridStart->bottomLeft() << " " << *subGridStart->bottomRight() << endl; + double* b = KisPerspectiveMath::computeMatrixTransfoFromPerspective( r, *subGridStart->topLeft(), *subGridStart->topRight(), *subGridStart->bottomLeft(), *subGridStart->bottomRight()); + for(int i = 0; i < 3; i++) + { + for(int j = 0; j < 3; j++) + { +// kdDebug() << "sol[" << 3*i+j << "]=" << b[3*i+j] << endl; + startM[i][j] = b[3*i+j]; + } + } + + } +#endif +#if 1 + // Second look for the grid corresponding to the end point + KisSubPerspectiveGrid* subGridEnd = *device->image()->perspectiveGrid()->begin();// device->image()->perspectiveGrid()->gridAt(pos); + if(subGridEnd) + { +// kdDebug() << "second grid" << endl; + double* b = KisPerspectiveMath::computeMatrixTransfoToPerspective(*subGridEnd->topLeft(), *subGridEnd->topRight(), *subGridEnd->bottomLeft(), *subGridEnd->bottomRight(), r); + for(int i = 0; i < 3; i++) + { + for(int j = 0; j < 3; j++) + { +// kdDebug() << "sol[" << 3*i+j << "]=" << b[3*i+j] << endl; + endM[i][j] = b[3*i+j]; + } + } + } +#endif +// kdDebug()<< " oouuuuh" << srcPointF << KisPerspectiveMath::matProd(startM, KisPerspectiveMath::matProd(endM, srcPointF ) ) << KisPerspectiveMath::matProd(endM, KisPerspectiveMath::matProd(startM, srcPointF ) ); + + // Compute the translation in the perspective transformation space: + KisPoint positionStartPaintingT = KisPerspectiveMath::matProd(endM, m_painter->duplicateStart() ); + KisPoint duplicateStartPoisitionT = KisPerspectiveMath::matProd(endM, m_painter->duplicateStart() - m_painter->duplicateOffset() ); + KisPoint translat = duplicateStartPoisitionT - positionStartPaintingT; + KisRectIteratorPixel dstIt = m_srcdev->createRectIterator(0, 0, sw, sh, true); + KisRandomSubAccessorPixel srcAcc = device->createRandomSubAccessor(); + //Action + while(!dstIt.isDone()) + { + if(dstIt.isSelected()) + { + KisPoint p = KisPerspectiveMath::matProd(startM, KisPerspectiveMath::matProd(endM, KisPoint(dstIt.x() + x, dstIt.y() + y) ) + translat ); + srcAcc.moveTo( p ); + srcAcc.sampledOldRawData( dstIt.rawData() ); + } + ++dstIt; + } + + + } else { + // Or, copy the source data on the temporary device: + copyPainter.bitBlt(0, 0, COMPOSITE_COPY, device, srcPoint.x(), srcPoint.y(), sw, sh); + copyPainter.end(); + } + + // heal ? + + if(heal) + { + Q_UINT16 dataDevice[4]; + Q_UINT16 dataSrcDev[4]; + QMemArray matrix ( 3 * sw * sh ); + // First divide + KisColorSpace* deviceCs = device->colorSpace(); + KisHLineIteratorPixel deviceIt = device->createHLineIterator(x, y, sw, false ); + KisHLineIteratorPixel srcDevIt = m_srcdev->createHLineIterator(0, 0, sw, true ); + double* matrixIt = &matrix[0]; + for(int j = 0; j < sh; j++) + { + for(int i= 0; !srcDevIt.isDone(); i++) + { + deviceCs->toLabA16(deviceIt.rawData(), (Q_UINT8*)dataDevice, 1); + deviceCs->toLabA16(srcDevIt.rawData(), (Q_UINT8*)dataSrcDev, 1); + // Division + for( int k = 0; k < 3; k++) + { + matrixIt[k] = dataDevice[k] / (double)QMAX(dataSrcDev [k], 1); + } + ++deviceIt; + ++srcDevIt; + matrixIt +=3; + } + deviceIt.nextRow(); + srcDevIt.nextRow(); + } + // Minimize energy + { + int iter = 0; + double err; + QMemArray solution ( 3 * sw * sh ); + do { + err = minimizeEnergy(&matrix[0], &solution[0],sw,sh); + memcpy (&matrix[0], &solution[0], sw * sh * 3 * sizeof(double)); + iter++; + } while( err < 0.00001 && iter < 100); + } + + // Finaly multiply + deviceIt = device->createHLineIterator(x, y, sw, false ); + srcDevIt = m_srcdev->createHLineIterator(0, 0, sw, true ); + matrixIt = &matrix[0]; + for(int j = 0; j < sh; j++) + { + for(int i= 0; !srcDevIt.isDone(); i++) + { + deviceCs->toLabA16(deviceIt.rawData(), (Q_UINT8*)dataDevice, 1); + deviceCs->toLabA16(srcDevIt.rawData(), (Q_UINT8*)dataSrcDev, 1); + // Multiplication + for( int k = 0; k < 3; k++) + { + dataSrcDev[k] = (int)CLAMP( matrixIt[k] * QMAX( dataSrcDev[k], 1), 0, 65535 ); + } + deviceCs->fromLabA16((Q_UINT8*)dataSrcDev, srcDevIt.rawData(), 1); + ++deviceIt; + ++srcDevIt; + matrixIt +=3; + } + deviceIt.nextRow(); + srcDevIt.nextRow(); + } + } + + + // Add the dab as selection to the srcdev +// KisPainter copySelection(srcdev->selection().data()); +// copySelection.bitBlt(0, 0, COMPOSITE_OVER, dab, 0, 0, sw, sh); +// copySelection.end(); + + // copy the srcdev onto a new device, after applying the dab selection + copyPainter.begin(m_target); + + copyPainter.bltMask(0, 0, COMPOSITE_OVER, m_srcdev, dab, + OPACITY_OPAQUE, 0, 0, sw, sh); + copyPainter.end(); + + QRect dabRect = QRect(0, 0, brush->maskWidth(info), brush->maskHeight(info)); + QRect dstRect = QRect(x, y, dabRect.width(), dabRect.height()); + + KisImage * image = device->image(); + + if (image != 0) { + dstRect &= image->bounds(); + } + + if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; + + Q_INT32 sx = dstRect.x() - x; + Q_INT32 sy = dstRect.y() - y; + sw = dstRect.width(); + sh = dstRect.height(); + + if (m_source->hasSelection()) { + m_painter->bltSelection(dstRect.x(), dstRect.y(), m_painter->compositeOp(), m_target, + m_source->selection(), m_painter->opacity(), sx, sy, sw, sh); + } + else { + m_painter->bitBlt(dstRect.x(), dstRect.y(), m_painter->compositeOp(), m_target, m_painter->opacity(), sx, sy, sw, sh); + } + + + m_painter->addDirtyRect(dstRect); +} diff --git a/krita/plugins/paintops/defaultpaintops/kis_duplicateop.h b/krita/plugins/paintops/defaultpaintops/kis_duplicateop.h new file mode 100644 index 00000000..965e0dc9 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_duplicateop.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2002 Patrick Julien + * Copyright (c) 2004 Boudewijn Rempt + * Copyright (c) 2004 Clarence Dang + * Copyright (c) 2004 Adrian Page + * Copyright (c) 2004 Cyrille Berger + * + * 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_DUPLICATEOP_H_ +#define KIS_DUPLICATEOP_H_ + +#include "kis_paintop.h" + +class KisPoint; +class KisPainter; + +class KisDuplicateOpFactory : public KisPaintOpFactory { + +public: + KisDuplicateOpFactory() {} + virtual ~KisDuplicateOpFactory() {} + + virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter); + virtual KisID id() { return KisID("duplicate", i18n("Duplicate")); } + virtual bool userVisible(KisColorSpace *) { return false; } + +}; + +class KisDuplicateOp : public KisPaintOp { + + typedef KisPaintOp super; + + + public: + + KisDuplicateOp(KisPainter * painter); + virtual ~KisDuplicateOp(); + + + void paintAt(const KisPoint &pos, const KisPaintInformation& info); + private: + double minimizeEnergy(const double* m, double* sol, int w, int h); + private: + KisPaintDeviceSP m_target, m_srcdev; + +}; + +#endif // KIS_DUPLICATEOP_H_ diff --git a/krita/plugins/paintops/defaultpaintops/kis_eraseop.cc b/krita/plugins/paintops/defaultpaintops/kis_eraseop.cc new file mode 100644 index 00000000..4fe46af2 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_eraseop.cc @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2002 Patrick Julien + * Copyright (c) 2004 Boudewijn Rempt + * Copyright (c) 2004 Clarence Dang + * Copyright (c) 2004 Adrian Page + * Copyright (c) 2004 Cyrille Berger + * + * 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 "kis_brush.h" +#include "kis_global.h" +#include "kis_paint_device.h" +#include "kis_layer.h" +#include "kis_painter.h" +#include "kis_types.h" +#include "kis_paintop.h" +#include "kis_iterators_pixel.h" +#include "kis_colorspace.h" +#include "kis_selection.h" +#include "kis_eraseop.h" + +KisPaintOp * KisEraseOpFactory::createOp(const KisPaintOpSettings */*settings*/, KisPainter * painter) +{ + KisPaintOp * op = new KisEraseOp(painter); + Q_CHECK_PTR(op); + return op; +} + + +KisEraseOp::KisEraseOp(KisPainter * painter) + : super(painter) +{ +} + +KisEraseOp::~KisEraseOp() +{ +} + +void KisEraseOp::paintAt(const KisPoint &pos, const KisPaintInformation& info) +{ +// Erasing is traditionally in paint applications one of two things: +// either it is painting in the 'background' color, or it is replacing +// all pixels with transparent (black?) pixels. +// +// That's what this paint op does for now; however, anyone who has +// ever worked with paper and soft pencils knows that a sharp piece of +// eraser rubber is a pretty useful too for making sharp to fuzzy lines +// in the graphite layer, or equally useful: for smudging skin tones. +// +// A smudge tool for Krita is in the making, but when working with +// a tablet, the eraser tip should be at least as functional as a rubber eraser. +// That means that only after repeated or forceful application should all the +// 'paint' or 'graphite' be removed from the surface -- a kind of pressure +// sensitive, incremental smudge. +// +// And there should be an option to not have the eraser work on certain +// kinds of material. Layers are just a hack for this; putting your ink work +// in one layer and your pencil in another is not the same as really working +// with the combination. + + if (!m_painter) return; + + KisPaintDeviceSP device = m_painter->device(); + if (!device) return; + + KisBrush *brush = m_painter->brush(); + if (! brush->canPaintFor(info) ) + return; + KisPoint hotSpot = brush->hotSpot(info); + KisPoint pt = pos - hotSpot; + + Q_INT32 destX; + double xFraction; + Q_INT32 destY; + double yFraction; + + splitCoordinate(pt.x(), &destX, &xFraction); + splitCoordinate(pt.y(), &destY, &yFraction); + + KisAlphaMaskSP mask = brush->mask(info, xFraction, yFraction); + + KisPaintDeviceSP dab = new KisPaintDevice(device->colorSpace(), "erase op dab"); + Q_CHECK_PTR(dab); + + Q_INT32 maskWidth = mask->width(); + Q_INT32 maskHeight = mask->height(); + + QRect dstRect; + + KisRectIteratorPixel it = dab->createRectIterator(0, 0, maskWidth, maskHeight, true); + KisColorSpace* cs = dab->colorSpace(); + while (!it.isDone()) { + cs->setAlpha(it.rawData(), Q_UINT8_MAX - mask->alphaAt(it.x(), it.y()), 1); + ++it; + } + + QRect dabRect = QRect(0, 0, maskWidth, maskHeight); + dstRect = QRect(destX, destY, dabRect.width(), dabRect.height()); + + KisImage * image = device->image(); + + if (image != 0) { + dstRect &= image->bounds(); + } + + if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; + + Q_INT32 sx = dstRect.x() - destX; + Q_INT32 sy = dstRect.y() - destY; + Q_INT32 sw = dstRect.width(); + Q_INT32 sh = dstRect.height(); + + if (m_source->hasSelection()) { + m_painter->bltSelection(dstRect.x(), dstRect.y(), COMPOSITE_ERASE, dab.data(), + m_source->selection(), m_painter->opacity(), sx, sy, sw, sh); + } + else { + m_painter->bitBlt(dstRect.x(), dstRect.y(), COMPOSITE_ERASE, dab.data(), m_painter->opacity(), sx, sy, sw, sh); + } + + m_painter->addDirtyRect(dstRect); +} + diff --git a/krita/plugins/paintops/defaultpaintops/kis_eraseop.h b/krita/plugins/paintops/defaultpaintops/kis_eraseop.h new file mode 100644 index 00000000..c15d11b3 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_eraseop.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002 Patrick Julien + * Copyright (c) 2004 Boudewijn Rempt + * Copyright (c) 2004 Clarence Dang + * Copyright (c) 2004 Adrian Page + * Copyright (c) 2004 Cyrille Berger + * + * 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_ERASEOP_H_ +#define KIS_ERASEOP_H_ + +#include "kis_paintop.h" + +class KisPoint; +class KisPainter; + +class KisEraseOpFactory : public KisPaintOpFactory { + +public: + KisEraseOpFactory() {} + virtual ~KisEraseOpFactory() {} + + virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter); + virtual KisID id() { return KisID("eraser", i18n("Pixel Eraser")); } + virtual QString pixmap() { return "eraser.png"; } +}; + + +class KisEraseOp : public KisPaintOp { + + typedef KisPaintOp super; + +public: + + KisEraseOp(KisPainter * painter); + virtual ~KisEraseOp(); + + void paintAt(const KisPoint &pos, const KisPaintInformation& info); + +}; + +#endif // KIS_ERASEOP_H_ diff --git a/krita/plugins/paintops/defaultpaintops/kis_penop.cc b/krita/plugins/paintops/defaultpaintops/kis_penop.cc new file mode 100644 index 00000000..d93a75d4 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_penop.cc @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2002 Patrick Julien + * Copyright (c) 2004 Boudewijn Rempt + * Copyright (c) 2004 Clarence Dang + * Copyright (c) 2004 Adrian Page + * Copyright (c) 2004 Cyrille Berger + * + * 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 "kis_brush.h" +#include "kis_global.h" +#include "kis_paint_device.h" +#include "klocale.h" +#include "kis_layer.h" +#include "kis_painter.h" +#include "kis_types.h" +#include "kis_paintop.h" +#include "kis_iterator.h" +#include "kis_selection.h" +#include "kis_iterators_pixel.h" + +#include "kis_penop.h" + + +KisPaintOp * KisPenOpFactory::createOp(const KisPaintOpSettings */*settings*/, KisPainter * painter) +{ + KisPaintOp * op = new KisPenOp(painter); + Q_CHECK_PTR(op); + return op; +} + + +KisPenOp::KisPenOp(KisPainter * painter) + : super(painter) +{ +} + +KisPenOp::~KisPenOp() +{ +} + +void KisPenOp::paintAt(const KisPoint &pos, const KisPaintInformation& info) +{ + if (!m_painter) return; + KisPaintDeviceSP device = m_painter->device(); + if (!device) return; + KisBrush * brush = m_painter->brush(); + if (!brush) return; + if (! brush->canPaintFor(info) ) + return; + + KisPoint hotSpot = brush->hotSpot(info); + KisPoint pt = pos - hotSpot; + + Q_INT32 x = pt.roundX(); + Q_INT32 y = pt.roundY(); + + KisPaintDeviceSP dab = 0; + if (brush->brushType() == IMAGE || + brush->brushType() == PIPE_IMAGE) { + dab = brush->image(device->colorSpace(), info); + } + else { + // Compute mask without sub-pixel positioning + KisAlphaMaskSP mask = brush->mask(info); + dab = computeDab(mask); + } + + m_painter->setPressure(info.pressure); + QRect dabRect = QRect(0, 0, brush->maskWidth(info), brush->maskHeight(info)); + QRect dstRect = QRect(x, y, dabRect.width(), dabRect.height()); + + KisImage * image = device->image(); + + if (image != 0) { + dstRect &= image->bounds(); + } + + if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; + + KisColorSpace * 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. + + KisRectIteratorPixel pixelIt = dab->createRectIterator(dabRect.x(), dabRect.y(), dabRect.width(), dabRect.height(), true); + + while (!pixelIt.isDone()) { + Q_UINT8 alpha = cs->getAlpha(pixelIt.rawData()); + + if (alpha < (4 * OPACITY_OPAQUE) / 10) { + cs->setAlpha(pixelIt.rawData(), OPACITY_TRANSPARENT, 1); + } else { + cs->setAlpha(pixelIt.rawData(), OPACITY_OPAQUE, 1); + } + + ++pixelIt; + } + + Q_INT32 sx = dstRect.x() - x; + Q_INT32 sy = dstRect.y() - y; + Q_INT32 sw = dstRect.width(); + Q_INT32 sh = dstRect.height(); + + if (m_source->hasSelection()) { + m_painter->bltSelection(dstRect.x(), dstRect.y(), m_painter->compositeOp(), dab.data(), + m_source->selection(), m_painter->opacity(), sx, sy, sw, sh); + } + else { + m_painter->bitBlt(dstRect.x(), dstRect.y(), m_painter->compositeOp(), dab.data(), m_painter->opacity(), sx, sy, sw, sh); + } + + m_painter->addDirtyRect(dstRect); +} diff --git a/krita/plugins/paintops/defaultpaintops/kis_penop.h b/krita/plugins/paintops/defaultpaintops/kis_penop.h new file mode 100644 index 00000000..f548bed5 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_penop.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2002 Patrick Julien + * Copyright (c) 2004 Boudewijn Rempt + * Copyright (c) 2004 Clarence Dang + * Copyright (c) 2004 Adrian Page + * Copyright (c) 2004 Cyrille Berger + * + * 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_PENOP_H_ +#define KIS_PENOP_H_ + +#include +#include +#include "kis_paintop.h" + +class KisPoint; +class KisPainter; + +class KisPenOpFactory : public KisPaintOpFactory { + +public: + KisPenOpFactory() {} + virtual ~KisPenOpFactory() {} + + virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter); + virtual KisID id(){ return KisID("pen", i18n("Pixel Pencil")); } + virtual QString pixmap() { return "pencil.png"; } +}; + + +class KisPenOp : public KisPaintOp { + + typedef KisPaintOp super; + +public: + + KisPenOp(KisPainter * painter); + virtual ~KisPenOp(); + + void paintAt(const KisPoint &pos, const KisPaintInformation& info); + +}; + +#endif // KIS_PENOP_H_ diff --git a/krita/plugins/paintops/defaultpaintops/kis_smudgeop.cc b/krita/plugins/paintops/defaultpaintops/kis_smudgeop.cc new file mode 100644 index 00000000..a339c062 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_smudgeop.cc @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2006 Cyrille Berger + * + * 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_smudgeop.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "kis_colorspace_factory_registry.h" +#include "kcurve.h" +#include "kis_brush.h" +#include "kis_global.h" +#include "kis_paint_device.h" +#include "kis_layer.h" +#include "kis_meta_registry.h" +#include "kis_painter.h" +#include "kis_types.h" +#include "kis_paintop.h" +#include "kis_input_device.h" +#include "kis_selection.h" + +#include "kis_dlgbrushcurvecontrol.h" + +KisPaintOp * KisSmudgeOpFactory::createOp(const KisPaintOpSettings *settings, KisPainter * painter) +{ + const KisSmudgeOpSettings *brushopSettings = dynamic_cast(settings); + Q_ASSERT(settings == 0 || brushopSettings != 0); + + KisPaintOp * op = new KisSmudgeOp(brushopSettings, painter); + Q_CHECK_PTR(op); + return op; +} + +KisSmudgeOpSettings::KisSmudgeOpSettings(QWidget *parent, bool isTablet) + : super(parent) +{ + m_optionsWidget = new QWidget(parent, "brush option widget"); + QHBoxLayout * l = new QHBoxLayout(m_optionsWidget); + l->setAutoAdd(true); + m_rateLabel = new QLabel(i18n("Rate: "), m_optionsWidget); + m_rateSlider = new QSlider(0,100,1, 50, Qt::Horizontal, m_optionsWidget); + if(isTablet) + { + m_pressureVariation = new QLabel(i18n("Pressure variation: "), m_optionsWidget); + m_size = new QCheckBox(i18n("Size"), m_optionsWidget); + m_size->setChecked(true); + m_opacity = new QCheckBox(i18n("Opacity"), m_optionsWidget); + m_rate = new QCheckBox(i18n("Rate"), m_optionsWidget); + m_curveControl = new WdgBrushCurveControl(m_optionsWidget); + // We abuse the darken curve here for rate + m_curveControl->tabWidget->setTabLabel(m_curveControl->tabWidget->page(2), i18n("Rate")); + m_curveControl->tabWidget->setTabToolTip(m_curveControl->tabWidget->page(2), + i18n("Modifies the rate. Bottom is 0% of the rate top is 100% of the original rate.")); + QToolButton* moreButton = new QToolButton(Qt::UpArrow, m_optionsWidget); + moreButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + moreButton->setMinimumSize(QSize(24,24)); // Bah, I had hoped the above line would make this unneeded + connect(moreButton, SIGNAL(clicked()), this, SLOT(slotCustomCurves())); + } else { + m_pressureVariation = 0; + m_size = 0; + m_rate = 0; + m_opacity = 0; + m_curveControl = 0; + } + + m_customRate = false; + m_customSize = false; + m_customOpacity = false; + // the curves will get filled in when the slot gets accepted +} + +void KisSmudgeOpSettings::slotCustomCurves() { + if (m_curveControl->exec() == QDialog::Accepted) { + m_customRate = m_curveControl->darkenCheckbox->isChecked(); + m_customSize = m_curveControl->sizeCheckbox->isChecked(); + m_customOpacity = m_curveControl->opacityCheckbox->isChecked(); + + if (m_customRate) { + transferCurve(m_curveControl->darkenCurve, m_rateCurve); + } + if (m_customSize) { + transferCurve(m_curveControl->sizeCurve, m_sizeCurve); + } + if (m_customOpacity) { + transferCurve(m_curveControl->opacityCurve, m_opacityCurve); + } + } +} + +void KisSmudgeOpSettings::transferCurve(KCurve* curve, double* target) { + double value; + for (int i = 0; i < 256; i++) { + value = curve->getCurveValue( i / 255.0); + if (value < PRESSURE_MIN) + target[i] = PRESSURE_MIN; + else if (value > PRESSURE_MAX) + target[i] = PRESSURE_MAX; + else + target[i] = value; + } +} + +int KisSmudgeOpSettings::rate() const +{ + return m_rateSlider->value(); +} + +bool KisSmudgeOpSettings::varyRate() const +{ + return m_rate ? m_rate->isChecked() : false; +} + +bool KisSmudgeOpSettings::varySize() const +{ + return m_size ? m_size->isChecked() : true; +} + +bool KisSmudgeOpSettings::varyOpacity() const +{ + return m_opacity ? m_opacity->isChecked() : false; +} + +KisPaintOpSettings* KisSmudgeOpFactory::settings(QWidget * parent, const KisInputDevice& inputDevice) +{ + if (inputDevice == KisInputDevice::mouse()) { + // No options for mouse, only tablet devices + return new KisSmudgeOpSettings(parent, false); + } else { + return new KisSmudgeOpSettings(parent, true); + } +} + +KisSmudgeOp::KisSmudgeOp(const KisSmudgeOpSettings *settings, KisPainter *painter) + : super(painter) + , m_firstRun(true) + , m_rate(50) + , m_pressureSize(true) + , m_pressureRate(false) + , m_pressureOpacity(false) + , m_customRate(false) + , m_customSize(false) + , m_customOpacity(false) + , m_target(0) + , m_srcdev(0) +{ + if (settings != 0) { + m_rate = settings->rate(); + m_pressureRate = settings->varyRate(); + m_pressureSize = settings->varySize(); + m_pressureOpacity = settings->varyOpacity(); + m_customRate = settings->customRate(); + m_customSize = settings->customSize(); + m_customOpacity = settings->customOpacity(); + if (m_customSize) { + memcpy(m_sizeCurve, settings->sizeCurve(), 256 * sizeof(double)); + } + if (m_customOpacity) { + memcpy(m_opacityCurve, settings->opacityCurve(), 256 * sizeof(double)); + } + if (m_customRate) { + memcpy(m_rateCurve, settings->rateCurve(), 256 * sizeof(double)); + } + } + KisPaintDeviceSP device = m_painter->device(); + m_srcdev = new KisPaintDevice(device->colorSpace(), "duplicate source dev"); + m_target = new KisPaintDevice(device->colorSpace(), "duplicate target dev"); +} + +KisSmudgeOp::~KisSmudgeOp() +{ +} + +void KisSmudgeOp::paintAt(const KisPoint &pos, const KisPaintInformation& info) +{ + KisPaintInformation adjustedInfo(info); + if (!m_pressureSize) + adjustedInfo.pressure = PRESSURE_DEFAULT; + else if (m_customSize) + adjustedInfo.pressure = scaleToCurve(adjustedInfo.pressure, m_sizeCurve); + + // Painting should be implemented according to the following algorithm: + // retrieve brush + // if brush == mask + // retrieve mask + // else if brush == image + // retrieve image + // subsample (mask | image) for position -- pos should be double! + // apply filters to mask (colour | gradient | pattern | etc. + // composite filtered mask into temporary layer + // composite temporary layer into target layer + // @see: doc/brush.txt + + if (!m_painter->device()) return; + + KisBrush *brush = m_painter->brush(); + + Q_ASSERT(brush); + if (!brush) return; + if (! brush->canPaintFor(adjustedInfo) ) + return; + + KisPaintDeviceSP device = m_painter->device(); + + KisPoint hotSpot = brush->hotSpot(adjustedInfo); + KisPoint pt = pos - hotSpot; + + // Split the coordinates into integer plus fractional parts. The integer + // is where the dab will be positioned and the fractional part determines + // the sub-pixel positioning. + Q_INT32 x; + double xFraction; + Q_INT32 y; + double yFraction; + + splitCoordinate(pt.x(), &x, &xFraction); + splitCoordinate(pt.y(), &y, &yFraction); + + KisPaintDeviceSP dab = 0; + + Q_UINT8 origOpacity = m_painter->opacity(); + + if (m_pressureOpacity) { + if (!m_customOpacity) + m_painter->setOpacity((Q_INT8)(origOpacity * info.pressure)); + else + m_painter->setOpacity((Q_INT8)(origOpacity * scaleToCurve(info.pressure, m_opacityCurve))); + } + + if (brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) { + dab = brush->image(device->colorSpace(), adjustedInfo, xFraction, yFraction); + dab->convertTo(KisMetaRegistry::instance()->csRegistry()->getAlpha8()); + } + else { + KisAlphaMaskSP mask = brush->mask(adjustedInfo, xFraction, yFraction); + dab = computeDab(mask, KisMetaRegistry::instance()->csRegistry()->getAlpha8()); + } + + + m_painter->setPressure(adjustedInfo.pressure); + + QRect dabRect = QRect(0, 0, brush->maskWidth(adjustedInfo), + brush->maskHeight(adjustedInfo)); + QRect dstRect = QRect(x, y, dabRect.width(), dabRect.height()); + + KisImage * image = device->image(); + + if (image != 0) { + dstRect &= image->bounds(); + } + + Q_INT32 sw = dab->extent().width(); + Q_INT32 sh = dab->extent().height(); + + KisPainter copyPainter(m_srcdev); + int opacity = OPACITY_OPAQUE; + if(!m_firstRun) + { + opacity = rate(); + if (m_pressureRate) { + if (m_customRate) { + opacity = CLAMP((Q_UINT8)(double(opacity) * scaleToCurve(info.pressure, m_rateCurve)), OPACITY_TRANSPARENT, OPACITY_OPAQUE); + } else { + opacity = CLAMP((Q_UINT8)(double(opacity) * info.pressure), OPACITY_TRANSPARENT, OPACITY_OPAQUE); + } + } + opacity = OPACITY_OPAQUE - opacity; + } else { + m_firstRun = false; + } + copyPainter.bitBlt(0, 0, COMPOSITE_OVER, device, opacity, pt.x(), pt.y(), sw, sh); + copyPainter.end(); + + m_target = new KisPaintDevice(device->colorSpace(), "duplicate target dev"); + + copyPainter.begin(m_target); + + copyPainter.bltMask(0, 0, COMPOSITE_OVER, m_srcdev, dab, + OPACITY_OPAQUE, 0, 0, sw, sh); + copyPainter.end(); + + + if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; + + Q_INT32 sx = dstRect.x() - x; + Q_INT32 sy = dstRect.y() - y; + sw = dstRect.width(); + sh = dstRect.height(); + + if (m_source->hasSelection()) { + m_painter->bltSelection(dstRect.x(), dstRect.y(), m_painter->compositeOp(), m_target, + m_source->selection(), m_painter->opacity(), sx, sy, sw, sh); + } + else { + m_painter->bitBlt(dstRect.x(), dstRect.y(), m_painter->compositeOp(), m_target, m_painter->opacity(), sx, sy, sw, sh); + } + + m_painter->addDirtyRect(dstRect); + + m_painter->setOpacity(origOpacity); + +} + +#include "kis_smudgeop.moc" diff --git a/krita/plugins/paintops/defaultpaintops/kis_smudgeop.h b/krita/plugins/paintops/defaultpaintops/kis_smudgeop.h new file mode 100644 index 00000000..26a82e07 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kis_smudgeop.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2006 Cyrille Berger + * + * 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_SMUDGEOP_H_ +#define KIS_SMUDGEOP_H_ + +#include "kis_paintop.h" +#include + +class QWidget; +class QCheckBox; +class QLabel; +class QSlider; +class KisPoint; +class KisPainter; +class KCurve; +class WdgBrushCurveControl; + +class KisSmudgeOpFactory : public KisPaintOpFactory { + +public: + KisSmudgeOpFactory() {} + virtual ~KisSmudgeOpFactory() {} + + virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter); + virtual KisID id() { return KisID("smudge", i18n("Smudge Brush")); } + virtual QString pixmap() { return "paintbrush.png"; } + virtual KisPaintOpSettings *settings(QWidget * parent, const KisInputDevice& inputDevice); +}; + +class KisSmudgeOpSettings : public QObject, public KisPaintOpSettings { + Q_OBJECT + typedef KisPaintOpSettings super; +public: + KisSmudgeOpSettings(QWidget *parent, bool isTablet); + + int rate() const; + bool varyRate() const; + bool varySize() const; + bool varyOpacity() const; + + bool customRate() const { return m_customRate; } + bool customSize() const { return m_customSize; } + bool customOpacity() const { return m_customOpacity; } + const double* rateCurve() const { return m_rateCurve; } + const double* sizeCurve() const { return m_sizeCurve; } + const double* opacityCurve() const { return m_opacityCurve; } + + virtual QWidget *widget() const { return m_optionsWidget; } +private slots: + void slotCustomCurves(); +private: + void transferCurve(KCurve* curve, double* target); + QWidget *m_optionsWidget; + QLabel* m_rateLabel; + QSlider* m_rateSlider; + QLabel * m_pressureVariation; + QCheckBox * m_rate; + QCheckBox * m_size; + QCheckBox * m_opacity; + WdgBrushCurveControl* m_curveControl; + + bool m_customSize; + bool m_customRate; + bool m_customOpacity; + double m_rateCurve[256]; + double m_sizeCurve[256]; + double m_opacityCurve[256]; +}; + +class KisSmudgeOp : public KisPaintOp { + + typedef KisPaintOp super; + +public: + + KisSmudgeOp(const KisSmudgeOpSettings *settings, KisPainter * painter); + virtual ~KisSmudgeOp(); + + void paintAt(const KisPoint &pos, const KisPaintInformation& info); + + int rate() { return (m_rate * 255) / 100; } +private: + KisPaintDeviceSP m_target, m_srcdev; + inline double scaleToCurve(double pressure, double* curve) const { + int offset = CLAMP(int(255.0 * pressure), 0, 255); + return curve[offset]; + } + bool m_firstRun; + int m_rate; + bool m_pressureRate; + bool m_pressureSize; + bool m_pressureOpacity; + bool m_customRate; + bool m_customSize; + bool m_customOpacity; + double m_rateCurve[256]; + double m_sizeCurve[256]; + double m_opacityCurve[256]; +}; + +#endif // KIS_BRUSHOP_H_ diff --git a/krita/plugins/paintops/defaultpaintops/kritadefaultpaintops.desktop b/krita/plugins/paintops/defaultpaintops/kritadefaultpaintops.desktop new file mode 100644 index 00000000..95982cd4 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/kritadefaultpaintops.desktop @@ -0,0 +1,93 @@ +[Desktop Entry] +Name=Default Paint Operations +Name[bg]=Операции за рисуване по подразбиране +Name[ca]=Operacions de pintura per defecte +Name[cy]=Gweithrediadau Paent Rhagosodol +Name[da]=Standard maleoperationer +Name[de]=Standard Maloperation +Name[el]=Προκαθορισμένες λειτουργίες ζωγραφικής +Name[eo]=Aprioraj pentrooperacioj +Name[es]=Operaciones de pintura predefinidas +Name[et]=Vaikimisi joonistamistoimingud +Name[eu]=Margotze-eragiketa lehenetsiak +Name[fa]=عملیات رنگ‌آمیزی پیش‌فرض +Name[fi]=Oletusväritystoimenpiteet +Name[fr]=Opérations de dessin par défaut +Name[fy]=Standertskilderaksjes +Name[ga]=Oibríochtaí Réamhshocraithe Péinteála +Name[gl]=Operacións de Pintura Predefinidas +Name[he]=פעולות הצביעה המוגדרות כברירת מחדל +Name[hu]=Alapértelmezett festési műveletek +Name[is]=Sjálfgefnar málunaraðgerðir +Name[it]=Operazioni predefinite di disegno +Name[ja]=標準の描画操作 +Name[km]=ប្រតិបត្តិការ​គូរ​លំនាំដើម +Name[ms]=Operasi Cat Piawai +Name[nb]=Standard maleteknikker +Name[nds]=Standard-Maalakschonen +Name[ne]=पूर्वनिर्धारित पेन्ट सञ्चालन +Name[nl]=Standaardschilderoperaties +Name[nn]=Standard måleoperasjonar +Name[pl]=Domyślne operacje na obrazkach +Name[pt]=Operações de Pintura Predefinidas +Name[pt_BR]=Operações de pintura padrão +Name[ru]=Стандартные инструменты рисования +Name[se]=Standárda málendoaimmat +Name[sk]=Štandardné operácie kreslenia +Name[sl]=Privzete operacije za slikanje +Name[sr]=Подразумеване сликарске операције +Name[sr@Latn]=Podrazumevane slikarske operacije +Name[sv]=Förvalda målningsåtgärder +Name[uk]=Типові дії малювання +Name[uz]=Andoza chizish amallari +Name[uz@cyrillic]=Андоза чизиш амаллари +Name[zh_CN]=默认绘图操作 +Name[zh_TW]=預設繪圖操作 +Comment=Default paint operations +Comment[bg]=Операции за рисуване по подразбиране +Comment[ca]=Operacions de pintura per defecte +Comment[cy]=Gweithrediadau paent rhagosodol +Comment[da]=Standard maleoperationer +Comment[de]=Standard Maloperation +Comment[el]=Προκαθορισμένες λειτουργίες ζωγραφικής +Comment[eo]=Aprioraj pentrooperacioj +Comment[es]=Operaciones de pintado predefinidas +Comment[et]=Vaikimisi joonistamistoimingud +Comment[eu]=Margotze-eragiketa lehenetsiak +Comment[fa]=عملیات رنگ‌آمیزی پیش‌فرض +Comment[fi]=Oletusväritystoimenpiteet +Comment[fr]=Opérations de dessin par défaut +Comment[fy]=Standertskilderaksjes +Comment[ga]=Oibríochtaí réamhshocraithe péinteála +Comment[gl]=Operacións de pintura predefinidas +Comment[he]=פעולות הצביעה המוגדרות כברירת מחדל +Comment[hu]=Alapértelmezett festési műveletek +Comment[is]=Sjálfgefnar málunaraðgerðir +Comment[it]=Operazioni predefinite di disegno +Comment[ja]=標準の描画操作 +Comment[km]=ប្រតិបត្តិកា​គូរ​លំនាំ​ដើម​ +Comment[ms]=Operasi cat piawai +Comment[nb]=Standard maleteknikker +Comment[nds]=Standard-Maalakschonen +Comment[ne]=पूर्वनिर्धारित पेन्ट सञ्चालन +Comment[nl]=Standaardschilderoperaties +Comment[nn]=Standard måleoperasjonar +Comment[pl]=Domyślne operacje na obrazkach +Comment[pt]=Operações de pintura predefinidas +Comment[pt_BR]=Operações de pintura padrão +Comment[ru]=Инструменты рисования по умолчанию +Comment[se]=Standárda málendoaimmat +Comment[sk]=Štandardné operácie kreslenia +Comment[sl]=Privzete operacije za slikanje +Comment[sr]=Подразумеване сликарске операције +Comment[sr@Latn]=Podrazumevane slikarske operacije +Comment[sv]=Förvalda målningsåtgärder +Comment[uk]=Типові дії малювання +Comment[uz]=Andoza chizish amallari +Comment[uz@cyrillic]=Андоза чизиш амаллари +Comment[zh_CN]=默认绘图操作 +Comment[zh_TW]=預設繪圖操作 +ServiceTypes=Krita/Paintop +Type=Service +X-KDE-Library=kritadefaultpaintops +X-Krita-Version=2 diff --git a/krita/plugins/paintops/defaultpaintops/paintbrush.png b/krita/plugins/paintops/defaultpaintops/paintbrush.png new file mode 100644 index 00000000..089567e3 Binary files /dev/null and b/krita/plugins/paintops/defaultpaintops/paintbrush.png differ diff --git a/krita/plugins/paintops/defaultpaintops/pencil.png b/krita/plugins/paintops/defaultpaintops/pencil.png new file mode 100644 index 00000000..5af23ad6 Binary files /dev/null and b/krita/plugins/paintops/defaultpaintops/pencil.png differ diff --git a/krita/plugins/paintops/defaultpaintops/src/README b/krita/plugins/paintops/defaultpaintops/src/README new file mode 100644 index 00000000..769ced65 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/src/README @@ -0,0 +1,2 @@ +These svg images are the basis of the paintop pixmaps; they were taken from +the OpenClipArt repository and are in the public domain. diff --git a/krita/plugins/paintops/defaultpaintops/src/pencil_01.svg b/krita/plugins/paintops/defaultpaintops/src/pencil_01.svg new file mode 100644 index 00000000..40319104 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/src/pencil_01.svg @@ -0,0 +1,637 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pencil + + + + + office + + + + + Karol Szczerba + + + + + Karol Szczerba + + + + + Karol Szczerba + + + + image/svg+xml + + + + + en + + + + + + + + + diff --git a/krita/plugins/paintops/defaultpaintops/src/pencil_jonathan_dietrich_01.svg b/krita/plugins/paintops/defaultpaintops/src/pencil_jonathan_dietrich_01.svg new file mode 100644 index 00000000..4b29bb9a --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/src/pencil_jonathan_dietrich_01.svg @@ -0,0 +1,434 @@ + + + + + + + + Pencil + HASH(0x885a0cc) + + + pencil + + + + + Jonathan Dietrich + + + + + Jonathan Dietrich + + + + + Jonathan Dietrich + + + HASH(0x846b07c) + image/svg+xml + + + en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/krita/plugins/paintops/defaultpaintops/src/pennello_mauro_olivo_01.svg b/krita/plugins/paintops/defaultpaintops/src/pennello_mauro_olivo_01.svg new file mode 100644 index 00000000..b79fcd57 --- /dev/null +++ b/krita/plugins/paintops/defaultpaintops/src/pennello_mauro_olivo_01.svg @@ -0,0 +1,616 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pennello + Created with The Inkscape + + + + office + + + + + Mauro Olivo + + + + + Mauro Olivo + + + + + Mauro Olivo + + + + image/svg+xml + + + + + en + + + + + + + + + -- cgit v1.2.1