File indexing completed on 2025-01-26 04:11:23

0001 /*
0002  *  SPDX-FileCopyrightText: 2006-2007, 2009 Cyrille Berger <cberger@cberger.net>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #include "kis_color_source.h"
0008 #include <kis_paint_device.h>
0009 
0010 #include <resources/KoAbstractGradient.h>
0011 #include <KoColorSpaceRegistry.h>
0012 #include <KoColorTransformation.h>
0013 #include <KoMixColorsOp.h>
0014 #include <kis_datamanager.h>
0015 #include <kis_fill_painter.h>
0016 #include "kis_iterator_ng.h"
0017 #include "kis_selection.h"
0018 #include <brushengine/kis_random_source.h>
0019 #include <brushengine/kis_paint_information.h>
0020 
0021 #include <random>
0022 
0023 
0024 KisColorSource::~KisColorSource() { }
0025 
0026 KisUniformColorSource::KisUniformColorSource()
0027 {
0028 }
0029 
0030 KisUniformColorSource::~KisUniformColorSource()
0031 {
0032 }
0033 
0034 void KisUniformColorSource::rotate(double)
0035 {}
0036 
0037 void KisUniformColorSource::resize(double , double)
0038 {
0039     // Do nothing as plain color does not have size
0040 }
0041 
0042 void KisUniformColorSource::colorize(KisPaintDeviceSP dev, const QRect& size, const QPoint&) const
0043 {
0044     Q_UNUSED(size);
0045     KoColor c(dev->colorSpace());
0046     c.fromKoColor(m_color);
0047     dev->dataManager()->setDefaultPixel(c.data());
0048     dev->clear();
0049 }
0050 
0051 const KoColor& KisUniformColorSource::uniformColor() const
0052 {
0053     return m_color;
0054 }
0055 
0056 void KisUniformColorSource::applyColorTransformation(const KoColorTransformation* transfo)
0057 {
0058     transfo->transform(m_color.data(), m_color.data(), 1);
0059 }
0060 
0061 const KoColorSpace* KisUniformColorSource::colorSpace() const
0062 {
0063     return m_color.colorSpace();
0064 }
0065 
0066 //-------------------------------------------------//
0067 //---------------- KisPlainColorSource ---------------//
0068 //-------------------------------------------------//
0069 
0070 KisPlainColorSource::KisPlainColorSource(const KoColor& backGroundColor, const KoColor& foreGroundColor)
0071     : m_backGroundColor(backGroundColor)
0072     , m_cachedBackGroundColor(backGroundColor)
0073     , m_foreGroundColor(foreGroundColor)
0074 {
0075 }
0076 
0077 KisPlainColorSource::~KisPlainColorSource()
0078 {
0079 }
0080 
0081 void KisPlainColorSource::selectColor(double mix, const KisPaintInformation &pi)
0082 {
0083     Q_UNUSED(pi);
0084 
0085     if (m_color.colorSpace() != m_foreGroundColor.colorSpace()) {
0086         m_color = KoColor(m_foreGroundColor.colorSpace());
0087         m_cachedBackGroundColor = KoColor(m_foreGroundColor.colorSpace());
0088         m_cachedBackGroundColor.fromKoColor(m_backGroundColor);
0089     }
0090 
0091     const quint8 *colors[2];
0092     colors[0] = m_cachedBackGroundColor.data();
0093     colors[1] = m_foreGroundColor.data();
0094 
0095     // equally distribute mix factor over [0..255]
0096     // mix * 256 ensures that, with exception of mix==1.0, which gets special handling
0097     const int weight = (mix == 1.0) ? 255 : (int)(mix * 256);
0098     const qint16 weights[2] = { (qint16)(255 - weight), (qint16)weight };
0099 
0100     m_color.colorSpace()->mixColorsOp()->mixColors(colors, weights, 2, m_color.data());
0101 }
0102 
0103 //-------------------------------------------------//
0104 //--------------- KisGradientColorSource -------------//
0105 //-------------------------------------------------//
0106 
0107 KisGradientColorSource::KisGradientColorSource(const KoAbstractGradientSP gradient, const KoColorSpace* workingCS)
0108     : m_gradient(gradient)
0109 {
0110     m_color = KoColor(workingCS);
0111 
0112     Q_ASSERT(gradient);
0113 }
0114 
0115 KisGradientColorSource::~KisGradientColorSource()
0116 {
0117 }
0118 
0119 void KisGradientColorSource::selectColor(double mix, const KisPaintInformation &pi)
0120 {
0121     Q_UNUSED(pi);
0122     if (m_gradient) {
0123         m_gradient->colorAt(m_color, mix);
0124     }
0125 }
0126 
0127 //-------------------------------------------------//
0128 //--------------- KisGradientColorSource -------------//
0129 //-------------------------------------------------//
0130 
0131 KisUniformRandomColorSource::KisUniformRandomColorSource()
0132 {
0133 }
0134 
0135 KisUniformRandomColorSource::~KisUniformRandomColorSource()
0136 {
0137 }
0138 
0139 void KisUniformRandomColorSource::selectColor(double mix, const KisPaintInformation &pi)
0140 {
0141     Q_UNUSED(pi);
0142     Q_UNUSED(mix);
0143 
0144     KisRandomSourceSP source = pi.randomSource();
0145     m_color.fromQColor(QColor((int)source->generate(0, 255),
0146                               (int)source->generate(0, 255),
0147                               (int)source->generate(0, 255)));
0148 }
0149 
0150 
0151 //------------------------------------------------------//
0152 //--------------- KisTotalRandomColorSource ---------------//
0153 //------------------------------------------------------//
0154 
0155 KisTotalRandomColorSource::KisTotalRandomColorSource() : m_colorSpace(KoColorSpaceRegistry::instance()->rgb8())
0156 {
0157 }
0158 
0159 KisTotalRandomColorSource::~KisTotalRandomColorSource()
0160 {
0161 }
0162 
0163 void KisTotalRandomColorSource::selectColor(double mix, const KisPaintInformation &pi)
0164 {
0165     Q_UNUSED(mix);
0166     Q_UNUSED(pi);
0167 }
0168 
0169 void KisTotalRandomColorSource::applyColorTransformation(const KoColorTransformation*) {}
0170 const KoColorSpace* KisTotalRandomColorSource::colorSpace() const
0171 {
0172     return m_colorSpace;
0173 }
0174 
0175 void KisTotalRandomColorSource::colorize(KisPaintDeviceSP dev, const QRect& rect, const QPoint&) const
0176 {
0177     KoColor kc(dev->colorSpace());
0178 
0179     QColor qc;
0180 
0181     std::random_device rand_dev;
0182     std::default_random_engine rand_engine{rand_dev()};
0183     std::uniform_int_distribution<> rand_distr(0, 255);
0184 
0185     int pixelSize = dev->colorSpace()->pixelSize();
0186 
0187     KisHLineIteratorSP it = dev->createHLineIteratorNG(rect.x(), rect.y(), rect.width());
0188     for (int y = 0; y < rect.height(); y++) {
0189         do {
0190             qc.setRgb(rand_distr(rand_engine), rand_distr(rand_engine), rand_distr(rand_engine));
0191             kc.fromQColor(qc);
0192             memcpy(it->rawData(), kc.data(), pixelSize);
0193         } while (it->nextPixel());
0194         it->nextRow();
0195     }
0196 
0197 }
0198 
0199 void KisTotalRandomColorSource::rotate(double) {}
0200 void KisTotalRandomColorSource::resize(double , double) {}
0201 
0202 
0203 
0204 KoPatternColorSource::KoPatternColorSource(KisPaintDeviceSP _pattern, int _width, int _height, bool _locked)
0205     : m_device(_pattern)
0206     , m_bounds(QRect(0, 0, _width, _height))
0207     , m_locked(_locked)
0208 {
0209 }
0210 
0211 KoPatternColorSource::~KoPatternColorSource()
0212 {
0213 }
0214 
0215 void KoPatternColorSource::selectColor(double mix, const KisPaintInformation &pi)
0216 {
0217     Q_UNUSED(mix);
0218     Q_UNUSED(pi);
0219 }
0220 
0221 void KoPatternColorSource::applyColorTransformation(const KoColorTransformation* transfo)
0222 {
0223     Q_UNUSED(transfo);
0224 }
0225 
0226 const KoColorSpace* KoPatternColorSource::colorSpace() const
0227 {
0228     return m_device->colorSpace();
0229 }
0230 
0231 void KoPatternColorSource::colorize(KisPaintDeviceSP device, const QRect& rect, const QPoint& offset) const
0232 {
0233     KisFillPainter painter(device);
0234     if (m_locked) {
0235         painter.fillRect(rect.x(), rect.y(), rect.width(), rect.height(), m_device, m_bounds);
0236     }
0237     else {
0238         int x = offset.x() % m_bounds.width();
0239         int y = offset.y() % m_bounds.height();
0240 
0241         // Change the position, because the pattern is always applied starting
0242         // from (0,0) in the paint device reference
0243         device->setX(x);
0244         device->setY(y);
0245         painter.fillRect(rect.x() + x, rect.y() + y, rect.width(), rect.height(), m_device, m_bounds);
0246         device->setX(0);
0247         device->setY(0);
0248     }
0249 }
0250 
0251 void KoPatternColorSource::rotate(double r)
0252 {
0253     Q_UNUSED(r);
0254 }
0255 
0256 void KoPatternColorSource::resize(double xs, double ys)
0257 {
0258     Q_UNUSED(xs);
0259     Q_UNUSED(ys);
0260 }
0261