14#include <QPainterPath>
35#if defined(_WIN32) || defined(_WIN64)
38inline double drand48()
40 return double(rand()) / RAND_MAX;
60 QScopedPointer<KisMaskGenerator>
shape;
73 d->idealThreadCountCached = QThread::idealThreadCount();
84 setWidth(qMax(qreal(1.0),
d->shape->width()));
85 setHeight(qMax(qreal(1.0),
d->shape->height()));
115 Q_UNUSED(resourcesInterface);
130 result =
d->shape->valueAt(0,0) > 0.05 * 255;
150 return d->shape->diameter();
155 d->shape->setDiameter(
value);
209 int block1 = size / 8;
210 int block2 = size % 8;
212 quint32 *src =
reinterpret_cast<quint32*
>(color);
213 quint32 *dst =
reinterpret_cast<quint32*
>(buf);
220 for (
int i = 0; i < block1; i++) {
233 for (
int i = 0; i < block2; i++) {
248 int block1 = size / 8;
249 int block2 = size % 8;
251 for (
int i = 0; i < block1; i++) {
253 quint8 *d2 = buf + pixelSize;
254 quint8 *d3 = buf + 2 * pixelSize;
255 quint8 *d4 = buf + 3 * pixelSize;
256 quint8 *d5 = buf + 4 * pixelSize;
257 quint8 *d6 = buf + 5 * pixelSize;
258 quint8 *d7 = buf + 6 * pixelSize;
259 quint8 *d8 = buf + 7 * pixelSize;
261 for (
int j = 0; j < pixelSize; j++) {
262 *(d1 + j) = color[j];
263 *(d2 + j) = color[j];
264 *(d3 + j) = color[j];
265 *(d4 + j) = color[j];
266 *(d5 + j) = color[j];
267 *(d6 + j) = color[j];
268 *(d7 + j) = color[j];
269 *(d8 + j) = color[j];
272 buf += 8 * pixelSize;
275 for (
int i = 0; i < block2; i++) {
276 memcpy(buf, color, pixelSize);
285 double subPixelX ,
double subPixelY, qreal softnessFactor, qreal lightnessStrength)
const
288 Q_UNUSED(lightnessStrength);
295 int dstWidth =
maskWidth(shape, subPixelX, subPixelY, info);
296 int dstHeight =
maskHeight(shape, subPixelX, subPixelY, info);
304 if (coloringInformation) {
306 dst->
setRect(QRect(0, 0, dstWidth, dstHeight));
311 dst->
bounds().height() >= dstHeight);
316 quint8* dabPointer = dst->
data();
320 color =
const_cast<quint8*
>(coloringInformation->
color());
323 double centerX =
hotSpot.x() - 0.5 + subPixelX;
324 double centerY =
hotSpot.y() - 0.5 + subPixelY;
326 d->shape->setSoftness(softnessFactor);
330 for (
int y = 0; y < dstHeight; y++) {
331 for (
int x = 0; x < dstWidth; x++) {
332 memcpy(dabPointer, coloringInformation->
color(), pixelSize);
334 dabPointer += pixelSize;
336 coloringInformation->
nextRow();
341 d->randomness,
d->density,
345 const QRect
rect(0, 0, dstWidth, dstHeight);
363 QDomElement shapeElt = doc.createElement(
"MaskGenerator");
364 d->shape->toXML(doc, shapeElt);
365 e.appendChild(shapeElt);
366 e.setAttribute(
"type",
"auto_brush");
367 e.setAttribute(
"spacing", QString::number(
spacing()));
371 e.setAttribute(
"randomness", QString::number(
d->randomness));
372 e.setAttribute(
"density", QString::number(
d->density));
386 size.scale(128, 128, Qt::KeepAspectRatio);
414 return d->shape.data();
424 return d->randomness;
429 const bool requiresComplexOutline =
d->shape->spikes() > 2;
430 if (!requiresComplexOutline && !forcePreciseOutline) {
434 path.addEllipse(brushBoundingbox);
437 path.addRect(brushBoundingbox);
451 l->
limitations <<
KoID(
"auto-brush-density", i18nc(
"PaintOp instant preview limitation",
"Brush Density recommended value 100.0"));
455 l->
limitations <<
KoID(
"auto-brush-randomness", i18nc(
"PaintOp instant preview limitation",
"Brush Randomness recommended value 0.0"));
float value(const T *src, size_t ch)
void toXML(QDomDocument &, QDomElement &) const override
KisFixedPaintDeviceSP paintDevice(const KoColorSpace *, KisDabShape const &, const KisPaintInformation &, double=0, double=0) const override
qint32 maskWidth(KisDabShape const &shape, qreal subPixelX, qreal subPixelY, const KisPaintInformation &info) const override
const QScopedPointer< Private > d
void coldInitBrush() override
const KisMaskGenerator * maskGenerator() const
bool loadFromDevice(QIODevice *dev, KisResourcesInterfaceSP resourcesInterface) override
bool saveToDevice(QIODevice *dev) const override
KisFixedPaintDeviceSP outlineSourceImage() const override
void lodLimitations(KisPaintopLodLimitations *l) const override
bool supportsCaching() const override
void notifyBrushIsGoingToBeClonedForStroke() override
void setUserEffectiveSize(qreal value) override
qreal userEffectiveSize() const override
KoResourceSP clone() const override
bool isPiercedApprox() const override
qint32 maskHeight(KisDabShape const &shape, qreal subPixelX, qreal subPixelY, const KisPaintInformation &info) const override
void generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst, KisBrush::ColoringInformation *src, KisDabShape const &, const KisPaintInformation &info, double subPixelX=0, double subPixelY=0, qreal softnessFactor=DEFAULT_SOFTNESS_FACTOR, qreal lightnessStrength=DEFAULT_LIGHTNESS_STRENGTH) const override
QImage createBrushPreview(int maxSize=-1)
bool isEphemeral() const override
KisAutoBrush(KisMaskGenerator *as, qreal angle, qreal randomness, qreal density=1.0)
KisOptimizedBrushOutline outline(bool forcePreciseOutline=false) const override
QSizeF characteristicSize(KisDabShape const &) const override
virtual void process(const QRect &rect)=0
void initializeData(const MaskProcessingData *data)
virtual qint32 maskHeight(KisDabShape const &, qreal subPixelX, qreal subPixelY, const KisPaintInformation &info) const
virtual void lodLimitations(KisPaintopLodLimitations *l) const
virtual void setAngle(qreal _angle)
virtual void setBrushType(enumBrushType type)
bool autoSpacingActive() const
QPointF hotSpot(KisDabShape const &, const KisPaintInformation &info) const
void mask(KisFixedPaintDeviceSP dst, const KoColor &color, KisDabShape const &shape, const KisPaintInformation &info, double subPixelX=0, double subPixelY=0, qreal softnessFactor=DEFAULT_SOFTNESS_FACTOR, qreal lightnessStrength=DEFAULT_LIGHTNESS_STRENGTH) const
void generateOutlineCache()
virtual QSizeF characteristicSize(KisDabShape const &) const
virtual void toXML(QDomDocument &, QDomElement &) const
virtual KisOptimizedBrushOutline outline(bool forcePreciseOutline=false) const
qreal autoSpacingCoeff() const
void setWidth(qint32 width)
void setHeight(qint32 height)
virtual qint32 maskWidth(KisDabShape const &, qreal subPixelX, qreal subPixelY, const KisPaintInformation &info) const
void setRect(const QRect &rc)
bool initialize(quint8 defaultValue=0)
virtual QImage convertToQImage(const KoColorProfile *dstProfile, qint32 x, qint32 y, qint32 w, qint32 h, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags()) const
void lazyGrowBufferWithoutInitialization()
const KoColorSpace * colorSpace() const
virtual quint32 pixelSize() const =0
static bool qFuzzyCompare(half p1, half p2)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
static KisDabShape lieAboutDabShape(KisDabShape const &shape, int spikes)
void fillPixelOptimized_4bytes(quint8 *color, quint8 *buf, int size)
void fillPixelOptimized_general(quint8 *color, quint8 *buf, int size, int pixelSize)
const KoID SoftId("soft", ki18n("Soft"))
generate brush mask from former softbrush paintop, where softness is based on curve
QSharedPointer< KoResource > KoResourceSP
auto maxDimension(Size size) -> decltype(size.width())
int idealThreadCountCached
Private(const Private &rhs)
QScopedPointer< KisMaskGenerator > shape
static KoColorSpaceRegistry * instance()
const KoColorSpace * rgb8(const QString &profileName=QString())
void setImage(const QImage &image)