Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_hatching_paintop.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2008, 2009 Lukáš Tvrdý <lukast.dev@gmail.com>
3 * SPDX-FileCopyrightText: 2010 José Luis Vergara <pentalis@gmail.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
10
11#include <cmath>
12#include <QRect>
13
14#include <KoColor.h>
15#include <KoColorSpace.h>
16
17#include <kis_image.h>
18#include <kis_debug.h>
19
20#include <kis_global.h>
21#include <kis_paint_device.h>
22#include <kis_painter.h>
23#include <kis_types.h>
28#include <kis_lod_transform.h>
30
31
32
34
36 : KisBrushBasedPaintOp(settings, painter)
37 , m_angleOption(settings.data())
38 , m_crosshatchingOption(settings.data())
39 , m_separationOption(settings.data())
40 , m_thicknessOption(settings.data())
41 , m_opacityOption(settings.data(), node)
42 , m_sizeOption(settings.data())
43{
44 Q_UNUSED(node);
45
46 m_settings = static_cast<KisHatchingPaintOpSettings*>(settings->clone().data());
47 static_cast<const KisHatchingPaintOpSettings*>(settings.data())->initializeTwin(m_settings);
48
50 m_hatchingOptions.read(settings.data());
52
53}
54
59
61{
62 //------START SIMPLE ERROR CATCHING-------
63 if (!painter()->device()) return KisSpacingInformation(1.0);
64
65 if (!m_hatchedDab)
67 else
69
70 //Simple convenience renaming, I'm thinking of removing these inherited quirks
71 KisBrushSP brush = m_brush;
72 KisPaintDeviceSP device = painter()->device();
73
74 //Macro to catch errors
75 Q_ASSERT(brush);
76
77 //----------SIMPLE error catching code, maybe it's not even needed------
78 if (!brush) return KisSpacingInformation(1.0);
79 if (!brush->canPaintFor(info)) return KisSpacingInformation(1.0);
80
81 //SENSOR-depending settings
86
87 const qreal additionalScale = KisLodTransform::lodToScale(painter()->device());
88 const double scale = additionalScale * m_sizeOption.apply(info);
89 if ((scale * brush->width()) <= 0.01 || (scale * brush->height()) <= 0.01) return KisSpacingInformation(1.0);
90 KisDabShape shape(scale, 1.0, 0.0);
91
93
94 /*----Fetch the Dab----*/
96 static KoColor color(Qt::black, cs);
97
98 QRect dstRect;
99 KisFixedPaintDeviceSP maskDab =
100 m_dabCache->fetchDab(cs, color, info.pos(),
101 shape,
102 info, 1.0, &dstRect);
103
104 // sanity check
105 KIS_ASSERT_RECOVER_NOOP(dstRect.size() == maskDab->bounds().size());
106
107 /*-----Convenient renaming for the limits of the maskDab, this will be used
108 to hatch a dab of just the right size------*/
109 qint32 x, y, sw, sh;
110 dstRect.getRect(&x, &y, &sw, &sh);
111
112 //------This If_block pre-fills the future m_hatchedDab with a pretty backgroundColor
114 KoColor aersh = painter()->backgroundColor();
115 m_hatchedDab->fill(0, 0, (sw - 1), (sh - 1), aersh.data()); //this plus yellow background = french fry brush
116 }
117
118 /* If block describing how to stack hatching passes to generate
119 crosshatching according to user specifications */
123 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle(90), painter()->paintColor(), additionalScale);
124 }
127 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle(-45), painter()->paintColor(), additionalScale);
129 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle(45), painter()->paintColor(), additionalScale);
130 }
133 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle(45), painter()->paintColor(), additionalScale);
135 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle(-45), painter()->paintColor(), additionalScale);
136 }
138 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle((m_settings->crosshatchingsensorvalue) * 360), painter()->paintColor(), additionalScale);
139 }
140 } else {
142 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle(90), painter()->paintColor(), additionalScale);
143 }
145 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle(-45), painter()->paintColor(), additionalScale);
146 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle(45), painter()->paintColor(), additionalScale);
147 }
149 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle(45), painter()->paintColor(), additionalScale);
150 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle(-45), painter()->paintColor(), additionalScale);
151 }
153 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle(-10), painter()->paintColor(), additionalScale);
154 }
155 }
156
158 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, spinAngle((m_settings->anglesensorvalue)*360+m_hatchingOptions.angle), painter()->paintColor(), additionalScale);
159
160 // The base hatch... unless moiré or angle
162 m_hatchingBrush->hatch(m_hatchedDab, x, y, sw, sh, m_hatchingOptions.angle, painter()->paintColor(), additionalScale);
163
164
165 // The most important line, the one that paints to the screen.
166 painter()->bitBltWithFixedSelection(x, y, m_hatchedDab, maskDab, sw, sh);
167 painter()->renderMirrorMaskSafe(QRect(QPoint(x, y), QSize(sw, sh)), m_hatchedDab, 0, 0, maskDab,
169
170 return effectiveSpacing(scale);
171}
172
174{
175 const qreal scale = KisLodTransform::lodToScale(painter()->device()) * m_sizeOption.apply(info);
176 return effectiveSpacing(scale);
177}
178
180{
181 double tempangle = m_hatchingOptions.angle + spin;
182 qint8 factor = 1;
183
184 if (tempangle < 0)
185 factor = -1;
186
187 tempangle = fabs(fmod(tempangle, 180));
188
189 if ((tempangle >= 0) && (tempangle <= 90))
190 return factor * tempangle;
191 else if ((tempangle > 90) && (tempangle <= 180))
192 return factor * -(180 - tempangle);
193
194 return 0; // this should never be executed except if NAN
195}
void hatch(KisPaintDeviceSP dev, qreal x, qreal y, double width, double height, double givenAngle, const KoColor &color, qreal additionalScale)
KisSpacingInformation effectiveSpacing(qreal scale) const
bool isChecked() const
bool needSeparateOriginal() const
KisFixedPaintDeviceSP fetchDab(const KoColorSpace *cs, KisColorSource *colorSource, const QPointF &cursorPoint, KisDabShape const &, const KisPaintInformation &info, qreal softnessFactor, QRect *dstDabRect, qreal lightnessStrength=1.0)
KisThicknessOption m_thicknessOption
HatchingBrush * m_hatchingBrush
KisAngleOption m_angleOption
double spinAngle(double spin)
KisHatchingOptionsData m_hatchingOptions
KisCrosshatchingOption m_crosshatchingOption
KisSpacingInformation updateSpacingImpl(const KisPaintInformation &info) const override
KisSeparationOption m_separationOption
KisPaintDeviceSP m_hatchedDab
KisHatchingPreferencesData m_hatchingPreferences
KisHatchingPaintOpSettingsSP m_settings
KisSpacingInformation paintAt(const KisPaintInformation &info) override
KisHatchingPaintOp(const KisPaintOpSettingsSP settings, KisPainter *painter, KisNodeSP node, KisImageSP image)
KisOpacityOption m_opacityOption
static qreal lodToScale(int levelOfDetail)
void apply(KisPainter *painter, const KisPaintInformation &info) const
virtual void clear()
KisPaintDeviceSP createCompositionSourceDevice() const
void fill(const QRect &rc, const KoColor &color)
const QPointF & pos() const
void renderMirrorMaskSafe(QRect rc, KisFixedPaintDeviceSP dab, bool preserveDab)
KisPaintDeviceSP device
KoColor backgroundColor
void bitBltWithFixedSelection(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, const KisFixedPaintDeviceSP selection, qint32 selX, qint32 selY, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
qreal apply(const KisPaintInformation &info) const
quint8 * data()
Definition KoColor.h:144
#define KIS_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:97
CrosshatchingType crosshatchingStyle
bool read(const KisPropertiesConfiguration *setting)
bool read(const KisPropertiesConfiguration *setting)
KisPainter * painter
KisPaintDeviceSP source() const
static KoColorSpaceRegistry * instance()
const KoColorSpace * alpha8()