File indexing completed on 2024-05-12 15:58:11

0001 /*
0002  *  SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_cached_gradient_shape_strategy.h"
0008 
0009 #include <QRect>
0010 #include "bsplines/kis_bspline_2d.h"
0011 
0012 #include <cmath>
0013 
0014 #include <functional>
0015 
0016 #include "kis_algebra_2d.h"
0017 #include "kis_debug.h"
0018 
0019 
0020 using namespace KisBSplines;
0021 
0022 struct Q_DECL_HIDDEN KisCachedGradientShapeStrategy::Private
0023 {
0024     QRect rc;
0025     qreal xStep;
0026     qreal yStep;
0027     QScopedPointer<KisGradientShapeStrategy> baseStrategy;
0028     QScopedPointer<KisBSpline2D> spline;
0029 };
0030 
0031 KisCachedGradientShapeStrategy::KisCachedGradientShapeStrategy(const QRect &rc,
0032                                                                qreal xStep,
0033                                                                qreal yStep,
0034                                                                KisGradientShapeStrategy *baseStrategy)
0035     : KisGradientShapeStrategy(),
0036       m_d(new Private())
0037 {
0038     using namespace std::placeholders;  // for _1, _2, _3...
0039 
0040     KIS_ASSERT_RECOVER_NOOP(rc.width() >= 3 && rc.height() >= 3);
0041 
0042     m_d->rc = rc;
0043     m_d->xStep = xStep;
0044     m_d->yStep = yStep;
0045     m_d->baseStrategy.reset(baseStrategy);
0046 
0047     qreal xStart = rc.x();
0048     qreal yStart = rc.y();
0049     qreal xEnd = rc.x() + rc.width();
0050     qreal yEnd = rc.y() + rc.height();
0051 
0052     int numSamplesX = std::ceil(qreal(rc.width()) / xStep);
0053     int numSamplesY = std::ceil(qreal(rc.height()) / yStep);
0054 
0055     if (numSamplesX < 2 || numSamplesY < 2) {
0056         warnKrita;
0057         warnKrita << "############";
0058         warnKrita << "WARNING: KisCachedGradientShapeStrategy numSamplesX/Y is too small!"  << ppVar(numSamplesX) << ppVar(numSamplesY);
0059         warnKrita << "WARNING:" << ppVar(rc) << ppVar(xStep) << ppVar(yStep);
0060         warnKrita << "WARNING:" << ppVar(numSamplesX) << ppVar(numSamplesY);
0061 
0062         numSamplesX = qMax(numSamplesX, 2);
0063         numSamplesY = qMax(numSamplesY, 2);
0064 
0065         warnKrita << "WARNING: adjusting:" << ppVar(numSamplesX) << ppVar(numSamplesY);
0066         warnKrita << "############";
0067         warnKrita;
0068     }
0069 
0070     m_d->spline.reset(new KisBSpline2D(xStart, xEnd, numSamplesX, Natural,
0071                                        yStart, yEnd, numSamplesY, Natural));
0072 
0073 
0074     std::function<qreal(qreal, qreal)> valueOp =
0075         std::bind(&KisGradientShapeStrategy::valueAt, m_d->baseStrategy.data(), _1, _2);
0076 
0077     m_d->spline->initializeSpline(valueOp);
0078 
0079 }
0080 
0081 KisCachedGradientShapeStrategy::~KisCachedGradientShapeStrategy()
0082 {
0083 }
0084 
0085 double KisCachedGradientShapeStrategy::valueAt(double x, double y) const
0086 {
0087     QPointF pt = KisAlgebra2D::ensureInRect(QPointF(x, y), m_d->rc);
0088     return m_d->spline->value(pt.x(), pt.y());
0089 }