File indexing completed on 2024-12-22 04:11:42
0001 /* 0002 * KDE. Krita Project. 0003 * 0004 * SPDX-FileCopyrightText: 2020 Deif Lou <ginoba@gmail.com> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include <QList> 0010 0011 #include <KoCanvasResourcesIds.h> 0012 #include <KoColorSpaceRegistry.h> 0013 0014 #include "KisGradientConversion.h" 0015 0016 namespace KisGradientConversion 0017 { 0018 QGradientStops toQGradientStops(KoAbstractGradientSP gradient, 0019 KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0020 { 0021 if (!gradient) { 0022 return QGradientStops(); 0023 } 0024 if (gradient.dynamicCast<KoStopGradient>()) { 0025 return toQGradientStops(gradient.dynamicCast<KoStopGradient>(), canvasResourcesInterface); 0026 } else if (gradient.dynamicCast<KoSegmentGradient>()) { 0027 return toQGradientStops(gradient.dynamicCast<KoSegmentGradient>(), canvasResourcesInterface); 0028 } 0029 return QGradientStops(); 0030 } 0031 0032 QGradientStop toQGradientStop(const KoColor &color, KoGradientStopType type, qreal position, 0033 KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0034 { 0035 QGradientStop stop; 0036 stop.first = position; 0037 0038 if (type == FOREGROUNDSTOP) { 0039 if (canvasResourcesInterface) { 0040 canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>().toQColor(&stop.second); 0041 return stop; 0042 } 0043 } else if (type == BACKGROUNDSTOP) { 0044 if (canvasResourcesInterface) { 0045 canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>().toQColor(&stop.second); 0046 return stop; 0047 } 0048 } 0049 0050 color.toQColor(&stop.second); 0051 return stop; 0052 } 0053 0054 QGradientStops toQGradientStops(KoStopGradientSP gradient, 0055 KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0056 { 0057 QGradientStops stops; 0058 0059 if (!gradient) { 0060 return stops; 0061 } 0062 0063 qreal lastStopPosition = -1.0; 0064 for (const KoGradientStop &stopGradientStop : gradient->stops()) { 0065 if (qFuzzyCompare(stopGradientStop.position, lastStopPosition)) { 0066 stops << toQGradientStop( 0067 stopGradientStop.color, stopGradientStop.type, stopGradientStop.position + 0.000001, 0068 canvasResourcesInterface 0069 ); 0070 lastStopPosition = stopGradientStop.position + 0.000001; 0071 } else { 0072 stops << toQGradientStop( 0073 stopGradientStop.color, stopGradientStop.type, stopGradientStop.position, 0074 canvasResourcesInterface 0075 ); 0076 lastStopPosition = stopGradientStop.position; 0077 } 0078 } 0079 return stops; 0080 } 0081 0082 QGradientStop toQGradientStop(const KoColor &color, KoGradientSegmentEndpointType type, qreal offset, 0083 KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0084 { 0085 QGradientStop stop; 0086 stop.first = offset; 0087 0088 if (type == FOREGROUND_ENDPOINT) { 0089 if (canvasResourcesInterface) { 0090 canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>().toQColor(&stop.second); 0091 return stop; 0092 } 0093 } else if (type == FOREGROUND_TRANSPARENT_ENDPOINT) { 0094 if (canvasResourcesInterface) { 0095 canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>().toQColor(&stop.second); 0096 stop.second.setAlpha(0); 0097 return stop; 0098 } 0099 } else if (type == BACKGROUND_ENDPOINT) { 0100 if (canvasResourcesInterface) { 0101 canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>().toQColor(&stop.second); 0102 return stop; 0103 } 0104 } else if (type == BACKGROUND_TRANSPARENT_ENDPOINT) { 0105 if (canvasResourcesInterface) { 0106 canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>().toQColor(&stop.second); 0107 stop.second.setAlpha(0); 0108 return stop; 0109 } 0110 } 0111 0112 color.toQColor(&stop.second); 0113 return stop; 0114 } 0115 0116 QGradientStops toQGradientStops(KoSegmentGradientSP gradient, 0117 KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0118 { 0119 QGradientStops stops; 0120 0121 if (!gradient) { 0122 return stops; 0123 } 0124 0125 QGradientStop lastStop; 0126 lastStop.first = -1.0; 0127 0128 for (KoGradientSegment *segment : gradient->segments()) { 0129 QGradientStop stop; 0130 0131 stop = toQGradientStop( 0132 segment->startColor(), segment->startType(), segment->startOffset(), 0133 canvasResourcesInterface 0134 ); 0135 if (qFuzzyCompare(stop.first, lastStop.first)) { 0136 if (stop.second != lastStop.second) { 0137 stop.first = stop.first + 0.000001; 0138 stops << stop; 0139 lastStop = stop; 0140 } 0141 } else { 0142 stops << stop; 0143 lastStop = stop; 0144 } 0145 0146 stop = toQGradientStop( 0147 segment->endColor(), segment->endType(), segment->endOffset(), 0148 canvasResourcesInterface 0149 ); 0150 if (qFuzzyCompare(stop.first, lastStop.first)) { 0151 if (stop.second != lastStop.second) { 0152 stop.first = stop.first + 0.000001; 0153 stops << stop; 0154 lastStop = stop; 0155 } 0156 } else { 0157 stops << stop; 0158 lastStop = stop; 0159 } 0160 } 0161 0162 return stops; 0163 } 0164 0165 QGradient* toQGradient(KoAbstractGradientSP gradient, KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0166 { 0167 if (!gradient) { 0168 return nullptr; 0169 } 0170 if (gradient.dynamicCast<KoStopGradient>()) { 0171 return toQGradient(gradient.dynamicCast<KoStopGradient>(), canvasResourcesInterface); 0172 } else if (gradient.dynamicCast<KoSegmentGradient>()) { 0173 return toQGradient(gradient.dynamicCast<KoSegmentGradient>(), canvasResourcesInterface); 0174 } 0175 return nullptr; 0176 } 0177 0178 QGradient* toQGradient(KoStopGradientSP gradient, KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0179 { 0180 if (!gradient) { 0181 return nullptr; 0182 } 0183 QGradient *qGradient = new QLinearGradient; 0184 qGradient->setStops(toQGradientStops(gradient, canvasResourcesInterface)); 0185 return qGradient; 0186 } 0187 0188 QGradient* toQGradient(KoSegmentGradientSP gradient, KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0189 { 0190 if (!gradient) { 0191 return nullptr; 0192 } 0193 QGradient *qGradient = new QLinearGradient; 0194 qGradient->setStops(toQGradientStops(gradient, canvasResourcesInterface)); 0195 return qGradient; 0196 } 0197 0198 KoAbstractGradientSP toAbstractGradient(const QGradientStops &gradient) 0199 { 0200 return toStopGradient(gradient).dynamicCast<KoAbstractGradient>(); 0201 } 0202 0203 KoAbstractGradientSP toAbstractGradient(const QGradient *gradient) 0204 { 0205 if (!gradient) { 0206 return nullptr; 0207 } 0208 return toStopGradient(gradient).dynamicCast<KoAbstractGradient>(); 0209 } 0210 0211 KoAbstractGradientSP toAbstractGradient(KoStopGradientSP gradient) 0212 { 0213 if (!gradient) { 0214 return nullptr; 0215 } 0216 return gradient->clone().dynamicCast<KoAbstractGradient>(); 0217 } 0218 0219 KoAbstractGradientSP toAbstractGradient(KoSegmentGradientSP gradient) 0220 { 0221 if (!gradient) { 0222 return nullptr; 0223 } 0224 return gradient->clone().dynamicCast<KoAbstractGradient>(); 0225 } 0226 0227 KoStopGradientSP toStopGradient(const QGradientStops &gradient) 0228 { 0229 KoStopGradientSP stopGradient(new KoStopGradient); 0230 QList<KoGradientStop> stops; 0231 0232 for (const QGradientStop &qGradientStop : gradient) { 0233 KoGradientStop stop; 0234 stop.type = COLORSTOP; 0235 stop.position = qGradientStop.first; 0236 stop.color = KoColor(qGradientStop.second, stopGradient->colorSpace()); 0237 stops << stop; 0238 } 0239 0240 stopGradient->setStops(stops); 0241 stopGradient->setType(QGradient::LinearGradient); 0242 stopGradient->setValid(true); 0243 0244 return stopGradient; 0245 } 0246 0247 KoStopGradientSP toStopGradient(const QGradient *gradient) 0248 { 0249 if (!gradient || gradient->type() == QGradient::NoGradient) { 0250 return nullptr; 0251 } 0252 KoStopGradientSP stopGradient = toStopGradient(gradient->stops()); 0253 stopGradient->setType(gradient->type()); 0254 stopGradient->setSpread(gradient->spread()); 0255 return stopGradient; 0256 } 0257 0258 KoStopGradientSP toStopGradient(KoAbstractGradientSP gradient, 0259 KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0260 { 0261 if (!gradient) { 0262 return nullptr; 0263 } 0264 if (gradient.dynamicCast<KoStopGradient>()) { 0265 return gradient->clone().dynamicCast<KoStopGradient>(); 0266 } else if (gradient.dynamicCast<KoSegmentGradient>()) { 0267 return toStopGradient(gradient.dynamicCast<KoSegmentGradient>(), canvasResourcesInterface); 0268 } 0269 return nullptr; 0270 } 0271 0272 KoGradientStop toKoGradientStop(const KoColor &color, KoGradientSegmentEndpointType type, qreal offset, 0273 KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0274 { 0275 KoGradientStop stop; 0276 0277 stop.position = offset; 0278 0279 if (type == FOREGROUND_ENDPOINT) { 0280 stop.type = FOREGROUNDSTOP; 0281 stop.color = color; 0282 } else if (type == FOREGROUND_TRANSPARENT_ENDPOINT) { 0283 stop.type = COLORSTOP; 0284 if (canvasResourcesInterface) { 0285 stop.color = canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>(); 0286 } else { 0287 stop.color = color; 0288 } 0289 stop.color.setOpacity(static_cast<quint8>(0)); 0290 } else if (type == BACKGROUND_ENDPOINT) { 0291 stop.type = BACKGROUNDSTOP; 0292 stop.color = color; 0293 } else if (type == BACKGROUND_TRANSPARENT_ENDPOINT) { 0294 stop.type = COLORSTOP; 0295 if (canvasResourcesInterface) { 0296 stop.color = canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>(); 0297 } else { 0298 stop.color = color; 0299 } 0300 stop.color.setOpacity(static_cast<quint8>(0)); 0301 } else { 0302 stop.type = COLORSTOP; 0303 stop.color = color; 0304 } 0305 0306 return stop; 0307 } 0308 0309 KoStopGradientSP toStopGradient(KoSegmentGradientSP gradient, KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0310 { 0311 if (!gradient) { 0312 return nullptr; 0313 } 0314 0315 KoStopGradientSP stopGradient(new KoStopGradient); 0316 QList<KoGradientStop> stops; 0317 0318 KoGradientStop lastStop; 0319 lastStop.position = -1.0; 0320 0321 for (KoGradientSegment *segment : gradient->segments()) { 0322 KoGradientStop stop; 0323 0324 stop = toKoGradientStop( 0325 segment->startColor(), segment->startType(), segment->startOffset(), 0326 canvasResourcesInterface 0327 ); 0328 stop.color.convertTo(stopGradient->colorSpace()); 0329 if (!qFuzzyCompare(stop.position, lastStop.position) || stop.type != lastStop.type || stop.color != lastStop.color) { 0330 stops << stop; 0331 lastStop.type = stop.type; 0332 lastStop.color = stop.color; 0333 lastStop.position = stop.position; 0334 } 0335 0336 stop = toKoGradientStop( 0337 segment->endColor(), segment->endType(), segment->endOffset(), 0338 canvasResourcesInterface 0339 ); 0340 stop.color.convertTo(stopGradient->colorSpace()); 0341 if (!qFuzzyCompare(stop.position, lastStop.position) || stop.type != lastStop.type || stop.color != lastStop.color) { 0342 stops << stop; 0343 lastStop.type = stop.type; 0344 lastStop.color = stop.color; 0345 lastStop.position = stop.position; 0346 } 0347 } 0348 0349 stopGradient->setType(gradient->type()); 0350 stopGradient->setSpread(gradient->spread()); 0351 stopGradient->setStops(stops); 0352 0353 stopGradient->setName(gradient->name()); 0354 stopGradient->setFilename(gradient->filename()); 0355 stopGradient->setValid(true); 0356 0357 return stopGradient; 0358 } 0359 0360 KoSegmentGradientSP toSegmentGradient(const QGradientStops &gradient) 0361 { 0362 KoSegmentGradientSP segmentGradient(new KoSegmentGradient); 0363 const QGradientStops &stops = gradient; 0364 0365 for (int i = 0; i < stops.size() - 1; ++i) { 0366 if (qFuzzyCompare(stops[i].first, stops[i + 1].first)) { 0367 continue; 0368 } 0369 segmentGradient->createSegment( 0370 INTERP_LINEAR, COLOR_INTERP_RGB, 0371 stops[i].first, stops[i + 1].first, (stops[i].first + stops[i + 1].first) / 2, 0372 stops[i].second, stops[i + 1].second 0373 ); 0374 } 0375 0376 segmentGradient->setValid(true); 0377 0378 return segmentGradient; 0379 } 0380 0381 KoSegmentGradientSP toSegmentGradient(const QGradient *gradient) 0382 { 0383 if (!gradient || gradient->type() == QGradient::NoGradient) { 0384 return nullptr; 0385 } 0386 KoSegmentGradientSP segmentGradient = toSegmentGradient(gradient->stops()); 0387 segmentGradient->setType(gradient->type()); 0388 segmentGradient->setSpread(gradient->spread()); 0389 return segmentGradient; 0390 } 0391 0392 KoSegmentGradientSP toSegmentGradient(KoAbstractGradientSP gradient) 0393 { 0394 if (!gradient) { 0395 return nullptr; 0396 } 0397 if (gradient.dynamicCast<KoSegmentGradient>()) { 0398 return gradient->clone().dynamicCast<KoSegmentGradient>(); 0399 } else if (gradient.dynamicCast<KoStopGradient>()) { 0400 return toSegmentGradient(gradient.dynamicCast<KoStopGradient>()); 0401 } 0402 return nullptr; 0403 } 0404 0405 KoSegmentGradientSP toSegmentGradient(KoStopGradientSP gradient) 0406 { 0407 if (!gradient) { 0408 return nullptr; 0409 } 0410 0411 KoSegmentGradientSP segmentGradient(new KoSegmentGradient); 0412 QList<KoGradientStop> stops = gradient->stops(); 0413 0414 for (int i = 0; i < stops.size() - 1; ++i) { 0415 if (qFuzzyCompare(stops[i].position, stops[i + 1].position)) { 0416 continue; 0417 } 0418 0419 KoGradientSegmentEndpointType startType, endType; 0420 const KoGradientStopType startStopType = stops[i].type; 0421 const KoGradientStopType endStopType = stops[i + 1].type; 0422 0423 if (startStopType == FOREGROUNDSTOP) { 0424 startType = FOREGROUND_ENDPOINT; 0425 } else if (startStopType == BACKGROUNDSTOP) { 0426 startType = BACKGROUND_ENDPOINT; 0427 } else { 0428 startType = COLOR_ENDPOINT; 0429 } 0430 0431 if (endStopType == FOREGROUNDSTOP) { 0432 endType = FOREGROUND_ENDPOINT; 0433 } else if (endStopType == BACKGROUNDSTOP) { 0434 endType = BACKGROUND_ENDPOINT; 0435 } else { 0436 endType = COLOR_ENDPOINT; 0437 } 0438 0439 segmentGradient->createSegment( 0440 INTERP_LINEAR, COLOR_INTERP_RGB, 0441 stops[i].position, stops[i + 1].position, (stops[i].position + stops[i + 1].position) / 2, 0442 stops[i].color.toQColor(), stops[i + 1].color.toQColor(), 0443 startType, endType 0444 ); 0445 } 0446 0447 segmentGradient->setType(gradient->type()); 0448 segmentGradient->setSpread(gradient->spread()); 0449 0450 segmentGradient->setName(gradient->name()); 0451 segmentGradient->setFilename(gradient->filename()); 0452 segmentGradient->setValid(true); 0453 0454 return segmentGradient; 0455 } 0456 }