File indexing completed on 2024-06-16 04:17:32
0001 /* 0002 * SPDX-FileCopyrightText: 2022 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "MyPaintCurveRangeModel.h" 0008 #include "kis_algebra_2d.h" 0009 #include "kis_cubic_curve.h" 0010 #include <lager/lenses.hpp> 0011 #include <lager/constant.hpp> 0012 #include <KisZug.h> 0013 #include <KisDynamicSensorFactoryRegistry.h> 0014 #include <KisCurveRangeModel.h> 0015 0016 namespace { 0017 auto formatQRealAsString = [] (qreal value) { 0018 return QString("%1").arg(value, 0, 'f', 2); 0019 }; 0020 0021 auto formatQRealAsStringWithSuffix = [] (const QString &suffix) { 0022 return [suffix] (qreal value) { 0023 return QString("%1%2").arg(value, 0, 'f', 2).arg(suffix); 0024 }; 0025 }; 0026 0027 0028 auto curveToNormalizedCurve = lager::lenses::getset( 0029 [] (const std::tuple<QString, QRectF> &curveData) 0030 { 0031 MyPaintCurveRangeModel::NormalizedCurve normalized; 0032 QList<QPointF> points = KisCubicCurve(std::get<0>(curveData)).points(); 0033 const QRectF bounds = std::get<1>(curveData); 0034 0035 normalized.yLimit = qMax(qAbs(bounds.top()), qAbs(bounds.bottom())); 0036 normalized.xMax = bounds.right(); 0037 normalized.xMin = bounds.left(); 0038 0039 if (qFuzzyIsNull(normalized.yLimit)) { 0040 points = {{0.0,0.5}, {1.0, 0.5}}; 0041 } else { 0042 for (auto it = points.begin(); it != points.end(); ++it) { 0043 it->rx() = (it->x() - bounds.left()) / bounds.width(); 0044 it->ry() = it->y() / (2.0 * normalized.yLimit) + 0.5; 0045 } 0046 } 0047 0048 normalized.curve = KisCubicCurve(points).toString(); 0049 0050 //qDebug() << "get" << std::get<0>(curveData) << "->" << normalized.curve << bounds; 0051 return normalized; 0052 }, 0053 [] (std::tuple<QString, QRectF> curveData, const MyPaintCurveRangeModel::NormalizedCurve &normalizedCurve) { 0054 QList<QPointF> points = KisCubicCurve(normalizedCurve.curve).points(); 0055 0056 for (auto it = points.begin(); it != points.end(); ++it) { 0057 it->rx() = it->x() * (normalizedCurve.xMax - normalizedCurve.xMin) + normalizedCurve.xMin; 0058 it->ry() = (it->y() - 0.5) * normalizedCurve.yLimit * 2.0; 0059 } 0060 0061 std::get<0>(curveData) = KisCubicCurve(points).toString(); 0062 0063 std::get<1>(curveData) = QRectF(normalizedCurve.xMin, 0064 -normalizedCurve.yLimit, 0065 normalizedCurve.xMax - normalizedCurve.xMin, 0066 2.0 * normalizedCurve.yLimit); 0067 0068 //qDebug() << "set" << std::get<0>(curveData) << "<-" << normalizedCurve.curve << std::get<1>(curveData); 0069 return curveData; 0070 } 0071 ); 0072 0073 } // namespace 0074 0075 0076 using KisWidgetConnectionUtils::ToSpinBoxState; 0077 0078 MyPaintCurveRangeModel::MyPaintCurveRangeModel(lager::cursor<QString> curve, 0079 lager::cursor<QRectF> curveRange, 0080 lager::reader<QString> activeSensorId, 0081 lager::reader<int> activeSensorLength, 0082 qreal maxYRange, 0083 const QString &yValueSuffix) 0084 : m_curve(std::move(curve)) 0085 , m_curveRange(std::move(curveRange)) 0086 , m_activeSensorId(std::move(activeSensorId)) 0087 , m_activeSensorLength(std::move(activeSensorLength)) 0088 , m_normalizedCurve(lager::with(m_curve, m_curveRange).zoom(curveToNormalizedCurve)) 0089 , m_maxYRange(maxYRange) 0090 , m_yValueSuffix(yValueSuffix) 0091 , LAGER_QT(yLimit) {m_normalizedCurve[&NormalizedCurve::yLimit]} 0092 , LAGER_QT(xMin) {m_normalizedCurve[&NormalizedCurve::xMin]} 0093 , LAGER_QT(xMax) {m_normalizedCurve[&NormalizedCurve::xMax]} 0094 , LAGER_QT(xMinState) {lager::with(m_normalizedCurve[&NormalizedCurve::xMin], 0095 m_activeSensorId.map(&KisCurveRangeModel::calcXMinValueWithFactory), 0096 lager::make_constant(0.0), 0097 lager::make_constant(true)) 0098 .map(ToSpinBoxState{})} 0099 , LAGER_QT(xMaxState) {lager::with(m_normalizedCurve[&NormalizedCurve::xMax], 0100 lager::make_constant(1.0), 0101 lager::with(m_activeSensorId, m_activeSensorLength) 0102 .map(&KisCurveRangeModel::calcXMaxValueWithFactory), 0103 lager::make_constant(true)) 0104 .map(ToSpinBoxState{})} 0105 { 0106 0107 } 0108 0109 MyPaintCurveRangeModel::~MyPaintCurveRangeModel() 0110 { 0111 0112 } 0113 0114 KisCurveRangeModelFactory MyPaintCurveRangeModel::factory(qreal maxYRange, const QString &yValueSuffix) 0115 { 0116 return 0117 [maxYRange, yValueSuffix](lager::cursor<QString> curve, lager::cursor<QRectF> curveRange, lager::reader<QString> activeSensorId, lager::reader<int> activeSensorLength) { 0118 return new MyPaintCurveRangeModel(curve, curveRange, activeSensorId, activeSensorLength, maxYRange, yValueSuffix); 0119 }; 0120 } 0121 0122 std::tuple<QString, QRectF> MyPaintCurveRangeModel::reshapeCurve(std::tuple<QString, QRectF> curve) 0123 { 0124 /** 0125 * Krita's GUI doesn't support x-range more narrow than 0...1, so 0126 * we should extend it if necessary 0127 */ 0128 std::get<1>(curve) |= QRect(0, -1, 1, 2); 0129 0130 NormalizedCurve normalized = lager::view(curveToNormalizedCurve, curve); 0131 curve = lager::set(curveToNormalizedCurve, curve, normalized); 0132 return curve; 0133 } 0134 0135 lager::cursor<QString> MyPaintCurveRangeModel::curve() 0136 { 0137 return m_normalizedCurve[&NormalizedCurve::curve]; 0138 } 0139 0140 lager::reader<QString> MyPaintCurveRangeModel::xMinLabel() 0141 { 0142 return m_normalizedCurve[&NormalizedCurve::xMin].map(formatQRealAsString); 0143 } 0144 0145 lager::reader<QString> MyPaintCurveRangeModel::xMaxLabel() 0146 { 0147 return m_normalizedCurve[&NormalizedCurve::xMax].map(formatQRealAsString); 0148 } 0149 0150 lager::reader<QString> MyPaintCurveRangeModel::yMinLabel() 0151 { 0152 return yMinValue().map(formatQRealAsStringWithSuffix(m_yValueSuffix)); 0153 } 0154 0155 lager::reader<QString> MyPaintCurveRangeModel::yMaxLabel() 0156 { 0157 return yMaxValue().map(formatQRealAsStringWithSuffix(m_yValueSuffix)); 0158 } 0159 0160 lager::reader<qreal> MyPaintCurveRangeModel::yMinValue() 0161 { 0162 return m_normalizedCurve[&NormalizedCurve::yLimit].xform(kiszug::map_mupliply<qreal>(-1.0)); 0163 } 0164 0165 lager::reader<qreal> MyPaintCurveRangeModel::yMaxValue() 0166 { 0167 return m_normalizedCurve[&NormalizedCurve::yLimit]; 0168 } 0169 0170 lager::reader<QString> MyPaintCurveRangeModel::yValueSuffix() 0171 { 0172 return lager::make_constant(m_yValueSuffix); 0173 } 0174 0175 lager::reader<qreal> MyPaintCurveRangeModel::xMinValue() 0176 { 0177 return m_normalizedCurve[&NormalizedCurve::xMin]; 0178 } 0179 0180 lager::reader<qreal> MyPaintCurveRangeModel::xMaxValue() 0181 { 0182 return m_normalizedCurve[&NormalizedCurve::xMax]; 0183 } 0184 0185 lager::reader<QString> MyPaintCurveRangeModel::xValueSuffix() 0186 { 0187 return lager::make_constant(QString()); 0188 } 0189 0190 qreal MyPaintCurveRangeModel::maxYRange() const 0191 { 0192 return m_maxYRange; 0193 }