49 , m_sizeOption(settings.data())
50 , m_ratioOption(settings.data())
51 , m_rateOption(settings.data())
52 , m_softnessOption(settings.data())
53 , m_lightnessStrengthOption(settings.data())
54 , m_spacingOption(settings.data())
55 , m_scatterOption(settings.data())
56 , m_sharpnessOption(settings.data())
57 , m_rotationOption(settings.data())
58 , m_opacityOption(settings.data(), node)
61 , m_avgUpdateTimePerDab(50)
63 , m_minUpdatePeriod(10)
64 , m_maxUpdatePeriod(100)
77 m_brush->notifyBrushIsGoingToBeClonedForStroke();
80 auto resourcesFactory =
81 [baseBrush, settings,
painter] () {
84 resources->
brush = baseBrush->clone().dynamicCast<
KisBrush>();
112 if (!brush->canPaintFor(info))
125 brush->maskWidth(shape, 0, 0, info),
126 brush->maskHeight(shape, 0, 0, info));
181 const bool skipMirrorPixels = prevDabDevice && prevDabDevice ==
dab.device;
184 [state, &
dab, direction, skipMirrorPixels] () {
185 state->painter->mirrorDab(direction, &
dab, skipMirrorPixels);
189 prevDabDevice =
dab.device;
194 for (QRect &rc : rects) {
195 state->painter->mirrorRect(direction, &rc);
199 state->painter->bltFixed(rc, state->dabsQueue);
204 state->allDirtyRects.append(rects);
209 bool someDabsAreStillInQueue =
false;
210 const bool hasPreparedDabsAtStart =
m_dabExecutor->hasPreparedDabs();
220 const qreal dabRenderingTime =
m_dabExecutor->averageDabRenderingTime();
225 const int dabsLimit =
226 totalRenderingTimePerDab > 0 ?
230 state->dabsQueue =
m_dabExecutor->takeReadyDabs(
painter()->hasMirroring(), dabsLimit, &someDabsAreStillInQueue);
244 if (
painter()->device()->defaultBounds()->wrapAroundMode()) {
267 Q_FOREACH(
const QPoint &pt, normalizationOrigins) {
272 wrappedDabs.append(newDab);
276 state->dabsQueue = wrappedDabs;
281 rects.append(
dab.realBounds());
287 idealNumRects, diameter, spacing);
289 state->allDirtyRects = rects;
292 state->dabPoints.append(
dab.realBounds().center());
295 state->dabRenderingTimer.start();
297 Q_FOREACH (
const QRect &rc, rects) {
300 state->painter->bltFixed(rc, state->dabsQueue);
311 if (state->painter->hasHorizontalMirroring()) {
315 if (state->painter->hasVerticalMirroring()) {
319 if (state->painter->hasHorizontalMirroring() && state->painter->hasVerticalMirroring()) {
324 [state,
this, someDabsAreStillInQueue] () {
325 Q_FOREACH(
const QRect &rc, state->allDirtyRects) {
326 state->painter->addDirtyRect(rc);
329 state->painter->setAverageOpacity(state->dabsQueue.last().averageOpacity);
331 const int updateRenderingTime = state->dabRenderingTimer.elapsed();
332 const qreal dabRenderingTime =
m_dabExecutor->averageDabRenderingTime();
336 const qreal currentUpdateTimePerDab = qreal(updateRenderingTime) / state->dabsQueue.size();
344 const qreal totalRenderingTimePerDab = dabRenderingTime + currentUpdateTimePerDab;
346 const int approxDabRenderingTime =
360 state->dabsQueue.clear();
366 someDabsAreStillInQueue =
true;
396 p.setPaintColor(
painter()->paintColor());
397 p.drawDDALine(pi1.
pos(), pi2.
pos());
const qreal OPACITY_OPAQUE_F
KisMirrorOption m_mirrorOption
KisPrecisionOption m_precisionOption
KisSpacingInformation effectiveSpacing(qreal scale) const
bool checkSizeTooSmall(qreal scale)
KisScatterOption m_scatterOption
KisSoftnessOption m_softnessOption
KisRateOption m_rateOption
KisSpacingOption m_spacingOption
KisRotationOption m_rotationOption
KisRatioOption m_ratioOption
QScopedPointer< KisDabRenderingExecutor > m_dabExecutor
KisLightnessStrengthOption m_lightnessStrengthOption
const int m_idealNumRects
KisRollingMeanAccumulatorWrapper m_avgSpacing
KisSizeOption m_sizeOption
UpdateSharedStateSP m_updateSharedState
KisPaintDeviceSP m_lineCacheDevice
KisSharpnessOption m_sharpnessOption
qreal m_currentUpdatePeriod
void addMirroringJobs(Qt::Orientation direction, QVector< QRect > &rects, UpdateSharedStateSP state, QVector< KisRunnableStrokeJobData * > &jobs)
std::pair< int, bool > doAsynchronousUpdate(QVector< KisRunnableStrokeJobData * > &jobs) override
KisSpacingInformation paintAt(const KisPaintInformation &info) override
KisRollingMeanAccumulatorWrapper m_avgNumDabs
KisFlowOpacityOption2 m_opacityOption
void paintLine(const KisPaintInformation &pi1, const KisPaintInformation &pi2, KisDistanceInformation *currentDistance) override
KisSpacingInformation updateSpacingImpl(const KisPaintInformation &info) const override
const int m_minUpdatePeriod
KisRollingMeanAccumulatorWrapper m_avgUpdateTimePerDab
KisBrushOp(const KisPaintOpSettingsSP settings, KisPainter *painter, KisNodeSP node, KisImageSP image)
KisTimingInformation updateTimingImpl(const KisPaintInformation &info) const override
const int m_maxUpdatePeriod
KisAirbrushOptionData m_airbrushData
virtual WrapAroundAxis wrapAroundModeAxis() const =0
virtual QRect imageBorderRect() const
void apply(KisPainter *painter, const KisPaintInformation &info)
KisPaintDeviceSP createCompositionSourceDevice() const
virtual const KoColorSpace * compositionSourceColorSpace() const
KisDefaultBoundsBaseSP defaultBounds() const
void renderMirrorMask(QRect rc, KisFixedPaintDeviceSP dab)
void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
KisRunnableStrokeJobsInterface * runnableStrokeJobsInterface
bool hasImprecisePositionOptions() const
void setHasImprecisePositionOptions(bool value)
qreal rollingMeanSafe() const
qreal rollingMean() const
qreal apply(const KisPaintInformation &info) const
void applyFanCornersInfo(KisPaintOp *op)
QPointF apply(const KisPaintInformation &info, qreal width, qreal height) const
qreal apply(const KisPaintInformation &info) const
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
QSharedPointer< T > toQShared(T *ptr)
KisTimingInformation effectiveTiming(const KisAirbrushOptionData *airbrushOption, const KisRateOption *rateOption, const KisPaintInformation &pi)
QVector< QRect > splitDabsIntoRects(const QVector< QRect > &dabRects, int idealNumRects, int diameter, qreal spacing)
void addJobConcurrent(QVector< Job * > &jobs, Func func)
void addJobSequential(QVector< Job * > &jobs, Func func)
bool read(const KisPropertiesConfiguration *setting)
QList< KisRenderedDab > dabsQueue
QVector< QRect > allDirtyRects
QElapsedTimer dabRenderingTimer
QVector< QPointF > dabPoints
KisFixedPaintDeviceSP dab
KisPaintDeviceSP source() const
virtual void paintLine(const KisPaintInformation &pi1, const KisPaintInformation &pi2, KisDistanceInformation *currentDistance)
static QRect clipToWrapRect(QRect rc, const QRect &wrapRect, WrapAroundAxis wrapAxis)
static QVector< QPoint > normalizationOriginsForRect(const QRect &rc, const QRect &wrapRect, WrapAroundAxis wrapAxis)