9 #include <kis_paintop_settings.h>
10 #include <resources/KoPattern.h>
13 #include <KoColorSpace.h>
14 #include <KoColorSpaceRegistry.h>
16 #include <kis_algebra_2d.h>
17 #include <kis_lod_transform.h>
18 #include <kis_iterator_ng.h>
20 #include <QGlobalStatic>
28 : m_levelOfDetail(levelOfDetail),
29 m_preserveAlpha(preserveAlpha)
34 : m_levelOfDetail(rhs.m_levelOfDetail),
35 m_pattern(rhs.m_pattern),
37 m_brightness(rhs.m_brightness),
38 m_contrast(rhs.m_contrast),
39 m_neutralPoint(rhs.m_neutralPoint),
40 m_invert(rhs.m_invert),
41 m_cutoffLeft(rhs.m_cutoffLeft),
42 m_cutoffRight(rhs.m_cutoffRight),
43 m_cutoffPolicy(rhs.m_cutoffPolicy),
44 m_preserveAlpha(rhs.m_preserveAlpha)
54 lhs.m_levelOfDetail == rhs.m_levelOfDetail &&
55 (lhs.m_pattern == rhs.m_pattern ||
58 lhs.m_pattern->md5() == rhs.m_pattern->md5())) &&
59 qFuzzyCompare(lhs.m_scale, rhs.m_scale) &&
60 qFuzzyCompare(lhs.m_brightness, rhs.m_brightness) &&
61 qFuzzyCompare(lhs.m_contrast, rhs.m_contrast) &&
62 qFuzzyCompare(lhs.m_neutralPoint, rhs.m_neutralPoint) &&
63 lhs.m_invert == rhs.m_invert &&
64 lhs.m_cutoffLeft == rhs.m_cutoffLeft &&
65 lhs.m_cutoffRight == rhs.m_cutoffRight &&
66 lhs.m_cutoffPolicy == rhs.m_cutoffPolicy &&
67 lhs.m_preserveAlpha == rhs.m_preserveAlpha;
72 m_levelOfDetail = rhs.m_levelOfDetail;
73 m_pattern = rhs.m_pattern;
74 m_scale = rhs.m_scale;
75 m_brightness = rhs.m_brightness;
76 m_contrast = rhs.m_contrast;
77 m_neutralPoint = rhs.m_neutralPoint;
78 m_invert = rhs.m_invert;
79 m_cutoffLeft = rhs.m_cutoffLeft;
80 m_cutoffRight = rhs.m_cutoffRight;
81 m_cutoffPolicy = rhs.m_cutoffPolicy;
82 m_preserveAlpha = rhs.m_preserveAlpha;
88 return m_levelOfDetail;
106 if (!setting->hasProperty(
"Texture/Pattern/PatternMD5")) {
113 warnKrita <<
"WARNING: Couldn't load the pattern for a stroke";
117 m_scale = setting->getDouble(
"Texture/Pattern/Scale", 1.0);
118 m_brightness = setting->getDouble(
"Texture/Pattern/Brightness");
119 m_contrast = setting->getDouble(
"Texture/Pattern/Contrast", 1.0);
120 m_neutralPoint = setting->getDouble(
"Texture/Pattern/NeutralPoint", 0.5);
121 m_invert = setting->getBool(
"Texture/Pattern/Invert");
122 m_cutoffLeft = setting->getInt(
"Texture/Pattern/CutoffLeft", 0);
123 m_cutoffRight = setting->getInt(
"Texture/Pattern/CutoffRight", 255);
124 m_cutoffPolicy = setting->getInt(
"Texture/Pattern/CutoffPolicy", 0);
131 if (!m_pattern)
return;
133 const KoColorSpace* cs;
134 const bool useAlpha = m_pattern->hasAlpha() && m_preserveAlpha;
137 cs = KoColorSpaceRegistry::instance()->rgb8();
139 cs = KoColorSpaceRegistry::instance()->alpha8();
142 m_mask =
new KisPaintDevice(cs);
147 if ((
mask.format() != QImage::Format_RGB32) |
148 (
mask.format() != QImage::Format_ARGB32)) {
150 mask =
mask.convertToFormat(QImage::Format_ARGB32);
153 qreal scale = m_scale * KisLodTransform::lodToScale(m_levelOfDetail);
155 if (!qFuzzyCompare(scale, 0.0) && !qFuzzyCompare(scale, 1.0)) {
157 tf.
scale(scale, scale);
159 mask =
mask.scaled(rc.
size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
165 QRgb* pixel = reinterpret_cast<QRgb*>(
mask.bits());
166 const int width =
mask.width();
167 const int height =
mask.height();
169 KisHLineIteratorSP iter = m_mask->createHLineIteratorNG(0, 0, width);
171 for (
int row = 0; row < height; ++row) {
172 for (
int col = 0; col < width; ++col) {
173 const QRgb currentPixel = pixel[row * width + col];
175 const int red = qRed(currentPixel);
176 const int green = qGreen(currentPixel);
177 const int blue = qBlue(currentPixel);
178 float alpha = qAlpha(currentPixel) / 255.0;
180 const int grayValue = (red * 11 + green * 16 + blue * 5) / 32;
181 float maskValue = (grayValue / 255.0) * alpha + (1 - alpha);
183 maskValue = maskValue - m_brightness;
185 maskValue = ((maskValue - 0.5)*m_contrast)+0.5;
187 if (maskValue > 1.0) {maskValue = 1;}
188 else if (maskValue < 0) {maskValue = 0;}
191 maskValue = 1 - maskValue;
194 maskValue = qBound(0.0f, maskValue, 1.0f);
196 float neutralAdjustedValue;
200 if (m_neutralPoint == 1 || (m_neutralPoint != 0 && maskValue <= m_neutralPoint)) {
201 neutralAdjustedValue = maskValue / (2 * m_neutralPoint);
203 neutralAdjustedValue = 0.5 + (maskValue - m_neutralPoint) / (2 - 2 * m_neutralPoint);
206 if (m_cutoffPolicy == 1 && (neutralAdjustedValue < (m_cutoffLeft / 255.0) || neutralAdjustedValue >(m_cutoffRight / 255.0))) {
208 alpha = OPACITY_TRANSPARENT_F;
210 neutralAdjustedValue = alpha;
212 }
else if (m_cutoffPolicy == 2 && (neutralAdjustedValue < (m_cutoffLeft / 255.0) || neutralAdjustedValue >(m_cutoffRight / 255.0))) {
213 alpha = OPACITY_OPAQUE_F;
215 neutralAdjustedValue = alpha;
220 int finalValue = qRound(neutralAdjustedValue * 255.0);
221 pixel[row * width + col] =
QColor(finalValue, finalValue, finalValue, qRound(alpha * 255.0)).
rgba();
223 cs->setOpacity(iter->rawData(), neutralAdjustedValue, 1);
232 m_mask->convertFromQImage(
mask, 0);
234 m_maskBounds =
QRect(0, 0, width, height);
238 return m_pattern->hasAlpha();
258 if (!cachedInfo || *cachedInfo != *info) {