Krita Source Code Documentation
Loading...
Searching...
No Matches
KisRectsGrid Class Reference

A utility class to maintain a sparse grid of loaded/unloaded rects. More...

#include <KisRectsGrid.h>

Public Member Functions

QVector< QRect > addAlignedRect (const QRect &rc)
 
QVector< QRect > addRect (const QRect &rc)
 
QRect alignRect (const QRect &rc) const
 
QRect boundingRect () const
 
bool contains (const QRect &rc) const
 
 KisRectsGrid (int gridSize=64)
 
QVector< QRect > removeAlignedRect (const QRect &rc)
 
QVector< QRect > removeRect (const QRect &rc)
 

Private Member Functions

void resize (const QRect &newMappedAreaSize)
 

Static Private Member Functions

static QRect shrinkRectToAlignedGrid (const QRect &srcRect, int lod)
 

Private Attributes

int m_gridSize
 
int m_logGridSize
 
QRect m_mappedAreaSize
 
QVector< quint8 > m_mapping
 

Detailed Description

A utility class to maintain a sparse grid of loaded/unloaded rects.

KisRectsGrid manages the presence of the rectangular cells in the grid covering some specific area. The main usecase of the class is to maintain an overlay device over another paint device.

When you need to ensure that the overlay has some particular rect loaded, you just call grid->addRect(rect) and get a list of rects that have not yet been loaded into the overlay. The returned list may be empty if all the grid cells intersecting rect has already been loaded (added to the grid).

The size of the cell is defined at the construction stage and must be power of 2.

Definition at line 30 of file KisRectsGrid.h.

Constructor & Destructor Documentation

◆ KisRectsGrid()

KisRectsGrid::KisRectsGrid ( int gridSize = 64)

Create a grid with cell size set to gridSize

Definition at line 18 of file KisRectsGrid.cpp.

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}
static void log(const QString &message)
Logs with date/time.
static bool qFuzzyCompare(half p1, half p2)

References KisUsageLogger::log(), m_gridSize, m_logGridSize, and qFuzzyCompare().

Member Function Documentation

◆ addAlignedRect()

QVector< QRect > KisRectsGrid::addAlignedRect ( const QRect & rc)

Add an aligned rect to the grid

The grid will form a list of cells that intersect rc and have not not yet been loaded, mark them as loaded and return the list to the caller.

Parameters
rcthe rect to be added, the rect must be aligned
Returns
the list of cells that has actually been changed

Definition at line 62 of file KisRectsGrid.cpp.

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}
static QRect scaledRect(const QRect &srcRect, int lod)
static QRect upscaledRect(const QRect &srcRect, int lod)
QRect m_mappedAreaSize
QVector< quint8 > m_mapping
void resize(const QRect &newMappedAreaSize)
Rect blowRect(const Rect &rect, qreal coeff)

References KisAlgebra2D::blowRect(), m_logGridSize, m_mappedAreaSize, m_mapping, resize(), KisLodTransformBase::scaledRect(), and KisLodTransformBase::upscaledRect().

◆ addRect()

QVector< QRect > KisRectsGrid::addRect ( const QRect & rc)

Add an arbitrary (non-aligned) rect to the grid

The grid will form a list of cells that intersect rc and have not not yet been loaded, mark them as loaded and return the list to the caller.

Parameters
rcthe rect to be added, not necessary aligned to the grid
Returns
the list of cells that has actually been changed

Definition at line 57 of file KisRectsGrid.cpp.

58{
59 return addAlignedRect(alignRect(rc));
60}
QRect alignRect(const QRect &rc) const
QVector< QRect > addAlignedRect(const QRect &rc)

References addAlignedRect(), and alignRect().

◆ alignRect()

QRect KisRectsGrid::alignRect ( const QRect & rc) const

Grow rectangle rc until it becomes aligned to the grid cell borders.

Definition at line 52 of file KisRectsGrid.cpp.

