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