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 }