Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_brush_mask_scalar_applicator.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2012 Sven Langkamp <sven.langkamp@gmail.com>
3 * SPDX-FileCopyrightText: 2012 Dmitry Kazakov <dimula73@gmail.com>
4 * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy@amyspark.me>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#ifndef KIS_BRUSH_SCALAR_APPLICATOR_H
10#define KIS_BRUSH_SCALAR_APPLICATOR_H
11
13#include "kis_global.h"
14#include "kis_random_source.h"
15
16template<class MaskGenerator, typename impl>
18 KisBrushMaskScalarApplicator(MaskGenerator *maskGenerator)
19 : m_maskGenerator(maskGenerator)
20 {
21 }
22
23 void process(const QRect &rect) override
24 {
26 }
27
28protected:
29 void processScalar(const QRect &rect)
30 {
33
34 qreal random = 1.0;
35 quint8 *dabPointer = m_d->device->data() + rect.y() * rect.width() * m_d->pixelSize;
36 quint8 alphaValue = OPACITY_TRANSPARENT_U8;
37 // this offset is needed when brush size is smaller then fixed device size
38 int offset = (m_d->device->bounds().width() - rect.width()) * m_d->pixelSize;
39 int supersample = 1;
40 if (m_maskGenerator->shouldSupersample()) {
41 // strengthen supersampling from 3x3 for very small dabs, to smooth out dashed strokes
42 supersample = (m_maskGenerator->shouldSupersample6x6() ? 6 : 3);
43 }
44 double invss = 1.0 / supersample;
45 int samplearea = pow2(supersample);
46 for (int y = rect.y(); y < rect.y() + rect.height(); y++) {
47 for (int x = rect.x(); x < rect.x() + rect.width(); x++) {
48 int value = 0;
49 for (int sy = 0; sy < supersample; sy++) {
50 for (int sx = 0; sx < supersample; sx++) {
51 double x_ = x + sx * invss - m_d->centerX;
52 double y_ = y + sy * invss - m_d->centerY;
53 double maskX = m_d->cosa * x_ - m_d->sina * y_;
54 double maskY = m_d->sina * x_ + m_d->cosa * y_;
55 value += m_maskGenerator->valueAt(maskX, maskY);
56 }
57 }
58 if (supersample != 1)
59 value /= samplearea;
60
61 if (m_d->randomness != 0.0) {
63 }
64
65 alphaValue = quint8((OPACITY_OPAQUE_U8 - value) * random);
66
67 // avoid computation of random numbers if density is full
68 if (m_d->density != 1.0) {
69 // compute density only for visible pixels of the mask
70 if (alphaValue != OPACITY_TRANSPARENT_U8) {
72 alphaValue = OPACITY_TRANSPARENT_U8;
73 }
74 }
75 }
76
77 if (m_d->color) {
78 memcpy(dabPointer, m_d->color, static_cast<size_t>(m_d->pixelSize));
79 }
80
81 m_d->colorSpace->applyAlphaU8Mask(dabPointer, &alphaValue, 1);
82 dabPointer += m_d->pixelSize;
83 } // endfor x
84 dabPointer += offset;
85 } // endfor y
86 }
87
88protected:
89 MaskGenerator *m_maskGenerator;
90 KisRandomSource m_randomSource; // TODO: make it more deterministic for LoD
91};
92
93#endif /* KIS_BRUSH_SCALAR_APPLICATOR_H */
float value(const T *src, size_t ch)
const quint8 OPACITY_TRANSPARENT_U8
const quint8 OPACITY_OPAQUE_U8
qreal generateNormalized() const
virtual void applyAlphaU8Mask(quint8 *pixels, const quint8 *alpha, qint32 nPixels) const =0
T pow2(const T &x)
Definition kis_global.h:166
void process(const QRect &rect) override
KisBrushMaskScalarApplicator(MaskGenerator *maskGenerator)