Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_brush_based_paintop.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2008 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
10#include "kis_brush_option.h"
11#include "KisSpacingOption.h"
12#include "kis_painter.h"
13#include <kis_lod_transform.h>
14#include "kis_paintop_utils.h"
16#include <KisResourceTypes.h>
17#include <QGlobalStatic>
18#include <kis_brush_registry.h>
19#include <KisUsageLogger.h>
21
22#include <QPainter>
23
24#ifdef HAVE_THREADED_TEXT_RENDERING_WORKAROUND
25
27
28
30{
31 return s_instance;
32}
33
35{
36 if (KisBrushOptionProperties::isTextBrush(settings.data())) {
37 KisBrushOptionProperties brushOption;
38 brushOption.readOptionSetting(settings, settings->resourcesInterface(), settings->canvasResourcesInterface());
39 m_brush = brushOption.brush();
40 m_settings = settings;
41 }
42 else {
43 m_brush = 0;
44 m_settings = 0;
45 }
46}
47
49{
50 return (settings && settings == m_settings ? m_brush : 0);
51}
52
54 : m_settings(0)
55{}
56
58{}
59
60void KisBrushBasedPaintOp::preinitializeOpStatically(KisPaintOpSettingsSP settings)
61{
63}
64
65#endif /* HAVE_THREADED_TEXT_RENDERING_WORKAROUND */
66
67
68KisBrushBasedPaintOp::KisBrushBasedPaintOp(const KisPaintOpSettingsSP settings, KisPainter* painter, KisBrushTextureFlags textureFlags)
69 : KisPaintOp(painter),
70 m_textureOption(settings.data(),
71 settings->resourcesInterface(),
72 settings->canvasResourcesInterface(),
73 painter->device()->defaultBounds()->currentLevelOfDetail(),
74 textureFlags),
75 m_mirrorOption(settings.data()),
76 m_precisionOption(settings.data())
77{
78 Q_ASSERT(settings);
79
80#ifdef HAVE_THREADED_TEXT_RENDERING_WORKAROUND
82#endif /* HAVE_THREADED_TEXT_RENDERING_WORKAROUND */
83
84 if (!m_brush) {
85 const KisBrushBasedPaintOpSettings *brushBasedSettings =
86 dynamic_cast<const KisBrushBasedPaintOpSettings*>(settings.data());
87
88 if (brushBasedSettings) {
89 // we don't use KisBrushOptionProperties manually here because
90 // we want the properties to cache this brush in m_savedBrush
91 m_brush = brushBasedSettings->brush();
92 }
93
94 if (!m_brush) {
95 qWarning() << "Could not find brush tip " << settings->getString("brush_definition") << ", will use a default brush instead";
96 QString brushDefinition("<Brush useAutoSpacing=\"1\" angle=\"0\" spacing=\"0.1\" density=\"1\" BrushVersion=\"2\" type=\"auto_brush\" randomness=\"0\" autoSpacingCoeff=\"0.8\"> <MaskGenerator spikes=\"2\" hfade=\"1\" ratio=\"1\" diameter=\"40\" id=\"default\" type=\"circle\" antialiasEdges=\"1\" vfade=\"1\"/> </Brush> ");
97 QDomDocument d;
98 d.setContent(brushDefinition, false);
99 QDomElement element = d.firstChildElement("Brush");
100 m_brush = KisBrushRegistry::instance()->createBrush(element, settings->resourcesInterface()).resource<KisBrush>();
101 Q_ASSERT(m_brush);
102 }
103 }
104
105 m_brush->notifyStrokeStarted();
106
111
115}
116
121
123{
125
126 KisBrushOptionProperties brushOption;
127 resources << brushOption.prepareLinkedResources(settings, resourcesInterface);
128
129 resources << KisTextureOption::prepareLinkedResources(settings, resourcesInterface);
130
131 return resources;
132}
133
135{
137
138 resources << KisTextureOption::prepareEmbeddedResources(settings, resourcesInterface);
139
140 return resources;
141}
142
144{
145 scale *= m_brush->scale();
146 return KisPaintOpUtils::checkSizeTooSmall(scale, m_brush->width(), m_brush->height());
147}
148
150{
151 // we parse dab rotation separately, so don't count it
152 QSizeF metric = m_brush->characteristicSize(KisDabShape(scale, 1.0, 0));
153 return effectiveSpacing(metric.width(), metric.height(), 1.0, false, 0.0, false);
154}
155
157{
158 return effectiveSpacing(scale, rotation, static_cast<KisAirbrushOptionData*>(nullptr), nullptr, pi);
159}
160
161KisSpacingInformation KisBrushBasedPaintOp::effectiveSpacing(qreal scale, qreal rotation, const KisSpacingOption &spacingOption, const KisPaintInformation &pi) const
162{
163 return effectiveSpacing(scale, rotation, static_cast<KisAirbrushOptionData*>(nullptr), &spacingOption, pi);
164}
165
167 const KisAirbrushOptionData *airbrushOption,
168 const KisSpacingOption *spacingOption,
169 const KisPaintInformation &pi) const
170{
171 bool isotropicSpacing = spacingOption && spacingOption->isotropicSpacing();
172
174 const bool implicitFlipped = prop.horizontalMirror != prop.verticalMirror;
175
176 // we parse dab rotation separately, so don't count it
177 QSizeF metric = m_brush->characteristicSize(KisDabShape(scale, 1.0, 0));
178
179 return KisPaintOpPluginUtils::effectiveSpacing(metric.width(), metric.height(),
180 isotropicSpacing, rotation, implicitFlipped,
181 m_brush->spacing(),
182 m_brush->autoSpacingActive(),
183 m_brush->autoSpacingCoeff(),
185 airbrushOption, spacingOption,
186 pi);
187}
188
190 qreal extraScale,
191 bool isotropicSpacing, qreal rotation,
192 bool axesFlipped) const
193{
194 return KisPaintOpUtils::effectiveSpacing(dabWidth, dabHeight,
195 extraScale,
196 true,
197 isotropicSpacing,
198 rotation,
199 axesFlipped,
200 m_brush->spacing(),
201 m_brush->autoSpacingActive(),
202 m_brush->autoSpacingCoeff(),
204}
205
207{
208 return m_brush != 0;
209}
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
KisBrushBasedPaintOp(const KisPaintOpSettingsSP settings, KisPainter *painter, KisBrushTextureFlags textureFlags=None)
KisPrecisionOption m_precisionOption
bool canPaint() const override
Reimplemented, false if brush is 0.
static QList< KoResourceLoadResult > prepareLinkedResources(const KisPaintOpSettingsSP settings, KisResourcesInterfaceSP resourcesInterface)
KisSpacingInformation effectiveSpacing(qreal scale) const
static QList< KoResourceLoadResult > prepareEmbeddedResources(const KisPaintOpSettingsSP settings, KisResourcesInterfaceSP resourcesInterface)
static KisBrushRegistry * instance()
KoResourceLoadResult createBrush(const QDomElement &element, KisResourcesInterfaceSP resourcesInterface)
bool isChecked() const
void setPrecisionOption(KisPrecisionOption *option)
void setMirrorPostprocessing(KisMirrorOption *option)
The KisDabCache class provides caching for dabs into the brush paintop.
void setTexturePostprocessing(KisTextureOption *option)
static qreal lodToScale(int levelOfDetail)
MirrorProperties apply(const KisPaintInformation &info) const
QList< KoResourceLoadResult > prepareLinkedResources(const KisPropertiesConfigurationPointer settings, KisResourcesInterfaceSP resourcesInterface) const
void readOptionSetting(KisPropertiesConfigurationPointer settings, KisResourcesInterfaceSP resourcesInterface, KoCanvasResourcesInterfaceSP canvasResourcesInterface)
bool hasImprecisePositionOptions() const
void setHasImprecisePositionOptions(bool value)
bool isotropicSpacing() const
static QList< KoResourceLoadResult > prepareEmbeddedResources(const KisPropertiesConfigurationSP setting, KisResourcesInterfaceSP resourcesInterface)
static QList< KoResourceLoadResult > prepareLinkedResources(const KisPropertiesConfigurationSP setting, KisResourcesInterfaceSP resourcesInterface)
KoResourceSP resource() const noexcept
static TextBrushInitializationWorkaround * instance()
KisPropertiesConfigurationSP m_settings
void preinitialize(KisPaintOpSettingsSP settings)
KisBrushSP tryGetBrush(const KisPropertiesConfigurationSP settings)
KisSpacingInformation effectiveSpacing(qreal dabWidth, qreal dabHeight, bool isotropicSpacing, qreal rotation, bool axesFlipped, qreal spacingVal, bool autoSpacingActive, qreal autoSpacingCoeff, qreal lodScale, const KisAirbrushOptionData *airbrushOption, const KisSpacingOption *spacingOption, const KisPaintInformation &pi)
KisSpacingInformation effectiveSpacing(qreal dabWidth, qreal dabHeight, qreal extraScale, bool distanceSpacingEnabled, bool isotropicSpacing, qreal rotation, bool axesFlipped, qreal spacingVal, bool autoSpacingActive, qreal autoSpacingCoeff, qreal lodScale)
bool checkSizeTooSmall(qreal scale, qreal width, qreal height)
KisPainter * painter
Private *const d