File indexing completed on 2024-06-16 04:17:34
0001 /* 0002 * SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_particle_paintop.h" 0008 #include "kis_particle_paintop_settings.h" 0009 0010 #include <cmath> 0011 0012 #include "kis_vec.h" 0013 0014 #include <KoCompositeOp.h> 0015 0016 #include <kis_image.h> 0017 #include <kis_debug.h> 0018 0019 #include <kis_global.h> 0020 #include <kis_paint_device.h> 0021 #include <kis_painter.h> 0022 #include <kis_lod_transform.h> 0023 #include <kis_types.h> 0024 #include <kis_paintop_plugin_utils.h> 0025 #include <brushengine/kis_paintop.h> 0026 #include <brushengine/kis_paint_information.h> 0027 0028 #include "KisParticleOpOptionData.h" 0029 0030 #include "particle_brush.h" 0031 0032 KisParticlePaintOp::KisParticlePaintOp(const KisPaintOpSettingsSP settings, KisPainter * painter, KisNodeSP node, KisImageSP image) 0033 : KisPaintOp(painter) 0034 , m_rateOption(settings.data()) 0035 , m_first(true) 0036 { 0037 Q_UNUSED(image); 0038 Q_UNUSED(node); 0039 0040 m_particleOpData.read(settings.data()); 0041 0042 m_particleBrush.setProperties(&m_particleOpData); 0043 m_particleBrush.initParticles(); 0044 0045 m_airbrushData.read(settings.data()); 0046 } 0047 0048 KisParticlePaintOp::~KisParticlePaintOp() 0049 { 0050 } 0051 0052 KisSpacingInformation KisParticlePaintOp::paintAt(const KisPaintInformation& info) 0053 { 0054 doPaintLine(info, info); 0055 return updateSpacingImpl(info); 0056 } 0057 0058 KisSpacingInformation KisParticlePaintOp::updateSpacingImpl(const KisPaintInformation &info) const 0059 { 0060 return KisPaintOpPluginUtils::effectiveSpacing(0.0, 0.0, true, 0.0, false, 0.0, false, 0.0, 0061 KisLodTransform::lodToScale(painter()->device()), 0062 &m_airbrushData, nullptr, info); 0063 } 0064 0065 KisTimingInformation KisParticlePaintOp::updateTimingImpl(const KisPaintInformation &info) const 0066 { 0067 return KisPaintOpPluginUtils::effectiveTiming(&m_airbrushData, &m_rateOption, info); 0068 } 0069 0070 void KisParticlePaintOp::paintLine(const KisPaintInformation &pi1, const KisPaintInformation &pi2, 0071 KisDistanceInformation *currentDistance) 0072 { 0073 // Use superclass behavior for lines of zero length. Otherwise, airbrushing can happen faster 0074 // than it is supposed to. 0075 if (pi1.pos() == pi2.pos()) { 0076 KisPaintOp::paintLine(pi1, pi2, currentDistance); 0077 } else { 0078 doPaintLine(pi1, pi2); 0079 } 0080 } 0081 0082 void KisParticlePaintOp::doPaintLine(const KisPaintInformation &pi1, const KisPaintInformation &pi2) 0083 { 0084 if (!painter()) return; 0085 0086 if (!m_dab) { 0087 m_dab = source()->createCompositionSourceDevice(); 0088 } 0089 else { 0090 m_dab->clear(); 0091 } 0092 0093 0094 if (m_first) { 0095 m_particleBrush.setInitialPosition(pi1.pos()); 0096 m_first = false; 0097 } 0098 0099 m_particleBrush.draw(m_dab, painter()->paintColor(), pi2.pos()); 0100 QRect rc = m_dab->extent(); 0101 0102 painter()->bitBlt(rc.x(), rc.y(), m_dab, rc.x(), rc.y(), rc.width(), rc.height()); 0103 painter()->renderMirrorMask(rc, m_dab); 0104 }