File indexing completed on 2024-05-12 15:58:15
0001 /* 0002 * SPDX-FileCopyrightText: 2004 Adrian Page <adrian@pagenet.plus.com> 0003 * SPDX-FileCopyrightText: 2004 Bart Coppens <kde@bartcoppens.be> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 #ifndef KIS_FILL_PAINTER_H_ 0008 #define KIS_FILL_PAINTER_H_ 0009 0010 #include <QRect> 0011 0012 #include <KoColor.h> 0013 #include <KoColorSpaceRegistry.h> 0014 #include <KoPattern.h> 0015 0016 #include "kis_painter.h" 0017 #include "kis_types.h" 0018 #include "kis_selection.h" 0019 0020 #include <kritaimage_export.h> 0021 0022 0023 class KisFilterConfiguration; 0024 0025 // XXX: Filling should set dirty rect. 0026 /** 0027 * This painter can be used to fill paint devices in different ways. This can also be used 0028 * for flood filling related operations. 0029 */ 0030 class KRITAIMAGE_EXPORT KisFillPainter : public KisPainter 0031 { 0032 0033 public: 0034 0035 /** 0036 * Construct an empty painter. Use the begin(KisPaintDeviceSP) method to attach 0037 * to a paint device 0038 */ 0039 KisFillPainter(); 0040 /** 0041 * Start painting on the specified paint device 0042 */ 0043 KisFillPainter(KisPaintDeviceSP device); 0044 0045 KisFillPainter(KisPaintDeviceSP device, KisSelectionSP selection); 0046 0047 private: 0048 0049 void initFillPainter(); 0050 0051 public: 0052 /** 0053 * Fill current selection of KisPainter with a specified \p color. 0054 * 0055 * The filling rect is limited by \p rc to allow multithreaded 0056 * filling/processing. 0057 */ 0058 void fillSelection(const QRect &rc, const KoColor &color); 0059 0060 /** 0061 * Fill a rectangle with a certain color and opacity. 0062 */ 0063 void fillRect(qint32 x, 0064 qint32 y, 0065 qint32 w, 0066 qint32 h, 0067 const KoColor &c, 0068 quint8 opacity); 0069 0070 /** 0071 * Overloaded version of the above function. 0072 */ 0073 inline void fillRect(const QRect &rc, const KoColor &c, quint8 opacity) 0074 { 0075 fillRect(rc.x(), rc.y(), rc.width(), rc.height(), c, opacity); 0076 } 0077 0078 /** 0079 * Fill a rectangle with a certain color. 0080 */ 0081 inline void 0082 fillRect(qint32 x, qint32 y, qint32 w, qint32 h, const KoColor &c) 0083 { 0084 fillRect(x, y, w, h, c, OPACITY_OPAQUE_U8); 0085 } 0086 0087 /** 0088 * Overloaded version of the above function. 0089 */ 0090 inline void fillRect(const QRect &rc, const KoColor &c) 0091 { 0092 fillRect(rc.x(), rc.y(), rc.width(), rc.height(), c, OPACITY_OPAQUE_U8); 0093 } 0094 0095 /** 0096 * Fill a rectangle with a certain pattern. The pattern is repeated if it does not fit the 0097 * entire rectangle. 0098 */ 0099 void fillRect(qint32 x1, qint32 y1, qint32 w, qint32 h, const KoPatternSP pattern, const QPoint &offset = QPoint()); 0100 0101 /** 0102 * Fill a rectangle with a certain pattern. The pattern is repeated if it does not fit the 0103 * entire rectangle. 0104 * 0105 * This one uses blitting and thus makes use of proper composition. 0106 */ 0107 void fillRect(qint32 x1, qint32 y1, qint32 w, qint32 h, const KisPaintDeviceSP device, const QRect& deviceRect); 0108 0109 /** 0110 * Overloaded version of the above function. 0111 */ 0112 void fillRect(const QRect &rc, const KisPaintDeviceSP device, const QRect &deviceRect); 0113 0114 /** 0115 * Overloaded version of the above function. 0116 */ 0117 void fillRect(const QRect& rc, const KoPatternSP pattern, const QPoint &offset = QPoint()); 0118 0119 /** 0120 * Fill a rectangle with black transparent pixels (0, 0, 0, 0 for RGBA). 0121 */ 0122 inline void eraseRect(qint32 x1, qint32 y1, qint32 w, qint32 h) 0123 { 0124 const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8(); 0125 KoColor c(Qt::black, cs); 0126 fillRect(x1, y1, w, h, c, OPACITY_TRANSPARENT_U8); 0127 } 0128 0129 /** 0130 * Overloaded version of the above function. 0131 */ 0132 inline void eraseRect(const QRect &rc) 0133 { 0134 const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8(); 0135 KoColor c(Qt::black, cs); 0136 fillRect(rc.x(), 0137 rc.y(), 0138 rc.width(), 0139 rc.height(), 0140 c, 0141 OPACITY_TRANSPARENT_U8); 0142 } 0143 0144 /** 0145 * @brief fillRect 0146 * Fill a rectangle with a certain pattern. The pattern is repeated if it does not fit the 0147 * entire rectangle. Differs from other functions that it uses a transform, does not support 0148 * composite ops in turn. 0149 * @param rc rectangle to fill. 0150 * @param pattern pattern to use. 0151 * @param transform transformation to apply to the pattern. 0152 */ 0153 void fillRectNoCompose(const QRect& rc, const KoPatternSP pattern, const QTransform transform); 0154 0155 /** 0156 * Fill a rectangle with a certain pattern. The pattern is repeated if it does not fit the 0157 * entire rectangle. 0158 * 0159 * This one supports transforms, but does not use blitting. 0160 */ 0161 void fillRectNoCompose(qint32 x1, qint32 y1, qint32 w, qint32 h, const KisPaintDeviceSP device, const QRect& deviceRect, const QTransform transform); 0162 0163 /** 0164 * Fill the specified area with the output of the generator plugin that is configured 0165 * in the generator parameter 0166 */ 0167 void fillRect(qint32 x1, qint32 y1, qint32 w, qint32 h, const KisFilterConfigurationSP generator); 0168 0169 /** 0170 * Fills the enclosed area around the point with the set color. If 0171 * there is a selection, the whole selection is filled. Note that 0172 * you must have set the width and height on the painter if you 0173 * don't have a selection. 0174 * 0175 * @param startX the X position where the floodfill starts 0176 * @param startY the Y position where the floodfill starts 0177 * @param sourceDevice the sourceDevice that determines the area that 0178 * is floodfilled if sampleMerged is on 0179 */ 0180 void fillColor(int startX, int startY, KisPaintDeviceSP sourceDevice); 0181 0182 /** 0183 * Fills the enclosed area around the point with the set pattern. 0184 * If there is a selection, the whole selection is filled. Note 0185 * that you must have set the width and height on the painter if 0186 * you don't have a selection. 0187 * 0188 * @param startX the X position where the floodfill starts 0189 * @param startY the Y position where the floodfill starts 0190 * @param sourceDevice the sourceDevice that determines the area that 0191 * is floodfilled if sampleMerged is on 0192 * @param patternTransform transform applied to the pattern; 0193 */ 0194 void fillPattern(int startX, int startY, KisPaintDeviceSP sourceDevice, QTransform patternTransform = QTransform()); 0195 0196 /** 0197 * Returns a selection mask for the floodfill starting at the specified position. 0198 * This variant basically creates a new selection object and passes it down 0199 * to the other variant of the function. 0200 * 0201 * @param startX the X position where the floodfill starts 0202 * @param startY the Y position where the floodfill starts 0203 * @param sourceDevice the sourceDevice that determines the area that 0204 * is floodfilled if sampleMerged is on 0205 */ 0206 KisPixelSelectionSP createFloodSelection(int startX, int startY, 0207 KisPaintDeviceSP sourceDevice, KisPaintDeviceSP existingSelection); 0208 0209 /** 0210 * Returns a selection mask for the floodfill starting at the specified position. 0211 * This variant requires an empty selection object. It is used in cases where the pointer 0212 * to the selection must be known beforehand, for example when the selection is filled 0213 * in a stroke and then the pointer to the pixel selection is needed later. 0214 * 0215 * @param selection empty new selection object 0216 * @param startX the X position where the floodfill starts 0217 * @param startY the Y position where the floodfill starts 0218 * @param sourceDevice the sourceDevice that determines the area that 0219 * is floodfilled if sampleMerged is on 0220 */ 0221 KisPixelSelectionSP createFloodSelection(KisPixelSelectionSP newSelection, int startX, int startY, 0222 KisPaintDeviceSP sourceDevice, KisPaintDeviceSP existingSelection); 0223 0224 /** 0225 * Set the threshold for floodfill. The range is 0-255: 0 means the fill will only 0226 * fill parts that are the exact same color, 255 means anything will be filled 0227 */ 0228 inline void setFillThreshold(int threshold) 0229 { 0230 m_threshold = threshold; 0231 } 0232 0233 /** Returns the fill threshold, see setFillThreshold for details */ 0234 int fillThreshold() const { 0235 return m_threshold; 0236 } 0237 0238 /** 0239 * Set the opacity spread for floodfill. The range is 0-100: 0% means that 0240 * the fully opaque area only encompasses the pixels exactly equal to the 0241 * seed point with the other pixels of the selected region being 0242 * semi-transparent (depending on how similar they are to the seed pixel) 0243 * up to the region boundary (given by the threshold value). 100 means that 0244 * the fully opaque area will encompass all the pixels of the selected 0245 * region up to the contour. Any value inbetween will make the fully opaque 0246 * portion of the region vary in size, with semi-transparent pixels 0247 * inbetween it and the region boundary 0248 */ 0249 void setOpacitySpread(int opacitySpread) 0250 { 0251 m_opacitySpread = opacitySpread; 0252 } 0253 0254 /** Returns the fill opacity spread, see setOpacitySpread for details */ 0255 int opacitySpread() const { 0256 return m_opacitySpread; 0257 } 0258 0259 bool useCompositioning() const { 0260 return m_useCompositioning; 0261 } 0262 0263 void setUseCompositioning(bool useCompositioning) { 0264 m_useCompositioning = useCompositioning; 0265 } 0266 0267 /** Sets the width of the paint device */ 0268 void setWidth(int w) { 0269 m_width = w; 0270 } 0271 0272 /** Sets the height of the paint device */ 0273 void setHeight(int h) { 0274 m_height = h; 0275 } 0276 0277 /** If true, floodfill doesn't fill outside the selected area of a layer */ 0278 bool careForSelection() const { 0279 return m_careForSelection; 0280 } 0281 0282 /** Set caring for selection. See careForSelection for details */ 0283 void setCareForSelection(bool set) { 0284 m_careForSelection = set; 0285 } 0286 0287 /** Sets if antiAlias should be applied to the selection */ 0288 void setAntiAlias(bool antiAlias) { 0289 m_antiAlias = antiAlias; 0290 } 0291 0292 /** Get if antiAlias should be applied to the selection */ 0293 bool antiAlias() const { 0294 return m_antiAlias; 0295 } 0296 0297 /** Sets the auto growth/shrinking radius */ 0298 void setSizemod(int sizemod) { 0299 m_sizemod = sizemod; 0300 } 0301 0302 /** Sets how much to auto-grow or shrink (if @p sizemod is negative) the selection 0303 flood before painting, this affects every fill operation except fillRect */ 0304 int sizemod() const { 0305 return m_sizemod; 0306 } 0307 0308 /** Sets feathering radius */ 0309 void setFeather(int feather) { 0310 m_feather = feather; 0311 } 0312 0313 /** defines the feathering radius for selection flood operations, this affects every 0314 fill operation except fillRect */ 0315 uint feather() const { 0316 return m_feather; 0317 } 0318 0319 /** Sets selection borders being treated as boundary */ 0320 void setUseSelectionAsBoundary(bool useSelectionAsBoundary) { 0321 m_useSelectionAsBoundary = useSelectionAsBoundary; 0322 } 0323 0324 /** defines if the selection borders are treated as boundary in flood fill or not */ 0325 uint useSelectionAsBoundary() const { 0326 return m_useSelectionAsBoundary; 0327 } 0328 0329 protected: 0330 void setCurrentFillSelection(KisSelectionSP fillSelection) 0331 { 0332 m_fillSelection = fillSelection; 0333 } 0334 0335 KisSelectionSP currentFillSelection() const 0336 { 0337 return m_fillSelection; 0338 } 0339 0340 // for floodfill 0341 void genericFillStart(int startX, int startY, KisPaintDeviceSP sourceDevice); 0342 void genericFillEnd(KisPaintDeviceSP filled); 0343 0344 private: 0345 KisSelectionSP m_fillSelection; 0346 0347 int m_feather; 0348 int m_sizemod; 0349 bool m_antiAlias; 0350 int m_threshold; 0351 int m_opacitySpread; 0352 int m_width, m_height; 0353 QRect m_rect; 0354 bool m_careForSelection; 0355 bool m_useCompositioning; 0356 bool m_useSelectionAsBoundary; 0357 }; 0358 0359 #endif //KIS_FILL_PAINTER_H_