Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_grid_paintop.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2009, 2010 Lukáš Tvrdý (lukast.dev@gmail.com)
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "kis_grid_paintop.h"
9
10#include <cmath>
11
12#include <QtGlobal>
13#include <QRect>
14
15#include <kis_global.h>
16#include <kis_paint_device.h>
17#include <kis_painter.h>
18#include <kis_types.h>
23
24#include <KoColor.h>
25#include <KoColorSpace.h>
26#include <KoMixColorsOp.h>
27
28#include <KisColorOptionData.h>
29#include <kis_lod_transform.h>
30
31
32#ifdef BENCHMARK
33#include <QTime>
34#endif
35
36
38 : KisPaintOp(painter)
39 , m_settings(static_cast<KisGridPaintOpSettings*>(const_cast<KisPaintOpSettings*>(settings.data())))
40 , m_node(node)
41{
42
43 m_properties.read(settings.data());
44 m_colorProperties.read(settings.data());
45 m_shapeProperties.read(settings.data());
46
50
55#ifdef BENCHMARK
56 m_count = m_total = 0;
57#endif
58
59}
60
65
67{
68#ifdef BENCHMARK
69 QTime time;
70 time.start();
71#endif
72
73 KisRandomSourceSP randomSource = info.randomSource();
74 const qreal additionalScale = KisLodTransform::lodToScale(painter()->device());
75
76 m_dab->clear();
77
78 qreal gridWidth = m_properties.diameter * m_properties.grid_scale * additionalScale;
79 qreal gridHeight = m_properties.diameter * m_properties.grid_scale * additionalScale;
80
81 qreal cellWidth = m_properties.grid_width * m_properties.grid_scale * additionalScale;
82 qreal cellHeight = m_properties.grid_height * m_properties.grid_scale * additionalScale;
83
84 qreal horizontalOffset = m_properties.horizontal_offset;
85 qreal verticalOffset = m_properties.vertical_offset;
86
87 int divide;
90 }
91 else {
93 }
94
95 divide = qRound(m_properties.grid_scale * divide);
96
97 //Adjust the start position of the drawn grid to the top left of the brush instead of in the center
98 qreal posX = info.pos().x() - (gridWidth/2) + (cellWidth/2) - horizontalOffset;
99 qreal posY = info.pos().y() - (gridHeight/2) + (cellHeight/2) - verticalOffset;
100
101 //Lock the grid alignment
102 posX = posX - std::fmod(posX, cellWidth) + horizontalOffset;
103 posY = posY - std::fmod(posY, cellHeight) + verticalOffset;
104 const QRectF dabRect(posX , posY , cellWidth, cellHeight);
105 const QRect dabRectAligned = dabRect.toAlignedRect();
106
107 divide = qMax(1, divide);
108 const qreal yStep = cellHeight / (qreal)divide;
109 const qreal xStep = cellWidth / (qreal)divide;
110
111 QRectF tile;
112 KoColor color(painter()->paintColor());
113
114 QScopedPointer<KisCrossDeviceColorSampler> colorSampler;
115 if (m_node) {
116 colorSampler.reset(new KisCrossDeviceColorSampler(m_node->paintDevice(), color));
117 }
118
119 qreal vertBorder = m_properties.grid_vertical_border * additionalScale;
120 qreal horzBorder = m_properties.grid_horizontal_border * additionalScale;
122 if (vertBorder == horzBorder) {
123 vertBorder = horzBorder = vertBorder * randomSource->generateNormalized();
124 }
125 else {
126 vertBorder *= randomSource->generateNormalized();
127 horzBorder *= randomSource->generateNormalized();
128 }
129 }
130
131 bool shouldColor = true;
132 // fill the tile
134 m_dab->fill(dabRectAligned, painter()->backgroundColor());
135 }
136 for (int y = 0; y < (gridHeight)/yStep; y++) {
137 for (int x = 0; x < (gridWidth)/xStep; x++) {
138 // determine the tile size
139 tile = QRectF(dabRect.x() + x * xStep, dabRect.y() + y * yStep, xStep, yStep);
140 tile.adjust(vertBorder, horzBorder, -vertBorder, -horzBorder);
141 tile = tile.normalized();
142
143 // do color transformation
144 if (shouldColor) {
145 if (colorSampler && m_colorProperties.sampleInputColor) {
146 colorSampler->sampleOldColor(tile.center().x(), tile.center().y(), color.data());
147 }
148
149 // mix the color with background color
151 KoMixColorsOp * mixOp = source()->colorSpace()->mixColorsOp();
152
153 const quint8 *colors[2];
154 colors[0] = color.data();
155 colors[1] = painter()->backgroundColor().data();
156
157 qint16 colorWeights[2];
158 int MAX_16BIT = 255;
159 qreal blend = info.pressure();
160
161 colorWeights[0] = static_cast<quint16>(blend * MAX_16BIT);
162 colorWeights[1] = static_cast<quint16>((1.0 - blend) * MAX_16BIT);
163 mixOp->mixColors(colors, colorWeights, 2, color.data());
164 }
165
167 QHash<QString, QVariant> params;
168 params["h"] = (m_colorProperties.hue / 180.0) * randomSource->generateNormalized();
169 params["s"] = (m_colorProperties.saturation / 100.0) * randomSource->generateNormalized();
170 params["v"] = (m_colorProperties.value / 100.0) * randomSource->generateNormalized();
171 KoColorTransformation* transfo;
172 transfo = m_dab->colorSpace()->createColorTransformation("hsv_adjustment", params);
173 transfo->setParameter(3, 1);//sets the type to HSV. For some reason 0 is not an option.
174 transfo->setParameter(4, false);//sets the colorize to false.
175 transfo->transform(color.data(), color.data() , 1);
176 }
177
179 const qreal alpha = randomSource->generateNormalized();
180 color.setOpacity(alpha);
181 m_painter->setOpacityF(alpha);
182 }
183
185 shouldColor = false;
186 }
187 m_painter->setPaintColor(color);
188 }
189
190 // paint some element
191 switch (m_shapeProperties.shape) {
192 case 0: {
193 m_painter->paintEllipse(tile);
194 break;
195 }
196 case 1: {
197 // anti-aliased version
198 //m_painter->paintRect(tile);
199 m_dab->fill(tile.topLeft().x(), tile.topLeft().y(), tile.width(), tile.height(), color.data());
200 break;
201 }
202 case 2: {
203 m_painter->drawDDALine(tile.topRight(), tile.bottomLeft());
204 break;
205 }
206 case 3: {
207 m_painter->drawLine(tile.topRight(), tile.bottomLeft());
208 break;
209 }
210 case 4: {
211 m_painter->drawThickLine(tile.topRight(), tile.bottomLeft() , 1, 10);
212 break;
213 }
214 default: {
215 break;
216 }
217 }
218
220 color=painter()->paintColor();//reset color//
221 }
222 }
223 }
224
225 QRect rc = m_dab->extent();
226 painter()->bitBlt(rc.topLeft(), m_dab, rc);
228
229#ifdef BENCHMARK
230 int msec = time.elapsed();
231 dbgKrita << msec << " ms/dab " << "[average: " << m_total / (qreal)m_count << "]";
232 m_total += msec;
233 m_count++;
234#endif
235 return computeSpacing(additionalScale);
236}
237
243
245{
246 return KisSpacingInformation(m_spacing * lodScale);
247}
KisPainter * m_painter
KisColorOptionData m_colorProperties
KisSpacingInformation computeSpacing(qreal lodScale) const
KisGridPaintOp(const KisPaintOpSettingsSP settings, KisPainter *painter, KisNodeSP node, KisImageSP image)
KisSpacingInformation updateSpacingImpl(const KisPaintInformation &info) const override
~KisGridPaintOp() override
KisGridOpOptionData m_properties
KisGridShapeOptionData m_shapeProperties
KisSpacingInformation paintAt(const KisPaintInformation &info) override
KisPaintDeviceSP m_dab
static qreal lodToScale(int levelOfDetail)
virtual void clear()
KisPaintDeviceSP createCompositionSourceDevice() const
QRect extent() const
void fill(const QRect &rc, const KoColor &color)
const KoColorSpace * colorSpace() const
KisRandomSourceSP randomSource() const
const QPointF & pos() const
qreal pressure() const
The pressure of the value (from 0.0 to 1.0)
@ FillStyleForegroundColor
KoColor paintColor
void paintEllipse(const QRectF &rect)
void drawDDALine(const QPointF &start, const QPointF &end)
void drawThickLine(const QPointF &start, const QPointF &end, int startWidth, int endWidth)
void renderMirrorMask(QRect rc, KisFixedPaintDeviceSP dab)
void setOpacityF(qreal opacity)
void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
void setFillStyle(FillStyle fillStyle)
Set the current style with which to fill.
void drawLine(const QPointF &start, const QPointF &end)
KoColor backgroundColor
void setPaintColor(const KoColor &color)
qreal generateNormalized() const
KoColorTransformation * createColorTransformation(const QString &id, const QHash< QString, QVariant > &parameters) const
KoMixColorsOp * mixColorsOp
virtual void setParameter(int id, const QVariant &parameter)
virtual void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const =0
void setOpacity(quint8 alpha)
Definition KoColor.cpp:333
quint8 * data()
Definition KoColor.h:144
virtual void mixColors(const quint8 *const *colors, const qint16 *weights, int nColors, quint8 *dst, int weightSum=255) const =0
KisCrossDeviceColorSamplerImpl< SamplerTraitReal > KisCrossDeviceColorSampler
#define dbgKrita
Definition kis_debug.h:45
virtual KisPaintDeviceSP paintDevice() const =0
bool read(const KisPropertiesConfiguration *setting)
bool read(const KisPropertiesConfiguration *setting)
bool read(const KisPropertiesConfiguration *setting)
int shape
Ellipse, rectangle, line, pixel, anti-aliased pixel.
KisPainter * painter
KisPaintDeviceSP source() const