17#include "bitmapbucket.h"
23#include "layermanager.h"
25#include "layerbitmap.h"
27BitmapBucket::BitmapBucket()
31BitmapBucket::BitmapBucket(
Editor* editor,
37 mMaxFillRegion(maxFillRegion),
38 mProperties(properties)
41 Layer* initialLayer = editor->layers()->currentLayer();
42 int initialLayerIndex = mEditor->currentLayerIndex();
43 int frameIndex = mEditor->currentFrame();
45 mBucketColor = qPremultiply(color.
rgba());
47 mTargetFillToLayer = initialLayer;
48 mTargetFillToLayerIndex = initialLayerIndex;
50 mTolerance = mProperties.colorToleranceEnabled() ? mProperties.tolerance() : 0;
51 const QPoint& point =
QPoint(qFloor(fillPoint.
x()), qFloor(fillPoint.
y()));
53 Q_ASSERT(mTargetFillToLayer);
55 BitmapImage singleLayerImage = *
static_cast<BitmapImage*
>(initialLayer->getLastKeyFrameAtPosition(frameIndex));
56 if (properties.fillReferenceMode() == 1)
58 mReferenceImage = flattenBitmapLayersToImage();
60 mReferenceImage = singleLayerImage;
62 mStartReferenceColor = mReferenceImage.constScanLine(point.
x(), point.
y());
63 mUseDragToFill = canUseDragToFill(point, color, singleLayerImage);
70 QRgb pressReferenceColorSingleLayer = referenceImage.constScanLine(fillPoint.
x(), fillPoint.
y());
71 QRgb startRef = qUnpremultiply(pressReferenceColorSingleLayer);
73 if (mProperties.fillMode() == 0 && ((
QColor(qRed(startRef), qGreen(startRef), qBlue(startRef)) == bucketColor.
rgb() && qAlpha(startRef) == 255) || bucketColor.
alpha() == 0)) {
77 }
else if (mProperties.fillMode() == 2 && qAlpha(startRef) == 255) {
92 return allowContinuousFill(checkPoint, checkColor);
95bool BitmapBucket::allowContinuousFill(
const QPoint& checkPoint,
const QRgb& checkColor)
const
97 if (!mUseDragToFill) {
101 const QRgb& colorOfReferenceImage = mReferenceImage.constScanLine(checkPoint.
x(), checkPoint.
y());
103 if (checkColor == mBucketColor && (mProperties.fillMode() == 1 || qAlpha(checkColor) == 255))
116 const int currentFrameIndex = mEditor->currentFrame();
118 BitmapImage* targetImage =
static_cast<LayerBitmap*
>(mTargetFillToLayer)->getLastBitmapImageAtFrame(currentFrameIndex);
119 if (targetImage ==
nullptr || !targetImage->
isLoaded()) {
return; }
121 QPoint point =
QPoint(qFloor(updatedPoint.
x()), qFloor(updatedPoint.
y()));
122 if (!mReferenceImage.contains(point))
125 point = mReferenceImage.topLeft();
128 const QRgb& targetPixelColor = targetImage->constScanLine(point.
x(), point.
y());
130 if (!
allowFill(point, targetPixelColor)) {
134 QRgb fillColor = mBucketColor;
135 if (mProperties.fillMode() == 1)
143 fillColor = tempColor.
rgba();
148 int expandValue = mProperties.fillExpandEnabled() ? mProperties.fillExpandAmount() : 0;
149 bool didFloodFill = BitmapImage::floodFill(&replaceImage,
161 Q_ASSERT(replaceImage !=
nullptr);
163 state(BucketState::WillFillTarget, mTargetFillToLayerIndex, currentFrameIndex);
165 if (mProperties.fillMode() == 0)
167 targetImage->paste(replaceImage);
169 else if (mProperties.fillMode() == 2)
181 targetImage->paste(&properColor);
184 targetImage->modification();
187 state(BucketState::DidFillTarget, mTargetFillToLayerIndex, currentFrameIndex);
191BitmapImage BitmapBucket::flattenBitmapLayersToImage()
194 int currentFrame = mEditor->currentFrame();
195 auto layerMan = mEditor->layers();
196 for (
int i = 0; i < layerMan->count(); i++)
198 Layer* layer = layerMan->getLayer(i);
200 if (layer->type() == Layer::BITMAP && layer->visible())
204 flattenImage.paste(image);
bool canUseDragToFill(const QPoint &fillPoint, const QColor &bucketColor, const BitmapImage &referenceImage)
Determines whether fill to drag feature can be used.
bool allowFill(const QPoint &checkPoint, const QRgb &checkColor) const
Based on the various factors dependant on which tool properties are set, the result will:
void paint(const QPointF &updatedPoint, std::function< void(BucketState, int, int)> progress)
Will paint at the given point, given that it makes sense.
bool isLoaded() const override
Checks whether the keyframe holds valid image data.
static bool compareColor(QRgb newColor, QRgb oldColor, int tolerance, QHash< QRgb, bool > *cache)
Compare colors for the purposes of flood filling.
QColor fromRgba(QRgb rgba)
void setAlphaF(qreal alpha)
CompositionMode_DestinationOver