kis_curve_option.h 7.35 KB
Newer Older
1
/* This file is part of the KDE project
2 3
 * Copyright (C) 2008 Boudewijn Rempt <boud@valdyas.org>
 * Copyright (C) 2011 Silvio Heinrich <plassy@web.de>
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef KIS_CURVE_OPTION_H
#define KIS_CURVE_OPTION_H

#include <QObject>
#include <QVector>

27
#include "kis_paintop_option.h"
28
#include "kis_global.h"
Boudewijn Rempt's avatar
Boudewijn Rempt committed
29
#include <brushengine/kis_paint_information.h>
30
#include "kritapaintop_export.h"
31
#include "kis_dynamic_sensor.h"
32

33
class KisDynamicSensor;
34

35 36
/**
 * KisCurveOption is the base class for paintop options that are
37 38 39 40
 * defined through one or more curves.
 *
 * Note: it is NOT a KisPaintOpOption, even though the API is pretty similar!
 *
41 42 43 44 45
 * KisCurveOption classes have a generic GUI widget, KisCurveOptionWidget. So,
 * in contrast to KisPaintOpOption classes, KisCurveOption instances can and
 * will be created in the constructor of KisPaintOp paintops. This class can
 * manage to read and write its settings directly.
 *
46
 */
47
class PAINTOP_EXPORT KisCurveOption
Boudewijn Rempt's avatar
Boudewijn Rempt committed
48
{
49
public:
50 51
    KisCurveOption(const QString& name,
                   KisPaintOpOption::PaintopCategory category,
52 53 54 55 56
                   bool checked,
                   qreal value = 1.0,
                   qreal min = 0.0,
                   qreal max = 1.0);

Sven Langkamp's avatar
Sven Langkamp committed
57
    virtual ~KisCurveOption();
58

59 60
    virtual void writeOptionSetting(KisPropertiesConfigurationSP setting) const;
    virtual void readOptionSetting(KisPropertiesConfigurationSP setting);
61
    virtual void lodLimitations(KisPaintopLodLimitations *l) const;
62

63 64 65 66 67
    //Please override for other values than 0-100 and %
    virtual int intMinValue()const;
    virtual int intMaxValue()const;
    virtual QString valueSuffix()const;

68
    const QString& name() const;
69
    KisPaintOpOption::PaintopCategory category() const;
70 71 72
    qreal minValue() const;
    qreal maxValue() const;
    qreal value() const;
73

74
    void resetAllSensors();
75
    KisDynamicSensorSP sensor(DynamicSensorType sensorType, bool active) const;
76 77 78
    void replaceSensor(KisDynamicSensorSP sensor);
    QList<KisDynamicSensorSP> sensors();
    QList<KisDynamicSensorSP> activeSensors() const;
79

80 81
    bool isCheckable();
    bool isChecked() const;
82
    bool isCurveUsed() const;
83
    bool isSameCurveUsed() const;
84
    bool isRandom() const;
85

86 87
    int getCurveMode() const;

88 89 90 91 92 93
    /**
     * Returns the curve that is being used instead of sensor ones
     * in case "Use the same curve" is checked.
     */
    KisCubicCurve getCommonCurve() const;

94 95
    void setSeparateCurveValue(bool separateCurveValue);

96
    void setChecked(bool checked);
97
    void setCurveUsed(bool useCurve);
98
    void setCurve(DynamicSensorType sensorType, bool useSameCurve, const KisCubicCurve &curve);
99
    void setValue(qreal value);
100
    void setCurveMode(int mode);
101

102 103 104 105 106
    /**
     * Sets the bool indicating whether "Share curve across all settings" is checked.
     */
    void setUseSameCurve(bool useSameCurve);

107 108
    /**
     * Sets the curve that is being used instead of sensor ones
109
     * in case "Share curve across all settings" is checked.
110 111 112
     */
    void setCommonCurve(KisCubicCurve curve);

113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
    struct ValueComponents {

        ValueComponents()
            : constant(1.0),
              scaling(1.0),
              additive(0.0),
              absoluteOffset(0.0),
              hasAbsoluteOffset(false),
              hasScaling(false),
              hasAdditive(false)
        {
        }

        qreal constant;
        qreal scaling;
        qreal additive;
        qreal absoluteOffset;
        bool hasAbsoluteOffset;
        bool hasScaling;
        bool hasAdditive;
        qreal minSizeLikeValue;
        qreal maxSizeLikeValue;

136
        /**
Yuri Chornoivan's avatar
Yuri Chornoivan committed
137
         * @param normalizedBaseAngle canvas rotation angle normalized to range [0; 1]
138 139 140 141
         * @param absoluteAxesFlipped true if underlying image coordinate system is flipped (horiz. mirror != vert. mirror)
         */

        qreal rotationLikeValue(qreal normalizedBaseAngle, bool absoluteAxesFlipped) const {
142
            const qreal offset =
143 144 145
                !hasAbsoluteOffset ? normalizedBaseAngle :
                absoluteAxesFlipped ? 1.0 - absoluteOffset :
                absoluteOffset;
146 147 148 149

            const qreal realScalingPart = hasScaling ? KisDynamicSensor::scalingToAdditive(scaling) : 0.0;
            const qreal realAdditivePart = hasAdditive ? additive : 0;

150
            qreal value = wrapInRange(2 * offset + constant * (realScalingPart + realAdditivePart), -1.0, 1.0);
151 152 153 154 155
            if (qIsNaN(value)) {
                qWarning() << "rotationLikeValue returns NaN!" << normalizedBaseAngle << absoluteAxesFlipped;
                value = 0;
            }
            return value;
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
        }

        qreal sizeLikeValue() const {
            const qreal offset =
                hasAbsoluteOffset ? absoluteOffset : 1.0;

            const qreal realScalingPart = hasScaling ? scaling : 1.0;
            const qreal realAdditivePart = hasAdditive ? KisDynamicSensor::additiveToScaling(additive) : 1.0;

            return qBound(minSizeLikeValue,
                          constant * offset * realScalingPart * realAdditivePart,
                          maxSizeLikeValue);
        }

    private:
        static inline qreal wrapInRange(qreal x, qreal min, qreal max) {
            const qreal range = max - min;

            x -= min;

            if (x < 0.0) {
                x = range + fmod(x, range);
            }

            if (x > range) {
                x = fmod(x, range);
            }

            return x + min;
        }
    };

188 189 190
    /**
     * Uses the curves set on the sensors to compute a single
     * double value that can control the parameters of a brush.
191
     *
Yuri Chornoivan's avatar
Yuri Chornoivan committed
192 193
     * This value is derives from the values stored in
     * ValuesComponents object.
194
     */
195 196 197
    ValueComponents computeValueComponents(const KisPaintInformation& info) const;

    qreal computeSizeLikeValue(const KisPaintInformation &info) const;
198
    qreal computeRotationLikeValue(const KisPaintInformation& info, qreal baseValue, bool absoluteAxesFlipped) const;
199

200
protected:
201

202
    void setValueRange(qreal min, qreal max);
203

204 205 206
    /**
     * Read the option using the prefix in argument
     */
207
    void readNamedOptionSetting(const QString& prefix, const KisPropertiesConfigurationSP setting);
208

209
    QString m_name;
210
    KisPaintOpOption::PaintopCategory m_category;
211

212 213
    bool m_checkable;
    bool m_checked;
214 215 216 217
    bool m_useCurve;
    bool m_useSameCurve;
    bool m_separateCurveValue;

218 219 220 221 222 223
    /**
     * Curve that is being used instead of sensors' internal ones
     * in case "Use the same curve" is checked.
     */
    KisCubicCurve m_commonCurve;

224 225
    int m_curveMode;

226
    QMap<DynamicSensorType, KisDynamicSensorSP> m_sensorMap;
227

228
private:
229 230 231 232

    qreal m_value;
    qreal m_minValue;
    qreal m_maxValue;
233 234 235
};

#endif