File indexing completed on 2024-05-12 15:58:40

0001 /*
0002  *  SPDX-FileCopyrightText: 2008 Cyrille Berger <cberger@cberger.net>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef _KIS_REPEAT_ITERATORS_PIXEL_H_
0008 #define _KIS_REPEAT_ITERATORS_PIXEL_H_
0009 
0010 #include <QRect>
0011 #include "kis_shared.h"
0012 #include "tiles3/kis_hline_iterator.h"
0013 #include "tiles3/kis_vline_iterator.h"
0014 
0015 template<class T>
0016 class KisRepeatHLineIteratorPixelBase;
0017 template<class T>
0018 class KisRepeatVLineIteratorPixelBase;
0019 
0020 /**
0021  * This iterator is an iterator that will "artificially" extend the paint device with the
0022  * value of the border when trying to access values outside the range of data.
0023  */
0024 template<class T>
0025 class KisRepeatLineIteratorPixelBase : public KisShared
0026 {
0027     Q_DISABLE_COPY(KisRepeatLineIteratorPixelBase)
0028 public:
0029 
0030     friend class KisRepeatHLineIteratorPixelBase<T>;
0031     friend class KisRepeatVLineIteratorPixelBase<T>;
0032     /**
0033      * @param dm data manager
0034      * @param x x of top left corner
0035      * @param y y of top left corner
0036      * @param offsetx x offset
0037      * @param offsety y offset
0038      * @param _rc indicates the rectangle that truly contains data
0039      * @param completeListener completion listener
0040      */
0041     inline KisRepeatLineIteratorPixelBase(KisDataManager *dm, qint32 x, qint32 y, qint32 offsetx, qint32 offsety, const QRect& _rc, KisIteratorCompleteListener *completeListener);
0042     virtual inline ~KisRepeatLineIteratorPixelBase();
0043 public:
0044     inline qint32 x() const {
0045         return m_realX;
0046     }
0047     inline qint32 y() const {
0048         return m_realY;
0049     }
0050     inline const quint8 * oldRawData() const {
0051         return m_iterator->oldRawData();
0052     }
0053 
0054 private:
0055     KisDataManager* m_dm;
0056     qint32 m_realX, m_realY;
0057     qint32 m_offsetX, m_offsetY;
0058     QRect m_dataRect;
0059     T* m_iterator;
0060     KisIteratorCompleteListener *m_completeListener;
0061 };
0062 
0063 /**
0064  * This iterator is an iterator that will "artificially" extend the paint device with the
0065  * value of the border when trying to access values outside the range of data.
0066  */
0067 template<class T>
0068 class KisRepeatHLineIteratorPixelBase : public KisRepeatLineIteratorPixelBase<T>
0069 {
0070 public:
0071     /**
0072      * @param dm data manager
0073      * @param x x of top left corner
0074      * @param y y of top left corner
0075      * @param w width
0076      * @param offsetx x offset
0077      * @param offsety y offset
0078      * @param _rc indicates the rectangle that truly contains data
0079      * @param completeListener completion listener
0080      */
0081     inline KisRepeatHLineIteratorPixelBase(KisDataManager *dm, qint32 x, qint32 y, qint32 w, qint32 offsetx, qint32 offsety, const QRect& _rc, KisIteratorCompleteListener *completeListener);
0082     inline ~KisRepeatHLineIteratorPixelBase() override;
0083     inline bool nextPixel();
0084     /**
0085      * Reach next row.
0086      */
0087     inline void nextRow();
0088 private:
0089     void createIterator();
0090 private:
0091     qint32 m_startX;
0092     qint32 m_startIteratorX;
0093     qint32 m_width;
0094 };
0095 
0096 /**
0097  * This iterator is an iterator that will "artificially" extend the paint device with the
0098  * value of the border when trying to access values outside the range of data.
0099  */
0100 template<class T>
0101 class KisRepeatVLineIteratorPixelBase : public KisRepeatLineIteratorPixelBase<T>
0102 {
0103 public:
0104     /**
0105      * @param dm data manager
0106      * @param x x of top left corner
0107      * @param y y of top left corner
0108      * @param h height
0109      * @param offsetx x offset
0110      * @param offsety y offset
0111      * @param _rc indicates the rectangle that truly contains data
0112      * @param completeListener completion listener
0113      */
0114     inline KisRepeatVLineIteratorPixelBase(KisDataManager *dm, qint32 x, qint32 y, qint32 h, qint32 offsetx, qint32 offsety, const QRect& _rc, KisIteratorCompleteListener *completeListener);
0115     inline ~KisRepeatVLineIteratorPixelBase() override;
0116     inline KisRepeatVLineIteratorPixelBase<T> & operator ++();
0117     inline bool nextPixel();
0118     /**
0119      * Reach next row.
0120      */
0121     inline void nextColumn();
0122 private:
0123     void createIterator();
0124 private:
0125     qint32 m_startY;
0126     qint32 m_startIteratorY;
0127     qint32 m_height;
0128 };
0129 
0130 //------------------------ Implementations ------------------------//
0131 
0132 //---------------- KisRepeatLineIteratorPixelBase -----------------//
0133 
0134 template<class T>
0135 KisRepeatLineIteratorPixelBase<T>::KisRepeatLineIteratorPixelBase(KisDataManager *dm, qint32 x, qint32 y, qint32 offsetx, qint32 offsety, const QRect& _rc, KisIteratorCompleteListener *completeListener) :
0136     m_dm(dm),
0137     m_realX(x), m_realY(y),
0138     m_offsetX(offsetx), m_offsetY(offsety),
0139     m_dataRect(_rc),
0140     m_iterator(0),
0141     m_completeListener(completeListener)
0142 {
0143 }
0144 
0145 template<class T>
0146 KisRepeatLineIteratorPixelBase<T>::~KisRepeatLineIteratorPixelBase()
0147 {
0148     delete m_iterator;
0149 }
0150 
0151 //---------------- KisRepeatHLineIteratorPixelBase ----------------//
0152 
0153 template<class T>
0154 KisRepeatHLineIteratorPixelBase<T>::KisRepeatHLineIteratorPixelBase(KisDataManager *dm, qint32 x, qint32 y, qint32 w, qint32 offsetx, qint32 offsety, const QRect& _rc, KisIteratorCompleteListener *completeListener)
0155     : KisRepeatLineIteratorPixelBase<T>(dm, x, y, offsetx, offsety , _rc, completeListener),
0156       m_startX(x), m_startIteratorX(x),
0157       m_width(w)
0158 {
0159     // Compute the startx value of the iterator
0160     if (m_startIteratorX < _rc.left()) {
0161         m_startIteratorX = _rc.left();
0162     }
0163     createIterator();
0164 }
0165 
0166 template<class T>
0167 KisRepeatHLineIteratorPixelBase<T>::~KisRepeatHLineIteratorPixelBase()
0168 {
0169 }
0170 
0171 template<class T>
0172 inline bool KisRepeatHLineIteratorPixelBase<T>::nextPixel()
0173 {
0174     Q_ASSERT(this->m_iterator);
0175     if (this->m_realX >= this->m_dataRect.x() && this->m_realX < this->m_dataRect.x() + this->m_dataRect.width() - 1) {
0176         this->m_iterator->nextPixel();
0177     }
0178     ++this->m_realX;
0179 
0180     return (this->m_realX < m_startX + m_width);
0181 }
0182 
0183 template<class T>
0184 inline void KisRepeatHLineIteratorPixelBase<T>::nextRow()
0185 {
0186     if (this->m_realY >= this->m_dataRect.y() && this->m_realY < this->m_dataRect.y() + this->m_dataRect.height() - 1) {
0187         this->m_iterator->nextRow();
0188     } else {
0189         createIterator();
0190     }
0191     this->m_realX = this->m_startX;
0192     ++this->m_realY;
0193 }
0194 
0195 template<class T>
0196 void KisRepeatHLineIteratorPixelBase<T>::createIterator()
0197 {
0198     // Cleanup
0199     delete this->m_iterator;
0200     qint32 startY = this->m_realY;
0201     if (startY < this->m_dataRect.y()) {
0202         startY = this->m_dataRect.top();
0203     }
0204     if (startY > (this->m_dataRect.y() + this->m_dataRect.height() - 1)) {
0205         startY = (this->m_dataRect.y() + this->m_dataRect.height() - 1);
0206     }
0207 
0208     int width = this->m_dataRect.x() + this->m_dataRect.width() - this->m_startIteratorX;
0209     this->m_iterator = new T(this->m_dm, this->m_startIteratorX, startY, width, this->m_offsetX, this->m_offsetY, false, this->m_completeListener);
0210     this->m_realX = this->m_startX;
0211 }
0212 
0213 //---------------- KisRepeatVLineIteratorPixelBase ----------------//
0214 
0215 template<class T>
0216 KisRepeatVLineIteratorPixelBase<T>::KisRepeatVLineIteratorPixelBase(KisDataManager *dm, qint32 x, qint32 y, qint32 h, qint32 offsetx, qint32 offsety, const QRect& _rc, KisIteratorCompleteListener *completeListener)
0217     : KisRepeatLineIteratorPixelBase<T>(dm, x, y, offsetx, offsety , _rc, completeListener),
0218       m_startY(y), m_startIteratorY(y),
0219       m_height(h)
0220 {
0221     // Compute the startx value of the iterator
0222     if (m_startIteratorY < _rc.top()) {
0223         m_startIteratorY = _rc.top();
0224     }
0225     createIterator();
0226 }
0227 
0228 template<class T>
0229 KisRepeatVLineIteratorPixelBase<T>::~KisRepeatVLineIteratorPixelBase()
0230 {
0231 }
0232 
0233 template<class T>
0234 inline bool KisRepeatVLineIteratorPixelBase<T>::nextPixel()
0235 {
0236     Q_ASSERT(this->m_iterator);
0237     if (this->m_realY >= this->m_dataRect.y() && this->m_realY < this->m_dataRect.y() + this->m_dataRect.height() - 1) {
0238         this->m_iterator->nextPixel();
0239     }
0240     ++this->m_realY;
0241     return (this->m_realY < m_startY + m_height);
0242 
0243 }
0244 
0245 template<class T>
0246 inline void KisRepeatVLineIteratorPixelBase<T>::nextColumn()
0247 {
0248     if (this->m_realX >= this->m_dataRect.x() && this->m_realX < this->m_dataRect.x() + this->m_dataRect.width() - 1) {
0249         this->m_iterator->nextColumn();
0250     } else {
0251         createIterator();
0252     }
0253     this->m_realY = this->m_startY;
0254     ++this->m_realX;
0255 }
0256 
0257 template<class T>
0258 void KisRepeatVLineIteratorPixelBase<T>::createIterator()
0259 {
0260     // Cleanup
0261     delete this->m_iterator;
0262     qint32 startX = this->m_realX;
0263     if (startX < this->m_dataRect.x()) {
0264         startX = this->m_dataRect.x();
0265     }
0266     if (startX > (this->m_dataRect.x() + this->m_dataRect.width() - 1)) {
0267         startX = (this->m_dataRect.x() + this->m_dataRect.width() - 1);
0268     }
0269 
0270     int height = this->m_dataRect.y() + this->m_dataRect.height() - this->m_startIteratorY;
0271     this->m_iterator = new T(this->m_dm, startX, this->m_startIteratorY, height, this->m_offsetX, this->m_offsetY, false, this->m_completeListener);
0272     this->m_realY = this->m_startY;
0273 }
0274 
0275 
0276 #endif