KisRectsGrid.h 3.66 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
/*
 *  SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 */

#ifndef KISRECTSGRID_H
#define KISRECTSGRID_H

#include <QRect>
#include <QVector>
#include "kritaglobal_export.h"

Dmitry Kazakov's avatar
Dmitry Kazakov committed
14
15
16
17
18
19

/**
 * @brief 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
20
 * an overlay device over another paint device.
Dmitry Kazakov's avatar
Dmitry Kazakov committed
21
22
 *
 * When you need to ensure that the overlay has some particular `rect` loaded,
23
24
 * 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
Dmitry Kazakov's avatar
Dmitry Kazakov committed
25
26
27
28
29
 * 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.
 */
30
31
32
class KRITAGLOBAL_EXPORT KisRectsGrid
{
public:
Dmitry Kazakov's avatar
Dmitry Kazakov committed
33
34
35
    /**
     * Create a grid with cell size set to \p gridSize
     */
36
37
    KisRectsGrid(int gridSize = 64);

Dmitry Kazakov's avatar
Dmitry Kazakov committed
38
39
40
41
42

    /**
     * Grow rectangle \p rc until it becomes aligned to
     * the grid cell borders.
     */
43
44
    QRect alignRect(const QRect &rc) const;

Dmitry Kazakov's avatar
Dmitry Kazakov committed
45
46
47
    /**
     * Add an arbitrary (non-aligned) rect to the grid
     *
48
49
     * The grid will form a list of cells that intersect \p rc and have not
     * not yet been loaded, mark them as loaded and return the list to the caller.
Dmitry Kazakov's avatar
Dmitry Kazakov committed
50
51
52
53
     *
     * \param rc the rect to be added, not necessary aligned to the grid
     * \return the list of cells that has actually been changed
     */
54
    QVector<QRect> addRect(const QRect &rc);
Dmitry Kazakov's avatar
Dmitry Kazakov committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

    /**
     * Remove an arbitrary (non-aligned) rect from the grid
     *
     * The grid will form a list of loaded cells that are fully contained in \p
     * 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".
     *
     * \param rc the rect to be removed, not necessary aligned to the grid
     * \return the list of cells that has actually been changed
     */
70
71
    QVector<QRect> removeRect(const QRect &rc);

Dmitry Kazakov's avatar
Dmitry Kazakov committed
72
73
74
    /**
     * Add an aligned rect to the grid
     *
75
76
     * The grid will form a list of cells that intersect \p rc and have not
     * not yet been loaded, mark them as loaded and return the list to the caller.
Dmitry Kazakov's avatar
Dmitry Kazakov committed
77
78
79
80
     *
     * \param rc the rect to be added, the rect must be aligned
     * \return the list of cells that has actually been changed
     */
81
    QVector<QRect> addAlignedRect(const QRect &rc);
Dmitry Kazakov's avatar
Dmitry Kazakov committed
82
83
84
85
86
87
88
89
90
91

    /**
     * Remove an aligned rect from the grid
     *
     * The grid will form a list of loaded cells that are fully contained in \p
     * rc, mark them as unloaded and return the list to the caller.
     *
     * \param rc the rect to be removed, not necessary aligned to the grid
     * \return the list of cells that has actually been changed
     */
92
93
    QVector<QRect> removeAlignedRect(const QRect &rc);

Dmitry Kazakov's avatar
Dmitry Kazakov committed
94
95
96
    /**
     * Return is \p rc is fully covered by the loaded cells of the grid
     */
97
98
    bool contains(const QRect &rc) const;

Dmitry Kazakov's avatar
Dmitry Kazakov committed
99
100
101
    /**
     * Return the bounding box of the loaded cells of the grid
     */
102
103
    QRect boundingRect() const;

104
105
106
107
108
109
110
111
112
113
114
115
116
private:
    void resize(const QRect &newMappedAreaSize);
    static QRect shrinkRectToAlignedGrid(const QRect &srcRect, int lod);

private:
    int m_gridSize;
    int m_logGridSize;
    QVector<quint8> m_mapping;
    QRect m_mappedAreaSize; // measured in col/row

};

#endif // KISRECTSGRID_H