File indexing completed on 2024-05-12 15:57:03
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #ifndef KISREGION_H 0007 #define KISREGION_H 0008 0009 #include "kritaglobal_export.h" 0010 #include <QVector> 0011 #include <QRect> 0012 #include <boost/operators.hpp> 0013 0014 class QRegion; 0015 0016 /** 0017 * An more efficient (and more limited) replacement for QRegion. 0018 * 0019 * Its main purpose it to be able to merge a huge set of rectangles 0020 * into a smaller set of bigger rectangles, the same thing that QRegion 0021 * is supposed to do. The main difference (and limitation) is: all the 0022 * input rects must be non-intersecting. This requirement is perfectly 0023 * fine for Krita's tiles, which do never intersect. 0024 */ 0025 class KRITAGLOBAL_EXPORT KisRegion : 0026 public boost::equality_comparable<KisRegion>, 0027 public boost::andable<KisRegion, QRect> 0028 { 0029 public: 0030 /** 0031 * @brief merge a set of rectangles into a smaller set of bigger rectangles 0032 * 0033 * The algorithm does two passes over the rectangles. First it tries to 0034 * merge all the rectangles horizontally, then vertically. The merge happens 0035 * in-place, that is, all the merged elements will be moved to the front 0036 * of the original range. 0037 * 0038 * The final range is defined by [beginIt, retvalIt) 0039 * 0040 * @param beginIt iterator to the beginning of the source range 0041 * @param endIt iterator to the end of the source range 0042 * @return iteration pointing past the last element of the merged range 0043 */ 0044 static QVector<QRect>::iterator mergeSparseRects(QVector<QRect>::iterator beginIt, QVector<QRect>::iterator endIt); 0045 0046 0047 /** 0048 * Simplifies \p rects in a way that they don't overlap anymore. The actual 0049 * resulting area may be larger than original \p rects, but not more than 0050 * \p gridSize in any dimension. 0051 */ 0052 static void approximateOverlappingRects(QVector<QRect> &rects, int gridSize); 0053 0054 static void makeGridLikeRectsUnique(QVector<QRect> &rects); 0055 0056 public: 0057 KisRegion() = default; 0058 KisRegion(const KisRegion &rhs) = default; 0059 KisRegion(const QRect &rect); 0060 KisRegion(std::initializer_list<QRect> rects); 0061 0062 /** 0063 * @brief creates a region from a set of non-intersecting rectangles 0064 * @param rects rectangles that should be merged. Rectangles must not intersect. 0065 */ 0066 KisRegion(const QVector<QRect> &rects); 0067 KisRegion(QVector<QRect> &&rects); 0068 0069 KisRegion& operator=(const KisRegion &rhs); 0070 friend KRITAGLOBAL_EXPORT bool operator==(const KisRegion &lhs, const KisRegion &rhs); 0071 0072 KisRegion& operator&=(const QRect &rect); 0073 0074 QRect boundingRect() const; 0075 QVector<QRect> rects() const; 0076 int rectCount() const; 0077 bool isEmpty() const; 0078 0079 QRegion toQRegion() const; 0080 0081 void translate(int dx, int dy); 0082 KisRegion translated(int x, int y) const; 0083 0084 static KisRegion fromQRegion(const QRegion ®ion); 0085 0086 /** 0087 * Approximates a KisRegion from \p rects, which may overlap. The resulting 0088 * KisRegion may be larger than the original set of rects, but it is guaranteed 0089 * to cover it completely. 0090 */ 0091 static KisRegion fromOverlappingRects(const QVector<QRect> &rects, int gridSize); 0092 0093 private: 0094 void mergeAllRects(); 0095 0096 private: 0097 QVector<QRect> m_rects; 0098 }; 0099 0100 KRITAGLOBAL_EXPORT bool operator==(const KisRegion &lhs, const KisRegion &rhs); 0101 0102 0103 #endif // KISREGION_H