File indexing completed on 2024-05-12 15:57:03
0001 /* 0002 * SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef KISRECTSGRID_H 0008 #define KISRECTSGRID_H 0009 0010 #include <QRect> 0011 #include <QVector> 0012 #include "kritaglobal_export.h" 0013 0014 0015 /** 0016 * @brief A utility class to maintain a sparse grid of loaded/unloaded rects 0017 * 0018 * KisRectsGrid manages the presence of the rectangular cells in the grid 0019 * covering some specific area. The main usecase of the class is to maintain 0020 * an overlay device over another paint device. 0021 * 0022 * When you need to ensure that the overlay has some particular `rect` loaded, 0023 * you just call `grid->addRect(rect)` and get a list of rects that have not 0024 * yet been loaded into the overlay. The returned list may be empty if all the 0025 * grid cells intersecting `rect` has already been loaded (added to the grid). 0026 * 0027 * The size of the cell is defined at the construction stage and must be 0028 * power of 2. 0029 */ 0030 class KRITAGLOBAL_EXPORT KisRectsGrid 0031 { 0032 public: 0033 /** 0034 * Create a grid with cell size set to \p gridSize 0035 */ 0036 KisRectsGrid(int gridSize = 64); 0037 0038 0039 /** 0040 * Grow rectangle \p rc until it becomes aligned to 0041 * the grid cell borders. 0042 */ 0043 QRect alignRect(const QRect &rc) const; 0044 0045 /** 0046 * Add an arbitrary (non-aligned) rect to the grid 0047 * 0048 * The grid will form a list of cells that intersect \p rc and have not 0049 * not yet been loaded, mark them as loaded and return the list to the caller. 0050 * 0051 * \param rc the rect to be added, not necessary aligned to the grid 0052 * \return the list of cells that has actually been changed 0053 */ 0054 QVector<QRect> addRect(const QRect &rc); 0055 0056 /** 0057 * Remove an arbitrary (non-aligned) rect from the grid 0058 * 0059 * The grid will form a list of loaded cells that are fully contained in \p 0060 * rc, mark them as unloaded and return the list to the caller. 0061 * 0062 * TODO: please note that removing two neighbouring non-aligned rectangles 0063 * may still leave some cells marked as loaded. Perhaps we should change 0064 * the meaning of this function to remove "all intersecting rectangles" 0065 * instead of "all contained rectangles". 0066 * 0067 * \param rc the rect to be removed, not necessary aligned to the grid 0068 * \return the list of cells that has actually been changed 0069 */ 0070 QVector<QRect> removeRect(const QRect &rc); 0071 0072 /** 0073 * Add an aligned rect to the grid 0074 * 0075 * The grid will form a list of cells that intersect \p rc and have not 0076 * not yet been loaded, mark them as loaded and return the list to the caller. 0077 * 0078 * \param rc the rect to be added, the rect must be aligned 0079 * \return the list of cells that has actually been changed 0080 */ 0081 QVector<QRect> addAlignedRect(const QRect &rc); 0082 0083 /** 0084 * Remove an aligned rect from the grid 0085 * 0086 * The grid will form a list of loaded cells that are fully contained in \p 0087 * rc, mark them as unloaded and return the list to the caller. 0088 * 0089 * \param rc the rect to be removed, not necessary aligned to the grid 0090 * \return the list of cells that has actually been changed 0091 */ 0092 QVector<QRect> removeAlignedRect(const QRect &rc); 0093 0094 /** 0095 * Return is \p rc is fully covered by the loaded cells of the grid 0096 */ 0097 bool contains(const QRect &rc) const; 0098 0099 /** 0100 * Return the bounding box of the loaded cells of the grid 0101 */ 0102 QRect boundingRect() const; 0103 0104 private: 0105 void resize(const QRect &newMappedAreaSize); 0106 static QRect shrinkRectToAlignedGrid(const QRect &srcRect, int lod); 0107 0108 private: 0109 int m_gridSize; 0110 int m_logGridSize; 0111 QVector<quint8> m_mapping; 0112 QRect m_mappedAreaSize; // measured in col/row 0113 0114 }; 0115 0116 #endif // KISRECTSGRID_H