Added support for 4 and 8 connected pixel fill method in paint bucket

This commit is contained in:
rscotchmer 2019-03-28 21:07:32 -04:00 committed by David Capello
parent 39d229b0e9
commit a08cfa9e13
8 changed files with 104 additions and 1 deletions

View File

@ -46,6 +46,10 @@
<value id="ACTIVE_LAYER" value="0" />
<value id="ALL_LAYERS" value="1" />
</enum>
<enum id="PixelConnectivity">
<value id="FOUR_CONNECTED" value="0" />
<value id="EIGHT_CONNECTED" value="1" />
</enum>
<enum id="EyedropperChannel">
<value id="COLOR_ALPHA" value="0" />
<value id="COLOR" value="1" />
@ -358,6 +362,7 @@
<section id="floodfill">
<option id="stop_at_grid" type="StopAtGrid" default="StopAtGrid::NEVER" />
<option id="refer_to" type="FillReferTo" default="FillReferTo::ACTIVE_LAYER" />
<option id="pixel_connectivity" type="PixelConnectivity" default="PixelConnectivity::FOUR_CONNECTED" />
</section>
</tool>

View File

@ -155,6 +155,7 @@ FOR_ENUM(app::gen::HueSaturationMode)
FOR_ENUM(app::gen::OnionskinType)
FOR_ENUM(app::gen::PaintingCursorType)
FOR_ENUM(app::gen::PivotPosition)
FOR_ENUM(app::gen::PixelConnectivity)
FOR_ENUM(app::gen::RightClickMode)
FOR_ENUM(app::gen::SelectionMode)
FOR_ENUM(app::gen::StopAtGrid)

View File

@ -103,6 +103,7 @@ public:
get_pixel(srcImage, pt.x, pt.y),
loop->getTolerance(),
loop->getContiguous(),
loop->isPixelConnectivityEightConnected(),
loop, (AlgoHLine)doInkHline);
}

View File

@ -182,6 +182,7 @@ namespace app {
virtual bool getSnapToGrid() = 0;
virtual bool getStopAtGrid() = 0; // For floodfill-like tools
virtual gfx::Rect getGridBounds() = 0;
virtual bool isPixelConnectivityEightConnected() = 0;
// Returns true if the figure must be filled when we release the
// mouse (e.g. a filled rectangle, etc.)

View File

@ -383,6 +383,16 @@ protected:
menu.addChild(&activeLayer);
menu.addChild(&allLayers);
menu.addChild(new MenuSeparator);
menu.addChild(new Label("Pixel Connectivity:"));
HBox box;
ButtonSet buttonset(2);
buttonset.addItem("4-Connected");
buttonset.addItem("8-connected");
box.addChild(&buttonset);
menu.addChild(&box);
stopAtGrid.setSelected(
toolPref.floodfill.stopAtGrid() == app::gen::StopAtGrid::IF_VISIBLE);
activeLayer.setSelected(
@ -390,6 +400,15 @@ protected:
allLayers.setSelected(
toolPref.floodfill.referTo() == app::gen::FillReferTo::ALL_LAYERS);
int index = 0;
switch (toolPref.floodfill.pixelConnectivity()) {
case app::gen::PixelConnectivity::FOUR_CONNECTED: index = 0; break;
case app::gen::PixelConnectivity::EIGHT_CONNECTED: index = 1; break;
}
buttonset.setSelectedItem(index);
stopAtGrid.Click.connect(
[&]{
toolPref.floodfill.stopAtGrid(
@ -405,6 +424,18 @@ protected:
toolPref.floodfill.referTo(app::gen::FillReferTo::ALL_LAYERS);
});
buttonset.ItemChange.connect(
[&buttonset, &toolPref](ButtonSet::Item* item){
switch (buttonset.selectedItem()) {
case 0:
toolPref.floodfill.pixelConnectivity(app::gen::PixelConnectivity::FOUR_CONNECTED);
break;
case 1:
toolPref.floodfill.pixelConnectivity(app::gen::PixelConnectivity::EIGHT_CONNECTED);
break;
}
});
menu.showPopup(gfx::Point(bounds.x, bounds.y+bounds.h));
deselectItems();
}

View File

@ -246,6 +246,12 @@ public:
}
return false;
}
bool isPixelConnectivityEightConnected() override {
return (m_toolPref.floodfill.pixelConnectivity()
== app::gen::PixelConnectivity::EIGHT_CONNECTED);
}
gfx::Rect getGridBounds() override { return m_docPref.grid.bounds(); }
gfx::Point getCelOrigin() override { return m_celOrigin; }
void setSpeed(const gfx::Point& speed) override { m_speed = speed; }

