2
* Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
3
* Copyright (c) 2004-2008 Boudewijn Rempt <boud@valdyas.org>
4
* Copyright (c) 2004 Clarence Dang <dang@kde.org>
5
* Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
6
* Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23
#include "kis_eraseop.h"
27
#include <kis_image.h>
28
#include <kis_debug.h>
30
#include <KoColorTransformation.h>
32
#include <KoCompositeOp.h>
34
#include <kis_brush.h>
35
#include <kis_global.h>
36
#include <kis_paint_device.h>
37
#include <kis_painter.h>
38
#include <kis_brush_based_paintop_settings.h>
40
KisEraseOp::KisEraseOp(const KisBrushBasedPaintOpSettings *settings, KisPainter *painter, KisImageWSP image)
41
: KisBrushBasedPaintOp(settings, painter)
46
m_sizeOption.readOptionSetting(settings);
47
m_opacityOption.readOptionSetting(settings);
48
m_sizeOption.sensor()->reset();
49
m_opacityOption.sensor()->reset();
52
KisEraseOp::~KisEraseOp()
56
double KisEraseOp::paintAt(const KisPaintInformation& info)
58
// Erasing is traditionally in paint applications one of two things:
59
// either it is painting in the 'background' color, or it is replacing
60
// all pixels with transparent (black?) pixels.
62
// That's what this paint op does for now; however, anyone who has
63
// ever worked with paper and soft pencils knows that a sharp piece of
64
// eraser rubber is a pretty useful too for making sharp to fuzzy lines
65
// in the graphite layer, or equally useful: for smudging skin tones.
67
// A smudge tool for Krita is in the making, but when working with
68
// a tablet, the eraser tip should be at least as functional as a rubber eraser.
69
// That means that only after repeated or forceful application should all the
70
// 'paint' or 'graphite' be removed from the surface -- a kind of pressure
71
// sensitive, incremental smudge.
73
// And there should be an option to not have the eraser work on certain
74
// kinds of material. Layers are just a hack for this; putting your ink work
75
// in one layer and your pencil in another is not the same as really working
76
// with the combination.
78
if (!painter()->device()) return 1.0;
80
KisBrushSP brush = m_brush;
84
if (! brush->canPaintFor(info))
87
double scale = KisPaintOp::scaleForPressure(m_sizeOption.apply(info));
88
if ((scale * brush->width()) <= 0.01 || (scale * brush->height()) <= 0.01) return spacing(scale);
90
KisPaintDeviceSP device = painter()->device();
91
QPointF hotSpot = brush->hotSpot(scale, scale);
92
QPointF pt = info.pos() - hotSpot;
99
splitCoordinate(pt.x(), &x, &xFraction);
100
splitCoordinate(pt.y(), &y, &yFraction);
102
KisFixedPaintDeviceSP dab = cachedDab(device->colorSpace());
104
quint8 origOpacity = m_opacityOption.apply(painter(), info);
106
QRect dabRect = QRect(0, 0, brush->maskWidth(scale, 0.0), brush->maskHeight(scale, 0.0));
107
QRect dstRect = QRect(x, y, dabRect.width(), dabRect.height());
110
if (painter()->bounds().isValid()) {
111
dstRect &= painter()->bounds();
114
if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return 1.0;
116
qint32 sx = dstRect.x() - x;
117
qint32 sy = dstRect.y() - y;
118
qint32 sw = dstRect.width();
119
qint32 sh = dstRect.height();
121
if (brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) {
122
dab = brush->paintDevice(device->colorSpace(), scale, 0.0, info, xFraction, yFraction);
125
KoColor color = painter()->paintColor();
126
color.convertTo(dab->colorSpace());
127
brush->mask(dab, color, scale, scale, 0.0, info, xFraction, yFraction);
130
const KoCompositeOp* op = painter()->compositeOp();
131
painter()->setCompositeOp(COMPOSITE_ERASE);
132
painter()->bltFixed(dstRect.x(), dstRect.y(), dab, sx, sy, sw, sh);
133
painter()->setCompositeOp(op);
135
painter()->setOpacity(origOpacity);
137
return spacing(scale);