File indexing completed on 2024-05-12 15:56:11

0001 /*
0002  *  SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org>
0003  *  SPDX-FileCopyrightText: 2005 Bart Coppens <kde@bartcoppens.be>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 #include "kis_pipebrush_parasite.h"
0008 
0009 KisPipeBrushParasite::KisPipeBrushParasite(const QString& source)
0010 {
0011     init();
0012     needsMovement = false;
0013     QRegExp basicSplitter(" ");
0014     QRegExp parasiteSplitter(":");
0015     QStringList parasites = source.split(basicSplitter, QString::SkipEmptyParts);
0016     for (int i = 0; i < parasites.count(); i++) {
0017         QStringList split = parasites.at(i).split(parasiteSplitter, QString::SkipEmptyParts);
0018         if (split.count() != 2) {
0019             warnImage << "Wrong count for this parasite key/value:" << parasites.at(i);
0020             continue;
0021         }
0022         QString index = split.at(0);
0023         if (index == "dim") {
0024             dim = (split.at(1)).toInt();
0025             if (dim < 1 || dim > MaxDim) {
0026                 dim = 1;
0027             }
0028         } else if (index.startsWith(QString("sel"))) {
0029             int selIndex = index.mid(strlen("sel")).toInt();
0030 
0031             if (selIndex >= 0 && selIndex < dim) {
0032                 selectionMode = split.at(1);
0033 
0034                 if (selectionMode == "incremental") {
0035                     selection[selIndex] = KisParasite::Incremental;                    
0036                 }
0037                 else if (selectionMode == "angular") {
0038                     selection[selIndex] = KisParasite::Angular;
0039                     needsMovement = true;
0040                 }
0041                 else if (selectionMode == "random") {
0042                     selection[selIndex] = KisParasite::Random;
0043                 }
0044                 else if (selectionMode == "pressure") {
0045                     selection[selIndex] = KisParasite::Pressure;
0046                 }
0047                 else if (selectionMode == "xtilt") {
0048                     selection[selIndex] = KisParasite::TiltX;
0049                 }
0050                 else if (selectionMode == "ytilt") {
0051                     selection[selIndex] = KisParasite::TiltY;
0052                 }
0053                 else if (selectionMode == "velocity") {
0054                     selection[selIndex] = KisParasite::Velocity;
0055                 }
0056                 else {
0057                     selection[selIndex] = KisParasite::Constant;
0058                 }
0059             }
0060             else {
0061                 warnImage << "Sel: wrong index: " << selIndex << "(dim = " << dim << ")";
0062             }
0063         }
0064         else if (index.startsWith(QString("rank"))) {
0065             int rankIndex = index.mid(strlen("rank")).toInt();
0066             if (rankIndex < 0 || rankIndex > dim) {
0067                 warnImage << "Rankindex out of range: " << rankIndex;
0068                 continue;
0069             }
0070             rank[rankIndex] = (split.at(1)).toInt();
0071         }
0072         else if (index == "ncells") {
0073             ncells = (split.at(1)).toInt();
0074             if (ncells < 1) {
0075                 warnImage << "ncells out of range: " << ncells;
0076                 ncells = 1;
0077             }
0078         }
0079     }
0080 
0081     for (int i = 0; i < dim; i++) {
0082         index[i] = 0;
0083     }
0084 
0085     setBrushesCount();
0086 }
0087 
0088 void KisPipeBrushParasite::init()
0089 {
0090     for (int i = 0; i < MaxDim; i++) {
0091         rank[i] = index[i] = brushesCount[i] = 0;
0092         selection[i] = KisParasite::Constant;
0093     }
0094 }
0095 
0096 void KisPipeBrushParasite::sanitize()
0097 {
0098     for (int i = 0; i < dim; i++) {
0099         // In the 2 listed cases, we'd divide by 0!
0100         if (rank[i] == 0 &&
0101                 (selection[i] == KisParasite::Incremental
0102                  || selection[i] == KisParasite::Angular)) {
0103 
0104             warnImage << "PIPE brush has a wrong rank for its selection mode!";
0105             selection[i] = KisParasite::Constant;
0106         }
0107     }
0108 }
0109 
0110 void KisPipeBrushParasite::setBrushesCount()
0111 {
0112     // I assume ncells is correct. If it isn't, complain to the parasite header.
0113     if (rank[0] != 0) {
0114         brushesCount[0] = ncells / rank[0];
0115     }
0116     else {
0117         brushesCount[0] = ncells;
0118     }
0119     
0120     for (int i = 1; i < dim; i++) {
0121         if (rank[i] == 0) {
0122             brushesCount[i] = brushesCount[i - 1];
0123         }
0124         else {
0125             brushesCount[i] = brushesCount[i - 1] / rank[i];
0126         }
0127     }
0128 }
0129 
0130 bool KisPipeBrushParasite::saveToDevice(QIODevice* dev) const
0131 {
0132     // write out something like
0133     // <count> ncells:<count> dim:<dim> rank0:<rank0> sel0:<sel0> <...>
0134 
0135     QTextStream stream(dev);
0136     stream.setCodec("UTF-8");
0137 
0138     // XXX: FIXME things like step, placement and so are not added (nor loaded, as a matter of fact)"
0139     stream << ncells << " ncells:" << ncells << " dim:" << dim;
0140 
0141     for (int i = 0; i < dim; i++) {
0142         stream << " rank" << i << ":" << rank[i] << " sel" << i << ":";
0143         switch (selection[i]) {
0144         case KisParasite::Constant:
0145             stream << "constant"; break;
0146         case KisParasite::Incremental:
0147             stream << "incremental"; break;
0148         case KisParasite::Angular:
0149             stream << "angular"; break;
0150         case KisParasite::Velocity:
0151             stream << "velocity"; break;
0152         case KisParasite::Random:
0153             stream << "random"; break;
0154         case KisParasite::Pressure:
0155             stream << "pressure"; break;
0156         case KisParasite::TiltX:
0157             stream << "xtilt"; break;
0158         case KisParasite::TiltY:
0159             stream << "ytilt"; break;
0160         }
0161     }
0162 
0163     return true;
0164 }
0165 
0166 bool loadFromDevice(QIODevice */*dev*/)
0167 {
0168     // XXX: implement...
0169     return true;
0170 }