Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_paintop_utils.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2017 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "kis_paintop_utils.h"
8
9#include "krita_utils.h"
11#include <KisRenderedDab.h>
12
13#include <functional>
14
15namespace KisPaintOpUtils {
16
17
18KisSpacingInformation effectiveSpacing(qreal dabWidth, qreal dabHeight, qreal extraScale, bool distanceSpacingEnabled, bool isotropicSpacing, qreal rotation, bool axesFlipped, qreal spacingVal, bool autoSpacingActive, qreal autoSpacingCoeff, qreal lodScale)
19{
20 QPointF spacing;
21
22 if (!isotropicSpacing) {
23 if (autoSpacingActive) {
24 spacing = calcAutoSpacing(QPointF(dabWidth, dabHeight), autoSpacingCoeff, lodScale);
25 } else {
26 spacing = QPointF(dabWidth, dabHeight);
27 spacing *= spacingVal;
28 }
29 }
30 else {
31 qreal significantDimension = qMax(dabWidth, dabHeight);
32 if (autoSpacingActive) {
33 significantDimension = calcAutoSpacing(significantDimension, autoSpacingCoeff);
34 } else {
35 significantDimension *= spacingVal;
36 }
37 spacing = QPointF(significantDimension, significantDimension);
38 rotation = 0.0;
39 axesFlipped = false;
40 }
41
42 spacing *= extraScale;
43
44 return KisSpacingInformation(distanceSpacingEnabled, spacing, rotation, axesFlipped);
45}
46
47KisTimingInformation effectiveTiming(bool timingEnabled, qreal timingInterval, qreal rateExtraScale)
48{
49
50 if (!timingEnabled) {
51 return KisTimingInformation();
52 }
53 else {
54 qreal scaledInterval = rateExtraScale <= 0.0 ? LONG_TIME : timingInterval / rateExtraScale;
55 return KisTimingInformation(scaledInterval);
56 }
57}
58
59QVector<QRect> splitAndFilterDabRect(const QRect &totalRect, const QVector<QRect> &dabRects, int idealPatchSize)
60{
61 QVector<QRect> rects = KritaUtils::splitRectIntoPatches(totalRect, QSize(idealPatchSize,idealPatchSize));
62
64 [dabRects] (const QRect &rc) {
65 Q_FOREACH (const QRect &dab, dabRects) {
66 if (dab.intersects(rc)) {
67 return true;
68 }
69 }
70 return false;
71 });
72 return rects;
73}
74
75QVector<QRect> splitDabsIntoRects(const QVector<QRect> &dabRects, int idealNumRects, int diameter, qreal spacing)
76{
77 const QRect totalRect =
78 std::accumulate(dabRects.begin(), dabRects.end(), QRect(), std::bit_or<QRect>());
79
80 constexpr int minPatchSize = 128;
81 constexpr int maxPatchSize = 512;
82 constexpr int patchStep = 64;
83 constexpr int halfPatchStep = patchStep >> 1;
84
85
86 int idealPatchSize = qBound(minPatchSize,
87 (int(diameter * (2.0 - spacing)) + halfPatchStep) & ~(patchStep - 1),
88 maxPatchSize);
89
90
91 QVector<QRect> rects = splitAndFilterDabRect(totalRect, dabRects, idealPatchSize);
92
93 while (rects.size() < idealNumRects && idealPatchSize >minPatchSize) {
94 idealPatchSize = qMax(minPatchSize, idealPatchSize - patchStep);
95 rects = splitAndFilterDabRect(totalRect, dabRects, idealPatchSize);
96 }
97
98 return rects;
99}
100
101
102
103}
const qreal LONG_TIME
qreal calcAutoSpacing(qreal value, qreal coeff)
KisSpacingInformation effectiveSpacing(qreal dabWidth, qreal dabHeight, qreal extraScale, bool distanceSpacingEnabled, bool isotropicSpacing, qreal rotation, bool axesFlipped, qreal spacingVal, bool autoSpacingActive, qreal autoSpacingCoeff, qreal lodScale)
KisTimingInformation effectiveTiming(bool timingEnabled, qreal timingInterval, qreal rateExtraScale)
QVector< QRect > splitAndFilterDabRect(const QRect &totalRect, const QVector< QRect > &dabRects, int idealPatchSize)
QVector< QRect > splitDabsIntoRects(const QVector< QRect > &dabRects, int idealNumRects, int diameter, qreal spacing)
QVector< QRect > splitRectIntoPatches(const QRect &rc, const QSize &patchSize)
auto filterContainer(C &container, KeepIfFunction keepIf) -> decltype(bool(keepIf(container[0])), void())