Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_brush_export.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2016 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "kis_brush_export.h"
8
9#include <QCheckBox>
10#include <QSlider>
11#include <QBuffer>
12
13#include <KoProperties.h>
14#include <KoDialog.h>
15#include <kpluginfactory.h>
16#include <QFileInfo>
17
19#include <kis_paint_device.h>
20#include <KisViewManager.h>
21#include <kis_image.h>
22#include <KisDocument.h>
23#include <kis_paint_layer.h>
25#include <kis_gbr_brush.h>
26#include <kis_imagepipe_brush.h>
29#include <KisWdgOptionsBrush.h>
31#include <kis_config.h>
32
42
43
44K_PLUGIN_FACTORY_WITH_JSON(KisBrushExportFactory, "krita_brush_export.json", registerPlugin<KisBrushExport>();)
45
46KisBrushExport::KisBrushExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent)
47{
48}
49
53
55{
56
57// XXX: Loading the parasite itself was commented out -- needs investigation
58// KisAnnotationSP annotation = document->savingImage()->annotation("ImagePipe Parasite");
59// KisPipeBrushParasite parasite;
60// if (annotation) {
61// QBuffer buf(const_cast<QByteArray*>(&annotation->annotation()));
62// buf.open(QBuffer::ReadOnly);
63// parasite.loadFromDevice(&buf);
64// buf.close();
65// }
66
67 KisBrushExportOptions exportOptions;
68
69 if (document->savingImage()->dynamicPropertyNames().contains("brushspacing")) {
70 exportOptions.spacing = document->savingImage()->property("brushspacing").toFloat();
71 }
72 else {
73 exportOptions.spacing = configuration->getInt("spacing");
74 }
75 if (!configuration->getString("name").isEmpty()) {
76 exportOptions.name = configuration->getString("name");
77 }
78 else {
79 exportOptions.name = document->savingImage()->objectName();
80 }
81
82 exportOptions.mask = configuration->getBool("mask");
83 exportOptions.brushStyle = configuration->getInt("brushStyle");
84 exportOptions.dimensions = configuration->getInt("dimensions");
85
86 for (int i = 0; i < KisPipeBrushParasite::MaxDim; ++i) {
87 exportOptions.selectionModes[i] = configuration->getInt("selectionMode" + QString::number(i));
88 exportOptions.ranks[i] = configuration->getInt("rank" + QString::number(i));
89 }
90
91 KisGbrBrush *brush = 0;
92 if (mimeType() == "image/x-gimp-brush") {
93 brush = new KisGbrBrush(filename());
94 }
95 else if (mimeType() == "image/x-gimp-brush-animated") {
96 brush = new KisImagePipeBrush(filename());
97 }
98 else {
100 }
101
102 qApp->processEvents(); // For vector layers to be updated
103
104 QRect rc = document->savingImage()->bounds();
105
106 brush->setSpacing(exportOptions.spacing);
107
108 KisImagePipeBrush *pipeBrush = dynamic_cast<KisImagePipeBrush*>(brush);
109 if (pipeBrush) {
110 // Create parasite. XXX: share with KisCustomBrushWidget
112 devices.push_back(QVector<KisPaintDevice*>());
113
114 KoProperties properties;
115 properties.setProperty("visible", true);
116 QList<KisNodeSP> layers = document->savingImage()->root()->childNodes(QStringList("KisLayer"), properties);
117
118 Q_FOREACH (KisNodeSP node, layers) {
119 // push_front to behave exactly as gimp for gih creation
120 devices[0].push_front(node->projection().data());
121 }
122
124
125 for (int i = 0; i < KisPipeBrushParasite::MaxDim; ++i) {
126 switch (exportOptions.selectionModes[i]) {
127 case 0: modes.push_back(KisParasite::Constant); break;
128 case 1: modes.push_back(KisParasite::Random); break;
129 case 2: modes.push_back(KisParasite::Incremental); break;
130 case 3: modes.push_back(KisParasite::Pressure); break;
131 case 4: modes.push_back(KisParasite::Angular); break;
132 case 5: modes.push_back(KisParasite::Velocity); break;
133 default: modes.push_back(KisParasite::Incremental);
134 }
135 }
136
137 KisPipeBrushParasite parasite;
138
139 parasite.dim = exportOptions.dimensions;
140 parasite.ncells = devices.at(0).count();
141
142 int maxRanks = 0;
143 for (int i = 0; i < KisPipeBrushParasite::MaxDim; ++i) {
144 // ### This can mask some bugs, be careful here in the future
145 parasite.rank[i] = exportOptions.ranks[i];
146 parasite.selection[i] = modes.at(i);
147 maxRanks += exportOptions.ranks[i];
148 }
149
150 if (maxRanks > layers.count()) {
152 }
153 // XXX needs movement!
154 parasite.setBrushesCount();
155 pipeBrush->setParasite(parasite);
156 pipeBrush->setDevices(devices, rc.width(), rc.height());
157 }
158 else {
159 if (exportOptions.mask) {
160 QImage image = document->savingImage()->projection()->convertToQImage(0, 0, 0, rc.width(), rc.height(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
161 brush->setImage(image);
162 brush->setBrushTipImage(image);
163 } else {
164 brush->initFromPaintDev(document->savingImage()->projection(),0,0,rc.width(), rc.height());
165 }
166 }
167
168 brush->setName(exportOptions.name);
169 // brushes are created after devices are loaded, call mask mode after that
170 brush->setBrushApplication(exportOptions.mask ? ALPHAMASK : IMAGESTAMP);
171 brush->setWidth(rc.width());
172 brush->setHeight(rc.height());
173
174 if (brush->saveToDevice(io)) {
176 }
177 else {
179 }
180}
181
182KisPropertiesConfigurationSP KisBrushExport::defaultConfiguration(const QByteArray &/*from*/, const QByteArray &/*to*/) const
183{
185 cfg->setProperty("spacing", 1.0);
186 cfg->setProperty("name", "");
187 cfg->setProperty("mask", true);
188 cfg->setProperty("brushStyle", 0);
189 cfg->setProperty("dimensions", 1);
190
191 for (int i = 0; i < KisPipeBrushParasite::MaxDim; ++i) {
192 cfg->setProperty("selectionMode" + QString::number(i), 2);
193 cfg->getInt("rank" + QString::number(i), 0);
194 }
195 return cfg;
196}
197
198KisConfigWidget *KisBrushExport::createConfigurationWidget(QWidget *parent, const QByteArray &/*from*/, const QByteArray &to) const
199{
200 KisWdgOptionsBrush *wdg = new KisWdgOptionsBrush(parent);
201 if (to == "image/x-gimp-brush") {
202 wdg->groupBox->setVisible(false);
203 wdg->animStyleGroup->setVisible(false);
204 }
205 else if (to == "image/x-gimp-brush-animated") {
206 wdg->groupBox->setVisible(true);
207 wdg->animStyleGroup->setVisible(true);
208 }
209
210 // preload gih name with chosen filename
211 QFileInfo fileLocation(filename());
212 wdg->nameLineEdit->setText(fileLocation.completeBaseName());
213 return wdg;
214}
215
217{
218 QList<QPair<KoID, KoID> > supportedColorModels;
219 supportedColorModels << QPair<KoID, KoID>()
220 << QPair<KoID, KoID>(RGBAColorModelID, Integer8BitsColorDepthID)
221 << QPair<KoID, KoID>(GrayAColorModelID, Integer8BitsColorDepthID);
222 addSupportedColorModels(supportedColorModels, "Gimp Brushes");
223 if (mimeType() == "image/x-gimp-brush-animated") {
226 }
227}
228
229
230#include "kis_brush_export.moc"
231
VertexDescriptor get(PredecessorMap const &m, VertexDescriptor v)
QList< QString > QStringList
const KoID GrayAColorModelID("GRAYA", ki18n("Grayscale/Alpha"))
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
~KisBrushExport() override
KisImportExportErrorCode convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration=0) override
KisConfigWidget * createConfigurationWidget(QWidget *parent, const QByteArray &from="", const QByteArray &to="") const override
createConfigurationWidget creates a widget that can be used to define the settings for a given import...
KisPropertiesConfigurationSP defaultConfiguration(const QByteArray &from="", const QByteArray &to="") const override
defaultConfiguration defines the default settings for the given import export filter
KisBrushExport(QObject *parent, const QVariantList &)
void initializeCapabilities() override
virtual void setSpacing(double spacing)
void setWidth(qint32 width)
void setHeight(qint32 height)
virtual void setBrushApplication(enumBrushApplication brushApplication)
static KisExportCheckRegistry * instance()
void setBrushTipImage(const QImage &image) override
bool initFromPaintDev(KisPaintDeviceSP image, int x, int y, int w, int h)
bool saveToDevice(QIODevice *dev) const override
void setDevices(QVector< QVector< KisPaintDevice * > > devices, int w, int h)
void setParasite(const KisPipeBrushParasite &parasite)
The base class for import and export filters.
void addSupportedColorModels(QList< QPair< KoID, KoID > > supportedColorModels, const QString &name, KisExportCheckBase::Level level=KisExportCheckBase::PARTIALLY)
void addCapability(KisExportCheckBase *capability)
KisParasite::SelectionMode selection[MaxDim]
void setBrushesCount()
Initializes the brushesCount helper.
void setProperty(const QString &name, const QVariant &value)
K_PLUGIN_FACTORY_WITH_JSON(KritaASCCDLFactory, "kritaasccdl.json", registerPlugin< KritaASCCDL >();) KritaASCCDL
@ ALPHAMASK
Definition kis_brush.h:39
@ IMAGESTAMP
Definition kis_brush.h:40
virtual KisPaintDeviceSP projection() const =0
qint32 selectionModes[KisPipeBrushParasite::MaxDim]
qint32 ranks[KisPipeBrushParasite::MaxDim]
void setName(const QString &name)
void setImage(const QImage &image)