File indexing completed on 2024-05-19 04:24:17

0001 /*
0002  *  SPDX-FileCopyrightText: 2022 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "KisBrushModel.h"
0008 #include "kis_brush_registry.h"
0009 #include "brushengine/kis_paintop_lod_limitations.h"
0010 #include "KisGlobalResourcesInterface.h"
0011 #include <kis_predefined_brush_factory.h>
0012 
0013 namespace KisBrushModel {
0014 
0015 namespace detail {
0016 
0017 qreal effectiveSizeForBrush(BrushType type,
0018                             const AutoBrushData &autoBrush,
0019                             const PredefinedBrushData &predefinedBrush,
0020                             const TextBrushData &textBrush)
0021 {
0022     qreal result = 42;
0023 
0024     switch (type) {
0025     case Auto:
0026         result = autoBrush.generator.diameter;
0027         break;
0028     case Predefined:
0029         result = predefinedBrush.baseSize.width() * predefinedBrush.scale;
0030         break;
0031     case Text:
0032         result = textBrush.baseSize.width() * textBrush.scale;
0033         break;
0034     }
0035 
0036     return result;
0037 }
0038 
0039 QDomElement getBrushXMLElement(const KisPropertiesConfiguration *setting)
0040 {
0041     QDomElement element;
0042 
0043     QString brushDefinition = setting->getString("brush_definition");
0044 
0045     if (!brushDefinition.isEmpty()) {
0046         QDomDocument d;
0047         d.setContent(brushDefinition, false);
0048         element = d.firstChildElement("Brush");
0049     }
0050 
0051     return element;
0052 }
0053 
0054 }
0055 
0056 void BrushData::write(KisPropertiesConfiguration *settings) const
0057 {
0058     QDomDocument d;
0059     QDomElement e = d.createElement("Brush");
0060     KisBrushRegistry::instance()->toXML(d, e, *this);
0061     d.appendChild(e);
0062     settings->setProperty("brush_definition", d.toString());
0063 }
0064 
0065 std::optional<BrushData> BrushData::read(const KisPropertiesConfiguration *settings, KisResourcesInterfaceSP resourcesInterface)
0066 {
0067     QDomElement element = detail::getBrushXMLElement(settings);
0068     return KisBrushRegistry::instance()->createBrushModel(element, resourcesInterface);
0069 }
0070 
0071 KisPaintopLodLimitations brushLodLimitations(const BrushData &data)
0072 {
0073     KisPaintopLodLimitations l;
0074 
0075     if (!data.common.useAutoSpacing && data.common.spacing > 0.5) {
0076         l.limitations << KoID("huge-spacing", i18nc("PaintOp instant preview limitation", "Spacing > 0.5, consider disabling Instant Preview"));
0077     }
0078 
0079     if (data.type == Auto) {
0080         if (!qFuzzyCompare(data.autoBrush.density, 1.0)) {
0081             l.limitations << KoID("auto-brush-density", i18nc("PaintOp instant preview limitation", "Brush Density recommended value 100.0"));
0082         }
0083 
0084         if (!qFuzzyCompare(data.autoBrush.randomness, 0.0)) {
0085             l.limitations << KoID("auto-brush-randomness", i18nc("PaintOp instant preview limitation", "Brush Randomness recommended value 0.0"));
0086         }
0087     }
0088 
0089     return l;
0090 }
0091 
0092 qreal effectiveSizeForBrush(BrushType type,
0093                             const AutoBrushData &autoBrush,
0094                             const PredefinedBrushData &predefinedBrush,
0095                             const TextBrushData &textBrush)
0096 {
0097     qreal result = 42;
0098 
0099     switch (type) {
0100     case Auto:
0101         result = autoBrush.generator.diameter;
0102         break;
0103     case Predefined:
0104         result = predefinedBrush.baseSize.width() * predefinedBrush.scale;
0105         break;
0106     case Text:
0107         result = textBrush.baseSize.width() * textBrush.scale;
0108         break;
0109     }
0110 
0111     return result;
0112 }
0113 
0114 qreal lightnessModeActivated(BrushType type, const PredefinedBrushData &predefinedBrush)
0115 {
0116     // TODO: use effectiveApplication instead!!!
0117     return type == Predefined && predefinedBrush.application == LIGHTNESSMAP;
0118 }
0119 
0120 void setEffectiveSizeForBrush(const BrushType type,
0121                                AutoBrushData &autoBrush,
0122                                PredefinedBrushData &predefinedBrush,
0123                                TextBrushData &textBrush,
0124                                qreal value)
0125 {
0126     switch (type) {
0127     case Auto:
0128         autoBrush.generator.diameter = value;
0129         break;
0130     case Predefined:
0131         predefinedBrush.scale = value / predefinedBrush.baseSize.width();
0132         break;
0133     case Text:
0134         textBrush.scale = value / textBrush.baseSize.width();
0135         break;
0136     }
0137 }
0138 
0139 qreal effectiveSizeForBrush(const BrushData &brush)
0140 {
0141     return effectiveSizeForBrush(brush.type, brush.autoBrush, brush.predefinedBrush, brush.textBrush);
0142 }
0143 
0144 }