File indexing completed on 2024-06-16 04:17:59
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #include "kis_liquify_paint_helper.h" 0007 0008 #include <QElapsedTimer> 0009 #include <QPainterPath> 0010 0011 #include "kis_algebra_2d.h" 0012 #include "KoPointerEvent.h" 0013 #include <brushengine/kis_paint_information.h> 0014 #include "kis_painting_information_builder.h" 0015 #include "kis_liquify_transform_worker.h" 0016 #include <brushengine/kis_paintop_utils.h> 0017 #include "kis_coordinates_converter.h" 0018 #include "kis_liquify_paintop.h" 0019 #include "kis_liquify_properties.h" 0020 0021 struct KisLiquifyPaintHelper::Private 0022 { 0023 Private(const KisCoordinatesConverter *_converter) 0024 : converter(_converter), 0025 infoBuilder(new KisConverterPaintingInformationBuilder(converter)), 0026 hasPaintedAtLeastOnce(false) 0027 { 0028 } 0029 0030 KisPaintInformation previousPaintInfo; 0031 0032 QScopedPointer<KisLiquifyPaintop> paintOp; 0033 KisDistanceInformation currentDistance; 0034 const KisCoordinatesConverter *converter; 0035 QScopedPointer<KisPaintingInformationBuilder> infoBuilder; 0036 0037 QElapsedTimer strokeTime; 0038 0039 bool hasPaintedAtLeastOnce; 0040 0041 KisDistanceInformation previousDistanceInfo; 0042 KisPaintOpUtils::PositionHistory lastOutlinePos; 0043 void updatePreviousPaintInfo(const KisPaintInformation &info); 0044 }; 0045 0046 0047 KisLiquifyPaintHelper::KisLiquifyPaintHelper(const KisCoordinatesConverter *converter) 0048 : m_d(new Private(converter)) 0049 { 0050 } 0051 0052 KisLiquifyPaintHelper::~KisLiquifyPaintHelper() 0053 { 0054 } 0055 0056 void KisLiquifyPaintHelper::Private::updatePreviousPaintInfo(const KisPaintInformation &info) 0057 { 0058 QPointF prevPos = lastOutlinePos.pushThroughHistory(info.pos(), converter->effectiveZoom()); 0059 qreal angle = KisAlgebra2D::directionBetweenPoints(prevPos, info.pos(), 0); 0060 0061 previousDistanceInfo = 0062 KisDistanceInformation(prevPos, angle); 0063 0064 previousPaintInfo = info; 0065 } 0066 0067 QPainterPath KisLiquifyPaintHelper::brushOutline(const KisLiquifyProperties &props) 0068 { 0069 KisPaintInformation::DistanceInformationRegistrar registrar = 0070 m_d->previousPaintInfo.registerDistanceInformation(&m_d->previousDistanceInfo); 0071 0072 return KisLiquifyPaintop::brushOutline(props, m_d->previousPaintInfo); 0073 } 0074 0075 void KisLiquifyPaintHelper::configurePaintOp(const KisLiquifyProperties &props, 0076 KisLiquifyTransformWorker *worker) 0077 { 0078 m_d->paintOp.reset(new KisLiquifyPaintop(props, worker)); 0079 } 0080 0081 void KisLiquifyPaintHelper::startPaint(KoPointerEvent *event, const KoCanvasResourceProvider *manager) 0082 { 0083 KIS_ASSERT_RECOVER_RETURN(m_d->paintOp); 0084 0085 m_d->strokeTime.start(); 0086 KisPaintInformation pi = 0087 m_d->infoBuilder->startStroke(event, m_d->strokeTime.elapsed(), manager); 0088 0089 m_d->updatePreviousPaintInfo(pi); 0090 m_d->hasPaintedAtLeastOnce = false; 0091 } 0092 0093 void KisLiquifyPaintHelper::continuePaint(KoPointerEvent *event) 0094 { 0095 KIS_ASSERT_RECOVER_RETURN(m_d->paintOp); 0096 0097 KisPaintInformation pi = 0098 m_d->infoBuilder->continueStroke(event, m_d->strokeTime.elapsed()); 0099 0100 KisPaintOpUtils::paintLine(*m_d->paintOp.data(), 0101 m_d->previousPaintInfo, 0102 pi, 0103 &m_d->currentDistance, 0104 false, false); 0105 0106 m_d->updatePreviousPaintInfo(pi); 0107 m_d->hasPaintedAtLeastOnce = true; 0108 } 0109 0110 bool KisLiquifyPaintHelper::endPaint(KoPointerEvent *event) 0111 { 0112 KIS_ASSERT_RECOVER(m_d->paintOp) { return false; } 0113 0114 if (!m_d->hasPaintedAtLeastOnce) { 0115 KisPaintInformation pi = 0116 m_d->infoBuilder->continueStroke(event, m_d->strokeTime.elapsed()); 0117 0118 pi.paintAt(*m_d->paintOp.data(), &m_d->previousDistanceInfo); 0119 } 0120 0121 m_d->paintOp.reset(); 0122 0123 return !m_d->hasPaintedAtLeastOnce; 0124 } 0125 0126 void KisLiquifyPaintHelper::hoverPaint(KoPointerEvent *event) 0127 { 0128 QPointF imagePoint = m_d->converter->documentToImage(event->pos()); 0129 KisPaintInformation pi = m_d->infoBuilder->hover(imagePoint, event, m_d->paintOp); 0130 0131 m_d->updatePreviousPaintInfo(pi); 0132 }