File indexing completed on 2024-05-26 04:33:51

0001 /*
0002  *  SPDX-FileCopyrightText: 2008-2011 Lukáš Tvrdý <lukast.dev@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_curve_paintop.h"
0008 
0009 #include <cmath>
0010 
0011 #include <QPainterPath>
0012 #include <QRect>
0013 
0014 #include <kis_image.h>
0015 #include <kis_debug.h>
0016 #include "kis_global.h"
0017 #include "kis_paint_device.h"
0018 #include "kis_painter.h"
0019 #include "kis_types.h"
0020 #include "kis_spacing_information.h"
0021 #include <kis_lod_transform.h>
0022 #include <kis_paintop_settings.h>
0023 
0024 
0025 KisCurvePaintOp::KisCurvePaintOp(const KisPaintOpSettingsSP settings, KisPainter * painter, KisNodeSP node, KisImageSP image)
0026     : KisPaintOp(painter)
0027     , m_opacityOption(settings.data())
0028     , m_lineWidthOption(settings.data())
0029     , m_curvesOpacityOption(settings.data())
0030     , m_painter(0)
0031 {
0032     Q_ASSERT(settings);
0033     Q_UNUSED(image);
0034     Q_UNUSED(node);
0035 
0036     m_curveOpOption.read(settings.data());
0037 }
0038 
0039 KisCurvePaintOp::~KisCurvePaintOp()
0040 {
0041     delete m_painter;
0042 }
0043 
0044 KisSpacingInformation KisCurvePaintOp::paintAt(const KisPaintInformation& info)
0045 {
0046     return updateSpacingImpl(info);
0047 }
0048 
0049 KisSpacingInformation KisCurvePaintOp::updateSpacingImpl(const KisPaintInformation &info) const
0050 {
0051     Q_UNUSED(info);
0052     return KisSpacingInformation(1.0);
0053 }
0054 
0055 void KisCurvePaintOp::paintLine(const KisPaintInformation &pi1, const KisPaintInformation &pi2, KisDistanceInformation *currentDistance)
0056 {
0057     Q_UNUSED(currentDistance);
0058     if (!painter()) return;
0059 
0060     if (!m_dab) {
0061         m_dab = source()->createCompositionSourceDevice();
0062     }
0063     else {
0064         m_dab->clear();
0065     }
0066 
0067     paintLine(m_dab, pi1, pi2);
0068 
0069     QRect rc = m_dab->extent();
0070 
0071     quint8 origOpacity = m_opacityOption.apply(painter(), pi2);
0072     painter()->bitBlt(rc.topLeft(), m_dab, rc);
0073     painter()->renderMirrorMask(rc, m_dab);
0074     painter()->setOpacity(origOpacity);
0075 }
0076 
0077 void KisCurvePaintOp::paintLine(KisPaintDeviceSP dab, const KisPaintInformation &pi1, const KisPaintInformation &pi2)
0078 {
0079     if (!m_painter) {
0080         m_painter = new KisPainter(dab);
0081         m_painter->setPaintColor(painter()->paintColor());
0082     }
0083 
0084     int maxPoints = m_curveOpOption.curve_stroke_history_size;
0085 
0086     m_points.append(pi2.pos());
0087 
0088     while (m_points.length() > maxPoints) {
0089         m_points.removeFirst();
0090     }
0091 
0092     const qreal additionalScale = KisLodTransform::lodToScale(painter()->device());
0093     const qreal lineWidth = additionalScale * m_lineWidthOption.apply(pi2) * m_curveOpOption.curve_line_width;
0094 
0095     QPen pen(QBrush(Qt::white), lineWidth);
0096     QPainterPath path;
0097 
0098     if (m_curveOpOption.curve_paint_connection_line) {
0099         path.moveTo(pi1.pos());
0100         path.lineTo(pi2.pos());
0101         m_painter->drawPainterPath(path, pen);
0102         path = QPainterPath();
0103     }
0104 
0105     if (m_points.length() >= maxPoints) {
0106         // alpha * 0.2;
0107         path.moveTo(m_points.first());
0108 
0109         if (m_curveOpOption.curve_smoothing) {
0110             path.quadTo(m_points.at(maxPoints / 2), m_points.last());
0111         }
0112         else {
0113             // control point is at 1/3 of the history, 2/3 of the history and endpoint at 3/3
0114             int step = maxPoints / 3;
0115             path.cubicTo(m_points.at(step), m_points.at(step + step), m_points.last());
0116         }
0117 
0118         qreal curveOpacity = m_curvesOpacityOption.apply(pi2) * m_curveOpOption.curve_curves_opacity;
0119         m_painter->setOpacity(qRound(255.0 * curveOpacity));
0120         m_painter->drawPainterPath(path, pen);
0121         m_painter->setOpacity(255); // full
0122     }
0123 }