File indexing completed on 2024-05-19 04:24:14
0001 /* 0002 * SPDX-FileCopyrightText: 2008 Boudewijn Rempt <boud@valdyas.org> 0003 * SPDX-FileCopyrightText: 2010-2011 Lukáš Tvrdý <lukast.dev@gmail.com> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "kis_auto_brush_factory.h" 0009 0010 #include <QDomDocument> 0011 0012 #include "kis_auto_brush.h" 0013 #include "kis_mask_generator.h" 0014 #include <kis_dom_utils.h> 0015 #include <KoResourceLoadResult.h> 0016 #include "kis_mask_generator.h" 0017 0018 0019 KoResourceLoadResult KisAutoBrushFactory::createBrush(const QDomElement &brushDefinition, KisResourcesInterfaceSP resourcesInterface) 0020 { 0021 std::optional<KisBrushModel::BrushData> data = 0022 createBrushModel(brushDefinition, resourcesInterface); 0023 0024 if (data) { 0025 return createBrush(*data, resourcesInterface); 0026 } 0027 0028 // fallback, should never reach! 0029 return KoResourceSignature(ResourceType::Brushes, "", "", ""); 0030 } 0031 0032 KoResourceLoadResult KisAutoBrushFactory::createBrush(const KisBrushModel::BrushData &data, KisResourcesInterfaceSP resourcesInterface) 0033 { 0034 return createBrush(data.common, data.autoBrush, resourcesInterface); 0035 } 0036 0037 std::optional<KisBrushModel::BrushData> 0038 KisAutoBrushFactory::createBrushModel(const QDomElement &element, KisResourcesInterfaceSP resourcesInterface) 0039 { 0040 Q_UNUSED(resourcesInterface); 0041 0042 KisBrushModel::BrushData brush; 0043 0044 brush.type = KisBrushModel::Auto; 0045 brush.common.angle = KisDomUtils::toDouble(element.attribute("angle", "0.0")); 0046 brush.common.spacing = KisDomUtils::toDouble(element.attribute("spacing", "1.0")); 0047 brush.common.useAutoSpacing = KisDomUtils::toInt(element.attribute("useAutoSpacing", "0")); 0048 brush.common.autoSpacingCoeff = KisDomUtils::toDouble(element.attribute("autoSpacingCoeff", "1.0")); 0049 0050 // auto brush settings 0051 0052 brush.autoBrush.randomness = KisDomUtils::toDouble(element.attribute("randomness", "0.0")); 0053 brush.autoBrush.density = KisDomUtils::toDouble(element.attribute("density", "1.0")); 0054 0055 // generator settings 0056 0057 QDomElement generatorEl = element.firstChildElement("MaskGenerator"); 0058 0059 // backward compatibility -- it was mistakenly named radius for 2.2 0060 brush.autoBrush.generator.diameter = 0061 generatorEl.hasAttribute("radius") ? 0062 KisDomUtils::toDouble(generatorEl.attribute("radius", "1.0")) : 0063 KisDomUtils::toDouble(generatorEl.attribute("diameter", "1.0")); 0064 0065 brush.autoBrush.generator.ratio = KisDomUtils::toDouble(generatorEl.attribute("ratio", "1.0")); 0066 brush.autoBrush.generator.horizontalFade = KisDomUtils::toDouble(generatorEl.attribute("hfade", "0.0")); 0067 brush.autoBrush.generator.verticalFade = KisDomUtils::toDouble(generatorEl.attribute("vfade", "0.0")); 0068 brush.autoBrush.generator.antialiasEdges = generatorEl.attribute("antialiasEdges", "0").toInt(); 0069 brush.autoBrush.generator.spikes = generatorEl.attribute("spikes", "2").toInt(); 0070 0071 const QString shape = generatorEl.attribute("type", "circle"); 0072 brush.autoBrush.generator.shape = 0073 shape == "circle" ? KisBrushModel::Circle : KisBrushModel::Rectangle; 0074 0075 const QString type = generatorEl.attribute("id", DefaultId.id()); 0076 brush.autoBrush.generator.type = 0077 type == DefaultId.id() ? KisBrushModel::Default : 0078 type == SoftId.id() ? KisBrushModel::Soft : 0079 KisBrushModel::Gaussian; 0080 0081 if (generatorEl.hasAttribute("softness_curve")) { 0082 brush.autoBrush.generator.curveString = generatorEl.attribute("softness_curve",""); 0083 } 0084 0085 return {brush}; 0086 } 0087 0088 void KisAutoBrushFactory::toXML(QDomDocument &doc, QDomElement &e, const KisBrushModel::BrushData &model) 0089 { 0090 e.setAttribute("type", id()); 0091 e.setAttribute("BrushVersion", "2"); 0092 0093 e.setAttribute("spacing", QString::number(model.common.spacing)); 0094 e.setAttribute("useAutoSpacing", QString::number(model.common.useAutoSpacing)); 0095 e.setAttribute("autoSpacingCoeff", QString::number(model.common.autoSpacingCoeff)); 0096 e.setAttribute("angle", QString::number(model.common.angle)); 0097 e.setAttribute("randomness", QString::number(model.autoBrush.randomness)); 0098 e.setAttribute("density", QString::number(model.autoBrush.density)); 0099 0100 { 0101 QDomElement shapeElt = doc.createElement("MaskGenerator"); 0102 0103 shapeElt.setAttribute("diameter", QString::number(model.autoBrush.generator.diameter)); 0104 shapeElt.setAttribute("ratio", QString::number(model.autoBrush.generator.ratio)); 0105 shapeElt.setAttribute("hfade", QString::number(model.autoBrush.generator.horizontalFade)); 0106 shapeElt.setAttribute("vfade", QString::number(model.autoBrush.generator.verticalFade)); 0107 shapeElt.setAttribute("spikes", model.autoBrush.generator.spikes); 0108 shapeElt.setAttribute("type", model.autoBrush.generator.shape == KisBrushModel::Circle ? "circle" : "rct"); 0109 shapeElt.setAttribute("antialiasEdges", model.autoBrush.generator.antialiasEdges); 0110 0111 0112 QString idString; 0113 if (model.autoBrush.generator.type == KisBrushModel::Default) { 0114 idString = DefaultId.id(); 0115 } else if (model.autoBrush.generator.type == KisBrushModel::Soft) { 0116 idString = SoftId.id(); 0117 } else { 0118 idString = GaussId.id(); 0119 } 0120 0121 shapeElt.setAttribute("id", idString); 0122 0123 if (!model.autoBrush.generator.curveString.isEmpty()) { 0124 shapeElt.setAttribute("softness_curve", model.autoBrush.generator.curveString); 0125 } 0126 0127 e.appendChild(shapeElt); 0128 } 0129 } 0130 0131 KoResourceLoadResult KisAutoBrushFactory::createBrush(const KisBrushModel::CommonData &commonData, const KisBrushModel::AutoBrushData &autoBrushData, KisResourcesInterfaceSP resourcesInterface) 0132 { 0133 Q_UNUSED(resourcesInterface); 0134 0135 KisMaskGenerator *generator = 0; 0136 0137 if (autoBrushData.generator.type == KisBrushModel::Default && 0138 autoBrushData.generator.shape == KisBrushModel::Circle) { 0139 0140 generator = new KisCircleMaskGenerator(autoBrushData.generator.diameter, 0141 autoBrushData.generator.ratio, 0142 autoBrushData.generator.horizontalFade, 0143 autoBrushData.generator.verticalFade, 0144 autoBrushData.generator.spikes, 0145 autoBrushData.generator.antialiasEdges); 0146 0147 } else if (autoBrushData.generator.type == KisBrushModel::Default && 0148 autoBrushData.generator.shape == KisBrushModel::Rectangle) { 0149 0150 generator = new KisRectangleMaskGenerator(autoBrushData.generator.diameter, 0151 autoBrushData.generator.ratio, 0152 autoBrushData.generator.horizontalFade, 0153 autoBrushData.generator.verticalFade, 0154 autoBrushData.generator.spikes, 0155 autoBrushData.generator.antialiasEdges); 0156 0157 0158 } else if (autoBrushData.generator.type == KisBrushModel::Soft) { 0159 0160 QString curveString = autoBrushData.generator.curveString; 0161 if (curveString.isEmpty()) { 0162 curveString = "0,1;1,0"; 0163 } 0164 0165 const KisCubicCurve curve(curveString); 0166 0167 if (autoBrushData.generator.shape == KisBrushModel::Circle) { 0168 generator = new KisCurveCircleMaskGenerator(autoBrushData.generator.diameter, 0169 autoBrushData.generator.ratio, 0170 autoBrushData.generator.horizontalFade, 0171 autoBrushData.generator.verticalFade, 0172 autoBrushData.generator.spikes, 0173 curve, 0174 autoBrushData.generator.antialiasEdges); 0175 } else { 0176 generator = new KisCurveRectangleMaskGenerator(autoBrushData.generator.diameter, 0177 autoBrushData.generator.ratio, 0178 autoBrushData.generator.horizontalFade, 0179 autoBrushData.generator.verticalFade, 0180 autoBrushData.generator.spikes, 0181 curve, 0182 autoBrushData.generator.antialiasEdges); 0183 } 0184 0185 } else if (autoBrushData.generator.type == KisBrushModel::Gaussian && 0186 autoBrushData.generator.shape == KisBrushModel::Circle) { 0187 0188 generator = new KisGaussCircleMaskGenerator(autoBrushData.generator.diameter, 0189 autoBrushData.generator.ratio, 0190 autoBrushData.generator.horizontalFade, 0191 autoBrushData.generator.verticalFade, 0192 autoBrushData.generator.spikes, 0193 autoBrushData.generator.antialiasEdges); 0194 0195 } else if (autoBrushData.generator.type == KisBrushModel::Gaussian && 0196 autoBrushData.generator.shape == KisBrushModel::Rectangle) { 0197 0198 generator = new KisGaussRectangleMaskGenerator(autoBrushData.generator.diameter, 0199 autoBrushData.generator.ratio, 0200 autoBrushData.generator.horizontalFade, 0201 autoBrushData.generator.verticalFade, 0202 autoBrushData.generator.spikes, 0203 autoBrushData.generator.antialiasEdges); 0204 } 0205 0206 KisBrushSP brush = KisBrushSP(new KisAutoBrush(generator, commonData.angle, autoBrushData.randomness, autoBrushData.density)); 0207 brush->setSpacing(commonData.spacing); 0208 brush->setAutoSpacing(commonData.useAutoSpacing, commonData.autoSpacingCoeff); 0209 0210 return {brush}; 0211 }