53{
55}
static QRect alignedRect(const QRect &srcRect, int lod)

References KisLodTransformBase::alignedRect(), and m_logGridSize.

◆ boundingRect()

QRect KisRectsGrid::boundingRect ( ) const

Return the bounding box of the loaded cells of the grid

Definition at line 160 of file KisRectsGrid.cpp.

160 {
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}

References m_logGridSize, m_mappedAreaSize, and KisLodTransformBase::upscaledRect().

◆ contains()

bool KisRectsGrid::contains ( const QRect & rc) const

Return is rc is fully covered by the loaded cells of the grid

Definition at line 144 of file KisRectsGrid.cpp.

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}

References alignRect(), m_logGridSize, m_mappedAreaSize, m_mapping, and KisLodTransformBase::scaledRect().

◆ removeAlignedRect()

QVector< QRect > KisRectsGrid::removeAlignedRect ( const QRect & rc)

Remove an aligned rect from the grid

The grid will form a list of loaded cells that are fully contained in rc, mark them as unloaded and return the list to the caller.

Parameters
rcthe rect to be removed, not necessary aligned to the grid
Returns
the list of cells that has actually been changed

Definition at line 123 of file KisRectsGrid.cpp.

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}

References m_logGridSize, m_mappedAreaSize, m_mapping, KisLodTransformBase::scaledRect(), and KisLodTransformBase::upscaledRect().

◆ removeRect()

QVector< QRect > KisRectsGrid::removeRect ( const QRect & rc)

Remove an arbitrary (non-aligned) rect from the grid

The grid will form a list of loaded cells that are fully contained in rc, mark them as unloaded and return the list to the caller.

TODO: please note that removing two neighbouring non-aligned rectangles may still leave some cells marked as loaded. Perhaps we should change the meaning of this function to remove "all intersecting rectangles" instead of "all contained rectangles".

Parameters
rcthe rect to be removed, not necessary aligned to the grid
Returns
the list of cells that has actually been changed

Definition at line 117 of file KisRectsGrid.cpp.

118{
119 const QRect alignedRect = shrinkRectToAlignedGrid(rc, m_logGridSize);
120 return !alignedRect.isEmpty() ? removeAlignedRect(alignedRect) : QVector<QRect>();
121}
QVector< QRect > removeAlignedRect(const QRect &rc)
static QRect shrinkRectToAlignedGrid(const QRect &srcRect, int lod)

References m_logGridSize, removeAlignedRect(), and shrinkRectToAlignedGrid().

◆ resize()

void KisRectsGrid::resize ( const QRect & newMappedAreaSize)
private

Definition at line 29 of file KisRectsGrid.cpp.

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}
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130

References KIS_SAFE_ASSERT_RECOVER_NOOP, m_mappedAreaSize, and m_mapping.

◆ shrinkRectToAlignedGrid()

QRect KisRectsGrid::shrinkRectToAlignedGrid ( const QRect & srcRect,
int lod )
inlinestaticprivate

Definition at line 88 of file KisRectsGrid.cpp.

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}
static void alignByPow2ButOneHi(qint32 &value, qint32 alignment)
static void alignByPow2Lo(qint32 &value, qint32 alignment)

References KisLodTransformBase::alignByPow2ButOneHi(), and KisLodTransformBase::alignByPow2Lo().

Member Data Documentation

◆ m_gridSize

int KisRectsGrid::m_gridSize
private

Definition at line 109 of file KisRectsGrid.h.

◆ m_logGridSize

int KisRectsGrid::m_logGridSize
private

Definition at line 110 of file KisRectsGrid.h.

◆ m_mappedAreaSize

QRect KisRectsGrid::m_mappedAreaSize
private

Definition at line 112 of file KisRectsGrid.h.

◆ m_mapping

QVector<quint8> KisRectsGrid::m_mapping
private

Definition at line 111 of file KisRectsGrid.h.


The documentation for this class was generated from the following files: