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