File indexing completed on 2024-12-22 04:10:06

0001 /*
0002  *  SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef __KIS_SCANLINE_FILL_H
0008 #define __KIS_SCANLINE_FILL_H
0009 
0010 #include <QScopedPointer>
0011 
0012 #include <kritaimage_export.h>
0013 #include <kis_types.h>
0014 #include <kis_paint_device.h>
0015 
0016 class KisFillInterval;
0017 class KisFillIntervalMap;
0018 
0019 class KRITAIMAGE_EXPORT KisScanlineFill
0020 {
0021 public:
0022     KisScanlineFill(KisPaintDeviceSP device, const QPoint &startPoint, const QRect &boundingRect);
0023     ~KisScanlineFill();
0024 
0025     /**
0026      * Fill the source device with \p fillColor
0027      */
0028     void fill(const KoColor &fillColor);
0029 
0030     /**
0031      * Fill the source device with \p fillColor until \p boundaryColor is reached
0032      */
0033     void fillUntilColor(const KoColor &fillColor, const KoColor &boundaryColor);
0034 
0035     /**
0036      * Fill \p externalDevice with \p fillColor basing on the contents
0037      * of the source device.
0038      */
0039     void fill(const KoColor &fillColor, KisPaintDeviceSP externalDevice);
0040 
0041     /**
0042      * Fill \p externalDevice with \p fillColor basing on the contents
0043      * of the source device. Fills until \p boundaryColor is reached
0044      */
0045     void fillUntilColor(const KoColor &fillColor, const KoColor &boundaryColor, KisPaintDeviceSP externalDevice);
0046 
0047     /**
0048      * Fill \p pixelSelection with the opacity of the contiguous area.
0049      * This method uses an existing selection as boundary for the flood fill.
0050      */
0051     void fillSelection(KisPixelSelectionSP pixelSelection, KisPaintDeviceSP boundarySelection);
0052 
0053     /**
0054      * Fill \p pixelSelection with the opacity of the contiguous area
0055      */
0056     void fillSelection(KisPixelSelectionSP pixelSelection);
0057 
0058     /**
0059      * Fill \p pixelSelection with the opacity of the contiguous area, which
0060      * encompass all the connected pixels as long as the color in the
0061      * pixels of the source device is not similar to \p boundaryColor.
0062      * This method uses an existing selection as boundary for the flood fill.
0063      */
0064     void fillSelectionUntilColor(KisPixelSelectionSP pixelSelection, const KoColor &boundaryColor, KisPaintDeviceSP boundarySelection);
0065 
0066     /**
0067      * Fill \p pixelSelection with the opacity of the contiguous area, which
0068      * encompass all the connected pixels as long as the color in the
0069      * pixels of the source device is not similar to \p boundaryColor.
0070      */
0071     void fillSelectionUntilColor(KisPixelSelectionSP pixelSelection, const KoColor &boundaryColor);
0072 
0073     /**
0074      * Fill \p pixelSelection with the opacity of the contiguous area, which
0075      * encompass all the connected pixels as long as the color in the
0076      * pixels of the source device is not similar to \p boundaryColor or transparent.
0077      * This method uses an existing selection as boundary for the flood fill.
0078      */
0079     void fillSelectionUntilColorOrTransparent(KisPixelSelectionSP pixelSelection, const KoColor &boundaryColor, KisPaintDeviceSP boundarySelection);
0080 
0081     /**
0082      * Fill \p pixelSelection with the opacity of the contiguous area, which
0083      * encompass all the connected pixels as long as the color in the
0084      * pixels of the source device is not similar to \p boundaryColor or transparent.
0085      */
0086     void fillSelectionUntilColorOrTransparent(KisPixelSelectionSP pixelSelection, const KoColor &boundaryColor);
0087 
0088     /**
0089      * Clear the contiguous non-zero area of the device
0090      *
0091      * WARNING: the threshold parameter is not counted!
0092      */
0093     void clearNonZeroComponent();
0094 
0095     /**
0096      * A special filler algorithm for the Watershed initialization routine:
0097      *
0098      * 1) Clear the contiguous area in the destination device
0099      * 2) At the same time, fill the corresponding area of \p groupMapDevice with
0100      *    value \p groupIndex
0101      * 3) \p groupMapDevice **must** store 4 bytes per pixel
0102      */
0103     void fillContiguousGroup(KisPaintDeviceSP groupMapDevice, qint32 groupIndex);
0104 
0105     /**
0106      * Set the threshold of the filling operation
0107      *
0108      * Used in all functions except clearNonZeroComponent()
0109      */
0110     void setThreshold(int threshold);
0111 
0112     /**
0113      * Set the opacity spread for floodfill. The range is 0-100: 0% means that
0114      * the fully opaque area only encompasses the pixels exactly equal to the
0115      * seed point with the other pixels of the selected region being
0116      * semi-transparent (depending on how similar they are to the seed pixel)
0117      * up to the region boundary (given by the threshold value). 100 means that
0118      * the fully opaque area will encompass all the pixels of the selected
0119      * region up to the contour. Any value in between will make the fully opaque
0120      * portion of the region vary in size, with semi-transparent pixels
0121      * in between it and  the region boundary
0122      */
0123     void setOpacitySpread(int opacitySpread);
0124 
0125 private:
0126     friend class KisScanlineFillTest;
0127     Q_DISABLE_COPY(KisScanlineFill)
0128 
0129     template <typename DifferencePolicy, typename SelectionPolicy, typename PixelAccessPolicy>
0130     void processLine(KisFillInterval interval, const int rowIncrement,
0131                      DifferencePolicy &differencePolicy,
0132                      SelectionPolicy &selectionPolicy,
0133                      PixelAccessPolicy &pixelAccessPolicy);
0134 
0135     template <typename DifferencePolicy, typename SelectionPolicy, typename PixelAccessPolicy>
0136     void extendedPass(KisFillInterval *currentInterval, int srcRow, bool extendRight,
0137                       DifferencePolicy &differencePolicy,
0138                       SelectionPolicy &selectionPolicy,
0139                       PixelAccessPolicy &pixelAccessPolicy);
0140 
0141     template <typename DifferencePolicy, typename SelectionPolicy, typename PixelAccessPolicy>
0142     void runImpl(DifferencePolicy &differencePolicy,
0143                  SelectionPolicy &selectionPolicy,
0144                  PixelAccessPolicy &pixelAccessPolicy);
0145 
0146     template <template <typename SrcPixelType> typename OptimizedDifferencePolicy,
0147               typename SlowDifferencePolicy,
0148               typename SelectionPolicy, typename PixelAccessPolicy>
0149     void selectDifferencePolicyAndRun(const KoColor &srcColor,
0150                                       SelectionPolicy &selectionPolicy,
0151                                       PixelAccessPolicy &pixelAccessPolicy);
0152 
0153 private:
0154     void testingProcessLine(const KisFillInterval &processInterval);
0155     QVector<KisFillInterval> testingGetForwardIntervals() const;
0156     KisFillIntervalMap* testingGetBackwardIntervals() const;
0157 private:
0158     struct Private;
0159     const QScopedPointer<Private> m_d;
0160 };
0161 
0162 #endif /* __KIS_SCANLINE_FILL_H */