File indexing completed on 2025-02-02 04:22:18

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Ashwin Dhakaita <ashwingpdhakaita@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "MyPaintPaintOpSettings.h"
0008 
0009 #include <cmath>
0010 #include <KisOptimizedBrushOutline.h>
0011 #include <MyPaintStandardOptionData.h>
0012 
0013 #include <KisValueCache.h>
0014 
0015 
0016 struct KisMyPaintOpSettings::Private
0017 {
0018     struct Cache
0019     {
0020         qreal paintOpSize{0.0};
0021         qreal paintOpAngle{0.0};  // the original angle value as seen by KisPaintOpSettings interface
0022         qreal offsetValue{0.0};
0023     };
0024 
0025     struct CacheInitializer {
0026         CacheInitializer(KisMyPaintOpSettings *q) : m_q(q) {}
0027 
0028         Cache initialize() {
0029             Cache value;
0030 
0031             {
0032                 MyPaintOffsetByRandomData data;
0033                 data.read(m_q);
0034                 value.offsetValue = data.strengthValue;
0035             }
0036 
0037             {
0038                 MyPaintRadiusLogarithmicData data;
0039                 data.read(m_q);
0040                 value.paintOpSize = 2 * exp(data.strengthValue);
0041             }
0042 
0043             {
0044                 MyPaintEllipticalDabAngleData data;
0045                 data.read(m_q);
0046                 value.paintOpAngle = 180.0 - data.strengthValue;
0047             }
0048 
0049             return value;
0050         }
0051 
0052         KisMyPaintOpSettings *m_q;
0053     };
0054 
0055     Private(KisMyPaintOpSettings *q)
0056         : cache(q)
0057     {
0058     }
0059 
0060     KisValueCache<CacheInitializer> cache;
0061 };
0062 
0063 
0064 KisMyPaintOpSettings::KisMyPaintOpSettings(KisResourcesInterfaceSP resourcesInterface)
0065     : KisOutlineGenerationPolicy<KisPaintOpSettings>(KisCurrentOutlineFetcher::SIZE_OPTION |
0066                                                      KisCurrentOutlineFetcher::ROTATION_OPTION,
0067                                                      resourcesInterface),
0068     m_d(new Private(this))
0069 {
0070 }
0071 
0072 KisMyPaintOpSettings::~KisMyPaintOpSettings()
0073 {
0074 }
0075 
0076 void KisMyPaintOpSettings::setPaintOpSize(qreal value)
0077 {
0078     MyPaintRadiusLogarithmicData data;
0079     data.read(this);
0080     data.strengthValue = log(0.5 * value);
0081     data.write(this);
0082 }
0083 
0084 qreal KisMyPaintOpSettings::paintOpSize() const
0085 {
0086     return m_d->cache.value().paintOpSize;
0087 }
0088 
0089 void KisMyPaintOpSettings::setPaintOpAngle(qreal value)
0090 {
0091     MyPaintEllipticalDabAngleData data;
0092     data.read(this);
0093 
0094     value = normalizeAngleDegrees(value);
0095 
0096     if (value > 180.0) {
0097         value -= 180.0;
0098     }
0099 
0100     /**
0101      * All brushes are rotated in Krita counterclockwise,
0102      * so we should invert the value for MyPaint
0103      */
0104     value = 180.0 - value;
0105 
0106     data.strengthValue = value;
0107     data.write(this);
0108 }
0109 
0110 qreal KisMyPaintOpSettings::paintOpAngle() const
0111 {
0112     return m_d->cache.value().paintOpAngle;
0113 }
0114 
0115 void KisMyPaintOpSettings::setPaintOpOpacity(qreal value)
0116 {
0117     MyPaintOpacityData data;
0118     data.read(this);
0119     data.strengthValue = value;
0120     data.write(this);
0121 }
0122 
0123 qreal KisMyPaintOpSettings::paintOpOpacity()
0124 {
0125     MyPaintOpacityData data;
0126     data.read(this);
0127     return data.strengthValue;
0128 }
0129 
0130 bool KisMyPaintOpSettings::paintIncremental()
0131 {
0132     return true;
0133 }
0134 
0135 void KisMyPaintOpSettings::resetSettings(const QStringList &preserveProperties)
0136 {
0137     QStringList allKeys = preserveProperties;
0138     allKeys << MYPAINT_JSON;
0139     KisOutlineGenerationPolicy<KisPaintOpSettings>::resetSettings(allKeys);
0140 }
0141 
0142 void KisMyPaintOpSettings::onPropertyChanged()
0143 {
0144     m_d->cache.clear();
0145     KisOutlineGenerationPolicy::onPropertyChanged();
0146 }
0147 
0148 KisOptimizedBrushOutline KisMyPaintOpSettings::brushOutline(const KisPaintInformation &info, const OutlineMode &mode, qreal alignForZoom)
0149 {
0150     KisOptimizedBrushOutline path;
0151 
0152     if (mode.isVisible) {
0153         qreal finalScale = 1.0;
0154 
0155         const qreal offset = m_d->cache.value().offsetValue;
0156 
0157         qreal radius = 0.5 * m_d->cache.value().paintOpSize;
0158         radius = radius + 2 * radius * offset;
0159         radius = qBound(3.5, radius, 500.0);
0160 
0161         QPainterPath realOutline;
0162         realOutline.addEllipse(QPointF(), radius, radius);
0163 
0164         path = outlineFetcher()->fetchOutline(info, this, realOutline, mode, alignForZoom, finalScale);
0165 
0166         if (mode.showTiltDecoration) {
0167             QPainterPath tiltLine = makeTiltIndicator(info,
0168                 realOutline.boundingRect().center(),
0169                 realOutline.boundingRect().width() * 0.5,
0170                 3.0);
0171             path.addPath(outlineFetcher()->fetchOutline(info, this, tiltLine, mode, alignForZoom, finalScale, 0.0, true, realOutline.boundingRect().center().x(), realOutline.boundingRect().center().y()));
0172         }
0173     }
0174 
0175     return path;
0176 }