From 8b78a8791bc539bcffe7159f9d9714d577cb3d7d Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sun, 23 May 2021 20:48:35 +0900 Subject: Renaming of files in preparation for code style tools. Signed-off-by: Michele Calgaro --- chalk/plugins/paintops/defaultpaintops/Makefile.am | 14 +- .../defaultpaintops/defaultpaintops_plugin.cc | 70 ----- .../defaultpaintops/defaultpaintops_plugin.cpp | 70 +++++ .../paintops/defaultpaintops/kis_airbrushop.cc | 150 --------- .../paintops/defaultpaintops/kis_airbrushop.cpp | 150 +++++++++ .../paintops/defaultpaintops/kis_brushop.cc | 284 ----------------- .../paintops/defaultpaintops/kis_brushop.cpp | 284 +++++++++++++++++ .../paintops/defaultpaintops/kis_convolveop.cc | 58 ---- .../paintops/defaultpaintops/kis_convolveop.cpp | 58 ++++ .../paintops/defaultpaintops/kis_duplicateop.cc | 341 --------------------- .../paintops/defaultpaintops/kis_duplicateop.cpp | 341 +++++++++++++++++++++ .../paintops/defaultpaintops/kis_eraseop.cc | 140 --------- .../paintops/defaultpaintops/kis_eraseop.cpp | 140 +++++++++ .../plugins/paintops/defaultpaintops/kis_penop.cc | 132 -------- .../plugins/paintops/defaultpaintops/kis_penop.cpp | 132 ++++++++ .../paintops/defaultpaintops/kis_smudgeop.cc | 328 -------------------- .../paintops/defaultpaintops/kis_smudgeop.cpp | 328 ++++++++++++++++++++ 17 files changed, 1510 insertions(+), 1510 deletions(-) delete mode 100644 chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cc create mode 100644 chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cpp delete mode 100644 chalk/plugins/paintops/defaultpaintops/kis_airbrushop.cc create mode 100644 chalk/plugins/paintops/defaultpaintops/kis_airbrushop.cpp delete mode 100644 chalk/plugins/paintops/defaultpaintops/kis_brushop.cc create mode 100644 chalk/plugins/paintops/defaultpaintops/kis_brushop.cpp delete mode 100644 chalk/plugins/paintops/defaultpaintops/kis_convolveop.cc create mode 100644 chalk/plugins/paintops/defaultpaintops/kis_convolveop.cpp delete mode 100644 chalk/plugins/paintops/defaultpaintops/kis_duplicateop.cc create mode 100644 chalk/plugins/paintops/defaultpaintops/kis_duplicateop.cpp delete mode 100644 chalk/plugins/paintops/defaultpaintops/kis_eraseop.cc create mode 100644 chalk/plugins/paintops/defaultpaintops/kis_eraseop.cpp delete mode 100644 chalk/plugins/paintops/defaultpaintops/kis_penop.cc create mode 100644 chalk/plugins/paintops/defaultpaintops/kis_penop.cpp delete mode 100644 chalk/plugins/paintops/defaultpaintops/kis_smudgeop.cc create mode 100644 chalk/plugins/paintops/defaultpaintops/kis_smudgeop.cpp (limited to 'chalk/plugins/paintops') diff --git a/chalk/plugins/paintops/defaultpaintops/Makefile.am b/chalk/plugins/paintops/defaultpaintops/Makefile.am index 31acf6e0..84e2a408 100644 --- a/chalk/plugins/paintops/defaultpaintops/Makefile.am +++ b/chalk/plugins/paintops/defaultpaintops/Makefile.am @@ -18,14 +18,14 @@ INCLUDES = -I$(srcdir)/../../../sdk \ chalkdefaultpaintops_la_SOURCES = \ - defaultpaintops_plugin.cc \ - kis_airbrushop.cc \ - kis_brushop.cc \ - kis_duplicateop.cc \ - kis_eraseop.cc \ - kis_penop.cc \ + defaultpaintops_plugin.cpp \ + kis_airbrushop.cpp \ + kis_brushop.cpp \ + kis_duplicateop.cpp \ + kis_eraseop.cpp \ + kis_penop.cpp \ kis_dlgbrushcurvecontrol.ui \ - kis_smudgeop.cc + kis_smudgeop.cpp noinst_HEADERS = defaultpaintops_plugin.h kis_airbrushop.h kis_brushop.h \ kis_duplicateop.h kis_eraseop.h kis_penop.h kis_smudgeop.h diff --git a/chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cc b/chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cc deleted file mode 100644 index 25f12b87..00000000 --- a/chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* - * defaultpaintops_plugin.cc -- Part of Chalk - * - * 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( chalkdefaultpaintops, DefaultPaintOpsPluginFactory( "chalkcore" ) ) - - -DefaultPaintOpsPlugin::DefaultPaintOpsPlugin(TQObject *parent, const char *name, const TQStringList &) - : 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/chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cpp b/chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cpp new file mode 100644 index 00000000..6e1d3f75 --- /dev/null +++ b/chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cpp @@ -0,0 +1,70 @@ +/* + * defaultpaintops_plugin.cpp -- Part of Chalk + * + * 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( chalkdefaultpaintops, DefaultPaintOpsPluginFactory( "chalkcore" ) ) + + +DefaultPaintOpsPlugin::DefaultPaintOpsPlugin(TQObject *parent, const char *name, const TQStringList &) + : 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/chalk/plugins/paintops/defaultpaintops/kis_airbrushop.cc b/chalk/plugins/paintops/defaultpaintops/kis_airbrushop.cc deleted file mode 100644 index 2a8750f3..00000000 --- a/chalk/plugins/paintops/defaultpaintops/kis_airbrushop.cc +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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); - TQ_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 Chalk 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; - - TQ_INT32 x; - double xFraction; - TQ_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. - - TQRect dabRect = TQRect(0, 0, brush->maskWidth(info), brush->maskHeight(info)); - TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height()); - - KisImage * image = device->image(); - - if (image != 0) { - dstRect &= image->bounds(); - } - - if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; - - TQ_INT32 sx = dstRect.x() - x; - TQ_INT32 sy = dstRect.y() - y; - TQ_INT32 sw = dstRect.width(); - TQ_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/chalk/plugins/paintops/defaultpaintops/kis_airbrushop.cpp b/chalk/plugins/paintops/defaultpaintops/kis_airbrushop.cpp new file mode 100644 index 00000000..2a8750f3 --- /dev/null +++ b/chalk/plugins/paintops/defaultpaintops/kis_airbrushop.cpp @@ -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); + TQ_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 Chalk 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; + + TQ_INT32 x; + double xFraction; + TQ_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. + + TQRect dabRect = TQRect(0, 0, brush->maskWidth(info), brush->maskHeight(info)); + TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height()); + + KisImage * image = device->image(); + + if (image != 0) { + dstRect &= image->bounds(); + } + + if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; + + TQ_INT32 sx = dstRect.x() - x; + TQ_INT32 sy = dstRect.y() - y; + TQ_INT32 sw = dstRect.width(); + TQ_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/chalk/plugins/paintops/defaultpaintops/kis_brushop.cc b/chalk/plugins/paintops/defaultpaintops/kis_brushop.cc deleted file mode 100644 index 285b4d6f..00000000 --- a/chalk/plugins/paintops/defaultpaintops/kis_brushop.cc +++ /dev/null @@ -1,284 +0,0 @@ -/* - * 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); - TQ_CHECK_PTR(op); - return op; -} - -KisBrushOpSettings::KisBrushOpSettings(TQWidget *parent) - : super(parent) -{ - m_optionsWidget = new TQWidget(parent, "brush option widget"); - TQHBoxLayout * l = new TQHBoxLayout(m_optionsWidget); - l->setAutoAdd(true); - m_pressureVariation = new TQLabel(i18n("Pressure variation: "), m_optionsWidget); - m_size = new TQCheckBox(i18n("Size"), m_optionsWidget); - m_size->setChecked(true); - m_opacity = new TQCheckBox(i18n("Opacity"), m_optionsWidget); - m_darken = new TQCheckBox(i18n("Darken"), m_optionsWidget); - m_curveControl = new WdgBrushCurveControl(m_optionsWidget); - TQToolButton* moreButton = new TQToolButton(TQt::UpArrow, m_optionsWidget); - moreButton->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding); - moreButton->setMinimumSize(TQSize(24,24)); // Bah, I had hoped the above line would make this unneeded - connect(moreButton, TQT_SIGNAL(clicked()), this, TQT_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() == TQDialog::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(TQWidget * 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. - TQ_INT32 x; - double xFraction; - TQ_INT32 y; - double yFraction; - - splitCoordinate(pt.x(), &x, &xFraction); - splitCoordinate(pt.y(), &y, &yFraction); - - KisPaintDeviceSP dab = 0; - - TQ_UINT8 origOpacity = m_painter->opacity(); - KisColor origColor = m_painter->paintColor(); - - if (m_pressureOpacity) { - if (!m_customOpacity) - m_painter->setOpacity((TQ_INT8)(origOpacity * info.pressure)); - else - m_painter->setOpacity((TQ_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... - TQ_UINT32 darkenAmount; - if (!m_customDarken) - darkenAmount = (TQ_INT32)(255 - 75 * info.pressure); - else - darkenAmount = (TQ_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); - - TQRect dabRect = TQRect(0, 0, brush->maskWidth(adjustedInfo), - brush->maskHeight(adjustedInfo)); - TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height()); - - KisImage * image = device->image(); - - if (image != 0) { - dstRect &= image->bounds(); - } - - if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; - - TQ_INT32 sx = dstRect.x() - x; - TQ_INT32 sy = dstRect.y() - y; - TQ_INT32 sw = dstRect.width(); - TQ_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/chalk/plugins/paintops/defaultpaintops/kis_brushop.cpp b/chalk/plugins/paintops/defaultpaintops/kis_brushop.cpp new file mode 100644 index 00000000..285b4d6f --- /dev/null +++ b/chalk/plugins/paintops/defaultpaintops/kis_brushop.cpp @@ -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); + TQ_CHECK_PTR(op); + return op; +} + +KisBrushOpSettings::KisBrushOpSettings(TQWidget *parent) + : super(parent) +{ + m_optionsWidget = new TQWidget(parent, "brush option widget"); + TQHBoxLayout * l = new TQHBoxLayout(m_optionsWidget); + l->setAutoAdd(true); + m_pressureVariation = new TQLabel(i18n("Pressure variation: "), m_optionsWidget); + m_size = new TQCheckBox(i18n("Size"), m_optionsWidget); + m_size->setChecked(true); + m_opacity = new TQCheckBox(i18n("Opacity"), m_optionsWidget); + m_darken = new TQCheckBox(i18n("Darken"), m_optionsWidget); + m_curveControl = new WdgBrushCurveControl(m_optionsWidget); + TQToolButton* moreButton = new TQToolButton(TQt::UpArrow, m_optionsWidget); + moreButton->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding); + moreButton->setMinimumSize(TQSize(24,24)); // Bah, I had hoped the above line would make this unneeded + connect(moreButton, TQT_SIGNAL(clicked()), this, TQT_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() == TQDialog::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(TQWidget * 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. + TQ_INT32 x; + double xFraction; + TQ_INT32 y; + double yFraction; + + splitCoordinate(pt.x(), &x, &xFraction); + splitCoordinate(pt.y(), &y, &yFraction); + + KisPaintDeviceSP dab = 0; + + TQ_UINT8 origOpacity = m_painter->opacity(); + KisColor origColor = m_painter->paintColor(); + + if (m_pressureOpacity) { + if (!m_customOpacity) + m_painter->setOpacity((TQ_INT8)(origOpacity * info.pressure)); + else + m_painter->setOpacity((TQ_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... + TQ_UINT32 darkenAmount; + if (!m_customDarken) + darkenAmount = (TQ_INT32)(255 - 75 * info.pressure); + else + darkenAmount = (TQ_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); + + TQRect dabRect = TQRect(0, 0, brush->maskWidth(adjustedInfo), + brush->maskHeight(adjustedInfo)); + TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height()); + + KisImage * image = device->image(); + + if (image != 0) { + dstRect &= image->bounds(); + } + + if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; + + TQ_INT32 sx = dstRect.x() - x; + TQ_INT32 sy = dstRect.y() - y; + TQ_INT32 sw = dstRect.width(); + TQ_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/chalk/plugins/paintops/defaultpaintops/kis_convolveop.cc b/chalk/plugins/paintops/defaultpaintops/kis_convolveop.cc deleted file mode 100644 index 708d792c..00000000 --- a/chalk/plugins/paintops/defaultpaintops/kis_convolveop.cc +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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); - TQ_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/chalk/plugins/paintops/defaultpaintops/kis_convolveop.cpp b/chalk/plugins/paintops/defaultpaintops/kis_convolveop.cpp new file mode 100644 index 00000000..708d792c --- /dev/null +++ b/chalk/plugins/paintops/defaultpaintops/kis_convolveop.cpp @@ -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); + TQ_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/chalk/plugins/paintops/defaultpaintops/kis_duplicateop.cc b/chalk/plugins/paintops/defaultpaintops/kis_duplicateop.cc deleted file mode 100644 index 556a7775..00000000 --- a/chalk/plugins/paintops/defaultpaintops/kis_duplicateop.cc +++ /dev/null @@ -1,341 +0,0 @@ -/* - * 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); - TQ_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. - TQ_INT32 x; - double xFraction; - TQ_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(); - TQPoint srcPoint = TQPoint(x - static_cast(m_painter->duplicateOffset().x()), - y - static_cast(m_painter->duplicateOffset().y())); - - - TQ_INT32 sw = dab->extent().width(); - TQ_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"); - } - TQ_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())); - TQRect r = TQRect(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) - { - TQ_UINT16 dataDevice[4]; - TQ_UINT16 dataSrcDev[4]; - TQMemArray 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(), (TQ_UINT8*)dataDevice, 1); - deviceCs->toLabA16(srcDevIt.rawData(), (TQ_UINT8*)dataSrcDev, 1); - // Division - for( int k = 0; k < 3; k++) - { - matrixIt[k] = dataDevice[k] / (double)TQMAX(dataSrcDev [k], 1); - } - ++deviceIt; - ++srcDevIt; - matrixIt +=3; - } - deviceIt.nextRow(); - srcDevIt.nextRow(); - } - // Minimize energy - { - int iter = 0; - double err; - TQMemArray 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(), (TQ_UINT8*)dataDevice, 1); - deviceCs->toLabA16(srcDevIt.rawData(), (TQ_UINT8*)dataSrcDev, 1); - // Multiplication - for( int k = 0; k < 3; k++) - { - dataSrcDev[k] = (int)CLAMP( matrixIt[k] * TQMAX( dataSrcDev[k], 1), 0, 65535 ); - } - deviceCs->fromLabA16((TQ_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(); - - TQRect dabRect = TQRect(0, 0, brush->maskWidth(info), brush->maskHeight(info)); - TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height()); - - KisImage * image = device->image(); - - if (image != 0) { - dstRect &= image->bounds(); - } - - if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; - - TQ_INT32 sx = dstRect.x() - x; - TQ_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/chalk/plugins/paintops/defaultpaintops/kis_duplicateop.cpp b/chalk/plugins/paintops/defaultpaintops/kis_duplicateop.cpp new file mode 100644 index 00000000..556a7775 --- /dev/null +++ b/chalk/plugins/paintops/defaultpaintops/kis_duplicateop.cpp @@ -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); + TQ_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. + TQ_INT32 x; + double xFraction; + TQ_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(); + TQPoint srcPoint = TQPoint(x - static_cast(m_painter->duplicateOffset().x()), + y - static_cast(m_painter->duplicateOffset().y())); + + + TQ_INT32 sw = dab->extent().width(); + TQ_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"); + } + TQ_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())); + TQRect r = TQRect(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) + { + TQ_UINT16 dataDevice[4]; + TQ_UINT16 dataSrcDev[4]; + TQMemArray 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(), (TQ_UINT8*)dataDevice, 1); + deviceCs->toLabA16(srcDevIt.rawData(), (TQ_UINT8*)dataSrcDev, 1); + // Division + for( int k = 0; k < 3; k++) + { + matrixIt[k] = dataDevice[k] / (double)TQMAX(dataSrcDev [k], 1); + } + ++deviceIt; + ++srcDevIt; + matrixIt +=3; + } + deviceIt.nextRow(); + srcDevIt.nextRow(); + } + // Minimize energy + { + int iter = 0; + double err; + TQMemArray 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(), (TQ_UINT8*)dataDevice, 1); + deviceCs->toLabA16(srcDevIt.rawData(), (TQ_UINT8*)dataSrcDev, 1); + // Multiplication + for( int k = 0; k < 3; k++) + { + dataSrcDev[k] = (int)CLAMP( matrixIt[k] * TQMAX( dataSrcDev[k], 1), 0, 65535 ); + } + deviceCs->fromLabA16((TQ_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(); + + TQRect dabRect = TQRect(0, 0, brush->maskWidth(info), brush->maskHeight(info)); + TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height()); + + KisImage * image = device->image(); + + if (image != 0) { + dstRect &= image->bounds(); + } + + if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; + + TQ_INT32 sx = dstRect.x() - x; + TQ_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/chalk/plugins/paintops/defaultpaintops/kis_eraseop.cc b/chalk/plugins/paintops/defaultpaintops/kis_eraseop.cc deleted file mode 100644 index 55e3b7b8..00000000 --- a/chalk/plugins/paintops/defaultpaintops/kis_eraseop.cc +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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); - TQ_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 Chalk 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; - - TQ_INT32 destX; - double xFraction; - TQ_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"); - TQ_CHECK_PTR(dab); - - TQ_INT32 maskWidth = mask->width(); - TQ_INT32 maskHeight = mask->height(); - - TQRect dstRect; - - KisRectIteratorPixel it = dab->createRectIterator(0, 0, maskWidth, maskHeight, true); - KisColorSpace* cs = dab->colorSpace(); - while (!it.isDone()) { - cs->setAlpha(it.rawData(), TQ_UINT8_MAX - mask->alphaAt(it.x(), it.y()), 1); - ++it; - } - - TQRect dabRect = TQRect(0, 0, maskWidth, maskHeight); - dstRect = TQRect(destX, destY, dabRect.width(), dabRect.height()); - - KisImage * image = device->image(); - - if (image != 0) { - dstRect &= image->bounds(); - } - - if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; - - TQ_INT32 sx = dstRect.x() - destX; - TQ_INT32 sy = dstRect.y() - destY; - TQ_INT32 sw = dstRect.width(); - TQ_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/chalk/plugins/paintops/defaultpaintops/kis_eraseop.cpp b/chalk/plugins/paintops/defaultpaintops/kis_eraseop.cpp new file mode 100644 index 00000000..55e3b7b8 --- /dev/null +++ b/chalk/plugins/paintops/defaultpaintops/kis_eraseop.cpp @@ -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); + TQ_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 Chalk 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; + + TQ_INT32 destX; + double xFraction; + TQ_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"); + TQ_CHECK_PTR(dab); + + TQ_INT32 maskWidth = mask->width(); + TQ_INT32 maskHeight = mask->height(); + + TQRect dstRect; + + KisRectIteratorPixel it = dab->createRectIterator(0, 0, maskWidth, maskHeight, true); + KisColorSpace* cs = dab->colorSpace(); + while (!it.isDone()) { + cs->setAlpha(it.rawData(), TQ_UINT8_MAX - mask->alphaAt(it.x(), it.y()), 1); + ++it; + } + + TQRect dabRect = TQRect(0, 0, maskWidth, maskHeight); + dstRect = TQRect(destX, destY, dabRect.width(), dabRect.height()); + + KisImage * image = device->image(); + + if (image != 0) { + dstRect &= image->bounds(); + } + + if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; + + TQ_INT32 sx = dstRect.x() - destX; + TQ_INT32 sy = dstRect.y() - destY; + TQ_INT32 sw = dstRect.width(); + TQ_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/chalk/plugins/paintops/defaultpaintops/kis_penop.cc b/chalk/plugins/paintops/defaultpaintops/kis_penop.cc deleted file mode 100644 index 4a8da9a1..00000000 --- a/chalk/plugins/paintops/defaultpaintops/kis_penop.cc +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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 "tdelocale.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); - TQ_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; - - TQ_INT32 x = pt.roundX(); - TQ_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); - TQRect dabRect = TQRect(0, 0, brush->maskWidth(info), brush->maskHeight(info)); - TQRect dstRect = TQRect(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()) { - TQ_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; - } - - TQ_INT32 sx = dstRect.x() - x; - TQ_INT32 sy = dstRect.y() - y; - TQ_INT32 sw = dstRect.width(); - TQ_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/chalk/plugins/paintops/defaultpaintops/kis_penop.cpp b/chalk/plugins/paintops/defaultpaintops/kis_penop.cpp new file mode 100644 index 00000000..4a8da9a1 --- /dev/null +++ b/chalk/plugins/paintops/defaultpaintops/kis_penop.cpp @@ -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 "tdelocale.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); + TQ_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; + + TQ_INT32 x = pt.roundX(); + TQ_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); + TQRect dabRect = TQRect(0, 0, brush->maskWidth(info), brush->maskHeight(info)); + TQRect dstRect = TQRect(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()) { + TQ_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; + } + + TQ_INT32 sx = dstRect.x() - x; + TQ_INT32 sy = dstRect.y() - y; + TQ_INT32 sw = dstRect.width(); + TQ_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/chalk/plugins/paintops/defaultpaintops/kis_smudgeop.cc b/chalk/plugins/paintops/defaultpaintops/kis_smudgeop.cc deleted file mode 100644 index f15077b3..00000000 --- a/chalk/plugins/paintops/defaultpaintops/kis_smudgeop.cc +++ /dev/null @@ -1,328 +0,0 @@ -/* - * 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); - TQ_CHECK_PTR(op); - return op; -} - -KisSmudgeOpSettings::KisSmudgeOpSettings(TQWidget *parent, bool isTablet) - : super(parent) -{ - m_optionsWidget = new TQWidget(parent, "brush option widget"); - TQHBoxLayout * l = new TQHBoxLayout(m_optionsWidget); - l->setAutoAdd(true); - m_rateLabel = new TQLabel(i18n("Rate: "), m_optionsWidget); - m_rateSlider = new TQSlider(0,100,1, 50, Qt::Horizontal, m_optionsWidget); - if(isTablet) - { - m_pressureVariation = new TQLabel(i18n("Pressure variation: "), m_optionsWidget); - m_size = new TQCheckBox(i18n("Size"), m_optionsWidget); - m_size->setChecked(true); - m_opacity = new TQCheckBox(i18n("Opacity"), m_optionsWidget); - m_rate = new TQCheckBox(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.")); - TQToolButton* moreButton = new TQToolButton(TQt::UpArrow, m_optionsWidget); - moreButton->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding); - moreButton->setMinimumSize(TQSize(24,24)); // Bah, I had hoped the above line would make this unneeded - connect(moreButton, TQT_SIGNAL(clicked()), this, TQT_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() == TQDialog::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(TQWidget * 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. - TQ_INT32 x; - double xFraction; - TQ_INT32 y; - double yFraction; - - splitCoordinate(pt.x(), &x, &xFraction); - splitCoordinate(pt.y(), &y, &yFraction); - - KisPaintDeviceSP dab = 0; - - TQ_UINT8 origOpacity = m_painter->opacity(); - - if (m_pressureOpacity) { - if (!m_customOpacity) - m_painter->setOpacity((TQ_INT8)(origOpacity * info.pressure)); - else - m_painter->setOpacity((TQ_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); - - TQRect dabRect = TQRect(0, 0, brush->maskWidth(adjustedInfo), - brush->maskHeight(adjustedInfo)); - TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height()); - - KisImage * image = device->image(); - - if (image != 0) { - dstRect &= image->bounds(); - } - - TQ_INT32 sw = dab->extent().width(); - TQ_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((TQ_UINT8)(double(opacity) * scaleToCurve(info.pressure, m_rateCurve)), OPACITY_TRANSPARENT, OPACITY_OPAQUE); - } else { - opacity = CLAMP((TQ_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; - - TQ_INT32 sx = dstRect.x() - x; - TQ_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/chalk/plugins/paintops/defaultpaintops/kis_smudgeop.cpp b/chalk/plugins/paintops/defaultpaintops/kis_smudgeop.cpp new file mode 100644 index 00000000..f15077b3 --- /dev/null +++ b/chalk/plugins/paintops/defaultpaintops/kis_smudgeop.cpp @@ -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); + TQ_CHECK_PTR(op); + return op; +} + +KisSmudgeOpSettings::KisSmudgeOpSettings(TQWidget *parent, bool isTablet) + : super(parent) +{ + m_optionsWidget = new TQWidget(parent, "brush option widget"); + TQHBoxLayout * l = new TQHBoxLayout(m_optionsWidget); + l->setAutoAdd(true); + m_rateLabel = new TQLabel(i18n("Rate: "), m_optionsWidget); + m_rateSlider = new TQSlider(0,100,1, 50, Qt::Horizontal, m_optionsWidget); + if(isTablet) + { + m_pressureVariation = new TQLabel(i18n("Pressure variation: "), m_optionsWidget); + m_size = new TQCheckBox(i18n("Size"), m_optionsWidget); + m_size->setChecked(true); + m_opacity = new TQCheckBox(i18n("Opacity"), m_optionsWidget); + m_rate = new TQCheckBox(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.")); + TQToolButton* moreButton = new TQToolButton(TQt::UpArrow, m_optionsWidget); + moreButton->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding); + moreButton->setMinimumSize(TQSize(24,24)); // Bah, I had hoped the above line would make this unneeded + connect(moreButton, TQT_SIGNAL(clicked()), this, TQT_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() == TQDialog::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(TQWidget * 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. + TQ_INT32 x; + double xFraction; + TQ_INT32 y; + double yFraction; + + splitCoordinate(pt.x(), &x, &xFraction); + splitCoordinate(pt.y(), &y, &yFraction); + + KisPaintDeviceSP dab = 0; + + TQ_UINT8 origOpacity = m_painter->opacity(); + + if (m_pressureOpacity) { + if (!m_customOpacity) + m_painter->setOpacity((TQ_INT8)(origOpacity * info.pressure)); + else + m_painter->setOpacity((TQ_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); + + TQRect dabRect = TQRect(0, 0, brush->maskWidth(adjustedInfo), + brush->maskHeight(adjustedInfo)); + TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height()); + + KisImage * image = device->image(); + + if (image != 0) { + dstRect &= image->bounds(); + } + + TQ_INT32 sw = dab->extent().width(); + TQ_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((TQ_UINT8)(double(opacity) * scaleToCurve(info.pressure, m_rateCurve)), OPACITY_TRANSPARENT, OPACITY_OPAQUE); + } else { + opacity = CLAMP((TQ_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; + + TQ_INT32 sx = dstRect.x() - x; + TQ_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" -- cgit v1.2.1