Krita Source Code Documentation
Loading...
Searching...
No Matches
KisRectsGrid.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "KisRectsGrid.h"
8#include "kis_assert.h"
9#include <QtCore/qmath.h>
11#include "kis_global.h"
12#include "kis_algebra_2d.h"
13#include <KisUsageLogger.h>
14
15#include "kis_debug.h"
16
17
19 : m_gridSize(gridSize)
20 , m_logGridSize(qFloor(std::log2(gridSize)))
21{
22 if (!qFuzzyCompare(std::log2(gridSize), qreal(m_logGridSize))) {
23 KisUsageLogger::log(QString("Invalid grid configuration. Grid size: %1, log grid size: %2. Resetting to 64 and 6").arg(gridSize, m_logGridSize));
24 m_gridSize = 64;
25 m_logGridSize = 6;
26 }
27}
28
29void KisRectsGrid::resize(const QRect &newMappedAreaSize)
30{
31 KIS_SAFE_ASSERT_RECOVER_NOOP(m_mappedAreaSize.isEmpty() || newMappedAreaSize.contains(m_mappedAreaSize));
32
33 QVector<quint8> newMapping(newMappedAreaSize.width() * newMappedAreaSize.height());
34
35 const int xDiff = m_mappedAreaSize.x() - newMappedAreaSize.x();
36 const int yDiff = m_mappedAreaSize.y() - newMappedAreaSize.y();
37
38 int dstRowStride = newMappedAreaSize.width();
39 int dstRowStart = xDiff + yDiff * dstRowStride;
40
41 for (int y = 0; y < m_mappedAreaSize.height(); y++) {
42 int dstRowIndex = dstRowStart + dstRowStride * y;
43 int srcRowIndex = m_mappedAreaSize.width() * y;
44
45 memcpy(&newMapping[dstRowIndex], &m_mapping[srcRowIndex], m_mappedAreaSize.width());
46 }
47
48 std::swap(newMapping, m_mapping);
49 m_mappedAreaSize = newMappedAreaSize;
50}
51
52QRect KisRectsGrid::alignRect(const QRect &rc) const
53{
55}
56
58{
59 return addAlignedRect(alignRect(rc));
60}
61
63{
64 if (rc.isEmpty()) return QVector<QRect>();
65
66 const QRect mappedRect = KisLodTransformBase::scaledRect(rc, m_logGridSize);
67
68 if (!m_mappedAreaSize.contains(mappedRect)) {
69 QRect nextMappingSize = m_mappedAreaSize | mappedRect;
70 nextMappingSize = KisAlgebra2D::blowRect(nextMappingSize, 0.2);
71 resize(nextMappingSize);
72 }
73
74 QVector<QRect> addedRects;
75
76 for (int y = mappedRect.y(); y <= mappedRect.bottom(); y++) {
77 for (int x = mappedRect.x(); x <= mappedRect.right(); x++) {
78 quint8 *ptr = &m_mapping[m_mappedAreaSize.width() * (y - m_mappedAreaSize.y()) + (x - m_mappedAreaSize.x())];
79 if (!*ptr) {
80 *ptr = 1;
81 addedRects.append(KisLodTransformBase::upscaledRect(QRect(x, y, 1, 1), m_logGridSize));
82 }
83 }
84 }
85 return addedRects;
86}
87
88inline QRect KisRectsGrid::shrinkRectToAlignedGrid(const QRect &srcRect, int lod)
89{
90 qint32 alignment = 1 << lod;
91
92 qint32 x1, y1, x2, y2;
93 srcRect.getCoords(&x1, &y1, &x2, &y2);
94
95 x1--;
96 y1--;
97 x2++;
98 y2++;
99
102
105
106 x1++;
107 y1++;
108 x2--;
109 y2--;
110
111 QRect rect;
112 rect.setCoords(x1, y1, x2, y2);
113
114 return rect;
115}
116
118{
119 const QRect alignedRect = shrinkRectToAlignedGrid(rc, m_logGridSize);
120 return !alignedRect.isEmpty() ? removeAlignedRect(alignedRect) : QVector<QRect>();
121}
122
124{
125 const QRect mappedRect = KisLodTransformBase::scaledRect(rc, m_logGridSize);
126
127 // NOTE: we never shrink the size of the grid, just keep it as big as
128 // it ever was
129
130 QVector<QRect> removedRects;
131
132 for (int y = mappedRect.y(); y <= mappedRect.bottom(); y++) {
133 for (int x = mappedRect.x(); x <= mappedRect.right(); x++) {
134 quint8 *ptr = &m_mapping[m_mappedAreaSize.width() * (y - m_mappedAreaSize.y()) + (x - m_mappedAreaSize.x())];
135 if (*ptr) {
136 *ptr = 0;
137 removedRects.append(KisLodTransformBase::upscaledRect(QRect(x, y, 1, 1), m_logGridSize));
138 }
139 }
140 }
141 return removedRects;
142}
143
144bool KisRectsGrid::contains(const QRect &rc) const
145{
146 const QRect mappedRect = KisLodTransformBase::scaledRect(alignRect(rc), m_logGridSize);
147
148 if (!m_mappedAreaSize.contains(mappedRect)) return false;
149
150 for (int y = mappedRect.y(); y <= mappedRect.bottom(); y++) {
151 for (int x = mappedRect.x(); x <= mappedRect.right(); x++) {
152 const quint8 *ptr = &m_mapping[m_mappedAreaSize.width() * (y - m_mappedAreaSize.y()) + (x - m_mappedAreaSize.x())];
153 if (!*ptr) return false;
154 }
155 }
156
157 return true;
158}
159
161 QRect gridBounds;
162
163 for (int y = m_mappedAreaSize.y(); y <= m_mappedAreaSize.bottom(); y++) {
164 for (int x = m_mappedAreaSize.x(); x <= m_mappedAreaSize.right(); x++) {
165 gridBounds |= QRect(x, y, 1, 1);
166 }
167 }
168
170}
static QRect alignedRect(const QRect &srcRect, int lod)
static QRect scaledRect(const QRect &srcRect, int lod)
static void alignByPow2ButOneHi(qint32 &value, qint32 alignment)
static void alignByPow2Lo(qint32 &value, qint32 alignment)
static QRect upscaledRect(const QRect &srcRect, int lod)
QVector< QRect > removeAlignedRect(const QRect &rc)
bool contains(const QRect &rc) const
QRect m_mappedAreaSize
QRect alignRect(const QRect &rc) const
KisRectsGrid(int gridSize=64)
QVector< QRect > addRect(const QRect &rc)
QVector< QRect > addAlignedRect(const QRect &rc)
QVector< quint8 > m_mapping
QRect boundingRect() const
void resize(const QRect &newMappedAreaSize)
QVector< QRect > removeRect(const QRect &rc)
static QRect shrinkRectToAlignedGrid(const QRect &srcRect, int lod)
static void log(const QString &message)
Logs with date/time.
static bool qFuzzyCompare(half p1, half p2)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
Rect blowRect(const Rect &rect, qreal coeff)