View File

@ -346,6 +346,7 @@ void floodfill(const Image* image,
const doc::color_t src_color,
const int tolerance,
const bool contiguous,
const bool isEightConnected,
void* data,
AlgoHLine proc)
{
@ -398,8 +399,39 @@ void floodfill(const Image* image,
// Check below the segment?
if (p->flags & FLOOD_TODO_BELOW) {
p->flags &= ~FLOOD_TODO_BELOW;
if (isEightConnected) {
if (p->lpos+1 < bounds.x2() &&
check_flood_line(image, mask, p->y+1, p->lpos+1, p->rpos, bounds,
src_color, tolerance, data, proc)) {
done = false;
p = FLOOD_LINE(c);
}
if (p->lpos-1 >= 0 &&
check_flood_line(image, mask, p->y+1, p->lpos-1, p->rpos, bounds,
src_color, tolerance, data, proc)) {
done = false;
p = FLOOD_LINE(c);
}
if (p->rpos+1 < bounds.x2() &&
check_flood_line(image, mask, p->y+1, p->lpos, p->rpos+1, bounds,
src_color, tolerance, data, proc)) {
done = false;
p = FLOOD_LINE(c);
}
if (p->rpos-1 >= 0 &&
check_flood_line(image, mask, p->y+1, p->lpos, p->rpos-1, bounds,
src_color, tolerance, data, proc)) {
done = false;
p = FLOOD_LINE(c);
}
}
if (check_flood_line(image, mask, p->y+1, p->lpos, p->rpos, bounds,
src_color, tolerance, data, proc)) {
src_color, tolerance, data, proc)) {
done = false;
p = FLOOD_LINE(c);
}
@ -408,6 +440,31 @@ void floodfill(const Image* image,
// Check above the segment?
if (p->flags & FLOOD_TODO_ABOVE) {
p->flags &= ~FLOOD_TODO_ABOVE;
if (isEightConnected) {
if (p->lpos+1 < bounds.x2() &&
check_flood_line(image, mask, p->y-1, p->lpos+1, p->rpos, bounds,
src_color, tolerance, data, proc)) {
done = false;
}
if (p->lpos-1 >= 0 &&
check_flood_line(image, mask, p->y-1, p->lpos-1, p->rpos, bounds,
src_color, tolerance, data, proc)) {
done = false;
}
if (p->rpos+1 < bounds.x2() &&
check_flood_line(image, mask, p->y-1, p->lpos, p->rpos+1, bounds,
src_color, tolerance, data, proc)) {
done = false;
}
if (p->rpos-1 >= 0 &&
check_flood_line(image, mask, p->y-1, p->lpos, p->rpos-1, bounds,
src_color, tolerance, data, proc)) {
done = false;
}
}
if (check_flood_line(image, mask, p->y-1, p->lpos, p->rpos, bounds,
src_color, tolerance, data, proc)) {
done = false;

View File

@ -26,6 +26,7 @@ namespace doc {
const doc::color_t srcColor,
const int tolerance,
const bool contiguous,
const bool isEightConnected,
void* data,
AlgoHLine proc);